aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>2007-06-15 18:08:43 -0400
committerDavid S. Miller <davem@davemloft.net>2007-06-15 18:08:43 -0400
commitb9ce204f0a265f819d10c943a607746abb62f245 (patch)
tree45078d076bcd952d8820c590653939b312d06ac2
parent22b1a9203ea634ac0ee5240e021613da3328275f (diff)
[TCP]: Congestion control API RTT sampling fix
Commit 164891aadf1721fca4dce473bb0e0998181537c6 broke RTT sampling of congestion control modules. Inaccurate timestamps could be fed to them without providing any way for them to identify such cases. Previously RTT sampler was called only if FLAG_RETRANS_DATA_ACKED was not set filtering inaccurate timestamps nicely. In addition, the new behavior could give an invalid timestamp (zero) to RTT sampler if only skbs with TCPCB_RETRANS were ACKed. This solves both problems. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/ktime.h12
-rw-r--r--include/linux/skbuff.h4
-rw-r--r--net/ipv4/tcp_illinois.c3
-rw-r--r--net/ipv4/tcp_input.c6
-rw-r--r--net/ipv4/tcp_lp.c3
-rw-r--r--net/ipv4/tcp_vegas.c3
-rw-r--r--net/ipv4/tcp_veno.c3
7 files changed, 32 insertions, 2 deletions
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index c762954bda14..2b139f66027f 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -261,6 +261,18 @@ static inline s64 ktime_to_ns(const ktime_t kt)
261 261
262#endif 262#endif
263 263
264/**
265 * ktime_equal - Compares two ktime_t variables to see if they are equal
266 * @cmp1: comparable1
267 * @cmp2: comparable2
268 *
269 * Compare two ktime_t variables, returns 1 if equal
270 */
271static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
272{
273 return cmp1.tv64 == cmp2.tv64;
274}
275
264static inline s64 ktime_to_us(const ktime_t kt) 276static inline s64 ktime_to_us(const ktime_t kt)
265{ 277{
266 struct timeval tv = ktime_to_timeval(kt); 278 struct timeval tv = ktime_to_timeval(kt);
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index e7367c74e1bb..6f0b2f7d0010 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1579,6 +1579,10 @@ static inline ktime_t net_timedelta(ktime_t t)
1579 return ktime_sub(ktime_get_real(), t); 1579 return ktime_sub(ktime_get_real(), t);
1580} 1580}
1581 1581
1582static inline ktime_t net_invalid_timestamp(void)
1583{
1584 return ktime_set(0, 0);
1585}
1582 1586
1583extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); 1587extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
1584extern __sum16 __skb_checksum_complete(struct sk_buff *skb); 1588extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c
index 4adc47c55351..b2b2256d3b84 100644
--- a/net/ipv4/tcp_illinois.c
+++ b/net/ipv4/tcp_illinois.c
@@ -90,6 +90,9 @@ static void tcp_illinois_acked(struct sock *sk, u32 pkts_acked, ktime_t last)
90 90
91 ca->acked = pkts_acked; 91 ca->acked = pkts_acked;
92 92
93 if (ktime_equal(last, net_invalid_timestamp()))
94 return;
95
93 rtt = ktime_to_us(net_timedelta(last)); 96 rtt = ktime_to_us(net_timedelta(last));
94 97
95 /* ignore bogus values, this prevents wraparound in alpha math */ 98 /* ignore bogus values, this prevents wraparound in alpha math */
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index d6d0f9b6cdc6..aaf6f66677f9 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -2409,7 +2409,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
2409 int acked = 0; 2409 int acked = 0;
2410 int prior_packets = tp->packets_out; 2410 int prior_packets = tp->packets_out;
2411 __s32 seq_rtt = -1; 2411 __s32 seq_rtt = -1;
2412 ktime_t last_ackt = ktime_set(0,0); 2412 ktime_t last_ackt = net_invalid_timestamp();
2413 2413
2414 while ((skb = tcp_write_queue_head(sk)) && 2414 while ((skb = tcp_write_queue_head(sk)) &&
2415 skb != tcp_send_head(sk)) { 2415 skb != tcp_send_head(sk)) {
@@ -2487,6 +2487,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
2487 tcp_ack_update_rtt(sk, acked, seq_rtt); 2487 tcp_ack_update_rtt(sk, acked, seq_rtt);
2488 tcp_ack_packets_out(sk); 2488 tcp_ack_packets_out(sk);
2489 2489
2490 /* Is the ACK triggering packet unambiguous? */
2491 if (acked & FLAG_RETRANS_DATA_ACKED)
2492 last_ackt = net_invalid_timestamp();
2493
2490 if (ca_ops->pkts_acked) 2494 if (ca_ops->pkts_acked)
2491 ca_ops->pkts_acked(sk, pkts_acked, last_ackt); 2495 ca_ops->pkts_acked(sk, pkts_acked, last_ackt);
2492 } 2496 }
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c
index 43294ad9f63e..e49836ce012e 100644
--- a/net/ipv4/tcp_lp.c
+++ b/net/ipv4/tcp_lp.c
@@ -266,7 +266,8 @@ static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, ktime_t last)
266 struct tcp_sock *tp = tcp_sk(sk); 266 struct tcp_sock *tp = tcp_sk(sk);
267 struct lp *lp = inet_csk_ca(sk); 267 struct lp *lp = inet_csk_ca(sk);
268 268
269 tcp_lp_rtt_sample(sk, ktime_to_us(net_timedelta(last))); 269 if (!ktime_equal(last, net_invalid_timestamp()))
270 tcp_lp_rtt_sample(sk, ktime_to_us(net_timedelta(last)));
270 271
271 /* calc inference */ 272 /* calc inference */
272 if (tcp_time_stamp > tp->rx_opt.rcv_tsecr) 273 if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c
index 73e19cf7df21..e218a51ceced 100644
--- a/net/ipv4/tcp_vegas.c
+++ b/net/ipv4/tcp_vegas.c
@@ -117,6 +117,9 @@ void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
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()))
121 return;
122
120 /* Never allow zero rtt or baseRTT */ 123 /* Never allow zero rtt or baseRTT */
121 vrtt = ktime_to_us(net_timedelta(last)) + 1; 124 vrtt = ktime_to_us(net_timedelta(last)) + 1;
122 125
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c
index 9edb340f2f95..ec854cc5fad5 100644
--- a/net/ipv4/tcp_veno.c
+++ b/net/ipv4/tcp_veno.c
@@ -74,6 +74,9 @@ static void tcp_veno_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
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()))
78 return;
79
77 /* Never allow zero rtt or baseRTT */ 80 /* Never allow zero rtt or baseRTT */
78 vrtt = ktime_to_us(net_timedelta(last)) + 1; 81 vrtt = ktime_to_us(net_timedelta(last)) + 1;
79 82