blob: 17560e5de23a7e85ce03202b59258eecacf7b8b0 [file] [log] [blame]
Dave Barach371e4e12016-07-08 09:38:52 -04001/*
Ed Warnickecb9cada2015-12-08 15:45:58 -07002 *------------------------------------------------------------------
3 * api_shared.c - API message handling, common code for both clients
4 * and the vlib process itself.
Dave Barach371e4e12016-07-08 09:38:52 -04005 *
Ed Warnickecb9cada2015-12-08 15:45:58 -07006 *
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>
Dave Barach072f8de2016-12-02 13:31:25 -050024#include <stddef.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070025#include <string.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070026#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>
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +000033#include <vppinfra/callback.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070034
Dave Barach80f54e22017-03-08 19:08:56 -050035/* *INDENT-OFF* */
BenoƮt Ganne7f9256e2022-03-04 17:17:04 +010036static api_main_t api_global_main = {
37 .region_name = "/unset",
38 .api_uid = -1,
39 .api_gid = -1,
40};
Dave Barach80f54e22017-03-08 19:08:56 -050041/* *INDENT-ON* */
Dave Barach371e4e12016-07-08 09:38:52 -040042
Dave Barach39d69112019-11-27 11:42:13 -050043/* Please use vlibapi_get_main() to access my_api_main */
44__thread api_main_t *my_api_main = &api_global_main;
45
46void
47vl_msg_api_set_global_main (void *am_arg)
48{
49 ASSERT (am_arg);
50 my_api_main = (api_main_t *) am_arg;
51}
52
Dave Barach371e4e12016-07-08 09:38:52 -040053void
54vl_msg_api_increment_missing_client_counter (void)
55{
Dave Barach39d69112019-11-27 11:42:13 -050056 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -040057 am->missing_clients++;
58}
59
Dave Barach371e4e12016-07-08 09:38:52 -040060int
61vl_msg_api_rx_trace_enabled (api_main_t * am)
Ed Warnickecb9cada2015-12-08 15:45:58 -070062{
Dave Barach371e4e12016-07-08 09:38:52 -040063 return (am->rx_trace && am->rx_trace->enabled);
Ed Warnickecb9cada2015-12-08 15:45:58 -070064}
65
Dave Barach371e4e12016-07-08 09:38:52 -040066int
67vl_msg_api_tx_trace_enabled (api_main_t * am)
Ed Warnickecb9cada2015-12-08 15:45:58 -070068{
Dave Barach371e4e12016-07-08 09:38:52 -040069 return (am->tx_trace && am->tx_trace->enabled);
Ed Warnickecb9cada2015-12-08 15:45:58 -070070}
71
72/*
73 * vl_msg_api_trace
74 */
Dave Barach371e4e12016-07-08 09:38:52 -040075void
76vl_msg_api_trace (api_main_t * am, vl_api_trace_t * tp, void *msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -070077{
Dave Barach371e4e12016-07-08 09:38:52 -040078 u8 **this_trace;
79 u8 **old_trace;
80 u8 *msg_copy;
Dave Barach072f8de2016-12-02 13:31:25 -050081 u32 length;
Dave Barach371e4e12016-07-08 09:38:52 -040082 trace_cfg_t *cfgp;
Dave Barach9683c1e2019-07-01 09:42:41 -040083 u16 msg_id = clib_net_to_host_u16 (*((u16 *) msg));
Dave Barach072f8de2016-12-02 13:31:25 -050084 msgbuf_t *header = (msgbuf_t *) (((u8 *) msg) - offsetof (msgbuf_t, data));
Ed Warnickecb9cada2015-12-08 15:45:58 -070085
Dave Barach371e4e12016-07-08 09:38:52 -040086 cfgp = am->api_trace_cfg + msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -070087
Dave Barach371e4e12016-07-08 09:38:52 -040088 if (!cfgp || !cfgp->trace_enable)
89 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070090
Dave Barach371e4e12016-07-08 09:38:52 -040091 msg_copy = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070092
Dave Barach371e4e12016-07-08 09:38:52 -040093 if (tp->nitems == 0)
94 {
95 clib_warning ("tp->nitems is 0");
96 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070097 }
98
Dave Barach371e4e12016-07-08 09:38:52 -040099 if (vec_len (tp->traces) < tp->nitems)
100 {
101 vec_add1 (tp->traces, 0);
102 this_trace = tp->traces + vec_len (tp->traces) - 1;
103 }
104 else
105 {
106 tp->wrapped = 1;
107 old_trace = tp->traces + tp->curindex++;
108 if (tp->curindex == tp->nitems)
109 tp->curindex = 0;
Dave Barachf35a0722019-06-12 16:50:38 -0400110 /* Reuse the trace record, may save some memory allocator traffic */
111 msg_copy = *old_trace;
112 vec_reset_length (msg_copy);
Dave Barach371e4e12016-07-08 09:38:52 -0400113 this_trace = old_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700114 }
115
Dave Barach072f8de2016-12-02 13:31:25 -0500116 length = clib_net_to_host_u32 (header->data_len);
117
118 vec_validate (msg_copy, length - 1);
Dave Barach178cf492018-11-13 16:34:13 -0500119 clib_memcpy_fast (msg_copy, msg, length);
Dave Barach371e4e12016-07-08 09:38:52 -0400120 *this_trace = msg_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700121}
122
Dave Barach371e4e12016-07-08 09:38:52 -0400123int
124vl_msg_api_trace_onoff (api_main_t * am, vl_api_trace_which_t which,
125 int onoff)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126{
Dave Barach371e4e12016-07-08 09:38:52 -0400127 vl_api_trace_t *tp;
128 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700129
Dave Barach371e4e12016-07-08 09:38:52 -0400130 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700131 {
132 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400133 tp = am->tx_trace;
134 if (tp == 0)
135 {
136 vl_msg_api_trace_configure (am, which, 1024);
137 tp = am->tx_trace;
138 }
139 break;
140
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400142 tp = am->rx_trace;
143 if (tp == 0)
144 {
145 vl_msg_api_trace_configure (am, which, 1024);
146 tp = am->rx_trace;
147 }
148 break;
149
Ed Warnickecb9cada2015-12-08 15:45:58 -0700150 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400151 /* duh? */
152 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700153 }
154
Dave Barach371e4e12016-07-08 09:38:52 -0400155 /* Configured? */
156 if (tp == 0 || tp->nitems == 0)
157 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700158
Dave Barach371e4e12016-07-08 09:38:52 -0400159 rv = tp->enabled;
160 tp->enabled = onoff;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700161
Dave Barach371e4e12016-07-08 09:38:52 -0400162 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163}
164
Dave Barach371e4e12016-07-08 09:38:52 -0400165int
166vl_msg_api_trace_free (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700167{
Dave Barach371e4e12016-07-08 09:38:52 -0400168 vl_api_trace_t *tp;
169 int i;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170
Dave Barach371e4e12016-07-08 09:38:52 -0400171 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700172 {
173 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400174 tp = am->tx_trace;
175 break;
176
Ed Warnickecb9cada2015-12-08 15:45:58 -0700177 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400178 tp = am->rx_trace;
179 break;
180
Ed Warnickecb9cada2015-12-08 15:45:58 -0700181 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400182 /* duh? */
183 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700184 }
185
Dave Barach371e4e12016-07-08 09:38:52 -0400186 /* Configured? */
187 if (!tp || tp->nitems == 0)
188 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700189
Dave Barach371e4e12016-07-08 09:38:52 -0400190 tp->curindex = 0;
191 tp->wrapped = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700192
Dave Barach371e4e12016-07-08 09:38:52 -0400193 for (i = 0; i < vec_len (tp->traces); i++)
194 {
195 vec_free (tp->traces[i]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196 }
Dave Barach371e4e12016-07-08 09:38:52 -0400197 vec_free (tp->traces);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700198
Dave Barach371e4e12016-07-08 09:38:52 -0400199 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700200}
201
Ole Troanedfe2c02019-07-30 15:38:13 +0200202u8 *
203vl_api_serialize_message_table (api_main_t * am, u8 * vector)
204{
205 serialize_main_t _sm, *sm = &_sm;
206 hash_pair_t *hp;
207 u32 nmsg = hash_elts (am->msg_index_by_name_and_crc);
208
209 serialize_open_vector (sm, vector);
210
211 /* serialize the count */
212 serialize_integer (sm, nmsg, sizeof (u32));
213
214 /* *INDENT-OFF* */
215 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
216 ({
217 serialize_likely_small_unsigned_integer (sm, hp->value[0]);
218 serialize_cstring (sm, (char *) hp->key);
219 }));
220 /* *INDENT-ON* */
221
222 return serialize_close_vector (sm);
223}
224
Filip Tehlar36217e32021-07-23 08:51:10 +0000225static int
226vl_msg_api_trace_write_one (api_main_t *am, u8 *msg, FILE *fp)
227{
228 u8 *tmpmem = 0;
229 int tlen, slen;
230 cJSON *(*tojson_fn) (void *);
231
232 u32 msg_length = vec_len (msg);
233 vec_validate (tmpmem, msg_length - 1);
234 clib_memcpy_fast (tmpmem, msg, msg_length);
235 u16 id = clib_net_to_host_u16 (*((u16 *) msg));
236
237 void (*endian_fp) (void *);
238 endian_fp = am->msg_endian_handlers[id];
239 (*endian_fp) (tmpmem);
240
241 if (id < vec_len (am->msg_tojson_handlers) && am->msg_tojson_handlers[id])
242 {
243 tojson_fn = am->msg_tojson_handlers[id];
244 cJSON *o = tojson_fn (tmpmem);
245 char *s = cJSON_Print (o);
246 slen = strlen (s);
247 tlen = fwrite (s, 1, slen, fp);
248 cJSON_free (s);
249 cJSON_Delete (o);
250 vec_free (tmpmem);
251 if (tlen != slen)
252 {
253 fformat (stderr, "writing to file error\n");
254 return -11;
255 }
256 }
257 else
258 fformat (stderr, " [no registered tojson fn]\n");
259
260 return 0;
261}
262
263#define vl_msg_fwrite(_s, _f) fwrite (_s, 1, sizeof (_s) - 1, _f)
264
265typedef struct
266{
267 FILE *fp;
268 u32 n_traces;
269 u32 i;
270} vl_msg_write_json_args_t;
271
272static int
273vl_msg_write_json_fn (u8 *msg, void *ctx)
274{
275 vl_msg_write_json_args_t *arg = ctx;
276 FILE *fp = arg->fp;
277 api_main_t *am = vlibapi_get_main ();
278 int rc = vl_msg_api_trace_write_one (am, msg, fp);
279 if (rc < 0)
280 return rc;
281
282 if (arg->i < arg->n_traces - 1)
283 vl_msg_fwrite (",\n", fp);
284 arg->i++;
285 return 0;
286}
287
288static int
289vl_msg_api_trace_write_json (api_main_t *am, vl_api_trace_t *tp, FILE *fp)
290{
291 vl_msg_write_json_args_t args;
292 clib_memset (&args, 0, sizeof (args));
293 args.fp = fp;
294 args.n_traces = vec_len (tp->traces);
295 vl_msg_fwrite ("[\n", fp);
296
297 int rv = vl_msg_traverse_trace (tp, vl_msg_write_json_fn, &args);
298 if (rv < 0)
299 return rv;
300
301 vl_msg_fwrite ("]", fp);
302 return 0;
303}
304
Dave Barach371e4e12016-07-08 09:38:52 -0400305int
Filip Tehlar36217e32021-07-23 08:51:10 +0000306vl_msg_traverse_trace (vl_api_trace_t *tp, vl_msg_traverse_trace_fn fn,
307 void *ctx)
308{
309 int i;
310 u8 *msg;
311 int rv = 0;
312
313 /* No-wrap case */
314 if (tp->wrapped == 0)
315 {
316 for (i = 0; i < vec_len (tp->traces); i++)
317 {
318 /*sa_ignore NO_NULL_CHK */
319 msg = tp->traces[i];
320 if (!msg)
321 continue;
322
323 rv = fn (msg, ctx);
324 if (rv < 0)
325 return rv;
326 }
327 }
328 else
329 {
330 /* Wrap case: write oldest -> end of buffer */
331 for (i = tp->curindex; i < vec_len (tp->traces); i++)
332 {
333 msg = tp->traces[i];
334 if (!msg)
335 continue;
336
337 rv = fn (msg, ctx);
338 if (rv < 0)
339 return rv;
340 }
341 /* write beginning of buffer -> oldest-1 */
342 for (i = 0; i < tp->curindex; i++)
343 {
344 /*sa_ignore NO_NULL_CHK */
345 msg = tp->traces[i];
346 if (!msg)
347 continue;
348
349 rv = fn (msg, ctx);
350 if (rv < 0)
351 return rv;
352 }
353 }
354 return 0;
355}
356
357static int
358vl_api_msg_write_fn (u8 *msg, void *ctx)
359{
360 FILE *fp = ctx;
361 u32 msg_length = clib_host_to_net_u32 (vec_len (msg));
362 if (fwrite (&msg_length, 1, sizeof (msg_length), fp) != sizeof (msg_length))
363 {
364 return (-14);
365 }
366 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
367 {
368 return (-14);
369 }
370 return 0;
371}
372
373int
374vl_msg_api_trace_save (api_main_t *am, vl_api_trace_which_t which, FILE *fp,
375 u8 is_json)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700376{
Dave Barach371e4e12016-07-08 09:38:52 -0400377 vl_api_trace_t *tp;
378 vl_api_trace_file_header_t fh;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700379
Dave Barach371e4e12016-07-08 09:38:52 -0400380 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700381 {
382 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400383 tp = am->tx_trace;
384 break;
385
Ed Warnickecb9cada2015-12-08 15:45:58 -0700386 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400387 tp = am->rx_trace;
388 break;
389
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400391 /* duh? */
392 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700393 }
394
Dave Barach371e4e12016-07-08 09:38:52 -0400395 /* Configured, data present? */
396 if (tp == 0 || tp->nitems == 0 || vec_len (tp->traces) == 0)
397 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398
Dave Barach371e4e12016-07-08 09:38:52 -0400399 /* "Dare to be stupid" check */
400 if (fp == 0)
401 {
402 return -2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700403 }
404
Filip Tehlar36217e32021-07-23 08:51:10 +0000405 if (is_json)
406 return vl_msg_api_trace_write_json (am, tp, fp);
407
Dave Barach371e4e12016-07-08 09:38:52 -0400408 /* Write the file header */
Dave Barach371e4e12016-07-08 09:38:52 -0400409 fh.wrapped = tp->wrapped;
Ole Troanedfe2c02019-07-30 15:38:13 +0200410 fh.nitems = clib_host_to_net_u32 (vec_len (tp->traces));
Filip Tehlar36217e32021-07-23 08:51:10 +0000411
Ole Troanedfe2c02019-07-30 15:38:13 +0200412 u8 *m = vl_api_serialize_message_table (am, 0);
Ole Troanedfe2c02019-07-30 15:38:13 +0200413 fh.msgtbl_size = clib_host_to_net_u32 (vec_len (m));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414
Dave Barach371e4e12016-07-08 09:38:52 -0400415 if (fwrite (&fh, sizeof (fh), 1, fp) != 1)
416 {
417 return (-10);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700418 }
419
Ole Troanedfe2c02019-07-30 15:38:13 +0200420 /* Write the message table */
421 if (fwrite (m, vec_len (m), 1, fp) != 1)
422 {
423 return (-14);
424 }
425 vec_free (m);
426
Filip Tehlar36217e32021-07-23 08:51:10 +0000427 return vl_msg_traverse_trace (tp, vl_api_msg_write_fn, fp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700428}
429
Dave Barach371e4e12016-07-08 09:38:52 -0400430int
431vl_msg_api_trace_configure (api_main_t * am, vl_api_trace_which_t which,
432 u32 nitems)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700433{
Dave Barach371e4e12016-07-08 09:38:52 -0400434 vl_api_trace_t *tp;
435 int was_on = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700436
Dave Barach371e4e12016-07-08 09:38:52 -0400437 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700438 {
439 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400440 tp = am->tx_trace;
441 if (tp == 0)
442 {
443 vec_validate (am->tx_trace, 0);
444 tp = am->tx_trace;
445 }
446 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700447
Dave Barach371e4e12016-07-08 09:38:52 -0400448 case VL_API_TRACE_RX:
449 tp = am->rx_trace;
450 if (tp == 0)
451 {
452 vec_validate (am->rx_trace, 0);
453 tp = am->rx_trace;
454 }
455
456 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700457
458 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400459 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700460
461 }
462
Dave Barach371e4e12016-07-08 09:38:52 -0400463 if (tp->enabled)
464 {
465 was_on = vl_msg_api_trace_onoff (am, which, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700466 }
Dave Barach371e4e12016-07-08 09:38:52 -0400467 if (tp->traces)
468 {
469 vl_msg_api_trace_free (am, which);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700470 }
471
Dave Barachb7b92992018-10-17 10:38:51 -0400472 clib_memset (tp, 0, sizeof (*tp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700473
Dave Barach371e4e12016-07-08 09:38:52 -0400474 if (clib_arch_is_big_endian)
475 {
476 tp->endian = VL_API_BIG_ENDIAN;
477 }
478 else
479 {
480 tp->endian = VL_API_LITTLE_ENDIAN;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700481 }
482
Dave Barach371e4e12016-07-08 09:38:52 -0400483 tp->nitems = nitems;
484 if (was_on)
485 {
486 (void) vl_msg_api_trace_onoff (am, which, was_on);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700487 }
Dave Barach371e4e12016-07-08 09:38:52 -0400488 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489}
490
Dave Barach80f54e22017-03-08 19:08:56 -0500491void
492vl_msg_api_barrier_sync (void)
493{
494}
495
496void
497vl_msg_api_barrier_release (void)
498{
499}
500
Dave Barach371e4e12016-07-08 09:38:52 -0400501always_inline void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100502msg_handler_internal (api_main_t *am, void *the_msg, uword msg_len,
503 int trace_it, int do_it, int free_it)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700504{
Dave Barach9683c1e2019-07-01 09:42:41 -0400505 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400506 u8 *(*print_fp) (void *, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700507
Dave Barachb09f4d02019-07-15 16:00:03 -0400508 if (PREDICT_FALSE (am->elog_trace_api_messages))
509 {
510 /* *INDENT-OFF* */
511 ELOG_TYPE_DECLARE (e) =
512 {
513 .format = "api-msg: %s",
514 .format_args = "T4",
515 };
516 /* *INDENT-ON* */
517 struct
518 {
519 u32 c;
520 } *ed;
521 ed = ELOG_DATA (am->elog_main, e);
Andrew Yourtchenkof48de882021-02-06 12:28:52 +0000522 if (id < vec_len (am->msg_names) && am->msg_names[id])
Dave Barachb09f4d02019-07-15 16:00:03 -0400523 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
524 else
525 ed->c = elog_string (am->elog_main, "BOGUS");
526 }
527
Dave Barach371e4e12016-07-08 09:38:52 -0400528 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
529 {
530 if (trace_it)
531 vl_msg_api_trace (am, am->rx_trace, the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532
Dave Barach371e4e12016-07-08 09:38:52 -0400533 if (am->msg_print_flag)
534 {
535 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
536 print_fp = (void *) am->msg_print_handlers[id];
537 if (print_fp == 0)
538 {
539 fformat (stdout, " [no registered print fn]\n");
540 }
541 else
542 {
543 (*print_fp) (the_msg, stdout);
544 }
545 }
546
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100547 uword calc_size = 0;
548 uword (*calc_size_fp) (void *);
549 calc_size_fp = am->msg_calc_size_funcs[id];
550 ASSERT (NULL != calc_size_fp);
551 if (calc_size_fp)
Dave Barach371e4e12016-07-08 09:38:52 -0400552 {
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100553 calc_size = (*calc_size_fp) (the_msg);
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100554 if (calc_size > msg_len)
555 {
556 clib_warning (
557 "Truncated message '%s' (id %u) received, calculated size "
558 "%lu is bigger than actual size %llu, message dropped.",
559 am->msg_names[id], id, calc_size, msg_len);
560 }
561 }
562 else
563 {
564 clib_warning ("Message '%s' (id %u) has NULL calc_size_func, cannot "
565 "verify message size is correct",
566 am->msg_names[id], id);
567 }
568
569 /* don't process message if it's truncated, otherwise byte swaps
570 * and stuff could corrupt memory even beyond message if it's malicious
571 * e.g. VLA length field set to 1M elements, but VLA empty */
572 if (do_it && calc_size <= msg_len)
573 {
574
Dave Barach371e4e12016-07-08 09:38:52 -0400575 if (!am->is_mp_safe[id])
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100576 {
577 vl_msg_api_barrier_trace_context (am->msg_names[id]);
578 vl_msg_api_barrier_sync ();
579 }
Ole Troane796a182020-05-18 11:14:05 +0200580
581 if (am->is_autoendian[id])
582 {
583 void (*endian_fp) (void *);
584 endian_fp = am->msg_endian_handlers[id];
585 (*endian_fp) (the_msg);
586 }
587
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000588 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
589 clib_call_callbacks (am->perf_counter_cbs, am, id,
590 0 /* before */ );
591
Dave Barach371e4e12016-07-08 09:38:52 -0400592 (*am->msg_handlers[id]) (the_msg);
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000593
594 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
595 clib_call_callbacks (am->perf_counter_cbs, am, id,
596 1 /* after */ );
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100597
Dave Barach371e4e12016-07-08 09:38:52 -0400598 if (!am->is_mp_safe[id])
599 vl_msg_api_barrier_release ();
600 }
601 }
602 else
603 {
604 clib_warning ("no handler for msg id %d", id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700605 }
606
Dave Barach371e4e12016-07-08 09:38:52 -0400607 if (free_it)
608 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700609
Dave Barachb09f4d02019-07-15 16:00:03 -0400610 if (PREDICT_FALSE (am->elog_trace_api_messages))
611 {
612 /* *INDENT-OFF* */
613 ELOG_TYPE_DECLARE (e) =
614 {
615 .format = "api-msg-done(%s): %s",
616 .format_args = "t4T4",
617 .n_enum_strings = 2,
618 .enum_strings =
619 {
620 "barrier",
621 "mp-safe",
622 }
623 };
624 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700625
Dave Barachb09f4d02019-07-15 16:00:03 -0400626 struct
627 {
628 u32 barrier;
629 u32 c;
630 } *ed;
631 ed = ELOG_DATA (am->elog_main, e);
Andrew Yourtchenkof48de882021-02-06 12:28:52 +0000632 if (id < vec_len (am->msg_names) && am->msg_names[id])
Dave Barach67947872019-07-19 09:31:29 -0400633 {
634 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
635 ed->barrier = !am->is_mp_safe[id];
636 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400637 else
Dave Barach67947872019-07-19 09:31:29 -0400638 {
639 ed->c = elog_string (am->elog_main, "BOGUS");
640 ed->barrier = 0;
641 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400642 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700643}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700644
Dave Barach371e4e12016-07-08 09:38:52 -0400645void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100646vl_msg_api_handler (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700647{
Dave Barach39d69112019-11-27 11:42:13 -0500648 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700649
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100650 msg_handler_internal (am, the_msg, msg_len,
651 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
652 1 /* do_it */, 1 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700653}
654
Dave Barach371e4e12016-07-08 09:38:52 -0400655void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100656vl_msg_api_handler_no_free (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700657{
Dave Barach39d69112019-11-27 11:42:13 -0500658 api_main_t *am = vlibapi_get_main ();
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100659 msg_handler_internal (am, the_msg, msg_len,
660 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
661 1 /* do_it */, 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700662}
663
Dave Barach371e4e12016-07-08 09:38:52 -0400664void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100665vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700666{
Dave Barach39d69112019-11-27 11:42:13 -0500667 api_main_t *am = vlibapi_get_main ();
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100668 msg_handler_internal (am, the_msg, msg_len, 0 /* trace_it */, 1 /* do_it */,
669 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700670}
671
672/*
673 * Add a trace record to the API message trace buffer, if
674 * API message tracing is enabled. Handy for adding sufficient
675 * data to the trace to reproduce autonomous state, as opposed to
Dave Barach371e4e12016-07-08 09:38:52 -0400676 * state downloaded via control-plane API messages. Example: the NAT
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677 * application creates database entries based on packet traffic, not
678 * control-plane messages.
679 *
680 */
Dave Barach371e4e12016-07-08 09:38:52 -0400681void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100682vl_msg_api_trace_only (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700683{
Dave Barach39d69112019-11-27 11:42:13 -0500684 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700685
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100686 msg_handler_internal (am, the_msg, msg_len,
687 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
688 0 /* do_it */, 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700689}
690
Dave Barach371e4e12016-07-08 09:38:52 -0400691void
692vl_msg_api_cleanup_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700693{
Dave Barach39d69112019-11-27 11:42:13 -0500694 api_main_t *am = vlibapi_get_main ();
Dave Barach9683c1e2019-07-01 09:42:41 -0400695 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696
Dave Barach371e4e12016-07-08 09:38:52 -0400697 if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
698 {
699 clib_warning ("_vl_msg_id too large: %d\n", id);
700 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701 }
Dave Barach371e4e12016-07-08 09:38:52 -0400702 if (am->msg_cleanup_handlers[id])
703 (*am->msg_cleanup_handlers[id]) (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700704
Dave Barach371e4e12016-07-08 09:38:52 -0400705 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700706}
707
708/*
709 * vl_msg_api_replay_handler
710 */
Dave Barach371e4e12016-07-08 09:38:52 -0400711void
712vl_msg_api_replay_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700713{
Dave Barach39d69112019-11-27 11:42:13 -0500714 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700715
Dave Barach9683c1e2019-07-01 09:42:41 -0400716 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700717
Dave Barach371e4e12016-07-08 09:38:52 -0400718 if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
719 {
720 clib_warning ("_vl_msg_id too large: %d\n", id);
721 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722 }
Dave Barach371e4e12016-07-08 09:38:52 -0400723 /* do NOT trace the message... */
724 if (am->msg_handlers[id])
725 (*am->msg_handlers[id]) (the_msg);
726 /* do NOT free the message buffer... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727}
Dave Barach371e4e12016-07-08 09:38:52 -0400728
Dave Barachbfd92272017-05-12 11:59:25 -0400729u32
730vl_msg_api_get_msg_length (void *msg_arg)
731{
732 return vl_msg_api_get_msg_length_inline (msg_arg);
733}
734
Ed Warnickecb9cada2015-12-08 15:45:58 -0700735/*
736 * vl_msg_api_socket_handler
737 */
Dave Barach371e4e12016-07-08 09:38:52 -0400738void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100739vl_msg_api_socket_handler (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700740{
Dave Barach39d69112019-11-27 11:42:13 -0500741 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700742
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100743 msg_handler_internal (am, the_msg, msg_len,
744 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
745 1 /* do_it */, 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700746}
747
Filip Tehlar36217e32021-07-23 08:51:10 +0000748#define foreach_msg_api_vector \
749 _ (msg_names) \
750 _ (msg_handlers) \
751 _ (msg_cleanup_handlers) \
752 _ (msg_endian_handlers) \
753 _ (msg_print_handlers) \
754 _ (msg_print_json_handlers) \
755 _ (msg_tojson_handlers) \
756 _ (msg_fromjson_handlers) \
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100757 _ (msg_calc_size_funcs) \
Filip Tehlar36217e32021-07-23 08:51:10 +0000758 _ (api_trace_cfg) \
759 _ (message_bounce) \
760 _ (is_mp_safe) \
761 _ (is_autoendian)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700762
Dave Barach371e4e12016-07-08 09:38:52 -0400763void
764vl_msg_api_config (vl_msg_api_msg_config_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700765{
Dave Barach39d69112019-11-27 11:42:13 -0500766 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700767
Dave Barach65457162017-10-10 17:53:14 -0400768 /*
769 * This happens during the java core tests if the message
770 * dictionary is missing newly added xxx_reply_t messages.
771 * Should never happen, but since I shot myself in the foot once
772 * this way, I thought I'd make it easy to debug if I ever do
773 * it again... (;-)...
774 */
775 if (c->id == 0)
776 {
777 if (c->name)
778 clib_warning ("Trying to register %s with a NULL msg id!", c->name);
779 else
780 clib_warning ("Trying to register a NULL msg with a NULL msg id!");
781 clib_warning ("Did you forget to call setup_message_id_table?");
782 return;
783 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784
785#define _(a) vec_validate (am->a, c->id);
Dave Barach371e4e12016-07-08 09:38:52 -0400786 foreach_msg_api_vector;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787#undef _
788
Dave Barach392206e2017-09-20 08:40:16 -0400789 if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
790 clib_warning
791 ("BUG: re-registering 'vl_api_%s_t_handler'."
792 "Handler was %llx, replaced by %llx",
793 c->name, am->msg_handlers[c->id], c->handler);
Dave Baracha1a093d2017-03-02 13:13:23 -0500794
Dave Barach371e4e12016-07-08 09:38:52 -0400795 am->msg_names[c->id] = c->name;
796 am->msg_handlers[c->id] = c->handler;
797 am->msg_cleanup_handlers[c->id] = c->cleanup;
798 am->msg_endian_handlers[c->id] = c->endian;
799 am->msg_print_handlers[c->id] = c->print;
Filip Tehlar36217e32021-07-23 08:51:10 +0000800 am->msg_print_json_handlers[c->id] = c->print_json;
801 am->msg_tojson_handlers[c->id] = c->tojson;
802 am->msg_fromjson_handlers[c->id] = c->fromjson;
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100803 am->msg_calc_size_funcs[c->id] = c->calc_size;
Dave Barach371e4e12016-07-08 09:38:52 -0400804 am->message_bounce[c->id] = c->message_bounce;
805 am->is_mp_safe[c->id] = c->is_mp_safe;
Ole Troane796a182020-05-18 11:14:05 +0200806 am->is_autoendian[c->id] = c->is_autoendian;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700807
Dave Barach371e4e12016-07-08 09:38:52 -0400808 am->api_trace_cfg[c->id].size = c->size;
809 am->api_trace_cfg[c->id].trace_enable = c->traced;
810 am->api_trace_cfg[c->id].replay_enable = c->replay;
Filip Tehlar36217e32021-07-23 08:51:10 +0000811
812 if (!am->msg_id_by_name)
813 am->msg_id_by_name = hash_create_string (0, sizeof (uword));
814
815 hash_set_mem (am->msg_id_by_name, c->name, c->id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700816}
817
Dave Barach371e4e12016-07-08 09:38:52 -0400818/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700819 * vl_msg_api_set_handlers
820 * preserve the old API for a while
821 */
Dave Barach371e4e12016-07-08 09:38:52 -0400822void
823vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
Filip Tehlar36217e32021-07-23 08:51:10 +0000824 void *endian, void *print, int size, int traced,
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100825 void *print_json, void *tojson, void *fromjson,
826 void *calc_size)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700827{
Dave Barach371e4e12016-07-08 09:38:52 -0400828 vl_msg_api_msg_config_t cfg;
829 vl_msg_api_msg_config_t *c = &cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700830
Dave Barachb7b92992018-10-17 10:38:51 -0400831 clib_memset (c, 0, sizeof (*c));
Dave Barach0691d6e2017-01-05 10:08:52 -0500832
Dave Barach371e4e12016-07-08 09:38:52 -0400833 c->id = id;
834 c->name = name;
835 c->handler = handler;
836 c->cleanup = cleanup;
837 c->endian = endian;
838 c->print = print;
Dave Barach371e4e12016-07-08 09:38:52 -0400839 c->traced = traced;
840 c->replay = 1;
841 c->message_bounce = 0;
842 c->is_mp_safe = 0;
Ole Troane796a182020-05-18 11:14:05 +0200843 c->is_autoendian = 0;
Filip Tehlar36217e32021-07-23 08:51:10 +0000844 c->tojson = tojson;
845 c->fromjson = fromjson;
846 c->print_json = print_json;
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100847 c->calc_size = calc_size;
Dave Barach371e4e12016-07-08 09:38:52 -0400848 vl_msg_api_config (c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700849}
850
Dave Barach371e4e12016-07-08 09:38:52 -0400851void
Matej Perina75a17ec2017-09-21 17:03:27 +0200852vl_msg_api_clean_handlers (int msg_id)
853{
854 vl_msg_api_msg_config_t cfg;
855 vl_msg_api_msg_config_t *c = &cfg;
856
Dave Barachb7b92992018-10-17 10:38:51 -0400857 clib_memset (c, 0, sizeof (*c));
Matej Perina75a17ec2017-09-21 17:03:27 +0200858
859 c->id = msg_id;
860 vl_msg_api_config (c);
861}
862
863void
Dave Barach371e4e12016-07-08 09:38:52 -0400864vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700865{
Dave Barach39d69112019-11-27 11:42:13 -0500866 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400867 ASSERT (msg_id > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700868
Dave Barach371e4e12016-07-08 09:38:52 -0400869 vec_validate (am->msg_cleanup_handlers, msg_id);
870 am->msg_cleanup_handlers[msg_id] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700871}
872
Dave Barach371e4e12016-07-08 09:38:52 -0400873void
Florin Corase86a8ed2018-01-05 03:20:25 -0800874vl_msg_api_queue_handler (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700875{
Dave Barach371e4e12016-07-08 09:38:52 -0400876 uword msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700877
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100878 while (!svm_queue_sub (q, (u8 *) &msg, SVM_Q_WAIT, 0))
879 {
880 msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) msg - offsetof (msgbuf_t, data));
881 vl_msg_api_handler ((void *) msg, ntohl (msgbuf->data_len));
882 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700883}
884
Dave Barach77841402020-04-29 17:04:10 -0400885u32
886vl_msg_api_max_length (void *mp)
887{
888 msgbuf_t *mb;
889 u32 data_len = ~0;
890
891 /* Work out the maximum sane message length, and return it */
892 if (PREDICT_TRUE (mp != 0))
893 {
894 mb = (msgbuf_t *) (((u8 *) mp) - offsetof (msgbuf_t, data));
895 data_len = clib_net_to_host_u32 (mb->data_len);
896 }
897 return data_len;
898}
899
Dave Barach371e4e12016-07-08 09:38:52 -0400900vl_api_trace_t *
901vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700902{
Dave Barach371e4e12016-07-08 09:38:52 -0400903 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700904 {
905 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400906 return am->rx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700907 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400908 return am->tx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700909 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400910 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700911 }
912}
913
Dave Barach371e4e12016-07-08 09:38:52 -0400914void
915vl_noop_handler (void *mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700916{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700917}
918
Ed Warnickecb9cada2015-12-08 15:45:58 -0700919
920static u8 post_mortem_dump_enabled;
921
Dave Barach80f54e22017-03-08 19:08:56 -0500922void
923vl_msg_api_post_mortem_dump_enable_disable (int enable)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700924{
Dave Barach80f54e22017-03-08 19:08:56 -0500925 post_mortem_dump_enabled = enable;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700926}
927
Dave Barach371e4e12016-07-08 09:38:52 -0400928void
929vl_msg_api_post_mortem_dump (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700930{
Dave Barach39d69112019-11-27 11:42:13 -0500931 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400932 FILE *fp;
933 char filename[64];
934 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700935
Dave Barach371e4e12016-07-08 09:38:52 -0400936 if (post_mortem_dump_enabled == 0)
937 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700938
Dave Barach371e4e12016-07-08 09:38:52 -0400939 snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
940 getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700941
Dave Barach371e4e12016-07-08 09:38:52 -0400942 fp = fopen (filename, "w");
943 if (fp == NULL)
944 {
945 rv = write (2, "Couldn't create ", 16);
946 rv = write (2, filename, strlen (filename));
947 rv = write (2, "\n", 1);
948 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700949 }
Filip Tehlar36217e32021-07-23 08:51:10 +0000950 rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp, 0);
Dave Barach371e4e12016-07-08 09:38:52 -0400951 fclose (fp);
952 if (rv < 0)
953 {
954 rv = write (2, "Failed to save post-mortem API trace to ", 40);
955 rv = write (2, filename, strlen (filename));
956 rv = write (2, "\n", 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700957 }
Dave Barach371e4e12016-07-08 09:38:52 -0400958
Ed Warnickecb9cada2015-12-08 15:45:58 -0700959}
960
961/* Layered message handling support */
962
Dave Barach371e4e12016-07-08 09:38:52 -0400963void
Dave Barach371e4e12016-07-08 09:38:52 -0400964vl_msg_api_set_first_available_msg_id (u16 first_avail)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700965{
Dave Barach39d69112019-11-27 11:42:13 -0500966 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400967
968 am->first_available_msg_id = first_avail;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700969}
970
Dave Barach371e4e12016-07-08 09:38:52 -0400971u16
Neale Rannse72be392017-04-26 13:59:20 -0700972vl_msg_api_get_msg_ids (const char *name, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700973{
Dave Barach39d69112019-11-27 11:42:13 -0500974 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400975 u8 *name_copy;
976 vl_api_msg_range_t *rp;
977 uword *p;
978 u16 rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700979
Dave Barach371e4e12016-07-08 09:38:52 -0400980 if (am->msg_range_by_name == 0)
981 am->msg_range_by_name = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700982
Dave Barach371e4e12016-07-08 09:38:52 -0400983 name_copy = format (0, "%s%c", name, 0);
984
985 p = hash_get_mem (am->msg_range_by_name, name_copy);
986 if (p)
987 {
988 clib_warning ("WARNING: duplicate message range registration for '%s'",
989 name_copy);
990 vec_free (name_copy);
991 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700992 }
993
Dave Barach371e4e12016-07-08 09:38:52 -0400994 if (n < 0 || n > 1024)
995 {
996 clib_warning
997 ("WARNING: bad number of message-IDs (%d) requested by '%s'",
998 n, name_copy);
999 vec_free (name_copy);
1000 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001001 }
1002
Dave Barach371e4e12016-07-08 09:38:52 -04001003 vec_add2 (am->msg_ranges, rp, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001004
Dave Barach371e4e12016-07-08 09:38:52 -04001005 rv = rp->first_msg_id = am->first_available_msg_id;
1006 am->first_available_msg_id += n;
1007 rp->last_msg_id = am->first_available_msg_id - 1;
1008 rp->name = name_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001009
Dave Barach371e4e12016-07-08 09:38:52 -04001010 hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001011
Dave Barach371e4e12016-07-08 09:38:52 -04001012 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001013}
Dave Barach371e4e12016-07-08 09:38:52 -04001014
Dave Barach557d1282016-11-10 14:22:49 -05001015void
Neale Rannse72be392017-04-26 13:59:20 -07001016vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
Dave Barach557d1282016-11-10 14:22:49 -05001017{
1018 uword *p;
1019
1020 if (am->msg_index_by_name_and_crc == 0)
1021 am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
1022
1023 p = hash_get_mem (am->msg_index_by_name_and_crc, string);
1024 if (p)
1025 {
1026 clib_warning ("attempt to redefine '%s' ignored...", string);
1027 return;
1028 }
1029
1030 hash_set_mem (am->msg_index_by_name_and_crc, string, id);
1031}
1032
Dave Barach0d056e52017-09-28 15:11:16 -04001033void
1034vl_msg_api_add_version (api_main_t * am, const char *string,
1035 u32 major, u32 minor, u32 patch)
1036{
1037 api_version_t version = {.major = major,.minor = minor,.patch = patch };
1038 ASSERT (strlen (string) < 64);
Ole Troan7504e992017-10-10 08:43:35 +02001039 strncpy (version.name, string, 64 - 1);
Dave Barach0d056e52017-09-28 15:11:16 -04001040 vec_add1 (am->api_version_list, version);
1041}
Dave Barach557d1282016-11-10 14:22:49 -05001042
Florin Corase86a8ed2018-01-05 03:20:25 -08001043u32
1044vl_msg_api_get_msg_index (u8 * name_and_crc)
1045{
Dave Barach39d69112019-11-27 11:42:13 -05001046 api_main_t *am = vlibapi_get_main ();
Florin Corase86a8ed2018-01-05 03:20:25 -08001047 uword *p;
1048
1049 if (am->msg_index_by_name_and_crc)
1050 {
1051 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
1052 if (p)
1053 return p[0];
1054 }
1055 return ~0;
1056}
1057
Ole Troan73710c72018-06-04 22:27:49 +02001058void *
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001059vl_msg_push_heap_w_region (svm_region_t * vlib_rp)
1060{
1061 pthread_mutex_lock (&vlib_rp->mutex);
1062 return svm_push_data_heap (vlib_rp);
1063}
1064
1065void *
Ole Troan73710c72018-06-04 22:27:49 +02001066vl_msg_push_heap (void)
1067{
Dave Barach39d69112019-11-27 11:42:13 -05001068 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001069 return vl_msg_push_heap_w_region (am->vlib_rp);
1070}
1071
1072void
1073vl_msg_pop_heap_w_region (svm_region_t * vlib_rp, void *oldheap)
1074{
1075 svm_pop_heap (oldheap);
1076 pthread_mutex_unlock (&vlib_rp->mutex);
Ole Troan73710c72018-06-04 22:27:49 +02001077}
1078
1079void
1080vl_msg_pop_heap (void *oldheap)
1081{
Dave Barach39d69112019-11-27 11:42:13 -05001082 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001083 vl_msg_pop_heap_w_region (am->vlib_rp, oldheap);
Ole Troan73710c72018-06-04 22:27:49 +02001084}
1085
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001086/* Must be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001087int
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001088vl_api_c_string_to_api_string (const char *buf, vl_api_string_t * str)
Neale Ranns377860a2019-06-21 07:57:18 -07001089{
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001090 /* copy without nul terminator */
1091 u32 len = strlen (buf);
1092 if (len > 0)
Ole Troan33a58172019-09-04 09:12:29 +02001093 clib_memcpy_fast (str->buf, buf, len);
Neale Ranns377860a2019-06-21 07:57:18 -07001094 str->length = htonl (len);
1095 return len + sizeof (u32);
1096}
1097
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001098/* Must NOT be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001099int
1100vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
1101{
1102 u32 len = vec_len (vec);
1103 clib_memcpy (str->buf, vec, len);
1104 str->length = htonl (len);
1105 return len + sizeof (u32);
1106}
1107
Neale Ranns377860a2019-06-21 07:57:18 -07001108u32
1109vl_api_string_len (vl_api_string_t * astr)
1110{
Dave Barach9683c1e2019-07-01 09:42:41 -04001111 return clib_net_to_host_u32 (astr->length);
Neale Ranns377860a2019-06-21 07:57:18 -07001112}
1113
Ole Troan33a58172019-09-04 09:12:29 +02001114u8 *
1115vl_api_format_string (u8 * s, va_list * args)
1116{
1117 vl_api_string_t *a = va_arg (*args, vl_api_string_t *);
1118 vec_add (s, a->buf, clib_net_to_host_u32 (a->length));
1119 return s;
1120}
1121
Neale Ranns377860a2019-06-21 07:57:18 -07001122/*
1123 * Returns a new vector. Remember to free it after use.
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001124 * NOT nul terminated.
Neale Ranns377860a2019-06-21 07:57:18 -07001125 */
1126u8 *
Dave Barach77841402020-04-29 17:04:10 -04001127vl_api_from_api_to_new_vec (void *mp, vl_api_string_t * astr)
Neale Ranns377860a2019-06-21 07:57:18 -07001128{
1129 u8 *v = 0;
Dave Barach77841402020-04-29 17:04:10 -04001130
1131 if (vl_msg_api_max_length (mp) < clib_net_to_host_u32 (astr->length))
1132 return format (0, "insane astr->length %u%c",
1133 clib_net_to_host_u32 (astr->length), 0);
Dave Barach9683c1e2019-07-01 09:42:41 -04001134 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
Neale Ranns377860a2019-06-21 07:57:18 -07001135 return v;
1136}
Ole Troan73710c72018-06-04 22:27:49 +02001137
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001138/*
1139 * Returns a new vector. Remember to free it after use.
1140 * Nul terminated.
1141 */
1142char *
1143vl_api_from_api_to_new_c_string (vl_api_string_t * astr)
1144{
1145 char *v = 0;
1146 if (clib_net_to_host_u32 (astr->length) > 0)
1147 {
1148 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
1149 vec_add1 (v, 0);
1150 }
1151 return v;
1152}
1153
Dave Barachb09f4d02019-07-15 16:00:03 -04001154void
1155vl_api_set_elog_main (elog_main_t * m)
1156{
Dave Barach39d69112019-11-27 11:42:13 -05001157 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001158 am->elog_main = m;
1159}
1160
1161int
1162vl_api_set_elog_trace_api_messages (int enable)
1163{
1164 int rv;
Dave Barach39d69112019-11-27 11:42:13 -05001165 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001166
1167 rv = am->elog_trace_api_messages;
1168 am->elog_trace_api_messages = enable;
1169 return rv;
1170}
1171
1172int
1173vl_api_get_elog_trace_api_messages (void)
1174{
Dave Barach39d69112019-11-27 11:42:13 -05001175 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001176
1177 return am->elog_trace_api_messages;
1178}
1179
Dave Barach371e4e12016-07-08 09:38:52 -04001180/*
1181 * fd.io coding-style-patch-verification: ON
1182 *
1183 * Local Variables:
1184 * eval: (c-set-style "gnu")
1185 * End:
1186 */