[PATCH] route/link nested bridge attribute
David Ahern
dsa at cumulusnetworks.com
Tue Nov 24 11:44:38 PST 2015
Hi Tobias:
Someone in my company has an alternative solution to this that I
recently ported to top of tree; the patches have more functionality than
you provide here. I'll send those out today.
more below
On 11/24/15 6:50 AM, Tobias Jungel wrote:
> Modern kernels support vlan filtering on bridges. This patch stores
> configured vlan ids on bridge interfaces in struct bridge_data.
> Furthermore vlan ids are accessible via rtnl_link_bridge_get_vlan_info.
>
> The vlan ids are currently stored in the same way as they are sent from
> the kernel (i.e. in struct bridge_vlan_info).
>
> Signed-off-by: Tobias Jungel <tobias.jungel at bisdn.de>
> ---
> include/linux-private/linux/if_bridge.h | 14 +++++
> include/netlink/route/link/bridge.h | 4 ++
> lib/route/link.c | 7 ++-
> lib/route/link/bridge.c | 90 +++++++++++++++++++++++++++++----
> libnl-route-3.sym | 1 +
> 5 files changed, 106 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux-private/linux/if_bridge.h b/include/linux-private/linux/if_bridge.h
> index 5db2975..cfe7d12 100644
> --- a/include/linux-private/linux/if_bridge.h
> +++ b/include/linux-private/linux/if_bridge.h
> @@ -103,20 +103,34 @@ struct __fdb_entry {
>
> #define BRIDGE_MODE_VEB 0 /* Default loopback mode */
> #define BRIDGE_MODE_VEPA 1 /* 802.1Qbg defined VEPA mode */
> +#define BRIDGE_MODE_UNDEF 0xFFFF /* mode undefined */
>
> /* Bridge management nested attributes
> * [IFLA_AF_SPEC] = {
> * [IFLA_BRIDGE_FLAGS]
> * [IFLA_BRIDGE_MODE]
> + * [IFLA_BRIDGE_VLAN_INFO]
> * }
> */
> enum {
> IFLA_BRIDGE_FLAGS,
> IFLA_BRIDGE_MODE,
> + IFLA_BRIDGE_VLAN_INFO,
> __IFLA_BRIDGE_MAX,
> };
> #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
>
> +#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */
> +#define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */
> +#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */
> +#define BRIDGE_VLAN_INFO_RANGE_BEGIN (1<<3) /* VLAN is start of vlan range */
> +#define BRIDGE_VLAN_INFO_RANGE_END (1<<4) /* VLAN is end of vlan range */
> +
> +struct bridge_vlan_info {
> + __u16 flags;
> + __u16 vid;
> +};
> +
> /* Bridge multicast database attributes
> * [MDBA_MDB] = {
> * [MDBA_MDB_ENTRY] = {
> diff --git a/include/netlink/route/link/bridge.h b/include/netlink/route/link/bridge.h
> index 16a4505..c04a3e2 100644
> --- a/include/netlink/route/link/bridge.h
> +++ b/include/netlink/route/link/bridge.h
> @@ -14,6 +14,7 @@
>
> #include <netlink/netlink.h>
> #include <netlink/route/link.h>
> +#include <linux/if_bridge.h>
>
> #ifdef __cplusplus
> extern "C" {
> @@ -52,6 +53,9 @@ extern char * rtnl_link_bridge_flags2str(int, char *, size_t);
> extern int rtnl_link_bridge_str2flags(const char *);
>
> extern int rtnl_link_bridge_add(struct nl_sock *sk, const char *name);
> +
> +extern struct bridge_vlan_info *rtnl_link_bridge_get_vlan_info(struct rtnl_link *, int *);
> +
> #ifdef __cplusplus
> }
> #endif
> diff --git a/lib/route/link.c b/lib/route/link.c
> index cfe3779..01bd9ff 100644
> --- a/lib/route/link.c
> +++ b/lib/route/link.c
> @@ -604,6 +604,12 @@ static int link_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
> struct nlattr *af_attr;
> int remaining;
>
> + if (AF_BRIDGE == family && af_ops && af_ops->ao_parse_af) {
> + err = af_ops->ao_parse_af(link, tb[IFLA_AF_SPEC], link->l_af_data[family]);
> + if (err < 0)
> + goto errout;
> + }
> +
This is going to drop down and parse IFLA_AF_SPEC again which is not
what you want for AF_BRIDGE.
> nla_for_each_nested(af_attr, tb[IFLA_AF_SPEC], remaining) {
> af_ops = af_lookup_and_alloc(link, nla_type(af_attr));
> if (af_ops && af_ops->ao_parse_af) {
David
More information about the libnl
mailing list