ipsec: manually binding an SA to a worker
[vpp.git] / src / vnet / ipsec / ipsec_test.c
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4
5 #include <vat/vat.h>
6 #include <vlibapi/api.h>
7 #include <vlibmemory/api.h>
8 #include <vppinfra/error.h>
9 #include <vpp/api/types.h>
10
11 #include <vnet/ipsec/ipsec.h>
12 #include <vnet/ip/ip_types_api.h>
13
14 #define __plugin_msg_base ipsec_test_main.msg_id_base
15 #include <vlibapi/vat_helper_macros.h>
16
17 #include <vlibmemory/vlib.api_enum.h>
18 #include <vlibmemory/vlib.api_types.h>
19
20 /* Declare message IDs */
21 #include <vnet/format_fns.h>
22 #include <vnet/ipsec/ipsec.api_enum.h>
23 #include <vnet/ipsec/ipsec.api_types.h>
24
25 #define vl_endianfun /* define message structures */
26 #include <vnet/ipsec/ipsec.api.h>
27 #undef vl_endianfun
28
29 #define vl_calcsizefun
30 #include <vnet/ipsec/ipsec.api.h>
31 #undef vl_calcsizefun
32
33 typedef struct
34 {
35   /* API message ID base */
36   u16 msg_id_base;
37   u32 ping_id;
38   vat_main_t *vat_main;
39 } ipsec_test_main_t;
40
41 static ipsec_test_main_t ipsec_test_main;
42
43 static void
44 vl_api_ipsec_spds_details_t_handler (vl_api_ipsec_spds_details_t *mp)
45 {
46 }
47
48 static void
49 vl_api_ipsec_itf_details_t_handler (vl_api_ipsec_itf_details_t *mp)
50 {
51 }
52
53 static int
54 api_ipsec_itf_delete (vat_main_t *vat)
55 {
56   return -1;
57 }
58
59 static int
60 api_ipsec_itf_create (vat_main_t *vat)
61 {
62   return -1;
63 }
64
65 static void
66 vl_api_ipsec_itf_create_reply_t_handler (vl_api_ipsec_itf_create_reply_t *vat)
67 {
68 }
69
70 static int
71 api_ipsec_spd_entry_add_del (vat_main_t *vam)
72 {
73   unformat_input_t *i = vam->input;
74   vl_api_ipsec_spd_entry_add_del_t *mp;
75   u8 is_add = 1, is_outbound = 0;
76   u32 spd_id = 0, sa_id = 0, protocol = IPSEC_POLICY_PROTOCOL_ANY, policy = 0;
77   i32 priority = 0;
78   u32 rport_start = 0, rport_stop = (u32) ~0;
79   u32 lport_start = 0, lport_stop = (u32) ~0;
80   vl_api_address_t laddr_start = {}, laddr_stop = {}, raddr_start = {},
81                    raddr_stop = {};
82   int ret;
83
84   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
85     {
86       if (unformat (i, "del"))
87         is_add = 0;
88       if (unformat (i, "outbound"))
89         is_outbound = 1;
90       if (unformat (i, "inbound"))
91         is_outbound = 0;
92       else if (unformat (i, "spd_id %d", &spd_id))
93         ;
94       else if (unformat (i, "sa_id %d", &sa_id))
95         ;
96       else if (unformat (i, "priority %d", &priority))
97         ;
98       else if (unformat (i, "protocol %d", &protocol))
99         ;
100       else if (unformat (i, "lport_start %d", &lport_start))
101         ;
102       else if (unformat (i, "lport_stop %d", &lport_stop))
103         ;
104       else if (unformat (i, "rport_start %d", &rport_start))
105         ;
106       else if (unformat (i, "rport_stop %d", &rport_stop))
107         ;
108       else if (unformat (i, "laddr_start %U", unformat_vl_api_address,
109                          &laddr_start))
110         ;
111       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
112                          &laddr_stop))
113         ;
114       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
115                          &raddr_start))
116         ;
117       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
118                          &raddr_stop))
119         ;
120       else if (unformat (i, "action %U", unformat_ipsec_policy_action,
121                          &policy))
122         {
123           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
124             {
125               clib_warning ("unsupported action: 'resolve'");
126               return -99;
127             }
128         }
129       else
130         {
131           clib_warning ("parse error '%U'", format_unformat_error, i);
132           return -99;
133         }
134     }
135
136   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
137
138   mp->is_add = is_add;
139
140   mp->entry.spd_id = ntohl (spd_id);
141   mp->entry.priority = ntohl (priority);
142   mp->entry.is_outbound = is_outbound;
143
144   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
145                sizeof (vl_api_address_t));
146   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
147                sizeof (vl_api_address_t));
148   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
149                sizeof (vl_api_address_t));
150   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
151                sizeof (vl_api_address_t));
152
153   mp->entry.protocol = protocol ? (u8) protocol : IPSEC_POLICY_PROTOCOL_ANY;
154   mp->entry.local_port_start = ntohs ((u16) lport_start);
155   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
156   mp->entry.remote_port_start = ntohs ((u16) rport_start);
157   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
158   mp->entry.policy = (u8) policy;
159   mp->entry.sa_id = ntohl (sa_id);
160
161   S (mp);
162   W (ret);
163   return ret;
164 }
165
166 static int
167 api_ipsec_spd_entry_add_del_v2 (vat_main_t *vam)
168 {
169   unformat_input_t *i = vam->input;
170   vl_api_ipsec_spd_entry_add_del_t *mp;
171   u8 is_add = 1, is_outbound = 0;
172   u32 spd_id = 0, sa_id = 0, protocol = IPSEC_POLICY_PROTOCOL_ANY, policy = 0;
173   i32 priority = 0;
174   u32 rport_start = 0, rport_stop = (u32) ~0;
175   u32 lport_start = 0, lport_stop = (u32) ~0;
176   vl_api_address_t laddr_start = {}, laddr_stop = {}, raddr_start = {},
177                    raddr_stop = {};
178   int ret;
179
180   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
181     {
182       if (unformat (i, "del"))
183         is_add = 0;
184       if (unformat (i, "outbound"))
185         is_outbound = 1;
186       if (unformat (i, "inbound"))
187         is_outbound = 0;
188       else if (unformat (i, "spd_id %d", &spd_id))
189         ;
190       else if (unformat (i, "sa_id %d", &sa_id))
191         ;
192       else if (unformat (i, "priority %d", &priority))
193         ;
194       else if (unformat (i, "protocol %d", &protocol))
195         ;
196       else if (unformat (i, "lport_start %d", &lport_start))
197         ;
198       else if (unformat (i, "lport_stop %d", &lport_stop))
199         ;
200       else if (unformat (i, "rport_start %d", &rport_start))
201         ;
202       else if (unformat (i, "rport_stop %d", &rport_stop))
203         ;
204       else if (unformat (i, "laddr_start %U", unformat_vl_api_address,
205                          &laddr_start))
206         ;
207       else if (unformat (i, "laddr_stop %U", unformat_vl_api_address,
208                          &laddr_stop))
209         ;
210       else if (unformat (i, "raddr_start %U", unformat_vl_api_address,
211                          &raddr_start))
212         ;
213       else if (unformat (i, "raddr_stop %U", unformat_vl_api_address,
214                          &raddr_stop))
215         ;
216       else if (unformat (i, "action %U", unformat_ipsec_policy_action,
217                          &policy))
218         {
219           if (policy == IPSEC_POLICY_ACTION_RESOLVE)
220             {
221               clib_warning ("unsupported action: 'resolve'");
222               return -99;
223             }
224         }
225       else
226         {
227           clib_warning ("parse error '%U'", format_unformat_error, i);
228           return -99;
229         }
230     }
231
232   M (IPSEC_SPD_ENTRY_ADD_DEL, mp);
233
234   mp->is_add = is_add;
235
236   mp->entry.spd_id = ntohl (spd_id);
237   mp->entry.priority = ntohl (priority);
238   mp->entry.is_outbound = is_outbound;
239
240   clib_memcpy (&mp->entry.remote_address_start, &raddr_start,
241                sizeof (vl_api_address_t));
242   clib_memcpy (&mp->entry.remote_address_stop, &raddr_stop,
243                sizeof (vl_api_address_t));
244   clib_memcpy (&mp->entry.local_address_start, &laddr_start,
245                sizeof (vl_api_address_t));
246   clib_memcpy (&mp->entry.local_address_stop, &laddr_stop,
247                sizeof (vl_api_address_t));
248
249   mp->entry.protocol = (u8) protocol;
250   mp->entry.local_port_start = ntohs ((u16) lport_start);
251   mp->entry.local_port_stop = ntohs ((u16) lport_stop);
252   mp->entry.remote_port_start = ntohs ((u16) rport_start);
253   mp->entry.remote_port_stop = ntohs ((u16) rport_stop);
254   mp->entry.policy = (u8) policy;
255   mp->entry.sa_id = ntohl (sa_id);
256
257   S (mp);
258   W (ret);
259   return ret;
260 }
261
262 static void
263 vl_api_ipsec_spd_details_t_handler (vl_api_ipsec_spd_details_t *mp)
264 {
265 }
266
267 static void
268 vl_api_ipsec_sad_entry_add_del_reply_t_handler (
269   vl_api_ipsec_sad_entry_add_del_reply_t *mp)
270 {
271 }
272
273 static void
274 vl_api_ipsec_sad_entry_add_del_v3_reply_t_handler (
275   vl_api_ipsec_sad_entry_add_del_v3_reply_t *mp)
276 {
277 }
278
279 static void
280 vl_api_ipsec_sad_entry_add_reply_t_handler (
281   vl_api_ipsec_sad_entry_add_reply_t *mp)
282 {
283 }
284
285 static int
286 api_ipsec_sad_entry_del (vat_main_t *vat)
287 {
288   return -1;
289 }
290
291 static int
292 api_ipsec_sad_bind (vat_main_t *vat)
293 {
294   return -1;
295 }
296
297 static int
298 api_ipsec_sad_unbind (vat_main_t *vat)
299 {
300   return -1;
301 }
302
303 static void
304 vl_api_ipsec_sad_entry_add_del_v2_reply_t_handler (
305   vl_api_ipsec_sad_entry_add_del_v2_reply_t *mp)
306 {
307 }
308
309 static void
310 vl_api_ipsec_spd_interface_details_t_handler (
311   vl_api_ipsec_spd_interface_details_t *vat)
312 {
313 }
314
315 static int
316 api_ipsec_sad_entry_add_del_v3 (vat_main_t *vat)
317 {
318   return -1;
319 }
320
321 static int
322 api_ipsec_sad_entry_update (vat_main_t *vat)
323 {
324   return -1;
325 }
326
327 static int
328 api_ipsec_tunnel_protect_update (vat_main_t *vat)
329 {
330   return -1;
331 }
332
333 static void
334 vl_api_ipsec_backend_details_t_handler (vl_api_ipsec_backend_details_t *mp)
335 {
336 }
337
338 static int
339 api_ipsec_sa_v3_dump (vat_main_t *vat)
340 {
341   return -1;
342 }
343
344 static int
345 api_ipsec_tunnel_protect_dump (vat_main_t *vat)
346 {
347   return -1;
348 }
349
350 static int
351 api_ipsec_tunnel_protect_del (vat_main_t *vat)
352 {
353   return -1;
354 }
355
356 static void
357 vl_api_ipsec_tunnel_protect_details_t_handler (
358   vl_api_ipsec_tunnel_protect_details_t *mp)
359 {
360 }
361
362 static int
363 api_ipsec_sad_entry_add (vat_main_t *vat)
364 {
365   return -1;
366 }
367
368 static void
369 vl_api_ipsec_spd_entry_add_del_reply_t_handler (
370   vl_api_ipsec_spd_entry_add_del_reply_t *mp)
371 {
372 }
373
374 static void
375 vl_api_ipsec_spd_entry_add_del_v2_reply_t_handler (
376   vl_api_ipsec_spd_entry_add_del_v2_reply_t *mp)
377 {
378 }
379
380 static int
381 api_ipsec_spds_dump (vat_main_t *vam)
382 {
383   return -1;
384 }
385
386 static int
387 api_ipsec_itf_dump (vat_main_t *vam)
388 {
389   return -1;
390 }
391
392 static void
393 vl_api_ipsec_sa_v3_details_t_handler (vl_api_ipsec_sa_v3_details_t *mp)
394 {
395 }
396
397 static int
398 api_ipsec_spd_interface_dump (vat_main_t *vat)
399 {
400   return -1;
401 }
402
403 static void
404 vl_api_ipsec_sa_v2_details_t_handler (vl_api_ipsec_sa_v2_details_t *mp)
405 {
406 }
407
408 static int
409 api_ipsec_sa_v2_dump (vat_main_t *mp)
410 {
411   return -1;
412 }
413
414 static int
415 api_ipsec_sa_dump (vat_main_t *vam)
416 {
417   unformat_input_t *i = vam->input;
418   vl_api_ipsec_sa_dump_t *mp;
419   vl_api_control_ping_t *mp_ping;
420   u32 sa_id = ~0;
421   int ret;
422
423   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
424     {
425       if (unformat (i, "sa_id %d", &sa_id))
426         ;
427       else
428         {
429           clib_warning ("parse error '%U'", format_unformat_error, i);
430           return -99;
431         }
432     }
433
434   M (IPSEC_SA_DUMP, mp);
435
436   mp->sa_id = ntohl (sa_id);
437
438   S (mp);
439
440   /* Use a control ping for synchronization */
441   PING (&ipsec_test_main, mp_ping);
442   S (mp_ping);
443
444   W (ret);
445   return ret;
446 }
447
448 static void
449 vl_api_ipsec_sa_v4_details_t_handler (vl_api_ipsec_sa_v4_details_t *mp)
450 {
451 }
452
453 static int
454 api_ipsec_sa_v4_dump (vat_main_t *mp)
455 {
456   return -1;
457 }
458
459 static void
460 vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t *mp)
461 {
462   vat_main_t *vam = &vat_main;
463
464   print (vam->ofp,
465          "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u "
466          "crypto_key %U integ_alg %u integ_key %U flags %x "
467          "tunnel_src_addr %U tunnel_dst_addr %U "
468          "salt %u seq_outbound %lu last_seq_inbound %lu "
469          "replay_window %lu stat_index %u\n",
470          ntohl (mp->entry.sad_id), ntohl (mp->sw_if_index),
471          ntohl (mp->entry.spi), ntohl (mp->entry.protocol),
472          ntohl (mp->entry.crypto_algorithm), format_hex_bytes,
473          mp->entry.crypto_key.data, mp->entry.crypto_key.length,
474          ntohl (mp->entry.integrity_algorithm), format_hex_bytes,
475          mp->entry.integrity_key.data, mp->entry.integrity_key.length,
476          ntohl (mp->entry.flags), format_vl_api_address, &mp->entry.tunnel_src,
477          format_vl_api_address, &mp->entry.tunnel_dst, ntohl (mp->salt),
478          clib_net_to_host_u64 (mp->seq_outbound),
479          clib_net_to_host_u64 (mp->last_seq_inbound),
480          clib_net_to_host_u64 (mp->replay_window), ntohl (mp->stat_index));
481 }
482
483 static int
484 api_ipsec_spd_dump (vat_main_t *vam)
485 {
486   return -1;
487 }
488
489 uword
490 unformat_ipsec_api_crypto_alg (unformat_input_t *input, va_list *args)
491 {
492   u32 *r = va_arg (*args, u32 *);
493
494   if (0)
495     ;
496 #define _(v, f, s) else if (unformat (input, s)) *r = IPSEC_API_CRYPTO_ALG_##f;
497   foreach_ipsec_crypto_alg
498 #undef _
499     else return 0;
500   return 1;
501 }
502
503 uword
504 unformat_ipsec_api_integ_alg (unformat_input_t *input, va_list *args)
505 {
506   u32 *r = va_arg (*args, u32 *);
507
508   if (0)
509     ;
510 #define _(v, f, s) else if (unformat (input, s)) *r = IPSEC_API_INTEG_ALG_##f;
511   foreach_ipsec_integ_alg
512 #undef _
513     else return 0;
514   return 1;
515 }
516
517 static int
518 api_ipsec_sad_entry_add_del (vat_main_t *vam)
519 {
520   unformat_input_t *i = vam->input;
521   vl_api_ipsec_sad_entry_add_del_t *mp;
522   u32 sad_id = 0, spi = 0;
523   u8 *ck = 0, *ik = 0;
524   u8 is_add = 1;
525
526   vl_api_ipsec_crypto_alg_t crypto_alg = IPSEC_API_CRYPTO_ALG_NONE;
527   vl_api_ipsec_integ_alg_t integ_alg = IPSEC_API_INTEG_ALG_NONE;
528   vl_api_ipsec_sad_flags_t flags = IPSEC_API_SAD_FLAG_NONE;
529   vl_api_ipsec_proto_t protocol = IPSEC_API_PROTO_AH;
530   vl_api_address_t tun_src, tun_dst;
531   int ret;
532
533   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
534     {
535       if (unformat (i, "del"))
536         is_add = 0;
537       else if (unformat (i, "sad_id %d", &sad_id))
538         ;
539       else if (unformat (i, "spi %d", &spi))
540         ;
541       else if (unformat (i, "esp"))
542         protocol = IPSEC_API_PROTO_ESP;
543       else if (unformat (i, "tunnel_src %U", unformat_vl_api_address,
544                          &tun_src))
545         {
546           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
547           if (ADDRESS_IP6 == tun_src.af)
548             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
549         }
550       else if (unformat (i, "tunnel_dst %U", unformat_vl_api_address,
551                          &tun_dst))
552         {
553           flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL;
554           if (ADDRESS_IP6 == tun_src.af)
555             flags |= IPSEC_API_SAD_FLAG_IS_TUNNEL_V6;
556         }
557       else if (unformat (i, "crypto_alg %U", unformat_ipsec_api_crypto_alg,
558                          &crypto_alg))
559         ;
560       else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck))
561         ;
562       else if (unformat (i, "integ_alg %U", unformat_ipsec_api_integ_alg,
563                          &integ_alg))
564         ;
565       else if (unformat (i, "integ_key %U", unformat_hex_string, &ik))
566         ;
567       else
568         {
569           clib_warning ("parse error '%U'", format_unformat_error, i);
570           return -99;
571         }
572     }
573
574   M (IPSEC_SAD_ENTRY_ADD_DEL, mp);
575
576   mp->is_add = is_add;
577   mp->entry.sad_id = ntohl (sad_id);
578   mp->entry.protocol = protocol;
579   mp->entry.spi = ntohl (spi);
580   mp->entry.flags = flags;
581
582   mp->entry.crypto_algorithm = crypto_alg;
583   mp->entry.integrity_algorithm = integ_alg;
584   mp->entry.crypto_key.length = vec_len (ck);
585   mp->entry.integrity_key.length = vec_len (ik);
586
587   if (mp->entry.crypto_key.length > sizeof (mp->entry.crypto_key.data))
588     mp->entry.crypto_key.length = sizeof (mp->entry.crypto_key.data);
589
590   if (mp->entry.integrity_key.length > sizeof (mp->entry.integrity_key.data))
591     mp->entry.integrity_key.length = sizeof (mp->entry.integrity_key.data);
592
593   if (ck)
594     clib_memcpy (mp->entry.crypto_key.data, ck, mp->entry.crypto_key.length);
595   if (ik)
596     clib_memcpy (mp->entry.integrity_key.data, ik,
597                  mp->entry.integrity_key.length);
598
599   if (flags & IPSEC_API_SAD_FLAG_IS_TUNNEL)
600     {
601       clib_memcpy (&mp->entry.tunnel_src, &tun_src,
602                    sizeof (mp->entry.tunnel_src));
603       clib_memcpy (&mp->entry.tunnel_dst, &tun_dst,
604                    sizeof (mp->entry.tunnel_dst));
605     }
606
607   S (mp);
608   W (ret);
609   return ret;
610 }
611
612 static int
613 api_ipsec_sad_entry_add_del_v2 (vat_main_t *vam)
614 {
615   return -1;
616 }
617
618 static int
619 api_ipsec_interface_add_del_spd (vat_main_t *vam)
620 {
621   vnet_main_t *vnm = vnet_get_main ();
622   unformat_input_t *i = vam->input;
623   vl_api_ipsec_interface_add_del_spd_t *mp;
624   u32 sw_if_index;
625   u8 sw_if_index_set = 0;
626   u32 spd_id = (u32) ~0;
627   u8 is_add = 1;
628   int ret;
629
630   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
631     {
632       if (unformat (i, "del"))
633         is_add = 0;
634       else if (unformat (i, "spd_id %d", &spd_id))
635         ;
636       else if (unformat (i, "%U", unformat_vnet_sw_interface, vnm,
637                          &sw_if_index))
638         sw_if_index_set = 1;
639       else if (unformat (i, "sw_if_index %d", &sw_if_index))
640         sw_if_index_set = 1;
641       else
642         {
643           clib_warning ("parse error '%U'", format_unformat_error, i);
644           return -99;
645         }
646     }
647
648   if (spd_id == (u32) ~0)
649     {
650       errmsg ("spd_id must be set");
651       return -99;
652     }
653
654   if (sw_if_index_set == 0)
655     {
656       errmsg ("missing interface name or sw_if_index");
657       return -99;
658     }
659
660   M (IPSEC_INTERFACE_ADD_DEL_SPD, mp);
661
662   mp->spd_id = ntohl (spd_id);
663   mp->sw_if_index = ntohl (sw_if_index);
664   mp->is_add = is_add;
665
666   S (mp);
667   W (ret);
668   return ret;
669 }
670
671 static int
672 api_ipsec_backend_dump (vat_main_t *vam)
673 {
674   return -1;
675 }
676
677 static int
678 api_ipsec_select_backend (vat_main_t *vam)
679 {
680   return -1;
681 }
682
683 static int
684 api_ipsec_set_async_mode (vat_main_t *vam)
685 {
686   return -1;
687 }
688
689 static int
690 api_ipsec_spd_add_del (vat_main_t *vam)
691 {
692   unformat_input_t *i = vam->input;
693   vl_api_ipsec_spd_add_del_t *mp;
694   u32 spd_id = ~0;
695   u8 is_add = 1;
696   int ret;
697
698   while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
699     {
700       if (unformat (i, "spd_id %d", &spd_id))
701         ;
702       else if (unformat (i, "del"))
703         is_add = 0;
704       else
705         {
706           clib_warning ("parse error '%U'", format_unformat_error, i);
707           return -99;
708         }
709     }
710   if (spd_id == ~0)
711     {
712       errmsg ("spd_id must be set");
713       return -99;
714     }
715
716   M (IPSEC_SPD_ADD_DEL, mp);
717
718   mp->spd_id = ntohl (spd_id);
719   mp->is_add = is_add;
720
721   S (mp);
722   W (ret);
723   return ret;
724 }
725
726 #include <vnet/ipsec/ipsec.api_test.c>
727
728 /*
729  * Local Variables:
730  * eval: (c-set-style "gnu")
731  * End:
732  */