From: ThisSeanZhang <thisseanzhang@gmail.com>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
netdev@vger.kernel.org, Nick Hudson <nhudson@akamai.com>,
Felix Fietkau <nbd@nbd.name>, Qingfang Deng <dqfext@gmail.com>
Subject: [RFC bpf-next v2 1/3] bpf: Add PPPoE encap support to bpf_skb_adjust_room
Date: Sat, 3 Oct 2026 15:33:45 -0400 [thread overview]
Message-ID: <20261003193347.1137527-2-thisseanzhang@gmail.com> (raw)
In-Reply-To: <20261003193347.1137527-1-thisseanzhang@gmail.com>
Add a new BPF_F_ADJ_ROOM_ENCAP_PPPOE flag to bpf_skb_adjust_room() so
that a TC BPF program can encapsulate an IPv4 or IPv6 packet into a
PPPoE session header:
bpf_skb_adjust_room(skb, PPPOE_SES_HLEN, BPF_ADJ_ROOM_MAC,
BPF_F_ADJ_ROOM_ENCAP_PPPOE);
The flag inserts eight bytes between the MAC and network headers: the
six-byte PPPoE session header followed by the two-byte PPP protocol
field. It then updates the skb metadata, including skb->protocol and
skb->mac_len. The BPF program remains responsible for filling in the
PPPoE header and the Ethernet ethertype, for example with
bpf_skb_store_bytes().
Previously, a TC program could add the header bytes manually, but the
skb would continue to be treated as a plain IP packet because its
protocol metadata was unchanged. With the stale skb->protocol, software
GSO may select a non-PPPoE segmentation handler and process the packet
incorrectly.
This makes the skb metadata compatible with the PPPoE GRO/GSO handlers
registered for ETH_P_PPP_SES. The PPPoE GRO/GSO support must be built in
or loaded before receive-side GRO or software GSO uses those handlers.
Signed-off-by: ThisSeanZhang <thisseanzhang@gmail.com>
---
include/uapi/linux/bpf.h | 12 ++++++++++++
net/core/filter.c | 22 ++++++++++++++++++++++
tools/include/uapi/linux/bpf.h | 12 ++++++++++++
3 files changed, 46 insertions(+)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 732b35cc0..30481d040 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3036,6 +3036,17 @@ union bpf_attr {
* Use with BPF_F_ADJ_ROOM_ENCAP_L2 flag to further specify the
* L2 type as Ethernet.
*
+ * * **BPF_F_ADJ_ROOM_ENCAP_PPPOE**:
+ * Encapsulate the packet in a PPPoE session header. Must be
+ * used with **BPF_ADJ_ROOM_MAC** mode and *len_diff* equal to
+ * the size of the PPPoE session header plus the PPP protocol
+ * field (8 bytes in total). The room is inserted between the
+ * MAC header and the network header, *skb->protocol* is set
+ * to **ETH_P_PPP_SES** and *skb->mac_len* is updated
+ * accordingly. The PPPoE header itself and the ethertype of
+ * the MAC header are filled in by the BPF program, e.g. via
+ * **bpf_skb_store_bytes**.
+ *
* * **BPF_F_ADJ_ROOM_DECAP_L3_IPV4**,
* **BPF_F_ADJ_ROOM_DECAP_L3_IPV6**:
* Indicate the new IP header version after decapsulating the
@@ -6323,6 +6334,7 @@ enum bpf_adj_room_flags {
BPF_F_ADJ_ROOM_DECAP_L4_UDP = (1ULL << 10),
BPF_F_ADJ_ROOM_DECAP_IPXIP4 = (1ULL << 11),
BPF_F_ADJ_ROOM_DECAP_IPXIP6 = (1ULL << 12),
+ BPF_F_ADJ_ROOM_ENCAP_PPPOE = (1ULL << 13),
};
enum {
diff --git a/net/core/filter.c b/net/core/filter.c
index 70dc62167..5b204e316 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -47,6 +47,7 @@
#include <linux/ratelimit.h>
#include <linux/seccomp.h>
#include <linux/if_vlan.h>
+#include <linux/if_pppox.h>
#include <linux/bpf.h>
#include <linux/btf.h>
#include <net/sch_generic.h>
@@ -3583,6 +3584,7 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb)
BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \
BPF_F_ADJ_ROOM_ENCAP_L4_UDP | \
BPF_F_ADJ_ROOM_ENCAP_L2_ETH | \
+ BPF_F_ADJ_ROOM_ENCAP_PPPOE | \
BPF_F_ADJ_ROOM_ENCAP_L2( \
BPF_ADJ_ROOM_ENCAP_L2_MASK))
@@ -3688,6 +3690,14 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
skb_dst_drop(skb);
}
+ if (flags & BPF_F_ADJ_ROOM_ENCAP_PPPOE) {
+ /* Network header points at the inserted PPPoE header. */
+ skb->protocol = htons(ETH_P_PPP_SES);
+ skb_reset_mac_len(skb);
+ if (skb_valid_dst(skb))
+ skb_dst_drop(skb);
+ }
+
if (skb_is_gso(skb)) {
struct skb_shared_info *shinfo = skb_shinfo(skb);
@@ -3874,6 +3884,18 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
return -ENOTSUPP;
}
+ if (flags & BPF_F_ADJ_ROOM_ENCAP_PPPOE) {
+ /* The PPPoE session header has a fixed size and is
+ * inserted directly after the MAC header.
+ */
+ if (shrink || mode != BPF_ADJ_ROOM_MAC ||
+ len_diff != PPPOE_SES_HLEN ||
+ flags & ((BPF_F_ADJ_ROOM_ENCAP_MASK |
+ BPF_F_ADJ_ROOM_DECAP_MASK) &
+ ~BPF_F_ADJ_ROOM_ENCAP_PPPOE))
+ return -EINVAL;
+ }
+
if (flags & BPF_F_ADJ_ROOM_DECAP_MASK) {
u32 len_decap_min = 0;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 732b35cc0..30481d040 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3036,6 +3036,17 @@ union bpf_attr {
* Use with BPF_F_ADJ_ROOM_ENCAP_L2 flag to further specify the
* L2 type as Ethernet.
*
+ * * **BPF_F_ADJ_ROOM_ENCAP_PPPOE**:
+ * Encapsulate the packet in a PPPoE session header. Must be
+ * used with **BPF_ADJ_ROOM_MAC** mode and *len_diff* equal to
+ * the size of the PPPoE session header plus the PPP protocol
+ * field (8 bytes in total). The room is inserted between the
+ * MAC header and the network header, *skb->protocol* is set
+ * to **ETH_P_PPP_SES** and *skb->mac_len* is updated
+ * accordingly. The PPPoE header itself and the ethertype of
+ * the MAC header are filled in by the BPF program, e.g. via
+ * **bpf_skb_store_bytes**.
+ *
* * **BPF_F_ADJ_ROOM_DECAP_L3_IPV4**,
* **BPF_F_ADJ_ROOM_DECAP_L3_IPV6**:
* Indicate the new IP header version after decapsulating the
@@ -6323,6 +6334,7 @@ enum bpf_adj_room_flags {
BPF_F_ADJ_ROOM_DECAP_L4_UDP = (1ULL << 10),
BPF_F_ADJ_ROOM_DECAP_IPXIP4 = (1ULL << 11),
BPF_F_ADJ_ROOM_DECAP_IPXIP6 = (1ULL << 12),
+ BPF_F_ADJ_ROOM_ENCAP_PPPOE = (1ULL << 13),
};
enum {
--
2.47.3
next prev parent reply other threads:[~2026-10-03 19:34 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-03 19:33 [RFC bpf-next v2 0/3] bpf: Add PPPoE encap/decap support to bpf_skb_adjust_room ThisSeanZhang
2026-10-03 19:33 ` ThisSeanZhang [this message]
2026-10-03 19:33 ` [RFC bpf-next v2 2/3] bpf: Add PPPoE decap " ThisSeanZhang
2026-10-03 19:47 ` sashiko-bot
2026-10-03 19:33 ` [RFC bpf-next v2 3/3] selftests/bpf: Add a test for the PPPoE encap/decap adjust_room flags ThisSeanZhang
2026-10-03 20:11 ` bot+bpf-ci
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261003193347.1137527-2-thisseanzhang@gmail.com \
--to=thisseanzhang@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=dqfext@gmail.com \
--cc=eddyz87@gmail.com \
--cc=nbd@nbd.name \
--cc=netdev@vger.kernel.org \
--cc=nhudson@akamai.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.