blob: 1e7f5c420c6fbeeedd6d328ff2c0d15256fe7903 [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);
Ole Troanedfe2c02019-07-30 15:38:13 +0200252 fh.msgtbl_size = clib_host_to_net_u32 (vec_len (m));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253
Dave Barach371e4e12016-07-08 09:38:52 -0400254 if (fwrite (&fh, sizeof (fh), 1, fp) != 1)
255 {
256 return (-10);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700257 }
258
Ole Troanedfe2c02019-07-30 15:38:13 +0200259 /* Write the message table */
260 if (fwrite (m, vec_len (m), 1, fp) != 1)
261 {
262 return (-14);
263 }
264 vec_free (m);
265
Dave Barach371e4e12016-07-08 09:38:52 -0400266 /* No-wrap case */
267 if (tp->wrapped == 0)
268 {
269 /*
270 * Note: vec_len return 0 when fed a NULL pointer.
271 * Unfortunately, the static analysis tool doesn't
272 * figure it out, hence the suppressed warnings.
273 * What a great use of my time.
274 */
275 for (i = 0; i < vec_len (tp->traces); i++)
276 {
Dave Barach072f8de2016-12-02 13:31:25 -0500277 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400278 /*sa_ignore NO_NULL_CHK */
279 msg = tp->traces[i];
280 /*
281 * This retarded check required to pass
282 * [sic] SA-checking.
283 */
284 if (!msg)
285 continue;
Dave Barach072f8de2016-12-02 13:31:25 -0500286
287 msg_length = clib_host_to_net_u32 (vec_len (msg));
288 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
289 != sizeof (msg_length))
290 {
291 return (-14);
292 }
Dave Barach371e4e12016-07-08 09:38:52 -0400293 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
294 {
295 return (-11);
296 }
297 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700298 }
Dave Barach371e4e12016-07-08 09:38:52 -0400299 else
300 {
301 /* Wrap case: write oldest -> end of buffer */
302 for (i = tp->curindex; i < vec_len (tp->traces); i++)
303 {
Dave Barach072f8de2016-12-02 13:31:25 -0500304 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400305 msg = tp->traces[i];
306 /*
307 * This retarded check required to pass
308 * [sic] SA-checking
309 */
310 if (!msg)
311 continue;
312
Dave Barach072f8de2016-12-02 13:31:25 -0500313 msg_length = clib_host_to_net_u32 (vec_len (msg));
314 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
315 != sizeof (msg_length))
316 {
317 return (-14);
318 }
319
Dave Barach371e4e12016-07-08 09:38:52 -0400320 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
321 {
322 return (-12);
323 }
324 }
325 /* write beginning of buffer -> oldest-1 */
326 for (i = 0; i < tp->curindex; i++)
327 {
Dave Barach072f8de2016-12-02 13:31:25 -0500328 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400329 /*sa_ignore NO_NULL_CHK */
330 msg = tp->traces[i];
331 /*
332 * This retarded check required to pass
333 * [sic] SA-checking
334 */
335 if (!msg)
336 continue;
337
Dave Barach072f8de2016-12-02 13:31:25 -0500338 msg_length = clib_host_to_net_u32 (vec_len (msg));
339 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
340 != sizeof (msg_length))
341 {
342 return (-14);
343 }
344
Dave Barach371e4e12016-07-08 09:38:52 -0400345 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
346 {
347 return (-13);
348 }
349 }
350 }
351 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700352}
353
Dave Barach371e4e12016-07-08 09:38:52 -0400354int
355vl_msg_api_trace_configure (api_main_t * am, vl_api_trace_which_t which,
356 u32 nitems)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700357{
Dave Barach371e4e12016-07-08 09:38:52 -0400358 vl_api_trace_t *tp;
359 int was_on = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360
Dave Barach371e4e12016-07-08 09:38:52 -0400361 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700362 {
363 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400364 tp = am->tx_trace;
365 if (tp == 0)
366 {
367 vec_validate (am->tx_trace, 0);
368 tp = am->tx_trace;
369 }
370 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700371
Dave Barach371e4e12016-07-08 09:38:52 -0400372 case VL_API_TRACE_RX:
373 tp = am->rx_trace;
374 if (tp == 0)
375 {
376 vec_validate (am->rx_trace, 0);
377 tp = am->rx_trace;
378 }
379
380 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700381
382 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400383 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700384
385 }
386
Dave Barach371e4e12016-07-08 09:38:52 -0400387 if (tp->enabled)
388 {
389 was_on = vl_msg_api_trace_onoff (am, which, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390 }
Dave Barach371e4e12016-07-08 09:38:52 -0400391 if (tp->traces)
392 {
393 vl_msg_api_trace_free (am, which);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700394 }
395
Dave Barachb7b92992018-10-17 10:38:51 -0400396 clib_memset (tp, 0, sizeof (*tp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700397
Dave Barach371e4e12016-07-08 09:38:52 -0400398 if (clib_arch_is_big_endian)
399 {
400 tp->endian = VL_API_BIG_ENDIAN;
401 }
402 else
403 {
404 tp->endian = VL_API_LITTLE_ENDIAN;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 }
406
Dave Barach371e4e12016-07-08 09:38:52 -0400407 tp->nitems = nitems;
408 if (was_on)
409 {
410 (void) vl_msg_api_trace_onoff (am, which, was_on);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700411 }
Dave Barach371e4e12016-07-08 09:38:52 -0400412 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700413}
414
Dave Barach80f54e22017-03-08 19:08:56 -0500415void
416vl_msg_api_barrier_sync (void)
417{
418}
419
420void
421vl_msg_api_barrier_release (void)
422{
423}
424
Dave Barach371e4e12016-07-08 09:38:52 -0400425always_inline void
426msg_handler_internal (api_main_t * am,
427 void *the_msg, int trace_it, int do_it, int free_it)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700428{
Dave Barach9683c1e2019-07-01 09:42:41 -0400429 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400430 u8 *(*print_fp) (void *, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700431
Dave Barachb09f4d02019-07-15 16:00:03 -0400432 if (PREDICT_FALSE (am->elog_trace_api_messages))
433 {
434 /* *INDENT-OFF* */
435 ELOG_TYPE_DECLARE (e) =
436 {
437 .format = "api-msg: %s",
438 .format_args = "T4",
439 };
440 /* *INDENT-ON* */
441 struct
442 {
443 u32 c;
444 } *ed;
445 ed = ELOG_DATA (am->elog_main, e);
446 if (id < vec_len (am->msg_names))
447 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
448 else
449 ed->c = elog_string (am->elog_main, "BOGUS");
450 }
451
Dave Barach371e4e12016-07-08 09:38:52 -0400452 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
453 {
454 if (trace_it)
455 vl_msg_api_trace (am, am->rx_trace, the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700456
Dave Barach371e4e12016-07-08 09:38:52 -0400457 if (am->msg_print_flag)
458 {
459 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
460 print_fp = (void *) am->msg_print_handlers[id];
461 if (print_fp == 0)
462 {
463 fformat (stdout, " [no registered print fn]\n");
464 }
465 else
466 {
467 (*print_fp) (the_msg, stdout);
468 }
469 }
470
471 if (do_it)
472 {
473 if (!am->is_mp_safe[id])
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100474 {
475 vl_msg_api_barrier_trace_context (am->msg_names[id]);
476 vl_msg_api_barrier_sync ();
477 }
Dave Barach371e4e12016-07-08 09:38:52 -0400478 (*am->msg_handlers[id]) (the_msg);
479 if (!am->is_mp_safe[id])
480 vl_msg_api_barrier_release ();
481 }
482 }
483 else
484 {
485 clib_warning ("no handler for msg id %d", id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700486 }
487
Dave Barach371e4e12016-07-08 09:38:52 -0400488 if (free_it)
489 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700490
Dave Barachb09f4d02019-07-15 16:00:03 -0400491 if (PREDICT_FALSE (am->elog_trace_api_messages))
492 {
493 /* *INDENT-OFF* */
494 ELOG_TYPE_DECLARE (e) =
495 {
496 .format = "api-msg-done(%s): %s",
497 .format_args = "t4T4",
498 .n_enum_strings = 2,
499 .enum_strings =
500 {
501 "barrier",
502 "mp-safe",
503 }
504 };
505 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700506
Dave Barachb09f4d02019-07-15 16:00:03 -0400507 struct
508 {
509 u32 barrier;
510 u32 c;
511 } *ed;
512 ed = ELOG_DATA (am->elog_main, e);
513 if (id < vec_len (am->msg_names))
Dave Barach67947872019-07-19 09:31:29 -0400514 {
515 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
516 ed->barrier = !am->is_mp_safe[id];
517 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400518 else
Dave Barach67947872019-07-19 09:31:29 -0400519 {
520 ed->c = elog_string (am->elog_main, "BOGUS");
521 ed->barrier = 0;
522 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400523 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700524}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700525
526/* This is only to be called from a vlib/vnet app */
Dave Barach371e4e12016-07-08 09:38:52 -0400527void
528vl_msg_api_handler_with_vm_node (api_main_t * am,
529 void *the_msg, vlib_main_t * vm,
530 vlib_node_runtime_t * node)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700531{
Dave Barach9683c1e2019-07-01 09:42:41 -0400532 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400533 u8 *(*handler) (void *, void *, void *);
ezkexma75f9fb62019-03-21 07:38:19 -0400534 u8 *(*print_fp) (void *, void *);
Dave Barachc898a4f2019-06-14 17:29:55 -0400535 int is_mp_safe = 1;
Dave Barach371e4e12016-07-08 09:38:52 -0400536
Dave Barachb09f4d02019-07-15 16:00:03 -0400537 if (PREDICT_FALSE (am->elog_trace_api_messages))
Dave Barach371e4e12016-07-08 09:38:52 -0400538 {
Dave Barachc3a06552018-10-01 09:25:32 -0400539 /* *INDENT-OFF* */
540 ELOG_TYPE_DECLARE (e) =
541 {
542 .format = "api-msg: %s",
543 .format_args = "T4",
544 };
545 /* *INDENT-ON* */
546 struct
547 {
548 u32 c;
549 } *ed;
Dave Barachb09f4d02019-07-15 16:00:03 -0400550 ed = ELOG_DATA (am->elog_main, e);
Dave Barachc3a06552018-10-01 09:25:32 -0400551 if (id < vec_len (am->msg_names))
Dave Barachb09f4d02019-07-15 16:00:03 -0400552 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
Dave Barachc3a06552018-10-01 09:25:32 -0400553 else
Dave Barachb09f4d02019-07-15 16:00:03 -0400554 ed->c = elog_string (am->elog_main, "BOGUS");
Dave Barachc3a06552018-10-01 09:25:32 -0400555 }
Dave Barach371e4e12016-07-08 09:38:52 -0400556
557 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
558 {
559 handler = (void *) am->msg_handlers[id];
560
ezkexma75f9fb62019-03-21 07:38:19 -0400561 if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled))
Dave Barach371e4e12016-07-08 09:38:52 -0400562 vl_msg_api_trace (am, am->rx_trace, the_msg);
563
ezkexma75f9fb62019-03-21 07:38:19 -0400564 if (PREDICT_FALSE (am->msg_print_flag))
565 {
566 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
567 print_fp = (void *) am->msg_print_handlers[id];
568 if (print_fp == 0)
569 {
570 fformat (stdout, " [no registered print fn for msg %d]\n", id);
571 }
572 else
573 {
574 (*print_fp) (the_msg, vm);
575 }
576 }
Dave Barachc898a4f2019-06-14 17:29:55 -0400577 is_mp_safe = am->is_mp_safe[id];
ezkexma75f9fb62019-03-21 07:38:19 -0400578
Dave Barachc898a4f2019-06-14 17:29:55 -0400579 if (!is_mp_safe)
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100580 {
581 vl_msg_api_barrier_trace_context (am->msg_names[id]);
582 vl_msg_api_barrier_sync ();
583 }
Dave Barach371e4e12016-07-08 09:38:52 -0400584 (*handler) (the_msg, vm, node);
Dave Barachc898a4f2019-06-14 17:29:55 -0400585 if (!is_mp_safe)
Dave Barach371e4e12016-07-08 09:38:52 -0400586 vl_msg_api_barrier_release ();
587 }
588 else
589 {
Jon Loeligerf95b37e2017-02-13 15:21:12 -0600590 clib_warning ("no handler for msg id %d", id);
Dave Barach371e4e12016-07-08 09:38:52 -0400591 }
592
593 /*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700594 * Special-case, so we can e.g. bounce messages off the vnet
595 * main thread without copying them...
596 */
597 if (!(am->message_bounce[id]))
Dave Barach371e4e12016-07-08 09:38:52 -0400598 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700599
Dave Barachb09f4d02019-07-15 16:00:03 -0400600 if (PREDICT_FALSE (am->elog_trace_api_messages))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601 {
Dave Barachc3a06552018-10-01 09:25:32 -0400602 /* *INDENT-OFF* */
Dave Barachc898a4f2019-06-14 17:29:55 -0400603 ELOG_TYPE_DECLARE (e) =
604 {
605 .format = "api-msg-done(%s): %s",
606 .format_args = "t4T4",
607 .n_enum_strings = 2,
608 .enum_strings =
609 {
610 "barrier",
611 "mp-safe",
612 }
613 };
Dave Barachc3a06552018-10-01 09:25:32 -0400614 /* *INDENT-ON* */
615
616 struct
617 {
Dave Barachc898a4f2019-06-14 17:29:55 -0400618 u32 barrier;
Dave Barachc3a06552018-10-01 09:25:32 -0400619 u32 c;
620 } *ed;
Dave Barachb09f4d02019-07-15 16:00:03 -0400621 ed = ELOG_DATA (am->elog_main, e);
Dave Barachc3a06552018-10-01 09:25:32 -0400622 if (id < vec_len (am->msg_names))
Dave Barachb09f4d02019-07-15 16:00:03 -0400623 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
Dave Barachc3a06552018-10-01 09:25:32 -0400624 else
Dave Barachb09f4d02019-07-15 16:00:03 -0400625 ed->c = elog_string (am->elog_main, "BOGUS");
Dave Barachc898a4f2019-06-14 17:29:55 -0400626 ed->barrier = is_mp_safe;
Dave Barachc3a06552018-10-01 09:25:32 -0400627 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700628}
629
Dave Barach371e4e12016-07-08 09:38:52 -0400630void
631vl_msg_api_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700632{
Dave Barach371e4e12016-07-08 09:38:52 -0400633 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700634
Dave Barach371e4e12016-07-08 09:38:52 -0400635 msg_handler_internal (am, the_msg,
636 (am->rx_trace
637 && am->rx_trace->enabled) /* trace_it */ ,
638 1 /* do_it */ , 1 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700639}
640
Dave Barach371e4e12016-07-08 09:38:52 -0400641void
642vl_msg_api_handler_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700643{
Dave Barach371e4e12016-07-08 09:38:52 -0400644 api_main_t *am = &api_main;
645 msg_handler_internal (am, the_msg,
646 (am->rx_trace
647 && am->rx_trace->enabled) /* trace_it */ ,
648 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700649}
650
Dave Barach371e4e12016-07-08 09:38:52 -0400651void
652vl_msg_api_handler_no_trace_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700653{
Dave Barach371e4e12016-07-08 09:38:52 -0400654 api_main_t *am = &api_main;
655 msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
656 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700657}
658
659/*
660 * Add a trace record to the API message trace buffer, if
661 * API message tracing is enabled. Handy for adding sufficient
662 * data to the trace to reproduce autonomous state, as opposed to
Dave Barach371e4e12016-07-08 09:38:52 -0400663 * state downloaded via control-plane API messages. Example: the NAT
Ed Warnickecb9cada2015-12-08 15:45:58 -0700664 * application creates database entries based on packet traffic, not
665 * control-plane messages.
666 *
667 */
Dave Barach371e4e12016-07-08 09:38:52 -0400668void
669vl_msg_api_trace_only (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700670{
Dave Barach371e4e12016-07-08 09:38:52 -0400671 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700672
Dave Barach371e4e12016-07-08 09:38:52 -0400673 msg_handler_internal (am, the_msg,
674 (am->rx_trace
675 && am->rx_trace->enabled) /* trace_it */ ,
676 0 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700677}
678
Dave Barach371e4e12016-07-08 09:38:52 -0400679void
680vl_msg_api_cleanup_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700681{
Dave Barach371e4e12016-07-08 09:38:52 -0400682 api_main_t *am = &api_main;
Dave Barach9683c1e2019-07-01 09:42:41 -0400683 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700684
Dave Barach371e4e12016-07-08 09:38:52 -0400685 if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
686 {
687 clib_warning ("_vl_msg_id too large: %d\n", id);
688 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700689 }
Dave Barach371e4e12016-07-08 09:38:52 -0400690 if (am->msg_cleanup_handlers[id])
691 (*am->msg_cleanup_handlers[id]) (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700692
Dave Barach371e4e12016-07-08 09:38:52 -0400693 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700694}
695
696/*
697 * vl_msg_api_replay_handler
698 */
Dave Barach371e4e12016-07-08 09:38:52 -0400699void
700vl_msg_api_replay_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701{
Dave Barach371e4e12016-07-08 09:38:52 -0400702 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700703
Dave Barach9683c1e2019-07-01 09:42:41 -0400704 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700705
Dave Barach371e4e12016-07-08 09:38:52 -0400706 if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
707 {
708 clib_warning ("_vl_msg_id too large: %d\n", id);
709 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700710 }
Dave Barach371e4e12016-07-08 09:38:52 -0400711 /* do NOT trace the message... */
712 if (am->msg_handlers[id])
713 (*am->msg_handlers[id]) (the_msg);
714 /* do NOT free the message buffer... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700715}
Dave Barach371e4e12016-07-08 09:38:52 -0400716
Dave Barachbfd92272017-05-12 11:59:25 -0400717u32
718vl_msg_api_get_msg_length (void *msg_arg)
719{
720 return vl_msg_api_get_msg_length_inline (msg_arg);
721}
722
Ed Warnickecb9cada2015-12-08 15:45:58 -0700723/*
724 * vl_msg_api_socket_handler
725 */
Dave Barach371e4e12016-07-08 09:38:52 -0400726void
727vl_msg_api_socket_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700728{
Dave Barach371e4e12016-07-08 09:38:52 -0400729 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700730
Dave Barach371e4e12016-07-08 09:38:52 -0400731 msg_handler_internal (am, the_msg,
732 (am->rx_trace
733 && am->rx_trace->enabled) /* trace_it */ ,
734 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700735}
736
737#define foreach_msg_api_vector \
738_(msg_names) \
739_(msg_handlers) \
740_(msg_cleanup_handlers) \
741_(msg_endian_handlers) \
742_(msg_print_handlers) \
743_(api_trace_cfg) \
744_(message_bounce) \
745_(is_mp_safe)
746
Dave Barach371e4e12016-07-08 09:38:52 -0400747void
748vl_msg_api_config (vl_msg_api_msg_config_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700749{
Dave Barach371e4e12016-07-08 09:38:52 -0400750 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700751
Dave Barach65457162017-10-10 17:53:14 -0400752 /*
753 * This happens during the java core tests if the message
754 * dictionary is missing newly added xxx_reply_t messages.
755 * Should never happen, but since I shot myself in the foot once
756 * this way, I thought I'd make it easy to debug if I ever do
757 * it again... (;-)...
758 */
759 if (c->id == 0)
760 {
761 if (c->name)
762 clib_warning ("Trying to register %s with a NULL msg id!", c->name);
763 else
764 clib_warning ("Trying to register a NULL msg with a NULL msg id!");
765 clib_warning ("Did you forget to call setup_message_id_table?");
766 return;
767 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700768
769#define _(a) vec_validate (am->a, c->id);
Dave Barach371e4e12016-07-08 09:38:52 -0400770 foreach_msg_api_vector;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700771#undef _
772
Dave Barach392206e2017-09-20 08:40:16 -0400773 if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
774 clib_warning
775 ("BUG: re-registering 'vl_api_%s_t_handler'."
776 "Handler was %llx, replaced by %llx",
777 c->name, am->msg_handlers[c->id], c->handler);
Dave Baracha1a093d2017-03-02 13:13:23 -0500778
Dave Barach371e4e12016-07-08 09:38:52 -0400779 am->msg_names[c->id] = c->name;
780 am->msg_handlers[c->id] = c->handler;
781 am->msg_cleanup_handlers[c->id] = c->cleanup;
782 am->msg_endian_handlers[c->id] = c->endian;
783 am->msg_print_handlers[c->id] = c->print;
784 am->message_bounce[c->id] = c->message_bounce;
785 am->is_mp_safe[c->id] = c->is_mp_safe;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700786
Dave Barach371e4e12016-07-08 09:38:52 -0400787 am->api_trace_cfg[c->id].size = c->size;
788 am->api_trace_cfg[c->id].trace_enable = c->traced;
789 am->api_trace_cfg[c->id].replay_enable = c->replay;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700790}
791
Dave Barach371e4e12016-07-08 09:38:52 -0400792/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700793 * vl_msg_api_set_handlers
794 * preserve the old API for a while
795 */
Dave Barach371e4e12016-07-08 09:38:52 -0400796void
797vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
798 void *endian, void *print, int size, int traced)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700799{
Dave Barach371e4e12016-07-08 09:38:52 -0400800 vl_msg_api_msg_config_t cfg;
801 vl_msg_api_msg_config_t *c = &cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700802
Dave Barachb7b92992018-10-17 10:38:51 -0400803 clib_memset (c, 0, sizeof (*c));
Dave Barach0691d6e2017-01-05 10:08:52 -0500804
Dave Barach371e4e12016-07-08 09:38:52 -0400805 c->id = id;
806 c->name = name;
807 c->handler = handler;
808 c->cleanup = cleanup;
809 c->endian = endian;
810 c->print = print;
Dave Barach371e4e12016-07-08 09:38:52 -0400811 c->traced = traced;
812 c->replay = 1;
813 c->message_bounce = 0;
814 c->is_mp_safe = 0;
815 vl_msg_api_config (c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700816}
817
Dave Barach371e4e12016-07-08 09:38:52 -0400818void
Matej Perina75a17ec2017-09-21 17:03:27 +0200819vl_msg_api_clean_handlers (int msg_id)
820{
821 vl_msg_api_msg_config_t cfg;
822 vl_msg_api_msg_config_t *c = &cfg;
823
Dave Barachb7b92992018-10-17 10:38:51 -0400824 clib_memset (c, 0, sizeof (*c));
Matej Perina75a17ec2017-09-21 17:03:27 +0200825
826 c->id = msg_id;
827 vl_msg_api_config (c);
828}
829
830void
Dave Barach371e4e12016-07-08 09:38:52 -0400831vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700832{
Dave Barach371e4e12016-07-08 09:38:52 -0400833 api_main_t *am = &api_main;
834 ASSERT (msg_id > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700835
Dave Barach371e4e12016-07-08 09:38:52 -0400836 vec_validate (am->msg_cleanup_handlers, msg_id);
837 am->msg_cleanup_handlers[msg_id] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700838}
839
Dave Barach371e4e12016-07-08 09:38:52 -0400840void
Florin Corase86a8ed2018-01-05 03:20:25 -0800841vl_msg_api_queue_handler (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700842{
Dave Barach371e4e12016-07-08 09:38:52 -0400843 uword msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700844
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100845 while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
Dave Barach371e4e12016-07-08 09:38:52 -0400846 vl_msg_api_handler ((void *) msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700847}
848
Dave Barach371e4e12016-07-08 09:38:52 -0400849vl_api_trace_t *
850vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700851{
Dave Barach371e4e12016-07-08 09:38:52 -0400852 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700853 {
854 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400855 return am->rx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700856 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400857 return am->tx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700858 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400859 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700860 }
861}
862
Dave Barach371e4e12016-07-08 09:38:52 -0400863void
864vl_noop_handler (void *mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700865{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700866}
867
Ed Warnickecb9cada2015-12-08 15:45:58 -0700868
869static u8 post_mortem_dump_enabled;
870
Dave Barach80f54e22017-03-08 19:08:56 -0500871void
872vl_msg_api_post_mortem_dump_enable_disable (int enable)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700873{
Dave Barach80f54e22017-03-08 19:08:56 -0500874 post_mortem_dump_enabled = enable;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700875}
876
Dave Barach371e4e12016-07-08 09:38:52 -0400877void
878vl_msg_api_post_mortem_dump (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700879{
Dave Barach371e4e12016-07-08 09:38:52 -0400880 api_main_t *am = &api_main;
881 FILE *fp;
882 char filename[64];
883 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700884
Dave Barach371e4e12016-07-08 09:38:52 -0400885 if (post_mortem_dump_enabled == 0)
886 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700887
Dave Barach371e4e12016-07-08 09:38:52 -0400888 snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
889 getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700890
Dave Barach371e4e12016-07-08 09:38:52 -0400891 fp = fopen (filename, "w");
892 if (fp == NULL)
893 {
894 rv = write (2, "Couldn't create ", 16);
895 rv = write (2, filename, strlen (filename));
896 rv = write (2, "\n", 1);
897 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700898 }
Dave Barach371e4e12016-07-08 09:38:52 -0400899 rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp);
900 fclose (fp);
901 if (rv < 0)
902 {
903 rv = write (2, "Failed to save post-mortem API trace to ", 40);
904 rv = write (2, filename, strlen (filename));
905 rv = write (2, "\n", 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700906 }
Dave Barach371e4e12016-07-08 09:38:52 -0400907
Ed Warnickecb9cada2015-12-08 15:45:58 -0700908}
909
910/* Layered message handling support */
911
Dave Barach371e4e12016-07-08 09:38:52 -0400912void
913vl_msg_api_register_pd_handler (void *fp, u16 msg_id_host_byte_order)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700914{
Dave Barach371e4e12016-07-08 09:38:52 -0400915 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700916
Dave Barach371e4e12016-07-08 09:38:52 -0400917 /* Mild idiot proofing */
918 if (msg_id_host_byte_order > 10000)
919 clib_warning ("msg_id_host_byte_order endian issue? %d arg vs %d",
920 msg_id_host_byte_order,
921 clib_net_to_host_u16 (msg_id_host_byte_order));
922 vec_validate (am->pd_msg_handlers, msg_id_host_byte_order);
923 am->pd_msg_handlers[msg_id_host_byte_order] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700924}
925
Dave Barach371e4e12016-07-08 09:38:52 -0400926int
927vl_msg_api_pd_handler (void *mp, int rv)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700928{
Dave Barach371e4e12016-07-08 09:38:52 -0400929 api_main_t *am = &api_main;
930 int (*fp) (void *, int);
931 u16 msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700932
Dave Barach371e4e12016-07-08 09:38:52 -0400933 if (clib_arch_is_little_endian)
934 msg_id = clib_net_to_host_u16 (*((u16 *) mp));
935 else
936 msg_id = *((u16 *) mp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700937
Dave Barach371e4e12016-07-08 09:38:52 -0400938 if (msg_id >= vec_len (am->pd_msg_handlers)
939 || am->pd_msg_handlers[msg_id] == 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700940 return rv;
Dave Barach371e4e12016-07-08 09:38:52 -0400941
942 fp = am->pd_msg_handlers[msg_id];
943 rv = (*fp) (mp, rv);
944 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700945}
946
Dave Barach371e4e12016-07-08 09:38:52 -0400947void
948vl_msg_api_set_first_available_msg_id (u16 first_avail)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700949{
Dave Barach371e4e12016-07-08 09:38:52 -0400950 api_main_t *am = &api_main;
951
952 am->first_available_msg_id = first_avail;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700953}
954
Dave Barach371e4e12016-07-08 09:38:52 -0400955u16
Neale Rannse72be392017-04-26 13:59:20 -0700956vl_msg_api_get_msg_ids (const char *name, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700957{
Dave Barach371e4e12016-07-08 09:38:52 -0400958 api_main_t *am = &api_main;
959 u8 *name_copy;
960 vl_api_msg_range_t *rp;
961 uword *p;
962 u16 rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700963
Dave Barach371e4e12016-07-08 09:38:52 -0400964 if (am->msg_range_by_name == 0)
965 am->msg_range_by_name = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700966
Dave Barach371e4e12016-07-08 09:38:52 -0400967 name_copy = format (0, "%s%c", name, 0);
968
969 p = hash_get_mem (am->msg_range_by_name, name_copy);
970 if (p)
971 {
972 clib_warning ("WARNING: duplicate message range registration for '%s'",
973 name_copy);
974 vec_free (name_copy);
975 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700976 }
977
Dave Barach371e4e12016-07-08 09:38:52 -0400978 if (n < 0 || n > 1024)
979 {
980 clib_warning
981 ("WARNING: bad number of message-IDs (%d) requested by '%s'",
982 n, name_copy);
983 vec_free (name_copy);
984 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700985 }
986
Dave Barach371e4e12016-07-08 09:38:52 -0400987 vec_add2 (am->msg_ranges, rp, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700988
Dave Barach371e4e12016-07-08 09:38:52 -0400989 rv = rp->first_msg_id = am->first_available_msg_id;
990 am->first_available_msg_id += n;
991 rp->last_msg_id = am->first_available_msg_id - 1;
992 rp->name = name_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700993
Dave Barach371e4e12016-07-08 09:38:52 -0400994 hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700995
Dave Barach371e4e12016-07-08 09:38:52 -0400996 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700997}
Dave Barach371e4e12016-07-08 09:38:52 -0400998
Dave Barach557d1282016-11-10 14:22:49 -0500999void
Neale Rannse72be392017-04-26 13:59:20 -07001000vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
Dave Barach557d1282016-11-10 14:22:49 -05001001{
1002 uword *p;
1003
1004 if (am->msg_index_by_name_and_crc == 0)
1005 am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
1006
1007 p = hash_get_mem (am->msg_index_by_name_and_crc, string);
1008 if (p)
1009 {
1010 clib_warning ("attempt to redefine '%s' ignored...", string);
1011 return;
1012 }
1013
1014 hash_set_mem (am->msg_index_by_name_and_crc, string, id);
1015}
1016
Dave Barach0d056e52017-09-28 15:11:16 -04001017void
1018vl_msg_api_add_version (api_main_t * am, const char *string,
1019 u32 major, u32 minor, u32 patch)
1020{
1021 api_version_t version = {.major = major,.minor = minor,.patch = patch };
1022 ASSERT (strlen (string) < 64);
Ole Troan7504e992017-10-10 08:43:35 +02001023 strncpy (version.name, string, 64 - 1);
Dave Barach0d056e52017-09-28 15:11:16 -04001024 vec_add1 (am->api_version_list, version);
1025}
Dave Barach557d1282016-11-10 14:22:49 -05001026
Florin Corase86a8ed2018-01-05 03:20:25 -08001027u32
1028vl_msg_api_get_msg_index (u8 * name_and_crc)
1029{
1030 api_main_t *am = &api_main;
1031 uword *p;
1032
1033 if (am->msg_index_by_name_and_crc)
1034 {
1035 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
1036 if (p)
1037 return p[0];
1038 }
1039 return ~0;
1040}
1041
Ole Troan73710c72018-06-04 22:27:49 +02001042void *
1043vl_msg_push_heap (void)
1044{
1045 api_main_t *am = &api_main;
1046 pthread_mutex_lock (&am->vlib_rp->mutex);
1047 return svm_push_data_heap (am->vlib_rp);
1048}
1049
1050void
1051vl_msg_pop_heap (void *oldheap)
1052{
1053 api_main_t *am = &api_main;
1054 svm_pop_heap (oldheap);
1055 pthread_mutex_unlock (&am->vlib_rp->mutex);
1056}
1057
Neale Ranns377860a2019-06-21 07:57:18 -07001058int
1059vl_api_to_api_string (u32 len, const char *buf, vl_api_string_t * str)
1060{
Ole Troan33a58172019-09-04 09:12:29 +02001061 if (len)
1062 clib_memcpy_fast (str->buf, buf, len);
Neale Ranns377860a2019-06-21 07:57:18 -07001063 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
Ole Troan33a58172019-09-04 09:12:29 +02001089u8 *
1090vl_api_format_string (u8 * s, va_list * args)
1091{
1092 vl_api_string_t *a = va_arg (*args, vl_api_string_t *);
1093 vec_add (s, a->buf, clib_net_to_host_u32 (a->length));
1094 return s;
1095}
1096
Neale Ranns377860a2019-06-21 07:57:18 -07001097/*
1098 * Returns a new vector. Remember to free it after use.
1099 */
1100u8 *
1101vl_api_from_api_to_vec (vl_api_string_t * astr)
1102{
1103 u8 *v = 0;
Dave Barach9683c1e2019-07-01 09:42:41 -04001104 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
Neale Ranns377860a2019-06-21 07:57:18 -07001105 return v;
1106}
Ole Troan73710c72018-06-04 22:27:49 +02001107
Dave Barachb09f4d02019-07-15 16:00:03 -04001108void
1109vl_api_set_elog_main (elog_main_t * m)
1110{
1111 api_main_t *am = &api_main;
1112 am->elog_main = m;
1113}
1114
1115int
1116vl_api_set_elog_trace_api_messages (int enable)
1117{
1118 int rv;
1119 api_main_t *am = &api_main;
1120
1121 rv = am->elog_trace_api_messages;
1122 am->elog_trace_api_messages = enable;
1123 return rv;
1124}
1125
1126int
1127vl_api_get_elog_trace_api_messages (void)
1128{
1129 api_main_t *am = &api_main;
1130
1131 return am->elog_trace_api_messages;
1132}
1133
Dave Barach371e4e12016-07-08 09:38:52 -04001134/*
1135 * fd.io coding-style-patch-verification: ON
1136 *
1137 * Local Variables:
1138 * eval: (c-set-style "gnu")
1139 * End:
1140 */