[TCP]: Congestion control API RTT sampling fix
authorIlpo Järvinen <ilpo.jarvinen@helsinki.fi>
Fri, 15 Jun 2007 22:08:43 +0000 (15:08 -0700)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Jun 2007 22:08:43 +0000 (15:08 -0700)
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>
include/linux/ktime.h
include/linux/skbuff.h
net/ipv4/tcp_illinois.c
net/ipv4/tcp_input.c
net/ipv4/tcp_lp.c
net/ipv4/tcp_vegas.c
net/ipv4/tcp_veno.c

index c762954bda148fa18ab13f6d1f71aab26d2e3441..2b139f66027f3de7ae5f1a60df00ddf39c8cb147 100644 (file)
@@ -261,6 +261,18 @@ static inline s64 ktime_to_ns(const ktime_t kt)
 
 #endif
 
+/**
+ * ktime_equal - Compares two ktime_t variables to see if they are equal
+ * @cmp1:      comparable1
+ * @cmp2:      comparable2
+ *
+ * Compare two ktime_t variables, returns 1 if equal
+ */
+static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
+{
+       return cmp1.tv64 == cmp2.tv64;
+}
+
 static inline s64 ktime_to_us(const ktime_t kt)
 {
        struct timeval tv = ktime_to_timeval(kt);
index e7367c74e1bbedbca7c81ad69215d0e751deb9bb..6f0b2f7d00108835253403dc5f74039b49e3d002 100644 (file)
@@ -1579,6 +1579,10 @@ static inline ktime_t net_timedelta(ktime_t t)
        return ktime_sub(ktime_get_real(), t);
 }
 
+static inline ktime_t net_invalid_timestamp(void)
+{
+       return ktime_set(0, 0);
+}
 
 extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
 extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
index 4adc47c55351a49d09d172b1cb5a3baa194207bc..b2b2256d3b8450c944bc8d3a8869a76aaf2ceb69 100644 (file)
@@ -90,6 +90,9 @@ static void tcp_illinois_acked(struct sock *sk, u32 pkts_acked, ktime_t last)
 
        ca->acked = pkts_acked;
 
+       if (ktime_equal(last, net_invalid_timestamp()))
+               return;
+
        rtt = ktime_to_us(net_timedelta(last));
 
        /* ignore bogus values, this prevents wraparound in alpha math */
index d6d0f9b6cdc6f3eda97ea76b6c69610fba902b6a..aaf6f66677f992fc09dcf19f135eb483252efcf3 100644 (file)
@@ -2409,7 +2409,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
        int acked = 0;
        int prior_packets = tp->packets_out;
        __s32 seq_rtt = -1;
-       ktime_t last_ackt = ktime_set(0,0);
+       ktime_t last_ackt = net_invalid_timestamp();
 
        while ((skb = tcp_write_queue_head(sk)) &&
               skb != tcp_send_head(sk)) {
@@ -2487,6 +2487,10 @@ static int tcp_clean_rtx_queue(struct sock *sk, __s32 *seq_rtt_p)
                tcp_ack_update_rtt(sk, acked, seq_rtt);
                tcp_ack_packets_out(sk);
 
+               /* Is the ACK triggering packet unambiguous? */
+               if (acked & FLAG_RETRANS_DATA_ACKED)
+                       last_ackt = net_invalid_timestamp();
+
                if (ca_ops->pkts_acked)
                        ca_ops->pkts_acked(sk, pkts_acked, last_ackt);
        }
index 43294ad9f63ef839cd26f693ccf1a4eb8b4173ee..e49836ce012e768a4586432f7b62be9a0b6e5140 100644 (file)
@@ -266,7 +266,8 @@ static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, ktime_t last)
        struct tcp_sock *tp = tcp_sk(sk);
        struct lp *lp = inet_csk_ca(sk);
 
-       tcp_lp_rtt_sample(sk,  ktime_to_us(net_timedelta(last)));
+       if (!ktime_equal(last, net_invalid_timestamp()))
+               tcp_lp_rtt_sample(sk,  ktime_to_us(net_timedelta(last)));
 
        /* calc inference */
        if (tcp_time_stamp > tp->rx_opt.rcv_tsecr)
index 73e19cf7df2176e6189c45569939bf42e51f0363..e218a51ceced186b9c37acab906009dfbfe94233 100644 (file)
@@ -117,6 +117,9 @@ void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
        struct vegas *vegas = inet_csk_ca(sk);
        u32 vrtt;
 
+       if (ktime_equal(last, net_invalid_timestamp()))
+               return;
+
        /* Never allow zero rtt or baseRTT */
        vrtt = ktime_to_us(net_timedelta(last)) + 1;
 
index 9edb340f2f95c6e003f5ff09f135425423881134..ec854cc5fad50fd90899818086310cd51b61cbdc 100644 (file)
@@ -74,6 +74,9 @@ static void tcp_veno_pkts_acked(struct sock *sk, u32 cnt, ktime_t last)
        struct veno *veno = inet_csk_ca(sk);
        u32 vrtt;
 
+       if (ktime_equal(last, net_invalid_timestamp()))
+               return;
+
        /* Never allow zero rtt or baseRTT */
        vrtt = ktime_to_us(net_timedelta(last)) + 1;