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