FD.io VPP  v20.01-48-g3e0dafb74
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;
90  int is_add, rv;
91 
92  salt = 0;
93  error = NULL;
94  is_add = 0;
95  flags = IPSEC_SA_FLAG_NONE;
96  proto = IPSEC_PROTOCOL_ESP;
97  integ_alg = IPSEC_INTEG_ALG_NONE;
98  crypto_alg = IPSEC_CRYPTO_ALG_NONE;
99 
100  if (!unformat_user (input, unformat_line_input, line_input))
101  return 0;
102 
103  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
104  {
105  if (unformat (line_input, "add %u", &id))
106  is_add = 1;
107  else if (unformat (line_input, "del %u", &id))
108  is_add = 0;
109  else if (unformat (line_input, "spi %u", &spi))
110  ;
111  else if (unformat (line_input, "salt 0x%x", &salt))
112  ;
113  else if (unformat (line_input, "esp"))
114  proto = IPSEC_PROTOCOL_ESP;
115  else if (unformat (line_input, "ah"))
116  proto = IPSEC_PROTOCOL_AH;
117  else if (unformat (line_input, "crypto-key %U",
118  unformat_ipsec_key, &ck))
119  ;
120  else if (unformat (line_input, "crypto-alg %U",
121  unformat_ipsec_crypto_alg, &crypto_alg))
122  ;
123  else if (unformat (line_input, "integ-key %U", unformat_ipsec_key, &ik))
124  ;
125  else if (unformat (line_input, "integ-alg %U",
126  unformat_ipsec_integ_alg, &integ_alg))
127  ;
128  else if (unformat (line_input, "tunnel-src %U",
130  {
131  flags |= IPSEC_SA_FLAG_IS_TUNNEL;
132  if (!ip46_address_is_ip4 (&tun_src))
133  flags |= IPSEC_SA_FLAG_IS_TUNNEL_V6;
134  }
135  else if (unformat (line_input, "tunnel-dst %U",
137  ;
138  else if (unformat (line_input, "udp-encap"))
139  flags |= IPSEC_SA_FLAG_UDP_ENCAP;
140  else
141  {
142  error = clib_error_return (0, "parse error: '%U'",
143  format_unformat_error, line_input);
144  goto done;
145  }
146  }
147 
148  if (is_add)
149  rv = ipsec_sa_add_and_lock (id, spi, proto, crypto_alg,
150  &ck, integ_alg, &ik, flags,
151  0, clib_host_to_net_u32 (salt),
152  &tun_src, &tun_dst, NULL);
153  else
154  rv = ipsec_sa_unlock_id (id);
155 
156  if (rv)
157  error = clib_error_return (0, "failed");
158 
159 done:
160  unformat_free (line_input);
161 
162  return error;
163 }
164 
165 /* *INDENT-OFF* */
166 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
167  .path = "ipsec sa",
168  .short_help =
169  "ipsec sa [add|del]",
170  .function = ipsec_sa_add_del_command_fn,
171 };
172 /* *INDENT-ON* */
173 
174 static clib_error_t *
176  unformat_input_t * input,
177  vlib_cli_command_t * cmd)
178 {
179  unformat_input_t _line_input, *line_input = &_line_input;
180  u32 spd_id = ~0;
181  int is_add = ~0;
182  clib_error_t *error = NULL;
183 
184  if (!unformat_user (input, unformat_line_input, line_input))
185  return 0;
186 
187  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
188  {
189  if (unformat (line_input, "add"))
190  is_add = 1;
191  else if (unformat (line_input, "del"))
192  is_add = 0;
193  else if (unformat (line_input, "%u", &spd_id))
194  ;
195  else
196  {
197  error = clib_error_return (0, "parse error: '%U'",
198  format_unformat_error, line_input);
199  goto done;
200  }
201  }
202 
203  if (spd_id == ~0)
204  {
205  error = clib_error_return (0, "please specify SPD ID");
206  goto done;
207  }
208 
209  ipsec_add_del_spd (vm, spd_id, is_add);
210 
211 done:
212  unformat_free (line_input);
213 
214  return error;
215 }
216 
217 /* *INDENT-OFF* */
218 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
219  .path = "ipsec spd",
220  .short_help =
221  "ipsec spd [add|del] <id>",
222  .function = ipsec_spd_add_del_command_fn,
223 };
224 /* *INDENT-ON* */
225 
226 
227 static clib_error_t *
229  unformat_input_t * input,
230  vlib_cli_command_t * cmd)
231 {
232  unformat_input_t _line_input, *line_input = &_line_input;
233  ipsec_policy_t p;
234  int rv, is_add = 0;
235  u32 tmp, tmp2, stat_index;
236  clib_error_t *error = NULL;
238 
239  clib_memset (&p, 0, sizeof (p));
240  p.lport.stop = p.rport.stop = ~0;
241  is_outbound = 0;
242 
243  if (!unformat_user (input, unformat_line_input, line_input))
244  return 0;
245 
246  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
247  {
248  if (unformat (line_input, "add"))
249  is_add = 1;
250  else if (unformat (line_input, "del"))
251  is_add = 0;
252  else if (unformat (line_input, "spd %u", &p.id))
253  ;
254  else if (unformat (line_input, "inbound"))
255  is_outbound = 0;
256  else if (unformat (line_input, "outbound"))
257  is_outbound = 1;
258  else if (unformat (line_input, "priority %d", &p.priority))
259  ;
260  else if (unformat (line_input, "protocol %u", &tmp))
261  p.protocol = (u8) tmp;
262  else
263  if (unformat
264  (line_input, "action %U", unformat_ipsec_policy_action,
265  &p.policy))
266  {
267  if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
268  {
269  error = clib_error_return (0, "unsupported action: 'resolve'");
270  goto done;
271  }
272  }
273  else if (unformat (line_input, "sa %u", &p.sa_id))
274  ;
275  else if (unformat (line_input, "local-ip-range %U - %U",
278  ;
279  else if (unformat (line_input, "remote-ip-range %U - %U",
282  ;
283  else if (unformat (line_input, "local-ip-range %U - %U",
286  {
287  p.is_ipv6 = 1;
288  }
289  else if (unformat (line_input, "remote-ip-range %U - %U",
292  {
293  p.is_ipv6 = 1;
294  }
295  else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
296  {
297  p.lport.start = tmp;
298  p.lport.stop = tmp2;
299  }
300  else
301  if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
302  {
303  p.rport.start = tmp;
304  p.rport.stop = tmp2;
305  }
306  else
307  {
308  error = clib_error_return (0, "parse error: '%U'",
309  format_unformat_error, line_input);
310  goto done;
311  }
312  }
313 
314  rv = ipsec_policy_mk_type (is_outbound, p.is_ipv6, p.policy, &p.type);
315 
316  if (rv)
317  {
318  error = clib_error_return (0, "unsupported policy type for:",
319  " outboud:%s %s action:%U",
320  (is_outbound ? "yes" : "no"),
321  (p.is_ipv6 ? "IPv4" : "IPv6"),
323  goto done;
324  }
325 
326  rv = ipsec_add_del_policy (vm, &p, is_add, &stat_index);
327 
328  if (!rv)
329  vlib_cli_output (vm, "policy-index:%d", stat_index);
330  else
331  vlib_cli_output (vm, "error:%d", rv);
332 
333 done:
334  unformat_free (line_input);
335 
336  return error;
337 }
338 
339 /* *INDENT-OFF* */
340 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
341  .path = "ipsec policy",
342  .short_help =
343  "ipsec policy [add|del] spd <id> priority <n> ",
345 };
346 /* *INDENT-ON* */
347 
348 static void
350 {
351  u32 sai;
352 
353  /* *INDENT-OFF* */
354  pool_foreach_index (sai, im->sad, ({
355  vlib_cli_output(vm, "%U", format_ipsec_sa, sai,
356  (detail ? IPSEC_FORMAT_DETAIL : IPSEC_FORMAT_BRIEF));
357  }));
358  /* *INDENT-ON* */
359 }
360 
361 static void
363 {
364  u32 spdi;
365 
366  /* *INDENT-OFF* */
367  pool_foreach_index (spdi, im->spds, ({
368  vlib_cli_output(vm, "%U", format_ipsec_spd, spdi);
369  }));
370  /* *INDENT-ON* */
371 }
372 
373 static void
375 {
376  u32 spd_id, sw_if_index;
377  ipsec_spd_t *spd;
378 
379  vlib_cli_output (vm, "SPD Bindings:");
380 
381  /* *INDENT-OFF* */
382  hash_foreach(sw_if_index, spd_id, im->spd_index_by_sw_if_index, ({
383  spd = pool_elt_at_index (im->spds, spd_id);
384  vlib_cli_output (vm, " %d -> %U", spd->id,
385  format_vnet_sw_if_index_name, im->vnet_main,
386  sw_if_index);
387  }));
388  /* *INDENT-ON* */
389 }
390 
391 static walk_rc_t
393 {
394  vlib_cli_output (ctx, "%U", format_ipsec_tun_protect, itpi);
395 
396  return (WALK_CONTINUE);
397 }
398 
399 static void
401 {
403 }
404 
405 static clib_error_t *
407  unformat_input_t * input, vlib_cli_command_t * cmd)
408 {
409  ipsec_main_t *im = &ipsec_main;
410 
411  ipsec_sa_show_all (vm, im, 0);
412  ipsec_spd_show_all (vm, im);
415 
416  return 0;
417 }
418 
419 /* *INDENT-OFF* */
420 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
421  .path = "show ipsec all",
422  .short_help = "show ipsec all",
423  .function = show_ipsec_command_fn,
424 };
425 /* *INDENT-ON* */
426 
427 static clib_error_t *
429  unformat_input_t * input, vlib_cli_command_t * cmd)
430 {
431  ipsec_main_t *im = &ipsec_main;
432  u32 sai = ~0;
433  u8 detail = 0;
434 
436  {
437  if (unformat (input, "%u", &sai))
438  ;
439  if (unformat (input, "detail"))
440  detail = 1;
441  else
442  break;
443  }
444 
445  if (~0 == sai)
446  ipsec_sa_show_all (vm, im, detail);
447  else
448  vlib_cli_output (vm, "%U", format_ipsec_sa, sai,
450 
451  return 0;
452 }
453 
454 static clib_error_t *
456  unformat_input_t * input, vlib_cli_command_t * cmd)
457 {
458  ipsec_main_t *im = &ipsec_main;
459  u32 sai = ~0;
460 
462  {
463  if (unformat (input, "%u", &sai))
464  ;
465  else
466  break;
467  }
468 
469  if (~0 == sai)
470  {
471  /* *INDENT-OFF* */
472  pool_foreach_index (sai, im->sad, ({
473  ipsec_sa_clear(sai);
474  }));
475  /* *INDENT-ON* */
476  }
477  else
478  {
479  if (pool_is_free_index (im->sad, sai))
480  return clib_error_return (0, "unknown SA index: %d", sai);
481  else
482  ipsec_sa_clear (sai);
483  }
484 
485  return 0;
486 }
487 
488 /* *INDENT-OFF* */
489 VLIB_CLI_COMMAND (show_ipsec_sa_command, static) = {
490  .path = "show ipsec sa",
491  .short_help = "show ipsec sa [index]",
492  .function = show_ipsec_sa_command_fn,
493 };
494 
495 VLIB_CLI_COMMAND (clear_ipsec_sa_command, static) = {
496  .path = "clear ipsec sa",
497  .short_help = "clear ipsec sa [index]",
498  .function = clear_ipsec_sa_command_fn,
499 };
500 /* *INDENT-ON* */
501 
502 static clib_error_t *
504  unformat_input_t * input, vlib_cli_command_t * cmd)
505 {
506  ipsec_main_t *im = &ipsec_main;
507  u8 show_bindings = 0;
508  u32 spdi = ~0;
509 
511  {
512  if (unformat (input, "%u", &spdi))
513  ;
514  else if (unformat (input, "bindings"))
515  show_bindings = 1;
516  else
517  break;
518  }
519 
520  if (show_bindings)
522  else if (~0 != spdi)
523  vlib_cli_output (vm, "%U", format_ipsec_spd, spdi);
524  else
525  ipsec_spd_show_all (vm, im);
526 
527  return 0;
528 }
529 
530 /* *INDENT-OFF* */
531 VLIB_CLI_COMMAND (show_ipsec_spd_command, static) = {
532  .path = "show ipsec spd",
533  .short_help = "show ipsec spd [index]",
534  .function = show_ipsec_spd_command_fn,
535 };
536 /* *INDENT-ON* */
537 
538 static clib_error_t *
540  unformat_input_t * input,
541  vlib_cli_command_t * cmd)
542 {
544 
545  return 0;
546 }
547 
548 /* *INDENT-OFF* */
549 VLIB_CLI_COMMAND (show_ipsec_tunnel_command, static) = {
550  .path = "show ipsec tunnel",
551  .short_help = "show ipsec tunnel",
552  .function = show_ipsec_tunnel_command_fn,
553 };
554 /* *INDENT-ON* */
555 
556 static clib_error_t *
558  unformat_input_t * input,
559  vlib_cli_command_t * cmd)
560 {
561  ipsec_main_t *im = &ipsec_main;
562  u32 verbose = 0;
563 
564  (void) unformat (input, "verbose %u", &verbose);
565 
566  vlib_cli_output (vm, "IPsec AH backends available:");
567  u8 *s = format (NULL, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
568  ipsec_ah_backend_t *ab;
569  /* *INDENT-OFF* */
570  pool_foreach (ab, im->ah_backends, {
571  s = format (s, "%=25s %=25u %=10s\n", ab->name, ab - im->ah_backends,
572  ab - im->ah_backends == im->ah_current_backend ? "yes" : "no");
573  if (verbose) {
574  vlib_node_t *n;
575  n = vlib_get_node (vm, ab->ah4_encrypt_node_index);
576  s = format (s, " enc4 %s (next %d)\n", n->name, ab->ah4_encrypt_next_index);
577  n = vlib_get_node (vm, ab->ah4_decrypt_node_index);
578  s = format (s, " dec4 %s (next %d)\n", n->name, ab->ah4_decrypt_next_index);
579  n = vlib_get_node (vm, ab->ah6_encrypt_node_index);
580  s = format (s, " enc6 %s (next %d)\n", n->name, ab->ah6_encrypt_next_index);
581  n = vlib_get_node (vm, ab->ah6_decrypt_node_index);
582  s = format (s, " dec6 %s (next %d)\n", n->name, ab->ah6_decrypt_next_index);
583  }
584  });
585  /* *INDENT-ON* */
586  vlib_cli_output (vm, "%v", s);
587  _vec_len (s) = 0;
588  vlib_cli_output (vm, "IPsec ESP backends available:");
589  s = format (s, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
591  /* *INDENT-OFF* */
592  pool_foreach (eb, im->esp_backends, {
593  s = format (s, "%=25s %=25u %=10s\n", eb->name, eb - im->esp_backends,
594  eb - im->esp_backends == im->esp_current_backend ? "yes"
595  : "no");
596  if (verbose) {
597  vlib_node_t *n;
598  n = vlib_get_node (vm, eb->esp4_encrypt_node_index);
599  s = format (s, " enc4 %s (next %d)\n", n->name, eb->esp4_encrypt_next_index);
600  n = vlib_get_node (vm, eb->esp4_decrypt_node_index);
601  s = format (s, " dec4 %s (next %d)\n", n->name, eb->esp4_decrypt_next_index);
602  n = vlib_get_node (vm, eb->esp6_encrypt_node_index);
603  s = format (s, " enc6 %s (next %d)\n", n->name, eb->esp6_encrypt_next_index);
604  n = vlib_get_node (vm, eb->esp6_decrypt_node_index);
605  s = format (s, " dec6 %s (next %d)\n", n->name, eb->esp6_decrypt_next_index);
606  }
607  });
608  /* *INDENT-ON* */
609  vlib_cli_output (vm, "%v", s);
610 
611  vec_free (s);
612  return 0;
613 }
614 
615 /* *INDENT-OFF* */
616 VLIB_CLI_COMMAND (ipsec_show_backends_command, static) = {
617  .path = "show ipsec backends",
618  .short_help = "show ipsec backends",
619  .function = ipsec_show_backends_command_fn,
620 };
621 /* *INDENT-ON* */
622 
623 static clib_error_t *
625  unformat_input_t * input,
626  vlib_cli_command_t * cmd)
627 {
628  unformat_input_t _line_input, *line_input = &_line_input;
629  ipsec_main_t *im = &ipsec_main;
630  clib_error_t *error;
631  u32 backend_index;
632 
633  error = ipsec_rsc_in_use (im);
634 
635  if (error)
636  return error;
637 
638  /* Get a line of input. */
639  if (!unformat_user (input, unformat_line_input, line_input))
640  return 0;
641 
642  if (unformat (line_input, "ah"))
643  {
644  if (unformat (line_input, "%u", &backend_index))
645  {
646  if (ipsec_select_ah_backend (im, backend_index) < 0)
647  {
648  return clib_error_return (0, "Invalid AH backend index `%u'",
649  backend_index);
650  }
651  }
652  else
653  {
654  return clib_error_return (0, "Invalid backend index `%U'",
655  format_unformat_error, line_input);
656  }
657  }
658  else if (unformat (line_input, "esp"))
659  {
660  if (unformat (line_input, "%u", &backend_index))
661  {
662  if (ipsec_select_esp_backend (im, backend_index) < 0)
663  {
664  return clib_error_return (0, "Invalid ESP backend index `%u'",
665  backend_index);
666  }
667  }
668  else
669  {
670  return clib_error_return (0, "Invalid backend index `%U'",
671  format_unformat_error, line_input);
672  }
673  }
674  else
675  {
676  return clib_error_return (0, "Unknown input `%U'",
677  format_unformat_error, line_input);
678  }
679 
680  return 0;
681 }
682 
683 /* *INDENT-OFF* */
684 VLIB_CLI_COMMAND (ipsec_select_backend_command, static) = {
685  .path = "ipsec select backend",
686  .short_help = "ipsec select backend <ah|esp> <backend index>",
688 };
689 
690 /* *INDENT-ON* */
691 
692 static clib_error_t *
694  unformat_input_t * input,
695  vlib_cli_command_t * cmd)
696 {
699 
700  return (NULL);
701 }
702 
703 /* *INDENT-OFF* */
704 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
705  .path = "clear ipsec counters",
706  .short_help = "clear ipsec counters",
708 };
709 /* *INDENT-ON* */
710 
711 static u32
713 {
714  return (0x80000000 | ti);
715 }
716 
717 static u32
719 {
720  return (0xc0000000 | ti);
721 }
722 
723 static clib_error_t *
725  unformat_input_t * input,
726  vlib_cli_command_t * cmd)
727 {
728  unformat_input_t _line_input, *line_input = &_line_input;
729  ip46_address_t local_ip = ip46_address_initializer;
730  ip46_address_t remote_ip = ip46_address_initializer;
731  ipsec_crypto_alg_t crypto_alg;
732  ipsec_integ_alg_t integ_alg;
734  u32 local_spi, remote_spi, salt, table_id, fib_index;
735  u32 instance = ~0;
736  int rv;
737  u32 num_m_args = 0;
738  u8 ipv4_set = 0;
739  u8 ipv6_set = 0;
740  u8 is_add = 1;
741  clib_error_t *error = NULL;
742  ipsec_key_t rck = { 0 };
743  ipsec_key_t lck = { 0 };
744  ipsec_key_t lik = { 0 };
745  ipsec_key_t rik = { 0 };
746 
747  table_id = 0;
748  flags = IPSEC_SA_FLAG_NONE;
749 
750  /* Get a line of input. */
751  if (!unformat_user (input, unformat_line_input, line_input))
752  return 0;
753 
754  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
755  {
756  if (unformat
757  (line_input, "local-ip %U", unformat_ip46_address, &local_ip,
758  IP46_TYPE_ANY))
759  {
760  ip46_address_is_ip4 (&local_ip) ? (ipv4_set = 1) : (ipv6_set = 1);
761  num_m_args++;
762  }
763  else
764  if (unformat
765  (line_input, "remote-ip %U", unformat_ip46_address, &remote_ip,
766  IP46_TYPE_ANY))
767  {
768  ip46_address_is_ip4 (&remote_ip) ? (ipv4_set = 1) : (ipv6_set = 1);
769  num_m_args++;
770  }
771  else if (unformat (line_input, "local-spi %u", &local_spi))
772  num_m_args++;
773  else if (unformat (line_input, "remote-spi %u", &remote_spi))
774  num_m_args++;
775  else if (unformat (line_input, "salt 0x%x", &salt))
776  ;
777  else if (unformat (line_input, "udp-encap"))
778  flags |= IPSEC_SA_FLAG_UDP_ENCAP;
779  else if (unformat (line_input, "use-esn"))
780  flags |= IPSEC_SA_FLAG_USE_ESN;
781  else if (unformat (line_input, "use-anti-replay"))
782  flags |= IPSEC_SA_FLAG_USE_ANTI_REPLAY;
783  else if (unformat (line_input, "instance %u", &instance))
784  ;
785  else if (unformat (line_input, "tx-table %u", &table_id))
786  ;
787  else
788  if (unformat
789  (line_input, "local-crypto-key %U", unformat_ipsec_key, &lck))
790  ;
791  else
792  if (unformat
793  (line_input, "remote-crypto-key %U", unformat_ipsec_key, &rck))
794  ;
795  else if (unformat (line_input, "crypto-alg %U",
796  unformat_ipsec_crypto_alg, &crypto_alg))
797  ;
798  else
799  if (unformat
800  (line_input, "local-integ-key %U", unformat_ipsec_key, &lik))
801  ;
802  else
803  if (unformat
804  (line_input, "remote-integ-key %U", unformat_ipsec_key, &rik))
805  ;
806  else if (unformat (line_input, "integ-alg %U",
807  unformat_ipsec_integ_alg, &integ_alg))
808  ;
809  else if (unformat (line_input, "del"))
810  is_add = 0;
811  else
812  {
813  error = clib_error_return (0, "unknown input `%U'",
814  format_unformat_error, line_input);
815  goto done;
816  }
817  }
818 
819  if (num_m_args < 4)
820  {
821  error = clib_error_return (0, "mandatory argument(s) missing");
822  goto done;
823  }
824 
825  if (ipv4_set && ipv6_set)
826  return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
827 
828  fib_index = fib_table_find (fib_ip_proto (ipv6_set), table_id);
829 
830  if (~0 == fib_index)
831  {
832  rv = VNET_API_ERROR_NO_SUCH_FIB;
833  goto done;
834  }
835 
836  if (is_add)
837  {
838  // remote = input, local = output
840 
841  /* create an ip-ip tunnel, then the two SA, then bind them */
842  rv =
844  instance, &local_ip, &remote_ip, fib_index,
845  IPIP_TUNNEL_FLAG_NONE, IP_DSCP_CS0, &sw_if_index);
846  rv |=
848  local_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
849  &lck, integ_alg, &lik, flags, table_id,
850  clib_host_to_net_u32 (salt), &local_ip,
851  &remote_ip, NULL);
852  rv |=
854  remote_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
855  &rck, integ_alg, &rik,
856  (flags | IPSEC_SA_FLAG_IS_INBOUND), table_id,
857  clib_host_to_net_u32 (salt), &remote_ip,
858  &local_ip, NULL);
859  rv |=
860  ipsec_tun_protect_update_one (sw_if_index,
861  ipsec_tun_mk_local_sa_id (sw_if_index),
863  (sw_if_index));
864  }
865  else
866  rv = 0;
867 
868  switch (rv)
869  {
870  case 0:
871  break;
872  case VNET_API_ERROR_INVALID_VALUE:
873  error = clib_error_return (0,
874  "IPSec tunnel interface already exists...");
875  goto done;
876  default:
877  error = clib_error_return (0, "ipsec_register_interface returned %d",
878  rv);
879  goto done;
880  }
881 
882 done:
883  unformat_free (line_input);
884 
885  return error;
886 }
887 
888 /* *INDENT-OFF* */
889 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
890  .path = "create ipsec tunnel",
891  .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> "
892  "remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap] [use-esn] [use-anti-replay] "
893  "[tx-table <table-id>]",
894  .function = create_ipsec_tunnel_command_fn,
895 };
896 /* *INDENT-ON* */
897 
898 static clib_error_t *
900  unformat_input_t * input, vlib_cli_command_t * cmd)
901 {
902  unformat_input_t _line_input, *line_input = &_line_input;
903  u32 sw_if_index, is_del, sa_in, sa_out, *sa_ins = NULL;
904  vnet_main_t *vnm;
905 
906  is_del = 0;
907  sw_if_index = ~0;
908  vnm = vnet_get_main ();
909 
910  if (!unformat_user (input, unformat_line_input, line_input))
911  return 0;
912 
913  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
914  {
915  if (unformat (line_input, "del"))
916  is_del = 1;
917  else if (unformat (line_input, "add"))
918  is_del = 0;
919  else if (unformat (line_input, "sa-in %d", &sa_in))
920  vec_add1 (sa_ins, sa_in);
921  else if (unformat (line_input, "sa-out %d", &sa_out))
922  ;
923  else if (unformat (line_input, "%U",
924  unformat_vnet_sw_interface, vnm, &sw_if_index))
925  ;
926  else
927  return (clib_error_return (0, "unknown input '%U'",
928  format_unformat_error, line_input));
929  }
930 
931  if (!is_del)
932  ipsec_tun_protect_update (sw_if_index, sa_out, sa_ins);
933 
934  unformat_free (line_input);
935  return NULL;
936 }
937 
938 /**
939  * Protect tunnel with IPSEC
940  */
941 /* *INDENT-OFF* */
942 VLIB_CLI_COMMAND (ipsec_tun_protect_cmd_node, static) =
943 {
944  .path = "ipsec tunnel protect",
945  .function = ipsec_tun_protect_cmd,
946  .short_help = "ipsec tunnel protect <interface> input-sa <SA> output-sa <SA>",
947  // this is not MP safe
948 };
949 /* *INDENT-ON* */
950 
951 
952 static clib_error_t *
954  unformat_input_t * input, vlib_cli_command_t * cmd)
955 {
957 
958  return NULL;
959 }
960 
961 /**
962  * show IPSEC tunnel protection
963  */
964 /* *INDENT-OFF* */
965 VLIB_CLI_COMMAND (ipsec_tun_protect_show_node, static) =
966 {
967  .path = "show ipsec protect",
968  .function = ipsec_tun_protect_show,
969  .short_help = "show ipsec protect",
970 };
971 /* *INDENT-ON* */
972 
973 static clib_error_t *
975  unformat_input_t * input,
976  vlib_cli_command_t * cmd)
977 {
978  ipsec_main_t *im = &ipsec_main;
979 
980  {
982  ipsec4_tunnel_key_t key;
983 
984  vlib_cli_output (vm, "IPv4:");
985 
986  /* *INDENT-OFF* */
987  hash_foreach(key.as_u64, value.as_u64, im->tun4_protect_by_key,
988  ({
989  vlib_cli_output (vm, " %U", format_ipsec4_tunnel_key, &key);
990  vlib_cli_output (vm, " tun:%d sa:%d", value.tun_index, value.sa_index);
991  }));
992  /* *INDENT-ON* */
993  }
994 
995  {
997  ipsec6_tunnel_key_t *key;
998 
999  vlib_cli_output (vm, "IPv6:");
1000 
1001  /* *INDENT-OFF* */
1003  ({
1004  vlib_cli_output (vm, " %U", format_ipsec6_tunnel_key, key);
1005  vlib_cli_output (vm, " tun:%d sa:%d", value.tun_index, value.sa_index);
1006  }));
1007  /* *INDENT-ON* */
1008  }
1009 
1010  return NULL;
1011 }
1012 
1013 /**
1014  * show IPSEC tunnel protection hash tables
1015  */
1016 /* *INDENT-OFF* */
1017 VLIB_CLI_COMMAND (ipsec_tun_protect_hash_show_node, static) =
1018 {
1019  .path = "show ipsec protect-hash",
1020  .function = ipsec_tun_protect_hash_show,
1021  .short_help = "show ipsec protect-hash",
1022 };
1023 /* *INDENT-ON* */
1024 
1025 clib_error_t *
1027 {
1028  return 0;
1029 }
1030 
1032 
1033 
1034 /*
1035  * fd.io coding-style-patch-verification: ON
1036  *
1037  * Local Variables:
1038  * eval: (c-set-style "gnu")
1039  * End:
1040  */
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:624
u32 spi
ipsec_spd_t * spds
Definition: ipsec.h:100
u8 proto
Definition: acl_types.api:47
uword * tun6_protect_by_key
Definition: ipsec.h:121
static u32 ipsec_tun_mk_local_sa_id(u32 ti)
Definition: ipsec_cli.c:712
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
ipsec_integ_alg_t
Definition: ipsec_sa.h:58
int ipip_add_tunnel(ipip_transport_t transport, u32 instance, ip46_address_t *src, ip46_address_t *dst, u32 fib_index, ipip_tunnel_flags_t flags, ip_dscp_t dscp, u32 *sw_if_indexp)
Definition: ipip.c:414
ip46_address_range_t laddr
#define NULL
Definition: clib.h:58
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:503
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)
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:724
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:523
ipsec_protocol_t
Definition: ipsec_sa.h:66
void ipsec_sa_clear(index_t sai)
Definition: ipsec_sa.c:372
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:225
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:44
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:511
static void ipsec_tunnel_show_all(vlib_main_t *vm)
Definition: ipsec_cli.c:400
unsigned char u8
Definition: types.h:56
u8 id[64]
Definition: dhcp.api:160
uword * spd_index_by_sw_if_index
Definition: ipsec.h:114
enum walk_rc_t_ walk_rc_t
Walk return code.
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:498
unformat_function_t unformat_ip4_address
Definition: format.h:68
vl_api_interface_index_t sw_if_index
Definition: gre.api:59
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
ipsec_main_t ipsec_main
Definition: ipsec.c:28
u8 * format_ipsec_tun_protect(u8 *s, va_list *args)
Definition: ipsec_format.c:340
int ipsec_select_esp_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:248
#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:356
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:245
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:953
unformat_function_t unformat_line_input
Definition: format.h:283
u32 sa_out
Definition: ipsec.api:243
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
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:228
long ctx[MAX_CONNS]
Definition: main.c:144
vnet_main_t * vnet_main
Definition: ipsec.h:110
struct _unformat_input_t unformat_input_t
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
clib_error_t * ipsec_rsc_in_use(ipsec_main_t *im)
Definition: ipsec.c:213
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:557
ipsec_spd_policy_type_t type
#define hash_foreach_mem(key_var, value_var, h, body)
Definition: hash.h:461
vlib_main_t * vm
Definition: in2out_ed.c:1810
static void ipsec_spd_bindings_show_all(vlib_main_t *vm, ipsec_main_t *im)
Definition: ipsec_cli.c:374
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:693
unformat_function_t unformat_ip6_address
Definition: format.h:89
#define UNFORMAT_END_OF_INPUT
Definition: format.h:145
u32 flags
Definition: vhost_user.h:141
static void ipsec_sa_show_all(vlib_main_t *vm, ipsec_main_t *im, u8 detail)
Definition: ipsec_cli.c:349
int ipsec_tun_protect_update(u32 sw_if_index, u32 sa_out, u32 *sas_in)
Definition: ipsec_tun.c:362
ipsec_ah_backend_t * ah_backends
Definition: ipsec.h:158
clib_error_t * ipsec_cli_init(vlib_main_t *vm)
Definition: ipsec_cli.c:1026
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:342
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:455
ipsec_policy_action_t policy
ip46_address_t start
enum ipsec_sad_flags_t_ ipsec_sa_flags_t
u8 is_outbound
Definition: ipsec.api:93
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:284
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:362
vlib_combined_counter_main_t ipsec_sa_counters
SA packet & bytes counters.
Definition: ipsec_sa.c:27
u8 value
Definition: qos.api:54
ipsec_sa_t * sad
Definition: ipsec.h:102
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:428
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:899
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:83
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)
Definition: ipsec_sa.c:127
ip46_address_range_t raddr
u32 instance
Definition: gre.api:57
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:718
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:539
int ipsec_tun_protect_update_one(u32 sw_if_index, u32 sa_out, u32 sa_in)
Definition: ipsec_tun.c:256
static void unformat_free(unformat_input_t *i)
Definition: format.h:163
ipsec_crypto_alg_t
Definition: ipsec_sa.h:36
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:974
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:406
static walk_rc_t ipsec_tun_protect_show_one(index_t itpi, void *ctx)
Definition: ipsec_cli.c:392
#define pool_foreach_index(i, v, body)
Iterate pool by index.
Definition: pool.h:543
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:175
u32 table_id
Definition: fib_types.api:118
uword unformat_ipsec_key(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:242
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:689
#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:120