IPSEC; dpdk backend for tunnel interface encryption
Change-Id: Ide2a9df18db371c8428855d7f12f246006d7c04c
Signed-off-by: Neale Ranns <nranns@cisco.com>
diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h
index b474e19..c4cb3c9 100644
--- a/src/vnet/api_errno.h
+++ b/src/vnet/api_errno.h
@@ -147,7 +147,8 @@
_(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 c530a44..da1a3fe 100644
--- a/src/vnet/ipsec/ipsec.c
+++ b/src/vnet/ipsec/ipsec.c
@@ -100,6 +100,16 @@
*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 @@
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_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 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));
- return (WALK_CONTINUE);
+ 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 @@
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 @@
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 @@
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 232390c..45576b3 100644
--- a/src/vnet/ipsec/ipsec.h
+++ b/src/vnet/ipsec/ipsec.h
@@ -62,6 +62,8 @@
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
@@ -134,6 +136,10 @@
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 */
@@ -214,8 +220,10 @@
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);
@@ -223,6 +231,8 @@
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 4a15beb..5683b6c 100644
--- a/src/vnet/ipsec/ipsec_api.c
+++ b/src/vnet/ipsec/ipsec_api.c
@@ -909,23 +909,13 @@
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 16d9048..4691214 100644
--- a/src/vnet/ipsec/ipsec_cli.c
+++ b/src/vnet/ipsec/ipsec_cli.c
@@ -661,17 +661,16 @@
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
- u32 backend_index;
- ipsec_main_t *im = &ipsec_main;
-
- 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));
- }
-
unformat_input_t _line_input, *line_input = &_line_input;
+ ipsec_main_t *im = &ipsec_main;
+ clib_error_t *error;
+ u32 backend_index;
+
+ error = ipsec_rsc_in_use (im);
+
+ if (error)
+ return error;
+
/* 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 9f64634..8e2b4b5 100644
--- a/src/vnet/ipsec/ipsec_if.c
+++ b/src/vnet/ipsec/ipsec_if.c
@@ -231,18 +231,25 @@
}
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 @@
~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 @@
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)
@@ -663,9 +670,9 @@
* 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 */
@@ -682,7 +689,6 @@
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 2d2e90a..324e7a4 100644
--- a/src/vnet/ipsec/ipsec_sa.c
+++ b/src/vnet/ipsec/ipsec_sa.c
@@ -66,7 +66,7 @@
/**
* '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 4085076..bde0958 100644
--- a/src/vnet/ipsec/ipsec_sa.h
+++ b/src/vnet/ipsec/ipsec_sa.h
@@ -207,7 +207,6 @@
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,