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