BPF List
 help / color / mirror / Atom feed
* [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates
@ 2026-08-12  8:31 Nick Hudson
  2026-08-12  8:31 ` [PATCH bpf-next v7 1/6] bpf: name the enum for BPF_FUNC_skb_adjust_room flags Nick Hudson
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Nick Hudson @ 2026-08-12  8:31 UTC (permalink / raw)
  To: bpf, netdev, Willem de Bruijn, Martin KaFai Lau
  Cc: Nick Hudson, Max Tottenham, Anna Glasgall

This series extends bpf_skb_adjust_room() with decapsulation-specific
flags and tunnel GSO state updates for decap use cases.

Motivation
----------

When BPF decapsulates tunneled packets, skb GSO state needs to be
updated to match the removed tunnel layer. This includes clearing the
corresponding tunnel GSO type bits and resetting encapsulation state
once no tunnel GSO flags remain.

Series Overview
---------------

- Name the adjust_room flag enum for CO-RE lookups.
- Refactor adjust_room helper masks for maintainable validation logic.
- Add new DECAP flags to UAPI.
- Add guard rails for incompatible/invalid decap flag combinations.
- Implement decap GSO state clearing on shrink.
- Add selftests to validate decap GSO and encapsulation state.

Changes v6 -> v7:
- Resend only for formatting/threading fixes (no functional changes).
- Rebase onto current bpf-next/master (d114bb989367).

Changes v5 -> v6:
- Patch 5: extend decap-state handling for the new L4/IPXIP decap
  flags to non-GSO packets as well: when decapsulation is requested
  on a non-GSO skb, clear skb->encapsulation directly so behavior is
  consistent with the GSO path.
- Patch 6: broaden tc_tunnel coverage to exercise and validate both
  GSO and non-GSO decapsulation paths. This includes selecting
  IPXIP decap flags from the outer tunnel header family, adding
  explicit post-decap encapsulation checks for non-GSO packets,
  and removing forced TSO disable so GSO cases are exercised in
  the test harness.

Changes v4 -> v5:
- Patch 5: Remove explicit clearing of encap_hdr_csum and
  remcsum_offload on UDP decap, per review feedback.
- Patch 6: Remove SKB_GSO_TUNNEL_REMCSUM from SKB_GSO_UDP_TUNNEL_MASK
  in selftests, and minor test improvements.

Changes v3 -> v4:
- Patch 5: drop SKB_GSO_TUNNEL_REMCSUM handling from this series.
- Patch 5: clear encap_hdr_csum and remcsum_offload directly on UDP
  decap.

Changes v2 -> v3:
- Add a new selftests patch to validate decap GSO state behavior.
- Reorder the series so helper-mask refactoring precedes UAPI DECAP
  flag additions.
- Refresh patch 2 and patch 3 split to keep refactoring
  behavior-neutral.
- Patch 5: add decap tunnel GSO-state checks in "bpf: clear decap
  tunnel GSO state in skb_adjust_room" (per Gemini/sashiko).

Changes v1 -> v2:
- Patch 3: decap flag acceptance intentionally remains L3-only while
  adding helper masks.
- Patch 4: decap with L4/IPXIP support enabled with guard rails.

Co-developed-by: Max Tottenham <mtottenh@akamai.com>
Signed-off-by: Max Tottenham <mtottenh@akamai.com>
Co-developed-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Nick Hudson <nhudson@akamai.com>

Nick Hudson (6):
  bpf: name the enum for BPF_FUNC_skb_adjust_room flags
  bpf: refactor masks for ADJ_ROOM flags and encap validation
  bpf: add BPF_F_ADJ_ROOM_DECAP_* flags for tunnel decapsulation
  bpf: allow new DECAP flags and add guard rails
  bpf: clear decap state on skb_adjust_room shrink path
  selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state

 include/uapi/linux/bpf.h                      |  36 +++++-
 net/core/filter.c                             | 119 +++++++++++++++---
 tools/include/uapi/linux/bpf.h                |  36 +++++-
 .../selftests/bpf/prog_tests/test_tc_tunnel.c |   1 -
 .../selftests/bpf/progs/test_tc_tunnel.c      |  91 ++++++++++++--
 5 files changed, 252 insertions(+), 31 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH bpf-next v7 1/6] bpf: name the enum for BPF_FUNC_skb_adjust_room flags
  2026-08-12  8:31 [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates Nick Hudson
@ 2026-08-12  8:31 ` Nick Hudson
  2026-08-12  8:31 ` [PATCH bpf-next v7 2/6] bpf: refactor masks for ADJ_ROOM flags and encap validation Nick Hudson
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Nick Hudson @ 2026-08-12  8:31 UTC (permalink / raw)
  To: bpf, netdev, Willem de Bruijn, Martin KaFai Lau
  Cc: Nick Hudson, Max Tottenham, Anna Glasgall, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, linux-kernel

The existing anonymous enum for BPF_FUNC_skb_adjust_room flags is
named to enum bpf_adj_room_flags to enable CO-RE (Compile Once -
Run Everywhere) lookups in BPF programs.

Co-developed-by: Max Tottenham <mtottenh@akamai.com>
Signed-off-by: Max Tottenham <mtottenh@akamai.com>
Co-developed-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Nick Hudson <nhudson@akamai.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
 include/uapi/linux/bpf.h       | 2 +-
 tools/include/uapi/linux/bpf.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index ffd96e8b920b..f6c9dc856858 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -6283,7 +6283,7 @@ enum {
 };
 
 /* BPF_FUNC_skb_adjust_room flags. */
-enum {
+enum bpf_adj_room_flags {
 	BPF_F_ADJ_ROOM_FIXED_GSO	= (1ULL << 0),
 	BPF_F_ADJ_ROOM_ENCAP_L3_IPV4	= (1ULL << 1),
 	BPF_F_ADJ_ROOM_ENCAP_L3_IPV6	= (1ULL << 2),
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index ffd96e8b920b..f6c9dc856858 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -6283,7 +6283,7 @@ enum {
 };
 
 /* BPF_FUNC_skb_adjust_room flags. */
-enum {
+enum bpf_adj_room_flags {
 	BPF_F_ADJ_ROOM_FIXED_GSO	= (1ULL << 0),
 	BPF_F_ADJ_ROOM_ENCAP_L3_IPV4	= (1ULL << 1),
 	BPF_F_ADJ_ROOM_ENCAP_L3_IPV6	= (1ULL << 2),
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH bpf-next v7 2/6] bpf: refactor masks for ADJ_ROOM flags and encap validation
  2026-08-12  8:31 [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates Nick Hudson
  2026-08-12  8:31 ` [PATCH bpf-next v7 1/6] bpf: name the enum for BPF_FUNC_skb_adjust_room flags Nick Hudson
@ 2026-08-12  8:31 ` Nick Hudson
  2026-08-12 10:33   ` bot+bpf-ci
  2026-08-12  8:31 ` [PATCH bpf-next v7 3/6] bpf: add BPF_F_ADJ_ROOM_DECAP_* flags for tunnel decapsulation Nick Hudson
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 17+ messages in thread
From: Nick Hudson @ 2026-08-12  8:31 UTC (permalink / raw)
  To: bpf, netdev, Willem de Bruijn, Martin KaFai Lau
  Cc: Nick Hudson, Max Tottenham, Anna Glasgall, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-kernel

Refactor the helper masks for bpf_skb_adjust_room() flags to simplify
validation logic and introduce:

- BPF_F_ADJ_ROOM_ENCAP_MASK
- BPF_F_ADJ_ROOM_DECAP_MASK

Refactor existing validation checks in bpf_skb_net_shrink()
and bpf_skb_adjust_room() to use the new masks (no behavior change).

This is in preparation for supporting the new decap flags.

Co-developed-by: Max Tottenham <mtottenh@akamai.com>
Signed-off-by: Max Tottenham <mtottenh@akamai.com>
Co-developed-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Nick Hudson <nhudson@akamai.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
 net/core/filter.c | 38 +++++++++++++++++++++-----------------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index 3423734124a5..89e516049c85 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3572,14 +3572,19 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb)
 #define BPF_F_ADJ_ROOM_DECAP_L3_MASK	(BPF_F_ADJ_ROOM_DECAP_L3_IPV4 | \
 					 BPF_F_ADJ_ROOM_DECAP_L3_IPV6)
 
-#define BPF_F_ADJ_ROOM_MASK		(BPF_F_ADJ_ROOM_FIXED_GSO | \
-					 BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \
+#define BPF_F_ADJ_ROOM_ENCAP_MASK	(BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \
 					 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_L2( \
-					  BPF_ADJ_ROOM_ENCAP_L2_MASK) | \
-					 BPF_F_ADJ_ROOM_DECAP_L3_MASK)
+					  BPF_ADJ_ROOM_ENCAP_L2_MASK))
+
+#define BPF_F_ADJ_ROOM_DECAP_MASK	(BPF_F_ADJ_ROOM_DECAP_L3_MASK)
+
+#define BPF_F_ADJ_ROOM_MASK		(BPF_F_ADJ_ROOM_FIXED_GSO | \
+					 BPF_F_ADJ_ROOM_ENCAP_MASK | \
+					 BPF_F_ADJ_ROOM_DECAP_MASK | \
+					 BPF_F_ADJ_ROOM_NO_CSUM_RESET)
 
 static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff,
 			    u64 flags)
@@ -3702,8 +3707,8 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
 	bool decap = flags & BPF_F_ADJ_ROOM_DECAP_L3_MASK;
 	int ret;
 
-	if (unlikely(flags & ~(BPF_F_ADJ_ROOM_FIXED_GSO |
-			       BPF_F_ADJ_ROOM_DECAP_L3_MASK |
+	if (unlikely(flags & ~(BPF_F_ADJ_ROOM_DECAP_MASK |
+			       BPF_F_ADJ_ROOM_FIXED_GSO |
 			       BPF_F_ADJ_ROOM_NO_CSUM_RESET)))
 		return -EINVAL;
 
@@ -3802,8 +3807,7 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
 	u32 off;
 	int ret;
 
-	if (unlikely(flags & ~(BPF_F_ADJ_ROOM_MASK |
-			       BPF_F_ADJ_ROOM_NO_CSUM_RESET)))
+	if (unlikely(flags & ~BPF_F_ADJ_ROOM_MASK))
 		return -EINVAL;
 	if (unlikely(len_diff_abs > 0xfffU))
 		return -EFAULT;
@@ -3822,20 +3826,20 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
 		return -ENOTSUPP;
 	}
 
-	if (flags & BPF_F_ADJ_ROOM_DECAP_L3_MASK) {
+	if (flags & BPF_F_ADJ_ROOM_DECAP_MASK) {
 		if (!shrink)
 			return -EINVAL;
 
-		switch (flags & BPF_F_ADJ_ROOM_DECAP_L3_MASK) {
-		case BPF_F_ADJ_ROOM_DECAP_L3_IPV4:
+		/* Reject mutually exclusive decap flag pairs. */
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_L3_MASK) ==
+		    BPF_F_ADJ_ROOM_DECAP_L3_MASK)
+			return -EINVAL;
+
+		if (flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4)
 			len_min = sizeof(struct iphdr);
-			break;
-		case BPF_F_ADJ_ROOM_DECAP_L3_IPV6:
+
+		if (flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV6)
 			len_min = sizeof(struct ipv6hdr);
-			break;
-		default:
-			return -EINVAL;
-		}
 	}
 
 	len_cur = skb->len - skb_network_offset(skb);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH bpf-next v7 3/6] bpf: add BPF_F_ADJ_ROOM_DECAP_* flags for tunnel decapsulation
  2026-08-12  8:31 [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates Nick Hudson
  2026-08-12  8:31 ` [PATCH bpf-next v7 1/6] bpf: name the enum for BPF_FUNC_skb_adjust_room flags Nick Hudson
  2026-08-12  8:31 ` [PATCH bpf-next v7 2/6] bpf: refactor masks for ADJ_ROOM flags and encap validation Nick Hudson
@ 2026-08-12  8:31 ` Nick Hudson
  2026-08-12  8:31 ` [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails Nick Hudson
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Nick Hudson @ 2026-08-12  8:31 UTC (permalink / raw)
  To: bpf, netdev, Willem de Bruijn, Martin KaFai Lau
  Cc: Nick Hudson, Max Tottenham, Anna Glasgall, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, linux-kernel

Add new bpf_skb_adjust_room() decapsulation flags:

- BPF_F_ADJ_ROOM_DECAP_L4_GRE
- BPF_F_ADJ_ROOM_DECAP_L4_UDP
- BPF_F_ADJ_ROOM_DECAP_IPXIP4
- BPF_F_ADJ_ROOM_DECAP_IPXIP6

These flags let BPF programs describe which tunnel layer is being
removed, so later changes can update tunnel-related GSO state
accordingly during decapsulation.

This patch only introduces the UAPI flag definitions and helper
documentation.

Co-developed-by: Max Tottenham <mtottenh@akamai.com>
Signed-off-by: Max Tottenham <mtottenh@akamai.com>
Co-developed-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Nick Hudson <nhudson@akamai.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
 include/uapi/linux/bpf.h       | 34 ++++++++++++++++++++++++++++++++--
 tools/include/uapi/linux/bpf.h | 34 ++++++++++++++++++++++++++++++++--
 2 files changed, 64 insertions(+), 4 deletions(-)

diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index f6c9dc856858..732b35cc08d1 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3038,8 +3038,34 @@ union bpf_attr {
  *
  *		* **BPF_F_ADJ_ROOM_DECAP_L3_IPV4**,
  *		  **BPF_F_ADJ_ROOM_DECAP_L3_IPV6**:
- *		  Indicate the new IP header version after decapsulating the outer
- *		  IP header. Used when the inner and outer IP versions are different.
+ *		  Indicate the new IP header version after decapsulating the
+ *		  outer IP header. Used when the inner and outer IP versions
+ *		  are different. These flags only trigger a protocol change
+ *		  without clearing any tunnel-specific GSO flags.
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_L4_GRE**:
+ *		  Clear GRE tunnel GSO flags (SKB_GSO_GRE and SKB_GSO_GRE_CSUM)
+ *		  when decapsulating a GRE tunnel.
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_L4_UDP**:
+ *		  Clear UDP tunnel GSO flags (SKB_GSO_UDP_TUNNEL and
+ *		  SKB_GSO_UDP_TUNNEL_CSUM) when decapsulating a UDP tunnel.
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_IPXIP4**:
+ *		  Clear IPIP/SIT tunnel GSO flag (SKB_GSO_IPXIP4) when decapsulating
+ *		  a tunnel with an outer IPv4 header (IPv4-in-IPv4 or IPv6-in-IPv4).
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_IPXIP6**:
+ *		  Clear IPv6 encapsulation tunnel GSO flag (SKB_GSO_IPXIP6) when
+ *		  decapsulating a tunnel with an outer IPv6 header (IPv6-in-IPv6
+ *		  or IPv4-in-IPv6).
+ *
+ *		When using the decapsulation flags above, the skb->encapsulation
+ *		flag is automatically cleared if all tunnel-specific GSO flags
+ *		(SKB_GSO_UDP_TUNNEL, SKB_GSO_UDP_TUNNEL_CSUM, SKB_GSO_GRE,
+ *		SKB_GSO_GRE_CSUM, SKB_GSO_IPXIP4, SKB_GSO_IPXIP6) have been
+ *		removed from the packet. This handles cases where all tunnel
+ *		layers have been decapsulated.
  *
  * 		A call to this helper is susceptible to change the underlying
  * 		packet buffer. Therefore, at load time, all checks on pointers
@@ -6293,6 +6319,10 @@ enum bpf_adj_room_flags {
 	BPF_F_ADJ_ROOM_ENCAP_L2_ETH	= (1ULL << 6),
 	BPF_F_ADJ_ROOM_DECAP_L3_IPV4	= (1ULL << 7),
 	BPF_F_ADJ_ROOM_DECAP_L3_IPV6	= (1ULL << 8),
+	BPF_F_ADJ_ROOM_DECAP_L4_GRE	= (1ULL << 9),
+	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),
 };
 
 enum {
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index f6c9dc856858..732b35cc08d1 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3038,8 +3038,34 @@ union bpf_attr {
  *
  *		* **BPF_F_ADJ_ROOM_DECAP_L3_IPV4**,
  *		  **BPF_F_ADJ_ROOM_DECAP_L3_IPV6**:
- *		  Indicate the new IP header version after decapsulating the outer
- *		  IP header. Used when the inner and outer IP versions are different.
+ *		  Indicate the new IP header version after decapsulating the
+ *		  outer IP header. Used when the inner and outer IP versions
+ *		  are different. These flags only trigger a protocol change
+ *		  without clearing any tunnel-specific GSO flags.
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_L4_GRE**:
+ *		  Clear GRE tunnel GSO flags (SKB_GSO_GRE and SKB_GSO_GRE_CSUM)
+ *		  when decapsulating a GRE tunnel.
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_L4_UDP**:
+ *		  Clear UDP tunnel GSO flags (SKB_GSO_UDP_TUNNEL and
+ *		  SKB_GSO_UDP_TUNNEL_CSUM) when decapsulating a UDP tunnel.
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_IPXIP4**:
+ *		  Clear IPIP/SIT tunnel GSO flag (SKB_GSO_IPXIP4) when decapsulating
+ *		  a tunnel with an outer IPv4 header (IPv4-in-IPv4 or IPv6-in-IPv4).
+ *
+ *		* **BPF_F_ADJ_ROOM_DECAP_IPXIP6**:
+ *		  Clear IPv6 encapsulation tunnel GSO flag (SKB_GSO_IPXIP6) when
+ *		  decapsulating a tunnel with an outer IPv6 header (IPv6-in-IPv6
+ *		  or IPv4-in-IPv6).
+ *
+ *		When using the decapsulation flags above, the skb->encapsulation
+ *		flag is automatically cleared if all tunnel-specific GSO flags
+ *		(SKB_GSO_UDP_TUNNEL, SKB_GSO_UDP_TUNNEL_CSUM, SKB_GSO_GRE,
+ *		SKB_GSO_GRE_CSUM, SKB_GSO_IPXIP4, SKB_GSO_IPXIP6) have been
+ *		removed from the packet. This handles cases where all tunnel
+ *		layers have been decapsulated.
  *
  * 		A call to this helper is susceptible to change the underlying
  * 		packet buffer. Therefore, at load time, all checks on pointers
@@ -6293,6 +6319,10 @@ enum bpf_adj_room_flags {
 	BPF_F_ADJ_ROOM_ENCAP_L2_ETH	= (1ULL << 6),
 	BPF_F_ADJ_ROOM_DECAP_L3_IPV4	= (1ULL << 7),
 	BPF_F_ADJ_ROOM_DECAP_L3_IPV6	= (1ULL << 8),
+	BPF_F_ADJ_ROOM_DECAP_L4_GRE	= (1ULL << 9),
+	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),
 };
 
 enum {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails
  2026-08-12  8:31 [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates Nick Hudson
                   ` (2 preceding siblings ...)
  2026-08-12  8:31 ` [PATCH bpf-next v7 3/6] bpf: add BPF_F_ADJ_ROOM_DECAP_* flags for tunnel decapsulation Nick Hudson
@ 2026-08-12  8:31 ` Nick Hudson
  2026-08-12 10:22   ` sashiko-bot
  2026-08-12 10:33   ` bot+bpf-ci
  2026-08-12  8:31 ` [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path Nick Hudson
  2026-08-12  8:31 ` [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state Nick Hudson
  5 siblings, 2 replies; 17+ messages in thread
From: Nick Hudson @ 2026-08-12  8:31 UTC (permalink / raw)
  To: bpf, netdev, Willem de Bruijn, Martin KaFai Lau
  Cc: Nick Hudson, Max Tottenham, Anna Glasgall, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-kernel

Add checks to require shrink-only decap, reject conflicting decap flag
combinations, and verify removed length is sufficient for claimed header
decapsulation.

Co-developed-by: Max Tottenham <mtottenh@akamai.com>
Signed-off-by: Max Tottenham <mtottenh@akamai.com>
Co-developed-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Nick Hudson <nhudson@akamai.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
 net/core/filter.c | 44 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/net/core/filter.c b/net/core/filter.c
index 89e516049c85..981b75941e7f 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -56,6 +56,7 @@
 #include <net/sock_reuseport.h>
 #include <net/busy_poll.h>
 #include <net/tcp.h>
+#include <net/gre.h>
 #include <net/xfrm.h>
 #include <net/udp.h>
 #include <linux/bpf_trace.h>
@@ -3572,6 +3573,12 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb)
 #define BPF_F_ADJ_ROOM_DECAP_L3_MASK	(BPF_F_ADJ_ROOM_DECAP_L3_IPV4 | \
 					 BPF_F_ADJ_ROOM_DECAP_L3_IPV6)
 
