misc: remove GNU Indent directives
[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 scoreboard_trace_elt_t sb_trace[] = {};
39
40 static int
41 tcp_test_scoreboard_replay (vlib_main_t * vm, unformat_input_t * input)
42 {
43   int verbose = 0;
44   tcp_connection_t _tc, *tc = &_tc;
45   u8 *s = 0;
46
47   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
48     {
49       if (unformat (input, "detail"))
50         verbose = 1;
51       else
52         {
53           clib_error_t *e = clib_error_return
54             (0, "unknown input `%U'", format_unformat_error, input);
55           clib_error_report (e);
56           return -1;
57         }
58     }
59
60 #if TCP_SCOREBOARD_TRACE
61   tc->sack_sb.trace = sb_trace;
62 #endif
63   s = tcp_scoreboard_replay (s, tc, verbose);
64   vlib_cli_output (vm, "%v", s);
65   return 0;
66 }
67
68 static int
69 tcp_test_sack_rx (vlib_main_t * vm, unformat_input_t * input)
70 {
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;
75   int i, verbose = 0;
76
77   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
78     {
79       if (unformat (input, "verbose"))
80         verbose = 1;
81       else if (unformat (input, "replay"))
82         return tcp_test_scoreboard_replay (vm, input);
83     }
84
85   clib_memset (tc, 0, sizeof (*tc));
86
87   tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
88   tc->snd_una = 0;
89   tc->snd_nxt = 1000;
90   tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
91   tc->snd_mss = 150;
92   scoreboard_init (&tc->sack_sb);
93
94   for (i = 0; i < 1000 / 100; i++)
95     {
96       block.start = i * 100;
97       block.end = (i + 1) * 100;
98       vec_add1 (sacks, block);
99     }
100
101   /*
102    * Inject even blocks
103    */
104
105   for (i = 0; i < 1000 / 200; i++)
106     {
107       vec_add1 (tc->rcv_opts.sacks, sacks[i * 2]);
108     }
109   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
110   tcp_rcv_sacks (tc, 0);
111
112   if (verbose)
113     vlib_cli_output (vm, "sb after even blocks (mss %u):\n%U",
114                      tc->snd_mss, format_tcp_scoreboard, sb, tc);
115
116   TCP_TEST ((pool_elts (sb->holes) == 5),
117             "scoreboard has %d elements", pool_elts (sb->holes));
118
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);
132
133   /*
134    * Inject odd blocks except the last
135    *
136    */
137
138   vec_reset_length (tc->rcv_opts.sacks);
139   for (i = 0; i < 800 / 200; i++)
140     {
141       vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
142     }
143   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
144   tcp_rcv_sacks (tc, 0);
145
146   if (verbose)
147     vlib_cli_output (vm, "\nsb after odd blocks:\n%U", format_tcp_scoreboard,
148                      sb, tc);
149
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);
161
162   /*
163    *  Ack until byte 100 - this is reneging because we should ack until 900
164    */
165   tcp_rcv_sacks (tc, 100);
166   if (verbose)
167     vlib_cli_output (vm, "\nack until byte 100:\n%U", format_tcp_scoreboard,
168                      sb, tc);
169
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");
173
174   /*
175    * Make sure we accept duplicate acks while reneging.
176    */
177   tc->snd_una = 100;
178   sb->high_rxt = 950;
179
180   block.start = 900;
181   block.end = 950;
182   vec_add1 (tc->rcv_opts.sacks, block);
183
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",
191             sb->rxt_sacked);
192
193   /*
194    * Sack all up to 950
195    */
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");
203
204   /*
205    * Sack [960 970] [980 990]
206    */
207   sb->high_rxt = 985;
208
209   tc->snd_una = 950;
210   vec_reset_length (tc->rcv_opts.sacks);
211   block.start = 960;
212   block.end = 970;
213   vec_add1 (tc->rcv_opts.sacks, block);
214
215   block.start = 980;
216   block.end = 990;
217   vec_add1 (tc->rcv_opts.sacks, block);
218
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",
227             sb->rxt_sacked);
228
229   /*
230    * Ack up to 960 (reneging) + [961 971]
231    */
232   tc->rcv_opts.sacks[0].start = 961;
233   tc->rcv_opts.sacks[0].end = 971;
234
235   tcp_rcv_sacks (tc, 960);
236
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",
242             sb->rxt_sacked);
243   TCP_TEST ((sb->last_bytes_delivered == 0), "last bytes delivered %d",
244             sb->last_bytes_delivered);
245
246   /*
247    * Ack up to 960 (reneging) + [961 990]
248    */
249   tc->snd_una = 960;
250   tc->rcv_opts.sacks[0].start = 961;
251   tc->rcv_opts.sacks[0].end = 990;
252
253   tcp_rcv_sacks (tc, 960);
254
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",
260             sb->rxt_sacked);
261
262   /*
263    * Sack remaining bytes [990 1000]
264    */
265   tc->rcv_opts.sacks[0].start = 990;
266   tc->rcv_opts.sacks[0].end = 1000;
267
268   tcp_rcv_sacks (tc, 960);
269
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",
275             sb->rxt_sacked);
276   TCP_TEST (pool_elts (sb->holes) == 0, "no holes left");
277
278   /*
279    * Ack up to 970 no sack blocks
280    */
281   vec_reset_length (tc->rcv_opts.sacks);
282   tc->rcv_opts.flags &= ~TCP_OPTS_FLAG_SACK;
283   tcp_rcv_sacks (tc, 970);
284
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",
290             sb->rxt_sacked);
291
292   /*
293    * Ack all up to 1000
294    */
295   tc->snd_una = 970;
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");
305
306   /*
307    * Add new block
308    */
309   tc->flags = 0;
310   tc->rcv_opts.flags |= TCP_OPTS_FLAG_SACK;
311   vec_reset_length (tc->rcv_opts.sacks);
312
313   block.start = 1200;
314   block.end = 1300;
315   vec_add1 (tc->rcv_opts.sacks, block);
316
317   tc->snd_una = 1000;
318   tc->snd_nxt = 1500;
319   tcp_rcv_sacks (tc, 1000);
320
321   if (verbose)
322     vlib_cli_output (vm, "\nadd [1200, 1300] snd_una_max 1500, snd_una 1000:"
323                      " \n%U", format_tcp_scoreboard, sb, tc);
324
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);
337
338   /*
339    * Ack first hole
340    */
341
342   vec_reset_length (tc->rcv_opts.sacks);
343   /* Ack up to 1300 to avoid reneging */
344   tcp_rcv_sacks (tc, 1300);
345
346   if (verbose)
347     vlib_cli_output (vm, "\nsb ack up to byte 1300:\n%U",
348                      format_tcp_scoreboard, sb, tc);
349
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");
359
360   /*
361    * Add some more blocks and then remove all
362    */
363   vec_reset_length (tc->rcv_opts.sacks);
364   tc->snd_una = 1300;
365   tc->snd_nxt = 1900;
366   for (i = 0; i < 5; i++)
367     {
368       block.start = i * 100 + 1200;
369       block.end = (i + 1) * 100 + 1200;
370       vec_add1 (tc->rcv_opts.sacks, block);
371     }
372   tcp_rcv_sacks (tc, 1900);
373
374   scoreboard_clear (sb);
375   if (verbose)
376     vlib_cli_output (vm, "\nsb cleared all:\n%U", format_tcp_scoreboard, sb,
377                      tc);
378
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);
383
384   /*
385    * Re-inject odd blocks and ack them all
386    */
387
388   tc->snd_una = 0;
389   tc->snd_nxt = 1000;
390   vec_reset_length (tc->rcv_opts.sacks);
391   for (i = 0; i < 5; i++)
392     {
393       vec_add1 (tc->rcv_opts.sacks, sacks[i * 2 + 1]);
394     }
395   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
396   tcp_rcv_sacks (tc, 0);
397   if (verbose)
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);
406
407   /*
408    * Renege bytes from 950 to 1000
409    */
410   tcp_rcv_sacks (tc, 950);
411
412   if (verbose)
413     vlib_cli_output (vm, "\nack [0, 950]:\n%U", format_tcp_scoreboard, sb,
414                      tc);
415
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);
424
425   scoreboard_clear (sb);
426
427   /*
428    * Inject one block, ack it and overlap hole
429    */
430
431   tc->snd_una = 0;
432   tc->snd_nxt = 1000;
433
434   block.start = 100;
435   block.end = 500;
436   vec_add1 (tc->rcv_opts.sacks, block);
437   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
438
439   tcp_rcv_sacks (tc, 0);
440
441   if (verbose)
442     vlib_cli_output (vm, "\nsb added [100, 500] snd_una 0 snd_una_max 1000:"
443                      "\n%U", format_tcp_scoreboard, sb, tc);
444
445   tcp_rcv_sacks (tc, 800);
446
447   if (verbose)
448     vlib_cli_output (vm, "\nsb ack [0, 800]:\n%U", format_tcp_scoreboard, sb,
449                      tc);
450
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);
462
463   /*
464    * One hole close to head, patch head, split in two and start acking
465    * the lowest part
466    */
467   scoreboard_clear (sb);
468   tc->snd_una = 0;
469   tc->snd_nxt = 1000;
470
471   block.start = 500;
472   block.end = 1000;
473   vec_add1 (tc->rcv_opts.sacks, block);
474   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
475
476   tcp_rcv_sacks (tc, 0);
477   if (verbose)
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);
484
485   vec_reset_length (tc->rcv_opts.sacks);
486   block.start = 300;
487   block.end = 400;
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);
491   if (verbose)
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);
504
505   /*
506    * Ack [100 300] in two steps
507    *
508    * Step 1. Ack [100 200] which delivers 100 of the bytes lost
509    */
510   tc->snd_una = 100;
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);
516
517   /*
518    * Step 2. Ack up to 300, although 300 400 is sacked, so this is interpreted
519    * as reneging.
520    */
521   tc->snd_una = 200;
522   tcp_rcv_sacks (tc, 300);
523   if (verbose)
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");
531
532   /*
533    * Ack [300 500]. Delivers reneged segment [300 400] and reneges bytes
534    * above 500
535    */
536   tc->snd_una = 300;
537   tcp_rcv_sacks (tc, 500);
538   if (verbose)
539     vlib_cli_output (vm, "\nacked [400, 500]:\n%U", format_tcp_scoreboard, sb,
540                      tc);
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);
551
552   /*
553    * Ack up to 1000 to deliver all bytes
554    */
555   tc->snd_una = 500;
556   tcp_rcv_sacks (tc, 1000);
557   if (verbose)
558     vlib_cli_output (vm, "\nAck high sacked:\n%U", format_tcp_scoreboard, sb,
559                      tc);
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");
565
566   /*
567    * Add [1200, 1500] and test that [1000, 1200] is lost (bytes condition)
568    * snd_una = 1000 and snd_una_max = 1600
569    */
570   tc->snd_una = 1000;
571   tc->snd_nxt = 1600;
572   vec_reset_length (tc->rcv_opts.sacks);
573   block.start = 1200;
574   block.end = 1500;
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);
578   if (verbose)
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");
592
593   /*
594    * Restart
595    */
596   scoreboard_clear (sb);
597   vec_reset_length (tc->rcv_opts.sacks);
598
599   /*
600    * Inject [100 500]
601    */
602
603   tc->flags |= TCP_CONN_FAST_RECOVERY | TCP_CONN_RECOVERY;
604   tc->snd_una = 0;
605   tc->snd_nxt = 1000;
606   sb->high_rxt = 0;
607
608   block.start = 100;
609   block.end = 500;
610   vec_add1 (tc->rcv_opts.sacks, block);
611   tc->rcv_opts.n_sack_blocks = vec_len (tc->rcv_opts.sacks);
612
613   tcp_rcv_sacks (tc, 0);
614
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");
619
620   /*
621    * Renege, sack all of the remaining bytes and cover some rxt bytes
622    */
623   sb->high_rxt = 700;
624   tc->rcv_opts.sacks[0].start = 500;
625   tc->rcv_opts.sacks[0].end = 1000;
626
627   tcp_rcv_sacks (tc, 100);
628
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",
634             sb->rxt_sacked);
635
636   /*
637    * Restart
638    */
639   scoreboard_clear (sb);
640   vec_reset_length (tc->rcv_opts.sacks);
641
642   /*
643    * Broken sacks:
644    * block.start > snd_nxt
645    * && block.start < blk.end
646    * && block.end <= snd_nxt
647    */
648   tc->flags = 0;
649   block.start = 2147483647;
650   block.end = 4294967295;
651   vec_add1 (tc->rcv_opts.sacks, block);
652   tc->snd_una = tc->snd_nxt = 1969067947;
653
654   tcp_rcv_sacks (tc, tc->snd_una);
655
656   /*
657    * Clear
658    */
659   scoreboard_clear (sb);
660   vec_reset_length (tc->rcv_opts.sacks);
661
662   return 0;
663 }
664
665 static int
666 tcp_test_sack_tx (vlib_main_t * vm, unformat_input_t * input)
667 {
668   tcp_connection_t _tc, *tc = &_tc;
669   sack_block_t *sacks;
670   int i, verbose = 0, expected;
671
672   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
673     {
674       if (unformat (input, "verbose"))
675         verbose = 1;
676       else
677         {
678           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
679                            input);
680           return -1;
681         }
682     }
683
684   clib_memset (tc, 0, sizeof (*tc));
685
686   /*
687    * Add odd sack block pairs
688    */
689   for (i = 1; i < 10; i += 2)
690     {
691       tcp_update_sack_list (tc, i * 100, (i + 1) * 100);
692     }
693
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,
698             900);
699
700   /*
701    * Try to add one extra
702    */
703   sacks = vec_dup (tc->snd_sacks);
704
705   tcp_update_sack_list (tc, 1100, 1200);
706   if (verbose)
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,
714             1100);
715
716   /* restore */
717   vec_free (tc->snd_sacks);
718   tc->snd_sacks = sacks;
719
720   /*
721    * Overlap first 2 segment
722    */
723   tc->rcv_nxt = 300;
724   tcp_update_sack_list (tc, 300, 300);
725   if (verbose)
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,
732             500);
733
734   /*
735    * Add a new segment
736    */
737   tcp_update_sack_list (tc, 1100, 1200);
738   if (verbose)
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,
745             1100);
746
747   /*
748    * Join middle segments
749    */
750   tcp_update_sack_list (tc, 800, 900);
751   if (verbose)
752     vlib_cli_output (vm, "join middle segments [800, 900]\n%U",
753                      format_tcp_sacks, tc);
754
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,
759             1100);
760
761   /*
762    * Advance rcv_nxt to overlap all
763    */
764   tc->rcv_nxt = 1200;
765   tcp_update_sack_list (tc, 1200, 1200);
766   if (verbose)
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);
770
771
772   /*
773    * Add 2 blocks, overwrite first and update rcv_nxt to also remove it
774    */
775
776   vec_reset_length (tc->snd_sacks);
777   tc->rcv_nxt = 0;
778
779   tcp_update_sack_list (tc, 100, 200);
780   tcp_update_sack_list (tc, 300, 400);
781
782   if (verbose)
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,
789             300);
790
791   tc->rcv_nxt = 100;
792   tcp_update_sack_list (tc, 100, 100);
793   if (verbose)
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,
800             300);
801   return 0;
802 }
803
804 static int
805 tcp_test_sack (vlib_main_t * vm, unformat_input_t * input)
806 {
807   int res = 0;
808
809   /* Run all tests */
810   if (unformat_check_input (input) == UNFORMAT_END_OF_INPUT)
811     {
812       if (tcp_test_sack_tx (vm, input))
813         {
814           return -1;
815         }
816
817       if (tcp_test_sack_rx (vm, input))
818         {
819           return -1;
820         }
821     }
822   else
823     {
824       if (unformat (input, "tx"))
825         {
826           res = tcp_test_sack_tx (vm, input);
827         }
828       else if (unformat (input, "rx"))
829         {
830           res = tcp_test_sack_rx (vm, input);
831         }
832     }
833
834   return res;
835 }
836
837 static int
838 tcp_test_lookup (vlib_main_t * vm, unformat_input_t * input)
839 {
840   session_main_t *smm = &session_main;
841   transport_connection_t _tc1, *tc1 = &_tc1, _tc2, *tc2 = &_tc2, *tconn;
842   tcp_connection_t *tc;
843   session_t *s, *s1;
844   u8 cmp = 0, is_filtered = 0;
845   u32 sidx;
846
847   /*
848    * Allocate fake session and connection 1
849    */
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;
853
854   tc = tcp_connection_alloc (0);
855   tc->connection.s_index = s->session_index;
856   s->connection_index = tc->connection.c_index;
857
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));
865
866   /*
867    * Allocate fake session and connection 2
868    */
869   pool_get (smm->wrk[0].sessions, s);
870   clib_memset (s, 0, sizeof (*s));
871   s->session_index = s - smm->wrk[0].sessions;
872
873   tc = tcp_connection_alloc (0);
874   tc->connection.s_index = s->session_index;
875   s->connection_index = tc->connection.c_index;
876
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));
884
885   /*
886    * Confirm that connection lookup works
887    */
888
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,
892                                          &tc1->rmt_ip.ip4,
893                                          tc1->lcl_port, tc1->rmt_port,
894                                          tc1->proto, 0, &is_filtered);
895
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);
901
902   /*
903    * Non-existing connection lookup should not work
904    */
905
906   tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
907                                          &tc2->rmt_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");
911
912   /*
913    * Delete and lookup again
914    */
915   session_lookup_del_connection (tc1);
916   tconn = session_lookup_connection_wt4 (0, &tc1->lcl_ip.ip4,
917                                          &tc1->rmt_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,
922                                          &tc2->rmt_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");
926
927   /*
928    * Re-add and lookup tc2
929    */
930   session_lookup_add_connection (tc1, tc1->s_index);
931   tconn = session_lookup_connection_wt4 (0, &tc2->lcl_ip.ip4,
932                                          &tc2->rmt_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");
936
937   return 0;
938 }
939
940 static int
941 tcp_test_session (vlib_main_t * vm, unformat_input_t * input)
942 {
943   int rv = 0;
944   tcp_connection_t *tc0;
945   ip4_address_t local, remote;
946   u16 local_port, remote_port;
947   int is_add = 1;
948
949
950   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
951     {
952       if (unformat (input, "del"))
953         is_add = 0;
954       else if (unformat (input, "add"))
955         is_add = 1;
956       else
957         break;
958     }
959
960   if (is_add)
961     {
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);
966
967       tc0 = tcp_connection_alloc (0);
968
969       tc0->state = TCP_STATE_ESTABLISHED;
970       tc0->rcv_las = 1;
971       tc0->c_lcl_port = local_port;
972       tc0->c_rmt_port = remote_port;
973       tc0->c_is_ip4 = 1;
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);
979
980       TCP_EVT (TCP_EVT_OPEN, tc0);
981
982       if (session_stream_accept (&tc0->connection, 0 /* listener index */ ,
983                                  0 /* thread index */ , 0 /* notify */ ))
984         clib_warning ("stream_session_accept failed");
985
986       session_stream_accept_notify (&tc0->connection);
987     }
988   else
989     {
990       tc0 = tcp_connection_get (0 /* connection index */ , 0 /* thread */ );
991       tc0->state = TCP_STATE_CLOSED;
992       session_transport_closing_notify (&tc0->connection);
993     }
994
995   return rv;
996 }
997
998 static inline int
999 tbt_seq_lt (u32 a, u32 b)
1000 {
1001   return seq_lt (a, b);
1002 }
1003
1004 static void
1005 tcp_test_set_time (u32 thread_index, u32 val)
1006 {
1007   session_main.wrk[thread_index].last_vlib_time = val;
1008   tcp_set_time_now (&tcp_main.wrk_ctx[thread_index], val);
1009 }
1010
1011 static int
1012 tcp_test_delivery (vlib_main_t * vm, unformat_input_t * input)
1013 {
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;
1024
1025   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1026     {
1027       if (unformat (input, "verbose"))
1028         verbose = 1;
1029       else
1030         {
1031           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
1032                            input);
1033           return -1;
1034         }
1035     }
1036
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);
1041
1042   tcp_bt_init (tc);
1043   bt = tc->bt;
1044
1045   /*
1046    * Track simple bursts without rxt
1047    */
1048
1049   /* 1) track first burst a time 1 */
1050   tcp_bt_track_tx (tc, burst);
1051
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");
1062
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;
1067
1068   tcp_bt_sample_delivery_rate (tc, rs);
1069
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);
1079
1080   /* 3) track second burst at time 2 */
1081   tcp_bt_track_tx (tc, burst);
1082   tc->snd_nxt += burst;
1083
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;
1088
1089   TCP_TEST (pool_elts (bt->samples) == 2, "should have 2 samples");
1090
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");
1095
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");
1100
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;
1105
1106   tcp_bt_sample_delivery_rate (tc, rs);
1107
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",
1112             tc->delivered);
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);
1118
1119   /*
1120    * Track retransmissions
1121    *
1122    * snd_una should be 300 at this point
1123    */
1124
1125   snd_una = tc->snd_una;
1126
1127   /* 1) track first burst at time 4 */
1128   tcp_bt_track_tx (tc, burst);
1129   tc->snd_nxt += burst;
1130
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;
1135
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;
1140
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;
1147
1148   /* 5) check delivery rate at time 8
1149    *
1150    * tc->snd_una = snd_una + 10
1151    * sacks:
1152    * [snd_una + burst, snd_una + burst + 10]
1153    * [snd_una + 2 * burst + 10, snd_una + 2 * burst + 20]
1154    */
1155   tcp_test_set_time (thread_index, 8);
1156   tc->snd_una += 10;
1157   tc->bytes_acked = 10;
1158   sb->last_sacked_bytes = 20;
1159
1160   TCP_TEST (pool_elts (bt->samples) == 4, "there should be 4 samples");
1161
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;
1168
1169   tcp_bt_sample_delivery_rate (tc, rs);
1170
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",
1180             rs->interval_time);
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);
1189
1190   /* 6) Retransmit and track at time 9
1191    *
1192    * delivered = 3 * burst + 30
1193    * delivered_time = 8 (last ack)
1194    *
1195    * segments:
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]
1199    */
1200   tcp_test_set_time (thread_index, 9);
1201
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));
1207
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));
1212
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));
1218
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;
1225
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++)
1229     {
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;
1237     }
1238
1239   /* 7) check delivery rate at time 10
1240    *
1241    * tc->snd_una = snd_una + 2 * burst
1242    * sacks:
1243    * [snd_una + 2 * burst + 20, snd_una + 2 * burst + 30]
1244    * [snd_una + 2 * burst + 50, snd_una + 2 * burst + 60]
1245    */
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;
1250
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;
1255
1256   tcp_bt_sample_delivery_rate (tc, rs);
1257
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",
1268             rs->interval_time);
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",
1271             rs->delivered);
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);
1279
1280
1281   /*
1282    * 8) check delivery rate at time 11
1283    */
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;
1289
1290   memset (rs, 0, sizeof (*rs));
1291   tcp_bt_sample_delivery_rate (tc, rs);
1292
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
1301    * is 9 - 4 = 5 */
1302   TCP_TEST (rs->interval_time == 5, "ack time should be 5 is %.2f",
1303             rs->interval_time);
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",
1307             rs->delivered);
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);
1314
1315   /*
1316    * 9) test flush
1317    */
1318
1319   tcp_bt_track_tx (tc, burst);
1320   tc->snd_nxt += burst;
1321
1322   tcp_test_set_time (thread_index, 12);
1323   tcp_bt_track_tx (tc, burst);
1324   tc->snd_nxt += burst;
1325
1326   tcp_bt_flush_samples (tc);
1327
1328   /*
1329    * Cleanup
1330    */
1331   vec_free (sacks);
1332   vec_free (min_seqs);
1333   tcp_bt_cleanup (tc);
1334   return 0;
1335 }
1336
1337 static int
1338 tcp_test_bt (vlib_main_t * vm, unformat_input_t * input)
1339 {
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;
1346   u32 head;
1347   sack_block_t *blk;
1348
1349   /* Init data structures */
1350   memset (tc, 0, sizeof (*tc));
1351   tcp_bt_init (tc);
1352   bt = tc->bt;
1353
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);
1358   tc->snd_nxt += 100;
1359
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);
1363   head = 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");
1370
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);
1375   tc->snd_nxt += 100;
1376
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");
1383
1384   /* 3) acked partially at time 3 */
1385   /* ACK:150 */
1386   /* --> [150:200] */
1387   session_main.wrk[thread_index].last_vlib_time = 3;
1388   tc->snd_una = 150;
1389   tc->bytes_acked = 150;
1390   tc->sack_sb.last_sacked_bytes = 0;
1391   tcp_bt_sample_delivery_rate (tc, rs);
1392
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");
1396   head = bt->head;
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");
1400
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);
1405   tc->snd_nxt += 100;
1406
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");
1413
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);
1418   tc->snd_nxt += 100;
1419
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");
1426
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;
1431   tc->snd_una = 250;
1432   tc->bytes_acked = 100;
1433   tc->sack_sb.last_sacked_bytes = 50;
1434   vec_add2 (tc->rcv_opts.sacks, blk, 1);
1435   blk->start = 350;
1436   blk->end = 400;
1437   tcp_bt_sample_delivery_rate (tc, rs);
1438
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");
1442   head = bt->head;
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");
1453
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);
1458   tc->snd_nxt += 100;
1459
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");
1477
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);
1484
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");
1500
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;
1505   tc->snd_una = 400;
1506   tc->bytes_acked = 150;
1507   tc->sack_sb.last_sacked_bytes = 30;
1508   vec_add2 (tc->rcv_opts.sacks, blk, 1);
1509   blk->start = 420;
1510   blk->end = 450;
1511   tcp_bt_sample_delivery_rate (tc, rs);
1512
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");
1516   head = bt->head;
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");
1530
1531   /* 10) acked partially at time 10 */
1532   /* ACK:500 */
1533   /* --> [] */
1534   session_main.wrk[thread_index].last_vlib_time = 3;
1535   tc->snd_una = 500;
1536   tc->bytes_acked = 100;
1537   tc->sack_sb.last_sacked_bytes = 0;
1538   tcp_bt_sample_delivery_rate (tc, rs);
1539
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");
1544
1545   return 0;
1546 }
1547
1548 static clib_error_t *
1549 tcp_test (vlib_main_t * vm,
1550           unformat_input_t * input, vlib_cli_command_t * cmd_arg)
1551 {
1552   int res = 0;
1553
1554   vnet_session_enable_disable (vm, 1);
1555
1556   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1557     {
1558       if (unformat (input, "sack"))
1559         {
1560           res = tcp_test_sack (vm, input);
1561         }
1562       else if (unformat (input, "session"))
1563         {
1564           res = tcp_test_session (vm, input);
1565         }
1566       else if (unformat (input, "lookup"))
1567         {
1568           res = tcp_test_lookup (vm, input);
1569         }
1570       else if (unformat (input, "delivery"))
1571         {
1572           res = tcp_test_delivery (vm, input);
1573         }
1574       else if (unformat (input, "bt"))
1575         {
1576           res = tcp_test_bt (vm, input);
1577         }
1578       else if (unformat (input, "all"))
1579         {
1580           if ((res = tcp_test_sack (vm, input)))
1581             goto done;
1582           if ((res = tcp_test_lookup (vm, input)))
1583             goto done;
1584           if ((res = tcp_test_delivery (vm, input)))
1585             goto done;
1586         }
1587       else
1588         break;
1589     }
1590
1591 done:
1592   if (res)
1593     return clib_error_return (0, "TCP unit test failed");
1594   return 0;
1595 }
1596
1597 VLIB_CLI_COMMAND (tcp_test_command, static) =
1598 {
1599   .path = "test tcp",
1600   .short_help = "internal tcp unit tests",
1601   .function = tcp_test,
1602 };
1603
1604 /*
1605  * fd.io coding-style-patch-verification: ON
1606  *
1607  * Local Variables:
1608  * eval: (c-set-style "gnu")
1609  * End:
1610  */