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

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * api.c - message handler registration
       4             :  *
       5             :  * Copyright (c) 2010-2018 Cisco and/or its affiliates.
       6             :  * Licensed under the Apache License, Version 2.0 (the "License");
       7             :  * you may not use this file except in compliance with the License.
       8             :  * You may obtain a copy of the License at:
       9             :  *
      10             :  *     http://www.apache.org/licenses/LICENSE-2.0
      11             :  *
      12             :  * Unless required by applicable law or agreed to in writing, software
      13             :  * distributed under the License is distributed on an "AS IS" BASIS,
      14             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15             :  * See the License for the specific language governing permissions and
      16             :  * limitations under the License.
      17             :  *------------------------------------------------------------------
      18             :  */
      19             : 
      20             : #include <stdio.h>
      21             : #include <stdlib.h>
      22             : #include <string.h>
      23             : #include <sys/types.h>
      24             : #include <sys/mman.h>
      25             : #include <sys/stat.h>
      26             : #include <netinet/in.h>
      27             : #include <signal.h>
      28             : #include <pthread.h>
      29             : #include <unistd.h>
      30             : #include <time.h>
      31             : #include <fcntl.h>
      32             : #include <string.h>
      33             : #include <pwd.h>
      34             : #include <grp.h>
      35             : 
      36             : #include <vppinfra/clib.h>
      37             : #include <vppinfra/vec.h>
      38             : #include <vppinfra/hash.h>
      39             : #include <vppinfra/bitmap.h>
      40             : #include <vppinfra/fifo.h>
      41             : #include <vppinfra/time.h>
      42             : #include <vppinfra/heap.h>
      43             : #include <vppinfra/pool.h>
      44             : #include <vppinfra/format.h>
      45             : #include <vppinfra/error.h>
      46             : 
      47             : #include <vnet/api_errno.h>
      48             : #include <vnet/vnet.h>
      49             : 
      50             : #include <vlib/log.h>
      51             : #include <vlib/vlib.h>
      52             : #include <vlib/unix/unix.h>
      53             : #include <vlibapi/api.h>
      54             : #include <vlibmemory/api.h>
      55             : 
      56             : #undef BIHASH_TYPE
      57             : #undef __included_bihash_template_h__
      58             : 
      59             : #include <vnet/ip/format.h>
      60             : 
      61             : #include <vpp/api/types.h>
      62             : 
      63             : #include <vpp/api/vpe.api_enum.h>
      64             : #include <vpp/api/vpe.api_types.h>
      65             : 
      66             : static u16 msg_id_base;
      67             : #define REPLY_MSG_ID_BASE msg_id_base
      68             : #include <vlibapi/api_helper_macros.h>
      69             : 
      70             : #define QUOTE_(x) #x
      71             : #define QUOTE(x) QUOTE_(x)
      72             : 
      73             : typedef enum
      74             : {
      75             :   RESOLVE_IP4_ADD_DEL_ROUTE = 1,
      76             :   RESOLVE_IP6_ADD_DEL_ROUTE,
      77             : } resolve_t;
      78             : 
      79             : extern vpe_api_main_t vpe_api_main;
      80             : 
      81             : /* Clean up all registrations belonging to the indicated client */
      82             : static clib_error_t *
      83        1241 : memclnt_delete_callback (u32 client_index)
      84             : {
      85        1241 :   vpe_api_main_t *vam = &vpe_api_main;
      86             :   vpe_client_registration_t *rp;
      87             :   uword *p;
      88             : 
      89             : #define _(a)                                                    \
      90             :     p = hash_get (vam->a##_registration_hash, client_index);    \
      91             :     if (p) {                                                    \
      92             :         rp = pool_elt_at_index (vam->a##_registrations, p[0]);  \
      93             :         pool_put (vam->a##_registrations, rp);                  \
      94             :         hash_unset (vam->a##_registration_hash, client_index);  \
      95             :     }
      96        1241 :   foreach_registration_hash;
      97             : #undef _
      98        1241 :   return 0;
      99             : }
     100             : 
     101         575 : VL_MSG_API_REAPER_FUNCTION (memclnt_delete_callback);
     102             : 
     103             : static void
     104         142 : vl_api_show_version_t_handler (vl_api_show_version_t * mp)
     105             : {
     106             :   vl_api_show_version_reply_t *rmp;
     107         142 :   int rv = 0;
     108             :   char *vpe_api_get_build_directory (void);
     109             :   char *vpe_api_get_version (void);
     110             :   char *vpe_api_get_build_date (void);
     111             : 
     112             :   /* *INDENT-OFF* */
     113         142 :   REPLY_MACRO2(VL_API_SHOW_VERSION_REPLY,
     114             :   ({
     115             :     strncpy ((char *) rmp->program, "vpe", ARRAY_LEN(rmp->program)-1);
     116             :     strncpy ((char *) rmp->build_directory, vpe_api_get_build_directory(),
     117             :              ARRAY_LEN(rmp->build_directory)-1);
     118             :     strncpy ((char *) rmp->version, vpe_api_get_version(),
     119             :              ARRAY_LEN(rmp->version)-1);
     120             :     strncpy ((char *) rmp->build_date, vpe_api_get_build_date(),
     121             :              ARRAY_LEN(rmp->build_date)-1);
     122             :   }));
     123             :   /* *INDENT-ON* */
     124             : }
     125             : 
     126             : static void
     127           3 : vl_api_show_vpe_system_time_t_handler (vl_api_show_vpe_system_time_t *mp)
     128             : {
     129           3 :   int rv = 0;
     130             :   vl_api_show_vpe_system_time_reply_t *rmp;
     131             :   /* *INDENT-OFF* */
     132           3 :   REPLY_MACRO2 (
     133             :     VL_API_SHOW_VPE_SYSTEM_TIME_REPLY,
     134             :     ({ rmp->vpe_system_time = clib_host_to_net_f64 (unix_time_now ()); }));
     135             :   /* *INDENT-ON* */
     136             : }
     137             : 
     138             : static void
     139         277 : show_log_details (vl_api_registration_t * reg, u32 context,
     140             :                   f64 timestamp,
     141             :                   vl_api_log_level_t * level, u8 * msg_class, u8 * message)
     142             : {
     143             :   u32 msg_size;
     144             : 
     145             :   vl_api_log_details_t *rmp;
     146         277 :   int class_len =
     147         277 :     clib_min (vec_len (msg_class) + 1, ARRAY_LEN (rmp->msg_class));
     148         277 :   int message_len =
     149         277 :     clib_min (vec_len (message) + 1, ARRAY_LEN (rmp->message));
     150         277 :   msg_size = sizeof (*rmp) + class_len + message_len;
     151             : 
     152         277 :   rmp = vl_msg_api_alloc (msg_size);
     153         277 :   clib_memset (rmp, 0, msg_size);
     154         277 :   rmp->_vl_msg_id = ntohs (VL_API_LOG_DETAILS + msg_id_base);
     155             : 
     156         277 :   rmp->context = context;
     157         277 :   rmp->timestamp = clib_host_to_net_f64 (timestamp);
     158         277 :   rmp->level = htonl (*level);
     159             : 
     160         277 :   memcpy (rmp->msg_class, msg_class, class_len - 1);
     161         277 :   memcpy (rmp->message, message, message_len - 1);
     162             :   /* enforced by memset() above */
     163         277 :   ASSERT (0 == rmp->msg_class[class_len - 1]);
     164         277 :   ASSERT (0 == rmp->message[message_len - 1]);
     165             : 
     166         277 :   vl_api_send_msg (reg, (u8 *) rmp);
     167         277 : }
     168             : 
     169             : static void
     170           3 : vl_api_log_dump_t_handler (vl_api_log_dump_t * mp)
     171             : {
     172             : 
     173             :   /* from log.c */
     174           3 :   vlib_log_main_t *lm = &log_main;
     175             :   vlib_log_entry_t *e;
     176           3 :   int i = last_log_entry ();
     177           3 :   int count = lm->count;
     178             :   f64 time_offset, start_time;
     179             :   vl_api_registration_t *reg;
     180             : 
     181           3 :   reg = vl_api_client_index_to_registration (mp->client_index);
     182           3 :   if (reg == 0)
     183           0 :     return;
     184             : 
     185           3 :   start_time = clib_net_to_host_f64 (mp->start_timestamp);
     186             : 
     187           3 :   time_offset = (f64) lm->time_zero_timeval.tv_sec
     188           3 :     + (((f64) lm->time_zero_timeval.tv_usec) * 1e-6) - lm->time_zero;
     189             : 
     190         419 :   while (count--)
     191             :     {
     192         416 :       e = vec_elt_at_index (lm->entries, i);
     193         416 :       if (start_time <= e->timestamp + time_offset)
     194         277 :         show_log_details (reg, mp->context, e->timestamp + time_offset,
     195         277 :                           (vl_api_log_level_t *) & e->level,
     196             :                           format (0, "%U", format_vlib_log_class, e->class),
     197             :                           e->string);
     198         416 :       i = (i + 1) % lm->size;
     199             :     }
     200             : 
     201             : }
     202             : 
     203             : #define BOUNCE_HANDLER(nn)                                              \
     204             : static void vl_api_##nn##_t_handler (                                   \
     205             :     vl_api_##nn##_t *mp)                                                \
     206             : {                                                                       \
     207             :     vpe_client_registration_t *reg;                                     \
     208             :     vpe_api_main_t * vam = &vpe_api_main;                               \
     209             :     svm_queue_t * q;                                     \
     210             :                                                                         \
     211             :     /* One registration only... */                                      \
     212             :     pool_foreach (reg, vam->nn##_registrations)                          \
     213             :     ({                                                                  \
     214             :         q = vl_api_client_index_to_input_queue (reg->client_index);     \
     215             :         if (q) {                                                        \
     216             :             /*                                                          \
     217             :              * If the queue is stuffed, turf the msg and complain       \
     218             :              * It's unlikely that the intended recipient is             \
     219             :              * alive; avoid deadlock at all costs.                      \
     220             :              */                                                         \
     221             :             if (q->cursize == q->maxsize) {                             \
     222             :                 clib_warning ("ERROR: receiver queue full, drop msg");  \
     223             :                 vl_msg_api_free (mp);                                   \
     224             :                 return;                                                 \
     225             :             }                                                           \
     226             :             vl_msg_api_send_shmem (q, (u8 *)&mp);                       \
     227             :             return;                                                     \
     228             :         }                                                               \
     229             :     }));                                                                \
     230             :     vl_msg_api_free (mp);                                               \
     231             : }
     232             : 
     233             : /*
     234             :  * vpe_api_hookup
     235             :  * Add vpe's API message handlers to the table.
     236             :  * vlib has already mapped shared memory and
     237             :  * added the client registration handlers.
     238             :  * See .../open-repo/vlib/memclnt_vlib.c:memclnt_process()
     239             :  */
     240             : #include <vpp/api/vpe.api.c>
     241             : static clib_error_t *
     242         575 : vpe_api_hookup (vlib_main_t * vm)
     243             : {
     244         575 :   api_main_t *am = vlibapi_get_main ();
     245             : 
     246             :   /*
     247             :    * Set up the (msg_name, crc, message-id) table
     248             :    */
     249         575 :   msg_id_base = setup_message_id_table ();
     250             : 
     251             :   /* Mark messages as mp safe */
     252         575 :   vl_api_set_msg_thread_safe (am, msg_id_base + VL_API_SHOW_VERSION, 1);
     253         575 :   vl_api_set_msg_thread_safe (am, msg_id_base + VL_API_SHOW_VPE_SYSTEM_TIME,
     254             :                               1);
     255             : 
     256         575 :   return 0;
     257             : }
     258             : 
     259       22463 : VLIB_API_INIT_FUNCTION (vpe_api_hookup);
     260             : 
     261             : clib_error_t *
     262         575 : vpe_api_init (vlib_main_t * vm)
     263             : {
     264         575 :   vpe_api_main_t *am = &vpe_api_main;
     265             : 
     266         575 :   am->vlib_main = vm;
     267         575 :   am->vnet_main = vnet_get_main ();
     268             : #define _(a)                                                    \
     269             :   am->a##_registration_hash = hash_create (0, sizeof (uword));
     270         575 :   foreach_registration_hash;
     271             : #undef _
     272             : 
     273         575 :   vl_set_memory_region_name ("/vpe-api");
     274         575 :   vl_mem_api_enable_disable (vm, 1 /* enable it */ );
     275             : 
     276         575 :   return 0;
     277             : }
     278             : 
     279             : static clib_error_t *
     280         575 : api_segment_config (vlib_main_t * vm, unformat_input_t * input)
     281             : {
     282             :   u8 *chroot_path;
     283             :   u64 baseva, size, pvt_heap_size;
     284             :   int uid, gid, rv;
     285         575 :   const int max_buf_size = 4096;
     286             :   char *s, *buf;
     287             :   struct passwd _pw, *pw;
     288             :   struct group _grp, *grp;
     289             :   clib_error_t *e;
     290         575 :   buf = vec_new (char, 128);
     291        1150 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     292             :     {
     293         575 :       if (unformat (input, "prefix %s", &chroot_path))
     294             :         {
     295         575 :           vec_add1 (chroot_path, 0);
     296         575 :           vl_set_memory_root_path ((char *) chroot_path);
     297             :         }
     298           0 :       else if (unformat (input, "uid %d", &uid))
     299           0 :         vl_set_memory_uid (uid);
     300           0 :       else if (unformat (input, "gid %d", &gid))
     301           0 :         vl_set_memory_gid (gid);
     302           0 :       else if (unformat (input, "baseva %llx", &baseva))
     303           0 :         vl_set_global_memory_baseva (baseva);
     304           0 :       else if (unformat (input, "global-size %lldM", &size))
     305           0 :         vl_set_global_memory_size (size * (1ULL << 20));
     306           0 :       else if (unformat (input, "global-size %lldG", &size))
     307           0 :         vl_set_global_memory_size (size * (1ULL << 30));
     308           0 :       else if (unformat (input, "global-size %lld", &size))
     309           0 :         vl_set_global_memory_size (size);
     310           0 :       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
     311           0 :         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
     312           0 :       else if (unformat (input, "global-pvt-heap-size size %lld",
     313             :                          &pvt_heap_size))
     314           0 :         vl_set_global_pvt_heap_size (pvt_heap_size);
     315           0 :       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
     316           0 :         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
     317           0 :       else if (unformat (input, "api-pvt-heap-size size %lld",
     318             :                          &pvt_heap_size))
     319           0 :         vl_set_api_pvt_heap_size (pvt_heap_size);
     320           0 :       else if (unformat (input, "api-size %lldM", &size))
     321           0 :         vl_set_api_memory_size (size * (1ULL << 20));
     322           0 :       else if (unformat (input, "api-size %lldG", &size))
     323           0 :         vl_set_api_memory_size (size * (1ULL << 30));
     324           0 :       else if (unformat (input, "api-size %lld", &size))
     325           0 :         vl_set_api_memory_size (size);
     326           0 :       else if (unformat (input, "uid %s", &s))
     327             :         {
     328             :           /* lookup the username */
     329           0 :           pw = NULL;
     330           0 :           while (((rv =
     331           0 :                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
     332           0 :                  && (vec_len (buf) <= max_buf_size))
     333             :             {
     334           0 :               vec_resize (buf, vec_len (buf) * 2);
     335             :             }
     336           0 :           if (rv < 0)
     337             :             {
     338           0 :               e = clib_error_return_code (0, rv,
     339             :                                           CLIB_ERROR_ERRNO_VALID |
     340             :                                           CLIB_ERROR_FATAL,
     341             :                                           "cannot fetch username %s", s);
     342           0 :               vec_free (s);
     343           0 :               vec_free (buf);
     344           0 :               return e;
     345             :             }
     346           0 :           if (pw == NULL)
     347             :             {
     348             :               e =
     349           0 :                 clib_error_return_fatal (0, "username %s does not exist", s);
     350           0 :               vec_free (s);
     351           0 :               vec_free (buf);
     352           0 :               return e;
     353             :             }
     354           0 :           vec_free (s);
     355           0 :           vl_set_memory_uid (pw->pw_uid);
     356             :         }
     357           0 :       else if (unformat (input, "gid %s", &s))
     358             :         {
     359             :           /* lookup the group name */
     360           0 :           grp = NULL;
     361           0 :           while (((rv =
     362           0 :                    getgrnam_r (s, &_grp, buf, vec_len (buf),
     363             :                                &grp)) == ERANGE)
     364           0 :                  && (vec_len (buf) <= max_buf_size))
     365             :             {
     366           0 :               vec_resize (buf, vec_len (buf) * 2);
     367             :             }
     368           0 :           if (rv != 0)
     369             :             {
     370           0 :               e = clib_error_return_code (0, rv,
     371             :                                           CLIB_ERROR_ERRNO_VALID |
     372             :                                           CLIB_ERROR_FATAL,
     373             :                                           "cannot fetch group %s", s);
     374           0 :               vec_free (s);
     375           0 :               vec_free (buf);
     376           0 :               return e;
     377             :             }
     378           0 :           if (grp == NULL)
     379             :             {
     380           0 :               e = clib_error_return_fatal (0, "group %s does not exist", s);
     381           0 :               vec_free (s);
     382           0 :               vec_free (buf);
     383           0 :               return e;
     384             :             }
     385           0 :           vec_free (s);
     386           0 :           vec_free (buf);
     387           0 :           vl_set_memory_gid (grp->gr_gid);
     388             :         }
     389             :       else
     390           0 :         return clib_error_return (0, "unknown input `%U'",
     391             :                                   format_unformat_error, input);
     392             :     }
     393         575 :   return 0;
     394             : }
     395             : 
     396        7514 : VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
     397             : 
     398             : void *
     399           0 : get_unformat_vnet_sw_interface (void)
     400             : {
     401           0 :   return (void *) &unformat_vnet_sw_interface;
     402             : }
     403             : 
     404             : /*
     405             :  * fd.io coding-style-patch-verification: ON
     406             :  *
     407             :  * Local Variables:
     408             :  * eval: (c-set-style "gnu")
     409             :  * End:
     410             :  */

Generated by: LCOV version 1.14