blob: 61ac92fac38010e9201d28e510fec6067fdb8b2d [file] [log] [blame]
Damjan Marion7cd468a2016-12-19 23:05:39 +01001/*
2 *------------------------------------------------------------------
3 * api_format.c
4 *
Dave Barachac0326f2020-07-14 18:30:05 -04005 * Copyright (c) 2014-2020 Cisco and/or its affiliates.
Damjan Marion7cd468a2016-12-19 23:05:39 +01006 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <vat/vat.h>
jialv01082ebeb2019-09-10 00:23:55 +080021#include <vlib/pci/pci.h>
Neale Ranns86327be2018-11-02 09:14:01 -070022#include <vpp/api/types.h>
Dave Barach59b25652017-09-10 15:04:27 -040023#include <vppinfra/socket.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010024#include <vlibapi/api.h>
25#include <vlibmemory/api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010026#include <vnet/ip/ip.h>
Neale Rannscbe25aa2019-09-30 10:53:31 +000027#include <vnet/ip-neighbor/ip_neighbor.h>
Neale Ranns37029302018-08-10 05:30:06 -070028#include <vnet/ip/ip_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010029#include <vnet/l2/l2_input.h>
Florin Corasb040f982020-10-20 14:59:43 -070030#include <vnet/udp/udp_local.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010031
Damjan Marion7cd468a2016-12-19 23:05:39 +010032#include <vnet/l2/l2_classify.h>
33#include <vnet/l2/l2_vtr.h>
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +010034#include <vnet/classify/in_out_acl.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010035#include <vnet/classify/policer_classify.h>
36#include <vnet/classify/flow_classify.h>
37#include <vnet/mpls/mpls.h>
38#include <vnet/ipsec/ipsec.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010039#include <inttypes.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010040#include <vnet/ip/ip6_hop_by_hop.h>
41#include <vnet/ip/ip_source_and_port_range_check.h>
42#include <vnet/policer/xlate.h>
43#include <vnet/span/span.h>
44#include <vnet/policer/policer.h>
45#include <vnet/policer/police.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000046#include <vnet/mfib/mfib_types.h>
Steven9cd2d7a2017-12-20 12:43:01 -080047#include <vnet/bonding/node.h>
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -070048#include <vnet/qos/qos_types.h>
Neale Ranns37029302018-08-10 05:30:06 -070049#include <vnet/ethernet/ethernet_types_api.h>
50#include <vnet/ip/ip_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010051#include "vat/json_format.h"
Neale Ranns86327be2018-11-02 09:14:01 -070052#include <vnet/ip/ip_types_api.h>
53#include <vnet/ethernet/ethernet_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010054
55#include <inttypes.h>
56#include <sys/stat.h>
57
Ole Troan3459ece2021-09-27 17:11:34 +020058#include <vlibmemory/memclnt.api_enum.h>
59#include <vlibmemory/memclnt.api_types.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010060
61#define vl_endianfun /* define message structures */
Ole Troan3459ece2021-09-27 17:11:34 +020062#include <vlibmemory/memclnt.api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010063#undef vl_endianfun
64
65/* instantiate all the print functions we know about */
Dave Barachf35a0722019-06-12 16:50:38 -040066#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +010067#define vl_print(handle, ...)
Dave Barachf35a0722019-06-12 16:50:38 -040068#else
69#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
70#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +010071#define vl_printfun
Ole Troan3459ece2021-09-27 17:11:34 +020072#include <vlibmemory/memclnt.api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010073#undef vl_printfun
74
Dave Barach2d6b2d62017-01-25 16:32:08 -050075#define __plugin_msg_base 0
Dave Barachfe6bdfd2017-01-20 19:50:09 -050076#include <vlibapi/vat_helper_macros.h>
77
Dave Barachb09f4d02019-07-15 16:00:03 -040078void vl_api_set_elog_main (elog_main_t * m);
79int vl_api_set_elog_trace_api_messages (int enable);
80
Dave Barach59b25652017-09-10 15:04:27 -040081#if VPP_API_TEST_BUILTIN == 0
82#include <netdb.h>
83
84u32
85vl (void *p)
86{
87 return vec_len (p);
88}
89
90int
91vat_socket_connect (vat_main_t * vam)
92{
Florin Coras66a10032018-12-21 16:23:09 -080093 int rv;
Dave Barach69eeadc2020-04-14 09:52:26 -040094 api_main_t *am = vlibapi_get_main ();
Florin Coras90a63982017-12-19 04:50:01 -080095 vam->socket_client_main = &socket_client_main;
Florin Coras66a10032018-12-21 16:23:09 -080096 if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
97 "vpp_api_test",
98 0 /* default socket rx, tx buffer */ )))
99 return rv;
Dave Barach69eeadc2020-04-14 09:52:26 -0400100
Florin Coras66a10032018-12-21 16:23:09 -0800101 /* vpp expects the client index in network order */
102 vam->my_client_index = htonl (socket_client_main.client_index);
Dave Barach69eeadc2020-04-14 09:52:26 -0400103 am->my_client_index = vam->my_client_index;
Florin Coras66a10032018-12-21 16:23:09 -0800104 return 0;
Dave Barach59b25652017-09-10 15:04:27 -0400105}
106#else /* vpp built-in case, we don't do sockets... */
107int
108vat_socket_connect (vat_main_t * vam)
109{
110 return 0;
111}
112
Florin Coras90a63982017-12-19 04:50:01 -0800113int
114vl_socket_client_read (int wait)
Dave Barach59b25652017-09-10 15:04:27 -0400115{
Florin Coras90a63982017-12-19 04:50:01 -0800116 return -1;
Dave Barach59b25652017-09-10 15:04:27 -0400117};
Florin Coras90a63982017-12-19 04:50:01 -0800118
119int
120vl_socket_client_write ()
121{
122 return -1;
123};
124
125void *
126vl_socket_client_msg_alloc (int nbytes)
127{
128 return 0;
129}
Dave Barach59b25652017-09-10 15:04:27 -0400130#endif
131
132
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500133f64
134vat_time_now (vat_main_t * vam)
135{
136#if VPP_API_TEST_BUILTIN
137 return vlib_time_now (vam->vlib_main);
138#else
139 return clib_time_now (&vam->clib_time);
140#endif
141}
142
143void
144errmsg (char *fmt, ...)
145{
146 vat_main_t *vam = &vat_main;
147 va_list va;
148 u8 *s;
149
150 va_start (va, fmt);
151 s = va_format (0, fmt, &va);
152 va_end (va);
153
154 vec_add1 (s, 0);
155
156#if VPP_API_TEST_BUILTIN
157 vlib_cli_output (vam->vlib_main, (char *) s);
158#else
159 {
160 if (vam->ifp != stdin)
161 fformat (vam->ofp, "%s(%d): \n", vam->current_file,
162 vam->input_line_number);
Dave Barachb09f4d02019-07-15 16:00:03 -0400163 else
164 fformat (vam->ofp, "%s\n", (char *) s);
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500165 fflush (vam->ofp);
166 }
167#endif
168
169 vec_free (s);
170}
171
Dave Barach4a3f69c2017-02-22 12:44:56 -0500172#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +0100173static uword
174api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
175{
176 vat_main_t *vam = va_arg (*args, vat_main_t *);
177 u32 *result = va_arg (*args, u32 *);
178 u8 *if_name;
179 uword *p;
180
181 if (!unformat (input, "%s", &if_name))
182 return 0;
183
184 p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
185 if (p == 0)
186 return 0;
187 *result = p[0];
188 return 1;
189}
190
Damjan Marion7cd468a2016-12-19 23:05:39 +0100191/* Parse an IP4 address %d.%d.%d.%d. */
192uword
193unformat_ip4_address (unformat_input_t * input, va_list * args)
194{
195 u8 *result = va_arg (*args, u8 *);
196 unsigned a[4];
197
198 if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
199 return 0;
200
201 if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
202 return 0;
203
204 result[0] = a[0];
205 result[1] = a[1];
206 result[2] = a[2];
207 result[3] = a[3];
208
209 return 1;
210}
211
212uword
213unformat_ethernet_address (unformat_input_t * input, va_list * args)
214{
215 u8 *result = va_arg (*args, u8 *);
216 u32 i, a[6];
217
218 if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
219 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
220 return 0;
221
222 /* Check range. */
223 for (i = 0; i < 6; i++)
224 if (a[i] >= (1 << 8))
225 return 0;
226
227 for (i = 0; i < 6; i++)
228 result[i] = a[i];
229
230 return 1;
231}
232
233/* Returns ethernet type as an int in host byte order. */
234uword
235unformat_ethernet_type_host_byte_order (unformat_input_t * input,
236 va_list * args)
237{
238 u16 *result = va_arg (*args, u16 *);
239 int type;
240
241 /* Numeric type. */
242 if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
243 {
244 if (type >= (1 << 16))
245 return 0;
246 *result = type;
247 return 1;
248 }
249 return 0;
250}
251
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100252/* Parse an IP46 address. */
253uword
254unformat_ip46_address (unformat_input_t * input, va_list * args)
255{
256 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
257 ip46_type_t type = va_arg (*args, ip46_type_t);
258 if ((type != IP46_TYPE_IP6) &&
259 unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
260 {
261 ip46_address_mask_ip4 (ip46);
262 return 1;
263 }
264 else if ((type != IP46_TYPE_IP4) &&
265 unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
266 {
267 return 1;
268 }
269 return 0;
270}
271
Damjan Marion7cd468a2016-12-19 23:05:39 +0100272/* Parse an IP6 address. */
273uword
274unformat_ip6_address (unformat_input_t * input, va_list * args)
275{
276 ip6_address_t *result = va_arg (*args, ip6_address_t *);
277 u16 hex_quads[8];
278 uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
279 uword c, n_colon, double_colon_index;
280
281 n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
282 double_colon_index = ARRAY_LEN (hex_quads);
283 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
284 {
285 hex_digit = 16;
286 if (c >= '0' && c <= '9')
287 hex_digit = c - '0';
288 else if (c >= 'a' && c <= 'f')
289 hex_digit = c + 10 - 'a';
290 else if (c >= 'A' && c <= 'F')
291 hex_digit = c + 10 - 'A';
292 else if (c == ':' && n_colon < 2)
293 n_colon++;
294 else
295 {
296 unformat_put_input (input);
297 break;
298 }
299
300 /* Too many hex quads. */
301 if (n_hex_quads >= ARRAY_LEN (hex_quads))
302 return 0;
303
304 if (hex_digit < 16)
305 {
306 hex_quad = (hex_quad << 4) | hex_digit;
307
308 /* Hex quad must fit in 16 bits. */
309 if (n_hex_digits >= 4)
310 return 0;
311
312 n_colon = 0;
313 n_hex_digits++;
314 }
315
316 /* Save position of :: */
317 if (n_colon == 2)
318 {
319 /* More than one :: ? */
320 if (double_colon_index < ARRAY_LEN (hex_quads))
321 return 0;
322 double_colon_index = n_hex_quads;
323 }
324
325 if (n_colon > 0 && n_hex_digits > 0)
326 {
327 hex_quads[n_hex_quads++] = hex_quad;
328 hex_quad = 0;
329 n_hex_digits = 0;
330 }
331 }
332
333 if (n_hex_digits > 0)
334 hex_quads[n_hex_quads++] = hex_quad;
335
336 {
337 word i;
338
339 /* Expand :: to appropriate number of zero hex quads. */
340 if (double_colon_index < ARRAY_LEN (hex_quads))
341 {
342 word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
343
344 for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
345 hex_quads[n_zero + i] = hex_quads[i];
346
347 for (i = 0; i < n_zero; i++)
348 hex_quads[double_colon_index + i] = 0;
349
350 n_hex_quads = ARRAY_LEN (hex_quads);
351 }
352
353 /* Too few hex quads given. */
354 if (n_hex_quads < ARRAY_LEN (hex_quads))
355 return 0;
356
357 for (i = 0; i < ARRAY_LEN (hex_quads); i++)
358 result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
359
360 return 1;
361 }
362}
363
364uword
365unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
366{
367 u32 *r = va_arg (*args, u32 *);
368
369 if (0);
370#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
371 foreach_ipsec_policy_action
372#undef _
373 else
374 return 0;
375 return 1;
376}
377
Damjan Marion7cd468a2016-12-19 23:05:39 +0100378u8 *
379format_ipsec_crypto_alg (u8 * s, va_list * args)
380{
381 u32 i = va_arg (*args, u32);
382 u8 *t = 0;
383
384 switch (i)
385 {
386#define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
387 foreach_ipsec_crypto_alg
388#undef _
389 default:
390 return format (s, "unknown");
391 }
392 return format (s, "%s", t);
393}
394
Damjan Marion7cd468a2016-12-19 23:05:39 +0100395u8 *
396format_ipsec_integ_alg (u8 * s, va_list * args)
397{
398 u32 i = va_arg (*args, u32);
399 u8 *t = 0;
400
401 switch (i)
402 {
403#define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
404 foreach_ipsec_integ_alg
405#undef _
406 default:
407 return format (s, "unknown");
408 }
409 return format (s, "%s", t);
410}
411
Dave Barach4a3f69c2017-02-22 12:44:56 -0500412#else /* VPP_API_TEST_BUILTIN == 1 */
413static uword
414api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
415{
Benoît Ganne49ee6842019-04-30 11:50:46 +0200416 vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500417 vnet_main_t *vnm = vnet_get_main ();
418 u32 *result = va_arg (*args, u32 *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500419
eyal bariaf86a482018-04-17 11:20:27 +0300420 return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500421}
eyal bariaf86a482018-04-17 11:20:27 +0300422
Damjan Marion7cd468a2016-12-19 23:05:39 +0100423#endif /* VPP_API_TEST_BUILTIN */
424
Benoît Ganne49ee6842019-04-30 11:50:46 +0200425#if (VPP_API_TEST_BUILTIN==0)
426
Neale Ranns32e1c012016-11-22 17:07:28 +0000427static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
428static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
429static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
430static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
431
432uword
433unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
434{
435 mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
436 mfib_itf_attribute_t attr;
437
438 old = *iflags;
439 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
440 {
441 if (unformat (input, mfib_itf_flag_long_names[attr]))
442 *iflags |= (1 << attr);
443 }
444 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
445 {
446 if (unformat (input, mfib_itf_flag_names[attr]))
447 *iflags |= (1 << attr);
448 }
449
450 return (old == *iflags ? 0 : 1);
451}
452
453uword
454unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
455{
456 mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
457 mfib_entry_attribute_t attr;
458
459 old = *eflags;
460 FOR_EACH_MFIB_ATTRIBUTE (attr)
461 {
462 if (unformat (input, mfib_flag_long_names[attr]))
463 *eflags |= (1 << attr);
464 }
465 FOR_EACH_MFIB_ATTRIBUTE (attr)
466 {
467 if (unformat (input, mfib_flag_names[attr]))
468 *eflags |= (1 << attr);
469 }
470
471 return (old == *eflags ? 0 : 1);
472}
473
Damjan Marion7cd468a2016-12-19 23:05:39 +0100474u8 *
475format_ip4_address (u8 * s, va_list * args)
476{
477 u8 *a = va_arg (*args, u8 *);
478 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
479}
480
481u8 *
482format_ip6_address (u8 * s, va_list * args)
483{
484 ip6_address_t *a = va_arg (*args, ip6_address_t *);
485 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
486
487 i_max_n_zero = ARRAY_LEN (a->as_u16);
488 max_n_zeros = 0;
489 i_first_zero = i_max_n_zero;
490 n_zeros = 0;
491 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
492 {
493 u32 is_zero = a->as_u16[i] == 0;
494 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
495 {
496 i_first_zero = i;
497 n_zeros = 0;
498 }
499 n_zeros += is_zero;
500 if ((!is_zero && n_zeros > max_n_zeros)
501 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
502 {
503 i_max_n_zero = i_first_zero;
504 max_n_zeros = n_zeros;
505 i_first_zero = ARRAY_LEN (a->as_u16);
506 n_zeros = 0;
507 }
508 }
509
510 last_double_colon = 0;
511 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
512 {
513 if (i == i_max_n_zero && max_n_zeros > 1)
514 {
515 s = format (s, "::");
516 i += max_n_zeros - 1;
517 last_double_colon = 1;
518 }
519 else
520 {
521 s = format (s, "%s%x",
522 (last_double_colon || i == 0) ? "" : ":",
523 clib_net_to_host_u16 (a->as_u16[i]));
524 last_double_colon = 0;
525 }
526 }
527
528 return s;
529}
530
531/* Format an IP46 address. */
532u8 *
533format_ip46_address (u8 * s, va_list * args)
534{
535 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
536 ip46_type_t type = va_arg (*args, ip46_type_t);
537 int is_ip4 = 1;
538
539 switch (type)
540 {
541 case IP46_TYPE_ANY:
542 is_ip4 = ip46_address_is_ip4 (ip46);
543 break;
544 case IP46_TYPE_IP4:
545 is_ip4 = 1;
546 break;
547 case IP46_TYPE_IP6:
548 is_ip4 = 0;
549 break;
550 }
551
552 return is_ip4 ?
553 format (s, "%U", format_ip4_address, &ip46->ip4) :
554 format (s, "%U", format_ip6_address, &ip46->ip6);
555}
556
557u8 *
558format_ethernet_address (u8 * s, va_list * args)
559{
560 u8 *a = va_arg (*args, u8 *);
561
562 return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
563 a[0], a[1], a[2], a[3], a[4], a[5]);
564}
565#endif
566
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100567void
568ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
569{
570 if (is_ip4)
571 dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
572 else
573 clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
574 sizeof (ip6_address_t));
575}
576
Neale Ranns097fa662018-05-01 05:17:55 -0700577
Ole Troan01384fe2017-05-12 11:55:35 +0200578#define vl_api_bridge_domain_details_t_endian vl_noop_handler
579#define vl_api_bridge_domain_details_t_print vl_noop_handler
580
Damjan Marion7cd468a2016-12-19 23:05:39 +0100581static void vl_api_get_first_msg_id_reply_t_handler
582 (vl_api_get_first_msg_id_reply_t * mp)
583{
584 vat_main_t *vam = &vat_main;
585 i32 retval = ntohl (mp->retval);
586
587 if (vam->async_mode)
588 {
589 vam->async_errors += (retval < 0);
590 }
591 else
592 {
593 vam->retval = retval;
594 vam->result_ready = 1;
595 }
596 if (retval >= 0)
597 {
598 errmsg ("first message id %d", ntohs (mp->first_msg_id));
599 }
600}
601
602static void vl_api_get_first_msg_id_reply_t_handler_json
603 (vl_api_get_first_msg_id_reply_t * mp)
604{
605 vat_main_t *vam = &vat_main;
606 vat_json_node_t node;
607
608 vat_json_init_object (&node);
609 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
610 vat_json_object_add_uint (&node, "first_msg_id",
611 (uint) ntohs (mp->first_msg_id));
612
613 vat_json_print (vam->ofp, &node);
614 vat_json_free (&node);
615
616 vam->retval = ntohl (mp->retval);
617 vam->result_ready = 1;
618}
619
Damjan Marion7cd468a2016-12-19 23:05:39 +0100620/* Format hex dump. */
621u8 *
622format_hex_bytes (u8 * s, va_list * va)
623{
624 u8 *bytes = va_arg (*va, u8 *);
625 int n_bytes = va_arg (*va, int);
626 uword i;
627
628 /* Print short or long form depending on byte count. */
629 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200630 u32 indent = format_get_indent (s);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100631
632 if (n_bytes == 0)
633 return s;
634
635 for (i = 0; i < n_bytes; i++)
636 {
637 if (!short_form && (i % 32) == 0)
638 s = format (s, "%08x: ", i);
639 s = format (s, "%02x", bytes[i]);
640 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
641 s = format (s, "\n%U", format_white_space, indent);
642 }
643
644 return s;
645}
646
Damjan Marion7cd468a2016-12-19 23:05:39 +0100647/*
648 * Generate boilerplate reply handlers, which
649 * dig the return value out of the xxx_reply_t API message,
650 * stick it into vam->retval, and set vam->result_ready
651 *
652 * Could also do this by pointing N message decode slots at
653 * a single function, but that could break in subtle ways.
654 */
655
Filip Tehlar0046e972021-06-26 22:12:08 +0000656#define foreach_standard_reply_retval_handler
Damjan Marion7cd468a2016-12-19 23:05:39 +0100657
658#define _(n) \
659 static void vl_api_##n##_t_handler \
660 (vl_api_##n##_t * mp) \
661 { \
662 vat_main_t * vam = &vat_main; \
663 i32 retval = ntohl(mp->retval); \
664 if (vam->async_mode) { \
665 vam->async_errors += (retval < 0); \
666 } else { \
667 vam->retval = retval; \
668 vam->result_ready = 1; \
669 } \
670 }
671foreach_standard_reply_retval_handler;
672#undef _
673
674#define _(n) \
675 static void vl_api_##n##_t_handler_json \
676 (vl_api_##n##_t * mp) \
677 { \
678 vat_main_t * vam = &vat_main; \
679 vat_json_node_t node; \
680 vat_json_init_object(&node); \
681 vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
682 vat_json_print(vam->ofp, &node); \
683 vam->retval = ntohl(mp->retval); \
684 vam->result_ready = 1; \
685 }
686foreach_standard_reply_retval_handler;
687#undef _
688
689/*
690 * Table of message reply handlers, must include boilerplate handlers
691 * we just generated
692 */
693
Filip Tehlar0577ff12021-06-27 00:18:57 +0000694#define foreach_vpe_api_reply_msg \
695 _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +0100696
Dave Baracha1a093d2017-03-02 13:13:23 -0500697#define foreach_standalone_reply_msg \
Dave Baracha1a093d2017-03-02 13:13:23 -0500698
Damjan Marion7cd468a2016-12-19 23:05:39 +0100699typedef struct
700{
701 u8 *name;
702 u32 value;
703} name_sort_t;
704
Damjan Marion7cd468a2016-12-19 23:05:39 +0100705#define STR_VTR_OP_CASE(op) \
706 case L2_VTR_ ## op: \
707 return "" # op;
708
Damjan Marion7cd468a2016-12-19 23:05:39 +0100709int
Filip Tehlar0577ff12021-06-27 00:18:57 +0000710api_sw_interface_dump (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100711{
Filip Tehlar0577ff12021-06-27 00:18:57 +0000712 return 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100713}
714
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100715uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000716unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100717{
jialv01082ebeb2019-09-10 00:23:55 +0800718 vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100719 u32 x[4];
720
721 if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
722 return 0;
723
724 addr->domain = x[0];
725 addr->bus = x[1];
726 addr->slot = x[2];
727 addr->function = x[3];
728
729 return 1;
730}
731
Neale Ranns097fa662018-05-01 05:17:55 -0700732uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000733unformat_fib_path (unformat_input_t *input, va_list *args)
Neale Ranns097fa662018-05-01 05:17:55 -0700734{
735 vat_main_t *vam = va_arg (*args, vat_main_t *);
736 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
737 u32 weight, preference;
738 mpls_label_t out_label;
739
740 clib_memset (path, 0, sizeof (*path));
741 path->weight = 1;
742 path->sw_if_index = ~0;
743 path->rpf_id = ~0;
744 path->n_labels = 0;
745
746 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
747 {
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000748 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
749 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
750 &path->sw_if_index))
Neale Ranns097fa662018-05-01 05:17:55 -0700751 {
752 path->proto = FIB_API_PATH_NH_PROTO_IP4;
753 }
754 else if (unformat (input, "%U %U",
755 unformat_vl_api_ip6_address,
756 &path->nh.address.ip6,
757 api_unformat_sw_if_index, vam, &path->sw_if_index))
758 {
759 path->proto = FIB_API_PATH_NH_PROTO_IP6;
760 }
761 else if (unformat (input, "weight %u", &weight))
762 {
763 path->weight = weight;
764 }
765 else if (unformat (input, "preference %u", &preference))
766 {
767 path->preference = preference;
768 }
769 else if (unformat (input, "%U next-hop-table %d",
770 unformat_vl_api_ip4_address,
771 &path->nh.address.ip4, &path->table_id))
772 {
773 path->proto = FIB_API_PATH_NH_PROTO_IP4;
774 }
775 else if (unformat (input, "%U next-hop-table %d",
776 unformat_vl_api_ip6_address,
777 &path->nh.address.ip6, &path->table_id))
778 {
779 path->proto = FIB_API_PATH_NH_PROTO_IP6;
780 }
781 else if (unformat (input, "%U",
782 unformat_vl_api_ip4_address, &path->nh.address.ip4))
783 {
784 /*
785 * the recursive next-hops are by default in the default table
786 */
787 path->table_id = 0;
788 path->sw_if_index = ~0;
789 path->proto = FIB_API_PATH_NH_PROTO_IP4;
790 }
791 else if (unformat (input, "%U",
792 unformat_vl_api_ip6_address, &path->nh.address.ip6))
793 {
794 /*
795 * the recursive next-hops are by default in the default table
796 */
797 path->table_id = 0;
798 path->sw_if_index = ~0;
799 path->proto = FIB_API_PATH_NH_PROTO_IP6;
800 }
801 else if (unformat (input, "resolve-via-host"))
802 {
803 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
804 }
805 else if (unformat (input, "resolve-via-attached"))
806 {
807 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
808 }
809 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
810 {
811 path->type = FIB_API_PATH_TYPE_LOCAL;
812 path->sw_if_index = ~0;
813 path->proto = FIB_API_PATH_NH_PROTO_IP4;
814 }
815 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
816 {
817 path->type = FIB_API_PATH_TYPE_LOCAL;
818 path->sw_if_index = ~0;
819 path->proto = FIB_API_PATH_NH_PROTO_IP6;
820 }
821 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
822 ;
823 else if (unformat (input, "via-label %d", &path->nh.via_label))
824 {
825 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
826 path->sw_if_index = ~0;
827 }
828 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
829 {
830 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
831 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
832 }
833 else if (unformat (input, "local"))
834 {
835 path->type = FIB_API_PATH_TYPE_LOCAL;
836 }
837 else if (unformat (input, "out-labels"))
838 {
839 while (unformat (input, "%d", &out_label))
840 {
841 path->label_stack[path->n_labels].label = out_label;
842 path->label_stack[path->n_labels].is_uniform = 0;
843 path->label_stack[path->n_labels].ttl = 64;
844 path->n_labels++;
845 }
846 }
847 else if (unformat (input, "via"))
848 {
849 /* new path, back up and return */
850 unformat_put_input (input);
851 unformat_put_input (input);
852 unformat_put_input (input);
853 unformat_put_input (input);
854 break;
855 }
856 else
857 {
858 return (0);
859 }
860 }
861
862 path->proto = ntohl (path->proto);
863 path->type = ntohl (path->type);
864 path->flags = ntohl (path->flags);
865 path->table_id = ntohl (path->table_id);
866 path->sw_if_index = ntohl (path->sw_if_index);
867
868 return (1);
869}
870
Damjan Marion7cd468a2016-12-19 23:05:39 +0100871#define foreach_create_subif_bit \
872_(no_tags) \
873_(one_tag) \
874_(two_tags) \
875_(dot1ad) \
876_(exact_match) \
877_(default_sub) \
878_(outer_vlan_id_any) \
879_(inner_vlan_id_any)
880
Jakub Grajciar053204a2019-03-18 13:17:53 +0100881#define foreach_create_subif_flag \
882_(0, "no_tags") \
883_(1, "one_tag") \
884_(2, "two_tags") \
885_(3, "dot1ad") \
886_(4, "exact_match") \
887_(5, "default_sub") \
888_(6, "outer_vlan_id_any") \
889_(7, "inner_vlan_id_any")
890
Pablo Camarillofb380952016-12-07 18:34:18 +0100891
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000892#define foreach_tcp_proto_field \
893 _ (src_port) \
894 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100895
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000896#define foreach_udp_proto_field \
897 _ (src_port) \
898 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100899
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000900#define foreach_ip4_proto_field \
901 _ (src_address) \
902 _ (dst_address) \
903 _ (tos) \
904 _ (length) \
905 _ (fragment_id) \
906 _ (ttl) \
907 _ (protocol) \
908 _ (checksum)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100909
Dave Barach4a3f69c2017-02-22 12:44:56 -0500910typedef struct
911{
912 u16 src_port, dst_port;
913} tcpudp_header_t;
914
915#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +0100916uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000917unformat_tcp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100918{
919 u8 **maskp = va_arg (*args, u8 **);
920 u8 *mask = 0;
921 u8 found_something = 0;
922 tcp_header_t *tcp;
923
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000924#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100925 foreach_tcp_proto_field;
926#undef _
927
928 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
929 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000930 if (0)
931 ;
932#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100933 foreach_tcp_proto_field
934#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000935 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100936 }
937
938#define _(a) found_something += a;
939 foreach_tcp_proto_field;
940#undef _
941
942 if (found_something == 0)
943 return 0;
944
945 vec_validate (mask, sizeof (*tcp) - 1);
946
947 tcp = (tcp_header_t *) mask;
948
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000949#define _(a) \
950 if (a) \
951 clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100952 foreach_tcp_proto_field;
953#undef _
954
955 *maskp = mask;
956 return 1;
957}
958
959uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000960unformat_udp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100961{
962 u8 **maskp = va_arg (*args, u8 **);
963 u8 *mask = 0;
964 u8 found_something = 0;
965 udp_header_t *udp;
966
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000967#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100968 foreach_udp_proto_field;
969#undef _
970
971 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
972 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000973 if (0)
974 ;
975#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100976 foreach_udp_proto_field
977#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000978 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100979 }
980
981#define _(a) found_something += a;
982 foreach_udp_proto_field;
983#undef _
984
985 if (found_something == 0)
986 return 0;
987
988 vec_validate (mask, sizeof (*udp) - 1);
989
990 udp = (udp_header_t *) mask;
991
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000992#define _(a) \
993 if (a) \
994 clib_memset (&udp->a, 0xff, sizeof (udp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100995 foreach_udp_proto_field;
996#undef _
997
998 *maskp = mask;
999 return 1;
1000}
1001
Damjan Marion7cd468a2016-12-19 23:05:39 +01001002uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001003unformat_l4_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001004{
1005 u8 **maskp = va_arg (*args, u8 **);
1006 u16 src_port = 0, dst_port = 0;
1007 tcpudp_header_t *tcpudp;
1008
1009 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1010 {
1011 if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
1012 return 1;
1013 else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
1014 return 1;
1015 else if (unformat (input, "src_port"))
1016 src_port = 0xFFFF;
1017 else if (unformat (input, "dst_port"))
1018 dst_port = 0xFFFF;
1019 else
1020 return 0;
1021 }
1022
1023 if (!src_port && !dst_port)
1024 return 0;
1025
1026 u8 *mask = 0;
1027 vec_validate (mask, sizeof (tcpudp_header_t) - 1);
1028
1029 tcpudp = (tcpudp_header_t *) mask;
1030 tcpudp->src_port = src_port;
1031 tcpudp->dst_port = dst_port;
1032
1033 *maskp = mask;
1034
1035 return 1;
1036}
1037
1038uword
1039unformat_ip4_mask (unformat_input_t * input, va_list * args)
1040{
1041 u8 **maskp = va_arg (*args, u8 **);
1042 u8 *mask = 0;
1043 u8 found_something = 0;
1044 ip4_header_t *ip;
1045
1046#define _(a) u8 a=0;
1047 foreach_ip4_proto_field;
1048#undef _
1049 u8 version = 0;
1050 u8 hdr_length = 0;
1051
1052
1053 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1054 {
1055 if (unformat (input, "version"))
1056 version = 1;
1057 else if (unformat (input, "hdr_length"))
1058 hdr_length = 1;
1059 else if (unformat (input, "src"))
1060 src_address = 1;
1061 else if (unformat (input, "dst"))
1062 dst_address = 1;
1063 else if (unformat (input, "proto"))
1064 protocol = 1;
1065
1066#define _(a) else if (unformat (input, #a)) a=1;
1067 foreach_ip4_proto_field
1068#undef _
1069 else
1070 break;
1071 }
1072
1073#define _(a) found_something += a;
1074 foreach_ip4_proto_field;
1075#undef _
1076
1077 if (found_something == 0)
1078 return 0;
1079
1080 vec_validate (mask, sizeof (*ip) - 1);
1081
1082 ip = (ip4_header_t *) mask;
1083
Dave Barachb7b92992018-10-17 10:38:51 -04001084#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001085 foreach_ip4_proto_field;
1086#undef _
1087
1088 ip->ip_version_and_header_length = 0;
1089
1090 if (version)
1091 ip->ip_version_and_header_length |= 0xF0;
1092
1093 if (hdr_length)
1094 ip->ip_version_and_header_length |= 0x0F;
1095
1096 *maskp = mask;
1097 return 1;
1098}
1099
1100#define foreach_ip6_proto_field \
1101_(src_address) \
1102_(dst_address) \
1103_(payload_length) \
1104_(hop_limit) \
1105_(protocol)
1106
1107uword
1108unformat_ip6_mask (unformat_input_t * input, va_list * args)
1109{
1110 u8 **maskp = va_arg (*args, u8 **);
1111 u8 *mask = 0;
1112 u8 found_something = 0;
1113 ip6_header_t *ip;
1114 u32 ip_version_traffic_class_and_flow_label;
1115
1116#define _(a) u8 a=0;
1117 foreach_ip6_proto_field;
1118#undef _
1119 u8 version = 0;
1120 u8 traffic_class = 0;
1121 u8 flow_label = 0;
1122
1123 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1124 {
1125 if (unformat (input, "version"))
1126 version = 1;
1127 else if (unformat (input, "traffic-class"))
1128 traffic_class = 1;
1129 else if (unformat (input, "flow-label"))
1130 flow_label = 1;
1131 else if (unformat (input, "src"))
1132 src_address = 1;
1133 else if (unformat (input, "dst"))
1134 dst_address = 1;
1135 else if (unformat (input, "proto"))
1136 protocol = 1;
1137
1138#define _(a) else if (unformat (input, #a)) a=1;
1139 foreach_ip6_proto_field
1140#undef _
1141 else
1142 break;
1143 }
1144
1145#define _(a) found_something += a;
1146 foreach_ip6_proto_field;
1147#undef _
1148
1149 if (found_something == 0)
1150 return 0;
1151
1152 vec_validate (mask, sizeof (*ip) - 1);
1153
1154 ip = (ip6_header_t *) mask;
1155
Dave Barachb7b92992018-10-17 10:38:51 -04001156#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001157 foreach_ip6_proto_field;
1158#undef _
1159
1160 ip_version_traffic_class_and_flow_label = 0;
1161
1162 if (version)
1163 ip_version_traffic_class_and_flow_label |= 0xF0000000;
1164
1165 if (traffic_class)
1166 ip_version_traffic_class_and_flow_label |= 0x0FF00000;
1167
1168 if (flow_label)
1169 ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
1170
1171 ip->ip_version_traffic_class_and_flow_label =
1172 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1173
1174 *maskp = mask;
1175 return 1;
1176}
1177
1178uword
1179unformat_l3_mask (unformat_input_t * input, va_list * args)
1180{
1181 u8 **maskp = va_arg (*args, u8 **);
1182
1183 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1184 {
1185 if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
1186 return 1;
1187 else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
1188 return 1;
1189 else
1190 break;
1191 }
1192 return 0;
1193}
1194
1195uword
1196unformat_l2_mask (unformat_input_t * input, va_list * args)
1197{
1198 u8 **maskp = va_arg (*args, u8 **);
1199 u8 *mask = 0;
1200 u8 src = 0;
1201 u8 dst = 0;
1202 u8 proto = 0;
1203 u8 tag1 = 0;
1204 u8 tag2 = 0;
1205 u8 ignore_tag1 = 0;
1206 u8 ignore_tag2 = 0;
1207 u8 cos1 = 0;
1208 u8 cos2 = 0;
1209 u8 dot1q = 0;
1210 u8 dot1ad = 0;
1211 int len = 14;
1212
1213 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1214 {
1215 if (unformat (input, "src"))
1216 src = 1;
1217 else if (unformat (input, "dst"))
1218 dst = 1;
1219 else if (unformat (input, "proto"))
1220 proto = 1;
1221 else if (unformat (input, "tag1"))
1222 tag1 = 1;
1223 else if (unformat (input, "tag2"))
1224 tag2 = 1;
1225 else if (unformat (input, "ignore-tag1"))
1226 ignore_tag1 = 1;
1227 else if (unformat (input, "ignore-tag2"))
1228 ignore_tag2 = 1;
1229 else if (unformat (input, "cos1"))
1230 cos1 = 1;
1231 else if (unformat (input, "cos2"))
1232 cos2 = 1;
1233 else if (unformat (input, "dot1q"))
1234 dot1q = 1;
1235 else if (unformat (input, "dot1ad"))
1236 dot1ad = 1;
1237 else
1238 break;
1239 }
1240 if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
1241 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1242 return 0;
1243
1244 if (tag1 || ignore_tag1 || cos1 || dot1q)
1245 len = 18;
1246 if (tag2 || ignore_tag2 || cos2 || dot1ad)
1247 len = 22;
1248
1249 vec_validate (mask, len - 1);
1250
1251 if (dst)
Dave Barachb7b92992018-10-17 10:38:51 -04001252 clib_memset (mask, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001253
1254 if (src)
Dave Barachb7b92992018-10-17 10:38:51 -04001255 clib_memset (mask + 6, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001256
1257 if (tag2 || dot1ad)
1258 {
1259 /* inner vlan tag */
1260 if (tag2)
1261 {
1262 mask[19] = 0xff;
1263 mask[18] = 0x0f;
1264 }
1265 if (cos2)
1266 mask[18] |= 0xe0;
1267 if (proto)
1268 mask[21] = mask[20] = 0xff;
1269 if (tag1)
1270 {
1271 mask[15] = 0xff;
1272 mask[14] = 0x0f;
1273 }
1274 if (cos1)
1275 mask[14] |= 0xe0;
1276 *maskp = mask;
1277 return 1;
1278 }
1279 if (tag1 | dot1q)
1280 {
1281 if (tag1)
1282 {
1283 mask[15] = 0xff;
1284 mask[14] = 0x0f;
1285 }
1286 if (cos1)
1287 mask[14] |= 0xe0;
1288 if (proto)
1289 mask[16] = mask[17] = 0xff;
1290
1291 *maskp = mask;
1292 return 1;
1293 }
1294 if (cos2)
1295 mask[18] |= 0xe0;
1296 if (cos1)
1297 mask[14] |= 0xe0;
1298 if (proto)
1299 mask[12] = mask[13] = 0xff;
1300
1301 *maskp = mask;
1302 return 1;
1303}
1304
1305uword
1306unformat_classify_mask (unformat_input_t * input, va_list * args)
1307{
1308 u8 **maskp = va_arg (*args, u8 **);
1309 u32 *skipp = va_arg (*args, u32 *);
1310 u32 *matchp = va_arg (*args, u32 *);
1311 u32 match;
1312 u8 *mask = 0;
1313 u8 *l2 = 0;
1314 u8 *l3 = 0;
1315 u8 *l4 = 0;
1316 int i;
1317
1318 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1319 {
1320 if (unformat (input, "hex %U", unformat_hex_string, &mask))
1321 ;
1322 else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
1323 ;
1324 else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
1325 ;
1326 else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
1327 ;
1328 else
1329 break;
1330 }
1331
1332 if (l4 && !l3)
1333 {
1334 vec_free (mask);
1335 vec_free (l2);
1336 vec_free (l4);
1337 return 0;
1338 }
1339
1340 if (mask || l2 || l3 || l4)
1341 {
1342 if (l2 || l3 || l4)
1343 {
1344 /* "With a free Ethernet header in every package" */
1345 if (l2 == 0)
1346 vec_validate (l2, 13);
1347 mask = l2;
1348 if (vec_len (l3))
1349 {
1350 vec_append (mask, l3);
1351 vec_free (l3);
1352 }
1353 if (vec_len (l4))
1354 {
1355 vec_append (mask, l4);
1356 vec_free (l4);
1357 }
1358 }
1359
1360 /* Scan forward looking for the first significant mask octet */
1361 for (i = 0; i < vec_len (mask); i++)
1362 if (mask[i])
1363 break;
1364
1365 /* compute (skip, match) params */
1366 *skipp = i / sizeof (u32x4);
1367 vec_delete (mask, *skipp * sizeof (u32x4), 0);
1368
1369 /* Pad mask to an even multiple of the vector size */
1370 while (vec_len (mask) % sizeof (u32x4))
1371 vec_add1 (mask, 0);
1372
1373 match = vec_len (mask) / sizeof (u32x4);
1374
1375 for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
1376 {
1377 u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
1378 if (*tmp || *(tmp + 1))
1379 break;
1380 match--;
1381 }
1382 if (match == 0)
1383 clib_warning ("BUG: match 0");
1384
1385 _vec_len (mask) = match * sizeof (u32x4);
1386
1387 *matchp = match;
1388 *maskp = mask;
1389
1390 return 1;
1391 }
1392
1393 return 0;
1394}
Dave Barach4a3f69c2017-02-22 12:44:56 -05001395#endif /* VPP_API_TEST_BUILTIN */
Damjan Marion7cd468a2016-12-19 23:05:39 +01001396
1397#define foreach_l2_next \
1398_(drop, DROP) \
1399_(ethernet, ETHERNET_INPUT) \
1400_(ip4, IP4_INPUT) \
1401_(ip6, IP6_INPUT)
1402
1403uword
1404unformat_l2_next_index (unformat_input_t * input, va_list * args)
1405{
1406 u32 *miss_next_indexp = va_arg (*args, u32 *);
1407 u32 next_index = 0;
1408 u32 tmp;
1409
1410#define _(n,N) \
1411 if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
1412 foreach_l2_next;
1413#undef _
1414
1415 if (unformat (input, "%d", &tmp))
1416 {
1417 next_index = tmp;
1418 goto out;
1419 }
1420
1421 return 0;
1422
1423out:
1424 *miss_next_indexp = next_index;
1425 return 1;
1426}
1427
1428#define foreach_ip_next \
1429_(drop, DROP) \
1430_(local, LOCAL) \
1431_(rewrite, REWRITE)
1432
1433uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001434api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001435{
1436 u32 *miss_next_indexp = va_arg (*args, u32 *);
1437 u32 next_index = 0;
1438 u32 tmp;
1439
1440#define _(n,N) \
1441 if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
1442 foreach_ip_next;
1443#undef _
1444
1445 if (unformat (input, "%d", &tmp))
1446 {
1447 next_index = tmp;
1448 goto out;
1449 }
1450
1451 return 0;
1452
1453out:
1454 *miss_next_indexp = next_index;
1455 return 1;
1456}
1457
1458#define foreach_acl_next \
1459_(deny, DENY)
1460
1461uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001462api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001463{
1464 u32 *miss_next_indexp = va_arg (*args, u32 *);
1465 u32 next_index = 0;
1466 u32 tmp;
1467
1468#define _(n,N) \
1469 if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
1470 foreach_acl_next;
1471#undef _
1472
1473 if (unformat (input, "permit"))
1474 {
1475 next_index = ~0;
1476 goto out;
1477 }
1478 else if (unformat (input, "%d", &tmp))
1479 {
1480 next_index = tmp;
1481 goto out;
1482 }
1483
1484 return 0;
1485
1486out:
1487 *miss_next_indexp = next_index;
1488 return 1;
1489}
1490
1491uword
1492unformat_policer_precolor (unformat_input_t * input, va_list * args)
1493{
1494 u32 *r = va_arg (*args, u32 *);
1495
1496 if (unformat (input, "conform-color"))
1497 *r = POLICE_CONFORM;
1498 else if (unformat (input, "exceed-color"))
1499 *r = POLICE_EXCEED;
1500 else
1501 return 0;
1502
1503 return 1;
1504}
1505
Dave Barach4a3f69c2017-02-22 12:44:56 -05001506#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01001507uword
1508unformat_l4_match (unformat_input_t * input, va_list * args)
1509{
1510 u8 **matchp = va_arg (*args, u8 **);
1511
1512 u8 *proto_header = 0;
1513 int src_port = 0;
1514 int dst_port = 0;
1515
1516 tcpudp_header_t h;
1517
1518 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1519 {
1520 if (unformat (input, "src_port %d", &src_port))
1521 ;
1522 else if (unformat (input, "dst_port %d", &dst_port))
1523 ;
1524 else
1525 return 0;
1526 }
1527
1528 h.src_port = clib_host_to_net_u16 (src_port);
1529 h.dst_port = clib_host_to_net_u16 (dst_port);
1530 vec_validate (proto_header, sizeof (h) - 1);
1531 memcpy (proto_header, &h, sizeof (h));
1532
1533 *matchp = proto_header;
1534
1535 return 1;
1536}
1537
1538uword
1539unformat_ip4_match (unformat_input_t * input, va_list * args)
1540{
1541 u8 **matchp = va_arg (*args, u8 **);
1542 u8 *match = 0;
1543 ip4_header_t *ip;
1544 int version = 0;
1545 u32 version_val;
1546 int hdr_length = 0;
1547 u32 hdr_length_val;
1548 int src = 0, dst = 0;
1549 ip4_address_t src_val, dst_val;
1550 int proto = 0;
1551 u32 proto_val;
1552 int tos = 0;
1553 u32 tos_val;
1554 int length = 0;
1555 u32 length_val;
1556 int fragment_id = 0;
1557 u32 fragment_id_val;
1558 int ttl = 0;
1559 int ttl_val;
1560 int checksum = 0;
1561 u32 checksum_val;
1562
1563 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1564 {
1565 if (unformat (input, "version %d", &version_val))
1566 version = 1;
1567 else if (unformat (input, "hdr_length %d", &hdr_length_val))
1568 hdr_length = 1;
1569 else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
1570 src = 1;
1571 else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
1572 dst = 1;
1573 else if (unformat (input, "proto %d", &proto_val))
1574 proto = 1;
1575 else if (unformat (input, "tos %d", &tos_val))
1576 tos = 1;
1577 else if (unformat (input, "length %d", &length_val))
1578 length = 1;
1579 else if (unformat (input, "fragment_id %d", &fragment_id_val))
1580 fragment_id = 1;
1581 else if (unformat (input, "ttl %d", &ttl_val))
1582 ttl = 1;
1583 else if (unformat (input, "checksum %d", &checksum_val))
1584 checksum = 1;
1585 else
1586 break;
1587 }
1588
1589 if (version + hdr_length + src + dst + proto + tos + length + fragment_id
1590 + ttl + checksum == 0)
1591 return 0;
1592
1593 /*
1594 * Aligned because we use the real comparison functions
1595 */
1596 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1597
1598 ip = (ip4_header_t *) match;
1599
1600 /* These are realistically matched in practice */
1601 if (src)
1602 ip->src_address.as_u32 = src_val.as_u32;
1603
1604 if (dst)
1605 ip->dst_address.as_u32 = dst_val.as_u32;
1606
1607 if (proto)
1608 ip->protocol = proto_val;
1609
1610
1611 /* These are not, but they're included for completeness */
1612 if (version)
1613 ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
1614
1615 if (hdr_length)
1616 ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
1617
1618 if (tos)
1619 ip->tos = tos_val;
1620
1621 if (length)
1622 ip->length = clib_host_to_net_u16 (length_val);
1623
1624 if (ttl)
1625 ip->ttl = ttl_val;
1626
1627 if (checksum)
1628 ip->checksum = clib_host_to_net_u16 (checksum_val);
1629
1630 *matchp = match;
1631 return 1;
1632}
1633
1634uword
1635unformat_ip6_match (unformat_input_t * input, va_list * args)
1636{
1637 u8 **matchp = va_arg (*args, u8 **);
1638 u8 *match = 0;
1639 ip6_header_t *ip;
1640 int version = 0;
1641 u32 version_val;
1642 u8 traffic_class = 0;
1643 u32 traffic_class_val = 0;
1644 u8 flow_label = 0;
1645 u8 flow_label_val;
1646 int src = 0, dst = 0;
1647 ip6_address_t src_val, dst_val;
1648 int proto = 0;
1649 u32 proto_val;
1650 int payload_length = 0;
1651 u32 payload_length_val;
1652 int hop_limit = 0;
1653 int hop_limit_val;
1654 u32 ip_version_traffic_class_and_flow_label;
1655
1656 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1657 {
1658 if (unformat (input, "version %d", &version_val))
1659 version = 1;
1660 else if (unformat (input, "traffic_class %d", &traffic_class_val))
1661 traffic_class = 1;
1662 else if (unformat (input, "flow_label %d", &flow_label_val))
1663 flow_label = 1;
1664 else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
1665 src = 1;
1666 else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
1667 dst = 1;
1668 else if (unformat (input, "proto %d", &proto_val))
1669 proto = 1;
1670 else if (unformat (input, "payload_length %d", &payload_length_val))
1671 payload_length = 1;
1672 else if (unformat (input, "hop_limit %d", &hop_limit_val))
1673 hop_limit = 1;
1674 else
1675 break;
1676 }
1677
1678 if (version + traffic_class + flow_label + src + dst + proto +
1679 payload_length + hop_limit == 0)
1680 return 0;
1681
1682 /*
1683 * Aligned because we use the real comparison functions
1684 */
1685 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1686
1687 ip = (ip6_header_t *) match;
1688
1689 if (src)
1690 clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
1691
1692 if (dst)
1693 clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
1694
1695 if (proto)
1696 ip->protocol = proto_val;
1697
1698 ip_version_traffic_class_and_flow_label = 0;
1699
1700 if (version)
1701 ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
1702
1703 if (traffic_class)
1704 ip_version_traffic_class_and_flow_label |=
1705 (traffic_class_val & 0xFF) << 20;
1706
1707 if (flow_label)
1708 ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
1709
1710 ip->ip_version_traffic_class_and_flow_label =
1711 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1712
1713 if (payload_length)
1714 ip->payload_length = clib_host_to_net_u16 (payload_length_val);
1715
1716 if (hop_limit)
1717 ip->hop_limit = hop_limit_val;
1718
1719 *matchp = match;
1720 return 1;
1721}
1722
1723uword
1724unformat_l3_match (unformat_input_t * input, va_list * args)
1725{
1726 u8 **matchp = va_arg (*args, u8 **);
1727
1728 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1729 {
1730 if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
1731 return 1;
1732 else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
1733 return 1;
1734 else
1735 break;
1736 }
1737 return 0;
1738}
1739
1740uword
1741unformat_vlan_tag (unformat_input_t * input, va_list * args)
1742{
1743 u8 *tagp = va_arg (*args, u8 *);
1744 u32 tag;
1745
1746 if (unformat (input, "%d", &tag))
1747 {
1748 tagp[0] = (tag >> 8) & 0x0F;
1749 tagp[1] = tag & 0xFF;
1750 return 1;
1751 }
1752
1753 return 0;
1754}
1755
1756uword
1757unformat_l2_match (unformat_input_t * input, va_list * args)
1758{
1759 u8 **matchp = va_arg (*args, u8 **);
1760 u8 *match = 0;
1761 u8 src = 0;
1762 u8 src_val[6];
1763 u8 dst = 0;
1764 u8 dst_val[6];
1765 u8 proto = 0;
1766 u16 proto_val;
1767 u8 tag1 = 0;
1768 u8 tag1_val[2];
1769 u8 tag2 = 0;
1770 u8 tag2_val[2];
1771 int len = 14;
1772 u8 ignore_tag1 = 0;
1773 u8 ignore_tag2 = 0;
1774 u8 cos1 = 0;
1775 u8 cos2 = 0;
1776 u32 cos1_val = 0;
1777 u32 cos2_val = 0;
1778
1779 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1780 {
1781 if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
1782 src = 1;
1783 else
1784 if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
1785 dst = 1;
1786 else if (unformat (input, "proto %U",
1787 unformat_ethernet_type_host_byte_order, &proto_val))
1788 proto = 1;
1789 else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
1790 tag1 = 1;
1791 else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
1792 tag2 = 1;
1793 else if (unformat (input, "ignore-tag1"))
1794 ignore_tag1 = 1;
1795 else if (unformat (input, "ignore-tag2"))
1796 ignore_tag2 = 1;
1797 else if (unformat (input, "cos1 %d", &cos1_val))
1798 cos1 = 1;
1799 else if (unformat (input, "cos2 %d", &cos2_val))
1800 cos2 = 1;
1801 else
1802 break;
1803 }
1804 if ((src + dst + proto + tag1 + tag2 +
1805 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1806 return 0;
1807
1808 if (tag1 || ignore_tag1 || cos1)
1809 len = 18;
1810 if (tag2 || ignore_tag2 || cos2)
1811 len = 22;
1812
1813 vec_validate_aligned (match, len - 1, sizeof (u32x4));
1814
1815 if (dst)
1816 clib_memcpy (match, dst_val, 6);
1817
1818 if (src)
1819 clib_memcpy (match + 6, src_val, 6);
1820
1821 if (tag2)
1822 {
1823 /* inner vlan tag */
1824 match[19] = tag2_val[1];
1825 match[18] = tag2_val[0];
1826 if (cos2)
1827 match[18] |= (cos2_val & 0x7) << 5;
1828 if (proto)
1829 {
1830 match[21] = proto_val & 0xff;
1831 match[20] = proto_val >> 8;
1832 }
1833 if (tag1)
1834 {
1835 match[15] = tag1_val[1];
1836 match[14] = tag1_val[0];
1837 }
1838 if (cos1)
1839 match[14] |= (cos1_val & 0x7) << 5;
1840 *matchp = match;
1841 return 1;
1842 }
1843 if (tag1)
1844 {
1845 match[15] = tag1_val[1];
1846 match[14] = tag1_val[0];
1847 if (proto)
1848 {
1849 match[17] = proto_val & 0xff;
1850 match[16] = proto_val >> 8;
1851 }
1852 if (cos1)
1853 match[14] |= (cos1_val & 0x7) << 5;
1854
1855 *matchp = match;
1856 return 1;
1857 }
1858 if (cos2)
1859 match[18] |= (cos2_val & 0x7) << 5;
1860 if (cos1)
1861 match[14] |= (cos1_val & 0x7) << 5;
1862 if (proto)
1863 {
1864 match[13] = proto_val & 0xff;
1865 match[12] = proto_val >> 8;
1866 }
1867
1868 *matchp = match;
1869 return 1;
1870}
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -07001871
1872uword
1873unformat_qos_source (unformat_input_t * input, va_list * args)
1874{
1875 int *qs = va_arg (*args, int *);
1876
1877 if (unformat (input, "ip"))
1878 *qs = QOS_SOURCE_IP;
1879 else if (unformat (input, "mpls"))
1880 *qs = QOS_SOURCE_MPLS;
1881 else if (unformat (input, "ext"))
1882 *qs = QOS_SOURCE_EXT;
1883 else if (unformat (input, "vlan"))
1884 *qs = QOS_SOURCE_VLAN;
1885 else
1886 return 0;
1887
1888 return 1;
1889}
Dave Barach4a3f69c2017-02-22 12:44:56 -05001890#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01001891
1892uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001893api_unformat_classify_match (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001894{
1895 u8 **matchp = va_arg (*args, u8 **);
1896 u32 skip_n_vectors = va_arg (*args, u32);
1897 u32 match_n_vectors = va_arg (*args, u32);
1898
1899 u8 *match = 0;
1900 u8 *l2 = 0;
1901 u8 *l3 = 0;
1902 u8 *l4 = 0;
1903
1904 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1905 {
1906 if (unformat (input, "hex %U", unformat_hex_string, &match))
1907 ;
1908 else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
1909 ;
1910 else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
1911 ;
1912 else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
1913 ;
1914 else
1915 break;
1916 }
1917
1918 if (l4 && !l3)
1919 {
1920 vec_free (match);
1921 vec_free (l2);
1922 vec_free (l4);
1923 return 0;
1924 }
1925
1926 if (match || l2 || l3 || l4)
1927 {
1928 if (l2 || l3 || l4)
1929 {
1930 /* "Win a free Ethernet header in every packet" */
1931 if (l2 == 0)
1932 vec_validate_aligned (l2, 13, sizeof (u32x4));
1933 match = l2;
1934 if (vec_len (l3))
1935 {
1936 vec_append_aligned (match, l3, sizeof (u32x4));
1937 vec_free (l3);
1938 }
1939 if (vec_len (l4))
1940 {
1941 vec_append_aligned (match, l4, sizeof (u32x4));
1942 vec_free (l4);
1943 }
1944 }
1945
1946 /* Make sure the vector is big enough even if key is all 0's */
1947 vec_validate_aligned
1948 (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
1949 sizeof (u32x4));
1950
1951 /* Set size, include skipped vectors */
1952 _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
1953
1954 *matchp = match;
1955
1956 return 1;
1957 }
1958
1959 return 0;
1960}
1961
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001962#define foreach_vtr_op \
1963 _ ("disable", L2_VTR_DISABLED) \
1964 _ ("push-1", L2_VTR_PUSH_1) \
1965 _ ("push-2", L2_VTR_PUSH_2) \
1966 _ ("pop-1", L2_VTR_POP_1) \
1967 _ ("pop-2", L2_VTR_POP_2) \
1968 _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \
1969 _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \
1970 _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \
1971 _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001972
1973static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001974api_get_first_msg_id (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001975{
1976 vl_api_get_first_msg_id_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001977 unformat_input_t *i = vam->input;
1978 u8 *name;
1979 u8 name_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001980 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001981
1982 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1983 {
1984 if (unformat (i, "client %s", &name))
1985 name_set = 1;
1986 else
1987 break;
1988 }
1989
1990 if (name_set == 0)
1991 {
1992 errmsg ("missing client name");
1993 return -99;
1994 }
1995 vec_add1 (name, 0);
1996
1997 if (vec_len (name) > 63)
1998 {
1999 errmsg ("client name too long");
2000 return -99;
2001 }
2002
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002003 M (GET_FIRST_MSG_ID, mp);
Ole Troan7adaa222019-08-27 15:05:27 +02002004 clib_memcpy (mp->name, name, vec_len (name));
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002005 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002006 W (ret);
2007 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002008}
2009
Damjan Marion7cd468a2016-12-19 23:05:39 +01002010#define foreach_pbb_vtr_op \
2011_("disable", L2_VTR_DISABLED) \
2012_("pop", L2_VTR_POP_2) \
2013_("push", L2_VTR_PUSH_2)
2014
Florin Corascea194d2017-10-02 00:18:51 -07002015static int
Florin Coras90a63982017-12-19 04:50:01 -08002016api_sock_init_shm (vat_main_t * vam)
2017{
2018#if VPP_API_TEST_BUILTIN == 0
2019 unformat_input_t *i = vam->input;
2020 vl_api_shm_elem_config_t *config = 0;
2021 u64 size = 64 << 20;
2022 int rv;
2023
2024 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2025 {
2026 if (unformat (i, "size %U", unformat_memory_size, &size))
2027 ;
2028 else
2029 break;
2030 }
2031
Dave Barach78958722018-05-10 16:44:27 -04002032 /*
2033 * Canned custom ring allocator config.
2034 * Should probably parse all of this
2035 */
2036 vec_validate (config, 6);
Florin Coras90a63982017-12-19 04:50:01 -08002037 config[0].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002038 config[0].size = 256;
Dave Barach78958722018-05-10 16:44:27 -04002039 config[0].count = 32;
2040
2041 config[1].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002042 config[1].size = 1024;
Dave Barach78958722018-05-10 16:44:27 -04002043 config[1].count = 16;
2044
2045 config[2].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002046 config[2].size = 4096;
Dave Barach78958722018-05-10 16:44:27 -04002047 config[2].count = 2;
2048
2049 config[3].type = VL_API_CLIENT_RING;
2050 config[3].size = 256;
2051 config[3].count = 32;
2052
2053 config[4].type = VL_API_CLIENT_RING;
2054 config[4].size = 1024;
2055 config[4].count = 16;
2056
2057 config[5].type = VL_API_CLIENT_RING;
2058 config[5].size = 4096;
2059 config[5].count = 2;
2060
2061 config[6].type = VL_API_QUEUE;
2062 config[6].count = 128;
2063 config[6].size = sizeof (uword);
2064
Tomasz Kulasek97dcf5b2019-01-31 18:26:32 +01002065 rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
Florin Coras90a63982017-12-19 04:50:01 -08002066 if (!rv)
2067 vam->client_index_invalid = 1;
2068 return rv;
2069#else
2070 return -99;
2071#endif
2072}
2073
Florin Coras6c36f532017-11-03 18:32:34 -07002074static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002075q_or_quit (vat_main_t * vam)
2076{
Dave Barachdef19da2017-02-22 17:29:20 -05002077#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01002078 longjmp (vam->jump_buf, 1);
Dave Barachdef19da2017-02-22 17:29:20 -05002079#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002080 return 0; /* not so much */
2081}
2082
2083static int
2084q (vat_main_t * vam)
2085{
2086 return q_or_quit (vam);
2087}
2088
2089static int
2090quit (vat_main_t * vam)
2091{
2092 return q_or_quit (vam);
2093}
2094
2095static int
2096comment (vat_main_t * vam)
2097{
2098 return 0;
2099}
2100
2101static int
Dave Barachb09f4d02019-07-15 16:00:03 -04002102elog_save (vat_main_t * vam)
2103{
2104#if VPP_API_TEST_BUILTIN == 0
2105 elog_main_t *em = &vam->elog_main;
2106 unformat_input_t *i = vam->input;
2107 char *file, *chroot_file;
2108 clib_error_t *error;
2109
2110 if (!unformat (i, "%s", &file))
2111 {
2112 errmsg ("expected file name, got `%U'", format_unformat_error, i);
2113 return 0;
2114 }
2115
2116 /* It's fairly hard to get "../oopsie" through unformat; just in case */
2117 if (strstr (file, "..") || index (file, '/'))
2118 {
2119 errmsg ("illegal characters in filename '%s'", file);
2120 return 0;
2121 }
2122
2123 chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
2124
2125 vec_free (file);
2126
2127 errmsg ("Saving %wd of %wd events to %s",
2128 elog_n_events_in_buffer (em),
2129 elog_buffer_capacity (em), chroot_file);
2130
2131 error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
2132 vec_free (chroot_file);
2133
2134 if (error)
2135 clib_error_report (error);
2136#else
2137 errmsg ("Use the vpp event loger...");
2138#endif
2139
2140 return 0;
2141}
2142
2143static int
2144elog_setup (vat_main_t * vam)
2145{
2146#if VPP_API_TEST_BUILTIN == 0
2147 elog_main_t *em = &vam->elog_main;
2148 unformat_input_t *i = vam->input;
2149 u32 nevents = 128 << 10;
2150
2151 (void) unformat (i, "nevents %d", &nevents);
2152
2153 elog_init (em, nevents);
2154 vl_api_set_elog_main (em);
2155 vl_api_set_elog_trace_api_messages (1);
2156 errmsg ("Event logger initialized with %u events", nevents);
2157#else
2158 errmsg ("Use the vpp event loger...");
2159#endif
2160 return 0;
2161}
2162
2163static int
2164elog_enable (vat_main_t * vam)
2165{
2166#if VPP_API_TEST_BUILTIN == 0
2167 elog_main_t *em = &vam->elog_main;
2168
2169 elog_enable_disable (em, 1 /* enable */ );
2170 vl_api_set_elog_trace_api_messages (1);
2171 errmsg ("Event logger enabled...");
2172#else
2173 errmsg ("Use the vpp event loger...");
2174#endif
2175 return 0;
2176}
2177
2178static int
2179elog_disable (vat_main_t * vam)
2180{
2181#if VPP_API_TEST_BUILTIN == 0
2182 elog_main_t *em = &vam->elog_main;
2183
2184 elog_enable_disable (em, 0 /* enable */ );
2185 vl_api_set_elog_trace_api_messages (1);
2186 errmsg ("Event logger disabled...");
2187#else
2188 errmsg ("Use the vpp event loger...");
2189#endif
2190 return 0;
2191}
2192
2193static int
Dave Barach048a4e52018-06-01 18:52:25 -04002194statseg (vat_main_t * vam)
2195{
2196 ssvm_private_t *ssvmp = &vam->stat_segment;
2197 ssvm_shared_header_t *shared_header = ssvmp->sh;
2198 vlib_counter_t **counters;
2199 u64 thread0_index1_packets;
2200 u64 thread0_index1_bytes;
2201 f64 vector_rate, input_rate;
2202 uword *p;
2203
2204 uword *counter_vector_by_name;
2205 if (vam->stat_segment_lockp == 0)
2206 {
2207 errmsg ("Stat segment not mapped...");
2208 return -99;
2209 }
2210
2211 /* look up "/if/rx for sw_if_index 1 as a test */
2212
2213 clib_spinlock_lock (vam->stat_segment_lockp);
2214
2215 counter_vector_by_name = (uword *) shared_header->opaque[1];
2216
2217 p = hash_get_mem (counter_vector_by_name, "/if/rx");
2218 if (p == 0)
2219 {
2220 clib_spinlock_unlock (vam->stat_segment_lockp);
2221 errmsg ("/if/tx not found?");
2222 return -99;
2223 }
2224
2225 /* Fish per-thread vector of combined counters from shared memory */
2226 counters = (vlib_counter_t **) p[0];
2227
2228 if (vec_len (counters[0]) < 2)
2229 {
2230 clib_spinlock_unlock (vam->stat_segment_lockp);
2231 errmsg ("/if/tx vector length %d", vec_len (counters[0]));
2232 return -99;
2233 }
2234
2235 /* Read thread 0 sw_if_index 1 counter */
2236 thread0_index1_packets = counters[0][1].packets;
2237 thread0_index1_bytes = counters[0][1].bytes;
2238
2239 p = hash_get_mem (counter_vector_by_name, "vector_rate");
2240 if (p == 0)
2241 {
2242 clib_spinlock_unlock (vam->stat_segment_lockp);
2243 errmsg ("vector_rate not found?");
2244 return -99;
2245 }
2246
2247 vector_rate = *(f64 *) (p[0]);
2248 p = hash_get_mem (counter_vector_by_name, "input_rate");
2249 if (p == 0)
2250 {
2251 clib_spinlock_unlock (vam->stat_segment_lockp);
2252 errmsg ("input_rate not found?");
2253 return -99;
2254 }
2255 input_rate = *(f64 *) (p[0]);
2256
2257 clib_spinlock_unlock (vam->stat_segment_lockp);
2258
2259 print (vam->ofp, "vector_rate %.2f input_rate %.2f",
2260 vector_rate, input_rate);
2261 print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
2262 thread0_index1_packets, thread0_index1_bytes);
2263
2264 return 0;
2265}
2266
2267static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002268cmd_cmp (void *a1, void *a2)
2269{
2270 u8 **c1 = a1;
2271 u8 **c2 = a2;
2272
2273 return strcmp ((char *) (c1[0]), (char *) (c2[0]));
2274}
2275
2276static int
2277help (vat_main_t * vam)
2278{
2279 u8 **cmds = 0;
2280 u8 *name = 0;
2281 hash_pair_t *p;
2282 unformat_input_t *i = vam->input;
2283 int j;
2284
2285 if (unformat (i, "%s", &name))
2286 {
2287 uword *hs;
2288
2289 vec_add1 (name, 0);
2290
2291 hs = hash_get_mem (vam->help_by_name, name);
2292 if (hs)
2293 print (vam->ofp, "usage: %s %s", name, hs[0]);
2294 else
2295 print (vam->ofp, "No such msg / command '%s'", name);
2296 vec_free (name);
2297 return 0;
2298 }
2299
2300 print (vam->ofp, "Help is available for the following:");
2301
2302 /* *INDENT-OFF* */
2303 hash_foreach_pair (p, vam->function_by_name,
2304 ({
2305 vec_add1 (cmds, (u8 *)(p->key));
2306 }));
2307 /* *INDENT-ON* */
2308
2309 vec_sort_with_function (cmds, cmd_cmp);
2310
2311 for (j = 0; j < vec_len (cmds); j++)
2312 print (vam->ofp, "%s", cmds[j]);
2313
2314 vec_free (cmds);
2315 return 0;
2316}
2317
2318static int
2319set (vat_main_t * vam)
2320{
2321 u8 *name = 0, *value = 0;
2322 unformat_input_t *i = vam->input;
2323
2324 if (unformat (i, "%s", &name))
2325 {
2326 /* The input buffer is a vector, not a string. */
2327 value = vec_dup (i->buffer);
2328 vec_delete (value, i->index, 0);
2329 /* Almost certainly has a trailing newline */
2330 if (value[vec_len (value) - 1] == '\n')
2331 value[vec_len (value) - 1] = 0;
2332 /* Make sure it's a proper string, one way or the other */
2333 vec_add1 (value, 0);
2334 (void) clib_macro_set_value (&vam->macro_main,
2335 (char *) name, (char *) value);
2336 }
2337 else
2338 errmsg ("usage: set <name> <value>");
2339
2340 vec_free (name);
2341 vec_free (value);
2342 return 0;
2343}
2344
2345static int
2346unset (vat_main_t * vam)
2347{
2348 u8 *name = 0;
2349
2350 if (unformat (vam->input, "%s", &name))
2351 if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
2352 errmsg ("unset: %s wasn't set", name);
2353 vec_free (name);
2354 return 0;
2355}
2356
2357typedef struct
2358{
2359 u8 *name;
2360 u8 *value;
2361} macro_sort_t;
2362
2363
2364static int
2365macro_sort_cmp (void *a1, void *a2)
2366{
2367 macro_sort_t *s1 = a1;
2368 macro_sort_t *s2 = a2;
2369
2370 return strcmp ((char *) (s1->name), (char *) (s2->name));
2371}
2372
2373static int
2374dump_macro_table (vat_main_t * vam)
2375{
2376 macro_sort_t *sort_me = 0, *sm;
2377 int i;
2378 hash_pair_t *p;
2379
2380 /* *INDENT-OFF* */
2381 hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
2382 ({
2383 vec_add2 (sort_me, sm, 1);
2384 sm->name = (u8 *)(p->key);
2385 sm->value = (u8 *) (p->value[0]);
2386 }));
2387 /* *INDENT-ON* */
2388
2389 vec_sort_with_function (sort_me, macro_sort_cmp);
2390
2391 if (vec_len (sort_me))
2392 print (vam->ofp, "%-15s%s", "Name", "Value");
2393 else
2394 print (vam->ofp, "The macro table is empty...");
2395
2396 for (i = 0; i < vec_len (sort_me); i++)
2397 print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
2398 return 0;
2399}
2400
2401static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002402value_sort_cmp (void *a1, void *a2)
2403{
2404 name_sort_t *n1 = a1;
2405 name_sort_t *n2 = a2;
2406
2407 if (n1->value < n2->value)
2408 return -1;
2409 if (n1->value > n2->value)
2410 return 1;
2411 return 0;
2412}
2413
2414
2415static int
2416dump_msg_api_table (vat_main_t * vam)
2417{
Dave Barach39d69112019-11-27 11:42:13 -05002418 api_main_t *am = vlibapi_get_main ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01002419 name_sort_t *nses = 0, *ns;
2420 hash_pair_t *hp;
2421 int i;
2422
2423 /* *INDENT-OFF* */
2424 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
2425 ({
2426 vec_add2 (nses, ns, 1);
2427 ns->name = (u8 *)(hp->key);
2428 ns->value = (u32) hp->value[0];
2429 }));
2430 /* *INDENT-ON* */
2431
2432 vec_sort_with_function (nses, value_sort_cmp);
2433
2434 for (i = 0; i < vec_len (nses); i++)
2435 print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
2436 vec_free (nses);
2437 return 0;
2438}
2439
2440static int
2441get_msg_id (vat_main_t * vam)
2442{
2443 u8 *name_and_crc;
2444 u32 message_index;
2445
2446 if (unformat (vam->input, "%s", &name_and_crc))
2447 {
Florin Corase86a8ed2018-01-05 03:20:25 -08002448 message_index = vl_msg_api_get_msg_index (name_and_crc);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002449 if (message_index == ~0)
2450 {
2451 print (vam->ofp, " '%s' not found", name_and_crc);
2452 return 0;
2453 }
2454 print (vam->ofp, " '%s' has message index %d",
2455 name_and_crc, message_index);
2456 return 0;
2457 }
2458 errmsg ("name_and_crc required...");
2459 return 0;
2460}
2461
2462static int
2463search_node_table (vat_main_t * vam)
2464{
2465 unformat_input_t *line_input = vam->input;
2466 u8 *node_to_find;
2467 int j;
2468 vlib_node_t *node, *next_node;
2469 uword *p;
2470
2471 if (vam->graph_node_index_by_name == 0)
2472 {
2473 print (vam->ofp, "Node table empty, issue get_node_graph...");
2474 return 0;
2475 }
2476
2477 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2478 {
2479 if (unformat (line_input, "%s", &node_to_find))
2480 {
2481 vec_add1 (node_to_find, 0);
2482 p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
2483 if (p == 0)
2484 {
2485 print (vam->ofp, "%s not found...", node_to_find);
2486 goto out;
2487 }
Dave Barach1ddbc012018-06-13 09:26:05 -04002488 node = vam->graph_nodes[0][p[0]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01002489 print (vam->ofp, "[%d] %s", p[0], node->name);
2490 for (j = 0; j < vec_len (node->next_nodes); j++)
2491 {
2492 if (node->next_nodes[j] != ~0)
2493 {
Dave Barach1ddbc012018-06-13 09:26:05 -04002494 next_node = vam->graph_nodes[0][node->next_nodes[j]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01002495 print (vam->ofp, " [%d] %s", j, next_node->name);
2496 }
2497 }
2498 }
2499
2500 else
2501 {
2502 clib_warning ("parse error '%U'", format_unformat_error,
2503 line_input);
2504 return -99;
2505 }
2506
2507 out:
2508 vec_free (node_to_find);
2509
2510 }
2511
2512 return 0;
2513}
2514
2515
2516static int
2517script (vat_main_t * vam)
2518{
2519#if (VPP_API_TEST_BUILTIN==0)
2520 u8 *s = 0;
2521 char *save_current_file;
2522 unformat_input_t save_input;
2523 jmp_buf save_jump_buf;
2524 u32 save_line_number;
2525
2526 FILE *new_fp, *save_ifp;
2527
2528 if (unformat (vam->input, "%s", &s))
2529 {
2530 new_fp = fopen ((char *) s, "r");
2531 if (new_fp == 0)
2532 {
2533 errmsg ("Couldn't open script file %s", s);
2534 vec_free (s);
2535 return -99;
2536 }
2537 }
2538 else
2539 {
2540 errmsg ("Missing script name");
2541 return -99;
2542 }
2543
2544 clib_memcpy (&save_input, &vam->input, sizeof (save_input));
2545 clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
2546 save_ifp = vam->ifp;
2547 save_line_number = vam->input_line_number;
2548 save_current_file = (char *) vam->current_file;
2549
2550 vam->input_line_number = 0;
2551 vam->ifp = new_fp;
2552 vam->current_file = s;
2553 do_one_file (vam);
2554
Sirshak Dasb0861822018-05-29 21:13:21 -05002555 clib_memcpy (&vam->input, &save_input, sizeof (save_input));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002556 clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
2557 vam->ifp = save_ifp;
2558 vam->input_line_number = save_line_number;
2559 vam->current_file = (u8 *) save_current_file;
2560 vec_free (s);
2561
2562 return 0;
2563#else
2564 clib_warning ("use the exec command...");
2565 return -99;
2566#endif
2567}
2568
2569static int
2570echo (vat_main_t * vam)
2571{
2572 print (vam->ofp, "%v", vam->input->buffer);
2573 return 0;
2574}
2575
Florin Coras248210c2021-09-14 18:54:45 -07002576int exec (vat_main_t *vam) __attribute__ ((weak));
2577int
2578exec (vat_main_t *vam)
2579{
2580 return -1;
2581}
2582
Damjan Marion7cd468a2016-12-19 23:05:39 +01002583/* List of API message constructors, CLI names map to api_xxx */
2584#define foreach_vpe_api_msg \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002585_(get_first_msg_id, "client <name>") \
Florin Coras90a63982017-12-19 04:50:01 -08002586_(sock_init_shm, "size <nnn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002587/* List of command functions, CLI names map directly to functions */
2588#define foreach_cli_function \
2589_(comment, "usage: comment <ignore-rest-of-line>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002590_(dump_macro_table, "usage: dump_macro_table ") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002591_(dump_msg_api_table, "usage: dump_msg_api_table") \
Dave Barachb09f4d02019-07-15 16:00:03 -04002592_(elog_setup, "usage: elog_setup [nevents, default 128K]") \
2593_(elog_disable, "usage: elog_disable") \
2594_(elog_enable, "usage: elog_enable") \
2595_(elog_save, "usage: elog_save <filename>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002596_(get_msg_id, "usage: get_msg_id name_and_crc") \
2597_(echo, "usage: echo <message>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002598_(help, "usage: help") \
2599_(q, "usage: quit") \
2600_(quit, "usage: quit") \
2601_(search_node_table, "usage: search_node_table <name>...") \
2602_(set, "usage: set <variable-name> <value>") \
2603_(script, "usage: script <file-name>") \
Neale Ranns097fa662018-05-01 05:17:55 -07002604_(statseg, "usage: statseg") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002605_(unset, "usage: unset <variable-name>")
Dave Barach048a4e52018-06-01 18:52:25 -04002606
Damjan Marion7cd468a2016-12-19 23:05:39 +01002607#define _(N,n) \
2608 static void vl_api_##n##_t_handler_uni \
2609 (vl_api_##n##_t * mp) \
2610 { \
2611 vat_main_t * vam = &vat_main; \
2612 if (vam->json_output) { \
2613 vl_api_##n##_t_handler_json(mp); \
2614 } else { \
2615 vl_api_##n##_t_handler(mp); \
2616 } \
2617 }
2618foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05002619#if VPP_API_TEST_BUILTIN == 0
2620foreach_standalone_reply_msg;
2621#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002622#undef _
2623
2624void
2625vat_api_hookup (vat_main_t * vam)
2626{
Ole Troan3459ece2021-09-27 17:11:34 +02002627#define _(N, n) \
2628 vl_msg_api_set_handlers (VL_API_##N + 1, #n, vl_api_##n##_t_handler_uni, \
2629 vl_noop_handler, vl_api_##n##_t_endian, \
Filip Tehlar36217e32021-07-23 08:51:10 +00002630 vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1, \
2631 vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
2632 vl_api_##n##_t_fromjson);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002633 foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05002634#if VPP_API_TEST_BUILTIN == 0
2635 foreach_standalone_reply_msg;
2636#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002637#undef _
2638
2639#if (VPP_API_TEST_BUILTIN==0)
Ole Troan3459ece2021-09-27 17:11:34 +02002640 vl_msg_api_set_first_available_msg_id (VL_MSG_MEMCLNT_LAST + 1);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002641
2642 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2643
2644 vam->function_by_name = hash_create_string (0, sizeof (uword));
2645
2646 vam->help_by_name = hash_create_string (0, sizeof (uword));
Dave Barach45e4f362017-03-07 12:52:31 -05002647#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002648
2649 /* API messages we can send */
2650#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
2651 foreach_vpe_api_msg;
2652#undef _
2653
2654 /* Help strings */
2655#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2656 foreach_vpe_api_msg;
2657#undef _
Damjan Marion7cd468a2016-12-19 23:05:39 +01002658
2659 /* CLI functions */
2660#define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
2661 foreach_cli_function;
2662#undef _
2663
2664 /* Help strings */
2665#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2666 foreach_cli_function;
2667#undef _
2668}
2669
Dave Baracha1a093d2017-03-02 13:13:23 -05002670#if VPP_API_TEST_BUILTIN
2671static clib_error_t *
2672vat_api_hookup_shim (vlib_main_t * vm)
2673{
2674 vat_api_hookup (&vat_main);
2675 return 0;
2676}
2677
2678VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
2679#endif
2680
Damjan Marion7cd468a2016-12-19 23:05:39 +01002681/*
2682 * fd.io coding-style-patch-verification: ON
2683 *
2684 * Local Variables:
2685 * eval: (c-set-style "gnu")
2686 * End:
2687 */