blob: 65288d89f67a7e6d030605b5ff36eeefe92e043b [file] [log] [blame]
Dave Barach371e4e12016-07-08 09:38:52 -04001/*
Ed Warnickecb9cada2015-12-08 15:45:58 -07002 *------------------------------------------------------------------
3 * api_shared.c - API message handling, common code for both clients
4 * and the vlib process itself.
Dave Barach371e4e12016-07-08 09:38:52 -04005 *
Ed Warnickecb9cada2015-12-08 15:45:58 -07006 *
7 * Copyright (c) 2009 Cisco and/or its affiliates.
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at:
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *------------------------------------------------------------------
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
Dave Barach072f8de2016-12-02 13:31:25 -050024#include <stddef.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070025#include <string.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070026#include <vppinfra/format.h>
27#include <vppinfra/byte_order.h>
28#include <vppinfra/error.h>
29#include <vlib/vlib.h>
30#include <vlib/unix/unix.h>
31#include <vlibapi/api.h>
32#include <vppinfra/elog.h>
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +000033#include <vppinfra/callback.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070034
Dave Barach80f54e22017-03-08 19:08:56 -050035/* *INDENT-OFF* */
Dave Barach39d69112019-11-27 11:42:13 -050036api_main_t api_global_main =
Dave Barach80f54e22017-03-08 19:08:56 -050037 {
38 .region_name = "/unset",
39 .api_uid = -1,
40 .api_gid = -1,
41 };
42/* *INDENT-ON* */
Dave Barach371e4e12016-07-08 09:38:52 -040043
Dave Barach39d69112019-11-27 11:42:13 -050044/* Please use vlibapi_get_main() to access my_api_main */
45__thread api_main_t *my_api_main = &api_global_main;
46
47void
48vl_msg_api_set_global_main (void *am_arg)
49{
50 ASSERT (am_arg);
51 my_api_main = (api_main_t *) am_arg;
52}
53
Dave Barach371e4e12016-07-08 09:38:52 -040054void
55vl_msg_api_increment_missing_client_counter (void)
56{
Dave Barach39d69112019-11-27 11:42:13 -050057 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -040058 am->missing_clients++;
59}
60
Dave Barach371e4e12016-07-08 09:38:52 -040061int
62vl_msg_api_rx_trace_enabled (api_main_t * am)
Ed Warnickecb9cada2015-12-08 15:45:58 -070063{
Dave Barach371e4e12016-07-08 09:38:52 -040064 return (am->rx_trace && am->rx_trace->enabled);
Ed Warnickecb9cada2015-12-08 15:45:58 -070065}
66
Dave Barach371e4e12016-07-08 09:38:52 -040067int
68vl_msg_api_tx_trace_enabled (api_main_t * am)
Ed Warnickecb9cada2015-12-08 15:45:58 -070069{
Dave Barach371e4e12016-07-08 09:38:52 -040070 return (am->tx_trace && am->tx_trace->enabled);
Ed Warnickecb9cada2015-12-08 15:45:58 -070071}
72
73/*
74 * vl_msg_api_trace
75 */
Dave Barach371e4e12016-07-08 09:38:52 -040076void
77vl_msg_api_trace (api_main_t * am, vl_api_trace_t * tp, void *msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -070078{
Dave Barach371e4e12016-07-08 09:38:52 -040079 u8 **this_trace;
80 u8 **old_trace;
81 u8 *msg_copy;
Dave Barach072f8de2016-12-02 13:31:25 -050082 u32 length;
Dave Barach371e4e12016-07-08 09:38:52 -040083 trace_cfg_t *cfgp;
Dave Barach9683c1e2019-07-01 09:42:41 -040084 u16 msg_id = clib_net_to_host_u16 (*((u16 *) msg));
Dave Barach072f8de2016-12-02 13:31:25 -050085 msgbuf_t *header = (msgbuf_t *) (((u8 *) msg) - offsetof (msgbuf_t, data));
Ed Warnickecb9cada2015-12-08 15:45:58 -070086
Dave Barach371e4e12016-07-08 09:38:52 -040087 cfgp = am->api_trace_cfg + msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -070088
Dave Barach371e4e12016-07-08 09:38:52 -040089 if (!cfgp || !cfgp->trace_enable)
90 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070091
Dave Barach371e4e12016-07-08 09:38:52 -040092 msg_copy = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -070093
Dave Barach371e4e12016-07-08 09:38:52 -040094 if (tp->nitems == 0)
95 {
96 clib_warning ("tp->nitems is 0");
97 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070098 }
99
Dave Barach371e4e12016-07-08 09:38:52 -0400100 if (vec_len (tp->traces) < tp->nitems)
101 {
102 vec_add1 (tp->traces, 0);
103 this_trace = tp->traces + vec_len (tp->traces) - 1;
104 }
105 else
106 {
107 tp->wrapped = 1;
108 old_trace = tp->traces + tp->curindex++;
109 if (tp->curindex == tp->nitems)
110 tp->curindex = 0;
Dave Barachf35a0722019-06-12 16:50:38 -0400111 /* Reuse the trace record, may save some memory allocator traffic */
112 msg_copy = *old_trace;
113 vec_reset_length (msg_copy);
Dave Barach371e4e12016-07-08 09:38:52 -0400114 this_trace = old_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700115 }
116
Dave Barach072f8de2016-12-02 13:31:25 -0500117 length = clib_net_to_host_u32 (header->data_len);
118
119 vec_validate (msg_copy, length - 1);
Dave Barach178cf492018-11-13 16:34:13 -0500120 clib_memcpy_fast (msg_copy, msg, length);
Dave Barach371e4e12016-07-08 09:38:52 -0400121 *this_trace = msg_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700122}
123
Dave Barach371e4e12016-07-08 09:38:52 -0400124int
125vl_msg_api_trace_onoff (api_main_t * am, vl_api_trace_which_t which,
126 int onoff)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700127{
Dave Barach371e4e12016-07-08 09:38:52 -0400128 vl_api_trace_t *tp;
129 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700130
Dave Barach371e4e12016-07-08 09:38:52 -0400131 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700132 {
133 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400134 tp = am->tx_trace;
135 if (tp == 0)
136 {
137 vl_msg_api_trace_configure (am, which, 1024);
138 tp = am->tx_trace;
139 }
140 break;
141
Ed Warnickecb9cada2015-12-08 15:45:58 -0700142 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400143 tp = am->rx_trace;
144 if (tp == 0)
145 {
146 vl_msg_api_trace_configure (am, which, 1024);
147 tp = am->rx_trace;
148 }
149 break;
150
Ed Warnickecb9cada2015-12-08 15:45:58 -0700151 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400152 /* duh? */
153 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700154 }
155
Dave Barach371e4e12016-07-08 09:38:52 -0400156 /* Configured? */
157 if (tp == 0 || tp->nitems == 0)
158 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159
Dave Barach371e4e12016-07-08 09:38:52 -0400160 rv = tp->enabled;
161 tp->enabled = onoff;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700162
Dave Barach371e4e12016-07-08 09:38:52 -0400163 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164}
165
Dave Barach371e4e12016-07-08 09:38:52 -0400166int
167vl_msg_api_trace_free (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700168{
Dave Barach371e4e12016-07-08 09:38:52 -0400169 vl_api_trace_t *tp;
170 int i;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700171
Dave Barach371e4e12016-07-08 09:38:52 -0400172 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700173 {
174 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400175 tp = am->tx_trace;
176 break;
177
Ed Warnickecb9cada2015-12-08 15:45:58 -0700178 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400179 tp = am->rx_trace;
180 break;
181
Ed Warnickecb9cada2015-12-08 15:45:58 -0700182 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400183 /* duh? */
184 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700185 }
186
Dave Barach371e4e12016-07-08 09:38:52 -0400187 /* Configured? */
188 if (!tp || tp->nitems == 0)
189 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700190
Dave Barach371e4e12016-07-08 09:38:52 -0400191 tp->curindex = 0;
192 tp->wrapped = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700193
Dave Barach371e4e12016-07-08 09:38:52 -0400194 for (i = 0; i < vec_len (tp->traces); i++)
195 {
196 vec_free (tp->traces[i]);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700197 }
Dave Barach371e4e12016-07-08 09:38:52 -0400198 vec_free (tp->traces);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700199
Dave Barach371e4e12016-07-08 09:38:52 -0400200 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700201}
202
Ole Troanedfe2c02019-07-30 15:38:13 +0200203u8 *
204vl_api_serialize_message_table (api_main_t * am, u8 * vector)
205{
206 serialize_main_t _sm, *sm = &_sm;
207 hash_pair_t *hp;
208 u32 nmsg = hash_elts (am->msg_index_by_name_and_crc);
209
210 serialize_open_vector (sm, vector);
211
212 /* serialize the count */
213 serialize_integer (sm, nmsg, sizeof (u32));
214
215 /* *INDENT-OFF* */
216 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
217 ({
218 serialize_likely_small_unsigned_integer (sm, hp->value[0]);
219 serialize_cstring (sm, (char *) hp->key);
220 }));
221 /* *INDENT-ON* */
222
223 return serialize_close_vector (sm);
224}
225
Dave Barach371e4e12016-07-08 09:38:52 -0400226int
227vl_msg_api_trace_save (api_main_t * am, vl_api_trace_which_t which, FILE * fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700228{
Dave Barach371e4e12016-07-08 09:38:52 -0400229 vl_api_trace_t *tp;
230 vl_api_trace_file_header_t fh;
231 int i;
232 u8 *msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233
Dave Barach371e4e12016-07-08 09:38:52 -0400234 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700235 {
236 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400237 tp = am->tx_trace;
238 break;
239
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400241 tp = am->rx_trace;
242 break;
243
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400245 /* duh? */
246 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700247 }
248
Dave Barach371e4e12016-07-08 09:38:52 -0400249 /* Configured, data present? */
250 if (tp == 0 || tp->nitems == 0 || vec_len (tp->traces) == 0)
251 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700252
Dave Barach371e4e12016-07-08 09:38:52 -0400253 /* "Dare to be stupid" check */
254 if (fp == 0)
255 {
256 return -2;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700257 }
258
Dave Barach371e4e12016-07-08 09:38:52 -0400259 /* Write the file header */
Dave Barach371e4e12016-07-08 09:38:52 -0400260 fh.wrapped = tp->wrapped;
Ole Troanedfe2c02019-07-30 15:38:13 +0200261 fh.nitems = clib_host_to_net_u32 (vec_len (tp->traces));
262 u8 *m = vl_api_serialize_message_table (am, 0);
Ole Troanedfe2c02019-07-30 15:38:13 +0200263 fh.msgtbl_size = clib_host_to_net_u32 (vec_len (m));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700264
Dave Barach371e4e12016-07-08 09:38:52 -0400265 if (fwrite (&fh, sizeof (fh), 1, fp) != 1)
266 {
267 return (-10);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700268 }
269
Ole Troanedfe2c02019-07-30 15:38:13 +0200270 /* Write the message table */
271 if (fwrite (m, vec_len (m), 1, fp) != 1)
272 {
273 return (-14);
274 }
275 vec_free (m);
276
Dave Barach371e4e12016-07-08 09:38:52 -0400277 /* No-wrap case */
278 if (tp->wrapped == 0)
279 {
280 /*
281 * Note: vec_len return 0 when fed a NULL pointer.
282 * Unfortunately, the static analysis tool doesn't
283 * figure it out, hence the suppressed warnings.
284 * What a great use of my time.
285 */
286 for (i = 0; i < vec_len (tp->traces); i++)
287 {
Dave Barach072f8de2016-12-02 13:31:25 -0500288 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400289 /*sa_ignore NO_NULL_CHK */
290 msg = tp->traces[i];
291 /*
292 * This retarded check required to pass
293 * [sic] SA-checking.
294 */
295 if (!msg)
296 continue;
Dave Barach072f8de2016-12-02 13:31:25 -0500297
298 msg_length = clib_host_to_net_u32 (vec_len (msg));
299 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
300 != sizeof (msg_length))
301 {
302 return (-14);
303 }
Dave Barach371e4e12016-07-08 09:38:52 -0400304 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
305 {
306 return (-11);
307 }
308 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700309 }
Dave Barach371e4e12016-07-08 09:38:52 -0400310 else
311 {
312 /* Wrap case: write oldest -> end of buffer */
313 for (i = tp->curindex; i < vec_len (tp->traces); i++)
314 {
Dave Barach072f8de2016-12-02 13:31:25 -0500315 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400316 msg = tp->traces[i];
317 /*
318 * This retarded check required to pass
319 * [sic] SA-checking
320 */
321 if (!msg)
322 continue;
323
Dave Barach072f8de2016-12-02 13:31:25 -0500324 msg_length = clib_host_to_net_u32 (vec_len (msg));
325 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
326 != sizeof (msg_length))
327 {
328 return (-14);
329 }
330
Dave Barach371e4e12016-07-08 09:38:52 -0400331 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
332 {
333 return (-12);
334 }
335 }
336 /* write beginning of buffer -> oldest-1 */
337 for (i = 0; i < tp->curindex; i++)
338 {
Dave Barach072f8de2016-12-02 13:31:25 -0500339 u32 msg_length;
Dave Barach371e4e12016-07-08 09:38:52 -0400340 /*sa_ignore NO_NULL_CHK */
341 msg = tp->traces[i];
342 /*
343 * This retarded check required to pass
344 * [sic] SA-checking
345 */
346 if (!msg)
347 continue;
348
Dave Barach072f8de2016-12-02 13:31:25 -0500349 msg_length = clib_host_to_net_u32 (vec_len (msg));
350 if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
351 != sizeof (msg_length))
352 {
353 return (-14);
354 }
355
Dave Barach371e4e12016-07-08 09:38:52 -0400356 if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
357 {
358 return (-13);
359 }
360 }
361 }
362 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700363}
364
Dave Barach371e4e12016-07-08 09:38:52 -0400365int
366vl_msg_api_trace_configure (api_main_t * am, vl_api_trace_which_t which,
367 u32 nitems)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700368{
Dave Barach371e4e12016-07-08 09:38:52 -0400369 vl_api_trace_t *tp;
370 int was_on = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700371
Dave Barach371e4e12016-07-08 09:38:52 -0400372 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373 {
374 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400375 tp = am->tx_trace;
376 if (tp == 0)
377 {
378 vec_validate (am->tx_trace, 0);
379 tp = am->tx_trace;
380 }
381 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700382
Dave Barach371e4e12016-07-08 09:38:52 -0400383 case VL_API_TRACE_RX:
384 tp = am->rx_trace;
385 if (tp == 0)
386 {
387 vec_validate (am->rx_trace, 0);
388 tp = am->rx_trace;
389 }
390
391 break;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700392
393 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400394 return -1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395
396 }
397
Dave Barach371e4e12016-07-08 09:38:52 -0400398 if (tp->enabled)
399 {
400 was_on = vl_msg_api_trace_onoff (am, which, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700401 }
Dave Barach371e4e12016-07-08 09:38:52 -0400402 if (tp->traces)
403 {
404 vl_msg_api_trace_free (am, which);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700405 }
406
Dave Barachb7b92992018-10-17 10:38:51 -0400407 clib_memset (tp, 0, sizeof (*tp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700408
Dave Barach371e4e12016-07-08 09:38:52 -0400409 if (clib_arch_is_big_endian)
410 {
411 tp->endian = VL_API_BIG_ENDIAN;
412 }
413 else
414 {
415 tp->endian = VL_API_LITTLE_ENDIAN;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700416 }
417
Dave Barach371e4e12016-07-08 09:38:52 -0400418 tp->nitems = nitems;
419 if (was_on)
420 {
421 (void) vl_msg_api_trace_onoff (am, which, was_on);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700422 }
Dave Barach371e4e12016-07-08 09:38:52 -0400423 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424}
425
Dave Barach80f54e22017-03-08 19:08:56 -0500426void
427vl_msg_api_barrier_sync (void)
428{
429}
430
431void
432vl_msg_api_barrier_release (void)
433{
434}
435
Dave Barach371e4e12016-07-08 09:38:52 -0400436always_inline void
437msg_handler_internal (api_main_t * am,
438 void *the_msg, int trace_it, int do_it, int free_it)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700439{
Dave Barach9683c1e2019-07-01 09:42:41 -0400440 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400441 u8 *(*print_fp) (void *, void *);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700442
Dave Barachb09f4d02019-07-15 16:00:03 -0400443 if (PREDICT_FALSE (am->elog_trace_api_messages))
444 {
445 /* *INDENT-OFF* */
446 ELOG_TYPE_DECLARE (e) =
447 {
448 .format = "api-msg: %s",
449 .format_args = "T4",
450 };
451 /* *INDENT-ON* */
452 struct
453 {
454 u32 c;
455 } *ed;
456 ed = ELOG_DATA (am->elog_main, e);
Andrew Yourtchenkof48de882021-02-06 12:28:52 +0000457 if (id < vec_len (am->msg_names) && am->msg_names[id])
Dave Barachb09f4d02019-07-15 16:00:03 -0400458 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
459 else
460 ed->c = elog_string (am->elog_main, "BOGUS");
461 }
462
Dave Barach371e4e12016-07-08 09:38:52 -0400463 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
464 {
465 if (trace_it)
466 vl_msg_api_trace (am, am->rx_trace, the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700467
Dave Barach371e4e12016-07-08 09:38:52 -0400468 if (am->msg_print_flag)
469 {
470 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
471 print_fp = (void *) am->msg_print_handlers[id];
472 if (print_fp == 0)
473 {
474 fformat (stdout, " [no registered print fn]\n");
475 }
476 else
477 {
478 (*print_fp) (the_msg, stdout);
479 }
480 }
481
482 if (do_it)
483 {
484 if (!am->is_mp_safe[id])
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100485 {
486 vl_msg_api_barrier_trace_context (am->msg_names[id]);
487 vl_msg_api_barrier_sync ();
488 }
Ole Troane796a182020-05-18 11:14:05 +0200489
490 if (am->is_autoendian[id])
491 {
492 void (*endian_fp) (void *);
493 endian_fp = am->msg_endian_handlers[id];
494 (*endian_fp) (the_msg);
495 }
496
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000497 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
498 clib_call_callbacks (am->perf_counter_cbs, am, id,
499 0 /* before */ );
500
Dave Barach371e4e12016-07-08 09:38:52 -0400501 (*am->msg_handlers[id]) (the_msg);
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000502
503 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
504 clib_call_callbacks (am->perf_counter_cbs, am, id,
505 1 /* after */ );
Dave Barach371e4e12016-07-08 09:38:52 -0400506 if (!am->is_mp_safe[id])
507 vl_msg_api_barrier_release ();
508 }
509 }
510 else
511 {
512 clib_warning ("no handler for msg id %d", id);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513 }
514
Dave Barach371e4e12016-07-08 09:38:52 -0400515 if (free_it)
516 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700517
Dave Barachb09f4d02019-07-15 16:00:03 -0400518 if (PREDICT_FALSE (am->elog_trace_api_messages))
519 {
520 /* *INDENT-OFF* */
521 ELOG_TYPE_DECLARE (e) =
522 {
523 .format = "api-msg-done(%s): %s",
524 .format_args = "t4T4",
525 .n_enum_strings = 2,
526 .enum_strings =
527 {
528 "barrier",
529 "mp-safe",
530 }
531 };
532 /* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700533
Dave Barachb09f4d02019-07-15 16:00:03 -0400534 struct
535 {
536 u32 barrier;
537 u32 c;
538 } *ed;
539 ed = ELOG_DATA (am->elog_main, e);
Andrew Yourtchenkof48de882021-02-06 12:28:52 +0000540 if (id < vec_len (am->msg_names) && am->msg_names[id])
Dave Barach67947872019-07-19 09:31:29 -0400541 {
542 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
543 ed->barrier = !am->is_mp_safe[id];
544 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400545 else
Dave Barach67947872019-07-19 09:31:29 -0400546 {
547 ed->c = elog_string (am->elog_main, "BOGUS");
548 ed->barrier = 0;
549 }
Dave Barachb09f4d02019-07-15 16:00:03 -0400550 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700551}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700552
Dave Barach77841402020-04-29 17:04:10 -0400553void (*vl_msg_api_fuzz_hook) (u16, void *);
554
Ed Warnickecb9cada2015-12-08 15:45:58 -0700555/* This is only to be called from a vlib/vnet app */
Dave Barach371e4e12016-07-08 09:38:52 -0400556void
Florin Coras8d820852019-11-27 09:15:25 -0800557vl_msg_api_handler_with_vm_node (api_main_t * am, svm_region_t * vlib_rp,
Dave Barach371e4e12016-07-08 09:38:52 -0400558 void *the_msg, vlib_main_t * vm,
Florin Coras8d820852019-11-27 09:15:25 -0800559 vlib_node_runtime_t * node, u8 is_private)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700560{
Dave Barach9683c1e2019-07-01 09:42:41 -0400561 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Dave Barach371e4e12016-07-08 09:38:52 -0400562 u8 *(*handler) (void *, void *, void *);
ezkexma75f9fb62019-03-21 07:38:19 -0400563 u8 *(*print_fp) (void *, void *);
Florin Coras8d820852019-11-27 09:15:25 -0800564 svm_region_t *old_vlib_rp;
565 void *save_shmem_hdr;
Dave Barachc898a4f2019-06-14 17:29:55 -0400566 int is_mp_safe = 1;
Dave Barach371e4e12016-07-08 09:38:52 -0400567
Dave Barachb09f4d02019-07-15 16:00:03 -0400568 if (PREDICT_FALSE (am->elog_trace_api_messages))
Dave Barach371e4e12016-07-08 09:38:52 -0400569 {
Dave Barachc3a06552018-10-01 09:25:32 -0400570 /* *INDENT-OFF* */
571 ELOG_TYPE_DECLARE (e) =
572 {
573 .format = "api-msg: %s",
574 .format_args = "T4",
575 };
576 /* *INDENT-ON* */
577 struct
578 {
579 u32 c;
580 } *ed;
Dave Barachb09f4d02019-07-15 16:00:03 -0400581 ed = ELOG_DATA (am->elog_main, e);
Andrew Yourtchenkof48de882021-02-06 12:28:52 +0000582 if (id < vec_len (am->msg_names) && am->msg_names[id])
Dave Barachb09f4d02019-07-15 16:00:03 -0400583 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
Dave Barachc3a06552018-10-01 09:25:32 -0400584 else
Dave Barachb09f4d02019-07-15 16:00:03 -0400585 ed->c = elog_string (am->elog_main, "BOGUS");
Dave Barachc3a06552018-10-01 09:25:32 -0400586 }
Dave Barach371e4e12016-07-08 09:38:52 -0400587
588 if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
589 {
590 handler = (void *) am->msg_handlers[id];
591
ezkexma75f9fb62019-03-21 07:38:19 -0400592 if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled))
Dave Barach371e4e12016-07-08 09:38:52 -0400593 vl_msg_api_trace (am, am->rx_trace, the_msg);
594
ezkexma75f9fb62019-03-21 07:38:19 -0400595 if (PREDICT_FALSE (am->msg_print_flag))
596 {
597 fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
598 print_fp = (void *) am->msg_print_handlers[id];
599 if (print_fp == 0)
600 {
601 fformat (stdout, " [no registered print fn for msg %d]\n", id);
602 }
603 else
604 {
605 (*print_fp) (the_msg, vm);
606 }
607 }
Dave Barachc898a4f2019-06-14 17:29:55 -0400608 is_mp_safe = am->is_mp_safe[id];
ezkexma75f9fb62019-03-21 07:38:19 -0400609
Dave Barachc898a4f2019-06-14 17:29:55 -0400610 if (!is_mp_safe)
Colin Tregenza Dancereb1ac172017-09-06 20:23:24 +0100611 {
612 vl_msg_api_barrier_trace_context (am->msg_names[id]);
613 vl_msg_api_barrier_sync ();
614 }
Florin Coras8d820852019-11-27 09:15:25 -0800615 if (is_private)
616 {
617 old_vlib_rp = am->vlib_rp;
618 save_shmem_hdr = am->shmem_hdr;
619 am->vlib_rp = vlib_rp;
620 am->shmem_hdr = (void *) vlib_rp->user_ctx;
621 }
Dave Barach77841402020-04-29 17:04:10 -0400622
623 if (PREDICT_FALSE (vl_msg_api_fuzz_hook != 0))
624 (*vl_msg_api_fuzz_hook) (id, the_msg);
625
Ole Troane796a182020-05-18 11:14:05 +0200626 if (am->is_autoendian[id])
627 {
628 void (*endian_fp) (void *);
629 endian_fp = am->msg_endian_handlers[id];
630 (*endian_fp) (the_msg);
631 }
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000632 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
633 clib_call_callbacks (am->perf_counter_cbs, am, id, 0 /* before */ );
Ole Troane796a182020-05-18 11:14:05 +0200634
Dave Barach371e4e12016-07-08 09:38:52 -0400635 (*handler) (the_msg, vm, node);
Tom Seidenberg6c81f5a2020-07-10 15:49:03 +0000636
637 if (PREDICT_FALSE (vec_len (am->perf_counter_cbs) != 0))
638 clib_call_callbacks (am->perf_counter_cbs, am, id, 1 /* after */ );
Florin Coras8d820852019-11-27 09:15:25 -0800639 if (is_private)
640 {
641 am->vlib_rp = old_vlib_rp;
642 am->shmem_hdr = save_shmem_hdr;
643 }
Dave Barachc898a4f2019-06-14 17:29:55 -0400644 if (!is_mp_safe)
Dave Barach371e4e12016-07-08 09:38:52 -0400645 vl_msg_api_barrier_release ();
646 }
647 else
648 {
Jon Loeligerf95b37e2017-02-13 15:21:12 -0600649 clib_warning ("no handler for msg id %d", id);
Dave Barach371e4e12016-07-08 09:38:52 -0400650 }
651
652 /*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700653 * Special-case, so we can e.g. bounce messages off the vnet
654 * main thread without copying them...
655 */
Benoît Ganneff13e462020-01-21 18:33:14 +0100656 if (id >= vec_len (am->message_bounce) || !(am->message_bounce[id]))
wanghanlin9f42fff2021-05-08 11:39:53 +0800657 {
658 if (is_private)
659 {
660 old_vlib_rp = am->vlib_rp;
661 save_shmem_hdr = am->shmem_hdr;
662 am->vlib_rp = vlib_rp;
663 am->shmem_hdr = (void *) vlib_rp->user_ctx;
664 }
665 vl_msg_api_free (the_msg);
666 if (is_private)
667 {
668 am->vlib_rp = old_vlib_rp;
669 am->shmem_hdr = save_shmem_hdr;
670 }
671 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700672
Dave Barachb09f4d02019-07-15 16:00:03 -0400673 if (PREDICT_FALSE (am->elog_trace_api_messages))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674 {
Dave Barachc3a06552018-10-01 09:25:32 -0400675 /* *INDENT-OFF* */
Dave Barachc898a4f2019-06-14 17:29:55 -0400676 ELOG_TYPE_DECLARE (e) =
677 {
678 .format = "api-msg-done(%s): %s",
679 .format_args = "t4T4",
680 .n_enum_strings = 2,
681 .enum_strings =
682 {
683 "barrier",
684 "mp-safe",
685 }
686 };
Dave Barachc3a06552018-10-01 09:25:32 -0400687 /* *INDENT-ON* */
688
689 struct
690 {
Dave Barachc898a4f2019-06-14 17:29:55 -0400691 u32 barrier;
Dave Barachc3a06552018-10-01 09:25:32 -0400692 u32 c;
693 } *ed;
Dave Barachb09f4d02019-07-15 16:00:03 -0400694 ed = ELOG_DATA (am->elog_main, e);
Andrew Yourtchenkof48de882021-02-06 12:28:52 +0000695 if (id < vec_len (am->msg_names) && am->msg_names[id])
Dave Barachb09f4d02019-07-15 16:00:03 -0400696 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
Dave Barachc3a06552018-10-01 09:25:32 -0400697 else
Dave Barachb09f4d02019-07-15 16:00:03 -0400698 ed->c = elog_string (am->elog_main, "BOGUS");
Dave Barachc898a4f2019-06-14 17:29:55 -0400699 ed->barrier = is_mp_safe;
Dave Barachc3a06552018-10-01 09:25:32 -0400700 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700701}
702
Dave Barach371e4e12016-07-08 09:38:52 -0400703void
704vl_msg_api_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700705{
Dave Barach39d69112019-11-27 11:42:13 -0500706 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700707
Dave Barach371e4e12016-07-08 09:38:52 -0400708 msg_handler_internal (am, the_msg,
709 (am->rx_trace
710 && am->rx_trace->enabled) /* trace_it */ ,
711 1 /* do_it */ , 1 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700712}
713
Dave Barach371e4e12016-07-08 09:38:52 -0400714void
715vl_msg_api_handler_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716{
Dave Barach39d69112019-11-27 11:42:13 -0500717 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400718 msg_handler_internal (am, the_msg,
719 (am->rx_trace
720 && am->rx_trace->enabled) /* trace_it */ ,
721 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700722}
723
Dave Barach371e4e12016-07-08 09:38:52 -0400724void
725vl_msg_api_handler_no_trace_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700726{
Dave Barach39d69112019-11-27 11:42:13 -0500727 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400728 msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
729 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700730}
731
732/*
733 * Add a trace record to the API message trace buffer, if
734 * API message tracing is enabled. Handy for adding sufficient
735 * data to the trace to reproduce autonomous state, as opposed to
Dave Barach371e4e12016-07-08 09:38:52 -0400736 * state downloaded via control-plane API messages. Example: the NAT
Ed Warnickecb9cada2015-12-08 15:45:58 -0700737 * application creates database entries based on packet traffic, not
738 * control-plane messages.
739 *
740 */
Dave Barach371e4e12016-07-08 09:38:52 -0400741void
742vl_msg_api_trace_only (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700743{
Dave Barach39d69112019-11-27 11:42:13 -0500744 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700745
Dave Barach371e4e12016-07-08 09:38:52 -0400746 msg_handler_internal (am, the_msg,
747 (am->rx_trace
748 && am->rx_trace->enabled) /* trace_it */ ,
749 0 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700750}
751
Dave Barach371e4e12016-07-08 09:38:52 -0400752void
753vl_msg_api_cleanup_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700754{
Dave Barach39d69112019-11-27 11:42:13 -0500755 api_main_t *am = vlibapi_get_main ();
Dave Barach9683c1e2019-07-01 09:42:41 -0400756 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700757
Dave Barach371e4e12016-07-08 09:38:52 -0400758 if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
759 {
760 clib_warning ("_vl_msg_id too large: %d\n", id);
761 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700762 }
Dave Barach371e4e12016-07-08 09:38:52 -0400763 if (am->msg_cleanup_handlers[id])
764 (*am->msg_cleanup_handlers[id]) (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700765
Dave Barach371e4e12016-07-08 09:38:52 -0400766 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700767}
768
769/*
770 * vl_msg_api_replay_handler
771 */
Dave Barach371e4e12016-07-08 09:38:52 -0400772void
773vl_msg_api_replay_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700774{
Dave Barach39d69112019-11-27 11:42:13 -0500775 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700776
Dave Barach9683c1e2019-07-01 09:42:41 -0400777 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700778
Dave Barach371e4e12016-07-08 09:38:52 -0400779 if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
780 {
781 clib_warning ("_vl_msg_id too large: %d\n", id);
782 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700783 }
Dave Barach371e4e12016-07-08 09:38:52 -0400784 /* do NOT trace the message... */
785 if (am->msg_handlers[id])
786 (*am->msg_handlers[id]) (the_msg);
787 /* do NOT free the message buffer... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700788}
Dave Barach371e4e12016-07-08 09:38:52 -0400789
Dave Barachbfd92272017-05-12 11:59:25 -0400790u32
791vl_msg_api_get_msg_length (void *msg_arg)
792{
793 return vl_msg_api_get_msg_length_inline (msg_arg);
794}
795
Ed Warnickecb9cada2015-12-08 15:45:58 -0700796/*
797 * vl_msg_api_socket_handler
798 */
Dave Barach371e4e12016-07-08 09:38:52 -0400799void
800vl_msg_api_socket_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700801{
Dave Barach39d69112019-11-27 11:42:13 -0500802 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700803
Dave Barach371e4e12016-07-08 09:38:52 -0400804 msg_handler_internal (am, the_msg,
805 (am->rx_trace
806 && am->rx_trace->enabled) /* trace_it */ ,
807 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700808}
809
810#define foreach_msg_api_vector \
811_(msg_names) \
812_(msg_handlers) \
813_(msg_cleanup_handlers) \
814_(msg_endian_handlers) \
815_(msg_print_handlers) \
816_(api_trace_cfg) \
817_(message_bounce) \
Ole Troane796a182020-05-18 11:14:05 +0200818_(is_mp_safe) \
819_(is_autoendian)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700820
Dave Barach371e4e12016-07-08 09:38:52 -0400821void
822vl_msg_api_config (vl_msg_api_msg_config_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700823{
Dave Barach39d69112019-11-27 11:42:13 -0500824 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700825
Dave Barach65457162017-10-10 17:53:14 -0400826 /*
827 * This happens during the java core tests if the message
828 * dictionary is missing newly added xxx_reply_t messages.
829 * Should never happen, but since I shot myself in the foot once
830 * this way, I thought I'd make it easy to debug if I ever do
831 * it again... (;-)...
832 */
833 if (c->id == 0)
834 {
835 if (c->name)
836 clib_warning ("Trying to register %s with a NULL msg id!", c->name);
837 else
838 clib_warning ("Trying to register a NULL msg with a NULL msg id!");
839 clib_warning ("Did you forget to call setup_message_id_table?");
840 return;
841 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700842
843#define _(a) vec_validate (am->a, c->id);
Dave Barach371e4e12016-07-08 09:38:52 -0400844 foreach_msg_api_vector;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700845#undef _
846
Dave Barach392206e2017-09-20 08:40:16 -0400847 if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
848 clib_warning
849 ("BUG: re-registering 'vl_api_%s_t_handler'."
850 "Handler was %llx, replaced by %llx",
851 c->name, am->msg_handlers[c->id], c->handler);
Dave Baracha1a093d2017-03-02 13:13:23 -0500852
Dave Barach371e4e12016-07-08 09:38:52 -0400853 am->msg_names[c->id] = c->name;
854 am->msg_handlers[c->id] = c->handler;
855 am->msg_cleanup_handlers[c->id] = c->cleanup;
856 am->msg_endian_handlers[c->id] = c->endian;
857 am->msg_print_handlers[c->id] = c->print;
858 am->message_bounce[c->id] = c->message_bounce;
859 am->is_mp_safe[c->id] = c->is_mp_safe;
Ole Troane796a182020-05-18 11:14:05 +0200860 am->is_autoendian[c->id] = c->is_autoendian;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700861
Dave Barach371e4e12016-07-08 09:38:52 -0400862 am->api_trace_cfg[c->id].size = c->size;
863 am->api_trace_cfg[c->id].trace_enable = c->traced;
864 am->api_trace_cfg[c->id].replay_enable = c->replay;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700865}
866
Dave Barach371e4e12016-07-08 09:38:52 -0400867/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700868 * vl_msg_api_set_handlers
869 * preserve the old API for a while
870 */
Dave Barach371e4e12016-07-08 09:38:52 -0400871void
872vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
873 void *endian, void *print, int size, int traced)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700874{
Dave Barach371e4e12016-07-08 09:38:52 -0400875 vl_msg_api_msg_config_t cfg;
876 vl_msg_api_msg_config_t *c = &cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700877
Dave Barachb7b92992018-10-17 10:38:51 -0400878 clib_memset (c, 0, sizeof (*c));
Dave Barach0691d6e2017-01-05 10:08:52 -0500879
Dave Barach371e4e12016-07-08 09:38:52 -0400880 c->id = id;
881 c->name = name;
882 c->handler = handler;
883 c->cleanup = cleanup;
884 c->endian = endian;
885 c->print = print;
Dave Barach371e4e12016-07-08 09:38:52 -0400886 c->traced = traced;
887 c->replay = 1;
888 c->message_bounce = 0;
889 c->is_mp_safe = 0;
Ole Troane796a182020-05-18 11:14:05 +0200890 c->is_autoendian = 0;
Dave Barach371e4e12016-07-08 09:38:52 -0400891 vl_msg_api_config (c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700892}
893
Dave Barach371e4e12016-07-08 09:38:52 -0400894void
Matej Perina75a17ec2017-09-21 17:03:27 +0200895vl_msg_api_clean_handlers (int msg_id)
896{
897 vl_msg_api_msg_config_t cfg;
898 vl_msg_api_msg_config_t *c = &cfg;
899
Dave Barachb7b92992018-10-17 10:38:51 -0400900 clib_memset (c, 0, sizeof (*c));
Matej Perina75a17ec2017-09-21 17:03:27 +0200901
902 c->id = msg_id;
903 vl_msg_api_config (c);
904}
905
906void
Dave Barach371e4e12016-07-08 09:38:52 -0400907vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700908{
Dave Barach39d69112019-11-27 11:42:13 -0500909 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400910 ASSERT (msg_id > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700911
Dave Barach371e4e12016-07-08 09:38:52 -0400912 vec_validate (am->msg_cleanup_handlers, msg_id);
913 am->msg_cleanup_handlers[msg_id] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700914}
915
Dave Barach371e4e12016-07-08 09:38:52 -0400916void
Florin Corase86a8ed2018-01-05 03:20:25 -0800917vl_msg_api_queue_handler (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700918{
Dave Barach371e4e12016-07-08 09:38:52 -0400919 uword msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700920
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100921 while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
Dave Barach371e4e12016-07-08 09:38:52 -0400922 vl_msg_api_handler ((void *) msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700923}
924
Dave Barach77841402020-04-29 17:04:10 -0400925u32
926vl_msg_api_max_length (void *mp)
927{
928 msgbuf_t *mb;
929 u32 data_len = ~0;
930
931 /* Work out the maximum sane message length, and return it */
932 if (PREDICT_TRUE (mp != 0))
933 {
934 mb = (msgbuf_t *) (((u8 *) mp) - offsetof (msgbuf_t, data));
935 data_len = clib_net_to_host_u32 (mb->data_len);
936 }
937 return data_len;
938}
939
Dave Barach371e4e12016-07-08 09:38:52 -0400940vl_api_trace_t *
941vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942{
Dave Barach371e4e12016-07-08 09:38:52 -0400943 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700944 {
945 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400946 return am->rx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700947 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400948 return am->tx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700949 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400950 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700951 }
952}
953
Dave Barach371e4e12016-07-08 09:38:52 -0400954void
955vl_noop_handler (void *mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700956{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700957}
958
Ed Warnickecb9cada2015-12-08 15:45:58 -0700959
960static u8 post_mortem_dump_enabled;
961
Dave Barach80f54e22017-03-08 19:08:56 -0500962void
963vl_msg_api_post_mortem_dump_enable_disable (int enable)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700964{
Dave Barach80f54e22017-03-08 19:08:56 -0500965 post_mortem_dump_enabled = enable;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700966}
967
Dave Barach371e4e12016-07-08 09:38:52 -0400968void
969vl_msg_api_post_mortem_dump (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700970{
Dave Barach39d69112019-11-27 11:42:13 -0500971 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400972 FILE *fp;
973 char filename[64];
974 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700975
Dave Barach371e4e12016-07-08 09:38:52 -0400976 if (post_mortem_dump_enabled == 0)
977 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700978
Dave Barach371e4e12016-07-08 09:38:52 -0400979 snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
980 getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700981
Dave Barach371e4e12016-07-08 09:38:52 -0400982 fp = fopen (filename, "w");
983 if (fp == NULL)
984 {
985 rv = write (2, "Couldn't create ", 16);
986 rv = write (2, filename, strlen (filename));
987 rv = write (2, "\n", 1);
988 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700989 }
Dave Barach371e4e12016-07-08 09:38:52 -0400990 rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp);
991 fclose (fp);
992 if (rv < 0)
993 {
994 rv = write (2, "Failed to save post-mortem API trace to ", 40);
995 rv = write (2, filename, strlen (filename));
996 rv = write (2, "\n", 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700997 }
Dave Barach371e4e12016-07-08 09:38:52 -0400998
Ed Warnickecb9cada2015-12-08 15:45:58 -0700999}
1000
1001/* Layered message handling support */
1002
Dave Barach371e4e12016-07-08 09:38:52 -04001003void
1004vl_msg_api_register_pd_handler (void *fp, u16 msg_id_host_byte_order)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001005{
Dave Barach39d69112019-11-27 11:42:13 -05001006 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -07001007
Dave Barach371e4e12016-07-08 09:38:52 -04001008 /* Mild idiot proofing */
1009 if (msg_id_host_byte_order > 10000)
1010 clib_warning ("msg_id_host_byte_order endian issue? %d arg vs %d",
1011 msg_id_host_byte_order,
1012 clib_net_to_host_u16 (msg_id_host_byte_order));
1013 vec_validate (am->pd_msg_handlers, msg_id_host_byte_order);
1014 am->pd_msg_handlers[msg_id_host_byte_order] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001015}
1016
Dave Barach371e4e12016-07-08 09:38:52 -04001017int
1018vl_msg_api_pd_handler (void *mp, int rv)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001019{
Dave Barach39d69112019-11-27 11:42:13 -05001020 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -04001021 int (*fp) (void *, int);
1022 u16 msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001023
Dave Barach371e4e12016-07-08 09:38:52 -04001024 if (clib_arch_is_little_endian)
1025 msg_id = clib_net_to_host_u16 (*((u16 *) mp));
1026 else
1027 msg_id = *((u16 *) mp);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001028
Dave Barach371e4e12016-07-08 09:38:52 -04001029 if (msg_id >= vec_len (am->pd_msg_handlers)
1030 || am->pd_msg_handlers[msg_id] == 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001031 return rv;
Dave Barach371e4e12016-07-08 09:38:52 -04001032
1033 fp = am->pd_msg_handlers[msg_id];
1034 rv = (*fp) (mp, rv);
1035 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001036}
1037
Dave Barach371e4e12016-07-08 09:38:52 -04001038void
1039vl_msg_api_set_first_available_msg_id (u16 first_avail)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001040{
Dave Barach39d69112019-11-27 11:42:13 -05001041 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -04001042
1043 am->first_available_msg_id = first_avail;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001044}
1045
Dave Barach371e4e12016-07-08 09:38:52 -04001046u16
Neale Rannse72be392017-04-26 13:59:20 -07001047vl_msg_api_get_msg_ids (const char *name, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001048{
Dave Barach39d69112019-11-27 11:42:13 -05001049 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -04001050 u8 *name_copy;
1051 vl_api_msg_range_t *rp;
1052 uword *p;
1053 u16 rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001054
Dave Barach371e4e12016-07-08 09:38:52 -04001055 if (am->msg_range_by_name == 0)
1056 am->msg_range_by_name = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001057
Dave Barach371e4e12016-07-08 09:38:52 -04001058 name_copy = format (0, "%s%c", name, 0);
1059
1060 p = hash_get_mem (am->msg_range_by_name, name_copy);
1061 if (p)
1062 {
1063 clib_warning ("WARNING: duplicate message range registration for '%s'",
1064 name_copy);
1065 vec_free (name_copy);
1066 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001067 }
1068
Dave Barach371e4e12016-07-08 09:38:52 -04001069 if (n < 0 || n > 1024)
1070 {
1071 clib_warning
1072 ("WARNING: bad number of message-IDs (%d) requested by '%s'",
1073 n, name_copy);
1074 vec_free (name_copy);
1075 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001076 }
1077
Dave Barach371e4e12016-07-08 09:38:52 -04001078 vec_add2 (am->msg_ranges, rp, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001079
Dave Barach371e4e12016-07-08 09:38:52 -04001080 rv = rp->first_msg_id = am->first_available_msg_id;
1081 am->first_available_msg_id += n;
1082 rp->last_msg_id = am->first_available_msg_id - 1;
1083 rp->name = name_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001084
Dave Barach371e4e12016-07-08 09:38:52 -04001085 hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001086
Dave Barach371e4e12016-07-08 09:38:52 -04001087 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001088}
Dave Barach371e4e12016-07-08 09:38:52 -04001089
Dave Barach557d1282016-11-10 14:22:49 -05001090void
Neale Rannse72be392017-04-26 13:59:20 -07001091vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
Dave Barach557d1282016-11-10 14:22:49 -05001092{
1093 uword *p;
1094
1095 if (am->msg_index_by_name_and_crc == 0)
1096 am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
1097
1098 p = hash_get_mem (am->msg_index_by_name_and_crc, string);
1099 if (p)
1100 {
1101 clib_warning ("attempt to redefine '%s' ignored...", string);
1102 return;
1103 }
1104
1105 hash_set_mem (am->msg_index_by_name_and_crc, string, id);
1106}
1107
Dave Barach0d056e52017-09-28 15:11:16 -04001108void
1109vl_msg_api_add_version (api_main_t * am, const char *string,
1110 u32 major, u32 minor, u32 patch)
1111{
1112 api_version_t version = {.major = major,.minor = minor,.patch = patch };
1113 ASSERT (strlen (string) < 64);
Ole Troan7504e992017-10-10 08:43:35 +02001114 strncpy (version.name, string, 64 - 1);
Dave Barach0d056e52017-09-28 15:11:16 -04001115 vec_add1 (am->api_version_list, version);
1116}
Dave Barach557d1282016-11-10 14:22:49 -05001117
Florin Corase86a8ed2018-01-05 03:20:25 -08001118u32
1119vl_msg_api_get_msg_index (u8 * name_and_crc)
1120{
Dave Barach39d69112019-11-27 11:42:13 -05001121 api_main_t *am = vlibapi_get_main ();
Florin Corase86a8ed2018-01-05 03:20:25 -08001122 uword *p;
1123
1124 if (am->msg_index_by_name_and_crc)
1125 {
1126 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
1127 if (p)
1128 return p[0];
1129 }
1130 return ~0;
1131}
1132
Ole Troan73710c72018-06-04 22:27:49 +02001133void *
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001134vl_msg_push_heap_w_region (svm_region_t * vlib_rp)
1135{
1136 pthread_mutex_lock (&vlib_rp->mutex);
1137 return svm_push_data_heap (vlib_rp);
1138}
1139
1140void *
Ole Troan73710c72018-06-04 22:27:49 +02001141vl_msg_push_heap (void)
1142{
Dave Barach39d69112019-11-27 11:42:13 -05001143 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001144 return vl_msg_push_heap_w_region (am->vlib_rp);
1145}
1146
1147void
1148vl_msg_pop_heap_w_region (svm_region_t * vlib_rp, void *oldheap)
1149{
1150 svm_pop_heap (oldheap);
1151 pthread_mutex_unlock (&vlib_rp->mutex);
Ole Troan73710c72018-06-04 22:27:49 +02001152}
1153
1154void
1155vl_msg_pop_heap (void *oldheap)
1156{
Dave Barach39d69112019-11-27 11:42:13 -05001157 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001158 vl_msg_pop_heap_w_region (am->vlib_rp, oldheap);
Ole Troan73710c72018-06-04 22:27:49 +02001159}
1160
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001161/* Must be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001162int
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001163vl_api_c_string_to_api_string (const char *buf, vl_api_string_t * str)
Neale Ranns377860a2019-06-21 07:57:18 -07001164{
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001165 /* copy without nul terminator */
1166 u32 len = strlen (buf);
1167 if (len > 0)
Ole Troan33a58172019-09-04 09:12:29 +02001168 clib_memcpy_fast (str->buf, buf, len);
Neale Ranns377860a2019-06-21 07:57:18 -07001169 str->length = htonl (len);
1170 return len + sizeof (u32);
1171}
1172
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001173/* Must NOT be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001174int
1175vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
1176{
1177 u32 len = vec_len (vec);
1178 clib_memcpy (str->buf, vec, len);
1179 str->length = htonl (len);
1180 return len + sizeof (u32);
1181}
1182
Neale Ranns377860a2019-06-21 07:57:18 -07001183u32
1184vl_api_string_len (vl_api_string_t * astr)
1185{
Dave Barach9683c1e2019-07-01 09:42:41 -04001186 return clib_net_to_host_u32 (astr->length);
Neale Ranns377860a2019-06-21 07:57:18 -07001187}
1188
Ole Troan33a58172019-09-04 09:12:29 +02001189u8 *
1190vl_api_format_string (u8 * s, va_list * args)
1191{
1192 vl_api_string_t *a = va_arg (*args, vl_api_string_t *);
1193 vec_add (s, a->buf, clib_net_to_host_u32 (a->length));
1194 return s;
1195}
1196
Neale Ranns377860a2019-06-21 07:57:18 -07001197/*
1198 * Returns a new vector. Remember to free it after use.
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001199 * NOT nul terminated.
Neale Ranns377860a2019-06-21 07:57:18 -07001200 */
1201u8 *
Dave Barach77841402020-04-29 17:04:10 -04001202vl_api_from_api_to_new_vec (void *mp, vl_api_string_t * astr)
Neale Ranns377860a2019-06-21 07:57:18 -07001203{
1204 u8 *v = 0;
Dave Barach77841402020-04-29 17:04:10 -04001205
1206 if (vl_msg_api_max_length (mp) < clib_net_to_host_u32 (astr->length))
1207 return format (0, "insane astr->length %u%c",
1208 clib_net_to_host_u32 (astr->length), 0);
Dave Barach9683c1e2019-07-01 09:42:41 -04001209 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
Neale Ranns377860a2019-06-21 07:57:18 -07001210 return v;
1211}
Ole Troan73710c72018-06-04 22:27:49 +02001212
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001213/*
1214 * Returns a new vector. Remember to free it after use.
1215 * Nul terminated.
1216 */
1217char *
1218vl_api_from_api_to_new_c_string (vl_api_string_t * astr)
1219{
1220 char *v = 0;
1221 if (clib_net_to_host_u32 (astr->length) > 0)
1222 {
1223 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
1224 vec_add1 (v, 0);
1225 }
1226 return v;
1227}
1228
Dave Barachb09f4d02019-07-15 16:00:03 -04001229void
1230vl_api_set_elog_main (elog_main_t * m)
1231{
Dave Barach39d69112019-11-27 11:42:13 -05001232 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001233 am->elog_main = m;
1234}
1235
1236int
1237vl_api_set_elog_trace_api_messages (int enable)
1238{
1239 int rv;
Dave Barach39d69112019-11-27 11:42:13 -05001240 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001241
1242 rv = am->elog_trace_api_messages;
1243 am->elog_trace_api_messages = enable;
1244 return rv;
1245}
1246
1247int
1248vl_api_get_elog_trace_api_messages (void)
1249{
Dave Barach39d69112019-11-27 11:42:13 -05001250 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001251
1252 return am->elog_trace_api_messages;
1253}
1254
Dave Barach371e4e12016-07-08 09:38:52 -04001255/*
1256 * fd.io coding-style-patch-verification: ON
1257 *
1258 * Local Variables:
1259 * eval: (c-set-style "gnu")
1260 * End:
1261 */