aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h5
-rw-r--r--net/ipv4/tcp_input.c13
-rw-r--r--net/ipv4/tcp_output.c6
3 files changed, 17 insertions, 7 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index c6ecd455edab..ef8f9d4dae85 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1199,9 +1199,14 @@ static inline struct sk_buff *tcp_send_head(struct sock *sk)
1199 1199
1200static inline void tcp_advance_send_head(struct sock *sk, struct sk_buff *skb) 1200static inline void tcp_advance_send_head(struct sock *sk, struct sk_buff *skb)
1201{ 1201{
1202 struct tcp_sock *tp = tcp_sk(sk);
1203
1202 sk->sk_send_head = skb->next; 1204 sk->sk_send_head = skb->next;
1203 if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue) 1205 if (sk->sk_send_head == (struct sk_buff *)&sk->sk_write_queue)
1204 sk->sk_send_head = NULL; 1206 sk->sk_send_head = NULL;
1207 /* Don't override Nagle indefinately with F-RTO */
1208 if (tp->frto_counter == 2)
1209 tp->frto_counter = 3;
1205} 1210}
1206 1211
1207static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unlinked) 1212static inline void tcp_check_send_head(struct sock *sk, struct sk_buff *skb_unlinked)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 6b669898b197..7641b2761a14 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2637,7 +2637,9 @@ static void tcp_undo_spur_to_response(struct sock *sk, int flag)
2637 * algorithm is not part of the F-RTO detection algorithm 2637 * algorithm is not part of the F-RTO detection algorithm
2638 * given in RFC4138 but can be selected separately). 2638 * given in RFC4138 but can be selected separately).
2639 * 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
2640 * 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.
2641 * 2643 *
2642 * 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
2643 * original window even after we transmit two new data segments. 2645 * original window even after we transmit two new data segments.
@@ -2666,7 +2668,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag)
2666 inet_csk(sk)->icsk_retransmits = 0; 2668 inet_csk(sk)->icsk_retransmits = 0;
2667 2669
2668 if (!before(tp->snd_una, tp->frto_highmark)) { 2670 if (!before(tp->snd_una, tp->frto_highmark)) {
2669 tcp_enter_frto_loss(sk, tp->frto_counter + 1, flag); 2671 tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3), flag);
2670 return 1; 2672 return 1;
2671 } 2673 }
2672 2674
@@ -2692,7 +2694,7 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag)
2692 return 1; 2694 return 1;
2693 } 2695 }
2694 2696
2695 if ((tp->frto_counter == 2) && 2697 if ((tp->frto_counter >= 2) &&
2696 (!(flag&FLAG_FORWARD_PROGRESS) || 2698 (!(flag&FLAG_FORWARD_PROGRESS) ||
2697 ((flag&FLAG_DATA_SACKED) && !(flag&FLAG_ONLY_ORIG_SACKED)))) { 2699 ((flag&FLAG_DATA_SACKED) && !(flag&FLAG_ONLY_ORIG_SACKED)))) {
2698 /* RFC4138 shortcoming (see comment above) */ 2700 /* RFC4138 shortcoming (see comment above) */
@@ -2709,14 +2711,15 @@ static int tcp_process_frto(struct sock *sk, u32 prior_snd_una, int flag)
2709 if (!tcp_send_head(sk) || 2711 if (!tcp_send_head(sk) ||
2710 after(TCP_SKB_CB(tcp_send_head(sk))->end_seq, 2712 after(TCP_SKB_CB(tcp_send_head(sk))->end_seq,
2711 tp->snd_una + tp->snd_wnd)) { 2713 tp->snd_una + tp->snd_wnd)) {
2712 tcp_enter_frto_loss(sk, tp->frto_counter + 1, flag); 2714 tcp_enter_frto_loss(sk, (tp->frto_counter == 1 ? 2 : 3),
2715 flag);
2713 return 1; 2716 return 1;
2714 } 2717 }
2715 2718
2716 tp->snd_cwnd = tcp_packets_in_flight(tp) + 2; 2719 tp->snd_cwnd = tcp_packets_in_flight(tp) + 2;
2717 tp->frto_counter = 2; 2720 tp->frto_counter = 2;
2718 return 1; 2721 return 1;
2719 } else /* frto_counter == 2 */ { 2722 } else {
2720 switch (sysctl_tcp_frto_response) { 2723 switch (sysctl_tcp_frto_response) {
2721 case 2: 2724 case 2:
2722 tcp_undo_spur_to_response(sk, flag); 2725 tcp_undo_spur_to_response(sk, flag);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b5fa3c19afee..0faacf9c419d 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1035,8 +1035,10 @@ static inline int tcp_nagle_test(struct tcp_sock *tp, struct sk_buff *skb,
1035 if (nonagle & TCP_NAGLE_PUSH) 1035 if (nonagle & TCP_NAGLE_PUSH)
1036 return 1; 1036 return 1;
1037 1037
1038 /* Don't use the nagle rule for urgent data (or for the final FIN). */ 1038 /* Don't use the nagle rule for urgent data (or for the final FIN).
1039 if (tp->urg_mode || 1039 * Nagle can be ignored during F-RTO too (see RFC4138).
1040 */
1041 if (tp->urg_mode || (tp->frto_counter == 2) ||
1040 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN)) 1042 (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN))
1041 return 1; 1043 return 1;
1042 1044