6c945fa379
Removed upstreamed: bcm53xx/patches-5.10/033-v5.16-0024-ARM-dts-BCM5301X-Fix-I2C-controller-interrupt.patch[1] bcm53xx/patches-5.10/033-v5.16-0025-ARM-dts-BCM5301X-Add-interrupt-properties-to-GPIO-no.patch[2] All other patches automatically rebased. 1. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.10.83&id=b2cd6fdcbe0a5cb44e4610a08cc58261d494a885 2. https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.10.83&id=9db1d4a3c2700e1cc84c3d61199411d75c2a3ec6 Build system: x86_64* Build-tested: bcm2711/RPi4B, ipq806x/R7800† Run-tested: bcm2711/RPi4B, ipq806x/R7800† * Had to revert7c99085bd6
in order to build (latest bump of ca-certificates) † Had to revert7f1edbd412
in order to build (binutils 2.37, https://bugs.openwrt.org/index.php?do=details&task_id=4149) Signed-off-by: John Audia <graysky@archlinux.us>
208 lines
5.3 KiB
Diff
208 lines
5.3 KiB
Diff
From: Felix Fietkau <nbd@nbd.name>
|
|
Date: Wed, 24 Mar 2021 02:30:35 +0100
|
|
Subject: [PATCH] net: bridge: resolve forwarding path for VLAN tag
|
|
actions in bridge devices
|
|
|
|
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>
|
|
---
|
|
|
|
--- a/include/linux/netdevice.h
|
|
+++ b/include/linux/netdevice.h
|
|
@@ -841,10 +841,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;
|
|
@@ -854,6 +864,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 {
|
|
--- a/net/8021q/vlan_dev.c
|
|
+++ b/net/8021q/vlan_dev.c
|
|
@@ -780,6 +780,12 @@ static int vlan_dev_fill_forward_path(st
|
|
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;
|
|
}
|
|
--- a/net/bridge/br_device.c
|
|
+++ b/net/bridge/br_device.c
|
|
@@ -409,7 +409,10 @@ static int br_fill_forward_path(struct n
|
|
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;
|
|
|
|
@@ -417,10 +420,28 @@ static int br_fill_forward_path(struct n
|
|
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;
|
|
}
|
|
|
|
--- a/net/bridge/br_private.h
|
|
+++ b/net/bridge/br_private.h
|
|
@@ -1093,6 +1093,13 @@ void br_vlan_notify(const struct net_bri
|
|
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)
|
|
{
|
|
@@ -1250,6 +1257,19 @@ static inline int nbp_get_num_vlan_infos
|
|
{
|
|
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)
|
|
--- a/net/bridge/br_vlan.c
|
|
+++ b/net/bridge/br_vlan.c
|
|
@@ -1327,6 +1327,59 @@ int br_vlan_get_pvid_rcu(const struct ne
|
|
}
|
|
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)
|
|
{
|