aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2009-05-29 18:02:29 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-29 18:02:29 -0400
commit2df9001edc382c331f338f45d259feeaa740c418 (patch)
treeeb92c3ef77973295469743a1087c551acf7ece67 /net/ipv4
parent5d4e039b2cb1ca4de9774344ea7b61ad7fa1b0a1 (diff)
tcp: fix loop in ofo handling code and reduce its complexity
Somewhat luckily, I was looking into these parts with very fine comb because I've made somewhat similar changes on the same area (conflicts that arose weren't that lucky though). The loop was very much overengineered recently in commit 915219441d566 (tcp: Use SKB queue and list helpers instead of doing it by-hand), while it basically just wants to know if there are skbs after 'skb'. Also it got broken because skb1 = skb->next got translated into skb1 = skb1->next (though abstracted) improperly. Note that 'skb1' is pointing to previous sk_buff than skb or NULL if at head. Two things went wrong: - We'll kfree 'skb' on the first iteration instead of the skbuff following 'skb' (it would require required SACK reneging to recover I think). - The list head case where 'skb1' is NULL is checked too early and the loop won't execute whereas it previously did. Conclusion, mostly revert the recent changes which makes the cset very messy looking but using proper accessor in the previous-like version. The effective changes against the original can be viewed with: git-diff 915219441d566f1da0caa0e262be49b666159e17^ \ net/ipv4/tcp_input.c | sed -n -e '57,70 p' Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/tcp_input.c28
1 files changed, 11 insertions, 17 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ba34a23c1bfb..2bdb0da237e6 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4481,26 +4481,20 @@ drop:
4481 __skb_queue_after(&tp->out_of_order_queue, skb1, skb); 4481 __skb_queue_after(&tp->out_of_order_queue, skb1, skb);
4482 4482
4483 /* And clean segments covered by new one as whole. */ 4483 /* And clean segments covered by new one as whole. */
4484 if (skb1 && !skb_queue_is_last(&tp->out_of_order_queue, skb1)) { 4484 while (!skb_queue_is_last(&tp->out_of_order_queue, skb)) {
4485 struct sk_buff *n; 4485 skb1 = skb_queue_next(&tp->out_of_order_queue, skb);
4486 4486
4487 skb1 = skb_queue_next(&tp->out_of_order_queue, skb1); 4487 if (!after(end_seq, TCP_SKB_CB(skb1)->seq))
4488 skb_queue_walk_from_safe(&tp->out_of_order_queue, 4488 break;
4489 skb1, n) { 4489 if (before(end_seq, TCP_SKB_CB(skb1)->end_seq)) {
4490 if (!after(end_seq, TCP_SKB_CB(skb1)->seq))
4491 break;
4492 if (before(end_seq,
4493 TCP_SKB_CB(skb1)->end_seq)) {
4494 tcp_dsack_extend(sk,
4495 TCP_SKB_CB(skb1)->seq,
4496 end_seq);
4497 break;
4498 }
4499 __skb_unlink(skb1, &tp->out_of_order_queue);
4500 tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq, 4490 tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq,
4501 TCP_SKB_CB(skb1)->end_seq); 4491 end_seq);
4502 __kfree_skb(skb1); 4492 break;
4503 } 4493 }
4494 __skb_unlink(skb1, &tp->out_of_order_queue);
4495 tcp_dsack_extend(sk, TCP_SKB_CB(skb1)->seq,
4496 TCP_SKB_CB(skb1)->end_seq);
4497 __kfree_skb(skb1);
4504 } 4498 }
4505 4499
4506add_sack: 4500add_sack: