diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r-- | net/ipv4/tcp_input.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 723cee63791f..a283fc12186e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -1239,14 +1239,31 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1239 | /* F-RTO can only be used if these conditions are satisfied: | 1239 | /* F-RTO can only be used if these conditions are satisfied: |
1240 | * - there must be some unsent new data | 1240 | * - there must be some unsent new data |
1241 | * - the advertised window should allow sending it | 1241 | * - the advertised window should allow sending it |
1242 | * - TCP has never retransmitted anything other than head | ||
1242 | */ | 1243 | */ |
1243 | int tcp_use_frto(const struct sock *sk) | 1244 | int tcp_use_frto(struct sock *sk) |
1244 | { | 1245 | { |
1245 | const struct tcp_sock *tp = tcp_sk(sk); | 1246 | const struct tcp_sock *tp = tcp_sk(sk); |
1247 | struct sk_buff *skb; | ||
1248 | |||
1249 | if (!sysctl_tcp_frto || !sk->sk_send_head || | ||
1250 | after(TCP_SKB_CB(sk->sk_send_head)->end_seq, | ||
1251 | tp->snd_una + tp->snd_wnd)) | ||
1252 | return 0; | ||
1246 | 1253 | ||
1247 | return (sysctl_tcp_frto && sk->sk_send_head && | 1254 | /* Avoid expensive walking of rexmit queue if possible */ |
1248 | !after(TCP_SKB_CB(sk->sk_send_head)->end_seq, | 1255 | if (tp->retrans_out > 1) |
1249 | tp->snd_una + tp->snd_wnd)); | 1256 | return 0; |
1257 | |||
1258 | skb = skb_peek(&sk->sk_write_queue)->next; /* Skips head */ | ||
1259 | sk_stream_for_retrans_queue_from(skb, sk) { | ||
1260 | if (TCP_SKB_CB(skb)->sacked&TCPCB_RETRANS) | ||
1261 | return 0; | ||
1262 | /* Short-circuit when first non-SACKed skb has been checked */ | ||
1263 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED)) | ||
1264 | break; | ||
1265 | } | ||
1266 | return 1; | ||
1250 | } | 1267 | } |
1251 | 1268 | ||
1252 | /* RTO occurred, but do not yet enter Loss state. Instead, defer RTO | 1269 | /* RTO occurred, but do not yet enter Loss state. Instead, defer RTO |