blob: 77278431fb7636aab8d6c5977b323400ea29eee4 [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);
554 ASSERT (calc_size <= msg_len);
555 if (calc_size > msg_len)
556 {
557 clib_warning (
558 "Truncated message '%s' (id %u) received, calculated size "
559 "%lu is bigger than actual size %llu, message dropped.",
560 am->msg_names[id], id, calc_size, msg_len);
561 }
562 }
563 else
564 {
565 clib_warning ("Message '%s' (id %u) has NULL calc_size_func, cannot "
566 "verify message size is correct",
567 am->msg_names[id], id);
568 }
569
570 /* don't process message if it's truncated, otherwise byte swaps
571 * and stuff could corrupt memory even beyond message if it's malicious
572 * e.g. VLA length field set to 1M elements, but VLA empty */
573 if (do_it && calc_size <= msg_len)
574 {
575
Dave Barach371e4e12016-07-08 09:38:52 -0400576 if (!am->is_mp_safe[id])
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100577 {
578 vl_msg_api_barrier_trace_context (am->msg_names[id]);
579 vl_msg_api_barrier_sync ();
580 }
Ole Troane796a182020-05-18 11:14:05 +0200581
582 if (am->is_autoendian[id])
583 {
584 void (*endian_fp) (void *);
585 endian_fp = am->msg_endian_handlers[id];
586 (*endian_fp) (the_msg);
587 }
588
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000589 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
590 clib_call_callbacks (am->perf_counter_cbs, am, id,
591 0 /* before */ );
592
Dave Barach371e4e12016-07-08 09:38:52 -0400593 (*am->msg_handlers[id]) (the_msg);
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000594
595 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
596 clib_call_callbacks (am->perf_counter_cbs, am, id,
597 1 /* after */ );
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100598
Dave Barach371e4e12016-07-08 09:38:52 -0400599 if (!am->is_mp_safe[id])
600 vl_msg_api_barrier_release ();
601 }
602 }
603 else
604 {
605 clib_warning ("no handler for msg id %d", id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700606 }
607
Dave Barach371e4e12016-07-08 09:38:52 -0400608 if (free_it)
609 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700610
Dave Barachb09f4d02019-07-15 16:00:03 -0400611 if (PREDICT_FALSE (am->elog_trace_api_messages))
612 {
613 /* *INDENT-OFF* */
614 ELOG_TYPE_DECLARE (e) =
615 {
616 .format = "api-msg-done(%s): %s",
617 .format_args = "t4T4",
618 .n_enum_strings = 2,
619 .enum_strings =
620 {
621 "barrier",
622 "mp-safe",
623 }
624 };
625 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700626
Dave Barachb09f4d02019-07-15 16:00:03 -0400627 struct
628 {
629 u32 barrier;
630 u32 c;
631 } *ed;
632 ed = ELOG_DATA (am->elog_main, e);
Andrew Yourtchenkof48de882021-02-06 12:28:52 +0000633 if (id < vec_len (am->msg_names) && am->msg_names[id])
Dave Barach67947872019-07-19 09:31:29 -0400634 {
635 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
636 ed->barrier = !am->is_mp_safe[id];
637 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400638 else
Dave Barach67947872019-07-19 09:31:29 -0400639 {
640 ed->c = elog_string (am->elog_main, "BOGUS");
641 ed->barrier = 0;
642 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400643 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700644}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700645
Dave Barach371e4e12016-07-08 09:38:52 -0400646void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100647vl_msg_api_handler (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700648{
Dave Barach39d69112019-11-27 11:42:13 -0500649 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700650
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100651 msg_handler_internal (am, the_msg, msg_len,
652 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
653 1 /* do_it */, 1 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700654}
655
Dave Barach371e4e12016-07-08 09:38:52 -0400656void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100657vl_msg_api_handler_no_free (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658{
Dave Barach39d69112019-11-27 11:42:13 -0500659 api_main_t *am = vlibapi_get_main ();
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100660 msg_handler_internal (am, the_msg, msg_len,
661 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
662 1 /* do_it */, 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700663}
664
Dave Barach371e4e12016-07-08 09:38:52 -0400665void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100666vl_msg_api_handler_no_trace_no_free (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700667{
Dave Barach39d69112019-11-27 11:42:13 -0500668 api_main_t *am = vlibapi_get_main ();
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100669 msg_handler_internal (am, the_msg, msg_len, 0 /* trace_it */, 1 /* do_it */,
670 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700671}
672
673/*
674 * Add a trace record to the API message trace buffer, if
675 * API message tracing is enabled. Handy for adding sufficient
676 * data to the trace to reproduce autonomous state, as opposed to
Dave Barach371e4e12016-07-08 09:38:52 -0400677 * state downloaded via control-plane API messages. Example: the NAT
Ed Warnickecb9cada2015-12-08 15:45:58 -0700678 * application creates database entries based on packet traffic, not
679 * control-plane messages.
680 *
681 */
Dave Barach371e4e12016-07-08 09:38:52 -0400682void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100683vl_msg_api_trace_only (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700684{
Dave Barach39d69112019-11-27 11:42:13 -0500685 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700686
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100687 msg_handler_internal (am, the_msg, msg_len,
688 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
689 0 /* do_it */, 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700690}
691
Dave Barach371e4e12016-07-08 09:38:52 -0400692void
693vl_msg_api_cleanup_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700694{
Dave Barach39d69112019-11-27 11:42:13 -0500695 api_main_t *am = vlibapi_get_main ();
Dave Barach9683c1e2019-07-01 09:42:41 -0400696 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700697
Dave Barach371e4e12016-07-08 09:38:52 -0400698 if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
699 {
700 clib_warning ("_vl_msg_id too large: %d\n", id);
701 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700702 }
Dave Barach371e4e12016-07-08 09:38:52 -0400703 if (am->msg_cleanup_handlers[id])
704 (*am->msg_cleanup_handlers[id]) (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700705
Dave Barach371e4e12016-07-08 09:38:52 -0400706 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700707}
708
709/*
710 * vl_msg_api_replay_handler
711 */
Dave Barach371e4e12016-07-08 09:38:52 -0400712void
713vl_msg_api_replay_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700714{
Dave Barach39d69112019-11-27 11:42:13 -0500715 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716
Dave Barach9683c1e2019-07-01 09:42:41 -0400717 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700718
Dave Barach371e4e12016-07-08 09:38:52 -0400719 if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
720 {
721 clib_warning ("_vl_msg_id too large: %d\n", id);
722 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700723 }
Dave Barach371e4e12016-07-08 09:38:52 -0400724 /* do NOT trace the message... */
725 if (am->msg_handlers[id])
726 (*am->msg_handlers[id]) (the_msg);
727 /* do NOT free the message buffer... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700728}
Dave Barach371e4e12016-07-08 09:38:52 -0400729
Dave Barachbfd92272017-05-12 11:59:25 -0400730u32
731vl_msg_api_get_msg_length (void *msg_arg)
732{
733 return vl_msg_api_get_msg_length_inline (msg_arg);
734}
735
Ed Warnickecb9cada2015-12-08 15:45:58 -0700736/*
737 * vl_msg_api_socket_handler
738 */
Dave Barach371e4e12016-07-08 09:38:52 -0400739void
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100740vl_msg_api_socket_handler (void *the_msg, uword msg_len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700741{
Dave Barach39d69112019-11-27 11:42:13 -0500742 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700743
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100744 msg_handler_internal (am, the_msg, msg_len,
745 (am->rx_trace && am->rx_trace->enabled) /* trace_it */,
746 1 /* do_it */, 0 /* free_it */);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700747}
748
Filip Tehlar36217e32021-07-23 08:51:10 +0000749#define foreach_msg_api_vector \
750 _ (msg_names) \
751 _ (msg_handlers) \
752 _ (msg_cleanup_handlers) \
753 _ (msg_endian_handlers) \
754 _ (msg_print_handlers) \
755 _ (msg_print_json_handlers) \
756 _ (msg_tojson_handlers) \
757 _ (msg_fromjson_handlers) \
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100758 _ (msg_calc_size_funcs) \
Filip Tehlar36217e32021-07-23 08:51:10 +0000759 _ (api_trace_cfg) \
760 _ (message_bounce) \
761 _ (is_mp_safe) \
762 _ (is_autoendian)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700763
Dave Barach371e4e12016-07-08 09:38:52 -0400764void
765vl_msg_api_config (vl_msg_api_msg_config_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700766{
Dave Barach39d69112019-11-27 11:42:13 -0500767 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700768
Dave Barach65457162017-10-10 17:53:14 -0400769 /*
770 * This happens during the java core tests if the message
771 * dictionary is missing newly added xxx_reply_t messages.
772 * Should never happen, but since I shot myself in the foot once
773 * this way, I thought I'd make it easy to debug if I ever do
774 * it again... (;-)...
775 */
776 if (c->id == 0)
777 {
778 if (c->name)
779 clib_warning ("Trying to register %s with a NULL msg id!", c->name);
780 else
781 clib_warning ("Trying to register a NULL msg with a NULL msg id!");
782 clib_warning ("Did you forget to call setup_message_id_table?");
783 return;
784 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700785
786#define _(a) vec_validate (am->a, c->id);
Dave Barach371e4e12016-07-08 09:38:52 -0400787 foreach_msg_api_vector;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700788#undef _
789
Dave Barach392206e2017-09-20 08:40:16 -0400790 if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
791 clib_warning
792 ("BUG: re-registering 'vl_api_%s_t_handler'."
793 "Handler was %llx, replaced by %llx",
794 c->name, am->msg_handlers[c->id], c->handler);
Dave Baracha1a093d2017-03-02 13:13:23 -0500795
Dave Barach371e4e12016-07-08 09:38:52 -0400796 am->msg_names[c->id] = c->name;
797 am->msg_handlers[c->id] = c->handler;
798 am->msg_cleanup_handlers[c->id] = c->cleanup;
799 am->msg_endian_handlers[c->id] = c->endian;
800 am->msg_print_handlers[c->id] = c->print;
Filip Tehlar36217e32021-07-23 08:51:10 +0000801 am->msg_print_json_handlers[c->id] = c->print_json;
802 am->msg_tojson_handlers[c->id] = c->tojson;
803 am->msg_fromjson_handlers[c->id] = c->fromjson;
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100804 am->msg_calc_size_funcs[c->id] = c->calc_size;
Dave Barach371e4e12016-07-08 09:38:52 -0400805 am->message_bounce[c->id] = c->message_bounce;
806 am->is_mp_safe[c->id] = c->is_mp_safe;
Ole Troane796a182020-05-18 11:14:05 +0200807 am->is_autoendian[c->id] = c->is_autoendian;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700808
Dave Barach371e4e12016-07-08 09:38:52 -0400809 am->api_trace_cfg[c->id].size = c->size;
810 am->api_trace_cfg[c->id].trace_enable = c->traced;
811 am->api_trace_cfg[c->id].replay_enable = c->replay;
Filip Tehlar36217e32021-07-23 08:51:10 +0000812
813 if (!am->msg_id_by_name)
814 am->msg_id_by_name = hash_create_string (0, sizeof (uword));
815
816 hash_set_mem (am->msg_id_by_name, c->name, c->id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817}
818
Dave Barach371e4e12016-07-08 09:38:52 -0400819/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700820 * vl_msg_api_set_handlers
821 * preserve the old API for a while
822 */
Dave Barach371e4e12016-07-08 09:38:52 -0400823void
824vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
Filip Tehlar36217e32021-07-23 08:51:10 +0000825 void *endian, void *print, int size, int traced,
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100826 void *print_json, void *tojson, void *fromjson,
827 void *calc_size)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700828{
Dave Barach371e4e12016-07-08 09:38:52 -0400829 vl_msg_api_msg_config_t cfg;
830 vl_msg_api_msg_config_t *c = &cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700831
Dave Barachb7b92992018-10-17 10:38:51 -0400832 clib_memset (c, 0, sizeof (*c));
Dave Barach0691d6e2017-01-05 10:08:52 -0500833
Dave Barach371e4e12016-07-08 09:38:52 -0400834 c->id = id;
835 c->name = name;
836 c->handler = handler;
837 c->cleanup = cleanup;
838 c->endian = endian;
839 c->print = print;
Dave Barach371e4e12016-07-08 09:38:52 -0400840 c->traced = traced;
841 c->replay = 1;
842 c->message_bounce = 0;
843 c->is_mp_safe = 0;
Ole Troane796a182020-05-18 11:14:05 +0200844 c->is_autoendian = 0;
Filip Tehlar36217e32021-07-23 08:51:10 +0000845 c->tojson = tojson;
846 c->fromjson = fromjson;
847 c->print_json = print_json;
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100848 c->calc_size = calc_size;
Dave Barach371e4e12016-07-08 09:38:52 -0400849 vl_msg_api_config (c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700850}
851
Dave Barach371e4e12016-07-08 09:38:52 -0400852void
Matej Perina75a17ec2017-09-21 17:03:27 +0200853vl_msg_api_clean_handlers (int msg_id)
854{
855 vl_msg_api_msg_config_t cfg;
856 vl_msg_api_msg_config_t *c = &cfg;
857
Dave Barachb7b92992018-10-17 10:38:51 -0400858 clib_memset (c, 0, sizeof (*c));
Matej Perina75a17ec2017-09-21 17:03:27 +0200859
860 c->id = msg_id;
861 vl_msg_api_config (c);
862}
863
864void
Dave Barach371e4e12016-07-08 09:38:52 -0400865vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700866{
Dave Barach39d69112019-11-27 11:42:13 -0500867 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400868 ASSERT (msg_id > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700869
Dave Barach371e4e12016-07-08 09:38:52 -0400870 vec_validate (am->msg_cleanup_handlers, msg_id);
871 am->msg_cleanup_handlers[msg_id] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700872}
873
Dave Barach371e4e12016-07-08 09:38:52 -0400874void
Florin Corase86a8ed2018-01-05 03:20:25 -0800875vl_msg_api_queue_handler (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700876{
Dave Barach371e4e12016-07-08 09:38:52 -0400877 uword msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700878
Klement Sekera9b7e8ac2021-11-22 21:26:20 +0100879 while (!svm_queue_sub (q, (u8 *) &msg, SVM_Q_WAIT, 0))
880 {
881 msgbuf_t *msgbuf = (msgbuf_t *) ((u8 *) msg - offsetof (msgbuf_t, data));
882 vl_msg_api_handler ((void *) msg, ntohl (msgbuf->data_len));
883 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700884}
885
Dave Barach77841402020-04-29 17:04:10 -0400886u32
887vl_msg_api_max_length (void *mp)
888{
889 msgbuf_t *mb;
890 u32 data_len = ~0;
891
892 /* Work out the maximum sane message length, and return it */
893 if (PREDICT_TRUE (mp != 0))
894 {
895 mb = (msgbuf_t *) (((u8 *) mp) - offsetof (msgbuf_t, data));
896 data_len = clib_net_to_host_u32 (mb->data_len);
897 }
898 return data_len;
899}
900
Dave Barach371e4e12016-07-08 09:38:52 -0400901vl_api_trace_t *
902vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700903{
Dave Barach371e4e12016-07-08 09:38:52 -0400904 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700905 {
906 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400907 return am->rx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700908 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400909 return am->tx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700910 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400911 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700912 }
913}
914
Dave Barach371e4e12016-07-08 09:38:52 -0400915void
916vl_noop_handler (void *mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700917{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700918}
919
Ed Warnickecb9cada2015-12-08 15:45:58 -0700920
921static u8 post_mortem_dump_enabled;
922
Dave Barach80f54e22017-03-08 19:08:56 -0500923void
924vl_msg_api_post_mortem_dump_enable_disable (int enable)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700925{
Dave Barach80f54e22017-03-08 19:08:56 -0500926 post_mortem_dump_enabled = enable;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700927}
928
Dave Barach371e4e12016-07-08 09:38:52 -0400929void
930vl_msg_api_post_mortem_dump (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700931{
Dave Barach39d69112019-11-27 11:42:13 -0500932 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400933 FILE *fp;
934 char filename[64];
935 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700936
Dave Barach371e4e12016-07-08 09:38:52 -0400937 if (post_mortem_dump_enabled == 0)
938 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700939
Dave Barach371e4e12016-07-08 09:38:52 -0400940 snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
941 getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942
Dave Barach371e4e12016-07-08 09:38:52 -0400943 fp = fopen (filename, "w");
944 if (fp == NULL)
945 {
946 rv = write (2, "Couldn't create ", 16);
947 rv = write (2, filename, strlen (filename));
948 rv = write (2, "\n", 1);
949 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700950 }
Filip Tehlar36217e32021-07-23 08:51:10 +0000951 rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp, 0);
Dave Barach371e4e12016-07-08 09:38:52 -0400952 fclose (fp);
953 if (rv < 0)
954 {
955 rv = write (2, "Failed to save post-mortem API trace to ", 40);
956 rv = write (2, filename, strlen (filename));
957 rv = write (2, "\n", 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700958 }
Dave Barach371e4e12016-07-08 09:38:52 -0400959
Ed Warnickecb9cada2015-12-08 15:45:58 -0700960}
961
962/* Layered message handling support */
963
Dave Barach371e4e12016-07-08 09:38:52 -0400964void
Dave Barach371e4e12016-07-08 09:38:52 -0400965vl_msg_api_set_first_available_msg_id (u16 first_avail)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700966{
Dave Barach39d69112019-11-27 11:42:13 -0500967 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400968
969 am->first_available_msg_id = first_avail;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700970}
971
Dave Barach371e4e12016-07-08 09:38:52 -0400972u16
Neale Rannse72be392017-04-26 13:59:20 -0700973vl_msg_api_get_msg_ids (const char *name, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700974{
Dave Barach39d69112019-11-27 11:42:13 -0500975 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400976 u8 *name_copy;
977 vl_api_msg_range_t *rp;
978 uword *p;
979 u16 rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700980
Dave Barach371e4e12016-07-08 09:38:52 -0400981 if (am->msg_range_by_name == 0)
982 am->msg_range_by_name = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700983
Dave Barach371e4e12016-07-08 09:38:52 -0400984 name_copy = format (0, "%s%c", name, 0);
985
986 p = hash_get_mem (am->msg_range_by_name, name_copy);
987 if (p)
988 {
989 clib_warning ("WARNING: duplicate message range registration for '%s'",
990 name_copy);
991 vec_free (name_copy);
992 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700993 }
994
Dave Barach371e4e12016-07-08 09:38:52 -0400995 if (n < 0 || n > 1024)
996 {
997 clib_warning
998 ("WARNING: bad number of message-IDs (%d) requested by '%s'",
999 n, name_copy);
1000 vec_free (name_copy);
1001 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001002 }
1003
Dave Barach371e4e12016-07-08 09:38:52 -04001004 vec_add2 (am->msg_ranges, rp, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001005
Dave Barach371e4e12016-07-08 09:38:52 -04001006 rv = rp->first_msg_id = am->first_available_msg_id;
1007 am->first_available_msg_id += n;
1008 rp->last_msg_id = am->first_available_msg_id - 1;
1009 rp->name = name_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001010
Dave Barach371e4e12016-07-08 09:38:52 -04001011 hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001012
Dave Barach371e4e12016-07-08 09:38:52 -04001013 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001014}
Dave Barach371e4e12016-07-08 09:38:52 -04001015
Dave Barach557d1282016-11-10 14:22:49 -05001016void
Neale Rannse72be392017-04-26 13:59:20 -07001017vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
Dave Barach557d1282016-11-10 14:22:49 -05001018{
1019 uword *p;
1020
1021 if (am->msg_index_by_name_and_crc == 0)
1022 am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
1023
1024 p = hash_get_mem (am->msg_index_by_name_and_crc, string);
1025 if (p)
1026 {
1027 clib_warning ("attempt to redefine '%s' ignored...", string);
1028 return;
1029 }
1030
1031 hash_set_mem (am->msg_index_by_name_and_crc, string, id);
1032}
1033
Dave Barach0d056e52017-09-28 15:11:16 -04001034void
1035vl_msg_api_add_version (api_main_t * am, const char *string,
1036 u32 major, u32 minor, u32 patch)
1037{
1038 api_version_t version = {.major = major,.minor = minor,.patch = patch };
1039 ASSERT (strlen (string) < 64);
Ole Troan7504e992017-10-10 08:43:35 +02001040 strncpy (version.name, string, 64 - 1);
Dave Barach0d056e52017-09-28 15:11:16 -04001041 vec_add1 (am->api_version_list, version);
1042}
Dave Barach557d1282016-11-10 14:22:49 -05001043
Florin Corase86a8ed2018-01-05 03:20:25 -08001044u32
1045vl_msg_api_get_msg_index (u8 * name_and_crc)
1046{
Dave Barach39d69112019-11-27 11:42:13 -05001047 api_main_t *am = vlibapi_get_main ();
Florin Corase86a8ed2018-01-05 03:20:25 -08001048 uword *p;
1049
1050 if (am->msg_index_by_name_and_crc)
1051 {
1052 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
1053 if (p)
1054 return p[0];
1055 }
1056 return ~0;
1057}
1058
Ole Troan73710c72018-06-04 22:27:49 +02001059void *
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001060vl_msg_push_heap_w_region (svm_region_t * vlib_rp)
1061{
1062 pthread_mutex_lock (&vlib_rp->mutex);
1063 return svm_push_data_heap (vlib_rp);
1064}
1065
1066void *
Ole Troan73710c72018-06-04 22:27:49 +02001067vl_msg_push_heap (void)
1068{
Dave Barach39d69112019-11-27 11:42:13 -05001069 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001070 return vl_msg_push_heap_w_region (am->vlib_rp);
1071}
1072
1073void
1074vl_msg_pop_heap_w_region (svm_region_t * vlib_rp, void *oldheap)
1075{
1076 svm_pop_heap (oldheap);
1077 pthread_mutex_unlock (&vlib_rp->mutex);
Ole Troan73710c72018-06-04 22:27:49 +02001078}
1079
1080void
1081vl_msg_pop_heap (void *oldheap)
1082{
Dave Barach39d69112019-11-27 11:42:13 -05001083 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001084 vl_msg_pop_heap_w_region (am->vlib_rp, oldheap);
Ole Troan73710c72018-06-04 22:27:49 +02001085}
1086
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001087/* Must be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001088int
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001089vl_api_c_string_to_api_string (const char *buf, vl_api_string_t * str)
Neale Ranns377860a2019-06-21 07:57:18 -07001090{
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001091 /* copy without nul terminator */
1092 u32 len = strlen (buf);
1093 if (len > 0)
Ole Troan33a58172019-09-04 09:12:29 +02001094 clib_memcpy_fast (str->buf, buf, len);
Neale Ranns377860a2019-06-21 07:57:18 -07001095 str->length = htonl (len);
1096 return len + sizeof (u32);
1097}
1098
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001099/* Must NOT be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001100int
1101vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
1102{
1103 u32 len = vec_len (vec);
1104 clib_memcpy (str->buf, vec, len);
1105 str->length = htonl (len);
1106 return len + sizeof (u32);
1107}
1108
Neale Ranns377860a2019-06-21 07:57:18 -07001109u32
1110vl_api_string_len (vl_api_string_t * astr)
1111{
Dave Barach9683c1e2019-07-01 09:42:41 -04001112 return clib_net_to_host_u32 (astr->length);
Neale Ranns377860a2019-06-21 07:57:18 -07001113}
1114
Ole Troan33a58172019-09-04 09:12:29 +02001115u8 *
1116vl_api_format_string (u8 * s, va_list * args)
1117{
1118 vl_api_string_t *a = va_arg (*args, vl_api_string_t *);
1119 vec_add (s, a->buf, clib_net_to_host_u32 (a->length));
1120 return s;
1121}
1122
Neale Ranns377860a2019-06-21 07:57:18 -07001123/*
1124 * Returns a new vector. Remember to free it after use.
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001125 * NOT nul terminated.
Neale Ranns377860a2019-06-21 07:57:18 -07001126 */
1127u8 *
Dave Barach77841402020-04-29 17:04:10 -04001128vl_api_from_api_to_new_vec (void *mp, vl_api_string_t * astr)
Neale Ranns377860a2019-06-21 07:57:18 -07001129{
1130 u8 *v = 0;
Dave Barach77841402020-04-29 17:04:10 -04001131
1132 if (vl_msg_api_max_length (mp) < clib_net_to_host_u32 (astr->length))
1133 return format (0, "insane astr->length %u%c",
1134 clib_net_to_host_u32 (astr->length), 0);
Dave Barach9683c1e2019-07-01 09:42:41 -04001135 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
Neale Ranns377860a2019-06-21 07:57:18 -07001136 return v;
1137}
Ole Troan73710c72018-06-04 22:27:49 +02001138
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001139/*
1140 * Returns a new vector. Remember to free it after use.
1141 * Nul terminated.
1142 */
1143char *
1144vl_api_from_api_to_new_c_string (vl_api_string_t * astr)
1145{
1146 char *v = 0;
1147 if (clib_net_to_host_u32 (astr->length) > 0)
1148 {
1149 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
1150 vec_add1 (v, 0);
1151 }
1152 return v;
1153}
1154
Dave Barachb09f4d02019-07-15 16:00:03 -04001155void
1156vl_api_set_elog_main (elog_main_t * m)
1157{
Dave Barach39d69112019-11-27 11:42:13 -05001158 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001159 am->elog_main = m;
1160}
1161
1162int
1163vl_api_set_elog_trace_api_messages (int enable)
1164{
1165 int rv;
Dave Barach39d69112019-11-27 11:42:13 -05001166 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001167
1168 rv = am->elog_trace_api_messages;
1169 am->elog_trace_api_messages = enable;
1170 return rv;
1171}
1172
1173int
1174vl_api_get_elog_trace_api_messages (void)
1175{
Dave Barach39d69112019-11-27 11:42:13 -05001176 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001177
1178 return am->elog_trace_api_messages;
1179}
1180
Dave Barach371e4e12016-07-08 09:38:52 -04001181/*
1182 * fd.io coding-style-patch-verification: ON
1183 *
1184 * Local Variables:
1185 * eval: (c-set-style "gnu")
1186 * End:
1187 */