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