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) 37 #define PRIV_FLAG_NEW_ATTRS (1 << 0) 46 uint32_t b_flags_mask;
51 static void set_bit(
unsigned nr, uint32_t *addr)
53 if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
54 addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
57 static int find_next_bit(
int i, uint32_t x)
66 return __builtin_ffs(x);
69 j = __builtin_ffs(x >> i);
73 static struct rtnl_link_af_ops bridge_ops;
75 #define IS_BRIDGE_LINK_ASSERT(link) \ 76 if (!rtnl_link_is_bridge(link)) { \ 77 APPBUG("A function was expecting a link object of type bridge."); \ 78 return -NLE_OPNOTSUPP; \ 81 static inline struct bridge_data *bridge_data(
struct rtnl_link *link)
86 static void *bridge_alloc(
struct rtnl_link *link)
88 return calloc(1,
sizeof(
struct bridge_data));
91 static void *bridge_clone(
struct rtnl_link *link,
void *data)
93 struct bridge_data *bd;
95 if ((bd = bridge_alloc(link)))
96 memcpy(bd, data,
sizeof(*bd));
101 static void bridge_free(
struct rtnl_link *link,
void *data)
106 static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = {
108 [IFLA_BRPORT_PRIORITY] = { .type =
NLA_U16 },
109 [IFLA_BRPORT_COST] = { .type =
NLA_U32 },
110 [IFLA_BRPORT_MODE] = { .type =
NLA_U8 },
111 [IFLA_BRPORT_GUARD] = { .type =
NLA_U8 },
112 [IFLA_BRPORT_PROTECT] = { .type =
NLA_U8 },
113 [IFLA_BRPORT_FAST_LEAVE] = { .type =
NLA_U8 },
116 static void check_flag(
struct rtnl_link *link,
struct nlattr *attrs[],
123 static int bridge_parse_protinfo(
struct rtnl_link *link,
struct nlattr *attr,
126 struct bridge_data *bd = data;
127 struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
136 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
142 br_attrs_policy)) < 0)
145 bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;
147 if (br_attrs[IFLA_BRPORT_STATE]) {
148 bd->b_port_state =
nla_get_u8(br_attrs[IFLA_BRPORT_STATE]);
149 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
152 if (br_attrs[IFLA_BRPORT_PRIORITY]) {
153 bd->b_priority =
nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]);
154 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
157 if (br_attrs[IFLA_BRPORT_COST]) {
158 bd->b_cost =
nla_get_u32(br_attrs[IFLA_BRPORT_COST]);
159 bd->ce_mask |= BRIDGE_ATTR_COST;
162 check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE);
163 check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD);
164 check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK);
165 check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE);
170 static int bridge_parse_af_full(
struct rtnl_link *link,
struct nlattr *attr_full,
173 struct bridge_data *bd = data;
174 struct bridge_vlan_info *vinfo = NULL;
175 uint16_t vid_range_start = 0;
176 uint16_t vid_range_flags = -1;
183 if (
nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
186 if (
nla_len(attr) !=
sizeof(
struct bridge_vlan_info))
190 if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
194 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
195 vid_range_start = vinfo->vid;
196 vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
200 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
202 if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
203 NL_DBG(1,
"VLAN range flags differ; can not handle it.\n");
207 vid_range_start = vinfo->vid;
210 for (; vid_range_start <= vinfo->vid; vid_range_start++) {
211 if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
212 bd->vlan_info.pvid = vinfo->vid;
214 if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
215 set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
217 set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
218 bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
221 vid_range_flags = -1;
227 static int bridge_get_af(
struct nl_msg *msg, uint32_t *ext_filter_mask)
229 *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
233 static void dump_bitmap(
struct nl_dump_params *p,
const uint32_t *b)
236 int start = -1, prev = -1;
239 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
247 j = find_next_bit(i, a);
250 if (start < 0 && prev < 0) {
251 start = prev = j - 1 + base_bit;
255 if (j - 2 + base_bit == prev) {
264 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
275 start = prev = j - 1 + base_bit;
287 struct bridge_data *bd)
289 nl_dump(p,
"pvid %u", bd->vlan_info.pvid);
292 dump_bitmap(p, bd->vlan_info.vlan_bitmap);
294 nl_dump(p,
" untagged vlans:");
295 dump_bitmap(p, bd->vlan_info.untagged_bitmap);
298 static void bridge_dump_details(
struct rtnl_link *link,
301 struct bridge_data *bd = data;
303 nl_dump_line(p,
" bridge: ");
305 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
306 nl_dump(p,
"port-state %u ", bd->b_port_state);
308 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
309 nl_dump(p,
"prio %u ", bd->b_priority);
311 if (bd->ce_mask & BRIDGE_ATTR_COST)
312 nl_dump(p,
"cost %u ", bd->b_cost);
314 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
315 rtnl_link_bridge_dump_vlans(p, bd);
317 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
320 rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
329 int family, uint32_t attrs,
int flags)
331 struct bridge_data *a = bridge_data(_a);
332 struct bridge_data *b = bridge_data(_b);
335 #define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR) 336 diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state);
337 diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
338 diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
339 diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
342 if (flags & LOOSE_COMPARISON)
343 diff |= BRIDGE_DIFF(FLAGS,
344 (a->b_flags ^ b->b_flags) & b->b_flags_mask);
346 diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
410 return link->l_family == AF_BRIDGE &&
411 link->l_af_ops == &bridge_ops;
429 struct bridge_data *bd;
434 bd = bridge_data(link);
435 return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
458 struct bridge_data *bd = bridge_data(link);
460 IS_BRIDGE_LINK_ASSERT(link);
462 if (state > BR_STATE_BLOCKING)
465 bd->b_port_state = state;
466 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
482 struct bridge_data *bd = bridge_data(link);
484 IS_BRIDGE_LINK_ASSERT(link);
486 return bd->b_port_state;
501 struct bridge_data *bd = bridge_data(link);
503 IS_BRIDGE_LINK_ASSERT(link);
505 bd->b_priority = prio;
506 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
522 struct bridge_data *bd = bridge_data(link);
524 IS_BRIDGE_LINK_ASSERT(link);
526 return bd->b_priority;
541 struct bridge_data *bd = bridge_data(link);
543 IS_BRIDGE_LINK_ASSERT(link);
546 bd->ce_mask |= BRIDGE_ATTR_COST;
564 struct bridge_data *bd = bridge_data(link);
566 IS_BRIDGE_LINK_ASSERT(link);
589 struct bridge_data *bd = bridge_data(link);
591 IS_BRIDGE_LINK_ASSERT(link);
593 bd->b_flags_mask |= flags;
594 bd->b_flags &= ~flags;
595 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
619 struct bridge_data *bd = bridge_data(link);
621 IS_BRIDGE_LINK_ASSERT(link);
623 bd->b_flags_mask |= flags;
624 bd->b_flags |= flags;
625 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
642 struct bridge_data *bd = bridge_data(link);
644 IS_BRIDGE_LINK_ASSERT(link);
649 static const struct trans_tbl bridge_flags[] = {
650 __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
651 __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
652 __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
653 __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
661 char *rtnl_link_bridge_flags2str(
int flags,
char *buf,
size_t len)
663 return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
666 int rtnl_link_bridge_str2flags(
const char *name)
668 return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
673 int rtnl_link_bridge_pvid(
struct rtnl_link *link)
675 struct bridge_data *bd;
677 IS_BRIDGE_LINK_ASSERT(link);
679 bd = link->l_af_data[AF_BRIDGE];
680 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
681 return (
int) bd->vlan_info.pvid;
686 int rtnl_link_bridge_has_vlan(
struct rtnl_link *link)
688 struct bridge_data *bd;
691 IS_BRIDGE_LINK_ASSERT(link);
693 bd = link->l_af_data[AF_BRIDGE];
694 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
695 if (bd->vlan_info.pvid)
698 for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
699 if (bd->vlan_info.vlan_bitmap[i] ||
700 bd->vlan_info.untagged_bitmap[i])
709 struct bridge_data *data;
714 data = link->l_af_data[AF_BRIDGE];
715 if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
716 return &data->vlan_info;
721 static struct rtnl_link_af_ops bridge_ops = {
722 .ao_family = AF_BRIDGE,
723 .ao_alloc = &bridge_alloc,
724 .ao_clone = &bridge_clone,
725 .ao_free = &bridge_free,
726 .ao_parse_protinfo = &bridge_parse_protinfo,
728 .ao_compare = &bridge_compare,
729 .ao_parse_af_full = &bridge_parse_af_full,
730 .ao_get_af = &bridge_get_af,
733 static void __init bridge_init(
void)
738 static void __exit bridge_exit(
void)
int rtnl_link_bridge_set_cost(struct rtnl_link *link, uint32_t cost)
Set Spanning Tree Protocol (STP) path cost.
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.
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.
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.
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.
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.