[openwrt/openwrt] kernel: update 5.10 flow offload patches

LEDE Commits lede-commits at lists.infradead.org
Fri Mar 12 19:24:05 GMT 2021


nbd pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/0d5bf53197481d291f9a541eefa03b11a34033f9

commit 0d5bf53197481d291f9a541eefa03b11a34033f9
Author: Felix Fietkau <nbd at nbd.name>
AuthorDate: Mon Mar 8 17:20:20 2021 +0100

    kernel: update 5.10 flow offload patches
    
    Includes PPPoE support and VLAN related fixes
    
    Signed-off-by: Felix Fietkau <nbd at nbd.name>
---
 ... 650-netfilter-add-xt_FLOWOFFLOAD-target.patch} |  64 +++--
 ...-forwarding-path-from-virtual-netdevice-a.patch |   8 +-
 ...-resolve-forwarding-path-for-vlan-devices.patch |   6 +-
 ...lowtable-use-dev_fill_forward_path-to-obt.patch |  10 +-
 ...lowtable-use-dev_fill_forward_path-to-obt.patch |  26 +-
 ...0-07-netfilter-flowtable-add-vlan-support.patch | 165 +++++++------
 ...resolve-VLAN-tag-actions-in-forwarding-pa.patch |   4 +-
 ...t_flow_offload-add-bridge-vlan-filtering.patch} |  10 +-
 ...olve-forwarding-path-for-bridge-pppoe-dev.patch | 100 ++++++++
 ...olve-forwarding-path-for-dsa-slave-ports.patch} |  10 +-
 ...-13-netfilter-flowtable-add-pppoe-support.patch | 263 +++++++++++++++++++++
 ...tfilter-nft_flow_offload-add-dsa-support.patch} |  14 +-
 ...owtable-add-offload-support-for-xmit-pat.patch} |   6 +-
 ...ft_flow_offload-use-direct-xmit-if-hardwa.patch |  51 ----
 ...16-dsa-slave-add-support-for-TC_SETUP_FT.patch} |   0
 ...ft_flow_offload-fix-bridge-vlan-tag-handl.patch |  22 --
 ...er-flowtable-rework-ingress-vlan-matching.patch | 143 -----------
 ...ft_flow_offload-use-direct-xmit-if-hardwa.patch | 108 +++++++++
 ...lowtable-handle-bridge-vlan-filter-offloa.patch | 106 ---------
 ...f_flow_table-fix-untagging-with-hardware-.patch | 122 ++++++++++
 ...t-flow_offload-add-FLOW_ACTION_PPPOE_PUSH.patch |  26 ++
 ...lowtable-support-for-FLOW_ACTION_PPPOE_PU.patch |  31 +++
 ...80-NET-skip-GRO-for-foreign-MAC-addresses.patch |   2 +-
 ...net-add-support-for-threaded-NAPI-polling.patch |   2 +-
 ...t-mtk_eth_soc-add-flow-offloading-support.patch |  19 +-
 25 files changed, 845 insertions(+), 473 deletions(-)

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 eb540acc85..97aa7a673b 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 <nbd at nbd.name>
 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 <nbd at nbd.name>
 ---
@@ -98,7 +98,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  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 <nbd at nbd.name>
 + *
@@ -265,20 +265,14 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 +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 <nbd at nbd.name>
 +	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 <nbd at nbd.name>
 +	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 <nbd at nbd.name>
 +	}
 +
 +	*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 <nbd at nbd.name>
  #include <net/netfilter/nf_flow_table.h>
  #include <net/netfilter/nf_conntrack.h>
  #include <net/netfilter/nf_conntrack_core.h>
-@@ -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 <nbd at nbd.name>
  		      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 <nbd at nbd.name>
 +#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 953446baab..603dddfc36 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 <pablo at netfilter.org>
