aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/udp_offload.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/udp_offload.c')
-rw-r--r--net/ipv4/udp_offload.c29
1 files changed, 19 insertions, 10 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,
214 return segs; 214 return segs;
215 } 215 }
216 216
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
217 seg = segs; 224 seg = segs;
218 uh = udp_hdr(seg); 225 uh = udp_hdr(seg);
219 226
@@ -232,6 +239,12 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
232 uh->len = newlen; 239 uh->len = newlen;
233 uh->check = check; 240 uh->check = check;
234 241
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
235 seg = seg->next; 248 seg = seg->next;
236 uh = udp_hdr(seg); 249 uh = udp_hdr(seg);
237 } 250 }
@@ -244,6 +257,11 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
244 uh->len = newlen; 257 uh->len = newlen;
245 uh->check = check; 258 uh->check = check;
246 259
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
247 /* update refcount for the packet */ 265 /* update refcount for the packet */
248 refcount_add(sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc); 266 refcount_add(sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc);
249 267
@@ -251,15 +269,6 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
251} 269}
252EXPORT_SYMBOL_GPL(__udp_gso_segment); 270EXPORT_SYMBOL_GPL(__udp_gso_segment);
253 271
254static 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
263static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, 272static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
264 netdev_features_t features) 273 netdev_features_t features)
265{ 274{
@@ -283,7 +292,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
283 goto out; 292 goto out;
284 293
285 if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) 294 if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
286 return __udp4_gso_segment(skb, features); 295 return __udp_gso_segment(skb, features);
287 296
288 mss = skb_shinfo(skb)->gso_size; 297 mss = skb_shinfo(skb)->gso_size;
289 if (unlikely(skb->len <= mss)) 298 if (unlikely(skb->len <= mss))