clib_memset (tc, 0, sizeof (*tc));
+ tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
tc->snd_una = 0;
tc->snd_una_max = 1000;
tc->snd_nxt = 1000;
TCP_TEST ((hole->start == 900 && hole->end == 1000),
"last hole start %u end %u", hole->start, hole->end);
TCP_TEST ((sb->sacked_bytes == 400), "sacked bytes %d", sb->sacked_bytes);
- TCP_TEST ((sb->snd_una_adv == 0), "snd_una_adv %u", sb->snd_una_adv);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
TCP_TEST ((sb->last_sacked_bytes == 400),
"last sacked bytes %d", sb->last_sacked_bytes);
TCP_TEST ((sb->high_sacked == 900), "high sacked %u", sb->high_sacked);
TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
/*
- * Inject odd blocks
+ * Inject odd blocks except the last
+ *
*/
vec_reset_length (tc->rcv_opts.sacks);
- for (i = 0; i < 1000 / 200; i++)
+ for (i = 0; i < 800 / 200; i++)
{
vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
}
sb, tc);
hole = scoreboard_first_hole (sb);
- TCP_TEST ((pool_elts (sb->holes) == 1),
+ TCP_TEST ((pool_elts (sb->holes) == 2),
"scoreboard has %d holes", pool_elts (sb->holes));
TCP_TEST ((hole->start == 0 && hole->end == 100),
"first hole start %u end %u", hole->start, hole->end);
- TCP_TEST ((sb->sacked_bytes == 900), "sacked bytes %d", sb->sacked_bytes);
- TCP_TEST ((sb->snd_una_adv == 0), "snd_una_adv %u", sb->snd_una_adv);
- TCP_TEST ((sb->high_sacked == 1000), "high sacked %u", sb->high_sacked);
- TCP_TEST ((sb->last_sacked_bytes == 500),
+ TCP_TEST ((sb->sacked_bytes == 800), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
+ TCP_TEST ((sb->high_sacked == 900), "high sacked %u", sb->high_sacked);
+ TCP_TEST ((sb->last_sacked_bytes == 400),
"last sacked bytes %d", sb->last_sacked_bytes);
TCP_TEST ((sb->lost_bytes == 100), "lost bytes %u", sb->lost_bytes);
/*
- * Ack until byte 100, all bytes are now acked + sacked
+ * Ack until byte 100 - this is reneging because we should ack until 900
*/
tcp_rcv_sacks (tc, 100);
if (verbose)
vlib_cli_output (vm, "\nack until byte 100:\n%U", format_tcp_scoreboard,
sb, tc);
- TCP_TEST ((pool_elts (sb->holes) == 0),
- "scoreboard has %d elements", pool_elts (sb->holes));
- TCP_TEST ((sb->snd_una_adv == 900),
- "snd_una_adv after ack %u", sb->snd_una_adv);
+ TCP_TEST ((pool_elts (sb->holes) == 1), "scoreboard has %d elements",
+ pool_elts (sb->holes));
+ TCP_TEST ((sb->is_reneging), "is reneging");
+
+ /*
+ * Make sure we accept duplicate acks while reneging.
+ */
+ tc->snd_una = 100;
+ sb->high_rxt = 950;
+
+ block.start = 900;
+ block.end = 950;
+ vec_add1 (tc->rcv_opts.sacks, block);
+
+ tcp_rcv_sacks (tc, 100);
+ TCP_TEST ((pool_elts (sb->holes) == 1), "scoreboard has %d elements",
+ pool_elts (sb->holes));
+ TCP_TEST ((sb->is_reneging), "is reneging");
+ TCP_TEST ((sb->last_sacked_bytes == 50), "last sacked bytes %d",
+ sb->last_sacked_bytes);
+ TCP_TEST ((sb->rxt_sacked == 50), "last rxt sacked bytes %d",
+ sb->rxt_sacked);
+
+ /*
+ * Sack all up to 950
+ */
+ tcp_rcv_sacks (tc, 950);
+ TCP_TEST ((sb->high_sacked == 950), "max sacked byte %u", sb->high_sacked);
+ TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 0),
+ "last sacked bytes %d", sb->last_sacked_bytes);
+ TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
+
+ /*
+ * Sack [960 970] [980 990]
+ */
+ sb->high_rxt = 985;
+
+ tc->snd_una = 950;
+ vec_reset_length (tc->rcv_opts.sacks);
+ block.start = 960;
+ block.end = 970;
+ vec_add1 (tc->rcv_opts.sacks, block);
+
+ block.start = 980;
+ block.end = 990;
+ vec_add1 (tc->rcv_opts.sacks, block);
+
+ tcp_rcv_sacks (tc, 950);
+ TCP_TEST ((sb->high_sacked == 990), "max sacked byte %u", sb->high_sacked);
+ TCP_TEST ((sb->sacked_bytes == 20), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 20),
+ "last sacked bytes %d", sb->last_sacked_bytes);
+ TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
+ TCP_TEST ((sb->rxt_sacked == 15), "last rxt sacked bytes %d",
+ sb->rxt_sacked);
+
+ /*
+ * Ack up to 960 (reneging) + [961 971]
+ */
+ tc->rcv_opts.sacks[0].start = 961;
+ tc->rcv_opts.sacks[0].end = 971;
+
+ tcp_rcv_sacks (tc, 960);
+
+ TCP_TEST ((sb->is_reneging), "is reneging");
+ TCP_TEST ((sb->sacked_bytes == 21), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 1),
+ "last sacked bytes %d", sb->last_sacked_bytes);
+ TCP_TEST ((sb->rxt_sacked == 11), "last rxt sacked bytes %d",
+ sb->rxt_sacked);
+ TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
+ sb->last_bytes_delivered);
+
+ /*
+ * Ack up to 960 (reneging) + [961 990]
+ */
+ tc->snd_una = 960;
+ tc->rcv_opts.sacks[0].start = 961;
+ tc->rcv_opts.sacks[0].end = 990;
+
+ tcp_rcv_sacks (tc, 960);
+
+ TCP_TEST ((sb->is_reneging), "is reneging");
+ TCP_TEST ((sb->sacked_bytes == 30), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 9),
+ "last sacked bytes %d", sb->last_sacked_bytes);
+ TCP_TEST ((sb->rxt_sacked == 9), "last rxt sacked bytes %d",
+ sb->rxt_sacked);
+
+ /*
+ * Sack remaining bytes [990 1000]
+ */
+ tc->rcv_opts.sacks[0].start = 990;
+ tc->rcv_opts.sacks[0].end = 1000;
+
+ tcp_rcv_sacks (tc, 960);
+
+ TCP_TEST ((sb->is_reneging), "is reneging");
+ TCP_TEST ((sb->sacked_bytes == 40), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 10),
+ "last sacked bytes %d", sb->last_sacked_bytes);
+ TCP_TEST ((sb->rxt_sacked == 0), "last rxt sacked bytes %d",
+ sb->rxt_sacked);
+ TCP_TEST (pool_elts (sb->holes) == 0, "no holes left");
+
+ /*
+ * Ack up to 970 no sack blocks
+ */
+ vec_reset_length (tc->rcv_opts.sacks);
+ tc->rcv_opts.flags &= ~TCP_OPTS_FLAG_SACK;
+ tcp_rcv_sacks (tc, 970);
+
+ TCP_TEST ((sb->is_reneging), "is reneging");
+ TCP_TEST ((sb->sacked_bytes == 30), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 0),
+ "last sacked bytes %d", sb->last_sacked_bytes);
+ TCP_TEST ((sb->rxt_sacked == 0), "last rxt sacked bytes %d",
+ sb->rxt_sacked);
+
+ /*
+ * Ack all up to 1000
+ */
+ tc->snd_una = 970;
+ tcp_rcv_sacks (tc, 1000);
TCP_TEST ((sb->high_sacked == 1000), "max sacked byte %u", sb->high_sacked);
TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST (sb->last_bytes_delivered == 30, "last bytes delivered %d",
+ sb->last_bytes_delivered);
TCP_TEST ((sb->last_sacked_bytes == 0),
"last sacked bytes %d", sb->last_sacked_bytes);
TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
/*
* Add new block
*/
-
+ tc->flags = 0;
+ tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
vec_reset_length (tc->rcv_opts.sacks);
block.start = 1200;
vlib_cli_output (vm, "\nadd [1200, 1300] snd_una_max 1500, snd_una 1000:"
" \n%U", format_tcp_scoreboard, sb, tc);
- TCP_TEST ((sb->snd_una_adv == 0),
- "snd_una_adv after ack %u", sb->snd_una_adv);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
TCP_TEST ((pool_elts (sb->holes) == 2),
"scoreboard has %d holes", pool_elts (sb->holes));
hole = scoreboard_first_hole (sb);
TCP_TEST ((hole->start == 1000 && hole->end == 1200),
"first hole start %u end %u", hole->start, hole->end);
- TCP_TEST ((sb->snd_una_adv == 0),
- "snd_una_adv after ack %u", sb->snd_una_adv);
TCP_TEST ((sb->high_sacked == 1300), "max sacked byte %u", sb->high_sacked);
hole = scoreboard_last_hole (sb);
TCP_TEST ((hole->start == 1300 && hole->end == 1500),
*/
vec_reset_length (tc->rcv_opts.sacks);
- tcp_rcv_sacks (tc, 1200);
+ /* Ack up to 1300 to avoid reneging */
+ tcp_rcv_sacks (tc, 1300);
if (verbose)
- vlib_cli_output (vm, "\nsb ack up to byte 1200:\n%U",
+ vlib_cli_output (vm, "\nsb ack up to byte 1300:\n%U",
format_tcp_scoreboard, sb, tc);
- TCP_TEST ((sb->snd_una_adv == 100),
- "snd_una_adv after ack %u", sb->snd_una_adv);
TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
- TCP_TEST ((pool_elts (sb->holes) == 0),
+ TCP_TEST ((pool_elts (sb->holes) == 1),
"scoreboard has %d elements", pool_elts (sb->holes));
TCP_TEST ((sb->last_bytes_delivered == 100), "last bytes delivered %d",
sb->last_bytes_delivered);
TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
- TCP_TEST ((sb->head == TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
- TCP_TEST ((sb->tail == TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
+ TCP_TEST ((sb->head != TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
+ TCP_TEST ((sb->tail != TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
/*
* Add some more blocks and then remove all
*/
vec_reset_length (tc->rcv_opts.sacks);
- tc->snd_una += sb->snd_una_adv;
+ tc->snd_una = 1300;
tc->snd_nxt = tc->snd_una_max = 1900;
for (i = 0; i < 5; i++)
{
tc->snd_una = 0;
tc->snd_una_max = 1000;
tc->snd_nxt = 1000;
+ vec_reset_length (tc->rcv_opts.sacks);
for (i = 0; i < 5; i++)
{
vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
tcp_rcv_sacks (tc, 0);
if (verbose)
- vlib_cli_output (vm, "\nsb added odd blocks snd_una 0 snd_una_max 1500:"
+ vlib_cli_output (vm, "\nsb added odd blocks snd_una 0 snd_una_max 1000:"
"\n%U", format_tcp_scoreboard, sb, tc);
TCP_TEST ((pool_elts (sb->holes) == 5),
"scoreboard has %d elements", pool_elts (sb->holes));
TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
+ hole = scoreboard_last_hole (sb);
+ TCP_TEST ((hole->end == 900), "last hole end %u", hole->end);
+ TCP_TEST ((sb->high_sacked == 1000), "high sacked %u", sb->high_sacked);
+ /*
+ * Renege bytes from 950 to 1000
+ */
tcp_rcv_sacks (tc, 950);
if (verbose)
vlib_cli_output (vm, "\nack [0, 950]:\n%U", format_tcp_scoreboard, sb,
tc);
- TCP_TEST ((pool_elts (sb->holes) == 0),
- "scoreboard has %d elements", pool_elts (sb->holes));
- TCP_TEST ((sb->snd_una_adv == 50), "snd_una_adv %u", sb->snd_una_adv);
- TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
- TCP_TEST ((sb->last_sacked_bytes == 0),
- "last sacked bytes %d", sb->last_sacked_bytes);
+ TCP_TEST ((pool_elts (sb->holes) == 0), "scoreboard has %d elements",
+ pool_elts (sb->holes));
+ TCP_TEST ((sb->is_reneging), "is reneging");
+ TCP_TEST ((sb->sacked_bytes == 50), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
+ sb->last_sacked_bytes);
TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
+ TCP_TEST ((sb->high_sacked == 1000), "high sacked %u", sb->high_sacked);
+
+ scoreboard_clear (sb);
/*
* Inject one block, ack it and overlap hole
vlib_cli_output (vm, "\nsb ack [0, 800]:\n%U", format_tcp_scoreboard, sb,
tc);
- TCP_TEST ((pool_elts (sb->holes) == 0),
+ TCP_TEST ((pool_elts (sb->holes) == 1),
"scoreboard has %d elements", pool_elts (sb->holes));
- TCP_TEST ((sb->snd_una_adv == 0), "snd_una_adv %u", sb->snd_una_adv);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
sb->last_sacked_bytes);
TCP_TEST ((sb->last_bytes_delivered == 400),
"last bytes delivered %d", sb->last_bytes_delivered);
TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
- TCP_TEST ((sb->head == TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
- TCP_TEST ((sb->tail == TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
+ TCP_TEST ((sb->head != TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
+ TCP_TEST ((sb->tail != TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
/*
* One hole close to head, patch head, split in two and start acking
sb->last_bytes_delivered);
TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
+ /*
+ * Ack [100 300] in two steps
+ *
+ * Step 1. Ack [100 200] which delivers 100 of the bytes lost
+ */
tc->snd_una = 100;
tcp_rcv_sacks (tc, 200);
+ TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
+ sb->last_bytes_delivered);
+ TCP_TEST ((sb->lost_bytes == 200), "lost bytes %u", sb->lost_bytes);
+
+ /*
+ * Step 2. Ack up to 300, although 300 400 is sacked, so this is interpreted
+ * as reneging.
+ */
tc->snd_una = 200;
tcp_rcv_sacks (tc, 300);
if (verbose)
- vlib_cli_output (vm, "\nacked [0, 300] in two steps:\n%U",
+ vlib_cli_output (vm, "\nacked [100, 300] in two steps:\n%U",
format_tcp_scoreboard, sb, tc);
- TCP_TEST ((sb->sacked_bytes == 500), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
TCP_TEST ((sb->lost_bytes == 100), "lost bytes %u", sb->lost_bytes);
- TCP_TEST ((sb->last_bytes_delivered == 100), "last bytes delivered %d",
+ TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
sb->last_bytes_delivered);
+ TCP_TEST ((sb->is_reneging), "is reneging");
- tc->snd_una = 400;
+ /*
+ * Ack [300 500]. Delivers reneged segment [300 400] and reneges bytes
+ * above 500
+ */
+ tc->snd_una = 300;
tcp_rcv_sacks (tc, 500);
if (verbose)
vlib_cli_output (vm, "\nacked [400, 500]:\n%U", format_tcp_scoreboard, sb,
tc);
TCP_TEST ((pool_elts (sb->holes) == 0),
"scoreboard has %d elements", pool_elts (sb->holes));
- TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->sacked_bytes == 500), "sacked bytes %d", sb->sacked_bytes);
TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
sb->last_sacked_bytes);
- TCP_TEST ((sb->last_bytes_delivered == 500), "last bytes delivered %d",
+ TCP_TEST ((sb->last_bytes_delivered == 100), "last bytes delivered %d",
sb->last_bytes_delivered);
- TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
- TCP_TEST ((sb->snd_una_adv == 500), "snd_una_adv %u", sb->snd_una_adv);
+ TCP_TEST ((sb->is_reneging), "is reneging");
TCP_TEST ((sb->head == TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
TCP_TEST ((sb->tail == TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
/*
- * Re-ack high sacked, to make sure last_bytes_delivered and
- * snd_una_adv are 0-ed
+ * Ack up to 1000 to deliver all bytes
*/
+ tc->snd_una = 500;
tcp_rcv_sacks (tc, 1000);
if (verbose)
vlib_cli_output (vm, "\nAck high sacked:\n%U", format_tcp_scoreboard, sb,
tc);
- TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
+ TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
+ sb->last_sacked_bytes);
+ TCP_TEST ((sb->last_bytes_delivered == 500), "last bytes delivered %d",
sb->last_bytes_delivered);
- TCP_TEST ((sb->snd_una_adv == 0), "snd_una_adv %u", sb->snd_una_adv);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
/*
* Add [1200, 1500] and test that [1000, 1200] is lost (bytes condition)
TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
sb->last_bytes_delivered);
TCP_TEST ((sb->lost_bytes == 200), "lost bytes %u", sb->lost_bytes);
- TCP_TEST ((sb->snd_una_adv == 0), "snd_una_adv %u", sb->snd_una_adv);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
+
+ /*
+ * Restart
+ */
+ scoreboard_clear (sb);
+ vec_reset_length (tc->rcv_opts.sacks);
+
+ /*
+ * Inject [100 500]
+ */
+
+ tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
+ tc->snd_una = 0;
+ tc->snd_una_max = 1000;
+ tc->snd_nxt = 1000;
+ sb->high_rxt = 0;
+
+ block.start = 100;
+ block.end = 500;
+ vec_add1 (tc->rcv_opts.sacks, block);
+ tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
+
+ tcp_rcv_sacks (tc, 0);
+
+ TCP_TEST ((sb->sacked_bytes == 400), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 400), "last sacked bytes %d",
+ sb->last_sacked_bytes);
+ TCP_TEST ((!sb->is_reneging), "is not reneging");
+
+ /*
+ * Renege, sack all of the remaining bytes and cover some rxt bytes
+ */
+ sb->high_rxt = 700;
+ tc->rcv_opts.sacks[0].start = 500;
+ tc->rcv_opts.sacks[0].end = 1000;
+
+ tcp_rcv_sacks (tc, 100);
+
+ TCP_TEST ((sb->sacked_bytes == 900), "sacked bytes %d", sb->sacked_bytes);
+ TCP_TEST ((sb->last_sacked_bytes == 500), "last sacked bytes %d",
+ sb->last_sacked_bytes);
+ TCP_TEST (sb->is_reneging, "is reneging");
+ TCP_TEST ((sb->rxt_sacked == 300), "last rxt sacked bytes %d",
+ sb->rxt_sacked);
return 0;
}
tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input)
{
session_main_t *smm = &session_main;
- tcp_main_t *tm = &tcp_main;
transport_connection_t _tc1, *tc1 = &_tc1, _tc2, *tc2 = &_tc2, *tconn;
tcp_connection_t *tc;
session_t *s, *s1;
clib_memset (s, 0, sizeof (*s));
s->session_index = sidx = s - smm->wrk[0].sessions;
- pool_get (tm->connections[0], tc);
- clib_memset (tc, 0, sizeof (*tc));
- tc->connection.c_index = tc - tm->connections[0];
+ tc = tcp_connection_alloc (0);
tc->connection.s_index = s->session_index;
s->connection_index = tc->connection.c_index;
clib_memset (s, 0, sizeof (*s));
s->session_index = s - smm->wrk[0].sessions;
- pool_get (tm->connections[0], tc);
- clib_memset (tc, 0, sizeof (*tc));
- tc->connection.c_index = tc - tm->connections[0];
+ tc = tcp_connection_alloc (0);
tc->connection.s_index = s->session_index;
s->connection_index = tc->connection.c_index;
tcp_connection_t *tc0;
ip4_address_t local, remote;
u16 local_port, remote_port;
- tcp_main_t *tm = vnet_get_tcp_main ();
int is_add = 1;
local_port = clib_host_to_net_u16 (1234);
remote_port = clib_host_to_net_u16 (11234);
- pool_get (tm->connections[0], tc0);
- clib_memset (tc0, 0, sizeof (*tc0));
+ tc0 = tcp_connection_alloc (0);
tc0->state = TCP_STATE_ESTABLISHED;
tc0->rcv_las = 1;
- tc0->c_c_index = tc0 - tm->connections[0];
tc0->c_lcl_port = local_port;
tc0->c_rmt_port = remote_port;
tc0->c_is_ip4 = 1;
tc0->rcv_opts.mss = 1450;
tcp_connection_init_vars (tc0);
- TCP_EVT_DBG (TCP_EVT_OPEN, tc0);
+ TCP_EVT (TCP_EVT_OPEN, tc0);
if (session_stream_accept (&tc0->connection, 0 /* listener index */ ,
0 /* thread index */ , 0 /* notify */ ))
return seq_lt (a, b);
}
-static inline int
-approx_equal (u32 a, u32 b)
-{
- if (b > 0.99 * a && b < 1.01 * a)
- return 1;
- return 0;
-}
-
static int
tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
{
/* Init data structures */
memset (tc, 0, sizeof (*tc));
session_main.wrk[thread_index].last_vlib_time = 1;
- transport_connection_tx_pacer_update (&tc->connection, rate);
+ transport_connection_tx_pacer_update (&tc->connection, rate, 1e6);
tcp_bt_init (tc);
bt = tc->bt;
*/
/* 1) track first burst a time 1 */
- tcp_bt_track_tx (tc);
+ tcp_bt_track_tx (tc, burst);
TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
TCP_TEST (pool_elts (bt->samples) == 1, "should have 1 sample");
TCP_TEST (rs->interval_time == 1, "ack time should be 1");
TCP_TEST (rs->delivered == burst, "delivered should be 100");
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");
+ TCP_TEST (tc->first_tx_time == 1, "first_tx_time %u", tc->first_tx_time);
/* 3) track second burst at time 2 */
- tcp_bt_track_tx (tc);
+ tcp_bt_track_tx (tc, burst);
tc->snd_nxt += burst;
/* 4) track second burst at time 3 */
session_main.wrk[thread_index].last_vlib_time = 3;
- tcp_bt_track_tx (tc);
+ tcp_bt_track_tx (tc, burst);
tc->snd_nxt += burst;
TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
TCP_TEST (rs->interval_time == 2, "ack time should be 2");
TCP_TEST (rs->delivered == 2 * burst, "delivered should be 200");
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");
- TCP_TEST (!(bts->flags & TCP_BTS_IS_APP_LIMITED), "not app limited");
+ TCP_TEST (tc->first_tx_time == 2, "first_tx_time %u", tc->first_tx_time);
/*
* Track retransmissions
snd_una = tc->snd_una;
- /* 1) track first burst a time 4 */
- tcp_bt_track_tx (tc);
+ /* 1) track first burst at time 4 */
+ tcp_bt_track_tx (tc, burst);
tc->snd_nxt += burst;
/* 2) track second burst at time 5 */
session_main.wrk[thread_index].last_vlib_time = 5;
- tcp_bt_track_tx (tc);
+ tcp_bt_track_tx (tc, burst);
tc->snd_nxt += burst;
/* 3) track third burst at time 6 */
session_main.wrk[thread_index].last_vlib_time = 6;
- tcp_bt_track_tx (tc);
+ tcp_bt_track_tx (tc, burst);
tc->snd_nxt += burst;
/* 4) track fourth burst at time 7 */
session_main.wrk[thread_index].last_vlib_time = 7;
/* Limited until last burst is acked */
tc->app_limited = snd_una + 4 * burst - 1;
- tcp_bt_track_tx (tc);
+ tcp_bt_track_tx (tc, burst);
tc->snd_nxt += burst;
/* 5) check delivery rate at time 8
tcp_bt_sample_delivery_rate (tc, rs);
TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
- TCP_TEST (pool_elts (bt->samples) == 4, "there should be 4 samples");
+ TCP_TEST (pool_elts (bt->samples) == 7, "there should be 7 samples %u",
+ pool_elts (bt->samples));
TCP_TEST (tc->delivered_time == 8, "delivered time should be 8");
TCP_TEST (tc->delivered == 3 * burst + 30, "delivered should be %u is %u",
3 * burst + 30, tc->delivered);
TCP_TEST (rs->delivered == 30, "delivered should be 30");
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);
TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
TCP_TEST (!(rs->flags & TCP_BTS_IS_APP_LIMITED), "not app limited");
+ /* All 3 samples have the same delivered number of bytes. The first
+ * sets the first tx time */
+ TCP_TEST (tc->first_tx_time == 4, "first_tx_time %u", tc->first_tx_time);
/* 6) Retransmit and track at time 9
*
tcp_bt_track_rxt (tc, snd_una + 10, snd_una + burst);
TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
/* The retransmit covers everything left from first burst */
- TCP_TEST (pool_elts (bt->samples) == 4, "there should be 4 samples");
+ TCP_TEST (pool_elts (bt->samples) == 7, "there should be 7 samples %u",
+ pool_elts (bt->samples));
tcp_bt_track_rxt (tc, snd_una + burst + 10, snd_una + 2 * burst + 10);
TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
- TCP_TEST (pool_elts (bt->samples) == 5, "there should be 5 samples");
+ TCP_TEST (pool_elts (bt->samples) == 6, "there should be 6 samples %u",
+ pool_elts (bt->samples));
/* Retransmit covers last sample entirely so it should be removed */
tcp_bt_track_rxt (tc, snd_una + 2 * burst + 20, snd_una + 4 * burst);
TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
- TCP_TEST (pool_elts (bt->samples) == 5, "there should be 5 samples");
+ TCP_TEST (pool_elts (bt->samples) == 5, "there should be 5 samples %u",
+ pool_elts (bt->samples));
vec_validate (min_seqs, 4);
min_seqs[0] = snd_una + 10;
tcp_bt_sample_delivery_rate (tc, rs);
TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
- TCP_TEST (pool_elts (bt->samples) == 3, "num samples should be 3 is %u",
+ TCP_TEST (pool_elts (bt->samples) == 5, "num samples should be 5 is %u",
pool_elts (bt->samples));
TCP_TEST (tc->delivered_time == 10, "delivered time should be 10");
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->interval_time == 2, "ack time should be 2 is %.2f",
+ /* A rxt was acked and delivered time for it is 8 (last ack time) so
+ * ack_time is 2 (8 - 10). However, first_tx_time for rxt was 4 and rxt
+ * time 9. Therefore snd_time is 5 (9 - 4)*/
+ TCP_TEST (rs->interval_time == 5, "ack time should be 5 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->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);
TCP_TEST (rs->flags & TCP_BTS_IS_RXT, "is retransmitted");
/* Sample is app limited because of the retransmits */
TCP_TEST (rs->flags & TCP_BTS_IS_APP_LIMITED, "is app limited");
TCP_TEST (tc->app_limited, "app limited should be set");
+ TCP_TEST (tc->first_tx_time == 9, "first_tx_time %u", tc->first_tx_time);
+
/*
* 8) check delivery rate at time 11
TCP_TEST (tc->delivered_time == 11, "delivered time should be 11");
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->interval_time == 3, "ack time should be 3 is %.2f",
+ /* Delivered time at retransmit was 8 so ack_time is 11 - 8 = 3. However,
+ * first_tx_time for rxt was 4 and rxt time was 9. Therefore snd_time
+ * is 9 - 4 = 5 */
+ TCP_TEST (rs->interval_time == 5, "ack time should be 5 is %.2f",
rs->interval_time);
/* delivered_now - delivered_rxt ~ 7 * burst - 3 * burst - 30.
* That's because we didn't retransmit any new segment. */
rs->delivered);
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);
TCP_TEST (rs->flags & TCP_BTS_IS_RXT, "is retransmitted");
TCP_TEST (rs->flags & TCP_BTS_IS_APP_LIMITED, "is app limited");
TCP_TEST (tc->app_limited == 0, "app limited should be cleared");
+ TCP_TEST (tc->first_tx_time == 9, "first_tx_time %u", tc->first_tx_time);
+
+ /*
+ * 9) test flush
+ */
+
+ tcp_bt_track_tx (tc, burst);
+ tc->snd_nxt += burst;
+
+ session_main.wrk[thread_index].last_vlib_time = 12;
+ tcp_bt_track_tx (tc, burst);
+ tc->snd_nxt += burst;
+
+ tcp_bt_flush_samples (tc);
/*
* Cleanup