blob: c47cd3d208e8cc984c625bba03bf962d9b4c3248 [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>
Florin Corasa1400ce2021-09-15 09:02:08 -070033#include <vlibmemory/vlib.api_types.h>
Filip Tehlarabfe3652021-07-23 18:24:19 +000034
35#define vl_endianfun /* define message structures */
36#include <vnet/ip/ip.api.h>
37#undef vl_endianfun
38
39typedef struct
40{
41 /* API message ID base */
42 u16 msg_id_base;
Filip Tehlarabfe3652021-07-23 18:24:19 +000043 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{
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000102 vat_main_t *vam = va_arg (*args, vat_main_t *);
Filip Tehlarabfe3652021-07-23 18:24:19 +0000103 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,
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000116 &path->nh.address.ip4, api_unformat_sw_if_index, vam,
Filip Tehlarabfe3652021-07-23 18:24:19 +0000117 &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,
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000122 &path->nh.address.ip6, api_unformat_sw_if_index, vam,
123 &path->sw_if_index))
Filip Tehlarabfe3652021-07-23 18:24:19 +0000124 {
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{
Filip Tehlarabfe3652021-07-23 18:24:19 +0000240 unformat_input_t *i = vam->input;
241 vl_api_ip_route_add_del_t *mp;
242 u32 vrf_id = 0;
243 u8 is_add = 1;
244 u8 is_multipath = 0;
245 u8 prefix_set = 0;
246 u8 path_count = 0;
247 vl_api_prefix_t pfx = {};
248 vl_api_fib_path_t paths[8];
249 int count = 1;
250 int j;
251 f64 before = 0;
252 u32 random_add_del = 0;
253 u32 *random_vector = 0;
254 u32 random_seed = 0xdeaddabe;
255
256 /* Parse args required to build the message */
257 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
258 {
259 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
260 prefix_set = 1;
261 else if (unformat (i, "del"))
262 is_add = 0;
263 else if (unformat (i, "add"))
264 is_add = 1;
265 else if (unformat (i, "vrf %d", &vrf_id))
266 ;
267 else if (unformat (i, "count %d", &count))
268 ;
269 else if (unformat (i, "random"))
270 random_add_del = 1;
271 else if (unformat (i, "multipath"))
272 is_multipath = 1;
273 else if (unformat (i, "seed %d", &random_seed))
274 ;
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000275 else if (unformat (i, "via %U", unformat_fib_path, vam,
Filip Tehlarabfe3652021-07-23 18:24:19 +0000276 &paths[path_count]))
277 {
278 path_count++;
279 if (8 == path_count)
280 {
281 errmsg ("max 8 paths");
282 return -99;
283 }
284 }
285 else
286 {
287 clib_warning ("parse error '%U'", format_unformat_error, i);
288 return -99;
289 }
290 }
291
292 if (!path_count)
293 {
294 errmsg ("specify a path; via ...");
295 return -99;
296 }
297 if (prefix_set == 0)
298 {
299 errmsg ("missing prefix");
300 return -99;
301 }
302
303 /* Generate a pile of unique, random routes */
304 if (random_add_del)
305 {
306 ip4_address_t *i = (ip4_address_t *) &paths[0].nh.address.ip4;
307 u32 this_random_address;
308 uword *random_hash;
309
310 random_hash = hash_create (count, sizeof (uword));
311
312 hash_set (random_hash, i->as_u32, 1);
313 for (j = 0; j <= count; j++)
314 {
315 do
316 {
317 this_random_address = random_u32 (&random_seed);
318 this_random_address = clib_host_to_net_u32 (this_random_address);
319 }
320 while (hash_get (random_hash, this_random_address));
321 vec_add1 (random_vector, this_random_address);
322 hash_set (random_hash, this_random_address, 1);
323 }
324 hash_free (random_hash);
325 set_ip4_address (&pfx.address, random_vector[0]);
326 }
327
328 if (count > 1)
329 {
330 /* Turn on async mode */
331 vam->async_mode = 1;
332 vam->async_errors = 0;
333 before = vat_time_now (vam);
334 }
335
336 for (j = 0; j < count; j++)
337 {
338 /* Construct the API message */
339 M2 (IP_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path_t) * path_count);
340
341 mp->is_add = is_add;
342 mp->is_multipath = is_multipath;
343
344 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
345 mp->route.table_id = ntohl (vrf_id);
346 mp->route.n_paths = path_count;
347
348 clib_memcpy (&mp->route.paths, &paths, sizeof (paths[0]) * path_count);
349
350 if (random_add_del)
351 set_ip4_address (&pfx.address, random_vector[j + 1]);
352 else
353 increment_address (&pfx.address);
354 /* send it... */
355 S (mp);
356 /* If we receive SIGTERM, stop now... */
357 if (vam->do_exit)
358 break;
359 }
360
361 /* When testing multiple add/del ops, use a control-ping to sync */
362 if (count > 1)
363 {
364 vl_api_control_ping_t *mp_ping;
365 f64 after;
366 f64 timeout;
367
368 /* Shut off async mode */
369 vam->async_mode = 0;
370
371 PING (&ip_test_main, mp_ping);
372 S (mp_ping);
373
374 timeout = vat_time_now (vam) + 1.0;
375 while (vat_time_now (vam) < timeout)
376 if (vam->result_ready == 1)
377 goto out;
378 vam->retval = -99;
379
380 out:
381 if (vam->retval == -99)
382 errmsg ("timeout");
383
384 if (vam->async_errors > 0)
385 {
386 errmsg ("%d asynchronous errors", vam->async_errors);
387 vam->retval = -98;
388 }
389 vam->async_errors = 0;
390 after = vat_time_now (vam);
391
392 /* slim chance, but we might have eaten SIGTERM on the first iteration */
393 if (j > 0)
394 count = j;
395
396 print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", count,
397 after - before, count / (after - before));
398 }
399 else
400 {
401 int ret;
402
403 /* Wait for a reply... */
404 W (ret);
405 return ret;
406 }
407
408 /* Return the good/bad news */
409 return (vam->retval);
410}
411
412static int
413api_ip_table_add_del (vat_main_t *vam)
414{
415 unformat_input_t *i = vam->input;
416 vl_api_ip_table_add_del_t *mp;
417 u32 table_id = ~0;
418 u8 is_ipv6 = 0;
419 u8 is_add = 1;
420 int ret = 0;
421
422 /* Parse args required to build the message */
423 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
424 {
425 if (unformat (i, "ipv6"))
426 is_ipv6 = 1;
427 else if (unformat (i, "del"))
428 is_add = 0;
429 else if (unformat (i, "add"))
430 is_add = 1;
431 else if (unformat (i, "table %d", &table_id))
432 ;
433 else
434 {
435 clib_warning ("parse error '%U'", format_unformat_error, i);
436 return -99;
437 }
438 }
439
440 if (~0 == table_id)
441 {
442 errmsg ("missing table-ID");
443 return -99;
444 }
445
446 /* Construct the API message */
447 M (IP_TABLE_ADD_DEL, mp);
448
449 mp->table.table_id = ntohl (table_id);
450 mp->table.is_ip6 = is_ipv6;
451 mp->is_add = is_add;
452
453 /* send it... */
454 S (mp);
455
456 /* Wait for a reply... */
457 W (ret);
458
459 return ret;
460}
461
462static int
463api_ip_table_replace_begin (vat_main_t *vam)
464{
465 unformat_input_t *i = vam->input;
466 vl_api_ip_table_replace_begin_t *mp;
467 u32 table_id = 0;
468 u8 is_ipv6 = 0;
469
470 int ret;
471 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
472 {
473 if (unformat (i, "table %d", &table_id))
474 ;
475 else if (unformat (i, "ipv6"))
476 is_ipv6 = 1;
477 else
478 {
479 clib_warning ("parse error '%U'", format_unformat_error, i);
480 return -99;
481 }
482 }
483
484 M (IP_TABLE_REPLACE_BEGIN, mp);
485
486 mp->table.table_id = ntohl (table_id);
487 mp->table.is_ip6 = is_ipv6;
488
489 S (mp);
490 W (ret);
491 return ret;
492}
493
494static int
495api_ip_table_flush (vat_main_t *vam)
496{
497 unformat_input_t *i = vam->input;
498 vl_api_ip_table_flush_t *mp;
499 u32 table_id = 0;
500 u8 is_ipv6 = 0;
501
502 int ret;
503 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
504 {
505 if (unformat (i, "table %d", &table_id))
506 ;
507 else if (unformat (i, "ipv6"))
508 is_ipv6 = 1;
509 else
510 {
511 clib_warning ("parse error '%U'", format_unformat_error, i);
512 return -99;
513 }
514 }
515
516 M (IP_TABLE_FLUSH, mp);
517
518 mp->table.table_id = ntohl (table_id);
519 mp->table.is_ip6 = is_ipv6;
520
521 S (mp);
522 W (ret);
523 return ret;
524}
525
Aloys Augustin6e4cfb52021-09-16 20:53:14 +0200526static int
527api_ip_table_allocate (vat_main_t *vam)
528{
529 return -1;
530}
531
532static void
533vl_api_ip_table_allocate_reply_t_handler (vl_api_ip_table_allocate_reply_t *mp)
534{
535}
536
Filip Tehlarabfe3652021-07-23 18:24:19 +0000537static void
538vl_api_ip_route_add_del_v2_reply_t_handler (
539 vl_api_ip_route_add_del_v2_reply_t *mp)
540{
541}
542
543static void
544vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t *mp)
545{
546}
547
548static void
549vl_api_ip_route_v2_details_t_handler (vl_api_ip_route_v2_details_t *mp)
550{
551}
552
553static void
554vl_api_ip_route_add_del_reply_t_handler (vl_api_ip_route_add_del_reply_t *mp)
555{
556 vat_main_t *vam = ip_test_main.vat_main;
557 vam->result_ready = 1;
558}
559
560static void
561vl_api_ip_route_lookup_reply_t_handler (vl_api_ip_route_lookup_reply_t *mp)
562{
563}
564
565static void
566vl_api_ip_route_lookup_v2_reply_t_handler (
567 vl_api_ip_route_lookup_v2_reply_t *mp)
568{
569}
570
571static int
572api_set_ip_flow_hash_router_id (vat_main_t *vat)
573{
574 return -1;
575}
576
577static int
578api_ip_route_lookup (vat_main_t *vat)
579{
580 return -1;
581}
582
583static int
584api_ip_route_lookup_v2 (vat_main_t *vat)
585{
586 return -1;
587}
588
589static int
590api_set_ip_flow_hash (vat_main_t *vam)
591{
592 unformat_input_t *i = vam->input;
593 vl_api_set_ip_flow_hash_t *mp;
594 u32 vrf_id = 0;
595 u8 is_ipv6 = 0;
596 u8 vrf_id_set = 0;
597 u8 src = 0;
598 u8 dst = 0;
599 u8 sport = 0;
600 u8 dport = 0;
601 u8 proto = 0;
602 u8 reverse = 0;
603 int ret;
604
605 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
606 {
607 if (unformat (i, "vrf %d", &vrf_id))
608 vrf_id_set = 1;
609 else if (unformat (i, "ipv6"))
610 is_ipv6 = 1;
611 else if (unformat (i, "src"))
612 src = 1;
613 else if (unformat (i, "dst"))
614 dst = 1;
615 else if (unformat (i, "sport"))
616 sport = 1;
617 else if (unformat (i, "dport"))
618 dport = 1;
619 else if (unformat (i, "proto"))
620 proto = 1;
621 else if (unformat (i, "reverse"))
622 reverse = 1;
623
624 else
625 {
626 clib_warning ("parse error '%U'", format_unformat_error, i);
627 return -99;
628 }
629 }
630
631 if (vrf_id_set == 0)
632 {
633 errmsg ("missing vrf id");
634 return -99;
635 }
636
637 M (SET_IP_FLOW_HASH, mp);
638 mp->src = src;
639 mp->dst = dst;
640 mp->sport = sport;
641 mp->dport = dport;
642 mp->proto = proto;
643 mp->reverse = reverse;
644 mp->vrf_id = ntohl (vrf_id);
645 mp->is_ipv6 = is_ipv6;
646
647 S (mp);
648 W (ret);
649 return ret;
650}
651
652static int
653api_mfib_signal_dump (vat_main_t *vat)
654{
655 return -1;
656}
657
658static int
659api_ip_punt_police (vat_main_t *vat)
660{
661 return -1;
662}
663
664static int
665api_ip_punt_redirect (vat_main_t *vat)
666{
667 return -1;
668}
669
670static int
Nathan Skrzypczak2a1783f2021-08-10 15:05:29 +0200671api_add_del_ip_punt_redirect_v2 (vat_main_t *vat)
672{
673 return -1;
674}
675
676static int
Filip Tehlarabfe3652021-07-23 18:24:19 +0000677api_ip_punt_redirect_dump (vat_main_t *vat)
678{
679 return -1;
680}
681
682static void
683vl_api_ip_punt_redirect_details_t_handler (
684 vl_api_ip_punt_redirect_details_t *mp)
685{
Nathan Skrzypczak2a1783f2021-08-10 15:05:29 +0200686 /**/
687}
688
689static int
690api_ip_punt_redirect_v2_dump (vat_main_t *vat)
691{
692 return -1;
693}
694
695static void
696vl_api_ip_punt_redirect_v2_details_t_handler (
697 vl_api_ip_punt_redirect_v2_details_t *mp)
698{
699 /**/
Filip Tehlarabfe3652021-07-23 18:24:19 +0000700}
701
702static int
703api_ip_address_dump (vat_main_t *vam)
704{
Filip Tehlarabfe3652021-07-23 18:24:19 +0000705 unformat_input_t *i = vam->input;
706 vl_api_ip_address_dump_t *mp;
707 vl_api_control_ping_t *mp_ping;
708 u32 sw_if_index = ~0;
709 u8 sw_if_index_set = 0;
710 u8 ipv4_set = 0;
711 u8 ipv6_set = 0;
712 int ret;
713
714 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
715 {
716 if (unformat (i, "sw_if_index %d", &sw_if_index))
717 sw_if_index_set = 1;
Filip Tehlarf0e67d72021-07-23 22:03:05 +0000718 else if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
Filip Tehlarabfe3652021-07-23 18:24:19 +0000719 sw_if_index_set = 1;
720 else if (unformat (i, "ipv4"))
721 ipv4_set = 1;
722 else if (unformat (i, "ipv6"))
723 ipv6_set = 1;
724 else
725 break;
726 }
727
728 if (ipv4_set && ipv6_set)
729 {
730 errmsg ("ipv4 and ipv6 flags cannot be both set");
731 return -99;
732 }
733
734 if ((!ipv4_set) && (!ipv6_set))
735 {
736 errmsg ("no ipv4 nor ipv6 flag set");
737 return -99;
738 }
739
740 if (sw_if_index_set == 0)
741 {
742 errmsg ("missing interface name or sw_if_index");
743 return -99;
744 }
745
746 vam->current_sw_if_index = sw_if_index;
747 vam->is_ipv6 = ipv6_set;
748
749 M (IP_ADDRESS_DUMP, mp);
750 mp->sw_if_index = ntohl (sw_if_index);
751 mp->is_ipv6 = ipv6_set;
752 S (mp);
753
754 /* Use a control ping for synchronization */
755 PING (&ip_test_main, mp_ping);
756 S (mp_ping);
757
758 W (ret);
759 return ret;
760}
761
762static void
763vl_api_sw_interface_ip6_get_link_local_address_reply_t_handler (
764 vl_api_sw_interface_ip6_get_link_local_address_reply_t *mp)
765{
766}
767
768static int
769api_sw_interface_ip6_set_link_local_address (vat_main_t *vam)
770{
771 return -1;
772}
773
774static int
775api_sw_interface_ip6_get_link_local_address (vat_main_t *vam)
776{
777 return -1;
778}
779
780static int
781api_ip_path_mtu_replace_end (vat_main_t *vam)
782{
783 return -1;
784}
785
786static int
787api_ioam_enable (vat_main_t *vam)
788{
789 unformat_input_t *input = vam->input;
790 vl_api_ioam_enable_t *mp;
791 u32 id = 0;
792 int has_trace_option = 0;
793 int has_pot_option = 0;
794 int has_seqno_option = 0;
795 int has_analyse_option = 0;
796 int ret;
797
798 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
799 {
800 if (unformat (input, "trace"))
801 has_trace_option = 1;
802 else if (unformat (input, "pot"))
803 has_pot_option = 1;
804 else if (unformat (input, "seqno"))
805 has_seqno_option = 1;
806 else if (unformat (input, "analyse"))
807 has_analyse_option = 1;
808 else
809 break;
810 }
811 M (IOAM_ENABLE, mp);
812 mp->id = htons (id);
813 mp->seqno = has_seqno_option;
814 mp->analyse = has_analyse_option;
815 mp->pot_enable = has_pot_option;
816 mp->trace_enable = has_trace_option;
817
818 S (mp);
819 W (ret);
820 return ret;
821}
822
823static int
824api_ip_reassembly_get (vat_main_t *vam)
825{
826 return -1;
827}
828
829static int
830api_ip_path_mtu_replace_begin (vat_main_t *vam)
831{
832 return -1;
833}
834
835static int
836api_ip_path_mtu_update (vat_main_t *vam)
837{
838 return -1;
839}
840
841static int
842api_ioam_disable (vat_main_t *vam)
843{
844 vl_api_ioam_disable_t *mp;
845 int ret;
846
847 M (IOAM_DISABLE, mp);
848 S (mp);
849 W (ret);
850 return ret;
851}
852
853static int
854api_ip_source_and_port_range_check_add_del (vat_main_t *vam)
855{
856 unformat_input_t *input = vam->input;
857 vl_api_ip_source_and_port_range_check_add_del_t *mp;
858
859 u16 *low_ports = 0;
860 u16 *high_ports = 0;
861 u16 this_low;
862 u16 this_hi;
863 vl_api_prefix_t prefix;
864 u32 tmp, tmp2;
865 u8 prefix_set = 0;
866 u32 vrf_id = ~0;
867 u8 is_add = 1;
868 int ret;
869
870 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
871 {
872 if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
873 prefix_set = 1;
874 else if (unformat (input, "vrf %d", &vrf_id))
875 ;
876 else if (unformat (input, "del"))
877 is_add = 0;
878 else if (unformat (input, "port %d", &tmp))
879 {
880 if (tmp == 0 || tmp > 65535)
881 {
882 errmsg ("port %d out of range", tmp);
883 return -99;
884 }
885 this_low = tmp;
886 this_hi = this_low + 1;
887 vec_add1 (low_ports, this_low);
888 vec_add1 (high_ports, this_hi);
889 }
890 else if (unformat (input, "range %d - %d", &tmp, &tmp2))
891 {
892 if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
893 {
894 errmsg ("incorrect range parameters");
895 return -99;
896 }
897 this_low = tmp;
898 /* Note: in debug CLI +1 is added to high before
899 passing to real fn that does "the work"
900 (ip_source_and_port_range_check_add_del).
901 This fn is a wrapper around the binary API fn a
902 control plane will call, which expects this increment
903 to have occurred. Hence letting the binary API control
904 plane fn do the increment for consistency between VAT
905 and other control planes.
906 */
907 this_hi = tmp2;
908 vec_add1 (low_ports, this_low);
909 vec_add1 (high_ports, this_hi);
910 }
911 else
912 break;
913 }
914
915 if (prefix_set == 0)
916 {
917 errmsg ("<address>/<mask> not specified");
918 return -99;
919 }
920
921 if (vrf_id == ~0)
922 {
923 errmsg ("VRF ID required, not specified");
924 return -99;
925 }
926
927 if (vrf_id == 0)
928 {
929 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
930 "purpose.");
931 return -99;
932 }
933
934 if (vec_len (low_ports) == 0)
935 {
936 errmsg ("At least one port or port range required");
937 return -99;
938 }
939
940 M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
941
942 mp->is_add = is_add;
943
944 clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
945
946 mp->number_of_ranges = vec_len (low_ports);
947
948 clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
949 vec_free (low_ports);
950
951 clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
952 vec_free (high_ports);
953
954 mp->vrf_id = ntohl (vrf_id);
955
956 S (mp);
957 W (ret);
958 return ret;
959}
960
961static int
962api_ip_reassembly_set (vat_main_t *vat)
963{
964 return -1;
965}
966
967static int
968api_ip_container_proxy_add_del (vat_main_t *vam)
969{
970 vl_api_ip_container_proxy_add_del_t *mp;
971 unformat_input_t *i = vam->input;
972 u32 sw_if_index = ~0;
973 vl_api_prefix_t pfx = {};
974 u8 is_add = 1;
975 int ret;
976
977 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
978 {
979 if (unformat (i, "del"))
980 is_add = 0;
981 else if (unformat (i, "add"))
982 ;
983 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
984 ;
985 else if (unformat (i, "sw_if_index %u", &sw_if_index))
986 ;
987 else
988 break;
989 }
990 if (sw_if_index == ~0 || pfx.len == 0)
991 {
992 errmsg ("address and sw_if_index must be set");
993 return -99;
994 }
995
996 M (IP_CONTAINER_PROXY_ADD_DEL, mp);
997
998 mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
999 mp->is_add = is_add;
1000 clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
1001
1002 S (mp);
1003 W (ret);
1004 return ret;
1005}
1006
1007static int
1008api_ip_reassembly_enable_disable (vat_main_t *vat)
1009{
1010 return -1;
1011}
1012
1013static void
1014vl_api_ip_reassembly_get_reply_t_handler (vl_api_ip_reassembly_get_reply_t *mp)
1015{
1016}
1017
1018int
1019api_ip_source_and_port_range_check_interface_add_del (vat_main_t *vam)
1020{
Filip Tehlarabfe3652021-07-23 18:24:19 +00001021 unformat_input_t *input = vam->input;
1022 vl_api_ip_source_and_port_range_check_interface_add_del_t *mp;
1023 u32 sw_if_index = ~0;
1024 int vrf_set = 0;
1025 u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0;
1026 u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0;
1027 u8 is_add = 1;
1028 int ret;
1029
1030 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1031 {
Filip Tehlarf0e67d72021-07-23 22:03:05 +00001032 if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
Filip Tehlarabfe3652021-07-23 18:24:19 +00001033 ;
1034 else if (unformat (input, "sw_if_index %d", &sw_if_index))
1035 ;
1036 else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
1037 vrf_set = 1;
1038 else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
1039 vrf_set = 1;
1040 else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
1041 vrf_set = 1;
1042 else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
1043 vrf_set = 1;
1044 else if (unformat (input, "del"))
1045 is_add = 0;
1046 else
1047 break;
1048 }
1049
1050 if (sw_if_index == ~0)
1051 {
1052 errmsg ("Interface required but not specified");
1053 return -99;
1054 }
1055
1056 if (vrf_set == 0)
1057 {
1058 errmsg ("VRF ID required but not specified");
1059 return -99;
1060 }
1061
1062 if (tcp_out_vrf_id == 0 || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 ||
1063 udp_in_vrf_id == 0)
1064 {
1065 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
1066 "purpose.");
1067 return -99;
1068 }
1069
1070 /* Construct the API message */
1071 M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
1072
1073 mp->sw_if_index = ntohl (sw_if_index);
1074 mp->is_add = is_add;
1075 mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
1076 mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
1077 mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
1078 mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
1079
1080 /* send it... */
1081 S (mp);
1082
1083 /* Wait for a reply... */
1084 W (ret);
1085 return ret;
1086}
1087
1088static void
1089vl_api_ip_container_proxy_details_t_handler (
1090 vl_api_ip_container_proxy_details_t *mp)
1091{
1092}
1093
1094static int
1095api_ip_container_proxy_dump (vat_main_t *vam)
1096{
1097 return -1;
1098}
1099
1100static int
1101api_ip_dump (vat_main_t *vam)
1102{
1103 vl_api_ip_dump_t *mp;
1104 vl_api_control_ping_t *mp_ping;
1105 unformat_input_t *in = vam->input;
1106 int ipv4_set = 0;
1107 int ipv6_set = 0;
1108 int is_ipv6;
1109 int i;
1110 int ret;
1111
1112 while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
1113 {
1114 if (unformat (in, "ipv4"))
1115 ipv4_set = 1;
1116 else if (unformat (in, "ipv6"))
1117 ipv6_set = 1;
1118 else
1119 break;
1120 }
1121
1122 if (ipv4_set && ipv6_set)
1123 {
1124 errmsg ("ipv4 and ipv6 flags cannot be both set");
1125 return -99;
1126 }
1127
1128 if ((!ipv4_set) && (!ipv6_set))
1129 {
1130 errmsg ("no ipv4 nor ipv6 flag set");
1131 return -99;
1132 }
1133
1134 is_ipv6 = ipv6_set;
1135 vam->is_ipv6 = is_ipv6;
1136
1137 /* free old data */
1138 for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
1139 {
1140 vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
1141 }
1142 vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
1143
1144 M (IP_DUMP, mp);
1145 mp->is_ipv6 = ipv6_set;
1146 S (mp);
1147
1148 /* Use a control ping for synchronization */
1149 PING (&ip_test_main, mp_ping);
1150 S (mp_ping);
1151
1152 W (ret);
1153 return ret;
1154}
1155
1156static void
1157vl_api_mfib_signal_details_t_handler (vl_api_mfib_signal_details_t *mp)
1158{
1159}
1160
1161static void
1162vl_api_ip_mroute_details_t_handler (vl_api_ip_mroute_details_t *mp)
1163{
1164 vat_main_t *vam = ip_test_main.vat_main;
1165 vam->result_ready = 1;
1166}
1167
1168static int
1169api_ip_mroute_dump (vat_main_t *vam)
1170{
1171 unformat_input_t *input = vam->input;
1172 vl_api_control_ping_t *mp_ping;
1173 vl_api_ip_mroute_dump_t *mp;
1174 int ret, is_ip6;
1175 u32 table_id;
1176
1177 is_ip6 = 0;
1178 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1179 {
1180 if (unformat (input, "table_id %d", &table_id))
1181 ;
1182 else if (unformat (input, "ip6"))
1183 is_ip6 = 1;
1184 else if (unformat (input, "ip4"))
1185 is_ip6 = 0;
1186 else
1187 break;
1188 }
1189 if (table_id == ~0)
1190 {
1191 errmsg ("missing table id");
1192 return -99;
1193 }
1194
1195 M (IP_MROUTE_DUMP, mp);
1196 mp->table.table_id = table_id;
1197 mp->table.is_ip6 = is_ip6;
1198 S (mp);
1199
1200 /* Use a control ping for synchronization */
1201 PING (&ip_test_main, mp_ping);
1202 S (mp_ping);
1203
1204 W (ret);
1205 return ret;
1206}
1207
1208static int
1209api_sw_interface_ip6_enable_disable (vat_main_t *vam)
1210{
Filip Tehlarabfe3652021-07-23 18:24:19 +00001211 unformat_input_t *i = vam->input;
1212 vl_api_sw_interface_ip6_enable_disable_t *mp;
1213 u32 sw_if_index;
1214 u8 sw_if_index_set = 0;
1215 u8 enable = 0;
1216 int ret;
1217
1218 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1219 {
Filip Tehlarf0e67d72021-07-23 22:03:05 +00001220 if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
Filip Tehlarabfe3652021-07-23 18:24:19 +00001221 sw_if_index_set = 1;
1222 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1223 sw_if_index_set = 1;
1224 else if (unformat (i, "enable"))
1225 enable = 1;
1226 else if (unformat (i, "disable"))
1227 enable = 0;
1228 else
1229 {
1230 clib_warning ("parse error '%U'", format_unformat_error, i);
1231 return -99;
1232 }
1233 }
1234
1235 if (sw_if_index_set == 0)
1236 {
1237 errmsg ("missing interface name or sw_if_index");
1238 return -99;
1239 }
1240
1241 M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
1242
1243 mp->sw_if_index = ntohl (sw_if_index);
1244 mp->enable = enable;
1245
1246 S (mp);
1247 W (ret);
1248 return ret;
1249}
1250
1251static int
1252api_set_ip_flow_hash_v2 (vat_main_t *vat)
1253{
1254 return -1;
1255}
1256
1257static int
1258api_ip_mroute_add_del (vat_main_t *vam)
1259{
1260 unformat_input_t *i = vam->input;
1261 u8 path_set = 0, prefix_set = 0, is_add = 1;
1262 vl_api_ip_mroute_add_del_t *mp;
1263 mfib_entry_flags_t eflags = 0;
1264 vl_api_mfib_path_t path;
1265 vl_api_mprefix_t pfx = {};
1266 u32 vrf_id = 0;
1267 int ret;
1268
1269 /* Parse args required to build the message */
1270 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1271 {
1272 if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
1273 {
1274 prefix_set = 1;
1275 pfx.grp_address_length = htons (pfx.grp_address_length);
1276 }
1277 else if (unformat (i, "del"))
1278 is_add = 0;
1279 else if (unformat (i, "add"))
1280 is_add = 1;
1281 else if (unformat (i, "vrf %d", &vrf_id))
1282 ;
1283 else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
1284 path.itf_flags = htonl (path.itf_flags);
1285 else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
1286 ;
1287 else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
1288 path_set = 1;
1289 else
1290 {
1291 clib_warning ("parse error '%U'", format_unformat_error, i);
1292 return -99;
1293 }
1294 }
1295
1296 if (prefix_set == 0)
1297 {
1298 errmsg ("missing addresses\n");
1299 return -99;
1300 }
1301 if (path_set == 0)
1302 {
1303 errmsg ("missing path\n");
1304 return -99;
1305 }
1306
1307 /* Construct the API message */
1308 M (IP_MROUTE_ADD_DEL, mp);
1309
1310 mp->is_add = is_add;
1311 mp->is_multipath = 1;
1312
1313 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
1314 mp->route.table_id = htonl (vrf_id);
1315 mp->route.n_paths = 1;
1316 mp->route.entry_flags = htonl (eflags);
1317
1318 clib_memcpy (&mp->route.paths, &path, sizeof (path));
1319
1320 /* send it... */
1321 S (mp);
1322 /* Wait for a reply... */
1323 W (ret);
1324 return ret;
1325}
1326
1327static void
1328vl_api_ip_mroute_add_del_reply_t_handler (vl_api_ip_mroute_add_del_reply_t *mp)
1329{
1330 vat_main_t *vam = ip_test_main.vat_main;
1331 vam->result_ready = 1;
1332}
1333
1334static int
1335api_ip_mtable_dump (vat_main_t *vam)
1336{
1337 vl_api_ip_mtable_dump_t *mp;
1338 vl_api_control_ping_t *mp_ping;
1339 int ret;
1340
1341 M (IP_MTABLE_DUMP, mp);
1342 S (mp);
1343
1344 /* Use a control ping for synchronization */
1345 PING (&ip_test_main, mp_ping);
1346 S (mp_ping);
1347
1348 W (ret);
1349 return ret;
1350}
1351
1352static void
1353vl_api_ip_mtable_details_t_handler (vl_api_ip_mtable_details_t *mp)
1354{
1355 vat_main_t *vam = ip_test_main.vat_main;
1356 vam->result_ready = 1;
1357}
1358
1359static int
1360api_ip_table_replace_end (vat_main_t *vam)
1361{
1362 unformat_input_t *i = vam->input;
1363 vl_api_ip_table_replace_end_t *mp;
1364 u32 table_id = 0;
1365 u8 is_ipv6 = 0;
1366
1367 int ret;
1368 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1369 {
1370 if (unformat (i, "table %d", &table_id))
1371 ;
1372 else if (unformat (i, "ipv6"))
1373 is_ipv6 = 1;
1374 else
1375 {
1376 clib_warning ("parse error '%U'", format_unformat_error, i);
1377 return -99;
1378 }
1379 }
1380
1381 M (IP_TABLE_REPLACE_END, mp);
1382
1383 mp->table.table_id = ntohl (table_id);
1384 mp->table.is_ip6 = is_ipv6;
1385
1386 S (mp);
1387 W (ret);
1388 return ret;
1389}
1390
1391static int
1392api_ip_table_dump (vat_main_t *vam)
1393{
1394 vl_api_ip_table_dump_t *mp;
1395 vl_api_control_ping_t *mp_ping;
1396 int ret;
1397
1398 M (IP_TABLE_DUMP, mp);
1399 S (mp);
1400
1401 /* Use a control ping for synchronization */
1402 PING (&ip_test_main, mp_ping);
1403 S (mp_ping);
1404
1405 W (ret);
1406 return ret;
1407}
1408
1409static void
1410vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t *mp)
1411{
1412 vat_main_t *vam = ip_test_main.vat_main;
1413
1414 fformat (vam->ofp, "%s; table-id %d, prefix %U/%d", mp->table.name,
1415 ntohl (mp->table.table_id));
1416 vam->result_ready = 1;
1417}
1418
1419static int
1420api_ip_path_mtu_get (vat_main_t *vat)
1421{
1422 return -1;
1423}
1424
1425static int
1426api_ip_route_v2_dump (vat_main_t *vat)
1427{
1428 return -1;
1429}
1430
1431static void
1432vl_api_ip_path_mtu_get_reply_t_handler (vl_api_ip_path_mtu_get_reply_t *mp)
1433{
1434}
1435
1436static int
1437api_ip_route_dump (vat_main_t *vam)
1438{
1439 unformat_input_t *input = vam->input;
1440 vl_api_ip_route_dump_t *mp;
1441 vl_api_control_ping_t *mp_ping;
1442 u32 table_id;
1443 u8 is_ip6;
1444 int ret;
1445
1446 is_ip6 = 0;
1447 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1448 {
1449 if (unformat (input, "table_id %d", &table_id))
1450 ;
1451 else if (unformat (input, "ip6"))
1452 is_ip6 = 1;
1453 else if (unformat (input, "ip4"))
1454 is_ip6 = 0;
1455 else
1456 break;
1457 }
1458 if (table_id == ~0)
1459 {
1460 errmsg ("missing table id");
1461 return -99;
1462 }
1463
1464 M (IP_ROUTE_DUMP, mp);
1465
1466 mp->table.table_id = table_id;
1467 mp->table.is_ip6 = is_ip6;
1468
1469 S (mp);
1470
1471 /* Use a control ping for synchronization */
1472 PING (&ip_test_main, mp_ping);
1473 S (mp_ping);
1474
1475 W (ret);
1476 return ret;
1477}
1478
1479static void
1480vl_api_ip_address_details_t_handler (vl_api_ip_address_details_t *mp)
1481{
1482 vat_main_t *vam = ip_test_main.vat_main;
1483 static ip_address_details_t empty_ip_address_details = { { 0 } };
1484 ip_address_details_t *address = NULL;
1485 ip_details_t *current_ip_details = NULL;
1486 ip_details_t *details = NULL;
1487
1488 details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1489
1490 if (!details || vam->current_sw_if_index >= vec_len (details) ||
1491 !details[vam->current_sw_if_index].present)
1492 {
1493 errmsg ("ip address details arrived but not stored");
1494 errmsg ("ip_dump should be called first");
1495 return;
1496 }
1497
1498 current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1499
1500#define addresses (current_ip_details->addr)
1501
1502 vec_validate_init_empty (addresses, vec_len (addresses),
1503 empty_ip_address_details);
1504
1505 address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1506
1507 clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
1508 address->prefix_length = mp->prefix.len;
1509#undef addresses
1510}
1511
1512static int
1513api_ip_unnumbered_dump (vat_main_t *vam)
1514{
1515 return -1;
1516}
1517
1518static void
1519vl_api_ip_unnumbered_details_t_handler (vl_api_ip_unnumbered_details_t *mp)
1520{
1521}
1522
1523static void
1524vl_api_ip_details_t_handler (vl_api_ip_details_t *mp)
1525{
1526 vat_main_t *vam = &vat_main;
1527 static ip_details_t empty_ip_details = { 0 };
1528 ip_details_t *ip = NULL;
1529 u32 sw_if_index = ~0;
1530
1531 sw_if_index = ntohl (mp->sw_if_index);
1532
1533 vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1534 sw_if_index, empty_ip_details);
1535
1536 ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1537 sw_if_index);
1538
1539 ip->present = 1;
1540}
1541
1542#include <vnet/ip/ip.api_test.c>
1543
Filip Tehlarabfe3652021-07-23 18:24:19 +00001544/*
1545 * fd.io coding-style-patch-verification: ON
1546 *
1547 * Local Variables:
1548 * eval: (c-set-style "gnu")
1549 * End:
1550 */