diff options
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r-- | net/ipv6/af_inet6.c | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index c802bc1658a8..bd91eadcbe3f 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -799,24 +799,34 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
799 | int proto; | 799 | int proto; |
800 | __wsum csum; | 800 | __wsum csum; |
801 | 801 | ||
802 | if (unlikely(!pskb_may_pull(skb, sizeof(*iph)))) | 802 | iph = skb_gro_header(skb, sizeof(*iph)); |
803 | if (unlikely(!iph)) | ||
803 | goto out; | 804 | goto out; |
804 | 805 | ||
805 | iph = ipv6_hdr(skb); | 806 | skb_gro_pull(skb, sizeof(*iph)); |
806 | __skb_pull(skb, sizeof(*iph)); | 807 | skb_set_transport_header(skb, skb_gro_offset(skb)); |
807 | 808 | ||
808 | flush += ntohs(iph->payload_len) != skb->len; | 809 | flush += ntohs(iph->payload_len) != skb_gro_len(skb); |
809 | 810 | ||
810 | rcu_read_lock(); | 811 | rcu_read_lock(); |
811 | proto = ipv6_gso_pull_exthdrs(skb, iph->nexthdr); | 812 | proto = iph->nexthdr; |
812 | iph = ipv6_hdr(skb); | ||
813 | IPV6_GRO_CB(skb)->proto = proto; | ||
814 | ops = rcu_dereference(inet6_protos[proto]); | 813 | ops = rcu_dereference(inet6_protos[proto]); |
815 | if (!ops || !ops->gro_receive) | 814 | if (!ops || !ops->gro_receive) { |
816 | goto out_unlock; | 815 | __pskb_pull(skb, skb_gro_offset(skb)); |
816 | proto = ipv6_gso_pull_exthdrs(skb, proto); | ||
817 | skb_gro_pull(skb, -skb_transport_offset(skb)); | ||
818 | skb_reset_transport_header(skb); | ||
819 | __skb_push(skb, skb_gro_offset(skb)); | ||
820 | |||
821 | if (!ops || !ops->gro_receive) | ||
822 | goto out_unlock; | ||
823 | |||
824 | iph = ipv6_hdr(skb); | ||
825 | } | ||
826 | |||
827 | IPV6_GRO_CB(skb)->proto = proto; | ||
817 | 828 | ||
818 | flush--; | 829 | flush--; |
819 | skb_reset_transport_header(skb); | ||
820 | nlen = skb_network_header_len(skb); | 830 | nlen = skb_network_header_len(skb); |
821 | 831 | ||
822 | for (p = *head; p; p = p->next) { | 832 | for (p = *head; p; p = p->next) { |