Skip to content

Commit 6053d0f

Browse files
Alexander Duyckdavem330
authored andcommitted
udp: Add support for software checksum and GSO_PARTIAL with GSO offload
This patch adds support for a software provided checksum and GSO_PARTIAL segmentation support. With this we can offload UDP segmentation on devices that only have partial support for tunnels. Since we are no longer needing the hardware checksum we can drop the checks in the segmentation code that were verifying if it was present. Signed-off-by: Alexander Duyck <[email protected]> Acked-by: Willem de Bruijn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0ad6509 commit 6053d0f

File tree

2 files changed

+20
-20
lines changed

2 files changed

+20
-20
lines changed

net/ipv4/udp_offload.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
214214
return segs;
215215
}
216216

217+
/* GSO partial and frag_list segmentation only requires splitting
218+
* the frame into an MSS multiple and possibly a remainder, both
219+
* cases return a GSO skb. So update the mss now.
220+
*/
221+
if (skb_is_gso(segs))
222+
mss *= skb_shinfo(segs)->gso_segs;
223+
217224
seg = segs;
218225
uh = udp_hdr(seg);
219226

@@ -232,6 +239,12 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
232239
uh->len = newlen;
233240
uh->check = check;
234241

242+
if (seg->ip_summed == CHECKSUM_PARTIAL)
243+
gso_reset_checksum(seg, ~check);
244+
else
245+
uh->check = gso_make_checksum(seg, ~check) ? :
246+
CSUM_MANGLED_0;
247+
235248
seg = seg->next;
236249
uh = udp_hdr(seg);
237250
}
@@ -244,22 +257,18 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
244257
uh->len = newlen;
245258
uh->check = check;
246259

260+
if (seg->ip_summed == CHECKSUM_PARTIAL)
261+
gso_reset_checksum(seg, ~check);
262+
else
263+
uh->check = gso_make_checksum(seg, ~check) ? : CSUM_MANGLED_0;
264+
247265
/* update refcount for the packet */
248266
refcount_add(sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc);
249267

250268
return segs;
251269
}
252270
EXPORT_SYMBOL_GPL(__udp_gso_segment);
253271

254-
static struct sk_buff *__udp4_gso_segment(struct sk_buff *gso_skb,
255-
netdev_features_t features)
256-
{
257-
if (!can_checksum_protocol(features, htons(ETH_P_IP)))
258-
return ERR_PTR(-EIO);
259-
260-
return __udp_gso_segment(gso_skb, features);
261-
}
262-
263272
static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
264273
netdev_features_t features)
265274
{
@@ -283,7 +292,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
283292
goto out;
284293

285294
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
286-
return __udp4_gso_segment(skb, features);
295+
return __udp_gso_segment(skb, features);
287296

288297
mss = skb_shinfo(skb)->gso_size;
289298
if (unlikely(skb->len <= mss))

net/ipv6/udp_offload.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@
1717
#include <net/ip6_checksum.h>
1818
#include "ip6_offload.h"
1919

20-
static struct sk_buff *__udp6_gso_segment(struct sk_buff *gso_skb,
21-
netdev_features_t features)
22-
{
23-
if (!can_checksum_protocol(features, htons(ETH_P_IPV6)))
24-
return ERR_PTR(-EIO);
25-
26-
return __udp_gso_segment(gso_skb, features);
27-
}
28-
2920
static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
3021
netdev_features_t features)
3122
{
@@ -58,7 +49,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
5849
goto out;
5950

6051
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
61-
return __udp6_gso_segment(skb, features);
52+
return __udp_gso_segment(skb, features);
6253

6354
/* Do software UFO. Complete and fill in the UDP checksum as HW cannot
6455
* do checksum of UDP packets sent as multiple IP fragments.

0 commit comments

Comments
 (0)