[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