summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2019-06-26 09:12:34 -0700
committerJohn Lo <loj@cisco.com>2019-07-10 22:17:36 +0000
commit85fc13004df7f67012a04e73564ecef1b3641ef3 (patch)
treecc50b441d83b6c86ebeb1db51ff66dee83e9e2a4
parentadbaf7bc2e301e591d63fae47f0a9bbb1577494e (diff)
tcp: improve rate estimate
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>
-rw-r--r--src/plugins/unittest/tcp_test.c23
-rw-r--r--src/vnet/tcp/tcp.h14
-rw-r--r--src/vnet/tcp/tcp_bt.c17
3 files changed, 35 insertions, 19 deletions
diff --git a/src/plugins/unittest/tcp_test.c b/src/plugins/unittest/tcp_test.c
index 7d0d229f3ca..6f765e7a4fc 100644
--- a/src/plugins/unittest/tcp_test.c
+++ b/src/plugins/unittest/tcp_test.c
@@ -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);
diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h
index d736685771d..7ccc06aea9c 100644
--- a/src/vnet/tcp/tcp.h
+++ b/src/vnet/tcp/tcp.h
@@ -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;
diff --git a/src/vnet/tcp/tcp_bt.c b/src/vnet/tcp/tcp_bt.c
index 74947474b53..dd3d9539d9a 100644
--- a/src/vnet/tcp/tcp_bt.c
+++ b/src/vnet/tcp/tcp_bt.c
@@ -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