+#define BPF_F_ADJ_ROOM_DECAP_L4_MASK	(BPF_F_ADJ_ROOM_DECAP_L4_UDP | \
+					 BPF_F_ADJ_ROOM_DECAP_L4_GRE)
+
+#define BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK	(BPF_F_ADJ_ROOM_DECAP_IPXIP4 | \
+					 BPF_F_ADJ_ROOM_DECAP_IPXIP6)
+
 #define BPF_F_ADJ_ROOM_ENCAP_MASK	(BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \
 					 BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \
 					 BPF_F_ADJ_ROOM_ENCAP_L4_UDP | \
@@ -3579,7 +3586,9 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb)
 					 BPF_F_ADJ_ROOM_ENCAP_L2( \
 					  BPF_ADJ_ROOM_ENCAP_L2_MASK))
 
-#define BPF_F_ADJ_ROOM_DECAP_MASK	(BPF_F_ADJ_ROOM_DECAP_L3_MASK)
+#define BPF_F_ADJ_ROOM_DECAP_MASK	(BPF_F_ADJ_ROOM_DECAP_L3_MASK | \
+					 BPF_F_ADJ_ROOM_DECAP_L4_MASK | \
+					 BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)
 
 #define BPF_F_ADJ_ROOM_MASK		(BPF_F_ADJ_ROOM_FIXED_GSO | \
 					 BPF_F_ADJ_ROOM_ENCAP_MASK | \
