aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/af_inet6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/af_inet6.c')
-rw-r--r--net/ipv6/af_inet6.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e22e6d88bac6..a974247a9ae4 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -822,13 +822,6 @@ out:
822 return segs; 822 return segs;
823} 823}
824 824
825struct ipv6_gro_cb {
826 struct napi_gro_cb napi;
827 int proto;
828};
829
830#define IPV6_GRO_CB(skb) ((struct ipv6_gro_cb *)(skb)->cb)
831
832static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, 825static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
833 struct sk_buff *skb) 826 struct sk_buff *skb)
834{ 827{
@@ -874,28 +867,31 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
874 iph = ipv6_hdr(skb); 867 iph = ipv6_hdr(skb);
875 } 868 }
876 869
877 IPV6_GRO_CB(skb)->proto = proto; 870 NAPI_GRO_CB(skb)->proto = proto;
878 871
879 flush--; 872 flush--;
880 nlen = skb_network_header_len(skb); 873 nlen = skb_network_header_len(skb);
881 874
882 for (p = *head; p; p = p->next) { 875 for (p = *head; p; p = p->next) {
883 struct ipv6hdr *iph2; 876 const struct ipv6hdr *iph2;
877 __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
884 878
885 if (!NAPI_GRO_CB(p)->same_flow) 879 if (!NAPI_GRO_CB(p)->same_flow)
886 continue; 880 continue;
887 881
888 iph2 = ipv6_hdr(p); 882 iph2 = ipv6_hdr(p);
883 first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
889 884
890 /* All fields must match except length. */ 885 /* All fields must match except length and Traffic Class. */
891 if (nlen != skb_network_header_len(p) || 886 if (nlen != skb_network_header_len(p) ||
892 memcmp(iph, iph2, offsetof(struct ipv6hdr, payload_len)) || 887 (first_word & htonl(0xF00FFFFF)) ||
893 memcmp(&iph->nexthdr, &iph2->nexthdr, 888 memcmp(&iph->nexthdr, &iph2->nexthdr,
894 nlen - offsetof(struct ipv6hdr, nexthdr))) { 889 nlen - offsetof(struct ipv6hdr, nexthdr))) {
895 NAPI_GRO_CB(p)->same_flow = 0; 890 NAPI_GRO_CB(p)->same_flow = 0;
896 continue; 891 continue;
897 } 892 }
898 893 /* flush if Traffic Class fields are different */
894 NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
899 NAPI_GRO_CB(p)->flush |= flush; 895 NAPI_GRO_CB(p)->flush |= flush;
900 } 896 }
901 897
@@ -927,7 +923,7 @@ static int ipv6_gro_complete(struct sk_buff *skb)
927 sizeof(*iph)); 923 sizeof(*iph));
928 924
929 rcu_read_lock(); 925 rcu_read_lock();
930 ops = rcu_dereference(inet6_protos[IPV6_GRO_CB(skb)->proto]); 926 ops = rcu_dereference(inet6_protos[NAPI_GRO_CB(skb)->proto]);
931 if (WARN_ON(!ops || !ops->gro_complete)) 927 if (WARN_ON(!ops || !ops->gro_complete))
932 goto out_unlock; 928 goto out_unlock;
933 929