[PATCH RFC 7/9] sk_buff: move inner header fields after tail

Paolo Abeni pabeni at redhat.com
Wed Jul 21 16:44:39 UTC 2021


all the inner header fields are valid only if the 'encaspulation'
flag is set, and the relevant fields are always initialized when
the field is set: we don't need to initialize them at skb allocation
time

Signed-off-by: Paolo Abeni <pabeni at redhat.com>
---
 v1 -> v2:
  - add CHECK_SKB_FIELD(__encapsulation_offset) in __copy_skb_header
---
 include/linux/skbuff.h | 31 ++++++++++++++++++++++---------
 net/core/skbuff.c      |  6 ++----
 2 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index ea9fdcc7c7ca..a3e756575aa7 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -822,6 +822,9 @@ struct sk_buff {
 	__u8			ip_summed:2;
 	__u8			ooo_okay:1;
 
+	/* private: */
+	__u8			__pkt_encapsulation_offset[0];
+	/* public: */
 	__u8			l4_hash:1;
 	__u8			sw_hash:1;
 	__u8			wifi_acked_valid:1;
@@ -911,15 +914,6 @@ struct sk_buff {
 		__u32		reserved_tailroom;
 	};
 
-	union {
-		__be16		inner_protocol;
-		__u8		inner_ipproto;
-	};
-
-	__u16			inner_transport_header;
-	__u16			inner_network_header;
-	__u16			inner_mac_header;
-
 	__be16			protocol;
 	__u16			transport_header;
 	__u16			network_header;
@@ -948,6 +942,19 @@ struct sk_buff {
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
 	unsigned long		 _nfct;
 #endif
+	union {
+		struct {
+			union {
+			__be16	inner_protocol;
+			__u8	inner_ipproto;
+			};
+
+			__u16	inner_transport_header;
+			__u16	inner_network_header;
+			__u16	inner_mac_header;
+		};
+		__u64		inner_headers;
+	};
 };
 
 #ifdef __KERNEL__
@@ -2449,6 +2456,12 @@ static inline void skb_tailroom_reserve(struct sk_buff *skb, unsigned int mtu,
 #define ENCAP_TYPE_ETHER	0
 #define ENCAP_TYPE_IPPROTO	1
 
+static inline void __skb_copy_inner_headers(struct sk_buff *dst, const struct sk_buff *src)
+{
+	if (src->encapsulation)
+		dst->inner_headers = src->inner_headers;
+}
+
 static inline void skb_set_inner_protocol(struct sk_buff *skb,
 					  __be16 protocol)
 {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 9ed754da6e13..53b8db10e567 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -995,6 +995,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	skb_dst_copy(new, old);
 	__skb_ext_copy(new, old);
 	__nf_copy(new, old, false);
+	__skb_copy_inner_headers(new, old);
 
 	/* Note : this field could be in headers_start/headers_end section
 	 * It is not yet because we do not want to have a 16 bit hole
@@ -1005,6 +1006,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	       offsetof(struct sk_buff, headers_end) -
 	       offsetof(struct sk_buff, headers_start));
 	CHECK_SKB_FIELD(_state);
+	CHECK_SKB_FIELD(__pkt_encapsulation_offset);
 	CHECK_SKB_FIELD(protocol);
 	CHECK_SKB_FIELD(csum);
 	CHECK_SKB_FIELD(hash);
@@ -1015,10 +1017,6 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
 	CHECK_SKB_FIELD(transport_header);
 	CHECK_SKB_FIELD(network_header);
 	CHECK_SKB_FIELD(mac_header);
-	CHECK_SKB_FIELD(inner_protocol);
-	CHECK_SKB_FIELD(inner_transport_header);
-	CHECK_SKB_FIELD(inner_network_header);
-	CHECK_SKB_FIELD(inner_mac_header);
 	CHECK_SKB_FIELD(mark);
 #ifdef CONFIG_NETWORK_SECMARK
 	CHECK_SKB_FIELD(secmark);
-- 
2.26.3



More information about the Linux-security-module-archive mailing list