@@ -3827,6 +3836,8 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
 	}
 
 	if (flags & BPF_F_ADJ_ROOM_DECAP_MASK) {
+		u32 len_decap_min = 0;
+
 		if (!shrink)
 			return -EINVAL;
 
@@ -3835,6 +3846,37 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
 		    BPF_F_ADJ_ROOM_DECAP_L3_MASK)
 			return -EINVAL;
 
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) ==
+		    BPF_F_ADJ_ROOM_DECAP_L4_MASK)
+			return -EINVAL;
+
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) ==
+		    BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)
+			return -EINVAL;
+
+		/* Reject mutually exclusive decap tunnel type flags. */
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) &&
+		    (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK))
+			return -EINVAL;
+
+		if (flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK)
+			len_decap_min += bpf_skb_net_base_len(skb);
+
+		if (flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP)
+			len_decap_min += sizeof(struct udphdr);
+
+		if (flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE)
+			len_decap_min += sizeof(struct gre_base_hdr);
+
+		if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4)
+			len_decap_min += sizeof(struct iphdr);
+
+		if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6)
+			len_decap_min += sizeof(struct ipv6hdr);
+
+		if (len_diff_abs < len_decap_min)
+			return -EINVAL;
+
 		if (flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4)
 			len_min = sizeof(struct iphdr);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path
  2026-08-12  8:31 [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates Nick Hudson
                   ` (3 preceding siblings ...)
  2026-08-12  8:31 ` [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails Nick Hudson
@ 2026-08-12  8:31 ` Nick Hudson
  2026-08-12 10:26   ` sashiko-bot
  2026-08-12 10:33   ` bot+bpf-ci
  2026-08-12  8:31 ` [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state Nick Hudson
  5 siblings, 2 replies; 17+ messages in thread
From: Nick Hudson @ 2026-08-12  8:31 UTC (permalink / raw)
  To: bpf, netdev, Willem de Bruijn, Martin KaFai Lau
  Cc: Nick Hudson, Max Tottenham, Anna Glasgall, Daniel Borkmann,
	Alexei Starovoitov, Andrii Nakryiko, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, linux-kernel

On shrink in bpf_skb_adjust_room(), apply decapsulation state updates
according to BPF_F_ADJ_ROOM_DECAP_* flags.

For GSO skbs, clear only the tunnel gso_type bits that correspond to the
requested decap layer:
- DECAP_L4_UDP: SKB_GSO_UDP_TUNNEL{,_CSUM}
- DECAP_L4_GRE: SKB_GSO_GRE{,_CSUM}
- DECAP_IPXIP4: SKB_GSO_IPXIP4
- DECAP_IPXIP6: SKB_GSO_IPXIP6

Then clear skb->encapsulation only if no tunnel GSO bits remain, keeping
encapsulation set for cases such as ESP-in-UDP where tunnel state remains.

For non-GSO skbs, there are no tunnel GSO bits to consult, so clear
skb->encapsulation directly when DECAP_L4_* or DECAP_IPXIP_* flags are set.

This keeps decap state handling consistent between GSO and non-GSO packets.

Co-developed-by: Max Tottenham <mtottenh@akamai.com>
Signed-off-by: Max Tottenham <mtottenh@akamai.com>
Co-developed-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Anna Glasgall <aglasgal@akamai.com>
Signed-off-by: Nick Hudson <nhudson@akamai.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
---
 net/core/filter.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/net/core/filter.c b/net/core/filter.c
index 981b75941e7f..89effff3bc52 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3754,9 +3754,48 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
 		if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
 			skb_increase_gso_size(shinfo, len_diff);
 
+		/* Selective GSO flag clearing based on decap type.
+		 * Only clear the flags for the tunnel layer being removed.
+		 */
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) &&
+		    (shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
+					 SKB_GSO_UDP_TUNNEL_CSUM)))
+			shinfo->gso_type &= ~(SKB_GSO_UDP_TUNNEL |
+					      SKB_GSO_UDP_TUNNEL_CSUM);
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE) &&
+		    (shinfo->gso_type & (SKB_GSO_GRE | SKB_GSO_GRE_CSUM)))
+			shinfo->gso_type &= ~(SKB_GSO_GRE |
+					      SKB_GSO_GRE_CSUM);
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4) &&
+		    (shinfo->gso_type & SKB_GSO_IPXIP4))
+			shinfo->gso_type &= ~SKB_GSO_IPXIP4;
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6) &&
+		    (shinfo->gso_type & SKB_GSO_IPXIP6))
+			shinfo->gso_type &= ~SKB_GSO_IPXIP6;
+
+		/* Clear encapsulation flag only when no tunnel GSO flags remain */
+		if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
+			     BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) {
+			if (!(shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
+						  SKB_GSO_UDP_TUNNEL_CSUM |
+						  SKB_GSO_GRE |
+						  SKB_GSO_GRE_CSUM |
+						  SKB_GSO_IPXIP4 |
+						  SKB_GSO_IPXIP6 |
+						  SKB_GSO_ESP)))
+				if (skb->encapsulation)
+					skb->encapsulation = 0;
+		}
+
 		/* Header must be checked, and gso_segs recomputed. */
 		shinfo->gso_type |= SKB_GSO_DODGY;
 		shinfo->gso_segs = 0;
