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