summaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorVlad Yasevich <vyasevich@gmail.com>2015-01-31 10:40:18 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-02 19:28:05 -0800
commit32dce968dd987adfb0c00946d78dad9154f64759 (patch)
treeb5005ef754bb0dd4d6b15a37d94be210e2ee9045 /net/ipv6
parent03485f2adcde0c2d4e9228b659be78e872486bbb (diff)
downloadlinux-32dce968dd987adfb0c00946d78dad9154f64759.tar.gz
linux-32dce968dd987adfb0c00946d78dad9154f64759.tar.bz2
linux-32dce968dd987adfb0c00946d78dad9154f64759.zip
ipv6: Allow for partial checksums on non-ufo packets
Currntly, if we are not doing UFO on the packet, all UDP packets will start with CHECKSUM_NONE and thus perform full checksum computations in software even if device support IPv6 checksum offloading. Let's start start with CHECKSUM_PARTIAL if the device supports it and we are sending only a single packet at or below mtu size. Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_output.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index b89d3c27dac7..1a036f35d833 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1227,6 +1227,7 @@ static int __ip6_append_data(struct sock *sk,
u32 tskey = 0;
struct rt6_info *rt = (struct rt6_info *)cork->dst;
struct ipv6_txoptions *opt = v6_cork->opt;
+ int csummode = CHECKSUM_NONE;
skb = skb_peek_tail(queue);
if (!skb) {
@@ -1283,6 +1284,14 @@ emsgsize:
tskey = sk->sk_tskey++;
}
+ /* If this is the first and only packet and device
+ * supports checksum offloading, let's use it.
+ */
+ if (!skb &&
+ length + fragheaderlen < mtu &&
+ rt->dst.dev->features & NETIF_F_V6_CSUM &&
+ !exthdrlen)
+ csummode = CHECKSUM_PARTIAL;
/*
* Let's try using as much space as possible.
* Use MTU if total length of the message fits into the MTU.
@@ -1395,7 +1404,7 @@ alloc_new_skb:
* Fill in the control structures
*/
skb->protocol = htons(ETH_P_IPV6);
- skb->ip_summed = CHECKSUM_NONE;
+ skb->ip_summed = csummode;
skb->csum = 0;
/* reserve for fragmentation and ipsec header */
skb_reserve(skb, hh_len + sizeof(struct frag_hdr) +