+	} else {
+		/* For non-GSO packets, clear encapsulation if decap flags are set */
+		if ((flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
+			      BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) &&
+		    skb->encapsulation)
+			skb->encapsulation = 0;
 	}
 
 	return 0;
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state
  2026-08-12  8:31 [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates Nick Hudson
                   ` (4 preceding siblings ...)
  2026-08-12  8:31 ` [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path Nick Hudson
@ 2026-08-12  8:31 ` Nick Hudson
  2026-08-12 10:20   ` sashiko-bot
  2026-08-12 10:48   ` bot+bpf-ci
  5 siblings, 2 replies; 17+ messages in thread
From: Nick Hudson @ 2026-08-12  8:31 UTC (permalink / raw)
  To: bpf, netdev, Willem de Bruijn, Martin KaFai Lau
  Cc: Nick Hudson, Andrii Nakryiko, Eduard Zingerman,
	Alexei Starovoitov, Daniel Borkmann, Kumar Kartikeya Dwivedi,
	Shuah Khan, linux-kselftest, linux-kernel

tc_tunnel only partially validated decap state and missed some tunnel
cases. In particular, IPXIP decap checks were not exercised for
IPIP/SIT paths, and non-GSO decap encapsulation state was not
verified.

Tighten the test by:

- setting DECAP_IPXIP4/6 flags for IPIP/SIT/IP6 decap paths based on
  the outer tunnel header family;
- requiring needed DECAP enum values via CO-RE enum existence checks
  so missing kernel support fails fast;
- validating post-decap tunnel state for both GSO and non-GSO packets:
  expected gso_type bits must be cleared and skb->encapsulation must
  match remaining tunnel flags;
- removing forced TSO disable in the test harness so GSO validation is
  exercised.

This improves coverage for decap tunnel-state regressions and ensures
sit_none/ipip-style paths are checked correctly.

Signed-off-by: Nick Hudson <nhudson@akamai.com>
---
 .../selftests/bpf/prog_tests/test_tc_tunnel.c |  1 -
 .../selftests/bpf/progs/test_tc_tunnel.c      | 91 +++++++++++++++++--
 2 files changed, 84 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c b/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c
index 1aa7c9463980..67ba27d69347 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c
@@ -438,7 +438,6 @@ static int setup(void)
 	SYS(fail_close_ns_client, "ip link add %s type veth peer name %s",
 	    "veth1 mtu 1500 netns " CLIENT_NS " address " MAC_ADDR_VETH1,
 	    "veth2 mtu 1500 netns " SERVER_NS " address " MAC_ADDR_VETH2);
-	SYS(fail_close_ns_client, "ethtool -K veth1 tso off");
 	SYS(fail_close_ns_client, "ip link set veth1 up");
 	nstoken_server = open_netns(SERVER_NS);
 	if (!ASSERT_OK_PTR(nstoken_server, "open server ns"))
diff --git a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c
index 7376df405a6b..853bca962910 100644
--- a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c
+++ b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c
@@ -6,6 +6,7 @@
 
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_endian.h>
+#include <bpf/bpf_core_read.h>
 #include "bpf_tracing_net.h"
 #include "bpf_compiler.h"
 
@@ -37,6 +38,22 @@ struct vxlanhdr___local {
 
 #define	EXTPROTO_VXLAN	0x1
 
+#define SKB_GSO_UDP_TUNNEL_MASK	(SKB_GSO_UDP_TUNNEL |			\
+				 SKB_GSO_UDP_TUNNEL_CSUM)
+
+#define SKB_GSO_TUNNEL_MASK	(SKB_GSO_UDP_TUNNEL_MASK |		\
+				 SKB_GSO_GRE |				\
+				 SKB_GSO_GRE_CSUM |			\
+				 SKB_GSO_IPXIP4 |			\
+				 SKB_GSO_IPXIP6 |			\
+				 SKB_GSO_ESP)
+
+#define BPF_F_ADJ_ROOM_DECAP_L4_MASK	(BPF_F_ADJ_ROOM_DECAP_L4_UDP |	\
+					 BPF_F_ADJ_ROOM_DECAP_L4_GRE)
+
+#define BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK	(BPF_F_ADJ_ROOM_DECAP_IPXIP4 |	\
+					 BPF_F_ADJ_ROOM_DECAP_IPXIP6)
+
 #define	VXLAN_FLAGS     bpf_htonl(1<<27)
 #define	VNI_ID		1
 #define	VXLAN_VNI	bpf_htonl(VNI_ID << 8)
@@ -589,9 +606,12 @@ int __encap_ip6vxlan_eth(struct __sk_buff *skb)
 		return TC_ACT_OK;
 }
 
-static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
+static int decap_internal(struct __sk_buff *skb, int off, int len, char proto,
+			  __u64 ipxip_flag)
 {
 	__u64 flags = BPF_F_ADJ_ROOM_FIXED_GSO;
+	struct sk_buff *kskb;
+	struct skb_shared_info *shinfo;
 	struct ipv6_opt_hdr ip6_opt_hdr;
 	struct gre_hdr greh;
 	struct udphdr udph;
@@ -599,10 +619,12 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
 
 	switch (proto) {
 	case IPPROTO_IPIP:
-		flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV4;
+		flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV4 |
+			 ipxip_flag;
 		break;
 	case IPPROTO_IPV6:
-		flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV6;
+		flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV6 |
+			 ipxip_flag;
 		break;
 	case NEXTHDR_DEST:
 		if (bpf_skb_load_bytes(skb, off + len, &ip6_opt_hdr,
@@ -610,10 +632,12 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
 			return TC_ACT_OK;
 		switch (ip6_opt_hdr.nexthdr) {
 		case IPPROTO_IPIP:
-			flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV4;
+			flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV4 |
+				 ipxip_flag;
 			break;
 		case IPPROTO_IPV6:
-			flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV6;
+			flags |= BPF_F_ADJ_ROOM_DECAP_L3_IPV6 |
+				 ipxip_flag;
 			break;
 		default:
 			return TC_ACT_OK;
@@ -621,6 +645,11 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
 		break;
 	case IPPROTO_GRE:
 		olen += sizeof(struct gre_hdr);
+		if (!bpf_core_enum_value_exists(enum bpf_adj_room_flags,
+						BPF_F_ADJ_ROOM_DECAP_L4_GRE))
+			return TC_ACT_SHOT;
+		flags |= BPF_F_ADJ_ROOM_DECAP_L4_GRE;
+
 		if (bpf_skb_load_bytes(skb, off + len, &greh, sizeof(greh)) < 0)
 			return TC_ACT_OK;
 		switch (bpf_ntohs(greh.protocol)) {
@@ -634,6 +663,10 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
 		break;
 	case IPPROTO_UDP:
 		olen += sizeof(struct udphdr);
+		if (!bpf_core_enum_value_exists(enum bpf_adj_room_flags,
+						BPF_F_ADJ_ROOM_DECAP_L4_UDP))
+			return TC_ACT_SHOT;
+		flags |= BPF_F_ADJ_ROOM_DECAP_L4_UDP;
 		if (bpf_skb_load_bytes(skb, off + len, &udph, sizeof(udph)) < 0)
 			return TC_ACT_OK;
 		switch (bpf_ntohs(udph.dest)) {
@@ -655,6 +688,40 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
 	if (bpf_skb_adjust_room(skb, -olen, BPF_ADJ_ROOM_MAC, flags))
 		return TC_ACT_SHOT;
 
+	kskb = bpf_cast_to_kern_ctx(skb);
+	shinfo = bpf_core_cast(kskb->head + kskb->end, struct skb_shared_info);
+	if (shinfo->gso_size) {
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) &&
+		    (shinfo->gso_type & SKB_GSO_UDP_TUNNEL_MASK))
+			return TC_ACT_SHOT;
+
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE) &&
+		    (shinfo->gso_type & (SKB_GSO_GRE | SKB_GSO_GRE_CSUM)))
+			return TC_ACT_SHOT;
+
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4) &&
+		    (shinfo->gso_type & SKB_GSO_IPXIP4))
+			return TC_ACT_SHOT;
+
+		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6) &&
+		    (shinfo->gso_type & SKB_GSO_IPXIP6))
+			return TC_ACT_SHOT;
+
+		if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
+			     BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) {
+			if ((shinfo->gso_type & SKB_GSO_TUNNEL_MASK) &&
+			    !kskb->encapsulation)
+				return TC_ACT_SHOT;
+			if (!(shinfo->gso_type & SKB_GSO_TUNNEL_MASK) &&
+			    kskb->encapsulation)
+				return TC_ACT_SHOT;
+		}
+	} else if ((flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
+			     BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) &&
+		   kskb->encapsulation) {
+		return TC_ACT_SHOT;
+	}
+
 	return TC_ACT_OK;
 }
 
@@ -662,6 +729,10 @@ static int decap_ipv4(struct __sk_buff *skb)
 {
 	struct iphdr iph_outer;
 
+	if (!bpf_core_enum_value_exists(enum bpf_adj_room_flags,
+					BPF_F_ADJ_ROOM_DECAP_IPXIP4))
+		return TC_ACT_SHOT;
+
 	if (bpf_skb_load_bytes(skb, ETH_HLEN, &iph_outer,
 			       sizeof(iph_outer)) < 0)
 		return TC_ACT_OK;
@@ -670,19 +741,25 @@ static int decap_ipv4(struct __sk_buff *skb)
 		return TC_ACT_OK;
 
 	return decap_internal(skb, ETH_HLEN, sizeof(iph_outer),
-			      iph_outer.protocol);
+			      iph_outer.protocol,
+			      BPF_F_ADJ_ROOM_DECAP_IPXIP4);
 }
 
 static int decap_ipv6(struct __sk_buff *skb)
 {
 	struct ipv6hdr iph_outer;
 
+	if (!bpf_core_enum_value_exists(enum bpf_adj_room_flags,
+					BPF_F_ADJ_ROOM_DECAP_IPXIP6))
+		return TC_ACT_SHOT;
+
 	if (bpf_skb_load_bytes(skb, ETH_HLEN, &iph_outer,
 			       sizeof(iph_outer)) < 0)
 		return TC_ACT_OK;
 
 	return decap_internal(skb, ETH_HLEN, sizeof(iph_outer),
-			      iph_outer.nexthdr);
+			      iph_outer.nexthdr,
+			      BPF_F_ADJ_ROOM_DECAP_IPXIP6);
 }
 
 SEC("tc")
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state
  2026-08-12  8:31 ` [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state Nick Hudson
@ 2026-08-12 10:20   ` sashiko-bot
  2026-08-12 12:23     ` Hudson, Nick
  2026-08-12 10:48   ` bot+bpf-ci
  1 sibling, 1 reply; 17+ messages in thread
From: sashiko-bot @ 2026-08-12 10:20 UTC (permalink / raw)
  To: Nick Hudson; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Invalid pointer arithmetic `kskb->head + kskb->end` breaks 32-bit compilation and cross-architecture CO-RE portability.
--

--- Patch [6]: [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state ---
commit 51cad3ba4cd10bce6b9c9134b5e4188fc76f034c
Author: Nick Hudson <nhudson@akamai.com>
selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state

This commit tightens tc_tunnel tests by verifying post-decap tunnel
state for both GSO and non-GSO packets. It enforces DECAP flags and
ensures proper clearing of gso_type bits and encapsulation state.

> diff --git a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c
> --- a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c
> +++ b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c

[ ... ]

> @@ -655,6 +688,40 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
>  	if (bpf_skb_adjust_room(skb, -olen, BPF_ADJ_ROOM_MAC, flags))
>  		return TC_ACT_SHOT;
>  
> +	kskb = bpf_cast_to_kern_ctx(skb);
> +	shinfo = bpf_core_cast(kskb->head + kskb->end, struct skb_shared_info);
                                       ^^^^^^^^^^^^^^^^^^^^^

[Severity: Medium]
Does this pointer arithmetic break compilation on 32-bit architectures?

Since kskb->end is a pointer on 32-bit systems (rather than an integer offset
like it is on 64-bit), adding kskb->head and kskb->end together attempts to add
two pointers, which is invalid in C.

Additionally, CO-RE does not translate this pointer-integer addition to a single
pointer dereference when cross-compiled on 64-bit and run on 32-bit kernels,
which can lead to a garbage pointer dereference.

Is there a safer way to calculate the skb_shared_info offset in decap_internal
that is portable across both 32-bit and 64-bit architectures?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260812083115.73100-1-nhudson@akamai.com?part=6

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails
  2026-08-12  8:31 ` [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails Nick Hudson
@ 2026-08-12 10:22   ` sashiko-bot
  2026-08-12 12:13     ` Hudson, Nick
  2026-08-12 10:33   ` bot+bpf-ci
  1 sibling, 1 reply; 17+ messages in thread
From: sashiko-bot @ 2026-08-12 10:22 UTC (permalink / raw)
  To: Nick Hudson; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The patch exposes new decapsulation flags without implementing the required kernel side effects to clear tunnel-specific GSO flags and `skb->encapsulation` status, leading to stale tunnel metadata on decapsulated packets.
- [High] The `decap` flag check in `bpf_skb_net_shrink()` was not updated to include the new L4 and IPXIP decapsulation masks, causing critical packet state updates (like dropping the outer `dst_entry`) to be skipped.
--

--- Patch [4]: [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails ---
commit cdd433d824d20f40752fca9cc2db82451d364a2c
Author: Nick Hudson <nhudson@akamai.com>

bpf: allow new DECAP flags and add guard rails

Add checks to require shrink-only decap, reject conflicting decap flag
combinations, and verify removed length is sufficient for claimed header
decapsulation.

> diff --git a/net/core/filter.c b/net/core/filter.c
> index 89e516049c852..981b75941e7f7 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
[ ... ]
> @@ -3579,7 +3586,9 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb)
>  					 BPF_F_ADJ_ROOM_ENCAP_L2( \
>  					  BPF_ADJ_ROOM_ENCAP_L2_MASK))
>  
> -#define BPF_F_ADJ_ROOM_DECAP_MASK	(BPF_F_ADJ_ROOM_DECAP_L3_MASK)
> +#define BPF_F_ADJ_ROOM_DECAP_MASK	(BPF_F_ADJ_ROOM_DECAP_L3_MASK | \
> +					 BPF_F_ADJ_ROOM_DECAP_L4_MASK | \
> +					 BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)

[Severity: High]
Does this mask update also need to be reflected in the decap check in
bpf_skb_net_shrink()?

Currently, bpf_skb_net_shrink() evaluates decap based only on the L3 mask:

net/core/filter.c:bpf_skb_net_shrink() {
	bool decap = flags & BPF_F_ADJ_ROOM_DECAP_L3_MASK;
	...
	if (decap) {
		...
		if (skb_valid_dst(skb))
			skb_dst_drop(skb);
	}
	...
}

If a BPF program uses BPF_F_ADJ_ROOM_DECAP_L4_UDP to decapsulate an L4 or
IPXIP tunnel but does not provide BPF_F_ADJ_ROOM_DECAP_L3_MASK, decap
evaluates to false.

As a result, skb_dst_drop(skb) is skipped, causing the inner packet to
incorrectly inherit the outer tunnel's routing cache. This can route the
inner packet to the tunnel endpoint instead of its true destination.

[Severity: High]
Does this code miss clearing tunnel-specific GSO flags and skb->encapsulation
status?

The UAPI documentation promises that using BPF_F_ADJ_ROOM_DECAP_L4_UDP will
clear UDP tunnel GSO flags (SKB_GSO_UDP_TUNNEL and SKB_GSO_UDP_TUNNEL_CSUM)
when decapsulating a UDP tunnel.

However, bpf_skb_net_shrink() omits the logic to do this:

net/core/filter.c:bpf_skb_net_shrink() {
	...
	ret = bpf_skb_net_hdr_pop(skb, off, len_diff);
	if (unlikely(ret < 0))
		return ret;

	if (decap) {
		/* Match skb->protocol to new outer l3 protocol */
	...
}

Leaving stale tunnel metadata on the packet can cause downstream drivers to
parse incorrect header offsets, resulting in skb_over_panic or
skb_under_panic.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260812083115.73100-1-nhudson@akamai.com?part=4

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path
  2026-08-12  8:31 ` [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path Nick Hudson
@ 2026-08-12 10:26   ` sashiko-bot
  2026-08-12 12:30     ` Hudson, Nick
  2026-08-12 10:33   ` bot+bpf-ci
  1 sibling, 1 reply; 17+ messages in thread
From: sashiko-bot @ 2026-08-12 10:26 UTC (permalink / raw)
  To: Nick Hudson; +Cc: bpf

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] bpf_skb_net_shrink() leaves SKB_GSO_PARTIAL and SKB_GSO_TUNNEL_REMCSUM dangling in shinfo->gso_type after removing a tunnel.
--

--- Patch [5]: [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path ---
commit 672aa1a359079a58d5e4d80fc47569e00a437a80
Author: Nick Hudson <nhudson@akamai.com>
bpf: clear decap state on skb_adjust_room shrink path

This commit updates bpf_skb_adjust_room() on the shrink path to conditionally
clear decapsulation state updates based on BPF_F_ADJ_ROOM_DECAP_* flags. For
GSO skbs, it selectively clears tunnel gso_type bits and encapsulation, while
for non-GSO skbs it directly clears the encapsulation flag.

> diff --git a/net/core/filter.c b/net/core/filter.c
> index 981b75941e7f7..89effff3bc525 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c
> @@ -3754,9 +3754,48 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
>  		if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
>  			skb_increase_gso_size(shinfo, len_diff);
>  
> +		/* Selective GSO flag clearing based on decap type.
> +		 * Only clear the flags for the tunnel layer being removed.
> +		 */
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) &&
> +		    (shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
> +					 SKB_GSO_UDP_TUNNEL_CSUM)))
> +			shinfo->gso_type &= ~(SKB_GSO_UDP_TUNNEL |
> +					      SKB_GSO_UDP_TUNNEL_CSUM);

[Severity: High]
Does this leave SKB_GSO_PARTIAL and SKB_GSO_TUNNEL_REMCSUM dangling in
shinfo->gso_type after removing a tunnel?

If an SKB acquires SKB_GSO_PARTIAL or SKB_GSO_TUNNEL_REMCSUM (for example,
via software partial segmentation across a veth pair or GRO) and a BPF program
uses bpf_skb_adjust_room() to shrink the SKB, it seems the base tunnel flags
are cleared but the modifier flags remain.

Hardware drivers like ixgbe or fbnic use SKB_GSO_PARTIAL to identify packets
requiring partial GSO offload or special tunnel logic. Could leaving this flag
on a decapsulated, non-tunnel SKB cause drivers to misinterpret the packet
structure and corrupt the packet on transmit?

[ ... ]

> +		/* Clear encapsulation flag only when no tunnel GSO flags remain */
> +		if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
> +			     BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) {
> +			if (!(shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
> +						  SKB_GSO_UDP_TUNNEL_CSUM |
> +						  SKB_GSO_GRE |
> +						  SKB_GSO_GRE_CSUM |
> +						  SKB_GSO_IPXIP4 |
> +						  SKB_GSO_IPXIP6 |
> +						  SKB_GSO_ESP)))
> +				if (skb->encapsulation)
> +					skb->encapsulation = 0;
> +		}

[Severity: High]
If all base tunnel flags are cleared and encapsulation is set to 0, which
confirms the packet is no longer a tunnel, is it expected that SKB_GSO_PARTIAL
and SKB_GSO_TUNNEL_REMCSUM might still be set in gso_type?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260812083115.73100-1-nhudson@akamai.com?part=5

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails
  2026-08-12  8:31 ` [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails Nick Hudson
  2026-08-12 10:22   ` sashiko-bot
@ 2026-08-12 10:33   ` bot+bpf-ci
  1 sibling, 0 replies; 17+ messages in thread
From: bot+bpf-ci @ 2026-08-12 10:33 UTC (permalink / raw)
  To: nhudson, bpf, netdev, willemb, martin.lau
  Cc: nhudson, mtottenh, aglasgal, daniel, ast, andrii, eddyz87, memxor,
	davem, edumazet, kuba, pabeni, linux-kernel, ast, andrii, daniel,
	martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 4697 bytes --]

> commit e891bb72fdfdae2b71119ffb8be655bb3a4b26a7
> Author: Nick Hudson <nhudson@akamai.com>
> Date:   Wed Aug 12 09:31:13 2026 +0100
>
>     bpf: allow new DECAP flags and add guard rails
>
>     Add checks to require shrink-only decap, reject conflicting decap flag
>     combinations, and verify removed length is sufficient for claimed header
>     decapsulation.
>
>     Co-developed-by: Max Tottenham <mtottenh@akamai.com>
>     Signed-off-by: Max Tottenham <mtottenh@akamai.com>
>     Co-developed-by: Anna Glasgall <aglasgal@akamai.com>
>     Signed-off-by: Anna Glasgall <aglasgal@akamai.com>
>     Signed-off-by: Nick Hudson <nhudson@akamai.com>
>     Reviewed-by: Willem de Bruijn <willemb@google.com>

The changelog states this patch "Add checks to require shrink-only decap",
but that check already exists in the parent commit. From e891bb72^:

    if (flags & BPF_F_ADJ_ROOM_DECAP_MASK) {
            if (!shrink)
                    return -EINVAL;

The diff confirms both the shrink check and the L3 pair check are context
lines, not additions. What this patch actually does is extend the coverage
of those pre-existing checks by widening BPF_F_ADJ_ROOM_DECAP_MASK to
include the new L4 and IPXIP flags.

Could the changelog be reworded to clarify this extends existing checks to
the new flags, rather than implying it adds the shrink-only requirement?

> diff --git a/net/core/filter.c b/net/core/filter.c
> index 89e516049c852..981b75941e7f7 100644
> --- a/net/core/filter.c
> +++ b/net/core/filter.c

[ ... ]

> @@ -3827,6 +3836,8 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
>  	}
>
>  	if (flags & BPF_F_ADJ_ROOM_DECAP_MASK) {
> +		u32 len_decap_min = 0;
> +
>  		if (!shrink)
>  			return -EINVAL;
>
> @@ -3835,6 +3846,37 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff,
>  		    BPF_F_ADJ_ROOM_DECAP_L3_MASK)
>  			return -EINVAL;
>
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) ==
> +		    BPF_F_ADJ_ROOM_DECAP_L4_MASK)
> +			return -EINVAL;
> +
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) ==
> +		    BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)
> +			return -EINVAL;
> +
> +		/* Reject mutually exclusive decap tunnel type flags. */
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) &&
> +		    (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK))
> +			return -EINVAL;
> +
> +		if (flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK)
> +			len_decap_min += bpf_skb_net_base_len(skb);
> +
> +		if (flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP)
> +			len_decap_min += sizeof(struct udphdr);
> +
> +		if (flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE)
> +			len_decap_min += sizeof(struct gre_base_hdr);
> +
> +		if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4)
> +			len_decap_min += sizeof(struct iphdr);
> +
> +		if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6)
> +			len_decap_min += sizeof(struct ipv6hdr);
> +
> +		if (len_diff_abs < len_decap_min)
> +			return -EINVAL;
> +

