diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/udp_offload.c | 29 | ||||
-rw-r--r-- | net/ipv6/udp_offload.c | 11 |
2 files changed, 20 insertions, 20 deletions
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index b15c78ac3f23..d4f2daca0c33 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -214,6 +214,13 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, return segs; } + /* GSO partial and frag_list segmentation only requires splitting + * the frame into an MSS multiple and possibly a remainder, both + * cases return a GSO skb. So update the mss now. + */ + if (skb_is_gso(segs)) + mss *= skb_shinfo(segs)->gso_segs; + seg = segs; uh = udp_hdr(seg); @@ -232,6 +239,12 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, uh->len = newlen; uh->check = check; + if (seg->ip_summed == CHECKSUM_PARTIAL) + gso_reset_checksum(seg, ~check); + else + uh->check = gso_make_checksum(seg, ~check) ? : + CSUM_MANGLED_0; + seg = seg->next; uh = udp_hdr(seg); } @@ -244,6 +257,11 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, uh->len = newlen; uh->check = check; + if (seg->ip_summed == CHECKSUM_PARTIAL) + gso_reset_checksum(seg, ~check); + else + uh->check = gso_make_checksum(seg, ~check) ? : CSUM_MANGLED_0; + /* update refcount for the packet */ refcount_add(sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc); @@ -251,15 +269,6 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, } EXPORT_SYMBOL_GPL(__udp_gso_segment); -static struct sk_buff *__udp4_gso_segment(struct sk_buff *gso_skb, - netdev_features_t features) -{ - if (!can_checksum_protocol(features, htons(ETH_P_IP))) - return ERR_PTR(-EIO); - - return __udp_gso_segment(gso_skb, features); -} - static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, netdev_features_t features) { @@ -283,7 +292,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, goto out; if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) - return __udp4_gso_segment(skb, features); + return __udp_gso_segment(skb, features); mss = skb_shinfo(skb)->gso_size; if (unlikely(skb->len <= mss)) diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 61e34f1d2fa2..03a2ff3fe1e6 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c @@ -17,15 +17,6 @@ #include <net/ip6_checksum.h> #include "ip6_offload.h" -static struct sk_buff *__udp6_gso_segment(struct sk_buff *gso_skb, - netdev_features_t features) -{ - if (!can_checksum_protocol(features, htons(ETH_P_IPV6))) - return ERR_PTR(-EIO); - - return __udp_gso_segment(gso_skb, features); -} - static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, netdev_features_t features) { @@ -58,7 +49,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, goto out; if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) - return __udp6_gso_segment(skb, features); + return __udp_gso_segment(skb, features); /* Do software UFO. Complete and fill in the UDP checksum as HW cannot * do checksum of UDP packets sent as multiple IP fragments. |