blob: 48c1ccaa820f709735f8d6858df179bfcdb20831 [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>
Filip Tehlarf0e67d72021-07-23 22:03:05 +000060#include <vlibmemory/memclnt.api_tojson.h>
61#include <vlibmemory/memclnt.api_fromjson.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010062
63#define vl_endianfun /* define message structures */
Ole Troan3459ece2021-09-27 17:11:34 +020064#include <vlibmemory/memclnt.api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010065#undef vl_endianfun
66
Klement Sekera9b7e8ac2021-11-22 21:26:20 +010067#define vl_calcsizefun
68#include <vlibmemory/memclnt.api.h>
69#undef vl_calcsizefun
70
Damjan Marion7cd468a2016-12-19 23:05:39 +010071/* instantiate all the print functions we know about */
Damjan Marion7cd468a2016-12-19 23:05:39 +010072#define vl_printfun
Ole Troan3459ece2021-09-27 17:11:34 +020073#include <vlibmemory/memclnt.api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010074#undef vl_printfun
75
Dave Barach2d6b2d62017-01-25 16:32:08 -050076#define __plugin_msg_base 0
Dave Barachfe6bdfd2017-01-20 19:50:09 -050077#include <vlibapi/vat_helper_macros.h>
78
Dave Barachb09f4d02019-07-15 16:00:03 -040079void vl_api_set_elog_main (elog_main_t * m);
80int vl_api_set_elog_trace_api_messages (int enable);
81
Dave Barach59b25652017-09-10 15:04:27 -040082#if VPP_API_TEST_BUILTIN == 0
83#include <netdb.h>
84
85u32
86vl (void *p)
87{
88 return vec_len (p);
89}
90
91int
92vat_socket_connect (vat_main_t * vam)
93{
Florin Coras66a10032018-12-21 16:23:09 -080094 int rv;
Dave Barach69eeadc2020-04-14 09:52:26 -040095 api_main_t *am = vlibapi_get_main ();
Florin Coras90a63982017-12-19 04:50:01 -080096 vam->socket_client_main = &socket_client_main;
Florin Coras66a10032018-12-21 16:23:09 -080097 if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
98 "vpp_api_test",
99 0 /* default socket rx, tx buffer */ )))
100 return rv;
Dave Barach69eeadc2020-04-14 09:52:26 -0400101
Florin Coras66a10032018-12-21 16:23:09 -0800102 /* vpp expects the client index in network order */
103 vam->my_client_index = htonl (socket_client_main.client_index);
Dave Barach69eeadc2020-04-14 09:52:26 -0400104 am->my_client_index = vam->my_client_index;
Florin Coras66a10032018-12-21 16:23:09 -0800105 return 0;
Dave Barach59b25652017-09-10 15:04:27 -0400106}
107#else /* vpp built-in case, we don't do sockets... */
108int
109vat_socket_connect (vat_main_t * vam)
110{
111 return 0;
112}
113
Florin Coras90a63982017-12-19 04:50:01 -0800114int
115vl_socket_client_read (int wait)
Dave Barach59b25652017-09-10 15:04:27 -0400116{
Florin Coras90a63982017-12-19 04:50:01 -0800117 return -1;
Dave Barach59b25652017-09-10 15:04:27 -0400118};
Florin Coras90a63982017-12-19 04:50:01 -0800119
120int
121vl_socket_client_write ()
122{
123 return -1;
124};
125
126void *
127vl_socket_client_msg_alloc (int nbytes)
128{
129 return 0;
130}
Dave Barach59b25652017-09-10 15:04:27 -0400131#endif
132
133
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500134f64
135vat_time_now (vat_main_t * vam)
136{
137#if VPP_API_TEST_BUILTIN
138 return vlib_time_now (vam->vlib_main);
139#else
140 return clib_time_now (&vam->clib_time);
141#endif
142}
143
144void
145errmsg (char *fmt, ...)
146{
147 vat_main_t *vam = &vat_main;
148 va_list va;
149 u8 *s;
150
151 va_start (va, fmt);
152 s = va_format (0, fmt, &va);
153 va_end (va);
154
155 vec_add1 (s, 0);
156
157#if VPP_API_TEST_BUILTIN
158 vlib_cli_output (vam->vlib_main, (char *) s);
159#else
160 {
161 if (vam->ifp != stdin)
162 fformat (vam->ofp, "%s(%d): \n", vam->current_file,
163 vam->input_line_number);
Dave Barachb09f4d02019-07-15 16:00:03 -0400164 else
165 fformat (vam->ofp, "%s\n", (char *) s);
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500166 fflush (vam->ofp);
167 }
168#endif
169
170 vec_free (s);
171}
172
Dave Barach4a3f69c2017-02-22 12:44:56 -0500173#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +0100174
Damjan Marion7cd468a2016-12-19 23:05:39 +0100175/* Parse an IP4 address %d.%d.%d.%d. */
176uword
177unformat_ip4_address (unformat_input_t * input, va_list * args)
178{
179 u8 *result = va_arg (*args, u8 *);
180 unsigned a[4];
181
182 if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
183 return 0;
184
185 if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
186 return 0;
187
188 result[0] = a[0];
189 result[1] = a[1];
190 result[2] = a[2];
191 result[3] = a[3];
192
193 return 1;
194}
195
196uword
197unformat_ethernet_address (unformat_input_t * input, va_list * args)
198{
199 u8 *result = va_arg (*args, u8 *);
200 u32 i, a[6];
201
202 if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
203 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
204 return 0;
205
206 /* Check range. */
207 for (i = 0; i < 6; i++)
208 if (a[i] >= (1 << 8))
209 return 0;
210
211 for (i = 0; i < 6; i++)
212 result[i] = a[i];
213
214 return 1;
215}
216
217/* Returns ethernet type as an int in host byte order. */
218uword
219unformat_ethernet_type_host_byte_order (unformat_input_t * input,
220 va_list * args)
221{
222 u16 *result = va_arg (*args, u16 *);
223 int type;
224
225 /* Numeric type. */
226 if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
227 {
228 if (type >= (1 << 16))
229 return 0;
230 *result = type;
231 return 1;
232 }
233 return 0;
234}
235
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100236/* Parse an IP46 address. */
237uword
238unformat_ip46_address (unformat_input_t * input, va_list * args)
239{
240 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
241 ip46_type_t type = va_arg (*args, ip46_type_t);
242 if ((type != IP46_TYPE_IP6) &&
243 unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
244 {
245 ip46_address_mask_ip4 (ip46);
246 return 1;
247 }
248 else if ((type != IP46_TYPE_IP4) &&
249 unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
250 {
251 return 1;
252 }
253 return 0;
254}
255
Damjan Marion7cd468a2016-12-19 23:05:39 +0100256/* Parse an IP6 address. */
257uword
258unformat_ip6_address (unformat_input_t * input, va_list * args)
259{
260 ip6_address_t *result = va_arg (*args, ip6_address_t *);
261 u16 hex_quads[8];
262 uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
263 uword c, n_colon, double_colon_index;
264
265 n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
266 double_colon_index = ARRAY_LEN (hex_quads);
267 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
268 {
269 hex_digit = 16;
270 if (c >= '0' && c <= '9')
271 hex_digit = c - '0';
272 else if (c >= 'a' && c <= 'f')
273 hex_digit = c + 10 - 'a';
274 else if (c >= 'A' && c <= 'F')
275 hex_digit = c + 10 - 'A';
276 else if (c == ':' && n_colon < 2)
277 n_colon++;
278 else
279 {
280 unformat_put_input (input);
281 break;
282 }
283
284 /* Too many hex quads. */
285 if (n_hex_quads >= ARRAY_LEN (hex_quads))
286 return 0;
287
288 if (hex_digit < 16)
289 {
290 hex_quad = (hex_quad << 4) | hex_digit;
291
292 /* Hex quad must fit in 16 bits. */
293 if (n_hex_digits >= 4)
294 return 0;
295
296 n_colon = 0;
297 n_hex_digits++;
298 }
299
300 /* Save position of :: */
301 if (n_colon == 2)
302 {
303 /* More than one :: ? */
304 if (double_colon_index < ARRAY_LEN (hex_quads))
305 return 0;
306 double_colon_index = n_hex_quads;
307 }
308
309 if (n_colon > 0 && n_hex_digits > 0)
310 {
311 hex_quads[n_hex_quads++] = hex_quad;
312 hex_quad = 0;
313 n_hex_digits = 0;
314 }
315 }
316
317 if (n_hex_digits > 0)
318 hex_quads[n_hex_quads++] = hex_quad;
319
320 {
321 word i;
322
323 /* Expand :: to appropriate number of zero hex quads. */
324 if (double_colon_index < ARRAY_LEN (hex_quads))
325 {
326 word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
327
328 for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
329 hex_quads[n_zero + i] = hex_quads[i];
330
331 for (i = 0; i < n_zero; i++)
332 hex_quads[double_colon_index + i] = 0;
333
334 n_hex_quads = ARRAY_LEN (hex_quads);
335 }
336
337 /* Too few hex quads given. */
338 if (n_hex_quads < ARRAY_LEN (hex_quads))
339 return 0;
340
341 for (i = 0; i < ARRAY_LEN (hex_quads); i++)
342 result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
343
344 return 1;
345 }
346}
347
348uword
349unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
350{
351 u32 *r = va_arg (*args, u32 *);
352
353 if (0);
354#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
355 foreach_ipsec_policy_action
356#undef _
357 else
358 return 0;
359 return 1;
360}
361
Damjan Marion7cd468a2016-12-19 23:05:39 +0100362u8 *
363format_ipsec_crypto_alg (u8 * s, va_list * args)
364{
365 u32 i = va_arg (*args, u32);
366 u8 *t = 0;
367
368 switch (i)
369 {
370#define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
371 foreach_ipsec_crypto_alg
372#undef _
373 default:
374 return format (s, "unknown");
375 }
376 return format (s, "%s", t);
377}
378
Damjan Marion7cd468a2016-12-19 23:05:39 +0100379u8 *
380format_ipsec_integ_alg (u8 * s, va_list * args)
381{
382 u32 i = va_arg (*args, u32);
383 u8 *t = 0;
384
385 switch (i)
386 {
387#define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
388 foreach_ipsec_integ_alg
389#undef _
390 default:
391 return format (s, "unknown");
392 }
393 return format (s, "%s", t);
394}
395
Dave Barach4a3f69c2017-02-22 12:44:56 -0500396#else /* VPP_API_TEST_BUILTIN == 1 */
397static uword
398api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
399{
Benoît Ganne49ee6842019-04-30 11:50:46 +0200400 vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500401 vnet_main_t *vnm = vnet_get_main ();
402 u32 *result = va_arg (*args, u32 *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500403
eyal bariaf86a482018-04-17 11:20:27 +0300404 return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500405}
eyal bariaf86a482018-04-17 11:20:27 +0300406
Damjan Marion7cd468a2016-12-19 23:05:39 +0100407#endif /* VPP_API_TEST_BUILTIN */
408
Benoît Ganne49ee6842019-04-30 11:50:46 +0200409#if (VPP_API_TEST_BUILTIN==0)
410
Neale Ranns32e1c012016-11-22 17:07:28 +0000411static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
412static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
413static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
414static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
415
416uword
417unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
418{
419 mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
420 mfib_itf_attribute_t attr;
421
422 old = *iflags;
423 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
424 {
425 if (unformat (input, mfib_itf_flag_long_names[attr]))
426 *iflags |= (1 << attr);
427 }
428 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
429 {
430 if (unformat (input, mfib_itf_flag_names[attr]))
431 *iflags |= (1 << attr);
432 }
433
434 return (old == *iflags ? 0 : 1);
435}
436
437uword
438unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
439{
440 mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
441 mfib_entry_attribute_t attr;
442
443 old = *eflags;
444 FOR_EACH_MFIB_ATTRIBUTE (attr)
445 {
446 if (unformat (input, mfib_flag_long_names[attr]))
447 *eflags |= (1 << attr);
448 }
449 FOR_EACH_MFIB_ATTRIBUTE (attr)
450 {
451 if (unformat (input, mfib_flag_names[attr]))
452 *eflags |= (1 << attr);
453 }
454
455 return (old == *eflags ? 0 : 1);
456}
457
Damjan Marion7cd468a2016-12-19 23:05:39 +0100458u8 *
459format_ip4_address (u8 * s, va_list * args)
460{
461 u8 *a = va_arg (*args, u8 *);
462 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
463}
464
465u8 *
466format_ip6_address (u8 * s, va_list * args)
467{
468 ip6_address_t *a = va_arg (*args, ip6_address_t *);
469 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
470
471 i_max_n_zero = ARRAY_LEN (a->as_u16);
472 max_n_zeros = 0;
473 i_first_zero = i_max_n_zero;
474 n_zeros = 0;
475 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
476 {
477 u32 is_zero = a->as_u16[i] == 0;
478 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
479 {
480 i_first_zero = i;
481 n_zeros = 0;
482 }
483 n_zeros += is_zero;
484 if ((!is_zero && n_zeros > max_n_zeros)
485 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
486 {
487 i_max_n_zero = i_first_zero;
488 max_n_zeros = n_zeros;
489 i_first_zero = ARRAY_LEN (a->as_u16);
490 n_zeros = 0;
491 }
492 }
493
494 last_double_colon = 0;
495 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
496 {
497 if (i == i_max_n_zero && max_n_zeros > 1)
498 {
499 s = format (s, "::");
500 i += max_n_zeros - 1;
501 last_double_colon = 1;
502 }
503 else
504 {
505 s = format (s, "%s%x",
506 (last_double_colon || i == 0) ? "" : ":",
507 clib_net_to_host_u16 (a->as_u16[i]));
508 last_double_colon = 0;
509 }
510 }
511
512 return s;
513}
514
515/* Format an IP46 address. */
516u8 *
517format_ip46_address (u8 * s, va_list * args)
518{
519 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
520 ip46_type_t type = va_arg (*args, ip46_type_t);
521 int is_ip4 = 1;
522
523 switch (type)
524 {
525 case IP46_TYPE_ANY:
526 is_ip4 = ip46_address_is_ip4 (ip46);
527 break;
528 case IP46_TYPE_IP4:
529 is_ip4 = 1;
530 break;
531 case IP46_TYPE_IP6:
532 is_ip4 = 0;
533 break;
534 }
535
536 return is_ip4 ?
537 format (s, "%U", format_ip4_address, &ip46->ip4) :
538 format (s, "%U", format_ip6_address, &ip46->ip6);
539}
540
541u8 *
542format_ethernet_address (u8 * s, va_list * args)
543{
544 u8 *a = va_arg (*args, u8 *);
545
546 return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
547 a[0], a[1], a[2], a[3], a[4], a[5]);
548}
549#endif
550
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100551void
552ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
553{
554 if (is_ip4)
555 dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
556 else
557 clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
558 sizeof (ip6_address_t));
559}
560
Neale Ranns097fa662018-05-01 05:17:55 -0700561
Damjan Marion7cd468a2016-12-19 23:05:39 +0100562static void vl_api_get_first_msg_id_reply_t_handler
563 (vl_api_get_first_msg_id_reply_t * mp)
564{
565 vat_main_t *vam = &vat_main;
566 i32 retval = ntohl (mp->retval);
567
568 if (vam->async_mode)
569 {
570 vam->async_errors += (retval < 0);
571 }
572 else
573 {
574 vam->retval = retval;
575 vam->result_ready = 1;
576 }
577 if (retval >= 0)
578 {
579 errmsg ("first message id %d", ntohs (mp->first_msg_id));
580 }
581}
582
583static void vl_api_get_first_msg_id_reply_t_handler_json
584 (vl_api_get_first_msg_id_reply_t * mp)
585{
586 vat_main_t *vam = &vat_main;
587 vat_json_node_t node;
588
589 vat_json_init_object (&node);
590 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
591 vat_json_object_add_uint (&node, "first_msg_id",
592 (uint) ntohs (mp->first_msg_id));
593
594 vat_json_print (vam->ofp, &node);
595 vat_json_free (&node);
596
597 vam->retval = ntohl (mp->retval);
598 vam->result_ready = 1;
599}
600
Damjan Marion7cd468a2016-12-19 23:05:39 +0100601/* Format hex dump. */
602u8 *
603format_hex_bytes (u8 * s, va_list * va)
604{
605 u8 *bytes = va_arg (*va, u8 *);
606 int n_bytes = va_arg (*va, int);
607 uword i;
608
609 /* Print short or long form depending on byte count. */
610 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200611 u32 indent = format_get_indent (s);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100612
613 if (n_bytes == 0)
614 return s;
615
616 for (i = 0; i < n_bytes; i++)
617 {
618 if (!short_form && (i % 32) == 0)
619 s = format (s, "%08x: ", i);
620 s = format (s, "%02x", bytes[i]);
621 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
622 s = format (s, "\n%U", format_white_space, indent);
623 }
624
625 return s;
626}
627
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000628static void
629vl_api_control_ping_reply_t_handler (vl_api_control_ping_reply_t *mp)
630{
631 vat_main_t *vam = &vat_main;
632 i32 retval = ntohl (mp->retval);
633 if (vam->async_mode)
634 {
635 vam->async_errors += (retval < 0);
636 }
637 else
638 {
639 vam->retval = retval;
640 vam->result_ready = 1;
641 }
642 if (vam->socket_client_main)
643 vam->socket_client_main->control_pings_outstanding--;
644}
645
646static void
647vl_api_control_ping_reply_t_handler_json (vl_api_control_ping_reply_t *mp)
648{
649 vat_main_t *vam = &vat_main;
650 i32 retval = ntohl (mp->retval);
651
652 if (VAT_JSON_NONE != vam->json_tree.type)
653 {
654 vat_json_print (vam->ofp, &vam->json_tree);
655 vat_json_free (&vam->json_tree);
656 vam->json_tree.type = VAT_JSON_NONE;
657 }
658 else
659 {
660 /* just print [] */
661 vat_json_init_array (&vam->json_tree);
662 vat_json_print (vam->ofp, &vam->json_tree);
663 vam->json_tree.type = VAT_JSON_NONE;
664 }
665
666 vam->retval = retval;
667 vam->result_ready = 1;
668}
669
Damjan Marion7cd468a2016-12-19 23:05:39 +0100670/*
671 * Generate boilerplate reply handlers, which
672 * dig the return value out of the xxx_reply_t API message,
673 * stick it into vam->retval, and set vam->result_ready
674 *
675 * Could also do this by pointing N message decode slots at
676 * a single function, but that could break in subtle ways.
677 */
678
Filip Tehlar0046e972021-06-26 22:12:08 +0000679#define foreach_standard_reply_retval_handler
Damjan Marion7cd468a2016-12-19 23:05:39 +0100680
681#define _(n) \
682 static void vl_api_##n##_t_handler \
683 (vl_api_##n##_t * mp) \
684 { \
685 vat_main_t * vam = &vat_main; \
686 i32 retval = ntohl(mp->retval); \
687 if (vam->async_mode) { \
688 vam->async_errors += (retval < 0); \
689 } else { \
690 vam->retval = retval; \
691 vam->result_ready = 1; \
692 } \
693 }
694foreach_standard_reply_retval_handler;
695#undef _
696
697#define _(n) \
698 static void vl_api_##n##_t_handler_json \
699 (vl_api_##n##_t * mp) \
700 { \
701 vat_main_t * vam = &vat_main; \
702 vat_json_node_t node; \
703 vat_json_init_object(&node); \
704 vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
705 vat_json_print(vam->ofp, &node); \
706 vam->retval = ntohl(mp->retval); \
707 vam->result_ready = 1; \
708 }
709foreach_standard_reply_retval_handler;
710#undef _
711
712/*
713 * Table of message reply handlers, must include boilerplate handlers
714 * we just generated
715 */
716
Filip Tehlar0577ff12021-06-27 00:18:57 +0000717#define foreach_vpe_api_reply_msg \
718 _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000719 _ (CONTROL_PING_REPLY, control_ping_reply)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100720
Dave Baracha1a093d2017-03-02 13:13:23 -0500721#define foreach_standalone_reply_msg \
Dave Baracha1a093d2017-03-02 13:13:23 -0500722
Damjan Marion7cd468a2016-12-19 23:05:39 +0100723typedef struct
724{
725 u8 *name;
726 u32 value;
727} name_sort_t;
728
Damjan Marion7cd468a2016-12-19 23:05:39 +0100729#define STR_VTR_OP_CASE(op) \
730 case L2_VTR_ ## op: \
731 return "" # op;
732
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000733static const char *
734str_vtr_op (u32 vtr_op)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100735{
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000736 switch (vtr_op)
737 {
738 STR_VTR_OP_CASE (DISABLED);
739 STR_VTR_OP_CASE (PUSH_1);
740 STR_VTR_OP_CASE (PUSH_2);
741 STR_VTR_OP_CASE (POP_1);
742 STR_VTR_OP_CASE (POP_2);
743 STR_VTR_OP_CASE (TRANSLATE_1_1);
744 STR_VTR_OP_CASE (TRANSLATE_1_2);
745 STR_VTR_OP_CASE (TRANSLATE_2_1);
746 STR_VTR_OP_CASE (TRANSLATE_2_2);
747 }
748
749 return "UNKNOWN";
Damjan Marion7cd468a2016-12-19 23:05:39 +0100750}
751
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100752uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000753unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100754{
jialv01082ebeb2019-09-10 00:23:55 +0800755 vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100756 u32 x[4];
757
758 if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
759 return 0;
760
761 addr->domain = x[0];
762 addr->bus = x[1];
763 addr->slot = x[2];
764 addr->function = x[3];
765
766 return 1;
767}
768
Neale Ranns097fa662018-05-01 05:17:55 -0700769uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000770unformat_fib_path (unformat_input_t *input, va_list *args)
Neale Ranns097fa662018-05-01 05:17:55 -0700771{
772 vat_main_t *vam = va_arg (*args, vat_main_t *);
773 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
774 u32 weight, preference;
775 mpls_label_t out_label;
776
777 clib_memset (path, 0, sizeof (*path));
778 path->weight = 1;
779 path->sw_if_index = ~0;
780 path->rpf_id = ~0;
781 path->n_labels = 0;
782
783 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
784 {
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000785 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
786 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
787 &path->sw_if_index))
Neale Ranns097fa662018-05-01 05:17:55 -0700788 {
789 path->proto = FIB_API_PATH_NH_PROTO_IP4;
790 }
791 else if (unformat (input, "%U %U",
792 unformat_vl_api_ip6_address,
793 &path->nh.address.ip6,
794 api_unformat_sw_if_index, vam, &path->sw_if_index))
795 {
796 path->proto = FIB_API_PATH_NH_PROTO_IP6;
797 }
798 else if (unformat (input, "weight %u", &weight))
799 {
800 path->weight = weight;
801 }
802 else if (unformat (input, "preference %u", &preference))
803 {
804 path->preference = preference;
805 }
806 else if (unformat (input, "%U next-hop-table %d",
807 unformat_vl_api_ip4_address,
808 &path->nh.address.ip4, &path->table_id))
809 {
810 path->proto = FIB_API_PATH_NH_PROTO_IP4;
811 }
812 else if (unformat (input, "%U next-hop-table %d",
813 unformat_vl_api_ip6_address,
814 &path->nh.address.ip6, &path->table_id))
815 {
816 path->proto = FIB_API_PATH_NH_PROTO_IP6;
817 }
818 else if (unformat (input, "%U",
819 unformat_vl_api_ip4_address, &path->nh.address.ip4))
820 {
821 /*
822 * the recursive next-hops are by default in the default table
823 */
824 path->table_id = 0;
825 path->sw_if_index = ~0;
826 path->proto = FIB_API_PATH_NH_PROTO_IP4;
827 }
828 else if (unformat (input, "%U",
829 unformat_vl_api_ip6_address, &path->nh.address.ip6))
830 {
831 /*
832 * the recursive next-hops are by default in the default table
833 */
834 path->table_id = 0;
835 path->sw_if_index = ~0;
836 path->proto = FIB_API_PATH_NH_PROTO_IP6;
837 }
838 else if (unformat (input, "resolve-via-host"))
839 {
840 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
841 }
842 else if (unformat (input, "resolve-via-attached"))
843 {
844 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
845 }
846 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
847 {
848 path->type = FIB_API_PATH_TYPE_LOCAL;
849 path->sw_if_index = ~0;
850 path->proto = FIB_API_PATH_NH_PROTO_IP4;
851 }
852 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
853 {
854 path->type = FIB_API_PATH_TYPE_LOCAL;
855 path->sw_if_index = ~0;
856 path->proto = FIB_API_PATH_NH_PROTO_IP6;
857 }
858 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
859 ;
860 else if (unformat (input, "via-label %d", &path->nh.via_label))
861 {
862 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
863 path->sw_if_index = ~0;
864 }
865 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
866 {
867 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
868 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
869 }
870 else if (unformat (input, "local"))
871 {
872 path->type = FIB_API_PATH_TYPE_LOCAL;
873 }
874 else if (unformat (input, "out-labels"))
875 {
876 while (unformat (input, "%d", &out_label))
877 {
878 path->label_stack[path->n_labels].label = out_label;
879 path->label_stack[path->n_labels].is_uniform = 0;
880 path->label_stack[path->n_labels].ttl = 64;
881 path->n_labels++;
882 }
883 }
884 else if (unformat (input, "via"))
885 {
886 /* new path, back up and return */
887 unformat_put_input (input);
888 unformat_put_input (input);
889 unformat_put_input (input);
890 unformat_put_input (input);
891 break;
892 }
893 else
894 {
895 return (0);
896 }
897 }
898
899 path->proto = ntohl (path->proto);
900 path->type = ntohl (path->type);
901 path->flags = ntohl (path->flags);
902 path->table_id = ntohl (path->table_id);
903 path->sw_if_index = ntohl (path->sw_if_index);
904
905 return (1);
906}
907
Damjan Marion7cd468a2016-12-19 23:05:39 +0100908#define foreach_create_subif_bit \
909_(no_tags) \
910_(one_tag) \
911_(two_tags) \
912_(dot1ad) \
913_(exact_match) \
914_(default_sub) \
915_(outer_vlan_id_any) \
916_(inner_vlan_id_any)
917
Jakub Grajciar053204a2019-03-18 13:17:53 +0100918#define foreach_create_subif_flag \
919_(0, "no_tags") \
920_(1, "one_tag") \
921_(2, "two_tags") \
922_(3, "dot1ad") \
923_(4, "exact_match") \
924_(5, "default_sub") \
925_(6, "outer_vlan_id_any") \
926_(7, "inner_vlan_id_any")
927
Pablo Camarillofb380952016-12-07 18:34:18 +0100928
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000929#define foreach_tcp_proto_field \
930 _ (src_port) \
931 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100932
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000933#define foreach_udp_proto_field \
934 _ (src_port) \
935 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100936
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000937#define foreach_ip4_proto_field \
938 _ (src_address) \
939 _ (dst_address) \
940 _ (tos) \
941 _ (length) \
942 _ (fragment_id) \
943 _ (ttl) \
944 _ (protocol) \
945 _ (checksum)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100946
Dave Barach4a3f69c2017-02-22 12:44:56 -0500947typedef struct
948{
949 u16 src_port, dst_port;
950} tcpudp_header_t;
951
952#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +0100953uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000954unformat_tcp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100955{
956 u8 **maskp = va_arg (*args, u8 **);
957 u8 *mask = 0;
958 u8 found_something = 0;
959 tcp_header_t *tcp;
960
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000961#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100962 foreach_tcp_proto_field;
963#undef _
964
965 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
966 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000967 if (0)
968 ;
969#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100970 foreach_tcp_proto_field
971#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000972 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100973 }
974
975#define _(a) found_something += a;
976 foreach_tcp_proto_field;
977#undef _
978
979 if (found_something == 0)
980 return 0;
981
982 vec_validate (mask, sizeof (*tcp) - 1);
983
984 tcp = (tcp_header_t *) mask;
985
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000986#define _(a) \
987 if (a) \
988 clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100989 foreach_tcp_proto_field;
990#undef _
991
992 *maskp = mask;
993 return 1;
994}
995
996uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000997unformat_udp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100998{
999 u8 **maskp = va_arg (*args, u8 **);
1000 u8 *mask = 0;
1001 u8 found_something = 0;
1002 udp_header_t *udp;
1003
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001004#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001005 foreach_udp_proto_field;
1006#undef _
1007
1008 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1009 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001010 if (0)
1011 ;
1012#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001013 foreach_udp_proto_field
1014#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001015 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001016 }
1017
1018#define _(a) found_something += a;
1019 foreach_udp_proto_field;
1020#undef _
1021
1022 if (found_something == 0)
1023 return 0;
1024
1025 vec_validate (mask, sizeof (*udp) - 1);
1026
1027 udp = (udp_header_t *) mask;
1028
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001029#define _(a) \
1030 if (a) \
1031 clib_memset (&udp->a, 0xff, sizeof (udp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001032 foreach_udp_proto_field;
1033#undef _
1034
1035 *maskp = mask;
1036 return 1;
1037}
1038
Damjan Marion7cd468a2016-12-19 23:05:39 +01001039uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001040unformat_l4_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001041{
1042 u8 **maskp = va_arg (*args, u8 **);
1043 u16 src_port = 0, dst_port = 0;
1044 tcpudp_header_t *tcpudp;
1045
1046 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1047 {
1048 if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
1049 return 1;
1050 else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
1051 return 1;
1052 else if (unformat (input, "src_port"))
1053 src_port = 0xFFFF;
1054 else if (unformat (input, "dst_port"))
1055 dst_port = 0xFFFF;
1056 else
1057 return 0;
1058 }
1059
1060 if (!src_port && !dst_port)
1061 return 0;
1062
1063 u8 *mask = 0;
1064 vec_validate (mask, sizeof (tcpudp_header_t) - 1);
1065
1066 tcpudp = (tcpudp_header_t *) mask;
1067 tcpudp->src_port = src_port;
1068 tcpudp->dst_port = dst_port;
1069
1070 *maskp = mask;
1071
1072 return 1;
1073}
1074
1075uword
1076unformat_ip4_mask (unformat_input_t * input, va_list * args)
1077{
1078 u8 **maskp = va_arg (*args, u8 **);
1079 u8 *mask = 0;
1080 u8 found_something = 0;
1081 ip4_header_t *ip;
1082
1083#define _(a) u8 a=0;
1084 foreach_ip4_proto_field;
1085#undef _
1086 u8 version = 0;
1087 u8 hdr_length = 0;
1088
1089
1090 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1091 {
1092 if (unformat (input, "version"))
1093 version = 1;
1094 else if (unformat (input, "hdr_length"))
1095 hdr_length = 1;
1096 else if (unformat (input, "src"))
1097 src_address = 1;
1098 else if (unformat (input, "dst"))
1099 dst_address = 1;
1100 else if (unformat (input, "proto"))
1101 protocol = 1;
1102
1103#define _(a) else if (unformat (input, #a)) a=1;
1104 foreach_ip4_proto_field
1105#undef _
1106 else
1107 break;
1108 }
1109
1110#define _(a) found_something += a;
1111 foreach_ip4_proto_field;
1112#undef _
1113
1114 if (found_something == 0)
1115 return 0;
1116
1117 vec_validate (mask, sizeof (*ip) - 1);
1118
1119 ip = (ip4_header_t *) mask;
1120
Dave Barachb7b92992018-10-17 10:38:51 -04001121#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001122 foreach_ip4_proto_field;
1123#undef _
1124
1125 ip->ip_version_and_header_length = 0;
1126
1127 if (version)
1128 ip->ip_version_and_header_length |= 0xF0;
1129
1130 if (hdr_length)
1131 ip->ip_version_and_header_length |= 0x0F;
1132
1133 *maskp = mask;
1134 return 1;
1135}
1136
1137#define foreach_ip6_proto_field \
1138_(src_address) \
1139_(dst_address) \
1140_(payload_length) \
1141_(hop_limit) \
1142_(protocol)
1143
1144uword
1145unformat_ip6_mask (unformat_input_t * input, va_list * args)
1146{
1147 u8 **maskp = va_arg (*args, u8 **);
1148 u8 *mask = 0;
1149 u8 found_something = 0;
1150 ip6_header_t *ip;
1151 u32 ip_version_traffic_class_and_flow_label;
1152
1153#define _(a) u8 a=0;
1154 foreach_ip6_proto_field;
1155#undef _
1156 u8 version = 0;
1157 u8 traffic_class = 0;
1158 u8 flow_label = 0;
1159
1160 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1161 {
1162 if (unformat (input, "version"))
1163 version = 1;
1164 else if (unformat (input, "traffic-class"))
1165 traffic_class = 1;
1166 else if (unformat (input, "flow-label"))
1167 flow_label = 1;
1168 else if (unformat (input, "src"))
1169 src_address = 1;
1170 else if (unformat (input, "dst"))
1171 dst_address = 1;
1172 else if (unformat (input, "proto"))
1173 protocol = 1;
1174
1175#define _(a) else if (unformat (input, #a)) a=1;
1176 foreach_ip6_proto_field
1177#undef _
1178 else
1179 break;
1180 }
1181
1182#define _(a) found_something += a;
1183 foreach_ip6_proto_field;
1184#undef _
1185
1186 if (found_something == 0)
1187 return 0;
1188
1189 vec_validate (mask, sizeof (*ip) - 1);
1190
1191 ip = (ip6_header_t *) mask;
1192
Dave Barachb7b92992018-10-17 10:38:51 -04001193#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001194 foreach_ip6_proto_field;
1195#undef _
1196
1197 ip_version_traffic_class_and_flow_label = 0;
1198
1199 if (version)
1200 ip_version_traffic_class_and_flow_label |= 0xF0000000;
1201
1202 if (traffic_class)
1203 ip_version_traffic_class_and_flow_label |= 0x0FF00000;
1204
1205 if (flow_label)
1206 ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
1207
1208 ip->ip_version_traffic_class_and_flow_label =
1209 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1210
1211 *maskp = mask;
1212 return 1;
1213}
1214
1215uword
1216unformat_l3_mask (unformat_input_t * input, va_list * args)
1217{
1218 u8 **maskp = va_arg (*args, u8 **);
1219
1220 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1221 {
1222 if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
1223 return 1;
1224 else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
1225 return 1;
1226 else
1227 break;
1228 }
1229 return 0;
1230}
1231
1232uword
1233unformat_l2_mask (unformat_input_t * input, va_list * args)
1234{
1235 u8 **maskp = va_arg (*args, u8 **);
1236 u8 *mask = 0;
1237 u8 src = 0;
1238 u8 dst = 0;
1239 u8 proto = 0;
1240 u8 tag1 = 0;
1241 u8 tag2 = 0;
1242 u8 ignore_tag1 = 0;
1243 u8 ignore_tag2 = 0;
1244 u8 cos1 = 0;
1245 u8 cos2 = 0;
1246 u8 dot1q = 0;
1247 u8 dot1ad = 0;
1248 int len = 14;
1249
1250 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1251 {
1252 if (unformat (input, "src"))
1253 src = 1;
1254 else if (unformat (input, "dst"))
1255 dst = 1;
1256 else if (unformat (input, "proto"))
1257 proto = 1;
1258 else if (unformat (input, "tag1"))
1259 tag1 = 1;
1260 else if (unformat (input, "tag2"))
1261 tag2 = 1;
1262 else if (unformat (input, "ignore-tag1"))
1263 ignore_tag1 = 1;
1264 else if (unformat (input, "ignore-tag2"))
1265 ignore_tag2 = 1;
1266 else if (unformat (input, "cos1"))
1267 cos1 = 1;
1268 else if (unformat (input, "cos2"))
1269 cos2 = 1;
1270 else if (unformat (input, "dot1q"))
1271 dot1q = 1;
1272 else if (unformat (input, "dot1ad"))
1273 dot1ad = 1;
1274 else
1275 break;
1276 }
1277 if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
1278 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1279 return 0;
1280
1281 if (tag1 || ignore_tag1 || cos1 || dot1q)
1282 len = 18;
1283 if (tag2 || ignore_tag2 || cos2 || dot1ad)
1284 len = 22;
1285
1286 vec_validate (mask, len - 1);
1287
1288 if (dst)
Dave Barachb7b92992018-10-17 10:38:51 -04001289 clib_memset (mask, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001290
1291 if (src)
Dave Barachb7b92992018-10-17 10:38:51 -04001292 clib_memset (mask + 6, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001293
1294 if (tag2 || dot1ad)
1295 {
1296 /* inner vlan tag */
1297 if (tag2)
1298 {
1299 mask[19] = 0xff;
1300 mask[18] = 0x0f;
1301 }
1302 if (cos2)
1303 mask[18] |= 0xe0;
1304 if (proto)
1305 mask[21] = mask[20] = 0xff;
1306 if (tag1)
1307 {
1308 mask[15] = 0xff;
1309 mask[14] = 0x0f;
1310 }
1311 if (cos1)
1312 mask[14] |= 0xe0;
1313 *maskp = mask;
1314 return 1;
1315 }
1316 if (tag1 | dot1q)
1317 {
1318 if (tag1)
1319 {
1320 mask[15] = 0xff;
1321 mask[14] = 0x0f;
1322 }
1323 if (cos1)
1324 mask[14] |= 0xe0;
1325 if (proto)
1326 mask[16] = mask[17] = 0xff;
1327
1328 *maskp = mask;
1329 return 1;
1330 }
1331 if (cos2)
1332 mask[18] |= 0xe0;
1333 if (cos1)
1334 mask[14] |= 0xe0;
1335 if (proto)
1336 mask[12] = mask[13] = 0xff;
1337
1338 *maskp = mask;
1339 return 1;
1340}
1341
1342uword
1343unformat_classify_mask (unformat_input_t * input, va_list * args)
1344{
1345 u8 **maskp = va_arg (*args, u8 **);
1346 u32 *skipp = va_arg (*args, u32 *);
1347 u32 *matchp = va_arg (*args, u32 *);
1348 u32 match;
1349 u8 *mask = 0;
1350 u8 *l2 = 0;
1351 u8 *l3 = 0;
1352 u8 *l4 = 0;
1353 int i;
1354
1355 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1356 {
1357 if (unformat (input, "hex %U", unformat_hex_string, &mask))
1358 ;
1359 else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
1360 ;
1361 else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
1362 ;
1363 else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
1364 ;
1365 else
1366 break;
1367 }
1368
1369 if (l4 && !l3)
1370 {
1371 vec_free (mask);
1372 vec_free (l2);
1373 vec_free (l4);
1374 return 0;
1375 }
1376
1377 if (mask || l2 || l3 || l4)
1378 {
1379 if (l2 || l3 || l4)
1380 {
1381 /* "With a free Ethernet header in every package" */
1382 if (l2 == 0)
1383 vec_validate (l2, 13);
1384 mask = l2;
1385 if (vec_len (l3))
1386 {
1387 vec_append (mask, l3);
1388 vec_free (l3);
1389 }
1390 if (vec_len (l4))
1391 {
1392 vec_append (mask, l4);
1393 vec_free (l4);
1394 }
1395 }
1396
1397 /* Scan forward looking for the first significant mask octet */
1398 for (i = 0; i < vec_len (mask); i++)
1399 if (mask[i])
1400 break;
1401
1402 /* compute (skip, match) params */
1403 *skipp = i / sizeof (u32x4);
1404 vec_delete (mask, *skipp * sizeof (u32x4), 0);
1405
1406 /* Pad mask to an even multiple of the vector size */
1407 while (vec_len (mask) % sizeof (u32x4))
1408 vec_add1 (mask, 0);
1409
1410 match = vec_len (mask) / sizeof (u32x4);
1411
1412 for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
1413 {
1414 u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
1415 if (*tmp || *(tmp + 1))
1416 break;
1417 match--;
1418 }
1419 if (match == 0)
1420 clib_warning ("BUG: match 0");
1421
Damjan Marion8bea5892022-04-04 22:40:45 +02001422 vec_set_len (mask, match * sizeof (u32x4));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001423
1424 *matchp = match;
1425 *maskp = mask;
1426
1427 return 1;
1428 }
1429
1430 return 0;
1431}
Dave Barach4a3f69c2017-02-22 12:44:56 -05001432#endif /* VPP_API_TEST_BUILTIN */
Damjan Marion7cd468a2016-12-19 23:05:39 +01001433
1434#define foreach_l2_next \
1435_(drop, DROP) \
1436_(ethernet, ETHERNET_INPUT) \
1437_(ip4, IP4_INPUT) \
1438_(ip6, IP6_INPUT)
1439
1440uword
1441unformat_l2_next_index (unformat_input_t * input, va_list * args)
1442{
1443 u32 *miss_next_indexp = va_arg (*args, u32 *);
1444 u32 next_index = 0;
1445 u32 tmp;
1446
1447#define _(n,N) \
1448 if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
1449 foreach_l2_next;
1450#undef _
1451
1452 if (unformat (input, "%d", &tmp))
1453 {
1454 next_index = tmp;
1455 goto out;
1456 }
1457
1458 return 0;
1459
1460out:
1461 *miss_next_indexp = next_index;
1462 return 1;
1463}
1464
1465#define foreach_ip_next \
1466_(drop, DROP) \
1467_(local, LOCAL) \
1468_(rewrite, REWRITE)
1469
1470uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001471api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001472{
1473 u32 *miss_next_indexp = va_arg (*args, u32 *);
1474 u32 next_index = 0;
1475 u32 tmp;
1476
1477#define _(n,N) \
1478 if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
1479 foreach_ip_next;
1480#undef _
1481
1482 if (unformat (input, "%d", &tmp))
1483 {
1484 next_index = tmp;
1485 goto out;
1486 }
1487
1488 return 0;
1489
1490out:
1491 *miss_next_indexp = next_index;
1492 return 1;
1493}
1494
1495#define foreach_acl_next \
1496_(deny, DENY)
1497
1498uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001499api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001500{
1501 u32 *miss_next_indexp = va_arg (*args, u32 *);
1502 u32 next_index = 0;
1503 u32 tmp;
1504
1505#define _(n,N) \
1506 if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
1507 foreach_acl_next;
1508#undef _
1509
1510 if (unformat (input, "permit"))
1511 {
1512 next_index = ~0;
1513 goto out;
1514 }
1515 else if (unformat (input, "%d", &tmp))
1516 {
1517 next_index = tmp;
1518 goto out;
1519 }
1520
1521 return 0;
1522
1523out:
1524 *miss_next_indexp = next_index;
1525 return 1;
1526}
1527
1528uword
1529unformat_policer_precolor (unformat_input_t * input, va_list * args)
1530{
1531 u32 *r = va_arg (*args, u32 *);
1532
1533 if (unformat (input, "conform-color"))
1534 *r = POLICE_CONFORM;
1535 else if (unformat (input, "exceed-color"))
1536 *r = POLICE_EXCEED;
1537 else
1538 return 0;
1539
1540 return 1;
1541}
1542
Dave Barach4a3f69c2017-02-22 12:44:56 -05001543#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01001544uword
1545unformat_l4_match (unformat_input_t * input, va_list * args)
1546{
1547 u8 **matchp = va_arg (*args, u8 **);
1548
1549 u8 *proto_header = 0;
1550 int src_port = 0;
1551 int dst_port = 0;
1552
1553 tcpudp_header_t h;
1554
1555 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1556 {
1557 if (unformat (input, "src_port %d", &src_port))
1558 ;
1559 else if (unformat (input, "dst_port %d", &dst_port))
1560 ;
1561 else
1562 return 0;
1563 }
1564
1565 h.src_port = clib_host_to_net_u16 (src_port);
1566 h.dst_port = clib_host_to_net_u16 (dst_port);
1567 vec_validate (proto_header, sizeof (h) - 1);
1568 memcpy (proto_header, &h, sizeof (h));
1569
1570 *matchp = proto_header;
1571
1572 return 1;
1573}
1574
1575uword
1576unformat_ip4_match (unformat_input_t * input, va_list * args)
1577{
1578 u8 **matchp = va_arg (*args, u8 **);
1579 u8 *match = 0;
1580 ip4_header_t *ip;
1581 int version = 0;
1582 u32 version_val;
1583 int hdr_length = 0;
1584 u32 hdr_length_val;
1585 int src = 0, dst = 0;
1586 ip4_address_t src_val, dst_val;
1587 int proto = 0;
1588 u32 proto_val;
1589 int tos = 0;
1590 u32 tos_val;
1591 int length = 0;
1592 u32 length_val;
1593 int fragment_id = 0;
1594 u32 fragment_id_val;
1595 int ttl = 0;
1596 int ttl_val;
1597 int checksum = 0;
1598 u32 checksum_val;
1599
1600 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1601 {
1602 if (unformat (input, "version %d", &version_val))
1603 version = 1;
1604 else if (unformat (input, "hdr_length %d", &hdr_length_val))
1605 hdr_length = 1;
1606 else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
1607 src = 1;
1608 else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
1609 dst = 1;
1610 else if (unformat (input, "proto %d", &proto_val))
1611 proto = 1;
1612 else if (unformat (input, "tos %d", &tos_val))
1613 tos = 1;
1614 else if (unformat (input, "length %d", &length_val))
1615 length = 1;
1616 else if (unformat (input, "fragment_id %d", &fragment_id_val))
1617 fragment_id = 1;
1618 else if (unformat (input, "ttl %d", &ttl_val))
1619 ttl = 1;
1620 else if (unformat (input, "checksum %d", &checksum_val))
1621 checksum = 1;
1622 else
1623 break;
1624 }
1625
1626 if (version + hdr_length + src + dst + proto + tos + length + fragment_id
1627 + ttl + checksum == 0)
1628 return 0;
1629
1630 /*
1631 * Aligned because we use the real comparison functions
1632 */
1633 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1634
1635 ip = (ip4_header_t *) match;
1636
1637 /* These are realistically matched in practice */
1638 if (src)
1639 ip->src_address.as_u32 = src_val.as_u32;
1640
1641 if (dst)
1642 ip->dst_address.as_u32 = dst_val.as_u32;
1643
1644 if (proto)
1645 ip->protocol = proto_val;
1646
1647
1648 /* These are not, but they're included for completeness */
1649 if (version)
1650 ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
1651
1652 if (hdr_length)
1653 ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
1654
1655 if (tos)
1656 ip->tos = tos_val;
1657
1658 if (length)
1659 ip->length = clib_host_to_net_u16 (length_val);
1660
1661 if (ttl)
1662 ip->ttl = ttl_val;
1663
1664 if (checksum)
1665 ip->checksum = clib_host_to_net_u16 (checksum_val);
1666
1667 *matchp = match;
1668 return 1;
1669}
1670
1671uword
1672unformat_ip6_match (unformat_input_t * input, va_list * args)
1673{
1674 u8 **matchp = va_arg (*args, u8 **);
1675 u8 *match = 0;
1676 ip6_header_t *ip;
1677 int version = 0;
1678 u32 version_val;
1679 u8 traffic_class = 0;
1680 u32 traffic_class_val = 0;
1681 u8 flow_label = 0;
1682 u8 flow_label_val;
1683 int src = 0, dst = 0;
1684 ip6_address_t src_val, dst_val;
1685 int proto = 0;
1686 u32 proto_val;
1687 int payload_length = 0;
1688 u32 payload_length_val;
1689 int hop_limit = 0;
1690 int hop_limit_val;
1691 u32 ip_version_traffic_class_and_flow_label;
1692
1693 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1694 {
1695 if (unformat (input, "version %d", &version_val))
1696 version = 1;
1697 else if (unformat (input, "traffic_class %d", &traffic_class_val))
1698 traffic_class = 1;
1699 else if (unformat (input, "flow_label %d", &flow_label_val))
1700 flow_label = 1;
1701 else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
1702 src = 1;
1703 else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
1704 dst = 1;
1705 else if (unformat (input, "proto %d", &proto_val))
1706 proto = 1;
1707 else if (unformat (input, "payload_length %d", &payload_length_val))
1708 payload_length = 1;
1709 else if (unformat (input, "hop_limit %d", &hop_limit_val))
1710 hop_limit = 1;
1711 else
1712 break;
1713 }
1714
1715 if (version + traffic_class + flow_label + src + dst + proto +
1716 payload_length + hop_limit == 0)
1717 return 0;
1718
1719 /*
1720 * Aligned because we use the real comparison functions
1721 */
1722 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1723
1724 ip = (ip6_header_t *) match;
1725
1726 if (src)
1727 clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
1728
1729 if (dst)
1730 clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
1731
1732 if (proto)
1733 ip->protocol = proto_val;
1734
1735 ip_version_traffic_class_and_flow_label = 0;
1736
1737 if (version)
1738 ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
1739
1740 if (traffic_class)
1741 ip_version_traffic_class_and_flow_label |=
1742 (traffic_class_val & 0xFF) << 20;
1743
1744 if (flow_label)
1745 ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
1746
1747 ip->ip_version_traffic_class_and_flow_label =
1748 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1749
1750 if (payload_length)
1751 ip->payload_length = clib_host_to_net_u16 (payload_length_val);
1752
1753 if (hop_limit)
1754 ip->hop_limit = hop_limit_val;
1755
1756 *matchp = match;
1757 return 1;
1758}
1759
1760uword
1761unformat_l3_match (unformat_input_t * input, va_list * args)
1762{
1763 u8 **matchp = va_arg (*args, u8 **);
1764
1765 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1766 {
1767 if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
1768 return 1;
1769 else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
1770 return 1;
1771 else
1772 break;
1773 }
1774 return 0;
1775}
1776
1777uword
1778unformat_vlan_tag (unformat_input_t * input, va_list * args)
1779{
1780 u8 *tagp = va_arg (*args, u8 *);
1781 u32 tag;
1782
1783 if (unformat (input, "%d", &tag))
1784 {
1785 tagp[0] = (tag >> 8) & 0x0F;
1786 tagp[1] = tag & 0xFF;
1787 return 1;
1788 }
1789
1790 return 0;
1791}
1792
1793uword
1794unformat_l2_match (unformat_input_t * input, va_list * args)
1795{
1796 u8 **matchp = va_arg (*args, u8 **);
1797 u8 *match = 0;
1798 u8 src = 0;
1799 u8 src_val[6];
1800 u8 dst = 0;
1801 u8 dst_val[6];
1802 u8 proto = 0;
1803 u16 proto_val;
1804 u8 tag1 = 0;
1805 u8 tag1_val[2];
1806 u8 tag2 = 0;
1807 u8 tag2_val[2];
1808 int len = 14;
1809 u8 ignore_tag1 = 0;
1810 u8 ignore_tag2 = 0;
1811 u8 cos1 = 0;
1812 u8 cos2 = 0;
1813 u32 cos1_val = 0;
1814 u32 cos2_val = 0;
1815
1816 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1817 {
1818 if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
1819 src = 1;
1820 else
1821 if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
1822 dst = 1;
1823 else if (unformat (input, "proto %U",
1824 unformat_ethernet_type_host_byte_order, &proto_val))
1825 proto = 1;
1826 else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
1827 tag1 = 1;
1828 else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
1829 tag2 = 1;
1830 else if (unformat (input, "ignore-tag1"))
1831 ignore_tag1 = 1;
1832 else if (unformat (input, "ignore-tag2"))
1833 ignore_tag2 = 1;
1834 else if (unformat (input, "cos1 %d", &cos1_val))
1835 cos1 = 1;
1836 else if (unformat (input, "cos2 %d", &cos2_val))
1837 cos2 = 1;
1838 else
1839 break;
1840 }
1841 if ((src + dst + proto + tag1 + tag2 +
1842 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1843 return 0;
1844
1845 if (tag1 || ignore_tag1 || cos1)
1846 len = 18;
1847 if (tag2 || ignore_tag2 || cos2)
1848 len = 22;
1849
1850 vec_validate_aligned (match, len - 1, sizeof (u32x4));
1851
1852 if (dst)
1853 clib_memcpy (match, dst_val, 6);
1854
1855 if (src)
1856 clib_memcpy (match + 6, src_val, 6);
1857
1858 if (tag2)
1859 {
1860 /* inner vlan tag */
1861 match[19] = tag2_val[1];
1862 match[18] = tag2_val[0];
1863 if (cos2)
1864 match[18] |= (cos2_val & 0x7) << 5;
1865 if (proto)
1866 {
1867 match[21] = proto_val & 0xff;
1868 match[20] = proto_val >> 8;
1869 }
1870 if (tag1)
1871 {
1872 match[15] = tag1_val[1];
1873 match[14] = tag1_val[0];
1874 }
1875 if (cos1)
1876 match[14] |= (cos1_val & 0x7) << 5;
1877 *matchp = match;
1878 return 1;
1879 }
1880 if (tag1)
1881 {
1882 match[15] = tag1_val[1];
1883 match[14] = tag1_val[0];
1884 if (proto)
1885 {
1886 match[17] = proto_val & 0xff;
1887 match[16] = proto_val >> 8;
1888 }
1889 if (cos1)
1890 match[14] |= (cos1_val & 0x7) << 5;
1891
1892 *matchp = match;
1893 return 1;
1894 }
1895 if (cos2)
1896 match[18] |= (cos2_val & 0x7) << 5;
1897 if (cos1)
1898 match[14] |= (cos1_val & 0x7) << 5;
1899 if (proto)
1900 {
1901 match[13] = proto_val & 0xff;
1902 match[12] = proto_val >> 8;
1903 }
1904
1905 *matchp = match;
1906 return 1;
1907}
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -07001908
1909uword
1910unformat_qos_source (unformat_input_t * input, va_list * args)
1911{
1912 int *qs = va_arg (*args, int *);
1913
1914 if (unformat (input, "ip"))
1915 *qs = QOS_SOURCE_IP;
1916 else if (unformat (input, "mpls"))
1917 *qs = QOS_SOURCE_MPLS;
1918 else if (unformat (input, "ext"))
1919 *qs = QOS_SOURCE_EXT;
1920 else if (unformat (input, "vlan"))
1921 *qs = QOS_SOURCE_VLAN;
1922 else
1923 return 0;
1924
1925 return 1;
1926}
Dave Barach4a3f69c2017-02-22 12:44:56 -05001927#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01001928
1929uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001930api_unformat_classify_match (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001931{
1932 u8 **matchp = va_arg (*args, u8 **);
1933 u32 skip_n_vectors = va_arg (*args, u32);
1934 u32 match_n_vectors = va_arg (*args, u32);
1935
1936 u8 *match = 0;
1937 u8 *l2 = 0;
1938 u8 *l3 = 0;
1939 u8 *l4 = 0;
1940
1941 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1942 {
1943 if (unformat (input, "hex %U", unformat_hex_string, &match))
1944 ;
1945 else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
1946 ;
1947 else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
1948 ;
1949 else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
1950 ;
1951 else
1952 break;
1953 }
1954
1955 if (l4 && !l3)
1956 {
1957 vec_free (match);
1958 vec_free (l2);
1959 vec_free (l4);
1960 return 0;
1961 }
1962
1963 if (match || l2 || l3 || l4)
1964 {
1965 if (l2 || l3 || l4)
1966 {
1967 /* "Win a free Ethernet header in every packet" */
1968 if (l2 == 0)
1969 vec_validate_aligned (l2, 13, sizeof (u32x4));
1970 match = l2;
1971 if (vec_len (l3))
1972 {
1973 vec_append_aligned (match, l3, sizeof (u32x4));
1974 vec_free (l3);
1975 }
1976 if (vec_len (l4))
1977 {
1978 vec_append_aligned (match, l4, sizeof (u32x4));
1979 vec_free (l4);
1980 }
1981 }
1982
1983 /* Make sure the vector is big enough even if key is all 0's */
1984 vec_validate_aligned
1985 (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
1986 sizeof (u32x4));
1987
1988 /* Set size, include skipped vectors */
Damjan Marion8bea5892022-04-04 22:40:45 +02001989 vec_set_len (match, (match_n_vectors + skip_n_vectors) * sizeof (u32x4));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001990
1991 *matchp = match;
1992
1993 return 1;
1994 }
1995
1996 return 0;
1997}
1998
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001999#define foreach_vtr_op \
2000 _ ("disable", L2_VTR_DISABLED) \
2001 _ ("push-1", L2_VTR_PUSH_1) \
2002 _ ("push-2", L2_VTR_PUSH_2) \
2003 _ ("pop-1", L2_VTR_POP_1) \
2004 _ ("pop-2", L2_VTR_POP_2) \
2005 _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \
2006 _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \
2007 _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \
2008 _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002009
2010static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002011api_get_first_msg_id (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002012{
2013 vl_api_get_first_msg_id_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002014 unformat_input_t *i = vam->input;
2015 u8 *name;
2016 u8 name_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002017 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002018
2019 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2020 {
2021 if (unformat (i, "client %s", &name))
2022 name_set = 1;
2023 else
2024 break;
2025 }
2026
2027 if (name_set == 0)
2028 {
2029 errmsg ("missing client name");
2030 return -99;
2031 }
2032 vec_add1 (name, 0);
2033
2034 if (vec_len (name) > 63)
2035 {
2036 errmsg ("client name too long");
2037 return -99;
2038 }
2039
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002040 M (GET_FIRST_MSG_ID, mp);
Ole Troan7adaa222019-08-27 15:05:27 +02002041 clib_memcpy (mp->name, name, vec_len (name));
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002042 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002043 W (ret);
2044 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002045}
2046
Damjan Marion7cd468a2016-12-19 23:05:39 +01002047#define foreach_pbb_vtr_op \
2048_("disable", L2_VTR_DISABLED) \
2049_("pop", L2_VTR_POP_2) \
2050_("push", L2_VTR_PUSH_2)
2051
Florin Corascea194d2017-10-02 00:18:51 -07002052static int
Florin Coras90a63982017-12-19 04:50:01 -08002053api_sock_init_shm (vat_main_t * vam)
2054{
2055#if VPP_API_TEST_BUILTIN == 0
2056 unformat_input_t *i = vam->input;
2057 vl_api_shm_elem_config_t *config = 0;
2058 u64 size = 64 << 20;
2059 int rv;
2060
2061 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2062 {
2063 if (unformat (i, "size %U", unformat_memory_size, &size))
2064 ;
2065 else
2066 break;
2067 }
2068
Dave Barach78958722018-05-10 16:44:27 -04002069 /*
2070 * Canned custom ring allocator config.
2071 * Should probably parse all of this
2072 */
2073 vec_validate (config, 6);
Florin Coras90a63982017-12-19 04:50:01 -08002074 config[0].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002075 config[0].size = 256;
Dave Barach78958722018-05-10 16:44:27 -04002076 config[0].count = 32;
2077
2078 config[1].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002079 config[1].size = 1024;
Dave Barach78958722018-05-10 16:44:27 -04002080 config[1].count = 16;
2081
2082 config[2].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002083 config[2].size = 4096;
Dave Barach78958722018-05-10 16:44:27 -04002084 config[2].count = 2;
2085
2086 config[3].type = VL_API_CLIENT_RING;
2087 config[3].size = 256;
2088 config[3].count = 32;
2089
2090 config[4].type = VL_API_CLIENT_RING;
2091 config[4].size = 1024;
2092 config[4].count = 16;
2093
2094 config[5].type = VL_API_CLIENT_RING;
2095 config[5].size = 4096;
2096 config[5].count = 2;
2097
2098 config[6].type = VL_API_QUEUE;
2099 config[6].count = 128;
2100 config[6].size = sizeof (uword);
2101
Tomasz Kulasek97dcf5b2019-01-31 18:26:32 +01002102 rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
Florin Coras90a63982017-12-19 04:50:01 -08002103 if (!rv)
2104 vam->client_index_invalid = 1;
2105 return rv;
2106#else
2107 return -99;
2108#endif
2109}
2110
Florin Coras6c36f532017-11-03 18:32:34 -07002111static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002112q_or_quit (vat_main_t * vam)
2113{
Dave Barachdef19da2017-02-22 17:29:20 -05002114#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01002115 longjmp (vam->jump_buf, 1);
Dave Barachdef19da2017-02-22 17:29:20 -05002116#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002117 return 0; /* not so much */
2118}
2119
2120static int
2121q (vat_main_t * vam)
2122{
2123 return q_or_quit (vam);
2124}
2125
2126static int
2127quit (vat_main_t * vam)
2128{
2129 return q_or_quit (vam);
2130}
2131
2132static int
2133comment (vat_main_t * vam)
2134{
2135 return 0;
2136}
2137
2138static int
Dave Barachb09f4d02019-07-15 16:00:03 -04002139elog_save (vat_main_t * vam)
2140{
2141#if VPP_API_TEST_BUILTIN == 0
2142 elog_main_t *em = &vam->elog_main;
2143 unformat_input_t *i = vam->input;
2144 char *file, *chroot_file;
2145 clib_error_t *error;
2146
2147 if (!unformat (i, "%s", &file))
2148 {
2149 errmsg ("expected file name, got `%U'", format_unformat_error, i);
2150 return 0;
2151 }
2152
2153 /* It's fairly hard to get "../oopsie" through unformat; just in case */
Matus Fabian7f163b62024-07-22 09:56:01 +02002154 if (strstr (file, "..") || strchr (file, '/'))
Dave Barachb09f4d02019-07-15 16:00:03 -04002155 {
2156 errmsg ("illegal characters in filename '%s'", file);
2157 return 0;
2158 }
2159
2160 chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
2161
2162 vec_free (file);
2163
2164 errmsg ("Saving %wd of %wd events to %s",
2165 elog_n_events_in_buffer (em),
2166 elog_buffer_capacity (em), chroot_file);
2167
2168 error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
2169 vec_free (chroot_file);
2170
2171 if (error)
2172 clib_error_report (error);
2173#else
2174 errmsg ("Use the vpp event loger...");
2175#endif
2176
2177 return 0;
2178}
2179
2180static int
2181elog_setup (vat_main_t * vam)
2182{
2183#if VPP_API_TEST_BUILTIN == 0
2184 elog_main_t *em = &vam->elog_main;
2185 unformat_input_t *i = vam->input;
2186 u32 nevents = 128 << 10;
2187
2188 (void) unformat (i, "nevents %d", &nevents);
2189
2190 elog_init (em, nevents);
2191 vl_api_set_elog_main (em);
2192 vl_api_set_elog_trace_api_messages (1);
2193 errmsg ("Event logger initialized with %u events", nevents);
2194#else
2195 errmsg ("Use the vpp event loger...");
2196#endif
2197 return 0;
2198}
2199
2200static int
2201elog_enable (vat_main_t * vam)
2202{
2203#if VPP_API_TEST_BUILTIN == 0
2204 elog_main_t *em = &vam->elog_main;
2205
2206 elog_enable_disable (em, 1 /* enable */ );
2207 vl_api_set_elog_trace_api_messages (1);
2208 errmsg ("Event logger enabled...");
2209#else
2210 errmsg ("Use the vpp event loger...");
2211#endif
2212 return 0;
2213}
2214
2215static int
2216elog_disable (vat_main_t * vam)
2217{
2218#if VPP_API_TEST_BUILTIN == 0
2219 elog_main_t *em = &vam->elog_main;
2220
2221 elog_enable_disable (em, 0 /* enable */ );
2222 vl_api_set_elog_trace_api_messages (1);
2223 errmsg ("Event logger disabled...");
2224#else
2225 errmsg ("Use the vpp event loger...");
2226#endif
2227 return 0;
2228}
2229
2230static int
Dave Barach048a4e52018-06-01 18:52:25 -04002231statseg (vat_main_t * vam)
2232{
2233 ssvm_private_t *ssvmp = &vam->stat_segment;
2234 ssvm_shared_header_t *shared_header = ssvmp->sh;
2235 vlib_counter_t **counters;
2236 u64 thread0_index1_packets;
2237 u64 thread0_index1_bytes;
2238 f64 vector_rate, input_rate;
2239 uword *p;
2240
2241 uword *counter_vector_by_name;
2242 if (vam->stat_segment_lockp == 0)
2243 {
2244 errmsg ("Stat segment not mapped...");
2245 return -99;
2246 }
2247
2248 /* look up "/if/rx for sw_if_index 1 as a test */
2249
2250 clib_spinlock_lock (vam->stat_segment_lockp);
2251
2252 counter_vector_by_name = (uword *) shared_header->opaque[1];
2253
2254 p = hash_get_mem (counter_vector_by_name, "/if/rx");
2255 if (p == 0)
2256 {
2257 clib_spinlock_unlock (vam->stat_segment_lockp);
2258 errmsg ("/if/tx not found?");
2259 return -99;
2260 }
2261
2262 /* Fish per-thread vector of combined counters from shared memory */
2263 counters = (vlib_counter_t **) p[0];
2264
2265 if (vec_len (counters[0]) < 2)
2266 {
2267 clib_spinlock_unlock (vam->stat_segment_lockp);
2268 errmsg ("/if/tx vector length %d", vec_len (counters[0]));
2269 return -99;
2270 }
2271
2272 /* Read thread 0 sw_if_index 1 counter */
2273 thread0_index1_packets = counters[0][1].packets;
2274 thread0_index1_bytes = counters[0][1].bytes;
2275
2276 p = hash_get_mem (counter_vector_by_name, "vector_rate");
2277 if (p == 0)
2278 {
2279 clib_spinlock_unlock (vam->stat_segment_lockp);
2280 errmsg ("vector_rate not found?");
2281 return -99;
2282 }
2283
2284 vector_rate = *(f64 *) (p[0]);
2285 p = hash_get_mem (counter_vector_by_name, "input_rate");
2286 if (p == 0)
2287 {
2288 clib_spinlock_unlock (vam->stat_segment_lockp);
2289 errmsg ("input_rate not found?");
2290 return -99;
2291 }
2292 input_rate = *(f64 *) (p[0]);
2293
2294 clib_spinlock_unlock (vam->stat_segment_lockp);
2295
2296 print (vam->ofp, "vector_rate %.2f input_rate %.2f",
2297 vector_rate, input_rate);
2298 print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
2299 thread0_index1_packets, thread0_index1_bytes);
2300
2301 return 0;
2302}
2303
2304static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002305cmd_cmp (void *a1, void *a2)
2306{
2307 u8 **c1 = a1;
2308 u8 **c2 = a2;
2309
2310 return strcmp ((char *) (c1[0]), (char *) (c2[0]));
2311}
2312
2313static int
2314help (vat_main_t * vam)
2315{
2316 u8 **cmds = 0;
2317 u8 *name = 0;
2318 hash_pair_t *p;
2319 unformat_input_t *i = vam->input;
2320 int j;
2321
2322 if (unformat (i, "%s", &name))
2323 {
2324 uword *hs;
2325
2326 vec_add1 (name, 0);
2327
2328 hs = hash_get_mem (vam->help_by_name, name);
2329 if (hs)
2330 print (vam->ofp, "usage: %s %s", name, hs[0]);
2331 else
2332 print (vam->ofp, "No such msg / command '%s'", name);
2333 vec_free (name);
2334 return 0;
2335 }
2336
2337 print (vam->ofp, "Help is available for the following:");
2338
Damjan Marion7cd468a2016-12-19 23:05:39 +01002339 hash_foreach_pair (p, vam->function_by_name,
2340 ({
2341 vec_add1 (cmds, (u8 *)(p->key));
2342 }));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002343
2344 vec_sort_with_function (cmds, cmd_cmp);
2345
2346 for (j = 0; j < vec_len (cmds); j++)
2347 print (vam->ofp, "%s", cmds[j]);
2348
2349 vec_free (cmds);
2350 return 0;
2351}
2352
2353static int
2354set (vat_main_t * vam)
2355{
2356 u8 *name = 0, *value = 0;
2357 unformat_input_t *i = vam->input;
2358
2359 if (unformat (i, "%s", &name))
2360 {
2361 /* The input buffer is a vector, not a string. */
2362 value = vec_dup (i->buffer);
2363 vec_delete (value, i->index, 0);
2364 /* Almost certainly has a trailing newline */
2365 if (value[vec_len (value) - 1] == '\n')
2366 value[vec_len (value) - 1] = 0;
2367 /* Make sure it's a proper string, one way or the other */
2368 vec_add1 (value, 0);
2369 (void) clib_macro_set_value (&vam->macro_main,
2370 (char *) name, (char *) value);
2371 }
2372 else
2373 errmsg ("usage: set <name> <value>");
2374
2375 vec_free (name);
2376 vec_free (value);
2377 return 0;
2378}
2379
2380static int
2381unset (vat_main_t * vam)
2382{
2383 u8 *name = 0;
2384
2385 if (unformat (vam->input, "%s", &name))
2386 if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
2387 errmsg ("unset: %s wasn't set", name);
2388 vec_free (name);
2389 return 0;
2390}
2391
2392typedef struct
2393{
2394 u8 *name;
2395 u8 *value;
2396} macro_sort_t;
2397
2398
2399static int
2400macro_sort_cmp (void *a1, void *a2)
2401{
2402 macro_sort_t *s1 = a1;
2403 macro_sort_t *s2 = a2;
2404
2405 return strcmp ((char *) (s1->name), (char *) (s2->name));
2406}
2407
2408static int
2409dump_macro_table (vat_main_t * vam)
2410{
2411 macro_sort_t *sort_me = 0, *sm;
2412 int i;
2413 hash_pair_t *p;
2414
Filip Tehlarf0e67d72021-07-23 22:03:05 +00002415 hash_foreach_pair (p, vam->macro_main.the_value_table_hash, ({
2416 vec_add2 (sort_me, sm, 1);
2417 sm->name = (u8 *) (p->key);
2418 sm->value = (u8 *) (p->value[0]);
2419 }));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002420
2421 vec_sort_with_function (sort_me, macro_sort_cmp);
2422
2423 if (vec_len (sort_me))
2424 print (vam->ofp, "%-15s%s", "Name", "Value");
2425 else
2426 print (vam->ofp, "The macro table is empty...");
2427
2428 for (i = 0; i < vec_len (sort_me); i++)
2429 print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
2430 return 0;
2431}
2432
2433static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002434value_sort_cmp (void *a1, void *a2)
2435{
2436 name_sort_t *n1 = a1;
2437 name_sort_t *n2 = a2;
2438
2439 if (n1->value < n2->value)
2440 return -1;
2441 if (n1->value > n2->value)
2442 return 1;
2443 return 0;
2444}
2445
2446
2447static int
2448dump_msg_api_table (vat_main_t * vam)
2449{
Dave Barach39d69112019-11-27 11:42:13 -05002450 api_main_t *am = vlibapi_get_main ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01002451 name_sort_t *nses = 0, *ns;
2452 hash_pair_t *hp;
2453 int i;
2454
Damjan Marion7cd468a2016-12-19 23:05:39 +01002455 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
2456 ({
2457 vec_add2 (nses, ns, 1);
2458 ns->name = (u8 *)(hp->key);
2459 ns->value = (u32) hp->value[0];
2460 }));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002461
2462 vec_sort_with_function (nses, value_sort_cmp);
2463
2464 for (i = 0; i < vec_len (nses); i++)
2465 print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
2466 vec_free (nses);
2467 return 0;
2468}
2469
2470static int
2471get_msg_id (vat_main_t * vam)
2472{
2473 u8 *name_and_crc;
2474 u32 message_index;
2475
2476 if (unformat (vam->input, "%s", &name_and_crc))
2477 {
Florin Corase86a8ed2018-01-05 03:20:25 -08002478 message_index = vl_msg_api_get_msg_index (name_and_crc);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002479 if (message_index == ~0)
2480 {
2481 print (vam->ofp, " '%s' not found", name_and_crc);
2482 return 0;
2483 }
2484 print (vam->ofp, " '%s' has message index %d",
2485 name_and_crc, message_index);
2486 return 0;
2487 }
2488 errmsg ("name_and_crc required...");
2489 return 0;
2490}
2491
2492static int
2493search_node_table (vat_main_t * vam)
2494{
2495 unformat_input_t *line_input = vam->input;
2496 u8 *node_to_find;
2497 int j;
2498 vlib_node_t *node, *next_node;
2499 uword *p;
2500
2501 if (vam->graph_node_index_by_name == 0)
2502 {
2503 print (vam->ofp, "Node table empty, issue get_node_graph...");
2504 return 0;
2505 }
2506
2507 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2508 {
2509 if (unformat (line_input, "%s", &node_to_find))
2510 {
2511 vec_add1 (node_to_find, 0);
2512 p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
2513 if (p == 0)
2514 {
2515 print (vam->ofp, "%s not found...", node_to_find);
2516 goto out;
2517 }
Dave Barach1ddbc012018-06-13 09:26:05 -04002518 node = vam->graph_nodes[0][p[0]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01002519 print (vam->ofp, "[%d] %s", p[0], node->name);
2520 for (j = 0; j < vec_len (node->next_nodes); j++)
2521 {
2522 if (node->next_nodes[j] != ~0)
2523 {
Dave Barach1ddbc012018-06-13 09:26:05 -04002524 next_node = vam->graph_nodes[0][node->next_nodes[j]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01002525 print (vam->ofp, " [%d] %s", j, next_node->name);
2526 }
2527 }
2528 }
2529
2530 else
2531 {
2532 clib_warning ("parse error '%U'", format_unformat_error,
2533 line_input);
2534 return -99;
2535 }
2536
2537 out:
2538 vec_free (node_to_find);
2539
2540 }
2541
2542 return 0;
2543}
2544
2545
2546static int
2547script (vat_main_t * vam)
2548{
2549#if (VPP_API_TEST_BUILTIN==0)
2550 u8 *s = 0;
2551 char *save_current_file;
2552 unformat_input_t save_input;
2553 jmp_buf save_jump_buf;
2554 u32 save_line_number;
2555
2556 FILE *new_fp, *save_ifp;
2557
2558 if (unformat (vam->input, "%s", &s))
2559 {
2560 new_fp = fopen ((char *) s, "r");
2561 if (new_fp == 0)
2562 {
2563 errmsg ("Couldn't open script file %s", s);
2564 vec_free (s);
2565 return -99;
2566 }
2567 }
2568 else
2569 {
2570 errmsg ("Missing script name");
2571 return -99;
2572 }
2573
2574 clib_memcpy (&save_input, &vam->input, sizeof (save_input));
2575 clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
2576 save_ifp = vam->ifp;
2577 save_line_number = vam->input_line_number;
2578 save_current_file = (char *) vam->current_file;
2579
2580 vam->input_line_number = 0;
2581 vam->ifp = new_fp;
2582 vam->current_file = s;
2583 do_one_file (vam);
2584
Sirshak Dasb0861822018-05-29 21:13:21 -05002585 clib_memcpy (&vam->input, &save_input, sizeof (save_input));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002586 clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
2587 vam->ifp = save_ifp;
2588 vam->input_line_number = save_line_number;
2589 vam->current_file = (u8 *) save_current_file;
2590 vec_free (s);
2591
2592 return 0;
2593#else
2594 clib_warning ("use the exec command...");
2595 return -99;
2596#endif
2597}
2598
2599static int
2600echo (vat_main_t * vam)
2601{
2602 print (vam->ofp, "%v", vam->input->buffer);
2603 return 0;
2604}
2605
Florin Coras248210c2021-09-14 18:54:45 -07002606int exec (vat_main_t *vam) __attribute__ ((weak));
2607int
2608exec (vat_main_t *vam)
2609{
2610 return -1;
2611}
2612
Filip Tehlarf0e67d72021-07-23 22:03:05 +00002613static int
2614name_sort_cmp (void *a1, void *a2)
2615{
2616 name_sort_t *n1 = a1;
2617 name_sort_t *n2 = a2;
2618
2619 return strcmp ((char *) n1->name, (char *) n2->name);
2620}
2621
2622static int
2623dump_interface_table (vat_main_t *vam)
2624{
2625 hash_pair_t *p;
2626 name_sort_t *nses = 0, *ns;
2627
2628 if (vam->json_output)
2629 {
2630 clib_warning (
2631 "JSON output supported only for VPE API calls and dump_stats_table");
2632 return -99;
2633 }
2634
2635 hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
2636 vec_add2 (nses, ns, 1);
2637 ns->name = (u8 *) (p->key);
2638 ns->value = (u32) p->value[0];
2639 }));
2640
2641 vec_sort_with_function (nses, name_sort_cmp);
2642
2643 print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
2644 vec_foreach (ns, nses)
2645 {
2646 print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2647 }
2648 vec_free (nses);
2649 return 0;
2650}
2651
2652static int
2653dump_sub_interface_table (vat_main_t *vam)
2654{
2655 const sw_interface_subif_t *sub = NULL;
2656
2657 if (vam->json_output)
2658 {
2659 clib_warning (
2660 "JSON output supported only for VPE API calls and dump_stats_table");
2661 return -99;
2662 }
2663
2664 print (vam->ofp, "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
2665 "Interface", "sw_if_index", "sub id", "dot1ad", "tags", "outer id",
2666 "inner id", "exact", "default", "outer any", "inner any");
2667
2668 vec_foreach (sub, vam->sw_if_subif_table)
2669 {
2670 print (vam->ofp, "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
2671 sub->interface_name, sub->sw_if_index, sub->sub_id,
2672 sub->sub_dot1ad ? "dot1ad" : "dot1q", sub->sub_number_of_tags,
2673 sub->sub_outer_vlan_id, sub->sub_inner_vlan_id,
2674 sub->sub_exact_match, sub->sub_default,
2675 sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2676 if (sub->vtr_op != L2_VTR_DISABLED)
2677 {
2678 print (vam->ofp,
2679 " vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2680 "tag1: %d tag2: %d ]",
2681 str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q, sub->vtr_tag1,
2682 sub->vtr_tag2);
2683 }
2684 }
2685
2686 return 0;
2687}
2688
Damjan Marion7cd468a2016-12-19 23:05:39 +01002689/* List of API message constructors, CLI names map to api_xxx */
2690#define foreach_vpe_api_msg \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002691_(get_first_msg_id, "client <name>") \
Florin Coras90a63982017-12-19 04:50:01 -08002692_(sock_init_shm, "size <nnn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002693/* List of command functions, CLI names map directly to functions */
Filip Tehlarf0e67d72021-07-23 22:03:05 +00002694#define foreach_cli_function \
2695 _ (comment, "usage: comment <ignore-rest-of-line>") \
2696 _ (dump_interface_table, "usage: dump_interface_table") \
2697 _ (dump_sub_interface_table, "usage: dump_sub_interface_table") \
2698 _ (dump_macro_table, "usage: dump_macro_table ") \
2699 _ (dump_msg_api_table, "usage: dump_msg_api_table") \
2700 _ (elog_setup, "usage: elog_setup [nevents, default 128K]") \
2701 _ (elog_disable, "usage: elog_disable") \
2702 _ (elog_enable, "usage: elog_enable") \
2703 _ (elog_save, "usage: elog_save <filename>") \
2704 _ (get_msg_id, "usage: get_msg_id name_and_crc") \
2705 _ (echo, "usage: echo <message>") \
2706 _ (help, "usage: help") \
2707 _ (q, "usage: quit") \
2708 _ (quit, "usage: quit") \
2709 _ (search_node_table, "usage: search_node_table <name>...") \
2710 _ (set, "usage: set <variable-name> <value>") \
2711 _ (script, "usage: script <file-name>") \
2712 _ (statseg, "usage: statseg") \
2713 _ (unset, "usage: unset <variable-name>")
Dave Barach048a4e52018-06-01 18:52:25 -04002714
Damjan Marion7cd468a2016-12-19 23:05:39 +01002715#define _(N,n) \
2716 static void vl_api_##n##_t_handler_uni \
2717 (vl_api_##n##_t * mp) \
2718 { \
2719 vat_main_t * vam = &vat_main; \
2720 if (vam->json_output) { \
2721 vl_api_##n##_t_handler_json(mp); \
2722 } else { \
2723 vl_api_##n##_t_handler(mp); \
2724 } \
2725 }
2726foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05002727#if VPP_API_TEST_BUILTIN == 0
2728foreach_standalone_reply_msg;
2729#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002730#undef _
2731
2732void
2733vat_api_hookup (vat_main_t * vam)
2734{
Ole Troan3459ece2021-09-27 17:11:34 +02002735#define _(N, n) \
Damjan Mariona2eb5072022-05-20 20:06:01 +02002736 vl_msg_api_config (&(vl_msg_api_msg_config_t){ \
2737 .id = VL_API_##N + 1, \
2738 .name = #n, \
2739 .handler = vl_api_##n##_t_handler_uni, \
2740 .endian = vl_api_##n##_t_endian, \
2741 .format_fn = vl_api_##n##_t_format, \
2742 .size = sizeof (vl_api_##n##_t), \
2743 .traced = 1, \
2744 .tojson = vl_api_##n##_t_tojson, \
2745 .fromjson = vl_api_##n##_t_fromjson, \
2746 .calc_size = vl_api_##n##_t_calc_size, \
2747 });
Damjan Marion7cd468a2016-12-19 23:05:39 +01002748 foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05002749#if VPP_API_TEST_BUILTIN == 0
2750 foreach_standalone_reply_msg;
2751#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002752#undef _
2753
2754#if (VPP_API_TEST_BUILTIN==0)
Ole Troan3459ece2021-09-27 17:11:34 +02002755 vl_msg_api_set_first_available_msg_id (VL_MSG_MEMCLNT_LAST + 1);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002756
2757 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2758
2759 vam->function_by_name = hash_create_string (0, sizeof (uword));
2760
2761 vam->help_by_name = hash_create_string (0, sizeof (uword));
Dave Barach45e4f362017-03-07 12:52:31 -05002762#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002763
2764 /* API messages we can send */
2765#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
2766 foreach_vpe_api_msg;
2767#undef _
2768
2769 /* Help strings */
2770#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2771 foreach_vpe_api_msg;
2772#undef _
Damjan Marion7cd468a2016-12-19 23:05:39 +01002773
2774 /* CLI functions */
2775#define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
2776 foreach_cli_function;
2777#undef _
2778
2779 /* Help strings */
2780#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2781 foreach_cli_function;
2782#undef _
2783}
2784
Dave Baracha1a093d2017-03-02 13:13:23 -05002785#if VPP_API_TEST_BUILTIN
2786static clib_error_t *
2787vat_api_hookup_shim (vlib_main_t * vm)
2788{
2789 vat_api_hookup (&vat_main);
2790 return 0;
2791}
2792
2793VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
2794#endif
2795
Damjan Marion7cd468a2016-12-19 23:05:39 +01002796/*
2797 * fd.io coding-style-patch-verification: ON
2798 *
2799 * Local Variables:
2800 * eval: (c-set-style "gnu")
2801 * End:
2802 */