1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Wed, 24 Mar 2021 02:30:35 +0100
3 Subject: [PATCH] net: bridge: resolve forwarding path for VLAN tag
4 actions in bridge devices
6 Depending on the VLAN settings of the bridge and the port, the bridge can
7 either add or remove a tag. When vlan filtering is enabled, the fdb lookup
8 also needs to know the VLAN tag/proto for the destination address
9 To provide this, keep track of the stack of VLAN tags for the path in the
12 Signed-off-by: Felix Fietkau <nbd@nbd.name>
13 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
16 --- a/include/linux/netdevice.h
17 +++ b/include/linux/netdevice.h
18 @@ -841,10 +841,20 @@ struct net_device_path {
24 + DEV_PATH_BR_VLAN_KEEP,
25 + DEV_PATH_BR_VLAN_TAG,
26 + DEV_PATH_BR_VLAN_UNTAG,
34 #define NET_DEVICE_PATH_STACK_MAX 5
35 +#define NET_DEVICE_PATH_VLAN_MAX 2
37 struct net_device_path_stack {
39 @@ -854,6 +864,12 @@ struct net_device_path_stack {
40 struct net_device_path_ctx {
41 const struct net_device *dev;
48 + } vlan[NET_DEVICE_PATH_VLAN_MAX];
52 --- a/net/8021q/vlan_dev.c
53 +++ b/net/8021q/vlan_dev.c
54 @@ -780,6 +780,12 @@ static int vlan_dev_fill_forward_path(st
55 path->encap.proto = vlan->vlan_proto;
57 ctx->dev = vlan->real_dev;
58 + if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan))
61 + ctx->vlan[ctx->num_vlans].id = vlan->vlan_id;
62 + ctx->vlan[ctx->num_vlans].proto = vlan->vlan_proto;
67 --- a/net/bridge/br_device.c
68 +++ b/net/bridge/br_device.c
69 @@ -409,7 +409,10 @@ static int br_fill_forward_path(struct n
72 br = netdev_priv(ctx->dev);
73 - f = br_fdb_find_rcu(br, ctx->daddr, 0);
75 + br_vlan_fill_forward_path_pvid(br, ctx, path);
77 + f = br_fdb_find_rcu(br, ctx->daddr, path->bridge.vlan_id);
81 @@ -417,10 +420,28 @@ static int br_fill_forward_path(struct n
85 + if (br_vlan_fill_forward_path_mode(br, dst, path))
88 path->type = DEV_PATH_BRIDGE;
89 path->dev = dst->br->dev;
92 + switch (path->bridge.vlan_mode) {
93 + case DEV_PATH_BR_VLAN_TAG:
94 + if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan))
96 + ctx->vlan[ctx->num_vlans].id = path->bridge.vlan_id;
97 + ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
100 + case DEV_PATH_BR_VLAN_UNTAG:
103 + case DEV_PATH_BR_VLAN_KEEP:
110 --- a/net/bridge/br_private.h
111 +++ b/net/bridge/br_private.h
112 @@ -1093,6 +1093,13 @@ void br_vlan_notify(const struct net_bri
113 bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
114 const struct net_bridge_vlan *range_end);
116 +void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
117 + struct net_device_path_ctx *ctx,
118 + struct net_device_path *path);
119 +int br_vlan_fill_forward_path_mode(struct net_bridge *br,
120 + struct net_bridge_port *dst,
121 + struct net_device_path *path);
123 static inline struct net_bridge_vlan_group *br_vlan_group(
124 const struct net_bridge *br)
126 @@ -1250,6 +1257,19 @@ static inline int nbp_get_num_vlan_infos
131 +static inline void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
132 + struct net_device_path_ctx *ctx,
133 + struct net_device_path *path)
137 +static inline int br_vlan_fill_forward_path_mode(struct net_bridge *br,
138 + struct net_bridge_port *dst,
139 + struct net_device_path *path)
144 static inline struct net_bridge_vlan_group *br_vlan_group(
145 const struct net_bridge *br)
146 --- a/net/bridge/br_vlan.c
147 +++ b/net/bridge/br_vlan.c
148 @@ -1327,6 +1327,59 @@ int br_vlan_get_pvid_rcu(const struct ne
150 EXPORT_SYMBOL_GPL(br_vlan_get_pvid_rcu);
152 +void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
153 + struct net_device_path_ctx *ctx,
154 + struct net_device_path *path)
156 + struct net_bridge_vlan_group *vg;
157 + int idx = ctx->num_vlans - 1;
160 + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
162 + if (!br_opt_get(br, BROPT_VLAN_ENABLED))
165 + vg = br_vlan_group(br);
168 + ctx->vlan[idx].proto == br->vlan_proto) {
169 + vid = ctx->vlan[idx].id;
171 + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_TAG;
172 + vid = br_get_pvid(vg);
175 + path->bridge.vlan_id = vid;
176 + path->bridge.vlan_proto = br->vlan_proto;
179 +int br_vlan_fill_forward_path_mode(struct net_bridge *br,
180 + struct net_bridge_port *dst,
181 + struct net_device_path *path)
183 + struct net_bridge_vlan_group *vg;
184 + struct net_bridge_vlan *v;
186 + if (!br_opt_get(br, BROPT_VLAN_ENABLED))
189 + vg = nbp_vlan_group_rcu(dst);
190 + v = br_vlan_find(vg, path->bridge.vlan_id);
191 + if (!v || !br_vlan_should_use(v))
194 + if (!(v->flags & BRIDGE_VLAN_INFO_UNTAGGED))
197 + if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
198 + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
200 + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
205 int br_vlan_get_info(const struct net_device *dev, u16 vid,
206 struct bridge_vlan_info *p_vinfo)