From 0d5bf53197481d291f9a541eefa03b11a34033f9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 8 Mar 2021 17:20:20 +0100 Subject: [PATCH] kernel: update 5.10 flow offload patches Includes PPPoE support and VLAN related fixes Signed-off-by: Felix Fietkau --- ...netfilter-add-xt_FLOWOFFLOAD-target.patch} | 64 +++-- ...arding-path-from-virtual-netdevice-a.patch | 8 +- ...lve-forwarding-path-for-vlan-devices.patch | 6 +- ...ble-use-dev_fill_forward_path-to-obt.patch | 10 +- ...ble-use-dev_fill_forward_path-to-obt.patch | 26 +- ...netfilter-flowtable-add-vlan-support.patch | 165 ++++++----- ...ve-VLAN-tag-actions-in-forwarding-pa.patch | 4 +- ...w_offload-add-bridge-vlan-filtering.patch} | 10 +- ...forwarding-path-for-bridge-pppoe-dev.patch | 100 +++++++ ...forwarding-path-for-dsa-slave-ports.patch} | 10 +- ...etfilter-flowtable-add-pppoe-support.patch | 263 ++++++++++++++++++ ...er-nft_flow_offload-add-dsa-support.patch} | 14 +- ...le-add-offload-support-for-xmit-pat.patch} | 6 +- ...ow_offload-use-direct-xmit-if-hardwa.patch | 51 ---- ...a-slave-add-support-for-TC_SETUP_FT.patch} | 0 ...ow_offload-fix-bridge-vlan-tag-handl.patch | 22 -- ...owtable-rework-ingress-vlan-matching.patch | 143 ---------- ...ow_offload-use-direct-xmit-if-hardwa.patch | 108 +++++++ ...ble-handle-bridge-vlan-filter-offloa.patch | 106 ------- ...w_table-fix-untagging-with-hardware-.patch | 122 ++++++++ ...w_offload-add-FLOW_ACTION_PPPOE_PUSH.patch | 26 ++ ...ble-support-for-FLOW_ACTION_PPPOE_PU.patch | 31 +++ ...T-skip-GRO-for-foreign-MAC-addresses.patch | 2 +- ...dd-support-for-threaded-NAPI-polling.patch | 2 +- ..._eth_soc-add-flow-offloading-support.patch | 19 +- 25 files changed, 845 insertions(+), 473 deletions(-) rename target/linux/generic/hack-5.10/{650-netfilter-add-xt_OFFLOAD-target.patch => 650-netfilter-add-xt_FLOWOFFLOAD-target.patch} (93%) rename target/linux/generic/pending-5.10/{640-14-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch => 640-10-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch} (74%) create mode 100644 target/linux/generic/pending-5.10/640-11-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch rename target/linux/generic/pending-5.10/{640-10-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch => 640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch} (87%) create mode 100644 target/linux/generic/pending-5.10/640-13-netfilter-flowtable-add-pppoe-support.patch rename target/linux/generic/pending-5.10/{640-12-netfilter-nft_flow_offload-add-dsa-support.patch => 640-14-netfilter-nft_flow_offload-add-dsa-support.patch} (64%) rename target/linux/generic/pending-5.10/{640-11-netfilter-flowtable-add-offload-support-for-xmit-pat.patch => 640-15-netfilter-flowtable-add-offload-support-for-xmit-pat.patch} (98%) delete mode 100644 target/linux/generic/pending-5.10/640-15-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch rename target/linux/generic/pending-5.10/{640-13-dsa-slave-add-support-for-TC_SETUP_FT.patch => 640-16-dsa-slave-add-support-for-TC_SETUP_FT.patch} (100%) delete mode 100644 target/linux/generic/pending-5.10/640-16-netfilter-nft_flow_offload-fix-bridge-vlan-tag-handl.patch delete mode 100644 target/linux/generic/pending-5.10/640-17-netfilter-flowtable-rework-ingress-vlan-matching.patch create mode 100644 target/linux/generic/pending-5.10/640-17-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch delete mode 100644 target/linux/generic/pending-5.10/640-18-netfilter-flowtable-handle-bridge-vlan-filter-offloa.patch create mode 100644 target/linux/generic/pending-5.10/640-18-netfilter-nf_flow_table-fix-untagging-with-hardware-.patch create mode 100644 target/linux/generic/pending-5.10/640-19-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch create mode 100644 target/linux/generic/pending-5.10/640-20-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch diff --git a/target/linux/generic/hack-5.10/650-netfilter-add-xt_OFFLOAD-target.patch b/target/linux/generic/hack-5.10/650-netfilter-add-xt_FLOWOFFLOAD-target.patch similarity index 93% rename from target/linux/generic/hack-5.10/650-netfilter-add-xt_OFFLOAD-target.patch rename to target/linux/generic/hack-5.10/650-netfilter-add-xt_FLOWOFFLOAD-target.patch index eb540acc859..97aa7a673b2 100644 --- a/target/linux/generic/hack-5.10/650-netfilter-add-xt_OFFLOAD-target.patch +++ b/target/linux/generic/hack-5.10/650-netfilter-add-xt_FLOWOFFLOAD-target.patch @@ -1,6 +1,6 @@ From: Felix Fietkau Date: Tue, 20 Feb 2018 15:56:02 +0100 -Subject: [PATCH] netfilter: add xt_OFFLOAD target +Subject: [PATCH] netfilter: add xt_FLOWOFFLOAD target Signed-off-by: Felix Fietkau --- @@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o --- /dev/null +++ b/net/netfilter/xt_FLOWOFFLOAD.c -@@ -0,0 +1,660 @@ +@@ -0,0 +1,658 @@ +/* + * Copyright (C) 2018-2021 Felix Fietkau + * @@ -265,20 +265,14 @@ Signed-off-by: Felix Fietkau +xt_flowoffload_check_hook(struct flow_offload *flow, void *data) +{ + struct xt_flowoffload_table *table = data; -+ struct flow_offload_tuple *tuple = &flow->tuplehash[0].tuple; ++ struct flow_offload_tuple *tuple0 = &flow->tuplehash[0].tuple; ++ struct flow_offload_tuple *tuple1 = &flow->tuplehash[1].tuple; + struct xt_flowoffload_hook *hook; + + spin_lock_bh(&hooks_lock); + hlist_for_each_entry(hook, &table->hooks, list) { -+ int ifindex; -+ -+ if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) -+ ifindex = tuple->out.ifidx; -+ else -+ ifindex = tuple->dst_cache->dev->ifindex; -+ -+ if (hook->ops.dev->ifindex != tuple->iifidx && -+ hook->ops.dev->ifindex != ifindex) ++ if (hook->ops.dev->ifindex != tuple0->iifidx && ++ hook->ops.dev->ifindex != tuple1->iifidx) + continue; + + hook->used = true; @@ -357,6 +351,7 @@ Signed-off-by: Felix Fietkau + int i; + + route->tuple[!dir].in.ifindex = dev->ifindex; ++ route->tuple[dir].out.ifindex = dev->ifindex; + + if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM) + return; @@ -386,52 +381,54 @@ Signed-off-by: Felix Fietkau + prev_type = DEV_PATH_ETHERNET; + for (i = 0; i <= stack.num_paths; i++) { + const struct net_device_path *path = &stack.path[i]; -+ int n_vlans = route->tuple[!dir].in.num_vlans; ++ int n_encaps = route->tuple[!dir].in.num_encaps; + + dev = (struct net_device *)path->dev; + if (flow_is_valid_ether_device(dev)) { -+ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT) ++ if (route->tuple[dir].xmit_type != FLOW_OFFLOAD_XMIT_DIRECT) { + memcpy(route->tuple[dir].out.h_source, + dev->dev_addr, ETH_ALEN); ++ route->tuple[dir].out.ifindex = dev->ifindex; ++ } + route->tuple[dir].xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; -+ route->tuple[dir].out.ifindex = dev->ifindex; + } + + switch (path->type) { ++ case DEV_PATH_PPPOE: + case DEV_PATH_VLAN: -+ if (n_vlans >= NF_FLOW_TABLE_VLAN_MAX || ++ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || + i == stack.num_paths) { + last = true; + break; + } + -+ route->tuple[!dir].in.num_vlans++; -+ route->tuple[!dir].in.vid[n_vlans] = path->vlan.id; -+ route->tuple[!dir].in.vproto[n_vlans] = path->vlan.proto; ++ route->tuple[!dir].in.num_encaps++; ++ route->tuple[!dir].in.encap[n_encaps].id = path->encap.id; ++ route->tuple[!dir].in.encap[n_encaps].proto = path->encap.proto; ++ if (path->type == DEV_PATH_PPPOE) ++ memcpy(route->tuple[dir].out.h_dest, ++ path->encap.h_dest, ETH_ALEN); + break; + case DEV_PATH_BRIDGE: + switch (path->bridge.vlan_mode) { + case DEV_PATH_BR_VLAN_TAG: -+ if (n_vlans >= NF_FLOW_TABLE_VLAN_MAX || ++ if (n_encaps >= NF_FLOW_TABLE_ENCAP_MAX || + i == stack.num_paths) { + last = true; + break; + } + -+ route->tuple[!dir].in.num_vlans++; -+ route->tuple[!dir].in.vid[n_vlans] = ++ route->tuple[!dir].in.num_encaps++; ++ route->tuple[!dir].in.encap[n_encaps].id = + path->bridge.vlan_id; -+ route->tuple[!dir].in.vproto[n_vlans] = ++ route->tuple[!dir].in.encap[n_encaps].proto = + path->bridge.vlan_proto; + break; -+ case DEV_PATH_BR_VLAN_UNTAG_HW: -+ route->tuple[!dir].in.pvid.id = -+ route->tuple[!dir].in.vid[n_vlans - 1]; -+ route->tuple[!dir].in.pvid.proto = -+ route->tuple[!dir].in.vproto[n_vlans - 1]; -+ fallthrough; + case DEV_PATH_BR_VLAN_UNTAG: -+ route->tuple[!dir].in.num_vlans--; ++ route->tuple[!dir].in.num_encaps--; ++ break; ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ route->tuple[!dir].in.ingress_vlans |= BIT(n_encaps - 1); + break; + case DEV_PATH_BR_VLAN_KEEP: + break; @@ -447,6 +444,7 @@ Signed-off-by: Felix Fietkau + } + + *out_dev = dev; ++ route->tuple[dir].out.hw_ifindex = dev->ifindex; + route->tuple[!dir].in.ifindex = dev->ifindex; +} + @@ -769,7 +767,7 @@ Signed-off-by: Felix Fietkau #include #include #include -@@ -355,8 +354,7 @@ flow_offload_lookup(struct nf_flowtable +@@ -356,8 +355,7 @@ flow_offload_lookup(struct nf_flowtable } EXPORT_SYMBOL_GPL(flow_offload_lookup); @@ -779,7 +777,7 @@ Signed-off-by: Felix Fietkau void (*iter)(struct flow_offload *flow, void *data), void *data) { -@@ -388,6 +386,7 @@ nf_flow_table_iterate(struct nf_flowtabl +@@ -389,6 +387,7 @@ nf_flow_table_iterate(struct nf_flowtabl return err; } @@ -809,7 +807,7 @@ Signed-off-by: Felix Fietkau +#endif /* _XT_FLOWOFFLOAD_H */ --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h -@@ -265,6 +265,10 @@ void nf_flow_table_free(struct nf_flowta +@@ -266,6 +266,10 @@ void nf_flow_table_free(struct nf_flowta void flow_offload_teardown(struct flow_offload *flow); diff --git a/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch b/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch index 953446baabc..603dddfc365 100644 --- a/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch +++ b/target/linux/generic/pending-5.10/640-02-net-resolve-forwarding-path-from-virtual-netdevice-a.patch @@ -1,5 +1,5 @@ From: Pablo Neira Ayuso -Date: Sun, 10 Jan 2021 15:53:58 +0100 +Date: Thu, 4 Mar 2021 23:18:11 +0100 Subject: [PATCH] net: resolve forwarding path from virtual netdevice and HW destination address @@ -91,7 +91,7 @@ Signed-off-by: Pablo Neira Ayuso * If a device is paired with a peer device, return the peer instance. * The caller must be under RCU read context. + * int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, struct net_device_path *path); -+ * Get the forwarding path to reach the real device from the HW destination address ++ * Get the forwarding path to reach the real device from the HW destination address */ struct net_device_ops { int (*ndo_init)(struct net_device *dev); @@ -99,8 +99,8 @@ Signed-off-by: Pablo Neira Ayuso int (*ndo_tunnel_ctl)(struct net_device *dev, struct ip_tunnel_parm *p, int cmd); struct net_device * (*ndo_get_peer_dev)(struct net_device *dev); -+ int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, -+ struct net_device_path *path); ++ int (*ndo_fill_forward_path)(struct net_device_path_ctx *ctx, ++ struct net_device_path *path); }; /** diff --git a/target/linux/generic/pending-5.10/640-03-net-8021q-resolve-forwarding-path-for-vlan-devices.patch b/target/linux/generic/pending-5.10/640-03-net-8021q-resolve-forwarding-path-for-vlan-devices.patch index ddc0de0d3b9..26fb64509ce 100644 --- a/target/linux/generic/pending-5.10/640-03-net-8021q-resolve-forwarding-path-for-vlan-devices.patch +++ b/target/linux/generic/pending-5.10/640-03-net-8021q-resolve-forwarding-path-for-vlan-devices.patch @@ -42,7 +42,7 @@ Signed-off-by: Pablo Neira Ayuso + struct { + u16 id; + __be16 proto; -+ } vlan; ++ } encap; + }; }; @@ -59,8 +59,8 @@ Signed-off-by: Pablo Neira Ayuso + struct vlan_dev_priv *vlan = vlan_dev_priv(ctx->dev); + + path->type = DEV_PATH_VLAN; -+ path->vlan.id = vlan->vlan_id; -+ path->vlan.proto = vlan->vlan_proto; ++ path->encap.id = vlan->vlan_id; ++ path->encap.proto = vlan->vlan_proto; + path->dev = ctx->dev; + ctx->dev = vlan->real_dev; + diff --git a/target/linux/generic/pending-5.10/640-05-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch b/target/linux/generic/pending-5.10/640-05-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch index 34724a56964..1f61cff09d0 100644 --- a/target/linux/generic/pending-5.10/640-05-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch +++ b/target/linux/generic/pending-5.10/640-05-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch @@ -89,7 +89,7 @@ Signed-off-by: Pablo Neira Ayuso +} + +struct nft_forward_info { -+ const struct net_device *dev; ++ const struct net_device *indev; +}; + +static void nft_dev_path_info(const struct net_device_path_stack *stack, @@ -102,12 +102,12 @@ Signed-off-by: Pablo Neira Ayuso + path = &stack->path[i]; + switch (path->type) { + case DEV_PATH_ETHERNET: -+ info->dev = path->dev; ++ info->indev = path->dev; + break; + case DEV_PATH_VLAN: + case DEV_PATH_BRIDGE: + default: -+ info->dev = NULL; ++ info->indev = NULL; + break; + } + } @@ -142,10 +142,10 @@ Signed-off-by: Pablo Neira Ayuso + if (nft_dev_fill_forward_path(route, dst, ct, dir, &stack) >= 0) + nft_dev_path_info(&stack, &info); + -+ if (!info.dev || !nft_flowtable_find_dev(info.dev, ft)) ++ if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) + return; + -+ route->tuple[!dir].in.ifindex = info.dev->ifindex; ++ route->tuple[!dir].in.ifindex = info.indev->ifindex; +} + static int nft_flow_route(const struct nft_pktinfo *pkt, diff --git a/target/linux/generic/pending-5.10/640-06-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch b/target/linux/generic/pending-5.10/640-06-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch index d4bf68a690d..ada14e6c7a6 100644 --- a/target/linux/generic/pending-5.10/640-06-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch +++ b/target/linux/generic/pending-5.10/640-06-netfilter-flowtable-use-dev_fill_forward_path-to-obt.patch @@ -1,5 +1,5 @@ From: Pablo Neira Ayuso -Date: Fri, 20 Nov 2020 13:49:19 +0100 +Date: Thu, 4 Mar 2021 03:26:35 +0100 Subject: [PATCH] netfilter: flowtable: use dev_fill_forward_path() to obtain egress device @@ -271,10 +271,11 @@ Signed-off-by: Pablo Neira Ayuso struct neighbour *n; u8 nud_state; -@@ -66,22 +65,35 @@ static int nft_dev_fill_forward_path(con +@@ -66,27 +65,43 @@ static int nft_dev_fill_forward_path(con struct nft_forward_info { - const struct net_device *dev; + const struct net_device *indev; ++ const struct net_device *outdev; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + enum flow_offload_xmit_type xmit_type; @@ -294,7 +295,7 @@ Signed-off-by: Pablo Neira Ayuso path = &stack->path[i]; switch (path->type) { case DEV_PATH_ETHERNET: - info->dev = path->dev; + info->indev = path->dev; + if (is_zero_ether_addr(info->h_source)) + memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); break; @@ -307,9 +308,16 @@ Signed-off-by: Pablo Neira Ayuso + break; + case DEV_PATH_VLAN: default: - info->dev = NULL; + info->indev = NULL; break; -@@ -114,14 +126,22 @@ static void nft_dev_forward_path(struct + } + } ++ if (!info->outdev) ++ info->outdev = info->indev; + } + + static bool nft_flowtable_find_dev(const struct net_device *dev, +@@ -114,14 +129,22 @@ static void nft_dev_forward_path(struct const struct dst_entry *dst = route->tuple[dir].dst; struct net_device_path_stack stack; struct nft_forward_info info = {}; @@ -320,15 +328,15 @@ Signed-off-by: Pablo Neira Ayuso + if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) + nft_dev_path_info(&stack, &info, ha); - if (!info.dev || !nft_flowtable_find_dev(info.dev, ft)) + if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) return; - route->tuple[!dir].in.ifindex = info.dev->ifindex; + route->tuple[!dir].in.ifindex = info.indev->ifindex; + + if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { + memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); + memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); -+ route->tuple[dir].out.ifindex = info.dev->ifindex; ++ route->tuple[dir].out.ifindex = info.outdev->ifindex; + route->tuple[dir].xmit_type = info.xmit_type; + } } diff --git a/target/linux/generic/pending-5.10/640-07-netfilter-flowtable-add-vlan-support.patch b/target/linux/generic/pending-5.10/640-07-netfilter-flowtable-add-vlan-support.patch index 77aeaccbce7..fea1b59dc3f 100644 --- a/target/linux/generic/pending-5.10/640-07-netfilter-flowtable-add-vlan-support.patch +++ b/target/linux/generic/pending-5.10/640-07-netfilter-flowtable-add-vlan-support.patch @@ -16,7 +16,7 @@ Signed-off-by: Pablo Neira Ayuso FLOW_OFFLOAD_XMIT_DIRECT, }; -+#define NF_FLOW_TABLE_VLAN_MAX 2 ++#define NF_FLOW_TABLE_ENCAP_MAX 2 + struct flow_offload_tuple { union { @@ -28,7 +28,7 @@ Signed-off-by: Pablo Neira Ayuso + struct { + u16 id; + __be16 proto; -+ } in_vlan[NF_FLOW_TABLE_VLAN_MAX]; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; /* All members above are keys for lookups, see flow_offload_hash(). */ struct { } __hash; @@ -38,17 +38,19 @@ Signed-off-by: Pablo Neira Ayuso - + u8 dir:4, + xmit_type:2, -+ in_vlan_num:2; ++ encap_num:2; u16 mtu; union { struct dst_entry *dst_cache; -@@ -174,6 +180,9 @@ struct nf_flow_route { +@@ -174,6 +180,11 @@ struct nf_flow_route { struct dst_entry *dst; struct { u32 ifindex; -+ u16 vid[NF_FLOW_TABLE_VLAN_MAX]; -+ __be16 vproto[NF_FLOW_TABLE_VLAN_MAX]; -+ u8 num_vlans; ++ struct { ++ u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; } in; struct { u32 ifindex; @@ -66,33 +68,36 @@ Signed-off-by: Pablo Neira Ayuso } flow_tuple->iifidx = route->tuple[dir].in.ifindex; -+ for (i = route->tuple[dir].in.num_vlans - 1; i >= 0; i--) { -+ flow_tuple->in_vlan[j].id = route->tuple[dir].in.vid[i]; -+ flow_tuple->in_vlan[j].proto = route->tuple[dir].in.vproto[i]; ++ for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) { ++ flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id; ++ flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto; + j++; + } -+ flow_tuple->in_vlan_num = route->tuple[dir].in.num_vlans; ++ flow_tuple->encap_num = route->tuple[dir].in.num_encaps; switch (route->tuple[dir].xmit_type) { case FLOW_OFFLOAD_XMIT_DIRECT: --- a/net/netfilter/nf_flow_table_ip.c +++ b/net/netfilter/nf_flow_table_ip.c -@@ -159,17 +159,35 @@ static bool ip_has_options(unsigned int +@@ -159,17 +159,38 @@ static bool ip_has_options(unsigned int return thoff != sizeof(struct iphdr); } -+static void nf_flow_tuple_vlan(struct sk_buff *skb, -+ struct flow_offload_tuple *tuple) ++static void nf_flow_tuple_encap(struct sk_buff *skb, ++ struct flow_offload_tuple *tuple) +{ ++ int i = 0; ++ + if (skb_vlan_tag_present(skb)) { -+ tuple->in_vlan[0].id = skb_vlan_tag_get(skb); -+ tuple->in_vlan[0].proto = skb->vlan_proto; ++ tuple->encap[i].id = skb_vlan_tag_get(skb); ++ tuple->encap[i].proto = skb->vlan_proto; ++ i++; + } + if (skb->protocol == htons(ETH_P_8021Q)) { + struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); + -+ tuple->in_vlan[1].id = ntohs(veth->h_vlan_TCI); -+ tuple->in_vlan[1].proto = skb->protocol; ++ tuple->encap[i].id = ntohs(veth->h_vlan_TCI); ++ tuple->encap[i].proto = skb->protocol; + } +} + @@ -116,7 +121,7 @@ Signed-off-by: Pablo Neira Ayuso thoff = iph->ihl * 4; if (ip_is_fragment(iph) || -@@ -191,11 +209,11 @@ static int nf_flow_tuple_ip(struct sk_bu +@@ -191,11 +212,11 @@ static int nf_flow_tuple_ip(struct sk_bu return -1; thoff = iph->ihl * 4; @@ -131,19 +136,19 @@ Signed-off-by: Pablo Neira Ayuso tuple->src_v4.s_addr = iph->saddr; tuple->dst_v4.s_addr = iph->daddr; -@@ -204,6 +222,7 @@ static int nf_flow_tuple_ip(struct sk_bu +@@ -204,6 +225,7 @@ static int nf_flow_tuple_ip(struct sk_bu tuple->l3proto = AF_INET; tuple->l4proto = iph->protocol; tuple->iifidx = dev->ifindex; -+ nf_flow_tuple_vlan(skb, tuple); ++ nf_flow_tuple_encap(skb, tuple); return 0; } -@@ -248,6 +267,37 @@ static unsigned int nf_flow_xmit_xfrm(st +@@ -248,6 +270,40 @@ static unsigned int nf_flow_xmit_xfrm(st return NF_STOLEN; } -+static bool nf_flow_skb_vlan_protocol(const struct sk_buff *skb, __be16 proto) ++static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto) +{ + if (skb->protocol == htons(ETH_P_8021Q)) { + struct vlan_ethhdr *veth; @@ -156,29 +161,37 @@ Signed-off-by: Pablo Neira Ayuso + return false; +} + -+static void nf_flow_vlan_pop(struct sk_buff *skb, -+ struct flow_offload_tuple_rhash *tuplehash) ++static void nf_flow_encap_pop(struct sk_buff *skb, ++ struct flow_offload_tuple_rhash *tuplehash) +{ + struct vlan_hdr *vlan_hdr; + int i; + -+ for (i = 0; i < tuplehash->tuple.in_vlan_num; i++) { ++ for (i = 0; i < tuplehash->tuple.encap_num; i++) { + if (skb_vlan_tag_present(skb)) { + __vlan_hwaccel_clear_tag(skb); + continue; + } -+ vlan_hdr = (struct vlan_hdr *)skb->data; -+ __skb_pull(skb, VLAN_HLEN); -+ vlan_set_encap_proto(skb, vlan_hdr); -+ skb_reset_network_header(skb); ++ if (skb->protocol == htons(ETH_P_8021Q)) { ++ vlan_hdr = (struct vlan_hdr *)skb->data; ++ __skb_pull(skb, VLAN_HLEN); ++ vlan_set_encap_proto(skb, vlan_hdr); ++ skb_reset_network_header(skb); ++ break; ++ } + } +} + static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb, const struct flow_offload_tuple_rhash *tuplehash, unsigned short type) -@@ -280,9 +330,11 @@ nf_flow_offload_ip_hook(void *priv, stru - unsigned int thoff; +@@ -276,13 +332,15 @@ nf_flow_offload_ip_hook(void *priv, stru + enum flow_offload_tuple_dir dir; + struct flow_offload *flow; + struct net_device *outdev; ++ unsigned int thoff, mtu; + struct rtable *rt; +- unsigned int thoff; struct iphdr *iph; __be32 nexthop; + u32 offset = 0; @@ -186,12 +199,17 @@ Signed-off-by: Pablo Neira Ayuso - if (skb->protocol != htons(ETH_P_IP)) + if (skb->protocol != htons(ETH_P_IP) && -+ !nf_flow_skb_vlan_protocol(skb, htons(ETH_P_IP))) ++ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP))) return NF_ACCEPT; if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) -@@ -298,11 +350,15 @@ nf_flow_offload_ip_hook(void *priv, stru - if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) +@@ -295,14 +353,19 @@ nf_flow_offload_ip_hook(void *priv, stru + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); + +- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ mtu = flow->tuplehash[dir].tuple.mtu + offset; ++ if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) return NF_ACCEPT; - if (skb_try_make_writable(skb, sizeof(*iph))) @@ -209,17 +227,17 @@ Signed-off-by: Pablo Neira Ayuso return NF_ACCEPT; flow_offload_refresh(flow_table, flow); -@@ -312,6 +368,9 @@ nf_flow_offload_ip_hook(void *priv, stru +@@ -312,6 +375,9 @@ nf_flow_offload_ip_hook(void *priv, stru return NF_ACCEPT; } -+ nf_flow_vlan_pop(skb, tuplehash); ++ nf_flow_encap_pop(skb, tuplehash); + thoff -= offset; + if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0) return NF_DROP; -@@ -479,14 +538,17 @@ static int nf_flow_nat_ipv6(const struct +@@ -479,14 +545,17 @@ static int nf_flow_nat_ipv6(const struct static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, struct flow_offload_tuple *tuple) { @@ -240,7 +258,7 @@ Signed-off-by: Pablo Neira Ayuso switch (ip6h->nexthdr) { case IPPROTO_TCP: -@@ -503,11 +565,11 @@ static int nf_flow_tuple_ipv6(struct sk_ +@@ -503,11 +572,11 @@ static int nf_flow_tuple_ipv6(struct sk_ return -1; thoff = sizeof(*ip6h); @@ -255,29 +273,35 @@ Signed-off-by: Pablo Neira Ayuso tuple->src_v6 = ip6h->saddr; tuple->dst_v6 = ip6h->daddr; -@@ -516,6 +578,7 @@ static int nf_flow_tuple_ipv6(struct sk_ +@@ -516,6 +585,7 @@ static int nf_flow_tuple_ipv6(struct sk_ tuple->l3proto = AF_INET6; tuple->l4proto = ip6h->nexthdr; tuple->iifidx = dev->ifindex; -+ nf_flow_tuple_vlan(skb, tuple); ++ nf_flow_tuple_encap(skb, tuple); return 0; } -@@ -533,9 +596,11 @@ nf_flow_offload_ipv6_hook(void *priv, st +@@ -533,9 +603,12 @@ nf_flow_offload_ipv6_hook(void *priv, st struct net_device *outdev; struct ipv6hdr *ip6h; struct rt6_info *rt; ++ unsigned int mtu; + u32 offset = 0; int ret; - if (skb->protocol != htons(ETH_P_IPV6)) + if (skb->protocol != htons(ETH_P_IPV6) && -+ !nf_flow_skb_vlan_protocol(skb, htons(ETH_P_IPV6))) ++ !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6))) return NF_ACCEPT; if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) -@@ -551,8 +616,11 @@ nf_flow_offload_ipv6_hook(void *priv, st - if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) +@@ -548,11 +621,15 @@ nf_flow_offload_ipv6_hook(void *priv, st + dir = tuplehash->tuple.dir; + flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); + +- if (unlikely(nf_flow_exceeds_mtu(skb, flow->tuplehash[dir].tuple.mtu))) ++ mtu = flow->tuplehash[dir].tuple.mtu + offset; ++ if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) return NF_ACCEPT; - if (nf_flow_state_check(flow, ipv6_hdr(skb)->nexthdr, skb, @@ -290,33 +314,35 @@ Signed-off-by: Pablo Neira Ayuso return NF_ACCEPT; flow_offload_refresh(flow_table, flow); -@@ -562,6 +630,8 @@ nf_flow_offload_ipv6_hook(void *priv, st +@@ -562,6 +639,8 @@ nf_flow_offload_ipv6_hook(void *priv, st return NF_ACCEPT; } -+ nf_flow_vlan_pop(skb, tuplehash); ++ nf_flow_encap_pop(skb, tuplehash); + if (skb_try_make_writable(skb, sizeof(*ip6h))) return NF_DROP; --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c -@@ -65,6 +65,9 @@ static int nft_dev_fill_forward_path(con - +@@ -66,6 +66,11 @@ static int nft_dev_fill_forward_path(con struct nft_forward_info { - const struct net_device *dev; -+ __u16 vid[NF_FLOW_TABLE_VLAN_MAX]; -+ __be16 vproto[NF_FLOW_TABLE_VLAN_MAX]; -+ u8 num_vlans; + const struct net_device *indev; + const struct net_device *outdev; ++ struct id { ++ __u16 id; ++ __be16 proto; ++ } encap[NF_FLOW_TABLE_ENCAP_MAX]; ++ u8 num_encaps; u8 h_source[ETH_ALEN]; u8 h_dest[ETH_ALEN]; enum flow_offload_xmit_type xmit_type; -@@ -83,9 +86,22 @@ static void nft_dev_path_info(const stru +@@ -84,9 +89,23 @@ static void nft_dev_path_info(const stru path = &stack->path[i]; switch (path->type) { case DEV_PATH_ETHERNET: + case DEV_PATH_VLAN: - info->dev = path->dev; + info->indev = path->dev; if (is_zero_ether_addr(info->h_source)) memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + @@ -324,25 +350,26 @@ Signed-off-by: Pablo Neira Ayuso + break; + + /* DEV_PATH_VLAN */ -+ if (info->num_vlans >= NF_FLOW_TABLE_VLAN_MAX) { -+ info->dev = NULL; ++ if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { ++ info->indev = NULL; + break; + } -+ info->vid[info->num_vlans] = path->vlan.id; -+ info->vproto[info->num_vlans] = path->vlan.proto; -+ info->num_vlans++; ++ info->outdev = path->dev; ++ info->encap[info->num_encaps].id = path->encap.id; ++ info->encap[info->num_encaps].proto = path->encap.proto; ++ info->num_encaps++; break; case DEV_PATH_BRIDGE: if (is_zero_ether_addr(info->h_source)) -@@ -93,7 +109,6 @@ static void nft_dev_path_info(const stru +@@ -94,7 +113,6 @@ static void nft_dev_path_info(const stru info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; break; - case DEV_PATH_VLAN: default: - info->dev = NULL; + info->indev = NULL; break; -@@ -127,6 +142,7 @@ static void nft_dev_forward_path(struct +@@ -130,6 +148,7 @@ static void nft_dev_forward_path(struct struct net_device_path_stack stack; struct nft_forward_info info = {}; unsigned char ha[ETH_ALEN]; @@ -350,15 +377,15 @@ Signed-off-by: Pablo Neira Ayuso if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) nft_dev_path_info(&stack, &info, ha); -@@ -135,6 +151,11 @@ static void nft_dev_forward_path(struct +@@ -138,6 +157,11 @@ static void nft_dev_forward_path(struct return; - route->tuple[!dir].in.ifindex = info.dev->ifindex; -+ for (i = 0; i < info.num_vlans; i++) { -+ route->tuple[!dir].in.vid[i] = info.vid[i]; -+ route->tuple[!dir].in.vproto[i] = info.vproto[i]; + route->tuple[!dir].in.ifindex = info.indev->ifindex; ++ for (i = 0; i < info.num_encaps; i++) { ++ route->tuple[!dir].in.encap[i].id = info.encap[i].id; ++ route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; + } -+ route->tuple[!dir].in.num_vlans = info.num_vlans; ++ route->tuple[!dir].in.num_encaps = info.num_encaps; if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); diff --git a/target/linux/generic/pending-5.10/640-09-net-bridge-resolve-VLAN-tag-actions-in-forwarding-pa.patch b/target/linux/generic/pending-5.10/640-09-net-bridge-resolve-VLAN-tag-actions-in-forwarding-pa.patch index fb5f7366480..9bd1f6b4c6d 100644 --- a/target/linux/generic/pending-5.10/640-09-net-bridge-resolve-VLAN-tag-actions-in-forwarding-pa.patch +++ b/target/linux/generic/pending-5.10/640-09-net-bridge-resolve-VLAN-tag-actions-in-forwarding-pa.patch @@ -18,7 +18,7 @@ Signed-off-by: Pablo Neira Ayuso @@ -847,10 +847,20 @@ struct net_device_path { u16 id; __be16 proto; - } vlan; + } encap; + struct { + enum { + DEV_PATH_BR_VLAN_KEEP, @@ -52,7 +52,7 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -777,6 +777,12 @@ static int vlan_dev_fill_forward_path(st - path->vlan.proto = vlan->vlan_proto; + path->encap.proto = vlan->vlan_proto; path->dev = ctx->dev; ctx->dev = vlan->real_dev; + if (ctx->num_vlans >= ARRAY_SIZE(ctx->vlan)) diff --git a/target/linux/generic/pending-5.10/640-14-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch b/target/linux/generic/pending-5.10/640-10-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch similarity index 74% rename from target/linux/generic/pending-5.10/640-14-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch rename to target/linux/generic/pending-5.10/640-10-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch index 2e833117db6..86fd6bf77bd 100644 --- a/target/linux/generic/pending-5.10/640-14-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch +++ b/target/linux/generic/pending-5.10/640-10-netfilter-nft_flow_offload-add-bridge-vlan-filtering.patch @@ -10,18 +10,18 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c -@@ -112,6 +112,18 @@ static void nft_dev_path_info(const stru +@@ -111,6 +111,18 @@ static void nft_dev_path_info(const stru if (is_zero_ether_addr(info->h_source)) memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + switch (path->bridge.vlan_mode) { + case DEV_PATH_BR_VLAN_TAG: -+ info->vid[info->num_vlans] = path->vlan.id; -+ info->vproto[info->num_vlans] = path->vlan.proto; -+ info->num_vlans++; ++ info->encap[info->num_encaps].id = path->bridge.vlan_id; ++ info->encap[info->num_encaps].proto = path->bridge.vlan_proto; ++ info->num_encaps++; + break; + case DEV_PATH_BR_VLAN_UNTAG: -+ info->num_vlans--; ++ info->num_encaps--; + break; + case DEV_PATH_BR_VLAN_KEEP: + break; diff --git a/target/linux/generic/pending-5.10/640-11-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch b/target/linux/generic/pending-5.10/640-11-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch new file mode 100644 index 00000000000..34d918206fc --- /dev/null +++ b/target/linux/generic/pending-5.10/640-11-net-ppp-resolve-forwarding-path-for-bridge-pppoe-dev.patch @@ -0,0 +1,100 @@ +From: Pablo Neira Ayuso +Date: Tue, 2 Mar 2021 21:45:16 +0100 +Subject: [PATCH] net: ppp: resolve forwarding path for bridge pppoe + devices + +Pass on the PPPoE session ID and the real device. +--- + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1450,12 +1450,34 @@ static void ppp_dev_priv_destructor(stru + ppp_destroy_interface(ppp); + } + ++static int ppp_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path) ++{ ++ struct ppp *ppp = netdev_priv(path->dev); ++ struct ppp_channel *chan; ++ struct channel *pch; ++ ++ if (ppp->flags & SC_MULTILINK) ++ return -EOPNOTSUPP; ++ ++ if (list_empty(&ppp->channels)) ++ return -ENODEV; ++ ++ pch = list_first_entry(&ppp->channels, struct channel, clist); ++ chan = pch->chan; ++ if (!chan->ops->fill_forward_path) ++ return -EOPNOTSUPP; ++ ++ return chan->ops->fill_forward_path(ctx, path, chan); ++} ++ + static const struct net_device_ops ppp_netdev_ops = { + .ndo_init = ppp_dev_init, + .ndo_uninit = ppp_dev_uninit, + .ndo_start_xmit = ppp_start_xmit, + .ndo_do_ioctl = ppp_net_ioctl, + .ndo_get_stats64 = ppp_get_stats64, ++ .ndo_fill_forward_path = ppp_fill_forward_path, + }; + + static struct device_type ppp_type = { +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -972,8 +972,30 @@ static int pppoe_xmit(struct ppp_channel + return __pppoe_xmit(sk, skb); + } + ++static int pppoe_fill_forward_path(struct net_device_path_ctx *ctx, ++ struct net_device_path *path, ++ const struct ppp_channel *chan) ++{ ++ struct sock *sk = (struct sock *)chan->private; ++ struct pppox_sock *po = pppox_sk(sk); ++ struct net_device *dev = po->pppoe_dev; ++ ++ if (sock_flag(sk, SOCK_DEAD) || ++ !(sk->sk_state & PPPOX_CONNECTED) || !dev) ++ return -1; ++ ++ path->type = DEV_PATH_PPPOE; ++ path->encap.proto = htons(ETH_P_PPP_SES); ++ path->encap.id = be16_to_cpu(po->num); ++ path->dev = ctx->dev; ++ ctx->dev = dev; ++ ++ return 0; ++} ++ + static const struct ppp_channel_ops pppoe_chan_ops = { + .start_xmit = pppoe_xmit, ++ .fill_forward_path = pppoe_fill_forward_path, + }; + + static int pppoe_recvmsg(struct socket *sock, struct msghdr *m, +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -837,6 +837,7 @@ enum net_device_path_type { + DEV_PATH_ETHERNET = 0, + DEV_PATH_VLAN, + DEV_PATH_BRIDGE, ++ DEV_PATH_PPPOE, + }; + + struct net_device_path { +--- a/include/linux/ppp_channel.h ++++ b/include/linux/ppp_channel.h +@@ -28,6 +28,9 @@ struct ppp_channel_ops { + int (*start_xmit)(struct ppp_channel *, struct sk_buff *); + /* Handle an ioctl call that has come in via /dev/ppp. */ + int (*ioctl)(struct ppp_channel *, unsigned int, unsigned long); ++ int (*fill_forward_path)(struct net_device_path_ctx *, ++ struct net_device_path *, ++ const struct ppp_channel *); + }; + + struct ppp_channel { diff --git a/target/linux/generic/pending-5.10/640-10-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch b/target/linux/generic/pending-5.10/640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch similarity index 87% rename from target/linux/generic/pending-5.10/640-10-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch rename to target/linux/generic/pending-5.10/640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch index 64a2b14af54..3e7a9eaef96 100644 --- a/target/linux/generic/pending-5.10/640-10-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch +++ b/target/linux/generic/pending-5.10/640-12-net-dsa-resolve-forwarding-path-for-dsa-slave-ports.patch @@ -1,23 +1,21 @@ From: Felix Fietkau -Date: Mon, 7 Dec 2020 20:31:48 +0100 +Date: Thu, 4 Mar 2021 23:19:06 +0100 Subject: [PATCH] net: dsa: resolve forwarding path for dsa slave ports Add .ndo_fill_forward_path for dsa slave port devices - -Signed-off-by: Felix Fietkau --- --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -837,6 +837,7 @@ enum net_device_path_type { - DEV_PATH_ETHERNET = 0, +@@ -838,6 +838,7 @@ enum net_device_path_type { DEV_PATH_VLAN, DEV_PATH_BRIDGE, + DEV_PATH_PPPOE, + DEV_PATH_DSA, }; struct net_device_path { -@@ -856,6 +857,10 @@ struct net_device_path { +@@ -857,6 +858,10 @@ struct net_device_path { u16 vlan_id; __be16 vlan_proto; } bridge; diff --git a/target/linux/generic/pending-5.10/640-13-netfilter-flowtable-add-pppoe-support.patch b/target/linux/generic/pending-5.10/640-13-netfilter-flowtable-add-pppoe-support.patch new file mode 100644 index 00000000000..6a145145651 --- /dev/null +++ b/target/linux/generic/pending-5.10/640-13-netfilter-flowtable-add-pppoe-support.patch @@ -0,0 +1,263 @@ +From: Pablo Neira Ayuso +Date: Mon, 1 Mar 2021 23:52:49 +0100 +Subject: [PATCH] netfilter: flowtable: add pppoe support + +--- + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1453,7 +1453,7 @@ static void ppp_dev_priv_destructor(stru + static int ppp_fill_forward_path(struct net_device_path_ctx *ctx, + struct net_device_path *path) + { +- struct ppp *ppp = netdev_priv(path->dev); ++ struct ppp *ppp = netdev_priv(ctx->dev); + struct ppp_channel *chan; + struct channel *pch; + +--- a/drivers/net/ppp/pppoe.c ++++ b/drivers/net/ppp/pppoe.c +@@ -987,6 +987,7 @@ static int pppoe_fill_forward_path(struc + path->type = DEV_PATH_PPPOE; + path->encap.proto = htons(ETH_P_PPP_SES); + path->encap.id = be16_to_cpu(po->num); ++ memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN); + path->dev = ctx->dev; + ctx->dev = dev; + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -848,6 +848,7 @@ struct net_device_path { + struct { + u16 id; + __be16 proto; ++ u8 h_dest[ETH_ALEN]; + } encap; + struct { + enum { +--- a/net/netfilter/nf_flow_table_ip.c ++++ b/net/netfilter/nf_flow_table_ip.c +@@ -7,6 +7,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + #include +@@ -162,6 +165,8 @@ static bool ip_has_options(unsigned int + static void nf_flow_tuple_encap(struct sk_buff *skb, + struct flow_offload_tuple *tuple) + { ++ struct vlan_ethhdr *veth; ++ struct pppoe_hdr *phdr; + int i = 0; + + if (skb_vlan_tag_present(skb)) { +@@ -169,23 +174,35 @@ static void nf_flow_tuple_encap(struct s + tuple->encap[i].proto = skb->vlan_proto; + i++; + } +- if (skb->protocol == htons(ETH_P_8021Q)) { +- struct vlan_ethhdr *veth = (struct vlan_ethhdr *)skb_mac_header(skb); +- ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): ++ veth = (struct vlan_ethhdr *)skb_mac_header(skb); + tuple->encap[i].id = ntohs(veth->h_vlan_TCI); + tuple->encap[i].proto = skb->protocol; ++ break; ++ case htons(ETH_P_PPP_SES): ++ phdr = (struct pppoe_hdr *)skb_mac_header(skb); ++ tuple->encap[i].id = ntohs(phdr->sid); ++ tuple->encap[i].proto = skb->protocol; ++ break; + } + } + + static int nf_flow_tuple_ip(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple) ++ struct flow_offload_tuple *tuple, u32 *nhoff) + { + unsigned int thoff, hdrsize, offset = 0; + struct flow_ports *ports; + struct iphdr *iph; + +- if (skb->protocol == htons(ETH_P_8021Q)) ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): + offset += VLAN_HLEN; ++ break; ++ case htons(ETH_P_PPP_SES): ++ offset += PPPOE_SES_HLEN; ++ break; ++ } + + if (!pskb_may_pull(skb, sizeof(*iph) + offset)) + return -1; +@@ -226,6 +243,7 @@ static int nf_flow_tuple_ip(struct sk_bu + tuple->l4proto = iph->protocol; + tuple->iifidx = dev->ifindex; + nf_flow_tuple_encap(skb, tuple); ++ *nhoff = offset; + + return 0; + } +@@ -270,14 +288,36 @@ static unsigned int nf_flow_xmit_xfrm(st + return NF_STOLEN; + } + ++static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb) ++{ ++ __be16 proto; ++ ++ proto = *((__be16 *)(skb_mac_header(skb) + ETH_HLEN + ++ sizeof(struct pppoe_hdr))); ++ switch (proto) { ++ case htons(PPP_IP): ++ return htons(ETH_P_IP); ++ case htons(PPP_IPV6): ++ return htons(ETH_P_IPV6); ++ } ++ ++ return 0; ++} ++ + static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto) + { +- if (skb->protocol == htons(ETH_P_8021Q)) { +- struct vlan_ethhdr *veth; ++ struct vlan_ethhdr *veth; + ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): + veth = (struct vlan_ethhdr *)skb_mac_header(skb); + if (veth->h_vlan_encapsulated_proto == proto) + return true; ++ break; ++ case htons(ETH_P_PPP_SES): ++ if (nf_flow_pppoe_proto(skb) == proto) ++ return true; ++ break; + } + + return false; +@@ -294,12 +334,18 @@ static void nf_flow_encap_pop(struct sk_ + __vlan_hwaccel_clear_tag(skb); + continue; + } +- if (skb->protocol == htons(ETH_P_8021Q)) { ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): + vlan_hdr = (struct vlan_hdr *)skb->data; + __skb_pull(skb, VLAN_HLEN); + vlan_set_encap_proto(skb, vlan_hdr); + skb_reset_network_header(skb); + break; ++ case htons(ETH_P_PPP_SES): ++ skb->protocol = nf_flow_pppoe_proto(skb); ++ skb_pull(skb, PPPOE_SES_HLEN); ++ skb_reset_network_header(skb); ++ break; + } + } + } +@@ -343,7 +389,7 @@ nf_flow_offload_ip_hook(void *priv, stru + !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP))) + return NF_ACCEPT; + +- if (nf_flow_tuple_ip(skb, state->in, &tuple) < 0) ++ if (nf_flow_tuple_ip(skb, state->in, &tuple, &offset) < 0) + return NF_ACCEPT; + + tuplehash = flow_offload_lookup(flow_table, &tuple); +@@ -357,9 +403,6 @@ nf_flow_offload_ip_hook(void *priv, stru + if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) + return NF_ACCEPT; + +- if (skb->protocol == htons(ETH_P_8021Q)) +- offset += VLAN_HLEN; +- + if (skb_try_make_writable(skb, sizeof(*iph) + offset)) + return NF_DROP; + +@@ -543,14 +586,20 @@ static int nf_flow_nat_ipv6(const struct + } + + static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev, +- struct flow_offload_tuple *tuple) ++ struct flow_offload_tuple *tuple, u32 *nhoff) + { + unsigned int thoff, hdrsize, offset = 0; + struct flow_ports *ports; + struct ipv6hdr *ip6h; + +- if (skb->protocol == htons(ETH_P_8021Q)) ++ switch (skb->protocol) { ++ case htons(ETH_P_8021Q): + offset += VLAN_HLEN; ++ break; ++ case htons(ETH_P_PPP_SES): ++ offset += PPPOE_SES_HLEN; ++ break; ++ } + + if (!pskb_may_pull(skb, sizeof(*ip6h) + offset)) + return -1; +@@ -586,6 +635,7 @@ static int nf_flow_tuple_ipv6(struct sk_ + tuple->l4proto = ip6h->nexthdr; + tuple->iifidx = dev->ifindex; + nf_flow_tuple_encap(skb, tuple); ++ *nhoff = offset; + + return 0; + } +@@ -611,7 +661,7 @@ nf_flow_offload_ipv6_hook(void *priv, st + !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6))) + return NF_ACCEPT; + +- if (nf_flow_tuple_ipv6(skb, state->in, &tuple) < 0) ++ if (nf_flow_tuple_ipv6(skb, state->in, &tuple, &offset) < 0) + return NF_ACCEPT; + + tuplehash = flow_offload_lookup(flow_table, &tuple); +@@ -625,9 +675,6 @@ nf_flow_offload_ipv6_hook(void *priv, st + if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) + return NF_ACCEPT; + +- if (skb->protocol == htons(ETH_P_8021Q)) +- offset += VLAN_HLEN; +- + ip6h = (struct ipv6hdr *)(skb_network_header(skb) + offset); + if (nf_flow_state_check(flow, ip6h->nexthdr, skb, sizeof(*ip6h))) + return NF_ACCEPT; +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -90,6 +90,7 @@ static void nft_dev_path_info(const stru + switch (path->type) { + case DEV_PATH_ETHERNET: + case DEV_PATH_VLAN: ++ case DEV_PATH_PPPOE: + info->indev = path->dev; + if (is_zero_ether_addr(info->h_source)) + memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); +@@ -97,7 +98,7 @@ static void nft_dev_path_info(const stru + if (path->type == DEV_PATH_ETHERNET) + break; + +- /* DEV_PATH_VLAN */ ++ /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ + if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { + info->indev = NULL; + break; +@@ -106,6 +107,8 @@ static void nft_dev_path_info(const stru + info->encap[info->num_encaps].id = path->encap.id; + info->encap[info->num_encaps].proto = path->encap.proto; + info->num_encaps++; ++ if (path->type == DEV_PATH_PPPOE) ++ memcpy(info->h_dest, path->encap.h_dest, ETH_ALEN); + break; + case DEV_PATH_BRIDGE: + if (is_zero_ether_addr(info->h_source)) diff --git a/target/linux/generic/pending-5.10/640-12-netfilter-nft_flow_offload-add-dsa-support.patch b/target/linux/generic/pending-5.10/640-14-netfilter-nft_flow_offload-add-dsa-support.patch similarity index 64% rename from target/linux/generic/pending-5.10/640-12-netfilter-nft_flow_offload-add-dsa-support.patch rename to target/linux/generic/pending-5.10/640-14-netfilter-nft_flow_offload-add-dsa-support.patch index 3689a476b3a..7ff5dad1f7d 100644 --- a/target/linux/generic/pending-5.10/640-12-netfilter-nft_flow_offload-add-dsa-support.patch +++ b/target/linux/generic/pending-5.10/640-14-netfilter-nft_flow_offload-add-dsa-support.patch @@ -1,5 +1,5 @@ From: Pablo Neira Ayuso -Date: Mon, 18 Jan 2021 22:27:45 +0100 +Date: Thu, 4 Mar 2021 19:22:55 +0100 Subject: [PATCH] netfilter: nft_flow_offload: add dsa support Replace the master ethernet device by the dsa slave port. @@ -9,15 +9,15 @@ Signed-off-by: Pablo Neira Ayuso --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c -@@ -86,6 +86,7 @@ static void nft_dev_path_info(const stru +@@ -89,6 +89,7 @@ static void nft_dev_path_info(const stru path = &stack->path[i]; switch (path->type) { case DEV_PATH_ETHERNET: + case DEV_PATH_DSA: case DEV_PATH_VLAN: - info->dev = path->dev; - if (is_zero_ether_addr(info->h_source)) -@@ -93,6 +94,10 @@ static void nft_dev_path_info(const stru + case DEV_PATH_PPPOE: + info->indev = path->dev; +@@ -97,6 +98,10 @@ static void nft_dev_path_info(const stru if (path->type == DEV_PATH_ETHERNET) break; @@ -26,5 +26,5 @@ Signed-off-by: Pablo Neira Ayuso + break; + } - /* DEV_PATH_VLAN */ - if (info->num_vlans >= NF_FLOW_TABLE_VLAN_MAX) { + /* DEV_PATH_VLAN and DEV_PATH_PPPOE */ + if (info->num_encaps >= NF_FLOW_TABLE_ENCAP_MAX) { diff --git a/target/linux/generic/pending-5.10/640-11-netfilter-flowtable-add-offload-support-for-xmit-pat.patch b/target/linux/generic/pending-5.10/640-15-netfilter-flowtable-add-offload-support-for-xmit-pat.patch similarity index 98% rename from target/linux/generic/pending-5.10/640-11-netfilter-flowtable-add-offload-support-for-xmit-pat.patch rename to target/linux/generic/pending-5.10/640-15-netfilter-flowtable-add-offload-support-for-xmit-pat.patch index 508dc90e14c..696ea033326 100644 --- a/target/linux/generic/pending-5.10/640-11-netfilter-flowtable-add-offload-support-for-xmit-pat.patch +++ b/target/linux/generic/pending-5.10/640-15-netfilter-flowtable-add-offload-support-for-xmit-pat.patch @@ -229,12 +229,12 @@ tag to the driver. + other_tuple = &flow->tuplehash[!dir].tuple; + -+ for (i = 0; i < other_tuple->in_vlan_num; i++) { ++ for (i = 0; i < other_tuple->encap_num; i++) { + struct flow_action_entry *entry = flow_action_entry_next(flow_rule); + + entry->id = FLOW_ACTION_VLAN_PUSH; -+ entry->vlan.vid = other_tuple->in_vlan[i].id; -+ entry->vlan.proto = other_tuple->in_vlan[i].proto; ++ entry->vlan.vid = other_tuple->encap[i].id; ++ entry->vlan.proto = other_tuple->encap[i].proto; + } + + return 0; diff --git a/target/linux/generic/pending-5.10/640-15-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch b/target/linux/generic/pending-5.10/640-15-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch deleted file mode 100644 index 1c65a5e218c..00000000000 --- a/target/linux/generic/pending-5.10/640-15-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch +++ /dev/null @@ -1,51 +0,0 @@ -From: Pablo Neira Ayuso -Date: Tue, 2 Feb 2021 17:10:07 +0100 -Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if - hardware offload is enabled - -If there is a forward path to reach an ethernet device and hardware -offload is enabled, then use the direct xmit path. ---- - ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -73,9 +73,18 @@ struct nft_forward_info { - enum flow_offload_xmit_type xmit_type; - }; - -+static bool nft_is_valid_ether_device(const struct net_device *dev) -+{ -+ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || -+ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) -+ return false; -+ -+ return true; -+} -+ - static void nft_dev_path_info(const struct net_device_path_stack *stack, - struct nft_forward_info *info, -- unsigned char *ha) -+ unsigned char *ha, struct nf_flowtable *flowtable) - { - const struct net_device_path *path; - int i; -@@ -131,6 +140,10 @@ static void nft_dev_path_info(const stru - break; - } - } -+ -+ if (nf_flowtable_hw_offload(flowtable) && -+ nft_is_valid_ether_device(info->dev)) -+ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; - } - - static bool nft_flowtable_find_dev(const struct net_device *dev, -@@ -162,7 +175,7 @@ static void nft_dev_forward_path(struct - int i; - - if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) -- nft_dev_path_info(&stack, &info, ha); -+ nft_dev_path_info(&stack, &info, ha, &ft->data); - - if (!info.dev || !nft_flowtable_find_dev(info.dev, ft)) - return; diff --git a/target/linux/generic/pending-5.10/640-13-dsa-slave-add-support-for-TC_SETUP_FT.patch b/target/linux/generic/pending-5.10/640-16-dsa-slave-add-support-for-TC_SETUP_FT.patch similarity index 100% rename from target/linux/generic/pending-5.10/640-13-dsa-slave-add-support-for-TC_SETUP_FT.patch rename to target/linux/generic/pending-5.10/640-16-dsa-slave-add-support-for-TC_SETUP_FT.patch diff --git a/target/linux/generic/pending-5.10/640-16-netfilter-nft_flow_offload-fix-bridge-vlan-tag-handl.patch b/target/linux/generic/pending-5.10/640-16-netfilter-nft_flow_offload-fix-bridge-vlan-tag-handl.patch deleted file mode 100644 index 5877e91e785..00000000000 --- a/target/linux/generic/pending-5.10/640-16-netfilter-nft_flow_offload-fix-bridge-vlan-tag-handl.patch +++ /dev/null @@ -1,22 +0,0 @@ -From: Felix Fietkau -Date: Wed, 10 Feb 2021 10:23:38 +0100 -Subject: [PATCH] netfilter: nft_flow_offload: fix bridge vlan tag handling - -the brigde type uses the path->bridge.vlan_* fields - -Signed-off-by: Felix Fietkau ---- - ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -123,8 +123,8 @@ static void nft_dev_path_info(const stru - - switch (path->bridge.vlan_mode) { - case DEV_PATH_BR_VLAN_TAG: -- info->vid[info->num_vlans] = path->vlan.id; -- info->vproto[info->num_vlans] = path->vlan.proto; -+ info->vid[info->num_vlans] = path->bridge.vlan_id; -+ info->vproto[info->num_vlans] = path->bridge.vlan_proto; - info->num_vlans++; - break; - case DEV_PATH_BR_VLAN_UNTAG: diff --git a/target/linux/generic/pending-5.10/640-17-netfilter-flowtable-rework-ingress-vlan-matching.patch b/target/linux/generic/pending-5.10/640-17-netfilter-flowtable-rework-ingress-vlan-matching.patch deleted file mode 100644 index 67ec263f517..00000000000 --- a/target/linux/generic/pending-5.10/640-17-netfilter-flowtable-rework-ingress-vlan-matching.patch +++ /dev/null @@ -1,143 +0,0 @@ -From: Felix Fietkau -Date: Wed, 10 Feb 2021 19:39:23 +0100 -Subject: [PATCH] netfilter: flowtable: rework ingress vlan matching - -When dealing with bridges with VLAN filtering and DSA/switchdev offload, -the hardware could offload adding a VLAN tag configured in the bridge. -Since there doesn't seem to be an easy way to detect that, this patch -reworks the code to optionally match the last VLAN tag that would otherwise -be inserted by the bridge. -This matters when bypassing the bridge and attaching an ingress hook on -a DSA port below it. - -Signed-off-by: Felix Fietkau ---- - ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -115,14 +115,15 @@ struct flow_offload_tuple { - - u8 l3proto; - u8 l4proto; -- struct { -- u16 id; -- __be16 proto; -- } in_vlan[NF_FLOW_TABLE_VLAN_MAX]; - - /* All members above are keys for lookups, see flow_offload_hash(). */ - struct { } __hash; - -+ struct { -+ u16 id; -+ __be16 proto; -+ } in_vlan[NF_FLOW_TABLE_VLAN_MAX], in_pvid; -+ - u8 dir:4, - xmit_type:2, - in_vlan_num:2; ---- a/net/netfilter/nf_flow_table_ip.c -+++ b/net/netfilter/nf_flow_table_ip.c -@@ -281,12 +281,13 @@ static bool nf_flow_skb_vlan_protocol(co - } - - static void nf_flow_vlan_pop(struct sk_buff *skb, -- struct flow_offload_tuple_rhash *tuplehash) -+ struct flow_offload_tuple_rhash *tuplehash, -+ bool strip_pvid) - { - struct vlan_hdr *vlan_hdr; - int i; - -- for (i = 0; i < tuplehash->tuple.in_vlan_num; i++) { -+ for (i = 0; i < tuplehash->tuple.in_vlan_num + strip_pvid; i++) { - if (skb_vlan_tag_present(skb)) { - __vlan_hwaccel_clear_tag(skb); - continue; -@@ -316,6 +317,31 @@ static unsigned int nf_flow_queue_xmit(s - return NF_STOLEN; - } - -+static bool -+nf_flow_offload_check_vlan(struct flow_offload_tuple *tuple, -+ struct flow_offload_tuple *flow_tuple, -+ bool *strip_pvid) -+{ -+ int i, cur = 0; -+ -+ if (flow_tuple->in_pvid.proto && -+ !memcmp(&tuple->in_vlan[0], &flow_tuple->in_pvid, -+ sizeof(tuple->in_vlan[0]))) -+ cur++; -+ -+ *strip_pvid = cur; -+ -+ for (i = 0; i < flow_tuple->in_vlan_num; i++, cur++) { -+ if (!memcmp(&tuple->in_vlan[cur], &flow_tuple->in_vlan[i], -+ sizeof(tuple->in_vlan[0]))) -+ continue; -+ -+ return false; -+ } -+ -+ return true; -+} -+ - unsigned int - nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, - const struct nf_hook_state *state) -@@ -329,6 +355,7 @@ nf_flow_offload_ip_hook(void *priv, stru - struct rtable *rt; - unsigned int thoff; - struct iphdr *iph; -+ bool strip_pvid; - __be32 nexthop; - u32 offset = 0; - int ret; -@@ -344,6 +371,10 @@ nf_flow_offload_ip_hook(void *priv, stru - if (tuplehash == NULL) - return NF_ACCEPT; - -+ if (!nf_flow_offload_check_vlan(&tuple, &tuplehash->tuple, -+ &strip_pvid)) -+ return NF_ACCEPT; -+ - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - -@@ -368,7 +399,7 @@ nf_flow_offload_ip_hook(void *priv, stru - return NF_ACCEPT; - } - -- nf_flow_vlan_pop(skb, tuplehash); -+ nf_flow_vlan_pop(skb, tuplehash, strip_pvid); - thoff -= offset; - - if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0) -@@ -596,6 +627,7 @@ nf_flow_offload_ipv6_hook(void *priv, st - struct net_device *outdev; - struct ipv6hdr *ip6h; - struct rt6_info *rt; -+ bool strip_pvid; - u32 offset = 0; - int ret; - -@@ -610,6 +642,10 @@ nf_flow_offload_ipv6_hook(void *priv, st - if (tuplehash == NULL) - return NF_ACCEPT; - -+ if (!nf_flow_offload_check_vlan(&tuple, &tuplehash->tuple, -+ &strip_pvid)) -+ return NF_ACCEPT; -+ - dir = tuplehash->tuple.dir; - flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); - -@@ -630,7 +666,7 @@ nf_flow_offload_ipv6_hook(void *priv, st - return NF_ACCEPT; - } - -- nf_flow_vlan_pop(skb, tuplehash); -+ nf_flow_vlan_pop(skb, tuplehash, strip_pvid); - - if (skb_try_make_writable(skb, sizeof(*ip6h))) - return NF_DROP; diff --git a/target/linux/generic/pending-5.10/640-17-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch b/target/linux/generic/pending-5.10/640-17-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch new file mode 100644 index 00000000000..26d172bcf78 --- /dev/null +++ b/target/linux/generic/pending-5.10/640-17-netfilter-nft_flow_offload-use-direct-xmit-if-hardwa.patch @@ -0,0 +1,108 @@ +From: Pablo Neira Ayuso +Date: Thu, 4 Mar 2021 19:24:11 +0100 +Subject: [PATCH] netfilter: nft_flow_offload: use direct xmit if + hardware offload is enabled + +If there is a forward path to reach an ethernet device and hardware +offload is enabled, then use the direct xmit path. +--- + +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -131,6 +131,7 @@ struct flow_offload_tuple { + struct dst_entry *dst_cache; + struct { + u32 ifidx; ++ u32 hw_ifidx; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + } out; +@@ -188,6 +189,7 @@ struct nf_flow_route { + } in; + struct { + u32 ifindex; ++ u32 hw_ifindex; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + } out; +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -106,6 +106,7 @@ static int flow_offload_fill_route(struc + memcpy(flow_tuple->out.h_source, route->tuple[dir].out.h_source, + ETH_ALEN); + flow_tuple->out.ifidx = route->tuple[dir].out.ifindex; ++ flow_tuple->out.hw_ifidx = route->tuple[dir].out.hw_ifindex; + break; + case FLOW_OFFLOAD_XMIT_XFRM: + case FLOW_OFFLOAD_XMIT_NEIGH: +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -506,7 +506,7 @@ static void flow_offload_redirect(struct + switch (this_tuple->xmit_type) { + case FLOW_OFFLOAD_XMIT_DIRECT: + this_tuple = &flow->tuplehash[dir].tuple; +- ifindex = this_tuple->out.ifidx; ++ ifindex = this_tuple->out.hw_ifidx; + break; + case FLOW_OFFLOAD_XMIT_NEIGH: + other_tuple = &flow->tuplehash[!dir].tuple; +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -66,6 +66,7 @@ static int nft_dev_fill_forward_path(con + struct nft_forward_info { + const struct net_device *indev; + const struct net_device *outdev; ++ const struct net_device *hw_outdev; + struct id { + __u16 id; + __be16 proto; +@@ -76,9 +77,18 @@ struct nft_forward_info { + enum flow_offload_xmit_type xmit_type; + }; + ++static bool nft_is_valid_ether_device(const struct net_device *dev) ++{ ++ if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || ++ dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) ++ return false; ++ ++ return true; ++} ++ + static void nft_dev_path_info(const struct net_device_path_stack *stack, + struct nft_forward_info *info, +- unsigned char *ha) ++ unsigned char *ha, struct nf_flowtable *flowtable) + { + const struct net_device_path *path; + int i; +@@ -140,6 +150,12 @@ static void nft_dev_path_info(const stru + } + if (!info->outdev) + info->outdev = info->indev; ++ ++ info->hw_outdev = info->indev; ++ ++ if (nf_flowtable_hw_offload(flowtable) && ++ nft_is_valid_ether_device(info->indev)) ++ info->xmit_type = FLOW_OFFLOAD_XMIT_DIRECT; + } + + static bool nft_flowtable_find_dev(const struct net_device *dev, +@@ -171,7 +187,7 @@ static void nft_dev_forward_path(struct + int i; + + if (nft_dev_fill_forward_path(route, dst, ct, dir, ha, &stack) >= 0) +- nft_dev_path_info(&stack, &info, ha); ++ nft_dev_path_info(&stack, &info, ha, &ft->data); + + if (!info.indev || !nft_flowtable_find_dev(info.indev, ft)) + return; +@@ -187,6 +203,7 @@ static void nft_dev_forward_path(struct + memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); + memcpy(route->tuple[dir].out.h_dest, info.h_dest, ETH_ALEN); + route->tuple[dir].out.ifindex = info.outdev->ifindex; ++ route->tuple[dir].out.hw_ifindex = info.hw_outdev->ifindex; + route->tuple[dir].xmit_type = info.xmit_type; + } + } diff --git a/target/linux/generic/pending-5.10/640-18-netfilter-flowtable-handle-bridge-vlan-filter-offloa.patch b/target/linux/generic/pending-5.10/640-18-netfilter-flowtable-handle-bridge-vlan-filter-offloa.patch deleted file mode 100644 index ba480f3520d..00000000000 --- a/target/linux/generic/pending-5.10/640-18-netfilter-flowtable-handle-bridge-vlan-filter-offloa.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Felix Fietkau -Date: Wed, 10 Feb 2021 19:44:33 +0100 -Subject: [PATCH] netfilter: flowtable: handle bridge vlan filter offload - tags from DSA/switchdev - -When a switchdev/DSA port is an untagged member of a bridge vlan, ingress -packets could potentially be tagged with the id of the VLAN. -When the VLAN port group has been uploaded to switchdev, report the bridge -tag mode as DEV_PATH_BR_VLAN_UNTAG_HW instead of DEV_PATH_BR_VLAN_UNTAG -and handle it in netfilter flow offloading by storing the tag in the tuple -in_pvid field. -This allows the ingress hook to detect the optional tag and remove it for -software offload. This tag processing is for ingress only, egress needs to be -fully untagged - -Signed-off-by: Felix Fietkau ---- - ---- a/include/linux/netdevice.h -+++ b/include/linux/netdevice.h -@@ -853,6 +853,7 @@ struct net_device_path { - DEV_PATH_BR_VLAN_KEEP, - DEV_PATH_BR_VLAN_TAG, - DEV_PATH_BR_VLAN_UNTAG, -+ DEV_PATH_BR_VLAN_UNTAG_HW, - } vlan_mode; - u16 vlan_id; - __be16 vlan_proto; ---- a/include/net/netfilter/nf_flow_table.h -+++ b/include/net/netfilter/nf_flow_table.h -@@ -183,6 +183,10 @@ struct nf_flow_route { - u32 ifindex; - u16 vid[NF_FLOW_TABLE_VLAN_MAX]; - __be16 vproto[NF_FLOW_TABLE_VLAN_MAX]; -+ struct { -+ u16 id; -+ __be16 proto; -+ } pvid; - u8 num_vlans; - } in; - struct { ---- a/net/bridge/br_device.c -+++ b/net/bridge/br_device.c -@@ -435,6 +435,7 @@ static int br_fill_forward_path(struct n - ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto; - ctx->num_vlans++; - break; -+ case DEV_PATH_BR_VLAN_UNTAG_HW: - case DEV_PATH_BR_VLAN_UNTAG: - ctx->num_vlans--; - break; ---- a/net/bridge/br_vlan.c -+++ b/net/bridge/br_vlan.c -@@ -1374,6 +1374,8 @@ int br_vlan_fill_forward_path_mode(struc - - if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) - path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; -+ else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV) -+ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW; - else - path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG; - ---- a/net/netfilter/nf_flow_table_core.c -+++ b/net/netfilter/nf_flow_table_core.c -@@ -98,6 +98,8 @@ static int flow_offload_fill_route(struc - j++; - } - flow_tuple->in_vlan_num = route->tuple[dir].in.num_vlans; -+ flow_tuple->in_pvid.id = route->tuple[dir].in.pvid.id; -+ flow_tuple->in_pvid.proto = route->tuple[dir].in.pvid.proto; - - switch (route->tuple[dir].xmit_type) { - case FLOW_OFFLOAD_XMIT_DIRECT: ---- a/net/netfilter/nft_flow_offload.c -+++ b/net/netfilter/nft_flow_offload.c -@@ -67,6 +67,10 @@ struct nft_forward_info { - const struct net_device *dev; - __u16 vid[NF_FLOW_TABLE_VLAN_MAX]; - __be16 vproto[NF_FLOW_TABLE_VLAN_MAX]; -+ struct { -+ __u16 id; -+ __be16 proto; -+ } pvid; - u8 num_vlans; - u8 h_source[ETH_ALEN]; - u8 h_dest[ETH_ALEN]; -@@ -127,6 +131,10 @@ static void nft_dev_path_info(const stru - info->vproto[info->num_vlans] = path->bridge.vlan_proto; - info->num_vlans++; - break; -+ case DEV_PATH_BR_VLAN_UNTAG_HW: -+ info->pvid.id = info->vid[info->num_vlans - 1]; -+ info->pvid.proto = info->vproto[info->num_vlans - 1]; -+ fallthrough; - case DEV_PATH_BR_VLAN_UNTAG: - info->num_vlans--; - break; -@@ -185,6 +193,8 @@ static void nft_dev_forward_path(struct - route->tuple[!dir].in.vid[i] = info.vid[i]; - route->tuple[!dir].in.vproto[i] = info.vproto[i]; - } -+ route->tuple[!dir].in.pvid.id = info.pvid.id; -+ route->tuple[!dir].in.pvid.proto = info.pvid.proto; - route->tuple[!dir].in.num_vlans = info.num_vlans; - - if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { diff --git a/target/linux/generic/pending-5.10/640-18-netfilter-nf_flow_table-fix-untagging-with-hardware-.patch b/target/linux/generic/pending-5.10/640-18-netfilter-nf_flow_table-fix-untagging-with-hardware-.patch new file mode 100644 index 00000000000..33600a862e7 --- /dev/null +++ b/target/linux/generic/pending-5.10/640-18-netfilter-nf_flow_table-fix-untagging-with-hardware-.patch @@ -0,0 +1,122 @@ +From: Felix Fietkau +Date: Mon, 8 Mar 2021 12:06:44 +0100 +Subject: [PATCH] netfilter: nf_flow_table: fix untagging with + hardware-offloaded bridge vlan_filtering + +When switchdev offloading is enabled, treat an untagged VLAN as tagged for +ingress only + +Signed-off-by: Felix Fietkau +--- + +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -855,6 +855,7 @@ struct net_device_path { + DEV_PATH_BR_VLAN_KEEP, + DEV_PATH_BR_VLAN_TAG, + DEV_PATH_BR_VLAN_UNTAG, ++ DEV_PATH_BR_VLAN_UNTAG_HW, + } vlan_mode; + u16 vlan_id; + __be16 vlan_proto; +--- a/include/net/netfilter/nf_flow_table.h ++++ b/include/net/netfilter/nf_flow_table.h +@@ -123,9 +123,10 @@ struct flow_offload_tuple { + /* All members above are keys for lookups, see flow_offload_hash(). */ + struct { } __hash; + +- u8 dir:4, ++ u8 dir:2, + xmit_type:2, +- encap_num:2; ++ encap_num:2, ++ in_vlan_ingress:2; + u16 mtu; + union { + struct dst_entry *dst_cache; +@@ -185,7 +186,8 @@ struct nf_flow_route { + u16 id; + __be16 proto; + } encap[NF_FLOW_TABLE_ENCAP_MAX]; +- u8 num_encaps; ++ u8 num_encaps:2, ++ ingress_vlans:2; + } in; + struct { + u32 ifindex; +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -435,6 +435,7 @@ static int br_fill_forward_path(struct n + ctx->vlan[ctx->num_vlans].proto = path->bridge.vlan_proto; + ctx->num_vlans++; + break; ++ case DEV_PATH_BR_VLAN_UNTAG_HW: + case DEV_PATH_BR_VLAN_UNTAG: + ctx->num_vlans--; + break; +--- a/net/bridge/br_vlan.c ++++ b/net/bridge/br_vlan.c +@@ -1374,6 +1374,8 @@ int br_vlan_fill_forward_path_mode(struc + + if (path->bridge.vlan_mode == DEV_PATH_BR_VLAN_TAG) + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_KEEP; ++ else if (v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV) ++ path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG_HW; + else + path->bridge.vlan_mode = DEV_PATH_BR_VLAN_UNTAG; + +--- a/net/netfilter/nf_flow_table_core.c ++++ b/net/netfilter/nf_flow_table_core.c +@@ -95,6 +95,8 @@ static int flow_offload_fill_route(struc + for (i = route->tuple[dir].in.num_encaps - 1; i >= 0; i--) { + flow_tuple->encap[j].id = route->tuple[dir].in.encap[i].id; + flow_tuple->encap[j].proto = route->tuple[dir].in.encap[i].proto; ++ if (route->tuple[dir].in.ingress_vlans & BIT(i)) ++ flow_tuple->in_vlan_ingress |= BIT(j); + j++; + } + flow_tuple->encap_num = route->tuple[dir].in.num_encaps; +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -592,8 +592,12 @@ nf_flow_rule_route_common(struct net *ne + other_tuple = &flow->tuplehash[!dir].tuple; + + for (i = 0; i < other_tuple->encap_num; i++) { +- struct flow_action_entry *entry = flow_action_entry_next(flow_rule); ++ struct flow_action_entry *entry; + ++ if (other_tuple->in_vlan_ingress & BIT(i)) ++ continue; ++ ++ entry = flow_action_entry_next(flow_rule); + entry->id = FLOW_ACTION_VLAN_PUSH; + entry->vlan.vid = other_tuple->encap[i].id; + entry->vlan.proto = other_tuple->encap[i].proto; +--- a/net/netfilter/nft_flow_offload.c ++++ b/net/netfilter/nft_flow_offload.c +@@ -72,6 +72,7 @@ struct nft_forward_info { + __be16 proto; + } encap[NF_FLOW_TABLE_ENCAP_MAX]; + u8 num_encaps; ++ u8 ingress_vlans; + u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + enum flow_offload_xmit_type xmit_type; +@@ -130,6 +131,9 @@ static void nft_dev_path_info(const stru + memcpy(info->h_source, path->dev->dev_addr, ETH_ALEN); + + switch (path->bridge.vlan_mode) { ++ case DEV_PATH_BR_VLAN_UNTAG_HW: ++ info->ingress_vlans |= BIT(info->num_encaps - 1); ++ break; + case DEV_PATH_BR_VLAN_TAG: + info->encap[info->num_encaps].id = path->bridge.vlan_id; + info->encap[info->num_encaps].proto = path->bridge.vlan_proto; +@@ -198,6 +202,7 @@ static void nft_dev_forward_path(struct + route->tuple[!dir].in.encap[i].proto = info.encap[i].proto; + } + route->tuple[!dir].in.num_encaps = info.num_encaps; ++ route->tuple[!dir].in.ingress_vlans = info.ingress_vlans; + + if (info.xmit_type == FLOW_OFFLOAD_XMIT_DIRECT) { + memcpy(route->tuple[dir].out.h_source, info.h_source, ETH_ALEN); diff --git a/target/linux/generic/pending-5.10/640-19-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch b/target/linux/generic/pending-5.10/640-19-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch new file mode 100644 index 00000000000..3eaad27cdf8 --- /dev/null +++ b/target/linux/generic/pending-5.10/640-19-net-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch @@ -0,0 +1,26 @@ +From: Pablo Neira Ayuso +Date: Tue, 2 Mar 2021 00:51:31 +0100 +Subject: [PATCH] net: flow_offload: add FLOW_ACTION_PPPOE_PUSH + +--- + +--- a/include/net/flow_offload.h ++++ b/include/net/flow_offload.h +@@ -147,6 +147,7 @@ enum flow_action_id { + FLOW_ACTION_MPLS_POP, + FLOW_ACTION_MPLS_MANGLE, + FLOW_ACTION_GATE, ++ FLOW_ACTION_PPPOE_PUSH, + NUM_FLOW_ACTIONS, + }; + +@@ -271,6 +272,9 @@ struct flow_action_entry { + u32 num_entries; + struct action_gate_entry *entries; + } gate; ++ struct { /* FLOW_ACTION_PPPOE_PUSH */ ++ u16 sid; ++ } pppoe; + }; + struct flow_action_cookie *cookie; /* user defined action cookie */ + }; diff --git a/target/linux/generic/pending-5.10/640-20-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch b/target/linux/generic/pending-5.10/640-20-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch new file mode 100644 index 00000000000..fcafff1fffa --- /dev/null +++ b/target/linux/generic/pending-5.10/640-20-netfilter-flowtable-support-for-FLOW_ACTION_PPPOE_PU.patch @@ -0,0 +1,31 @@ +From: Pablo Neira Ayuso +Date: Tue, 2 Mar 2021 01:01:50 +0100 +Subject: [PATCH] netfilter: flowtable: support for + FLOW_ACTION_PPPOE_PUSH + +--- + +--- a/net/netfilter/nf_flow_table_offload.c ++++ b/net/netfilter/nf_flow_table_offload.c +@@ -598,9 +598,18 @@ nf_flow_rule_route_common(struct net *ne + continue; + + entry = flow_action_entry_next(flow_rule); +- entry->id = FLOW_ACTION_VLAN_PUSH; +- entry->vlan.vid = other_tuple->encap[i].id; +- entry->vlan.proto = other_tuple->encap[i].proto; ++ ++ switch (other_tuple->encap[i].proto) { ++ case htons(ETH_P_PPP_SES): ++ entry->id = FLOW_ACTION_PPPOE_PUSH; ++ entry->pppoe.sid = other_tuple->encap[i].id; ++ break; ++ case htons(ETH_P_8021Q): ++ entry->id = FLOW_ACTION_VLAN_PUSH; ++ entry->vlan.vid = other_tuple->encap[i].id; ++ entry->vlan.proto = other_tuple->encap[i].proto; ++ break; ++ } + } + + return 0; diff --git a/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch index 6d0c84c494d..04222214688 100644 --- a/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch +++ b/target/linux/generic/pending-5.10/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -11,7 +11,7 @@ Signed-off-by: Felix Fietkau --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h -@@ -2031,6 +2031,8 @@ struct net_device { +@@ -2033,6 +2033,8 @@ struct net_device { struct netdev_hw_addr_list mc; struct netdev_hw_addr_list dev_addrs; diff --git a/target/linux/generic/pending-5.10/690-net-add-support-for-threaded-NAPI-polling.patch b/target/linux/generic/pending-5.10/690-net-add-support-for-threaded-NAPI-polling.patch index b2c2d00ec00..24b78b94d73 100644 --- a/target/linux/generic/pending-5.10/690-net-add-support-for-threaded-NAPI-polling.patch +++ b/target/linux/generic/pending-5.10/690-net-add-support-for-threaded-NAPI-polling.patch @@ -50,7 +50,7 @@ Signed-off-by: Felix Fietkau }; enum gro_result { -@@ -2411,6 +2414,26 @@ void netif_napi_add(struct net_device *d +@@ -2413,6 +2416,26 @@ void netif_napi_add(struct net_device *d int (*poll)(struct napi_struct *, int), int weight); /** diff --git a/target/linux/generic/pending-5.10/770-16-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch b/target/linux/generic/pending-5.10/770-16-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch index fa9cbcafc89..2f1ae6cde63 100644 --- a/target/linux/generic/pending-5.10/770-16-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch +++ b/target/linux/generic/pending-5.10/770-16-net-ethernet-mtk_eth_soc-add-flow-offloading-support.patch @@ -80,7 +80,7 @@ Signed-off-by: Pablo Neira Ayuso #endif /* MTK_ETH_H */ --- /dev/null +++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c -@@ -0,0 +1,478 @@ +@@ -0,0 +1,491 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2020 Felix Fietkau @@ -113,6 +113,10 @@ Signed-off-by: Pablo Neira Ayuso + __be16 proto; + u8 num; + } vlan; ++ struct { ++ u16 sid; ++ u8 num; ++ } pppoe; +}; + +struct mtk_flow_entry { @@ -311,13 +315,20 @@ Signed-off-by: Pablo Neira Ayuso + break; + case FLOW_ACTION_VLAN_PUSH: + if (data.vlan.num == 1 || -+ data.vlan.proto != ETH_P_8021Q) ++ act->vlan.proto != htons(ETH_P_8021Q)) + return -EOPNOTSUPP; + + data.vlan.id = act->vlan.vid; + data.vlan.proto = act->vlan.proto; + data.vlan.num++; + break; ++ case FLOW_ACTION_PPPOE_PUSH: ++ if (data.pppoe.num == 1) ++ return -EOPNOTSUPP; ++ ++ data.pppoe.sid = act->pppoe.sid; ++ data.pppoe.num++; ++ break; + default: + return -EOPNOTSUPP; + } @@ -392,11 +403,13 @@ Signed-off-by: Pablo Neira Ayuso + } + + if (data.vlan.num == 1) { -+ if (data.vlan.proto != ETH_P_8021Q) ++ if (data.vlan.proto != htons(ETH_P_8021Q)) + return -EOPNOTSUPP; + + mtk_foe_entry_set_vlan(&foe, data.vlan.id); + } ++ if (data.pppoe.num == 1) ++ mtk_foe_entry_set_pppoe(&foe, data.pppoe.sid); + + err = mtk_flow_set_output_device(eth, &foe, odev); + if (err) -- 2.30.2