From 18d27bed0880b1ac8638a6f4f2edc2ecc6b5c6a1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Nov 2025 23:59:47 +0100 Subject: [PATCH] netfilter: flowtable: inline pppoe encapsulation in xmit path Push the pppoe header from the flowtable xmit path, inlining is faster than the original xmit path because it can avoid some locking. This is based on a patch originally written by wenxu. Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_flow_table_ip.c | 42 ++++++++++++++++++++++++++++++ net/netfilter/nf_flow_table_path.c | 9 ++----- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c index aef799edca9f7..ee6ec63257d11 100644 --- a/net/netfilter/nf_flow_table_ip.c +++ b/net/netfilter/nf_flow_table_ip.c @@ -413,6 +413,44 @@ static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx, return 1; } +static int nf_flow_pppoe_push(struct sk_buff *skb, u16 id) +{ + int data_len = skb->len + sizeof(__be16); + struct ppp_hdr { + struct pppoe_hdr hdr; + __be16 proto; + } *ph; + __be16 proto; + + if (skb_cow_head(skb, PPPOE_SES_HLEN)) + return -1; + + switch (skb->protocol) { + case htons(ETH_P_IP): + proto = htons(PPP_IP); + break; + case htons(ETH_P_IPV6): + proto = htons(PPP_IPV6); + break; + default: + return -1; + } + + __skb_push(skb, PPPOE_SES_HLEN); + skb_reset_network_header(skb); + + ph = (struct ppp_hdr *)(skb->data); + ph->hdr.ver = 1; + ph->hdr.type = 1; + ph->hdr.code = 0; + ph->hdr.sid = htons(id); + ph->hdr.length = htons(data_len); + ph->proto = proto; + skb->protocol = htons(ETH_P_PPP_SES); + + return 0; +} + static int nf_flow_encap_push(struct sk_buff *skb, struct flow_offload_tuple *tuple) { @@ -426,6 +464,10 @@ static int nf_flow_encap_push(struct sk_buff *skb, tuple->encap[i].id) < 0) return -1; break; + case htons(ETH_P_PPP_SES): + if (nf_flow_pppoe_push(skb, tuple->encap[i].id) < 0) + return -1; + break; } } diff --git a/net/netfilter/nf_flow_table_path.c b/net/netfilter/nf_flow_table_path.c index 38ebda1afdceb..c51e310bb2ab2 100644 --- a/net/netfilter/nf_flow_table_path.c +++ b/net/netfilter/nf_flow_table_path.c @@ -122,11 +122,8 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack, 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) { - if (!info->outdev) - info->outdev = path->dev; + 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)) @@ -161,9 +158,7 @@ static void nft_dev_path_info(const struct net_device_path_stack *stack, break; } } - if (!info->outdev) - info->outdev = info->indev; - + info->outdev = info->indev; info->hw_outdev = info->indev; if (nf_flowtable_hw_offload(flowtable) && -- 2.47.3