2 *------------------------------------------------------------------
3 * Copyright (c) 2021 Cisco and/or its affiliates.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *------------------------------------------------------------------
19 #include <vlibapi/api.h>
20 #include <vlibmemory/api.h>
21 #include <vppinfra/error.h>
22 #include <vpp/api/types.h>
23 #include <vnet/mpls/packet.h>
24 #include <vnet/ip/ip_types_api.h>
26 #define __plugin_msg_base ip_test_main.msg_id_base
27 #include <vlibapi/vat_helper_macros.h>
29 /* Declare message IDs */
30 #include <vnet/format_fns.h>
31 #include <vnet/ip/ip.api_enum.h>
32 #include <vnet/ip/ip.api_types.h>
34 #define vl_endianfun /* define message structures */
35 #include <vnet/ip/ip.api.h>
40 /* API message ID base */
46 static ip_test_main_t ip_test_main;
49 api_ip_route_add_del_v2 (vat_main_t *vam)
55 set_ip4_address (vl_api_address_t *a, u32 v)
57 if (a->af == ADDRESS_IP4)
59 ip4_address_t *i = (ip4_address_t *) &a->un.ip4;
65 increment_v4_address (vl_api_ip4_address_t *i)
67 ip4_address_t *a = (ip4_address_t *) i;
70 v = ntohl (a->as_u32) + 1;
71 a->as_u32 = ntohl (v);
75 increment_v6_address (vl_api_ip6_address_t *i)
77 ip6_address_t *a = (ip6_address_t *) i;
80 v0 = clib_net_to_host_u64 (a->as_u64[0]);
81 v1 = clib_net_to_host_u64 (a->as_u64[1]);
86 a->as_u64[0] = clib_net_to_host_u64 (v0);
87 a->as_u64[1] = clib_net_to_host_u64 (v1);
91 increment_address (vl_api_address_t *a)
93 if (a->af == ADDRESS_IP4)
94 increment_v4_address (&a->un.ip4);
95 else if (a->af == ADDRESS_IP6)
96 increment_v6_address (&a->un.ip6);
100 unformat_fib_path (unformat_input_t *input, va_list *args)
102 vnet_main_t *vnm = va_arg (*args, vnet_main_t *);
103 vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t *);
104 u32 weight, preference;
105 mpls_label_t out_label;
107 clib_memset (path, 0, sizeof (*path));
109 path->sw_if_index = ~0;
113 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
115 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
116 &path->nh.address.ip4, unformat_vnet_sw_interface, vnm,
119 path->proto = FIB_API_PATH_NH_PROTO_IP4;
121 else if (unformat (input, "%U %U", unformat_vl_api_ip6_address,
122 &path->nh.address.ip6, unformat_vnet_sw_interface,
123 vnm, &path->sw_if_index))
125 path->proto = FIB_API_PATH_NH_PROTO_IP6;
127 else if (unformat (input, "weight %u", &weight))
129 path->weight = weight;
131 else if (unformat (input, "preference %u", &preference))
133 path->preference = preference;
135 else if (unformat (input, "%U next-hop-table %d",
136 unformat_vl_api_ip4_address, &path->nh.address.ip4,
139 path->proto = FIB_API_PATH_NH_PROTO_IP4;
141 else if (unformat (input, "%U next-hop-table %d",
142 unformat_vl_api_ip6_address, &path->nh.address.ip6,
145 path->proto = FIB_API_PATH_NH_PROTO_IP6;
147 else if (unformat (input, "%U", unformat_vl_api_ip4_address,
148 &path->nh.address.ip4))
151 * the recursive next-hops are by default in the default table
154 path->sw_if_index = ~0;
155 path->proto = FIB_API_PATH_NH_PROTO_IP4;
157 else if (unformat (input, "%U", unformat_vl_api_ip6_address,
158 &path->nh.address.ip6))
161 * the recursive next-hops are by default in the default table
164 path->sw_if_index = ~0;
165 path->proto = FIB_API_PATH_NH_PROTO_IP6;
167 else if (unformat (input, "resolve-via-host"))
169 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
171 else if (unformat (input, "resolve-via-attached"))
173 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
175 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
177 path->type = FIB_API_PATH_TYPE_LOCAL;
178 path->sw_if_index = ~0;
179 path->proto = FIB_API_PATH_NH_PROTO_IP4;
181 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
183 path->type = FIB_API_PATH_TYPE_LOCAL;
184 path->sw_if_index = ~0;
185 path->proto = FIB_API_PATH_NH_PROTO_IP6;
187 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
189 else if (unformat (input, "via-label %d", &path->nh.via_label))
191 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
192 path->sw_if_index = ~0;
194 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
196 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
197 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
199 else if (unformat (input, "local"))
201 path->type = FIB_API_PATH_TYPE_LOCAL;
203 else if (unformat (input, "out-labels"))
205 while (unformat (input, "%d", &out_label))
207 path->label_stack[path->n_labels].label = out_label;
208 path->label_stack[path->n_labels].is_uniform = 0;
209 path->label_stack[path->n_labels].ttl = 64;
213 else if (unformat (input, "via"))
215 /* new path, back up and return */
216 unformat_put_input (input);
217 unformat_put_input (input);
218 unformat_put_input (input);
219 unformat_put_input (input);
228 path->proto = ntohl (path->proto);
229 path->type = ntohl (path->type);
230 path->flags = ntohl (path->flags);
231 path->table_id = ntohl (path->table_id);
232 path->sw_if_index = ntohl (path->sw_if_index);
238 api_ip_route_add_del (vat_main_t *vam)
240 vnet_main_t *vnm = vnet_get_main ();
241 unformat_input_t *i = vam->input;
242 vl_api_ip_route_add_del_t *mp;
248 vl_api_prefix_t pfx = {};
249 vl_api_fib_path_t paths[8];
253 u32 random_add_del = 0;
254 u32 *random_vector = 0;
255 u32 random_seed = 0xdeaddabe;
257 /* Parse args required to build the message */
258 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
260 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
262 else if (unformat (i, "del"))
264 else if (unformat (i, "add"))
266 else if (unformat (i, "vrf %d", &vrf_id))
268 else if (unformat (i, "count %d", &count))
270 else if (unformat (i, "random"))
272 else if (unformat (i, "multipath"))
274 else if (unformat (i, "seed %d", &random_seed))
276 else if (unformat (i, "via %U", unformat_fib_path, vnm,
282 errmsg ("max 8 paths");
288 clib_warning ("parse error '%U'", format_unformat_error, i);
295 errmsg ("specify a path; via ...");
300 errmsg ("missing prefix");
304 /* Generate a pile of unique, random routes */
307 ip4_address_t *i = (ip4_address_t *) &paths[0].nh.address.ip4;
308 u32 this_random_address;
311 random_hash = hash_create (count, sizeof (uword));
313 hash_set (random_hash, i->as_u32, 1);
314 for (j = 0; j <= count; j++)
318 this_random_address = random_u32 (&random_seed);
319 this_random_address = clib_host_to_net_u32 (this_random_address);
321 while (hash_get (random_hash, this_random_address));
322 vec_add1 (random_vector, this_random_address);
323 hash_set (random_hash, this_random_address, 1);
325 hash_free (random_hash);
326 set_ip4_address (&pfx.address, random_vector[0]);
331 /* Turn on async mode */
333 vam->async_errors = 0;
334 before = vat_time_now (vam);
337 for (j = 0; j < count; j++)
339 /* Construct the API message */
340 M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
343 mp->is_multipath = is_multipath;
345 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
346 mp->route.table_id = ntohl (vrf_id);
347 mp->route.n_paths = path_count;
349 clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
352 set_ip4_address (&pfx.address, random_vector[j + 1]);
354 increment_address (&pfx.address);
357 /* If we receive SIGTERM, stop now... */
362 /* When testing multiple add/del ops, use a control-ping to sync */
365 vl_api_control_ping_t *mp_ping;
369 /* Shut off async mode */
372 PING (&ip_test_main, mp_ping);
375 timeout = vat_time_now (vam) + 1.0;
376 while (vat_time_now (vam) < timeout)
377 if (vam->result_ready == 1)
382 if (vam->retval == -99)
385 if (vam->async_errors > 0)
387 errmsg ("%d asynchronous errors", vam->async_errors);
390 vam->async_errors = 0;
391 after = vat_time_now (vam);
393 /* slim chance, but we might have eaten SIGTERM on the first iteration */
397 print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", count,
398 after - before, count / (after - before));
404 /* Wait for a reply... */
409 /* Return the good/bad news */
410 return (vam->retval);
414 api_ip_table_add_del (vat_main_t *vam)
416 unformat_input_t *i = vam->input;
417 vl_api_ip_table_add_del_t *mp;
423 /* Parse args required to build the message */
424 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
426 if (unformat (i, "ipv6"))
428 else if (unformat (i, "del"))
430 else if (unformat (i, "add"))
432 else if (unformat (i, "table %d", &table_id))
436 clib_warning ("parse error '%U'", format_unformat_error, i);
443 errmsg ("missing table-ID");
447 /* Construct the API message */
448 M (IP_TABLE_ADD_DEL, mp);
450 mp->table.table_id = ntohl (table_id);
451 mp->table.is_ip6 = is_ipv6;
457 /* Wait for a reply... */
464 api_ip_table_replace_begin (vat_main_t *vam)
466 unformat_input_t *i = vam->input;
467 vl_api_ip_table_replace_begin_t *mp;
472 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
474 if (unformat (i, "table %d", &table_id))
476 else if (unformat (i, "ipv6"))
480 clib_warning ("parse error '%U'", format_unformat_error, i);
485 M (IP_TABLE_REPLACE_BEGIN, mp);
487 mp->table.table_id = ntohl (table_id);
488 mp->table.is_ip6 = is_ipv6;
496 api_ip_table_flush (vat_main_t *vam)
498 unformat_input_t *i = vam->input;
499 vl_api_ip_table_flush_t *mp;
504 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
506 if (unformat (i, "table %d", &table_id))
508 else if (unformat (i, "ipv6"))
512 clib_warning ("parse error '%U'", format_unformat_error, i);
517 M (IP_TABLE_FLUSH, mp);
519 mp->table.table_id = ntohl (table_id);
520 mp->table.is_ip6 = is_ipv6;
528 vl_api_ip_route_add_del_v2_reply_t_handler (
529 vl_api_ip_route_add_del_v2_reply_t *mp)
534 vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t *mp)
539 vl_api_ip_route_v2_details_t_handler (vl_api_ip_route_v2_details_t *mp)
544 vl_api_ip_route_add_del_reply_t_handler (vl_api_ip_route_add_del_reply_t *mp)
546 vat_main_t *vam = ip_test_main.vat_main;
547 vam->result_ready = 1;
551 vl_api_ip_route_lookup_reply_t_handler (vl_api_ip_route_lookup_reply_t *mp)
556 vl_api_ip_route_lookup_v2_reply_t_handler (
557 vl_api_ip_route_lookup_v2_reply_t *mp)
562 api_set_ip_flow_hash_router_id (vat_main_t *vat)
568 api_ip_route_lookup (vat_main_t *vat)
574 api_ip_route_lookup_v2 (vat_main_t *vat)
580 api_set_ip_flow_hash (vat_main_t *vam)
582 unformat_input_t *i = vam->input;
583 vl_api_set_ip_flow_hash_t *mp;
595 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
597 if (unformat (i, "vrf %d", &vrf_id))
599 else if (unformat (i, "ipv6"))
601 else if (unformat (i, "src"))
603 else if (unformat (i, "dst"))
605 else if (unformat (i, "sport"))
607 else if (unformat (i, "dport"))
609 else if (unformat (i, "proto"))
611 else if (unformat (i, "reverse"))
616 clib_warning ("parse error '%U'", format_unformat_error, i);
623 errmsg ("missing vrf id");
627 M (SET_IP_FLOW_HASH, mp);
633 mp->reverse = reverse;
634 mp->vrf_id = ntohl (vrf_id);
635 mp->is_ipv6 = is_ipv6;
643 api_mfib_signal_dump (vat_main_t *vat)
649 api_ip_punt_police (vat_main_t *vat)
655 api_ip_punt_redirect (vat_main_t *vat)
661 api_add_del_ip_punt_redirect_v2 (vat_main_t *vat)
667 api_ip_punt_redirect_dump (vat_main_t *vat)
673 vl_api_ip_punt_redirect_details_t_handler (
674 vl_api_ip_punt_redirect_details_t *mp)
680 api_ip_punt_redirect_v2_dump (vat_main_t *vat)
686 vl_api_ip_punt_redirect_v2_details_t_handler (
687 vl_api_ip_punt_redirect_v2_details_t *mp)
693 api_ip_address_dump (vat_main_t *vam)
695 vnet_main_t *vnm = vnet_get_main ();
696 unformat_input_t *i = vam->input;
697 vl_api_ip_address_dump_t *mp;
698 vl_api_control_ping_t *mp_ping;
699 u32 sw_if_index = ~0;
700 u8 sw_if_index_set = 0;
705 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
707 if (unformat (i, "sw_if_index %d", &sw_if_index))
709 else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
712 else if (unformat (i, "ipv4"))
714 else if (unformat (i, "ipv6"))
720 if (ipv4_set && ipv6_set)
722 errmsg ("ipv4 and ipv6 flags cannot be both set");
726 if ((!ipv4_set) && (!ipv6_set))
728 errmsg ("no ipv4 nor ipv6 flag set");
732 if (sw_if_index_set == 0)
734 errmsg ("missing interface name or sw_if_index");
738 vam->current_sw_if_index = sw_if_index;
739 vam->is_ipv6 = ipv6_set;
741 M (IP_ADDRESS_DUMP, mp);
742 mp->sw_if_index = ntohl (sw_if_index);
743 mp->is_ipv6 = ipv6_set;
746 /* Use a control ping for synchronization */
747 PING (&ip_test_main, mp_ping);
755 vl_api_sw_interface_ip6_get_link_local_address_reply_t_handler (
756 vl_api_sw_interface_ip6_get_link_local_address_reply_t *mp)
761 api_sw_interface_ip6_set_link_local_address (vat_main_t *vam)
767 api_sw_interface_ip6_get_link_local_address (vat_main_t *vam)
773 api_ip_path_mtu_replace_end (vat_main_t *vam)
779 api_ioam_enable (vat_main_t *vam)
781 unformat_input_t *input = vam->input;
782 vl_api_ioam_enable_t *mp;
784 int has_trace_option = 0;
785 int has_pot_option = 0;
786 int has_seqno_option = 0;
787 int has_analyse_option = 0;
790 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
792 if (unformat (input, "trace"))
793 has_trace_option = 1;
794 else if (unformat (input, "pot"))
796 else if (unformat (input, "seqno"))
797 has_seqno_option = 1;
798 else if (unformat (input, "analyse"))
799 has_analyse_option = 1;
805 mp->seqno = has_seqno_option;
806 mp->analyse = has_analyse_option;
807 mp->pot_enable = has_pot_option;
808 mp->trace_enable = has_trace_option;
816 api_ip_reassembly_get (vat_main_t *vam)
822 api_ip_path_mtu_replace_begin (vat_main_t *vam)
828 api_ip_path_mtu_update (vat_main_t *vam)
834 api_ioam_disable (vat_main_t *vam)
836 vl_api_ioam_disable_t *mp;
839 M (IOAM_DISABLE, mp);
846 api_ip_source_and_port_range_check_add_del (vat_main_t *vam)
848 unformat_input_t *input = vam->input;
849 vl_api_ip_source_and_port_range_check_add_del_t *mp;
855 vl_api_prefix_t prefix;
862 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
864 if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
866 else if (unformat (input, "vrf %d", &vrf_id))
868 else if (unformat (input, "del"))
870 else if (unformat (input, "port %d", &tmp))
872 if (tmp == 0 || tmp > 65535)
874 errmsg ("port %d out of range", tmp);
878 this_hi = this_low + 1;
879 vec_add1 (low_ports, this_low);
880 vec_add1 (high_ports, this_hi);
882 else if (unformat (input, "range %d - %d", &tmp, &tmp2))
884 if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
886 errmsg ("incorrect range parameters");
890 /* Note: in debug CLI +1 is added to high before
891 passing to real fn that does "the work"
892 (ip_source_and_port_range_check_add_del).
893 This fn is a wrapper around the binary API fn a
894 control plane will call, which expects this increment
895 to have occurred. Hence letting the binary API control
896 plane fn do the increment for consistency between VAT
897 and other control planes.
900 vec_add1 (low_ports, this_low);
901 vec_add1 (high_ports, this_hi);
909 errmsg ("<address>/<mask> not specified");
915 errmsg ("VRF ID required, not specified");
921 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
926 if (vec_len (low_ports) == 0)
928 errmsg ("At least one port or port range required");
932 M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
936 clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
938 mp->number_of_ranges = vec_len (low_ports);
940 clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
941 vec_free (low_ports);
943 clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
944 vec_free (high_ports);
946 mp->vrf_id = ntohl (vrf_id);
954 api_ip_reassembly_set (vat_main_t *vat)
960 api_ip_container_proxy_add_del (vat_main_t *vam)
962 vl_api_ip_container_proxy_add_del_t *mp;
963 unformat_input_t *i = vam->input;
964 u32 sw_if_index = ~0;
965 vl_api_prefix_t pfx = {};
969 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
971 if (unformat (i, "del"))
973 else if (unformat (i, "add"))
975 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
977 else if (unformat (i, "sw_if_index %u", &sw_if_index))
982 if (sw_if_index == ~0 || pfx.len == 0)
984 errmsg ("address and sw_if_index must be set");
988 M (IP_CONTAINER_PROXY_ADD_DEL, mp);
990 mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
992 clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
1000 api_ip_reassembly_enable_disable (vat_main_t *vat)
1006 vl_api_ip_reassembly_get_reply_t_handler (vl_api_ip_reassembly_get_reply_t *mp)
1011 api_ip_source_and_port_range_check_interface_add_del (vat_main_t *vam)
1013 vnet_main_t *vnm = vnet_get_main ();
1014 unformat_input_t *input = vam->input;
1015 vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
1016 u32 sw_if_index = ~0;
1018 u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
1019 u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
1023 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1025 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
1028 else if (unformat (input, "sw_if_index %d", &sw_if_index))
1030 else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
1032 else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
1034 else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
1036 else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
1038 else if (unformat (input, "del"))
1044 if (sw_if_index == ~0)
1046 errmsg ("Interface required but not specified");
1052 errmsg ("VRF ID required but not specified");
1056 if (tcp_out_vrf_id == 0 || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 ||
1059 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
1064 /* Construct the API message */
1065 M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
1067 mp->sw_if_index = ntohl (sw_if_index);
1068 mp->is_add = is_add;
1069 mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
1070 mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
1071 mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
1072 mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
1077 /* Wait for a reply... */
1083 vl_api_ip_container_proxy_details_t_handler (
1084 vl_api_ip_container_proxy_details_t *mp)
1089 api_ip_container_proxy_dump (vat_main_t *vam)
1095 api_ip_dump (vat_main_t *vam)
1097 vl_api_ip_dump_t *mp;
1098 vl_api_control_ping_t *mp_ping;
1099 unformat_input_t *in = vam->input;
1106 while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
1108 if (unformat (in, "ipv4"))
1110 else if (unformat (in, "ipv6"))
1116 if (ipv4_set && ipv6_set)
1118 errmsg ("ipv4 and ipv6 flags cannot be both set");
1122 if ((!ipv4_set) && (!ipv6_set))
1124 errmsg ("no ipv4 nor ipv6 flag set");
1129 vam->is_ipv6 = is_ipv6;
1132 for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
1134 vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
1136 vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
1139 mp->is_ipv6 = ipv6_set;
1142 /* Use a control ping for synchronization */
1143 PING (&ip_test_main, mp_ping);
1151 vl_api_mfib_signal_details_t_handler (vl_api_mfib_signal_details_t *mp)
1156 vl_api_ip_mroute_details_t_handler (vl_api_ip_mroute_details_t *mp)
1158 vat_main_t *vam = ip_test_main.vat_main;
1159 vam->result_ready = 1;
1163 api_ip_mroute_dump (vat_main_t *vam)
1165 unformat_input_t *input = vam->input;
1166 vl_api_control_ping_t *mp_ping;
1167 vl_api_ip_mroute_dump_t *mp;
1172 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1174 if (unformat (input, "table_id %d", &table_id))
1176 else if (unformat (input, "ip6"))
1178 else if (unformat (input, "ip4"))
1185 errmsg ("missing table id");
1189 M (IP_MROUTE_DUMP, mp);
1190 mp->table.table_id = table_id;
1191 mp->table.is_ip6 = is_ip6;
1194 /* Use a control ping for synchronization */
1195 PING (&ip_test_main, mp_ping);
1203 api_sw_interface_ip6_enable_disable (vat_main_t *vam)
1205 vnet_main_t *vnm = vnet_get_main ();
1206 unformat_input_t *i = vam->input;
1207 vl_api_sw_interface_ip6_enable_disable_t *mp;
1209 u8 sw_if_index_set = 0;
1213 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1215 if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1216 sw_if_index_set = 1;
1217 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1218 sw_if_index_set = 1;
1219 else if (unformat (i, "enable"))
1221 else if (unformat (i, "disable"))
1225 clib_warning ("parse error '%U'", format_unformat_error, i);
1230 if (sw_if_index_set == 0)
1232 errmsg ("missing interface name or sw_if_index");
1236 M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
1238 mp->sw_if_index = ntohl (sw_if_index);
1239 mp->enable = enable;
1247 api_set_ip_flow_hash_v2 (vat_main_t *vat)
1253 api_ip_mroute_add_del (vat_main_t *vam)
1255 unformat_input_t *i = vam->input;
1256 u8 path_set = 0, prefix_set = 0, is_add = 1;
1257 vl_api_ip_mroute_add_del_t *mp;
1258 mfib_entry_flags_t eflags = 0;
1259 vl_api_mfib_path_t path;
1260 vl_api_mprefix_t pfx = {};
1264 /* Parse args required to build the message */
1265 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1267 if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
1270 pfx.grp_address_length = htons (pfx.grp_address_length);
1272 else if (unformat (i, "del"))
1274 else if (unformat (i, "add"))
1276 else if (unformat (i, "vrf %d", &vrf_id))
1278 else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
1279 path.itf_flags = htonl (path.itf_flags);
1280 else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
1282 else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
1286 clib_warning ("parse error '%U'", format_unformat_error, i);
1291 if (prefix_set == 0)
1293 errmsg ("missing addresses\n");
1298 errmsg ("missing path\n");
1302 /* Construct the API message */
1303 M (IP_MROUTE_ADD_DEL, mp);
1305 mp->is_add = is_add;
1306 mp->is_multipath = 1;
1308 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
1309 mp->route.table_id = htonl (vrf_id);
1310 mp->route.n_paths = 1;
1311 mp->route.entry_flags = htonl (eflags);
1313 clib_memcpy (&mp->route.paths, &path, sizeof (path));
1317 /* Wait for a reply... */
1323 vl_api_ip_mroute_add_del_reply_t_handler (vl_api_ip_mroute_add_del_reply_t *mp)
1325 vat_main_t *vam = ip_test_main.vat_main;
1326 vam->result_ready = 1;
1330 api_ip_mtable_dump (vat_main_t *vam)
1332 vl_api_ip_mtable_dump_t *mp;
1333 vl_api_control_ping_t *mp_ping;
1336 M (IP_MTABLE_DUMP, mp);
1339 /* Use a control ping for synchronization */
1340 PING (&ip_test_main, mp_ping);
1348 vl_api_ip_mtable_details_t_handler (vl_api_ip_mtable_details_t *mp)
1350 vat_main_t *vam = ip_test_main.vat_main;
1351 vam->result_ready = 1;
1355 api_ip_table_replace_end (vat_main_t *vam)
1357 unformat_input_t *i = vam->input;
1358 vl_api_ip_table_replace_end_t *mp;
1363 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1365 if (unformat (i, "table %d", &table_id))
1367 else if (unformat (i, "ipv6"))
1371 clib_warning ("parse error '%U'", format_unformat_error, i);
1376 M (IP_TABLE_REPLACE_END, mp);
1378 mp->table.table_id = ntohl (table_id);
1379 mp->table.is_ip6 = is_ipv6;
1387 api_ip_table_dump (vat_main_t *vam)
1389 vl_api_ip_table_dump_t *mp;
1390 vl_api_control_ping_t *mp_ping;
1393 M (IP_TABLE_DUMP, mp);
1396 /* Use a control ping for synchronization */
1397 PING (&ip_test_main, mp_ping);
1405 vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t *mp)
1407 vat_main_t *vam = ip_test_main.vat_main;
1409 fformat (vam->ofp, "%s; table-id %d, prefix %U/%d", mp->table.name,
1410 ntohl (mp->table.table_id));
1411 vam->result_ready = 1;
1415 api_ip_path_mtu_get (vat_main_t *vat)
1421 api_ip_route_v2_dump (vat_main_t *vat)
1427 vl_api_ip_path_mtu_get_reply_t_handler (vl_api_ip_path_mtu_get_reply_t *mp)
1432 api_ip_route_dump (vat_main_t *vam)
1434 unformat_input_t *input = vam->input;
1435 vl_api_ip_route_dump_t *mp;
1436 vl_api_control_ping_t *mp_ping;
1442 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1444 if (unformat (input, "table_id %d", &table_id))
1446 else if (unformat (input, "ip6"))
1448 else if (unformat (input, "ip4"))
1455 errmsg ("missing table id");
1459 M (IP_ROUTE_DUMP, mp);
1461 mp->table.table_id = table_id;
1462 mp->table.is_ip6 = is_ip6;
1466 /* Use a control ping for synchronization */
1467 PING (&ip_test_main, mp_ping);
1475 vl_api_ip_address_details_t_handler (vl_api_ip_address_details_t *mp)
1477 vat_main_t *vam = ip_test_main.vat_main;
1478 static ip_address_details_t empty_ip_address_details = { { 0 } };
1479 ip_address_details_t *address = NULL;
1480 ip_details_t *current_ip_details = NULL;
1481 ip_details_t *details = NULL;
1483 details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1485 if (!details || vam->current_sw_if_index >= vec_len (details) ||
1486 !details[vam->current_sw_if_index].present)
1488 errmsg ("ip address details arrived but not stored");
1489 errmsg ("ip_dump should be called first");
1493 current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1495 #define addresses (current_ip_details->addr)
1497 vec_validate_init_empty (addresses, vec_len (addresses),
1498 empty_ip_address_details);
1500 address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1502 clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
1503 address->prefix_length = mp->prefix.len;
1508 api_ip_unnumbered_dump (vat_main_t *vam)
1514 vl_api_ip_unnumbered_details_t_handler (vl_api_ip_unnumbered_details_t *mp)
1519 vl_api_ip_details_t_handler (vl_api_ip_details_t *mp)
1521 vat_main_t *vam = &vat_main;
1522 static ip_details_t empty_ip_details = { 0 };
1523 ip_details_t *ip = NULL;
1524 u32 sw_if_index = ~0;
1526 sw_if_index = ntohl (mp->sw_if_index);
1528 vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1529 sw_if_index, empty_ip_details);
1531 ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1537 #include <vnet/ip/ip.api_test.c>
1539 VAT_REGISTER_FEATURE_FUNCTION (vat_ip_plugin_register);
1542 * fd.io coding-style-patch-verification: ON
1545 * eval: (c-set-style "gnu")