All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: davem@davemloft.net, netdev@vger.kernel.org, kuba@kernel.org
Subject: [PATCH net-next,v2 04/24] net: bridge: resolve forwarding path for VLAN tag actions in bridge devices
Date: Wed, 24 Mar 2021 02:30:35 +0100	[thread overview]
Message-ID: <20210324013055.5619-5-pablo@netfilter.org> (raw)
In-Reply-To: <20210324013055.5619-1-pablo@netfilter.org>

From: Felix Fietkau <nbd@nbd.name>

Depending on the VLAN settings of the bridge and the port, the bridge can
either add or remove a tag. When vlan filtering is enabled, the fdb lookup
also needs to know the VLAN tag/proto for the destination address
To provide this, keep track of the stack of VLAN tags for the path in the
lookup context

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v2: no changes.

 include/linux/netdevice.h | 16 ++++++++++++
 net/8021q/vlan_dev.c      |  6 +++++
 net/bridge/br_device.c    | 23 ++++++++++++++++-
 net/bridge/br_private.h   | 20 +++++++++++++++
 net/bridge/br_vlan.c      | 53 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index b8b6927e04fc..ad67f26c77d8 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -862,10 +862,20 @@ struct net_device_path {
 			u16		id;
 			__be16		proto;
 		} encap;
+		struct {
+			enum {
+				DEV_PATH_BR_VLAN_KEEP,
+				DEV_PATH_BR_VLAN_TAG,
+				DEV_PATH_BR_VLAN_UNTAG,
+			}		vlan_mode;
+			u16		vlan_id;
+			__be16		vlan_proto;
+		} bridge;
 	};
 };
 
 #define NET_DEVICE_PATH_STACK_MAX	5
+#define NET_DEVICE_PATH_VLAN_MAX	2
 
 struct net_device_path_stack {
 	int			num_paths;
@@ -875,6 +885,12 @@ struct net_device_path_stack {
 struct net_device_path_ctx {
 	const struct net_device *dev;
 	const u8		*daddr;
+
+	int			num_vlans;
+	struct {
+		u16		id;
+		__be16		proto;
+	} vlan[NET_DEVICE_PATH_VLAN_MAX];
 };
 
 enum tc_setup_type {
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 1b1955a63f7f..4db3f0621959 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -786,6 +786,12 @@ static int vlan_dev_fill_forward_path(struct net_device_path_ctx *ctx,
 	path->encap.proto = vlan->vlan_proto;
 	path->dev = ctx->dev;
 	ctx->dev = vlan->real_dev;
+	if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan))
+		return -ENOSPC;
+
+	ctx->vlan[ctx->num_vlans].id = vlan->vlan_id;
+	ctx->vlan[ctx->num_vlans].proto = vlan->vlan_proto;
+	ctx->num_vlans++;
 
 	return 0;
 }
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index c241719013f4..0c72503e0d39 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -396,7 +396,10 @@ static int br_fill_forward_path(struct net_device_path_ctx *ctx,
 		return -1;
 
 	br = netdev_priv(ctx->dev);
-	f = br_fdb_find_rcu(br, ctx->daddr, 0);
+
+	br_vlan_fill_forward_path_pvid(br, ctx, path);
+
+	f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id);
 	if (!f || !f->dst)
 		return -1;
 
@@ -404,10 +407,28 @@ static int br_fill_forward_path(struct net_device_path_ctx *ctx,
 	if (!dst)
 		return -1;
 
+	if (br_vlan_fill_forward_path_mode(br, dst, path))
+		return -1;
+
 	path->type = DEV_PATH_BRIDGE;
 	path->dev = dst->br->dev;
 	ctx->dev = dst->dev;
 
+	switch (path->bridge.vlan_mode) {
+	case DEV_PATH_BR_VLAN_TAG:
+		if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan))
+			return -ENOSPC;
+		ctx->vlan[ctx->num_vlans].id = path->bridge.vlan_id;
+		ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
+		ctx->num_vlans++;
+		break;
+	case DEV_PATH_BR_VLAN_UNTAG:
+		ctx->num_vlans--;
+		break;
+	case DEV_PATH_BR_VLAN_KEEP:
+		break;
+	}
+
 	return 0;
 }
 
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d7d167e10b70..50747990188e 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1118,6 +1118,13 @@ void br_vlan_notify(const struct net_bridge *br,
 bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
 			     const struct net_bridge_vlan *range_end);
 
