aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2019-04-23 20:57:55 -0400
committerNeale Ranns <nranns@cisco.com>2019-04-24 18:35:02 -0400
commit873b9ed405f291a954a8f45a0bba6b136d6ff19f (patch)
tree4c812bfdca2aeea94998ea8e0bdb726e37e74c49
parent3d18a191aaf31ef8b1524ab80fed22a304adf75d (diff)
IPSEC; dpdk backend for tunnel interface encryption (VPP-1662)v19.04.1-rc0
Change-Id: Ide2a9df18db371c8428855d7f12f246006d7c04c Signed-off-by: Neale Ranns <nranns@cisco.com>
-rw-r--r--src/plugins/dpdk/ipsec/esp_encrypt.c77
-rw-r--r--src/plugins/dpdk/ipsec/ipsec.c2
-rw-r--r--src/vnet/api_errno.h3
-rw-r--r--src/vnet/ipsec/ipsec.c66
-rw-r--r--src/vnet/ipsec/ipsec.h10
-rw-r--r--src/vnet/ipsec/ipsec_api.c16
-rw-r--r--src/vnet/ipsec/ipsec_cli.c15
-rw-r--r--src/vnet/ipsec/ipsec_if.c38
-rw-r--r--src/vnet/ipsec/ipsec_sa.c2
-rw-r--r--src/vnet/ipsec/ipsec_sa.h1
10 files changed, 169 insertions, 61 deletions
diff --git a/src/plugins/dpdk/ipsec/esp_encrypt.c b/src/plugins/dpdk/ipsec/esp_encrypt.c
index 908f846e315..6c3258602dd 100644
--- a/src/plugins/dpdk/ipsec/esp_encrypt.c
+++ b/src/plugins/dpdk/ipsec/esp_encrypt.c
@@ -110,7 +110,7 @@ format_esp_encrypt_trace (u8 * s, va_list * args)
always_inline uword
dpdk_esp_encrypt_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
- vlib_frame_t * from_frame, int is_ip6)
+ vlib_frame_t * from_frame, int is_ip6, int is_tun)
{
u32 n_left_from, *from, *to_next, next_index, thread_index;
ipsec_main_t *im = &ipsec_main;
@@ -200,7 +200,16 @@ dpdk_esp_encrypt_inline (vlib_main_t * vm,
sizeof (op[0]) + sizeof (op[0].sym[0]) + sizeof (priv[0]);
CLIB_PREFETCH (op, op_len, STORE);
- sa_index0 = vnet_buffer (b0)->ipsec.sad_index;
+ if (is_tun)
+ {
+ u32 tmp;
+ /* we are on a ipsec tunnel's feature arc */
+ sa_index0 = *(u32 *) vnet_feature_next_with_data (&tmp, b0,
+ sizeof
+ (sa_index0));
+ }
+ else
+ sa_index0 = vnet_buffer (b0)->ipsec.sad_index;
if (sa_index0 != last_sa_index)
{
@@ -576,7 +585,7 @@ VLIB_NODE_FN (dpdk_esp4_encrypt_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
{
- return dpdk_esp_encrypt_inline (vm, node, from_frame, 0 /*is_ip6 */ );
+ return dpdk_esp_encrypt_inline (vm, node, from_frame, 0 /*is_ip6 */ , 0);
}
/* *INDENT-OFF* */
@@ -599,7 +608,7 @@ VLIB_NODE_FN (dpdk_esp6_encrypt_node) (vlib_main_t * vm,
vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
{
- return dpdk_esp_encrypt_inline (vm, node, from_frame, 1 /*is_ip6 */ );
+ return dpdk_esp_encrypt_inline (vm, node, from_frame, 1 /*is_ip6 */ , 0);
}
/* *INDENT-OFF* */
@@ -618,6 +627,66 @@ VLIB_REGISTER_NODE (dpdk_esp6_encrypt_node) = {
};
/* *INDENT-ON* */
+VLIB_NODE_FN (dpdk_esp4_encrypt_tun_node) (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ return dpdk_esp_encrypt_inline (vm, node, from_frame, 0 /*is_ip6 */ , 1);
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (dpdk_esp4_encrypt_tun_node) = {
+ .name = "dpdk-esp4-encrypt-tun",
+ .flags = VLIB_NODE_FLAG_IS_OUTPUT,
+ .vector_size = sizeof (u32),
+ .format_trace = format_esp_encrypt_trace,
+ .n_errors = ARRAY_LEN (esp_encrypt_error_strings),
+ .error_strings = esp_encrypt_error_strings,
+ .n_next_nodes = 1,
+ .next_nodes =
+ {
+ [ESP_ENCRYPT_NEXT_DROP] = "error-drop",
+ }
+};
+
+VNET_FEATURE_INIT (dpdk_esp4_encrypt_tun_feat_node, static) =
+{
+ .arc_name = "ip4-output",
+ .node_name = "dpdk-esp4-encrypt-tun",
+ .runs_before = VNET_FEATURES ("adj-midchain-tx"),
+};
+/* *INDENT-ON* */
+
+VLIB_NODE_FN (dpdk_esp6_encrypt_tun_node) (vlib_main_t * vm,
+ vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ return dpdk_esp_encrypt_inline (vm, node, from_frame, 1 /*is_ip6 */ , 1);
+}
+
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (dpdk_esp6_encrypt_tun_node) = {
+ .name = "dpdk-esp6-encrypt-tun",
+ .flags = VLIB_NODE_FLAG_IS_OUTPUT,
+ .vector_size = sizeof (u32),
+ .format_trace = format_esp_encrypt_trace,
+ .n_errors = ARRAY_LEN (esp_encrypt_error_strings),
+ .error_strings = esp_encrypt_error_strings,
+ .n_next_nodes = 1,
+ .next_nodes =
+ {
+ [ESP_ENCRYPT_NEXT_DROP] = "error-drop",
+ }
+};
+
+VNET_FEATURE_INIT (dpdk_esp6_encrypt_tun_feat_node, static) =
+{
+ .arc_name = "ip6-output",
+ .node_name = "dpdk-esp6-encrypt-tun",
+ .runs_before = VNET_FEATURES ("adj-midchain-tx"),
+};
+/* *INDENT-ON* */
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/plugins/dpdk/ipsec/ipsec.c b/src/plugins/dpdk/ipsec/ipsec.c
index 682bcaf21c8..88fd75dcf1a 100644
--- a/src/plugins/dpdk/ipsec/ipsec.c
+++ b/src/plugins/dpdk/ipsec/ipsec.c
@@ -1069,8 +1069,10 @@ dpdk_ipsec_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
u32 idx = ipsec_register_esp_backend (vm, im, "dpdk backend",
"dpdk-esp4-encrypt",
+ "dpdk-esp4-encrypt-tun",
"dpdk-esp4-decrypt",
"dpdk-esp6-encrypt",
+ "dpdk-esp6-encrypt-tun",
"dpdk-esp6-decrypt",
dpdk_ipsec_check_support,
add_del_sa_session);
diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h
index b474e194636..c4cb3c9dda7 100644
--- a/src/vnet/api_errno.h
+++ b/src/vnet/api_errno.h
@@ -147,7 +147,8 @@ _(INVALID_VALUE_3, -150, "Invalid value #3") \
_(NON_ETHERNET, -151, "Interface is not an Ethernet interface") \
_(BD_ALREADY_HAS_BVI, -152, "Bridge domain already has a BVI interface") \
_(INVALID_PROTOCOL, -153, "Invalid Protocol") \
-_(INVALID_ALGORITHM, -154, "Invalid Algorithm")
+_(INVALID_ALGORITHM, -154, "Invalid Algorithm") \
+_(RSRC_IN_USE, -155, "Resource In Use")
typedef enum
{
diff --git a/src/vnet/ipsec/ipsec.c b/src/vnet/ipsec/ipsec.c
index 73c5cf4d7ab..b9392af2bd6 100644
--- a/src/vnet/ipsec/ipsec.c
+++ b/src/vnet/ipsec/ipsec.c
@@ -100,6 +100,16 @@ ipsec_add_node (vlib_main_t * vm, const char *node_name,
*out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
}
+static void
+ipsec_add_feature (const char *arc_name,
+ const char *node_name, u32 * out_feature_index)
+{
+ u8 arc;
+
+ arc = vnet_get_feature_arc_index (arc_name);
+ *out_feature_index = vnet_get_feature_index (arc, node_name);
+}
+
u32
ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
const char *name,
@@ -132,13 +142,16 @@ u32
ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
const char *name,
const char *esp4_encrypt_node_name,
+ const char *esp4_encrypt_node_tun_name,
const char *esp4_decrypt_node_name,
const char *esp6_encrypt_node_name,
+ const char *esp6_encrypt_node_tun_name,
const char *esp6_decrypt_node_name,
check_support_cb_t esp_check_support_cb,
add_del_sa_sess_cb_t esp_add_del_sa_sess_cb)
{
ipsec_esp_backend_t *b;
+
pool_get (im->esp_backends, b);
b->name = format (0, "%s%c", name, 0);
@@ -151,27 +164,42 @@ ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input-feature",
&b->esp6_decrypt_node_index, &b->esp6_decrypt_next_index);
+ ipsec_add_feature ("ip4-output", esp4_encrypt_node_tun_name,
+ &b->esp4_encrypt_tun_feature_index);
+ ipsec_add_feature ("ip6-output", esp6_encrypt_node_tun_name,
+ &b->esp6_encrypt_tun_feature_index);
+
b->check_support_cb = esp_check_support_cb;
b->add_del_sa_sess_cb = esp_add_del_sa_sess_cb;
return b - im->esp_backends;
}
-static walk_rc_t
-ipsec_sa_restack (ipsec_sa_t * sa, void *ctx)
+clib_error_t *
+ipsec_rsc_in_use (ipsec_main_t * im)
{
- ipsec_sa_stack (sa);
-
- return (WALK_CONTINUE);
+ /* return an error is crypto resource are in use */
+ if (pool_elts (im->sad) > 0)
+ return clib_error_return (0,
+ "%d SA entries configured",
+ pool_elts (im->sad));
+
+ if (pool_elts (im->tunnel_interfaces))
+ return clib_error_return (0,
+ "%d tunnel-interface entries configured",
+ pool_elts (im->tunnel_interfaces));
+
+ return (NULL);
}
int
ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
{
- if (pool_elts (im->sad) > 0
- || pool_is_free_index (im->ah_backends, backend_idx))
- {
- return -1;
- }
+ if (ipsec_rsc_in_use (im))
+ return VNET_API_ERROR_RSRC_IN_USE;
+
+ if (pool_is_free_index (im->ah_backends, backend_idx))
+ return VNET_API_ERROR_INVALID_VALUE;
+
ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
im->ah_current_backend = backend_idx;
im->ah4_encrypt_node_index = b->ah4_encrypt_node_index;
@@ -183,18 +211,18 @@ ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
im->ah6_encrypt_next_index = b->ah6_encrypt_next_index;
im->ah6_decrypt_next_index = b->ah6_decrypt_next_index;
- ipsec_sa_walk (ipsec_sa_restack, NULL);
return 0;
}
int
ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
{
- if (pool_elts (im->sad) > 0
- || pool_is_free_index (im->esp_backends, backend_idx))
- {
- return -1;
- }
+ if (ipsec_rsc_in_use (im))
+ return VNET_API_ERROR_RSRC_IN_USE;
+
+ if (pool_is_free_index (im->esp_backends, backend_idx))
+ return VNET_API_ERROR_INVALID_VALUE;
+
ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
im->esp_current_backend = backend_idx;
im->esp4_encrypt_node_index = b->esp4_encrypt_node_index;
@@ -206,7 +234,9 @@ ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
im->esp6_encrypt_next_index = b->esp6_encrypt_next_index;
im->esp6_decrypt_next_index = b->esp6_decrypt_next_index;
- ipsec_sa_walk (ipsec_sa_restack, NULL);
+ im->esp4_encrypt_tun_feature_index = b->esp4_encrypt_tun_feature_index;
+ im->esp6_encrypt_tun_feature_index = b->esp6_encrypt_tun_feature_index;
+
return 0;
}
@@ -243,8 +273,10 @@ ipsec_init (vlib_main_t * vm)
idx = ipsec_register_esp_backend (vm, im, "default openssl backend",
"esp4-encrypt",
+ "esp4-encrypt-tun",
"esp4-decrypt",
"esp6-encrypt",
+ "esp6-encrypt-tun",
"esp6-decrypt",
ipsec_check_esp_support, NULL);
im->esp_default_backend = idx;
diff --git a/src/vnet/ipsec/ipsec.h b/src/vnet/ipsec/ipsec.h
index 110bbcb3e5a..ea4b4a58ead 100644
--- a/src/vnet/ipsec/ipsec.h
+++ b/src/vnet/ipsec/ipsec.h
@@ -62,6 +62,8 @@ typedef struct
u32 esp6_decrypt_node_index;
u32 esp6_encrypt_next_index;
u32 esp6_decrypt_next_index;
+ u32 esp4_encrypt_tun_feature_index;
+ u32 esp6_encrypt_tun_feature_index;
} ipsec_esp_backend_t;
typedef struct
@@ -132,6 +134,10 @@ typedef struct
u32 ah6_encrypt_next_index;
u32 ah6_decrypt_next_index;
+ /* tun encrypt arcs and feature nodes */
+ u32 esp4_encrypt_tun_feature_index;
+ u32 esp6_encrypt_tun_feature_index;
+
/* pool of ah backends */
ipsec_ah_backend_t *ah_backends;
/* pool of esp backends */
@@ -212,8 +218,10 @@ u32 ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
u32 ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
const char *name,
const char *esp4_encrypt_node_name,
+ const char *esp4_encrypt_tun_node_name,
const char *esp4_decrypt_node_name,
const char *esp6_encrypt_node_name,
+ const char *esp6_encrypt_tun_node_name,
const char *esp6_decrypt_node_name,
check_support_cb_t esp_check_support_cb,
add_del_sa_sess_cb_t esp_add_del_sa_sess_cb);
@@ -221,6 +229,8 @@ u32 ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
int ipsec_select_ah_backend (ipsec_main_t * im, u32 ah_backend_idx);
int ipsec_select_esp_backend (ipsec_main_t * im, u32 esp_backend_idx);
+clib_error_t *ipsec_rsc_in_use (ipsec_main_t * im);
+
always_inline ipsec_sa_t *
ipsec_sa_get (u32 sa_index)
{
diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c
index 767cd2fb076..4311a30f859 100644
--- a/src/vnet/ipsec/ipsec_api.c
+++ b/src/vnet/ipsec/ipsec_api.c
@@ -909,23 +909,13 @@ vl_api_ipsec_select_backend_t_handler (vl_api_ipsec_select_backend_t * mp)
switch (protocol)
{
case IPSEC_PROTOCOL_ESP:
- if (pool_is_free_index (im->esp_backends, mp->index))
- {
- rv = VNET_API_ERROR_INVALID_VALUE;
- break;
- }
- ipsec_select_esp_backend (im, mp->index);
+ rv = ipsec_select_esp_backend (im, mp->index);
break;
case IPSEC_PROTOCOL_AH:
- if (pool_is_free_index (im->ah_backends, mp->index))
- {
- rv = VNET_API_ERROR_INVALID_VALUE;
- break;
- }
- ipsec_select_ah_backend (im, mp->index);
+ rv = ipsec_select_ah_backend (im, mp->index);
break;
default:
- rv = VNET_API_ERROR_INVALID_VALUE;
+ rv = VNET_API_ERROR_INVALID_PROTOCOL;
break;
}
#else
diff --git a/src/vnet/ipsec/ipsec_cli.c b/src/vnet/ipsec/ipsec_cli.c
index 096060865e9..b97fb02b66d 100644
--- a/src/vnet/ipsec/ipsec_cli.c
+++ b/src/vnet/ipsec/ipsec_cli.c
@@ -658,17 +658,16 @@ ipsec_select_backend_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- u32 backend_index;
+ unformat_input_t _line_input, *line_input = &_line_input;
ipsec_main_t *im = &ipsec_main;
+ clib_error_t *error;
+ u32 backend_index;
- if (pool_elts (im->sad) > 0)
- {
- return clib_error_return (0,
- "Cannot change IPsec backend, while %u SA entries are configured",
- pool_elts (im->sad));
- }
+ error = ipsec_rsc_in_use (im);
+
+ if (error)
+ return error;
- unformat_input_t _line_input, *line_input = &_line_input;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return 0;
diff --git a/src/vnet/ipsec/ipsec_if.c b/src/vnet/ipsec/ipsec_if.c
index 8d0eef21ae0..46902055aad 100644
--- a/src/vnet/ipsec/ipsec_if.c
+++ b/src/vnet/ipsec/ipsec_if.c
@@ -231,18 +231,25 @@ ipsec_tun_mk_output_sa_id (u32 ti)
}
static void
-ipsec_tunnel_feature_set (ipsec_tunnel_if_t * t, u8 enable)
+ipsec_tunnel_feature_set (ipsec_main_t * im, ipsec_tunnel_if_t * t, u8 enable)
{
- vnet_feature_enable_disable ("ip4-output",
- "esp4-encrypt-tun",
- t->sw_if_index, enable,
- &t->output_sa_index,
- sizeof (t->output_sa_index));
- vnet_feature_enable_disable ("ip6-output",
- "esp6-encrypt-tun",
- t->sw_if_index, enable,
- &t->output_sa_index,
- sizeof (t->output_sa_index));
+ u8 arc;
+
+ arc = vnet_get_feature_arc_index ("ip4-output");
+
+ vnet_feature_enable_disable_with_index (arc,
+ im->esp4_encrypt_tun_feature_index,
+ t->sw_if_index, enable,
+ &t->output_sa_index,
+ sizeof (t->output_sa_index));
+
+ arc = vnet_get_feature_arc_index ("ip6-output");
+
+ vnet_feature_enable_disable_with_index (arc,
+ im->esp6_encrypt_tun_feature_index,
+ t->sw_if_index, enable,
+ &t->output_sa_index,
+ sizeof (t->output_sa_index));
}
int
@@ -377,7 +384,7 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm,
~0);
im->ipsec_if_by_sw_if_index[t->sw_if_index] = dev_instance;
- ipsec_tunnel_feature_set (t, 1);
+ ipsec_tunnel_feature_set (im, t, 1);
/*1st interface, register protocol */
if (pool_elts (im->tunnel_interfaces) == 1)
@@ -402,7 +409,7 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm,
hi = vnet_get_hw_interface (vnm, t->hw_if_index);
vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 0); /* admin down */
- ipsec_tunnel_feature_set (t, 0);
+ ipsec_tunnel_feature_set (im, t, 0);
vnet_delete_hw_interface (vnm, t->hw_if_index);
if (is_ip6)
@@ -650,9 +657,9 @@ ipsec_set_interface_sa (vnet_main_t * vnm, u32 hw_if_index, u32 sa_id,
* re-enable the feature to get the new SA in
* the workers are stopped so no packets are sent in the clear
*/
- ipsec_tunnel_feature_set (t, 0);
+ ipsec_tunnel_feature_set (im, t, 0);
t->output_sa_index = sa_index;
- ipsec_tunnel_feature_set (t, 1);
+ ipsec_tunnel_feature_set (im, t, 1);
}
/* remove sa_id to sa_index mapping on old SA */
@@ -669,7 +676,6 @@ ipsec_set_interface_sa (vnet_main_t * vnm, u32 hw_if_index, u32 sa_id,
return 0;
}
-
clib_error_t *
ipsec_tunnel_if_init (vlib_main_t * vm)
{
diff --git a/src/vnet/ipsec/ipsec_sa.c b/src/vnet/ipsec/ipsec_sa.c
index 8f41c95159b..d696e933bf7 100644
--- a/src/vnet/ipsec/ipsec_sa.c
+++ b/src/vnet/ipsec/ipsec_sa.c
@@ -66,7 +66,7 @@ ipsec_mk_key (ipsec_key_t * key, const u8 * data, u8 len)
/**
* 'stack' (resolve the recursion for) the SA tunnel destination
*/
-void
+static void
ipsec_sa_stack (ipsec_sa_t * sa)
{
ipsec_main_t *im = &ipsec_main;
diff --git a/src/vnet/ipsec/ipsec_sa.h b/src/vnet/ipsec/ipsec_sa.h
index f87e12e0204..f25a760592e 100644
--- a/src/vnet/ipsec/ipsec_sa.h
+++ b/src/vnet/ipsec/ipsec_sa.h
@@ -203,7 +203,6 @@ extern int ipsec_sa_add (u32 id,
const ip46_address_t * tunnel_dst_addr,
u32 * sa_index);
extern u32 ipsec_sa_del (u32 id);
-extern void ipsec_sa_stack (ipsec_sa_t * sa);
extern void ipsec_sa_set_crypto_alg (ipsec_sa_t * sa,
ipsec_crypto_alg_t crypto_alg);
extern void ipsec_sa_set_integ_alg (ipsec_sa_t * sa,