libnl 3.10.0
bridge.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2010-2013 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup bridge Bridging
9 *
10 * @details
11 * @{
12 */
13
14#include "nl-default.h"
15
16#include <linux/if_bridge.h>
17
18#include <netlink/netlink.h>
19#include <netlink/attr.h>
20#include <netlink/route/rtnl.h>
21#include <netlink/route/link/bridge.h>
22
23#include "nl-route.h"
24#include "link-api.h"
25#include "nl-priv-dynamic-core/nl-core.h"
26#include "nl-priv-static-route/nl-priv-static-route.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_CONFIG_MODE (1 << 6)
38
39#define PRIV_FLAG_NEW_ATTRS (1 << 0)
40
41struct 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_config_mode;
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
55static 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
61static void unset_bit(unsigned nr, uint32_t *addr)
62{
63 if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
64 addr[nr / 32] &= ~(((uint32_t) 1) << (nr % 32));
65}
66
67static bool vlan_id_untagged(struct rtnl_link_bridge_vlan *vlan_info, uint16_t vid)
68{
69 uint32_t mask, bit;
70
71 _nl_assert(vid / 32u < ARRAY_SIZE(vlan_info->untagged_bitmap));
72
73 mask = vlan_info->untagged_bitmap[vid / 32];
74 bit = (((uint32_t) 1) << vid % 32);
75
76 return mask & bit;
77}
78
79static int find_next_bit(int i, uint32_t x)
80{
81 int j;
82
83 if (i >= 32)
84 return -1;
85
86 /* find first bit */
87 if (i < 0)
88 return __builtin_ffs(x);
89
90 /* mask off prior finds to get next */
91 j = __builtin_ffs(x >> i);
92 return j ? j + i : 0;
93}
94
95static struct rtnl_link_af_ops bridge_ops;
96
97#define IS_BRIDGE_LINK_ASSERT(link) \
98 if (!rtnl_link_is_bridge(link)) { \
99 APPBUG("A function was expecting a link object of type bridge."); \
100 return -NLE_OPNOTSUPP; \
101 }
102
103static inline struct bridge_data *bridge_data(struct rtnl_link *link)
104{
105 return rtnl_link_af_data(link, &bridge_ops);
106}
107
108static void *bridge_alloc(struct rtnl_link *link)
109{
110 return calloc(1, sizeof(struct bridge_data));
111}
112
113static void *bridge_clone(struct rtnl_link *link, void *data)
114{
115 struct bridge_data *bd;
116
117 if ((bd = bridge_alloc(link)))
118 memcpy(bd, data, sizeof(*bd));
119
120 return bd;
121}
122
123static void bridge_free(struct rtnl_link *link, void *data)
124{
125 free(data);
126}
127
128static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = {
129 [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
130 [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
131 [IFLA_BRPORT_COST] = { .type = NLA_U32 },
132 [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
133 [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
134 [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
135 [IFLA_BRPORT_FAST_LEAVE] = { .type = NLA_U8 },
136 [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
137 [IFLA_BRPORT_LEARNING_SYNC] = { .type = NLA_U8 },
138 [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
139};
140
141static void check_flag(struct rtnl_link *link, struct nlattr *attrs[],
142 int type, int flag)
143{
144 if (attrs[type] && nla_get_u8(attrs[type]))
146}
147
148static int bridge_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
149 void *data)
150{
151 struct bridge_data *bd = data;
152 struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
153 int err;
154
155 /* Backwards compatibility */
156 if (!nla_is_nested(attr)) {
157 if (nla_len(attr) < 1)
158 return -NLE_RANGE;
159
160 bd->b_port_state = nla_get_u8(attr);
161 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
162
163 return 0;
164 }
165
166 if ((err = nla_parse_nested(br_attrs, IFLA_BRPORT_MAX, attr,
167 br_attrs_policy)) < 0)
168 return err;
169
170 bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;
171
172 if (br_attrs[IFLA_BRPORT_STATE]) {
173 bd->b_port_state = nla_get_u8(br_attrs[IFLA_BRPORT_STATE]);
174 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
175 }
176
177 if (br_attrs[IFLA_BRPORT_PRIORITY]) {
178 bd->b_priority = nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]);
179 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
180 }
181
182 if (br_attrs[IFLA_BRPORT_COST]) {
183 bd->b_cost = nla_get_u32(br_attrs[IFLA_BRPORT_COST]);
184 bd->ce_mask |= BRIDGE_ATTR_COST;
185 }
186
187 check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE);
188 check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD);
189 check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK);
190 check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE);
191 check_flag(link, br_attrs, IFLA_BRPORT_UNICAST_FLOOD,
192 RTNL_BRIDGE_UNICAST_FLOOD);
193 check_flag(link, br_attrs, IFLA_BRPORT_LEARNING, RTNL_BRIDGE_LEARNING);
194 check_flag(link, br_attrs, IFLA_BRPORT_LEARNING_SYNC,
195 RTNL_BRIDGE_LEARNING_SYNC);
196
197 return 0;
198}
199
200static int bridge_parse_af_full(struct rtnl_link *link, struct nlattr *attr_full,
201 void *data)
202{
203 struct bridge_data *bd = data;
204 struct bridge_vlan_info *vinfo = NULL;
205 uint16_t vid_range_start = 0;
206 uint16_t vid_range_flags = -1;
207
208 struct nlattr *attr;
209 int remaining;
210
211 nla_for_each_nested(attr, attr_full, remaining) {
212
213 if (nla_type(attr) == IFLA_BRIDGE_MODE) {
214 bd->b_hwmode = nla_get_u16(attr);
215 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
216 continue;
217 } else if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
218 continue;
219
220 if (nla_len(attr) != sizeof(struct bridge_vlan_info))
221 return -EINVAL;
222
223 vinfo = nla_data(attr);
224 if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
225 return -EINVAL;
226
227
228 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
229 vid_range_start = vinfo->vid;
230 vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
231 continue;
232 }
233
234 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
235 /* sanity check the range flags */
236 if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
237 NL_DBG(1, "VLAN range flags differ; can not handle it.\n");
238 return -EINVAL;
239 }
240 } else {
241 vid_range_start = vinfo->vid;
242 }
243
244 for (; vid_range_start <= vinfo->vid; vid_range_start++) {
245 if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
246 bd->vlan_info.pvid = vinfo->vid;
247
248 if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
249 set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
250
251 set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
252 bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
253 }
254
255 vid_range_flags = -1;
256 }
257
258 return 0;
259}
260
261int _nl_bridge_fill_vlan_info(struct nl_msg *msg, struct rtnl_link_bridge_vlan * vlan_info)
262{
263 struct bridge_vlan_info vinfo;
264 int i = -1, j, k;
265 int start = -1, prev = -1;
266 int done;
267 bool untagged = false;
268
269 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++)
270 {
271 int base_bit;
272 uint32_t a = vlan_info->vlan_bitmap[k];
273
274 base_bit = k * 32;
275 i = -1;
276 done = 0;
277 while (!done)
278 {
279 j = find_next_bit(i, a);
280 if (j > 0)
281 {
282 /* Skip if id equal to pvid */
283 if (vlan_info->pvid != 0 && j - 1 + base_bit == vlan_info->pvid)
284 goto nxt;
285 /* first hit of any bit */
286 if (start < 0 && prev < 0)
287 {
288 start = prev = j - 1 + base_bit;
289 /* Start range attribute */
290 untagged = vlan_id_untagged(vlan_info,start);
291 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN;
292 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
293 vinfo.vid = start;
294 goto nxt;
295 }
296 /* this bit is a continuation of prior bits */
297 if (j - 2 + base_bit == prev)
298 {
299 prev++;
300 /* Hit end of untagged/tagged range */
301 if (untagged != vlan_id_untagged(vlan_info,prev))
302 {
303 /* put vlan into attributes */
304 if (start == prev-1)
305 {
306 /* only 1 vid in range */
307 vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
308 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,sizeof(vinfo),&vinfo);
309 }
310 else
311 {
312 /* end of untagged/tagged range */
313 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,sizeof(vinfo),&vinfo);
314
315 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END;
316 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
317 vinfo.vid = prev-1;
318 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,sizeof(vinfo),&vinfo);
319 }
320 /* start of new range */
321 untagged = !untagged;
322 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN;
323 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
324 vinfo.vid = prev;
325 }
326 goto nxt;
327 }
328 }
329 else
330 done = 1;
331
332 if (start >= 0)
333 {
334 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
335 break;
336
337 if (vinfo.flags & BRIDGE_VLAN_INFO_RANGE_BEGIN && start != prev)
338 {
339 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,sizeof(vinfo),&vinfo);
340
341 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END;
342 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
343 vinfo.vid = prev;
344 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,sizeof(vinfo),&vinfo);
345 }
346 else if (start == prev)
347 {
348 vinfo.flags = untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
349 vinfo.vid = start;
350 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,sizeof(vinfo),&vinfo);
351 }
352
353 if (done)
354 break;
355 }
356 if (j > 0)
357 {
358 start = prev = j - 1 + base_bit;
359 untagged = vlan_id_untagged(vlan_info,start);
360 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN;
361 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
362 vinfo.vid = start;
363 }
364nxt:
365 i = j;
366 }
367 }
368
369 if (vlan_info->pvid != 0)
370 {
371 untagged = vlan_id_untagged(vlan_info,vlan_info->pvid);
372 vinfo.flags = BRIDGE_VLAN_INFO_PVID;
373 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
374 vinfo.vid = vlan_info->pvid;
375 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,sizeof(vinfo),&vinfo);
376 }
377
378 return 0;
379
380nla_put_failure:
381 return -NLE_MSGSIZE;
382}
383
384static int bridge_fill_af(struct rtnl_link *link, struct nl_msg *msg,
385 void *data)
386{
387 struct bridge_data *bd = data;
388
389 if (bd->ce_mask & BRIDGE_ATTR_HWMODE)
390 {
391 NLA_PUT_U16(msg, IFLA_BRIDGE_MODE, bd->b_hwmode);
392 bd->b_config_mode = BRIDGE_FLAGS_SELF;
393 bd->ce_mask |= BRIDGE_ATTR_CONFIG_MODE;
394 }
395
396 if (bd->ce_mask & BRIDGE_ATTR_CONFIG_MODE)
397 NLA_PUT_U16(msg, IFLA_BRIDGE_FLAGS, bd->b_config_mode);
398
399 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
400 if (_nl_bridge_fill_vlan_info(msg, &bd->vlan_info)) {
401 goto nla_put_failure;
402 }
403 }
404
405 return 0;
406
407nla_put_failure:
408 return -NLE_MSGSIZE;
409}
410
411static int bridge_fill_pi(struct rtnl_link *link, struct nl_msg *msg,
412 void *data)
413{
414 struct bridge_data *bd = data;
415
416 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
417 if (bd->b_flags_mask & RTNL_BRIDGE_BPDU_GUARD) {
418 NLA_PUT_U8(msg, IFLA_BRPORT_GUARD,
419 bd->b_flags & RTNL_BRIDGE_BPDU_GUARD);
420 }
421 if (bd->b_flags_mask & RTNL_BRIDGE_HAIRPIN_MODE) {
422 NLA_PUT_U8(msg, IFLA_BRPORT_MODE,
423 bd->b_flags & RTNL_BRIDGE_HAIRPIN_MODE);
424 }
425 if (bd->b_flags_mask & RTNL_BRIDGE_FAST_LEAVE) {
426 NLA_PUT_U8(msg, IFLA_BRPORT_FAST_LEAVE,
427 bd->b_flags & RTNL_BRIDGE_FAST_LEAVE);
428 }
429 if (bd->b_flags_mask & RTNL_BRIDGE_ROOT_BLOCK) {
430 NLA_PUT_U8(msg, IFLA_BRPORT_PROTECT,
431 bd->b_flags & RTNL_BRIDGE_ROOT_BLOCK);
432 }
433 if (bd->b_flags_mask & RTNL_BRIDGE_UNICAST_FLOOD) {
434 NLA_PUT_U8(msg, IFLA_BRPORT_UNICAST_FLOOD,
435 bd->b_flags & RTNL_BRIDGE_UNICAST_FLOOD);
436 }
437 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING) {
438 NLA_PUT_U8(msg, IFLA_BRPORT_LEARNING,
439 bd->b_flags & RTNL_BRIDGE_LEARNING);
440 }
441 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING_SYNC) {
442 NLA_PUT_U8(msg, IFLA_BRPORT_LEARNING_SYNC,
443 bd->b_flags & RTNL_BRIDGE_LEARNING_SYNC);
444 }
445 }
446
447 if (bd->ce_mask & BRIDGE_ATTR_COST)
448 NLA_PUT_U32(msg, IFLA_BRPORT_COST, bd->b_cost);
449
450 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
451 NLA_PUT_U16(msg, IFLA_BRPORT_PRIORITY, bd->b_priority);
452
453 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
454 NLA_PUT_U8(msg, IFLA_BRPORT_STATE, bd->b_port_state);
455
456 return 0;
457
458nla_put_failure:
459 return -NLE_MSGSIZE;
460}
461
462static int bridge_override_rtm(struct rtnl_link *link) {
463 struct bridge_data *bd;
464
465 if (!rtnl_link_is_bridge(link))
466 return 0;
467
468 bd = bridge_data(link);
469
470 if (bd->ce_mask & BRIDGE_ATTR_FLAGS)
471 return 1;
472
473 return 0;
474}
475
476static int bridge_get_af(struct nl_msg *msg, uint32_t *ext_filter_mask)
477{
478 *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
479 return 0;
480}
481
482static void dump_bitmap(struct nl_dump_params *p, const uint32_t *b)
483{
484 int i = -1, j, k;
485 int start = -1, prev = -1;
486 int done, found = 0;
487
488 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
489 int base_bit;
490 uint32_t a = b[k];
491
492 base_bit = k * 32;
493 i = -1;
494 done = 0;
495 while (!done) {
496 j = find_next_bit(i, a);
497 if (j > 0) {
498 /* first hit of any bit */
499 if (start < 0 && prev < 0) {
500 start = prev = j - 1 + base_bit;
501 goto next;
502 }
503 /* this bit is a continuation of prior bits */
504 if (j - 2 + base_bit == prev) {
505 prev++;
506 goto next;
507 }
508 } else
509 done = 1;
510
511 if (start >= 0) {
512 found++;
513 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
514 break;
515
516 nl_dump(p, " %d", start);
517 if (start != prev)
518 nl_dump(p, "-%d", prev);
519
520 if (done)
521 break;
522 }
523 if (j > 0)
524 start = prev = j - 1 + base_bit;
525next:
526 i = j;
527 }
528 }
529 if (!found)
530 nl_dump(p, " <none>");
531
532 return;
533}
534
535static void rtnl_link_bridge_dump_vlans(struct nl_dump_params *p,
536 struct bridge_data *bd)
537{
538 nl_dump(p, "pvid %u", bd->vlan_info.pvid);
539
540 nl_dump(p, " all vlans:");
541 dump_bitmap(p, bd->vlan_info.vlan_bitmap);
542
543 nl_dump(p, " untagged vlans:");
544 dump_bitmap(p, bd->vlan_info.untagged_bitmap);
545}
546
547static void bridge_dump_details(struct rtnl_link *link,
548 struct nl_dump_params *p, void *data)
549{
550 struct bridge_data *bd = data;
551
552 nl_dump_line(p, " bridge: ");
553
554 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
555 nl_dump(p, "port-state %u ", bd->b_port_state);
556
557 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
558 nl_dump(p, "prio %u ", bd->b_priority);
559
560 if (bd->ce_mask & BRIDGE_ATTR_COST)
561 nl_dump(p, "cost %u ", bd->b_cost);
562
563 if (bd->ce_mask & BRIDGE_ATTR_HWMODE) {
564 char hbuf[32];
565
566 rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf, sizeof(hbuf));
567 nl_dump(p, "hwmode %s", hbuf);
568 }
569
570 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
571 rtnl_link_bridge_dump_vlans(p, bd);
572
573 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
574 char buf[256];
575
576 rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
577 buf, sizeof(buf));
578 nl_dump(p, "%s", buf);
579 }
580
581 nl_dump(p, "\n");
582}
583
584static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b,
585 int family, uint32_t attrs, int flags)
586{
587 struct bridge_data *a = bridge_data(_a);
588 struct bridge_data *b = bridge_data(_b);
589 int diff = 0;
590
591#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
592 diff |= _DIFF(BRIDGE_ATTR_PORT_STATE,
593 a->b_port_state != b->b_port_state);
594 diff |= _DIFF(BRIDGE_ATTR_PRIORITY, a->b_priority != b->b_priority);
595 diff |= _DIFF(BRIDGE_ATTR_COST, a->b_cost != b->b_cost);
596 diff |= _DIFF(BRIDGE_ATTR_PORT_VLAN,
597 memcmp(&a->vlan_info, &b->vlan_info,
598 sizeof(struct rtnl_link_bridge_vlan)));
599 diff |= _DIFF(BRIDGE_ATTR_HWMODE, a->b_hwmode != b->b_hwmode);
600 diff |= _DIFF(BRIDGE_ATTR_CONFIG_MODE, a->b_config_mode != b->b_config_mode);
601
602 if (flags & LOOSE_COMPARISON)
603 diff |= _DIFF(BRIDGE_ATTR_FLAGS,
604 (a->b_flags ^ b->b_flags) & b->b_flags_mask);
605 else
606 diff |= _DIFF(BRIDGE_ATTR_FLAGS, a->b_flags != b->b_flags);
607#undef _DIFF
608
609 return diff;
610}
611/** @endcond */
612
613/**
614 * Allocate link object of type bridge
615 *
616 * @return Allocated link object or NULL.
617 */
619{
620 struct rtnl_link *link;
621
622 if (!(link = rtnl_link_alloc()))
623 return NULL;
624
625 if (rtnl_link_set_type(link, "bridge") < 0) {
626 rtnl_link_put(link);
627 return NULL;
628 }
629
630 return link;
631}
632
633/**
634 * Create a new kernel bridge device
635 * @arg sk netlink socket
636 * @arg name name of the bridge device or NULL
637 *
638 * Creates a new bridge device in the kernel. If no name is
639 * provided, the kernel will automatically pick a name of the
640 * form "type%d" (e.g. bridge0, vlan1, etc.)
641 *
642 * @return 0 on success or a negative error code
643*/
644int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
645{
646 int err;
647 struct rtnl_link *link;
648
649 if (!(link = rtnl_link_bridge_alloc()))
650 return -NLE_NOMEM;
651
652 if(name)
653 rtnl_link_set_name(link, name);
654
655 err = rtnl_link_add(sk, link, NLM_F_CREATE);
656 rtnl_link_put(link);
657
658 return err;
659}
660
661/**
662 * Check if a link is a bridge
663 * @arg link Link object
664 *
665 * @return 1 if the link is a bridge, 0 otherwise.
666 */
668{
669 return link->l_family == AF_BRIDGE &&
670 link->l_af_ops == &bridge_ops;
671}
672
673/**
674 * Check if bridge has extended information
675 * @arg link Link object of type bridge
676 *
677 * Checks if the bridge object has been constructed based on
678 * information that is only available in newer kernels. This
679 * affectes the following functions:
680 * - rtnl_link_bridge_get_cost()
681 * - rtnl_link_bridge_get_priority()
682 * - rtnl_link_bridge_get_flags()
683 *
684 * @return 1 if extended information is available, otherwise 0 is returned.
685 */
687{
688 struct bridge_data *bd;
689
690 if (!rtnl_link_is_bridge(link))
691 return 0;
692
693 bd = bridge_data(link);
694 return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
695}
696
697/**
698 * Set Spanning Tree Protocol (STP) port state
699 * @arg link Link object of type bridge
700 * @arg state New STP port state
701 *
702 * The value of state must be one of the following:
703 * - BR_STATE_DISABLED
704 * - BR_STATE_LISTENING
705 * - BR_STATE_LEARNING
706 * - BR_STATE_FORWARDING
707 * - BR_STATE_BLOCKING
708 *
709 * @see rtnl_link_bridge_get_port_state()
710 *
711 * @return 0 on success or a negative error code.
712 * @retval -NLE_OPNOTSUPP Link is not a bridge
713 * @retval -NLE_INVAL Invalid state value (0..BR_STATE_BLOCKING)
714 */
715int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
716{
717 struct bridge_data *bd = bridge_data(link);
718
719 IS_BRIDGE_LINK_ASSERT(link);
720
721 if (state > BR_STATE_BLOCKING)
722 return -NLE_INVAL;
723
724 bd->b_port_state = state;
725 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
726
727 return 0;
728}
729
730/**
731 * Get Spanning Tree Protocol (STP) port state
732 * @arg link Link object of type bridge
733 *
734 * @see rtnl_link_bridge_set_port_state()
735 *
736 * @return The STP port state or a negative error code.
737 * @retval -NLE_OPNOTSUPP Link is not a bridge
738 */
740{
741 struct bridge_data *bd = bridge_data(link);
742
743 IS_BRIDGE_LINK_ASSERT(link);
744
745 return bd->b_port_state;
746}
747
748/**
749 * Set priority
750 * @arg link Link object of type bridge
751 * @arg prio Bridge priority
752 *
753 * @see rtnl_link_bridge_get_priority()
754 *
755 * @return 0 on success or a negative error code.
756 * @retval -NLE_OPNOTSUPP Link is not a bridge
757 */
758int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
759{
760 struct bridge_data *bd = bridge_data(link);
761
762 IS_BRIDGE_LINK_ASSERT(link);
763
764 bd->b_priority = prio;
765 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
766
767 return 0;
768}
769
770/**
771 * Get priority
772 * @arg link Link object of type bridge
773 *
774 * @see rtnl_link_bridge_set_priority()
775 *
776 * @return 0 on success or a negative error code.
777 * @retval -NLE_OPNOTSUPP Link is not a bridge
778 */
780{
781 struct bridge_data *bd = bridge_data(link);
782
783 IS_BRIDGE_LINK_ASSERT(link);
784
785 return bd->b_priority;
786}
787
788/**
789 * Set Spanning Tree Protocol (STP) path cost
790 * @arg link Link object of type bridge
791 * @arg cost New STP path cost value
792 *
793 * @see rtnl_link_bridge_get_cost()
794 *
795 * @return The bridge priority or a negative error code.
796 * @retval -NLE_OPNOTSUPP Link is not a bridge
797 */
798int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
799{
800 struct bridge_data *bd = bridge_data(link);
801
802 IS_BRIDGE_LINK_ASSERT(link);
803
804 bd->b_cost = cost;
805 bd->ce_mask |= BRIDGE_ATTR_COST;
806
807 return 0;
808}
809
810/**
811 * Get Spanning Tree Protocol (STP) path cost
812 * @arg link Link object of type bridge
813 * @arg cost Pointer to store STP cost value
814 *
815 * @see rtnl_link_bridge_set_cost()
816 *
817 * @return 0 on success or a negative error code.
818 * @retval -NLE_OPNOTSUPP Link is not a bridge
819 * @retval -NLE_INVAL `cost` is not a valid pointer
820 */
821int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
822{
823 struct bridge_data *bd = bridge_data(link);
824
825 IS_BRIDGE_LINK_ASSERT(link);
826
827 if (!cost)
828 return -NLE_INVAL;
829
830 *cost = bd->b_cost;
831
832 return 0;
833}
834
835/**
836 * Unset flags
837 * @arg link Link object of type bridge
838 * @arg flags Bridging flags to unset
839 *
840 * @see rtnl_link_bridge_set_flags()
841 * @see rtnl_link_bridge_get_flags()
842 *
843 * @return 0 on success or a negative error code.
844 * @retval -NLE_OPNOTSUPP Link is not a bridge
845 */
846int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
847{
848 struct bridge_data *bd = bridge_data(link);
849
850 IS_BRIDGE_LINK_ASSERT(link);
851
852 bd->b_flags_mask |= flags;
853 bd->b_flags &= ~flags;
854 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
855
856 return 0;
857}
858
859/**
860 * Set flags
861 * @arg link Link object of type bridge
862 * @arg flags Bridging flags to set
863 *
864 * Valid flags are:
865 * - RTNL_BRIDGE_HAIRPIN_MODE
866 * - RTNL_BRIDGE_BPDU_GUARD
867 * - RTNL_BRIDGE_ROOT_BLOCK
868 * - RTNL_BRIDGE_FAST_LEAVE
869 * - RTNL_BRIDGE_UNICAST_FLOOD
870 * - RTNL_BRIDGE_LEARNING
871 * - RTNL_BRIDGE_LEARNING_SYNC
872 *
873 * @see rtnl_link_bridge_unset_flags()
874 * @see rtnl_link_bridge_get_flags()
875 *
876 * @return 0 on success or a negative error code.
877 * @retval -NLE_OPNOTSUPP Link is not a bridge
878 */
879int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
880{
881 struct bridge_data *bd = bridge_data(link);
882
883 IS_BRIDGE_LINK_ASSERT(link);
884
885 bd->b_flags_mask |= flags;
886 bd->b_flags |= flags;
887 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
888
889 return 0;
890}
891
892/**
893 * Get flags
894 * @arg link Link object of type bridge
895 *
896 * @see rtnl_link_bridge_set_flags()
897 * @see rtnl_link_bridge_unset_flags()
898 *
899 * @return Flags or a negative error code.
900 * @retval -NLE_OPNOTSUPP Link is not a bridge
901 */
903{
904 struct bridge_data *bd = bridge_data(link);
905
906 IS_BRIDGE_LINK_ASSERT(link);
907
908 return bd->b_flags;
909}
910
911/**
912 * Set link change type to self
913 * @arg link Link Object of type bridge
914 *
915 * This will set the bridge change flag to self, meaning that changes to
916 * be applied with this link object will be applied directly to the physical
917 * device in a bridge instead of the virtual device.
918 *
919 * @return 0 on success or negative error code
920 * @return -NLE_OPNOTSUP Link is not a bridge
921 */
923{
924 struct bridge_data *bd = bridge_data(link);
925
926 IS_BRIDGE_LINK_ASSERT(link);
927
928 bd->b_config_mode = BRIDGE_FLAGS_SELF;
929 bd->ce_mask |= BRIDGE_ATTR_CONFIG_MODE;
930
931 return 0;
932}
933
934/**
935 * Set link change type to master
936 * @arg link Link Object of type bridge
937 *
938 * This will set the bridge change flag to master, meaning that changes to
939 * be applied with this link object will be applied directly to the virtual
940 * device in a bridge instead of the physical device.
941 *
942 * @return 0 on success or negative error code
943 * @return -NLE_OPNOTSUP Link is not a bridge
944 */
946{
947 struct bridge_data *bd = bridge_data(link);
948
949 IS_BRIDGE_LINK_ASSERT(link);
950
951 bd->b_config_mode = BRIDGE_FLAGS_MASTER;
952 bd->ce_mask |= BRIDGE_ATTR_CONFIG_MODE;
953
954 return 0;
955}
956
957/**
958 * Get hardware mode
959 * @arg link Link object of type bridge
960 * @arg hwmode Output argument.
961 *
962 * @see rtnl_link_bridge_set_hwmode()
963 *
964 * @return 0 if hardware mode is present and returned in hwmode
965 * @return -NLE_NOATTR if hardware mode is not present
966 * @return -NLE_OPNOTSUP Link is not a bridge
967 */
968int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode)
969{
970 struct bridge_data *bd = bridge_data(link);
971
972 IS_BRIDGE_LINK_ASSERT(link);
973
974 if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE))
975 return -NLE_NOATTR;
976
977 *hwmode = bd->b_hwmode;
978 return 0;
979}
980
981/**
982 * Set hardware mode
983 * @arg link Link object of type bridge
984 * @arg hwmode Hardware mode to set on link
985 *
986 * This will set the hardware mode of a link when it supports hardware
987 * offloads for bridging.
988 * @see rtnl_link_bridge_get_hwmode()
989 *
990 * Valid modes are:
991 * - RTNL_BRIDGE_HWMODE_VEB
992 * - RTNL_BRIDGE_HWMODE_VEPA
993 *
994 * When setting hardware mode, the change type will be set to self.
995 * @see rtnl_link_bridge_set_self()
996 *
997 * @return 0 on success or negative error code
998 * @return -NLE_OPNOTSUP Link is not a bridge
999 * @return -NLE_INVAL when specified hwmode is unsupported.
1000 */
1001int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode)
1002{
1003 int err;
1004 struct bridge_data *bd = bridge_data(link);
1005
1006 if (hwmode > RTNL_BRIDGE_HWMODE_MAX)
1007 return -NLE_INVAL;
1008
1009 if ((err = rtnl_link_bridge_set_self(link)) < 0)
1010 return err;
1011
1012 bd->b_hwmode = hwmode;
1013 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
1014
1015 return 0;
1016}
1017
1018
1019static const struct trans_tbl bridge_flags[] = {
1020 __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
1021 __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
1022 __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
1023 __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
1024 __ADD(RTNL_BRIDGE_UNICAST_FLOOD, flood),
1025 __ADD(RTNL_BRIDGE_LEARNING, learning),
1026 __ADD(RTNL_BRIDGE_LEARNING_SYNC, learning_sync),
1027};
1028
1029/**
1030 * @name Flag Translation
1031 * @{
1032 */
1033
1034char *rtnl_link_bridge_flags2str(int flags, char *buf, size_t len)
1035{
1036 return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
1037}
1038
1039int rtnl_link_bridge_str2flags(const char *name)
1040{
1041 return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
1042}
1043
1044/** @} */
1045
1046static const struct trans_tbl port_states[] = {
1047 __ADD(BR_STATE_DISABLED, disabled),
1048 __ADD(BR_STATE_LISTENING, listening),
1049 __ADD(BR_STATE_LEARNING, learning),
1050 __ADD(BR_STATE_FORWARDING, forwarding),
1051 __ADD(BR_STATE_BLOCKING, blocking),
1052};
1053
1054/**
1055 * @name Port State Translation
1056 * @{
1057 */
1058
1059char *rtnl_link_bridge_portstate2str(int st, char *buf, size_t len)
1060{
1061 return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states));
1062}
1063
1064int rtnl_link_bridge_str2portstate(const char *name)
1065{
1066 return __str2type(name, port_states, ARRAY_SIZE(port_states));
1067}
1068
1069/** @} */
1070
1071static const struct trans_tbl hw_modes[] = {
1072 __ADD(RTNL_BRIDGE_HWMODE_VEB, veb),
1073 __ADD(RTNL_BRIDGE_HWMODE_VEPA, vepa),
1074 __ADD(RTNL_BRIDGE_HWMODE_UNDEF, undef),
1075};
1076
1077/**
1078 * @name Hardware Mode Translation
1079 * @{
1080 */
1081
1082char *rtnl_link_bridge_hwmode2str(uint16_t st, char *buf, size_t len) {
1083 return __type2str(st, buf, len, hw_modes, ARRAY_SIZE(hw_modes));
1084}
1085
1086uint16_t rtnl_link_bridge_str2hwmode(const char *name)
1087{
1088 return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes));
1089}
1090
1091/** @} */
1092
1093/**
1094 * Enable the ability to set vlan info
1095 * @arg link Link object of type bridge
1096 *
1097 * @return 0 on success or negative error code
1098 * @return -NLE_OPNOTSUP Link is not a bridge
1099 */
1101{
1102 struct bridge_data *bd = bridge_data(link);
1103
1104 IS_BRIDGE_LINK_ASSERT(link);
1105
1106 bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
1107
1108 return 0;
1109}
1110
1111/**
1112 * @name Quality of Service
1113 * @{
1114 */
1115
1116/**
1117 * Set port vlan membership range
1118 * @arg link Link object of type bridge
1119 * @arg start Start of membership range.
1120 * @arg end End of membership range.
1121 * @arg untagged Set membership range to be untagged.
1122 *
1123 * This will set the vlan membership range for a bridge port.
1124 * This will unset the untagged membership if untagged is false.
1125 * Supported range is 1-4094
1126 *
1127 * @return 0 on success or negative error code
1128 * @return -NLE_NOATTR if port vlan attribute not present
1129 * @return -NLE_OPNOTSUP Link is not a bridge
1130 * @return -NLE_INVAL range is not in supported range.
1131 */
1132int rtnl_link_bridge_set_port_vlan_map_range (struct rtnl_link *link, uint16_t start, uint16_t end, int untagged)
1133{
1134 struct rtnl_link_bridge_vlan * vinfo;
1135
1136 IS_BRIDGE_LINK_ASSERT(link);
1137
1138 vinfo = rtnl_link_bridge_get_port_vlan(link);
1139
1140 if (!vinfo)
1141 return -NLE_NOATTR;
1142
1143 if (start == 0 || start > end || end >= VLAN_VID_MASK)
1144 return -NLE_INVAL;
1145
1146 for (uint16_t i = start; i <= end; i++)
1147 {
1148 set_bit(i,vinfo->vlan_bitmap);
1149 if (untagged) {
1150 set_bit(i,vinfo->untagged_bitmap);
1151 } else {
1152 unset_bit(i,vinfo->untagged_bitmap);
1153 }
1154 }
1155 return 0;
1156}
1157
1158/**
1159 * Unset port vlan membership range
1160 * @arg link Link object of type bridge
1161 * @arg start Start of membership range.
1162 * @arg end End of membership range.
1163 *
1164 * This will unset the vlan membership range for a bridge port
1165 * for both tagged and untagged membership.
1166 * Supported range is 1-4094
1167 *
1168 * @return 0 on success or negative error code
1169 * @return -NLE_NOATTR if port vlan attribute not present
1170 * @return -NLE_OPNOTSUP Link is not a bridge
1171 * @return -NLE_INVAL range is not in supported range.
1172 */
1173int rtnl_link_bridge_unset_port_vlan_map_range (struct rtnl_link *link, uint16_t start, uint16_t end)
1174{
1175 struct rtnl_link_bridge_vlan * vinfo;
1176
1177 IS_BRIDGE_LINK_ASSERT(link);
1178
1179 vinfo = rtnl_link_bridge_get_port_vlan(link);
1180
1181 if (!vinfo)
1182 return -NLE_NOATTR;
1183
1184 if (start == 0 || start > end || end >= VLAN_VID_MASK)
1185 return -NLE_INVAL;
1186
1187 for (uint16_t i = start; i <= end; i++)
1188 {
1189 unset_bit(i,vinfo->vlan_bitmap);
1190 unset_bit(i,vinfo->untagged_bitmap);
1191 }
1192 return 0;
1193}
1194
1195/**
1196 * Set port primary vlan id
1197 * @arg link Link object of type bridge
1198 * @arg pvid PVID to set.
1199 * @arg untagged Set vlan id to be untagged.
1200 *
1201 * This will set the primary vlan id for a bridge port.
1202 * Supported range is 0-4094, Setting pvid to 0 will unset it.
1203 * You will most likely want to set/unset pvid in the vlan map.
1204 * @see rtnl_link_bridge_set_port_vlan_map_range()
1205 * @see rtnl_link_bridge_unset_port_vlan_map_range()
1206 *
1207 * @return 0 on success or negative error code
1208 * @return -NLE_NOATTR if port vlan attribute not present
1209 * @return -NLE_OPNOTSUP Link is not a bridge
1210 * @return -NLE_INVAL PVID is above supported range.
1211 */
1212int rtnl_link_bridge_set_port_vlan_pvid (struct rtnl_link *link, uint16_t pvid)
1213{
1214 struct rtnl_link_bridge_vlan * vinfo;
1215
1216 IS_BRIDGE_LINK_ASSERT(link);
1217
1218 vinfo = rtnl_link_bridge_get_port_vlan(link);
1219
1220 if (!vinfo)
1221 return -NLE_NOATTR;
1222
1223 if (pvid >= VLAN_VID_MASK)
1224 return -NLE_INVAL;
1225
1226 vinfo->pvid = pvid;
1227
1228 return 0;
1229}
1230
1231/** @} */
1232
1233int rtnl_link_bridge_pvid(struct rtnl_link *link)
1234{
1235 struct bridge_data *bd;
1236
1237 IS_BRIDGE_LINK_ASSERT(link);
1238
1239 bd = link->l_af_data[AF_BRIDGE];
1240 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
1241 return (int) bd->vlan_info.pvid;
1242
1243 return -EINVAL;
1244}
1245
1246int rtnl_link_bridge_has_vlan(struct rtnl_link *link)
1247{
1248 struct bridge_data *bd;
1249 int i;
1250
1251 IS_BRIDGE_LINK_ASSERT(link);
1252
1253 bd = link->l_af_data[AF_BRIDGE];
1254 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
1255 if (bd->vlan_info.pvid)
1256 return 1;
1257
1258 for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
1259 if (bd->vlan_info.vlan_bitmap[i] ||
1260 bd->vlan_info.untagged_bitmap[i])
1261 return 1;
1262 }
1263 }
1264 return 0;
1265}
1266
1267struct rtnl_link_bridge_vlan *rtnl_link_bridge_get_port_vlan(struct rtnl_link *link)
1268{
1269 struct bridge_data *data;
1270
1271 if (!rtnl_link_is_bridge(link))
1272 return NULL;
1273
1274 data = link->l_af_data[AF_BRIDGE];
1275 if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
1276 return &data->vlan_info;
1277
1278 return NULL;
1279}
1280
1281static struct rtnl_link_af_ops bridge_ops = {
1282 .ao_family = AF_BRIDGE,
1283 .ao_alloc = &bridge_alloc,
1284 .ao_clone = &bridge_clone,
1285 .ao_free = &bridge_free,
1286 .ao_parse_protinfo = &bridge_parse_protinfo,
1287 .ao_dump[NL_DUMP_DETAILS] = &bridge_dump_details,
1288 .ao_compare = &bridge_compare,
1289 .ao_parse_af_full = &bridge_parse_af_full,
1290 .ao_get_af = &bridge_get_af,
1291 .ao_fill_af = &bridge_fill_af,
1292 .ao_fill_pi = &bridge_fill_pi,
1293 .ao_fill_pi_flags = NLA_F_NESTED,
1294 .ao_override_rtm = &bridge_override_rtm,
1295 .ao_fill_af_no_nest = 1,
1296};
1297
1298static void _nl_init bridge_init(void)
1299{
1300 rtnl_link_af_register(&bridge_ops);
1301}
1302
1303static void _nl_exit bridge_exit(void)
1304{
1305 rtnl_link_af_unregister(&bridge_ops);
1306}
1307
1308/** @} */
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:712
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition attr.c:662
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition attr.h:212
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:194
int nla_type(const struct nlattr *nla)
Return type of the attribute.
Definition attr.c:108
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
Definition attr.c:1047
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:159
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:230
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:612
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:1035
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
Definition attr.h:324
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition attr.c:130
@ NLA_U8
8 bit integer
Definition attr.h:35
@ NLA_U16
16 bit integer
Definition attr.h:36
@ NLA_U32
32 bit integer
Definition attr.h:37
int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
Set Spanning Tree Protocol (STP) path cost.
Definition bridge.c:798
int rtnl_link_bridge_get_port_state(struct rtnl_link *link)
Get Spanning Tree Protocol (STP) port state.
Definition bridge.c:739
int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode)
Set hardware mode.
Definition bridge.c:1001
int rtnl_link_bridge_has_ext_info(struct rtnl_link *link)
Check if bridge has extended information.
Definition bridge.c:686
int rtnl_link_bridge_set_master(struct rtnl_link *link)
Set link change type to master.
Definition bridge.c:945
int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
Create a new kernel bridge device.
Definition bridge.c:644
int rtnl_link_bridge_set_port_vlan_map_range(struct rtnl_link *link, uint16_t start, uint16_t end, int untagged)
Set port vlan membership range.
Definition bridge.c:1132
int rtnl_link_is_bridge(struct rtnl_link *link)
Check if a link is a bridge.
Definition bridge.c:667
int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
Set Spanning Tree Protocol (STP) port state.
Definition bridge.c:715
int rtnl_link_bridge_enable_vlan(struct rtnl_link *link)
Enable the ability to set vlan info.
Definition bridge.c:1100
int rtnl_link_bridge_set_self(struct rtnl_link *link)
Set link change type to self.
Definition bridge.c:922
int rtnl_link_bridge_set_port_vlan_pvid(struct rtnl_link *link, uint16_t pvid)
Set port primary vlan id.
Definition bridge.c:1212
struct rtnl_link * rtnl_link_bridge_alloc(void)
Allocate link object of type bridge.
Definition bridge.c:618
int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode)
Get hardware mode.
Definition bridge.c:968
int rtnl_link_bridge_get_flags(struct rtnl_link *link)
Get flags.
Definition bridge.c:902
int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
Get Spanning Tree Protocol (STP) path cost.
Definition bridge.c:821
int rtnl_link_bridge_get_priority(struct rtnl_link *link)
Get priority.
Definition bridge.c:779
int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset flags.
Definition bridge.c:846
int rtnl_link_bridge_unset_port_vlan_map_range(struct rtnl_link *link, uint16_t start, uint16_t end)
Unset port vlan membership range.
Definition bridge.c:1173
int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
Set priority.
Definition bridge.c:758
int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
Set flags.
Definition bridge.c:879
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:65