Does this minimum-length check account for the mode parameter? The
calculation assumes mode == BPF_ADJ_ROOM_MAC, but nothing constrains mode
when DECAP flags are set.

Earlier in this function, off is computed:

    off = skb_mac_header_len(skb);
    switch (mode) {
    case BPF_ADJ_ROOM_NET:
            off += bpf_skb_net_base_len(skb);
            break;
    case BPF_ADJ_ROOM_MAC:
            break;

In BPF_ADJ_ROOM_NET mode, the removal window starts after the outer L3
header, so that header is not part of the len_diff_abs bytes being removed.

Yet when an L4 decap flag is present, the check adds the outer L3 length
unconditionally:

    if (flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK)
            len_decap_min += bpf_skb_net_base_len(skb);

Consider a tc program on an IPv4 outer packet calling:

    bpf_skb_adjust_room(skb, -8, BPF_ADJ_ROOM_NET,
                        BPF_F_ADJ_ROOM_DECAP_L4_UDP)

to strip an 8-byte FOU/UDP tunnel header. This would compute len_decap_min
= 20 + 8 = 28, so len_diff_abs (8) < len_decap_min (28) causes -EINVAL even
though the request removes exactly the claimed header.

The same mismatch applies to the IPXIP terms: in NET mode the outer IP
header is outside the removal window entirely, yet
BPF_F_ADJ_ROOM_DECAP_IPXIP4/6 requires 20/40 bytes to be removed.

Should this either reject mode != BPF_ADJ_ROOM_MAC when
BPF_F_ADJ_ROOM_DECAP_MASK is set, or make the bpf_skb_net_base_len() term
conditional on mode == BPF_ADJ_ROOM_MAC?

>  		if (flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4)
>  			len_min = sizeof(struct iphdr);


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31584739682

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 2/6] bpf: refactor masks for ADJ_ROOM flags and encap validation
  2026-08-12  8:31 ` [PATCH bpf-next v7 2/6] bpf: refactor masks for ADJ_ROOM flags and encap validation Nick Hudson
@ 2026-08-12 10:33   ` bot+bpf-ci
  0 siblings, 0 replies; 17+ messages in thread
