--- 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 {