FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
api_shared.c
Go to the documentation of this file.
1 /*
2  *------------------------------------------------------------------
3  * api_shared.c - API message handling, common code for both clients
4  * and the vlib process itself.
5  *
6  *
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>
24 #include <stddef.h>
25 #include <string.h>
26 #include <vppinfra/format.h>
27 #include <vppinfra/byte_order.h>
28 #include <vppinfra/error.h>
29 #include <vlib/vlib.h>
30 #include <vlib/unix/unix.h>
31 #include <vlibapi/api.h>
32 #include <vppinfra/elog.h>
33 
34 /* *INDENT-OFF* */
35 api_main_t api_global_main =
36  {
37  .region_name = "/unset",
38  .api_uid = -1,
39  .api_gid = -1,
40  };
41 /* *INDENT-ON* */
42 
43 /* Please use vlibapi_get_main() to access my_api_main */
45 
46 void
48 {
49  ASSERT (am_arg);
50  my_api_main = (api_main_t *) am_arg;
51 }
52 
53 void
55 {
57  am->missing_clients++;
58 }
59 
60 int
62 {
63  return (am->rx_trace && am->rx_trace->enabled);
64 }
65 
66 int
68 {
69  return (am->tx_trace && am->tx_trace->enabled);
70 }
71 
72 /*
73  * vl_msg_api_trace
74  */
75 void
77 {
78  u8 **this_trace;
79  u8 **old_trace;
80  u8 *msg_copy;
81  u32 length;
82  trace_cfg_t *cfgp;
83  u16 msg_id = clib_net_to_host_u16 (*((u16 *) msg));
84  msgbuf_t *header = (msgbuf_t *) (((u8 *) msg) - offsetof (msgbuf_t, data));
85 
86  cfgp = am->api_trace_cfg + msg_id;
87 
88  if (!cfgp || !cfgp->trace_enable)
89  return;
90 
91  msg_copy = 0;
92 
93  if (tp->nitems == 0)
94  {
95  clib_warning ("tp->nitems is 0");
96  return;
97  }
98 
99  if (vec_len (tp->traces) < tp->nitems)
100  {
101  vec_add1 (tp->traces, 0);
102  this_trace = tp->traces + vec_len (tp->traces) - 1;
103  }
104  else
105  {
106  tp->wrapped = 1;
107  old_trace = tp->traces + tp->curindex++;
108  if (tp->curindex == tp->nitems)
109  tp->curindex = 0;
110  /* Reuse the trace record, may save some memory allocator traffic */
111  msg_copy = *old_trace;
112  vec_reset_length (msg_copy);
113  this_trace = old_trace;
114  }
115 
116  length = clib_net_to_host_u32 (header->data_len);
117 
118  vec_validate (msg_copy, length - 1);
119  clib_memcpy_fast (msg_copy, msg, length);
120  *this_trace = msg_copy;
121 }
122 
123 int
125  int onoff)
126 {
127  vl_api_trace_t *tp;
128  int rv;
129 
130  switch (which)
131  {
132  case VL_API_TRACE_TX:
133  tp = am->tx_trace;
134  if (tp == 0)
135  {
136  vl_msg_api_trace_configure (am, which, 1024);
137  tp = am->tx_trace;
138  }
139  break;
140 
141  case VL_API_TRACE_RX:
142  tp = am->rx_trace;
143  if (tp == 0)
144  {
145  vl_msg_api_trace_configure (am, which, 1024);
146  tp = am->rx_trace;
147  }
148  break;
149 
150  default:
151  /* duh? */
152  return -1;
153  }
154 
155  /* Configured? */
156  if (tp == 0 || tp->nitems == 0)
157  return -1;
158 
159  rv = tp->enabled;
160  tp->enabled = onoff;
161 
162  return rv;
163 }
164 
165 int
167 {
168  vl_api_trace_t *tp;
169  int i;
170 
171  switch (which)
172  {
173  case VL_API_TRACE_TX:
174  tp = am->tx_trace;
175  break;
176 
177  case VL_API_TRACE_RX:
178  tp = am->rx_trace;
179  break;
180 
181  default:
182  /* duh? */
183  return -1;
184  }
185 
186  /* Configured? */
187  if (!tp || tp->nitems == 0)
188  return -1;
189 
190  tp->curindex = 0;
191  tp->wrapped = 0;
192 
193  for (i = 0; i < vec_len (tp->traces); i++)
194  {
195  vec_free (tp->traces[i]);
196  }
197  vec_free (tp->traces);
198 
199  return 0;
200 }
201 
202 u8 *
204 {
205  serialize_main_t _sm, *sm = &_sm;
206  hash_pair_t *hp;
208 
209  serialize_open_vector (sm, vector);
210 
211  /* serialize the count */
212  serialize_integer (sm, nmsg, sizeof (u32));
213 
214  /* *INDENT-OFF* */
216  ({
217  serialize_likely_small_unsigned_integer (sm, hp->value[0]);
218  serialize_cstring (sm, (char *) hp->key);
219  }));
220  /* *INDENT-ON* */
221 
222  return serialize_close_vector (sm);
223 }
224 
225 int
227 {
228  vl_api_trace_t *tp;
229  vl_api_trace_file_header_t fh;
230  int i;
231  u8 *msg;
232 
233  switch (which)
234  {
235  case VL_API_TRACE_TX:
236  tp = am->tx_trace;
237  break;
238 
239  case VL_API_TRACE_RX:
240  tp = am->rx_trace;
241  break;
242 
243  default:
244  /* duh? */
245  return -1;
246  }
247 
248  /* Configured, data present? */
249  if (tp == 0 || tp->nitems == 0 || vec_len (tp->traces) == 0)
250  return -1;
251 
252  /* "Dare to be stupid" check */
253  if (fp == 0)
254  {
255  return -2;
256  }
257 
258  /* Write the file header */
259  fh.wrapped = tp->wrapped;
260  fh.nitems = clib_host_to_net_u32 (vec_len (tp->traces));
261  u8 *m = vl_api_serialize_message_table (am, 0);
262  fh.msgtbl_size = clib_host_to_net_u32 (vec_len (m));
263 
264  if (fwrite (&fh, sizeof (fh), 1, fp) != 1)
265  {
266  return (-10);
267  }
268 
269  /* Write the message table */
270  if (fwrite (m, vec_len (m), 1, fp) != 1)
271  {
272  return (-14);
273  }
274  vec_free (m);
275 
276  /* No-wrap case */
277  if (tp->wrapped == 0)
278  {
279  /*
280  * Note: vec_len return 0 when fed a NULL pointer.
281  * Unfortunately, the static analysis tool doesn't
282  * figure it out, hence the suppressed warnings.
283  * What a great use of my time.
284  */
285  for (i = 0; i < vec_len (tp->traces); i++)
286  {
287  u32 msg_length;
288  /*sa_ignore NO_NULL_CHK */
289  msg = tp->traces[i];
290  /*
291  * This retarded check required to pass
292  * [sic] SA-checking.
293  */
294  if (!msg)
295  continue;
296 
297  msg_length = clib_host_to_net_u32 (vec_len (msg));
298  if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
299  != sizeof (msg_length))
300  {
301  return (-14);
302  }
303  if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
304  {
305  return (-11);
306  }
307  }
308  }
309  else
310  {
311  /* Wrap case: write oldest -> end of buffer */
312  for (i = tp->curindex; i < vec_len (tp->traces); i++)
313  {
314  u32 msg_length;
315  msg = tp->traces[i];
316  /*
317  * This retarded check required to pass
318  * [sic] SA-checking
319  */
320  if (!msg)
321  continue;
322 
323  msg_length = clib_host_to_net_u32 (vec_len (msg));
324  if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
325  != sizeof (msg_length))
326  {
327  return (-14);
328  }
329 
330  if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
331  {
332  return (-12);
333  }
334  }
335  /* write beginning of buffer -> oldest-1 */
336  for (i = 0; i < tp->curindex; i++)
337  {
338  u32 msg_length;
339  /*sa_ignore NO_NULL_CHK */
340  msg = tp->traces[i];
341  /*
342  * This retarded check required to pass
343  * [sic] SA-checking
344  */
345  if (!msg)
346  continue;
347 
348  msg_length = clib_host_to_net_u32 (vec_len (msg));
349  if (fwrite (&msg_length, 1, sizeof (msg_length), fp)
350  != sizeof (msg_length))
351  {
352  return (-14);
353  }
354 
355  if (fwrite (msg, 1, vec_len (msg), fp) != vec_len (msg))
356  {
357  return (-13);
358  }
359  }
360  }
361  return 0;
362 }
363 
364 int
366  u32 nitems)
367 {
368  vl_api_trace_t *tp;
369  int was_on = 0;
370 
371  switch (which)
372  {
373  case VL_API_TRACE_TX:
374  tp = am->tx_trace;
375  if (tp == 0)
376  {
377  vec_validate (am->tx_trace, 0);
378  tp = am->tx_trace;
379  }
380  break;
381 
382  case VL_API_TRACE_RX:
383  tp = am->rx_trace;
384  if (tp == 0)
385  {
386  vec_validate (am->rx_trace, 0);
387  tp = am->rx_trace;
388  }
389 
390  break;
391 
392  default:
393  return -1;
394 
395  }
396 
397  if (tp->enabled)
398  {
399  was_on = vl_msg_api_trace_onoff (am, which, 0);
400  }
401  if (tp->traces)
402  {
403  vl_msg_api_trace_free (am, which);
404  }
405 
406  clib_memset (tp, 0, sizeof (*tp));
407 
409  {
411  }
412  else
413  {
415  }
416 
417  tp->nitems = nitems;
418  if (was_on)
419  {
420  (void) vl_msg_api_trace_onoff (am, which, was_on);
421  }
422  return 0;
423 }
424 
425 void
427 {
428 }
429 
430 void
432 {
433 }
434 
435 always_inline void
437  void *the_msg, int trace_it, int do_it, int free_it)
438 {
439  u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
440  u8 *(*print_fp) (void *, void *);
441 
443  {
444  /* *INDENT-OFF* */
445  ELOG_TYPE_DECLARE (e) =
446  {
447  .format = "api-msg: %s",
448  .format_args = "T4",
449  };
450  /* *INDENT-ON* */
451  struct
452  {
453  u32 c;
454  } *ed;
455  ed = ELOG_DATA (am->elog_main, e);
456  if (id < vec_len (am->msg_names))
457  ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
458  else
459  ed->c = elog_string (am->elog_main, "BOGUS");
460  }
461 
462  if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
463  {
464  if (trace_it)
465  vl_msg_api_trace (am, am->rx_trace, the_msg);
466 
467  if (am->msg_print_flag)
468  {
469  fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
470  print_fp = (void *) am->msg_print_handlers[id];
471  if (print_fp == 0)
472  {
473  fformat (stdout, " [no registered print fn]\n");
474  }
475  else
476  {
477  (*print_fp) (the_msg, stdout);
478  }
479  }
480 
481  if (do_it)
482  {
483  if (!am->is_mp_safe[id])
484  {
487  }
488  (*am->msg_handlers[id]) (the_msg);
489  if (!am->is_mp_safe[id])
491  }
492  }
493  else
494  {
495  clib_warning ("no handler for msg id %d", id);
496  }
497 
498  if (free_it)
499  vl_msg_api_free (the_msg);
500 
502  {
503  /* *INDENT-OFF* */
504  ELOG_TYPE_DECLARE (e) =
505  {
506  .format = "api-msg-done(%s): %s",
507  .format_args = "t4T4",
508  .n_enum_strings = 2,
509  .enum_strings =
510  {
511  "barrier",
512  "mp-safe",
513  }
514  };
515  /* *INDENT-ON* */
516 
517  struct
518  {
519  u32 barrier;
520  u32 c;
521  } *ed;
522  ed = ELOG_DATA (am->elog_main, e);
523  if (id < vec_len (am->msg_names))
524  {
525  ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
526  ed->barrier = !am->is_mp_safe[id];
527  }
528  else
529  {
530  ed->c = elog_string (am->elog_main, "BOGUS");
531  ed->barrier = 0;
532  }
533  }
534 }
535 
536 /* This is only to be called from a vlib/vnet app */
537 void
539  void *the_msg, vlib_main_t * vm,
540  vlib_node_runtime_t * node, u8 is_private)
541 {
542  u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
543  u8 *(*handler) (void *, void *, void *);
544  u8 *(*print_fp) (void *, void *);
545  svm_region_t *old_vlib_rp;
546  void *save_shmem_hdr;
547  int is_mp_safe = 1;
548 
550  {
551  /* *INDENT-OFF* */
552  ELOG_TYPE_DECLARE (e) =
553  {
554  .format = "api-msg: %s",
555  .format_args = "T4",
556  };
557  /* *INDENT-ON* */
558  struct
559  {
560  u32 c;
561  } *ed;
562  ed = ELOG_DATA (am->elog_main, e);
563  if (id < vec_len (am->msg_names))
564  ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
565  else
566  ed->c = elog_string (am->elog_main, "BOGUS");
567  }
568 
569  if (id < vec_len (am->msg_handlers) && am->msg_handlers[id])
570  {
571  handler = (void *) am->msg_handlers[id];
572 
573  if (PREDICT_FALSE (am->rx_trace && am->rx_trace->enabled))
574  vl_msg_api_trace (am, am->rx_trace, the_msg);
575 
576  if (PREDICT_FALSE (am->msg_print_flag))
577  {
578  fformat (stdout, "[%d]: %s\n", id, am->msg_names[id]);
579  print_fp = (void *) am->msg_print_handlers[id];
580  if (print_fp == 0)
581  {
582  fformat (stdout, " [no registered print fn for msg %d]\n", id);
583  }
584  else
585  {
586  (*print_fp) (the_msg, vm);
587  }
588  }
589  is_mp_safe = am->is_mp_safe[id];
590 
591  if (!is_mp_safe)
592  {
595  }
596  if (is_private)
597  {
598  old_vlib_rp = am->vlib_rp;
599  save_shmem_hdr = am->shmem_hdr;
600  am->vlib_rp = vlib_rp;
601  am->shmem_hdr = (void *) vlib_rp->user_ctx;
602  }
603  (*handler) (the_msg, vm, node);
604  if (is_private)
605  {
606  am->vlib_rp = old_vlib_rp;
607  am->shmem_hdr = save_shmem_hdr;
608  }
609  if (!is_mp_safe)
611  }
612  else
613  {
614  clib_warning ("no handler for msg id %d", id);
615  }
616 
617  /*
618  * Special-case, so we can e.g. bounce messages off the vnet
619  * main thread without copying them...
620  */
621  if (!(am->message_bounce[id]))
622  vl_msg_api_free (the_msg);
623 
625  {
626  /* *INDENT-OFF* */
627  ELOG_TYPE_DECLARE (e) =
628  {
629  .format = "api-msg-done(%s): %s",
630  .format_args = "t4T4",
631  .n_enum_strings = 2,
632  .enum_strings =
633  {
634  "barrier",
635  "mp-safe",
636  }
637  };
638  /* *INDENT-ON* */
639 
640  struct
641  {
642  u32 barrier;
643  u32 c;
644  } *ed;
645  ed = ELOG_DATA (am->elog_main, e);
646  if (id < vec_len (am->msg_names))
647  ed->c = elog_string (am->elog_main, (char *) am->msg_names[id]);
648  else
649  ed->c = elog_string (am->elog_main, "BOGUS");
650  ed->barrier = is_mp_safe;
651  }
652 }
653 
654 void
655 vl_msg_api_handler (void *the_msg)
656 {
657  api_main_t *am = vlibapi_get_main ();
658 
659  msg_handler_internal (am, the_msg,
660  (am->rx_trace
661  && am->rx_trace->enabled) /* trace_it */ ,
662  1 /* do_it */ , 1 /* free_it */ );
663 }
664 
665 void
667 {
668  api_main_t *am = vlibapi_get_main ();
669  msg_handler_internal (am, the_msg,
670  (am->rx_trace
671  && am->rx_trace->enabled) /* trace_it */ ,
672  1 /* do_it */ , 0 /* free_it */ );
673 }
674 
675 void
677 {
678  api_main_t *am = vlibapi_get_main ();
679  msg_handler_internal (am, the_msg, 0 /* trace_it */ , 1 /* do_it */ ,
680  0 /* free_it */ );
681 }
682 
683 /*
684  * Add a trace record to the API message trace buffer, if
685  * API message tracing is enabled. Handy for adding sufficient
686  * data to the trace to reproduce autonomous state, as opposed to
687  * state downloaded via control-plane API messages. Example: the NAT
688  * application creates database entries based on packet traffic, not
689  * control-plane messages.
690  *
691  */
692 void
693 vl_msg_api_trace_only (void *the_msg)
694 {
695  api_main_t *am = vlibapi_get_main ();
696 
697  msg_handler_internal (am, the_msg,
698  (am->rx_trace
699  && am->rx_trace->enabled) /* trace_it */ ,
700  0 /* do_it */ , 0 /* free_it */ );
701 }
702 
703 void
705 {
706  api_main_t *am = vlibapi_get_main ();
707  u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
708 
709  if (PREDICT_FALSE (id >= vec_len (am->msg_cleanup_handlers)))
710  {
711  clib_warning ("_vl_msg_id too large: %d\n", id);
712  return;
713  }
714  if (am->msg_cleanup_handlers[id])
715  (*am->msg_cleanup_handlers[id]) (the_msg);
716 
717  vl_msg_api_free (the_msg);
718 }
719 
720 /*
721  * vl_msg_api_replay_handler
722  */
723 void
725 {
726  api_main_t *am = vlibapi_get_main ();
727 
728  u16 id = clib_net_to_host_u16 (*((u16 *) the_msg));
729 
730  if (PREDICT_FALSE (id >= vec_len (am->msg_handlers)))
731  {
732  clib_warning ("_vl_msg_id too large: %d\n", id);
733  return;
734  }
735  /* do NOT trace the message... */
736  if (am->msg_handlers[id])
737  (*am->msg_handlers[id]) (the_msg);
738  /* do NOT free the message buffer... */
739 }
740 
741 u32
743 {
744  return vl_msg_api_get_msg_length_inline (msg_arg);
745 }
746 
747 /*
748  * vl_msg_api_socket_handler
749  */
750 void
752 {
753  api_main_t *am = vlibapi_get_main ();
754 
755  msg_handler_internal (am, the_msg,
756  (am->rx_trace
757  && am->rx_trace->enabled) /* trace_it */ ,
758  1 /* do_it */ , 0 /* free_it */ );
759 }
760 
761 #define foreach_msg_api_vector \
762 _(msg_names) \
763 _(msg_handlers) \
764 _(msg_cleanup_handlers) \
765 _(msg_endian_handlers) \
766 _(msg_print_handlers) \
767 _(api_trace_cfg) \
768 _(message_bounce) \
769 _(is_mp_safe)
770 
771 void
773 {
774  api_main_t *am = vlibapi_get_main ();
775 
776  /*
777  * This happens during the java core tests if the message
778  * dictionary is missing newly added xxx_reply_t messages.
779  * Should never happen, but since I shot myself in the foot once
780  * this way, I thought I'd make it easy to debug if I ever do
781  * it again... (;-)...
782  */
783  if (c->id == 0)
784  {
785  if (c->name)
786  clib_warning ("Trying to register %s with a NULL msg id!", c->name);
787  else
788  clib_warning ("Trying to register a NULL msg with a NULL msg id!");
789  clib_warning ("Did you forget to call setup_message_id_table?");
790  return;
791  }
792 
793 #define _(a) vec_validate (am->a, c->id);
795 #undef _
796 
797  if (am->msg_handlers[c->id] && am->msg_handlers[c->id] != c->handler)
799  ("BUG: re-registering 'vl_api_%s_t_handler'."
800  "Handler was %llx, replaced by %llx",
801  c->name, am->msg_handlers[c->id], c->handler);
802 
803  am->msg_names[c->id] = c->name;
804  am->msg_handlers[c->id] = c->handler;
805  am->msg_cleanup_handlers[c->id] = c->cleanup;
806  am->msg_endian_handlers[c->id] = c->endian;
807  am->msg_print_handlers[c->id] = c->print;
808  am->message_bounce[c->id] = c->message_bounce;
809  am->is_mp_safe[c->id] = c->is_mp_safe;
810 
811  am->api_trace_cfg[c->id].size = c->size;
812  am->api_trace_cfg[c->id].trace_enable = c->traced;
813  am->api_trace_cfg[c->id].replay_enable = c->replay;
814 }
815 
816 /*
817  * vl_msg_api_set_handlers
818  * preserve the old API for a while
819  */
820 void
821 vl_msg_api_set_handlers (int id, char *name, void *handler, void *cleanup,
822  void *endian, void *print, int size, int traced)
823 {
825  vl_msg_api_msg_config_t *c = &cfg;
826 
827  clib_memset (c, 0, sizeof (*c));
828 
829  c->id = id;
830  c->name = name;
831  c->handler = handler;
832  c->cleanup = cleanup;
833  c->endian = endian;
834  c->print = print;
835  c->traced = traced;
836  c->replay = 1;
837  c->message_bounce = 0;
838  c->is_mp_safe = 0;
839  vl_msg_api_config (c);
840 }
841 
842 void
844 {
846  vl_msg_api_msg_config_t *c = &cfg;
847 
848  clib_memset (c, 0, sizeof (*c));
849 
850  c->id = msg_id;
851  vl_msg_api_config (c);
852 }
853 
854 void
855 vl_msg_api_set_cleanup_handler (int msg_id, void *fp)
856 {
857  api_main_t *am = vlibapi_get_main ();
858  ASSERT (msg_id > 0);
859 
860  vec_validate (am->msg_cleanup_handlers, msg_id);
861  am->msg_cleanup_handlers[msg_id] = fp;
862 }
863 
864 void
866 {
867  uword msg;
868 
869  while (!svm_queue_sub (q, (u8 *) & msg, SVM_Q_WAIT, 0))
870  vl_msg_api_handler ((void *) msg);
871 }
872 
875 {
876  switch (which)
877  {
878  case VL_API_TRACE_RX:
879  return am->rx_trace;
880  case VL_API_TRACE_TX:
881  return am->tx_trace;
882  default:
883  return 0;
884  }
885 }
886 
887 void
888 vl_noop_handler (void *mp)
889 {
890 }
891 
892 
894 
895 void
897 {
898  post_mortem_dump_enabled = enable;
899 }
900 
901 void
903 {
904  api_main_t *am = vlibapi_get_main ();
905  FILE *fp;
906  char filename[64];
907  int rv;
908 
909  if (post_mortem_dump_enabled == 0)
910  return;
911 
912  snprintf (filename, sizeof (filename), "/tmp/api_post_mortem.%d",
913  getpid ());
914 
915  fp = fopen (filename, "w");
916  if (fp == NULL)
917  {
918  rv = write (2, "Couldn't create ", 16);
919  rv = write (2, filename, strlen (filename));
920  rv = write (2, "\n", 1);
921  return;
922  }
923  rv = vl_msg_api_trace_save (am, VL_API_TRACE_RX, fp);
924  fclose (fp);
925  if (rv < 0)
926  {
927  rv = write (2, "Failed to save post-mortem API trace to ", 40);
928  rv = write (2, filename, strlen (filename));
929  rv = write (2, "\n", 1);
930  }
931 
932 }
933 
934 /* Layered message handling support */
935 
936 void
937 vl_msg_api_register_pd_handler (void *fp, u16 msg_id_host_byte_order)
938 {
939  api_main_t *am = vlibapi_get_main ();
940 
941  /* Mild idiot proofing */
942  if (msg_id_host_byte_order > 10000)
943  clib_warning ("msg_id_host_byte_order endian issue? %d arg vs %d",
944  msg_id_host_byte_order,
945  clib_net_to_host_u16 (msg_id_host_byte_order));
946  vec_validate (am->pd_msg_handlers, msg_id_host_byte_order);
947  am->pd_msg_handlers[msg_id_host_byte_order] = fp;
948 }
949 
950 int
951 vl_msg_api_pd_handler (void *mp, int rv)
952 {
953  api_main_t *am = vlibapi_get_main ();
954  int (*fp) (void *, int);
955  u16 msg_id;
956 
958  msg_id = clib_net_to_host_u16 (*((u16 *) mp));
959  else
960  msg_id = *((u16 *) mp);
961 
962  if (msg_id >= vec_len (am->pd_msg_handlers)
963  || am->pd_msg_handlers[msg_id] == 0)
964  return rv;
965 
966  fp = am->pd_msg_handlers[msg_id];
967  rv = (*fp) (mp, rv);
968  return rv;
969 }
970 
971 void
973 {
974  api_main_t *am = vlibapi_get_main ();
975 
976  am->first_available_msg_id = first_avail;
977 }
978 
979 u16
980 vl_msg_api_get_msg_ids (const char *name, int n)
981 {
982  api_main_t *am = vlibapi_get_main ();
983  u8 *name_copy;
984  vl_api_msg_range_t *rp;
985  uword *p;
986  u16 rv;
987 
988  if (am->msg_range_by_name == 0)
989  am->msg_range_by_name = hash_create_string (0, sizeof (uword));
990 
991  name_copy = format (0, "%s%c", name, 0);
992 
993  p = hash_get_mem (am->msg_range_by_name, name_copy);
994  if (p)
995  {
996  clib_warning ("WARNING: duplicate message range registration for '%s'",
997  name_copy);
998  vec_free (name_copy);
999  return ((u16) ~ 0);
1000  }
1001 
1002  if (n < 0 || n > 1024)
1003  {
1004  clib_warning
1005  ("WARNING: bad number of message-IDs (%d) requested by '%s'",
1006  n, name_copy);
1007  vec_free (name_copy);
1008  return ((u16) ~ 0);
1009  }
1010 
1011  vec_add2 (am->msg_ranges, rp, 1);
1012 
1013  rv = rp->first_msg_id = am->first_available_msg_id;
1014  am->first_available_msg_id += n;
1015  rp->last_msg_id = am->first_available_msg_id - 1;
1016  rp->name = name_copy;
1017 
1018  hash_set_mem (am->msg_range_by_name, name_copy, rp - am->msg_ranges);
1019 
1020  return rv;
1021 }
1022 
1023 void
1024 vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, u32 id)
1025 {
1026  uword *p;
1027 
1028  if (am->msg_index_by_name_and_crc == 0)
1030 
1031  p = hash_get_mem (am->msg_index_by_name_and_crc, string);
1032  if (p)
1033  {
1034  clib_warning ("attempt to redefine '%s' ignored...", string);
1035  return;
1036  }
1037 
1038  hash_set_mem (am->msg_index_by_name_and_crc, string, id);
1039 }
1040 
1041 void
1042 vl_msg_api_add_version (api_main_t * am, const char *string,
1043  u32 major, u32 minor, u32 patch)
1044 {
1045  api_version_t version = {.major = major,.minor = minor,.patch = patch };
1046  ASSERT (strlen (string) < 64);
1047  strncpy (version.name, string, 64 - 1);
1048  vec_add1 (am->api_version_list, version);
1049 }
1050 
1051 u32
1053 {
1054  api_main_t *am = vlibapi_get_main ();
1055  uword *p;
1056 
1057  if (am->msg_index_by_name_and_crc)
1058  {
1059  p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc);
1060  if (p)
1061  return p[0];
1062  }
1063  return ~0;
1064 }
1065 
1066 void *
1068 {
1069  pthread_mutex_lock (&vlib_rp->mutex);
1070  return svm_push_data_heap (vlib_rp);
1071 }
1072 
1073 void *
1075 {
1076  api_main_t *am = vlibapi_get_main ();
1077  return vl_msg_push_heap_w_region (am->vlib_rp);
1078 }
1079 
1080 void
1081 vl_msg_pop_heap_w_region (svm_region_t * vlib_rp, void *oldheap)
1082 {
1083  svm_pop_heap (oldheap);
1084  pthread_mutex_unlock (&vlib_rp->mutex);
1085 }
1086 
1087 void
1088 vl_msg_pop_heap (void *oldheap)
1089 {
1090  api_main_t *am = vlibapi_get_main ();
1091  vl_msg_pop_heap_w_region (am->vlib_rp, oldheap);
1092 }
1093 
1094 int
1095 vl_api_to_api_string (u32 len, const char *buf, vl_api_string_t * str)
1096 {
1097  if (len)
1098  clib_memcpy_fast (str->buf, buf, len);
1099  str->length = htonl (len);
1100  return len + sizeof (u32);
1101 }
1102 
1103 int
1105 {
1106  u32 len = vec_len (vec);
1107  clib_memcpy (str->buf, vec, len);
1108  str->length = htonl (len);
1109  return len + sizeof (u32);
1110 }
1111 
1112 /* Return a pointer to the API string (not nul terminated */
1113 u8 *
1115 {
1116  return astr->buf;
1117 }
1118 
1119 u32
1121 {
1122  return clib_net_to_host_u32 (astr->length);
1123 }
1124 
1125 u8 *
1126 vl_api_format_string (u8 * s, va_list * args)
1127 {
1128  vl_api_string_t *a = va_arg (*args, vl_api_string_t *);
1129  vec_add (s, a->buf, clib_net_to_host_u32 (a->length));
1130  return s;
1131 }
1132 
1133 /*
1134  * Returns a new vector. Remember to free it after use.
1135  */
1136 u8 *
1138 {
1139  u8 *v = 0;
1140  vec_add (v, astr->buf, clib_net_to_host_u32 (astr->length));
1141  return v;
1142 }
1143 
1144 void
1146 {
1147  api_main_t *am = vlibapi_get_main ();
1148  am->elog_main = m;
1149 }
1150 
1151 int
1153 {
1154  int rv;
1155  api_main_t *am = vlibapi_get_main ();
1156 
1157  rv = am->elog_trace_api_messages;
1158  am->elog_trace_api_messages = enable;
1159  return rv;
1160 }
1161 
1162 int
1164 {
1165  api_main_t *am = vlibapi_get_main ();
1166 
1167  return am->elog_trace_api_messages;
1168 }
1169 
1170 /*
1171  * fd.io coding-style-patch-verification: ON
1172  *
1173  * Local Variables:
1174  * eval: (c-set-style "gnu")
1175  * End:
1176  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:440
void vl_msg_api_set_first_available_msg_id(u16 first_avail)
Definition: api_shared.c:972
Message range (belonging to a plugin)
Definition: api_common.h:112
int vl_msg_api_trace_onoff(api_main_t *am, vl_api_trace_which_t which, int onoff)
Definition: api_shared.c:124
int vl_msg_api_trace_save(api_main_t *am, vl_api_trace_which_t which, FILE *fp)
Definition: api_shared.c:226
int vl_api_to_api_string(u32 len, const char *buf, vl_api_string_t *str)
Definition: api_shared.c:1095
void vl_msg_api_set_handlers(int id, char *name, void *handler, void *cleanup, void *endian, void *print, int size, int traced)
Definition: api_shared.c:821
int vl_msg_api_trace_free(api_main_t *am, vl_api_trace_which_t which)
Definition: api_shared.c:166
int id
the message ID
Definition: api_common.h:122
u8 * name
name of the plugin
Definition: api_common.h:114
static void svm_pop_heap(void *oldheap)
Definition: svm.h:94
void vl_msg_api_set_cleanup_handler(int msg_id, void *fp)
Definition: api_shared.c:855
int vl_msg_api_pd_handler(void *mp, int rv)
Definition: api_shared.c:951
a
Definition: bitmap.h:538
void vl_msg_api_handler(void *the_msg)
Definition: api_shared.c:655
void * print
message print function
Definition: api_common.h:128
u8 wrapped
trace has wrapped
Definition: api_common.h:94
static u64 do_it(pg_main_t *pg, pg_stream_t *s, u32 *buffers, u32 n_buffers, u32 lo_bit, u32 hi_bit, u64 v_min, u64 v_max, u64 v, pg_edit_type_t edit_type)
Definition: input.c:756
Optimized string handling code, including c11-compliant "safe C library" variants.
int size
for sanity checking
Definition: api_common.h:82
option version
Definition: sample.api:19
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
#define NULL
Definition: clib.h:58
static void msg_handler_internal(api_main_t *am, void *the_msg, int trace_it, int do_it, int free_it)
Definition: api_shared.c:436
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
u8 * message_bounce
Don&#39;t automatically free message buffer vetor.
Definition: api_common.h:245
static u8 post_mortem_dump_enabled
Definition: api_shared.c:893
Message configuration definition.
Definition: api_common.h:120
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:523
vl_api_trace_t * vl_msg_api_trace_get(api_main_t *am, vl_api_trace_which_t which)
Definition: api_shared.c:874
u32 vl_msg_api_get_msg_length(void *msg_arg)
Definition: api_shared.c:742
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:561
int i
api_version_t * api_version_list
api version list
Definition: api_common.h:348
#define hash_set_mem(h, key, value)
Definition: hash.h:275
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
int vl_msg_api_trace_configure(api_main_t *am, vl_api_trace_which_t which, u32 nitems)
Definition: api_shared.c:365
void vl_msg_api_set_global_main(void *am_arg)
Definition: api_shared.c:47
#define vl_msg_api_barrier_trace_context(X)
Definition: api_common.h:189
void(** msg_cleanup_handlers)(void *)
non-default message cleanup handler vector
Definition: api_common.h:233
void vl_noop_handler(void *mp)
Definition: api_shared.c:888
void * cleanup
non-default message cleanup handler
Definition: api_common.h:126
u32 minor
Definition: memclnt.api:119
unsigned char u8
Definition: types.h:56
trace_cfg_t * api_trace_cfg
Current trace configuration.
Definition: api_common.h:272
void vl_msg_api_handler_no_trace_no_free(void *the_msg)
Definition: api_shared.c:676
int size
message size
Definition: api_common.h:129
u8 id[64]
Definition: dhcp.api:160
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
#define clib_memcpy(d, s, n)
Definition: string.h:180
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:599
void vl_msg_api_cleanup_handler(void *the_msg)
Definition: api_shared.c:704
void * endian
message endian function
Definition: api_common.h:127
u8 * vl_api_from_api_to_vec(vl_api_string_t *astr)
Definition: api_shared.c:1137
int svm_queue_sub(svm_queue_t *q, u8 *elem, svm_q_conditional_wait_t cond, u32 time)
Definition: queue.c:356
vl_api_trace_t * rx_trace
Received message trace configuration.
Definition: api_common.h:263
static void * svm_push_data_heap(svm_region_t *rp)
Definition: svm.h:86
void vl_msg_api_config(vl_msg_api_msg_config_t *c)
Definition: api_shared.c:772
volatile void * user_ctx
Definition: svm_common.h:47
void vl_msg_api_post_mortem_dump_enable_disable(int enable)
Definition: api_shared.c:896
#define clib_arch_is_little_endian
Definition: byte_order.h:54
svm_region_t * vlib_rp
Current binary api segment descriptor.
Definition: api_common.h:278
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
Definition: api_common.h:288
unsigned int u32
Definition: types.h:88
#define VL_API_BIG_ENDIAN
Definition: api_common.h:109
int vl_msg_api_tx_trace_enabled(api_main_t *am)
Definition: api_shared.c:67
char name[64]
Definition: api_common.h:221
void vl_msg_api_trace_only(void *the_msg)
Definition: api_shared.c:693
void vl_msg_api_clean_handlers(int msg_id)
Definition: api_shared.c:843
#define hash_create_string(elts, value_bytes)
Definition: hash.h:690
u32 patch
Definition: memclnt.api:120
u16 last_msg_id
last assigned message ID
Definition: api_common.h:116
int vl_api_get_elog_trace_api_messages(void)
Definition: api_shared.c:1163
int elog_trace_api_messages
Definition: api_common.h:370
void vl_msg_pop_heap_w_region(svm_region_t *vlib_rp, void *oldheap)
Definition: api_shared.c:1081
void vl_msg_api_add_msg_name_crc(api_main_t *am, const char *string, u32 id)
Definition: api_shared.c:1024
int vl_msg_api_rx_trace_enabled(api_main_t *am)
Definition: api_shared.c:61
void(** msg_print_handlers)(void *, void *)
Message print function vector.
Definition: api_common.h:239
int replay_enable
This message can be replayed.
Definition: api_common.h:84
unsigned short u16
Definition: types.h:57
u64 size
Definition: vhost_user.h:140
int message_bounce
do not free message after processing
Definition: api_common.h:132
u32 curindex
Current index in circular buffer.
Definition: api_common.h:97
static void cleanup(void)
Definition: client.c:131
#define ELOG_DATA(em, f)
Definition: elog.h:484
#define PREDICT_FALSE(x)
Definition: clib.h:111
#define always_inline
Definition: ipsec.h:28
u32 vl_api_string_len(vl_api_string_t *astr)
Definition: api_shared.c:1120
vlib_main_t * vm
Definition: in2out_ed.c:1810
word fformat(FILE *f, char *fmt,...)
Definition: format.c:462
elog_main_t * elog_main
event log
Definition: api_common.h:369
u8 len
Definition: ip_types.api:91
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:225
u8 enabled
trace is enabled
Definition: api_common.h:93
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
#define clib_arch_is_big_endian
Definition: byte_order.h:53
svmdb_client_t * c
API trace state.
Definition: api_common.h:90
void vl_msg_api_handler_with_vm_node(api_main_t *am, svm_region_t *vlib_rp, void *the_msg, vlib_main_t *vm, vlib_node_runtime_t *node, u8 is_private)
Definition: api_shared.c:538
void serialize_open_vector(serialize_main_t *m, u8 *vector)
Definition: serialize.c:909
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
void vl_msg_api_barrier_release(void)
Definition: api_shared.c:431
vl_api_msg_range_t * msg_ranges
vector of message ranges
Definition: api_common.h:303
void vl_msg_api_post_mortem_dump(void)
Definition: api_shared.c:902
#define clib_warning(format, args...)
Definition: error.h:59
int vl_api_set_elog_trace_api_messages(int enable)
Definition: api_shared.c:1152
u8 ** traces
Trace ring.
Definition: api_common.h:98
static void serialize_integer(serialize_main_t *m, u64 x, u32 n_bytes)
Definition: serialize.h:185
blocking call - best used in combination with condvars, for eventfds we don&#39;t yield the cpu ...
Definition: queue.h:42
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
const char ** msg_names
Message name vector.
Definition: api_common.h:242
string name[64]
Definition: ip.api:44
vlib_main_t vlib_node_runtime_t * node
Definition: in2out_ed.c:1810
int replay
is this message to be replayed?
Definition: api_common.h:131
void vl_msg_api_socket_handler(void *the_msg)
Definition: api_shared.c:751
vl_api_trace_t * tx_trace
Sent message trace configuration.
Definition: api_common.h:266
static uword hash_elts(void *v)
Definition: hash.h:118
#define ASSERT(truth)
__thread api_main_t * my_api_main
Definition: api_shared.c:44
u8 data[128]
Definition: ipsec_types.api:87
api_main_t api_global_main
Definition: api_shared.c:35
u32 data_len
message length not including header
Definition: api_common.h:140
Message header structure.
Definition: api_common.h:137
vl_api_trace_which_t
Trace RX / TX enum.
Definition: api_common.h:102
u8 * vl_api_serialize_message_table(api_main_t *am, u8 *vector)
Definition: api_shared.c:203
void vl_msg_api_replay_handler(void *the_msg)
Definition: api_shared.c:724
void vl_msg_api_add_version(api_main_t *am, const char *string, u32 major, u32 minor, u32 patch)
Definition: api_shared.c:1042
void vl_msg_api_handler_no_free(void *the_msg)
Definition: api_shared.c:666
void vl_msg_api_free(void *)
void vl_api_set_elog_main(elog_main_t *m)
Definition: api_shared.c:1145
u32 missing_clients
Number of missing clients / failed message sends.
Definition: api_common.h:260
void * vl_msg_push_heap(void)
Definition: api_shared.c:1074
u32 vl_msg_api_get_msg_index(u8 *name_and_crc)
Definition: api_shared.c:1052
void vl_msg_api_increment_missing_client_counter(void)
Definition: api_shared.c:54
u16 first_msg_id
first assigned message ID
Definition: api_common.h:115
void vl_msg_api_register_pd_handler(void *fp, u16 msg_id_host_byte_order)
Definition: api_shared.c:937
void(** msg_endian_handlers)(void *)
Message endian handler vector.
Definition: api_common.h:236
u32 elog_string(elog_main_t *em, char *fmt,...)
add a string to the event-log string table
Definition: elog.c:562
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:373
u64 uword
Definition: types.h:112
static u32 vl_msg_api_get_msg_length_inline(void *msg_arg)
Definition: api.h:91
int(** pd_msg_handlers)(void *, int)
Plaform-dependent (aka hardware) message handler vector.
Definition: api_common.h:230
#define foreach_msg_api_vector
Definition: api_shared.c:761
struct _svm_queue svm_queue_t
#define hash_get_mem(h, key)
Definition: hash.h:269
u16 vl_msg_api_get_msg_ids(const char *name, int n)
Definition: api_shared.c:980
u16 first_available_msg_id
First available message ID, for theplugin msg allocator.
Definition: api_common.h:297
static api_main_t * vlibapi_get_main(void)
Definition: api_common.h:378
void vl_msg_pop_heap(void *oldheap)
Definition: api_shared.c:1088
u8 * vl_api_from_api_string(vl_api_string_t *astr)
Definition: api_shared.c:1114
u8 * vl_api_format_string(u8 *s, va_list *args)
Definition: api_shared.c:1126
u8 endian
trace endianness
Definition: api_common.h:92
void(** msg_handlers)(void *)
Message handler vector.
Definition: api_common.h:228
u8 * is_mp_safe
Message is mp safe vector.
Definition: api_common.h:248
void vl_msg_api_queue_handler(svm_queue_t *q)
Definition: api_shared.c:865
void vl_msg_api_trace(api_main_t *am, vl_api_trace_t *tp, void *msg)
Definition: api_shared.c:76
int trace_enable
trace this message
Definition: api_common.h:83
int msg_print_flag
Print every received message.
Definition: api_common.h:269
void * serialize_close_vector(serialize_main_t *m)
Definition: serialize.c:919
int is_mp_safe
worker thread barrier required?
Definition: api_common.h:133
int traced
is this message to be traced?
Definition: api_common.h:130
const char * region_name
Shared VM binary API region name.
Definition: api_common.h:351
void * vl_msg_push_heap_w_region(svm_region_t *vlib_rp)
Definition: api_shared.c:1067
Trace configuration for a single message.
Definition: api_common.h:80
#define VL_API_LITTLE_ENDIAN
Definition: api_common.h:108
uword * msg_index_by_name_and_crc
client message index hash table
Definition: api_common.h:345
uword * msg_range_by_name
Message range by name hash.
Definition: api_common.h:300
char * name
the message name
Definition: api_common.h:123
u32 nitems
Number of trace records.
Definition: api_common.h:96
int vl_api_vec_to_api_string(const u8 *vec, vl_api_string_t *str)
Definition: api_shared.c:1104
void * handler
the message handler
Definition: api_common.h:125
pthread_mutex_t mutex
Definition: svm_common.h:37
void vl_msg_api_barrier_sync(void)
Definition: api_shared.c:426