From: bot+bpf-ci @ 2026-08-12 10:33 UTC (permalink / raw)
  To: nhudson, bpf, netdev, willemb, martin.lau
  Cc: nhudson, mtottenh, aglasgal, daniel, ast, andrii, eddyz87, memxor,
	davem, edumazet, kuba, pabeni, linux-kernel, ast, andrii, daniel,
	martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1753 bytes --]

> bpf: refactor masks for ADJ_ROOM flags and encap validation
>
> Refactor the helper masks for bpf_skb_adjust_room() flags to simplify
> validation logic and introduce:
>
> - BPF_F_ADJ_ROOM_ENCAP_MASK
> - BPF_F_ADJ_ROOM_DECAP_MASK
>
> Refactor existing validation checks in bpf_skb_net_shrink()
> and bpf_skb_adjust_room() to use the new masks (no behavior change).

Does the subject line accurately describe what is being refactored?

The subject claims the patch refactors "encap validation", but no encap
validation is refactored anywhere in the diff. The only encap validation
in this file is in bpf_skb_net_grow() (around the middle of filter.c),
and it is untouched. It still open-codes the pairwise mutual-exclusion
tests:

    if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 &&
        flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6)
            return -EINVAL;
    if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE &&
        flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP)
            return -EINVAL;

The newly introduced BPF_F_ADJ_ROOM_ENCAP_MASK is never used in a
validation expression. Its only consumer is the composition of
BPF_F_ADJ_ROOM_MASK. This is still true at the tip of the series.

The commit body itself only claims refactoring of bpf_skb_net_shrink()
and bpf_skb_adjust_room(), so the subject, body and diff disagree.

