Commit 7a53e718 authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller

net: bridge: vlan: add basic option dumping support

We'll be dumping the options for the whole range if they're equal. The
first range vlan will be used to extract the options. The commit doesn't
change anything yet it just adds the skeleton for the support. The dump
will happen when the first option is added.
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ac0e932d
...@@ -20,7 +20,7 @@ obj-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o ...@@ -20,7 +20,7 @@ obj-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o
bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o
bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o br_vlan_tunnel.o bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o br_vlan_tunnel.o br_vlan_options.o
bridge-$(CONFIG_NET_SWITCHDEV) += br_switchdev.o bridge-$(CONFIG_NET_SWITCHDEV) += br_switchdev.o
......
...@@ -1191,6 +1191,14 @@ static inline void br_vlan_notify(const struct net_bridge *br, ...@@ -1191,6 +1191,14 @@ static inline void br_vlan_notify(const struct net_bridge *br,
} }
#endif #endif
/* br_vlan_options.c */
#ifdef CONFIG_BRIDGE_VLAN_FILTERING
bool br_vlan_opts_eq(const struct net_bridge_vlan *v1,
const struct net_bridge_vlan *v2);
bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v);
size_t br_vlan_opts_nl_size(void);
#endif
struct nf_br_ops { struct nf_br_ops {
int (*br_dev_xmit_hook)(struct sk_buff *skb); int (*br_dev_xmit_hook)(struct sk_buff *skb);
}; };
......
...@@ -1547,7 +1547,9 @@ void br_vlan_port_event(struct net_bridge_port *p, unsigned long event) ...@@ -1547,7 +1547,9 @@ void br_vlan_port_event(struct net_bridge_port *p, unsigned long event)
} }
} }
/* v_opts is used to dump the options which must be equal in the whole range */
static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range, static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range,
const struct net_bridge_vlan *v_opts,
u16 flags) u16 flags)
{ {
struct bridge_vlan_info info; struct bridge_vlan_info info;
...@@ -1572,6 +1574,9 @@ static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range, ...@@ -1572,6 +1574,9 @@ static bool br_vlan_fill_vids(struct sk_buff *skb, u16 vid, u16 vid_range,
nla_put_u16(skb, BRIDGE_VLANDB_ENTRY_RANGE, vid_range)) nla_put_u16(skb, BRIDGE_VLANDB_ENTRY_RANGE, vid_range))
goto out_err; goto out_err;
if (v_opts && !br_vlan_opts_fill(skb, v_opts))
goto out_err;
nla_nest_end(skb, nest); nla_nest_end(skb, nest);
return true; return true;
...@@ -1586,7 +1591,8 @@ static size_t rtnl_vlan_nlmsg_size(void) ...@@ -1586,7 +1591,8 @@ static size_t rtnl_vlan_nlmsg_size(void)
return NLMSG_ALIGN(sizeof(struct br_vlan_msg)) return NLMSG_ALIGN(sizeof(struct br_vlan_msg))
+ nla_total_size(0) /* BRIDGE_VLANDB_ENTRY */ + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY */
+ nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_ENTRY_RANGE */ + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_ENTRY_RANGE */
+ nla_total_size(sizeof(struct bridge_vlan_info)); /* BRIDGE_VLANDB_ENTRY_INFO */ + nla_total_size(sizeof(struct bridge_vlan_info)) /* BRIDGE_VLANDB_ENTRY_INFO */
+ br_vlan_opts_nl_size(); /* bridge vlan options */
} }
void br_vlan_notify(const struct net_bridge *br, void br_vlan_notify(const struct net_bridge *br,
...@@ -1595,7 +1601,7 @@ void br_vlan_notify(const struct net_bridge *br, ...@@ -1595,7 +1601,7 @@ void br_vlan_notify(const struct net_bridge *br,
int cmd) int cmd)
{ {
struct net_bridge_vlan_group *vg; struct net_bridge_vlan_group *vg;
struct net_bridge_vlan *v; struct net_bridge_vlan *v = NULL;
struct br_vlan_msg *bvm; struct br_vlan_msg *bvm;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1647,7 +1653,7 @@ void br_vlan_notify(const struct net_bridge *br, ...@@ -1647,7 +1653,7 @@ void br_vlan_notify(const struct net_bridge *br,
goto out_kfree; goto out_kfree;
} }
if (!br_vlan_fill_vids(skb, vid, vid_range, flags)) if (!br_vlan_fill_vids(skb, vid, vid_range, v, flags))
goto out_err; goto out_err;
nlmsg_end(skb, nlh); nlmsg_end(skb, nlh);
...@@ -1665,7 +1671,8 @@ static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr, ...@@ -1665,7 +1671,8 @@ static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
const struct net_bridge_vlan *range_end) const struct net_bridge_vlan *range_end)
{ {
return v_curr->vid - range_end->vid == 1 && return v_curr->vid - range_end->vid == 1 &&
range_end->flags == v_curr->flags; range_end->flags == v_curr->flags &&
br_vlan_opts_eq(v_curr, range_end);
} }
static int br_vlan_dump_dev(const struct net_device *dev, static int br_vlan_dump_dev(const struct net_device *dev,
...@@ -1729,7 +1736,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, ...@@ -1729,7 +1736,8 @@ static int br_vlan_dump_dev(const struct net_device *dev,
u16 flags = br_vlan_flags(range_start, pvid); u16 flags = br_vlan_flags(range_start, pvid);
if (!br_vlan_fill_vids(skb, range_start->vid, if (!br_vlan_fill_vids(skb, range_start->vid,
range_end->vid, flags)) { range_end->vid, range_start,
flags)) {
err = -EMSGSIZE; err = -EMSGSIZE;
break; break;
} }
...@@ -1748,7 +1756,7 @@ static int br_vlan_dump_dev(const struct net_device *dev, ...@@ -1748,7 +1756,7 @@ static int br_vlan_dump_dev(const struct net_device *dev,
*/ */
if (!err && range_start && if (!err && range_start &&
!br_vlan_fill_vids(skb, range_start->vid, range_end->vid, !br_vlan_fill_vids(skb, range_start->vid, range_end->vid,
br_vlan_flags(range_start, pvid))) range_start, br_vlan_flags(range_start, pvid)))
err = -EMSGSIZE; err = -EMSGSIZE;
cb->args[1] = err ? idx : 0; cb->args[1] = err ? idx : 0;
......
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2020, Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <linux/slab.h>
#include "br_private.h"
/* check if the options between two vlans are equal */
bool br_vlan_opts_eq(const struct net_bridge_vlan *v1,
const struct net_bridge_vlan *v2)
{
return true;
}
bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v)
{
return true;
}
size_t br_vlan_opts_nl_size(void)
{
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment