libnl  3.5.0
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 #define BRIDGE_ATTR_HWMODE (1 << 5)
37 #define BRIDGE_ATTR_SELF (1 << 6)
38 
39 #define PRIV_FLAG_NEW_ATTRS (1 << 0)
40 
41 struct bridge_data
42 {
43  uint8_t b_port_state;
44  uint8_t b_priv_flags; /* internal flags */
45  uint16_t b_hwmode;
46  uint16_t b_priority;
47  uint16_t b_self; /* here for comparison reasons */
48  uint32_t b_cost;
49  uint32_t b_flags;
50  uint32_t b_flags_mask;
51  uint32_t ce_mask; /* HACK to support attr macros */
52  struct rtnl_link_bridge_vlan vlan_info;
53 };
54 
55 static void set_bit(unsigned nr, uint32_t *addr)
56 {
57  if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
58  addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
59 }
60 
61 static int find_next_bit(int i, uint32_t x)
62 {
63  int j;
64 
65  if (i >= 32)
66  return -1;
67 
68  /* find first bit */
69  if (i < 0)
70  return __builtin_ffs(x);
71 
72  /* mask off prior finds to get next */
73  j = __builtin_ffs(x >> i);
74  return j ? j + i : 0;
75 }
76 
77 static struct rtnl_link_af_ops bridge_ops;
78 
79 #define IS_BRIDGE_LINK_ASSERT(link) \
80  if (!rtnl_link_is_bridge(link)) { \
81  APPBUG("A function was expecting a link object of type bridge."); \
82  return -NLE_OPNOTSUPP; \
83  }
84 
85 static inline struct bridge_data *bridge_data(struct rtnl_link *link)
86 {
87  return rtnl_link_af_data(link, &bridge_ops);
88 }
89 
90 static void *bridge_alloc(struct rtnl_link *link)
91 {
92  return calloc(1, sizeof(struct bridge_data));
93 }
94 
95 static void *bridge_clone(struct rtnl_link *link, void *data)
96 {
97  struct bridge_data *bd;
98 
99  if ((bd = bridge_alloc(link)))
100  memcpy(bd, data, sizeof(*bd));
101 
102  return bd;
103 }
104 
105 static void bridge_free(struct rtnl_link *link, void *data)
106 {
107  free(data);
108 }
109 
110 static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = {
111  [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
112  [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
113  [IFLA_BRPORT_COST] = { .type = NLA_U32 },
114  [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
115  [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
116  [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
117  [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 },
118  [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
119  [IFLA_BRPORT_LEARNING_SYNC] = { .type = NLA_U8 },
120  [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
121 };
122 
123 static void check_flag(struct rtnl_link *link, struct nlattr *attrs[],
124  int type, int flag)
125 {
126  if (attrs[type] && nla_get_u8(attrs[type]))
127  rtnl_link_bridge_set_flags(link, flag);
128 }
129 
130 static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
131  void *data)
132 {
133  struct bridge_data *bd = data;
134  struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
135  int err;
136 
137  /* Backwards compatibility */
138  if (!nla_is_nested(attr)) {
139  if (nla_len(attr) < 1)
140  return -NLE_RANGE;
141 
142  bd->b_port_state = nla_get_u8(attr);
143  bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
144 
145  return 0;
146  }
147 
148  if ((err = nla_parse_nested(br_attrs, IFLA_BRPORT_MAX, attr,
149  br_attrs_policy)) < 0)
150  return err;
151 
152  bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;
153 
154  if (br_attrs[IFLA_BRPORT_STATE]) {
155  bd->b_port_state = nla_get_u8(br_attrs[IFLA_BRPORT_STATE]);
156  bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
157  }
158 
159  if (br_attrs[IFLA_BRPORT_PRIORITY]) {
160  bd->b_priority = nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]);
161  bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
162  }
163 
164  if (br_attrs[IFLA_BRPORT_COST]) {
165  bd->b_cost = nla_get_u32(br_attrs[IFLA_BRPORT_COST]);
166  bd->ce_mask |= BRIDGE_ATTR_COST;
167  }
168 
169  check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE);
170  check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD);
171  check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK);
172  check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE);
173  check_flag(link, br_attrs, IFLA_BRPORT_UNICAST_FLOOD,
174  RTNL_BRIDGE_UNICAST_FLOOD);
175  check_flag(link, br_attrs, IFLA_BRPORT_LEARNING, RTNL_BRIDGE_LEARNING);
176  check_flag(link, br_attrs, IFLA_BRPORT_LEARNING_SYNC,
177  RTNL_BRIDGE_LEARNING_SYNC);
178 
179  return 0;
180 }
181 
182 static int bridge_parse_af_full(struct rtnl_link *link, struct nlattr *attr_full,
183  void *data)
184 {
185  struct bridge_data *bd = data;
186  struct bridge_vlan_info *vinfo = NULL;
187  uint16_t vid_range_start = 0;
188  uint16_t vid_range_flags = -1;
189 
190  struct nlattr *attr;
191  int remaining;
192 
193  nla_for_each_nested(attr, attr_full, remaining) {
194 
195  if (nla_type(attr) == IFLA_BRIDGE_MODE) {
196  bd->b_hwmode = nla_get_u16(attr);
197  bd->ce_mask |= BRIDGE_ATTR_HWMODE;
198  } else if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
199  continue;
200 
201  if (nla_len(attr) != sizeof(struct bridge_vlan_info))
202  return -EINVAL;
203 
204  vinfo = nla_data(attr);
205  if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
206  return -EINVAL;
207 
208 
209  if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
210  vid_range_start = vinfo->vid;
211  vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
212  continue;
213  }
214 
215  if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
216  /* sanity check the range flags */
217  if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
218  NL_DBG(1, "VLAN range flags differ; can not handle it.\n");
219  return -EINVAL;
220  }
221  } else {
222  vid_range_start = vinfo->vid;
223  }
224 
225  for (; vid_range_start <= vinfo->vid; vid_range_start++) {
226  if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
227  bd->vlan_info.pvid = vinfo->vid;
228 
229  if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
230  set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
231 
232  set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
233  bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
234  }
235 
236  vid_range_flags = -1;
237  }
238 
239  return 0;
240 }
241 
242 static int bridge_fill_af(struct rtnl_link *link, struct nl_msg *msg,
243  void *data)
244 {
245  struct bridge_data *bd = data;
246 
247  if ((bd->ce_mask & BRIDGE_ATTR_SELF)||(bd->ce_mask & BRIDGE_ATTR_HWMODE))
248  NLA_PUT_U16(msg, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF);
249 
250  if (bd->ce_mask & BRIDGE_ATTR_HWMODE)
251  NLA_PUT_U16(msg, IFLA_BRIDGE_MODE, bd->b_hwmode);
252 
253  return 0;
254 
255 nla_put_failure:
256  return -NLE_MSGSIZE;
257 }
258 
259 static int bridge_fill_pi(struct rtnl_link *link, struct nl_msg *msg,
260  void *data)
261 {
262  struct bridge_data *bd = data;
263 
264  if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
265  if (bd->b_flags_mask & RTNL_BRIDGE_BPDU_GUARD) {
266  NLA_PUT_U8(msg, IFLA_BRPORT_GUARD,
267  bd->b_flags & RTNL_BRIDGE_BPDU_GUARD);
268  }
269  if (bd->b_flags_mask & RTNL_BRIDGE_HAIRPIN_MODE) {
270  NLA_PUT_U8(msg, IFLA_BRPORT_MODE,
271  bd->b_flags & RTNL_BRIDGE_HAIRPIN_MODE);
272  }
273  if (bd->b_flags_mask & RTNL_BRIDGE_FAST_LEAVE) {
274  NLA_PUT_U8(msg, IFLA_BRPORT_FAST_LEAVE,
275  bd->b_flags & RTNL_BRIDGE_FAST_LEAVE);
276  }
277  if (bd->b_flags_mask & RTNL_BRIDGE_ROOT_BLOCK) {
278  NLA_PUT_U8(msg, IFLA_BRPORT_PROTECT,
279  bd->b_flags & RTNL_BRIDGE_ROOT_BLOCK);
280  }
281  if (bd->b_flags_mask & RTNL_BRIDGE_UNICAST_FLOOD) {
282  NLA_PUT_U8(msg, IFLA_BRPORT_UNICAST_FLOOD,
283  bd->b_flags & RTNL_BRIDGE_UNICAST_FLOOD);
284  }
285  if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING) {
286  NLA_PUT_U8(msg, IFLA_BRPORT_LEARNING,
287  bd->b_flags & RTNL_BRIDGE_LEARNING);
288  }
289  if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING_SYNC) {
290  NLA_PUT_U8(msg, IFLA_BRPORT_LEARNING_SYNC,
291  bd->b_flags & RTNL_BRIDGE_LEARNING_SYNC);
292  }
293  }
294 
295  if (bd->ce_mask & BRIDGE_ATTR_COST)
296  NLA_PUT_U32(msg, IFLA_BRPORT_COST, bd->b_cost);
297 
298  if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
299  NLA_PUT_U16(msg, IFLA_BRPORT_PRIORITY, bd->b_priority);
300 
301  if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
302  NLA_PUT_U8(msg, IFLA_BRPORT_STATE, bd->b_port_state);
303 
304  return 0;
305 
306 nla_put_failure:
307  return -NLE_MSGSIZE;
308 }
309 
310 static int bridge_override_rtm(struct rtnl_link *link) {
311  struct bridge_data *bd;
312 
313  if (!rtnl_link_is_bridge(link))
314  return 0;
315 
316  bd = bridge_data(link);
317 
318  if (bd->ce_mask & BRIDGE_ATTR_FLAGS)
319  return 1;
320 
321  return 0;
322 }
323 
324 static int bridge_get_af(struct nl_msg *msg, uint32_t *ext_filter_mask)
325 {
326  *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
327  return 0;
328 }
329 
330 static void dump_bitmap(struct nl_dump_params *p, const uint32_t *b)
331 {
332  int i = -1, j, k;
333  int start = -1, prev = -1;
334  int done, found = 0;
335 
336  for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
337  int base_bit;
338  uint32_t a = b[k];
339 
340  base_bit = k * 32;
341  i = -1;
342  done = 0;
343  while (!done) {
344  j = find_next_bit(i, a);
345  if (j > 0) {
346  /* first hit of any bit */
347  if (start < 0 && prev < 0) {
348  start = prev = j - 1 + base_bit;
349  goto next;
350  }
351  /* this bit is a continuation of prior bits */
352  if (j - 2 + base_bit == prev) {
353  prev++;
354  goto next;
355  }
356  } else
357  done = 1;
358 
359  if (start >= 0) {
360  found++;
361  if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
362  break;
363 
364  nl_dump(p, " %d", start);
365  if (start != prev)
366  nl_dump(p, "-%d", prev);
367 
368  if (done)
369  break;
370  }
371  if (j > 0)
372  start = prev = j - 1 + base_bit;
373 next:
374  i = j;
375  }
376  }
377  if (!found)
378  nl_dump(p, " <none>");
379 
380  return;
381 }
382 
383 static void rtnl_link_bridge_dump_vlans(struct nl_dump_params *p,
384  struct bridge_data *bd)
385 {
386  nl_dump(p, "pvid %u", bd->vlan_info.pvid);
387 
388  nl_dump(p, " all vlans:");
389  dump_bitmap(p, bd->vlan_info.vlan_bitmap);
390 
391  nl_dump(p, " untagged vlans:");
392  dump_bitmap(p, bd->vlan_info.untagged_bitmap);
393 }
394 
395 static void bridge_dump_details(struct rtnl_link *link,
396  struct nl_dump_params *p, void *data)
397 {
398  struct bridge_data *bd = data;
399 
400  nl_dump_line(p, " bridge: ");
401 
402  if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
403  nl_dump(p, "port-state %u ", bd->b_port_state);
404 
405  if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
406  nl_dump(p, "prio %u ", bd->b_priority);
407 
408  if (bd->ce_mask & BRIDGE_ATTR_COST)
409  nl_dump(p, "cost %u ", bd->b_cost);
410 
411  if (bd->ce_mask & BRIDGE_ATTR_HWMODE) {
412  char hbuf[32];
413 
414  rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf, sizeof(hbuf));
415  nl_dump(p, "hwmode %s", hbuf);
416  }
417 
418  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
419  rtnl_link_bridge_dump_vlans(p, bd);
420 
421  if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
422  char buf[256];
423 
424  rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
425  buf, sizeof(buf));
426  nl_dump(p, "%s", buf);
427  }
428 
429  nl_dump(p, "\n");
430 }
431 
432 static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b,
433  int family, uint32_t attrs, int flags)
434 {
435  struct bridge_data *a = bridge_data(_a);
436  struct bridge_data *b = bridge_data(_b);
437  int diff = 0;
438 
439 #define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR)
440  diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state);
441  diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
442  diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
443  diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
444  sizeof(struct rtnl_link_bridge_vlan)));
445  diff |= BRIDGE_DIFF(HWMODE, a->b_hwmode != b->b_hwmode);
446  diff |= BRIDGE_DIFF(SELF, a->b_self != b->b_self);
447 
448  if (flags & LOOSE_COMPARISON)
449  diff |= BRIDGE_DIFF(FLAGS,
450  (a->b_flags ^ b->b_flags) & b->b_flags_mask);
451  else
452  diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
453 #undef BRIDGE_DIFF
454 
455  return diff;
456 }
457 /** @endcond */
458 
459 /**
460  * Allocate link object of type bridge
461  *
462  * @return Allocated link object or NULL.
463  */
465 {
466  struct rtnl_link *link;
467  int err;
468 
469  if (!(link = rtnl_link_alloc()))
470  return NULL;
471 
472  if ((err = rtnl_link_set_type(link, "bridge")) < 0) {
473  rtnl_link_put(link);
474  return NULL;
475  }
476 
477  return link;
478 }
479 
480 /**
481  * Create a new kernel bridge device
482  * @arg sk netlink socket
483  * @arg name name of the bridge device or NULL
484  *
485  * Creates a new bridge device in the kernel. If no name is
486  * provided, the kernel will automatically pick a name of the
487  * form "type%d" (e.g. bridge0, vlan1, etc.)
488  *
489  * @return 0 on success or a negative error code
490 */
491 int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
492 {
493  int err;
494  struct rtnl_link *link;
495 
496  if (!(link = rtnl_link_bridge_alloc()))
497  return -NLE_NOMEM;
498 
499  if(name)
500  rtnl_link_set_name(link, name);
501 
502  err = rtnl_link_add(sk, link, NLM_F_CREATE);
503  rtnl_link_put(link);
504 
505  return err;
506 }
507 
508 /**
509  * Check if a link is a bridge
510  * @arg link Link object
511  *
512  * @return 1 if the link is a bridge, 0 otherwise.
513  */
515 {
516  return link->l_family == AF_BRIDGE &&
517  link->l_af_ops == &bridge_ops;
518 }
519 
520 /**
521  * Check if bridge has extended information
522  * @arg link Link object of type bridge
523  *
524  * Checks if the bridge object has been constructed based on
525  * information that is only available in newer kernels. This
526  * affectes the following functions:
527  * - rtnl_link_bridge_get_cost()
528  * - rtnl_link_bridge_get_priority()
529  * - rtnl_link_bridge_get_flags()
530  *
531  * @return 1 if extended information is available, otherwise 0 is returned.
532  */
534 {
535  struct bridge_data *bd;
536 
537  if (!rtnl_link_is_bridge(link))
538  return 0;
539 
540  bd = bridge_data(link);
541  return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
542 }
543 
544 /**
545  * Set Spanning Tree Protocol (STP) port state
546  * @arg link Link object of type bridge
547  * @arg state New STP port state
548  *
549  * The value of state must be one of the following:
550  * - BR_STATE_DISABLED
551  * - BR_STATE_LISTENING
552  * - BR_STATE_LEARNING
553  * - BR_STATE_FORWARDING
554  * - BR_STATE_BLOCKING
555  *
556  * @see rtnl_link_bridge_get_port_state()
557  *
558  * @return 0 on success or a negative error code.
559  * @retval -NLE_OPNOTSUPP Link is not a bridge
560  * @retval -NLE_INVAL Invalid state value (0..BR_STATE_BLOCKING)
561  */
562 int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
563 {
564  struct bridge_data *bd = bridge_data(link);
565 
566  IS_BRIDGE_LINK_ASSERT(link);
567 
568  if (state > BR_STATE_BLOCKING)
569  return -NLE_INVAL;
570 
571  bd->b_port_state = state;
572  bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
573 
574  return 0;
575 }
576 
577 /**
578  * Get Spanning Tree Protocol (STP) port state
579  * @arg link Link object of type bridge
580  *
581  * @see rtnl_link_bridge_set_port_state()
582  *
583  * @return The STP port state or a negative error code.
584  * @retval -NLE_OPNOTSUPP Link is not a bridge
585  */
587 {
588  struct bridge_data *bd = bridge_data(link);
589 
590  IS_BRIDGE_LINK_ASSERT(link);
591 
592  return bd->b_port_state;
593 }
594 
595 /**
596  * Set priority
597  * @arg link Link object of type bridge
598  * @arg prio Bridge priority
599  *
600  * @see rtnl_link_bridge_get_priority()
601  *
602  * @return 0 on success or a negative error code.
603  * @retval -NLE_OPNOTSUPP Link is not a bridge
604  */
605 int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
606 {
607  struct bridge_data *bd = bridge_data(link);
608 
609  IS_BRIDGE_LINK_ASSERT(link);
610 
611  bd->b_priority = prio;
612  bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
613 
614  return 0;
615 }
616 
617 /**
618  * Get priority
619  * @arg link Link object of type bridge
620  *
621  * @see rtnl_link_bridge_set_priority()
622  *
623  * @return 0 on success or a negative error code.
624  * @retval -NLE_OPNOTSUPP Link is not a bridge
625  */
627 {
628  struct bridge_data *bd = bridge_data(link);
629 
630  IS_BRIDGE_LINK_ASSERT(link);
631 
632  return bd->b_priority;
633 }
634 
635 /**
636  * Set Spanning Tree Protocol (STP) path cost
637  * @arg link Link object of type bridge
638  * @arg cost New STP path cost value
639  *
640  * @see rtnl_link_bridge_get_cost()
641  *
642  * @return The bridge priority or a negative error code.
643  * @retval -NLE_OPNOTSUPP Link is not a bridge
644  */
645 int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
646 {
647  struct bridge_data *bd = bridge_data(link);
648 
649  IS_BRIDGE_LINK_ASSERT(link);
650 
651  bd->b_cost = cost;
652  bd->ce_mask |= BRIDGE_ATTR_COST;
653 
654  return 0;
655 }
656 
657 /**
658  * Get Spanning Tree Protocol (STP) path cost
659  * @arg link Link object of type bridge
660  * @arg cost Pointer to store STP cost value
661  *
662  * @see rtnl_link_bridge_set_cost()
663  *
664  * @return 0 on success or a negative error code.
665  * @retval -NLE_OPNOTSUPP Link is not a bridge
666  * @retval -NLE_INVAL `cost` is not a valid pointer
667  */
668 int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
669 {
670  struct bridge_data *bd = bridge_data(link);
671 
672  IS_BRIDGE_LINK_ASSERT(link);
673 
674  if (!cost)
675  return -NLE_INVAL;
676 
677  *cost = bd->b_cost;
678 
679  return 0;
680 }
681 
682 /**
683  * Unset flags
684  * @arg link Link object of type bridge
685  * @arg flags Bridging flags to unset
686  *
687  * @see rtnl_link_bridge_set_flags()
688  * @see rtnl_link_bridge_get_flags()
689  *
690  * @return 0 on success or a negative error code.
691  * @retval -NLE_OPNOTSUPP Link is not a bridge
692  */
693 int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
694 {
695  struct bridge_data *bd = bridge_data(link);
696 
697  IS_BRIDGE_LINK_ASSERT(link);
698 
699  bd->b_flags_mask |= flags;
700  bd->b_flags &= ~flags;
701  bd->ce_mask |= BRIDGE_ATTR_FLAGS;
702 
703  return 0;
704 }
705 
706 /**
707  * Set flags
708  * @arg link Link object of type bridge
709  * @arg flags Bridging flags to set
710  *
711  * Valid flags are:
712  * - RTNL_BRIDGE_HAIRPIN_MODE
713  * - RTNL_BRIDGE_BPDU_GUARD
714  * - RTNL_BRIDGE_ROOT_BLOCK
715  * - RTNL_BRIDGE_FAST_LEAVE
716  * - RTNL_BRIDGE_UNICAST_FLOOD
717  * - RTNL_BRIDGE_LEARNING
718  * - RTNL_BRIDGE_LEARNING_SYNC
719  *
720  * @see rtnl_link_bridge_unset_flags()
721  * @see rtnl_link_bridge_get_flags()
722  *
723  * @return 0 on success or a negative error code.
724  * @retval -NLE_OPNOTSUPP Link is not a bridge
725  */
726 int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
727 {
728  struct bridge_data *bd = bridge_data(link);
729 
730  IS_BRIDGE_LINK_ASSERT(link);
731 
732  bd->b_flags_mask |= flags;
733  bd->b_flags |= flags;
734  bd->ce_mask |= BRIDGE_ATTR_FLAGS;
735 
736  return 0;
737 }
738 
739 /**
740  * Get flags
741  * @arg link Link object of type bridge
742  *
743  * @see rtnl_link_bridge_set_flags()
744  * @see rtnl_link_bridge_unset_flags()
745  *
746  * @return Flags or a negative error code.
747  * @retval -NLE_OPNOTSUPP Link is not a bridge
748  */
750 {
751  struct bridge_data *bd = bridge_data(link);
752 
753  IS_BRIDGE_LINK_ASSERT(link);
754 
755  return bd->b_flags;
756 }
757 
758 /**
759  * Set link change type to self
760  * @arg link Link Object of type bridge
761  *
762  * This will set the bridge change flag to self, meaning that changes to
763  * be applied with this link object will be applied directly to the physical
764  * device in a bridge instead of the virtual device.
765  *
766  * @return 0 on success or negative error code
767  * @return -NLE_OPNOTSUP Link is not a bridge
768  */
770 {
771  struct bridge_data *bd = bridge_data(link);
772 
773  IS_BRIDGE_LINK_ASSERT(link);
774 
775  bd->b_self |= 1;
776  bd->ce_mask |= BRIDGE_ATTR_SELF;
777 
778  return 0;
779 }
780 
781 /**
782  * Get hardware mode
783  * @arg link Link object of type bridge
784  * @arg hwmode Output argument.
785  *
786  * @see rtnl_link_bridge_set_hwmode()
787  *
788  * @return 0 if hardware mode is present and returned in hwmode
789  * @return -NLE_NOATTR if hardware mode is not present
790  * @return -NLE_OPNOTSUP Link is not a bridge
791  */
792 int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode)
793 {
794  struct bridge_data *bd = bridge_data(link);
795 
796  IS_BRIDGE_LINK_ASSERT(link);
797 
798  if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE))
799  return -NLE_NOATTR;
800 
801  *hwmode = bd->b_hwmode;
802  return 0;
803 }
804 
805 /**
806  * Set hardware mode
807  * @arg link Link object of type bridge
808  * @arg hwmode Hardware mode to set on link
809  *
810  * This will set the hardware mode of a link when it supports hardware
811  * offloads for bridging.
812  * @see rtnl_link_bridge_get_hwmode()
813  *
814  * Valid modes are:
815  * - RTNL_BRIDGE_HWMODE_VEB
816  * - RTNL_BRIDGE_HWMODE_VEPA
817  *
818  * When setting hardware mode, the change type will be set to self.
819  * @see rtnl_link_bridge_set_self()
820  *
821  * @return 0 on success or negative error code
822  * @return -NLE_OPNOTSUP Link is not a bridge
823  * @return -NLE_INVAL when specified hwmode is unsupported.
824  */
825 int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode)
826 {
827  int err;
828  struct bridge_data *bd = bridge_data(link);
829 
830  if (hwmode > RTNL_BRIDGE_HWMODE_MAX)
831  return -NLE_INVAL;
832 
833  if ((err = rtnl_link_bridge_set_self(link)) < 0)
834  return err;
835 
836  bd->b_hwmode = hwmode;
837  bd->ce_mask |= BRIDGE_ATTR_HWMODE;
838 
839  return 0;
840 }
841 
842 
843 static const struct trans_tbl bridge_flags[] = {
844  __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
845  __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
846  __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
847  __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
848  __ADD(RTNL_BRIDGE_UNICAST_FLOOD, flood),
849  __ADD(RTNL_BRIDGE_LEARNING, learning),
850  __ADD(RTNL_BRIDGE_LEARNING_SYNC, learning_sync),
851 };
852 
853 /**
854  * @name Flag Translation
855  * @{
856  */
857 
858 char *rtnl_link_bridge_flags2str(int flags, char *buf, size_t len)
859 {
860  return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
861 }
862 
863 int rtnl_link_bridge_str2flags(const char *name)
864 {
865  return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
866 }
867 
868 /** @} */
869 
870 static const struct trans_tbl port_states[] = {
871  __ADD(BR_STATE_DISABLED, disabled),
872  __ADD(BR_STATE_LISTENING, listening),
873  __ADD(BR_STATE_LEARNING, learning),
874  __ADD(BR_STATE_FORWARDING, forwarding),
875  __ADD(BR_STATE_BLOCKING, blocking),
876 };
877 
878 /**
879  * @name Port State Translation
880  * @{
881  */
882 
883 char *rtnl_link_bridge_portstate2str(int st, char *buf, size_t len)
884 {
885  return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states));
886 }
887 
888 int rtnl_link_bridge_str2portstate(const char *name)
889 {
890  return __str2type(name, port_states, ARRAY_SIZE(port_states));
891 }
892 
893 /** @} */
894 
895 static const struct trans_tbl hw_modes[] = {
896  __ADD(RTNL_BRIDGE_HWMODE_VEB, veb),
897  __ADD(RTNL_BRIDGE_HWMODE_VEPA, vepa),
898  __ADD(RTNL_BRIDGE_HWMODE_UNDEF, undef),
899 };
900 
901 /**
902  * @name Hardware Mode Translation
903  * @{
904  */
905 
906 char *rtnl_link_bridge_hwmode2str(uint16_t st, char *buf, size_t len) {
907  return __type2str(st, buf, len, hw_modes, ARRAY_SIZE(hw_modes));
908 }
909 
910 uint16_t rtnl_link_bridge_str2hwmode(const char *name)
911 {
912  return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes));
913 }
914 
915 /** @} */
916 
917 int rtnl_link_bridge_pvid(struct rtnl_link *link)
918 {
919  struct bridge_data *bd;
920 
921  IS_BRIDGE_LINK_ASSERT(link);
922 
923  bd = link->l_af_data[AF_BRIDGE];
924  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
925  return (int) bd->vlan_info.pvid;
926 
927  return -EINVAL;
928 }
929 
930 int rtnl_link_bridge_has_vlan(struct rtnl_link *link)
931 {
932  struct bridge_data *bd;
933  int i;
934 
935  IS_BRIDGE_LINK_ASSERT(link);
936 
937  bd = link->l_af_data[AF_BRIDGE];
938  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
939  if (bd->vlan_info.pvid)
940  return 1;
941 
942  for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
943  if (bd->vlan_info.vlan_bitmap[i] ||
944  bd->vlan_info.untagged_bitmap[i])
945  return 1;
946  }
947  }
948  return 0;
949 }
950 
951 struct rtnl_link_bridge_vlan *rtnl_link_bridge_get_port_vlan(struct rtnl_link *link)
952 {
953  struct bridge_data *data;
954 
955  if (!rtnl_link_is_bridge(link))
956  return NULL;
957 
958  data = link->l_af_data[AF_BRIDGE];
959  if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
960  return &data->vlan_info;
961 
962  return NULL;
963 }
964 
965 static struct rtnl_link_af_ops bridge_ops = {
966  .ao_family = AF_BRIDGE,
967  .ao_alloc = &bridge_alloc,
968  .ao_clone = &bridge_clone,
969  .ao_free = &bridge_free,
970  .ao_parse_protinfo = &bridge_parse_protinfo,
971  .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details,
972  .ao_compare = &bridge_compare,
973  .ao_parse_af_full = &bridge_parse_af_full,
974  .ao_get_af = &bridge_get_af,
975  .ao_fill_af = &bridge_fill_af,
976  .ao_fill_pi = &bridge_fill_pi,
977  .ao_fill_pi_flags = NLA_F_NESTED,
978  .ao_override_rtm = &bridge_override_rtm,
979  .ao_fill_af_no_nest = 1,
980 };
981 
982 static void __init bridge_init(void)
983 {
984  rtnl_link_af_register(&bridge_ops);
985 }
986 
987 static void __exit bridge_exit(void)
988 {
989  rtnl_link_af_unregister(&bridge_ops);
990 }
991 
992 /** @} */
8 bit integer
Definition: attr.h:41
int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode)
Set hardware mode.
Definition: bridge.c:825
int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
Set Spanning Tree Protocol (STP) path cost.
Definition: bridge.c:645
int rtnl_link_bridge_set_self(struct rtnl_link *link)
Set link change type to self.
Definition: bridge.c:769
int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset flags.
Definition: bridge.c:693
Attribute validation policy.
Definition: attr.h:69
int rtnl_link_bridge_get_priority(struct rtnl_link *link)
Get priority.
Definition: bridge.c:626
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:607
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:707
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:200
int rtnl_link_bridge_get_port_state(struct rtnl_link *link)
Get Spanning Tree Protocol (STP) port state.
Definition: bridge.c:586
int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
Set Spanning Tree Protocol (STP) port state.
Definition: bridge.c:562
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
Definition: attr.c:1033
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:605
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:1021
int rtnl_link_is_bridge(struct rtnl_link *link)
Check if a link is a bridge.
Definition: bridge.c:514
struct rtnl_link * rtnl_link_bridge_alloc(void)
Allocate link object of type bridge.
Definition: bridge.c:464
int nla_type(const struct nlattr *nla)
Return type of the attribute.
Definition: attr.c:110
16 bit integer
Definition: attr.h:42
int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode)
Get hardware mode.
Definition: bridge.c:792
int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
Create a new kernel bridge device.
Definition: bridge.c:491
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:121
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:236
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition: attr.c:132
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
Definition: attr.h:330
int rtnl_link_bridge_has_ext_info(struct rtnl_link *link)
Check if bridge has extended information.
Definition: bridge.c:533
int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
Get Spanning Tree Protocol (STP) path cost.
Definition: bridge.c:668
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:71
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:657
32 bit integer
Definition: attr.h:43
Dumping parameters.
Definition: types.h:33
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:218
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:962
int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
Set flags.
Definition: bridge.c:726
int rtnl_link_bridge_get_flags(struct rtnl_link *link)
Get flags.
Definition: bridge.c:749