FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
vpp_echo_common.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdio.h>
17 #include <signal.h>
18 
20 
21 char *echo_fail_code_str[] = {
22 #define _(sym, str) str,
24 #undef _
25 };
26 
27 /*
28  *
29  * Format functions
30  *
31  */
32 
33 u8 *
34 format_ip4_address (u8 * s, va_list * args)
35 {
36  u8 *a = va_arg (*args, u8 *);
37  return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
38 }
39 
40 u8 *
41 format_ip6_address (u8 * s, va_list * args)
42 {
43  ip6_address_t *a = va_arg (*args, ip6_address_t *);
44  u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
45 
46  i_max_n_zero = ARRAY_LEN (a->as_u16);
47  max_n_zeros = 0;
48  i_first_zero = i_max_n_zero;
49  n_zeros = 0;
50  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
51  {
52  u32 is_zero = a->as_u16[i] == 0;
53  if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
54  {
55  i_first_zero = i;
56  n_zeros = 0;
57  }
58  n_zeros += is_zero;
59  if ((!is_zero && n_zeros > max_n_zeros)
60  || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
61  {
62  i_max_n_zero = i_first_zero;
63  max_n_zeros = n_zeros;
64  i_first_zero = ARRAY_LEN (a->as_u16);
65  n_zeros = 0;
66  }
67  }
68 
69  last_double_colon = 0;
70  for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
71  {
72  if (i == i_max_n_zero && max_n_zeros > 1)
73  {
74  s = format (s, "::");
75  i += max_n_zeros - 1;
76  last_double_colon = 1;
77  }
78  else
79  {
80  s = format (s, "%s%x",
81  (last_double_colon || i == 0) ? "" : ":",
82  clib_net_to_host_u16 (a->as_u16[i]));
83  last_double_colon = 0;
84  }
85  }
86 
87  return s;
88 }
89 
90 /* Format an IP46 address. */
91 u8 *
92 format_ip46_address (u8 * s, va_list * args)
93 {
94  ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
95  ip46_type_t type = va_arg (*args, ip46_type_t);
96  int is_ip4 = 1;
97 
98  switch (type)
99  {
100  case IP46_TYPE_ANY:
101  is_ip4 = ip46_address_is_ip4 (ip46);
102  break;
103  case IP46_TYPE_IP4:
104  is_ip4 = 1;
105  break;
106  case IP46_TYPE_IP6:
107  is_ip4 = 0;
108  break;
109  }
110 
111  return is_ip4 ?
112  format (s, "%U", format_ip4_address, &ip46->ip4) :
113  format (s, "%U", format_ip6_address, &ip46->ip6);
114 }
115 
116 u8 *
117 format_api_error (u8 * s, va_list * args)
118 {
119  echo_main_t *em = &echo_main;
120  i32 error = va_arg (*args, u32);
121  uword *p;
122 
123  p = hash_get (em->error_string_by_error_number, -error);
124 
125  if (p)
126  s = format (s, "%s", p[0]);
127  else
128  s = format (s, "%d", error);
129  return s;
130 }
131 
132 void
134 {
135  echo_main_t *em = &echo_main;
136  em->error_string_by_error_number = hash_create (0, sizeof (uword));
137 
138 #define _(n,v,s) hash_set (em->error_string_by_error_number, -v, s);
140 #undef _
141 
142  hash_set (em->error_string_by_error_number, 99, "Misc");
143 }
144 
145 u8 *
146 echo_format_session (u8 * s, va_list * args)
147 {
148  echo_session_t *session = va_arg (*args, echo_session_t *);
149 
150  return format (s, "%U 0x%lx S[%u]", echo_format_session_type,
151  session->session_type, session->vpp_session_handle,
152  session->session_index);
153 }
154 
155 u8 *
156 echo_format_session_type (u8 * s, va_list * args)
157 {
158  u32 session_type = va_arg (*args, u32);
159  switch (session_type)
160  {
162  return format (s, "Qsession");
164  return format (s, "Stream");
166  return format (s, "Lsession");
167  default:
168  break;
169  }
170  return format (s, "BadSession");
171 }
172 
173 u8 *
174 echo_format_session_state (u8 * s, va_list * args)
175 {
176  u32 session_state = va_arg (*args, u32);
177  switch (session_state)
178  {
180  return format (s, "ECHO_SESSION_STATE_INITIAL (%u)", session_state);
182  return format (s, "ECHO_SESSION_STATE_READY (%u)", session_state);
184  return format (s, "ECHO_SESSION_STATE_AWAIT_CLOSING (%u)",
185  session_state);
187  return format (s, "ECHO_SESSION_STATE_AWAIT_DATA (%u)", session_state);
189  return format (s, "ECHO_SESSION_STATE_CLOSING (%u)", session_state);
191  return format (s, "ECHO_SESSION_STATE_CLOSED (%u)", session_state);
192  default:
193  break;
194  }
195  return format (s, "unknown session state (%u)", session_state);
196 }
197 
198 u8 *
199 echo_format_app_state (u8 * s, va_list * args)
200 {
201  u32 state = va_arg (*args, u32);
202  if (state == STATE_START)
203  return format (s, "STATE_START (%u)", state);
204  if (state == STATE_ATTACHED)
205  return format (s, "STATE_ATTACHED (%u)", state);
206  if (state == STATE_ATTACHED_NO_CERT)
207  return format (s, "STATE_ATTACHED_NO_CERT (%u)", state);
208  if (state == STATE_LISTEN)
209  return format (s, "STATE_LISTEN (%u)", state);
210  if (state == STATE_READY)
211  return format (s, "STATE_READY (%u)", state);
212  if (state == STATE_DATA_DONE)
213  return format (s, "STATE_DATA_DONE (%u)", state);
214  if (state == STATE_DISCONNECTED)
215  return format (s, "STATE_DISCONNECTED (%u)", state);
216  if (state == STATE_DETACHED)
217  return format (s, "STATE_DETACHED (%u)", state);
218  else
219  return format (s, "unknown state (%u)", state);
220 }
221 
222 uword
223 echo_unformat_close (unformat_input_t * input, va_list * args)
224 {
225  u8 *a = va_arg (*args, u8 *);
226  if (unformat (input, "Y"))
227  *a = ECHO_CLOSE_F_ACTIVE;
228  else if (unformat (input, "N"))
229  *a = ECHO_CLOSE_F_NONE;
230  else if (unformat (input, "W"))
232  else
233  return 0;
234  return 1;
235 }
236 
237 uword
239 {
240  u8 *a = va_arg (*args, u8 *);
241  if (unformat (input, "start"))
242  *a = ECHO_EVT_START;
243  else if (unformat (input, "qconnected"))
245  else if (unformat (input, "qconnect"))
247  else if (unformat (input, "sconnected"))
249  else if (unformat (input, "sconnect"))
251  else if (unformat (input, "lastbyte"))
252  *a = ECHO_EVT_LAST_BYTE;
253  else if (unformat (input, "exit"))
254  *a = ECHO_EVT_EXIT;
255  else
256  return 0;
257  return 1;
258 }
259 
260 u8 *
261 echo_format_bytes_per_sec (u8 * s, va_list * args)
262 {
263  f64 bps = va_arg (*args, f64) * 8;
264  if (bps > 1e9)
265  return format (s, "%.3f Gb/s", bps / 1e9);
266  else if (bps > 1e6)
267  return format (s, "%.3f Mb/s", bps / 1e6);
268  else if (bps > 1e3)
269  return format (s, "%.3f Kb/s", bps / 1e3);
270  else
271  return format (s, "%.3f b/s", bps);
272 }
273 
274 u8 *
275 echo_format_timing_event (u8 * s, va_list * args)
276 {
277  u32 timing_event = va_arg (*args, u32);
278  if (timing_event == ECHO_EVT_START)
279  return format (s, "start");
280  if (timing_event == ECHO_EVT_FIRST_QCONNECT)
281  return format (s, "qconnect");
282  if (timing_event == ECHO_EVT_LAST_QCONNECTED)
283  return format (s, "qconnected");
284  if (timing_event == ECHO_EVT_FIRST_SCONNECT)
285  return format (s, "sconnect");
286  if (timing_event == ECHO_EVT_LAST_SCONNECTED)
287  return format (s, "sconnected");
288  if (timing_event == ECHO_EVT_LAST_BYTE)
289  return format (s, "lastbyte");
290  if (timing_event == ECHO_EVT_EXIT)
291  return format (s, "exit");
292  else
293  return format (s, "unknown timing event");
294 }
295 
296 uword
298 {
299  u32 *proto = va_arg (*args, u32 *);
300  if (unformat (input, "tcp"))
301  *proto = TRANSPORT_PROTO_TCP;
302  else if (unformat (input, "TCP"))
303  *proto = TRANSPORT_PROTO_TCP;
304  else if (unformat (input, "udpc"))
305  *proto = TRANSPORT_PROTO_UDPC;
306  else if (unformat (input, "UDPC"))
307  *proto = TRANSPORT_PROTO_UDPC;
308  else if (unformat (input, "udp"))
309  *proto = TRANSPORT_PROTO_UDP;
310  else if (unformat (input, "UDP"))
311  *proto = TRANSPORT_PROTO_UDP;
312  else if (unformat (input, "sctp"))
313  *proto = TRANSPORT_PROTO_SCTP;
314  else if (unformat (input, "SCTP"))
315  *proto = TRANSPORT_PROTO_SCTP;
316  else if (unformat (input, "tls"))
317  *proto = TRANSPORT_PROTO_TLS;
318  else if (unformat (input, "TLS"))
319  *proto = TRANSPORT_PROTO_TLS;
320  else if (unformat (input, "quic"))
321  *proto = TRANSPORT_PROTO_QUIC;
322  else if (unformat (input, "QUIC"))
323  *proto = TRANSPORT_PROTO_QUIC;
324  else
325  return 0;
326  return 1;
327 }
328 
329 u8 *
330 format_transport_proto (u8 * s, va_list * args)
331 {
332  u32 transport_proto = va_arg (*args, u32);
333  switch (transport_proto)
334  {
335  case TRANSPORT_PROTO_TCP:
336  s = format (s, "TCP");
337  break;
338  case TRANSPORT_PROTO_UDP:
339  s = format (s, "UDP");
340  break;
341  case TRANSPORT_PROTO_SCTP:
342  s = format (s, "SCTP");
343  break;
344  case TRANSPORT_PROTO_NONE:
345  s = format (s, "NONE");
346  break;
347  case TRANSPORT_PROTO_TLS:
348  s = format (s, "TLS");
349  break;
350  case TRANSPORT_PROTO_UDPC:
351  s = format (s, "UDPC");
352  break;
353  case TRANSPORT_PROTO_QUIC:
354  s = format (s, "QUIC");
355  break;
356  default:
357  s = format (s, "UNKNOWN");
358  break;
359  }
360  return s;
361 }
362 
363 uword
364 unformat_ip4_address (unformat_input_t * input, va_list * args)
365 {
366  u8 *result = va_arg (*args, u8 *);
367  unsigned a[4];
368 
369  if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
370  return 0;
371 
372  if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
373  return 0;
374 
375  result[0] = a[0];
376  result[1] = a[1];
377  result[2] = a[2];
378  result[3] = a[3];
379 
380  return 1;
381 }
382 
383 uword
384 unformat_ip6_address (unformat_input_t * input, va_list * args)
385 {
386  ip6_address_t *result = va_arg (*args, ip6_address_t *);
387  u16 hex_quads[8];
388  uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
389  uword c, n_colon, double_colon_index;
390 
391  n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
392  double_colon_index = ARRAY_LEN (hex_quads);
393  while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
394  {
395  hex_digit = 16;
396  if (c >= '0' && c <= '9')
397  hex_digit = c - '0';
398  else if (c >= 'a' && c <= 'f')
399  hex_digit = c + 10 - 'a';
400  else if (c >= 'A' && c <= 'F')
401  hex_digit = c + 10 - 'A';
402  else if (c == ':' && n_colon < 2)
403  n_colon++;
404  else
405  {
406  unformat_put_input (input);
407  break;
408  }
409 
410  /* Too many hex quads. */
411  if (n_hex_quads >= ARRAY_LEN (hex_quads))
412  return 0;
413 
414  if (hex_digit < 16)
415  {
416  hex_quad = (hex_quad << 4) | hex_digit;
417 
418  /* Hex quad must fit in 16 bits. */
419  if (n_hex_digits >= 4)
420  return 0;
421 
422  n_colon = 0;
423  n_hex_digits++;
424  }
425 
426  /* Save position of :: */
427  if (n_colon == 2)
428  {
429  /* More than one :: ? */
430  if (double_colon_index < ARRAY_LEN (hex_quads))
431  return 0;
432  double_colon_index = n_hex_quads;
433  }
434 
435  if (n_colon > 0 && n_hex_digits > 0)
436  {
437  hex_quads[n_hex_quads++] = hex_quad;
438  hex_quad = 0;
439  n_hex_digits = 0;
440  }
441  }
442 
443  if (n_hex_digits > 0)
444  hex_quads[n_hex_quads++] = hex_quad;
445 
446  {
447  word i;
448 
449  /* Expand :: to appropriate number of zero hex quads. */
450  if (double_colon_index < ARRAY_LEN (hex_quads))
451  {
452  word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
453 
454  for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
455  hex_quads[n_zero + i] = hex_quads[i];
456 
457  for (i = 0; i < n_zero; i++)
458  hex_quads[double_colon_index + i] = 0;
459 
460  n_hex_quads = ARRAY_LEN (hex_quads);
461  }
462 
463  /* Too few hex quads given. */
464  if (n_hex_quads < ARRAY_LEN (hex_quads))
465  return 0;
466 
467  for (i = 0; i < ARRAY_LEN (hex_quads); i++)
468  result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
469 
470  return 1;
471  }
472 }
473 
474 uword
475 unformat_ip46_address (unformat_input_t * input, va_list * args)
476 {
477  ip46_address_t *ip = va_arg (*args, ip46_address_t *);
478 
479  if (unformat (input, "%U", unformat_ip4_address, &ip->ip4))
480  ;
481  else if (unformat (input, "%U", unformat_ip6_address, &ip->ip6))
482  ;
483  else
484  return 0;
485  return 1;
486 }
487 
488 u8 *
489 echo_format_crypto_engine (u8 * s, va_list * args)
490 {
491  u32 state = va_arg (*args, u32);
492  if (state == CRYPTO_ENGINE_MBEDTLS)
493  return format (s, "mbedtls");
494  if (state == CRYPTO_ENGINE_OPENSSL)
495  return format (s, "openssl");
496  if (state == CRYPTO_ENGINE_PICOTLS)
497  return format (s, "picotls");
498  if (state == CRYPTO_ENGINE_VPP)
499  return format (s, "vpp");
500  else
501  return format (s, "unknown crypto engine");
502 }
503 
504 uword
506 {
507  u8 *a = va_arg (*args, u8 *);
508  if (unformat (input, "mbedtls"))
510  else if (unformat (input, "openssl"))
512  else if (unformat (input, "picotls"))
514  else if (unformat (input, "vpp"))
515  *a = CRYPTO_ENGINE_VPP;
516  else
517  return 0;
518  return 1;
519 }
520 
521 
522 /*
523  *
524  * End of format functions
525  *
526  */
527 
528 void
530 {
532  if (sid == SESSION_INVALID_INDEX)
533  {
534  ECHO_LOG (3, "hash_unset(0x%lx)", handle);
536  }
537  else
538  {
539  ECHO_LOG (3, "hash_set(0x%lx) S[%d]", handle, sid);
540  hash_set (em->session_index_by_vpp_handles, handle, sid);
541  }
543 }
544 
547 {
548  /* thread safe new prealloced session
549  * see echo_session_prealloc */
550  return pool_elt_at_index (em->sessions,
552  1));
553 }
554 
555 int
556 echo_send_rpc (echo_main_t * em, void *fp, echo_rpc_args_t * args)
557 {
558  svm_msg_q_msg_t msg;
559  echo_rpc_msg_t *evt;
561  {
562  ECHO_FAIL (ECHO_FAIL_RPC_SIZE, "RPC lock failed");
563  return -1;
564  }
566  {
568  ECHO_FAIL (ECHO_FAIL_RPC_SIZE, "RPC ring is full");
569  return -2;
570  }
572  evt = (echo_rpc_msg_t *) svm_msg_q_msg_data (em->rpc_msq_queue, &msg);
573  evt->fp = fp;
574  clib_memcpy (&evt->args, args, sizeof (evt->args));
575 
577  return 0;
578 }
579 
582 {
583  uword *p;
585  p = hash_get (em->session_index_by_vpp_handles, handle);
587  if (!p)
588  {
589  ECHO_LOG (2, "unknown handle 0x%lx", handle);
590  return 0;
591  }
592  return pool_elt_at_index (em->sessions, p[0]);
593 }
594 
595 int
597  f64 timeout)
598 {
599  f64 end_time = clib_time_now (&em->clib_time) + timeout;
600  while (!timeout || clib_time_now (&em->clib_time) < end_time)
601  {
602  if (em->state == state)
603  return 0;
604  if (em->time_to_stop)
605  return 1;
606  }
607  ECHO_LOG (2, "timeout waiting for %U", echo_format_app_state, state);
608  return -1;
609 }
610 
611 void
613 {
614  if (em->timing.events_sent & e)
615  return;
616  if (em->timing.start_event == e)
618  else if (em->timing.end_event == e)
619  em->timing.end_time = clib_time_now (&em->clib_time);
620  em->timing.events_sent |= e;
621 }
622 
623 void
625 {
626  f64 deltat = clib_time_now (&em->clib_time) - session->start;
627  ECHO_LOG (1, "Session 0x%x done in %.6fs RX[%.4f] TX[%.4f] Gbit/s\n",
628  session->vpp_session_handle, deltat,
629  (session->bytes_received * 8.0) / deltat / 1e9,
630  (session->bytes_sent * 8.0) / deltat / 1e9);
631 }
632 
633 /*
634  * fd.io coding-style-patch-verification: ON
635  *
636  * Local Variables:
637  * eval: (c-set-style "gnu")
638  * End:
639  */
clib_time_t clib_time
u8 proto
Definition: acl_types.api:47
#define hash_set(h, key, value)
Definition: hash.h:255
void * svm_msg_q_msg_data(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Get data for message in queue.
static u8 svm_msg_q_ring_is_full(svm_msg_q_t *mq, u32 ring_index)
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
Definition: lock.h:102
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
Definition: lock.h:80
u8 * echo_format_timing_event(u8 *s, va_list *args)
u8 * echo_format_session(u8 *s, va_list *args)
#define hash_unset(h, key)
Definition: hash.h:261
a
Definition: bitmap.h:538
uword unformat_ip6_address(unformat_input_t *input, va_list *args)
echo_session_t * sessions
u8 * format_ip6_address(u8 *s, va_list *args)
clib_spinlock_t sid_vpp_handles_lock
static uword unformat_get_input(unformat_input_t *input)
Definition: format.h:192
unsigned long u64
Definition: types.h:89
static f64 clib_time_now(clib_time_t *c)
Definition: time.h:224
uword echo_unformat_timing_event(unformat_input_t *input, va_list *args)
uword unformat_ip4_address(unformat_input_t *input, va_list *args)
int i
echo_main_t echo_main
Definition: vpp_echo.c:24
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
volatile connection_state_t state
char * echo_fail_code_str[]
uword echo_unformat_crypto_engine(unformat_input_t *input, va_list *args)
static u8 ip46_address_is_ip4(const ip46_address_t *ip46)
Definition: ip46_address.h:55
unsigned char u8
Definition: types.h:56
int wait_for_state_change(echo_main_t *em, connection_state_t state, f64 timeout)
foreach_app_session_field u64 vpp_session_handle
double f64
Definition: types.h:142
struct echo_main_t::@572 timing
#define clib_memcpy(d, s, n)
Definition: string.h:180
u8 * echo_format_session_state(u8 *s, va_list *args)
echo_session_t * echo_session_new(echo_main_t *em)
i64 word
Definition: types.h:111
connection_state_t
volatile u64 bytes_received
void echo_session_handle_add_del(echo_main_t *em, u64 handle, u32 sid)
#define ECHO_FAIL(fail, _fmt, _args...)
unsigned int u32
Definition: types.h:88
uword unformat_ip46_address(unformat_input_t *input, va_list *args)
vl_api_fib_path_type_t type
Definition: fib_types.api:123
#define hash_get(h, key)
Definition: hash.h:249
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:519
void init_error_string_table()
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
u8 * echo_format_bytes_per_sec(u8 *s, va_list *args)
#define PREDICT_FALSE(x)
Definition: clib.h:111
u8 * echo_format_app_state(u8 *s, va_list *args)
uword * error_string_by_error_number
static void unformat_put_input(unformat_input_t *input)
Definition: format.h:205
#define SESSION_INVALID_INDEX
Definition: session_types.h:22
u8 is_ip4
Definition: lisp_gpe.api:232
u8 * format_ip46_address(u8 *s, va_list *args)
enum echo_test_evt_ echo_test_evt_t
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
svmdb_client_t * c
static void svm_msg_q_unlock(svm_msg_q_t *mq)
Unlock message queue.
u8 * format_ip4_address(u8 *s, va_list *args)
#define ECHO_LOG(lvl, _fmt, _args...)
void echo_notify_event(echo_main_t *em, echo_test_evt_t e)
volatile u8 time_to_stop
#define ARRAY_LEN(x)
Definition: clib.h:62
uword unformat_transport_proto(unformat_input_t *input, va_list *args)
#define foreach_vnet_api_error
Definition: api_errno.h:22
int echo_send_rpc(echo_main_t *em, void *fp, echo_rpc_args_t *args)
signed int i32
Definition: types.h:77
#define hash_create(elts, value_bytes)
Definition: hash.h:696
void svm_msg_q_add_and_unlock(svm_msg_q_t *mq, svm_msg_q_msg_t *msg)
Producer enqueue one message to queue with mutex held.
volatile u32 nxt_available_sidx
echo_session_t * echo_get_session_from_handle(echo_main_t *em, u64 handle)
u8 * echo_format_session_type(u8 *s, va_list *args)
#define clib_atomic_fetch_add(a, b)
Definition: atomics.h:23
vl_api_address_t ip
Definition: l2.api:490
u64 uword
Definition: types.h:112
u8 * format_api_error(u8 *s, va_list *args)
uword * session_index_by_vpp_handles
svm_msg_q_t * rpc_msq_queue
vl_api_dhcp_client_state_t state
Definition: dhcp.api:201
u16 as_u16[8]
Definition: ip6_packet.h:49
static int svm_msg_q_lock(svm_msg_q_t *mq)
Lock, or block trying, the message queue.
void echo_session_print_stats(echo_main_t *em, echo_session_t *session)
u8 * echo_format_crypto_engine(u8 *s, va_list *args)
svm_msg_q_msg_t svm_msg_q_alloc_msg_w_ring(svm_msg_q_t *mq, u32 ring_index)
Allocate message buffer on ring.
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
uword echo_unformat_close(unformat_input_t *input, va_list *args)
u8 * format_transport_proto(u8 *s, va_list *args)
ip46_type_t
Definition: ip46_address.h:22
echo_rpc_args_t args