2 * decap.c : IPSec tunnel support
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:
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
24 #include <vnet/ipsec/ipsec.h>
27 set_interface_spd_command_fn (vlib_main_t * vm,
28 unformat_input_t * input,
29 vlib_cli_command_t * cmd)
31 unformat_input_t _line_input, *line_input = &_line_input;
32 ipsec_main_t *im = &ipsec_main;
33 u32 sw_if_index = (u32) ~ 0;
36 clib_error_t *error = NULL;
38 if (!unformat_user (input, unformat_line_input, line_input))
42 (line_input, "%U %u", unformat_vnet_sw_interface, im->vnet_main,
43 &sw_if_index, &spd_id))
45 else if (unformat (line_input, "del"))
49 error = clib_error_return (0, "parse error: '%U'",
50 format_unformat_error, line_input);
54 ipsec_set_interface_spd (vm, sw_if_index, spd_id, is_add);
57 unformat_free (line_input);
63 VLIB_CLI_COMMAND (set_interface_spd_command, static) = {
64 .path = "set interface ipsec spd",
66 "set interface ipsec spd <int> <id>",
67 .function = set_interface_spd_command_fn,
72 ipsec_sa_add_del_command_fn (vlib_main_t * vm,
73 unformat_input_t * input,
74 vlib_cli_command_t * cmd)
76 ipsec_main_t *im = &ipsec_main;
77 unformat_input_t _line_input, *line_input = &_line_input;
81 clib_error_t *error = NULL;
83 clib_memset (&sa, 0, sizeof (sa));
84 sa.tx_fib_index = ~((u32) 0); /* Only supported for ipsec interfaces */
86 if (!unformat_user (input, unformat_line_input, line_input))
89 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
91 if (unformat (line_input, "add %u", &sa.id))
93 else if (unformat (line_input, "del %u", &sa.id))
95 else if (unformat (line_input, "spi %u", &sa.spi))
97 else if (unformat (line_input, "esp"))
98 sa.protocol = IPSEC_PROTOCOL_ESP;
99 else if (unformat (line_input, "ah"))
101 sa.protocol = IPSEC_PROTOCOL_AH;
104 if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
105 sa.crypto_key_len = vec_len (ck);
108 (line_input, "crypto-alg %U", unformat_ipsec_crypto_alg,
111 if (sa.crypto_alg < IPSEC_CRYPTO_ALG_NONE ||
112 sa.crypto_alg >= IPSEC_CRYPTO_N_ALG)
114 error = clib_error_return (0, "unsupported crypto-alg: '%U'",
115 format_ipsec_crypto_alg,
121 if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
122 sa.integ_key_len = vec_len (ik);
123 else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
126 if (sa.integ_alg < IPSEC_INTEG_ALG_NONE ||
127 sa.integ_alg >= IPSEC_INTEG_N_ALG)
129 error = clib_error_return (0, "unsupported integ-alg: '%U'",
130 format_ipsec_integ_alg,
135 else if (unformat (line_input, "tunnel-src %U",
136 unformat_ip4_address, &sa.tunnel_src_addr.ip4))
138 else if (unformat (line_input, "tunnel-dst %U",
139 unformat_ip4_address, &sa.tunnel_dst_addr.ip4))
141 else if (unformat (line_input, "tunnel-src %U",
142 unformat_ip6_address, &sa.tunnel_src_addr.ip6))
145 sa.is_tunnel_ip6 = 1;
147 else if (unformat (line_input, "tunnel-dst %U",
148 unformat_ip6_address, &sa.tunnel_dst_addr.ip6))
151 sa.is_tunnel_ip6 = 1;
153 else if (unformat (line_input, "udp-encap"))
159 error = clib_error_return (0, "parse error: '%U'",
160 format_unformat_error, line_input);
165 if (sa.crypto_key_len > sizeof (sa.crypto_key))
166 sa.crypto_key_len = sizeof (sa.crypto_key);
168 if (sa.integ_key_len > sizeof (sa.integ_key))
169 sa.integ_key_len = sizeof (sa.integ_key);
172 memcpy (sa.crypto_key, ck, sa.crypto_key_len);
175 memcpy (sa.integ_key, ik, sa.integ_key_len);
179 error = ipsec_check_support_cb (im, &sa);
184 ipsec_add_del_sa (vm, &sa, is_add);
187 unformat_free (line_input);
193 VLIB_CLI_COMMAND (ipsec_sa_add_del_command, static) = {
196 "ipsec sa [add|del]",
197 .function = ipsec_sa_add_del_command_fn,
201 static clib_error_t *
202 ipsec_spd_add_del_command_fn (vlib_main_t * vm,
203 unformat_input_t * input,
204 vlib_cli_command_t * cmd)
206 unformat_input_t _line_input, *line_input = &_line_input;
209 clib_error_t *error = NULL;
211 if (!unformat_user (input, unformat_line_input, line_input))
214 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
216 if (unformat (line_input, "add"))
218 else if (unformat (line_input, "del"))
220 else if (unformat (line_input, "%u", &spd_id))
224 error = clib_error_return (0, "parse error: '%U'",
225 format_unformat_error, line_input);
232 error = clib_error_return (0, "please specify SPD ID");
236 ipsec_add_del_spd (vm, spd_id, is_add);
239 unformat_free (line_input);
245 VLIB_CLI_COMMAND (ipsec_spd_add_del_command, static) = {
248 "ipsec spd [add|del] <id>",
249 .function = ipsec_spd_add_del_command_fn,
254 static clib_error_t *
255 ipsec_policy_add_del_command_fn (vlib_main_t * vm,
256 unformat_input_t * input,
257 vlib_cli_command_t * cmd)
259 unformat_input_t _line_input, *line_input = &_line_input;
264 clib_error_t *error = NULL;
266 clib_memset (&p, 0, sizeof (p));
267 p.lport.stop = p.rport.stop = ~0;
268 p.laddr.stop.ip4.as_u32 = p.raddr.stop.ip4.as_u32 = (u32) ~ 0;
269 p.laddr.stop.ip6.as_u64[0] = p.laddr.stop.ip6.as_u64[1] = (u64) ~ 0;
270 p.raddr.stop.ip6.as_u64[0] = p.raddr.stop.ip6.as_u64[1] = (u64) ~ 0;
272 if (!unformat_user (input, unformat_line_input, line_input))
275 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
277 if (unformat (line_input, "add"))
279 else if (unformat (line_input, "del"))
281 else if (unformat (line_input, "spd %u", &p.id))
283 else if (unformat (line_input, "inbound"))
285 else if (unformat (line_input, "outbound"))
287 else if (unformat (line_input, "priority %d", &p.priority))
289 else if (unformat (line_input, "protocol %u", &tmp))
290 p.protocol = (u8) tmp;
293 (line_input, "action %U", unformat_ipsec_policy_action,
296 if (p.policy == IPSEC_POLICY_ACTION_RESOLVE)
298 error = clib_error_return (0, "unsupported action: 'resolve'");
302 else if (unformat (line_input, "sa %u", &p.sa_id))
304 else if (unformat (line_input, "local-ip-range %U - %U",
305 unformat_ip4_address, &p.laddr.start.ip4,
306 unformat_ip4_address, &p.laddr.stop.ip4))
308 else if (unformat (line_input, "remote-ip-range %U - %U",
309 unformat_ip4_address, &p.raddr.start.ip4,
310 unformat_ip4_address, &p.raddr.stop.ip4))
312 else if (unformat (line_input, "local-ip-range %U - %U",
313 unformat_ip6_address, &p.laddr.start.ip6,
314 unformat_ip6_address, &p.laddr.stop.ip6))
319 else if (unformat (line_input, "remote-ip-range %U - %U",
320 unformat_ip6_address, &p.raddr.start.ip6,
321 unformat_ip6_address, &p.raddr.stop.ip6))
326 else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
332 if (unformat (line_input, "remote-port-range %u - %u", &tmp, &tmp2))
339 error = clib_error_return (0, "parse error: '%U'",
340 format_unformat_error, line_input);
345 /* Check if SA is for IPv6/AH which is not supported. Return error if TRUE. */
349 ipsec_main_t *im = &ipsec_main;
351 p1 = hash_get (im->sa_index_by_sa_id, p.sa_id);
355 clib_error_return (0, "SA with index %u not found", p.sa_id);
358 sa = pool_elt_at_index (im->sad, p1[0]);
359 if (sa && sa->protocol == IPSEC_PROTOCOL_AH && is_add && p.is_ipv6)
361 error = clib_error_return (0, "AH not supported for IPV6: '%U'",
362 format_unformat_error, line_input);
366 ipsec_add_del_policy (vm, &p, is_add);
370 ipsec_add_del_policy (vm, &p, is_add);
374 unformat_free (line_input);
380 VLIB_CLI_COMMAND (ipsec_policy_add_del_command, static) = {
381 .path = "ipsec policy",
383 "ipsec policy [add|del] spd <id> priority <n> ",
384 .function = ipsec_policy_add_del_command_fn,
388 static clib_error_t *
389 set_ipsec_sa_key_command_fn (vlib_main_t * vm,
390 unformat_input_t * input,
391 vlib_cli_command_t * cmd)
393 unformat_input_t _line_input, *line_input = &_line_input;
396 clib_error_t *error = NULL;
398 clib_memset (&sa, 0, sizeof (sa));
400 if (!unformat_user (input, unformat_line_input, line_input))
403 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
405 if (unformat (line_input, "%u", &sa.id))
408 if (unformat (line_input, "crypto-key %U", unformat_hex_string, &ck))
409 sa.crypto_key_len = vec_len (ck);
411 if (unformat (line_input, "integ-key %U", unformat_hex_string, &ik))
412 sa.integ_key_len = vec_len (ik);
415 error = clib_error_return (0, "parse error: '%U'",
416 format_unformat_error, line_input);
421 if (sa.crypto_key_len > sizeof (sa.crypto_key))
422 sa.crypto_key_len = sizeof (sa.crypto_key);
424 if (sa.integ_key_len > sizeof (sa.integ_key))
425 sa.integ_key_len = sizeof (sa.integ_key);
428 strncpy ((char *) sa.crypto_key, (char *) ck, sa.crypto_key_len);
431 strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len);
433 ipsec_set_sa_key (vm, &sa);
436 unformat_free (line_input);
442 VLIB_CLI_COMMAND (set_ipsec_sa_key_command, static) = {
443 .path = "set ipsec sa",
445 "set ipsec sa <id> crypto-key <key> integ-key <key>",
446 .function = set_ipsec_sa_key_command_fn,
450 static clib_error_t *
451 show_ipsec_command_fn (vlib_main_t * vm,
452 unformat_input_t * input, vlib_cli_command_t * cmd)
457 ipsec_main_t *im = &ipsec_main;
459 ipsec_tunnel_if_t *t;
460 vnet_hw_interface_t *hi;
466 pool_foreach (sa, im->sad, ({
468 vlib_cli_output(vm, "sa %u spi %u mode %s protocol %s%s%s%s", sa->id, sa->spi,
469 sa->is_tunnel ? "tunnel" : "transport",
470 sa->protocol ? "esp" : "ah",
471 sa->udp_encap ? " udp-encap-enabled" : "",
472 sa->use_anti_replay ? " anti-replay" : "",
473 sa->use_esn ? " extended-sequence-number" : "");
474 if (sa->protocol == IPSEC_PROTOCOL_ESP) {
475 vlib_cli_output(vm, " crypto alg %U%s%U integrity alg %U%s%U",
476 format_ipsec_crypto_alg, sa->crypto_alg,
477 sa->crypto_alg ? " key " : "",
478 format_hex_bytes, sa->crypto_key, sa->crypto_key_len,
479 format_ipsec_integ_alg, sa->integ_alg,
480 sa->integ_alg ? " key " : "",
481 format_hex_bytes, sa->integ_key, sa->integ_key_len);
483 if (sa->is_tunnel && sa->is_tunnel_ip6) {
484 vlib_cli_output(vm, " tunnel src %U dst %U",
485 format_ip6_address, &sa->tunnel_src_addr.ip6,
486 format_ip6_address, &sa->tunnel_dst_addr.ip6);
487 } else if (sa->is_tunnel) {
488 vlib_cli_output(vm, " tunnel src %U dst %U",
489 format_ip4_address, &sa->tunnel_src_addr.ip4,
490 format_ip4_address, &sa->tunnel_dst_addr.ip4);
497 pool_foreach (spd, im->spds, ({
498 vlib_cli_output(vm, "spd %u", spd->id);
500 vlib_cli_output(vm, " outbound policies");
501 vec_foreach(i, spd->ipv4_outbound_policies)
503 p = pool_elt_at_index(spd->policies, *i);
504 vec_reset_length(protocol);
505 vec_reset_length(policy);
507 protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
509 protocol = format(protocol, "any");
511 if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
512 policy = format(policy, " sa %u", p->sa_id);
515 vlib_cli_output(vm, " priority %d action %U protocol %v%v",
516 p->priority, format_ipsec_policy_action, p->policy,
518 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
519 format_ip4_address, &p->laddr.start.ip4,
520 format_ip4_address, &p->laddr.stop.ip4,
521 p->lport.start, p->lport.stop);
522 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
523 format_ip4_address, &p->raddr.start.ip4,
524 format_ip4_address, &p->raddr.stop.ip4,
525 p->rport.start, p->rport.stop);
526 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
529 vec_foreach(i, spd->ipv6_outbound_policies)
531 p = pool_elt_at_index(spd->policies, *i);
532 vec_reset_length(protocol);
533 vec_reset_length(policy);
535 protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
537 protocol = format(protocol, "any");
539 if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
540 policy = format(policy, " sa %u", p->sa_id);
542 vlib_cli_output(vm, " priority %d action %U protocol %v%v",
543 p->priority, format_ipsec_policy_action, p->policy,
545 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
546 format_ip6_address, &p->laddr.start.ip6,
547 format_ip6_address, &p->laddr.stop.ip6,
548 p->lport.start, p->lport.stop);
549 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
550 format_ip6_address, &p->raddr.start.ip6,
551 format_ip6_address, &p->raddr.stop.ip6,
552 p->rport.start, p->rport.stop);
553 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
556 vlib_cli_output(vm, " inbound policies");
557 vec_foreach(i, spd->ipv4_inbound_protect_policy_indices)
559 p = pool_elt_at_index(spd->policies, *i);
560 vec_reset_length(protocol);
561 vec_reset_length(policy);
563 protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
565 protocol = format(protocol, "any");
567 if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
568 policy = format(policy, " sa %u", p->sa_id);
570 vlib_cli_output(vm, " priority %d action %U protocol %v%v",
571 p->priority, format_ipsec_policy_action, p->policy,
573 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
574 format_ip4_address, &p->laddr.start.ip4,
575 format_ip4_address, &p->laddr.stop.ip4,
576 p->lport.start, p->lport.stop);
577 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
578 format_ip4_address, &p->raddr.start.ip4,
579 format_ip4_address, &p->raddr.stop.ip4,
580 p->rport.start, p->rport.stop);
581 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
584 vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices)
586 p = pool_elt_at_index(spd->policies, *i);
587 vec_reset_length(protocol);
588 vec_reset_length(policy);
590 protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
592 protocol = format(protocol, "any");
594 if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
595 policy = format(policy, " sa %u", p->sa_id);
597 vlib_cli_output(vm, " priority %d action %U protocol %v%v",
598 p->priority, format_ipsec_policy_action, p->policy,
600 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
601 format_ip4_address, &p->laddr.start.ip4,
602 format_ip4_address, &p->laddr.stop.ip4,
603 p->lport.start, p->lport.stop);
604 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
605 format_ip4_address, &p->raddr.start.ip4,
606 format_ip4_address, &p->raddr.stop.ip4,
607 p->rport.start, p->rport.stop);
608 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
611 vec_foreach(i, spd->ipv6_inbound_protect_policy_indices)
613 p = pool_elt_at_index(spd->policies, *i);
614 vec_reset_length(protocol);
615 vec_reset_length(policy);
617 protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
619 protocol = format(protocol, "any");
621 if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
622 policy = format(policy, " sa %u", p->sa_id);
624 vlib_cli_output(vm, " priority %d action %U protocol %v%v",
625 p->priority, format_ipsec_policy_action, p->policy,
627 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
628 format_ip6_address, &p->laddr.start.ip6,
629 format_ip6_address, &p->laddr.stop.ip6,
630 p->lport.start, p->lport.stop);
631 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
632 format_ip6_address, &p->raddr.start.ip6,
633 format_ip6_address, &p->raddr.stop.ip6,
634 p->rport.start, p->rport.stop);
635 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
638 vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices)
640 p = pool_elt_at_index(spd->policies, *i);
641 vec_reset_length(protocol);
642 vec_reset_length(policy);
644 protocol = format(protocol, "%U", format_ip_protocol, p->protocol);
646 protocol = format(protocol, "any");
648 if (p->policy == IPSEC_POLICY_ACTION_PROTECT) {
649 policy = format(policy, " sa %u", p->sa_id);
651 vlib_cli_output(vm, " priority %d action %U protocol %v%v",
652 p->priority, format_ipsec_policy_action, p->policy,
654 vlib_cli_output(vm, " local addr range %U - %U port range %u - %u",
655 format_ip6_address, &p->laddr.start.ip6,
656 format_ip6_address, &p->laddr.stop.ip6,
657 p->lport.start, p->lport.stop);
658 vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u",
659 format_ip6_address, &p->raddr.start.ip6,
660 format_ip6_address, &p->raddr.stop.ip6,
661 p->rport.start, p->rport.stop);
662 vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets,
668 vlib_cli_output (vm, "tunnel interfaces");
670 pool_foreach (t, im->tunnel_interfaces, ({
671 if (t->hw_if_index == ~0)
673 hi = vnet_get_hw_interface (im->vnet_main, t->hw_if_index);
674 vlib_cli_output(vm, " %s seq", hi->name);
675 sa = pool_elt_at_index(im->sad, t->output_sa_index);
677 tx_table_id = fib_table_get_table_id(sa->tx_fib_index, FIB_PROTOCOL_IP4);
679 vlib_cli_output(vm, " seq %u seq-hi %u esn %u anti-replay %u udp-encap %u tx-table %u",
680 sa->seq, sa->seq_hi, sa->use_esn, sa->use_anti_replay, sa->udp_encap, tx_table_id);
681 vlib_cli_output(vm, " local-spi %u local-ip %U", sa->spi,
682 format_ip4_address, &sa->tunnel_src_addr.ip4);
683 vlib_cli_output(vm, " local-crypto %U %U",
684 format_ipsec_crypto_alg, sa->crypto_alg,
685 format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
686 vlib_cli_output(vm, " local-integrity %U %U",
687 format_ipsec_integ_alg, sa->integ_alg,
688 format_hex_bytes, sa->integ_key, sa->integ_key_len);
689 sa = pool_elt_at_index(im->sad, t->input_sa_index);
690 vlib_cli_output(vm, " last-seq %u last-seq-hi %u esn %u anti-replay %u window %U",
691 sa->last_seq, sa->last_seq_hi, sa->use_esn,
693 format_ipsec_replay_window, sa->replay_window);
694 vlib_cli_output(vm, " remote-spi %u remote-ip %U", sa->spi,
695 format_ip4_address, &sa->tunnel_src_addr.ip4);
696 vlib_cli_output(vm, " remote-crypto %U %U",
697 format_ipsec_crypto_alg, sa->crypto_alg,
698 format_hex_bytes, sa->crypto_key, sa->crypto_key_len);
699 vlib_cli_output(vm, " remote-integrity %U %U",
700 format_ipsec_integ_alg, sa->integ_alg,
701 format_hex_bytes, sa->integ_key, sa->integ_key_len);
710 VLIB_CLI_COMMAND (show_ipsec_command, static) = {
711 .path = "show ipsec",
712 .short_help = "show ipsec [backends]",
713 .function = show_ipsec_command_fn,
717 static clib_error_t *
718 ipsec_show_backends_command_fn (vlib_main_t * vm,
719 unformat_input_t * input,
720 vlib_cli_command_t * cmd)
722 ipsec_main_t *im = &ipsec_main;
725 (void) unformat (input, "verbose %u", &verbose);
727 vlib_cli_output (vm, "IPsec AH backends available:");
728 u8 *s = format (NULL, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
729 ipsec_ah_backend_t *ab;
731 pool_foreach (ab, im->ah_backends, {
732 s = format (s, "%=25s %=25u %=10s\n", ab->name, ab - im->ah_backends,
733 ab - im->ah_backends == im->ah_current_backend ? "yes" : "no");
736 n = vlib_get_node (vm, ab->ah4_encrypt_node_index);
737 s = format (s, " enc4 %s (next %d)\n", n->name, ab->ah4_encrypt_next_index);
738 n = vlib_get_node (vm, ab->ah4_decrypt_node_index);
739 s = format (s, " dec4 %s (next %d)\n", n->name, ab->ah4_decrypt_next_index);
740 n = vlib_get_node (vm, ab->ah6_encrypt_node_index);
741 s = format (s, " enc6 %s (next %d)\n", n->name, ab->ah6_encrypt_next_index);
742 n = vlib_get_node (vm, ab->ah6_decrypt_node_index);
743 s = format (s, " dec6 %s (next %d)\n", n->name, ab->ah6_decrypt_next_index);
747 vlib_cli_output (vm, "%v", s);
749 vlib_cli_output (vm, "IPsec ESP backends available:");
750 s = format (s, "%=25s %=25s %=10s\n", "Name", "Index", "Active");
751 ipsec_esp_backend_t *eb;
753 pool_foreach (eb, im->esp_backends, {
754 s = format (s, "%=25s %=25u %=10s\n", eb->name, eb - im->esp_backends,
755 eb - im->esp_backends == im->esp_current_backend ? "yes"
759 n = vlib_get_node (vm, eb->esp4_encrypt_node_index);
760 s = format (s, " enc4 %s (next %d)\n", n->name, eb->esp4_encrypt_next_index);
761 n = vlib_get_node (vm, eb->esp4_decrypt_node_index);
762 s = format (s, " dec4 %s (next %d)\n", n->name, eb->esp4_decrypt_next_index);
763 n = vlib_get_node (vm, eb->esp6_encrypt_node_index);
764 s = format (s, " enc6 %s (next %d)\n", n->name, eb->esp6_encrypt_next_index);
765 n = vlib_get_node (vm, eb->esp6_decrypt_node_index);
766 s = format (s, " dec6 %s (next %d)\n", n->name, eb->esp6_decrypt_next_index);
770 vlib_cli_output (vm, "%v", s);
777 VLIB_CLI_COMMAND (ipsec_show_backends_command, static) = {
778 .path = "show ipsec backends",
779 .short_help = "show ipsec backends",
780 .function = ipsec_show_backends_command_fn,
784 static clib_error_t *
785 ipsec_select_backend_command_fn (vlib_main_t * vm,
786 unformat_input_t * input,
787 vlib_cli_command_t * cmd)
790 ipsec_main_t *im = &ipsec_main;
792 if (pool_elts (im->sad) > 0)
794 return clib_error_return (0,
795 "Cannot change IPsec backend, while %u SA entries are configured",
796 pool_elts (im->sad));
799 unformat_input_t _line_input, *line_input = &_line_input;
800 /* Get a line of input. */
801 if (!unformat_user (input, unformat_line_input, line_input))
804 if (unformat (line_input, "ah"))
806 if (unformat (line_input, "%u", &backend_index))
808 if (ipsec_select_ah_backend (im, backend_index) < 0)
810 return clib_error_return (0, "Invalid AH backend index `%u'",
816 return clib_error_return (0, "Invalid backend index `%U'",
817 format_unformat_error, line_input);
820 else if (unformat (line_input, "esp"))
822 if (unformat (line_input, "%u", &backend_index))
824 if (ipsec_select_esp_backend (im, backend_index) < 0)
826 return clib_error_return (0, "Invalid ESP backend index `%u'",
832 return clib_error_return (0, "Invalid backend index `%U'",
833 format_unformat_error, line_input);
838 return clib_error_return (0, "Unknown input `%U'",
839 format_unformat_error, line_input);
846 VLIB_CLI_COMMAND (ipsec_select_backend_command, static) = {
847 .path = "ipsec select backend",
848 .short_help = "ipsec select backend <ah|esp> <backend index>",
849 .function = ipsec_select_backend_command_fn,
854 static clib_error_t *
855 clear_ipsec_counters_command_fn (vlib_main_t * vm,
856 unformat_input_t * input,
857 vlib_cli_command_t * cmd)
859 ipsec_main_t *im = &ipsec_main;
864 pool_foreach (spd, im->spds, ({
865 pool_foreach(p, spd->policies, ({
866 p->counter.packets = p->counter.bytes = 0;
875 VLIB_CLI_COMMAND (clear_ipsec_counters_command, static) = {
876 .path = "clear ipsec counters",
877 .short_help = "clear ipsec counters",
878 .function = clear_ipsec_counters_command_fn,
882 static clib_error_t *
883 create_ipsec_tunnel_command_fn (vlib_main_t * vm,
884 unformat_input_t * input,
885 vlib_cli_command_t * cmd)
887 unformat_input_t _line_input, *line_input = &_line_input;
888 ipsec_add_del_tunnel_args_t a;
891 clib_error_t *error = NULL;
893 clib_memset (&a, 0, sizeof (a));
896 /* Get a line of input. */
897 if (!unformat_user (input, unformat_line_input, line_input))
900 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
903 (line_input, "local-ip %U", unformat_ip4_address, &a.local_ip))
907 (line_input, "remote-ip %U", unformat_ip4_address, &a.remote_ip))
909 else if (unformat (line_input, "local-spi %u", &a.local_spi))
911 else if (unformat (line_input, "remote-spi %u", &a.remote_spi))
913 else if (unformat (line_input, "instance %u", &a.show_instance))
915 else if (unformat (line_input, "del"))
917 else if (unformat (line_input, "udp-encap"))
919 else if (unformat (line_input, "tx-table %u", &a.tx_table_id))
923 error = clib_error_return (0, "unknown input `%U'",
924 format_unformat_error, line_input);
931 error = clib_error_return (0, "mandatory argument(s) missing");
935 rv = ipsec_add_del_tunnel_if (&a);
941 case VNET_API_ERROR_INVALID_VALUE:
943 error = clib_error_return (0,
944 "IPSec tunnel interface already exists...");
946 error = clib_error_return (0, "IPSec tunnel interface not exists...");
949 error = clib_error_return (0, "ipsec_register_interface returned %d",
955 unformat_free (line_input);
961 VLIB_CLI_COMMAND (create_ipsec_tunnel_command, static) = {
962 .path = "create ipsec tunnel",
963 .short_help = "create ipsec tunnel local-ip <addr> local-spi <spi> "
964 "remote-ip <addr> remote-spi <spi> [instance <inst_num>] [udp-encap] "
965 "[tx-table <table-id>]",
966 .function = create_ipsec_tunnel_command_fn,
970 static clib_error_t *
971 set_interface_key_command_fn (vlib_main_t * vm,
972 unformat_input_t * input,
973 vlib_cli_command_t * cmd)
975 unformat_input_t _line_input, *line_input = &_line_input;
976 ipsec_main_t *im = &ipsec_main;
977 ipsec_if_set_key_type_t type = IPSEC_IF_SET_KEY_TYPE_NONE;
978 u32 hw_if_index = (u32) ~ 0;
981 clib_error_t *error = NULL;
983 if (!unformat_user (input, unformat_line_input, line_input))
986 while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
988 if (unformat (line_input, "%U",
989 unformat_vnet_hw_interface, im->vnet_main, &hw_if_index))
993 (line_input, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
994 type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
997 (line_input, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
998 type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
1001 (line_input, "local integ %U", unformat_ipsec_integ_alg, &alg))
1002 type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
1005 (line_input, "remote integ %U", unformat_ipsec_integ_alg, &alg))
1006 type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
1007 else if (unformat (line_input, "%U", unformat_hex_string, &key))
1011 error = clib_error_return (0, "parse error: '%U'",
1012 format_unformat_error, line_input);
1017 if (type == IPSEC_IF_SET_KEY_TYPE_NONE)
1019 error = clib_error_return (0, "unknown key type");
1023 if (alg > 0 && vec_len (key) == 0)
1025 error = clib_error_return (0, "key is not specified");
1029 if (hw_if_index == (u32) ~ 0)
1031 error = clib_error_return (0, "interface not specified");
1035 ipsec_set_interface_key (im->vnet_main, hw_if_index, type, alg, key);
1039 unformat_free (line_input);
1045 VLIB_CLI_COMMAND (set_interface_key_command, static) = {
1046 .path = "set interface ipsec key",
1048 "set interface ipsec key <int> <local|remote> <crypto|integ> <key type> <key>",
1049 .function = set_interface_key_command_fn,
1054 ipsec_cli_init (vlib_main_t * vm)
1059 VLIB_INIT_FUNCTION (ipsec_cli_init);
1063 * fd.io coding-style-patch-verification: ON
1066 * eval: (c-set-style "gnu")