LCOV - code coverage report
Current view: top level - plugins/unittest - segment_manager_test.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 226 351 64.4 %
Date: 2023-07-05 22:20:52 Functions: 7 15 46.7 %

          Line data    Source code
       1             : #include <vnet/vnet.h>
       2             : #include <vnet/plugin/plugin.h>
       3             : #include <vpp/app/version.h>
       4             : #include <vnet/session/session.h>
       5             : #include <vnet/session/segment_manager.h>
       6             : #include <vnet/session/application.h>
       7             : 
       8             : #define SEG_MGR_TEST_I(_cond, _comment, _args...)               \
       9             : ({                                                              \
      10             :   int _evald = (_cond);                                         \
      11             :   if (!(_evald)) {                                              \
      12             :     fformat(stderr, "FAIL:%d: " _comment "\n",                  \
      13             :             __LINE__, ##_args);                                 \
      14             :   } else {                                                      \
      15             :     fformat(stderr, "PASS:%d: " _comment "\n",                  \
      16             :             __LINE__, ##_args);                                 \
      17             :   }                                                             \
      18             :   _evald;                                                       \
      19             : })
      20             : 
      21             : #define SEG_MGR_TEST(_cond, _comment, _args...)                 \
      22             : {                                                               \
      23             :     if (!SEG_MGR_TEST_I(_cond, _comment, ##_args)) {            \
      24             :         return 1;                                               \
      25             :     }                                                           \
      26             : }
      27             : 
      28             : #define ST_DBG(_comment, _args...)                              \
      29             :     fformat(stderr,  _comment "\n",  ##_args);                  \
      30             : 
      31             : #define SEGMENT_MANAGER_GET_INDEX_FROM_HANDLE(x) (x >> 32)
      32             : 
      33             : /* placeholder callback functions */
      34             : static void
      35           0 : placeholder_session_reset_callback (session_t * s)
      36             : {
      37           0 :   clib_warning ("called...");
      38           0 : }
      39             : 
      40             : static int
      41           0 : placeholder_session_connected_callback (u32 app_index, u32 api_context,
      42             :                                         session_t * s, session_error_t err)
      43             : {
      44           0 :   clib_warning ("called...");
      45           0 :   return 0;
      46             : }
      47             : 
      48             : static int
      49           0 : placeholder_add_segment_callback (u32 client_index, u64 segment_handle)
      50             : {
      51           0 :   clib_warning ("called...");
      52           0 :   return 0;
      53             : }
      54             : 
      55             : static int
      56           0 : placeholder_del_segment_callback (u32 client_index, u64 segment_handle)
      57             : {
      58           0 :   clib_warning ("called...");
      59           0 :   return 0;
      60             : }
      61             : 
      62             : static void
      63           0 : placeholder_session_disconnect_callback (session_t * s)
      64             : {
      65           0 :   clib_warning ("called...");
      66           0 : }
      67             : 
      68             : static int
      69           0 : placeholder_session_accept_callback (session_t * s)
      70             : {
      71           0 :   clib_warning ("called...");
      72           0 :   return 0;
      73             : }
      74             : 
      75             : static int
      76           0 : placeholder_server_rx_callback (session_t * s)
      77             : {
      78           0 :   clib_warning ("called...");
      79           0 :   return -1;
      80             : }
      81             : 
      82             : /* *INDENT-OFF* */
      83             : static session_cb_vft_t placeholder_session_cbs = {
      84             :   .session_reset_callback = placeholder_session_reset_callback,
      85             :   .session_connected_callback = placeholder_session_connected_callback,
      86             :   .session_accept_callback = placeholder_session_accept_callback,
      87             :   .session_disconnect_callback = placeholder_session_disconnect_callback,
      88             :   .builtin_app_rx_callback = placeholder_server_rx_callback,
      89             :   .add_segment_callback = placeholder_add_segment_callback,
      90             :   .del_segment_callback = placeholder_del_segment_callback,
      91             : };
      92             : /* *INDENT-ON* */
      93             : 
      94             : static char *states_str[] = {
      95             : #define _(sym,str) str,
      96             :   foreach_segment_mem_status
      97             : #undef _
      98             : };
      99             : 
     100             : static u32 size_4KB = 4 << 10;
     101             : static u32 size_8KB = 8 << 10;
     102             : static u32 size_12KB = 12 << 10;
     103             : static u32 size_16KB = 16 << 10;
     104             : static u32 size_20KB = 20 << 10;
     105             : static u32 size_32KB = 32 << 10;
     106             : static u32 size_52KB = 52 << 10;
     107             : static u32 size_64KB = 64 << 10;
     108             : static u32 size_128KB = 128 << 10;
     109             : static u32 size_1MB = 1 << 20;
     110             : static u32 size_2MB = 2 << 20;
     111             : 
     112             : 
     113             : static int
     114           1 : segment_manager_test_pressure_1 (vlib_main_t * vm, unformat_input_t * input)
     115           1 : {
     116             :   int rv;
     117             :   segment_manager_t *sm;
     118             :   fifo_segment_t *fs0, *fs;
     119             :   svm_fifo_t *rx_fifo, *tx_fifo;
     120           1 :   uword app_seg_size = size_2MB;
     121           1 :   u32 fifo_size = size_128KB;
     122             :   u64 options[APP_OPTIONS_N_OPTIONS];
     123           1 :   u8 data[size_128KB];
     124             : 
     125           1 :   memset (&options, 0, sizeof (options));
     126             : 
     127           2 :   vnet_app_attach_args_t attach_args = {
     128             :     .api_client_index = ~0,
     129             :     .options = options,
     130             :     .namespace_id = 0,
     131             :     .session_cb_vft = &placeholder_session_cbs,
     132           1 :     .name = format (0, "segment_manager_test_pressure_1"),
     133             :   };
     134             : 
     135           1 :   attach_args.options[APP_OPTIONS_SEGMENT_SIZE] = app_seg_size;
     136           1 :   attach_args.options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
     137           1 :   attach_args.options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
     138           1 :   attach_args.options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
     139           1 :   rv = vnet_application_attach (&attach_args);
     140           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_attach %d", rv);
     141             : 
     142             :   sm =
     143           1 :     segment_manager_get (SEGMENT_MANAGER_GET_INDEX_FROM_HANDLE
     144             :                          (attach_args.segment_handle));
     145           1 :   SEG_MGR_TEST ((sm != 0), "segment_manager_get %p", sm);
     146             : 
     147             :   /* initial status : (0 / 2MB) */
     148           1 :   fs0 = segment_manager_get_segment (sm, 0);
     149           1 :   rv = fifo_segment_get_mem_status (fs0);
     150           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     151             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     152             : 
     153             : 
     154             :   /* allocate a fifo : 128KB x2 */
     155           1 :   rv = segment_manager_alloc_session_fifos (sm,
     156           1 :                                             vlib_get_thread_index (),
     157             :                                             &rx_fifo, &tx_fifo);
     158           1 :   SEG_MGR_TEST ((rv == 0), "segment_manager_alloc_session_fifos %d", rv);
     159             : 
     160           1 :   svm_fifo_set_size (rx_fifo, size_1MB);
     161           1 :   svm_fifo_set_size (tx_fifo, size_1MB);
     162             : 
     163           1 :   fs = segment_manager_get_segment (sm, rx_fifo->segment_index);
     164           1 :   SEG_MGR_TEST ((fs == fs0), "fs %p", fs);
     165             : 
     166             :   /* fill fifos (but not add chunks) */
     167           1 :   svm_fifo_enqueue (rx_fifo, fifo_size - 1, data);
     168           1 :   svm_fifo_enqueue (tx_fifo, fifo_size - 1, data);
     169             : 
     170             :   /* 256KB+ / 2048KB+ => ~12% */
     171           1 :   rv = fifo_segment_get_mem_status (fs);
     172           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     173             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     174             : 
     175             :   /* grow fifos */
     176           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     177           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     178           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     179           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     180           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     181             : 
     182             :   /* 7 chunks : ~44% */
     183           1 :   rv = fifo_segment_get_mem_status (fs);
     184           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     185             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     186             : 
     187             :   /* grow fifos */
     188           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     189           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     190           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     191             : 
     192             :   /* 10 chunks : 61% */
     193           1 :   rv = fifo_segment_get_mem_status (fs);
     194           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_LOW_PRESSURE),
     195             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     196             : 
     197             :   /* grow fifos */
     198           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     199           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     200           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     201           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     202             : 
     203             :   /* 14 chunks : 85% */
     204           1 :   rv = fifo_segment_get_mem_status (fs);
     205           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_HIGH_PRESSURE),
     206             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     207             : 
     208             : 
     209             :   /* shrink fifos */
     210           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     211           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     212           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     213           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     214             : 
     215             :   /* 10 chunks : 63% */
     216           1 :   rv = fifo_segment_get_mem_status (fs);
     217           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_LOW_PRESSURE),
     218             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     219             : 
     220             : 
     221             :   /* grow fifos */
     222           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     223           1 :   svm_fifo_enqueue (rx_fifo, fifo_size, data);
     224           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     225           1 :   svm_fifo_enqueue (tx_fifo, fifo_size, data);
     226             : 
     227             :   /* 14 chunks : 88% */
     228           1 :   rv = fifo_segment_get_mem_status (fs);
     229           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_HIGH_PRESSURE),
     230             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     231             : 
     232           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     233           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     234           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     235           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     236             : 
     237             :   /* 10 chunks : 63% */
     238           1 :   rv = fifo_segment_get_mem_status (fs);
     239           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_LOW_PRESSURE),
     240             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     241             : 
     242             :   /* shrink fifos */
     243           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     244           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     245           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     246           1 :   svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     247           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     248           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     249           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     250           1 :   svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     251             : 
     252             :   /* 2 chunks : 12% */
     253           1 :   rv = fifo_segment_get_mem_status (fs);
     254           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     255             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     256             : 
     257             : 
     258           1 :   vnet_app_detach_args_t detach_args = {
     259           1 :     .app_index = attach_args.app_index,
     260             :     .api_client_index = ~0,
     261             :   };
     262           1 :   rv = vnet_application_detach (&detach_args);
     263           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_detach %d", rv);
     264             : 
     265           1 :   return 0;
     266             : }
     267             : 
     268             : static int
     269           1 : segment_manager_test_pressure_2 (vlib_main_t * vm, unformat_input_t * input)
     270           1 : {
     271             :   int rv, i;
     272             :   segment_manager_t *sm;
     273             :   fifo_segment_t *fs0, *fs;
     274             :   svm_fifo_t *rx_fifo, *tx_fifo;
     275           1 :   uword app_seg_size = size_2MB;
     276           1 :   u32 fifo_size = size_4KB;
     277             :   u64 options[APP_OPTIONS_N_OPTIONS];
     278           1 :   u8 data[size_4KB];
     279             : 
     280           1 :   memset (&options, 0, sizeof (options));
     281             : 
     282           2 :   vnet_app_attach_args_t attach_args = {
     283             :     .api_client_index = ~0,
     284             :     .options = options,
     285             :     .namespace_id = 0,
     286             :     .session_cb_vft = &placeholder_session_cbs,
     287           1 :     .name = format (0, "segment_manager_test_pressure_2"),
     288             :   };
     289             : 
     290           1 :   attach_args.options[APP_OPTIONS_SEGMENT_SIZE] = app_seg_size;
     291           1 :   attach_args.options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
     292           1 :   attach_args.options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
     293           1 :   attach_args.options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
     294           1 :   rv = vnet_application_attach (&attach_args);
     295           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_attach %d", rv);
     296             : 
     297             :   sm =
     298           1 :     segment_manager_get (SEGMENT_MANAGER_GET_INDEX_FROM_HANDLE
     299             :                          (attach_args.segment_handle));
     300           1 :   SEG_MGR_TEST ((sm != 0), "segment_manager_get %p", sm);
     301             : 
     302             :   /* initial status : (0 / 2MB) */
     303           1 :   fs0 = segment_manager_get_segment (sm, 0);
     304           1 :   rv = fifo_segment_get_mem_status (fs0);
     305           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     306             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     307             : 
     308             : 
     309             :   /* allocate fifos : 4KB x2 */
     310           1 :   rv = segment_manager_alloc_session_fifos (sm,
     311           1 :                                             vlib_get_thread_index (),
     312             :                                             &rx_fifo, &tx_fifo);
     313           1 :   SEG_MGR_TEST ((rv == 0), "segment_manager_alloc_session_fifos %d", rv);
     314             : 
     315           1 :   svm_fifo_set_size (rx_fifo, size_1MB);
     316           1 :   svm_fifo_set_size (tx_fifo, size_1MB);
     317             : 
     318             :   /* fill fifos (but not add chunks) */
     319           1 :   svm_fifo_enqueue (rx_fifo, fifo_size - 1, data);
     320           1 :   svm_fifo_enqueue (tx_fifo, fifo_size - 1, data);
     321             : 
     322           1 :   fs = segment_manager_get_segment (sm, rx_fifo->segment_index);
     323             : 
     324             :   /* grow fifos */
     325         510 :   for (i = 0; i < 509; ++i)
     326             :     {
     327         509 :       svm_fifo_enqueue (rx_fifo, fifo_size, data);
     328         509 :       svm_fifo_enqueue (tx_fifo, fifo_size, data);
     329             :     }
     330             : 
     331             :   /* 100% of 2MB */
     332           1 :   rv = fifo_segment_get_mem_status (fs);
     333           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_HIGH_PRESSURE),
     334             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     335             : 
     336             :   /* this fifo growth is expected to fail */
     337           1 :   rv = svm_fifo_enqueue (rx_fifo, fifo_size, data);
     338           1 :   SEG_MGR_TEST ((rv == SVM_FIFO_EGROW), "svm_fifo_enqueue %d", rv);
     339             : 
     340             :   /* shrink fifos */
     341          21 :   for (i = 0; i < 20; ++i)
     342             :     {
     343          20 :       svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     344          20 :       svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     345             :     }
     346             : 
     347             :   /* 489 chunks : 96%, it is high-pressure level
     348             :    * but the reached-mem-limit record is not reset
     349             :    * so the no-memory state lasts.
     350             :    */
     351             :   /*
     352             :    rv = fifo_segment_get_mem_status (fs);
     353             :    SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_MEMORY),
     354             :                  "fifo_segment_get_mem_status %s", states_str[rv]);
     355             :   */
     356             : 
     357             :   /* shrink fifos */
     358         134 :   for (i = 0; i < 133; ++i)
     359             :     {
     360         133 :       svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     361             :     }
     362             : 
     363             :   /* 356 chunks : 70% of 2MB */
     364           1 :   rv = fifo_segment_get_mem_status (fs);
     365           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_LOW_PRESSURE),
     366             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     367             : 
     368             :   /* shrink fifos */
     369         361 :   for (i = 0; i < 360; ++i)
     370             :     {
     371         360 :       svm_fifo_dequeue_drop (rx_fifo, fifo_size);
     372         360 :       svm_fifo_dequeue_drop (tx_fifo, fifo_size);
     373             :     }
     374             : 
     375             :   /* 2 chunks : 3% of 2MB */
     376           1 :   rv = fifo_segment_get_mem_status (fs);
     377           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     378             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     379             : 
     380             : 
     381           1 :   vnet_app_detach_args_t detach_args = {
     382           1 :     .app_index = attach_args.app_index,
     383             :     .api_client_index = ~0,
     384             :   };
     385           1 :   rv = vnet_application_detach (&detach_args);
     386           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_detach %d", rv);
     387             : 
     388           1 :   return 0;
     389             : }
     390             : 
     391             : static int
     392           1 : segment_manager_test_fifo_balanced_alloc (vlib_main_t * vm,
     393             :                                           unformat_input_t * input)
     394           1 : {
     395             :   int rv, i, fs_index;
     396             :   segment_manager_t *sm;
     397             :   fifo_segment_t *fs[4];
     398             :   svm_fifo_t *rx_fifo[4], *tx_fifo[4];
     399           1 :   uword app_seg_size = size_2MB;
     400           1 :   u32 fifo_size = size_4KB;
     401             :   u64 options[APP_OPTIONS_N_OPTIONS];
     402           1 :   u8 data[size_4KB];
     403             : 
     404           1 :   memset (&options, 0, sizeof (options));
     405             : 
     406           2 :   vnet_app_attach_args_t attach_args = {
     407             :     .api_client_index = ~0,
     408             :     .options = options,
     409             :     .namespace_id = 0,
     410             :     .session_cb_vft = &placeholder_session_cbs,
     411           1 :     .name = format (0, "segment_manager_test_fifo_balanced_alloc"),
     412             :   };
     413             : 
     414           1 :   attach_args.options[APP_OPTIONS_SEGMENT_SIZE] = app_seg_size;
     415           1 :   attach_args.options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
     416           1 :   attach_args.options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
     417           1 :   attach_args.options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
     418           1 :   rv = vnet_application_attach (&attach_args);
     419           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_attach %d", rv);
     420             : 
     421             :   sm =
     422           1 :     segment_manager_get (SEGMENT_MANAGER_GET_INDEX_FROM_HANDLE
     423             :                          (attach_args.segment_handle));
     424           1 :   SEG_MGR_TEST ((sm != 0), "segment_manager_get %p", sm);
     425             : 
     426             :   /* initial status : (0 / 2MB) */
     427           1 :   fs[0] = segment_manager_get_segment (sm, 0);
     428           1 :   rv = fifo_segment_get_mem_status (fs[0]);
     429           1 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     430             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     431             : 
     432             :   /* allocate fifos : 4KB x2 */
     433           1 :   rv = segment_manager_alloc_session_fifos (sm,
     434           1 :                                             vlib_get_thread_index (),
     435             :                                             &rx_fifo[0], &tx_fifo[0]);
     436           1 :   SEG_MGR_TEST ((rv == 0), "segment_manager_alloc_session_fifos %d", rv);
     437           1 :   SEG_MGR_TEST ((rx_fifo[0]->segment_index == 0),
     438             :                 "segment_index %d", rx_fifo[0]->segment_index);
     439           1 :   SEG_MGR_TEST ((tx_fifo[0]->segment_index == 0),
     440             :                 "segment_index %d", tx_fifo[0]->segment_index);
     441             : 
     442             :   /* grow fifos */
     443           1 :   svm_fifo_set_size (rx_fifo[0], size_1MB);
     444         201 :   for (i = 0; i < 200; ++i)
     445             :     {
     446         200 :       svm_fifo_enqueue (rx_fifo[0], fifo_size, data);
     447             :     }
     448             : 
     449             :   /* add another 2MB segment */
     450           1 :   fs_index = segment_manager_add_segment (sm, size_2MB, 0);
     451           1 :   SEG_MGR_TEST ((fs_index == 1), "fs_index %d", fs_index);
     452             : 
     453             :   /* allocate fifos : 4KB x2
     454             :    * expected to be allocated on the newer segment,
     455             :    * because the usage of the first segment is high.
     456             :    */
     457           1 :   rv = segment_manager_alloc_session_fifos (sm,
     458           1 :                                             vlib_get_thread_index (),
     459             :                                             &rx_fifo[1], &tx_fifo[1]);
     460           1 :   SEG_MGR_TEST ((rv == 0), "segment_manager_alloc_session_fifos %d", rv);
     461           1 :   SEG_MGR_TEST ((rx_fifo[1]->segment_index == 1),
     462             :                 "segment_index %d", rx_fifo[1]->segment_index);
     463           1 :   SEG_MGR_TEST ((tx_fifo[1]->segment_index == 1),
     464             :                 "segment_index %d", tx_fifo[1]->segment_index);
     465             : 
     466             :   /* allocate fifos : 4KB x2
     467             :    * expected to be allocated on the newer segment.
     468             :    */
     469           1 :   rv = segment_manager_alloc_session_fifos (sm,
     470           1 :                                             vlib_get_thread_index (),
     471             :                                             &rx_fifo[2], &tx_fifo[2]);
     472           1 :   SEG_MGR_TEST ((rv == 0), "segment_manager_alloc_session_fifos %d", rv);
     473           1 :   SEG_MGR_TEST ((rx_fifo[2]->segment_index == 1),
     474             :                 "segment_index %d", rx_fifo[2]->segment_index);
     475           1 :   SEG_MGR_TEST ((tx_fifo[2]->segment_index == 1),
     476             :                 "segment_index %d", tx_fifo[2]->segment_index);
     477             : 
     478             :   /* grow fifos, so the usage of the secong segment becomes
     479             :    * higher than the first one.
     480             :    */
     481           1 :   svm_fifo_set_size (rx_fifo[1], size_1MB);
     482         401 :   for (i = 0; i < 400; ++i)
     483             :     {
     484         400 :       svm_fifo_enqueue (rx_fifo[1], fifo_size, data);
     485             :     }
     486             : 
     487             :   /* allocate fifos : 4KB x2
     488             :    * expected to be allocated on the first segment.
     489             :    */
     490           1 :   rv = segment_manager_alloc_session_fifos (sm,
     491           1 :                                             vlib_get_thread_index (),
     492             :                                             &rx_fifo[3], &tx_fifo[3]);
     493           1 :   SEG_MGR_TEST ((rv == 0), "segment_manager_alloc_session_fifos %d", rv);
     494           1 :   SEG_MGR_TEST ((rx_fifo[3]->segment_index == 0),
     495             :                 "segment_index %d", rx_fifo[3]->segment_index);
     496           1 :   SEG_MGR_TEST ((tx_fifo[3]->segment_index == 0),
     497             :                 "segment_index %d", tx_fifo[3]->segment_index);
     498             : 
     499             : 
     500             : 
     501           1 :   vnet_app_detach_args_t detach_args = {
     502           1 :     .app_index = attach_args.app_index,
     503             :     .api_client_index = ~0,
     504             :   };
     505           1 :   rv = vnet_application_detach (&detach_args);
     506           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_detach %d", rv);
     507             : 
     508           1 :   return 0;
     509             : }
     510             : 
     511             : /* disabled until fifo tuning and memory pressure are properly working */
     512             : __clib_unused static int
     513           0 : segment_manager_test_fifo_ops (vlib_main_t *vm, unformat_input_t *input)
     514           0 : {
     515             :   int rv, i;
     516             :   segment_manager_t *sm;
     517             :   fifo_segment_t *fs;
     518             :   svm_fifo_t *rx_fifo, *tx_fifo;
     519           0 :   uword app_seg_size = size_2MB, most_grown = 0;
     520           0 :   u32 fifo_size = size_4KB;
     521           0 :   u32 max_dequeue = 0;
     522             :   u64 options[APP_OPTIONS_N_OPTIONS];
     523           0 :   u8 data[size_128KB];
     524             : 
     525           0 :   memset (&options, 0, sizeof (options));
     526             : 
     527           0 :   vnet_app_attach_args_t attach_args = {
     528             :     .api_client_index = ~0,
     529             :     .options = options,
     530             :     .namespace_id = 0,
     531             :     .session_cb_vft = &placeholder_session_cbs,
     532           0 :     .name = format (0, "segment_manager_test_pressure_1"),
     533             :   };
     534             : 
     535           0 :   attach_args.options[APP_OPTIONS_SEGMENT_SIZE] = app_seg_size;
     536           0 :   attach_args.options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
     537           0 :   attach_args.options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
     538           0 :   attach_args.options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
     539           0 :   rv = vnet_application_attach (&attach_args);
     540           0 :   SEG_MGR_TEST ((rv == 0), "vnet_application_attach %d", rv);
     541             : 
     542             :   sm =
     543           0 :     segment_manager_get (SEGMENT_MANAGER_GET_INDEX_FROM_HANDLE
     544             :                          (attach_args.segment_handle));
     545           0 :   SEG_MGR_TEST ((sm != 0), "segment_manager_get %p", sm);
     546             : 
     547             :   /* initial status : (0 / 2MB) */
     548           0 :   fs = segment_manager_get_segment (sm, 0);
     549           0 :   rv = fifo_segment_get_mem_status (fs);
     550           0 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     551             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     552             : 
     553             :   /* allocate fifos : 4KB x2 */
     554           0 :   rv = segment_manager_alloc_session_fifos (sm,
     555           0 :                                             vlib_get_thread_index (),
     556             :                                             &rx_fifo, &tx_fifo);
     557           0 :   SEG_MGR_TEST ((rv == 0), "segment_manager_alloc_session_fifos %d", rv);
     558             : 
     559             :   /* check the initial fifo size : 4KB */
     560           0 :   rv = svm_fifo_size (rx_fifo);
     561           0 :   SEG_MGR_TEST ((rv == size_4KB), "svm_fifo_size %d", rv);
     562             : 
     563             :   /* fill 4KB */
     564           0 :   rv = svm_fifo_enqueue (rx_fifo, size_4KB, data);
     565           0 :   SEG_MGR_TEST ((rv == size_4KB), "svm_fifo_enqueue %d", rv);
     566           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     567           0 :   SEG_MGR_TEST ((max_dequeue == size_4KB), "max_dequeue %u", max_dequeue);
     568             : 
     569             :   /* grow the fifo size : 4KB -> 8KB */
     570           0 :   svm_fifo_set_size (rx_fifo, size_8KB);
     571           0 :   rv = svm_fifo_size (rx_fifo);
     572           0 :   SEG_MGR_TEST ((rv == size_8KB), "svm_fifo_size %d", rv);
     573             : 
     574             :   /* verify that fifo cannot grow larger than the fifo size */
     575             :   /* 4KB + 8KB > 8KB, so only 4KB is queued */
     576           0 :   rv = svm_fifo_enqueue (rx_fifo, size_8KB, data);
     577           0 :   SEG_MGR_TEST ((rv == size_4KB), "svm_fifo_enqueue %d", rv);
     578           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     579           0 :   SEG_MGR_TEST ((max_dequeue == size_8KB), "max_dequeue %u", max_dequeue);
     580             : 
     581             :   /* grow the fifo size : 8KB -> 16KB */
     582           0 :   svm_fifo_set_size (rx_fifo, size_16KB);
     583             : 
     584             :   /* 8KB + 4KB = 12KB */
     585           0 :   svm_fifo_enqueue (rx_fifo, size_4KB, data);
     586           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     587           0 :   SEG_MGR_TEST ((max_dequeue == size_12KB), "max_dequeue %u", max_dequeue);
     588             : 
     589             :   /* grow the fifo size : 16KB -> 32KB */
     590           0 :   svm_fifo_set_size (rx_fifo, size_32KB);
     591             : 
     592             :   /* 12KB + 8KB = 20KB */
     593           0 :   svm_fifo_enqueue (rx_fifo, size_8KB, data);
     594           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     595           0 :   SEG_MGR_TEST ((max_dequeue == size_20KB), "max_dequeue %u", max_dequeue);
     596             : 
     597             :   /* grow the fifo size : 32KB -> 64KB */
     598           0 :   svm_fifo_set_size (rx_fifo, size_64KB);
     599             : 
     600             :   /* 20KB + 32KB = 52KB */
     601           0 :   svm_fifo_enqueue (rx_fifo, size_32KB, data);
     602           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     603           0 :   SEG_MGR_TEST ((max_dequeue == size_52KB), "max_dequeue %u", max_dequeue);
     604             : 
     605             :   /* bulk enqueue */
     606           0 :   for (i = 0; i < 55; ++i)
     607             :     {
     608           0 :       svm_fifo_set_size (rx_fifo, svm_fifo_size (rx_fifo) + size_32KB);
     609           0 :       svm_fifo_enqueue (rx_fifo, size_32KB, data);
     610             :     }
     611           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     612           0 :   SEG_MGR_TEST ((max_dequeue == (size_52KB + size_32KB * 55)),
     613             :                 "max_dequeue %u", max_dequeue);
     614           0 :   rv = fifo_segment_get_mem_status (fs);
     615           0 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_HIGH_PRESSURE),
     616             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     617           0 :   most_grown = svm_fifo_size (rx_fifo);
     618             : 
     619             :   /* dequeue */
     620           0 :   svm_fifo_dequeue_drop (rx_fifo, size_20KB);
     621           0 :   svm_fifo_dequeue_drop (rx_fifo, size_32KB);
     622             : 
     623             :   /* bulk dequeue */
     624           0 :   for (i = 0; i < 20; ++i)
     625           0 :     svm_fifo_dequeue_drop (rx_fifo, size_32KB);
     626           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     627           0 :   SEG_MGR_TEST ((max_dequeue == (size_32KB * 35)), "max_dequeue %u",
     628             :                 max_dequeue);
     629           0 :   rv = fifo_segment_get_mem_status (fs);
     630           0 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_LOW_PRESSURE),
     631             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     632             : 
     633             :   /* bulk dequeue */
     634           0 :   for (i = 0; i < 10; ++i)
     635           0 :     svm_fifo_dequeue_drop (rx_fifo, size_32KB);
     636           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     637           0 :   SEG_MGR_TEST ((max_dequeue == (size_32KB * 25)), "max_dequeue %u",
     638             :                 max_dequeue);
     639           0 :   rv = fifo_segment_get_mem_status (fs);
     640           0 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     641             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     642             : 
     643             :   /* bulk enqueue */
     644           0 :   for (i = 0; i < 30; ++i)
     645           0 :     svm_fifo_enqueue (rx_fifo, size_32KB, data);
     646           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     647           0 :   SEG_MGR_TEST ((max_dequeue == (size_32KB * 55)), "max_dequeue %u",
     648             :                 max_dequeue);
     649           0 :   rv = fifo_segment_get_mem_status (fs);
     650           0 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_HIGH_PRESSURE),
     651             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     652             : 
     653             :   /* bulk dequeue */
     654           0 :   for (i = 0; i < 20; ++i)
     655           0 :     svm_fifo_dequeue_drop (rx_fifo, size_32KB);
     656           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     657           0 :   SEG_MGR_TEST ((max_dequeue == (size_32KB * 35)), "max_dequeue %u",
     658             :                 max_dequeue);
     659           0 :   rv = fifo_segment_get_mem_status (fs);
     660           0 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_LOW_PRESSURE),
     661             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     662             : 
     663             :   /* bulk dequeue */
     664           0 :   for (i = 0; i < 35; ++i)
     665           0 :     svm_fifo_dequeue_drop (rx_fifo, size_32KB);
     666           0 :   max_dequeue = svm_fifo_max_dequeue (rx_fifo);
     667           0 :   SEG_MGR_TEST ((max_dequeue == 0), "max_dequeue %u", max_dequeue);
     668           0 :   rv = fifo_segment_get_mem_status (fs);
     669           0 :   SEG_MGR_TEST ((rv == MEMORY_PRESSURE_NO_PRESSURE),
     670             :                 "fifo_segment_get_mem_status %s", states_str[rv]);
     671             : 
     672             :   /* (virtual) fifo size is still large as it is not updated */
     673           0 :   SEG_MGR_TEST ((rx_fifo->shr->size == most_grown), "rx_fifo->size %u",
     674             :                 rx_fifo->shr->size);
     675             : 
     676           0 :   vnet_app_detach_args_t detach_args = {
     677           0 :     .app_index = attach_args.app_index,
     678             :     .api_client_index = ~0,
     679             :   };
     680           0 :   rv = vnet_application_detach (&detach_args);
     681           0 :   SEG_MGR_TEST ((rv == 0), "vnet_application_detach %d", rv);
     682             : 
     683           0 :   return 0;
     684             : }
     685             : 
     686             : static int
     687           1 : segment_manager_test_prealloc_hdrs (vlib_main_t * vm,
     688             :                                     unformat_input_t * input)
     689             : {
     690           1 :   u32 fifo_size = size_4KB, prealloc_hdrs, sm_index, fs_index;
     691             :   u64 options[APP_OPTIONS_N_OPTIONS];
     692           1 :   uword app_seg_size = size_2MB * 2;
     693             :   segment_manager_t *sm;
     694             :   fifo_segment_t *fs;
     695             :   int rv;
     696             : 
     697           1 :   memset (&options, 0, sizeof (options));
     698             : 
     699           2 :   vnet_app_attach_args_t attach_args = {
     700             :     .api_client_index = ~0,
     701             :     .options = options,
     702             :     .namespace_id = 0,
     703             :     .session_cb_vft = &placeholder_session_cbs,
     704           1 :     .name = format (0, "segment_manager_test_prealloc_hdrs"),
     705             :   };
     706             : 
     707           1 :   prealloc_hdrs = 64;
     708             : 
     709           1 :   attach_args.options[APP_OPTIONS_SEGMENT_SIZE] = app_seg_size;
     710           1 :   attach_args.options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
     711           1 :   attach_args.options[APP_OPTIONS_RX_FIFO_SIZE] = fifo_size;
     712           1 :   attach_args.options[APP_OPTIONS_TX_FIFO_SIZE] = fifo_size;
     713           1 :   attach_args.options[APP_OPTIONS_PREALLOC_FIFO_HDRS] = prealloc_hdrs;
     714             : 
     715           1 :   rv = vnet_application_attach (&attach_args);
     716           1 :   vec_free (attach_args.name);
     717             : 
     718           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_attach %d", rv);
     719             : 
     720           1 :   segment_manager_parse_segment_handle (attach_args.segment_handle, &sm_index,
     721             :                                         &fs_index);
     722           1 :   sm = segment_manager_get (sm_index);
     723             : 
     724           1 :   SEG_MGR_TEST ((sm != 0), "seg manager is valid", sm);
     725             : 
     726           1 :   fs = segment_manager_get_segment (sm, fs_index);
     727           1 :   SEG_MGR_TEST (fifo_segment_num_free_fifos (fs) == prealloc_hdrs,
     728             :                 "prealloc should be %u", prealloc_hdrs);
     729             : 
     730           1 :   vnet_app_detach_args_t detach_args = {
     731           1 :     .app_index = attach_args.app_index,
     732             :     .api_client_index = ~0,
     733             :   };
     734           1 :   rv = vnet_application_detach (&detach_args);
     735           1 :   SEG_MGR_TEST ((rv == 0), "vnet_application_detach %d", rv);
     736           1 :   return 0;
     737             : }
     738             : 
     739             : static clib_error_t *
     740           1 : segment_manager_test (vlib_main_t * vm,
     741             :                       unformat_input_t * input, vlib_cli_command_t * cmd_arg)
     742             : {
     743           1 :   int res = 0;
     744             : 
     745           1 :   vnet_session_enable_disable (vm, 1);
     746             : 
     747           2 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     748             :     {
     749           1 :       if (unformat (input, "pressure_levels_1"))
     750           0 :         res = segment_manager_test_pressure_1 (vm, input);
     751           1 :       else if (unformat (input, "pressure_levels_2"))
     752           0 :         res = segment_manager_test_pressure_2 (vm, input);
     753           1 :       else if (unformat (input, "alloc"))
     754           0 :         res = segment_manager_test_fifo_balanced_alloc (vm, input);
     755           1 :       else if (unformat (input, "prealloc_hdrs"))
     756           0 :         res = segment_manager_test_prealloc_hdrs (vm, input);
     757             : 
     758           1 :       else if (unformat (input, "all"))
     759             :         {
     760           1 :           if ((res = segment_manager_test_pressure_1 (vm, input)))
     761           0 :             goto done;
     762           1 :           if ((res = segment_manager_test_pressure_2 (vm, input)))
     763           0 :             goto done;
     764           1 :           if ((res = segment_manager_test_fifo_balanced_alloc (vm, input)))
     765           0 :             goto done;
     766           1 :           if ((res = segment_manager_test_prealloc_hdrs (vm, input)))
     767           0 :             goto done;
     768             :         }
     769             :       else
     770           0 :         break;
     771             :     }
     772             : 
     773           1 : done:
     774           1 :   if (res)
     775           0 :     return clib_error_return (0, "Segment manager unit test failed.");
     776           1 :   return 0;
     777             : }
     778             : 
     779             : /* *INDENT-OFF* */
     780       16239 : VLIB_CLI_COMMAND (tcp_test_command, static) =
     781             : {
     782             :   .path = "test segment-manager",
     783             :   .short_help = "test segment manager [pressure_levels_1]"
     784             :                 "[pressure_level_2][alloc][fifo_ops][prealloc_hdrs][all]",
     785             :   .function = segment_manager_test,
     786             : };
     787             : 
     788             : /*
     789             :  * fd.io coding-style-patch-verification: ON
     790             :  *
     791             :  * Local Variables:
     792             :  * eval: (c-set-style "gnu")
     793             :  * End:
     794             :  */

Generated by: LCOV version 1.14