blob: 52eb5aeb4ebd3a706a84545f46731032626594a1 [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 vl_api_create_loopback_reply_t_handler
583 (vl_api_create_loopback_reply_t * mp)
584{
585 vat_main_t *vam = &vat_main;
586 i32 retval = ntohl (mp->retval);
587
588 vam->retval = retval;
589 vam->regenerate_interface_table = 1;
590 vam->sw_if_index = ntohl (mp->sw_if_index);
591 vam->result_ready = 1;
592}
593
594static void vl_api_create_loopback_reply_t_handler_json
595 (vl_api_create_loopback_reply_t * mp)
596{
597 vat_main_t *vam = &vat_main;
598 vat_json_node_t node;
599
600 vat_json_init_object (&node);
601 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
602 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
603
604 vat_json_print (vam->ofp, &node);
605 vat_json_free (&node);
606 vam->retval = ntohl (mp->retval);
607 vam->result_ready = 1;
608}
609
Jon Loeligerc83c3b72017-02-23 13:57:35 -0600610static void vl_api_create_loopback_instance_reply_t_handler
611 (vl_api_create_loopback_instance_reply_t * mp)
612{
613 vat_main_t *vam = &vat_main;
614 i32 retval = ntohl (mp->retval);
615
616 vam->retval = retval;
617 vam->regenerate_interface_table = 1;
618 vam->sw_if_index = ntohl (mp->sw_if_index);
619 vam->result_ready = 1;
620}
621
622static void vl_api_create_loopback_instance_reply_t_handler_json
623 (vl_api_create_loopback_instance_reply_t * mp)
624{
625 vat_main_t *vam = &vat_main;
626 vat_json_node_t node;
627
628 vat_json_init_object (&node);
629 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
630 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
631
632 vat_json_print (vam->ofp, &node);
633 vat_json_free (&node);
634 vam->retval = ntohl (mp->retval);
635 vam->result_ready = 1;
636}
637
Damjan Marion7cd468a2016-12-19 23:05:39 +0100638static void vl_api_create_vlan_subif_reply_t_handler
639 (vl_api_create_vlan_subif_reply_t * mp)
640{
641 vat_main_t *vam = &vat_main;
642 i32 retval = ntohl (mp->retval);
643
644 vam->retval = retval;
645 vam->regenerate_interface_table = 1;
646 vam->sw_if_index = ntohl (mp->sw_if_index);
647 vam->result_ready = 1;
648}
649
650static void vl_api_create_vlan_subif_reply_t_handler_json
651 (vl_api_create_vlan_subif_reply_t * mp)
652{
653 vat_main_t *vam = &vat_main;
654 vat_json_node_t node;
655
656 vat_json_init_object (&node);
657 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
658 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
659
660 vat_json_print (vam->ofp, &node);
661 vat_json_free (&node);
662
663 vam->retval = ntohl (mp->retval);
664 vam->result_ready = 1;
665}
666
667static void vl_api_create_subif_reply_t_handler
668 (vl_api_create_subif_reply_t * mp)
669{
670 vat_main_t *vam = &vat_main;
671 i32 retval = ntohl (mp->retval);
672
673 vam->retval = retval;
674 vam->regenerate_interface_table = 1;
675 vam->sw_if_index = ntohl (mp->sw_if_index);
676 vam->result_ready = 1;
677}
678
679static void vl_api_create_subif_reply_t_handler_json
680 (vl_api_create_subif_reply_t * mp)
681{
682 vat_main_t *vam = &vat_main;
683 vat_json_node_t node;
684
685 vat_json_init_object (&node);
686 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
687 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
688
689 vat_json_print (vam->ofp, &node);
690 vat_json_free (&node);
691
692 vam->retval = ntohl (mp->retval);
693 vam->result_ready = 1;
694}
695
696static void vl_api_interface_name_renumber_reply_t_handler
697 (vl_api_interface_name_renumber_reply_t * mp)
698{
699 vat_main_t *vam = &vat_main;
700 i32 retval = ntohl (mp->retval);
701
702 vam->retval = retval;
703 vam->regenerate_interface_table = 1;
704 vam->result_ready = 1;
705}
706
707static void vl_api_interface_name_renumber_reply_t_handler_json
708 (vl_api_interface_name_renumber_reply_t * mp)
709{
710 vat_main_t *vam = &vat_main;
711 vat_json_node_t node;
712
713 vat_json_init_object (&node);
714 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
715
716 vat_json_print (vam->ofp, &node);
717 vat_json_free (&node);
718
719 vam->retval = ntohl (mp->retval);
720 vam->result_ready = 1;
721}
722
723/*
724 * Special-case: build the interface table, maintain
725 * the next loopback sw_if_index vbl.
726 */
727static void vl_api_sw_interface_details_t_handler
728 (vl_api_sw_interface_details_t * mp)
729{
730 vat_main_t *vam = &vat_main;
Ole Troane5ff5a32019-08-23 22:55:18 +0200731 u8 *s = format (0, "%s%c", mp->interface_name, 0);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100732
733 hash_set_mem (vam->sw_if_index_by_interface_name, s,
734 ntohl (mp->sw_if_index));
735
736 /* In sub interface case, fill the sub interface table entry */
737 if (mp->sw_if_index != mp->sup_sw_if_index)
738 {
739 sw_interface_subif_t *sub = NULL;
740
741 vec_add2 (vam->sw_if_subif_table, sub, 1);
742
743 vec_validate (sub->interface_name, strlen ((char *) s) + 1);
744 strncpy ((char *) sub->interface_name, (char *) s,
745 vec_len (sub->interface_name));
746 sub->sw_if_index = ntohl (mp->sw_if_index);
747 sub->sub_id = ntohl (mp->sub_id);
748
Jakub Grajciar053204a2019-03-18 13:17:53 +0100749 sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
750
Damjan Marion7cd468a2016-12-19 23:05:39 +0100751 sub->sub_number_of_tags = mp->sub_number_of_tags;
752 sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
753 sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100754
755 /* vlan tag rewrite */
756 sub->vtr_op = ntohl (mp->vtr_op);
757 sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
758 sub->vtr_tag1 = ntohl (mp->vtr_tag1);
759 sub->vtr_tag2 = ntohl (mp->vtr_tag2);
760 }
761}
762
763static void vl_api_sw_interface_details_t_handler_json
764 (vl_api_sw_interface_details_t * mp)
765{
766 vat_main_t *vam = &vat_main;
767 vat_json_node_t *node = NULL;
768
769 if (VAT_JSON_ARRAY != vam->json_tree.type)
770 {
771 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
772 vat_json_init_array (&vam->json_tree);
773 }
774 node = vat_json_array_add (&vam->json_tree);
775
776 vat_json_init_object (node);
777 vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
778 vat_json_object_add_uint (node, "sup_sw_if_index",
779 ntohl (mp->sup_sw_if_index));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100780 vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
781 sizeof (mp->l2_address));
782 vat_json_object_add_string_copy (node, "interface_name",
Ole Troane5ff5a32019-08-23 22:55:18 +0200783 mp->interface_name);
Mohsin Kazmide312c22019-09-27 13:44:28 +0200784 vat_json_object_add_string_copy (node, "interface_dev_type",
785 mp->interface_dev_type);
Jakub Grajciar053204a2019-03-18 13:17:53 +0100786 vat_json_object_add_uint (node, "flags", mp->flags);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100787 vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
788 vat_json_object_add_uint (node, "link_speed", mp->link_speed);
Damjan Marionfe7d4a22018-04-13 19:43:39 +0200789 vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100790 vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100791 vat_json_object_add_uint (node, "sub_number_of_tags",
792 mp->sub_number_of_tags);
793 vat_json_object_add_uint (node, "sub_outer_vlan_id",
794 ntohs (mp->sub_outer_vlan_id));
795 vat_json_object_add_uint (node, "sub_inner_vlan_id",
796 ntohs (mp->sub_inner_vlan_id));
Jakub Grajciar053204a2019-03-18 13:17:53 +0100797 vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100798 vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
799 vat_json_object_add_uint (node, "vtr_push_dot1q",
800 ntohl (mp->vtr_push_dot1q));
801 vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
802 vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
Jakub Grajciar053204a2019-03-18 13:17:53 +0100803 if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
Pavel Kotucek65e84572017-01-16 17:01:56 +0100804 {
805 vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
806 format (0, "%U",
807 format_ethernet_address,
808 &mp->b_dmac));
809 vat_json_object_add_string_copy (node, "pbb_vtr_smac",
810 format (0, "%U",
811 format_ethernet_address,
812 &mp->b_smac));
813 vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
814 vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
815 }
Damjan Marion7cd468a2016-12-19 23:05:39 +0100816}
817
Dave Baracha1a093d2017-03-02 13:13:23 -0500818#if VPP_API_TEST_BUILTIN == 0
Neale Rannsa07bd702017-08-07 07:53:49 -0700819static void vl_api_sw_interface_event_t_handler
820 (vl_api_sw_interface_event_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100821{
822 vat_main_t *vam = &vat_main;
823 if (vam->interface_event_display)
824 errmsg ("interface flags: sw_if_index %d %s %s",
825 ntohl (mp->sw_if_index),
Jakub Grajciar053204a2019-03-18 13:17:53 +0100826 ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
827 "admin-up" : "admin-down",
828 ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
829 "link-up" : "link-down");
Damjan Marion7cd468a2016-12-19 23:05:39 +0100830}
Dave Baracha1a093d2017-03-02 13:13:23 -0500831#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +0100832
Benoît Ganne49ee6842019-04-30 11:50:46 +0200833__clib_unused static void
834vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100835{
836 /* JSON output not supported */
837}
838
839static void
840vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
841{
842 vat_main_t *vam = &vat_main;
843 i32 retval = ntohl (mp->retval);
844
845 vam->retval = retval;
Damjan Marion7bee80c2017-04-26 15:32:12 +0200846 vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100847 vam->result_ready = 1;
848}
849
850static void
851vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
852{
853 vat_main_t *vam = &vat_main;
854 vat_json_node_t node;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100855 void *oldheap;
856 u8 *reply;
857
858 vat_json_init_object (&node);
859 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
860 vat_json_object_add_uint (&node, "reply_in_shmem",
861 ntohl (mp->reply_in_shmem));
862 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100863 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +0100864
Damjan Marion7bee80c2017-04-26 15:32:12 +0200865 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100866 vec_free (reply);
867
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100868 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100869
870 vat_json_print (vam->ofp, &node);
871 vat_json_free (&node);
872
873 vam->retval = ntohl (mp->retval);
874 vam->result_ready = 1;
875}
876
877static void
878vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
879{
880 vat_main_t *vam = &vat_main;
881 i32 retval = ntohl (mp->retval);
Dave Barach59b25652017-09-10 15:04:27 -0400882
883 vec_reset_length (vam->cmd_reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100884
885 vam->retval = retval;
Dave Barach59b25652017-09-10 15:04:27 -0400886 if (retval == 0)
Dave Barach77841402020-04-29 17:04:10 -0400887 vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100888 vam->result_ready = 1;
889}
890
891static void
892vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
893{
894 vat_main_t *vam = &vat_main;
895 vat_json_node_t node;
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100896 u8 *reply = 0; /* reply vector */
Damjan Marion7cd468a2016-12-19 23:05:39 +0100897
Dave Barach77841402020-04-29 17:04:10 -0400898 reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
Dave Barach59b25652017-09-10 15:04:27 -0400899 vec_reset_length (vam->cmd_reply);
900
Damjan Marion7cd468a2016-12-19 23:05:39 +0100901 vat_json_init_object (&node);
902 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100903 vat_json_object_add_string_copy (&node, "reply", reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100904
905 vat_json_print (vam->ofp, &node);
906 vat_json_free (&node);
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100907 vec_free (reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100908
909 vam->retval = ntohl (mp->retval);
910 vam->result_ready = 1;
911}
912
Damjan Marion7cd468a2016-12-19 23:05:39 +0100913static void vl_api_get_node_index_reply_t_handler
914 (vl_api_get_node_index_reply_t * mp)
915{
916 vat_main_t *vam = &vat_main;
917 i32 retval = ntohl (mp->retval);
918 if (vam->async_mode)
919 {
920 vam->async_errors += (retval < 0);
921 }
922 else
923 {
924 vam->retval = retval;
925 if (retval == 0)
926 errmsg ("node index %d", ntohl (mp->node_index));
927 vam->result_ready = 1;
928 }
929}
930
931static void vl_api_get_node_index_reply_t_handler_json
932 (vl_api_get_node_index_reply_t * mp)
933{
934 vat_main_t *vam = &vat_main;
935 vat_json_node_t node;
936
937 vat_json_init_object (&node);
938 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
939 vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
940
941 vat_json_print (vam->ofp, &node);
942 vat_json_free (&node);
943
944 vam->retval = ntohl (mp->retval);
945 vam->result_ready = 1;
946}
947
948static void vl_api_get_next_index_reply_t_handler
949 (vl_api_get_next_index_reply_t * mp)
950{
951 vat_main_t *vam = &vat_main;
952 i32 retval = ntohl (mp->retval);
953 if (vam->async_mode)
954 {
955 vam->async_errors += (retval < 0);
956 }
957 else
958 {
959 vam->retval = retval;
960 if (retval == 0)
961 errmsg ("next node index %d", ntohl (mp->next_index));
962 vam->result_ready = 1;
963 }
964}
965
966static void vl_api_get_next_index_reply_t_handler_json
967 (vl_api_get_next_index_reply_t * mp)
968{
969 vat_main_t *vam = &vat_main;
970 vat_json_node_t node;
971
972 vat_json_init_object (&node);
973 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
974 vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
975
976 vat_json_print (vam->ofp, &node);
977 vat_json_free (&node);
978
979 vam->retval = ntohl (mp->retval);
980 vam->result_ready = 1;
981}
982
983static void vl_api_add_node_next_reply_t_handler
984 (vl_api_add_node_next_reply_t * mp)
985{
986 vat_main_t *vam = &vat_main;
987 i32 retval = ntohl (mp->retval);
988 if (vam->async_mode)
989 {
990 vam->async_errors += (retval < 0);
991 }
992 else
993 {
994 vam->retval = retval;
995 if (retval == 0)
996 errmsg ("next index %d", ntohl (mp->next_index));
997 vam->result_ready = 1;
998 }
999}
1000
1001static void vl_api_add_node_next_reply_t_handler_json
1002 (vl_api_add_node_next_reply_t * mp)
1003{
1004 vat_main_t *vam = &vat_main;
1005 vat_json_node_t node;
1006
1007 vat_json_init_object (&node);
1008 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1009 vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1010
1011 vat_json_print (vam->ofp, &node);
1012 vat_json_free (&node);
1013
1014 vam->retval = ntohl (mp->retval);
1015 vam->result_ready = 1;
1016}
1017
1018static void vl_api_show_version_reply_t_handler
1019 (vl_api_show_version_reply_t * mp)
1020{
1021 vat_main_t *vam = &vat_main;
1022 i32 retval = ntohl (mp->retval);
1023
1024 if (retval >= 0)
1025 {
Ole Troane5ff5a32019-08-23 22:55:18 +02001026 errmsg (" program: %s", mp->program);
1027 errmsg (" version: %s", mp->version);
1028 errmsg (" build date: %s", mp->build_date);
1029 errmsg ("build directory: %s", mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001030 }
1031 vam->retval = retval;
1032 vam->result_ready = 1;
1033}
1034
1035static void vl_api_show_version_reply_t_handler_json
1036 (vl_api_show_version_reply_t * mp)
1037{
1038 vat_main_t *vam = &vat_main;
1039 vat_json_node_t node;
1040
1041 vat_json_init_object (&node);
1042 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
Ole Troane5ff5a32019-08-23 22:55:18 +02001043 vat_json_object_add_string_copy (&node, "program", mp->program);
1044 vat_json_object_add_string_copy (&node, "version", mp->version);
1045 vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001046 vat_json_object_add_string_copy (&node, "build_directory",
Ole Troane5ff5a32019-08-23 22:55:18 +02001047 mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001048
1049 vat_json_print (vam->ofp, &node);
1050 vat_json_free (&node);
1051
1052 vam->retval = ntohl (mp->retval);
1053 vam->result_ready = 1;
1054}
1055
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001056static void vl_api_show_threads_reply_t_handler
1057 (vl_api_show_threads_reply_t * mp)
1058{
1059 vat_main_t *vam = &vat_main;
1060 i32 retval = ntohl (mp->retval);
1061 int i, count = 0;
1062
1063 if (retval >= 0)
1064 count = ntohl (mp->count);
1065
1066 for (i = 0; i < count; i++)
1067 print (vam->ofp,
1068 "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1069 ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1070 mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1071 ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1072 ntohl (mp->thread_data[i].cpu_socket));
1073
1074 vam->retval = retval;
1075 vam->result_ready = 1;
1076}
1077
1078static void vl_api_show_threads_reply_t_handler_json
1079 (vl_api_show_threads_reply_t * mp)
1080{
1081 vat_main_t *vam = &vat_main;
1082 vat_json_node_t node;
1083 vl_api_thread_data_t *td;
Mohsin Kazmi5df628b2018-10-01 17:41:08 +02001084 i32 retval = ntohl (mp->retval);
1085 int i, count = 0;
1086
1087 if (retval >= 0)
1088 count = ntohl (mp->count);
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001089
1090 vat_json_init_object (&node);
Mohsin Kazmi5df628b2018-10-01 17:41:08 +02001091 vat_json_object_add_int (&node, "retval", retval);
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001092 vat_json_object_add_uint (&node, "count", count);
1093
1094 for (i = 0; i < count; i++)
1095 {
1096 td = &mp->thread_data[i];
1097 vat_json_object_add_uint (&node, "id", ntohl (td->id));
1098 vat_json_object_add_string_copy (&node, "name", td->name);
1099 vat_json_object_add_string_copy (&node, "type", td->type);
1100 vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1101 vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1102 vat_json_object_add_int (&node, "core", ntohl (td->id));
1103 vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1104 }
1105
1106 vat_json_print (vam->ofp, &node);
1107 vat_json_free (&node);
1108
Mohsin Kazmi5df628b2018-10-01 17:41:08 +02001109 vam->retval = retval;
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001110 vam->result_ready = 1;
1111}
1112
1113static int
1114api_show_threads (vat_main_t * vam)
1115{
1116 vl_api_show_threads_t *mp;
1117 int ret;
1118
1119 print (vam->ofp,
1120 "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1121 "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1122
1123 M (SHOW_THREADS, mp);
1124
1125 S (mp);
1126 W (ret);
1127 return ret;
1128}
1129
Ole Troan01384fe2017-05-12 11:55:35 +02001130#define vl_api_bridge_domain_details_t_endian vl_noop_handler
1131#define vl_api_bridge_domain_details_t_print vl_noop_handler
1132
Damjan Marion7cd468a2016-12-19 23:05:39 +01001133static void vl_api_control_ping_reply_t_handler
1134 (vl_api_control_ping_reply_t * mp)
1135{
1136 vat_main_t *vam = &vat_main;
1137 i32 retval = ntohl (mp->retval);
1138 if (vam->async_mode)
1139 {
1140 vam->async_errors += (retval < 0);
1141 }
1142 else
1143 {
1144 vam->retval = retval;
1145 vam->result_ready = 1;
1146 }
Florin Coras90a63982017-12-19 04:50:01 -08001147 if (vam->socket_client_main)
1148 vam->socket_client_main->control_pings_outstanding--;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001149}
1150
1151static void vl_api_control_ping_reply_t_handler_json
1152 (vl_api_control_ping_reply_t * mp)
1153{
1154 vat_main_t *vam = &vat_main;
1155 i32 retval = ntohl (mp->retval);
1156
1157 if (VAT_JSON_NONE != vam->json_tree.type)
1158 {
1159 vat_json_print (vam->ofp, &vam->json_tree);
1160 vat_json_free (&vam->json_tree);
1161 vam->json_tree.type = VAT_JSON_NONE;
1162 }
1163 else
1164 {
1165 /* just print [] */
1166 vat_json_init_array (&vam->json_tree);
1167 vat_json_print (vam->ofp, &vam->json_tree);
1168 vam->json_tree.type = VAT_JSON_NONE;
1169 }
1170
1171 vam->retval = retval;
1172 vam->result_ready = 1;
1173}
1174
Damjan Marion7cd468a2016-12-19 23:05:39 +01001175
Damjan Marion7cd468a2016-12-19 23:05:39 +01001176static void vl_api_get_first_msg_id_reply_t_handler
1177 (vl_api_get_first_msg_id_reply_t * mp)
1178{
1179 vat_main_t *vam = &vat_main;
1180 i32 retval = ntohl (mp->retval);
1181
1182 if (vam->async_mode)
1183 {
1184 vam->async_errors += (retval < 0);
1185 }
1186 else
1187 {
1188 vam->retval = retval;
1189 vam->result_ready = 1;
1190 }
1191 if (retval >= 0)
1192 {
1193 errmsg ("first message id %d", ntohs (mp->first_msg_id));
1194 }
1195}
1196
1197static void vl_api_get_first_msg_id_reply_t_handler_json
1198 (vl_api_get_first_msg_id_reply_t * mp)
1199{
1200 vat_main_t *vam = &vat_main;
1201 vat_json_node_t node;
1202
1203 vat_json_init_object (&node);
1204 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1205 vat_json_object_add_uint (&node, "first_msg_id",
1206 (uint) ntohs (mp->first_msg_id));
1207
1208 vat_json_print (vam->ofp, &node);
1209 vat_json_free (&node);
1210
1211 vam->retval = ntohl (mp->retval);
1212 vam->result_ready = 1;
1213}
1214
1215static void vl_api_get_node_graph_reply_t_handler
1216 (vl_api_get_node_graph_reply_t * mp)
1217{
1218 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001219 i32 retval = ntohl (mp->retval);
1220 u8 *pvt_copy, *reply;
1221 void *oldheap;
1222 vlib_node_t *node;
1223 int i;
1224
1225 if (vam->async_mode)
1226 {
1227 vam->async_errors += (retval < 0);
1228 }
1229 else
1230 {
1231 vam->retval = retval;
1232 vam->result_ready = 1;
1233 }
1234
1235 /* "Should never happen..." */
1236 if (retval != 0)
1237 return;
1238
Damjan Marion7bee80c2017-04-26 15:32:12 +02001239 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001240 pvt_copy = vec_dup (reply);
1241
1242 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001243 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01001244
1245 vec_free (reply);
1246
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001247 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001248
1249 if (vam->graph_nodes)
1250 {
1251 hash_free (vam->graph_node_index_by_name);
1252
Dave Barach1ddbc012018-06-13 09:26:05 -04001253 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001254 {
Dave Barach1ddbc012018-06-13 09:26:05 -04001255 node = vam->graph_nodes[0][i];
Damjan Marion7cd468a2016-12-19 23:05:39 +01001256 vec_free (node->name);
1257 vec_free (node->next_nodes);
1258 vec_free (node);
1259 }
Dave Barach1ddbc012018-06-13 09:26:05 -04001260 vec_free (vam->graph_nodes[0]);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001261 vec_free (vam->graph_nodes);
1262 }
1263
1264 vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
1265 vam->graph_nodes = vlib_node_unserialize (pvt_copy);
1266 vec_free (pvt_copy);
1267
Dave Barach1ddbc012018-06-13 09:26:05 -04001268 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001269 {
Dave Barach1ddbc012018-06-13 09:26:05 -04001270 node = vam->graph_nodes[0][i];
Damjan Marion7cd468a2016-12-19 23:05:39 +01001271 hash_set_mem (vam->graph_node_index_by_name, node->name, i);
1272 }
1273}
1274
1275static void vl_api_get_node_graph_reply_t_handler_json
1276 (vl_api_get_node_graph_reply_t * mp)
1277{
1278 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001279 void *oldheap;
1280 vat_json_node_t node;
1281 u8 *reply;
1282
1283 /* $$$$ make this real? */
1284 vat_json_init_object (&node);
1285 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1286 vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
1287
Damjan Marion7bee80c2017-04-26 15:32:12 +02001288 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001289
1290 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001291 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01001292
1293 vec_free (reply);
1294
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001295 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001296
1297 vat_json_print (vam->ofp, &node);
1298 vat_json_free (&node);
1299
1300 vam->retval = ntohl (mp->retval);
1301 vam->result_ready = 1;
1302}
1303
Damjan Marion7cd468a2016-12-19 23:05:39 +01001304/* Format hex dump. */
1305u8 *
1306format_hex_bytes (u8 * s, va_list * va)
1307{
1308 u8 *bytes = va_arg (*va, u8 *);
1309 int n_bytes = va_arg (*va, int);
1310 uword i;
1311
1312 /* Print short or long form depending on byte count. */
1313 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +02001314 u32 indent = format_get_indent (s);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001315
1316 if (n_bytes == 0)
1317 return s;
1318
1319 for (i = 0; i < n_bytes; i++)
1320 {
1321 if (!short_form && (i % 32) == 0)
1322 s = format (s, "%08x: ", i);
1323 s = format (s, "%02x", bytes[i]);
1324 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
1325 s = format (s, "\n%U", format_white_space, indent);
1326 }
1327
1328 return s;
1329}
1330
Damjan Marion7cd468a2016-12-19 23:05:39 +01001331/*
1332 * Generate boilerplate reply handlers, which
1333 * dig the return value out of the xxx_reply_t API message,
1334 * stick it into vam->retval, and set vam->result_ready
1335 *
1336 * Could also do this by pointing N message decode slots at
1337 * a single function, but that could break in subtle ways.
1338 */
1339
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001340#define foreach_standard_reply_retval_handler \
1341 _ (sw_interface_set_flags_reply) \
1342 _ (sw_interface_add_del_address_reply) \
1343 _ (sw_interface_set_rx_placement_reply) \
1344 _ (sw_interface_set_unnumbered_reply) \
1345 _ (sw_interface_set_table_reply) \
1346 _ (delete_loopback_reply) \
1347 _ (want_interface_events_reply) \
1348 _ (sw_interface_clear_stats_reply) \
1349 _ (delete_subif_reply) \
1350 _ (sw_interface_tag_add_del_reply) \
1351 _ (sw_interface_add_del_mac_address_reply) \
1352 _ (hw_interface_set_mtu_reply) \
1353 _ (session_rule_add_del_reply)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001354
1355#define _(n) \
1356 static void vl_api_##n##_t_handler \
1357 (vl_api_##n##_t * mp) \
1358 { \
1359 vat_main_t * vam = &vat_main; \
1360 i32 retval = ntohl(mp->retval); \
1361 if (vam->async_mode) { \
1362 vam->async_errors += (retval < 0); \
1363 } else { \
1364 vam->retval = retval; \
1365 vam->result_ready = 1; \
1366 } \
1367 }
1368foreach_standard_reply_retval_handler;
1369#undef _
1370
1371#define _(n) \
1372 static void vl_api_##n##_t_handler_json \
1373 (vl_api_##n##_t * mp) \
1374 { \
1375 vat_main_t * vam = &vat_main; \
1376 vat_json_node_t node; \
1377 vat_json_init_object(&node); \
1378 vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
1379 vat_json_print(vam->ofp, &node); \
1380 vam->retval = ntohl(mp->retval); \
1381 vam->result_ready = 1; \
1382 }
1383foreach_standard_reply_retval_handler;
1384#undef _
1385
1386/*
1387 * Table of message reply handlers, must include boilerplate handlers
1388 * we just generated
1389 */
1390
1391#define foreach_vpe_api_reply_msg \
1392_(CREATE_LOOPBACK_REPLY, create_loopback_reply) \
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001393_(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001394_(SW_INTERFACE_DETAILS, sw_interface_details) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001395_(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply) \
1396_(CONTROL_PING_REPLY, control_ping_reply) \
1397_(CLI_REPLY, cli_reply) \
1398_(CLI_INBAND_REPLY, cli_inband_reply) \
1399_(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY, \
1400 sw_interface_add_del_address_reply) \
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001401_(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply) \
Mohsin Kazmif0b42f42018-09-10 18:11:00 +02001402_(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001403_(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001404_(SW_INTERFACE_SET_UNNUMBERED_REPLY, \
1405 sw_interface_set_unnumbered_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001406_(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply) \
1407_(CREATE_SUBIF_REPLY, create_subif_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001408_(GET_NODE_INDEX_REPLY, get_node_index_reply) \
1409_(ADD_NODE_NEXT_REPLY, add_node_next_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001410_(SHOW_VERSION_REPLY, show_version_reply) \
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001411_(SHOW_THREADS_REPLY, show_threads_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001412_(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001413_(DELETE_LOOPBACK_REPLY, delete_loopback_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001414_(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001415_(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001416_(GET_NODE_GRAPH_REPLY, get_node_graph_reply) \
1417_(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001418_(GET_NEXT_INDEX_REPLY, get_next_index_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001419_(DELETE_SUBIF_REPLY, delete_subif_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001420_(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply) \
Matthew Smithe0792fd2019-07-12 11:48:24 -05001421_(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
Ole Troand7231612018-06-07 10:17:57 +02001422_(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply) \
Pavel Kotucek6899a302017-06-08 08:46:10 +02001423_(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply) \
Dave Barach65457162017-10-10 17:53:14 -04001424_(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply) \
Florin Coras6c36f532017-11-03 18:32:34 -07001425_(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply) \
Florin Coras595992c2017-11-06 17:17:08 -08001426_(SESSION_RULES_DETAILS, session_rules_details) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001427
Dave Baracha1a093d2017-03-02 13:13:23 -05001428#define foreach_standalone_reply_msg \
Ole Troanf49ba0e2018-11-13 14:04:50 +01001429_(SW_INTERFACE_EVENT, sw_interface_event)
Dave Baracha1a093d2017-03-02 13:13:23 -05001430
Damjan Marion7cd468a2016-12-19 23:05:39 +01001431typedef struct
1432{
1433 u8 *name;
1434 u32 value;
1435} name_sort_t;
1436
Damjan Marion7cd468a2016-12-19 23:05:39 +01001437#define STR_VTR_OP_CASE(op) \
1438 case L2_VTR_ ## op: \
1439 return "" # op;
1440
1441static const char *
1442str_vtr_op (u32 vtr_op)
1443{
1444 switch (vtr_op)
1445 {
1446 STR_VTR_OP_CASE (DISABLED);
1447 STR_VTR_OP_CASE (PUSH_1);
1448 STR_VTR_OP_CASE (PUSH_2);
1449 STR_VTR_OP_CASE (POP_1);
1450 STR_VTR_OP_CASE (POP_2);
1451 STR_VTR_OP_CASE (TRANSLATE_1_1);
1452 STR_VTR_OP_CASE (TRANSLATE_1_2);
1453 STR_VTR_OP_CASE (TRANSLATE_2_1);
1454 STR_VTR_OP_CASE (TRANSLATE_2_2);
1455 }
1456
1457 return "UNKNOWN";
1458}
1459
1460static int
1461dump_sub_interface_table (vat_main_t * vam)
1462{
1463 const sw_interface_subif_t *sub = NULL;
1464
1465 if (vam->json_output)
1466 {
1467 clib_warning
1468 ("JSON output supported only for VPE API calls and dump_stats_table");
1469 return -99;
1470 }
1471
1472 print (vam->ofp,
1473 "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
1474 "Interface", "sw_if_index",
1475 "sub id", "dot1ad", "tags", "outer id",
1476 "inner id", "exact", "default", "outer any", "inner any");
1477
1478 vec_foreach (sub, vam->sw_if_subif_table)
1479 {
1480 print (vam->ofp,
1481 "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
1482 sub->interface_name,
1483 sub->sw_if_index,
1484 sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
1485 sub->sub_number_of_tags, sub->sub_outer_vlan_id,
1486 sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
1487 sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
1488 if (sub->vtr_op != L2_VTR_DISABLED)
1489 {
1490 print (vam->ofp,
1491 " vlan-tag-rewrite - op: %-14s [ dot1q: %d "
1492 "tag1: %d tag2: %d ]",
1493 str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
1494 sub->vtr_tag1, sub->vtr_tag2);
1495 }
1496 }
1497
1498 return 0;
1499}
1500
1501static int
1502name_sort_cmp (void *a1, void *a2)
1503{
1504 name_sort_t *n1 = a1;
1505 name_sort_t *n2 = a2;
1506
1507 return strcmp ((char *) n1->name, (char *) n2->name);
1508}
1509
1510static int
1511dump_interface_table (vat_main_t * vam)
1512{
1513 hash_pair_t *p;
1514 name_sort_t *nses = 0, *ns;
1515
1516 if (vam->json_output)
1517 {
1518 clib_warning
1519 ("JSON output supported only for VPE API calls and dump_stats_table");
1520 return -99;
1521 }
1522
1523 /* *INDENT-OFF* */
1524 hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1525 ({
1526 vec_add2 (nses, ns, 1);
1527 ns->name = (u8 *)(p->key);
1528 ns->value = (u32) p->value[0];
1529 }));
1530 /* *INDENT-ON* */
1531
1532 vec_sort_with_function (nses, name_sort_cmp);
1533
1534 print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
1535 vec_foreach (ns, nses)
1536 {
1537 print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
1538 }
1539 vec_free (nses);
1540 return 0;
1541}
1542
Damjan Marion7cd468a2016-12-19 23:05:39 +01001543/*
Dave Barach59b25652017-09-10 15:04:27 -04001544 * Pass CLI buffers directly in the CLI_INBAND API message,
1545 * instead of an additional shared memory area.
Damjan Marion7cd468a2016-12-19 23:05:39 +01001546 */
1547static int
1548exec_inband (vat_main_t * vam)
1549{
1550 vl_api_cli_inband_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001551 unformat_input_t *i = vam->input;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001552 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001553
1554 if (vec_len (i->buffer) == 0)
1555 return -1;
1556
1557 if (vam->exec_mode == 0 && unformat (i, "mode"))
1558 {
1559 vam->exec_mode = 1;
1560 return 0;
1561 }
1562 if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
1563 {
1564 vam->exec_mode = 0;
1565 return 0;
1566 }
1567
1568 /*
1569 * In order for the CLI command to work, it
1570 * must be a vector ending in \n, not a C-string ending
1571 * in \n\0.
1572 */
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001573 M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
1574 vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001575
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001576 S (mp);
Dave Barach59b25652017-09-10 15:04:27 -04001577 W (ret);
1578 /* json responses may or may not include a useful reply... */
1579 if (vec_len (vam->cmd_reply))
Dave Barachcf5e8482017-10-17 11:48:29 -04001580 print (vam->ofp, "%v", (char *) (vam->cmd_reply));
Jon Loeliger56c7b012017-02-01 12:31:41 -06001581 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001582}
1583
Dave Barach59b25652017-09-10 15:04:27 -04001584int
1585exec (vat_main_t * vam)
1586{
1587 return exec_inband (vam);
1588}
1589
Damjan Marion7cd468a2016-12-19 23:05:39 +01001590static int
1591api_create_loopback (vat_main_t * vam)
1592{
1593 unformat_input_t *i = vam->input;
1594 vl_api_create_loopback_t *mp;
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001595 vl_api_create_loopback_instance_t *mp_lbi;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001596 u8 mac_address[6];
1597 u8 mac_set = 0;
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001598 u8 is_specified = 0;
1599 u32 user_instance = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001600 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001601
Dave Barachb7b92992018-10-17 10:38:51 -04001602 clib_memset (mac_address, 0, sizeof (mac_address));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001603
1604 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1605 {
1606 if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
1607 mac_set = 1;
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001608 if (unformat (i, "instance %d", &user_instance))
1609 is_specified = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001610 else
1611 break;
1612 }
1613
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001614 if (is_specified)
1615 {
1616 M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
1617 mp_lbi->is_specified = is_specified;
1618 if (is_specified)
1619 mp_lbi->user_instance = htonl (user_instance);
1620 if (mac_set)
1621 clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
1622 S (mp_lbi);
1623 }
1624 else
1625 {
1626 /* Construct the API message */
1627 M (CREATE_LOOPBACK, mp);
1628 if (mac_set)
1629 clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
1630 S (mp);
1631 }
Damjan Marion7cd468a2016-12-19 23:05:39 +01001632
Jon Loeliger56c7b012017-02-01 12:31:41 -06001633 W (ret);
1634 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001635}
1636
1637static int
1638api_delete_loopback (vat_main_t * vam)
1639{
1640 unformat_input_t *i = vam->input;
1641 vl_api_delete_loopback_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001642 u32 sw_if_index = ~0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001643 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001644
1645 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1646 {
1647 if (unformat (i, "sw_if_index %d", &sw_if_index))
1648 ;
1649 else
1650 break;
1651 }
1652
1653 if (sw_if_index == ~0)
1654 {
1655 errmsg ("missing sw_if_index");
1656 return -99;
1657 }
1658
1659 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001660 M (DELETE_LOOPBACK, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001661 mp->sw_if_index = ntohl (sw_if_index);
1662
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001663 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06001664 W (ret);
1665 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001666}
1667
1668static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01001669api_want_interface_events (vat_main_t * vam)
1670{
1671 unformat_input_t *i = vam->input;
1672 vl_api_want_interface_events_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001673 int enable = -1;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001674 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001675
1676 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1677 {
1678 if (unformat (i, "enable"))
1679 enable = 1;
1680 else if (unformat (i, "disable"))
1681 enable = 0;
1682 else
1683 break;
1684 }
1685
1686 if (enable == -1)
1687 {
1688 errmsg ("missing enable|disable");
1689 return -99;
1690 }
1691
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001692 M (WANT_INTERFACE_EVENTS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001693 mp->enable_disable = enable;
1694
1695 vam->interface_event_display = enable;
1696
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001697 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06001698 W (ret);
1699 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001700}
1701
1702
1703/* Note: non-static, called once to set up the initial intfc table */
1704int
1705api_sw_interface_dump (vat_main_t * vam)
1706{
1707 vl_api_sw_interface_dump_t *mp;
Jon Loeliger2d23eca2017-02-01 13:09:58 -06001708 vl_api_control_ping_t *mp_ping;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001709 hash_pair_t *p;
1710 name_sort_t *nses = 0, *ns;
1711 sw_interface_subif_t *sub = NULL;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001712 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001713
1714 /* Toss the old name table */
1715 /* *INDENT-OFF* */
1716 hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1717 ({
1718 vec_add2 (nses, ns, 1);
1719 ns->name = (u8 *)(p->key);
1720 ns->value = (u32) p->value[0];
1721 }));
1722 /* *INDENT-ON* */
1723
1724 hash_free (vam->sw_if_index_by_interface_name);
1725
1726 vec_foreach (ns, nses) vec_free (ns->name);
1727
1728 vec_free (nses);
1729
1730 vec_foreach (sub, vam->sw_if_subif_table)
1731 {
1732 vec_free (sub->interface_name);
1733 }
1734 vec_free (vam->sw_if_subif_table);
1735
1736 /* recreate the interface name hash table */
1737 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
1738
Dave Barachf72212e2018-01-11 10:25:07 -05001739 /*
1740 * Ask for all interface names. Otherwise, the epic catalog of
1741 * name filters becomes ridiculously long, and vat ends up needing
1742 * to be taught about new interface types.
1743 */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001744 M (SW_INTERFACE_DUMP, mp);
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001745 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001746
1747 /* Use a control ping for synchronization */
Dave Barach59b25652017-09-10 15:04:27 -04001748 MPING (CONTROL_PING, mp_ping);
Jon Loeliger2d23eca2017-02-01 13:09:58 -06001749 S (mp_ping);
1750
Jon Loeliger56c7b012017-02-01 12:31:41 -06001751 W (ret);
1752 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001753}
1754
1755static int
1756api_sw_interface_set_flags (vat_main_t * vam)
1757{
1758 unformat_input_t *i = vam->input;
1759 vl_api_sw_interface_set_flags_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001760 u32 sw_if_index;
1761 u8 sw_if_index_set = 0;
Neale Rannsa07bd702017-08-07 07:53:49 -07001762 u8 admin_up = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001763 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001764
1765 /* Parse args required to build the message */
1766 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1767 {
1768 if (unformat (i, "admin-up"))
1769 admin_up = 1;
1770 else if (unformat (i, "admin-down"))
1771 admin_up = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001772 else
1773 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1774 sw_if_index_set = 1;
1775 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1776 sw_if_index_set = 1;
1777 else
1778 break;
1779 }
1780
1781 if (sw_if_index_set == 0)
1782 {
1783 errmsg ("missing interface name or sw_if_index");
1784 return -99;
1785 }
1786
1787 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001788 M (SW_INTERFACE_SET_FLAGS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001789 mp->sw_if_index = ntohl (sw_if_index);
Jakub Grajciar053204a2019-03-18 13:17:53 +01001790 mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001791
1792 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001793 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001794
1795 /* Wait for a reply, return the good/bad news... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06001796 W (ret);
1797 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001798}
1799
1800static int
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001801api_sw_interface_set_rx_placement (vat_main_t * vam)
1802{
1803 unformat_input_t *i = vam->input;
1804 vl_api_sw_interface_set_rx_placement_t *mp;
1805 u32 sw_if_index;
1806 u8 sw_if_index_set = 0;
1807 int ret;
1808 u8 is_main = 0;
1809 u32 queue_id, thread_index;
1810
1811 /* Parse args required to build the message */
1812 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1813 {
1814 if (unformat (i, "queue %d", &queue_id))
1815 ;
1816 else if (unformat (i, "main"))
1817 is_main = 1;
1818 else if (unformat (i, "worker %d", &thread_index))
1819 ;
1820 else
1821 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1822 sw_if_index_set = 1;
1823 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1824 sw_if_index_set = 1;
1825 else
1826 break;
1827 }
1828
1829 if (sw_if_index_set == 0)
1830 {
1831 errmsg ("missing interface name or sw_if_index");
1832 return -99;
1833 }
1834
1835 if (is_main)
1836 thread_index = 0;
1837 /* Construct the API message */
1838 M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
1839 mp->sw_if_index = ntohl (sw_if_index);
1840 mp->worker_id = ntohl (thread_index);
1841 mp->queue_id = ntohl (queue_id);
1842 mp->is_main = is_main;
1843
1844 /* send it... */
1845 S (mp);
1846 /* Wait for a reply, return the good/bad news... */
1847 W (ret);
1848 return ret;
1849}
1850
Mohsin Kazmif0b42f42018-09-10 18:11:00 +02001851static void vl_api_sw_interface_rx_placement_details_t_handler
1852 (vl_api_sw_interface_rx_placement_details_t * mp)
1853{
1854 vat_main_t *vam = &vat_main;
1855 u32 worker_id = ntohl (mp->worker_id);
1856
1857 print (vam->ofp,
1858 "\n%-11d %-11s %-6d %-5d %-9s",
1859 ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
1860 worker_id, ntohl (mp->queue_id),
1861 (mp->mode ==
1862 1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
1863}
1864
1865static void vl_api_sw_interface_rx_placement_details_t_handler_json
1866 (vl_api_sw_interface_rx_placement_details_t * mp)
1867{
1868 vat_main_t *vam = &vat_main;
1869 vat_json_node_t *node = NULL;
1870
1871 if (VAT_JSON_ARRAY != vam->json_tree.type)
1872 {
1873 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1874 vat_json_init_array (&vam->json_tree);
1875 }
1876 node = vat_json_array_add (&vam->json_tree);
1877
1878 vat_json_init_object (node);
1879 vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
1880 vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
1881 vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
1882 vat_json_object_add_uint (node, "mode", mp->mode);
1883}
1884
1885static int
1886api_sw_interface_rx_placement_dump (vat_main_t * vam)
1887{
1888 unformat_input_t *i = vam->input;
1889 vl_api_sw_interface_rx_placement_dump_t *mp;
1890 vl_api_control_ping_t *mp_ping;
1891 int ret;
1892 u32 sw_if_index;
1893 u8 sw_if_index_set = 0;
1894
1895 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1896 {
1897 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1898 sw_if_index_set++;
1899 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1900 sw_if_index_set++;
1901 else
1902 break;
1903 }
1904
1905 print (vam->ofp,
1906 "\n%-11s %-11s %-6s %-5s %-4s",
1907 "sw_if_index", "main/worker", "thread", "queue", "mode");
1908
1909 /* Dump Interface rx placement */
1910 M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
1911
1912 if (sw_if_index_set)
1913 mp->sw_if_index = htonl (sw_if_index);
1914 else
1915 mp->sw_if_index = ~0;
1916
1917 S (mp);
1918
1919 /* Use a control ping for synchronization */
1920 MPING (CONTROL_PING, mp_ping);
1921 S (mp_ping);
1922
1923 W (ret);
1924 return ret;
1925}
1926
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001927static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01001928api_sw_interface_clear_stats (vat_main_t * vam)
1929{
1930 unformat_input_t *i = vam->input;
1931 vl_api_sw_interface_clear_stats_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001932 u32 sw_if_index;
1933 u8 sw_if_index_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001934 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001935
1936 /* Parse args required to build the message */
1937 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1938 {
1939 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1940 sw_if_index_set = 1;
1941 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1942 sw_if_index_set = 1;
1943 else
1944 break;
1945 }
1946
1947 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001948 M (SW_INTERFACE_CLEAR_STATS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001949
1950 if (sw_if_index_set == 1)
1951 mp->sw_if_index = ntohl (sw_if_index);
1952 else
1953 mp->sw_if_index = ~0;
1954
1955 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001956 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001957
1958 /* Wait for a reply, return the good/bad news... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06001959 W (ret);
1960 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001961}
1962
Damjan Marion7cd468a2016-12-19 23:05:39 +01001963static int
1964api_sw_interface_add_del_address (vat_main_t * vam)
1965{
1966 unformat_input_t *i = vam->input;
1967 vl_api_sw_interface_add_del_address_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001968 u32 sw_if_index;
1969 u8 sw_if_index_set = 0;
1970 u8 is_add = 1, del_all = 0;
1971 u32 address_length = 0;
1972 u8 v4_address_set = 0;
1973 u8 v6_address_set = 0;
1974 ip4_address_t v4address;
1975 ip6_address_t v6address;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001976 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001977
1978 /* Parse args required to build the message */
1979 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1980 {
1981 if (unformat (i, "del-all"))
1982 del_all = 1;
1983 else if (unformat (i, "del"))
1984 is_add = 0;
1985 else
1986 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
1987 sw_if_index_set = 1;
1988 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1989 sw_if_index_set = 1;
1990 else if (unformat (i, "%U/%d",
1991 unformat_ip4_address, &v4address, &address_length))
1992 v4_address_set = 1;
1993 else if (unformat (i, "%U/%d",
1994 unformat_ip6_address, &v6address, &address_length))
1995 v6_address_set = 1;
1996 else
1997 break;
1998 }
1999
2000 if (sw_if_index_set == 0)
2001 {
2002 errmsg ("missing interface name or sw_if_index");
2003 return -99;
2004 }
2005 if (v4_address_set && v6_address_set)
2006 {
2007 errmsg ("both v4 and v6 addresses set");
2008 return -99;
2009 }
2010 if (!v4_address_set && !v6_address_set && !del_all)
2011 {
2012 errmsg ("no addresses set");
2013 return -99;
2014 }
2015
2016 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002017 M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002018
2019 mp->sw_if_index = ntohl (sw_if_index);
2020 mp->is_add = is_add;
2021 mp->del_all = del_all;
2022 if (v6_address_set)
2023 {
Jakub Grajciar053204a2019-03-18 13:17:53 +01002024 mp->prefix.address.af = ADDRESS_IP6;
2025 clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002026 }
2027 else
2028 {
Jakub Grajciar053204a2019-03-18 13:17:53 +01002029 mp->prefix.address.af = ADDRESS_IP4;
2030 clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002031 }
Jakub Grajciar053204a2019-03-18 13:17:53 +01002032 mp->prefix.len = address_length;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002033
2034 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002035 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002036
2037 /* Wait for a reply, return good/bad news */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002038 W (ret);
2039 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002040}
2041
2042static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002043api_sw_interface_set_table (vat_main_t * vam)
2044{
2045 unformat_input_t *i = vam->input;
2046 vl_api_sw_interface_set_table_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002047 u32 sw_if_index, vrf_id = 0;
2048 u8 sw_if_index_set = 0;
2049 u8 is_ipv6 = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002050 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002051
2052 /* Parse args required to build the message */
2053 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2054 {
2055 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2056 sw_if_index_set = 1;
2057 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2058 sw_if_index_set = 1;
2059 else if (unformat (i, "vrf %d", &vrf_id))
2060 ;
2061 else if (unformat (i, "ipv6"))
2062 is_ipv6 = 1;
2063 else
2064 break;
2065 }
2066
2067 if (sw_if_index_set == 0)
2068 {
2069 errmsg ("missing interface name or sw_if_index");
2070 return -99;
2071 }
2072
2073 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002074 M (SW_INTERFACE_SET_TABLE, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002075
2076 mp->sw_if_index = ntohl (sw_if_index);
2077 mp->is_ipv6 = is_ipv6;
2078 mp->vrf_id = ntohl (vrf_id);
2079
2080 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002081 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002082
2083 /* Wait for a reply... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002084 W (ret);
2085 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002086}
2087
2088static void vl_api_sw_interface_get_table_reply_t_handler
2089 (vl_api_sw_interface_get_table_reply_t * mp)
2090{
2091 vat_main_t *vam = &vat_main;
2092
2093 print (vam->ofp, "%d", ntohl (mp->vrf_id));
2094
2095 vam->retval = ntohl (mp->retval);
2096 vam->result_ready = 1;
2097
2098}
2099
2100static void vl_api_sw_interface_get_table_reply_t_handler_json
2101 (vl_api_sw_interface_get_table_reply_t * mp)
2102{
2103 vat_main_t *vam = &vat_main;
2104 vat_json_node_t node;
2105
2106 vat_json_init_object (&node);
2107 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2108 vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
2109
2110 vat_json_print (vam->ofp, &node);
2111 vat_json_free (&node);
2112
2113 vam->retval = ntohl (mp->retval);
2114 vam->result_ready = 1;
2115}
2116
2117static int
2118api_sw_interface_get_table (vat_main_t * vam)
2119{
2120 unformat_input_t *i = vam->input;
2121 vl_api_sw_interface_get_table_t *mp;
2122 u32 sw_if_index;
2123 u8 sw_if_index_set = 0;
2124 u8 is_ipv6 = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002125 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002126
2127 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2128 {
2129 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2130 sw_if_index_set = 1;
2131 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2132 sw_if_index_set = 1;
2133 else if (unformat (i, "ipv6"))
2134 is_ipv6 = 1;
2135 else
2136 break;
2137 }
2138
2139 if (sw_if_index_set == 0)
2140 {
2141 errmsg ("missing interface name or sw_if_index");
2142 return -99;
2143 }
2144
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002145 M (SW_INTERFACE_GET_TABLE, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002146 mp->sw_if_index = htonl (sw_if_index);
2147 mp->is_ipv6 = is_ipv6;
2148
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002149 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002150 W (ret);
2151 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002152}
2153
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01002154uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00002155unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01002156{
jialv01082ebeb2019-09-10 00:23:55 +08002157 vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01002158 u32 x[4];
2159
2160 if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
2161 return 0;
2162
2163 addr->domain = x[0];
2164 addr->bus = x[1];
2165 addr->slot = x[2];
2166 addr->function = x[3];
2167
2168 return 1;
2169}
2170
Neale Ranns097fa662018-05-01 05:17:55 -07002171uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00002172unformat_fib_path (unformat_input_t *input, va_list *args)
Neale Ranns097fa662018-05-01 05:17:55 -07002173{
2174 vat_main_t *vam = va_arg (*args, vat_main_t *);
2175 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
2176 u32 weight, preference;
2177 mpls_label_t out_label;
2178
2179 clib_memset (path, 0, sizeof (*path));
2180 path->weight = 1;
2181 path->sw_if_index = ~0;
2182 path->rpf_id = ~0;
2183 path->n_labels = 0;
2184
2185 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2186 {
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00002187 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
2188 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
2189 &path->sw_if_index))
Neale Ranns097fa662018-05-01 05:17:55 -07002190 {
2191 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2192 }
2193 else if (unformat (input, "%U %U",
2194 unformat_vl_api_ip6_address,
2195 &path->nh.address.ip6,
2196 api_unformat_sw_if_index, vam, &path->sw_if_index))
2197 {
2198 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2199 }
2200 else if (unformat (input, "weight %u", &weight))
2201 {
2202 path->weight = weight;
2203 }
2204 else if (unformat (input, "preference %u", &preference))
2205 {
2206 path->preference = preference;
2207 }
2208 else if (unformat (input, "%U next-hop-table %d",
2209 unformat_vl_api_ip4_address,
2210 &path->nh.address.ip4, &path->table_id))
2211 {
2212 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2213 }
2214 else if (unformat (input, "%U next-hop-table %d",
2215 unformat_vl_api_ip6_address,
2216 &path->nh.address.ip6, &path->table_id))
2217 {
2218 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2219 }
2220 else if (unformat (input, "%U",
2221 unformat_vl_api_ip4_address, &path->nh.address.ip4))
2222 {
2223 /*
2224 * the recursive next-hops are by default in the default table
2225 */
2226 path->table_id = 0;
2227 path->sw_if_index = ~0;
2228 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2229 }
2230 else if (unformat (input, "%U",
2231 unformat_vl_api_ip6_address, &path->nh.address.ip6))
2232 {
2233 /*
2234 * the recursive next-hops are by default in the default table
2235 */
2236 path->table_id = 0;
2237 path->sw_if_index = ~0;
2238 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2239 }
2240 else if (unformat (input, "resolve-via-host"))
2241 {
2242 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
2243 }
2244 else if (unformat (input, "resolve-via-attached"))
2245 {
2246 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
2247 }
2248 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
2249 {
2250 path->type = FIB_API_PATH_TYPE_LOCAL;
2251 path->sw_if_index = ~0;
2252 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2253 }
2254 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
2255 {
2256 path->type = FIB_API_PATH_TYPE_LOCAL;
2257 path->sw_if_index = ~0;
2258 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2259 }
2260 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
2261 ;
2262 else if (unformat (input, "via-label %d", &path->nh.via_label))
2263 {
2264 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
2265 path->sw_if_index = ~0;
2266 }
2267 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
2268 {
2269 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
2270 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
2271 }
2272 else if (unformat (input, "local"))
2273 {
2274 path->type = FIB_API_PATH_TYPE_LOCAL;
2275 }
2276 else if (unformat (input, "out-labels"))
2277 {
2278 while (unformat (input, "%d", &out_label))
2279 {
2280 path->label_stack[path->n_labels].label = out_label;
2281 path->label_stack[path->n_labels].is_uniform = 0;
2282 path->label_stack[path->n_labels].ttl = 64;
2283 path->n_labels++;
2284 }
2285 }
2286 else if (unformat (input, "via"))
2287 {
2288 /* new path, back up and return */
2289 unformat_put_input (input);
2290 unformat_put_input (input);
2291 unformat_put_input (input);
2292 unformat_put_input (input);
2293 break;
2294 }
2295 else
2296 {
2297 return (0);
2298 }
2299 }
2300
2301 path->proto = ntohl (path->proto);
2302 path->type = ntohl (path->type);
2303 path->flags = ntohl (path->flags);
2304 path->table_id = ntohl (path->table_id);
2305 path->sw_if_index = ntohl (path->sw_if_index);
2306
2307 return (1);
2308}
2309
Neale Ranns28ab9cc2017-08-14 07:18:42 -07002310static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002311api_sw_interface_set_unnumbered (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002312{
2313 unformat_input_t *i = vam->input;
2314 vl_api_sw_interface_set_unnumbered_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002315 u32 sw_if_index;
2316 u32 unnum_sw_index = ~0;
2317 u8 is_add = 1;
2318 u8 sw_if_index_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002319 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002320
2321 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2322 {
2323 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2324 sw_if_index_set = 1;
2325 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2326 sw_if_index_set = 1;
2327 else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
2328 ;
2329 else if (unformat (i, "del"))
2330 is_add = 0;
2331 else
2332 {
2333 clib_warning ("parse error '%U'", format_unformat_error, i);
2334 return -99;
2335 }
2336 }
2337
2338 if (sw_if_index_set == 0)
2339 {
2340 errmsg ("missing interface name or sw_if_index");
2341 return -99;
2342 }
2343
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002344 M (SW_INTERFACE_SET_UNNUMBERED, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002345
2346 mp->sw_if_index = ntohl (sw_if_index);
2347 mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
2348 mp->is_add = is_add;
2349
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002350 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002351 W (ret);
2352 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002353}
2354
Damjan Marion7cd468a2016-12-19 23:05:39 +01002355static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002356api_create_vlan_subif (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002357{
2358 unformat_input_t *i = vam->input;
2359 vl_api_create_vlan_subif_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002360 u32 sw_if_index;
2361 u8 sw_if_index_set = 0;
2362 u32 vlan_id;
2363 u8 vlan_id_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002364 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002365
2366 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2367 {
2368 if (unformat (i, "sw_if_index %d", &sw_if_index))
2369 sw_if_index_set = 1;
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002370 else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
Damjan Marion7cd468a2016-12-19 23:05:39 +01002371 sw_if_index_set = 1;
2372 else if (unformat (i, "vlan %d", &vlan_id))
2373 vlan_id_set = 1;
2374 else
2375 {
2376 clib_warning ("parse error '%U'", format_unformat_error, i);
2377 return -99;
2378 }
2379 }
2380
2381 if (sw_if_index_set == 0)
2382 {
2383 errmsg ("missing interface name or sw_if_index");
2384 return -99;
2385 }
2386
2387 if (vlan_id_set == 0)
2388 {
2389 errmsg ("missing vlan_id");
2390 return -99;
2391 }
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002392 M (CREATE_VLAN_SUBIF, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002393
2394 mp->sw_if_index = ntohl (sw_if_index);
2395 mp->vlan_id = ntohl (vlan_id);
2396
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002397 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002398 W (ret);
2399 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002400}
2401
2402#define foreach_create_subif_bit \
2403_(no_tags) \
2404_(one_tag) \
2405_(two_tags) \
2406_(dot1ad) \
2407_(exact_match) \
2408_(default_sub) \
2409_(outer_vlan_id_any) \
2410_(inner_vlan_id_any)
2411
Jakub Grajciar053204a2019-03-18 13:17:53 +01002412#define foreach_create_subif_flag \
2413_(0, "no_tags") \
2414_(1, "one_tag") \
2415_(2, "two_tags") \
2416_(3, "dot1ad") \
2417_(4, "exact_match") \
2418_(5, "default_sub") \
2419_(6, "outer_vlan_id_any") \
2420_(7, "inner_vlan_id_any")
2421
Damjan Marion7cd468a2016-12-19 23:05:39 +01002422static int
2423api_create_subif (vat_main_t * vam)
2424{
2425 unformat_input_t *i = vam->input;
2426 vl_api_create_subif_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002427 u32 sw_if_index;
2428 u8 sw_if_index_set = 0;
2429 u32 sub_id;
2430 u8 sub_id_set = 0;
Jakub Grajciar053204a2019-03-18 13:17:53 +01002431 u32 __attribute__ ((unused)) no_tags = 0;
2432 u32 __attribute__ ((unused)) one_tag = 0;
2433 u32 __attribute__ ((unused)) two_tags = 0;
2434 u32 __attribute__ ((unused)) dot1ad = 0;
2435 u32 __attribute__ ((unused)) exact_match = 0;
2436 u32 __attribute__ ((unused)) default_sub = 0;
2437 u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
2438 u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002439 u32 tmp;
2440 u16 outer_vlan_id = 0;
2441 u16 inner_vlan_id = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002442 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002443
2444 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2445 {
2446 if (unformat (i, "sw_if_index %d", &sw_if_index))
2447 sw_if_index_set = 1;
2448 else
2449 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2450 sw_if_index_set = 1;
2451 else if (unformat (i, "sub_id %d", &sub_id))
2452 sub_id_set = 1;
2453 else if (unformat (i, "outer_vlan_id %d", &tmp))
2454 outer_vlan_id = tmp;
2455 else if (unformat (i, "inner_vlan_id %d", &tmp))
2456 inner_vlan_id = tmp;
2457
2458#define _(a) else if (unformat (i, #a)) a = 1 ;
2459 foreach_create_subif_bit
2460#undef _
2461 else
2462 {
2463 clib_warning ("parse error '%U'", format_unformat_error, i);
2464 return -99;
2465 }
2466 }
2467
2468 if (sw_if_index_set == 0)
2469 {
2470 errmsg ("missing interface name or sw_if_index");
2471 return -99;
2472 }
2473
2474 if (sub_id_set == 0)
2475 {
2476 errmsg ("missing sub_id");
2477 return -99;
2478 }
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002479 M (CREATE_SUBIF, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002480
2481 mp->sw_if_index = ntohl (sw_if_index);
2482 mp->sub_id = ntohl (sub_id);
2483
Jakub Grajciar053204a2019-03-18 13:17:53 +01002484#define _(a,b) mp->sub_if_flags |= (1 << a);
2485 foreach_create_subif_flag;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002486#undef _
2487
2488 mp->outer_vlan_id = ntohs (outer_vlan_id);
2489 mp->inner_vlan_id = ntohs (inner_vlan_id);
2490
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002491 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002492 W (ret);
2493 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002494}
2495
Pablo Camarillofb380952016-12-07 18:34:18 +01002496u8 is_del;
2497u8 localsid_addr[16];
2498u8 end_psp;
2499u8 behavior;
2500u32 sw_if_index;
2501u32 vlan_index;
2502u32 fib_table;
2503u8 nh_addr[16];
2504
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002505#define foreach_tcp_proto_field \
2506 _ (src_port) \
2507 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002508
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002509#define foreach_udp_proto_field \
2510 _ (src_port) \
2511 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002512
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002513#define foreach_ip4_proto_field \
2514 _ (src_address) \
2515 _ (dst_address) \
2516 _ (tos) \
2517 _ (length) \
2518 _ (fragment_id) \
2519 _ (ttl) \
2520 _ (protocol) \
2521 _ (checksum)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002522
Dave Barach4a3f69c2017-02-22 12:44:56 -05002523typedef struct
2524{
2525 u16 src_port, dst_port;
2526} tcpudp_header_t;
2527
2528#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01002529uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002530unformat_tcp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002531{
2532 u8 **maskp = va_arg (*args, u8 **);
2533 u8 *mask = 0;
2534 u8 found_something = 0;
2535 tcp_header_t *tcp;
2536
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002537#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002538 foreach_tcp_proto_field;
2539#undef _
2540
2541 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2542 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002543 if (0)
2544 ;
2545#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002546 foreach_tcp_proto_field
2547#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002548 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002549 }
2550
2551#define _(a) found_something += a;
2552 foreach_tcp_proto_field;
2553#undef _
2554
2555 if (found_something == 0)
2556 return 0;
2557
2558 vec_validate (mask, sizeof (*tcp) - 1);
2559
2560 tcp = (tcp_header_t *) mask;
2561
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002562#define _(a) \
2563 if (a) \
2564 clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002565 foreach_tcp_proto_field;
2566#undef _
2567
2568 *maskp = mask;
2569 return 1;
2570}
2571
2572uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002573unformat_udp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002574{
2575 u8 **maskp = va_arg (*args, u8 **);
2576 u8 *mask = 0;
2577 u8 found_something = 0;
2578 udp_header_t *udp;
2579
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002580#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002581 foreach_udp_proto_field;
2582#undef _
2583
2584 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2585 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002586 if (0)
2587 ;
2588#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002589 foreach_udp_proto_field
2590#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002591 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002592 }
2593
2594#define _(a) found_something += a;
2595 foreach_udp_proto_field;
2596#undef _
2597
2598 if (found_something == 0)
2599 return 0;
2600
2601 vec_validate (mask, sizeof (*udp) - 1);
2602
2603 udp = (udp_header_t *) mask;
2604
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002605#define _(a) \
2606 if (a) \
2607 clib_memset (&udp->a, 0xff, sizeof (udp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002608 foreach_udp_proto_field;
2609#undef _
2610
2611 *maskp = mask;
2612 return 1;
2613}
2614
Damjan Marion7cd468a2016-12-19 23:05:39 +01002615uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002616unformat_l4_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002617{
2618 u8 **maskp = va_arg (*args, u8 **);
2619 u16 src_port = 0, dst_port = 0;
2620 tcpudp_header_t *tcpudp;
2621
2622 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2623 {
2624 if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
2625 return 1;
2626 else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
2627 return 1;
2628 else if (unformat (input, "src_port"))
2629 src_port = 0xFFFF;
2630 else if (unformat (input, "dst_port"))
2631 dst_port = 0xFFFF;
2632 else
2633 return 0;
2634 }
2635
2636 if (!src_port && !dst_port)
2637 return 0;
2638
2639 u8 *mask = 0;
2640 vec_validate (mask, sizeof (tcpudp_header_t) - 1);
2641
2642 tcpudp = (tcpudp_header_t *) mask;
2643 tcpudp->src_port = src_port;
2644 tcpudp->dst_port = dst_port;
2645
2646 *maskp = mask;
2647
2648 return 1;
2649}
2650
2651uword
2652unformat_ip4_mask (unformat_input_t * input, va_list * args)
2653{
2654 u8 **maskp = va_arg (*args, u8 **);
2655 u8 *mask = 0;
2656 u8 found_something = 0;
2657 ip4_header_t *ip;
2658
2659#define _(a) u8 a=0;
2660 foreach_ip4_proto_field;
2661#undef _
2662 u8 version = 0;
2663 u8 hdr_length = 0;
2664
2665
2666 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2667 {
2668 if (unformat (input, "version"))
2669 version = 1;
2670 else if (unformat (input, "hdr_length"))
2671 hdr_length = 1;
2672 else if (unformat (input, "src"))
2673 src_address = 1;
2674 else if (unformat (input, "dst"))
2675 dst_address = 1;
2676 else if (unformat (input, "proto"))
2677 protocol = 1;
2678
2679#define _(a) else if (unformat (input, #a)) a=1;
2680 foreach_ip4_proto_field
2681#undef _
2682 else
2683 break;
2684 }
2685
2686#define _(a) found_something += a;
2687 foreach_ip4_proto_field;
2688#undef _
2689
2690 if (found_something == 0)
2691 return 0;
2692
2693 vec_validate (mask, sizeof (*ip) - 1);
2694
2695 ip = (ip4_header_t *) mask;
2696
Dave Barachb7b92992018-10-17 10:38:51 -04002697#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002698 foreach_ip4_proto_field;
2699#undef _
2700
2701 ip->ip_version_and_header_length = 0;
2702
2703 if (version)
2704 ip->ip_version_and_header_length |= 0xF0;
2705
2706 if (hdr_length)
2707 ip->ip_version_and_header_length |= 0x0F;
2708
2709 *maskp = mask;
2710 return 1;
2711}
2712
2713#define foreach_ip6_proto_field \
2714_(src_address) \
2715_(dst_address) \
2716_(payload_length) \
2717_(hop_limit) \
2718_(protocol)
2719
2720uword
2721unformat_ip6_mask (unformat_input_t * input, va_list * args)
2722{
2723 u8 **maskp = va_arg (*args, u8 **);
2724 u8 *mask = 0;
2725 u8 found_something = 0;
2726 ip6_header_t *ip;
2727 u32 ip_version_traffic_class_and_flow_label;
2728
2729#define _(a) u8 a=0;
2730 foreach_ip6_proto_field;
2731#undef _
2732 u8 version = 0;
2733 u8 traffic_class = 0;
2734 u8 flow_label = 0;
2735
2736 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2737 {
2738 if (unformat (input, "version"))
2739 version = 1;
2740 else if (unformat (input, "traffic-class"))
2741 traffic_class = 1;
2742 else if (unformat (input, "flow-label"))
2743 flow_label = 1;
2744 else if (unformat (input, "src"))
2745 src_address = 1;
2746 else if (unformat (input, "dst"))
2747 dst_address = 1;
2748 else if (unformat (input, "proto"))
2749 protocol = 1;
2750
2751#define _(a) else if (unformat (input, #a)) a=1;
2752 foreach_ip6_proto_field
2753#undef _
2754 else
2755 break;
2756 }
2757
2758#define _(a) found_something += a;
2759 foreach_ip6_proto_field;
2760#undef _
2761
2762 if (found_something == 0)
2763 return 0;
2764
2765 vec_validate (mask, sizeof (*ip) - 1);
2766
2767 ip = (ip6_header_t *) mask;
2768
Dave Barachb7b92992018-10-17 10:38:51 -04002769#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002770 foreach_ip6_proto_field;
2771#undef _
2772
2773 ip_version_traffic_class_and_flow_label = 0;
2774
2775 if (version)
2776 ip_version_traffic_class_and_flow_label |= 0xF0000000;
2777
2778 if (traffic_class)
2779 ip_version_traffic_class_and_flow_label |= 0x0FF00000;
2780
2781 if (flow_label)
2782 ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
2783
2784 ip->ip_version_traffic_class_and_flow_label =
2785 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
2786
2787 *maskp = mask;
2788 return 1;
2789}
2790
2791uword
2792unformat_l3_mask (unformat_input_t * input, va_list * args)
2793{
2794 u8 **maskp = va_arg (*args, u8 **);
2795
2796 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2797 {
2798 if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
2799 return 1;
2800 else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
2801 return 1;
2802 else
2803 break;
2804 }
2805 return 0;
2806}
2807
2808uword
2809unformat_l2_mask (unformat_input_t * input, va_list * args)
2810{
2811 u8 **maskp = va_arg (*args, u8 **);
2812 u8 *mask = 0;
2813 u8 src = 0;
2814 u8 dst = 0;
2815 u8 proto = 0;
2816 u8 tag1 = 0;
2817 u8 tag2 = 0;
2818 u8 ignore_tag1 = 0;
2819 u8 ignore_tag2 = 0;
2820 u8 cos1 = 0;
2821 u8 cos2 = 0;
2822 u8 dot1q = 0;
2823 u8 dot1ad = 0;
2824 int len = 14;
2825
2826 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2827 {
2828 if (unformat (input, "src"))
2829 src = 1;
2830 else if (unformat (input, "dst"))
2831 dst = 1;
2832 else if (unformat (input, "proto"))
2833 proto = 1;
2834 else if (unformat (input, "tag1"))
2835 tag1 = 1;
2836 else if (unformat (input, "tag2"))
2837 tag2 = 1;
2838 else if (unformat (input, "ignore-tag1"))
2839 ignore_tag1 = 1;
2840 else if (unformat (input, "ignore-tag2"))
2841 ignore_tag2 = 1;
2842 else if (unformat (input, "cos1"))
2843 cos1 = 1;
2844 else if (unformat (input, "cos2"))
2845 cos2 = 1;
2846 else if (unformat (input, "dot1q"))
2847 dot1q = 1;
2848 else if (unformat (input, "dot1ad"))
2849 dot1ad = 1;
2850 else
2851 break;
2852 }
2853 if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
2854 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
2855 return 0;
2856
2857 if (tag1 || ignore_tag1 || cos1 || dot1q)
2858 len = 18;
2859 if (tag2 || ignore_tag2 || cos2 || dot1ad)
2860 len = 22;
2861
2862 vec_validate (mask, len - 1);
2863
2864 if (dst)
Dave Barachb7b92992018-10-17 10:38:51 -04002865 clib_memset (mask, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002866
2867 if (src)
Dave Barachb7b92992018-10-17 10:38:51 -04002868 clib_memset (mask + 6, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002869
2870 if (tag2 || dot1ad)
2871 {
2872 /* inner vlan tag */
2873 if (tag2)
2874 {
2875 mask[19] = 0xff;
2876 mask[18] = 0x0f;
2877 }
2878 if (cos2)
2879 mask[18] |= 0xe0;
2880 if (proto)
2881 mask[21] = mask[20] = 0xff;
2882 if (tag1)
2883 {
2884 mask[15] = 0xff;
2885 mask[14] = 0x0f;
2886 }
2887 if (cos1)
2888 mask[14] |= 0xe0;
2889 *maskp = mask;
2890 return 1;
2891 }
2892 if (tag1 | dot1q)
2893 {
2894 if (tag1)
2895 {
2896 mask[15] = 0xff;
2897 mask[14] = 0x0f;
2898 }
2899 if (cos1)
2900 mask[14] |= 0xe0;
2901 if (proto)
2902 mask[16] = mask[17] = 0xff;
2903
2904 *maskp = mask;
2905 return 1;
2906 }
2907 if (cos2)
2908 mask[18] |= 0xe0;
2909 if (cos1)
2910 mask[14] |= 0xe0;
2911 if (proto)
2912 mask[12] = mask[13] = 0xff;
2913
2914 *maskp = mask;
2915 return 1;
2916}
2917
2918uword
2919unformat_classify_mask (unformat_input_t * input, va_list * args)
2920{
2921 u8 **maskp = va_arg (*args, u8 **);
2922 u32 *skipp = va_arg (*args, u32 *);
2923 u32 *matchp = va_arg (*args, u32 *);
2924 u32 match;
2925 u8 *mask = 0;
2926 u8 *l2 = 0;
2927 u8 *l3 = 0;
2928 u8 *l4 = 0;
2929 int i;
2930
2931 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2932 {
2933 if (unformat (input, "hex %U", unformat_hex_string, &mask))
2934 ;
2935 else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
2936 ;
2937 else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
2938 ;
2939 else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
2940 ;
2941 else
2942 break;
2943 }
2944
2945 if (l4 && !l3)
2946 {
2947 vec_free (mask);
2948 vec_free (l2);
2949 vec_free (l4);
2950 return 0;
2951 }
2952
2953 if (mask || l2 || l3 || l4)
2954 {
2955 if (l2 || l3 || l4)
2956 {
2957 /* "With a free Ethernet header in every package" */
2958 if (l2 == 0)
2959 vec_validate (l2, 13);
2960 mask = l2;
2961 if (vec_len (l3))
2962 {
2963 vec_append (mask, l3);
2964 vec_free (l3);
2965 }
2966 if (vec_len (l4))
2967 {
2968 vec_append (mask, l4);
2969 vec_free (l4);
2970 }
2971 }
2972
2973 /* Scan forward looking for the first significant mask octet */
2974 for (i = 0; i < vec_len (mask); i++)
2975 if (mask[i])
2976 break;
2977
2978 /* compute (skip, match) params */
2979 *skipp = i / sizeof (u32x4);
2980 vec_delete (mask, *skipp * sizeof (u32x4), 0);
2981
2982 /* Pad mask to an even multiple of the vector size */
2983 while (vec_len (mask) % sizeof (u32x4))
2984 vec_add1 (mask, 0);
2985
2986 match = vec_len (mask) / sizeof (u32x4);
2987
2988 for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
2989 {
2990 u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
2991 if (*tmp || *(tmp + 1))
2992 break;
2993 match--;
2994 }
2995 if (match == 0)
2996 clib_warning ("BUG: match 0");
2997
2998 _vec_len (mask) = match * sizeof (u32x4);
2999
3000 *matchp = match;
3001 *maskp = mask;
3002
3003 return 1;
3004 }
3005
3006 return 0;
3007}
Dave Barach4a3f69c2017-02-22 12:44:56 -05003008#endif /* VPP_API_TEST_BUILTIN */
Damjan Marion7cd468a2016-12-19 23:05:39 +01003009
3010#define foreach_l2_next \
3011_(drop, DROP) \
3012_(ethernet, ETHERNET_INPUT) \
3013_(ip4, IP4_INPUT) \
3014_(ip6, IP6_INPUT)
3015
3016uword
3017unformat_l2_next_index (unformat_input_t * input, va_list * args)
3018{
3019 u32 *miss_next_indexp = va_arg (*args, u32 *);
3020 u32 next_index = 0;
3021 u32 tmp;
3022
3023#define _(n,N) \
3024 if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
3025 foreach_l2_next;
3026#undef _
3027
3028 if (unformat (input, "%d", &tmp))
3029 {
3030 next_index = tmp;
3031 goto out;
3032 }
3033
3034 return 0;
3035
3036out:
3037 *miss_next_indexp = next_index;
3038 return 1;
3039}
3040
3041#define foreach_ip_next \
3042_(drop, DROP) \
3043_(local, LOCAL) \
3044_(rewrite, REWRITE)
3045
3046uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05003047api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003048{
3049 u32 *miss_next_indexp = va_arg (*args, u32 *);
3050 u32 next_index = 0;
3051 u32 tmp;
3052
3053#define _(n,N) \
3054 if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
3055 foreach_ip_next;
3056#undef _
3057
3058 if (unformat (input, "%d", &tmp))
3059 {
3060 next_index = tmp;
3061 goto out;
3062 }
3063
3064 return 0;
3065
3066out:
3067 *miss_next_indexp = next_index;
3068 return 1;
3069}
3070
3071#define foreach_acl_next \
3072_(deny, DENY)
3073
3074uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05003075api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003076{
3077 u32 *miss_next_indexp = va_arg (*args, u32 *);
3078 u32 next_index = 0;
3079 u32 tmp;
3080
3081#define _(n,N) \
3082 if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
3083 foreach_acl_next;
3084#undef _
3085
3086 if (unformat (input, "permit"))
3087 {
3088 next_index = ~0;
3089 goto out;
3090 }
3091 else if (unformat (input, "%d", &tmp))
3092 {
3093 next_index = tmp;
3094 goto out;
3095 }
3096
3097 return 0;
3098
3099out:
3100 *miss_next_indexp = next_index;
3101 return 1;
3102}
3103
3104uword
3105unformat_policer_precolor (unformat_input_t * input, va_list * args)
3106{
3107 u32 *r = va_arg (*args, u32 *);
3108
3109 if (unformat (input, "conform-color"))
3110 *r = POLICE_CONFORM;
3111 else if (unformat (input, "exceed-color"))
3112 *r = POLICE_EXCEED;
3113 else
3114 return 0;
3115
3116 return 1;
3117}
3118
Dave Barach4a3f69c2017-02-22 12:44:56 -05003119#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01003120uword
3121unformat_l4_match (unformat_input_t * input, va_list * args)
3122{
3123 u8 **matchp = va_arg (*args, u8 **);
3124
3125 u8 *proto_header = 0;
3126 int src_port = 0;
3127 int dst_port = 0;
3128
3129 tcpudp_header_t h;
3130
3131 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3132 {
3133 if (unformat (input, "src_port %d", &src_port))
3134 ;
3135 else if (unformat (input, "dst_port %d", &dst_port))
3136 ;
3137 else
3138 return 0;
3139 }
3140
3141 h.src_port = clib_host_to_net_u16 (src_port);
3142 h.dst_port = clib_host_to_net_u16 (dst_port);
3143 vec_validate (proto_header, sizeof (h) - 1);
3144 memcpy (proto_header, &h, sizeof (h));
3145
3146 *matchp = proto_header;
3147
3148 return 1;
3149}
3150
3151uword
3152unformat_ip4_match (unformat_input_t * input, va_list * args)
3153{
3154 u8 **matchp = va_arg (*args, u8 **);
3155 u8 *match = 0;
3156 ip4_header_t *ip;
3157 int version = 0;
3158 u32 version_val;
3159 int hdr_length = 0;
3160 u32 hdr_length_val;
3161 int src = 0, dst = 0;
3162 ip4_address_t src_val, dst_val;
3163 int proto = 0;
3164 u32 proto_val;
3165 int tos = 0;
3166 u32 tos_val;
3167 int length = 0;
3168 u32 length_val;
3169 int fragment_id = 0;
3170 u32 fragment_id_val;
3171 int ttl = 0;
3172 int ttl_val;
3173 int checksum = 0;
3174 u32 checksum_val;
3175
3176 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3177 {
3178 if (unformat (input, "version %d", &version_val))
3179 version = 1;
3180 else if (unformat (input, "hdr_length %d", &hdr_length_val))
3181 hdr_length = 1;
3182 else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
3183 src = 1;
3184 else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
3185 dst = 1;
3186 else if (unformat (input, "proto %d", &proto_val))
3187 proto = 1;
3188 else if (unformat (input, "tos %d", &tos_val))
3189 tos = 1;
3190 else if (unformat (input, "length %d", &length_val))
3191 length = 1;
3192 else if (unformat (input, "fragment_id %d", &fragment_id_val))
3193 fragment_id = 1;
3194 else if (unformat (input, "ttl %d", &ttl_val))
3195 ttl = 1;
3196 else if (unformat (input, "checksum %d", &checksum_val))
3197 checksum = 1;
3198 else
3199 break;
3200 }
3201
3202 if (version + hdr_length + src + dst + proto + tos + length + fragment_id
3203 + ttl + checksum == 0)
3204 return 0;
3205
3206 /*
3207 * Aligned because we use the real comparison functions
3208 */
3209 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
3210
3211 ip = (ip4_header_t *) match;
3212
3213 /* These are realistically matched in practice */
3214 if (src)
3215 ip->src_address.as_u32 = src_val.as_u32;
3216
3217 if (dst)
3218 ip->dst_address.as_u32 = dst_val.as_u32;
3219
3220 if (proto)
3221 ip->protocol = proto_val;
3222
3223
3224 /* These are not, but they're included for completeness */
3225 if (version)
3226 ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
3227
3228 if (hdr_length)
3229 ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
3230
3231 if (tos)
3232 ip->tos = tos_val;
3233
3234 if (length)
3235 ip->length = clib_host_to_net_u16 (length_val);
3236
3237 if (ttl)
3238 ip->ttl = ttl_val;
3239
3240 if (checksum)
3241 ip->checksum = clib_host_to_net_u16 (checksum_val);
3242
3243 *matchp = match;
3244 return 1;
3245}
3246
3247uword
3248unformat_ip6_match (unformat_input_t * input, va_list * args)
3249{
3250 u8 **matchp = va_arg (*args, u8 **);
3251 u8 *match = 0;
3252 ip6_header_t *ip;
3253 int version = 0;
3254 u32 version_val;
3255 u8 traffic_class = 0;
3256 u32 traffic_class_val = 0;
3257 u8 flow_label = 0;
3258 u8 flow_label_val;
3259 int src = 0, dst = 0;
3260 ip6_address_t src_val, dst_val;
3261 int proto = 0;
3262 u32 proto_val;
3263 int payload_length = 0;
3264 u32 payload_length_val;
3265 int hop_limit = 0;
3266 int hop_limit_val;
3267 u32 ip_version_traffic_class_and_flow_label;
3268
3269 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3270 {
3271 if (unformat (input, "version %d", &version_val))
3272 version = 1;
3273 else if (unformat (input, "traffic_class %d", &traffic_class_val))
3274 traffic_class = 1;
3275 else if (unformat (input, "flow_label %d", &flow_label_val))
3276 flow_label = 1;
3277 else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
3278 src = 1;
3279 else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
3280 dst = 1;
3281 else if (unformat (input, "proto %d", &proto_val))
3282 proto = 1;
3283 else if (unformat (input, "payload_length %d", &payload_length_val))
3284 payload_length = 1;
3285 else if (unformat (input, "hop_limit %d", &hop_limit_val))
3286 hop_limit = 1;
3287 else
3288 break;
3289 }
3290
3291 if (version + traffic_class + flow_label + src + dst + proto +
3292 payload_length + hop_limit == 0)
3293 return 0;
3294
3295 /*
3296 * Aligned because we use the real comparison functions
3297 */
3298 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
3299
3300 ip = (ip6_header_t *) match;
3301
3302 if (src)
3303 clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
3304
3305 if (dst)
3306 clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
3307
3308 if (proto)
3309 ip->protocol = proto_val;
3310
3311 ip_version_traffic_class_and_flow_label = 0;
3312
3313 if (version)
3314 ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
3315
3316 if (traffic_class)
3317 ip_version_traffic_class_and_flow_label |=
3318 (traffic_class_val & 0xFF) << 20;
3319
3320 if (flow_label)
3321 ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
3322
3323 ip->ip_version_traffic_class_and_flow_label =
3324 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
3325
3326 if (payload_length)
3327 ip->payload_length = clib_host_to_net_u16 (payload_length_val);
3328
3329 if (hop_limit)
3330 ip->hop_limit = hop_limit_val;
3331
3332 *matchp = match;
3333 return 1;
3334}
3335
3336uword
3337unformat_l3_match (unformat_input_t * input, va_list * args)
3338{
3339 u8 **matchp = va_arg (*args, u8 **);
3340
3341 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3342 {
3343 if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
3344 return 1;
3345 else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
3346 return 1;
3347 else
3348 break;
3349 }
3350 return 0;
3351}
3352
3353uword
3354unformat_vlan_tag (unformat_input_t * input, va_list * args)
3355{
3356 u8 *tagp = va_arg (*args, u8 *);
3357 u32 tag;
3358
3359 if (unformat (input, "%d", &tag))
3360 {
3361 tagp[0] = (tag >> 8) & 0x0F;
3362 tagp[1] = tag & 0xFF;
3363 return 1;
3364 }
3365
3366 return 0;
3367}
3368
3369uword
3370unformat_l2_match (unformat_input_t * input, va_list * args)
3371{
3372 u8 **matchp = va_arg (*args, u8 **);
3373 u8 *match = 0;
3374 u8 src = 0;
3375 u8 src_val[6];
3376 u8 dst = 0;
3377 u8 dst_val[6];
3378 u8 proto = 0;
3379 u16 proto_val;
3380 u8 tag1 = 0;
3381 u8 tag1_val[2];
3382 u8 tag2 = 0;
3383 u8 tag2_val[2];
3384 int len = 14;
3385 u8 ignore_tag1 = 0;
3386 u8 ignore_tag2 = 0;
3387 u8 cos1 = 0;
3388 u8 cos2 = 0;
3389 u32 cos1_val = 0;
3390 u32 cos2_val = 0;
3391
3392 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3393 {
3394 if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
3395 src = 1;
3396 else
3397 if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
3398 dst = 1;
3399 else if (unformat (input, "proto %U",
3400 unformat_ethernet_type_host_byte_order, &proto_val))
3401 proto = 1;
3402 else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
3403 tag1 = 1;
3404 else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
3405 tag2 = 1;
3406 else if (unformat (input, "ignore-tag1"))
3407 ignore_tag1 = 1;
3408 else if (unformat (input, "ignore-tag2"))
3409 ignore_tag2 = 1;
3410 else if (unformat (input, "cos1 %d", &cos1_val))
3411 cos1 = 1;
3412 else if (unformat (input, "cos2 %d", &cos2_val))
3413 cos2 = 1;
3414 else
3415 break;
3416 }
3417 if ((src + dst + proto + tag1 + tag2 +
3418 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
3419 return 0;
3420
3421 if (tag1 || ignore_tag1 || cos1)
3422 len = 18;
3423 if (tag2 || ignore_tag2 || cos2)
3424 len = 22;
3425
3426 vec_validate_aligned (match, len - 1, sizeof (u32x4));
3427
3428 if (dst)
3429 clib_memcpy (match, dst_val, 6);
3430
3431 if (src)
3432 clib_memcpy (match + 6, src_val, 6);
3433
3434 if (tag2)
3435 {
3436 /* inner vlan tag */
3437 match[19] = tag2_val[1];
3438 match[18] = tag2_val[0];
3439 if (cos2)
3440 match[18] |= (cos2_val & 0x7) << 5;
3441 if (proto)
3442 {
3443 match[21] = proto_val & 0xff;
3444 match[20] = proto_val >> 8;
3445 }
3446 if (tag1)
3447 {
3448 match[15] = tag1_val[1];
3449 match[14] = tag1_val[0];
3450 }
3451 if (cos1)
3452 match[14] |= (cos1_val & 0x7) << 5;
3453 *matchp = match;
3454 return 1;
3455 }
3456 if (tag1)
3457 {
3458 match[15] = tag1_val[1];
3459 match[14] = tag1_val[0];
3460 if (proto)
3461 {
3462 match[17] = proto_val & 0xff;
3463 match[16] = proto_val >> 8;
3464 }
3465 if (cos1)
3466 match[14] |= (cos1_val & 0x7) << 5;
3467
3468 *matchp = match;
3469 return 1;
3470 }
3471 if (cos2)
3472 match[18] |= (cos2_val & 0x7) << 5;
3473 if (cos1)
3474 match[14] |= (cos1_val & 0x7) << 5;
3475 if (proto)
3476 {
3477 match[13] = proto_val & 0xff;
3478 match[12] = proto_val >> 8;
3479 }
3480
3481 *matchp = match;
3482 return 1;
3483}
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -07003484
3485uword
3486unformat_qos_source (unformat_input_t * input, va_list * args)
3487{
3488 int *qs = va_arg (*args, int *);
3489
3490 if (unformat (input, "ip"))
3491 *qs = QOS_SOURCE_IP;
3492 else if (unformat (input, "mpls"))
3493 *qs = QOS_SOURCE_MPLS;
3494 else if (unformat (input, "ext"))
3495 *qs = QOS_SOURCE_EXT;
3496 else if (unformat (input, "vlan"))
3497 *qs = QOS_SOURCE_VLAN;
3498 else
3499 return 0;
3500
3501 return 1;
3502}
Dave Barach4a3f69c2017-02-22 12:44:56 -05003503#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01003504
3505uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05003506api_unformat_classify_match (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003507{
3508 u8 **matchp = va_arg (*args, u8 **);
3509 u32 skip_n_vectors = va_arg (*args, u32);
3510 u32 match_n_vectors = va_arg (*args, u32);
3511
3512 u8 *match = 0;
3513 u8 *l2 = 0;
3514 u8 *l3 = 0;
3515 u8 *l4 = 0;
3516
3517 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3518 {
3519 if (unformat (input, "hex %U", unformat_hex_string, &match))
3520 ;
3521 else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
3522 ;
3523 else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
3524 ;
3525 else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
3526 ;
3527 else
3528 break;
3529 }
3530
3531 if (l4 && !l3)
3532 {
3533 vec_free (match);
3534 vec_free (l2);
3535 vec_free (l4);
3536 return 0;
3537 }
3538
3539 if (match || l2 || l3 || l4)
3540 {
3541 if (l2 || l3 || l4)
3542 {
3543 /* "Win a free Ethernet header in every packet" */
3544 if (l2 == 0)
3545 vec_validate_aligned (l2, 13, sizeof (u32x4));
3546 match = l2;
3547 if (vec_len (l3))
3548 {
3549 vec_append_aligned (match, l3, sizeof (u32x4));
3550 vec_free (l3);
3551 }
3552 if (vec_len (l4))
3553 {
3554 vec_append_aligned (match, l4, sizeof (u32x4));
3555 vec_free (l4);
3556 }
3557 }
3558
3559 /* Make sure the vector is big enough even if key is all 0's */
3560 vec_validate_aligned
3561 (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
3562 sizeof (u32x4));
3563
3564 /* Set size, include skipped vectors */
3565 _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
3566
3567 *matchp = match;
3568
3569 return 1;
3570 }
3571
3572 return 0;
3573}
3574
3575static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00003576api_get_node_index (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003577{
3578 unformat_input_t *i = vam->input;
3579 vl_api_get_node_index_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003580 u8 *name = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003581 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003582
3583 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3584 {
3585 if (unformat (i, "node %s", &name))
3586 ;
3587 else
3588 break;
3589 }
3590 if (name == 0)
3591 {
3592 errmsg ("node name required");
3593 return -99;
3594 }
3595 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
3596 {
3597 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
3598 return -99;
3599 }
3600
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003601 M (GET_NODE_INDEX, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003602 clib_memcpy (mp->node_name, name, vec_len (name));
3603 vec_free (name);
3604
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003605 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003606 W (ret);
3607 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003608}
3609
3610static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00003611api_get_next_index (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003612{
3613 unformat_input_t *i = vam->input;
3614 vl_api_get_next_index_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003615 u8 *node_name = 0, *next_node_name = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003616 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003617
3618 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3619 {
3620 if (unformat (i, "node-name %s", &node_name))
3621 ;
3622 else if (unformat (i, "next-node-name %s", &next_node_name))
3623 break;
3624 }
3625
3626 if (node_name == 0)
3627 {
3628 errmsg ("node name required");
3629 return -99;
3630 }
3631 if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
3632 {
3633 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
3634 return -99;
3635 }
3636
3637 if (next_node_name == 0)
3638 {
3639 errmsg ("next node name required");
3640 return -99;
3641 }
3642 if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
3643 {
3644 errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
3645 return -99;
3646 }
3647
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003648 M (GET_NEXT_INDEX, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003649 clib_memcpy (mp->node_name, node_name, vec_len (node_name));
3650 clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
3651 vec_free (node_name);
3652 vec_free (next_node_name);
3653
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003654 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003655 W (ret);
3656 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003657}
3658
3659static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00003660api_add_node_next (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003661{
3662 unformat_input_t *i = vam->input;
3663 vl_api_add_node_next_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003664 u8 *name = 0;
3665 u8 *next = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003666 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003667
3668 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3669 {
3670 if (unformat (i, "node %s", &name))
3671 ;
3672 else if (unformat (i, "next %s", &next))
3673 ;
3674 else
3675 break;
3676 }
3677 if (name == 0)
3678 {
3679 errmsg ("node name required");
3680 return -99;
3681 }
3682 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
3683 {
3684 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
3685 return -99;
3686 }
3687 if (next == 0)
3688 {
3689 errmsg ("next node required");
3690 return -99;
3691 }
3692 if (vec_len (next) >= ARRAY_LEN (mp->next_name))
3693 {
3694 errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
3695 return -99;
3696 }
3697
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003698 M (ADD_NODE_NEXT, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003699 clib_memcpy (mp->node_name, name, vec_len (name));
3700 clib_memcpy (mp->next_name, next, vec_len (next));
3701 vec_free (name);
3702 vec_free (next);
3703
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003704 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003705 W (ret);
3706 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003707}
3708
Filip Tehlar5ff59a12021-06-23 14:38:38 +00003709#define foreach_vtr_op \
3710 _ ("disable", L2_VTR_DISABLED) \
3711 _ ("push-1", L2_VTR_PUSH_1) \
3712 _ ("push-2", L2_VTR_PUSH_2) \
3713 _ ("pop-1", L2_VTR_POP_1) \
3714 _ ("pop-2", L2_VTR_POP_2) \
3715 _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \
3716 _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \
3717 _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \
3718 _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003719
3720static int
Filip Tehlar4f348df2021-06-22 12:18:17 +00003721api_show_version (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003722{
3723 vl_api_show_version_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003724 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003725
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003726 M (SHOW_VERSION, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003727
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003728 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003729 W (ret);
3730 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003731}
3732
Damjan Marion7cd468a2016-12-19 23:05:39 +01003733static int
Filip Tehlar4f348df2021-06-22 12:18:17 +00003734api_interface_name_renumber (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003735{
3736 unformat_input_t *line_input = vam->input;
3737 vl_api_interface_name_renumber_t *mp;
3738 u32 sw_if_index = ~0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003739 u32 new_show_dev_instance = ~0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003740 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003741
3742 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
3743 {
3744 if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
3745 &sw_if_index))
3746 ;
3747 else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
3748 ;
3749 else if (unformat (line_input, "new_show_dev_instance %d",
3750 &new_show_dev_instance))
3751 ;
3752 else
3753 break;
3754 }
3755
3756 if (sw_if_index == ~0)
3757 {
3758 errmsg ("missing interface name or sw_if_index");
3759 return -99;
3760 }
3761
3762 if (new_show_dev_instance == ~0)
3763 {
3764 errmsg ("missing new_show_dev_instance");
3765 return -99;
3766 }
3767
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003768 M (INTERFACE_NAME_RENUMBER, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003769
3770 mp->sw_if_index = ntohl (sw_if_index);
3771 mp->new_show_dev_instance = ntohl (new_show_dev_instance);
3772
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003773 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003774 W (ret);
3775 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003776}
3777
3778static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00003779api_get_first_msg_id (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003780{
3781 vl_api_get_first_msg_id_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003782 unformat_input_t *i = vam->input;
3783 u8 *name;
3784 u8 name_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003785 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003786
3787 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3788 {
3789 if (unformat (i, "client %s", &name))
3790 name_set = 1;
3791 else
3792 break;
3793 }
3794
3795 if (name_set == 0)
3796 {
3797 errmsg ("missing client name");
3798 return -99;
3799 }
3800 vec_add1 (name, 0);
3801
3802 if (vec_len (name) > 63)
3803 {
3804 errmsg ("client name too long");
3805 return -99;
3806 }
3807
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003808 M (GET_FIRST_MSG_ID, mp);
Ole Troan7adaa222019-08-27 15:05:27 +02003809 clib_memcpy (mp->name, name, vec_len (name));
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003810 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003811 W (ret);
3812 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003813}
3814
3815static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00003816api_get_node_graph (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003817{
3818 vl_api_get_node_graph_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003819 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003820
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003821 M (GET_NODE_GRAPH, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003822
3823 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003824 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003825 /* Wait for the reply */
Jon Loeliger56c7b012017-02-01 12:31:41 -06003826 W (ret);
3827 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003828}
3829
Damjan Marion7cd468a2016-12-19 23:05:39 +01003830static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01003831api_delete_subif (vat_main_t * vam)
3832{
3833 unformat_input_t *i = vam->input;
3834 vl_api_delete_subif_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003835 u32 sw_if_index = ~0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003836 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003837
3838 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3839 {
3840 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3841 ;
3842 if (unformat (i, "sw_if_index %d", &sw_if_index))
3843 ;
3844 else
3845 break;
3846 }
3847
3848 if (sw_if_index == ~0)
3849 {
3850 errmsg ("missing sw_if_index");
3851 return -99;
3852 }
3853
3854 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003855 M (DELETE_SUBIF, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003856 mp->sw_if_index = ntohl (sw_if_index);
3857
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003858 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003859 W (ret);
3860 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003861}
3862
3863#define foreach_pbb_vtr_op \
3864_("disable", L2_VTR_DISABLED) \
3865_("pop", L2_VTR_POP_2) \
3866_("push", L2_VTR_PUSH_2)
3867
Damjan Marion7cd468a2016-12-19 23:05:39 +01003868
3869static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01003870api_sw_interface_tag_add_del (vat_main_t * vam)
3871{
3872 unformat_input_t *i = vam->input;
3873 vl_api_sw_interface_tag_add_del_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003874 u32 sw_if_index = ~0;
3875 u8 *tag = 0;
3876 u8 enable = 1;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003877 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003878
3879 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3880 {
3881 if (unformat (i, "tag %s", &tag))
3882 ;
3883 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3884 ;
3885 else if (unformat (i, "sw_if_index %d", &sw_if_index))
3886 ;
3887 else if (unformat (i, "del"))
3888 enable = 0;
3889 else
3890 break;
3891 }
3892
3893 if (sw_if_index == ~0)
3894 {
3895 errmsg ("missing interface name or sw_if_index");
3896 return -99;
3897 }
3898
3899 if (enable && (tag == 0))
3900 {
3901 errmsg ("no tag specified");
3902 return -99;
3903 }
3904
3905 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003906 M (SW_INTERFACE_TAG_ADD_DEL, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003907 mp->sw_if_index = ntohl (sw_if_index);
3908 mp->is_add = enable;
3909 if (enable)
Ole Troane5ff5a32019-08-23 22:55:18 +02003910 strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003911 vec_free (tag);
3912
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003913 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003914 W (ret);
3915 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003916}
3917
Matthew Smithe0792fd2019-07-12 11:48:24 -05003918static int
3919api_sw_interface_add_del_mac_address (vat_main_t * vam)
3920{
3921 unformat_input_t *i = vam->input;
3922 vl_api_mac_address_t mac = { 0 };
3923 vl_api_sw_interface_add_del_mac_address_t *mp;
3924 u32 sw_if_index = ~0;
3925 u8 is_add = 1;
3926 u8 mac_set = 0;
3927 int ret;
3928
3929 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3930 {
3931 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3932 ;
3933 else if (unformat (i, "sw_if_index %d", &sw_if_index))
3934 ;
3935 else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
3936 mac_set++;
3937 else if (unformat (i, "del"))
3938 is_add = 0;
3939 else
3940 break;
3941 }
3942
3943 if (sw_if_index == ~0)
3944 {
3945 errmsg ("missing interface name or sw_if_index");
3946 return -99;
3947 }
3948
3949 if (!mac_set)
3950 {
3951 errmsg ("missing MAC address");
3952 return -99;
3953 }
3954
3955 /* Construct the API message */
3956 M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
3957 mp->sw_if_index = ntohl (sw_if_index);
3958 mp->is_add = is_add;
3959 clib_memcpy (&mp->addr, &mac, sizeof (mac));
3960
3961 S (mp);
3962 W (ret);
3963 return ret;
3964}
3965
Damjan Marion7cd468a2016-12-19 23:05:39 +01003966static int
Ole Troand7231612018-06-07 10:17:57 +02003967api_hw_interface_set_mtu (vat_main_t * vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003968{
3969 unformat_input_t *i = vam->input;
Ole Troand7231612018-06-07 10:17:57 +02003970 vl_api_hw_interface_set_mtu_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003971 u32 sw_if_index = ~0;
3972 u32 mtu = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003973 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003974
3975 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3976 {
3977 if (unformat (i, "mtu %d", &mtu))
3978 ;
3979 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3980 ;
3981 else if (unformat (i, "sw_if_index %d", &sw_if_index))
3982 ;
3983 else
3984 break;
3985 }
3986
3987 if (sw_if_index == ~0)
3988 {
3989 errmsg ("missing interface name or sw_if_index");
3990 return -99;
3991 }
3992
3993 if (mtu == 0)
3994 {
3995 errmsg ("no mtu specified");
3996 return -99;
3997 }
3998
3999 /* Construct the API message */
Ole Troand7231612018-06-07 10:17:57 +02004000 M (HW_INTERFACE_SET_MTU, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004001 mp->sw_if_index = ntohl (sw_if_index);
4002 mp->mtu = ntohs ((u16) mtu);
4003
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004004 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06004005 W (ret);
4006 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004007}
4008
Florin Coras6e8c6672017-11-10 09:03:54 -08004009static void vl_api_app_namespace_add_del_reply_t_handler
4010 (vl_api_app_namespace_add_del_reply_t * mp)
4011{
4012 vat_main_t *vam = &vat_main;
4013 i32 retval = ntohl (mp->retval);
4014 if (vam->async_mode)
4015 {
4016 vam->async_errors += (retval < 0);
4017 }
4018 else
4019 {
4020 vam->retval = retval;
4021 if (retval == 0)
4022 errmsg ("app ns index %d\n", ntohl (mp->appns_index));
4023 vam->result_ready = 1;
4024 }
4025}
4026
4027static void vl_api_app_namespace_add_del_reply_t_handler_json
4028 (vl_api_app_namespace_add_del_reply_t * mp)
4029{
4030 vat_main_t *vam = &vat_main;
4031 vat_json_node_t node;
4032
4033 vat_json_init_object (&node);
4034 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
4035 vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
4036
4037 vat_json_print (vam->ofp, &node);
4038 vat_json_free (&node);
4039
4040 vam->retval = ntohl (mp->retval);
4041 vam->result_ready = 1;
4042}
4043
Dave Barach3bbcfab2017-08-15 19:03:44 -04004044static int
Florin Corascea194d2017-10-02 00:18:51 -07004045api_app_namespace_add_del (vat_main_t * vam)
4046{
4047 vl_api_app_namespace_add_del_t *mp;
4048 unformat_input_t *i = vam->input;
4049 u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
4050 u32 sw_if_index, ip4_fib_id, ip6_fib_id;
4051 u64 secret;
4052 int ret;
4053
4054 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4055 {
4056 if (unformat (i, "id %_%v%_", &ns_id))
4057 ;
4058 else if (unformat (i, "secret %lu", &secret))
4059 secret_set = 1;
4060 else if (unformat (i, "sw_if_index %d", &sw_if_index))
4061 sw_if_index_set = 1;
4062 else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
4063 ;
4064 else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
4065 ;
4066 else
4067 break;
4068 }
4069 if (!ns_id || !secret_set || !sw_if_index_set)
4070 {
4071 errmsg ("namespace id, secret and sw_if_index must be set");
4072 return -99;
4073 }
4074 if (vec_len (ns_id) > 64)
4075 {
4076 errmsg ("namespace id too long");
4077 return -99;
4078 }
4079 M (APP_NAMESPACE_ADD_DEL, mp);
4080
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004081 vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
Florin Coras9a9adb22017-10-26 08:16:59 -07004082 mp->secret = clib_host_to_net_u64 (secret);
Florin Corascea194d2017-10-02 00:18:51 -07004083 mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
4084 mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
4085 mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
4086 vec_free (ns_id);
4087 S (mp);
4088 W (ret);
4089 return ret;
4090}
4091
4092static int
Florin Coras90a63982017-12-19 04:50:01 -08004093api_sock_init_shm (vat_main_t * vam)
4094{
4095#if VPP_API_TEST_BUILTIN == 0
4096 unformat_input_t *i = vam->input;
4097 vl_api_shm_elem_config_t *config = 0;
4098 u64 size = 64 << 20;
4099 int rv;
4100
4101 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4102 {
4103 if (unformat (i, "size %U", unformat_memory_size, &size))
4104 ;
4105 else
4106 break;
4107 }
4108
Dave Barach78958722018-05-10 16:44:27 -04004109 /*
4110 * Canned custom ring allocator config.
4111 * Should probably parse all of this
4112 */
4113 vec_validate (config, 6);
Florin Coras90a63982017-12-19 04:50:01 -08004114 config[0].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08004115 config[0].size = 256;
Dave Barach78958722018-05-10 16:44:27 -04004116 config[0].count = 32;
4117
4118 config[1].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08004119 config[1].size = 1024;
Dave Barach78958722018-05-10 16:44:27 -04004120 config[1].count = 16;
4121
4122 config[2].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08004123 config[2].size = 4096;
Dave Barach78958722018-05-10 16:44:27 -04004124 config[2].count = 2;
4125
4126 config[3].type = VL_API_CLIENT_RING;
4127 config[3].size = 256;
4128 config[3].count = 32;
4129
4130 config[4].type = VL_API_CLIENT_RING;
4131 config[4].size = 1024;
4132 config[4].count = 16;
4133
4134 config[5].type = VL_API_CLIENT_RING;
4135 config[5].size = 4096;
4136 config[5].count = 2;
4137
4138 config[6].type = VL_API_QUEUE;
4139 config[6].count = 128;
4140 config[6].size = sizeof (uword);
4141
Tomasz Kulasek97dcf5b2019-01-31 18:26:32 +01004142 rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
Florin Coras90a63982017-12-19 04:50:01 -08004143 if (!rv)
4144 vam->client_index_invalid = 1;
4145 return rv;
4146#else
4147 return -99;
4148#endif
4149}
4150
Florin Coras6c36f532017-11-03 18:32:34 -07004151static void
4152vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
4153{
4154 vat_main_t *vam = &vat_main;
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004155 fib_prefix_t lcl, rmt;
Florin Coras6c36f532017-11-03 18:32:34 -07004156
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004157 ip_prefix_decode (&mp->lcl, &lcl);
4158 ip_prefix_decode (&mp->rmt, &rmt);
4159
4160 if (lcl.fp_proto == FIB_PROTOCOL_IP4)
Florin Coras6c36f532017-11-03 18:32:34 -07004161 {
Florin Corasc97a7392017-11-05 23:07:07 -08004162 print (vam->ofp,
4163 "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
Steven85dbac02017-11-07 16:29:53 -08004164 clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004165 mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
Steven85dbac02017-11-07 16:29:53 -08004166 clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004167 &rmt.fp_addr.ip4, rmt.fp_len,
4168 clib_net_to_host_u16 (mp->rmt_port),
Steven85dbac02017-11-07 16:29:53 -08004169 clib_net_to_host_u32 (mp->action_index), mp->tag);
Florin Coras6c36f532017-11-03 18:32:34 -07004170 }
4171 else
4172 {
Florin Corasc97a7392017-11-05 23:07:07 -08004173 print (vam->ofp,
4174 "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
Steven85dbac02017-11-07 16:29:53 -08004175 clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004176 mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
Steven85dbac02017-11-07 16:29:53 -08004177 clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004178 &rmt.fp_addr.ip6, rmt.fp_len,
4179 clib_net_to_host_u16 (mp->rmt_port),
Steven85dbac02017-11-07 16:29:53 -08004180 clib_net_to_host_u32 (mp->action_index), mp->tag);
Florin Coras6c36f532017-11-03 18:32:34 -07004181 }
4182}
4183
4184static void
4185vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
4186 mp)
4187{
4188 vat_main_t *vam = &vat_main;
4189 vat_json_node_t *node = NULL;
4190 struct in6_addr ip6;
4191 struct in_addr ip4;
4192
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004193 fib_prefix_t lcl, rmt;
4194
4195 ip_prefix_decode (&mp->lcl, &lcl);
4196 ip_prefix_decode (&mp->rmt, &rmt);
4197
Florin Coras6c36f532017-11-03 18:32:34 -07004198 if (VAT_JSON_ARRAY != vam->json_tree.type)
4199 {
4200 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4201 vat_json_init_array (&vam->json_tree);
4202 }
4203 node = vat_json_array_add (&vam->json_tree);
4204 vat_json_init_object (node);
4205
Florin Coras6c36f532017-11-03 18:32:34 -07004206 vat_json_object_add_uint (node, "appns_index",
4207 clib_net_to_host_u32 (mp->appns_index));
4208 vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
4209 vat_json_object_add_uint (node, "scope", mp->scope);
4210 vat_json_object_add_uint (node, "action_index",
4211 clib_net_to_host_u32 (mp->action_index));
4212 vat_json_object_add_uint (node, "lcl_port",
4213 clib_net_to_host_u16 (mp->lcl_port));
4214 vat_json_object_add_uint (node, "rmt_port",
4215 clib_net_to_host_u16 (mp->rmt_port));
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004216 vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
4217 vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
Florin Corasc97a7392017-11-05 23:07:07 -08004218 vat_json_object_add_string_copy (node, "tag", mp->tag);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004219 if (lcl.fp_proto == FIB_PROTOCOL_IP4)
Florin Coras6c36f532017-11-03 18:32:34 -07004220 {
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004221 clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
Florin Coras6c36f532017-11-03 18:32:34 -07004222 vat_json_object_add_ip4 (node, "lcl_ip", ip4);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004223 clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
Florin Coras6c36f532017-11-03 18:32:34 -07004224 vat_json_object_add_ip4 (node, "rmt_ip", ip4);
4225 }
4226 else
4227 {
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004228 clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
Florin Coras6c36f532017-11-03 18:32:34 -07004229 vat_json_object_add_ip6 (node, "lcl_ip", ip6);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004230 clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
Florin Coras6c36f532017-11-03 18:32:34 -07004231 vat_json_object_add_ip6 (node, "rmt_ip", ip6);
4232 }
4233}
4234
Florin Coras1c710452017-10-17 00:03:13 -07004235static int
4236api_session_rule_add_del (vat_main_t * vam)
4237{
4238 vl_api_session_rule_add_del_t *mp;
4239 unformat_input_t *i = vam->input;
4240 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
4241 u32 appns_index = 0, scope = 0;
4242 ip4_address_t lcl_ip4, rmt_ip4;
4243 ip6_address_t lcl_ip6, rmt_ip6;
4244 u8 is_ip4 = 1, conn_set = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08004245 u8 is_add = 1, *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07004246 int ret;
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004247 fib_prefix_t lcl, rmt;
Florin Coras1c710452017-10-17 00:03:13 -07004248
4249 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4250 {
4251 if (unformat (i, "del"))
4252 is_add = 0;
4253 else if (unformat (i, "add"))
4254 ;
4255 else if (unformat (i, "proto tcp"))
4256 proto = 0;
4257 else if (unformat (i, "proto udp"))
4258 proto = 1;
4259 else if (unformat (i, "appns %d", &appns_index))
4260 ;
4261 else if (unformat (i, "scope %d", &scope))
4262 ;
Florin Corasc97a7392017-11-05 23:07:07 -08004263 else if (unformat (i, "tag %_%v%_", &tag))
4264 ;
Florin Coras1c710452017-10-17 00:03:13 -07004265 else
4266 if (unformat
4267 (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
4268 &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
4269 &rmt_port))
4270 {
4271 is_ip4 = 1;
4272 conn_set = 1;
4273 }
4274 else
4275 if (unformat
4276 (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
4277 &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
4278 &rmt_port))
4279 {
4280 is_ip4 = 0;
4281 conn_set = 1;
4282 }
4283 else if (unformat (i, "action %d", &action))
4284 ;
4285 else
4286 break;
4287 }
4288 if (proto == ~0 || !conn_set || action == ~0)
4289 {
4290 errmsg ("transport proto, connection and action must be set");
4291 return -99;
4292 }
4293
4294 if (scope > 3)
4295 {
4296 errmsg ("scope should be 0-3");
4297 return -99;
4298 }
4299
4300 M (SESSION_RULE_ADD_DEL, mp);
4301
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004302 clib_memset (&lcl, 0, sizeof (lcl));
4303 clib_memset (&rmt, 0, sizeof (rmt));
4304 if (is_ip4)
4305 {
4306 ip_set (&lcl.fp_addr, &lcl_ip4, 1);
4307 ip_set (&rmt.fp_addr, &rmt_ip4, 1);
4308 lcl.fp_len = lcl_plen;
4309 rmt.fp_len = rmt_plen;
4310 }
4311 else
4312 {
4313 ip_set (&lcl.fp_addr, &lcl_ip6, 0);
4314 ip_set (&rmt.fp_addr, &rmt_ip6, 0);
4315 lcl.fp_len = lcl_plen;
4316 rmt.fp_len = rmt_plen;
4317 }
4318
4319
4320 ip_prefix_encode (&lcl, &mp->lcl);
4321 ip_prefix_encode (&rmt, &mp->rmt);
Florin Corasc97a7392017-11-05 23:07:07 -08004322 mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
4323 mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01004324 mp->transport_proto =
4325 proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
Florin Coras1c710452017-10-17 00:03:13 -07004326 mp->action_index = clib_host_to_net_u32 (action);
4327 mp->appns_index = clib_host_to_net_u32 (appns_index);
4328 mp->scope = scope;
4329 mp->is_add = is_add;
Florin Corasc97a7392017-11-05 23:07:07 -08004330 if (tag)
4331 {
4332 clib_memcpy (mp->tag, tag, vec_len (tag));
4333 vec_free (tag);
4334 }
Florin Coras1c710452017-10-17 00:03:13 -07004335
4336 S (mp);
4337 W (ret);
4338 return ret;
4339}
Dave Barach65457162017-10-10 17:53:14 -04004340
4341static int
Florin Coras6c36f532017-11-03 18:32:34 -07004342api_session_rules_dump (vat_main_t * vam)
4343{
4344 vl_api_session_rules_dump_t *mp;
4345 vl_api_control_ping_t *mp_ping;
4346 int ret;
4347
4348 if (!vam->json_output)
4349 {
4350 print (vam->ofp, "%=20s", "Session Rules");
4351 }
4352
4353 M (SESSION_RULES_DUMP, mp);
4354 /* send it... */
4355 S (mp);
4356
4357 /* Use a control ping for synchronization */
4358 MPING (CONTROL_PING, mp_ping);
4359 S (mp_ping);
4360
4361 /* Wait for a reply... */
4362 W (ret);
4363 return ret;
4364}
4365
4366static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01004367q_or_quit (vat_main_t * vam)
4368{
Dave Barachdef19da2017-02-22 17:29:20 -05004369#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01004370 longjmp (vam->jump_buf, 1);
Dave Barachdef19da2017-02-22 17:29:20 -05004371#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01004372 return 0; /* not so much */
4373}
4374
4375static int
4376q (vat_main_t * vam)
4377{
4378 return q_or_quit (vam);
4379}
4380
4381static int
4382quit (vat_main_t * vam)
4383{
4384 return q_or_quit (vam);
4385}
4386
4387static int
4388comment (vat_main_t * vam)
4389{
4390 return 0;
4391}
4392
4393static int
Dave Barachb09f4d02019-07-15 16:00:03 -04004394elog_save (vat_main_t * vam)
4395{
4396#if VPP_API_TEST_BUILTIN == 0
4397 elog_main_t *em = &vam->elog_main;
4398 unformat_input_t *i = vam->input;
4399 char *file, *chroot_file;
4400 clib_error_t *error;
4401
4402 if (!unformat (i, "%s", &file))
4403 {
4404 errmsg ("expected file name, got `%U'", format_unformat_error, i);
4405 return 0;
4406 }
4407
4408 /* It's fairly hard to get "../oopsie" through unformat; just in case */
4409 if (strstr (file, "..") || index (file, '/'))
4410 {
4411 errmsg ("illegal characters in filename '%s'", file);
4412 return 0;
4413 }
4414
4415 chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
4416
4417 vec_free (file);
4418
4419 errmsg ("Saving %wd of %wd events to %s",
4420 elog_n_events_in_buffer (em),
4421 elog_buffer_capacity (em), chroot_file);
4422
4423 error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
4424 vec_free (chroot_file);
4425
4426 if (error)
4427 clib_error_report (error);
4428#else
4429 errmsg ("Use the vpp event loger...");
4430#endif
4431
4432 return 0;
4433}
4434
4435static int
4436elog_setup (vat_main_t * vam)
4437{
4438#if VPP_API_TEST_BUILTIN == 0
4439 elog_main_t *em = &vam->elog_main;
4440 unformat_input_t *i = vam->input;
4441 u32 nevents = 128 << 10;
4442
4443 (void) unformat (i, "nevents %d", &nevents);
4444
4445 elog_init (em, nevents);
4446 vl_api_set_elog_main (em);
4447 vl_api_set_elog_trace_api_messages (1);
4448 errmsg ("Event logger initialized with %u events", nevents);
4449#else
4450 errmsg ("Use the vpp event loger...");
4451#endif
4452 return 0;
4453}
4454
4455static int
4456elog_enable (vat_main_t * vam)
4457{
4458#if VPP_API_TEST_BUILTIN == 0
4459 elog_main_t *em = &vam->elog_main;
4460
4461 elog_enable_disable (em, 1 /* enable */ );
4462 vl_api_set_elog_trace_api_messages (1);
4463 errmsg ("Event logger enabled...");
4464#else
4465 errmsg ("Use the vpp event loger...");
4466#endif
4467 return 0;
4468}
4469
4470static int
4471elog_disable (vat_main_t * vam)
4472{
4473#if VPP_API_TEST_BUILTIN == 0
4474 elog_main_t *em = &vam->elog_main;
4475
4476 elog_enable_disable (em, 0 /* enable */ );
4477 vl_api_set_elog_trace_api_messages (1);
4478 errmsg ("Event logger disabled...");
4479#else
4480 errmsg ("Use the vpp event loger...");
4481#endif
4482 return 0;
4483}
4484
4485static int
Dave Barach048a4e52018-06-01 18:52:25 -04004486statseg (vat_main_t * vam)
4487{
4488 ssvm_private_t *ssvmp = &vam->stat_segment;
4489 ssvm_shared_header_t *shared_header = ssvmp->sh;
4490 vlib_counter_t **counters;
4491 u64 thread0_index1_packets;
4492 u64 thread0_index1_bytes;
4493 f64 vector_rate, input_rate;
4494 uword *p;
4495
4496 uword *counter_vector_by_name;
4497 if (vam->stat_segment_lockp == 0)
4498 {
4499 errmsg ("Stat segment not mapped...");
4500 return -99;
4501 }
4502
4503 /* look up "/if/rx for sw_if_index 1 as a test */
4504
4505 clib_spinlock_lock (vam->stat_segment_lockp);
4506
4507 counter_vector_by_name = (uword *) shared_header->opaque[1];
4508
4509 p = hash_get_mem (counter_vector_by_name, "/if/rx");
4510 if (p == 0)
4511 {
4512 clib_spinlock_unlock (vam->stat_segment_lockp);
4513 errmsg ("/if/tx not found?");
4514 return -99;
4515 }
4516
4517 /* Fish per-thread vector of combined counters from shared memory */
4518 counters = (vlib_counter_t **) p[0];
4519
4520 if (vec_len (counters[0]) < 2)
4521 {
4522 clib_spinlock_unlock (vam->stat_segment_lockp);
4523 errmsg ("/if/tx vector length %d", vec_len (counters[0]));
4524 return -99;
4525 }
4526
4527 /* Read thread 0 sw_if_index 1 counter */
4528 thread0_index1_packets = counters[0][1].packets;
4529 thread0_index1_bytes = counters[0][1].bytes;
4530
4531 p = hash_get_mem (counter_vector_by_name, "vector_rate");
4532 if (p == 0)
4533 {
4534 clib_spinlock_unlock (vam->stat_segment_lockp);
4535 errmsg ("vector_rate not found?");
4536 return -99;
4537 }
4538
4539 vector_rate = *(f64 *) (p[0]);
4540 p = hash_get_mem (counter_vector_by_name, "input_rate");
4541 if (p == 0)
4542 {
4543 clib_spinlock_unlock (vam->stat_segment_lockp);
4544 errmsg ("input_rate not found?");
4545 return -99;
4546 }
4547 input_rate = *(f64 *) (p[0]);
4548
4549 clib_spinlock_unlock (vam->stat_segment_lockp);
4550
4551 print (vam->ofp, "vector_rate %.2f input_rate %.2f",
4552 vector_rate, input_rate);
4553 print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
4554 thread0_index1_packets, thread0_index1_bytes);
4555
4556 return 0;
4557}
4558
4559static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01004560cmd_cmp (void *a1, void *a2)
4561{
4562 u8 **c1 = a1;
4563 u8 **c2 = a2;
4564
4565 return strcmp ((char *) (c1[0]), (char *) (c2[0]));
4566}
4567
4568static int
4569help (vat_main_t * vam)
4570{
4571 u8 **cmds = 0;
4572 u8 *name = 0;
4573 hash_pair_t *p;
4574 unformat_input_t *i = vam->input;
4575 int j;
4576
4577 if (unformat (i, "%s", &name))
4578 {
4579 uword *hs;
4580
4581 vec_add1 (name, 0);
4582
4583 hs = hash_get_mem (vam->help_by_name, name);
4584 if (hs)
4585 print (vam->ofp, "usage: %s %s", name, hs[0]);
4586 else
4587 print (vam->ofp, "No such msg / command '%s'", name);
4588 vec_free (name);
4589 return 0;
4590 }
4591
4592 print (vam->ofp, "Help is available for the following:");
4593
4594 /* *INDENT-OFF* */
4595 hash_foreach_pair (p, vam->function_by_name,
4596 ({
4597 vec_add1 (cmds, (u8 *)(p->key));
4598 }));
4599 /* *INDENT-ON* */
4600
4601 vec_sort_with_function (cmds, cmd_cmp);
4602
4603 for (j = 0; j < vec_len (cmds); j++)
4604 print (vam->ofp, "%s", cmds[j]);
4605
4606 vec_free (cmds);
4607 return 0;
4608}
4609
4610static int
4611set (vat_main_t * vam)
4612{
4613 u8 *name = 0, *value = 0;
4614 unformat_input_t *i = vam->input;
4615
4616 if (unformat (i, "%s", &name))
4617 {
4618 /* The input buffer is a vector, not a string. */
4619 value = vec_dup (i->buffer);
4620 vec_delete (value, i->index, 0);
4621 /* Almost certainly has a trailing newline */
4622 if (value[vec_len (value) - 1] == '\n')
4623 value[vec_len (value) - 1] = 0;
4624 /* Make sure it's a proper string, one way or the other */
4625 vec_add1 (value, 0);
4626 (void) clib_macro_set_value (&vam->macro_main,
4627 (char *) name, (char *) value);
4628 }
4629 else
4630 errmsg ("usage: set <name> <value>");
4631
4632 vec_free (name);
4633 vec_free (value);
4634 return 0;
4635}
4636
4637static int
4638unset (vat_main_t * vam)
4639{
4640 u8 *name = 0;
4641
4642 if (unformat (vam->input, "%s", &name))
4643 if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
4644 errmsg ("unset: %s wasn't set", name);
4645 vec_free (name);
4646 return 0;
4647}
4648
4649typedef struct
4650{
4651 u8 *name;
4652 u8 *value;
4653} macro_sort_t;
4654
4655
4656static int
4657macro_sort_cmp (void *a1, void *a2)
4658{
4659 macro_sort_t *s1 = a1;
4660 macro_sort_t *s2 = a2;
4661
4662 return strcmp ((char *) (s1->name), (char *) (s2->name));
4663}
4664
4665static int
4666dump_macro_table (vat_main_t * vam)
4667{
4668 macro_sort_t *sort_me = 0, *sm;
4669 int i;
4670 hash_pair_t *p;
4671
4672 /* *INDENT-OFF* */
4673 hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
4674 ({
4675 vec_add2 (sort_me, sm, 1);
4676 sm->name = (u8 *)(p->key);
4677 sm->value = (u8 *) (p->value[0]);
4678 }));
4679 /* *INDENT-ON* */
4680
4681 vec_sort_with_function (sort_me, macro_sort_cmp);
4682
4683 if (vec_len (sort_me))
4684 print (vam->ofp, "%-15s%s", "Name", "Value");
4685 else
4686 print (vam->ofp, "The macro table is empty...");
4687
4688 for (i = 0; i < vec_len (sort_me); i++)
4689 print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
4690 return 0;
4691}
4692
4693static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01004694value_sort_cmp (void *a1, void *a2)
4695{
4696 name_sort_t *n1 = a1;
4697 name_sort_t *n2 = a2;
4698
4699 if (n1->value < n2->value)
4700 return -1;
4701 if (n1->value > n2->value)
4702 return 1;
4703 return 0;
4704}
4705
4706
4707static int
4708dump_msg_api_table (vat_main_t * vam)
4709{
Dave Barach39d69112019-11-27 11:42:13 -05004710 api_main_t *am = vlibapi_get_main ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01004711 name_sort_t *nses = 0, *ns;
4712 hash_pair_t *hp;
4713 int i;
4714
4715 /* *INDENT-OFF* */
4716 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
4717 ({
4718 vec_add2 (nses, ns, 1);
4719 ns->name = (u8 *)(hp->key);
4720 ns->value = (u32) hp->value[0];
4721 }));
4722 /* *INDENT-ON* */
4723
4724 vec_sort_with_function (nses, value_sort_cmp);
4725
4726 for (i = 0; i < vec_len (nses); i++)
4727 print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
4728 vec_free (nses);
4729 return 0;
4730}
4731
4732static int
4733get_msg_id (vat_main_t * vam)
4734{
4735 u8 *name_and_crc;
4736 u32 message_index;
4737
4738 if (unformat (vam->input, "%s", &name_and_crc))
4739 {
Florin Corase86a8ed2018-01-05 03:20:25 -08004740 message_index = vl_msg_api_get_msg_index (name_and_crc);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004741 if (message_index == ~0)
4742 {
4743 print (vam->ofp, " '%s' not found", name_and_crc);
4744 return 0;
4745 }
4746 print (vam->ofp, " '%s' has message index %d",
4747 name_and_crc, message_index);
4748 return 0;
4749 }
4750 errmsg ("name_and_crc required...");
4751 return 0;
4752}
4753
4754static int
4755search_node_table (vat_main_t * vam)
4756{
4757 unformat_input_t *line_input = vam->input;
4758 u8 *node_to_find;
4759 int j;
4760 vlib_node_t *node, *next_node;
4761 uword *p;
4762
4763 if (vam->graph_node_index_by_name == 0)
4764 {
4765 print (vam->ofp, "Node table empty, issue get_node_graph...");
4766 return 0;
4767 }
4768
4769 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
4770 {
4771 if (unformat (line_input, "%s", &node_to_find))
4772 {
4773 vec_add1 (node_to_find, 0);
4774 p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
4775 if (p == 0)
4776 {
4777 print (vam->ofp, "%s not found...", node_to_find);
4778 goto out;
4779 }
Dave Barach1ddbc012018-06-13 09:26:05 -04004780 node = vam->graph_nodes[0][p[0]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01004781 print (vam->ofp, "[%d] %s", p[0], node->name);
4782 for (j = 0; j < vec_len (node->next_nodes); j++)
4783 {
4784 if (node->next_nodes[j] != ~0)
4785 {
Dave Barach1ddbc012018-06-13 09:26:05 -04004786 next_node = vam->graph_nodes[0][node->next_nodes[j]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01004787 print (vam->ofp, " [%d] %s", j, next_node->name);
4788 }
4789 }
4790 }
4791
4792 else
4793 {
4794 clib_warning ("parse error '%U'", format_unformat_error,
4795 line_input);
4796 return -99;
4797 }
4798
4799 out:
4800 vec_free (node_to_find);
4801
4802 }
4803
4804 return 0;
4805}
4806
4807
4808static int
4809script (vat_main_t * vam)
4810{
4811#if (VPP_API_TEST_BUILTIN==0)
4812 u8 *s = 0;
4813 char *save_current_file;
4814 unformat_input_t save_input;
4815 jmp_buf save_jump_buf;
4816 u32 save_line_number;
4817
4818 FILE *new_fp, *save_ifp;
4819
4820 if (unformat (vam->input, "%s", &s))
4821 {
4822 new_fp = fopen ((char *) s, "r");
4823 if (new_fp == 0)
4824 {
4825 errmsg ("Couldn't open script file %s", s);
4826 vec_free (s);
4827 return -99;
4828 }
4829 }
4830 else
4831 {
4832 errmsg ("Missing script name");
4833 return -99;
4834 }
4835
4836 clib_memcpy (&save_input, &vam->input, sizeof (save_input));
4837 clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
4838 save_ifp = vam->ifp;
4839 save_line_number = vam->input_line_number;
4840 save_current_file = (char *) vam->current_file;
4841
4842 vam->input_line_number = 0;
4843 vam->ifp = new_fp;
4844 vam->current_file = s;
4845 do_one_file (vam);
4846
Sirshak Dasb0861822018-05-29 21:13:21 -05004847 clib_memcpy (&vam->input, &save_input, sizeof (save_input));
Damjan Marion7cd468a2016-12-19 23:05:39 +01004848 clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
4849 vam->ifp = save_ifp;
4850 vam->input_line_number = save_line_number;
4851 vam->current_file = (u8 *) save_current_file;
4852 vec_free (s);
4853
4854 return 0;
4855#else
4856 clib_warning ("use the exec command...");
4857 return -99;
4858#endif
4859}
4860
4861static int
4862echo (vat_main_t * vam)
4863{
4864 print (vam->ofp, "%v", vam->input->buffer);
4865 return 0;
4866}
4867
4868/* List of API message constructors, CLI names map to api_xxx */
4869#define foreach_vpe_api_msg \
Jon Loeligerc83c3b72017-02-23 13:57:35 -06004870_(create_loopback,"[mac <mac-addr>] [instance <instance>]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004871_(sw_interface_dump,"") \
4872_(sw_interface_set_flags, \
4873 "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
4874_(sw_interface_add_del_address, \
4875 "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02004876_(sw_interface_set_rx_placement, \
4877 "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]") \
Mohsin Kazmif0b42f42018-09-10 18:11:00 +02004878_(sw_interface_rx_placement_dump, \
4879 "[<intfc> | sw_if_index <id>]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004880_(sw_interface_set_table, \
4881 "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004882_(sw_interface_set_unnumbered, \
4883 "<intfc> | sw_if_index <id> unnum_if_index <id> [del]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004884_(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>") \
4885_(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n" \
4886 "[outer_vlan_id <n>][inner_vlan_id <n>]\n" \
4887 "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n" \
4888 "[outer_vlan_id_any][inner_vlan_id_any]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004889_(get_node_index, "node <node-name") \
4890_(add_node_next, "node <node-name> next <next-node-name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004891_(show_version, "") \
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02004892_(show_threads, "") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004893_(interface_name_renumber, \
4894 "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004895_(delete_loopback,"sw_if_index <nn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004896_(want_interface_events, "enable|disable") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004897_(get_first_msg_id, "client <name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004898_(get_node_graph, " ") \
4899_(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004900_(get_next_index, "node-name <node-name> next-node-name <node-name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004901_(delete_subif,"<intfc> | sw_if_index <nn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004902_(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>" \
4903"[disable]") \
Matthew Smithe0792fd2019-07-12 11:48:24 -05004904_(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> " \
4905 "mac <mac-address> [del]") \
Ole Troand7231612018-06-07 10:17:57 +02004906_(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>") \
Pavel Kotucek6899a302017-06-08 08:46:10 +02004907_(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]") \
Florin Coras90a63982017-12-19 04:50:01 -08004908_(sock_init_shm, "size <nnn>") \
Florin Corascea194d2017-10-02 00:18:51 -07004909_(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
Florin Coras1c710452017-10-17 00:03:13 -07004910_(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> " \
4911 "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>") \
Florin Coras6c36f532017-11-03 18:32:34 -07004912_(session_rules_dump, "") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004913
4914/* List of command functions, CLI names map directly to functions */
4915#define foreach_cli_function \
4916_(comment, "usage: comment <ignore-rest-of-line>") \
4917_(dump_interface_table, "usage: dump_interface_table") \
4918_(dump_sub_interface_table, "usage: dump_sub_interface_table") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004919_(dump_macro_table, "usage: dump_macro_table ") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004920_(dump_msg_api_table, "usage: dump_msg_api_table") \
Dave Barachb09f4d02019-07-15 16:00:03 -04004921_(elog_setup, "usage: elog_setup [nevents, default 128K]") \
4922_(elog_disable, "usage: elog_disable") \
4923_(elog_enable, "usage: elog_enable") \
4924_(elog_save, "usage: elog_save <filename>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004925_(get_msg_id, "usage: get_msg_id name_and_crc") \
4926_(echo, "usage: echo <message>") \
4927_(exec, "usage: exec <vpe-debug-CLI-command>") \
4928_(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>") \
4929_(help, "usage: help") \
4930_(q, "usage: quit") \
4931_(quit, "usage: quit") \
4932_(search_node_table, "usage: search_node_table <name>...") \
4933_(set, "usage: set <variable-name> <value>") \
4934_(script, "usage: script <file-name>") \
Neale Ranns097fa662018-05-01 05:17:55 -07004935_(statseg, "usage: statseg") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01004936_(unset, "usage: unset <variable-name>")
Dave Barach048a4e52018-06-01 18:52:25 -04004937
Damjan Marion7cd468a2016-12-19 23:05:39 +01004938#define _(N,n) \
4939 static void vl_api_##n##_t_handler_uni \
4940 (vl_api_##n##_t * mp) \
4941 { \
4942 vat_main_t * vam = &vat_main; \
4943 if (vam->json_output) { \
4944 vl_api_##n##_t_handler_json(mp); \
4945 } else { \
4946 vl_api_##n##_t_handler(mp); \
4947 } \
4948 }
4949foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05004950#if VPP_API_TEST_BUILTIN == 0
4951foreach_standalone_reply_msg;
4952#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01004953#undef _
4954
4955void
4956vat_api_hookup (vat_main_t * vam)
4957{
4958#define _(N,n) \
4959 vl_msg_api_set_handlers(VL_API_##N, #n, \
4960 vl_api_##n##_t_handler_uni, \
4961 vl_noop_handler, \
4962 vl_api_##n##_t_endian, \
4963 vl_api_##n##_t_print, \
4964 sizeof(vl_api_##n##_t), 1);
4965 foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05004966#if VPP_API_TEST_BUILTIN == 0
4967 foreach_standalone_reply_msg;
4968#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01004969#undef _
4970
4971#if (VPP_API_TEST_BUILTIN==0)
4972 vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004973
4974 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
4975
4976 vam->function_by_name = hash_create_string (0, sizeof (uword));
4977
4978 vam->help_by_name = hash_create_string (0, sizeof (uword));
Dave Barach45e4f362017-03-07 12:52:31 -05004979#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01004980
4981 /* API messages we can send */
4982#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
4983 foreach_vpe_api_msg;
4984#undef _
4985
4986 /* Help strings */
4987#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
4988 foreach_vpe_api_msg;
4989#undef _
Damjan Marion7cd468a2016-12-19 23:05:39 +01004990
4991 /* CLI functions */
4992#define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
4993 foreach_cli_function;
4994#undef _
4995
4996 /* Help strings */
4997#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
4998 foreach_cli_function;
4999#undef _
5000}
5001
Dave Baracha1a093d2017-03-02 13:13:23 -05005002#if VPP_API_TEST_BUILTIN
5003static clib_error_t *
5004vat_api_hookup_shim (vlib_main_t * vm)
5005{
5006 vat_api_hookup (&vat_main);
5007 return 0;
5008}
5009
5010VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
5011#endif
5012
Damjan Marion7cd468a2016-12-19 23:05:39 +01005013/*
5014 * fd.io coding-style-patch-verification: ON
5015 *
5016 * Local Variables:
5017 * eval: (c-set-style "gnu")
5018 * End:
5019 */