aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-11-10 19:53:30 -0500
committerDavid S. Miller <davem@davemloft.net>2005-11-10 19:53:30 -0500
commitf4805eded7d38c4e42bf473dc5eb2f34853beb06 (patch)
tree1f7e0e90642e775b4e8c2c47d84e2df8ce2de3c3
parent6e6ece5dc6022e8086c565498d23511bbceda811 (diff)
[TCP]: fix congestion window update when using TSO deferal
TCP peformance with TSO over networks with delay is awful. On a 100Mbit link with 150ms delay, we get 4Mbits/sec with TSO and 50Mbits/sec without TSO. The problem is with TSO, we intentionally do not keep the maximum number of packets in flight to fill the window, we hold out to until we can send a MSS chunk. But, we also don't update the congestion window unless we have filled, as per RFC2861. This patch replaces the check for the congestion window being full with something smarter that accounts for TSO. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/tcp.h21
-rw-r--r--net/ipv4/tcp_bic.c2
-rw-r--r--net/ipv4/tcp_cong.c2
-rw-r--r--net/ipv4/tcp_highspeed.c4
-rw-r--r--net/ipv4/tcp_htcp.c2
-rw-r--r--net/ipv4/tcp_hybla.c6
-rw-r--r--net/ipv4/tcp_output.c1
-rw-r--r--net/ipv4/tcp_scalable.c3
8 files changed, 32 insertions, 9 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 96cc3b434e40..15bdbc6bd571 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -810,6 +810,27 @@ static __inline__ __u32 tcp_max_burst(const struct tcp_sock *tp)
810 return 3; 810 return 3;
811} 811}
812 812
813/* RFC2861 Check whether we are limited by application or congestion window
814 * This is the inverse of cwnd check in tcp_tso_should_defer
815 */
816static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight)
817{
818 const struct tcp_sock *tp = tcp_sk(sk);
819 u32 left;
820
821 if (in_flight >= tp->snd_cwnd)
822 return 1;
823
824 if (!(sk->sk_route_caps & NETIF_F_TSO))
825 return 0;
826
827 left = tp->snd_cwnd - in_flight;
828 if (sysctl_tcp_tso_win_divisor)
829 return left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd;
830 else
831 return left <= tcp_max_burst(tp);
832}
833
813static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss, 834static __inline__ void tcp_minshall_update(struct tcp_sock *tp, int mss,
814 const struct sk_buff *skb) 835 const struct sk_buff *skb)
815{ 836{
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c
index ae35e0609047..5af99b3ef5d7 100644
--- a/net/ipv4/tcp_bic.c
+++ b/net/ipv4/tcp_bic.c
@@ -217,7 +217,7 @@ static void bictcp_cong_avoid(struct sock *sk, u32 ack,
217 217
218 bictcp_low_utilization(sk, data_acked); 218 bictcp_low_utilization(sk, data_acked);
219 219
220 if (in_flight < tp->snd_cwnd) 220 if (!tcp_is_cwnd_limited(sk, in_flight))
221 return; 221 return;
222 222
223 if (tp->snd_cwnd <= tp->snd_ssthresh) { 223 if (tp->snd_cwnd <= tp->snd_ssthresh) {
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c
index bbf2d6624e89..0705b496c6b3 100644
--- a/net/ipv4/tcp_cong.c
+++ b/net/ipv4/tcp_cong.c
@@ -186,7 +186,7 @@ void tcp_reno_cong_avoid(struct sock *sk, u32 ack, u32 rtt, u32 in_flight,
186{ 186{
187 struct tcp_sock *tp = tcp_sk(sk); 187 struct tcp_sock *tp = tcp_sk(sk);
188 188
189 if (in_flight < tp->snd_cwnd) 189 if (!tcp_is_cwnd_limited(sk, in_flight))
190 return; 190 return;
191 191
192 if (tp->snd_cwnd <= tp->snd_ssthresh) { 192 if (tp->snd_cwnd <= tp->snd_ssthresh) {
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c
index 6acc04bde080..5e56ad368dd2 100644
--- a/net/ipv4/tcp_highspeed.c
+++ b/net/ipv4/tcp_highspeed.c
@@ -111,12 +111,12 @@ static void hstcp_init(struct sock *sk)
111} 111}
112 112
113static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, 113static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt,
114 u32 in_flight, int good) 114 u32 in_flight, u32 pkts_acked)
115{ 115{
116 struct tcp_sock *tp = tcp_sk(sk); 116 struct tcp_sock *tp = tcp_sk(sk);
117 struct hstcp *ca = inet_csk_ca(sk); 117 struct hstcp *ca = inet_csk_ca(sk);
118 118
119 if (in_flight < tp->snd_cwnd) 119 if (!tcp_is_cwnd_limited(sk, in_flight))
120 return; 120 return;
121 121
122 if (tp->snd_cwnd <= tp->snd_ssthresh) { 122 if (tp->snd_cwnd <= tp->snd_ssthresh) {
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c
index e47b37984e95..404a326ba345 100644
--- a/net/ipv4/tcp_htcp.c
+++ b/net/ipv4/tcp_htcp.c
@@ -207,7 +207,7 @@ static void htcp_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
207 struct tcp_sock *tp = tcp_sk(sk); 207 struct tcp_sock *tp = tcp_sk(sk);
208 struct htcp *ca = inet_csk_ca(sk); 208 struct htcp *ca = inet_csk_ca(sk);
209 209
210 if (in_flight < tp->snd_cwnd) 210 if (!tcp_is_cwnd_limited(sk, in_flight))
211 return; 211 return;
212 212
213 if (tp->snd_cwnd <= tp->snd_ssthresh) { 213 if (tp->snd_cwnd <= tp->snd_ssthresh) {
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c
index 77add63623df..40dbb3877510 100644
--- a/net/ipv4/tcp_hybla.c
+++ b/net/ipv4/tcp_hybla.c
@@ -100,12 +100,12 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
100 ca->minrtt = tp->srtt; 100 ca->minrtt = tp->srtt;
101 } 101 }
102 102
103 if (!tcp_is_cwnd_limited(sk, in_flight))
104 return;
105
103 if (!ca->hybla_en) 106 if (!ca->hybla_en)
104 return tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag); 107 return tcp_reno_cong_avoid(sk, ack, rtt, in_flight, flag);
105 108
106 if (in_flight < tp->snd_cwnd)
107 return;
108
109 if (ca->rho == 0) 109 if (ca->rho == 0)
110 hybla_recalc_param(sk); 110 hybla_recalc_param(sk);
111 111
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index b907456a79f4..998f6416ef8b 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2058,3 +2058,4 @@ EXPORT_SYMBOL(tcp_connect);
2058EXPORT_SYMBOL(tcp_make_synack); 2058EXPORT_SYMBOL(tcp_make_synack);
2059EXPORT_SYMBOL(tcp_simple_retransmit); 2059EXPORT_SYMBOL(tcp_simple_retransmit);
2060EXPORT_SYMBOL(tcp_sync_mss); 2060EXPORT_SYMBOL(tcp_sync_mss);
2061EXPORT_SYMBOL(sysctl_tcp_tso_win_divisor);
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c
index 327770bf5522..a2fd25617d24 100644
--- a/net/ipv4/tcp_scalable.c
+++ b/net/ipv4/tcp_scalable.c
@@ -20,7 +20,8 @@ static void tcp_scalable_cong_avoid(struct sock *sk, u32 ack, u32 rtt,
20 u32 in_flight, int flag) 20 u32 in_flight, int flag)
21{ 21{
22 struct tcp_sock *tp = tcp_sk(sk); 22 struct tcp_sock *tp = tcp_sk(sk);
23 if (in_flight < tp->snd_cwnd) 23
24 if (!tcp_is_cwnd_limited(sk, in_flight))
24 return; 25 return;
25 26
26 if (tp->snd_cwnd <= tp->snd_ssthresh) { 27 if (tp->snd_cwnd <= tp->snd_ssthresh) {