diff options
author | Stephen Hemminger <shemminger@linux-foundation.org> | 2007-07-26 02:49:34 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-31 05:27:57 -0400 |
commit | 30cfd0baf0a0c4329fff1ef4b622919297969ec8 (patch) | |
tree | 945a72f636ced1b443d894495704237e4cb7816d | |
parent | 6a302358d87fedaf7bda12b8e909265ebf1ce674 (diff) |
[TCP]: congestion control API pass RTT in microseconds
This patch changes the API for the callback that is done after an ACK is
received. It solves a couple of issues:
* Some congestion controls want higher resolution value of RTT
(controlled by TCP_CONG_RTT_SAMPLE flag). These don't really want a ktime, but
all compute a RTT in microseconds.
* Other congestion control could use RTT at jiffies resolution.
To keep API consistent the units should be the same for both cases, just the
resolution should change.
Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_bic.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_cubic.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_htcp.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_illinois.c | 8 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 21 | ||||
-rw-r--r-- | net/ipv4/tcp_lp.c | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_vegas.c | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_vegas.h | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_veno.c | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_westwood.c | 7 | ||||
-rw-r--r-- | net/ipv4/tcp_yeah.c | 4 |
12 files changed, 39 insertions, 29 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 8b404b1ef7c8..c209361ab74a 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -660,7 +660,7 @@ struct tcp_congestion_ops { | |||
660 | /* new value of cwnd after loss (optional) */ | 660 | /* new value of cwnd after loss (optional) */ |
661 | u32 (*undo_cwnd)(struct sock *sk); | 661 | u32 (*undo_cwnd)(struct sock *sk); |
662 | /* hook for packet ack accounting (optional) */ | 662 | /* hook for packet ack accounting (optional) */ |
663 | void (*pkts_acked)(struct sock *sk, u32 num_acked, ktime_t last); | 663 | void (*pkts_acked)(struct sock *sk, u32 num_acked, s32 rtt_us); |
664 | /* get info for inet_diag (optional) */ | 664 | /* get info for inet_diag (optional) */ |
665 | void (*get_info)(struct sock *sk, u32 ext, struct sk_buff *skb); | 665 | void (*get_info)(struct sock *sk, u32 ext, struct sk_buff *skb); |
666 | 666 | ||
diff --git a/net/ipv4/tcp_bic.c b/net/ipv4/tcp_bic.c index 519de091a94d..4586211e3757 100644 --- a/net/ipv4/tcp_bic.c +++ b/net/ipv4/tcp_bic.c | |||
@@ -206,7 +206,7 @@ static void bictcp_state(struct sock *sk, u8 new_state) | |||
206 | /* Track delayed acknowledgment ratio using sliding window | 206 | /* Track delayed acknowledgment ratio using sliding window |
207 | * ratio = (15*ratio + sample) / 16 | 207 | * ratio = (15*ratio + sample) / 16 |
208 | */ | 208 | */ |
209 | static void bictcp_acked(struct sock *sk, u32 cnt, ktime_t last) | 209 | static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt) |
210 | { | 210 | { |
211 | const struct inet_connection_sock *icsk = inet_csk(sk); | 211 | const struct inet_connection_sock *icsk = inet_csk(sk); |
212 | 212 | ||
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index d17da30d82d6..0c44bb67a671 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
@@ -334,7 +334,7 @@ static void bictcp_state(struct sock *sk, u8 new_state) | |||
334 | /* Track delayed acknowledgment ratio using sliding window | 334 | /* Track delayed acknowledgment ratio using sliding window |
335 | * ratio = (15*ratio + sample) / 16 | 335 | * ratio = (15*ratio + sample) / 16 |
336 | */ | 336 | */ |
337 | static void bictcp_acked(struct sock *sk, u32 cnt, ktime_t last) | 337 | static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) |
338 | { | 338 | { |
339 | const struct inet_connection_sock *icsk = inet_csk(sk); | 339 | const struct inet_connection_sock *icsk = inet_csk(sk); |
340 | 340 | ||
diff --git a/net/ipv4/tcp_htcp.c b/net/ipv4/tcp_htcp.c index 08a02e6045c9..fa61663ace3b 100644 --- a/net/ipv4/tcp_htcp.c +++ b/net/ipv4/tcp_htcp.c | |||
@@ -98,7 +98,7 @@ static inline void measure_rtt(struct sock *sk) | |||
98 | } | 98 | } |
99 | } | 99 | } |
100 | 100 | ||
101 | static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked, ktime_t last) | 101 | static void measure_achieved_throughput(struct sock *sk, u32 pkts_acked, s32 rtt) |
102 | { | 102 | { |
103 | const struct inet_connection_sock *icsk = inet_csk(sk); | 103 | const struct inet_connection_sock *icsk = inet_csk(sk); |
104 | const struct tcp_sock *tp = tcp_sk(sk); | 104 | const struct tcp_sock *tp = tcp_sk(sk); |
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index cc5de6f69d46..64f1cbaf96e8 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c | |||
@@ -83,18 +83,16 @@ static void tcp_illinois_init(struct sock *sk) | |||
83 | } | 83 | } |
84 | 84 | ||
85 | /* Measure RTT for each ack. */ | 85 | /* Measure RTT for each ack. */ |
86 | static void tcp_illinois_acked(struct sock *sk, u32 pkts_acked, ktime_t last) | 86 | static void tcp_illinois_acked(struct sock *sk, u32 pkts_acked, s32 rtt) |
87 | { | 87 | { |
88 | struct illinois *ca = inet_csk_ca(sk); | 88 | struct illinois *ca = inet_csk_ca(sk); |
89 | u32 rtt; | ||
90 | 89 | ||
91 | ca->acked = pkts_acked; | 90 | ca->acked = pkts_acked; |
92 | 91 | ||
93 | if (ktime_equal(last, net_invalid_timestamp())) | 92 | /* dup ack, no rtt sample */ |
93 | if (rtt < 0) | ||
94 | return; | 94 | return; |
95 | 95 | ||
96 | rtt = ktime_to_us(net_timedelta(last)); | ||
97 | |||
98 | /* ignore bogus values, this prevents wraparound in alpha math */ | 96 | /* ignore bogus values, this prevents wraparound in alpha math */ |
99 | if (rtt > RTT_MAX) | 97 | if (rtt > RTT_MAX) |
100 | rtt = RTT_MAX; | 98 | rtt = RTT_MAX; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fec8a7a4dbaf..4b255fe999d9 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -2490,12 +2490,23 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p) | |||
2490 | tcp_ack_update_rtt(sk, acked, seq_rtt); | 2490 | tcp_ack_update_rtt(sk, acked, seq_rtt); |
2491 | tcp_ack_packets_out(sk); | 2491 | tcp_ack_packets_out(sk); |
2492 | 2492 | ||
2493 | /* Is the ACK triggering packet unambiguous? */ | 2493 | if (ca_ops->pkts_acked) { |
2494 | if (acked & FLAG_RETRANS_DATA_ACKED) | 2494 | s32 rtt_us = -1; |
2495 | last_ackt = net_invalid_timestamp(); | 2495 | |
2496 | /* Is the ACK triggering packet unambiguous? */ | ||
2497 | if (!(acked & FLAG_RETRANS_DATA_ACKED)) { | ||
2498 | /* High resolution needed and available? */ | ||
2499 | if (ca_ops->flags & TCP_CONG_RTT_STAMP && | ||
2500 | !ktime_equal(last_ackt, | ||
2501 | net_invalid_timestamp())) | ||
2502 | rtt_us = ktime_us_delta(ktime_get_real(), | ||
2503 | last_ackt); | ||
2504 | else if (seq_rtt > 0) | ||
2505 | rtt_us = jiffies_to_usecs(seq_rtt); | ||
2506 | } | ||
2496 | 2507 | ||
2497 | if (ca_ops->pkts_acked) | 2508 | ca_ops->pkts_acked(sk, pkts_acked, rtt_us); |
2498 | ca_ops->pkts_acked(sk, pkts_acked, last_ackt); | 2509 | } |
2499 | } | 2510 | } |
2500 | 2511 | ||
2501 | #if FASTRETRANS_DEBUG > 0 | 2512 | #if FASTRETRANS_DEBUG > 0 |
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index 80e140e3ec2d..e7f5ef92cbd8 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c | |||
@@ -260,13 +260,13 @@ static void tcp_lp_rtt_sample(struct sock *sk, u32 rtt) | |||
260 | * newReno in increase case. | 260 | * newReno in increase case. |
261 | * We work it out by following the idea from TCP-LP's paper directly | 261 | * We work it out by following the idea from TCP-LP's paper directly |
262 | */ | 262 | */ |
263 | static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, ktime_t last) | 263 | static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, s32 rtt_us) |
264 | { | 264 | { |
265 | struct tcp_sock *tp = tcp_sk(sk); | 265 | struct tcp_sock *tp = tcp_sk(sk); |
266 | struct lp *lp = inet_csk_ca(sk); | 266 | struct lp *lp = inet_csk_ca(sk); |
267 | 267 | ||
268 | if (!ktime_equal(last, net_invalid_timestamp())) | 268 | if (rtt_us > 0) |
269 | tcp_lp_rtt_sample(sk, ktime_to_us(net_timedelta(last))); | 269 | tcp_lp_rtt_sample(sk, rtt_us); |
270 | 270 | ||
271 | /* calc inference */ | 271 | /* calc inference */ |
272 | if (tcp_time_stamp > tp->rx_opt.rcv_tsecr) | 272 | if (tcp_time_stamp > tp->rx_opt.rcv_tsecr) |
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index 914e0307f7af..b49dedcda52d 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c | |||
@@ -112,16 +112,16 @@ EXPORT_SYMBOL_GPL(tcp_vegas_init); | |||
112 | * o min-filter RTT samples from a much longer window (forever for now) | 112 | * o min-filter RTT samples from a much longer window (forever for now) |
113 | * to find the propagation delay (baseRTT) | 113 | * to find the propagation delay (baseRTT) |
114 | */ | 114 | */ |
115 | void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, ktime_t last) | 115 | void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us) |
116 | { | 116 | { |
117 | struct vegas *vegas = inet_csk_ca(sk); | 117 | struct vegas *vegas = inet_csk_ca(sk); |
118 | u32 vrtt; | 118 | u32 vrtt; |
119 | 119 | ||
120 | if (ktime_equal(last, net_invalid_timestamp())) | 120 | if (rtt_us < 0) |
121 | return; | 121 | return; |
122 | 122 | ||
123 | /* Never allow zero rtt or baseRTT */ | 123 | /* Never allow zero rtt or baseRTT */ |
124 | vrtt = ktime_to_us(net_timedelta(last)) + 1; | 124 | vrtt = rtt_us + 1; |
125 | 125 | ||
126 | /* Filter to find propagation delay: */ | 126 | /* Filter to find propagation delay: */ |
127 | if (vrtt < vegas->baseRTT) | 127 | if (vrtt < vegas->baseRTT) |
diff --git a/net/ipv4/tcp_vegas.h b/net/ipv4/tcp_vegas.h index 502fa8183634..6c0eea2f8249 100644 --- a/net/ipv4/tcp_vegas.h +++ b/net/ipv4/tcp_vegas.h | |||
@@ -17,7 +17,7 @@ struct vegas { | |||
17 | 17 | ||
18 | extern void tcp_vegas_init(struct sock *sk); | 18 | extern void tcp_vegas_init(struct sock *sk); |
19 | extern void tcp_vegas_state(struct sock *sk, u8 ca_state); | 19 | extern void tcp_vegas_state(struct sock *sk, u8 ca_state); |
20 | extern void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, ktime_t last); | 20 | extern void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us); |
21 | extern void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event); | 21 | extern void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event); |
22 | extern void tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb); | 22 | extern void tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb); |
23 | 23 | ||
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c index 7a55ddf86032..8fb2aee0b1a4 100644 --- a/net/ipv4/tcp_veno.c +++ b/net/ipv4/tcp_veno.c | |||
@@ -69,16 +69,16 @@ static void tcp_veno_init(struct sock *sk) | |||
69 | } | 69 | } |
70 | 70 | ||
71 | /* Do rtt sampling needed for Veno. */ | 71 | /* Do rtt sampling needed for Veno. */ |
72 | static void tcp_veno_pkts_acked(struct sock *sk, u32 cnt, ktime_t last) | 72 | static void tcp_veno_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us) |
73 | { | 73 | { |
74 | struct veno *veno = inet_csk_ca(sk); | 74 | struct veno *veno = inet_csk_ca(sk); |
75 | u32 vrtt; | 75 | u32 vrtt; |
76 | 76 | ||
77 | if (ktime_equal(last, net_invalid_timestamp())) | 77 | if (rtt_us < 0) |
78 | return; | 78 | return; |
79 | 79 | ||
80 | /* Never allow zero rtt or baseRTT */ | 80 | /* Never allow zero rtt or baseRTT */ |
81 | vrtt = ktime_to_us(net_timedelta(last)) + 1; | 81 | vrtt = rtt_us + 1; |
82 | 82 | ||
83 | /* Filter to find propagation delay: */ | 83 | /* Filter to find propagation delay: */ |
84 | if (vrtt < veno->basertt) | 84 | if (vrtt < veno->basertt) |
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c index e61e09dd513e..20151d6a6241 100644 --- a/net/ipv4/tcp_westwood.c +++ b/net/ipv4/tcp_westwood.c | |||
@@ -100,11 +100,12 @@ static void westwood_filter(struct westwood *w, u32 delta) | |||
100 | * Called after processing group of packets. | 100 | * Called after processing group of packets. |
101 | * but all westwood needs is the last sample of srtt. | 101 | * but all westwood needs is the last sample of srtt. |
102 | */ | 102 | */ |
103 | static void tcp_westwood_pkts_acked(struct sock *sk, u32 cnt, ktime_t last) | 103 | static void tcp_westwood_pkts_acked(struct sock *sk, u32 cnt, s32 rtt) |
104 | { | 104 | { |
105 | struct westwood *w = inet_csk_ca(sk); | 105 | struct westwood *w = inet_csk_ca(sk); |
106 | if (cnt > 0) | 106 | |
107 | w->rtt = tcp_sk(sk)->srtt >> 3; | 107 | if (rtt > 0) |
108 | w->rtt = usecs_to_jiffies(rtt); | ||
108 | } | 109 | } |
109 | 110 | ||
110 | /* | 111 | /* |
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index c04b7c6ec702..c107fba7430e 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c | |||
@@ -58,7 +58,7 @@ static void tcp_yeah_init(struct sock *sk) | |||
58 | } | 58 | } |
59 | 59 | ||
60 | 60 | ||
61 | static void tcp_yeah_pkts_acked(struct sock *sk, u32 pkts_acked, ktime_t last) | 61 | static void tcp_yeah_pkts_acked(struct sock *sk, u32 pkts_acked, s32 rtt_us) |
62 | { | 62 | { |
63 | const struct inet_connection_sock *icsk = inet_csk(sk); | 63 | const struct inet_connection_sock *icsk = inet_csk(sk); |
64 | struct yeah *yeah = inet_csk_ca(sk); | 64 | struct yeah *yeah = inet_csk_ca(sk); |
@@ -66,7 +66,7 @@ static void tcp_yeah_pkts_acked(struct sock *sk, u32 pkts_acked, ktime_t last) | |||
66 | if (icsk->icsk_ca_state == TCP_CA_Open) | 66 | if (icsk->icsk_ca_state == TCP_CA_Open) |
67 | yeah->pkts_acked = pkts_acked; | 67 | yeah->pkts_acked = pkts_acked; |
68 | 68 | ||
69 | tcp_vegas_pkts_acked(sk, pkts_acked, last); | 69 | tcp_vegas_pkts_acked(sk, pkts_acked, rtt_us); |
70 | } | 70 | } |
71 | 71 | ||
72 | static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, | 72 | static void tcp_yeah_cong_avoid(struct sock *sk, u32 ack, |