libnl  3.3.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_get_af(struct nl_msg *msg, uint32_t *ext_filter_mask)
311 {
312  *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
313  return 0;
314 }
315 
316 static void dump_bitmap(struct nl_dump_params *p, const uint32_t *b)
317 {
318  int i = -1, j, k;
319  int start = -1, prev = -1;
320  int done, found = 0;
321 
322  for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
323  int base_bit;
324  uint32_t a = b[k];
325 
326  base_bit = k * 32;
327  i = -1;
328  done = 0;
329  while (!done) {
330  j = find_next_bit(i, a);
331  if (j > 0) {
332  /* first hit of any bit */
333  if (start < 0 && prev < 0) {
334  start = prev = j - 1 + base_bit;
335  goto next;
336  }
337  /* this bit is a continuation of prior bits */
338  if (j - 2 + base_bit == prev) {
339  prev++;
340  goto next;
341  }
342  } else
343  done = 1;
344 
345  if (start >= 0) {
346  found++;
347  if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
348  break;
349 
350  nl_dump(p, " %d", start);
351  if (start != prev)
352  nl_dump(p, "-%d", prev);
353 
354  if (done)
355  break;
356  }
357  if (j > 0)
358  start = prev = j - 1 + base_bit;
359 next:
360  i = j;
361  }
362  }
363  if (!found)
364  nl_dump(p, " <none>");
365 
366  return;
367 }
368 
369 static void rtnl_link_bridge_dump_vlans(struct nl_dump_params *p,
370  struct bridge_data *bd)
371 {
372  nl_dump(p, "pvid %u", bd->vlan_info.pvid);
373 
374  nl_dump(p, " all vlans:");
375  dump_bitmap(p, bd->vlan_info.vlan_bitmap);
376 
377  nl_dump(p, " untagged vlans:");
378  dump_bitmap(p, bd->vlan_info.untagged_bitmap);
379 }
380 
381 static void bridge_dump_details(struct rtnl_link *link,
382  struct nl_dump_params *p, void *data)
383 {
384  struct bridge_data *bd = data;
385 
386  nl_dump_line(p, " bridge: ");
387 
388  if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
389  nl_dump(p, "port-state %u ", bd->b_port_state);
390 
391  if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
392  nl_dump(p, "prio %u ", bd->b_priority);
393 
394  if (bd->ce_mask & BRIDGE_ATTR_COST)
395  nl_dump(p, "cost %u ", bd->b_cost);
396 
397  if (bd->ce_mask & BRIDGE_ATTR_HWMODE) {
398  char hbuf[32];
399 
400  rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf, sizeof(hbuf));
401  nl_dump(p, "hwmode %s", hbuf);
402  }
403 
404  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
405  rtnl_link_bridge_dump_vlans(p, bd);
406 
407  if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
408  char buf[256];
409 
410  rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
411  buf, sizeof(buf));
412  nl_dump(p, "%s", buf);
413  }
414 
415  nl_dump(p, "\n");
416 }
417 
418 static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b,
419  int family, uint32_t attrs, int flags)
420 {
421  struct bridge_data *a = bridge_data(_a);
422  struct bridge_data *b = bridge_data(_b);
423  int diff = 0;
424 
425 #define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR)
426  diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state);
427  diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
428  diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
429  diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
430  sizeof(struct rtnl_link_bridge_vlan)));
431  diff |= BRIDGE_DIFF(HWMODE, a->b_hwmode != b->b_hwmode);
432  diff |= BRIDGE_DIFF(SELF, a->b_self != b->b_self);
433 
434  if (flags & LOOSE_COMPARISON)
435  diff |= BRIDGE_DIFF(FLAGS,
436  (a->b_flags ^ b->b_flags) & b->b_flags_mask);
437  else
438  diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
439 #undef BRIDGE_DIFF
440 
441  return diff;
442 }
443 /** @endcond */
444 
445 /**
446  * Allocate link object of type bridge
447  *
448  * @return Allocated link object or NULL.
449  */
451 {
452  struct rtnl_link *link;
453  int err;
454 
455  if (!(link = rtnl_link_alloc()))
456  return NULL;
457 
458  if ((err = rtnl_link_set_type(link, "bridge")) < 0) {
459  rtnl_link_put(link);
460  return NULL;
461  }
462 
463  return link;
464 }
465 
466 /**
467  * Create a new kernel bridge device
468  * @arg sk netlink socket
469  * @arg name name of the bridge device or NULL
470  *
471  * Creates a new bridge device in the kernel. If no name is
472  * provided, the kernel will automatically pick a name of the
473  * form "type%d" (e.g. bridge0, vlan1, etc.)
474  *
475  * @return 0 on success or a negative error code
476 */
477 int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
478 {
479  int err;
480  struct rtnl_link *link;
481 
482  if (!(link = rtnl_link_bridge_alloc()))
483  return -NLE_NOMEM;
484 
485  if(name)
486  rtnl_link_set_name(link, name);
487 
488  err = rtnl_link_add(sk, link, NLM_F_CREATE);
489  rtnl_link_put(link);
490 
491  return err;
492 }
493 
494 /**
495  * Check if a link is a bridge
496  * @arg link Link object
497  *
498  * @return 1 if the link is a bridge, 0 otherwise.
499  */
501 {
502  return link->l_family == AF_BRIDGE &&
503  link->l_af_ops == &bridge_ops;
504 }
505 
506 /**
507  * Check if bridge has extended information
508  * @arg link Link object of type bridge
509  *
510  * Checks if the bridge object has been constructed based on
511  * information that is only available in newer kernels. This
512  * affectes the following functions:
513  * - rtnl_link_bridge_get_cost()
514  * - rtnl_link_bridge_get_priority()
515  * - rtnl_link_bridge_get_flags()
516  *
517  * @return 1 if extended information is available, otherwise 0 is returned.
518  */
520 {
521  struct bridge_data *bd;
522 
523  if (!rtnl_link_is_bridge(link))
524  return 0;
525 
526  bd = bridge_data(link);
527  return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
528 }
529 
530 /**
531  * Set Spanning Tree Protocol (STP) port state
532  * @arg link Link object of type bridge
533  * @arg state New STP port state
534  *
535  * The value of state must be one of the following:
536  * - BR_STATE_DISABLED
537  * - BR_STATE_LISTENING
538  * - BR_STATE_LEARNING
539  * - BR_STATE_FORWARDING
540  * - BR_STATE_BLOCKING
541  *
542  * @see rtnl_link_bridge_get_port_state()
543  *
544  * @return 0 on success or a negative error code.
545  * @retval -NLE_OPNOTSUPP Link is not a bridge
546  * @retval -NLE_INVAL Invalid state value (0..BR_STATE_BLOCKING)
547  */
548 int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
549 {
550  struct bridge_data *bd = bridge_data(link);
551 
552  IS_BRIDGE_LINK_ASSERT(link);
553 
554  if (state > BR_STATE_BLOCKING)
555  return -NLE_INVAL;
556 
557  bd->b_port_state = state;
558  bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
559 
560  return 0;
561 }
562 
563 /**
564  * Get Spanning Tree Protocol (STP) port state
565  * @arg link Link object of type bridge
566  *
567  * @see rtnl_link_bridge_set_port_state()
568  *
569  * @return The STP port state or a negative error code.
570  * @retval -NLE_OPNOTSUPP Link is not a bridge
571  */
573 {
574  struct bridge_data *bd = bridge_data(link);
575 
576  IS_BRIDGE_LINK_ASSERT(link);
577 
578  return bd->b_port_state;
579 }
580 
581 /**
582  * Set priority
583  * @arg link Link object of type bridge
584  * @arg prio Bridge priority
585  *
586  * @see rtnl_link_bridge_get_priority()
587  *
588  * @return 0 on success or a negative error code.
589  * @retval -NLE_OPNOTSUPP Link is not a bridge
590  */
591 int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
592 {
593  struct bridge_data *bd = bridge_data(link);
594 
595  IS_BRIDGE_LINK_ASSERT(link);
596 
597  bd->b_priority = prio;
598  bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
599 
600  return 0;
601 }
602 
603 /**
604  * Get priority
605  * @arg link Link object of type bridge
606  *
607  * @see rtnl_link_bridge_set_priority()
608  *
609  * @return 0 on success or a negative error code.
610  * @retval -NLE_OPNOTSUPP Link is not a bridge
611  */
613 {
614  struct bridge_data *bd = bridge_data(link);
615 
616  IS_BRIDGE_LINK_ASSERT(link);
617 
618  return bd->b_priority;
619 }
620 
621 /**
622  * Set Spanning Tree Protocol (STP) path cost
623  * @arg link Link object of type bridge
624  * @arg cost New STP path cost value
625  *
626  * @see rtnl_link_bridge_get_cost()
627  *
628  * @return The bridge priority or a negative error code.
629  * @retval -NLE_OPNOTSUPP Link is not a bridge
630  */
631 int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
632 {
633  struct bridge_data *bd = bridge_data(link);
634 
635  IS_BRIDGE_LINK_ASSERT(link);
636 
637  bd->b_cost = cost;
638  bd->ce_mask |= BRIDGE_ATTR_COST;
639 
640  return 0;
641 }
642 
643 /**
644  * Get Spanning Tree Protocol (STP) path cost
645  * @arg link Link object of type bridge
646  * @arg cost Pointer to store STP cost value
647  *
648  * @see rtnl_link_bridge_set_cost()
649  *
650  * @return 0 on success or a negative error code.
651  * @retval -NLE_OPNOTSUPP Link is not a bridge
652  * @retval -NLE_INVAL `cost` is not a valid pointer
653  */
654 int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
655 {
656  struct bridge_data *bd = bridge_data(link);
657 
658  IS_BRIDGE_LINK_ASSERT(link);
659 
660  if (!cost)
661  return -NLE_INVAL;
662 
663  *cost = bd->b_cost;
664 
665  return 0;
666 }
667 
668 /**
669  * Unset flags
670  * @arg link Link object of type bridge
671  * @arg flags Bridging flags to unset
672  *
673  * @see rtnl_link_bridge_set_flags()
674  * @see rtnl_link_bridge_get_flags()
675  *
676  * @return 0 on success or a negative error code.
677  * @retval -NLE_OPNOTSUPP Link is not a bridge
678  */
679 int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
680 {
681  struct bridge_data *bd = bridge_data(link);
682 
683  IS_BRIDGE_LINK_ASSERT(link);
684 
685  bd->b_flags_mask |= flags;
686  bd->b_flags &= ~flags;
687  bd->ce_mask |= BRIDGE_ATTR_FLAGS;
688 
689  return 0;
690 }
691 
692 /**
693  * Set flags
694  * @arg link Link object of type bridge
695  * @arg flags Bridging flags to set
696  *
697  * Valid flags are:
698  * - RTNL_BRIDGE_HAIRPIN_MODE
699  * - RTNL_BRIDGE_BPDU_GUARD
700  * - RTNL_BRIDGE_ROOT_BLOCK
701  * - RTNL_BRIDGE_FAST_LEAVE
702  * - RTNL_BRIDGE_UNICAST_FLOOD
703  * - RTNL_BRIDGE_LEARNING
704  * - RTNL_BRIDGE_LEARNING_SYNC
705  *
706  * @see rtnl_link_bridge_unset_flags()
707  * @see rtnl_link_bridge_get_flags()
708  *
709  * @return 0 on success or a negative error code.
710  * @retval -NLE_OPNOTSUPP Link is not a bridge
711  */
712 int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
713 {
714  struct bridge_data *bd = bridge_data(link);
715 
716  IS_BRIDGE_LINK_ASSERT(link);
717 
718  bd->b_flags_mask |= flags;
719  bd->b_flags |= flags;
720  bd->ce_mask |= BRIDGE_ATTR_FLAGS;
721 
722  return 0;
723 }
724 
725 /**
726  * Get flags
727  * @arg link Link object of type bridge
728  *
729  * @see rtnl_link_bridge_set_flags()
730  * @see rtnl_link_bridge_unset_flags()
731  *
732  * @return Flags or a negative error code.
733  * @retval -NLE_OPNOTSUPP Link is not a bridge
734  */
736 {
737  struct bridge_data *bd = bridge_data(link);
738 
739  IS_BRIDGE_LINK_ASSERT(link);
740 
741  return bd->b_flags;
742 }
743 
744 /**
745  * Set link change type to self
746  * @arg link Link Object of type bridge
747  *
748  * This will set the bridge change flag to self, meaning that changes to
749  * be applied with this link object will be applied directly to the physical
750  * device in a bridge instead of the virtual device.
751  *
752  * @return 0 on success or negative error code
753  * @return -NLE_OPNOTSUP Link is not a bridge
754  */
756 {
757  struct bridge_data *bd = bridge_data(link);
758 
759  IS_BRIDGE_LINK_ASSERT(link);
760 
761  bd->b_self |= 1;
762  bd->ce_mask |= BRIDGE_ATTR_SELF;
763 
764  return 0;
765 }
766 
767 /**
768  * Get hardware mode
769  * @arg link Link object of type bridge
770  * @arg hwmode Output argument.
771  *
772  * @see rtnl_link_bridge_set_hwmode()
773  *
774  * @return 0 if hardware mode is present and returned in hwmode
775  * @return -NLE_NOATTR if hardware mode is not present
776  * @return -NLE_OPNOTSUP Link is not a bridge
777  */
778 int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode)
779 {
780  struct bridge_data *bd = bridge_data(link);
781 
782  IS_BRIDGE_LINK_ASSERT(link);
783 
784  if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE))
785  return -NLE_NOATTR;
786 
787  *hwmode = bd->b_hwmode;
788  return 0;
789 }
790 
791 /**
792  * Set hardware mode
793  * @arg link Link object of type bridge
794  * @arg hwmode Hardware mode to set on link
795  *
796  * This will set the hardware mode of a link when it supports hardware
797  * offloads for bridging.
798  * @see rtnl_link_bridge_get_hwmode()
799  *
800  * Valid modes are:
801  * - RTNL_BRIDGE_HWMODE_VEB
802  * - RTNL_BRIDGE_HWMODE_VEPA
803  *
804  * When setting hardware mode, the change type will be set to self.
805  * @see rtnl_link_bridge_set_self()
806  *
807  * @return 0 on success or negative error code
808  * @return -NLE_OPNOTSUP Link is not a bridge
809  * @return -NLE_INVAL when specified hwmode is unsupported.
810  */
811 int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode)
812 {
813  int err;
814  struct bridge_data *bd = bridge_data(link);
815 
816  if (hwmode > RTNL_BRIDGE_HWMODE_MAX)
817  return -NLE_INVAL;
818 
819  if ((err = rtnl_link_bridge_set_self(link)) < 0)
820  return err;
821 
822  bd->b_hwmode = hwmode;
823  bd->ce_mask |= BRIDGE_ATTR_HWMODE;
824 
825  return 0;
826 }
827 
828 
829 static const struct trans_tbl bridge_flags[] = {
830  __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
831  __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
832  __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
833  __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
834  __ADD(RTNL_BRIDGE_UNICAST_FLOOD, flood),
835  __ADD(RTNL_BRIDGE_LEARNING, learning),
836  __ADD(RTNL_BRIDGE_LEARNING_SYNC, learning_sync),
837 };
838 
839 /**
840  * @name Flag Translation
841  * @{
842  */
843 
844 char *rtnl_link_bridge_flags2str(int flags, char *buf, size_t len)
845 {
846  return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
847 }
848 
849 int rtnl_link_bridge_str2flags(const char *name)
850 {
851  return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
852 }
853 
854 /** @} */
855 
856 static const struct trans_tbl port_states[] = {
857  __ADD(BR_STATE_DISABLED, disabled),
858  __ADD(BR_STATE_LISTENING, listening),
859  __ADD(BR_STATE_LEARNING, learning),
860  __ADD(BR_STATE_FORWARDING, forwarding),
861  __ADD(BR_STATE_BLOCKING, blocking),
862 };
863 
864 /**
865  * @name Port State Translation
866  * @{
867  */
868 
869 char *rtnl_link_bridge_portstate2str(int st, char *buf, size_t len)
870 {
871  return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states));
872 }
873 
874 int rtnl_link_bridge_str2portstate(const char *name)
875 {
876  return __str2type(name, port_states, ARRAY_SIZE(port_states));
877 }
878 
879 /** @} */
880 
881 static const struct trans_tbl hw_modes[] = {
882  __ADD(RTNL_BRIDGE_HWMODE_VEB, veb),
883  __ADD(RTNL_BRIDGE_HWMODE_VEPA, vepa),
884  __ADD(RTNL_BRIDGE_HWMODE_UNDEF, undef),
885 };
886 
887 /**
888  * @name Hardware Mode Translation
889  * @{
890  */
891 
892 char *rtnl_link_bridge_hwmode2str(uint16_t st, char *buf, size_t len) {
893  return __type2str(st, buf, len, hw_modes, ARRAY_SIZE(hw_modes));
894 }
895 
896 uint16_t rtnl_link_bridge_str2hwmode(const char *name)
897 {
898  return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes));
899 }
900 
901 /** @} */
902 
903 int rtnl_link_bridge_pvid(struct rtnl_link *link)
904 {
905  struct bridge_data *bd;
906 
907  IS_BRIDGE_LINK_ASSERT(link);
908 
909  bd = link->l_af_data[AF_BRIDGE];
910  if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
911  return (int) bd->vlan_info.pvid;
912 
913  return -EINVAL;
914 }
915 
916 int rtnl_link_bridge_has_vlan(struct rtnl_link *link)
917 {
918  struct bridge_data *bd;
919  int i;
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  if (bd->vlan_info.pvid)
926  return 1;
927 
928  for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
929  if (bd->vlan_info.vlan_bitmap[i] ||
930  bd->vlan_info.untagged_bitmap[i])
931  return 1;
932  }
933  }
934  return 0;
935 }
936 
937 struct rtnl_link_bridge_vlan *rtnl_link_bridge_get_port_vlan(struct rtnl_link *link)
938 {
939  struct bridge_data *data;
940 
941  if (!rtnl_link_is_bridge(link))
942  return NULL;
943 
944  data = link->l_af_data[AF_BRIDGE];
945  if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
946  return &data->vlan_info;
947 
948  return NULL;
949 }
950 
951 static struct rtnl_link_af_ops bridge_ops = {
952  .ao_family = AF_BRIDGE,
953  .ao_alloc = &bridge_alloc,
954  .ao_clone = &bridge_clone,
955  .ao_free = &bridge_free,
956  .ao_parse_protinfo = &bridge_parse_protinfo,
957  .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details,
958  .ao_compare = &bridge_compare,
959  .ao_parse_af_full = &bridge_parse_af_full,
960  .ao_get_af = &bridge_get_af,
961  .ao_fill_af = &bridge_fill_af,
962  .ao_fill_pi = &bridge_fill_pi,
963  .ao_fill_pi_flags = NLA_F_NESTED,
964  .ao_override_rtm = 1,
965  .ao_fill_af_no_nest = 1,
966 };
967 
968 static void __init bridge_init(void)
969 {
970  rtnl_link_af_register(&bridge_ops);
971 }
972 
973 static void __exit bridge_exit(void)
974 {
975  rtnl_link_af_unregister(&bridge_ops);
976 }
977 
978 /** @} */
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:811
int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
Set Spanning Tree Protocol (STP) path cost.
Definition: bridge.c:631
int rtnl_link_bridge_set_self(struct rtnl_link *link)
Set link change type to self.
Definition: bridge.c:755
int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset flags.
Definition: bridge.c:679
Attribute validation policy.
Definition: attr.h:69
int rtnl_link_bridge_get_priority(struct rtnl_link *link)
Get priority.
Definition: bridge.c:612
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:606
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:706
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:199
int rtnl_link_bridge_get_port_state(struct rtnl_link *link)
Get Spanning Tree Protocol (STP) port state.
Definition: bridge.c:572
int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
Set Spanning Tree Protocol (STP) port state.
Definition: bridge.c:548
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
Definition: attr.c:1011
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:591
int rtnl_link_is_bridge(struct rtnl_link *link)
Check if a link is a bridge.
Definition: bridge.c:500
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:999
struct rtnl_link * rtnl_link_bridge_alloc(void)
Allocate link object of type bridge.
Definition: bridge.c:450
int nla_type(const struct nlattr *nla)
Return type of the attribute.
Definition: attr.c:109
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:778
int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
Create a new kernel bridge device.
Definition: bridge.c:477
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:120
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:235
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:329
int rtnl_link_bridge_has_ext_info(struct rtnl_link *link)
Check if bridge has extended information.
Definition: bridge.c:519
int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
Get Spanning Tree Protocol (STP) path cost.
Definition: bridge.c:654
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:656
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:217
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:961
int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
Set flags.
Definition: bridge.c:712
int rtnl_link_bridge_get_flags(struct rtnl_link *link)
Get flags.
Definition: bridge.c:735