blob: 1b77fb8bcb31765e146e517895d48ef96356875b [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
571static void
Neale Ranns097fa662018-05-01 05:17:55 -0700572increment_v4_address (vl_api_ip4_address_t * i)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100573{
Neale Ranns097fa662018-05-01 05:17:55 -0700574 ip4_address_t *a = (ip4_address_t *) i;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100575 u32 v;
576
577 v = ntohl (a->as_u32) + 1;
578 a->as_u32 = ntohl (v);
579}
580
581static void
Neale Ranns097fa662018-05-01 05:17:55 -0700582increment_v6_address (vl_api_ip6_address_t * i)
Neale Ranns2b5ba952019-04-02 10:15:40 +0000583{
Neale Ranns097fa662018-05-01 05:17:55 -0700584 ip6_address_t *a = (ip6_address_t *) i;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100585 u64 v0, v1;
586
587 v0 = clib_net_to_host_u64 (a->as_u64[0]);
588 v1 = clib_net_to_host_u64 (a->as_u64[1]);
589
590 v1 += 1;
591 if (v1 == 0)
592 v0 += 1;
593 a->as_u64[0] = clib_net_to_host_u64 (v0);
594 a->as_u64[1] = clib_net_to_host_u64 (v1);
595}
596
597static void
Neale Ranns097fa662018-05-01 05:17:55 -0700598increment_address (vl_api_address_t * a)
599{
Dave Barach54582662020-04-21 08:01:16 -0400600 if (a->af == ADDRESS_IP4)
Neale Ranns097fa662018-05-01 05:17:55 -0700601 increment_v4_address (&a->un.ip4);
Dave Barach54582662020-04-21 08:01:16 -0400602 else if (a->af == ADDRESS_IP6)
Neale Ranns097fa662018-05-01 05:17:55 -0700603 increment_v6_address (&a->un.ip6);
604}
605
606static void
607set_ip4_address (vl_api_address_t * a, u32 v)
608{
609 if (a->af == ADDRESS_IP4)
610 {
611 ip4_address_t *i = (ip4_address_t *) & a->un.ip4;
612 i->as_u32 = v;
613 }
614}
615
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100616void
617ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
618{
619 if (is_ip4)
620 dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
621 else
622 clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
623 sizeof (ip6_address_t));
624}
625
Neale Ranns097fa662018-05-01 05:17:55 -0700626static void
Neale Ranns097fa662018-05-01 05:17:55 -0700627vat_json_object_add_address (vat_json_node_t * node,
628 const char *str, const vl_api_address_t * addr)
629{
630 if (ADDRESS_IP6 == addr->af)
631 {
632 struct in6_addr ip6;
633
634 clib_memcpy (&ip6, &addr->un.ip6, sizeof (ip6));
635 vat_json_object_add_ip6 (node, str, ip6);
636 }
637 else
638 {
639 struct in_addr ip4;
640
641 clib_memcpy (&ip4, &addr->un.ip4, sizeof (ip4));
642 vat_json_object_add_ip4 (node, str, ip4);
643 }
644}
645
646static void
647vat_json_object_add_prefix (vat_json_node_t * node,
648 const vl_api_prefix_t * prefix)
649{
Paul Vinciguerraab055082019-06-06 14:07:55 -0400650 vat_json_object_add_uint (node, "len", prefix->len);
651 vat_json_object_add_address (node, "address", &prefix->address);
Neale Ranns097fa662018-05-01 05:17:55 -0700652}
653
Damjan Marion7cd468a2016-12-19 23:05:39 +0100654static void vl_api_create_loopback_reply_t_handler
655 (vl_api_create_loopback_reply_t * mp)
656{
657 vat_main_t *vam = &vat_main;
658 i32 retval = ntohl (mp->retval);
659
660 vam->retval = retval;
661 vam->regenerate_interface_table = 1;
662 vam->sw_if_index = ntohl (mp->sw_if_index);
663 vam->result_ready = 1;
664}
665
666static void vl_api_create_loopback_reply_t_handler_json
667 (vl_api_create_loopback_reply_t * mp)
668{
669 vat_main_t *vam = &vat_main;
670 vat_json_node_t node;
671
672 vat_json_init_object (&node);
673 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
674 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
675
676 vat_json_print (vam->ofp, &node);
677 vat_json_free (&node);
678 vam->retval = ntohl (mp->retval);
679 vam->result_ready = 1;
680}
681
Jon Loeligerc83c3b72017-02-23 13:57:35 -0600682static void vl_api_create_loopback_instance_reply_t_handler
683 (vl_api_create_loopback_instance_reply_t * mp)
684{
685 vat_main_t *vam = &vat_main;
686 i32 retval = ntohl (mp->retval);
687
688 vam->retval = retval;
689 vam->regenerate_interface_table = 1;
690 vam->sw_if_index = ntohl (mp->sw_if_index);
691 vam->result_ready = 1;
692}
693
694static void vl_api_create_loopback_instance_reply_t_handler_json
695 (vl_api_create_loopback_instance_reply_t * mp)
696{
697 vat_main_t *vam = &vat_main;
698 vat_json_node_t node;
699
700 vat_json_init_object (&node);
701 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
702 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
703
704 vat_json_print (vam->ofp, &node);
705 vat_json_free (&node);
706 vam->retval = ntohl (mp->retval);
707 vam->result_ready = 1;
708}
709
Damjan Marion7cd468a2016-12-19 23:05:39 +0100710static void vl_api_create_vlan_subif_reply_t_handler
711 (vl_api_create_vlan_subif_reply_t * mp)
712{
713 vat_main_t *vam = &vat_main;
714 i32 retval = ntohl (mp->retval);
715
716 vam->retval = retval;
717 vam->regenerate_interface_table = 1;
718 vam->sw_if_index = ntohl (mp->sw_if_index);
719 vam->result_ready = 1;
720}
721
722static void vl_api_create_vlan_subif_reply_t_handler_json
723 (vl_api_create_vlan_subif_reply_t * mp)
724{
725 vat_main_t *vam = &vat_main;
726 vat_json_node_t node;
727
728 vat_json_init_object (&node);
729 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
730 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
731
732 vat_json_print (vam->ofp, &node);
733 vat_json_free (&node);
734
735 vam->retval = ntohl (mp->retval);
736 vam->result_ready = 1;
737}
738
739static void vl_api_create_subif_reply_t_handler
740 (vl_api_create_subif_reply_t * mp)
741{
742 vat_main_t *vam = &vat_main;
743 i32 retval = ntohl (mp->retval);
744
745 vam->retval = retval;
746 vam->regenerate_interface_table = 1;
747 vam->sw_if_index = ntohl (mp->sw_if_index);
748 vam->result_ready = 1;
749}
750
751static void vl_api_create_subif_reply_t_handler_json
752 (vl_api_create_subif_reply_t * mp)
753{
754 vat_main_t *vam = &vat_main;
755 vat_json_node_t node;
756
757 vat_json_init_object (&node);
758 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
759 vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index));
760
761 vat_json_print (vam->ofp, &node);
762 vat_json_free (&node);
763
764 vam->retval = ntohl (mp->retval);
765 vam->result_ready = 1;
766}
767
768static void vl_api_interface_name_renumber_reply_t_handler
769 (vl_api_interface_name_renumber_reply_t * mp)
770{
771 vat_main_t *vam = &vat_main;
772 i32 retval = ntohl (mp->retval);
773
774 vam->retval = retval;
775 vam->regenerate_interface_table = 1;
776 vam->result_ready = 1;
777}
778
779static void vl_api_interface_name_renumber_reply_t_handler_json
780 (vl_api_interface_name_renumber_reply_t * mp)
781{
782 vat_main_t *vam = &vat_main;
783 vat_json_node_t node;
784
785 vat_json_init_object (&node);
786 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
787
788 vat_json_print (vam->ofp, &node);
789 vat_json_free (&node);
790
791 vam->retval = ntohl (mp->retval);
792 vam->result_ready = 1;
793}
794
795/*
796 * Special-case: build the interface table, maintain
797 * the next loopback sw_if_index vbl.
798 */
799static void vl_api_sw_interface_details_t_handler
800 (vl_api_sw_interface_details_t * mp)
801{
802 vat_main_t *vam = &vat_main;
Ole Troane5ff5a32019-08-23 22:55:18 +0200803 u8 *s = format (0, "%s%c", mp->interface_name, 0);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100804
805 hash_set_mem (vam->sw_if_index_by_interface_name, s,
806 ntohl (mp->sw_if_index));
807
808 /* In sub interface case, fill the sub interface table entry */
809 if (mp->sw_if_index != mp->sup_sw_if_index)
810 {
811 sw_interface_subif_t *sub = NULL;
812
813 vec_add2 (vam->sw_if_subif_table, sub, 1);
814
815 vec_validate (sub->interface_name, strlen ((char *) s) + 1);
816 strncpy ((char *) sub->interface_name, (char *) s,
817 vec_len (sub->interface_name));
818 sub->sw_if_index = ntohl (mp->sw_if_index);
819 sub->sub_id = ntohl (mp->sub_id);
820
Jakub Grajciar053204a2019-03-18 13:17:53 +0100821 sub->raw_flags = ntohl (mp->sub_if_flags & SUB_IF_API_FLAG_MASK_VNET);
822
Damjan Marion7cd468a2016-12-19 23:05:39 +0100823 sub->sub_number_of_tags = mp->sub_number_of_tags;
824 sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id);
825 sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100826
827 /* vlan tag rewrite */
828 sub->vtr_op = ntohl (mp->vtr_op);
829 sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q);
830 sub->vtr_tag1 = ntohl (mp->vtr_tag1);
831 sub->vtr_tag2 = ntohl (mp->vtr_tag2);
832 }
833}
834
835static void vl_api_sw_interface_details_t_handler_json
836 (vl_api_sw_interface_details_t * mp)
837{
838 vat_main_t *vam = &vat_main;
839 vat_json_node_t *node = NULL;
840
841 if (VAT_JSON_ARRAY != vam->json_tree.type)
842 {
843 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
844 vat_json_init_array (&vam->json_tree);
845 }
846 node = vat_json_array_add (&vam->json_tree);
847
848 vat_json_init_object (node);
849 vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
850 vat_json_object_add_uint (node, "sup_sw_if_index",
851 ntohl (mp->sup_sw_if_index));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100852 vat_json_object_add_bytes (node, "l2_address", mp->l2_address,
853 sizeof (mp->l2_address));
854 vat_json_object_add_string_copy (node, "interface_name",
Ole Troane5ff5a32019-08-23 22:55:18 +0200855 mp->interface_name);
Mohsin Kazmide312c22019-09-27 13:44:28 +0200856 vat_json_object_add_string_copy (node, "interface_dev_type",
857 mp->interface_dev_type);
Jakub Grajciar053204a2019-03-18 13:17:53 +0100858 vat_json_object_add_uint (node, "flags", mp->flags);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100859 vat_json_object_add_uint (node, "link_duplex", mp->link_duplex);
860 vat_json_object_add_uint (node, "link_speed", mp->link_speed);
Damjan Marionfe7d4a22018-04-13 19:43:39 +0200861 vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100862 vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100863 vat_json_object_add_uint (node, "sub_number_of_tags",
864 mp->sub_number_of_tags);
865 vat_json_object_add_uint (node, "sub_outer_vlan_id",
866 ntohs (mp->sub_outer_vlan_id));
867 vat_json_object_add_uint (node, "sub_inner_vlan_id",
868 ntohs (mp->sub_inner_vlan_id));
Jakub Grajciar053204a2019-03-18 13:17:53 +0100869 vat_json_object_add_uint (node, "sub_if_flags", ntohl (mp->sub_if_flags));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100870 vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op));
871 vat_json_object_add_uint (node, "vtr_push_dot1q",
872 ntohl (mp->vtr_push_dot1q));
873 vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1));
874 vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2));
Jakub Grajciar053204a2019-03-18 13:17:53 +0100875 if (ntohl (mp->sub_if_flags) & SUB_IF_API_FLAG_DOT1AH)
Pavel Kotucek65e84572017-01-16 17:01:56 +0100876 {
877 vat_json_object_add_string_copy (node, "pbb_vtr_dmac",
878 format (0, "%U",
879 format_ethernet_address,
880 &mp->b_dmac));
881 vat_json_object_add_string_copy (node, "pbb_vtr_smac",
882 format (0, "%U",
883 format_ethernet_address,
884 &mp->b_smac));
885 vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid);
886 vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid);
887 }
Damjan Marion7cd468a2016-12-19 23:05:39 +0100888}
889
Dave Baracha1a093d2017-03-02 13:13:23 -0500890#if VPP_API_TEST_BUILTIN == 0
Neale Rannsa07bd702017-08-07 07:53:49 -0700891static void vl_api_sw_interface_event_t_handler
892 (vl_api_sw_interface_event_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100893{
894 vat_main_t *vam = &vat_main;
895 if (vam->interface_event_display)
896 errmsg ("interface flags: sw_if_index %d %s %s",
897 ntohl (mp->sw_if_index),
Jakub Grajciar053204a2019-03-18 13:17:53 +0100898 ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_ADMIN_UP) ?
899 "admin-up" : "admin-down",
900 ((ntohl (mp->flags)) & IF_STATUS_API_FLAG_LINK_UP) ?
901 "link-up" : "link-down");
Damjan Marion7cd468a2016-12-19 23:05:39 +0100902}
Dave Baracha1a093d2017-03-02 13:13:23 -0500903#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +0100904
Benoît Ganne49ee6842019-04-30 11:50:46 +0200905__clib_unused static void
906vl_api_sw_interface_event_t_handler_json (vl_api_sw_interface_event_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100907{
908 /* JSON output not supported */
909}
910
911static void
912vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp)
913{
914 vat_main_t *vam = &vat_main;
915 i32 retval = ntohl (mp->retval);
916
917 vam->retval = retval;
Damjan Marion7bee80c2017-04-26 15:32:12 +0200918 vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100919 vam->result_ready = 1;
920}
921
922static void
923vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp)
924{
925 vat_main_t *vam = &vat_main;
926 vat_json_node_t node;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100927 void *oldheap;
928 u8 *reply;
929
930 vat_json_init_object (&node);
931 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
932 vat_json_object_add_uint (&node, "reply_in_shmem",
933 ntohl (mp->reply_in_shmem));
934 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100935 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +0100936
Damjan Marion7bee80c2017-04-26 15:32:12 +0200937 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100938 vec_free (reply);
939
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +0100940 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100941
942 vat_json_print (vam->ofp, &node);
943 vat_json_free (&node);
944
945 vam->retval = ntohl (mp->retval);
946 vam->result_ready = 1;
947}
948
949static void
950vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp)
951{
952 vat_main_t *vam = &vat_main;
953 i32 retval = ntohl (mp->retval);
Dave Barach59b25652017-09-10 15:04:27 -0400954
955 vec_reset_length (vam->cmd_reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100956
957 vam->retval = retval;
Dave Barach59b25652017-09-10 15:04:27 -0400958 if (retval == 0)
Dave Barach77841402020-04-29 17:04:10 -0400959 vam->cmd_reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100960 vam->result_ready = 1;
961}
962
963static void
964vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp)
965{
966 vat_main_t *vam = &vat_main;
967 vat_json_node_t node;
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100968 u8 *reply = 0; /* reply vector */
Damjan Marion7cd468a2016-12-19 23:05:39 +0100969
Dave Barach77841402020-04-29 17:04:10 -0400970 reply = vl_api_from_api_to_new_vec (mp, &mp->reply);
Dave Barach59b25652017-09-10 15:04:27 -0400971 vec_reset_length (vam->cmd_reply);
972
Damjan Marion7cd468a2016-12-19 23:05:39 +0100973 vat_json_init_object (&node);
974 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100975 vat_json_object_add_string_copy (&node, "reply", reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100976
977 vat_json_print (vam->ofp, &node);
978 vat_json_free (&node);
Jakub Grajciar2dbee932020-02-07 11:30:26 +0100979 vec_free (reply);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100980
981 vam->retval = ntohl (mp->retval);
982 vam->result_ready = 1;
983}
984
Damjan Marion7cd468a2016-12-19 23:05:39 +0100985static void vl_api_get_node_index_reply_t_handler
986 (vl_api_get_node_index_reply_t * mp)
987{
988 vat_main_t *vam = &vat_main;
989 i32 retval = ntohl (mp->retval);
990 if (vam->async_mode)
991 {
992 vam->async_errors += (retval < 0);
993 }
994 else
995 {
996 vam->retval = retval;
997 if (retval == 0)
998 errmsg ("node index %d", ntohl (mp->node_index));
999 vam->result_ready = 1;
1000 }
1001}
1002
1003static void vl_api_get_node_index_reply_t_handler_json
1004 (vl_api_get_node_index_reply_t * mp)
1005{
1006 vat_main_t *vam = &vat_main;
1007 vat_json_node_t node;
1008
1009 vat_json_init_object (&node);
1010 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1011 vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index));
1012
1013 vat_json_print (vam->ofp, &node);
1014 vat_json_free (&node);
1015
1016 vam->retval = ntohl (mp->retval);
1017 vam->result_ready = 1;
1018}
1019
1020static void vl_api_get_next_index_reply_t_handler
1021 (vl_api_get_next_index_reply_t * mp)
1022{
1023 vat_main_t *vam = &vat_main;
1024 i32 retval = ntohl (mp->retval);
1025 if (vam->async_mode)
1026 {
1027 vam->async_errors += (retval < 0);
1028 }
1029 else
1030 {
1031 vam->retval = retval;
1032 if (retval == 0)
1033 errmsg ("next node index %d", ntohl (mp->next_index));
1034 vam->result_ready = 1;
1035 }
1036}
1037
1038static void vl_api_get_next_index_reply_t_handler_json
1039 (vl_api_get_next_index_reply_t * mp)
1040{
1041 vat_main_t *vam = &vat_main;
1042 vat_json_node_t node;
1043
1044 vat_json_init_object (&node);
1045 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1046 vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1047
1048 vat_json_print (vam->ofp, &node);
1049 vat_json_free (&node);
1050
1051 vam->retval = ntohl (mp->retval);
1052 vam->result_ready = 1;
1053}
1054
1055static void vl_api_add_node_next_reply_t_handler
1056 (vl_api_add_node_next_reply_t * mp)
1057{
1058 vat_main_t *vam = &vat_main;
1059 i32 retval = ntohl (mp->retval);
1060 if (vam->async_mode)
1061 {
1062 vam->async_errors += (retval < 0);
1063 }
1064 else
1065 {
1066 vam->retval = retval;
1067 if (retval == 0)
1068 errmsg ("next index %d", ntohl (mp->next_index));
1069 vam->result_ready = 1;
1070 }
1071}
1072
1073static void vl_api_add_node_next_reply_t_handler_json
1074 (vl_api_add_node_next_reply_t * mp)
1075{
1076 vat_main_t *vam = &vat_main;
1077 vat_json_node_t node;
1078
1079 vat_json_init_object (&node);
1080 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1081 vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index));
1082
1083 vat_json_print (vam->ofp, &node);
1084 vat_json_free (&node);
1085
1086 vam->retval = ntohl (mp->retval);
1087 vam->result_ready = 1;
1088}
1089
1090static void vl_api_show_version_reply_t_handler
1091 (vl_api_show_version_reply_t * mp)
1092{
1093 vat_main_t *vam = &vat_main;
1094 i32 retval = ntohl (mp->retval);
1095
1096 if (retval >= 0)
1097 {
Ole Troane5ff5a32019-08-23 22:55:18 +02001098 errmsg (" program: %s", mp->program);
1099 errmsg (" version: %s", mp->version);
1100 errmsg (" build date: %s", mp->build_date);
1101 errmsg ("build directory: %s", mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001102 }
1103 vam->retval = retval;
1104 vam->result_ready = 1;
1105}
1106
1107static void vl_api_show_version_reply_t_handler_json
1108 (vl_api_show_version_reply_t * mp)
1109{
1110 vat_main_t *vam = &vat_main;
1111 vat_json_node_t node;
1112
1113 vat_json_init_object (&node);
1114 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
Ole Troane5ff5a32019-08-23 22:55:18 +02001115 vat_json_object_add_string_copy (&node, "program", mp->program);
1116 vat_json_object_add_string_copy (&node, "version", mp->version);
1117 vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001118 vat_json_object_add_string_copy (&node, "build_directory",
Ole Troane5ff5a32019-08-23 22:55:18 +02001119 mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001120
1121 vat_json_print (vam->ofp, &node);
1122 vat_json_free (&node);
1123
1124 vam->retval = ntohl (mp->retval);
1125 vam->result_ready = 1;
1126}
1127
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001128static void vl_api_show_threads_reply_t_handler
1129 (vl_api_show_threads_reply_t * mp)
1130{
1131 vat_main_t *vam = &vat_main;
1132 i32 retval = ntohl (mp->retval);
1133 int i, count = 0;
1134
1135 if (retval >= 0)
1136 count = ntohl (mp->count);
1137
1138 for (i = 0; i < count; i++)
1139 print (vam->ofp,
1140 "\n%-2d %-11s %-11s %-5d %-6d %-4d %-6d",
1141 ntohl (mp->thread_data[i].id), mp->thread_data[i].name,
1142 mp->thread_data[i].type, ntohl (mp->thread_data[i].pid),
1143 ntohl (mp->thread_data[i].cpu_id), ntohl (mp->thread_data[i].core),
1144 ntohl (mp->thread_data[i].cpu_socket));
1145
1146 vam->retval = retval;
1147 vam->result_ready = 1;
1148}
1149
1150static void vl_api_show_threads_reply_t_handler_json
1151 (vl_api_show_threads_reply_t * mp)
1152{
1153 vat_main_t *vam = &vat_main;
1154 vat_json_node_t node;
1155 vl_api_thread_data_t *td;
Mohsin Kazmi5df628b2018-10-01 17:41:08 +02001156 i32 retval = ntohl (mp->retval);
1157 int i, count = 0;
1158
1159 if (retval >= 0)
1160 count = ntohl (mp->count);
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001161
1162 vat_json_init_object (&node);
Mohsin Kazmi5df628b2018-10-01 17:41:08 +02001163 vat_json_object_add_int (&node, "retval", retval);
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001164 vat_json_object_add_uint (&node, "count", count);
1165
1166 for (i = 0; i < count; i++)
1167 {
1168 td = &mp->thread_data[i];
1169 vat_json_object_add_uint (&node, "id", ntohl (td->id));
1170 vat_json_object_add_string_copy (&node, "name", td->name);
1171 vat_json_object_add_string_copy (&node, "type", td->type);
1172 vat_json_object_add_uint (&node, "pid", ntohl (td->pid));
1173 vat_json_object_add_int (&node, "cpu_id", ntohl (td->cpu_id));
1174 vat_json_object_add_int (&node, "core", ntohl (td->id));
1175 vat_json_object_add_int (&node, "cpu_socket", ntohl (td->cpu_socket));
1176 }
1177
1178 vat_json_print (vam->ofp, &node);
1179 vat_json_free (&node);
1180
Mohsin Kazmi5df628b2018-10-01 17:41:08 +02001181 vam->retval = retval;
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001182 vam->result_ready = 1;
1183}
1184
1185static int
1186api_show_threads (vat_main_t * vam)
1187{
1188 vl_api_show_threads_t *mp;
1189 int ret;
1190
1191 print (vam->ofp,
1192 "\n%-2s %-11s %-11s %-5s %-6s %-4s %-6s",
1193 "ID", "Name", "Type", "LWP", "cpu_id", "Core", "Socket");
1194
1195 M (SHOW_THREADS, mp);
1196
1197 S (mp);
1198 W (ret);
1199 return ret;
1200}
1201
Ole Troan01384fe2017-05-12 11:55:35 +02001202#define vl_api_bridge_domain_details_t_endian vl_noop_handler
1203#define vl_api_bridge_domain_details_t_print vl_noop_handler
1204
Damjan Marion7cd468a2016-12-19 23:05:39 +01001205static void vl_api_control_ping_reply_t_handler
1206 (vl_api_control_ping_reply_t * mp)
1207{
1208 vat_main_t *vam = &vat_main;
1209 i32 retval = ntohl (mp->retval);
1210 if (vam->async_mode)
1211 {
1212 vam->async_errors += (retval < 0);
1213 }
1214 else
1215 {
1216 vam->retval = retval;
1217 vam->result_ready = 1;
1218 }
Florin Coras90a63982017-12-19 04:50:01 -08001219 if (vam->socket_client_main)
1220 vam->socket_client_main->control_pings_outstanding--;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001221}
1222
1223static void vl_api_control_ping_reply_t_handler_json
1224 (vl_api_control_ping_reply_t * mp)
1225{
1226 vat_main_t *vam = &vat_main;
1227 i32 retval = ntohl (mp->retval);
1228
1229 if (VAT_JSON_NONE != vam->json_tree.type)
1230 {
1231 vat_json_print (vam->ofp, &vam->json_tree);
1232 vat_json_free (&vam->json_tree);
1233 vam->json_tree.type = VAT_JSON_NONE;
1234 }
1235 else
1236 {
1237 /* just print [] */
1238 vat_json_init_array (&vam->json_tree);
1239 vat_json_print (vam->ofp, &vam->json_tree);
1240 vam->json_tree.type = VAT_JSON_NONE;
1241 }
1242
1243 vam->retval = retval;
1244 vam->result_ready = 1;
1245}
1246
Damjan Marion7cd468a2016-12-19 23:05:39 +01001247
Damjan Marion7cd468a2016-12-19 23:05:39 +01001248static void vl_api_ip_address_details_t_handler
1249 (vl_api_ip_address_details_t * mp)
1250{
1251 vat_main_t *vam = &vat_main;
1252 static ip_address_details_t empty_ip_address_details = { {0} };
1253 ip_address_details_t *address = NULL;
1254 ip_details_t *current_ip_details = NULL;
1255 ip_details_t *details = NULL;
1256
1257 details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1258
1259 if (!details || vam->current_sw_if_index >= vec_len (details)
1260 || !details[vam->current_sw_if_index].present)
1261 {
1262 errmsg ("ip address details arrived but not stored");
1263 errmsg ("ip_dump should be called first");
1264 return;
1265 }
1266
1267 current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1268
1269#define addresses (current_ip_details->addr)
1270
1271 vec_validate_init_empty (addresses, vec_len (addresses),
1272 empty_ip_address_details);
1273
1274 address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1275
Neale Ranns097fa662018-05-01 05:17:55 -07001276 clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
Paul Vinciguerraab055082019-06-06 14:07:55 -04001277 address->prefix_length = mp->prefix.len;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001278#undef addresses
1279}
1280
1281static void vl_api_ip_address_details_t_handler_json
1282 (vl_api_ip_address_details_t * mp)
1283{
1284 vat_main_t *vam = &vat_main;
1285 vat_json_node_t *node = NULL;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001286
1287 if (VAT_JSON_ARRAY != vam->json_tree.type)
1288 {
1289 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1290 vat_json_init_array (&vam->json_tree);
1291 }
1292 node = vat_json_array_add (&vam->json_tree);
1293
1294 vat_json_init_object (node);
Neale Ranns097fa662018-05-01 05:17:55 -07001295 vat_json_object_add_prefix (node, &mp->prefix);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001296}
1297
1298static void
1299vl_api_ip_details_t_handler (vl_api_ip_details_t * mp)
1300{
1301 vat_main_t *vam = &vat_main;
1302 static ip_details_t empty_ip_details = { 0 };
1303 ip_details_t *ip = NULL;
1304 u32 sw_if_index = ~0;
1305
1306 sw_if_index = ntohl (mp->sw_if_index);
1307
1308 vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1309 sw_if_index, empty_ip_details);
1310
1311 ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1312 sw_if_index);
1313
1314 ip->present = 1;
1315}
1316
1317static void
1318vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp)
1319{
1320 vat_main_t *vam = &vat_main;
1321
1322 if (VAT_JSON_ARRAY != vam->json_tree.type)
1323 {
1324 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
1325 vat_json_init_array (&vam->json_tree);
1326 }
1327 vat_json_array_add_uint (&vam->json_tree,
1328 clib_net_to_host_u32 (mp->sw_if_index));
1329}
1330
Damjan Marion7cd468a2016-12-19 23:05:39 +01001331static void vl_api_get_first_msg_id_reply_t_handler
1332 (vl_api_get_first_msg_id_reply_t * mp)
1333{
1334 vat_main_t *vam = &vat_main;
1335 i32 retval = ntohl (mp->retval);
1336
1337 if (vam->async_mode)
1338 {
1339 vam->async_errors += (retval < 0);
1340 }
1341 else
1342 {
1343 vam->retval = retval;
1344 vam->result_ready = 1;
1345 }
1346 if (retval >= 0)
1347 {
1348 errmsg ("first message id %d", ntohs (mp->first_msg_id));
1349 }
1350}
1351
1352static void vl_api_get_first_msg_id_reply_t_handler_json
1353 (vl_api_get_first_msg_id_reply_t * mp)
1354{
1355 vat_main_t *vam = &vat_main;
1356 vat_json_node_t node;
1357
1358 vat_json_init_object (&node);
1359 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1360 vat_json_object_add_uint (&node, "first_msg_id",
1361 (uint) ntohs (mp->first_msg_id));
1362
1363 vat_json_print (vam->ofp, &node);
1364 vat_json_free (&node);
1365
1366 vam->retval = ntohl (mp->retval);
1367 vam->result_ready = 1;
1368}
1369
1370static void vl_api_get_node_graph_reply_t_handler
1371 (vl_api_get_node_graph_reply_t * mp)
1372{
1373 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001374 i32 retval = ntohl (mp->retval);
1375 u8 *pvt_copy, *reply;
1376 void *oldheap;
1377 vlib_node_t *node;
1378 int i;
1379
1380 if (vam->async_mode)
1381 {
1382 vam->async_errors += (retval < 0);
1383 }
1384 else
1385 {
1386 vam->retval = retval;
1387 vam->result_ready = 1;
1388 }
1389
1390 /* "Should never happen..." */
1391 if (retval != 0)
1392 return;
1393
Damjan Marion7bee80c2017-04-26 15:32:12 +02001394 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001395 pvt_copy = vec_dup (reply);
1396
1397 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001398 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01001399
1400 vec_free (reply);
1401
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001402 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001403
1404 if (vam->graph_nodes)
1405 {
1406 hash_free (vam->graph_node_index_by_name);
1407
Dave Barach1ddbc012018-06-13 09:26:05 -04001408 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001409 {
Dave Barach1ddbc012018-06-13 09:26:05 -04001410 node = vam->graph_nodes[0][i];
Damjan Marion7cd468a2016-12-19 23:05:39 +01001411 vec_free (node->name);
1412 vec_free (node->next_nodes);
1413 vec_free (node);
1414 }
Dave Barach1ddbc012018-06-13 09:26:05 -04001415 vec_free (vam->graph_nodes[0]);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001416 vec_free (vam->graph_nodes);
1417 }
1418
1419 vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword));
1420 vam->graph_nodes = vlib_node_unserialize (pvt_copy);
1421 vec_free (pvt_copy);
1422
Dave Barach1ddbc012018-06-13 09:26:05 -04001423 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001424 {
Dave Barach1ddbc012018-06-13 09:26:05 -04001425 node = vam->graph_nodes[0][i];
Damjan Marion7cd468a2016-12-19 23:05:39 +01001426 hash_set_mem (vam->graph_node_index_by_name, node->name, i);
1427 }
1428}
1429
1430static void vl_api_get_node_graph_reply_t_handler_json
1431 (vl_api_get_node_graph_reply_t * mp)
1432{
1433 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001434 void *oldheap;
1435 vat_json_node_t node;
1436 u8 *reply;
1437
1438 /* $$$$ make this real? */
1439 vat_json_init_object (&node);
1440 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
1441 vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem);
1442
Damjan Marion7bee80c2017-04-26 15:32:12 +02001443 reply = uword_to_pointer (mp->reply_in_shmem, u8 *);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001444
1445 /* Toss the shared-memory original... */
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001446 oldheap = vl_msg_push_heap ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01001447
1448 vec_free (reply);
1449
Nathan Skrzypczak0aa40132019-11-25 16:29:38 +01001450 vl_msg_pop_heap (oldheap);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001451
1452 vat_json_print (vam->ofp, &node);
1453 vat_json_free (&node);
1454
1455 vam->retval = ntohl (mp->retval);
1456 vam->result_ready = 1;
1457}
1458
Damjan Marion7cd468a2016-12-19 23:05:39 +01001459/* Format hex dump. */
1460u8 *
1461format_hex_bytes (u8 * s, va_list * va)
1462{
1463 u8 *bytes = va_arg (*va, u8 *);
1464 int n_bytes = va_arg (*va, int);
1465 uword i;
1466
1467 /* Print short or long form depending on byte count. */
1468 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +02001469 u32 indent = format_get_indent (s);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001470
1471 if (n_bytes == 0)
1472 return s;
1473
1474 for (i = 0; i < n_bytes; i++)
1475 {
1476 if (!short_form && (i % 32) == 0)
1477 s = format (s, "%08x: ", i);
1478 s = format (s, "%02x", bytes[i]);
1479 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
1480 s = format (s, "\n%U", format_white_space, indent);
1481 }
1482
1483 return s;
1484}
1485
Damjan Marion7cd468a2016-12-19 23:05:39 +01001486/*
1487 * Generate boilerplate reply handlers, which
1488 * dig the return value out of the xxx_reply_t API message,
1489 * stick it into vam->retval, and set vam->result_ready
1490 *
1491 * Could also do this by pointing N message decode slots at
1492 * a single function, but that could break in subtle ways.
1493 */
1494
1495#define foreach_standard_reply_retval_handler \
1496_(sw_interface_set_flags_reply) \
1497_(sw_interface_add_del_address_reply) \
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001498_(sw_interface_set_rx_placement_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001499_(sw_interface_set_table_reply) \
Neale Ranns097fa662018-05-01 05:17:55 -07001500_(ip_route_add_del_reply) \
Neale Ranns28ab9cc2017-08-14 07:18:42 -07001501_(ip_table_add_del_reply) \
Neale Ranns9db6ada2019-11-08 12:42:31 +00001502_(ip_table_replace_begin_reply) \
1503_(ip_table_flush_reply) \
1504_(ip_table_replace_end_reply) \
Neale Ranns32e1c012016-11-22 17:07:28 +00001505_(ip_mroute_add_del_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001506_(sw_interface_set_unnumbered_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001507_(set_ip_flow_hash_reply) \
1508_(sw_interface_ip6_enable_disable_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001509_(delete_loopback_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001510_(want_interface_events_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001511_(sw_interface_clear_stats_reply) \
Dave Barach65457162017-10-10 17:53:14 -04001512_(ioam_enable_reply) \
1513_(ioam_disable_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001514_(ip_source_and_port_range_check_add_del_reply) \
1515_(ip_source_and_port_range_check_interface_add_del_reply)\
1516_(delete_subif_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001517_(sw_interface_tag_add_del_reply) \
Matthew Smithe0792fd2019-07-12 11:48:24 -05001518_(sw_interface_add_del_mac_address_reply) \
Ole Troand7231612018-06-07 10:17:57 +02001519_(hw_interface_set_mtu_reply) \
Florin Coras595992c2017-11-06 17:17:08 -08001520_(session_rule_add_del_reply) \
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +01001521_(ip_container_proxy_add_del_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001522
1523#define _(n) \
1524 static void vl_api_##n##_t_handler \
1525 (vl_api_##n##_t * mp) \
1526 { \
1527 vat_main_t * vam = &vat_main; \
1528 i32 retval = ntohl(mp->retval); \
1529 if (vam->async_mode) { \
1530 vam->async_errors += (retval < 0); \
1531 } else { \
1532 vam->retval = retval; \
1533 vam->result_ready = 1; \
1534 } \
1535 }
1536foreach_standard_reply_retval_handler;
1537#undef _
1538
1539#define _(n) \
1540 static void vl_api_##n##_t_handler_json \
1541 (vl_api_##n##_t * mp) \
1542 { \
1543 vat_main_t * vam = &vat_main; \
1544 vat_json_node_t node; \
1545 vat_json_init_object(&node); \
1546 vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
1547 vat_json_print(vam->ofp, &node); \
1548 vam->retval = ntohl(mp->retval); \
1549 vam->result_ready = 1; \
1550 }
1551foreach_standard_reply_retval_handler;
1552#undef _
1553
1554/*
1555 * Table of message reply handlers, must include boilerplate handlers
1556 * we just generated
1557 */
1558
1559#define foreach_vpe_api_reply_msg \
1560_(CREATE_LOOPBACK_REPLY, create_loopback_reply) \
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001561_(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001562_(SW_INTERFACE_DETAILS, sw_interface_details) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001563_(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply) \
1564_(CONTROL_PING_REPLY, control_ping_reply) \
1565_(CLI_REPLY, cli_reply) \
1566_(CLI_INBAND_REPLY, cli_inband_reply) \
1567_(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY, \
1568 sw_interface_add_del_address_reply) \
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02001569_(SW_INTERFACE_SET_RX_PLACEMENT_REPLY, sw_interface_set_rx_placement_reply) \
Mohsin Kazmif0b42f42018-09-10 18:11:00 +02001570_(SW_INTERFACE_RX_PLACEMENT_DETAILS, sw_interface_rx_placement_details) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001571_(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply) \
Neale Ranns097fa662018-05-01 05:17:55 -07001572_(IP_ROUTE_ADD_DEL_REPLY, ip_route_add_del_reply) \
Neale Ranns28ab9cc2017-08-14 07:18:42 -07001573_(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply) \
Neale Ranns9db6ada2019-11-08 12:42:31 +00001574_(IP_TABLE_REPLACE_BEGIN_REPLY, ip_table_replace_begin_reply) \
1575_(IP_TABLE_FLUSH_REPLY, ip_table_flush_reply) \
1576_(IP_TABLE_REPLACE_END_REPLY, ip_table_replace_end_reply) \
Neale Ranns32e1c012016-11-22 17:07:28 +00001577_(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001578_(SW_INTERFACE_SET_UNNUMBERED_REPLY, \
1579 sw_interface_set_unnumbered_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001580_(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply) \
1581_(CREATE_SUBIF_REPLY, create_subif_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001582_(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply) \
1583_(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY, \
1584 sw_interface_ip6_enable_disable_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001585_(GET_NODE_INDEX_REPLY, get_node_index_reply) \
1586_(ADD_NODE_NEXT_REPLY, add_node_next_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001587_(SHOW_VERSION_REPLY, show_version_reply) \
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02001588_(SHOW_THREADS_REPLY, show_threads_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001589_(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001590_(IP_ADDRESS_DETAILS, ip_address_details) \
1591_(IP_DETAILS, ip_details) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001592_(DELETE_LOOPBACK_REPLY, delete_loopback_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001593_(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001594_(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001595_(GET_NODE_GRAPH_REPLY, get_node_graph_reply) \
1596_(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply) \
1597_(IOAM_ENABLE_REPLY, ioam_enable_reply) \
1598_(IOAM_DISABLE_REPLY, ioam_disable_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001599_(GET_NEXT_INDEX_REPLY, get_next_index_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001600_(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY, \
1601 ip_source_and_port_range_check_add_del_reply) \
1602_(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY, \
1603 ip_source_and_port_range_check_interface_add_del_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001604_(DELETE_SUBIF_REPLY, delete_subif_reply) \
Neale Ranns097fa662018-05-01 05:17:55 -07001605_(IP_TABLE_DETAILS, ip_table_details) \
1606_(IP_ROUTE_DETAILS, ip_route_details) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001607_(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply) \
Matthew Smithe0792fd2019-07-12 11:48:24 -05001608_(SW_INTERFACE_ADD_DEL_MAC_ADDRESS_REPLY, sw_interface_add_del_mac_address_reply) \
Ole Troand7231612018-06-07 10:17:57 +02001609_(HW_INTERFACE_SET_MTU_REPLY, hw_interface_set_mtu_reply) \
Pavel Kotucek6899a302017-06-08 08:46:10 +02001610_(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply) \
Dave Barach65457162017-10-10 17:53:14 -04001611_(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply) \
Florin Coras6c36f532017-11-03 18:32:34 -07001612_(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply) \
Florin Coras595992c2017-11-06 17:17:08 -08001613_(SESSION_RULES_DETAILS, session_rules_details) \
1614_(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +01001615
Dave Baracha1a093d2017-03-02 13:13:23 -05001616#define foreach_standalone_reply_msg \
Ole Troanf49ba0e2018-11-13 14:04:50 +01001617_(SW_INTERFACE_EVENT, sw_interface_event)
Dave Baracha1a093d2017-03-02 13:13:23 -05001618
Damjan Marion7cd468a2016-12-19 23:05:39 +01001619typedef struct
1620{
1621 u8 *name;
1622 u32 value;
1623} name_sort_t;
1624
Damjan Marion7cd468a2016-12-19 23:05:39 +01001625#define STR_VTR_OP_CASE(op) \
1626 case L2_VTR_ ## op: \
1627 return "" # op;
1628
1629static const char *
1630str_vtr_op (u32 vtr_op)
1631{
1632 switch (vtr_op)
1633 {
1634 STR_VTR_OP_CASE (DISABLED);
1635 STR_VTR_OP_CASE (PUSH_1);
1636 STR_VTR_OP_CASE (PUSH_2);
1637 STR_VTR_OP_CASE (POP_1);
1638 STR_VTR_OP_CASE (POP_2);
1639 STR_VTR_OP_CASE (TRANSLATE_1_1);
1640 STR_VTR_OP_CASE (TRANSLATE_1_2);
1641 STR_VTR_OP_CASE (TRANSLATE_2_1);
1642 STR_VTR_OP_CASE (TRANSLATE_2_2);
1643 }
1644
1645 return "UNKNOWN";
1646}
1647
1648static int
1649dump_sub_interface_table (vat_main_t * vam)
1650{
1651 const sw_interface_subif_t *sub = NULL;
1652
1653 if (vam->json_output)
1654 {
1655 clib_warning
1656 ("JSON output supported only for VPE API calls and dump_stats_table");
1657 return -99;
1658 }
1659
1660 print (vam->ofp,
1661 "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
1662 "Interface", "sw_if_index",
1663 "sub id", "dot1ad", "tags", "outer id",
1664 "inner id", "exact", "default", "outer any", "inner any");
1665
1666 vec_foreach (sub, vam->sw_if_subif_table)
1667 {
1668 print (vam->ofp,
1669 "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
1670 sub->interface_name,
1671 sub->sw_if_index,
1672 sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q",
1673 sub->sub_number_of_tags, sub->sub_outer_vlan_id,
1674 sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default,
1675 sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
1676 if (sub->vtr_op != L2_VTR_DISABLED)
1677 {
1678 print (vam->ofp,
1679 " vlan-tag-rewrite - op: %-14s [ dot1q: %d "
1680 "tag1: %d tag2: %d ]",
1681 str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q,
1682 sub->vtr_tag1, sub->vtr_tag2);
1683 }
1684 }
1685
1686 return 0;
1687}
1688
1689static int
1690name_sort_cmp (void *a1, void *a2)
1691{
1692 name_sort_t *n1 = a1;
1693 name_sort_t *n2 = a2;
1694
1695 return strcmp ((char *) n1->name, (char *) n2->name);
1696}
1697
1698static int
1699dump_interface_table (vat_main_t * vam)
1700{
1701 hash_pair_t *p;
1702 name_sort_t *nses = 0, *ns;
1703
1704 if (vam->json_output)
1705 {
1706 clib_warning
1707 ("JSON output supported only for VPE API calls and dump_stats_table");
1708 return -99;
1709 }
1710
1711 /* *INDENT-OFF* */
1712 hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1713 ({
1714 vec_add2 (nses, ns, 1);
1715 ns->name = (u8 *)(p->key);
1716 ns->value = (u32) p->value[0];
1717 }));
1718 /* *INDENT-ON* */
1719
1720 vec_sort_with_function (nses, name_sort_cmp);
1721
1722 print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
1723 vec_foreach (ns, nses)
1724 {
1725 print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
1726 }
1727 vec_free (nses);
1728 return 0;
1729}
1730
1731static int
1732dump_ip_table (vat_main_t * vam, int is_ipv6)
1733{
1734 const ip_details_t *det = NULL;
1735 const ip_address_details_t *address = NULL;
1736 u32 i = ~0;
1737
1738 print (vam->ofp, "%-12s", "sw_if_index");
1739
1740 vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6])
1741 {
1742 i++;
1743 if (!det->present)
1744 {
1745 continue;
1746 }
1747 print (vam->ofp, "%-12d", i);
1748 print (vam->ofp, " %-30s%-13s", "Address", "Prefix length");
1749 if (!det->addr)
1750 {
1751 continue;
1752 }
1753 vec_foreach (address, det->addr)
1754 {
1755 print (vam->ofp,
1756 " %-30U%-13d",
1757 is_ipv6 ? format_ip6_address : format_ip4_address,
1758 address->ip, address->prefix_length);
1759 }
1760 }
1761
1762 return 0;
1763}
1764
1765static int
1766dump_ipv4_table (vat_main_t * vam)
1767{
1768 if (vam->json_output)
1769 {
1770 clib_warning
1771 ("JSON output supported only for VPE API calls and dump_stats_table");
1772 return -99;
1773 }
1774
1775 return dump_ip_table (vam, 0);
1776}
1777
1778static int
1779dump_ipv6_table (vat_main_t * vam)
1780{
1781 if (vam->json_output)
1782 {
1783 clib_warning
1784 ("JSON output supported only for VPE API calls and dump_stats_table");
1785 return -99;
1786 }
1787
1788 return dump_ip_table (vam, 1);
1789}
1790
Damjan Marion7cd468a2016-12-19 23:05:39 +01001791/*
Dave Barach59b25652017-09-10 15:04:27 -04001792 * Pass CLI buffers directly in the CLI_INBAND API message,
1793 * instead of an additional shared memory area.
Damjan Marion7cd468a2016-12-19 23:05:39 +01001794 */
1795static int
1796exec_inband (vat_main_t * vam)
1797{
1798 vl_api_cli_inband_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001799 unformat_input_t *i = vam->input;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001800 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001801
1802 if (vec_len (i->buffer) == 0)
1803 return -1;
1804
1805 if (vam->exec_mode == 0 && unformat (i, "mode"))
1806 {
1807 vam->exec_mode = 1;
1808 return 0;
1809 }
1810 if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit")))
1811 {
1812 vam->exec_mode = 0;
1813 return 0;
1814 }
1815
1816 /*
1817 * In order for the CLI command to work, it
1818 * must be a vector ending in \n, not a C-string ending
1819 * in \n\0.
1820 */
Jakub Grajciar2dbee932020-02-07 11:30:26 +01001821 M2 (CLI_INBAND, mp, vec_len (vam->input->buffer));
1822 vl_api_vec_to_api_string (vam->input->buffer, &mp->cmd);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001823
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001824 S (mp);
Dave Barach59b25652017-09-10 15:04:27 -04001825 W (ret);
1826 /* json responses may or may not include a useful reply... */
1827 if (vec_len (vam->cmd_reply))
Dave Barachcf5e8482017-10-17 11:48:29 -04001828 print (vam->ofp, "%v", (char *) (vam->cmd_reply));
Jon Loeliger56c7b012017-02-01 12:31:41 -06001829 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001830}
1831
Dave Barach59b25652017-09-10 15:04:27 -04001832int
1833exec (vat_main_t * vam)
1834{
1835 return exec_inband (vam);
1836}
1837
Damjan Marion7cd468a2016-12-19 23:05:39 +01001838static int
1839api_create_loopback (vat_main_t * vam)
1840{
1841 unformat_input_t *i = vam->input;
1842 vl_api_create_loopback_t *mp;
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001843 vl_api_create_loopback_instance_t *mp_lbi;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001844 u8 mac_address[6];
1845 u8 mac_set = 0;
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001846 u8 is_specified = 0;
1847 u32 user_instance = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001848 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001849
Dave Barachb7b92992018-10-17 10:38:51 -04001850 clib_memset (mac_address, 0, sizeof (mac_address));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001851
1852 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1853 {
1854 if (unformat (i, "mac %U", unformat_ethernet_address, mac_address))
1855 mac_set = 1;
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001856 if (unformat (i, "instance %d", &user_instance))
1857 is_specified = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001858 else
1859 break;
1860 }
1861
Jon Loeligerc83c3b72017-02-23 13:57:35 -06001862 if (is_specified)
1863 {
1864 M (CREATE_LOOPBACK_INSTANCE, mp_lbi);
1865 mp_lbi->is_specified = is_specified;
1866 if (is_specified)
1867 mp_lbi->user_instance = htonl (user_instance);
1868 if (mac_set)
1869 clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address));
1870 S (mp_lbi);
1871 }
1872 else
1873 {
1874 /* Construct the API message */
1875 M (CREATE_LOOPBACK, mp);
1876 if (mac_set)
1877 clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address));
1878 S (mp);
1879 }
Damjan Marion7cd468a2016-12-19 23:05:39 +01001880
Jon Loeliger56c7b012017-02-01 12:31:41 -06001881 W (ret);
1882 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001883}
1884
1885static int
1886api_delete_loopback (vat_main_t * vam)
1887{
1888 unformat_input_t *i = vam->input;
1889 vl_api_delete_loopback_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001890 u32 sw_if_index = ~0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001891 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001892
1893 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1894 {
1895 if (unformat (i, "sw_if_index %d", &sw_if_index))
1896 ;
1897 else
1898 break;
1899 }
1900
1901 if (sw_if_index == ~0)
1902 {
1903 errmsg ("missing sw_if_index");
1904 return -99;
1905 }
1906
1907 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001908 M (DELETE_LOOPBACK, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001909 mp->sw_if_index = ntohl (sw_if_index);
1910
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001911 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06001912 W (ret);
1913 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001914}
1915
1916static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01001917api_want_interface_events (vat_main_t * vam)
1918{
1919 unformat_input_t *i = vam->input;
1920 vl_api_want_interface_events_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001921 int enable = -1;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001922 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001923
1924 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1925 {
1926 if (unformat (i, "enable"))
1927 enable = 1;
1928 else if (unformat (i, "disable"))
1929 enable = 0;
1930 else
1931 break;
1932 }
1933
1934 if (enable == -1)
1935 {
1936 errmsg ("missing enable|disable");
1937 return -99;
1938 }
1939
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001940 M (WANT_INTERFACE_EVENTS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001941 mp->enable_disable = enable;
1942
1943 vam->interface_event_display = enable;
1944
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001945 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06001946 W (ret);
1947 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001948}
1949
1950
1951/* Note: non-static, called once to set up the initial intfc table */
1952int
1953api_sw_interface_dump (vat_main_t * vam)
1954{
1955 vl_api_sw_interface_dump_t *mp;
Jon Loeliger2d23eca2017-02-01 13:09:58 -06001956 vl_api_control_ping_t *mp_ping;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001957 hash_pair_t *p;
1958 name_sort_t *nses = 0, *ns;
1959 sw_interface_subif_t *sub = NULL;
Jon Loeliger56c7b012017-02-01 12:31:41 -06001960 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001961
1962 /* Toss the old name table */
1963 /* *INDENT-OFF* */
1964 hash_foreach_pair (p, vam->sw_if_index_by_interface_name,
1965 ({
1966 vec_add2 (nses, ns, 1);
1967 ns->name = (u8 *)(p->key);
1968 ns->value = (u32) p->value[0];
1969 }));
1970 /* *INDENT-ON* */
1971
1972 hash_free (vam->sw_if_index_by_interface_name);
1973
1974 vec_foreach (ns, nses) vec_free (ns->name);
1975
1976 vec_free (nses);
1977
1978 vec_foreach (sub, vam->sw_if_subif_table)
1979 {
1980 vec_free (sub->interface_name);
1981 }
1982 vec_free (vam->sw_if_subif_table);
1983
1984 /* recreate the interface name hash table */
1985 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
1986
Dave Barachf72212e2018-01-11 10:25:07 -05001987 /*
1988 * Ask for all interface names. Otherwise, the epic catalog of
1989 * name filters becomes ridiculously long, and vat ends up needing
1990 * to be taught about new interface types.
1991 */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06001992 M (SW_INTERFACE_DUMP, mp);
Jon Loeliger7bc770c2017-01-31 14:03:33 -06001993 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001994
1995 /* Use a control ping for synchronization */
Dave Barach59b25652017-09-10 15:04:27 -04001996 MPING (CONTROL_PING, mp_ping);
Jon Loeliger2d23eca2017-02-01 13:09:58 -06001997 S (mp_ping);
1998
Jon Loeliger56c7b012017-02-01 12:31:41 -06001999 W (ret);
2000 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002001}
2002
2003static int
2004api_sw_interface_set_flags (vat_main_t * vam)
2005{
2006 unformat_input_t *i = vam->input;
2007 vl_api_sw_interface_set_flags_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002008 u32 sw_if_index;
2009 u8 sw_if_index_set = 0;
Neale Rannsa07bd702017-08-07 07:53:49 -07002010 u8 admin_up = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002011 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002012
2013 /* Parse args required to build the message */
2014 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2015 {
2016 if (unformat (i, "admin-up"))
2017 admin_up = 1;
2018 else if (unformat (i, "admin-down"))
2019 admin_up = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002020 else
2021 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2022 sw_if_index_set = 1;
2023 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2024 sw_if_index_set = 1;
2025 else
2026 break;
2027 }
2028
2029 if (sw_if_index_set == 0)
2030 {
2031 errmsg ("missing interface name or sw_if_index");
2032 return -99;
2033 }
2034
2035 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002036 M (SW_INTERFACE_SET_FLAGS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002037 mp->sw_if_index = ntohl (sw_if_index);
Jakub Grajciar053204a2019-03-18 13:17:53 +01002038 mp->flags = ntohl ((admin_up) ? IF_STATUS_API_FLAG_ADMIN_UP : 0);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002039
2040 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002041 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002042
2043 /* Wait for a reply, return the good/bad news... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002044 W (ret);
2045 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002046}
2047
2048static int
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02002049api_sw_interface_set_rx_placement (vat_main_t * vam)
2050{
2051 unformat_input_t *i = vam->input;
2052 vl_api_sw_interface_set_rx_placement_t *mp;
2053 u32 sw_if_index;
2054 u8 sw_if_index_set = 0;
2055 int ret;
2056 u8 is_main = 0;
2057 u32 queue_id, thread_index;
2058
2059 /* Parse args required to build the message */
2060 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2061 {
2062 if (unformat (i, "queue %d", &queue_id))
2063 ;
2064 else if (unformat (i, "main"))
2065 is_main = 1;
2066 else if (unformat (i, "worker %d", &thread_index))
2067 ;
2068 else
2069 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2070 sw_if_index_set = 1;
2071 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2072 sw_if_index_set = 1;
2073 else
2074 break;
2075 }
2076
2077 if (sw_if_index_set == 0)
2078 {
2079 errmsg ("missing interface name or sw_if_index");
2080 return -99;
2081 }
2082
2083 if (is_main)
2084 thread_index = 0;
2085 /* Construct the API message */
2086 M (SW_INTERFACE_SET_RX_PLACEMENT, mp);
2087 mp->sw_if_index = ntohl (sw_if_index);
2088 mp->worker_id = ntohl (thread_index);
2089 mp->queue_id = ntohl (queue_id);
2090 mp->is_main = is_main;
2091
2092 /* send it... */
2093 S (mp);
2094 /* Wait for a reply, return the good/bad news... */
2095 W (ret);
2096 return ret;
2097}
2098
Mohsin Kazmif0b42f42018-09-10 18:11:00 +02002099static void vl_api_sw_interface_rx_placement_details_t_handler
2100 (vl_api_sw_interface_rx_placement_details_t * mp)
2101{
2102 vat_main_t *vam = &vat_main;
2103 u32 worker_id = ntohl (mp->worker_id);
2104
2105 print (vam->ofp,
2106 "\n%-11d %-11s %-6d %-5d %-9s",
2107 ntohl (mp->sw_if_index), (worker_id == 0) ? "main" : "worker",
2108 worker_id, ntohl (mp->queue_id),
2109 (mp->mode ==
2110 1) ? "polling" : ((mp->mode == 2) ? "interrupt" : "adaptive"));
2111}
2112
2113static void vl_api_sw_interface_rx_placement_details_t_handler_json
2114 (vl_api_sw_interface_rx_placement_details_t * mp)
2115{
2116 vat_main_t *vam = &vat_main;
2117 vat_json_node_t *node = NULL;
2118
2119 if (VAT_JSON_ARRAY != vam->json_tree.type)
2120 {
2121 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
2122 vat_json_init_array (&vam->json_tree);
2123 }
2124 node = vat_json_array_add (&vam->json_tree);
2125
2126 vat_json_init_object (node);
2127 vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index));
2128 vat_json_object_add_uint (node, "worker_id", ntohl (mp->worker_id));
2129 vat_json_object_add_uint (node, "queue_id", ntohl (mp->queue_id));
2130 vat_json_object_add_uint (node, "mode", mp->mode);
2131}
2132
2133static int
2134api_sw_interface_rx_placement_dump (vat_main_t * vam)
2135{
2136 unformat_input_t *i = vam->input;
2137 vl_api_sw_interface_rx_placement_dump_t *mp;
2138 vl_api_control_ping_t *mp_ping;
2139 int ret;
2140 u32 sw_if_index;
2141 u8 sw_if_index_set = 0;
2142
2143 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2144 {
2145 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2146 sw_if_index_set++;
2147 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2148 sw_if_index_set++;
2149 else
2150 break;
2151 }
2152
2153 print (vam->ofp,
2154 "\n%-11s %-11s %-6s %-5s %-4s",
2155 "sw_if_index", "main/worker", "thread", "queue", "mode");
2156
2157 /* Dump Interface rx placement */
2158 M (SW_INTERFACE_RX_PLACEMENT_DUMP, mp);
2159
2160 if (sw_if_index_set)
2161 mp->sw_if_index = htonl (sw_if_index);
2162 else
2163 mp->sw_if_index = ~0;
2164
2165 S (mp);
2166
2167 /* Use a control ping for synchronization */
2168 MPING (CONTROL_PING, mp_ping);
2169 S (mp_ping);
2170
2171 W (ret);
2172 return ret;
2173}
2174
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02002175static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002176api_sw_interface_clear_stats (vat_main_t * vam)
2177{
2178 unformat_input_t *i = vam->input;
2179 vl_api_sw_interface_clear_stats_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002180 u32 sw_if_index;
2181 u8 sw_if_index_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002182 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002183
2184 /* Parse args required to build the message */
2185 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2186 {
2187 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2188 sw_if_index_set = 1;
2189 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2190 sw_if_index_set = 1;
2191 else
2192 break;
2193 }
2194
2195 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002196 M (SW_INTERFACE_CLEAR_STATS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002197
2198 if (sw_if_index_set == 1)
2199 mp->sw_if_index = ntohl (sw_if_index);
2200 else
2201 mp->sw_if_index = ~0;
2202
2203 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002204 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002205
2206 /* Wait for a reply, return the good/bad news... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002207 W (ret);
2208 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002209}
2210
Damjan Marion7cd468a2016-12-19 23:05:39 +01002211static int
2212api_sw_interface_add_del_address (vat_main_t * vam)
2213{
2214 unformat_input_t *i = vam->input;
2215 vl_api_sw_interface_add_del_address_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002216 u32 sw_if_index;
2217 u8 sw_if_index_set = 0;
2218 u8 is_add = 1, del_all = 0;
2219 u32 address_length = 0;
2220 u8 v4_address_set = 0;
2221 u8 v6_address_set = 0;
2222 ip4_address_t v4address;
2223 ip6_address_t v6address;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002224 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002225
2226 /* Parse args required to build the message */
2227 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2228 {
2229 if (unformat (i, "del-all"))
2230 del_all = 1;
2231 else if (unformat (i, "del"))
2232 is_add = 0;
2233 else
2234 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2235 sw_if_index_set = 1;
2236 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2237 sw_if_index_set = 1;
2238 else if (unformat (i, "%U/%d",
2239 unformat_ip4_address, &v4address, &address_length))
2240 v4_address_set = 1;
2241 else if (unformat (i, "%U/%d",
2242 unformat_ip6_address, &v6address, &address_length))
2243 v6_address_set = 1;
2244 else
2245 break;
2246 }
2247
2248 if (sw_if_index_set == 0)
2249 {
2250 errmsg ("missing interface name or sw_if_index");
2251 return -99;
2252 }
2253 if (v4_address_set && v6_address_set)
2254 {
2255 errmsg ("both v4 and v6 addresses set");
2256 return -99;
2257 }
2258 if (!v4_address_set && !v6_address_set && !del_all)
2259 {
2260 errmsg ("no addresses set");
2261 return -99;
2262 }
2263
2264 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002265 M (SW_INTERFACE_ADD_DEL_ADDRESS, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002266
2267 mp->sw_if_index = ntohl (sw_if_index);
2268 mp->is_add = is_add;
2269 mp->del_all = del_all;
2270 if (v6_address_set)
2271 {
Jakub Grajciar053204a2019-03-18 13:17:53 +01002272 mp->prefix.address.af = ADDRESS_IP6;
2273 clib_memcpy (mp->prefix.address.un.ip6, &v6address, sizeof (v6address));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002274 }
2275 else
2276 {
Jakub Grajciar053204a2019-03-18 13:17:53 +01002277 mp->prefix.address.af = ADDRESS_IP4;
2278 clib_memcpy (mp->prefix.address.un.ip4, &v4address, sizeof (v4address));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002279 }
Jakub Grajciar053204a2019-03-18 13:17:53 +01002280 mp->prefix.len = address_length;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002281
2282 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002283 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002284
2285 /* Wait for a reply, return good/bad news */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002286 W (ret);
2287 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002288}
2289
2290static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002291api_sw_interface_set_table (vat_main_t * vam)
2292{
2293 unformat_input_t *i = vam->input;
2294 vl_api_sw_interface_set_table_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002295 u32 sw_if_index, vrf_id = 0;
2296 u8 sw_if_index_set = 0;
2297 u8 is_ipv6 = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002298 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002299
2300 /* Parse args required to build the message */
2301 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2302 {
2303 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2304 sw_if_index_set = 1;
2305 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2306 sw_if_index_set = 1;
2307 else if (unformat (i, "vrf %d", &vrf_id))
2308 ;
2309 else if (unformat (i, "ipv6"))
2310 is_ipv6 = 1;
2311 else
2312 break;
2313 }
2314
2315 if (sw_if_index_set == 0)
2316 {
2317 errmsg ("missing interface name or sw_if_index");
2318 return -99;
2319 }
2320
2321 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002322 M (SW_INTERFACE_SET_TABLE, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002323
2324 mp->sw_if_index = ntohl (sw_if_index);
2325 mp->is_ipv6 = is_ipv6;
2326 mp->vrf_id = ntohl (vrf_id);
2327
2328 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002329 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002330
2331 /* Wait for a reply... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002332 W (ret);
2333 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002334}
2335
2336static void vl_api_sw_interface_get_table_reply_t_handler
2337 (vl_api_sw_interface_get_table_reply_t * mp)
2338{
2339 vat_main_t *vam = &vat_main;
2340
2341 print (vam->ofp, "%d", ntohl (mp->vrf_id));
2342
2343 vam->retval = ntohl (mp->retval);
2344 vam->result_ready = 1;
2345
2346}
2347
2348static void vl_api_sw_interface_get_table_reply_t_handler_json
2349 (vl_api_sw_interface_get_table_reply_t * mp)
2350{
2351 vat_main_t *vam = &vat_main;
2352 vat_json_node_t node;
2353
2354 vat_json_init_object (&node);
2355 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
2356 vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id));
2357
2358 vat_json_print (vam->ofp, &node);
2359 vat_json_free (&node);
2360
2361 vam->retval = ntohl (mp->retval);
2362 vam->result_ready = 1;
2363}
2364
2365static int
2366api_sw_interface_get_table (vat_main_t * vam)
2367{
2368 unformat_input_t *i = vam->input;
2369 vl_api_sw_interface_get_table_t *mp;
2370 u32 sw_if_index;
2371 u8 sw_if_index_set = 0;
2372 u8 is_ipv6 = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002373 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002374
2375 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2376 {
2377 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2378 sw_if_index_set = 1;
2379 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2380 sw_if_index_set = 1;
2381 else if (unformat (i, "ipv6"))
2382 is_ipv6 = 1;
2383 else
2384 break;
2385 }
2386
2387 if (sw_if_index_set == 0)
2388 {
2389 errmsg ("missing interface name or sw_if_index");
2390 return -99;
2391 }
2392
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002393 M (SW_INTERFACE_GET_TABLE, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002394 mp->sw_if_index = htonl (sw_if_index);
2395 mp->is_ipv6 = is_ipv6;
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
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01002402uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00002403unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01002404{
jialv01082ebeb2019-09-10 00:23:55 +08002405 vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +01002406 u32 x[4];
2407
2408 if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
2409 return 0;
2410
2411 addr->domain = x[0];
2412 addr->bus = x[1];
2413 addr->slot = x[2];
2414 addr->function = x[3];
2415
2416 return 1;
2417}
2418
2419static int
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00002420api_ip_table_add_del (vat_main_t *vam)
Neale Ranns28ab9cc2017-08-14 07:18:42 -07002421{
2422 unformat_input_t *i = vam->input;
2423 vl_api_ip_table_add_del_t *mp;
2424 u32 table_id = ~0;
2425 u8 is_ipv6 = 0;
2426 u8 is_add = 1;
2427 int ret = 0;
2428
2429 /* Parse args required to build the message */
2430 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2431 {
2432 if (unformat (i, "ipv6"))
2433 is_ipv6 = 1;
2434 else if (unformat (i, "del"))
2435 is_add = 0;
2436 else if (unformat (i, "add"))
2437 is_add = 1;
2438 else if (unformat (i, "table %d", &table_id))
2439 ;
2440 else
2441 {
2442 clib_warning ("parse error '%U'", format_unformat_error, i);
2443 return -99;
2444 }
2445 }
2446
2447 if (~0 == table_id)
2448 {
2449 errmsg ("missing table-ID");
2450 return -99;
2451 }
2452
2453 /* Construct the API message */
2454 M (IP_TABLE_ADD_DEL, mp);
2455
Neale Ranns097fa662018-05-01 05:17:55 -07002456 mp->table.table_id = ntohl (table_id);
2457 mp->table.is_ip6 = is_ipv6;
Neale Ranns28ab9cc2017-08-14 07:18:42 -07002458 mp->is_add = is_add;
2459
2460 /* send it... */
2461 S (mp);
2462
2463 /* Wait for a reply... */
2464 W (ret);
2465
2466 return ret;
2467}
2468
Neale Ranns097fa662018-05-01 05:17:55 -07002469uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00002470unformat_fib_path (unformat_input_t *input, va_list *args)
Neale Ranns097fa662018-05-01 05:17:55 -07002471{
2472 vat_main_t *vam = va_arg (*args, vat_main_t *);
2473 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
2474 u32 weight, preference;
2475 mpls_label_t out_label;
2476
2477 clib_memset (path, 0, sizeof (*path));
2478 path->weight = 1;
2479 path->sw_if_index = ~0;
2480 path->rpf_id = ~0;
2481 path->n_labels = 0;
2482
2483 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2484 {
Filip Tehlar5a9d2a12021-06-22 21:20:29 +00002485 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
2486 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
2487 &path->sw_if_index))
Neale Ranns097fa662018-05-01 05:17:55 -07002488 {
2489 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2490 }
2491 else if (unformat (input, "%U %U",
2492 unformat_vl_api_ip6_address,
2493 &path->nh.address.ip6,
2494 api_unformat_sw_if_index, vam, &path->sw_if_index))
2495 {
2496 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2497 }
2498 else if (unformat (input, "weight %u", &weight))
2499 {
2500 path->weight = weight;
2501 }
2502 else if (unformat (input, "preference %u", &preference))
2503 {
2504 path->preference = preference;
2505 }
2506 else if (unformat (input, "%U next-hop-table %d",
2507 unformat_vl_api_ip4_address,
2508 &path->nh.address.ip4, &path->table_id))
2509 {
2510 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2511 }
2512 else if (unformat (input, "%U next-hop-table %d",
2513 unformat_vl_api_ip6_address,
2514 &path->nh.address.ip6, &path->table_id))
2515 {
2516 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2517 }
2518 else if (unformat (input, "%U",
2519 unformat_vl_api_ip4_address, &path->nh.address.ip4))
2520 {
2521 /*
2522 * the recursive next-hops are by default in the default table
2523 */
2524 path->table_id = 0;
2525 path->sw_if_index = ~0;
2526 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2527 }
2528 else if (unformat (input, "%U",
2529 unformat_vl_api_ip6_address, &path->nh.address.ip6))
2530 {
2531 /*
2532 * the recursive next-hops are by default in the default table
2533 */
2534 path->table_id = 0;
2535 path->sw_if_index = ~0;
2536 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2537 }
2538 else if (unformat (input, "resolve-via-host"))
2539 {
2540 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
2541 }
2542 else if (unformat (input, "resolve-via-attached"))
2543 {
2544 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
2545 }
2546 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
2547 {
2548 path->type = FIB_API_PATH_TYPE_LOCAL;
2549 path->sw_if_index = ~0;
2550 path->proto = FIB_API_PATH_NH_PROTO_IP4;
2551 }
2552 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
2553 {
2554 path->type = FIB_API_PATH_TYPE_LOCAL;
2555 path->sw_if_index = ~0;
2556 path->proto = FIB_API_PATH_NH_PROTO_IP6;
2557 }
2558 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
2559 ;
2560 else if (unformat (input, "via-label %d", &path->nh.via_label))
2561 {
2562 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
2563 path->sw_if_index = ~0;
2564 }
2565 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
2566 {
2567 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
2568 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
2569 }
2570 else if (unformat (input, "local"))
2571 {
2572 path->type = FIB_API_PATH_TYPE_LOCAL;
2573 }
2574 else if (unformat (input, "out-labels"))
2575 {
2576 while (unformat (input, "%d", &out_label))
2577 {
2578 path->label_stack[path->n_labels].label = out_label;
2579 path->label_stack[path->n_labels].is_uniform = 0;
2580 path->label_stack[path->n_labels].ttl = 64;
2581 path->n_labels++;
2582 }
2583 }
2584 else if (unformat (input, "via"))
2585 {
2586 /* new path, back up and return */
2587 unformat_put_input (input);
2588 unformat_put_input (input);
2589 unformat_put_input (input);
2590 unformat_put_input (input);
2591 break;
2592 }
2593 else
2594 {
2595 return (0);
2596 }
2597 }
2598
2599 path->proto = ntohl (path->proto);
2600 path->type = ntohl (path->type);
2601 path->flags = ntohl (path->flags);
2602 path->table_id = ntohl (path->table_id);
2603 path->sw_if_index = ntohl (path->sw_if_index);
2604
2605 return (1);
2606}
2607
Neale Ranns28ab9cc2017-08-14 07:18:42 -07002608static int
Neale Ranns097fa662018-05-01 05:17:55 -07002609api_ip_route_add_del (vat_main_t * vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002610{
2611 unformat_input_t *i = vam->input;
Neale Ranns097fa662018-05-01 05:17:55 -07002612 vl_api_ip_route_add_del_t *mp;
2613 u32 vrf_id = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002614 u8 is_add = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002615 u8 is_multipath = 0;
Neale Ranns097fa662018-05-01 05:17:55 -07002616 u8 prefix_set = 0;
2617 u8 path_count = 0;
2618 vl_api_prefix_t pfx = { };
2619 vl_api_fib_path_t paths[8];
Damjan Marion7cd468a2016-12-19 23:05:39 +01002620 int count = 1;
2621 int j;
2622 f64 before = 0;
2623 u32 random_add_del = 0;
2624 u32 *random_vector = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002625 u32 random_seed = 0xdeaddabe;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002626
2627 /* Parse args required to build the message */
2628 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2629 {
Neale Ranns097fa662018-05-01 05:17:55 -07002630 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
2631 prefix_set = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002632 else if (unformat (i, "del"))
2633 is_add = 0;
2634 else if (unformat (i, "add"))
2635 is_add = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002636 else if (unformat (i, "vrf %d", &vrf_id))
2637 ;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002638 else if (unformat (i, "count %d", &count))
2639 ;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002640 else if (unformat (i, "random"))
2641 random_add_del = 1;
Neale Ranns097fa662018-05-01 05:17:55 -07002642 else if (unformat (i, "multipath"))
2643 is_multipath = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002644 else if (unformat (i, "seed %d", &random_seed))
2645 ;
2646 else
Neale Ranns097fa662018-05-01 05:17:55 -07002647 if (unformat
2648 (i, "via %U", unformat_fib_path, vam, &paths[path_count]))
2649 {
2650 path_count++;
2651 if (8 == path_count)
2652 {
2653 errmsg ("max 8 paths");
2654 return -99;
2655 }
2656 }
2657 else
Damjan Marion7cd468a2016-12-19 23:05:39 +01002658 {
2659 clib_warning ("parse error '%U'", format_unformat_error, i);
2660 return -99;
2661 }
2662 }
2663
Neale Ranns097fa662018-05-01 05:17:55 -07002664 if (!path_count)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002665 {
Neale Ranns097fa662018-05-01 05:17:55 -07002666 errmsg ("specify a path; via ...");
Damjan Marion7cd468a2016-12-19 23:05:39 +01002667 return -99;
2668 }
Neale Ranns097fa662018-05-01 05:17:55 -07002669 if (prefix_set == 0)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002670 {
Neale Ranns097fa662018-05-01 05:17:55 -07002671 errmsg ("missing prefix");
Damjan Marion7cd468a2016-12-19 23:05:39 +01002672 return -99;
2673 }
2674
2675 /* Generate a pile of unique, random routes */
2676 if (random_add_del)
2677 {
Neale Ranns097fa662018-05-01 05:17:55 -07002678 ip4_address_t *i = (ip4_address_t *) & paths[0].nh.address.ip4;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002679 u32 this_random_address;
Neale Ranns097fa662018-05-01 05:17:55 -07002680 uword *random_hash;
2681
Damjan Marion7cd468a2016-12-19 23:05:39 +01002682 random_hash = hash_create (count, sizeof (uword));
2683
Neale Ranns097fa662018-05-01 05:17:55 -07002684 hash_set (random_hash, i->as_u32, 1);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002685 for (j = 0; j <= count; j++)
2686 {
2687 do
2688 {
2689 this_random_address = random_u32 (&random_seed);
2690 this_random_address =
2691 clib_host_to_net_u32 (this_random_address);
2692 }
2693 while (hash_get (random_hash, this_random_address));
2694 vec_add1 (random_vector, this_random_address);
2695 hash_set (random_hash, this_random_address, 1);
2696 }
2697 hash_free (random_hash);
Neale Ranns097fa662018-05-01 05:17:55 -07002698 set_ip4_address (&pfx.address, random_vector[0]);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002699 }
2700
2701 if (count > 1)
2702 {
2703 /* Turn on async mode */
2704 vam->async_mode = 1;
2705 vam->async_errors = 0;
2706 before = vat_time_now (vam);
2707 }
2708
2709 for (j = 0; j < count; j++)
2710 {
2711 /* Construct the API message */
Neale Ranns097fa662018-05-01 05:17:55 -07002712 M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002713
2714 mp->is_add = is_add;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002715 mp->is_multipath = is_multipath;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002716
Neale Ranns097fa662018-05-01 05:17:55 -07002717 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
2718 mp->route.table_id = ntohl (vrf_id);
2719 mp->route.n_paths = path_count;
2720
2721 clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
2722
2723 if (random_add_del)
2724 set_ip4_address (&pfx.address, random_vector[j + 1]);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002725 else
Neale Ranns097fa662018-05-01 05:17:55 -07002726 increment_address (&pfx.address);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002727 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002728 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002729 /* If we receive SIGTERM, stop now... */
2730 if (vam->do_exit)
2731 break;
2732 }
2733
2734 /* When testing multiple add/del ops, use a control-ping to sync */
2735 if (count > 1)
2736 {
Jon Loeliger2d23eca2017-02-01 13:09:58 -06002737 vl_api_control_ping_t *mp_ping;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002738 f64 after;
Jon Loeliger1f9191f2017-01-31 15:27:19 -06002739 f64 timeout;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002740
2741 /* Shut off async mode */
2742 vam->async_mode = 0;
2743
Dave Barach59b25652017-09-10 15:04:27 -04002744 MPING (CONTROL_PING, mp_ping);
Jon Loeliger2d23eca2017-02-01 13:09:58 -06002745 S (mp_ping);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002746
2747 timeout = vat_time_now (vam) + 1.0;
2748 while (vat_time_now (vam) < timeout)
2749 if (vam->result_ready == 1)
2750 goto out;
2751 vam->retval = -99;
2752
2753 out:
2754 if (vam->retval == -99)
2755 errmsg ("timeout");
2756
2757 if (vam->async_errors > 0)
2758 {
2759 errmsg ("%d asynchronous errors", vam->async_errors);
2760 vam->retval = -98;
2761 }
2762 vam->async_errors = 0;
2763 after = vat_time_now (vam);
2764
2765 /* slim chance, but we might have eaten SIGTERM on the first iteration */
2766 if (j > 0)
2767 count = j;
2768
2769 print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec",
2770 count, after - before, count / (after - before));
2771 }
2772 else
2773 {
Jon Loeliger56c7b012017-02-01 12:31:41 -06002774 int ret;
2775
Damjan Marion7cd468a2016-12-19 23:05:39 +01002776 /* Wait for a reply... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002777 W (ret);
2778 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002779 }
2780
2781 /* Return the good/bad news */
2782 return (vam->retval);
2783}
2784
2785static int
Neale Ranns32e1c012016-11-22 17:07:28 +00002786api_ip_mroute_add_del (vat_main_t * vam)
2787{
2788 unformat_input_t *i = vam->input;
Neale Ranns097fa662018-05-01 05:17:55 -07002789 u8 path_set = 0, prefix_set = 0, is_add = 1;
Neale Ranns32e1c012016-11-22 17:07:28 +00002790 vl_api_ip_mroute_add_del_t *mp;
Neale Ranns32e1c012016-11-22 17:07:28 +00002791 mfib_entry_flags_t eflags = 0;
Neale Ranns097fa662018-05-01 05:17:55 -07002792 vl_api_mfib_path_t path;
2793 vl_api_mprefix_t pfx = { };
2794 u32 vrf_id = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002795 int ret;
Neale Ranns32e1c012016-11-22 17:07:28 +00002796
2797 /* Parse args required to build the message */
2798 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2799 {
Neale Ranns097fa662018-05-01 05:17:55 -07002800 if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
Neale Ranns32e1c012016-11-22 17:07:28 +00002801 {
Neale Ranns097fa662018-05-01 05:17:55 -07002802 prefix_set = 1;
2803 pfx.grp_address_length = htons (pfx.grp_address_length);
Neale Ranns32e1c012016-11-22 17:07:28 +00002804 }
2805 else if (unformat (i, "del"))
2806 is_add = 0;
2807 else if (unformat (i, "add"))
2808 is_add = 1;
2809 else if (unformat (i, "vrf %d", &vrf_id))
2810 ;
Neale Ranns097fa662018-05-01 05:17:55 -07002811 else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
2812 path.itf_flags = htonl (path.itf_flags);
Neale Ranns32e1c012016-11-22 17:07:28 +00002813 else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
2814 ;
Neale Ranns097fa662018-05-01 05:17:55 -07002815 else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
2816 path_set = 1;
Neale Ranns32e1c012016-11-22 17:07:28 +00002817 else
2818 {
2819 clib_warning ("parse error '%U'", format_unformat_error, i);
2820 return -99;
2821 }
2822 }
2823
Neale Ranns097fa662018-05-01 05:17:55 -07002824 if (prefix_set == 0)
Neale Ranns32e1c012016-11-22 17:07:28 +00002825 {
2826 errmsg ("missing addresses\n");
2827 return -99;
2828 }
Neale Ranns097fa662018-05-01 05:17:55 -07002829 if (path_set == 0)
2830 {
2831 errmsg ("missing path\n");
2832 return -99;
2833 }
Neale Ranns32e1c012016-11-22 17:07:28 +00002834
2835 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002836 M (IP_MROUTE_ADD_DEL, mp);
Neale Ranns32e1c012016-11-22 17:07:28 +00002837
Neale Ranns32e1c012016-11-22 17:07:28 +00002838 mp->is_add = is_add;
Neale Ranns097fa662018-05-01 05:17:55 -07002839 mp->is_multipath = 1;
Neale Ranns32e1c012016-11-22 17:07:28 +00002840
Neale Ranns097fa662018-05-01 05:17:55 -07002841 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
2842 mp->route.table_id = htonl (vrf_id);
2843 mp->route.n_paths = 1;
2844 mp->route.entry_flags = htonl (eflags);
Neale Ranns32e1c012016-11-22 17:07:28 +00002845
Neale Ranns097fa662018-05-01 05:17:55 -07002846 clib_memcpy (&mp->route.paths, &path, sizeof (path));
Neale Ranns32e1c012016-11-22 17:07:28 +00002847
2848 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002849 S (mp);
Neale Ranns32e1c012016-11-22 17:07:28 +00002850 /* Wait for a reply... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06002851 W (ret);
2852 return ret;
Neale Ranns32e1c012016-11-22 17:07:28 +00002853}
2854
2855static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002856api_sw_interface_set_unnumbered (vat_main_t * vam)
2857{
2858 unformat_input_t *i = vam->input;
2859 vl_api_sw_interface_set_unnumbered_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002860 u32 sw_if_index;
2861 u32 unnum_sw_index = ~0;
2862 u8 is_add = 1;
2863 u8 sw_if_index_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002864 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002865
2866 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2867 {
2868 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2869 sw_if_index_set = 1;
2870 else if (unformat (i, "sw_if_index %d", &sw_if_index))
2871 sw_if_index_set = 1;
2872 else if (unformat (i, "unnum_if_index %d", &unnum_sw_index))
2873 ;
2874 else if (unformat (i, "del"))
2875 is_add = 0;
2876 else
2877 {
2878 clib_warning ("parse error '%U'", format_unformat_error, i);
2879 return -99;
2880 }
2881 }
2882
2883 if (sw_if_index_set == 0)
2884 {
2885 errmsg ("missing interface name or sw_if_index");
2886 return -99;
2887 }
2888
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002889 M (SW_INTERFACE_SET_UNNUMBERED, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002890
2891 mp->sw_if_index = ntohl (sw_if_index);
2892 mp->unnumbered_sw_if_index = ntohl (unnum_sw_index);
2893 mp->is_add = is_add;
2894
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002895 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002896 W (ret);
2897 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002898}
2899
Damjan Marion7cd468a2016-12-19 23:05:39 +01002900
2901static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002902api_create_vlan_subif (vat_main_t * vam)
2903{
2904 unformat_input_t *i = vam->input;
2905 vl_api_create_vlan_subif_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002906 u32 sw_if_index;
2907 u8 sw_if_index_set = 0;
2908 u32 vlan_id;
2909 u8 vlan_id_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002910 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002911
2912 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2913 {
2914 if (unformat (i, "sw_if_index %d", &sw_if_index))
2915 sw_if_index_set = 1;
2916 else
2917 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2918 sw_if_index_set = 1;
2919 else if (unformat (i, "vlan %d", &vlan_id))
2920 vlan_id_set = 1;
2921 else
2922 {
2923 clib_warning ("parse error '%U'", format_unformat_error, i);
2924 return -99;
2925 }
2926 }
2927
2928 if (sw_if_index_set == 0)
2929 {
2930 errmsg ("missing interface name or sw_if_index");
2931 return -99;
2932 }
2933
2934 if (vlan_id_set == 0)
2935 {
2936 errmsg ("missing vlan_id");
2937 return -99;
2938 }
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002939 M (CREATE_VLAN_SUBIF, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002940
2941 mp->sw_if_index = ntohl (sw_if_index);
2942 mp->vlan_id = ntohl (vlan_id);
2943
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002944 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002945 W (ret);
2946 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002947}
2948
2949#define foreach_create_subif_bit \
2950_(no_tags) \
2951_(one_tag) \
2952_(two_tags) \
2953_(dot1ad) \
2954_(exact_match) \
2955_(default_sub) \
2956_(outer_vlan_id_any) \
2957_(inner_vlan_id_any)
2958
Jakub Grajciar053204a2019-03-18 13:17:53 +01002959#define foreach_create_subif_flag \
2960_(0, "no_tags") \
2961_(1, "one_tag") \
2962_(2, "two_tags") \
2963_(3, "dot1ad") \
2964_(4, "exact_match") \
2965_(5, "default_sub") \
2966_(6, "outer_vlan_id_any") \
2967_(7, "inner_vlan_id_any")
2968
Damjan Marion7cd468a2016-12-19 23:05:39 +01002969static int
2970api_create_subif (vat_main_t * vam)
2971{
2972 unformat_input_t *i = vam->input;
2973 vl_api_create_subif_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002974 u32 sw_if_index;
2975 u8 sw_if_index_set = 0;
2976 u32 sub_id;
2977 u8 sub_id_set = 0;
Jakub Grajciar053204a2019-03-18 13:17:53 +01002978 u32 __attribute__ ((unused)) no_tags = 0;
2979 u32 __attribute__ ((unused)) one_tag = 0;
2980 u32 __attribute__ ((unused)) two_tags = 0;
2981 u32 __attribute__ ((unused)) dot1ad = 0;
2982 u32 __attribute__ ((unused)) exact_match = 0;
2983 u32 __attribute__ ((unused)) default_sub = 0;
2984 u32 __attribute__ ((unused)) outer_vlan_id_any = 0;
2985 u32 __attribute__ ((unused)) inner_vlan_id_any = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002986 u32 tmp;
2987 u16 outer_vlan_id = 0;
2988 u16 inner_vlan_id = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002989 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002990
2991 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2992 {
2993 if (unformat (i, "sw_if_index %d", &sw_if_index))
2994 sw_if_index_set = 1;
2995 else
2996 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
2997 sw_if_index_set = 1;
2998 else if (unformat (i, "sub_id %d", &sub_id))
2999 sub_id_set = 1;
3000 else if (unformat (i, "outer_vlan_id %d", &tmp))
3001 outer_vlan_id = tmp;
3002 else if (unformat (i, "inner_vlan_id %d", &tmp))
3003 inner_vlan_id = tmp;
3004
3005#define _(a) else if (unformat (i, #a)) a = 1 ;
3006 foreach_create_subif_bit
3007#undef _
3008 else
3009 {
3010 clib_warning ("parse error '%U'", format_unformat_error, i);
3011 return -99;
3012 }
3013 }
3014
3015 if (sw_if_index_set == 0)
3016 {
3017 errmsg ("missing interface name or sw_if_index");
3018 return -99;
3019 }
3020
3021 if (sub_id_set == 0)
3022 {
3023 errmsg ("missing sub_id");
3024 return -99;
3025 }
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003026 M (CREATE_SUBIF, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003027
3028 mp->sw_if_index = ntohl (sw_if_index);
3029 mp->sub_id = ntohl (sub_id);
3030
Jakub Grajciar053204a2019-03-18 13:17:53 +01003031#define _(a,b) mp->sub_if_flags |= (1 << a);
3032 foreach_create_subif_flag;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003033#undef _
3034
3035 mp->outer_vlan_id = ntohs (outer_vlan_id);
3036 mp->inner_vlan_id = ntohs (inner_vlan_id);
3037
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003038 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003039 W (ret);
3040 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003041}
3042
3043static int
Neale Ranns9db6ada2019-11-08 12:42:31 +00003044api_ip_table_replace_begin (vat_main_t * vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003045{
3046 unformat_input_t *i = vam->input;
Neale Ranns9db6ada2019-11-08 12:42:31 +00003047 vl_api_ip_table_replace_begin_t *mp;
3048 u32 table_id = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003049 u8 is_ipv6 = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003050
Jon Loeliger56c7b012017-02-01 12:31:41 -06003051 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003052 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3053 {
Neale Ranns9db6ada2019-11-08 12:42:31 +00003054 if (unformat (i, "table %d", &table_id))
3055 ;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003056 else if (unformat (i, "ipv6"))
3057 is_ipv6 = 1;
3058 else
3059 {
3060 clib_warning ("parse error '%U'", format_unformat_error, i);
3061 return -99;
3062 }
3063 }
3064
Neale Ranns9db6ada2019-11-08 12:42:31 +00003065 M (IP_TABLE_REPLACE_BEGIN, mp);
3066
3067 mp->table.table_id = ntohl (table_id);
3068 mp->table.is_ip6 = is_ipv6;
3069
3070 S (mp);
3071 W (ret);
3072 return ret;
3073}
3074
3075static int
3076api_ip_table_flush (vat_main_t * vam)
3077{
3078 unformat_input_t *i = vam->input;
3079 vl_api_ip_table_flush_t *mp;
3080 u32 table_id = 0;
3081 u8 is_ipv6 = 0;
3082
3083 int ret;
3084 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003085 {
Neale Ranns9db6ada2019-11-08 12:42:31 +00003086 if (unformat (i, "table %d", &table_id))
3087 ;
3088 else if (unformat (i, "ipv6"))
3089 is_ipv6 = 1;
3090 else
3091 {
3092 clib_warning ("parse error '%U'", format_unformat_error, i);
3093 return -99;
3094 }
Damjan Marion7cd468a2016-12-19 23:05:39 +01003095 }
3096
Neale Ranns9db6ada2019-11-08 12:42:31 +00003097 M (IP_TABLE_FLUSH, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003098
Neale Ranns9db6ada2019-11-08 12:42:31 +00003099 mp->table.table_id = ntohl (table_id);
3100 mp->table.is_ip6 = is_ipv6;
3101
3102 S (mp);
3103 W (ret);
3104 return ret;
3105}
3106
3107static int
3108api_ip_table_replace_end (vat_main_t * vam)
3109{
3110 unformat_input_t *i = vam->input;
3111 vl_api_ip_table_replace_end_t *mp;
3112 u32 table_id = 0;
3113 u8 is_ipv6 = 0;
3114
3115 int ret;
3116 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3117 {
3118 if (unformat (i, "table %d", &table_id))
3119 ;
3120 else if (unformat (i, "ipv6"))
3121 is_ipv6 = 1;
3122 else
3123 {
3124 clib_warning ("parse error '%U'", format_unformat_error, i);
3125 return -99;
3126 }
3127 }
3128
3129 M (IP_TABLE_REPLACE_END, mp);
3130
3131 mp->table.table_id = ntohl (table_id);
3132 mp->table.is_ip6 = is_ipv6;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003133
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003134 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003135 W (ret);
3136 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003137}
3138
3139static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01003140api_set_ip_flow_hash (vat_main_t * vam)
3141{
3142 unformat_input_t *i = vam->input;
3143 vl_api_set_ip_flow_hash_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003144 u32 vrf_id = 0;
3145 u8 is_ipv6 = 0;
3146 u8 vrf_id_set = 0;
3147 u8 src = 0;
3148 u8 dst = 0;
3149 u8 sport = 0;
3150 u8 dport = 0;
3151 u8 proto = 0;
3152 u8 reverse = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003153 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003154
3155 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3156 {
3157 if (unformat (i, "vrf %d", &vrf_id))
3158 vrf_id_set = 1;
3159 else if (unformat (i, "ipv6"))
3160 is_ipv6 = 1;
3161 else if (unformat (i, "src"))
3162 src = 1;
3163 else if (unformat (i, "dst"))
3164 dst = 1;
3165 else if (unformat (i, "sport"))
3166 sport = 1;
3167 else if (unformat (i, "dport"))
3168 dport = 1;
3169 else if (unformat (i, "proto"))
3170 proto = 1;
3171 else if (unformat (i, "reverse"))
3172 reverse = 1;
3173
3174 else
3175 {
3176 clib_warning ("parse error '%U'", format_unformat_error, i);
3177 return -99;
3178 }
3179 }
3180
3181 if (vrf_id_set == 0)
3182 {
3183 errmsg ("missing vrf id");
3184 return -99;
3185 }
3186
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003187 M (SET_IP_FLOW_HASH, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003188 mp->src = src;
3189 mp->dst = dst;
3190 mp->sport = sport;
3191 mp->dport = dport;
3192 mp->proto = proto;
3193 mp->reverse = reverse;
3194 mp->vrf_id = ntohl (vrf_id);
3195 mp->is_ipv6 = is_ipv6;
3196
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003197 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003198 W (ret);
3199 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003200}
3201
3202static int
3203api_sw_interface_ip6_enable_disable (vat_main_t * vam)
3204{
3205 unformat_input_t *i = vam->input;
3206 vl_api_sw_interface_ip6_enable_disable_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003207 u32 sw_if_index;
3208 u8 sw_if_index_set = 0;
3209 u8 enable = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003210 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003211
3212 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
3213 {
3214 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
3215 sw_if_index_set = 1;
3216 else if (unformat (i, "sw_if_index %d", &sw_if_index))
3217 sw_if_index_set = 1;
3218 else if (unformat (i, "enable"))
3219 enable = 1;
3220 else if (unformat (i, "disable"))
3221 enable = 0;
3222 else
3223 {
3224 clib_warning ("parse error '%U'", format_unformat_error, i);
3225 return -99;
3226 }
3227 }
3228
3229 if (sw_if_index_set == 0)
3230 {
3231 errmsg ("missing interface name or sw_if_index");
3232 return -99;
3233 }
3234
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003235 M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003236
3237 mp->sw_if_index = ntohl (sw_if_index);
3238 mp->enable = enable;
3239
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003240 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003241 W (ret);
3242 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003243}
3244
Pablo Camarillofb380952016-12-07 18:34:18 +01003245u8 is_del;
3246u8 localsid_addr[16];
3247u8 end_psp;
3248u8 behavior;
3249u32 sw_if_index;
3250u32 vlan_index;
3251u32 fib_table;
3252u8 nh_addr[16];
3253
3254static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01003255api_ioam_enable (vat_main_t * vam)
3256{
3257 unformat_input_t *input = vam->input;
3258 vl_api_ioam_enable_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003259 u32 id = 0;
3260 int has_trace_option = 0;
3261 int has_pot_option = 0;
3262 int has_seqno_option = 0;
3263 int has_analyse_option = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003264 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003265
3266 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3267 {
3268 if (unformat (input, "trace"))
3269 has_trace_option = 1;
3270 else if (unformat (input, "pot"))
3271 has_pot_option = 1;
3272 else if (unformat (input, "seqno"))
3273 has_seqno_option = 1;
3274 else if (unformat (input, "analyse"))
3275 has_analyse_option = 1;
3276 else
3277 break;
3278 }
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003279 M (IOAM_ENABLE, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003280 mp->id = htons (id);
3281 mp->seqno = has_seqno_option;
3282 mp->analyse = has_analyse_option;
3283 mp->pot_enable = has_pot_option;
3284 mp->trace_enable = has_trace_option;
3285
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003286 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003287 W (ret);
3288 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003289}
3290
3291
3292static int
3293api_ioam_disable (vat_main_t * vam)
3294{
3295 vl_api_ioam_disable_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06003296 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003297
Jon Loeliger8a2aea32017-01-31 13:19:40 -06003298 M (IOAM_DISABLE, mp);
Jon Loeliger7bc770c2017-01-31 14:03:33 -06003299 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06003300 W (ret);
3301 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01003302}
3303
Damjan Marion7cd468a2016-12-19 23:05:39 +01003304#define foreach_tcp_proto_field \
3305_(src_port) \
3306_(dst_port)
3307
3308#define foreach_udp_proto_field \
3309_(src_port) \
3310_(dst_port)
3311
3312#define foreach_ip4_proto_field \
3313_(src_address) \
3314_(dst_address) \
3315_(tos) \
3316_(length) \
3317_(fragment_id) \
3318_(ttl) \
3319_(protocol) \
3320_(checksum)
3321
Dave Barach4a3f69c2017-02-22 12:44:56 -05003322typedef struct
3323{
3324 u16 src_port, dst_port;
3325} tcpudp_header_t;
3326
3327#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01003328uword
3329unformat_tcp_mask (unformat_input_t * input, va_list * args)
3330{
3331 u8 **maskp = va_arg (*args, u8 **);
3332 u8 *mask = 0;
3333 u8 found_something = 0;
3334 tcp_header_t *tcp;
3335
3336#define _(a) u8 a=0;
3337 foreach_tcp_proto_field;
3338#undef _
3339
3340 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3341 {
3342 if (0);
3343#define _(a) else if (unformat (input, #a)) a=1;
3344 foreach_tcp_proto_field
3345#undef _
3346 else
3347 break;
3348 }
3349
3350#define _(a) found_something += a;
3351 foreach_tcp_proto_field;
3352#undef _
3353
3354 if (found_something == 0)
3355 return 0;
3356
3357 vec_validate (mask, sizeof (*tcp) - 1);
3358
3359 tcp = (tcp_header_t *) mask;
3360
Dave Barachb7b92992018-10-17 10:38:51 -04003361#define _(a) if (a) clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01003362 foreach_tcp_proto_field;
3363#undef _
3364
3365 *maskp = mask;
3366 return 1;
3367}
3368
3369uword
3370unformat_udp_mask (unformat_input_t * input, va_list * args)
3371{
3372 u8 **maskp = va_arg (*args, u8 **);
3373 u8 *mask = 0;
3374 u8 found_something = 0;
3375 udp_header_t *udp;
3376
3377#define _(a) u8 a=0;
3378 foreach_udp_proto_field;
3379#undef _
3380
3381 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3382 {
3383 if (0);
3384#define _(a) else if (unformat (input, #a)) a=1;
3385 foreach_udp_proto_field
3386#undef _
3387 else
3388 break;
3389 }
3390
3391#define _(a) found_something += a;
3392 foreach_udp_proto_field;
3393#undef _
3394
3395 if (found_something == 0)
3396 return 0;
3397
3398 vec_validate (mask, sizeof (*udp) - 1);
3399
3400 udp = (udp_header_t *) mask;
3401
Dave Barachb7b92992018-10-17 10:38:51 -04003402#define _(a) if (a) clib_memset (&udp->a, 0xff, sizeof (udp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01003403 foreach_udp_proto_field;
3404#undef _
3405
3406 *maskp = mask;
3407 return 1;
3408}
3409
Damjan Marion7cd468a2016-12-19 23:05:39 +01003410uword
3411unformat_l4_mask (unformat_input_t * input, va_list * args)
3412{
3413 u8 **maskp = va_arg (*args, u8 **);
3414 u16 src_port = 0, dst_port = 0;
3415 tcpudp_header_t *tcpudp;
3416
3417 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3418 {
3419 if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
3420 return 1;
3421 else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
3422 return 1;
3423 else if (unformat (input, "src_port"))
3424 src_port = 0xFFFF;
3425 else if (unformat (input, "dst_port"))
3426 dst_port = 0xFFFF;
3427 else
3428 return 0;
3429 }
3430
3431 if (!src_port && !dst_port)
3432 return 0;
3433
3434 u8 *mask = 0;
3435 vec_validate (mask, sizeof (tcpudp_header_t) - 1);
3436
3437 tcpudp = (tcpudp_header_t *) mask;
3438 tcpudp->src_port = src_port;
3439 tcpudp->dst_port = dst_port;
3440
3441 *maskp = mask;
3442
3443 return 1;
3444}
3445
3446uword
3447unformat_ip4_mask (unformat_input_t * input, va_list * args)
3448{
3449 u8 **maskp = va_arg (*args, u8 **);
3450 u8 *mask = 0;
3451 u8 found_something = 0;
3452 ip4_header_t *ip;
3453
3454#define _(a) u8 a=0;
3455 foreach_ip4_proto_field;
3456#undef _
3457 u8 version = 0;
3458 u8 hdr_length = 0;
3459
3460
3461 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3462 {
3463 if (unformat (input, "version"))
3464 version = 1;
3465 else if (unformat (input, "hdr_length"))
3466 hdr_length = 1;
3467 else if (unformat (input, "src"))
3468 src_address = 1;
3469 else if (unformat (input, "dst"))
3470 dst_address = 1;
3471 else if (unformat (input, "proto"))
3472 protocol = 1;
3473
3474#define _(a) else if (unformat (input, #a)) a=1;
3475 foreach_ip4_proto_field
3476#undef _
3477 else
3478 break;
3479 }
3480
3481#define _(a) found_something += a;
3482 foreach_ip4_proto_field;
3483#undef _
3484
3485 if (found_something == 0)
3486 return 0;
3487
3488 vec_validate (mask, sizeof (*ip) - 1);
3489
3490 ip = (ip4_header_t *) mask;
3491
Dave Barachb7b92992018-10-17 10:38:51 -04003492#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01003493 foreach_ip4_proto_field;
3494#undef _
3495
3496 ip->ip_version_and_header_length = 0;
3497
3498 if (version)
3499 ip->ip_version_and_header_length |= 0xF0;
3500
3501 if (hdr_length)
3502 ip->ip_version_and_header_length |= 0x0F;
3503
3504 *maskp = mask;
3505 return 1;
3506}
3507
3508#define foreach_ip6_proto_field \
3509_(src_address) \
3510_(dst_address) \
3511_(payload_length) \
3512_(hop_limit) \
3513_(protocol)
3514
3515uword
3516unformat_ip6_mask (unformat_input_t * input, va_list * args)
3517{
3518 u8 **maskp = va_arg (*args, u8 **);
3519 u8 *mask = 0;
3520 u8 found_something = 0;
3521 ip6_header_t *ip;
3522 u32 ip_version_traffic_class_and_flow_label;
3523
3524#define _(a) u8 a=0;
3525 foreach_ip6_proto_field;
3526#undef _
3527 u8 version = 0;
3528 u8 traffic_class = 0;
3529 u8 flow_label = 0;
3530
3531 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3532 {
3533 if (unformat (input, "version"))
3534 version = 1;
3535 else if (unformat (input, "traffic-class"))
3536 traffic_class = 1;
3537 else if (unformat (input, "flow-label"))
3538 flow_label = 1;
3539 else if (unformat (input, "src"))
3540 src_address = 1;
3541 else if (unformat (input, "dst"))
3542 dst_address = 1;
3543 else if (unformat (input, "proto"))
3544 protocol = 1;
3545
3546#define _(a) else if (unformat (input, #a)) a=1;
3547 foreach_ip6_proto_field
3548#undef _
3549 else
3550 break;
3551 }
3552
3553#define _(a) found_something += a;
3554 foreach_ip6_proto_field;
3555#undef _
3556
3557 if (found_something == 0)
3558 return 0;
3559
3560 vec_validate (mask, sizeof (*ip) - 1);
3561
3562 ip = (ip6_header_t *) mask;
3563
Dave Barachb7b92992018-10-17 10:38:51 -04003564#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01003565 foreach_ip6_proto_field;
3566#undef _
3567
3568 ip_version_traffic_class_and_flow_label = 0;
3569
3570 if (version)
3571 ip_version_traffic_class_and_flow_label |= 0xF0000000;
3572
3573 if (traffic_class)
3574 ip_version_traffic_class_and_flow_label |= 0x0FF00000;
3575
3576 if (flow_label)
3577 ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
3578
3579 ip->ip_version_traffic_class_and_flow_label =
3580 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
3581
3582 *maskp = mask;
3583 return 1;
3584}
3585
3586uword
3587unformat_l3_mask (unformat_input_t * input, va_list * args)
3588{
3589 u8 **maskp = va_arg (*args, u8 **);
3590
3591 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3592 {
3593 if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
3594 return 1;
3595 else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
3596 return 1;
3597 else
3598 break;
3599 }
3600 return 0;
3601}
3602
3603uword
3604unformat_l2_mask (unformat_input_t * input, va_list * args)
3605{
3606 u8 **maskp = va_arg (*args, u8 **);
3607 u8 *mask = 0;
3608 u8 src = 0;
3609 u8 dst = 0;
3610 u8 proto = 0;
3611 u8 tag1 = 0;
3612 u8 tag2 = 0;
3613 u8 ignore_tag1 = 0;
3614 u8 ignore_tag2 = 0;
3615 u8 cos1 = 0;
3616 u8 cos2 = 0;
3617 u8 dot1q = 0;
3618 u8 dot1ad = 0;
3619 int len = 14;
3620
3621 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3622 {
3623 if (unformat (input, "src"))
3624 src = 1;
3625 else if (unformat (input, "dst"))
3626 dst = 1;
3627 else if (unformat (input, "proto"))
3628 proto = 1;
3629 else if (unformat (input, "tag1"))
3630 tag1 = 1;
3631 else if (unformat (input, "tag2"))
3632 tag2 = 1;
3633 else if (unformat (input, "ignore-tag1"))
3634 ignore_tag1 = 1;
3635 else if (unformat (input, "ignore-tag2"))
3636 ignore_tag2 = 1;
3637 else if (unformat (input, "cos1"))
3638 cos1 = 1;
3639 else if (unformat (input, "cos2"))
3640 cos2 = 1;
3641 else if (unformat (input, "dot1q"))
3642 dot1q = 1;
3643 else if (unformat (input, "dot1ad"))
3644 dot1ad = 1;
3645 else
3646 break;
3647 }
3648 if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
3649 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
3650 return 0;
3651
3652 if (tag1 || ignore_tag1 || cos1 || dot1q)
3653 len = 18;
3654 if (tag2 || ignore_tag2 || cos2 || dot1ad)
3655 len = 22;
3656
3657 vec_validate (mask, len - 1);
3658
3659 if (dst)
Dave Barachb7b92992018-10-17 10:38:51 -04003660 clib_memset (mask, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003661
3662 if (src)
Dave Barachb7b92992018-10-17 10:38:51 -04003663 clib_memset (mask + 6, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01003664
3665 if (tag2 || dot1ad)
3666 {
3667 /* inner vlan tag */
3668 if (tag2)
3669 {
3670 mask[19] = 0xff;
3671 mask[18] = 0x0f;
3672 }
3673 if (cos2)
3674 mask[18] |= 0xe0;
3675 if (proto)
3676 mask[21] = mask[20] = 0xff;
3677 if (tag1)
3678 {
3679 mask[15] = 0xff;
3680 mask[14] = 0x0f;
3681 }
3682 if (cos1)
3683 mask[14] |= 0xe0;
3684 *maskp = mask;
3685 return 1;
3686 }
3687 if (tag1 | dot1q)
3688 {
3689 if (tag1)
3690 {
3691 mask[15] = 0xff;
3692 mask[14] = 0x0f;
3693 }
3694 if (cos1)
3695 mask[14] |= 0xe0;
3696 if (proto)
3697 mask[16] = mask[17] = 0xff;
3698
3699 *maskp = mask;
3700 return 1;
3701 }
3702 if (cos2)
3703 mask[18] |= 0xe0;
3704 if (cos1)
3705 mask[14] |= 0xe0;
3706 if (proto)
3707 mask[12] = mask[13] = 0xff;
3708
3709 *maskp = mask;
3710 return 1;
3711}
3712
3713uword
3714unformat_classify_mask (unformat_input_t * input, va_list * args)
3715{
3716 u8 **maskp = va_arg (*args, u8 **);
3717 u32 *skipp = va_arg (*args, u32 *);
3718 u32 *matchp = va_arg (*args, u32 *);
3719 u32 match;
3720 u8 *mask = 0;
3721 u8 *l2 = 0;
3722 u8 *l3 = 0;
3723 u8 *l4 = 0;
3724 int i;
3725
3726 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3727 {
3728 if (unformat (input, "hex %U", unformat_hex_string, &mask))
3729 ;
3730 else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
3731 ;
3732 else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
3733 ;
3734 else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
3735 ;
3736 else
3737 break;
3738 }
3739
3740 if (l4 && !l3)
3741 {
3742 vec_free (mask);
3743 vec_free (l2);
3744 vec_free (l4);
3745 return 0;
3746 }
3747
3748 if (mask || l2 || l3 || l4)
3749 {
3750 if (l2 || l3 || l4)
3751 {
3752 /* "With a free Ethernet header in every package" */
3753 if (l2 == 0)
3754 vec_validate (l2, 13);
3755 mask = l2;
3756 if (vec_len (l3))
3757 {
3758 vec_append (mask, l3);
3759 vec_free (l3);
3760 }
3761 if (vec_len (l4))
3762 {
3763 vec_append (mask, l4);
3764 vec_free (l4);
3765 }
3766 }
3767
3768 /* Scan forward looking for the first significant mask octet */
3769 for (i = 0; i < vec_len (mask); i++)
3770 if (mask[i])
3771 break;
3772
3773 /* compute (skip, match) params */
3774 *skipp = i / sizeof (u32x4);
3775 vec_delete (mask, *skipp * sizeof (u32x4), 0);
3776
3777 /* Pad mask to an even multiple of the vector size */
3778 while (vec_len (mask) % sizeof (u32x4))
3779 vec_add1 (mask, 0);
3780
3781 match = vec_len (mask) / sizeof (u32x4);
3782
3783 for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
3784 {
3785 u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
3786 if (*tmp || *(tmp + 1))
3787 break;
3788 match--;
3789 }
3790 if (match == 0)
3791 clib_warning ("BUG: match 0");
3792
3793 _vec_len (mask) = match * sizeof (u32x4);
3794
3795 *matchp = match;
3796 *maskp = mask;
3797
3798 return 1;
3799 }
3800
3801 return 0;
3802}
Dave Barach4a3f69c2017-02-22 12:44:56 -05003803#endif /* VPP_API_TEST_BUILTIN */
Damjan Marion7cd468a2016-12-19 23:05:39 +01003804
3805#define foreach_l2_next \
3806_(drop, DROP) \
3807_(ethernet, ETHERNET_INPUT) \
3808_(ip4, IP4_INPUT) \
3809_(ip6, IP6_INPUT)
3810
3811uword
3812unformat_l2_next_index (unformat_input_t * input, va_list * args)
3813{
3814 u32 *miss_next_indexp = va_arg (*args, u32 *);
3815 u32 next_index = 0;
3816 u32 tmp;
3817
3818#define _(n,N) \
3819 if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
3820 foreach_l2_next;
3821#undef _
3822
3823 if (unformat (input, "%d", &tmp))
3824 {
3825 next_index = tmp;
3826 goto out;
3827 }
3828
3829 return 0;
3830
3831out:
3832 *miss_next_indexp = next_index;
3833 return 1;
3834}
3835
3836#define foreach_ip_next \
3837_(drop, DROP) \
3838_(local, LOCAL) \
3839_(rewrite, REWRITE)
3840
3841uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05003842api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003843{
3844 u32 *miss_next_indexp = va_arg (*args, u32 *);
3845 u32 next_index = 0;
3846 u32 tmp;
3847
3848#define _(n,N) \
3849 if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
3850 foreach_ip_next;
3851#undef _
3852
3853 if (unformat (input, "%d", &tmp))
3854 {
3855 next_index = tmp;
3856 goto out;
3857 }
3858
3859 return 0;
3860
3861out:
3862 *miss_next_indexp = next_index;
3863 return 1;
3864}
3865
3866#define foreach_acl_next \
3867_(deny, DENY)
3868
3869uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05003870api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01003871{
3872 u32 *miss_next_indexp = va_arg (*args, u32 *);
3873 u32 next_index = 0;
3874 u32 tmp;
3875
3876#define _(n,N) \
3877 if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
3878 foreach_acl_next;
3879#undef _
3880
3881 if (unformat (input, "permit"))
3882 {
3883 next_index = ~0;
3884 goto out;
3885 }
3886 else if (unformat (input, "%d", &tmp))
3887 {
3888 next_index = tmp;
3889 goto out;
3890 }
3891
3892 return 0;
3893
3894out:
3895 *miss_next_indexp = next_index;
3896 return 1;
3897}
3898
3899uword
3900unformat_policer_precolor (unformat_input_t * input, va_list * args)
3901{
3902 u32 *r = va_arg (*args, u32 *);
3903
3904 if (unformat (input, "conform-color"))
3905 *r = POLICE_CONFORM;
3906 else if (unformat (input, "exceed-color"))
3907 *r = POLICE_EXCEED;
3908 else
3909 return 0;
3910
3911 return 1;
3912}
3913
Dave Barach4a3f69c2017-02-22 12:44:56 -05003914#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01003915uword
3916unformat_l4_match (unformat_input_t * input, va_list * args)
3917{
3918 u8 **matchp = va_arg (*args, u8 **);
3919
3920 u8 *proto_header = 0;
3921 int src_port = 0;
3922 int dst_port = 0;
3923
3924 tcpudp_header_t h;
3925
3926 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3927 {
3928 if (unformat (input, "src_port %d", &src_port))
3929 ;
3930 else if (unformat (input, "dst_port %d", &dst_port))
3931 ;
3932 else
3933 return 0;
3934 }
3935
3936 h.src_port = clib_host_to_net_u16 (src_port);
3937 h.dst_port = clib_host_to_net_u16 (dst_port);
3938 vec_validate (proto_header, sizeof (h) - 1);
3939 memcpy (proto_header, &h, sizeof (h));
3940
3941 *matchp = proto_header;
3942
3943 return 1;
3944}
3945
3946uword
3947unformat_ip4_match (unformat_input_t * input, va_list * args)
3948{
3949 u8 **matchp = va_arg (*args, u8 **);
3950 u8 *match = 0;
3951 ip4_header_t *ip;
3952 int version = 0;
3953 u32 version_val;
3954 int hdr_length = 0;
3955 u32 hdr_length_val;
3956 int src = 0, dst = 0;
3957 ip4_address_t src_val, dst_val;
3958 int proto = 0;
3959 u32 proto_val;
3960 int tos = 0;
3961 u32 tos_val;
3962 int length = 0;
3963 u32 length_val;
3964 int fragment_id = 0;
3965 u32 fragment_id_val;
3966 int ttl = 0;
3967 int ttl_val;
3968 int checksum = 0;
3969 u32 checksum_val;
3970
3971 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
3972 {
3973 if (unformat (input, "version %d", &version_val))
3974 version = 1;
3975 else if (unformat (input, "hdr_length %d", &hdr_length_val))
3976 hdr_length = 1;
3977 else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
3978 src = 1;
3979 else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
3980 dst = 1;
3981 else if (unformat (input, "proto %d", &proto_val))
3982 proto = 1;
3983 else if (unformat (input, "tos %d", &tos_val))
3984 tos = 1;
3985 else if (unformat (input, "length %d", &length_val))
3986 length = 1;
3987 else if (unformat (input, "fragment_id %d", &fragment_id_val))
3988 fragment_id = 1;
3989 else if (unformat (input, "ttl %d", &ttl_val))
3990 ttl = 1;
3991 else if (unformat (input, "checksum %d", &checksum_val))
3992 checksum = 1;
3993 else
3994 break;
3995 }
3996
3997 if (version + hdr_length + src + dst + proto + tos + length + fragment_id
3998 + ttl + checksum == 0)
3999 return 0;
4000
4001 /*
4002 * Aligned because we use the real comparison functions
4003 */
4004 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
4005
4006 ip = (ip4_header_t *) match;
4007
4008 /* These are realistically matched in practice */
4009 if (src)
4010 ip->src_address.as_u32 = src_val.as_u32;
4011
4012 if (dst)
4013 ip->dst_address.as_u32 = dst_val.as_u32;
4014
4015 if (proto)
4016 ip->protocol = proto_val;
4017
4018
4019 /* These are not, but they're included for completeness */
4020 if (version)
4021 ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
4022
4023 if (hdr_length)
4024 ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
4025
4026 if (tos)
4027 ip->tos = tos_val;
4028
4029 if (length)
4030 ip->length = clib_host_to_net_u16 (length_val);
4031
4032 if (ttl)
4033 ip->ttl = ttl_val;
4034
4035 if (checksum)
4036 ip->checksum = clib_host_to_net_u16 (checksum_val);
4037
4038 *matchp = match;
4039 return 1;
4040}
4041
4042uword
4043unformat_ip6_match (unformat_input_t * input, va_list * args)
4044{
4045 u8 **matchp = va_arg (*args, u8 **);
4046 u8 *match = 0;
4047 ip6_header_t *ip;
4048 int version = 0;
4049 u32 version_val;
4050 u8 traffic_class = 0;
4051 u32 traffic_class_val = 0;
4052 u8 flow_label = 0;
4053 u8 flow_label_val;
4054 int src = 0, dst = 0;
4055 ip6_address_t src_val, dst_val;
4056 int proto = 0;
4057 u32 proto_val;
4058 int payload_length = 0;
4059 u32 payload_length_val;
4060 int hop_limit = 0;
4061 int hop_limit_val;
4062 u32 ip_version_traffic_class_and_flow_label;
4063
4064 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4065 {
4066 if (unformat (input, "version %d", &version_val))
4067 version = 1;
4068 else if (unformat (input, "traffic_class %d", &traffic_class_val))
4069 traffic_class = 1;
4070 else if (unformat (input, "flow_label %d", &flow_label_val))
4071 flow_label = 1;
4072 else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
4073 src = 1;
4074 else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
4075 dst = 1;
4076 else if (unformat (input, "proto %d", &proto_val))
4077 proto = 1;
4078 else if (unformat (input, "payload_length %d", &payload_length_val))
4079 payload_length = 1;
4080 else if (unformat (input, "hop_limit %d", &hop_limit_val))
4081 hop_limit = 1;
4082 else
4083 break;
4084 }
4085
4086 if (version + traffic_class + flow_label + src + dst + proto +
4087 payload_length + hop_limit == 0)
4088 return 0;
4089
4090 /*
4091 * Aligned because we use the real comparison functions
4092 */
4093 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
4094
4095 ip = (ip6_header_t *) match;
4096
4097 if (src)
4098 clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
4099
4100 if (dst)
4101 clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
4102
4103 if (proto)
4104 ip->protocol = proto_val;
4105
4106 ip_version_traffic_class_and_flow_label = 0;
4107
4108 if (version)
4109 ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
4110
4111 if (traffic_class)
4112 ip_version_traffic_class_and_flow_label |=
4113 (traffic_class_val & 0xFF) << 20;
4114
4115 if (flow_label)
4116 ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
4117
4118 ip->ip_version_traffic_class_and_flow_label =
4119 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
4120
4121 if (payload_length)
4122 ip->payload_length = clib_host_to_net_u16 (payload_length_val);
4123
4124 if (hop_limit)
4125 ip->hop_limit = hop_limit_val;
4126
4127 *matchp = match;
4128 return 1;
4129}
4130
4131uword
4132unformat_l3_match (unformat_input_t * input, va_list * args)
4133{
4134 u8 **matchp = va_arg (*args, u8 **);
4135
4136 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4137 {
4138 if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
4139 return 1;
4140 else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
4141 return 1;
4142 else
4143 break;
4144 }
4145 return 0;
4146}
4147
4148uword
4149unformat_vlan_tag (unformat_input_t * input, va_list * args)
4150{
4151 u8 *tagp = va_arg (*args, u8 *);
4152 u32 tag;
4153
4154 if (unformat (input, "%d", &tag))
4155 {
4156 tagp[0] = (tag >> 8) & 0x0F;
4157 tagp[1] = tag & 0xFF;
4158 return 1;
4159 }
4160
4161 return 0;
4162}
4163
4164uword
4165unformat_l2_match (unformat_input_t * input, va_list * args)
4166{
4167 u8 **matchp = va_arg (*args, u8 **);
4168 u8 *match = 0;
4169 u8 src = 0;
4170 u8 src_val[6];
4171 u8 dst = 0;
4172 u8 dst_val[6];
4173 u8 proto = 0;
4174 u16 proto_val;
4175 u8 tag1 = 0;
4176 u8 tag1_val[2];
4177 u8 tag2 = 0;
4178 u8 tag2_val[2];
4179 int len = 14;
4180 u8 ignore_tag1 = 0;
4181 u8 ignore_tag2 = 0;
4182 u8 cos1 = 0;
4183 u8 cos2 = 0;
4184 u32 cos1_val = 0;
4185 u32 cos2_val = 0;
4186
4187 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4188 {
4189 if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
4190 src = 1;
4191 else
4192 if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
4193 dst = 1;
4194 else if (unformat (input, "proto %U",
4195 unformat_ethernet_type_host_byte_order, &proto_val))
4196 proto = 1;
4197 else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
4198 tag1 = 1;
4199 else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
4200 tag2 = 1;
4201 else if (unformat (input, "ignore-tag1"))
4202 ignore_tag1 = 1;
4203 else if (unformat (input, "ignore-tag2"))
4204 ignore_tag2 = 1;
4205 else if (unformat (input, "cos1 %d", &cos1_val))
4206 cos1 = 1;
4207 else if (unformat (input, "cos2 %d", &cos2_val))
4208 cos2 = 1;
4209 else
4210 break;
4211 }
4212 if ((src + dst + proto + tag1 + tag2 +
4213 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
4214 return 0;
4215
4216 if (tag1 || ignore_tag1 || cos1)
4217 len = 18;
4218 if (tag2 || ignore_tag2 || cos2)
4219 len = 22;
4220
4221 vec_validate_aligned (match, len - 1, sizeof (u32x4));
4222
4223 if (dst)
4224 clib_memcpy (match, dst_val, 6);
4225
4226 if (src)
4227 clib_memcpy (match + 6, src_val, 6);
4228
4229 if (tag2)
4230 {
4231 /* inner vlan tag */
4232 match[19] = tag2_val[1];
4233 match[18] = tag2_val[0];
4234 if (cos2)
4235 match[18] |= (cos2_val & 0x7) << 5;
4236 if (proto)
4237 {
4238 match[21] = proto_val & 0xff;
4239 match[20] = proto_val >> 8;
4240 }
4241 if (tag1)
4242 {
4243 match[15] = tag1_val[1];
4244 match[14] = tag1_val[0];
4245 }
4246 if (cos1)
4247 match[14] |= (cos1_val & 0x7) << 5;
4248 *matchp = match;
4249 return 1;
4250 }
4251 if (tag1)
4252 {
4253 match[15] = tag1_val[1];
4254 match[14] = tag1_val[0];
4255 if (proto)
4256 {
4257 match[17] = proto_val & 0xff;
4258 match[16] = proto_val >> 8;
4259 }
4260 if (cos1)
4261 match[14] |= (cos1_val & 0x7) << 5;
4262
4263 *matchp = match;
4264 return 1;
4265 }
4266 if (cos2)
4267 match[18] |= (cos2_val & 0x7) << 5;
4268 if (cos1)
4269 match[14] |= (cos1_val & 0x7) << 5;
4270 if (proto)
4271 {
4272 match[13] = proto_val & 0xff;
4273 match[12] = proto_val >> 8;
4274 }
4275
4276 *matchp = match;
4277 return 1;
4278}
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -07004279
4280uword
4281unformat_qos_source (unformat_input_t * input, va_list * args)
4282{
4283 int *qs = va_arg (*args, int *);
4284
4285 if (unformat (input, "ip"))
4286 *qs = QOS_SOURCE_IP;
4287 else if (unformat (input, "mpls"))
4288 *qs = QOS_SOURCE_MPLS;
4289 else if (unformat (input, "ext"))
4290 *qs = QOS_SOURCE_EXT;
4291 else if (unformat (input, "vlan"))
4292 *qs = QOS_SOURCE_VLAN;
4293 else
4294 return 0;
4295
4296 return 1;
4297}
Dave Barach4a3f69c2017-02-22 12:44:56 -05004298#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01004299
4300uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05004301api_unformat_classify_match (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004302{
4303 u8 **matchp = va_arg (*args, u8 **);
4304 u32 skip_n_vectors = va_arg (*args, u32);
4305 u32 match_n_vectors = va_arg (*args, u32);
4306
4307 u8 *match = 0;
4308 u8 *l2 = 0;
4309 u8 *l3 = 0;
4310 u8 *l4 = 0;
4311
4312 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4313 {
4314 if (unformat (input, "hex %U", unformat_hex_string, &match))
4315 ;
4316 else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
4317 ;
4318 else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
4319 ;
4320 else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
4321 ;
4322 else
4323 break;
4324 }
4325
4326 if (l4 && !l3)
4327 {
4328 vec_free (match);
4329 vec_free (l2);
4330 vec_free (l4);
4331 return 0;
4332 }
4333
4334 if (match || l2 || l3 || l4)
4335 {
4336 if (l2 || l3 || l4)
4337 {
4338 /* "Win a free Ethernet header in every packet" */
4339 if (l2 == 0)
4340 vec_validate_aligned (l2, 13, sizeof (u32x4));
4341 match = l2;
4342 if (vec_len (l3))
4343 {
4344 vec_append_aligned (match, l3, sizeof (u32x4));
4345 vec_free (l3);
4346 }
4347 if (vec_len (l4))
4348 {
4349 vec_append_aligned (match, l4, sizeof (u32x4));
4350 vec_free (l4);
4351 }
4352 }
4353
4354 /* Make sure the vector is big enough even if key is all 0's */
4355 vec_validate_aligned
4356 (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
4357 sizeof (u32x4));
4358
4359 /* Set size, include skipped vectors */
4360 _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
4361
4362 *matchp = match;
4363
4364 return 1;
4365 }
4366
4367 return 0;
4368}
4369
4370static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01004371api_get_node_index (vat_main_t * vam)
4372{
4373 unformat_input_t *i = vam->input;
4374 vl_api_get_node_index_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004375 u8 *name = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004376 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004377
4378 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4379 {
4380 if (unformat (i, "node %s", &name))
4381 ;
4382 else
4383 break;
4384 }
4385 if (name == 0)
4386 {
4387 errmsg ("node name required");
4388 return -99;
4389 }
4390 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
4391 {
4392 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
4393 return -99;
4394 }
4395
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004396 M (GET_NODE_INDEX, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004397 clib_memcpy (mp->node_name, name, vec_len (name));
4398 vec_free (name);
4399
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004400 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06004401 W (ret);
4402 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004403}
4404
4405static int
4406api_get_next_index (vat_main_t * vam)
4407{
4408 unformat_input_t *i = vam->input;
4409 vl_api_get_next_index_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004410 u8 *node_name = 0, *next_node_name = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004411 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004412
4413 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4414 {
4415 if (unformat (i, "node-name %s", &node_name))
4416 ;
4417 else if (unformat (i, "next-node-name %s", &next_node_name))
4418 break;
4419 }
4420
4421 if (node_name == 0)
4422 {
4423 errmsg ("node name required");
4424 return -99;
4425 }
4426 if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
4427 {
4428 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
4429 return -99;
4430 }
4431
4432 if (next_node_name == 0)
4433 {
4434 errmsg ("next node name required");
4435 return -99;
4436 }
4437 if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
4438 {
4439 errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
4440 return -99;
4441 }
4442
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004443 M (GET_NEXT_INDEX, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004444 clib_memcpy (mp->node_name, node_name, vec_len (node_name));
4445 clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
4446 vec_free (node_name);
4447 vec_free (next_node_name);
4448
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004449 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06004450 W (ret);
4451 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004452}
4453
4454static int
4455api_add_node_next (vat_main_t * vam)
4456{
4457 unformat_input_t *i = vam->input;
4458 vl_api_add_node_next_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004459 u8 *name = 0;
4460 u8 *next = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004461 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004462
4463 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4464 {
4465 if (unformat (i, "node %s", &name))
4466 ;
4467 else if (unformat (i, "next %s", &next))
4468 ;
4469 else
4470 break;
4471 }
4472 if (name == 0)
4473 {
4474 errmsg ("node name required");
4475 return -99;
4476 }
4477 if (vec_len (name) >= ARRAY_LEN (mp->node_name))
4478 {
4479 errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
4480 return -99;
4481 }
4482 if (next == 0)
4483 {
4484 errmsg ("next node required");
4485 return -99;
4486 }
4487 if (vec_len (next) >= ARRAY_LEN (mp->next_name))
4488 {
4489 errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
4490 return -99;
4491 }
4492
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004493 M (ADD_NODE_NEXT, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004494 clib_memcpy (mp->node_name, name, vec_len (name));
4495 clib_memcpy (mp->next_name, next, vec_len (next));
4496 vec_free (name);
4497 vec_free (next);
4498
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004499 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06004500 W (ret);
4501 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004502}
4503
Damjan Marion7cd468a2016-12-19 23:05:39 +01004504#define foreach_vtr_op \
4505_("disable", L2_VTR_DISABLED) \
4506_("push-1", L2_VTR_PUSH_1) \
4507_("push-2", L2_VTR_PUSH_2) \
4508_("pop-1", L2_VTR_POP_1) \
4509_("pop-2", L2_VTR_POP_2) \
4510_("translate-1-1", L2_VTR_TRANSLATE_1_1) \
4511_("translate-1-2", L2_VTR_TRANSLATE_1_2) \
4512_("translate-2-1", L2_VTR_TRANSLATE_2_1) \
4513_("translate-2-2", L2_VTR_TRANSLATE_2_2)
4514
4515static int
Filip Tehlar4f348df2021-06-22 12:18:17 +00004516api_show_version (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004517{
4518 vl_api_show_version_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004519 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004520
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004521 M (SHOW_VERSION, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004522
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004523 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06004524 W (ret);
4525 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004526}
4527
Damjan Marion7cd468a2016-12-19 23:05:39 +01004528static int
Filip Tehlar4f348df2021-06-22 12:18:17 +00004529api_interface_name_renumber (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004530{
4531 unformat_input_t *line_input = vam->input;
4532 vl_api_interface_name_renumber_t *mp;
4533 u32 sw_if_index = ~0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004534 u32 new_show_dev_instance = ~0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004535 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004536
4537 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
4538 {
4539 if (unformat (line_input, "%U", api_unformat_sw_if_index, vam,
4540 &sw_if_index))
4541 ;
4542 else if (unformat (line_input, "sw_if_index %d", &sw_if_index))
4543 ;
4544 else if (unformat (line_input, "new_show_dev_instance %d",
4545 &new_show_dev_instance))
4546 ;
4547 else
4548 break;
4549 }
4550
4551 if (sw_if_index == ~0)
4552 {
4553 errmsg ("missing interface name or sw_if_index");
4554 return -99;
4555 }
4556
4557 if (new_show_dev_instance == ~0)
4558 {
4559 errmsg ("missing new_show_dev_instance");
4560 return -99;
4561 }
4562
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004563 M (INTERFACE_NAME_RENUMBER, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004564
4565 mp->sw_if_index = ntohl (sw_if_index);
4566 mp->new_show_dev_instance = ntohl (new_show_dev_instance);
4567
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004568 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06004569 W (ret);
4570 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004571}
4572
4573static int
Filip Tehlar4f348df2021-06-22 12:18:17 +00004574api_ip_address_dump (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004575{
4576 unformat_input_t *i = vam->input;
4577 vl_api_ip_address_dump_t *mp;
Jon Loeliger2d23eca2017-02-01 13:09:58 -06004578 vl_api_control_ping_t *mp_ping;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004579 u32 sw_if_index = ~0;
4580 u8 sw_if_index_set = 0;
4581 u8 ipv4_set = 0;
4582 u8 ipv6_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004583 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004584
4585 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4586 {
4587 if (unformat (i, "sw_if_index %d", &sw_if_index))
4588 sw_if_index_set = 1;
Filip Tehlar4f348df2021-06-22 12:18:17 +00004589 else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
Damjan Marion7cd468a2016-12-19 23:05:39 +01004590 sw_if_index_set = 1;
4591 else if (unformat (i, "ipv4"))
4592 ipv4_set = 1;
4593 else if (unformat (i, "ipv6"))
4594 ipv6_set = 1;
4595 else
4596 break;
4597 }
4598
4599 if (ipv4_set && ipv6_set)
4600 {
4601 errmsg ("ipv4 and ipv6 flags cannot be both set");
4602 return -99;
4603 }
4604
4605 if ((!ipv4_set) && (!ipv6_set))
4606 {
4607 errmsg ("no ipv4 nor ipv6 flag set");
4608 return -99;
4609 }
4610
4611 if (sw_if_index_set == 0)
4612 {
4613 errmsg ("missing interface name or sw_if_index");
4614 return -99;
4615 }
4616
4617 vam->current_sw_if_index = sw_if_index;
4618 vam->is_ipv6 = ipv6_set;
4619
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004620 M (IP_ADDRESS_DUMP, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004621 mp->sw_if_index = ntohl (sw_if_index);
4622 mp->is_ipv6 = ipv6_set;
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004623 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004624
4625 /* Use a control ping for synchronization */
Dave Barach59b25652017-09-10 15:04:27 -04004626 MPING (CONTROL_PING, mp_ping);
Jon Loeliger2d23eca2017-02-01 13:09:58 -06004627 S (mp_ping);
4628
Jon Loeliger56c7b012017-02-01 12:31:41 -06004629 W (ret);
4630 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004631}
4632
4633static int
4634api_ip_dump (vat_main_t * vam)
4635{
4636 vl_api_ip_dump_t *mp;
Jon Loeliger2d23eca2017-02-01 13:09:58 -06004637 vl_api_control_ping_t *mp_ping;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004638 unformat_input_t *in = vam->input;
4639 int ipv4_set = 0;
4640 int ipv6_set = 0;
4641 int is_ipv6;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004642 int i;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004643 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004644
4645 while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
4646 {
4647 if (unformat (in, "ipv4"))
4648 ipv4_set = 1;
4649 else if (unformat (in, "ipv6"))
4650 ipv6_set = 1;
4651 else
4652 break;
4653 }
4654
4655 if (ipv4_set && ipv6_set)
4656 {
4657 errmsg ("ipv4 and ipv6 flags cannot be both set");
4658 return -99;
4659 }
4660
4661 if ((!ipv4_set) && (!ipv6_set))
4662 {
4663 errmsg ("no ipv4 nor ipv6 flag set");
4664 return -99;
4665 }
4666
4667 is_ipv6 = ipv6_set;
4668 vam->is_ipv6 = is_ipv6;
4669
4670 /* free old data */
4671 for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
4672 {
4673 vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
4674 }
4675 vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
4676
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004677 M (IP_DUMP, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004678 mp->is_ipv6 = ipv6_set;
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004679 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004680
4681 /* Use a control ping for synchronization */
Dave Barach59b25652017-09-10 15:04:27 -04004682 MPING (CONTROL_PING, mp_ping);
Jon Loeliger2d23eca2017-02-01 13:09:58 -06004683 S (mp_ping);
4684
Jon Loeliger56c7b012017-02-01 12:31:41 -06004685 W (ret);
4686 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004687}
4688
4689static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01004690api_get_first_msg_id (vat_main_t * vam)
4691{
4692 vl_api_get_first_msg_id_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004693 unformat_input_t *i = vam->input;
4694 u8 *name;
4695 u8 name_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004696 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004697
4698 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
4699 {
4700 if (unformat (i, "client %s", &name))
4701 name_set = 1;
4702 else
4703 break;
4704 }
4705
4706 if (name_set == 0)
4707 {
4708 errmsg ("missing client name");
4709 return -99;
4710 }
4711 vec_add1 (name, 0);
4712
4713 if (vec_len (name) > 63)
4714 {
4715 errmsg ("client name too long");
4716 return -99;
4717 }
4718
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004719 M (GET_FIRST_MSG_ID, mp);
Ole Troan7adaa222019-08-27 15:05:27 +02004720 clib_memcpy (mp->name, name, vec_len (name));
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004721 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06004722 W (ret);
4723 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004724}
4725
4726static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01004727api_get_node_graph (vat_main_t * vam)
4728{
4729 vl_api_get_node_graph_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004730 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004731
Jon Loeliger8a2aea32017-01-31 13:19:40 -06004732 M (GET_NODE_GRAPH, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004733
4734 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004735 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004736 /* Wait for the reply */
Jon Loeliger56c7b012017-02-01 12:31:41 -06004737 W (ret);
4738 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004739}
4740
Neale Ranns097fa662018-05-01 05:17:55 -07004741static u8 *
4742format_fib_api_path_nh_proto (u8 * s, va_list * args)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08004743{
Neale Ranns097fa662018-05-01 05:17:55 -07004744 vl_api_fib_path_nh_proto_t proto =
4745 va_arg (*args, vl_api_fib_path_nh_proto_t);
4746
4747 switch (proto)
4748 {
4749 case FIB_API_PATH_NH_PROTO_IP4:
4750 s = format (s, "ip4");
4751 break;
4752 case FIB_API_PATH_NH_PROTO_IP6:
4753 s = format (s, "ip6");
4754 break;
4755 case FIB_API_PATH_NH_PROTO_MPLS:
4756 s = format (s, "mpls");
4757 break;
4758 case FIB_API_PATH_NH_PROTO_BIER:
4759 s = format (s, "bier");
4760 break;
4761 case FIB_API_PATH_NH_PROTO_ETHERNET:
4762 s = format (s, "ethernet");
4763 break;
4764 }
4765
4766 return (s);
4767}
4768
4769static u8 *
4770format_vl_api_ip_address_union (u8 * s, va_list * args)
4771{
Jakub Grajciar7dd63e52020-03-19 08:03:55 +01004772 vl_api_address_family_t af = va_arg (*args, int);
Neale Ranns097fa662018-05-01 05:17:55 -07004773 const vl_api_address_union_t *u = va_arg (*args, vl_api_address_union_t *);
4774
4775 switch (af)
4776 {
4777 case ADDRESS_IP4:
4778 s = format (s, "%U", format_ip4_address, u->ip4);
4779 break;
4780 case ADDRESS_IP6:
4781 s = format (s, "%U", format_ip6_address, u->ip6);
4782 break;
4783 }
4784 return (s);
4785}
4786
4787static u8 *
4788format_vl_api_fib_path_type (u8 * s, va_list * args)
4789{
4790 vl_api_fib_path_type_t t = va_arg (*args, vl_api_fib_path_type_t);
4791
4792 switch (t)
4793 {
4794 case FIB_API_PATH_TYPE_NORMAL:
4795 s = format (s, "normal");
4796 break;
4797 case FIB_API_PATH_TYPE_LOCAL:
4798 s = format (s, "local");
4799 break;
4800 case FIB_API_PATH_TYPE_DROP:
4801 s = format (s, "drop");
4802 break;
4803 case FIB_API_PATH_TYPE_UDP_ENCAP:
4804 s = format (s, "udp-encap");
4805 break;
4806 case FIB_API_PATH_TYPE_BIER_IMP:
4807 s = format (s, "bier-imp");
4808 break;
4809 case FIB_API_PATH_TYPE_ICMP_UNREACH:
4810 s = format (s, "unreach");
4811 break;
4812 case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
4813 s = format (s, "prohibit");
4814 break;
4815 case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
4816 s = format (s, "src-lookup");
4817 break;
4818 case FIB_API_PATH_TYPE_DVR:
4819 s = format (s, "dvr");
4820 break;
4821 case FIB_API_PATH_TYPE_INTERFACE_RX:
4822 s = format (s, "interface-rx");
4823 break;
4824 case FIB_API_PATH_TYPE_CLASSIFY:
4825 s = format (s, "classify");
4826 break;
4827 }
4828
4829 return (s);
4830}
4831
4832static void
4833vl_api_fib_path_print (vat_main_t * vam, vl_api_fib_path_t * fp)
4834{
4835 print (vam->ofp,
4836 " weight %d, sw_if_index %d, type %U, afi %U, next_hop %U",
4837 ntohl (fp->weight), ntohl (fp->sw_if_index),
4838 format_vl_api_fib_path_type, fp->type,
4839 format_fib_api_path_nh_proto, fp->proto,
4840 format_vl_api_ip_address_union, &fp->nh.address);
Neale Ranns0f26c5a2017-03-01 15:12:11 -08004841}
4842
4843static void
4844vl_api_mpls_fib_path_json_print (vat_json_node_t * node,
Neale Ranns31ed7442018-02-23 05:29:09 -08004845 vl_api_fib_path_t * fp)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08004846{
4847 struct in_addr ip4;
4848 struct in6_addr ip6;
4849
4850 vat_json_object_add_uint (node, "weight", ntohl (fp->weight));
4851 vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index));
Neale Ranns097fa662018-05-01 05:17:55 -07004852 vat_json_object_add_uint (node, "type", fp->type);
4853 vat_json_object_add_uint (node, "next_hop_proto", fp->proto);
4854 if (fp->proto == FIB_API_PATH_NH_PROTO_IP4)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08004855 {
Neale Ranns097fa662018-05-01 05:17:55 -07004856 clib_memcpy (&ip4, &fp->nh.address.ip4, sizeof (ip4));
Neale Ranns0f26c5a2017-03-01 15:12:11 -08004857 vat_json_object_add_ip4 (node, "next_hop", ip4);
4858 }
Dave Barachc35f3e82020-04-02 10:44:09 -04004859 else if (fp->proto == FIB_API_PATH_NH_PROTO_IP6)
Neale Ranns0f26c5a2017-03-01 15:12:11 -08004860 {
Neale Ranns097fa662018-05-01 05:17:55 -07004861 clib_memcpy (&ip6, &fp->nh.address.ip6, sizeof (ip6));
Neale Ranns0f26c5a2017-03-01 15:12:11 -08004862 vat_json_object_add_ip6 (node, "next_hop", ip6);
4863 }
4864}
4865
Neale Ranns097fa662018-05-01 05:17:55 -07004866#define vl_api_ip_table_details_t_endian vl_noop_handler
4867#define vl_api_ip_table_details_t_print vl_noop_handler
Damjan Marion7cd468a2016-12-19 23:05:39 +01004868
4869static void
Neale Ranns097fa662018-05-01 05:17:55 -07004870vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004871{
4872 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004873
4874 print (vam->ofp,
Neale Ranns097fa662018-05-01 05:17:55 -07004875 "%s; table-id %d, prefix %U/%d",
4876 mp->table.name, ntohl (mp->table.table_id));
Damjan Marion7cd468a2016-12-19 23:05:39 +01004877}
4878
Neale Ranns097fa662018-05-01 05:17:55 -07004879
4880static void vl_api_ip_table_details_t_handler_json
4881 (vl_api_ip_table_details_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004882{
4883 vat_main_t *vam = &vat_main;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004884 vat_json_node_t *node = NULL;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004885
4886 if (VAT_JSON_ARRAY != vam->json_tree.type)
4887 {
4888 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
4889 vat_json_init_array (&vam->json_tree);
4890 }
4891 node = vat_json_array_add (&vam->json_tree);
4892
4893 vat_json_init_object (node);
Neale Ranns097fa662018-05-01 05:17:55 -07004894 vat_json_object_add_uint (node, "table", ntohl (mp->table.table_id));
Damjan Marion7cd468a2016-12-19 23:05:39 +01004895}
4896
4897static int
Neale Ranns097fa662018-05-01 05:17:55 -07004898api_ip_table_dump (vat_main_t * vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004899{
Neale Ranns097fa662018-05-01 05:17:55 -07004900 vl_api_ip_table_dump_t *mp;
Jon Loeliger2d23eca2017-02-01 13:09:58 -06004901 vl_api_control_ping_t *mp_ping;
Jon Loeliger56c7b012017-02-01 12:31:41 -06004902 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004903
Neale Ranns097fa662018-05-01 05:17:55 -07004904 M (IP_TABLE_DUMP, mp);
Jon Loeliger7bc770c2017-01-31 14:03:33 -06004905 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004906
4907 /* Use a control ping for synchronization */
Dave Barach59b25652017-09-10 15:04:27 -04004908 MPING (CONTROL_PING, mp_ping);
Jon Loeliger2d23eca2017-02-01 13:09:58 -06004909 S (mp_ping);
4910
Jon Loeliger56c7b012017-02-01 12:31:41 -06004911 W (ret);
4912 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004913}
4914
Neale Ranns5a8123b2017-01-26 01:18:23 -08004915static int
Neale Ranns097fa662018-05-01 05:17:55 -07004916api_ip_mtable_dump (vat_main_t * vam)
Neale Ranns5a8123b2017-01-26 01:18:23 -08004917{
Neale Ranns097fa662018-05-01 05:17:55 -07004918 vl_api_ip_mtable_dump_t *mp;
Neale Ranns5a8123b2017-01-26 01:18:23 -08004919 vl_api_control_ping_t *mp_ping;
4920 int ret;
4921
Neale Ranns097fa662018-05-01 05:17:55 -07004922 M (IP_MTABLE_DUMP, mp);
4923 S (mp);
4924
4925 /* Use a control ping for synchronization */
4926 MPING (CONTROL_PING, mp_ping);
4927 S (mp_ping);
4928
4929 W (ret);
4930 return ret;
4931}
4932
4933static int
4934api_ip_mroute_dump (vat_main_t * vam)
4935{
4936 unformat_input_t *input = vam->input;
4937 vl_api_control_ping_t *mp_ping;
4938 vl_api_ip_mroute_dump_t *mp;
4939 int ret, is_ip6;
4940 u32 table_id;
4941
4942 is_ip6 = 0;
4943 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
4944 {
4945 if (unformat (input, "table_id %d", &table_id))
4946 ;
4947 else if (unformat (input, "ip6"))
4948 is_ip6 = 1;
4949 else if (unformat (input, "ip4"))
4950 is_ip6 = 0;
4951 else
4952 break;
4953 }
4954 if (table_id == ~0)
4955 {
4956 errmsg ("missing table id");
4957 return -99;
4958 }
4959
4960 M (IP_MROUTE_DUMP, mp);
4961 mp->table.table_id = table_id;
4962 mp->table.is_ip6 = is_ip6;
Neale Ranns5a8123b2017-01-26 01:18:23 -08004963 S (mp);
4964
4965 /* Use a control ping for synchronization */
Dave Barach59b25652017-09-10 15:04:27 -04004966 MPING (CONTROL_PING, mp_ping);
Neale Ranns5a8123b2017-01-26 01:18:23 -08004967 S (mp_ping);
4968
4969 W (ret);
4970 return ret;
4971}
4972
Neale Ranns097fa662018-05-01 05:17:55 -07004973#define vl_api_ip_route_details_t_endian vl_noop_handler
4974#define vl_api_ip_route_details_t_print vl_noop_handler
Damjan Marion7cd468a2016-12-19 23:05:39 +01004975
4976static void
Neale Ranns097fa662018-05-01 05:17:55 -07004977vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004978{
4979 vat_main_t *vam = &vat_main;
Neale Ranns097fa662018-05-01 05:17:55 -07004980 u8 count = mp->route.n_paths;
Damjan Marion7cd468a2016-12-19 23:05:39 +01004981 vl_api_fib_path_t *fp;
4982 int i;
4983
4984 print (vam->ofp,
Neale Ranns097fa662018-05-01 05:17:55 -07004985 "table-id %d, prefix %U/%d",
4986 ntohl (mp->route.table_id),
Paul Vinciguerraab055082019-06-06 14:07:55 -04004987 format_ip46_address, mp->route.prefix.address, mp->route.prefix.len);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004988 for (i = 0; i < count; i++)
4989 {
Neale Ranns097fa662018-05-01 05:17:55 -07004990 fp = &mp->route.paths[i];
4991
4992 vl_api_fib_path_print (vam, fp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01004993 fp++;
4994 }
4995}
4996
Neale Ranns097fa662018-05-01 05:17:55 -07004997static void vl_api_ip_route_details_t_handler_json
4998 (vl_api_ip_route_details_t * mp)
Damjan Marion7cd468a2016-12-19 23:05:39 +01004999{
5000 vat_main_t *vam = &vat_main;
Neale Ranns097fa662018-05-01 05:17:55 -07005001 u8 count = mp->route.n_paths;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005002 vat_json_node_t *node = NULL;
5003 struct in_addr ip4;
5004 struct in6_addr ip6;
5005 vl_api_fib_path_t *fp;
5006 int i;
5007
5008 if (VAT_JSON_ARRAY != vam->json_tree.type)
5009 {
5010 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5011 vat_json_init_array (&vam->json_tree);
5012 }
5013 node = vat_json_array_add (&vam->json_tree);
5014
5015 vat_json_init_object (node);
Neale Ranns097fa662018-05-01 05:17:55 -07005016 vat_json_object_add_uint (node, "table", ntohl (mp->route.table_id));
5017 if (ADDRESS_IP6 == mp->route.prefix.address.af)
5018 {
5019 clib_memcpy (&ip6, &mp->route.prefix.address.un.ip6, sizeof (ip6));
5020 vat_json_object_add_ip6 (node, "prefix", ip6);
5021 }
5022 else
5023 {
5024 clib_memcpy (&ip4, &mp->route.prefix.address.un.ip4, sizeof (ip4));
5025 vat_json_object_add_ip4 (node, "prefix", ip4);
5026 }
Paul Vinciguerraab055082019-06-06 14:07:55 -04005027 vat_json_object_add_uint (node, "mask_length", mp->route.prefix.len);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005028 vat_json_object_add_uint (node, "path_count", count);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005029 for (i = 0; i < count; i++)
5030 {
Neale Ranns097fa662018-05-01 05:17:55 -07005031 fp = &mp->route.paths[i];
5032 vl_api_mpls_fib_path_json_print (node, fp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005033 }
5034}
5035
5036static int
Neale Ranns097fa662018-05-01 05:17:55 -07005037api_ip_route_dump (vat_main_t * vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01005038{
Neale Ranns097fa662018-05-01 05:17:55 -07005039 unformat_input_t *input = vam->input;
5040 vl_api_ip_route_dump_t *mp;
Jon Loeliger2d23eca2017-02-01 13:09:58 -06005041 vl_api_control_ping_t *mp_ping;
Neale Ranns097fa662018-05-01 05:17:55 -07005042 u32 table_id;
5043 u8 is_ip6;
Jon Loeliger56c7b012017-02-01 12:31:41 -06005044 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005045
Neale Ranns097fa662018-05-01 05:17:55 -07005046 is_ip6 = 0;
5047 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5048 {
5049 if (unformat (input, "table_id %d", &table_id))
5050 ;
5051 else if (unformat (input, "ip6"))
5052 is_ip6 = 1;
5053 else if (unformat (input, "ip4"))
5054 is_ip6 = 0;
5055 else
5056 break;
5057 }
5058 if (table_id == ~0)
5059 {
5060 errmsg ("missing table id");
5061 return -99;
5062 }
Damjan Marion7cd468a2016-12-19 23:05:39 +01005063
Neale Ranns097fa662018-05-01 05:17:55 -07005064 M (IP_ROUTE_DUMP, mp);
Jon Loeliger2d23eca2017-02-01 13:09:58 -06005065
Neale Ranns097fa662018-05-01 05:17:55 -07005066 mp->table.table_id = table_id;
5067 mp->table.is_ip6 = is_ip6;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005068
Neale Ranns5a8123b2017-01-26 01:18:23 -08005069 S (mp);
5070
5071 /* Use a control ping for synchronization */
Dave Barach59b25652017-09-10 15:04:27 -04005072 MPING (CONTROL_PING, mp_ping);
Neale Ranns5a8123b2017-01-26 01:18:23 -08005073 S (mp_ping);
5074
5075 W (ret);
5076 return ret;
5077}
5078
Damjan Marion7cd468a2016-12-19 23:05:39 +01005079int
Damjan Marion7cd468a2016-12-19 23:05:39 +01005080api_ip_source_and_port_range_check_add_del (vat_main_t * vam)
5081{
5082 unformat_input_t *input = vam->input;
5083 vl_api_ip_source_and_port_range_check_add_del_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005084
5085 u16 *low_ports = 0;
5086 u16 *high_ports = 0;
5087 u16 this_low;
5088 u16 this_hi;
Neale Ranns37029302018-08-10 05:30:06 -07005089 vl_api_prefix_t prefix;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005090 u32 tmp, tmp2;
5091 u8 prefix_set = 0;
5092 u32 vrf_id = ~0;
5093 u8 is_add = 1;
Jon Loeliger56c7b012017-02-01 12:31:41 -06005094 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005095
5096 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5097 {
Neale Ranns37029302018-08-10 05:30:06 -07005098 if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
5099 prefix_set = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005100 else if (unformat (input, "vrf %d", &vrf_id))
5101 ;
5102 else if (unformat (input, "del"))
5103 is_add = 0;
5104 else if (unformat (input, "port %d", &tmp))
5105 {
5106 if (tmp == 0 || tmp > 65535)
5107 {
5108 errmsg ("port %d out of range", tmp);
5109 return -99;
5110 }
5111 this_low = tmp;
5112 this_hi = this_low + 1;
5113 vec_add1 (low_ports, this_low);
5114 vec_add1 (high_ports, this_hi);
5115 }
5116 else if (unformat (input, "range %d - %d", &tmp, &tmp2))
5117 {
5118 if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
5119 {
5120 errmsg ("incorrect range parameters");
5121 return -99;
5122 }
5123 this_low = tmp;
5124 /* Note: in debug CLI +1 is added to high before
5125 passing to real fn that does "the work"
5126 (ip_source_and_port_range_check_add_del).
5127 This fn is a wrapper around the binary API fn a
5128 control plane will call, which expects this increment
5129 to have occurred. Hence letting the binary API control
5130 plane fn do the increment for consistency between VAT
5131 and other control planes.
5132 */
5133 this_hi = tmp2;
5134 vec_add1 (low_ports, this_low);
5135 vec_add1 (high_ports, this_hi);
5136 }
5137 else
5138 break;
5139 }
5140
5141 if (prefix_set == 0)
5142 {
5143 errmsg ("<address>/<mask> not specified");
5144 return -99;
5145 }
5146
5147 if (vrf_id == ~0)
5148 {
5149 errmsg ("VRF ID required, not specified");
5150 return -99;
5151 }
5152
5153 if (vrf_id == 0)
5154 {
5155 errmsg
5156 ("VRF ID should not be default. Should be distinct VRF for this purpose.");
5157 return -99;
5158 }
5159
5160 if (vec_len (low_ports) == 0)
5161 {
5162 errmsg ("At least one port or port range required");
5163 return -99;
5164 }
5165
Jon Loeliger8a2aea32017-01-31 13:19:40 -06005166 M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005167
5168 mp->is_add = is_add;
5169
Neale Ranns37029302018-08-10 05:30:06 -07005170 clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
Damjan Marion7cd468a2016-12-19 23:05:39 +01005171
Damjan Marion7cd468a2016-12-19 23:05:39 +01005172 mp->number_of_ranges = vec_len (low_ports);
5173
5174 clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
5175 vec_free (low_ports);
5176
5177 clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
5178 vec_free (high_ports);
5179
5180 mp->vrf_id = ntohl (vrf_id);
5181
Jon Loeliger7bc770c2017-01-31 14:03:33 -06005182 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06005183 W (ret);
5184 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005185}
5186
5187int
5188api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam)
5189{
5190 unformat_input_t *input = vam->input;
5191 vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005192 u32 sw_if_index = ~0;
5193 int vrf_set = 0;
5194 u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
5195 u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
5196 u8 is_add = 1;
Jon Loeliger56c7b012017-02-01 12:31:41 -06005197 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005198
5199 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
5200 {
5201 if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5202 ;
5203 else if (unformat (input, "sw_if_index %d", &sw_if_index))
5204 ;
5205 else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
5206 vrf_set = 1;
5207 else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
5208 vrf_set = 1;
5209 else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
5210 vrf_set = 1;
5211 else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
5212 vrf_set = 1;
5213 else if (unformat (input, "del"))
5214 is_add = 0;
5215 else
5216 break;
5217 }
5218
5219 if (sw_if_index == ~0)
5220 {
5221 errmsg ("Interface required but not specified");
5222 return -99;
5223 }
5224
5225 if (vrf_set == 0)
5226 {
5227 errmsg ("VRF ID required but not specified");
5228 return -99;
5229 }
5230
5231 if (tcp_out_vrf_id == 0
5232 || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0)
5233 {
5234 errmsg
5235 ("VRF ID should not be default. Should be distinct VRF for this purpose.");
5236 return -99;
5237 }
5238
5239 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06005240 M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005241
5242 mp->sw_if_index = ntohl (sw_if_index);
5243 mp->is_add = is_add;
5244 mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
5245 mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
5246 mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
5247 mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
5248
5249 /* send it... */
Jon Loeliger7bc770c2017-01-31 14:03:33 -06005250 S (mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005251
5252 /* Wait for a reply... */
Jon Loeliger56c7b012017-02-01 12:31:41 -06005253 W (ret);
5254 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005255}
5256
5257static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01005258api_delete_subif (vat_main_t * vam)
5259{
5260 unformat_input_t *i = vam->input;
5261 vl_api_delete_subif_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005262 u32 sw_if_index = ~0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06005263 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005264
5265 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5266 {
5267 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5268 ;
5269 if (unformat (i, "sw_if_index %d", &sw_if_index))
5270 ;
5271 else
5272 break;
5273 }
5274
5275 if (sw_if_index == ~0)
5276 {
5277 errmsg ("missing sw_if_index");
5278 return -99;
5279 }
5280
5281 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06005282 M (DELETE_SUBIF, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005283 mp->sw_if_index = ntohl (sw_if_index);
5284
Jon Loeliger7bc770c2017-01-31 14:03:33 -06005285 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06005286 W (ret);
5287 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005288}
5289
5290#define foreach_pbb_vtr_op \
5291_("disable", L2_VTR_DISABLED) \
5292_("pop", L2_VTR_POP_2) \
5293_("push", L2_VTR_PUSH_2)
5294
Damjan Marion7cd468a2016-12-19 23:05:39 +01005295
5296static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01005297api_sw_interface_tag_add_del (vat_main_t * vam)
5298{
5299 unformat_input_t *i = vam->input;
5300 vl_api_sw_interface_tag_add_del_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005301 u32 sw_if_index = ~0;
5302 u8 *tag = 0;
5303 u8 enable = 1;
Jon Loeliger56c7b012017-02-01 12:31:41 -06005304 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005305
5306 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5307 {
5308 if (unformat (i, "tag %s", &tag))
5309 ;
5310 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5311 ;
5312 else if (unformat (i, "sw_if_index %d", &sw_if_index))
5313 ;
5314 else if (unformat (i, "del"))
5315 enable = 0;
5316 else
5317 break;
5318 }
5319
5320 if (sw_if_index == ~0)
5321 {
5322 errmsg ("missing interface name or sw_if_index");
5323 return -99;
5324 }
5325
5326 if (enable && (tag == 0))
5327 {
5328 errmsg ("no tag specified");
5329 return -99;
5330 }
5331
5332 /* Construct the API message */
Jon Loeliger8a2aea32017-01-31 13:19:40 -06005333 M (SW_INTERFACE_TAG_ADD_DEL, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005334 mp->sw_if_index = ntohl (sw_if_index);
5335 mp->is_add = enable;
5336 if (enable)
Ole Troane5ff5a32019-08-23 22:55:18 +02005337 strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005338 vec_free (tag);
5339
Jon Loeliger7bc770c2017-01-31 14:03:33 -06005340 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06005341 W (ret);
5342 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005343}
5344
Matthew Smithe0792fd2019-07-12 11:48:24 -05005345static int
5346api_sw_interface_add_del_mac_address (vat_main_t * vam)
5347{
5348 unformat_input_t *i = vam->input;
5349 vl_api_mac_address_t mac = { 0 };
5350 vl_api_sw_interface_add_del_mac_address_t *mp;
5351 u32 sw_if_index = ~0;
5352 u8 is_add = 1;
5353 u8 mac_set = 0;
5354 int ret;
5355
5356 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5357 {
5358 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5359 ;
5360 else if (unformat (i, "sw_if_index %d", &sw_if_index))
5361 ;
5362 else if (unformat (i, "%U", unformat_vl_api_mac_address, &mac))
5363 mac_set++;
5364 else if (unformat (i, "del"))
5365 is_add = 0;
5366 else
5367 break;
5368 }
5369
5370 if (sw_if_index == ~0)
5371 {
5372 errmsg ("missing interface name or sw_if_index");
5373 return -99;
5374 }
5375
5376 if (!mac_set)
5377 {
5378 errmsg ("missing MAC address");
5379 return -99;
5380 }
5381
5382 /* Construct the API message */
5383 M (SW_INTERFACE_ADD_DEL_MAC_ADDRESS, mp);
5384 mp->sw_if_index = ntohl (sw_if_index);
5385 mp->is_add = is_add;
5386 clib_memcpy (&mp->addr, &mac, sizeof (mac));
5387
5388 S (mp);
5389 W (ret);
5390 return ret;
5391}
5392
Damjan Marion7cd468a2016-12-19 23:05:39 +01005393static int
Ole Troand7231612018-06-07 10:17:57 +02005394api_hw_interface_set_mtu (vat_main_t * vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01005395{
5396 unformat_input_t *i = vam->input;
Ole Troand7231612018-06-07 10:17:57 +02005397 vl_api_hw_interface_set_mtu_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005398 u32 sw_if_index = ~0;
5399 u32 mtu = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06005400 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005401
5402 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5403 {
5404 if (unformat (i, "mtu %d", &mtu))
5405 ;
5406 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
5407 ;
5408 else if (unformat (i, "sw_if_index %d", &sw_if_index))
5409 ;
5410 else
5411 break;
5412 }
5413
5414 if (sw_if_index == ~0)
5415 {
5416 errmsg ("missing interface name or sw_if_index");
5417 return -99;
5418 }
5419
5420 if (mtu == 0)
5421 {
5422 errmsg ("no mtu specified");
5423 return -99;
5424 }
5425
5426 /* Construct the API message */
Ole Troand7231612018-06-07 10:17:57 +02005427 M (HW_INTERFACE_SET_MTU, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01005428 mp->sw_if_index = ntohl (sw_if_index);
5429 mp->mtu = ntohs ((u16) mtu);
5430
Jon Loeliger7bc770c2017-01-31 14:03:33 -06005431 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06005432 W (ret);
5433 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01005434}
5435
Florin Coras6e8c6672017-11-10 09:03:54 -08005436static void vl_api_app_namespace_add_del_reply_t_handler
5437 (vl_api_app_namespace_add_del_reply_t * mp)
5438{
5439 vat_main_t *vam = &vat_main;
5440 i32 retval = ntohl (mp->retval);
5441 if (vam->async_mode)
5442 {
5443 vam->async_errors += (retval < 0);
5444 }
5445 else
5446 {
5447 vam->retval = retval;
5448 if (retval == 0)
5449 errmsg ("app ns index %d\n", ntohl (mp->appns_index));
5450 vam->result_ready = 1;
5451 }
5452}
5453
5454static void vl_api_app_namespace_add_del_reply_t_handler_json
5455 (vl_api_app_namespace_add_del_reply_t * mp)
5456{
5457 vat_main_t *vam = &vat_main;
5458 vat_json_node_t node;
5459
5460 vat_json_init_object (&node);
5461 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
5462 vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index));
5463
5464 vat_json_print (vam->ofp, &node);
5465 vat_json_free (&node);
5466
5467 vam->retval = ntohl (mp->retval);
5468 vam->result_ready = 1;
5469}
5470
Dave Barach3bbcfab2017-08-15 19:03:44 -04005471static int
Florin Corascea194d2017-10-02 00:18:51 -07005472api_app_namespace_add_del (vat_main_t * vam)
5473{
5474 vl_api_app_namespace_add_del_t *mp;
5475 unformat_input_t *i = vam->input;
5476 u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0;
5477 u32 sw_if_index, ip4_fib_id, ip6_fib_id;
5478 u64 secret;
5479 int ret;
5480
5481 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5482 {
5483 if (unformat (i, "id %_%v%_", &ns_id))
5484 ;
5485 else if (unformat (i, "secret %lu", &secret))
5486 secret_set = 1;
5487 else if (unformat (i, "sw_if_index %d", &sw_if_index))
5488 sw_if_index_set = 1;
5489 else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id))
5490 ;
5491 else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id))
5492 ;
5493 else
5494 break;
5495 }
5496 if (!ns_id || !secret_set || !sw_if_index_set)
5497 {
5498 errmsg ("namespace id, secret and sw_if_index must be set");
5499 return -99;
5500 }
5501 if (vec_len (ns_id) > 64)
5502 {
5503 errmsg ("namespace id too long");
5504 return -99;
5505 }
5506 M (APP_NAMESPACE_ADD_DEL, mp);
5507
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005508 vl_api_vec_to_api_string (ns_id, &mp->namespace_id);
Florin Coras9a9adb22017-10-26 08:16:59 -07005509 mp->secret = clib_host_to_net_u64 (secret);
Florin Corascea194d2017-10-02 00:18:51 -07005510 mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
5511 mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id);
5512 mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id);
5513 vec_free (ns_id);
5514 S (mp);
5515 W (ret);
5516 return ret;
5517}
5518
5519static int
Florin Coras90a63982017-12-19 04:50:01 -08005520api_sock_init_shm (vat_main_t * vam)
5521{
5522#if VPP_API_TEST_BUILTIN == 0
5523 unformat_input_t *i = vam->input;
5524 vl_api_shm_elem_config_t *config = 0;
5525 u64 size = 64 << 20;
5526 int rv;
5527
5528 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5529 {
5530 if (unformat (i, "size %U", unformat_memory_size, &size))
5531 ;
5532 else
5533 break;
5534 }
5535
Dave Barach78958722018-05-10 16:44:27 -04005536 /*
5537 * Canned custom ring allocator config.
5538 * Should probably parse all of this
5539 */
5540 vec_validate (config, 6);
Florin Coras90a63982017-12-19 04:50:01 -08005541 config[0].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08005542 config[0].size = 256;
Dave Barach78958722018-05-10 16:44:27 -04005543 config[0].count = 32;
5544
5545 config[1].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08005546 config[1].size = 1024;
Dave Barach78958722018-05-10 16:44:27 -04005547 config[1].count = 16;
5548
5549 config[2].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08005550 config[2].size = 4096;
Dave Barach78958722018-05-10 16:44:27 -04005551 config[2].count = 2;
5552
5553 config[3].type = VL_API_CLIENT_RING;
5554 config[3].size = 256;
5555 config[3].count = 32;
5556
5557 config[4].type = VL_API_CLIENT_RING;
5558 config[4].size = 1024;
5559 config[4].count = 16;
5560
5561 config[5].type = VL_API_CLIENT_RING;
5562 config[5].size = 4096;
5563 config[5].count = 2;
5564
5565 config[6].type = VL_API_QUEUE;
5566 config[6].count = 128;
5567 config[6].size = sizeof (uword);
5568
Tomasz Kulasek97dcf5b2019-01-31 18:26:32 +01005569 rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
Florin Coras90a63982017-12-19 04:50:01 -08005570 if (!rv)
5571 vam->client_index_invalid = 1;
5572 return rv;
5573#else
5574 return -99;
5575#endif
5576}
5577
Florin Coras6c36f532017-11-03 18:32:34 -07005578static void
5579vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp)
5580{
5581 vat_main_t *vam = &vat_main;
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005582 fib_prefix_t lcl, rmt;
Florin Coras6c36f532017-11-03 18:32:34 -07005583
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005584 ip_prefix_decode (&mp->lcl, &lcl);
5585 ip_prefix_decode (&mp->rmt, &rmt);
5586
5587 if (lcl.fp_proto == FIB_PROTOCOL_IP4)
Florin Coras6c36f532017-11-03 18:32:34 -07005588 {
Florin Corasc97a7392017-11-05 23:07:07 -08005589 print (vam->ofp,
5590 "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
Steven85dbac02017-11-07 16:29:53 -08005591 clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005592 mp->scope, format_ip4_address, &lcl.fp_addr.ip4, lcl.fp_len,
Steven85dbac02017-11-07 16:29:53 -08005593 clib_net_to_host_u16 (mp->lcl_port), format_ip4_address,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005594 &rmt.fp_addr.ip4, rmt.fp_len,
5595 clib_net_to_host_u16 (mp->rmt_port),
Steven85dbac02017-11-07 16:29:53 -08005596 clib_net_to_host_u32 (mp->action_index), mp->tag);
Florin Coras6c36f532017-11-03 18:32:34 -07005597 }
5598 else
5599 {
Florin Corasc97a7392017-11-05 23:07:07 -08005600 print (vam->ofp,
5601 "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s",
Steven85dbac02017-11-07 16:29:53 -08005602 clib_net_to_host_u32 (mp->appns_index), mp->transport_proto,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005603 mp->scope, format_ip6_address, &lcl.fp_addr.ip6, lcl.fp_len,
Steven85dbac02017-11-07 16:29:53 -08005604 clib_net_to_host_u16 (mp->lcl_port), format_ip6_address,
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005605 &rmt.fp_addr.ip6, rmt.fp_len,
5606 clib_net_to_host_u16 (mp->rmt_port),
Steven85dbac02017-11-07 16:29:53 -08005607 clib_net_to_host_u32 (mp->action_index), mp->tag);
Florin Coras6c36f532017-11-03 18:32:34 -07005608 }
5609}
5610
5611static void
5612vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t *
5613 mp)
5614{
5615 vat_main_t *vam = &vat_main;
5616 vat_json_node_t *node = NULL;
5617 struct in6_addr ip6;
5618 struct in_addr ip4;
5619
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005620 fib_prefix_t lcl, rmt;
5621
5622 ip_prefix_decode (&mp->lcl, &lcl);
5623 ip_prefix_decode (&mp->rmt, &rmt);
5624
Florin Coras6c36f532017-11-03 18:32:34 -07005625 if (VAT_JSON_ARRAY != vam->json_tree.type)
5626 {
5627 ASSERT (VAT_JSON_NONE == vam->json_tree.type);
5628 vat_json_init_array (&vam->json_tree);
5629 }
5630 node = vat_json_array_add (&vam->json_tree);
5631 vat_json_init_object (node);
5632
Florin Coras6c36f532017-11-03 18:32:34 -07005633 vat_json_object_add_uint (node, "appns_index",
5634 clib_net_to_host_u32 (mp->appns_index));
5635 vat_json_object_add_uint (node, "transport_proto", mp->transport_proto);
5636 vat_json_object_add_uint (node, "scope", mp->scope);
5637 vat_json_object_add_uint (node, "action_index",
5638 clib_net_to_host_u32 (mp->action_index));
5639 vat_json_object_add_uint (node, "lcl_port",
5640 clib_net_to_host_u16 (mp->lcl_port));
5641 vat_json_object_add_uint (node, "rmt_port",
5642 clib_net_to_host_u16 (mp->rmt_port));
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005643 vat_json_object_add_uint (node, "lcl_plen", lcl.fp_len);
5644 vat_json_object_add_uint (node, "rmt_plen", rmt.fp_len);
Florin Corasc97a7392017-11-05 23:07:07 -08005645 vat_json_object_add_string_copy (node, "tag", mp->tag);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005646 if (lcl.fp_proto == FIB_PROTOCOL_IP4)
Florin Coras6c36f532017-11-03 18:32:34 -07005647 {
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005648 clib_memcpy (&ip4, &lcl.fp_addr.ip4, sizeof (ip4));
Florin Coras6c36f532017-11-03 18:32:34 -07005649 vat_json_object_add_ip4 (node, "lcl_ip", ip4);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005650 clib_memcpy (&ip4, &rmt.fp_addr.ip4, sizeof (ip4));
Florin Coras6c36f532017-11-03 18:32:34 -07005651 vat_json_object_add_ip4 (node, "rmt_ip", ip4);
5652 }
5653 else
5654 {
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005655 clib_memcpy (&ip6, &lcl.fp_addr.ip6, sizeof (ip6));
Florin Coras6c36f532017-11-03 18:32:34 -07005656 vat_json_object_add_ip6 (node, "lcl_ip", ip6);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005657 clib_memcpy (&ip6, &rmt.fp_addr.ip6, sizeof (ip6));
Florin Coras6c36f532017-11-03 18:32:34 -07005658 vat_json_object_add_ip6 (node, "rmt_ip", ip6);
5659 }
5660}
5661
Florin Coras1c710452017-10-17 00:03:13 -07005662static int
5663api_session_rule_add_del (vat_main_t * vam)
5664{
5665 vl_api_session_rule_add_del_t *mp;
5666 unformat_input_t *i = vam->input;
5667 u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen;
5668 u32 appns_index = 0, scope = 0;
5669 ip4_address_t lcl_ip4, rmt_ip4;
5670 ip6_address_t lcl_ip6, rmt_ip6;
5671 u8 is_ip4 = 1, conn_set = 0;
Florin Corasc97a7392017-11-05 23:07:07 -08005672 u8 is_add = 1, *tag = 0;
Florin Coras1c710452017-10-17 00:03:13 -07005673 int ret;
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005674 fib_prefix_t lcl, rmt;
Florin Coras1c710452017-10-17 00:03:13 -07005675
5676 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5677 {
5678 if (unformat (i, "del"))
5679 is_add = 0;
5680 else if (unformat (i, "add"))
5681 ;
5682 else if (unformat (i, "proto tcp"))
5683 proto = 0;
5684 else if (unformat (i, "proto udp"))
5685 proto = 1;
5686 else if (unformat (i, "appns %d", &appns_index))
5687 ;
5688 else if (unformat (i, "scope %d", &scope))
5689 ;
Florin Corasc97a7392017-11-05 23:07:07 -08005690 else if (unformat (i, "tag %_%v%_", &tag))
5691 ;
Florin Coras1c710452017-10-17 00:03:13 -07005692 else
5693 if (unformat
5694 (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4,
5695 &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen,
5696 &rmt_port))
5697 {
5698 is_ip4 = 1;
5699 conn_set = 1;
5700 }
5701 else
5702 if (unformat
5703 (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6,
5704 &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen,
5705 &rmt_port))
5706 {
5707 is_ip4 = 0;
5708 conn_set = 1;
5709 }
5710 else if (unformat (i, "action %d", &action))
5711 ;
5712 else
5713 break;
5714 }
5715 if (proto == ~0 || !conn_set || action == ~0)
5716 {
5717 errmsg ("transport proto, connection and action must be set");
5718 return -99;
5719 }
5720
5721 if (scope > 3)
5722 {
5723 errmsg ("scope should be 0-3");
5724 return -99;
5725 }
5726
5727 M (SESSION_RULE_ADD_DEL, mp);
5728
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005729 clib_memset (&lcl, 0, sizeof (lcl));
5730 clib_memset (&rmt, 0, sizeof (rmt));
5731 if (is_ip4)
5732 {
5733 ip_set (&lcl.fp_addr, &lcl_ip4, 1);
5734 ip_set (&rmt.fp_addr, &rmt_ip4, 1);
5735 lcl.fp_len = lcl_plen;
5736 rmt.fp_len = rmt_plen;
5737 }
5738 else
5739 {
5740 ip_set (&lcl.fp_addr, &lcl_ip6, 0);
5741 ip_set (&rmt.fp_addr, &rmt_ip6, 0);
5742 lcl.fp_len = lcl_plen;
5743 rmt.fp_len = rmt_plen;
5744 }
5745
5746
5747 ip_prefix_encode (&lcl, &mp->lcl);
5748 ip_prefix_encode (&rmt, &mp->rmt);
Florin Corasc97a7392017-11-05 23:07:07 -08005749 mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port);
5750 mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port);
Jakub Grajciarb4e5e502020-01-31 09:35:29 +01005751 mp->transport_proto =
5752 proto ? TRANSPORT_PROTO_API_UDP : TRANSPORT_PROTO_API_TCP;
Florin Coras1c710452017-10-17 00:03:13 -07005753 mp->action_index = clib_host_to_net_u32 (action);
5754 mp->appns_index = clib_host_to_net_u32 (appns_index);
5755 mp->scope = scope;
5756 mp->is_add = is_add;
Florin Corasc97a7392017-11-05 23:07:07 -08005757 if (tag)
5758 {
5759 clib_memcpy (mp->tag, tag, vec_len (tag));
5760 vec_free (tag);
5761 }
Florin Coras1c710452017-10-17 00:03:13 -07005762
5763 S (mp);
5764 W (ret);
5765 return ret;
5766}
Dave Barach65457162017-10-10 17:53:14 -04005767
5768static int
Florin Coras6c36f532017-11-03 18:32:34 -07005769api_session_rules_dump (vat_main_t * vam)
5770{
5771 vl_api_session_rules_dump_t *mp;
5772 vl_api_control_ping_t *mp_ping;
5773 int ret;
5774
5775 if (!vam->json_output)
5776 {
5777 print (vam->ofp, "%=20s", "Session Rules");
5778 }
5779
5780 M (SESSION_RULES_DUMP, mp);
5781 /* send it... */
5782 S (mp);
5783
5784 /* Use a control ping for synchronization */
5785 MPING (CONTROL_PING, mp_ping);
5786 S (mp_ping);
5787
5788 /* Wait for a reply... */
5789 W (ret);
5790 return ret;
5791}
5792
5793static int
Florin Coras595992c2017-11-06 17:17:08 -08005794api_ip_container_proxy_add_del (vat_main_t * vam)
5795{
5796 vl_api_ip_container_proxy_add_del_t *mp;
5797 unformat_input_t *i = vam->input;
Neale Ranns37029302018-08-10 05:30:06 -07005798 u32 sw_if_index = ~0;
5799 vl_api_prefix_t pfx = { };
Florin Coras595992c2017-11-06 17:17:08 -08005800 u8 is_add = 1;
5801 int ret;
5802
5803 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
5804 {
5805 if (unformat (i, "del"))
5806 is_add = 0;
5807 else if (unformat (i, "add"))
5808 ;
Neale Ranns37029302018-08-10 05:30:06 -07005809 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
5810 ;
Florin Coras595992c2017-11-06 17:17:08 -08005811 else if (unformat (i, "sw_if_index %u", &sw_if_index))
5812 ;
5813 else
5814 break;
5815 }
Paul Vinciguerraab055082019-06-06 14:07:55 -04005816 if (sw_if_index == ~0 || pfx.len == 0)
Florin Coras595992c2017-11-06 17:17:08 -08005817 {
5818 errmsg ("address and sw_if_index must be set");
5819 return -99;
5820 }
5821
5822 M (IP_CONTAINER_PROXY_ADD_DEL, mp);
5823
Florin Coras595992c2017-11-06 17:17:08 -08005824 mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
Florin Coras595992c2017-11-06 17:17:08 -08005825 mp->is_add = is_add;
Neale Ranns37029302018-08-10 05:30:06 -07005826 clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
Florin Coras595992c2017-11-06 17:17:08 -08005827
5828 S (mp);
5829 W (ret);
5830 return ret;
5831}
5832
5833static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01005834q_or_quit (vat_main_t * vam)
5835{
Dave Barachdef19da2017-02-22 17:29:20 -05005836#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01005837 longjmp (vam->jump_buf, 1);
Dave Barachdef19da2017-02-22 17:29:20 -05005838#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01005839 return 0; /* not so much */
5840}
5841
5842static int
5843q (vat_main_t * vam)
5844{
5845 return q_or_quit (vam);
5846}
5847
5848static int
5849quit (vat_main_t * vam)
5850{
5851 return q_or_quit (vam);
5852}
5853
5854static int
5855comment (vat_main_t * vam)
5856{
5857 return 0;
5858}
5859
5860static int
Dave Barachb09f4d02019-07-15 16:00:03 -04005861elog_save (vat_main_t * vam)
5862{
5863#if VPP_API_TEST_BUILTIN == 0
5864 elog_main_t *em = &vam->elog_main;
5865 unformat_input_t *i = vam->input;
5866 char *file, *chroot_file;
5867 clib_error_t *error;
5868
5869 if (!unformat (i, "%s", &file))
5870 {
5871 errmsg ("expected file name, got `%U'", format_unformat_error, i);
5872 return 0;
5873 }
5874
5875 /* It's fairly hard to get "../oopsie" through unformat; just in case */
5876 if (strstr (file, "..") || index (file, '/'))
5877 {
5878 errmsg ("illegal characters in filename '%s'", file);
5879 return 0;
5880 }
5881
5882 chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
5883
5884 vec_free (file);
5885
5886 errmsg ("Saving %wd of %wd events to %s",
5887 elog_n_events_in_buffer (em),
5888 elog_buffer_capacity (em), chroot_file);
5889
5890 error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
5891 vec_free (chroot_file);
5892
5893 if (error)
5894 clib_error_report (error);
5895#else
5896 errmsg ("Use the vpp event loger...");
5897#endif
5898
5899 return 0;
5900}
5901
5902static int
5903elog_setup (vat_main_t * vam)
5904{
5905#if VPP_API_TEST_BUILTIN == 0
5906 elog_main_t *em = &vam->elog_main;
5907 unformat_input_t *i = vam->input;
5908 u32 nevents = 128 << 10;
5909
5910 (void) unformat (i, "nevents %d", &nevents);
5911
5912 elog_init (em, nevents);
5913 vl_api_set_elog_main (em);
5914 vl_api_set_elog_trace_api_messages (1);
5915 errmsg ("Event logger initialized with %u events", nevents);
5916#else
5917 errmsg ("Use the vpp event loger...");
5918#endif
5919 return 0;
5920}
5921
5922static int
5923elog_enable (vat_main_t * vam)
5924{
5925#if VPP_API_TEST_BUILTIN == 0
5926 elog_main_t *em = &vam->elog_main;
5927
5928 elog_enable_disable (em, 1 /* enable */ );
5929 vl_api_set_elog_trace_api_messages (1);
5930 errmsg ("Event logger enabled...");
5931#else
5932 errmsg ("Use the vpp event loger...");
5933#endif
5934 return 0;
5935}
5936
5937static int
5938elog_disable (vat_main_t * vam)
5939{
5940#if VPP_API_TEST_BUILTIN == 0
5941 elog_main_t *em = &vam->elog_main;
5942
5943 elog_enable_disable (em, 0 /* enable */ );
5944 vl_api_set_elog_trace_api_messages (1);
5945 errmsg ("Event logger disabled...");
5946#else
5947 errmsg ("Use the vpp event loger...");
5948#endif
5949 return 0;
5950}
5951
5952static int
Dave Barach048a4e52018-06-01 18:52:25 -04005953statseg (vat_main_t * vam)
5954{
5955 ssvm_private_t *ssvmp = &vam->stat_segment;
5956 ssvm_shared_header_t *shared_header = ssvmp->sh;
5957 vlib_counter_t **counters;
5958 u64 thread0_index1_packets;
5959 u64 thread0_index1_bytes;
5960 f64 vector_rate, input_rate;
5961 uword *p;
5962
5963 uword *counter_vector_by_name;
5964 if (vam->stat_segment_lockp == 0)
5965 {
5966 errmsg ("Stat segment not mapped...");
5967 return -99;
5968 }
5969
5970 /* look up "/if/rx for sw_if_index 1 as a test */
5971
5972 clib_spinlock_lock (vam->stat_segment_lockp);
5973
5974 counter_vector_by_name = (uword *) shared_header->opaque[1];
5975
5976 p = hash_get_mem (counter_vector_by_name, "/if/rx");
5977 if (p == 0)
5978 {
5979 clib_spinlock_unlock (vam->stat_segment_lockp);
5980 errmsg ("/if/tx not found?");
5981 return -99;
5982 }
5983
5984 /* Fish per-thread vector of combined counters from shared memory */
5985 counters = (vlib_counter_t **) p[0];
5986
5987 if (vec_len (counters[0]) < 2)
5988 {
5989 clib_spinlock_unlock (vam->stat_segment_lockp);
5990 errmsg ("/if/tx vector length %d", vec_len (counters[0]));
5991 return -99;
5992 }
5993
5994 /* Read thread 0 sw_if_index 1 counter */
5995 thread0_index1_packets = counters[0][1].packets;
5996 thread0_index1_bytes = counters[0][1].bytes;
5997
5998 p = hash_get_mem (counter_vector_by_name, "vector_rate");
5999 if (p == 0)
6000 {
6001 clib_spinlock_unlock (vam->stat_segment_lockp);
6002 errmsg ("vector_rate not found?");
6003 return -99;
6004 }
6005
6006 vector_rate = *(f64 *) (p[0]);
6007 p = hash_get_mem (counter_vector_by_name, "input_rate");
6008 if (p == 0)
6009 {
6010 clib_spinlock_unlock (vam->stat_segment_lockp);
6011 errmsg ("input_rate not found?");
6012 return -99;
6013 }
6014 input_rate = *(f64 *) (p[0]);
6015
6016 clib_spinlock_unlock (vam->stat_segment_lockp);
6017
6018 print (vam->ofp, "vector_rate %.2f input_rate %.2f",
6019 vector_rate, input_rate);
6020 print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
6021 thread0_index1_packets, thread0_index1_bytes);
6022
6023 return 0;
6024}
6025
6026static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01006027cmd_cmp (void *a1, void *a2)
6028{
6029 u8 **c1 = a1;
6030 u8 **c2 = a2;
6031
6032 return strcmp ((char *) (c1[0]), (char *) (c2[0]));
6033}
6034
6035static int
6036help (vat_main_t * vam)
6037{
6038 u8 **cmds = 0;
6039 u8 *name = 0;
6040 hash_pair_t *p;
6041 unformat_input_t *i = vam->input;
6042 int j;
6043
6044 if (unformat (i, "%s", &name))
6045 {
6046 uword *hs;
6047
6048 vec_add1 (name, 0);
6049
6050 hs = hash_get_mem (vam->help_by_name, name);
6051 if (hs)
6052 print (vam->ofp, "usage: %s %s", name, hs[0]);
6053 else
6054 print (vam->ofp, "No such msg / command '%s'", name);
6055 vec_free (name);
6056 return 0;
6057 }
6058
6059 print (vam->ofp, "Help is available for the following:");
6060
6061 /* *INDENT-OFF* */
6062 hash_foreach_pair (p, vam->function_by_name,
6063 ({
6064 vec_add1 (cmds, (u8 *)(p->key));
6065 }));
6066 /* *INDENT-ON* */
6067
6068 vec_sort_with_function (cmds, cmd_cmp);
6069
6070 for (j = 0; j < vec_len (cmds); j++)
6071 print (vam->ofp, "%s", cmds[j]);
6072
6073 vec_free (cmds);
6074 return 0;
6075}
6076
6077static int
6078set (vat_main_t * vam)
6079{
6080 u8 *name = 0, *value = 0;
6081 unformat_input_t *i = vam->input;
6082
6083 if (unformat (i, "%s", &name))
6084 {
6085 /* The input buffer is a vector, not a string. */
6086 value = vec_dup (i->buffer);
6087 vec_delete (value, i->index, 0);
6088 /* Almost certainly has a trailing newline */
6089 if (value[vec_len (value) - 1] == '\n')
6090 value[vec_len (value) - 1] = 0;
6091 /* Make sure it's a proper string, one way or the other */
6092 vec_add1 (value, 0);
6093 (void) clib_macro_set_value (&vam->macro_main,
6094 (char *) name, (char *) value);
6095 }
6096 else
6097 errmsg ("usage: set <name> <value>");
6098
6099 vec_free (name);
6100 vec_free (value);
6101 return 0;
6102}
6103
6104static int
6105unset (vat_main_t * vam)
6106{
6107 u8 *name = 0;
6108
6109 if (unformat (vam->input, "%s", &name))
6110 if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
6111 errmsg ("unset: %s wasn't set", name);
6112 vec_free (name);
6113 return 0;
6114}
6115
6116typedef struct
6117{
6118 u8 *name;
6119 u8 *value;
6120} macro_sort_t;
6121
6122
6123static int
6124macro_sort_cmp (void *a1, void *a2)
6125{
6126 macro_sort_t *s1 = a1;
6127 macro_sort_t *s2 = a2;
6128
6129 return strcmp ((char *) (s1->name), (char *) (s2->name));
6130}
6131
6132static int
6133dump_macro_table (vat_main_t * vam)
6134{
6135 macro_sort_t *sort_me = 0, *sm;
6136 int i;
6137 hash_pair_t *p;
6138
6139 /* *INDENT-OFF* */
6140 hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
6141 ({
6142 vec_add2 (sort_me, sm, 1);
6143 sm->name = (u8 *)(p->key);
6144 sm->value = (u8 *) (p->value[0]);
6145 }));
6146 /* *INDENT-ON* */
6147
6148 vec_sort_with_function (sort_me, macro_sort_cmp);
6149
6150 if (vec_len (sort_me))
6151 print (vam->ofp, "%-15s%s", "Name", "Value");
6152 else
6153 print (vam->ofp, "The macro table is empty...");
6154
6155 for (i = 0; i < vec_len (sort_me); i++)
6156 print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
6157 return 0;
6158}
6159
6160static int
6161dump_node_table (vat_main_t * vam)
6162{
6163 int i, j;
6164 vlib_node_t *node, *next_node;
6165
6166 if (vec_len (vam->graph_nodes) == 0)
6167 {
6168 print (vam->ofp, "Node table empty, issue get_node_graph...");
6169 return 0;
6170 }
6171
Dave Barach1ddbc012018-06-13 09:26:05 -04006172 for (i = 0; i < vec_len (vam->graph_nodes[0]); i++)
Damjan Marion7cd468a2016-12-19 23:05:39 +01006173 {
Dave Barach1ddbc012018-06-13 09:26:05 -04006174 node = vam->graph_nodes[0][i];
Damjan Marion7cd468a2016-12-19 23:05:39 +01006175 print (vam->ofp, "[%d] %s", i, node->name);
6176 for (j = 0; j < vec_len (node->next_nodes); j++)
6177 {
6178 if (node->next_nodes[j] != ~0)
6179 {
Dave Barach1ddbc012018-06-13 09:26:05 -04006180 next_node = vam->graph_nodes[0][node->next_nodes[j]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01006181 print (vam->ofp, " [%d] %s", j, next_node->name);
6182 }
6183 }
6184 }
6185 return 0;
6186}
6187
6188static int
6189value_sort_cmp (void *a1, void *a2)
6190{
6191 name_sort_t *n1 = a1;
6192 name_sort_t *n2 = a2;
6193
6194 if (n1->value < n2->value)
6195 return -1;
6196 if (n1->value > n2->value)
6197 return 1;
6198 return 0;
6199}
6200
6201
6202static int
6203dump_msg_api_table (vat_main_t * vam)
6204{
Dave Barach39d69112019-11-27 11:42:13 -05006205 api_main_t *am = vlibapi_get_main ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01006206 name_sort_t *nses = 0, *ns;
6207 hash_pair_t *hp;
6208 int i;
6209
6210 /* *INDENT-OFF* */
6211 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
6212 ({
6213 vec_add2 (nses, ns, 1);
6214 ns->name = (u8 *)(hp->key);
6215 ns->value = (u32) hp->value[0];
6216 }));
6217 /* *INDENT-ON* */
6218
6219 vec_sort_with_function (nses, value_sort_cmp);
6220
6221 for (i = 0; i < vec_len (nses); i++)
6222 print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
6223 vec_free (nses);
6224 return 0;
6225}
6226
6227static int
6228get_msg_id (vat_main_t * vam)
6229{
6230 u8 *name_and_crc;
6231 u32 message_index;
6232
6233 if (unformat (vam->input, "%s", &name_and_crc))
6234 {
Florin Corase86a8ed2018-01-05 03:20:25 -08006235 message_index = vl_msg_api_get_msg_index (name_and_crc);
Damjan Marion7cd468a2016-12-19 23:05:39 +01006236 if (message_index == ~0)
6237 {
6238 print (vam->ofp, " '%s' not found", name_and_crc);
6239 return 0;
6240 }
6241 print (vam->ofp, " '%s' has message index %d",
6242 name_and_crc, message_index);
6243 return 0;
6244 }
6245 errmsg ("name_and_crc required...");
6246 return 0;
6247}
6248
6249static int
6250search_node_table (vat_main_t * vam)
6251{
6252 unformat_input_t *line_input = vam->input;
6253 u8 *node_to_find;
6254 int j;
6255 vlib_node_t *node, *next_node;
6256 uword *p;
6257
6258 if (vam->graph_node_index_by_name == 0)
6259 {
6260 print (vam->ofp, "Node table empty, issue get_node_graph...");
6261 return 0;
6262 }
6263
6264 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
6265 {
6266 if (unformat (line_input, "%s", &node_to_find))
6267 {
6268 vec_add1 (node_to_find, 0);
6269 p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
6270 if (p == 0)
6271 {
6272 print (vam->ofp, "%s not found...", node_to_find);
6273 goto out;
6274 }
Dave Barach1ddbc012018-06-13 09:26:05 -04006275 node = vam->graph_nodes[0][p[0]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01006276 print (vam->ofp, "[%d] %s", p[0], node->name);
6277 for (j = 0; j < vec_len (node->next_nodes); j++)
6278 {
6279 if (node->next_nodes[j] != ~0)
6280 {
Dave Barach1ddbc012018-06-13 09:26:05 -04006281 next_node = vam->graph_nodes[0][node->next_nodes[j]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01006282 print (vam->ofp, " [%d] %s", j, next_node->name);
6283 }
6284 }
6285 }
6286
6287 else
6288 {
6289 clib_warning ("parse error '%U'", format_unformat_error,
6290 line_input);
6291 return -99;
6292 }
6293
6294 out:
6295 vec_free (node_to_find);
6296
6297 }
6298
6299 return 0;
6300}
6301
6302
6303static int
6304script (vat_main_t * vam)
6305{
6306#if (VPP_API_TEST_BUILTIN==0)
6307 u8 *s = 0;
6308 char *save_current_file;
6309 unformat_input_t save_input;
6310 jmp_buf save_jump_buf;
6311 u32 save_line_number;
6312
6313 FILE *new_fp, *save_ifp;
6314
6315 if (unformat (vam->input, "%s", &s))
6316 {
6317 new_fp = fopen ((char *) s, "r");
6318 if (new_fp == 0)
6319 {
6320 errmsg ("Couldn't open script file %s", s);
6321 vec_free (s);
6322 return -99;
6323 }
6324 }
6325 else
6326 {
6327 errmsg ("Missing script name");
6328 return -99;
6329 }
6330
6331 clib_memcpy (&save_input, &vam->input, sizeof (save_input));
6332 clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
6333 save_ifp = vam->ifp;
6334 save_line_number = vam->input_line_number;
6335 save_current_file = (char *) vam->current_file;
6336
6337 vam->input_line_number = 0;
6338 vam->ifp = new_fp;
6339 vam->current_file = s;
6340 do_one_file (vam);
6341
Sirshak Dasb0861822018-05-29 21:13:21 -05006342 clib_memcpy (&vam->input, &save_input, sizeof (save_input));
Damjan Marion7cd468a2016-12-19 23:05:39 +01006343 clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
6344 vam->ifp = save_ifp;
6345 vam->input_line_number = save_line_number;
6346 vam->current_file = (u8 *) save_current_file;
6347 vec_free (s);
6348
6349 return 0;
6350#else
6351 clib_warning ("use the exec command...");
6352 return -99;
6353#endif
6354}
6355
6356static int
6357echo (vat_main_t * vam)
6358{
6359 print (vam->ofp, "%v", vam->input->buffer);
6360 return 0;
6361}
6362
6363/* List of API message constructors, CLI names map to api_xxx */
6364#define foreach_vpe_api_msg \
Jon Loeligerc83c3b72017-02-23 13:57:35 -06006365_(create_loopback,"[mac <mac-addr>] [instance <instance>]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006366_(sw_interface_dump,"") \
6367_(sw_interface_set_flags, \
6368 "<intfc> | sw_if_index <id> admin-up | admin-down link-up | link down") \
6369_(sw_interface_add_del_address, \
6370 "<intfc> | sw_if_index <id> <ip4-address> | <ip6-address> [del] [del-all] ") \
Mohsin Kazmi54f7c512018-08-23 18:28:11 +02006371_(sw_interface_set_rx_placement, \
6372 "<intfc> | sw_if_index <id> [queue <id>] [worker <id> | main]") \
Mohsin Kazmif0b42f42018-09-10 18:11:00 +02006373_(sw_interface_rx_placement_dump, \
6374 "[<intfc> | sw_if_index <id>]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006375_(sw_interface_set_table, \
6376 "<intfc> | sw_if_index <id> vrf <table-id> [ipv6]") \
Neale Ranns28ab9cc2017-08-14 07:18:42 -07006377_(ip_table_add_del, \
John Loe166fd92018-09-13 14:08:59 -04006378 "table <n> [ipv6] [add | del]\n") \
Neale Ranns097fa662018-05-01 05:17:55 -07006379_(ip_route_add_del, \
John Lo22030432018-09-20 16:07:00 -04006380 "<addr>/<mask> via <<addr>|<intfc>|sw_if_index <id>|via-label <n>>\n" \
6381 "[table-id <n>] [<intfc> | sw_if_index <id>] [resolve-attempts <n>]\n"\
John Lo06fda9c2018-10-03 16:32:44 -04006382 "[weight <n>] [drop] [local] [classify <n>] [out-label <n>]\n" \
6383 "[multipath] [count <n>] [del]") \
Neale Ranns32e1c012016-11-22 17:07:28 +00006384_(ip_mroute_add_del, \
6385 "<src> <grp>/<mask> [table-id <n>]\n" \
6386 "[<intfc> | sw_if_index <id>] [local] [del]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006387_(sw_interface_set_unnumbered, \
6388 "<intfc> | sw_if_index <id> unnum_if_index <id> [del]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006389_(create_vlan_subif, "<intfc> | sw_if_index <id> vlan <n>") \
6390_(create_subif, "<intfc> | sw_if_index <id> sub_id <n>\n" \
6391 "[outer_vlan_id <n>][inner_vlan_id <n>]\n" \
6392 "[no_tags][one_tag][two_tags][dot1ad][exact_match][default_sub]\n" \
6393 "[outer_vlan_id_any][inner_vlan_id_any]") \
Neale Ranns9db6ada2019-11-08 12:42:31 +00006394_(ip_table_replace_begin, "table <n> [ipv6]") \
6395_(ip_table_flush, "table <n> [ipv6]") \
6396_(ip_table_replace_end, "table <n> [ipv6]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006397_(set_ip_flow_hash, \
6398 "vrf <n> [src] [dst] [sport] [dport] [proto] [reverse] [ipv6]") \
6399_(sw_interface_ip6_enable_disable, \
6400 "<intfc> | sw_if_index <id> enable | disable") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006401_(get_node_index, "node <node-name") \
6402_(add_node_next, "node <node-name> next <next-node-name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006403_(show_version, "") \
Mohsin Kazmi5d64c782018-09-11 20:27:09 +02006404_(show_threads, "") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006405_(interface_name_renumber, \
6406 "<intfc> | sw_if_index <nn> new_show_dev_instance <nn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006407_(ip_address_dump, "(ipv4 | ipv6) (<intfc> | sw_if_index <id>)") \
6408_(ip_dump, "ipv4 | ipv6") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006409_(delete_loopback,"sw_if_index <nn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006410_(want_interface_events, "enable|disable") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006411_(get_first_msg_id, "client <name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006412_(get_node_graph, " ") \
6413_(sw_interface_clear_stats,"<intfc> | sw_if_index <nn>") \
6414_(ioam_enable, "[trace] [pow] [ppc <encap|decap>]") \
6415_(ioam_disable, "") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006416_(get_next_index, "node-name <node-name> next-node-name <node-name>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006417_(ip_source_and_port_range_check_add_del, \
6418 "<ip-addr>/<mask> range <nn>-<nn> vrf <id>") \
6419_(ip_source_and_port_range_check_interface_add_del, \
6420 "<intf> | sw_if_index <nn> [tcp-out-vrf <id>] [tcp-in-vrf <id>]" \
6421 "[udp-in-vrf <id>] [udp-out-vrf <id>]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006422_(delete_subif,"<intfc> | sw_if_index <nn>") \
Neale Ranns097fa662018-05-01 05:17:55 -07006423_(ip_table_dump, "") \
6424_(ip_route_dump, "table-id [ip4|ip6]") \
6425_(ip_mtable_dump, "") \
6426_(ip_mroute_dump, "table-id [ip4|ip6]") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006427_(sw_interface_tag_add_del, "<intfc> | sw_if_index <nn> tag <text>" \
6428"[disable]") \
Matthew Smithe0792fd2019-07-12 11:48:24 -05006429_(sw_interface_add_del_mac_address, "<intfc> | sw_if_index <nn> " \
6430 "mac <mac-address> [del]") \
Ole Troand7231612018-06-07 10:17:57 +02006431_(hw_interface_set_mtu, "<intfc> | hw_if_index <nn> mtu <nn>") \
Pavel Kotucek6899a302017-06-08 08:46:10 +02006432_(sw_interface_get_table, "<intfc> | sw_if_index <id> [ipv6]") \
Florin Coras90a63982017-12-19 04:50:01 -08006433_(sock_init_shm, "size <nnn>") \
Florin Corascea194d2017-10-02 00:18:51 -07006434_(app_namespace_add_del, "[add] id <ns-id> secret <nn> sw_if_index <nn>")\
Florin Coras1c710452017-10-17 00:03:13 -07006435_(session_rule_add_del, "[add|del] proto <tcp/udp> <lcl-ip>/<plen> " \
6436 "<lcl-port> <rmt-ip>/<plen> <rmt-port> action <nn>") \
Florin Coras6c36f532017-11-03 18:32:34 -07006437_(session_rules_dump, "") \
Florin Coras595992c2017-11-06 17:17:08 -08006438_(ip_container_proxy_add_del, "[add|del] <address> <sw_if_index>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006439
6440/* List of command functions, CLI names map directly to functions */
6441#define foreach_cli_function \
6442_(comment, "usage: comment <ignore-rest-of-line>") \
6443_(dump_interface_table, "usage: dump_interface_table") \
6444_(dump_sub_interface_table, "usage: dump_sub_interface_table") \
6445_(dump_ipv4_table, "usage: dump_ipv4_table") \
6446_(dump_ipv6_table, "usage: dump_ipv6_table") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006447_(dump_macro_table, "usage: dump_macro_table ") \
6448_(dump_node_table, "usage: dump_node_table") \
6449_(dump_msg_api_table, "usage: dump_msg_api_table") \
Dave Barachb09f4d02019-07-15 16:00:03 -04006450_(elog_setup, "usage: elog_setup [nevents, default 128K]") \
6451_(elog_disable, "usage: elog_disable") \
6452_(elog_enable, "usage: elog_enable") \
6453_(elog_save, "usage: elog_save <filename>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006454_(get_msg_id, "usage: get_msg_id name_and_crc") \
6455_(echo, "usage: echo <message>") \
6456_(exec, "usage: exec <vpe-debug-CLI-command>") \
6457_(exec_inband, "usage: exec_inband <vpe-debug-CLI-command>") \
6458_(help, "usage: help") \
6459_(q, "usage: quit") \
6460_(quit, "usage: quit") \
6461_(search_node_table, "usage: search_node_table <name>...") \
6462_(set, "usage: set <variable-name> <value>") \
6463_(script, "usage: script <file-name>") \
Neale Ranns097fa662018-05-01 05:17:55 -07006464_(statseg, "usage: statseg") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01006465_(unset, "usage: unset <variable-name>")
Dave Barach048a4e52018-06-01 18:52:25 -04006466
Damjan Marion7cd468a2016-12-19 23:05:39 +01006467#define _(N,n) \
6468 static void vl_api_##n##_t_handler_uni \
6469 (vl_api_##n##_t * mp) \
6470 { \
6471 vat_main_t * vam = &vat_main; \
6472 if (vam->json_output) { \
6473 vl_api_##n##_t_handler_json(mp); \
6474 } else { \
6475 vl_api_##n##_t_handler(mp); \
6476 } \
6477 }
6478foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05006479#if VPP_API_TEST_BUILTIN == 0
6480foreach_standalone_reply_msg;
6481#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01006482#undef _
6483
6484void
6485vat_api_hookup (vat_main_t * vam)
6486{
6487#define _(N,n) \
6488 vl_msg_api_set_handlers(VL_API_##N, #n, \
6489 vl_api_##n##_t_handler_uni, \
6490 vl_noop_handler, \
6491 vl_api_##n##_t_endian, \
6492 vl_api_##n##_t_print, \
6493 sizeof(vl_api_##n##_t), 1);
6494 foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05006495#if VPP_API_TEST_BUILTIN == 0
6496 foreach_standalone_reply_msg;
6497#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01006498#undef _
6499
6500#if (VPP_API_TEST_BUILTIN==0)
6501 vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
Damjan Marion7cd468a2016-12-19 23:05:39 +01006502
6503 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
6504
6505 vam->function_by_name = hash_create_string (0, sizeof (uword));
6506
6507 vam->help_by_name = hash_create_string (0, sizeof (uword));
Dave Barach45e4f362017-03-07 12:52:31 -05006508#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01006509
6510 /* API messages we can send */
6511#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
6512 foreach_vpe_api_msg;
6513#undef _
6514
6515 /* Help strings */
6516#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
6517 foreach_vpe_api_msg;
6518#undef _
Damjan Marion7cd468a2016-12-19 23:05:39 +01006519
6520 /* CLI functions */
6521#define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
6522 foreach_cli_function;
6523#undef _
6524
6525 /* Help strings */
6526#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
6527 foreach_cli_function;
6528#undef _
6529}
6530
Dave Baracha1a093d2017-03-02 13:13:23 -05006531#if VPP_API_TEST_BUILTIN
6532static clib_error_t *
6533vat_api_hookup_shim (vlib_main_t * vm)
6534{
6535 vat_api_hookup (&vat_main);
6536 return 0;
6537}
6538
6539VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
6540#endif
6541
Damjan Marion7cd468a2016-12-19 23:05:39 +01006542/*
6543 * fd.io coding-style-patch-verification: ON
6544 *
6545 * Local Variables:
6546 * eval: (c-set-style "gnu")
6547 * End:
6548 */