diff options
author | Tom Herbert <therbert@google.com> | 2014-08-22 16:33:47 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-08-24 21:09:23 -0400 |
commit | 573e8fca255a27e3573b51f9b183d62641c47a3d (patch) | |
tree | 037fa48ffcd2b80e9b861904370ae64a6cba4224 /include/linux/netdevice.h | |
parent | 8fc54f68919298ff9689d980efb495707ef43f30 (diff) |
net: skb_gro_checksum_* functions
Add skb_gro_checksum_validate, skb_gro_checksum_validate_zero_check,
and skb_gro_checksum_simple_validate, and __skb_gro_checksum_complete.
These are the cognates of the normal checksum functions but are used
in the gro_receive path and operate on GRO related fields in sk_buffs.
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/netdevice.h')
-rw-r--r-- | include/linux/netdevice.h | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7e2b0b8b5cd7..eb73444e1bd0 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1883,7 +1883,13 @@ struct napi_gro_cb { | |||
1883 | u16 proto; | 1883 | u16 proto; |
1884 | 1884 | ||
1885 | /* Used in udp_gro_receive */ | 1885 | /* Used in udp_gro_receive */ |
1886 | u16 udp_mark; | 1886 | u8 udp_mark:1; |
1887 | |||
1888 | /* GRO checksum is valid */ | ||
1889 | u8 csum_valid:1; | ||
1890 | |||
1891 | /* Number encapsulation layers crossed */ | ||
1892 | u8 encapsulation; | ||
1887 | 1893 | ||
1888 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ | 1894 | /* used to support CHECKSUM_COMPLETE for tunneling protocols */ |
1889 | __wsum csum; | 1895 | __wsum csum; |
@@ -2154,11 +2160,77 @@ static inline void *skb_gro_network_header(struct sk_buff *skb) | |||
2154 | static inline void skb_gro_postpull_rcsum(struct sk_buff *skb, | 2160 | static inline void skb_gro_postpull_rcsum(struct sk_buff *skb, |
2155 | const void *start, unsigned int len) | 2161 | const void *start, unsigned int len) |
2156 | { | 2162 | { |
2157 | if (skb->ip_summed == CHECKSUM_COMPLETE) | 2163 | if (NAPI_GRO_CB(skb)->csum_valid) |
2158 | NAPI_GRO_CB(skb)->csum = csum_sub(NAPI_GRO_CB(skb)->csum, | 2164 | NAPI_GRO_CB(skb)->csum = csum_sub(NAPI_GRO_CB(skb)->csum, |
2159 | csum_partial(start, len, 0)); | 2165 | csum_partial(start, len, 0)); |
2160 | } | 2166 | } |
2161 | 2167 | ||
2168 | /* GRO checksum functions. These are logical equivalents of the normal | ||
2169 | * checksum functions (in skbuff.h) except that they operate on the GRO | ||
2170 | * offsets and fields in sk_buff. | ||
2171 | */ | ||
2172 | |||
2173 | __sum16 __skb_gro_checksum_complete(struct sk_buff *skb); | ||
2174 | |||
2175 | static inline bool __skb_gro_checksum_validate_needed(struct sk_buff *skb, | ||
2176 | bool zero_okay, | ||
2177 | __sum16 check) | ||
2178 | { | ||
2179 | return (skb->ip_summed != CHECKSUM_PARTIAL && | ||
2180 | (skb->ip_summed != CHECKSUM_UNNECESSARY || | ||
2181 | (NAPI_GRO_CB(skb)->encapsulation > skb->encapsulation)) && | ||
2182 | (!zero_okay || check)); | ||
2183 | } | ||
2184 | |||
2185 | static inline __sum16 __skb_gro_checksum_validate_complete(struct sk_buff *skb, | ||
2186 | __wsum psum) | ||
2187 | { | ||
2188 | if (NAPI_GRO_CB(skb)->csum_valid && | ||
2189 | !csum_fold(csum_add(psum, NAPI_GRO_CB(skb)->csum))) | ||
2190 | return 0; | ||
2191 | |||
2192 | NAPI_GRO_CB(skb)->csum = psum; | ||
2193 | |||
2194 | return __skb_gro_checksum_complete(skb); | ||
2195 | } | ||
2196 | |||
2197 | /* Update skb for CHECKSUM_UNNECESSARY when we verified a top level | ||
2198 | * checksum or an encapsulated one during GRO. This saves work | ||
2199 | * if we fallback to normal path with the packet. | ||
2200 | */ | ||
2201 | static inline void skb_gro_incr_csum_unnecessary(struct sk_buff *skb) | ||
2202 | { | ||
2203 | if (skb->ip_summed == CHECKSUM_UNNECESSARY) { | ||
2204 | if (NAPI_GRO_CB(skb)->encapsulation) | ||
2205 | skb->encapsulation = 1; | ||
2206 | } else if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
2207 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
2208 | skb->encapsulation = 0; | ||
2209 | } | ||
2210 | } | ||
2211 | |||
2212 | #define __skb_gro_checksum_validate(skb, proto, zero_okay, check, \ | ||
2213 | compute_pseudo) \ | ||
2214 | ({ \ | ||
2215 | __sum16 __ret = 0; \ | ||
2216 | if (__skb_gro_checksum_validate_needed(skb, zero_okay, check)) \ | ||
2217 | __ret = __skb_gro_checksum_validate_complete(skb, \ | ||
2218 | compute_pseudo(skb, proto)); \ | ||
2219 | if (!__ret) \ | ||
2220 | skb_gro_incr_csum_unnecessary(skb); \ | ||
2221 | __ret; \ | ||
2222 | }) | ||
2223 | |||
2224 | #define skb_gro_checksum_validate(skb, proto, compute_pseudo) \ | ||
2225 | __skb_gro_checksum_validate(skb, proto, false, 0, compute_pseudo) | ||
2226 | |||
2227 | #define skb_gro_checksum_validate_zero_check(skb, proto, check, \ | ||
2228 | compute_pseudo) \ | ||
2229 | __skb_gro_checksum_validate(skb, proto, true, check, compute_pseudo) | ||
2230 | |||
2231 | #define skb_gro_checksum_simple_validate(skb) \ | ||
2232 | __skb_gro_checksum_validate(skb, 0, false, 0, null_compute_pseudo) | ||
2233 | |||
2162 | static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, | 2234 | static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, |
2163 | unsigned short type, | 2235 | unsigned short type, |
2164 | const void *daddr, const void *saddr, | 2236 | const void *daddr, const void *saddr, |