blob: 81a84c12a3bc7df942b28ea81e7fb325a01aefc1 [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
Aloys Augustin6e4cfb52021-09-16 20:53:14 +0200527static int
528api_ip_table_allocate (vat_main_t *vam)
529{
530 return -1;
531}
532
533static void
534vl_api_ip_table_allocate_reply_t_handler (vl_api_ip_table_allocate_reply_t *mp)
535{
536}
537
Filip Tehlarabfe3652021-07-23 18:24:19 +0000538static void
539vl_api_ip_route_add_del_v2_reply_t_handler (
540 vl_api_ip_route_add_del_v2_reply_t *mp)
541{
542}
543
544static void
545vl_api_ip_route_details_t_handler (vl_api_ip_route_details_t *mp)
546{
547}
548
549static void
550vl_api_ip_route_v2_details_t_handler (vl_api_ip_route_v2_details_t *mp)
551{
552}
553
554static void
555vl_api_ip_route_add_del_reply_t_handler (vl_api_ip_route_add_del_reply_t *mp)
556{
557 vat_main_t *vam = ip_test_main.vat_main;
558 vam->result_ready = 1;
559}
560
561static void
562vl_api_ip_route_lookup_reply_t_handler (vl_api_ip_route_lookup_reply_t *mp)
563{
564}
565
566static void
567vl_api_ip_route_lookup_v2_reply_t_handler (
568 vl_api_ip_route_lookup_v2_reply_t *mp)
569{
570}
571
572static int
573api_set_ip_flow_hash_router_id (vat_main_t *vat)
574{
575 return -1;
576}
577
578static int
579api_ip_route_lookup (vat_main_t *vat)
580{
581 return -1;
582}
583
584static int
585api_ip_route_lookup_v2 (vat_main_t *vat)
586{
587 return -1;
588}
589
590static int
591api_set_ip_flow_hash (vat_main_t *vam)
592{
593 unformat_input_t *i = vam->input;
594 vl_api_set_ip_flow_hash_t *mp;
595 u32 vrf_id = 0;
596 u8 is_ipv6 = 0;
597 u8 vrf_id_set = 0;
598 u8 src = 0;
599 u8 dst = 0;
600 u8 sport = 0;
601 u8 dport = 0;
602 u8 proto = 0;
603 u8 reverse = 0;
604 int ret;
605
606 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
607 {
608 if (unformat (i, "vrf %d", &vrf_id))
609 vrf_id_set = 1;
610 else if (unformat (i, "ipv6"))
611 is_ipv6 = 1;
612 else if (unformat (i, "src"))
613 src = 1;
614 else if (unformat (i, "dst"))
615 dst = 1;
616 else if (unformat (i, "sport"))
617 sport = 1;
618 else if (unformat (i, "dport"))
619 dport = 1;
620 else if (unformat (i, "proto"))
621 proto = 1;
622 else if (unformat (i, "reverse"))
623 reverse = 1;
624
625 else
626 {
627 clib_warning ("parse error '%U'", format_unformat_error, i);
628 return -99;
629 }
630 }
631
632 if (vrf_id_set == 0)
633 {
634 errmsg ("missing vrf id");
635 return -99;
636 }
637
638 M (SET_IP_FLOW_HASH, mp);
639 mp->src = src;
640 mp->dst = dst;
641 mp->sport = sport;
642 mp->dport = dport;
643 mp->proto = proto;
644 mp->reverse = reverse;
645 mp->vrf_id = ntohl (vrf_id);
646 mp->is_ipv6 = is_ipv6;
647
648 S (mp);
649 W (ret);
650 return ret;
651}
652
653static int
654api_mfib_signal_dump (vat_main_t *vat)
655{
656 return -1;
657}
658
659static int
660api_ip_punt_police (vat_main_t *vat)
661{
662 return -1;
663}
664
665static int
666api_ip_punt_redirect (vat_main_t *vat)
667{
668 return -1;
669}
670
671static int
Nathan Skrzypczak2a1783f2021-08-10 15:05:29 +0200672api_add_del_ip_punt_redirect_v2 (vat_main_t *vat)
673{
674 return -1;
675}
676
677static int
Filip Tehlarabfe3652021-07-23 18:24:19 +0000678api_ip_punt_redirect_dump (vat_main_t *vat)
679{
680 return -1;
681}
682
683static void
684vl_api_ip_punt_redirect_details_t_handler (
685 vl_api_ip_punt_redirect_details_t *mp)
686{
Nathan Skrzypczak2a1783f2021-08-10 15:05:29 +0200687 /**/
688}
689
690static int
691api_ip_punt_redirect_v2_dump (vat_main_t *vat)
692{
693 return -1;
694}
695
696static void
697vl_api_ip_punt_redirect_v2_details_t_handler (
698 vl_api_ip_punt_redirect_v2_details_t *mp)
699{
700 /**/
Filip Tehlarabfe3652021-07-23 18:24:19 +0000701}
702
703static int
704api_ip_address_dump (vat_main_t *vam)
705{
706 vnet_main_t *vnm = vnet_get_main ();
707 unformat_input_t *i = vam->input;
708 vl_api_ip_address_dump_t *mp;
709 vl_api_control_ping_t *mp_ping;
710 u32 sw_if_index = ~0;
711 u8 sw_if_index_set = 0;
712 u8 ipv4_set = 0;
713 u8 ipv6_set = 0;
714 int ret;
715
716 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
717 {
718 if (unformat (i, "sw_if_index %d", &sw_if_index))
719 sw_if_index_set = 1;
720 else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
721 &sw_if_index))
722 sw_if_index_set = 1;
723 else if (unformat (i, "ipv4"))
724 ipv4_set = 1;
725 else if (unformat (i, "ipv6"))
726 ipv6_set = 1;
727 else
728 break;
729 }
730
731 if (ipv4_set && ipv6_set)
732 {
733 errmsg ("ipv4 and ipv6 flags cannot be both set");
734 return -99;
735 }
736
737 if ((!ipv4_set) && (!ipv6_set))
738 {
739 errmsg ("no ipv4 nor ipv6 flag set");
740 return -99;
741 }
742
743 if (sw_if_index_set == 0)
744 {
745 errmsg ("missing interface name or sw_if_index");
746 return -99;
747 }
748
749 vam->current_sw_if_index = sw_if_index;
750 vam->is_ipv6 = ipv6_set;
751
752 M (IP_ADDRESS_DUMP, mp);
753 mp->sw_if_index = ntohl (sw_if_index);
754 mp->is_ipv6 = ipv6_set;
755 S (mp);
756
757 /* Use a control ping for synchronization */
758 PING (&ip_test_main, mp_ping);
759 S (mp_ping);
760
761 W (ret);
762 return ret;
763}
764
765static void
766vl_api_sw_interface_ip6_get_link_local_address_reply_t_handler (
767 vl_api_sw_interface_ip6_get_link_local_address_reply_t *mp)
768{
769}
770
771static int
772api_sw_interface_ip6_set_link_local_address (vat_main_t *vam)
773{
774 return -1;
775}
776
777static int
778api_sw_interface_ip6_get_link_local_address (vat_main_t *vam)
779{
780 return -1;
781}
782
783static int
784api_ip_path_mtu_replace_end (vat_main_t *vam)
785{
786 return -1;
787}
788
789static int
790api_ioam_enable (vat_main_t *vam)
791{
792 unformat_input_t *input = vam->input;
793 vl_api_ioam_enable_t *mp;
794 u32 id = 0;
795 int has_trace_option = 0;
796 int has_pot_option = 0;
797 int has_seqno_option = 0;
798 int has_analyse_option = 0;
799 int ret;
800
801 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
802 {
803 if (unformat (input, "trace"))
804 has_trace_option = 1;
805 else if (unformat (input, "pot"))
806 has_pot_option = 1;
807 else if (unformat (input, "seqno"))
808 has_seqno_option = 1;
809 else if (unformat (input, "analyse"))
810 has_analyse_option = 1;
811 else
812 break;
813 }
814 M (IOAM_ENABLE, mp);
815 mp->id = htons (id);
816 mp->seqno = has_seqno_option;
817 mp->analyse = has_analyse_option;
818 mp->pot_enable = has_pot_option;
819 mp->trace_enable = has_trace_option;
820
821 S (mp);
822 W (ret);
823 return ret;
824}
825
826static int
827api_ip_reassembly_get (vat_main_t *vam)
828{
829 return -1;
830}
831
832static int
833api_ip_path_mtu_replace_begin (vat_main_t *vam)
834{
835 return -1;
836}
837
838static int
839api_ip_path_mtu_update (vat_main_t *vam)
840{
841 return -1;
842}
843
844static int
845api_ioam_disable (vat_main_t *vam)
846{
847 vl_api_ioam_disable_t *mp;
848 int ret;
849
850 M (IOAM_DISABLE, mp);
851 S (mp);
852 W (ret);
853 return ret;
854}
855
856static int
857api_ip_source_and_port_range_check_add_del (vat_main_t *vam)
858{
859 unformat_input_t *input = vam->input;
860 vl_api_ip_source_and_port_range_check_add_del_t *mp;
861
862 u16 *low_ports = 0;
863 u16 *high_ports = 0;
864 u16 this_low;
865 u16 this_hi;
866 vl_api_prefix_t prefix;
867 u32 tmp, tmp2;
868 u8 prefix_set = 0;
869 u32 vrf_id = ~0;
870 u8 is_add = 1;
871 int ret;
872
873 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
874 {
875 if (unformat (input, "%U", unformat_vl_api_prefix, &prefix))
876 prefix_set = 1;
877 else if (unformat (input, "vrf %d", &vrf_id))
878 ;
879 else if (unformat (input, "del"))
880 is_add = 0;
881 else if (unformat (input, "port %d", &tmp))
882 {
883 if (tmp == 0 || tmp > 65535)
884 {
885 errmsg ("port %d out of range", tmp);
886 return -99;
887 }
888 this_low = tmp;
889 this_hi = this_low + 1;
890 vec_add1 (low_ports, this_low);
891 vec_add1 (high_ports, this_hi);
892 }
893 else if (unformat (input, "range %d - %d", &tmp, &tmp2))
894 {
895 if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535))
896 {
897 errmsg ("incorrect range parameters");
898 return -99;
899 }
900 this_low = tmp;
901 /* Note: in debug CLI +1 is added to high before
902 passing to real fn that does "the work"
903 (ip_source_and_port_range_check_add_del).
904 This fn is a wrapper around the binary API fn a
905 control plane will call, which expects this increment
906 to have occurred. Hence letting the binary API control
907 plane fn do the increment for consistency between VAT
908 and other control planes.
909 */
910 this_hi = tmp2;
911 vec_add1 (low_ports, this_low);
912 vec_add1 (high_ports, this_hi);
913 }
914 else
915 break;
916 }
917
918 if (prefix_set == 0)
919 {
920 errmsg ("<address>/<mask> not specified");
921 return -99;
922 }
923
924 if (vrf_id == ~0)
925 {
926 errmsg ("VRF ID required, not specified");
927 return -99;
928 }
929
930 if (vrf_id == 0)
931 {
932 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
933 "purpose.");
934 return -99;
935 }
936
937 if (vec_len (low_ports) == 0)
938 {
939 errmsg ("At least one port or port range required");
940 return -99;
941 }
942
943 M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp);
944
945 mp->is_add = is_add;
946
947 clib_memcpy (&mp->prefix, &prefix, sizeof (prefix));
948
949 mp->number_of_ranges = vec_len (low_ports);
950
951 clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports));
952 vec_free (low_ports);
953
954 clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports));
955 vec_free (high_ports);
956
957 mp->vrf_id = ntohl (vrf_id);
958
959 S (mp);
960 W (ret);
961 return ret;
962}
963
964static int
965api_ip_reassembly_set (vat_main_t *vat)
966{
967 return -1;
968}
969
970static int
971api_ip_container_proxy_add_del (vat_main_t *vam)
972{
973 vl_api_ip_container_proxy_add_del_t *mp;
974 unformat_input_t *i = vam->input;
975 u32 sw_if_index = ~0;
976 vl_api_prefix_t pfx = {};
977 u8 is_add = 1;
978 int ret;
979
980 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
981 {
982 if (unformat (i, "del"))
983 is_add = 0;
984 else if (unformat (i, "add"))
985 ;
986 if (unformat (i, "%U", unformat_vl_api_prefix, &pfx))
987 ;
988 else if (unformat (i, "sw_if_index %u", &sw_if_index))
989 ;
990 else
991 break;
992 }
993 if (sw_if_index == ~0 || pfx.len == 0)
994 {
995 errmsg ("address and sw_if_index must be set");
996 return -99;
997 }
998
999 M (IP_CONTAINER_PROXY_ADD_DEL, mp);
1000
1001 mp->sw_if_index = clib_host_to_net_u32 (sw_if_index);
1002 mp->is_add = is_add;
1003 clib_memcpy (&mp->pfx, &pfx, sizeof (pfx));
1004
1005 S (mp);
1006 W (ret);
1007 return ret;
1008}
1009
1010static int
1011api_ip_reassembly_enable_disable (vat_main_t *vat)
1012{
1013 return -1;
1014}
1015
1016static void
1017vl_api_ip_reassembly_get_reply_t_handler (vl_api_ip_reassembly_get_reply_t *mp)
1018{
1019}
1020
1021int
1022api_ip_source_and_port_range_check_interface_add_del (vat_main_t *vam)
1023{
1024 vnet_main_t *vnm = vnet_get_main ();
1025 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 {
1036 if (unformat (input, "%U", unformat_vnet_sw_interface, vnm,
1037 &sw_if_index))
1038 ;
1039 else if (unformat (input, "sw_if_index %d", &sw_if_index))
1040 ;
1041 else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id))
1042 vrf_set = 1;
1043 else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id))
1044 vrf_set = 1;
1045 else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id))
1046 vrf_set = 1;
1047 else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id))
1048 vrf_set = 1;
1049 else if (unformat (input, "del"))
1050 is_add = 0;
1051 else
1052 break;
1053 }
1054
1055 if (sw_if_index == ~0)
1056 {
1057 errmsg ("Interface required but not specified");
1058 return -99;
1059 }
1060
1061 if (vrf_set == 0)
1062 {
1063 errmsg ("VRF ID required but not specified");
1064 return -99;
1065 }
1066
1067 if (tcp_out_vrf_id == 0 || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 ||
1068 udp_in_vrf_id == 0)
1069 {
1070 errmsg ("VRF ID should not be default. Should be distinct VRF for this "
1071 "purpose.");
1072 return -99;
1073 }
1074
1075 /* Construct the API message */
1076 M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp);
1077
1078 mp->sw_if_index = ntohl (sw_if_index);
1079 mp->is_add = is_add;
1080 mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id);
1081 mp->udp_out_vrf_id = ntohl (udp_out_vrf_id);
1082 mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id);
1083 mp->udp_in_vrf_id = ntohl (udp_in_vrf_id);
1084
1085 /* send it... */
1086 S (mp);
1087
1088 /* Wait for a reply... */
1089 W (ret);
1090 return ret;
1091}
1092
1093static void
1094vl_api_ip_container_proxy_details_t_handler (
1095 vl_api_ip_container_proxy_details_t *mp)
1096{
1097}
1098
1099static int
1100api_ip_container_proxy_dump (vat_main_t *vam)
1101{
1102 return -1;
1103}
1104
1105static int
1106api_ip_dump (vat_main_t *vam)
1107{
1108 vl_api_ip_dump_t *mp;
1109 vl_api_control_ping_t *mp_ping;
1110 unformat_input_t *in = vam->input;
1111 int ipv4_set = 0;
1112 int ipv6_set = 0;
1113 int is_ipv6;
1114 int i;
1115 int ret;
1116
1117 while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT)
1118 {
1119 if (unformat (in, "ipv4"))
1120 ipv4_set = 1;
1121 else if (unformat (in, "ipv6"))
1122 ipv6_set = 1;
1123 else
1124 break;
1125 }
1126
1127 if (ipv4_set && ipv6_set)
1128 {
1129 errmsg ("ipv4 and ipv6 flags cannot be both set");
1130 return -99;
1131 }
1132
1133 if ((!ipv4_set) && (!ipv6_set))
1134 {
1135 errmsg ("no ipv4 nor ipv6 flag set");
1136 return -99;
1137 }
1138
1139 is_ipv6 = ipv6_set;
1140 vam->is_ipv6 = is_ipv6;
1141
1142 /* free old data */
1143 for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++)
1144 {
1145 vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr);
1146 }
1147 vec_free (vam->ip_details_by_sw_if_index[is_ipv6]);
1148
1149 M (IP_DUMP, mp);
1150 mp->is_ipv6 = ipv6_set;
1151 S (mp);
1152
1153 /* Use a control ping for synchronization */
1154 PING (&ip_test_main, mp_ping);
1155 S (mp_ping);
1156
1157 W (ret);
1158 return ret;
1159}
1160
1161static void
1162vl_api_mfib_signal_details_t_handler (vl_api_mfib_signal_details_t *mp)
1163{
1164}
1165
1166static void
1167vl_api_ip_mroute_details_t_handler (vl_api_ip_mroute_details_t *mp)
1168{
1169 vat_main_t *vam = ip_test_main.vat_main;
1170 vam->result_ready = 1;
1171}
1172
1173static int
1174api_ip_mroute_dump (vat_main_t *vam)
1175{
1176 unformat_input_t *input = vam->input;
1177 vl_api_control_ping_t *mp_ping;
1178 vl_api_ip_mroute_dump_t *mp;
1179 int ret, is_ip6;
1180 u32 table_id;
1181
1182 is_ip6 = 0;
1183 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1184 {
1185 if (unformat (input, "table_id %d", &table_id))
1186 ;
1187 else if (unformat (input, "ip6"))
1188 is_ip6 = 1;
1189 else if (unformat (input, "ip4"))
1190 is_ip6 = 0;
1191 else
1192 break;
1193 }
1194 if (table_id == ~0)
1195 {
1196 errmsg ("missing table id");
1197 return -99;
1198 }
1199
1200 M (IP_MROUTE_DUMP, mp);
1201 mp->table.table_id = table_id;
1202 mp->table.is_ip6 = is_ip6;
1203 S (mp);
1204
1205 /* Use a control ping for synchronization */
1206 PING (&ip_test_main, mp_ping);
1207 S (mp_ping);
1208
1209 W (ret);
1210 return ret;
1211}
1212
1213static int
1214api_sw_interface_ip6_enable_disable (vat_main_t *vam)
1215{
1216 vnet_main_t *vnm = vnet_get_main ();
1217 unformat_input_t *i = vam->input;
1218 vl_api_sw_interface_ip6_enable_disable_t *mp;
1219 u32 sw_if_index;
1220 u8 sw_if_index_set = 0;
1221 u8 enable = 0;
1222 int ret;
1223
1224 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1225 {
1226 if (unformat (i, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
1227 sw_if_index_set = 1;
1228 else if (unformat (i, "sw_if_index %d", &sw_if_index))
1229 sw_if_index_set = 1;
1230 else if (unformat (i, "enable"))
1231 enable = 1;
1232 else if (unformat (i, "disable"))
1233 enable = 0;
1234 else
1235 {
1236 clib_warning ("parse error '%U'", format_unformat_error, i);
1237 return -99;
1238 }
1239 }
1240
1241 if (sw_if_index_set == 0)
1242 {
1243 errmsg ("missing interface name or sw_if_index");
1244 return -99;
1245 }
1246
1247 M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp);
1248
1249 mp->sw_if_index = ntohl (sw_if_index);
1250 mp->enable = enable;
1251
1252 S (mp);
1253 W (ret);
1254 return ret;
1255}
1256
1257static int
1258api_set_ip_flow_hash_v2 (vat_main_t *vat)
1259{
1260 return -1;
1261}
1262
1263static int
1264api_ip_mroute_add_del (vat_main_t *vam)
1265{
1266 unformat_input_t *i = vam->input;
1267 u8 path_set = 0, prefix_set = 0, is_add = 1;
1268 vl_api_ip_mroute_add_del_t *mp;
1269 mfib_entry_flags_t eflags = 0;
1270 vl_api_mfib_path_t path;
1271 vl_api_mprefix_t pfx = {};
1272 u32 vrf_id = 0;
1273 int ret;
1274
1275 /* Parse args required to build the message */
1276 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1277 {
1278 if (unformat (i, "%U", unformat_vl_api_mprefix, &pfx))
1279 {
1280 prefix_set = 1;
1281 pfx.grp_address_length = htons (pfx.grp_address_length);
1282 }
1283 else if (unformat (i, "del"))
1284 is_add = 0;
1285 else if (unformat (i, "add"))
1286 is_add = 1;
1287 else if (unformat (i, "vrf %d", &vrf_id))
1288 ;
1289 else if (unformat (i, "%U", unformat_mfib_itf_flags, &path.itf_flags))
1290 path.itf_flags = htonl (path.itf_flags);
1291 else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags))
1292 ;
1293 else if (unformat (i, "via %U", unformat_fib_path, vam, &path.path))
1294 path_set = 1;
1295 else
1296 {
1297 clib_warning ("parse error '%U'", format_unformat_error, i);
1298 return -99;
1299 }
1300 }
1301
1302 if (prefix_set == 0)
1303 {
1304 errmsg ("missing addresses\n");
1305 return -99;
1306 }
1307 if (path_set == 0)
1308 {
1309 errmsg ("missing path\n");
1310 return -99;
1311 }
1312
1313 /* Construct the API message */
1314 M (IP_MROUTE_ADD_DEL, mp);
1315
1316 mp->is_add = is_add;
1317 mp->is_multipath = 1;
1318
1319 clib_memcpy (&mp->route.prefix, &pfx, sizeof (pfx));
1320 mp->route.table_id = htonl (vrf_id);
1321 mp->route.n_paths = 1;
1322 mp->route.entry_flags = htonl (eflags);
1323
1324 clib_memcpy (&mp->route.paths, &path, sizeof (path));
1325
1326 /* send it... */
1327 S (mp);
1328 /* Wait for a reply... */
1329 W (ret);
1330 return ret;
1331}
1332
1333static void
1334vl_api_ip_mroute_add_del_reply_t_handler (vl_api_ip_mroute_add_del_reply_t *mp)
1335{
1336 vat_main_t *vam = ip_test_main.vat_main;
1337 vam->result_ready = 1;
1338}
1339
1340static int
1341api_ip_mtable_dump (vat_main_t *vam)
1342{
1343 vl_api_ip_mtable_dump_t *mp;
1344 vl_api_control_ping_t *mp_ping;
1345 int ret;
1346
1347 M (IP_MTABLE_DUMP, mp);
1348 S (mp);
1349
1350 /* Use a control ping for synchronization */
1351 PING (&ip_test_main, mp_ping);
1352 S (mp_ping);
1353
1354 W (ret);
1355 return ret;
1356}
1357
1358static void
1359vl_api_ip_mtable_details_t_handler (vl_api_ip_mtable_details_t *mp)
1360{
1361 vat_main_t *vam = ip_test_main.vat_main;
1362 vam->result_ready = 1;
1363}
1364
1365static int
1366api_ip_table_replace_end (vat_main_t *vam)
1367{
1368 unformat_input_t *i = vam->input;
1369 vl_api_ip_table_replace_end_t *mp;
1370 u32 table_id = 0;
1371 u8 is_ipv6 = 0;
1372
1373 int ret;
1374 while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1375 {
1376 if (unformat (i, "table %d", &table_id))
1377 ;
1378 else if (unformat (i, "ipv6"))
1379 is_ipv6 = 1;
1380 else
1381 {
1382 clib_warning ("parse error '%U'", format_unformat_error, i);
1383 return -99;
1384 }
1385 }
1386
1387 M (IP_TABLE_REPLACE_END, mp);
1388
1389 mp->table.table_id = ntohl (table_id);
1390 mp->table.is_ip6 = is_ipv6;
1391
1392 S (mp);
1393 W (ret);
1394 return ret;
1395}
1396
1397static int
1398api_ip_table_dump (vat_main_t *vam)
1399{
1400 vl_api_ip_table_dump_t *mp;
1401 vl_api_control_ping_t *mp_ping;
1402 int ret;
1403
1404 M (IP_TABLE_DUMP, mp);
1405 S (mp);
1406
1407 /* Use a control ping for synchronization */
1408 PING (&ip_test_main, mp_ping);
1409 S (mp_ping);
1410
1411 W (ret);
1412 return ret;
1413}
1414
1415static void
1416vl_api_ip_table_details_t_handler (vl_api_ip_table_details_t *mp)
1417{
1418 vat_main_t *vam = ip_test_main.vat_main;
1419
1420 fformat (vam->ofp, "%s; table-id %d, prefix %U/%d", mp->table.name,
1421 ntohl (mp->table.table_id));
1422 vam->result_ready = 1;
1423}
1424
1425static int
1426api_ip_path_mtu_get (vat_main_t *vat)
1427{
1428 return -1;
1429}
1430
1431static int
1432api_ip_route_v2_dump (vat_main_t *vat)
1433{
1434 return -1;
1435}
1436
1437static void
1438vl_api_ip_path_mtu_get_reply_t_handler (vl_api_ip_path_mtu_get_reply_t *mp)
1439{
1440}
1441
1442static int
1443api_ip_route_dump (vat_main_t *vam)
1444{
1445 unformat_input_t *input = vam->input;
1446 vl_api_ip_route_dump_t *mp;
1447 vl_api_control_ping_t *mp_ping;
1448 u32 table_id;
1449 u8 is_ip6;
1450 int ret;
1451
1452 is_ip6 = 0;
1453 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1454 {
1455 if (unformat (input, "table_id %d", &table_id))
1456 ;
1457 else if (unformat (input, "ip6"))
1458 is_ip6 = 1;
1459 else if (unformat (input, "ip4"))
1460 is_ip6 = 0;
1461 else
1462 break;
1463 }
1464 if (table_id == ~0)
1465 {
1466 errmsg ("missing table id");
1467 return -99;
1468 }
1469
1470 M (IP_ROUTE_DUMP, mp);
1471
1472 mp->table.table_id = table_id;
1473 mp->table.is_ip6 = is_ip6;
1474
1475 S (mp);
1476
1477 /* Use a control ping for synchronization */
1478 PING (&ip_test_main, mp_ping);
1479 S (mp_ping);
1480
1481 W (ret);
1482 return ret;
1483}
1484
1485static void
1486vl_api_ip_address_details_t_handler (vl_api_ip_address_details_t *mp)
1487{
1488 vat_main_t *vam = ip_test_main.vat_main;
1489 static ip_address_details_t empty_ip_address_details = { { 0 } };
1490 ip_address_details_t *address = NULL;
1491 ip_details_t *current_ip_details = NULL;
1492 ip_details_t *details = NULL;
1493
1494 details = vam->ip_details_by_sw_if_index[vam->is_ipv6];
1495
1496 if (!details || vam->current_sw_if_index >= vec_len (details) ||
1497 !details[vam->current_sw_if_index].present)
1498 {
1499 errmsg ("ip address details arrived but not stored");
1500 errmsg ("ip_dump should be called first");
1501 return;
1502 }
1503
1504 current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index);
1505
1506#define addresses (current_ip_details->addr)
1507
1508 vec_validate_init_empty (addresses, vec_len (addresses),
1509 empty_ip_address_details);
1510
1511 address = vec_elt_at_index (addresses, vec_len (addresses) - 1);
1512
1513 clib_memcpy (&address->ip, &mp->prefix.address.un, sizeof (address->ip));
1514 address->prefix_length = mp->prefix.len;
1515#undef addresses
1516}
1517
1518static int
1519api_ip_unnumbered_dump (vat_main_t *vam)
1520{
1521 return -1;
1522}
1523
1524static void
1525vl_api_ip_unnumbered_details_t_handler (vl_api_ip_unnumbered_details_t *mp)
1526{
1527}
1528
1529static void
1530vl_api_ip_details_t_handler (vl_api_ip_details_t *mp)
1531{
1532 vat_main_t *vam = &vat_main;
1533 static ip_details_t empty_ip_details = { 0 };
1534 ip_details_t *ip = NULL;
1535 u32 sw_if_index = ~0;
1536
1537 sw_if_index = ntohl (mp->sw_if_index);
1538
1539 vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1540 sw_if_index, empty_ip_details);
1541
1542 ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6],
1543 sw_if_index);
1544
1545 ip->present = 1;
1546}
1547
1548#include <vnet/ip/ip.api_test.c>
1549
Filip Tehlarabfe3652021-07-23 18:24:19 +00001550/*
1551 * fd.io coding-style-patch-verification: ON
1552 *
1553 * Local Variables:
1554 * eval: (c-set-style "gnu")
1555 * End:
1556 */