14#include "nl-default.h"
16#include <linux/if_bridge.h>
17#include <linux/rtnetlink.h>
19#include <netlink/netlink.h>
20#include <netlink/attr.h>
21#include <netlink/route/rtnl.h>
22#include <netlink/route/link/bridge.h>
23#include <netlink/list.h>
27#include "nl-priv-dynamic-core/nl-core.h"
28#include "nl-priv-static-route/nl-priv-static-route.h"
30#define VLAN_VID_MASK 0x0fff
33#define BRIDGE_ATTR_PORT_STATE (1UL << 0)
34#define BRIDGE_ATTR_PRIORITY (1UL << 1)
35#define BRIDGE_ATTR_COST (1UL << 2)
36#define BRIDGE_ATTR_FLAGS (1UL << 3)
37#define BRIDGE_ATTR_PORT_VLAN (1UL << 4)
38#define BRIDGE_ATTR_HWMODE (1UL << 5)
39#define BRIDGE_ATTR_CONFIG_MODE (1UL << 6)
40#define BRIDGE_ATTR_MST (1UL << 7)
42#define PRIV_FLAG_NEW_ATTRS (1UL << 0)
50 uint16_t b_config_mode;
53 uint32_t b_flags_mask;
59struct mst_state_entry {
65static void set_bit(
unsigned nr, uint32_t *addr)
67 if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
68 addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
71static void unset_bit(
unsigned nr, uint32_t *addr)
73 if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
74 addr[nr / 32] &= ~(((uint32_t) 1) << (nr % 32));
81 _nl_assert(vid / 32u < ARRAY_SIZE(vlan_info->untagged_bitmap));
83 mask = vlan_info->untagged_bitmap[vid / 32];
84 bit = (((uint32_t) 1) << vid % 32);
89static int find_next_bit(
int i, uint32_t x)
98 return __builtin_ffs(x);
101 j = __builtin_ffs(x >> i);
102 return j ? j + i : 0;
107#define IS_BRIDGE_LINK_ASSERT(link) \
108 if (!rtnl_link_is_bridge(link)) { \
109 APPBUG("A function was expecting a link object of type bridge."); \
110 return -NLE_OPNOTSUPP; \
113static inline struct bridge_data *bridge_data(
struct rtnl_link *link)
118static void *bridge_alloc(
struct rtnl_link *link)
120 struct bridge_data *bridge_data = calloc(1,
sizeof(
struct bridge_data));
122 if (bridge_data == NULL)
125 nl_init_list_head(&bridge_data->mst_list);
130static struct mst_state_entry *mst_state_entry_alloc(
void)
132 struct mst_state_entry *entry;
134 entry = calloc(1,
sizeof(*entry));
138 nl_init_list_head(&entry->list_node);
143static struct mst_state_entry *mst_state_entry_create(uint16_t msti,
146 struct mst_state_entry *entry;
148 entry = mst_state_entry_alloc();
153 entry->state = state;
158static void mst_state_entry_del(
struct mst_state_entry *entry)
160 nl_list_del(&entry->list_node);
164static void mst_list_clear(
struct nl_list_head *mst_list)
166 struct mst_state_entry *entry;
167 struct mst_state_entry *entry_safe;
169 nl_list_for_each_entry_safe(entry, entry_safe, mst_list, list_node)
170 mst_state_entry_del(entry);
173static void bridge_data_free(
struct bridge_data *bd)
175 mst_list_clear(&bd->mst_list);
179static void bridge_free(
struct rtnl_link *link,
void *data)
181 bridge_data_free(data);
184static struct mst_state_entry *find_mst_state_entry(
struct bridge_data *bd,
187 struct mst_state_entry *entry;
189 nl_list_for_each_entry(entry, &bd->mst_list, list_node) {
190 if (entry->msti == msti)
197static struct mst_state_entry *
198mst_state_entry_clone(
struct mst_state_entry *src)
200 return mst_state_entry_create(src->msti, src->state);
203static void *bridge_clone(
struct rtnl_link *link,
void *data)
205 struct bridge_data *src_bd = (
struct bridge_data *)data;
206 struct bridge_data *dst_bd;
207 struct mst_state_entry *entry;
209 dst_bd = calloc(1,
sizeof(*dst_bd));
213 memcpy(dst_bd, src_bd,
sizeof(*dst_bd));
215 nl_init_list_head(&dst_bd->mst_list);
217 nl_list_for_each_entry(entry, &src_bd->mst_list, list_node) {
218 struct mst_state_entry *entry_copy =
219 mst_state_entry_clone(entry);
222 bridge_data_free(dst_bd);
226 nl_list_add_tail(&entry_copy->list_node, &dst_bd->mst_list);
266 struct bridge_data *bd = data;
267 struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
276 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
282 br_attrs_policy)) < 0)
285 bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;
287 if (br_attrs[IFLA_BRPORT_STATE]) {
288 bd->b_port_state =
nla_get_u8(br_attrs[IFLA_BRPORT_STATE]);
289 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
292 if (br_attrs[IFLA_BRPORT_PRIORITY]) {
293 bd->b_priority =
nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]);
294 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
297 if (br_attrs[IFLA_BRPORT_COST]) {
298 bd->b_cost =
nla_get_u32(br_attrs[IFLA_BRPORT_COST]);
299 bd->ce_mask |= BRIDGE_ATTR_COST;
302 check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE);
303 check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD);
304 check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK);
305 check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE);
306 check_flag(link, br_attrs, IFLA_BRPORT_UNICAST_FLOOD,
307 RTNL_BRIDGE_UNICAST_FLOOD);
308 check_flag(link, br_attrs, IFLA_BRPORT_LEARNING, RTNL_BRIDGE_LEARNING);
309 check_flag(link, br_attrs, IFLA_BRPORT_LEARNING_SYNC,
310 RTNL_BRIDGE_LEARNING_SYNC);
311 check_flag(link, br_attrs, IFLA_BRPORT_PROXYARP, RTNL_BRIDGE_PROXYARP);
312 check_flag(link, br_attrs, IFLA_BRPORT_PROXYARP_WIFI,
313 RTNL_BRIDGE_PROXYARP_WIFI);
314 check_flag(link, br_attrs, IFLA_BRPORT_MCAST_FLOOD,
315 RTNL_BRIDGE_MCAST_FLOOD);
316 check_flag(link, br_attrs, IFLA_BRPORT_MCAST_TO_UCAST,
317 RTNL_BRIDGE_MCAST_TO_UCAST);
318 check_flag(link, br_attrs, IFLA_BRPORT_VLAN_TUNNEL,
319 RTNL_BRIDGE_VLAN_TUNNEL);
320 check_flag(link, br_attrs, IFLA_BRPORT_BCAST_FLOOD,
321 RTNL_BRIDGE_BCAST_FLOOD);
322 check_flag(link, br_attrs, IFLA_BRPORT_NEIGH_SUPPRESS,
323 RTNL_BRIDGE_NEIGH_SUPPRESS);
324 check_flag(link, br_attrs, IFLA_BRPORT_ISOLATED, RTNL_BRIDGE_ISOLATED);
325 check_flag(link, br_attrs, IFLA_BRPORT_LOCKED, RTNL_BRIDGE_LOCKED);
326 check_flag(link, br_attrs, IFLA_BRPORT_MAB, RTNL_BRIDGE_MAB);
327 check_flag(link, br_attrs, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
328 RTNL_BRIDGE_NEIGH_VLAN_SUPPRESS);
341 struct nlattr *tb[IFLA_BRIDGE_MST_ENTRY_MAX + 1];
342 struct mst_state_entry *new_entry;
343 struct mst_state_entry *existing_entry;
348 br_mst_entry_policy) < 0)
351 if (!tb[IFLA_BRIDGE_MST_ENTRY_MSTI] ||
352 !tb[IFLA_BRIDGE_MST_ENTRY_STATE]) {
356 msti =
nla_get_u16(tb[IFLA_BRIDGE_MST_ENTRY_MSTI]);
357 state =
nla_get_u8(tb[IFLA_BRIDGE_MST_ENTRY_STATE]);
359 existing_entry = find_mst_state_entry(bd, msti);
360 if (existing_entry) {
361 existing_entry->state = state;
365 new_entry = mst_state_entry_create(msti, state);
369 nl_list_add_tail(&new_entry->list_node, &bd->mst_list);
370 bd->ce_mask |= BRIDGE_ATTR_MST;
375static int bridge_parse_mst(
struct nlattr *mst_attr,
struct bridge_data *bd) {
383 case IFLA_BRIDGE_MST_ENTRY:
384 err = bridge_parse_mst_state_entry(attr, bd);
397static int bridge_parse_af_full(
struct rtnl_link *link,
struct nlattr *attr_full,
400 struct bridge_data *bd = data;
401 struct bridge_vlan_info *vinfo = NULL;
402 uint16_t vid_range_start = 0;
403 uint16_t vid_range_flags = -1;
410 if (
nla_type(attr) == IFLA_BRIDGE_MODE) {
412 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
414 }
else if (
nla_type(attr) == IFLA_BRIDGE_MST) {
415 int err = bridge_parse_mst(attr, bd);
419 }
else if (
nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
422 if (
nla_len(attr) !=
sizeof(
struct bridge_vlan_info))
426 if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
430 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
431 vid_range_start = vinfo->vid;
432 vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
436 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
438 if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
439 NL_DBG(1,
"VLAN range flags differ; can not handle it.\n");
443 vid_range_start = vinfo->vid;
446 for (; vid_range_start <= vinfo->vid; vid_range_start++) {
447 if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
448 bd->vlan_info.pvid = vinfo->vid;
450 if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
451 set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
453 set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
454 bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
457 vid_range_flags = -1;
465 struct bridge_vlan_info vinfo;
467 int start = -1, prev = -1;
469 bool untagged =
false;
471 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++)
474 uint32_t a = vlan_info->vlan_bitmap[k];
481 j = find_next_bit(i, a);
485 if (vlan_info->pvid != 0 && j - 1 + base_bit == vlan_info->pvid)
488 if (start < 0 && prev < 0)
490 start = prev = j - 1 + base_bit;
492 untagged = vlan_id_untagged(vlan_info,start);
493 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN;
494 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
499 if (j - 2 + base_bit == prev)
503 if (untagged != vlan_id_untagged(vlan_info,prev))
509 vinfo.flags &= ~BRIDGE_VLAN_INFO_RANGE_BEGIN;
510 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo),&vinfo);
515 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo),&vinfo);
517 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END;
518 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
520 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo),&vinfo);
523 untagged = !untagged;
524 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN;
525 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
536 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
539 if (vinfo.flags & BRIDGE_VLAN_INFO_RANGE_BEGIN && start != prev)
541 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo),&vinfo);
543 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_END;
544 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
546 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo),&vinfo);
548 else if (start == prev)
550 vinfo.flags = untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
552 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo),&vinfo);
560 start = prev = j - 1 + base_bit;
561 untagged = vlan_id_untagged(vlan_info,start);
562 vinfo.flags = BRIDGE_VLAN_INFO_RANGE_BEGIN;
563 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
571 if (vlan_info->pvid != 0)
573 untagged = vlan_id_untagged(vlan_info,vlan_info->pvid);
574 vinfo.flags = BRIDGE_VLAN_INFO_PVID;
575 vinfo.flags |= untagged ? BRIDGE_VLAN_INFO_UNTAGGED : 0;
576 vinfo.vid = vlan_info->pvid;
577 NLA_PUT(msg,IFLA_BRIDGE_VLAN_INFO,
sizeof(vinfo),&vinfo);
586static int bridge_fill_mst(
struct nl_msg *msg,
struct nl_list_head *mst_list) {
587 struct nlattr *attr = NULL;
588 struct nlattr *entry_attr = NULL;
589 struct mst_state_entry *entry;
591 if (nl_list_empty(mst_list))
598 nl_list_for_each_entry(entry, mst_list, list_node) {
601 goto err_out_nest_cancel_attr;
603 NLA_PUT_U16(msg, IFLA_BRIDGE_MST_ENTRY_MSTI, entry->msti);
604 NLA_PUT_U8(msg, IFLA_BRIDGE_MST_ENTRY_STATE, entry->state);
615err_out_nest_cancel_attr:
621static int bridge_fill_af(
struct rtnl_link *link,
struct nl_msg *msg,
624 struct bridge_data *bd = data;
626 if (bd->ce_mask & BRIDGE_ATTR_HWMODE)
629 bd->b_config_mode = BRIDGE_FLAGS_SELF;
630 bd->ce_mask |= BRIDGE_ATTR_CONFIG_MODE;
633 if (bd->ce_mask & BRIDGE_ATTR_MST)
635 if (bridge_fill_mst(msg, &bd->mst_list) < 0) {
636 goto nla_put_failure;
640 if (bd->ce_mask & BRIDGE_ATTR_CONFIG_MODE)
641 NLA_PUT_U16(msg, IFLA_BRIDGE_FLAGS, bd->b_config_mode);
643 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
644 if (_nl_bridge_fill_vlan_info(msg, &bd->vlan_info)) {
645 goto nla_put_failure;
655static int bridge_fill_pi(
struct rtnl_link *link,
struct nl_msg *msg,
658 struct bridge_data *bd = data;
660 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
661 if (bd->b_flags_mask & RTNL_BRIDGE_BPDU_GUARD) {
663 !!(bd->b_flags & RTNL_BRIDGE_BPDU_GUARD));
665 if (bd->b_flags_mask & RTNL_BRIDGE_HAIRPIN_MODE) {
667 !!(bd->b_flags & RTNL_BRIDGE_HAIRPIN_MODE));
669 if (bd->b_flags_mask & RTNL_BRIDGE_FAST_LEAVE) {
671 !!(bd->b_flags & RTNL_BRIDGE_FAST_LEAVE));
673 if (bd->b_flags_mask & RTNL_BRIDGE_ROOT_BLOCK) {
675 !!(bd->b_flags & RTNL_BRIDGE_ROOT_BLOCK));
677 if (bd->b_flags_mask & RTNL_BRIDGE_UNICAST_FLOOD) {
679 !!(bd->b_flags & RTNL_BRIDGE_UNICAST_FLOOD));
681 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING) {
683 !!(bd->b_flags & RTNL_BRIDGE_LEARNING));
685 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING_SYNC) {
687 !!(bd->b_flags & RTNL_BRIDGE_LEARNING_SYNC));
689 if (bd->b_flags_mask & RTNL_BRIDGE_PROXYARP) {
691 !!(bd->b_flags & RTNL_BRIDGE_PROXYARP));
693 if (bd->b_flags_mask & RTNL_BRIDGE_PROXYARP_WIFI) {
695 !!(bd->b_flags & RTNL_BRIDGE_PROXYARP_WIFI));
697 if (bd->b_flags_mask & RTNL_BRIDGE_MCAST_FLOOD) {
699 !!(bd->b_flags & RTNL_BRIDGE_MCAST_FLOOD));
701 if (bd->b_flags_mask & RTNL_BRIDGE_MCAST_TO_UCAST) {
704 RTNL_BRIDGE_MCAST_TO_UCAST));
706 if (bd->b_flags_mask & RTNL_BRIDGE_VLAN_TUNNEL) {
708 !!(bd->b_flags & RTNL_BRIDGE_VLAN_TUNNEL));
710 if (bd->b_flags_mask & RTNL_BRIDGE_BCAST_FLOOD) {
712 !!(bd->b_flags & RTNL_BRIDGE_BCAST_FLOOD));
714 if (bd->b_flags_mask & RTNL_BRIDGE_NEIGH_SUPPRESS) {
717 RTNL_BRIDGE_NEIGH_SUPPRESS));
719 if (bd->b_flags_mask & RTNL_BRIDGE_ISOLATED) {
721 !!(bd->b_flags & RTNL_BRIDGE_ISOLATED));
723 if (bd->b_flags_mask & RTNL_BRIDGE_LOCKED) {
725 !!(bd->b_flags & RTNL_BRIDGE_LOCKED));
727 if (bd->b_flags_mask & RTNL_BRIDGE_MAB) {
729 !!(bd->b_flags & RTNL_BRIDGE_MAB));
731 if (bd->b_flags_mask & RTNL_BRIDGE_NEIGH_VLAN_SUPPRESS) {
732 NLA_PUT_U8(msg, IFLA_BRPORT_NEIGH_VLAN_SUPPRESS,
734 RTNL_BRIDGE_NEIGH_VLAN_SUPPRESS));
738 if (bd->ce_mask & BRIDGE_ATTR_COST)
741 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
742 NLA_PUT_U16(msg, IFLA_BRPORT_PRIORITY, bd->b_priority);
744 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
745 NLA_PUT_U8(msg, IFLA_BRPORT_STATE, bd->b_port_state);
753static int bridge_override_rtm(
struct rtnl_link *link) {
754 struct bridge_data *bd;
759 bd = bridge_data(link);
761 if (bd->ce_mask & (BRIDGE_ATTR_FLAGS | BRIDGE_ATTR_MST))
767static int bridge_get_af(
struct nl_msg *msg, uint32_t *ext_filter_mask)
769 *ext_filter_mask |= RTEXT_FILTER_BRVLAN | RTEXT_FILTER_MST;
773static void dump_bitmap(
struct nl_dump_params *p,
const uint32_t *b)
776 int start = -1, prev = -1;
779 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
787 j = find_next_bit(i, a);
790 if (start < 0 && prev < 0) {
791 start = prev = j - 1 + base_bit;
795 if (j - 2 + base_bit == prev) {
804 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
815 start = prev = j - 1 + base_bit;
827 struct bridge_data *bd)
829 nl_dump(p,
"pvid %u", bd->vlan_info.pvid);
832 dump_bitmap(p, bd->vlan_info.vlan_bitmap);
834 nl_dump(p,
" untagged vlans:");
835 dump_bitmap(p, bd->vlan_info.untagged_bitmap);
838static const char *
const br_port_state_names[] = {
839 [BR_STATE_DISABLED] =
"disabled",
840 [BR_STATE_LISTENING] =
"listening",
841 [BR_STATE_LEARNING] =
"learning",
842 [BR_STATE_FORWARDING] =
"forwarding",
843 [BR_STATE_BLOCKING] =
"blocking",
846static const char *stp_state2str(uint8_t state) {
847 if (state > BR_STATE_BLOCKING)
850 return br_port_state_names[state];
853static void bridge_dump_details(
struct rtnl_link *link,
856 struct bridge_data *bd = data;
858 nl_dump_line(p,
" bridge: ");
860 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
861 nl_dump(p,
"port-state %u ", bd->b_port_state);
863 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
864 nl_dump(p,
"prio %u ", bd->b_priority);
866 if (bd->ce_mask & BRIDGE_ATTR_COST)
867 nl_dump(p,
"cost %u ", bd->b_cost);
869 if (bd->ce_mask & BRIDGE_ATTR_HWMODE) {
872 rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf,
sizeof(hbuf));
876 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
877 rtnl_link_bridge_dump_vlans(p, bd);
879 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
882 rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
889 if (bd->ce_mask & BRIDGE_ATTR_MST && !nl_list_empty(&bd->mst_list)) {
890 struct mst_state_entry *entry;
892 nl_dump_line(p,
" mst:\n");
894 nl_list_for_each_entry(entry, &bd->mst_list, list_node) {
895 nl_dump_line(p,
" instance %u: %s\n",
896 entry->msti, stp_state2str(entry->state));
901static bool mst_state_entries_are_equal(
const struct mst_state_entry *a,
902 const struct mst_state_entry *b)
904 return a->msti == b->msti && a->state == b->state;
918static bool msts_lists_are_equal(
struct nl_list_head *list_1,
921 struct mst_state_entry *entry_a;
922 struct mst_state_entry *entry_b;
925 nl_list_entry(list_1->next,
struct mst_state_entry, list_node);
927 nl_list_entry(list_2->next,
struct mst_state_entry, list_node);
930 while (&entry_a->list_node != list_1 && &entry_b->list_node != list_2) {
931 if (!mst_state_entries_are_equal(entry_a, entry_b)) {
935 entry_a = nl_list_entry(entry_a->list_node.next,
936 struct mst_state_entry, list_node);
937 entry_b = nl_list_entry(entry_b->list_node.next,
938 struct mst_state_entry, list_node);
942 return &entry_a->list_node == list_1 && &entry_b->list_node == list_2;
946 int family, uint32_t attrs,
int flags)
948 struct bridge_data *a = bridge_data(_a);
949 struct bridge_data *b = bridge_data(_b);
952#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
953 diff |= _DIFF(BRIDGE_ATTR_PORT_STATE,
954 a->b_port_state != b->b_port_state);
955 diff |= _DIFF(BRIDGE_ATTR_PRIORITY, a->b_priority != b->b_priority);
956 diff |= _DIFF(BRIDGE_ATTR_COST, a->b_cost != b->b_cost);
957 diff |= _DIFF(BRIDGE_ATTR_PORT_VLAN,
958 memcmp(&a->vlan_info, &b->vlan_info,
960 diff |= _DIFF(BRIDGE_ATTR_HWMODE, a->b_hwmode != b->b_hwmode);
961 diff |= _DIFF(BRIDGE_ATTR_CONFIG_MODE, a->b_config_mode != b->b_config_mode);
962 diff |= _DIFF(BRIDGE_ATTR_MST,
963 !msts_lists_are_equal(&a->mst_list, &b->mst_list));
965 if (flags & LOOSE_COMPARISON)
966 diff |= _DIFF(BRIDGE_ATTR_FLAGS,
967 (a->b_flags ^ b->b_flags) & b->b_flags_mask);
969 diff |= _DIFF(BRIDGE_ATTR_FLAGS, a->b_flags != b->b_flags);
1032 return link->l_family == AF_BRIDGE &&
1033 link->l_af_ops == &bridge_ops;
1051 struct bridge_data *bd;
1056 bd = bridge_data(link);
1057 return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
1080 struct bridge_data *bd = bridge_data(link);
1082 IS_BRIDGE_LINK_ASSERT(link);
1084 if (state > BR_STATE_BLOCKING)
1087 bd->b_port_state = state;
1088 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
1104 struct bridge_data *bd = bridge_data(link);
1106 IS_BRIDGE_LINK_ASSERT(link);
1108 return bd->b_port_state;
1123 struct bridge_data *bd = bridge_data(link);
1125 IS_BRIDGE_LINK_ASSERT(link);
1127 bd->b_priority = prio;
1128 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
1144 struct bridge_data *bd = bridge_data(link);
1146 IS_BRIDGE_LINK_ASSERT(link);
1148 return bd->b_priority;
1163 struct bridge_data *bd = bridge_data(link);
1165 IS_BRIDGE_LINK_ASSERT(link);
1168 bd->ce_mask |= BRIDGE_ATTR_COST;
1186 struct bridge_data *bd = bridge_data(link);
1188 IS_BRIDGE_LINK_ASSERT(link);
1211 struct bridge_data *bd = bridge_data(link);
1213 IS_BRIDGE_LINK_ASSERT(link);
1215 bd->b_flags_mask |= flags;
1216 bd->b_flags &= ~flags;
1217 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
1255 struct bridge_data *bd = bridge_data(link);
1257 IS_BRIDGE_LINK_ASSERT(link);
1259 bd->b_flags_mask |= flags;
1260 bd->b_flags |= flags;
1261 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
1278 struct bridge_data *bd = bridge_data(link);
1280 IS_BRIDGE_LINK_ASSERT(link);
1298 struct bridge_data *bd = bridge_data(link);
1300 IS_BRIDGE_LINK_ASSERT(link);
1302 bd->b_config_mode = BRIDGE_FLAGS_SELF;
1303 bd->ce_mask |= BRIDGE_ATTR_CONFIG_MODE;
1321 struct bridge_data *bd = bridge_data(link);
1323 IS_BRIDGE_LINK_ASSERT(link);
1325 bd->b_config_mode = BRIDGE_FLAGS_MASTER;
1326 bd->ce_mask |= BRIDGE_ATTR_CONFIG_MODE;
1344 struct bridge_data *bd = bridge_data(link);
1346 IS_BRIDGE_LINK_ASSERT(link);
1348 if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE))
1351 *hwmode = bd->b_hwmode;
1378 struct bridge_data *bd = bridge_data(link);
1380 if (hwmode > RTNL_BRIDGE_HWMODE_MAX)
1386 bd->b_hwmode = hwmode;
1387 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
1393static const struct trans_tbl bridge_flags[] = {
1394 __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
1395 __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
1396 __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
1397 __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
1398 __ADD(RTNL_BRIDGE_UNICAST_FLOOD, flood),
1399 __ADD(RTNL_BRIDGE_LEARNING, learning),
1400 __ADD(RTNL_BRIDGE_LEARNING_SYNC, learning_sync),
1401 __ADD(RTNL_BRIDGE_PROXYARP, proxy_arp),
1402 __ADD(RTNL_BRIDGE_PROXYARP_WIFI, proxy_arp_wifi),
1403 __ADD(RTNL_BRIDGE_MCAST_FLOOD, mcast_flood),
1404 __ADD(RTNL_BRIDGE_MCAST_TO_UCAST, mcast_to_unicast),
1405 __ADD(RTNL_BRIDGE_VLAN_TUNNEL, vlan_tunnel),
1406 __ADD(RTNL_BRIDGE_BCAST_FLOOD, bcast_flood),
1407 __ADD(RTNL_BRIDGE_NEIGH_SUPPRESS, neigh_suppress),
1408 __ADD(RTNL_BRIDGE_ISOLATED, isolated),
1409 __ADD(RTNL_BRIDGE_LOCKED, locked),
1410 __ADD(RTNL_BRIDGE_MAB, mab),
1411 __ADD(RTNL_BRIDGE_NEIGH_VLAN_SUPPRESS, neigh_vlan_suppress),
1419char *rtnl_link_bridge_flags2str(
int flags,
char *buf,
size_t len)
1421 return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
1424int rtnl_link_bridge_str2flags(
const char *name)
1426 return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
1431static const struct trans_tbl port_states[] = {
1432 __ADD(BR_STATE_DISABLED, disabled),
1433 __ADD(BR_STATE_LISTENING, listening),
1434 __ADD(BR_STATE_LEARNING, learning),
1435 __ADD(BR_STATE_FORWARDING, forwarding),
1436 __ADD(BR_STATE_BLOCKING, blocking),
1444char *rtnl_link_bridge_portstate2str(
int st,
char *buf,
size_t len)
1446 return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states));
1449int rtnl_link_bridge_str2portstate(
const char *name)
1451 return __str2type(name, port_states, ARRAY_SIZE(port_states));
1456static const struct trans_tbl hw_modes[] = {
1457 __ADD(RTNL_BRIDGE_HWMODE_VEB, veb),
1458 __ADD(RTNL_BRIDGE_HWMODE_VEPA, vepa),
1459 __ADD(RTNL_BRIDGE_HWMODE_UNDEF, undef),
1467char *rtnl_link_bridge_hwmode2str(uint16_t st,
char *buf,
size_t len) {
1468 return __type2str(st, buf, len, hw_modes, ARRAY_SIZE(hw_modes));
1471uint16_t rtnl_link_bridge_str2hwmode(
const char *name)
1473 return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes));
1487 struct bridge_data *bd = bridge_data(link);
1489 IS_BRIDGE_LINK_ASSERT(link);
1491 bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
1521 IS_BRIDGE_LINK_ASSERT(link);
1523 vinfo = rtnl_link_bridge_get_port_vlan(link);
1528 if (start == 0 || start > end || end >= VLAN_VID_MASK)
1531 for (uint16_t i = start; i <= end; i++)
1533 set_bit(i,vinfo->vlan_bitmap);
1535 set_bit(i,vinfo->untagged_bitmap);
1537 unset_bit(i,vinfo->untagged_bitmap);
1562 IS_BRIDGE_LINK_ASSERT(link);
1564 vinfo = rtnl_link_bridge_get_port_vlan(link);
1569 if (start == 0 || start > end || end >= VLAN_VID_MASK)
1572 for (uint16_t i = start; i <= end; i++)
1574 unset_bit(i,vinfo->vlan_bitmap);
1575 unset_bit(i,vinfo->untagged_bitmap);
1601 IS_BRIDGE_LINK_ASSERT(link);
1603 vinfo = rtnl_link_bridge_get_port_vlan(link);
1608 if (pvid >= VLAN_VID_MASK)
1618int rtnl_link_bridge_pvid(
struct rtnl_link *link)
1620 struct bridge_data *bd;
1622 IS_BRIDGE_LINK_ASSERT(link);
1624 bd = link->l_af_data[AF_BRIDGE];
1625 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
1626 return (
int) bd->vlan_info.pvid;
1631int rtnl_link_bridge_has_vlan(
struct rtnl_link *link)
1633 struct bridge_data *bd;
1636 IS_BRIDGE_LINK_ASSERT(link);
1638 bd = link->l_af_data[AF_BRIDGE];
1639 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
1640 if (bd->vlan_info.pvid)
1643 for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
1644 if (bd->vlan_info.vlan_bitmap[i] ||
1645 bd->vlan_info.untagged_bitmap[i])
1654 struct bridge_data *data;
1659 data = link->l_af_data[AF_BRIDGE];
1660 if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
1661 return &data->vlan_info;
1678 uint16_t instance, uint8_t state)
1680 struct bridge_data *bd;
1681 struct mst_state_entry *existing_entry;
1682 struct mst_state_entry *new_entry;
1687 IS_BRIDGE_LINK_ASSERT(link);
1689 bd = bridge_data(link);
1691 return -NLE_OPNOTSUPP;
1693 existing_entry = find_mst_state_entry(bd, instance);
1695 if (existing_entry != NULL) {
1696 existing_entry->state = state;
1700 new_entry = mst_state_entry_create(instance, state);
1701 if (new_entry == NULL)
1704 nl_list_add_tail(&new_entry->list_node, &bd->mst_list);
1705 bd->ce_mask |= BRIDGE_ATTR_MST;
1723 struct bridge_data *bd;
1724 struct mst_state_entry *entry;
1729 IS_BRIDGE_LINK_ASSERT(link);
1731 bd = bridge_data(link);
1733 return -NLE_OPNOTSUPP;
1735 entry = find_mst_state_entry(bd, instance);
1738 return -NLE_OBJ_NOTFOUND;
1740 return entry->state;
1756 struct bridge_data *bd;
1757 struct mst_state_entry *entry;
1762 IS_BRIDGE_LINK_ASSERT(link);
1764 bd = bridge_data(link);
1766 return -NLE_OPNOTSUPP;
1768 entry = find_mst_state_entry(bd, instance);
1771 return -NLE_OBJ_NOTFOUND;
1773 mst_state_entry_del(entry);
1775 if (nl_list_empty(&bd->mst_list))
1776 bd->ce_mask &= ~BRIDGE_ATTR_MST;
1791 struct bridge_data *bd;
1796 IS_BRIDGE_LINK_ASSERT(link);
1798 bd = bridge_data(link);
1800 return -NLE_OPNOTSUPP;
1802 mst_list_clear(&bd->mst_list);
1803 bd->ce_mask &= ~BRIDGE_ATTR_MST;
1825 void (*cb)(uint16_t instance, uint8_t state,
void *arg),
void *arg)
1827 struct bridge_data *bd;
1828 struct mst_state_entry *entry;
1830 if (link == NULL || cb == NULL)
1833 IS_BRIDGE_LINK_ASSERT(link);
1835 bd = bridge_data(link);
1837 return -NLE_OPNOTSUPP;
1839 nl_list_for_each_entry(entry, &bd->mst_list, list_node) {
1840 cb(entry->msti, entry->state, arg);
1848 .ao_alloc = &bridge_alloc,
1849 .ao_clone = &bridge_clone,
1850 .ao_free = &bridge_free,
1851 .ao_parse_protinfo = &bridge_parse_protinfo,
1853 .ao_compare = &bridge_compare,
1854 .ao_parse_af_full = &bridge_parse_af_full,
1855 .ao_get_af = &bridge_get_af,
1856 .ao_fill_af = &bridge_fill_af,
1857 .ao_fill_pi = &bridge_fill_pi,
1858 .ao_fill_pi_flags = NLA_F_NESTED,
1859 .ao_override_rtm = &bridge_override_rtm,
1860 .ao_fill_af_no_nest = 1,
1863static void _nl_init bridge_init(
void)
1868static void _nl_exit bridge_exit(
void)
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
int nla_type(const struct nlattr *nla)
Return type of the attribute.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
void nla_nest_cancel(struct nl_msg *msg, const struct nlattr *attr)
Cancel the addition of a nested attribute.
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
int nla_len(const struct nlattr *nla)
Return length of the payload .
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int rtnl_link_bridge_set_mst_port_state(struct rtnl_link *link, uint16_t instance, uint8_t state)
Set the Multiple Spanning Tree (MST) port state for a given MST instance.
int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
Set Spanning Tree Protocol (STP) path cost.
int rtnl_link_bridge_get_port_state(struct rtnl_link *link)
Get Spanning Tree Protocol (STP) port state.
int rtnl_link_bridge_get_mst_port_state(struct rtnl_link *link, uint16_t instance)
Get the Multiple Spanning Tree (MST) port state for a given MST instance.
int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode)
Set hardware mode.
int rtnl_link_bridge_has_ext_info(struct rtnl_link *link)
Check if bridge has extended information.
int rtnl_link_bridge_set_master(struct rtnl_link *link)
Set link change type to master.
int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
Create a new kernel bridge device.
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.
int rtnl_link_is_bridge(struct rtnl_link *link)
Check if a link is a bridge.
int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
Set Spanning Tree Protocol (STP) port state.
int rtnl_link_bridge_foreach_mst_entry(struct rtnl_link *link, void(*cb)(uint16_t instance, uint8_t state, void *arg), void *arg)
Iterate over all Multiple Spanning Tree (MST) port state entries.
int rtnl_link_bridge_enable_vlan(struct rtnl_link *link)
Enable the ability to set vlan info.
int rtnl_link_bridge_del_mst_port_state(struct rtnl_link *link, uint16_t instance)
Delete the Multiple Spanning Tree (MST) port state for a given MST instance.
int rtnl_link_bridge_set_self(struct rtnl_link *link)
Set link change type to self.
int rtnl_link_bridge_set_port_vlan_pvid(struct rtnl_link *link, uint16_t pvid)
Set port primary vlan id.
struct rtnl_link * rtnl_link_bridge_alloc(void)
Allocate link object of type bridge.
int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode)
Get hardware mode.
int rtnl_link_bridge_clear_mst_port_state_info(struct rtnl_link *link)
Delete all Multiple Spanning Tree (MST) port state information.
int rtnl_link_bridge_get_flags(struct rtnl_link *link)
Get flags.
int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
Get Spanning Tree Protocol (STP) path cost.
int rtnl_link_bridge_get_priority(struct rtnl_link *link)
Get priority.
int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset flags.
int rtnl_link_bridge_unset_port_vlan_map_range(struct rtnl_link *link, uint16_t start, uint16_t end)
Unset port vlan membership range.
int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
Set priority.
int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
Set flags.
int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
Unregister operations for a link address family.
int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
Register operations for a link address family.
void * rtnl_link_af_data(const struct rtnl_link *link, const struct rtnl_link_af_ops *ops)
Return data buffer for link address family modules.
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
void rtnl_link_put(struct rtnl_link *link)
Release a link object reference.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t type
Type of attribute or NLA_UNSPEC.
Available operations to modules implementing a link address family.
const unsigned int ao_family
The address family this operations set implements.