FD.io VPP  v20.05.1-6-gf53edbc3b
Vector Packet Processing
ipsec_cli.c
Go to the documentation of this file.
1 /*
2  * decap.c : IPSec tunnel support
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/interface.h>
22 #include <vnet/fib/fib.h>
23 #include <vnet/ipip/ipip.h>
24 
25 #include <vnet/ipsec/ipsec.h>
26 #include <vnet/ipsec/ipsec_tun.h>
27 
28 static clib_error_t *
30  unformat_input_t * input,
31  vlib_cli_command_t * cmd)
32 {
33  unformat_input_t _line_input, *line_input = &_line_input;
34  ipsec_main_t *im = &ipsec_main;
35  u32 sw_if_index = (u32) ~ 0;
36  u32 spd_id;
37  int is_add = 1;
38  clib_error_t *error = NULL;
39 
40  if (!unformat_user (input, unformat_line_input, line_input))
41  return 0;
42 
43  if (unformat
44  (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
45  &sw_if_index, &spd_id))
46  ;
47  else if (unformat (line_input, "del"))
48  is_add = 0;
49  else
50  {
51  error = clib_error_return (0, "parse error: '%U'",
52  format_unformat_error, line_input);
53  goto done;
54  }
55 
56  ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add);
57 
58 done:
59  unformat_free (line_input);
60 
61  return error;
62 }
63 
64 /* *INDENT-OFF* */
65 VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
66  .path = "set interface ipsec spd",
67  .short_help =
68  "set interface ipsec spd <int> <id>",
69  .function = set_interface_spd_command_fn,
70 };
71 /* *INDENT-ON* */
72 
73 static clib_error_t *
75  unformat_input_t * input,
76  vlib_cli_command_t * cmd)
77 {
78  unformat_input_t _line_input, *line_input = &_line_input;
79  ip46_address_t tun_src = { }, tun_dst =
80  {
81  };
82  ipsec_crypto_alg_t crypto_alg;
83  ipsec_integ_alg_t integ_alg;
86  clib_error_t *error;
87  ipsec_key_t ck = { 0 };
88  ipsec_key_t ik = { 0 };
89  u32 id, spi, salt, sai;
90  u16 udp_src, udp_dst;
91  int is_add, rv;
92 
93  salt = 0;
94  error = NULL;
95  is_add = 0;
96  flags = IPSEC_SA_FLAG_NONE;
97  proto = IPSEC_PROTOCOL_ESP;
98  integ_alg = IPSEC_INTEG_ALG_NONE;
99  crypto_alg = IPSEC_CRYPTO_ALG_NONE;
100  udp_src = udp_dst = IPSEC_UDP_PORT_NONE;
101 
102  if (!unformat_user (input, unformat_line_input, line_input))
103  return 0;
104 
105  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
106  {
107  if (unformat (line_input, "add %u", &id))
108  is_add = 1;
109  else if (unformat (line_input, "del %u", &id))
110  is_add = 0;
111  else if (unformat (line_input, "spi %u", &spi))
112  ;
113  else if (unformat (line_input, "salt 0x%x", &salt))
114  ;
115  else if (unformat (line_input, "esp"))
116  proto = IPSEC_PROTOCOL_ESP;
117  else if (unformat (line_input, "ah"))
118  proto = IPSEC_PROTOCOL_AH;
119  else if (unformat (line_input, "crypto-key %U",
120  unformat_ipsec_key, &ck))
121  ;
122  else if (unformat (line_input, "crypto-alg %U",
123  unformat_ipsec_crypto_alg, &crypto_alg))
124  ;
125  else if (unformat (line_input, "integ-key %U", unformat_ipsec_key, &ik))
126  ;
127  else if (unformat (line_input, "integ-alg %U",
128  unformat_ipsec_integ_alg, &integ_alg))
129  ;
130  else if (unformat (line_input, "tunnel-src %U",
132  {
133  flags |= IPSEC_SA_FLAG_IS_TUNNEL;
134  if (!ip46_address_is_ip4 (&tun_src))
135  flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
136  }
137  else if (unformat (line_input, "tunnel-dst %U",
139  ;
140  else if (unformat (line_input, "udp-encap"))
141  flags |= IPSEC_SA_FLAG_UDP_ENCAP;
142  else
143  {
144  error = clib_error_return (0, "parse error: '%U'",
145  format_unformat_error, line_input);
146  goto done;
147  }
148  }
149 
150  if (is_add)
151  rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg,
152  &ck, integ_alg, &ik, flags,
153  0, clib_host_to_net_u32 (salt),
154  &tun_src, &tun_dst, &sai, udp_src, udp_dst);
155  else
156  rv = ipsec_sa_unlock_id (id);
157 
158  if (rv)
159  error = clib_error_return (0, "failed");
160 
161 done:
162  unformat_free (line_input);
163 
164  return error;
165 }
166 
167 /* *INDENT-OFF* */
168 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
169  .path = "ipsec sa",
170  .short_help =
171  "ipsec sa [add|del]",
172  .function = ipsec_sa_add_del_command_fn,
173 };
174 /* *INDENT-ON* */
175 
176 static clib_error_t *
178  unformat_input_t * input,
179  vlib_cli_command_t * cmd)
180 {
181  unformat_input_t _line_input, *line_input = &_line_input;
182  u32 spd_id = ~0;
183  int is_add = ~0;
184  clib_error_t *error = NULL;
185 
186  if (!unformat_user (input, unformat_line_input, line_input))
187  return 0;
188 
189  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
190  {
191  if (unformat (line_input, "add"))
192  is_add = 1;
193  else if (unformat (line_input, "del"))
194  is_add = 0;
195  else if (unformat (line_input, "%u", &spd_id))
196  ;
197  else
198  {
199  error = clib_error_return (0, "parse error: '%U'",
200  format_unformat_error, line_input);
201  goto done;
202  }
203  }
204 
205  if (spd_id == ~0)
206  {
207  error = clib_error_return (0, "please specify SPD ID");
208  goto done;
209  }
210 
211  ipsec_add_del_spd (vm, spd_id, is_add);
212 
213 done:
214  unformat_free (line_input);
215 
216  return error;
217 }
218 
219 /* *INDENT-OFF* */
220 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
221  .path = "ipsec spd",
222  .short_help =
223  "ipsec spd [add|del] <id>",
224  .function = ipsec_spd_add_del_command_fn,
225 };
226 /* *INDENT-ON* */
227 
228 
229 static clib_error_t *
231  unformat_input_t * input,
232  vlib_cli_command_t * cmd)
233 {
234  unformat_input_t _line_input, *line_input = &_line_input;
235  ipsec_policy_t p;
236  int rv, is_add = 0;
237  u32 tmp, tmp2, stat_index, local_range_set, remote_range_set;
238  clib_error_t *error = NULL;
240 
241  clib_memset (&p, 0, sizeof (p));
242  p.lport.stop = p.rport.stop = ~0;
243  remote_range_set = local_range_set = is_outbound = 0;
244 
245  if (!unformat_user (input, unformat_line_input, line_input))
246  return 0;
247 
248  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
249  {
250  if (unformat (line_input, "add"))
251  is_add = 1;
252  else if (unformat (line_input, "del"))
253  is_add = 0;
254  else if (unformat (line_input, "ip6"))
255  p.is_ipv6 = 1;
256  else if (unformat (line_input, "spd %u", &p.id))
257  ;
258  else if (unformat (line_input, "inbound"))
259  is_outbound = 0;
260  else if (unformat (line_input, "outbound"))
261  is_outbound = 1;
262  else if (unformat (line_input, "priority %d", &p.priority))
263  ;
264  else if (unformat (line_input, "protocol %u", &tmp))
265  p.protocol = (u8) tmp;
266  else
267  if (unformat
268  (line_input, "action %U", unformat_ipsec_policy_action,
269  &p.policy))
270  {
271  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
272  {
273  error = clib_error_return (0, "unsupported action: 'resolve'");
274  goto done;
275  }
276  }
277  else if (unformat (line_input, "sa %u", &p.sa_id))
278  ;
279  else if (unformat (line_input, "local-ip-range %U - %U",
282  local_range_set = 1;
283  else if (unformat (line_input, "remote-ip-range %U - %U",
286  remote_range_set = 1;
287  else if (unformat (line_input, "local-ip-range %U - %U",
290  {
291  p.is_ipv6 = 1;
292  local_range_set = 1;
293  }
294  else if (unformat (line_input, "remote-ip-range %U - %U",
297  {
298  p.is_ipv6 = 1;
299  remote_range_set = 1;
300  }
301  else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
302  {
303  p.lport.start = tmp;
304  p.lport.stop = tmp2;
305  }
306  else
307  if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
308  {
309  p.rport.start = tmp;
310  p.rport.stop = tmp2;
311  }
312  else
313  {
314  error = clib_error_return (0, "parse error: '%U'",
315  format_unformat_error, line_input);
316  goto done;
317  }
318  }
319 
320  if (!remote_range_set)
321  {
322  if (p.is_ipv6)
323  clib_memset (&p.raddr.stop.ip6, 0xff, 16);
324  else
325  clib_memset (&p.raddr.stop.ip4, 0xff, 4);
326  }
327  if (!local_range_set)
328  {
329  if (p.is_ipv6)
330  clib_memset (&p.laddr.stop.ip6, 0xff, 16);
331  else
332  clib_memset (&p.laddr.stop.ip4, 0xff, 4);
333  }
334 
335  rv = ipsec_policy_mk_type (is_outbound, p.is_ipv6, p.policy, &p.type);
336 
337  if (rv)
338  {
339  error = clib_error_return (0, "unsupported policy type for:",
340  " outboud:%s %s action:%U",
341  (is_outbound ? "yes" : "no"),
342  (p.is_ipv6 ? "IPv4" : "IPv6"),
344  goto done;
345  }
346 
347  rv = ipsec_add_del_policy (vm, &p, is_add, &stat_index);
348 
349  if (!rv)
350  vlib_cli_output (vm, "policy-index:%d", stat_index);
351  else
352  vlib_cli_output (vm, "error:%d", rv);
353 
354 done:
355  unformat_free (line_input);
356 
357  return error;
358 }
359 
360 /* *INDENT-OFF* */
361 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
362  .path = "ipsec policy",
363  .short_help =
364  "ipsec policy [add|del] spd <id> priority <n> ",
366 };
367 /* *INDENT-ON* */
368 
369 static void
371 {
372  u32 sai;
373 
374  /* *INDENT-OFF* */
375  pool_foreach_index (sai, im->sad, ({
376  vlib_cli_output(vm, "%U", format_ipsec_sa, sai,
377  (detail ? IPSEC_FORMAT_DETAIL : IPSEC_FORMAT_BRIEF));
378  }));
379  /* *INDENT-ON* */
380 }
381 
382 static void
384 {
385  u32 spdi;
386 
387  /* *INDENT-OFF* */
388  pool_foreach_index (spdi, im->spds, ({
389  vlib_cli_output(vm, "%U", format_ipsec_spd, spdi);
390  }));
391  /* *INDENT-ON* */
392 }
393 
394 static void
396 {
397  u32 spd_id, sw_if_index;
398  ipsec_spd_t *spd;
399 
400  vlib_cli_output (vm, "SPD Bindings:");
401 
402  /* *INDENT-OFF* */
403  hash_foreach(sw_if_index, spd_id, im->spd_index_by_sw_if_index, ({
404  spd = pool_elt_at_index (im->spds, spd_id);
405  vlib_cli_output (vm, " %d -> %U", spd->id,
406  format_vnet_sw_if_index_name, im->vnet_main,
407  sw_if_index);
408  }));
409  /* *INDENT-ON* */
410 }
411 
412 static walk_rc_t
414 {
416 
417  return (WALK_CONTINUE);
418 }
419 
420 static void
422 {
424 }
425 
426 static clib_error_t *
428  unformat_input_t * input, vlib_cli_command_t * cmd)
429 {
430  ipsec_main_t *im = &ipsec_main;
431 
432  ipsec_sa_show_all (vm, im, 0);
433  ipsec_spd_show_all (vm, im);
436 
437  vlib_cli_output (vm, "IPSec async mode: %s",
438  (im->async_mode ? "on" : "off"));
439 
440  return 0;
441 }
442 
443 /* *INDENT-OFF* */
444 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
445  .path = "show ipsec all",
446  .short_help = "show ipsec all",
447  .function = show_ipsec_command_fn,
448 };
449 /* *INDENT-ON* */
450 
451 static clib_error_t *
453  unformat_input_t * input, vlib_cli_command_t * cmd)
454 {
455  ipsec_main_t *im = &ipsec_main;
456  u32 sai = ~0;
457  u8 detail = 0;
458 
460  {
461  if (unformat (input, "%u", &sai))
462  ;
463  if (unformat (input, "detail"))
464  detail = 1;
465  else
466  break;
467  }
468 
469  if (~0 == sai)
470  ipsec_sa_show_all (vm, im, detail);
471  else
472  vlib_cli_output (vm, "%U", format_ipsec_sa, sai,
474 
475  return 0;
476 }
477 
478 static clib_error_t *
480  unformat_input_t * input, vlib_cli_command_t * cmd)
481 {
482  ipsec_main_t *im = &ipsec_main;
483  u32 sai = ~0;
484 
486  {
487  if (unformat (input, "%u", &sai))
488  ;
489  else
490  break;
491  }
492 
493  if (~0 == sai)
494  {
495  /* *INDENT-OFF* */
496  pool_foreach_index (sai, im->sad, ({
497  ipsec_sa_clear(sai);
498  }));
499  /* *INDENT-ON* */
500  }
501  else
502  {
503  if (pool_is_free_index (im->sad, sai))
504  return clib_error_return (0, "unknown SA index: %d", sai);
505  else
506  ipsec_sa_clear (sai);
507  }
508 
509  return 0;
510 }
511 
512 /* *INDENT-OFF* */
513 VLIB_CLI_COMMAND (show_ipsec_sa_command, static) = {
514  .path = "show ipsec sa",
515  .short_help = "show ipsec sa [index]",
516  .function = show_ipsec_sa_command_fn,
517 };
518 
519 VLIB_CLI_COMMAND (clear_ipsec_sa_command, static) = {
520  .path = "clear ipsec sa",
521  .short_help = "clear ipsec sa [index]",
522  .function = clear_ipsec_sa_command_fn,
523 };
524 /* *INDENT-ON* */
525 
526 static clib_error_t *
528  unformat_input_t * input, vlib_cli_command_t * cmd)
529 {
530  ipsec_main_t *im = &ipsec_main;
531  u8 show_bindings = 0;
532  u32 spdi = ~0;
533 
535  {
536  if (unformat (input, "%u", &spdi))
537  ;
538  else if (unformat (input, "bindings"))
539  show_bindings = 1;
540  else
541  break;
542  }
543 
544  if (show_bindings)
546  else if (~0 != spdi)
547  vlib_cli_output (vm, "%U", format_ipsec_spd, spdi);
548  else
549  ipsec_spd_show_all (vm, im);
550 
551  return 0;
552 }
553 
554 /* *INDENT-OFF* */
555 VLIB_CLI_COMMAND (show_ipsec_spd_command, static) = {
556  .path = "show ipsec spd",
557  .short_help = "show ipsec spd [index]",
558  .function = show_ipsec_spd_command_fn,
559 };
560 /* *INDENT-ON* */
561 
562 static clib_error_t *
564  unformat_input_t * input,
565  vlib_cli_command_t * cmd)
566 {
568 
569  return 0;
570 }
571 
572 /* *INDENT-OFF* */
573 VLIB_CLI_COMMAND (show_ipsec_tunnel_command, static) = {
574  .path = "show ipsec tunnel",
575  .short_help = "show ipsec tunnel",
576  .function = show_ipsec_tunnel_command_fn,
577 };
578 /* *INDENT-ON* */
579 
580 static clib_error_t *
582  unformat_input_t * input,
583  vlib_cli_command_t * cmd)
584 {
585  ipsec_main_t *im = &ipsec_main;
586  u32 verbose = 0;
587 
588  (void) unformat (input, "verbose %u", &verbose);
589 
590  vlib_cli_output (vm, "IPsec AH backends available:");
591  u8 *s = format (NULL, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
592  ipsec_ah_backend_t *ab;
593  /* *INDENT-OFF* */
594  pool_foreach (ab, im->ah_backends, {
595  s = format (s, "%=25s %=25u %=10s\n", ab->name, ab - im->ah_backends,
596  ab - im->ah_backends == im->ah_current_backend ? "yes" : "no");
597  if (verbose) {
598  vlib_node_t *n;
599  n = vlib_get_node (vm, ab->ah4_encrypt_node_index);
600  s = format (s, " enc4 %s (next %d)\n", n->name, ab->ah4_encrypt_next_index);
601  n = vlib_get_node (vm, ab->ah4_decrypt_node_index);
602  s = format (s, " dec4 %s (next %d)\n", n->name, ab->ah4_decrypt_next_index);
603  n = vlib_get_node (vm, ab->ah6_encrypt_node_index);
604  s = format (s, " enc6 %s (next %d)\n", n->name, ab->ah6_encrypt_next_index);
605  n = vlib_get_node (vm, ab->ah6_decrypt_node_index);
606  s = format (s, " dec6 %s (next %d)\n", n->name, ab->ah6_decrypt_next_index);
607  }
608  });
609  /* *INDENT-ON* */
610  vlib_cli_output (vm, "%v", s);
611  _vec_len (s) = 0;
612  vlib_cli_output (vm, "IPsec ESP backends available:");
613  s = format (s, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
615  /* *INDENT-OFF* */
616  pool_foreach (eb, im->esp_backends, {
617  s = format (s, "%=25s %=25u %=10s\n", eb->name, eb - im->esp_backends,
618  eb - im->esp_backends == im->esp_current_backend ? "yes"
619  : "no");
620  if (verbose) {
621  vlib_node_t *n;
622  n = vlib_get_node (vm, eb->esp4_encrypt_node_index);
623  s = format (s, " enc4 %s (next %d)\n", n->name, eb->esp4_encrypt_next_index);
624  n = vlib_get_node (vm, eb->esp4_decrypt_node_index);
625  s = format (s, " dec4 %s (next %d)\n", n->name, eb->esp4_decrypt_next_index);
626  n = vlib_get_node (vm, eb->esp6_encrypt_node_index);
627  s = format (s, " enc6 %s (next %d)\n", n->name, eb->esp6_encrypt_next_index);
628  n = vlib_get_node (vm, eb->esp6_decrypt_node_index);
629  s = format (s, " dec6 %s (next %d)\n", n->name, eb->esp6_decrypt_next_index);
630  }
631  });
632  /* *INDENT-ON* */
633  vlib_cli_output (vm, "%v", s);
634 
635  vec_free (s);
636  return 0;
637 }
638 
639 /* *INDENT-OFF* */
640 VLIB_CLI_COMMAND (ipsec_show_backends_command, static) = {
641  .path = "show ipsec backends",
642  .short_help = "show ipsec backends",
643  .function = ipsec_show_backends_command_fn,
644 };
645 /* *INDENT-ON* */
646 
647 static clib_error_t *
649  unformat_input_t * input,
650  vlib_cli_command_t * cmd)
651 {
652  unformat_input_t _line_input, *line_input = &_line_input;
653  ipsec_main_t *im = &ipsec_main;
654  clib_error_t *error;
655  u32 backend_index;
656 
657  error = ipsec_rsc_in_use (im);
658 
659  if (error)
660  return error;
661 
662  /* Get a line of input. */
663  if (!unformat_user (input, unformat_line_input, line_input))
664  return 0;
665 
666  if (unformat (line_input, "ah"))
667  {
668  if (unformat (line_input, "%u", &backend_index))
669  {
670  if (ipsec_select_ah_backend (im, backend_index) < 0)
671  {
672  return clib_error_return (0, "Invalid AH backend index `%u'",
673  backend_index);
674  }
675  }
676  else
677  {
678  return clib_error_return (0, "Invalid backend index `%U'",
679  format_unformat_error, line_input);
680  }
681  }
682  else if (unformat (line_input, "esp"))
683  {
684  if (unformat (line_input, "%u", &backend_index))
685  {
686  if (ipsec_select_esp_backend (im, backend_index) < 0)
687  {
688  return clib_error_return (0, "Invalid ESP backend index `%u'",
689  backend_index);
690  }
691  }
692  else
693  {
694  return clib_error_return (0, "Invalid backend index `%U'",
695  format_unformat_error, line_input);
696  }
697  }
698  else
699  {
700  return clib_error_return (0, "Unknown input `%U'",
701  format_unformat_error, line_input);
702  }
703 
704  return 0;
705 }
706 
707 /* *INDENT-OFF* */
708 VLIB_CLI_COMMAND (ipsec_select_backend_command, static) = {
709  .path = "ipsec select backend",
710  .short_help = "ipsec select backend <ah|esp> <backend index>",
712 };
713 
714 /* *INDENT-ON* */
715 
716 static clib_error_t *
718  unformat_input_t * input,
719  vlib_cli_command_t * cmd)
720 {
723 
724  return (NULL);
725 }
726 
727 /* *INDENT-OFF* */
728 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
729  .path = "clear ipsec counters",
730  .short_help = "clear ipsec counters",
732 };
733 /* *INDENT-ON* */
734 
735 static u32
737 {
738  return (0x80000000 | ti);
739 }
740 
741 static u32
743 {
744  return (0xc0000000 | ti);
745 }
746 
747 static clib_error_t *
749  unformat_input_t * input,
750  vlib_cli_command_t * cmd)
751 {
752  unformat_input_t _line_input, *line_input = &_line_input;
753  ip46_address_t local_ip = ip46_address_initializer;
754  ip46_address_t remote_ip = ip46_address_initializer;
756  ipsec_crypto_alg_t crypto_alg = IPSEC_CRYPTO_ALG_NONE;
757  ipsec_integ_alg_t integ_alg = IPSEC_INTEG_ALG_NONE;
759  u32 local_spi, remote_spi, salt, table_id, fib_index;
760  u32 instance = ~0;
761  int rv;
762  u32 num_m_args = 0;
763  u8 ipv4_set = 0;
764  u8 ipv6_set = 0;
765  u8 is_add = 1;
766  clib_error_t *error = NULL;
767  ipsec_key_t rck = { 0 };
768  ipsec_key_t lck = { 0 };
769  ipsec_key_t lik = { 0 };
770  ipsec_key_t rik = { 0 };
771 
772  table_id = 0;
773  flags = IPSEC_SA_FLAG_NONE;
774 
775  /* Get a line of input. */
776  if (!unformat_user (input, unformat_line_input, line_input))
777  return 0;
778 
779  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
780  {
781  if (unformat
782  (line_input, "local-ip %U", unformat_ip46_address, &local_ip,
783  IP46_TYPE_ANY))
784  {
785  ip46_address_is_ip4 (&local_ip) ? (ipv4_set = 1) : (ipv6_set = 1);
786  num_m_args++;
787  }
788  else
789  if (unformat
790  (line_input, "remote-ip %U", unformat_ip46_address, &remote_ip,
791  IP46_TYPE_ANY))
792  {
793  ip46_address_is_ip4 (&remote_ip) ? (ipv4_set = 1) : (ipv6_set = 1);
794  num_m_args++;
795  }
796  else if (unformat (line_input, "local-spi %u", &local_spi))
797  num_m_args++;
798  else if (unformat (line_input, "remote-spi %u", &remote_spi))
799  num_m_args++;
800  else if (unformat (line_input, "salt 0x%x", &salt))
801  ;
802  else if (unformat (line_input, "udp-encap"))
803  flags |= IPSEC_SA_FLAG_UDP_ENCAP;
804  else if (unformat (line_input, "use-esn"))
805  flags |= IPSEC_SA_FLAG_USE_ESN;
806  else if (unformat (line_input, "use-anti-replay"))
807  flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
808  else if (unformat (line_input, "instance %u", &instance))
809  ;
810  else if (unformat (line_input, "tx-table %u", &table_id))
811  ;
812  else
813  if (unformat
814  (line_input, "local-crypto-key %U", unformat_ipsec_key, &lck))
815  ;
816  else
817  if (unformat
818  (line_input, "remote-crypto-key %U", unformat_ipsec_key, &rck))
819  ;
820  else if (unformat (line_input, "crypto-alg %U",
821  unformat_ipsec_crypto_alg, &crypto_alg))
822  ;
823  else
824  if (unformat
825  (line_input, "local-integ-key %U", unformat_ipsec_key, &lik))
826  ;
827  else
828  if (unformat
829  (line_input, "remote-integ-key %U", unformat_ipsec_key, &rik))
830  ;
831  else if (unformat (line_input, "integ-alg %U",
832  unformat_ipsec_integ_alg, &integ_alg))
833  ;
834  else if (unformat (line_input, "del"))
835  is_add = 0;
836  else if (unformat (line_input, "nh &U", unformat_ip_address, &nh))
837  ;
838  else
839  {
840  error = clib_error_return (0, "unknown input `%U'",
841  format_unformat_error, line_input);
842  goto done;
843  }
844  }
845 
846  if (num_m_args < 4)
847  {
848  error = clib_error_return (0, "mandatory argument(s) missing");
849  goto done;
850  }
851 
852  if (ipv4_set && ipv6_set)
853  return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
854 
855  fib_index = fib_table_find (fib_ip_proto (ipv6_set), table_id);
856 
857  if (~0 == fib_index)
858  {
859  rv = VNET_API_ERROR_NO_SUCH_FIB;
860  goto done;
861  }
862 
863  if (is_add)
864  {
865  // remote = input, local = output
867 
868  /* create an ip-ip tunnel, then the two SA, then bind them */
869  rv =
871  instance, &local_ip, &remote_ip, fib_index,
872  TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
873  TUNNEL_MODE_P2P, &sw_if_index);
874  rv |=
876  local_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
877  &lck, integ_alg, &lik, flags, table_id,
878  clib_host_to_net_u32 (salt), &local_ip,
879  &remote_ip, NULL, IPSEC_UDP_PORT_NONE,
881  rv |=
883  remote_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
884  &rck, integ_alg, &rik,
885  (flags | IPSEC_SA_FLAG_IS_INBOUND), table_id,
886  clib_host_to_net_u32 (salt), &remote_ip,
887  &local_ip, NULL, IPSEC_UDP_PORT_NONE,
889  rv |=
890  ipsec_tun_protect_update_one (sw_if_index, &nh,
891  ipsec_tun_mk_local_sa_id (sw_if_index),
893  (sw_if_index));
894  }
895  else
896  rv = 0;
897 
898  switch (rv)
899  {
900  case 0:
901  break;
902  case VNET_API_ERROR_INVALID_VALUE:
903  error = clib_error_return (0,
904  "IPSec tunnel interface already exists...");
905  goto done;
906  default:
907  error = clib_error_return (0, "ipsec_register_interface returned %d",
908  rv);
909  goto done;
910  }
911 
912 done:
913  unformat_free (line_input);
914 
915  return error;
916 }
917 
918 /* *INDENT-OFF* */
919 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
920  .path = "create ipsec tunnel",
921  .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> "
922  "remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap] [use-esn] [use-anti-replay] "
923  "[tx-table <table-id>]",
924  .function = create_ipsec_tunnel_command_fn,
925 };
926 /* *INDENT-ON* */
927 
928 static clib_error_t *
930  unformat_input_t * input, vlib_cli_command_t * cmd)
931 {
932  unformat_input_t _line_input, *line_input = &_line_input;
933  u32 sw_if_index, is_del, sa_in, sa_out, *sa_ins = NULL;
934  ip_address_t peer = { };
935  vnet_main_t *vnm;
936 
937  is_del = 0;
938  sw_if_index = ~0;
939  vnm = vnet_get_main ();
940 
941  if (!unformat_user (input, unformat_line_input, line_input))
942  return 0;
943 
944  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
945  {
946  if (unformat (line_input, "del"))
947  is_del = 1;
948  else if (unformat (line_input, "add"))
949  is_del = 0;
950  else if (unformat (line_input, "sa-in %d", &sa_in))
951  vec_add1 (sa_ins, sa_in);
952  else if (unformat (line_input, "sa-out %d", &sa_out))
953  ;
954  else if (unformat (line_input, "%U",
955  unformat_vnet_sw_interface, vnm, &sw_if_index))
956  ;
957  else if (unformat (line_input, "%U", unformat_ip_address, &peer))
958  ;
959  else
960  return (clib_error_return (0, "unknown input '%U'",
961  format_unformat_error, line_input));
962  }
963 
964  if (!is_del)
965  ipsec_tun_protect_update (sw_if_index, &peer, sa_out, sa_ins);
966 
967  unformat_free (line_input);
968  return NULL;
969 }
970 
971 /**
972  * Protect tunnel with IPSEC
973  */
974 /* *INDENT-OFF* */
975 VLIB_CLI_COMMAND (ipsec_tun_protect_cmd_node, static) =
976 {
977  .path = "ipsec tunnel protect",
978  .function = ipsec_tun_protect_cmd,
979  .short_help = "ipsec tunnel protect <interface> input-sa <SA> output-sa <SA>",
980  // this is not MP safe
981 };
982 /* *INDENT-ON* */
983 
984 
985 static clib_error_t *
987  unformat_input_t * input, vlib_cli_command_t * cmd)
988 {
990 
991  return NULL;
992 }
993 
994 /**
995  * show IPSEC tunnel protection
996  */
997 /* *INDENT-OFF* */
998 VLIB_CLI_COMMAND (ipsec_tun_protect_show_node, static) =
999 {
1000  .path = "show ipsec protect",
1001  .function = ipsec_tun_protect_show,
1002  .short_help = "show ipsec protect",
1003 };
1004 /* *INDENT-ON* */
1005 
1006 static clib_error_t *
1008  unformat_input_t * input,
1009  vlib_cli_command_t * cmd)
1010 {
1011  ipsec_main_t *im = &ipsec_main;
1012 
1013  {
1015  ipsec4_tunnel_key_t key;
1016 
1017  vlib_cli_output (vm, "IPv4:");
1018 
1019  /* *INDENT-OFF* */
1020  hash_foreach(key.as_u64, value.as_u64, im->tun4_protect_by_key,
1021  ({
1022  vlib_cli_output (vm, " %U", format_ipsec4_tunnel_key, &key);
1023  vlib_cli_output (vm, " tun:%d sa:%d", value.tun_index, value.sa_index);
1024  }));
1025  /* *INDENT-ON* */
1026  }
1027 
1028  {
1030  ipsec6_tunnel_key_t *key;
1031 
1032  vlib_cli_output (vm, "IPv6:");
1033 
1034  /* *INDENT-OFF* */
1036  ({
1037  vlib_cli_output (vm, " %U", format_ipsec6_tunnel_key, key);
1038  vlib_cli_output (vm, " tun:%d sa:%d", value.tun_index, value.sa_index);
1039  }));
1040  /* *INDENT-ON* */
1041  }
1042 
1043  return NULL;
1044 }
1045 
1046 /**
1047  * show IPSEC tunnel protection hash tables
1048  */
1049 /* *INDENT-OFF* */
1050 VLIB_CLI_COMMAND (ipsec_tun_protect_hash_show_node, static) =
1051 {
1052  .path = "show ipsec protect-hash",
1053  .function = ipsec_tun_protect_hash_show,
1054  .short_help = "show ipsec protect-hash",
1055 };
1056 /* *INDENT-ON* */
1057 
1058 clib_error_t *
1060 {
1061  return 0;
1062 }
1063 
1065 
1066 static clib_error_t *
1068  vlib_cli_command_t * cmd)
1069 {
1070  unformat_input_t _line_input, *line_input = &_line_input;
1071  int async_enable = 0;
1072 
1073  if (!unformat_user (input, unformat_line_input, line_input))
1074  return 0;
1075 
1076  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
1077  {
1078  if (unformat (line_input, "on"))
1079  async_enable = 1;
1080  else if (unformat (line_input, "off"))
1081  async_enable = 0;
1082  else
1083  return (clib_error_return (0, "unknown input '%U'",
1084  format_unformat_error, line_input));
1085  }
1086 
1087  vnet_crypto_request_async_mode (async_enable);
1088  ipsec_set_async_mode (async_enable);
1089 
1090  unformat_free (line_input);
1091  return (NULL);
1092 }
1093 
1094 /* *INDENT-OFF* */
1095 VLIB_CLI_COMMAND (set_async_mode_command, static) = {
1096  .path = "set ipsec async mode",
1097  .short_help = "set ipsec async mode on|off",
1098  .function = set_async_mode_command_fn,
1099 };
1100 /* *INDENT-ON* */
1101 
1102 /*
1103  * fd.io coding-style-patch-verification: ON
1104  *
1105  * Local Variables:
1106  * eval: (c-set-style "gnu")
1107  * End:
1108  */
static clib_error_t * ipsec_select_backend_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:648
u32 spi
ipsec_spd_t * spds
Definition: ipsec.h:105
uword * tun6_protect_by_key
Definition: ipsec.h:129
static u32 ipsec_tun_mk_local_sa_id(u32 ti)
Definition: ipsec_cli.c:736
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
vl_api_fib_path_nh_t nh
Definition: fib_types.api:126
ipsec_integ_alg_t
Definition: ipsec_sa.h:59
ip46_address_range_t laddr
static clib_error_t * show_ipsec_spd_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:527
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
int ipsec_policy_mk_type(bool is_outbound, bool is_ipv6, ipsec_policy_action_t action, ipsec_spd_policy_type_t *type)
void vnet_crypto_request_async_mode(int is_enable)
Definition: crypto.c:554
static clib_error_t * create_ipsec_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:748
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:590
ipsec_protocol_t
Definition: ipsec_sa.h:67
void ipsec_sa_clear(index_t sai)
Definition: ipsec_sa.c:444
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
int ipsec_select_ah_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:270
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
unformat_function_t unformat_vnet_sw_interface
A Secruity Policy Database.
Definition: ipsec_spd.h:46
int ipsec_sa_add_and_lock(u32 id, u32 spi, ipsec_protocol_t proto, ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck, ipsec_integ_alg_t integ_alg, const ipsec_key_t *ik, ipsec_sa_flags_t flags, u32 tx_table_id, u32 salt, const ip46_address_t *tun_src, const ip46_address_t *tun_dst, u32 *sa_out_index, u16 src_port, u16 dst_port)
Definition: ipsec_sa.c:170
int ipip_add_tunnel(ipip_transport_t transport, u32 instance, ip46_address_t *src, ip46_address_t *dst, u32 fib_index, tunnel_encap_decap_flags_t flags, ip_dscp_t dscp, tunnel_mode_t tmode, u32 *sw_if_indexp)
Definition: ipip.c:653
static u8 ip46_address_is_ip4(const ip46_address_t *ip46)
Definition: ip46_address.h:55
void ipsec_tun_protect_walk(ipsec_tun_protect_walk_cb_t fn, void *ctx)
Definition: ipsec_tun.c:762
static void ipsec_tunnel_show_all(vlib_main_t *vm)
Definition: ipsec_cli.c:421
unsigned char u8
Definition: types.h:56
u8 id[64]
Definition: dhcp.api:160
u8 * format_ipsec_tun_protect_index(u8 *s, va_list *args)
Definition: ipsec_format.c:343
uword * spd_index_by_sw_if_index
Definition: ipsec.h:122
enum walk_rc_t_ walk_rc_t
Walk return code.
bool is_outbound
Definition: ipsec.api:95
void vlib_clear_combined_counters(vlib_combined_counter_main_t *cm)
Clear a collection of combined counters.
Definition: counter.c:61
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:513
unformat_function_t unformat_ip4_address
Definition: format.h:68
vl_api_interface_index_t sw_if_index
Definition: gre.api:53
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
ipsec_main_t ipsec_main
Definition: ipsec.c:28
int ipsec_select_esp_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:293
#define hash_foreach(key_var, value_var, h, body)
Definition: hash.h:442
uword unformat_ipsec_crypto_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:96
#define clib_error_return(e, args...)
Definition: error.h:99
int ipsec_sa_unlock_id(u32 id)
Definition: ipsec_sa.c:428
port_range_t rport
u8 * format_ipsec_sa(u8 *s, va_list *args)
Definition: ipsec_format.c:269
u32 salt
unsigned int u32
Definition: types.h:88
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1097
u32 sa_in[n_sa_in]
Definition: ipsec.api:252
static clib_error_t * ipsec_tun_protect_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:986
unformat_function_t unformat_line_input
Definition: format.h:283
u32 sa_out
Definition: ipsec.api:250
vlib_combined_counter_main_t ipsec_spd_policy_counters
Policy packet & bytes counters.
u8 * format_ipsec_spd(u8 *s, va_list *args)
Definition: ipsec_format.c:203
vl_api_ip_proto_t proto
Definition: acl_types.api:50
static clib_error_t * ipsec_policy_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:230
long ctx[MAX_CONNS]
Definition: main.c:144
vnet_main_t * vnet_main
Definition: ipsec.h:118
struct _unformat_input_t unformat_input_t
unsigned short u16
Definition: types.h:57
int ipsec_add_del_policy(vlib_main_t *vm, ipsec_policy_t *policy, int is_add, u32 *stat_index)
Add/Delete a SPD.
static clib_error_t * set_interface_spd_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:29
static clib_error_t * set_async_mode_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:1067
clib_error_t * ipsec_rsc_in_use(ipsec_main_t *im)
Definition: ipsec.c:258
static clib_error_t * ipsec_show_backends_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:581
ipsec_spd_policy_type_t type
uword unformat_ip_address(unformat_input_t *input, va_list *args)
Definition: ip_types.c:41
#define hash_foreach_mem(key_var, value_var, h, body)
Definition: hash.h:461
vlib_main_t * vm
Definition: in2out_ed.c:1599
vl_api_address_t peer
Definition: teib.api:28
#define IP_ADDRESS_V4_ALL_0S
Definition: ip_types.h:54
static void ipsec_spd_bindings_show_all(vlib_main_t *vm, ipsec_main_t *im)
Definition: ipsec_cli.c:395
static clib_error_t * clear_ipsec_counters_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:717
unformat_function_t unformat_ip6_address
Definition: format.h:89
int ipsec_tun_protect_update_one(u32 sw_if_index, const ip_address_t *nh, u32 sa_out, u32 sa_in)
Definition: ipsec_tun.c:477
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 flags
Definition: vhost_user.h:248
static void ipsec_sa_show_all(vlib_main_t *vm, ipsec_main_t *im, u8 detail)
Definition: ipsec_cli.c:370
ipsec_ah_backend_t * ah_backends
Definition: ipsec.h:166
clib_error_t * ipsec_cli_init(vlib_main_t *vm)
Definition: ipsec_cli.c:1059
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
static clib_error_t * clear_ipsec_sa_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:479
ipsec_policy_action_t policy
ip46_address_t start
enum ipsec_sad_flags_t_ ipsec_sa_flags_t
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:299
A Secruity Policy.
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:152
static void ipsec_spd_show_all(vlib_main_t *vm, ipsec_main_t *im)
Definition: ipsec_cli.c:383
vlib_combined_counter_main_t ipsec_sa_counters
SA packet & bytes counters.
Definition: ipsec_sa.c:27
u8 value
Definition: qos.api:54
void ipsec_set_async_mode(u32 is_enabled)
Definition: ipsec.c:339
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
ipsec_sa_t * sad
Definition: ipsec.h:107
static clib_error_t * show_ipsec_sa_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:452
uword unformat_ipsec_integ_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:128
static clib_error_t * ipsec_tun_protect_cmd(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:929
u8 * format_ipsec_policy_action(u8 *s, va_list *args)
Definition: ipsec_format.c:28
uword unformat_ipsec_policy_action(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:64
unformat_function_t unformat_ip46_address
Definition: format.h:63
typedef key
Definition: ipsec_types.api:85
ip46_address_range_t raddr
u32 instance
Definition: gre.api:51
static fib_protocol_t fib_ip_proto(bool is_ip6)
Convert from boolean is_ip6 to FIB protocol.
Definition: fib_types.h:80
static u32 ipsec_tun_mk_remote_sa_id(u32 ti)
Definition: ipsec_cli.c:742
static clib_error_t * show_ipsec_tunnel_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:563
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
ipsec_crypto_alg_t
Definition: ipsec_sa.h:37
static clib_error_t * ipsec_sa_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:74
int ipsec_set_interface_spd(vlib_main_t *vm, u32 sw_if_index, u32 spd_id, int is_add)
Bind/attach a SPD to an interface.
Definition: ipsec_spd.c:63
static clib_error_t * ipsec_tun_protect_hash_show(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:1007
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
port_range_t lport
int ipsec_add_del_spd(vlib_main_t *vm, u32 spd_id, int is_add)
Add/Delete a SPD.
Definition: ipsec_spd.c:20
static clib_error_t * show_ipsec_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:427
static walk_rc_t ipsec_tun_protect_show_one(index_t itpi, void *ctx)
Definition: ipsec_cli.c:413
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:558
static clib_error_t * ipsec_spd_add_del_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: ipsec_cli.c:177
u32 table_id
Definition: fib_types.api:118
u8 async_mode
Definition: ipsec.h:202
uword unformat_ipsec_key(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:242
#define IPSEC_UDP_PORT_NONE
Definition: ipsec_sa.h:277
#define ip46_address_initializer
Definition: ip46_address.h:52
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:171
uword * tun4_protect_by_key
Definition: ipsec.h:128
int ipsec_tun_protect_update(u32 sw_if_index, const ip_address_t *nh, u32 sa_out, u32 *sas_in)
Definition: ipsec_tun.c:598