blob: bb168f8459e4347b22a755665cf67bbd1991ba13 [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
32#include <vpp/api/vpe_msg_enum.h>
33#include <vnet/l2/l2_classify.h>
34#include <vnet/l2/l2_vtr.h>
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +010035#include <vnet/classify/in_out_acl.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010036#include <vnet/classify/policer_classify.h>
37#include <vnet/classify/flow_classify.h>
38#include <vnet/mpls/mpls.h>
39#include <vnet/ipsec/ipsec.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010040#include <inttypes.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010041#include <vnet/ip/ip6_hop_by_hop.h>
42#include <vnet/ip/ip_source_and_port_range_check.h>
43#include <vnet/policer/xlate.h>
44#include <vnet/span/span.h>
45#include <vnet/policer/policer.h>
46#include <vnet/policer/police.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000047#include <vnet/mfib/mfib_types.h>
Steven9cd2d7a2017-12-20 12:43:01 -080048#include <vnet/bonding/node.h>
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -070049#include <vnet/qos/qos_types.h>
Neale Ranns37029302018-08-10 05:30:06 -070050#include <vnet/ethernet/ethernet_types_api.h>
51#include <vnet/ip/ip_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010052#include "vat/json_format.h"
Neale Ranns86327be2018-11-02 09:14:01 -070053#include <vnet/ip/ip_types_api.h>
54#include <vnet/ethernet/ethernet_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010055
56#include <inttypes.h>
57#include <sys/stat.h>
58
59#define vl_typedefs /* define message structures */
60#include <vpp/api/vpe_all_api_h.h>
61#undef vl_typedefs
62
63/* declare message handlers for each api */
64
65#define vl_endianfun /* define message structures */
66#include <vpp/api/vpe_all_api_h.h>
67#undef vl_endianfun
68
69/* instantiate all the print functions we know about */
Dave Barachf35a0722019-06-12 16:50:38 -040070#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +010071#define vl_print(handle, ...)
Dave Barachf35a0722019-06-12 16:50:38 -040072#else
73#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
74#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +010075#define vl_printfun
76#include <vpp/api/vpe_all_api_h.h>
77#undef vl_printfun
78
Dave Barach2d6b2d62017-01-25 16:32:08 -050079#define __plugin_msg_base 0
Dave Barachfe6bdfd2017-01-20 19:50:09 -050080#include <vlibapi/vat_helper_macros.h>
81
Dave Barachb09f4d02019-07-15 16:00:03 -040082void vl_api_set_elog_main (elog_main_t * m);
83int vl_api_set_elog_trace_api_messages (int enable);
84
Dave Barach59b25652017-09-10 15:04:27 -040085#if VPP_API_TEST_BUILTIN == 0
86#include <netdb.h>
87
88u32
89vl (void *p)
90{
91 return vec_len (p);
92}
93
94int
95vat_socket_connect (vat_main_t * vam)
96{
Florin Coras66a10032018-12-21 16:23:09 -080097 int rv;
Dave Barach69eeadc2020-04-14 09:52:26 -040098 api_main_t *am = vlibapi_get_main ();
Florin Coras90a63982017-12-19 04:50:01 -080099 vam->socket_client_main = &socket_client_main;
Florin Coras66a10032018-12-21 16:23:09 -0800100 if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
101 "vpp_api_test",
102 0 /* default socket rx, tx buffer */ )))
103 return rv;
Dave Barach69eeadc2020-04-14 09:52:26 -0400104
Florin Coras66a10032018-12-21 16:23:09 -0800105 /* vpp expects the client index in network order */
106 vam->my_client_index = htonl (socket_client_main.client_index);
Dave Barach69eeadc2020-04-14 09:52:26 -0400107 am->my_client_index = vam->my_client_index;
Florin Coras66a10032018-12-21 16:23:09 -0800108 return 0;
Dave Barach59b25652017-09-10 15:04:27 -0400109}
110#else /* vpp built-in case, we don't do sockets... */
111int
112vat_socket_connect (vat_main_t * vam)
113{
114 return 0;
115}
116
Florin Coras90a63982017-12-19 04:50:01 -0800117int
118vl_socket_client_read (int wait)
Dave Barach59b25652017-09-10 15:04:27 -0400119{
Florin Coras90a63982017-12-19 04:50:01 -0800120 return -1;
Dave Barach59b25652017-09-10 15:04:27 -0400121};
Florin Coras90a63982017-12-19 04:50:01 -0800122
123int
124vl_socket_client_write ()
125{
126 return -1;
127};
128
129void *
130vl_socket_client_msg_alloc (int nbytes)
131{
132 return 0;
133}
Dave Barach59b25652017-09-10 15:04:27 -0400134#endif
135
136
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500137f64
138vat_time_now (vat_main_t * vam)
139{
140#if VPP_API_TEST_BUILTIN
141 return vlib_time_now (vam->vlib_main);
142#else
143 return clib_time_now (&vam->clib_time);
144#endif
145}
146
147void
148errmsg (char *fmt, ...)
149{
150 vat_main_t *vam = &vat_main;
151 va_list va;
152 u8 *s;
153
154 va_start (va, fmt);
155 s = va_format (0, fmt, &va);
156 va_end (va);
157
158 vec_add1 (s, 0);
159
160#if VPP_API_TEST_BUILTIN
161 vlib_cli_output (vam->vlib_main, (char *) s);
162#else
163 {
164 if (vam->ifp != stdin)
165 fformat (vam->ofp, "%s(%d): \n", vam->current_file,
166 vam->input_line_number);
Dave Barachb09f4d02019-07-15 16:00:03 -0400167 else
168 fformat (vam->ofp, "%s\n", (char *) s);
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500169 fflush (vam->ofp);
170 }
171#endif
172
173 vec_free (s);
174}
175
Dave Barach4a3f69c2017-02-22 12:44:56 -0500176#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +0100177static uword
178api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
179{
180 vat_main_t *vam = va_arg (*args, vat_main_t *);
181 u32 *result = va_arg (*args, u32 *);
182 u8 *if_name;
183 uword *p;
184
185 if (!unformat (input, "%s", &if_name))
186 return 0;
187
188 p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
189 if (p == 0)
190 return 0;
191 *result = p[0];
192 return 1;
193}
194
Damjan Marion7cd468a2016-12-19 23:05:39 +0100195/* Parse an IP4 address %d.%d.%d.%d. */
196uword
197unformat_ip4_address (unformat_input_t * input, va_list * args)
198{
199 u8 *result = va_arg (*args, u8 *);
200 unsigned a[4];
201
202 if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
203 return 0;
204
205 if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
206 return 0;
207
208 result[0] = a[0];
209 result[1] = a[1];
210 result[2] = a[2];
211 result[3] = a[3];
212
213 return 1;
214}
215
216uword
217unformat_ethernet_address (unformat_input_t * input, va_list * args)
218{
219 u8 *result = va_arg (*args, u8 *);
220 u32 i, a[6];
221
222 if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
223 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
224 return 0;
225
226 /* Check range. */
227 for (i = 0; i < 6; i++)
228 if (a[i] >= (1 << 8))
229 return 0;
230
231 for (i = 0; i < 6; i++)
232 result[i] = a[i];
233
234 return 1;
235}
236
237/* Returns ethernet type as an int in host byte order. */
238uword
239unformat_ethernet_type_host_byte_order (unformat_input_t * input,
240 va_list * args)
241{
242 u16 *result = va_arg (*args, u16 *);
243 int type;
244
245 /* Numeric type. */
246 if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
247 {
248 if (type >= (1 << 16))
249 return 0;
250 *result = type;
251 return 1;
252 }
253 return 0;
254}
255
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100256/* Parse an IP46 address. */
257uword
258unformat_ip46_address (unformat_input_t * input, va_list * args)
259{
260 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
261 ip46_type_t type = va_arg (*args, ip46_type_t);
262 if ((type != IP46_TYPE_IP6) &&
263 unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
264 {
265 ip46_address_mask_ip4 (ip46);
266 return 1;
267 }
268 else if ((type != IP46_TYPE_IP4) &&
269 unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
270 {
271 return 1;
272 }
273 return 0;
274}
275
Damjan Marion7cd468a2016-12-19 23:05:39 +0100276/* Parse an IP6 address. */
277uword
278unformat_ip6_address (unformat_input_t * input, va_list * args)
279{
280 ip6_address_t *result = va_arg (*args, ip6_address_t *);
281 u16 hex_quads[8];
282 uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
283 uword c, n_colon, double_colon_index;
284
285 n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
286 double_colon_index = ARRAY_LEN (hex_quads);
287 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
288 {
289 hex_digit = 16;
290 if (c >= '0' && c <= '9')
291 hex_digit = c - '0';
292 else if (c >= 'a' && c <= 'f')
293 hex_digit = c + 10 - 'a';
294 else if (c >= 'A' && c <= 'F')
295 hex_digit = c + 10 - 'A';
296 else if (c == ':' && n_colon < 2)
297 n_colon++;
298 else
299 {
300 unformat_put_input (input);
301 break;
302 }
303
304 /* Too many hex quads. */
305 if (n_hex_quads >= ARRAY_LEN (hex_quads))
306 return 0;
307
308 if (hex_digit < 16)
309 {
310 hex_quad = (hex_quad << 4) | hex_digit;
311
312 /* Hex quad must fit in 16 bits. */
313 if (n_hex_digits >= 4)
314 return 0;
315
316 n_colon = 0;
317 n_hex_digits++;
318 }
319
320 /* Save position of :: */
321 if (n_colon == 2)
322 {
323 /* More than one :: ? */
324 if (double_colon_index < ARRAY_LEN (hex_quads))
325 return 0;
326 double_colon_index = n_hex_quads;
327 }
328
329 if (n_colon > 0 && n_hex_digits > 0)
330 {
331 hex_quads[n_hex_quads++] = hex_quad;
332 hex_quad = 0;
333 n_hex_digits = 0;
334 }
335 }
336
337 if (n_hex_digits > 0)
338 hex_quads[n_hex_quads++] = hex_quad;
339
340 {
341 word i;
342
343 /* Expand :: to appropriate number of zero hex quads. */
344 if (double_colon_index < ARRAY_LEN (hex_quads))
345 {
346 word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
347
348 for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
349 hex_quads[n_zero + i] = hex_quads[i];
350
351 for (i = 0; i < n_zero; i++)
352 hex_quads[double_colon_index + i] = 0;
353
354 n_hex_quads = ARRAY_LEN (hex_quads);
355 }
356
357 /* Too few hex quads given. */
358 if (n_hex_quads < ARRAY_LEN (hex_quads))
359 return 0;
360
361 for (i = 0; i < ARRAY_LEN (hex_quads); i++)
362 result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
363
364 return 1;
365 }
366}
367
368uword
369unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
370{
371 u32 *r = va_arg (*args, u32 *);
372
373 if (0);
374#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
375 foreach_ipsec_policy_action
376#undef _
377 else
378 return 0;
379 return 1;
380}
381
Damjan Marion7cd468a2016-12-19 23:05:39 +0100382u8 *
383format_ipsec_crypto_alg (u8 * s, va_list * args)
384{
385 u32 i = va_arg (*args, u32);
386 u8 *t = 0;
387
388 switch (i)
389 {
390#define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
391 foreach_ipsec_crypto_alg
392#undef _
393 default:
394 return format (s, "unknown");
395 }
396 return format (s, "%s", t);
397}
398
Damjan Marion7cd468a2016-12-19 23:05:39 +0100399u8 *
400format_ipsec_integ_alg (u8 * s, va_list * args)
401{
402 u32 i = va_arg (*args, u32);
403 u8 *t = 0;
404
405 switch (i)
406 {
407#define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
408 foreach_ipsec_integ_alg
409#undef _
410 default:
411 return format (s, "unknown");
412 }
413 return format (s, "%s", t);
414}
415
Dave Barach4a3f69c2017-02-22 12:44:56 -0500416#else /* VPP_API_TEST_BUILTIN == 1 */
417static uword
418api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
419{
Benoît Ganne49ee6842019-04-30 11:50:46 +0200420 vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500421 vnet_main_t *vnm = vnet_get_main ();
422 u32 *result = va_arg (*args, u32 *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500423
eyal bariaf86a482018-04-17 11:20:27 +0300424 return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500425}
eyal bariaf86a482018-04-17 11:20:27 +0300426
Damjan Marion7cd468a2016-12-19 23:05:39 +0100427#endif /* VPP_API_TEST_BUILTIN */
428
Benoît Ganne49ee6842019-04-30 11:50:46 +0200429#if (VPP_API_TEST_BUILTIN==0)
430
Neale Ranns32e1c012016-11-22 17:07:28 +0000431static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
432static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
433static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
434static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
435
436uword
437unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
438{
439 mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
440 mfib_itf_attribute_t attr;
441
442 old = *iflags;
443 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
444 {
445 if (unformat (input, mfib_itf_flag_long_names[attr]))
446 *iflags |= (1 << attr);
447 }
448 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
449 {
450 if (unformat (input, mfib_itf_flag_names[attr]))
451 *iflags |= (1 << attr);
452 }
453
454 return (old == *iflags ? 0 : 1);
455}
456
457uword
458unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
459{
460 mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
461 mfib_entry_attribute_t attr;
462
463 old = *eflags;
464 FOR_EACH_MFIB_ATTRIBUTE (attr)
465 {
466 if (unformat (input, mfib_flag_long_names[attr]))
467 *eflags |= (1 << attr);
468 }
469 FOR_EACH_MFIB_ATTRIBUTE (attr)
470 {
471 if (unformat (input, mfib_flag_names[attr]))
472 *eflags |= (1 << attr);
473 }
474
475 return (old == *eflags ? 0 : 1);
476}
477
Damjan Marion7cd468a2016-12-19 23:05:39 +0100478u8 *
479format_ip4_address (u8 * s, va_list * args)
480{
481 u8 *a = va_arg (*args, u8 *);
482 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
483}
484
485u8 *
486format_ip6_address (u8 * s, va_list * args)
487{
488 ip6_address_t *a = va_arg (*args, ip6_address_t *);
489 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
490
491 i_max_n_zero = ARRAY_LEN (a->as_u16);
492 max_n_zeros = 0;
493 i_first_zero = i_max_n_zero;
494 n_zeros = 0;
495 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
496 {
497 u32 is_zero = a->as_u16[i] == 0;
498 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
499 {
500 i_first_zero = i;
501 n_zeros = 0;
502 }
503 n_zeros += is_zero;
504 if ((!is_zero && n_zeros > max_n_zeros)
505 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
506 {
507 i_max_n_zero = i_first_zero;
508 max_n_zeros = n_zeros;
509 i_first_zero = ARRAY_LEN (a->as_u16);
510 n_zeros = 0;
511 }
512 }
513
514 last_double_colon = 0;
515 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
516 {
517 if (i == i_max_n_zero && max_n_zeros > 1)
518 {
519 s = format (s, "::");
520 i += max_n_zeros - 1;
521 last_double_colon = 1;
522 }
523 else
524 {
525 s = format (s, "%s%x",
526 (last_double_colon || i == 0) ? "" : ":",
527 clib_net_to_host_u16 (a->as_u16[i]));
528 last_double_colon = 0;
529 }
530 }
531
532 return s;
533}
534
535/* Format an IP46 address. */
536u8 *
537format_ip46_address (u8 * s, va_list * args)
538{
539 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
540 ip46_type_t type = va_arg (*args, ip46_type_t);
541 int is_ip4 = 1;
542
543 switch (type)
544 {
545 case IP46_TYPE_ANY:
546 is_ip4 = ip46_address_is_ip4 (ip46);
547 break;
548 case IP46_TYPE_IP4:
549 is_ip4 = 1;
550 break;
551 case IP46_TYPE_IP6:
552 is_ip4 = 0;
553 break;
554 }
555
556 return is_ip4 ?
557 format (s, "%U", format_ip4_address, &ip46->ip4) :
558 format (s, "%U", format_ip6_address, &ip46->ip6);
559}
560
561u8 *
562format_ethernet_address (u8 * s, va_list * args)
563{
564 u8 *a = va_arg (*args, u8 *);
565
566 return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
567 a[0], a[1], a[2], a[3], a[4], a[5]);
568}
569#endif
570
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100571void
572ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
573{
574 if (is_ip4)
575 dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
576 else
577 clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
578 sizeof (ip6_address_t));
579}
580
Neale Ranns097fa662018-05-01 05:17:55 -0700581
Damjan Marion7cd468a2016-12-19 23:05:39 +0100582static void
583vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
584{
585 vat_main_t *vam = &vat_main;
586 i32 retval = ntohl (mp->retval);
587
588 vam->retval = retval;
Damjan Marion7bee80c2017-04-26 15:32:12 +0200589 vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100590 vam->result_ready = 1;
591}
592
593static void
594vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
595{
596 vat_main_t *vam = &vat_main;
597 vat_json_node_t node;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100598 void *oldheap;
599 u8 *reply;
600
601 vat_json_init_object (&node);
602 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
603 vat_json_object_add_uint (&node, "reply_in_shmem",
604 ntohl (mp->reply_in_shmem));
605 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100606 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +0100607
Damjan Marion7bee80c2017-04-26 15:32:12 +0200608 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100609 vec_free (reply);
610
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100611 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100612
613 vat_json_print (vam->ofp, &node);
614 vat_json_free (&node);
615
616 vam->retval = ntohl (mp->retval);
617 vam->result_ready = 1;
618}
619
620static void
621vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
622{
623 vat_main_t *vam = &vat_main;
624 i32 retval = ntohl (mp->retval);
Dave Barach59b25652017-09-10 15:04:27 -0400625
626 vec_reset_length (vam->cmd_reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100627
628 vam->retval = retval;
Dave Barach59b25652017-09-10 15:04:27 -0400629 if (retval == 0)
Dave Barach77841402020-04-29 17:04:10 -0400630 vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100631 vam->result_ready = 1;
632}
633
634static void
635vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
636{
637 vat_main_t *vam = &vat_main;
638 vat_json_node_t node;
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100639 u8 *reply = 0; /* reply vector */
Damjan Marion7cd468a2016-12-19 23:05:39 +0100640
Dave Barach77841402020-04-29 17:04:10 -0400641 reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
Dave Barach59b25652017-09-10 15:04:27 -0400642 vec_reset_length (vam->cmd_reply);
643
Damjan Marion7cd468a2016-12-19 23:05:39 +0100644 vat_json_init_object (&node);
645 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100646 vat_json_object_add_string_copy (&node, "reply", reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100647
648 vat_json_print (vam->ofp, &node);
649 vat_json_free (&node);
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100650 vec_free (reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100651
652 vam->retval = ntohl (mp->retval);
653 vam->result_ready = 1;
654}
655
Damjan Marion7cd468a2016-12-19 23:05:39 +0100656static void vl_api_get_node_index_reply_t_handler
657 (vl_api_get_node_index_reply_t * mp)
658{
659 vat_main_t *vam = &vat_main;
660 i32 retval = ntohl (mp->retval);
661 if (vam->async_mode)
662 {
663 vam->async_errors += (retval < 0);
664 }
665 else
666 {
667 vam->retval = retval;
668 if (retval == 0)
669 errmsg ("node index %d", ntohl (mp->node_index));
670 vam->result_ready = 1;
671 }
672}
673
674static void vl_api_get_node_index_reply_t_handler_json
675 (vl_api_get_node_index_reply_t * mp)
676{
677 vat_main_t *vam = &vat_main;
678 vat_json_node_t node;
679
680 vat_json_init_object (&node);
681 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
682 vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
683
684 vat_json_print (vam->ofp, &node);
685 vat_json_free (&node);
686
687 vam->retval = ntohl (mp->retval);
688 vam->result_ready = 1;
689}
690
691static void vl_api_get_next_index_reply_t_handler
692 (vl_api_get_next_index_reply_t * mp)
693{
694 vat_main_t *vam = &vat_main;
695 i32 retval = ntohl (mp->retval);
696 if (vam->async_mode)
697 {
698 vam->async_errors += (retval < 0);
699 }
700 else
701 {
702 vam->retval = retval;
703 if (retval == 0)
704 errmsg ("next node index %d", ntohl (mp->next_index));
705 vam->result_ready = 1;
706 }
707}
708
709static void vl_api_get_next_index_reply_t_handler_json
710 (vl_api_get_next_index_reply_t * mp)
711{
712 vat_main_t *vam = &vat_main;
713 vat_json_node_t node;
714
715 vat_json_init_object (&node);
716 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
717 vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
718
719 vat_json_print (vam->ofp, &node);
720 vat_json_free (&node);
721
722 vam->retval = ntohl (mp->retval);
723 vam->result_ready = 1;
724}
725
726static void vl_api_add_node_next_reply_t_handler
727 (vl_api_add_node_next_reply_t * mp)
728{
729 vat_main_t *vam = &vat_main;
730 i32 retval = ntohl (mp->retval);
731 if (vam->async_mode)
732 {
733 vam->async_errors += (retval < 0);
734 }
735 else
736 {
737 vam->retval = retval;
738 if (retval == 0)
739 errmsg ("next index %d", ntohl (mp->next_index));
740 vam->result_ready = 1;
741 }
742}
743
744static void vl_api_add_node_next_reply_t_handler_json
745 (vl_api_add_node_next_reply_t * mp)
746{
747 vat_main_t *vam = &vat_main;
748 vat_json_node_t node;
749
750 vat_json_init_object (&node);
751 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
752 vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
753
754 vat_json_print (vam->ofp, &node);
755 vat_json_free (&node);
756
757 vam->retval = ntohl (mp->retval);
758 vam->result_ready = 1;
759}
760
761static void vl_api_show_version_reply_t_handler
762 (vl_api_show_version_reply_t * mp)
763{
764 vat_main_t *vam = &vat_main;
765 i32 retval = ntohl (mp->retval);
766
767 if (retval >= 0)
768 {
Ole Troane5ff5a32019-08-23 22:55:18 +0200769 errmsg (" program: %s", mp->program);
770 errmsg (" version: %s", mp->version);
771 errmsg (" build date: %s", mp->build_date);
772 errmsg ("build directory: %s", mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100773 }
774 vam->retval = retval;
775 vam->result_ready = 1;
776}
777
778static void vl_api_show_version_reply_t_handler_json
779 (vl_api_show_version_reply_t * mp)
780{
781 vat_main_t *vam = &vat_main;
782 vat_json_node_t node;
783
784 vat_json_init_object (&node);
785 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
Ole Troane5ff5a32019-08-23 22:55:18 +0200786 vat_json_object_add_string_copy (&node, "program", mp->program);
787 vat_json_object_add_string_copy (&node, "version", mp->version);
788 vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100789 vat_json_object_add_string_copy (&node, "build_directory",
Ole Troane5ff5a32019-08-23 22:55:18 +0200790 mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100791
792 vat_json_print (vam->ofp, &node);
793 vat_json_free (&node);
794
795 vam->retval = ntohl (mp->retval);
796 vam->result_ready = 1;
797}
798
Mohsin Kazmi5d64c782018-09-11 20:27:09 +0200799static void vl_api_show_threads_reply_t_handler
800 (vl_api_show_threads_reply_t * mp)
801{
802 vat_main_t *vam = &vat_main;
803 i32 retval = ntohl (mp->retval);
804 int i, count = 0;
805
806 if (retval >= 0)
807 count = ntohl (mp->count);
808
809 for (i = 0; i < count; i++)
810 print (vam->ofp,
811 "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
812 ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
813 mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
814 ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
815 ntohl (mp->thread_data[i].cpu_socket));
816
817 vam->retval = retval;
818 vam->result_ready = 1;
819}
820
821static void vl_api_show_threads_reply_t_handler_json
822 (vl_api_show_threads_reply_t * mp)
823{
824 vat_main_t *vam = &vat_main;
825 vat_json_node_t node;
826 vl_api_thread_data_t *td;
Mohsin Kazmi5df628b2018-10-01 17:41:08 +0200827 i32 retval = ntohl (mp->retval);
828 int i, count = 0;
829
830 if (retval >= 0)
831 count = ntohl (mp->count);
Mohsin Kazmi5d64c782018-09-11 20:27:09 +0200832
833 vat_json_init_object (&node);
Mohsin Kazmi5df628b2018-10-01 17:41:08 +0200834 vat_json_object_add_int (&node, "retval", retval);
Mohsin Kazmi5d64c782018-09-11 20:27:09 +0200835 vat_json_object_add_uint (&node, "count", count);
836
837 for (i = 0; i < count; i++)
838 {
839 td = &mp->thread_data[i];
840 vat_json_object_add_uint (&node, "id", ntohl (td->id));
841 vat_json_object_add_string_copy (&node, "name", td->name);
842 vat_json_object_add_string_copy (&node, "type", td->type);
843 vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
844 vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
845 vat_json_object_add_int (&node, "core", ntohl (td->id));
846 vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
847 }
848
849 vat_json_print (vam->ofp, &node);
850 vat_json_free (&node);
851
Mohsin Kazmi5df628b2018-10-01 17:41:08 +0200852 vam->retval = retval;
Mohsin Kazmi5d64c782018-09-11 20:27:09 +0200853 vam->result_ready = 1;
854}
855
856static int
857api_show_threads (vat_main_t * vam)
858{
859 vl_api_show_threads_t *mp;
860 int ret;
861
862 print (vam->ofp,
863 "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
864 "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
865
866 M (SHOW_THREADS, mp);
867
868 S (mp);
869 W (ret);
870 return ret;
871}
872
Ole Troan01384fe2017-05-12 11:55:35 +0200873#define vl_api_bridge_domain_details_t_endian vl_noop_handler
874#define vl_api_bridge_domain_details_t_print vl_noop_handler
875
Damjan Marion7cd468a2016-12-19 23:05:39 +0100876static void vl_api_control_ping_reply_t_handler
877 (vl_api_control_ping_reply_t * mp)
878{
879 vat_main_t *vam = &vat_main;
880 i32 retval = ntohl (mp->retval);
881 if (vam->async_mode)
882 {
883 vam->async_errors += (retval < 0);
884 }
885 else
886 {
887 vam->retval = retval;
888 vam->result_ready = 1;
889 }
Florin Coras90a63982017-12-19 04:50:01 -0800890 if (vam->socket_client_main)
891 vam->socket_client_main->control_pings_outstanding--;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100892}
893
894static void vl_api_control_ping_reply_t_handler_json
895 (vl_api_control_ping_reply_t * mp)
896{
897 vat_main_t *vam = &vat_main;
898 i32 retval = ntohl (mp->retval);
899
900 if (VAT_JSON_NONE != vam->json_tree.type)
901 {
902 vat_json_print (vam->ofp, &vam->json_tree);
903 vat_json_free (&vam->json_tree);
904 vam->json_tree.type = VAT_JSON_NONE;
905 }
906 else
907 {
908 /* just print [] */
909 vat_json_init_array (&vam->json_tree);
910 vat_json_print (vam->ofp, &vam->json_tree);
911 vam->json_tree.type = VAT_JSON_NONE;
912 }
913
914 vam->retval = retval;
915 vam->result_ready = 1;
916}
917
Damjan Marion7cd468a2016-12-19 23:05:39 +0100918
Damjan Marion7cd468a2016-12-19 23:05:39 +0100919static void vl_api_get_first_msg_id_reply_t_handler
920 (vl_api_get_first_msg_id_reply_t * mp)
921{
922 vat_main_t *vam = &vat_main;
923 i32 retval = ntohl (mp->retval);
924
925 if (vam->async_mode)
926 {
927 vam->async_errors += (retval < 0);
928 }
929 else
930 {
931 vam->retval = retval;
932 vam->result_ready = 1;
933 }
934 if (retval >= 0)
935 {
936 errmsg ("first message id %d", ntohs (mp->first_msg_id));
937 }
938}
939
940static void vl_api_get_first_msg_id_reply_t_handler_json
941 (vl_api_get_first_msg_id_reply_t * mp)
942{
943 vat_main_t *vam = &vat_main;
944 vat_json_node_t node;
945
946 vat_json_init_object (&node);
947 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
948 vat_json_object_add_uint (&node, "first_msg_id",
949 (uint) ntohs (mp->first_msg_id));
950
951 vat_json_print (vam->ofp, &node);
952 vat_json_free (&node);
953
954 vam->retval = ntohl (mp->retval);
955 vam->result_ready = 1;
956}
957
958static void vl_api_get_node_graph_reply_t_handler
959 (vl_api_get_node_graph_reply_t * mp)
960{
961 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100962 i32 retval = ntohl (mp->retval);
963 u8 *pvt_copy, *reply;
964 void *oldheap;
965 vlib_node_t *node;
966 int i;
967
968 if (vam->async_mode)
969 {
970 vam->async_errors += (retval < 0);
971 }
972 else
973 {
974 vam->retval = retval;
975 vam->result_ready = 1;
976 }
977
978 /* "Should never happen..." */
979 if (retval != 0)
980 return;
981
Damjan Marion7bee80c2017-04-26 15:32:12 +0200982 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100983 pvt_copy = vec_dup (reply);
984
985 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100986 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +0100987
988 vec_free (reply);
989
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100990 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100991
992 if (vam->graph_nodes)
993 {
994 hash_free (vam->graph_node_index_by_name);
995
Dave Barach1ddbc012018-06-13 09:26:05 -0400996 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100997 {
Dave Barach1ddbc012018-06-13 09:26:05 -0400998 node = vam->graph_nodes[0][i];
Damjan Marion7cd468a2016-12-19 23:05:39 +0100999 vec_free (node->name);
1000 vec_free (node->next_nodes);
1001 vec_free (node);
1002 }
Dave Barach1ddbc012018-06-13 09:26:05 -04001003 vec_free (vam->graph_nodes[0]);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001004 vec_free (vam->graph_nodes);
1005 }
1006
1007 vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
1008 vam->graph_nodes = vlib_node_unserialize (pvt_copy);
1009 vec_free (pvt_copy);
1010
Dave Barach1ddbc012018-06-13 09:26:05 -04001011 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001012 {
Dave Barach1ddbc012018-06-13 09:26:05 -04001013 node = vam->graph_nodes[0][i];
Damjan Marion7cd468a2016-12-19 23:05:39 +01001014 hash_set_mem (vam->graph_node_index_by_name, node->name, i);
1015 }
1016}
1017
1018static void vl_api_get_node_graph_reply_t_handler_json
1019 (vl_api_get_node_graph_reply_t * mp)
1020{
1021 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001022 void *oldheap;
1023 vat_json_node_t node;
1024 u8 *reply;
1025
1026 /* $$$$ make this real? */
1027 vat_json_init_object (&node);
1028 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1029 vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
1030
Damjan Marion7bee80c2017-04-26 15:32:12 +02001031 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001032
1033 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001034 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01001035
1036 vec_free (reply);
1037
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001038 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001039
1040 vat_json_print (vam->ofp, &node);
1041 vat_json_free (&node);
1042
1043 vam->retval = ntohl (mp->retval);
1044 vam->result_ready = 1;
1045}
1046
Damjan Marion7cd468a2016-12-19 23:05:39 +01001047/* Format hex dump. */
1048u8 *
1049format_hex_bytes (u8 * s, va_list * va)
1050{
1051 u8 *bytes = va_arg (*va, u8 *);
1052 int n_bytes = va_arg (*va, int);
1053 uword i;
1054
1055 /* Print short or long form depending on byte count. */
1056 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +02001057 u32 indent = format_get_indent (s);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001058
1059 if (n_bytes == 0)
1060 return s;
1061
1062 for (i = 0; i < n_bytes; i++)
1063 {
1064 if (!short_form && (i % 32) == 0)
1065 s = format (s, "%08x: ", i);
1066 s = format (s, "%02x", bytes[i]);
1067 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
1068 s = format (s, "\n%U", format_white_space, indent);
1069 }
1070
1071 return s;
1072}
1073
Damjan Marion7cd468a2016-12-19 23:05:39 +01001074/*
1075 * Generate boilerplate reply handlers, which
1076 * dig the return value out of the xxx_reply_t API message,
1077 * stick it into vam->retval, and set vam->result_ready
1078 *
1079 * Could also do this by pointing N message decode slots at
1080 * a single function, but that could break in subtle ways.
1081 */
1082
Filip Tehlar0046e972021-06-26 22:12:08 +00001083#define foreach_standard_reply_retval_handler
Damjan Marion7cd468a2016-12-19 23:05:39 +01001084
1085#define _(n) \
1086 static void vl_api_##n##_t_handler \
1087 (vl_api_##n##_t * mp) \
1088 { \
1089 vat_main_t * vam = &vat_main; \
1090 i32 retval = ntohl(mp->retval); \
1091 if (vam->async_mode) { \
1092 vam->async_errors += (retval < 0); \
1093 } else { \
1094 vam->retval = retval; \
1095 vam->result_ready = 1; \
1096 } \
1097 }
1098foreach_standard_reply_retval_handler;
1099#undef _
1100
1101#define _(n) \
1102 static void vl_api_##n##_t_handler_json \
1103 (vl_api_##n##_t * mp) \
1104 { \
1105 vat_main_t * vam = &vat_main; \
1106 vat_json_node_t node; \
1107 vat_json_init_object(&node); \
1108 vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
1109 vat_json_print(vam->ofp, &node); \
1110 vam->retval = ntohl(mp->retval); \
1111 vam->result_ready = 1; \
1112 }
1113foreach_standard_reply_retval_handler;
1114#undef _
1115
1116/*
1117 * Table of message reply handlers, must include boilerplate handlers
1118 * we just generated
1119 */
1120
Filip Tehlar0577ff12021-06-27 00:18:57 +00001121#define foreach_vpe_api_reply_msg \
1122 _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
1123 _ (GET_NODE_GRAPH_REPLY, get_node_graph_reply) \
1124 _ (CONTROL_PING_REPLY, control_ping_reply) \
1125 _ (CLI_REPLY, cli_reply) \
1126 _ (CLI_INBAND_REPLY, cli_inband_reply) \
1127 _ (GET_NODE_INDEX_REPLY, get_node_index_reply) \
1128 _ (GET_NEXT_INDEX_REPLY, get_next_index_reply) \
1129 _ (ADD_NODE_NEXT_REPLY, add_node_next_reply) \
1130 _ (SHOW_VERSION_REPLY, show_version_reply) \
1131 _ (SHOW_THREADS_REPLY, show_threads_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001132
Dave Baracha1a093d2017-03-02 13:13:23 -05001133#define foreach_standalone_reply_msg \
Dave Baracha1a093d2017-03-02 13:13:23 -05001134
Damjan Marion7cd468a2016-12-19 23:05:39 +01001135typedef struct
1136{
1137 u8 *name;
1138 u32 value;
1139} name_sort_t;
1140
Damjan Marion7cd468a2016-12-19 23:05:39 +01001141#define STR_VTR_OP_CASE(op) \
1142 case L2_VTR_ ## op: \
1143 return "" # op;
1144
Damjan Marion7cd468a2016-12-19 23:05:39 +01001145/*
Dave Barach59b25652017-09-10 15:04:27 -04001146 * Pass CLI buffers directly in the CLI_INBAND API message,
1147 * instead of an additional shared memory area.
Damjan Marion7cd468a2016-12-19 23:05:39 +01001148 */
1149static int
1150exec_inband (vat_main_t * vam)
1151{
1152 vl_api_cli_inband_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001153 unformat_input_t *i = vam->input;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001154 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001155
1156 if (vec_len (i->buffer) == 0)
1157 return -1;
1158
1159 if (vam->exec_mode == 0 && unformat (i, "mode"))
1160 {
1161 vam->exec_mode = 1;
1162 return 0;
1163 }
1164 if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
1165 {
1166 vam->exec_mode = 0;
1167 return 0;
1168 }
1169
1170 /*
1171 * In order for the CLI command to work, it
1172 * must be a vector ending in \n, not a C-string ending
1173 * in \n\0.
1174 */
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001175 M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
1176 vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001177
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001178 S (mp);
Dave Barach59b25652017-09-10 15:04:27 -04001179 W (ret);
1180 /* json responses may or may not include a useful reply... */
1181 if (vec_len (vam->cmd_reply))
Dave Barachcf5e8482017-10-17 11:48:29 -04001182 print (vam->ofp, "%v", (char *) (vam->cmd_reply));
Jon Loeliger56c7b012017-02-01 12:31:41 -06001183 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001184}
1185
Dave Barach59b25652017-09-10 15:04:27 -04001186int
Filip Tehlar0577ff12021-06-27 00:18:57 +00001187exec (vat_main_t *vam)
Dave Barach59b25652017-09-10 15:04:27 -04001188{
1189 return exec_inband (vam);
1190}
1191
Damjan Marion7cd468a2016-12-19 23:05:39 +01001192int
Filip Tehlar0577ff12021-06-27 00:18:57 +00001193api_sw_interface_dump (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001194{
Filip Tehlar0577ff12021-06-27 00:18:57 +00001195 return 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001196}
1197
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01001198uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00001199unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01001200{
jialv01082ebeb2019-09-10 00:23:55 +08001201 vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01001202 u32 x[4];
1203
1204 if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
1205 return 0;
1206
1207 addr->domain = x[0];
1208 addr->bus = x[1];
1209 addr->slot = x[2];
1210 addr->function = x[3];
1211
1212 return 1;
1213}
1214
Neale Ranns097fa662018-05-01 05:17:55 -07001215uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00001216unformat_fib_path (unformat_input_t *input, va_list *args)
Neale Ranns097fa662018-05-01 05:17:55 -07001217{
1218 vat_main_t *vam = va_arg (*args, vat_main_t *);
1219 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
1220 u32 weight, preference;
1221 mpls_label_t out_label;
1222
1223 clib_memset (path, 0, sizeof (*path));
1224 path->weight = 1;
1225 path->sw_if_index = ~0;
1226 path->rpf_id = ~0;
1227 path->n_labels = 0;
1228
1229 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1230 {
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00001231 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
1232 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
1233 &path->sw_if_index))
Neale Ranns097fa662018-05-01 05:17:55 -07001234 {
1235 path->proto = FIB_API_PATH_NH_PROTO_IP4;
1236 }
1237 else if (unformat (input, "%U %U",
1238 unformat_vl_api_ip6_address,
1239 &path->nh.address.ip6,
1240 api_unformat_sw_if_index, vam, &path->sw_if_index))
1241 {
1242 path->proto = FIB_API_PATH_NH_PROTO_IP6;
1243 }
1244 else if (unformat (input, "weight %u", &weight))
1245 {
1246 path->weight = weight;
1247 }
1248 else if (unformat (input, "preference %u", &preference))
1249 {
1250 path->preference = preference;
1251 }
1252 else if (unformat (input, "%U next-hop-table %d",
1253 unformat_vl_api_ip4_address,
1254 &path->nh.address.ip4, &path->table_id))
1255 {
1256 path->proto = FIB_API_PATH_NH_PROTO_IP4;
1257 }
1258 else if (unformat (input, "%U next-hop-table %d",
1259 unformat_vl_api_ip6_address,
1260 &path->nh.address.ip6, &path->table_id))
1261 {
1262 path->proto = FIB_API_PATH_NH_PROTO_IP6;
1263 }
1264 else if (unformat (input, "%U",
1265 unformat_vl_api_ip4_address, &path->nh.address.ip4))
1266 {
1267 /*
1268 * the recursive next-hops are by default in the default table
1269 */
1270 path->table_id = 0;
1271 path->sw_if_index = ~0;
1272 path->proto = FIB_API_PATH_NH_PROTO_IP4;
1273 }
1274 else if (unformat (input, "%U",
1275 unformat_vl_api_ip6_address, &path->nh.address.ip6))
1276 {
1277 /*
1278 * the recursive next-hops are by default in the default table
1279 */
1280 path->table_id = 0;
1281 path->sw_if_index = ~0;
1282 path->proto = FIB_API_PATH_NH_PROTO_IP6;
1283 }
1284 else if (unformat (input, "resolve-via-host"))
1285 {
1286 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
1287 }
1288 else if (unformat (input, "resolve-via-attached"))
1289 {
1290 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
1291 }
1292 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
1293 {
1294 path->type = FIB_API_PATH_TYPE_LOCAL;
1295 path->sw_if_index = ~0;
1296 path->proto = FIB_API_PATH_NH_PROTO_IP4;
1297 }
1298 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
1299 {
1300 path->type = FIB_API_PATH_TYPE_LOCAL;
1301 path->sw_if_index = ~0;
1302 path->proto = FIB_API_PATH_NH_PROTO_IP6;
1303 }
1304 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
1305 ;
1306 else if (unformat (input, "via-label %d", &path->nh.via_label))
1307 {
1308 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
1309 path->sw_if_index = ~0;
1310 }
1311 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
1312 {
1313 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
1314 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
1315 }
1316 else if (unformat (input, "local"))
1317 {
1318 path->type = FIB_API_PATH_TYPE_LOCAL;
1319 }
1320 else if (unformat (input, "out-labels"))
1321 {
1322 while (unformat (input, "%d", &out_label))
1323 {
1324 path->label_stack[path->n_labels].label = out_label;
1325 path->label_stack[path->n_labels].is_uniform = 0;
1326 path->label_stack[path->n_labels].ttl = 64;
1327 path->n_labels++;
1328 }
1329 }
1330 else if (unformat (input, "via"))
1331 {
1332 /* new path, back up and return */
1333 unformat_put_input (input);
1334 unformat_put_input (input);
1335 unformat_put_input (input);
1336 unformat_put_input (input);
1337 break;
1338 }
1339 else
1340 {
1341 return (0);
1342 }
1343 }
1344
1345 path->proto = ntohl (path->proto);
1346 path->type = ntohl (path->type);
1347 path->flags = ntohl (path->flags);
1348 path->table_id = ntohl (path->table_id);
1349 path->sw_if_index = ntohl (path->sw_if_index);
1350
1351 return (1);
1352}
1353
Damjan Marion7cd468a2016-12-19 23:05:39 +01001354#define foreach_create_subif_bit \
1355_(no_tags) \
1356_(one_tag) \
1357_(two_tags) \
1358_(dot1ad) \
1359_(exact_match) \
1360_(default_sub) \
1361_(outer_vlan_id_any) \
1362_(inner_vlan_id_any)
1363
Jakub Grajciar053204a2019-03-18 13:17:53 +01001364#define foreach_create_subif_flag \
1365_(0, "no_tags") \
1366_(1, "one_tag") \
1367_(2, "two_tags") \
1368_(3, "dot1ad") \
1369_(4, "exact_match") \
1370_(5, "default_sub") \
1371_(6, "outer_vlan_id_any") \
1372_(7, "inner_vlan_id_any")
1373
Pablo Camarillofb380952016-12-07 18:34:18 +01001374
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001375#define foreach_tcp_proto_field \
1376 _ (src_port) \
1377 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001378
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001379#define foreach_udp_proto_field \
1380 _ (src_port) \
1381 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001382
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001383#define foreach_ip4_proto_field \
1384 _ (src_address) \
1385 _ (dst_address) \
1386 _ (tos) \
1387 _ (length) \
1388 _ (fragment_id) \
1389 _ (ttl) \
1390 _ (protocol) \
1391 _ (checksum)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001392
Dave Barach4a3f69c2017-02-22 12:44:56 -05001393typedef struct
1394{
1395 u16 src_port, dst_port;
1396} tcpudp_header_t;
1397
1398#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01001399uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001400unformat_tcp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001401{
1402 u8 **maskp = va_arg (*args, u8 **);
1403 u8 *mask = 0;
1404 u8 found_something = 0;
1405 tcp_header_t *tcp;
1406
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001407#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001408 foreach_tcp_proto_field;
1409#undef _
1410
1411 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1412 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001413 if (0)
1414 ;
1415#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001416 foreach_tcp_proto_field
1417#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001418 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001419 }
1420
1421#define _(a) found_something += a;
1422 foreach_tcp_proto_field;
1423#undef _
1424
1425 if (found_something == 0)
1426 return 0;
1427
1428 vec_validate (mask, sizeof (*tcp) - 1);
1429
1430 tcp = (tcp_header_t *) mask;
1431
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001432#define _(a) \
1433 if (a) \
1434 clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001435 foreach_tcp_proto_field;
1436#undef _
1437
1438 *maskp = mask;
1439 return 1;
1440}
1441
1442uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001443unformat_udp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001444{
1445 u8 **maskp = va_arg (*args, u8 **);
1446 u8 *mask = 0;
1447 u8 found_something = 0;
1448 udp_header_t *udp;
1449
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001450#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001451 foreach_udp_proto_field;
1452#undef _
1453
1454 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1455 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001456 if (0)
1457 ;
1458#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001459 foreach_udp_proto_field
1460#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001461 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001462 }
1463
1464#define _(a) found_something += a;
1465 foreach_udp_proto_field;
1466#undef _
1467
1468 if (found_something == 0)
1469 return 0;
1470
1471 vec_validate (mask, sizeof (*udp) - 1);
1472
1473 udp = (udp_header_t *) mask;
1474
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001475#define _(a) \
1476 if (a) \
1477 clib_memset (&udp->a, 0xff, sizeof (udp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001478 foreach_udp_proto_field;
1479#undef _
1480
1481 *maskp = mask;
1482 return 1;
1483}
1484
Damjan Marion7cd468a2016-12-19 23:05:39 +01001485uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001486unformat_l4_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001487{
1488 u8 **maskp = va_arg (*args, u8 **);
1489 u16 src_port = 0, dst_port = 0;
1490 tcpudp_header_t *tcpudp;
1491
1492 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1493 {
1494 if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
1495 return 1;
1496 else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
1497 return 1;
1498 else if (unformat (input, "src_port"))
1499 src_port = 0xFFFF;
1500 else if (unformat (input, "dst_port"))
1501 dst_port = 0xFFFF;
1502 else
1503 return 0;
1504 }
1505
1506 if (!src_port && !dst_port)
1507 return 0;
1508
1509 u8 *mask = 0;
1510 vec_validate (mask, sizeof (tcpudp_header_t) - 1);
1511
1512 tcpudp = (tcpudp_header_t *) mask;
1513 tcpudp->src_port = src_port;
1514 tcpudp->dst_port = dst_port;
1515
1516 *maskp = mask;
1517
1518 return 1;
1519}
1520
1521uword
1522unformat_ip4_mask (unformat_input_t * input, va_list * args)
1523{
1524 u8 **maskp = va_arg (*args, u8 **);
1525 u8 *mask = 0;
1526 u8 found_something = 0;
1527 ip4_header_t *ip;
1528
1529#define _(a) u8 a=0;
1530 foreach_ip4_proto_field;
1531#undef _
1532 u8 version = 0;
1533 u8 hdr_length = 0;
1534
1535
1536 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1537 {
1538 if (unformat (input, "version"))
1539 version = 1;
1540 else if (unformat (input, "hdr_length"))
1541 hdr_length = 1;
1542 else if (unformat (input, "src"))
1543 src_address = 1;
1544 else if (unformat (input, "dst"))
1545 dst_address = 1;
1546 else if (unformat (input, "proto"))
1547 protocol = 1;
1548
1549#define _(a) else if (unformat (input, #a)) a=1;
1550 foreach_ip4_proto_field
1551#undef _
1552 else
1553 break;
1554 }
1555
1556#define _(a) found_something += a;
1557 foreach_ip4_proto_field;
1558#undef _
1559
1560 if (found_something == 0)
1561 return 0;
1562
1563 vec_validate (mask, sizeof (*ip) - 1);
1564
1565 ip = (ip4_header_t *) mask;
1566
Dave Barachb7b92992018-10-17 10:38:51 -04001567#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001568 foreach_ip4_proto_field;
1569#undef _
1570
1571 ip->ip_version_and_header_length = 0;
1572
1573 if (version)
1574 ip->ip_version_and_header_length |= 0xF0;
1575
1576 if (hdr_length)
1577 ip->ip_version_and_header_length |= 0x0F;
1578
1579 *maskp = mask;
1580 return 1;
1581}
1582
1583#define foreach_ip6_proto_field \
1584_(src_address) \
1585_(dst_address) \
1586_(payload_length) \
1587_(hop_limit) \
1588_(protocol)
1589
1590uword
1591unformat_ip6_mask (unformat_input_t * input, va_list * args)
1592{
1593 u8 **maskp = va_arg (*args, u8 **);
1594 u8 *mask = 0;
1595 u8 found_something = 0;
1596 ip6_header_t *ip;
1597 u32 ip_version_traffic_class_and_flow_label;
1598
1599#define _(a) u8 a=0;
1600 foreach_ip6_proto_field;
1601#undef _
1602 u8 version = 0;
1603 u8 traffic_class = 0;
1604 u8 flow_label = 0;
1605
1606 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1607 {
1608 if (unformat (input, "version"))
1609 version = 1;
1610 else if (unformat (input, "traffic-class"))
1611 traffic_class = 1;
1612 else if (unformat (input, "flow-label"))
1613 flow_label = 1;
1614 else if (unformat (input, "src"))
1615 src_address = 1;
1616 else if (unformat (input, "dst"))
1617 dst_address = 1;
1618 else if (unformat (input, "proto"))
1619 protocol = 1;
1620
1621#define _(a) else if (unformat (input, #a)) a=1;
1622 foreach_ip6_proto_field
1623#undef _
1624 else
1625 break;
1626 }
1627
1628#define _(a) found_something += a;
1629 foreach_ip6_proto_field;
1630#undef _
1631
1632 if (found_something == 0)
1633 return 0;
1634
1635 vec_validate (mask, sizeof (*ip) - 1);
1636
1637 ip = (ip6_header_t *) mask;
1638
Dave Barachb7b92992018-10-17 10:38:51 -04001639#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001640 foreach_ip6_proto_field;
1641#undef _
1642
1643 ip_version_traffic_class_and_flow_label = 0;
1644
1645 if (version)
1646 ip_version_traffic_class_and_flow_label |= 0xF0000000;
1647
1648 if (traffic_class)
1649 ip_version_traffic_class_and_flow_label |= 0x0FF00000;
1650
1651 if (flow_label)
1652 ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
1653
1654 ip->ip_version_traffic_class_and_flow_label =
1655 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1656
1657 *maskp = mask;
1658 return 1;
1659}
1660
1661uword
1662unformat_l3_mask (unformat_input_t * input, va_list * args)
1663{
1664 u8 **maskp = va_arg (*args, u8 **);
1665
1666 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1667 {
1668 if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
1669 return 1;
1670 else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
1671 return 1;
1672 else
1673 break;
1674 }
1675 return 0;
1676}
1677
1678uword
1679unformat_l2_mask (unformat_input_t * input, va_list * args)
1680{
1681 u8 **maskp = va_arg (*args, u8 **);
1682 u8 *mask = 0;
1683 u8 src = 0;
1684 u8 dst = 0;
1685 u8 proto = 0;
1686 u8 tag1 = 0;
1687 u8 tag2 = 0;
1688 u8 ignore_tag1 = 0;
1689 u8 ignore_tag2 = 0;
1690 u8 cos1 = 0;
1691 u8 cos2 = 0;
1692 u8 dot1q = 0;
1693 u8 dot1ad = 0;
1694 int len = 14;
1695
1696 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1697 {
1698 if (unformat (input, "src"))
1699 src = 1;
1700 else if (unformat (input, "dst"))
1701 dst = 1;
1702 else if (unformat (input, "proto"))
1703 proto = 1;
1704 else if (unformat (input, "tag1"))
1705 tag1 = 1;
1706 else if (unformat (input, "tag2"))
1707 tag2 = 1;
1708 else if (unformat (input, "ignore-tag1"))
1709 ignore_tag1 = 1;
1710 else if (unformat (input, "ignore-tag2"))
1711 ignore_tag2 = 1;
1712 else if (unformat (input, "cos1"))
1713 cos1 = 1;
1714 else if (unformat (input, "cos2"))
1715 cos2 = 1;
1716 else if (unformat (input, "dot1q"))
1717 dot1q = 1;
1718 else if (unformat (input, "dot1ad"))
1719 dot1ad = 1;
1720 else
1721 break;
1722 }
1723 if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
1724 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1725 return 0;
1726
1727 if (tag1 || ignore_tag1 || cos1 || dot1q)
1728 len = 18;
1729 if (tag2 || ignore_tag2 || cos2 || dot1ad)
1730 len = 22;
1731
1732 vec_validate (mask, len - 1);
1733
1734 if (dst)
Dave Barachb7b92992018-10-17 10:38:51 -04001735 clib_memset (mask, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001736
1737 if (src)
Dave Barachb7b92992018-10-17 10:38:51 -04001738 clib_memset (mask + 6, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001739
1740 if (tag2 || dot1ad)
1741 {
1742 /* inner vlan tag */
1743 if (tag2)
1744 {
1745 mask[19] = 0xff;
1746 mask[18] = 0x0f;
1747 }
1748 if (cos2)
1749 mask[18] |= 0xe0;
1750 if (proto)
1751 mask[21] = mask[20] = 0xff;
1752 if (tag1)
1753 {
1754 mask[15] = 0xff;
1755 mask[14] = 0x0f;
1756 }
1757 if (cos1)
1758 mask[14] |= 0xe0;
1759 *maskp = mask;
1760 return 1;
1761 }
1762 if (tag1 | dot1q)
1763 {
1764 if (tag1)
1765 {
1766 mask[15] = 0xff;
1767 mask[14] = 0x0f;
1768 }
1769 if (cos1)
1770 mask[14] |= 0xe0;
1771 if (proto)
1772 mask[16] = mask[17] = 0xff;
1773
1774 *maskp = mask;
1775 return 1;
1776 }
1777 if (cos2)
1778 mask[18] |= 0xe0;
1779 if (cos1)
1780 mask[14] |= 0xe0;
1781 if (proto)
1782 mask[12] = mask[13] = 0xff;
1783
1784 *maskp = mask;
1785 return 1;
1786}
1787
1788uword
1789unformat_classify_mask (unformat_input_t * input, va_list * args)
1790{
1791 u8 **maskp = va_arg (*args, u8 **);
1792 u32 *skipp = va_arg (*args, u32 *);
1793 u32 *matchp = va_arg (*args, u32 *);
1794 u32 match;
1795 u8 *mask = 0;
1796 u8 *l2 = 0;
1797 u8 *l3 = 0;
1798 u8 *l4 = 0;
1799 int i;
1800
1801 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1802 {
1803 if (unformat (input, "hex %U", unformat_hex_string, &mask))
1804 ;
1805 else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
1806 ;
1807 else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
1808 ;
1809 else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
1810 ;
1811 else
1812 break;
1813 }
1814
1815 if (l4 && !l3)
1816 {
1817 vec_free (mask);
1818 vec_free (l2);
1819 vec_free (l4);
1820 return 0;
1821 }
1822
1823 if (mask || l2 || l3 || l4)
1824 {
1825 if (l2 || l3 || l4)
1826 {
1827 /* "With a free Ethernet header in every package" */
1828 if (l2 == 0)
1829 vec_validate (l2, 13);
1830 mask = l2;
1831 if (vec_len (l3))
1832 {
1833 vec_append (mask, l3);
1834 vec_free (l3);
1835 }
1836 if (vec_len (l4))
1837 {
1838 vec_append (mask, l4);
1839 vec_free (l4);
1840 }
1841 }
1842
1843 /* Scan forward looking for the first significant mask octet */
1844 for (i = 0; i < vec_len (mask); i++)
1845 if (mask[i])
1846 break;
1847
1848 /* compute (skip, match) params */
1849 *skipp = i / sizeof (u32x4);
1850 vec_delete (mask, *skipp * sizeof (u32x4), 0);
1851
1852 /* Pad mask to an even multiple of the vector size */
1853 while (vec_len (mask) % sizeof (u32x4))
1854 vec_add1 (mask, 0);
1855
1856 match = vec_len (mask) / sizeof (u32x4);
1857
1858 for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
1859 {
1860 u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
1861 if (*tmp || *(tmp + 1))
1862 break;
1863 match--;
1864 }
1865 if (match == 0)
1866 clib_warning ("BUG: match 0");
1867
1868 _vec_len (mask) = match * sizeof (u32x4);
1869
1870 *matchp = match;
1871 *maskp = mask;
1872
1873 return 1;
1874 }
1875
1876 return 0;
1877}
Dave Barach4a3f69c2017-02-22 12:44:56 -05001878#endif /* VPP_API_TEST_BUILTIN */
Damjan Marion7cd468a2016-12-19 23:05:39 +01001879
1880#define foreach_l2_next \
1881_(drop, DROP) \
1882_(ethernet, ETHERNET_INPUT) \
1883_(ip4, IP4_INPUT) \
1884_(ip6, IP6_INPUT)
1885
1886uword
1887unformat_l2_next_index (unformat_input_t * input, va_list * args)
1888{
1889 u32 *miss_next_indexp = va_arg (*args, u32 *);
1890 u32 next_index = 0;
1891 u32 tmp;
1892
1893#define _(n,N) \
1894 if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
1895 foreach_l2_next;
1896#undef _
1897
1898 if (unformat (input, "%d", &tmp))
1899 {
1900 next_index = tmp;
1901 goto out;
1902 }
1903
1904 return 0;
1905
1906out:
1907 *miss_next_indexp = next_index;
1908 return 1;
1909}
1910
1911#define foreach_ip_next \
1912_(drop, DROP) \
1913_(local, LOCAL) \
1914_(rewrite, REWRITE)
1915
1916uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001917api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001918{
1919 u32 *miss_next_indexp = va_arg (*args, u32 *);
1920 u32 next_index = 0;
1921 u32 tmp;
1922
1923#define _(n,N) \
1924 if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
1925 foreach_ip_next;
1926#undef _
1927
1928 if (unformat (input, "%d", &tmp))
1929 {
1930 next_index = tmp;
1931 goto out;
1932 }
1933
1934 return 0;
1935
1936out:
1937 *miss_next_indexp = next_index;
1938 return 1;
1939}
1940
1941#define foreach_acl_next \
1942_(deny, DENY)
1943
1944uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001945api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001946{
1947 u32 *miss_next_indexp = va_arg (*args, u32 *);
1948 u32 next_index = 0;
1949 u32 tmp;
1950
1951#define _(n,N) \
1952 if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
1953 foreach_acl_next;
1954#undef _
1955
1956 if (unformat (input, "permit"))
1957 {
1958 next_index = ~0;
1959 goto out;
1960 }
1961 else if (unformat (input, "%d", &tmp))
1962 {
1963 next_index = tmp;
1964 goto out;
1965 }
1966
1967 return 0;
1968
1969out:
1970 *miss_next_indexp = next_index;
1971 return 1;
1972}
1973
1974uword
1975unformat_policer_precolor (unformat_input_t * input, va_list * args)
1976{
1977 u32 *r = va_arg (*args, u32 *);
1978
1979 if (unformat (input, "conform-color"))
1980 *r = POLICE_CONFORM;
1981 else if (unformat (input, "exceed-color"))
1982 *r = POLICE_EXCEED;
1983 else
1984 return 0;
1985
1986 return 1;
1987}
1988
Dave Barach4a3f69c2017-02-22 12:44:56 -05001989#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01001990uword
1991unformat_l4_match (unformat_input_t * input, va_list * args)
1992{
1993 u8 **matchp = va_arg (*args, u8 **);
1994
1995 u8 *proto_header = 0;
1996 int src_port = 0;
1997 int dst_port = 0;
1998
1999 tcpudp_header_t h;
2000
2001 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2002 {
2003 if (unformat (input, "src_port %d", &src_port))
2004 ;
2005 else if (unformat (input, "dst_port %d", &dst_port))
2006 ;
2007 else
2008 return 0;
2009 }
2010
2011 h.src_port = clib_host_to_net_u16 (src_port);
2012 h.dst_port = clib_host_to_net_u16 (dst_port);
2013 vec_validate (proto_header, sizeof (h) - 1);
2014 memcpy (proto_header, &h, sizeof (h));
2015
2016 *matchp = proto_header;
2017
2018 return 1;
2019}
2020
2021uword
2022unformat_ip4_match (unformat_input_t * input, va_list * args)
2023{
2024 u8 **matchp = va_arg (*args, u8 **);
2025 u8 *match = 0;
2026 ip4_header_t *ip;
2027 int version = 0;
2028 u32 version_val;
2029 int hdr_length = 0;
2030 u32 hdr_length_val;
2031 int src = 0, dst = 0;
2032 ip4_address_t src_val, dst_val;
2033 int proto = 0;
2034 u32 proto_val;
2035 int tos = 0;
2036 u32 tos_val;
2037 int length = 0;
2038 u32 length_val;
2039 int fragment_id = 0;
2040 u32 fragment_id_val;
2041 int ttl = 0;
2042 int ttl_val;
2043 int checksum = 0;
2044 u32 checksum_val;
2045
2046 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2047 {
2048 if (unformat (input, "version %d", &version_val))
2049 version = 1;
2050 else if (unformat (input, "hdr_length %d", &hdr_length_val))
2051 hdr_length = 1;
2052 else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
2053 src = 1;
2054 else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
2055 dst = 1;
2056 else if (unformat (input, "proto %d", &proto_val))
2057 proto = 1;
2058 else if (unformat (input, "tos %d", &tos_val))
2059 tos = 1;
2060 else if (unformat (input, "length %d", &length_val))
2061 length = 1;
2062 else if (unformat (input, "fragment_id %d", &fragment_id_val))
2063 fragment_id = 1;
2064 else if (unformat (input, "ttl %d", &ttl_val))
2065 ttl = 1;
2066 else if (unformat (input, "checksum %d", &checksum_val))
2067 checksum = 1;
2068 else
2069 break;
2070 }
2071
2072 if (version + hdr_length + src + dst + proto + tos + length + fragment_id
2073 + ttl + checksum == 0)
2074 return 0;
2075
2076 /*
2077 * Aligned because we use the real comparison functions
2078 */
2079 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
2080
2081 ip = (ip4_header_t *) match;
2082
2083 /* These are realistically matched in practice */
2084 if (src)
2085 ip->src_address.as_u32 = src_val.as_u32;
2086
2087 if (dst)
2088 ip->dst_address.as_u32 = dst_val.as_u32;
2089
2090 if (proto)
2091 ip->protocol = proto_val;
2092
2093
2094 /* These are not, but they're included for completeness */
2095 if (version)
2096 ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
2097
2098 if (hdr_length)
2099 ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
2100
2101 if (tos)
2102 ip->tos = tos_val;
2103
2104 if (length)
2105 ip->length = clib_host_to_net_u16 (length_val);
2106
2107 if (ttl)
2108 ip->ttl = ttl_val;
2109
2110 if (checksum)
2111 ip->checksum = clib_host_to_net_u16 (checksum_val);
2112
2113 *matchp = match;
2114 return 1;
2115}
2116
2117uword
2118unformat_ip6_match (unformat_input_t * input, va_list * args)
2119{
2120 u8 **matchp = va_arg (*args, u8 **);
2121 u8 *match = 0;
2122 ip6_header_t *ip;
2123 int version = 0;
2124 u32 version_val;
2125 u8 traffic_class = 0;
2126 u32 traffic_class_val = 0;
2127 u8 flow_label = 0;
2128 u8 flow_label_val;
2129 int src = 0, dst = 0;
2130 ip6_address_t src_val, dst_val;
2131 int proto = 0;
2132 u32 proto_val;
2133 int payload_length = 0;
2134 u32 payload_length_val;
2135 int hop_limit = 0;
2136 int hop_limit_val;
2137 u32 ip_version_traffic_class_and_flow_label;
2138
2139 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2140 {
2141 if (unformat (input, "version %d", &version_val))
2142 version = 1;
2143 else if (unformat (input, "traffic_class %d", &traffic_class_val))
2144 traffic_class = 1;
2145 else if (unformat (input, "flow_label %d", &flow_label_val))
2146 flow_label = 1;
2147 else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
2148 src = 1;
2149 else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
2150 dst = 1;
2151 else if (unformat (input, "proto %d", &proto_val))
2152 proto = 1;
2153 else if (unformat (input, "payload_length %d", &payload_length_val))
2154 payload_length = 1;
2155 else if (unformat (input, "hop_limit %d", &hop_limit_val))
2156 hop_limit = 1;
2157 else
2158 break;
2159 }
2160
2161 if (version + traffic_class + flow_label + src + dst + proto +
2162 payload_length + hop_limit == 0)
2163 return 0;
2164
2165 /*
2166 * Aligned because we use the real comparison functions
2167 */
2168 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
2169
2170 ip = (ip6_header_t *) match;
2171
2172 if (src)
2173 clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
2174
2175 if (dst)
2176 clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
2177
2178 if (proto)
2179 ip->protocol = proto_val;
2180
2181 ip_version_traffic_class_and_flow_label = 0;
2182
2183 if (version)
2184 ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
2185
2186 if (traffic_class)
2187 ip_version_traffic_class_and_flow_label |=
2188 (traffic_class_val & 0xFF) << 20;
2189
2190 if (flow_label)
2191 ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
2192
2193 ip->ip_version_traffic_class_and_flow_label =
2194 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
2195
2196 if (payload_length)
2197 ip->payload_length = clib_host_to_net_u16 (payload_length_val);
2198
2199 if (hop_limit)
2200 ip->hop_limit = hop_limit_val;
2201
2202 *matchp = match;
2203 return 1;
2204}
2205
2206uword
2207unformat_l3_match (unformat_input_t * input, va_list * args)
2208{
2209 u8 **matchp = va_arg (*args, u8 **);
2210
2211 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2212 {
2213 if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
2214 return 1;
2215 else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
2216 return 1;
2217 else
2218 break;
2219 }
2220 return 0;
2221}
2222
2223uword
2224unformat_vlan_tag (unformat_input_t * input, va_list * args)
2225{
2226 u8 *tagp = va_arg (*args, u8 *);
2227 u32 tag;
2228
2229 if (unformat (input, "%d", &tag))
2230 {
2231 tagp[0] = (tag >> 8) & 0x0F;
2232 tagp[1] = tag & 0xFF;
2233 return 1;
2234 }
2235
2236 return 0;
2237}
2238
2239uword
2240unformat_l2_match (unformat_input_t * input, va_list * args)
2241{
2242 u8 **matchp = va_arg (*args, u8 **);
2243 u8 *match = 0;
2244 u8 src = 0;
2245 u8 src_val[6];
2246 u8 dst = 0;
2247 u8 dst_val[6];
2248 u8 proto = 0;
2249 u16 proto_val;
2250 u8 tag1 = 0;
2251 u8 tag1_val[2];
2252 u8 tag2 = 0;
2253 u8 tag2_val[2];
2254 int len = 14;
2255 u8 ignore_tag1 = 0;
2256 u8 ignore_tag2 = 0;
2257 u8 cos1 = 0;
2258 u8 cos2 = 0;
2259 u32 cos1_val = 0;
2260 u32 cos2_val = 0;
2261
2262 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2263 {
2264 if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
2265 src = 1;
2266 else
2267 if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
2268 dst = 1;
2269 else if (unformat (input, "proto %U",
2270 unformat_ethernet_type_host_byte_order, &proto_val))
2271 proto = 1;
2272 else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
2273 tag1 = 1;
2274 else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
2275 tag2 = 1;
2276 else if (unformat (input, "ignore-tag1"))
2277 ignore_tag1 = 1;
2278 else if (unformat (input, "ignore-tag2"))
2279 ignore_tag2 = 1;
2280 else if (unformat (input, "cos1 %d", &cos1_val))
2281 cos1 = 1;
2282 else if (unformat (input, "cos2 %d", &cos2_val))
2283 cos2 = 1;
2284 else
2285 break;
2286 }
2287 if ((src + dst + proto + tag1 + tag2 +
2288 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
2289 return 0;
2290
2291 if (tag1 || ignore_tag1 || cos1)
2292 len = 18;
2293 if (tag2 || ignore_tag2 || cos2)
2294 len = 22;
2295
2296 vec_validate_aligned (match, len - 1, sizeof (u32x4));
2297
2298 if (dst)
2299 clib_memcpy (match, dst_val, 6);
2300
2301 if (src)
2302 clib_memcpy (match + 6, src_val, 6);
2303
2304 if (tag2)
2305 {
2306 /* inner vlan tag */
2307 match[19] = tag2_val[1];
2308 match[18] = tag2_val[0];
2309 if (cos2)
2310 match[18] |= (cos2_val & 0x7) << 5;
2311 if (proto)
2312 {
2313 match[21] = proto_val & 0xff;
2314 match[20] = proto_val >> 8;
2315 }
2316 if (tag1)
2317 {
2318 match[15] = tag1_val[1];
2319 match[14] = tag1_val[0];
2320 }
2321 if (cos1)
2322 match[14] |= (cos1_val & 0x7) << 5;
2323 *matchp = match;
2324 return 1;
2325 }
2326 if (tag1)
2327 {
2328 match[15] = tag1_val[1];
2329 match[14] = tag1_val[0];
2330 if (proto)
2331 {
2332 match[17] = proto_val & 0xff;
2333 match[16] = proto_val >> 8;
2334 }
2335 if (cos1)
2336 match[14] |= (cos1_val & 0x7) << 5;
2337
2338 *matchp = match;
2339 return 1;
2340 }
2341 if (cos2)
2342 match[18] |= (cos2_val & 0x7) << 5;
2343 if (cos1)
2344 match[14] |= (cos1_val & 0x7) << 5;
2345 if (proto)
2346 {
2347 match[13] = proto_val & 0xff;
2348 match[12] = proto_val >> 8;
2349 }
2350
2351 *matchp = match;
2352 return 1;
2353}
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -07002354
2355uword
2356unformat_qos_source (unformat_input_t * input, va_list * args)
2357{
2358 int *qs = va_arg (*args, int *);
2359
2360 if (unformat (input, "ip"))
2361 *qs = QOS_SOURCE_IP;
2362 else if (unformat (input, "mpls"))
2363 *qs = QOS_SOURCE_MPLS;
2364 else if (unformat (input, "ext"))
2365 *qs = QOS_SOURCE_EXT;
2366 else if (unformat (input, "vlan"))
2367 *qs = QOS_SOURCE_VLAN;
2368 else
2369 return 0;
2370
2371 return 1;
2372}
Dave Barach4a3f69c2017-02-22 12:44:56 -05002373#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002374
2375uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05002376api_unformat_classify_match (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002377{
2378 u8 **matchp = va_arg (*args, u8 **);
2379 u32 skip_n_vectors = va_arg (*args, u32);
2380 u32 match_n_vectors = va_arg (*args, u32);
2381
2382 u8 *match = 0;
2383 u8 *l2 = 0;
2384 u8 *l3 = 0;
2385 u8 *l4 = 0;
2386
2387 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2388 {
2389 if (unformat (input, "hex %U", unformat_hex_string, &match))
2390 ;
2391 else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
2392 ;
2393 else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
2394 ;
2395 else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
2396 ;
2397 else
2398 break;
2399 }
2400
2401 if (l4 && !l3)
2402 {
2403 vec_free (match);
2404 vec_free (l2);
2405 vec_free (l4);
2406 return 0;
2407 }
2408
2409 if (match || l2 || l3 || l4)
2410 {
2411 if (l2 || l3 || l4)
2412 {
2413 /* "Win a free Ethernet header in every packet" */
2414 if (l2 == 0)
2415 vec_validate_aligned (l2, 13, sizeof (u32x4));
2416 match = l2;
2417 if (vec_len (l3))
2418 {
2419 vec_append_aligned (match, l3, sizeof (u32x4));
2420 vec_free (l3);
2421 }
2422 if (vec_len (l4))
2423 {
2424 vec_append_aligned (match, l4, sizeof (u32x4));
2425 vec_free (l4);
2426 }
2427 }
2428
2429 /* Make sure the vector is big enough even if key is all 0's */
2430 vec_validate_aligned
2431 (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
2432 sizeof (u32x4));
2433
2434 /* Set size, include skipped vectors */
2435 _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
2436
2437 *matchp = match;
2438
2439 return 1;
2440 }
2441
2442 return 0;
2443}
2444
2445static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002446api_get_node_index (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002447{
2448 unformat_input_t *i = vam->input;
2449 vl_api_get_node_index_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002450 u8 *name = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002451 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002452
2453 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2454 {
2455 if (unformat (i, "node %s", &name))
2456 ;
2457 else
2458 break;
2459 }
2460 if (name == 0)
2461 {
2462 errmsg ("node name required");
2463 return -99;
2464 }
2465 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
2466 {
2467 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
2468 return -99;
2469 }
2470
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002471 M (GET_NODE_INDEX, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002472 clib_memcpy (mp->node_name, name, vec_len (name));
2473 vec_free (name);
2474
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002475 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002476 W (ret);
2477 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002478}
2479
2480static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002481api_get_next_index (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002482{
2483 unformat_input_t *i = vam->input;
2484 vl_api_get_next_index_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002485 u8 *node_name = 0, *next_node_name = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002486 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002487
2488 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2489 {
2490 if (unformat (i, "node-name %s", &node_name))
2491 ;
2492 else if (unformat (i, "next-node-name %s", &next_node_name))
2493 break;
2494 }
2495
2496 if (node_name == 0)
2497 {
2498 errmsg ("node name required");
2499 return -99;
2500 }
2501 if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
2502 {
2503 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
2504 return -99;
2505 }
2506
2507 if (next_node_name == 0)
2508 {
2509 errmsg ("next node name required");
2510 return -99;
2511 }
2512 if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
2513 {
2514 errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
2515 return -99;
2516 }
2517
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002518 M (GET_NEXT_INDEX, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002519 clib_memcpy (mp->node_name, node_name, vec_len (node_name));
2520 clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
2521 vec_free (node_name);
2522 vec_free (next_node_name);
2523
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002524 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002525 W (ret);
2526 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002527}
2528
2529static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002530api_add_node_next (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002531{
2532 unformat_input_t *i = vam->input;
2533 vl_api_add_node_next_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002534 u8 *name = 0;
2535 u8 *next = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002536 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002537
2538 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2539 {
2540 if (unformat (i, "node %s", &name))
2541 ;
2542 else if (unformat (i, "next %s", &next))
2543 ;
2544 else
2545 break;
2546 }
2547 if (name == 0)
2548 {
2549 errmsg ("node name required");
2550 return -99;
2551 }
2552 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
2553 {
2554 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
2555 return -99;
2556 }
2557 if (next == 0)
2558 {
2559 errmsg ("next node required");
2560 return -99;
2561 }
2562 if (vec_len (next) >= ARRAY_LEN (mp->next_name))
2563 {
2564 errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
2565 return -99;
2566 }
2567
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002568 M (ADD_NODE_NEXT, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002569 clib_memcpy (mp->node_name, name, vec_len (name));
2570 clib_memcpy (mp->next_name, next, vec_len (next));
2571 vec_free (name);
2572 vec_free (next);
2573
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002574 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002575 W (ret);
2576 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002577}
2578
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002579#define foreach_vtr_op \
2580 _ ("disable", L2_VTR_DISABLED) \
2581 _ ("push-1", L2_VTR_PUSH_1) \
2582 _ ("push-2", L2_VTR_PUSH_2) \
2583 _ ("pop-1", L2_VTR_POP_1) \
2584 _ ("pop-2", L2_VTR_POP_2) \
2585 _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \
2586 _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \
2587 _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \
2588 _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002589
2590static int
Filip Tehlar4f348df2021-06-22 12:18:17 +00002591api_show_version (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002592{
2593 vl_api_show_version_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002594 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002595
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002596 M (SHOW_VERSION, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002597
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002598 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002599 W (ret);
2600 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002601}
2602
Damjan Marion7cd468a2016-12-19 23:05:39 +01002603static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002604api_get_first_msg_id (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002605{
2606 vl_api_get_first_msg_id_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002607 unformat_input_t *i = vam->input;
2608 u8 *name;
2609 u8 name_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002610 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002611
2612 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2613 {
2614 if (unformat (i, "client %s", &name))
2615 name_set = 1;
2616 else
2617 break;
2618 }
2619
2620 if (name_set == 0)
2621 {
2622 errmsg ("missing client name");
2623 return -99;
2624 }
2625 vec_add1 (name, 0);
2626
2627 if (vec_len (name) > 63)
2628 {
2629 errmsg ("client name too long");
2630 return -99;
2631 }
2632
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002633 M (GET_FIRST_MSG_ID, mp);
Ole Troan7adaa222019-08-27 15:05:27 +02002634 clib_memcpy (mp->name, name, vec_len (name));
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002635 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002636 W (ret);
2637 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002638}
2639
2640static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002641api_get_node_graph (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002642{
2643 vl_api_get_node_graph_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002644 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002645
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002646 M (GET_NODE_GRAPH, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002647
2648 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002649 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002650 /* Wait for the reply */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002651 W (ret);
2652 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002653}
2654
Damjan Marion7cd468a2016-12-19 23:05:39 +01002655#define foreach_pbb_vtr_op \
2656_("disable", L2_VTR_DISABLED) \
2657_("pop", L2_VTR_POP_2) \
2658_("push", L2_VTR_PUSH_2)
2659
Florin Corascea194d2017-10-02 00:18:51 -07002660static int
Florin Coras90a63982017-12-19 04:50:01 -08002661api_sock_init_shm (vat_main_t * vam)
2662{
2663#if VPP_API_TEST_BUILTIN == 0
2664 unformat_input_t *i = vam->input;
2665 vl_api_shm_elem_config_t *config = 0;
2666 u64 size = 64 << 20;
2667 int rv;
2668
2669 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2670 {
2671 if (unformat (i, "size %U", unformat_memory_size, &size))
2672 ;
2673 else
2674 break;
2675 }
2676
Dave Barach78958722018-05-10 16:44:27 -04002677 /*
2678 * Canned custom ring allocator config.
2679 * Should probably parse all of this
2680 */
2681 vec_validate (config, 6);
Florin Coras90a63982017-12-19 04:50:01 -08002682 config[0].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002683 config[0].size = 256;
Dave Barach78958722018-05-10 16:44:27 -04002684 config[0].count = 32;
2685
2686 config[1].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002687 config[1].size = 1024;
Dave Barach78958722018-05-10 16:44:27 -04002688 config[1].count = 16;
2689
2690 config[2].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002691 config[2].size = 4096;
Dave Barach78958722018-05-10 16:44:27 -04002692 config[2].count = 2;
2693
2694 config[3].type = VL_API_CLIENT_RING;
2695 config[3].size = 256;
2696 config[3].count = 32;
2697
2698 config[4].type = VL_API_CLIENT_RING;
2699 config[4].size = 1024;
2700 config[4].count = 16;
2701
2702 config[5].type = VL_API_CLIENT_RING;
2703 config[5].size = 4096;
2704 config[5].count = 2;
2705
2706 config[6].type = VL_API_QUEUE;
2707 config[6].count = 128;
2708 config[6].size = sizeof (uword);
2709
Tomasz Kulasek97dcf5b2019-01-31 18:26:32 +01002710 rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
Florin Coras90a63982017-12-19 04:50:01 -08002711 if (!rv)
2712 vam->client_index_invalid = 1;
2713 return rv;
2714#else
2715 return -99;
2716#endif
2717}
2718
Florin Coras6c36f532017-11-03 18:32:34 -07002719static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002720q_or_quit (vat_main_t * vam)
2721{
Dave Barachdef19da2017-02-22 17:29:20 -05002722#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01002723 longjmp (vam->jump_buf, 1);
Dave Barachdef19da2017-02-22 17:29:20 -05002724#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002725 return 0; /* not so much */
2726}
2727
2728static int
2729q (vat_main_t * vam)
2730{
2731 return q_or_quit (vam);
2732}
2733
2734static int
2735quit (vat_main_t * vam)
2736{
2737 return q_or_quit (vam);
2738}
2739
2740static int
2741comment (vat_main_t * vam)
2742{
2743 return 0;
2744}
2745
2746static int
Dave Barachb09f4d02019-07-15 16:00:03 -04002747elog_save (vat_main_t * vam)
2748{
2749#if VPP_API_TEST_BUILTIN == 0
2750 elog_main_t *em = &vam->elog_main;
2751 unformat_input_t *i = vam->input;
2752 char *file, *chroot_file;
2753 clib_error_t *error;
2754
2755 if (!unformat (i, "%s", &file))
2756 {
2757 errmsg ("expected file name, got `%U'", format_unformat_error, i);
2758 return 0;
2759 }
2760
2761 /* It's fairly hard to get "../oopsie" through unformat; just in case */
2762 if (strstr (file, "..") || index (file, '/'))
2763 {
2764 errmsg ("illegal characters in filename '%s'", file);
2765 return 0;
2766 }
2767
2768 chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
2769
2770 vec_free (file);
2771
2772 errmsg ("Saving %wd of %wd events to %s",
2773 elog_n_events_in_buffer (em),
2774 elog_buffer_capacity (em), chroot_file);
2775
2776 error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
2777 vec_free (chroot_file);
2778
2779 if (error)
2780 clib_error_report (error);
2781#else
2782 errmsg ("Use the vpp event loger...");
2783#endif
2784
2785 return 0;
2786}
2787
2788static int
2789elog_setup (vat_main_t * vam)
2790{
2791#if VPP_API_TEST_BUILTIN == 0
2792 elog_main_t *em = &vam->elog_main;
2793 unformat_input_t *i = vam->input;
2794 u32 nevents = 128 << 10;
2795
2796 (void) unformat (i, "nevents %d", &nevents);
2797
2798 elog_init (em, nevents);
2799 vl_api_set_elog_main (em);
2800 vl_api_set_elog_trace_api_messages (1);
2801 errmsg ("Event logger initialized with %u events", nevents);
2802#else
2803 errmsg ("Use the vpp event loger...");
2804#endif
2805 return 0;
2806}
2807
2808static int
2809elog_enable (vat_main_t * vam)
2810{
2811#if VPP_API_TEST_BUILTIN == 0
2812 elog_main_t *em = &vam->elog_main;
2813
2814 elog_enable_disable (em, 1 /* enable */ );
2815 vl_api_set_elog_trace_api_messages (1);
2816 errmsg ("Event logger enabled...");
2817#else
2818 errmsg ("Use the vpp event loger...");
2819#endif
2820 return 0;
2821}
2822
2823static int
2824elog_disable (vat_main_t * vam)
2825{
2826#if VPP_API_TEST_BUILTIN == 0
2827 elog_main_t *em = &vam->elog_main;
2828
2829 elog_enable_disable (em, 0 /* enable */ );
2830 vl_api_set_elog_trace_api_messages (1);
2831 errmsg ("Event logger disabled...");
2832#else
2833 errmsg ("Use the vpp event loger...");
2834#endif
2835 return 0;
2836}
2837
2838static int
Dave Barach048a4e52018-06-01 18:52:25 -04002839statseg (vat_main_t * vam)
2840{
2841 ssvm_private_t *ssvmp = &vam->stat_segment;
2842 ssvm_shared_header_t *shared_header = ssvmp->sh;
2843 vlib_counter_t **counters;
2844 u64 thread0_index1_packets;
2845 u64 thread0_index1_bytes;
2846 f64 vector_rate, input_rate;
2847 uword *p;
2848
2849 uword *counter_vector_by_name;
2850 if (vam->stat_segment_lockp == 0)
2851 {
2852 errmsg ("Stat segment not mapped...");
2853 return -99;
2854 }
2855
2856 /* look up "/if/rx for sw_if_index 1 as a test */
2857
2858 clib_spinlock_lock (vam->stat_segment_lockp);
2859
2860 counter_vector_by_name = (uword *) shared_header->opaque[1];
2861
2862 p = hash_get_mem (counter_vector_by_name, "/if/rx");
2863 if (p == 0)
2864 {
2865 clib_spinlock_unlock (vam->stat_segment_lockp);
2866 errmsg ("/if/tx not found?");
2867 return -99;
2868 }
2869
2870 /* Fish per-thread vector of combined counters from shared memory */
2871 counters = (vlib_counter_t **) p[0];
2872
2873 if (vec_len (counters[0]) < 2)
2874 {
2875 clib_spinlock_unlock (vam->stat_segment_lockp);
2876 errmsg ("/if/tx vector length %d", vec_len (counters[0]));
2877 return -99;
2878 }
2879
2880 /* Read thread 0 sw_if_index 1 counter */
2881 thread0_index1_packets = counters[0][1].packets;
2882 thread0_index1_bytes = counters[0][1].bytes;
2883
2884 p = hash_get_mem (counter_vector_by_name, "vector_rate");
2885 if (p == 0)
2886 {
2887 clib_spinlock_unlock (vam->stat_segment_lockp);
2888 errmsg ("vector_rate not found?");
2889 return -99;
2890 }
2891
2892 vector_rate = *(f64 *) (p[0]);
2893 p = hash_get_mem (counter_vector_by_name, "input_rate");
2894 if (p == 0)
2895 {
2896 clib_spinlock_unlock (vam->stat_segment_lockp);
2897 errmsg ("input_rate not found?");
2898 return -99;
2899 }
2900 input_rate = *(f64 *) (p[0]);
2901
2902 clib_spinlock_unlock (vam->stat_segment_lockp);
2903
2904 print (vam->ofp, "vector_rate %.2f input_rate %.2f",
2905 vector_rate, input_rate);
2906 print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
2907 thread0_index1_packets, thread0_index1_bytes);
2908
2909 return 0;
2910}
2911
2912static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002913cmd_cmp (void *a1, void *a2)
2914{
2915 u8 **c1 = a1;
2916 u8 **c2 = a2;
2917
2918 return strcmp ((char *) (c1[0]), (char *) (c2[0]));
2919}
2920
2921static int
2922help (vat_main_t * vam)
2923{
2924 u8 **cmds = 0;
2925 u8 *name = 0;
2926 hash_pair_t *p;
2927 unformat_input_t *i = vam->input;
2928 int j;
2929
2930 if (unformat (i, "%s", &name))
2931 {
2932 uword *hs;
2933
2934 vec_add1 (name, 0);
2935
2936 hs = hash_get_mem (vam->help_by_name, name);
2937 if (hs)
2938 print (vam->ofp, "usage: %s %s", name, hs[0]);
2939 else
2940 print (vam->ofp, "No such msg / command '%s'", name);
2941 vec_free (name);
2942 return 0;
2943 }
2944
2945 print (vam->ofp, "Help is available for the following:");
2946
2947 /* *INDENT-OFF* */
2948 hash_foreach_pair (p, vam->function_by_name,
2949 ({
2950 vec_add1 (cmds, (u8 *)(p->key));
2951 }));
2952 /* *INDENT-ON* */
2953
2954 vec_sort_with_function (cmds, cmd_cmp);
2955
2956 for (j = 0; j < vec_len (cmds); j++)
2957 print (vam->ofp, "%s", cmds[j]);
2958
2959 vec_free (cmds);
2960 return 0;
2961}
2962
2963static int
2964set (vat_main_t * vam)
2965{
2966 u8 *name = 0, *value = 0;
2967 unformat_input_t *i = vam->input;
2968
2969 if (unformat (i, "%s", &name))
2970 {
2971 /* The input buffer is a vector, not a string. */
2972 value = vec_dup (i->buffer);
2973 vec_delete (value, i->index, 0);
2974 /* Almost certainly has a trailing newline */
2975 if (value[vec_len (value) - 1] == '\n')
2976 value[vec_len (value) - 1] = 0;
2977 /* Make sure it's a proper string, one way or the other */
2978 vec_add1 (value, 0);
2979 (void) clib_macro_set_value (&vam->macro_main,
2980 (char *) name, (char *) value);
2981 }
2982 else
2983 errmsg ("usage: set <name> <value>");
2984
2985 vec_free (name);
2986 vec_free (value);
2987 return 0;
2988}
2989
2990static int
2991unset (vat_main_t * vam)
2992{
2993 u8 *name = 0;
2994
2995 if (unformat (vam->input, "%s", &name))
2996 if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
2997 errmsg ("unset: %s wasn't set", name);
2998 vec_free (name);
2999 return 0;
3000}
3001
3002typedef struct
3003{
3004 u8 *name;
3005 u8 *value;
3006} macro_sort_t;
3007
3008
3009static int
3010macro_sort_cmp (void *a1, void *a2)
3011{
3012 macro_sort_t *s1 = a1;
3013 macro_sort_t *s2 = a2;
3014
3015 return strcmp ((char *) (s1->name), (char *) (s2->name));
3016}
3017
3018static int
3019dump_macro_table (vat_main_t * vam)
3020{
3021 macro_sort_t *sort_me = 0, *sm;
3022 int i;
3023 hash_pair_t *p;
3024
3025 /* *INDENT-OFF* */
3026 hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
3027 ({
3028 vec_add2 (sort_me, sm, 1);
3029 sm->name = (u8 *)(p->key);
3030 sm->value = (u8 *) (p->value[0]);
3031 }));
3032 /* *INDENT-ON* */
3033
3034 vec_sort_with_function (sort_me, macro_sort_cmp);
3035
3036 if (vec_len (sort_me))
3037 print (vam->ofp, "%-15s%s", "Name", "Value");
3038 else
3039 print (vam->ofp, "The macro table is empty...");
3040
3041 for (i = 0; i < vec_len (sort_me); i++)
3042 print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
3043 return 0;
3044}
3045
3046static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01003047value_sort_cmp (void *a1, void *a2)
3048{
3049 name_sort_t *n1 = a1;
3050 name_sort_t *n2 = a2;
3051
3052 if (n1->value < n2->value)
3053 return -1;
3054 if (n1->value > n2->value)
3055 return 1;
3056 return 0;
3057}
3058
3059
3060static int
3061dump_msg_api_table (vat_main_t * vam)
3062{
Dave Barach39d69112019-11-27 11:42:13 -05003063 api_main_t *am = vlibapi_get_main ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01003064 name_sort_t *nses = 0, *ns;
3065 hash_pair_t *hp;
3066 int i;
3067
3068 /* *INDENT-OFF* */
3069 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
3070 ({
3071 vec_add2 (nses, ns, 1);
3072 ns->name = (u8 *)(hp->key);
3073 ns->value = (u32) hp->value[0];
3074 }));
3075 /* *INDENT-ON* */
3076
3077 vec_sort_with_function (nses, value_sort_cmp);
3078
3079 for (i = 0; i < vec_len (nses); i++)
3080 print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
3081 vec_free (nses);
3082 return 0;
3083}
3084
3085static int
3086get_msg_id (vat_main_t * vam)
3087{
3088 u8 *name_and_crc;
3089 u32 message_index;
3090
3091 if (unformat (vam->input, "%s", &name_and_crc))
3092 {
Florin Corase86a8ed2018-01-05 03:20:25 -08003093 message_index = vl_msg_api_get_msg_index (name_and_crc);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003094 if (message_index == ~0)
3095 {
3096 print (vam->ofp, " '%s' not found", name_and_crc);
3097 return 0;
3098 }
3099 print (vam->ofp, " '%s' has message index %d",
3100 name_and_crc, message_index);
3101 return 0;
3102 }
3103 errmsg ("name_and_crc required...");
3104 return 0;
3105}
3106
3107static int
3108search_node_table (vat_main_t * vam)
3109{
3110 unformat_input_t *line_input = vam->input;
3111 u8 *node_to_find;
3112 int j;
3113 vlib_node_t *node, *next_node;
3114 uword *p;
3115
3116 if (vam->graph_node_index_by_name == 0)
3117 {
3118 print (vam->ofp, "Node table empty, issue get_node_graph...");
3119 return 0;
3120 }
3121
3122 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3123 {
3124 if (unformat (line_input, "%s", &node_to_find))
3125 {
3126 vec_add1 (node_to_find, 0);
3127 p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
3128 if (p == 0)
3129 {
3130 print (vam->ofp, "%s not found...", node_to_find);
3131 goto out;
3132 }
Dave Barach1ddbc012018-06-13 09:26:05 -04003133 node = vam->graph_nodes[0][p[0]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01003134 print (vam->ofp, "[%d] %s", p[0], node->name);
3135 for (j = 0; j < vec_len (node->next_nodes); j++)
3136 {
3137 if (node->next_nodes[j] != ~0)
3138 {
Dave Barach1ddbc012018-06-13 09:26:05 -04003139 next_node = vam->graph_nodes[0][node->next_nodes[j]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01003140 print (vam->ofp, " [%d] %s", j, next_node->name);
3141 }
3142 }
3143 }
3144
3145 else
3146 {
3147 clib_warning ("parse error '%U'", format_unformat_error,
3148 line_input);
3149 return -99;
3150 }
3151
3152 out:
3153 vec_free (node_to_find);
3154
3155 }
3156
3157 return 0;
3158}
3159
3160
3161static int
3162script (vat_main_t * vam)
3163{
3164#if (VPP_API_TEST_BUILTIN==0)
3165 u8 *s = 0;
3166 char *save_current_file;
3167 unformat_input_t save_input;
3168 jmp_buf save_jump_buf;
3169 u32 save_line_number;
3170
3171 FILE *new_fp, *save_ifp;
3172
3173 if (unformat (vam->input, "%s", &s))
3174 {
3175 new_fp = fopen ((char *) s, "r");
3176 if (new_fp == 0)
3177 {
3178 errmsg ("Couldn't open script file %s", s);
3179 vec_free (s);
3180 return -99;
3181 }
3182 }
3183 else
3184 {
3185 errmsg ("Missing script name");
3186 return -99;
3187 }
3188
3189 clib_memcpy (&save_input, &vam->input, sizeof (save_input));
3190 clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
3191 save_ifp = vam->ifp;
3192 save_line_number = vam->input_line_number;
3193 save_current_file = (char *) vam->current_file;
3194
3195 vam->input_line_number = 0;
3196 vam->ifp = new_fp;
3197 vam->current_file = s;
3198 do_one_file (vam);
3199
Sirshak Dasb0861822018-05-29 21:13:21 -05003200 clib_memcpy (&vam->input, &save_input, sizeof (save_input));
Damjan Marion7cd468a2016-12-19 23:05:39 +01003201 clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
3202 vam->ifp = save_ifp;
3203 vam->input_line_number = save_line_number;
3204 vam->current_file = (u8 *) save_current_file;
3205 vec_free (s);
3206
3207 return 0;
3208#else
3209 clib_warning ("use the exec command...");
3210 return -99;
3211#endif
3212}
3213
3214static int
3215echo (vat_main_t * vam)
3216{
3217 print (vam->ofp, "%v", vam->input->buffer);
3218 return 0;
3219}
3220
3221/* List of API message constructors, CLI names map to api_xxx */
3222#define foreach_vpe_api_msg \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003223_(get_node_index, "node <node-name") \
3224_(add_node_next, "node <node-name> next <next-node-name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003225_(show_version, "") \
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02003226_(show_threads, "") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003227_(get_first_msg_id, "client <name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003228_(get_node_graph, " ") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003229_(get_next_index, "node-name <node-name> next-node-name <node-name>") \
Florin Coras90a63982017-12-19 04:50:01 -08003230_(sock_init_shm, "size <nnn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003231/* List of command functions, CLI names map directly to functions */
3232#define foreach_cli_function \
3233_(comment, "usage: comment <ignore-rest-of-line>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003234_(dump_macro_table, "usage: dump_macro_table ") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003235_(dump_msg_api_table, "usage: dump_msg_api_table") \
Dave Barachb09f4d02019-07-15 16:00:03 -04003236_(elog_setup, "usage: elog_setup [nevents, default 128K]") \
3237_(elog_disable, "usage: elog_disable") \
3238_(elog_enable, "usage: elog_enable") \
3239_(elog_save, "usage: elog_save <filename>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003240_(get_msg_id, "usage: get_msg_id name_and_crc") \
3241_(echo, "usage: echo <message>") \
3242_(exec, "usage: exec <vpe-debug-CLI-command>") \
3243_(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>") \
3244_(help, "usage: help") \
3245_(q, "usage: quit") \
3246_(quit, "usage: quit") \
3247_(search_node_table, "usage: search_node_table <name>...") \
3248_(set, "usage: set <variable-name> <value>") \
3249_(script, "usage: script <file-name>") \
Neale Ranns097fa662018-05-01 05:17:55 -07003250_(statseg, "usage: statseg") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01003251_(unset, "usage: unset <variable-name>")
Dave Barach048a4e52018-06-01 18:52:25 -04003252
Damjan Marion7cd468a2016-12-19 23:05:39 +01003253#define _(N,n) \
3254 static void vl_api_##n##_t_handler_uni \
3255 (vl_api_##n##_t * mp) \
3256 { \
3257 vat_main_t * vam = &vat_main; \
3258 if (vam->json_output) { \
3259 vl_api_##n##_t_handler_json(mp); \
3260 } else { \
3261 vl_api_##n##_t_handler(mp); \
3262 } \
3263 }
3264foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05003265#if VPP_API_TEST_BUILTIN == 0
3266foreach_standalone_reply_msg;
3267#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01003268#undef _
3269
3270void
3271vat_api_hookup (vat_main_t * vam)
3272{
3273#define _(N,n) \
3274 vl_msg_api_set_handlers(VL_API_##N, #n, \
3275 vl_api_##n##_t_handler_uni, \
3276 vl_noop_handler, \
3277 vl_api_##n##_t_endian, \
3278 vl_api_##n##_t_print, \
3279 sizeof(vl_api_##n##_t), 1);
3280 foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05003281#if VPP_API_TEST_BUILTIN == 0
3282 foreach_standalone_reply_msg;
3283#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01003284#undef _
3285
3286#if (VPP_API_TEST_BUILTIN==0)
3287 vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003288
3289 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
3290
3291 vam->function_by_name = hash_create_string (0, sizeof (uword));
3292
3293 vam->help_by_name = hash_create_string (0, sizeof (uword));
Dave Barach45e4f362017-03-07 12:52:31 -05003294#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01003295
3296 /* API messages we can send */
3297#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
3298 foreach_vpe_api_msg;
3299#undef _
3300
3301 /* Help strings */
3302#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
3303 foreach_vpe_api_msg;
3304#undef _
Damjan Marion7cd468a2016-12-19 23:05:39 +01003305
3306 /* CLI functions */
3307#define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
3308 foreach_cli_function;
3309#undef _
3310
3311 /* Help strings */
3312#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
3313 foreach_cli_function;
3314#undef _
3315}
3316
Dave Baracha1a093d2017-03-02 13:13:23 -05003317#if VPP_API_TEST_BUILTIN
3318static clib_error_t *
3319vat_api_hookup_shim (vlib_main_t * vm)
3320{
3321 vat_api_hookup (&vat_main);
3322 return 0;
3323}
3324
3325VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
3326#endif
3327
Damjan Marion7cd468a2016-12-19 23:05:39 +01003328/*
3329 * fd.io coding-style-patch-verification: ON
3330 *
3331 * Local Variables:
3332 * eval: (c-set-style "gnu")
3333 * End:
3334 */