aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netdevice.h76
-rw-r--r--net/core/dev.c34
2 files changed, 107 insertions, 3 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)
2154static inline void skb_gro_postpull_rcsum(struct sk_buff *skb, 2160static 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
2175static 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
2185static 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 */
2201static 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
2162static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, 2234static 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,
diff --git a/net/core/dev.c b/net/core/dev.c
index 1421dad4cb29..b6a718ec11c1 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3962,7 +3962,13 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
3962 goto normal; 3962 goto normal;
3963 3963
3964 gro_list_prepare(napi, skb); 3964 gro_list_prepare(napi, skb);
3965 NAPI_GRO_CB(skb)->csum = skb->csum; /* Needed for CHECKSUM_COMPLETE */ 3965
3966 if (skb->ip_summed == CHECKSUM_COMPLETE) {
3967 NAPI_GRO_CB(skb)->csum = skb->csum;
3968 NAPI_GRO_CB(skb)->csum_valid = 1;
3969 } else {
3970 NAPI_GRO_CB(skb)->csum_valid = 0;
3971 }
3966 3972
3967 rcu_read_lock(); 3973 rcu_read_lock();
3968 list_for_each_entry_rcu(ptype, head, list) { 3974 list_for_each_entry_rcu(ptype, head, list) {
@@ -3975,6 +3981,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
3975 NAPI_GRO_CB(skb)->flush = 0; 3981 NAPI_GRO_CB(skb)->flush = 0;
3976 NAPI_GRO_CB(skb)->free = 0; 3982 NAPI_GRO_CB(skb)->free = 0;
3977 NAPI_GRO_CB(skb)->udp_mark = 0; 3983 NAPI_GRO_CB(skb)->udp_mark = 0;
3984 NAPI_GRO_CB(skb)->encapsulation = 0;
3978 3985
3979 pp = ptype->callbacks.gro_receive(&napi->gro_list, skb); 3986 pp = ptype->callbacks.gro_receive(&napi->gro_list, skb);
3980 break; 3987 break;
@@ -4205,6 +4212,31 @@ gro_result_t napi_gro_frags(struct napi_struct *napi)
4205} 4212}
4206EXPORT_SYMBOL(napi_gro_frags); 4213EXPORT_SYMBOL(napi_gro_frags);
4207 4214
4215/* Compute the checksum from gro_offset and return the folded value
4216 * after adding in any pseudo checksum.
4217 */
4218__sum16 __skb_gro_checksum_complete(struct sk_buff *skb)
4219{
4220 __wsum wsum;
4221 __sum16 sum;
4222
4223 wsum = skb_checksum(skb, skb_gro_offset(skb), skb_gro_len(skb), 0);
4224
4225 /* NAPI_GRO_CB(skb)->csum holds pseudo checksum */
4226 sum = csum_fold(csum_add(NAPI_GRO_CB(skb)->csum, wsum));
4227 if (likely(!sum)) {
4228 if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
4229 !skb->csum_complete_sw)
4230 netdev_rx_csum_fault(skb->dev);
4231 }
4232
4233 NAPI_GRO_CB(skb)->csum = wsum;
4234 NAPI_GRO_CB(skb)->csum_valid = 1;
4235
4236 return sum;
4237}
4238EXPORT_SYMBOL(__skb_gro_checksum_complete);
4239
4208/* 4240/*
4209 * net_rps_action_and_irq_enable sends any pending IPI's for rps. 4241 * net_rps_action_and_irq_enable sends any pending IPI's for rps.
4210 * Note: called with local irq disabled, but exits with local irq enabled. 4242 * Note: called with local irq disabled, but exits with local irq enabled.