-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 <pablo at netfilter.org>
   *	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 <pablo at netfilter.org>
  	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 ddc0de0d3b..26fb64509c 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 <pablo at netfilter.org>
 +		struct {
 +			u16		id;
 +			__be16		proto;
-+		} vlan;
++		} encap;
 +	};
  };
  
@@ -59,8 +59,8 @@ Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>
 +	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 34724a5696..1f61cff09d 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 <pablo at netfilter.org>
 +}
 +
 +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 <pablo at netfilter.org>
 +		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 <pablo at netfilter.org>
 +	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 d4bf68a690..ada14e6c7a 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 <pablo at netfilter.org>
-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 <pablo at netfilter.org>
  	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 <pablo at netfilter.org>
  		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 <pablo at netfilter.org>
 +			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 <pablo at netfilter.org>
 +	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 77aeaccbce..fea1b59dc3 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 <pablo at netfilter.org>
  	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 <pablo at netfilter.org>
 +	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 <pablo at netfilter.org>
 -
 +	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 <pablo at netfilter.org>
  	}
  
  	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 <pablo at netfilter.org>
  	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 <pablo at netfilter.org>
  
  	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 <pablo at netfilter.org>
 +	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 <pablo at netfilter.org>
  
 -	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 <pablo at netfilter.org>
  		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 <pablo at netfilter.org>
  
  	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 <pablo at netfilter.org>
  
  	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 <pablo at netfilter.org>
  		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 <pablo at netfilter.org>
 +				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 <pablo at netfilter.org>
  
  	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 fb5f736648..9bd1f6b4c6 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 <pablo at netfilter.org>
 @@ -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 <pablo at netfilter.org>
 --- 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 2e833117db..86fd6bf77b 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 <pablo at netfilter.org>
 
 --- 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 0000000000..34d918206f
--- /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 <pablo at netfilter.org>
+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 64a2b14af5..3e7a9eaef9 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 <nbd at nbd.name>
-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 <nbd at nbd.name>
 ---
 
 --- 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 0000000000..6a14514565
--- /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 <pablo at netfilter.org>
+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 <linux/ip.h>
+ #include <linux/ipv6.h>
+ #include <linux/netdevice.h>
++#include <linux/if_ether.h>
++#include <linux/if_pppox.h>
++#include <linux/ppp_defs.h>
+ #include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/ip6_route.h>
+@@ -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 3689a476b3..7ff5dad1f7 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 <pablo at netfilter.org>
-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 <pablo at netfilter.org>
 
 --- 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 <pablo at netfilter.org>
 +				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 508dc90e14..696ea03332 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 1c65a5e218..0000000000
--- 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 <pablo at netfilter.org>
-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 5877e91e78..0000000000
--- 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 <nbd at nbd.name>
-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 <nbd at nbd.name>
----
-
---- 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 67ec263f51..0000000000
--- 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 <nbd at nbd.name>
-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 <nbd at nbd.name>
----
-
---- 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 0000000000..26d172bcf7
--- /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 <pablo at netfilter.org>
+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 ba480f3520..0000000000
--- 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 <nbd at nbd.name>
-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 <nbd at nbd.name>
----
-
---- 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 0000000000..33600a862e
--- /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 <nbd at nbd.name>
+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 <nbd at nbd.name>
+---
+
+--- 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 0000000000..3eaad27cdf
--- /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 <pablo at netfilter.org>
+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 0000000000..fcafff1fff
--- /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 <pablo at netfilter.org>
+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 6d0c84c494..0422221468 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 <nbd at nbd.name>
 
 --- 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 b2c2d00ec0..24b78b94d7 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 <nbd at nbd.name>
  };
  
  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 fa9cbcafc8..2f1ae6cde6 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 <pablo at netfilter.org>
  #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 <nbd at nbd.name>
@@ -113,6 +113,10 @@ Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>
 +		__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 <pablo at netfilter.org>
 +			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 <pablo at netfilter.org>
 +	}
 +
 +	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)



More information about the lede-commits mailing list