tcp: improve rate estimate 68/20368/6
authorFlorin Coras <fcoras@cisco.com>
Wed, 26 Jun 2019 16:12:34 +0000 (09:12 -0700)
committerJohn Lo <loj@cisco.com>
Wed, 10 Jul 2019 22:17:36 +0000 (22:17 +0000)
Type:feature

- sample rtt estimation
- report acked+sacked
- report last lost bytes
- use snd_una == snd_nxt to detect 0 bytes in flight

Change-Id: I83181261fdb375c7e33d24b7a82343561e6a905f
Signed-off-by: Florin Coras <fcoras@cisco.com>
src/plugins/unittest/tcp_test.c
src/vnet/tcp/tcp.h
src/vnet/tcp/tcp_bt.c

index 7d0d229..6f765e7 100644 (file)
@@ -857,9 +857,9 @@ tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
   TCP_TEST (pool_elts (bt->samples) == 0, "sample should've been consumed");
   TCP_TEST (tc->delivered_time == 2, "delivered time should be 2");
   TCP_TEST (tc->delivered == burst, "delivered should be 100");
-  TCP_TEST (rs->ack_time == 1, "ack time should be 1");
+  TCP_TEST (rs->interval_time == 1, "ack time should be 1");
   TCP_TEST (rs->delivered == burst, "delivered should be 100");
-  TCP_TEST (rs->sample_delivered == 0, "sample delivered should be 0");
+  TCP_TEST (rs->prior_delivered == 0, "sample delivered should be 0");
   TCP_TEST (approx_equal (rate, rs->tx_rate), "rate should be %u is %u", rate,
            rs->tx_rate);
   TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
@@ -897,9 +897,9 @@ tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
   TCP_TEST (tc->delivered_time == 4, "delivered time should be 4");
   TCP_TEST (tc->delivered == 3 * burst, "delivered should be 300 is %u",
            tc->delivered);
-  TCP_TEST (rs->ack_time == 2, "ack time should be 2");
+  TCP_TEST (rs->interval_time == 2, "ack time should be 2");
   TCP_TEST (rs->delivered == 2 * burst, "delivered should be 200");
-  TCP_TEST (rs->sample_delivered == burst, "delivered should be 100");
+  TCP_TEST (rs->prior_delivered == burst, "delivered should be 100");
   TCP_TEST (approx_equal (rate, rs->tx_rate), "rate should be %u is %u", rate,
            rs->tx_rate);
   TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
@@ -964,9 +964,10 @@ tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
            3 * burst + 30, tc->delivered);
   /* All 3 samples have the same delivered number of bytes. So the first is
    * the reference for delivery estimate. */
-  TCP_TEST (rs->ack_time == 4, "ack time should be 4 is %.2f", rs->ack_time);
+  TCP_TEST (rs->interval_time == 4, "ack time should be 4 is %.2f",
+           rs->interval_time);
   TCP_TEST (rs->delivered == 30, "delivered should be 30");
