blob: 33e5a275551b4b05494c4ea975bb726ba3851bea [file] [log] [blame]
Damjan Marion7cd468a2016-12-19 23:05:39 +01001/*
2 *------------------------------------------------------------------
3 * api_format.c
4 *
Dave Barachac0326f2020-07-14 18:30:05 -04005 * Copyright (c) 2014-2020 Cisco and/or its affiliates.
Damjan Marion7cd468a2016-12-19 23:05:39 +01006 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
20#include <vat/vat.h>
jialv01082ebeb2019-09-10 00:23:55 +080021#include <vlib/pci/pci.h>
Neale Ranns86327be2018-11-02 09:14:01 -070022#include <vpp/api/types.h>
Dave Barach59b25652017-09-10 15:04:27 -040023#include <vppinfra/socket.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010024#include <vlibapi/api.h>
25#include <vlibmemory/api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010026#include <vnet/ip/ip.h>
Neale Rannscbe25aa2019-09-30 10:53:31 +000027#include <vnet/ip-neighbor/ip_neighbor.h>
Neale Ranns37029302018-08-10 05:30:06 -070028#include <vnet/ip/ip_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010029#include <vnet/l2/l2_input.h>
Florin Corasb040f982020-10-20 14:59:43 -070030#include <vnet/udp/udp_local.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010031
32#include <vpp/api/vpe_msg_enum.h>
33#include <vnet/l2/l2_classify.h>
34#include <vnet/l2/l2_vtr.h>
Andrew Yourtchenko815d7d52018-02-07 11:37:02 +010035#include <vnet/classify/in_out_acl.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010036#include <vnet/classify/policer_classify.h>
37#include <vnet/classify/flow_classify.h>
38#include <vnet/mpls/mpls.h>
39#include <vnet/ipsec/ipsec.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010040#include <inttypes.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010041#include <vnet/ip/ip6_hop_by_hop.h>
42#include <vnet/ip/ip_source_and_port_range_check.h>
43#include <vnet/policer/xlate.h>
44#include <vnet/span/span.h>
45#include <vnet/policer/policer.h>
46#include <vnet/policer/police.h>
Neale Ranns32e1c012016-11-22 17:07:28 +000047#include <vnet/mfib/mfib_types.h>
Steven9cd2d7a2017-12-20 12:43:01 -080048#include <vnet/bonding/node.h>
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -070049#include <vnet/qos/qos_types.h>
Neale Ranns37029302018-08-10 05:30:06 -070050#include <vnet/ethernet/ethernet_types_api.h>
51#include <vnet/ip/ip_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010052#include "vat/json_format.h"
Neale Ranns86327be2018-11-02 09:14:01 -070053#include <vnet/ip/ip_types_api.h>
54#include <vnet/ethernet/ethernet_types_api.h>
Damjan Marion7cd468a2016-12-19 23:05:39 +010055
56#include <inttypes.h>
57#include <sys/stat.h>
58
59#define vl_typedefs /* define message structures */
60#include <vpp/api/vpe_all_api_h.h>
61#undef vl_typedefs
62
63/* declare message handlers for each api */
64
65#define vl_endianfun /* define message structures */
66#include <vpp/api/vpe_all_api_h.h>
67#undef vl_endianfun
68
69/* instantiate all the print functions we know about */
Dave Barachf35a0722019-06-12 16:50:38 -040070#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +010071#define vl_print(handle, ...)
Dave Barachf35a0722019-06-12 16:50:38 -040072#else
73#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
74#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +010075#define vl_printfun
76#include <vpp/api/vpe_all_api_h.h>
77#undef vl_printfun
78
Dave Barach2d6b2d62017-01-25 16:32:08 -050079#define __plugin_msg_base 0
Dave Barachfe6bdfd2017-01-20 19:50:09 -050080#include <vlibapi/vat_helper_macros.h>
81
Dave Barachb09f4d02019-07-15 16:00:03 -040082void vl_api_set_elog_main (elog_main_t * m);
83int vl_api_set_elog_trace_api_messages (int enable);
84
Dave Barach59b25652017-09-10 15:04:27 -040085#if VPP_API_TEST_BUILTIN == 0
86#include <netdb.h>
87
88u32
89vl (void *p)
90{
91 return vec_len (p);
92}
93
94int
95vat_socket_connect (vat_main_t * vam)
96{
Florin Coras66a10032018-12-21 16:23:09 -080097 int rv;
Dave Barach69eeadc2020-04-14 09:52:26 -040098 api_main_t *am = vlibapi_get_main ();
Florin Coras90a63982017-12-19 04:50:01 -080099 vam->socket_client_main = &socket_client_main;
Florin Coras66a10032018-12-21 16:23:09 -0800100 if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
101 "vpp_api_test",
102 0 /* default socket rx, tx buffer */ )))
103 return rv;
Dave Barach69eeadc2020-04-14 09:52:26 -0400104
Florin Coras66a10032018-12-21 16:23:09 -0800105 /* vpp expects the client index in network order */
106 vam->my_client_index = htonl (socket_client_main.client_index);
Dave Barach69eeadc2020-04-14 09:52:26 -0400107 am->my_client_index = vam->my_client_index;
Florin Coras66a10032018-12-21 16:23:09 -0800108 return 0;
Dave Barach59b25652017-09-10 15:04:27 -0400109}
110#else /* vpp built-in case, we don't do sockets... */
111int
112vat_socket_connect (vat_main_t * vam)
113{
114 return 0;
115}
116
Florin Coras90a63982017-12-19 04:50:01 -0800117int
118vl_socket_client_read (int wait)
Dave Barach59b25652017-09-10 15:04:27 -0400119{
Florin Coras90a63982017-12-19 04:50:01 -0800120 return -1;
Dave Barach59b25652017-09-10 15:04:27 -0400121};
Florin Coras90a63982017-12-19 04:50:01 -0800122
123int
124vl_socket_client_write ()
125{
126 return -1;
127};
128
129void *
130vl_socket_client_msg_alloc (int nbytes)
131{
132 return 0;
133}
Dave Barach59b25652017-09-10 15:04:27 -0400134#endif
135
136
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500137f64
138vat_time_now (vat_main_t * vam)
139{
140#if VPP_API_TEST_BUILTIN
141 return vlib_time_now (vam->vlib_main);
142#else
143 return clib_time_now (&vam->clib_time);
144#endif
145}
146
147void
148errmsg (char *fmt, ...)
149{
150 vat_main_t *vam = &vat_main;
151 va_list va;
152 u8 *s;
153
154 va_start (va, fmt);
155 s = va_format (0, fmt, &va);
156 va_end (va);
157
158 vec_add1 (s, 0);
159
160#if VPP_API_TEST_BUILTIN
161 vlib_cli_output (vam->vlib_main, (char *) s);
162#else
163 {
164 if (vam->ifp != stdin)
165 fformat (vam->ofp, "%s(%d): \n", vam->current_file,
166 vam->input_line_number);
Dave Barachb09f4d02019-07-15 16:00:03 -0400167 else
168 fformat (vam->ofp, "%s\n", (char *) s);
Dave Barachfe6bdfd2017-01-20 19:50:09 -0500169 fflush (vam->ofp);
170 }
171#endif
172
173 vec_free (s);
174}
175
Dave Barach4a3f69c2017-02-22 12:44:56 -0500176#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +0100177static uword
178api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
179{
180 vat_main_t *vam = va_arg (*args, vat_main_t *);
181 u32 *result = va_arg (*args, u32 *);
182 u8 *if_name;
183 uword *p;
184
185 if (!unformat (input, "%s", &if_name))
186 return 0;
187
188 p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name);
189 if (p == 0)
190 return 0;
191 *result = p[0];
192 return 1;
193}
194
Damjan Marion7cd468a2016-12-19 23:05:39 +0100195/* Parse an IP4 address %d.%d.%d.%d. */
196uword
197unformat_ip4_address (unformat_input_t * input, va_list * args)
198{
199 u8 *result = va_arg (*args, u8 *);
200 unsigned a[4];
201
202 if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
203 return 0;
204
205 if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
206 return 0;
207
208 result[0] = a[0];
209 result[1] = a[1];
210 result[2] = a[2];
211 result[3] = a[3];
212
213 return 1;
214}
215
216uword
217unformat_ethernet_address (unformat_input_t * input, va_list * args)
218{
219 u8 *result = va_arg (*args, u8 *);
220 u32 i, a[6];
221
222 if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
223 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
224 return 0;
225
226 /* Check range. */
227 for (i = 0; i < 6; i++)
228 if (a[i] >= (1 << 8))
229 return 0;
230
231 for (i = 0; i < 6; i++)
232 result[i] = a[i];
233
234 return 1;
235}
236
237/* Returns ethernet type as an int in host byte order. */
238uword
239unformat_ethernet_type_host_byte_order (unformat_input_t * input,
240 va_list * args)
241{
242 u16 *result = va_arg (*args, u16 *);
243 int type;
244
245 /* Numeric type. */
246 if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
247 {
248 if (type >= (1 << 16))
249 return 0;
250 *result = type;
251 return 1;
252 }
253 return 0;
254}
255
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100256/* Parse an IP46 address. */
257uword
258unformat_ip46_address (unformat_input_t * input, va_list * args)
259{
260 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
261 ip46_type_t type = va_arg (*args, ip46_type_t);
262 if ((type != IP46_TYPE_IP6) &&
263 unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
264 {
265 ip46_address_mask_ip4 (ip46);
266 return 1;
267 }
268 else if ((type != IP46_TYPE_IP4) &&
269 unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
270 {
271 return 1;
272 }
273 return 0;
274}
275
Damjan Marion7cd468a2016-12-19 23:05:39 +0100276/* Parse an IP6 address. */
277uword
278unformat_ip6_address (unformat_input_t * input, va_list * args)
279{
280 ip6_address_t *result = va_arg (*args, ip6_address_t *);
281 u16 hex_quads[8];
282 uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
283 uword c, n_colon, double_colon_index;
284
285 n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
286 double_colon_index = ARRAY_LEN (hex_quads);
287 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
288 {
289 hex_digit = 16;
290 if (c >= '0' && c <= '9')
291 hex_digit = c - '0';
292 else if (c >= 'a' && c <= 'f')
293 hex_digit = c + 10 - 'a';
294 else if (c >= 'A' && c <= 'F')
295 hex_digit = c + 10 - 'A';
296 else if (c == ':' && n_colon < 2)
297 n_colon++;
298 else
299 {
300 unformat_put_input (input);
301 break;
302 }
303
304 /* Too many hex quads. */
305 if (n_hex_quads >= ARRAY_LEN (hex_quads))
306 return 0;
307
308 if (hex_digit < 16)
309 {
310 hex_quad = (hex_quad << 4) | hex_digit;
311
312 /* Hex quad must fit in 16 bits. */
313 if (n_hex_digits >= 4)
314 return 0;
315
316 n_colon = 0;
317 n_hex_digits++;
318 }
319
320 /* Save position of :: */
321 if (n_colon == 2)
322 {
323 /* More than one :: ? */
324 if (double_colon_index < ARRAY_LEN (hex_quads))
325 return 0;
326 double_colon_index = n_hex_quads;
327 }
328
329 if (n_colon > 0 && n_hex_digits > 0)
330 {
331 hex_quads[n_hex_quads++] = hex_quad;
332 hex_quad = 0;
333 n_hex_digits = 0;
334 }
335 }
336
337 if (n_hex_digits > 0)
338 hex_quads[n_hex_quads++] = hex_quad;
339
340 {
341 word i;
342
343 /* Expand :: to appropriate number of zero hex quads. */
344 if (double_colon_index < ARRAY_LEN (hex_quads))
345 {
346 word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
347
348 for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
349 hex_quads[n_zero + i] = hex_quads[i];
350
351 for (i = 0; i < n_zero; i++)
352 hex_quads[double_colon_index + i] = 0;
353
354 n_hex_quads = ARRAY_LEN (hex_quads);
355 }
356
357 /* Too few hex quads given. */
358 if (n_hex_quads < ARRAY_LEN (hex_quads))
359 return 0;
360
361 for (i = 0; i < ARRAY_LEN (hex_quads); i++)
362 result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
363
364 return 1;
365 }
366}
367
368uword
369unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
370{
371 u32 *r = va_arg (*args, u32 *);
372
373 if (0);
374#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
375 foreach_ipsec_policy_action
376#undef _
377 else
378 return 0;
379 return 1;
380}
381
Damjan Marion7cd468a2016-12-19 23:05:39 +0100382u8 *
383format_ipsec_crypto_alg (u8 * s, va_list * args)
384{
385 u32 i = va_arg (*args, u32);
386 u8 *t = 0;
387
388 switch (i)
389 {
390#define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
391 foreach_ipsec_crypto_alg
392#undef _
393 default:
394 return format (s, "unknown");
395 }
396 return format (s, "%s", t);
397}
398
Damjan Marion7cd468a2016-12-19 23:05:39 +0100399u8 *
400format_ipsec_integ_alg (u8 * s, va_list * args)
401{
402 u32 i = va_arg (*args, u32);
403 u8 *t = 0;
404
405 switch (i)
406 {
407#define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
408 foreach_ipsec_integ_alg
409#undef _
410 default:
411 return format (s, "unknown");
412 }
413 return format (s, "%s", t);
414}
415
Dave Barach4a3f69c2017-02-22 12:44:56 -0500416#else /* VPP_API_TEST_BUILTIN == 1 */
417static uword
418api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
419{
Benoît Ganne49ee6842019-04-30 11:50:46 +0200420 vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500421 vnet_main_t *vnm = vnet_get_main ();
422 u32 *result = va_arg (*args, u32 *);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500423
eyal bariaf86a482018-04-17 11:20:27 +0300424 return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
Dave Barach4a3f69c2017-02-22 12:44:56 -0500425}
eyal bariaf86a482018-04-17 11:20:27 +0300426
Damjan Marion7cd468a2016-12-19 23:05:39 +0100427#endif /* VPP_API_TEST_BUILTIN */
428
Benoît Ganne49ee6842019-04-30 11:50:46 +0200429#if (VPP_API_TEST_BUILTIN==0)
430
Neale Ranns32e1c012016-11-22 17:07:28 +0000431static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
432static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
433static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
434static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
435
436uword
437unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
438{
439 mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
440 mfib_itf_attribute_t attr;
441
442 old = *iflags;
443 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
444 {
445 if (unformat (input, mfib_itf_flag_long_names[attr]))
446 *iflags |= (1 << attr);
447 }
448 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
449 {
450 if (unformat (input, mfib_itf_flag_names[attr]))
451 *iflags |= (1 << attr);
452 }
453
454 return (old == *iflags ? 0 : 1);
455}
456
457uword
458unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
459{
460 mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
461 mfib_entry_attribute_t attr;
462
463 old = *eflags;
464 FOR_EACH_MFIB_ATTRIBUTE (attr)
465 {
466 if (unformat (input, mfib_flag_long_names[attr]))
467 *eflags |= (1 << attr);
468 }
469 FOR_EACH_MFIB_ATTRIBUTE (attr)
470 {
471 if (unformat (input, mfib_flag_names[attr]))
472 *eflags |= (1 << attr);
473 }
474
475 return (old == *eflags ? 0 : 1);
476}
477
Damjan Marion7cd468a2016-12-19 23:05:39 +0100478u8 *
479format_ip4_address (u8 * s, va_list * args)
480{
481 u8 *a = va_arg (*args, u8 *);
482 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
483}
484
485u8 *
486format_ip6_address (u8 * s, va_list * args)
487{
488 ip6_address_t *a = va_arg (*args, ip6_address_t *);
489 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
490
491 i_max_n_zero = ARRAY_LEN (a->as_u16);
492 max_n_zeros = 0;
493 i_first_zero = i_max_n_zero;
494 n_zeros = 0;
495 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
496 {
497 u32 is_zero = a->as_u16[i] == 0;
498 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
499 {
500 i_first_zero = i;
501 n_zeros = 0;
502 }
503 n_zeros += is_zero;
504 if ((!is_zero && n_zeros > max_n_zeros)
505 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
506 {
507 i_max_n_zero = i_first_zero;
508 max_n_zeros = n_zeros;
509 i_first_zero = ARRAY_LEN (a->as_u16);
510 n_zeros = 0;
511 }
512 }
513
514 last_double_colon = 0;
515 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
516 {
517 if (i == i_max_n_zero && max_n_zeros > 1)
518 {
519 s = format (s, "::");
520 i += max_n_zeros - 1;
521 last_double_colon = 1;
522 }
523 else
524 {
525 s = format (s, "%s%x",
526 (last_double_colon || i == 0) ? "" : ":",
527 clib_net_to_host_u16 (a->as_u16[i]));
528 last_double_colon = 0;
529 }
530 }
531
532 return s;
533}
534
535/* Format an IP46 address. */
536u8 *
537format_ip46_address (u8 * s, va_list * args)
538{
539 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
540 ip46_type_t type = va_arg (*args, ip46_type_t);
541 int is_ip4 = 1;
542
543 switch (type)
544 {
545 case IP46_TYPE_ANY:
546 is_ip4 = ip46_address_is_ip4 (ip46);
547 break;
548 case IP46_TYPE_IP4:
549 is_ip4 = 1;
550 break;
551 case IP46_TYPE_IP6:
552 is_ip4 = 0;
553 break;
554 }
555
556 return is_ip4 ?
557 format (s, "%U", format_ip4_address, &ip46->ip4) :
558 format (s, "%U", format_ip6_address, &ip46->ip6);
559}
560
561u8 *
562format_ethernet_address (u8 * s, va_list * args)
563{
564 u8 *a = va_arg (*args, u8 *);
565
566 return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
567 a[0], a[1], a[2], a[3], a[4], a[5]);
568}
569#endif
570
Jakub Grajciar23a386b2020-02-26 11:01:43 +0100571void
572ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
573{
574 if (is_ip4)
575 dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
576 else
577 clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
578 sizeof (ip6_address_t));
579}
580
Neale Ranns097fa662018-05-01 05:17:55 -0700581
Damjan Marion7cd468a2016-12-19 23:05:39 +0100582static void vl_api_show_version_reply_t_handler
583 (vl_api_show_version_reply_t * mp)
584{
585 vat_main_t *vam = &vat_main;
586 i32 retval = ntohl (mp->retval);
587
588 if (retval >= 0)
589 {
Ole Troane5ff5a32019-08-23 22:55:18 +0200590 errmsg (" program: %s", mp->program);
591 errmsg (" version: %s", mp->version);
592 errmsg (" build date: %s", mp->build_date);
593 errmsg ("build directory: %s", mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100594 }
595 vam->retval = retval;
596 vam->result_ready = 1;
597}
598
599static void vl_api_show_version_reply_t_handler_json
600 (vl_api_show_version_reply_t * mp)
601{
602 vat_main_t *vam = &vat_main;
603 vat_json_node_t node;
604
605 vat_json_init_object (&node);
606 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
Ole Troane5ff5a32019-08-23 22:55:18 +0200607 vat_json_object_add_string_copy (&node, "program", mp->program);
608 vat_json_object_add_string_copy (&node, "version", mp->version);
609 vat_json_object_add_string_copy (&node, "build_date", mp->build_date);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100610 vat_json_object_add_string_copy (&node, "build_directory",
Ole Troane5ff5a32019-08-23 22:55:18 +0200611 mp->build_directory);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100612
613 vat_json_print (vam->ofp, &node);
614 vat_json_free (&node);
615
616 vam->retval = ntohl (mp->retval);
617 vam->result_ready = 1;
618}
619
Ole Troan01384fe2017-05-12 11:55:35 +0200620#define vl_api_bridge_domain_details_t_endian vl_noop_handler
621#define vl_api_bridge_domain_details_t_print vl_noop_handler
622
Damjan Marion7cd468a2016-12-19 23:05:39 +0100623static void vl_api_get_first_msg_id_reply_t_handler
624 (vl_api_get_first_msg_id_reply_t * mp)
625{
626 vat_main_t *vam = &vat_main;
627 i32 retval = ntohl (mp->retval);
628
629 if (vam->async_mode)
630 {
631 vam->async_errors += (retval < 0);
632 }
633 else
634 {
635 vam->retval = retval;
636 vam->result_ready = 1;
637 }
638 if (retval >= 0)
639 {
640 errmsg ("first message id %d", ntohs (mp->first_msg_id));
641 }
642}
643
644static void vl_api_get_first_msg_id_reply_t_handler_json
645 (vl_api_get_first_msg_id_reply_t * mp)
646{
647 vat_main_t *vam = &vat_main;
648 vat_json_node_t node;
649
650 vat_json_init_object (&node);
651 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
652 vat_json_object_add_uint (&node, "first_msg_id",
653 (uint) ntohs (mp->first_msg_id));
654
655 vat_json_print (vam->ofp, &node);
656 vat_json_free (&node);
657
658 vam->retval = ntohl (mp->retval);
659 vam->result_ready = 1;
660}
661
Damjan Marion7cd468a2016-12-19 23:05:39 +0100662/* Format hex dump. */
663u8 *
664format_hex_bytes (u8 * s, va_list * va)
665{
666 u8 *bytes = va_arg (*va, u8 *);
667 int n_bytes = va_arg (*va, int);
668 uword i;
669
670 /* Print short or long form depending on byte count. */
671 uword short_form = n_bytes <= 32;
Christophe Fontained3c008d2017-10-02 18:10:54 +0200672 u32 indent = format_get_indent (s);
Damjan Marion7cd468a2016-12-19 23:05:39 +0100673
674 if (n_bytes == 0)
675 return s;
676
677 for (i = 0; i < n_bytes; i++)
678 {
679 if (!short_form && (i % 32) == 0)
680 s = format (s, "%08x: ", i);
681 s = format (s, "%02x", bytes[i]);
682 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
683 s = format (s, "\n%U", format_white_space, indent);
684 }
685
686 return s;
687}
688
Damjan Marion7cd468a2016-12-19 23:05:39 +0100689/*
690 * Generate boilerplate reply handlers, which
691 * dig the return value out of the xxx_reply_t API message,
692 * stick it into vam->retval, and set vam->result_ready
693 *
694 * Could also do this by pointing N message decode slots at
695 * a single function, but that could break in subtle ways.
696 */
697
Filip Tehlar0046e972021-06-26 22:12:08 +0000698#define foreach_standard_reply_retval_handler
Damjan Marion7cd468a2016-12-19 23:05:39 +0100699
700#define _(n) \
701 static void vl_api_##n##_t_handler \
702 (vl_api_##n##_t * mp) \
703 { \
704 vat_main_t * vam = &vat_main; \
705 i32 retval = ntohl(mp->retval); \
706 if (vam->async_mode) { \
707 vam->async_errors += (retval < 0); \
708 } else { \
709 vam->retval = retval; \
710 vam->result_ready = 1; \
711 } \
712 }
713foreach_standard_reply_retval_handler;
714#undef _
715
716#define _(n) \
717 static void vl_api_##n##_t_handler_json \
718 (vl_api_##n##_t * mp) \
719 { \
720 vat_main_t * vam = &vat_main; \
721 vat_json_node_t node; \
722 vat_json_init_object(&node); \
723 vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
724 vat_json_print(vam->ofp, &node); \
725 vam->retval = ntohl(mp->retval); \
726 vam->result_ready = 1; \
727 }
728foreach_standard_reply_retval_handler;
729#undef _
730
731/*
732 * Table of message reply handlers, must include boilerplate handlers
733 * we just generated
734 */
735
Filip Tehlar0577ff12021-06-27 00:18:57 +0000736#define foreach_vpe_api_reply_msg \
737 _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
Filip Tehlar0577ff12021-06-27 00:18:57 +0000738 _ (SHOW_VERSION_REPLY, show_version_reply) \
Damjan Marion7cd468a2016-12-19 23:05:39 +0100739
Dave Baracha1a093d2017-03-02 13:13:23 -0500740#define foreach_standalone_reply_msg \
Dave Baracha1a093d2017-03-02 13:13:23 -0500741
Damjan Marion7cd468a2016-12-19 23:05:39 +0100742typedef struct
743{
744 u8 *name;
745 u32 value;
746} name_sort_t;
747
Damjan Marion7cd468a2016-12-19 23:05:39 +0100748#define STR_VTR_OP_CASE(op) \
749 case L2_VTR_ ## op: \
750 return "" # op;
751
Damjan Marion7cd468a2016-12-19 23:05:39 +0100752int
Filip Tehlar0577ff12021-06-27 00:18:57 +0000753api_sw_interface_dump (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100754{
Filip Tehlar0577ff12021-06-27 00:18:57 +0000755 return 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100756}
757
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100758uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000759unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100760{
jialv01082ebeb2019-09-10 00:23:55 +0800761 vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
Mohsin Kazmi03ae24b2019-01-18 11:50:00 +0100762 u32 x[4];
763
764 if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
765 return 0;
766
767 addr->domain = x[0];
768 addr->bus = x[1];
769 addr->slot = x[2];
770 addr->function = x[3];
771
772 return 1;
773}
774
Neale Ranns097fa662018-05-01 05:17:55 -0700775uword
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000776unformat_fib_path (unformat_input_t *input, va_list *args)
Neale Ranns097fa662018-05-01 05:17:55 -0700777{
778 vat_main_t *vam = va_arg (*args, vat_main_t *);
779 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
780 u32 weight, preference;
781 mpls_label_t out_label;
782
783 clib_memset (path, 0, sizeof (*path));
784 path->weight = 1;
785 path->sw_if_index = ~0;
786 path->rpf_id = ~0;
787 path->n_labels = 0;
788
789 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
790 {
Filip Tehlar5a9d2a12021-06-22 21:20:29 +0000791 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
792 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
793 &path->sw_if_index))
Neale Ranns097fa662018-05-01 05:17:55 -0700794 {
795 path->proto = FIB_API_PATH_NH_PROTO_IP4;
796 }
797 else if (unformat (input, "%U %U",
798 unformat_vl_api_ip6_address,
799 &path->nh.address.ip6,
800 api_unformat_sw_if_index, vam, &path->sw_if_index))
801 {
802 path->proto = FIB_API_PATH_NH_PROTO_IP6;
803 }
804 else if (unformat (input, "weight %u", &weight))
805 {
806 path->weight = weight;
807 }
808 else if (unformat (input, "preference %u", &preference))
809 {
810 path->preference = preference;
811 }
812 else if (unformat (input, "%U next-hop-table %d",
813 unformat_vl_api_ip4_address,
814 &path->nh.address.ip4, &path->table_id))
815 {
816 path->proto = FIB_API_PATH_NH_PROTO_IP4;
817 }
818 else if (unformat (input, "%U next-hop-table %d",
819 unformat_vl_api_ip6_address,
820 &path->nh.address.ip6, &path->table_id))
821 {
822 path->proto = FIB_API_PATH_NH_PROTO_IP6;
823 }
824 else if (unformat (input, "%U",
825 unformat_vl_api_ip4_address, &path->nh.address.ip4))
826 {
827 /*
828 * the recursive next-hops are by default in the default table
829 */
830 path->table_id = 0;
831 path->sw_if_index = ~0;
832 path->proto = FIB_API_PATH_NH_PROTO_IP4;
833 }
834 else if (unformat (input, "%U",
835 unformat_vl_api_ip6_address, &path->nh.address.ip6))
836 {
837 /*
838 * the recursive next-hops are by default in the default table
839 */
840 path->table_id = 0;
841 path->sw_if_index = ~0;
842 path->proto = FIB_API_PATH_NH_PROTO_IP6;
843 }
844 else if (unformat (input, "resolve-via-host"))
845 {
846 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
847 }
848 else if (unformat (input, "resolve-via-attached"))
849 {
850 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
851 }
852 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
853 {
854 path->type = FIB_API_PATH_TYPE_LOCAL;
855 path->sw_if_index = ~0;
856 path->proto = FIB_API_PATH_NH_PROTO_IP4;
857 }
858 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
859 {
860 path->type = FIB_API_PATH_TYPE_LOCAL;
861 path->sw_if_index = ~0;
862 path->proto = FIB_API_PATH_NH_PROTO_IP6;
863 }
864 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
865 ;
866 else if (unformat (input, "via-label %d", &path->nh.via_label))
867 {
868 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
869 path->sw_if_index = ~0;
870 }
871 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
872 {
873 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
874 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
875 }
876 else if (unformat (input, "local"))
877 {
878 path->type = FIB_API_PATH_TYPE_LOCAL;
879 }
880 else if (unformat (input, "out-labels"))
881 {
882 while (unformat (input, "%d", &out_label))
883 {
884 path->label_stack[path->n_labels].label = out_label;
885 path->label_stack[path->n_labels].is_uniform = 0;
886 path->label_stack[path->n_labels].ttl = 64;
887 path->n_labels++;
888 }
889 }
890 else if (unformat (input, "via"))
891 {
892 /* new path, back up and return */
893 unformat_put_input (input);
894 unformat_put_input (input);
895 unformat_put_input (input);
896 unformat_put_input (input);
897 break;
898 }
899 else
900 {
901 return (0);
902 }
903 }
904
905 path->proto = ntohl (path->proto);
906 path->type = ntohl (path->type);
907 path->flags = ntohl (path->flags);
908 path->table_id = ntohl (path->table_id);
909 path->sw_if_index = ntohl (path->sw_if_index);
910
911 return (1);
912}
913
Damjan Marion7cd468a2016-12-19 23:05:39 +0100914#define foreach_create_subif_bit \
915_(no_tags) \
916_(one_tag) \
917_(two_tags) \
918_(dot1ad) \
919_(exact_match) \
920_(default_sub) \
921_(outer_vlan_id_any) \
922_(inner_vlan_id_any)
923
Jakub Grajciar053204a2019-03-18 13:17:53 +0100924#define foreach_create_subif_flag \
925_(0, "no_tags") \
926_(1, "one_tag") \
927_(2, "two_tags") \
928_(3, "dot1ad") \
929_(4, "exact_match") \
930_(5, "default_sub") \
931_(6, "outer_vlan_id_any") \
932_(7, "inner_vlan_id_any")
933
Pablo Camarillofb380952016-12-07 18:34:18 +0100934
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000935#define foreach_tcp_proto_field \
936 _ (src_port) \
937 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100938
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000939#define foreach_udp_proto_field \
940 _ (src_port) \
941 _ (dst_port)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100942
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000943#define foreach_ip4_proto_field \
944 _ (src_address) \
945 _ (dst_address) \
946 _ (tos) \
947 _ (length) \
948 _ (fragment_id) \
949 _ (ttl) \
950 _ (protocol) \
951 _ (checksum)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100952
Dave Barach4a3f69c2017-02-22 12:44:56 -0500953typedef struct
954{
955 u16 src_port, dst_port;
956} tcpudp_header_t;
957
958#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +0100959uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000960unformat_tcp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +0100961{
962 u8 **maskp = va_arg (*args, u8 **);
963 u8 *mask = 0;
964 u8 found_something = 0;
965 tcp_header_t *tcp;
966
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000967#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100968 foreach_tcp_proto_field;
969#undef _
970
971 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
972 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000973 if (0)
974 ;
975#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100976 foreach_tcp_proto_field
977#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000978 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +0100979 }
980
981#define _(a) found_something += a;
982 foreach_tcp_proto_field;
983#undef _
984
985 if (found_something == 0)
986 return 0;
987
988 vec_validate (mask, sizeof (*tcp) - 1);
989
990 tcp = (tcp_header_t *) mask;
991
Filip Tehlar5ff59a12021-06-23 14:38:38 +0000992#define _(a) \
993 if (a) \
994 clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +0100995 foreach_tcp_proto_field;
996#undef _
997
998 *maskp = mask;
999 return 1;
1000}
1001
1002uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001003unformat_udp_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001004{
1005 u8 **maskp = va_arg (*args, u8 **);
1006 u8 *mask = 0;
1007 u8 found_something = 0;
1008 udp_header_t *udp;
1009
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001010#define _(a) u8 a = 0;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001011 foreach_udp_proto_field;
1012#undef _
1013
1014 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1015 {
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001016 if (0)
1017 ;
1018#define _(a) else if (unformat (input, #a)) a = 1;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001019 foreach_udp_proto_field
1020#undef _
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001021 else break;
Damjan Marion7cd468a2016-12-19 23:05:39 +01001022 }
1023
1024#define _(a) found_something += a;
1025 foreach_udp_proto_field;
1026#undef _
1027
1028 if (found_something == 0)
1029 return 0;
1030
1031 vec_validate (mask, sizeof (*udp) - 1);
1032
1033 udp = (udp_header_t *) mask;
1034
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001035#define _(a) \
1036 if (a) \
1037 clib_memset (&udp->a, 0xff, sizeof (udp->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001038 foreach_udp_proto_field;
1039#undef _
1040
1041 *maskp = mask;
1042 return 1;
1043}
1044
Damjan Marion7cd468a2016-12-19 23:05:39 +01001045uword
Filip Tehlar5ff59a12021-06-23 14:38:38 +00001046unformat_l4_mask (unformat_input_t *input, va_list *args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001047{
1048 u8 **maskp = va_arg (*args, u8 **);
1049 u16 src_port = 0, dst_port = 0;
1050 tcpudp_header_t *tcpudp;
1051
1052 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1053 {
1054 if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
1055 return 1;
1056 else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
1057 return 1;
1058 else if (unformat (input, "src_port"))
1059 src_port = 0xFFFF;
1060 else if (unformat (input, "dst_port"))
1061 dst_port = 0xFFFF;
1062 else
1063 return 0;
1064 }
1065
1066 if (!src_port && !dst_port)
1067 return 0;
1068
1069 u8 *mask = 0;
1070 vec_validate (mask, sizeof (tcpudp_header_t) - 1);
1071
1072 tcpudp = (tcpudp_header_t *) mask;
1073 tcpudp->src_port = src_port;
1074 tcpudp->dst_port = dst_port;
1075
1076 *maskp = mask;
1077
1078 return 1;
1079}
1080
1081uword
1082unformat_ip4_mask (unformat_input_t * input, va_list * args)
1083{
1084 u8 **maskp = va_arg (*args, u8 **);
1085 u8 *mask = 0;
1086 u8 found_something = 0;
1087 ip4_header_t *ip;
1088
1089#define _(a) u8 a=0;
1090 foreach_ip4_proto_field;
1091#undef _
1092 u8 version = 0;
1093 u8 hdr_length = 0;
1094
1095
1096 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1097 {
1098 if (unformat (input, "version"))
1099 version = 1;
1100 else if (unformat (input, "hdr_length"))
1101 hdr_length = 1;
1102 else if (unformat (input, "src"))
1103 src_address = 1;
1104 else if (unformat (input, "dst"))
1105 dst_address = 1;
1106 else if (unformat (input, "proto"))
1107 protocol = 1;
1108
1109#define _(a) else if (unformat (input, #a)) a=1;
1110 foreach_ip4_proto_field
1111#undef _
1112 else
1113 break;
1114 }
1115
1116#define _(a) found_something += a;
1117 foreach_ip4_proto_field;
1118#undef _
1119
1120 if (found_something == 0)
1121 return 0;
1122
1123 vec_validate (mask, sizeof (*ip) - 1);
1124
1125 ip = (ip4_header_t *) mask;
1126
Dave Barachb7b92992018-10-17 10:38:51 -04001127#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001128 foreach_ip4_proto_field;
1129#undef _
1130
1131 ip->ip_version_and_header_length = 0;
1132
1133 if (version)
1134 ip->ip_version_and_header_length |= 0xF0;
1135
1136 if (hdr_length)
1137 ip->ip_version_and_header_length |= 0x0F;
1138
1139 *maskp = mask;
1140 return 1;
1141}
1142
1143#define foreach_ip6_proto_field \
1144_(src_address) \
1145_(dst_address) \
1146_(payload_length) \
1147_(hop_limit) \
1148_(protocol)
1149
1150uword
1151unformat_ip6_mask (unformat_input_t * input, va_list * args)
1152{
1153 u8 **maskp = va_arg (*args, u8 **);
1154 u8 *mask = 0;
1155 u8 found_something = 0;
1156 ip6_header_t *ip;
1157 u32 ip_version_traffic_class_and_flow_label;
1158
1159#define _(a) u8 a=0;
1160 foreach_ip6_proto_field;
1161#undef _
1162 u8 version = 0;
1163 u8 traffic_class = 0;
1164 u8 flow_label = 0;
1165
1166 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1167 {
1168 if (unformat (input, "version"))
1169 version = 1;
1170 else if (unformat (input, "traffic-class"))
1171 traffic_class = 1;
1172 else if (unformat (input, "flow-label"))
1173 flow_label = 1;
1174 else if (unformat (input, "src"))
1175 src_address = 1;
1176 else if (unformat (input, "dst"))
1177 dst_address = 1;
1178 else if (unformat (input, "proto"))
1179 protocol = 1;
1180
1181#define _(a) else if (unformat (input, #a)) a=1;
1182 foreach_ip6_proto_field
1183#undef _
1184 else
1185 break;
1186 }
1187
1188#define _(a) found_something += a;
1189 foreach_ip6_proto_field;
1190#undef _
1191
1192 if (found_something == 0)
1193 return 0;
1194
1195 vec_validate (mask, sizeof (*ip) - 1);
1196
1197 ip = (ip6_header_t *) mask;
1198
Dave Barachb7b92992018-10-17 10:38:51 -04001199#define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
Damjan Marion7cd468a2016-12-19 23:05:39 +01001200 foreach_ip6_proto_field;
1201#undef _
1202
1203 ip_version_traffic_class_and_flow_label = 0;
1204
1205 if (version)
1206 ip_version_traffic_class_and_flow_label |= 0xF0000000;
1207
1208 if (traffic_class)
1209 ip_version_traffic_class_and_flow_label |= 0x0FF00000;
1210
1211 if (flow_label)
1212 ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
1213
1214 ip->ip_version_traffic_class_and_flow_label =
1215 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1216
1217 *maskp = mask;
1218 return 1;
1219}
1220
1221uword
1222unformat_l3_mask (unformat_input_t * input, va_list * args)
1223{
1224 u8 **maskp = va_arg (*args, u8 **);
1225
1226 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1227 {
1228 if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
1229 return 1;
1230 else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
1231 return 1;
1232 else
1233 break;
1234 }
1235 return 0;
1236}
1237
1238uword
1239unformat_l2_mask (unformat_input_t * input, va_list * args)
1240{
1241 u8 **maskp = va_arg (*args, u8 **);
1242 u8 *mask = 0;
1243 u8 src = 0;
1244 u8 dst = 0;
1245 u8 proto = 0;
1246 u8 tag1 = 0;
1247 u8 tag2 = 0;
1248 u8 ignore_tag1 = 0;
1249 u8 ignore_tag2 = 0;
1250 u8 cos1 = 0;
1251 u8 cos2 = 0;
1252 u8 dot1q = 0;
1253 u8 dot1ad = 0;
1254 int len = 14;
1255
1256 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1257 {
1258 if (unformat (input, "src"))
1259 src = 1;
1260 else if (unformat (input, "dst"))
1261 dst = 1;
1262 else if (unformat (input, "proto"))
1263 proto = 1;
1264 else if (unformat (input, "tag1"))
1265 tag1 = 1;
1266 else if (unformat (input, "tag2"))
1267 tag2 = 1;
1268 else if (unformat (input, "ignore-tag1"))
1269 ignore_tag1 = 1;
1270 else if (unformat (input, "ignore-tag2"))
1271 ignore_tag2 = 1;
1272 else if (unformat (input, "cos1"))
1273 cos1 = 1;
1274 else if (unformat (input, "cos2"))
1275 cos2 = 1;
1276 else if (unformat (input, "dot1q"))
1277 dot1q = 1;
1278 else if (unformat (input, "dot1ad"))
1279 dot1ad = 1;
1280 else
1281 break;
1282 }
1283 if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
1284 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1285 return 0;
1286
1287 if (tag1 || ignore_tag1 || cos1 || dot1q)
1288 len = 18;
1289 if (tag2 || ignore_tag2 || cos2 || dot1ad)
1290 len = 22;
1291
1292 vec_validate (mask, len - 1);
1293
1294 if (dst)
Dave Barachb7b92992018-10-17 10:38:51 -04001295 clib_memset (mask, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001296
1297 if (src)
Dave Barachb7b92992018-10-17 10:38:51 -04001298 clib_memset (mask + 6, 0xff, 6);
Damjan Marion7cd468a2016-12-19 23:05:39 +01001299
1300 if (tag2 || dot1ad)
1301 {
1302 /* inner vlan tag */
1303 if (tag2)
1304 {
1305 mask[19] = 0xff;
1306 mask[18] = 0x0f;
1307 }
1308 if (cos2)
1309 mask[18] |= 0xe0;
1310 if (proto)
1311 mask[21] = mask[20] = 0xff;
1312 if (tag1)
1313 {
1314 mask[15] = 0xff;
1315 mask[14] = 0x0f;
1316 }
1317 if (cos1)
1318 mask[14] |= 0xe0;
1319 *maskp = mask;
1320 return 1;
1321 }
1322 if (tag1 | dot1q)
1323 {
1324 if (tag1)
1325 {
1326 mask[15] = 0xff;
1327 mask[14] = 0x0f;
1328 }
1329 if (cos1)
1330 mask[14] |= 0xe0;
1331 if (proto)
1332 mask[16] = mask[17] = 0xff;
1333
1334 *maskp = mask;
1335 return 1;
1336 }
1337 if (cos2)
1338 mask[18] |= 0xe0;
1339 if (cos1)
1340 mask[14] |= 0xe0;
1341 if (proto)
1342 mask[12] = mask[13] = 0xff;
1343
1344 *maskp = mask;
1345 return 1;
1346}
1347
1348uword
1349unformat_classify_mask (unformat_input_t * input, va_list * args)
1350{
1351 u8 **maskp = va_arg (*args, u8 **);
1352 u32 *skipp = va_arg (*args, u32 *);
1353 u32 *matchp = va_arg (*args, u32 *);
1354 u32 match;
1355 u8 *mask = 0;
1356 u8 *l2 = 0;
1357 u8 *l3 = 0;
1358 u8 *l4 = 0;
1359 int i;
1360
1361 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1362 {
1363 if (unformat (input, "hex %U", unformat_hex_string, &mask))
1364 ;
1365 else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
1366 ;
1367 else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
1368 ;
1369 else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
1370 ;
1371 else
1372 break;
1373 }
1374
1375 if (l4 && !l3)
1376 {
1377 vec_free (mask);
1378 vec_free (l2);
1379 vec_free (l4);
1380 return 0;
1381 }
1382
1383 if (mask || l2 || l3 || l4)
1384 {
1385 if (l2 || l3 || l4)
1386 {
1387 /* "With a free Ethernet header in every package" */
1388 if (l2 == 0)
1389 vec_validate (l2, 13);
1390 mask = l2;
1391 if (vec_len (l3))
1392 {
1393 vec_append (mask, l3);
1394 vec_free (l3);
1395 }
1396 if (vec_len (l4))
1397 {
1398 vec_append (mask, l4);
1399 vec_free (l4);
1400 }
1401 }
1402
1403 /* Scan forward looking for the first significant mask octet */
1404 for (i = 0; i < vec_len (mask); i++)
1405 if (mask[i])
1406 break;
1407
1408 /* compute (skip, match) params */
1409 *skipp = i / sizeof (u32x4);
1410 vec_delete (mask, *skipp * sizeof (u32x4), 0);
1411
1412 /* Pad mask to an even multiple of the vector size */
1413 while (vec_len (mask) % sizeof (u32x4))
1414 vec_add1 (mask, 0);
1415
1416 match = vec_len (mask) / sizeof (u32x4);
1417
1418 for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
1419 {
1420 u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
1421 if (*tmp || *(tmp + 1))
1422 break;
1423 match--;
1424 }
1425 if (match == 0)
1426 clib_warning ("BUG: match 0");
1427
1428 _vec_len (mask) = match * sizeof (u32x4);
1429
1430 *matchp = match;
1431 *maskp = mask;
1432
1433 return 1;
1434 }
1435
1436 return 0;
1437}
Dave Barach4a3f69c2017-02-22 12:44:56 -05001438#endif /* VPP_API_TEST_BUILTIN */
Damjan Marion7cd468a2016-12-19 23:05:39 +01001439
1440#define foreach_l2_next \
1441_(drop, DROP) \
1442_(ethernet, ETHERNET_INPUT) \
1443_(ip4, IP4_INPUT) \
1444_(ip6, IP6_INPUT)
1445
1446uword
1447unformat_l2_next_index (unformat_input_t * input, va_list * args)
1448{
1449 u32 *miss_next_indexp = va_arg (*args, u32 *);
1450 u32 next_index = 0;
1451 u32 tmp;
1452
1453#define _(n,N) \
1454 if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
1455 foreach_l2_next;
1456#undef _
1457
1458 if (unformat (input, "%d", &tmp))
1459 {
1460 next_index = tmp;
1461 goto out;
1462 }
1463
1464 return 0;
1465
1466out:
1467 *miss_next_indexp = next_index;
1468 return 1;
1469}
1470
1471#define foreach_ip_next \
1472_(drop, DROP) \
1473_(local, LOCAL) \
1474_(rewrite, REWRITE)
1475
1476uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001477api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001478{
1479 u32 *miss_next_indexp = va_arg (*args, u32 *);
1480 u32 next_index = 0;
1481 u32 tmp;
1482
1483#define _(n,N) \
1484 if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
1485 foreach_ip_next;
1486#undef _
1487
1488 if (unformat (input, "%d", &tmp))
1489 {
1490 next_index = tmp;
1491 goto out;
1492 }
1493
1494 return 0;
1495
1496out:
1497 *miss_next_indexp = next_index;
1498 return 1;
1499}
1500
1501#define foreach_acl_next \
1502_(deny, DENY)
1503
1504uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001505api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001506{
1507 u32 *miss_next_indexp = va_arg (*args, u32 *);
1508 u32 next_index = 0;
1509 u32 tmp;
1510
1511#define _(n,N) \
1512 if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
1513 foreach_acl_next;
1514#undef _
1515
1516 if (unformat (input, "permit"))
1517 {
1518 next_index = ~0;
1519 goto out;
1520 }
1521 else if (unformat (input, "%d", &tmp))
1522 {
1523 next_index = tmp;
1524 goto out;
1525 }
1526
1527 return 0;
1528
1529out:
1530 *miss_next_indexp = next_index;
1531 return 1;
1532}
1533
1534uword
1535unformat_policer_precolor (unformat_input_t * input, va_list * args)
1536{
1537 u32 *r = va_arg (*args, u32 *);
1538
1539 if (unformat (input, "conform-color"))
1540 *r = POLICE_CONFORM;
1541 else if (unformat (input, "exceed-color"))
1542 *r = POLICE_EXCEED;
1543 else
1544 return 0;
1545
1546 return 1;
1547}
1548
Dave Barach4a3f69c2017-02-22 12:44:56 -05001549#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01001550uword
1551unformat_l4_match (unformat_input_t * input, va_list * args)
1552{
1553 u8 **matchp = va_arg (*args, u8 **);
1554
1555 u8 *proto_header = 0;
1556 int src_port = 0;
1557 int dst_port = 0;
1558
1559 tcpudp_header_t h;
1560
1561 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1562 {
1563 if (unformat (input, "src_port %d", &src_port))
1564 ;
1565 else if (unformat (input, "dst_port %d", &dst_port))
1566 ;
1567 else
1568 return 0;
1569 }
1570
1571 h.src_port = clib_host_to_net_u16 (src_port);
1572 h.dst_port = clib_host_to_net_u16 (dst_port);
1573 vec_validate (proto_header, sizeof (h) - 1);
1574 memcpy (proto_header, &h, sizeof (h));
1575
1576 *matchp = proto_header;
1577
1578 return 1;
1579}
1580
1581uword
1582unformat_ip4_match (unformat_input_t * input, va_list * args)
1583{
1584 u8 **matchp = va_arg (*args, u8 **);
1585 u8 *match = 0;
1586 ip4_header_t *ip;
1587 int version = 0;
1588 u32 version_val;
1589 int hdr_length = 0;
1590 u32 hdr_length_val;
1591 int src = 0, dst = 0;
1592 ip4_address_t src_val, dst_val;
1593 int proto = 0;
1594 u32 proto_val;
1595 int tos = 0;
1596 u32 tos_val;
1597 int length = 0;
1598 u32 length_val;
1599 int fragment_id = 0;
1600 u32 fragment_id_val;
1601 int ttl = 0;
1602 int ttl_val;
1603 int checksum = 0;
1604 u32 checksum_val;
1605
1606 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1607 {
1608 if (unformat (input, "version %d", &version_val))
1609 version = 1;
1610 else if (unformat (input, "hdr_length %d", &hdr_length_val))
1611 hdr_length = 1;
1612 else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
1613 src = 1;
1614 else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
1615 dst = 1;
1616 else if (unformat (input, "proto %d", &proto_val))
1617 proto = 1;
1618 else if (unformat (input, "tos %d", &tos_val))
1619 tos = 1;
1620 else if (unformat (input, "length %d", &length_val))
1621 length = 1;
1622 else if (unformat (input, "fragment_id %d", &fragment_id_val))
1623 fragment_id = 1;
1624 else if (unformat (input, "ttl %d", &ttl_val))
1625 ttl = 1;
1626 else if (unformat (input, "checksum %d", &checksum_val))
1627 checksum = 1;
1628 else
1629 break;
1630 }
1631
1632 if (version + hdr_length + src + dst + proto + tos + length + fragment_id
1633 + ttl + checksum == 0)
1634 return 0;
1635
1636 /*
1637 * Aligned because we use the real comparison functions
1638 */
1639 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1640
1641 ip = (ip4_header_t *) match;
1642
1643 /* These are realistically matched in practice */
1644 if (src)
1645 ip->src_address.as_u32 = src_val.as_u32;
1646
1647 if (dst)
1648 ip->dst_address.as_u32 = dst_val.as_u32;
1649
1650 if (proto)
1651 ip->protocol = proto_val;
1652
1653
1654 /* These are not, but they're included for completeness */
1655 if (version)
1656 ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
1657
1658 if (hdr_length)
1659 ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
1660
1661 if (tos)
1662 ip->tos = tos_val;
1663
1664 if (length)
1665 ip->length = clib_host_to_net_u16 (length_val);
1666
1667 if (ttl)
1668 ip->ttl = ttl_val;
1669
1670 if (checksum)
1671 ip->checksum = clib_host_to_net_u16 (checksum_val);
1672
1673 *matchp = match;
1674 return 1;
1675}
1676
1677uword
1678unformat_ip6_match (unformat_input_t * input, va_list * args)
1679{
1680 u8 **matchp = va_arg (*args, u8 **);
1681 u8 *match = 0;
1682 ip6_header_t *ip;
1683 int version = 0;
1684 u32 version_val;
1685 u8 traffic_class = 0;
1686 u32 traffic_class_val = 0;
1687 u8 flow_label = 0;
1688 u8 flow_label_val;
1689 int src = 0, dst = 0;
1690 ip6_address_t src_val, dst_val;
1691 int proto = 0;
1692 u32 proto_val;
1693 int payload_length = 0;
1694 u32 payload_length_val;
1695 int hop_limit = 0;
1696 int hop_limit_val;
1697 u32 ip_version_traffic_class_and_flow_label;
1698
1699 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1700 {
1701 if (unformat (input, "version %d", &version_val))
1702 version = 1;
1703 else if (unformat (input, "traffic_class %d", &traffic_class_val))
1704 traffic_class = 1;
1705 else if (unformat (input, "flow_label %d", &flow_label_val))
1706 flow_label = 1;
1707 else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
1708 src = 1;
1709 else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
1710 dst = 1;
1711 else if (unformat (input, "proto %d", &proto_val))
1712 proto = 1;
1713 else if (unformat (input, "payload_length %d", &payload_length_val))
1714 payload_length = 1;
1715 else if (unformat (input, "hop_limit %d", &hop_limit_val))
1716 hop_limit = 1;
1717 else
1718 break;
1719 }
1720
1721 if (version + traffic_class + flow_label + src + dst + proto +
1722 payload_length + hop_limit == 0)
1723 return 0;
1724
1725 /*
1726 * Aligned because we use the real comparison functions
1727 */
1728 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1729
1730 ip = (ip6_header_t *) match;
1731
1732 if (src)
1733 clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
1734
1735 if (dst)
1736 clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
1737
1738 if (proto)
1739 ip->protocol = proto_val;
1740
1741 ip_version_traffic_class_and_flow_label = 0;
1742
1743 if (version)
1744 ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
1745
1746 if (traffic_class)
1747 ip_version_traffic_class_and_flow_label |=
1748 (traffic_class_val & 0xFF) << 20;
1749
1750 if (flow_label)
1751 ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
1752
1753 ip->ip_version_traffic_class_and_flow_label =
1754 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1755
1756 if (payload_length)
1757 ip->payload_length = clib_host_to_net_u16 (payload_length_val);
1758
1759 if (hop_limit)
1760 ip->hop_limit = hop_limit_val;
1761
1762 *matchp = match;
1763 return 1;
1764}
1765
1766uword
1767unformat_l3_match (unformat_input_t * input, va_list * args)
1768{
1769 u8 **matchp = va_arg (*args, u8 **);
1770
1771 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1772 {
1773 if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
1774 return 1;
1775 else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
1776 return 1;
1777 else
1778 break;
1779 }
1780 return 0;
1781}
1782
1783uword
1784unformat_vlan_tag (unformat_input_t * input, va_list * args)
1785{
1786 u8 *tagp = va_arg (*args, u8 *);
1787 u32 tag;
1788
1789 if (unformat (input, "%d", &tag))
1790 {
1791 tagp[0] = (tag >> 8) & 0x0F;
1792 tagp[1] = tag & 0xFF;
1793 return 1;
1794 }
1795
1796 return 0;
1797}
1798
1799uword
1800unformat_l2_match (unformat_input_t * input, va_list * args)
1801{
1802 u8 **matchp = va_arg (*args, u8 **);
1803 u8 *match = 0;
1804 u8 src = 0;
1805 u8 src_val[6];
1806 u8 dst = 0;
1807 u8 dst_val[6];
1808 u8 proto = 0;
1809 u16 proto_val;
1810 u8 tag1 = 0;
1811 u8 tag1_val[2];
1812 u8 tag2 = 0;
1813 u8 tag2_val[2];
1814 int len = 14;
1815 u8 ignore_tag1 = 0;
1816 u8 ignore_tag2 = 0;
1817 u8 cos1 = 0;
1818 u8 cos2 = 0;
1819 u32 cos1_val = 0;
1820 u32 cos2_val = 0;
1821
1822 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1823 {
1824 if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
1825 src = 1;
1826 else
1827 if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
1828 dst = 1;
1829 else if (unformat (input, "proto %U",
1830 unformat_ethernet_type_host_byte_order, &proto_val))
1831 proto = 1;
1832 else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
1833 tag1 = 1;
1834 else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
1835 tag2 = 1;
1836 else if (unformat (input, "ignore-tag1"))
1837 ignore_tag1 = 1;
1838 else if (unformat (input, "ignore-tag2"))
1839 ignore_tag2 = 1;
1840 else if (unformat (input, "cos1 %d", &cos1_val))
1841 cos1 = 1;
1842 else if (unformat (input, "cos2 %d", &cos2_val))
1843 cos2 = 1;
1844 else
1845 break;
1846 }
1847 if ((src + dst + proto + tag1 + tag2 +
1848 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1849 return 0;
1850
1851 if (tag1 || ignore_tag1 || cos1)
1852 len = 18;
1853 if (tag2 || ignore_tag2 || cos2)
1854 len = 22;
1855
1856 vec_validate_aligned (match, len - 1, sizeof (u32x4));
1857
1858 if (dst)
1859 clib_memcpy (match, dst_val, 6);
1860
1861 if (src)
1862 clib_memcpy (match + 6, src_val, 6);
1863
1864 if (tag2)
1865 {
1866 /* inner vlan tag */
1867 match[19] = tag2_val[1];
1868 match[18] = tag2_val[0];
1869 if (cos2)
1870 match[18] |= (cos2_val & 0x7) << 5;
1871 if (proto)
1872 {
1873 match[21] = proto_val & 0xff;
1874 match[20] = proto_val >> 8;
1875 }
1876 if (tag1)
1877 {
1878 match[15] = tag1_val[1];
1879 match[14] = tag1_val[0];
1880 }
1881 if (cos1)
1882 match[14] |= (cos1_val & 0x7) << 5;
1883 *matchp = match;
1884 return 1;
1885 }
1886 if (tag1)
1887 {
1888 match[15] = tag1_val[1];
1889 match[14] = tag1_val[0];
1890 if (proto)
1891 {
1892 match[17] = proto_val & 0xff;
1893 match[16] = proto_val >> 8;
1894 }
1895 if (cos1)
1896 match[14] |= (cos1_val & 0x7) << 5;
1897
1898 *matchp = match;
1899 return 1;
1900 }
1901 if (cos2)
1902 match[18] |= (cos2_val & 0x7) << 5;
1903 if (cos1)
1904 match[14] |= (cos1_val & 0x7) << 5;
1905 if (proto)
1906 {
1907 match[13] = proto_val & 0xff;
1908 match[12] = proto_val >> 8;
1909 }
1910
1911 *matchp = match;
1912 return 1;
1913}
Igor Mikhailov (imichail)582caa32018-04-26 21:33:02 -07001914
1915uword
1916unformat_qos_source (unformat_input_t * input, va_list * args)
1917{
1918 int *qs = va_arg (*args, int *);
1919
1920 if (unformat (input, "ip"))
1921 *qs = QOS_SOURCE_IP;
1922 else if (unformat (input, "mpls"))
1923 *qs = QOS_SOURCE_MPLS;
1924 else if (unformat (input, "ext"))
1925 *qs = QOS_SOURCE_EXT;
1926 else if (unformat (input, "vlan"))
1927 *qs = QOS_SOURCE_VLAN;
1928 else
1929 return 0;
1930
1931 return 1;
1932}
Dave Barach4a3f69c2017-02-22 12:44:56 -05001933#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01001934
1935uword
Dave Barach4a3f69c2017-02-22 12:44:56 -05001936api_unformat_classify_match (unformat_input_t * input, va_list * args)
Damjan Marion7cd468a2016-12-19 23:05:39 +01001937{
1938 u8 **matchp = va_arg (*args, u8 **);
1939 u32 skip_n_vectors = va_arg (*args, u32);
1940 u32 match_n_vectors = va_arg (*args, u32);
1941
1942 u8 *match = 0;
1943 u8 *l2 = 0;
1944 u8 *l3 = 0;
1945 u8 *l4 = 0;
1946
1947 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1948 {
1949 if (unformat (input, "hex %U", unformat_hex_string, &match))
1950 ;
1951 else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
1952 ;
1953 else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
1954 ;
1955 else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
1956 ;
1957 else
1958 break;
1959 }
1960
1961 if (l4 && !l3)
1962 {
1963 vec_free (match);
1964 vec_free (l2);
1965 vec_free (l4);
1966 return 0;
1967 }
1968
1969 if (match || l2 || l3 || l4)
1970 {
1971 if (l2 || l3 || l4)
1972 {
1973 /* "Win a free Ethernet header in every packet" */
1974 if (l2 == 0)
1975 vec_validate_aligned (l2, 13, sizeof (u32x4));
1976 match = l2;
1977 if (vec_len (l3))
1978 {
1979 vec_append_aligned (match, l3, sizeof (u32x4));
1980 vec_free (l3);
1981 }
1982 if (vec_len (l4))
1983 {
1984 vec_append_aligned (match, l4, sizeof (u32x4));
1985 vec_free (l4);
1986 }
1987 }
1988
1989 /* Make sure the vector is big enough even if key is all 0's */
1990 vec_validate_aligned
1991 (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
1992 sizeof (u32x4));
1993
1994 /* Set size, include skipped vectors */
1995 _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
1996
1997 *matchp = match;
1998
1999 return 1;
2000 }
2001
2002 return 0;
2003}
2004
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002005#define foreach_vtr_op \
2006 _ ("disable", L2_VTR_DISABLED) \
2007 _ ("push-1", L2_VTR_PUSH_1) \
2008 _ ("push-2", L2_VTR_PUSH_2) \
2009 _ ("pop-1", L2_VTR_POP_1) \
2010 _ ("pop-2", L2_VTR_POP_2) \
2011 _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \
2012 _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \
2013 _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \
2014 _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002015
2016static int
Filip Tehlar4f348df2021-06-22 12:18:17 +00002017api_show_version (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002018{
2019 vl_api_show_version_t *mp;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002020 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002021
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002022 M (SHOW_VERSION, mp);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002023
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002024 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002025 W (ret);
2026 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002027}
2028
Damjan Marion7cd468a2016-12-19 23:05:39 +01002029static int
Filip Tehlar5ff59a12021-06-23 14:38:38 +00002030api_get_first_msg_id (vat_main_t *vam)
Damjan Marion7cd468a2016-12-19 23:05:39 +01002031{
2032 vl_api_get_first_msg_id_t *mp;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002033 unformat_input_t *i = vam->input;
2034 u8 *name;
2035 u8 name_set = 0;
Jon Loeliger56c7b012017-02-01 12:31:41 -06002036 int ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002037
2038 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2039 {
2040 if (unformat (i, "client %s", &name))
2041 name_set = 1;
2042 else
2043 break;
2044 }
2045
2046 if (name_set == 0)
2047 {
2048 errmsg ("missing client name");
2049 return -99;
2050 }
2051 vec_add1 (name, 0);
2052
2053 if (vec_len (name) > 63)
2054 {
2055 errmsg ("client name too long");
2056 return -99;
2057 }
2058
Jon Loeliger8a2aea32017-01-31 13:19:40 -06002059 M (GET_FIRST_MSG_ID, mp);
Ole Troan7adaa222019-08-27 15:05:27 +02002060 clib_memcpy (mp->name, name, vec_len (name));
Jon Loeliger7bc770c2017-01-31 14:03:33 -06002061 S (mp);
Jon Loeliger56c7b012017-02-01 12:31:41 -06002062 W (ret);
2063 return ret;
Damjan Marion7cd468a2016-12-19 23:05:39 +01002064}
2065
Damjan Marion7cd468a2016-12-19 23:05:39 +01002066#define foreach_pbb_vtr_op \
2067_("disable", L2_VTR_DISABLED) \
2068_("pop", L2_VTR_POP_2) \
2069_("push", L2_VTR_PUSH_2)
2070
Florin Corascea194d2017-10-02 00:18:51 -07002071static int
Florin Coras90a63982017-12-19 04:50:01 -08002072api_sock_init_shm (vat_main_t * vam)
2073{
2074#if VPP_API_TEST_BUILTIN == 0
2075 unformat_input_t *i = vam->input;
2076 vl_api_shm_elem_config_t *config = 0;
2077 u64 size = 64 << 20;
2078 int rv;
2079
2080 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2081 {
2082 if (unformat (i, "size %U", unformat_memory_size, &size))
2083 ;
2084 else
2085 break;
2086 }
2087
Dave Barach78958722018-05-10 16:44:27 -04002088 /*
2089 * Canned custom ring allocator config.
2090 * Should probably parse all of this
2091 */
2092 vec_validate (config, 6);
Florin Coras90a63982017-12-19 04:50:01 -08002093 config[0].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002094 config[0].size = 256;
Dave Barach78958722018-05-10 16:44:27 -04002095 config[0].count = 32;
2096
2097 config[1].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002098 config[1].size = 1024;
Dave Barach78958722018-05-10 16:44:27 -04002099 config[1].count = 16;
2100
2101 config[2].type = VL_API_VLIB_RING;
Florin Coras90a63982017-12-19 04:50:01 -08002102 config[2].size = 4096;
Dave Barach78958722018-05-10 16:44:27 -04002103 config[2].count = 2;
2104
2105 config[3].type = VL_API_CLIENT_RING;
2106 config[3].size = 256;
2107 config[3].count = 32;
2108
2109 config[4].type = VL_API_CLIENT_RING;
2110 config[4].size = 1024;
2111 config[4].count = 16;
2112
2113 config[5].type = VL_API_CLIENT_RING;
2114 config[5].size = 4096;
2115 config[5].count = 2;
2116
2117 config[6].type = VL_API_QUEUE;
2118 config[6].count = 128;
2119 config[6].size = sizeof (uword);
2120
Tomasz Kulasek97dcf5b2019-01-31 18:26:32 +01002121 rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
Florin Coras90a63982017-12-19 04:50:01 -08002122 if (!rv)
2123 vam->client_index_invalid = 1;
2124 return rv;
2125#else
2126 return -99;
2127#endif
2128}
2129
Florin Coras6c36f532017-11-03 18:32:34 -07002130static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002131q_or_quit (vat_main_t * vam)
2132{
Dave Barachdef19da2017-02-22 17:29:20 -05002133#if VPP_API_TEST_BUILTIN == 0
Damjan Marion7cd468a2016-12-19 23:05:39 +01002134 longjmp (vam->jump_buf, 1);
Dave Barachdef19da2017-02-22 17:29:20 -05002135#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002136 return 0; /* not so much */
2137}
2138
2139static int
2140q (vat_main_t * vam)
2141{
2142 return q_or_quit (vam);
2143}
2144
2145static int
2146quit (vat_main_t * vam)
2147{
2148 return q_or_quit (vam);
2149}
2150
2151static int
2152comment (vat_main_t * vam)
2153{
2154 return 0;
2155}
2156
2157static int
Dave Barachb09f4d02019-07-15 16:00:03 -04002158elog_save (vat_main_t * vam)
2159{
2160#if VPP_API_TEST_BUILTIN == 0
2161 elog_main_t *em = &vam->elog_main;
2162 unformat_input_t *i = vam->input;
2163 char *file, *chroot_file;
2164 clib_error_t *error;
2165
2166 if (!unformat (i, "%s", &file))
2167 {
2168 errmsg ("expected file name, got `%U'", format_unformat_error, i);
2169 return 0;
2170 }
2171
2172 /* It's fairly hard to get "../oopsie" through unformat; just in case */
2173 if (strstr (file, "..") || index (file, '/'))
2174 {
2175 errmsg ("illegal characters in filename '%s'", file);
2176 return 0;
2177 }
2178
2179 chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
2180
2181 vec_free (file);
2182
2183 errmsg ("Saving %wd of %wd events to %s",
2184 elog_n_events_in_buffer (em),
2185 elog_buffer_capacity (em), chroot_file);
2186
2187 error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
2188 vec_free (chroot_file);
2189
2190 if (error)
2191 clib_error_report (error);
2192#else
2193 errmsg ("Use the vpp event loger...");
2194#endif
2195
2196 return 0;
2197}
2198
2199static int
2200elog_setup (vat_main_t * vam)
2201{
2202#if VPP_API_TEST_BUILTIN == 0
2203 elog_main_t *em = &vam->elog_main;
2204 unformat_input_t *i = vam->input;
2205 u32 nevents = 128 << 10;
2206
2207 (void) unformat (i, "nevents %d", &nevents);
2208
2209 elog_init (em, nevents);
2210 vl_api_set_elog_main (em);
2211 vl_api_set_elog_trace_api_messages (1);
2212 errmsg ("Event logger initialized with %u events", nevents);
2213#else
2214 errmsg ("Use the vpp event loger...");
2215#endif
2216 return 0;
2217}
2218
2219static int
2220elog_enable (vat_main_t * vam)
2221{
2222#if VPP_API_TEST_BUILTIN == 0
2223 elog_main_t *em = &vam->elog_main;
2224
2225 elog_enable_disable (em, 1 /* enable */ );
2226 vl_api_set_elog_trace_api_messages (1);
2227 errmsg ("Event logger enabled...");
2228#else
2229 errmsg ("Use the vpp event loger...");
2230#endif
2231 return 0;
2232}
2233
2234static int
2235elog_disable (vat_main_t * vam)
2236{
2237#if VPP_API_TEST_BUILTIN == 0
2238 elog_main_t *em = &vam->elog_main;
2239
2240 elog_enable_disable (em, 0 /* enable */ );
2241 vl_api_set_elog_trace_api_messages (1);
2242 errmsg ("Event logger disabled...");
2243#else
2244 errmsg ("Use the vpp event loger...");
2245#endif
2246 return 0;
2247}
2248
2249static int
Dave Barach048a4e52018-06-01 18:52:25 -04002250statseg (vat_main_t * vam)
2251{
2252 ssvm_private_t *ssvmp = &vam->stat_segment;
2253 ssvm_shared_header_t *shared_header = ssvmp->sh;
2254 vlib_counter_t **counters;
2255 u64 thread0_index1_packets;
2256 u64 thread0_index1_bytes;
2257 f64 vector_rate, input_rate;
2258 uword *p;
2259
2260 uword *counter_vector_by_name;
2261 if (vam->stat_segment_lockp == 0)
2262 {
2263 errmsg ("Stat segment not mapped...");
2264 return -99;
2265 }
2266
2267 /* look up "/if/rx for sw_if_index 1 as a test */
2268
2269 clib_spinlock_lock (vam->stat_segment_lockp);
2270
2271 counter_vector_by_name = (uword *) shared_header->opaque[1];
2272
2273 p = hash_get_mem (counter_vector_by_name, "/if/rx");
2274 if (p == 0)
2275 {
2276 clib_spinlock_unlock (vam->stat_segment_lockp);
2277 errmsg ("/if/tx not found?");
2278 return -99;
2279 }
2280
2281 /* Fish per-thread vector of combined counters from shared memory */
2282 counters = (vlib_counter_t **) p[0];
2283
2284 if (vec_len (counters[0]) < 2)
2285 {
2286 clib_spinlock_unlock (vam->stat_segment_lockp);
2287 errmsg ("/if/tx vector length %d", vec_len (counters[0]));
2288 return -99;
2289 }
2290
2291 /* Read thread 0 sw_if_index 1 counter */
2292 thread0_index1_packets = counters[0][1].packets;
2293 thread0_index1_bytes = counters[0][1].bytes;
2294
2295 p = hash_get_mem (counter_vector_by_name, "vector_rate");
2296 if (p == 0)
2297 {
2298 clib_spinlock_unlock (vam->stat_segment_lockp);
2299 errmsg ("vector_rate not found?");
2300 return -99;
2301 }
2302
2303 vector_rate = *(f64 *) (p[0]);
2304 p = hash_get_mem (counter_vector_by_name, "input_rate");
2305 if (p == 0)
2306 {
2307 clib_spinlock_unlock (vam->stat_segment_lockp);
2308 errmsg ("input_rate not found?");
2309 return -99;
2310 }
2311 input_rate = *(f64 *) (p[0]);
2312
2313 clib_spinlock_unlock (vam->stat_segment_lockp);
2314
2315 print (vam->ofp, "vector_rate %.2f input_rate %.2f",
2316 vector_rate, input_rate);
2317 print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
2318 thread0_index1_packets, thread0_index1_bytes);
2319
2320 return 0;
2321}
2322
2323static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002324cmd_cmp (void *a1, void *a2)
2325{
2326 u8 **c1 = a1;
2327 u8 **c2 = a2;
2328
2329 return strcmp ((char *) (c1[0]), (char *) (c2[0]));
2330}
2331
2332static int
2333help (vat_main_t * vam)
2334{
2335 u8 **cmds = 0;
2336 u8 *name = 0;
2337 hash_pair_t *p;
2338 unformat_input_t *i = vam->input;
2339 int j;
2340
2341 if (unformat (i, "%s", &name))
2342 {
2343 uword *hs;
2344
2345 vec_add1 (name, 0);
2346
2347 hs = hash_get_mem (vam->help_by_name, name);
2348 if (hs)
2349 print (vam->ofp, "usage: %s %s", name, hs[0]);
2350 else
2351 print (vam->ofp, "No such msg / command '%s'", name);
2352 vec_free (name);
2353 return 0;
2354 }
2355
2356 print (vam->ofp, "Help is available for the following:");
2357
2358 /* *INDENT-OFF* */
2359 hash_foreach_pair (p, vam->function_by_name,
2360 ({
2361 vec_add1 (cmds, (u8 *)(p->key));
2362 }));
2363 /* *INDENT-ON* */
2364
2365 vec_sort_with_function (cmds, cmd_cmp);
2366
2367 for (j = 0; j < vec_len (cmds); j++)
2368 print (vam->ofp, "%s", cmds[j]);
2369
2370 vec_free (cmds);
2371 return 0;
2372}
2373
2374static int
2375set (vat_main_t * vam)
2376{
2377 u8 *name = 0, *value = 0;
2378 unformat_input_t *i = vam->input;
2379
2380 if (unformat (i, "%s", &name))
2381 {
2382 /* The input buffer is a vector, not a string. */
2383 value = vec_dup (i->buffer);
2384 vec_delete (value, i->index, 0);
2385 /* Almost certainly has a trailing newline */
2386 if (value[vec_len (value) - 1] == '\n')
2387 value[vec_len (value) - 1] = 0;
2388 /* Make sure it's a proper string, one way or the other */
2389 vec_add1 (value, 0);
2390 (void) clib_macro_set_value (&vam->macro_main,
2391 (char *) name, (char *) value);
2392 }
2393 else
2394 errmsg ("usage: set <name> <value>");
2395
2396 vec_free (name);
2397 vec_free (value);
2398 return 0;
2399}
2400
2401static int
2402unset (vat_main_t * vam)
2403{
2404 u8 *name = 0;
2405
2406 if (unformat (vam->input, "%s", &name))
2407 if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
2408 errmsg ("unset: %s wasn't set", name);
2409 vec_free (name);
2410 return 0;
2411}
2412
2413typedef struct
2414{
2415 u8 *name;
2416 u8 *value;
2417} macro_sort_t;
2418
2419
2420static int
2421macro_sort_cmp (void *a1, void *a2)
2422{
2423 macro_sort_t *s1 = a1;
2424 macro_sort_t *s2 = a2;
2425
2426 return strcmp ((char *) (s1->name), (char *) (s2->name));
2427}
2428
2429static int
2430dump_macro_table (vat_main_t * vam)
2431{
2432 macro_sort_t *sort_me = 0, *sm;
2433 int i;
2434 hash_pair_t *p;
2435
2436 /* *INDENT-OFF* */
2437 hash_foreach_pair (p, vam->macro_main.the_value_table_hash,
2438 ({
2439 vec_add2 (sort_me, sm, 1);
2440 sm->name = (u8 *)(p->key);
2441 sm->value = (u8 *) (p->value[0]);
2442 }));
2443 /* *INDENT-ON* */
2444
2445 vec_sort_with_function (sort_me, macro_sort_cmp);
2446
2447 if (vec_len (sort_me))
2448 print (vam->ofp, "%-15s%s", "Name", "Value");
2449 else
2450 print (vam->ofp, "The macro table is empty...");
2451
2452 for (i = 0; i < vec_len (sort_me); i++)
2453 print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
2454 return 0;
2455}
2456
2457static int
Damjan Marion7cd468a2016-12-19 23:05:39 +01002458value_sort_cmp (void *a1, void *a2)
2459{
2460 name_sort_t *n1 = a1;
2461 name_sort_t *n2 = a2;
2462
2463 if (n1->value < n2->value)
2464 return -1;
2465 if (n1->value > n2->value)
2466 return 1;
2467 return 0;
2468}
2469
2470
2471static int
2472dump_msg_api_table (vat_main_t * vam)
2473{
Dave Barach39d69112019-11-27 11:42:13 -05002474 api_main_t *am = vlibapi_get_main ();
Damjan Marion7cd468a2016-12-19 23:05:39 +01002475 name_sort_t *nses = 0, *ns;
2476 hash_pair_t *hp;
2477 int i;
2478
2479 /* *INDENT-OFF* */
2480 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
2481 ({
2482 vec_add2 (nses, ns, 1);
2483 ns->name = (u8 *)(hp->key);
2484 ns->value = (u32) hp->value[0];
2485 }));
2486 /* *INDENT-ON* */
2487
2488 vec_sort_with_function (nses, value_sort_cmp);
2489
2490 for (i = 0; i < vec_len (nses); i++)
2491 print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
2492 vec_free (nses);
2493 return 0;
2494}
2495
2496static int
2497get_msg_id (vat_main_t * vam)
2498{
2499 u8 *name_and_crc;
2500 u32 message_index;
2501
2502 if (unformat (vam->input, "%s", &name_and_crc))
2503 {
Florin Corase86a8ed2018-01-05 03:20:25 -08002504 message_index = vl_msg_api_get_msg_index (name_and_crc);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002505 if (message_index == ~0)
2506 {
2507 print (vam->ofp, " '%s' not found", name_and_crc);
2508 return 0;
2509 }
2510 print (vam->ofp, " '%s' has message index %d",
2511 name_and_crc, message_index);
2512 return 0;
2513 }
2514 errmsg ("name_and_crc required...");
2515 return 0;
2516}
2517
2518static int
2519search_node_table (vat_main_t * vam)
2520{
2521 unformat_input_t *line_input = vam->input;
2522 u8 *node_to_find;
2523 int j;
2524 vlib_node_t *node, *next_node;
2525 uword *p;
2526
2527 if (vam->graph_node_index_by_name == 0)
2528 {
2529 print (vam->ofp, "Node table empty, issue get_node_graph...");
2530 return 0;
2531 }
2532
2533 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2534 {
2535 if (unformat (line_input, "%s", &node_to_find))
2536 {
2537 vec_add1 (node_to_find, 0);
2538 p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
2539 if (p == 0)
2540 {
2541 print (vam->ofp, "%s not found...", node_to_find);
2542 goto out;
2543 }
Dave Barach1ddbc012018-06-13 09:26:05 -04002544 node = vam->graph_nodes[0][p[0]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01002545 print (vam->ofp, "[%d] %s", p[0], node->name);
2546 for (j = 0; j < vec_len (node->next_nodes); j++)
2547 {
2548 if (node->next_nodes[j] != ~0)
2549 {
Dave Barach1ddbc012018-06-13 09:26:05 -04002550 next_node = vam->graph_nodes[0][node->next_nodes[j]];
Damjan Marion7cd468a2016-12-19 23:05:39 +01002551 print (vam->ofp, " [%d] %s", j, next_node->name);
2552 }
2553 }
2554 }
2555
2556 else
2557 {
2558 clib_warning ("parse error '%U'", format_unformat_error,
2559 line_input);
2560 return -99;
2561 }
2562
2563 out:
2564 vec_free (node_to_find);
2565
2566 }
2567
2568 return 0;
2569}
2570
2571
2572static int
2573script (vat_main_t * vam)
2574{
2575#if (VPP_API_TEST_BUILTIN==0)
2576 u8 *s = 0;
2577 char *save_current_file;
2578 unformat_input_t save_input;
2579 jmp_buf save_jump_buf;
2580 u32 save_line_number;
2581
2582 FILE *new_fp, *save_ifp;
2583
2584 if (unformat (vam->input, "%s", &s))
2585 {
2586 new_fp = fopen ((char *) s, "r");
2587 if (new_fp == 0)
2588 {
2589 errmsg ("Couldn't open script file %s", s);
2590 vec_free (s);
2591 return -99;
2592 }
2593 }
2594 else
2595 {
2596 errmsg ("Missing script name");
2597 return -99;
2598 }
2599
2600 clib_memcpy (&save_input, &vam->input, sizeof (save_input));
2601 clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
2602 save_ifp = vam->ifp;
2603 save_line_number = vam->input_line_number;
2604 save_current_file = (char *) vam->current_file;
2605
2606 vam->input_line_number = 0;
2607 vam->ifp = new_fp;
2608 vam->current_file = s;
2609 do_one_file (vam);
2610
Sirshak Dasb0861822018-05-29 21:13:21 -05002611 clib_memcpy (&vam->input, &save_input, sizeof (save_input));
Damjan Marion7cd468a2016-12-19 23:05:39 +01002612 clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
2613 vam->ifp = save_ifp;
2614 vam->input_line_number = save_line_number;
2615 vam->current_file = (u8 *) save_current_file;
2616 vec_free (s);
2617
2618 return 0;
2619#else
2620 clib_warning ("use the exec command...");
2621 return -99;
2622#endif
2623}
2624
2625static int
2626echo (vat_main_t * vam)
2627{
2628 print (vam->ofp, "%v", vam->input->buffer);
2629 return 0;
2630}
2631
Florin Coras248210c2021-09-14 18:54:45 -07002632int exec (vat_main_t *vam) __attribute__ ((weak));
2633int
2634exec (vat_main_t *vam)
2635{
2636 return -1;
2637}
2638
Damjan Marion7cd468a2016-12-19 23:05:39 +01002639/* List of API message constructors, CLI names map to api_xxx */
2640#define foreach_vpe_api_msg \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002641_(show_version, "") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002642_(get_first_msg_id, "client <name>") \
Florin Coras90a63982017-12-19 04:50:01 -08002643_(sock_init_shm, "size <nnn>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002644/* List of command functions, CLI names map directly to functions */
2645#define foreach_cli_function \
2646_(comment, "usage: comment <ignore-rest-of-line>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002647_(dump_macro_table, "usage: dump_macro_table ") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002648_(dump_msg_api_table, "usage: dump_msg_api_table") \
Dave Barachb09f4d02019-07-15 16:00:03 -04002649_(elog_setup, "usage: elog_setup [nevents, default 128K]") \
2650_(elog_disable, "usage: elog_disable") \
2651_(elog_enable, "usage: elog_enable") \
2652_(elog_save, "usage: elog_save <filename>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002653_(get_msg_id, "usage: get_msg_id name_and_crc") \
2654_(echo, "usage: echo <message>") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002655_(help, "usage: help") \
2656_(q, "usage: quit") \
2657_(quit, "usage: quit") \
2658_(search_node_table, "usage: search_node_table <name>...") \
2659_(set, "usage: set <variable-name> <value>") \
2660_(script, "usage: script <file-name>") \
Neale Ranns097fa662018-05-01 05:17:55 -07002661_(statseg, "usage: statseg") \
Damjan Marion7cd468a2016-12-19 23:05:39 +01002662_(unset, "usage: unset <variable-name>")
Dave Barach048a4e52018-06-01 18:52:25 -04002663
Damjan Marion7cd468a2016-12-19 23:05:39 +01002664#define _(N,n) \
2665 static void vl_api_##n##_t_handler_uni \
2666 (vl_api_##n##_t * mp) \
2667 { \
2668 vat_main_t * vam = &vat_main; \
2669 if (vam->json_output) { \
2670 vl_api_##n##_t_handler_json(mp); \
2671 } else { \
2672 vl_api_##n##_t_handler(mp); \
2673 } \
2674 }
2675foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05002676#if VPP_API_TEST_BUILTIN == 0
2677foreach_standalone_reply_msg;
2678#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002679#undef _
2680
2681void
2682vat_api_hookup (vat_main_t * vam)
2683{
2684#define _(N,n) \
2685 vl_msg_api_set_handlers(VL_API_##N, #n, \
2686 vl_api_##n##_t_handler_uni, \
2687 vl_noop_handler, \
2688 vl_api_##n##_t_endian, \
2689 vl_api_##n##_t_print, \
2690 sizeof(vl_api_##n##_t), 1);
2691 foreach_vpe_api_reply_msg;
Dave Baracha1a093d2017-03-02 13:13:23 -05002692#if VPP_API_TEST_BUILTIN == 0
2693 foreach_standalone_reply_msg;
2694#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002695#undef _
2696
2697#if (VPP_API_TEST_BUILTIN==0)
2698 vl_msg_api_set_first_available_msg_id (VL_MSG_FIRST_AVAILABLE);
Damjan Marion7cd468a2016-12-19 23:05:39 +01002699
2700 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2701
2702 vam->function_by_name = hash_create_string (0, sizeof (uword));
2703
2704 vam->help_by_name = hash_create_string (0, sizeof (uword));
Dave Barach45e4f362017-03-07 12:52:31 -05002705#endif
Damjan Marion7cd468a2016-12-19 23:05:39 +01002706
2707 /* API messages we can send */
2708#define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
2709 foreach_vpe_api_msg;
2710#undef _
2711
2712 /* Help strings */
2713#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2714 foreach_vpe_api_msg;
2715#undef _
Damjan Marion7cd468a2016-12-19 23:05:39 +01002716
2717 /* CLI functions */
2718#define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
2719 foreach_cli_function;
2720#undef _
2721
2722 /* Help strings */
2723#define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2724 foreach_cli_function;
2725#undef _
2726}
2727
Dave Baracha1a093d2017-03-02 13:13:23 -05002728#if VPP_API_TEST_BUILTIN
2729static clib_error_t *
2730vat_api_hookup_shim (vlib_main_t * vm)
2731{
2732 vat_api_hookup (&vat_main);
2733 return 0;
2734}
2735
2736VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
2737#endif
2738
Damjan Marion7cd468a2016-12-19 23:05:39 +01002739/*
2740 * fd.io coding-style-patch-verification: ON
2741 *
2742 * Local Variables:
2743 * eval: (c-set-style "gnu")
2744 * End:
2745 */