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