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> 28 #define VLAN_VID_MASK 0x0fff 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) 39 #define PRIV_FLAG_NEW_ATTRS (1 << 0) 50 uint32_t b_flags_mask;
55 static void set_bit(
unsigned nr, uint32_t *addr)
57 if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
58 addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
61 static int find_next_bit(
int i, uint32_t x)
70 return __builtin_ffs(x);
73 j = __builtin_ffs(x >> i);
77 static struct rtnl_link_af_ops bridge_ops;
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; \ 85 static inline struct bridge_data *bridge_data(
struct rtnl_link *link)
90 static void *bridge_alloc(
struct rtnl_link *link)
92 return calloc(1,
sizeof(
struct bridge_data));
95 static void *bridge_clone(
struct rtnl_link *link,
void *data)
97 struct bridge_data *bd;
99 if ((bd = bridge_alloc(link)))
100 memcpy(bd, data,
sizeof(*bd));
105 static void bridge_free(
struct rtnl_link *link,
void *data)
110 static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = {
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 },
123 static void check_flag(
struct rtnl_link *link,
struct nlattr *attrs[],
130 static int bridge_parse_protinfo(
struct rtnl_link *link,
struct nlattr *attr,
133 struct bridge_data *bd = data;
134 struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
143 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
149 br_attrs_policy)) < 0)
152 bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;
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;
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;
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;
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);
182 static int bridge_parse_af_full(
struct rtnl_link *link,
struct nlattr *attr_full,
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;
195 if (
nla_type(attr) == IFLA_BRIDGE_MODE) {
197 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
198 }
else if (
nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
201 if (
nla_len(attr) !=
sizeof(
struct bridge_vlan_info))
205 if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
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);
215 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
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");
222 vid_range_start = vinfo->vid;
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;
229 if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
230 set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
232 set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
233 bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
236 vid_range_flags = -1;
242 static int bridge_fill_af(
struct rtnl_link *link,
struct nl_msg *msg,
245 struct bridge_data *bd = data;
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);
250 if (bd->ce_mask & BRIDGE_ATTR_HWMODE)
259 static int bridge_fill_pi(
struct rtnl_link *link,
struct nl_msg *msg,
262 struct bridge_data *bd = data;
264 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
265 if (bd->b_flags_mask & RTNL_BRIDGE_BPDU_GUARD) {
267 bd->b_flags & RTNL_BRIDGE_BPDU_GUARD);
269 if (bd->b_flags_mask & RTNL_BRIDGE_HAIRPIN_MODE) {
271 bd->b_flags & RTNL_BRIDGE_HAIRPIN_MODE);
273 if (bd->b_flags_mask & RTNL_BRIDGE_FAST_LEAVE) {
275 bd->b_flags & RTNL_BRIDGE_FAST_LEAVE);
277 if (bd->b_flags_mask & RTNL_BRIDGE_ROOT_BLOCK) {
279 bd->b_flags & RTNL_BRIDGE_ROOT_BLOCK);
281 if (bd->b_flags_mask & RTNL_BRIDGE_UNICAST_FLOOD) {
283 bd->b_flags & RTNL_BRIDGE_UNICAST_FLOOD);
285 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING) {
287 bd->b_flags & RTNL_BRIDGE_LEARNING);
289 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING_SYNC) {
291 bd->b_flags & RTNL_BRIDGE_LEARNING_SYNC);
295 if (bd->ce_mask & BRIDGE_ATTR_COST)
298 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
299 NLA_PUT_U16(msg, IFLA_BRPORT_PRIORITY, bd->b_priority);
301 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
302 NLA_PUT_U8(msg, IFLA_BRPORT_STATE, bd->b_port_state);
310 static int bridge_get_af(
struct nl_msg *msg, uint32_t *ext_filter_mask)
312 *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
316 static void dump_bitmap(
struct nl_dump_params *p,
const uint32_t *b)
319 int start = -1, prev = -1;
322 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
330 j = find_next_bit(i, a);
333 if (start < 0 && prev < 0) {
334 start = prev = j - 1 + base_bit;
338 if (j - 2 + base_bit == prev) {
347 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
358 start = prev = j - 1 + base_bit;
370 struct bridge_data *bd)
372 nl_dump(p,
"pvid %u", bd->vlan_info.pvid);
375 dump_bitmap(p, bd->vlan_info.vlan_bitmap);
377 nl_dump(p,
" untagged vlans:");
378 dump_bitmap(p, bd->vlan_info.untagged_bitmap);
381 static void bridge_dump_details(
struct rtnl_link *link,
384 struct bridge_data *bd = data;
386 nl_dump_line(p,
" bridge: ");
388 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
389 nl_dump(p,
"port-state %u ", bd->b_port_state);
391 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
392 nl_dump(p,
"prio %u ", bd->b_priority);
394 if (bd->ce_mask & BRIDGE_ATTR_COST)
395 nl_dump(p,
"cost %u ", bd->b_cost);
397 if (bd->ce_mask & BRIDGE_ATTR_HWMODE) {
400 rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf,
sizeof(hbuf));
404 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
405 rtnl_link_bridge_dump_vlans(p, bd);
407 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
410 rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
419 int family, uint32_t attrs,
int flags)
421 struct bridge_data *a = bridge_data(_a);
422 struct bridge_data *b = bridge_data(_b);
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,
431 diff |= BRIDGE_DIFF(HWMODE, a->b_hwmode != b->b_hwmode);
432 diff |= BRIDGE_DIFF(SELF, a->b_self != b->b_self);
434 if (flags & LOOSE_COMPARISON)
435 diff |= BRIDGE_DIFF(FLAGS,
436 (a->b_flags ^ b->b_flags) & b->b_flags_mask);
438 diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
502 return link->l_family == AF_BRIDGE &&
503 link->l_af_ops == &bridge_ops;
521 struct bridge_data *bd;
526 bd = bridge_data(link);
527 return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
550 struct bridge_data *bd = bridge_data(link);
552 IS_BRIDGE_LINK_ASSERT(link);
554 if (state > BR_STATE_BLOCKING)
557 bd->b_port_state = state;
558 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
574 struct bridge_data *bd = bridge_data(link);
576 IS_BRIDGE_LINK_ASSERT(link);
578 return bd->b_port_state;
593 struct bridge_data *bd = bridge_data(link);
595 IS_BRIDGE_LINK_ASSERT(link);
597 bd->b_priority = prio;
598 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
614 struct bridge_data *bd = bridge_data(link);
616 IS_BRIDGE_LINK_ASSERT(link);
618 return bd->b_priority;
633 struct bridge_data *bd = bridge_data(link);
635 IS_BRIDGE_LINK_ASSERT(link);
638 bd->ce_mask |= BRIDGE_ATTR_COST;
656 struct bridge_data *bd = bridge_data(link);
658 IS_BRIDGE_LINK_ASSERT(link);
681 struct bridge_data *bd = bridge_data(link);
683 IS_BRIDGE_LINK_ASSERT(link);
685 bd->b_flags_mask |= flags;
686 bd->b_flags &= ~flags;
687 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
714 struct bridge_data *bd = bridge_data(link);
716 IS_BRIDGE_LINK_ASSERT(link);
718 bd->b_flags_mask |= flags;
719 bd->b_flags |= flags;
720 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
737 struct bridge_data *bd = bridge_data(link);
739 IS_BRIDGE_LINK_ASSERT(link);
757 struct bridge_data *bd = bridge_data(link);
759 IS_BRIDGE_LINK_ASSERT(link);
762 bd->ce_mask |= BRIDGE_ATTR_SELF;
780 struct bridge_data *bd = bridge_data(link);
782 IS_BRIDGE_LINK_ASSERT(link);
784 if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE))
787 *hwmode = bd->b_hwmode;
814 struct bridge_data *bd = bridge_data(link);
816 if (hwmode > RTNL_BRIDGE_HWMODE_MAX)
822 bd->b_hwmode = hwmode;
823 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
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),
844 char *rtnl_link_bridge_flags2str(
int flags,
char *buf,
size_t len)
846 return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
849 int rtnl_link_bridge_str2flags(
const char *name)
851 return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
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),
869 char *rtnl_link_bridge_portstate2str(
int st,
char *buf,
size_t len)
871 return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states));
874 int rtnl_link_bridge_str2portstate(
const char *name)
876 return __str2type(name, port_states, ARRAY_SIZE(port_states));
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),
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));
896 uint16_t rtnl_link_bridge_str2hwmode(
const char *name)
898 return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes));
903 int rtnl_link_bridge_pvid(
struct rtnl_link *link)
905 struct bridge_data *bd;
907 IS_BRIDGE_LINK_ASSERT(link);
909 bd = link->l_af_data[AF_BRIDGE];
910 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
911 return (
int) bd->vlan_info.pvid;
916 int rtnl_link_bridge_has_vlan(
struct rtnl_link *link)
918 struct bridge_data *bd;
921 IS_BRIDGE_LINK_ASSERT(link);
923 bd = link->l_af_data[AF_BRIDGE];
924 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
925 if (bd->vlan_info.pvid)
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])
939 struct bridge_data *data;
944 data = link->l_af_data[AF_BRIDGE];
945 if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
946 return &data->vlan_info;
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,
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,
968 static void __init bridge_init(
void)
973 static void __exit bridge_exit(
void)
int rtnl_link_bridge_set_hwmode(struct rtnl_link *link, uint16_t hwmode)
Set hardware mode.
int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
Set Spanning Tree Protocol (STP) path cost.
int rtnl_link_bridge_set_self(struct rtnl_link *link)
Set link change type to self.
int rtnl_link_af_register(struct rtnl_link_af_ops *ops)
Register operations for a link address family.
int rtnl_link_bridge_unset_flags(struct rtnl_link *link, unsigned int flags)
Unset flags.
Attribute validation policy.
int rtnl_link_bridge_get_priority(struct rtnl_link *link)
Get priority.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
int rtnl_link_af_unregister(struct rtnl_link_af_ops *ops)
Unregister operations for a link address family.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
int rtnl_link_bridge_get_port_state(struct rtnl_link *link)
Get Spanning Tree Protocol (STP) port state.
int rtnl_link_bridge_set_port_state(struct rtnl_link *link, uint8_t state)
Set Spanning Tree Protocol (STP) port state.
int nla_is_nested(const struct nlattr *attr)
Return true if attribute has NLA_F_NESTED flag set.
Dump all attributes but no statistics.
int rtnl_link_bridge_set_priority(struct rtnl_link *link, uint16_t prio)
Set priority.
int rtnl_link_is_bridge(struct rtnl_link *link)
Check if a link is a bridge.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
struct rtnl_link * rtnl_link_bridge_alloc(void)
Allocate link object of type bridge.
int nla_type(const struct nlattr *nla)
Return type of the attribute.
int rtnl_link_bridge_get_hwmode(struct rtnl_link *link, uint16_t *hwmode)
Get hardware mode.
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
int rtnl_link_bridge_add(struct nl_sock *sk, const char *name)
Create a new kernel bridge device.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
int nla_len(const struct nlattr *nla)
Return length of the payload .
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
int rtnl_link_bridge_has_ext_info(struct rtnl_link *link)
Check if bridge has extended information.
int rtnl_link_bridge_get_cost(struct rtnl_link *link, uint32_t *cost)
Get Spanning Tree Protocol (STP) path cost.
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.
uint16_t type
Type of attribute or NLA_UNSPEC.
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.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
int rtnl_link_bridge_set_flags(struct rtnl_link *link, unsigned int flags)
Set flags.
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
int rtnl_link_bridge_get_flags(struct rtnl_link *link)
Get flags.