LCOV - code coverage report
Current view: top level - vlibmemory - memory_client.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 208 277 75.1 %
Date: 2023-10-26 01:39:38 Functions: 19 26 73.1 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * memory_client.c - API message handling, client code.
       4             :  *
       5             :  * Copyright (c) 2010 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 <setjmp.h>
      21             : 
      22             : #include <svm/svm.h>
      23             : #include <svm/ssvm.h>
      24             : #include <vppinfra/serialize.h>
      25             : #include <vppinfra/hash.h>
      26             : #include <vlibmemory/memory_client.h>
      27             : #include <vlibapi/api_common.h>
      28             : 
      29             : /* A hack. vl_client_get_first_plugin_msg_id depends on it */
      30             : #include <vlibmemory/socket_client.h>
      31             : 
      32             : #include <vlibmemory/vl_memory_msg_enum.h>
      33             : 
      34             : #define vl_typedefs             /* define message structures */
      35             : #include <vlibmemory/vl_memory_api_h.h>
      36             : #undef vl_typedefs
      37             : 
      38             : #define vl_endianfun            /* define message structures */
      39             : #include <vlibmemory/vl_memory_api_h.h>
      40             : #undef vl_endianfun
      41             : 
      42             : #define vl_calcsizefun
      43             : #include <vlibmemory/vl_memory_api_h.h>
      44             : #undef vl_calcsizefun
      45             : 
      46             : /* instantiate all the print functions we know about */
      47             : #define vl_printfun
      48             : #include <vlibmemory/vl_memory_api_h.h>
      49             : #undef vl_printfun
      50             : 
      51             : memory_client_main_t memory_client_main;
      52             : __thread memory_client_main_t *my_memory_client_main = &memory_client_main;
      53             : 
      54             : typedef struct rx_thread_fn_arg
      55             : {
      56             :   api_main_t *am;
      57             :   memory_client_main_t *mm;
      58             : } rx_thread_fn_arg_t;
      59             : 
      60             : static void *
      61          29 : rx_thread_fn (void *arg)
      62             : {
      63          29 :   rx_thread_fn_arg_t *a = (rx_thread_fn_arg_t *) arg;
      64             :   memory_client_main_t *mm;
      65             :   svm_queue_t *q;
      66             : 
      67          29 :   vlibapi_set_main (a->am);
      68          29 :   vlibapi_set_memory_client_main (a->mm);
      69          29 :   free (a);
      70             : 
      71          29 :   mm = vlibapi_get_memory_client_main ();
      72          29 :   q = vlibapi_get_main ()->vl_input_queue;
      73             : 
      74             :   /* So we can make the rx thread terminate cleanly */
      75          29 :   if (setjmp (mm->rx_thread_jmpbuf) == 0)
      76             :     {
      77          29 :       mm->rx_thread_jmpbuf_valid = 1;
      78          29 :       clib_mem_set_thread_index ();
      79             :       while (1)
      80          29 :         vl_msg_api_queue_handler (q);
      81             :     }
      82          29 :   pthread_exit (0);
      83             : }
      84             : 
      85             : static void
      86          29 : vl_api_rx_thread_exit_t_handler (vl_api_rx_thread_exit_t * mp)
      87             : {
      88          29 :   memory_client_main_t *mm = vlibapi_get_memory_client_main ();
      89          29 :   if (mm->rx_thread_jmpbuf_valid)
      90          29 :     longjmp (mm->rx_thread_jmpbuf, 1);
      91           0 : }
      92             : 
      93             : static void
      94          58 : vl_api_name_and_crc_free (void)
      95             : {
      96          58 :   api_main_t *am = vlibapi_get_main ();
      97             :   int i;
      98          58 :   u8 **keys = 0;
      99             :   hash_pair_t *hp;
     100             : 
     101          58 :   if (!am->msg_index_by_name_and_crc)
     102          29 :     return;
     103             : 
     104             :   /* *INDENT-OFF* */
     105      169911 :   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
     106             :       ({
     107             :         vec_add1 (keys, (u8 *) hp->key);
     108             :       }));
     109             :   /* *INDENT-ON* */
     110       51127 :   for (i = 0; i < vec_len (keys); i++)
     111       51098 :     vec_free (keys[i]);
     112          29 :   vec_free (keys);
     113          29 :   hash_free (am->msg_index_by_name_and_crc);
     114             : }
     115             : 
     116             : __clib_nosanitize_addr static void
     117          29 : VL_API_VEC_UNPOISON (const void *v)
     118             : {
     119          29 :   const vec_header_t *vh = &((vec_header_t *) v)[-1];
     120          29 :   clib_mem_unpoison (vh, sizeof (*vh) + vec_len (v));
     121          29 : }
     122             : 
     123             : static void
     124          29 : vl_api_memclnt_create_reply_t_handler (vl_api_memclnt_create_reply_t * mp)
     125             : {
     126          29 :   serialize_main_t _sm, *sm = &_sm;
     127          29 :   api_main_t *am = vlibapi_get_main ();
     128             :   u8 *tblv;
     129             :   u32 nmsgs;
     130             :   int i;
     131             :   u8 *name_and_crc;
     132             :   u32 msg_index;
     133             : 
     134          29 :   am->my_client_index = mp->index;
     135          29 :   am->my_registration = (vl_api_registration_t *) (uword) mp->handle;
     136             : 
     137             :   /* Clean out any previous hash table (unlikely) */
     138          29 :   vl_api_name_and_crc_free ();
     139             : 
     140          29 :   am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
     141             : 
     142             :   /* Recreate the vnet-side API message handler table */
     143          29 :   tblv = uword_to_pointer (mp->message_table, u8 *);
     144          29 :   unserialize_open_data (sm, tblv, vec_len (tblv));
     145          29 :   unserialize_integer (sm, &nmsgs, sizeof (u32));
     146             : 
     147          29 :   VL_API_VEC_UNPOISON (tblv);
     148             : 
     149       51127 :   for (i = 0; i < nmsgs; i++)
     150             :     {
     151       51098 :       msg_index = unserialize_likely_small_unsigned_integer (sm);
     152       51098 :       unserialize_cstring (sm, (char **) &name_and_crc);
     153      102196 :       hash_set_mem (am->msg_index_by_name_and_crc, name_and_crc, msg_index);
     154             :     }
     155          29 : }
     156             : 
     157             : void vl_msg_api_send_shmem (svm_queue_t * q, u8 * elem);
     158             : int
     159          29 : vl_client_connect (const char *name, int ctx_quota, int input_queue_size)
     160             : {
     161             :   vl_api_memclnt_create_t *mp;
     162             :   vl_api_memclnt_create_reply_t *rp;
     163             :   svm_queue_t *vl_input_queue;
     164             :   vl_shmem_hdr_t *shmem_hdr;
     165          29 :   int rv = 0;
     166             :   void *oldheap;
     167          29 :   api_main_t *am = vlibapi_get_main ();
     168             : 
     169          29 :   if (am->my_registration)
     170             :     {
     171           0 :       clib_warning ("client %s already connected...", name);
     172           0 :       return -1;
     173             :     }
     174             : 
     175          29 :   if (am->vlib_rp == 0)
     176             :     {
     177           0 :       clib_warning ("am->vlib_rp NULL");
     178           0 :       return -1;
     179             :     }
     180             : 
     181          29 :   shmem_hdr = am->shmem_hdr;
     182             : 
     183          29 :   if (shmem_hdr == 0 || shmem_hdr->vl_input_queue == 0)
     184             :     {
     185           0 :       clib_warning ("shmem_hdr / input queue NULL");
     186           0 :       return -1;
     187             :     }
     188             : 
     189          29 :   clib_mem_unpoison (shmem_hdr, sizeof (*shmem_hdr));
     190          29 :   VL_MSG_API_SVM_QUEUE_UNPOISON (shmem_hdr->vl_input_queue);
     191             : 
     192          29 :   oldheap = vl_msg_push_heap ();
     193          29 :   vl_input_queue = svm_queue_alloc_and_init (input_queue_size, sizeof (uword),
     194             :                                              getpid ());
     195          29 :   vl_msg_pop_heap (oldheap);
     196             : 
     197          29 :   am->my_client_index = ~0;
     198          29 :   am->my_registration = 0;
     199          29 :   am->vl_input_queue = vl_input_queue;
     200             : 
     201          29 :   mp = vl_msg_api_alloc (sizeof (vl_api_memclnt_create_t));
     202          29 :   clib_memset (mp, 0, sizeof (*mp));
     203          29 :   mp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE);
     204          29 :   mp->ctx_quota = ctx_quota;
     205          29 :   mp->input_queue = (uword) vl_input_queue;
     206          29 :   strncpy ((char *) mp->name, name, sizeof (mp->name) - 1);
     207             : 
     208          29 :   vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
     209             : 
     210             :   while (1)
     211           0 :     {
     212             :       int qstatus;
     213             :       struct timespec ts, tsrem;
     214             :       int i;
     215             : 
     216             :       /* Wait up to 10 seconds */
     217          58 :       for (i = 0; i < 1000; i++)
     218             :         {
     219          58 :           qstatus = svm_queue_sub (vl_input_queue, (u8 *) & rp,
     220             :                                    SVM_Q_NOWAIT, 0);
     221          58 :           if (qstatus == 0)
     222          29 :             goto read_one_msg;
     223          29 :           ts.tv_sec = 0;
     224          29 :           ts.tv_nsec = 10000 * 1000;    /* 10 ms */
     225          29 :           while (nanosleep (&ts, &tsrem) < 0)
     226           0 :             ts = tsrem;
     227             :         }
     228             :       /* Timeout... */
     229           0 :       clib_warning ("memclnt_create_reply timeout");
     230           0 :       return -1;
     231             : 
     232          29 :     read_one_msg:
     233          29 :       VL_MSG_API_UNPOISON (rp);
     234          29 :       if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_CREATE_REPLY)
     235             :         {
     236           0 :           clib_warning ("unexpected reply: id %d", ntohs (rp->_vl_msg_id));
     237           0 :           continue;
     238             :         }
     239          29 :       rv = clib_net_to_host_u32 (rp->response);
     240             : 
     241          29 :       msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
     242          29 :       vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
     243          29 :       break;
     244             :     }
     245          29 :   return (rv);
     246             : }
     247             : 
     248             : static void
     249          29 : vl_api_memclnt_delete_reply_t_handler (vl_api_memclnt_delete_reply_t * mp)
     250             : {
     251             :   void *oldheap;
     252          29 :   api_main_t *am = vlibapi_get_main ();
     253             : 
     254          29 :   oldheap = vl_msg_push_heap ();
     255          29 :   svm_queue_free (am->vl_input_queue);
     256          29 :   vl_msg_pop_heap (oldheap);
     257             : 
     258          29 :   am->my_client_index = ~0;
     259          29 :   am->my_registration = 0;
     260          29 :   am->vl_input_queue = 0;
     261          29 : }
     262             : 
     263             : void
     264          29 : vl_client_send_disconnect (u8 do_cleanup)
     265             : {
     266             :   vl_api_memclnt_delete_t *mp;
     267             :   vl_shmem_hdr_t *shmem_hdr;
     268          29 :   api_main_t *am = vlibapi_get_main ();
     269             : 
     270          29 :   ASSERT (am->vlib_rp);
     271          29 :   shmem_hdr = am->shmem_hdr;
     272          29 :   ASSERT (shmem_hdr && shmem_hdr->vl_input_queue);
     273             : 
     274          29 :   mp = vl_msg_api_alloc (sizeof (vl_api_memclnt_delete_t));
     275          29 :   clib_memset (mp, 0, sizeof (*mp));
     276          29 :   mp->_vl_msg_id = ntohs (VL_API_MEMCLNT_DELETE);
     277          29 :   mp->index = am->my_client_index;
     278          29 :   mp->handle = (uword) am->my_registration;
     279          29 :   mp->do_cleanup = do_cleanup;
     280             : 
     281          29 :   vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
     282          29 : }
     283             : 
     284             : int
     285          29 : vl_client_disconnect (void)
     286             : {
     287             :   vl_api_memclnt_delete_reply_t *rp;
     288             :   svm_queue_t *vl_input_queue;
     289          29 :   api_main_t *am = vlibapi_get_main ();
     290             :   time_t begin;
     291             :   msgbuf_t *msgbuf;
     292             : 
     293          29 :   vl_input_queue = am->vl_input_queue;
     294          29 :   vl_client_send_disconnect (0 /* wait for reply */ );
     295             : 
     296             :   /*
     297             :    * Have to be careful here, in case the client is disconnecting
     298             :    * because e.g. the vlib process died, or is unresponsive.
     299             :    */
     300          29 :   begin = time (0);
     301             :   while (1)
     302       18015 :     {
     303             :       time_t now;
     304             : 
     305       18044 :       now = time (0);
     306             : 
     307       18044 :       if (now >= (begin + 2))
     308             :         {
     309           0 :           clib_warning ("peer unresponsive, give up");
     310           0 :           am->my_client_index = ~0;
     311           0 :           am->my_registration = 0;
     312           0 :           am->shmem_hdr = 0;
     313           0 :           return -1;
     314             :         }
     315       18044 :       if (svm_queue_sub (vl_input_queue, (u8 *) & rp, SVM_Q_NOWAIT, 0) < 0)
     316       18004 :         continue;
     317             : 
     318          40 :       VL_MSG_API_UNPOISON (rp);
     319             : 
     320             :       /* drain the queue */
     321          40 :       if (ntohs (rp->_vl_msg_id) != VL_API_MEMCLNT_DELETE_REPLY)
     322             :         {
     323          11 :           clib_warning ("queue drain: %d", ntohs (rp->_vl_msg_id));
     324          11 :           msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
     325          11 :           vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
     326          11 :           continue;
     327             :         }
     328          29 :       msgbuf = (msgbuf_t *) ((u8 *) rp - offsetof (msgbuf_t, data));
     329          29 :       vl_msg_api_handler ((void *) rp, ntohl (msgbuf->data_len));
     330          29 :       break;
     331             :     }
     332             : 
     333          29 :   vl_api_name_and_crc_free ();
     334          29 :   return 0;
     335             : }
     336             : 
     337             : /**
     338             :  * Stave off the binary API dead client reaper
     339             :  * Only sent to inactive clients
     340             :  */
     341             : static void
     342           0 : vl_api_memclnt_keepalive_t_handler (vl_api_memclnt_keepalive_t * mp)
     343             : {
     344             :   vl_api_memclnt_keepalive_reply_t *rmp;
     345             :   api_main_t *am;
     346             :   vl_shmem_hdr_t *shmem_hdr;
     347             : 
     348           0 :   am = vlibapi_get_main ();
     349           0 :   shmem_hdr = am->shmem_hdr;
     350             : 
     351           0 :   rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp));
     352           0 :   clib_memset (rmp, 0, sizeof (*rmp));
     353           0 :   rmp->_vl_msg_id = ntohs (VL_API_MEMCLNT_KEEPALIVE_REPLY);
     354           0 :   rmp->context = mp->context;
     355           0 :   vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & rmp);
     356           0 : }
     357             : 
     358             : #define foreach_api_msg                         \
     359             : _(RX_THREAD_EXIT, rx_thread_exit)               \
     360             : _(MEMCLNT_CREATE_REPLY, memclnt_create_reply)   \
     361             : _(MEMCLNT_DELETE_REPLY, memclnt_delete_reply)   \
     362             : _(MEMCLNT_KEEPALIVE, memclnt_keepalive)
     363             : 
     364             : void
     365          29 : vl_client_install_client_message_handlers (void)
     366             : {
     367          29 :   api_main_t *am = vlibapi_get_main ();
     368             : #define _(N, n)                                                               \
     369             :   vl_msg_api_config (&(vl_msg_api_msg_config_t){                              \
     370             :     .id = VL_API_##N,                                                         \
     371             :     .name = #n,                                                               \
     372             :     .handler = vl_api_##n##_t_handler,                                        \
     373             :     .endian = vl_api_##n##_t_endian,                                          \
     374             :     .format_fn = vl_api_##n##_t_format,                                       \
     375             :     .size = sizeof (vl_api_##n##_t),                                          \
     376             :     .traced = 0,                                                              \
     377             :     .tojson = vl_api_##n##_t_tojson,                                          \
     378             :     .fromjson = vl_api_##n##_t_fromjson,                                      \
     379             :     .calc_size = vl_api_##n##_t_calc_size,                                    \
     380             :   });                                                                         \
     381             :   am->msg_data[VL_API_##N].replay_allowed = 0;
     382          29 :   foreach_api_msg;
     383             : #undef _
     384          29 : }
     385             : 
     386             : int
     387           0 : vl_client_api_map (const char *region_name)
     388             : {
     389             :   int rv;
     390             : 
     391           0 :   if ((rv = vl_map_shmem (region_name, 0 /* is_vlib */ )) < 0)
     392           0 :     return rv;
     393             : 
     394           0 :   vl_client_install_client_message_handlers ();
     395           0 :   return 0;
     396             : }
     397             : 
     398             : void
     399          46 : vl_client_api_unmap (void)
     400             : {
     401          46 :   vl_unmap_shmem_client ();
     402          46 : }
     403             : 
     404             : u8
     405          29 : vl_mem_client_is_connected (void)
     406             : {
     407          29 :   return (my_memory_client_main->connected_to_vlib != 0);
     408             : }
     409             : 
     410             : static int
     411          29 : connect_to_vlib_internal (const char *svm_name,
     412             :                           const char *client_name,
     413             :                           int rx_queue_size, void *(*thread_fn) (void *),
     414             :                           void *thread_fn_arg, int do_map)
     415             : {
     416          29 :   int rv = 0;
     417          29 :   memory_client_main_t *mm = vlibapi_get_memory_client_main ();
     418          29 :   api_main_t *am = vlibapi_get_main ();
     419             : 
     420          29 :   if (do_map && (rv = vl_client_api_map (svm_name)))
     421             :     {
     422           0 :       clib_warning ("vl_client_api map rv %d", rv);
     423           0 :       return rv;
     424             :     }
     425             : 
     426          29 :   if (vl_client_connect (client_name, 0 /* punt quota */ ,
     427             :                          rx_queue_size /* input queue */ ) < 0)
     428             :     {
     429           0 :       vl_client_api_unmap ();
     430           0 :       return -1;
     431             :     }
     432             : 
     433             :   /* Start the rx queue thread */
     434             : 
     435          29 :   if (thread_fn)
     436             :     {
     437          29 :       if (thread_fn == rx_thread_fn)
     438             :         {
     439             :           rx_thread_fn_arg_t *arg;
     440          29 :           arg = malloc (sizeof (*arg));
     441          29 :           arg->am = vlibapi_get_main ();
     442          29 :           arg->mm = vlibapi_get_memory_client_main ();
     443          29 :           thread_fn_arg = (void *) arg;
     444             :         }
     445             : 
     446          29 :       rv = pthread_create (&mm->rx_thread_handle,
     447             :                            NULL /*attr */ , thread_fn, thread_fn_arg);
     448          29 :       if (rv)
     449             :         {
     450           0 :           clib_warning ("pthread_create returned %d", rv);
     451           0 :           am->rx_thread_handle = 0;
     452             :         }
     453             :       else
     454             :         {
     455          29 :           am->rx_thread_handle = mm->rx_thread_handle;
     456             :         }
     457             :     }
     458             : 
     459          29 :   mm->connected_to_vlib = 1;
     460          29 :   return 0;
     461             : }
     462             : 
     463             : int
     464           0 : vl_client_connect_to_vlib (const char *svm_name,
     465             :                            const char *client_name, int rx_queue_size)
     466             : {
     467           0 :   return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
     468             :                                    rx_thread_fn, 0 /* thread fn arg */ ,
     469             :                                    1 /* do map */ );
     470             : }
     471             : 
     472             : int
     473           0 : vl_client_connect_to_vlib_no_rx_pthread (const char *svm_name,
     474             :                                          const char *client_name,
     475             :                                          int rx_queue_size)
     476             : {
     477           0 :   return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
     478             :                                    0 /* no rx_thread_fn */ ,
     479             :                                    0 /* no thread fn arg */ ,
     480             :                                    1 /* do map */ );
     481             : }
     482             : 
     483             : int
     484          29 : vl_client_connect_to_vlib_no_map (const char *svm_name,
     485             :                                   const char *client_name, int rx_queue_size)
     486             : {
     487          29 :   return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
     488             :                                    rx_thread_fn, 0 /* no thread fn arg */ ,
     489             :                                    0 /* dont map */ );
     490             : }
     491             : 
     492             : int
     493           0 : vl_client_connect_to_vlib_no_rx_pthread_no_map (const char *svm_name,
     494             :                                                 const char *client_name,
     495             :                                                 int rx_queue_size)
     496             : {
     497           0 :   return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
     498             :                                    0 /* no thread_fn */ ,
     499             :                                    0 /* no thread fn arg */ ,
     500             :                                    0 /* dont map */ );
     501             : }
     502             : 
     503             : int
     504           0 : vl_client_connect_to_vlib_thread_fn (const char *svm_name,
     505             :                                      const char *client_name,
     506             :                                      int rx_queue_size,
     507             :                                      void *(*thread_fn) (void *), void *arg)
     508             : {
     509           0 :   return connect_to_vlib_internal (svm_name, client_name, rx_queue_size,
     510             :                                    thread_fn, arg, 1 /* do map */ );
     511             : }
     512             : 
     513             : void
     514          29 : vl_client_stop_rx_thread (svm_queue_t *vl_input_queue)
     515             : {
     516             :   vl_api_rx_thread_exit_t *ep;
     517          29 :   ep = vl_msg_api_alloc (sizeof (*ep));
     518          29 :   ep->_vl_msg_id = ntohs (VL_API_RX_THREAD_EXIT);
     519          29 :   vl_msg_api_send_shmem (vl_input_queue, (u8 *) &ep);
     520          29 : }
     521             : 
     522             : static void
     523          29 : disconnect_from_vlib_internal (u8 do_unmap)
     524             : {
     525          29 :   memory_client_main_t *mm = vlibapi_get_memory_client_main ();
     526          29 :   api_main_t *am = vlibapi_get_main ();
     527             :   uword junk;
     528             : 
     529          29 :   if (mm->rx_thread_jmpbuf_valid)
     530             :     {
     531          29 :       vl_client_stop_rx_thread (am->vl_input_queue);
     532          29 :       pthread_join (mm->rx_thread_handle, (void **) &junk);
     533             :     }
     534          29 :   if (mm->connected_to_vlib)
     535             :     {
     536          29 :       vl_client_disconnect ();
     537          29 :       if (do_unmap)
     538           0 :         vl_client_api_unmap ();
     539             :     }
     540          29 :   clib_memset (mm, 0, sizeof (*mm));
     541          29 : }
     542             : 
     543             : void
     544           0 : vl_client_disconnect_from_vlib (void)
     545             : {
     546           0 :   disconnect_from_vlib_internal (1);
     547           0 : }
     548             : 
     549             : void
     550          29 : vl_client_disconnect_from_vlib_no_unmap (void)
     551             : {
     552          29 :   disconnect_from_vlib_internal (0);
     553          29 : }
     554             : 
     555          29 : static void vl_api_get_first_msg_id_reply_t_handler
     556             :   (vl_api_get_first_msg_id_reply_t * mp)
     557             : {
     558          29 :   memory_client_main_t *mm = vlibapi_get_memory_client_main ();
     559          29 :   i32 retval = ntohl (mp->retval);
     560             : 
     561          29 :   mm->first_msg_id_reply = (retval >= 0) ? ntohs (mp->first_msg_id) : ~0;
     562          29 :   mm->first_msg_id_reply_ready = 1;
     563          29 : }
     564             : 
     565             : u16
     566          29 : vl_client_get_first_plugin_msg_id (const char *plugin_name)
     567             : {
     568             :   vl_api_get_first_msg_id_t *mp;
     569          29 :   api_main_t *am = vlibapi_get_main ();
     570          29 :   memory_client_main_t *mm = vlibapi_get_memory_client_main ();
     571             :   vl_api_msg_data_t *m =
     572          29 :     vl_api_get_msg_data (am, VL_API_GET_FIRST_MSG_ID_REPLY);
     573             :   f64 timeout;
     574             :   void *old_handler;
     575             :   clib_time_t clib_time;
     576          29 :   u16 rv = ~0;
     577             : 
     578          29 :   if (strlen (plugin_name) + 1 > sizeof (mp->name))
     579           0 :     return (rv);
     580             : 
     581          29 :   clib_memset (&clib_time, 0, sizeof (clib_time));
     582          29 :   clib_time_init (&clib_time);
     583             : 
     584             :   /* Push this plugin's first_msg_id_reply handler */
     585          29 :   old_handler = m->handler;
     586          29 :   m->handler = (void *) vl_api_get_first_msg_id_reply_t_handler;
     587          29 :   if (!m->calc_size_func)
     588             :     {
     589          29 :       m->calc_size_func =
     590             :         (uword (*) (void *)) vl_api_get_first_msg_id_reply_t_calc_size;
     591             :     }
     592             : 
     593             :   /* Ask the data-plane for the message-ID base of the indicated plugin */
     594          29 :   mm->first_msg_id_reply_ready = 0;
     595             : 
     596             :   /* Not using shm client */
     597          29 :   if (!am->my_registration)
     598             :     {
     599           0 :       mp = vl_socket_client_msg_alloc (sizeof (*mp));
     600           0 :       clib_memset (mp, 0, sizeof (*mp));
     601           0 :       mp->_vl_msg_id = ntohs (VL_API_GET_FIRST_MSG_ID);
     602           0 :       mp->client_index = am->my_client_index;
     603           0 :       strncpy ((char *) mp->name, plugin_name, sizeof (mp->name) - 1);
     604             : 
     605           0 :       if (vl_socket_client_write () <= 0)
     606           0 :         goto sock_err;
     607           0 :       if (vl_socket_client_read (1))
     608           0 :         goto sock_err;
     609             : 
     610           0 :       if (mm->first_msg_id_reply_ready == 1)
     611             :         {
     612           0 :           rv = mm->first_msg_id_reply;
     613           0 :           goto result;
     614             :         }
     615             : 
     616           0 :     sock_err:
     617             :       /* Restore old handler */
     618           0 :       m->handler = old_handler;
     619             : 
     620           0 :       return -1;
     621             :     }
     622             :   else
     623             :     {
     624          29 :       mp = vl_msg_api_alloc (sizeof (*mp));
     625          29 :       clib_memset (mp, 0, sizeof (*mp));
     626          29 :       mp->_vl_msg_id = ntohs (VL_API_GET_FIRST_MSG_ID);
     627          29 :       mp->client_index = am->my_client_index;
     628          29 :       strncpy ((char *) mp->name, plugin_name, sizeof (mp->name) - 1);
     629             : 
     630          29 :       vl_msg_api_send_shmem (am->shmem_hdr->vl_input_queue, (u8 *) & mp);
     631             : 
     632             :       /* Synchronously wait for the answer */
     633          29 :       timeout = clib_time_now (&clib_time) + 1.0;
     634      228397 :       while (clib_time_now (&clib_time) < timeout)
     635             :         {
     636      228397 :           if (mm->first_msg_id_reply_ready == 1)
     637             :             {
     638          29 :               rv = mm->first_msg_id_reply;
     639          29 :               goto result;
     640             :             }
     641             :         }
     642             :       /* Restore old handler */
     643           0 :       m->handler = old_handler;
     644             : 
     645           0 :       return rv;
     646             :     }
     647             : 
     648          29 : result:
     649             : 
     650             :   /* Restore the old handler */
     651          29 :   m->handler = old_handler;
     652             : 
     653          29 :   if (rv == (u16) ~ 0)
     654           0 :     clib_warning ("plugin '%s' not registered", plugin_name);
     655             : 
     656          29 :   return rv;
     657             : }
     658             : 
     659             : /*
     660             :  * fd.io coding-style-patch-verification: ON
     661             :  *
     662             :  * Local Variables:
     663             :  * eval: (c-set-style "gnu")
     664             :  * End:
     665             :  */

Generated by: LCOV version 1.14