-  TCP_TEST (rs->sample_delivered == 3 * burst,
+  TCP_TEST (rs->prior_delivered == 3 * burst,
            "sample delivered should be %u", 3 * burst);
   TCP_TEST (approx_equal (rate, rs->tx_rate), "rate should be %u is %u", rate,
            rs->tx_rate);
@@ -1045,11 +1046,12 @@ tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
   TCP_TEST (tc->delivered == 5 * burst + 40, "delivered should be %u is %u",
            5 * burst + 40, tc->delivered);
   /* A rxt was acked and delivered time for it is 8 (last ack time) */
-  TCP_TEST (rs->ack_time == 2, "ack time should be 2 is %.2f", rs->ack_time);
+  TCP_TEST (rs->interval_time == 2, "ack time should be 2 is %.2f",
+           rs->interval_time);
   /* delivered_now - delivered_rxt ~ 5 * burst + 40 - 3 * burst - 30 */
   TCP_TEST (rs->delivered == 2 * burst + 10, "delivered should be 210 is %u",
            rs->delivered);
-  TCP_TEST (rs->sample_delivered == 3 * burst + 30,
+  TCP_TEST (rs->prior_delivered == 3 * burst + 30,
            "sample delivered should be %u", 3 * burst + 30);
   TCP_TEST (approx_equal (rate, rs->tx_rate), "rate should be %u is %u", rate,
            rs->tx_rate);
@@ -1077,12 +1079,13 @@ tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
   TCP_TEST (tc->delivered == 7 * burst, "delivered should be %u is %u",
            7 * burst, tc->delivered);
   /* Last rxt was at time 8 */
-  TCP_TEST (rs->ack_time == 3, "ack time should be 3 is %.2f", rs->ack_time);
+  TCP_TEST (rs->interval_time == 3, "ack time should be 3 is %.2f",
+           rs->interval_time);
   /* delivered_now - delivered_rxt ~ 7 * burst - 3 * burst - 30.
    * That's because we didn't retransmit any new segment. */
   TCP_TEST (rs->delivered == 4 * burst - 30, "delivered should be 160 is %u",
            rs->delivered);
-  TCP_TEST (rs->sample_delivered == 3 * burst + 30,
+  TCP_TEST (rs->prior_delivered == 3 * burst + 30,
            "sample delivered should be %u", 3 * burst + 30);
   TCP_TEST (approx_equal (rate, rs->tx_rate), "rate should be %u is %u", rate,
            rs->tx_rate);
index d736685..7ccc06a 100644 (file)
@@ -249,18 +249,24 @@ typedef struct tcp_bt_sample_
   u32 prev;                    /**< Previous sample index in list */
   u32 min_seq;                 /**< Min seq number in sample */
   u32 max_seq;                 /**< Max seq number. Set for rxt samples */
-  u64 delivered;               /**< Total delivered when sample taken */
+  u64 delivered;               /**< Total delivered bytes for sample */
   f64 delivered_time;          /**< Delivered time when sample taken */
+  f64 tx_time;                 /**< Transmit time for the burst */
   u64 tx_rate;                 /**< Tx pacing rate */
   tcp_bts_flags_t flags;       /**< Sample flag */
 } tcp_bt_sample_t;
 
 typedef struct tcp_rate_sample_
 {
-  u64 sample_delivered;                /**< Delivered of sample used for rate */
-  u32 delivered;               /**< Bytes delivered in ack time */
-  f64 ack_time;                        /**< Time to ack the bytes delivered */
+  u64 prior_delivered;         /**< Delivered of sample used for rate, i.e.,
+                                    total bytes delivered at prior_time */
+  f64 prior_time;              /**< Delivered time of sample used for rate */
+  f64 interval_time;           /**< Time to ack the bytes delivered */
+  f64 rtt_time;                        /**< RTT for sample */
   u64 tx_rate;                 /**< Tx pacing rate */
+  u32 delivered;               /**< Bytes delivered in interval_time */
+  u32 acked_and_sacked;                /**< Bytes acked + sacked now */
+  u32 lost;                    /**< Bytes lost now */
   tcp_bts_flags_t flags;       /**< Rate sample flags from bt sample */
 } tcp_rate_sample_t;
 
index 7494747..dd3d953 100644 (file)
@@ -242,6 +242,7 @@ tcp_bt_alloc_tx_sample (tcp_connection_t * tc, u32 min_seq)
   bts->delivered = tc->delivered;
   bts->delivered_time = tc->delivered_time;
   bts->tx_rate = transport_connection_tx_pacer_rate (&tc->connection);
+  bts->tx_time = tcp_time_now_us (tc->c_thread_index);
   bts->flags |= tc->app_limited ? TCP_BTS_IS_APP_LIMITED : 0;
   return bts;
 }
@@ -268,7 +269,7 @@ tcp_bt_track_tx (tcp_connection_t * tc)
   tcp_bt_sample_t *bts, *tail;
   u32 bts_index;
 
-  if (!tcp_flight_size (tc))
+  if (tc->snd_una == tc->snd_nxt)
     tc->delivered_time = tcp_time_now_us (tc->c_thread_index);
 
   bts = tcp_bt_alloc_tx_sample (tc, tc->snd_nxt);
@@ -415,12 +416,12 @@ static void
 tcp_bt_sample_to_rate_sample (tcp_connection_t * tc, tcp_bt_sample_t * bts,
                              tcp_rate_sample_t * rs)
 {
-  if (rs->sample_delivered && rs->sample_delivered >= bts->delivered)
+  if (rs->prior_delivered && rs->prior_delivered >= bts->delivered)
     return;
 
-  rs->sample_delivered = bts->delivered;
-  rs->delivered = tc->delivered - bts->delivered;
-  rs->ack_time = tc->delivered_time - bts->delivered_time;
+  rs->prior_delivered = bts->delivered;
+  rs->prior_time = bts->delivered_time;
+  rs->rtt_time = bts->tx_time;
   rs->tx_rate = bts->tx_rate;
   rs->flags = bts->flags;
 }
@@ -527,6 +528,12 @@ tcp_bt_sample_delivery_rate (tcp_connection_t * tc, tcp_rate_sample_t * rs)
 
   if (tc->sack_sb.last_sacked_bytes)
     tcp_bt_walk_samples_ooo (tc, rs);
+
+  rs->interval_time = tc->delivered_time - rs->prior_time;
+  rs->delivered = tc->delivered - rs->prior_delivered;
+  rs->rtt_time = tc->delivered_time - rs->rtt_time;
+  rs->acked_and_sacked = delivered;
+  rs->lost = tc->sack_sb.last_lost_bytes;
 }
 
 void