gro: should aggregate frames without DF
authorEric Dumazet <edumazet@google.com>
Fri, 31 May 2013 11:18:10 +0000 (11:18 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 31 May 2013 23:25:56 +0000 (16:25 -0700)
GRO on IPv4 doesn't aggregate frames if they don't have DF bit set.

Some servers use IP_MTU_DISCOVER/IP_PMTUDISC_PROBE, so linux receivers
are unable to aggregate this kind of traffic.

The right thing to do is to allow aggregation as long as the DF bit has
same value on all segments.

bnx2x LRO does this correctly.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Jerry Chu <hkchu@google.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Ben Hutchings <bhutchings@solarflare.com>
Reviewed-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/af_inet.c

index b05ae96aec4449be3e6f69f408622b09c697ac7c..9c090c7daea1d12a1a5babbca388f4f7741948b6 100644 (file)
@@ -1385,7 +1385,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
                goto out_unlock;
 
        id = ntohl(*(__be32 *)&iph->id);
-       flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id IP_DF));
+       flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id & ~IP_DF));
        id >>= 16;
 
        for (p = *head; p; p = p->next) {
@@ -1407,6 +1407,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
                NAPI_GRO_CB(p)->flush |=
                        (iph->ttl ^ iph2->ttl) |
                        (iph->tos ^ iph2->tos) |
+                       ((iph->frag_off ^ iph2->frag_off) & htons(IP_DF)) |
                        ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id);
 
                NAPI_GRO_CB(p)->flush |= flush;