diff options
author | Robert Dabrowski <rdabrowski@maxlinear.com> | 2022-03-02 09:37:06 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-08-24 17:47:20 (GMT) |
commit | 08dc5d9c40e1cecca5f3a0aec05a077053ebdf24 (patch) | |
tree | ef20e1dc5f4f143116d5b183f99dd5b8e28af443 | |
parent | 7391a38e3d5edc5aac11c9d2fa0bf5ca67655bdb (diff) | |
download | libnl-08dc5d9c40e1cecca5f3a0aec05a077053ebdf24.zip libnl-08dc5d9c40e1cecca5f3a0aec05a077053ebdf24.tar.gz libnl-08dc5d9c40e1cecca5f3a0aec05a077053ebdf24.tar.bz2 |
bridge: extend libnl with options needed for VLAN aware forwarding
Signed-off-by: Robert Dabrowski <rdabrowski@maxlinear.com>
Co-Authored-By: Kacper Ludwinski <kludwinski@maxlinear.com>
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | include/netlink/route/link/bridge_info.h | 35 | ||||
-rw-r--r-- | lib/route/link/bridge_info.c | 193 | ||||
-rw-r--r-- | libnl-route-3.sym | 10 |
4 files changed, 238 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index 7f9cd56..0ac63d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -148,6 +148,7 @@ libnlinclude_netlink_route_linkdir = $(libnlincludedir)/netlink/route/link libnlinclude_netlink_route_link_HEADERS = \ include/netlink/route/link/api.h \ include/netlink/route/link/bonding.h \ + include/netlink/route/link/bridge_info.h \ include/netlink/route/link/bridge.h \ include/netlink/route/link/can.h \ include/netlink/route/link/geneve.h \ diff --git a/include/netlink/route/link/bridge_info.h b/include/netlink/route/link/bridge_info.h new file mode 100644 index 0000000..461144a --- /dev/null +++ b/include/netlink/route/link/bridge_info.h @@ -0,0 +1,35 @@ +/* + * netlink/route/link/bridge_info.h Bridge Info + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * Copyright (c) 2022 MaxLinear, Inc. + */ + +#ifndef NETLINK_LINK_BRIDGE_INFO_H_ +#define NETLINK_LINK_BRIDGE_INFO_H_ + +#include <netlink/netlink.h> +#include <netlink/route/link.h> + +#ifdef __cplusplus +extern "C" { +#endif + +extern void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link, uint8_t vlan_filtering); +extern int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link, uint8_t *vlan_filtering); + +extern void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link, uint16_t vlan_protocol); +extern int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link, uint16_t *vlan_protocol); + +extern void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link, uint8_t vlan_stats_enabled); +extern int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, uint8_t *vlan_stats_enabled); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c index 5662b17..eee5a7c 100644 --- a/lib/route/link/bridge_info.c +++ b/lib/route/link/bridge_info.c @@ -18,15 +18,25 @@ */ #include <netlink-private/netlink.h> +#include <netlink/route/link/bridge_info.h> #include <netlink-private/route/link/api.h> +#define BRIDGE_ATTR_VLAN_FILTERING (1 << 2) +#define BRIDGE_ATTR_VLAN_PROTOCOL (1 << 3) +#define BRIDGE_ATTR_VLAN_STATS_ENABLED (1 << 4) + struct bridge_info { + uint8_t b_vlan_filtering; + uint16_t b_vlan_protocol; + uint8_t b_vlan_stats_enabled; uint32_t ce_mask; /* to support attr macros */ }; static struct nla_policy bi_attrs_policy[IFLA_BR_MAX+1] = { - + [IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 }, + [IFLA_BR_VLAN_PROTOCOL] = { .type = NLA_U16 }, + [IFLA_BR_VLAN_STATS_ENABLED] = { .type = NLA_U8 }, }; static inline struct bridge_info *bridge_info(struct rtnl_link *link) @@ -68,6 +78,24 @@ static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data, bi = link->l_info; + if (tb[IFLA_BR_VLAN_FILTERING]) { + bi->b_vlan_filtering = + nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]); + bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING; + } + + if (tb[IFLA_BR_VLAN_PROTOCOL]) { + bi->b_vlan_protocol = + nla_get_u8(tb[IFLA_BR_VLAN_PROTOCOL]); + bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL; + } + + if (tb[IFLA_BR_VLAN_STATS_ENABLED]) { + bi->b_vlan_stats_enabled = + nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]); + bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED; + } + errout: return err; } @@ -81,8 +109,24 @@ static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link) if (!data) return -NLE_MSGSIZE; + if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING) + NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, + bi->b_vlan_filtering); + + if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL) + NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL, + bi->b_vlan_protocol); + + if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED) + NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED, + bi->b_vlan_stats_enabled); + nla_nest_end(msg, data); return 0; + + nla_put_failure: + nla_nest_cancel(msg, data); + return -NLE_MSGSIZE; } static void bridge_info_free(struct rtnl_link *link) @@ -106,6 +150,153 @@ static struct rtnl_link_info_ops bridge_info_ops = { } \ } while(0) +/** + * Set VLAN filtering flag + * @arg link Link object of type bridge + * @arg vlan_filtering VLAN_filtering boolean flag to set. + * + * @see rtnl_link_bridge_get_vlan_filtering() + * + * @return void + */ +void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link, + uint8_t vlan_filtering) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_vlan_filtering = !!vlan_filtering; + + bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING; +} + +/** + * Get VLAN filtering flag + * @arg link Link object of type bridge + * @arg vlan_filtering Output argument. + * + * @see rtnl_link_bridge_set_vlan_filtering() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link, uint8_t *vlan_filtering) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)) + return -NLE_NOATTR; + + if (!vlan_filtering) + return -NLE_INVAL; + + *vlan_filtering = bi->b_vlan_filtering; + return 0; +} + +/** + * Set VLAN protocol + * @arg link Link object of type bridge + * @arg vlan_protocol VLAN protocol to set. + * + * @see rtnl_link_bridge_get_vlan_protocol() + * + * @return void + */ +void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link, + uint16_t vlan_protocol) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_vlan_protocol = vlan_protocol; + + bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL; +} + +/** + * Get VLAN protocol + * @arg link Link object of type bridge + * @arg vlan_protocol Output argument. + * + * @see rtnl_link_bridge_set_vlan_protocol() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link, + uint16_t *vlan_protocol) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)) + return -NLE_NOATTR; + + if (!vlan_protocol) + return -NLE_INVAL; + + *vlan_protocol = bi->b_vlan_protocol; + + return 0; +} + +/** + * Set VLAN stats enabled flag + * @arg link Link object of type bridge + * @arg vlan_stats_enabled VLAN stats enabled flag to set + * + * @see rtnl_link_bridge_get_vlan_stats_enabled() + * + * @return void + */ +void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link, + uint8_t vlan_stats_enabled) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + bi->b_vlan_stats_enabled = vlan_stats_enabled; + + bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED; +} + +/** + * Get VLAN stats enabled flag + * @arg link Link object of type bridge + * @arg vlan_stats_enabled Output argument. + * + * @see rtnl_link_bridge_set_vlan_stats_enabled() + * + * @return Zero on success, otherwise a negative error code. + * @retval -NLE_NOATTR + * @retval -NLE_INVAL + */ +int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link, uint8_t *vlan_stats_enabled) +{ + struct bridge_info *bi = bridge_info(link); + + IS_BRIDGE_INFO_ASSERT(link); + + if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)) + return -NLE_NOATTR; + + if (!vlan_stats_enabled) + return -NLE_INVAL; + + *vlan_stats_enabled = bi->b_vlan_stats_enabled; + + return 0; +} + static void __init bridge_info_init(void) { rtnl_link_register_info(&bridge_info_ops); diff --git a/libnl-route-3.sym b/libnl-route-3.sym index b6503b3..5e37acf 100644 --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -1274,3 +1274,13 @@ global: rtnl_nat_set_new_addr; rtnl_nat_set_old_addr; } libnl_3_6; + +libnl_3_8 { +global: + rtnl_link_bridge_get_vlan_filtering; + rtnl_link_bridge_get_vlan_protocol; + rtnl_link_bridge_get_vlan_stats_enabled; + rtnl_link_bridge_set_vlan_filtering; + rtnl_link_bridge_set_vlan_protocol; + rtnl_link_bridge_set_vlan_stats_enabled; +} libnl_3_7; |