diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r-- | net/ipv4/tcp_output.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 20847de991ea..f9181a133462 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1402,12 +1402,13 @@ static void tcp_cwnd_application_limited(struct sock *sk) | |||
1402 | tp->snd_cwnd_stamp = tcp_time_stamp; | 1402 | tp->snd_cwnd_stamp = tcp_time_stamp; |
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | /* Congestion window validation. (RFC2861) */ | 1405 | static void tcp_cwnd_validate(struct sock *sk, u32 unsent_segs) |
1406 | static void tcp_cwnd_validate(struct sock *sk) | ||
1407 | { | 1406 | { |
1408 | struct tcp_sock *tp = tcp_sk(sk); | 1407 | struct tcp_sock *tp = tcp_sk(sk); |
1409 | 1408 | ||
1410 | if (tp->packets_out >= tp->snd_cwnd) { | 1409 | tp->lsnd_pending = tp->packets_out + unsent_segs; |
1410 | |||
1411 | if (tcp_is_cwnd_limited(sk, 0)) { | ||
1411 | /* Network is feed fully. */ | 1412 | /* Network is feed fully. */ |
1412 | tp->snd_cwnd_used = 0; | 1413 | tp->snd_cwnd_used = 0; |
1413 | tp->snd_cwnd_stamp = tcp_time_stamp; | 1414 | tp->snd_cwnd_stamp = tcp_time_stamp; |
@@ -1880,7 +1881,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1880 | { | 1881 | { |
1881 | struct tcp_sock *tp = tcp_sk(sk); | 1882 | struct tcp_sock *tp = tcp_sk(sk); |
1882 | struct sk_buff *skb; | 1883 | struct sk_buff *skb; |
1883 | unsigned int tso_segs, sent_pkts; | 1884 | unsigned int tso_segs, sent_pkts, unsent_segs = 0; |
1884 | int cwnd_quota; | 1885 | int cwnd_quota; |
1885 | int result; | 1886 | int result; |
1886 | 1887 | ||
@@ -1924,7 +1925,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1924 | break; | 1925 | break; |
1925 | } else { | 1926 | } else { |
1926 | if (!push_one && tcp_tso_should_defer(sk, skb)) | 1927 | if (!push_one && tcp_tso_should_defer(sk, skb)) |
1927 | break; | 1928 | goto compute_unsent_segs; |
1928 | } | 1929 | } |
1929 | 1930 | ||
1930 | /* TCP Small Queues : | 1931 | /* TCP Small Queues : |
@@ -1949,8 +1950,14 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1949 | * there is no smp_mb__after_set_bit() yet | 1950 | * there is no smp_mb__after_set_bit() yet |
1950 | */ | 1951 | */ |
1951 | smp_mb__after_clear_bit(); | 1952 | smp_mb__after_clear_bit(); |
1952 | if (atomic_read(&sk->sk_wmem_alloc) > limit) | 1953 | if (atomic_read(&sk->sk_wmem_alloc) > limit) { |
1954 | u32 unsent_bytes; | ||
1955 | |||
1956 | compute_unsent_segs: | ||
1957 | unsent_bytes = tp->write_seq - tp->snd_nxt; | ||
1958 | unsent_segs = DIV_ROUND_UP(unsent_bytes, mss_now); | ||
1953 | break; | 1959 | break; |
1960 | } | ||
1954 | } | 1961 | } |
1955 | 1962 | ||
1956 | limit = mss_now; | 1963 | limit = mss_now; |
@@ -1990,7 +1997,7 @@ repair: | |||
1990 | /* Send one loss probe per tail loss episode. */ | 1997 | /* Send one loss probe per tail loss episode. */ |
1991 | if (push_one != 2) | 1998 | if (push_one != 2) |
1992 | tcp_schedule_loss_probe(sk); | 1999 | tcp_schedule_loss_probe(sk); |
1993 | tcp_cwnd_validate(sk); | 2000 | tcp_cwnd_validate(sk, unsent_segs); |
1994 | return false; | 2001 | return false; |
1995 | } | 2002 | } |
1996 | return (push_one == 2) || (!tp->packets_out && tcp_send_head(sk)); | 2003 | return (push_one == 2) || (!tp->packets_out && tcp_send_head(sk)); |