@@ -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)
{
@@ -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);
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@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(-)