LCOV - code coverage report
Current view: top level - plugins/unittest - svm_fifo_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 1144 1445 79.2 %
Date: 2023-07-05 22:20:52 Functions: 38 42 90.5 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 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 <svm/svm_fifo.h>
      16             : #include <vlib/vlib.h>
      17             : #include <svm/svm_common.h>
      18             : #include <svm/fifo_segment.h>
      19             : 
      20             : #define SFIFO_TEST_I(_cond, _comment, _args...)                 \
      21             : ({                                                              \
      22             :   int _evald = (_cond);                                         \
      23             :   if (!(_evald)) {                                              \
      24             :     fformat(stderr, "FAIL:%d: " _comment "\n",                      \
      25             :             __LINE__, ##_args);                                 \
      26             :   } else {                                                      \
      27             :     fformat(stderr, "PASS:%d: " _comment "\n",                      \
      28             :             __LINE__, ##_args);                                 \
      29             :   }                                                             \
      30             :   _evald;                                                       \
      31             : })
      32             : 
      33             : #define SFIFO_TEST(_cond, _comment, _args...)                   \
      34             : {                                                               \
      35             :     if (!SFIFO_TEST_I(_cond, _comment, ##_args)) {              \
      36             :         return 1;                                               \
      37             :     }                                                           \
      38             : }
      39             : 
      40             : typedef struct
      41             : {
      42             :   u32 offset;
      43             :   u32 len;
      44             : } test_pattern_t;
      45             : 
      46             : /* *INDENT-OFF* */
      47             : test_pattern_t test_pattern[] = {
      48             :   {380, 8}, {768, 8}, {1156, 8}, {1544, 8}, {1932, 8}, {2320, 8}, {2708, 8},
      49             :   {2992, 8}, {372, 8}, {760, 8}, {1148, 8}, {1536, 8}, {1924, 8}, {2312, 8},
      50             :   {2700, 8}, {2984, 8}, {364, 8}, {752, 8}, {1140, 8}, {1528, 8}, {1916, 8},
      51             :   {2304, 8}, {2692, 8}, {2976, 8}, {356, 8}, {744, 8}, {1132, 8}, {1520, 8},
      52             :   {1908, 8}, {2296, 8}, {2684, 8}, {2968, 8}, {348, 8}, {736, 8}, {1124, 8},
      53             :   {1512, 8}, {1900, 8}, {2288, 8}, {2676, 8}, {2960, 8}, {340, 8}, {728, 8},
      54             :   {1116, 8}, {1504, 8}, {1892, 8}, {2280, 8}, {2668, 8}, {2952, 8}, {332, 8},
      55             :   {720, 8}, {1108, 8}, {1496, 8}, {1884, 8}, {2272, 8}, {2660, 8}, {2944, 8},
      56             :   {324, 8}, {712, 8}, {1100, 8}, {1488, 8}, {1876, 8}, {2264, 8}, {2652, 8},
      57             :   {2936, 8}, {316, 8}, {704, 8}, {1092, 8}, {1480, 8}, {1868, 8}, {2256, 8},
      58             :   {2644, 8}, {2928, 8}, {308, 8}, {696, 8}, {1084, 8}, {1472, 8}, {1860, 8},
      59             :   {2248, 8}, {2636, 8}, {2920, 8}, {300, 8}, {688, 8}, {1076, 8}, {1464, 8},
      60             :   {1852, 8}, {2240, 8}, {2628, 8}, {2912, 8}, {292, 8}, {680, 8}, {1068, 8},
      61             :   {1456, 8}, {1844, 8}, {2232, 8}, {2620, 8}, {2904, 8}, {284, 8}, {672, 8},
      62             :   {1060, 8}, {1448, 8}, {1836, 8}, {2224, 8}, {2612, 8}, {2896, 8}, {276, 8},
      63             :   {664, 8}, {1052, 8}, {1440, 8}, {1828, 8},  {2216, 8}, {2604, 8}, {2888, 8},
      64             :   {268, 8}, {656, 8}, {1044, 8}, {1432, 8}, {1820, 8}, {2208, 8}, {2596, 8},
      65             :   {2880, 8}, {260, 8}, {648, 8}, {1036, 8}, {1424, 8}, {1812, 8}, {2200, 8},
      66             :   {2588, 8}, {2872, 8}, {252, 8}, {640, 8}, {1028, 8}, {1416, 8}, {1804, 8},
      67             :   {2192, 8}, {2580, 8}, {2864, 8}, {244, 8}, {632, 8}, {1020, 8}, {1408, 8},
      68             :   {1796, 8}, {2184, 8}, {2572, 8}, {2856, 8}, {236, 8}, {624, 8}, {1012, 8},
      69             :   {1400, 8}, {1788, 8}, {2176, 8}, {2564, 8}, {2848, 8}, {228, 8}, {616, 8},
      70             :   {1004, 8}, {1392, 8}, {1780, 8}, {2168, 8}, {2556, 8}, {2840, 8}, {220, 8},
      71             :   {608, 8}, {996, 8}, {1384, 8}, {1772, 8}, {2160, 8}, {2548, 8}, {2832, 8},
      72             :   {212, 8}, {600, 8}, {988, 8}, {1376, 8}, {1764, 8}, {2152, 8}, {2540, 8},
      73             :   {2824, 8}, {204, 8}, {592, 8}, {980, 8}, {1368, 8}, {1756, 8}, {2144, 8},
      74             :   {2532, 8}, {2816, 8}, {196, 8}, {584, 8}, {972, 8}, {1360, 8}, {1748, 8},
      75             :   {2136, 8}, {2524, 8}, {2808, 8}, {188, 8}, {576, 8}, {964, 8}, {1352, 8},
      76             :   {1740, 8}, {2128, 8}, {2516, 8}, {2800, 8}, {180, 8}, {568, 8}, {956, 8},
      77             :   {1344, 8}, {1732, 8}, {2120, 8}, {2508, 8}, {2792, 8}, {172, 8}, {560, 8},
      78             :   {948, 8}, {1336, 8}, {1724, 8}, {2112, 8}, {2500, 8}, {2784, 8}, {164, 8},
      79             :   {552, 8}, {940, 8}, {1328, 8}, {1716, 8}, {2104, 8}, {2492, 8}, {2776, 8},
      80             :   {156, 8}, {544, 8}, {932, 8}, {1320, 8}, {1708, 8}, {2096, 8}, {2484, 8},
      81             :   {2768, 8}, {148, 8}, {536, 8}, {924, 8}, {1312, 8}, {1700, 8}, {2088, 8},
      82             :   {2476, 8}, {2760, 8}, {140, 8}, {528, 8}, {916, 8}, {1304, 8}, {1692, 8},
      83             :   {2080, 8}, {2468, 8}, {2752, 8}, {132, 8}, {520, 8}, {908, 8}, {1296, 8},
      84             :   {1684, 8}, {2072, 8}, {2460, 8}, {2744, 8}, {124, 8}, {512, 8}, {900, 8},
      85             :   {1288, 8}, {1676, 8}, {2064, 8}, {2452, 8}, {2736, 8}, {116, 8}, {504, 8},
      86             :   {892, 8}, {1280, 8}, {1668, 8}, {2056, 8}, {2444, 8}, {2728, 8}, {108, 8},
      87             :   {496, 8}, {884, 8}, {1272, 8}, {1660, 8}, {2048, 8}, {2436, 8}, {2720, 8},
      88             :   {100, 8}, {488, 8}, {876, 8}, {1264, 8}, {1652, 8}, {2040, 8}, {2428, 8},
      89             :   {2716, 4}, {92, 8}, {480, 8}, {868, 8}, {1256, 8}, {1644, 8}, {2032, 8},
      90             :   {2420, 8}, {84, 8}, {472, 8}, {860, 8}, {1248, 8}, {1636, 8}, {2024, 8},
      91             :   {2412, 8}, {76, 8}, {464, 8}, {852, 8}, {1240, 8}, {1628, 8}, {2016, 8},
      92             :   {2404, 8}, {68, 8}, {456, 8}, {844, 8}, {1232, 8}, {1620, 8}, {2008, 8},
      93             :   {2396, 8}, {60, 8}, {448, 8}, {836, 8}, {1224, 8}, {1612, 8}, {2000, 8},
      94             :   {2388, 8}, {52, 8}, {440, 8}, {828, 8}, {1216, 8}, {1604, 8}, {1992, 8},
      95             :   {2380, 8}, {44, 8}, {432, 8}, {820, 8}, {1208, 8}, {1596, 8}, {1984, 8},
      96             :   {2372, 8}, {36, 8}, {424, 8}, {812, 8}, {1200, 8}, {1588, 8}, {1976, 8},
      97             :   {2364, 8}, {28, 8}, {416, 8}, {804, 8}, {1192, 8}, {1580, 8}, {1968, 8},
      98             :   {2356, 8}, {20, 8}, {408, 8}, {796, 8}, {1184, 8}, {1572, 8}, {1960, 8},
      99             :   {2348, 8}, {12, 8}, {400, 8}, {788, 8}, {1176, 8}, {1564, 8}, {1952, 8},
     100             :   {2340, 8}, {4, 8}, {392, 8}, {780, 8}, {1168, 8}, {1556, 8}, {1944, 8},
     101             :   {2332, 8},
     102             :   /* missing from original data set */
     103             :   {388, 4}, {776, 4}, {1164, 4}, {1552, 4}, {1940, 4}, {2328, 4},
     104             : };
     105             : /* *INDENT-ON* */
     106             : 
     107             : int
     108        2613 : pattern_cmp (const void *arg1, const void *arg2)
     109             : {
     110        2613 :   test_pattern_t *a1 = (test_pattern_t *) arg1;
     111        2613 :   test_pattern_t *a2 = (test_pattern_t *) arg2;
     112             : 
     113        2613 :   if (a1->offset < a2->offset)
     114        1322 :     return -1;
     115        1291 :   else if (a1->offset > a2->offset)
     116        1291 :     return 1;
     117           0 :   return 0;
     118             : }
     119             : 
     120             : static u8
     121           2 : fifo_validate_pattern (vlib_main_t * vm, test_pattern_t * pattern,
     122             :                        u32 pattern_length)
     123             : {
     124           2 :   test_pattern_t *tp = pattern;
     125             :   int i;
     126             : 
     127             :   /* Go through the pattern and make 100% sure it's sane */
     128         389 :   for (i = 0; i < pattern_length - 1; i++)
     129             :     {
     130         387 :       if (tp->offset + tp->len != (tp + 1)->offset)
     131             :         {
     132           0 :           vlib_cli_output (vm, "[%d] missing {%d, %d}", i,
     133           0 :                            (tp->offset + tp->len),
     134           0 :                            (tp + 1)->offset - (tp->offset + tp->len));
     135           0 :           return 0;
     136             :         }
     137         387 :       tp++;
     138             :     }
     139           2 :   return 1;
     140             : }
     141             : 
     142             : static test_pattern_t *
     143           1 : fifo_get_validate_pattern (vlib_main_t * vm, test_pattern_t * test_data,
     144             :                            u32 test_data_len)
     145             : {
     146           1 :   test_pattern_t *validate_pattern = 0;
     147             : 
     148             :   /* Validate, and try segments in order... */
     149           1 :   vec_validate (validate_pattern, test_data_len - 1);
     150           1 :   memcpy (validate_pattern, test_data,
     151             :           test_data_len * sizeof (test_pattern_t));
     152           1 :   qsort ((u8 *) validate_pattern, test_data_len, sizeof (test_pattern_t),
     153             :          pattern_cmp);
     154             : 
     155           1 :   if (fifo_validate_pattern (vm, validate_pattern, test_data_len) == 0)
     156           0 :     return 0;
     157             : 
     158           1 :   return validate_pattern;
     159             : }
     160             : 
     161             : static fifo_segment_t *
     162          15 : fifo_segment_prepare (fifo_segment_main_t * sm, char *seg_name, u32 seg_size)
     163             : {
     164          15 :   fifo_segment_create_args_t _a, *a = &_a;
     165             : 
     166          15 :   clib_memset (a, 0, sizeof (*a));
     167          15 :   a->segment_name = seg_name;
     168          15 :   a->segment_size = seg_size ? seg_size : 32 << 20;
     169             : 
     170          15 :   if (fifo_segment_create (sm, a))
     171           0 :     return 0;
     172             : 
     173          15 :   return fifo_segment_get_segment (sm, a->new_segment_indices[0]);
     174             : }
     175             : 
     176             : static void
     177          15 : ft_fifo_segment_free (fifo_segment_main_t * sm, fifo_segment_t * fs)
     178             : {
     179          15 :   fifo_segment_delete (sm, fs);
     180          15 : }
     181             : 
     182             : static svm_fifo_t *
     183         149 : fifo_segment_alloc_fifo (fifo_segment_t * fs, u32 data_bytes,
     184             :                          fifo_segment_ftype_t ftype)
     185             : {
     186         149 :   return fifo_segment_alloc_fifo_w_slice (fs, 0, data_bytes, ftype);
     187             : }
     188             : 
     189             : static svm_fifo_t *
     190          19 : fifo_prepare (fifo_segment_t * fs, u32 fifo_size)
     191             : {
     192             :   svm_fifo_t *f;
     193             :   svm_fifo_chunk_t *c;
     194             : 
     195          19 :   f = fifo_segment_alloc_fifo (fs, fifo_size, FIFO_SEGMENT_RX_FIFO);
     196             : 
     197             :   /* Paint 1st fifo chunk with -1's */
     198          19 :   c = f_head_cptr (f);
     199          19 :   clib_memset (c->data, 0xFF, c->length);
     200             : 
     201          19 :   svm_fifo_init_ooo_lookup (f, 1 /* deq ooo */ );
     202          19 :   return f;
     203             : }
     204             : 
     205             : static void
     206          19 : ft_fifo_free (fifo_segment_t * fs, svm_fifo_t * f)
     207             : {
     208          19 :   fifo_segment_free_fifo (fs, f);
     209          19 : }
     210             : 
     211             : static int
     212         124 : compare_data (u8 * data1, u8 * data2, u32 start, u32 len, u32 * index)
     213             : {
     214             :   int i;
     215             : 
     216    12676100 :   for (i = start; i < start + len; i++)
     217             :     {
     218    12676000 :       if (data1[i] != data2[i])
     219             :         {
     220           0 :           *index = i;
     221           0 :           return 1;
     222             :         }
     223             :     }
     224         124 :   return 0;
     225             : }
     226             : 
     227             : int
     228           1 : sfifo_test_fifo1 (vlib_main_t * vm, unformat_input_t * input)
     229             : {
     230           1 :   u32 fifo_size = 1 << 20, *test_data = 0, offset, data_word, test_data_len;
     231           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
     232           1 :   u8 *data, *s, *data_buf = 0;
     233           1 :   int i, rv, verbose = 0;
     234             :   ooo_segment_t *ooo_seg;
     235             :   fifo_segment_t *fs;
     236             :   svm_fifo_t *f;
     237             :   u32 j;
     238             : 
     239           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     240             :     {
     241           0 :       if (unformat (input, "verbose"))
     242           0 :         verbose = 1;
     243             :     }
     244             : 
     245           1 :   test_data_len = fifo_size / sizeof (u32);
     246           1 :   vec_validate (test_data, test_data_len - 1);
     247             : 
     248      262145 :   for (i = 0; i < vec_len (test_data); i++)
     249      262144 :     test_data[i] = i;
     250             : 
     251           1 :   fs = fifo_segment_prepare (fsm, "fifo-test1", 0);
     252           1 :   f = fifo_prepare (fs, fifo_size);
     253             : 
     254             :   /*
     255             :    * Enqueue an initial (un-dequeued) chunk
     256             :    */
     257           1 :   rv = svm_fifo_enqueue (f, sizeof (u32), (u8 *) test_data);
     258           1 :   SFIFO_TEST ((rv == sizeof (u32)), "enqueued %d", rv);
     259           1 :   SFIFO_TEST ((f->shr->tail == 4), "fifo tail %u", f->shr->tail);
     260             : 
     261             :   /*
     262             :    * Create 3 chunks in the future. The offsets are relative
     263             :    * to the current fifo tail
     264             :    */
     265           4 :   for (i = 0; i < 3; i++)
     266             :     {
     267           3 :       offset = (2 * i + 1) * sizeof (u32) - f->shr->tail;
     268           3 :       data = (u8 *) (test_data + (2 * i + 1));
     269           3 :       if (i == 0)
     270             :         {
     271           1 :           rv = svm_fifo_enqueue (f, sizeof (u32), data);
     272           1 :           rv = rv > 0 ? 0 : rv;
     273             :         }
     274             :       else
     275           2 :         rv = svm_fifo_enqueue_with_offset (f, offset, sizeof (u32), data);
     276           3 :       if (verbose)
     277           0 :         vlib_cli_output (vm, "add [%d] [%d, %d]", 2 * i + 1, offset,
     278             :                          offset + sizeof (u32));
     279           3 :       if (rv)
     280             :         {
     281           0 :           clib_warning ("enqueue returned %d", rv);
     282           0 :           goto err;
     283             :         }
     284             :     }
     285             : 
     286           1 :   if (verbose)
     287           0 :     vlib_cli_output (vm, "fifo after odd segs: %U", format_svm_fifo, f, 1);
     288             : 
     289           1 :   SFIFO_TEST ((f->shr->tail == 8), "fifo tail %u", f->shr->tail);
     290           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 2),
     291             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     292             : 
     293             :   /*
     294             :    * Try adding a completely overlapped segment
     295             :    */
     296           1 :   offset = 3 * sizeof (u32) - f->shr->tail;
     297           1 :   data = (u8 *) (test_data + 3);
     298           1 :   rv = svm_fifo_enqueue_with_offset (f, offset, sizeof (u32), data);
     299           1 :   if (rv)
     300             :     {
     301           0 :       clib_warning ("enqueue returned %d", rv);
     302           0 :       goto err;
     303             :     }
     304             : 
     305           1 :   if (verbose)
     306           0 :     vlib_cli_output (vm, "fifo after overlap seg: %U", format_svm_fifo, f, 1);
     307             : 
     308           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 2),
     309             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     310             : 
     311             :   /*
     312             :    * Make sure format functions are not buggy
     313             :    */
     314           1 :   s = format (0, "%U", format_svm_fifo, f, 2);
     315           1 :   vec_free (s);
     316             : 
     317             :   /*
     318             :    * Paint some of missing data backwards
     319             :    */
     320           3 :   for (i = 3; i > 1; i--)
     321             :     {
     322           2 :       offset = (2 * i + 0) * sizeof (u32) - f->shr->tail;
     323           2 :       data = (u8 *) (test_data + (2 * i + 0));
     324           2 :       rv = svm_fifo_enqueue_with_offset (f, offset, sizeof (u32), data);
     325           2 :       if (verbose)
     326           0 :         vlib_cli_output (vm, "add [%d] [%d, %d]", 2 * i, offset,
     327             :                          offset + sizeof (u32));
     328           2 :       if (rv)
     329             :         {
     330           0 :           clib_warning ("enqueue returned %d", rv);
     331           0 :           goto err;
     332             :         }
     333             :     }
     334             : 
     335           1 :   if (verbose)
     336           0 :     vlib_cli_output (vm, "fifo before missing link: %U", format_svm_fifo, f,
     337             :                      1);
     338           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 1),
     339             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     340           1 :   ooo_seg = svm_fifo_first_ooo_segment (f);
     341           1 :   SFIFO_TEST ((ooo_seg->start == 12),
     342             :               "first ooo seg position %u", ooo_seg->start);
     343           1 :   SFIFO_TEST ((ooo_seg->length == 16),
     344             :               "first ooo seg length %u", ooo_seg->length);
     345             : 
     346             :   /*
     347             :    * Enqueue the missing u32
     348             :    */
     349           1 :   rv = svm_fifo_enqueue (f, sizeof (u32), (u8 *) (test_data + 2));
     350           1 :   if (verbose)
     351           0 :     vlib_cli_output (vm, "fifo after missing link: %U", format_svm_fifo, f,
     352             :                      1);
     353           1 :   SFIFO_TEST ((rv == 20), "bytes to be enqueued %u", rv);
     354           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 0),
     355             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     356             : 
     357             :   /*
     358             :    * Collect results
     359             :    */
     360           8 :   for (i = 0; i < 7; i++)
     361             :     {
     362           7 :       rv = svm_fifo_dequeue (f, sizeof (u32), (u8 *) & data_word);
     363           7 :       if (rv != sizeof (u32))
     364             :         {
     365           0 :           clib_warning ("bytes dequeues %u", rv);
     366           0 :           goto err;
     367             :         }
     368           7 :       if (data_word != test_data[i])
     369             :         {
     370           0 :           clib_warning ("recovered [%d] %d not %d", i, data_word,
     371             :                         test_data[i]);
     372           0 :           goto err;
     373             :         }
     374             :     }
     375             : 
     376             :   /*
     377             :    * Test segment overlaps: last ooo segment overlaps all
     378             :    */
     379           1 :   ft_fifo_free (fs, f);
     380           1 :   f = fifo_prepare (fs, fifo_size);
     381             : 
     382           5 :   for (i = 0; i < 4; i++)
     383             :     {
     384           4 :       offset = (2 * i + 1) * sizeof (u32) - f->shr->tail;
     385           4 :       data = (u8 *) (test_data + (2 * i + 1));
     386           4 :       rv = svm_fifo_enqueue_with_offset (f, offset, sizeof (u32), data);
     387           4 :       if (verbose)
     388           0 :         vlib_cli_output (vm, "add [%d] [%d, %d]", 2 * i + 1, offset,
     389             :                          offset + sizeof (u32));
     390           4 :       if (rv)
     391             :         {
     392           0 :           clib_warning ("enqueue returned %d", rv);
     393           0 :           goto err;
     394             :         }
     395             :     }
     396             : 
     397           1 :   rv = svm_fifo_enqueue_with_offset (f, 8 - f->shr->tail, 21, data);
     398           1 :   SFIFO_TEST ((rv == 0), "ooo enqueued %u", rv);
     399           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 1),
     400             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     401             : 
     402             :   /* add missing data to be able to dequeue something */
     403           1 :   rv = svm_fifo_enqueue (f, 4, data);
     404           1 :   SFIFO_TEST ((rv == 32), "enqueued %u", rv);
     405           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 0),
     406             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     407             : 
     408           1 :   vec_validate (data_buf, vec_len (test_data));
     409           1 :   svm_fifo_peek (f, 0, 4, data_buf);
     410           1 :   if (compare_data (data_buf, data, 0, 4, &j))
     411           0 :     SFIFO_TEST (0, "[%d] peeked %u expected %u", j, data_buf[j], data[j]);
     412           1 :   svm_fifo_peek (f, 8, 21, data_buf);
     413           1 :   if (compare_data (data_buf, data, 0, 21, &j))
     414           0 :     SFIFO_TEST (0, "[%d] peeked %u expected %u", j, data_buf[j], data[j]);
     415           1 :   vec_reset_length (data_buf);
     416             : 
     417             :   /*
     418             :    * Test segment overlaps: enqueue and overlap ooo segments
     419             :    */
     420           1 :   ft_fifo_free (fs, f);
     421           1 :   f = fifo_prepare (fs, fifo_size);
     422             : 
     423           5 :   for (i = 0; i < 4; i++)
     424             :     {
     425           4 :       offset = (2 * i + 1) * sizeof (u32) - f->shr->tail;
     426           4 :       data = (u8 *) (test_data + (2 * i + 1));
     427           4 :       rv = svm_fifo_enqueue_with_offset (f, offset, sizeof (u32), data);
     428           4 :       if (verbose)
     429           0 :         vlib_cli_output (vm, "add [%d] [%d, %d]", 2 * i + 1, offset,
     430             :                          offset + sizeof (u32));
     431           4 :       if (rv)
     432             :         {
     433           0 :           clib_warning ("enqueue returned %d", rv);
     434           0 :           goto err;
     435             :         }
     436             :     }
     437             : 
     438           1 :   if (verbose)
     439           0 :     vlib_cli_output (vm, "fifo after enqueue: %U", format_svm_fifo, f, 1);
     440             : 
     441           1 :   rv = svm_fifo_enqueue (f, 29, data);
     442           1 :   if (verbose)
     443           0 :     vlib_cli_output (vm, "fifo after enqueueing 29: %U", format_svm_fifo, f,
     444             :                      1);
     445           1 :   SFIFO_TEST ((rv == 32), "ooo enqueued %u", rv);
     446           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 0),
     447             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     448             : 
     449           1 :   vec_validate (data_buf, vec_len (data));
     450           1 :   svm_fifo_peek (f, 0, vec_len (data), data_buf);
     451           1 :   if (compare_data (data_buf, data, 0, vec_len (data), &j))
     452             :     {
     453           0 :       SFIFO_TEST (0, "[%d] peeked %u expected %u", j, data_buf[j], data[j]);
     454             :     }
     455             : 
     456             :   /* Try to peek beyond the data */
     457           1 :   rv = svm_fifo_peek (f, svm_fifo_max_dequeue (f), vec_len (data), data_buf);
     458           1 :   SFIFO_TEST ((rv == 0), "peeked %u expected 0", rv);
     459             : 
     460           1 :   vec_free (data_buf);
     461           1 :   ft_fifo_free (fs, f);
     462           1 :   ft_fifo_segment_free (fsm, fs);
     463           1 :   vec_free (test_data);
     464             : 
     465           1 :   return 0;
     466             : 
     467           0 : err:
     468           0 :   ft_fifo_free (fs, f);
     469           0 :   ft_fifo_segment_free (fsm, fs);
     470           0 :   vec_free (test_data);
     471             : 
     472           0 :   return -1;
     473             : }
     474             : 
     475             : static int
     476           1 : sfifo_test_fifo2 (vlib_main_t * vm)
     477             : {
     478           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
     479             :   test_pattern_t *tp, *vp, *test_data;
     480           1 :   u32 fifo_size = (1 << 20) + 1;
     481             :   int i, rv, test_data_len;
     482             :   ooo_segment_t *ooo_seg;
     483             :   fifo_segment_t *fs;
     484             :   svm_fifo_t *f;
     485             :   u64 data64;
     486             : 
     487           1 :   test_data = test_pattern;
     488           1 :   test_data_len = ARRAY_LEN (test_pattern);
     489             : 
     490           1 :   vp = fifo_get_validate_pattern (vm, test_data, test_data_len);
     491             : 
     492             :   /* Create a fifo */
     493           1 :   fs = fifo_segment_prepare (fsm, "fifo-test2", 0);
     494           1 :   f = fifo_prepare (fs, fifo_size);
     495             : 
     496             :   /*
     497             :    * Try with sorted data
     498             :    */
     499         379 :   for (i = 0; i < test_data_len; i++)
     500             :     {
     501         378 :       tp = vp + i;
     502         378 :       data64 = tp->offset;
     503         378 :       svm_fifo_enqueue_with_offset (f, tp->offset - f->shr->tail, tp->len,
     504             :                                     (u8 *) &data64);
     505             :     }
     506             : 
     507             :   /* Expected result: one big fat chunk at offset 4 */
     508           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 1),
     509             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     510           1 :   ooo_seg = svm_fifo_first_ooo_segment (f);
     511           1 :   SFIFO_TEST ((ooo_seg->start == 4),
     512             :               "first ooo seg position %u", ooo_seg->start);
     513           1 :   SFIFO_TEST ((ooo_seg->length == 2996),
     514             :               "first ooo seg length %u", ooo_seg->length);
     515             : 
     516           1 :   data64 = 0;
     517           1 :   rv = svm_fifo_enqueue (f, sizeof (u32), (u8 *) & data64);
     518           1 :   SFIFO_TEST ((rv == 3000), "bytes to be enqueued %u", rv);
     519             : 
     520           1 :   ft_fifo_free (fs, f);
     521           1 :   vec_free (vp);
     522             : 
     523             :   /*
     524             :    * Now try it again w/ unsorted data...
     525             :    */
     526             : 
     527           1 :   f = fifo_prepare (fs, fifo_size);
     528             : 
     529         379 :   for (i = 0; i < test_data_len; i++)
     530             :     {
     531         378 :       tp = &test_data[i];
     532         378 :       data64 = tp->offset;
     533         378 :       rv = svm_fifo_enqueue_with_offset (f, tp->offset - f->shr->tail, tp->len,
     534             :                                          (u8 *) &data64);
     535         378 :       if (rv)
     536             :         {
     537           0 :           clib_warning ("enqueue returned %d", rv);
     538             :         }
     539             :     }
     540             : 
     541             :   /* Expecting the same result: one big fat chunk at offset 4 */
     542           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 1),
     543             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     544           1 :   ooo_seg = svm_fifo_first_ooo_segment (f);
     545           1 :   SFIFO_TEST ((ooo_seg->start == 4),
     546             :               "first ooo seg position %u", ooo_seg->start);
     547           1 :   SFIFO_TEST ((ooo_seg->length == 2996),
     548             :               "first ooo seg length %u", ooo_seg->length);
     549             : 
     550           1 :   data64 = 0;
     551           1 :   rv = svm_fifo_enqueue (f, sizeof (u32), (u8 *) & data64);
     552             : 
     553           1 :   SFIFO_TEST ((rv == 3000), "bytes to be enqueued %u", rv);
     554             : 
     555           1 :   ft_fifo_free (fs, f);
     556           1 :   ft_fifo_segment_free (fsm, fs);
     557             : 
     558           1 :   return 0;
     559             : }
     560             : 
     561             : static int
     562           5 : sfifo_test_fifo3 (vlib_main_t * vm, unformat_input_t * input)
     563             : {
     564           5 :   u32 nsegs = 2, seg_size, length_so_far, current_offset, offset_increment;
     565           5 :   int overlap = 0, verbose = 0, randomize = 1, drop = 0, in_seq_all = 0;
     566           5 :   u32 len_this_chunk, seed = 0xdeaddabe, j, total_size = 2 << 10;
     567           5 :   u32 fifo_size = (4 << 10) + 1, fifo_initial_offset = 0;
     568           5 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
     569           5 :   u8 *data_pattern = 0, *data_buf = 0;
     570           5 :   test_pattern_t *tp, *generate = 0;
     571             :   fifo_segment_t *fs;
     572             :   svm_fifo_t *f;
     573             :   int i, rv;
     574             : 
     575          26 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     576             :     {
     577          21 :       if (unformat (input, "fifo-size %d", &fifo_size))
     578             :         ;
     579          21 :       else if (unformat (input, "total-size %d", &total_size))
     580             :         ;
     581          21 :       else if (unformat (input, "verbose"))
     582           0 :         verbose = 1;
     583          21 :       else if (unformat (input, "overlap"))
     584           4 :         overlap = 1;
     585          17 :       else if (unformat (input, "initial-offset %d", &fifo_initial_offset))
     586             :         ;
     587          14 :       else if (unformat (input, "seed %d", &seed))
     588             :         ;
     589           9 :       else if (unformat (input, "nsegs %d", &nsegs))
     590             :         ;
     591           4 :       else if (unformat (input, "no-randomize"))
     592           1 :         randomize = 0;
     593           3 :       else if (unformat (input, "in-seq-all"))
     594           1 :         in_seq_all = 1;
     595           2 :       else if (unformat (input, "drop"))
     596           2 :         drop = 1;
     597             :       else
     598             :         {
     599           0 :           clib_error_t *e = clib_error_return
     600             :             (0, "unknown input `%U'", format_unformat_error, input);
     601           0 :           clib_error_report (e);
     602           0 :           return -1;
     603             :         }
     604             :     }
     605             : 
     606           5 :   if (total_size > fifo_size)
     607             :     {
     608           0 :       clib_warning ("total_size %d greater than fifo size %d", total_size,
     609             :                     fifo_size);
     610           0 :       return -1;
     611             :     }
     612           5 :   if (overlap && randomize == 0)
     613             :     {
     614           0 :       clib_warning ("Can't enqueue in-order with overlap");
     615           0 :       return -1;
     616             :     }
     617             : 
     618             :   /*
     619             :    * Generate data
     620             :    */
     621           5 :   vec_validate (data_pattern, total_size - 1);
     622       10245 :   for (i = 0; i < vec_len (data_pattern); i++)
     623       10240 :     data_pattern[i] = i & 0xff;
     624             : 
     625             :   /*
     626             :    * Generate segments
     627             :    */
     628           5 :   seg_size = total_size / nsegs;
     629           5 :   length_so_far = 0;
     630           5 :   current_offset = randomize;
     631         220 :   while (length_so_far < total_size)
     632             :     {
     633         215 :       vec_add2 (generate, tp, 1);
     634         215 :       len_this_chunk = clib_min (seg_size, total_size - length_so_far);
     635         215 :       tp->offset = current_offset;
     636         215 :       tp->len = len_this_chunk;
     637             : 
     638         215 :       if (overlap && (len_this_chunk == seg_size))
     639             :         do
     640             :           {
     641         204 :             offset_increment = len_this_chunk
     642         204 :               % (1 + (random_u32 (&seed) % len_this_chunk));
     643             :           }
     644         204 :         while (offset_increment == 0);
     645             :       else
     646          19 :         offset_increment = len_this_chunk;
     647             : 
     648         215 :       current_offset += offset_increment;
     649         215 :       length_so_far = tp->offset + tp->len;
     650             :     }
     651             : 
     652             :   /*
     653             :    * Validate segment list. Only valid for non-overlap cases.
     654             :    */
     655           5 :   if (overlap == 0)
     656           1 :     fifo_validate_pattern (vm, generate, vec_len (generate));
     657             : 
     658           5 :   if (verbose)
     659             :     {
     660           0 :       vlib_cli_output (vm, "raw data pattern:");
     661           0 :       for (i = 0; i < vec_len (generate); i++)
     662             :         {
     663           0 :           vlib_cli_output (vm, "[%d] offset %u len %u", i,
     664           0 :                            generate[i].offset, generate[i].len);
     665             :         }
     666             :     }
     667             : 
     668             :   /* Randomize data pattern */
     669           5 :   if (randomize)
     670             :     {
     671         104 :       for (i = 0; i < vec_len (generate) / 2; i++)
     672             :         {
     673             :           u32 src_index, dst_index;
     674         100 :           test_pattern_t _tmp, *tmp = &_tmp;
     675             : 
     676         100 :           src_index = random_u32 (&seed) % vec_len (generate);
     677         100 :           dst_index = random_u32 (&seed) % vec_len (generate);
     678             : 
     679         100 :           tmp[0] = generate[dst_index];
     680         100 :           generate[dst_index] = generate[src_index];
     681         100 :           generate[src_index] = tmp[0];
     682             :         }
     683           4 :       if (verbose)
     684             :         {
     685           0 :           vlib_cli_output (vm, "randomized data pattern:");
     686           0 :           for (i = 0; i < vec_len (generate); i++)
     687             :             {
     688           0 :               vlib_cli_output (vm, "[%d] offset %u len %u", i,
     689           0 :                                generate[i].offset, generate[i].len);
     690             :             }
     691             :         }
     692             :     }
     693             : 
     694             :   /*
     695             :    * Create a fifo and add segments
     696             :    */
     697           5 :   fs = fifo_segment_prepare (fsm, "fifo-test3", 0);
     698           5 :   f = fifo_prepare (fs, fifo_size);
     699             : 
     700             :   /* manually set head and tail pointers to validate modular arithmetic */
     701           5 :   fifo_initial_offset = fifo_initial_offset % fifo_size;
     702           5 :   svm_fifo_init_pointers (f, fifo_initial_offset, fifo_initial_offset);
     703             : 
     704         219 :   for (i = !randomize; i < vec_len (generate); i++)
     705             :     {
     706         214 :       tp = generate + i;
     707         214 :       svm_fifo_enqueue_with_offset (
     708         214 :         f, fifo_initial_offset + tp->offset - f->shr->tail, tp->len,
     709         214 :         (u8 *) data_pattern + tp->offset);
     710             :     }
     711             : 
     712             :   /* Add the first segment in order for non random data */
     713           5 :   if (!randomize)
     714           1 :     svm_fifo_enqueue (f, generate[0].len, (u8 *) data_pattern);
     715             : 
     716             :   /*
     717             :    * Expected result: one big fat chunk at offset 1 if randomize == 1
     718             :    */
     719             : 
     720           5 :   if (verbose)
     721           0 :     vlib_cli_output (vm, "fifo before missing link: %U",
     722             :                      format_svm_fifo, f, 1 /* verbose */ );
     723             : 
     724             :   /*
     725             :    * Add the missing byte if segments were randomized
     726             :    */
     727           5 :   if (randomize)
     728             :     {
     729           4 :       u32 bytes_to_enq = 1;
     730           4 :       if (in_seq_all)
     731           1 :         bytes_to_enq = total_size;
     732           4 :       rv = svm_fifo_enqueue (f, bytes_to_enq, data_pattern + 0);
     733             : 
     734           4 :       if (verbose)
     735           0 :         vlib_cli_output (vm, "in-order enqueue returned %d", rv);
     736             : 
     737           4 :       SFIFO_TEST ((rv == total_size), "enqueued %u expected %u", rv,
     738             :                   total_size);
     739             : 
     740             :     }
     741             : 
     742           5 :   SFIFO_TEST ((svm_fifo_has_ooo_data (f) == 0), "number of ooo segments %u",
     743             :               svm_fifo_n_ooo_segments (f));
     744             : 
     745             :   /*
     746             :    * Test if peeked data is the same as original data
     747             :    */
     748           5 :   vec_validate (data_buf, vec_len (data_pattern));
     749           5 :   svm_fifo_peek (f, 0, vec_len (data_pattern), data_buf);
     750           5 :   if (compare_data (data_buf, data_pattern, 0, vec_len (data_pattern), &j))
     751             :     {
     752           0 :       SFIFO_TEST (0, "[%d] peeked %u expected %u", j, data_buf[j],
     753             :                   data_pattern[j]);
     754             :     }
     755             : 
     756             :   /*
     757             :    * Dequeue or drop all data
     758             :    */
     759           5 :   if (drop)
     760             :     {
     761           2 :       svm_fifo_dequeue_drop (f, vec_len (data_pattern));
     762             :     }
     763             :   else
     764             :     {
     765           3 :       memset (data_buf, 0, vec_len (data_pattern));
     766           3 :       svm_fifo_dequeue (f, vec_len (data_pattern), data_buf);
     767           3 :       if (compare_data
     768           3 :           (data_buf, data_pattern, 0, vec_len (data_pattern), &j))
     769             :         {
     770           0 :           SFIFO_TEST (0, "[%d] dequeued %u expected %u", j, data_buf[j],
     771             :                       data_pattern[j]);
     772             :         }
     773             :     }
     774             : 
     775           5 :   SFIFO_TEST ((svm_fifo_max_dequeue (f) == 0), "fifo has %d bytes",
     776             :               svm_fifo_max_dequeue (f));
     777             : 
     778           5 :   ft_fifo_free (fs, f);
     779           5 :   ft_fifo_segment_free (fsm, fs);
     780           5 :   vec_free (data_pattern);
     781           5 :   vec_free (data_buf);
     782             : 
     783           5 :   return 0;
     784             : }
     785             : 
     786             : static int
     787           1 : sfifo_test_fifo4 (vlib_main_t * vm, unformat_input_t * input)
     788             : {
     789           1 :   u32 fifo_size = 6 << 10, fifo_initial_offset = 1e9, test_n_bytes = 5000, j;
     790           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
     791           1 :   u8 *test_data = 0, *data_buf = 0;
     792           1 :   int i, rv, verbose = 0;
     793             :   fifo_segment_t *fs;
     794             :   svm_fifo_t *f;
     795             : 
     796           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     797             :     {
     798           0 :       if (unformat (input, "verbose"))
     799           0 :         verbose = 1;
     800             :       else
     801             :         {
     802           0 :           clib_error_t *e = clib_error_return
     803             :             (0, "unknown input `%U'", format_unformat_error, input);
     804           0 :           clib_error_report (e);
     805           0 :           return -1;
     806             :         }
     807             :     }
     808             : 
     809             :   /*
     810             :    * Create a fifo and add segments
     811             :    */
     812           1 :   fs = fifo_segment_prepare (fsm, "fifo-test4", 0);
     813           1 :   f = fifo_prepare (fs, fifo_size);
     814             : 
     815             :   /* Set head and tail pointers */
     816           1 :   fifo_initial_offset = fifo_initial_offset % fifo_size;
     817           1 :   svm_fifo_init_pointers (f, fifo_initial_offset, fifo_initial_offset);
     818             : 
     819           1 :   vec_validate (test_data, test_n_bytes - 1);
     820        5001 :   for (i = 0; i < vec_len (test_data); i++)
     821        5000 :     test_data[i] = i;
     822             : 
     823        5000 :   for (i = test_n_bytes - 1; i > 0; i--)
     824             :     {
     825        4999 :       rv = svm_fifo_enqueue_with_offset (
     826        4999 :         f, fifo_initial_offset + i - f->shr->tail, sizeof (u8), &test_data[i]);
     827        4999 :       if (verbose)
     828           0 :         vlib_cli_output (vm, "add [%d] [%d, %d]", i, i, i + sizeof (u8));
     829        4999 :       if (rv)
     830           0 :         SFIFO_TEST (0, "enqueue returned %d", rv);
     831             :     }
     832             : 
     833           1 :   svm_fifo_enqueue (f, sizeof (u8), &test_data[0]);
     834             : 
     835           1 :   vec_validate (data_buf, vec_len (test_data));
     836             : 
     837           1 :   svm_fifo_dequeue (f, vec_len (test_data), data_buf);
     838           1 :   rv = compare_data (data_buf, test_data, 0, vec_len (test_data), &j);
     839           1 :   if (rv)
     840           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", j, data_buf[j],
     841           0 :                      test_data[j]);
     842           1 :   SFIFO_TEST ((rv == 0), "dequeued compared to original returned %d", rv);
     843             : 
     844           1 :   ft_fifo_free (fs, f);
     845           1 :   ft_fifo_segment_free (fsm, fs);
     846           1 :   vec_free (test_data);
     847           1 :   return 0;
     848             : }
     849             : 
     850             : static u32
     851           8 : fifo_pos (svm_fifo_t * f, u32 pos)
     852             : {
     853           8 :   return pos;
     854             : }
     855             : 
     856             : /* Avoids exposing svm_fifo.c internal function */
     857             : static ooo_segment_t *
     858           2 : ooo_seg_next (svm_fifo_t * f, ooo_segment_t * s)
     859             : {
     860           2 :   if (pool_is_free_index (f->ooo_segments, s->next))
     861           0 :     return 0;
     862           2 :   return pool_elt_at_index (f->ooo_segments, s->next);
     863             : }
     864             : 
     865             : static int
     866           1 : sfifo_test_fifo5 (vlib_main_t * vm, unformat_input_t * input)
     867             : {
     868           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
     869           1 :   u32 fifo_size = 401, j = 0, offset = 200;
     870           1 :   u8 *test_data = 0, *data_buf = 0;
     871           1 :   int i, rv, verbose = 0;
     872             :   ooo_segment_t *ooo_seg;
     873             :   fifo_segment_t *fs;
     874             :   svm_fifo_t *f;
     875             : 
     876           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     877             :     {
     878           0 :       if (unformat (input, "verbose"))
     879           0 :         verbose = 1;
     880             :       else
     881             :         {
     882           0 :           clib_error_t *e = clib_error_return (0, "unknown input `%U'",
     883             :                                                format_unformat_error, input);
     884           0 :           clib_error_report (e);
     885           0 :           return -1;
     886             :         }
     887             :     }
     888             : 
     889           1 :   fs = fifo_segment_prepare (fsm, "fifo-test5", 0);
     890           1 :   f = fifo_prepare (fs, fifo_size);
     891           1 :   svm_fifo_init_pointers (f, offset, offset);
     892             : 
     893           1 :   vec_validate (test_data, 399);
     894         401 :   for (i = 0; i < vec_len (test_data); i++)
     895         400 :     test_data[i] = i % 0xff;
     896             : 
     897             :   /*
     898             :    * Start with [100, 200] and [300, 400]
     899             :    */
     900           1 :   svm_fifo_enqueue_with_offset (f, 100, 100, &test_data[100]);
     901           1 :   svm_fifo_enqueue_with_offset (f, 300, 100, &test_data[300]);
     902             : 
     903           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 2),
     904             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     905           1 :   SFIFO_TEST ((f->ooos_newest == 1), "newest %u", f->ooos_newest);
     906           1 :   if (verbose)
     907           0 :     vlib_cli_output (vm, "fifo after [100, 200] and [300, 400] : %U",
     908             :                      format_svm_fifo, f, 2 /* verbose */ );
     909             : 
     910             :   /*
     911             :    * Add [225, 275]
     912             :    */
     913             : 
     914           1 :   rv = svm_fifo_enqueue_with_offset (f, 225, 50, &test_data[225]);
     915           1 :   if (verbose)
     916           0 :     vlib_cli_output (vm, "fifo after [225, 275] : %U",
     917             :                      format_svm_fifo, f, 2 /* verbose */ );
     918           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 3),
     919             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     920           1 :   ooo_seg = svm_fifo_first_ooo_segment (f);
     921           1 :   SFIFO_TEST ((ooo_seg->start == fifo_pos (f, 100 + offset)),
     922             :               "first seg start %u expected %u", ooo_seg->start,
     923             :               fifo_pos (f, 100 + offset));
     924           1 :   SFIFO_TEST ((ooo_seg->length == 100), "first seg length %u expected %u",
     925             :               ooo_seg->length, 100);
     926           1 :   ooo_seg = ooo_seg_next (f, ooo_seg);
     927           1 :   SFIFO_TEST ((ooo_seg->start == fifo_pos (f, 225 + offset)),
     928             :               "second seg start %u expected %u",
     929             :               ooo_seg->start, fifo_pos (f, 225 + offset));
     930           1 :   SFIFO_TEST ((ooo_seg->length == 50), "second seg length %u expected %u",
     931             :               ooo_seg->length, 50);
     932           1 :   ooo_seg = ooo_seg_next (f, ooo_seg);
     933           1 :   SFIFO_TEST ((ooo_seg->start == fifo_pos (f, 300 + offset)),
     934             :               "third seg start %u expected %u",
     935             :               ooo_seg->start, fifo_pos (f, 300 + offset));
     936           1 :   SFIFO_TEST ((ooo_seg->length == 100), "third seg length %u expected %u",
     937             :               ooo_seg->length, 100);
     938           1 :   SFIFO_TEST ((f->ooos_newest == 2), "newest %u", f->ooos_newest);
     939             :   /*
     940             :    * Add [190, 310]
     941             :    */
     942           1 :   rv = svm_fifo_enqueue_with_offset (f, 190, 120, &test_data[190]);
     943           1 :   if (verbose)
     944           0 :     vlib_cli_output (vm, "fifo after [190, 310] : %U",
     945             :                      format_svm_fifo, f, 1 /* verbose */ );
     946           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 1),
     947             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     948           1 :   ooo_seg = svm_fifo_first_ooo_segment (f);
     949           1 :   SFIFO_TEST ((ooo_seg->start == fifo_pos (f, offset + 100)),
     950             :               "first seg start %u expected %u",
     951             :               ooo_seg->start, fifo_pos (f, offset + 100));
     952           1 :   SFIFO_TEST ((ooo_seg->length == 300), "first seg length %u expected %u",
     953             :               ooo_seg->length, 300);
     954             : 
     955             :   /*
     956             :    * Add [0, 150]
     957             :    */
     958           1 :   rv = svm_fifo_enqueue (f, 150, test_data);
     959             : 
     960           1 :   if (verbose)
     961           0 :     vlib_cli_output (vm, "fifo after [0 150] : %U", format_svm_fifo, f,
     962             :                      2 /* verbose */ );
     963             : 
     964           1 :   SFIFO_TEST ((rv == 400), "managed to enqueue %u expected %u", rv, 400);
     965           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 0),
     966             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     967             : 
     968           1 :   vec_validate (data_buf, 399);
     969           1 :   svm_fifo_peek (f, 0, 400, data_buf);
     970           1 :   if (compare_data (data_buf, test_data, 0, 400, &j))
     971             :     {
     972           0 :       SFIFO_TEST (0, "[%d] peeked %u expected %u", j, data_buf[j],
     973             :                   test_data[j]);
     974             :     }
     975             : 
     976             :   /*
     977             :    * Add [100 200] and overlap it with [50 250]
     978             :    */
     979           1 :   ft_fifo_free (fs, f);
     980           1 :   f = fifo_prepare (fs, fifo_size);
     981             : 
     982           1 :   svm_fifo_enqueue_with_offset (f, 100, 100, &test_data[100]);
     983           1 :   svm_fifo_enqueue_with_offset (f, 50, 200, &test_data[50]);
     984           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 1),
     985             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
     986           1 :   ooo_seg = svm_fifo_first_ooo_segment (f);
     987           1 :   SFIFO_TEST ((ooo_seg->start == 50), "first seg start %u expected %u",
     988             :               ooo_seg->start, 50);
     989           1 :   SFIFO_TEST ((ooo_seg->length == 200), "first seg length %u expected %u",
     990             :               ooo_seg->length, 200);
     991             : 
     992           1 :   ft_fifo_free (fs, f);
     993           1 :   ft_fifo_segment_free (fsm, fs);
     994           1 :   vec_free (test_data);
     995           1 :   return 0;
     996             : }
     997             : 
     998             : /*
     999             :  * Test ooo head/tail u32 wrapping
    1000             :  */
    1001             : static int
    1002           1 : sfifo_test_fifo6 (vlib_main_t * vm, unformat_input_t * input)
    1003             : {
    1004           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
    1005           1 :   u32 fifo_size = 101, n_test_bytes = 100;
    1006           1 :   int i, j, rv, __clib_unused verbose = 0;
    1007           1 :   u8 *test_data = 0, *data_buf = 0;
    1008             :   ooo_segment_t *ooo_seg;
    1009             :   fifo_segment_t *fs;
    1010             :   svm_fifo_t *f;
    1011             : 
    1012           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1013             :     {
    1014           0 :       if (unformat (input, "verbose"))
    1015           0 :         verbose = 1;
    1016             :       else
    1017             :         {
    1018           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    1019             :                            input);
    1020           0 :           return -1;
    1021             :         }
    1022             :     }
    1023             : 
    1024           1 :   fs = fifo_segment_prepare (fsm, "fifo-test6", 0);
    1025           1 :   f = fifo_prepare (fs, fifo_size);
    1026             : 
    1027           1 :   vec_validate (test_data, n_test_bytes - 1);
    1028           1 :   vec_validate (data_buf, n_test_bytes - 1);
    1029         101 :   for (i = 0; i < vec_len (test_data); i++)
    1030         100 :     test_data[i] = i % 0xff;
    1031             : 
    1032             :   /*
    1033             :    * Add ooo with tail and ooo segment start u32 wrap
    1034             :    */
    1035           1 :   svm_fifo_init_pointers (f, ~0 % fifo_size, ~0 % fifo_size);
    1036           1 :   svm_fifo_enqueue_with_offset (f, 10, 10, &test_data[10]);
    1037           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 1),
    1038             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
    1039           1 :   ooo_seg = svm_fifo_first_ooo_segment (f);
    1040           1 :   rv = ooo_segment_offset_prod (f, ooo_seg);
    1041           1 :   SFIFO_TEST (rv == 10, "offset should be %u is %u", 10, rv);
    1042             : 
    1043           1 :   svm_fifo_enqueue (f, 10, test_data);
    1044           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 0),
    1045             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
    1046           1 :   SFIFO_TEST (f->ooos_list_head == OOO_SEGMENT_INVALID_INDEX,
    1047             :               "there should be no ooo seg");
    1048             : 
    1049           1 :   svm_fifo_peek (f, 5, 10, &data_buf[5]);
    1050           1 :   if (compare_data (data_buf, test_data, 5, 10, (u32 *) & j))
    1051           0 :     SFIFO_TEST (0, "[%d] dequeued %u expected %u", j, data_buf[j],
    1052             :                 test_data[j]);
    1053             : 
    1054           1 :   svm_fifo_dequeue (f, 20, data_buf);
    1055           1 :   if (compare_data (data_buf, test_data, 0, 20, (u32 *) & j))
    1056           0 :     SFIFO_TEST (0, "[%d] dequeued %u expected %u", j, data_buf[j],
    1057             :                 test_data[j]);
    1058             : 
    1059             :   /*
    1060             :    * Force collect with tail u32 wrap and without ooo segment start u32 wrap
    1061             :    */
    1062           1 :   svm_fifo_init_pointers (f, (~0 - 10) % fifo_size, (~0 - 10) % fifo_size);
    1063           1 :   svm_fifo_enqueue_with_offset (f, 5, 15, &test_data[5]);
    1064           1 :   svm_fifo_enqueue (f, 12, test_data);
    1065             : 
    1066           1 :   SFIFO_TEST ((svm_fifo_n_ooo_segments (f) == 0),
    1067             :               "number of ooo segments %u", svm_fifo_n_ooo_segments (f));
    1068           1 :   SFIFO_TEST (f->ooos_list_head == OOO_SEGMENT_INVALID_INDEX,
    1069             :               "there should be no ooo seg");
    1070             : 
    1071           1 :   svm_fifo_dequeue (f, 20, data_buf);
    1072           1 :   if (compare_data (data_buf, test_data, 0, 20, (u32 *) & j))
    1073           0 :     SFIFO_TEST (0, "[%d] dequeued %u expected %u", j, data_buf[j],
    1074             :                 test_data[j]);
    1075             : 
    1076             :   /*
    1077             :    * Cleanup
    1078             :    */
    1079           1 :   vec_free (test_data);
    1080           1 :   vec_free (data_buf);
    1081           1 :   ft_fifo_free (fs, f);
    1082           1 :   ft_fifo_segment_free (fsm, fs);
    1083           1 :   return 0;
    1084             : }
    1085             : 
    1086             : /*
    1087             :  * Multiple ooo enqueues and dequeues that force fifo tail/head wrap
    1088             :  */
    1089             : static int
    1090           1 : sfifo_test_fifo7 (vlib_main_t * vm, unformat_input_t * input)
    1091             : {
    1092           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
    1093           1 :   u32 fifo_size = 101, n_iterations = 100;
    1094           1 :   int i, j, rv, __clib_unused verbose = 0;
    1095           1 :   u8 *test_data = 0, *data_buf = 0;
    1096           1 :   u64 n_test_bytes = 100;
    1097             :   fifo_segment_t *fs;
    1098             :   svm_fifo_t *f;
    1099             : 
    1100           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1101             :     {
    1102           0 :       if (unformat (input, "verbose"))
    1103           0 :         verbose = 1;
    1104             :       else
    1105             :         {
    1106           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    1107             :                            input);
    1108           0 :           return -1;
    1109             :         }
    1110             :     }
    1111             : 
    1112             :   /*
    1113             :    * Prepare data structures
    1114             :    */
    1115           1 :   fs = fifo_segment_prepare (fsm, "fifo-test7", 0);
    1116           1 :   f = fifo_prepare (fs, fifo_size);
    1117           1 :   svm_fifo_init_pointers (f, ~0 % fifo_size, ~0 % fifo_size);
    1118             : 
    1119           1 :   vec_validate (test_data, n_test_bytes - 1);
    1120           1 :   vec_validate (data_buf, n_test_bytes - 1);
    1121         101 :   for (i = 0; i < vec_len (test_data); i++)
    1122         100 :     test_data[i] = i % 0xff;
    1123             : 
    1124             :   /*
    1125             :    * Run n iterations of test
    1126             :    */
    1127         101 :   for (i = 0; i < n_iterations; i++)
    1128             :     {
    1129        5100 :       for (j = n_test_bytes - 1; j > 0; j -= 2)
    1130             :         {
    1131        5000 :           svm_fifo_enqueue_with_offset (f, j, 1, &test_data[j]);
    1132        5000 :           rv = svm_fifo_n_ooo_segments (f);
    1133        5000 :           if (rv != (n_test_bytes - j) / 2 + 1)
    1134           0 :             SFIFO_TEST (0, "number of ooo segments expected %u is %u",
    1135             :                         (n_test_bytes - j) / 2 + 1, rv);
    1136             :         }
    1137             : 
    1138         100 :       svm_fifo_enqueue_with_offset (f, 1, n_test_bytes - 1, &test_data[1]);
    1139         100 :       rv = svm_fifo_n_ooo_segments (f);
    1140         100 :       if (rv != 1)
    1141           0 :         SFIFO_TEST (0, "number of ooo segments %u", rv);
    1142             : 
    1143         100 :       svm_fifo_enqueue (f, 1, test_data);
    1144         100 :       rv = svm_fifo_n_ooo_segments (f);
    1145         100 :       if (rv != 0)
    1146           0 :         SFIFO_TEST (0, "number of ooo segments %u", rv);
    1147             : 
    1148         100 :       svm_fifo_dequeue (f, n_test_bytes, data_buf);
    1149         100 :       if (compare_data (data_buf, test_data, 0, n_test_bytes, (u32 *) & j))
    1150           0 :         SFIFO_TEST (0, "[%d] dequeued %u expected %u", j, data_buf[j],
    1151             :                     test_data[j]);
    1152         100 :       svm_fifo_init_pointers (f, (~0 - i) % f->shr->size,
    1153         100 :                               (~0 - i) % f->shr->size);
    1154             :     }
    1155           1 :   SFIFO_TEST (1, "passed multiple ooo enqueue/dequeue");
    1156             : 
    1157             :   /*
    1158             :    * Cleanup
    1159             :    */
    1160           1 :   vec_free (test_data);
    1161           1 :   vec_free (data_buf);
    1162           1 :   ft_fifo_free (fs, f);
    1163           1 :   ft_fifo_segment_free (fsm, fs);
    1164           1 :   return 0;
    1165             : }
    1166             : 
    1167             : /*
    1168             :  * Enqueue more than 4GB
    1169             :  */
    1170             : static int
    1171           0 : sfifo_test_fifo_large (vlib_main_t * vm, unformat_input_t * input)
    1172             : {
    1173           0 :   u32 n_iterations = 100, n_bytes_per_iter, half, fifo_size;
    1174           0 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
    1175           0 :   int i, j, rv, __clib_unused verbose = 0;
    1176           0 :   u8 *test_data = 0, *data_buf = 0;
    1177           0 :   u64 n_test_bytes = 100;
    1178             :   fifo_segment_t *fs;
    1179             :   svm_fifo_t *f;
    1180             : 
    1181           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1182             :     {
    1183           0 :       if (unformat (input, "verbose"))
    1184           0 :         verbose = 1;
    1185             :       else
    1186             :         {
    1187           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    1188             :                            input);
    1189           0 :           return -1;
    1190             :         }
    1191             :     }
    1192             : 
    1193           0 :   n_test_bytes = 5ULL << 30;
    1194           0 :   n_iterations = 1 << 10;
    1195           0 :   n_bytes_per_iter = n_test_bytes / n_iterations;
    1196           0 :   fifo_size = n_bytes_per_iter + 1;
    1197             : 
    1198           0 :   fs = fifo_segment_prepare (fsm, "fifo-large", 0);
    1199           0 :   f = fifo_prepare (fs, fifo_size);
    1200           0 :   svm_fifo_init_pointers (f, ~0 % fifo_size, ~0 % fifo_size);
    1201             : 
    1202           0 :   vec_validate (test_data, n_bytes_per_iter - 1);
    1203           0 :   vec_validate (data_buf, n_bytes_per_iter - 1);
    1204           0 :   for (i = 0; i < vec_len (test_data); i++)
    1205           0 :     test_data[i] = i % 0xff;
    1206             : 
    1207           0 :   half = n_bytes_per_iter / 2;
    1208           0 :   for (i = 0; i < n_iterations; i++)
    1209             :     {
    1210           0 :       svm_fifo_enqueue_with_offset (f, half, half, &test_data[half]);
    1211           0 :       svm_fifo_enqueue (f, half, test_data);
    1212           0 :       rv = svm_fifo_n_ooo_segments (f);
    1213           0 :       if (rv != 0)
    1214           0 :         SFIFO_TEST (0, "number of ooo segments %u", rv);
    1215           0 :       svm_fifo_dequeue (f, n_bytes_per_iter, data_buf);
    1216           0 :       if (compare_data (data_buf, test_data, 0, n_bytes_per_iter,
    1217             :                         (u32 *) & j))
    1218           0 :         SFIFO_TEST (0, "[%d][%d] dequeued %u expected %u", i, j, data_buf[j],
    1219             :                     test_data[j]);
    1220             :     }
    1221           0 :   SFIFO_TEST (1, "passed large transfer");
    1222             : 
    1223           0 :   ft_fifo_free (fs, f);
    1224           0 :   ft_fifo_segment_free (fsm, fs);
    1225             : 
    1226           0 :   return 0;
    1227             : }
    1228             : 
    1229             : static void
    1230           9 : validate_test_and_buf_vecs (u8 ** test_data, u8 ** data_buf, u32 len)
    1231             : {
    1232             :   int i, cur_len;
    1233             : 
    1234           9 :   cur_len = vec_len (*test_data);
    1235           9 :   vec_validate (*test_data, len - 1);
    1236           9 :   vec_validate (*data_buf, len - 1);
    1237             : 
    1238    12849100 :   for (i = cur_len; i < vec_len (*test_data); i++)
    1239    12849100 :     (*test_data)[i] = i;
    1240           9 : }
    1241             : 
    1242             : static int
    1243           4 : enqueue_ooo (svm_fifo_t * f, u8 * test_data, u32 len, u32 iterations)
    1244             : {
    1245             :   u32 offset, enq_now, ooo_chunk;
    1246             :   int i, rv;
    1247             : 
    1248           4 :   ooo_chunk = len / iterations;
    1249       16310 :   for (i = iterations; i > 0; i--)
    1250             :     {
    1251       16306 :       offset = i * ooo_chunk;
    1252       16306 :       enq_now = clib_min (ooo_chunk, len - offset);
    1253       16306 :       if (!enq_now)
    1254           2 :         continue;
    1255       16304 :       rv = svm_fifo_enqueue_with_offset (f, offset, enq_now,
    1256             :                                          test_data + offset);
    1257       16304 :       if (rv)
    1258           0 :         return rv;
    1259             :     }
    1260             : 
    1261           4 :   return 0;
    1262             : }
    1263             : 
    1264             : static int
    1265           1 : enqueue_ooo_packets (svm_fifo_t * f, u32 len, u32 enq_chunk, u8 * test_data)
    1266             : {
    1267             :   u32 offset, enq_now;
    1268             :   int i, rv;
    1269             : 
    1270        2797 :   for (i = 1; i <= len / enq_chunk; i++)
    1271             :     {
    1272        2796 :       offset = i * enq_chunk;
    1273        2796 :       enq_now = clib_min (enq_chunk, len - offset);
    1274        2796 :       if (!enq_now)
    1275           0 :         continue;
    1276        2796 :       rv = svm_fifo_enqueue_with_offset (f, offset, enq_now,
    1277             :                                          test_data + offset);
    1278        2796 :       if (rv)
    1279           0 :         return rv;
    1280             : 
    1281        2796 :       if (svm_fifo_size (f) < len - 4096)
    1282        2791 :         svm_fifo_set_size (f, svm_fifo_size (f) + enq_now);
    1283             :       else
    1284           5 :         svm_fifo_set_size (f, len);
    1285             :     }
    1286             : 
    1287           1 :   return 0;
    1288             : }
    1289             : 
    1290             : static int
    1291           2 : enqueue_packets_inc (svm_fifo_t * f, u32 len, u32 enq_chunk, u8 * test_data)
    1292             : {
    1293             :   u32 enq_now, offset;
    1294             :   int i, rv;
    1295             : 
    1296        5596 :   for (i = 0; i <= len / enq_chunk; i++)
    1297             :     {
    1298        5594 :       offset = i * enq_chunk;
    1299        5594 :       enq_now = clib_min (enq_chunk, len - offset);
    1300        5594 :       rv = svm_fifo_enqueue (f, enq_now, test_data + offset);
    1301        5594 :       if (rv != enq_now)
    1302           0 :         return -1;
    1303        5594 :       if (svm_fifo_size (f) < len - 4096)
    1304        5582 :         svm_fifo_set_size (f, svm_fifo_size (f) + enq_now);
    1305             :       else
    1306          12 :         svm_fifo_set_size (f, len);
    1307             :     }
    1308           2 :   return 0;
    1309             : }
    1310             : 
    1311             : static int
    1312           2 : dequeue_ooo (svm_fifo_t * f, u8 * data_buf, u32 len, u32 iterations)
    1313             : {
    1314             :   u32 offset, ooo_chunk, deq_now;
    1315             :   int i, rv;
    1316             : 
    1317           2 :   ooo_chunk = len / iterations;
    1318     4206500 :   for (i = iterations; i >= 0; i--)
    1319             :     {
    1320     4206490 :       offset = i * ooo_chunk;
    1321     4206490 :       deq_now = clib_min (ooo_chunk, len - offset);
    1322     4206490 :       if (deq_now == 0)
    1323           2 :         continue;
    1324     4206490 :       rv = svm_fifo_peek (f, offset, deq_now, data_buf + offset);
    1325     4206490 :       if (rv != deq_now)
    1326           0 :         return rv;
    1327             :     }
    1328           2 :   return 0;
    1329             : }
    1330             : 
    1331             : static int
    1332           1 : dequeue_ooo_inc (svm_fifo_t * f, u8 * data_buf, u32 len, u32 iterations)
    1333             : {
    1334             :   u32 offset, ooo_chunk, deq_now;
    1335             :   int i, rv;
    1336             : 
    1337           1 :   ooo_chunk = len / iterations;
    1338          12 :   for (i = 0; i <= iterations; i++)
    1339             :     {
    1340          11 :       offset = i * ooo_chunk;
    1341          11 :       deq_now = clib_min (ooo_chunk, len - offset);
    1342          11 :       if (deq_now == 0)
    1343           0 :         continue;
    1344          11 :       rv = svm_fifo_peek (f, offset, deq_now, data_buf + offset);
    1345          11 :       if (rv != deq_now)
    1346           0 :         return rv;
    1347             :     }
    1348           1 :   return 0;
    1349             : }
    1350             : 
    1351             : static int
    1352           1 : dequeue_packets (svm_fifo_t * f, u32 len, u32 deq_chunk, u8 * data_buf)
    1353             : {
    1354             :   u32 offset, deq_now;
    1355             :   int i, rv;
    1356             : 
    1357        2798 :   for (i = 0; i <= len / deq_chunk; i++)
    1358             :     {
    1359        2797 :       offset = i * deq_chunk;
    1360        2797 :       deq_now = clib_min (deq_chunk, len - offset);
    1361        2797 :       if (deq_now == 0)
    1362           0 :         continue;
    1363        2797 :       rv = svm_fifo_dequeue (f, deq_now, data_buf + offset);
    1364        2797 :       if (rv != deq_now)
    1365           0 :         return rv;
    1366             :     }
    1367           1 :   return 0;
    1368             : }
    1369             : 
    1370             : static int
    1371           1 : sfifo_test_fifo_grow (vlib_main_t * vm, unformat_input_t * input)
    1372             : {
    1373           1 :   int __clib_unused verbose = 0, fifo_size = 4096, fifo_inc = 4096, rv, i;
    1374             :   u32 enq_chunk, offset, deq_now, last_start_byte;
    1375           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
    1376           1 :   u8 *test_data = 0, *data_buf = 0;
    1377             :   svm_fifo_chunk_t *c;
    1378             :   fifo_segment_t *fs;
    1379             :   svm_fifo_t *f;
    1380             : 
    1381           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1382             :     {
    1383           0 :       if (unformat (input, "verbose"))
    1384           0 :         verbose = 1;
    1385             :       else
    1386             :         {
    1387           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    1388             :                            input);
    1389           0 :           return -1;
    1390             :         }
    1391             :     }
    1392             : 
    1393           1 :   fs = fifo_segment_prepare (fsm, "fifo-grow", 0);
    1394           1 :   f = fifo_prepare (fs, fifo_size);
    1395             : 
    1396             :   /*
    1397             :    * Grow size and alloc chunks by enqueueing in order
    1398             :    */
    1399           1 :   fifo_size += fifo_inc;
    1400           1 :   svm_fifo_set_size (f, fifo_size);
    1401           1 :   last_start_byte = 4096;
    1402           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, fifo_size);
    1403             : 
    1404           1 :   rv = svm_fifo_enqueue (f, fifo_size, test_data);
    1405             : 
    1406           1 :   SFIFO_TEST (rv == fifo_size, "enqueue should work");
    1407           1 :   SFIFO_TEST (svm_fifo_size (f) == fifo_size, "size expected %u is %u",
    1408             :               fifo_size, svm_fifo_size (f));
    1409           1 :   SFIFO_TEST (svm_fifo_max_dequeue (f) == fifo_size, "max deq should be %u",
    1410             :               fifo_size);
    1411           1 :   rv = svm_fifo_n_chunks (f);
    1412           1 :   SFIFO_TEST (rv == 2, "should have 2 chunks has %u", rv);
    1413           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1414             : 
    1415           1 :   c = f_head_cptr (f);
    1416           1 :   SFIFO_TEST (c->start_byte == 0, "head start byte should be %u", 0);
    1417           1 :   SFIFO_TEST (c->length == 4096, "head chunk length should be %u", 4096);
    1418           1 :   SFIFO_TEST (f->shr->tail_chunk == 0, "no tail chunk");
    1419           1 :   SFIFO_TEST (f->ooo_enq == 0, "should have no ooo enq chunk");
    1420           1 :   SFIFO_TEST (f->ooo_deq == 0, "should have no ooo deq chunk");
    1421           1 :   c = f_end_cptr (f);
    1422           1 :   SFIFO_TEST (c->start_byte == last_start_byte, "end chunk start byte should"
    1423             :               " be %u", last_start_byte);
    1424           1 :   SFIFO_TEST (c->length == 4096, "end chunk length should be %u", 4096);
    1425             : 
    1426             :   /*
    1427             :    * Dequeue and validate data
    1428             :    */
    1429             : 
    1430           1 :   rv = svm_fifo_dequeue (f, fifo_size, data_buf);
    1431           1 :   SFIFO_TEST (rv == fifo_size, "should dequeue all data");
    1432           1 :   last_start_byte += 4096;      /* size of last segment */
    1433             : 
    1434           1 :   rv = compare_data (data_buf, test_data, 0, vec_len (test_data),
    1435             :                      (u32 *) & i);
    1436             : 
    1437           1 :   if (rv)
    1438           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1439           0 :                      test_data[i]);
    1440           1 :   SFIFO_TEST ((rv == 0), "dequeued compared to original returned %d", rv);
    1441           1 :   SFIFO_TEST (f->shr->head_chunk == 0, "head chunk should be 0");
    1442           1 :   SFIFO_TEST (f->shr->tail_chunk == 0, "tail chunk should be 0");
    1443           1 :   SFIFO_TEST (f->ooo_deq == 0, "should have no ooo deq chunk");
    1444           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1445             : 
    1446             :   /*
    1447             :    * Allocate one new chunk by enqueueing out of order all but first chunk
    1448             :    *
    1449             :    */
    1450             : 
    1451           1 :   enq_chunk = vec_len (test_data) / 10;
    1452           1 :   rv = enqueue_ooo (f, test_data, vec_len (test_data), 10);
    1453           1 :   SFIFO_TEST (!rv, "enqueue ooo should work");
    1454             : 
    1455           1 :   SFIFO_TEST (svm_fifo_size (f) == fifo_size, "size expected %u is %u",
    1456             :               fifo_size, svm_fifo_size (f));
    1457           1 :   SFIFO_TEST (svm_fifo_max_dequeue (f) == 0, "max deq should be %u", 0);
    1458             :   /* Fifo has 2 chunks because the we didn't allow the first chunk to be
    1459             :    * freed when all the data was dequeued. Could be optimized in the future */
    1460           1 :   rv = svm_fifo_n_chunks (f);
    1461           1 :   SFIFO_TEST (rv == 2, "should have %u chunks has %u", 2, rv);
    1462           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1463             : 
    1464           1 :   SFIFO_TEST (f->shr->head_chunk == 0, "should have no head chunk");
    1465             :   /* When new fifo chunks are allocated, tail is initialized */
    1466           1 :   SFIFO_TEST (f->shr->tail_chunk != 0, "should have no tail chunk");
    1467           1 :   SFIFO_TEST (f->ooo_enq != 0, "should have an ooo enq chunk");
    1468             : 
    1469           1 :   c = f_end_cptr (f);
    1470           1 :   SFIFO_TEST (c->start_byte == last_start_byte,
    1471             :               "end chunk should start at %u", last_start_byte);
    1472           1 :   SFIFO_TEST (c->length == 8192, "end chunk length should be %u", 8192);
    1473           1 :   SFIFO_TEST (f->ooo_enq == c, "ooo enq chunk should be end chunk");
    1474             : 
    1475             :   /*
    1476             :    * Enqueue the first chunk
    1477             :    */
    1478           1 :   rv = svm_fifo_enqueue (f, enq_chunk, test_data);
    1479           1 :   SFIFO_TEST (rv == fifo_size, "enq should succeed %u", rv);
    1480           1 :   rv = svm_fifo_max_dequeue (f);
    1481           1 :   SFIFO_TEST (rv == fifo_size, "max deq should be %u is %u", fifo_size, rv);
    1482           1 :   rv = svm_fifo_n_chunks (f);
    1483           1 :   SFIFO_TEST (rv == 2, "should have %u chunks has %u", 2, rv);
    1484           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1485             : 
    1486           1 :   SFIFO_TEST (f->shr->head_chunk == 0, "should have no head chunk");
    1487             :   /* Fifo is full so tail and ooo_enq should be 0 */
    1488           1 :   SFIFO_TEST (f->shr->tail_chunk == 0, "should have no tail chunk");
    1489           1 :   SFIFO_TEST (f->ooo_enq == 0, "should have no ooo enq chunk");
    1490             : 
    1491             :   /*
    1492             :    * Peek and validate data
    1493             :    */
    1494             : 
    1495           1 :   memset (data_buf, 0, vec_len (data_buf));
    1496             : 
    1497           1 :   rv = dequeue_ooo_inc (f, data_buf, fifo_size, 10);
    1498           1 :   SFIFO_TEST (!rv, "ooo deq should work %d", rv);
    1499             : 
    1500           1 :   rv = compare_data (data_buf, test_data, 0, vec_len (test_data),
    1501             :                      (u32 *) & i);
    1502           1 :   if (rv)
    1503           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1504           0 :                      test_data[i]);
    1505           1 :   SFIFO_TEST ((rv == 0), "peeked compared to original returned %d", rv);
    1506           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1507             :   /* Peeked all the data in a full fifo so ooo_deq ends up 0 */
    1508           1 :   SFIFO_TEST (f->ooo_deq == 0, "should have no ooo deq chunk");
    1509             : 
    1510             :   /*
    1511             :    * Peek in reverse order and validate data
    1512             :    *
    1513             :    * RB tree should be exercised
    1514             :    */
    1515             : 
    1516           1 :   memset (data_buf, 0, vec_len (data_buf));
    1517          12 :   for (i = 10; i >= 0; i--)
    1518             :     {
    1519          11 :       offset = i * enq_chunk;
    1520          11 :       deq_now = clib_min (enq_chunk, vec_len (test_data) - offset);
    1521          11 :       rv = svm_fifo_peek (f, offset, deq_now, data_buf + offset);
    1522          11 :       if (rv != deq_now)
    1523           0 :         SFIFO_TEST (0, "failed to peek");
    1524             :     }
    1525             : 
    1526           1 :   rv = compare_data (data_buf, test_data, 0, vec_len (test_data),
    1527             :                      (u32 *) & i);
    1528             : 
    1529           1 :   if (rv)
    1530           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1531           0 :                      test_data[i]);
    1532           1 :   SFIFO_TEST ((rv == 0), "peeked compared to original returned %d", rv);
    1533           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1534             :   /* Last chunk peeked is the first, so ooo_deq should be non zero */
    1535           1 :   SFIFO_TEST (f->ooo_deq != 0, "should have ooo deq chunk");
    1536             : 
    1537             :   /*
    1538             :    * Dequeue drop all bytes
    1539             :    */
    1540           1 :   rv = svm_fifo_dequeue_drop (f, fifo_size);
    1541           1 :   SFIFO_TEST ((rv == fifo_size), "all bytes should be dropped %u", rv);
    1542           1 :   last_start_byte += 8192;
    1543             : 
    1544           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1545           1 :   SFIFO_TEST (f->shr->head_chunk == 0, "should have no head chunk");
    1546           1 :   SFIFO_TEST (f->shr->tail_chunk == 0, "should have no tail chunk");
    1547             : 
    1548             :   /* We don't remove the last chunk even when the fifo goes empty */
    1549           1 :   rv = svm_fifo_n_chunks (f);
    1550           1 :   SFIFO_TEST (rv == 1, "should have %u chunks has %u", 1, rv);
    1551             : 
    1552             :   /*
    1553             :    * Increase size such that it can't be the sum of multiple chunk lengths
    1554             :    *
    1555             :    * A chunk of 16kB should be allocated
    1556             :    */
    1557           1 :   fifo_size += 2 * fifo_inc - 100;
    1558           1 :   svm_fifo_set_size (f, fifo_size);
    1559           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, fifo_size + fifo_inc);
    1560           1 :   enq_chunk = vec_len (test_data) / 10;
    1561           1 :   memset (data_buf, 0, vec_len (data_buf));
    1562             : 
    1563             :   /*
    1564             :    * Enqueue data ooo
    1565             :    */
    1566           1 :   rv = enqueue_ooo (f, test_data, fifo_size, 10);
    1567           1 :   SFIFO_TEST (!rv, "enqueue ooo should work");
    1568             : 
    1569           1 :   SFIFO_TEST (svm_fifo_size (f) == fifo_size, "size expected %u is %u",
    1570             :               fifo_size, svm_fifo_size (f));
    1571           1 :   SFIFO_TEST (svm_fifo_max_dequeue (f) == 0, "max deq should be %u", 0);
    1572             :   /* Fifo has 2 chunks because the we didn't allow the first chunk to be
    1573             :    * freed when all the data was dequeued. Could be optimized in the future */
    1574           1 :   rv = svm_fifo_n_chunks (f);
    1575           1 :   SFIFO_TEST (rv == 2, "should have %u chunks has %u", 2, rv);
    1576           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1577             : 
    1578           1 :   SFIFO_TEST (f->shr->head_chunk == 0, "should have no head chunk");
    1579             :   /* When new fifo chunks are allocated, tail is initialized */
    1580           1 :   SFIFO_TEST (f->shr->tail_chunk != 0, "should have no tail chunk");
    1581           1 :   SFIFO_TEST (f->ooo_enq != 0, "should have an ooo enq chunk");
    1582             : 
    1583           1 :   c = f_end_cptr (f);
    1584           1 :   SFIFO_TEST (c->start_byte == last_start_byte,
    1585             :               "end chunk should start at %u", last_start_byte);
    1586           1 :   SFIFO_TEST (c->length == 16384, "end chunk length should be %u", 16384);
    1587           1 :   SFIFO_TEST (f->ooo_enq == c, "ooo enq chunk should be end chunk");
    1588             : 
    1589             :   /*
    1590             :    * Enqueue the first chunk
    1591             :    */
    1592           1 :   rv = svm_fifo_enqueue (f, enq_chunk, test_data);
    1593           1 :   SFIFO_TEST (rv == fifo_size, "enq should succeed %u", rv);
    1594           1 :   rv = svm_fifo_max_dequeue (f);
    1595           1 :   SFIFO_TEST (rv == fifo_size, "max deq should be %u is %u", fifo_size, rv);
    1596           1 :   rv = svm_fifo_n_chunks (f);
    1597           1 :   SFIFO_TEST (rv == 2, "should have %u chunks has %u", 2, rv);
    1598           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1599             : 
    1600             :   /*
    1601             :    * Dequeue just a part of data. Because we're tracking ooo data, we can't
    1602             :    * call dequeue. Therefore, first peek and then dequeue drop
    1603             :    */
    1604           1 :   rv = svm_fifo_peek (f, 0, fifo_inc, data_buf);
    1605           1 :   SFIFO_TEST (rv == fifo_inc, "should dequeue all data");
    1606           1 :   rv = svm_fifo_dequeue_drop (f, fifo_inc);
    1607           1 :   SFIFO_TEST (rv == fifo_inc, "should dequeue all data");
    1608           1 :   rv = svm_fifo_n_chunks (f);
    1609           1 :   SFIFO_TEST (rv == 1, "should have %u chunks has %u", 1, rv);
    1610           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1611             : 
    1612             :   /*
    1613             :    * Enqueue ooo as much data as it was dequeued
    1614             :    */
    1615           1 :   rv = enqueue_ooo (f, test_data + fifo_size, fifo_inc, 2);
    1616           1 :   SFIFO_TEST (!rv, "ooo enqueue should work %d", rv);
    1617             : 
    1618           1 :   rv = svm_fifo_enqueue (f, fifo_inc / 2, test_data + fifo_size);
    1619           1 :   SFIFO_TEST (rv == fifo_inc, "enqueue should work %d", rv);
    1620             : 
    1621           1 :   rv = svm_fifo_n_chunks (f);
    1622           1 :   SFIFO_TEST (rv == 2, "should have %u chunks has %u", 2, rv);
    1623           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1624             : 
    1625           1 :   last_start_byte += 16384;
    1626           1 :   c = f_end_cptr (f);
    1627           1 :   SFIFO_TEST (c->start_byte == last_start_byte,
    1628             :               "end chunk should start at %u", last_start_byte);
    1629           1 :   SFIFO_TEST (c->length == 4096, "end chunk length should be %u", 4096);
    1630             : 
    1631             :   /*
    1632             :    * Dequeue all. Don't call dequeue see above
    1633             :    */
    1634           1 :   rv = svm_fifo_peek (f, 0, fifo_size, data_buf + fifo_inc);
    1635           1 :   SFIFO_TEST (rv == fifo_size, "should dequeue all data");
    1636           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1637             : 
    1638           1 :   rv = compare_data (data_buf, test_data, 0, vec_len (test_data),
    1639             :                      (u32 *) & i);
    1640           1 :   if (rv)
    1641           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1642           0 :                      test_data[i]);
    1643           1 :   SFIFO_TEST ((rv == 0), "dequeued compared to original returned %d", rv);
    1644             : 
    1645           1 :   rv = svm_fifo_dequeue_drop (f, fifo_size);
    1646           1 :   SFIFO_TEST (rv == fifo_size, "should dequeue all data");
    1647             : 
    1648           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1649             :   /* fifo does not end on chunk boundary because of the - 100 */
    1650           1 :   SFIFO_TEST (f->shr->head_chunk != 0, "should have head chunk");
    1651           1 :   SFIFO_TEST (f->shr->tail_chunk != 0, "should have tail chunk");
    1652             : 
    1653             :   /*
    1654             :    * Enqueue and dequeue byte-by-byte ooo
    1655             :    */
    1656             : 
    1657           1 :   memset (data_buf, 0, vec_len (data_buf));
    1658             : 
    1659           1 :   rv = enqueue_ooo (f, test_data, fifo_size, fifo_size);
    1660           1 :   SFIFO_TEST (!rv, "ooo enqueue should work %d", rv);
    1661             : 
    1662           1 :   rv = svm_fifo_enqueue (f, 1, test_data);
    1663           1 :   SFIFO_TEST (rv == fifo_size, "enqueue should work %d", rv);
    1664             : 
    1665           1 :   rv = dequeue_ooo (f, data_buf, fifo_size, fifo_size);
    1666           1 :   SFIFO_TEST (!rv, "ooo deq should work %d", rv);
    1667             : 
    1668           1 :   rv = compare_data (data_buf, test_data, 0, fifo_size, (u32 *) & i);
    1669           1 :   if (rv)
    1670           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1671           0 :                      test_data[i]);
    1672           1 :   SFIFO_TEST ((rv == 0), "dequeued compared to original returned %d", rv);
    1673           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1674             : 
    1675           1 :   last_start_byte += 4096;
    1676           1 :   c = f_end_cptr (f);
    1677           1 :   SFIFO_TEST (c->start_byte == last_start_byte,
    1678             :               "end chunk should start at %u", last_start_byte);
    1679           1 :   SFIFO_TEST (c->length == 16384, "end chunk length should be %u", 16384);
    1680             : 
    1681           1 :   rv = svm_fifo_n_chunks (f);
    1682           1 :   SFIFO_TEST (rv == 2, "should have %u chunks has %u", 2, rv);
    1683             : 
    1684             :   /*
    1685             :    * Dequeue drop all bytes
    1686             :    */
    1687           1 :   rv = svm_fifo_dequeue_drop (f, fifo_size);
    1688           1 :   SFIFO_TEST ((rv == fifo_size), "all bytes should be dropped %u", rv);
    1689             : 
    1690           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1691           1 :   SFIFO_TEST (f->shr->head_chunk != 0, "should have head chunk");
    1692           1 :   SFIFO_TEST (f->shr->tail_chunk != 0, "should have tail chunk");
    1693             : 
    1694             :   /* We don't remove the last chunk even when the fifo goes empty */
    1695           1 :   rv = svm_fifo_n_chunks (f);
    1696           1 :   SFIFO_TEST (rv == 1, "should have %u chunks has %u", 1, rv);
    1697           1 :   SFIFO_TEST (f->ooo_enq == 0, "should have no ooo enq chunk");
    1698           1 :   SFIFO_TEST (f->ooo_deq == 0, "should have no ooo deq chunk");
    1699             : 
    1700             :   /*
    1701             :    * Grow fifo to 4MB and force only 4kB chunk allocations
    1702             :    */
    1703           1 :   fifo_size = 4 << 20;
    1704           1 :   svm_fifo_set_size (f, fifo_inc);
    1705           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, fifo_size);
    1706           1 :   enq_chunk = 1500;
    1707           1 :   memset (data_buf, 0, vec_len (data_buf));
    1708             : 
    1709           1 :   rv = enqueue_packets_inc (f, fifo_size, enq_chunk, test_data);
    1710           1 :   SFIFO_TEST (!rv, "incremental packet enqueue should work");
    1711             : 
    1712           1 :   SFIFO_TEST (svm_fifo_max_dequeue (f) == fifo_size, "max deq should be %u",
    1713             :               fifo_size);
    1714           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1715             : 
    1716           1 :   rv = svm_fifo_n_chunks (f);
    1717           1 :   SFIFO_TEST (rv == (fifo_size / 4096) + 1, "should have %u chunks has %u",
    1718             :               (fifo_size / 4096) + 1, rv);
    1719             : 
    1720             : 
    1721             :   /*
    1722             :    * Dequeue all
    1723             :    */
    1724             : 
    1725             :   /* Because we're tracking ooo data, we can't call dequeue. Therefore,
    1726             :    * first peek and then dequeue drop */
    1727           1 :   rv = svm_fifo_peek (f, 0, fifo_size, data_buf);
    1728           1 :   SFIFO_TEST (rv == fifo_size, "should dequeue all data");
    1729             : 
    1730           1 :   rv = compare_data (data_buf, test_data, 0, vec_len (test_data),
    1731             :                      (u32 *) & i);
    1732           1 :   if (rv)
    1733           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1734           0 :                      test_data[i]);
    1735           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1736           1 :   SFIFO_TEST ((rv == 0), "dequeued compared to original returned %d", rv);
    1737             : 
    1738             : 
    1739           1 :   rv = svm_fifo_dequeue_drop (f, fifo_size);
    1740           1 :   SFIFO_TEST ((rv == fifo_size), "all bytes should be dropped %u", rv);
    1741           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1742           1 :   SFIFO_TEST (f->ooo_deq == 0, "should have no ooo deq chunk");
    1743           1 :   rv = svm_fifo_n_chunks (f);
    1744           1 :   SFIFO_TEST (rv == 1, "should have %u chunks has %u", 1, rv);
    1745             : 
    1746             :   /*
    1747             :    * Cleanup
    1748             :    */
    1749             : 
    1750           1 :   ft_fifo_free (fs, f);
    1751           1 :   ft_fifo_segment_free (fsm, fs);
    1752           1 :   vec_free (test_data);
    1753           1 :   vec_free (data_buf);
    1754           1 :   return 0;
    1755             : }
    1756             : 
    1757             : static int
    1758           1 : sfifo_test_fifo_shrink (vlib_main_t * vm, unformat_input_t * input)
    1759             : {
    1760           1 :   int __clib_unused verbose = 0, fifo_size = 4096, deq_chunk;
    1761           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
    1762           1 :   u8 *test_data = 0, *data_buf = 0;
    1763             :   fifo_segment_t *fs;
    1764             :   svm_fifo_t *f;
    1765             :   u32 enq_chunk;
    1766             :   int i, rv;
    1767             : 
    1768           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1769             :     {
    1770           0 :       if (unformat (input, "verbose"))
    1771           0 :         verbose = 1;
    1772             :       else
    1773             :         {
    1774           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    1775             :                            input);
    1776           0 :           return -1;
    1777             :         }
    1778             :     }
    1779             : 
    1780             :   /*
    1781             :    * Init fifo and enqueue data such that multiple 4096 chunks are allocated
    1782             :    */
    1783           1 :   fs = fifo_segment_prepare (fsm, "fifo-shrink", 0);
    1784           1 :   f = fifo_prepare (fs, fifo_size);
    1785             : 
    1786           1 :   fifo_size = 4 << 20;
    1787           1 :   svm_fifo_set_size (f, 4096);
    1788           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, fifo_size);
    1789           1 :   enq_chunk = 1500;
    1790           1 :   rv = enqueue_packets_inc (f, fifo_size, enq_chunk, test_data);
    1791           1 :   SFIFO_TEST (!rv, "incremental packet enqueue should work");
    1792             : 
    1793           1 :   rv = svm_fifo_max_enqueue (f);
    1794           1 :   SFIFO_TEST (rv == 0, "enqueue space %u", rv);
    1795           1 :   SFIFO_TEST (svm_fifo_max_dequeue (f) == fifo_size, "max deq should be %u",
    1796             :               fifo_size);
    1797           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1798             : 
    1799           1 :   rv = svm_fifo_n_chunks (f);
    1800           1 :   SFIFO_TEST (rv == (fifo_size / 4096), "should have %u chunks has %u",
    1801             :               (fifo_size / 4096), rv);
    1802             : 
    1803             :   /*
    1804             :    * Dequeue enough to collect one chunk
    1805             :    */
    1806           1 :   deq_chunk = 4096;
    1807           1 :   rv = svm_fifo_dequeue (f, deq_chunk, data_buf);
    1808           1 :   SFIFO_TEST (rv == deq_chunk, "should dequeue all data");
    1809             : 
    1810           1 :   rv = svm_fifo_n_chunks (f);
    1811           1 :   SFIFO_TEST (rv == (fifo_size / 4096) - 1, "should have %u chunks has %u",
    1812             :               (fifo_size / 4096) - 1, rv);
    1813           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1814             : 
    1815           1 :   rv = svm_fifo_max_enqueue (f);
    1816           1 :   SFIFO_TEST (rv == deq_chunk, "enqueue space %u", rv);
    1817             : 
    1818             :   /*
    1819             :    * Dequeue ooo byte-by-byte remaining data
    1820             :    */
    1821           1 :   rv = dequeue_ooo (f, data_buf + deq_chunk, fifo_size - deq_chunk,
    1822           1 :                     fifo_size - deq_chunk);
    1823           1 :   SFIFO_TEST (!rv, "ooo deq should work %d", rv);
    1824             : 
    1825           1 :   rv = compare_data (data_buf, test_data, 0, fifo_size, (u32 *) & i);
    1826           1 :   if (rv)
    1827           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1828           0 :                      test_data[i]);
    1829             : 
    1830           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1831           1 :   rv = svm_fifo_n_chunks (f);
    1832           1 :   SFIFO_TEST (rv == (fifo_size / 4096) - 1, "should have %u chunks has %u",
    1833             :               (fifo_size / 4096) - 1, rv);
    1834             : 
    1835             :   /*
    1836             :    * Drop all data
    1837             :    */
    1838           1 :   rv = svm_fifo_dequeue_drop (f, fifo_size - deq_chunk);
    1839           1 :   SFIFO_TEST (rv == fifo_size - deq_chunk, "should drop all data");
    1840           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1841           1 :   rv = svm_fifo_n_chunks (f);
    1842           1 :   SFIFO_TEST (rv == 1, "should have %u chunks has %u", 1, rv);
    1843           1 :   rv = svm_fifo_max_enqueue (f);
    1844           1 :   SFIFO_TEST (rv == fifo_size, "enqueue space %u", rv);
    1845             : 
    1846             : 
    1847             :   /*
    1848             :    * Reset size and enqueue ooo all data
    1849             :    */
    1850           1 :   svm_fifo_set_size (f, 4096);
    1851           1 :   enq_chunk = deq_chunk = 1500;
    1852           1 :   rv = enqueue_ooo_packets (f, vec_len (test_data), 1500, test_data);
    1853           1 :   SFIFO_TEST (!rv, "enqueue ooo should work");
    1854           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1855             : 
    1856             :   /* 1 additional chunk left from previous test */
    1857           1 :   rv = svm_fifo_n_chunks (f);
    1858           1 :   SFIFO_TEST (rv == (fifo_size / 4096) + 1, "should have %u chunks has %u",
    1859             :               (fifo_size / 4096) + 1, rv);
    1860             : 
    1861             :   /*
    1862             :    * Add missing first chunk
    1863             :    */
    1864           1 :   rv = svm_fifo_enqueue (f, enq_chunk, test_data);
    1865           1 :   SFIFO_TEST (rv == fifo_size, "enq should succeed %u", rv);
    1866           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1867           1 :   rv = svm_fifo_max_dequeue (f);
    1868           1 :   SFIFO_TEST (rv == fifo_size, "max deq should be %u is %u", fifo_size, rv);
    1869           1 :   rv = svm_fifo_n_chunks (f);
    1870           1 :   SFIFO_TEST (rv == (fifo_size / 4096) + 1, "should have %u chunks has %u",
    1871             :               (fifo_size / 4096) + 1, rv);
    1872             : 
    1873             :   /*
    1874             :    * Dequeue as packets
    1875             :    */
    1876           1 :   memset (data_buf, 0, vec_len (data_buf));
    1877           1 :   rv = dequeue_packets (f, fifo_size, deq_chunk, data_buf);
    1878           1 :   SFIFO_TEST (!rv, "deq pkts should work %d", rv);
    1879             : 
    1880           1 :   rv = compare_data (data_buf, test_data, 0, fifo_size, (u32 *) & i);
    1881           1 :   if (rv)
    1882           0 :     vlib_cli_output (vm, "[%d] dequeued %u expected %u", i, data_buf[i],
    1883           0 :                      test_data[i]);
    1884             : 
    1885             :   /*
    1886             :    * Enqueue and dequeue set of packets
    1887             :    */
    1888           1 :   svm_fifo_set_size (f, 4096);
    1889        1001 :   for (i = 0; i < 1000; i++)
    1890             :     {
    1891        1000 :       rv = svm_fifo_enqueue (f, enq_chunk, test_data);
    1892        1000 :       if (rv != enq_chunk)
    1893           0 :         SFIFO_TEST (0, "enq fail");
    1894        1000 :       rv = svm_fifo_dequeue (f, deq_chunk, data_buf);
    1895        1000 :       if (rv != deq_chunk)
    1896           0 :         SFIFO_TEST (0, "deq fail");
    1897             :     }
    1898             : 
    1899             :   /*
    1900             :    * Cleanup
    1901             :    */
    1902             : 
    1903           1 :   ft_fifo_free (fs, f);
    1904           1 :   ft_fifo_segment_free (fsm, fs);
    1905           1 :   vec_free (test_data);
    1906           1 :   vec_free (data_buf);
    1907             : 
    1908           1 :   return 0;
    1909             : }
    1910             : 
    1911             : static int
    1912           1 : sfifo_test_fifo_indirect (vlib_main_t * vm, unformat_input_t * input)
    1913             : {
    1914           1 :   int __clib_unused verbose = 0, fifo_size = 4096, deq_chunk;
    1915           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
    1916           1 :   u8 *test_data = 0, *data_buf = 0;
    1917             :   svm_fifo_chunk_t *c;
    1918             :   fifo_segment_t *fs;
    1919             :   svm_fifo_t *f;
    1920             :   int rv;
    1921             : 
    1922           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    1923             :     {
    1924           0 :       if (unformat (input, "verbose"))
    1925           0 :         verbose = 1;
    1926             :       else
    1927             :         {
    1928           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    1929             :                            input);
    1930           0 :           return -1;
    1931             :         }
    1932             :     }
    1933             : 
    1934             :   /*
    1935             :    * Init fifo and enqueue data such that multiple 4096 chunks are allocated
    1936             :    */
    1937           1 :   fs = fifo_segment_prepare (fsm, "fifo-indirect", 0);
    1938           1 :   f = fifo_prepare (fs, fifo_size);
    1939             : 
    1940           1 :   fifo_size = 4 << 20;
    1941           1 :   svm_fifo_set_size (f, fifo_size);
    1942           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, fifo_size);
    1943             : 
    1944           1 :   c = f_start_cptr (f);
    1945           1 :   SFIFO_TEST (c->next == 0, "no next");
    1946             : 
    1947           1 :   svm_fifo_fill_chunk_list (f);
    1948           1 :   SFIFO_TEST (c->next != 0, "new chunk should've been allocated");
    1949           1 :   SFIFO_TEST (f_cptr (f, c->next)->length == 4 << 20,
    1950             :               "new chunk should be 4MB");
    1951             : 
    1952           1 :   rv = svm_fifo_max_write_chunk (f);
    1953           1 :   SFIFO_TEST (rv == 4096, "max write chunk %u", rv);
    1954             : 
    1955             :   /*
    1956             :    * Enqueue enough to fill first chunk
    1957             :    */
    1958           1 :   svm_fifo_enqueue_nocopy (f, 4096);
    1959           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1960             : 
    1961           1 :   c = f_tail_cptr (f);
    1962           1 :   SFIFO_TEST (c == f_end_cptr (f), "tail is end chunk");
    1963             : 
    1964             :   /* Initialize head chunk */
    1965           1 :   rv = svm_fifo_max_read_chunk (f);
    1966           1 :   SFIFO_TEST (rv == 4096, "max read chunk %u", rv);
    1967           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    1968             : 
    1969             :   /*
    1970             :    * Move head over last segment
    1971             :    */
    1972           1 :   rv = svm_fifo_dequeue (f, 4096, data_buf);
    1973           1 :   SFIFO_TEST (rv == 4096, "dequeue should work");
    1974             : 
    1975           1 :   c = f_head_cptr (f);
    1976           1 :   SFIFO_TEST (c == f_end_cptr (f), "head chunk should be last");
    1977             : 
    1978           1 :   rv = svm_fifo_max_read_chunk (f);
    1979           1 :   SFIFO_TEST (rv == 0, "max read chunk %u", rv);
    1980             : 
    1981           1 :   rv = svm_fifo_max_write_chunk (f);
    1982           1 :   SFIFO_TEST (rv == 4 << 20, "max write chunk %u", rv);
    1983             : 
    1984             :   /*
    1985             :    * Cleanup
    1986             :    */
    1987             : 
    1988           1 :   ft_fifo_free (fs, f);
    1989           1 :   ft_fifo_segment_free (fsm, fs);
    1990           1 :   vec_free (test_data);
    1991           1 :   vec_free (data_buf);
    1992             : 
    1993           1 :   return 0;
    1994             : }
    1995             : 
    1996             : /* *INDENT-OFF* */
    1997             : svm_fifo_trace_elem_t fifo_trace[] = {};
    1998             : /* *INDENT-ON* */
    1999             : 
    2000             : static int
    2001           0 : sfifo_test_fifo_replay (vlib_main_t * vm, unformat_input_t * input)
    2002             : {
    2003             :   svm_fifo_t f;
    2004           0 :   int verbose = 0;
    2005           0 :   u8 no_read = 0, *str = 0;
    2006             : 
    2007           0 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    2008             :     {
    2009           0 :       if (unformat (input, "verbose"))
    2010           0 :         verbose = 1;
    2011           0 :       else if (unformat (input, "no-read"))
    2012           0 :         no_read = 1;
    2013             :       else
    2014             :         {
    2015           0 :           clib_error_t *e = clib_error_return
    2016             :             (0, "unknown input `%U'", format_unformat_error, input);
    2017           0 :           clib_error_report (e);
    2018           0 :           return -1;
    2019             :         }
    2020             :     }
    2021             : 
    2022             : #if SVMF_FIFO_TRACE
    2023             :   f.trace = fifo_trace;
    2024             : #endif
    2025             : 
    2026           0 :   str = svm_fifo_replay (str, &f, no_read, verbose);
    2027           0 :   vlib_cli_output (vm, "%v", str);
    2028           0 :   return 0;
    2029             : }
    2030             : 
    2031             : static int
    2032           1 : sfifo_test_fifo_make_rcv_wnd_zero (vlib_main_t * vm, unformat_input_t * input)
    2033             : {
    2034           1 :   int __clib_unused verbose = 0, fifo_size = 4096, deq_chunk;
    2035           1 :   fifo_segment_main_t _fsm = { 0 }, *fsm = &_fsm;
    2036           1 :   u8 *test_data = 0, *data_buf = 0;
    2037             :   fifo_segment_t *fs;
    2038             :   svm_fifo_t *f;
    2039             :   int rv;
    2040             : 
    2041           1 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    2042             :     {
    2043           0 :       if (unformat (input, "verbose"))
    2044           0 :         verbose = 1;
    2045             :       else
    2046             :         {
    2047           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    2048             :                            input);
    2049           0 :           return -1;
    2050             :         }
    2051             :     }
    2052             : 
    2053             :   /*
    2054             :    * Init fifo and enqueue data such that multiple 4096 chunks are allocated
    2055             :    */
    2056           1 :   fs = fifo_segment_prepare (fsm, "fifo-rcv-wnd-zero", 0);
    2057           1 :   f = fifo_prepare (fs, fifo_size);
    2058             : 
    2059             :   /* Enqueue 3000 into 4KB chunk, so there'll be 1096 free space */
    2060           1 :   svm_fifo_set_size (f, 4096);
    2061           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, fifo_size);
    2062           1 :   rv = svm_fifo_enqueue (f, 3000, test_data);
    2063           1 :   SFIFO_TEST (rv == 3000, "enqueued %u", rv);
    2064           1 :   rv = svm_fifo_max_enqueue (f);
    2065           1 :   SFIFO_TEST (rv == 1096, "svm_fifo_max_enqueue %u", rv);
    2066           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2067             : 
    2068             :   /* Shrink fifo size to the in-use size */
    2069           1 :   svm_fifo_set_size (f, 3000);
    2070           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2071             : 
    2072             :   /* In TCP, this should result in rcv-wnd = 0 */
    2073           1 :   rv = svm_fifo_max_enqueue (f);
    2074           1 :   SFIFO_TEST (rv == 0, "svm_fifo_max_enqueue %u", rv);
    2075           1 :   rv = svm_fifo_max_enqueue_prod (f);
    2076           1 :   SFIFO_TEST (rv == 0, "svm_fifo_max_enqueue_prod %u", rv);
    2077             : 
    2078             :   /* Dequeue and ... */
    2079           1 :   rv = svm_fifo_dequeue (f, 3000, data_buf);
    2080           1 :   SFIFO_TEST (rv == 3000, "dequeued %u", rv);
    2081             : 
    2082             :   /* Clean up */
    2083           1 :   ft_fifo_free (fs, f);
    2084           1 :   ft_fifo_segment_free (fsm, fs);
    2085           1 :   vec_free (test_data);
    2086           1 :   vec_free (data_buf);
    2087             : 
    2088           1 :   return 0;
    2089             : }
    2090             : 
    2091             : 
    2092             : static fifo_segment_main_t segment_main;
    2093             : 
    2094             : static int
    2095           1 : sfifo_test_fifo_segment_hello_world (int verbose)
    2096             : {
    2097           1 :   fifo_segment_create_args_t _a, *a = &_a;
    2098           1 :   fifo_segment_main_t *sm = &segment_main;
    2099           1 :   u8 *test_data, *retrieved_data = 0;
    2100             :   fifo_segment_t *fs;
    2101             :   svm_fifo_t *f;
    2102             :   int rv;
    2103             : 
    2104           1 :   clib_memset (a, 0, sizeof (*a));
    2105           1 :   a->segment_name = "fifo-test1";
    2106           1 :   a->segment_size = 256 << 10;
    2107           1 :   a->segment_type = SSVM_SEGMENT_PRIVATE;
    2108             : 
    2109           1 :   rv = fifo_segment_create (sm, a);
    2110           1 :   SFIFO_TEST (!rv, "svm_fifo_segment_create returned %d", rv);
    2111             : 
    2112           1 :   fs = fifo_segment_get_segment (sm, a->new_segment_indices[0]);
    2113           1 :   f = fifo_segment_alloc_fifo (fs, 4096, FIFO_SEGMENT_RX_FIFO);
    2114             : 
    2115           1 :   SFIFO_TEST (f != 0, "svm_fifo_segment_alloc_fifo");
    2116             : 
    2117           1 :   test_data = format (0, "Hello world%c", 0);
    2118           1 :   vec_validate (retrieved_data, vec_len (test_data) - 1);
    2119             : 
    2120         342 :   while (svm_fifo_max_enqueue (f) >= vec_len (test_data))
    2121         341 :     svm_fifo_enqueue (f, vec_len (test_data), test_data);
    2122             : 
    2123         342 :   while (svm_fifo_max_dequeue (f) >= vec_len (test_data))
    2124         341 :     svm_fifo_dequeue (f, vec_len (retrieved_data), retrieved_data);
    2125             : 
    2126         342 :   while (svm_fifo_max_enqueue (f) >= vec_len (test_data))
    2127         341 :     svm_fifo_enqueue (f, vec_len (test_data), test_data);
    2128             : 
    2129         342 :   while (svm_fifo_max_dequeue (f) >= vec_len (test_data))
    2130         341 :     svm_fifo_dequeue (f, vec_len (retrieved_data), retrieved_data);
    2131             : 
    2132           1 :   SFIFO_TEST (!memcmp (retrieved_data, test_data, vec_len (test_data)),
    2133             :               "data should be identical");
    2134             : 
    2135           1 :   vec_free (test_data);
    2136           1 :   vec_free (retrieved_data);
    2137           1 :   vec_free (a->new_segment_indices);
    2138           1 :   fifo_segment_free_fifo (fs, f);
    2139           1 :   fifo_segment_delete (sm, fs);
    2140           1 :   return 0;
    2141             : }
    2142             : 
    2143             : static int
    2144           1 : sfifo_test_fifo_segment_fifo_grow (int verbose)
    2145             : {
    2146           1 :   int rv, fifo_size = 4096, n_chunks, n_batch;
    2147           1 :   fifo_segment_main_t *sm = &segment_main;
    2148           1 :   fifo_segment_create_args_t _a, *a = &_a;
    2149           1 :   u8 *test_data = 0, *data_buf = 0;
    2150             :   u32 n_free_chunk_bytes, new_size;
    2151             :   fifo_segment_t *fs;
    2152             :   svm_fifo_t *f, *tf;
    2153             : 
    2154           1 :   clib_memset (a, 0, sizeof (*a));
    2155           1 :   a->segment_name = "fifo-test1";
    2156             :   /* size chosen to be able to force multi chunk allocation lower */
    2157           1 :   a->segment_size = 256 << 10;
    2158             :   /* overhead that reduces the amount of space dedicated to fifos */
    2159           1 :   a->segment_size += 1 << 14;
    2160           1 :   a->segment_type = SSVM_SEGMENT_PRIVATE;
    2161             : 
    2162             :   /* fifo allocation allocates chunks in batch */
    2163           1 :   n_batch = FIFO_SEGMENT_ALLOC_BATCH_SIZE;
    2164             : 
    2165           1 :   rv = fifo_segment_create (sm, a);
    2166             : 
    2167           1 :   SFIFO_TEST (!rv, "svm_fifo_segment_create returned %d", rv);
    2168             : 
    2169             :   /*
    2170             :    * Alloc fifo
    2171             :    */
    2172           1 :   fs = fifo_segment_get_segment (sm, a->new_segment_indices[0]);
    2173           1 :   fs->h->pct_first_alloc = 100;
    2174           1 :   f = fifo_segment_alloc_fifo (fs, fifo_size, FIFO_SEGMENT_RX_FIFO);
    2175             : 
    2176           1 :   SFIFO_TEST (f != 0, "svm_fifo_segment_alloc_fifo");
    2177             : 
    2178           1 :   n_chunks = fifo_segment_num_free_chunks (fs, fifo_size);
    2179           1 :   SFIFO_TEST (n_chunks == n_batch - 1, "free 2^10B chunks "
    2180             :               "should be %u is %u", n_batch - 1, n_chunks);
    2181           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2182           1 :   SFIFO_TEST (rv == (n_batch - 1) * fifo_size, "free chunk bytes %u "
    2183             :               "expected %u", rv, (n_batch - 1) * fifo_size);
    2184             : 
    2185             :   /*
    2186             :    * Grow fifo by preallocated fifo_size chunk
    2187             :    */
    2188           1 :   svm_fifo_set_size (f, 2 * fifo_size);
    2189           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, 2 * fifo_size);
    2190             : 
    2191           1 :   rv = svm_fifo_enqueue (f, vec_len (test_data), test_data);
    2192           1 :   SFIFO_TEST (rv == vec_len (test_data), "enq should succeed %u", rv);
    2193           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2194             : 
    2195           1 :   n_chunks = fifo_segment_num_free_chunks (fs, fifo_size);
    2196           1 :   SFIFO_TEST (n_chunks == n_batch - 2, "free 2^10B chunks "
    2197             :               "should be %u is %u", n_batch - 2, n_chunks);
    2198           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2199           1 :   SFIFO_TEST (rv == (n_batch - 2) * fifo_size, "free chunk bytes %u "
    2200             :               "expected %u", rv, (n_batch - 2) * fifo_size);
    2201             : 
    2202             :   /* Grow by a size not preallocated but first make sure there's space */
    2203           1 :   rv = fifo_segment_free_bytes (fs);
    2204           1 :   SFIFO_TEST (rv > 16 * fifo_size, "free bytes %u more than %u", rv,
    2205             :               16 * fifo_size);
    2206             : 
    2207             :   /* Force fifo growth */
    2208           1 :   svm_fifo_set_size (f, svm_fifo_size (f) + 16 * fifo_size);
    2209           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, svm_fifo_size (f));
    2210           1 :   rv = svm_fifo_enqueue (f, vec_len (test_data), test_data);
    2211             : 
    2212           1 :   SFIFO_TEST (svm_fifo_size (f) == 18 * fifo_size, "fifo size should be %u "
    2213             :               "is %u", 18 * fifo_size, svm_fifo_size (f));
    2214             : 
    2215           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2216           1 :   SFIFO_TEST (rv == (n_batch - 2) * fifo_size, "free chunk bytes %u "
    2217             :               "expected %u", rv, (n_batch - 2) * fifo_size);
    2218             : 
    2219             :   /*
    2220             :    * Free and test free list size
    2221             :    */
    2222           1 :   fifo_segment_free_fifo (fs, f);
    2223             : 
    2224           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2225           1 :   SFIFO_TEST (rv == (16 + n_batch) * fifo_size, "free chunk bytes expected %u"
    2226             :               " is %u", (16 + n_batch) * fifo_size, rv);
    2227           1 :   n_chunks = fifo_segment_num_free_chunks (fs, fifo_size);
    2228           1 :   SFIFO_TEST (n_chunks == n_batch, "free 2^10B chunks "
    2229             :               "should be %u is %u", n_batch, n_chunks);
    2230           1 :   n_chunks = fifo_segment_num_free_chunks (fs, 16 * fifo_size);
    2231           1 :   SFIFO_TEST (n_chunks == 1, "free 2^14B chunks should be %u is %u", 1,
    2232             :               n_chunks);
    2233           1 :   n_chunks = fifo_segment_num_free_chunks (fs, ~0);
    2234           1 :   SFIFO_TEST (n_chunks == 1 + n_batch, "free chunks should be %u is %u",
    2235             :               1 + n_batch, n_chunks);
    2236             : 
    2237             :   /*
    2238             :    * Realloc fifo
    2239             :    */
    2240           1 :   f = fifo_segment_alloc_fifo (fs, fifo_size, FIFO_SEGMENT_RX_FIFO);
    2241             : 
    2242             :   /* Force chunk allocation */
    2243           1 :   svm_fifo_set_size (f, svm_fifo_size (f) + fifo_size);
    2244           1 :   rv = svm_fifo_enqueue (f, svm_fifo_size (f), test_data);
    2245             : 
    2246           1 :   SFIFO_TEST (rv == svm_fifo_size (f), "enq should succeed %u", rv);
    2247           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2248             : 
    2249           1 :   n_chunks = fifo_segment_num_free_chunks (fs, fifo_size);
    2250           1 :   SFIFO_TEST (n_chunks == n_batch - 2, "free 2^10B chunks should be %u is %u",
    2251             :               n_batch - 2, n_chunks);
    2252             : 
    2253             :   /* Grow and alloc 16 * fifo_size chunk */
    2254           1 :   svm_fifo_set_size (f, svm_fifo_size (f) + 16 * fifo_size);
    2255           1 :   rv = svm_fifo_enqueue (f, svm_fifo_size (f), test_data);
    2256             : 
    2257           1 :   n_chunks = fifo_segment_num_free_chunks (fs, 16 * fifo_size);
    2258           1 :   SFIFO_TEST (n_chunks == 0, "free 2^14B chunks should be %u is %u", 0,
    2259             :               n_chunks);
    2260           1 :   n_chunks = fifo_segment_num_free_chunks (fs, ~0);
    2261           1 :   SFIFO_TEST (n_chunks == n_batch - 2, "free chunks should be %u is %u",
    2262             :               n_batch - 2, n_chunks);
    2263             : 
    2264             :   /*
    2265             :    * Free again
    2266             :    */
    2267           1 :   fifo_segment_free_fifo (fs, f);
    2268           1 :   n_chunks = fifo_segment_num_free_chunks (fs, ~0);
    2269           1 :   SFIFO_TEST (n_chunks == 1 + n_batch, "free chunks should be %u is %u",
    2270             :               1 + n_batch, n_chunks);
    2271             : 
    2272           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2273           1 :   SFIFO_TEST (rv == (16 + n_batch) * fifo_size, "free chunk bytes expected %u"
    2274             :               " is %u", (16 + n_batch) * fifo_size, rv);
    2275             : 
    2276           1 :   n_free_chunk_bytes = rv;
    2277             : 
    2278             :   /*
    2279             :    * Allocate non power of 2 fifo/chunk and check that free chunk bytes
    2280             :    * is correctly updated
    2281             :    */
    2282             : 
    2283           1 :   f = fifo_segment_alloc_fifo (fs, 16 * fifo_size - 1, FIFO_SEGMENT_RX_FIFO);
    2284           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2285             : 
    2286           1 :   SFIFO_TEST (n_free_chunk_bytes - 16 * fifo_size == rv, "free chunk bytes "
    2287             :               "expected %u is %u", n_free_chunk_bytes - 16 * fifo_size, rv);
    2288           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2289             : 
    2290           1 :   fifo_segment_free_fifo (fs, f);
    2291           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2292             : 
    2293           1 :   SFIFO_TEST (n_free_chunk_bytes == rv, "free chunk bytes expected %u is %u",
    2294             :               n_free_chunk_bytes, rv);
    2295             : 
    2296             :   /*
    2297             :    * Force multi chunk fifo allocation
    2298             :    */
    2299             : 
    2300             :   /* Check that we can force multi chunk allocation. Note that fifo size
    2301             :    * rounded up to power of 2, i.e., 17 becomes 32 */
    2302           1 :   rv = fifo_segment_free_bytes (fs);
    2303           1 :   SFIFO_TEST (rv < 32 * fifo_size, "free bytes %u less than %u", rv,
    2304             :               32 * fifo_size);
    2305             : 
    2306           1 :   f = fifo_segment_alloc_fifo (fs, 17 * fifo_size, FIFO_SEGMENT_RX_FIFO);
    2307           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2308             : 
    2309           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2310             : 
    2311             :   /* Make sure that the non-power of two chunk freed above is correctly
    2312             :    * accounted for in the chunk free bytes reduction due to chunk allocation
    2313             :    * for the fifo, i.e., it's rounded up by 1 */
    2314           1 :   SFIFO_TEST (n_free_chunk_bytes - 17 * fifo_size == rv, "free chunk bytes "
    2315             :               "expected %u is %u", n_free_chunk_bytes - 17 * fifo_size, rv);
    2316             : 
    2317           1 :   fifo_segment_free_fifo (fs, f);
    2318             : 
    2319           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2320           1 :   SFIFO_TEST (n_free_chunk_bytes == rv, "free chunk bytes expected %u is %u",
    2321             :               n_free_chunk_bytes, rv);
    2322             : 
    2323             :   /*
    2324             :    * Allocate fifo that has all chunks. Because we have a chunk size limit of
    2325             :    * segment_size / 2, allocate 2 fifos.
    2326             :    */
    2327           1 :   tf = fifo_segment_alloc_fifo (fs, n_free_chunk_bytes / 2,
    2328             :                                 FIFO_SEGMENT_RX_FIFO);
    2329           1 :   SFIFO_TEST (tf != 0, "allocation should work");
    2330           1 :   SFIFO_TEST (svm_fifo_is_sane (tf), "fifo should be sane");
    2331             : 
    2332           1 :   f = fifo_segment_alloc_fifo (fs, n_free_chunk_bytes / 2,
    2333             :                                FIFO_SEGMENT_RX_FIFO);
    2334           1 :   SFIFO_TEST (f != 0, "allocation should work");
    2335           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2336             : 
    2337           1 :   fifo_segment_free_fifo (fs, tf);
    2338           1 :   fifo_segment_free_fifo (fs, f);
    2339             : 
    2340           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2341           1 :   SFIFO_TEST (n_free_chunk_bytes == rv, "free chunk bytes expected %u is %u",
    2342             :               n_free_chunk_bytes, rv);
    2343             : 
    2344             :   /*
    2345             :    * Try to allocate more than space available
    2346             :    */
    2347             : 
    2348           1 :   f = fifo_segment_alloc_fifo (fs, n_free_chunk_bytes + fifo_size,
    2349             :                                FIFO_SEGMENT_RX_FIFO);
    2350           1 :   SFIFO_TEST (f == 0, "allocation should fail");
    2351             : 
    2352             :   /*
    2353             :    * Allocate fifo and try to grow beyond available space
    2354             :    */
    2355           1 :   f = fifo_segment_alloc_fifo (fs, fifo_segment_free_bytes (fs),
    2356             :                                FIFO_SEGMENT_RX_FIFO);
    2357             : 
    2358             :   /* Try to force fifo growth */
    2359           1 :   new_size = svm_fifo_size (f) + n_free_chunk_bytes + 1;
    2360           1 :   svm_fifo_set_size (f, new_size);
    2361           1 :   validate_test_and_buf_vecs (&test_data, &data_buf, new_size);
    2362           1 :   rv = svm_fifo_enqueue (f, new_size, test_data);
    2363             : 
    2364           1 :   SFIFO_TEST (rv != new_size, "grow should fail size %u wrote %d",
    2365             :               new_size, rv);
    2366             : 
    2367           1 :   fifo_segment_free_fifo (fs, f);
    2368             : 
    2369             :   /*
    2370             :    * Cleanup
    2371             :    */
    2372           1 :   fifo_segment_delete (sm, fs);
    2373           1 :   vec_free (a->new_segment_indices);
    2374           1 :   return 0;
    2375             : }
    2376             : 
    2377             : static int
    2378           0 : sfifo_test_fifo_segment_slave (int verbose)
    2379             : {
    2380           0 :   fifo_segment_create_args_t _a, *a = &_a;
    2381           0 :   fifo_segment_main_t *sm = &segment_main;
    2382           0 :   u8 *test_data, *retrieved_data = 0;
    2383             :   fifo_segment_t *fs;
    2384             :   svm_fifo_t *f;
    2385             :   u32 *result;
    2386             :   int rv, i;
    2387             : 
    2388           0 :   sleep (2);
    2389             : 
    2390           0 :   sm->timeout_in_seconds = 5;
    2391           0 :   clib_memset (a, 0, sizeof (*a));
    2392           0 :   a->segment_name = "fifo-test1";
    2393             : 
    2394           0 :   rv = fifo_segment_attach (sm, a);
    2395             : 
    2396           0 :   SFIFO_TEST (!rv, "svm_fifo_segment_attach returned %d", rv);
    2397             : 
    2398           0 :   fs = fifo_segment_get_segment (sm, a->new_segment_indices[0]);
    2399           0 :   vec_free (a->new_segment_indices);
    2400             : 
    2401             :   /* might wanna wait.. */
    2402           0 :   f = fifo_segment_get_slice_fifo_list (fs, 0);
    2403             : 
    2404             :   /* Lazy bastards united */
    2405           0 :   test_data = format (0, "Hello world%c", 0);
    2406           0 :   vec_validate (retrieved_data, vec_len (test_data) - 1);
    2407             : 
    2408           0 :   for (i = 0; i < 1000; i++)
    2409             :     {
    2410           0 :       svm_fifo_dequeue (f, vec_len (retrieved_data), retrieved_data);
    2411           0 :       if (memcmp (retrieved_data, test_data, vec_len (retrieved_data)))
    2412             :         {
    2413           0 :           result = (u32 *) f_head_cptr (f)->data;
    2414           0 :           *result = 1;
    2415           0 :           _exit (0);
    2416             :         }
    2417             :     }
    2418             : 
    2419           0 :   result = (u32 *) f_head_cptr (f)->data;
    2420           0 :   *result = 0;
    2421             : 
    2422           0 :   vec_free (test_data);
    2423           0 :   vec_free (retrieved_data);
    2424           0 :   _exit (0);
    2425             : }
    2426             : 
    2427             : static int
    2428           0 : sfifo_test_fifo_segment_master_slave (int verbose)
    2429             : {
    2430           0 :   fifo_segment_create_args_t _a, *a = &_a;
    2431           0 :   fifo_segment_main_t *sm = &segment_main;
    2432             :   fifo_segment_t *sp;
    2433             :   svm_fifo_t *f;
    2434             :   u8 *test_data;
    2435             :   u32 *result;
    2436             :   int rv, i;
    2437             :   pid_t pid;
    2438             : 
    2439           0 :   pid = fork ();
    2440           0 :   if (pid < 0)
    2441           0 :     SFIFO_TEST (0, "fork failed");
    2442             : 
    2443           0 :   if (!pid)
    2444           0 :     sfifo_test_fifo_segment_slave (verbose);
    2445             : 
    2446           0 :   clib_memset (a, 0, sizeof (*a));
    2447           0 :   a->segment_name = "fifo-test1";
    2448           0 :   a->segment_size = 256 << 10;
    2449             : 
    2450           0 :   rv = fifo_segment_create (sm, a);
    2451             : 
    2452           0 :   SFIFO_TEST (!rv, "svm_fifo_segment_create returned %d", rv);
    2453             : 
    2454           0 :   sp = fifo_segment_get_segment (sm, a->new_segment_indices[0]);
    2455           0 :   f = fifo_segment_alloc_fifo (sp, 4096, FIFO_SEGMENT_RX_FIFO);
    2456             : 
    2457           0 :   SFIFO_TEST (f != 0, "svm_fifo_segment_alloc_fifo alloc");
    2458             : 
    2459           0 :   test_data = format (0, "Hello world%c", 0);
    2460             : 
    2461           0 :   usleep (200e3);
    2462             : 
    2463           0 :   for (i = 0; i < 1000; i++)
    2464           0 :     svm_fifo_enqueue (f, vec_len (test_data), test_data);
    2465             : 
    2466             :   /* Wait for slave */
    2467           0 :   i = 0;
    2468           0 :   while (svm_fifo_max_dequeue (f) && i++ < 1e10)
    2469             :     ;
    2470             : 
    2471           0 :   usleep (1e3);
    2472             : 
    2473           0 :   result = (u32 *) f_head_cptr (f)->data;
    2474           0 :   SFIFO_TEST (*result == 0, "slave reported no error");
    2475             : 
    2476           0 :   vec_free (a->new_segment_indices);
    2477           0 :   vec_free (test_data);
    2478           0 :   fifo_segment_free_fifo (sp, f);
    2479           0 :   fifo_segment_delete (sm, sp);
    2480           0 :   return 0;
    2481             : }
    2482             : 
    2483             : static int
    2484           1 : sfifo_test_fifo_segment_mempig (int verbose)
    2485             : {
    2486           1 :   fifo_segment_create_args_t _a, *a = &_a;
    2487           1 :   fifo_segment_main_t *sm = &segment_main;
    2488             :   fifo_segment_t *sp;
    2489             :   svm_fifo_t *f;
    2490           1 :   svm_fifo_t **flist = 0;
    2491             :   int rv;
    2492             :   int i;
    2493             : 
    2494           1 :   clib_memset (a, 0, sizeof (*a));
    2495             : 
    2496           1 :   a->segment_name = "fifo-test1";
    2497           1 :   a->segment_size = 256 << 10;
    2498           1 :   a->segment_type = SSVM_SEGMENT_PRIVATE;
    2499             : 
    2500           1 :   rv = fifo_segment_create (sm, a);
    2501             : 
    2502           1 :   SFIFO_TEST (!rv, "svm_fifo_segment_create returned %d", rv);
    2503             : 
    2504           1 :   sp = fifo_segment_get_segment (sm, a->new_segment_indices[0]);
    2505             : 
    2506          59 :   for (i = 0; i < 1000; i++)
    2507             :     {
    2508          59 :       f = fifo_segment_alloc_fifo (sp, 4096, FIFO_SEGMENT_RX_FIFO);
    2509          59 :       if (f == 0)
    2510           1 :         break;
    2511          58 :       vec_add1 (flist, f);
    2512             :     }
    2513             : 
    2514           1 :   SFIFO_TEST (vec_len (flist), "created %d fifos", vec_len (flist));
    2515             : 
    2516          59 :   for (i = 0; i < vec_len (flist); i++)
    2517             :     {
    2518          58 :       f = flist[i];
    2519          58 :       fifo_segment_free_fifo (sp, f);
    2520             :     }
    2521             : 
    2522           1 :   vec_set_len (flist, 0);
    2523             : 
    2524          59 :   for (i = 0; i < 1000; i++)
    2525             :     {
    2526          59 :       f = fifo_segment_alloc_fifo (sp, 4096, FIFO_SEGMENT_RX_FIFO);
    2527          59 :       if (f == 0)
    2528           1 :         break;
    2529          58 :       vec_add1 (flist, f);
    2530             :     }
    2531             : 
    2532           1 :   SFIFO_TEST (vec_len (flist), "second try created %d fifos",
    2533             :               vec_len (flist));
    2534          59 :   for (i = 0; i < vec_len (flist); i++)
    2535             :     {
    2536          58 :       f = flist[i];
    2537          58 :       fifo_segment_free_fifo (sp, f);
    2538             :     }
    2539             : 
    2540           1 :   fifo_segment_delete (sm, sp);
    2541           1 :   return 0;
    2542             : }
    2543             : 
    2544             : static int
    2545           2 : approx_leq (uword a, uword b, u32 margin)
    2546             : {
    2547           2 :   if (a - margin <= b && b <= a)
    2548           2 :     return 1;
    2549           0 :   return 0;
    2550             : }
    2551             : 
    2552             : static int
    2553           1 : sfifo_test_fifo_segment_prealloc (int verbose)
    2554             : {
    2555             :   u32 max_pairs, pairs_req, free_space, pair_mem, overhead;
    2556           1 :   fifo_segment_create_args_t _a, *a = &_a;
    2557           1 :   fifo_segment_main_t *sm = &segment_main;
    2558             :   svm_fifo_t *f, *tf, *old;
    2559             :   fifo_segment_t *fs;
    2560             :   int rv, alloc;
    2561             : 
    2562           1 :   clib_memset (a, 0, sizeof (*a));
    2563             : 
    2564             :   /* Overhead due to segment internal headers and offsets. The magic 384
    2565             :    * bytes are the fsh->n_reserved_bytes after seg init */
    2566           1 :   overhead = (8 << 10) + 384;
    2567           1 :   a->segment_name = "fifo-test-prealloc";
    2568           1 :   a->segment_size = (256 << 10) + overhead;
    2569           1 :   a->segment_type = SSVM_SEGMENT_PRIVATE;
    2570             : 
    2571           1 :   rv = fifo_segment_create (sm, a);
    2572           1 :   SFIFO_TEST (!rv, "svm_fifo_segment_create returned %d", rv);
    2573           1 :   fs = fifo_segment_get_segment (sm, a->new_segment_indices[0]);
    2574           1 :   fs->h->pct_first_alloc = 100;
    2575             : 
    2576             :   /*
    2577             :    * Prealloc chunks and headers
    2578             :    */
    2579           1 :   free_space = fifo_segment_free_bytes (fs);
    2580           1 :   SFIFO_TEST (free_space - 4096 <= 256 << 10, "free space expected %u is %u",
    2581             :               256 << 10, free_space);
    2582           1 :   rv = fifo_segment_prealloc_fifo_chunks (fs, 0, 4096, 50);
    2583           1 :   SFIFO_TEST (rv == 0, "chunk prealloc should work");
    2584           1 :   rv = fifo_segment_num_free_chunks (fs, 4096);
    2585           1 :   SFIFO_TEST (rv == 50, "prealloc chunks expected %u is %u", 50, rv);
    2586           1 :   rv = fifo_segment_free_bytes (fs);
    2587           1 :   free_space -= (sizeof (svm_fifo_chunk_t) + 4096) * 50;
    2588             :   /* Memory alloc alignment accounts for the difference */
    2589           1 :   SFIFO_TEST (approx_leq (free_space, rv, 16), "free space expected %u is %u",
    2590             :               free_space, rv);
    2591           1 :   free_space = rv;
    2592           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2593           1 :   SFIFO_TEST (rv == 4096 * 50, "chunk free space expected %u is %u",
    2594             :               4096 * 50, rv);
    2595             : 
    2596           1 :   rv = fifo_segment_prealloc_fifo_hdrs (fs, 0, 50);
    2597           1 :   SFIFO_TEST (rv == 0, "fifo hdr prealloc should work");
    2598           1 :   rv = fifo_segment_num_free_fifos (fs);
    2599           1 :   SFIFO_TEST (rv == 50, "prealloc fifo hdrs expected %u is %u", 50, rv);
    2600           1 :   rv = fifo_segment_free_bytes (fs);
    2601           1 :   free_space -= sizeof (svm_fifo_shared_t) * 50;
    2602             :   /* Memory alloc alignment accounts for the difference */
    2603           1 :   SFIFO_TEST (approx_leq (free_space, rv, 128), "free space expected %u is %u",
    2604             :               free_space, rv);
    2605           1 :   free_space = rv;
    2606             : 
    2607           1 :   rv = fifo_segment_free_bytes (fs);
    2608           1 :   SFIFO_TEST (clib_abs (rv - (int) free_space) < 512,
    2609             :               "free space expected %u is %u", free_space, rv);
    2610             : 
    2611             :   /* Use all free chunk memory */
    2612           1 :   f = fifo_segment_alloc_fifo (fs, 100 << 10, FIFO_SEGMENT_RX_FIFO);
    2613           1 :   SFIFO_TEST (f != 0, "fifo allocated");
    2614           1 :   SFIFO_TEST (svm_fifo_is_sane (f), "fifo should be sane");
    2615             : 
    2616           1 :   tf = fifo_segment_alloc_fifo (fs, 100 << 10, FIFO_SEGMENT_RX_FIFO);
    2617           1 :   SFIFO_TEST (tf != 0, "fifo allocated");
    2618           1 :   SFIFO_TEST (svm_fifo_is_sane (tf), "fifo should be sane");
    2619             : 
    2620           1 :   rv = fifo_segment_num_free_chunks (fs, 4096);
    2621           1 :   SFIFO_TEST (rv == 0, "prealloc chunks expected %u is %u", 0, rv);
    2622           1 :   rv = fifo_segment_fl_chunk_bytes (fs);
    2623           1 :   SFIFO_TEST (rv == 0, "chunk free space expected %u is %u", 0, rv);
    2624             : 
    2625             : 
    2626             :   /*
    2627             :    * Multiple preallocs that consume the remaining space
    2628             :    */
    2629           1 :   free_space = fifo_segment_free_bytes (fs);
    2630           1 :   pair_mem = 2 * (4096 + sizeof (*f) + sizeof (svm_fifo_chunk_t));
    2631           1 :   max_pairs = pairs_req = (free_space / pair_mem) - 1;
    2632           1 :   fifo_segment_preallocate_fifo_pairs (fs, 4096, 4096, &pairs_req);
    2633           1 :   SFIFO_TEST (pairs_req == 0, "prealloc pairs should work req %u", max_pairs);
    2634           1 :   rv = fifo_segment_num_free_chunks (fs, 4096);
    2635           1 :   SFIFO_TEST (rv == max_pairs * 2, "prealloc chunks expected %u is %u",
    2636             :               max_pairs * 2, rv);
    2637             : 
    2638           1 :   rv = fifo_segment_free_bytes (fs);
    2639           1 :   SFIFO_TEST (rv < 2 * pair_mem, "free bytes %u less than %u", rv,
    2640             :               2 * pair_mem);
    2641             : 
    2642             :   /* Preallocate as many more chunks as possible. Heap is almost full
    2643             :    * so we may not use all the free space*/
    2644           1 :   alloc = 0;
    2645           4 :   while (!fifo_segment_prealloc_fifo_chunks (fs, 0, 4096, 1))
    2646           3 :     alloc++;
    2647           1 :   SFIFO_TEST (alloc, "chunk prealloc should work %u", alloc);
    2648           1 :   rv = fifo_segment_num_free_chunks (fs, 4096);
    2649           1 :   SFIFO_TEST (rv == max_pairs * 2 + alloc, "prealloc chunks expected %u "
    2650             :               "is %u", max_pairs * 2 + alloc, rv);
    2651             : 
    2652           1 :   rv = fifo_segment_free_bytes (fs);
    2653           1 :   SFIFO_TEST (rv < pair_mem, "free bytes expected less than %u is %u",
    2654             :               pair_mem, rv);
    2655             : 
    2656             :   /*
    2657             :    * Test negative prealloc cases
    2658             :    */
    2659           1 :   pairs_req = 1;
    2660           1 :   fifo_segment_preallocate_fifo_pairs (fs, 4096, 4096, &pairs_req);
    2661           1 :   SFIFO_TEST (pairs_req == 1, "prealloc pairs should not work");
    2662             : 
    2663           1 :   old = f;
    2664           1 :   f = fifo_segment_alloc_fifo (fs, 200 << 10, FIFO_SEGMENT_RX_FIFO);
    2665           1 :   SFIFO_TEST (f == 0, "fifo alloc should fail");
    2666             : 
    2667           1 :   rv = fifo_segment_prealloc_fifo_chunks (fs, 0, 4096, 50);
    2668           1 :   SFIFO_TEST (rv == -1, "chunk prealloc should fail");
    2669             : 
    2670           1 :   rv = fifo_segment_prealloc_fifo_hdrs (fs, 0, 50);
    2671           1 :   SFIFO_TEST (rv == -1, "fifo hdr prealloc should fail");
    2672             : 
    2673             :   /*
    2674             :    * Cleanup
    2675             :    */
    2676           1 :   fifo_segment_free_fifo (fs, old);
    2677           1 :   fifo_segment_free_fifo (fs, tf);
    2678           1 :   fifo_segment_delete (sm, fs);
    2679           1 :   return 0;
    2680             : }
    2681             : 
    2682             : static int
    2683           1 : sfifo_test_fifo_segment (vlib_main_t * vm, unformat_input_t * input)
    2684             : {
    2685           1 :   int rv, verbose = 0;
    2686             : 
    2687           2 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    2688             :     {
    2689           1 :       if (unformat (input, "verbose"))
    2690           0 :         verbose = 1;
    2691           1 :       else if (unformat (input, "masterslave"))
    2692             :         {
    2693           0 :           if ((rv = sfifo_test_fifo_segment_master_slave (verbose)))
    2694           0 :             return -1;
    2695             :         }
    2696           1 :       else if (unformat (input, "basic"))
    2697             :         {
    2698           0 :           if ((rv = sfifo_test_fifo_segment_hello_world (verbose)))
    2699           0 :             return -1;
    2700             :         }
    2701           1 :       else if (unformat (input, "mempig"))
    2702             :         {
    2703           0 :           if ((rv = sfifo_test_fifo_segment_mempig (verbose)))
    2704           0 :             return -1;
    2705             :         }
    2706           1 :       else if (unformat (input, "grow fifo"))
    2707             :         {
    2708           0 :           if ((rv = sfifo_test_fifo_segment_fifo_grow (verbose)))
    2709           0 :             return -1;
    2710             :         }
    2711           1 :       else if (unformat (input, "prealloc"))
    2712             :         {
    2713           0 :           if ((rv = sfifo_test_fifo_segment_prealloc (verbose)))
    2714           0 :             return -1;
    2715             :         }
    2716           1 :       else if (unformat (input, "all"))
    2717             :         {
    2718           1 :           if ((rv = sfifo_test_fifo_segment_hello_world (verbose)))
    2719           0 :             return -1;
    2720           1 :           if ((rv = sfifo_test_fifo_segment_mempig (verbose)))
    2721           0 :             return -1;
    2722           1 :           if ((rv = sfifo_test_fifo_segment_fifo_grow (verbose)))
    2723           0 :             return -1;
    2724           1 :           if ((rv = sfifo_test_fifo_segment_prealloc (verbose)))
    2725           0 :             return -1;
    2726             :           /* Pretty slow so avoid running it always
    2727             :              if ((rv = sfifo_test_fifo_segment_master_slave (verbose)))
    2728             :              return -1;
    2729             :            */
    2730             :         }
    2731             :       else
    2732             :         {
    2733           0 :           vlib_cli_output (vm, "parse error: '%U'", format_unformat_error,
    2734             :                            input);
    2735           0 :           return -1;
    2736             :         }
    2737             :     }
    2738           1 :   return 0;
    2739             : }
    2740             : 
    2741             : static clib_error_t *
    2742           1 : svm_fifo_test (vlib_main_t * vm, unformat_input_t * input,
    2743             :                vlib_cli_command_t * cmd_arg)
    2744             : {
    2745           1 :   int res = 0;
    2746             :   char *str;
    2747             : 
    2748           1 :   clib_warning ("high mem %lu", HIGH_SEGMENT_BASEVA);
    2749           1 :   fifo_segment_main_init (&segment_main, HIGH_SEGMENT_BASEVA, 5);
    2750           2 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
    2751             :     {
    2752           1 :       if (unformat (input, "fifo1"))
    2753           0 :         res = sfifo_test_fifo1 (vm, input);
    2754           1 :       else if (unformat (input, "fifo2"))
    2755           0 :         res = sfifo_test_fifo2 (vm);
    2756           1 :       else if (unformat (input, "fifo3"))
    2757           0 :         res = sfifo_test_fifo3 (vm, input);
    2758           1 :       else if (unformat (input, "fifo4"))
    2759           0 :         res = sfifo_test_fifo4 (vm, input);
    2760           1 :       else if (unformat (input, "fifo5"))
    2761           0 :         res = sfifo_test_fifo5 (vm, input);
    2762           1 :       else if (unformat (input, "fifo6"))
    2763           0 :         res = sfifo_test_fifo6 (vm, input);
    2764           1 :       else if (unformat (input, "fifo7"))
    2765           0 :         res = sfifo_test_fifo7 (vm, input);
    2766           1 :       else if (unformat (input, "large"))
    2767           0 :         res = sfifo_test_fifo_large (vm, input);
    2768           1 :       else if (unformat (input, "replay"))
    2769           0 :         res = sfifo_test_fifo_replay (vm, input);
    2770           1 :       else if (unformat (input, "grow"))
    2771           0 :         res = sfifo_test_fifo_grow (vm, input);
    2772           1 :       else if (unformat (input, "shrink"))
    2773           0 :         res = sfifo_test_fifo_shrink (vm, input);
    2774           1 :       else if (unformat (input, "indirect"))
    2775           0 :         res = sfifo_test_fifo_indirect (vm, input);
    2776           1 :       else if (unformat (input, "zero"))
    2777           0 :         res = sfifo_test_fifo_make_rcv_wnd_zero (vm, input);
    2778           1 :       else if (unformat (input, "segment"))
    2779           0 :         res = sfifo_test_fifo_segment (vm, input);
    2780           1 :       else if (unformat (input, "all"))
    2781             :         {
    2782           1 :           if ((res = sfifo_test_fifo1 (vm, input)))
    2783           0 :             goto done;
    2784             : 
    2785           1 :           if ((res = sfifo_test_fifo2 (vm)))
    2786           0 :             goto done;
    2787             : 
    2788             :           /*
    2789             :            * Run a number of fifo3 configs
    2790             :            */
    2791           1 :           str = "nsegs 10 overlap seed 123";
    2792           1 :           unformat_init_cstring (input, str);
    2793           1 :           if ((res = sfifo_test_fifo3 (vm, input)))
    2794           0 :             goto done;
    2795           1 :           unformat_free (input);
    2796             : 
    2797           1 :           str = "nsegs 10 overlap seed 123 in-seq-all";
    2798           1 :           unformat_init_cstring (input, str);
    2799           1 :           if ((res = sfifo_test_fifo3 (vm, input)))
    2800           0 :             goto done;
    2801           1 :           unformat_free (input);
    2802             : 
    2803           1 :           str = "nsegs 10 overlap seed 123 initial-offset 3917";
    2804           1 :           unformat_init_cstring (input, str);
    2805           1 :           if ((res = sfifo_test_fifo3 (vm, input)))
    2806           0 :             goto done;
    2807           1 :           unformat_free (input);
    2808             : 
    2809           1 :           str = "nsegs 10 overlap seed 123 initial-offset 3917 drop";
    2810           1 :           unformat_init_cstring (input, str);
    2811           1 :           if ((res = sfifo_test_fifo3 (vm, input)))
    2812           0 :             goto done;
    2813           1 :           unformat_free (input);
    2814             : 
    2815           1 :           str = "nsegs 10 seed 123 initial-offset 3917 drop no-randomize";
    2816           1 :           unformat_init_cstring (input, str);
    2817           1 :           if ((res = sfifo_test_fifo3 (vm, input)))
    2818           0 :             goto done;
    2819           1 :           unformat_free (input);
    2820             : 
    2821           1 :           if ((res = sfifo_test_fifo4 (vm, input)))
    2822           0 :             goto done;
    2823             : 
    2824           1 :           if ((res = sfifo_test_fifo5 (vm, input)))
    2825           0 :             goto done;
    2826             : 
    2827           1 :           if ((res = sfifo_test_fifo6 (vm, input)))
    2828           0 :             goto done;
    2829             : 
    2830           1 :           if ((res = sfifo_test_fifo7 (vm, input)))
    2831           0 :             goto done;
    2832             : 
    2833           1 :           if ((res = sfifo_test_fifo_grow (vm, input)))
    2834           0 :             goto done;
    2835             : 
    2836           1 :           if ((res = sfifo_test_fifo_shrink (vm, input)))
    2837           0 :             goto done;
    2838             : 
    2839           1 :           if ((res = sfifo_test_fifo_indirect (vm, input)))
    2840           0 :             goto done;
    2841             : 
    2842           1 :           if ((res = sfifo_test_fifo_make_rcv_wnd_zero (vm, input)))
    2843           0 :             goto done;
    2844             : 
    2845           1 :           str = "all";
    2846           1 :           unformat_init_cstring (input, str);
    2847           1 :           if ((res = sfifo_test_fifo_segment (vm, input)))
    2848           0 :             goto done;
    2849             :         }
    2850             :       else
    2851             :         {
    2852           0 :           vlib_cli_output (vm, "unknown input `%U'", format_unformat_error,
    2853             :                            input);
    2854           0 :           res = -1;
    2855           0 :           goto done;
    2856             :         }
    2857             : 
    2858             :     }
    2859             : 
    2860           1 : done:
    2861           1 :   if (res)
    2862           0 :     return clib_error_return (0, "svm fifo unit test failed");
    2863           1 :   return 0;
    2864             : }
    2865             : 
    2866             : /* *INDENT-OFF* */
    2867       16239 : VLIB_CLI_COMMAND (svm_fifo_test_command, static) =
    2868             : {
    2869             :   .path = "test svm fifo",
    2870             :   .short_help = "internal svm fifo unit tests",
    2871             :   .function = svm_fifo_test,
    2872             : };
    2873             : /* *INDENT-ON* */
    2874             : 
    2875             : /*
    2876             :  * fd.io coding-style-patch-verification: ON
    2877             :  *
    2878             :  * Local Variables:
    2879             :  * eval: (c-set-style "gnu")
    2880             :  * End:
    2881             :  */

Generated by: LCOV version 1.14