aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp_offload.c
diff options
context:
space:
mode:
authorAlexander Duyck <aduyck@mirantis.com>2016-02-24 16:46:21 -0800
committerDavid S. Miller <davem@davemloft.net>2016-02-26 14:23:35 -0500
commit224638766235ba82c53b4216e4dabc510701fbf2 (patch)
tree593d446859b883db6cfb9f8926a28efc141e0a99 /net/ipv6/udp_offload.c
parentMerge branch 'vrf-saddr-selection' (diff)
downloadlinux-dev-224638766235ba82c53b4216e4dabc510701fbf2.tar.xz
linux-dev-224638766235ba82c53b4216e4dabc510701fbf2.zip
GSO: Provide software checksum of tunneled UDP fragmentation offload
On reviewing the code I realized that GRE and UDP tunnels could cause a kernel panic if we used GSO to segment a large UDP frame that was sent through the tunnel with an outer checksum and hardware offloads were not available. In order to correct this we need to update the feature flags that are passed to the skb_segment function so that in the event of UDP fragmentation being requested for the inner header the segmentation function will correctly generate the checksum for the payload if we cannot segment the outer header. Signed-off-by: Alexander Duyck <aduyck@mirantis.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/udp_offload.c')
-rw-r--r--net/ipv6/udp_offload.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index 7441e1e63893..2b0fbe6929e8 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -81,12 +81,18 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
csum = skb_checksum(skb, 0, skb->len, 0);
uh->check = udp_v6_check(skb->len, &ipv6h->saddr,
&ipv6h->daddr, csum);
-
if (uh->check == 0)
uh->check = CSUM_MANGLED_0;
skb->ip_summed = CHECKSUM_NONE;
+ /* If there is no outer header we can fake a checksum offload
+ * due to the fact that we have already done the checksum in
+ * software prior to segmenting the frame.
+ */
+ if (!skb->encap_hdr_csum)
+ features |= NETIF_F_HW_CSUM;
+
/* Check if there is enough headroom to insert fragment header. */
tnl_hlen = skb_tnl_header_len(skb);
if (skb->mac_header < (tnl_hlen + frag_hdr_sz)) {