LCOV - code coverage report
Current view: top level - vpp/api - api.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 65 132 49.2 %
Date: 2023-07-05 22:20:52 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        1207 : memclnt_delete_callback (u32 client_index)
      84             : {
      85        1207 :   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        1207 :   foreach_registration_hash;
      97             : #undef _
      98        1207 :   return 0;
      99             : }
     100             : 
     101         559 : 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         267 : 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         267 :   int class_len =
     147         267 :     clib_min (vec_len (msg_class) + 1, ARRAY_LEN (rmp->msg_class));
     148         267 :   int message_len =
     149         267 :     clib_min (vec_len (message) + 1, ARRAY_LEN (rmp->message));
     150         267 :   msg_size = sizeof (*rmp) + class_len + message_len;
     151             : 
     152         267 :   rmp = vl_msg_api_alloc (msg_size);
     153         267 :   clib_memset (rmp, 0, msg_size);
     154         267 :   rmp->_vl_msg_id = ntohs (VL_API_LOG_DETAILS + msg_id_base);
     155             : 
     156         267 :   rmp->context = context;
     157         267 :   rmp->timestamp = clib_host_to_net_f64 (timestamp);
     158         267 :   rmp->level = htonl (*level);
     159             : 
     160         267 :   memcpy (rmp->msg_class, msg_class, class_len - 1);
     161         267 :   memcpy (rmp->message, message, message_len - 1);
     162             :   /* enforced by memset() above */
     163         267 :   ASSERT (0 == rmp->msg_class[class_len - 1]);
     164         267 :   ASSERT (0 == rmp->message[message_len - 1]);
     165             : 
     166         267 :   vl_api_send_msg (reg, (u8 *) rmp);
     167         267 : }
     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         404 :   while (count--)
     191             :     {
     192         401 :       e = vec_elt_at_index (lm->entries, i);
     193         401 :       if (start_time <= e->timestamp + time_offset)
     194         267 :         show_log_details (reg, mp->context, e->timestamp + time_offset,
     195         267 :                           (vl_api_log_level_t *) & e->level,
     196             :                           format (0, "%U", format_vlib_log_class, e->class),
     197             :                           e->string);
     198         401 :       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         559 : vpe_api_hookup (vlib_main_t * vm)
     243             : {
     244             :   /*
     245             :    * Set up the (msg_name, crc, message-id) table
     246             :    */
     247         559 :   msg_id_base = setup_message_id_table ();
     248             : 
     249         559 :   return 0;
     250             : }
     251             : 
     252       21839 : VLIB_API_INIT_FUNCTION (vpe_api_hookup);
     253             : 
     254             : clib_error_t *
     255         559 : vpe_api_init (vlib_main_t * vm)
     256             : {
     257         559 :   vpe_api_main_t *am = &vpe_api_main;
     258             : 
     259         559 :   am->vlib_main = vm;
     260         559 :   am->vnet_main = vnet_get_main ();
     261             : #define _(a)                                                    \
     262             :   am->a##_registration_hash = hash_create (0, sizeof (uword));
     263         559 :   foreach_registration_hash;
     264             : #undef _
     265             : 
     266         559 :   vl_set_memory_region_name ("/vpe-api");
     267         559 :   vl_mem_api_enable_disable (vm, 1 /* enable it */ );
     268             : 
     269         559 :   return 0;
     270             : }
     271             : 
     272             : static clib_error_t *
     273         559 : api_segment_config (vlib_main_t * vm, unformat_input_t * input)
     274             : {
     275             :   u8 *chroot_path;
     276             :   u64 baseva, size, pvt_heap_size;
     277             :   int uid, gid, rv;
     278         559 :   const int max_buf_size = 4096;
     279             :   char *s, *buf;
     280             :   struct passwd _pw, *pw;
     281             :   struct group _grp, *grp;
     282             :   clib_error_t *e;
     283         559 :   buf = vec_new (char, 128);
     284        1118 :   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     285             :     {
     286         559 :       if (unformat (input, "prefix %s", &chroot_path))
     287             :         {
     288         559 :           vec_add1 (chroot_path, 0);
     289         559 :           vl_set_memory_root_path ((char *) chroot_path);
     290             :         }
     291           0 :       else if (unformat (input, "uid %d", &uid))
     292           0 :         vl_set_memory_uid (uid);
     293           0 :       else if (unformat (input, "gid %d", &gid))
     294           0 :         vl_set_memory_gid (gid);
     295           0 :       else if (unformat (input, "baseva %llx", &baseva))
     296           0 :         vl_set_global_memory_baseva (baseva);
     297           0 :       else if (unformat (input, "global-size %lldM", &size))
     298           0 :         vl_set_global_memory_size (size * (1ULL << 20));
     299           0 :       else if (unformat (input, "global-size %lldG", &size))
     300           0 :         vl_set_global_memory_size (size * (1ULL << 30));
     301           0 :       else if (unformat (input, "global-size %lld", &size))
     302           0 :         vl_set_global_memory_size (size);
     303           0 :       else if (unformat (input, "global-pvt-heap-size %lldM", &pvt_heap_size))
     304           0 :         vl_set_global_pvt_heap_size (pvt_heap_size * (1ULL << 20));
     305           0 :       else if (unformat (input, "global-pvt-heap-size size %lld",
     306             :                          &pvt_heap_size))
     307           0 :         vl_set_global_pvt_heap_size (pvt_heap_size);
     308           0 :       else if (unformat (input, "api-pvt-heap-size %lldM", &pvt_heap_size))
     309           0 :         vl_set_api_pvt_heap_size (pvt_heap_size * (1ULL << 20));
     310           0 :       else if (unformat (input, "api-pvt-heap-size size %lld",
     311             :                          &pvt_heap_size))
     312           0 :         vl_set_api_pvt_heap_size (pvt_heap_size);
     313           0 :       else if (unformat (input, "api-size %lldM", &size))
     314           0 :         vl_set_api_memory_size (size * (1ULL << 20));
     315           0 :       else if (unformat (input, "api-size %lldG", &size))
     316           0 :         vl_set_api_memory_size (size * (1ULL << 30));
     317           0 :       else if (unformat (input, "api-size %lld", &size))
     318           0 :         vl_set_api_memory_size (size);
     319           0 :       else if (unformat (input, "uid %s", &s))
     320             :         {
     321             :           /* lookup the username */
     322           0 :           pw = NULL;
     323           0 :           while (((rv =
     324           0 :                    getpwnam_r (s, &_pw, buf, vec_len (buf), &pw)) == ERANGE)
     325           0 :                  && (vec_len (buf) <= max_buf_size))
     326             :             {
     327           0 :               vec_resize (buf, vec_len (buf) * 2);
     328             :             }
     329           0 :           if (rv < 0)
     330             :             {
     331           0 :               e = clib_error_return_code (0, rv,
     332             :                                           CLIB_ERROR_ERRNO_VALID |
     333             :                                           CLIB_ERROR_FATAL,
     334             :                                           "cannot fetch username %s", s);
     335           0 :               vec_free (s);
     336           0 :               vec_free (buf);
     337           0 :               return e;
     338             :             }
     339           0 :           if (pw == NULL)
     340             :             {
     341             :               e =
     342           0 :                 clib_error_return_fatal (0, "username %s does not exist", s);
     343           0 :               vec_free (s);
     344           0 :               vec_free (buf);
     345           0 :               return e;
     346             :             }
     347           0 :           vec_free (s);
     348           0 :           vl_set_memory_uid (pw->pw_uid);
     349             :         }
     350           0 :       else if (unformat (input, "gid %s", &s))
     351             :         {
     352             :           /* lookup the group name */
     353           0 :           grp = NULL;
     354           0 :           while (((rv =
     355           0 :                    getgrnam_r (s, &_grp, buf, vec_len (buf),
     356             :                                &grp)) == ERANGE)
     357           0 :                  && (vec_len (buf) <= max_buf_size))
     358             :             {
     359           0 :               vec_resize (buf, vec_len (buf) * 2);
     360             :             }
     361           0 :           if (rv != 0)
     362             :             {
     363           0 :               e = clib_error_return_code (0, rv,
     364             :                                           CLIB_ERROR_ERRNO_VALID |
     365             :                                           CLIB_ERROR_FATAL,
     366             :                                           "cannot fetch group %s", s);
     367           0 :               vec_free (s);
     368           0 :               vec_free (buf);
     369           0 :               return e;
     370             :             }
     371           0 :           if (grp == NULL)
     372             :             {
     373           0 :               e = clib_error_return_fatal (0, "group %s does not exist", s);
     374           0 :               vec_free (s);
     375           0 :               vec_free (buf);
     376           0 :               return e;
     377             :             }
     378           0 :           vec_free (s);
     379           0 :           vec_free (buf);
     380           0 :           vl_set_memory_gid (grp->gr_gid);
     381             :         }
     382             :       else
     383           0 :         return clib_error_return (0, "unknown input `%U'",
     384             :                                   format_unformat_error, input);
     385             :     }
     386         559 :   return 0;
     387             : }
     388             : 
     389        7306 : VLIB_EARLY_CONFIG_FUNCTION (api_segment_config, "api-segment");
     390             : 
     391             : void *
     392           0 : get_unformat_vnet_sw_interface (void)
     393             : {
     394           0 :   return (void *) &unformat_vnet_sw_interface;
     395             : }
     396             : 
     397             : /*
     398             :  * fd.io coding-style-patch-verification: ON
     399             :  *
     400             :  * Local Variables:
     401             :  * eval: (c-set-style "gnu")
     402             :  * End:
     403             :  */

Generated by: LCOV version 1.14