aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2015-03-05 16:47:48 -0500
committerDavid S. Miller <davem@davemloft.net>2015-03-06 21:50:55 -0500
commit58025e46ea2d39f1840d5b1be5edea3297cfd23f (patch)
treecf0593edf6cac7b70da9213139ae481a013381c2 /net/core
parentfeb27d155dfabcb8baabe10367f25fc2b1bcede1 (diff)
net: gro: remove obsolete code from skb_gro_receive()
Some drivers use copybreak to copy tiny frames into smaller skb, and this smaller skb might not have skb->head_frag set for various reasons. skb_gro_receive() currently doesn't allow to aggregate the smaller skb into the previous GRO packet if this GRO packet has at least 2 MSS in it. Following workload easily demonstrates the problem. netperf -t TCP_RR -H target -- -r 3000,3000 (tcpdump shows one GRO packet with 2 MSS, plus one additional packet of 104 bytes that should have been appended.) It turns out that we can remove code from skb_gro_receive(), because commit 8a29111c7ca6 ("net: gro: allow to build full sized skb") and its followups removed the assumption that a GRO packet with a frag_list had to have an empty head. Removing this code allows the aggregation of the last (incomplete) frame in some RPC workloads. Note that tcp_gro_receive() already takes care of forcing a flush if necessary, including this case. If we want to avoid using frag_list in the first place (in forwarding workloads for example, as the outgoing NIC is generally not able to cope with skbs having a frag_list), we need to address this separately. Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/skbuff.c45
1 files changed, 1 insertions, 44 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 913b94a77060..47c32413d5b9 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3206,10 +3206,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
3206 struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb); 3206 struct skb_shared_info *pinfo, *skbinfo = skb_shinfo(skb);
3207 unsigned int offset = skb_gro_offset(skb); 3207 unsigned int offset = skb_gro_offset(skb);
3208 unsigned int headlen = skb_headlen(skb); 3208 unsigned int headlen = skb_headlen(skb);
3209 struct sk_buff *nskb, *lp, *p = *head;
3210 unsigned int len = skb_gro_len(skb); 3209 unsigned int len = skb_gro_len(skb);
3210 struct sk_buff *lp, *p = *head;
3211 unsigned int delta_truesize; 3211 unsigned int delta_truesize;
3212 unsigned int headroom;
3213 3212
3214 if (unlikely(p->len + len >= 65536)) 3213 if (unlikely(p->len + len >= 65536))
3215 return -E2BIG; 3214 return -E2BIG;
@@ -3276,48 +3275,6 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
3276 NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD; 3275 NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD;
3277 goto done; 3276 goto done;
3278 } 3277 }
3279 /* switch back to head shinfo */
3280 pinfo = skb_shinfo(p);
3281
3282 if (pinfo->frag_list)
3283 goto merge;
3284 if (skb_gro_len(p) != pinfo->gso_size)
3285 return -E2BIG;
3286
3287 headroom = skb_headroom(p);
3288 nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
3289 if (unlikely(!nskb))
3290 return -ENOMEM;
3291
3292 __copy_skb_header(nskb, p);
3293 nskb->mac_len = p->mac_len;
3294
3295 skb_reserve(nskb, headroom);
3296 __skb_put(nskb, skb_gro_offset(p));
3297
3298 skb_set_mac_header(nskb, skb_mac_header(p) - p->data);
3299 skb_set_network_header(nskb, skb_network_offset(p));
3300 skb_set_transport_header(nskb, skb_transport_offset(p));
3301
3302 __skb_pull(p, skb_gro_offset(p));
3303 memcpy(skb_mac_header(nskb), skb_mac_header(p),
3304 p->data - skb_mac_header(p));
3305
3306 skb_shinfo(nskb)->frag_list = p;
3307 skb_shinfo(nskb)->gso_size = pinfo->gso_size;
3308 pinfo->gso_size = 0;
3309 __skb_header_release(p);
3310 NAPI_GRO_CB(nskb)->last = p;
3311
3312 nskb->data_len += p->len;
3313 nskb->truesize += p->truesize;
3314 nskb->len += p->len;
3315
3316 *head = nskb;
3317 nskb->next = p->next;
3318 p->next = NULL;
3319
3320 p = nskb;
3321 3278
3322merge: 3279merge:
3323 delta_truesize = skb->truesize; 3280 delta_truesize = skb->truesize;