From cb9cadad578297ffd78fa8a33670bdf1ab669e7e Mon Sep 17 00:00:00 2001 From: Ed Warnicke Date: Tue, 8 Dec 2015 15:45:58 -0700 Subject: Initial commit of vpp code. Change-Id: Ib246f1fbfce93274020ee93ce461e3d8bd8b9f17 Signed-off-by: Ed Warnicke --- build-data/packages/dpdk.mk | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 build-data/packages/dpdk.mk (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk new file mode 100644 index 00000000..c7f04346 --- /dev/null +++ b/build-data/packages/dpdk.mk @@ -0,0 +1,24 @@ + +DPDK_MARCH = $(strip $($(PLATFORM)_dpdk_arch)) +ifeq ($(DPDK_MARCH),) + DPDK_MARCH="native" +endif + +ifneq (,$(findstring debug,$(TAG))) + DPDK_DEBUG=y +else + DPDK_DEBUG=n +endif + +DPDK_MAKE_ARGS = -C $(call find_source_fn,$(PACKAGE_SOURCE)) \ + DPDK_BUILD_DIR=$(PACKAGE_BUILD_DIR) \ + DPDK_INSTALL_DIR=$(PACKAGE_INSTALL_DIR) \ + DPDK_MARCH=$(DPDK_MARCH) \ + DPDK_DEBUG=$(DPDK_DEBUG) + + +dpdk_configure = echo + +dpdk_make_args = $(DPDK_MAKE_ARGS) config + +dpdk_install = make $(DPDK_MAKE_ARGS) build -- cgit 1.2.3-korg From 737547efc348c5c60d75a14e04d4aad8499fd3b6 Mon Sep 17 00:00:00 2001 From: Christophe Fontaine Date: Wed, 11 May 2016 08:40:33 +0000 Subject: dpdk/Makefile - Allow dpdk target to be set according to the platform Allows DPDK parameters to be overriden from the platform definition. $(PLATFORM)_dpdk_arch = "armv7a" $(PLATFORM)_dpdk_target = "arm-armv7a-linuxapp-gcc" $(PLATFORM)_dpdk_make_extra_args = "CONFIG_RTE_EAL_IGB_UIO=y" Change-Id: I8c0f233942744cb82ca3ed2d65e33acee845cb4e Signed-off-by: Christophe Fontaine --- build-data/packages/dpdk.mk | 10 ++++++++++ build-data/platforms/arm32.mk | 14 +++++++++++--- dpdk/Makefile | 11 ++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index c7f04346..2bfc4b49 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -17,6 +17,16 @@ DPDK_MAKE_ARGS = -C $(call find_source_fn,$(PACKAGE_SOURCE)) \ DPDK_DEBUG=$(DPDK_DEBUG) +TARGET=$(strip $($(PLATFORM)_dpdk_target)) +ifneq ($(TARGET),) +DPDK_MAKE_ARGS += DPDK_TARGET=$(TARGET) +endif + +DPDK_MAKE_EXTRA_ARGS = $(strip $($(PLATFORM)_dpdk_make_extra_args)) +ifneq ($(DPDK_MAKE_EXTRA_ARGS),) +DPDK_MAKE_ARGS += DPDK_MAKE_EXTRA_ARGS="$(DPDK_MAKE_EXTRA_ARGS)" +endif + dpdk_configure = echo dpdk_make_args = $(DPDK_MAKE_ARGS) config diff --git a/build-data/platforms/arm32.mk b/build-data/platforms/arm32.mk index fecc5bbc..5e1adabf 100644 --- a/build-data/platforms/arm32.mk +++ b/build-data/platforms/arm32.mk @@ -15,16 +15,24 @@ arm32_arch = native arm32_native_tools = vppapigen -arm32_uses_dpdk = no +arm32_uses_dpdk = yes arm32_uses_openssl = no arm32_root_packages = vpp vlib vlib-api vnet svm vpp-api-test \ vpp-japi gmod vlib_configure_args_arm32 = --with-pre-data=128 +vnet_configure_args_arm32 = --with-dpdk --without-vcgn --without-ipsec --without-ipv6sr +vpp_configure_args_arm32 = --with-dpdk --without-vcgn --without-ipsec --without-ipv6sr + +arm32_dpdk_arch = "armv7a" +arm32_dpdk_target = "arm-armv7a-linuxapp-gcc" +arm32_dpdk_make_extra_args = "CPU_CFLAGS='-mfloat-abi=hard' \ + CONFIG_RTE_EAL_IGB_UIO=y \ + CONFIG_RTE_LIBRTE_E1000_PMD=y \ + CONFIG_RTE_MAX_LCORE=4 \ + CONFIG_RTE_MAX_NUMA_NODES=1" -vnet_configure_args_arm32 = --without-vcgn --without-ipsec --without-ipv6sr -vpp_configure_args_arm32 = --without-vcgn --without-ipsec --without-ipv6sr arm32_debug_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 -DVLIB_MAX_CPUS=4 -march=armv7-a \ -fstack-protector-all -fPIC -Werror diff --git a/dpdk/Makefile b/dpdk/Makefile index 5d05e6af..165058d9 100644 --- a/dpdk/Makefile +++ b/dpdk/Makefile @@ -38,7 +38,11 @@ else DPDK_CC=gcc endif + +ifeq (,$(DPDK_TARGET)) DPDK_TARGET := x86_64-native-linuxapp-$(DPDK_CC) +endif + JOBS := $(shell grep processor /proc/cpuinfo | wc -l) # compiler/linker custom arguments @@ -63,6 +67,10 @@ else ifeq ($(DPDK_MARCH),core-avx-i) DPDK_MACHINE:=ivb # Ivy Bridge else ifeq ($(DPDK_MARCH),core-avx2) DPDK_MACHINE:=hsw # Haswell +else ifeq ($(DPDK_MARCH),armv7a) +DPDK_MACHINE:=armv7a # ARMv7 +else ifeq ($(DPDK_MARCH),armv8a) +DPDK_MACHINE:=armv8a # ARMv8 else $(error Unknown DPDK_MARCH) endif @@ -75,7 +83,8 @@ DPDK_MAKE_ARGS := -C $(DPDK_SOURCE) -j $(JOBS) \ EXTRA_CFLAGS="$(DPDK_EXTRA_CFLAGS)" \ EXTRA_LDFLAGS="$(DPDK_EXTRA_LDFLAGS)" \ CPU_CFLAGS="$(DPDK_CPU_CFLAGS)" \ - CPU_LDFLAGS="$(DPDK_CPU_LDFLAGS)" + CPU_LDFLAGS="$(DPDK_CPU_LDFLAGS)" \ + $(DPDK_MAKE_EXTRA_ARGS) DPDK_SOURCE_FILES := $(shell [ -e $(DPDK_SOURCE) ] && find $(DPDK_SOURCE) -name "*.[chS]") -- cgit 1.2.3-korg From 1c80e831b728ab378949714d5059a0b5b1822a0a Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Wed, 11 May 2016 23:07:18 +0200 Subject: Add support for multiple microarchitectures in single binary * compiler -march= parameter is changed from native to corei7 so code is always genereted with instructions which are available on the Nehalem microarchitecture (up to SSE4.2) * compiler -mtune= parameter is added so code is optimized for corei7-avx which equals to Sandy Bridge microarchitecture * set of macros is added which allows run-time detection of available cpu instructions (e.g. clib_cpu_supports_avx()) * set of macros is added which allows us to clone graph node funcitons where cloned function is optmized for different microarchitecture Those macros are using following attributes: __attribute__((flatten)) __attribute__((target("arch=core-avx2))) I.e. If applied to foo_node_fn() macro will generate cloned functions foo_node_fn_avx2() and foo_node_fn_avx512() (future) It will also generate function void * foo_node_fn_multiarch_select() which detects available instruction set and returns pointer to the best matching function clone. Change-Id: I2dce0ac92a5ede95fcb56f47f3d1f3c4c040bac0 Signed-off-by: Damjan Marion --- build-data/packages/dpdk.mk | 6 +++ build-data/platforms/vpp.mk | 7 +++- build-data/platforms/vpp_lite.mk | 6 ++- build-root/Makefile | 5 +++ dpdk/Makefile | 3 +- vlib/vlib/node.h | 27 ++++++++++++ vnet/vnet/classify/ip_classify.c | 4 ++ vnet/vnet/cop/ip4_whitelist.c | 2 + vnet/vnet/cop/ip6_whitelist.c | 2 + vnet/vnet/cop/node1.c | 2 + vnet/vnet/devices/af_packet/device.c | 3 ++ vnet/vnet/devices/af_packet/node.c | 4 +- vnet/vnet/devices/dpdk/cli.c | 8 ++++ vnet/vnet/devices/dpdk/device.c | 3 ++ vnet/vnet/devices/dpdk/dpdk.h | 5 ++- vnet/vnet/devices/dpdk/init.c | 8 ++-- vnet/vnet/devices/dpdk/node.c | 50 +++++++++++++++++++--- vnet/vnet/devices/netmap/device.c | 3 ++ vnet/vnet/devices/netmap/node.c | 3 +- vnet/vnet/devices/ssvm/node.c | 2 + vnet/vnet/devices/ssvm/ssvm_eth.c | 3 ++ vnet/vnet/devices/virtio/vhost-user.c | 5 +++ vnet/vnet/ethernet/node.c | 6 +++ vnet/vnet/gre/gre.c | 3 ++ vnet/vnet/gre/node.c | 2 + vnet/vnet/interface.h | 26 ++++++++++++ vnet/vnet/interface_output.c | 6 +++ vnet/vnet/ip/ip4_forward.c | 18 ++++++++ vnet/vnet/ip/ip4_hop_by_hop.c | 2 + vnet/vnet/ip/ip4_input.c | 4 ++ vnet/vnet/ip/ip4_source_check.c | 6 +++ vnet/vnet/ip/ip6_forward.c | 16 +++++++ vnet/vnet/ip/ip6_hop_by_hop.c | 5 +++ vnet/vnet/ip/ip6_input.c | 2 + vnet/vnet/ip/ip_input_acl.c | 4 ++ vnet/vnet/ip/udp_local.c | 4 ++ vnet/vnet/ipsec/esp_decrypt.c | 2 + vnet/vnet/ipsec/esp_encrypt.c | 2 + vnet/vnet/ipsec/ipsec_if_in.c | 5 ++- vnet/vnet/ipsec/ipsec_if_out.c | 2 + vnet/vnet/ipsec/ipsec_input.c | 7 ++++ vnet/vnet/ipsec/ipsec_output.c | 2 + vnet/vnet/l2/l2_classify.c | 2 + vnet/vnet/l2/l2_efp_filter.c | 2 + vnet/vnet/l2/l2_flood.c | 2 + vnet/vnet/l2/l2_fwd.c | 2 + vnet/vnet/l2/l2_input.c | 2 + vnet/vnet/l2/l2_input_acl.c | 2 + vnet/vnet/l2/l2_input_vtr.c | 2 + vnet/vnet/l2/l2_learn.c | 1 + vnet/vnet/l2/l2_output.c | 2 + vnet/vnet/l2/l2_output_acl.c | 2 + vnet/vnet/l2/l2_patch.c | 2 + vnet/vnet/l2/l2_rw.c | 2 + vnet/vnet/l2/l2_xcrw.c | 2 + vnet/vnet/l2tp/decap.c | 2 + vnet/vnet/l2tp/encap.c | 2 + vnet/vnet/lawful-intercept/node.c | 2 + vnet/vnet/mpls-gre/interface.c | 7 ++++ vnet/vnet/mpls-gre/node.c | 4 ++ vnet/vnet/mpls-gre/policy_encap.c | 2 + vnet/vnet/policer/node_funcs.c | 3 ++ vnet/vnet/sr/sr.c | 6 +++ vnet/vnet/sr/sr_replicate.c | 2 + vnet/vnet/vxlan/decap.c | 5 +++ vnet/vnet/vxlan/encap.c | 3 ++ vpp/app/l2t_ip6.c | 2 + vpp/app/l2t_l2.c | 2 + vpp/app/version.c | 1 + vpp/vnet/main.c | 19 +++++---- vppinfra/vppinfra/cpu.c | 23 ++++++++--- vppinfra/vppinfra/cpu.h | 78 ++++++++++++++++++++++++++++++++++- 72 files changed, 439 insertions(+), 34 deletions(-) (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index 2bfc4b49..0a4c1610 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -4,6 +4,11 @@ ifeq ($(DPDK_MARCH),) DPDK_MARCH="native" endif +DPDK_TUNE = $(strip $($(PLATFORM)_mtune)) +ifeq ($(DPDK_TUNE),) + DPDK_MARCH="generic" +endif + ifneq (,$(findstring debug,$(TAG))) DPDK_DEBUG=y else @@ -14,6 +19,7 @@ DPDK_MAKE_ARGS = -C $(call find_source_fn,$(PACKAGE_SOURCE)) \ DPDK_BUILD_DIR=$(PACKAGE_BUILD_DIR) \ DPDK_INSTALL_DIR=$(PACKAGE_INSTALL_DIR) \ DPDK_MARCH=$(DPDK_MARCH) \ + DPDK_TUNE=$(DPDK_TUNE) \ DPDK_DEBUG=$(DPDK_DEBUG) diff --git a/build-data/platforms/vpp.mk b/build-data/platforms/vpp.mk index c381be19..ec0d874d 100644 --- a/build-data/platforms/vpp.mk +++ b/build-data/platforms/vpp.mk @@ -13,6 +13,9 @@ # vector packet processor vpp_arch = native +vpp_march = corei7 # Nehalem Instruction set +vpp_mtune = corei7-avx # Optimize for Sandy Bridge +vpp_dpdk_arch = corei7 vpp_native_tools = vppapigen vpp_uses_dpdk = yes @@ -40,9 +43,9 @@ vpp_debug_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 -march=$(MARCH) \ vpp_debug_TAG_LDFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 -march=$(MARCH) \ -fstack-protector-all -fPIC -Werror -vpp_TAG_CFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) \ +vpp_TAG_CFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) -mtune=$(MTUNE) \ -fstack-protector -fPIC -Werror -vpp_TAG_LDFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) \ +vpp_TAG_LDFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) -mtune=$(MTUNE) \ -fstack-protector -fPIC -Werror vpp_gcov_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -march=$(MARCH) \ diff --git a/build-data/platforms/vpp_lite.mk b/build-data/platforms/vpp_lite.mk index 4183700e..d35d2347 100644 --- a/build-data/platforms/vpp_lite.mk +++ b/build-data/platforms/vpp_lite.mk @@ -13,6 +13,8 @@ # vector packet processor vpp_lite_arch = native +vpp_lite_march = corei7 # Nehalem Instruction set +vpp_lite_mtune = corei7-avx # Optimize for Sandy Bridge vpp_lite_native_tools = vppapigen vpp_lite_uses_dpdk = no @@ -30,7 +32,7 @@ vpp_lite_debug_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 -march=$(MARC vpp_lite_debug_TAG_LDFLAGS = -g -O0 -DCLIB_DEBUG -DFORTIFY_SOURCE=2 -march=$(MARCH) \ -fstack-protector-all -fPIC -Werror -vpp_lite_TAG_CFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) \ +vpp_lite_TAG_CFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) -mtune=$(MTUNE) \ -fstack-protector -fPIC -Werror -vpp_lite_TAG_LDFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) \ +vpp_lite_TAG_LDFLAGS = -g -O2 -DFORTIFY_SOURCE=2 -march=$(MARCH) -mtune=$(MTUNE) \ -fstack-protector -fPIC -Werror diff --git a/build-root/Makefile b/build-root/Makefile index a60cbf0a..97fb43d4 100644 --- a/build-root/Makefile +++ b/build-root/Makefile @@ -220,6 +220,11 @@ else endif export MARCH +MTUNE = $(strip $($(PLATFORM)_mtune)) +ifeq ($(MTUNE),) + MTUNE = generic +endif + ###################################################################### # Generic build stuff ###################################################################### diff --git a/dpdk/Makefile b/dpdk/Makefile index 165058d9..b7e1e097 100644 --- a/dpdk/Makefile +++ b/dpdk/Makefile @@ -19,6 +19,7 @@ DPDK_INSTALL_DIR ?= $(CURDIR)/_install DPDK_PKTMBUF_HEADROOM ?= 128 DPDK_DOWNLOAD_DIR ?= $(HOME)/Downloads DPDK_MARCH ?= native +DPDK_TUNE ?= generic DPDK_DEBUG ?= n B := $(DPDK_BUILD_DIR) @@ -51,7 +52,7 @@ DPDK_CPU_LDFLAGS := DPDK_EXTRA_LDFLAGS := -g ifeq ($(DPDK_DEBUG),n) -DPDK_EXTRA_CFLAGS := -g +DPDK_EXTRA_CFLAGS := -g -mtune=$(DPDK_TUNE) else DPDK_EXTRA_CFLAGS := -g -O0 endif diff --git a/vlib/vlib/node.h b/vlib/vlib/node.h index 2caede6e..9b33a0a3 100644 --- a/vlib/vlib/node.h +++ b/vlib/vlib/node.h @@ -40,6 +40,7 @@ #ifndef included_vlib_node_h #define included_vlib_node_h +#include #include #include #include /* for vlib_trace_filter_t */ @@ -149,6 +150,32 @@ static void __vlib_add_node_registration_##x (void) \ } \ __VA_ARGS__ vlib_node_registration_t x +#if CLIB_DEBUG > 0 +#define VLIB_NODE_FUNCTION_CLONE_TEMPLATE(arch, fn) +#define VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn) +#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn) +#else +#define VLIB_NODE_FUNCTION_CLONE_TEMPLATE(arch, fn, tgt) \ + uword \ + __attribute__ ((flatten)) \ + __attribute__ ((target (tgt))) \ + CLIB_CPU_OPTIMIZED \ + fn ## _ ## arch ( struct vlib_main_t * vm, \ + struct vlib_node_runtime_t * node, \ + struct vlib_frame_t * frame) \ + { return fn (vm, node, frame); } + +#define VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn) \ + foreach_march_variant(VLIB_NODE_FUNCTION_CLONE_TEMPLATE, fn) + +#define VLIB_NODE_FUNCTION_MULTIARCH(node, fn) \ + VLIB_NODE_FUNCTION_MULTIARCH_CLONE(fn) \ + CLIB_MULTIARCH_SELECT_FN(fn, static inline) \ + static void __attribute__((__constructor__)) \ + __vlib_node_function_multiarch_select_##node (void) \ + { node.function = fn ## _multiarch_select(); } +#endif + always_inline vlib_node_registration_t * vlib_node_next_registered (vlib_node_registration_t * c) { diff --git a/vnet/vnet/classify/ip_classify.c b/vnet/vnet/classify/ip_classify.c index 8152f6ce..75e80ad6 100644 --- a/vnet/vnet/classify/ip_classify.c +++ b/vnet/vnet/classify/ip_classify.c @@ -329,6 +329,8 @@ VLIB_REGISTER_NODE (ip4_classify_node) = { .next_nodes = IP4_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_classify_node, ip4_classify) + static uword ip6_classify (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -350,6 +352,8 @@ VLIB_REGISTER_NODE (ip6_classify_node) = { .next_nodes = IP6_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_classify_node, ip6_classify) + static clib_error_t * ip_classify_init (vlib_main_t * vm) { diff --git a/vnet/vnet/cop/ip4_whitelist.c b/vnet/vnet/cop/ip4_whitelist.c index 6178e891..5578558c 100644 --- a/vnet/vnet/cop/ip4_whitelist.c +++ b/vnet/vnet/cop/ip4_whitelist.c @@ -348,6 +348,8 @@ VLIB_REGISTER_NODE (ip4_cop_whitelist_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_cop_whitelist_node, ip4_cop_whitelist_node_fn) + static clib_error_t * ip4_whitelist_init (vlib_main_t * vm) { diff --git a/vnet/vnet/cop/ip6_whitelist.c b/vnet/vnet/cop/ip6_whitelist.c index dc6a1ee5..4a8f33fb 100644 --- a/vnet/vnet/cop/ip6_whitelist.c +++ b/vnet/vnet/cop/ip6_whitelist.c @@ -286,6 +286,8 @@ VLIB_REGISTER_NODE (ip6_cop_whitelist_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_cop_whitelist_node, ip6_cop_whitelist_node_fn) + static clib_error_t * ip6_whitelist_init (vlib_main_t * vm) { diff --git a/vnet/vnet/cop/node1.c b/vnet/vnet/cop/node1.c index 3ee7006a..b448b531 100644 --- a/vnet/vnet/cop/node1.c +++ b/vnet/vnet/cop/node1.c @@ -282,6 +282,8 @@ VLIB_REGISTER_NODE (cop_input_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (cop_input_node, cop_input_node_fn) + #define foreach_cop_stub \ _(default-cop-whitelist, default_cop_whitelist) diff --git a/vnet/vnet/devices/af_packet/device.c b/vnet/vnet/devices/af_packet/device.c index f0e91487..0671d9e2 100644 --- a/vnet/vnet/devices/af_packet/device.c +++ b/vnet/vnet/devices/af_packet/device.c @@ -204,3 +204,6 @@ VNET_DEVICE_CLASS (af_packet_device_class) = { .subif_add_del_function = af_packet_subif_add_del_function, .no_flatten_output_chains = 1, }; + +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (af_packet_device_class, + af_packet_interface_tx) diff --git a/vnet/vnet/devices/af_packet/node.c b/vnet/vnet/devices/af_packet/node.c index b622a221..0c608ea4 100644 --- a/vnet/vnet/devices/af_packet/node.c +++ b/vnet/vnet/devices/af_packet/node.c @@ -267,7 +267,6 @@ af_packet_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, return n_rx_packets; } - VLIB_REGISTER_NODE (af_packet_input_node) = { .function = af_packet_input_fn, .name = "af-packet-input", @@ -283,3 +282,6 @@ VLIB_REGISTER_NODE (af_packet_input_node) = { [AF_PACKET_INPUT_NEXT_ETHERNET_INPUT] = "ethernet-input", }, }; + +VLIB_NODE_FUNCTION_MULTIARCH (af_packet_input_node, af_packet_input_fn) + diff --git a/vnet/vnet/devices/dpdk/cli.c b/vnet/vnet/devices/dpdk/cli.c index 9ec19867..9063cad8 100644 --- a/vnet/vnet/devices/dpdk/cli.c +++ b/vnet/vnet/devices/dpdk/cli.c @@ -759,6 +759,7 @@ set_efd (vlib_main_t *vm, unformat_input_t *input, dpdk_main_t * dm = &dpdk_main; vlib_thread_main_t * tm = vlib_get_thread_main(); clib_error_t * error = NULL; + vlib_node_runtime_t * rt = vlib_node_get_runtime (vm, dpdk_input_node.index); if (unformat(input, "enable")) { if (unformat(input, "dpdk")) { @@ -844,6 +845,13 @@ set_efd (vlib_main_t *vm, unformat_input_t *input, format_unformat_error, input); } + if (dm->efd.enabled) + rt->function = dpdk_input_efd_multiarch_select(); + else if (dm->use_rss) + rt->function = dpdk_input_rss_multiarch_select(); + else + rt->function = dpdk_input_multiarch_select(); + return error; } diff --git a/vnet/vnet/devices/dpdk/device.c b/vnet/vnet/devices/dpdk/device.c index ab85dfb4..a38c8d19 100644 --- a/vnet/vnet/devices/dpdk/device.c +++ b/vnet/vnet/devices/dpdk/device.c @@ -1184,6 +1184,9 @@ VNET_DEVICE_CLASS (dpdk_device_class) = { .name_renumber = dpdk_device_renumber, }; +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (dpdk_device_class, + dpdk_interface_tx) + void dpdk_set_flowcontrol_callback (vlib_main_t *vm, dpdk_flowcontrol_callback_t callback) { diff --git a/vnet/vnet/devices/dpdk/dpdk.h b/vnet/vnet/devices/dpdk/dpdk.h index 019d83f7..525cd8d1 100644 --- a/vnet/vnet/devices/dpdk/dpdk.h +++ b/vnet/vnet/devices/dpdk/dpdk.h @@ -584,8 +584,9 @@ dpdk_pmd_t dpdk_get_pmd_type (vnet_hw_interface_t *hi); i8 dpdk_get_cpu_socket (vnet_hw_interface_t *hi); -uword -dpdk_input_rss (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f); +void * dpdk_input_multiarch_select(); +void * dpdk_input_rss_multiarch_select(); +void * dpdk_input_efd_multiarch_select(); clib_error_t* dpdk_get_hw_interface_stats (u32 hw_if_index, struct rte_eth_stats* dest); diff --git a/vnet/vnet/devices/dpdk/init.c b/vnet/vnet/devices/dpdk/init.c index 63fa4c07..8ee59ff8 100644 --- a/vnet/vnet/devices/dpdk/init.c +++ b/vnet/vnet/devices/dpdk/init.c @@ -804,6 +804,7 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input) clib_error_t * error = 0; dpdk_main_t * dm = &dpdk_main; vlib_thread_main_t * tm = vlib_get_thread_main(); + vlib_node_runtime_t * rt = vlib_node_get_runtime (vm, dpdk_input_node.index); u8 * s, * tmp = 0; u8 * pci_dev_id = 0; u8 * rte_cmd = 0, * ethname = 0; @@ -1251,10 +1252,9 @@ dpdk_config (vlib_main_t * vm, unformat_input_t * input) } if (dm->use_rss) - { - vlib_node_runtime_t * rt = vlib_node_get_runtime (vm, dpdk_input_node.index); - rt->function = dpdk_input_rss; - } + rt->function = dpdk_input_rss_multiarch_select(); + else + rt->function = dpdk_input_multiarch_select(); done: return error; } diff --git a/vnet/vnet/devices/dpdk/node.c b/vnet/vnet/devices/dpdk/node.c index a7590a5c..ca94511b 100644 --- a/vnet/vnet/devices/dpdk/node.c +++ b/vnet/vnet/devices/dpdk/node.c @@ -251,6 +251,8 @@ VLIB_REGISTER_NODE (handoff_dispatch_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (handoff_dispatch_node, handoff_dispatch_node_fn) + clib_error_t *handoff_dispatch_init (vlib_main_t *vm) { handoff_dispatch_main_t * mp = &handoff_dispatch_main; @@ -488,7 +490,8 @@ static inline u32 dpdk_device_input ( dpdk_main_t * dm, dpdk_device_t * xd, vlib_node_runtime_t * node, u32 cpu_index, - u16 queue_id) + u16 queue_id, + int use_efd) { u32 n_buffers; u32 next_index = DPDK_RX_NEXT_ETHERNET_INPUT; @@ -510,7 +513,7 @@ static inline u32 dpdk_device_input ( dpdk_main_t * dm, if (n_buffers == 0) { /* check if EFD (dpdk) is enabled */ - if (PREDICT_FALSE(dm->efd.enabled)) + if (PREDICT_FALSE(use_efd && dm->efd.enabled)) { /* reset a few stats */ xd->efd_agent.last_poll_time = 0; @@ -546,7 +549,7 @@ static inline u32 dpdk_device_input ( dpdk_main_t * dm, /* Check for congestion if EFD (Early-Fast-Discard) is enabled * in any mode (e.g. dpdk, monitor, or drop_all) */ - if (PREDICT_FALSE(dm->efd.enabled)) + if (PREDICT_FALSE(use_efd && dm->efd.enabled)) { /* update EFD counters */ dpdk_efd_update_counters(xd, n_buffers, dm->efd.enabled); @@ -793,7 +796,7 @@ dpdk_input (vlib_main_t * vm, { xd = vec_elt_at_index(dm->devices, dq->device); ASSERT(dq->queue_id == 0); - n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, 0); + n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, 0, 0); } VIRL_SPEED_LIMIT() @@ -818,7 +821,7 @@ dpdk_input_rss (vlib_main_t * vm, vec_foreach (dq, dm->devices_by_cpu[cpu_index]) { xd = vec_elt_at_index(dm->devices, dq->device); - n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, dq->queue_id); + n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, dq->queue_id, 0); } VIRL_SPEED_LIMIT() @@ -826,6 +829,32 @@ dpdk_input_rss (vlib_main_t * vm, return n_rx_packets; } +uword +dpdk_input_efd (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * f) +{ + dpdk_main_t * dm = &dpdk_main; + dpdk_device_t * xd; + uword n_rx_packets = 0; + dpdk_device_and_queue_t * dq; + u32 cpu_index = os_get_cpu_number(); + + /* + * Poll all devices on this cpu for input/interrupts. + */ + vec_foreach (dq, dm->devices_by_cpu[cpu_index]) + { + xd = vec_elt_at_index(dm->devices, dq->device); + n_rx_packets += dpdk_device_input (dm, xd, node, cpu_index, dq->queue_id, 1); + } + + VIRL_SPEED_LIMIT() + + return n_rx_packets; +} + + VLIB_REGISTER_NODE (dpdk_input_node) = { .function = dpdk_input, .type = VLIB_NODE_TYPE_INPUT, @@ -850,6 +879,17 @@ VLIB_REGISTER_NODE (dpdk_input_node) = { }, }; + +/* handle dpdk_input_rss alternative function */ +VLIB_NODE_FUNCTION_MULTIARCH_CLONE(dpdk_input) +VLIB_NODE_FUNCTION_MULTIARCH_CLONE(dpdk_input_rss) +VLIB_NODE_FUNCTION_MULTIARCH_CLONE(dpdk_input_efd) + +/* this macro defines dpdk_input_rss_multiarch_select() */ +CLIB_MULTIARCH_SELECT_FN(dpdk_input); +CLIB_MULTIARCH_SELECT_FN(dpdk_input_rss); +CLIB_MULTIARCH_SELECT_FN(dpdk_input_efd); + /* * Override the next nodes for the dpdk input nodes. * Must be invoked prior to VLIB_INIT_FUNCTION calls. diff --git a/vnet/vnet/devices/netmap/device.c b/vnet/vnet/devices/netmap/device.c index f04e0672..a966ffef 100644 --- a/vnet/vnet/devices/netmap/device.c +++ b/vnet/vnet/devices/netmap/device.c @@ -232,3 +232,6 @@ VNET_DEVICE_CLASS (netmap_device_class) = { .subif_add_del_function = netmap_subif_add_del_function, .no_flatten_output_chains = 1, }; + +VLIB_DEVICE_TX_FUNCTION_MULTIARCH(netmap_device_class, + netmap_interface_tx) diff --git a/vnet/vnet/devices/netmap/node.c b/vnet/vnet/devices/netmap/node.c index 3986c7e4..f4c39e62 100644 --- a/vnet/vnet/devices/netmap/node.c +++ b/vnet/vnet/devices/netmap/node.c @@ -270,7 +270,6 @@ netmap_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, return n_rx_packets; } - VLIB_REGISTER_NODE (netmap_input_node) = { .function = netmap_input_fn, .name = "netmap-input", @@ -287,3 +286,5 @@ VLIB_REGISTER_NODE (netmap_input_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (netmap_input_node, netmap_input_fn) + diff --git a/vnet/vnet/devices/ssvm/node.c b/vnet/vnet/devices/ssvm/node.c index 84625696..57b5fd22 100644 --- a/vnet/vnet/devices/ssvm/node.c +++ b/vnet/vnet/devices/ssvm/node.c @@ -334,3 +334,5 @@ VLIB_REGISTER_NODE (ssvm_eth_input_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ssvm_eth_input_node, ssvm_eth_input_node_fn) + diff --git a/vnet/vnet/devices/ssvm/ssvm_eth.c b/vnet/vnet/devices/ssvm/ssvm_eth.c index 49f2d5f8..7c65e212 100644 --- a/vnet/vnet/devices/ssvm/ssvm_eth.c +++ b/vnet/vnet/devices/ssvm/ssvm_eth.c @@ -474,3 +474,6 @@ VNET_DEVICE_CLASS (ssvm_eth_device_class) = { .rx_redirect_to_node = ssvm_eth_set_interface_next_node, .no_flatten_output_chains = 1, }; + +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (ssvm_eth_device_class, + ssvm_eth_interface_tx) diff --git a/vnet/vnet/devices/virtio/vhost-user.c b/vnet/vnet/devices/virtio/vhost-user.c index 5902c42b..ef4993f9 100644 --- a/vnet/vnet/devices/virtio/vhost-user.c +++ b/vnet/vnet/devices/virtio/vhost-user.c @@ -1144,6 +1144,8 @@ VLIB_REGISTER_NODE (vhost_user_input_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (vhost_user_input_node, vhost_user_input) + static uword vhost_user_intfc_tx (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -1373,6 +1375,9 @@ VNET_DEVICE_CLASS (vhost_user_dev_class,static) = { .no_flatten_output_chains = 1, }; +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (vhost_user_dev_class, + vhost_user_intfc_tx) + static uword vhost_user_process (vlib_main_t * vm, vlib_node_runtime_t * rt, diff --git a/vnet/vnet/ethernet/node.c b/vnet/vnet/ethernet/node.c index e8902fd7..226a66e9 100644 --- a/vnet/vnet/ethernet/node.c +++ b/vnet/vnet/ethernet/node.c @@ -945,6 +945,8 @@ VLIB_REGISTER_NODE (ethernet_input_node) = { .unformat_buffer = unformat_ethernet_header, }; +VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_node, ethernet_input) + VLIB_REGISTER_NODE (ethernet_input_type_node,static) = { .function = ethernet_input_type, .name = "ethernet-input-type", @@ -959,6 +961,8 @@ VLIB_REGISTER_NODE (ethernet_input_type_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_type_node, ethernet_input_type) + VLIB_REGISTER_NODE (ethernet_input_not_l2_node,static) = { .function = ethernet_input_not_l2, .name = "ethernet-input-not-l2", @@ -973,6 +977,8 @@ VLIB_REGISTER_NODE (ethernet_input_not_l2_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ethernet_input_not_l2_node, ethernet_input_not_l2) + void ethernet_set_rx_redirect (vnet_main_t * vnm, vnet_hw_interface_t * hi, u32 enable) diff --git a/vnet/vnet/gre/gre.c b/vnet/vnet/gre/gre.c index 075bd6fd..6d375159 100644 --- a/vnet/vnet/gre/gre.c +++ b/vnet/vnet/gre/gre.c @@ -454,6 +454,9 @@ VNET_DEVICE_CLASS (gre_device_class) = { #endif }; +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (gre_device_class, + gre_interface_tx) + VNET_HW_INTERFACE_CLASS (gre_hw_interface_class) = { .name = "GRE", diff --git a/vnet/vnet/gre/node.c b/vnet/vnet/gre/node.c index a91f7e9e..e33b2b05 100644 --- a/vnet/vnet/gre/node.c +++ b/vnet/vnet/gre/node.c @@ -434,6 +434,8 @@ VLIB_REGISTER_NODE (gre_input_node) = { .unformat_buffer = unformat_gre_header, }; +VLIB_NODE_FUNCTION_MULTIARCH (gre_input_node, gre_input) + void gre_register_input_protocol (vlib_main_t * vm, gre_protocol_t protocol, diff --git a/vnet/vnet/interface.h b/vnet/vnet/interface.h index 2829a0cc..30dcf276 100644 --- a/vnet/vnet/interface.h +++ b/vnet/vnet/interface.h @@ -163,6 +163,32 @@ static void __vnet_add_device_class_registration_##x (void) \ } \ __VA_ARGS__ vnet_device_class_t x +#define VLIB_DEVICE_TX_FUNCTION_CLONE_TEMPLATE(arch, fn, tgt) \ + uword \ + __attribute__ ((flatten)) \ + __attribute__ ((target (tgt))) \ + CLIB_CPU_OPTIMIZED \ + fn ## _ ## arch ( vlib_main_t * vm, \ + vlib_node_runtime_t * node, \ + vlib_frame_t * frame) \ + { return fn (vm, node, frame); } + +#define VLIB_DEVICE_TX_FUNCTION_MULTIARCH_CLONE(fn) \ + foreach_march_variant(VLIB_DEVICE_TX_FUNCTION_CLONE_TEMPLATE, fn) + +#if CLIB_DEBUG > 0 +#define VLIB_MULTIARCH_CLONE_AND_SELECT_FN(fn,...) +#define VLIB_DEVICE_TX_FUNCTION_MULTIARCH(dev, fn) +#else +#define VLIB_DEVICE_TX_FUNCTION_MULTIARCH(dev, fn) \ + VLIB_DEVICE_TX_FUNCTION_MULTIARCH_CLONE(fn) \ + CLIB_MULTIARCH_SELECT_FN(fn, static inline) \ + static void __attribute__((__constructor__)) \ + __vlib_device_tx_function_multiarch_select_##dev (void) \ + { dev.tx_function = fn ## _multiarch_select(); } +#endif + + /* Layer-2 (e.g. Ethernet) interface class. */ typedef struct _vnet_hw_interface_class { /* Index into main vector. */ diff --git a/vnet/vnet/interface_output.c b/vnet/vnet/interface_output.c index 04c1b7f5..9f9fb707 100644 --- a/vnet/vnet/interface_output.c +++ b/vnet/vnet/interface_output.c @@ -1140,6 +1140,8 @@ VLIB_REGISTER_NODE (drop_buffers,static) = { .validate_frame = validate_error_frame, }; +VLIB_NODE_FUNCTION_MULTIARCH (drop_buffers, process_drop) + VLIB_REGISTER_NODE (punt_buffers,static) = { .function = process_punt, .flags = (VLIB_NODE_FLAG_FRAME_NO_FREE_AFTER_DISPATCH @@ -1150,12 +1152,16 @@ VLIB_REGISTER_NODE (punt_buffers,static) = { .validate_frame = validate_error_frame, }; +VLIB_NODE_FUNCTION_MULTIARCH (punt_buffers, process_punt) + VLIB_REGISTER_NODE (vnet_per_buffer_interface_output_node,static) = { .function = vnet_per_buffer_interface_output, .name = "interface-output", .vector_size = sizeof (u32), }; +VLIB_NODE_FUNCTION_MULTIARCH (vnet_per_buffer_interface_output_node, vnet_per_buffer_interface_output) + clib_error_t * vnet_per_buffer_interface_output_hw_interface_add_del (vnet_main_t * vnm, u32 hw_if_index, diff --git a/vnet/vnet/ip/ip4_forward.c b/vnet/vnet/ip/ip4_forward.c index a84b83bc..ae2f9eea 100644 --- a/vnet/vnet/ip/ip4_forward.c +++ b/vnet/vnet/ip/ip4_forward.c @@ -1354,6 +1354,8 @@ VLIB_REGISTER_NODE (ip4_lookup_node) = { .next_nodes = IP4_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_lookup_node, ip4_lookup) + static uword ip4_indirect (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -1373,6 +1375,8 @@ VLIB_REGISTER_NODE (ip4_indirect_node) = { .next_nodes = IP4_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_indirect_node, ip4_indirect) + /* Global IP4 main. */ ip4_main_t ip4_main; @@ -1612,6 +1616,8 @@ VLIB_REGISTER_NODE (ip4_drop_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_drop_node, ip4_drop) + VLIB_REGISTER_NODE (ip4_punt_node,static) = { .function = ip4_punt, .name = "ip4-punt", @@ -1625,6 +1631,8 @@ VLIB_REGISTER_NODE (ip4_punt_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_punt_node, ip4_punt) + VLIB_REGISTER_NODE (ip4_miss_node,static) = { .function = ip4_miss, .name = "ip4-miss", @@ -1638,6 +1646,8 @@ VLIB_REGISTER_NODE (ip4_miss_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_miss_node, ip4_miss) + /* Compute TCP/UDP/ICMP4 checksum in software. */ u16 ip4_tcp_udp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0, @@ -2076,6 +2086,8 @@ VLIB_REGISTER_NODE (ip4_local_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_local_node, ip4_local) + void ip4_register_protocol (u32 protocol, u32 node_index) { vlib_main_t * vm = vlib_get_main(); @@ -2743,6 +2755,8 @@ VLIB_REGISTER_NODE (ip4_rewrite_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_node, ip4_rewrite_transit) + VLIB_REGISTER_NODE (ip4_rewrite_local_node,static) = { .function = ip4_rewrite_local, .name = "ip4-rewrite-local", @@ -2759,6 +2773,8 @@ VLIB_REGISTER_NODE (ip4_rewrite_local_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_rewrite_local_node, ip4_rewrite_local) + static clib_error_t * add_del_interface_table (vlib_main_t * vm, unformat_input_t * input, @@ -3032,6 +3048,8 @@ VLIB_REGISTER_NODE (ip4_lookup_multicast_node,static) = { .next_nodes = IP4_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_lookup_multicast_node, ip4_lookup_multicast) + VLIB_REGISTER_NODE (ip4_multicast_node,static) = { .function = ip4_drop, .name = "ip4-multicast", diff --git a/vnet/vnet/ip/ip4_hop_by_hop.c b/vnet/vnet/ip/ip4_hop_by_hop.c index ae46040a..177feb74 100644 --- a/vnet/vnet/ip/ip4_hop_by_hop.c +++ b/vnet/vnet/ip/ip4_hop_by_hop.c @@ -233,6 +233,8 @@ VLIB_REGISTER_NODE (ip4_hop_by_hop_node) = { .next_nodes = IP4_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_hop_by_hop_node, ip4_hop_by_hop_node_fn) + VLIB_REGISTER_NODE (ip4_add_hop_by_hop_node) = { .function = ip4_hop_by_hop_node_fn, .name = "ip4-add-hop-by-hop", diff --git a/vnet/vnet/ip/ip4_input.c b/vnet/vnet/ip/ip4_input.c index f31df0f6..60634250 100644 --- a/vnet/vnet/ip/ip4_input.c +++ b/vnet/vnet/ip/ip4_input.c @@ -371,6 +371,8 @@ VLIB_REGISTER_NODE (ip4_input_node) = { .format_trace = format_ip4_input_trace, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_input_node, ip4_input) + VLIB_REGISTER_NODE (ip4_input_no_checksum_node,static) = { .function = ip4_input_no_checksum, .name = "ip4-input-no-checksum", @@ -389,6 +391,8 @@ VLIB_REGISTER_NODE (ip4_input_no_checksum_node,static) = { .format_trace = format_ip4_input_trace, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_input_no_checksum_node, ip4_input_no_checksum) + static clib_error_t * ip4_init (vlib_main_t * vm) { clib_error_t * error; diff --git a/vnet/vnet/ip/ip4_source_check.c b/vnet/vnet/ip/ip4_source_check.c index 47e22f23..11e6678e 100644 --- a/vnet/vnet/ip/ip4_source_check.c +++ b/vnet/vnet/ip/ip4_source_check.c @@ -297,6 +297,9 @@ VLIB_REGISTER_NODE (ip4_check_source_reachable_via_any) = { .format_trace = format_ip4_source_check_trace, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_check_source_reachable_via_any, + ip4_source_check_reachable_via_any) + VLIB_REGISTER_NODE (ip4_check_source_reachable_via_rx) = { .function = ip4_source_check_reachable_via_rx, .name = "ip4-source-check-via-rx", @@ -311,6 +314,9 @@ VLIB_REGISTER_NODE (ip4_check_source_reachable_via_rx) = { .format_trace = format_ip4_source_check_trace, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_check_source_reachable_via_rx, + ip4_source_check_reachable_via_rx) + static clib_error_t * set_ip_source_check (vlib_main_t * vm, unformat_input_t * input, diff --git a/vnet/vnet/ip/ip6_forward.c b/vnet/vnet/ip/ip6_forward.c index a136da3e..7093c571 100644 --- a/vnet/vnet/ip/ip6_forward.c +++ b/vnet/vnet/ip/ip6_forward.c @@ -1260,6 +1260,8 @@ VLIB_REGISTER_NODE (ip6_lookup_node) = { .next_nodes = IP6_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_lookup_node, ip6_lookup) + static uword ip6_indirect (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -1278,6 +1280,8 @@ VLIB_REGISTER_NODE (ip6_indirect_node) = { .next_nodes = IP6_LOOKUP_NEXT_NODES, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_indirect_node, ip6_indirect) + typedef struct { /* Adjacency taken. */ u32 adj_index; @@ -1454,6 +1458,8 @@ VLIB_REGISTER_NODE (ip6_drop_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_drop_node, ip6_drop) + VLIB_REGISTER_NODE (ip6_punt_node,static) = { .function = ip6_punt, .name = "ip6-punt", @@ -1467,6 +1473,8 @@ VLIB_REGISTER_NODE (ip6_punt_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_punt_node, ip6_punt) + VLIB_REGISTER_NODE (ip6_miss_node,static) = { .function = ip6_miss, .name = "ip6-miss", @@ -1480,6 +1488,8 @@ VLIB_REGISTER_NODE (ip6_miss_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_miss_node, ip6_miss) + VLIB_REGISTER_NODE (ip6_multicast_node,static) = { .function = ip6_drop, .name = "ip6-multicast", @@ -1858,6 +1868,8 @@ VLIB_REGISTER_NODE (ip6_local_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_local_node, ip6_local) + void ip6_register_protocol (u32 protocol, u32 node_index) { vlib_main_t * vm = vlib_get_main(); @@ -2424,6 +2436,8 @@ VLIB_REGISTER_NODE (ip6_rewrite_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_node, ip6_rewrite_transit) + VLIB_REGISTER_NODE (ip6_rewrite_local_node,static) = { .function = ip6_rewrite_local, .name = "ip6-rewrite-local", @@ -2439,6 +2453,8 @@ VLIB_REGISTER_NODE (ip6_rewrite_local_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_rewrite_local_node, ip6_rewrite_local) + /* Global IP6 main. */ ip6_main_t ip6_main; diff --git a/vnet/vnet/ip/ip6_hop_by_hop.c b/vnet/vnet/ip/ip6_hop_by_hop.c index 16650dde..045dbc7f 100644 --- a/vnet/vnet/ip/ip6_hop_by_hop.c +++ b/vnet/vnet/ip/ip6_hop_by_hop.c @@ -628,6 +628,8 @@ VLIB_REGISTER_NODE (ip6_hop_by_hop_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_hop_by_hop_node, ip6_hop_by_hop_node_fn) + /* The main h-b-h tracer will be invoked, no need to do much here */ typedef struct { u32 next_index; @@ -849,6 +851,7 @@ VLIB_REGISTER_NODE (ip6_add_hop_by_hop_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_add_hop_by_hop_node, ip6_add_hop_by_hop_node_fn) /* The main h-b-h tracer was already invoked, no need to do much here */ typedef struct { @@ -1162,6 +1165,8 @@ VLIB_REGISTER_NODE (ip6_pop_hop_by_hop_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_pop_hop_by_hop_node, + ip6_pop_hop_by_hop_node_fn) static clib_error_t * ip6_hop_by_hop_init (vlib_main_t * vm) diff --git a/vnet/vnet/ip/ip6_input.c b/vnet/vnet/ip/ip6_input.c index f96a1cfb..2042cbd7 100644 --- a/vnet/vnet/ip/ip6_input.c +++ b/vnet/vnet/ip/ip6_input.c @@ -305,6 +305,8 @@ VLIB_REGISTER_NODE (ip6_input_node) = { .format_trace = format_ip6_input_trace, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_input_node, ip6_input) + static clib_error_t * ip6_init (vlib_main_t * vm) { ethernet_register_input_type (vm, ETHERNET_TYPE_IP6, diff --git a/vnet/vnet/ip/ip_input_acl.c b/vnet/vnet/ip/ip_input_acl.c index e905ed15..fcf8eeab 100644 --- a/vnet/vnet/ip/ip_input_acl.c +++ b/vnet/vnet/ip/ip_input_acl.c @@ -369,6 +369,8 @@ VLIB_REGISTER_NODE (ip4_inacl_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip4_inacl_node, ip4_inacl) + static uword ip6_inacl (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -392,6 +394,8 @@ VLIB_REGISTER_NODE (ip6_inacl_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ip6_inacl_node, ip6_inacl) + static clib_error_t * ip_inacl_init (vlib_main_t * vm) { diff --git a/vnet/vnet/ip/udp_local.c b/vnet/vnet/ip/udp_local.c index 253ad0f3..354dd4e8 100644 --- a/vnet/vnet/ip/udp_local.c +++ b/vnet/vnet/ip/udp_local.c @@ -327,6 +327,8 @@ VLIB_REGISTER_NODE (udp4_input_node) = { .unformat_buffer = unformat_udp_header, }; +VLIB_NODE_FUNCTION_MULTIARCH (udp4_input_node, udp4_input) + VLIB_REGISTER_NODE (udp6_input_node) = { .function = udp6_input, .name = "ip6-udp-lookup", @@ -350,6 +352,8 @@ VLIB_REGISTER_NODE (udp6_input_node) = { .unformat_buffer = unformat_udp_header, }; +VLIB_NODE_FUNCTION_MULTIARCH (udp6_input_node, udp6_input) + static void add_dst_port (udp_main_t * um, udp_dst_port_t dst_port, char * dst_port_name, u8 is_ip4) diff --git a/vnet/vnet/ipsec/esp_decrypt.c b/vnet/vnet/ipsec/esp_decrypt.c index 958a4d67..7af88b23 100644 --- a/vnet/vnet/ipsec/esp_decrypt.c +++ b/vnet/vnet/ipsec/esp_decrypt.c @@ -425,3 +425,5 @@ VLIB_REGISTER_NODE (esp_decrypt_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (esp_decrypt_node, esp_decrypt_node_fn) + diff --git a/vnet/vnet/ipsec/esp_encrypt.c b/vnet/vnet/ipsec/esp_encrypt.c index 39bbf2e4..d1dbcf96 100644 --- a/vnet/vnet/ipsec/esp_encrypt.c +++ b/vnet/vnet/ipsec/esp_encrypt.c @@ -387,3 +387,5 @@ VLIB_REGISTER_NODE (esp_encrypt_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (esp_encrypt_node, esp_encrypt_node_fn) + diff --git a/vnet/vnet/ipsec/ipsec_if_in.c b/vnet/vnet/ipsec/ipsec_if_in.c index 517f8bff..5a8a6858 100644 --- a/vnet/vnet/ipsec/ipsec_if_in.c +++ b/vnet/vnet/ipsec/ipsec_if_in.c @@ -148,4 +148,7 @@ VLIB_REGISTER_NODE (ipsec_if_input_node) = { [IPSEC_IF_INPUT_NEXT_ESP_DECRYPT] = "esp-decrypt", [IPSEC_IF_INPUT_NEXT_DROP] = "error-drop", }, -}; \ No newline at end of file +}; + +VLIB_NODE_FUNCTION_MULTIARCH (ipsec_if_input_node, ipsec_if_input_node_fn) + diff --git a/vnet/vnet/ipsec/ipsec_if_out.c b/vnet/vnet/ipsec/ipsec_if_out.c index 1e1dd528..9573c4f6 100644 --- a/vnet/vnet/ipsec/ipsec_if_out.c +++ b/vnet/vnet/ipsec/ipsec_if_out.c @@ -138,3 +138,5 @@ VLIB_REGISTER_NODE (ipsec_if_output_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ipsec_if_output_node, ipsec_if_output_node_fn) + diff --git a/vnet/vnet/ipsec/ipsec_input.c b/vnet/vnet/ipsec/ipsec_input.c index 3cd60ba1..09acd106 100644 --- a/vnet/vnet/ipsec/ipsec_input.c +++ b/vnet/vnet/ipsec/ipsec_input.c @@ -288,6 +288,9 @@ VLIB_REGISTER_NODE (ipsec_input_ip4_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip4_node, + ipsec_input_ip4_node_fn) + static vlib_node_registration_t ipsec_input_ip6_node; @@ -406,3 +409,7 @@ VLIB_REGISTER_NODE (ipsec_input_ip6_node,static) = { #undef _ }, }; + +VLIB_NODE_FUNCTION_MULTIARCH (ipsec_input_ip6_node, + ipsec_input_ip6_node_fn) + diff --git a/vnet/vnet/ipsec/ipsec_output.c b/vnet/vnet/ipsec/ipsec_output.c index 509b1e2f..93554681 100644 --- a/vnet/vnet/ipsec/ipsec_output.c +++ b/vnet/vnet/ipsec/ipsec_output.c @@ -405,6 +405,8 @@ VLIB_REGISTER_NODE (ipsec_output_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (ipsec_output_node, ipsec_output_node_fn) + #else /* IPSEC > 1 */ /* Dummy ipsec output node, in case when IPSec is disabled */ diff --git a/vnet/vnet/l2/l2_classify.c b/vnet/vnet/l2/l2_classify.c index 449dea72..765bc686 100644 --- a/vnet/vnet/l2/l2_classify.c +++ b/vnet/vnet/l2/l2_classify.c @@ -399,6 +399,8 @@ VLIB_REGISTER_NODE (l2_classify_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_classify_node, l2_classify_node_fn) + clib_error_t *l2_classify_init (vlib_main_t *vm) { l2_classify_main_t * cm = &l2_classify_main; diff --git a/vnet/vnet/l2/l2_efp_filter.c b/vnet/vnet/l2/l2_efp_filter.c index b865c375..17b7eb3f 100644 --- a/vnet/vnet/l2/l2_efp_filter.c +++ b/vnet/vnet/l2/l2_efp_filter.c @@ -498,6 +498,8 @@ VLIB_REGISTER_NODE (l2_efp_filter_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_efp_filter_node, l2_efp_filter_node_fn) + clib_error_t *l2_efp_filter_init (vlib_main_t *vm) { l2_efp_filter_main_t * mp = &l2_efp_filter_main; diff --git a/vnet/vnet/l2/l2_flood.c b/vnet/vnet/l2/l2_flood.c index ca8c171c..9f71677c 100644 --- a/vnet/vnet/l2/l2_flood.c +++ b/vnet/vnet/l2/l2_flood.c @@ -442,6 +442,8 @@ VLIB_REGISTER_NODE (l2flood_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2flood_node, l2flood_node_fn) + clib_error_t *l2flood_init (vlib_main_t *vm) { l2flood_main_t * mp = &l2flood_main; diff --git a/vnet/vnet/l2/l2_fwd.c b/vnet/vnet/l2/l2_fwd.c index 88a6b69c..5af83a75 100644 --- a/vnet/vnet/l2/l2_fwd.c +++ b/vnet/vnet/l2/l2_fwd.c @@ -367,6 +367,8 @@ VLIB_REGISTER_NODE (l2fwd_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2fwd_node, l2fwd_node_fn) + clib_error_t *l2fwd_init (vlib_main_t *vm) { l2fwd_main_t * mp = &l2fwd_main; diff --git a/vnet/vnet/l2/l2_input.c b/vnet/vnet/l2/l2_input.c index 870aff68..dd3a8b75 100644 --- a/vnet/vnet/l2/l2_input.c +++ b/vnet/vnet/l2/l2_input.c @@ -433,6 +433,8 @@ VLIB_REGISTER_NODE (l2input_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2input_node, l2input_node_fn) + clib_error_t *l2input_init (vlib_main_t *vm) { l2input_main_t * mp = &l2input_main; diff --git a/vnet/vnet/l2/l2_input_acl.c b/vnet/vnet/l2/l2_input_acl.c index 49df0f65..68c005f1 100644 --- a/vnet/vnet/l2/l2_input_acl.c +++ b/vnet/vnet/l2/l2_input_acl.c @@ -371,6 +371,8 @@ VLIB_REGISTER_NODE (l2_inacl_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_inacl_node, l2_inacl_node_fn) + clib_error_t *l2_inacl_init (vlib_main_t *vm) { l2_inacl_main_t * mp = &l2_inacl_main; diff --git a/vnet/vnet/l2/l2_input_vtr.c b/vnet/vnet/l2/l2_input_vtr.c index bbef33a9..d0f2181b 100644 --- a/vnet/vnet/l2/l2_input_vtr.c +++ b/vnet/vnet/l2/l2_input_vtr.c @@ -293,6 +293,8 @@ VLIB_REGISTER_NODE (l2_invtr_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_invtr_node, l2_invtr_node_fn) + clib_error_t *l2_invtr_init (vlib_main_t *vm) { l2_invtr_main_t * mp = &l2_invtr_main; diff --git a/vnet/vnet/l2/l2_learn.c b/vnet/vnet/l2/l2_learn.c index a891cb3c..0d94e43d 100644 --- a/vnet/vnet/l2/l2_learn.c +++ b/vnet/vnet/l2/l2_learn.c @@ -415,6 +415,7 @@ VLIB_REGISTER_NODE (l2learn_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2learn_node, l2learn_node_fn) clib_error_t *l2learn_init (vlib_main_t *vm) { diff --git a/vnet/vnet/l2/l2_output.c b/vnet/vnet/l2/l2_output.c index a550d075..f5b22117 100644 --- a/vnet/vnet/l2/l2_output.c +++ b/vnet/vnet/l2/l2_output.c @@ -414,6 +414,8 @@ VLIB_REGISTER_NODE (l2output_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2output_node, l2output_node_fn) + clib_error_t *l2output_init (vlib_main_t *vm) { l2output_main_t * mp = &l2output_main; diff --git a/vnet/vnet/l2/l2_output_acl.c b/vnet/vnet/l2/l2_output_acl.c index f75345f1..b222255f 100644 --- a/vnet/vnet/l2/l2_output_acl.c +++ b/vnet/vnet/l2/l2_output_acl.c @@ -274,6 +274,8 @@ VLIB_REGISTER_NODE (l2_outacl_node,static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_outacl_node, l2_outacl_node_fn) + clib_error_t *l2_outacl_init (vlib_main_t *vm) { l2_outacl_main_t * mp = &l2_outacl_main; diff --git a/vnet/vnet/l2/l2_patch.c b/vnet/vnet/l2/l2_patch.c index 63be409d..0839142b 100644 --- a/vnet/vnet/l2/l2_patch.c +++ b/vnet/vnet/l2/l2_patch.c @@ -252,6 +252,8 @@ VLIB_REGISTER_NODE (l2_patch_node, static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_patch_node, l2_patch_node_fn) + int vnet_l2_patch_add_del (u32 rx_sw_if_index, u32 tx_sw_if_index, int is_add) { l2_patch_main_t * l2pm = &l2_patch_main; diff --git a/vnet/vnet/l2/l2_rw.c b/vnet/vnet/l2/l2_rw.c index 93580c24..b66a7d34 100644 --- a/vnet/vnet/l2/l2_rw.c +++ b/vnet/vnet/l2/l2_rw.c @@ -604,3 +604,5 @@ VLIB_REGISTER_NODE (l2_rw_node) = { .next_nodes = { [L2_RW_NEXT_DROP] = "error-drop"}, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_rw_node, l2_rw_node_fn) + diff --git a/vnet/vnet/l2/l2_xcrw.c b/vnet/vnet/l2/l2_xcrw.c index f5fe3ca1..00542a19 100644 --- a/vnet/vnet/l2/l2_xcrw.c +++ b/vnet/vnet/l2/l2_xcrw.c @@ -255,6 +255,8 @@ VLIB_REGISTER_NODE (l2_xcrw_node, static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2_xcrw_node, l2_xcrw_node_fn) + clib_error_t *l2_xcrw_init (vlib_main_t *vm) { l2_xcrw_main_t * mp = &l2_xcrw_main; diff --git a/vnet/vnet/l2tp/decap.c b/vnet/vnet/l2tp/decap.c index 1a2bc489..5f0d05c0 100644 --- a/vnet/vnet/l2tp/decap.c +++ b/vnet/vnet/l2tp/decap.c @@ -247,6 +247,8 @@ VLIB_REGISTER_NODE (l2t_decap_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2t_decap_node, l2t_decap_node_fn) + void l2tp_decap_init (void) { ip6_register_protocol (IP_PROTOCOL_L2TP, l2t_decap_node.index); diff --git a/vnet/vnet/l2tp/encap.c b/vnet/vnet/l2tp/encap.c index 8f26ab00..eca098cb 100644 --- a/vnet/vnet/l2tp/encap.c +++ b/vnet/vnet/l2tp/encap.c @@ -206,6 +206,8 @@ VLIB_REGISTER_NODE (l2t_encap_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2t_encap_node, l2t_encap_node_fn) + void l2tp_encap_init (vlib_main_t * vm) { l2tp_encap_runtime_t * rt; diff --git a/vnet/vnet/lawful-intercept/node.c b/vnet/vnet/lawful-intercept/node.c index 26514cc5..8701c323 100644 --- a/vnet/vnet/lawful-intercept/node.c +++ b/vnet/vnet/lawful-intercept/node.c @@ -272,6 +272,8 @@ VLIB_REGISTER_NODE (li_hit_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (li_hit_node, li_hit_node_fn) + #else #include diff --git a/vnet/vnet/mpls-gre/interface.c b/vnet/vnet/mpls-gre/interface.c index 408ca750..75cd022a 100644 --- a/vnet/vnet/mpls-gre/interface.c +++ b/vnet/vnet/mpls-gre/interface.c @@ -259,6 +259,9 @@ VNET_DEVICE_CLASS (mpls_gre_device_class) = { #endif }; +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (mpls_gre_device_class, + mpls_gre_interface_tx) + VNET_HW_INTERFACE_CLASS (mpls_gre_hw_interface_class) = { .name = "MPLS-GRE", .format_header = format_mpls_gre_header_with_length, @@ -510,6 +513,8 @@ VNET_DEVICE_CLASS (mpls_eth_device_class) = { #endif }; +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (mpls_eth_device_class, + mpls_eth_interface_tx) VNET_HW_INTERFACE_CLASS (mpls_eth_hw_interface_class) = { .name = "MPLS-ETH", @@ -676,6 +681,8 @@ VLIB_REGISTER_NODE (mpls_post_rewrite_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (mpls_post_rewrite_node, mpls_post_rewrite) + static u8 * mpls_gre_rewrite (mpls_main_t *mm, mpls_gre_tunnel_t * t) { ip4_header_t * ip0; diff --git a/vnet/vnet/mpls-gre/node.c b/vnet/vnet/mpls-gre/node.c index 6bf5f814..474e2e2a 100644 --- a/vnet/vnet/mpls-gre/node.c +++ b/vnet/vnet/mpls-gre/node.c @@ -278,6 +278,8 @@ VLIB_REGISTER_NODE (mpls_input_node) = { .unformat_buffer = unformat_mpls_gre_header, }; +VLIB_NODE_FUNCTION_MULTIARCH (mpls_input_node, mpls_input) + static uword mpls_ethernet_input (vlib_main_t * vm, vlib_node_runtime_t * node, @@ -310,6 +312,8 @@ VLIB_REGISTER_NODE (mpls_ethernet_input_node) = { .unformat_buffer = unformat_mpls_gre_header, }; +VLIB_NODE_FUNCTION_MULTIARCH (mpls_ethernet_input_node, mpls_ethernet_input) + static void mpls_setup_nodes (vlib_main_t * vm) { diff --git a/vnet/vnet/mpls-gre/policy_encap.c b/vnet/vnet/mpls-gre/policy_encap.c index b4439193..e3f4beb6 100644 --- a/vnet/vnet/mpls-gre/policy_encap.c +++ b/vnet/vnet/mpls-gre/policy_encap.c @@ -153,6 +153,8 @@ VLIB_REGISTER_NODE (mpls_policy_encap_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (mpls_policy_encap_node, mpls_policy_encap) + static clib_error_t * mpls_policy_encap_init (vlib_main_t * vm) { diff --git a/vnet/vnet/policer/node_funcs.c b/vnet/vnet/policer/node_funcs.c index 8a76e869..739ce455 100644 --- a/vnet/vnet/policer/node_funcs.c +++ b/vnet/vnet/policer/node_funcs.c @@ -324,6 +324,9 @@ VLIB_REGISTER_NODE (policer_by_sw_if_index_node, static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (policer_by_sw_if_index_node, + vnet_policer_by_sw_if_index); + int test_policer_add_del (u32 rx_sw_if_index, u8 *config_name, int is_add) diff --git a/vnet/vnet/sr/sr.c b/vnet/vnet/sr/sr.c index 46318a27..e0ef3181 100644 --- a/vnet/vnet/sr/sr.c +++ b/vnet/vnet/sr/sr.c @@ -653,6 +653,8 @@ VLIB_REGISTER_NODE (sr_rewrite_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (sr_rewrite_node, sr_rewrite) + static int ip6_delete_route_no_next_hop (ip6_address_t *dst_address_arg, u32 dst_address_length, u32 rx_table_id) @@ -1911,6 +1913,8 @@ VLIB_REGISTER_NODE (sr_fix_dst_addr_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (sr_fix_dst_addr_node, sr_fix_dst_addr) + static clib_error_t * sr_init (vlib_main_t * vm) { ip6_sr_main_t * sm = &sr_main; @@ -2560,6 +2564,8 @@ VLIB_REGISTER_NODE (sr_local_node, static) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (sr_local_node, sr_local) + ip6_sr_main_t * sr_get_main (vlib_main_t * vm) { vlib_call_init_function (vm, sr_init); diff --git a/vnet/vnet/sr/sr_replicate.c b/vnet/vnet/sr/sr_replicate.c index 80d04ba6..ccc01465 100644 --- a/vnet/vnet/sr/sr_replicate.c +++ b/vnet/vnet/sr/sr_replicate.c @@ -350,6 +350,8 @@ VLIB_REGISTER_NODE (sr_replicate_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (sr_replicate_node, sr_replicate_node_fn) + clib_error_t *sr_replicate_init (vlib_main_t *vm) { sr_replicate_main_t *msm = &sr_replicate_main; diff --git a/vnet/vnet/vxlan/decap.c b/vnet/vnet/vxlan/decap.c index bd61f4bb..00acd660 100644 --- a/vnet/vnet/vxlan/decap.c +++ b/vnet/vnet/vxlan/decap.c @@ -550,6 +550,8 @@ VLIB_REGISTER_NODE (vxlan4_input_node) = { // $$$$ .unformat_buffer = unformat_vxlan_header, }; +VLIB_NODE_FUNCTION_MULTIARCH (vxlan4_input_node, vxlan4_input) + VLIB_REGISTER_NODE (vxlan6_input_node) = { .function = vxlan6_input, .name = "vxlan6-input", @@ -570,3 +572,6 @@ VLIB_REGISTER_NODE (vxlan6_input_node) = { .format_trace = format_vxlan_rx_trace, // $$$$ .unformat_buffer = unformat_vxlan_header, }; + +VLIB_NODE_FUNCTION_MULTIARCH (vxlan6_input_node, vxlan6_input) + diff --git a/vnet/vnet/vxlan/encap.c b/vnet/vnet/vxlan/encap.c index ee5c7d5e..387a728a 100644 --- a/vnet/vnet/vxlan/encap.c +++ b/vnet/vnet/vxlan/encap.c @@ -586,3 +586,6 @@ VLIB_REGISTER_NODE (vxlan_encap_node) = { [VXLAN_ENCAP_NEXT_DROP] = "error-drop", }, }; + +VLIB_NODE_FUNCTION_MULTIARCH (vxlan_encap_node, vxlan_encap) + diff --git a/vpp/app/l2t_ip6.c b/vpp/app/l2t_ip6.c index ac24886a..8a1e23a9 100644 --- a/vpp/app/l2t_ip6.c +++ b/vpp/app/l2t_ip6.c @@ -274,6 +274,8 @@ static VLIB_REGISTER_NODE (sw6_ip6_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (sw6_ip6_node, ip6_l2t_node_fn) + static clib_error_t * l2tp_config (vlib_main_t * vm, unformat_input_t * input) { diff --git a/vpp/app/l2t_l2.c b/vpp/app/l2t_l2.c index 5c8327d5..f6385a5a 100644 --- a/vpp/app/l2t_l2.c +++ b/vpp/app/l2t_l2.c @@ -250,3 +250,5 @@ VLIB_REGISTER_NODE (l2t_l2_node) = { }, }; +VLIB_NODE_FUNCTION_MULTIARCH (l2t_l2_node, l2t_l2_node_fn) + diff --git a/vpp/app/version.c b/vpp/app/version.c index 588aadf2..22bec400 100644 --- a/vpp/app/version.c +++ b/vpp/app/version.c @@ -59,6 +59,7 @@ show_vpe_version_command_fn (vlib_main_t * vm, _("Compiler", "%s", vpe_compiler); _("CPU model name", "%U", format_cpu_model_name); _("CPU microarchitecture", "%U", format_cpu_uarch); + _("CPU flags", "%U", format_cpu_flags); _("Current PID", "%d", getpid()); #if DPDK > 0 _("DPDK Version", "%s", rte_version()); diff --git a/vpp/vnet/main.c b/vpp/vnet/main.c index f707994b..25400839 100644 --- a/vpp/vnet/main.c +++ b/vpp/vnet/main.c @@ -12,6 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include #include #include #include @@ -59,33 +61,32 @@ int main (int argc, char * argv[]) u32 size; void vlib_set_get_handoff_structure_cb (void *cb); -#if __x86_64__ && !defined(__clang__) - __builtin_cpu_init (); +#if __x86_64__ const char * msg = "ERROR: This binary requires CPU with %s extensions.\n"; #define _(a,b) \ - if (!__builtin_cpu_supports(a)) \ + if (!clib_cpu_supports_ ## a ()) \ { \ fprintf(stderr, msg, b); \ exit(1); \ } #if __AVX2__ - _("avx2", "AVX2") + _(avx2, "AVX2") #endif #if __AVX__ - _("avx", "AVX") + _(avx, "AVX") #endif #if __SSE4_2__ - _("sse4.2", "SSE4.2") + _(sse42, "SSE4.2") #endif #if __SSE4_1__ - _("sse4.1", "SSE4.1") + _(sse41, "SSE4.1") #endif #if __SSSE3__ - _("ssse3", "SSSE3") + _(ssse3, "SSSE3") #endif #if __SSE3__ - _("sse3", "SSE3") + _(sse3, "SSE3") #endif #undef _ #endif diff --git a/vppinfra/vppinfra/cpu.c b/vppinfra/vppinfra/cpu.c index f2dbaf1f..9008ee3d 100644 --- a/vppinfra/vppinfra/cpu.c +++ b/vppinfra/vppinfra/cpu.c @@ -16,10 +16,6 @@ #include #include -#if __x86_64__ -#include -#endif - #define foreach_x86_cpu_uarch \ _(0x06, 0x4f, "Broadwell", "Broadwell-EP/EX") \ _(0x06, 0x3d, "Broadwell", "Broadwell") \ @@ -108,4 +104,21 @@ format_cpu_model_name (u8 * s, va_list * args) #else /* ! __x86_64__ */ return format (s, "unknown"); #endif -} \ No newline at end of file +} + +u8 * +format_cpu_flags (u8 * s, va_list * args) +{ +#if __x86_64__ +#define _(flag, func, reg, bit) \ + if (clib_cpu_supports_ ## flag()) \ + s = format (s, #flag " "); + foreach_x86_64_flags + return s; +#undef _ +#else /* ! __x86_64__ */ + return format (s, "unknown"); +#endif +} + + diff --git a/vppinfra/vppinfra/cpu.h b/vppinfra/vppinfra/cpu.h index 79cdf74f..961af709 100644 --- a/vppinfra/vppinfra/cpu.h +++ b/vppinfra/vppinfra/cpu.h @@ -16,7 +16,83 @@ #ifndef included_clib_cpu_h #define included_clib_cpu_h +#include + +/* + * multiarchitecture support. Adding new entry will produce + * new graph node function variant optimized for specific cpu + * microarchitecture. + * Order is important for runtime selection, as 1st match wins... + */ + +#if __x86_64__ && CLIB_DEBUG == 0 +#define foreach_march_variant(macro, x) \ + macro(avx2, x, "arch=core-avx2") +#else +#define foreach_march_variant(macro, x) +#endif + + +#if __GNUC__ > 4 && !__clang__ +#define CLIB_CPU_OPTIMIZED __attribute__ ((optimize ("tree-vectorize"))) +#else +#define CLIB_CPU_OPTIMIZED +#endif + + +#define CLIB_MULTIARCH_ARCH_CHECK(arch, fn, tgt) \ + if (clib_cpu_supports_ ## arch()) \ + return & fn ## _ ##arch; + +#define CLIB_MULTIARCH_SELECT_FN(fn,...) \ + __VA_ARGS__ void * fn ## _multiarch_select(void) \ +{ \ + foreach_march_variant(CLIB_MULTIARCH_ARCH_CHECK, fn) \ + return & fn; \ +} + +#if __x86_64__ +#include "cpuid.h" + +#define foreach_x86_64_flags \ +_ (sse3, 1, ecx, 0) \ +_ (ssse3, 1, ecx, 9) \ +_ (sse41, 1, ecx, 19) \ +_ (sse42, 1, ecx, 20) \ +_ (avx, 1, ecx, 28) \ +_ (avx2, 7, ebx, 5) \ +_ (avx512f, 7, ebx, 16) \ +_ (aes, 1, ecx, 25) \ +_ (sha, 7, ebx, 29) + +static inline int +clib_get_cpuid(const u32 lev, u32 * eax, u32 *ebx, u32 * ecx, u32 * edx) +{ + if ((u32) __get_cpuid_max (0x80000000 & lev, 0) < lev) + return 0; + if (lev == 7) + __cpuid_count(lev, 0, *eax, *ebx, *ecx, *edx); + else + __cpuid(lev, *eax, *ebx, *ecx, *edx); + return 1; +} + + +#define _(flag, func, reg, bit) \ +static inline int \ +clib_cpu_supports_ ## flag() \ +{ \ + u32 __attribute__((unused)) eax, ebx = 0, ecx = 0, edx = 0; \ + clib_get_cpuid (func, &eax, &ebx, &ecx, &edx); \ + \ + return ((reg & (1 << bit)) != 0); \ +} + foreach_x86_64_flags +#undef _ +#endif + format_function_t format_cpu_uarch; format_function_t format_cpu_model_name; +format_function_t format_cpu_flags; -#endif \ No newline at end of file +#endif -- cgit 1.2.3-korg From b635c567d16cb942e9380bedd6cd9e59428da4eb Mon Sep 17 00:00:00 2001 From: Dave Barach Date: Fri, 20 May 2016 12:56:41 -0400 Subject: VPP-79: fix cross-compilation build break .../packages/dpdk.mk must not set $(TARGET). The Makefile fragment really only needed to use a temporary variable to control the dpdk Makefile. Simple fix: set $(DPDK_PLATFORM_TARGET) instead. Change-Id: Ieb61b603bc36ed708a1b1237dc6bc503e90a0b7b Signed-off-by: Dave Barach --- build-data/packages/dpdk.mk | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index 0a4c1610..f38b82bf 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -23,9 +23,9 @@ DPDK_MAKE_ARGS = -C $(call find_source_fn,$(PACKAGE_SOURCE)) \ DPDK_DEBUG=$(DPDK_DEBUG) -TARGET=$(strip $($(PLATFORM)_dpdk_target)) -ifneq ($(TARGET),) -DPDK_MAKE_ARGS += DPDK_TARGET=$(TARGET) +DPDK_PLATFORM_TARGET=$(strip $($(PLATFORM)_dpdk_target)) +ifneq ($(DPDK_PLATFORM_TARGET),) +DPDK_MAKE_ARGS += DPDK_TARGET=$(DPDK_PLATFORM_TARGET) endif DPDK_MAKE_EXTRA_ARGS = $(strip $($(PLATFORM)_dpdk_make_extra_args)) -- cgit 1.2.3-korg From 68c69d896736e12730a7a9a55ec3d7dcbbd19e99 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Fri, 27 May 2016 10:17:45 +0200 Subject: Fix dpdk march/mtune defaults Change-Id: I6e6940c8467a331b37da153bb8a2154c1d165261 Signed-off-by: Damjan Marion --- build-data/packages/dpdk.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index f38b82bf..f9163c87 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -6,7 +6,7 @@ endif DPDK_TUNE = $(strip $($(PLATFORM)_mtune)) ifeq ($(DPDK_TUNE),) - DPDK_MARCH="generic" + DPDK_TUNE="generic" endif ifneq (,$(findstring debug,$(TAG))) -- cgit 1.2.3-korg From a10f62b11e7a710fde628ae75fe5791e54caba0a Mon Sep 17 00:00:00 2001 From: Sergio Gonzalez Monroy Date: Fri, 25 Nov 2016 13:36:12 +0000 Subject: dpdk: add ipsec cryptodev support DPDK Cryptodev support and related IPsec ESP nodes using DPDK Cryptodev APIs. 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 The following nodes are added: * dpdk-crypto-input : polling input node * dpdk-esp-encrypt-post : internal node * dpdk-esp-decrypt-post : internal node Change-Id: I6dca9a890abaf4fb2a4fffce3fd08ac013e4d701 Signed-off-by: Zhang, Roy Fan Signed-off-by: Sergio Gonzalez Monroy --- build-data/packages/dpdk.mk | 4 + build-data/packages/vnet.mk | 3 + build-data/packages/vpp.mk | 3 + build-data/platforms/vpp.mk | 1 + doxygen/user_doc.md | 1 + dpdk/Makefile | 4 + vnet/Makefile.am | 17 +- vnet/configure.ac | 8 + vnet/vnet/devices/dpdk/ipsec/cli.c | 141 ++++++ vnet/vnet/devices/dpdk/ipsec/crypto_node.c | 209 ++++++++ vnet/vnet/devices/dpdk/ipsec/dir.dox | 18 + .../devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md | 73 +++ vnet/vnet/devices/dpdk/ipsec/esp.h | 268 ++++++++++ vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c | 549 ++++++++++++++++++++ vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c | 554 +++++++++++++++++++++ vnet/vnet/devices/dpdk/ipsec/ipsec.c | 313 ++++++++++++ vnet/vnet/devices/dpdk/ipsec/ipsec.h | 216 ++++++++ vnet/vnet/ipsec-gre/interface.c | 9 +- vnet/vnet/ipsec/esp.h | 151 ++++++ vnet/vnet/ipsec/esp_decrypt.c | 121 ----- vnet/vnet/ipsec/esp_encrypt.c | 25 - vnet/vnet/ipsec/ipsec.c | 31 +- vnet/vnet/ipsec/ipsec.h | 5 + vnet/vnet/ipsec/ipsec_cli.c | 1 - vnet/vnet/ipsec/ipsec_if.c | 39 ++ vnet/vnet/ipsec/ipsec_if_in.c | 10 +- vnet/vnet/ipsec/ipsec_if_out.c | 7 +- vnet/vnet/ipsec/ipsec_input.c | 8 +- vnet/vnet/ipsec/ipsec_output.c | 8 +- vpp/Makefile.am | 5 +- vpp/configure.ac | 8 + 31 files changed, 2651 insertions(+), 159 deletions(-) create mode 100644 vnet/vnet/devices/dpdk/ipsec/cli.c create mode 100644 vnet/vnet/devices/dpdk/ipsec/crypto_node.c create mode 100644 vnet/vnet/devices/dpdk/ipsec/dir.dox create mode 100644 vnet/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md create mode 100644 vnet/vnet/devices/dpdk/ipsec/esp.h create mode 100644 vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c create mode 100644 vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c create mode 100644 vnet/vnet/devices/dpdk/ipsec/ipsec.c create mode 100644 vnet/vnet/devices/dpdk/ipsec/ipsec.h (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index f9163c87..a529e365 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -22,6 +22,10 @@ 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 +endif DPDK_PLATFORM_TARGET=$(strip $($(PLATFORM)_dpdk_target)) ifneq ($(DPDK_PLATFORM_TARGET),) diff --git a/build-data/packages/vnet.mk b/build-data/packages/vnet.mk index cafb9393..399ca1b4 100644 --- a/build-data/packages/vnet.mk +++ b/build-data/packages/vnet.mk @@ -38,4 +38,7 @@ vnet_configure_depend += dpdk-install vnet_CPPFLAGS += $(call installed_includes_fn, dpdk) vnet_LDFLAGS += $(call installed_libs_fn, dpdk) endif +ifeq ($($(PLATFORM)_uses_dpdk_cryptodev),yes) +vnet_configure_args += --with-dpdk-crypto +endif endif diff --git a/build-data/packages/vpp.mk b/build-data/packages/vpp.mk index be10e17d..6831c6b8 100644 --- a/build-data/packages/vpp.mk +++ b/build-data/packages/vpp.mk @@ -45,4 +45,7 @@ vpp_configure_depend += dpdk-install vpp_CPPFLAGS += $(call installed_includes_fn, dpdk) vpp_LDFLAGS += $(call installed_libs_fn, dpdk) endif +ifeq ($($(PLATFORM)_uses_dpdk_cryptodev),yes) +vpp_configure_args += --with-dpdk-crypto +endif endif diff --git a/build-data/platforms/vpp.mk b/build-data/platforms/vpp.mk index 4fe7cc8f..15d4dc39 100644 --- a/build-data/platforms/vpp.mk +++ b/build-data/platforms/vpp.mk @@ -41,6 +41,7 @@ vlib_configure_args_vpp = --with-pre-data=128 plugins_configure_args_vpp = --with-dpdk # DPDK configuration parameters +# vpp_uses_dpdk_cryptodev = yes # vpp_uses_external_dpdk = yes # vpp_dpdk_inc_dir = /usr/include/dpdk # vpp_dpdk_lib_dir = /usr/lib diff --git a/doxygen/user_doc.md b/doxygen/user_doc.md index 59063764..2e87c877 100644 --- a/doxygen/user_doc.md +++ b/doxygen/user_doc.md @@ -6,6 +6,7 @@ Several modules provide operational, dataplane-user focused documentation. - [GUI guided user demo](https://wiki.fd.io/view/VPP_Sandbox/vpp-userdemo) - @subpage qos_doc - @subpage ipsec_gre_doc +- @subpage dpdk_crypto_ipsec_doc - @subpage map_doc - @subpage lldp_doc - @subpage ioam_plugin_doc diff --git a/dpdk/Makefile b/dpdk/Makefile index 2f5037df..46cc3db1 100644 --- a/dpdk/Makefile +++ b/dpdk/Makefile @@ -21,6 +21,7 @@ DPDK_DOWNLOAD_DIR ?= $(HOME)/Downloads DPDK_MARCH ?= native DPDK_TUNE ?= generic DPDK_DEBUG ?= n +DPDK_CRYPTO_PMD ?= n B := $(DPDK_BUILD_DIR) I := $(DPDK_INSTALL_DIR) @@ -118,6 +119,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)) @# not needed $(call set,RTE_LIBRTE_TIMER,n) $(call set,RTE_LIBRTE_CFGFILE,n) diff --git a/vnet/Makefile.am b/vnet/Makefile.am index 86b73906..d806785f 100644 --- a/vnet/Makefile.am +++ b/vnet/Makefile.am @@ -13,7 +13,7 @@ AUTOMAKE_OPTIONS = foreign subdir-objects -AM_CFLAGS = -Wall -Werror @DPDK@ @IPSEC@ @IPV6SR@ +AM_CFLAGS = -Wall -Werror @DPDK@ @DPDK_CRYPTO@ @IPSEC@ @IPV6SR@ libvnet_la_SOURCES = libvnetplugin_la_SOURCES = @@ -345,7 +345,15 @@ libvnet_la_SOURCES += \ vnet/ipsec/ikev2_cli.c \ vnet/ipsec/ikev2_payload.c \ vnet/ipsec/ikev2_format.c -endif +if WITH_DPDK_CRYPTO +libvnet_la_SOURCES += \ + vnet/devices/dpdk/ipsec/esp_encrypt.c \ + vnet/devices/dpdk/ipsec/esp_decrypt.c \ + vnet/devices/dpdk/ipsec/crypto_node.c \ + vnet/devices/dpdk/ipsec/cli.c \ + vnet/devices/dpdk/ipsec/ipsec.c +endif +endif libvnet_la_SOURCES += \ vnet/ipsec/ipsec_output.c @@ -355,6 +363,11 @@ nobase_include_HEADERS += \ vnet/ipsec/esp.h \ vnet/ipsec/ikev2.h \ vnet/ipsec/ikev2_priv.h +if WITH_DPDK_CRYPTO +nobase_include_HEADERS += \ + vnet/devices/dpdk/ipsec/ipsec.h \ + vnet/devices/dpdk/ipsec/esp.h +endif ######################################## # Layer 3 protocol: osi diff --git a/vnet/configure.ac b/vnet/configure.ac index 80de43af..6a5281b0 100644 --- a/vnet/configure.ac +++ b/vnet/configure.ac @@ -12,6 +12,11 @@ AC_ARG_WITH(dpdk, [with_dpdk=1], [with_dpdk=0]) +AC_ARG_WITH(dpdk_crypto, + AC_HELP_STRING([--with-dpdk-crypto],[Use DPDK cryptodev]), + [with_dpdk_crypto=1], + [with_dpdk_crypto=0]) + AC_ARG_WITH(ipsec, AC_HELP_STRING([--without-ipsec],[Disable ipsec]), [with_ipsec=0], @@ -27,6 +32,9 @@ AC_ARG_ENABLE(tests, [enable_tests=1], [enable_tests=0]) +AM_CONDITIONAL(WITH_DPDK_CRYPTO, test "$with_dpdk_crypto" = "1") +AC_SUBST(DPDK_CRYPTO,[-DDPDK_CRYPTO=${with_dpdk_crypto}]) + AM_CONDITIONAL(WITH_DPDK, test "$with_dpdk" = "1") AC_SUBST(DPDK,[-DDPDK=${with_dpdk}]) diff --git a/vnet/vnet/devices/dpdk/ipsec/cli.c b/vnet/vnet/devices/dpdk/ipsec/cli.c new file mode 100644 index 00000000..3b634e03 --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/cli.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016 Intel 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 + +static void +dpdk_ipsec_show_mapping (vlib_main_t * vm, u16 detail_display) +{ + dpdk_crypto_main_t *dcm = &dpdk_crypto_main; + vlib_thread_main_t *tm = vlib_get_thread_main (); + u32 i, skip_master; + + if (detail_display) + vlib_cli_output (vm, "worker\t%10s\t%15s\tdir\tdev\tqp\n", + "cipher", "auth"); + else + vlib_cli_output (vm, "worker\tcrypto device id(type)\n"); + + skip_master = vlib_num_workers () > 0; + + for (i = 0; i < tm->n_vlib_mains; i++) + { + uword key, data; + u32 cpu_index = vlib_mains[i]->cpu_index; + crypto_worker_main_t *cwm = &dcm->workers_main[cpu_index]; + u8 *s = 0; + + if (skip_master) + { + skip_master = 0; + continue; + } + + if (!detail_display) + { + i32 last_cdev = -1; + crypto_qp_data_t *qpd; + + s = format (s, "%u\t", cpu_index); + + /* *INDENT-OFF* */ + vec_foreach (qpd, cwm->qp_data) + { + u32 dev_id = qpd->dev_id; + + if ((u16) last_cdev != dev_id) + { + struct rte_cryptodev_info cdev_info; + + rte_cryptodev_info_get (dev_id, &cdev_info); + + s = format(s, "%u(%s)\t", dev_id, cdev_info.feature_flags & + RTE_CRYPTODEV_FF_HW_ACCELERATED ? "HW" : "SW"); + } + last_cdev = dev_id; + } + /* *INDENT-ON* */ + vlib_cli_output (vm, "%s", s); + } + else + { + char cipher_str[15], auth_str[15]; + struct rte_cryptodev_capabilities cap; + crypto_worker_qp_key_t *p_key = (crypto_worker_qp_key_t *) & key; + /* *INDENT-OFF* */ + hash_foreach (key, data, cwm->algo_qp_map, + ({ + cap.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC; + cap.sym.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER; + cap.sym.cipher.algo = p_key->cipher_algo; + check_algo_is_supported (&cap, cipher_str); + cap.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC; + cap.sym.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH; + cap.sym.auth.algo = p_key->auth_algo; + check_algo_is_supported (&cap, auth_str); + vlib_cli_output (vm, "%u\t%10s\t%15s\t%3s\t%u\t%u\n", + vlib_mains[i]->cpu_index, cipher_str, auth_str, + p_key->is_outbound ? "out" : "in", + cwm->qp_data[data].dev_id, + cwm->qp_data[data].qp_id); + })); + /* *INDENT-ON* */ + } + } +} + +static clib_error_t * +lcore_cryptodev_map_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + unformat_input_t _line_input, *line_input = &_line_input; + u16 detail = 0; + + if (!unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "verbose")) + detail = 1; + else + return clib_error_return (0, "parse error: '%U'", + format_unformat_error, line_input); + } + + unformat_free (line_input); + + dpdk_ipsec_show_mapping (vm, detail); + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (lcore_cryptodev_map, static) = { + .path = "show crypto device mapping", + .short_help = + "show cryptodev device mapping ", + .function = lcore_cryptodev_map_fn, +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/vnet/vnet/devices/dpdk/ipsec/crypto_node.c b/vnet/vnet/devices/dpdk/ipsec/crypto_node.c new file mode 100644 index 00000000..37d5e5fa --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/crypto_node.c @@ -0,0 +1,209 @@ +/* + *------------------------------------------------------------------ + * crypto_node.c - DPDK Cryptodev input node + * + * Copyright (c) 2016 Intel 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 + +#define foreach_dpdk_crypto_input_next \ + _(DROP, "error-drop") \ + _(ENCRYPT_POST, "dpdk-esp-encrypt-post") \ + _(DECRYPT_POST, "dpdk-esp-decrypt-post") + +typedef enum +{ +#define _(f,s) DPDK_CRYPTO_INPUT_NEXT_##f, + foreach_dpdk_crypto_input_next +#undef _ + DPDK_CRYPTO_INPUT_N_NEXT, +} dpdk_crypto_input_next_t; + +#define foreach_dpdk_crypto_input_error \ + _(DQ_COPS, "Crypto ops dequeued") \ + _(COP_FAILED, "Crypto op failed") + +typedef enum +{ +#define _(f,s) DPDK_CRYPTO_INPUT_ERROR_##f, + foreach_dpdk_crypto_input_error +#undef _ + DPDK_CRYPTO_INPUT_N_ERROR, +} dpdk_crypto_input_error_t; + +static char *dpdk_crypto_input_error_strings[] = { +#define _(n, s) s, + foreach_dpdk_crypto_input_error +#undef _ +}; + +vlib_node_registration_t dpdk_crypto_input_node; + +typedef struct +{ + u32 cdev; + u32 qp; + u32 status; + u32 sa_idx; + u32 next_index; +} dpdk_crypto_input_trace_t; + +static u8 * +format_dpdk_crypto_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 *); + dpdk_crypto_input_trace_t *t = va_arg (*args, dpdk_crypto_input_trace_t *); + + s = format (s, "dpdk_crypto: cryptodev-id %u queue-pair %u next-index %d", + t->cdev, t->qp, t->next_index); + + s = format (s, "status %u sa-idx %u\n", t->status, t->sa_idx); + + return s; +} + +static_always_inline u32 +dpdk_crypto_dequeue (vlib_main_t * vm, vlib_node_runtime_t * node, + crypto_qp_data_t * qpd) +{ + u32 n_deq, *to_next = 0, next_index, n_cops, def_next_index; + struct rte_crypto_op **cops = qpd->cops; + + if (qpd->inflights == 0) + return 0; + + if (qpd->is_outbound) + def_next_index = DPDK_CRYPTO_INPUT_NEXT_ENCRYPT_POST; + else + def_next_index = DPDK_CRYPTO_INPUT_NEXT_DECRYPT_POST; + + n_cops = rte_cryptodev_dequeue_burst (qpd->dev_id, qpd->qp_id, + cops, VLIB_FRAME_SIZE); + n_deq = n_cops; + next_index = def_next_index; + + qpd->inflights -= n_cops; + ASSERT (qpd->inflights >= 0); + + while (n_cops > 0) + { + u32 n_left_to_next; + + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + while (n_cops > 0 && n_left_to_next > 0) + { + u32 bi0, next0; + vlib_buffer_t *b0 = 0; + struct rte_crypto_op *cop; + struct rte_crypto_sym_op *sym_cop; + + cop = cops[0]; + cops += 1; + n_cops -= 1; + n_left_to_next -= 1; + + next0 = def_next_index; + + if (PREDICT_FALSE (cop->status != RTE_CRYPTO_OP_STATUS_SUCCESS)) + { + next0 = DPDK_CRYPTO_INPUT_NEXT_DROP; + vlib_node_increment_counter (vm, dpdk_crypto_input_node.index, + DPDK_CRYPTO_INPUT_ERROR_COP_FAILED, + 1); + } + cop->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED; + + sym_cop = (struct rte_crypto_sym_op *) (cop + 1); + b0 = vlib_buffer_from_rte_mbuf (sym_cop->m_src); + bi0 = vlib_get_buffer_index (vm, b0); + + to_next[0] = bi0; + to_next += 1; + + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + dpdk_crypto_input_trace_t *tr; + tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->cdev = qpd->dev_id; + tr->qp = qpd->qp_id; + tr->status = cop->status; + tr->next_index = next0; + tr->sa_idx = vnet_buffer (b0)->ipsec.sad_index; + } + + 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); + } + + crypto_free_cop (qpd, qpd->cops, n_deq); + + vlib_node_increment_counter (vm, dpdk_crypto_input_node.index, + DPDK_CRYPTO_INPUT_ERROR_DQ_COPS, n_deq); + return n_deq; +} + +static uword +dpdk_crypto_input_fn (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + 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]; + crypto_qp_data_t *qpd; + u32 n_deq = 0; + + /* *INDENT-OFF* */ + vec_foreach (qpd, cwm->qp_data) + n_deq += dpdk_crypto_dequeue(vm, node, qpd); + /* *INDENT-ON* */ + + return n_deq; +} + +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 = + { +#define _(s,n) [DPDK_CRYPTO_INPUT_NEXT_##s] = n, + foreach_dpdk_crypto_input_next +#undef _ + } +,}; + +#if DPDK_CRYPTO==1 +VLIB_NODE_FUNCTION_MULTIARCH (dpdk_crypto_input_node, dpdk_crypto_input_fn) +#endif +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/vnet/vnet/devices/dpdk/ipsec/dir.dox b/vnet/vnet/devices/dpdk/ipsec/dir.dox new file mode 100644 index 00000000..ffebfc4d --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/dir.dox @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016 Intel 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. + */ +/** + @dir vnet/vnet/devices/dpdk/ipsec + @brief IPSec ESP encrypt/decrypt using DPDK Cryptodev API +*/ diff --git a/vnet/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md b/vnet/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md new file mode 100644 index 00000000..8089696f --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/dpdk_crypto_ipsec_doc.md @@ -0,0 +1,73 @@ +# VPP IPSec implementation using DPDK Cryptodev API {#dpdk_crypto_ipsec_doc} + +This document is meant to contain all related information about implementation and usability. + + +## VPP IPsec with DPDK Cryptodev + +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 + +The following nodes are added: +* dpdk-crypto-input : polling input node, basically dequeuing from crypto devices. +* dpdk-esp-encrypt-post : internal node. +* dpdk-esp-decrypt-post : internal node. + + +### How to enable VPP IPSec with DPDK Cryptodev support + +To enable DPDK Cryptodev support (disabled by default), we need the following env option: + + vpp_uses_dpdk_cryptodev=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) + + +### 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: + + 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. + +Example startup.conf: + +``` +dpdk { + socket-mem 1024,1024 + num-mbufs 131072 + dev 0000:81:00.0 + dev 0000:81:00.1 + dev 0000:85:01.0 + dev 0000:85:01.1 + vdev cryptodev_aesni_mb_pmd,socket_id=1 + vdev cryptodev_aesni_mb_pmd,socket_id=1 +} +``` + +In the above configuration: +* 0000:85:01.0 and 0000:85:01.1 are crypto BDFs and they require the same driver binding as DPDK Ethernet devices but they do not support any extra configuration options. +* Two AESNI-MB Software Cryptodev PMDs are created in NUMA node 1. + +For further details refer to [DPDK Crypto Device Driver documentation](http://dpdk.org/doc/guides/cryptodevs/index.html) + +### Operational data + +The following CLI command displays the Cryptodev/Worker mapping: + + show crypto device mapping [verbose] diff --git a/vnet/vnet/devices/dpdk/ipsec/esp.h b/vnet/vnet/devices/dpdk/ipsec/esp.h new file mode 100644 index 00000000..71282ac0 --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/esp.h @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2016 Intel 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. + */ +#ifndef __DPDK_ESP_H__ +#define __DPDK_ESP_H__ + +#include +#include +#include + +typedef struct +{ + enum rte_crypto_cipher_algorithm algo; + u8 key_len; + u8 iv_len; +} dpdk_esp_crypto_alg_t; + +typedef struct +{ + enum rte_crypto_auth_algorithm algo; + u8 trunc_size; +} dpdk_esp_integ_alg_t; + +typedef struct +{ + dpdk_esp_crypto_alg_t *esp_crypto_algs; + dpdk_esp_integ_alg_t *esp_integ_algs; +} dpdk_esp_main_t; + +dpdk_esp_main_t dpdk_esp_main; + +static_always_inline void +dpdk_esp_init () +{ + dpdk_esp_main_t *em = &dpdk_esp_main; + dpdk_esp_integ_alg_t *i; + dpdk_esp_crypto_alg_t *c; + + vec_validate (em->esp_crypto_algs, IPSEC_CRYPTO_N_ALG - 1); + + c = &em->esp_crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_128]; + c->algo = RTE_CRYPTO_CIPHER_AES_CBC; + c->key_len = 16; + c->iv_len = 16; + + c = &em->esp_crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_192]; + c->algo = RTE_CRYPTO_CIPHER_AES_CBC; + c->key_len = 24; + c->iv_len = 16; + + c = &em->esp_crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_256]; + c->algo = RTE_CRYPTO_CIPHER_AES_CBC; + c->key_len = 32; + c->iv_len = 16; + + vec_validate (em->esp_integ_algs, IPSEC_INTEG_N_ALG - 1); + + i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA1_96]; + i->algo = RTE_CRYPTO_AUTH_SHA1_HMAC; + i->trunc_size = 12; + + i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_256_96]; + i->algo = RTE_CRYPTO_AUTH_SHA256_HMAC; + i->trunc_size = 12; + + i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_256_128]; + i->algo = RTE_CRYPTO_AUTH_SHA256_HMAC; + i->trunc_size = 16; + + i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_384_192]; + i->algo = RTE_CRYPTO_AUTH_SHA384_HMAC; + i->trunc_size = 24; + + i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_512_256]; + i->algo = RTE_CRYPTO_AUTH_SHA512_HMAC; + i->trunc_size = 32; +} + +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) +{ + switch (crypto_algo) + { + case IPSEC_CRYPTO_ALG_NONE: + cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_NULL; + break; + case IPSEC_CRYPTO_ALG_AES_CBC_128: + case IPSEC_CRYPTO_ALG_AES_CBC_192: + case IPSEC_CRYPTO_ALG_AES_CBC_256: + cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC; + break; + default: + return -1; + } + + cipher_xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER; + + return 0; +} + +static_always_inline int +translate_integ_algo(ipsec_integ_alg_t integ_alg, + struct rte_crypto_sym_xform *auth_xform) +{ + switch (integ_alg) { + case IPSEC_INTEG_ALG_NONE: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_NULL; + auth_xform->auth.digest_length = 0; + break; + case IPSEC_INTEG_ALG_SHA1_96: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC; + auth_xform->auth.digest_length = 12; + break; + case IPSEC_INTEG_ALG_SHA_256_96: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA256_HMAC; + auth_xform->auth.digest_length = 12; + break; + case IPSEC_INTEG_ALG_SHA_256_128: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA256_HMAC; + auth_xform->auth.digest_length = 16; + break; + case IPSEC_INTEG_ALG_SHA_384_192: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA384_HMAC; + auth_xform->auth.digest_length = 24; + break; + case IPSEC_INTEG_ALG_SHA_512_256: + auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA512_HMAC; + auth_xform->auth.digest_length = 32; + break; + default: + return -1; + } + + auth_xform->type = RTE_CRYPTO_SYM_XFORM_AUTH; + + return 0; +} + +static_always_inline int +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; + 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 *xfs; + uword key = 0, *data; + crypto_worker_qp_key_t *p_key = (crypto_worker_qp_key_t *)&key; + + cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; + cipher_xform.cipher.key.data = sa->crypto_key; + cipher_xform.cipher.key.length = sa->crypto_key_len; + + auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH; + 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) + return -1; + p_key->cipher_algo = cipher_xform.cipher.algo; + + if (translate_integ_algo(sa->integ_alg, &auth_xform) < 0) + return -1; + p_key->auth_algo = auth_xform.auth.algo; + + if (is_outbound) + { + cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT; + auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_GENERATE; + cipher_xform.next = &auth_xform; + xfs = &cipher_xform; + } + else + { + cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT; + auth_xform.auth.op = RTE_CRYPTO_AUTH_OP_VERIFY; + auth_xform.next = &cipher_xform; + xfs = &auth_xform; + } + + p_key->is_outbound = is_outbound; + + 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); + + if (!sa_sess->sess) + return -1; + + sa_sess->qp_index = (u8)*data; + + return 0; +} + +#endif /* __DPDK_ESP_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c b/vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c new file mode 100644 index 00000000..c898d05e --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c @@ -0,0 +1,549 @@ +/* + * esp_decrypt.c : IPSec ESP Decrypt node using DPDK Cryptodev + * + * Copyright (c) 2016 Intel 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 + +#define foreach_esp_decrypt_next \ +_(DROP, "error-drop") \ +_(IP4_INPUT, "ip4-input") \ +_(IP6_INPUT, "ip6-input") + +#define _(v, s) ESP_DECRYPT_NEXT_##v, +typedef enum { + foreach_esp_decrypt_next +#undef _ + ESP_DECRYPT_N_NEXT, +} esp_decrypt_next_t; + +#define foreach_esp_decrypt_error \ + _(RX_PKTS, "ESP pkts received") \ + _(DECRYPTION_FAILED, "ESP decryption failed") \ + _(REPLAY, "SA replayed packet") \ + _(NOT_IP, "Not IP packet (dropped)") \ + _(ENQ_FAIL, "Enqueue failed (buffer full)") \ + _(NO_CRYPTODEV, "Cryptodev not configured") \ + _(BAD_LEN, "Invalid ciphertext length") \ + _(UNSUPPORTED, "Cipher/Auth not supported") + + +typedef enum { +#define _(sym,str) ESP_DECRYPT_ERROR_##sym, + foreach_esp_decrypt_error +#undef _ + ESP_DECRYPT_N_ERROR, +} esp_decrypt_error_t; + +static char * esp_decrypt_error_strings[] = { +#define _(sym,string) string, + foreach_esp_decrypt_error +#undef _ +}; + +vlib_node_registration_t dpdk_esp_decrypt_node; + +typedef struct { + ipsec_crypto_alg_t crypto_alg; + ipsec_integ_alg_t integ_alg; +} esp_decrypt_trace_t; + +/* packet trace format function */ +static u8 * format_esp_decrypt_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 *); + esp_decrypt_trace_t * t = va_arg (*args, esp_decrypt_trace_t *); + + s = format (s, "esp: crypto %U integrity %U", + format_ipsec_crypto_alg, t->crypto_alg, + format_ipsec_integ_alg, t->integ_alg); + return s; +} + +static uword +dpdk_esp_decrypt_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, *to_next, next_index; + ipsec_main_t *im = &ipsec_main; + u32 cpu_index = os_get_cpu_number(); + dpdk_crypto_main_t * dcm = &dpdk_crypto_main; + dpdk_esp_main_t * em = &dpdk_esp_main; + u32 i; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + if (PREDICT_FALSE(!dcm->workers_main)) + { + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_NO_CRYPTODEV, n_left_from); + vlib_buffer_free(vm, from, n_left_from); + return n_left_from; + } + + crypto_worker_main_t *cwm = vec_elt_at_index(dcm->workers_main, cpu_index); + u32 n_qps = vec_len(cwm->qp_data); + struct rte_crypto_op ** cops_to_enq[n_qps]; + u32 n_cop_qp[n_qps], * bi_to_enq[n_qps]; + + for (i = 0; i < n_qps; i++) + { + bi_to_enq[i] = cwm->qp_data[i].bi; + cops_to_enq[i] = cwm->qp_data[i].cops; + } + + memset(n_cop_qp, 0, n_qps * sizeof(u32)); + + crypto_alloc_cops(); + + next_index = ESP_DECRYPT_NEXT_DROP; + + 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, sa_index0 = ~0, seq, icv_size; + vlib_buffer_t * b0; + esp_header_t * esp0; + ipsec_sa_t * sa0; + struct rte_mbuf * mb0 = 0; + const int BLOCK_SIZE = 16; + const int IV_SIZE = 16; + crypto_sa_session_t * sa_sess; + void * sess; + u16 qp_index; + struct rte_crypto_op * cop = 0; + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + + b0 = vlib_get_buffer (vm, bi0); + esp0 = vlib_buffer_get_current (b0); + + sa_index0 = vnet_buffer(b0)->ipsec.sad_index; + sa0 = pool_elt_at_index (im->sad, sa_index0); + + seq = clib_host_to_net_u32(esp0->seq); + + /* anti-replay check */ + if (sa0->use_anti_replay) + { + int rv = 0; + + if (PREDICT_TRUE(sa0->use_esn)) + rv = esp_replay_check_esn(sa0, seq); + else + rv = esp_replay_check(sa0, seq); + + if (PREDICT_FALSE(rv)) + { + clib_warning ("anti-replay SPI %u seq %u", sa0->spi, seq); + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_REPLAY, 1); + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + goto trace; + } + } + + if (PREDICT_FALSE(sa0->integ_alg == IPSEC_INTEG_ALG_NONE) || + PREDICT_FALSE(sa0->crypto_alg == IPSEC_CRYPTO_ALG_NONE)) + { + clib_warning ("SPI %u : only cipher + auth supported", sa0->spi); + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_UNSUPPORTED, 1); + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + goto trace; + } + + sa_sess = pool_elt_at_index(cwm->sa_sess_d[0], sa_index0); + + if (PREDICT_FALSE(!sa_sess->sess)) + { + int ret = create_sym_sess(sa0, sa_sess, 0); + ASSERT(ret == 0); + } + + sess = sa_sess->sess; + qp_index = sa_sess->qp_index; + + ASSERT (vec_len (vec_elt (cwm->qp_data, qp_index).free_cops) > 0); + cop = vec_pop (vec_elt (cwm->qp_data, qp_index).free_cops); + ASSERT (cop->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED); + + cops_to_enq[qp_index][0] = cop; + cops_to_enq[qp_index] += 1; + n_cop_qp[qp_index] += 1; + bi_to_enq[qp_index][0] = bi0; + bi_to_enq[qp_index] += 1; + + rte_crypto_op_attach_sym_session(cop, sess); + + icv_size = em->esp_integ_algs[sa0->integ_alg].trunc_size; + + /* Convert vlib buffer to mbuf */ + mb0 = rte_mbuf_from_vlib_buffer(b0); + mb0->data_len = b0->current_length; + mb0->pkt_len = b0->current_length; + mb0->data_off = RTE_PKTMBUF_HEADROOM + b0->current_data; + + /* Outer IP header has already been stripped */ + u16 payload_len = rte_pktmbuf_pkt_len(mb0) - sizeof (esp_header_t) - + IV_SIZE - icv_size; + + if ((payload_len & (BLOCK_SIZE - 1)) || (payload_len <= 0)) + { + clib_warning ("payload %u not multiple of %d\n", + payload_len, BLOCK_SIZE); + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_BAD_LEN, 1); + vec_add (vec_elt (cwm->qp_data, qp_index).free_cops, &cop, 1); + bi_to_enq[qp_index] -= 1; + cops_to_enq[qp_index] -= 1; + n_cop_qp[qp_index] -= 1; + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + goto trace; + } + + struct rte_crypto_sym_op *sym_cop = (struct rte_crypto_sym_op *)(cop + 1); + + sym_cop->m_src = mb0; + sym_cop->cipher.data.offset = sizeof (esp_header_t) + IV_SIZE; + sym_cop->cipher.data.length = payload_len; + + sym_cop->cipher.iv.data = + rte_pktmbuf_mtod_offset(mb0, void*, sizeof (esp_header_t)); + sym_cop->cipher.iv.phys_addr = + rte_pktmbuf_mtophys_offset(mb0, sizeof (esp_header_t)); + sym_cop->cipher.iv.length = IV_SIZE; + + if (sa0->use_esn) + { + dpdk_cop_priv_t* priv = (dpdk_cop_priv_t*) (sym_cop + 1); + u8* payload_end = + rte_pktmbuf_mtod_offset(mb0, u8*, sizeof(esp_header_t) + IV_SIZE + + payload_len); + + memcpy (priv->icv, payload_end, icv_size); + *((u32*) payload_end) = sa0->seq_hi; + sym_cop->auth.data.offset = 0; + sym_cop->auth.data.length = + sizeof(esp_header_t) + IV_SIZE + payload_len + sizeof(sa0->seq_hi); + sym_cop->auth.digest.data = priv->icv; + sym_cop->auth.digest.phys_addr = + cop->phys_addr + (uintptr_t) priv->icv - (uintptr_t) cop; + sym_cop->auth.digest.length = icv_size; + } + else + { + sym_cop->auth.data.offset = 0; + sym_cop->auth.data.length = sizeof(esp_header_t) + + IV_SIZE + payload_len; + + sym_cop->auth.digest.data = + rte_pktmbuf_mtod_offset(mb0, void*, + rte_pktmbuf_pkt_len(mb0) - icv_size); + sym_cop->auth.digest.phys_addr = + rte_pktmbuf_mtophys_offset(mb0, + rte_pktmbuf_pkt_len(mb0) - icv_size); + sym_cop->auth.digest.length = icv_size; + } + +trace: + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + esp_decrypt_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->crypto_alg = sa0->crypto_alg; + tr->integ_alg = sa0->integ_alg; + } + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_RX_PKTS, + from_frame->n_vectors); + crypto_qp_data_t *qpd; + /* *INDENT-OFF* */ + vec_foreach_index (i, cwm->qp_data) + { + u32 enq; + + qpd = vec_elt_at_index(cwm->qp_data, i); + enq = rte_cryptodev_enqueue_burst(qpd->dev_id, qpd->qp_id, + qpd->cops, n_cop_qp[i]); + qpd->inflights += enq; + + if (PREDICT_FALSE(enq < n_cop_qp[i])) + { + crypto_free_cop (qpd, &qpd->cops[enq], n_cop_qp[i] - enq); + vlib_buffer_free (vm, &qpd->bi[enq], n_cop_qp[i] - enq); + + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_ENQ_FAIL, + n_cop_qp[i] - enq); + } + } + /* *INDENT-ON* */ + + return from_frame->n_vectors; +} + +VLIB_REGISTER_NODE (dpdk_esp_decrypt_node) = { + .function = dpdk_esp_decrypt_node_fn, + .name = "dpdk-esp-decrypt", + .vector_size = sizeof (u32), + .format_trace = format_esp_decrypt_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(esp_decrypt_error_strings), + .error_strings = esp_decrypt_error_strings, + + .n_next_nodes = ESP_DECRYPT_N_NEXT, + .next_nodes = { +#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n, + foreach_esp_decrypt_next +#undef _ + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (dpdk_esp_decrypt_node, dpdk_esp_decrypt_node_fn) + +/* + * Decrypt Post Node + */ + +#define foreach_esp_decrypt_post_error \ + _(PKTS, "ESP post pkts") + +typedef enum { +#define _(sym,str) ESP_DECRYPT_POST_ERROR_##sym, + foreach_esp_decrypt_post_error +#undef _ + ESP_DECRYPT_POST_N_ERROR, +} esp_decrypt_post_error_t; + +static char * esp_decrypt_post_error_strings[] = { +#define _(sym,string) string, + foreach_esp_decrypt_post_error +#undef _ +}; + +vlib_node_registration_t dpdk_esp_decrypt_post_node; + +static u8 * format_esp_decrypt_post_trace (u8 * s, va_list * args) +{ + return s; +} + +static uword +dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, *to_next = 0, next_index; + ipsec_sa_t * sa0; + u32 sa_index0 = ~0; + ipsec_main_t *im = &ipsec_main; + dpdk_esp_main_t *em = &dpdk_esp_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) + { + esp_footer_t * f0; + const u32 IV_SIZE = 16; + u32 bi0, next0, icv_size; + vlib_buffer_t * b0 = 0; + ip4_header_t *ih4 = 0, *oh4 = 0; + ip6_header_t *ih6 = 0, *oh6 = 0; + u8 tunnel_mode = 1; + u8 transport_ip6 = 0; + + next0 = ESP_DECRYPT_NEXT_DROP; + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + sa_index0 = vnet_buffer(b0)->ipsec.sad_index; + sa0 = pool_elt_at_index (im->sad, sa_index0); + + to_next[0] = bi0; + to_next += 1; + + icv_size = em->esp_integ_algs[sa0->integ_alg].trunc_size; + + if (sa0->use_anti_replay) + { + esp_header_t * esp0 = vlib_buffer_get_current (b0); + u32 seq; + seq = clib_host_to_net_u32(esp0->seq); + if (PREDICT_TRUE(sa0->use_esn)) + esp_replay_advance_esn(sa0, seq); + else + esp_replay_advance(sa0, seq); + } + + ih4 = (ip4_header_t *) (b0->data + sizeof(ethernet_header_t)); + vlib_buffer_advance (b0, sizeof (esp_header_t) + IV_SIZE); + + b0->current_length -= (icv_size + 2); + b0->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID; + f0 = (esp_footer_t *) ((u8 *) vlib_buffer_get_current (b0) + + b0->current_length); + b0->current_length -= f0->pad_length; + + /* transport mode */ + if (PREDICT_FALSE(!sa0->is_tunnel && !sa0->is_tunnel_ip6)) + { + tunnel_mode = 0; + + if (PREDICT_TRUE((ih4->ip_version_and_header_length & 0xF0) != 0x40)) + { + if (PREDICT_TRUE((ih4->ip_version_and_header_length & 0xF0) == 0x60)) + transport_ip6 = 1; + else + { + clib_warning("next header: 0x%x", f0->next_header); + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_NOT_IP, 1); + goto trace; + } + } + } + + if (PREDICT_TRUE (tunnel_mode)) + { + if (PREDICT_TRUE(f0->next_header == IP_PROTOCOL_IP_IN_IP)) + next0 = ESP_DECRYPT_NEXT_IP4_INPUT; + else if (f0->next_header == IP_PROTOCOL_IPV6) + next0 = ESP_DECRYPT_NEXT_IP6_INPUT; + else + { + clib_warning("next header: 0x%x", f0->next_header); + vlib_node_increment_counter (vm, dpdk_esp_decrypt_node.index, + ESP_DECRYPT_ERROR_DECRYPTION_FAILED, + 1); + goto trace; + } + } + /* transport mode */ + else + { + if (PREDICT_FALSE(transport_ip6)) + { + next0 = ESP_DECRYPT_NEXT_IP6_INPUT; + ih6 = (ip6_header_t *) (b0->data + sizeof(ethernet_header_t)); + vlib_buffer_advance (b0, -sizeof(ip6_header_t)); + oh6 = vlib_buffer_get_current (b0); + memmove(oh6, ih6, sizeof(ip6_header_t)); + + oh6->protocol = f0->next_header; + oh6->payload_length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain(vm, b0) - + sizeof (ip6_header_t)); + } + else + { + next0 = ESP_DECRYPT_NEXT_IP4_INPUT; + vlib_buffer_advance (b0, -sizeof(ip4_header_t)); + oh4 = vlib_buffer_get_current (b0); + + oh4->ip_version_and_header_length = 0x45; + oh4->tos = ih4->tos; + oh4->fragment_id = 0; + oh4->flags_and_fragment_offset = 0; + oh4->ttl = ih4->ttl; + oh4->protocol = f0->next_header; + oh4->src_address.as_u32 = ih4->src_address.as_u32; + oh4->dst_address.as_u32 = ih4->dst_address.as_u32; + oh4->length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + oh4->checksum = ip4_header_checksum (oh4); + } + } + + vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32)~0; + +trace: + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + esp_decrypt_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->crypto_alg = sa0->crypto_alg; + tr->integ_alg = sa0->integ_alg; + } + + 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, dpdk_esp_decrypt_post_node.index, + ESP_DECRYPT_POST_ERROR_PKTS, + from_frame->n_vectors); + + return from_frame->n_vectors; +} + +VLIB_REGISTER_NODE (dpdk_esp_decrypt_post_node) = { + .function = dpdk_esp_decrypt_post_node_fn, + .name = "dpdk-esp-decrypt-post", + .vector_size = sizeof (u32), + .format_trace = format_esp_decrypt_post_trace, + .type = VLIB_NODE_TYPE_INTERNAL, + + .n_errors = ARRAY_LEN(esp_decrypt_post_error_strings), + .error_strings = esp_decrypt_post_error_strings, + + .n_next_nodes = ESP_DECRYPT_N_NEXT, + .next_nodes = { +#define _(s,n) [ESP_DECRYPT_NEXT_##s] = n, + foreach_esp_decrypt_next +#undef _ + }, +}; + +VLIB_NODE_FUNCTION_MULTIARCH (dpdk_esp_decrypt_post_node, dpdk_esp_decrypt_post_node_fn) diff --git a/vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c b/vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c new file mode 100644 index 00000000..aef4b90d --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c @@ -0,0 +1,554 @@ +/* + * esp_encrypt.c : IPSec ESP encrypt node using DPDK Cryptodev + * + * Copyright (c) 2016 Intel 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 + +#define foreach_esp_encrypt_next \ +_(DROP, "error-drop") \ +_(IP4_INPUT, "ip4-input") \ +_(IP6_INPUT, "ip6-input") \ +_(INTERFACE_OUTPUT, "interface-output") + +#define _(v, s) ESP_ENCRYPT_NEXT_##v, +typedef enum +{ + foreach_esp_encrypt_next +#undef _ + ESP_ENCRYPT_N_NEXT, +} esp_encrypt_next_t; + +#define foreach_esp_encrypt_error \ + _(RX_PKTS, "ESP pkts received") \ + _(SEQ_CYCLED, "sequence number cycled") \ + _(ENQ_FAIL, "Enqueue failed (buffer full)") \ + _(NO_CRYPTODEV, "Cryptodev not configured") \ + _(UNSUPPORTED, "Cipher/Auth not supported") + + +typedef enum +{ +#define _(sym,str) ESP_ENCRYPT_ERROR_##sym, + foreach_esp_encrypt_error +#undef _ + ESP_ENCRYPT_N_ERROR, +} esp_encrypt_error_t; + +static char *esp_encrypt_error_strings[] = { +#define _(sym,string) string, + foreach_esp_encrypt_error +#undef _ +}; + +vlib_node_registration_t dpdk_esp_encrypt_node; + +typedef struct +{ + u32 spi; + u32 seq; + ipsec_crypto_alg_t crypto_alg; + ipsec_integ_alg_t integ_alg; +} esp_encrypt_trace_t; + +/* packet trace format function */ +static u8 * +format_esp_encrypt_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 *); + esp_encrypt_trace_t *t = va_arg (*args, esp_encrypt_trace_t *); + + s = format (s, "esp: spi %u seq %u crypto %U integrity %U", + t->spi, t->seq, + format_ipsec_crypto_alg, t->crypto_alg, + format_ipsec_integ_alg, t->integ_alg); + return s; +} + +static uword +dpdk_esp_encrypt_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, *to_next, next_index; + ipsec_main_t *im = &ipsec_main; + u32 cpu_index = os_get_cpu_number (); + dpdk_crypto_main_t *dcm = &dpdk_crypto_main; + dpdk_esp_main_t *em = &dpdk_esp_main; + u32 i; + + from = vlib_frame_vector_args (from_frame); + n_left_from = from_frame->n_vectors; + + if (PREDICT_FALSE (!dcm->workers_main)) + { + /* Likely there are not enough cryptodevs, so drop frame */ + vlib_node_increment_counter (vm, dpdk_esp_encrypt_node.index, + ESP_ENCRYPT_ERROR_NO_CRYPTODEV, + n_left_from); + vlib_buffer_free (vm, from, n_left_from); + return n_left_from; + } + + crypto_worker_main_t *cwm = vec_elt_at_index (dcm->workers_main, cpu_index); + u32 n_qps = vec_len (cwm->qp_data); + struct rte_crypto_op **cops_to_enq[n_qps]; + u32 n_cop_qp[n_qps], *bi_to_enq[n_qps]; + + for (i = 0; i < n_qps; i++) + { + bi_to_enq[i] = cwm->qp_data[i].bi; + cops_to_enq[i] = cwm->qp_data[i].cops; + } + + memset (n_cop_qp, 0, n_qps * sizeof (u32)); + + crypto_alloc_cops (); + + next_index = ESP_ENCRYPT_NEXT_DROP; + + 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 = 0; + u32 sa_index0; + ipsec_sa_t *sa0; + ip4_and_esp_header_t *ih0, *oh0 = 0; + ip6_and_esp_header_t *ih6_0, *oh6_0 = 0; + struct rte_mbuf *mb0 = 0; + esp_footer_t *f0; + u8 is_ipv6; + u8 ip_hdr_size; + u8 next_hdr_type; + u8 transport_mode = 0; + const int BLOCK_SIZE = 16; + const int IV_SIZE = 16; + u16 orig_sz; + crypto_sa_session_t *sa_sess; + void *sess; + struct rte_crypto_op *cop = 0; + u16 qp_index; + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + + b0 = vlib_get_buffer (vm, bi0); + sa_index0 = vnet_buffer (b0)->ipsec.sad_index; + sa0 = pool_elt_at_index (im->sad, sa_index0); + + if (PREDICT_FALSE (esp_seq_advance (sa0))) + { + clib_warning ("sequence number counter has cycled SPI %u", + sa0->spi); + vlib_node_increment_counter (vm, dpdk_esp_encrypt_node.index, + ESP_ENCRYPT_ERROR_SEQ_CYCLED, 1); + //TODO: rekey SA + to_next[0] = bi0; + to_next += 1; + n_left_to_next -= 1; + goto trace; + } + + sa_sess = pool_elt_at_index (cwm->sa_sess_d[1], sa_index0); + if (PREDICT_FALSE (!sa_sess->sess)) + { + int ret = create_sym_sess (sa0, sa_sess, 1); + ASSERT (ret == 0); + } + + qp_index = sa_sess->qp_index; + sess = sa_sess->sess; + + ASSERT (vec_len (vec_elt (cwm->qp_data, qp_index).free_cops) > 0); + cop = vec_pop (vec_elt (cwm->qp_data, qp_index).free_cops); + ASSERT (cop->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED); + + cops_to_enq[qp_index][0] = cop; + cops_to_enq[qp_index] += 1; + n_cop_qp[qp_index] += 1; + bi_to_enq[qp_index][0] = bi0; + bi_to_enq[qp_index] += 1; + + ssize_t adv; + ih0 = vlib_buffer_get_current (b0); + orig_sz = b0->current_length; + is_ipv6 = (ih0->ip4.ip_version_and_header_length & 0xF0) == 0x60; + /* is ipv6 */ + if (PREDICT_TRUE (sa0->is_tunnel)) + { + if (PREDICT_TRUE (!is_ipv6)) + adv = -sizeof (ip4_and_esp_header_t); + else + adv = -sizeof (ip6_and_esp_header_t); + } + else + { + adv = -sizeof (esp_header_t); + if (PREDICT_TRUE (!is_ipv6)) + orig_sz -= sizeof (ip4_header_t); + else + orig_sz -= sizeof (ip6_header_t); + } + + /*transport mode save the eth header before it is overwritten */ + if (PREDICT_FALSE (!sa0->is_tunnel)) + { + ethernet_header_t *ieh0 = (ethernet_header_t *) + ((u8 *) vlib_buffer_get_current (b0) - + sizeof (ethernet_header_t)); + ethernet_header_t *oeh0 = + (ethernet_header_t *) ((u8 *) ieh0 + (adv - IV_SIZE)); + clib_memcpy (oeh0, ieh0, sizeof (ethernet_header_t)); + } + + vlib_buffer_advance (b0, adv - IV_SIZE); + + /* XXX IP6/ip4 and IP4/IP6 not supported, only IP4/IP4 and IP6/IP6 */ + + /* is ipv6 */ + if (PREDICT_FALSE (is_ipv6)) + { + ih6_0 = (ip6_and_esp_header_t *) ih0; + ip_hdr_size = sizeof (ip6_header_t); + oh6_0 = vlib_buffer_get_current (b0); + + if (PREDICT_TRUE (sa0->is_tunnel)) + { + next_hdr_type = IP_PROTOCOL_IPV6; + oh6_0->ip6.ip_version_traffic_class_and_flow_label = + ih6_0->ip6.ip_version_traffic_class_and_flow_label; + } + else + { + next_hdr_type = ih6_0->ip6.protocol; + memmove (oh6_0, ih6_0, sizeof (ip6_header_t)); + } + + oh6_0->ip6.protocol = IP_PROTOCOL_IPSEC_ESP; + oh6_0->ip6.hop_limit = 254; + oh6_0->esp.spi = clib_net_to_host_u32 (sa0->spi); + oh6_0->esp.seq = clib_net_to_host_u32 (sa0->seq); + } + else + { + ip_hdr_size = sizeof (ip4_header_t); + next_hdr_type = IP_PROTOCOL_IP_IN_IP; + oh0 = vlib_buffer_get_current (b0); + + oh0->ip4.ip_version_and_header_length = 0x45; + oh0->ip4.tos = ih0->ip4.tos; + oh0->ip4.fragment_id = 0; + oh0->ip4.flags_and_fragment_offset = 0; + oh0->ip4.ttl = 254; + oh0->ip4.protocol = IP_PROTOCOL_IPSEC_ESP; + oh0->esp.spi = clib_net_to_host_u32 (sa0->spi); + oh0->esp.seq = clib_net_to_host_u32 (sa0->seq); + } + + if (PREDICT_TRUE (sa0->is_tunnel && !sa0->is_tunnel_ip6)) + { + oh0->ip4.src_address.as_u32 = sa0->tunnel_src_addr.ip4.as_u32; + oh0->ip4.dst_address.as_u32 = sa0->tunnel_dst_addr.ip4.as_u32; + + /* in tunnel mode send it back to FIB */ + next0 = ESP_ENCRYPT_NEXT_IP4_INPUT; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0; + } + else if (sa0->is_tunnel && sa0->is_tunnel_ip6) + { + oh6_0->ip6.src_address.as_u64[0] = + sa0->tunnel_src_addr.ip6.as_u64[0]; + oh6_0->ip6.src_address.as_u64[1] = + sa0->tunnel_src_addr.ip6.as_u64[1]; + oh6_0->ip6.dst_address.as_u64[0] = + sa0->tunnel_dst_addr.ip6.as_u64[0]; + oh6_0->ip6.dst_address.as_u64[1] = + sa0->tunnel_dst_addr.ip6.as_u64[1]; + + /* in tunnel mode send it back to FIB */ + next0 = ESP_ENCRYPT_NEXT_IP6_INPUT; + vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0; + } + else + { + next0 = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT; + transport_mode = 1; + /*ipv6 already handled */ + if (PREDICT_TRUE (!is_ipv6)) + { + next_hdr_type = ih0->ip4.protocol; + oh0->ip4.src_address.as_u32 = ih0->ip4.src_address.as_u32; + oh0->ip4.dst_address.as_u32 = ih0->ip4.dst_address.as_u32; + } + } + + ASSERT (sa0->crypto_alg < IPSEC_CRYPTO_N_ALG); + ASSERT (sa0->crypto_alg != IPSEC_CRYPTO_ALG_NONE); + + int blocks = 1 + (orig_sz + 1) / BLOCK_SIZE; + + /* pad packet in input buffer */ + u8 pad_bytes = BLOCK_SIZE * blocks - 2 - orig_sz; + u8 i; + u8 *padding = vlib_buffer_get_current (b0) + b0->current_length; + + for (i = 0; i < pad_bytes; ++i) + padding[i] = i + 1; + + f0 = vlib_buffer_get_current (b0) + b0->current_length + pad_bytes; + f0->pad_length = pad_bytes; + f0->next_header = next_hdr_type; + b0->current_length += pad_bytes + 2 + + em->esp_integ_algs[sa0->integ_alg].trunc_size; + + vnet_buffer (b0)->sw_if_index[VLIB_RX] = + vnet_buffer (b0)->sw_if_index[VLIB_RX]; + b0->flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID; + + struct rte_crypto_sym_op *sym_cop; + sym_cop = (struct rte_crypto_sym_op *) (cop + 1); + + dpdk_cop_priv_t *priv = (dpdk_cop_priv_t *) (sym_cop + 1); + + vnet_buffer (b0)->unused[0] = next0; + priv->iv[0] = sa0->seq; + priv->iv[1] = sa0->seq_hi; + + mb0 = rte_mbuf_from_vlib_buffer (b0); + mb0->data_len = b0->current_length; + mb0->pkt_len = b0->current_length; + mb0->data_off = RTE_PKTMBUF_HEADROOM + b0->current_data; + + rte_crypto_op_attach_sym_session (cop, sess); + + sym_cop->m_src = mb0; + sym_cop->cipher.data.offset = ip_hdr_size + sizeof (esp_header_t); + sym_cop->cipher.data.length = BLOCK_SIZE * blocks + IV_SIZE; + + sym_cop->cipher.iv.data = (u8 *) priv->iv; + sym_cop->cipher.iv.phys_addr = cop->phys_addr + + (uintptr_t) priv->iv - (uintptr_t) cop; + sym_cop->cipher.iv.length = IV_SIZE; + + ASSERT (sa0->integ_alg < IPSEC_INTEG_N_ALG); + ASSERT (sa0->integ_alg != IPSEC_INTEG_ALG_NONE); + + sym_cop->auth.data.offset = ip_hdr_size; + sym_cop->auth.data.length = b0->current_length - ip_hdr_size - + em->esp_integ_algs[sa0->integ_alg].trunc_size; + + sym_cop->auth.digest.data = vlib_buffer_get_current (b0) + + b0->current_length - + em->esp_integ_algs[sa0->integ_alg].trunc_size; + sym_cop->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset (mb0, + b0->current_length + - + em->esp_integ_algs + [sa0->integ_alg].trunc_size); + sym_cop->auth.digest.length = + em->esp_integ_algs[sa0->integ_alg].trunc_size; + + if (PREDICT_FALSE (sa0->use_esn)) + { + u8 *payload_end = + vlib_buffer_get_current (b0) + b0->current_length; + *((u32 *) payload_end) = sa0->seq_hi; + sym_cop->auth.data.length += sizeof (sa0->seq_hi); + } + + if (PREDICT_FALSE (is_ipv6)) + { + oh6_0->ip6.payload_length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) - + sizeof (ip6_header_t)); + } + else + { + oh0->ip4.length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + oh0->ip4.checksum = ip4_header_checksum (&oh0->ip4); + } + + if (transport_mode) + vlib_buffer_advance (b0, -sizeof (ethernet_header_t)); + + trace: + if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + { + esp_encrypt_trace_t *tr = + vlib_add_trace (vm, node, b0, sizeof (*tr)); + tr->spi = sa0->spi; + tr->seq = sa0->seq - 1; + tr->crypto_alg = sa0->crypto_alg; + tr->integ_alg = sa0->integ_alg; + } + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + vlib_node_increment_counter (vm, dpdk_esp_encrypt_node.index, + ESP_ENCRYPT_ERROR_RX_PKTS, + from_frame->n_vectors); + crypto_qp_data_t *qpd; + /* *INDENT-OFF* */ + vec_foreach_index (i, cwm->qp_data) + { + u32 enq; + + qpd = vec_elt_at_index(cwm->qp_data, i); + enq = rte_cryptodev_enqueue_burst(qpd->dev_id, qpd->qp_id, + qpd->cops, n_cop_qp[i]); + qpd->inflights += enq; + + if (PREDICT_FALSE(enq < n_cop_qp[i])) + { + crypto_free_cop (qpd, &qpd->cops[enq], n_cop_qp[i] - enq); + vlib_buffer_free (vm, &qpd->bi[enq], n_cop_qp[i] - enq); + + vlib_node_increment_counter (vm, dpdk_esp_encrypt_node.index, + ESP_ENCRYPT_ERROR_ENQ_FAIL, + n_cop_qp[i] - enq); + } + } + /* *INDENT-ON* */ + + return from_frame->n_vectors; +} + +VLIB_REGISTER_NODE (dpdk_esp_encrypt_node) = +{ + .function = dpdk_esp_encrypt_node_fn,.name = "dpdk-esp-encrypt",.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",} +}; + +VLIB_NODE_FUNCTION_MULTIARCH (dpdk_esp_encrypt_node, dpdk_esp_encrypt_node_fn) +/* + * ESP Encrypt Post Node + */ +#define foreach_esp_encrypt_post_error \ + _(PKTS, "ESP post pkts") + typedef enum + { +#define _(sym,str) ESP_ENCRYPT_POST_ERROR_##sym, + foreach_esp_encrypt_post_error +#undef _ + ESP_ENCRYPT_POST_N_ERROR, + } esp_encrypt_post_error_t; + + static char *esp_encrypt_post_error_strings[] = { +#define _(sym,string) string, + foreach_esp_encrypt_post_error +#undef _ + }; + +vlib_node_registration_t dpdk_esp_encrypt_post_node; + +static u8 * +format_esp_encrypt_post_trace (u8 * s, va_list * args) +{ + return s; +} + +static uword +dpdk_esp_encrypt_post_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * from_frame) +{ + u32 n_left_from, *from, *to_next = 0, next_index; + + 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 = 0; + + bi0 = from[0]; + from += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer (vm, bi0); + + to_next[0] = bi0; + to_next += 1; + + next0 = vnet_buffer (b0)->unused[0]; + + 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, dpdk_esp_encrypt_post_node.index, + ESP_ENCRYPT_POST_ERROR_PKTS, + from_frame->n_vectors); + + return from_frame->n_vectors; +} + +VLIB_REGISTER_NODE (dpdk_esp_encrypt_post_node) = +{ + .function = dpdk_esp_encrypt_post_node_fn,.name = + "dpdk-esp-encrypt-post",.vector_size = sizeof (u32),.format_trace = + format_esp_encrypt_post_trace,.type = VLIB_NODE_TYPE_INTERNAL,.n_errors = + ARRAY_LEN (esp_encrypt_post_error_strings),.error_strings = + esp_encrypt_post_error_strings,.n_next_nodes = + ESP_ENCRYPT_N_NEXT,.next_nodes = + { +#define _(s,n) [ESP_ENCRYPT_NEXT_##s] = n, + foreach_esp_encrypt_next +#undef _ + } +}; + +VLIB_NODE_FUNCTION_MULTIARCH (dpdk_esp_encrypt_post_node, + dpdk_esp_encrypt_post_node_fn) +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/vnet/vnet/devices/dpdk/ipsec/ipsec.c b/vnet/vnet/devices/dpdk/ipsec/ipsec.c new file mode 100644 index 00000000..de253f02 --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/ipsec.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2016 Intel 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 +#include + +#define DPDK_CRYPTO_NB_OBJS 2048 +#define DPDK_CRYPTO_CACHE_SIZE 512 +#define DPDK_CRYPTO_PRIV_SIZE 128 +#define DPDK_CRYPTO_N_QUEUE_DESC 512 +#define DPDK_CRYPTO_NB_COPS (1024 * 4) + +/* + * return: + * -1: update failed + * 0: already exist + * 1: mapped + */ +static int +update_qp_data (crypto_worker_main_t * cwm, + u8 cdev_id, u16 qp_id, u8 is_outbound, u16 * idx) +{ + crypto_qp_data_t *qpd; + + /* *INDENT-OFF* */ + vec_foreach_index (*idx, cwm->qp_data) + { + qpd = vec_elt_at_index(cwm->qp_data, *idx); + + if (qpd->dev_id == cdev_id && qpd->qp_id == qp_id && + qpd->is_outbound == is_outbound) + return 0; + } + /* *INDENT-ON* */ + + vec_add2 (cwm->qp_data, qpd, 1); + + 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 + */ +static int +add_mapping (crypto_worker_main_t * cwm, + u8 cdev_id, u16 qp, u8 is_outbound, + 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; + + p_key->cipher_algo = (u8) cipher_cap->sym.cipher.algo; + p_key->auth_algo = (u8) auth_cap->sym.auth.algo; + p_key->is_outbound = is_outbound; + + ret = hash_get (cwm->algo_qp_map, key); + if (ret) + return 0; + + mapped = update_qp_data (cwm, cdev_id, qp, is_outbound, &qp_index); + if (mapped < 0) + return -1; + + data = (uword) qp_index; + + ret = hash_set (cwm->algo_qp_map, key, data); + if (!ret) + rte_panic ("Failed to insert hash table\n"); + + return mapped; +} + +/* + * return: + * 0: already exist + * 1: mapped + */ +static int +add_cdev_mapping (crypto_worker_main_t * cwm, + struct rte_cryptodev_info *dev_info, u8 cdev_id, + u16 qp, u8 is_outbound) +{ + const struct rte_cryptodev_capabilities *i, *j; + u32 mapped = 0; + + for (i = dev_info->capabilities; i->op != RTE_CRYPTO_OP_TYPE_UNDEFINED; i++) + { + if (i->sym.xform_type != RTE_CRYPTO_SYM_XFORM_CIPHER) + continue; + + if (check_algo_is_supported (i, NULL) != 0) + continue; + + 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; + } + } + + return mapped; +} + +static int +check_cryptodev_queues () +{ + u32 n_qs = 0; + u8 cdev_id; + u32 n_req_qs = 2; + + if (vlib_num_workers () > 0) + n_req_qs = vlib_num_workers () * 2; + + for (cdev_id = 0; cdev_id < rte_cryptodev_count (); cdev_id++) + { + struct rte_cryptodev_info cdev_info; + + rte_cryptodev_info_get (cdev_id, &cdev_info); + + if (! + (cdev_info.feature_flags & RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING)) + continue; + + n_qs += cdev_info.max_nb_queue_pairs; + } + + if (n_qs >= n_req_qs) + return 0; + else + return -1; +} + +static clib_error_t * +dpdk_ipsec_init (vlib_main_t * vm) +{ + dpdk_crypto_main_t *dcm = &dpdk_crypto_main; + vlib_thread_main_t *tm = vlib_get_thread_main (); + struct rte_cryptodev_config dev_conf; + struct rte_cryptodev_qp_conf qp_conf; + struct rte_cryptodev_info cdev_info; + struct rte_mempool *rmp; + i32 dev_id, ret; + u32 i, skip_master; + + if (check_cryptodev_queues () < 0) + return clib_error_return (0, "not enough cryptodevs for ipsec"); + + vec_alloc (dcm->workers_main, tm->n_vlib_mains); + _vec_len (dcm->workers_main) = tm->n_vlib_mains; + + fprintf (stdout, "DPDK Cryptodevs info:\n"); + fprintf (stdout, "dev_id\tn_qp\tnb_obj\tcache_size\n"); + /* HW cryptodevs have higher dev_id, use HW first */ + for (dev_id = rte_cryptodev_count () - 1; dev_id >= 0; dev_id--) + { + u16 max_nb_qp, qp = 0; + skip_master = vlib_num_workers () > 0; + + rte_cryptodev_info_get (dev_id, &cdev_info); + + if (! + (cdev_info.feature_flags & RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING)) + continue; + + max_nb_qp = cdev_info.max_nb_queue_pairs; + + for (i = 0; i < tm->n_vlib_mains; i++) + { + u8 is_outbound; + crypto_worker_main_t *cwm; + uword *map; + + if (skip_master) + { + skip_master = 0; + continue; + } + + cwm = vec_elt_at_index (dcm->workers_main, i); + map = cwm->algo_qp_map; + + if (!map) + { + 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); + 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"); + } + } + + if (qp == 0) + continue; + + 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.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); + + qp_conf.nb_descriptors = DPDK_CRYPTO_N_QUEUE_DESC; + for (qp = 0; qp < dev_conf.nb_queue_pairs; qp++) + { + 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); + } + 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); + } + + u32 socket_id = rte_socket_id (); + + vec_validate_aligned (dcm->cop_pools, socket_id, CLIB_CACHE_LINE_BYTES); + + /* pool already exists, nothing to do */ + if (dcm->cop_pools[socket_id]) + return 0; + + u8 *pool_name = format (0, "crypto_op_pool_socket%u%c", 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, socket_id); + vec_free (pool_name); + + if (!rmp) + return clib_error_return (0, "failed to allocate mempool on socket %u", + socket_id); + dcm->cop_pools[socket_id] = rmp; + + dpdk_esp_init (); + + if (vec_len (vlib_mains) == 0) + vlib_node_set_state (&vlib_global_main, dpdk_crypto_input_node.index, + VLIB_NODE_STATE_POLLING); + else + for (i = 1; i < tm->n_vlib_mains; i++) + vlib_node_set_state (vlib_mains[i], dpdk_crypto_input_node.index, + VLIB_NODE_STATE_POLLING); + + return 0; +} + +VLIB_MAIN_LOOP_ENTER_FUNCTION (dpdk_ipsec_init); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/vnet/vnet/devices/dpdk/ipsec/ipsec.h b/vnet/vnet/devices/dpdk/ipsec/ipsec.h new file mode 100644 index 00000000..e103655c --- /dev/null +++ b/vnet/vnet/devices/dpdk/ipsec/ipsec.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2016 Intel 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. + */ +#ifndef __DPDK_IPSEC_H__ +#define __DPDK_IPSEC_H__ + +#include + +#undef always_inline +#include +#include + +#if CLIB_DEBUG > 0 +#define always_inline static inline +#else +#define always_inline static inline __attribute__ ((__always_inline__)) +#endif + + +#define MAX_QP_PER_LCORE 16 + +typedef struct +{ + u32 iv[4]; + u8 icv[64]; +} dpdk_cop_priv_t; + +typedef struct +{ + u8 cipher_algo; + u8 auth_algo; + u8 is_outbound; +} crypto_worker_qp_key_t; + +typedef struct +{ + u16 dev_id; + u16 qp_id; + u16 is_outbound; + i16 inflights; + u32 bi[VLIB_FRAME_SIZE]; + struct rte_crypto_op *cops[VLIB_FRAME_SIZE]; + struct rte_crypto_op **free_cops; +} crypto_qp_data_t; + +typedef struct +{ + u8 qp_index; + void *sess; +} crypto_sa_session_t; + +typedef struct +{ + crypto_sa_session_t *sa_sess_d[2]; + crypto_qp_data_t *qp_data; + uword *algo_qp_map; +} crypto_worker_main_t; + +typedef struct +{ + struct rte_mempool **cop_pools; + crypto_worker_main_t *workers_main; +} dpdk_crypto_main_t; + +dpdk_crypto_main_t dpdk_crypto_main; + +extern vlib_node_registration_t dpdk_crypto_input_node; + +#define CRYPTO_N_FREE_COPS (VLIB_FRAME_SIZE * 3) + +static_always_inline void +crypto_alloc_cops () +{ + dpdk_crypto_main_t *dcm = &dpdk_crypto_main; + u32 cpu_index = os_get_cpu_number (); + crypto_worker_main_t *cwm = &dcm->workers_main[cpu_index]; + unsigned socket_id = rte_socket_id (); + crypto_qp_data_t *qpd; + + /* *INDENT-OFF* */ + vec_foreach (qpd, cwm->qp_data) + { + u32 l = vec_len (qpd->free_cops); + + if (PREDICT_FALSE (l < VLIB_FRAME_SIZE)) + { + u32 n_alloc; + + if (PREDICT_FALSE (!qpd->free_cops)) + vec_alloc (qpd->free_cops, CRYPTO_N_FREE_COPS); + + n_alloc = rte_crypto_op_bulk_alloc (dcm->cop_pools[socket_id], + RTE_CRYPTO_OP_TYPE_SYMMETRIC, + &qpd->free_cops[l], + CRYPTO_N_FREE_COPS - l - 1); + + _vec_len (qpd->free_cops) = l + n_alloc; + } + } + /* *INDENT-ON* */ +} + +static_always_inline void +crypto_free_cop (crypto_qp_data_t * qpd, struct rte_crypto_op **cops, u32 n) +{ + u32 l = vec_len (qpd->free_cops); + + if (l + n >= CRYPTO_N_FREE_COPS) + { + l -= VLIB_FRAME_SIZE; + rte_mempool_put_bulk (cops[0]->mempool, + (void **) &qpd->free_cops[l], VLIB_FRAME_SIZE); + } + clib_memcpy (&qpd->free_cops[l], cops, sizeof (*cops) * n); + + _vec_len (qpd->free_cops) = l + n; +} + +static_always_inline int +check_algo_is_supported (const struct rte_cryptodev_capabilities *cap, + char *name) +{ + struct + { + uint8_t cipher_algo; + enum rte_crypto_sym_xform_type type; + union + { + enum rte_crypto_auth_algorithm auth; + enum rte_crypto_cipher_algorithm cipher; + }; + char *name; + } supported_algo[] = + { + { + .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher = + RTE_CRYPTO_CIPHER_NULL,.name = "NULL"}, + { + .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher = + RTE_CRYPTO_CIPHER_AES_CBC,.name = "AES_CBC"}, + { + .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher = + RTE_CRYPTO_CIPHER_AES_CTR,.name = "AES_CTR"}, + { + .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.cipher = + RTE_CRYPTO_CIPHER_3DES_CBC,.name = "3DES-CBC"}, + { + .type = RTE_CRYPTO_SYM_XFORM_CIPHER,.auth = + RTE_CRYPTO_CIPHER_AES_GCM,.name = "AES-GCM"}, + { + .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth = + RTE_CRYPTO_AUTH_SHA1_HMAC,.name = "HMAC-SHA1"}, + { + .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth = + RTE_CRYPTO_AUTH_SHA256_HMAC,.name = "HMAC-SHA256"}, + { + .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth = + RTE_CRYPTO_AUTH_SHA384_HMAC,.name = "HMAC-SHA384"}, + { + .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth = + RTE_CRYPTO_AUTH_SHA512_HMAC,.name = "HMAC-SHA512"}, + { + .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth = + RTE_CRYPTO_AUTH_AES_XCBC_MAC,.name = "AES-XCBC-MAC"}, + { + .type = RTE_CRYPTO_SYM_XFORM_AUTH,.auth = + RTE_CRYPTO_AUTH_AES_GCM,.name = "AES-GCM"}, + { + /* tail */ + .type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED},}; + uint32_t i = 0; + + if (cap->op != RTE_CRYPTO_OP_TYPE_SYMMETRIC) + return -1; + + while (supported_algo[i].type != RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED) + { + if (cap->sym.xform_type == supported_algo[i].type) + { + if ((cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_CIPHER && + cap->sym.cipher.algo == supported_algo[i].cipher) || + (cap->sym.xform_type == RTE_CRYPTO_SYM_XFORM_AUTH && + cap->sym.auth.algo == supported_algo[i].auth)) + { + if (name) + strcpy (name, supported_algo[i].name); + return 0; + } + } + + i++; + } + + return -1; +} + +#endif /* __DPDK_IPSEC_H__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/vnet/vnet/ipsec-gre/interface.c b/vnet/vnet/ipsec-gre/interface.c index fae79b97..56832ee1 100644 --- a/vnet/vnet/ipsec-gre/interface.c +++ b/vnet/vnet/ipsec-gre/interface.c @@ -27,7 +27,14 @@ #include #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) @@ -186,7 +193,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-encrypt", + (vnm->vlib_main, hi->tx_node_index, ESP_NODE, IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT); ASSERT (slot == IPSEC_GRE_OUTPUT_NEXT_ESP_ENCRYPT); diff --git a/vnet/vnet/ipsec/esp.h b/vnet/vnet/ipsec/esp.h index b9feacbb..50cac806 100644 --- a/vnet/vnet/ipsec/esp.h +++ b/vnet/vnet/ipsec/esp.h @@ -12,6 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef __ESP_H__ +#define __ESP_H__ #include #include @@ -77,6 +79,154 @@ typedef struct esp_main_t esp_main; +#define ESP_WINDOW_SIZE (64) +#define ESP_SEQ_MAX (4294967295UL) + + +always_inline int +esp_replay_check (ipsec_sa_t * sa, u32 seq) +{ + u32 diff; + + if (PREDICT_TRUE (seq > sa->last_seq)) + return 0; + + diff = sa->last_seq - seq; + + if (ESP_WINDOW_SIZE > diff) + return (sa->replay_window & (1ULL << diff)) ? 1 : 0; + else + return 1; + + return 0; +} + +always_inline int +esp_replay_check_esn (ipsec_sa_t * sa, u32 seq) +{ + u32 tl = sa->last_seq; + u32 th = sa->last_seq_hi; + u32 diff = tl - seq; + + if (PREDICT_TRUE (tl >= (ESP_WINDOW_SIZE - 1))) + { + if (seq >= (tl - ESP_WINDOW_SIZE + 1)) + { + sa->seq_hi = th; + if (seq <= tl) + return (sa->replay_window & (1ULL << diff)) ? 1 : 0; + else + return 0; + } + else + { + sa->seq_hi = th + 1; + return 0; + } + } + else + { + if (seq >= (tl - ESP_WINDOW_SIZE + 1)) + { + sa->seq_hi = th - 1; + return (sa->replay_window & (1ULL << diff)) ? 1 : 0; + } + else + { + sa->seq_hi = th; + if (seq <= tl) + return (sa->replay_window & (1ULL << diff)) ? 1 : 0; + else + return 0; + } + } + + return 0; +} + +/* TODO seq increment should be atomic to be accessed by multiple workers */ +always_inline void +esp_replay_advance (ipsec_sa_t * sa, u32 seq) +{ + u32 pos; + + if (seq > sa->last_seq) + { + pos = seq - sa->last_seq; + if (pos < ESP_WINDOW_SIZE) + sa->replay_window = ((sa->replay_window) << pos) | 1; + else + sa->replay_window = 1; + sa->last_seq = seq; + } + else + { + pos = sa->last_seq - seq; + sa->replay_window |= (1ULL << pos); + } +} + +always_inline void +esp_replay_advance_esn (ipsec_sa_t * sa, u32 seq) +{ + int wrap = sa->seq_hi - sa->last_seq_hi; + u32 pos; + + if (wrap == 0 && seq > sa->last_seq) + { + pos = seq - sa->last_seq; + if (pos < ESP_WINDOW_SIZE) + sa->replay_window = ((sa->replay_window) << pos) | 1; + else + sa->replay_window = 1; + sa->last_seq = seq; + } + else if (wrap > 0) + { + pos = ~seq + sa->last_seq + 1; + if (pos < ESP_WINDOW_SIZE) + sa->replay_window = ((sa->replay_window) << pos) | 1; + else + sa->replay_window = 1; + sa->last_seq = seq; + sa->last_seq_hi = sa->seq_hi; + } + else if (wrap < 0) + { + pos = ~seq + sa->last_seq + 1; + sa->replay_window |= (1ULL << pos); + } + else + { + pos = sa->last_seq - seq; + sa->replay_window |= (1ULL << pos); + } +} + +always_inline int +esp_seq_advance (ipsec_sa_t * sa) +{ + if (PREDICT_TRUE (sa->use_esn)) + { + if (PREDICT_FALSE (sa->seq == ESP_SEQ_MAX)) + { + if (PREDICT_FALSE + (sa->use_anti_replay && sa->seq_hi == ESP_SEQ_MAX)) + return 1; + sa->seq_hi++; + } + sa->seq++; + } + else + { + if (PREDICT_FALSE (sa->use_anti_replay && sa->seq == ESP_SEQ_MAX)) + return 1; + sa->seq++; + } + + return 0; +} + always_inline void esp_init () { @@ -159,6 +309,7 @@ hmac_calc (ipsec_integ_alg_t alg, return em->esp_integ_algs[alg].trunc_size; } +#endif /* __ESP_H__ */ /* * fd.io coding-style-patch-verification: ON diff --git a/vnet/vnet/ipsec/esp_decrypt.c b/vnet/vnet/ipsec/esp_decrypt.c index 07a5edac..e69cd851 100644 --- a/vnet/vnet/ipsec/esp_decrypt.c +++ b/vnet/vnet/ipsec/esp_decrypt.c @@ -22,8 +22,6 @@ #include #include -#define ESP_WINDOW_SIZE 64 - #define foreach_esp_decrypt_next \ _(DROP, "error-drop") \ _(IP4_INPUT, "ip4-input") \ @@ -109,125 +107,6 @@ esp_decrypt_aes_cbc (ipsec_crypto_alg_t alg, EVP_DecryptFinal_ex (ctx, out + out_len, &out_len); } -always_inline int -esp_replay_check (ipsec_sa_t * sa, u32 seq) -{ - u32 diff; - - if (PREDICT_TRUE (seq > sa->last_seq)) - return 0; - - diff = sa->last_seq - seq; - - if (ESP_WINDOW_SIZE > diff) - return (sa->replay_window & (1ULL << diff)) ? 1 : 0; - else - return 1; - - return 0; -} - -always_inline int -esp_replay_check_esn (ipsec_sa_t * sa, u32 seq) -{ - u32 tl = sa->last_seq; - u32 th = sa->last_seq_hi; - u32 diff = tl - seq; - - if (PREDICT_TRUE (tl >= (ESP_WINDOW_SIZE - 1))) - { - if (seq >= (tl - ESP_WINDOW_SIZE + 1)) - { - sa->seq_hi = th; - if (seq <= tl) - return (sa->replay_window & (1ULL << diff)) ? 1 : 0; - else - return 0; - } - else - { - sa->seq_hi = th + 1; - return 0; - } - } - else - { - if (seq >= (tl - ESP_WINDOW_SIZE + 1)) - { - sa->seq_hi = th - 1; - return (sa->replay_window & (1ULL << diff)) ? 1 : 0; - } - else - { - sa->seq_hi = th; - if (seq <= tl) - return (sa->replay_window & (1ULL << diff)) ? 1 : 0; - else - return 0; - } - } - - return 0; -} - -always_inline void -esp_replay_advance (ipsec_sa_t * sa, u32 seq) -{ - u32 pos; - - if (seq > sa->last_seq) - { - pos = seq - sa->last_seq; - if (pos < ESP_WINDOW_SIZE) - sa->replay_window = ((sa->replay_window) << pos) | 1; - else - sa->replay_window = 1; - sa->last_seq = seq; - } - else - { - pos = sa->last_seq - seq; - sa->replay_window |= (1ULL << pos); - } -} - -always_inline void -esp_replay_advance_esn (ipsec_sa_t * sa, u32 seq) -{ - int wrap = sa->seq_hi - sa->last_seq_hi; - u32 pos; - - if (wrap == 0 && seq > sa->last_seq) - { - pos = seq - sa->last_seq; - if (pos < ESP_WINDOW_SIZE) - sa->replay_window = ((sa->replay_window) << pos) | 1; - else - sa->replay_window = 1; - sa->last_seq = seq; - } - else if (wrap > 0) - { - pos = ~seq + sa->last_seq + 1; - if (pos < ESP_WINDOW_SIZE) - sa->replay_window = ((sa->replay_window) << pos) | 1; - else - sa->replay_window = 1; - sa->last_seq = seq; - sa->last_seq_hi = sa->seq_hi; - } - else if (wrap < 0) - { - pos = ~seq + sa->last_seq + 1; - sa->replay_window |= (1ULL << pos); - } - else - { - pos = sa->last_seq - seq; - sa->replay_window |= (1ULL << pos); - } -} - static uword esp_decrypt_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) diff --git a/vnet/vnet/ipsec/esp_encrypt.c b/vnet/vnet/ipsec/esp_encrypt.c index b7186e3d..b947611e 100644 --- a/vnet/vnet/ipsec/esp_encrypt.c +++ b/vnet/vnet/ipsec/esp_encrypt.c @@ -22,7 +22,6 @@ #include #include -#define ESP_SEQ_MAX (4294967295UL) #define foreach_esp_encrypt_next \ _(DROP, "error-drop") \ @@ -111,30 +110,6 @@ esp_encrypt_aes_cbc (ipsec_crypto_alg_t alg, EVP_EncryptFinal_ex (ctx, out + out_len, &out_len); } -always_inline int -esp_seq_advance (ipsec_sa_t * sa) -{ - if (PREDICT_TRUE (sa->use_esn)) - { - if (PREDICT_FALSE (sa->seq == ESP_SEQ_MAX)) - { - if (PREDICT_FALSE - (sa->use_anti_replay && sa->seq_hi == ESP_SEQ_MAX)) - return 1; - sa->seq_hi++; - } - sa->seq++; - } - else - { - if (PREDICT_FALSE (sa->use_anti_replay && sa->seq == ESP_SEQ_MAX)) - return 1; - sa->seq++; - } - - return 0; -} - static uword esp_encrypt_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) diff --git a/vnet/vnet/ipsec/ipsec.c b/vnet/vnet/ipsec/ipsec.c index 223440ec..ee85c402 100644 --- a/vnet/vnet/ipsec/ipsec.c +++ b/vnet/vnet/ipsec/ipsec.c @@ -21,9 +21,25 @@ #include #include -#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) { @@ -433,6 +449,7 @@ 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); pool_put (im->sad, sa); } else /* create new SA */ @@ -441,6 +458,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) + return VNET_API_ERROR_SYSCALL_ERROR_1; } return 0; } @@ -476,6 +495,12 @@ ipsec_set_sa_key (vlib_main_t * vm, ipsec_sa_t * sa_update) sa->integ_key_len = sa_update->integ_key_len; } + if (sa->crypto_key_len + sa->integ_key_len > 0) + { + if (add_del_sa_sess (sa_index, 0) < 0) + return VNET_API_ERROR_SYSCALL_ERROR_1; + } + return 0; } @@ -522,7 +547,8 @@ ipsec_init (vlib_main_t * vm) ASSERT (node); im->error_drop_node_index = node->index; - node = vlib_get_node_by_name (vm, (u8 *) "esp-encrypt"); + node = vlib_get_node_by_name (vm, (u8 *) ESP_NODE); + ASSERT (node); im->esp_encrypt_node_index = node->index; @@ -530,7 +556,6 @@ ipsec_init (vlib_main_t * vm) ASSERT (node); im->ip4_lookup_node_index = node->index; - if ((error = vlib_call_init_function (vm, ipsec_cli_init))) return error; diff --git a/vnet/vnet/ipsec/ipsec.h b/vnet/vnet/ipsec/ipsec.h index d33df383..65d7bad3 100644 --- a/vnet/vnet/ipsec/ipsec.h +++ b/vnet/vnet/ipsec/ipsec.h @@ -12,6 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef __IPSEC_H__ +#define __IPSEC_H__ + #define IPSEC_FLAG_IPSEC_GRE_TUNNEL (1 << 0) #define foreach_ipsec_policy_action \ @@ -307,6 +310,8 @@ get_next_output_feature_node_index (vlib_buffer_t * b, return node->next_nodes[next]; } +#endif /* __IPSEC_H__ */ + /* * fd.io coding-style-patch-verification: ON * diff --git a/vnet/vnet/ipsec/ipsec_cli.c b/vnet/vnet/ipsec/ipsec_cli.c index 785e040b..8920924d 100644 --- a/vnet/vnet/ipsec/ipsec_cli.c +++ b/vnet/vnet/ipsec/ipsec_cli.c @@ -768,7 +768,6 @@ VLIB_CLI_COMMAND (set_interface_key_command, static) = { }; /* *INDENT-ON* */ - clib_error_t * ipsec_cli_init (vlib_main_t * vm) { diff --git a/vnet/vnet/ipsec/ipsec_if.c b/vnet/vnet/ipsec/ipsec_if.c index 77d5d19a..a8da046f 100644 --- a/vnet/vnet/ipsec/ipsec_if.c +++ b/vnet/vnet/ipsec/ipsec_if.c @@ -20,6 +20,20 @@ #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); @@ -124,6 +138,8 @@ 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); + pool_get (im->sad, sa); memset (sa, 0, sizeof (*sa)); t->output_sa_index = sa - im->sad; @@ -149,6 +165,8 @@ 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); + hash_set (im->ipsec_if_pool_index_by_key, key, t - im->tunnel_interfaces); @@ -192,8 +210,17 @@ 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) + 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) + return VNET_API_ERROR_SYSCALL_ERROR_1; + pool_put (im->sad, sa); hash_unset (im->ipsec_if_pool_index_by_key, key); @@ -282,6 +309,9 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->crypto_alg = alg; 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) + return VNET_API_ERROR_SYSCALL_ERROR_1; } else if (type == IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG) { @@ -289,6 +319,9 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->integ_alg = alg; 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) + return VNET_API_ERROR_SYSCALL_ERROR_1; } else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO) { @@ -296,6 +329,9 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->crypto_alg = alg; 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) + return VNET_API_ERROR_SYSCALL_ERROR_1; } else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG) { @@ -303,6 +339,9 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index, sa->integ_alg = alg; 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) + return VNET_API_ERROR_SYSCALL_ERROR_1; } else return VNET_API_ERROR_INVALID_VALUE; diff --git a/vnet/vnet/ipsec/ipsec_if_in.c b/vnet/vnet/ipsec/ipsec_if_in.c index 93cedce2..db75ab92 100644 --- a/vnet/vnet/ipsec/ipsec_if_in.c +++ b/vnet/vnet/ipsec/ipsec_if_in.c @@ -22,6 +22,12 @@ #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") @@ -153,8 +159,8 @@ VLIB_REGISTER_NODE (ipsec_if_input_node) = { .n_next_nodes = IPSEC_IF_INPUT_N_NEXT, .next_nodes = { - [IPSEC_IF_INPUT_NEXT_ESP_DECRYPT] = "esp-decrypt", - [IPSEC_IF_INPUT_NEXT_DROP] = "error-drop", + [IPSEC_IF_INPUT_NEXT_ESP_DECRYPT] = ESP_NODE, + [IPSEC_IF_INPUT_NEXT_DROP] = "error-drop", }, }; /* *INDENT-ON* */ diff --git a/vnet/vnet/ipsec/ipsec_if_out.c b/vnet/vnet/ipsec/ipsec_if_out.c index a605874e..8f062828 100644 --- a/vnet/vnet/ipsec/ipsec_if_out.c +++ b/vnet/vnet/ipsec/ipsec_if_out.c @@ -21,6 +21,11 @@ #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 \ @@ -140,7 +145,7 @@ VLIB_REGISTER_NODE (ipsec_if_output_node) = { .n_next_nodes = IPSEC_IF_OUTPUT_N_NEXT, .next_nodes = { - [IPSEC_IF_OUTPUT_NEXT_ESP_ENCRYPT] = "esp-encrypt", + [IPSEC_IF_OUTPUT_NEXT_ESP_ENCRYPT] = ESP_NODE, [IPSEC_IF_OUTPUT_NEXT_DROP] = "error-drop", }, }; diff --git a/vnet/vnet/ipsec/ipsec_input.c b/vnet/vnet/ipsec/ipsec_input.c index 8360a1d5..4662c1a1 100644 --- a/vnet/vnet/ipsec/ipsec_input.c +++ b/vnet/vnet/ipsec/ipsec_input.c @@ -23,9 +23,15 @@ #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-decrypt") +_(ESP_DECRYPT, ESP_NODE) #define _(v, s) IPSEC_INPUT_NEXT_##v, typedef enum diff --git a/vnet/vnet/ipsec/ipsec_output.c b/vnet/vnet/ipsec/ipsec_output.c index 3810520d..97977899 100644 --- a/vnet/vnet/ipsec/ipsec_output.c +++ b/vnet/vnet/ipsec/ipsec_output.c @@ -21,11 +21,17 @@ #include +#if DPDK_CRYPTO==1 +#define ESP_NODE "dpdk-esp-encrypt" +#else +#define ESP_NODE "esp-encrypt" +#endif + #if IPSEC > 0 #define foreach_ipsec_output_next \ _(DROP, "error-drop") \ -_(ESP_ENCRYPT, "esp-encrypt") +_(ESP_ENCRYPT, ESP_NODE) #define _(v, s) IPSEC_OUTPUT_NEXT_##v, typedef enum diff --git a/vpp/Makefile.am b/vpp/Makefile.am index 52ce0655..214cc743 100644 --- a/vpp/Makefile.am +++ b/vpp/Makefile.am @@ -13,7 +13,7 @@ AUTOMAKE_OPTIONS = foreign subdir-objects -AM_CFLAGS = -Wall @DPDK@ @IPSEC@ @VCGN@ @IPV6SR@ +AM_CFLAGS = -Wall @DPDK@ @DPDK_CRYPTO@ @IPSEC@ @VCGN@ @IPV6SR@ noinst_PROGRAMS = BUILT_SOURCES = @@ -110,6 +110,9 @@ else vpp_LDFLAGS += -l:libdpdk.a endif vpp_LDFLAGS += -Wl,--no-whole-archive +if WITH_DPDK_CRYPTO +vpp_LDADD += -L$(AESNI_MULTI_BUFFER_LIB_PATH) -lIPSec_MB +endif endif vpp_LDADD += -lvppinfra -lm -lpthread -ldl diff --git a/vpp/configure.ac b/vpp/configure.ac index 0bc13e63..d36695cc 100644 --- a/vpp/configure.ac +++ b/vpp/configure.ac @@ -9,6 +9,11 @@ AC_ARG_WITH(dpdk, [with_dpdk=1], [with_dpdk=0]) +AC_ARG_WITH(dpdk_crypto, + AC_HELP_STRING([--with-dpdk-crypto],[Use DPDK cryptodev]), + [with_dpdk_crypto=1], + [with_dpdk_crypto=0]) + AC_ARG_ENABLE(dpdk-shared, AC_HELP_STRING([--enable-dpdk-shared],[Link with DPDK shared lib]), [enable_dpdk_shared=1], @@ -32,6 +37,9 @@ AC_ARG_WITH(ipv6sr, AM_CONDITIONAL(WITH_DPDK, test "$with_dpdk" = "1") AM_CONDITIONAL(ENABLE_DPDK_SHARED, test "$enable_dpdk_shared" = "1") AC_SUBST(DPDK,["-DDPDK=${with_dpdk} -DDPDK_SHARED_LIB=${enable_dpdk_shared}"]) +AM_CONDITIONAL(WITH_DPDK_CRYPTO, test "$with_dpdk_crypto" = "1") +AC_SUBST(DPDK_CRYPTO,[-DDPDK_CRYPTO=${with_dpdk_crypto}]) + AM_COND_IF( [ENABLE_DPDK_SHARED], -- cgit 1.2.3-korg From 696f1adec0df3b8f161862566dd9c86174302658 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Fri, 23 Dec 2016 22:42:41 +0100 Subject: dpdk: Add support for Mellanox ConnectX-4 devices Due to external library dependency support for Mellanox devices is disabled. To enable it uncoment following line: vpp_uses_dpdk_mlx5_pmd = yes in build-data/platforms/vpp.mk and install OFED libraries. Change-Id: I131d52b5d449a958349f31f9cc04311948f78b71 Signed-off-by: Damjan Marion --- build-data/packages/dpdk.mk | 5 +++ build-data/packages/vnet.mk | 3 ++ build-data/packages/vpp.mk | 3 ++ build-data/platforms/vpp.mk | 1 + dpdk/Makefile | 4 +- vnet/vnet/devices/dpdk/dpdk.h | 2 + vnet/vnet/devices/dpdk/dpdk_priv.h | 9 +--- vnet/vnet/devices/dpdk/format.c | 8 ++++ vnet/vnet/devices/dpdk/init.c | 86 ++++++++++++++++++++++++++------------ vpp/Makefile.am | 3 ++ vpp/configure.ac | 7 +++- 11 files changed, 96 insertions(+), 35 deletions(-) (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index a529e365..2dcf4093 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -27,6 +27,11 @@ ifneq ($(DPDK_CRYPTO_PMD),) DPDK_MAKE_ARGS += DPDK_CRYPTO_PMD=y endif +DPDK_MLX5_PMD=$(strip $($(PLATFORM)_uses_dpdk_mlx5_pmd)) +ifneq ($(DPDK_MLX5_PMD),) +DPDK_MAKE_ARGS += DPDK_MLX5_PMD=y +endif + DPDK_PLATFORM_TARGET=$(strip $($(PLATFORM)_dpdk_target)) ifneq ($(DPDK_PLATFORM_TARGET),) DPDK_MAKE_ARGS += DPDK_TARGET=$(DPDK_PLATFORM_TARGET) diff --git a/build-data/packages/vnet.mk b/build-data/packages/vnet.mk index 399ca1b4..57c444e8 100644 --- a/build-data/packages/vnet.mk +++ b/build-data/packages/vnet.mk @@ -41,4 +41,7 @@ endif ifeq ($($(PLATFORM)_uses_dpdk_cryptodev),yes) vnet_configure_args += --with-dpdk-crypto endif +ifeq ($($(PLATFORM)_uses_dpdk_mlx5_pmd),yes) +vnet_configure_args += --with-dpdk-mlx5-pmd +endif endif diff --git a/build-data/packages/vpp.mk b/build-data/packages/vpp.mk index 6831c6b8..a3d60528 100644 --- a/build-data/packages/vpp.mk +++ b/build-data/packages/vpp.mk @@ -48,4 +48,7 @@ endif ifeq ($($(PLATFORM)_uses_dpdk_cryptodev),yes) vpp_configure_args += --with-dpdk-crypto endif +ifeq ($($(PLATFORM)_uses_dpdk_mlx5_pmd),yes) +vpp_configure_args += --with-dpdk-mlx5-pmd +endif endif diff --git a/build-data/platforms/vpp.mk b/build-data/platforms/vpp.mk index 15d4dc39..97ddc57d 100644 --- a/build-data/platforms/vpp.mk +++ b/build-data/platforms/vpp.mk @@ -42,6 +42,7 @@ plugins_configure_args_vpp = --with-dpdk # DPDK configuration parameters # vpp_uses_dpdk_cryptodev = yes +# vpp_uses_dpdk_mlx5_pmd = yes # vpp_uses_external_dpdk = yes # vpp_dpdk_inc_dir = /usr/include/dpdk # vpp_dpdk_lib_dir = /usr/lib diff --git a/dpdk/Makefile b/dpdk/Makefile index 46cc3db1..178c30c6 100644 --- a/dpdk/Makefile +++ b/dpdk/Makefile @@ -21,7 +21,8 @@ DPDK_DOWNLOAD_DIR ?= $(HOME)/Downloads DPDK_MARCH ?= native DPDK_TUNE ?= generic DPDK_DEBUG ?= n -DPDK_CRYPTO_PMD ?= n +DPDK_CRYPTO_PMD ?= n +DPDK_MLX5_PMD ?= n B := $(DPDK_BUILD_DIR) I := $(DPDK_INSTALL_DIR) @@ -122,6 +123,7 @@ $(B)/custom-config: $(B)/.patch.ok Makefile $(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_MLX5_PMD,$(DPDK_MLX5_PMD)) @# not needed $(call set,RTE_LIBRTE_TIMER,n) $(call set,RTE_LIBRTE_CFGFILE,n) diff --git a/vnet/vnet/devices/dpdk/dpdk.h b/vnet/vnet/devices/dpdk/dpdk.h index 3669bc5f..d8f378d2 100644 --- a/vnet/vnet/devices/dpdk/dpdk.h +++ b/vnet/vnet/devices/dpdk/dpdk.h @@ -83,6 +83,7 @@ extern vlib_node_registration_t handoff_dispatch_node; _ ("rte_bond_pmd", BOND) \ _ ("net_fm10k", FM10K) \ _ ("net_cxgbe", CXGBE) \ + _ ("net_mlx5", MLX5) \ _ ("net_dpaa2", DPAA2) #else #define foreach_dpdk_pmd \ @@ -118,6 +119,7 @@ typedef enum VNET_DPDK_PORT_TYPE_ETH_1G, VNET_DPDK_PORT_TYPE_ETH_10G, VNET_DPDK_PORT_TYPE_ETH_40G, + VNET_DPDK_PORT_TYPE_ETH_100G, VNET_DPDK_PORT_TYPE_ETH_BOND, VNET_DPDK_PORT_TYPE_ETH_SWITCH, VNET_DPDK_PORT_TYPE_AF_PACKET, diff --git a/vnet/vnet/devices/dpdk/dpdk_priv.h b/vnet/vnet/devices/dpdk/dpdk_priv.h index eb13df2c..0c81dbc3 100644 --- a/vnet/vnet/devices/dpdk/dpdk_priv.h +++ b/vnet/vnet/devices/dpdk/dpdk_priv.h @@ -13,15 +13,10 @@ * limitations under the License. */ -#define DPDK_NB_RX_DESC_DEFAULT 512 -#define DPDK_NB_TX_DESC_DEFAULT 512 +#define DPDK_NB_RX_DESC_DEFAULT 1024 +#define DPDK_NB_TX_DESC_DEFAULT 1024 #define DPDK_NB_RX_DESC_VIRTIO 256 #define DPDK_NB_TX_DESC_VIRTIO 256 -#define DPDK_NB_RX_DESC_10GE 1024 -#define DPDK_NB_TX_DESC_10GE 1024 -#define DPDK_NB_RX_DESC_40GE 1024 -#define DPDK_NB_TX_DESC_40GE 1024 -#define DPDK_NB_RX_DESC_ENIC 1024 #define I40E_DEV_ID_SFP_XL710 0x1572 #define I40E_DEV_ID_QSFP_A 0x1583 diff --git a/vnet/vnet/devices/dpdk/format.c b/vnet/vnet/devices/dpdk/format.c index 0b8a6939..ff7c7a5a 100644 --- a/vnet/vnet/devices/dpdk/format.c +++ b/vnet/vnet/devices/dpdk/format.c @@ -184,6 +184,10 @@ format_dpdk_device_name (u8 * s, va_list * args) device_name = "FortyGigabitEthernet"; break; + case VNET_DPDK_PORT_TYPE_ETH_100G: + device_name = "HundredGigabitEthernet"; + break; + case VNET_DPDK_PORT_TYPE_ETH_BOND: return format (s, "BondEthernet%d", dm->devices[i].device_index); @@ -268,6 +272,10 @@ format_dpdk_device_type (u8 * s, va_list * args) dev_type = "Chelsio T4/T5"; break; + case VNET_DPDK_PMD_MLX5: + dev_type = "Mellanox ConnectX-4 Family"; + break; + case VNET_DPDK_PMD_VMXNET3: dev_type = "VMware VMXNET3"; break; diff --git a/vnet/vnet/devices/dpdk/init.c b/vnet/vnet/devices/dpdk/init.c index 0448c15f..693ca985 100755 --- a/vnet/vnet/devices/dpdk/init.c +++ b/vnet/vnet/devices/dpdk/init.c @@ -293,11 +293,6 @@ dpdk_lib_init (dpdk_main_t * dm) vec_validate_aligned (dm->hqos_threads, tm->n_vlib_mains - 1, CLIB_CACHE_LINE_BYTES); -#ifdef NETMAP - if (rte_netmap_probe () < 0) - return clib_error_return (0, "rte netmap probe failed"); -#endif - nports = rte_eth_dev_count (); if (nports < 1) { @@ -448,6 +443,9 @@ dpdk_lib_init (dpdk_main_t * dm) else xd->pmd = VNET_DPDK_PMD_UNKNOWN; + xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN; + xd->nb_rx_desc = DPDK_NB_RX_DESC_DEFAULT; + xd->nb_tx_desc = DPDK_NB_TX_DESC_DEFAULT; switch (xd->pmd) { @@ -463,8 +461,6 @@ dpdk_lib_init (dpdk_main_t * dm) case VNET_DPDK_PMD_IXGBEVF: case VNET_DPDK_PMD_THUNDERX: xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G; - xd->nb_rx_desc = DPDK_NB_RX_DESC_10GE; - xd->nb_tx_desc = DPDK_NB_TX_DESC_10GE; break; case VNET_DPDK_PMD_DPAA2: xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G; @@ -474,17 +470,10 @@ dpdk_lib_init (dpdk_main_t * dm) case VNET_DPDK_PMD_ENIC: rte_eth_link_get_nowait (i, &l); xd->flags |= DPDK_DEVICE_FLAG_PMD_SUPPORTS_PTYPE; - xd->nb_rx_desc = DPDK_NB_RX_DESC_ENIC; if (l.link_speed == 40000) - { - xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G; - xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE; - } + xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G; else - { - xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G; - xd->nb_tx_desc = DPDK_NB_TX_DESC_10GE; - } + xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G; break; /* Intel Fortville */ @@ -492,8 +481,6 @@ dpdk_lib_init (dpdk_main_t * dm) case VNET_DPDK_PMD_I40EVF: xd->flags |= DPDK_DEVICE_FLAG_PMD_SUPPORTS_PTYPE; xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G; - xd->nb_rx_desc = DPDK_NB_RX_DESC_40GE; - xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE; switch (dev_info.pci_dev->id.device_id) { @@ -521,27 +508,74 @@ dpdk_lib_init (dpdk_main_t * dm) { case 0x540d: /* T580-CR */ case 0x5410: /* T580-LP-cr */ - xd->nb_rx_desc = DPDK_NB_RX_DESC_40GE; - xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE; xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G; break; case 0x5403: /* T540-CR */ - xd->nb_rx_desc = DPDK_NB_RX_DESC_10GE; - xd->nb_tx_desc = DPDK_NB_TX_DESC_10GE; xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G; break; default: - xd->nb_rx_desc = DPDK_NB_RX_DESC_10GE; - xd->nb_tx_desc = DPDK_NB_TX_DESC_10GE; xd->port_type = VNET_DPDK_PORT_TYPE_UNKNOWN; } break; + case VNET_DPDK_PMD_MLX5: + { + char *pn_100g[] = { "MCX415A-CCAT", "MCX416A-CCAT", 0 }; + char *pn_40g[] = { "MCX413A-BCAT", "MCX414A-BCAT", + "MCX415A-BCAT", "MCX416A-BCAT", "MCX4131A-BCAT", 0 + }; + char *pn_10g[] = { "MCX4111A-XCAT", "MCX4121A-XCAT", 0 }; + + vlib_pci_device_t *pd = vlib_get_pci_device (&pci_addr); + u8 *pn = 0; + char **c; + int found = 0; + pn = format (0, "%U%c", + format_vlib_pci_vpd, pd->vpd_r, "PN", 0); + + if (!pn) + break; + + c = pn_100g; + while (!found && c[0]) + { + if (strncmp ((char *) pn, c[0], strlen (c[0])) == 0) + { + xd->port_type = VNET_DPDK_PORT_TYPE_ETH_100G; + break; + } + c++; + } + + c = pn_40g; + while (!found && c[0]) + { + if (strncmp ((char *) pn, c[0], strlen (c[0])) == 0) + { + xd->port_type = VNET_DPDK_PORT_TYPE_ETH_40G; + break; + } + c++; + } + + c = pn_10g; + while (!found && c[0]) + { + if (strncmp ((char *) pn, c[0], strlen (c[0])) == 0) + { + xd->port_type = VNET_DPDK_PORT_TYPE_ETH_10G; + break; + } + c++; + } + + vec_free (pn); + } + + break; /* Intel Red Rock Canyon */ case VNET_DPDK_PMD_FM10K: xd->port_type = VNET_DPDK_PORT_TYPE_ETH_SWITCH; - xd->nb_rx_desc = DPDK_NB_RX_DESC_40GE; - xd->nb_tx_desc = DPDK_NB_TX_DESC_40GE; break; /* virtio */ diff --git a/vpp/Makefile.am b/vpp/Makefile.am index f90cb647..25d72749 100644 --- a/vpp/Makefile.am +++ b/vpp/Makefile.am @@ -121,6 +121,9 @@ vpp_LDFLAGS += -Wl,--no-whole-archive if WITH_DPDK_CRYPTO vpp_LDADD += -L$(AESNI_MULTI_BUFFER_LIB_PATH) -lIPSec_MB endif +if WITH_DPDK_MLX5_PMD +vpp_LDFLAGS += -libverbs -lmlx5 -lnuma +endif endif vpp_LDADD += -lvppinfra -lm -lpthread -ldl diff --git a/vpp/configure.ac b/vpp/configure.ac index 2ade3d2a..8c333fd1 100644 --- a/vpp/configure.ac +++ b/vpp/configure.ac @@ -14,6 +14,11 @@ AC_ARG_WITH(dpdk_crypto, [with_dpdk_crypto=1], [with_dpdk_crypto=0]) +AC_ARG_WITH(dpdk_mlx5_pmd, + AC_HELP_STRING([--with-dpdk-mlx5-pmd],[Use Mellanox ConnetxX-4 DPDK PMD]), + [with_dpdk_mlx5_pmd=1], + [with_dpdk_mlx5_pmd=0]) + AC_ARG_ENABLE(dpdk-shared, AC_HELP_STRING([--enable-dpdk-shared],[Link with DPDK shared lib]), [enable_dpdk_shared=1], @@ -44,7 +49,7 @@ AM_CONDITIONAL(ENABLE_DPDK_SHARED, test "$enable_dpdk_shared" = "1") AC_SUBST(DPDK,["-DDPDK=${with_dpdk} -DDPDK_SHARED_LIB=${enable_dpdk_shared}"]) AM_CONDITIONAL(WITH_DPDK_CRYPTO, test "$with_dpdk_crypto" = "1") AC_SUBST(DPDK_CRYPTO,[-DDPDK_CRYPTO=${with_dpdk_crypto}]) - +AM_CONDITIONAL(WITH_DPDK_MLX5_PMD, test "$with_dpdk_mlx5_pmd" = "1") AM_COND_IF( [ENABLE_DPDK_SHARED], -- cgit 1.2.3-korg From 2ce7f9834ab55728520bff0dd15f8d82c10b95a0 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 9 Jan 2017 20:24:50 +0100 Subject: Add dpdk development packaging Change-Id: I6aa2a6709241d99ce734c29e47487eb456907351 Signed-off-by: Damjan Marion --- Makefile | 25 ++++--- build-data/packages/dpdk.mk | 6 +- build-data/packages/vpp.mk | 3 +- build-data/platforms.mk | 4 -- build-root/Makefile | 1 - build-root/deb/debian/.gitignore | 3 - build-root/deb/debian/control | 17 +---- build-root/deb/debian/rules | 5 +- build-root/rpm/vpp.spec | 1 - build-root/scripts/find-dpdk-contents | 29 -------- dpdk/Makefile | 126 ++++++++++++++++++++++++++++++++-- dpdk/deb/debian/compat | 1 + dpdk/deb/debian/control | 18 +++++ dpdk/deb/debian/dkms/Makefile | 10 +++ dpdk/deb/debian/rules | 38 ++++++++++ dpdk/deb/debian/vpp-dpdk-dkms.dkms | 8 +++ dpdk/dkms/Makefile | 10 --- dpdk/dkms/create_deb_manifest.sh | 28 -------- dpdk/rpm/vpp-dpdk.spec | 26 +++++++ 19 files changed, 244 insertions(+), 115 deletions(-) delete mode 100755 build-root/scripts/find-dpdk-contents create mode 100755 dpdk/deb/debian/compat create mode 100644 dpdk/deb/debian/control create mode 100644 dpdk/deb/debian/dkms/Makefile create mode 100755 dpdk/deb/debian/rules create mode 100644 dpdk/deb/debian/vpp-dpdk-dkms.dkms delete mode 100644 dpdk/dkms/Makefile delete mode 100755 dpdk/dkms/create_deb_manifest.sh create mode 100644 dpdk/rpm/vpp-dpdk.spec (limited to 'build-data/packages/dpdk.mk') diff --git a/Makefile b/Makefile index f1813a30..71eec082 100644 --- a/Makefile +++ b/Makefile @@ -30,6 +30,12 @@ OS_ID = $(shell grep '^ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\" OS_VERSION_ID= $(shell grep '^VERSION_ID=' /etc/os-release | cut -f2- -d= | sed -e 's/\"//g') endif +ifeq ($(OS_ID),ubuntu) +PKG=deb +else ifeq ($(OS_ID),centos) +PKG=rpm +endif + DEB_DEPENDS = curl build-essential autoconf automake bison libssl-dev ccache DEB_DEPENDS += debhelper dkms git libtool libganglia1-dev libapr1-dev dh-systemd DEB_DEPENDS += libconfuse-dev git-review exuberant-ctags cscope pkg-config @@ -84,6 +90,7 @@ help: @echo " run-vat - run vpp-api-test tool" @echo " pkg-deb - build DEB packages" @echo " pkg-rpm - build RPM packages" + @echo " dpdk-install-dev - install DPDK development packages" @echo " ctags - (re)generate ctags database" @echo " gtags - (re)generate gtags database" @echo " cscope - (re)generate cscope database" @@ -295,6 +302,9 @@ pkg-deb: pkg-rpm: dist $(call make,$(PLATFORM),install-rpm) +dpdk-install-dev: + make -C dpdk install-$(PKG) + ctags: ctags.files @ctags --totals --tag-relative -L $< @rm $< @@ -340,26 +350,19 @@ define banner @echo " " endef -verify: install-dep $(BR)/.bootstrap.ok +verify: install-dep $(BR)/.bootstrap.ok dpdk-install-dev $(call banner,"Building for PLATFORM=vpp using gcc") @make -C build-root PLATFORM=vpp TAG=vpp wipe-all install-packages $(call banner,"Building for PLATFORM=vpp_lite using gcc") @make -C build-root PLATFORM=vpp_lite TAG=vpp_lite wipe-all install-packages -ifeq ($(OS_ID),ubuntu) -ifeq ($(OS_VERSION_ID),16.04) +ifeq ($(OS_ID)-$(OS_VERSION_ID),ubuntu-16.04) $(call banner,"Installing dependencies") @sudo -E apt-get update @sudo -E apt-get $(CONFIRM) $(FORCE) install clang $(call banner,"Building for PLATFORM=vpp using clang") @make -C build-root CC=clang PLATFORM=vpp TAG=vpp_clang wipe-all install-packages endif - $(call banner,"Building deb packages") - @make pkg-deb -endif -ifeq ($(OS_ID),centos) - $(call banner,"Building rpm packages") - @make pkg-rpm -endif - @make test + $(call banner,"Building $(PKG) packages") + @make pkg-$(PKG) diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index 2dcf4093..6c136824 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -42,8 +42,8 @@ ifneq ($(DPDK_MAKE_EXTRA_ARGS),) DPDK_MAKE_ARGS += DPDK_MAKE_EXTRA_ARGS="$(DPDK_MAKE_EXTRA_ARGS)" endif -dpdk_configure = echo +dpdk_configure = echo -dpdk_make_args = $(DPDK_MAKE_ARGS) config +dpdk_make_args = $(DPDK_MAKE_ARGS) ebuild-build -dpdk_install = make $(DPDK_MAKE_ARGS) build +dpdk_install = make $(DPDK_MAKE_ARGS) ebuild-install diff --git a/build-data/packages/vpp.mk b/build-data/packages/vpp.mk index fe68cd82..81aeab69 100644 --- a/build-data/packages/vpp.mk +++ b/build-data/packages/vpp.mk @@ -19,8 +19,9 @@ vpp_CPPFLAGS += -I$($(PLATFORM)_dpdk_inc_dir) vpp_LDFLAGS += -L$($(PLATFORM)_dpdk_lib_dir) else vpp_configure_depend += dpdk-install -vpp_CPPFLAGS += $(call installed_includes_fn, dpdk) +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 diff --git a/build-data/platforms.mk b/build-data/platforms.mk index 41836750..2351898e 100644 --- a/build-data/platforms.mk +++ b/build-data/platforms.mk @@ -63,10 +63,6 @@ install-deb: $(patsubst %,%-find-source,$(ROOT_PACKAGES)) ./scripts/find-vpp-api-python-contents $(INSTALL_PREFIX)$(ARCH) \ deb/debian/vpp-api-python.install ; \ \ - : dpdk headers ; \ - ./scripts/find-dpdk-contents $(INSTALL_PREFIX)$(ARCH) \ - deb/debian/vpp-dpdk-dev.install ; \ - \ : bin package needs startup config ; \ echo ../../src/vpp/conf/startup.conf /etc/vpp \ >> deb/debian/vpp.install ; \ diff --git a/build-root/Makefile b/build-root/Makefile index 6e26e90e..8b83990e 100644 --- a/build-root/Makefile +++ b/build-root/Makefile @@ -1167,5 +1167,4 @@ distclean: rm -rf $(MU_BUILD_ROOT_DIR)/python if [ -e /usr/bin/dh ];then (cd $(MU_BUILD_ROOT_DIR)/deb/;debian/rules clean); fi rm -f $(MU_BUILD_ROOT_DIR)/deb/debian/*.install - rm -f $(MU_BUILD_ROOT_DIR)/deb/debian/*.dkms rm -f $(MU_BUILD_ROOT_DIR)/deb/debian/changelog diff --git a/build-root/deb/debian/.gitignore b/build-root/deb/debian/.gitignore index c5e915a8..7b1028d6 100644 --- a/build-root/deb/debian/.gitignore +++ b/build-root/deb/debian/.gitignore @@ -3,12 +3,9 @@ files *debhelper* *.substvars *.install -vpp-dpdk-dkms* vpp/ vpp-dev/ vpp-lib/ -vpp-dpdk-dev/ -vpp-dpdk-dkms/ vpp-dbg/ vppctl/ vpp-api-lua/ diff --git a/build-root/deb/debian/control b/build-root/deb/debian/control index 6d26266a..e90cfca8 100644 --- a/build-root/deb/debian/control +++ b/build-root/deb/debian/control @@ -2,7 +2,7 @@ Source: vpp Section: net Priority: extra Maintainer: Cisco OpenVPP Packaging Team -Build-Depends: debhelper (>= 9), dkms, dh-systemd, dh-python, chrpath +Build-Depends: debhelper (>= 9), dh-systemd, dh-python, chrpath Standards-Version: 3.9.4 Package: vpp @@ -26,14 +26,6 @@ Description: Vector Packet Processing--development support This package contains development support files for the VPP libraries . -Package: vpp-dpdk-dev -Architecture: any -Depends: ${misc:Depends} -Description: Vector Packet Processing--development support - This package contains dpdk header files which match the dpdk version - compiled into the vpp executable - . - Package: vpp-lib Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} @@ -41,7 +33,6 @@ Description: Vector Packet Processing--runtime libraries This package contains the VPP shared libraries, including: . vppinfra - foundation library supporting vectors, hashes, bitmaps, pools, and string formatting. - dpdk - DPDK library svm - vm library vlib - vector processing library vlib-api - binary API library @@ -54,12 +45,6 @@ Description: Vector Packet Processing--runtime plugins This package contains VPP plugins . -Package: vpp-dpdk-dkms -Architecture: any -Depends: ${misc:Depends} -Description: DPDK 2.1 igb_uio_driver - This package contains Linux kernel modules distributed with DPDK. - Package: vpp-api-lua Architecture: any Depends: ${misc:Depends}, vpp (= ${source:Version}) diff --git a/build-root/deb/debian/rules b/build-root/deb/debian/rules index 4c84fc32..7046105c 100755 --- a/build-root/deb/debian/rules +++ b/build-root/deb/debian/rules @@ -18,7 +18,7 @@ include /usr/share/dpkg/default.mk # main packaging script based on dh7 syntax %: - dh $@ --with dkms --with systemd,python2 + dh $@ --with systemd,python2 override_dh_install: dh_install --exclude .git @@ -31,6 +31,3 @@ override_dh_shlibdeps: override_dh_strip: dh_strip --dbg-package=vpp-dbg - -override_dh_dkms: - dh_dkms -pvpp-dpdk-dkms diff --git a/build-root/rpm/vpp.spec b/build-root/rpm/vpp.spec index b3a337b1..9e3ad11b 100644 --- a/build-root/rpm/vpp.spec +++ b/build-root/rpm/vpp.spec @@ -43,7 +43,6 @@ Group: System Environment/Libraries %description lib This package contains the VPP shared libraries, including: vppinfra - foundation library supporting vectors, hashes, bitmaps, pools, and string formatting. -dpdk - DPDK library svm - vm library vlib - vector processing library vlib-api - binary API library diff --git a/build-root/scripts/find-dpdk-contents b/build-root/scripts/find-dpdk-contents deleted file mode 100755 index c7065139..00000000 --- a/build-root/scripts/find-dpdk-contents +++ /dev/null @@ -1,29 +0,0 @@ -#!/bin/bash - -# includes -rm -rf dpdk-includes -mkdir dpdk-includes -(cd $1/dpdk/include; tar cfh - . | (cd ../../../dpdk-includes; tar xf -)) - -# If CDPATH is set, the "Change Directory" builtin (cd) will output the -# destination directory when a relative path is passed as an argument. -# In this case, this has the negative side effect of polluting the "paths" -# variable with the destination directory, breaking the package generation. -# -# Patient: Doctor! Doctor! It hurts when I do this... -# Doctor: Don't do that! -# -unset CDPATH -paths=`cd dpdk-includes; find . -type f -print` -rm -f $2 - -for path in $paths -do - dir=`dirname $path` - if [ $dir = "." ] ; then - echo ../dpdk-includes/$path /usr/include/vpp-dpdk >> $2 - else - echo ../dpdk-includes/$path /usr/include/vpp-dpdk/$dir >> $2 - fi -done - diff --git a/dpdk/Makefile b/dpdk/Makefile index 82804f20..f6f90e0d 100644 --- a/dpdk/Makefile +++ b/dpdk/Makefile @@ -27,6 +27,7 @@ DPDK_MLX5_PMD ?= n B := $(DPDK_BUILD_DIR) I := $(DPDK_INSTALL_DIR) DPDK_VERSION ?= 16.11 +PKG_SUFFIX ?= vpp1 DPDK_BASE_URL ?= http://fast.dpdk.org/rel DPDK_TARBALL := dpdk-$(DPDK_VERSION).tar.xz DPDK_TAR_URL := $(DPDK_BASE_URL)/$(DPDK_TARBALL) @@ -81,11 +82,11 @@ endif DPDK_MAKE_ARGS := -C $(DPDK_SOURCE) -j $(JOBS) \ T=$(DPDK_TARGET) \ RTE_CONFIG_TEMPLATE=../custom-config \ - RTE_OUTPUT=$(I) \ EXTRA_CFLAGS="$(DPDK_EXTRA_CFLAGS)" \ EXTRA_LDFLAGS="$(DPDK_EXTRA_LDFLAGS)" \ CPU_CFLAGS="$(DPDK_CPU_CFLAGS)" \ CPU_LDFLAGS="$(DPDK_CPU_LDFLAGS)" \ + DESTDIR=$(I) \ $(DPDK_MAKE_EXTRA_ARGS) DPDK_SOURCE_FILES := $(shell [ -e $(DPDK_SOURCE) ] && find $(DPDK_SOURCE) -name "*.[chS]") @@ -140,7 +141,6 @@ $(B)/custom-config: $(B)/.patch.ok Makefile @rm -f .config.ok $(CURDIR)/$(DPDK_TARBALL): - @mkdir -p $(B) @if [ -e $(DPDK_DOWNLOAD_DIR)/$(DPDK_TARBALL) ] ; \ then cp $(DPDK_DOWNLOAD_DIR)/$(DPDK_TARBALL) $(CURDIR) ; \ else curl -o $(CURDIR)/$(DPDK_TARBALL) -LO $(DPDK_TAR_URL) ; \ @@ -148,6 +148,7 @@ $(CURDIR)/$(DPDK_TARBALL): @rm -f $(B)/.download.ok $(B)/.download.ok: $(CURDIR)/$(DPDK_TARBALL) + @mkdir -p $(B) @openssl md5 $< | cut -f 2 -d " " - > $(B)/$(DPDK_TARBALL).md5sum @([ "$$(<$(B)/$(DPDK_TARBALL).md5sum)" = "$(DPDK_$(DPDK_VERSION)_TARBALL_MD5_CKSUM)" ] || \ ( echo "Bad Checksum! Please remove $< and retry" && \ @@ -168,7 +169,7 @@ extract: $(B)/.extract.ok $(B)/.patch.ok: $(B)/.extract.ok ifneq ($(wildcard $(CURDIR)/dpdk-$(DPDK_VERSION)_patches/*.patch),) @echo --- patching --- - for f in $(CURDIR)/dpdk-$(DPDK_VERSION)_patches/*.patch ; do \ + @for f in $(CURDIR)/dpdk-$(DPDK_VERSION)_patches/*.patch ; do \ echo Applying patch: $$(basename $$f) ; \ patch -p1 -d $(DPDK_SOURCE) < $$f ; \ done @@ -188,13 +189,130 @@ config: $(B)/.config.ok $(B)/.build.ok: $(DPDK_SOURCE_FILES) @if [ ! -e $(B)/.config.ok ] ; then echo 'Please run "make config" first' && false ; fi @make $(DPDK_MAKE_ARGS) install - @dkms/create_deb_manifest.sh $(DPDK_VERSION) $(subst $(realpath ..)/,,$(B)) @touch $@ .PHONY: build build: $(B)/.build.ok +.PHONY: install +install: $(B)/.build.ok + .PHONY: clean clean: @rm -rf $(B) $(I) +############################################################################## +# .deb packaging +############################################################################## + +DEB_ARCH=$(shell dpkg --print-architecture 2> /dev/null) +DEV_DEB=vpp-dpdk-dev_$(DPDK_VERSION)-$(PKG_SUFFIX)_$(DEB_ARCH).deb +INSTALLED_DEB_VER=$(shell dpkg-query --showformat='$${Version}' --show vpp-dpdk-dev 2> /dev/null) + +.PHONY: build-deb install-deb check-deb + +deb/debian/changelog: Makefile + @echo "vpp-dpdk ($(DPDK_VERSION)-$(PKG_SUFFIX)) unstable; urgency=low" > $@ + @echo "" >> $@ + @echo " * DPDK Release $(DPDK_VERSION)" >> $@ + @echo "" >> $@ + @echo " -- VPP Dev $(shell date -R)" >> $@ + +$(DEV_DEB): deb/debian/changelog + @cd deb && dpkg-buildpackage -b -uc -us + git clean -fdx deb + +build-deb: $(DEV_DEB) + +install-deb: +ifneq ($(INSTALLED_DEB_VER),$(DPDK_VERSION)-$(PKG_SUFFIX)) + @make $(DEV_DEB) + @sudo dpkg -i $(DEV_DEB) +else + @echo "==========================================================" + @echo " Up-to-date DPDK package already installed" + @echo "==========================================================" +endif + +check-deb: +ifneq ($(INSTALLED_DEB_VER),$(DPDK_VERSION)-$(PKG_SUFFIX)) + @echo "==========================================================" + @echo " Outdated DPDK package detected:" + @echo " Installed: vpp-dpdk-dev $(INSTALLED_DEB_VER)" + @echo " Current: vpp-dpdk-dev $(DPDK_VERSION)-$(PKG_SUFFIX)" + @echo "" + @echo " Please upgrade by invoking 'make dpdk-install-dev'" + @echo " from the top level directory." + @echo "==========================================================" +endif + +############################################################################## +# .rpm packaging +############################################################################## + +RPM_ARCH=$(shell rpm --eval "%{_arch}" 2> /dev/null) +DEV_RPM=vpp-dpdk-devel-$(DPDK_VERSION)-$(PKG_SUFFIX).$(RPM_ARCH).rpm +INSTALLED_RPM_VER=$(shell rpm -q --queryformat '%{VERSION}-%{RELEASE}' vpp-dpdk-devel | grep -v "not inst") + +.PHONY: build-rpm install-rpm check-rpm + +$(DEV_RPM): Makefile rpm/vpp-dpdk.spec + @rpmbuild -bb \ + --define "_topdir $(CURDIR)/rpm" \ + --define "_version $(DPDK_VERSION)" \ + --define "_release $(PKG_SUFFIX)" \ + $(CURDIR)/rpm/vpp-dpdk.spec + mv rpm/RPMS/$(RPM_ARCH)/*.rpm . + git clean -fdx rpm + +build-rpm: $(DEV_RPM) + +install-rpm: +ifneq ($(INSTALLED_RPM_VER),$(DPDK_VERSION)-$(PKG_SUFFIX)) + @make $(DEV_RPM) + sudo rpm -Uih $(DEV_RPM) +else + @echo "==========================================================" + @echo " Up-to-date DPDK package already installed" + @echo "==========================================================" +endif + +check-rpm: +ifneq ($(INSTALLED_RPM_VER),$(DPDK_VERSION)-$(PKG_SUFFIX)) + @echo "==========================================================" + @echo " Outdated DPDK package detected:" + @echo " Installed: vpp-dpdk-devel $(INSTALLED_RPM_VER)" + @echo " Current: vpp-dpdk-devel $(DPDK_VERSION)-$(PKG_SUFFIX)" + @echo "" + @echo " Please upgrade by invoking 'make dpdk-install-dev'" + @echo " from the top level directory." + @echo "==========================================================" +endif + +############################################################################## +# ebuild support +############################################################################## + +.PHONY: ebuild-build ebuild-install + +ebuild-build: +ifeq ($(INSTALLED_DEB_VER)$(INSTALLED_RPM_VER),) + @echo "==========================================================" + @echo "Building DPDK from source. Consider installing development" + @echo "package by invoking 'make dpdk-install-dev' from the" + @echo "top level directory" + @echo "==========================================================" + make config +else +ifneq ($(INSTALLED_DEB_VER),) + make check-deb +endif +ifneq ($(INSTALLED_RPM_VER),) + make check-rpm +endif +endif + +ebuild-install: +ifeq ($(INSTALLED_DEB_VER)$(INSTALLED_RPM_VER),) + make install +endif diff --git a/dpdk/deb/debian/compat b/dpdk/deb/debian/compat new file mode 100755 index 00000000..ec635144 --- /dev/null +++ b/dpdk/deb/debian/compat @@ -0,0 +1 @@ +9 diff --git a/dpdk/deb/debian/control b/dpdk/deb/debian/control new file mode 100644 index 00000000..9ffa1a0a --- /dev/null +++ b/dpdk/deb/debian/control @@ -0,0 +1,18 @@ +Source: vpp-dpdk +Section: net +Priority: extra +Maintainer: vpp-dev@lists.fd.io +Build-Depends: debhelper (>= 9), dkms +Standards-Version: 3.9.4 + +Package: vpp-dpdk-dev +Architecture: any +Depends: ${shlibs:Depends} +Description: DPDK Development Package for VPP +Conflicts: dpdk, dpdk-dev, libdpdk-dev + +Package: vpp-dpdk-dkms +Architecture: any +Depends: ${misc:Depends} +Description: DPDK Development Package for VPP - Kernel Modules +Conflicts: dpdk-igb-uio-dkms diff --git a/dpdk/deb/debian/dkms/Makefile b/dpdk/deb/debian/dkms/Makefile new file mode 100644 index 00000000..452c7c26 --- /dev/null +++ b/dpdk/deb/debian/dkms/Makefile @@ -0,0 +1,10 @@ +obj-m:=igb_uio.o + +CONFIG_MODULE_SIG=n + +EXTRA_CFLAGS += -Winline -I$(PWD) + +default: + $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules +clean: + $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean diff --git a/dpdk/deb/debian/rules b/dpdk/deb/debian/rules new file mode 100755 index 00000000..98b1048b --- /dev/null +++ b/dpdk/deb/debian/rules @@ -0,0 +1,38 @@ +#!/usr/bin/make -f +DH_VERBOSE = 1 +PKG=vpp-dpdk + +VERSION = $(shell dpkg-parsechangelog | sed -nr '/^Version:/s/Version: //p') +BASE_VER = $(word 1, $(subst -, ,$(VERSION))) + +export DPDK_BUILD_DIR=$(CURDIR)/_build +export DPDK_INSTALL_DIR=$(CURDIR)/debian/tmp/usr + +SRC=_build/dpdk-$(BASE_VER) + +MAKE_ARGS=-C .. + +include /usr/share/dpkg/default.mk + +%: + dh $@ --with dkms + +override_dh_clean: + make $(MAKE_ARGS) clean + +override_dh_auto_configure: + make $(MAKE_ARGS) config + +override_dh_install: + make $(MAKE_ARGS) install + dh_install -p$(PKG)-dkms \ + $(SRC)/lib/librte_eal/common/include/rte_pci_dev_feature_defs.h \ + $(SRC)/lib/librte_eal/common/include/rte_pci_dev_features.h \ + $(SRC)/lib/librte_eal/linuxapp/igb_uio/igb_uio.c \ + $(SRC)/lib/librte_eal/linuxapp/igb_uio/compat.h \ + debian/dkms/Makefile \ + /usr/src/$(PKG)-dkms-$(VERSION) + dh_install -p$(PKG)-dev --autodest /usr + +override_dh_dkms: + dh_dkms -p$(PKG)-dkms -V $(VERSION) diff --git a/dpdk/deb/debian/vpp-dpdk-dkms.dkms b/dpdk/deb/debian/vpp-dpdk-dkms.dkms new file mode 100644 index 00000000..a166c313 --- /dev/null +++ b/dpdk/deb/debian/vpp-dpdk-dkms.dkms @@ -0,0 +1,8 @@ +PACKAGE_VERSION=#MODULE_VERSION# +PACKAGE_NAME="vpp-dpdk-dkms" +CLEAN="make clean" +BUILT_MODULE_NAME[0]="igb_uio" +BUILT_MODULE_LOCATION[0]="./" +DEST_MODULE_LOCATION[0]="/kernel/net" +MAKE[1]="make" +AUTOINSTALL="yes" diff --git a/dpdk/dkms/Makefile b/dpdk/dkms/Makefile deleted file mode 100644 index 452c7c26..00000000 --- a/dpdk/dkms/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -obj-m:=igb_uio.o - -CONFIG_MODULE_SIG=n - -EXTRA_CFLAGS += -Winline -I$(PWD) - -default: - $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules -clean: - $(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean diff --git a/dpdk/dkms/create_deb_manifest.sh b/dpdk/dkms/create_deb_manifest.sh deleted file mode 100755 index f8305588..00000000 --- a/dpdk/dkms/create_deb_manifest.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh - -VER=$1 -DPDK_ROOT=../../$2/dpdk-${VER} -DEBIAN_DIR=../build-root/deb/debian -SRC_DIR=/usr/src/vpp-dpdk-dkms-${VER}/ - - -cat > ${DEBIAN_DIR}/vpp-dpdk-dkms.install << _EOF_ -${DPDK_ROOT}/lib/librte_eal/common/include/rte_pci_dev_feature_defs.h ${SRC_DIR} -${DPDK_ROOT}/lib/librte_eal/common/include/rte_pci_dev_features.h ${SRC_DIR} -${DPDK_ROOT}/lib/librte_eal/linuxapp/igb_uio/igb_uio.c ${SRC_DIR} -${DPDK_ROOT}/lib/librte_eal/linuxapp/igb_uio/compat.h ${SRC_DIR} -../../dpdk/dkms/Makefile ${SRC_DIR} -_EOF_ - - -# dkms config -cat > ${DEBIAN_DIR}/vpp-dpdk-dkms.dkms << _EOF_ -PACKAGE_VERSION="${VER}" -PACKAGE_NAME="vpp-dpdk-dkms" -CLEAN="make clean" -BUILT_MODULE_NAME[0]="igb_uio" -BUILT_MODULE_LOCATION[0]="./" -DEST_MODULE_LOCATION[0]="/kernel/net" -MAKE[1]="make" -AUTOINSTALL="yes" -_EOF_ diff --git a/dpdk/rpm/vpp-dpdk.spec b/dpdk/rpm/vpp-dpdk.spec new file mode 100644 index 00000000..cc617681 --- /dev/null +++ b/dpdk/rpm/vpp-dpdk.spec @@ -0,0 +1,26 @@ +%define _make_args -C ../.. DPDK_BUILD_DIR=%{_topdir}/tmp DPDK_INSTALL_DIR=%{buildroot}/usr + +Name: vpp-dpdk +Version: %{_version} +Release: %{_release} +Summary: DPDK development packages for VPP +License: BSD + +%description + +%package devel +Summary: DPDK development package for VPP +Group: Development/Libraries + +%description devel + +%install +make %{_make_args} config +make %{_make_args} install + +%files devel +/usr/bin/* +/usr/include/dpdk +/usr/lib/* +/usr/sbin/* +/usr/share/dpdk -- 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 'build-data/packages/dpdk.mk') 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 78edb8e722fe2bb72ba7f8e63b420733c7fb51c6 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Mon, 6 Feb 2017 22:28:52 +0100 Subject: Multiple platofrm support for dpdk/Makefile, fix optimizations Using -march=native was causing SIGILLs on Atoms. Change-Id: I98c7fdaa139e3db70c972950dc9c167bf5803656 Signed-off-by: Damjan Marion --- build-data/packages/dpdk.mk | 12 ---------- build-data/platforms/thunder.mk | 36 ---------------------------- build-data/platforms/vpp.mk | 3 --- dpdk/Makefile | 52 ++++++++++++++++++++--------------------- 4 files changed, 25 insertions(+), 78 deletions(-) delete mode 100644 build-data/platforms/thunder.mk (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index 6938392c..ed89bb1b 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -1,14 +1,4 @@ -DPDK_MARCH = $(strip $($(PLATFORM)_dpdk_arch)) -ifeq ($(DPDK_MARCH),) - DPDK_MARCH="native" -endif - -DPDK_TUNE = $(strip $($(PLATFORM)_mtune)) -ifeq ($(DPDK_TUNE),) - DPDK_TUNE="generic" -endif - ifneq (,$(findstring debug,$(TAG))) DPDK_DEBUG=y else @@ -18,8 +8,6 @@ endif DPDK_MAKE_ARGS = -C $(call find_source_fn,$(PACKAGE_SOURCE)) \ DPDK_BUILD_DIR=$(PACKAGE_BUILD_DIR) \ DPDK_INSTALL_DIR=$(PACKAGE_INSTALL_DIR) \ - DPDK_MARCH=$(DPDK_MARCH) \ - DPDK_TUNE=$(DPDK_TUNE) \ DPDK_DEBUG=$(DPDK_DEBUG) DPDK_CRYPTO_SW_PMD=$(strip $($(PLATFORM)_uses_dpdk_cryptodev_sw)) diff --git a/build-data/platforms/thunder.mk b/build-data/platforms/thunder.mk deleted file mode 100644 index 31b6a510..00000000 --- a/build-data/platforms/thunder.mk +++ /dev/null @@ -1,36 +0,0 @@ -# Override OS so we can use the sdk toolchain instead of building one -thunder_os = thunderx-linux-gnu - -# Override CROSS_LDFLAGS so we can use -# /lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 instead of building glibc -thunder_cross_ldflags = \ - -Wl,--dynamic-linker=/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1 \ - -Wl,-rpath -Wl,$(lots_of_slashes_to_pad_names)$(TOOL_INSTALL_LIB_DIR) - -thunder_arch = aarch64 -# suppress -march=foo, the cross compiler doesn't understand it -thunder_march = " " - -thunder_root_packages = vppinfra vlib-cavium-dpdk vnet-cavium-dpdk cavium-dpdk \ - vpp-cavium-dpdk vpp-api-test-cavium-dpdk - -vnet-cavium-dpdk_configure_args_thunder = \ - --with-dpdk --without-libssl - -vpp-cavium-dpdk_configure_args_thunder = \ - --with-dpdk --without-libssl - -cavium-dpdk_configure_args_thunder = --with-headroom=256 - -vlib-cavium-dpdk_configure_args_thunder = --with-pre-data=128 - -# native tool chain additions for this platform -thunder_native_tools = vppapigen - -thunder_debug_TAG_CFLAGS = -g -O0 -DCLIB_DEBUG -thunder_debug_TAG_LDFLAGS = -g -O0 -DCLIB_DEBUG - -thunder_TAG_CFLAGS = -g -O2 -thunder_TAG_LDFLAGS = -g -O2 - - diff --git a/build-data/platforms/vpp.mk b/build-data/platforms/vpp.mk index ee307639..401a383a 100644 --- a/build-data/platforms/vpp.mk +++ b/build-data/platforms/vpp.mk @@ -16,17 +16,14 @@ vpp_arch = native ifeq ($(shell uname -m),x86_64) vpp_march = corei7 # Nehalem Instruction set vpp_mtune = corei7-avx # Optimize for Sandy Bridge -vpp_dpdk_arch = corei7 else ifeq ($(shell uname -m),aarch64) ifeq ($(TARGET_PLATFORM),thunderx) vpp_march = armv8-a+crc vpp_mtune = thunderx -vpp_dpdk_arch = armv8a vpp_dpdk_target = arm64-thunderx-linuxapp-gcc else vpp_march = native vpp_mtune = generic -vpp_dpdk_arch = native endif endif vpp_native_tools = vppapigen diff --git a/dpdk/Makefile b/dpdk/Makefile index 00d606d2..c9ed8730 100644 --- a/dpdk/Makefile +++ b/dpdk/Makefile @@ -18,8 +18,6 @@ DPDK_BUILD_DIR ?= $(CURDIR)/_build DPDK_INSTALL_DIR ?= $(CURDIR)/_install DPDK_PKTMBUF_HEADROOM ?= 128 DPDK_DOWNLOAD_DIR ?= $(HOME)/Downloads -DPDK_MARCH ?= native -DPDK_TUNE ?= generic DPDK_DEBUG ?= n DPDK_CRYPTO_SW_PMD ?= n DPDK_MLX5_PMD ?= n @@ -27,7 +25,7 @@ DPDK_MLX5_PMD ?= n B := $(DPDK_BUILD_DIR) I := $(DPDK_INSTALL_DIR) DPDK_VERSION ?= 16.11 -PKG_SUFFIX ?= vpp4 +PKG_SUFFIX ?= vpp5 DPDK_BASE_URL ?= http://fast.dpdk.org/rel DPDK_TARBALL := dpdk-$(DPDK_VERSION).tar.xz DPDK_TAR_URL := $(DPDK_BASE_URL)/$(DPDK_TARBALL) @@ -37,20 +35,40 @@ DPDK_SOURCE := $(B)/dpdk-$(DPDK_VERSION) ifneq (,$(findstring clang,$(CC))) DPDK_CC=clang +else ifneq (,$(findstring icc,$(CC))) +DPDK_CC=icc else DPDK_CC=gcc endif +############################################################################## +# Intel x86_64 +############################################################################## +ifeq ($(shell uname -m),x86_64) +DPDK_TARGET ?= x86_64-native-linuxapp-$(DPDK_CC) +DPDK_MACHINE ?= nhm +DPDK_TUNE ?= core-avx2 + +############################################################################## +# Cavium ThunderX +############################################################################## +else ifneq (,$(findstring thunder,$(shell cat /sys/bus/pci/devices/0000:00:01.0/uevent | grep cavium))) +export CROSS="" +DPDK_TARGET ?= arm64-thunderx-linuxapp-$(DPDK_CC) +DPDK_MACHINE ?= thunderx +DPDK_TUNE ?= generic -ifeq (,$(DPDK_TARGET)) -DPDK_TARGET := x86_64-native-linuxapp-$(DPDK_CC) +############################################################################## +# Unknown platofrm +############################################################################## +else +$(error unknown platform) endif JOBS := $(shell grep processor /proc/cpuinfo | wc -l) # compiler/linker custom arguments DPDK_CPU_CFLAGS := -pie -fPIC -DPDK_CPU_LDFLAGS := DPDK_EXTRA_LDFLAGS := -g ifeq ($(DPDK_DEBUG),n) @@ -59,25 +77,6 @@ else DPDK_EXTRA_CFLAGS := -g -O0 endif -# translate gcc march values to DPDK arch -ifeq ($(DPDK_MARCH),native) -DPDK_MACHINE:=native # autodetect host CPU -else ifeq ($(DPDK_MARCH),corei7) -DPDK_MACHINE:=nhm # Nehalem / Westmere -else ifeq ($(DPDK_MARCH),corei7-avx) -DPDK_MACHINE:=snb # Sandy Bridge -else ifeq ($(DPDK_MARCH),core-avx-i) -DPDK_MACHINE:=ivb # Ivy Bridge -else ifeq ($(DPDK_MARCH),core-avx2) -DPDK_MACHINE:=hsw # Haswell -else ifeq ($(DPDK_MARCH),armv7a) -DPDK_MACHINE:=armv7a # ARMv7 -else ifeq ($(DPDK_MARCH),armv8a) -DPDK_MACHINE:=armv8a # ARMv8 -else -$(error Unknown DPDK_MARCH) -endif - # assemble DPDK make arguments DPDK_MAKE_ARGS := -C $(DPDK_SOURCE) -j $(JOBS) \ T=$(DPDK_TARGET) \ @@ -85,11 +84,10 @@ DPDK_MAKE_ARGS := -C $(DPDK_SOURCE) -j $(JOBS) \ EXTRA_CFLAGS="$(DPDK_EXTRA_CFLAGS)" \ EXTRA_LDFLAGS="$(DPDK_EXTRA_LDFLAGS)" \ CPU_CFLAGS="$(DPDK_CPU_CFLAGS)" \ - CPU_LDFLAGS="$(DPDK_CPU_LDFLAGS)" \ DESTDIR=$(I) \ $(DPDK_MAKE_EXTRA_ARGS) -DPDK_SOURCE_FILES := $(shell [ -e $(DPDK_SOURCE) ] && find $(DPDK_SOURCE) -name "*.[chS]") +DPDK_SOURCE_FILES := $(shell [ -e $(DPDK_SOURCE) ] && find $(DPDK_SOURCE) -name "*.[chS]") define set @if grep -q CONFIG_$1 $@ ; \ -- cgit 1.2.3-korg From 6be3255d4655c2ba81c9e4bc6b6f3b25e94ce57d Mon Sep 17 00:00:00 2001 From: Sergio Gonzalez Monroy Date: Mon, 14 Aug 2017 09:46:19 +0100 Subject: dpdk: cleanup unused build option *_uses_dpdk_cryptodev_sw Change-Id: I62939592bd3cb151e02c55a3f1ee6e7d1ce469cb Signed-off-by: Sergio Gonzalez Monroy --- build-data/packages/dpdk.mk | 5 ----- build-data/packages/vpp.mk | 3 --- build-data/platforms/vpp.mk | 1 - src/plugins/dpdk/ipsec/dpdk_crypto_ipsec_doc.md | 15 ++++----------- 4 files changed, 4 insertions(+), 20 deletions(-) (limited to 'build-data/packages/dpdk.mk') diff --git a/build-data/packages/dpdk.mk b/build-data/packages/dpdk.mk index ed89bb1b..ddfb8fd1 100644 --- a/build-data/packages/dpdk.mk +++ b/build-data/packages/dpdk.mk @@ -10,11 +10,6 @@ DPDK_MAKE_ARGS = -C $(call find_source_fn,$(PACKAGE_SOURCE)) \ DPDK_INSTALL_DIR=$(PACKAGE_INSTALL_DIR) \ DPDK_DEBUG=$(DPDK_DEBUG) -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)) ifneq ($(DPDK_MLX5_PMD),) DPDK_MAKE_ARGS += DPDK_MLX5_PMD=y diff --git a/build-data/packages/vpp.mk b/build-data/packages/vpp.mk index 1acc59b2..170f99c5 100644 --- a/build-data/packages/vpp.mk +++ b/build-data/packages/vpp.mk @@ -23,9 +23,6 @@ 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_sw),yes) -vpp_configure_args += --with-dpdk-crypto-sw -endif ifeq ($($(PLATFORM)_uses_dpdk_mlx5_pmd),yes) vpp_configure_args += --with-dpdk-mlx5-pmd endif diff --git a/build-data/platforms/vpp.mk b/build-data/platforms/vpp.mk index acbe0e7f..77457174 100644 --- a/build-data/platforms/vpp.mk +++ b/build-data/platforms/vpp.mk @@ -39,7 +39,6 @@ vpp_uses_dpdk = yes vpp_root_packages = vpp # DPDK configuration parameters -# 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/src/plugins/dpdk/ipsec/dpdk_crypto_ipsec_doc.md b/src/plugins/dpdk/ipsec/dpdk_crypto_ipsec_doc.md index 5a9f9c6e..b3dbd6ea 100644 --- a/src/plugins/dpdk/ipsec/dpdk_crypto_ipsec_doc.md +++ b/src/plugins/dpdk/ipsec/dpdk_crypto_ipsec_doc.md @@ -7,10 +7,10 @@ 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 support is enabled and there are enough Cryptodev resources for all workers, the node graph is reconfigured by adding and changing default next nodes. +When there are enough Cryptodev resources for all workers, the node graph is reconfigured by adding and changing the default next nodes. The following nodes are added: -* dpdk-crypto-input : polling input node, basically dequeuing from crypto devices. +* dpdk-crypto-input : polling input node, dequeuing from crypto devices. * dpdk-esp-encrypt : internal node. * dpdk-esp-decrypt : internal node. * dpdk-esp-encrypt-post : internal node. @@ -23,16 +23,9 @@ Set new default next nodes: ### How to enable VPP IPSec with DPDK Cryptodev support -DPDK Cryptodev is supported in DPDK enabled VPP and by default only HW Cryptodev is supported. -To enable SW Cryptodev support (AESNI-MB-PMD and GCM-PMD), we need the following env option: +When building DPDK with VPP, Cryptodev support is always enabled. - 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_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. This requires nasm, see nasm section below. +Additionally, on x86_64 platforms, DPDK is built with SW crypto support. ### Crypto Resources allocation -- cgit 1.2.3-korg