blob: 5e715d6f8298c73f1ae82d17dbd2d0f20b40eedd [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);
457 if (id < vec_len (am->msg_names))
458 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);
540 if (id < vec_len (am->msg_names))
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);
Dave Barachc3a06552018-10-01 09:25:32 -0400582 if (id < vec_len (am->msg_names))
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]))
Dave Barach371e4e12016-07-08 09:38:52 -0400657 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700658
Dave Barachb09f4d02019-07-15 16:00:03 -0400659 if (PREDICT_FALSE (am->elog_trace_api_messages))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660 {
Dave Barachc3a06552018-10-01 09:25:32 -0400661 /* *INDENT-OFF* */
Dave Barachc898a4f2019-06-14 17:29:55 -0400662 ELOG_TYPE_DECLARE (e) =
663 {
664 .format = "api-msg-done(%s): %s",
665 .format_args = "t4T4",
666 .n_enum_strings = 2,
667 .enum_strings =
668 {
669 "barrier",
670 "mp-safe",
671 }
672 };
Dave Barachc3a06552018-10-01 09:25:32 -0400673 /* *INDENT-ON* */
674
675 struct
676 {
Dave Barachc898a4f2019-06-14 17:29:55 -0400677 u32 barrier;
Dave Barachc3a06552018-10-01 09:25:32 -0400678 u32 c;
679 } *ed;
Dave Barachb09f4d02019-07-15 16:00:03 -0400680 ed = ELOG_DATA (am->elog_main, e);
Dave Barachc3a06552018-10-01 09:25:32 -0400681 if (id < vec_len (am->msg_names))
Dave Barachb09f4d02019-07-15 16:00:03 -0400682 ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
Dave Barachc3a06552018-10-01 09:25:32 -0400683 else
Dave Barachb09f4d02019-07-15 16:00:03 -0400684 ed->c = elog_string (am->elog_main, "BOGUS");
Dave Barachc898a4f2019-06-14 17:29:55 -0400685 ed->barrier = is_mp_safe;
Dave Barachc3a06552018-10-01 09:25:32 -0400686 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700687}
688
Dave Barach371e4e12016-07-08 09:38:52 -0400689void
690vl_msg_api_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700691{
Dave Barach39d69112019-11-27 11:42:13 -0500692 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700693
Dave Barach371e4e12016-07-08 09:38:52 -0400694 msg_handler_internal (am, the_msg,
695 (am->rx_trace
696 && am->rx_trace->enabled) /* trace_it */ ,
697 1 /* do_it */ , 1 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700698}
699
Dave Barach371e4e12016-07-08 09:38:52 -0400700void
701vl_msg_api_handler_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700702{
Dave Barach39d69112019-11-27 11:42:13 -0500703 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400704 msg_handler_internal (am, the_msg,
705 (am->rx_trace
706 && am->rx_trace->enabled) /* trace_it */ ,
707 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700708}
709
Dave Barach371e4e12016-07-08 09:38:52 -0400710void
711vl_msg_api_handler_no_trace_no_free (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700712{
Dave Barach39d69112019-11-27 11:42:13 -0500713 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400714 msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
715 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700716}
717
718/*
719 * Add a trace record to the API message trace buffer, if
720 * API message tracing is enabled. Handy for adding sufficient
721 * data to the trace to reproduce autonomous state, as opposed to
Dave Barach371e4e12016-07-08 09:38:52 -0400722 * state downloaded via control-plane API messages. Example: the NAT
Ed Warnickecb9cada2015-12-08 15:45:58 -0700723 * application creates database entries based on packet traffic, not
724 * control-plane messages.
725 *
726 */
Dave Barach371e4e12016-07-08 09:38:52 -0400727void
728vl_msg_api_trace_only (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700729{
Dave Barach39d69112019-11-27 11:42:13 -0500730 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700731
Dave Barach371e4e12016-07-08 09:38:52 -0400732 msg_handler_internal (am, the_msg,
733 (am->rx_trace
734 && am->rx_trace->enabled) /* trace_it */ ,
735 0 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700736}
737
Dave Barach371e4e12016-07-08 09:38:52 -0400738void
739vl_msg_api_cleanup_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700740{
Dave Barach39d69112019-11-27 11:42:13 -0500741 api_main_t *am = vlibapi_get_main ();
Dave Barach9683c1e2019-07-01 09:42:41 -0400742 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700743
Dave Barach371e4e12016-07-08 09:38:52 -0400744 if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
745 {
746 clib_warning ("_vl_msg_id too large: %d\n", id);
747 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700748 }
Dave Barach371e4e12016-07-08 09:38:52 -0400749 if (am->msg_cleanup_handlers[id])
750 (*am->msg_cleanup_handlers[id]) (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700751
Dave Barach371e4e12016-07-08 09:38:52 -0400752 vl_msg_api_free (the_msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700753}
754
755/*
756 * vl_msg_api_replay_handler
757 */
Dave Barach371e4e12016-07-08 09:38:52 -0400758void
759vl_msg_api_replay_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700760{
Dave Barach39d69112019-11-27 11:42:13 -0500761 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700762
Dave Barach9683c1e2019-07-01 09:42:41 -0400763 u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700764
Dave Barach371e4e12016-07-08 09:38:52 -0400765 if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
766 {
767 clib_warning ("_vl_msg_id too large: %d\n", id);
768 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700769 }
Dave Barach371e4e12016-07-08 09:38:52 -0400770 /* do NOT trace the message... */
771 if (am->msg_handlers[id])
772 (*am->msg_handlers[id]) (the_msg);
773 /* do NOT free the message buffer... */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700774}
Dave Barach371e4e12016-07-08 09:38:52 -0400775
Dave Barachbfd92272017-05-12 11:59:25 -0400776u32
777vl_msg_api_get_msg_length (void *msg_arg)
778{
779 return vl_msg_api_get_msg_length_inline (msg_arg);
780}
781
Ed Warnickecb9cada2015-12-08 15:45:58 -0700782/*
783 * vl_msg_api_socket_handler
784 */
Dave Barach371e4e12016-07-08 09:38:52 -0400785void
786vl_msg_api_socket_handler (void *the_msg)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700787{
Dave Barach39d69112019-11-27 11:42:13 -0500788 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700789
Dave Barach371e4e12016-07-08 09:38:52 -0400790 msg_handler_internal (am, the_msg,
791 (am->rx_trace
792 && am->rx_trace->enabled) /* trace_it */ ,
793 1 /* do_it */ , 0 /* free_it */ );
Ed Warnickecb9cada2015-12-08 15:45:58 -0700794}
795
796#define foreach_msg_api_vector \
797_(msg_names) \
798_(msg_handlers) \
799_(msg_cleanup_handlers) \
800_(msg_endian_handlers) \
801_(msg_print_handlers) \
802_(api_trace_cfg) \
803_(message_bounce) \
Ole Troane796a182020-05-18 11:14:05 +0200804_(is_mp_safe) \
805_(is_autoendian)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700806
Dave Barach371e4e12016-07-08 09:38:52 -0400807void
808vl_msg_api_config (vl_msg_api_msg_config_t * c)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700809{
Dave Barach39d69112019-11-27 11:42:13 -0500810 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700811
Dave Barach65457162017-10-10 17:53:14 -0400812 /*
813 * This happens during the java core tests if the message
814 * dictionary is missing newly added xxx_reply_t messages.
815 * Should never happen, but since I shot myself in the foot once
816 * this way, I thought I'd make it easy to debug if I ever do
817 * it again... (;-)...
818 */
819 if (c->id == 0)
820 {
821 if (c->name)
822 clib_warning ("Trying to register %s with a NULL msg id!", c->name);
823 else
824 clib_warning ("Trying to register a NULL msg with a NULL msg id!");
825 clib_warning ("Did you forget to call setup_message_id_table?");
826 return;
827 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700828
829#define _(a) vec_validate (am->a, c->id);
Dave Barach371e4e12016-07-08 09:38:52 -0400830 foreach_msg_api_vector;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700831#undef _
832
Dave Barach392206e2017-09-20 08:40:16 -0400833 if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
834 clib_warning
835 ("BUG: re-registering 'vl_api_%s_t_handler'."
836 "Handler was %llx, replaced by %llx",
837 c->name, am->msg_handlers[c->id], c->handler);
Dave Baracha1a093d2017-03-02 13:13:23 -0500838
Dave Barach371e4e12016-07-08 09:38:52 -0400839 am->msg_names[c->id] = c->name;
840 am->msg_handlers[c->id] = c->handler;
841 am->msg_cleanup_handlers[c->id] = c->cleanup;
842 am->msg_endian_handlers[c->id] = c->endian;
843 am->msg_print_handlers[c->id] = c->print;
844 am->message_bounce[c->id] = c->message_bounce;
845 am->is_mp_safe[c->id] = c->is_mp_safe;
Ole Troane796a182020-05-18 11:14:05 +0200846 am->is_autoendian[c->id] = c->is_autoendian;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700847
Dave Barach371e4e12016-07-08 09:38:52 -0400848 am->api_trace_cfg[c->id].size = c->size;
849 am->api_trace_cfg[c->id].trace_enable = c->traced;
850 am->api_trace_cfg[c->id].replay_enable = c->replay;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700851}
852
Dave Barach371e4e12016-07-08 09:38:52 -0400853/*
Ed Warnickecb9cada2015-12-08 15:45:58 -0700854 * vl_msg_api_set_handlers
855 * preserve the old API for a while
856 */
Dave Barach371e4e12016-07-08 09:38:52 -0400857void
858vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
859 void *endian, void *print, int size, int traced)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700860{
Dave Barach371e4e12016-07-08 09:38:52 -0400861 vl_msg_api_msg_config_t cfg;
862 vl_msg_api_msg_config_t *c = &cfg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700863
Dave Barachb7b92992018-10-17 10:38:51 -0400864 clib_memset (c, 0, sizeof (*c));
Dave Barach0691d6e2017-01-05 10:08:52 -0500865
Dave Barach371e4e12016-07-08 09:38:52 -0400866 c->id = id;
867 c->name = name;
868 c->handler = handler;
869 c->cleanup = cleanup;
870 c->endian = endian;
871 c->print = print;
Dave Barach371e4e12016-07-08 09:38:52 -0400872 c->traced = traced;
873 c->replay = 1;
874 c->message_bounce = 0;
875 c->is_mp_safe = 0;
Ole Troane796a182020-05-18 11:14:05 +0200876 c->is_autoendian = 0;
Dave Barach371e4e12016-07-08 09:38:52 -0400877 vl_msg_api_config (c);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700878}
879
Dave Barach371e4e12016-07-08 09:38:52 -0400880void
Matej Perina75a17ec2017-09-21 17:03:27 +0200881vl_msg_api_clean_handlers (int msg_id)
882{
883 vl_msg_api_msg_config_t cfg;
884 vl_msg_api_msg_config_t *c = &cfg;
885
Dave Barachb7b92992018-10-17 10:38:51 -0400886 clib_memset (c, 0, sizeof (*c));
Matej Perina75a17ec2017-09-21 17:03:27 +0200887
888 c->id = msg_id;
889 vl_msg_api_config (c);
890}
891
892void
Dave Barach371e4e12016-07-08 09:38:52 -0400893vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700894{
Dave Barach39d69112019-11-27 11:42:13 -0500895 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400896 ASSERT (msg_id > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700897
Dave Barach371e4e12016-07-08 09:38:52 -0400898 vec_validate (am->msg_cleanup_handlers, msg_id);
899 am->msg_cleanup_handlers[msg_id] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700900}
901
Dave Barach371e4e12016-07-08 09:38:52 -0400902void
Florin Corase86a8ed2018-01-05 03:20:25 -0800903vl_msg_api_queue_handler (svm_queue_t * q)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700904{
Dave Barach371e4e12016-07-08 09:38:52 -0400905 uword msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700906
Mohsin Kazmi3fca5672018-01-04 18:57:26 +0100907 while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
Dave Barach371e4e12016-07-08 09:38:52 -0400908 vl_msg_api_handler ((void *) msg);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700909}
910
Dave Barach77841402020-04-29 17:04:10 -0400911u32
912vl_msg_api_max_length (void *mp)
913{
914 msgbuf_t *mb;
915 u32 data_len = ~0;
916
917 /* Work out the maximum sane message length, and return it */
918 if (PREDICT_TRUE (mp != 0))
919 {
920 mb = (msgbuf_t *) (((u8 *) mp) - offsetof (msgbuf_t, data));
921 data_len = clib_net_to_host_u32 (mb->data_len);
922 }
923 return data_len;
924}
925
Dave Barach371e4e12016-07-08 09:38:52 -0400926vl_api_trace_t *
927vl_msg_api_trace_get (api_main_t * am, vl_api_trace_which_t which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700928{
Dave Barach371e4e12016-07-08 09:38:52 -0400929 switch (which)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700930 {
931 case VL_API_TRACE_RX:
Dave Barach371e4e12016-07-08 09:38:52 -0400932 return am->rx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700933 case VL_API_TRACE_TX:
Dave Barach371e4e12016-07-08 09:38:52 -0400934 return am->tx_trace;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700935 default:
Dave Barach371e4e12016-07-08 09:38:52 -0400936 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700937 }
938}
939
Dave Barach371e4e12016-07-08 09:38:52 -0400940void
941vl_noop_handler (void *mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700942{
Ed Warnickecb9cada2015-12-08 15:45:58 -0700943}
944
Ed Warnickecb9cada2015-12-08 15:45:58 -0700945
946static u8 post_mortem_dump_enabled;
947
Dave Barach80f54e22017-03-08 19:08:56 -0500948void
949vl_msg_api_post_mortem_dump_enable_disable (int enable)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700950{
Dave Barach80f54e22017-03-08 19:08:56 -0500951 post_mortem_dump_enabled = enable;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700952}
953
Dave Barach371e4e12016-07-08 09:38:52 -0400954void
955vl_msg_api_post_mortem_dump (void)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700956{
Dave Barach39d69112019-11-27 11:42:13 -0500957 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -0400958 FILE *fp;
959 char filename[64];
960 int rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700961
Dave Barach371e4e12016-07-08 09:38:52 -0400962 if (post_mortem_dump_enabled == 0)
963 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700964
Dave Barach371e4e12016-07-08 09:38:52 -0400965 snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
966 getpid ());
Ed Warnickecb9cada2015-12-08 15:45:58 -0700967
Dave Barach371e4e12016-07-08 09:38:52 -0400968 fp = fopen (filename, "w");
969 if (fp == NULL)
970 {
971 rv = write (2, "Couldn't create ", 16);
972 rv = write (2, filename, strlen (filename));
973 rv = write (2, "\n", 1);
974 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700975 }
Dave Barach371e4e12016-07-08 09:38:52 -0400976 rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp);
977 fclose (fp);
978 if (rv < 0)
979 {
980 rv = write (2, "Failed to save post-mortem API trace to ", 40);
981 rv = write (2, filename, strlen (filename));
982 rv = write (2, "\n", 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700983 }
Dave Barach371e4e12016-07-08 09:38:52 -0400984
Ed Warnickecb9cada2015-12-08 15:45:58 -0700985}
986
987/* Layered message handling support */
988
Dave Barach371e4e12016-07-08 09:38:52 -0400989void
990vl_msg_api_register_pd_handler (void *fp, u16 msg_id_host_byte_order)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700991{
Dave Barach39d69112019-11-27 11:42:13 -0500992 api_main_t *am = vlibapi_get_main ();
Ed Warnickecb9cada2015-12-08 15:45:58 -0700993
Dave Barach371e4e12016-07-08 09:38:52 -0400994 /* Mild idiot proofing */
995 if (msg_id_host_byte_order > 10000)
996 clib_warning ("msg_id_host_byte_order endian issue? %d arg vs %d",
997 msg_id_host_byte_order,
998 clib_net_to_host_u16 (msg_id_host_byte_order));
999 vec_validate (am->pd_msg_handlers, msg_id_host_byte_order);
1000 am->pd_msg_handlers[msg_id_host_byte_order] = fp;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001001}
1002
Dave Barach371e4e12016-07-08 09:38:52 -04001003int
1004vl_msg_api_pd_handler (void *mp, int rv)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001005{
Dave Barach39d69112019-11-27 11:42:13 -05001006 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -04001007 int (*fp) (void *, int);
1008 u16 msg_id;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001009
Dave Barach371e4e12016-07-08 09:38:52 -04001010 if (clib_arch_is_little_endian)
1011 msg_id = clib_net_to_host_u16 (*((u16 *) mp));
1012 else
1013 msg_id = *((u16 *) mp);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001014
Dave Barach371e4e12016-07-08 09:38:52 -04001015 if (msg_id >= vec_len (am->pd_msg_handlers)
1016 || am->pd_msg_handlers[msg_id] == 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001017 return rv;
Dave Barach371e4e12016-07-08 09:38:52 -04001018
1019 fp = am->pd_msg_handlers[msg_id];
1020 rv = (*fp) (mp, rv);
1021 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001022}
1023
Dave Barach371e4e12016-07-08 09:38:52 -04001024void
1025vl_msg_api_set_first_available_msg_id (u16 first_avail)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001026{
Dave Barach39d69112019-11-27 11:42:13 -05001027 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -04001028
1029 am->first_available_msg_id = first_avail;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001030}
1031
Dave Barach371e4e12016-07-08 09:38:52 -04001032u16
Neale Rannse72be392017-04-26 13:59:20 -07001033vl_msg_api_get_msg_ids (const char *name, int n)
Ed Warnickecb9cada2015-12-08 15:45:58 -07001034{
Dave Barach39d69112019-11-27 11:42:13 -05001035 api_main_t *am = vlibapi_get_main ();
Dave Barach371e4e12016-07-08 09:38:52 -04001036 u8 *name_copy;
1037 vl_api_msg_range_t *rp;
1038 uword *p;
1039 u16 rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001040
Dave Barach371e4e12016-07-08 09:38:52 -04001041 if (am->msg_range_by_name == 0)
1042 am->msg_range_by_name = hash_create_string (0, sizeof (uword));
Ed Warnickecb9cada2015-12-08 15:45:58 -07001043
Dave Barach371e4e12016-07-08 09:38:52 -04001044 name_copy = format (0, "%s%c", name, 0);
1045
1046 p = hash_get_mem (am->msg_range_by_name, name_copy);
1047 if (p)
1048 {
1049 clib_warning ("WARNING: duplicate message range registration for '%s'",
1050 name_copy);
1051 vec_free (name_copy);
1052 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001053 }
1054
Dave Barach371e4e12016-07-08 09:38:52 -04001055 if (n < 0 || n > 1024)
1056 {
1057 clib_warning
1058 ("WARNING: bad number of message-IDs (%d) requested by '%s'",
1059 n, name_copy);
1060 vec_free (name_copy);
1061 return ((u16) ~ 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001062 }
1063
Dave Barach371e4e12016-07-08 09:38:52 -04001064 vec_add2 (am->msg_ranges, rp, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001065
Dave Barach371e4e12016-07-08 09:38:52 -04001066 rv = rp->first_msg_id = am->first_available_msg_id;
1067 am->first_available_msg_id += n;
1068 rp->last_msg_id = am->first_available_msg_id - 1;
1069 rp->name = name_copy;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001070
Dave Barach371e4e12016-07-08 09:38:52 -04001071 hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
Ed Warnickecb9cada2015-12-08 15:45:58 -07001072
Dave Barach371e4e12016-07-08 09:38:52 -04001073 return rv;
Ed Warnickecb9cada2015-12-08 15:45:58 -07001074}
Dave Barach371e4e12016-07-08 09:38:52 -04001075
Dave Barach557d1282016-11-10 14:22:49 -05001076void
Neale Rannse72be392017-04-26 13:59:20 -07001077vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
Dave Barach557d1282016-11-10 14:22:49 -05001078{
1079 uword *p;
1080
1081 if (am->msg_index_by_name_and_crc == 0)
1082 am->msg_index_by_name_and_crc = hash_create_string (0, sizeof (uword));
1083
1084 p = hash_get_mem (am->msg_index_by_name_and_crc, string);
1085 if (p)
1086 {
1087 clib_warning ("attempt to redefine '%s' ignored...", string);
1088 return;
1089 }
1090
1091 hash_set_mem (am->msg_index_by_name_and_crc, string, id);
1092}
1093
Dave Barach0d056e52017-09-28 15:11:16 -04001094void
1095vl_msg_api_add_version (api_main_t * am, const char *string,
1096 u32 major, u32 minor, u32 patch)
1097{
1098 api_version_t version = {.major = major,.minor = minor,.patch = patch };
1099 ASSERT (strlen (string) < 64);
Ole Troan7504e992017-10-10 08:43:35 +02001100 strncpy (version.name, string, 64 - 1);
Dave Barach0d056e52017-09-28 15:11:16 -04001101 vec_add1 (am->api_version_list, version);
1102}
Dave Barach557d1282016-11-10 14:22:49 -05001103
Florin Corase86a8ed2018-01-05 03:20:25 -08001104u32
1105vl_msg_api_get_msg_index (u8 * name_and_crc)
1106{
Dave Barach39d69112019-11-27 11:42:13 -05001107 api_main_t *am = vlibapi_get_main ();
Florin Corase86a8ed2018-01-05 03:20:25 -08001108 uword *p;
1109
1110 if (am->msg_index_by_name_and_crc)
1111 {
1112 p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
1113 if (p)
1114 return p[0];
1115 }
1116 return ~0;
1117}
1118
Ole Troan73710c72018-06-04 22:27:49 +02001119void *
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001120vl_msg_push_heap_w_region (svm_region_t * vlib_rp)
1121{
1122 pthread_mutex_lock (&vlib_rp->mutex);
1123 return svm_push_data_heap (vlib_rp);
1124}
1125
1126void *
Ole Troan73710c72018-06-04 22:27:49 +02001127vl_msg_push_heap (void)
1128{
Dave Barach39d69112019-11-27 11:42:13 -05001129 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001130 return vl_msg_push_heap_w_region (am->vlib_rp);
1131}
1132
1133void
1134vl_msg_pop_heap_w_region (svm_region_t * vlib_rp, void *oldheap)
1135{
1136 svm_pop_heap (oldheap);
1137 pthread_mutex_unlock (&vlib_rp->mutex);
Ole Troan73710c72018-06-04 22:27:49 +02001138}
1139
1140void
1141vl_msg_pop_heap (void *oldheap)
1142{
Dave Barach39d69112019-11-27 11:42:13 -05001143 api_main_t *am = vlibapi_get_main ();
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001144 vl_msg_pop_heap_w_region (am->vlib_rp, oldheap);
Ole Troan73710c72018-06-04 22:27:49 +02001145}
1146
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001147/* Must be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001148int
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001149vl_api_c_string_to_api_string (const char *buf, vl_api_string_t * str)
Neale Ranns377860a2019-06-21 07:57:18 -07001150{
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001151 /* copy without nul terminator */
1152 u32 len = strlen (buf);
1153 if (len > 0)
Ole Troan33a58172019-09-04 09:12:29 +02001154 clib_memcpy_fast (str->buf, buf, len);
Neale Ranns377860a2019-06-21 07:57:18 -07001155 str->length = htonl (len);
1156 return len + sizeof (u32);
1157}
1158
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001159/* Must NOT be nul terminated */
Neale Ranns377860a2019-06-21 07:57:18 -07001160int
1161vl_api_vec_to_api_string (const u8 * vec, vl_api_string_t * str)
1162{
1163 u32 len = vec_len (vec);
1164 clib_memcpy (str->buf, vec, len);
1165 str->length = htonl (len);
1166 return len + sizeof (u32);
1167}
1168
Neale Ranns377860a2019-06-21 07:57:18 -07001169u32
1170vl_api_string_len (vl_api_string_t * astr)
1171{
Dave Barach9683c1e2019-07-01 09:42:41 -04001172 return clib_net_to_host_u32 (astr->length);
Neale Ranns377860a2019-06-21 07:57:18 -07001173}
1174
Ole Troan33a58172019-09-04 09:12:29 +02001175u8 *
1176vl_api_format_string (u8 * s, va_list * args)
1177{
1178 vl_api_string_t *a = va_arg (*args, vl_api_string_t *);
1179 vec_add (s, a->buf, clib_net_to_host_u32 (a->length));
1180 return s;
1181}
1182
Neale Ranns377860a2019-06-21 07:57:18 -07001183/*
1184 * Returns a new vector. Remember to free it after use.
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001185 * NOT nul terminated.
Neale Ranns377860a2019-06-21 07:57:18 -07001186 */
1187u8 *
Dave Barach77841402020-04-29 17:04:10 -04001188vl_api_from_api_to_new_vec (void *mp, vl_api_string_t * astr)
Neale Ranns377860a2019-06-21 07:57:18 -07001189{
1190 u8 *v = 0;
Dave Barach77841402020-04-29 17:04:10 -04001191
1192 if (vl_msg_api_max_length (mp) < clib_net_to_host_u32 (astr->length))
1193 return format (0, "insane astr->length %u%c",
1194 clib_net_to_host_u32 (astr->length), 0);
Dave Barach9683c1e2019-07-01 09:42:41 -04001195 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
Neale Ranns377860a2019-06-21 07:57:18 -07001196 return v;
1197}
Ole Troan73710c72018-06-04 22:27:49 +02001198
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001199/*
1200 * Returns a new vector. Remember to free it after use.
1201 * Nul terminated.
1202 */
1203char *
1204vl_api_from_api_to_new_c_string (vl_api_string_t * astr)
1205{
1206 char *v = 0;
1207 if (clib_net_to_host_u32 (astr->length) > 0)
1208 {
1209 vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
1210 vec_add1 (v, 0);
1211 }
1212 return v;
1213}
1214
Dave Barachb09f4d02019-07-15 16:00:03 -04001215void
1216vl_api_set_elog_main (elog_main_t * m)
1217{
Dave Barach39d69112019-11-27 11:42:13 -05001218 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001219 am->elog_main = m;
1220}
1221
1222int
1223vl_api_set_elog_trace_api_messages (int enable)
1224{
1225 int rv;
Dave Barach39d69112019-11-27 11:42:13 -05001226 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001227
1228 rv = am->elog_trace_api_messages;
1229 am->elog_trace_api_messages = enable;
1230 return rv;
1231}
1232
1233int
1234vl_api_get_elog_trace_api_messages (void)
1235{
Dave Barach39d69112019-11-27 11:42:13 -05001236 api_main_t *am = vlibapi_get_main ();
Dave Barachb09f4d02019-07-15 16:00:03 -04001237
1238 return am->elog_trace_api_messages;
1239}
1240
Dave Barach371e4e12016-07-08 09:38:52 -04001241/*
1242 * fd.io coding-style-patch-verification: ON
1243 *
1244 * Local Variables:
1245 * eval: (c-set-style "gnu")
1246 * End:
1247 */