LCOV - code coverage report
Current view: top level - vlibapi - api_shared.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 311 488 63.7 %
Date: 2023-10-26 01:39:38 Functions: 37 52 71.2 %

          Line data    Source code
       1             : /*
       2             :  *------------------------------------------------------------------
       3             :  * api_shared.c - API message handling, common code for both clients
       4             :  * and the vlib process itself.
       5             :  *
       6             :  *
       7             :  * Copyright (c) 2009 Cisco and/or its affiliates.
       8             :  * Licensed under the Apache License, Version 2.0 (the "License");
       9             :  * you may not use this file except in compliance with the License.
      10             :  * You may obtain a copy of the License at:
      11             :  *
      12             :  *     http://www.apache.org/licenses/LICENSE-2.0
      13             :  *
      14             :  * Unless required by applicable law or agreed to in writing, software
      15             :  * distributed under the License is distributed on an "AS IS" BASIS,
      16             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      17             :  * See the License for the specific language governing permissions and
      18             :  * limitations under the License.
      19             :  *------------------------------------------------------------------
      20             :  */
      21             : 
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <stddef.h>
      25             : #include <string.h>
      26             : #include <vppinfra/format.h>
      27             : #include <vppinfra/byte_order.h>
      28             : #include <vppinfra/error.h>
      29             : #include <vlib/vlib.h>
      30             : #include <vlib/unix/unix.h>
      31             : #include <vlibapi/api.h>
      32             : #include <vppinfra/elog.h>
      33             : #include <vppinfra/callback.h>
      34             : 
      35             : /* *INDENT-OFF* */
      36             : static api_main_t api_global_main = {
      37             :   .region_name = "/unset",
      38             :   .api_uid = -1,
      39             :   .api_gid = -1,
      40             : };
      41             : /* *INDENT-ON* */
      42             : 
      43             : /* Please use vlibapi_get_main() to access my_api_main */
      44             : __thread api_main_t *my_api_main = &api_global_main;
      45             : 
      46             : void
      47           0 : vl_msg_api_set_global_main (void *am_arg)
      48             : {
      49           0 :   ASSERT (am_arg);
      50           0 :   my_api_main = (api_main_t *) am_arg;
      51           0 : }
      52             : 
      53             : void
      54           1 : vl_msg_api_increment_missing_client_counter (void)
      55             : {
      56           1 :   api_main_t *am = vlibapi_get_main ();
      57           1 :   am->missing_clients++;
      58           1 : }
      59             : 
      60             : int
      61           0 : vl_msg_api_rx_trace_enabled (api_main_t * am)
      62             : {
      63           0 :   return (am->rx_trace && am->rx_trace->enabled);
      64             : }
      65             : 
      66             : int
      67           0 : vl_msg_api_tx_trace_enabled (api_main_t * am)
      68             : {
      69           0 :   return (am->tx_trace && am->tx_trace->enabled);
      70             : }
      71             : 
      72             : /*
      73             :  * vl_msg_api_trace
      74             :  */
      75             : void
      76      504964 : vl_msg_api_trace (api_main_t * am, vl_api_trace_t * tp, void *msg)
      77             : {
      78             :   u8 **this_trace;
      79             :   u8 **old_trace;
      80             :   u8 *msg_copy;
      81             :   u32 length;
      82      504964 :   u16 msg_id = clib_net_to_host_u16 (*((u16 *) msg));
      83      504964 :   vl_api_msg_data_t *m = vl_api_get_msg_data (am, msg_id);
      84      504964 :   msgbuf_t *header = (msgbuf_t *) (((u8 *) msg) - offsetof (msgbuf_t, data));
      85             : 
      86      504964 :   if (!m || !m->trace_enable)
      87        1567 :     return;
      88             : 
      89      503397 :   msg_copy = 0;
      90             : 
      91      503397 :   if (tp->nitems == 0)
      92             :     {
      93           0 :       clib_warning ("tp->nitems is 0");
      94           0 :       return;
      95             :     }
      96             : 
      97      503397 :   if (vec_len (tp->traces) < tp->nitems)
      98             :     {
      99      503397 :       vec_add1 (tp->traces, 0);
     100      503397 :       this_trace = tp->traces + vec_len (tp->traces) - 1;
     101             :     }
     102             :   else
     103             :     {
     104           0 :       tp->wrapped = 1;
     105           0 :       old_trace = tp->traces + tp->curindex++;
     106           0 :       if (tp->curindex == tp->nitems)
     107           0 :         tp->curindex = 0;
     108             :       /* Reuse the trace record, may save some memory allocator traffic */
     109           0 :       msg_copy = *old_trace;
     110           0 :       vec_reset_length (msg_copy);
     111           0 :       this_trace = old_trace;
     112             :     }
     113             : 
     114      503397 :   length = clib_net_to_host_u32 (header->data_len);
     115             : 
     116      503397 :   vec_validate (msg_copy, length - 1);
     117      503397 :   clib_memcpy_fast (msg_copy, msg, length);
     118      503397 :   *this_trace = msg_copy;
     119             : }
     120             : 
     121             : int
     122         583 : vl_msg_api_trace_onoff (api_main_t * am, vl_api_trace_which_t which,
     123             :                         int onoff)
     124             : {
     125             :   vl_api_trace_t *tp;
     126             :   int rv;
     127             : 
     128         583 :   switch (which)
     129             :     {
     130           4 :     case VL_API_TRACE_TX:
     131           4 :       tp = am->tx_trace;
     132           4 :       if (tp == 0)
     133             :         {
     134           0 :           vl_msg_api_trace_configure (am, which, 1024);
     135           0 :           tp = am->tx_trace;
     136             :         }
     137           4 :       break;
     138             : 
     139         579 :     case VL_API_TRACE_RX:
     140         579 :       tp = am->rx_trace;
     141         579 :       if (tp == 0)
     142             :         {
     143           0 :           vl_msg_api_trace_configure (am, which, 1024);
     144           0 :           tp = am->rx_trace;
     145             :         }
     146         579 :       break;
     147             : 
     148           0 :     default:
     149             :       /* duh? */
     150           0 :       return -1;
     151             :     }
     152             : 
     153             :   /* Configured? */
     154         583 :   if (tp == 0 || tp->nitems == 0)
     155           0 :     return -1;
     156             : 
     157         583 :   rv = tp->enabled;
     158         583 :   tp->enabled = onoff;
     159             : 
     160         583 :   return rv;
     161             : }
     162             : 
     163             : int
     164           2 : vl_msg_api_trace_free (api_main_t * am, vl_api_trace_which_t which)
     165             : {
     166             :   vl_api_trace_t *tp;
     167             :   int i;
     168             : 
     169           2 :   switch (which)
     170             :     {
     171           0 :     case VL_API_TRACE_TX:
     172           0 :       tp = am->tx_trace;
     173           0 :       break;
     174             : 
     175           2 :     case VL_API_TRACE_RX:
     176           2 :       tp = am->rx_trace;
     177           2 :       break;
     178             : 
     179           0 :     default:
     180             :       /* duh? */
     181           0 :       return -1;
     182             :     }
     183             : 
     184             :   /* Configured? */
     185           2 :   if (!tp || tp->nitems == 0)
     186           0 :     return -1;
     187             : 
     188           2 :   tp->curindex = 0;
     189           2 :   tp->wrapped = 0;
     190             : 
     191         123 :   for (i = 0; i < vec_len (tp->traces); i++)
     192             :     {
     193         121 :       vec_free (tp->traces[i]);
     194             :     }
     195           2 :   vec_free (tp->traces);
     196             : 
     197           2 :   return 0;
     198             : }
     199             : 
     200             : u8 *
     201        1635 : vl_api_serialize_message_table (api_main_t * am, u8 * vector)
     202             : {
     203        1635 :   serialize_main_t _sm, *sm = &_sm;
     204             :   hash_pair_t *hp;
     205        1635 :   u32 nmsg = hash_elts (am->msg_index_by_name_and_crc);
     206             : 
     207        1635 :   serialize_open_vector (sm, vector);
     208             : 
     209             :   /* serialize the count */
     210        1635 :   serialize_integer (sm, nmsg, sizeof (u32));
     211             : 
     212             :   /* *INDENT-OFF* */
     213     9579510 :   hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
     214             :   ({
     215             :     serialize_likely_small_unsigned_integer (sm, hp->value[0]);
     216             :     serialize_cstring (sm, (char *) hp->key);
     217             :   }));
     218             :   /* *INDENT-ON* */
     219             : 
     220        1635 :   return serialize_close_vector (sm);
     221             : }
     222             : 
     223             : static int
     224           3 : vl_msg_api_trace_write_one (api_main_t *am, u8 *msg, FILE *fp)
     225             : {
     226           3 :   u8 *tmpmem = 0;
     227             :   int tlen, slen;
     228             : 
     229           3 :   u32 msg_length = vec_len (msg);
     230           3 :   vec_validate (tmpmem, msg_length - 1);
     231           3 :   clib_memcpy_fast (tmpmem, msg, msg_length);
     232           3 :   u16 id = clib_net_to_host_u16 (*((u16 *) msg));
     233           3 :   vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
     234             : 
     235           3 :   if (m && m->endian_handler)
     236             :     {
     237           3 :       m->endian_handler (tmpmem);
     238             :     }
     239             : 
     240           3 :   if (m && m->tojson_handler)
     241           3 :     {
     242           3 :       cJSON *o = m->tojson_handler (tmpmem);
     243           3 :       char *s = cJSON_Print (o);
     244           3 :       slen = strlen (s);
     245           3 :       tlen = fwrite (s, 1, slen, fp);
     246           3 :       cJSON_free (s);
     247           3 :       cJSON_Delete (o);
     248           3 :       vec_free (tmpmem);
     249           3 :       if (tlen != slen)
     250             :         {
     251           0 :           fformat (stderr, "writing to file error\n");
     252           0 :           return -11;
     253             :         }
     254             :     }
     255             :   else
     256           0 :     fformat (stderr, "  [no registered tojson fn]\n");
     257             : 
     258           3 :   return 0;
     259             : }
     260             : 
     261             : #define vl_msg_fwrite(_s, _f) fwrite (_s, 1, sizeof (_s) - 1, _f)
     262             : 
     263             : typedef struct
     264             : {
     265             :   FILE *fp;
     266             :   u32 n_traces;
     267             :   u32 i;
     268             : } vl_msg_write_json_args_t;
     269             : 
     270             : static int
     271           3 : vl_msg_write_json_fn (u8 *msg, void *ctx)
     272             : {
     273           3 :   vl_msg_write_json_args_t *arg = ctx;
     274           3 :   FILE *fp = arg->fp;
     275           3 :   api_main_t *am = vlibapi_get_main ();
     276           3 :   int rc = vl_msg_api_trace_write_one (am, msg, fp);
     277           3 :   if (rc < 0)
     278           0 :     return rc;
     279             : 
     280           3 :   if (arg->i < arg->n_traces - 1)
     281           2 :     vl_msg_fwrite (",\n", fp);
     282           3 :   arg->i++;
     283           3 :   return 0;
     284             : }
     285             : 
     286             : static int
     287           1 : vl_msg_api_trace_write_json (api_main_t *am, vl_api_trace_t *tp, FILE *fp)
     288             : {
     289             :   vl_msg_write_json_args_t args;
     290           1 :   clib_memset (&args, 0, sizeof (args));
     291           1 :   args.fp = fp;
     292           1 :   args.n_traces = vec_len (tp->traces);
     293           1 :   vl_msg_fwrite ("[\n", fp);
     294             : 
     295           1 :   int rv = vl_msg_traverse_trace (tp, vl_msg_write_json_fn, &args);
     296           1 :   if (rv < 0)
     297           0 :     return rv;
     298             : 
     299           1 :   vl_msg_fwrite ("]", fp);
     300           1 :   return 0;
     301             : }
     302             : 
     303             : int
     304        1578 : vl_msg_traverse_trace (vl_api_trace_t *tp, vl_msg_traverse_trace_fn fn,
     305             :                        void *ctx)
     306             : {
     307             :   int i;
     308             :   u8 *msg;
     309        1578 :   int rv = 0;
     310             : 
     311             :   /* No-wrap case */
     312        1578 :   if (tp->wrapped == 0)
     313             :     {
     314     2017980 :       for (i = 0; i < vec_len (tp->traces); i++)
     315             :         {
     316             :           /*sa_ignore NO_NULL_CHK */
     317     2016400 :           msg = tp->traces[i];
     318     2016400 :           if (!msg)
     319           0 :             continue;
     320             : 
     321     2016400 :           rv = fn (msg, ctx);
     322     2016400 :           if (rv < 0)
     323           0 :             return rv;
     324             :         }
     325             :     }
     326             :   else
     327             :     {
     328             :       /* Wrap case: write oldest -> end of buffer */
     329           0 :       for (i = tp->curindex; i < vec_len (tp->traces); i++)
     330             :         {
     331           0 :           msg = tp->traces[i];
     332           0 :           if (!msg)
     333           0 :             continue;
     334             : 
     335           0 :           rv = fn (msg, ctx);
     336           0 :           if (rv < 0)
     337           0 :             return rv;
     338             :         }
     339             :       /* write beginning of buffer -> oldest-1 */
     340           0 :       for (i = 0; i < tp->curindex; i++)
     341             :         {
     342             :           /*sa_ignore NO_NULL_CHK */
     343           0 :           msg = tp->traces[i];
     344           0 :           if (!msg)
     345           0 :             continue;
     346             : 
     347           0 :           rv = fn (msg, ctx);
     348           0 :           if (rv < 0)
     349           0 :             return rv;
     350             :         }
     351             :     }
     352        1578 :   return 0;
     353             : }
     354             : 
     355             : static int
     356     2016400 : vl_api_msg_write_fn (u8 *msg, void *ctx)
     357             : {
     358     2016400 :   FILE *fp = ctx;
     359     2016400 :   u32 msg_length = clib_host_to_net_u32 (vec_len (msg));
     360     2016400 :   if (fwrite (&msg_length, 1, sizeof (msg_length), fp) != sizeof (msg_length))
     361             :     {
     362           0 :       return (-14);
     363             :     }
     364     2016400 :   if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
     365             :     {
     366           0 :       return (-14);
     367             :     }
     368     2016400 :   return 0;
     369             : }
     370             : 
     371             : int
     372        1578 : vl_msg_api_trace_save (api_main_t *am, vl_api_trace_which_t which, FILE *fp,
     373             :                        u8 is_json)
     374             : {
     375             :   vl_api_trace_t *tp;
     376             :   vl_api_trace_file_header_t fh;
     377             : 
     378        1578 :   switch (which)
     379             :     {
     380           0 :     case VL_API_TRACE_TX:
     381           0 :       tp = am->tx_trace;
     382           0 :       break;
     383             : 
     384        1578 :     case VL_API_TRACE_RX:
     385        1578 :       tp = am->rx_trace;
     386        1578 :       break;
     387             : 
     388           0 :     default:
     389             :       /* duh? */
     390           0 :       return -1;
     391             :     }
     392             : 
     393             :   /* Configured, data present? */
     394        1578 :   if (tp == 0 || tp->nitems == 0 || vec_len (tp->traces) == 0)
     395           0 :     return -1;
     396             : 
     397             :   /* "Dare to be stupid" check */
     398        1578 :   if (fp == 0)
     399             :     {
     400           0 :       return -2;
     401             :     }
     402             : 
     403        1578 :   if (is_json)
     404           1 :     return vl_msg_api_trace_write_json (am, tp, fp);
     405             : 
     406             :   /* Write the file header */
     407        1577 :   fh.wrapped = tp->wrapped;
     408        1577 :   fh.nitems = clib_host_to_net_u32 (vec_len (tp->traces));
     409             : 
     410        1577 :   u8 *m = vl_api_serialize_message_table (am, 0);
     411        1577 :   fh.msgtbl_size = clib_host_to_net_u32 (vec_len (m));
     412             : 
     413        1577 :   if (fwrite (&fh, sizeof (fh), 1, fp) != 1)
     414             :     {
     415           0 :       return (-10);
     416             :     }
     417             : 
     418             :   /* Write the message table */
     419        1577 :   if (fwrite (m, vec_len (m), 1, fp) != 1)
     420             :     {
     421           0 :       return (-14);
     422             :     }
     423        1577 :   vec_free (m);
     424             : 
     425        1577 :   return vl_msg_traverse_trace (tp, vl_api_msg_write_fn, fp);
     426             : }
     427             : 
     428             : int
     429         579 : vl_msg_api_trace_configure (api_main_t * am, vl_api_trace_which_t which,
     430             :                             u32 nitems)
     431             : {
     432             :   vl_api_trace_t *tp;
     433         579 :   int was_on = 0;
     434             : 
     435         579 :   switch (which)
     436             :     {
     437           2 :     case VL_API_TRACE_TX:
     438           2 :       tp = am->tx_trace;
     439           2 :       if (tp == 0)
     440             :         {
     441           1 :           vec_validate (am->tx_trace, 0);
     442           1 :           tp = am->tx_trace;
     443             :         }
     444           2 :       break;
     445             : 
     446         577 :     case VL_API_TRACE_RX:
     447         577 :       tp = am->rx_trace;
     448         577 :       if (tp == 0)
     449             :         {
     450         575 :           vec_validate (am->rx_trace, 0);
     451         575 :           tp = am->rx_trace;
     452             :         }
     453             : 
     454         577 :       break;
     455             : 
     456           0 :     default:
     457           0 :       return -1;
     458             : 
     459             :     }
     460             : 
     461         579 :   if (tp->enabled)
     462             :     {
     463           1 :       was_on = vl_msg_api_trace_onoff (am, which, 0);
     464             :     }
     465         579 :   if (tp->traces)
     466             :     {
     467           0 :       vl_msg_api_trace_free (am, which);
     468             :     }
     469             : 
     470         579 :   clib_memset (tp, 0, sizeof (*tp));
     471             : 
     472             :   if (clib_arch_is_big_endian)
     473             :     {
     474             :       tp->endian = VL_API_BIG_ENDIAN;
     475             :     }
     476             :   else
     477             :     {
     478         579 :       tp->endian = VL_API_LITTLE_ENDIAN;
     479             :     }
     480             : 
     481         579 :   tp->nitems = nitems;
     482         579 :   if (was_on)
     483             :     {
     484           1 :       (void) vl_msg_api_trace_onoff (am, which, was_on);
     485             :     }
     486         579 :   return 0;
     487             : }
     488             : 
     489             : void
     490         245 : vl_msg_api_barrier_sync (void)
     491             : {
     492         245 : }
     493             : 
     494             : void
     495         216 : vl_msg_api_barrier_release (void)
     496             : {
     497         216 : }
     498             : 
     499             : always_inline void
     500      442105 : msg_handler_internal (api_main_t *am, void *the_msg, uword msg_len,
     501             :                       int trace_it, int do_it, int free_it)
     502             : {
     503      442105 :   u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
     504      442105 :   vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
     505             : 
     506      442105 :   if (PREDICT_FALSE (am->elog_trace_api_messages))
     507             :     {
     508             :       /* *INDENT-OFF* */
     509             :       ELOG_TYPE_DECLARE (e) =
     510             :         {
     511             :           .format = "api-msg: %s",
     512             :           .format_args = "T4",
     513             :         };
     514             :       /* *INDENT-ON* */
     515             :       struct
     516             :       {
     517             :         u32 c;
     518             :       } *ed;
     519      441726 :       ed = ELOG_DATA (am->elog_main, e);
     520      441726 :       if (m && m->name)
     521      441726 :         ed->c = elog_string (am->elog_main, (char *) m->name);
     522             :       else
     523           0 :         ed->c = elog_string (am->elog_main, "BOGUS");
     524             :     }
     525             : 
     526      442105 :   if (m && m->handler)
     527      442076 :     {
     528      442105 :       if (trace_it)
     529      441858 :         vl_msg_api_trace (am, am->rx_trace, the_msg);
     530             : 
     531      442105 :       if (am->msg_print_flag)
     532             :         {
     533           0 :           fformat (stdout, "[%d]: %s\n", id, m->name);
     534           0 :           fformat (stdout, "%U", format_vl_api_msg_text, am, id, the_msg);
     535             :         }
     536             : 
     537      442105 :       uword calc_size = 0;
     538      442105 :       ASSERT (NULL != m->calc_size_func);
     539      442105 :       if (m->calc_size_func)
     540             :         {
     541      442105 :           calc_size = m->calc_size_func (the_msg);
     542      442105 :           if (calc_size > msg_len)
     543             :             {
     544           1 :               clib_warning (
     545             :                 "Truncated message '%s' (id %u) received, calculated size "
     546             :                 "%lu is bigger than actual size %llu, message dropped.",
     547             :                 m->name, id, calc_size, msg_len);
     548             :             }
     549             :         }
     550             :       else
     551             :         {
     552           0 :           clib_warning ("Message '%s' (id %u) has NULL calc_size_func, cannot "
     553             :                         "verify message size is correct",
     554             :                         m->name, id);
     555             :         }
     556             : 
     557             :       /* don't process message if it's truncated, otherwise byte swaps
     558             :        * and stuff could corrupt memory even beyond message if it's malicious
     559             :        * e.g. VLA length field set to 1M elements, but VLA empty */
     560      442105 :       if (do_it && calc_size <= msg_len)
     561             :         {
     562             : 
     563      442104 :           if (!m->is_mp_safe)
     564             :             {
     565             :               vl_msg_api_barrier_trace_context (am->msg_names[id]);
     566      399410 :               vl_msg_api_barrier_sync ();
     567             :             }
     568             : 
     569      442104 :           if (m->is_autoendian)
     570        4208 :             m->endian_handler (the_msg);
     571             : 
     572      442104 :           if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
     573           0 :             clib_call_callbacks (am->perf_counter_cbs, am, id,
     574             :                                  0 /* before */ );
     575             : 
     576      442104 :           m->handler (the_msg);
     577             : 
     578      442075 :           if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
     579           0 :             clib_call_callbacks (am->perf_counter_cbs, am, id,
     580             :                                  1 /* after */ );
     581             : 
     582      442075 :           if (!m->is_mp_safe)
     583      399381 :             vl_msg_api_barrier_release ();
     584             :         }
     585             :     }
     586             :   else
     587             :     {
     588           0 :       clib_warning ("no handler for msg id %d", id);
     589             :     }
     590             : 
     591      442076 :   if (free_it)
     592         158 :     vl_msg_api_free (the_msg);
     593             : 
     594      442076 :   if (PREDICT_FALSE (am->elog_trace_api_messages))
     595             :     {
     596             :       /* *INDENT-OFF* */
     597             :       ELOG_TYPE_DECLARE (e) =
     598             :         {
     599             :           .format = "api-msg-done(%s): %s",
     600             :           .format_args = "t4T4",
     601             :           .n_enum_strings = 2,
     602             :           .enum_strings =
     603             :           {
     604             :             "barrier",
     605             :             "mp-safe",
     606             :           }
     607             :         };
     608             :       /* *INDENT-ON* */
     609             : 
     610             :       struct
     611             :       {
     612             :         u32 barrier;
     613             :         u32 c;
     614             :       } *ed;
     615      441725 :       ed = ELOG_DATA (am->elog_main, e);
     616      441725 :       if (m && m->name)
     617             :         {
     618      441725 :           ed->c = elog_string (am->elog_main, (char *) m->name);
     619      441725 :           ed->barrier = !m->is_mp_safe;
     620             :         }
     621             :       else
     622             :         {
     623           0 :           ed->c = elog_string (am->elog_main, "BOGUS");
     624           0 :           ed->barrier = 0;
     625             :         }
     626             :     }
     627      442076 : }
     628             : 
     629             : void
     630         187 : vl_msg_api_handler (void *the_msg, uword msg_len)
     631             : {
     632         187 :   api_main_t *am = vlibapi_get_main ();
     633             : 
     634         187 :   msg_handler_internal (am, the_msg, msg_len,
     635         187 :                         (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
     636             :                         1 /* do_it */, 1 /* free_it */);
     637         158 : }
     638             : 
     639             : void
     640           0 : vl_msg_api_handler_no_free (void *the_msg, uword msg_len)
     641             : {
     642           0 :   api_main_t *am = vlibapi_get_main ();
     643           0 :   msg_handler_internal (am, the_msg, msg_len,
     644           0 :                         (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
     645             :                         1 /* do_it */, 0 /* free_it */);
     646           0 : }
     647             : 
     648             : void
     649           0 : vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len)
     650             : {
     651           0 :   api_main_t *am = vlibapi_get_main ();
     652           0 :   msg_handler_internal (am, the_msg, msg_len, 0 /* trace_it */, 1 /* do_it */,
     653             :                         0 /* free_it */);
     654           0 : }
     655             : 
     656             : /*
     657             :  * Add a trace record to the API message trace buffer, if
     658             :  * API message tracing is enabled. Handy for adding sufficient
     659             :  * data to the trace to reproduce autonomous state, as opposed to
     660             :  * state downloaded via control-plane API messages. Example: the NAT
     661             :  * application creates database entries based on packet traffic, not
     662             :  * control-plane messages.
     663             :  *
     664             :  */
     665             : void
     666           0 : vl_msg_api_trace_only (void *the_msg, uword msg_len)
     667             : {
     668           0 :   api_main_t *am = vlibapi_get_main ();
     669             : 
     670           0 :   msg_handler_internal (am, the_msg, msg_len,
     671           0 :                         (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
     672             :                         0 /* do_it */, 0 /* free_it */);
     673           0 : }
     674             : 
     675             : void
     676           0 : vl_msg_api_cleanup_handler (void *the_msg)
     677             : {
     678           0 :   api_main_t *am = vlibapi_get_main ();
     679           0 :   u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
     680           0 :   vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
     681             : 
     682           0 :   if (PREDICT_FALSE (!m))
     683             :     {
     684           0 :       clib_warning ("_vl_msg_id too large: %d\n", id);
     685           0 :       return;
     686             :     }
     687             : 
     688           0 :   if (m->cleanup_handler)
     689           0 :     m->cleanup_handler (the_msg);
     690             : 
     691           0 :   vl_msg_api_free (the_msg);
     692             : }
     693             : 
     694             : /*
     695             :  * vl_msg_api_replay_handler
     696             :  */
     697             : void
     698           0 : vl_msg_api_replay_handler (void *the_msg)
     699             : {
     700           0 :   api_main_t *am = vlibapi_get_main ();
     701           0 :   u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
     702           0 :   vl_api_msg_data_t *m = vl_api_get_msg_data (am, id);
     703             : 
     704           0 :   if (PREDICT_FALSE (!m))
     705             :     {
     706           0 :       clib_warning ("_vl_msg_id too large: %d\n", id);
     707           0 :       return;
     708             :     }
     709             :   /* do NOT trace the message... */
     710           0 :   if (m->handler)
     711           0 :     m->handler (the_msg);
     712             :   /* do NOT free the message buffer... */
     713             : }
     714             : 
     715             : u32
     716      264312 : vl_msg_api_get_msg_length (void *msg_arg)
     717             : {
     718      264312 :   return vl_msg_api_get_msg_length_inline (msg_arg);
     719             : }
     720             : 
     721             : /*
     722             :  * vl_msg_api_socket_handler
     723             :  */
     724             : void
     725      441918 : vl_msg_api_socket_handler (void *the_msg, uword msg_len)
     726             : {
     727      441918 :   api_main_t *am = vlibapi_get_main ();
     728             : 
     729      441918 :   msg_handler_internal (am, the_msg, msg_len,
     730      441918 :                         (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
     731             :                         1 /* do_it */, 0 /* free_it */);
     732      441918 : }
     733             : 
     734             : void
     735     1261900 : vl_msg_api_config (vl_msg_api_msg_config_t * c)
     736             : {
     737     1261900 :   api_main_t *am = vlibapi_get_main ();
     738             :   vl_api_msg_data_t *m;
     739             : 
     740             :   /*
     741             :    * This happens during the java core tests if the message
     742             :    * dictionary is missing newly added xxx_reply_t messages.
     743             :    * Should never happen, but since I shot myself in the foot once
     744             :    * this way, I thought I'd make it easy to debug if I ever do
     745             :    * it again... (;-)...
     746             :    */
     747     1261900 :   if (c->id == 0)
     748             :     {
     749           0 :       if (c->name)
     750           0 :         clib_warning ("Trying to register %s with a NULL msg id!", c->name);
     751             :       else
     752           0 :         clib_warning ("Trying to register a NULL msg with a NULL msg id!");
     753           0 :       clib_warning ("Did you forget to call setup_message_id_table?");
     754           0 :       return;
     755             :     }
     756             : 
     757     1261900 :   vec_validate (am->msg_data, c->id);
     758     1261900 :   m = vl_api_get_msg_data (am, c->id);
     759             : 
     760     1261900 :   if (m->handler && m->handler != c->handler)
     761           0 :     clib_warning ("BUG: re-registering 'vl_api_%s_t_handler'."
     762             :                   "Handler was %llx, replaced by %llx",
     763             :                   c->name, m->handler, c->handler);
     764             : 
     765     1261900 :   m->name = c->name;
     766     1261900 :   m->handler = c->handler;
     767     1261900 :   m->cleanup_handler = c->cleanup;
     768     1261900 :   m->endian_handler = c->endian;
     769     1261900 :   m->format_fn = c->format_fn;
     770     1261900 :   m->tojson_handler = c->tojson;
     771     1261900 :   m->fromjson_handler = c->fromjson;
     772     1261900 :   m->calc_size_func = c->calc_size;
     773     1261900 :   m->bounce = c->message_bounce;
     774     1261900 :   m->is_mp_safe = c->is_mp_safe;
     775     1261900 :   m->is_autoendian = c->is_autoendian;
     776             : 
     777     1261900 :   m->trace_size = c->size;
     778     1261900 :   m->trace_enable = c->traced;
     779     1261900 :   m->replay_allowed = c->replay;
     780             : 
     781     1261900 :   if (!am->msg_id_by_name)
     782         604 :     am->msg_id_by_name = hash_create_string (0, sizeof (uword));
     783             : 
     784     2523800 :   hash_set_mem (am->msg_id_by_name, c->name, c->id);
     785             : }
     786             : 
     787             : void
     788           0 : vl_msg_api_clean_handlers (int msg_id)
     789             : {
     790             :   vl_msg_api_msg_config_t cfg;
     791           0 :   vl_msg_api_msg_config_t *c = &cfg;
     792             : 
     793           0 :   clib_memset (c, 0, sizeof (*c));
     794             : 
     795           0 :   c->id = msg_id;
     796           0 :   vl_msg_api_config (c);
     797           0 : }
     798             : 
     799             : void
     800           0 : vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
     801             : {
     802           0 :   api_main_t *am = vlibapi_get_main ();
     803           0 :   vl_api_msg_data_t *m = vl_api_get_msg_data (am, msg_id);
     804           0 :   ASSERT (msg_id > 0);
     805             : 
     806           0 :   m->cleanup_handler = fp;
     807           0 : }
     808             : 
     809             : void
     810          29 : vl_msg_api_queue_handler (svm_queue_t * q)
     811             : {
     812             :   uword msg;
     813             : 
     814         118 :   while (!svm_queue_sub (q, (u8 *) &msg, SVM_Q_WAIT, 0))
     815             :     {
     816         118 :       VL_MSG_API_UNPOISON ((u8 *) msg);
     817         118 :       msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) msg - offsetof (msgbuf_t, data));
     818         118 :       vl_msg_api_handler ((void *) msg, ntohl (msgbuf->data_len));
     819             :     }
     820           0 : }
     821             : 
     822             : u32
     823      261685 : vl_msg_api_max_length (void *mp)
     824             : {
     825             :   msgbuf_t *mb;
     826      261685 :   u32 data_len = ~0;
     827             : 
     828             :   /* Work out the maximum sane message length, and return it */
     829      261685 :   if (PREDICT_TRUE (mp != 0))
     830             :     {
     831      261683 :       mb = (msgbuf_t *) (((u8 *) mp) - offsetof (msgbuf_t, data));
     832      261683 :       data_len = clib_net_to_host_u32 (mb->data_len);
     833             :     }
     834      261685 :   return data_len;
     835             : }
     836             : 
     837             : vl_api_trace_t *
     838           0 : vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
     839             : {
     840           0 :   switch (which)
     841             :     {
     842           0 :     case VL_API_TRACE_RX:
     843           0 :       return am->rx_trace;
     844           0 :     case VL_API_TRACE_TX:
     845           0 :       return am->tx_trace;
     846           0 :     default:
     847           0 :       return 0;
     848             :     }
     849             : }
     850             : 
     851             : static u8 post_mortem_dump_enabled;
     852             : 
     853             : void
     854         575 : vl_msg_api_post_mortem_dump_enable_disable (int enable)
     855             : {
     856         575 :   post_mortem_dump_enabled = enable;
     857         575 : }
     858             : 
     859             : void
     860           0 : vl_msg_api_post_mortem_dump (void)
     861             : {
     862           0 :   api_main_t *am = vlibapi_get_main ();
     863             :   FILE *fp;
     864             :   char filename[64];
     865             :   int rv;
     866             : 
     867           0 :   if (post_mortem_dump_enabled == 0)
     868           0 :     return;
     869             : 
     870           0 :   snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
     871             :             getpid ());
     872             : 
     873           0 :   fp = fopen (filename, "w");
     874           0 :   if (fp == NULL)
     875             :     {
     876           0 :       rv = write (2, "Couldn't create ", 16);
     877           0 :       rv = write (2, filename, strlen (filename));
     878           0 :       rv = write (2, "\n", 1);
     879           0 :       return;
     880             :     }
     881           0 :   rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp, 0);
     882           0 :   fclose (fp);
     883           0 :   if (rv < 0)
     884             :     {
     885           0 :       rv = write (2, "Failed to save post-mortem API trace to ", 40);
     886           0 :       rv = write (2, filename, strlen (filename));
     887           0 :       rv = write (2, "\n", 1);
     888             :     }
     889             : 
     890             : }
     891             : 
     892             : /* Layered message handling support */
     893             : 
     894             : void
     895         575 : vl_msg_api_set_first_available_msg_id (u16 first_avail)
     896             : {
     897         575 :   api_main_t *am = vlibapi_get_main ();
     898             : 
     899         575 :   am->first_available_msg_id = first_avail;
     900         575 : }
     901             : 
     902             : u16
     903       62103 : vl_msg_api_get_msg_ids (const char *name, int n)
     904             : {
     905       62103 :   api_main_t *am = vlibapi_get_main ();
     906             :   u8 *name_copy;
     907             :   vl_api_msg_range_t *rp;
     908             :   uword *p;
     909             :   u16 rv;
     910             : 
     911       62103 :   if (am->msg_range_by_name == 0)
     912         575 :     am->msg_range_by_name = hash_create_string (0, sizeof (uword));
     913             : 
     914       62103 :   name_copy = format (0, "%s%c", name, 0);
     915             : 
     916      124206 :   p = hash_get_mem (am->msg_range_by_name, name_copy);
     917       62103 :   if (p)
     918             :     {
     919           0 :       clib_warning ("WARNING: duplicate message range registration for '%s'",
     920             :                     name_copy);
     921           0 :       vec_free (name_copy);
     922           0 :       return ((u16) ~ 0);
     923             :     }
     924             : 
     925       62103 :   if (n < 0 || n > 1024)
     926             :     {
     927           0 :       clib_warning
     928             :         ("WARNING: bad number of message-IDs (%d) requested by '%s'",
     929             :          n, name_copy);
     930           0 :       vec_free (name_copy);
     931           0 :       return ((u16) ~ 0);
     932             :     }
     933             : 
     934       62103 :   vec_add2 (am->msg_ranges, rp, 1);
     935             : 
     936       62103 :   rv = rp->first_msg_id = am->first_available_msg_id;
     937       62103 :   am->first_available_msg_id += n;
     938       62103 :   rp->last_msg_id = am->first_available_msg_id - 1;
     939       62103 :   rp->name = name_copy;
     940             : 
     941      124206 :   hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
     942             : 
     943       62103 :   return rv;
     944             : }
     945             : 
     946             : void
     947     1013180 : vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
     948             : {
     949             :   uword *p;
     950             : 
     951     1013180 :   if (am->msg_index_by_name_and_crc == 0)
     952         575 :     am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
     953             : 
     954     1013180 :   p = hash_get_mem (am->msg_index_by_name_and_crc, string);
     955     1013180 :   if (p)
     956             :     {
     957           0 :       clib_warning ("attempt to redefine '%s' ignored...", string);
     958           0 :       return;
     959             :     }
     960             : 
     961     2026360 :   hash_set_mem (am->msg_index_by_name_and_crc, string, id);
     962             : }
     963             : 
     964             : void
     965           0 : vl_msg_api_add_version (api_main_t * am, const char *string,
     966             :                         u32 major, u32 minor, u32 patch)
     967             : {
     968           0 :   api_version_t version = {.major = major,.minor = minor,.patch = patch };
     969           0 :   ASSERT (strlen (string) < 64);
     970           0 :   strncpy (version.name, string, 64 - 1);
     971           0 :   vec_add1 (am->api_version_list, version);
     972           0 : }
     973             : 
     974             : u32
     975           0 : vl_msg_api_get_msg_index (u8 * name_and_crc)
     976             : {
     977           0 :   api_main_t *am = vlibapi_get_main ();
     978             :   uword *p;
     979             : 
     980           0 :   if (am->msg_index_by_name_and_crc)
     981             :     {
     982           0 :       p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
     983           0 :       if (p)
     984           0 :         return p[0];
     985             :     }
     986           0 :   return ~0;
     987             : }
     988             : 
     989             : void *
     990       55574 : vl_msg_push_heap_w_region (svm_region_t * vlib_rp)
     991             : {
     992       55574 :   pthread_mutex_lock (&vlib_rp->mutex);
     993       55574 :   return svm_push_data_heap (vlib_rp);
     994             : }
     995             : 
     996             : void *
     997         180 : vl_msg_push_heap (void)
     998             : {
     999         180 :   api_main_t *am = vlibapi_get_main ();
    1000         180 :   return vl_msg_push_heap_w_region (am->vlib_rp);
    1001             : }
    1002             : 
    1003             : void
    1004       55574 : vl_msg_pop_heap_w_region (svm_region_t * vlib_rp, void *oldheap)
    1005             : {
    1006       55574 :   svm_pop_heap (oldheap);
    1007       55574 :   pthread_mutex_unlock (&vlib_rp->mutex);
    1008       55574 : }
    1009             : 
    1010             : void
    1011         180 : vl_msg_pop_heap (void *oldheap)
    1012             : {
    1013         180 :   api_main_t *am = vlibapi_get_main ();
    1014         180 :   vl_msg_pop_heap_w_region (am->vlib_rp, oldheap);
    1015         180 : }
    1016             : 
    1017             : /* Must be nul terminated */
    1018             : int
    1019           1 : vl_api_c_string_to_api_string (const char *buf, vl_api_string_t * str)
    1020             : {
    1021             :   /* copy without nul terminator */
    1022           1 :   u32 len = strlen (buf);
    1023           1 :   if (len > 0)
    1024           1 :     clib_memcpy_fast (str->buf, buf, len);
    1025           1 :   str->length = htonl (len);
    1026           1 :   return len + sizeof (u32);
    1027             : }
    1028             : 
    1029             : /* Must NOT be nul terminated */
    1030             : int
    1031      261662 : vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
    1032             : {
    1033      261662 :   u32 len = vec_len (vec);
    1034      261662 :   clib_memcpy (str->buf, vec, len);
    1035      261662 :   str->length = htonl (len);
    1036      261662 :   return len + sizeof (u32);
    1037             : }
    1038             : 
    1039             : u32
    1040      791758 : vl_api_string_len (vl_api_string_t * astr)
    1041             : {
    1042      791758 :   return clib_net_to_host_u32 (astr->length);
    1043             : }
    1044             : 
    1045             : u8 *
    1046           0 : vl_api_format_string (u8 * s, va_list * args)
    1047             : {
    1048           0 :   vl_api_string_t *a = va_arg (*args, vl_api_string_t *);
    1049           0 :   vec_add (s, a->buf, clib_net_to_host_u32 (a->length));
    1050           0 :   return s;
    1051             : }
    1052             : 
    1053             : /*
    1054             :  * Returns a new vector. Remember to free it after use.
    1055             :  * NOT nul terminated.
    1056             :  */
    1057             : u8 *
    1058      261683 : vl_api_from_api_to_new_vec (void *mp, vl_api_string_t * astr)
    1059             : {
    1060      261683 :   u8 *v = 0;
    1061             : 
    1062      261683 :   if (vl_msg_api_max_length (mp) < clib_net_to_host_u32 (astr->length))
    1063           0 :     return format (0, "Invalid astr->length %u > max (%u)%c",
    1064             :                    clib_net_to_host_u32 (astr->length),
    1065             :                    vl_msg_api_max_length (mp), 0);
    1066      261683 :   vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
    1067      261683 :   return v;
    1068             : }
    1069             : 
    1070             : /*
    1071             :  * Returns a new vector. Remember to free it after use.
    1072             :  * Nul terminated.
    1073             :  */
    1074             : char *
    1075          31 : vl_api_from_api_to_new_c_string (vl_api_string_t * astr)
    1076             : {
    1077          31 :   char *v = 0;
    1078          31 :   if (clib_net_to_host_u32 (astr->length) > 0)
    1079             :     {
    1080          31 :       vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
    1081          31 :       vec_add1 (v, 0);
    1082             :     }
    1083          31 :   return v;
    1084             : }
    1085             : 
    1086             : void
    1087         575 : vl_api_set_elog_main (elog_main_t * m)
    1088             : {
    1089         575 :   api_main_t *am = vlibapi_get_main ();
    1090         575 :   am->elog_main = m;
    1091         575 : }
    1092             : 
    1093             : int
    1094         580 : vl_api_set_elog_trace_api_messages (int enable)
    1095             : {
    1096             :   int rv;
    1097         580 :   api_main_t *am = vlibapi_get_main ();
    1098             : 
    1099         580 :   rv = am->elog_trace_api_messages;
    1100         580 :   am->elog_trace_api_messages = enable;
    1101         580 :   return rv;
    1102             : }
    1103             : 
    1104             : int
    1105           9 : vl_api_get_elog_trace_api_messages (void)
    1106             : {
    1107           9 :   api_main_t *am = vlibapi_get_main ();
    1108             : 
    1109           9 :   return am->elog_trace_api_messages;
    1110             : }
    1111             : 
    1112             : /*
    1113             :  * fd.io coding-style-patch-verification: ON
    1114             :  *
    1115             :  * Local Variables:
    1116             :  * eval: (c-set-style "gnu")
    1117             :  * End:
    1118             :  */

Generated by: LCOV version 1.14