blob: 9579fe1c60fc43803fba9fb3b6ef8ef6848f9ad6 [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>
33
Dave Barach80f54e22017-03-08 19:08:56 -050034/* *INDENT-OFF* */
35api_main_t api_main =
36 {
37 .region_name = "/unset",
38 .api_uid = -1,
39 .api_gid = -1,
40 };
41/* *INDENT-ON* */
Dave Barach371e4e12016-07-08 09:38:52 -040042
43void
44vl_msg_api_increment_missing_client_counter (void)
45{
46 api_main_t *am = &api_main;
47 am->missing_clients++;
48}
49
Dave Barach371e4e12016-07-08 09:38:52 -040050int
51vl_msg_api_rx_trace_enabled (api_main_t * am)
Ed Warnickecb9cada2015-12-08 15:45:58 -070052{
Dave Barach371e4e12016-07-08 09:38:52 -040053 return (am->rx_trace && am->rx_trace->enabled);
Ed Warnickecb9cada2015-12-08 15:45:58 -070054}
55
Dave Barach371e4e12016-07-08 09:38:52 -040056int
57vl_msg_api_tx_trace_enabled (api_main_t * am)
Ed Warnickecb9cada2015-12-08 15:45:58 -070058{
Dave Barach371e4e12016-07-08 09:38:52 -040059 return (am->tx_trace && am->tx_trace->enabled);
Ed Warnickecb9cada2015-12-08 15:45:58 -070060}
61
62/*
63 * vl_msg_api_trace
64 */
Dave Barach371e4e12016-07-08 09:38:52 -040065void
66vl_msg_api_trace (api_main_t * am, vl_api_trace_t * tp, void *msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -070067{
Dave Barach371e4e12016-07-08 09:38:52 -040068 u8 **this_trace;
69 u8 **old_trace;
70 u8 *msg_copy;
Dave Barach072f8de2016-12-02 13:31:25 -050071 u32 length;
Dave Barach371e4e12016-07-08 09:38:52 -040072 trace_cfg_t *cfgp;
Dave Barach9683c1e2019-07-01 09:42:41 -040073 u16 msg_id = clib_net_to_host_u16 (*((u16 *) msg));
Dave Barach072f8de2016-12-02 13:31:25 -050074 msgbuf_t *header = (msgbuf_t *) (((u8 *) msg) - offsetof (msgbuf_t, data));
Ed Warnickecb9cada2015-12-08 15:45:58 -070075
Dave Barach371e4e12016-07-08 09:38:52 -040076 cfgp = am->api_trace_cfg + msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -070077
Dave Barach371e4e12016-07-08 09:38:52 -040078 if (!cfgp || !cfgp->trace_enable)
79 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070080
Dave Barach371e4e12016-07-08 09:38:52 -040081 msg_copy = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070082
Dave Barach371e4e12016-07-08 09:38:52 -040083 if (tp->nitems == 0)
84 {
85 clib_warning ("tp->nitems is 0");
86 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070087 }
88
Dave Barach371e4e12016-07-08 09:38:52 -040089 if (vec_len (tp->traces) < tp->nitems)
90 {
91 vec_add1 (tp->traces, 0);
92 this_trace = tp->traces + vec_len (tp->traces) - 1;
93 }
94 else
95 {
96 tp->wrapped = 1;
97 old_trace = tp->traces + tp->curindex++;
98 if (tp->curindex == tp->nitems)
99 tp->curindex = 0;
Dave Barachf35a0722019-06-12 16:50:38 -0400100 /* Reuse the trace record, may save some memory allocator traffic */
101 msg_copy = *old_trace;
102 vec_reset_length (msg_copy);
Dave Barach371e4e12016-07-08 09:38:52 -0400103 this_trace = old_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700104 }
105
Dave Barach072f8de2016-12-02 13:31:25 -0500106 length = clib_net_to_host_u32 (header->data_len);
107
108 vec_validate (msg_copy, length - 1);
Dave Barach178cf492018-11-13 16:34:13 -0500109 clib_memcpy_fast (msg_copy, msg, length);
Dave Barach371e4e12016-07-08 09:38:52 -0400110 *this_trace = msg_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700111}
112
Dave Barach371e4e12016-07-08 09:38:52 -0400113int
114vl_msg_api_trace_onoff (api_main_t * am, vl_api_trace_which_t which,
115 int onoff)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700116{
Dave Barach371e4e12016-07-08 09:38:52 -0400117 vl_api_trace_t *tp;
118 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700119
Dave Barach371e4e12016-07-08 09:38:52 -0400120 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700121 {
122 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400123 tp = am->tx_trace;
124 if (tp == 0)
125 {
126 vl_msg_api_trace_configure (am, which, 1024);
127 tp = am->tx_trace;
128 }
129 break;
130
Ed Warnickecb9cada2015-12-08 15:45:58 -0700131 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400132 tp = am->rx_trace;
133 if (tp == 0)
134 {
135 vl_msg_api_trace_configure (am, which, 1024);
136 tp = am->rx_trace;
137 }
138 break;
139
Ed Warnickecb9cada2015-12-08 15:45:58 -0700140 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400141 /* duh? */
142 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700143 }
144
Dave Barach371e4e12016-07-08 09:38:52 -0400145 /* Configured? */
146 if (tp == 0 || tp->nitems == 0)
147 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700148
Dave Barach371e4e12016-07-08 09:38:52 -0400149 rv = tp->enabled;
150 tp->enabled = onoff;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700151
Dave Barach371e4e12016-07-08 09:38:52 -0400152 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700153}
154
Dave Barach371e4e12016-07-08 09:38:52 -0400155int
156vl_msg_api_trace_free (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700157{
Dave Barach371e4e12016-07-08 09:38:52 -0400158 vl_api_trace_t *tp;
159 int i;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700160
Dave Barach371e4e12016-07-08 09:38:52 -0400161 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700162 {
163 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400164 tp = am->tx_trace;
165 break;
166
Ed Warnickecb9cada2015-12-08 15:45:58 -0700167 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400168 tp = am->rx_trace;
169 break;
170
Ed Warnickecb9cada2015-12-08 15:45:58 -0700171 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400172 /* duh? */
173 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174 }
175
Dave Barach371e4e12016-07-08 09:38:52 -0400176 /* Configured? */
177 if (!tp || tp->nitems == 0)
178 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700179
Dave Barach371e4e12016-07-08 09:38:52 -0400180 tp->curindex = 0;
181 tp->wrapped = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700182
Dave Barach371e4e12016-07-08 09:38:52 -0400183 for (i = 0; i < vec_len (tp->traces); i++)
184 {
185 vec_free (tp->traces[i]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700186 }
Dave Barach371e4e12016-07-08 09:38:52 -0400187 vec_free (tp->traces);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700188
Dave Barach371e4e12016-07-08 09:38:52 -0400189 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700190}
191
Dave Barach371e4e12016-07-08 09:38:52 -0400192int
193vl_msg_api_trace_save (api_main_t * am, vl_api_trace_which_t which, FILE * fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700194{
Dave Barach371e4e12016-07-08 09:38:52 -0400195 vl_api_trace_t *tp;
196 vl_api_trace_file_header_t fh;
197 int i;
198 u8 *msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700199
Dave Barach371e4e12016-07-08 09:38:52 -0400200 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700201 {
202 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400203 tp = am->tx_trace;
204 break;
205
Ed Warnickecb9cada2015-12-08 15:45:58 -0700206 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400207 tp = am->rx_trace;
208 break;
209
Ed Warnickecb9cada2015-12-08 15:45:58 -0700210 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400211 /* duh? */
212 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213 }
214
Dave Barach371e4e12016-07-08 09:38:52 -0400215 /* Configured, data present? */
216 if (tp == 0 || tp->nitems == 0 || vec_len (tp->traces) == 0)
217 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700218
Dave Barach371e4e12016-07-08 09:38:52 -0400219 /* "Dare to be stupid" check */
220 if (fp == 0)
221 {
222 return -2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700223 }
224
Dave Barach371e4e12016-07-08 09:38:52 -0400225 /* Write the file header */
226 fh.nitems = vec_len (tp->traces);
227 fh.endian = tp->endian;
228 fh.wrapped = tp->wrapped;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229
Dave Barach371e4e12016-07-08 09:38:52 -0400230 if (fwrite (&fh, sizeof (fh), 1, fp) != 1)
231 {
232 return (-10);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233 }
234
Dave Barach371e4e12016-07-08 09:38:52 -0400235 /* No-wrap case */
236 if (tp->wrapped == 0)
237 {
238 /*
239 * Note: vec_len return 0 when fed a NULL pointer.
240 * Unfortunately, the static analysis tool doesn't
241 * figure it out, hence the suppressed warnings.
242 * What a great use of my time.
243 */
244 for (i = 0; i < vec_len (tp->traces); i++)
245 {
Dave Barach072f8de2016-12-02 13:31:25 -0500246 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400247 /*sa_ignore NO_NULL_CHK */
248 msg = tp->traces[i];
249 /*
250 * This retarded check required to pass
251 * [sic] SA-checking.
252 */
253 if (!msg)
254 continue;
Dave Barach072f8de2016-12-02 13:31:25 -0500255
256 msg_length = clib_host_to_net_u32 (vec_len (msg));
257 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
258 != sizeof (msg_length))
259 {
260 return (-14);
261 }
Dave Barach371e4e12016-07-08 09:38:52 -0400262 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
263 {
264 return (-11);
265 }
266 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700267 }
Dave Barach371e4e12016-07-08 09:38:52 -0400268 else
269 {
270 /* Wrap case: write oldest -> end of buffer */
271 for (i = tp->curindex; i < vec_len (tp->traces); i++)
272 {
Dave Barach072f8de2016-12-02 13:31:25 -0500273 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400274 msg = tp->traces[i];
275 /*
276 * This retarded check required to pass
277 * [sic] SA-checking
278 */
279 if (!msg)
280 continue;
281
Dave Barach072f8de2016-12-02 13:31:25 -0500282 msg_length = clib_host_to_net_u32 (vec_len (msg));
283 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
284 != sizeof (msg_length))
285 {
286 return (-14);
287 }
288
Dave Barach371e4e12016-07-08 09:38:52 -0400289 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
290 {
291 return (-12);
292 }
293 }
294 /* write beginning of buffer -> oldest-1 */
295 for (i = 0; i < tp->curindex; i++)
296 {
Dave Barach072f8de2016-12-02 13:31:25 -0500297 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400298 /*sa_ignore NO_NULL_CHK */
299 msg = tp->traces[i];
300 /*
301 * This retarded check required to pass
302 * [sic] SA-checking
303 */
304 if (!msg)
305 continue;
306
Dave Barach072f8de2016-12-02 13:31:25 -0500307 msg_length = clib_host_to_net_u32 (vec_len (msg));
308 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
309 != sizeof (msg_length))
310 {
311 return (-14);
312 }
313
Dave Barach371e4e12016-07-08 09:38:52 -0400314 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
315 {
316 return (-13);
317 }
318 }
319 }
320 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700321}
322
Dave Barach371e4e12016-07-08 09:38:52 -0400323int
324vl_msg_api_trace_configure (api_main_t * am, vl_api_trace_which_t which,
325 u32 nitems)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700326{
Dave Barach371e4e12016-07-08 09:38:52 -0400327 vl_api_trace_t *tp;
328 int was_on = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700329
Dave Barach371e4e12016-07-08 09:38:52 -0400330 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331 {
332 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400333 tp = am->tx_trace;
334 if (tp == 0)
335 {
336 vec_validate (am->tx_trace, 0);
337 tp = am->tx_trace;
338 }
339 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700340
Dave Barach371e4e12016-07-08 09:38:52 -0400341 case VL_API_TRACE_RX:
342 tp = am->rx_trace;
343 if (tp == 0)
344 {
345 vec_validate (am->rx_trace, 0);
346 tp = am->rx_trace;
347 }
348
349 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350
351 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400352 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353
354 }
355
Dave Barach371e4e12016-07-08 09:38:52 -0400356 if (tp->enabled)
357 {
358 was_on = vl_msg_api_trace_onoff (am, which, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700359 }
Dave Barach371e4e12016-07-08 09:38:52 -0400360 if (tp->traces)
361 {
362 vl_msg_api_trace_free (am, which);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363 }
364
Dave Barachb7b92992018-10-17 10:38:51 -0400365 clib_memset (tp, 0, sizeof (*tp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700366
Dave Barach371e4e12016-07-08 09:38:52 -0400367 if (clib_arch_is_big_endian)
368 {
369 tp->endian = VL_API_BIG_ENDIAN;
370 }
371 else
372 {
373 tp->endian = VL_API_LITTLE_ENDIAN;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700374 }
375
Dave Barach371e4e12016-07-08 09:38:52 -0400376 tp->nitems = nitems;
377 if (was_on)
378 {
379 (void) vl_msg_api_trace_onoff (am, which, was_on);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700380 }
Dave Barach371e4e12016-07-08 09:38:52 -0400381 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382}
383
Dave Barach80f54e22017-03-08 19:08:56 -0500384void
385vl_msg_api_barrier_sync (void)
386{
387}
388
389void
390vl_msg_api_barrier_release (void)
391{
392}
393
Dave Barach371e4e12016-07-08 09:38:52 -0400394always_inline void
395msg_handler_internal (api_main_t * am,
396 void *the_msg, int trace_it, int do_it, int free_it)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700397{
Dave Barach9683c1e2019-07-01 09:42:41 -0400398 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400399 u8 *(*print_fp) (void *, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400
Dave Barach371e4e12016-07-08 09:38:52 -0400401 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
402 {
403 if (trace_it)
404 vl_msg_api_trace (am, am->rx_trace, the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405
Dave Barach371e4e12016-07-08 09:38:52 -0400406 if (am->msg_print_flag)
407 {
408 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
409 print_fp = (void *) am->msg_print_handlers[id];
410 if (print_fp == 0)
411 {
412 fformat (stdout, " [no registered print fn]\n");
413 }
414 else
415 {
416 (*print_fp) (the_msg, stdout);
417 }
418 }
419
420 if (do_it)
421 {
422 if (!am->is_mp_safe[id])
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100423 {
424 vl_msg_api_barrier_trace_context (am->msg_names[id]);
425 vl_msg_api_barrier_sync ();
426 }
Dave Barach371e4e12016-07-08 09:38:52 -0400427 (*am->msg_handlers[id]) (the_msg);
428 if (!am->is_mp_safe[id])
429 vl_msg_api_barrier_release ();
430 }
431 }
432 else
433 {
434 clib_warning ("no handler for msg id %d", id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700435 }
436
Dave Barach371e4e12016-07-08 09:38:52 -0400437 if (free_it)
438 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700439}
440
Dave Barach371e4e12016-07-08 09:38:52 -0400441static u32
Dave Barachc3a06552018-10-01 09:25:32 -0400442elog_id_for_msg_name (vlib_main_t * vm, const char *msg_name)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700443{
Dave Barach371e4e12016-07-08 09:38:52 -0400444 uword *p, r;
445 static uword *h;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700446 u8 *name_copy;
447
Dave Barach371e4e12016-07-08 09:38:52 -0400448 if (!h)
449 h = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700450
451 p = hash_get_mem (h, msg_name);
452 if (p)
453 return p[0];
454 r = elog_string (&vm->elog_main, "%s", msg_name);
455
456 name_copy = format (0, "%s%c", msg_name, 0);
457
458 hash_set_mem (h, name_copy, r);
459
460 return r;
461}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700462
463/* This is only to be called from a vlib/vnet app */
Dave Barach371e4e12016-07-08 09:38:52 -0400464void
465vl_msg_api_handler_with_vm_node (api_main_t * am,
466 void *the_msg, vlib_main_t * vm,
467 vlib_node_runtime_t * node)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700468{
Dave Barach9683c1e2019-07-01 09:42:41 -0400469 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400470 u8 *(*handler) (void *, void *, void *);
ezkexma75f9fb62019-03-21 07:38:19 -0400471 u8 *(*print_fp) (void *, void *);
Dave Barachc898a4f2019-06-14 17:29:55 -0400472 int is_mp_safe = 1;
Dave Barach371e4e12016-07-08 09:38:52 -0400473
Dave Barachc3a06552018-10-01 09:25:32 -0400474 if (PREDICT_FALSE (vm->elog_trace_api_messages))
Dave Barach371e4e12016-07-08 09:38:52 -0400475 {
Dave Barachc3a06552018-10-01 09:25:32 -0400476 /* *INDENT-OFF* */
477 ELOG_TYPE_DECLARE (e) =
478 {
479 .format = "api-msg: %s",
480 .format_args = "T4",
481 };
482 /* *INDENT-ON* */
483 struct
484 {
485 u32 c;
486 } *ed;
487 ed = ELOG_DATA (&vm->elog_main, e);
488 if (id < vec_len (am->msg_names))
489 ed->c = elog_id_for_msg_name (vm, (const char *) am->msg_names[id]);
490 else
491 ed->c = elog_id_for_msg_name (vm, "BOGUS");
492 }
Dave Barach371e4e12016-07-08 09:38:52 -0400493
494 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
495 {
496 handler = (void *) am->msg_handlers[id];
497
ezkexma75f9fb62019-03-21 07:38:19 -0400498 if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled))
Dave Barach371e4e12016-07-08 09:38:52 -0400499 vl_msg_api_trace (am, am->rx_trace, the_msg);
500
ezkexma75f9fb62019-03-21 07:38:19 -0400501 if (PREDICT_FALSE (am->msg_print_flag))
502 {
503 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
504 print_fp = (void *) am->msg_print_handlers[id];
505 if (print_fp == 0)
506 {
507 fformat (stdout, " [no registered print fn for msg %d]\n", id);
508 }
509 else
510 {
511 (*print_fp) (the_msg, vm);
512 }
513 }
Dave Barachc898a4f2019-06-14 17:29:55 -0400514 is_mp_safe = am->is_mp_safe[id];
ezkexma75f9fb62019-03-21 07:38:19 -0400515
Dave Barachc898a4f2019-06-14 17:29:55 -0400516 if (!is_mp_safe)
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100517 {
518 vl_msg_api_barrier_trace_context (am->msg_names[id]);
519 vl_msg_api_barrier_sync ();
520 }
Dave Barach371e4e12016-07-08 09:38:52 -0400521 (*handler) (the_msg, vm, node);
Dave Barachc898a4f2019-06-14 17:29:55 -0400522 if (!is_mp_safe)
Dave Barach371e4e12016-07-08 09:38:52 -0400523 vl_msg_api_barrier_release ();
524 }
525 else
526 {
Jon Loeligerf95b37e2017-02-13 15:21:12 -0600527 clib_warning ("no handler for msg id %d", id);
Dave Barach371e4e12016-07-08 09:38:52 -0400528 }
529
530 /*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700531 * Special-case, so we can e.g. bounce messages off the vnet
532 * main thread without copying them...
533 */
534 if (!(am->message_bounce[id]))
Dave Barach371e4e12016-07-08 09:38:52 -0400535 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700536
Dave Barachc3a06552018-10-01 09:25:32 -0400537 if (PREDICT_FALSE (vm->elog_trace_api_messages))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700538 {
Dave Barachc3a06552018-10-01 09:25:32 -0400539 /* *INDENT-OFF* */
Dave Barachc898a4f2019-06-14 17:29:55 -0400540 ELOG_TYPE_DECLARE (e) =
541 {
542 .format = "api-msg-done(%s): %s",
543 .format_args = "t4T4",
544 .n_enum_strings = 2,
545 .enum_strings =
546 {
547 "barrier",
548 "mp-safe",
549 }
550 };
Dave Barachc3a06552018-10-01 09:25:32 -0400551 /* *INDENT-ON* */
552
553 struct
554 {
Dave Barachc898a4f2019-06-14 17:29:55 -0400555 u32 barrier;
Dave Barachc3a06552018-10-01 09:25:32 -0400556 u32 c;
557 } *ed;
558 ed = ELOG_DATA (&vm->elog_main, e);
559 if (id < vec_len (am->msg_names))
560 ed->c = elog_id_for_msg_name (vm, (const char *) am->msg_names[id]);
561 else
562 ed->c = elog_id_for_msg_name (vm, "BOGUS");
Dave Barachc898a4f2019-06-14 17:29:55 -0400563 ed->barrier = is_mp_safe;
Dave Barachc3a06552018-10-01 09:25:32 -0400564 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700565}
566
Dave Barach371e4e12016-07-08 09:38:52 -0400567void
568vl_msg_api_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700569{
Dave Barach371e4e12016-07-08 09:38:52 -0400570 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700571
Dave Barach371e4e12016-07-08 09:38:52 -0400572 msg_handler_internal (am, the_msg,
573 (am->rx_trace
574 && am->rx_trace->enabled) /* trace_it */ ,
575 1 /* do_it */ , 1 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700576}
577
Dave Barach371e4e12016-07-08 09:38:52 -0400578void
579vl_msg_api_handler_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580{
Dave Barach371e4e12016-07-08 09:38:52 -0400581 api_main_t *am = &api_main;
582 msg_handler_internal (am, the_msg,
583 (am->rx_trace
584 && am->rx_trace->enabled) /* trace_it */ ,
585 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700586}
587
Dave Barach371e4e12016-07-08 09:38:52 -0400588void
589vl_msg_api_handler_no_trace_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700590{
Dave Barach371e4e12016-07-08 09:38:52 -0400591 api_main_t *am = &api_main;
592 msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
593 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700594}
595
596/*
597 * Add a trace record to the API message trace buffer, if
598 * API message tracing is enabled. Handy for adding sufficient
599 * data to the trace to reproduce autonomous state, as opposed to
Dave Barach371e4e12016-07-08 09:38:52 -0400600 * state downloaded via control-plane API messages. Example: the NAT
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601 * application creates database entries based on packet traffic, not
602 * control-plane messages.
603 *
604 */
Dave Barach371e4e12016-07-08 09:38:52 -0400605void
606vl_msg_api_trace_only (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700607{
Dave Barach371e4e12016-07-08 09:38:52 -0400608 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700609
Dave Barach371e4e12016-07-08 09:38:52 -0400610 msg_handler_internal (am, the_msg,
611 (am->rx_trace
612 && am->rx_trace->enabled) /* trace_it */ ,
613 0 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700614}
615
Dave Barach371e4e12016-07-08 09:38:52 -0400616void
617vl_msg_api_cleanup_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700618{
Dave Barach371e4e12016-07-08 09:38:52 -0400619 api_main_t *am = &api_main;
Dave Barach9683c1e2019-07-01 09:42:41 -0400620 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700621
Dave Barach371e4e12016-07-08 09:38:52 -0400622 if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
623 {
624 clib_warning ("_vl_msg_id too large: %d\n", id);
625 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700626 }
Dave Barach371e4e12016-07-08 09:38:52 -0400627 if (am->msg_cleanup_handlers[id])
628 (*am->msg_cleanup_handlers[id]) (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700629
Dave Barach371e4e12016-07-08 09:38:52 -0400630 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700631}
632
633/*
634 * vl_msg_api_replay_handler
635 */
Dave Barach371e4e12016-07-08 09:38:52 -0400636void
637vl_msg_api_replay_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700638{
Dave Barach371e4e12016-07-08 09:38:52 -0400639 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700640
Dave Barach9683c1e2019-07-01 09:42:41 -0400641 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700642
Dave Barach371e4e12016-07-08 09:38:52 -0400643 if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
644 {
645 clib_warning ("_vl_msg_id too large: %d\n", id);
646 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700647 }
Dave Barach371e4e12016-07-08 09:38:52 -0400648 /* do NOT trace the message... */
649 if (am->msg_handlers[id])
650 (*am->msg_handlers[id]) (the_msg);
651 /* do NOT free the message buffer... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700652}
Dave Barach371e4e12016-07-08 09:38:52 -0400653
Dave Barachbfd92272017-05-12 11:59:25 -0400654u32
655vl_msg_api_get_msg_length (void *msg_arg)
656{
657 return vl_msg_api_get_msg_length_inline (msg_arg);
658}
659
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660/*
661 * vl_msg_api_socket_handler
662 */
Dave Barach371e4e12016-07-08 09:38:52 -0400663void
664vl_msg_api_socket_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665{
Dave Barach371e4e12016-07-08 09:38:52 -0400666 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700667
Dave Barach371e4e12016-07-08 09:38:52 -0400668 msg_handler_internal (am, the_msg,
669 (am->rx_trace
670 && am->rx_trace->enabled) /* trace_it */ ,
671 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700672}
673
674#define foreach_msg_api_vector \
675_(msg_names) \
676_(msg_handlers) \
677_(msg_cleanup_handlers) \
678_(msg_endian_handlers) \
679_(msg_print_handlers) \
680_(api_trace_cfg) \
681_(message_bounce) \
682_(is_mp_safe)
683
Dave Barach371e4e12016-07-08 09:38:52 -0400684void
685vl_msg_api_config (vl_msg_api_msg_config_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700686{
Dave Barach371e4e12016-07-08 09:38:52 -0400687 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700688
Dave Barach65457162017-10-10 17:53:14 -0400689 /*
690 * This happens during the java core tests if the message
691 * dictionary is missing newly added xxx_reply_t messages.
692 * Should never happen, but since I shot myself in the foot once
693 * this way, I thought I'd make it easy to debug if I ever do
694 * it again... (;-)...
695 */
696 if (c->id == 0)
697 {
698 if (c->name)
699 clib_warning ("Trying to register %s with a NULL msg id!", c->name);
700 else
701 clib_warning ("Trying to register a NULL msg with a NULL msg id!");
702 clib_warning ("Did you forget to call setup_message_id_table?");
703 return;
704 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700705
706#define _(a) vec_validate (am->a, c->id);
Dave Barach371e4e12016-07-08 09:38:52 -0400707 foreach_msg_api_vector;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700708#undef _
709
Dave Barach392206e2017-09-20 08:40:16 -0400710 if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
711 clib_warning
712 ("BUG: re-registering 'vl_api_%s_t_handler'."
713 "Handler was %llx, replaced by %llx",
714 c->name, am->msg_handlers[c->id], c->handler);
Dave Baracha1a093d2017-03-02 13:13:23 -0500715
Dave Barach371e4e12016-07-08 09:38:52 -0400716 am->msg_names[c->id] = c->name;
717 am->msg_handlers[c->id] = c->handler;
718 am->msg_cleanup_handlers[c->id] = c->cleanup;
719 am->msg_endian_handlers[c->id] = c->endian;
720 am->msg_print_handlers[c->id] = c->print;
721 am->message_bounce[c->id] = c->message_bounce;
722 am->is_mp_safe[c->id] = c->is_mp_safe;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700723
Dave Barach371e4e12016-07-08 09:38:52 -0400724 am->api_trace_cfg[c->id].size = c->size;
725 am->api_trace_cfg[c->id].trace_enable = c->traced;
726 am->api_trace_cfg[c->id].replay_enable = c->replay;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700727}
728
Dave Barach371e4e12016-07-08 09:38:52 -0400729/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700730 * vl_msg_api_set_handlers
731 * preserve the old API for a while
732 */
Dave Barach371e4e12016-07-08 09:38:52 -0400733void
734vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
735 void *endian, void *print, int size, int traced)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700736{
Dave Barach371e4e12016-07-08 09:38:52 -0400737 vl_msg_api_msg_config_t cfg;
738 vl_msg_api_msg_config_t *c = &cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700739
Dave Barachb7b92992018-10-17 10:38:51 -0400740 clib_memset (c, 0, sizeof (*c));
Dave Barach0691d6e2017-01-05 10:08:52 -0500741
Dave Barach371e4e12016-07-08 09:38:52 -0400742 c->id = id;
743 c->name = name;
744 c->handler = handler;
745 c->cleanup = cleanup;
746 c->endian = endian;
747 c->print = print;
Dave Barach371e4e12016-07-08 09:38:52 -0400748 c->traced = traced;
749 c->replay = 1;
750 c->message_bounce = 0;
751 c->is_mp_safe = 0;
752 vl_msg_api_config (c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700753}
754
Dave Barach371e4e12016-07-08 09:38:52 -0400755void
Matej Perina75a17ec2017-09-21 17:03:27 +0200756vl_msg_api_clean_handlers (int msg_id)
757{
758 vl_msg_api_msg_config_t cfg;
759 vl_msg_api_msg_config_t *c = &cfg;
760
Dave Barachb7b92992018-10-17 10:38:51 -0400761 clib_memset (c, 0, sizeof (*c));
Matej Perina75a17ec2017-09-21 17:03:27 +0200762
763 c->id = msg_id;
764 vl_msg_api_config (c);
765}
766
767void
Dave Barach371e4e12016-07-08 09:38:52 -0400768vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700769{
Dave Barach371e4e12016-07-08 09:38:52 -0400770 api_main_t *am = &api_main;
771 ASSERT (msg_id > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700772
Dave Barach371e4e12016-07-08 09:38:52 -0400773 vec_validate (am->msg_cleanup_handlers, msg_id);
774 am->msg_cleanup_handlers[msg_id] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700775}
776
Dave Barach371e4e12016-07-08 09:38:52 -0400777void
Florin Corase86a8ed2018-01-05 03:20:25 -0800778vl_msg_api_queue_handler (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700779{
Dave Barach371e4e12016-07-08 09:38:52 -0400780 uword msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700781
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100782 while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
Dave Barach371e4e12016-07-08 09:38:52 -0400783 vl_msg_api_handler ((void *) msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700784}
785
Dave Barach371e4e12016-07-08 09:38:52 -0400786vl_api_trace_t *
787vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700788{
Dave Barach371e4e12016-07-08 09:38:52 -0400789 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700790 {
791 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400792 return am->rx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700793 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400794 return am->tx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700795 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400796 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700797 }
798}
799
Dave Barach371e4e12016-07-08 09:38:52 -0400800void
801vl_noop_handler (void *mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700802{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700803}
804
Ed Warnickecb9cada2015-12-08 15:45:58 -0700805
806static u8 post_mortem_dump_enabled;
807
Dave Barach80f54e22017-03-08 19:08:56 -0500808void
809vl_msg_api_post_mortem_dump_enable_disable (int enable)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700810{
Dave Barach80f54e22017-03-08 19:08:56 -0500811 post_mortem_dump_enabled = enable;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700812}
813
Dave Barach371e4e12016-07-08 09:38:52 -0400814void
815vl_msg_api_post_mortem_dump (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700816{
Dave Barach371e4e12016-07-08 09:38:52 -0400817 api_main_t *am = &api_main;
818 FILE *fp;
819 char filename[64];
820 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700821
Dave Barach371e4e12016-07-08 09:38:52 -0400822 if (post_mortem_dump_enabled == 0)
823 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700824
Dave Barach371e4e12016-07-08 09:38:52 -0400825 snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
826 getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700827
Dave Barach371e4e12016-07-08 09:38:52 -0400828 fp = fopen (filename, "w");
829 if (fp == NULL)
830 {
831 rv = write (2, "Couldn't create ", 16);
832 rv = write (2, filename, strlen (filename));
833 rv = write (2, "\n", 1);
834 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700835 }
Dave Barach371e4e12016-07-08 09:38:52 -0400836 rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp);
837 fclose (fp);
838 if (rv < 0)
839 {
840 rv = write (2, "Failed to save post-mortem API trace to ", 40);
841 rv = write (2, filename, strlen (filename));
842 rv = write (2, "\n", 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700843 }
Dave Barach371e4e12016-07-08 09:38:52 -0400844
Ed Warnickecb9cada2015-12-08 15:45:58 -0700845}
846
847/* Layered message handling support */
848
Dave Barach371e4e12016-07-08 09:38:52 -0400849void
850vl_msg_api_register_pd_handler (void *fp, u16 msg_id_host_byte_order)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700851{
Dave Barach371e4e12016-07-08 09:38:52 -0400852 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700853
Dave Barach371e4e12016-07-08 09:38:52 -0400854 /* Mild idiot proofing */
855 if (msg_id_host_byte_order > 10000)
856 clib_warning ("msg_id_host_byte_order endian issue? %d arg vs %d",
857 msg_id_host_byte_order,
858 clib_net_to_host_u16 (msg_id_host_byte_order));
859 vec_validate (am->pd_msg_handlers, msg_id_host_byte_order);
860 am->pd_msg_handlers[msg_id_host_byte_order] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700861}
862
Dave Barach371e4e12016-07-08 09:38:52 -0400863int
864vl_msg_api_pd_handler (void *mp, int rv)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700865{
Dave Barach371e4e12016-07-08 09:38:52 -0400866 api_main_t *am = &api_main;
867 int (*fp) (void *, int);
868 u16 msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700869
Dave Barach371e4e12016-07-08 09:38:52 -0400870 if (clib_arch_is_little_endian)
871 msg_id = clib_net_to_host_u16 (*((u16 *) mp));
872 else
873 msg_id = *((u16 *) mp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700874
Dave Barach371e4e12016-07-08 09:38:52 -0400875 if (msg_id >= vec_len (am->pd_msg_handlers)
876 || am->pd_msg_handlers[msg_id] == 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700877 return rv;
Dave Barach371e4e12016-07-08 09:38:52 -0400878
879 fp = am->pd_msg_handlers[msg_id];
880 rv = (*fp) (mp, rv);
881 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700882}
883
Dave Barach371e4e12016-07-08 09:38:52 -0400884void
885vl_msg_api_set_first_available_msg_id (u16 first_avail)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700886{
Dave Barach371e4e12016-07-08 09:38:52 -0400887 api_main_t *am = &api_main;
888
889 am->first_available_msg_id = first_avail;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700890}
891
Dave Barach371e4e12016-07-08 09:38:52 -0400892u16
Neale Rannse72be392017-04-26 13:59:20 -0700893vl_msg_api_get_msg_ids (const char *name, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700894{
Dave Barach371e4e12016-07-08 09:38:52 -0400895 api_main_t *am = &api_main;
896 u8 *name_copy;
897 vl_api_msg_range_t *rp;
898 uword *p;
899 u16 rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700900
Dave Barach371e4e12016-07-08 09:38:52 -0400901 if (am->msg_range_by_name == 0)
902 am->msg_range_by_name = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700903
Dave Barach371e4e12016-07-08 09:38:52 -0400904 name_copy = format (0, "%s%c", name, 0);
905
906 p = hash_get_mem (am->msg_range_by_name, name_copy);
907 if (p)
908 {
909 clib_warning ("WARNING: duplicate message range registration for '%s'",
910 name_copy);
911 vec_free (name_copy);
912 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700913 }
914
Dave Barach371e4e12016-07-08 09:38:52 -0400915 if (n < 0 || n > 1024)
916 {
917 clib_warning
918 ("WARNING: bad number of message-IDs (%d) requested by '%s'",
919 n, name_copy);
920 vec_free (name_copy);
921 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700922 }
923
Dave Barach371e4e12016-07-08 09:38:52 -0400924 vec_add2 (am->msg_ranges, rp, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700925
Dave Barach371e4e12016-07-08 09:38:52 -0400926 rv = rp->first_msg_id = am->first_available_msg_id;
927 am->first_available_msg_id += n;
928 rp->last_msg_id = am->first_available_msg_id - 1;
929 rp->name = name_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700930
Dave Barach371e4e12016-07-08 09:38:52 -0400931 hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700932
Dave Barach371e4e12016-07-08 09:38:52 -0400933 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700934}
Dave Barach371e4e12016-07-08 09:38:52 -0400935
Dave Barach557d1282016-11-10 14:22:49 -0500936void
Neale Rannse72be392017-04-26 13:59:20 -0700937vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
Dave Barach557d1282016-11-10 14:22:49 -0500938{
939 uword *p;
940
941 if (am->msg_index_by_name_and_crc == 0)
942 am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
943
944 p = hash_get_mem (am->msg_index_by_name_and_crc, string);
945 if (p)
946 {
947 clib_warning ("attempt to redefine '%s' ignored...", string);
948 return;
949 }
950
951 hash_set_mem (am->msg_index_by_name_and_crc, string, id);
952}
953
Dave Barach0d056e52017-09-28 15:11:16 -0400954void
955vl_msg_api_add_version (api_main_t * am, const char *string,
956 u32 major, u32 minor, u32 patch)
957{
958 api_version_t version = {.major = major,.minor = minor,.patch = patch };
959 ASSERT (strlen (string) < 64);
Ole Troan7504e992017-10-10 08:43:35 +0200960 strncpy (version.name, string, 64 - 1);
Dave Barach0d056e52017-09-28 15:11:16 -0400961 vec_add1 (am->api_version_list, version);
962}
Dave Barach557d1282016-11-10 14:22:49 -0500963
Florin Corase86a8ed2018-01-05 03:20:25 -0800964u32
965vl_msg_api_get_msg_index (u8 * name_and_crc)
966{
967 api_main_t *am = &api_main;
968 uword *p;
969
970 if (am->msg_index_by_name_and_crc)
971 {
972 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
973 if (p)
974 return p[0];
975 }
976 return ~0;
977}
978
Ole Troan73710c72018-06-04 22:27:49 +0200979void *
980vl_msg_push_heap (void)
981{
982 api_main_t *am = &api_main;
983 pthread_mutex_lock (&am->vlib_rp->mutex);
984 return svm_push_data_heap (am->vlib_rp);
985}
986
987void
988vl_msg_pop_heap (void *oldheap)
989{
990 api_main_t *am = &api_main;
991 svm_pop_heap (oldheap);
992 pthread_mutex_unlock (&am->vlib_rp->mutex);
993}
994
Neale Ranns377860a2019-06-21 07:57:18 -0700995int
996vl_api_to_api_string (u32 len, const char *buf, vl_api_string_t * str)
997{
998 clib_memcpy_fast (str->buf, buf, len);
999 str->length = htonl (len);
1000 return len + sizeof (u32);
1001}
1002
1003int
1004vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
1005{
1006 u32 len = vec_len (vec);
1007 clib_memcpy (str->buf, vec, len);
1008 str->length = htonl (len);
1009 return len + sizeof (u32);
1010}
1011
1012/* Return a pointer to the API string (not nul terminated */
1013u8 *
1014vl_api_from_api_string (vl_api_string_t * astr)
1015{
1016 return astr->buf;
1017}
1018
1019u32
1020vl_api_string_len (vl_api_string_t * astr)
1021{
Dave Barach9683c1e2019-07-01 09:42:41 -04001022 return clib_net_to_host_u32 (astr->length);
Neale Ranns377860a2019-06-21 07:57:18 -07001023}
1024
1025/*
1026 * Returns a new vector. Remember to free it after use.
1027 */
1028u8 *
1029vl_api_from_api_to_vec (vl_api_string_t * astr)
1030{
1031 u8 *v = 0;
Dave Barach9683c1e2019-07-01 09:42:41 -04001032 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
Neale Ranns377860a2019-06-21 07:57:18 -07001033 return v;
1034}
Ole Troan73710c72018-06-04 22:27:49 +02001035
Dave Barach371e4e12016-07-08 09:38:52 -04001036/*
1037 * fd.io coding-style-patch-verification: ON
1038 *
1039 * Local Variables:
1040 * eval: (c-set-style "gnu")
1041 * End:
1042 */