blob: 2de8235288da0c66cbe2184e36e72e025699782e [file] [log] [blame]
Filip Tehlarabfe3652021-07-23 18:24:19 +00001/*
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:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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 *------------------------------------------------------------------
16 */
17
18#include <vat/vat.h>
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>
25
26#define __plugin_msg_base ip_test_main.msg_id_base
27#include <vlibapi/vat_helper_macros.h>
28
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>
33
34#define vl_endianfun /* define message structures */
35#include <vnet/ip/ip.api.h>
36#undef vl_endianfun
37
38typedef struct
39{
40 /* API message ID base */
41 u16 msg_id_base;
42 u32 ping_id;
43 vat_main_t *vat_main;
44} ip_test_main_t;
45
46static ip_test_main_t ip_test_main;
47
48static int
49api_ip_route_add_del_v2 (vat_main_t *vam)
50{
51 return -1;
52}
53
54static void
55set_ip4_address (vl_api_address_t *a, u32 v)
56{
57 if (a->af == ADDRESS_IP4)
58 {
59 ip4_address_t *i = (ip4_address_t *) &a->un.ip4;
60 i->as_u32 = v;
61 }
62}
63
64static void
65increment_v4_address (vl_api_ip4_address_t *i)
66{
67 ip4_address_t *a = (ip4_address_t *) i;
68 u32 v;
69
70 v = ntohl (a->as_u32) + 1;
71 a->as_u32 = ntohl (v);
72}
73
74static void
75increment_v6_address (vl_api_ip6_address_t *i)
76{
77 ip6_address_t *a = (ip6_address_t *) i;
78 u64 v0, v1;
79
80 v0 = clib_net_to_host_u64 (a->as_u64[0]);
81 v1 = clib_net_to_host_u64 (a->as_u64[1]);
82
83 v1 += 1;
84 if (v1 == 0)
85 v0 += 1;
86 a->as_u64[0] = clib_net_to_host_u64 (v0);
87 a->as_u64[1] = clib_net_to_host_u64 (v1);
88}
89
90static void
91increment_address (vl_api_address_t *a)
92{
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);
97}
98
99static uword
100unformat_fib_path (unformat_input_t *input, va_list *args)
101{
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;
106
107 clib_memset (path, 0, sizeof (*path));
108 path->weight = 1;
109 path->sw_if_index = ~0;
110 path->rpf_id = ~0;
111 path->n_labels = 0;
112
113 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
114 {
115 if (unformat (input, "%U %U", unformat_vl_api_ip4_address,
116 &path->nh.address.ip4, unformat_vnet_sw_interface, vnm,
117 &path->sw_if_index))
118 {
119 path->proto = FIB_API_PATH_NH_PROTO_IP4;
120 }
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))
124 {
125 path->proto = FIB_API_PATH_NH_PROTO_IP6;
126 }
127 else if (unformat (input, "weight %u", &weight))
128 {
129 path->weight = weight;
130 }
131 else if (unformat (input, "preference %u", &preference))
132 {
133 path->preference = preference;
134 }
135 else if (unformat (input, "%U next-hop-table %d",
136 unformat_vl_api_ip4_address, &path->nh.address.ip4,
137 &path->table_id))
138 {
139 path->proto = FIB_API_PATH_NH_PROTO_IP4;
140 }
141 else if (unformat (input, "%U next-hop-table %d",
142 unformat_vl_api_ip6_address, &path->nh.address.ip6,
143 &path->table_id))
144 {
145 path->proto = FIB_API_PATH_NH_PROTO_IP6;
146 }
147 else if (unformat (input, "%U", unformat_vl_api_ip4_address,
148 &path->nh.address.ip4))
149 {
150 /*
151 * the recursive next-hops are by default in the default table
152 */
153 path->table_id = 0;
154 path->sw_if_index = ~0;
155 path->proto = FIB_API_PATH_NH_PROTO_IP4;
156 }
157 else if (unformat (input, "%U", unformat_vl_api_ip6_address,
158 &path->nh.address.ip6))
159 {
160 /*
161 * the recursive next-hops are by default in the default table
162 */
163 path->table_id = 0;
164 path->sw_if_index = ~0;
165 path->proto = FIB_API_PATH_NH_PROTO_IP6;
166 }
167 else if (unformat (input, "resolve-via-host"))
168 {
169 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_HOST;
170 }
171 else if (unformat (input, "resolve-via-attached"))
172 {
173 path->flags |= FIB_API_PATH_FLAG_RESOLVE_VIA_ATTACHED;
174 }
175 else if (unformat (input, "ip4-lookup-in-table %d", &path->table_id))
176 {
177 path->type = FIB_API_PATH_TYPE_LOCAL;
178 path->sw_if_index = ~0;
179 path->proto = FIB_API_PATH_NH_PROTO_IP4;
180 }
181 else if (unformat (input, "ip6-lookup-in-table %d", &path->table_id))
182 {
183 path->type = FIB_API_PATH_TYPE_LOCAL;
184 path->sw_if_index = ~0;
185 path->proto = FIB_API_PATH_NH_PROTO_IP6;
186 }
187 else if (unformat (input, "sw_if_index %d", &path->sw_if_index))
188 ;
189 else if (unformat (input, "via-label %d", &path->nh.via_label))
190 {
191 path->proto = FIB_API_PATH_NH_PROTO_MPLS;
192 path->sw_if_index = ~0;
193 }
194 else if (unformat (input, "l2-input-on %d", &path->sw_if_index))
195 {
196 path->proto = FIB_API_PATH_NH_PROTO_ETHERNET;
197 path->type = FIB_API_PATH_TYPE_INTERFACE_RX;
198 }
199 else if (unformat (input, "local"))
200 {
201 path->type = FIB_API_PATH_TYPE_LOCAL;
202 }
203 else if (unformat (input, "out-labels"))
204 {
205 while (unformat (input, "%d", &out_label))
206 {
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;
210 path->n_labels++;
211 }
212 }
213 else if (unformat (input, "via"))
214 {
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);
220 break;
221 }
222 else
223 {
224 return (0);
225 }
226 }
227
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);
233
234 return (1);
235}
236
237static int
238api_ip_route_add_del (vat_main_t *vam)
239{
240 vnet_main_t *vnm = vnet_get_main ();
241 unformat_input_t *i = vam->input;
242 vl_api_ip_route_add_del_t *mp;
243 u32 vrf_id = 0;
244 u8 is_add = 1;
245 u8 is_multipath = 0;
246 u8 prefix_set = 0;
247 u8 path_count = 0;
248 vl_api_prefix_t pfx = {};
249 vl_api_fib_path_t paths[8];
250 int count = 1;
251 int j;
252 f64 before = 0;
253 u32 random_add_del = 0;
254 u32 *random_vector = 0;
255 u32 random_seed = 0xdeaddabe;
256
257 /* Parse args required to build the message */
258 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
259 {
260 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
261 prefix_set = 1;
262 else if (unformat (i, "del"))
263 is_add = 0;
264 else if (unformat (i, "add"))
265 is_add = 1;
266 else if (unformat (i, "vrf %d", &vrf_id))
267 ;
268 else if (unformat (i, "count %d", &count))
269 ;
270 else if (unformat (i, "random"))
271 random_add_del = 1;
272 else if (unformat (i, "multipath"))
273 is_multipath = 1;
274 else if (unformat (i, "seed %d", &random_seed))
275 ;
276 else if (unformat (i, "via %U", unformat_fib_path, vnm,
277 &paths[path_count]))
278 {
279 path_count++;
280 if (8 == path_count)
281 {
282 errmsg ("max 8 paths");
283 return -99;
284 }
285 }
286 else
287 {
288 clib_warning ("parse error '%U'", format_unformat_error, i);
289 return -99;
290 }
291 }
292
293 if (!path_count)
294 {
295 errmsg ("specify a path; via ...");
296 return -99;
297 }
298 if (prefix_set == 0)
299 {
300 errmsg ("missing prefix");
301 return -99;
302 }
303
304 /* Generate a pile of unique, random routes */
305 if (random_add_del)
306 {
307 ip4_address_t *i = (ip4_address_t *) &paths[0].nh.address.ip4;
308 u32 this_random_address;
309 uword *random_hash;
310
311 random_hash = hash_create (count, sizeof (uword));
312
313 hash_set (random_hash, i->as_u32, 1);
314 for (j = 0; j <= count; j++)
315 {
316 do
317 {
318 this_random_address = random_u32 (&random_seed);
319 this_random_address = clib_host_to_net_u32 (this_random_address);
320 }
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);
324 }
325 hash_free (random_hash);
326 set_ip4_address (&pfx.address, random_vector[0]);
327 }
328
329 if (count > 1)
330 {
331 /* Turn on async mode */
332 vam->async_mode = 1;
333 vam->async_errors = 0;
334 before = vat_time_now (vam);
335 }
336
337 for (j = 0; j < count; j++)
338 {
339 /* Construct the API message */
340 M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
341
342 mp->is_add = is_add;
343 mp->is_multipath = is_multipath;
344
345 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
346 mp->route.table_id = ntohl (vrf_id);
347 mp->route.n_paths = path_count;
348
349 clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
350
351 if (random_add_del)
352 set_ip4_address (&pfx.address, random_vector[j + 1]);
353 else
354 increment_address (&pfx.address);
355 /* send it... */
356 S (mp);
357 /* If we receive SIGTERM, stop now... */
358 if (vam->do_exit)
359 break;
360 }
361
362 /* When testing multiple add/del ops, use a control-ping to sync */
363 if (count > 1)
364 {
365 vl_api_control_ping_t *mp_ping;
366 f64 after;
367 f64 timeout;
368
369 /* Shut off async mode */
370 vam->async_mode = 0;
371
372 PING (&ip_test_main, mp_ping);
373 S (mp_ping);
374
375 timeout = vat_time_now (vam) + 1.0;
376 while (vat_time_now (vam) < timeout)
377 if (vam->result_ready == 1)
378 goto out;
379 vam->retval = -99;
380
381 out:
382 if (vam->retval == -99)
383 errmsg ("timeout");
384
385 if (vam->async_errors > 0)
386 {
387 errmsg ("%d asynchronous errors", vam->async_errors);
388 vam->retval = -98;
389 }
390 vam->async_errors = 0;
391 after = vat_time_now (vam);
392
393 /* slim chance, but we might have eaten SIGTERM on the first iteration */
394 if (j > 0)
395 count = j;
396
397 print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", count,
398 after - before, count / (after - before));
399 }
400 else
401 {
402 int ret;
403
404 /* Wait for a reply... */
405 W (ret);
406 return ret;
407 }
408
409 /* Return the good/bad news */
410 return (vam->retval);
411}
412
413static int
414api_ip_table_add_del (vat_main_t *vam)
415{
416 unformat_input_t *i = vam->input;
417 vl_api_ip_table_add_del_t *mp;
418 u32 table_id = ~0;
419 u8 is_ipv6 = 0;
420 u8 is_add = 1;
421 int ret = 0;
422
423 /* Parse args required to build the message */
424 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
425 {
426 if (unformat (i, "ipv6"))
427 is_ipv6 = 1;
428 else if (unformat (i, "del"))
429 is_add = 0;
430 else if (unformat (i, "add"))
431 is_add = 1;
432 else if (unformat (i, "table %d", &table_id))
433 ;
434 else
435 {
436 clib_warning ("parse error '%U'", format_unformat_error, i);
437 return -99;
438 }
439 }
440
441 if (~0 == table_id)
442 {
443 errmsg ("missing table-ID");
444 return -99;
445 }
446
447 /* Construct the API message */
448 M (IP_TABLE_ADD_DEL, mp);
449
450 mp->table.table_id = ntohl (table_id);
451 mp->table.is_ip6 = is_ipv6;
452 mp->is_add = is_add;
453
454 /* send it... */
455 S (mp);
456
457 /* Wait for a reply... */
458 W (ret);
459
460 return ret;
461}
462
463static int
464api_ip_table_replace_begin (vat_main_t *vam)
465{
466 unformat_input_t *i = vam->input;
467 vl_api_ip_table_replace_begin_t *mp;
468 u32 table_id = 0;
469 u8 is_ipv6 = 0;
470
471 int ret;
472 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
473 {
474 if (unformat (i, "table %d", &table_id))
475 ;
476 else if (unformat (i, "ipv6"))
477 is_ipv6 = 1;
478 else
479 {
480 clib_warning ("parse error '%U'", format_unformat_error, i);
481 return -99;
482 }
483 }
484
485 M (IP_TABLE_REPLACE_BEGIN, mp);
486
487 mp->table.table_id = ntohl (table_id);
488 mp->table.is_ip6 = is_ipv6;
489
490 S (mp);
491 W (ret);
492 return ret;
493}
494
495static int
496api_ip_table_flush (vat_main_t *vam)
497{
498 unformat_input_t *i = vam->input;
499 vl_api_ip_table_flush_t *mp;
500 u32 table_id = 0;
501 u8 is_ipv6 = 0;
502
503 int ret;
504 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
505 {
506 if (unformat (i, "table %d", &table_id))
507 ;
508 else if (unformat (i, "ipv6"))
509 is_ipv6 = 1;
510 else
511 {
512 clib_warning ("parse error '%U'", format_unformat_error, i);
513 return -99;
514 }
515 }
516
517 M (IP_TABLE_FLUSH, mp);
518
519 mp->table.table_id = ntohl (table_id);
520 mp->table.is_ip6 = is_ipv6;
521
522 S (mp);
523 W (ret);
524 return ret;
525}
526
527static void
528vl_api_ip_route_add_del_v2_reply_t_handler (
529 vl_api_ip_route_add_del_v2_reply_t *mp)
530{
531}
532
533static void
534vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t *mp)
535{
536}
537
538static void
539vl_api_ip_route_v2_details_t_handler (vl_api_ip_route_v2_details_t *mp)
540{
541}
542
543static void
544vl_api_ip_route_add_del_reply_t_handler (vl_api_ip_route_add_del_reply_t *mp)
545{
546 vat_main_t *vam = ip_test_main.vat_main;
547 vam->result_ready = 1;
548}
549
550static void
551vl_api_ip_route_lookup_reply_t_handler (vl_api_ip_route_lookup_reply_t *mp)
552{
553}
554
555static void
556vl_api_ip_route_lookup_v2_reply_t_handler (
557 vl_api_ip_route_lookup_v2_reply_t *mp)
558{
559}
560
561static int
562api_set_ip_flow_hash_router_id (vat_main_t *vat)
563{
564 return -1;
565}
566
567static int
568api_ip_route_lookup (vat_main_t *vat)
569{
570 return -1;
571}
572
573static int
574api_ip_route_lookup_v2 (vat_main_t *vat)
575{
576 return -1;
577}
578
579static int
580api_set_ip_flow_hash (vat_main_t *vam)
581{
582 unformat_input_t *i = vam->input;
583 vl_api_set_ip_flow_hash_t *mp;
584 u32 vrf_id = 0;
585 u8 is_ipv6 = 0;
586 u8 vrf_id_set = 0;
587 u8 src = 0;
588 u8 dst = 0;
589 u8 sport = 0;
590 u8 dport = 0;
591 u8 proto = 0;
592 u8 reverse = 0;
593 int ret;
594
595 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
596 {
597 if (unformat (i, "vrf %d", &vrf_id))
598 vrf_id_set = 1;
599 else if (unformat (i, "ipv6"))
600 is_ipv6 = 1;
601 else if (unformat (i, "src"))
602 src = 1;
603 else if (unformat (i, "dst"))
604 dst = 1;
605 else if (unformat (i, "sport"))
606 sport = 1;
607 else if (unformat (i, "dport"))
608 dport = 1;
609 else if (unformat (i, "proto"))
610 proto = 1;
611 else if (unformat (i, "reverse"))
612 reverse = 1;
613
614 else
615 {
616 clib_warning ("parse error '%U'", format_unformat_error, i);
617 return -99;
618 }
619 }
620
621 if (vrf_id_set == 0)
622 {
623 errmsg ("missing vrf id");
624 return -99;
625 }
626
627 M (SET_IP_FLOW_HASH, mp);
628 mp->src = src;
629 mp->dst = dst;
630 mp->sport = sport;
631 mp->dport = dport;
632 mp->proto = proto;
633 mp->reverse = reverse;
634 mp->vrf_id = ntohl (vrf_id);
635 mp->is_ipv6 = is_ipv6;
636
637 S (mp);
638 W (ret);
639 return ret;
640}
641
642static int
643api_mfib_signal_dump (vat_main_t *vat)
644{
645 return -1;
646}
647
648static int
649api_ip_punt_police (vat_main_t *vat)
650{
651 return -1;
652}
653
654static int
655api_ip_punt_redirect (vat_main_t *vat)
656{
657 return -1;
658}
659
660static int
Nathan Skrzypczak2a1783f2021-08-10 15:05:29 +0200661api_add_del_ip_punt_redirect_v2 (vat_main_t *vat)
662{
663 return -1;
664}
665
666static int
Filip Tehlarabfe3652021-07-23 18:24:19 +0000667api_ip_punt_redirect_dump (vat_main_t *vat)
668{
669 return -1;
670}
671
672static void
673vl_api_ip_punt_redirect_details_t_handler (
674 vl_api_ip_punt_redirect_details_t *mp)
675{
Nathan Skrzypczak2a1783f2021-08-10 15:05:29 +0200676 /**/
677}
678
679static int
680api_ip_punt_redirect_v2_dump (vat_main_t *vat)
681{
682 return -1;
683}
684
685static void
686vl_api_ip_punt_redirect_v2_details_t_handler (
687 vl_api_ip_punt_redirect_v2_details_t *mp)
688{
689 /**/
Filip Tehlarabfe3652021-07-23 18:24:19 +0000690}
691
692static int
693api_ip_address_dump (vat_main_t *vam)
694{
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;
701 u8 ipv4_set = 0;
702 u8 ipv6_set = 0;
703 int ret;
704
705 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
706 {
707 if (unformat (i, "sw_if_index %d", &sw_if_index))
708 sw_if_index_set = 1;
709 else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
710 &sw_if_index))
711 sw_if_index_set = 1;
712 else if (unformat (i, "ipv4"))
713 ipv4_set = 1;
714 else if (unformat (i, "ipv6"))
715 ipv6_set = 1;
716 else
717 break;
718 }
719
720 if (ipv4_set && ipv6_set)
721 {
722 errmsg ("ipv4 and ipv6 flags cannot be both set");
723 return -99;
724 }
725
726 if ((!ipv4_set) && (!ipv6_set))
727 {
728 errmsg ("no ipv4 nor ipv6 flag set");
729 return -99;
730 }
731
732 if (sw_if_index_set == 0)
733 {
734 errmsg ("missing interface name or sw_if_index");
735 return -99;
736 }
737
738 vam->current_sw_if_index = sw_if_index;
739 vam->is_ipv6 = ipv6_set;
740
741 M (IP_ADDRESS_DUMP, mp);
742 mp->sw_if_index = ntohl (sw_if_index);
743 mp->is_ipv6 = ipv6_set;
744 S (mp);
745
746 /* Use a control ping for synchronization */
747 PING (&ip_test_main, mp_ping);
748 S (mp_ping);
749
750 W (ret);
751 return ret;
752}
753
754static void
755vl_api_sw_interface_ip6_get_link_local_address_reply_t_handler (
756 vl_api_sw_interface_ip6_get_link_local_address_reply_t *mp)
757{
758}
759
760static int
761api_sw_interface_ip6_set_link_local_address (vat_main_t *vam)
762{
763 return -1;
764}
765
766static int
767api_sw_interface_ip6_get_link_local_address (vat_main_t *vam)
768{
769 return -1;
770}
771
772static int
773api_ip_path_mtu_replace_end (vat_main_t *vam)
774{
775 return -1;
776}
777
778static int
779api_ioam_enable (vat_main_t *vam)
780{
781 unformat_input_t *input = vam->input;
782 vl_api_ioam_enable_t *mp;
783 u32 id = 0;
784 int has_trace_option = 0;
785 int has_pot_option = 0;
786 int has_seqno_option = 0;
787 int has_analyse_option = 0;
788 int ret;
789
790 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
791 {
792 if (unformat (input, "trace"))
793 has_trace_option = 1;
794 else if (unformat (input, "pot"))
795 has_pot_option = 1;
796 else if (unformat (input, "seqno"))
797 has_seqno_option = 1;
798 else if (unformat (input, "analyse"))
799 has_analyse_option = 1;
800 else
801 break;
802 }
803 M (IOAM_ENABLE, mp);
804 mp->id = htons (id);
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;
809
810 S (mp);
811 W (ret);
812 return ret;
813}
814
815static int
816api_ip_reassembly_get (vat_main_t *vam)
817{
818 return -1;
819}
820
821static int
822api_ip_path_mtu_replace_begin (vat_main_t *vam)
823{
824 return -1;
825}
826
827static int
828api_ip_path_mtu_update (vat_main_t *vam)
829{
830 return -1;
831}
832
833static int
834api_ioam_disable (vat_main_t *vam)
835{
836 vl_api_ioam_disable_t *mp;
837 int ret;
838
839 M (IOAM_DISABLE, mp);
840 S (mp);
841 W (ret);
842 return ret;
843}
844
845static int
846api_ip_source_and_port_range_check_add_del (vat_main_t *vam)
847{
848 unformat_input_t *input = vam->input;
849 vl_api_ip_source_and_port_range_check_add_del_t *mp;
850
851 u16 *low_ports = 0;
852 u16 *high_ports = 0;
853 u16 this_low;
854 u16 this_hi;
855 vl_api_prefix_t prefix;
856 u32 tmp, tmp2;
857 u8 prefix_set = 0;
858 u32 vrf_id = ~0;
859 u8 is_add = 1;
860 int ret;
861
862 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
863 {
864 if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
865 prefix_set = 1;
866 else if (unformat (input, "vrf %d", &vrf_id))
867 ;
868 else if (unformat (input, "del"))
869 is_add = 0;
870 else if (unformat (input, "port %d", &tmp))
871 {
872 if (tmp == 0 || tmp > 65535)
873 {
874 errmsg ("port %d out of range", tmp);
875 return -99;
876 }
877 this_low = tmp;
878 this_hi = this_low + 1;
879 vec_add1 (low_ports, this_low);
880 vec_add1 (high_ports, this_hi);
881 }
882 else if (unformat (input, "range %d - %d", &tmp, &tmp2))
883 {
884 if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
885 {
886 errmsg ("incorrect range parameters");
887 return -99;
888 }
889 this_low = tmp;
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.
898 */
899 this_hi = tmp2;
900 vec_add1 (low_ports, this_low);
901 vec_add1 (high_ports, this_hi);
902 }
903 else
904 break;
905 }
906
907 if (prefix_set == 0)
908 {
909 errmsg ("<address>/<mask> not specified");
910 return -99;
911 }
912
913 if (vrf_id == ~0)
914 {
915 errmsg ("VRF ID required, not specified");
916 return -99;
917 }
918
919 if (vrf_id == 0)
920 {
921 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
922 "purpose.");
923 return -99;
924 }
925
926 if (vec_len (low_ports) == 0)
927 {
928 errmsg ("At least one port or port range required");
929 return -99;
930 }
931
932 M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
933
934 mp->is_add = is_add;
935
936 clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
937
938 mp->number_of_ranges = vec_len (low_ports);
939
940 clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
941 vec_free (low_ports);
942
943 clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
944 vec_free (high_ports);
945
946 mp->vrf_id = ntohl (vrf_id);
947
948 S (mp);
949 W (ret);
950 return ret;
951}
952
953static int
954api_ip_reassembly_set (vat_main_t *vat)
955{
956 return -1;
957}
958
959static int
960api_ip_container_proxy_add_del (vat_main_t *vam)
961{
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 = {};
966 u8 is_add = 1;
967 int ret;
968
969 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
970 {
971 if (unformat (i, "del"))
972 is_add = 0;
973 else if (unformat (i, "add"))
974 ;
975 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
976 ;
977 else if (unformat (i, "sw_if_index %u", &sw_if_index))
978 ;
979 else
980 break;
981 }
982 if (sw_if_index == ~0 || pfx.len == 0)
983 {
984 errmsg ("address and sw_if_index must be set");
985 return -99;
986 }
987
988 M (IP_CONTAINER_PROXY_ADD_DEL, mp);
989
990 mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
991 mp->is_add = is_add;
992 clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
993
994 S (mp);
995 W (ret);
996 return ret;
997}
998
999static int
1000api_ip_reassembly_enable_disable (vat_main_t *vat)
1001{
1002 return -1;
1003}
1004
1005static void
1006vl_api_ip_reassembly_get_reply_t_handler (vl_api_ip_reassembly_get_reply_t *mp)
1007{
1008}
1009
1010int
1011api_ip_source_and_port_range_check_interface_add_del (vat_main_t *vam)
1012{
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;
1017 int vrf_set = 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;
1020 u8 is_add = 1;
1021 int ret;
1022
1023 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1024 {
1025 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
1026 &sw_if_index))
1027 ;
1028 else if (unformat (input, "sw_if_index %d", &sw_if_index))
1029 ;
1030 else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
1031 vrf_set = 1;
1032 else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
1033 vrf_set = 1;
1034 else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
1035 vrf_set = 1;
1036 else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
1037 vrf_set = 1;
1038 else if (unformat (input, "del"))
1039 is_add = 0;
1040 else
1041 break;
1042 }
1043
1044 if (sw_if_index == ~0)
1045 {
1046 errmsg ("Interface required but not specified");
1047 return -99;
1048 }
1049
1050 if (vrf_set == 0)
1051 {
1052 errmsg ("VRF ID required but not specified");
1053 return -99;
1054 }
1055
1056 if (tcp_out_vrf_id == 0 || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 ||
1057 udp_in_vrf_id == 0)
1058 {
1059 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
1060 "purpose.");
1061 return -99;
1062 }
1063
1064 /* Construct the API message */
1065 M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
1066
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);
1073
1074 /* send it... */
1075 S (mp);
1076
1077 /* Wait for a reply... */
1078 W (ret);
1079 return ret;
1080}
1081
1082static void
1083vl_api_ip_container_proxy_details_t_handler (
1084 vl_api_ip_container_proxy_details_t *mp)
1085{
1086}
1087
1088static int
1089api_ip_container_proxy_dump (vat_main_t *vam)
1090{
1091 return -1;
1092}
1093
1094static int
1095api_ip_dump (vat_main_t *vam)
1096{
1097 vl_api_ip_dump_t *mp;
1098 vl_api_control_ping_t *mp_ping;
1099 unformat_input_t *in = vam->input;
1100 int ipv4_set = 0;
1101 int ipv6_set = 0;
1102 int is_ipv6;
1103 int i;
1104 int ret;
1105
1106 while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
1107 {
1108 if (unformat (in, "ipv4"))
1109 ipv4_set = 1;
1110 else if (unformat (in, "ipv6"))
1111 ipv6_set = 1;
1112 else
1113 break;
1114 }
1115
1116 if (ipv4_set && ipv6_set)
1117 {
1118 errmsg ("ipv4 and ipv6 flags cannot be both set");
1119 return -99;
1120 }
1121
1122 if ((!ipv4_set) && (!ipv6_set))
1123 {
1124 errmsg ("no ipv4 nor ipv6 flag set");
1125 return -99;
1126 }
1127
1128 is_ipv6 = ipv6_set;
1129 vam->is_ipv6 = is_ipv6;
1130
1131 /* free old data */
1132 for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
1133 {
1134 vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
1135 }
1136 vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
1137
1138 M (IP_DUMP, mp);
1139 mp->is_ipv6 = ipv6_set;
1140 S (mp);
1141
1142 /* Use a control ping for synchronization */
1143 PING (&ip_test_main, mp_ping);
1144 S (mp_ping);
1145
1146 W (ret);
1147 return ret;
1148}
1149
1150static void
1151vl_api_mfib_signal_details_t_handler (vl_api_mfib_signal_details_t *mp)
1152{
1153}
1154
1155static void
1156vl_api_ip_mroute_details_t_handler (vl_api_ip_mroute_details_t *mp)
1157{
1158 vat_main_t *vam = ip_test_main.vat_main;
1159 vam->result_ready = 1;
1160}
1161
1162static int
1163api_ip_mroute_dump (vat_main_t *vam)
1164{
1165 unformat_input_t *input = vam->input;
1166 vl_api_control_ping_t *mp_ping;
1167 vl_api_ip_mroute_dump_t *mp;
1168 int ret, is_ip6;
1169 u32 table_id;
1170
1171 is_ip6 = 0;
1172 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1173 {
1174 if (unformat (input, "table_id %d", &table_id))
1175 ;
1176 else if (unformat (input, "ip6"))
1177 is_ip6 = 1;
1178 else if (unformat (input, "ip4"))
1179 is_ip6 = 0;
1180 else
1181 break;
1182 }
1183 if (table_id == ~0)
1184 {
1185 errmsg ("missing table id");
1186 return -99;
1187 }
1188
1189 M (IP_MROUTE_DUMP, mp);
1190 mp->table.table_id = table_id;
1191 mp->table.is_ip6 = is_ip6;
1192 S (mp);
1193
1194 /* Use a control ping for synchronization */
1195 PING (&ip_test_main, mp_ping);
1196 S (mp_ping);
1197
1198 W (ret);
1199 return ret;
1200}
1201
1202static int
1203api_sw_interface_ip6_enable_disable (vat_main_t *vam)
1204{
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;
1208 u32 sw_if_index;
1209 u8 sw_if_index_set = 0;
1210 u8 enable = 0;
1211 int ret;
1212
1213 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1214 {
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"))
1220 enable = 1;
1221 else if (unformat (i, "disable"))
1222 enable = 0;
1223 else
1224 {
1225 clib_warning ("parse error '%U'", format_unformat_error, i);
1226 return -99;
1227 }
1228 }
1229
1230 if (sw_if_index_set == 0)
1231 {
1232 errmsg ("missing interface name or sw_if_index");
1233 return -99;
1234 }
1235
1236 M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
1237
1238 mp->sw_if_index = ntohl (sw_if_index);
1239 mp->enable = enable;
1240
1241 S (mp);
1242 W (ret);
1243 return ret;
1244}
1245
1246static int
1247api_set_ip_flow_hash_v2 (vat_main_t *vat)
1248{
1249 return -1;
1250}
1251
1252static int
1253api_ip_mroute_add_del (vat_main_t *vam)
1254{
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 = {};
1261 u32 vrf_id = 0;
1262 int ret;
1263
1264 /* Parse args required to build the message */
1265 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1266 {
1267 if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
1268 {
1269 prefix_set = 1;
1270 pfx.grp_address_length = htons (pfx.grp_address_length);
1271 }
1272 else if (unformat (i, "del"))
1273 is_add = 0;
1274 else if (unformat (i, "add"))
1275 is_add = 1;
1276 else if (unformat (i, "vrf %d", &vrf_id))
1277 ;
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))
1281 ;
1282 else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
1283 path_set = 1;
1284 else
1285 {
1286 clib_warning ("parse error '%U'", format_unformat_error, i);
1287 return -99;
1288 }
1289 }
1290
1291 if (prefix_set == 0)
1292 {
1293 errmsg ("missing addresses\n");
1294 return -99;
1295 }
1296 if (path_set == 0)
1297 {
1298 errmsg ("missing path\n");
1299 return -99;
1300 }
1301
1302 /* Construct the API message */
1303 M (IP_MROUTE_ADD_DEL, mp);
1304
1305 mp->is_add = is_add;
1306 mp->is_multipath = 1;
1307
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);
1312
1313 clib_memcpy (&mp->route.paths, &path, sizeof (path));
1314
1315 /* send it... */
1316 S (mp);
1317 /* Wait for a reply... */
1318 W (ret);
1319 return ret;
1320}
1321
1322static void
1323vl_api_ip_mroute_add_del_reply_t_handler (vl_api_ip_mroute_add_del_reply_t *mp)
1324{
1325 vat_main_t *vam = ip_test_main.vat_main;
1326 vam->result_ready = 1;
1327}
1328
1329static int
1330api_ip_mtable_dump (vat_main_t *vam)
1331{
1332 vl_api_ip_mtable_dump_t *mp;
1333 vl_api_control_ping_t *mp_ping;
1334 int ret;
1335
1336 M (IP_MTABLE_DUMP, mp);
1337 S (mp);
1338
1339 /* Use a control ping for synchronization */
1340 PING (&ip_test_main, mp_ping);
1341 S (mp_ping);
1342
1343 W (ret);
1344 return ret;
1345}
1346
1347static void
1348vl_api_ip_mtable_details_t_handler (vl_api_ip_mtable_details_t *mp)
1349{
1350 vat_main_t *vam = ip_test_main.vat_main;
1351 vam->result_ready = 1;
1352}
1353
1354static int
1355api_ip_table_replace_end (vat_main_t *vam)
1356{
1357 unformat_input_t *i = vam->input;
1358 vl_api_ip_table_replace_end_t *mp;
1359 u32 table_id = 0;
1360 u8 is_ipv6 = 0;
1361
1362 int ret;
1363 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1364 {
1365 if (unformat (i, "table %d", &table_id))
1366 ;
1367 else if (unformat (i, "ipv6"))
1368 is_ipv6 = 1;
1369 else
1370 {
1371 clib_warning ("parse error '%U'", format_unformat_error, i);
1372 return -99;
1373 }
1374 }
1375
1376 M (IP_TABLE_REPLACE_END, mp);
1377
1378 mp->table.table_id = ntohl (table_id);
1379 mp->table.is_ip6 = is_ipv6;
1380
1381 S (mp);
1382 W (ret);
1383 return ret;
1384}
1385
1386static int
1387api_ip_table_dump (vat_main_t *vam)
1388{
1389 vl_api_ip_table_dump_t *mp;
1390 vl_api_control_ping_t *mp_ping;
1391 int ret;
1392
1393 M (IP_TABLE_DUMP, mp);
1394 S (mp);
1395
1396 /* Use a control ping for synchronization */
1397 PING (&ip_test_main, mp_ping);
1398 S (mp_ping);
1399
1400 W (ret);
1401 return ret;
1402}
1403
1404static void
1405vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t *mp)
1406{
1407 vat_main_t *vam = ip_test_main.vat_main;
1408
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;
1412}
1413
1414static int
1415api_ip_path_mtu_get (vat_main_t *vat)
1416{
1417 return -1;
1418}
1419
1420static int
1421api_ip_route_v2_dump (vat_main_t *vat)
1422{
1423 return -1;
1424}
1425
1426static void
1427vl_api_ip_path_mtu_get_reply_t_handler (vl_api_ip_path_mtu_get_reply_t *mp)
1428{
1429}
1430
1431static int
1432api_ip_route_dump (vat_main_t *vam)
1433{
1434 unformat_input_t *input = vam->input;
1435 vl_api_ip_route_dump_t *mp;
1436 vl_api_control_ping_t *mp_ping;
1437 u32 table_id;
1438 u8 is_ip6;
1439 int ret;
1440
1441 is_ip6 = 0;
1442 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1443 {
1444 if (unformat (input, "table_id %d", &table_id))
1445 ;
1446 else if (unformat (input, "ip6"))
1447 is_ip6 = 1;
1448 else if (unformat (input, "ip4"))
1449 is_ip6 = 0;
1450 else
1451 break;
1452 }
1453 if (table_id == ~0)
1454 {
1455 errmsg ("missing table id");
1456 return -99;
1457 }
1458
1459 M (IP_ROUTE_DUMP, mp);
1460
1461 mp->table.table_id = table_id;
1462 mp->table.is_ip6 = is_ip6;
1463
1464 S (mp);
1465
1466 /* Use a control ping for synchronization */
1467 PING (&ip_test_main, mp_ping);
1468 S (mp_ping);
1469
1470 W (ret);
1471 return ret;
1472}
1473
1474static void
1475vl_api_ip_address_details_t_handler (vl_api_ip_address_details_t *mp)
1476{
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;
1482
1483 details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1484
1485 if (!details || vam->current_sw_if_index >= vec_len (details) ||
1486 !details[vam->current_sw_if_index].present)
1487 {
1488 errmsg ("ip address details arrived but not stored");
1489 errmsg ("ip_dump should be called first");
1490 return;
1491 }
1492
1493 current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1494
1495#define addresses (current_ip_details->addr)
1496
1497 vec_validate_init_empty (addresses, vec_len (addresses),
1498 empty_ip_address_details);
1499
1500 address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1501
1502 clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
1503 address->prefix_length = mp->prefix.len;
1504#undef addresses
1505}
1506
1507static int
1508api_ip_unnumbered_dump (vat_main_t *vam)
1509{
1510 return -1;
1511}
1512
1513static void
1514vl_api_ip_unnumbered_details_t_handler (vl_api_ip_unnumbered_details_t *mp)
1515{
1516}
1517
1518static void
1519vl_api_ip_details_t_handler (vl_api_ip_details_t *mp)
1520{
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;
1525
1526 sw_if_index = ntohl (mp->sw_if_index);
1527
1528 vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1529 sw_if_index, empty_ip_details);
1530
1531 ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1532 sw_if_index);
1533
1534 ip->present = 1;
1535}
1536
1537#include <vnet/ip/ip.api_test.c>
1538
1539VAT_REGISTER_FEATURE_FUNCTION (vat_ip_plugin_register);
1540
1541/*
1542 * fd.io coding-style-patch-verification: ON
1543 *
1544 * Local Variables:
1545 * eval: (c-set-style "gnu")
1546 * End:
1547 */