+void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+				    struct net_device_path_ctx *ctx,
+				    struct net_device_path *path);
+int br_vlan_fill_forward_path_mode(struct net_bridge *br,
+				   struct net_bridge_port *dst,
+				   struct net_device_path *path);
+
 static inline struct net_bridge_vlan_group *br_vlan_group(
 					const struct net_bridge *br)
 {
@@ -1277,6 +1284,19 @@ static inline int nbp_get_num_vlan_infos(struct net_bridge_port *p,
 	return 0;
 }
 
+static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+						  struct net_device_path_ctx *ctx,
+						  struct net_device_path *path)
+{
+}
+
+static inline int br_vlan_fill_forward_path_mode(struct net_bridge *br,
+						 struct net_bridge_port *dst,
+						 struct net_device_path *path)
+{
+	return 0;
+}
+
 static inline struct net_bridge_vlan_group *br_vlan_group(
 					const struct net_bridge *br)
 {
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 8829f621b8ec..0d09d3745e52 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1339,6 +1339,59 @@ int br_vlan_get_pvid_rcu(const struct net_device *dev, u16 *p_pvid)
 }
 EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu);
 
+void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
+				    struct net_device_path_ctx *ctx,
+				    struct net_device_path *path)
+{
+	struct net_bridge_vlan_group *vg;
+	int idx = ctx->num_vlans - 1;
+	u16 vid;
+
+	path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
+
+	if (!br_opt_get(br, BROPT_VLAN_ENABLED))
+		return;
+
+	vg = br_vlan_group(br);
+
+	if (idx >= 0 &&
+	    ctx->vlan[idx].proto == br->vlan_proto) {
+		vid = ctx->vlan[idx].id;
+	} else {
+		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_TAG;
+		vid = br_get_pvid(vg);
+	}
+
+	path->bridge.vlan_id = vid;
+	path->bridge.vlan_proto = br->vlan_proto;
+}
+
+int br_vlan_fill_forward_path_mode(struct net_bridge *br,
+				   struct net_bridge_port *dst,
+				   struct net_device_path *path)
+{
+	struct net_bridge_vlan_group *vg;
+	struct net_bridge_vlan *v;
+
+	if (!br_opt_get(br, BROPT_VLAN_ENABLED))
+		return 0;
+
+	vg = nbp_vlan_group_rcu(dst);
+	v = br_vlan_find(vg, path->bridge.vlan_id);
+	if (!v || !br_vlan_should_use(v))
+		return -EINVAL;
+
+	if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED))
+		return 0;
+
+	if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
+		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
+	else
+		path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
+
+	return 0;
+}
+
 int br_vlan_get_info(const struct net_device *dev, u16 vid,
 		     struct bridge_vlan_info *p_vinfo)
 {
-- 
2.20.1


  parent reply	other threads:[~2021-03-24  1:32 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-24  1:30 [PATCH net-next,v2 00/24] netfilter: flowtable enhancements Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 01/24] net: resolve forwarding path from virtual netdevice and HW destination address Pablo Neira Ayuso
2021-03-24  7:27   ` DENG Qingfang
2021-03-24 10:03     ` Pablo Neira Ayuso
2021-03-24 16:07       ` DENG Qingfang
2021-03-24 19:15         ` Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 02/24] net: 8021q: resolve forwarding path for vlan devices Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 03/24] net: bridge: resolve forwarding path for bridge devices Pablo Neira Ayuso
2021-03-24  1:30 ` Pablo Neira Ayuso [this message]
2021-03-24  1:30 ` [PATCH net-next,v2 05/24] net: ppp: resolve forwarding path for bridge pppoe devices Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 06/24] net: dsa: resolve forwarding path for dsa slave ports Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 07/24] netfilter: flowtable: add xmit path types Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 08/24] netfilter: flowtable: use dev_fill_forward_path() to obtain ingress device Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 09/24] netfilter: flowtable: use dev_fill_forward_path() to obtain egress device Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 10/24] netfilter: flowtable: add vlan support Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 11/24] netfilter: flowtable: add bridge vlan filtering support Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 12/24] netfilter: flowtable: add pppoe support Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 13/24] netfilter: flowtable: add dsa support Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 14/24] selftests: netfilter: flowtable bridge and vlan support Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 15/24] netfilter: flowtable: add offload support for xmit path types Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 16/24] netfilter: nft_flow_offload: use direct xmit if hardware offload is enabled Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 17/24] netfilter: flowtable: bridge vlan hardware offload and switchdev Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 18/24] net: flow_offload: add FLOW_ACTION_PPPOE_PUSH Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 19/24] netfilter: flowtable: support for FLOW_ACTION_PPPOE_PUSH Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 20/24] dsa: slave: add support for TC_SETUP_FT Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 21/24] net: ethernet: mtk_eth_soc: fix parsing packets in GDM Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 22/24] net: ethernet: mtk_eth_soc: add support for initializing the PPE Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 23/24] net: ethernet: mtk_eth_soc: add flow offloading support Pablo Neira Ayuso
2021-03-24  1:30 ` [PATCH net-next,v2 24/24] docs: nf_flowtable: update documentation with enhancements Pablo Neira Ayuso
2021-03-24 20:00 ` [PATCH net-next,v2 00/24] netfilter: flowtable enhancements patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210324013055.5619-5-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=davem@davemloft.net \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.