2 * Copyright (c) 2017-2019 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
15 #include <vnet/tcp/tcp.h>
16 #include <vnet/tcp/tcp_inlines.h>
18 #define TCP_TEST_I(_cond, _comment, _args...) \
20 int _evald = (_cond); \
22 fformat(stderr, "FAIL:%d: " _comment "\n", \
25 fformat(stderr, "PASS:%d: " _comment "\n", \
31 #define TCP_TEST(_cond, _comment, _args...) \
33 if (!TCP_TEST_I(_cond, _comment, ##_args)) { \
38 scoreboard_trace_elt_t sb_trace[] = {};
41 tcp_test_scoreboard_replay (vlib_main_t * vm, unformat_input_t * input)
44 tcp_connection_t _tc, *tc = &_tc;
47 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
49 if (unformat (input, "detail"))
53 clib_error_t *e = clib_error_return
54 (0, "unknown input `%U'", format_unformat_error, input);
55 clib_error_report (e);
60 #if TCP_SCOREBOARD_TRACE
61 tc->sack_sb.trace = sb_trace;
63 s = tcp_scoreboard_replay (s, tc, verbose);
64 vlib_cli_output (vm, "%v", s);
69 tcp_test_sack_rx (vlib_main_t * vm, unformat_input_t * input)
71 tcp_connection_t _tc, *tc = &_tc;
72 sack_scoreboard_t *sb = &tc->sack_sb;
73 sack_block_t *sacks = 0, block;
74 sack_scoreboard_hole_t *hole;
77 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
79 if (unformat (input, "verbose"))
81 else if (unformat (input, "replay"))
82 return tcp_test_scoreboard_replay (vm, input);
85 clib_memset (tc, 0, sizeof (*tc));
87 tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
90 tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
92 scoreboard_init (&tc->sack_sb);
94 for (i = 0; i < 1000 / 100; i++)
96 block.start = i * 100;
97 block.end = (i + 1) * 100;
98 vec_add1 (sacks, block);
105 for (i = 0; i < 1000 / 200; i++)
107 vec_add1 (tc->rcv_opts.sacks, sacks[i * 2]);
109 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
110 tcp_rcv_sacks (tc, 0);
113 vlib_cli_output (vm, "sb after even blocks (mss %u):\n%U",
114 tc->snd_mss, format_tcp_scoreboard, sb, tc);
116 TCP_TEST ((pool_elts (sb->holes) == 5),
117 "scoreboard has %d elements", pool_elts (sb->holes));
119 /* First SACK block should be rejected */
120 hole = scoreboard_first_hole (sb);
121 TCP_TEST ((hole->start == 0 && hole->end == 200),
122 "first hole start %u end %u", hole->start, hole->end);
123 hole = scoreboard_last_hole (sb);
124 TCP_TEST ((hole->start == 900 && hole->end == 1000),
125 "last hole start %u end %u", hole->start, hole->end);
126 TCP_TEST ((sb->sacked_bytes == 400), "sacked bytes %d", sb->sacked_bytes);
127 TCP_TEST ((!sb->is_reneging), "is not reneging");
128 TCP_TEST ((sb->last_sacked_bytes == 400),
129 "last sacked bytes %d", sb->last_sacked_bytes);
130 TCP_TEST ((sb->high_sacked == 900), "high sacked %u", sb->high_sacked);
131 TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
134 * Inject odd blocks except the last
138 vec_reset_length (tc->rcv_opts.sacks);
139 for (i = 0; i < 800 / 200; i++)
141 vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
143 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
144 tcp_rcv_sacks (tc, 0);
147 vlib_cli_output (vm, "\nsb after odd blocks:\n%U", format_tcp_scoreboard,
150 hole = scoreboard_first_hole (sb);
151 TCP_TEST ((pool_elts (sb->holes) == 2),
152 "scoreboard has %d holes", pool_elts (sb->holes));
153 TCP_TEST ((hole->start == 0 && hole->end == 100),
154 "first hole start %u end %u", hole->start, hole->end);
155 TCP_TEST ((sb->sacked_bytes == 800), "sacked bytes %d", sb->sacked_bytes);
156 TCP_TEST ((!sb->is_reneging), "is not reneging");
157 TCP_TEST ((sb->high_sacked == 900), "high sacked %u", sb->high_sacked);
158 TCP_TEST ((sb->last_sacked_bytes == 400),
159 "last sacked bytes %d", sb->last_sacked_bytes);
160 TCP_TEST ((sb->lost_bytes == 100), "lost bytes %u", sb->lost_bytes);
163 * Ack until byte 100 - this is reneging because we should ack until 900
165 tcp_rcv_sacks (tc, 100);
167 vlib_cli_output (vm, "\nack until byte 100:\n%U", format_tcp_scoreboard,
170 TCP_TEST ((pool_elts (sb->holes) == 1), "scoreboard has %d elements",
171 pool_elts (sb->holes));
172 TCP_TEST ((sb->is_reneging), "is reneging");
175 * Make sure we accept duplicate acks while reneging.
182 vec_add1 (tc->rcv_opts.sacks, block);
184 tcp_rcv_sacks (tc, 100);
185 TCP_TEST ((pool_elts (sb->holes) == 1), "scoreboard has %d elements",
186 pool_elts (sb->holes));
187 TCP_TEST ((sb->is_reneging), "is reneging");
188 TCP_TEST ((sb->last_sacked_bytes == 50), "last sacked bytes %d",
189 sb->last_sacked_bytes);
190 TCP_TEST ((sb->rxt_sacked == 50), "last rxt sacked bytes %d",
196 tcp_rcv_sacks (tc, 950);
197 TCP_TEST ((sb->high_sacked == 950), "max sacked byte %u", sb->high_sacked);
198 TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
199 TCP_TEST ((sb->last_sacked_bytes == 0),
200 "last sacked bytes %d", sb->last_sacked_bytes);
201 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
202 TCP_TEST ((!sb->is_reneging), "is not reneging");
205 * Sack [960 970] [980 990]
210 vec_reset_length (tc->rcv_opts.sacks);
213 vec_add1 (tc->rcv_opts.sacks, block);
217 vec_add1 (tc->rcv_opts.sacks, block);
219 tcp_rcv_sacks (tc, 950);
220 TCP_TEST ((sb->high_sacked == 990), "max sacked byte %u", sb->high_sacked);
221 TCP_TEST ((sb->sacked_bytes == 20), "sacked bytes %d", sb->sacked_bytes);
222 TCP_TEST ((sb->last_sacked_bytes == 20),
223 "last sacked bytes %d", sb->last_sacked_bytes);
224 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
225 TCP_TEST ((!sb->is_reneging), "is not reneging");
226 TCP_TEST ((sb->rxt_sacked == 15), "last rxt sacked bytes %d",
230 * Ack up to 960 (reneging) + [961 971]
232 tc->rcv_opts.sacks[0].start = 961;
233 tc->rcv_opts.sacks[0].end = 971;
235 tcp_rcv_sacks (tc, 960);
237 TCP_TEST ((sb->is_reneging), "is reneging");
238 TCP_TEST ((sb->sacked_bytes == 21), "sacked bytes %d", sb->sacked_bytes);
239 TCP_TEST ((sb->last_sacked_bytes == 1),
240 "last sacked bytes %d", sb->last_sacked_bytes);
241 TCP_TEST ((sb->rxt_sacked == 11), "last rxt sacked bytes %d",
243 TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
244 sb->last_bytes_delivered);
247 * Ack up to 960 (reneging) + [961 990]
250 tc->rcv_opts.sacks[0].start = 961;
251 tc->rcv_opts.sacks[0].end = 990;
253 tcp_rcv_sacks (tc, 960);
255 TCP_TEST ((sb->is_reneging), "is reneging");
256 TCP_TEST ((sb->sacked_bytes == 30), "sacked bytes %d", sb->sacked_bytes);
257 TCP_TEST ((sb->last_sacked_bytes == 9),
258 "last sacked bytes %d", sb->last_sacked_bytes);
259 TCP_TEST ((sb->rxt_sacked == 9), "last rxt sacked bytes %d",
263 * Sack remaining bytes [990 1000]
265 tc->rcv_opts.sacks[0].start = 990;
266 tc->rcv_opts.sacks[0].end = 1000;
268 tcp_rcv_sacks (tc, 960);
270 TCP_TEST ((sb->is_reneging), "is reneging");
271 TCP_TEST ((sb->sacked_bytes == 40), "sacked bytes %d", sb->sacked_bytes);
272 TCP_TEST ((sb->last_sacked_bytes == 10),
273 "last sacked bytes %d", sb->last_sacked_bytes);
274 TCP_TEST ((sb->rxt_sacked == 0), "last rxt sacked bytes %d",
276 TCP_TEST (pool_elts (sb->holes) == 0, "no holes left");
279 * Ack up to 970 no sack blocks
281 vec_reset_length (tc->rcv_opts.sacks);
282 tc->rcv_opts.flags &= ~TCP_OPTS_FLAG_SACK;
283 tcp_rcv_sacks (tc, 970);
285 TCP_TEST ((sb->is_reneging), "is reneging");
286 TCP_TEST ((sb->sacked_bytes == 30), "sacked bytes %d", sb->sacked_bytes);
287 TCP_TEST ((sb->last_sacked_bytes == 0),
288 "last sacked bytes %d", sb->last_sacked_bytes);
289 TCP_TEST ((sb->rxt_sacked == 0), "last rxt sacked bytes %d",
296 tcp_rcv_sacks (tc, 1000);
297 TCP_TEST ((sb->high_sacked == 1000), "max sacked byte %u", sb->high_sacked);
298 TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
299 TCP_TEST (sb->last_bytes_delivered == 30, "last bytes delivered %d",
300 sb->last_bytes_delivered);
301 TCP_TEST ((sb->last_sacked_bytes == 0),
302 "last sacked bytes %d", sb->last_sacked_bytes);
303 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
304 TCP_TEST ((!sb->is_reneging), "is not reneging");
310 tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
311 vec_reset_length (tc->rcv_opts.sacks);
315 vec_add1 (tc->rcv_opts.sacks, block);
319 tcp_rcv_sacks (tc, 1000);
322 vlib_cli_output (vm, "\nadd [1200, 1300] snd_una_max 1500, snd_una 1000:"
323 " \n%U", format_tcp_scoreboard, sb, tc);
325 TCP_TEST ((!sb->is_reneging), "is not reneging");
326 TCP_TEST ((pool_elts (sb->holes) == 2),
327 "scoreboard has %d holes", pool_elts (sb->holes));
328 hole = scoreboard_first_hole (sb);
329 TCP_TEST ((hole->start == 1000 && hole->end == 1200),
330 "first hole start %u end %u", hole->start, hole->end);
331 TCP_TEST ((sb->high_sacked == 1300), "max sacked byte %u", sb->high_sacked);
332 hole = scoreboard_last_hole (sb);
333 TCP_TEST ((hole->start == 1300 && hole->end == 1500),
334 "last hole start %u end %u", hole->start, hole->end);
335 TCP_TEST ((sb->sacked_bytes == 100), "sacked bytes %d", sb->sacked_bytes);
336 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
342 vec_reset_length (tc->rcv_opts.sacks);
343 /* Ack up to 1300 to avoid reneging */
344 tcp_rcv_sacks (tc, 1300);
347 vlib_cli_output (vm, "\nsb ack up to byte 1300:\n%U",
348 format_tcp_scoreboard, sb, tc);
350 TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
351 TCP_TEST ((pool_elts (sb->holes) == 1),
352 "scoreboard has %d elements", pool_elts (sb->holes));
353 TCP_TEST ((sb->last_bytes_delivered == 100), "last bytes delivered %d",
354 sb->last_bytes_delivered);
355 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
356 TCP_TEST ((sb->head != TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
357 TCP_TEST ((sb->tail != TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
358 TCP_TEST ((!sb->is_reneging), "is not reneging");
361 * Add some more blocks and then remove all
363 vec_reset_length (tc->rcv_opts.sacks);
366 for (i = 0; i < 5; i++)
368 block.start = i * 100 + 1200;
369 block.end = (i + 1) * 100 + 1200;
370 vec_add1 (tc->rcv_opts.sacks, block);
372 tcp_rcv_sacks (tc, 1900);
374 scoreboard_clear (sb);
376 vlib_cli_output (vm, "\nsb cleared all:\n%U", format_tcp_scoreboard, sb,
379 TCP_TEST ((pool_elts (sb->holes) == 0),
380 "number of holes %d", pool_elts (sb->holes));
381 TCP_TEST ((sb->head == TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
382 TCP_TEST ((sb->tail == TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
385 * Re-inject odd blocks and ack them all
390 vec_reset_length (tc->rcv_opts.sacks);
391 for (i = 0; i < 5; i++)
393 vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
395 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
396 tcp_rcv_sacks (tc, 0);
398 vlib_cli_output (vm, "\nsb added odd blocks snd_una 0 snd_una_max 1000:"
399 "\n%U", format_tcp_scoreboard, sb, tc);
400 TCP_TEST ((pool_elts (sb->holes) == 5),
401 "scoreboard has %d elements", pool_elts (sb->holes));
402 TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
403 hole = scoreboard_last_hole (sb);
404 TCP_TEST ((hole->end == 900), "last hole end %u", hole->end);
405 TCP_TEST ((sb->high_sacked == 1000), "high sacked %u", sb->high_sacked);
408 * Renege bytes from 950 to 1000
410 tcp_rcv_sacks (tc, 950);
413 vlib_cli_output (vm, "\nack [0, 950]:\n%U", format_tcp_scoreboard, sb,
416 TCP_TEST ((pool_elts (sb->holes) == 0), "scoreboard has %d elements",
417 pool_elts (sb->holes));
418 TCP_TEST ((sb->is_reneging), "is reneging");
419 TCP_TEST ((sb->sacked_bytes == 50), "sacked bytes %d", sb->sacked_bytes);
420 TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
421 sb->last_sacked_bytes);
422 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
423 TCP_TEST ((sb->high_sacked == 1000), "high sacked %u", sb->high_sacked);
425 scoreboard_clear (sb);
428 * Inject one block, ack it and overlap hole
436 vec_add1 (tc->rcv_opts.sacks, block);
437 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
439 tcp_rcv_sacks (tc, 0);
442 vlib_cli_output (vm, "\nsb added [100, 500] snd_una 0 snd_una_max 1000:"
443 "\n%U", format_tcp_scoreboard, sb, tc);
445 tcp_rcv_sacks (tc, 800);
448 vlib_cli_output (vm, "\nsb ack [0, 800]:\n%U", format_tcp_scoreboard, sb,
451 TCP_TEST ((pool_elts (sb->holes) == 1),
452 "scoreboard has %d elements", pool_elts (sb->holes));
453 TCP_TEST ((!sb->is_reneging), "is not reneging");
454 TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
455 TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
456 sb->last_sacked_bytes);
457 TCP_TEST ((sb->last_bytes_delivered == 400),
458 "last bytes delivered %d", sb->last_bytes_delivered);
459 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
460 TCP_TEST ((sb->head != TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
461 TCP_TEST ((sb->tail != TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
464 * One hole close to head, patch head, split in two and start acking
467 scoreboard_clear (sb);
473 vec_add1 (tc->rcv_opts.sacks, block);
474 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
476 tcp_rcv_sacks (tc, 0);
478 vlib_cli_output (vm, "\nsb added [500, 1000]:\n%U",
479 format_tcp_scoreboard, sb, tc);
480 TCP_TEST ((sb->sacked_bytes == 500), "sacked bytes %d", sb->sacked_bytes);
481 TCP_TEST ((sb->last_sacked_bytes == 500), "last sacked bytes %d",
482 sb->last_sacked_bytes);
483 TCP_TEST ((sb->lost_bytes == 500), "lost bytes %u", sb->lost_bytes);
485 vec_reset_length (tc->rcv_opts.sacks);
488 vec_add1 (tc->rcv_opts.sacks, block);
489 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
490 tcp_rcv_sacks (tc, 100);
492 vlib_cli_output (vm, "\nsb added [0, 100] [300, 400]:\n%U",
493 format_tcp_scoreboard, sb, tc);
494 TCP_TEST ((pool_elts (sb->holes) == 2),
495 "scoreboard has %d elements", pool_elts (sb->holes));
496 TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
497 TCP_TEST ((sb->last_sacked_bytes == 100), "last sacked bytes %d",
498 sb->last_sacked_bytes);
499 TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
500 sb->last_bytes_delivered);
501 /* Hole should be split in 2 lost holes that add up to 300 */
502 TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
503 TCP_TEST ((sb->reorder == 7), "reorder %u", sb->reorder);
506 * Ack [100 300] in two steps
508 * Step 1. Ack [100 200] which delivers 100 of the bytes lost
511 tcp_rcv_sacks (tc, 200);
512 TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
513 TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
514 sb->last_bytes_delivered);
515 TCP_TEST ((sb->lost_bytes == 200), "lost bytes %u", sb->lost_bytes);
518 * Step 2. Ack up to 300, although 300 400 is sacked, so this is interpreted
522 tcp_rcv_sacks (tc, 300);
524 vlib_cli_output (vm, "\nacked [100, 300] in two steps:\n%U",
525 format_tcp_scoreboard, sb, tc);
526 TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
527 TCP_TEST ((sb->lost_bytes == 100), "lost bytes %u", sb->lost_bytes);
528 TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
529 sb->last_bytes_delivered);
530 TCP_TEST ((sb->is_reneging), "is reneging");
533 * Ack [300 500]. Delivers reneged segment [300 400] and reneges bytes
537 tcp_rcv_sacks (tc, 500);
539 vlib_cli_output (vm, "\nacked [400, 500]:\n%U", format_tcp_scoreboard, sb,
541 TCP_TEST ((pool_elts (sb->holes) == 0),
542 "scoreboard has %d elements", pool_elts (sb->holes));
543 TCP_TEST ((sb->sacked_bytes == 500), "sacked bytes %d", sb->sacked_bytes);
544 TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
545 sb->last_sacked_bytes);
546 TCP_TEST ((sb->last_bytes_delivered == 100), "last bytes delivered %d",
547 sb->last_bytes_delivered);
548 TCP_TEST ((sb->is_reneging), "is reneging");
549 TCP_TEST ((sb->head == TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
550 TCP_TEST ((sb->tail == TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
553 * Ack up to 1000 to deliver all bytes
556 tcp_rcv_sacks (tc, 1000);
558 vlib_cli_output (vm, "\nAck high sacked:\n%U", format_tcp_scoreboard, sb,
560 TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
561 sb->last_sacked_bytes);
562 TCP_TEST ((sb->last_bytes_delivered == 500), "last bytes delivered %d",
563 sb->last_bytes_delivered);
564 TCP_TEST ((!sb->is_reneging), "is not reneging");
567 * Add [1200, 1500] and test that [1000, 1200] is lost (bytes condition)
568 * snd_una = 1000 and snd_una_max = 1600
572 vec_reset_length (tc->rcv_opts.sacks);
575 vec_add1 (tc->rcv_opts.sacks, block);
576 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
577 tcp_rcv_sacks (tc, 1000);
579 vlib_cli_output (vm, "\nacked [1200, 1500] test first hole is lost:\n%U",
580 format_tcp_scoreboard, sb, tc);
581 TCP_TEST ((pool_elts (sb->holes) == 2), "scoreboard has %d elements",
582 pool_elts (sb->holes));
583 TCP_TEST ((sb->sacked_bytes == 300), "sacked bytes %d", sb->sacked_bytes);
584 TCP_TEST ((sb->last_sacked_bytes == 300), "last sacked bytes %d",
585 sb->last_sacked_bytes);
586 TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
587 sb->last_bytes_delivered);
588 /* No bytes lost because of reorder */
589 TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
590 TCP_TEST ((sb->reorder == 7), "reorder %u", sb->reorder);
591 TCP_TEST ((!sb->is_reneging), "is not reneging");
596 scoreboard_clear (sb);
597 vec_reset_length (tc->rcv_opts.sacks);
603 tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
610 vec_add1 (tc->rcv_opts.sacks, block);
611 tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
613 tcp_rcv_sacks (tc, 0);
615 TCP_TEST ((sb->sacked_bytes == 400), "sacked bytes %d", sb->sacked_bytes);
616 TCP_TEST ((sb->last_sacked_bytes == 400), "last sacked bytes %d",
617 sb->last_sacked_bytes);
618 TCP_TEST ((!sb->is_reneging), "is not reneging");
621 * Renege, sack all of the remaining bytes and cover some rxt bytes
624 tc->rcv_opts.sacks[0].start = 500;
625 tc->rcv_opts.sacks[0].end = 1000;
627 tcp_rcv_sacks (tc, 100);
629 TCP_TEST ((sb->sacked_bytes == 900), "sacked bytes %d", sb->sacked_bytes);
630 TCP_TEST ((sb->last_sacked_bytes == 500), "last sacked bytes %d",
631 sb->last_sacked_bytes);
632 TCP_TEST (sb->is_reneging, "is reneging");
633 TCP_TEST ((sb->rxt_sacked == 300), "last rxt sacked bytes %d",
639 scoreboard_clear (sb);
640 vec_reset_length (tc->rcv_opts.sacks);
644 * block.start > snd_nxt
645 * && block.start < blk.end
646 * && block.end <= snd_nxt
649 block.start = 2147483647;
650 block.end = 4294967295;
651 vec_add1 (tc->rcv_opts.sacks, block);
652 tc->snd_una = tc->snd_nxt = 1969067947;
654 tcp_rcv_sacks (tc, tc->snd_una);
659 scoreboard_clear (sb);
660 vec_reset_length (tc->rcv_opts.sacks);
666 tcp_test_sack_tx (vlib_main_t * vm, unformat_input_t * input)
668 tcp_connection_t _tc, *tc = &_tc;
670 int i, verbose = 0, expected;
672 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
674 if (unformat (input, "verbose"))
678 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
684 clib_memset (tc, 0, sizeof (*tc));
687 * Add odd sack block pairs
689 for (i = 1; i < 10; i += 2)
691 tcp_update_sack_list (tc, i * 100, (i + 1) * 100);
694 TCP_TEST ((vec_len (tc->snd_sacks) == 5), "sack blocks %d expected %d",
695 vec_len (tc->snd_sacks), 5);
696 TCP_TEST ((tc->snd_sacks[0].start = 900),
697 "first sack block start %u expected %u", tc->snd_sacks[0].start,
701 * Try to add one extra
703 sacks = vec_dup (tc->snd_sacks);
705 tcp_update_sack_list (tc, 1100, 1200);
707 vlib_cli_output (vm, "add new segment [1100, 1200]\n%U",
708 format_tcp_sacks, tc);
709 expected = 5 < TCP_MAX_SACK_BLOCKS ? 6 : 5;
710 TCP_TEST ((vec_len (tc->snd_sacks) == expected),
711 "sack blocks %d expected %d", vec_len (tc->snd_sacks), expected);
712 TCP_TEST ((tc->snd_sacks[0].start == 1100),
713 "first sack block start %u expected %u", tc->snd_sacks[0].start,
717 vec_free (tc->snd_sacks);
718 tc->snd_sacks = sacks;
721 * Overlap first 2 segment
724 tcp_update_sack_list (tc, 300, 300);
726 vlib_cli_output (vm, "overlap first 2 segments:\n%U",
727 format_tcp_sacks, tc);
728 TCP_TEST ((vec_len (tc->snd_sacks) == 3), "sack blocks %d expected %d",
729 vec_len (tc->snd_sacks), 3);
730 TCP_TEST ((tc->snd_sacks[0].start == 900),
731 "first sack block start %u expected %u", tc->snd_sacks[0].start,
737 tcp_update_sack_list (tc, 1100, 1200);
739 vlib_cli_output (vm, "add new segment [1100, 1200]\n%U",
740 format_tcp_sacks, tc);
741 TCP_TEST ((vec_len (tc->snd_sacks) == 4), "sack blocks %d expected %d",
742 vec_len (tc->snd_sacks), 4);
743 TCP_TEST ((tc->snd_sacks[0].start == 1100),
744 "first sack block start %u expected %u", tc->snd_sacks[0].start,
748 * Join middle segments
750 tcp_update_sack_list (tc, 800, 900);
752 vlib_cli_output (vm, "join middle segments [800, 900]\n%U",
753 format_tcp_sacks, tc);
755 TCP_TEST ((vec_len (tc->snd_sacks) == 3), "sack blocks %d expected %d",
756 vec_len (tc->snd_sacks), 3);
757 TCP_TEST ((tc->snd_sacks[0].start == 700),
758 "first sack block start %u expected %u", tc->snd_sacks[0].start,
762 * Advance rcv_nxt to overlap all
765 tcp_update_sack_list (tc, 1200, 1200);
767 vlib_cli_output (vm, "advance rcv_nxt to 1200\n%U", format_tcp_sacks, tc);
768 TCP_TEST ((vec_len (tc->snd_sacks) == 0), "sack blocks %d expected %d",
769 vec_len (tc->snd_sacks), 0);
773 * Add 2 blocks, overwrite first and update rcv_nxt to also remove it
776 vec_reset_length (tc->snd_sacks);
779 tcp_update_sack_list (tc, 100, 200);
780 tcp_update_sack_list (tc, 300, 400);
783 vlib_cli_output (vm, "add [100, 200] [300, 400]\n%U",
784 format_tcp_sacks, tc);
785 TCP_TEST ((vec_len (tc->snd_sacks) == 2),
786 "sack blocks %d expected %d", vec_len (tc->snd_sacks), 2);
787 TCP_TEST ((tc->snd_sacks[0].start == 300),
788 "first sack block start %u expected %u", tc->snd_sacks[0].start,
792 tcp_update_sack_list (tc, 100, 100);
794 vlib_cli_output (vm, "add [100, 200] rcv_nxt = 100\n%U",
795 format_tcp_sacks, tc);
796 TCP_TEST ((vec_len (tc->snd_sacks) == 1),
797 "sack blocks %d expected %d", vec_len (tc->snd_sacks), 1);
798 TCP_TEST ((tc->snd_sacks[0].start == 300),
799 "first sack block start %u expected %u", tc->snd_sacks[0].start,
805 tcp_test_sack (vlib_main_t * vm, unformat_input_t * input)
810 if (unformat_check_input (input) == UNFORMAT_END_OF_INPUT)
812 if (tcp_test_sack_tx (vm, input))
817 if (tcp_test_sack_rx (vm, input))
824 if (unformat (input, "tx"))
826 res = tcp_test_sack_tx (vm, input);
828 else if (unformat (input, "rx"))
830 res = tcp_test_sack_rx (vm, input);
838 tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input)
840 session_main_t *smm = &session_main;
841 transport_connection_t _tc1, *tc1 = &_tc1, _tc2, *tc2 = &_tc2, *tconn;
842 tcp_connection_t *tc;
844 u8 cmp = 0, is_filtered = 0;
848 * Allocate fake session and connection 1
850 pool_get (smm->wrk[0].sessions, s);
851 clib_memset (s, 0, sizeof (*s));
852 s->session_index = sidx = s - smm->wrk[0].sessions;
854 tc = tcp_connection_alloc (0);
855 tc->connection.s_index = s->session_index;
856 s->connection_index = tc->connection.c_index;
858 tc->connection.lcl_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000101);
859 tc->connection.rmt_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000103);
860 tc->connection.lcl_port = 35051;
861 tc->connection.rmt_port = 53764;
862 tc->connection.proto = TRANSPORT_PROTO_TCP;
863 tc->connection.is_ip4 = 1;
864 clib_memcpy_fast (tc1, &tc->connection, sizeof (*tc1));
867 * Allocate fake session and connection 2
869 pool_get (smm->wrk[0].sessions, s);
870 clib_memset (s, 0, sizeof (*s));
871 s->session_index = s - smm->wrk[0].sessions;
873 tc = tcp_connection_alloc (0);
874 tc->connection.s_index = s->session_index;
875 s->connection_index = tc->connection.c_index;
877 tc->connection.lcl_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000101);
878 tc->connection.rmt_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000102);
879 tc->connection.lcl_port = 38225;
880 tc->connection.rmt_port = 53764;
881 tc->connection.proto = TRANSPORT_PROTO_TCP;
882 tc->connection.is_ip4 = 1;
883 clib_memcpy_fast (tc2, &tc->connection, sizeof (*tc2));
886 * Confirm that connection lookup works
889 s1 = pool_elt_at_index (smm->wrk[0].sessions, sidx);
890 session_lookup_add_connection (tc1, session_handle (s1));
891 tconn = session_lookup_connection_wt4 (0, &tc1->lcl_ip.ip4,
893 tc1->lcl_port, tc1->rmt_port,
894 tc1->proto, 0, &is_filtered);
896 TCP_TEST ((tconn != 0), "connection exists");
897 cmp = (memcmp (&tconn->rmt_ip, &tc1->rmt_ip, sizeof (tc1->rmt_ip)) == 0);
898 TCP_TEST ((cmp), "rmt ip is identical %d", cmp);
899 TCP_TEST ((tconn->lcl_port == tc1->lcl_port),
900 "rmt port is identical %d", tconn->lcl_port == tc1->lcl_port);
903 * Non-existing connection lookup should not work
906 tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
908 tc2->lcl_port, tc2->rmt_port,
909 tc2->proto, 0, &is_filtered);
910 TCP_TEST ((tconn == 0), "lookup result should be null");
913 * Delete and lookup again
915 session_lookup_del_connection (tc1);
916 tconn = session_lookup_connection_wt4 (0, &tc1->lcl_ip.ip4,
918 tc1->lcl_port, tc1->rmt_port,
919 tc1->proto, 0, &is_filtered);
920 TCP_TEST ((tconn == 0), "lookup result should be null");
921 tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
923 tc2->lcl_port, tc2->rmt_port,
924 tc2->proto, 0, &is_filtered);
925 TCP_TEST ((tconn == 0), "lookup result should be null");
928 * Re-add and lookup tc2
930 session_lookup_add_connection (tc1, tc1->s_index);
931 tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
933 tc2->lcl_port, tc2->rmt_port,
934 tc2->proto, 0, &is_filtered);
935 TCP_TEST ((tconn == 0), "lookup result should be null");
941 tcp_test_session (vlib_main_t * vm, unformat_input_t * input)
944 tcp_connection_t *tc0;
945 ip4_address_t local, remote;
946 u16 local_port, remote_port;
950 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
952 if (unformat (input, "del"))
954 else if (unformat (input, "add"))
962 local.as_u32 = clib_host_to_net_u32 (0x06000101);
963 remote.as_u32 = clib_host_to_net_u32 (0x06000102);
964 local_port = clib_host_to_net_u16 (1234);
965 remote_port = clib_host_to_net_u16 (11234);
967 tc0 = tcp_connection_alloc (0);
969 tc0->state = TCP_STATE_ESTABLISHED;
971 tc0->c_lcl_port = local_port;
972 tc0->c_rmt_port = remote_port;
974 tc0->c_thread_index = 0;
975 tc0->c_lcl_ip4.as_u32 = local.as_u32;
976 tc0->c_rmt_ip4.as_u32 = remote.as_u32;
977 tc0->rcv_opts.mss = 1450;
978 tcp_connection_init_vars (tc0);
980 TCP_EVT (TCP_EVT_OPEN, tc0);
982 if (session_stream_accept (&tc0->connection, 0 /* listener index */ ,
983 0 /* thread index */ , 0 /* notify */ ))
984 clib_warning ("stream_session_accept failed");
986 session_stream_accept_notify (&tc0->connection);
990 tc0 = tcp_connection_get (0 /* connection index */ , 0 /* thread */ );
991 tc0->state = TCP_STATE_CLOSED;
992 session_transport_closing_notify (&tc0->connection);
999 tbt_seq_lt (u32 a, u32 b)
1001 return seq_lt (a, b);
1005 tcp_test_set_time (u32 thread_index, u32 val)
1007 session_main.wrk[thread_index].last_vlib_time = val;
1008 tcp_set_time_now (&tcp_main.wrk_ctx[thread_index], val);
1012 tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
1014 u32 thread_index = 0, snd_una, *min_seqs = 0;
1015 tcp_rate_sample_t _rs = { 0 }, *rs = &_rs;
1016 tcp_connection_t _tc, *tc = &_tc;
1017 sack_scoreboard_t *sb = &tc->sack_sb;
1018 int __clib_unused verbose = 0, i;
1019 u64 rate = 1000, burst = 100;
1020 sack_block_t *sacks = 0;
1021 tcp_byte_tracker_t *bt;
1022 rb_node_t *root, *rbn;
1023 tcp_bt_sample_t *bts;
1025 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1027 if (unformat (input, "verbose"))
1031 vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1037 /* Init data structures */
1038 memset (tc, 0, sizeof (*tc));
1039 tcp_test_set_time (thread_index, 1);
1040 transport_connection_tx_pacer_update (&tc->connection, rate, 1e6);
1046 * Track simple bursts without rxt
1049 /* 1) track first burst a time 1 */
1050 tcp_bt_track_tx (tc, burst);
1052 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1053 TCP_TEST (pool_elts (bt->samples) == 1, "should have 1 sample");
1054 bts = pool_elt_at_index (bt->samples, bt->head);
1055 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1056 TCP_TEST (bts->next == TCP_BTS_INVALID_INDEX, "next should be invalid");
1057 TCP_TEST (bts->prev == TCP_BTS_INVALID_INDEX, "prev should be invalid");
1058 TCP_TEST (bts->delivered_time == 1, "delivered time should be 1");
1059 TCP_TEST (bts->delivered == 0, "delivered should be 0");
1060 TCP_TEST (!(bts->flags & TCP_BTS_IS_RXT), "not retransmitted");
1061 TCP_TEST (!(bts->flags & TCP_BTS_IS_APP_LIMITED), "not app limited");
1063 /* 2) check delivery rate at time 2 */
1064 tcp_test_set_time (thread_index, 2);
1065 tc->snd_una = tc->snd_nxt = burst;
1066 tc->bytes_acked = burst;
1068 tcp_bt_sample_delivery_rate (tc, rs);
1070 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1071 TCP_TEST (pool_elts (bt->samples) == 0, "sample should've been consumed");
1072 TCP_TEST (tc->delivered_time == 2, "delivered time should be 2");
1073 TCP_TEST (tc->delivered == burst, "delivered should be 100");
1074 TCP_TEST (rs->interval_time == 1, "ack time should be 1");
1075 TCP_TEST (rs->delivered == burst, "delivered should be 100");
1076 TCP_TEST (rs->prior_delivered == 0, "sample delivered should be 0");
1077 TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
1078 TCP_TEST (tc->first_tx_time == 1, "first_tx_time %u", tc->first_tx_time);
1080 /* 3) track second burst at time 2 */
1081 tcp_bt_track_tx (tc, burst);
1082 tc->snd_nxt += burst;
1084 /* 4) track second burst at time 3 */
1085 tcp_test_set_time (thread_index, 3);
1086 tcp_bt_track_tx (tc, burst);
1087 tc->snd_nxt += burst;
1089 TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
1091 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1092 bts = pool_elt_at_index (bt->samples, bt->head);
1093 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1094 TCP_TEST (bts->next == bt->tail, "next should tail");
1096 bts = pool_elt_at_index (bt->samples, bt->tail);
1097 TCP_TEST (bts->min_seq == tc->snd_nxt - burst,
1098 "min seq should be snd_nxt prior to burst");
1099 TCP_TEST (bts->prev == bt->head, "prev should be head");
1101 /* 5) check delivery rate at time 4 */
1102 tcp_test_set_time (thread_index, 4);
1103 tc->snd_una = tc->snd_nxt;
1104 tc->bytes_acked = 2 * burst;
1106 tcp_bt_sample_delivery_rate (tc, rs);
1108 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1109 TCP_TEST (pool_elts (bt->samples) == 0, "sample should've been consumed");
1110 TCP_TEST (tc->delivered_time == 4, "delivered time should be 4");
1111 TCP_TEST (tc->delivered == 3 * burst, "delivered should be 300 is %u",
1113 TCP_TEST (rs->interval_time == 2, "ack time should be 2");
1114 TCP_TEST (rs->delivered == 2 * burst, "delivered should be 200");
1115 TCP_TEST (rs->prior_delivered == burst, "delivered should be 100");
1116 TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
1117 TCP_TEST (tc->first_tx_time == 2, "first_tx_time %u", tc->first_tx_time);
1120 * Track retransmissions
1122 * snd_una should be 300 at this point
1125 snd_una = tc->snd_una;
1127 /* 1) track first burst at time 4 */
1128 tcp_bt_track_tx (tc, burst);
1129 tc->snd_nxt += burst;
1131 /* 2) track second burst at time 5 */
1132 tcp_test_set_time (thread_index, 5);
1133 tcp_bt_track_tx (tc, burst);
1134 tc->snd_nxt += burst;
1136 /* 3) track third burst at time 6 */
1137 tcp_test_set_time (thread_index, 6);
1138 tcp_bt_track_tx (tc, burst);
1139 tc->snd_nxt += burst;
1141 /* 4) track fourth burst at time 7 */
1142 tcp_test_set_time (thread_index, 7);
1143 /* Limited until last burst is acked */
1144 tc->app_limited = snd_una + 4 * burst - 1;
1145 tcp_bt_track_tx (tc, burst);
1146 tc->snd_nxt += burst;
1148 /* 5) check delivery rate at time 8
1150 * tc->snd_una = snd_una + 10
1152 * [snd_una + burst, snd_una + burst + 10]
1153 * [snd_una + 2 * burst + 10, snd_una + 2 * burst + 20]
1155 tcp_test_set_time (thread_index, 8);
1157 tc->bytes_acked = 10;
1158 sb->last_sacked_bytes = 20;
1160 TCP_TEST (pool_elts (bt->samples) == 4, "there should be 4 samples");
1162 vec_validate (sacks, 1);
1163 sacks[0].start = snd_una + burst;
1164 sacks[0].end = snd_una + burst + 10;
1165 sacks[1].start = snd_una + 2 * burst + 10;
1166 sacks[1].end = snd_una + 2 * burst + 20;
1167 tc->rcv_opts.sacks = sacks;
1169 tcp_bt_sample_delivery_rate (tc, rs);
1171 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1172 TCP_TEST (pool_elts (bt->samples) == 7, "there should be 7 samples %u",
1173 pool_elts (bt->samples));
1174 TCP_TEST (tc->delivered_time == 8, "delivered time should be 8");
1175 TCP_TEST (tc->delivered == 3 * burst + 30, "delivered should be %u is %u",
1176 3 * burst + 30, tc->delivered);
1177 /* All 3 samples have the same delivered number of bytes. So the first is
1178 * the reference for delivery estimate. */
1179 TCP_TEST (rs->interval_time == 4, "ack time should be 4 is %.2f",
1181 TCP_TEST (rs->delivered == 30, "delivered should be 30");
1182 TCP_TEST (rs->prior_delivered == 3 * burst,
1183 "sample delivered should be %u", 3 * burst);
1184 TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
1185 TCP_TEST (!(rs->flags & TCP_BTS_IS_APP_LIMITED), "not app limited");
1186 /* All 3 samples have the same delivered number of bytes. The first
1187 * sets the first tx time */
1188 TCP_TEST (tc->first_tx_time == 4, "first_tx_time %u", tc->first_tx_time);
1190 /* 6) Retransmit and track at time 9
1192 * delivered = 3 * burst + 30
1193 * delivered_time = 8 (last ack)
1196 * [snd_una + 10, snd_una + burst]
1197 * [snd_una + burst + 10, snd_una + 2 * burst + 10]
1198 * [snd_una + 2 * burst + 20, snd_una + 4 * burst]
1200 tcp_test_set_time (thread_index, 9);
1202 tcp_bt_track_rxt (tc, snd_una + 10, snd_una + burst);
1203 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1204 /* The retransmit covers everything left from first burst */
1205 TCP_TEST (pool_elts (bt->samples) == 7, "there should be 7 samples %u",
1206 pool_elts (bt->samples));
1208 tcp_bt_track_rxt (tc, snd_una + burst + 10, snd_una + 2 * burst + 10);
1209 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1210 TCP_TEST (pool_elts (bt->samples) == 6, "there should be 6 samples %u",
1211 pool_elts (bt->samples));
1213 /* Retransmit covers last sample entirely so it should be removed */
1214 tcp_bt_track_rxt (tc, snd_una + 2 * burst + 20, snd_una + 4 * burst);
1215 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1216 TCP_TEST (pool_elts (bt->samples) == 5, "there should be 5 samples %u",
1217 pool_elts (bt->samples));
1219 vec_validate (min_seqs, 4);
1220 min_seqs[0] = snd_una + 10;
1221 min_seqs[1] = snd_una + burst;
1222 min_seqs[2] = snd_una + burst + 10;
1223 min_seqs[3] = snd_una + 2 * burst + 10;
1224 min_seqs[4] = snd_una + 2 * burst + 20;
1226 root = bt->sample_lookup.nodes + bt->sample_lookup.root;
1227 bts = bt->samples + bt->head;
1228 for (i = 0; i < vec_len (min_seqs); i++)
1230 if (bts->min_seq != min_seqs[i])
1231 TCP_TEST (0, "should be %u is %u", min_seqs[i], bts->min_seq);
1232 rbn = rb_tree_search_subtree_custom (&bt->sample_lookup, root,
1233 bts->min_seq, tbt_seq_lt);
1234 if (rbn->opaque != bts - bt->samples)
1235 TCP_TEST (0, "lookup should work");
1236 bts = bt->samples + bts->next;
1239 /* 7) check delivery rate at time 10
1241 * tc->snd_una = snd_una + 2 * burst
1243 * [snd_una + 2 * burst + 20, snd_una + 2 * burst + 30]
1244 * [snd_una + 2 * burst + 50, snd_una + 2 * burst + 60]
1246 tcp_test_set_time (thread_index, 10);
1247 tc->snd_una = snd_una + 2 * burst;
1248 tc->bytes_acked = 2 * burst - 10;
1249 sb->last_sacked_bytes = 20;
1251 sacks[0].start = snd_una + 2 * burst + 20;
1252 sacks[0].end = snd_una + 2 * burst + 30;
1253 sacks[1].start = snd_una + 2 * burst + 50;
1254 sacks[1].end = snd_una + 2 * burst + 60;
1256 tcp_bt_sample_delivery_rate (tc, rs);
1258 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1259 TCP_TEST (pool_elts (bt->samples) == 5, "num samples should be 5 is %u",
1260 pool_elts (bt->samples));
1261 TCP_TEST (tc->delivered_time == 10, "delivered time should be 10");
1262 TCP_TEST (tc->delivered == 5 * burst + 40, "delivered should be %u is %u",
1263 5 * burst + 40, tc->delivered);
1264 /* A rxt was acked and delivered time for it is 8 (last ack time) so
1265 * ack_time is 2 (8 - 10). However, first_tx_time for rxt was 4 and rxt
1266 * time 9. Therefore snd_time is 5 (9 - 4)*/
1267 TCP_TEST (rs->interval_time == 5, "ack time should be 5 is %.2f",
1269 /* delivered_now - delivered_rxt ~ 5 * burst + 40 - 3 * burst - 30 */
1270 TCP_TEST (rs->delivered == 2 * burst + 10, "delivered should be 210 is %u",
1272 TCP_TEST (rs->prior_delivered == 3 * burst + 30,
1273 "sample delivered should be %u", 3 * burst + 30);
1274 TCP_TEST (rs->flags & TCP_BTS_IS_RXT, "is retransmitted");
1275 /* Sample is app limited because of the retransmits */
1276 TCP_TEST (rs->flags & TCP_BTS_IS_APP_LIMITED, "is app limited");
1277 TCP_TEST (tc->app_limited, "app limited should be set");
1278 TCP_TEST (tc->first_tx_time == 9, "first_tx_time %u", tc->first_tx_time);
1282 * 8) check delivery rate at time 11
1284 tcp_test_set_time (thread_index, 11);
1285 tc->snd_una = tc->snd_nxt;
1286 tc->bytes_acked = 2 * burst;
1287 sb->last_sacked_bytes = 0;
1288 sb->last_bytes_delivered = 40;
1290 memset (rs, 0, sizeof (*rs));
1291 tcp_bt_sample_delivery_rate (tc, rs);
1293 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1294 TCP_TEST (pool_elts (bt->samples) == 0, "num samples should be 0 is %u",
1295 pool_elts (bt->samples));
1296 TCP_TEST (tc->delivered_time == 11, "delivered time should be 11");
1297 TCP_TEST (tc->delivered == 7 * burst, "delivered should be %u is %u",
1298 7 * burst, tc->delivered);
1299 /* Delivered time at retransmit was 8 so ack_time is 11 - 8 = 3. However,
1300 * first_tx_time for rxt was 4 and rxt time was 9. Therefore snd_time
1302 TCP_TEST (rs->interval_time == 5, "ack time should be 5 is %.2f",
1304 /* delivered_now - delivered_rxt ~ 7 * burst - 3 * burst - 30.
1305 * That's because we didn't retransmit any new segment. */
1306 TCP_TEST (rs->delivered == 4 * burst - 30, "delivered should be 160 is %u",
1308 TCP_TEST (rs->prior_delivered == 3 * burst + 30,
1309 "sample delivered should be %u", 3 * burst + 30);
1310 TCP_TEST (rs->flags & TCP_BTS_IS_RXT, "is retransmitted");
1311 TCP_TEST (rs->flags & TCP_BTS_IS_APP_LIMITED, "is app limited");
1312 TCP_TEST (tc->app_limited == 0, "app limited should be cleared");
1313 TCP_TEST (tc->first_tx_time == 9, "first_tx_time %u", tc->first_tx_time);
1319 tcp_bt_track_tx (tc, burst);
1320 tc->snd_nxt += burst;
1322 tcp_test_set_time (thread_index, 12);
1323 tcp_bt_track_tx (tc, burst);
1324 tc->snd_nxt += burst;
1326 tcp_bt_flush_samples (tc);
1332 vec_free (min_seqs);
1333 tcp_bt_cleanup (tc);
1338 tcp_test_bt (vlib_main_t * vm, unformat_input_t * input)
1340 u32 thread_index = 0;
1341 tcp_rate_sample_t _rs = { 0 }, *rs = &_rs;
1342 tcp_connection_t _tc, *tc = &_tc;
1343 int __clib_unused verbose = 0, i;
1344 tcp_byte_tracker_t *bt;
1345 tcp_bt_sample_t *bts;
1349 /* Init data structures */
1350 memset (tc, 0, sizeof (*tc));
1354 /* 1) track first burst at time 1 */
1355 /* [] --> [0:100] */
1356 session_main.wrk[thread_index].last_vlib_time = 1;
1357 tcp_bt_track_tx (tc, 100);
1360 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1361 TCP_TEST (pool_elts (bt->samples) == 1, "should have 1 sample");
1362 bts = pool_elt_at_index (bt->samples, bt->head);
1364 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1365 TCP_TEST (bts->next == TCP_BTS_INVALID_INDEX, "next should be invalid");
1366 TCP_TEST (bts->prev == TCP_BTS_INVALID_INDEX, "prev should be invalid");
1367 TCP_TEST (bts->tx_time == 1, "tx time should be 1");
1368 TCP_TEST (!(bts->flags & TCP_BTS_IS_RXT), "not retransmitted");
1369 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1371 /* 2) track second butst at time 2 */
1372 /* --> [0:100][100:200] */
1373 session_main.wrk[thread_index].last_vlib_time = 2;
1374 tcp_bt_track_tx (tc, 100);
1377 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1378 TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
1379 bts = pool_elt_at_index (bt->samples, bt->head);
1380 TCP_TEST (head == bt->head, "head is not updated");
1381 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1382 TCP_TEST (bts->tx_time == 1, "tx time of head should be 1");
1384 /* 3) acked partially at time 3 */
1387 session_main.wrk[thread_index].last_vlib_time = 3;
1389 tc->bytes_acked = 150;
1390 tc->sack_sb.last_sacked_bytes = 0;
1391 tcp_bt_sample_delivery_rate (tc, rs);
1393 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1394 TCP_TEST (pool_elts (bt->samples) == 1, "should have 1 sample");
1395 TCP_TEST (head != bt->head, "head is updated");
1397 bts = pool_elt_at_index (bt->samples, bt->head);
1398 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1399 TCP_TEST (bts->tx_time == 2, "tx time should be 2");
1401 /* 4) track another burst at time 4 */
1402 /* --> [150:200][200:300] */
1403 session_main.wrk[thread_index].last_vlib_time = 4;
1404 tcp_bt_track_tx (tc, 100);
1407 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1408 TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
1409 bts = pool_elt_at_index (bt->samples, bt->head);
1410 TCP_TEST (head == bt->head, "head is not updated");
1411 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1412 TCP_TEST (bts->tx_time == 2, "tx time of head should be 2");
1414 /* 5) track another burst at time 5 */
1415 /* --> [150:200][200:300][300:400] */
1416 session_main.wrk[thread_index].last_vlib_time = 5;
1417 tcp_bt_track_tx (tc, 100);
1420 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1421 TCP_TEST (pool_elts (bt->samples) == 3, "should have 3 samples");
1422 bts = pool_elt_at_index (bt->samples, bt->head);
1423 TCP_TEST (head == bt->head, "head is not updated");
1424 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1425 TCP_TEST (bts->tx_time == 2, "tx time of head should be 2");
1427 /* 6) acked with SACK option at time 6 */
1428 /* ACK:250 + SACK[350:400] */
1429 /* --> [250:300][300:350][350:400/sacked] */
1430 session_main.wrk[thread_index].last_vlib_time = 6;
1432 tc->bytes_acked = 100;
1433 tc->sack_sb.last_sacked_bytes = 50;
1434 vec_add2 (tc->rcv_opts.sacks, blk, 1);
1437 tcp_bt_sample_delivery_rate (tc, rs);
1439 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1440 TCP_TEST (pool_elts (bt->samples) == 3, "should have 3 samples");
1441 TCP_TEST (head != bt->head, "head is updated");
1443 bts = pool_elt_at_index (bt->samples, bt->head);
1444 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1445 TCP_TEST (bts->tx_time == 4, "tx time of head should be 4");
1446 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1447 bts = pool_elt_at_index (bt->samples, bts->next);
1448 TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1449 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1450 bts = pool_elt_at_index (bt->samples, bt->tail);
1451 TCP_TEST (bts->tx_time == 5, "tx time of tail should be 5");
1452 TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1454 /* 7) track another burst at time 7 */
1455 /* --> [250:300][300:350][350:400/sacked][400-500] */
1456 session_main.wrk[thread_index].last_vlib_time = 7;
1457 tcp_bt_track_tx (tc, 100);
1460 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1461 TCP_TEST (pool_elts (bt->samples) == 4, "should have 4 samples");
1462 bts = pool_elt_at_index (bt->samples, bt->head);
1463 TCP_TEST (head == bt->head, "head is not updated");
1464 bts = pool_elt_at_index (bt->samples, bt->head);
1465 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1466 TCP_TEST (bts->tx_time == 4, "tx time of head should be 4");
1467 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1468 bts = pool_elt_at_index (bt->samples, bts->next);
1469 TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1470 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1471 bts = pool_elt_at_index (bt->samples, bts->next);
1472 TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1473 TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1474 bts = pool_elt_at_index (bt->samples, bt->tail);
1475 TCP_TEST (bts->tx_time == 7, "tx time of tail should be 7");
1476 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1478 /* 8) retransmit lost one at time 8 */
1479 /* retransmit [250:300] */
1480 /* --> [250:300][300:350][350:400/sacked][400-500] */
1481 session_main.wrk[thread_index].last_vlib_time = 8;
1482 tcp_bt_track_rxt (tc, 250, 300);
1483 tcp_bt_sample_delivery_rate (tc, rs);
1485 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1486 TCP_TEST (pool_elts (bt->samples) == 4, "should have 4 samples");
1487 TCP_TEST (head == bt->head, "head is not updated");
1488 bts = pool_elt_at_index (bt->samples, bt->head);
1489 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1490 TCP_TEST (bts->tx_time == 8, "tx time of head should be 8");
1491 bts = pool_elt_at_index (bt->samples, bts->next);
1492 TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1493 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1494 bts = pool_elt_at_index (bt->samples, bts->next);
1495 TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1496 TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1497 bts = pool_elt_at_index (bt->samples, bt->tail);
1498 TCP_TEST (bts->tx_time == 7, "tx time of tail should be 7");
1499 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1501 /* 9) acked with SACK option at time 9 */
1502 /* ACK:350 + SACK[420:450] */
1503 /* --> [400:420][420:450/sacked][450:400] */
1504 session_main.wrk[thread_index].last_vlib_time = 6;
1506 tc->bytes_acked = 150;
1507 tc->sack_sb.last_sacked_bytes = 30;
1508 vec_add2 (tc->rcv_opts.sacks, blk, 1);
1511 tcp_bt_sample_delivery_rate (tc, rs);
1513 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1514 TCP_TEST (pool_elts (bt->samples) == 3, "should have 3 samples");
1515 TCP_TEST (head != bt->head, "head is updated");
1517 bts = pool_elt_at_index (bt->samples, bt->head);
1518 TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1519 TCP_TEST (bts->min_seq == 400 && bts->max_seq == 420, "bts [400:420]");
1520 TCP_TEST (bts->tx_time == 7, "tx time of head should be 7");
1521 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1522 bts = pool_elt_at_index (bt->samples, bts->next);
1523 TCP_TEST (bts->min_seq == 420 && bts->max_seq == 450, "bts [420:450]");
1524 TCP_TEST (bts->tx_time == 7, "tx time of head should be 7");
1525 TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1526 bts = pool_elt_at_index (bt->samples, bts->next);
1527 TCP_TEST (bts->min_seq == 450 && bts->max_seq == 500, "bts [450:500]");
1528 TCP_TEST (bts->tx_time == 7, "tx time of head should be 7");
1529 TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1531 /* 10) acked partially at time 10 */
1534 session_main.wrk[thread_index].last_vlib_time = 3;
1536 tc->bytes_acked = 100;
1537 tc->sack_sb.last_sacked_bytes = 0;
1538 tcp_bt_sample_delivery_rate (tc, rs);
1540 TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1541 TCP_TEST (pool_elts (bt->samples) == 0, "should have 0 samples");
1542 TCP_TEST (bt->head == TCP_BTS_INVALID_INDEX, "bt->head is invalidated");
1543 TCP_TEST (tc->snd_una == tc->snd_nxt, "snd_una == snd_nxt");
1548 static clib_error_t *
1549 tcp_test (vlib_main_t * vm,
1550 unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1554 vnet_session_enable_disable (vm, 1);
1556 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1558 if (unformat (input, "sack"))
1560 res = tcp_test_sack (vm, input);
1562 else if (unformat (input, "session"))
1564 res = tcp_test_session (vm, input);
1566 else if (unformat (input, "lookup"))
1568 res = tcp_test_lookup (vm, input);
1570 else if (unformat (input, "delivery"))
1572 res = tcp_test_delivery (vm, input);
1574 else if (unformat (input, "bt"))
1576 res = tcp_test_bt (vm, input);
1578 else if (unformat (input, "all"))
1580 if ((res = tcp_test_sack (vm, input)))
1582 if ((res = tcp_test_lookup (vm, input)))
1584 if ((res = tcp_test_delivery (vm, input)))
1593 return clib_error_return (0, "TCP unit test failed");
1597 VLIB_CLI_COMMAND (tcp_test_command, static) =
1600 .short_help = "internal tcp unit tests",
1601 .function = tcp_test,
1605 * fd.io coding-style-patch-verification: ON
1608 * eval: (c-set-style "gnu")