aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 051f0f815f17..7641b2761a14 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1265,20 +1265,15 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_
1265 return flag; 1265 return flag;
1266} 1266}
1267 1267
1268/* F-RTO can only be used if these conditions are satisfied: 1268/* F-RTO can only be used if TCP has never retransmitted anything other than
1269 * - there must be some unsent new data 1269 * head (SACK enhanced variant from Appendix B of RFC4138 is more robust here)
1270 * - the advertised window should allow sending it
1271 * - TCP has never retransmitted anything other than head (SACK enhanced
1272 * variant from Appendix B of RFC4138 is more robust here)
1273 */ 1270 */
1274int tcp_use_frto(struct sock *sk) 1271int tcp_use_frto(struct sock *sk)
1275{ 1272{
1276 const struct tcp_sock *tp = tcp_sk(sk); 1273 const struct tcp_sock *tp = tcp_sk(sk);
1277 struct sk_buff *skb; 1274 struct sk_buff *skb;
1278 1275
1279 if (!sysctl_tcp_frto || !tcp_send_head(sk) || 1276 if (!sysctl_tcp_frto)
1280 after(TCP_SKB_CB(tcp_send_head(sk))->end_seq,
1281 tp->snd_una + tp->snd_wnd))
1282 return 0; 1277 return 0;
1283 1278
1284 if (IsSackFrto()) 1279 if (IsSackFrto())
@@ -2642,7 +2637,9 @@ static void tcp_undo_spur_to_response(struct sock *sk, int flag)
2642 * algorithm is not part of the F-RTO detection algorithm 2637 * algorithm is not part of the F-RTO detection algorithm
2643 * given in RFC4138 but can be selected separately). 2638 * given in RFC4138 but can be selected separately).
2644 * Otherwise (basically on duplicate ACK), RTO was (likely) caused by a loss 2639 * Otherwise (basically on duplicate ACK), RTO was (likely) caused by a loss
2645 * and TCP falls back to conventional RTO recovery. 2640 * and TCP falls back to conventional RTO recovery. F-RTO allows overriding
2641 * of Nagle, this is done using frto_counter states 2 and 3, when a new data
2642 * segment of any size sent during F-RTO, state 2 is upgraded to 3.
2646 * 2643 *
2647 * Rationale: if the RTO was spurious, new ACKs should arrive from the 2644 * Rationale: if the RTO was spurious, new ACKs should arrive from the
2648 * original window even after we transmit two new data segments. 2645 * original window even after we transmit two new data segments.
@@ -2671,7 +2668,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag)
2671 inet_csk(sk)->icsk_retransmits = 0; 2668 inet_csk(sk)->icsk_retransmits = 0;
2672 2669
2673 if (!before(tp->snd_una, tp->frto_highmark)) { 2670 if (!before(tp->snd_una, tp->frto_highmark)) {
2674 tcp_enter_frto_loss(sk, tp->frto_counter + 1, flag); 2671 tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag);
2675 return 1; 2672 return 1;
2676 } 2673 }
2677 2674
@@ -2697,7 +2694,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag)
2697 return 1; 2694 return 1;
2698 } 2695 }
2699 2696
2700 if ((tp->frto_counter == 2) && 2697 if ((tp->frto_counter >= 2) &&
2701 (!(flag&FLAG_FORWARD_PROGRESS) || 2698 (!(flag&FLAG_FORWARD_PROGRESS) ||
2702 ((flag&FLAG_DATA_SACKED) && !(flag&FLAG_ONLY_ORIG_SACKED)))) { 2699 ((flag&FLAG_DATA_SACKED) && !(flag&FLAG_ONLY_ORIG_SACKED)))) {
2703 /* RFC4138 shortcoming (see comment above) */ 2700 /* RFC4138 shortcoming (see comment above) */
@@ -2710,10 +2707,19 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag)
2710 } 2707 }
2711 2708
2712 if (tp->frto_counter == 1) { 2709 if (tp->frto_counter == 1) {
2710 /* Sending of the next skb must be allowed or no FRTO */
2711 if (!tcp_send_head(sk) ||
2712 after(TCP_SKB_CB(tcp_send_head(sk))->end_seq,
2713 tp->snd_una + tp->snd_wnd)) {
2714 tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3),
2715 flag);
2716 return 1;
2717 }
2718
2713 tp->snd_cwnd = tcp_packets_in_flight(tp) + 2; 2719 tp->snd_cwnd = tcp_packets_in_flight(tp) + 2;
2714 tp->frto_counter = 2; 2720 tp->frto_counter = 2;
2715 return 1; 2721 return 1;
2716 } else /* frto_counter == 2 */ { 2722 } else {
2717 switch (sysctl_tcp_frto_response) { 2723 switch (sysctl_tcp_frto_response) {
2718 case 2: 2724 case 2:
2719 tcp_undo_spur_to_response(sk, flag); 2725 tcp_undo_spur_to_response(sk, flag);