diff options
author | Tom Herbert <therbert@google.com> | 2014-08-31 18:12:43 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-02 00:36:28 -0400 |
commit | 2abb7cdc0dc84e99b76ef983a1ae1978922aa9b3 (patch) | |
tree | 9bf6029678d74ef6ad12e832d48d769caf88a4ed /net/ipv4 | |
parent | d96535a17dbbafd567961d14c08c0984ddda9c3c (diff) |
udp: Add support for doing checksum unnecessary conversion
Add support for doing CHECKSUM_UNNECESSARY to CHECKSUM_COMPLETE
conversion in UDP tunneling path.
In the normal UDP path, we call skb_checksum_try_convert after locating
the UDP socket. The check is that checksum conversion is enabled for
the socket (new flag in UDP socket) and that checksum field is
non-zero.
In the UDP GRO path, we call skb_gro_checksum_try_convert after
checksum is validated and checksum field is non-zero. Since this is
already in GRO we assume that checksum conversion is always wanted.
Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/udp.c | 4 | ||||
-rw-r--r-- | net/ipv4/udp_offload.c | 25 |
2 files changed, 21 insertions, 8 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 3549c21fe5f7..0da3849fd35b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1788,6 +1788,10 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
1788 | if (sk != NULL) { | 1788 | if (sk != NULL) { |
1789 | int ret; | 1789 | int ret; |
1790 | 1790 | ||
1791 | if (udp_sk(sk)->convert_csum && uh->check && !IS_UDPLITE(sk)) | ||
1792 | skb_checksum_try_convert(skb, IPPROTO_UDP, uh->check, | ||
1793 | inet_compute_pseudo); | ||
1794 | |||
1791 | ret = udp_queue_rcv_skb(sk, skb); | 1795 | ret = udp_queue_rcv_skb(sk, skb); |
1792 | sock_put(sk); | 1796 | sock_put(sk); |
1793 | 1797 | ||
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index a6adff98382a..84e0e05c9c0e 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -290,16 +290,25 @@ static struct sk_buff **udp4_gro_receive(struct sk_buff **head, | |||
290 | { | 290 | { |
291 | struct udphdr *uh = udp_gro_udphdr(skb); | 291 | struct udphdr *uh = udp_gro_udphdr(skb); |
292 | 292 | ||
293 | /* Don't bother verifying checksum if we're going to flush anyway. */ | 293 | if (unlikely(!uh)) |
294 | if (unlikely(!uh) || | 294 | goto flush; |
295 | (!NAPI_GRO_CB(skb)->flush && | ||
296 | skb_gro_checksum_validate_zero_check(skb, IPPROTO_UDP, uh->check, | ||
297 | inet_gro_compute_pseudo))) { | ||
298 | NAPI_GRO_CB(skb)->flush = 1; | ||
299 | return NULL; | ||
300 | } | ||
301 | 295 | ||
296 | /* Don't bother verifying checksum if we're going to flush anyway. */ | ||
297 | if (!NAPI_GRO_CB(skb)->flush) | ||
298 | goto skip; | ||
299 | |||
300 | if (skb_gro_checksum_validate_zero_check(skb, IPPROTO_UDP, uh->check, | ||
301 | inet_gro_compute_pseudo)) | ||
302 | goto flush; | ||
303 | else if (uh->check) | ||
304 | skb_gro_checksum_try_convert(skb, IPPROTO_UDP, uh->check, | ||
305 | inet_gro_compute_pseudo); | ||
306 | skip: | ||
302 | return udp_gro_receive(head, skb, uh); | 307 | return udp_gro_receive(head, skb, uh); |
308 | |||
309 | flush: | ||
310 | NAPI_GRO_CB(skb)->flush = 1; | ||
311 | return NULL; | ||
303 | } | 312 | } |
304 | 313 | ||
305 | int udp_gro_complete(struct sk_buff *skb, int nhoff) | 314 | int udp_gro_complete(struct sk_buff *skb, int nhoff) |