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