1 /* SPDX-License-Identifier: GPL-2.0-or-later */
6 #include <linux/skbuff.h>
8 /* Keeps track of mac header offset relative to skb->head.
9 * It is useful for TSO of Tunneling protocol. e.g. GRE.
10 * For non-tunnel skb it points to skb_mac_header() and for
11 * tunnel skb it points to outer mac header.
12 * Keeps track of level of encapsulation of network headers.
23 #define SKB_GSO_CB_OFFSET 32
24 #define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_GSO_CB_OFFSET))
26 static inline int skb_tnl_header_len(const struct sk_buff
*inner_skb
)
28 return (skb_mac_header(inner_skb
) - inner_skb
->head
) -
29 SKB_GSO_CB(inner_skb
)->mac_offset
;
32 static inline int gso_pskb_expand_head(struct sk_buff
*skb
, int extra
)
34 int new_headroom
, headroom
;
37 headroom
= skb_headroom(skb
);
38 ret
= pskb_expand_head(skb
, extra
, 0, GFP_ATOMIC
);
42 new_headroom
= skb_headroom(skb
);
43 SKB_GSO_CB(skb
)->mac_offset
+= (new_headroom
- headroom
);
47 static inline void gso_reset_checksum(struct sk_buff
*skb
, __wsum res
)
49 /* Do not update partial checksums if remote checksum is enabled. */
50 if (skb
->remcsum_offload
)
53 SKB_GSO_CB(skb
)->csum
= res
;
54 SKB_GSO_CB(skb
)->csum_start
= skb_checksum_start(skb
) - skb
->head
;
57 /* Compute the checksum for a gso segment. First compute the checksum value
58 * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and
59 * then add in skb->csum (checksum from csum_start to end of packet).
60 * skb->csum and csum_start are then updated to reflect the checksum of the
61 * resultant packet starting from the transport header-- the resultant checksum
62 * is in the res argument (i.e. normally zero or ~ of checksum of a pseudo
65 static inline __sum16
gso_make_checksum(struct sk_buff
*skb
, __wsum res
)
67 unsigned char *csum_start
= skb_transport_header(skb
);
68 int plen
= (skb
->head
+ SKB_GSO_CB(skb
)->csum_start
) - csum_start
;
69 __wsum partial
= SKB_GSO_CB(skb
)->csum
;
71 SKB_GSO_CB(skb
)->csum
= res
;
72 SKB_GSO_CB(skb
)->csum_start
= csum_start
- skb
->head
;
74 return csum_fold(csum_partial(csum_start
, plen
, partial
));
77 struct sk_buff
*__skb_gso_segment(struct sk_buff
*skb
,
78 netdev_features_t features
, bool tx_path
);
80 static inline struct sk_buff
*skb_gso_segment(struct sk_buff
*skb
,
81 netdev_features_t features
)
83 return __skb_gso_segment(skb
, features
, true);
86 struct sk_buff
*skb_eth_gso_segment(struct sk_buff
*skb
,
87 netdev_features_t features
, __be16 type
);
89 struct sk_buff
*skb_mac_gso_segment(struct sk_buff
*skb
,
90 netdev_features_t features
);
92 bool skb_gso_validate_network_len(const struct sk_buff
*skb
, unsigned int mtu
);
94 bool skb_gso_validate_mac_len(const struct sk_buff
*skb
, unsigned int len
);
96 static inline void skb_gso_error_unwind(struct sk_buff
*skb
, __be16 protocol
,
97 int pulled_hlen
, u16 mac_offset
,
100 skb
->protocol
= protocol
;
101 skb
->encapsulation
= 1;
102 skb_push(skb
, pulled_hlen
);
103 skb_reset_transport_header(skb
);
104 skb
->mac_header
= mac_offset
;
105 skb
->network_header
= skb
->mac_header
+ mac_len
;
106 skb
->mac_len
= mac_len
;
109 #endif /* _NET_GSO_H */