|
@@ -41,6 +41,14 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
|
|
|
{
|
|
|
struct sk_buff *segs = ERR_PTR(-EINVAL);
|
|
|
unsigned int mss;
|
|
|
+ int offset;
|
|
|
+ __wsum csum;
|
|
|
+
|
|
|
+ if (skb->encapsulation &&
|
|
|
+ skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) {
|
|
|
+ segs = skb_udp_tunnel_segment(skb, features);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
|
|
|
mss = skb_shinfo(skb)->gso_size;
|
|
|
if (unlikely(skb->len <= mss))
|
|
@@ -63,27 +71,20 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
+ /* Do software UFO. Complete and fill in the UDP checksum as
|
|
|
+ * HW cannot do checksum of UDP packets sent as multiple
|
|
|
+ * IP fragments.
|
|
|
+ */
|
|
|
+ offset = skb_checksum_start_offset(skb);
|
|
|
+ csum = skb_checksum(skb, offset, skb->len - offset, 0);
|
|
|
+ offset += skb->csum_offset;
|
|
|
+ *(__sum16 *)(skb->data + offset) = csum_fold(csum);
|
|
|
+ skb->ip_summed = CHECKSUM_NONE;
|
|
|
+
|
|
|
/* Fragment the skb. IP headers of the fragments are updated in
|
|
|
* inet_gso_segment()
|
|
|
*/
|
|
|
- if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL)
|
|
|
- segs = skb_udp_tunnel_segment(skb, features);
|
|
|
- else {
|
|
|
- int offset;
|
|
|
- __wsum csum;
|
|
|
-
|
|
|
- /* Do software UFO. Complete and fill in the UDP checksum as
|
|
|
- * HW cannot do checksum of UDP packets sent as multiple
|
|
|
- * IP fragments.
|
|
|
- */
|
|
|
- offset = skb_checksum_start_offset(skb);
|
|
|
- csum = skb_checksum(skb, offset, skb->len - offset, 0);
|
|
|
- offset += skb->csum_offset;
|
|
|
- *(__sum16 *)(skb->data + offset) = csum_fold(csum);
|
|
|
- skb->ip_summed = CHECKSUM_NONE;
|
|
|
-
|
|
|
- segs = skb_segment(skb, features);
|
|
|
- }
|
|
|
+ segs = skb_segment(skb, features);
|
|
|
out:
|
|
|
return segs;
|
|
|
}
|