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