Could "and encap validation" be dropped from the subject (e.g. "bpf:
refactor bpf_skb_adjust_room() flag masks"), or should bpf_skb_net_grow()'s
encap checks be converted to the new mask in this patch?


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31584739682

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path
  2026-08-12  8:31 ` [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path Nick Hudson
  2026-08-12 10:26   ` sashiko-bot
@ 2026-08-12 10:33   ` bot+bpf-ci
  1 sibling, 0 replies; 17+ messages in thread
From: bot+bpf-ci @ 2026-08-12 10:33 UTC (permalink / raw)
  To: nhudson, bpf, netdev, willemb, martin.lau
  Cc: nhudson, mtottenh, aglasgal, daniel, ast, andrii, eddyz87, memxor,
	davem, edumazet, kuba, pabeni, linux-kernel, ast, andrii, daniel,
	martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1406 bytes --]

> On shrink in bpf_skb_adjust_room(), apply decapsulation state updates
> according to BPF_F_ADJ_ROOM_DECAP_* flags.
>
> For GSO skbs, clear only the tunnel gso_type bits that correspond to the
> requested decap layer:
> - DECAP_L4_UDP: SKB_GSO_UDP_TUNNEL{,_CSUM}
> - DECAP_L4_GRE: SKB_GSO_GRE{,_CSUM}
> - DECAP_IPXIP4: SKB_GSO_IPXIP4
> - DECAP_IPXIP6: SKB_GSO_IPXIP6
>
> Then clear skb->encapsulation only if no tunnel GSO bits remain, keeping
> encapsulation set for cases such as ESP-in-UDP where tunnel state remains.
>
> For non-GSO skbs, there are no tunnel GSO bits to consult, so clear
> skb->encapsulation directly when DECAP_L4_* or DECAP_IPXIP_* flags are set.
>
> This keeps decap state handling consistent between GSO and non-GSO packets.

This looks like a bug fix for the DECAP flags added in commit 0e08a219f910.
That commit added the BPF_F_ADJ_ROOM_DECAP_* flags and documented that they
would clear GSO state and encapsulation flags, but the behavior was never
implemented in the code. This commit implements that documented behavior.

Should this include:

  Fixes: 0e08a219f910 ("bpf: add BPF_F_ADJ_ROOM_DECAP_* flags for tunnel decapsulation")


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31584739682

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state
  2026-08-12  8:31 ` [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state Nick Hudson
  2026-08-12 10:20   ` sashiko-bot
@ 2026-08-12 10:48   ` bot+bpf-ci
  1 sibling, 0 replies; 17+ messages in thread
From: bot+bpf-ci @ 2026-08-12 10:48 UTC (permalink / raw)
  To: nhudson, bpf, netdev, willemb, martin.lau
  Cc: nhudson, andrii, eddyz87, ast, daniel, memxor, shuah,
	linux-kselftest, linux-kernel, ast, andrii, daniel, martin.lau,
	eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 4805 bytes --]

> diff --git a/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c b/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c
> index 1aa7c9463980b..67ba27d693474 100644
> --- a/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c
> +++ b/tools/testing/selftests/bpf/prog_tests/test_tc_tunnel.c
> @@ -438,7 +438,6 @@ static int setup(void)
>  	SYS(fail_close_ns_client, "ip link add %s type veth peer name %s",
>  	    "veth1 mtu 1500 netns " CLIENT_NS " address " MAC_ADDR_VETH1,
>  	    "veth2 mtu 1500 netns " SERVER_NS " address " MAC_ADDR_VETH2);
> -	SYS(fail_close_ns_client, "ethtool -K veth1 tso off");
>  	SYS(fail_close_ns_client, "ip link set veth1 up");

Dropping the TSO-off setting here changes what the encap side of the test
exercises. With TSO off, veth1's xmit path had to software-segment the
BPF-encapsulated GSO skb, which validated the encap-side GSO metadata
(inner_protocol, inner_protocol_type, inner header offsets, gso_type,
csum_start) written by BPF_F_ADJ_ROOM_ENCAP_* through gre_gso_segment()
and UDP-tunnel GSO. With TSO on, veth advertises NETIF_F_GSO_SOFTWARE and
NETIF_F_GSO_ENCAP_ALL, so the encapsulated GSO super-packet is forwarded
to veth2 intact and no tunnel GSO segmentation happens anywhere in the
path for any of the 12 `.test_gso = true` subtests.

It also changes what the kernel-decap leg sees: a GSO super-packet through
gre_rcv()/fou_udp_recv() -> iptunnel_pull_offloads() instead of a stream
of segmented packets.

Is it intentional to remove the encap-side segmentation coverage, or should
both modes be preserved?

> diff --git a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c
> index 7376df405a6be..853bca9629103 100644
> --- a/tools/testing/selftests/bpf/progs/test_tc_tunnel.c
> +++ b/tools/testing/selftests/bpf/progs/test_tc_tunnel.c

[ ... ]

> @@ -655,6 +688,40 @@ static int decap_internal(struct __sk_buff *skb, int off, int len, char proto)
>  	if (bpf_skb_adjust_room(skb, -olen, BPF_ADJ_ROOM_MAC, flags))
>  		return TC_ACT_SHOT;
>
> +	kskb = bpf_cast_to_kern_ctx(skb);
> +	shinfo = bpf_core_cast(kskb->head + kskb->end, struct skb_shared_info);
> +	if (shinfo->gso_size) {
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) &&
> +		    (shinfo->gso_type & SKB_GSO_UDP_TUNNEL_MASK))
> +			return TC_ACT_SHOT;
> +
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE) &&
> +		    (shinfo->gso_type & (SKB_GSO_GRE | SKB_GSO_GRE_CSUM)))
> +			return TC_ACT_SHOT;
> +
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4) &&
> +		    (shinfo->gso_type & SKB_GSO_IPXIP4))
> +			return TC_ACT_SHOT;
> +
> +		if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6) &&
> +		    (shinfo->gso_type & SKB_GSO_IPXIP6))
> +			return TC_ACT_SHOT;
> +
> +		if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
> +			     BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) {
> +			if ((shinfo->gso_type & SKB_GSO_TUNNEL_MASK) &&
> +			    !kskb->encapsulation)
> +				return TC_ACT_SHOT;
> +			if (!(shinfo->gso_type & SKB_GSO_TUNNEL_MASK) &&
> +			    kskb->encapsulation)
> +				return TC_ACT_SHOT;
> +		}
> +	} else if ((flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
> +			     BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) &&
> +		   kskb->encapsulation) {
> +		return TC_ACT_SHOT;
> +	}
> +

All of the new GSO assertions sit under `if (shinfo->gso_size)`. If the
packet reaching veth2 ingress is not a GSO skb, this entire block is
skipped, the program returns TC_ACT_OK, and the subtest reports PASS.

Whether a GSO skb reaches the BPF decap program at all depends on emergent
path behavior: TCP builds a GSO skb because sk_setup_caps() forces
NETIF_F_GSO|NETIF_F_GSO_SOFTWARE for TCP sockets, and veth1 does not
segment it because VETH_FEATURES includes NETIF_F_GSO_SOFTWARE and
NETIF_F_GSO_ENCAP_ALL.

Nothing in the test verifies that assumption held. There is no counter or
flag exported to user space saying "a GSO skb was seen and validated". If
a future change to veth features, to sk_route_caps, to the send size, or
to the MTU clamping stops producing GSO skbs on that path, the newly added
assertions become silent no-ops and the test keeps passing green - a false
pass of precisely the kind selftests.md warns about under "Test the
Interface.../negative-test tautologies".

The sibling test progs/decap_sanity.c shows the pattern that avoids this:
record state in a global (init_csum_partial, etc.) and ASSERT_* on it from
the prog_tests side, so "the check never ran" is distinguishable from "the
check passed".

Should this test export a flag or counter indicating that the GSO
validation actually executed?


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31584739682

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails
  2026-08-12 10:22   ` sashiko-bot
@ 2026-08-12 12:13     ` Hudson, Nick
  0 siblings, 0 replies; 17+ messages in thread
From: Hudson, Nick @ 2026-08-12 12:13 UTC (permalink / raw)
  To: sashiko-reviews@lists.linux.dev; +Cc: bpf@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 3732 bytes --]



> On Aug 12, 2026, at 11:22 AM, sashiko-bot@kernel.org wrote:
> 
> !-------------------------------------------------------------------|
>  This Message Is From an External Sender
>  This message came from outside your organization.
> |-------------------------------------------------------------------!
> 
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] The patch exposes new decapsulation flags without implementing the required kernel side effects to clear tunnel-specific GSO flags and `skb->encapsulation` status, leading to stale tunnel metadata on decapsulated packets.
> - [High] The `decap` flag check in `bpf_skb_net_shrink()` was not updated to include the new L4 and IPXIP decapsulation masks, causing critical packet state updates (like dropping the outer `dst_entry`) to be skipped.
> --
> 
> --- Patch [4]: [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails ---
> commit cdd433d824d20f40752fca9cc2db82451d364a2c
> Author: Nick Hudson <nhudson@akamai.com>
> 
> bpf: allow new DECAP flags and add guard rails
> 
> Add checks to require shrink-only decap, reject conflicting decap flag
> combinations, and verify removed length is sufficient for claimed header
> decapsulation.
> 
>> diff --git a/net/core/filter.c b/net/core/filter.c
>> index 89e516049c852..981b75941e7f7 100644
>> --- a/net/core/filter.c
>> +++ b/net/core/filter.c
> [ ... ]
>> @@ -3579,7 +3586,9 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb)
>> BPF_F_ADJ_ROOM_ENCAP_L2( \
>>  BPF_ADJ_ROOM_ENCAP_L2_MASK))
>> 
>> -#define BPF_F_ADJ_ROOM_DECAP_MASK (BPF_F_ADJ_ROOM_DECAP_L3_MASK)
>> +#define BPF_F_ADJ_ROOM_DECAP_MASK (BPF_F_ADJ_ROOM_DECAP_L3_MASK | \
>> + BPF_F_ADJ_ROOM_DECAP_L4_MASK | \
>> + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)
> 
> [Severity: High]
> Does this mask update also need to be reflected in the decap check in
> bpf_skb_net_shrink()?
> 
> Currently, bpf_skb_net_shrink() evaluates decap based only on the L3 mask:
> 
> net/core/filter.c:bpf_skb_net_shrink() {
> bool decap = flags & BPF_F_ADJ_ROOM_DECAP_L3_MASK;
> ...
> if (decap) {
> ...
> if (skb_valid_dst(skb))
> skb_dst_drop(skb);
> }
> ...
> }
> 
> If a BPF program uses BPF_F_ADJ_ROOM_DECAP_L4_UDP to decapsulate an L4 or
> IPXIP tunnel but does not provide BPF_F_ADJ_ROOM_DECAP_L3_MASK, decap
> evaluates to false.
> 
> As a result, skb_dst_drop(skb) is skipped, causing the inner packet to
> incorrectly inherit the outer tunnel's routing cache. This can route the
> inner packet to the tunnel endpoint instead of its true destination.


