aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-01-29 09:19:50 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-29 19:33:03 -0500
commit86911732d3996a9da07914b280621450111bb6da (patch)
treee787240d5ba869ddf4d0adfc3f9c69e0372e96ef /net/ipv4/tcp.c
parent5d0d9be8ef456afc6c3fb5f8aad06ef19b704b05 (diff)
gro: Avoid copying headers of unmerged packets
Unfortunately simplicity isn't always the best. The fraginfo interface turned out to be suboptimal. The problem was quite obvious. For every packet, we have to copy the headers from the frags structure into skb->head, even though for 99% of the packets this part is immediately thrown away after the merge. LRO didn't have this problem because it directly read the headers from the frags structure. This patch attempts to address this by creating an interface that allows GRO to access the headers in the first frag without having to copy it. Because all drivers that use frags place the headers in the first frag this optimisation should be enough. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 0cd71b84e483..1cd608253940 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2481,19 +2481,19 @@ struct sk_buff **tcp_gro_receive(struct sk_buff **head, struct sk_buff *skb)
2481 unsigned int mss = 1; 2481 unsigned int mss = 1;
2482 int flush = 1; 2482 int flush = 1;
2483 2483
2484 if (!pskb_may_pull(skb, sizeof(*th))) 2484 th = skb_gro_header(skb, sizeof(*th));
2485 if (unlikely(!th))
2485 goto out; 2486 goto out;
2486 2487
2487 th = tcp_hdr(skb);
2488 thlen = th->doff * 4; 2488 thlen = th->doff * 4;
2489 if (thlen < sizeof(*th)) 2489 if (thlen < sizeof(*th))
2490 goto out; 2490 goto out;
2491 2491
2492 if (!pskb_may_pull(skb, thlen)) 2492 th = skb_gro_header(skb, thlen);
2493 if (unlikely(!th))
2493 goto out; 2494 goto out;
2494 2495
2495 th = tcp_hdr(skb); 2496 skb_gro_pull(skb, thlen);
2496 __skb_pull(skb, thlen);
2497 2497
2498 flags = tcp_flag_word(th); 2498 flags = tcp_flag_word(th);
2499 2499
@@ -2521,10 +2521,10 @@ found:
2521 flush |= th->ack_seq != th2->ack_seq || th->window != th2->window; 2521 flush |= th->ack_seq != th2->ack_seq || th->window != th2->window;
2522 flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th)); 2522 flush |= memcmp(th + 1, th2 + 1, thlen - sizeof(*th));
2523 2523
2524 total = p->len; 2524 total = skb_gro_len(p);
2525 mss = skb_shinfo(p)->gso_size; 2525 mss = skb_shinfo(p)->gso_size;
2526 2526
2527 flush |= skb->len > mss || skb->len <= 0; 2527 flush |= skb_gro_len(skb) > mss || !skb_gro_len(skb);
2528 flush |= ntohl(th2->seq) + total != ntohl(th->seq); 2528 flush |= ntohl(th2->seq) + total != ntohl(th->seq);
2529 2529
2530 if (flush || skb_gro_receive(head, skb)) { 2530 if (flush || skb_gro_receive(head, skb)) {
@@ -2537,7 +2537,7 @@ found:
2537 tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH); 2537 tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH);
2538 2538
2539out_check_final: 2539out_check_final:
2540 flush = skb->len < mss; 2540 flush = skb_gro_len(skb) < mss;
2541 flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST | 2541 flush |= flags & (TCP_FLAG_URG | TCP_FLAG_PSH | TCP_FLAG_RST |
2542 TCP_FLAG_SYN | TCP_FLAG_FIN); 2542 TCP_FLAG_SYN | TCP_FLAG_FIN);
2543 2543