From 7cd468a3d7dee7d6c92f69a0bb7061ae208ec727 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 19 Dec 2016 23:05:39 +0100 Subject: Reorganize source tree to use single autotools instance Change-Id: I7b51f88292e057c6443b12224486f2d0c9f8ae23 Signed-off-by: Damjan Marion --- src/vnet/ipsec/ipsec_input.c | 455 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 455 insertions(+) create mode 100644 src/vnet/ipsec/ipsec_input.c (limited to 'src/vnet/ipsec/ipsec_input.c') diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c new file mode 100644 index 00000000..4662c1a1 --- /dev/null +++ b/src/vnet/ipsec/ipsec_input.c @@ -0,0 +1,455 @@ +/* + * decap.c : IPSec tunnel decapsulation + * + * Copyright (c) 2015 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#if DPDK_CRYPTO==1 +#define ESP_NODE "dpdk-esp-decrypt" +#else +#define ESP_NODE "esp-decrypt" +#endif + +#define foreach_ipsec_input_next \ +_(DROP, "error-drop") \ +_(ESP_DECRYPT, ESP_NODE) + +#define _(v, s) IPSEC_INPUT_NEXT_##v, +typedef enum +{ + foreach_ipsec_input_next +#undef _ + IPSEC_INPUT_N_NEXT, +} ipsec_input_next_t; + + +#define foreach_ipsec_input_error \ + _(RX_PKTS, "IPSEC pkts received") \ + _(DECRYPTION_FAILED, "IPSEC decryption failed") + + +typedef enum +{ +#define _(sym,str) IPSEC_INPUT_ERROR_##sym, + foreach_ipsec_input_error +#undef _ + IPSEC_INPUT_N_ERROR, +} ipsec_input_error_t; + +static char *ipsec_input_error_strings[] = { +#define _(sym,string) string, + foreach_ipsec_input_error +#undef _ +}; + +typedef struct +{ + u32 sa_id; + u32 spi; + u32 seq; +} ipsec_input_trace_t; + +/* packet trace format function */ +static u8 * +format_ipsec_input_trace (u8 * s, va_list * args) +{ + CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); + CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); + ipsec_input_trace_t *t = va_arg (*args, ipsec_input_trace_t *); + + if (t->spi == 0 && t->seq == 0) + { + s = format (s, "esp: no esp packet"); + return s; + } + + if (t->sa_id != 0) + { + s = format (s, "esp: sa_id %u spi %u seq %u", t->sa_id, t->spi, t->seq); + } + else + { + s = format (s, "esp: no sa spi %u seq %u", t->spi, t->seq); + } + return s; +} + +always_inline ipsec_policy_t * +ipsec_input_protect_policy_match (ipsec_spd_t * spd, u32 sa, u32 da, u32 spi) +{ + ipsec_main_t *im = &ipsec_main; + ipsec_policy_t *p; + ipsec_sa_t *s; + u32 *i; + + vec_foreach (i, spd->ipv4_inbound_protect_policy_indices) + { + p = pool_elt_at_index (spd->policies, *i); + s = pool_elt_at_index (im->sad, p->sa_index); + + if (spi != s->spi) + continue; + + if (s->is_tunnel) + { + if (da != clib_net_to_host_u32 (s->tunnel_dst_addr.ip4.as_u32)) + continue; + + if (sa != clib_net_to_host_u32 (s->tunnel_src_addr.ip4.as_u32)) + continue; + + return p; + } + + if (da < clib_net_to_host_u32 (p->laddr.start.ip4.as_u32)) + continue; + + if (da > clib_net_to_host_u32 (p->laddr.stop.ip4.as_u32)) + continue; + + if (sa < clib_net_to_host_u32 (p->raddr.start.ip4.as_u32)) + continue; + + if (sa > clib_net_to_host_u32 (p->raddr.stop.ip4.as_u32)) + continue; + + return p; + } + return 0; +} + +always_inline uword +ip6_addr_match_range (ip6_address_t * a, ip6_address_t * la, + ip6_address_t * ua) +{ + if ((memcmp (a->as_u64, la->as_u64, 2 * sizeof (u64)) >= 0) && + (memcmp (a->as_u64, ua->as_u64, 2 * sizeof (u64)) <= 0)) + return 1; + return 0; +} + +always_inline ipsec_policy_t * +ipsec_input_ip6_protect_policy_match (ipsec_spd_t * spd, + ip6_address_t * sa, + ip6_address_t * da, u32 spi) +{ + ipsec_main_t *im = &ipsec_main; + ipsec_policy_t *p; + ipsec_sa_t *s; + u32 *i; + + vec_foreach (i, spd->ipv6_inbound_protect_policy_indices) + { + p = pool_elt_at_index (spd->policies, *i); + s = pool_elt_at_index (im->sad, p->sa_index); + + if (spi != s->spi) + continue; + + if (s->is_tunnel) + { + if (!ip6_address_is_equal (sa, &s->tunnel_src_addr.ip6)) + continue; + + if (!ip6_address_is_equal (da, &s->tunnel_dst_addr.ip6)) + continue; + + return p; + } + + if (!ip6_addr_match_range (sa, &p->raddr.start.ip6, &p->raddr.stop.ip6)) + continue; + + if (!ip6_addr_match_range (da, &p->laddr.start.ip6, &p->laddr.stop.ip6)) + continue; + + return p; + } + return 0; +} + +static vlib_node_registration_t ipsec_input_ip4_node; + +static uword +ipsec_input_ip4_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, next_index, *to_next; + ipsec_main_t *im = &ipsec_main; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0, next0; + vlib_buffer_t *b0; + ip4_header_t *ip0; + esp_header_t *esp0; + ip4_ipsec_config_t *c0; + ipsec_spd_t *spd0; + ipsec_policy_t *p0 = 0; + + bi0 = to_next[0] = from[0]; + from += 1; + n_left_from -= 1; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + c0 = + vnet_feature_next_with_data (vnet_buffer (b0)->sw_if_index + [VLIB_RX], &next0, b0, + sizeof (c0[0])); + + spd0 = pool_elt_at_index (im->spds, c0->spd_index); + + ip0 = vlib_buffer_get_current (b0); + esp0 = (esp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); + + if (PREDICT_TRUE (ip0->protocol == IP_PROTOCOL_IPSEC_ESP)) + { +#if 0 + clib_warning + ("packet received from %U to %U spi %u size %u spd_id %u", + format_ip4_address, ip0->src_address.as_u8, + format_ip4_address, ip0->dst_address.as_u8, + clib_net_to_host_u32 (esp0->spi), + clib_net_to_host_u16 (ip0->length), spd0->id); +#endif + + p0 = ipsec_input_protect_policy_match (spd0, + clib_net_to_host_u32 + (ip0->src_address. + as_u32), + clib_net_to_host_u32 + (ip0->dst_address. + as_u32), + clib_net_to_host_u32 + (esp0->spi)); + + if (PREDICT_TRUE (p0 != 0)) + { + p0->counter.packets++; + p0->counter.bytes += clib_net_to_host_u16 (ip0->length); + vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; + vnet_buffer (b0)->ipsec.flags = 0; + next0 = IPSEC_INPUT_NEXT_ESP_DECRYPT; + vlib_buffer_advance (b0, ip4_header_bytes (ip0)); + goto trace0; + } + } + + /* FIXME bypass and discard */ + + trace0: + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + ipsec_input_trace_t *tr = + vlib_add_trace (vm, node, b0, sizeof (*tr)); + if (ip0->protocol == IP_PROTOCOL_IPSEC_ESP) + { + if (p0) + tr->sa_id = p0->sa_id; + tr->spi = clib_host_to_net_u32 (esp0->spi); + tr->seq = clib_host_to_net_u32 (esp0->seq); + } + } + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, bi0, + next0); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter (vm, ipsec_input_ip4_node.index, + IPSEC_INPUT_ERROR_RX_PKTS, + from_frame->n_vectors); + + return from_frame->n_vectors; +} + + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ipsec_input_ip4_node,static) = { + .function = ipsec_input_ip4_node_fn, + .name = "ipsec-input-ip4", + .vector_size = sizeof (u32), + .format_trace = format_ipsec_input_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(ipsec_input_error_strings), + .error_strings = ipsec_input_error_strings, + + .n_next_nodes = IPSEC_INPUT_N_NEXT, + .next_nodes = { +#define _(s,n) [IPSEC_INPUT_NEXT_##s] = n, + foreach_ipsec_input_next +#undef _ + }, +}; +/* *INDENT-ON* */ + +VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, ipsec_input_ip4_node_fn) + static vlib_node_registration_t ipsec_input_ip6_node; + + static uword + ipsec_input_ip6_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, next_index, *to_next; + ipsec_main_t *im = &ipsec_main; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_left_from > 0 && n_left_to_next > 0) + { + u32 bi0, next0; + vlib_buffer_t *b0; + ip6_header_t *ip0; + esp_header_t *esp0; + ip4_ipsec_config_t *c0; + ipsec_spd_t *spd0; + ipsec_policy_t *p0 = 0; + u32 header_size = sizeof (ip0[0]); + + bi0 = to_next[0] = from[0]; + from += 1; + n_left_from -= 1; + to_next += 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + c0 = + vnet_feature_next_with_data (vnet_buffer (b0)->sw_if_index + [VLIB_RX], &next0, b0, + sizeof (c0[0])); + + spd0 = pool_elt_at_index (im->spds, c0->spd_index); + + ip0 = vlib_buffer_get_current (b0); + esp0 = (esp_header_t *) ((u8 *) ip0 + header_size); + + if (PREDICT_TRUE (ip0->protocol == IP_PROTOCOL_IPSEC_ESP)) + { +#if 0 + clib_warning + ("packet received from %U to %U spi %u size %u spd_id %u", + format_ip6_address, &ip0->src_address, format_ip6_address, + &ip0->dst_address, clib_net_to_host_u32 (esp0->spi), + clib_net_to_host_u16 (ip0->payload_length) + header_size, + spd0->id); +#endif + p0 = ipsec_input_ip6_protect_policy_match (spd0, + &ip0->src_address, + &ip0->dst_address, + clib_net_to_host_u32 + (esp0->spi)); + + if (PREDICT_TRUE (p0 != 0)) + { + p0->counter.packets++; + p0->counter.bytes += + clib_net_to_host_u16 (ip0->payload_length); + p0->counter.bytes += header_size; + vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; + vnet_buffer (b0)->ipsec.flags = 0; + next0 = IPSEC_INPUT_NEXT_ESP_DECRYPT; + vlib_buffer_advance (b0, header_size); + goto trace0; + } + } + + trace0: + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + ipsec_input_trace_t *tr = + vlib_add_trace (vm, node, b0, sizeof (*tr)); + if (ip0->protocol == IP_PROTOCOL_IPSEC_ESP) + { + if (p0) + tr->sa_id = p0->sa_id; + tr->spi = clib_host_to_net_u32 (esp0->spi); + tr->seq = clib_host_to_net_u32 (esp0->seq); + } + } + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, + n_left_to_next, bi0, next0); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter (vm, ipsec_input_ip6_node.index, + IPSEC_INPUT_ERROR_RX_PKTS, + from_frame->n_vectors); + + return from_frame->n_vectors; +} + + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (ipsec_input_ip6_node,static) = { + .function = ipsec_input_ip6_node_fn, + .name = "ipsec-input-ip6", + .vector_size = sizeof (u32), + .format_trace = format_ipsec_input_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(ipsec_input_error_strings), + .error_strings = ipsec_input_error_strings, + + .n_next_nodes = IPSEC_INPUT_N_NEXT, + .next_nodes = { +#define _(s,n) [IPSEC_INPUT_NEXT_##s] = n, + foreach_ipsec_input_next +#undef _ + }, +}; +/* *INDENT-ON* */ + +VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip6_node, ipsec_input_ip6_node_fn) +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ -- cgit 1.2.3-korg From d04b60bfa940e21ab4676a1cb3c15989748be40a Mon Sep 17 00:00:00 2001 From: Sergio Gonzalez Monroy Date: Fri, 20 Jan 2017 15:35:23 +0000 Subject: dpdk: rework cryptodev ipsec build and setup Build Cryptodev IPsec support by default when DPDK is enabled but only build hardware Cryptodev PMDs. To enable Cryptodev support, a new startup.conf option for dpdk has been introduced 'enable-cryptodev'. During VPP init, if Cryptodev support is not enabled or not enough cryptodev resources are available then default to OpenSSL ipsec implementation. Change-Id: I5aa7e0d5c2676bdb41d775ef40364536a081956d Signed-off-by: Sergio Gonzalez Monroy --- build-data/packages/dpdk.mk | 6 +- build-data/packages/vpp.mk | 4 +- build-data/platforms/vpp.mk | 2 +- dpdk/Makefile | 10 +- src/Makefile.am | 2 +- src/configure.ac | 4 +- src/vat/api_format.c | 31 --- src/vnet.am | 4 +- src/vnet/devices/dpdk/dpdk.h | 1 + src/vnet/devices/dpdk/format.c | 3 + src/vnet/devices/dpdk/init.c | 3 + src/vnet/devices/dpdk/ipsec/cli.c | 8 + src/vnet/devices/dpdk/ipsec/crypto_node.c | 25 +- .../devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md | 37 ++- src/vnet/devices/dpdk/ipsec/esp.h | 95 ++------ src/vnet/devices/dpdk/ipsec/esp_decrypt.c | 11 +- src/vnet/devices/dpdk/ipsec/esp_encrypt.c | 11 +- src/vnet/devices/dpdk/ipsec/ipsec.c | 257 +++++++++++++++------ src/vnet/devices/dpdk/ipsec/ipsec.h | 2 +- src/vnet/ipsec-gre/interface.c | 8 +- src/vnet/ipsec/ipsec.c | 51 ++-- src/vnet/ipsec/ipsec.h | 63 +++-- src/vnet/ipsec/ipsec_api.c | 43 +--- src/vnet/ipsec/ipsec_cli.c | 31 +-- src/vnet/ipsec/ipsec_if.c | 73 ++++-- src/vnet/ipsec/ipsec_if_in.c | 24 +- src/vnet/ipsec/ipsec_if_out.c | 22 +- src/vnet/ipsec/ipsec_input.c | 24 +- src/vnet/ipsec/ipsec_output.c | 20 -- 29 files changed, 452 insertions(+), 423 deletions(-) (limited to 'src/vnet/ipsec/ipsec_input.c') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index 6c136824..6938392c 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -22,9 +22,9 @@ DPDK_MAKE_ARGS = -C $(call find_source_fn,$(PACKAGE_SOURCE)) \ DPDK_TUNE=$(DPDK_TUNE) \ DPDK_DEBUG=$(DPDK_DEBUG) -DPDK_CRYPTO_PMD=$(strip $($(PLATFORM)_uses_dpdk_cryptodev)) -ifneq ($(DPDK_CRYPTO_PMD),) -DPDK_MAKE_ARGS += DPDK_CRYPTO_PMD=y +DPDK_CRYPTO_SW_PMD=$(strip $($(PLATFORM)_uses_dpdk_cryptodev_sw)) +ifneq ($(DPDK_CRYPTO_SW_PMD),) +DPDK_MAKE_ARGS += DPDK_CRYPTO_SW_PMD=y endif DPDK_MLX5_PMD=$(strip $($(PLATFORM)_uses_dpdk_mlx5_pmd)) diff --git a/build-data/packages/vpp.mk b/build-data/packages/vpp.mk index 81aeab69..64eb0d89 100644 --- a/build-data/packages/vpp.mk +++ b/build-data/packages/vpp.mk @@ -23,8 +23,8 @@ vpp_CPPFLAGS += $(call installed_includes_fn, dpdk)/dpdk vpp_LDFLAGS += $(call installed_libs_fn, dpdk) vpp_CPPFLAGS += -I/usr/include/dpdk endif -ifeq ($($(PLATFORM)_uses_dpdk_cryptodev),yes) -vpp_configure_args += --with-dpdk-crypto +ifeq ($($(PLATFORM)_uses_dpdk_cryptodev_sw),yes) +vpp_configure_args += --with-dpdk-crypto-sw endif ifeq ($($(PLATFORM)_uses_dpdk_mlx5_pmd),yes) vpp_configure_args += --with-dpdk-mlx5-pmd diff --git a/build-data/platforms/vpp.mk b/build-data/platforms/vpp.mk index dd6f9dc2..5b200587 100644 --- a/build-data/platforms/vpp.mk +++ b/build-data/platforms/vpp.mk @@ -44,7 +44,7 @@ vpp_configure_args_vpp = --with-dpdk vlib_configure_args_vpp = --with-pre-data=128 # DPDK configuration parameters -# vpp_uses_dpdk_cryptodev = yes +# vpp_uses_dpdk_cryptodev_sw = yes # vpp_uses_dpdk_mlx5_pmd = yes # vpp_uses_external_dpdk = yes # vpp_dpdk_inc_dir = /usr/include/dpdk diff --git a/dpdk/Makefile b/dpdk/Makefile index 586d2425..22e97878 100644 --- a/dpdk/Makefile +++ b/dpdk/Makefile @@ -21,13 +21,13 @@ DPDK_DOWNLOAD_DIR ?= $(HOME)/Downloads DPDK_MARCH ?= native DPDK_TUNE ?= generic DPDK_DEBUG ?= n -DPDK_CRYPTO_PMD ?= n +DPDK_CRYPTO_SW_PMD ?= n DPDK_MLX5_PMD ?= n B := $(DPDK_BUILD_DIR) I := $(DPDK_INSTALL_DIR) DPDK_VERSION ?= 16.11 -PKG_SUFFIX ?= vpp1 +PKG_SUFFIX ?= vpp2 DPDK_BASE_URL ?= http://fast.dpdk.org/rel DPDK_TARBALL := dpdk-$(DPDK_VERSION).tar.xz DPDK_TAR_URL := $(DPDK_BASE_URL)/$(DPDK_TARBALL) @@ -121,9 +121,9 @@ $(B)/custom-config: $(B)/.patch.ok Makefile $(call set,RTE_LIBRTE_VMXNET3_DEBUG_INIT,$(DPDK_DEBUG)) $(call set,RTE_LIBRTE_PMD_BOND,y) $(call set,RTE_LIBRTE_IP_FRAG,y) - $(call set,RTE_LIBRTE_PMD_AESNI_MB,$(DPDK_CRYPTO_PMD)) - $(call set,RTE_LIBRTE_PMD_AESNI_GCM,$(DPDK_CRYPTO_PMD)) - $(call set,RTE_LIBRTE_PMD_QAT,$(DPDK_CRYPTO_PMD)) + $(call set,RTE_LIBRTE_PMD_QAT,y) + $(call set,RTE_LIBRTE_PMD_AESNI_MB,$(DPDK_CRYPTO_SW_PMD)) + $(call set,RTE_LIBRTE_PMD_AESNI_GCM,$(DPDK_CRYPTO_SW_PMD)) $(call set,RTE_LIBRTE_MLX5_PMD,$(DPDK_MLX5_PMD)) @# not needed $(call set,RTE_LIBRTE_TIMER,n) diff --git a/src/Makefile.am b/src/Makefile.am index 5e248972..239afeac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,7 +47,7 @@ DPDK_LD_FLAGS = -Wl,--whole-archive,-ldpdk,--no-whole-archive else DPDK_LD_FLAGS = -Wl,--whole-archive,-l:libdpdk.a,--no-whole-archive,-lm,-ldl endif -if WITH_DPDK_CRYPTO +if WITH_DPDK_CRYPTO_SW DPDK_LD_ADD = -L$(AESNI_MULTI_BUFFER_LIB_PATH) -lIPSec_MB endif if WITH_DPDK_MLX5_PMD diff --git a/src/configure.ac b/src/configure.ac index fbedabf0..49da6248 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -98,7 +98,7 @@ DISABLE_ARG(japi, [Disable Java API bindings]) # --with-X WITH_ARG(dpdk, [Use use DPDK]) -WITH_ARG(dpdk_crypto, [Use DPDK cryptodev]) +WITH_ARG(dpdk_crypto_sw,[Use DPDK cryptodev SW PMDs]) WITH_ARG(dpdk_mlx5_pmd, [Use DPDK with mlx5 PMD]) # --without-X @@ -132,7 +132,7 @@ AC_SUBST(APICLI, [-DVPP_API_TEST_BUILTIN=${n_with_apicli}]) AC_DEFINE_UNQUOTED(DPDK, [${n_with_dpdk}]) AC_DEFINE_UNQUOTED(DPDK_SHARED_LIB, [${n_enable_dpdk_shared}]) -AC_DEFINE_UNQUOTED(DPDK_CRYPTO, [${n_with_dpdk_crypto}]) +AC_DEFINE_UNQUOTED(DPDK_CRYPTO_SW, [${n_with_dpdk_crypto_sw}]) AC_DEFINE_UNQUOTED(WITH_LIBSSL, [${n_with_libssl}]) diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 4cfe4a58..6b8c5fb9 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -12199,11 +12199,7 @@ api_ipsec_sad_add_del_entry (vat_main_t * vam) if (unformat (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) { -#if DPDK_CRYPTO==1 - if (integ_alg < IPSEC_INTEG_ALG_NONE || -#else if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 || -#endif integ_alg >= IPSEC_INTEG_N_ALG) { clib_warning ("unsupported integ-alg: '%U'", @@ -12221,33 +12217,6 @@ api_ipsec_sad_add_del_entry (vat_main_t * vam) } -#if DPDK_CRYPTO==1 - /*Special cases, aes-gcm-128 encryption */ - if (crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) - { - if (integ_alg != IPSEC_INTEG_ALG_NONE - && integ_alg != IPSEC_INTEG_ALG_AES_GCM_128) - { - clib_warning - ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg"); - return -99; - } - else /*set integ-alg internally to aes-gcm-128 */ - integ_alg = IPSEC_INTEG_ALG_AES_GCM_128; - } - else if (integ_alg == IPSEC_INTEG_ALG_AES_GCM_128) - { - clib_warning ("unsupported integ-alg: aes-gcm-128"); - return -99; - } - else if (integ_alg == IPSEC_INTEG_ALG_NONE) - { - clib_warning ("unsupported integ-alg: none"); - return -99; - } -#endif - - M (IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry); mp->sad_id = ntohl (sad_id); diff --git a/src/vnet.am b/src/vnet.am index 28a1b19a..96cfa557 100644 --- a/src/vnet.am +++ b/src/vnet.am @@ -400,7 +400,7 @@ libvnet_la_SOURCES += \ API_FILES += vnet/ipsec/ipsec.api -if WITH_DPDK_CRYPTO +if WITH_DPDK libvnet_la_SOURCES += \ vnet/devices/dpdk/ipsec/esp_encrypt.c \ vnet/devices/dpdk/ipsec/esp_decrypt.c \ @@ -419,7 +419,7 @@ nobase_include_HEADERS += \ vnet/ipsec/ikev2.h \ vnet/ipsec/ikev2_priv.h \ vnet/ipsec/ipsec.api.h -if WITH_DPDK_CRYPTO +if WITH_DPDK nobase_include_HEADERS += \ vnet/devices/dpdk/ipsec/ipsec.h \ vnet/devices/dpdk/ipsec/esp.h diff --git a/src/vnet/devices/dpdk/dpdk.h b/src/vnet/devices/dpdk/dpdk.h index a91e87df..1b54460e 100644 --- a/src/vnet/devices/dpdk/dpdk.h +++ b/src/vnet/devices/dpdk/dpdk.h @@ -338,6 +338,7 @@ typedef struct u8 *uio_driver_name; u8 no_multi_seg; u8 enable_tcp_udp_checksum; + u8 cryptodev; /* Required config parameters */ u8 coremask_set_manually; diff --git a/src/vnet/devices/dpdk/format.c b/src/vnet/devices/dpdk/format.c index ff7c7a5a..cc0d71af 100644 --- a/src/vnet/devices/dpdk/format.c +++ b/src/vnet/devices/dpdk/format.c @@ -684,6 +684,8 @@ format_dpdk_rte_mbuf (u8 * s, va_list * va) return s; } +/* FIXME is this function used? */ +#if 0 uword unformat_socket_mem (unformat_input_t * input, va_list * va) { @@ -710,6 +712,7 @@ unformat_socket_mem (unformat_input_t * input, va_list * va) done: return 1; } +#endif clib_error_t * unformat_rss_fn (unformat_input_t * input, uword * rss_fn) diff --git a/src/vnet/devices/dpdk/init.c b/src/vnet/devices/dpdk/init.c index 3fa656ea..01ef48cb 100755 --- a/src/vnet/devices/dpdk/init.c +++ b/src/vnet/devices/dpdk/init.c @@ -1054,6 +1054,9 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input) else if (unformat (input, "no-multi-seg")) conf->no_multi_seg = 1; + else if (unformat (input, "enable-cryptodev")) + conf->cryptodev = 1; + else if (unformat (input, "dev default %U", unformat_vlib_cli_sub_input, &sub_input)) { diff --git a/src/vnet/devices/dpdk/ipsec/cli.c b/src/vnet/devices/dpdk/ipsec/cli.c index 3b634e03..93df4a64 100644 --- a/src/vnet/devices/dpdk/ipsec/cli.c +++ b/src/vnet/devices/dpdk/ipsec/cli.c @@ -14,15 +14,23 @@ */ #include +#include #include static void dpdk_ipsec_show_mapping (vlib_main_t * vm, u16 detail_display) { + dpdk_config_main_t *conf = &dpdk_config_main; dpdk_crypto_main_t *dcm = &dpdk_crypto_main; vlib_thread_main_t *tm = vlib_get_thread_main (); u32 i, skip_master; + if (!conf->cryptodev) + { + vlib_cli_output (vm, "DPDK Cryptodev support is disabled\n"); + return; + } + if (detail_display) vlib_cli_output (vm, "worker\t%10s\t%15s\tdir\tdev\tqp\n", "cipher", "auth"); diff --git a/src/vnet/devices/dpdk/ipsec/crypto_node.c b/src/vnet/devices/dpdk/ipsec/crypto_node.c index 7b32704e..e8fef235 100644 --- a/src/vnet/devices/dpdk/ipsec/crypto_node.c +++ b/src/vnet/devices/dpdk/ipsec/crypto_node.c @@ -22,6 +22,8 @@ #include #include +#include +#include #include #define foreach_dpdk_crypto_input_next \ @@ -183,24 +185,27 @@ dpdk_crypto_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, return n_deq; } +/* *INDENT-OFF* */ VLIB_REGISTER_NODE (dpdk_crypto_input_node) = { - .function = dpdk_crypto_input_fn,.name = "dpdk-crypto-input",.format_trace = - format_dpdk_crypto_input_trace,.type = VLIB_NODE_TYPE_INPUT,.state = - VLIB_NODE_STATE_DISABLED,.n_errors = - DPDK_CRYPTO_INPUT_N_ERROR,.error_strings = - dpdk_crypto_input_error_strings,.n_next_nodes = - DPDK_CRYPTO_INPUT_N_NEXT,.next_nodes = + .function = dpdk_crypto_input_fn, + .name = "dpdk-crypto-input", + .format_trace = format_dpdk_crypto_input_trace, + .type = VLIB_NODE_TYPE_INPUT, + .state = VLIB_NODE_STATE_DISABLED, + .n_errors = DPDK_CRYPTO_INPUT_N_ERROR, + .error_strings = dpdk_crypto_input_error_strings, + .n_next_nodes = DPDK_CRYPTO_INPUT_N_NEXT, + .next_nodes = { #define _(s,n) [DPDK_CRYPTO_INPUT_NEXT_##s] = n, foreach_dpdk_crypto_input_next #undef _ - } -,}; + }, +}; +/* *INDENT-ON* */ -#if DPDK_CRYPTO==1 VLIB_NODE_FUNCTION_MULTIARCH (dpdk_crypto_input_node, dpdk_crypto_input_fn) -#endif /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md b/src/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md index 8089696f..fed2fe0e 100644 --- a/src/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md +++ b/src/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md @@ -7,43 +7,55 @@ This document is meant to contain all related information about implementation a DPDK Cryptodev is an asynchronous crypto API that supports both Hardware and Software implementations (for more details refer to [DPDK Cryptography Device Library documentation](http://dpdk.org/doc/guides/prog_guide/cryptodev_lib.html)). -When DPDK Cryptodev support is enabled, the node graph is modified by adding and replacing some of the nodes. - -The following nodes are replaced: -* esp-encrypt -> dpdk-esp-encrypt -* esp-decrypt -> dpdk-esp-decrypt +When DPDK support is enabled and there are enough Cryptodev resources for all workers, the node graph is reconfigured by adding and changing default next nodes. The following nodes are added: * dpdk-crypto-input : polling input node, basically dequeuing from crypto devices. +* dpdk-esp-encrypt : internal node. +* dpdk-esp-decrypt : internal node. * dpdk-esp-encrypt-post : internal node. * dpdk-esp-decrypt-post : internal node. +Set new default next nodes: +* for esp encryption: esp-encrypt -> dpdk-esp-encrypt +* for esp decryption: esp-decrypt -> dpdk-esp-decrypt + ### How to enable VPP IPSec with DPDK Cryptodev support -To enable DPDK Cryptodev support (disabled by default), we need the following env option: +DPDK Cryptodev is supported in DPDK enabled VPP. +By default, only HW Cryptodev is supported but needs to be explicetly enabled with the following config option: + +``` +dpdk { + enable-cryptodev +} +``` + +To enable SW Cryptodev support (AESNI-MB-PMD and GCM-PMD), we need the following env option: - vpp_uses_dpdk_cryptodev=yes + vpp_uses_dpdk_cryptodev_sw=yes A couple of ways to achive this: * uncomment/add it in the platforms config (ie. build-data/platforms/vpp.mk) -* set the option when building vpp (ie. make vpp_uses_dpdk_cryptodev=yes build-release) +* set the option when building vpp (ie. make vpp_uses_dpdk_cryptodev_sw=yes build-release) + +When enabling SW Cryptodev support, it means that you need to pre-build the required crypto libraries needed by those SW Cryptodev PMDs. ### Crypto Resources allocation VPP allocates crypto resources based on a best effort approach: * first allocate Hardware crypto resources, then Software. -* if there are not enough crypto resources for all workers, all packets will be dropped if they reach ESP encrypt/decrypt nodes, displaying the warning: +* if there are not enough crypto resources for all workers, the graph node is not modifed, therefore the default VPP IPsec implementation based in OpenSSL is used. The following message is displayed: 0: dpdk_ipsec_init: not enough cryptodevs for ipsec ### Configuration example -No especial IPsec configuration is required. - -Once DPDK Cryptodev is enabled, the user just needs to provide cryptodevs in the startup.conf. +To enable DPDK Cryptodev the user just need to provide the startup.conf option +as mentioned previously. Example startup.conf: @@ -53,6 +65,7 @@ dpdk { num-mbufs 131072 dev 0000:81:00.0 dev 0000:81:00.1 + enable-cryptodev dev 0000:85:01.0 dev 0000:85:01.1 vdev cryptodev_aesni_mb_pmd,socket_id=1 diff --git a/src/vnet/devices/dpdk/ipsec/esp.h b/src/vnet/devices/dpdk/ipsec/esp.h index 7ef90c49..d414d679 100644 --- a/src/vnet/devices/dpdk/ipsec/esp.h +++ b/src/vnet/devices/dpdk/ipsec/esp.h @@ -97,60 +97,11 @@ dpdk_esp_init () } static_always_inline int -add_del_sa_sess (u32 sa_index, u8 is_add) -{ - dpdk_crypto_main_t *dcm = &dpdk_crypto_main; - crypto_worker_main_t *cwm; - u8 skip_master = vlib_num_workers () > 0; - - /* *INDENT-OFF* */ - vec_foreach (cwm, dcm->workers_main) - { - crypto_sa_session_t *sa_sess; - u8 is_outbound; - - if (skip_master) - { - skip_master = 0; - continue; - } - - for (is_outbound = 0; is_outbound < 2; is_outbound++) - { - if (is_add) - { - pool_get (cwm->sa_sess_d[is_outbound], sa_sess); - } - else - { - u8 dev_id; - - sa_sess = pool_elt_at_index (cwm->sa_sess_d[is_outbound], sa_index); - dev_id = cwm->qp_data[sa_sess->qp_index].dev_id; - - if (!sa_sess->sess) - continue; - - if (rte_cryptodev_sym_session_free(dev_id, sa_sess->sess)) - { - clib_warning("failed to free session"); - return -1; - } - memset(sa_sess, 0, sizeof(sa_sess[0])); - } - } - } - /* *INDENT-OFF* */ - - return 0; -} - -static_always_inline int -translate_crypto_algo(ipsec_crypto_alg_t crypto_algo, - struct rte_crypto_sym_xform *cipher_xform) +translate_crypto_algo (ipsec_crypto_alg_t crypto_algo, + struct rte_crypto_sym_xform *cipher_xform) { switch (crypto_algo) - { + { case IPSEC_CRYPTO_ALG_NONE: cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_NULL; break; @@ -164,7 +115,7 @@ translate_crypto_algo(ipsec_crypto_alg_t crypto_algo, break; default: return -1; - } + } cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER; @@ -172,10 +123,11 @@ translate_crypto_algo(ipsec_crypto_alg_t crypto_algo, } static_always_inline int -translate_integ_algo(ipsec_integ_alg_t integ_alg, - struct rte_crypto_sym_xform *auth_xform, int use_esn) +translate_integ_algo (ipsec_integ_alg_t integ_alg, + struct rte_crypto_sym_xform *auth_xform, int use_esn) { - switch (integ_alg) { + switch (integ_alg) + { case IPSEC_INTEG_ALG_NONE: auth_xform->auth.algo = RTE_CRYPTO_AUTH_NULL; auth_xform->auth.digest_length = 0; @@ -203,11 +155,11 @@ translate_integ_algo(ipsec_integ_alg_t integ_alg, case IPSEC_INTEG_ALG_AES_GCM_128: auth_xform->auth.algo = RTE_CRYPTO_AUTH_AES_GCM; auth_xform->auth.digest_length = 16; - auth_xform->auth.add_auth_data_length = use_esn? 12 : 8; + auth_xform->auth.add_auth_data_length = use_esn ? 12 : 8; break; default: return -1; - } + } auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH; @@ -215,25 +167,26 @@ translate_integ_algo(ipsec_integ_alg_t integ_alg, } static_always_inline int -create_sym_sess(ipsec_sa_t *sa, crypto_sa_session_t *sa_sess, u8 is_outbound) +create_sym_sess (ipsec_sa_t * sa, crypto_sa_session_t * sa_sess, + u8 is_outbound) { - u32 cpu_index = os_get_cpu_number(); - dpdk_crypto_main_t * dcm = &dpdk_crypto_main; + u32 cpu_index = os_get_cpu_number (); + dpdk_crypto_main_t *dcm = &dpdk_crypto_main; crypto_worker_main_t *cwm = &dcm->workers_main[cpu_index]; - struct rte_crypto_sym_xform cipher_xform = {0}; - struct rte_crypto_sym_xform auth_xform = {0}; + struct rte_crypto_sym_xform cipher_xform = { 0 }; + struct rte_crypto_sym_xform auth_xform = { 0 }; struct rte_crypto_sym_xform *xfs; uword key = 0, *data; - crypto_worker_qp_key_t *p_key = (crypto_worker_qp_key_t *)&key; + crypto_worker_qp_key_t *p_key = (crypto_worker_qp_key_t *) & key; if (sa->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) { sa->crypto_key_len -= 4; - clib_memcpy(&sa->salt, &sa->crypto_key[sa->crypto_key_len], 4); + clib_memcpy (&sa->salt, &sa->crypto_key[sa->crypto_key_len], 4); } else { - sa->salt = (u32) rand(); + sa->salt = (u32) rand (); } cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; @@ -244,11 +197,11 @@ create_sym_sess(ipsec_sa_t *sa, crypto_sa_session_t *sa_sess, u8 is_outbound) auth_xform.auth.key.data = sa->integ_key; auth_xform.auth.key.length = sa->integ_key_len; - if (translate_crypto_algo(sa->crypto_alg, &cipher_xform) < 0) + if (translate_crypto_algo (sa->crypto_alg, &cipher_xform) < 0) return -1; p_key->cipher_algo = cipher_xform.cipher.algo; - if (translate_integ_algo(sa->integ_alg, &auth_xform, sa->use_esn) < 0) + if (translate_integ_algo (sa->integ_alg, &auth_xform, sa->use_esn) < 0) return -1; p_key->auth_algo = auth_xform.auth.algo; @@ -269,17 +222,17 @@ create_sym_sess(ipsec_sa_t *sa, crypto_sa_session_t *sa_sess, u8 is_outbound) p_key->is_outbound = is_outbound; - data = hash_get(cwm->algo_qp_map, key); + data = hash_get (cwm->algo_qp_map, key); if (!data) return -1; sa_sess->sess = - rte_cryptodev_sym_session_create(cwm->qp_data[*data].dev_id, xfs); + rte_cryptodev_sym_session_create (cwm->qp_data[*data].dev_id, xfs); if (!sa_sess->sess) return -1; - sa_sess->qp_index = (u8)*data; + sa_sess->qp_index = (u8) * data; return 0; } diff --git a/src/vnet/devices/dpdk/ipsec/esp_decrypt.c b/src/vnet/devices/dpdk/ipsec/esp_decrypt.c index 89ab9f9b..53b2d122 100644 --- a/src/vnet/devices/dpdk/ipsec/esp_decrypt.c +++ b/src/vnet/devices/dpdk/ipsec/esp_decrypt.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #define foreach_esp_decrypt_next \ _(DROP, "error-drop") \ @@ -189,7 +191,14 @@ dpdk_esp_decrypt_node_fn (vlib_main_t * vm, if (PREDICT_FALSE(!sa_sess->sess)) { int ret = create_sym_sess(sa0, sa_sess, 0); - ASSERT(ret == 0); + + if (PREDICT_FALSE (ret)) + { + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + goto trace; + } } sess = sa_sess->sess; diff --git a/src/vnet/devices/dpdk/ipsec/esp_encrypt.c b/src/vnet/devices/dpdk/ipsec/esp_encrypt.c index 10bb4616..b6f00004 100644 --- a/src/vnet/devices/dpdk/ipsec/esp_encrypt.c +++ b/src/vnet/devices/dpdk/ipsec/esp_encrypt.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #define foreach_esp_encrypt_next \ _(DROP, "error-drop") \ @@ -179,7 +181,14 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm, if (PREDICT_FALSE (!sa_sess->sess)) { int ret = create_sym_sess (sa0, sa_sess, 1); - ASSERT (ret == 0); + + if (PREDICT_FALSE (ret)) + { + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + goto trace; + } } qp_index = sa_sess->qp_index; diff --git a/src/vnet/devices/dpdk/ipsec/ipsec.c b/src/vnet/devices/dpdk/ipsec/ipsec.c index de253f02..05c17c99 100644 --- a/src/vnet/devices/dpdk/ipsec/ipsec.c +++ b/src/vnet/devices/dpdk/ipsec/ipsec.c @@ -15,24 +15,69 @@ #include #include #include +#include +#include + #include #include #include -#include -#define DPDK_CRYPTO_NB_OBJS 2048 +#define DPDK_CRYPTO_NB_SESS_OBJS 20000 #define DPDK_CRYPTO_CACHE_SIZE 512 #define DPDK_CRYPTO_PRIV_SIZE 128 -#define DPDK_CRYPTO_N_QUEUE_DESC 512 +#define DPDK_CRYPTO_N_QUEUE_DESC 1024 #define DPDK_CRYPTO_NB_COPS (1024 * 4) -/* - * return: - * -1: update failed - * 0: already exist - * 1: mapped - */ static int +add_del_sa_sess (u32 sa_index, u8 is_add) +{ + dpdk_crypto_main_t *dcm = &dpdk_crypto_main; + crypto_worker_main_t *cwm; + u8 skip_master = vlib_num_workers () > 0; + + /* *INDENT-OFF* */ + vec_foreach (cwm, dcm->workers_main) + { + crypto_sa_session_t *sa_sess; + u8 is_outbound; + + if (skip_master) + { + skip_master = 0; + continue; + } + + for (is_outbound = 0; is_outbound < 2; is_outbound++) + { + if (is_add) + { + pool_get (cwm->sa_sess_d[is_outbound], sa_sess); + } + else + { + u8 dev_id; + + sa_sess = pool_elt_at_index (cwm->sa_sess_d[is_outbound], sa_index); + dev_id = cwm->qp_data[sa_sess->qp_index].dev_id; + + if (!sa_sess->sess) + continue; + + if (rte_cryptodev_sym_session_free(dev_id, sa_sess->sess)) + { + clib_warning("failed to free session"); + return -1; + } + memset(sa_sess, 0, sizeof(sa_sess[0])); + } + } + } + /* *INDENT-OFF* */ + + return 0; +} + +static void update_qp_data (crypto_worker_main_t * cwm, u8 cdev_id, u16 qp_id, u8 is_outbound, u16 * idx) { @@ -45,7 +90,7 @@ update_qp_data (crypto_worker_main_t * cwm, if (qpd->dev_id == cdev_id && qpd->qp_id == qp_id && qpd->is_outbound == is_outbound) - return 0; + return; } /* *INDENT-ON* */ @@ -54,13 +99,10 @@ update_qp_data (crypto_worker_main_t * cwm, qpd->dev_id = cdev_id; qpd->qp_id = qp_id; qpd->is_outbound = is_outbound; - - return 1; } /* * return: - * -1: error * 0: already exist * 1: mapped */ @@ -70,7 +112,6 @@ add_mapping (crypto_worker_main_t * cwm, const struct rte_cryptodev_capabilities *cipher_cap, const struct rte_cryptodev_capabilities *auth_cap) { - int mapped; u16 qp_index; uword key = 0, data, *ret; crypto_worker_qp_key_t *p_key = (crypto_worker_qp_key_t *) & key; @@ -83,17 +124,12 @@ add_mapping (crypto_worker_main_t * cwm, if (ret) return 0; - mapped = update_qp_data (cwm, cdev_id, qp, is_outbound, &qp_index); - if (mapped < 0) - return -1; + update_qp_data (cwm, cdev_id, qp, is_outbound, &qp_index); data = (uword) qp_index; + hash_set (cwm->algo_qp_map, key, data); - ret = hash_set (cwm->algo_qp_map, key, data); - if (!ret) - rte_panic ("Failed to insert hash table\n"); - - return mapped; + return 1; } /* @@ -120,19 +156,13 @@ add_cdev_mapping (crypto_worker_main_t * cwm, for (j = dev_info->capabilities; j->op != RTE_CRYPTO_OP_TYPE_UNDEFINED; j++) { - int status = 0; - if (j->sym.xform_type != RTE_CRYPTO_SYM_XFORM_AUTH) continue; if (check_algo_is_supported (j, NULL) != 0) continue; - status = add_mapping (cwm, cdev_id, qp, is_outbound, i, j); - if (status == 1) - mapped += 1; - if (status < 0) - return status; + mapped |= add_mapping (cwm, cdev_id, qp, is_outbound, i, j); } } @@ -169,8 +199,33 @@ check_cryptodev_queues () } static clib_error_t * -dpdk_ipsec_init (vlib_main_t * vm) +dpdk_ipsec_check_support (ipsec_sa_t * sa) +{ + if (sa->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) + { + if (sa->integ_alg != IPSEC_INTEG_ALG_NONE) + return clib_error_return (0, "unsupported integ-alg %U with " + "crypto-algo aes-gcm-128", + format_ipsec_integ_alg, sa->integ_alg); + sa->integ_alg = IPSEC_INTEG_ALG_AES_GCM_128; + } + else + { + if (sa->integ_alg == IPSEC_INTEG_ALG_NONE || + sa->integ_alg == IPSEC_INTEG_ALG_AES_GCM_128) + return clib_error_return (0, "unsupported integ-alg %U", + format_ipsec_integ_alg, sa->integ_alg); + } + + return 0; +} + +static uword +dpdk_ipsec_process (vlib_main_t * vm, vlib_node_runtime_t * rt, + vlib_frame_t * f) { + dpdk_config_main_t *conf = &dpdk_config_main; + ipsec_main_t *im = &ipsec_main; dpdk_crypto_main_t *dcm = &dpdk_crypto_main; vlib_thread_main_t *tm = vlib_get_thread_main (); struct rte_cryptodev_config dev_conf; @@ -180,8 +235,19 @@ dpdk_ipsec_init (vlib_main_t * vm) i32 dev_id, ret; u32 i, skip_master; + if (!conf->cryptodev) + { + clib_warning ("DPDK Cryptodev support is disabled, " + "default to OpenSSL IPsec"); + return 0; + } + if (check_cryptodev_queues () < 0) - return clib_error_return (0, "not enough cryptodevs for ipsec"); + { + conf->cryptodev = 0; + clib_warning ("not enough Cryptodevs, default to OpenSSL IPsec"); + return 0; + } vec_alloc (dcm->workers_main, tm->n_vlib_mains); _vec_len (dcm->workers_main) = tm->n_vlib_mains; @@ -221,24 +287,17 @@ dpdk_ipsec_init (vlib_main_t * vm) { map = hash_create (0, sizeof (crypto_worker_qp_key_t)); if (!map) - return clib_error_return (0, "unable to create hash table " - "for worker %u", - vlib_mains[i]->cpu_index); + { + clib_warning ("unable to create hash table for worker %u", + vlib_mains[i]->cpu_index); + goto error; + } cwm->algo_qp_map = map; } for (is_outbound = 0; is_outbound < 2 && qp < max_nb_qp; is_outbound++) - { - int mapped = add_cdev_mapping (cwm, &cdev_info, - dev_id, qp, is_outbound); - if (mapped > 0) - qp++; - - if (mapped < 0) - return clib_error_return (0, - "too many queues for one worker"); - } + qp += add_cdev_mapping (cwm, &cdev_info, dev_id, qp, is_outbound); } if (qp == 0) @@ -246,12 +305,15 @@ dpdk_ipsec_init (vlib_main_t * vm) dev_conf.socket_id = rte_cryptodev_socket_id (dev_id); dev_conf.nb_queue_pairs = cdev_info.max_nb_queue_pairs; - dev_conf.session_mp.nb_objs = DPDK_CRYPTO_NB_OBJS; + dev_conf.session_mp.nb_objs = DPDK_CRYPTO_NB_SESS_OBJS; dev_conf.session_mp.cache_size = DPDK_CRYPTO_CACHE_SIZE; ret = rte_cryptodev_configure (dev_id, &dev_conf); if (ret < 0) - return clib_error_return (0, "cryptodev %u config error", dev_id); + { + clib_warning ("cryptodev %u config error", dev_id); + goto error; + } qp_conf.nb_descriptors = DPDK_CRYPTO_N_QUEUE_DESC; for (qp = 0; qp < dev_conf.nb_queue_pairs; qp++) @@ -259,37 +321,64 @@ dpdk_ipsec_init (vlib_main_t * vm) ret = rte_cryptodev_queue_pair_setup (dev_id, qp, &qp_conf, dev_conf.socket_id); if (ret < 0) - return clib_error_return (0, "cryptodev %u qp %u setup error", - dev_id, qp); + { + clib_warning ("cryptodev %u qp %u setup error", dev_id, qp); + goto error; + } } - fprintf (stdout, "%u\t%u\t%u\t%u\n", dev_id, dev_conf.nb_queue_pairs, - DPDK_CRYPTO_NB_OBJS, DPDK_CRYPTO_CACHE_SIZE); - } + vec_validate_aligned (dcm->cop_pools, dev_conf.socket_id, + CLIB_CACHE_LINE_BYTES); - u32 socket_id = rte_socket_id (); + if (!vec_elt (dcm->cop_pools, dev_conf.socket_id)) + { + u8 *pool_name = format (0, "crypto_op_pool_socket%u%c", + dev_conf.socket_id, 0); + + rmp = rte_crypto_op_pool_create ((char *) pool_name, + RTE_CRYPTO_OP_TYPE_SYMMETRIC, + DPDK_CRYPTO_NB_COPS * + (1 + vlib_num_workers ()), + DPDK_CRYPTO_CACHE_SIZE, + DPDK_CRYPTO_PRIV_SIZE, + dev_conf.socket_id); + vec_free (pool_name); + + if (!rmp) + { + clib_warning ("failed to allocate mempool on socket %u", + dev_conf.socket_id); + goto error; + } + vec_elt (dcm->cop_pools, dev_conf.socket_id) = rmp; + } - vec_validate_aligned (dcm->cop_pools, socket_id, CLIB_CACHE_LINE_BYTES); + fprintf (stdout, "%u\t%u\t%u\t%u\n", dev_id, dev_conf.nb_queue_pairs, + DPDK_CRYPTO_NB_SESS_OBJS, DPDK_CRYPTO_CACHE_SIZE); + } - /* pool already exists, nothing to do */ - if (dcm->cop_pools[socket_id]) - return 0; + dpdk_esp_init (); - u8 *pool_name = format (0, "crypto_op_pool_socket%u%c", socket_id, 0); + /* Add new next node and set as default */ + vlib_node_t *node, *next_node; - rmp = rte_crypto_op_pool_create ((char *) pool_name, - RTE_CRYPTO_OP_TYPE_SYMMETRIC, - DPDK_CRYPTO_NB_COPS * - (1 + vlib_num_workers ()), - DPDK_CRYPTO_CACHE_SIZE, - DPDK_CRYPTO_PRIV_SIZE, socket_id); - vec_free (pool_name); + next_node = vlib_get_node_by_name (vm, (u8 *) "dpdk-esp-encrypt"); + ASSERT (next_node); + node = vlib_get_node_by_name (vm, (u8 *) "ipsec-output-ip4"); + ASSERT (node); + im->esp_encrypt_node_index = next_node->index; + im->esp_encrypt_next_index = + vlib_node_add_next (vm, node->index, next_node->index); - if (!rmp) - return clib_error_return (0, "failed to allocate mempool on socket %u", - socket_id); - dcm->cop_pools[socket_id] = rmp; + next_node = vlib_get_node_by_name (vm, (u8 *) "dpdk-esp-decrypt"); + ASSERT (next_node); + node = vlib_get_node_by_name (vm, (u8 *) "ipsec-input-ip4"); + ASSERT (node); + im->esp_decrypt_node_index = next_node->index; + im->esp_decrypt_next_index = + vlib_node_add_next (vm, node->index, next_node->index); - dpdk_esp_init (); + im->cb.check_support_cb = dpdk_ipsec_check_support; + im->cb.add_del_sa_sess_cb = add_del_sa_sess; if (vec_len (vlib_mains) == 0) vlib_node_set_state (&vlib_global_main, dpdk_crypto_input_node.index, @@ -299,10 +388,38 @@ dpdk_ipsec_init (vlib_main_t * vm) vlib_node_set_state (vlib_mains[i], dpdk_crypto_input_node.index, VLIB_NODE_STATE_POLLING); + /* TODO cryptodev counters */ + + return 0; + +error: + ; + crypto_worker_main_t *cwm; + struct rte_mempool **mp; + /* *INDENT-OFF* */ + vec_foreach (cwm, dcm->workers_main) + hash_free (cwm->algo_qp_map); + + vec_foreach (mp, dcm->cop_pools) + { + if (mp) + rte_mempool_free (mp[0]); + } + /* *INDENT-ON* */ + vec_free (dcm->workers_main); + vec_free (dcm->cop_pools); + return 0; } -VLIB_MAIN_LOOP_ENTER_FUNCTION (dpdk_ipsec_init); +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (dpdk_ipsec_process_node,static) = { + .function = dpdk_ipsec_process, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "dpdk-ipsec-process", + .process_log2_n_stack_bytes = 17, +}; +/* *INDENT-ON* */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/devices/dpdk/ipsec/ipsec.h b/src/vnet/devices/dpdk/ipsec/ipsec.h index e6c7498c..3465b361 100644 --- a/src/vnet/devices/dpdk/ipsec/ipsec.h +++ b/src/vnet/devices/dpdk/ipsec/ipsec.h @@ -167,7 +167,7 @@ check_algo_is_supported (const struct rte_cryptodev_capabilities *cap, .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher = RTE_CRYPTO_CIPHER_3DES_CBC,.name = "3DES-CBC"}, { - .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.auth = + .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher = RTE_CRYPTO_CIPHER_AES_GCM,.name = "AES-GCM"}, { .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth = diff --git a/src/vnet/ipsec-gre/interface.c b/src/vnet/ipsec-gre/interface.c index 56832ee1..3b6e4ac2 100644 --- a/src/vnet/ipsec-gre/interface.c +++ b/src/vnet/ipsec-gre/interface.c @@ -28,13 +28,7 @@ #include #include -#if DPDK_CRYPTO==1 -#include -#define ESP_NODE "dpdk-esp-encrypt" -#else #include -#define ESP_NODE "esp-encrypt" -#endif u8 * format_ipsec_gre_tunnel (u8 * s, va_list * args) @@ -193,7 +187,7 @@ vnet_ipsec_gre_add_del_tunnel (vnet_ipsec_gre_add_del_tunnel_args_t * a, hash_set (igm->tunnel_by_key, key, t - igm->tunnels); slot = vlib_node_add_named_next_with_slot - (vnm->vlib_main, hi->tx_node_index, ESP_NODE, + (vnm->vlib_main, hi->tx_node_index, "esp-encrypt", IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT); ASSERT (slot == IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT); diff --git a/src/vnet/ipsec/ipsec.c b/src/vnet/ipsec/ipsec.c index ee85c402..cfe434ab 100644 --- a/src/vnet/ipsec/ipsec.c +++ b/src/vnet/ipsec/ipsec.c @@ -22,23 +22,7 @@ #include #include - -#if DPDK_CRYPTO==1 -#include -#define ESP_NODE "dpdk-esp-encrypt" -#else #include -#define ESP_NODE "esp-encrypt" -#endif - -#if DPDK_CRYPTO==0 -/* dummy function */ -static int -add_del_sa_sess (u32 sa_index, u8 is_add) -{ - return 0; -} -#endif u32 ipsec_get_sa_index_by_sa_id (u32 sa_id) @@ -449,7 +433,9 @@ ipsec_add_del_sa (vlib_main_t * vm, ipsec_sa_t * new_sa, int is_add) return VNET_API_ERROR_SYSCALL_ERROR_1; /* sa used in policy */ } hash_unset (im->sa_index_by_sa_id, sa->id); - add_del_sa_sess (sa_index, is_add); + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (sa_index, is_add) < 0) + return VNET_API_ERROR_SYSCALL_ERROR_1; pool_put (im->sad, sa); } else /* create new SA */ @@ -458,7 +444,8 @@ ipsec_add_del_sa (vlib_main_t * vm, ipsec_sa_t * new_sa, int is_add) clib_memcpy (sa, new_sa, sizeof (*sa)); sa_index = sa - im->sad; hash_set (im->sa_index_by_sa_id, sa->id, sa_index); - if (add_del_sa_sess (sa_index, is_add) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (sa_index, is_add) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; } return 0; @@ -497,7 +484,8 @@ ipsec_set_sa_key (vlib_main_t * vm, ipsec_sa_t * sa_update) if (sa->crypto_key_len + sa->integ_key_len > 0) { - if (add_del_sa_sess (sa_index, 0) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (sa_index, 0) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; } @@ -521,6 +509,19 @@ ipsec_rand_seed (void) RAND_seed ((const void *) &seed_data, sizeof (seed_data)); } +static clib_error_t * +ipsec_check_support (ipsec_sa_t * sa) +{ + if (sa->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) + return clib_error_return (0, "unsupported aes-gcm-128 crypto-alg"); + if (sa->integ_alg == IPSEC_INTEG_ALG_NONE) + return clib_error_return (0, "unsupported none integ-alg"); + if (sa->integ_alg == IPSEC_INTEG_ALG_AES_GCM_128) + return clib_error_return (0, "unsupported aes-gcm-128 integ-alg"); + + return 0; +} + static clib_error_t * ipsec_init (vlib_main_t * vm) { @@ -547,14 +548,18 @@ ipsec_init (vlib_main_t * vm) ASSERT (node); im->error_drop_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) ESP_NODE); - + node = vlib_get_node_by_name (vm, (u8 *) "esp-encrypt"); ASSERT (node); im->esp_encrypt_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "ip4-lookup"); + node = vlib_get_node_by_name (vm, (u8 *) "esp-decrypt"); ASSERT (node); - im->ip4_lookup_node_index = node->index; + im->esp_decrypt_node_index = node->index; + + im->esp_encrypt_next_index = IPSEC_OUTPUT_NEXT_ESP_ENCRYPT; + im->esp_decrypt_next_index = IPSEC_INPUT_NEXT_ESP_DECRYPT; + + im->cb.check_support_cb = ipsec_check_support; if ((error = vlib_call_init_function (vm, ipsec_cli_init))) return error; diff --git a/src/vnet/ipsec/ipsec.h b/src/vnet/ipsec/ipsec.h index 32c7edfc..6726dba0 100644 --- a/src/vnet/ipsec/ipsec.h +++ b/src/vnet/ipsec/ipsec.h @@ -17,6 +17,33 @@ #define IPSEC_FLAG_IPSEC_GRE_TUNNEL (1 << 0) + +#define foreach_ipsec_output_next \ +_(DROP, "error-drop") \ +_(ESP_ENCRYPT, "esp-encrypt") + +#define _(v, s) IPSEC_OUTPUT_NEXT_##v, +typedef enum +{ + foreach_ipsec_output_next +#undef _ + IPSEC_OUTPUT_N_NEXT, +} ipsec_output_next_t; + + +#define foreach_ipsec_input_next \ +_(DROP, "error-drop") \ +_(ESP_DECRYPT, "esp-decrypt") + +#define _(v, s) IPSEC_INPUT_NEXT_##v, +typedef enum +{ + foreach_ipsec_input_next +#undef _ + IPSEC_INPUT_N_NEXT, +} ipsec_input_next_t; + + #define foreach_ipsec_policy_action \ _(0, BYPASS, "bypass") \ _(1, DISCARD, "discard") \ @@ -31,20 +58,12 @@ typedef enum IPSEC_POLICY_N_ACTION, } ipsec_policy_action_t; -#if DPDK_CRYPTO==1 #define foreach_ipsec_crypto_alg \ _(0, NONE, "none") \ _(1, AES_CBC_128, "aes-cbc-128") \ _(2, AES_CBC_192, "aes-cbc-192") \ _(3, AES_CBC_256, "aes-cbc-256") \ _(4, AES_GCM_128, "aes-gcm-128") -#else -#define foreach_ipsec_crypto_alg \ - _(0, NONE, "none") \ - _(1, AES_CBC_128, "aes-cbc-128") \ - _(2, AES_CBC_192, "aes-cbc-192") \ - _(3, AES_CBC_256, "aes-cbc-256") -#endif typedef enum { @@ -54,7 +73,6 @@ typedef enum IPSEC_CRYPTO_N_ALG, } ipsec_crypto_alg_t; -#if DPDK_CRYPTO==1 #define foreach_ipsec_integ_alg \ _(0, NONE, "none") \ _(1, MD5_96, "md5-96") /* RFC2403 */ \ @@ -63,17 +81,7 @@ typedef enum _(4, SHA_256_128, "sha-256-128") /* RFC4868 */ \ _(5, SHA_384_192, "sha-384-192") /* RFC4868 */ \ _(6, SHA_512_256, "sha-512-256") /* RFC4868 */ \ - _(7, AES_GCM_128, "aes-gcm-128") -#else -#define foreach_ipsec_integ_alg \ - _(0, NONE, "none") \ - _(1, MD5_96, "md5-96") /* RFC2403 */ \ - _(2, SHA1_96, "sha1-96") /* RFC2404 */ \ - _(3, SHA_256_96, "sha-256-96") /* draft-ietf-ipsec-ciph-sha-256-00 */ \ - _(4, SHA_256_128, "sha-256-128") /* RFC4868 */ \ - _(5, SHA_384_192, "sha-384-192") /* RFC4868 */ \ - _(6, SHA_512_256, "sha-512-256") /* RFC4868 */ -#endif + _(7, AES_GCM_128, "aes-gcm-128") /* RFC4106 */ typedef enum { @@ -223,6 +231,12 @@ typedef struct u32 hw_if_index; } ipsec_tunnel_if_t; +typedef struct +{ + i32 (*add_del_sa_sess_cb) (u32 sa_index, u8 is_add); + clib_error_t *(*check_support_cb) (ipsec_sa_t * sa); +} ipsec_main_callbacks_t; + typedef struct { /* pool of tunnel instances */ @@ -250,11 +264,16 @@ typedef struct uword *sa_index_by_sa_id; uword *ipsec_if_pool_index_by_key; - /* node indexes */ + /* node indeces */ u32 error_drop_node_index; - u32 ip4_lookup_node_index; u32 esp_encrypt_node_index; + u32 esp_decrypt_node_index; + /* next node indeces */ + u32 esp_encrypt_next_index; + u32 esp_decrypt_next_index; + /* callbacks */ + ipsec_main_callbacks_t cb; } ipsec_main_t; ipsec_main_t ipsec_main; diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c index 9bcf63b4..30732266 100644 --- a/src/vnet/ipsec/ipsec_api.c +++ b/src/vnet/ipsec/ipsec_api.c @@ -177,6 +177,7 @@ static void vl_api_ipsec_sad_add_del_entry_t_handler vl_api_ipsec_sad_add_del_entry_reply_t *rmp; int rv; #if WITH_LIBSSL > 0 + ipsec_main_t *im = &ipsec_main; ipsec_sa_t sa; memset (&sa, 0, sizeof (sa)); @@ -204,11 +205,7 @@ static void vl_api_ipsec_sad_add_del_entry_t_handler sa.crypto_key_len = mp->crypto_key_length; clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key)); /* check for unsupported integ-alg */ -#if DPDK_CRYPTO==1 if (mp->integrity_algorithm < IPSEC_INTEG_ALG_NONE || -#else - if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 || -#endif mp->integrity_algorithm >= IPSEC_INTEG_N_ALG) { clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg, @@ -217,35 +214,6 @@ static void vl_api_ipsec_sad_add_del_entry_t_handler goto out; } -#if DPDK_CRYPTO==1 - /*Special cases, aes-gcm-128 encryption */ - if (mp->crypto_algorithm == IPSEC_CRYPTO_ALG_AES_GCM_128) - { - if (mp->integrity_algorithm != IPSEC_INTEG_ALG_NONE - && mp->integrity_algorithm != IPSEC_INTEG_ALG_AES_GCM_128) - { - clib_warning - ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg"); - rv = VNET_API_ERROR_UNIMPLEMENTED; - goto out; - } - else /*set integ-alg internally to aes-gcm-128 */ - mp->integrity_algorithm = IPSEC_INTEG_ALG_AES_GCM_128; - } - else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_AES_GCM_128) - { - clib_warning ("unsupported integ-alg: aes-gcm-128"); - rv = VNET_API_ERROR_UNIMPLEMENTED; - goto out; - } - else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_NONE) - { - clib_warning ("unsupported integ-alg: none"); - rv = VNET_API_ERROR_UNIMPLEMENTED; - goto out; - } -#endif - sa.integ_alg = mp->integrity_algorithm; sa.integ_key_len = mp->integrity_key_length; clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key)); @@ -263,6 +231,15 @@ static void vl_api_ipsec_sad_add_del_entry_t_handler clib_memcpy (&sa.tunnel_dst_addr.ip4.data, mp->tunnel_dst_address, 4); } + ASSERT (im->cb.check_support_cb); + clib_error_t *err = im->cb.check_support_cb (&sa); + if (err) + { + clib_warning ("%s", err->what); + rv = VNET_API_ERROR_UNIMPLEMENTED; + goto out; + } + rv = ipsec_add_del_sa (vm, &sa, mp->is_add); #else rv = VNET_API_ERROR_UNIMPLEMENTED; diff --git a/src/vnet/ipsec/ipsec_cli.c b/src/vnet/ipsec/ipsec_cli.c index 7ab85d4a..3c1e26f2 100644 --- a/src/vnet/ipsec/ipsec_cli.c +++ b/src/vnet/ipsec/ipsec_cli.c @@ -67,10 +67,12 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { + ipsec_main_t *im = &ipsec_main; unformat_input_t _line_input, *line_input = &_line_input; ipsec_sa_t sa; int is_add = ~0; u8 *ck = 0, *ik = 0; + clib_error_t *err = 0; memset (&sa, 0, sizeof (sa)); @@ -109,11 +111,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg, &sa.integ_alg)) { -#if DPDK_CRYPTO==1 - if (sa.integ_alg < IPSEC_INTEG_ALG_NONE || -#else if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 || -#endif sa.integ_alg >= IPSEC_INTEG_N_ALG) return clib_error_return (0, "unsupported integ-alg: '%U'", format_ipsec_integ_alg, sa.integ_alg); @@ -141,23 +139,6 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, format_unformat_error, line_input); } -#if DPDK_CRYPTO==1 - /*Special cases, aes-gcm-128 encryption */ - if (sa.crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) - { - if (sa.integ_alg != IPSEC_INTEG_ALG_NONE - && sa.integ_alg != IPSEC_INTEG_ALG_AES_GCM_128) - return clib_error_return (0, - "unsupported: aes-gcm-128 crypto-alg needs none as integ-alg"); - else /*set integ-alg internally to aes-gcm-128 */ - sa.integ_alg = IPSEC_INTEG_ALG_AES_GCM_128; - } - else if (sa.integ_alg == IPSEC_INTEG_ALG_AES_GCM_128) - return clib_error_return (0, "unsupported integ-alg: aes-gcm-128"); - else if (sa.integ_alg == IPSEC_INTEG_ALG_NONE) - return clib_error_return (0, "unsupported integ-alg: none"); -#endif - unformat_free (line_input); if (sa.crypto_key_len > sizeof (sa.crypto_key)) @@ -172,6 +153,14 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm, if (ik) strncpy ((char *) sa.integ_key, (char *) ik, sa.integ_key_len); + if (is_add) + { + ASSERT (im->cb.check_support_cb); + err = im->cb.check_support_cb (&sa); + if (err) + return err; + } + ipsec_add_del_sa (vm, &sa, is_add); return 0; diff --git a/src/vnet/ipsec/ipsec_if.c b/src/vnet/ipsec/ipsec_if.c index a8da046f..ca6b0092 100644 --- a/src/vnet/ipsec/ipsec_if.c +++ b/src/vnet/ipsec/ipsec_if.c @@ -20,20 +20,7 @@ #include #include -#if DPDK_CRYPTO==1 -#include -#else #include -#endif - -#if DPDK_CRYPTO==0 -/* dummy function */ -static int -add_del_sa_sess (u32 sa_index, u8 is_add) -{ - return 0; -} -#endif void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); @@ -52,6 +39,39 @@ dummy_interface_tx (vlib_main_t * vm, return frame->n_vectors; } +static clib_error_t * +ipsec_admin_up_down_function (vnet_main_t * vnm, u32 hw_if_index, u32 flags) +{ + ipsec_main_t *im = &ipsec_main; + clib_error_t *err = 0; + ipsec_tunnel_if_t *t; + vnet_hw_interface_t *hi; + ipsec_sa_t *sa; + + hi = vnet_get_hw_interface (vnm, hw_if_index); + if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) + { + t = pool_elt_at_index (im->tunnel_interfaces, hi->hw_instance); + ASSERT (im->cb.check_support_cb); + sa = pool_elt_at_index (im->sad, t->input_sa_index); + err = im->cb.check_support_cb (sa); + if (err) + return err; + + sa = pool_elt_at_index (im->sad, t->output_sa_index); + err = im->cb.check_support_cb (sa); + if (err) + return err; + + vnet_sw_interface_set_flags (vnm, hi->sw_if_index, + VNET_HW_INTERFACE_FLAG_LINK_UP); + } + else + vnet_sw_interface_set_flags (vnm, hi->sw_if_index, 0 /* down */ ); + + return /* no error */ 0; +} + /* *INDENT-OFF* */ VNET_DEVICE_CLASS (ipsec_device_class, static) = { @@ -59,6 +79,7 @@ VNET_DEVICE_CLASS (ipsec_device_class, static) = .format_device_name = format_ipsec_name, .format_tx_trace = format_ipsec_if_output_trace, .tx_function = dummy_interface_tx, + .admin_up_down_function = ipsec_admin_up_down_function, }; /* *INDENT-ON* */ @@ -138,7 +159,9 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, args->remote_crypto_key_len); } - add_del_sa_sess (t->input_sa_index, args->is_add); + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->input_sa_index, args->is_add) < 0) + return VNET_API_ERROR_SYSCALL_ERROR_1; pool_get (im->sad, sa); memset (sa, 0, sizeof (*sa)); @@ -165,7 +188,9 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, args->local_crypto_key_len); } - add_del_sa_sess (t->output_sa_index, args->is_add); + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->output_sa_index, args->is_add) < 0) + return VNET_API_ERROR_SYSCALL_ERROR_1; hash_set (im->ipsec_if_pool_index_by_key, key, t - im->tunnel_interfaces); @@ -211,14 +236,16 @@ ipsec_add_del_tunnel_if_internal (vnet_main_t * vnm, /* delete input and output SA */ sa = pool_elt_at_index (im->sad, t->input_sa_index); - if (add_del_sa_sess (t->input_sa_index, args->is_add) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->input_sa_index, args->is_add) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; pool_put (im->sad, sa); sa = pool_elt_at_index (im->sad, t->output_sa_index); - if (add_del_sa_sess (t->output_sa_index, args->is_add) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->output_sa_index, args->is_add) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; pool_put (im->sad, sa); @@ -310,7 +337,8 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->crypto_key_len = vec_len (key); clib_memcpy (sa->crypto_key, key, vec_len (key)); - if (add_del_sa_sess (t->input_sa_index, 0) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->output_sa_index, 0) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; } else if (type == IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG) @@ -320,7 +348,8 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->integ_key_len = vec_len (key); clib_memcpy (sa->integ_key, key, vec_len (key)); - if (add_del_sa_sess (t->output_sa_index, 0) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->output_sa_index, 0) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; } else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO) @@ -330,7 +359,8 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->crypto_key_len = vec_len (key); clib_memcpy (sa->crypto_key, key, vec_len (key)); - if (add_del_sa_sess (t->input_sa_index, 0) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->input_sa_index, 0) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; } else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG) @@ -340,7 +370,8 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->integ_key_len = vec_len (key); clib_memcpy (sa->integ_key, key, vec_len (key)); - if (add_del_sa_sess (t->output_sa_index, 0) < 0) + if (im->cb.add_del_sa_sess_cb && + im->cb.add_del_sa_sess_cb (t->input_sa_index, 0) < 0) return VNET_API_ERROR_SYSCALL_ERROR_1; } else diff --git a/src/vnet/ipsec/ipsec_if_in.c b/src/vnet/ipsec/ipsec_if_in.c index db75ab92..bd2a9f78 100644 --- a/src/vnet/ipsec/ipsec_if_in.c +++ b/src/vnet/ipsec/ipsec_if_in.c @@ -22,12 +22,6 @@ #include #include -#if DPDK_CRYPTO==1 -#define ESP_NODE "dpdk-esp-decrypt" -#else -#define ESP_NODE "esp-decrypt" -#endif - /* Statistics (not really errors) */ #define foreach_ipsec_if_input_error \ _(RX, "good packets received") @@ -46,12 +40,6 @@ typedef enum IPSEC_IF_INPUT_N_ERROR, } ipsec_if_input_error_t; -typedef enum -{ - IPSEC_IF_INPUT_NEXT_ESP_DECRYPT, - IPSEC_IF_INPUT_NEXT_DROP, - IPSEC_IF_INPUT_N_NEXT, -} ipsec_if_input_next_t; typedef struct { @@ -59,7 +47,6 @@ typedef struct u32 seq; } ipsec_if_input_trace_t; - u8 * format_ipsec_if_input_trace (u8 * s, va_list * args) { @@ -106,7 +93,7 @@ ipsec_if_input_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, ip0 = vlib_buffer_get_current (b0); esp0 = (esp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); - next0 = IPSEC_IF_INPUT_NEXT_DROP; + next0 = IPSEC_INPUT_NEXT_DROP; u64 key = (u64) ip0->src_address.as_u32 << 32 | (u64) clib_net_to_host_u32 (esp0->spi); @@ -121,7 +108,7 @@ ipsec_if_input_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vnet_buffer (b0)->ipsec.flags = t->hw_if_index == ~0 ? IPSEC_FLAG_IPSEC_GRE_TUNNEL : 0; vlib_buffer_advance (b0, ip4_header_bytes (ip0)); - next0 = IPSEC_IF_INPUT_NEXT_ESP_DECRYPT; + next0 = im->esp_decrypt_next_index; } if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) @@ -156,12 +143,7 @@ VLIB_REGISTER_NODE (ipsec_if_input_node) = { .n_errors = ARRAY_LEN(ipsec_if_input_error_strings), .error_strings = ipsec_if_input_error_strings, - .n_next_nodes = IPSEC_IF_INPUT_N_NEXT, - - .next_nodes = { - [IPSEC_IF_INPUT_NEXT_ESP_DECRYPT] = ESP_NODE, - [IPSEC_IF_INPUT_NEXT_DROP] = "error-drop", - }, + .sibling_of = "ipsec-input-ip4", }; /* *INDENT-ON* */ diff --git a/src/vnet/ipsec/ipsec_if_out.c b/src/vnet/ipsec/ipsec_if_out.c index 8f062828..62ff67ac 100644 --- a/src/vnet/ipsec/ipsec_if_out.c +++ b/src/vnet/ipsec/ipsec_if_out.c @@ -21,12 +21,6 @@ #include -#if DPDK_CRYPTO==1 -#define ESP_NODE "dpdk-esp-encrypt" -#else -#define ESP_NODE "esp-encrypt" -#endif - /* Statistics (not really errors) */ #define foreach_ipsec_if_output_error \ _(TX, "good packets transmitted") @@ -45,12 +39,6 @@ typedef enum IPSEC_IF_OUTPUT_N_ERROR, } ipsec_if_output_error_t; -typedef enum -{ - IPSEC_IF_OUTPUT_NEXT_ESP_ENCRYPT, - IPSEC_IF_OUTPUT_NEXT_DROP, - IPSEC_IF_OUTPUT_N_NEXT, -} ipsec_if_output_next_t; typedef struct { @@ -58,7 +46,6 @@ typedef struct u32 seq; } ipsec_if_output_trace_t; - u8 * format_ipsec_if_output_trace (u8 * s, va_list * args) { @@ -106,7 +93,7 @@ ipsec_if_output_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); t0 = pool_elt_at_index (im->tunnel_interfaces, hi0->dev_instance); vnet_buffer (b0)->ipsec.sad_index = t0->output_sa_index; - next0 = IPSEC_IF_OUTPUT_NEXT_ESP_ENCRYPT; + next0 = im->esp_encrypt_next_index; if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { @@ -142,12 +129,7 @@ VLIB_REGISTER_NODE (ipsec_if_output_node) = { .n_errors = ARRAY_LEN(ipsec_if_output_error_strings), .error_strings = ipsec_if_output_error_strings, - .n_next_nodes = IPSEC_IF_OUTPUT_N_NEXT, - - .next_nodes = { - [IPSEC_IF_OUTPUT_NEXT_ESP_ENCRYPT] = ESP_NODE, - [IPSEC_IF_OUTPUT_NEXT_DROP] = "error-drop", - }, + .sibling_of = "ipsec-output-ip4", }; /* *INDENT-ON* */ diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c index 4662c1a1..deaa7b7b 100644 --- a/src/vnet/ipsec/ipsec_input.c +++ b/src/vnet/ipsec/ipsec_input.c @@ -23,30 +23,10 @@ #include #include -#if DPDK_CRYPTO==1 -#define ESP_NODE "dpdk-esp-decrypt" -#else -#define ESP_NODE "esp-decrypt" -#endif - -#define foreach_ipsec_input_next \ -_(DROP, "error-drop") \ -_(ESP_DECRYPT, ESP_NODE) - -#define _(v, s) IPSEC_INPUT_NEXT_##v, -typedef enum -{ - foreach_ipsec_input_next -#undef _ - IPSEC_INPUT_N_NEXT, -} ipsec_input_next_t; - - #define foreach_ipsec_input_error \ _(RX_PKTS, "IPSEC pkts received") \ _(DECRYPTION_FAILED, "IPSEC decryption failed") - typedef enum { #define _(sym,str) IPSEC_INPUT_ERROR_##sym, @@ -262,7 +242,7 @@ ipsec_input_ip4_node_fn (vlib_main_t * vm, p0->counter.bytes += clib_net_to_host_u16 (ip0->length); vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; vnet_buffer (b0)->ipsec.flags = 0; - next0 = IPSEC_INPUT_NEXT_ESP_DECRYPT; + next0 = im->esp_decrypt_next_index; vlib_buffer_advance (b0, ip4_header_bytes (ip0)); goto trace0; } @@ -392,7 +372,7 @@ VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, ipsec_input_ip4_node_fn) p0->counter.bytes += header_size; vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; vnet_buffer (b0)->ipsec.flags = 0; - next0 = IPSEC_INPUT_NEXT_ESP_DECRYPT; + next0 = im->esp_decrypt_next_index; vlib_buffer_advance (b0, header_size); goto trace0; } diff --git a/src/vnet/ipsec/ipsec_output.c b/src/vnet/ipsec/ipsec_output.c index df93b5e4..1b8070d6 100644 --- a/src/vnet/ipsec/ipsec_output.c +++ b/src/vnet/ipsec/ipsec_output.c @@ -21,27 +21,8 @@ #include -#if DPDK_CRYPTO==1 -#define ESP_NODE "dpdk-esp-encrypt" -#else -#define ESP_NODE "esp-encrypt" -#endif - #if WITH_LIBSSL > 0 -#define foreach_ipsec_output_next \ -_(DROP, "error-drop") \ -_(ESP_ENCRYPT, ESP_NODE) - -#define _(v, s) IPSEC_OUTPUT_NEXT_##v, -typedef enum -{ - foreach_ipsec_output_next -#undef _ - IPSEC_OUTPUT_N_NEXT, -} ipsec_output_next_t; - - #define foreach_ipsec_output_error \ _(RX_PKTS, "IPSec pkts received") \ _(POLICY_DISCARD, "IPSec policy discard") \ @@ -50,7 +31,6 @@ typedef enum _(POLICY_BYPASS, "IPSec policy bypass") \ _(ENCAPS_FAILED, "IPSec encapsulation failed") - typedef enum { #define _(sym,str) IPSEC_OUTPUT_ERROR_##sym, -- cgit 1.2.3-korg From 52a047a822242216247a97988ee5ffb329ef9f48 Mon Sep 17 00:00:00 2001 From: Radu Nicolau Date: Thu, 16 Feb 2017 13:43:41 +0000 Subject: ipsec: changed ipsec-input-ip6 node to be a sibling of ipsec-input-ip4, fixes a problem that occurs with cryptodev ipv6 input. Change-Id: I1f0c0db45b2aabc243dd785c8d5d5ef990cac903 Signed-off-by: Radu Nicolau --- src/vnet/ipsec/ipsec_input.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/vnet/ipsec/ipsec_input.c') diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c index deaa7b7b..f27058bb 100644 --- a/src/vnet/ipsec/ipsec_input.c +++ b/src/vnet/ipsec/ipsec_input.c @@ -416,12 +416,7 @@ VLIB_REGISTER_NODE (ipsec_input_ip6_node,static) = { .n_errors = ARRAY_LEN(ipsec_input_error_strings), .error_strings = ipsec_input_error_strings, - .n_next_nodes = IPSEC_INPUT_N_NEXT, - .next_nodes = { -#define _(s,n) [IPSEC_INPUT_NEXT_##s] = n, - foreach_ipsec_input_next -#undef _ - }, + .sibling_of = "ipsec-input-ip4", }; /* *INDENT-ON* */ -- cgit 1.2.3-korg