diff options
-rw-r--r-- | drivers/net/macvtap.c | 3 | ||||
-rw-r--r-- | drivers/net/tun.c | 12 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 12 | ||||
-rw-r--r-- | include/linux/skbuff.h | 19 | ||||
-rw-r--r-- | net/core/dev.c | 9 | ||||
-rw-r--r-- | net/core/skbuff.c | 4 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 1 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 4 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 4 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 4 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 4 | ||||
-rw-r--r-- | net/ipv6/ip6_offload.c | 1 |
13 files changed, 65 insertions, 15 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 0f0f9ce3a776..b181dfb3d6d6 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -543,6 +543,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, | |||
543 | skb->data_len += len; | 543 | skb->data_len += len; |
544 | skb->len += len; | 544 | skb->len += len; |
545 | skb->truesize += truesize; | 545 | skb->truesize += truesize; |
546 | skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG; | ||
546 | atomic_add(truesize, &skb->sk->sk_wmem_alloc); | 547 | atomic_add(truesize, &skb->sk->sk_wmem_alloc); |
547 | while (len) { | 548 | while (len) { |
548 | int off = base & ~PAGE_MASK; | 549 | int off = base & ~PAGE_MASK; |
@@ -598,7 +599,7 @@ static int macvtap_skb_from_vnet_hdr(struct sk_buff *skb, | |||
598 | 599 | ||
599 | if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { | 600 | if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
600 | skb_shinfo(skb)->gso_size = vnet_hdr->gso_size; | 601 | skb_shinfo(skb)->gso_size = vnet_hdr->gso_size; |
601 | skb_shinfo(skb)->gso_type = gso_type; | 602 | skb_shinfo(skb)->gso_type |= gso_type; |
602 | 603 | ||
603 | /* Header must be checked, and gso_segs computed. */ | 604 | /* Header must be checked, and gso_segs computed. */ |
604 | skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; | 605 | skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index c81680dc10eb..293ce8dfc9e6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1005,6 +1005,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, | |||
1005 | skb->data_len += len; | 1005 | skb->data_len += len; |
1006 | skb->len += len; | 1006 | skb->len += len; |
1007 | skb->truesize += truesize; | 1007 | skb->truesize += truesize; |
1008 | skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG; | ||
1008 | atomic_add(truesize, &skb->sk->sk_wmem_alloc); | 1009 | atomic_add(truesize, &skb->sk->sk_wmem_alloc); |
1009 | while (len) { | 1010 | while (len) { |
1010 | int off = base & ~PAGE_MASK; | 1011 | int off = base & ~PAGE_MASK; |
@@ -1150,16 +1151,18 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1150 | } | 1151 | } |
1151 | 1152 | ||
1152 | if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { | 1153 | if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
1154 | unsigned short gso_type = 0; | ||
1155 | |||
1153 | pr_debug("GSO!\n"); | 1156 | pr_debug("GSO!\n"); |
1154 | switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { | 1157 | switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { |
1155 | case VIRTIO_NET_HDR_GSO_TCPV4: | 1158 | case VIRTIO_NET_HDR_GSO_TCPV4: |
1156 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | 1159 | gso_type = SKB_GSO_TCPV4; |
1157 | break; | 1160 | break; |
1158 | case VIRTIO_NET_HDR_GSO_TCPV6: | 1161 | case VIRTIO_NET_HDR_GSO_TCPV6: |
1159 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | 1162 | gso_type = SKB_GSO_TCPV6; |
1160 | break; | 1163 | break; |
1161 | case VIRTIO_NET_HDR_GSO_UDP: | 1164 | case VIRTIO_NET_HDR_GSO_UDP: |
1162 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 1165 | gso_type = SKB_GSO_UDP; |
1163 | break; | 1166 | break; |
1164 | default: | 1167 | default: |
1165 | tun->dev->stats.rx_frame_errors++; | 1168 | tun->dev->stats.rx_frame_errors++; |
@@ -1168,9 +1171,10 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1168 | } | 1171 | } |
1169 | 1172 | ||
1170 | if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN) | 1173 | if (gso.gso_type & VIRTIO_NET_HDR_GSO_ECN) |
1171 | skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; | 1174 | gso_type |= SKB_GSO_TCP_ECN; |
1172 | 1175 | ||
1173 | skb_shinfo(skb)->gso_size = gso.gso_size; | 1176 | skb_shinfo(skb)->gso_size = gso.gso_size; |
1177 | skb_shinfo(skb)->gso_type |= gso_type; | ||
1174 | if (skb_shinfo(skb)->gso_size == 0) { | 1178 | if (skb_shinfo(skb)->gso_size == 0) { |
1175 | tun->dev->stats.rx_frame_errors++; | 1179 | tun->dev->stats.rx_frame_errors++; |
1176 | kfree_skb(skb); | 1180 | kfree_skb(skb); |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 701408a1ded6..58914c8ea68f 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -220,6 +220,7 @@ static void set_skb_frag(struct sk_buff *skb, struct page *page, | |||
220 | skb->len += size; | 220 | skb->len += size; |
221 | skb->truesize += PAGE_SIZE; | 221 | skb->truesize += PAGE_SIZE; |
222 | skb_shinfo(skb)->nr_frags++; | 222 | skb_shinfo(skb)->nr_frags++; |
223 | skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG; | ||
223 | *len -= size; | 224 | *len -= size; |
224 | } | 225 | } |
225 | 226 | ||
@@ -379,16 +380,18 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | |||
379 | ntohs(skb->protocol), skb->len, skb->pkt_type); | 380 | ntohs(skb->protocol), skb->len, skb->pkt_type); |
380 | 381 | ||
381 | if (hdr->hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) { | 382 | if (hdr->hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) { |
383 | unsigned short gso_type = 0; | ||
384 | |||
382 | pr_debug("GSO!\n"); | 385 | pr_debug("GSO!\n"); |
383 | switch (hdr->hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { | 386 | switch (hdr->hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { |
384 | case VIRTIO_NET_HDR_GSO_TCPV4: | 387 | case VIRTIO_NET_HDR_GSO_TCPV4: |
385 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | 388 | gso_type = SKB_GSO_TCPV4; |
386 | break; | 389 | break; |
387 | case VIRTIO_NET_HDR_GSO_UDP: | 390 | case VIRTIO_NET_HDR_GSO_UDP: |
388 | skb_shinfo(skb)->gso_type = SKB_GSO_UDP; | 391 | gso_type = SKB_GSO_UDP; |
389 | break; | 392 | break; |
390 | case VIRTIO_NET_HDR_GSO_TCPV6: | 393 | case VIRTIO_NET_HDR_GSO_TCPV6: |
391 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | 394 | gso_type = SKB_GSO_TCPV6; |
392 | break; | 395 | break; |
393 | default: | 396 | default: |
394 | net_warn_ratelimited("%s: bad gso type %u.\n", | 397 | net_warn_ratelimited("%s: bad gso type %u.\n", |
@@ -397,7 +400,7 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | |||
397 | } | 400 | } |
398 | 401 | ||
399 | if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) | 402 | if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) |
400 | skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; | 403 | gso_type |= SKB_GSO_TCP_ECN; |
401 | 404 | ||
402 | skb_shinfo(skb)->gso_size = hdr->hdr.gso_size; | 405 | skb_shinfo(skb)->gso_size = hdr->hdr.gso_size; |
403 | if (skb_shinfo(skb)->gso_size == 0) { | 406 | if (skb_shinfo(skb)->gso_size == 0) { |
@@ -405,6 +408,7 @@ static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) | |||
405 | goto frame_err; | 408 | goto frame_err; |
406 | } | 409 | } |
407 | 410 | ||
411 | skb_shinfo(skb)->gso_type |= gso_type; | ||
408 | /* Header must be checked, and gso_segs computed. */ | 412 | /* Header must be checked, and gso_segs computed. */ |
409 | skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; | 413 | skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; |
410 | skb_shinfo(skb)->gso_segs = 0; | 414 | skb_shinfo(skb)->gso_segs = 0; |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 8b2256e880e0..0259b719bebf 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -307,6 +307,13 @@ enum { | |||
307 | SKB_GSO_TCPV6 = 1 << 4, | 307 | SKB_GSO_TCPV6 = 1 << 4, |
308 | 308 | ||
309 | SKB_GSO_FCOE = 1 << 5, | 309 | SKB_GSO_FCOE = 1 << 5, |
310 | |||
311 | /* This indicates at least one fragment might be overwritten | ||
312 | * (as in vmsplice(), sendfile() ...) | ||
313 | * If we need to compute a TX checksum, we'll need to copy | ||
314 | * all frags to avoid possible bad checksum | ||
315 | */ | ||
316 | SKB_GSO_SHARED_FRAG = 1 << 6, | ||
310 | }; | 317 | }; |
311 | 318 | ||
312 | #if BITS_PER_LONG > 32 | 319 | #if BITS_PER_LONG > 32 |
@@ -2201,6 +2208,18 @@ static inline int skb_linearize(struct sk_buff *skb) | |||
2201 | } | 2208 | } |
2202 | 2209 | ||
2203 | /** | 2210 | /** |
2211 | * skb_has_shared_frag - can any frag be overwritten | ||
2212 | * @skb: buffer to test | ||
2213 | * | ||
2214 | * Return true if the skb has at least one frag that might be modified | ||
2215 | * by an external entity (as in vmsplice()/sendfile()) | ||
2216 | */ | ||
2217 | static inline bool skb_has_shared_frag(const struct sk_buff *skb) | ||
2218 | { | ||
2219 | return skb_shinfo(skb)->gso_type & SKB_GSO_SHARED_FRAG; | ||
2220 | } | ||
2221 | |||
2222 | /** | ||
2204 | * skb_linearize_cow - make sure skb is linear and writable | 2223 | * skb_linearize_cow - make sure skb is linear and writable |
2205 | * @skb: buffer to process | 2224 | * @skb: buffer to process |
2206 | * | 2225 | * |
diff --git a/net/core/dev.c b/net/core/dev.c index c69cd8721b28..a83375d3af72 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2271,6 +2271,15 @@ int skb_checksum_help(struct sk_buff *skb) | |||
2271 | return -EINVAL; | 2271 | return -EINVAL; |
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | /* Before computing a checksum, we should make sure no frag could | ||
2275 | * be modified by an external entity : checksum could be wrong. | ||
2276 | */ | ||
2277 | if (skb_has_shared_frag(skb)) { | ||
2278 | ret = __skb_linearize(skb); | ||
2279 | if (ret) | ||
2280 | goto out; | ||
2281 | } | ||
2282 | |||
2274 | offset = skb_checksum_start_offset(skb); | 2283 | offset = skb_checksum_start_offset(skb); |
2275 | BUG_ON(offset >= skb_headlen(skb)); | 2284 | BUG_ON(offset >= skb_headlen(skb)); |
2276 | csum = skb_checksum(skb, offset, skb->len - offset, 0); | 2285 | csum = skb_checksum(skb, offset, skb->len - offset, 0); |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 2568c449fe36..bddc1dd2e7f2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -2340,6 +2340,8 @@ void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len) | |||
2340 | { | 2340 | { |
2341 | int pos = skb_headlen(skb); | 2341 | int pos = skb_headlen(skb); |
2342 | 2342 | ||
2343 | skb_shinfo(skb1)->gso_type = skb_shinfo(skb)->gso_type; | ||
2344 | |||
2343 | if (len < pos) /* Split line is inside header. */ | 2345 | if (len < pos) /* Split line is inside header. */ |
2344 | skb_split_inside_header(skb, skb1, len, pos); | 2346 | skb_split_inside_header(skb, skb1, len, pos); |
2345 | else /* Second chunk has no header, nothing to copy. */ | 2347 | else /* Second chunk has no header, nothing to copy. */ |
@@ -2845,6 +2847,8 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
2845 | skb_copy_from_linear_data_offset(skb, offset, | 2847 | skb_copy_from_linear_data_offset(skb, offset, |
2846 | skb_put(nskb, hsize), hsize); | 2848 | skb_put(nskb, hsize), hsize); |
2847 | 2849 | ||
2850 | skb_shinfo(nskb)->gso_type = skb_shinfo(skb)->gso_type; | ||
2851 | |||
2848 | while (pos < offset + len && i < nfrags) { | 2852 | while (pos < offset + len && i < nfrags) { |
2849 | *frag = skb_shinfo(skb)->frags[i]; | 2853 | *frag = skb_shinfo(skb)->frags[i]; |
2850 | __skb_frag_ref(frag); | 2854 | __skb_frag_ref(frag); |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 4b7053919976..49ddca31c4da 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1306,6 +1306,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, | |||
1306 | SKB_GSO_UDP | | 1306 | SKB_GSO_UDP | |
1307 | SKB_GSO_DODGY | | 1307 | SKB_GSO_DODGY | |
1308 | SKB_GSO_TCP_ECN | | 1308 | SKB_GSO_TCP_ECN | |
1309 | SKB_GSO_SHARED_FRAG | | ||
1309 | 0))) | 1310 | 0))) |
1310 | goto out; | 1311 | goto out; |
1311 | 1312 | ||
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 303012adf9e6..af6be70821c4 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -738,7 +738,7 @@ drop: | |||
738 | static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 738 | static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) |
739 | { | 739 | { |
740 | struct ip_tunnel *tunnel = netdev_priv(dev); | 740 | struct ip_tunnel *tunnel = netdev_priv(dev); |
741 | const struct iphdr *old_iph = ip_hdr(skb); | 741 | const struct iphdr *old_iph; |
742 | const struct iphdr *tiph; | 742 | const struct iphdr *tiph; |
743 | struct flowi4 fl4; | 743 | struct flowi4 fl4; |
744 | u8 tos; | 744 | u8 tos; |
@@ -756,6 +756,8 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
756 | skb_checksum_help(skb)) | 756 | skb_checksum_help(skb)) |
757 | goto tx_error; | 757 | goto tx_error; |
758 | 758 | ||
759 | old_iph = ip_hdr(skb); | ||
760 | |||
759 | if (dev->type == ARPHRD_ETHER) | 761 | if (dev->type == ARPHRD_ETHER) |
760 | IPCB(skb)->flags = 0; | 762 | IPCB(skb)->flags = 0; |
761 | 763 | ||
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 191fc24a745a..8f024d41eefa 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -472,7 +472,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
472 | __be16 df = tiph->frag_off; | 472 | __be16 df = tiph->frag_off; |
473 | struct rtable *rt; /* Route to the other host */ | 473 | struct rtable *rt; /* Route to the other host */ |
474 | struct net_device *tdev; /* Device to other host */ | 474 | struct net_device *tdev; /* Device to other host */ |
475 | const struct iphdr *old_iph = ip_hdr(skb); | 475 | const struct iphdr *old_iph; |
476 | struct iphdr *iph; /* Our new IP header */ | 476 | struct iphdr *iph; /* Our new IP header */ |
477 | unsigned int max_headroom; /* The extra header space needed */ | 477 | unsigned int max_headroom; /* The extra header space needed */ |
478 | __be32 dst = tiph->daddr; | 478 | __be32 dst = tiph->daddr; |
@@ -486,6 +486,8 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
486 | skb_checksum_help(skb)) | 486 | skb_checksum_help(skb)) |
487 | goto tx_error; | 487 | goto tx_error; |
488 | 488 | ||
489 | old_iph = ip_hdr(skb); | ||
490 | |||
489 | if (tos & 1) | 491 | if (tos & 1) |
490 | tos = old_iph->tos; | 492 | tos = old_iph->tos; |
491 | 493 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 52271947a471..3ec1f69c5ceb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -896,6 +896,8 @@ new_segment: | |||
896 | skb_fill_page_desc(skb, i, page, offset, copy); | 896 | skb_fill_page_desc(skb, i, page, offset, copy); |
897 | } | 897 | } |
898 | 898 | ||
899 | skb_shinfo(skb)->gso_type |= SKB_GSO_SHARED_FRAG; | ||
900 | |||
899 | skb->len += copy; | 901 | skb->len += copy; |
900 | skb->data_len += copy; | 902 | skb->data_len += copy; |
901 | skb->truesize += copy; | 903 | skb->truesize += copy; |
@@ -3032,6 +3034,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, | |||
3032 | SKB_GSO_DODGY | | 3034 | SKB_GSO_DODGY | |
3033 | SKB_GSO_TCP_ECN | | 3035 | SKB_GSO_TCP_ECN | |
3034 | SKB_GSO_TCPV6 | | 3036 | SKB_GSO_TCPV6 | |
3037 | SKB_GSO_SHARED_FRAG | | ||
3035 | 0) || | 3038 | 0) || |
3036 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) | 3039 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) |
3037 | goto out; | 3040 | goto out; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0905997e5873..492c7cfe1453 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1240,13 +1240,13 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, | |||
1240 | */ | 1240 | */ |
1241 | if (!skb_shinfo(prev)->gso_size) { | 1241 | if (!skb_shinfo(prev)->gso_size) { |
1242 | skb_shinfo(prev)->gso_size = mss; | 1242 | skb_shinfo(prev)->gso_size = mss; |
1243 | skb_shinfo(prev)->gso_type = sk->sk_gso_type; | 1243 | skb_shinfo(prev)->gso_type |= sk->sk_gso_type; |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | /* CHECKME: To clear or not to clear? Mimics normal skb currently */ | 1246 | /* CHECKME: To clear or not to clear? Mimics normal skb currently */ |
1247 | if (skb_shinfo(skb)->gso_segs <= 1) { | 1247 | if (skb_shinfo(skb)->gso_segs <= 1) { |
1248 | skb_shinfo(skb)->gso_size = 0; | 1248 | skb_shinfo(skb)->gso_size = 0; |
1249 | skb_shinfo(skb)->gso_type = 0; | 1249 | skb_shinfo(skb)->gso_type &= SKB_GSO_SHARED_FRAG; |
1250 | } | 1250 | } |
1251 | 1251 | ||
1252 | /* Difference in this won't matter, both ACKed by the same cumul. ACK */ | 1252 | /* Difference in this won't matter, both ACKed by the same cumul. ACK */ |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 667a6adfccf8..367e2ec01da1 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1133,6 +1133,7 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) | |||
1133 | static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, | 1133 | static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, |
1134 | unsigned int mss_now) | 1134 | unsigned int mss_now) |
1135 | { | 1135 | { |
1136 | skb_shinfo(skb)->gso_type &= SKB_GSO_SHARED_FRAG; | ||
1136 | if (skb->len <= mss_now || !sk_can_gso(sk) || | 1137 | if (skb->len <= mss_now || !sk_can_gso(sk) || |
1137 | skb->ip_summed == CHECKSUM_NONE) { | 1138 | skb->ip_summed == CHECKSUM_NONE) { |
1138 | /* Avoid the costly divide in the normal | 1139 | /* Avoid the costly divide in the normal |
@@ -1140,11 +1141,10 @@ static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, | |||
1140 | */ | 1141 | */ |
1141 | skb_shinfo(skb)->gso_segs = 1; | 1142 | skb_shinfo(skb)->gso_segs = 1; |
1142 | skb_shinfo(skb)->gso_size = 0; | 1143 | skb_shinfo(skb)->gso_size = 0; |
1143 | skb_shinfo(skb)->gso_type = 0; | ||
1144 | } else { | 1144 | } else { |
1145 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss_now); | 1145 | skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss_now); |
1146 | skb_shinfo(skb)->gso_size = mss_now; | 1146 | skb_shinfo(skb)->gso_size = mss_now; |
1147 | skb_shinfo(skb)->gso_type = sk->sk_gso_type; | 1147 | skb_shinfo(skb)->gso_type |= sk->sk_gso_type; |
1148 | } | 1148 | } |
1149 | } | 1149 | } |
1150 | 1150 | ||
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index f26f0da7f095..d141fc32a2ea 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -100,6 +100,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
100 | SKB_GSO_DODGY | | 100 | SKB_GSO_DODGY | |
101 | SKB_GSO_TCP_ECN | | 101 | SKB_GSO_TCP_ECN | |
102 | SKB_GSO_TCPV6 | | 102 | SKB_GSO_TCPV6 | |
103 | SKB_GSO_SHARED_FRAG | | ||
103 | 0))) | 104 | 0))) |
104 | goto out; | 105 | goto out; |
105 | 106 | ||