diff --git a/target/linux/generic/hack-5.10/998-fix-pppoe-flow-offload.patch b/target/linux/generic/hack-5.10/998-fix-pppoe-flow-offload.patch new file mode 100755 index 0000000000..1171fb3d73 --- /dev/null +++ b/target/linux/generic/hack-5.10/998-fix-pppoe-flow-offload.patch @@ -0,0 +1,127 @@ +--- a/net/netfilter/xt_FLOWOFFLOAD.c 2022-04-20 07:17:12.515991000 +0800 ++++ b/net/netfilter/xt_FLOWOFFLOAD.c 2022-04-20 07:45:03.874095949 +0800 +@@ -222,13 +222,31 @@ + return false; + } + +-static bool flow_is_valid_ether_device(const struct net_device *dev) ++ ++static void ++xt_flowoffload_get_dest_macaddr(u8 *dest, const struct dst_entry *dst, ++ const void *daddr) + { +- if (!dev || (dev->flags & IFF_LOOPBACK) || dev->type != ARPHRD_ETHER || +- dev->addr_len != ETH_ALEN || !is_valid_ether_addr(dev->dev_addr)) +- return false; ++ struct net_device *dev = dst->dev; ++ struct neighbour *n; ++ u8 nud_state; ++ ++ memset(dest, 0, ETH_ALEN); ++ ++ if (dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || ++ !is_valid_ether_addr(dev->dev_addr)) ++ return; ++ ++ n = dst_neigh_lookup(dst, daddr); ++ if (!n) ++ return; + +- return true; ++ read_lock_bh(&n->lock); ++ nud_state = n->nud_state; ++ if (nud_state & NUD_VALID) ++ memcpy(dest, n->ha, ETH_ALEN); ++ read_unlock_bh(&n->lock); ++ neigh_release(n); + } + + static void +@@ -242,9 +260,7 @@ + struct net_device_path_stack stack; + enum net_device_path_type prev_type; + struct net_device *dev = dst->dev; +- struct neighbour *n; + bool last = false; +- u8 nud_state; + int i; + + route->tuple[!dir].in.ifindex = dev->ifindex; +@@ -253,24 +269,10 @@ + if (route->tuple[dir].xmit_type == FLOW_OFFLOAD_XMIT_XFRM) + return; + +- if ((dev->flags & IFF_LOOPBACK) || +- dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN || +- !is_valid_ether_addr(dev->dev_addr)) +- return; +- +- n = dst_neigh_lookup(dst, daddr); +- if (!n) +- return; +- +- read_lock_bh(&n->lock); +- nud_state = n->nud_state; +- memcpy(route->tuple[dir].out.h_dest, n->ha, ETH_ALEN); +- read_unlock_bh(&n->lock); +- neigh_release(n); +- +- if (!(nud_state & NUD_VALID)) ++ if (dev->flags & IFF_LOOPBACK) + return; + ++ xt_flowoffload_get_dest_macaddr(route->tuple[dir].out.h_dest, dst, daddr); + if (dev_fill_forward_path(dev, route->tuple[dir].out.h_dest, &stack) || + !stack.num_paths) + return; +@@ -281,14 +283,12 @@ + 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) { + 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; +- } + + switch (path->type) { + case DEV_PATH_PPPOE: +@@ -302,9 +302,10 @@ + 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); ++ if (path->type == DEV_PATH_PPPOE){ ++ memcpy(route->tuple[dir].out.h_source,path->encap.h_source, ETH_ALEN); ++ memcpy(route->tuple[dir].out.h_dest,path->encap.h_dest, ETH_ALEN); ++ } + break; + case DEV_PATH_BRIDGE: + switch (path->bridge.vlan_mode) { + +--- a/drivers/net/ppp/pppoe.c 2022-04-18 12:53:13.150031000 +0800 ++++ b/drivers/net/ppp/pppoe.c 2022-04-18 14:42:40.856174129 +0800 +@@ -987,6 +987,7 @@ + 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_source, po->pppoe_dev->dev_addr, ETH_ALEN); + memcpy(path->encap.h_dest, po->pppoe_pa.remote, ETH_ALEN); + path->dev = ctx->dev; + ctx->dev = dev; + +--- a/include/linux/netdevice.h 2022-04-18 12:53:16.722194000 +0800 ++++ b/include/linux/netdevice.h 2022-04-18 15:05:42.459170231 +0800 +@@ -843,6 +843,7 @@ + struct { + u16 id; + __be16 proto; ++ u8 h_source[ETH_ALEN]; + u8 h_dest[ETH_ALEN]; + } encap; + struct {