crypto crypto-openssl: support hashing operations
[vpp.git] / src / plugins / unittest / tcp_test.c
1 /*
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:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
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.
14  */
15 #include <vnet/tcp/tcp.h>
16 #include <vnet/tcp/tcp_inlines.h>
17
18 #define TCP_TEST_I(_cond, _comment, _args...)                   \
19 ({                                                              \
20   int _evald = (_cond);                                         \
21   if (!(_evald)) {                                              \
22     fformat(stderr, "FAIL:%d: " _comment "\n",                  \
23             __LINE__, ##_args);                                 \
24   } else {                                                      \
25     fformat(stderr, "PASS:%d: " _comment "\n",                  \
26             __LINE__, ##_args);                                 \
27   }                                                             \
28   _evald;                                                       \
29 })
30
31 #define TCP_TEST(_cond, _comment, _args...)                     \
32 {                                                               \
33     if (!TCP_TEST_I(_cond, _comment, ##_args)) {                \
34         return 1;                                               \
35     }                                                           \
36 }
37
38 /* *INDENT-OFF* */
39 scoreboard_trace_elt_t sb_trace[] = {};
40 /* *INDENT-ON* */
41
42 static int
43 tcp_test_scoreboard_replay (vlib_main_t * vm, unformat_input_t * input)
44 {
45   int verbose = 0;
46   tcp_connection_t _tc, *tc = &_tc;
47   u8 *s = 0;
48
49   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
50     {
51       if (unformat (input, "detail"))
52         verbose = 1;
53       else
54         {
55           clib_error_t *e = clib_error_return
56             (0, "unknown input `%U'", format_unformat_error, input);
57           clib_error_report (e);
58           return -1;
59         }
60     }
61
62 #if TCP_SCOREBOARD_TRACE
63   tc->sack_sb.trace = sb_trace;
64 #endif
65   s = tcp_scoreboard_replay (s, tc, verbose);
66   vlib_cli_output (vm, "%v", s);
67   return 0;
68 }
69
70 static int
71 tcp_test_sack_rx (vlib_main_t * vm, unformat_input_t * input)
72 {
73   tcp_connection_t _tc, *tc = &_tc;
74   sack_scoreboard_t *sb = &tc->sack_sb;
75   sack_block_t *sacks = 0, block;
76   sack_scoreboard_hole_t *hole;
77   int i, verbose = 0;
78
79   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
80     {
81       if (unformat (input, "verbose"))
82         verbose = 1;
83       else if (unformat (input, "replay"))
84         return tcp_test_scoreboard_replay (vm, input);
85     }
86
87   clib_memset (tc, 0, sizeof (*tc));
88
89   tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
90   tc->snd_una = 0;
91   tc->snd_nxt = 1000;
92   tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
93   tc->snd_mss = 150;
94   scoreboard_init (&tc->sack_sb);
95
96   for (i = 0; i < 1000 / 100; i++)
97     {
98       block.start = i * 100;
99       block.end = (i + 1) * 100;
100       vec_add1 (sacks, block);
101     }
102
103   /*
104    * Inject even blocks
105    */
106
107   for (i = 0; i < 1000 / 200; i++)
108     {
109       vec_add1 (tc->rcv_opts.sacks, sacks[i * 2]);
110     }
111   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
112   tcp_rcv_sacks (tc, 0);
113
114   if (verbose)
115     vlib_cli_output (vm, "sb after even blocks (mss %u):\n%U",
116                      tc->snd_mss, format_tcp_scoreboard, sb, tc);
117
118   TCP_TEST ((pool_elts (sb->holes) == 5),
119             "scoreboard has %d elements", pool_elts (sb->holes));
120
121   /* First SACK block should be rejected */
122   hole = scoreboard_first_hole (sb);
123   TCP_TEST ((hole->start == 0 && hole->end == 200),
124             "first hole start %u end %u", hole->start, hole->end);
125   hole = scoreboard_last_hole (sb);
126   TCP_TEST ((hole->start == 900 && hole->end == 1000),
127             "last hole start %u end %u", hole->start, hole->end);
128   TCP_TEST ((sb->sacked_bytes == 400), "sacked bytes %d", sb->sacked_bytes);
129   TCP_TEST ((!sb->is_reneging), "is not reneging");
130   TCP_TEST ((sb->last_sacked_bytes == 400),
131             "last sacked bytes %d", sb->last_sacked_bytes);
132   TCP_TEST ((sb->high_sacked == 900), "high sacked %u", sb->high_sacked);
133   TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
134
135   /*
136    * Inject odd blocks except the last
137    *
138    */
139
140   vec_reset_length (tc->rcv_opts.sacks);
141   for (i = 0; i < 800 / 200; i++)
142     {
143       vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
144     }
145   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
146   tcp_rcv_sacks (tc, 0);
147
148   if (verbose)
149     vlib_cli_output (vm, "\nsb after odd blocks:\n%U", format_tcp_scoreboard,
150                      sb, tc);
151
152   hole = scoreboard_first_hole (sb);
153   TCP_TEST ((pool_elts (sb->holes) == 2),
154             "scoreboard has %d holes", pool_elts (sb->holes));
155   TCP_TEST ((hole->start == 0 && hole->end == 100),
156             "first hole start %u end %u", hole->start, hole->end);
157   TCP_TEST ((sb->sacked_bytes == 800), "sacked bytes %d", sb->sacked_bytes);
158   TCP_TEST ((!sb->is_reneging), "is not reneging");
159   TCP_TEST ((sb->high_sacked == 900), "high sacked %u", sb->high_sacked);
160   TCP_TEST ((sb->last_sacked_bytes == 400),
161             "last sacked bytes %d", sb->last_sacked_bytes);
162   TCP_TEST ((sb->lost_bytes == 100), "lost bytes %u", sb->lost_bytes);
163
164   /*
165    *  Ack until byte 100 - this is reneging because we should ack until 900
166    */
167   tcp_rcv_sacks (tc, 100);
168   if (verbose)
169     vlib_cli_output (vm, "\nack until byte 100:\n%U", format_tcp_scoreboard,
170                      sb, tc);
171
172   TCP_TEST ((pool_elts (sb->holes) == 1), "scoreboard has %d elements",
173             pool_elts (sb->holes));
174   TCP_TEST ((sb->is_reneging), "is reneging");
175
176   /*
177    * Make sure we accept duplicate acks while reneging.
178    */
179   tc->snd_una = 100;
180   sb->high_rxt = 950;
181
182   block.start = 900;
183   block.end = 950;
184   vec_add1 (tc->rcv_opts.sacks, block);
185
186   tcp_rcv_sacks (tc, 100);
187   TCP_TEST ((pool_elts (sb->holes) == 1), "scoreboard has %d elements",
188             pool_elts (sb->holes));
189   TCP_TEST ((sb->is_reneging), "is reneging");
190   TCP_TEST ((sb->last_sacked_bytes == 50), "last sacked bytes %d",
191             sb->last_sacked_bytes);
192   TCP_TEST ((sb->rxt_sacked == 50), "last rxt sacked bytes %d",
193             sb->rxt_sacked);
194
195   /*
196    * Sack all up to 950
197    */
198   tcp_rcv_sacks (tc, 950);
199   TCP_TEST ((sb->high_sacked == 950), "max sacked byte %u", sb->high_sacked);
200   TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
201   TCP_TEST ((sb->last_sacked_bytes == 0),
202             "last sacked bytes %d", sb->last_sacked_bytes);
203   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
204   TCP_TEST ((!sb->is_reneging), "is not reneging");
205
206   /*
207    * Sack [960 970] [980 990]
208    */
209   sb->high_rxt = 985;
210
211   tc->snd_una = 950;
212   vec_reset_length (tc->rcv_opts.sacks);
213   block.start = 960;
214   block.end = 970;
215   vec_add1 (tc->rcv_opts.sacks, block);
216
217   block.start = 980;
218   block.end = 990;
219   vec_add1 (tc->rcv_opts.sacks, block);
220
221   tcp_rcv_sacks (tc, 950);
222   TCP_TEST ((sb->high_sacked == 990), "max sacked byte %u", sb->high_sacked);
223   TCP_TEST ((sb->sacked_bytes == 20), "sacked bytes %d", sb->sacked_bytes);
224   TCP_TEST ((sb->last_sacked_bytes == 20),
225             "last sacked bytes %d", sb->last_sacked_bytes);
226   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
227   TCP_TEST ((!sb->is_reneging), "is not reneging");
228   TCP_TEST ((sb->rxt_sacked == 15), "last rxt sacked bytes %d",
229             sb->rxt_sacked);
230
231   /*
232    * Ack up to 960 (reneging) + [961 971]
233    */
234   tc->rcv_opts.sacks[0].start = 961;
235   tc->rcv_opts.sacks[0].end = 971;
236
237   tcp_rcv_sacks (tc, 960);
238
239   TCP_TEST ((sb->is_reneging), "is reneging");
240   TCP_TEST ((sb->sacked_bytes == 21), "sacked bytes %d", sb->sacked_bytes);
241   TCP_TEST ((sb->last_sacked_bytes == 1),
242             "last sacked bytes %d", sb->last_sacked_bytes);
243   TCP_TEST ((sb->rxt_sacked == 11), "last rxt sacked bytes %d",
244             sb->rxt_sacked);
245   TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
246             sb->last_bytes_delivered);
247
248   /*
249    * Ack up to 960 (reneging) + [961 990]
250    */
251   tc->snd_una = 960;
252   tc->rcv_opts.sacks[0].start = 961;
253   tc->rcv_opts.sacks[0].end = 990;
254
255   tcp_rcv_sacks (tc, 960);
256
257   TCP_TEST ((sb->is_reneging), "is reneging");
258   TCP_TEST ((sb->sacked_bytes == 30), "sacked bytes %d", sb->sacked_bytes);
259   TCP_TEST ((sb->last_sacked_bytes == 9),
260             "last sacked bytes %d", sb->last_sacked_bytes);
261   TCP_TEST ((sb->rxt_sacked == 9), "last rxt sacked bytes %d",
262             sb->rxt_sacked);
263
264   /*
265    * Sack remaining bytes [990 1000]
266    */
267   tc->rcv_opts.sacks[0].start = 990;
268   tc->rcv_opts.sacks[0].end = 1000;
269
270   tcp_rcv_sacks (tc, 960);
271
272   TCP_TEST ((sb->is_reneging), "is reneging");
273   TCP_TEST ((sb->sacked_bytes == 40), "sacked bytes %d", sb->sacked_bytes);
274   TCP_TEST ((sb->last_sacked_bytes == 10),
275             "last sacked bytes %d", sb->last_sacked_bytes);
276   TCP_TEST ((sb->rxt_sacked == 0), "last rxt sacked bytes %d",
277             sb->rxt_sacked);
278   TCP_TEST (pool_elts (sb->holes) == 0, "no holes left");
279
280   /*
281    * Ack up to 970 no sack blocks
282    */
283   vec_reset_length (tc->rcv_opts.sacks);
284   tc->rcv_opts.flags &= ~TCP_OPTS_FLAG_SACK;
285   tcp_rcv_sacks (tc, 970);
286
287   TCP_TEST ((sb->is_reneging), "is reneging");
288   TCP_TEST ((sb->sacked_bytes == 30), "sacked bytes %d", sb->sacked_bytes);
289   TCP_TEST ((sb->last_sacked_bytes == 0),
290             "last sacked bytes %d", sb->last_sacked_bytes);
291   TCP_TEST ((sb->rxt_sacked == 0), "last rxt sacked bytes %d",
292             sb->rxt_sacked);
293
294   /*
295    * Ack all up to 1000
296    */
297   tc->snd_una = 970;
298   tcp_rcv_sacks (tc, 1000);
299   TCP_TEST ((sb->high_sacked == 1000), "max sacked byte %u", sb->high_sacked);
300   TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
301   TCP_TEST (sb->last_bytes_delivered == 30, "last bytes delivered %d",
302             sb->last_bytes_delivered);
303   TCP_TEST ((sb->last_sacked_bytes == 0),
304             "last sacked bytes %d", sb->last_sacked_bytes);
305   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
306   TCP_TEST ((!sb->is_reneging), "is not reneging");
307
308   /*
309    * Add new block
310    */
311   tc->flags = 0;
312   tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
313   vec_reset_length (tc->rcv_opts.sacks);
314
315   block.start = 1200;
316   block.end = 1300;
317   vec_add1 (tc->rcv_opts.sacks, block);
318
319   tc->snd_una = 1000;
320   tc->snd_nxt = 1500;
321   tcp_rcv_sacks (tc, 1000);
322
323   if (verbose)
324     vlib_cli_output (vm, "\nadd [1200, 1300] snd_una_max 1500, snd_una 1000:"
325                      " \n%U", format_tcp_scoreboard, sb, tc);
326
327   TCP_TEST ((!sb->is_reneging), "is not reneging");
328   TCP_TEST ((pool_elts (sb->holes) == 2),
329             "scoreboard has %d holes", pool_elts (sb->holes));
330   hole = scoreboard_first_hole (sb);
331   TCP_TEST ((hole->start == 1000 && hole->end == 1200),
332             "first hole start %u end %u", hole->start, hole->end);
333   TCP_TEST ((sb->high_sacked == 1300), "max sacked byte %u", sb->high_sacked);
334   hole = scoreboard_last_hole (sb);
335   TCP_TEST ((hole->start == 1300 && hole->end == 1500),
336             "last hole start %u end %u", hole->start, hole->end);
337   TCP_TEST ((sb->sacked_bytes == 100), "sacked bytes %d", sb->sacked_bytes);
338   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
339
340   /*
341    * Ack first hole
342    */
343
344   vec_reset_length (tc->rcv_opts.sacks);
345   /* Ack up to 1300 to avoid reneging */
346   tcp_rcv_sacks (tc, 1300);
347
348   if (verbose)
349     vlib_cli_output (vm, "\nsb ack up to byte 1300:\n%U",
350                      format_tcp_scoreboard, sb, tc);
351
352   TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
353   TCP_TEST ((pool_elts (sb->holes) == 1),
354             "scoreboard has %d elements", pool_elts (sb->holes));
355   TCP_TEST ((sb->last_bytes_delivered == 100), "last bytes delivered %d",
356             sb->last_bytes_delivered);
357   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
358   TCP_TEST ((sb->head != TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
359   TCP_TEST ((sb->tail != TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
360   TCP_TEST ((!sb->is_reneging), "is not reneging");
361
362   /*
363    * Add some more blocks and then remove all
364    */
365   vec_reset_length (tc->rcv_opts.sacks);
366   tc->snd_una = 1300;
367   tc->snd_nxt = 1900;
368   for (i = 0; i < 5; i++)
369     {
370       block.start = i * 100 + 1200;
371       block.end = (i + 1) * 100 + 1200;
372       vec_add1 (tc->rcv_opts.sacks, block);
373     }
374   tcp_rcv_sacks (tc, 1900);
375
376   scoreboard_clear (sb);
377   if (verbose)
378     vlib_cli_output (vm, "\nsb cleared all:\n%U", format_tcp_scoreboard, sb,
379                      tc);
380
381   TCP_TEST ((pool_elts (sb->holes) == 0),
382             "number of holes %d", pool_elts (sb->holes));
383   TCP_TEST ((sb->head == TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
384   TCP_TEST ((sb->tail == TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
385
386   /*
387    * Re-inject odd blocks and ack them all
388    */
389
390   tc->snd_una = 0;
391   tc->snd_nxt = 1000;
392   vec_reset_length (tc->rcv_opts.sacks);
393   for (i = 0; i < 5; i++)
394     {
395       vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
396     }
397   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
398   tcp_rcv_sacks (tc, 0);
399   if (verbose)
400     vlib_cli_output (vm, "\nsb added odd blocks snd_una 0 snd_una_max 1000:"
401                      "\n%U", format_tcp_scoreboard, sb, tc);
402   TCP_TEST ((pool_elts (sb->holes) == 5),
403             "scoreboard has %d elements", pool_elts (sb->holes));
404   TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
405   hole = scoreboard_last_hole (sb);
406   TCP_TEST ((hole->end == 900), "last hole end %u", hole->end);
407   TCP_TEST ((sb->high_sacked == 1000), "high sacked %u", sb->high_sacked);
408
409   /*
410    * Renege bytes from 950 to 1000
411    */
412   tcp_rcv_sacks (tc, 950);
413
414   if (verbose)
415     vlib_cli_output (vm, "\nack [0, 950]:\n%U", format_tcp_scoreboard, sb,
416                      tc);
417
418   TCP_TEST ((pool_elts (sb->holes) == 0), "scoreboard has %d elements",
419             pool_elts (sb->holes));
420   TCP_TEST ((sb->is_reneging), "is reneging");
421   TCP_TEST ((sb->sacked_bytes == 50), "sacked bytes %d", sb->sacked_bytes);
422   TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
423             sb->last_sacked_bytes);
424   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
425   TCP_TEST ((sb->high_sacked == 1000), "high sacked %u", sb->high_sacked);
426
427   scoreboard_clear (sb);
428
429   /*
430    * Inject one block, ack it and overlap hole
431    */
432
433   tc->snd_una = 0;
434   tc->snd_nxt = 1000;
435
436   block.start = 100;
437   block.end = 500;
438   vec_add1 (tc->rcv_opts.sacks, block);
439   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
440
441   tcp_rcv_sacks (tc, 0);
442
443   if (verbose)
444     vlib_cli_output (vm, "\nsb added [100, 500] snd_una 0 snd_una_max 1000:"
445                      "\n%U", format_tcp_scoreboard, sb, tc);
446
447   tcp_rcv_sacks (tc, 800);
448
449   if (verbose)
450     vlib_cli_output (vm, "\nsb ack [0, 800]:\n%U", format_tcp_scoreboard, sb,
451                      tc);
452
453   TCP_TEST ((pool_elts (sb->holes) == 1),
454             "scoreboard has %d elements", pool_elts (sb->holes));
455   TCP_TEST ((!sb->is_reneging), "is not reneging");
456   TCP_TEST ((sb->sacked_bytes == 0), "sacked bytes %d", sb->sacked_bytes);
457   TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
458             sb->last_sacked_bytes);
459   TCP_TEST ((sb->last_bytes_delivered == 400),
460             "last bytes delivered %d", sb->last_bytes_delivered);
461   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
462   TCP_TEST ((sb->head != TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
463   TCP_TEST ((sb->tail != TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
464
465   /*
466    * One hole close to head, patch head, split in two and start acking
467    * the lowest part
468    */
469   scoreboard_clear (sb);
470   tc->snd_una = 0;
471   tc->snd_nxt = 1000;
472
473   block.start = 500;
474   block.end = 1000;
475   vec_add1 (tc->rcv_opts.sacks, block);
476   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
477
478   tcp_rcv_sacks (tc, 0);
479   if (verbose)
480     vlib_cli_output (vm, "\nsb added [500, 1000]:\n%U",
481                      format_tcp_scoreboard, sb, tc);
482   TCP_TEST ((sb->sacked_bytes == 500), "sacked bytes %d", sb->sacked_bytes);
483   TCP_TEST ((sb->last_sacked_bytes == 500), "last sacked bytes %d",
484             sb->last_sacked_bytes);
485   TCP_TEST ((sb->lost_bytes == 500), "lost bytes %u", sb->lost_bytes);
486
487   vec_reset_length (tc->rcv_opts.sacks);
488   block.start = 300;
489   block.end = 400;
490   vec_add1 (tc->rcv_opts.sacks, block);
491   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
492   tcp_rcv_sacks (tc, 100);
493   if (verbose)
494     vlib_cli_output (vm, "\nsb added [0, 100] [300, 400]:\n%U",
495                      format_tcp_scoreboard, sb, tc);
496   TCP_TEST ((pool_elts (sb->holes) == 2),
497             "scoreboard has %d elements", pool_elts (sb->holes));
498   TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
499   TCP_TEST ((sb->last_sacked_bytes == 100), "last sacked bytes %d",
500             sb->last_sacked_bytes);
501   TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
502             sb->last_bytes_delivered);
503   /* Hole should be split in 2 lost holes that add up to 300 */
504   TCP_TEST ((sb->lost_bytes == 300), "lost bytes %u", sb->lost_bytes);
505   TCP_TEST ((sb->reorder == 7), "reorder %u", sb->reorder);
506
507   /*
508    * Ack [100 300] in two steps
509    *
510    * Step 1. Ack [100 200] which delivers 100 of the bytes lost
511    */
512   tc->snd_una = 100;
513   tcp_rcv_sacks (tc, 200);
514   TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
515   TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
516             sb->last_bytes_delivered);
517   TCP_TEST ((sb->lost_bytes == 200), "lost bytes %u", sb->lost_bytes);
518
519   /*
520    * Step 2. Ack up to 300, although 300 400 is sacked, so this is interpreted
521    * as reneging.
522    */
523   tc->snd_una = 200;
524   tcp_rcv_sacks (tc, 300);
525   if (verbose)
526     vlib_cli_output (vm, "\nacked [100, 300] in two steps:\n%U",
527                      format_tcp_scoreboard, sb, tc);
528   TCP_TEST ((sb->sacked_bytes == 600), "sacked bytes %d", sb->sacked_bytes);
529   TCP_TEST ((sb->lost_bytes == 100), "lost bytes %u", sb->lost_bytes);
530   TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
531             sb->last_bytes_delivered);
532   TCP_TEST ((sb->is_reneging), "is reneging");
533
534   /*
535    * Ack [300 500]. Delivers reneged segment [300 400] and reneges bytes
536    * above 500
537    */
538   tc->snd_una = 300;
539   tcp_rcv_sacks (tc, 500);
540   if (verbose)
541     vlib_cli_output (vm, "\nacked [400, 500]:\n%U", format_tcp_scoreboard, sb,
542                      tc);
543   TCP_TEST ((pool_elts (sb->holes) == 0),
544             "scoreboard has %d elements", pool_elts (sb->holes));
545   TCP_TEST ((sb->sacked_bytes == 500), "sacked bytes %d", sb->sacked_bytes);
546   TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
547             sb->last_sacked_bytes);
548   TCP_TEST ((sb->last_bytes_delivered == 100), "last bytes delivered %d",
549             sb->last_bytes_delivered);
550   TCP_TEST ((sb->is_reneging), "is reneging");
551   TCP_TEST ((sb->head == TCP_INVALID_SACK_HOLE_INDEX), "head %u", sb->head);
552   TCP_TEST ((sb->tail == TCP_INVALID_SACK_HOLE_INDEX), "tail %u", sb->tail);
553
554   /*
555    * Ack up to 1000 to deliver all bytes
556    */
557   tc->snd_una = 500;
558   tcp_rcv_sacks (tc, 1000);
559   if (verbose)
560     vlib_cli_output (vm, "\nAck high sacked:\n%U", format_tcp_scoreboard, sb,
561                      tc);
562   TCP_TEST ((sb->last_sacked_bytes == 0), "last sacked bytes %d",
563             sb->last_sacked_bytes);
564   TCP_TEST ((sb->last_bytes_delivered == 500), "last bytes delivered %d",
565             sb->last_bytes_delivered);
566   TCP_TEST ((!sb->is_reneging), "is not reneging");
567
568   /*
569    * Add [1200, 1500] and test that [1000, 1200] is lost (bytes condition)
570    * snd_una = 1000 and snd_una_max = 1600
571    */
572   tc->snd_una = 1000;
573   tc->snd_nxt = 1600;
574   vec_reset_length (tc->rcv_opts.sacks);
575   block.start = 1200;
576   block.end = 1500;
577   vec_add1 (tc->rcv_opts.sacks, block);
578   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
579   tcp_rcv_sacks (tc, 1000);
580   if (verbose)
581     vlib_cli_output (vm, "\nacked [1200, 1500] test first hole is lost:\n%U",
582                      format_tcp_scoreboard, sb, tc);
583   TCP_TEST ((pool_elts (sb->holes) == 2), "scoreboard has %d elements",
584             pool_elts (sb->holes));
585   TCP_TEST ((sb->sacked_bytes == 300), "sacked bytes %d", sb->sacked_bytes);
586   TCP_TEST ((sb->last_sacked_bytes == 300), "last sacked bytes %d",
587             sb->last_sacked_bytes);
588   TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
589             sb->last_bytes_delivered);
590   /* No bytes lost because of reorder */
591   TCP_TEST ((sb->lost_bytes == 0), "lost bytes %u", sb->lost_bytes);
592   TCP_TEST ((sb->reorder == 7), "reorder %u", sb->reorder);
593   TCP_TEST ((!sb->is_reneging), "is not reneging");
594
595   /*
596    * Restart
597    */
598   scoreboard_clear (sb);
599   vec_reset_length (tc->rcv_opts.sacks);
600
601   /*
602    * Inject [100 500]
603    */
604
605   tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
606   tc->snd_una = 0;
607   tc->snd_nxt = 1000;
608   sb->high_rxt = 0;
609
610   block.start = 100;
611   block.end = 500;
612   vec_add1 (tc->rcv_opts.sacks, block);
613   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
614
615   tcp_rcv_sacks (tc, 0);
616
617   TCP_TEST ((sb->sacked_bytes == 400), "sacked bytes %d", sb->sacked_bytes);
618   TCP_TEST ((sb->last_sacked_bytes == 400), "last sacked bytes %d",
619             sb->last_sacked_bytes);
620   TCP_TEST ((!sb->is_reneging), "is not reneging");
621
622   /*
623    * Renege, sack all of the remaining bytes and cover some rxt bytes
624    */
625   sb->high_rxt = 700;
626   tc->rcv_opts.sacks[0].start = 500;
627   tc->rcv_opts.sacks[0].end = 1000;
628
629   tcp_rcv_sacks (tc, 100);
630
631   TCP_TEST ((sb->sacked_bytes == 900), "sacked bytes %d", sb->sacked_bytes);
632   TCP_TEST ((sb->last_sacked_bytes == 500), "last sacked bytes %d",
633             sb->last_sacked_bytes);
634   TCP_TEST (sb->is_reneging, "is reneging");
635   TCP_TEST ((sb->rxt_sacked == 300), "last rxt sacked bytes %d",
636             sb->rxt_sacked);
637
638   /*
639    * Restart
640    */
641   scoreboard_clear (sb);
642   vec_reset_length (tc->rcv_opts.sacks);
643
644   /*
645    * Broken sacks:
646    * block.start > snd_nxt
647    * && block.start < blk.end
648    * && block.end <= snd_nxt
649    */
650   tc->flags = 0;
651   block.start = 2147483647;
652   block.end = 4294967295;
653   vec_add1 (tc->rcv_opts.sacks, block);
654   tc->snd_una = tc->snd_nxt = 1969067947;
655
656   tcp_rcv_sacks (tc, tc->snd_una);
657
658   /*
659    * Clear
660    */
661   scoreboard_clear (sb);
662   vec_reset_length (tc->rcv_opts.sacks);
663
664   return 0;
665 }
666
667 static int
668 tcp_test_sack_tx (vlib_main_t * vm, unformat_input_t * input)
669 {
670   tcp_connection_t _tc, *tc = &_tc;
671   sack_block_t *sacks;
672   int i, verbose = 0, expected;
673
674   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
675     {
676       if (unformat (input, "verbose"))
677         verbose = 1;
678       else
679         {
680           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
681                            input);
682           return -1;
683         }
684     }
685
686   clib_memset (tc, 0, sizeof (*tc));
687
688   /*
689    * Add odd sack block pairs
690    */
691   for (i = 1; i < 10; i += 2)
692     {
693       tcp_update_sack_list (tc, i * 100, (i + 1) * 100);
694     }
695
696   TCP_TEST ((vec_len (tc->snd_sacks) == 5), "sack blocks %d expected %d",
697             vec_len (tc->snd_sacks), 5);
698   TCP_TEST ((tc->snd_sacks[0].start = 900),
699             "first sack block start %u expected %u", tc->snd_sacks[0].start,
700             900);
701
702   /*
703    * Try to add one extra
704    */
705   sacks = vec_dup (tc->snd_sacks);
706
707   tcp_update_sack_list (tc, 1100, 1200);
708   if (verbose)
709     vlib_cli_output (vm, "add new segment [1100, 1200]\n%U",
710                      format_tcp_sacks, tc);
711   expected = 5 < TCP_MAX_SACK_BLOCKS ? 6 : 5;
712   TCP_TEST ((vec_len (tc->snd_sacks) == expected),
713             "sack blocks %d expected %d", vec_len (tc->snd_sacks), expected);
714   TCP_TEST ((tc->snd_sacks[0].start == 1100),
715             "first sack block start %u expected %u", tc->snd_sacks[0].start,
716             1100);
717
718   /* restore */
719   vec_free (tc->snd_sacks);
720   tc->snd_sacks = sacks;
721
722   /*
723    * Overlap first 2 segment
724    */
725   tc->rcv_nxt = 300;
726   tcp_update_sack_list (tc, 300, 300);
727   if (verbose)
728     vlib_cli_output (vm, "overlap first 2 segments:\n%U",
729                      format_tcp_sacks, tc);
730   TCP_TEST ((vec_len (tc->snd_sacks) == 3), "sack blocks %d expected %d",
731             vec_len (tc->snd_sacks), 3);
732   TCP_TEST ((tc->snd_sacks[0].start == 900),
733             "first sack block start %u expected %u", tc->snd_sacks[0].start,
734             500);
735
736   /*
737    * Add a new segment
738    */
739   tcp_update_sack_list (tc, 1100, 1200);
740   if (verbose)
741     vlib_cli_output (vm, "add new segment [1100, 1200]\n%U",
742                      format_tcp_sacks, tc);
743   TCP_TEST ((vec_len (tc->snd_sacks) == 4), "sack blocks %d expected %d",
744             vec_len (tc->snd_sacks), 4);
745   TCP_TEST ((tc->snd_sacks[0].start == 1100),
746             "first sack block start %u expected %u", tc->snd_sacks[0].start,
747             1100);
748
749   /*
750    * Join middle segments
751    */
752   tcp_update_sack_list (tc, 800, 900);
753   if (verbose)
754     vlib_cli_output (vm, "join middle segments [800, 900]\n%U",
755                      format_tcp_sacks, tc);
756
757   TCP_TEST ((vec_len (tc->snd_sacks) == 3), "sack blocks %d expected %d",
758             vec_len (tc->snd_sacks), 3);
759   TCP_TEST ((tc->snd_sacks[0].start == 700),
760             "first sack block start %u expected %u", tc->snd_sacks[0].start,
761             1100);
762
763   /*
764    * Advance rcv_nxt to overlap all
765    */
766   tc->rcv_nxt = 1200;
767   tcp_update_sack_list (tc, 1200, 1200);
768   if (verbose)
769     vlib_cli_output (vm, "advance rcv_nxt to 1200\n%U", format_tcp_sacks, tc);
770   TCP_TEST ((vec_len (tc->snd_sacks) == 0), "sack blocks %d expected %d",
771             vec_len (tc->snd_sacks), 0);
772
773
774   /*
775    * Add 2 blocks, overwrite first and update rcv_nxt to also remove it
776    */
777
778   vec_reset_length (tc->snd_sacks);
779   tc->rcv_nxt = 0;
780
781   tcp_update_sack_list (tc, 100, 200);
782   tcp_update_sack_list (tc, 300, 400);
783
784   if (verbose)
785     vlib_cli_output (vm, "add [100, 200] [300, 400]\n%U",
786                      format_tcp_sacks, tc);
787   TCP_TEST ((vec_len (tc->snd_sacks) == 2),
788             "sack blocks %d expected %d", vec_len (tc->snd_sacks), 2);
789   TCP_TEST ((tc->snd_sacks[0].start == 300),
790             "first sack block start %u expected %u", tc->snd_sacks[0].start,
791             300);
792
793   tc->rcv_nxt = 100;
794   tcp_update_sack_list (tc, 100, 100);
795   if (verbose)
796     vlib_cli_output (vm, "add [100, 200] rcv_nxt = 100\n%U",
797                      format_tcp_sacks, tc);
798   TCP_TEST ((vec_len (tc->snd_sacks) == 1),
799             "sack blocks %d expected %d", vec_len (tc->snd_sacks), 1);
800   TCP_TEST ((tc->snd_sacks[0].start == 300),
801             "first sack block start %u expected %u", tc->snd_sacks[0].start,
802             300);
803   return 0;
804 }
805
806 static int
807 tcp_test_sack (vlib_main_t * vm, unformat_input_t * input)
808 {
809   int res = 0;
810
811   /* Run all tests */
812   if (unformat_check_input (input) == UNFORMAT_END_OF_INPUT)
813     {
814       if (tcp_test_sack_tx (vm, input))
815         {
816           return -1;
817         }
818
819       if (tcp_test_sack_rx (vm, input))
820         {
821           return -1;
822         }
823     }
824   else
825     {
826       if (unformat (input, "tx"))
827         {
828           res = tcp_test_sack_tx (vm, input);
829         }
830       else if (unformat (input, "rx"))
831         {
832           res = tcp_test_sack_rx (vm, input);
833         }
834     }
835
836   return res;
837 }
838
839 static int
840 tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input)
841 {
842   session_main_t *smm = &session_main;
843   transport_connection_t _tc1, *tc1 = &_tc1, _tc2, *tc2 = &_tc2, *tconn;
844   tcp_connection_t *tc;
845   session_t *s, *s1;
846   u8 cmp = 0, is_filtered = 0;
847   u32 sidx;
848
849   /*
850    * Allocate fake session and connection 1
851    */
852   pool_get (smm->wrk[0].sessions, s);
853   clib_memset (s, 0, sizeof (*s));
854   s->session_index = sidx = s - smm->wrk[0].sessions;
855
856   tc = tcp_connection_alloc (0);
857   tc->connection.s_index = s->session_index;
858   s->connection_index = tc->connection.c_index;
859
860   tc->connection.lcl_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000101);
861   tc->connection.rmt_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000103);
862   tc->connection.lcl_port = 35051;
863   tc->connection.rmt_port = 53764;
864   tc->connection.proto = TRANSPORT_PROTO_TCP;
865   tc->connection.is_ip4 = 1;
866   clib_memcpy_fast (tc1, &tc->connection, sizeof (*tc1));
867
868   /*
869    * Allocate fake session and connection 2
870    */
871   pool_get (smm->wrk[0].sessions, s);
872   clib_memset (s, 0, sizeof (*s));
873   s->session_index = s - smm->wrk[0].sessions;
874
875   tc = tcp_connection_alloc (0);
876   tc->connection.s_index = s->session_index;
877   s->connection_index = tc->connection.c_index;
878
879   tc->connection.lcl_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000101);
880   tc->connection.rmt_ip.ip4.as_u32 = clib_host_to_net_u32 (0x06000102);
881   tc->connection.lcl_port = 38225;
882   tc->connection.rmt_port = 53764;
883   tc->connection.proto = TRANSPORT_PROTO_TCP;
884   tc->connection.is_ip4 = 1;
885   clib_memcpy_fast (tc2, &tc->connection, sizeof (*tc2));
886
887   /*
888    * Confirm that connection lookup works
889    */
890
891   s1 = pool_elt_at_index (smm->wrk[0].sessions, sidx);
892   session_lookup_add_connection (tc1, session_handle (s1));
893   tconn = session_lookup_connection_wt4 (0, &tc1->lcl_ip.ip4,
894                                          &tc1->rmt_ip.ip4,
895                                          tc1->lcl_port, tc1->rmt_port,
896                                          tc1->proto, 0, &is_filtered);
897
898   TCP_TEST ((tconn != 0), "connection exists");
899   cmp = (memcmp (&tconn->rmt_ip, &tc1->rmt_ip, sizeof (tc1->rmt_ip)) == 0);
900   TCP_TEST ((cmp), "rmt ip is identical %d", cmp);
901   TCP_TEST ((tconn->lcl_port == tc1->lcl_port),
902             "rmt port is identical %d", tconn->lcl_port == tc1->lcl_port);
903
904   /*
905    * Non-existing connection lookup should not work
906    */
907
908   tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
909                                          &tc2->rmt_ip.ip4,
910                                          tc2->lcl_port, tc2->rmt_port,
911                                          tc2->proto, 0, &is_filtered);
912   TCP_TEST ((tconn == 0), "lookup result should be null");
913
914   /*
915    * Delete and lookup again
916    */
917   session_lookup_del_connection (tc1);
918   tconn = session_lookup_connection_wt4 (0, &tc1->lcl_ip.ip4,
919                                          &tc1->rmt_ip.ip4,
920                                          tc1->lcl_port, tc1->rmt_port,
921                                          tc1->proto, 0, &is_filtered);
922   TCP_TEST ((tconn == 0), "lookup result should be null");
923   tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
924                                          &tc2->rmt_ip.ip4,
925                                          tc2->lcl_port, tc2->rmt_port,
926                                          tc2->proto, 0, &is_filtered);
927   TCP_TEST ((tconn == 0), "lookup result should be null");
928
929   /*
930    * Re-add and lookup tc2
931    */
932   session_lookup_add_connection (tc1, tc1->s_index);
933   tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
934                                          &tc2->rmt_ip.ip4,
935                                          tc2->lcl_port, tc2->rmt_port,
936                                          tc2->proto, 0, &is_filtered);
937   TCP_TEST ((tconn == 0), "lookup result should be null");
938
939   return 0;
940 }
941
942 static int
943 tcp_test_session (vlib_main_t * vm, unformat_input_t * input)
944 {
945   int rv = 0;
946   tcp_connection_t *tc0;
947   ip4_address_t local, remote;
948   u16 local_port, remote_port;
949   int is_add = 1;
950
951
952   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
953     {
954       if (unformat (input, "del"))
955         is_add = 0;
956       else if (unformat (input, "add"))
957         is_add = 1;
958       else
959         break;
960     }
961
962   if (is_add)
963     {
964       local.as_u32 = clib_host_to_net_u32 (0x06000101);
965       remote.as_u32 = clib_host_to_net_u32 (0x06000102);
966       local_port = clib_host_to_net_u16 (1234);
967       remote_port = clib_host_to_net_u16 (11234);
968
969       tc0 = tcp_connection_alloc (0);
970
971       tc0->state = TCP_STATE_ESTABLISHED;
972       tc0->rcv_las = 1;
973       tc0->c_lcl_port = local_port;
974       tc0->c_rmt_port = remote_port;
975       tc0->c_is_ip4 = 1;
976       tc0->c_thread_index = 0;
977       tc0->c_lcl_ip4.as_u32 = local.as_u32;
978       tc0->c_rmt_ip4.as_u32 = remote.as_u32;
979       tc0->rcv_opts.mss = 1450;
980       tcp_connection_init_vars (tc0);
981
982       TCP_EVT (TCP_EVT_OPEN, tc0);
983
984       if (session_stream_accept (&tc0->connection, 0 /* listener index */ ,
985                                  0 /* thread index */ , 0 /* notify */ ))
986         clib_warning ("stream_session_accept failed");
987
988       session_stream_accept_notify (&tc0->connection);
989     }
990   else
991     {
992       tc0 = tcp_connection_get (0 /* connection index */ , 0 /* thread */ );
993       tc0->state = TCP_STATE_CLOSED;
994       session_transport_closing_notify (&tc0->connection);
995     }
996
997   return rv;
998 }
999
1000 static inline int
1001 tbt_seq_lt (u32 a, u32 b)
1002 {
1003   return seq_lt (a, b);
1004 }
1005
1006 static void
1007 tcp_test_set_time (u32 thread_index, u32 val)
1008 {
1009   session_main.wrk[thread_index].last_vlib_time = val;
1010   tcp_set_time_now (&tcp_main.wrk_ctx[thread_index], val);
1011 }
1012
1013 static int
1014 tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
1015 {
1016   u32 thread_index = 0, snd_una, *min_seqs = 0;
1017   tcp_rate_sample_t _rs = { 0 }, *rs = &_rs;
1018   tcp_connection_t _tc, *tc = &_tc;
1019   sack_scoreboard_t *sb = &tc->sack_sb;
1020   int __clib_unused verbose = 0, i;
1021   u64 rate = 1000, burst = 100;
1022   sack_block_t *sacks = 0;
1023   tcp_byte_tracker_t *bt;
1024   rb_node_t *root, *rbn;
1025   tcp_bt_sample_t *bts;
1026
1027   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1028     {
1029       if (unformat (input, "verbose"))
1030         verbose = 1;
1031       else
1032         {
1033           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1034                            input);
1035           return -1;
1036         }
1037     }
1038
1039   /* Init data structures */
1040   memset (tc, 0, sizeof (*tc));
1041   tcp_test_set_time (thread_index, 1);
1042   transport_connection_tx_pacer_update (&tc->connection, rate, 1e6);
1043
1044   tcp_bt_init (tc);
1045   bt = tc->bt;
1046
1047   /*
1048    * Track simple bursts without rxt
1049    */
1050
1051   /* 1) track first burst a time 1 */
1052   tcp_bt_track_tx (tc, burst);
1053
1054   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1055   TCP_TEST (pool_elts (bt->samples) == 1, "should have 1 sample");
1056   bts = pool_elt_at_index (bt->samples, bt->head);
1057   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1058   TCP_TEST (bts->next == TCP_BTS_INVALID_INDEX, "next should be invalid");
1059   TCP_TEST (bts->prev == TCP_BTS_INVALID_INDEX, "prev should be invalid");
1060   TCP_TEST (bts->delivered_time == 1, "delivered time should be 1");
1061   TCP_TEST (bts->delivered == 0, "delivered should be 0");
1062   TCP_TEST (!(bts->flags & TCP_BTS_IS_RXT), "not retransmitted");
1063   TCP_TEST (!(bts->flags & TCP_BTS_IS_APP_LIMITED), "not app limited");
1064
1065   /* 2) check delivery rate at time 2 */
1066   tcp_test_set_time (thread_index, 2);
1067   tc->snd_una = tc->snd_nxt = burst;
1068   tc->bytes_acked = burst;
1069
1070   tcp_bt_sample_delivery_rate (tc, rs);
1071
1072   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1073   TCP_TEST (pool_elts (bt->samples) == 0, "sample should've been consumed");
1074   TCP_TEST (tc->delivered_time == 2, "delivered time should be 2");
1075   TCP_TEST (tc->delivered == burst, "delivered should be 100");
1076   TCP_TEST (rs->interval_time == 1, "ack time should be 1");
1077   TCP_TEST (rs->delivered == burst, "delivered should be 100");
1078   TCP_TEST (rs->prior_delivered == 0, "sample delivered should be 0");
1079   TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
1080   TCP_TEST (tc->first_tx_time == 1, "first_tx_time %u", tc->first_tx_time);
1081
1082   /* 3) track second burst at time 2 */
1083   tcp_bt_track_tx (tc, burst);
1084   tc->snd_nxt += burst;
1085
1086   /* 4) track second burst at time 3 */
1087   tcp_test_set_time (thread_index, 3);
1088   tcp_bt_track_tx (tc, burst);
1089   tc->snd_nxt += burst;
1090
1091   TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
1092
1093   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1094   bts = pool_elt_at_index (bt->samples, bt->head);
1095   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1096   TCP_TEST (bts->next == bt->tail, "next should tail");
1097
1098   bts = pool_elt_at_index (bt->samples, bt->tail);
1099   TCP_TEST (bts->min_seq == tc->snd_nxt - burst,
1100             "min seq should be snd_nxt prior to burst");
1101   TCP_TEST (bts->prev == bt->head, "prev should be head");
1102
1103   /* 5) check delivery rate at time 4 */
1104   tcp_test_set_time (thread_index, 4);
1105   tc->snd_una = tc->snd_nxt;
1106   tc->bytes_acked = 2 * burst;
1107
1108   tcp_bt_sample_delivery_rate (tc, rs);
1109
1110   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1111   TCP_TEST (pool_elts (bt->samples) == 0, "sample should've been consumed");
1112   TCP_TEST (tc->delivered_time == 4, "delivered time should be 4");
1113   TCP_TEST (tc->delivered == 3 * burst, "delivered should be 300 is %u",
1114             tc->delivered);
1115   TCP_TEST (rs->interval_time == 2, "ack time should be 2");
1116   TCP_TEST (rs->delivered == 2 * burst, "delivered should be 200");
1117   TCP_TEST (rs->prior_delivered == burst, "delivered should be 100");
1118   TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
1119   TCP_TEST (tc->first_tx_time == 2, "first_tx_time %u", tc->first_tx_time);
1120
1121   /*
1122    * Track retransmissions
1123    *
1124    * snd_una should be 300 at this point
1125    */
1126
1127   snd_una = tc->snd_una;
1128
1129   /* 1) track first burst at time 4 */
1130   tcp_bt_track_tx (tc, burst);
1131   tc->snd_nxt += burst;
1132
1133   /* 2) track second burst at time 5 */
1134   tcp_test_set_time (thread_index, 5);
1135   tcp_bt_track_tx (tc, burst);
1136   tc->snd_nxt += burst;
1137
1138   /* 3) track third burst at time 6 */
1139   tcp_test_set_time (thread_index, 6);
1140   tcp_bt_track_tx (tc, burst);
1141   tc->snd_nxt += burst;
1142
1143   /* 4) track fourth burst at time 7 */
1144   tcp_test_set_time (thread_index, 7);
1145   /* Limited until last burst is acked */
1146   tc->app_limited = snd_una + 4 * burst - 1;
1147   tcp_bt_track_tx (tc, burst);
1148   tc->snd_nxt += burst;
1149
1150   /* 5) check delivery rate at time 8
1151    *
1152    * tc->snd_una = snd_una + 10
1153    * sacks:
1154    * [snd_una + burst, snd_una + burst + 10]
1155    * [snd_una + 2 * burst + 10, snd_una + 2 * burst + 20]
1156    */
1157   tcp_test_set_time (thread_index, 8);
1158   tc->snd_una += 10;
1159   tc->bytes_acked = 10;
1160   sb->last_sacked_bytes = 20;
1161
1162   TCP_TEST (pool_elts (bt->samples) == 4, "there should be 4 samples");
1163
1164   vec_validate (sacks, 1);
1165   sacks[0].start = snd_una + burst;
1166   sacks[0].end = snd_una + burst + 10;
1167   sacks[1].start = snd_una + 2 * burst + 10;
1168   sacks[1].end = snd_una + 2 * burst + 20;
1169   tc->rcv_opts.sacks = sacks;
1170
1171   tcp_bt_sample_delivery_rate (tc, rs);
1172
1173   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1174   TCP_TEST (pool_elts (bt->samples) == 7, "there should be 7 samples %u",
1175             pool_elts (bt->samples));
1176   TCP_TEST (tc->delivered_time == 8, "delivered time should be 8");
1177   TCP_TEST (tc->delivered == 3 * burst + 30, "delivered should be %u is %u",
1178             3 * burst + 30, tc->delivered);
1179   /* All 3 samples have the same delivered number of bytes. So the first is
1180    * the reference for delivery estimate. */
1181   TCP_TEST (rs->interval_time == 4, "ack time should be 4 is %.2f",
1182             rs->interval_time);
1183   TCP_TEST (rs->delivered == 30, "delivered should be 30");
1184   TCP_TEST (rs->prior_delivered == 3 * burst,
1185             "sample delivered should be %u", 3 * burst);
1186   TCP_TEST (!(rs->flags & TCP_BTS_IS_RXT), "not retransmitted");
1187   TCP_TEST (!(rs->flags & TCP_BTS_IS_APP_LIMITED), "not app limited");
1188   /* All 3 samples have the same delivered number of bytes. The first
1189    * sets the first tx time */
1190   TCP_TEST (tc->first_tx_time == 4, "first_tx_time %u", tc->first_tx_time);
1191
1192   /* 6) Retransmit and track at time 9
1193    *
1194    * delivered = 3 * burst + 30
1195    * delivered_time = 8 (last ack)
1196    *
1197    * segments:
1198    * [snd_una + 10, snd_una + burst]
1199    * [snd_una + burst + 10, snd_una + 2 * burst + 10]
1200    * [snd_una + 2 * burst + 20, snd_una + 4 * burst]
1201    */
1202   tcp_test_set_time (thread_index, 9);
1203
1204   tcp_bt_track_rxt (tc, snd_una + 10, snd_una + burst);
1205   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1206   /* The retransmit covers everything left from first burst */
1207   TCP_TEST (pool_elts (bt->samples) == 7, "there should be 7 samples %u",
1208             pool_elts (bt->samples));
1209
1210   tcp_bt_track_rxt (tc, snd_una + burst + 10, snd_una + 2 * burst + 10);
1211   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1212   TCP_TEST (pool_elts (bt->samples) == 6, "there should be 6 samples %u",
1213             pool_elts (bt->samples));
1214
1215   /* Retransmit covers last sample entirely so it should be removed */
1216   tcp_bt_track_rxt (tc, snd_una + 2 * burst + 20, snd_una + 4 * burst);
1217   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1218   TCP_TEST (pool_elts (bt->samples) == 5, "there should be 5 samples %u",
1219             pool_elts (bt->samples));
1220
1221   vec_validate (min_seqs, 4);
1222   min_seqs[0] = snd_una + 10;
1223   min_seqs[1] = snd_una + burst;
1224   min_seqs[2] = snd_una + burst + 10;
1225   min_seqs[3] = snd_una + 2 * burst + 10;
1226   min_seqs[4] = snd_una + 2 * burst + 20;
1227
1228   root = bt->sample_lookup.nodes + bt->sample_lookup.root;
1229   bts = bt->samples + bt->head;
1230   for (i = 0; i < vec_len (min_seqs); i++)
1231     {
1232       if (bts->min_seq != min_seqs[i])
1233         TCP_TEST (0, "should be %u is %u", min_seqs[i], bts->min_seq);
1234       rbn = rb_tree_search_subtree_custom (&bt->sample_lookup, root,
1235                                            bts->min_seq, tbt_seq_lt);
1236       if (rbn->opaque != bts - bt->samples)
1237         TCP_TEST (0, "lookup should work");
1238       bts = bt->samples + bts->next;
1239     }
1240
1241   /* 7) check delivery rate at time 10
1242    *
1243    * tc->snd_una = snd_una + 2 * burst
1244    * sacks:
1245    * [snd_una + 2 * burst + 20, snd_una + 2 * burst + 30]
1246    * [snd_una + 2 * burst + 50, snd_una + 2 * burst + 60]
1247    */
1248   tcp_test_set_time (thread_index, 10);
1249   tc->snd_una = snd_una + 2 * burst;
1250   tc->bytes_acked = 2 * burst - 10;
1251   sb->last_sacked_bytes = 20;
1252
1253   sacks[0].start = snd_una + 2 * burst + 20;
1254   sacks[0].end = snd_una + 2 * burst + 30;
1255   sacks[1].start = snd_una + 2 * burst + 50;
1256   sacks[1].end = snd_una + 2 * burst + 60;
1257
1258   tcp_bt_sample_delivery_rate (tc, rs);
1259
1260   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1261   TCP_TEST (pool_elts (bt->samples) == 5, "num samples should be 5 is %u",
1262             pool_elts (bt->samples));
1263   TCP_TEST (tc->delivered_time == 10, "delivered time should be 10");
1264   TCP_TEST (tc->delivered == 5 * burst + 40, "delivered should be %u is %u",
1265             5 * burst + 40, tc->delivered);
1266   /* A rxt was acked and delivered time for it is 8 (last ack time) so
1267    * ack_time is 2 (8 - 10). However, first_tx_time for rxt was 4 and rxt
1268    * time 9. Therefore snd_time is 5 (9 - 4)*/
1269   TCP_TEST (rs->interval_time == 5, "ack time should be 5 is %.2f",
1270             rs->interval_time);
1271   /* delivered_now - delivered_rxt ~ 5 * burst + 40 - 3 * burst - 30 */
1272   TCP_TEST (rs->delivered == 2 * burst + 10, "delivered should be 210 is %u",
1273             rs->delivered);
1274   TCP_TEST (rs->prior_delivered == 3 * burst + 30,
1275             "sample delivered should be %u", 3 * burst + 30);
1276   TCP_TEST (rs->flags & TCP_BTS_IS_RXT, "is retransmitted");
1277   /* Sample is app limited because of the retransmits */
1278   TCP_TEST (rs->flags & TCP_BTS_IS_APP_LIMITED, "is app limited");
1279   TCP_TEST (tc->app_limited, "app limited should be set");
1280   TCP_TEST (tc->first_tx_time == 9, "first_tx_time %u", tc->first_tx_time);
1281
1282
1283   /*
1284    * 8) check delivery rate at time 11
1285    */
1286   tcp_test_set_time (thread_index, 11);
1287   tc->snd_una = tc->snd_nxt;
1288   tc->bytes_acked = 2 * burst;
1289   sb->last_sacked_bytes = 0;
1290   sb->last_bytes_delivered = 40;
1291
1292   memset (rs, 0, sizeof (*rs));
1293   tcp_bt_sample_delivery_rate (tc, rs);
1294
1295   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1296   TCP_TEST (pool_elts (bt->samples) == 0, "num samples should be 0 is %u",
1297             pool_elts (bt->samples));
1298   TCP_TEST (tc->delivered_time == 11, "delivered time should be 11");
1299   TCP_TEST (tc->delivered == 7 * burst, "delivered should be %u is %u",
1300             7 * burst, tc->delivered);
1301   /* Delivered time at retransmit was 8 so ack_time is 11 - 8 = 3. However,
1302    * first_tx_time for rxt was 4 and rxt time was 9. Therefore snd_time
1303    * is 9 - 4 = 5 */
1304   TCP_TEST (rs->interval_time == 5, "ack time should be 5 is %.2f",
1305             rs->interval_time);
1306   /* delivered_now - delivered_rxt ~ 7 * burst - 3 * burst - 30.
1307    * That's because we didn't retransmit any new segment. */
1308   TCP_TEST (rs->delivered == 4 * burst - 30, "delivered should be 160 is %u",
1309             rs->delivered);
1310   TCP_TEST (rs->prior_delivered == 3 * burst + 30,
1311             "sample delivered should be %u", 3 * burst + 30);
1312   TCP_TEST (rs->flags & TCP_BTS_IS_RXT, "is retransmitted");
1313   TCP_TEST (rs->flags & TCP_BTS_IS_APP_LIMITED, "is app limited");
1314   TCP_TEST (tc->app_limited == 0, "app limited should be cleared");
1315   TCP_TEST (tc->first_tx_time == 9, "first_tx_time %u", tc->first_tx_time);
1316
1317   /*
1318    * 9) test flush
1319    */
1320
1321   tcp_bt_track_tx (tc, burst);
1322   tc->snd_nxt += burst;
1323
1324   tcp_test_set_time (thread_index, 12);
1325   tcp_bt_track_tx (tc, burst);
1326   tc->snd_nxt += burst;
1327
1328   tcp_bt_flush_samples (tc);
1329
1330   /*
1331    * Cleanup
1332    */
1333   vec_free (sacks);
1334   vec_free (min_seqs);
1335   tcp_bt_cleanup (tc);
1336   return 0;
1337 }
1338
1339 static int
1340 tcp_test_bt (vlib_main_t * vm, unformat_input_t * input)
1341 {
1342   u32 thread_index = 0;
1343   tcp_rate_sample_t _rs = { 0 }, *rs = &_rs;
1344   tcp_connection_t _tc, *tc = &_tc;
1345   int __clib_unused verbose = 0, i;
1346   tcp_byte_tracker_t *bt;
1347   tcp_bt_sample_t *bts;
1348   u32 head;
1349   sack_block_t *blk;
1350
1351   /* Init data structures */
1352   memset (tc, 0, sizeof (*tc));
1353   tcp_bt_init (tc);
1354   bt = tc->bt;
1355
1356   /* 1) track first burst at time 1 */
1357   /* [] --> [0:100] */
1358   session_main.wrk[thread_index].last_vlib_time = 1;
1359   tcp_bt_track_tx (tc, 100);
1360   tc->snd_nxt += 100;
1361
1362   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1363   TCP_TEST (pool_elts (bt->samples) == 1, "should have 1 sample");
1364   bts = pool_elt_at_index (bt->samples, bt->head);
1365   head = bt->head;
1366   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1367   TCP_TEST (bts->next == TCP_BTS_INVALID_INDEX, "next should be invalid");
1368   TCP_TEST (bts->prev == TCP_BTS_INVALID_INDEX, "prev should be invalid");
1369   TCP_TEST (bts->tx_time == 1, "tx time should be 1");
1370   TCP_TEST (!(bts->flags & TCP_BTS_IS_RXT), "not retransmitted");
1371   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1372
1373   /* 2) track second butst at time 2 */
1374   /* --> [0:100][100:200] */
1375   session_main.wrk[thread_index].last_vlib_time = 2;
1376   tcp_bt_track_tx (tc, 100);
1377   tc->snd_nxt += 100;
1378
1379   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1380   TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
1381   bts = pool_elt_at_index (bt->samples, bt->head);
1382   TCP_TEST (head == bt->head, "head is not updated");
1383   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1384   TCP_TEST (bts->tx_time == 1, "tx time of head should be 1");
1385
1386   /* 3) acked partially at time 3 */
1387   /* ACK:150 */
1388   /* --> [150:200] */
1389   session_main.wrk[thread_index].last_vlib_time = 3;
1390   tc->snd_una = 150;
1391   tc->bytes_acked = 150;
1392   tc->sack_sb.last_sacked_bytes = 0;
1393   tcp_bt_sample_delivery_rate (tc, rs);
1394
1395   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1396   TCP_TEST (pool_elts (bt->samples) == 1, "should have 1 sample");
1397   TCP_TEST (head != bt->head, "head is updated");
1398   head = bt->head;
1399   bts = pool_elt_at_index (bt->samples, bt->head);
1400   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1401   TCP_TEST (bts->tx_time == 2, "tx time should be 2");
1402
1403   /* 4) track another burst at time 4 */
1404   /* --> [150:200][200:300] */
1405   session_main.wrk[thread_index].last_vlib_time = 4;
1406   tcp_bt_track_tx (tc, 100);
1407   tc->snd_nxt += 100;
1408
1409   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1410   TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
1411   bts = pool_elt_at_index (bt->samples, bt->head);
1412   TCP_TEST (head == bt->head, "head is not updated");
1413   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1414   TCP_TEST (bts->tx_time == 2, "tx time of head should be 2");
1415
1416   /* 5) track another burst at time 5 */
1417   /* --> [150:200][200:300][300:400] */
1418   session_main.wrk[thread_index].last_vlib_time = 5;
1419   tcp_bt_track_tx (tc, 100);
1420   tc->snd_nxt += 100;
1421
1422   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1423   TCP_TEST (pool_elts (bt->samples) == 3, "should have 3 samples");
1424   bts = pool_elt_at_index (bt->samples, bt->head);
1425   TCP_TEST (head == bt->head, "head is not updated");
1426   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1427   TCP_TEST (bts->tx_time == 2, "tx time of head should be 2");
1428
1429   /* 6) acked with SACK option at time 6 */
1430   /* ACK:250 + SACK[350:400] */
1431   /* --> [250:300][300:350][350:400/sacked] */
1432   session_main.wrk[thread_index].last_vlib_time = 6;
1433   tc->snd_una = 250;
1434   tc->bytes_acked = 100;
1435   tc->sack_sb.last_sacked_bytes = 50;
1436   vec_add2 (tc->rcv_opts.sacks, blk, 1);
1437   blk->start = 350;
1438   blk->end = 400;
1439   tcp_bt_sample_delivery_rate (tc, rs);
1440
1441   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1442   TCP_TEST (pool_elts (bt->samples) == 3, "should have 3 samples");
1443   TCP_TEST (head != bt->head, "head is updated");
1444   head = bt->head;
1445   bts = pool_elt_at_index (bt->samples, bt->head);
1446   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1447   TCP_TEST (bts->tx_time == 4, "tx time of head should be 4");
1448   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1449   bts = pool_elt_at_index (bt->samples, bts->next);
1450   TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1451   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1452   bts = pool_elt_at_index (bt->samples, bt->tail);
1453   TCP_TEST (bts->tx_time == 5, "tx time of tail should be 5");
1454   TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1455
1456   /* 7) track another burst at time 7 */
1457   /* --> [250:300][300:350][350:400/sacked][400-500] */
1458   session_main.wrk[thread_index].last_vlib_time = 7;
1459   tcp_bt_track_tx (tc, 100);
1460   tc->snd_nxt += 100;
1461
1462   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1463   TCP_TEST (pool_elts (bt->samples) == 4, "should have 4 samples");
1464   bts = pool_elt_at_index (bt->samples, bt->head);
1465   TCP_TEST (head == bt->head, "head is not updated");
1466   bts = pool_elt_at_index (bt->samples, bt->head);
1467   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1468   TCP_TEST (bts->tx_time == 4, "tx time of head should be 4");
1469   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1470   bts = pool_elt_at_index (bt->samples, bts->next);
1471   TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1472   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1473   bts = pool_elt_at_index (bt->samples, bts->next);
1474   TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1475   TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1476   bts = pool_elt_at_index (bt->samples, bt->tail);
1477   TCP_TEST (bts->tx_time == 7, "tx time of tail should be 7");
1478   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1479
1480   /* 8) retransmit lost one at time 8 */
1481   /* retransmit [250:300] */
1482   /* --> [250:300][300:350][350:400/sacked][400-500] */
1483   session_main.wrk[thread_index].last_vlib_time = 8;
1484   tcp_bt_track_rxt (tc, 250, 300);
1485   tcp_bt_sample_delivery_rate (tc, rs);
1486
1487   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1488   TCP_TEST (pool_elts (bt->samples) == 4, "should have 4 samples");
1489   TCP_TEST (head == bt->head, "head is not updated");
1490   bts = pool_elt_at_index (bt->samples, bt->head);
1491   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1492   TCP_TEST (bts->tx_time == 8, "tx time of head should be 8");
1493   bts = pool_elt_at_index (bt->samples, bts->next);
1494   TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1495   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1496   bts = pool_elt_at_index (bt->samples, bts->next);
1497   TCP_TEST (bts->tx_time == 5, "tx time of next should be 5");
1498   TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1499   bts = pool_elt_at_index (bt->samples, bt->tail);
1500   TCP_TEST (bts->tx_time == 7, "tx time of tail should be 7");
1501   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1502
1503   /* 9) acked with SACK option at time 9 */
1504   /* ACK:350 + SACK[420:450] */
1505   /* --> [400:420][420:450/sacked][450:400] */
1506   session_main.wrk[thread_index].last_vlib_time = 6;
1507   tc->snd_una = 400;
1508   tc->bytes_acked = 150;
1509   tc->sack_sb.last_sacked_bytes = 30;
1510   vec_add2 (tc->rcv_opts.sacks, blk, 1);
1511   blk->start = 420;
1512   blk->end = 450;
1513   tcp_bt_sample_delivery_rate (tc, rs);
1514
1515   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1516   TCP_TEST (pool_elts (bt->samples) == 3, "should have 3 samples");
1517   TCP_TEST (head != bt->head, "head is updated");
1518   head = bt->head;
1519   bts = pool_elt_at_index (bt->samples, bt->head);
1520   TCP_TEST (bts->min_seq == tc->snd_una, "min seq should be snd_una");
1521   TCP_TEST (bts->min_seq == 400 && bts->max_seq == 420, "bts [400:420]");
1522   TCP_TEST (bts->tx_time == 7, "tx time of head should be 7");
1523   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1524   bts = pool_elt_at_index (bt->samples, bts->next);
1525   TCP_TEST (bts->min_seq == 420 && bts->max_seq == 450, "bts [420:450]");
1526   TCP_TEST (bts->tx_time == 7, "tx time of head should be 7");
1527   TCP_TEST ((bts->flags & TCP_BTS_IS_SACKED), "sacked");
1528   bts = pool_elt_at_index (bt->samples, bts->next);
1529   TCP_TEST (bts->min_seq == 450 && bts->max_seq == 500, "bts [450:500]");
1530   TCP_TEST (bts->tx_time == 7, "tx time of head should be 7");
1531   TCP_TEST (!(bts->flags & TCP_BTS_IS_SACKED), "not sacked");
1532
1533   /* 10) acked partially at time 10 */
1534   /* ACK:500 */
1535   /* --> [] */
1536   session_main.wrk[thread_index].last_vlib_time = 3;
1537   tc->snd_una = 500;
1538   tc->bytes_acked = 100;
1539   tc->sack_sb.last_sacked_bytes = 0;
1540   tcp_bt_sample_delivery_rate (tc, rs);
1541
1542   TCP_TEST (tcp_bt_is_sane (bt), "tracker should be sane");
1543   TCP_TEST (pool_elts (bt->samples) == 0, "should have 0 samples");
1544   TCP_TEST (bt->head == TCP_BTS_INVALID_INDEX, "bt->head is invalidated");
1545   TCP_TEST (tc->snd_una == tc->snd_nxt, "snd_una == snd_nxt");
1546
1547   return 0;
1548 }
1549
1550 static clib_error_t *
1551 tcp_test (vlib_main_t * vm,
1552           unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1553 {
1554   int res = 0;
1555
1556   vnet_session_enable_disable (vm, 1);
1557
1558   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1559     {
1560       if (unformat (input, "sack"))
1561         {
1562           res = tcp_test_sack (vm, input);
1563         }
1564       else if (unformat (input, "session"))
1565         {
1566           res = tcp_test_session (vm, input);
1567         }
1568       else if (unformat (input, "lookup"))
1569         {
1570           res = tcp_test_lookup (vm, input);
1571         }
1572       else if (unformat (input, "delivery"))
1573         {
1574           res = tcp_test_delivery (vm, input);
1575         }
1576       else if (unformat (input, "bt"))
1577         {
1578           res = tcp_test_bt (vm, input);
1579         }
1580       else if (unformat (input, "all"))
1581         {
1582           if ((res = tcp_test_sack (vm, input)))
1583             goto done;
1584           if ((res = tcp_test_lookup (vm, input)))
1585             goto done;
1586           if ((res = tcp_test_delivery (vm, input)))
1587             goto done;
1588         }
1589       else
1590         break;
1591     }
1592
1593 done:
1594   if (res)
1595     return clib_error_return (0, "TCP unit test failed");
1596   return 0;
1597 }
1598
1599 /* *INDENT-OFF* */
1600 VLIB_CLI_COMMAND (tcp_test_command, static) =
1601 {
1602   .path = "test tcp",
1603   .short_help = "internal tcp unit tests",
1604   .function = tcp_test,
1605 };
1606 /* *INDENT-ON* */
1607
1608 /*
1609  * fd.io coding-style-patch-verification: ON
1610  *
1611  * Local Variables:
1612  * eval: (c-set-style "gnu")
1613  * End:
1614  */