This exact dst-drop gating question was already discussed on-list:

https://lore.kernel.org/all/20250604210604.257036-1-kuba@kernel.org/

Keeping L3-gated behavior in this series is intentional. Any broader change will be a separate follow-up.

> 
> [Severity: High]
> Does this code miss clearing tunnel-specific GSO flags and skb->encapsulation
> status?
> 
> The UAPI documentation promises that using BPF_F_ADJ_ROOM_DECAP_L4_UDP will
> clear UDP tunnel GSO flags (SKB_GSO_UDP_TUNNEL and SKB_GSO_UDP_TUNNEL_CSUM)
> when decapsulating a UDP tunnel.
> 
> However, bpf_skb_net_shrink() omits the logic to do this:
> 
> net/core/filter.c:bpf_skb_net_shrink() {
> ...
> ret = bpf_skb_net_hdr_pop(skb, off, len_diff);
> if (unlikely(ret < 0))
> return ret;
> 
> if (decap) {
> /* Match skb->protocol to new outer l3 protocol */
> ...
> }
> 
> Leaving stale tunnel metadata on the packet can cause downstream drivers to
> parse incorrect header offsets, resulting in skb_over_panic or
> skb_under_panic.

This is done in patch 5 of the series.





[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 3066 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state
  2026-08-12 10:20   ` sashiko-bot
@ 2026-08-12 12:23     ` Hudson, Nick
  0 siblings, 0 replies; 17+ messages in thread
From: Hudson, Nick @ 2026-08-12 12:23 UTC (permalink / raw)
  To: sashiko-reviews@lists.linux.dev; +Cc: bpf@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 1097 bytes --]



> On Aug 12, 2026, at 11:20 AM, sashiko-bot@kernel.org wrote:
> 
> [Severity: Medium]
> Does this pointer arithmetic break compilation on 32-bit architectures?
> 
> Since kskb->end is a pointer on 32-bit systems (rather than an integer offset
> like it is on 64-bit), adding kskb->head and kskb->end together attempts to add
> two pointers, which is invalid in C.
> 
> Additionally, CO-RE does not translate this pointer-integer addition to a single
> pointer dereference when cross-compiled on 64-bit and run on 32-bit kernels,
> which can lead to a garbage pointer dereference.
> 
> Is there a safer way to calculate the skb_shared_info offset in decap_internal
> that is portable across both 32-bit and 64-bit architectures?


Martin KaFai Lau previously replied.

"Other tests have been using it to get shinfo already. I would leave it as is.
If it really would be needed to run and compile on 32-bit in the future,
it could use bpf_core_field_size(kskb->end) and then do things differently.”

https://lore.kernel.org/all/2026416193859.IJ9_.martin.lau@linux.dev/

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 3066 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path
  2026-08-12 10:26   ` sashiko-bot
@ 2026-08-12 12:30     ` Hudson, Nick
  0 siblings, 0 replies; 17+ messages in thread
From: Hudson, Nick @ 2026-08-12 12:30 UTC (permalink / raw)
  To: sashiko-reviews@lists.linux.dev; +Cc: bpf@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 3738 bytes --]



> On Aug 12, 2026, at 11:26 AM, sashiko-bot@kernel.org wrote:
> 
> !-------------------------------------------------------------------|
>  This Message Is From an External Sender
>  This message came from outside your organization.
> |-------------------------------------------------------------------!
> 
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] bpf_skb_net_shrink() leaves SKB_GSO_PARTIAL and SKB_GSO_TUNNEL_REMCSUM dangling in shinfo->gso_type after removing a tunnel.
> --
> 
> --- Patch [5]: [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path ---
> commit 672aa1a359079a58d5e4d80fc47569e00a437a80
> Author: Nick Hudson <nhudson@akamai.com>
> bpf: clear decap state on skb_adjust_room shrink path
> 
> This commit updates bpf_skb_adjust_room() on the shrink path to conditionally
> clear decapsulation state updates based on BPF_F_ADJ_ROOM_DECAP_* flags. For
> GSO skbs, it selectively clears tunnel gso_type bits and encapsulation, while
> for non-GSO skbs it directly clears the encapsulation flag.
> 
>> diff --git a/net/core/filter.c b/net/core/filter.c
>> index 981b75941e7f7..89effff3bc525 100644
>> --- a/net/core/filter.c
>> +++ b/net/core/filter.c
>> @@ -3754,9 +3754,48 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
>> if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
>> skb_increase_gso_size(shinfo, len_diff);
>> 
>> + /* Selective GSO flag clearing based on decap type.
>> + * Only clear the flags for the tunnel layer being removed.
>> + */
>> + if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) &&
>> +    (shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
>> + SKB_GSO_UDP_TUNNEL_CSUM)))
>> + shinfo->gso_type &= ~(SKB_GSO_UDP_TUNNEL |
>> +      SKB_GSO_UDP_TUNNEL_CSUM);
> 
> [Severity: High]
> Does this leave SKB_GSO_PARTIAL and SKB_GSO_TUNNEL_REMCSUM dangling in
> shinfo->gso_type after removing a tunnel?
> 
> If an SKB acquires SKB_GSO_PARTIAL or SKB_GSO_TUNNEL_REMCSUM (for example,
> via software partial segmentation across a veth pair or GRO) and a BPF program
> uses bpf_skb_adjust_room() to shrink the SKB, it seems the base tunnel flags
> are cleared but the modifier flags remain.
> 
> Hardware drivers like ixgbe or fbnic use SKB_GSO_PARTIAL to identify packets
> requiring partial GSO offload or special tunnel logic. Could leaving this flag
> on a decapsulated, non-tunnel SKB cause drivers to misinterpret the packet
> structure and corrupt the packet on transmit?

Willem de Bruijn said to not add it to this series.

REMCSUM was previously not included in the series.

It is a non-obvious and rare enough feature that I would exclude it,
or move it to a separate patch.

https://lore.kernel.org/all/willemdebruijn.kernel.245c592e6d270@gmail.com/


> 
> [ ... ]
> 
>> + /* Clear encapsulation flag only when no tunnel GSO flags remain */
>> + if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
>> +     BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) {
>> + if (!(shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
>> +  SKB_GSO_UDP_TUNNEL_CSUM |
>> +  SKB_GSO_GRE |
>> +  SKB_GSO_GRE_CSUM |
>> +  SKB_GSO_IPXIP4 |
>> +  SKB_GSO_IPXIP6 |
>> +  SKB_GSO_ESP)))
>> + if (skb->encapsulation)
>> + skb->encapsulation = 0;
>> + }
> 
> [Severity: High]
> If all base tunnel flags are cleared and encapsulation is set to 0, which
> confirms the packet is no longer a tunnel, is it expected that SKB_GSO_PARTIAL
> and SKB_GSO_TUNNEL_REMCSUM might still be set in gso_type?
> 


Any change to force-clear REMCSUM/PARTIAL would be done as a separate follow-up with dedicated justification/tests, rather than folded into this decap-flag series.”


[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 3066 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2026-08-12 12:30 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12  8:31 [PATCH bpf-next v7 0/6] bpf: decap flags and GSO state updates Nick Hudson
2026-08-12  8:31 ` [PATCH bpf-next v7 1/6] bpf: name the enum for BPF_FUNC_skb_adjust_room flags Nick Hudson
2026-08-12  8:31 ` [PATCH bpf-next v7 2/6] bpf: refactor masks for ADJ_ROOM flags and encap validation Nick Hudson
2026-08-12 10:33   ` bot+bpf-ci
2026-08-12  8:31 ` [PATCH bpf-next v7 3/6] bpf: add BPF_F_ADJ_ROOM_DECAP_* flags for tunnel decapsulation Nick Hudson
2026-08-12  8:31 ` [PATCH bpf-next v7 4/6] bpf: allow new DECAP flags and add guard rails Nick Hudson
2026-08-12 10:22   ` sashiko-bot
2026-08-12 12:13     ` Hudson, Nick
2026-08-12 10:33   ` bot+bpf-ci
2026-08-12  8:31 ` [PATCH bpf-next v7 5/6] bpf: clear decap state on skb_adjust_room shrink path Nick Hudson
2026-08-12 10:26   ` sashiko-bot
2026-08-12 12:30     ` Hudson, Nick
2026-08-12 10:33   ` bot+bpf-ci
2026-08-12  8:31 ` [PATCH bpf-next v7 6/6] selftests/bpf: tc_tunnel - validate decap GSO and encapsulation state Nick Hudson
2026-08-12 10:20   ` sashiko-bot
2026-08-12 12:23     ` Hudson, Nick
2026-08-12 10:48   ` bot+bpf-ci

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox