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_override_rtm(
struct rtnl_link *link) {
311 struct bridge_data *bd;
316 bd = bridge_data(link);
318 if (bd->ce_mask & BRIDGE_ATTR_FLAGS)
324 static int bridge_get_af(
struct nl_msg *msg, uint32_t *ext_filter_mask)
326 *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
330 static void dump_bitmap(
struct nl_dump_params *p,
const uint32_t *b)
333 int start = -1, prev = -1;
336 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
344 j = find_next_bit(i, a);
347 if (start < 0 && prev < 0) {
348 start = prev = j - 1 + base_bit;
352 if (j - 2 + base_bit == prev) {
361 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
372 start = prev = j - 1 + base_bit;
384 struct bridge_data *bd)
386 nl_dump(p,
"pvid %u", bd->vlan_info.pvid);
389 dump_bitmap(p, bd->vlan_info.vlan_bitmap);
391 nl_dump(p,
" untagged vlans:");
392 dump_bitmap(p, bd->vlan_info.untagged_bitmap);
395 static void bridge_dump_details(
struct rtnl_link *link,
398 struct bridge_data *bd = data;
400 nl_dump_line(p,
" bridge: ");
402 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
403 nl_dump(p,
"port-state %u ", bd->b_port_state);
405 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
406 nl_dump(p,
"prio %u ", bd->b_priority);
408 if (bd->ce_mask & BRIDGE_ATTR_COST)
409 nl_dump(p,
"cost %u ", bd->b_cost);
411 if (bd->ce_mask & BRIDGE_ATTR_HWMODE) {
414 rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf,
sizeof(hbuf));
418 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
419 rtnl_link_bridge_dump_vlans(p, bd);
421 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
424 rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
433 int family, uint32_t attrs,
int flags)
435 struct bridge_data *a = bridge_data(_a);
436 struct bridge_data *b = bridge_data(_b);
439 #define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR) 440 diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state);
441 diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
442 diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
443 diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
445 diff |= BRIDGE_DIFF(HWMODE, a->b_hwmode != b->b_hwmode);
446 diff |= BRIDGE_DIFF(SELF, a->b_self != b->b_self);
448 if (flags & LOOSE_COMPARISON)
449 diff |= BRIDGE_DIFF(FLAGS,
450 (a->b_flags ^ b->b_flags) & b->b_flags_mask);
452 diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
516 return link->l_family == AF_BRIDGE &&
517 link->l_af_ops == &bridge_ops;
535 struct bridge_data *bd;
540 bd = bridge_data(link);
541 return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
564 struct bridge_data *bd = bridge_data(link);
566 IS_BRIDGE_LINK_ASSERT(link);
568 if (state > BR_STATE_BLOCKING)
571 bd->b_port_state = state;
572 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
588 struct bridge_data *bd = bridge_data(link);
590 IS_BRIDGE_LINK_ASSERT(link);
592 return bd->b_port_state;
607 struct bridge_data *bd = bridge_data(link);
609 IS_BRIDGE_LINK_ASSERT(link);
611 bd->b_priority = prio;
612 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
628 struct bridge_data *bd = bridge_data(link);
630 IS_BRIDGE_LINK_ASSERT(link);
632 return bd->b_priority;
647 struct bridge_data *bd = bridge_data(link);
649 IS_BRIDGE_LINK_ASSERT(link);
652 bd->ce_mask |= BRIDGE_ATTR_COST;
670 struct bridge_data *bd = bridge_data(link);
672 IS_BRIDGE_LINK_ASSERT(link);
695 struct bridge_data *bd = bridge_data(link);
697 IS_BRIDGE_LINK_ASSERT(link);
699 bd->b_flags_mask |= flags;
700 bd->b_flags &= ~flags;
701 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
728 struct bridge_data *bd = bridge_data(link);
730 IS_BRIDGE_LINK_ASSERT(link);
732 bd->b_flags_mask |= flags;
733 bd->b_flags |= flags;
734 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
751 struct bridge_data *bd = bridge_data(link);
753 IS_BRIDGE_LINK_ASSERT(link);
771 struct bridge_data *bd = bridge_data(link);
773 IS_BRIDGE_LINK_ASSERT(link);
776 bd->ce_mask |= BRIDGE_ATTR_SELF;
794 struct bridge_data *bd = bridge_data(link);
796 IS_BRIDGE_LINK_ASSERT(link);
798 if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE))
801 *hwmode = bd->b_hwmode;
828 struct bridge_data *bd = bridge_data(link);
830 if (hwmode > RTNL_BRIDGE_HWMODE_MAX)
836 bd->b_hwmode = hwmode;
837 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
843 static const struct trans_tbl bridge_flags[] = {
844 __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
845 __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
846 __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
847 __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
848 __ADD(RTNL_BRIDGE_UNICAST_FLOOD, flood),
849 __ADD(RTNL_BRIDGE_LEARNING, learning),
850 __ADD(RTNL_BRIDGE_LEARNING_SYNC, learning_sync),
858 char *rtnl_link_bridge_flags2str(
int flags,
char *buf,
size_t len)
860 return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
863 int rtnl_link_bridge_str2flags(
const char *name)
865 return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
870 static const struct trans_tbl port_states[] = {
871 __ADD(BR_STATE_DISABLED, disabled),
872 __ADD(BR_STATE_LISTENING, listening),
873 __ADD(BR_STATE_LEARNING, learning),
874 __ADD(BR_STATE_FORWARDING, forwarding),
875 __ADD(BR_STATE_BLOCKING, blocking),
883 char *rtnl_link_bridge_portstate2str(
int st,
char *buf,
size_t len)
885 return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states));
888 int rtnl_link_bridge_str2portstate(
const char *name)
890 return __str2type(name, port_states, ARRAY_SIZE(port_states));
895 static const struct trans_tbl hw_modes[] = {
896 __ADD(RTNL_BRIDGE_HWMODE_VEB, veb),
897 __ADD(RTNL_BRIDGE_HWMODE_VEPA, vepa),
898 __ADD(RTNL_BRIDGE_HWMODE_UNDEF, undef),
906 char *rtnl_link_bridge_hwmode2str(uint16_t st,
char *buf,
size_t len) {
907 return __type2str(st, buf, len, hw_modes, ARRAY_SIZE(hw_modes));
910 uint16_t rtnl_link_bridge_str2hwmode(
const char *name)
912 return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes));
917 int rtnl_link_bridge_pvid(
struct rtnl_link *link)
919 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 return (
int) bd->vlan_info.pvid;
930 int rtnl_link_bridge_has_vlan(
struct rtnl_link *link)
932 struct bridge_data *bd;
935 IS_BRIDGE_LINK_ASSERT(link);
937 bd = link->l_af_data[AF_BRIDGE];
938 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
939 if (bd->vlan_info.pvid)
942 for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
943 if (bd->vlan_info.vlan_bitmap[i] ||
944 bd->vlan_info.untagged_bitmap[i])
953 struct bridge_data *data;
958 data = link->l_af_data[AF_BRIDGE];
959 if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
960 return &data->vlan_info;
965 static struct rtnl_link_af_ops bridge_ops = {
966 .ao_family = AF_BRIDGE,
967 .ao_alloc = &bridge_alloc,
968 .ao_clone = &bridge_clone,
969 .ao_free = &bridge_free,
970 .ao_parse_protinfo = &bridge_parse_protinfo,
972 .ao_compare = &bridge_compare,
973 .ao_parse_af_full = &bridge_parse_af_full,
974 .ao_get_af = &bridge_get_af,
975 .ao_fill_af = &bridge_fill_af,
976 .ao_fill_pi = &bridge_fill_pi,
977 .ao_fill_pi_flags = NLA_F_NESTED,
978 .ao_override_rtm = &bridge_override_rtm,
979 .ao_fill_af_no_nest = 1,
982 static void __init bridge_init(
void)
987 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 nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
int rtnl_link_is_bridge(struct rtnl_link *link)
Check if a link is a bridge.
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.