libnl  3.2.28
bridge.c
1 /*
2  * lib/route/link/bridge.c AF_BRIDGE link support
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2010-2013 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup link
14  * @defgroup bridge Bridging
15  *
16  * @details
17  * @{
18  */
19 
20 #include <netlink-private/netlink.h>
21 #include <netlink/netlink.h>
22 #include <netlink/attr.h>
23 #include <netlink/route/rtnl.h>
24 #include <netlink/route/link/bridge.h>
25 #include <netlink-private/route/link/api.h>
26 #include <linux/if_bridge.h>
27 
28 #define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
29 
30 /** @cond SKIP */
31 #define BRIDGE_ATTR_PORT_STATE (1 << 0)
32 #define BRIDGE_ATTR_PRIORITY (1 << 1)
33 #define BRIDGE_ATTR_COST (1 << 2)
34 #define BRIDGE_ATTR_FLAGS (1 << 3)
35 #define BRIDGE_ATTR_PORT_VLAN (1 << 4)
36 
37 #define PRIV_FLAG_NEW_ATTRS (1 << 0)
38 
39 struct bridge_data
40 {
41  uint8_t b_port_state;
42  uint8_t b_priv_flags; /* internal flags */
43  uint16_t b_priority;
44  uint32_t b_cost;
45  uint32_t b_flags;
46  uint32_t b_flags_mask;
47  uint32_t ce_mask; /* HACK to support attr macros */
48  struct rtnl_link_bridge_vlan vlan_info;
49 };
50 
51 static void set_bit(unsigned nr, uint32_t *addr)
52 {
53  if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
54  addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
55 }
56 
57 static int find_next_bit(int i, uint32_t x)
58 {
59  int j;
60 
61  if (i >= 32)
62  return -1;
63 
64  /* find first bit */
65  if (i < 0)
66  return __builtin_ffs(x);
67 
68  /* mask off prior finds to get next */
69  j = __builtin_ffs(x >> i);
70  return j ? j + i : 0;
71 }
72 
73 static struct rtnl_link_af_ops bridge_ops;
74 
75 #define IS_BRIDGE_LINK_ASSERT(link) \
76  if (!rtnl_link_is_bridge(link)) { \
77  APPBUG("A function was expecting a link object of type bridge."); \
78  return -NLE_OPNOTSUPP; \
79  }
80 
81 static inline struct bridge_data *bridge_data(struct rtnl_link *link)
82 {
83  return rtnl_link_af_data(link, &bridge_ops);
84 }
85 
86 static void *bridge_alloc(struct rtnl_link *link)
87 {
88  return calloc(1, sizeof(struct bridge_data));
89 }
90 
91 static void *bridge_clone(struct rtnl_link *link, void *data)
92 {
93  struct bridge_data *bd;
94 
95  if ((bd = bridge_alloc(link)))
96  memcpy(bd, data, sizeof(*bd));
97 
98  return bd;
99 }
100 
101 static void bridge_free(struct rtnl_link *link, void *data)
102 {
103  free(data);
104 }
105 
106 static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = {
107  [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
108  [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
109  [IFLA_BRPORT_COST] = { .type = NLA_U32 },
110  [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
111  [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
112  [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
113  [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 },
114 };
115 
116 static void check_flag(struct rtnl_link *link, struct nlattr *attrs[],
117  int type, int flag)
118 {
119  if (attrs[type] && nla_get_u8(attrs[type]))
120  rtnl_link_bridge_set_flags(link, flag);
121 }
122 
123 static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
124  void *data)
125 {
126  struct bridge_data *bd = data;
127  struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
128  int err;
129 
130  /* Backwards compatibility */
131  if (!nla_is_nested(attr)) {
132  if (nla_len(attr) < 1)
133  return -NLE_RANGE;
134 
135  bd->b_port_state = nla_get_u8(attr);
136  bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
137 
138  return 0;
139  }
140 
141  if ((err = nla_parse_nested(br_attrs, IFLA_BRPORT_MAX, attr,
142  br_attrs_policy)) < 0)
143  return err;
144 
145  bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;
146 
147  if (br_attrs[IFLA_BRPORT_STATE]) {
148  bd->b_port_state = nla_get_u8(br_attrs[IFLA_BRPORT_STATE]);
149  bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
150  }
151 
152  if (br_attrs[IFLA_BRPORT_PRIORITY]) {
153  bd->b_priority = nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]);
154  bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
155  }
156 
157  if (br_attrs[IFLA_BRPORT_COST]) {
158  bd->b_cost = nla_get_u32(br_attrs[IFLA_BRPORT_COST]);
159  bd->ce_mask |= BRIDGE_ATTR_COST;
160  }
161 
162  check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE);
163  check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD);
164  check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK);
165  check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE);
166 
167  return 0;
168 }
169 
170 static int bridge_parse_af_full(struct rtnl_link *link, struct nlattr *attr_full,
171  void *data)
172 {
173  struct bridge_data *bd = data;
174  struct bridge_vlan_info *vinfo = NULL;
175  uint16_t vid_range_start = 0;
176  uint16_t vid_range_flags = -1;
177 
178  struct nlattr *attr;
179  int remaining;
180 
181  nla_for_each_nested(attr, attr_full, remaining) {
182 
183  if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
184  continue;
185 
186  if (nla_len(attr) != sizeof(struct bridge_vlan_info))
187  return -EINVAL;
188 
189  vinfo = nla_data(attr);
190  if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
191  return -EINVAL;
192 
193 
194  if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
195  vid_range_start = vinfo->vid;
196  vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
197  continue;
198  }
199 
200  if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
201  /* sanity check the range flags */
202  if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
203  NL_DBG(1, "VLAN range flags differ; can not handle it.\n");
204  return -EINVAL;
205  }
206  } else {
207  vid_range_start = vinfo->vid;
208  }
209 
210  for (; vid_range_start <= vinfo->vid; vid_range_start++) {
211  if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
212  bd->vlan_info.pvid = vinfo->vid;
213 
214  if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
215  set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
216 
217  set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
218  bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
219  }
220 
221  vid_range_flags = -1;
222  }
223 
224  return 0;
225 }
226 
227 static int bridge_get_af(struct nl_msg *msg, uint32_t *ext_filter_mask)
228 {
229  *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
230  return 0;
231 }
232 
233 static void dump_bitmap(struct nl_dump_params *p, const uint32_t *b)
234 {
235  int i = -1, j, k;
236  int start = -1, prev = -1;
237  int done, found = 0;
238 
239  for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
240  int base_bit;
241  uint32_t a = b[k];
242 
243  base_bit = k * 32;
244  i = -1;
245  done = 0;
246  while (!done) {
247  j = find_next_bit(i, a);
248  if (j > 0) {
249  /* first hit of any bit */
250  if (start < 0 && prev < 0) {
251  start = prev = j - 1 + base_bit;
252  goto next;
253  }
254  /* this bit is a continuation of prior bits */
255  if (j - 2 + base_bit == prev) {
256  prev++;
257  goto next;
258  }
259  } else
260  done = 1;
261 
262  if (start >= 0) {
263  found++;
264  if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
265  break;
266 
267  nl_dump(p, " %d", start);
268  if (start != prev)
269  nl_dump(p, "-%d", prev);
270 
271  if (done)
272  break;
273  }
274  if (j > 0)
275  start = prev = j - 1 + base_bit;
276 next:
277  i = j;
278  }
279  }
280  if (!found)
281  nl_dump(p, " <none>");
282 
283  return;
284 }
285 
286 static void rtnl_link_bridge_dump_vlans(struct nl_dump_params *p,
287  struct bridge_data *bd)
288 {
289  nl_dump(p, "pvid %u", bd->vlan_info.pvid);
290 
291  nl_dump(p, " all vlans:");
292  dump_bitmap(p, bd->vlan_info.vlan_bitmap);
293 
294  nl_dump(p, " untagged vlans:");
295  dump_bitmap(p, bd->vlan_info.untagged_bitmap);
296 }
297 
298 static void bridge_dump_details(struct rtnl_link *link,
299  struct nl_dump_params *p, void *data)
300 {
301  struct bridge_data *bd = data;
302 
303  nl_dump_line(p, " bridge: ");
304 
305  if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
306  nl_dump(p, "port-state %u ", bd->b_port_state);
307 
308  if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
309  nl_dump(p, "prio %u ", bd->b_priority);
310 
311  if (bd->ce_mask & BRIDGE_ATTR_COST)
312  nl_dump(p, "cost %u ", bd->b_cost);
313 
314  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
315  rtnl_link_bridge_dump_vlans(p, bd);
316 
317  if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
318  char buf[256];
319 
320  rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
321  buf, sizeof(buf));
322  nl_dump(p, "%s", buf);
323  }
324 
325  nl_dump(p, "\n");
326 }
327 
328 static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b,
329  int family, uint32_t attrs, int flags)
330 {
331  struct bridge_data *a = bridge_data(_a);
332  struct bridge_data *b = bridge_data(_b);
333  int diff = 0;
334 
335 #define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR)
336  diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state);
337  diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
338  diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
339  diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
340  sizeof(struct rtnl_link_bridge_vlan)));
341 
342  if (flags & LOOSE_COMPARISON)
343  diff |= BRIDGE_DIFF(FLAGS,
344  (a->b_flags ^ b->b_flags) & b->b_flags_mask);
345  else
346  diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
347 #undef BRIDGE_DIFF
348 
349  return diff;
350 }
351 /** @endcond */
352 
353 /**
354  * Allocate link object of type bridge
355  *
356  * @return Allocated link object or NULL.
357  */
359 {
360  struct rtnl_link *link;
361  int err;
362 
363  if (!(link = rtnl_link_alloc()))
364  return NULL;
365 
366  if ((err = rtnl_link_set_type(link, "bridge")) < 0) {
367  rtnl_link_put(link);
368  return NULL;
369  }
370 
371  return link;
372 }
373 
374 /**
375  * Create a new kernel bridge device
376  * @arg sk netlink socket
377  * @arg name name of the bridge device or NULL
378  *
379  * Creates a new bridge device in the kernel. If no name is
380  * provided, the kernel will automatically pick a name of the
381  * form "type%d" (e.g. bridge0, vlan1, etc.)
382  *
383  * @return 0 on success or a negative error code
384 */
385 int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
386 {
387  int err;
388  struct rtnl_link *link;
389 
390  if (!(link = rtnl_link_bridge_alloc()))
391  return -NLE_NOMEM;
392 
393  if(name)
394  rtnl_link_set_name(link, name);
395 
396  err = rtnl_link_add(sk, link, NLM_F_CREATE);
397  rtnl_link_put(link);
398 
399  return err;
400 }
401 
402 /**
403  * Check if a link is a bridge
404  * @arg link Link object
405  *
406  * @return 1 if the link is a bridge, 0 otherwise.
407  */
409 {
410  return link->l_family == AF_BRIDGE &&
411  link->l_af_ops == &bridge_ops;
412 }
413 
414 /**
415  * Check if bridge has extended information
416  * @arg link Link object of type bridge
417  *
418  * Checks if the bridge object has been constructed based on
419  * information that is only available in newer kernels. This
420  * affectes the following functions:
421  * - rtnl_link_bridge_get_cost()
422  * - rtnl_link_bridge_get_priority()
423  * - rtnl_link_bridge_get_flags()
424  *
425  * @return 1 if extended information is available, otherwise 0 is returned.
426  */
428 {
429  struct bridge_data *bd;
430 
431  if (!rtnl_link_is_bridge(link))
432  return 0;
433 
434  bd = bridge_data(link);
435  return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
436 }
437 
438 /**
439  * Set Spanning Tree Protocol (STP) port state
440  * @arg link Link object of type bridge
441  * @arg state New STP port state
442  *
443  * The value of state must be one of the following:
444  * - BR_STATE_DISABLED
445  * - BR_STATE_LISTENING
446  * - BR_STATE_LEARNING
447  * - BR_STATE_FORWARDING
448  * - BR_STATE_BLOCKING
449  *
450  * @see rtnl_link_bridge_get_port_state()
451  *
452  * @return 0 on success or a negative error code.
453  * @retval -NLE_OPNOTSUPP Link is not a bridge
454  * @retval -NLE_INVAL Invalid state value (0..BR_STATE_BLOCKING)
455  */
456 int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
457 {
458  struct bridge_data *bd = bridge_data(link);
459 
460  IS_BRIDGE_LINK_ASSERT(link);
461 
462  if (state > BR_STATE_BLOCKING)
463  return -NLE_INVAL;
464 
465  bd->b_port_state = state;
466  bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
467 
468  return 0;
469 }
470 
471 /**
472  * Get Spanning Tree Protocol (STP) port state
473  * @arg link Link object of type bridge
474  *
475  * @see rtnl_link_bridge_set_port_state()
476  *
477  * @return The STP port state or a negative error code.
478  * @retval -NLE_OPNOTSUPP Link is not a bridge
479  */
481 {
482  struct bridge_data *bd = bridge_data(link);
483 
484  IS_BRIDGE_LINK_ASSERT(link);
485 
486  return bd->b_port_state;
487 }
488 
489 /**
490  * Set priority
491  * @arg link Link object of type bridge
492  * @arg prio Bridge priority
493  *
494  * @see rtnl_link_bridge_get_priority()
495  *
496  * @return 0 on success or a negative error code.
497  * @retval -NLE_OPNOTSUPP Link is not a bridge
498  */
499 int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
500 {
501  struct bridge_data *bd = bridge_data(link);
502 
503  IS_BRIDGE_LINK_ASSERT(link);
504 
505  bd->b_priority = prio;
506  bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
507 
508  return 0;
509 }
510 
511 /**
512  * Get priority
513  * @arg link Link object of type bridge
514  *
515  * @see rtnl_link_bridge_set_priority()
516  *
517  * @return 0 on success or a negative error code.
518  * @retval -NLE_OPNOTSUPP Link is not a bridge
519  */
521 {
522  struct bridge_data *bd = bridge_data(link);
523 
524  IS_BRIDGE_LINK_ASSERT(link);
525 
526  return bd->b_priority;
527 }
528 
529 /**
530  * Set Spanning Tree Protocol (STP) path cost
531  * @arg link Link object of type bridge
532  * @arg cost New STP path cost value
533  *
534  * @see rtnl_link_bridge_get_cost()
535  *
536  * @return The bridge priority or a negative error code.
537  * @retval -NLE_OPNOTSUPP Link is not a bridge
538  */
539 int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
540 {
541  struct bridge_data *bd = bridge_data(link);
542 
543  IS_BRIDGE_LINK_ASSERT(link);
544 
545  bd->b_cost = cost;
546  bd->ce_mask |= BRIDGE_ATTR_COST;
547 
548  return 0;
549 }
550 
551 /**
552  * Get Spanning Tree Protocol (STP) path cost
553  * @arg link Link object of type bridge
554  * @arg cost Pointer to store STP cost value
555  *
556  * @see rtnl_link_bridge_set_cost()
557  *
558  * @return 0 on success or a negative error code.
559  * @retval -NLE_OPNOTSUPP Link is not a bridge
560  * @retval -NLE_INVAL `cost` is not a valid pointer
561  */
562 int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
563 {
564  struct bridge_data *bd = bridge_data(link);
565 
566  IS_BRIDGE_LINK_ASSERT(link);
567 
568  if (!cost)
569  return -NLE_INVAL;
570 
571  *cost = bd->b_cost;
572 
573  return 0;
574 }
575 
576 /**
577  * Unset flags
578  * @arg link Link object of type bridge
579  * @arg flags Bridging flags to unset
580  *
581  * @see rtnl_link_bridge_set_flags()
582  * @see rtnl_link_bridge_get_flags()
583  *
584  * @return 0 on success or a negative error code.
585  * @retval -NLE_OPNOTSUPP Link is not a bridge
586  */
587 int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
588 {
589  struct bridge_data *bd = bridge_data(link);
590 
591  IS_BRIDGE_LINK_ASSERT(link);
592 
593  bd->b_flags_mask |= flags;
594  bd->b_flags &= ~flags;
595  bd->ce_mask |= BRIDGE_ATTR_FLAGS;
596 
597  return 0;
598 }
599 
600 /**
601  * Set flags
602  * @arg link Link object of type bridge
603  * @arg flags Bridging flags to set
604  *
605  * Valid flags are:
606  * - RTNL_BRIDGE_HAIRPIN_MODE
607  * - RTNL_BRIDGE_BPDU_GUARD
608  * - RTNL_BRIDGE_ROOT_BLOCK
609  * - RTNL_BRIDGE_FAST_LEAVE
610  *
611  * @see rtnl_link_bridge_unset_flags()
612  * @see rtnl_link_bridge_get_flags()
613  *
614  * @return 0 on success or a negative error code.
615  * @retval -NLE_OPNOTSUPP Link is not a bridge
616  */
617 int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
618 {
619  struct bridge_data *bd = bridge_data(link);
620 
621  IS_BRIDGE_LINK_ASSERT(link);
622 
623  bd->b_flags_mask |= flags;
624  bd->b_flags |= flags;
625  bd->ce_mask |= BRIDGE_ATTR_FLAGS;
626 
627  return 0;
628 }
629 
630 /**
631  * Get flags
632  * @arg link Link object of type bridge
633  *
634  * @see rtnl_link_bridge_set_flags()
635  * @see rtnl_link_bridge_unset_flags()
636  *
637  * @return Flags or a negative error code.
638  * @retval -NLE_OPNOTSUPP Link is not a bridge
639  */
641 {
642  struct bridge_data *bd = bridge_data(link);
643 
644  IS_BRIDGE_LINK_ASSERT(link);
645 
646  return bd->b_flags;
647 }
648 
649 static const struct trans_tbl bridge_flags[] = {
650  __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
651  __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
652  __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
653  __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
654 };
655 
656 /**
657  * @name Flag Translation
658  * @{
659  */
660 
661 char *rtnl_link_bridge_flags2str(int flags, char *buf, size_t len)
662 {
663  return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
664 }
665 
666 int rtnl_link_bridge_str2flags(const char *name)
667 {
668  return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
669 }
670 
671 /** @} */
672 
673 int rtnl_link_bridge_pvid(struct rtnl_link *link)
674 {
675  struct bridge_data *bd;
676 
677  IS_BRIDGE_LINK_ASSERT(link);
678 
679  bd = link->l_af_data[AF_BRIDGE];
680  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
681  return (int) bd->vlan_info.pvid;
682 
683  return -EINVAL;
684 }
685 
686 int rtnl_link_bridge_has_vlan(struct rtnl_link *link)
687 {
688  struct bridge_data *bd;
689  int i;
690 
691  IS_BRIDGE_LINK_ASSERT(link);
692 
693  bd = link->l_af_data[AF_BRIDGE];
694  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
695  if (bd->vlan_info.pvid)
696  return 1;
697 
698  for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
699  if (bd->vlan_info.vlan_bitmap[i] ||
700  bd->vlan_info.untagged_bitmap[i])
701  return 1;
702  }
703  }
704  return 0;
705 }
706 
707 struct rtnl_link_bridge_vlan *rtnl_link_bridge_get_port_vlan(struct rtnl_link *link)
708 {
709  struct bridge_data *data;
710 
711  if (!rtnl_link_is_bridge(link))
712  return NULL;
713 
714  data = link->l_af_data[AF_BRIDGE];
715  if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
716  return &data->vlan_info;
717 
718  return NULL;
719 }
720 
721 static struct rtnl_link_af_ops bridge_ops = {
722  .ao_family = AF_BRIDGE,
723  .ao_alloc = &bridge_alloc,
724  .ao_clone = &bridge_clone,
725  .ao_free = &bridge_free,
726  .ao_parse_protinfo = &bridge_parse_protinfo,
727  .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details,
728  .ao_compare = &bridge_compare,
729  .ao_parse_af_full = &bridge_parse_af_full,
730  .ao_get_af = &bridge_get_af,
731 };
732 
733 static void __init bridge_init(void)
734 {
735  rtnl_link_af_register(&bridge_ops);
736 }
737 
738 static void __exit bridge_exit(void)
739 {
740  rtnl_link_af_unregister(&bridge_ops);
741 }
742 
743 /** @} */
8 bit integer
Definition: attr.h:39
int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
Set Spanning Tree Protocol (STP) path cost.
Definition: bridge.c:539
int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset flags.
Definition: bridge.c:587
Attribute validation policy.
Definition: attr.h:67
int rtnl_link_bridge_get_priority(struct rtnl_link *link)
Get priority.
Definition: bridge.c:520
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:599
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
int rtnl_link_bridge_get_port_state(struct rtnl_link *link)
Get Spanning Tree Protocol (STP) port state.
Definition: bridge.c:480
int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
Set Spanning Tree Protocol (STP) port state.
Definition: bridge.c:456
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
Definition: attr.c:1004
Dump all attributes but no statistics.
Definition: types.h:23
int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
Set priority.
Definition: bridge.c:499
int rtnl_link_is_bridge(struct rtnl_link *link)
Check if a link is a bridge.
Definition: bridge.c:408
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:992
struct rtnl_link * rtnl_link_bridge_alloc(void)
Allocate link object of type bridge.
Definition: bridge.c:358
int nla_type(const struct nlattr *nla)
Return type of the attribute.
Definition: attr.c:109
16 bit integer
Definition: attr.h:40
int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
Create a new kernel bridge device.
Definition: bridge.c:385
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:120
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:131
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
Definition: attr.h:327
int rtnl_link_bridge_has_ext_info(struct rtnl_link *link)
Check if bridge has extended information.
Definition: bridge.c:427
int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
Get Spanning Tree Protocol (STP) path cost.
Definition: bridge.c:562
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:69
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:649
32 bit integer
Definition: attr.h:41
Dumping parameters.
Definition: types.h:33
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:914
int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
Set flags.
Definition: bridge.c:617
int rtnl_link_bridge_get_flags(struct rtnl_link *link)
Get flags.
Definition: bridge.c:640