2 *------------------------------------------------------------------
5 * Copyright (c) 2014-2020 Cisco and/or its affiliates.
6 * 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:
10 * http://www.apache.org/licenses/LICENSE-2.0
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 *------------------------------------------------------------------
21 #include <vlib/pci/pci.h>
22 #include <vpp/api/types.h>
23 #include <vppinfra/socket.h>
24 #include <vlibapi/api.h>
25 #include <vlibmemory/api.h>
26 #include <vnet/ip/ip.h>
27 #include <vnet/ip-neighbor/ip_neighbor.h>
28 #include <vnet/ip/ip_types_api.h>
29 #include <vnet/l2/l2_input.h>
30 #include <vnet/udp/udp_local.h>
32 #include <vnet/l2/l2_classify.h>
33 #include <vnet/l2/l2_vtr.h>
34 #include <vnet/classify/in_out_acl.h>
35 #include <vnet/classify/policer_classify.h>
36 #include <vnet/classify/flow_classify.h>
37 #include <vnet/mpls/mpls.h>
38 #include <vnet/ipsec/ipsec.h>
40 #include <vnet/ip/ip6_hop_by_hop.h>
41 #include <vnet/ip/ip_source_and_port_range_check.h>
42 #include <vnet/policer/xlate.h>
43 #include <vnet/span/span.h>
44 #include <vnet/policer/policer.h>
45 #include <vnet/policer/police.h>
46 #include <vnet/mfib/mfib_types.h>
47 #include <vnet/bonding/node.h>
48 #include <vnet/qos/qos_types.h>
49 #include <vnet/ethernet/ethernet_types_api.h>
50 #include <vnet/ip/ip_types_api.h>
51 #include "vat/json_format.h"
52 #include <vnet/ip/ip_types_api.h>
53 #include <vnet/ethernet/ethernet_types_api.h>
58 #include <vlibmemory/memclnt.api_enum.h>
59 #include <vlibmemory/memclnt.api_types.h>
60 #include <vlibmemory/memclnt.api_tojson.h>
61 #include <vlibmemory/memclnt.api_fromjson.h>
63 #define vl_endianfun /* define message structures */
64 #include <vlibmemory/memclnt.api.h>
67 #define vl_calcsizefun
68 #include <vlibmemory/memclnt.api.h>
71 /* instantiate all the print functions we know about */
72 #if VPP_API_TEST_BUILTIN == 0
73 #define vl_print(handle, ...)
75 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
78 #include <vlibmemory/memclnt.api.h>
81 #define __plugin_msg_base 0
82 #include <vlibapi/vat_helper_macros.h>
84 void vl_api_set_elog_main (elog_main_t * m);
85 int vl_api_set_elog_trace_api_messages (int enable);
87 #if VPP_API_TEST_BUILTIN == 0
97 vat_socket_connect (vat_main_t * vam)
100 api_main_t *am = vlibapi_get_main ();
101 vam->socket_client_main = &socket_client_main;
102 if ((rv = vl_socket_client_connect ((char *) vam->socket_name,
104 0 /* default socket rx, tx buffer */ )))
107 /* vpp expects the client index in network order */
108 vam->my_client_index = htonl (socket_client_main.client_index);
109 am->my_client_index = vam->my_client_index;
112 #else /* vpp built-in case, we don't do sockets... */
114 vat_socket_connect (vat_main_t * vam)
120 vl_socket_client_read (int wait)
126 vl_socket_client_write ()
132 vl_socket_client_msg_alloc (int nbytes)
140 vat_time_now (vat_main_t * vam)
142 #if VPP_API_TEST_BUILTIN
143 return vlib_time_now (vam->vlib_main);
145 return clib_time_now (&vam->clib_time);
150 errmsg (char *fmt, ...)
152 vat_main_t *vam = &vat_main;
157 s = va_format (0, fmt, &va);
162 #if VPP_API_TEST_BUILTIN
163 vlib_cli_output (vam->vlib_main, (char *) s);
166 if (vam->ifp != stdin)
167 fformat (vam->ofp, "%s(%d): \n", vam->current_file,
168 vam->input_line_number);
170 fformat (vam->ofp, "%s\n", (char *) s);
178 #if VPP_API_TEST_BUILTIN == 0
180 /* Parse an IP4 address %d.%d.%d.%d. */
182 unformat_ip4_address (unformat_input_t * input, va_list * args)
184 u8 *result = va_arg (*args, u8 *);
187 if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]))
190 if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256)
202 unformat_ethernet_address (unformat_input_t * input, va_list * args)
204 u8 *result = va_arg (*args, u8 *);
207 if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_",
208 &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]))
212 for (i = 0; i < 6; i++)
213 if (a[i] >= (1 << 8))
216 for (i = 0; i < 6; i++)
222 /* Returns ethernet type as an int in host byte order. */
224 unformat_ethernet_type_host_byte_order (unformat_input_t * input,
227 u16 *result = va_arg (*args, u16 *);
231 if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type))
233 if (type >= (1 << 16))
241 /* Parse an IP46 address. */
243 unformat_ip46_address (unformat_input_t * input, va_list * args)
245 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
246 ip46_type_t type = va_arg (*args, ip46_type_t);
247 if ((type != IP46_TYPE_IP6) &&
248 unformat (input, "%U", unformat_ip4_address, &ip46->ip4))
250 ip46_address_mask_ip4 (ip46);
253 else if ((type != IP46_TYPE_IP4) &&
254 unformat (input, "%U", unformat_ip6_address, &ip46->ip6))
261 /* Parse an IP6 address. */
263 unformat_ip6_address (unformat_input_t * input, va_list * args)
265 ip6_address_t *result = va_arg (*args, ip6_address_t *);
267 uword hex_quad, n_hex_quads, hex_digit, n_hex_digits;
268 uword c, n_colon, double_colon_index;
270 n_hex_quads = hex_quad = n_hex_digits = n_colon = 0;
271 double_colon_index = ARRAY_LEN (hex_quads);
272 while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT)
275 if (c >= '0' && c <= '9')
277 else if (c >= 'a' && c <= 'f')
278 hex_digit = c + 10 - 'a';
279 else if (c >= 'A' && c <= 'F')
280 hex_digit = c + 10 - 'A';
281 else if (c == ':' && n_colon < 2)
285 unformat_put_input (input);
289 /* Too many hex quads. */
290 if (n_hex_quads >= ARRAY_LEN (hex_quads))
295 hex_quad = (hex_quad << 4) | hex_digit;
297 /* Hex quad must fit in 16 bits. */
298 if (n_hex_digits >= 4)
305 /* Save position of :: */
308 /* More than one :: ? */
309 if (double_colon_index < ARRAY_LEN (hex_quads))
311 double_colon_index = n_hex_quads;
314 if (n_colon > 0 && n_hex_digits > 0)
316 hex_quads[n_hex_quads++] = hex_quad;
322 if (n_hex_digits > 0)
323 hex_quads[n_hex_quads++] = hex_quad;
328 /* Expand :: to appropriate number of zero hex quads. */
329 if (double_colon_index < ARRAY_LEN (hex_quads))
331 word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads;
333 for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--)
334 hex_quads[n_zero + i] = hex_quads[i];
336 for (i = 0; i < n_zero; i++)
337 hex_quads[double_colon_index + i] = 0;
339 n_hex_quads = ARRAY_LEN (hex_quads);
342 /* Too few hex quads given. */
343 if (n_hex_quads < ARRAY_LEN (hex_quads))
346 for (i = 0; i < ARRAY_LEN (hex_quads); i++)
347 result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]);
354 unformat_ipsec_policy_action (unformat_input_t * input, va_list * args)
356 u32 *r = va_arg (*args, u32 *);
359 #define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f;
360 foreach_ipsec_policy_action
368 format_ipsec_crypto_alg (u8 * s, va_list * args)
370 u32 i = va_arg (*args, u32);
375 #define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break;
376 foreach_ipsec_crypto_alg
379 return format (s, "unknown");
381 return format (s, "%s", t);
385 format_ipsec_integ_alg (u8 * s, va_list * args)
387 u32 i = va_arg (*args, u32);
392 #define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break;
393 foreach_ipsec_integ_alg
396 return format (s, "unknown");
398 return format (s, "%s", t);
401 #else /* VPP_API_TEST_BUILTIN == 1 */
403 api_unformat_sw_if_index (unformat_input_t * input, va_list * args)
405 vat_main_t *vam __clib_unused = va_arg (*args, vat_main_t *);
406 vnet_main_t *vnm = vnet_get_main ();
407 u32 *result = va_arg (*args, u32 *);
409 return unformat (input, "%U", unformat_vnet_sw_interface, vnm, result);
412 #endif /* VPP_API_TEST_BUILTIN */
414 #if (VPP_API_TEST_BUILTIN==0)
416 static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT;
417 static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG;
418 static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG;
419 static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT;
422 unformat_mfib_itf_flags (unformat_input_t * input, va_list * args)
424 mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *);
425 mfib_itf_attribute_t attr;
428 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
430 if (unformat (input, mfib_itf_flag_long_names[attr]))
431 *iflags |= (1 << attr);
433 FOR_EACH_MFIB_ITF_ATTRIBUTE (attr)
435 if (unformat (input, mfib_itf_flag_names[attr]))
436 *iflags |= (1 << attr);
439 return (old == *iflags ? 0 : 1);
443 unformat_mfib_entry_flags (unformat_input_t * input, va_list * args)
445 mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *);
446 mfib_entry_attribute_t attr;
449 FOR_EACH_MFIB_ATTRIBUTE (attr)
451 if (unformat (input, mfib_flag_long_names[attr]))
452 *eflags |= (1 << attr);
454 FOR_EACH_MFIB_ATTRIBUTE (attr)
456 if (unformat (input, mfib_flag_names[attr]))
457 *eflags |= (1 << attr);
460 return (old == *eflags ? 0 : 1);
464 format_ip4_address (u8 * s, va_list * args)
466 u8 *a = va_arg (*args, u8 *);
467 return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
471 format_ip6_address (u8 * s, va_list * args)
473 ip6_address_t *a = va_arg (*args, ip6_address_t *);
474 u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
476 i_max_n_zero = ARRAY_LEN (a->as_u16);
478 i_first_zero = i_max_n_zero;
480 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
482 u32 is_zero = a->as_u16[i] == 0;
483 if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
489 if ((!is_zero && n_zeros > max_n_zeros)
490 || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
492 i_max_n_zero = i_first_zero;
493 max_n_zeros = n_zeros;
494 i_first_zero = ARRAY_LEN (a->as_u16);
499 last_double_colon = 0;
500 for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
502 if (i == i_max_n_zero && max_n_zeros > 1)
504 s = format (s, "::");
505 i += max_n_zeros - 1;
506 last_double_colon = 1;
510 s = format (s, "%s%x",
511 (last_double_colon || i == 0) ? "" : ":",
512 clib_net_to_host_u16 (a->as_u16[i]));
513 last_double_colon = 0;
520 /* Format an IP46 address. */
522 format_ip46_address (u8 * s, va_list * args)
524 ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
525 ip46_type_t type = va_arg (*args, ip46_type_t);
531 is_ip4 = ip46_address_is_ip4 (ip46);
542 format (s, "%U", format_ip4_address, &ip46->ip4) :
543 format (s, "%U", format_ip6_address, &ip46->ip6);
547 format_ethernet_address (u8 * s, va_list * args)
549 u8 *a = va_arg (*args, u8 *);
551 return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
552 a[0], a[1], a[2], a[3], a[4], a[5]);
557 ip_set (ip46_address_t * dst, void *src, u8 is_ip4)
560 dst->ip4.as_u32 = ((ip4_address_t *) src)->as_u32;
562 clib_memcpy_fast (&dst->ip6, (ip6_address_t *) src,
563 sizeof (ip6_address_t));
567 #define vl_api_bridge_domain_details_t_endian vl_noop_handler
568 #define vl_api_bridge_domain_details_t_print vl_noop_handler
570 static void vl_api_get_first_msg_id_reply_t_handler
571 (vl_api_get_first_msg_id_reply_t * mp)
573 vat_main_t *vam = &vat_main;
574 i32 retval = ntohl (mp->retval);
578 vam->async_errors += (retval < 0);
582 vam->retval = retval;
583 vam->result_ready = 1;
587 errmsg ("first message id %d", ntohs (mp->first_msg_id));
591 static void vl_api_get_first_msg_id_reply_t_handler_json
592 (vl_api_get_first_msg_id_reply_t * mp)
594 vat_main_t *vam = &vat_main;
595 vat_json_node_t node;
597 vat_json_init_object (&node);
598 vat_json_object_add_int (&node, "retval", ntohl (mp->retval));
599 vat_json_object_add_uint (&node, "first_msg_id",
600 (uint) ntohs (mp->first_msg_id));
602 vat_json_print (vam->ofp, &node);
603 vat_json_free (&node);
605 vam->retval = ntohl (mp->retval);
606 vam->result_ready = 1;
609 /* Format hex dump. */
611 format_hex_bytes (u8 * s, va_list * va)
613 u8 *bytes = va_arg (*va, u8 *);
614 int n_bytes = va_arg (*va, int);
617 /* Print short or long form depending on byte count. */
618 uword short_form = n_bytes <= 32;
619 u32 indent = format_get_indent (s);
624 for (i = 0; i < n_bytes; i++)
626 if (!short_form && (i % 32) == 0)
627 s = format (s, "%08x: ", i);
628 s = format (s, "%02x", bytes[i]);
629 if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes)
630 s = format (s, "\n%U", format_white_space, indent);
637 vl_api_control_ping_reply_t_handler (vl_api_control_ping_reply_t *mp)
639 vat_main_t *vam = &vat_main;
640 i32 retval = ntohl (mp->retval);
643 vam->async_errors += (retval < 0);
647 vam->retval = retval;
648 vam->result_ready = 1;
650 if (vam->socket_client_main)
651 vam->socket_client_main->control_pings_outstanding--;
655 vl_api_control_ping_reply_t_handler_json (vl_api_control_ping_reply_t *mp)
657 vat_main_t *vam = &vat_main;
658 i32 retval = ntohl (mp->retval);
660 if (VAT_JSON_NONE != vam->json_tree.type)
662 vat_json_print (vam->ofp, &vam->json_tree);
663 vat_json_free (&vam->json_tree);
664 vam->json_tree.type = VAT_JSON_NONE;
669 vat_json_init_array (&vam->json_tree);
670 vat_json_print (vam->ofp, &vam->json_tree);
671 vam->json_tree.type = VAT_JSON_NONE;
674 vam->retval = retval;
675 vam->result_ready = 1;
679 * Generate boilerplate reply handlers, which
680 * dig the return value out of the xxx_reply_t API message,
681 * stick it into vam->retval, and set vam->result_ready
683 * Could also do this by pointing N message decode slots at
684 * a single function, but that could break in subtle ways.
687 #define foreach_standard_reply_retval_handler
690 static void vl_api_##n##_t_handler \
691 (vl_api_##n##_t * mp) \
693 vat_main_t * vam = &vat_main; \
694 i32 retval = ntohl(mp->retval); \
695 if (vam->async_mode) { \
696 vam->async_errors += (retval < 0); \
698 vam->retval = retval; \
699 vam->result_ready = 1; \
702 foreach_standard_reply_retval_handler;
706 static void vl_api_##n##_t_handler_json \
707 (vl_api_##n##_t * mp) \
709 vat_main_t * vam = &vat_main; \
710 vat_json_node_t node; \
711 vat_json_init_object(&node); \
712 vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \
713 vat_json_print(vam->ofp, &node); \
714 vam->retval = ntohl(mp->retval); \
715 vam->result_ready = 1; \
717 foreach_standard_reply_retval_handler;
721 * Table of message reply handlers, must include boilerplate handlers
725 #define foreach_vpe_api_reply_msg \
726 _ (GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \
727 _ (CONTROL_PING_REPLY, control_ping_reply)
729 #define foreach_standalone_reply_msg \
737 #define STR_VTR_OP_CASE(op) \
738 case L2_VTR_ ## op: \
742 str_vtr_op (u32 vtr_op)
746 STR_VTR_OP_CASE (DISABLED);
747 STR_VTR_OP_CASE (PUSH_1);
748 STR_VTR_OP_CASE (PUSH_2);
749 STR_VTR_OP_CASE (POP_1);
750 STR_VTR_OP_CASE (POP_2);
751 STR_VTR_OP_CASE (TRANSLATE_1_1);
752 STR_VTR_OP_CASE (TRANSLATE_1_2);
753 STR_VTR_OP_CASE (TRANSLATE_2_1);
754 STR_VTR_OP_CASE (TRANSLATE_2_2);
761 unformat_vlib_pci_addr (unformat_input_t *input, va_list *args)
763 vlib_pci_addr_t *addr = va_arg (*args, vlib_pci_addr_t *);
766 if (!unformat (input, "%x:%x:%x.%x", &x[0], &x[1], &x[2], &x[3]))
772 addr->function = x[3];
778 unformat_fib_path (unformat_input_t *input, va_list *args)
780 vat_main_t *vam = va_arg (*args, vat_main_t *);
781 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
782 u32 weight, preference;
783 mpls_label_t out_label;
785 clib_memset (path, 0, sizeof (*path));
787 path->sw_if_index = ~0;
791 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
793 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
794 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
797 path->proto = FIB_API_PATH_NH_PROTO_IP4;
799 else if (unformat (input, "%U %U",
800 unformat_vl_api_ip6_address,
801 &path->nh.address.ip6,
802 api_unformat_sw_if_index, vam, &path->sw_if_index))
804 path->proto = FIB_API_PATH_NH_PROTO_IP6;
806 else if (unformat (input, "weight %u", &weight))
808 path->weight = weight;
810 else if (unformat (input, "preference %u", &preference))
812 path->preference = preference;
814 else if (unformat (input, "%U next-hop-table %d",
815 unformat_vl_api_ip4_address,
816 &path->nh.address.ip4, &path->table_id))
818 path->proto = FIB_API_PATH_NH_PROTO_IP4;
820 else if (unformat (input, "%U next-hop-table %d",
821 unformat_vl_api_ip6_address,
822 &path->nh.address.ip6, &path->table_id))
824 path->proto = FIB_API_PATH_NH_PROTO_IP6;
826 else if (unformat (input, "%U",
827 unformat_vl_api_ip4_address, &path->nh.address.ip4))
830 * the recursive next-hops are by default in the default table
833 path->sw_if_index = ~0;
834 path->proto = FIB_API_PATH_NH_PROTO_IP4;
836 else if (unformat (input, "%U",
837 unformat_vl_api_ip6_address, &path->nh.address.ip6))
840 * the recursive next-hops are by default in the default table
843 path->sw_if_index = ~0;
844 path->proto = FIB_API_PATH_NH_PROTO_IP6;
846 else if (unformat (input, "resolve-via-host"))
848 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
850 else if (unformat (input, "resolve-via-attached"))
852 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
854 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
856 path->type = FIB_API_PATH_TYPE_LOCAL;
857 path->sw_if_index = ~0;
858 path->proto = FIB_API_PATH_NH_PROTO_IP4;
860 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
862 path->type = FIB_API_PATH_TYPE_LOCAL;
863 path->sw_if_index = ~0;
864 path->proto = FIB_API_PATH_NH_PROTO_IP6;
866 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
868 else if (unformat (input, "via-label %d", &path->nh.via_label))
870 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
871 path->sw_if_index = ~0;
873 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
875 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
876 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
878 else if (unformat (input, "local"))
880 path->type = FIB_API_PATH_TYPE_LOCAL;
882 else if (unformat (input, "out-labels"))
884 while (unformat (input, "%d", &out_label))
886 path->label_stack[path->n_labels].label = out_label;
887 path->label_stack[path->n_labels].is_uniform = 0;
888 path->label_stack[path->n_labels].ttl = 64;
892 else if (unformat (input, "via"))
894 /* new path, back up and return */
895 unformat_put_input (input);
896 unformat_put_input (input);
897 unformat_put_input (input);
898 unformat_put_input (input);
907 path->proto = ntohl (path->proto);
908 path->type = ntohl (path->type);
909 path->flags = ntohl (path->flags);
910 path->table_id = ntohl (path->table_id);
911 path->sw_if_index = ntohl (path->sw_if_index);
916 #define foreach_create_subif_bit \
923 _(outer_vlan_id_any) \
926 #define foreach_create_subif_flag \
931 _(4, "exact_match") \
932 _(5, "default_sub") \
933 _(6, "outer_vlan_id_any") \
934 _(7, "inner_vlan_id_any")
937 #define foreach_tcp_proto_field \
941 #define foreach_udp_proto_field \
945 #define foreach_ip4_proto_field \
957 u16 src_port, dst_port;
960 #if VPP_API_TEST_BUILTIN == 0
962 unformat_tcp_mask (unformat_input_t *input, va_list *args)
964 u8 **maskp = va_arg (*args, u8 **);
966 u8 found_something = 0;
969 #define _(a) u8 a = 0;
970 foreach_tcp_proto_field;
973 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
977 #define _(a) else if (unformat (input, #a)) a = 1;
978 foreach_tcp_proto_field
983 #define _(a) found_something += a;
984 foreach_tcp_proto_field;
987 if (found_something == 0)
990 vec_validate (mask, sizeof (*tcp) - 1);
992 tcp = (tcp_header_t *) mask;
996 clib_memset (&tcp->a, 0xff, sizeof (tcp->a));
997 foreach_tcp_proto_field;
1005 unformat_udp_mask (unformat_input_t *input, va_list *args)
1007 u8 **maskp = va_arg (*args, u8 **);
1009 u8 found_something = 0;
1012 #define _(a) u8 a = 0;
1013 foreach_udp_proto_field;
1016 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1020 #define _(a) else if (unformat (input, #a)) a = 1;
1021 foreach_udp_proto_field
1026 #define _(a) found_something += a;
1027 foreach_udp_proto_field;
1030 if (found_something == 0)
1033 vec_validate (mask, sizeof (*udp) - 1);
1035 udp = (udp_header_t *) mask;
1039 clib_memset (&udp->a, 0xff, sizeof (udp->a));
1040 foreach_udp_proto_field;
1048 unformat_l4_mask (unformat_input_t *input, va_list *args)
1050 u8 **maskp = va_arg (*args, u8 **);
1051 u16 src_port = 0, dst_port = 0;
1052 tcpudp_header_t *tcpudp;
1054 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1056 if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
1058 else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
1060 else if (unformat (input, "src_port"))
1062 else if (unformat (input, "dst_port"))
1068 if (!src_port && !dst_port)
1072 vec_validate (mask, sizeof (tcpudp_header_t) - 1);
1074 tcpudp = (tcpudp_header_t *) mask;
1075 tcpudp->src_port = src_port;
1076 tcpudp->dst_port = dst_port;
1084 unformat_ip4_mask (unformat_input_t * input, va_list * args)
1086 u8 **maskp = va_arg (*args, u8 **);
1088 u8 found_something = 0;
1091 #define _(a) u8 a=0;
1092 foreach_ip4_proto_field;
1098 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1100 if (unformat (input, "version"))
1102 else if (unformat (input, "hdr_length"))
1104 else if (unformat (input, "src"))
1106 else if (unformat (input, "dst"))
1108 else if (unformat (input, "proto"))
1111 #define _(a) else if (unformat (input, #a)) a=1;
1112 foreach_ip4_proto_field
1118 #define _(a) found_something += a;
1119 foreach_ip4_proto_field;
1122 if (found_something == 0)
1125 vec_validate (mask, sizeof (*ip) - 1);
1127 ip = (ip4_header_t *) mask;
1129 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
1130 foreach_ip4_proto_field;
1133 ip->ip_version_and_header_length = 0;
1136 ip->ip_version_and_header_length |= 0xF0;
1139 ip->ip_version_and_header_length |= 0x0F;
1145 #define foreach_ip6_proto_field \
1153 unformat_ip6_mask (unformat_input_t * input, va_list * args)
1155 u8 **maskp = va_arg (*args, u8 **);
1157 u8 found_something = 0;
1159 u32 ip_version_traffic_class_and_flow_label;
1161 #define _(a) u8 a=0;
1162 foreach_ip6_proto_field;
1165 u8 traffic_class = 0;
1168 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1170 if (unformat (input, "version"))
1172 else if (unformat (input, "traffic-class"))
1174 else if (unformat (input, "flow-label"))
1176 else if (unformat (input, "src"))
1178 else if (unformat (input, "dst"))
1180 else if (unformat (input, "proto"))
1183 #define _(a) else if (unformat (input, #a)) a=1;
1184 foreach_ip6_proto_field
1190 #define _(a) found_something += a;
1191 foreach_ip6_proto_field;
1194 if (found_something == 0)
1197 vec_validate (mask, sizeof (*ip) - 1);
1199 ip = (ip6_header_t *) mask;
1201 #define _(a) if (a) clib_memset (&ip->a, 0xff, sizeof (ip->a));
1202 foreach_ip6_proto_field;
1205 ip_version_traffic_class_and_flow_label = 0;
1208 ip_version_traffic_class_and_flow_label |= 0xF0000000;
1211 ip_version_traffic_class_and_flow_label |= 0x0FF00000;
1214 ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
1216 ip->ip_version_traffic_class_and_flow_label =
1217 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1224 unformat_l3_mask (unformat_input_t * input, va_list * args)
1226 u8 **maskp = va_arg (*args, u8 **);
1228 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1230 if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
1232 else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
1241 unformat_l2_mask (unformat_input_t * input, va_list * args)
1243 u8 **maskp = va_arg (*args, u8 **);
1258 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1260 if (unformat (input, "src"))
1262 else if (unformat (input, "dst"))
1264 else if (unformat (input, "proto"))
1266 else if (unformat (input, "tag1"))
1268 else if (unformat (input, "tag2"))
1270 else if (unformat (input, "ignore-tag1"))
1272 else if (unformat (input, "ignore-tag2"))
1274 else if (unformat (input, "cos1"))
1276 else if (unformat (input, "cos2"))
1278 else if (unformat (input, "dot1q"))
1280 else if (unformat (input, "dot1ad"))
1285 if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
1286 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1289 if (tag1 || ignore_tag1 || cos1 || dot1q)
1291 if (tag2 || ignore_tag2 || cos2 || dot1ad)
1294 vec_validate (mask, len - 1);
1297 clib_memset (mask, 0xff, 6);
1300 clib_memset (mask + 6, 0xff, 6);
1304 /* inner vlan tag */
1313 mask[21] = mask[20] = 0xff;
1334 mask[16] = mask[17] = 0xff;
1344 mask[12] = mask[13] = 0xff;
1351 unformat_classify_mask (unformat_input_t * input, va_list * args)
1353 u8 **maskp = va_arg (*args, u8 **);
1354 u32 *skipp = va_arg (*args, u32 *);
1355 u32 *matchp = va_arg (*args, u32 *);
1363 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1365 if (unformat (input, "hex %U", unformat_hex_string, &mask))
1367 else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
1369 else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
1371 else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
1385 if (mask || l2 || l3 || l4)
1389 /* "With a free Ethernet header in every package" */
1391 vec_validate (l2, 13);
1395 vec_append (mask, l3);
1400 vec_append (mask, l4);
1405 /* Scan forward looking for the first significant mask octet */
1406 for (i = 0; i < vec_len (mask); i++)
1410 /* compute (skip, match) params */
1411 *skipp = i / sizeof (u32x4);
1412 vec_delete (mask, *skipp * sizeof (u32x4), 0);
1414 /* Pad mask to an even multiple of the vector size */
1415 while (vec_len (mask) % sizeof (u32x4))
1418 match = vec_len (mask) / sizeof (u32x4);
1420 for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
1422 u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
1423 if (*tmp || *(tmp + 1))
1428 clib_warning ("BUG: match 0");
1430 _vec_len (mask) = match * sizeof (u32x4);
1440 #endif /* VPP_API_TEST_BUILTIN */
1442 #define foreach_l2_next \
1444 _(ethernet, ETHERNET_INPUT) \
1449 unformat_l2_next_index (unformat_input_t * input, va_list * args)
1451 u32 *miss_next_indexp = va_arg (*args, u32 *);
1456 if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
1460 if (unformat (input, "%d", &tmp))
1469 *miss_next_indexp = next_index;
1473 #define foreach_ip_next \
1479 api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
1481 u32 *miss_next_indexp = va_arg (*args, u32 *);
1486 if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
1490 if (unformat (input, "%d", &tmp))
1499 *miss_next_indexp = next_index;
1503 #define foreach_acl_next \
1507 api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
1509 u32 *miss_next_indexp = va_arg (*args, u32 *);
1514 if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
1518 if (unformat (input, "permit"))
1523 else if (unformat (input, "%d", &tmp))
1532 *miss_next_indexp = next_index;
1537 unformat_policer_precolor (unformat_input_t * input, va_list * args)
1539 u32 *r = va_arg (*args, u32 *);
1541 if (unformat (input, "conform-color"))
1542 *r = POLICE_CONFORM;
1543 else if (unformat (input, "exceed-color"))
1551 #if VPP_API_TEST_BUILTIN == 0
1553 unformat_l4_match (unformat_input_t * input, va_list * args)
1555 u8 **matchp = va_arg (*args, u8 **);
1557 u8 *proto_header = 0;
1563 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1565 if (unformat (input, "src_port %d", &src_port))
1567 else if (unformat (input, "dst_port %d", &dst_port))
1573 h.src_port = clib_host_to_net_u16 (src_port);
1574 h.dst_port = clib_host_to_net_u16 (dst_port);
1575 vec_validate (proto_header, sizeof (h) - 1);
1576 memcpy (proto_header, &h, sizeof (h));
1578 *matchp = proto_header;
1584 unformat_ip4_match (unformat_input_t * input, va_list * args)
1586 u8 **matchp = va_arg (*args, u8 **);
1593 int src = 0, dst = 0;
1594 ip4_address_t src_val, dst_val;
1601 int fragment_id = 0;
1602 u32 fragment_id_val;
1608 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1610 if (unformat (input, "version %d", &version_val))
1612 else if (unformat (input, "hdr_length %d", &hdr_length_val))
1614 else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
1616 else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
1618 else if (unformat (input, "proto %d", &proto_val))
1620 else if (unformat (input, "tos %d", &tos_val))
1622 else if (unformat (input, "length %d", &length_val))
1624 else if (unformat (input, "fragment_id %d", &fragment_id_val))
1626 else if (unformat (input, "ttl %d", &ttl_val))
1628 else if (unformat (input, "checksum %d", &checksum_val))
1634 if (version + hdr_length + src + dst + proto + tos + length + fragment_id
1635 + ttl + checksum == 0)
1639 * Aligned because we use the real comparison functions
1641 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1643 ip = (ip4_header_t *) match;
1645 /* These are realistically matched in practice */
1647 ip->src_address.as_u32 = src_val.as_u32;
1650 ip->dst_address.as_u32 = dst_val.as_u32;
1653 ip->protocol = proto_val;
1656 /* These are not, but they're included for completeness */
1658 ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
1661 ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
1667 ip->length = clib_host_to_net_u16 (length_val);
1673 ip->checksum = clib_host_to_net_u16 (checksum_val);
1680 unformat_ip6_match (unformat_input_t * input, va_list * args)
1682 u8 **matchp = va_arg (*args, u8 **);
1687 u8 traffic_class = 0;
1688 u32 traffic_class_val = 0;
1691 int src = 0, dst = 0;
1692 ip6_address_t src_val, dst_val;
1695 int payload_length = 0;
1696 u32 payload_length_val;
1699 u32 ip_version_traffic_class_and_flow_label;
1701 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1703 if (unformat (input, "version %d", &version_val))
1705 else if (unformat (input, "traffic_class %d", &traffic_class_val))
1707 else if (unformat (input, "flow_label %d", &flow_label_val))
1709 else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
1711 else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
1713 else if (unformat (input, "proto %d", &proto_val))
1715 else if (unformat (input, "payload_length %d", &payload_length_val))
1717 else if (unformat (input, "hop_limit %d", &hop_limit_val))
1723 if (version + traffic_class + flow_label + src + dst + proto +
1724 payload_length + hop_limit == 0)
1728 * Aligned because we use the real comparison functions
1730 vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
1732 ip = (ip6_header_t *) match;
1735 clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
1738 clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
1741 ip->protocol = proto_val;
1743 ip_version_traffic_class_and_flow_label = 0;
1746 ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
1749 ip_version_traffic_class_and_flow_label |=
1750 (traffic_class_val & 0xFF) << 20;
1753 ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
1755 ip->ip_version_traffic_class_and_flow_label =
1756 clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
1759 ip->payload_length = clib_host_to_net_u16 (payload_length_val);
1762 ip->hop_limit = hop_limit_val;
1769 unformat_l3_match (unformat_input_t * input, va_list * args)
1771 u8 **matchp = va_arg (*args, u8 **);
1773 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1775 if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
1777 else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
1786 unformat_vlan_tag (unformat_input_t * input, va_list * args)
1788 u8 *tagp = va_arg (*args, u8 *);
1791 if (unformat (input, "%d", &tag))
1793 tagp[0] = (tag >> 8) & 0x0F;
1794 tagp[1] = tag & 0xFF;
1802 unformat_l2_match (unformat_input_t * input, va_list * args)
1804 u8 **matchp = va_arg (*args, u8 **);
1824 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1826 if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
1829 if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
1831 else if (unformat (input, "proto %U",
1832 unformat_ethernet_type_host_byte_order, &proto_val))
1834 else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
1836 else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
1838 else if (unformat (input, "ignore-tag1"))
1840 else if (unformat (input, "ignore-tag2"))
1842 else if (unformat (input, "cos1 %d", &cos1_val))
1844 else if (unformat (input, "cos2 %d", &cos2_val))
1849 if ((src + dst + proto + tag1 + tag2 +
1850 ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
1853 if (tag1 || ignore_tag1 || cos1)
1855 if (tag2 || ignore_tag2 || cos2)
1858 vec_validate_aligned (match, len - 1, sizeof (u32x4));
1861 clib_memcpy (match, dst_val, 6);
1864 clib_memcpy (match + 6, src_val, 6);
1868 /* inner vlan tag */
1869 match[19] = tag2_val[1];
1870 match[18] = tag2_val[0];
1872 match[18] |= (cos2_val & 0x7) << 5;
1875 match[21] = proto_val & 0xff;
1876 match[20] = proto_val >> 8;
1880 match[15] = tag1_val[1];
1881 match[14] = tag1_val[0];
1884 match[14] |= (cos1_val & 0x7) << 5;
1890 match[15] = tag1_val[1];
1891 match[14] = tag1_val[0];
1894 match[17] = proto_val & 0xff;
1895 match[16] = proto_val >> 8;
1898 match[14] |= (cos1_val & 0x7) << 5;
1904 match[18] |= (cos2_val & 0x7) << 5;
1906 match[14] |= (cos1_val & 0x7) << 5;
1909 match[13] = proto_val & 0xff;
1910 match[12] = proto_val >> 8;
1918 unformat_qos_source (unformat_input_t * input, va_list * args)
1920 int *qs = va_arg (*args, int *);
1922 if (unformat (input, "ip"))
1923 *qs = QOS_SOURCE_IP;
1924 else if (unformat (input, "mpls"))
1925 *qs = QOS_SOURCE_MPLS;
1926 else if (unformat (input, "ext"))
1927 *qs = QOS_SOURCE_EXT;
1928 else if (unformat (input, "vlan"))
1929 *qs = QOS_SOURCE_VLAN;
1938 api_unformat_classify_match (unformat_input_t * input, va_list * args)
1940 u8 **matchp = va_arg (*args, u8 **);
1941 u32 skip_n_vectors = va_arg (*args, u32);
1942 u32 match_n_vectors = va_arg (*args, u32);
1949 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1951 if (unformat (input, "hex %U", unformat_hex_string, &match))
1953 else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
1955 else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
1957 else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
1971 if (match || l2 || l3 || l4)
1975 /* "Win a free Ethernet header in every packet" */
1977 vec_validate_aligned (l2, 13, sizeof (u32x4));
1981 vec_append_aligned (match, l3, sizeof (u32x4));
1986 vec_append_aligned (match, l4, sizeof (u32x4));
1991 /* Make sure the vector is big enough even if key is all 0's */
1992 vec_validate_aligned
1993 (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
1996 /* Set size, include skipped vectors */
1997 _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
2007 #define foreach_vtr_op \
2008 _ ("disable", L2_VTR_DISABLED) \
2009 _ ("push-1", L2_VTR_PUSH_1) \
2010 _ ("push-2", L2_VTR_PUSH_2) \
2011 _ ("pop-1", L2_VTR_POP_1) \
2012 _ ("pop-2", L2_VTR_POP_2) \
2013 _ ("translate-1-1", L2_VTR_TRANSLATE_1_1) \
2014 _ ("translate-1-2", L2_VTR_TRANSLATE_1_2) \
2015 _ ("translate-2-1", L2_VTR_TRANSLATE_2_1) \
2016 _ ("translate-2-2", L2_VTR_TRANSLATE_2_2)
2019 api_get_first_msg_id (vat_main_t *vam)
2021 vl_api_get_first_msg_id_t *mp;
2022 unformat_input_t *i = vam->input;
2027 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2029 if (unformat (i, "client %s", &name))
2037 errmsg ("missing client name");
2042 if (vec_len (name) > 63)
2044 errmsg ("client name too long");
2048 M (GET_FIRST_MSG_ID, mp);
2049 clib_memcpy (mp->name, name, vec_len (name));
2055 #define foreach_pbb_vtr_op \
2056 _("disable", L2_VTR_DISABLED) \
2057 _("pop", L2_VTR_POP_2) \
2058 _("push", L2_VTR_PUSH_2)
2061 api_sock_init_shm (vat_main_t * vam)
2063 #if VPP_API_TEST_BUILTIN == 0
2064 unformat_input_t *i = vam->input;
2065 vl_api_shm_elem_config_t *config = 0;
2066 u64 size = 64 << 20;
2069 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
2071 if (unformat (i, "size %U", unformat_memory_size, &size))
2078 * Canned custom ring allocator config.
2079 * Should probably parse all of this
2081 vec_validate (config, 6);
2082 config[0].type = VL_API_VLIB_RING;
2083 config[0].size = 256;
2084 config[0].count = 32;
2086 config[1].type = VL_API_VLIB_RING;
2087 config[1].size = 1024;
2088 config[1].count = 16;
2090 config[2].type = VL_API_VLIB_RING;
2091 config[2].size = 4096;
2092 config[2].count = 2;
2094 config[3].type = VL_API_CLIENT_RING;
2095 config[3].size = 256;
2096 config[3].count = 32;
2098 config[4].type = VL_API_CLIENT_RING;
2099 config[4].size = 1024;
2100 config[4].count = 16;
2102 config[5].type = VL_API_CLIENT_RING;
2103 config[5].size = 4096;
2104 config[5].count = 2;
2106 config[6].type = VL_API_QUEUE;
2107 config[6].count = 128;
2108 config[6].size = sizeof (uword);
2110 rv = vl_socket_client_init_shm (config, 1 /* want_pthread */ );
2112 vam->client_index_invalid = 1;
2120 q_or_quit (vat_main_t * vam)
2122 #if VPP_API_TEST_BUILTIN == 0
2123 longjmp (vam->jump_buf, 1);
2125 return 0; /* not so much */
2129 q (vat_main_t * vam)
2131 return q_or_quit (vam);
2135 quit (vat_main_t * vam)
2137 return q_or_quit (vam);
2141 comment (vat_main_t * vam)
2147 elog_save (vat_main_t * vam)
2149 #if VPP_API_TEST_BUILTIN == 0
2150 elog_main_t *em = &vam->elog_main;
2151 unformat_input_t *i = vam->input;
2152 char *file, *chroot_file;
2153 clib_error_t *error;
2155 if (!unformat (i, "%s", &file))
2157 errmsg ("expected file name, got `%U'", format_unformat_error, i);
2161 /* It's fairly hard to get "../oopsie" through unformat; just in case */
2162 if (strstr (file, "..") || index (file, '/'))
2164 errmsg ("illegal characters in filename '%s'", file);
2168 chroot_file = (char *) format (0, "/tmp/%s%c", file, 0);
2172 errmsg ("Saving %wd of %wd events to %s",
2173 elog_n_events_in_buffer (em),
2174 elog_buffer_capacity (em), chroot_file);
2176 error = elog_write_file (em, chroot_file, 1 /* flush ring */ );
2177 vec_free (chroot_file);
2180 clib_error_report (error);
2182 errmsg ("Use the vpp event loger...");
2189 elog_setup (vat_main_t * vam)
2191 #if VPP_API_TEST_BUILTIN == 0
2192 elog_main_t *em = &vam->elog_main;
2193 unformat_input_t *i = vam->input;
2194 u32 nevents = 128 << 10;
2196 (void) unformat (i, "nevents %d", &nevents);
2198 elog_init (em, nevents);
2199 vl_api_set_elog_main (em);
2200 vl_api_set_elog_trace_api_messages (1);
2201 errmsg ("Event logger initialized with %u events", nevents);
2203 errmsg ("Use the vpp event loger...");
2209 elog_enable (vat_main_t * vam)
2211 #if VPP_API_TEST_BUILTIN == 0
2212 elog_main_t *em = &vam->elog_main;
2214 elog_enable_disable (em, 1 /* enable */ );
2215 vl_api_set_elog_trace_api_messages (1);
2216 errmsg ("Event logger enabled...");
2218 errmsg ("Use the vpp event loger...");
2224 elog_disable (vat_main_t * vam)
2226 #if VPP_API_TEST_BUILTIN == 0
2227 elog_main_t *em = &vam->elog_main;
2229 elog_enable_disable (em, 0 /* enable */ );
2230 vl_api_set_elog_trace_api_messages (1);
2231 errmsg ("Event logger disabled...");
2233 errmsg ("Use the vpp event loger...");
2239 statseg (vat_main_t * vam)
2241 ssvm_private_t *ssvmp = &vam->stat_segment;
2242 ssvm_shared_header_t *shared_header = ssvmp->sh;
2243 vlib_counter_t **counters;
2244 u64 thread0_index1_packets;
2245 u64 thread0_index1_bytes;
2246 f64 vector_rate, input_rate;
2249 uword *counter_vector_by_name;
2250 if (vam->stat_segment_lockp == 0)
2252 errmsg ("Stat segment not mapped...");
2256 /* look up "/if/rx for sw_if_index 1 as a test */
2258 clib_spinlock_lock (vam->stat_segment_lockp);
2260 counter_vector_by_name = (uword *) shared_header->opaque[1];
2262 p = hash_get_mem (counter_vector_by_name, "/if/rx");
2265 clib_spinlock_unlock (vam->stat_segment_lockp);
2266 errmsg ("/if/tx not found?");
2270 /* Fish per-thread vector of combined counters from shared memory */
2271 counters = (vlib_counter_t **) p[0];
2273 if (vec_len (counters[0]) < 2)
2275 clib_spinlock_unlock (vam->stat_segment_lockp);
2276 errmsg ("/if/tx vector length %d", vec_len (counters[0]));
2280 /* Read thread 0 sw_if_index 1 counter */
2281 thread0_index1_packets = counters[0][1].packets;
2282 thread0_index1_bytes = counters[0][1].bytes;
2284 p = hash_get_mem (counter_vector_by_name, "vector_rate");
2287 clib_spinlock_unlock (vam->stat_segment_lockp);
2288 errmsg ("vector_rate not found?");
2292 vector_rate = *(f64 *) (p[0]);
2293 p = hash_get_mem (counter_vector_by_name, "input_rate");
2296 clib_spinlock_unlock (vam->stat_segment_lockp);
2297 errmsg ("input_rate not found?");
2300 input_rate = *(f64 *) (p[0]);
2302 clib_spinlock_unlock (vam->stat_segment_lockp);
2304 print (vam->ofp, "vector_rate %.2f input_rate %.2f",
2305 vector_rate, input_rate);
2306 print (vam->ofp, "thread 0 sw_if_index 1 rx pkts %lld, bytes %lld",
2307 thread0_index1_packets, thread0_index1_bytes);
2313 cmd_cmp (void *a1, void *a2)
2318 return strcmp ((char *) (c1[0]), (char *) (c2[0]));
2322 help (vat_main_t * vam)
2327 unformat_input_t *i = vam->input;
2330 if (unformat (i, "%s", &name))
2336 hs = hash_get_mem (vam->help_by_name, name);
2338 print (vam->ofp, "usage: %s %s", name, hs[0]);
2340 print (vam->ofp, "No such msg / command '%s'", name);
2345 print (vam->ofp, "Help is available for the following:");
2347 hash_foreach_pair (p, vam->function_by_name,
2349 vec_add1 (cmds, (u8 *)(p->key));
2352 vec_sort_with_function (cmds, cmd_cmp);
2354 for (j = 0; j < vec_len (cmds); j++)
2355 print (vam->ofp, "%s", cmds[j]);
2362 set (vat_main_t * vam)
2364 u8 *name = 0, *value = 0;
2365 unformat_input_t *i = vam->input;
2367 if (unformat (i, "%s", &name))
2369 /* The input buffer is a vector, not a string. */
2370 value = vec_dup (i->buffer);
2371 vec_delete (value, i->index, 0);
2372 /* Almost certainly has a trailing newline */
2373 if (value[vec_len (value) - 1] == '\n')
2374 value[vec_len (value) - 1] = 0;
2375 /* Make sure it's a proper string, one way or the other */
2376 vec_add1 (value, 0);
2377 (void) clib_macro_set_value (&vam->macro_main,
2378 (char *) name, (char *) value);
2381 errmsg ("usage: set <name> <value>");
2389 unset (vat_main_t * vam)
2393 if (unformat (vam->input, "%s", &name))
2394 if (clib_macro_unset (&vam->macro_main, (char *) name) == 1)
2395 errmsg ("unset: %s wasn't set", name);
2408 macro_sort_cmp (void *a1, void *a2)
2410 macro_sort_t *s1 = a1;
2411 macro_sort_t *s2 = a2;
2413 return strcmp ((char *) (s1->name), (char *) (s2->name));
2417 dump_macro_table (vat_main_t * vam)
2419 macro_sort_t *sort_me = 0, *sm;
2423 hash_foreach_pair (p, vam->macro_main.the_value_table_hash, ({
2424 vec_add2 (sort_me, sm, 1);
2425 sm->name = (u8 *) (p->key);
2426 sm->value = (u8 *) (p->value[0]);
2429 vec_sort_with_function (sort_me, macro_sort_cmp);
2431 if (vec_len (sort_me))
2432 print (vam->ofp, "%-15s%s", "Name", "Value");
2434 print (vam->ofp, "The macro table is empty...");
2436 for (i = 0; i < vec_len (sort_me); i++)
2437 print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value);
2442 value_sort_cmp (void *a1, void *a2)
2444 name_sort_t *n1 = a1;
2445 name_sort_t *n2 = a2;
2447 if (n1->value < n2->value)
2449 if (n1->value > n2->value)
2456 dump_msg_api_table (vat_main_t * vam)
2458 api_main_t *am = vlibapi_get_main ();
2459 name_sort_t *nses = 0, *ns;
2463 hash_foreach_pair (hp, am->msg_index_by_name_and_crc,
2465 vec_add2 (nses, ns, 1);
2466 ns->name = (u8 *)(hp->key);
2467 ns->value = (u32) hp->value[0];
2470 vec_sort_with_function (nses, value_sort_cmp);
2472 for (i = 0; i < vec_len (nses); i++)
2473 print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name);
2479 get_msg_id (vat_main_t * vam)
2484 if (unformat (vam->input, "%s", &name_and_crc))
2486 message_index = vl_msg_api_get_msg_index (name_and_crc);
2487 if (message_index == ~0)
2489 print (vam->ofp, " '%s' not found", name_and_crc);
2492 print (vam->ofp, " '%s' has message index %d",
2493 name_and_crc, message_index);
2496 errmsg ("name_and_crc required...");
2501 search_node_table (vat_main_t * vam)
2503 unformat_input_t *line_input = vam->input;
2506 vlib_node_t *node, *next_node;
2509 if (vam->graph_node_index_by_name == 0)
2511 print (vam->ofp, "Node table empty, issue get_node_graph...");
2515 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
2517 if (unformat (line_input, "%s", &node_to_find))
2519 vec_add1 (node_to_find, 0);
2520 p = hash_get_mem (vam->graph_node_index_by_name, node_to_find);
2523 print (vam->ofp, "%s not found...", node_to_find);
2526 node = vam->graph_nodes[0][p[0]];
2527 print (vam->ofp, "[%d] %s", p[0], node->name);
2528 for (j = 0; j < vec_len (node->next_nodes); j++)
2530 if (node->next_nodes[j] != ~0)
2532 next_node = vam->graph_nodes[0][node->next_nodes[j]];
2533 print (vam->ofp, " [%d] %s", j, next_node->name);
2540 clib_warning ("parse error '%U'", format_unformat_error,
2546 vec_free (node_to_find);
2555 script (vat_main_t * vam)
2557 #if (VPP_API_TEST_BUILTIN==0)
2559 char *save_current_file;
2560 unformat_input_t save_input;
2561 jmp_buf save_jump_buf;
2562 u32 save_line_number;
2564 FILE *new_fp, *save_ifp;
2566 if (unformat (vam->input, "%s", &s))
2568 new_fp = fopen ((char *) s, "r");
2571 errmsg ("Couldn't open script file %s", s);
2578 errmsg ("Missing script name");
2582 clib_memcpy (&save_input, &vam->input, sizeof (save_input));
2583 clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf));
2584 save_ifp = vam->ifp;
2585 save_line_number = vam->input_line_number;
2586 save_current_file = (char *) vam->current_file;
2588 vam->input_line_number = 0;
2590 vam->current_file = s;
2593 clib_memcpy (&vam->input, &save_input, sizeof (save_input));
2594 clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf));
2595 vam->ifp = save_ifp;
2596 vam->input_line_number = save_line_number;
2597 vam->current_file = (u8 *) save_current_file;
2602 clib_warning ("use the exec command...");
2608 echo (vat_main_t * vam)
2610 print (vam->ofp, "%v", vam->input->buffer);
2614 int exec (vat_main_t *vam) __attribute__ ((weak));
2616 exec (vat_main_t *vam)
2622 name_sort_cmp (void *a1, void *a2)
2624 name_sort_t *n1 = a1;
2625 name_sort_t *n2 = a2;
2627 return strcmp ((char *) n1->name, (char *) n2->name);
2631 dump_interface_table (vat_main_t *vam)
2634 name_sort_t *nses = 0, *ns;
2636 if (vam->json_output)
2639 "JSON output supported only for VPE API calls and dump_stats_table");
2643 hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
2644 vec_add2 (nses, ns, 1);
2645 ns->name = (u8 *) (p->key);
2646 ns->value = (u32) p->value[0];
2649 vec_sort_with_function (nses, name_sort_cmp);
2651 print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index");
2652 vec_foreach (ns, nses)
2654 print (vam->ofp, "%-25s%-15d", ns->name, ns->value);
2661 dump_sub_interface_table (vat_main_t *vam)
2663 const sw_interface_subif_t *sub = NULL;
2665 if (vam->json_output)
2668 "JSON output supported only for VPE API calls and dump_stats_table");
2672 print (vam->ofp, "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s",
2673 "Interface", "sw_if_index", "sub id", "dot1ad", "tags", "outer id",
2674 "inner id", "exact", "default", "outer any", "inner any");
2676 vec_foreach (sub, vam->sw_if_subif_table)
2678 print (vam->ofp, "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d",
2679 sub->interface_name, sub->sw_if_index, sub->sub_id,
2680 sub->sub_dot1ad ? "dot1ad" : "dot1q", sub->sub_number_of_tags,
2681 sub->sub_outer_vlan_id, sub->sub_inner_vlan_id,
2682 sub->sub_exact_match, sub->sub_default,
2683 sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any);
2684 if (sub->vtr_op != L2_VTR_DISABLED)
2687 " vlan-tag-rewrite - op: %-14s [ dot1q: %d "
2688 "tag1: %d tag2: %d ]",
2689 str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q, sub->vtr_tag1,
2697 /* List of API message constructors, CLI names map to api_xxx */
2698 #define foreach_vpe_api_msg \
2699 _(get_first_msg_id, "client <name>") \
2700 _(sock_init_shm, "size <nnn>") \
2701 /* List of command functions, CLI names map directly to functions */
2702 #define foreach_cli_function \
2703 _ (comment, "usage: comment <ignore-rest-of-line>") \
2704 _ (dump_interface_table, "usage: dump_interface_table") \
2705 _ (dump_sub_interface_table, "usage: dump_sub_interface_table") \
2706 _ (dump_macro_table, "usage: dump_macro_table ") \
2707 _ (dump_msg_api_table, "usage: dump_msg_api_table") \
2708 _ (elog_setup, "usage: elog_setup [nevents, default 128K]") \
2709 _ (elog_disable, "usage: elog_disable") \
2710 _ (elog_enable, "usage: elog_enable") \
2711 _ (elog_save, "usage: elog_save <filename>") \
2712 _ (get_msg_id, "usage: get_msg_id name_and_crc") \
2713 _ (echo, "usage: echo <message>") \
2714 _ (help, "usage: help") \
2715 _ (q, "usage: quit") \
2716 _ (quit, "usage: quit") \
2717 _ (search_node_table, "usage: search_node_table <name>...") \
2718 _ (set, "usage: set <variable-name> <value>") \
2719 _ (script, "usage: script <file-name>") \
2720 _ (statseg, "usage: statseg") \
2721 _ (unset, "usage: unset <variable-name>")
2724 static void vl_api_##n##_t_handler_uni \
2725 (vl_api_##n##_t * mp) \
2727 vat_main_t * vam = &vat_main; \
2728 if (vam->json_output) { \
2729 vl_api_##n##_t_handler_json(mp); \
2731 vl_api_##n##_t_handler(mp); \
2734 foreach_vpe_api_reply_msg;
2735 #if VPP_API_TEST_BUILTIN == 0
2736 foreach_standalone_reply_msg;
2741 vat_api_hookup (vat_main_t * vam)
2744 vl_msg_api_set_handlers ( \
2745 VL_API_##N + 1, #n, vl_api_##n##_t_handler_uni, vl_noop_handler, \
2746 vl_api_##n##_t_endian, vl_api_##n##_t_print, sizeof (vl_api_##n##_t), 1, \
2747 vl_api_##n##_t_print_json, vl_api_##n##_t_tojson, \
2748 vl_api_##n##_t_fromjson, vl_api_##n##_t_calc_size);
2749 foreach_vpe_api_reply_msg;
2750 #if VPP_API_TEST_BUILTIN == 0
2751 foreach_standalone_reply_msg;
2755 #if (VPP_API_TEST_BUILTIN==0)
2756 vl_msg_api_set_first_available_msg_id (VL_MSG_MEMCLNT_LAST + 1);
2758 vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword));
2760 vam->function_by_name = hash_create_string (0, sizeof (uword));
2762 vam->help_by_name = hash_create_string (0, sizeof (uword));
2765 /* API messages we can send */
2766 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
2767 foreach_vpe_api_msg;
2771 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2772 foreach_vpe_api_msg;
2776 #define _(n,h) hash_set_mem (vam->function_by_name, #n, n);
2777 foreach_cli_function;
2781 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
2782 foreach_cli_function;
2786 #if VPP_API_TEST_BUILTIN
2787 static clib_error_t *
2788 vat_api_hookup_shim (vlib_main_t * vm)
2790 vat_api_hookup (&vat_main);
2794 VLIB_API_INIT_FUNCTION (vat_api_hookup_shim);
2798 * fd.io coding-style-patch-verification: ON
2801 * eval: (c-set-style "gnu")