14#include <netlink-private/netlink.h>
15#include <netlink/netlink.h>
16#include <netlink/attr.h>
17#include <netlink/route/rtnl.h>
18#include <netlink/route/link/bridge.h>
19#include <netlink-private/route/link/api.h>
20#include <linux/if_bridge.h>
22#define VLAN_VID_MASK 0x0fff
25#define BRIDGE_ATTR_PORT_STATE (1 << 0)
26#define BRIDGE_ATTR_PRIORITY (1 << 1)
27#define BRIDGE_ATTR_COST (1 << 2)
28#define BRIDGE_ATTR_FLAGS (1 << 3)
29#define BRIDGE_ATTR_PORT_VLAN (1 << 4)
30#define BRIDGE_ATTR_HWMODE (1 << 5)
31#define BRIDGE_ATTR_SELF (1 << 6)
33#define PRIV_FLAG_NEW_ATTRS (1 << 0)
44 uint32_t b_flags_mask;
49static void set_bit(
unsigned nr, uint32_t *addr)
51 if (nr < RTNL_LINK_BRIDGE_VLAN_BITMAP_MAX)
52 addr[nr / 32] |= (((uint32_t) 1) << (nr % 32));
55static int find_next_bit(
int i, uint32_t x)
64 return __builtin_ffs(x);
67 j = __builtin_ffs(x >> i);
71static struct rtnl_link_af_ops bridge_ops;
73#define IS_BRIDGE_LINK_ASSERT(link) \
74 if (!rtnl_link_is_bridge(link)) { \
75 APPBUG("A function was expecting a link object of type bridge."); \
76 return -NLE_OPNOTSUPP; \
79static inline struct bridge_data *bridge_data(
struct rtnl_link *link)
84static void *bridge_alloc(
struct rtnl_link *link)
86 return calloc(1,
sizeof(
struct bridge_data));
89static void *bridge_clone(
struct rtnl_link *link,
void *data)
91 struct bridge_data *bd;
93 if ((bd = bridge_alloc(link)))
94 memcpy(bd, data,
sizeof(*bd));
99static void bridge_free(
struct rtnl_link *link,
void *data)
104static struct nla_policy br_attrs_policy[IFLA_BRPORT_MAX+1] = {
106 [IFLA_BRPORT_PRIORITY] = { .type =
NLA_U16 },
107 [IFLA_BRPORT_COST] = { .type =
NLA_U32 },
108 [IFLA_BRPORT_MODE] = { .type =
NLA_U8 },
109 [IFLA_BRPORT_GUARD] = { .type =
NLA_U8 },
110 [IFLA_BRPORT_PROTECT] = { .type =
NLA_U8 },
111 [IFLA_BRPORT_FAST_LEAVE] = { .type =
NLA_U8 },
112 [IFLA_BRPORT_LEARNING] = { .type =
NLA_U8 },
113 [IFLA_BRPORT_LEARNING_SYNC] = { .type =
NLA_U8 },
114 [IFLA_BRPORT_UNICAST_FLOOD] = { .type =
NLA_U8 },
117static void check_flag(
struct rtnl_link *link,
struct nlattr *attrs[],
124static int bridge_parse_protinfo(
struct rtnl_link *link,
struct nlattr *attr,
127 struct bridge_data *bd = data;
128 struct nlattr *br_attrs[IFLA_BRPORT_MAX+1];
137 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
143 br_attrs_policy)) < 0)
146 bd->b_priv_flags |= PRIV_FLAG_NEW_ATTRS;
148 if (br_attrs[IFLA_BRPORT_STATE]) {
149 bd->b_port_state =
nla_get_u8(br_attrs[IFLA_BRPORT_STATE]);
150 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
153 if (br_attrs[IFLA_BRPORT_PRIORITY]) {
154 bd->b_priority =
nla_get_u16(br_attrs[IFLA_BRPORT_PRIORITY]);
155 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
158 if (br_attrs[IFLA_BRPORT_COST]) {
159 bd->b_cost =
nla_get_u32(br_attrs[IFLA_BRPORT_COST]);
160 bd->ce_mask |= BRIDGE_ATTR_COST;
163 check_flag(link, br_attrs, IFLA_BRPORT_MODE, RTNL_BRIDGE_HAIRPIN_MODE);
164 check_flag(link, br_attrs, IFLA_BRPORT_GUARD, RTNL_BRIDGE_BPDU_GUARD);
165 check_flag(link, br_attrs, IFLA_BRPORT_PROTECT, RTNL_BRIDGE_ROOT_BLOCK);
166 check_flag(link, br_attrs, IFLA_BRPORT_FAST_LEAVE, RTNL_BRIDGE_FAST_LEAVE);
167 check_flag(link, br_attrs, IFLA_BRPORT_UNICAST_FLOOD,
168 RTNL_BRIDGE_UNICAST_FLOOD);
169 check_flag(link, br_attrs, IFLA_BRPORT_LEARNING, RTNL_BRIDGE_LEARNING);
170 check_flag(link, br_attrs, IFLA_BRPORT_LEARNING_SYNC,
171 RTNL_BRIDGE_LEARNING_SYNC);
176static int bridge_parse_af_full(
struct rtnl_link *link,
struct nlattr *attr_full,
179 struct bridge_data *bd = data;
180 struct bridge_vlan_info *vinfo = NULL;
181 uint16_t vid_range_start = 0;
182 uint16_t vid_range_flags = -1;
189 if (
nla_type(attr) == IFLA_BRIDGE_MODE) {
191 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
192 }
else if (
nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
195 if (
nla_len(attr) !=
sizeof(
struct bridge_vlan_info))
199 if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
203 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
204 vid_range_start = vinfo->vid;
205 vid_range_flags = (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_BEGIN);
209 if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END) {
211 if (vid_range_flags != (vinfo->flags ^ BRIDGE_VLAN_INFO_RANGE_END)) {
212 NL_DBG(1,
"VLAN range flags differ; can not handle it.\n");
216 vid_range_start = vinfo->vid;
219 for (; vid_range_start <= vinfo->vid; vid_range_start++) {
220 if (vinfo->flags & BRIDGE_VLAN_INFO_PVID)
221 bd->vlan_info.pvid = vinfo->vid;
223 if (vinfo->flags & BRIDGE_VLAN_INFO_UNTAGGED)
224 set_bit(vid_range_start, bd->vlan_info.untagged_bitmap);
226 set_bit(vid_range_start, bd->vlan_info.vlan_bitmap);
227 bd->ce_mask |= BRIDGE_ATTR_PORT_VLAN;
230 vid_range_flags = -1;
236static int bridge_fill_af(
struct rtnl_link *link,
struct nl_msg *msg,
239 struct bridge_data *bd = data;
241 if ((bd->ce_mask & BRIDGE_ATTR_SELF)||(bd->ce_mask & BRIDGE_ATTR_HWMODE))
242 NLA_PUT_U16(msg, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF);
244 if (bd->ce_mask & BRIDGE_ATTR_HWMODE)
253static int bridge_fill_pi(
struct rtnl_link *link,
struct nl_msg *msg,
256 struct bridge_data *bd = data;
258 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
259 if (bd->b_flags_mask & RTNL_BRIDGE_BPDU_GUARD) {
261 bd->b_flags & RTNL_BRIDGE_BPDU_GUARD);
263 if (bd->b_flags_mask & RTNL_BRIDGE_HAIRPIN_MODE) {
265 bd->b_flags & RTNL_BRIDGE_HAIRPIN_MODE);
267 if (bd->b_flags_mask & RTNL_BRIDGE_FAST_LEAVE) {
269 bd->b_flags & RTNL_BRIDGE_FAST_LEAVE);
271 if (bd->b_flags_mask & RTNL_BRIDGE_ROOT_BLOCK) {
273 bd->b_flags & RTNL_BRIDGE_ROOT_BLOCK);
275 if (bd->b_flags_mask & RTNL_BRIDGE_UNICAST_FLOOD) {
277 bd->b_flags & RTNL_BRIDGE_UNICAST_FLOOD);
279 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING) {
281 bd->b_flags & RTNL_BRIDGE_LEARNING);
283 if (bd->b_flags_mask & RTNL_BRIDGE_LEARNING_SYNC) {
285 bd->b_flags & RTNL_BRIDGE_LEARNING_SYNC);
289 if (bd->ce_mask & BRIDGE_ATTR_COST)
292 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
293 NLA_PUT_U16(msg, IFLA_BRPORT_PRIORITY, bd->b_priority);
295 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
296 NLA_PUT_U8(msg, IFLA_BRPORT_STATE, bd->b_port_state);
304static int bridge_override_rtm(
struct rtnl_link *link) {
305 struct bridge_data *bd;
310 bd = bridge_data(link);
312 if (bd->ce_mask & BRIDGE_ATTR_FLAGS)
318static int bridge_get_af(
struct nl_msg *msg, uint32_t *ext_filter_mask)
320 *ext_filter_mask |= RTEXT_FILTER_BRVLAN;
324static void dump_bitmap(
struct nl_dump_params *p,
const uint32_t *b)
327 int start = -1, prev = -1;
330 for (k = 0; k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; k++) {
338 j = find_next_bit(i, a);
341 if (start < 0 && prev < 0) {
342 start = prev = j - 1 + base_bit;
346 if (j - 2 + base_bit == prev) {
355 if (done && k < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN - 1)
366 start = prev = j - 1 + base_bit;
378 struct bridge_data *bd)
380 nl_dump(p,
"pvid %u", bd->vlan_info.pvid);
383 dump_bitmap(p, bd->vlan_info.vlan_bitmap);
385 nl_dump(p,
" untagged vlans:");
386 dump_bitmap(p, bd->vlan_info.untagged_bitmap);
389static void bridge_dump_details(
struct rtnl_link *link,
392 struct bridge_data *bd = data;
394 nl_dump_line(p,
" bridge: ");
396 if (bd->ce_mask & BRIDGE_ATTR_PORT_STATE)
397 nl_dump(p,
"port-state %u ", bd->b_port_state);
399 if (bd->ce_mask & BRIDGE_ATTR_PRIORITY)
400 nl_dump(p,
"prio %u ", bd->b_priority);
402 if (bd->ce_mask & BRIDGE_ATTR_COST)
403 nl_dump(p,
"cost %u ", bd->b_cost);
405 if (bd->ce_mask & BRIDGE_ATTR_HWMODE) {
408 rtnl_link_bridge_hwmode2str(bd->b_hwmode, hbuf,
sizeof(hbuf));
412 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
413 rtnl_link_bridge_dump_vlans(p, bd);
415 if (bd->ce_mask & BRIDGE_ATTR_FLAGS) {
418 rtnl_link_bridge_flags2str(bd->b_flags & bd->b_flags_mask,
427 int family, uint32_t attrs,
int flags)
429 struct bridge_data *a = bridge_data(_a);
430 struct bridge_data *b = bridge_data(_b);
433#define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR)
434 diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state);
435 diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
436 diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
437 diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
439 diff |= BRIDGE_DIFF(HWMODE, a->b_hwmode != b->b_hwmode);
440 diff |= BRIDGE_DIFF(SELF, a->b_self != b->b_self);
442 if (flags & LOOSE_COMPARISON)
443 diff |= BRIDGE_DIFF(FLAGS,
444 (a->b_flags ^ b->b_flags) & b->b_flags_mask);
446 diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
509 return link->l_family == AF_BRIDGE &&
510 link->l_af_ops == &bridge_ops;
528 struct bridge_data *bd;
533 bd = bridge_data(link);
534 return !!(bd->b_priv_flags & PRIV_FLAG_NEW_ATTRS);
557 struct bridge_data *bd = bridge_data(link);
559 IS_BRIDGE_LINK_ASSERT(link);
561 if (state > BR_STATE_BLOCKING)
564 bd->b_port_state = state;
565 bd->ce_mask |= BRIDGE_ATTR_PORT_STATE;
581 struct bridge_data *bd = bridge_data(link);
583 IS_BRIDGE_LINK_ASSERT(link);
585 return bd->b_port_state;
600 struct bridge_data *bd = bridge_data(link);
602 IS_BRIDGE_LINK_ASSERT(link);
604 bd->b_priority = prio;
605 bd->ce_mask |= BRIDGE_ATTR_PRIORITY;
621 struct bridge_data *bd = bridge_data(link);
623 IS_BRIDGE_LINK_ASSERT(link);
625 return bd->b_priority;
640 struct bridge_data *bd = bridge_data(link);
642 IS_BRIDGE_LINK_ASSERT(link);
645 bd->ce_mask |= BRIDGE_ATTR_COST;
663 struct bridge_data *bd = bridge_data(link);
665 IS_BRIDGE_LINK_ASSERT(link);
688 struct bridge_data *bd = bridge_data(link);
690 IS_BRIDGE_LINK_ASSERT(link);
692 bd->b_flags_mask |= flags;
693 bd->b_flags &= ~flags;
694 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
721 struct bridge_data *bd = bridge_data(link);
723 IS_BRIDGE_LINK_ASSERT(link);
725 bd->b_flags_mask |= flags;
726 bd->b_flags |= flags;
727 bd->ce_mask |= BRIDGE_ATTR_FLAGS;
744 struct bridge_data *bd = bridge_data(link);
746 IS_BRIDGE_LINK_ASSERT(link);
764 struct bridge_data *bd = bridge_data(link);
766 IS_BRIDGE_LINK_ASSERT(link);
769 bd->ce_mask |= BRIDGE_ATTR_SELF;
787 struct bridge_data *bd = bridge_data(link);
789 IS_BRIDGE_LINK_ASSERT(link);
791 if (!(bd->ce_mask & BRIDGE_ATTR_HWMODE))
794 *hwmode = bd->b_hwmode;
821 struct bridge_data *bd = bridge_data(link);
823 if (hwmode > RTNL_BRIDGE_HWMODE_MAX)
829 bd->b_hwmode = hwmode;
830 bd->ce_mask |= BRIDGE_ATTR_HWMODE;
836static const struct trans_tbl bridge_flags[] = {
837 __ADD(RTNL_BRIDGE_HAIRPIN_MODE, hairpin_mode),
838 __ADD(RTNL_BRIDGE_BPDU_GUARD, bpdu_guard),
839 __ADD(RTNL_BRIDGE_ROOT_BLOCK, root_block),
840 __ADD(RTNL_BRIDGE_FAST_LEAVE, fast_leave),
841 __ADD(RTNL_BRIDGE_UNICAST_FLOOD, flood),
842 __ADD(RTNL_BRIDGE_LEARNING, learning),
843 __ADD(RTNL_BRIDGE_LEARNING_SYNC, learning_sync),
851char *rtnl_link_bridge_flags2str(
int flags,
char *buf,
size_t len)
853 return __flags2str(flags, buf, len, bridge_flags, ARRAY_SIZE(bridge_flags));
856int rtnl_link_bridge_str2flags(
const char *name)
858 return __str2flags(name, bridge_flags, ARRAY_SIZE(bridge_flags));
863static const struct trans_tbl port_states[] = {
864 __ADD(BR_STATE_DISABLED, disabled),
865 __ADD(BR_STATE_LISTENING, listening),
866 __ADD(BR_STATE_LEARNING, learning),
867 __ADD(BR_STATE_FORWARDING, forwarding),
868 __ADD(BR_STATE_BLOCKING, blocking),
876char *rtnl_link_bridge_portstate2str(
int st,
char *buf,
size_t len)
878 return __type2str(st, buf, len, port_states, ARRAY_SIZE(port_states));
881int rtnl_link_bridge_str2portstate(
const char *name)
883 return __str2type(name, port_states, ARRAY_SIZE(port_states));
888static const struct trans_tbl hw_modes[] = {
889 __ADD(RTNL_BRIDGE_HWMODE_VEB, veb),
890 __ADD(RTNL_BRIDGE_HWMODE_VEPA, vepa),
891 __ADD(RTNL_BRIDGE_HWMODE_UNDEF, undef),
899char *rtnl_link_bridge_hwmode2str(uint16_t st,
char *buf,
size_t len) {
900 return __type2str(st, buf, len, hw_modes, ARRAY_SIZE(hw_modes));
903uint16_t rtnl_link_bridge_str2hwmode(
const char *name)
905 return __str2type(name, hw_modes, ARRAY_SIZE(hw_modes));
910int rtnl_link_bridge_pvid(
struct rtnl_link *link)
912 struct bridge_data *bd;
914 IS_BRIDGE_LINK_ASSERT(link);
916 bd = link->l_af_data[AF_BRIDGE];
917 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN)
918 return (
int) bd->vlan_info.pvid;
923int rtnl_link_bridge_has_vlan(
struct rtnl_link *link)
925 struct bridge_data *bd;
928 IS_BRIDGE_LINK_ASSERT(link);
930 bd = link->l_af_data[AF_BRIDGE];
931 if (bd->ce_mask & BRIDGE_ATTR_PORT_VLAN) {
932 if (bd->vlan_info.pvid)
935 for (i = 0; i < RTNL_LINK_BRIDGE_VLAN_BITMAP_LEN; ++i) {
936 if (bd->vlan_info.vlan_bitmap[i] ||
937 bd->vlan_info.untagged_bitmap[i])
946 struct bridge_data *data;
951 data = link->l_af_data[AF_BRIDGE];
952 if (data && (data->ce_mask & BRIDGE_ATTR_PORT_VLAN))
953 return &data->vlan_info;
958static struct rtnl_link_af_ops bridge_ops = {
959 .ao_family = AF_BRIDGE,
960 .ao_alloc = &bridge_alloc,
961 .ao_clone = &bridge_clone,
962 .ao_free = &bridge_free,
963 .ao_parse_protinfo = &bridge_parse_protinfo,
965 .ao_compare = &bridge_compare,
966 .ao_parse_af_full = &bridge_parse_af_full,
967 .ao_get_af = &bridge_get_af,
968 .ao_fill_af = &bridge_fill_af,
969 .ao_fill_pi = &bridge_fill_pi,
970 .ao_fill_pi_flags = NLA_F_NESTED,
971 .ao_override_rtm = &bridge_override_rtm,
972 .ao_fill_af_no_nest = 1,
975static void __init bridge_init(
void)
980static void __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_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.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on 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 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_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_add(struct nl_sock *sk, const char *name)
Create a new kernel bridge device.
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_set_self(struct rtnl_link *link)
Set link change type to self.
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_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_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)
Return 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.