14#include "nl-default.h"
16#include <linux/if_bridge.h>
18#include <netlink/route/link/bridge_info.h>
23#define BRIDGE_ATTR_VLAN_FILTERING (1 << 0)
24#define BRIDGE_ATTR_VLAN_PROTOCOL (1 << 1)
25#define BRIDGE_ATTR_VLAN_STATS_ENABLED (1 << 2)
26#define BRIDGE_ATTR_AGEING_TIME (1 << 3)
27#define BRIDGE_ATTR_VLAN_DEFAULT_PVID (1 << 4)
28#define BRIDGE_ATTR_NF_CALL_IPTABLES (1 << 5)
29#define BRIDGE_ATTR_NF_CALL_IP6TABLES (1 << 6)
30#define BRIDGE_ATTR_NF_CALL_ARPTABLES (1 << 7)
31#define BRIDGE_ATTR_STP_STATE (1 << 8)
32#define BRIDGE_ATTR_MCAST_ROUTER (1 << 9)
33#define BRIDGE_ATTR_MCAST_SNOOPING (1 << 10)
34#define BRIDGE_ATTR_BOOLOPT (1 << 11)
38 uint32_t b_ageing_time;
39 uint16_t b_vlan_protocol;
40 uint16_t b_vlan_default_pvid;
41 uint8_t b_vlan_filtering;
42 uint8_t b_vlan_stats_enabled;
43 uint8_t b_nf_call_iptables;
44 uint8_t b_nf_call_ip6tables;
45 uint8_t b_nf_call_arptables;
47 uint8_t b_mcast_router;
48 uint8_t b_mcast_snooping;
49 struct br_boolopt_multi b_boolopts;
52static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = {
53 [IFLA_BR_AGEING_TIME] = { .type =
NLA_U32 },
54 [IFLA_BR_VLAN_DEFAULT_PVID] = { .type =
NLA_U16 },
55 [IFLA_BR_VLAN_FILTERING] = { .type =
NLA_U8 },
56 [IFLA_BR_VLAN_PROTOCOL] = { .type =
NLA_U16 },
57 [IFLA_BR_VLAN_STATS_ENABLED] = { .type =
NLA_U8 },
58 [IFLA_BR_NF_CALL_IPTABLES] = { .type =
NLA_U8 },
59 [IFLA_BR_NF_CALL_IP6TABLES] = { .type =
NLA_U8 },
60 [IFLA_BR_NF_CALL_ARPTABLES] = { .type =
NLA_U8 },
61 [IFLA_BR_STP_STATE] = { .type =
NLA_U32 },
62 [IFLA_BR_MCAST_ROUTER] = { .type =
NLA_U8 },
63 [IFLA_BR_MCAST_SNOOPING] = { .type =
NLA_U8 },
64 [IFLA_BR_MULTI_BOOLOPT] = { .type = NLA_BINARY,
65 .minlen =
sizeof(
struct br_boolopt_multi),
66 .maxlen =
sizeof(
struct br_boolopt_multi) },
74static int bridge_info_alloc(
struct rtnl_link *link)
79 memset(link->l_info, 0,
sizeof(*bi));
81 bi = calloc(1,
sizeof(*bi));
98 err = bridge_info_alloc(dst);
102 bi_dst = dst->l_info;
111static int bridge_info_parse(
struct rtnl_link *link,
struct nlattr *data,
112 struct nlattr *xstats)
114 struct nlattr *tb[IFLA_BR_MAX + 1];
118 NL_DBG(3,
"Parsing Bridge link info\n");
124 if ((err = bridge_info_alloc(link)) < 0)
129 if (tb[IFLA_BR_AGEING_TIME]) {
130 bi->b_ageing_time =
nla_get_u32(tb[IFLA_BR_AGEING_TIME]);
131 bi->ce_mask |= BRIDGE_ATTR_AGEING_TIME;
134 if (tb[IFLA_BR_VLAN_DEFAULT_PVID]) {
135 bi->b_vlan_default_pvid =
137 bi->ce_mask |= BRIDGE_ATTR_VLAN_DEFAULT_PVID;
140 if (tb[IFLA_BR_VLAN_FILTERING]) {
141 bi->b_vlan_filtering =
nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]);
142 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
145 if (tb[IFLA_BR_VLAN_PROTOCOL]) {
146 bi->b_vlan_protocol =
148 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
151 if (tb[IFLA_BR_VLAN_STATS_ENABLED]) {
152 bi->b_vlan_stats_enabled =
154 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
157 if (tb[IFLA_BR_NF_CALL_IPTABLES]) {
158 bi->b_nf_call_iptables =
160 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IPTABLES;
163 if (tb[IFLA_BR_NF_CALL_IP6TABLES]) {
164 bi->b_nf_call_ip6tables =
166 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IP6TABLES;
169 if (tb[IFLA_BR_NF_CALL_ARPTABLES]) {
170 bi->b_nf_call_arptables =
172 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES;
175 if (tb[IFLA_BR_STP_STATE]) {
176 bi->b_stp_state =
nla_get_u32(tb[IFLA_BR_STP_STATE]);
177 bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
180 if (tb[IFLA_BR_MCAST_ROUTER]) {
181 bi->b_mcast_router =
nla_get_u8(tb[IFLA_BR_MCAST_ROUTER]);
182 bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
185 if (tb[IFLA_BR_MCAST_SNOOPING]) {
186 bi->b_mcast_snooping =
nla_get_u8(tb[IFLA_BR_MCAST_SNOOPING]);
187 bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
190 if (tb[IFLA_BR_MULTI_BOOLOPT]) {
191 nla_memcpy(&bi->b_boolopts, tb[IFLA_BR_MULTI_BOOLOPT],
192 sizeof(bi->b_boolopts));
193 bi->ce_mask |= BRIDGE_ATTR_BOOLOPT;
199static int bridge_info_put_attrs(
struct nl_msg *msg,
struct rtnl_link *link)
208 if (bi->ce_mask & BRIDGE_ATTR_AGEING_TIME)
209 NLA_PUT_U32(msg, IFLA_BR_AGEING_TIME, bi->b_ageing_time);
211 if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)
212 NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, bi->b_vlan_filtering);
214 if (bi->ce_mask & BRIDGE_ATTR_VLAN_DEFAULT_PVID)
216 bi->b_vlan_default_pvid);
218 if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)
220 htons(bi->b_vlan_protocol));
222 if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)
224 bi->b_vlan_stats_enabled);
226 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_IPTABLES)
228 bi->b_nf_call_iptables);
230 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_IP6TABLES)
232 bi->b_nf_call_ip6tables);
234 if (bi->ce_mask & BRIDGE_ATTR_NF_CALL_ARPTABLES)
236 bi->b_nf_call_arptables);
238 if (bi->ce_mask & BRIDGE_ATTR_STP_STATE)
239 NLA_PUT_U32(msg, IFLA_BR_STP_STATE, bi->b_stp_state);
241 if (bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER)
242 NLA_PUT_U8(msg, IFLA_BR_MCAST_ROUTER, bi->b_mcast_router);
244 if (bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING)
245 NLA_PUT_U8(msg, IFLA_BR_MCAST_SNOOPING, bi->b_mcast_snooping);
247 if (bi->ce_mask & BRIDGE_ATTR_BOOLOPT)
248 NLA_PUT(msg, IFLA_BR_MULTI_BOOLOPT,
sizeof(bi->b_boolopts),
259static void bridge_info_free(
struct rtnl_link *link)
261 _nl_clear_free(&link->l_info);
264static int bridge_info_compare(
struct rtnl_link *link_a,
269 uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0u;
272#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
273 diff |= _DIFF(BRIDGE_ATTR_VLAN_FILTERING,
274 a->b_vlan_filtering != b->b_vlan_filtering);
275 diff |= _DIFF(BRIDGE_ATTR_VLAN_PROTOCOL,
276 a->b_vlan_protocol != b->b_vlan_protocol);
277 diff |= _DIFF(BRIDGE_ATTR_VLAN_STATS_ENABLED,
278 a->b_vlan_stats_enabled != b->b_vlan_stats_enabled);
279 diff |= _DIFF(BRIDGE_ATTR_AGEING_TIME,
280 a->b_ageing_time != b->b_ageing_time);
281 diff |= _DIFF(BRIDGE_ATTR_VLAN_DEFAULT_PVID,
282 a->b_vlan_default_pvid != b->b_vlan_default_pvid);
283 diff |= _DIFF(BRIDGE_ATTR_NF_CALL_IPTABLES,
284 a->b_nf_call_iptables != b->b_nf_call_iptables);
285 diff |= _DIFF(BRIDGE_ATTR_NF_CALL_IP6TABLES,
286 a->b_nf_call_ip6tables != b->b_nf_call_ip6tables);
287 diff |= _DIFF(BRIDGE_ATTR_NF_CALL_ARPTABLES,
288 a->b_nf_call_arptables != b->b_nf_call_arptables);
289 diff |= _DIFF(BRIDGE_ATTR_STP_STATE, a->b_stp_state != b->b_stp_state);
290 diff |= _DIFF(BRIDGE_ATTR_MCAST_ROUTER,
291 a->b_mcast_router != b->b_mcast_router);
292 diff |= _DIFF(BRIDGE_ATTR_MCAST_SNOOPING,
293 a->b_mcast_snooping != b->b_mcast_snooping);
295 if (flags & LOOSE_COMPARISON)
298 (b->b_boolopts.optmask & ~a->b_boolopts.optmask) ||
299 ((a->b_boolopts.optval ^ b->b_boolopts.optval) &
300 b->b_boolopts.optmask));
304 (a->b_boolopts.optmask != b->b_boolopts.optmask) ||
305 (a->b_boolopts.optval != b->b_boolopts.optval));
313 .io_alloc = bridge_info_alloc,
314 .io_clone = bridge_info_clone,
315 .io_parse = bridge_info_parse,
316 .io_put_attrs = bridge_info_put_attrs,
317 .io_free = bridge_info_free,
318 .io_compare = bridge_info_compare,
321#define IS_BRIDGE_INFO_ASSERT(link) \
323 if ((link)->l_info_ops != &bridge_info_ops) { \
324 APPBUG("Link is not a bridge link. Set type \"bridge\" first."); \
338 uint32_t ageing_time)
342 IS_BRIDGE_INFO_ASSERT(link);
344 bi->b_ageing_time = ageing_time;
346 bi->ce_mask |= BRIDGE_ATTR_AGEING_TIME;
360 uint32_t *ageing_time)
364 IS_BRIDGE_INFO_ASSERT(link);
366 if (!(bi->ce_mask & BRIDGE_ATTR_AGEING_TIME))
372 *ageing_time = bi->b_ageing_time;
387 uint8_t vlan_filtering)
391 IS_BRIDGE_INFO_ASSERT(link);
393 bi->b_vlan_filtering = vlan_filtering;
395 bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
410 uint8_t *vlan_filtering)
414 IS_BRIDGE_INFO_ASSERT(link);
416 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING))
422 *vlan_filtering = bi->b_vlan_filtering;
437 uint16_t vlan_protocol)
441 IS_BRIDGE_INFO_ASSERT(link);
443 bi->b_vlan_protocol = vlan_protocol;
445 bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
460 uint16_t *vlan_protocol)
464 IS_BRIDGE_INFO_ASSERT(link);
466 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL))
472 *vlan_protocol = bi->b_vlan_protocol;
487 uint16_t default_pvid)
491 IS_BRIDGE_INFO_ASSERT(link);
493 bi->b_vlan_default_pvid = default_pvid;
495 bi->ce_mask |= BRIDGE_ATTR_VLAN_DEFAULT_PVID;
510 uint16_t *default_pvid)
514 IS_BRIDGE_INFO_ASSERT(link);
516 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_DEFAULT_PVID))
522 *default_pvid = bi->b_vlan_default_pvid;
537 uint8_t vlan_stats_enabled)
541 IS_BRIDGE_INFO_ASSERT(link);
543 bi->b_vlan_stats_enabled = vlan_stats_enabled;
545 bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
560 uint8_t *vlan_stats_enabled)
564 IS_BRIDGE_INFO_ASSERT(link);
566 if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED))
569 if (!vlan_stats_enabled)
572 *vlan_stats_enabled = bi->b_vlan_stats_enabled;
587 uint8_t call_enabled)
591 IS_BRIDGE_INFO_ASSERT(link);
593 bi->b_nf_call_iptables = call_enabled;
595 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IPTABLES;
610 uint8_t *call_enabled)
614 IS_BRIDGE_INFO_ASSERT(link);
616 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IPTABLES))
622 *call_enabled = bi->b_nf_call_iptables;
637 uint8_t call_enabled)
641 IS_BRIDGE_INFO_ASSERT(link);
643 bi->b_nf_call_ip6tables = call_enabled;
645 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_IP6TABLES;
660 uint8_t *call_enabled)
664 IS_BRIDGE_INFO_ASSERT(link);
666 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_IP6TABLES))
672 *call_enabled = bi->b_nf_call_ip6tables;
687 uint8_t call_enabled)
691 IS_BRIDGE_INFO_ASSERT(link);
693 bi->b_nf_call_arptables = call_enabled;
695 bi->ce_mask |= BRIDGE_ATTR_NF_CALL_ARPTABLES;
710 uint8_t *call_enabled)
714 IS_BRIDGE_INFO_ASSERT(link);
716 if (!(bi->ce_mask & BRIDGE_ATTR_NF_CALL_ARPTABLES))
722 *call_enabled = bi->b_nf_call_arptables;
740 IS_BRIDGE_INFO_ASSERT(link);
742 bi->b_stp_state = stp_state;
744 bi->ce_mask |= BRIDGE_ATTR_STP_STATE;
762 IS_BRIDGE_INFO_ASSERT(link);
764 if (!(bi->ce_mask & BRIDGE_ATTR_STP_STATE))
770 *stp_state = bi->b_stp_state;
787 IS_BRIDGE_INFO_ASSERT(link);
789 bi->b_mcast_router = type;
791 bi->ce_mask |= BRIDGE_ATTR_MCAST_ROUTER;
809 IS_BRIDGE_INFO_ASSERT(link);
811 if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_ROUTER))
817 *type = bi->b_mcast_router;
834 IS_BRIDGE_INFO_ASSERT(link);
836 bi->b_mcast_snooping = value;
838 bi->ce_mask |= BRIDGE_ATTR_MCAST_SNOOPING;
856 IS_BRIDGE_INFO_ASSERT(link);
858 if (!(bi->ce_mask & BRIDGE_ATTR_MCAST_SNOOPING))
864 *value = bi->b_mcast_snooping;
884 IS_BRIDGE_INFO_ASSERT(link);
886 if (opt < 0 || opt >= 32 || !(value == 0 || value == 1))
892 bi->b_boolopts.optval |= mask;
894 bi->b_boolopts.optval &= ~mask;
896 bi->b_boolopts.optmask |= mask;
897 bi->ce_mask |= BRIDGE_ATTR_BOOLOPT;
918 IS_BRIDGE_INFO_ASSERT(link);
920 if (opt < 0 || opt >= 32)
925 if (!(bi->ce_mask & BRIDGE_ATTR_BOOLOPT) ||
926 !(bi->b_boolopts.optmask & mask))
929 return !!(bi->b_boolopts.optval & mask);
932static void _nl_init bridge_info_init(
void)
937static void _nl_exit bridge_info_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.
#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.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
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.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int rtnl_link_bridge_get_nf_call_arptables(struct rtnl_link *link, uint8_t *call_enabled)
Get call enabled flag for passing ARP traffic to arptables.
void rtnl_link_bridge_set_stp_state(struct rtnl_link *link, uint32_t stp_state)
Set STP state.
int rtnl_link_bridge_get_vlan_default_pvid(struct rtnl_link *link, uint16_t *default_pvid)
Get VLAN default pvid.
int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link, uint16_t *vlan_protocol)
Get VLAN protocol.
void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link, uint8_t vlan_stats_enabled)
Set VLAN stats enabled flag.
void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link, uint8_t vlan_filtering)
Set VLAN filtering flag.
void rtnl_link_bridge_set_mcast_snooping(struct rtnl_link *link, uint8_t value)
Set multicast snooping.
int rtnl_link_bridge_get_stp_state(struct rtnl_link *link, uint32_t *stp_state)
Get STP state.
int rtnl_link_bridge_get_ageing_time(struct rtnl_link *link, uint32_t *ageing_time)
Get ageing time for dynamic forwarding entries.
int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link, uint8_t *vlan_filtering)
Get VLAN filtering flag.
void rtnl_link_bridge_set_mcast_router(struct rtnl_link *link, uint8_t type)
Set multicast router type.
void rtnl_link_bridge_set_nf_call_iptables(struct rtnl_link *link, uint8_t call_enabled)
Set call enabled flag for passing IPv4 traffic to iptables.
int rtnl_link_bridge_get_mcast_snooping(struct rtnl_link *link, uint8_t *value)
Get multicast snooping value.
void rtnl_link_bridge_set_ageing_time(struct rtnl_link *link, uint32_t ageing_time)
Set ageing time for dynamic forwarding entries.
int rtnl_link_bridge_get_boolopt(struct rtnl_link *link, int opt)
Get the value of a boolopt.
void rtnl_link_bridge_set_nf_call_arptables(struct rtnl_link *link, uint8_t call_enabled)
Set call enabled flag for passing ARP traffic to arptables.
int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, uint8_t *vlan_stats_enabled)
Get VLAN stats enabled flag.
int rtnl_link_bridge_set_boolopt(struct rtnl_link *link, int opt, int value)
Set a the value of a boolopt.
void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link, uint16_t vlan_protocol)
Set VLAN protocol.
int rtnl_link_bridge_get_mcast_router(struct rtnl_link *link, uint8_t *type)
Get multicast router type.
int rtnl_link_bridge_get_nf_call_iptables(struct rtnl_link *link, uint8_t *call_enabled)
Get call enabled flag for passing IPv4 traffic to iptables.
void rtnl_link_bridge_set_nf_call_ip6tables(struct rtnl_link *link, uint8_t call_enabled)
Set call enabled flag for passing IPv6 traffic to ip6tables.
int rtnl_link_bridge_get_nf_call_ip6tables(struct rtnl_link *link, uint8_t *call_enabled)
Get call enabled flag for passing IPv6 traffic to iptables.
void rtnl_link_bridge_set_vlan_default_pvid(struct rtnl_link *link, uint16_t default_pvid)
Set VLAN default pvid.
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
Attribute validation policy.
Available operations to modules implementing a link info type.