kernel: add linux 5.10 support
[openwrt/staging/rmilecki.git] / target / linux / generic / pending-5.10 / 640-18-netfilter-flowtable-handle-bridge-vlan-filter-offloa.patch
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Wed, 10 Feb 2021 19:44:33 +0100
3 Subject: [PATCH] netfilter: flowtable: handle bridge vlan filter offload
4 tags from DSA/switchdev
5
6 When a switchdev/DSA port is an untagged member of a bridge vlan, ingress
7 packets could potentially be tagged with the id of the VLAN.
8 When the VLAN port group has been uploaded to switchdev, report the bridge
9 tag mode as DEV_PATH_BR_VLAN_UNTAG_HW instead of DEV_PATH_BR_VLAN_UNTAG
10 and handle it in netfilter flow offloading by storing the tag in the tuple
11 in_pvid field.
12 This allows the ingress hook to detect the optional tag and remove it for
13 software offload. This tag processing is for ingress only, egress needs to be
14 fully untagged
15
16 Signed-off-by: Felix Fietkau <nbd@nbd.name>
17 ---
18
19 --- a/include/linux/netdevice.h
20 +++ b/include/linux/netdevice.h
21 @@ -853,6 +853,7 @@ struct net_device_path {
22 DEV_PATH_BR_VLAN_KEEP,
23 DEV_PATH_BR_VLAN_TAG,
24 DEV_PATH_BR_VLAN_UNTAG,
25 + DEV_PATH_BR_VLAN_UNTAG_HW,
26 } vlan_mode;
27 u16 vlan_id;
28 __be16 vlan_proto;
29 --- a/include/net/netfilter/nf_flow_table.h
30 +++ b/include/net/netfilter/nf_flow_table.h
31 @@ -183,6 +183,10 @@ struct nf_flow_route {
32 u32 ifindex;
33 u16 vid[NF_FLOW_TABLE_VLAN_MAX];
34 __be16 vproto[NF_FLOW_TABLE_VLAN_MAX];
35 + struct {
36 + u16 id;
37 + __be16 proto;
38 + } pvid;
39 u8 num_vlans;
40 } in;
41 struct {
42 --- a/net/bridge/br_device.c
43 +++ b/net/bridge/br_device.c
44 @@ -435,6 +435,7 @@ static int br_fill_forward_path(struct n
45 ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto;
46 ctx->num_vlans++;
47 break;
48 + case DEV_PATH_BR_VLAN_UNTAG_HW:
49 case DEV_PATH_BR_VLAN_UNTAG:
50 ctx->num_vlans--;
51 break;
52 --- a/net/bridge/br_vlan.c
53 +++ b/net/bridge/br_vlan.c
54 @@ -1374,6 +1374,8 @@ int br_vlan_fill_forward_path_mode(struc
55
56 if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG)
57 path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP;
58 + else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV)
59 + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW;
60 else
61 path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG;
62
63 --- a/net/netfilter/nf_flow_table_core.c
64 +++ b/net/netfilter/nf_flow_table_core.c
65 @@ -98,6 +98,8 @@ static int flow_offload_fill_route(struc
66 j++;
67 }
68 flow_tuple->in_vlan_num = route->tuple[dir].in.num_vlans;
69 + flow_tuple->in_pvid.id = route->tuple[dir].in.pvid.id;
70 + flow_tuple->in_pvid.proto = route->tuple[dir].in.pvid.proto;
71
72 switch (route->tuple[dir].xmit_type) {
73 case FLOW_OFFLOAD_XMIT_DIRECT:
74 --- a/net/netfilter/nft_flow_offload.c
75 +++ b/net/netfilter/nft_flow_offload.c
76 @@ -67,6 +67,10 @@ struct nft_forward_info {
77 const struct net_device *dev;
78 __u16 vid[NF_FLOW_TABLE_VLAN_MAX];
79 __be16 vproto[NF_FLOW_TABLE_VLAN_MAX];
80 + struct {
81 + __u16 id;
82 + __be16 proto;
83 + } pvid;
84 u8 num_vlans;
85 u8 h_source[ETH_ALEN];
86 u8 h_dest[ETH_ALEN];
87 @@ -127,6 +131,10 @@ static void nft_dev_path_info(const stru
88 info->vproto[info->num_vlans] = path->bridge.vlan_proto;
89 info->num_vlans++;
90 break;
91 + case DEV_PATH_BR_VLAN_UNTAG_HW:
92 + info->pvid.id = info->vid[info->num_vlans - 1];
93 + info->pvid.proto = info->vproto[info->num_vlans - 1];
94 + fallthrough;
95 case DEV_PATH_BR_VLAN_UNTAG:
96 info->num_vlans--;
97 break;
98 @@ -185,6 +193,8 @@ static void nft_dev_forward_path(struct
99 route->tuple[!dir].in.vid[i] = info.vid[i];
100 route->tuple[!dir].in.vproto[i] = info.vproto[i];
101 }
102 + route->tuple[!dir].in.pvid.id = info.pvid.id;
103 + route->tuple[!dir].in.pvid.proto = info.pvid.proto;
104 route->tuple[!dir].in.num_vlans = info.num_vlans;
105
106 if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) {