LCOV - code coverage report
Current view: top level - vpp/api - api_main.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 115 147 78.2 %
Date: 2023-10-26 01:39:38 Functions: 13 14 92.9 %

          Line data    Source code
       1             : #include "vat.h"
       2             : #include <dlfcn.h>
       3             : #include <vat/plugin.h>
       4             : 
       5             : vat_main_t vat_main;
       6             : 
       7             : void __clib_no_tail_calls
       8      785365 : vat_suspend (vlib_main_t *vm, f64 interval)
       9             : {
      10      785365 :   vlib_process_suspend (vm, interval);
      11      785365 : }
      12             : 
      13             : static u8 *
      14          16 : format_api_error (u8 * s, va_list * args)
      15             : {
      16          16 :   vat_main_t *vam = va_arg (*args, vat_main_t *);
      17          16 :   i32 error = va_arg (*args, u32);
      18             :   uword *p;
      19             : 
      20          16 :   p = hash_get (vam->error_string_by_error_number, -error);
      21             : 
      22          16 :   if (p)
      23          16 :     s = format (s, "%s", p[0]);
      24             :   else
      25           0 :     s = format (s, "%d", error);
      26          16 :   return s;
      27             : }
      28             : 
      29             : 
      30             : static void
      31         575 : init_error_string_table (vat_main_t * vam)
      32             : {
      33             : 
      34         575 :   vam->error_string_by_error_number = hash_create (0, sizeof (uword));
      35             : 
      36             : #define _(n,v,s) hash_set (vam->error_string_by_error_number, -v, s);
      37         575 :   foreach_vnet_api_error;
      38             : #undef _
      39             : 
      40         575 :   hash_set (vam->error_string_by_error_number, 99, "Misc");
      41         575 : }
      42             : 
      43             : #if VPP_API_TEST_BUILTIN > 0
      44             : static void
      45         575 : load_features (void)
      46             : {
      47             :   vat_registered_features_t *f;
      48         575 :   vat_main_t *vam = &vat_main;
      49             :   clib_error_t *error;
      50             : 
      51         575 :   f = vam->feature_function_registrations;
      52             : 
      53         575 :   while (f)
      54             :     {
      55           0 :       error = f->function (vam);
      56           0 :       if (error)
      57             :         {
      58           0 :           clib_warning ("INIT FAILED");
      59             :         }
      60           0 :       f = f->next;
      61             :     }
      62         575 : }
      63             : 
      64             : clib_error_t *
      65         575 : vat_builtin_main_init (vlib_main_t * vm)
      66             : {
      67         575 :   vat_main_t *vam = &vat_main;
      68             :   int rv;
      69             :   int vat_plugin_init (vat_main_t * vam);
      70             : 
      71         575 :   vam->vlib_main = vm;
      72         575 :   vam->my_client_index = (u32) ~ 0;
      73             :   /* Ensure that vam->inbuf is never NULL */
      74         575 :   vec_validate (vam->inbuf, 0);
      75         575 :   vec_validate (vam->cmd_reply, 0);
      76         575 :   vec_reset_length (vam->cmd_reply);
      77         575 :   init_error_string_table (vam);
      78         575 :   rv = vat_plugin_init (vam);
      79         575 :   if (rv)
      80           0 :     clib_warning ("vat_plugin_init returned %d", rv);
      81             : 
      82         575 :   load_features ();
      83             : 
      84         575 :   return 0;
      85             : }
      86             : #endif
      87             : 
      88             : void
      89         575 : vat_plugin_hash_create (void)
      90             : {
      91         575 :   vat_main_t *vam = &vat_main;
      92             : 
      93         575 :   vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
      94         575 :   vam->function_by_name = hash_create_string (0, sizeof (uword));
      95         575 :   vam->help_by_name = hash_create_string (0, sizeof (uword));
      96         575 : }
      97             : 
      98             : static void
      99           2 : vat_register_interface_dump (vat_main_t *vam)
     100             : {
     101             :   void *handle;
     102             :   plugin_info_t *pi;
     103             : 
     104          24 :   vec_foreach (pi, vat_plugin_main.plugin_info)
     105             :     {
     106          24 :       handle = dlsym (pi->handle, "api_sw_interface_dump");
     107          24 :       if (handle)
     108             :         {
     109           2 :           vam->api_sw_interface_dump = handle;
     110           2 :           break;
     111             :         }
     112             :     }
     113             : 
     114           2 :   if (!vam->api_sw_interface_dump)
     115             :     {
     116           0 :       fformat (stderr,
     117             :                "sw_interface_dump not found in interface_test plugin!\n");
     118           0 :       exit (1);
     119             :     }
     120           2 : }
     121             : 
     122             : static void
     123          16 : maybe_register_api_client (vat_main_t * vam)
     124             : {
     125             :   vl_api_registration_t **regpp;
     126             :   vl_api_registration_t *regp;
     127             :   void *oldheap;
     128          16 :   api_main_t *am = vlibapi_get_main ();
     129             : 
     130          16 :   if (vam->my_client_index != ~0)
     131          14 :     return;
     132             : 
     133           2 :   pool_get (am->vl_clients, regpp);
     134             : 
     135           2 :   oldheap = vl_msg_push_heap ();
     136             : 
     137           2 :   *regpp = clib_mem_alloc (sizeof (vl_api_registration_t));
     138             : 
     139           2 :   regp = *regpp;
     140           2 :   clib_memset (regp, 0, sizeof (*regp));
     141           2 :   regp->registration_type = REGISTRATION_TYPE_SHMEM;
     142           2 :   regp->vl_api_registration_pool_index = regpp - am->vl_clients;
     143           2 :   regp->vlib_rp = am->vlib_rp;
     144           2 :   regp->shmem_hdr = am->shmem_hdr;
     145             : 
     146             :   /* Loopback connection */
     147           2 :   regp->vl_input_queue = am->shmem_hdr->vl_input_queue;
     148             : 
     149           2 :   regp->name = format (0, "%s", "vpp-internal");
     150           2 :   vec_add1 (regp->name, 0);
     151             : 
     152           2 :   vl_msg_pop_heap (oldheap);
     153             : 
     154           4 :   vam->my_client_index = vl_msg_api_handle_from_index_and_epoch
     155             :     (regp->vl_api_registration_pool_index,
     156           2 :      am->shmem_hdr->application_restarts);
     157             : 
     158           2 :   vam->vl_input_queue = am->shmem_hdr->vl_input_queue;
     159           2 :   vat_register_interface_dump (vam);
     160           2 :   vam->api_sw_interface_dump (vam);
     161             : }
     162             : 
     163             : static clib_error_t *
     164          16 : api_command_fn (vlib_main_t * vm,
     165             :                 unformat_input_t * input, vlib_cli_command_t * cmd)
     166             : {
     167          16 :   vat_main_t *vam = &vat_main;
     168             :   unformat_input_t _input;
     169             :   uword c;
     170             :   u8 *cmdp, *argsp, *this_cmd;
     171             :   uword *p;
     172             :   u32 arg_len;
     173             :   int rv;
     174             :   int (*fp) (vat_main_t *);
     175             : 
     176          16 :   maybe_register_api_client (vam);
     177             : 
     178             :   /* vec_validated in the init routine */
     179          16 :   vec_set_len (vam->inbuf, 0);
     180             : 
     181          16 :   vam->input = &_input;
     182             : 
     183        1068 :   while (((c = unformat_get_input (input)) != '\n') &&
     184             :          (c != UNFORMAT_END_OF_INPUT))
     185        1052 :     vec_add1 (vam->inbuf, c);
     186             : 
     187             :   /* Null-terminate the command */
     188          16 :   vec_add1 (vam->inbuf, 0);
     189             : 
     190             :   /* In case no args given */
     191          16 :   vec_add1 (vam->inbuf, 0);
     192             : 
     193             :   /* Split input into cmd + args */
     194          16 :   this_cmd = cmdp = vam->inbuf;
     195             : 
     196             :   /* Skip leading whitespace */
     197          16 :   while (cmdp < (this_cmd + vec_len (this_cmd)))
     198             :     {
     199          16 :       if (*cmdp == ' ' || *cmdp == '\t' || *cmdp == '\n')
     200             :         {
     201           0 :           cmdp++;
     202             :         }
     203             :       else
     204             :         break;
     205             :     }
     206             : 
     207          16 :   argsp = cmdp;
     208             : 
     209             :   /* Advance past the command */
     210         369 :   while (argsp < (this_cmd + vec_len (this_cmd)))
     211             :     {
     212         369 :       if (*argsp != ' ' && *argsp != '\t' && *argsp != '\n' && *argsp != 0)
     213             :         {
     214         353 :           argsp++;
     215             :         }
     216             :       else
     217             :         break;
     218             :     }
     219             :   /* NULL terminate the command */
     220          16 :   *argsp++ = 0;
     221             : 
     222             :   /* No arguments? Ensure that argsp points to a proper (empty) string */
     223          16 :   if (argsp == (this_cmd + vec_len (this_cmd) - 1))
     224           0 :     argsp[0] = 0;
     225             :   else
     226          16 :     while (argsp < (this_cmd + vec_len (this_cmd)))
     227             :       {
     228          16 :         if (*argsp == ' ' || *argsp == '\t' || *argsp == '\n')
     229             :           {
     230           0 :             argsp++;
     231             :           }
     232             :         else
     233             :           break;
     234             :       }
     235             : 
     236             :   /* Blank input line? */
     237          16 :   if (*cmdp == 0)
     238           0 :     return 0;
     239             : 
     240          16 :   p = hash_get_mem (vam->function_by_name, cmdp);
     241          16 :   if (p == 0)
     242             :     {
     243           0 :       return clib_error_return (0, "'%s': function not found\n", cmdp);
     244             :     }
     245             : 
     246          16 :   arg_len = strlen ((char *) argsp);
     247             : 
     248          16 :   unformat_init_string (vam->input, (char *) argsp, arg_len);
     249          16 :   fp = (void *) p[0];
     250             : 
     251          16 :   rv = (*fp) (vam);
     252             : 
     253          16 :   if (rv < 0)
     254             :     {
     255          16 :       unformat_free (vam->input);
     256          16 :       return clib_error_return (0,
     257             :                                 "%s error: %U\n", cmdp,
     258             :                                 format_api_error, vam, rv);
     259             : 
     260             :     }
     261           0 :   if (vam->regenerate_interface_table)
     262             :     {
     263           0 :       vam->regenerate_interface_table = 0;
     264           0 :       vam->api_sw_interface_dump (vam);
     265             :     }
     266           0 :   unformat_free (vam->input);
     267           0 :   return 0;
     268             : }
     269             : 
     270             : /* *INDENT-OFF* */
     271      285289 : VLIB_CLI_COMMAND (api_command, static) =
     272             : {
     273             :   .path = "binary-api",
     274             :   .short_help = "binary-api [help] <name> [<args>]",
     275             :   .function = api_command_fn,
     276             :   .is_mp_safe = 1,
     277             : };
     278             : /* *INDENT-ON* */
     279             : 
     280             : void
     281           0 : api_cli_output (void *notused, const char *fmt, ...)
     282             : {
     283             :   va_list va;
     284           0 :   vat_main_t *vam = &vat_main;
     285           0 :   vlib_main_t *vm = vam->vlib_main;
     286           0 :   vlib_process_t *cp = vlib_get_current_process (vm);
     287             :   u8 *s;
     288             : 
     289           0 :   va_start (va, fmt);
     290           0 :   s = va_format (0, fmt, &va);
     291           0 :   va_end (va);
     292             : 
     293             :   /* Terminate with \n if not present. */
     294           0 :   if (vec_len (s) > 0 && s[vec_len (s) - 1] != '\n')
     295           0 :     vec_add1 (s, '\n');
     296             : 
     297           0 :   if ((!cp) || (!cp->output_function))
     298           0 :     fformat (stdout, "%v", s);
     299             :   else
     300           0 :     cp->output_function (cp->output_function_arg, s, vec_len (s));
     301             : 
     302           0 :   vec_free (s);
     303           0 : }
     304             : 
     305             : u16
     306       31050 : vl_client_get_first_plugin_msg_id (const char *plugin_name)
     307             : {
     308       31050 :   api_main_t *am = vlibapi_get_main ();
     309             :   vl_api_msg_range_t *rp;
     310             :   uword *p;
     311             : 
     312       31050 :   p = hash_get_mem (am->msg_range_by_name, plugin_name);
     313       31050 :   if (p == 0)
     314        1725 :     return ~0;
     315             : 
     316       29325 :   rp = vec_elt_at_index (am->msg_ranges, p[0]);
     317             : 
     318       29325 :   return (rp->first_msg_id);
     319             : }
     320             : 
     321             : uword
     322           9 : unformat_sw_if_index (unformat_input_t * input, va_list * args)
     323             : {
     324           9 :   void *vam_unused = va_arg (*args, void *);
     325             :   (void) (vam_unused);
     326           9 :   u32 *result = va_arg (*args, u32 *);
     327           9 :   vnet_main_t *vnm = vnet_get_main ();
     328           9 :   u32 sw_if_index = ~0;
     329             : 
     330           9 :   if (unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
     331             :     {
     332           4 :       *result = sw_if_index;
     333           4 :       return 1;
     334             :     }
     335           5 :   return 0;
     336             : }
     337             : 
     338             : /*
     339             :  * fd.io coding-style-patch-verification: ON
     340             :  *
     341             :  * Local Variables:
     342             :  * eval: (c-set-style "gnu")
     343             :  * End:
     344             :  */

Generated by: LCOV version 1.14