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.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index e22e6d88bac6..f757e3b7cfbf 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -880,22 +880,25 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
880 nlen = skb_network_header_len(skb); 880 nlen = skb_network_header_len(skb);
881 881
882 for (p = *head; p; p = p->next) { 882 for (p = *head; p; p = p->next) {
883 struct ipv6hdr *iph2; 883 const struct ipv6hdr *iph2;
884 __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
884 885
885 if (!NAPI_GRO_CB(p)->same_flow) 886 if (!NAPI_GRO_CB(p)->same_flow)
886 continue; 887 continue;
887 888
888 iph2 = ipv6_hdr(p); 889 iph2 = ipv6_hdr(p);
890 first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
889 891
890 /* All fields must match except length. */ 892 /* All fields must match except length and Traffic Class. */
891 if (nlen != skb_network_header_len(p) || 893 if (nlen != skb_network_header_len(p) ||
892 memcmp(iph, iph2, offsetof(struct ipv6hdr, payload_len)) || 894 (first_word & htonl(0xF00FFFFF)) ||
893 memcmp(&iph->nexthdr, &iph2->nexthdr, 895 memcmp(&iph->nexthdr, &iph2->nexthdr,
894 nlen - offsetof(struct ipv6hdr, nexthdr))) { 896 nlen - offsetof(struct ipv6hdr, nexthdr))) {
895 NAPI_GRO_CB(p)->same_flow = 0; 897 NAPI_GRO_CB(p)->same_flow = 0;
896 continue; 898 continue;
897 } 899 }
898 900 /* flush if Traffic Class fields are different */
901 NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
899 NAPI_GRO_CB(p)->flush |= flush; 902 NAPI_GRO_CB(p)->flush |= flush;
900 } 903 }
901 904