blob: ce7c4aec712473170795c0744831b3b70203f4df [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
Ole Troanedfe2c02019-07-30 15:38:13 +0200192u8 *
193vl_api_serialize_message_table (api_main_t * am, u8 * vector)
194{
195 serialize_main_t _sm, *sm = &_sm;
196 hash_pair_t *hp;
197 u32 nmsg = hash_elts (am->msg_index_by_name_and_crc);
198
199 serialize_open_vector (sm, vector);
200
201 /* serialize the count */
202 serialize_integer (sm, nmsg, sizeof (u32));
203
204 /* *INDENT-OFF* */
205 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
206 ({
207 serialize_likely_small_unsigned_integer (sm, hp->value[0]);
208 serialize_cstring (sm, (char *) hp->key);
209 }));
210 /* *INDENT-ON* */
211
212 return serialize_close_vector (sm);
213}
214
Dave Barach371e4e12016-07-08 09:38:52 -0400215int
216vl_msg_api_trace_save (api_main_t * am, vl_api_trace_which_t which, FILE * fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700217{
Dave Barach371e4e12016-07-08 09:38:52 -0400218 vl_api_trace_t *tp;
219 vl_api_trace_file_header_t fh;
220 int i;
221 u8 *msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222
Dave Barach371e4e12016-07-08 09:38:52 -0400223 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700224 {
225 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400226 tp = am->tx_trace;
227 break;
228
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400230 tp = am->rx_trace;
231 break;
232
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400234 /* duh? */
235 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700236 }
237
Dave Barach371e4e12016-07-08 09:38:52 -0400238 /* Configured, data present? */
239 if (tp == 0 || tp->nitems == 0 || vec_len (tp->traces) == 0)
240 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700241
Dave Barach371e4e12016-07-08 09:38:52 -0400242 /* "Dare to be stupid" check */
243 if (fp == 0)
244 {
245 return -2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700246 }
247
Dave Barach371e4e12016-07-08 09:38:52 -0400248 /* Write the file header */
Dave Barach371e4e12016-07-08 09:38:52 -0400249 fh.wrapped = tp->wrapped;
Ole Troanedfe2c02019-07-30 15:38:13 +0200250 fh.nitems = clib_host_to_net_u32 (vec_len (tp->traces));
251 u8 *m = vl_api_serialize_message_table (am, 0);
252 clib_warning ("Message table length %d", vec_len (m));
253 fh.msgtbl_size = clib_host_to_net_u32 (vec_len (m));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254
Dave Barach371e4e12016-07-08 09:38:52 -0400255 if (fwrite (&fh, sizeof (fh), 1, fp) != 1)
256 {
257 return (-10);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700258 }
259
Ole Troanedfe2c02019-07-30 15:38:13 +0200260 /* Write the message table */
261 if (fwrite (m, vec_len (m), 1, fp) != 1)
262 {
263 return (-14);
264 }
265 vec_free (m);
266
Dave Barach371e4e12016-07-08 09:38:52 -0400267 /* No-wrap case */
268 if (tp->wrapped == 0)
269 {
270 /*
271 * Note: vec_len return 0 when fed a NULL pointer.
272 * Unfortunately, the static analysis tool doesn't
273 * figure it out, hence the suppressed warnings.
274 * What a great use of my time.
275 */
276 for (i = 0; i < vec_len (tp->traces); i++)
277 {
Dave Barach072f8de2016-12-02 13:31:25 -0500278 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400279 /*sa_ignore NO_NULL_CHK */
280 msg = tp->traces[i];
281 /*
282 * This retarded check required to pass
283 * [sic] SA-checking.
284 */
285 if (!msg)
286 continue;
Dave Barach072f8de2016-12-02 13:31:25 -0500287
288 msg_length = clib_host_to_net_u32 (vec_len (msg));
289 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
290 != sizeof (msg_length))
291 {
292 return (-14);
293 }
Dave Barach371e4e12016-07-08 09:38:52 -0400294 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
295 {
296 return (-11);
297 }
298 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700299 }
Dave Barach371e4e12016-07-08 09:38:52 -0400300 else
301 {
302 /* Wrap case: write oldest -> end of buffer */
303 for (i = tp->curindex; i < vec_len (tp->traces); i++)
304 {
Dave Barach072f8de2016-12-02 13:31:25 -0500305 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400306 msg = tp->traces[i];
307 /*
308 * This retarded check required to pass
309 * [sic] SA-checking
310 */
311 if (!msg)
312 continue;
313
Dave Barach072f8de2016-12-02 13:31:25 -0500314 msg_length = clib_host_to_net_u32 (vec_len (msg));
315 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
316 != sizeof (msg_length))
317 {
318 return (-14);
319 }
320
Dave Barach371e4e12016-07-08 09:38:52 -0400321 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
322 {
323 return (-12);
324 }
325 }
326 /* write beginning of buffer -> oldest-1 */
327 for (i = 0; i < tp->curindex; i++)
328 {
Dave Barach072f8de2016-12-02 13:31:25 -0500329 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400330 /*sa_ignore NO_NULL_CHK */
331 msg = tp->traces[i];
332 /*
333 * This retarded check required to pass
334 * [sic] SA-checking
335 */
336 if (!msg)
337 continue;
338
Dave Barach072f8de2016-12-02 13:31:25 -0500339 msg_length = clib_host_to_net_u32 (vec_len (msg));
340 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
341 != sizeof (msg_length))
342 {
343 return (-14);
344 }
345
Dave Barach371e4e12016-07-08 09:38:52 -0400346 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
347 {
348 return (-13);
349 }
350 }
351 }
352 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700353}
354
Dave Barach371e4e12016-07-08 09:38:52 -0400355int
356vl_msg_api_trace_configure (api_main_t * am, vl_api_trace_which_t which,
357 u32 nitems)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358{
Dave Barach371e4e12016-07-08 09:38:52 -0400359 vl_api_trace_t *tp;
360 int was_on = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700361
Dave Barach371e4e12016-07-08 09:38:52 -0400362 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363 {
364 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400365 tp = am->tx_trace;
366 if (tp == 0)
367 {
368 vec_validate (am->tx_trace, 0);
369 tp = am->tx_trace;
370 }
371 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700372
Dave Barach371e4e12016-07-08 09:38:52 -0400373 case VL_API_TRACE_RX:
374 tp = am->rx_trace;
375 if (tp == 0)
376 {
377 vec_validate (am->rx_trace, 0);
378 tp = am->rx_trace;
379 }
380
381 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382
383 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400384 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700385
386 }
387
Dave Barach371e4e12016-07-08 09:38:52 -0400388 if (tp->enabled)
389 {
390 was_on = vl_msg_api_trace_onoff (am, which, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700391 }
Dave Barach371e4e12016-07-08 09:38:52 -0400392 if (tp->traces)
393 {
394 vl_msg_api_trace_free (am, which);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395 }
396
Dave Barachb7b92992018-10-17 10:38:51 -0400397 clib_memset (tp, 0, sizeof (*tp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700398
Dave Barach371e4e12016-07-08 09:38:52 -0400399 if (clib_arch_is_big_endian)
400 {
401 tp->endian = VL_API_BIG_ENDIAN;
402 }
403 else
404 {
405 tp->endian = VL_API_LITTLE_ENDIAN;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406 }
407
Dave Barach371e4e12016-07-08 09:38:52 -0400408 tp->nitems = nitems;
409 if (was_on)
410 {
411 (void) vl_msg_api_trace_onoff (am, which, was_on);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700412 }
Dave Barach371e4e12016-07-08 09:38:52 -0400413 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414}
415
Dave Barach80f54e22017-03-08 19:08:56 -0500416void
417vl_msg_api_barrier_sync (void)
418{
419}
420
421void
422vl_msg_api_barrier_release (void)
423{
424}
425
Dave Barach371e4e12016-07-08 09:38:52 -0400426always_inline void
427msg_handler_internal (api_main_t * am,
428 void *the_msg, int trace_it, int do_it, int free_it)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700429{
Dave Barach9683c1e2019-07-01 09:42:41 -0400430 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400431 u8 *(*print_fp) (void *, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432
Dave Barachb09f4d02019-07-15 16:00:03 -0400433 if (PREDICT_FALSE (am->elog_trace_api_messages))
434 {
435 /* *INDENT-OFF* */
436 ELOG_TYPE_DECLARE (e) =
437 {
438 .format = "api-msg: %s",
439 .format_args = "T4",
440 };
441 /* *INDENT-ON* */
442 struct
443 {
444 u32 c;
445 } *ed;
446 ed = ELOG_DATA (am->elog_main, e);
447 if (id < vec_len (am->msg_names))
448 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
449 else
450 ed->c = elog_string (am->elog_main, "BOGUS");
451 }
452
Dave Barach371e4e12016-07-08 09:38:52 -0400453 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
454 {
455 if (trace_it)
456 vl_msg_api_trace (am, am->rx_trace, the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700457
Dave Barach371e4e12016-07-08 09:38:52 -0400458 if (am->msg_print_flag)
459 {
460 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
461 print_fp = (void *) am->msg_print_handlers[id];
462 if (print_fp == 0)
463 {
464 fformat (stdout, " [no registered print fn]\n");
465 }
466 else
467 {
468 (*print_fp) (the_msg, stdout);
469 }
470 }
471
472 if (do_it)
473 {
474 if (!am->is_mp_safe[id])
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100475 {
476 vl_msg_api_barrier_trace_context (am->msg_names[id]);
477 vl_msg_api_barrier_sync ();
478 }
Dave Barach371e4e12016-07-08 09:38:52 -0400479 (*am->msg_handlers[id]) (the_msg);
480 if (!am->is_mp_safe[id])
481 vl_msg_api_barrier_release ();
482 }
483 }
484 else
485 {
486 clib_warning ("no handler for msg id %d", id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700487 }
488
Dave Barach371e4e12016-07-08 09:38:52 -0400489 if (free_it)
490 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700491
Dave Barachb09f4d02019-07-15 16:00:03 -0400492 if (PREDICT_FALSE (am->elog_trace_api_messages))
493 {
494 /* *INDENT-OFF* */
495 ELOG_TYPE_DECLARE (e) =
496 {
497 .format = "api-msg-done(%s): %s",
498 .format_args = "t4T4",
499 .n_enum_strings = 2,
500 .enum_strings =
501 {
502 "barrier",
503 "mp-safe",
504 }
505 };
506 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700507
Dave Barachb09f4d02019-07-15 16:00:03 -0400508 struct
509 {
510 u32 barrier;
511 u32 c;
512 } *ed;
513 ed = ELOG_DATA (am->elog_main, e);
514 if (id < vec_len (am->msg_names))
Dave Barach67947872019-07-19 09:31:29 -0400515 {
516 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
517 ed->barrier = !am->is_mp_safe[id];
518 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400519 else
Dave Barach67947872019-07-19 09:31:29 -0400520 {
521 ed->c = elog_string (am->elog_main, "BOGUS");
522 ed->barrier = 0;
523 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400524 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700525}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700526
527/* This is only to be called from a vlib/vnet app */
Dave Barach371e4e12016-07-08 09:38:52 -0400528void
529vl_msg_api_handler_with_vm_node (api_main_t * am,
530 void *the_msg, vlib_main_t * vm,
531 vlib_node_runtime_t * node)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700532{
Dave Barach9683c1e2019-07-01 09:42:41 -0400533 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400534 u8 *(*handler) (void *, void *, void *);
ezkexma75f9fb62019-03-21 07:38:19 -0400535 u8 *(*print_fp) (void *, void *);
Dave Barachc898a4f2019-06-14 17:29:55 -0400536 int is_mp_safe = 1;
Dave Barach371e4e12016-07-08 09:38:52 -0400537
Dave Barachb09f4d02019-07-15 16:00:03 -0400538 if (PREDICT_FALSE (am->elog_trace_api_messages))
Dave Barach371e4e12016-07-08 09:38:52 -0400539 {
Dave Barachc3a06552018-10-01 09:25:32 -0400540 /* *INDENT-OFF* */
541 ELOG_TYPE_DECLARE (e) =
542 {
543 .format = "api-msg: %s",
544 .format_args = "T4",
545 };
546 /* *INDENT-ON* */
547 struct
548 {
549 u32 c;
550 } *ed;
Dave Barachb09f4d02019-07-15 16:00:03 -0400551 ed = ELOG_DATA (am->elog_main, e);
Dave Barachc3a06552018-10-01 09:25:32 -0400552 if (id < vec_len (am->msg_names))
Dave Barachb09f4d02019-07-15 16:00:03 -0400553 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
Dave Barachc3a06552018-10-01 09:25:32 -0400554 else
Dave Barachb09f4d02019-07-15 16:00:03 -0400555 ed->c = elog_string (am->elog_main, "BOGUS");
Dave Barachc3a06552018-10-01 09:25:32 -0400556 }
Dave Barach371e4e12016-07-08 09:38:52 -0400557
558 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
559 {
560 handler = (void *) am->msg_handlers[id];
561
ezkexma75f9fb62019-03-21 07:38:19 -0400562 if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled))
Dave Barach371e4e12016-07-08 09:38:52 -0400563 vl_msg_api_trace (am, am->rx_trace, the_msg);
564
ezkexma75f9fb62019-03-21 07:38:19 -0400565 if (PREDICT_FALSE (am->msg_print_flag))
566 {
567 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
568 print_fp = (void *) am->msg_print_handlers[id];
569 if (print_fp == 0)
570 {
571 fformat (stdout, " [no registered print fn for msg %d]\n", id);
572 }
573 else
574 {
575 (*print_fp) (the_msg, vm);
576 }
577 }
Dave Barachc898a4f2019-06-14 17:29:55 -0400578 is_mp_safe = am->is_mp_safe[id];
ezkexma75f9fb62019-03-21 07:38:19 -0400579
Dave Barachc898a4f2019-06-14 17:29:55 -0400580 if (!is_mp_safe)
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100581 {
582 vl_msg_api_barrier_trace_context (am->msg_names[id]);
583 vl_msg_api_barrier_sync ();
584 }
Dave Barach371e4e12016-07-08 09:38:52 -0400585 (*handler) (the_msg, vm, node);
Dave Barachc898a4f2019-06-14 17:29:55 -0400586 if (!is_mp_safe)
Dave Barach371e4e12016-07-08 09:38:52 -0400587 vl_msg_api_barrier_release ();
588 }
589 else
590 {
Jon Loeligerf95b37e2017-02-13 15:21:12 -0600591 clib_warning ("no handler for msg id %d", id);
Dave Barach371e4e12016-07-08 09:38:52 -0400592 }
593
594 /*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700595 * Special-case, so we can e.g. bounce messages off the vnet
596 * main thread without copying them...
597 */
598 if (!(am->message_bounce[id]))
Dave Barach371e4e12016-07-08 09:38:52 -0400599 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700600
Dave Barachb09f4d02019-07-15 16:00:03 -0400601 if (PREDICT_FALSE (am->elog_trace_api_messages))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700602 {
Dave Barachc3a06552018-10-01 09:25:32 -0400603 /* *INDENT-OFF* */
Dave Barachc898a4f2019-06-14 17:29:55 -0400604 ELOG_TYPE_DECLARE (e) =
605 {
606 .format = "api-msg-done(%s): %s",
607 .format_args = "t4T4",
608 .n_enum_strings = 2,
609 .enum_strings =
610 {
611 "barrier",
612 "mp-safe",
613 }
614 };
Dave Barachc3a06552018-10-01 09:25:32 -0400615 /* *INDENT-ON* */
616
617 struct
618 {
Dave Barachc898a4f2019-06-14 17:29:55 -0400619 u32 barrier;
Dave Barachc3a06552018-10-01 09:25:32 -0400620 u32 c;
621 } *ed;
Dave Barachb09f4d02019-07-15 16:00:03 -0400622 ed = ELOG_DATA (am->elog_main, e);
Dave Barachc3a06552018-10-01 09:25:32 -0400623 if (id < vec_len (am->msg_names))
Dave Barachb09f4d02019-07-15 16:00:03 -0400624 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
Dave Barachc3a06552018-10-01 09:25:32 -0400625 else
Dave Barachb09f4d02019-07-15 16:00:03 -0400626 ed->c = elog_string (am->elog_main, "BOGUS");
Dave Barachc898a4f2019-06-14 17:29:55 -0400627 ed->barrier = is_mp_safe;
Dave Barachc3a06552018-10-01 09:25:32 -0400628 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700629}
630
Dave Barach371e4e12016-07-08 09:38:52 -0400631void
632vl_msg_api_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700633{
Dave Barach371e4e12016-07-08 09:38:52 -0400634 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700635
Dave Barach371e4e12016-07-08 09:38:52 -0400636 msg_handler_internal (am, the_msg,
637 (am->rx_trace
638 && am->rx_trace->enabled) /* trace_it */ ,
639 1 /* do_it */ , 1 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700640}
641
Dave Barach371e4e12016-07-08 09:38:52 -0400642void
643vl_msg_api_handler_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700644{
Dave Barach371e4e12016-07-08 09:38:52 -0400645 api_main_t *am = &api_main;
646 msg_handler_internal (am, the_msg,
647 (am->rx_trace
648 && am->rx_trace->enabled) /* trace_it */ ,
649 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700650}
651
Dave Barach371e4e12016-07-08 09:38:52 -0400652void
653vl_msg_api_handler_no_trace_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700654{
Dave Barach371e4e12016-07-08 09:38:52 -0400655 api_main_t *am = &api_main;
656 msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
657 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658}
659
660/*
661 * Add a trace record to the API message trace buffer, if
662 * API message tracing is enabled. Handy for adding sufficient
663 * data to the trace to reproduce autonomous state, as opposed to
Dave Barach371e4e12016-07-08 09:38:52 -0400664 * state downloaded via control-plane API messages. Example: the NAT
Ed Warnickecb9cada2015-12-08 15:45:58 -0700665 * application creates database entries based on packet traffic, not
666 * control-plane messages.
667 *
668 */
Dave Barach371e4e12016-07-08 09:38:52 -0400669void
670vl_msg_api_trace_only (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700671{
Dave Barach371e4e12016-07-08 09:38:52 -0400672 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700673
Dave Barach371e4e12016-07-08 09:38:52 -0400674 msg_handler_internal (am, the_msg,
675 (am->rx_trace
676 && am->rx_trace->enabled) /* trace_it */ ,
677 0 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700678}
679
Dave Barach371e4e12016-07-08 09:38:52 -0400680void
681vl_msg_api_cleanup_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700682{
Dave Barach371e4e12016-07-08 09:38:52 -0400683 api_main_t *am = &api_main;
Dave Barach9683c1e2019-07-01 09:42:41 -0400684 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700685
Dave Barach371e4e12016-07-08 09:38:52 -0400686 if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
687 {
688 clib_warning ("_vl_msg_id too large: %d\n", id);
689 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700690 }
Dave Barach371e4e12016-07-08 09:38:52 -0400691 if (am->msg_cleanup_handlers[id])
692 (*am->msg_cleanup_handlers[id]) (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700693
Dave Barach371e4e12016-07-08 09:38:52 -0400694 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700695}
696
697/*
698 * vl_msg_api_replay_handler
699 */
Dave Barach371e4e12016-07-08 09:38:52 -0400700void
701vl_msg_api_replay_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700702{
Dave Barach371e4e12016-07-08 09:38:52 -0400703 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700704
Dave Barach9683c1e2019-07-01 09:42:41 -0400705 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700706
Dave Barach371e4e12016-07-08 09:38:52 -0400707 if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
708 {
709 clib_warning ("_vl_msg_id too large: %d\n", id);
710 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700711 }
Dave Barach371e4e12016-07-08 09:38:52 -0400712 /* do NOT trace the message... */
713 if (am->msg_handlers[id])
714 (*am->msg_handlers[id]) (the_msg);
715 /* do NOT free the message buffer... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716}
Dave Barach371e4e12016-07-08 09:38:52 -0400717
Dave Barachbfd92272017-05-12 11:59:25 -0400718u32
719vl_msg_api_get_msg_length (void *msg_arg)
720{
721 return vl_msg_api_get_msg_length_inline (msg_arg);
722}
723
Ed Warnickecb9cada2015-12-08 15:45:58 -0700724/*
725 * vl_msg_api_socket_handler
726 */
Dave Barach371e4e12016-07-08 09:38:52 -0400727void
728vl_msg_api_socket_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700729{
Dave Barach371e4e12016-07-08 09:38:52 -0400730 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700731
Dave Barach371e4e12016-07-08 09:38:52 -0400732 msg_handler_internal (am, the_msg,
733 (am->rx_trace
734 && am->rx_trace->enabled) /* trace_it */ ,
735 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700736}
737
738#define foreach_msg_api_vector \
739_(msg_names) \
740_(msg_handlers) \
741_(msg_cleanup_handlers) \
742_(msg_endian_handlers) \
743_(msg_print_handlers) \
744_(api_trace_cfg) \
745_(message_bounce) \
746_(is_mp_safe)
747
Dave Barach371e4e12016-07-08 09:38:52 -0400748void
749vl_msg_api_config (vl_msg_api_msg_config_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700750{
Dave Barach371e4e12016-07-08 09:38:52 -0400751 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700752
Dave Barach65457162017-10-10 17:53:14 -0400753 /*
754 * This happens during the java core tests if the message
755 * dictionary is missing newly added xxx_reply_t messages.
756 * Should never happen, but since I shot myself in the foot once
757 * this way, I thought I'd make it easy to debug if I ever do
758 * it again... (;-)...
759 */
760 if (c->id == 0)
761 {
762 if (c->name)
763 clib_warning ("Trying to register %s with a NULL msg id!", c->name);
764 else
765 clib_warning ("Trying to register a NULL msg with a NULL msg id!");
766 clib_warning ("Did you forget to call setup_message_id_table?");
767 return;
768 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700769
770#define _(a) vec_validate (am->a, c->id);
Dave Barach371e4e12016-07-08 09:38:52 -0400771 foreach_msg_api_vector;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700772#undef _
773
Dave Barach392206e2017-09-20 08:40:16 -0400774 if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
775 clib_warning
776 ("BUG: re-registering 'vl_api_%s_t_handler'."
777 "Handler was %llx, replaced by %llx",
778 c->name, am->msg_handlers[c->id], c->handler);
Dave Baracha1a093d2017-03-02 13:13:23 -0500779
Dave Barach371e4e12016-07-08 09:38:52 -0400780 am->msg_names[c->id] = c->name;
781 am->msg_handlers[c->id] = c->handler;
782 am->msg_cleanup_handlers[c->id] = c->cleanup;
783 am->msg_endian_handlers[c->id] = c->endian;
784 am->msg_print_handlers[c->id] = c->print;
785 am->message_bounce[c->id] = c->message_bounce;
786 am->is_mp_safe[c->id] = c->is_mp_safe;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787
Dave Barach371e4e12016-07-08 09:38:52 -0400788 am->api_trace_cfg[c->id].size = c->size;
789 am->api_trace_cfg[c->id].trace_enable = c->traced;
790 am->api_trace_cfg[c->id].replay_enable = c->replay;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700791}
792
Dave Barach371e4e12016-07-08 09:38:52 -0400793/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700794 * vl_msg_api_set_handlers
795 * preserve the old API for a while
796 */
Dave Barach371e4e12016-07-08 09:38:52 -0400797void
798vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
799 void *endian, void *print, int size, int traced)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700800{
Dave Barach371e4e12016-07-08 09:38:52 -0400801 vl_msg_api_msg_config_t cfg;
802 vl_msg_api_msg_config_t *c = &cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700803
Dave Barachb7b92992018-10-17 10:38:51 -0400804 clib_memset (c, 0, sizeof (*c));
Dave Barach0691d6e2017-01-05 10:08:52 -0500805
Dave Barach371e4e12016-07-08 09:38:52 -0400806 c->id = id;
807 c->name = name;
808 c->handler = handler;
809 c->cleanup = cleanup;
810 c->endian = endian;
811 c->print = print;
Dave Barach371e4e12016-07-08 09:38:52 -0400812 c->traced = traced;
813 c->replay = 1;
814 c->message_bounce = 0;
815 c->is_mp_safe = 0;
816 vl_msg_api_config (c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700817}
818
Dave Barach371e4e12016-07-08 09:38:52 -0400819void
Matej Perina75a17ec2017-09-21 17:03:27 +0200820vl_msg_api_clean_handlers (int msg_id)
821{
822 vl_msg_api_msg_config_t cfg;
823 vl_msg_api_msg_config_t *c = &cfg;
824
Dave Barachb7b92992018-10-17 10:38:51 -0400825 clib_memset (c, 0, sizeof (*c));
Matej Perina75a17ec2017-09-21 17:03:27 +0200826
827 c->id = msg_id;
828 vl_msg_api_config (c);
829}
830
831void
Dave Barach371e4e12016-07-08 09:38:52 -0400832vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700833{
Dave Barach371e4e12016-07-08 09:38:52 -0400834 api_main_t *am = &api_main;
835 ASSERT (msg_id > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700836
Dave Barach371e4e12016-07-08 09:38:52 -0400837 vec_validate (am->msg_cleanup_handlers, msg_id);
838 am->msg_cleanup_handlers[msg_id] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700839}
840
Dave Barach371e4e12016-07-08 09:38:52 -0400841void
Florin Corase86a8ed2018-01-05 03:20:25 -0800842vl_msg_api_queue_handler (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700843{
Dave Barach371e4e12016-07-08 09:38:52 -0400844 uword msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700845
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100846 while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
Dave Barach371e4e12016-07-08 09:38:52 -0400847 vl_msg_api_handler ((void *) msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700848}
849
Dave Barach371e4e12016-07-08 09:38:52 -0400850vl_api_trace_t *
851vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700852{
Dave Barach371e4e12016-07-08 09:38:52 -0400853 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700854 {
855 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400856 return am->rx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700857 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400858 return am->tx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700859 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400860 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700861 }
862}
863
Dave Barach371e4e12016-07-08 09:38:52 -0400864void
865vl_noop_handler (void *mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700866{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700867}
868
Ed Warnickecb9cada2015-12-08 15:45:58 -0700869
870static u8 post_mortem_dump_enabled;
871
Dave Barach80f54e22017-03-08 19:08:56 -0500872void
873vl_msg_api_post_mortem_dump_enable_disable (int enable)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700874{
Dave Barach80f54e22017-03-08 19:08:56 -0500875 post_mortem_dump_enabled = enable;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700876}
877
Dave Barach371e4e12016-07-08 09:38:52 -0400878void
879vl_msg_api_post_mortem_dump (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700880{
Dave Barach371e4e12016-07-08 09:38:52 -0400881 api_main_t *am = &api_main;
882 FILE *fp;
883 char filename[64];
884 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700885
Dave Barach371e4e12016-07-08 09:38:52 -0400886 if (post_mortem_dump_enabled == 0)
887 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700888
Dave Barach371e4e12016-07-08 09:38:52 -0400889 snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
890 getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700891
Dave Barach371e4e12016-07-08 09:38:52 -0400892 fp = fopen (filename, "w");
893 if (fp == NULL)
894 {
895 rv = write (2, "Couldn't create ", 16);
896 rv = write (2, filename, strlen (filename));
897 rv = write (2, "\n", 1);
898 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700899 }
Dave Barach371e4e12016-07-08 09:38:52 -0400900 rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp);
901 fclose (fp);
902 if (rv < 0)
903 {
904 rv = write (2, "Failed to save post-mortem API trace to ", 40);
905 rv = write (2, filename, strlen (filename));
906 rv = write (2, "\n", 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700907 }
Dave Barach371e4e12016-07-08 09:38:52 -0400908
Ed Warnickecb9cada2015-12-08 15:45:58 -0700909}
910
911/* Layered message handling support */
912
Dave Barach371e4e12016-07-08 09:38:52 -0400913void
914vl_msg_api_register_pd_handler (void *fp, u16 msg_id_host_byte_order)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700915{
Dave Barach371e4e12016-07-08 09:38:52 -0400916 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700917
Dave Barach371e4e12016-07-08 09:38:52 -0400918 /* Mild idiot proofing */
919 if (msg_id_host_byte_order > 10000)
920 clib_warning ("msg_id_host_byte_order endian issue? %d arg vs %d",
921 msg_id_host_byte_order,
922 clib_net_to_host_u16 (msg_id_host_byte_order));
923 vec_validate (am->pd_msg_handlers, msg_id_host_byte_order);
924 am->pd_msg_handlers[msg_id_host_byte_order] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700925}
926
Dave Barach371e4e12016-07-08 09:38:52 -0400927int
928vl_msg_api_pd_handler (void *mp, int rv)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700929{
Dave Barach371e4e12016-07-08 09:38:52 -0400930 api_main_t *am = &api_main;
931 int (*fp) (void *, int);
932 u16 msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700933
Dave Barach371e4e12016-07-08 09:38:52 -0400934 if (clib_arch_is_little_endian)
935 msg_id = clib_net_to_host_u16 (*((u16 *) mp));
936 else
937 msg_id = *((u16 *) mp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700938
Dave Barach371e4e12016-07-08 09:38:52 -0400939 if (msg_id >= vec_len (am->pd_msg_handlers)
940 || am->pd_msg_handlers[msg_id] == 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700941 return rv;
Dave Barach371e4e12016-07-08 09:38:52 -0400942
943 fp = am->pd_msg_handlers[msg_id];
944 rv = (*fp) (mp, rv);
945 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700946}
947
Dave Barach371e4e12016-07-08 09:38:52 -0400948void
949vl_msg_api_set_first_available_msg_id (u16 first_avail)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700950{
Dave Barach371e4e12016-07-08 09:38:52 -0400951 api_main_t *am = &api_main;
952
953 am->first_available_msg_id = first_avail;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700954}
955
Dave Barach371e4e12016-07-08 09:38:52 -0400956u16
Neale Rannse72be392017-04-26 13:59:20 -0700957vl_msg_api_get_msg_ids (const char *name, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700958{
Dave Barach371e4e12016-07-08 09:38:52 -0400959 api_main_t *am = &api_main;
960 u8 *name_copy;
961 vl_api_msg_range_t *rp;
962 uword *p;
963 u16 rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700964
Dave Barach371e4e12016-07-08 09:38:52 -0400965 if (am->msg_range_by_name == 0)
966 am->msg_range_by_name = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700967
Dave Barach371e4e12016-07-08 09:38:52 -0400968 name_copy = format (0, "%s%c", name, 0);
969
970 p = hash_get_mem (am->msg_range_by_name, name_copy);
971 if (p)
972 {
973 clib_warning ("WARNING: duplicate message range registration for '%s'",
974 name_copy);
975 vec_free (name_copy);
976 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700977 }
978
Dave Barach371e4e12016-07-08 09:38:52 -0400979 if (n < 0 || n > 1024)
980 {
981 clib_warning
982 ("WARNING: bad number of message-IDs (%d) requested by '%s'",
983 n, name_copy);
984 vec_free (name_copy);
985 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700986 }
987
Dave Barach371e4e12016-07-08 09:38:52 -0400988 vec_add2 (am->msg_ranges, rp, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700989
Dave Barach371e4e12016-07-08 09:38:52 -0400990 rv = rp->first_msg_id = am->first_available_msg_id;
991 am->first_available_msg_id += n;
992 rp->last_msg_id = am->first_available_msg_id - 1;
993 rp->name = name_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700994
Dave Barach371e4e12016-07-08 09:38:52 -0400995 hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700996
Dave Barach371e4e12016-07-08 09:38:52 -0400997 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700998}
Dave Barach371e4e12016-07-08 09:38:52 -0400999
Dave Barach557d1282016-11-10 14:22:49 -05001000void
Neale Rannse72be392017-04-26 13:59:20 -07001001vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
Dave Barach557d1282016-11-10 14:22:49 -05001002{
1003 uword *p;
1004
1005 if (am->msg_index_by_name_and_crc == 0)
1006 am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
1007
1008 p = hash_get_mem (am->msg_index_by_name_and_crc, string);
1009 if (p)
1010 {
1011 clib_warning ("attempt to redefine '%s' ignored...", string);
1012 return;
1013 }
1014
1015 hash_set_mem (am->msg_index_by_name_and_crc, string, id);
1016}
1017
Dave Barach0d056e52017-09-28 15:11:16 -04001018void
1019vl_msg_api_add_version (api_main_t * am, const char *string,
1020 u32 major, u32 minor, u32 patch)
1021{
1022 api_version_t version = {.major = major,.minor = minor,.patch = patch };
1023 ASSERT (strlen (string) < 64);
Ole Troan7504e992017-10-10 08:43:35 +02001024 strncpy (version.name, string, 64 - 1);
Dave Barach0d056e52017-09-28 15:11:16 -04001025 vec_add1 (am->api_version_list, version);
1026}
Dave Barach557d1282016-11-10 14:22:49 -05001027
Florin Corase86a8ed2018-01-05 03:20:25 -08001028u32
1029vl_msg_api_get_msg_index (u8 * name_and_crc)
1030{
1031 api_main_t *am = &api_main;
1032 uword *p;
1033
1034 if (am->msg_index_by_name_and_crc)
1035 {
1036 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
1037 if (p)
1038 return p[0];
1039 }
1040 return ~0;
1041}
1042
Ole Troan73710c72018-06-04 22:27:49 +02001043void *
1044vl_msg_push_heap (void)
1045{
1046 api_main_t *am = &api_main;
1047 pthread_mutex_lock (&am->vlib_rp->mutex);
1048 return svm_push_data_heap (am->vlib_rp);
1049}
1050
1051void
1052vl_msg_pop_heap (void *oldheap)
1053{
1054 api_main_t *am = &api_main;
1055 svm_pop_heap (oldheap);
1056 pthread_mutex_unlock (&am->vlib_rp->mutex);
1057}
1058
Neale Ranns377860a2019-06-21 07:57:18 -07001059int
1060vl_api_to_api_string (u32 len, const char *buf, vl_api_string_t * str)
1061{
1062 clib_memcpy_fast (str->buf, buf, len);
1063 str->length = htonl (len);
1064 return len + sizeof (u32);
1065}
1066
1067int
1068vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
1069{
1070 u32 len = vec_len (vec);
1071 clib_memcpy (str->buf, vec, len);
1072 str->length = htonl (len);
1073 return len + sizeof (u32);
1074}
1075
1076/* Return a pointer to the API string (not nul terminated */
1077u8 *
1078vl_api_from_api_string (vl_api_string_t * astr)
1079{
1080 return astr->buf;
1081}
1082
1083u32
1084vl_api_string_len (vl_api_string_t * astr)
1085{
Dave Barach9683c1e2019-07-01 09:42:41 -04001086 return clib_net_to_host_u32 (astr->length);
Neale Ranns377860a2019-06-21 07:57:18 -07001087}
1088
1089/*
1090 * Returns a new vector. Remember to free it after use.
1091 */
1092u8 *
1093vl_api_from_api_to_vec (vl_api_string_t * astr)
1094{
1095 u8 *v = 0;
Dave Barach9683c1e2019-07-01 09:42:41 -04001096 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
Neale Ranns377860a2019-06-21 07:57:18 -07001097 return v;
1098}
Ole Troan73710c72018-06-04 22:27:49 +02001099
Dave Barachb09f4d02019-07-15 16:00:03 -04001100void
1101vl_api_set_elog_main (elog_main_t * m)
1102{
1103 api_main_t *am = &api_main;
1104 am->elog_main = m;
1105}
1106
1107int
1108vl_api_set_elog_trace_api_messages (int enable)
1109{
1110 int rv;
1111 api_main_t *am = &api_main;
1112
1113 rv = am->elog_trace_api_messages;
1114 am->elog_trace_api_messages = enable;
1115 return rv;
1116}
1117
1118int
1119vl_api_get_elog_trace_api_messages (void)
1120{
1121 api_main_t *am = &api_main;
1122
1123 return am->elog_trace_api_messages;
1124}
1125
Dave Barach371e4e12016-07-08 09:38:52 -04001126/*
1127 * fd.io coding-style-patch-verification: ON
1128 *
1129 * Local Variables:
1130 * eval: (c-set-style "gnu")
1131 * End:
1132 */