aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/tcp_input.c63
1 files changed, 39 insertions, 24 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 125b4517f368..03f5ede87224 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2461,6 +2461,44 @@ static int tcp_time_to_recover(struct sock *sk)
2461 return 0; 2461 return 0;
2462} 2462}
2463 2463
2464/* New heuristics: it is possible only after we switched to restart timer
2465 * each time when something is ACKed. Hence, we can detect timed out packets
2466 * during fast retransmit without falling to slow start.
2467 *
2468 * Usefulness of this as is very questionable, since we should know which of
2469 * the segments is the next to timeout which is relatively expensive to find
2470 * in general case unless we add some data structure just for that. The
2471 * current approach certainly won't find the right one too often and when it
2472 * finally does find _something_ it usually marks large part of the window
2473 * right away (because a retransmission with a larger timestamp blocks the
2474 * loop from advancing). -ij
2475 */
2476static void tcp_timeout_skbs(struct sock *sk)
2477{
2478 struct tcp_sock *tp = tcp_sk(sk);
2479 struct sk_buff *skb;
2480
2481 if (!tcp_is_fack(tp) || !tcp_head_timedout(sk))
2482 return;
2483
2484 skb = tp->scoreboard_skb_hint;
2485 if (tp->scoreboard_skb_hint == NULL)
2486 skb = tcp_write_queue_head(sk);
2487
2488 tcp_for_write_queue_from(skb, sk) {
2489 if (skb == tcp_send_head(sk))
2490 break;
2491 if (!tcp_skb_timedout(sk, skb))
2492 break;
2493
2494 tcp_skb_mark_lost(tp, skb);
2495 }
2496
2497 tp->scoreboard_skb_hint = skb;
2498
2499 tcp_verify_left_out(tp);
2500}
2501
2464/* Mark head of queue up as lost. With RFC3517 SACK, the packets is 2502/* Mark head of queue up as lost. With RFC3517 SACK, the packets is
2465 * is against sacked "cnt", otherwise it's against facked "cnt" 2503 * is against sacked "cnt", otherwise it's against facked "cnt"
2466 */ 2504 */
@@ -2533,30 +2571,7 @@ static void tcp_update_scoreboard(struct sock *sk, int fast_rexmit)
2533 tcp_mark_head_lost(sk, sacked_upto); 2571 tcp_mark_head_lost(sk, sacked_upto);
2534 } 2572 }
2535 2573
2536 /* New heuristics: it is possible only after we switched 2574 tcp_timeout_skbs(sk);
2537 * to restart timer each time when something is ACKed.
2538 * Hence, we can detect timed out packets during fast
2539 * retransmit without falling to slow start.
2540 */
2541 if (tcp_is_fack(tp) && tcp_head_timedout(sk)) {
2542 struct sk_buff *skb;
2543
2544 skb = tp->scoreboard_skb_hint ? tp->scoreboard_skb_hint
2545 : tcp_write_queue_head(sk);
2546
2547 tcp_for_write_queue_from(skb, sk) {
2548 if (skb == tcp_send_head(sk))
2549 break;
2550 if (!tcp_skb_timedout(sk, skb))
2551 break;
2552
2553 tcp_skb_mark_lost(tp, skb);
2554 }
2555
2556 tp->scoreboard_skb_hint = skb;
2557
2558 tcp_verify_left_out(tp);
2559 }
2560} 2575}
2561 2576
2562/* CWND moderation, preventing bursts due to too big ACKs 2577/* CWND moderation, preventing bursts due to too big ACKs