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