diff options
Diffstat (limited to 'examples/dpdk_qat')
-rw-r--r-- | examples/dpdk_qat/Makefile | 93 | ||||
-rw-r--r-- | examples/dpdk_qat/config_files/coleto/dh895xcc_qa_dev0.conf | 65 | ||||
-rw-r--r-- | examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev0.conf | 293 | ||||
-rw-r--r-- | examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev1.conf | 292 | ||||
-rw-r--r-- | examples/dpdk_qat/config_files/stargo/dh89xxcc_qa_dev0.conf | 235 | ||||
-rw-r--r-- | examples/dpdk_qat/crypto.c | 944 | ||||
-rw-r--r-- | examples/dpdk_qat/crypto.h | 90 | ||||
-rw-r--r-- | examples/dpdk_qat/main.c | 824 |
8 files changed, 2836 insertions, 0 deletions
diff --git a/examples/dpdk_qat/Makefile b/examples/dpdk_qat/Makefile new file mode 100644 index 00000000..01d61bcf --- /dev/null +++ b/examples/dpdk_qat/Makefile @@ -0,0 +1,93 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2013 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ifeq ($(RTE_SDK),) +$(error "Please define RTE_SDK environment variable") +endif + +ifeq ($(ICP_ROOT),) +$(error "Please define ICP_ROOT environment variable") +endif + +# Default target, can be overriden by command line or environment +RTE_TARGET ?= x86_64-native-linuxapp-gcc + +include $(RTE_SDK)/mk/rte.vars.mk + +ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +$(error This application can only operate in a linuxapp environment, \ +please change the definition of the RTE_TARGET environment variable) +endif + +LBITS := $(shell uname -p) +ifeq ($(CROSS_COMPILE),) + ifneq ($(CONFIG_RTE_ARCH),"x86_64") + ifneq ($(LBITS),i686) + $(error The RTE_TARGET chosen is not compatible with this environment \ + (x86_64), for this application. Please change the definition of the \ + RTE_TARGET environment variable, or run the application on a i686 OS) + endif + endif +endif + +# binary name +APP = dpdk_qat + +# all source are stored in SRCS-y +SRCS-y := main.c crypto.c + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) +CFLAGS += -I$(ICP_ROOT)/quickassist/include \ + -I$(ICP_ROOT)/quickassist/include/lac \ + -I$(ICP_ROOT)/quickassist/lookaside/access_layer/include + +# From CRF 1.2 driver, library was renamed to libicp_qa_al.a +ifneq ($(wildcard $(ICP_ROOT)/build/icp_qa_al.a),) +ICP_LIBRARY_PATH = $(ICP_ROOT)/build/icp_qa_al.a +else +ICP_LIBRARY_PATH = $(ICP_ROOT)/build/libicp_qa_al.a +endif + +LDLIBS += -L$(ICP_ROOT)/build +LDLIBS += $(ICP_LIBRARY_PATH) \ + -lz \ + -losal \ + -ladf_proxy \ + -lcrypto + +# workaround for a gcc bug with noreturn attribute +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) +CFLAGS_main.o += -Wno-return-type +endif + +include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/dpdk_qat/config_files/coleto/dh895xcc_qa_dev0.conf b/examples/dpdk_qat/config_files/coleto/dh895xcc_qa_dev0.conf new file mode 100644 index 00000000..fd139e2f --- /dev/null +++ b/examples/dpdk_qat/config_files/coleto/dh895xcc_qa_dev0.conf @@ -0,0 +1,65 @@ +[GENERAL] +ServicesEnabled = cy;dc +ConfigVersion = 2 +cyHmacAuthMode = 1 +dcTotalSRAMAvailable = 0 +Firmware_MofPath = dh895xcc/mof_firmware.bin +Firmware_MmpPath = dh895xcc/mmp_firmware.bin +statsGeneral = 1 +statsDc = 1 +statsDh = 1 +statsDrbg = 1 +statsDsa = 1 +statsEcc = 1 +statsKeyGen = 1 +statsLn = 1 +statsPrime = 1 +statsRsa = 1 +statsSym = 1 +SRIOV_Enabled = 0 +ProcDebug = 1 + +[KERNEL] +NumberCyInstances = 0 +NumberDcInstances = 0 + +[SSL] +NumberCyInstances = 8 +NumberDcInstances = 0 +NumProcesses = 1 +LimitDevAccess = 0 + +Cy0Name = "SSL0" +Cy0IsPolled = 1 +Cy0CoreAffinity = 0 + +Cy1Name = "SSL1" +Cy1IsPolled = 1 +Cy1CoreAffinity = 1 + +Cy2Name = "SSL2" +Cy2IsPolled = 1 +Cy2CoreAffinity = 2 + +Cy3Name = "SSL3" +Cy3IsPolled = 1 +Cy3CoreAffinity = 3 + + +Cy4Name = "SSL4" +Cy4IsPolled = 1 +Cy4CoreAffinity = 4 + + +Cy5Name = "SSL5" +Cy5IsPolled = 1 +Cy5CoreAffinity = 5 + +Cy6Name = "SSL6" +Cy6IsPolled = 1 +Cy6CoreAffinity = 6 + + +Cy7Name = "SSL7" +Cy7IsPolled = 1 +Cy7CoreAffinity = 7 diff --git a/examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev0.conf b/examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev0.conf new file mode 100644 index 00000000..9e1c1d11 --- /dev/null +++ b/examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev0.conf @@ -0,0 +1,293 @@ +######################################################################### +# +# @par +# BSD LICENSE +# +# Copyright(c) 2010-2014 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ######################################################################### +# ######################################################## +# +# This file is the configuration for a single dh89xxcc_qa +# device. +# +# Each device has up to two accelerators. +# - The client may load balance between these +# accelerators. +# Each accelerator has 8 independent ring banks. +# - The interrupt for each can be directed to a +# specific core. +# Each ring bank as 16 rings (hardware assisted queues). +# +######################################################### +# General Section +############################################## + +[GENERAL] +ServicesEnabled = cy0;cy1 + +# Use version 2 of the config file +ConfigVersion = 2 +# Look Aside Cryptographic Configuration +cyHmacAuthMode = 1 + +# Look Aside Compression Configuration +dcTotalSRAMAvailable = 0 + +# Firmware Location Configuration +Firmware_MofPath = mof_firmware.bin +Firmware_MmpPath = mmp_firmware.bin + +#Default values for number of concurrent requests*/ +CyNumConcurrentSymRequests = 512 +CyNumConcurrentAsymRequests = 64 +DcNumConcurrentRequests = 512 + +#Statistics, valid values: 1,0 +statsGeneral = 1 +statsDc = 1 +statsDh = 1 +statsDrbg = 1 +statsDsa = 1 +statsEcc = 1 +statsKeyGen = 1 +statsLn = 1 +statsPrime = 1 +statsRsa = 1 +statsSym = 1 + +# Enables or disables Single Root Complex IO Virtualization. +# If this is enabled (1) then SRIOV and VT-d need to be enabled in +# BIOS and there can be no Cy or Dc instances created in PF (Dom0). +# If this i disabled (0) then SRIOV and VT-d need to be disabled +# in BIOS and Cy and/or Dc instances can be used in PF (Dom0) +SRIOV_Enabled = 0 + +#Debug feature, if set to 1 it enables additional entries in /proc filesystem +ProcDebug = 1 + +####################################################### +# +# Logical Instances Section +# A logical instance allows each address domain +# (kernel space and individual user space processes) +# to configure rings (i.e. hardware assisted queues) +# to be used by that address domain and to define the +# behavior of that ring. +# +# The address domains are in the following format +# - For kernel address domains +# [KERNEL] +# - For user process address domains +# [xxxxx] +# Where xxxxx may be any ascii value which uniquely identifies +# the user mode process. +# To allow the driver correctly configure the +# logical instances associated with this user process, +# the process must call the icp_sal_userStartMultiProcess(...) +# passing the xxxxx string during process initialisation. +# When the user space process is finished it must call +# icp_sal_userStop(...) to free resources. +# NumProcesses will indicate the maximum number of processes +# that can call icp_sal_userStartMultiProcess on this instance. +# Warning: the resources are preallocated: if NumProcesses +# is too high, the driver will fail to load +# +# Items configurable by a logical instance are: +# - Name of the logical instance +# - The accelerator associated with this logical +# instance +# - The core the instance is affinitized to (optional) +# +# Note: Logical instances may not share the same ring, but +# may share a ring bank. +# +# The format of the logical instances are: +# - For crypto: +# Cy<n>Name = "xxxx" +# Cy<n>AcceleratorNumber = 0-3 +# Cy<n>CoreAffinity = 0-7 +# +# - For Data Compression +# Dc<n>Name = "xxxx" +# Dc<n>AcceleratorNumber = 0-1 +# Dc<n>CoreAffinity = 0-7 +# +# Where: +# - n is the number of this logical instance starting at 0. +# - xxxx may be any ascii value which identifies the logical instance. +# +# Note: for user space processes, a list of values can be specified for +# the accelerator number and the core affinity: for example +# Cy0AcceleratorNumber = 0,2 +# Cy0CoreAffinity = 0,2,4 +# These comma-separated lists will allow the multiple processes to use +# different accelerators and cores, and will wrap around the numbers +# in the list. In the above example, process 0 will use accelerator 0, +# and process 1 will use accelerator 2 +# +######################################################## + +############################################## +# Kernel Instances Section +############################################## +[KERNEL] +NumberCyInstances = 0 +NumberDcInstances = 0 + +############################################## +# User Process Instance Section +############################################## +[SSL] +NumberCyInstances = 16 +NumberDcInstances = 0 +NumProcesses = 1 +LimitDevAccess = 0 + +# Crypto - User instance #0 +Cy0Name = "SSL0" +Cy0IsPolled = 1 +Cy0AcceleratorNumber = 0 +# List of core affinities +Cy0CoreAffinity = 0 + +# Crypto - User instance #1 +Cy1Name = "SSL1" +Cy1IsPolled = 1 +Cy1AcceleratorNumber = 1 +# List of core affinities +Cy1CoreAffinity = 1 + +# Crypto - User instance #2 +Cy2Name = "SSL2" +Cy2IsPolled = 1 +Cy2AcceleratorNumber = 2 +# List of core affinities +Cy2CoreAffinity = 2 + +# Crypto - User instance #3 +Cy3Name = "SSL3" +Cy3IsPolled = 1 +Cy3AcceleratorNumber = 3 +# List of core affinities +Cy3CoreAffinity = 3 + +# Crypto - User instance #4 +Cy4Name = "SSL4" +Cy4IsPolled = 1 +Cy4AcceleratorNumber = 0 +# List of core affinities +Cy4CoreAffinity = 4 + +# Crypto - User instance #5 +Cy5Name = "SSL5" +Cy5IsPolled = 1 +Cy5AcceleratorNumber = 1 +# List of core affinities +Cy5CoreAffinity = 5 + +# Crypto - User instance #6 +Cy6Name = "SSL6" +Cy6IsPolled = 1 +Cy6AcceleratorNumber = 2 +# List of core affinities +Cy6CoreAffinity = 6 + +# Crypto - User instance #7 +Cy7Name = "SSL7" +Cy7IsPolled = 1 +Cy7AcceleratorNumber = 3 +# List of core affinities +Cy7CoreAffinity = 7 + +# Crypto - User instance #8 +Cy8Name = "SSL8" +Cy8IsPolled = 1 +Cy8AcceleratorNumber = 0 +# List of core affinities +Cy8CoreAffinity = 16 + +# Crypto - User instance #9 +Cy9Name = "SSL9" +Cy9IsPolled = 1 +Cy9AcceleratorNumber = 1 +# List of core affinities +Cy9CoreAffinity = 17 + +# Crypto - User instance #10 +Cy10Name = "SSL10" +Cy10IsPolled = 1 +Cy10AcceleratorNumber = 2 +# List of core affinities +Cy10CoreAffinity = 18 + +# Crypto - User instance #11 +Cy11Name = "SSL11" +Cy11IsPolled = 1 +Cy11AcceleratorNumber = 3 +# List of core affinities +Cy11CoreAffinity = 19 + +# Crypto - User instance #12 +Cy12Name = "SSL12" +Cy12IsPolled = 1 +Cy12AcceleratorNumber = 0 +# List of core affinities +Cy12CoreAffinity = 20 + +# Crypto - User instance #13 +Cy13Name = "SSL13" +Cy13IsPolled = 1 +Cy13AcceleratorNumber = 1 +# List of core affinities +Cy13CoreAffinity = 21 + +# Crypto - User instance #14 +Cy14Name = "SSL14" +Cy14IsPolled = 1 +Cy14AcceleratorNumber = 2 +# List of core affinities +Cy14CoreAffinity = 22 + +# Crypto - User instance #15 +Cy15Name = "SSL15" +Cy15IsPolled = 1 +Cy15AcceleratorNumber = 3 +# List of core affinities +Cy15CoreAffinity = 23 + + + +############################################## +# Wireless Process Instance Section +############################################## +[WIRELESS] +NumberCyInstances = 0 +NumberDcInstances = 0 +NumProcesses = 0 diff --git a/examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev1.conf b/examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev1.conf new file mode 100644 index 00000000..3e8d8b6b --- /dev/null +++ b/examples/dpdk_qat/config_files/shumway/dh89xxcc_qa_dev1.conf @@ -0,0 +1,292 @@ +######################################################################### +# +# @par +# BSD LICENSE +# +# Copyright(c) 2010-2014 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ######################################################################### +# ######################################################## +# +# This file is the configuration for a single dh89xxcc_qa +# device. +# +# Each device has up to two accelerators. +# - The client may load balance between these +# accelerators. +# Each accelerator has 8 independent ring banks. +# - The interrupt for each can be directed to a +# specific core. +# Each ring bank as 16 rings (hardware assisted queues). +# +######################################################### +# General Section +############################################## + +[GENERAL] +ServicesEnabled = cy0;cy1 + +# Use version 2 of the config file +ConfigVersion = 2 +# Look Aside Cryptographic Configuration +cyHmacAuthMode = 1 + +# Look Aside Compression Configuration +dcTotalSRAMAvailable = 0 + +# Firmware Location Configuration +Firmware_MofPath = mof_firmware.bin +Firmware_MmpPath = mmp_firmware.bin + +#Default values for number of concurrent requests*/ +CyNumConcurrentSymRequests = 512 +CyNumConcurrentAsymRequests = 64 +DcNumConcurrentRequests = 512 + +#Statistics, valid values: 1,0 +statsGeneral = 1 +statsDc = 1 +statsDh = 1 +statsDrbg = 1 +statsDsa = 1 +statsEcc = 1 +statsKeyGen = 1 +statsLn = 1 +statsPrime = 1 +statsRsa = 1 +statsSym = 1 + +# Enables or disables Single Root Complex IO Virtualization. +# If this is enabled (1) then SRIOV and VT-d need to be enabled in +# BIOS and there can be no Cy or Dc instances created in PF (Dom0). +# If this i disabled (0) then SRIOV and VT-d need to be disabled +# in BIOS and Cy and/or Dc instances can be used in PF (Dom0) +SRIOV_Enabled = 0 + +#Debug feature, if set to 1 it enables additional entries in /proc filesystem +ProcDebug = 1 + +####################################################### +# +# Logical Instances Section +# A logical instance allows each address domain +# (kernel space and individual user space processes) +# to configure rings (i.e. hardware assisted queues) +# to be used by that address domain and to define the +# behavior of that ring. +# +# The address domains are in the following format +# - For kernel address domains +# [KERNEL] +# - For user process address domains +# [xxxxx] +# Where xxxxx may be any ascii value which uniquely identifies +# the user mode process. +# To allow the driver correctly configure the +# logical instances associated with this user process, +# the process must call the icp_sal_userStartMultiProcess(...) +# passing the xxxxx string during process initialisation. +# When the user space process is finished it must call +# icp_sal_userStop(...) to free resources. +# NumProcesses will indicate the maximum number of processes +# that can call icp_sal_userStartMultiProcess on this instance. +# Warning: the resources are preallocated: if NumProcesses +# is too high, the driver will fail to load +# +# Items configurable by a logical instance are: +# - Name of the logical instance +# - The accelerator associated with this logical +# instance +# - The core the instance is affinitized to (optional) +# +# Note: Logical instances may not share the same ring, but +# may share a ring bank. +# +# The format of the logical instances are: +# - For crypto: +# Cy<n>Name = "xxxx" +# Cy<n>AcceleratorNumber = 0-3 +# Cy<n>CoreAffinity = 0-7 +# +# - For Data Compression +# Dc<n>Name = "xxxx" +# Dc<n>AcceleratorNumber = 0-1 +# Dc<n>CoreAffinity = 0-7 +# +# Where: +# - n is the number of this logical instance starting at 0. +# - xxxx may be any ascii value which identifies the logical instance. +# +# Note: for user space processes, a list of values can be specified for +# the accelerator number and the core affinity: for example +# Cy0AcceleratorNumber = 0,2 +# Cy0CoreAffinity = 0,2,4 +# These comma-separated lists will allow the multiple processes to use +# different accelerators and cores, and will wrap around the numbers +# in the list. In the above example, process 0 will use accelerator 0, +# and process 1 will use accelerator 2 +# +######################################################## + +############################################## +# Kernel Instances Section +############################################## +[KERNEL] +NumberCyInstances = 0 +NumberDcInstances = 0 + +############################################## +# User Process Instance Section +############################################## +[SSL] +NumberCyInstances = 16 +NumberDcInstances = 0 +NumProcesses = 1 +LimitDevAccess = 0 + +# Crypto - User instance #0 +Cy0Name = "SSL0" +Cy0IsPolled = 1 +Cy0AcceleratorNumber = 0 +# List of core affinities +Cy0CoreAffinity = 8 + +# Crypto - User instance #1 +Cy1Name = "SSL1" +Cy1IsPolled = 1 +Cy1AcceleratorNumber = 1 +# List of core affinities +Cy1CoreAffinity = 9 + +# Crypto - User instance #2 +Cy2Name = "SSL2" +Cy2IsPolled = 1 +Cy2AcceleratorNumber = 2 +# List of core affinities +Cy2CoreAffinity = 10 + +# Crypto - User instance #3 +Cy3Name = "SSL3" +Cy3IsPolled = 1 +Cy3AcceleratorNumber = 3 +# List of core affinities +Cy3CoreAffinity = 11 + +# Crypto - User instance #4 +Cy4Name = "SSL4" +Cy4IsPolled = 1 +Cy4AcceleratorNumber = 0 +# List of core affinities +Cy4CoreAffinity = 12 + +# Crypto - User instance #5 +Cy5Name = "SSL5" +Cy5IsPolled = 1 +Cy5AcceleratorNumber = 1 +# List of core affinities +Cy5CoreAffinity = 13 + +# Crypto - User instance #6 +Cy6Name = "SSL6" +Cy6IsPolled = 1 +Cy6AcceleratorNumber = 2 +# List of core affinities +Cy6CoreAffinity = 14 + +# Crypto - User instance #7 +Cy7Name = "SSL7" +Cy7IsPolled = 1 +Cy7AcceleratorNumber = 3 +# List of core affinities +Cy7CoreAffinity = 15 + +# Crypto - User instance #8 +Cy8Name = "SSL8" +Cy8IsPolled = 1 +Cy8AcceleratorNumber = 0 +# List of core affinities +Cy8CoreAffinity = 24 + +# Crypto - User instance #9 +Cy9Name = "SSL9" +Cy9IsPolled = 1 +Cy9AcceleratorNumber = 1 +# List of core affinities +Cy9CoreAffinity = 25 + +# Crypto - User instance #10 +Cy10Name = "SSL10" +Cy10IsPolled = 1 +Cy10AcceleratorNumber = 2 +# List of core affinities +Cy10CoreAffinity = 26 + +# Crypto - User instance #11 +Cy11Name = "SSL11" +Cy11IsPolled = 1 +Cy11AcceleratorNumber = 3 +# List of core affinities +Cy11CoreAffinity = 27 + +# Crypto - User instance #12 +Cy12Name = "SSL12" +Cy12IsPolled = 1 +Cy12AcceleratorNumber = 0 +# List of core affinities +Cy12CoreAffinity = 28 + +# Crypto - User instance #13 +Cy13Name = "SSL13" +Cy13IsPolled = 1 +Cy13AcceleratorNumber = 1 +# List of core affinities +Cy13CoreAffinity = 29 + +# Crypto - User instance #14 +Cy14Name = "SSL14" +Cy14IsPolled = 1 +Cy14AcceleratorNumber = 2 +# List of core affinities +Cy14CoreAffinity = 30 + +# Crypto - User instance #15 +Cy15Name = "SSL15" +Cy15IsPolled = 1 +Cy15AcceleratorNumber = 3 +# List of core affinities +Cy15CoreAffinity = 31 + + +############################################## +# Wireless Process Instance Section +############################################## +[WIRELESS] +NumberCyInstances = 0 +NumberDcInstances = 0 +NumProcesses = 0 diff --git a/examples/dpdk_qat/config_files/stargo/dh89xxcc_qa_dev0.conf b/examples/dpdk_qat/config_files/stargo/dh89xxcc_qa_dev0.conf new file mode 100644 index 00000000..c3a85dea --- /dev/null +++ b/examples/dpdk_qat/config_files/stargo/dh89xxcc_qa_dev0.conf @@ -0,0 +1,235 @@ +######################################################################### +# +# @par +# BSD LICENSE +# +# Copyright(c) 2010-2014 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# ######################################################################### +# ######################################################## +# +# This file is the configuration for a single dh89xxcc_qa +# device. +# +# Each device has up to two accelerators. +# - The client may load balance between these +# accelerators. +# Each accelerator has 8 independent ring banks. +# - The interrupt for each can be directed to a +# specific core. +# Each ring bank as 16 rings (hardware assisted queues). +# +######################################################### +# General Section +############################################## + +[GENERAL] +ServicesEnabled = cy0;cy1 + +# Use version 2 of the config file +ConfigVersion = 2 +# Look Aside Cryptographic Configuration +cyHmacAuthMode = 1 + +# Look Aside Compression Configuration +dcTotalSRAMAvailable = 0 + +# Firmware Location Configuration +Firmware_MofPath = mof_firmware.bin +Firmware_MmpPath = mmp_firmware.bin + +#Default values for number of concurrent requests*/ +CyNumConcurrentSymRequests = 512 +CyNumConcurrentAsymRequests = 64 +DcNumConcurrentRequests = 512 + +#Statistics, valid values: 1,0 +statsGeneral = 1 +statsDc = 1 +statsDh = 1 +statsDrbg = 1 +statsDsa = 1 +statsEcc = 1 +statsKeyGen = 1 +statsLn = 1 +statsPrime = 1 +statsRsa = 1 +statsSym = 1 + +# Enables or disables Single Root Complex IO Virtualization. +# If this is enabled (1) then SRIOV and VT-d need to be enabled in +# BIOS and there can be no Cy or Dc instances created in PF (Dom0). +# If this i disabled (0) then SRIOV and VT-d need to be disabled +# in BIOS and Cy and/or Dc instances can be used in PF (Dom0) +SRIOV_Enabled = 0 + +#Debug feature, if set to 1 it enables additional entries in /proc filesystem +ProcDebug = 1 + +####################################################### +# +# Logical Instances Section +# A logical instance allows each address domain +# (kernel space and individual user space processes) +# to configure rings (i.e. hardware assisted queues) +# to be used by that address domain and to define the +# behavior of that ring. +# +# The address domains are in the following format +# - For kernel address domains +# [KERNEL] +# - For user process address domains +# [xxxxx] +# Where xxxxx may be any ascii value which uniquely identifies +# the user mode process. +# To allow the driver correctly configure the +# logical instances associated with this user process, +# the process must call the icp_sal_userStartMultiProcess(...) +# passing the xxxxx string during process initialisation. +# When the user space process is finished it must call +# icp_sal_userStop(...) to free resources. +# NumProcesses will indicate the maximum number of processes +# that can call icp_sal_userStartMultiProcess on this instance. +# Warning: the resources are preallocated: if NumProcesses +# is too high, the driver will fail to load +# +# Items configurable by a logical instance are: +# - Name of the logical instance +# - The accelerator associated with this logical +# instance +# - The core the instance is affinitized to (optional) +# +# Note: Logical instances may not share the same ring, but +# may share a ring bank. +# +# The format of the logical instances are: +# - For crypto: +# Cy<n>Name = "xxxx" +# Cy<n>AcceleratorNumber = 0-3 +# Cy<n>CoreAffinity = 0-7 +# +# - For Data Compression +# Dc<n>Name = "xxxx" +# Dc<n>AcceleratorNumber = 0-1 +# Dc<n>CoreAffinity = 0-7 +# +# Where: +# - n is the number of this logical instance starting at 0. +# - xxxx may be any ascii value which identifies the logical instance. +# +# Note: for user space processes, a list of values can be specified for +# the accelerator number and the core affinity: for example +# Cy0AcceleratorNumber = 0,2 +# Cy0CoreAffinity = 0,2,4 +# These comma-separated lists will allow the multiple processes to use +# different accelerators and cores, and will wrap around the numbers +# in the list. In the above example, process 0 will use accelerator 0, +# and process 1 will use accelerator 2 +# +######################################################## + +############################################## +# Kernel Instances Section +############################################## +[KERNEL] +NumberCyInstances = 0 +NumberDcInstances = 0 + +############################################## +# User Process Instance Section +############################################## +[SSL] +NumberCyInstances = 8 +NumberDcInstances = 0 +NumProcesses = 1 +LimitDevAccess = 0 + +# Crypto - User instance #0 +Cy0Name = "SSL0" +Cy0IsPolled = 1 +Cy0AcceleratorNumber = 0 +# List of core affinities +Cy0CoreAffinity = 0 + +# Crypto - User instance #1 +Cy1Name = "SSL1" +Cy1IsPolled = 1 +Cy1AcceleratorNumber = 1 +# List of core affinities +Cy1CoreAffinity = 1 + +# Crypto - User instance #2 +Cy2Name = "SSL2" +Cy2IsPolled = 1 +Cy2AcceleratorNumber = 2 +# List of core affinities +Cy2CoreAffinity = 2 + +# Crypto - User instance #3 +Cy3Name = "SSL3" +Cy3IsPolled = 1 +Cy3AcceleratorNumber = 3 +# List of core affinities +Cy3CoreAffinity = 3 + +# Crypto - User instance #4 +Cy4Name = "SSL4" +Cy4IsPolled = 1 +Cy4AcceleratorNumber = 0 +# List of core affinities +Cy4CoreAffinity = 4 + +# Crypto - User instance #5 +Cy5Name = "SSL5" +Cy5IsPolled = 1 +Cy5AcceleratorNumber = 1 +# List of core affinities +Cy5CoreAffinity = 5 + +# Crypto - User instance #6 +Cy6Name = "SSL6" +Cy6IsPolled = 1 +Cy6AcceleratorNumber = 2 +# List of core affinities +Cy6CoreAffinity = 6 + +# Crypto - User instance #7 +Cy7Name = "SSL7" +Cy7IsPolled = 1 +Cy7AcceleratorNumber = 3 +# List of core affinities +Cy7CoreAffinity = 7 + +############################################## +# Wireless Process Instance Section +############################################## +[WIRELESS] +NumberCyInstances = 0 +NumberDcInstances = 0 +NumProcesses = 0 diff --git a/examples/dpdk_qat/crypto.c b/examples/dpdk_qat/crypto.c new file mode 100644 index 00000000..8954bf87 --- /dev/null +++ b/examples/dpdk_qat/crypto.c @@ -0,0 +1,944 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <string.h> +#include <inttypes.h> +#include <errno.h> +#include <sys/queue.h> +#include <stdarg.h> + +#include <rte_common.h> +#include <rte_log.h> +#include <rte_debug.h> +#include <rte_memory.h> +#include <rte_memzone.h> +#include <rte_ether.h> +#include <rte_malloc.h> +#include <rte_launch.h> +#include <rte_eal.h> +#include <rte_per_lcore.h> +#include <rte_lcore.h> +#include <rte_atomic.h> +#include <rte_branch_prediction.h> +#include <rte_ring.h> +#include <rte_mempool.h> +#include <rte_mbuf.h> +#include <rte_string_fns.h> + +#define CPA_CY_SYM_DP_TMP_WORKAROUND 1 + +#include "cpa.h" +#include "cpa_types.h" +#include "cpa_cy_sym_dp.h" +#include "cpa_cy_common.h" +#include "cpa_cy_im.h" +#include "icp_sal_user.h" +#include "icp_sal_poll.h" + +#include "crypto.h" + +/* CIPHER KEY LENGTHS */ +#define KEY_SIZE_64_IN_BYTES (64 / 8) +#define KEY_SIZE_56_IN_BYTES (56 / 8) +#define KEY_SIZE_128_IN_BYTES (128 / 8) +#define KEY_SIZE_168_IN_BYTES (168 / 8) +#define KEY_SIZE_192_IN_BYTES (192 / 8) +#define KEY_SIZE_256_IN_BYTES (256 / 8) + +/* HMAC AUTH KEY LENGTHS */ +#define AES_XCBC_AUTH_KEY_LENGTH_IN_BYTES (128 / 8) +#define SHA1_AUTH_KEY_LENGTH_IN_BYTES (160 / 8) +#define SHA224_AUTH_KEY_LENGTH_IN_BYTES (224 / 8) +#define SHA256_AUTH_KEY_LENGTH_IN_BYTES (256 / 8) +#define SHA384_AUTH_KEY_LENGTH_IN_BYTES (384 / 8) +#define SHA512_AUTH_KEY_LENGTH_IN_BYTES (512 / 8) +#define MD5_AUTH_KEY_LENGTH_IN_BYTES (128 / 8) +#define KASUMI_AUTH_KEY_LENGTH_IN_BYTES (128 / 8) + +/* HASH DIGEST LENGHTS */ +#define AES_XCBC_DIGEST_LENGTH_IN_BYTES (128 / 8) +#define AES_XCBC_96_DIGEST_LENGTH_IN_BYTES (96 / 8) +#define MD5_DIGEST_LENGTH_IN_BYTES (128 / 8) +#define SHA1_DIGEST_LENGTH_IN_BYTES (160 / 8) +#define SHA1_96_DIGEST_LENGTH_IN_BYTES (96 / 8) +#define SHA224_DIGEST_LENGTH_IN_BYTES (224 / 8) +#define SHA256_DIGEST_LENGTH_IN_BYTES (256 / 8) +#define SHA384_DIGEST_LENGTH_IN_BYTES (384 / 8) +#define SHA512_DIGEST_LENGTH_IN_BYTES (512 / 8) +#define KASUMI_DIGEST_LENGTH_IN_BYTES (32 / 8) + +#define IV_LENGTH_16_BYTES (16) +#define IV_LENGTH_8_BYTES (8) + + +/* + * rte_memzone is used to allocate physically contiguous virtual memory. + * In this application we allocate a single block and divide between variables + * which require a virtual to physical mapping for use by the QAT driver. + * Virt2phys is only performed during initialisation and not on the data-path. + */ + +#define LCORE_MEMZONE_SIZE (1 << 22) + +struct lcore_memzone +{ + const struct rte_memzone *memzone; + void *next_free_address; +}; + +/* + * Size the qa software response queue. + * Note: Head and Tail are 8 bit, therefore, the queue is + * fixed to 256 entries. + */ +#define CRYPTO_SOFTWARE_QUEUE_SIZE 256 + +struct qa_callbackQueue { + uint8_t head; + uint8_t tail; + uint16_t numEntries; + struct rte_mbuf *qaCallbackRing[CRYPTO_SOFTWARE_QUEUE_SIZE]; +}; + +struct qa_core_conf { + CpaCySymDpSessionCtx *encryptSessionHandleTbl[NUM_CRYPTO][NUM_HMAC]; + CpaCySymDpSessionCtx *decryptSessionHandleTbl[NUM_CRYPTO][NUM_HMAC]; + CpaInstanceHandle instanceHandle; + struct qa_callbackQueue callbackQueue; + uint64_t qaOutstandingRequests; + uint64_t numResponseAttempts; + uint8_t kickFreq; + void *pPacketIV; + CpaPhysicalAddr packetIVPhy; + struct lcore_memzone lcoreMemzone; +} __rte_cache_aligned; + +#define MAX_CORES (RTE_MAX_LCORE) + +static struct qa_core_conf qaCoreConf[MAX_CORES]; + +/* + *Create maximum possible key size, + *One for cipher and one for hash + */ +struct glob_keys { + uint8_t cipher_key[32]; + uint8_t hash_key[64]; + uint8_t iv[16]; +}; + +struct glob_keys g_crypto_hash_keys = { + .cipher_key = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20}, + .hash_key = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10, + 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, + 0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20, + 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,0x30, + 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38, + 0x39,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50}, + .iv = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10} +}; + +/* + * Offsets from the start of the packet. + * + */ +#define PACKET_DATA_START_PHYS(p) \ + ((p)->buf_physaddr + (p)->data_off) + +/* + * A fixed offset to where the crypto is to be performed, which is the first + * byte after the Ethernet(14 bytes) and IPv4 headers(20 bytes) + */ +#define CRYPTO_START_OFFSET (14+20) +#define HASH_START_OFFSET (14+20) +#define CIPHER_BLOCK_DEFAULT_SIZE (16) +#define HASH_BLOCK_DEFAULT_SIZE (16) + +/* + * Offset to the opdata from the start of the data portion of packet. + * Assumption: The buffer is physically contiguous. + * +18 takes this to the next cache line. + */ + +#define CRYPTO_OFFSET_TO_OPDATA (ETHER_MAX_LEN+18) + +/* + * Default number of requests to place on the hardware ring before kicking the + * ring pointers. + */ +#define CRYPTO_BURST_TX (16) + +/* + * Only call the qa poll function when the number responses in the software + * queue drops below this number. + */ +#define CRYPTO_QUEUED_RESP_POLL_THRESHOLD (32) + +/* + * Limit the number of polls per call to get_next_response. + */ +#define GET_NEXT_RESPONSE_FREQ (32) + +/* + * Max number of responses to pull from the qa in one poll. + */ +#define CRYPTO_MAX_RESPONSE_QUOTA \ + (CRYPTO_SOFTWARE_QUEUE_SIZE-CRYPTO_QUEUED_RESP_POLL_THRESHOLD-1) + +#if (CRYPTO_QUEUED_RESP_POLL_THRESHOLD + CRYPTO_MAX_RESPONSE_QUOTA >= \ + CRYPTO_SOFTWARE_QUEUE_SIZE) +#error Its possible to overflow the qa response Q with current poll and \ + response quota. +#endif + +static void +crypto_callback(CpaCySymDpOpData *pOpData, + __rte_unused CpaStatus status, + __rte_unused CpaBoolean verifyResult) +{ + uint32_t lcore_id; + lcore_id = rte_lcore_id(); + struct qa_callbackQueue *callbackQ = &(qaCoreConf[lcore_id].callbackQueue); + + /* + * Received a completion from the QA hardware. + * Place the response on the return queue. + */ + callbackQ->qaCallbackRing[callbackQ->head] = pOpData->pCallbackTag; + callbackQ->head++; + callbackQ->numEntries++; + qaCoreConf[lcore_id].qaOutstandingRequests--; +} + +static void +qa_crypto_callback(CpaCySymDpOpData *pOpData, CpaStatus status, + CpaBoolean verifyResult) +{ + crypto_callback(pOpData, status, verifyResult); +} + +/* + * Each allocation from a particular memzone lasts for the life-time of + * the application. No freeing of previous allocations will occur. + */ +static void * +alloc_memzone_region(uint32_t length, uint32_t lcore_id) +{ + char *current_free_addr_ptr = NULL; + struct lcore_memzone *lcore_memzone = &(qaCoreConf[lcore_id].lcoreMemzone); + + current_free_addr_ptr = lcore_memzone->next_free_address; + + if (current_free_addr_ptr + length >= + (char *)lcore_memzone->memzone->addr + lcore_memzone->memzone->len) { + printf("Crypto: No memory available in memzone\n"); + return NULL; + } + lcore_memzone->next_free_address = current_free_addr_ptr + length; + + return (void *)current_free_addr_ptr; +} + +/* + * Virtual to Physical Address translation is only executed during initialization + * and not on the data-path. + */ +static CpaPhysicalAddr +qa_v2p(void *ptr) +{ + const struct rte_memzone *memzone = NULL; + uint32_t lcore_id = 0; + RTE_LCORE_FOREACH(lcore_id) { + memzone = qaCoreConf[lcore_id].lcoreMemzone.memzone; + + if ((char*) ptr >= (char *) memzone->addr && + (char*) ptr < ((char*) memzone->addr + memzone->len)) { + return (CpaPhysicalAddr) + (memzone->phys_addr + ((char *) ptr - (char*) memzone->addr)); + } + } + printf("Crypto: Corresponding physical address not found in memzone\n"); + return (CpaPhysicalAddr) 0; +} + +static CpaStatus +getCoreAffinity(Cpa32U *coreAffinity, const CpaInstanceHandle instanceHandle) +{ + CpaInstanceInfo2 info; + Cpa16U i = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + memset(&info, 0, sizeof(CpaInstanceInfo2)); + + status = cpaCyInstanceGetInfo2(instanceHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: Error getting instance info\n"); + return CPA_STATUS_FAIL; + } + for (i = 0; i < MAX_CORES; i++) { + if (CPA_BITMAP_BIT_TEST(info.coreAffinity, i)) { + *coreAffinity = i; + return CPA_STATUS_SUCCESS; + } + } + return CPA_STATUS_FAIL; +} + +static CpaStatus +get_crypto_instance_on_core(CpaInstanceHandle *pInstanceHandle, + uint32_t lcore_id) +{ + Cpa16U numInstances = 0, i = 0; + CpaStatus status = CPA_STATUS_FAIL; + CpaInstanceHandle *pLocalInstanceHandles = NULL; + Cpa32U coreAffinity = 0; + + status = cpaCyGetNumInstances(&numInstances); + if (CPA_STATUS_SUCCESS != status || numInstances == 0) { + return CPA_STATUS_FAIL; + } + + pLocalInstanceHandles = rte_malloc("pLocalInstanceHandles", + sizeof(CpaInstanceHandle) * numInstances, RTE_CACHE_LINE_SIZE); + + if (NULL == pLocalInstanceHandles) { + return CPA_STATUS_FAIL; + } + status = cpaCyGetInstances(numInstances, pLocalInstanceHandles); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: cpaCyGetInstances failed with status: %"PRId32"\n", status); + rte_free((void *) pLocalInstanceHandles); + return CPA_STATUS_FAIL; + } + + for (i = 0; i < numInstances; i++) { + status = getCoreAffinity(&coreAffinity, pLocalInstanceHandles[i]); + if (CPA_STATUS_SUCCESS != status) { + rte_free((void *) pLocalInstanceHandles); + return CPA_STATUS_FAIL; + } + if (coreAffinity == lcore_id) { + printf("Crypto: instance found on core %d\n", i); + *pInstanceHandle = pLocalInstanceHandles[i]; + return CPA_STATUS_SUCCESS; + } + } + /* core affinity not found */ + rte_free((void *) pLocalInstanceHandles); + return CPA_STATUS_FAIL; +} + +static CpaStatus +initCySymSession(const int pkt_cipher_alg, + const int pkt_hash_alg, const CpaCySymHashMode hashMode, + const CpaCySymCipherDirection crypto_direction, + CpaCySymSessionCtx **ppSessionCtx, + const CpaInstanceHandle cyInstanceHandle, + const uint32_t lcore_id) +{ + Cpa32U sessionCtxSizeInBytes = 0; + CpaStatus status = CPA_STATUS_FAIL; + CpaBoolean isCrypto = CPA_TRUE, isHmac = CPA_TRUE; + CpaCySymSessionSetupData sessionSetupData; + + memset(&sessionSetupData, 0, sizeof(CpaCySymSessionSetupData)); + + /* Assumption: key length is set to each algorithm's max length */ + switch (pkt_cipher_alg) { + case NO_CIPHER: + isCrypto = CPA_FALSE; + break; + case CIPHER_DES: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_DES_ECB; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + KEY_SIZE_64_IN_BYTES; + break; + case CIPHER_DES_CBC: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_DES_CBC; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + KEY_SIZE_64_IN_BYTES; + break; + case CIPHER_DES3: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_3DES_ECB; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + KEY_SIZE_192_IN_BYTES; + break; + case CIPHER_DES3_CBC: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_3DES_CBC; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + KEY_SIZE_192_IN_BYTES; + break; + case CIPHER_AES: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_AES_ECB; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + KEY_SIZE_128_IN_BYTES; + break; + case CIPHER_AES_CBC_128: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_AES_CBC; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + KEY_SIZE_128_IN_BYTES; + break; + case CIPHER_KASUMI_F8: + sessionSetupData.cipherSetupData.cipherAlgorithm = + CPA_CY_SYM_CIPHER_KASUMI_F8; + sessionSetupData.cipherSetupData.cipherKeyLenInBytes = + KEY_SIZE_128_IN_BYTES; + break; + default: + printf("Crypto: Undefined Cipher specified\n"); + break; + } + /* Set the cipher direction */ + if (isCrypto) { + sessionSetupData.cipherSetupData.cipherDirection = crypto_direction; + sessionSetupData.cipherSetupData.pCipherKey = + g_crypto_hash_keys.cipher_key; + sessionSetupData.symOperation = CPA_CY_SYM_OP_CIPHER; + } + + /* Setup Hash common fields */ + switch (pkt_hash_alg) { + case NO_HASH: + isHmac = CPA_FALSE; + break; + case HASH_AES_XCBC: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_XCBC; + sessionSetupData.hashSetupData.digestResultLenInBytes = + AES_XCBC_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_AES_XCBC_96: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_AES_XCBC; + sessionSetupData.hashSetupData.digestResultLenInBytes = + AES_XCBC_96_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_MD5: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_MD5; + sessionSetupData.hashSetupData.digestResultLenInBytes = + MD5_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_SHA1: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + sessionSetupData.hashSetupData.digestResultLenInBytes = + SHA1_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_SHA1_96: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + sessionSetupData.hashSetupData.digestResultLenInBytes = + SHA1_96_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_SHA224: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA224; + sessionSetupData.hashSetupData.digestResultLenInBytes = + SHA224_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_SHA256: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA256; + sessionSetupData.hashSetupData.digestResultLenInBytes = + SHA256_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_SHA384: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA384; + sessionSetupData.hashSetupData.digestResultLenInBytes = + SHA384_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_SHA512: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA512; + sessionSetupData.hashSetupData.digestResultLenInBytes = + SHA512_DIGEST_LENGTH_IN_BYTES; + break; + case HASH_KASUMI_F9: + sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_KASUMI_F9; + sessionSetupData.hashSetupData.digestResultLenInBytes = + KASUMI_DIGEST_LENGTH_IN_BYTES; + break; + default: + printf("Crypto: Undefined Hash specified\n"); + break; + } + if (isHmac) { + sessionSetupData.hashSetupData.hashMode = hashMode; + sessionSetupData.symOperation = CPA_CY_SYM_OP_HASH; + /* If using authenticated hash setup key lengths */ + if (CPA_CY_SYM_HASH_MODE_AUTH == hashMode) { + /* Use a common max length key */ + sessionSetupData.hashSetupData.authModeSetupData.authKey = + g_crypto_hash_keys.hash_key; + switch (pkt_hash_alg) { + case HASH_AES_XCBC: + case HASH_AES_XCBC_96: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + AES_XCBC_AUTH_KEY_LENGTH_IN_BYTES; + break; + case HASH_MD5: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + SHA1_AUTH_KEY_LENGTH_IN_BYTES; + break; + case HASH_SHA1: + case HASH_SHA1_96: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + SHA1_AUTH_KEY_LENGTH_IN_BYTES; + break; + case HASH_SHA224: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + SHA224_AUTH_KEY_LENGTH_IN_BYTES; + break; + case HASH_SHA256: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + SHA256_AUTH_KEY_LENGTH_IN_BYTES; + break; + case HASH_SHA384: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + SHA384_AUTH_KEY_LENGTH_IN_BYTES; + break; + case HASH_SHA512: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + SHA512_AUTH_KEY_LENGTH_IN_BYTES; + break; + case HASH_KASUMI_F9: + sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes = + KASUMI_AUTH_KEY_LENGTH_IN_BYTES; + break; + default: + printf("Crypto: Undefined Hash specified\n"); + return CPA_STATUS_FAIL; + } + } + } + + /* Only high priority supported */ + sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH; + + /* If chaining algorithms */ + if (isCrypto && isHmac) { + sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING; + /* @assumption Alg Chain order is cipher then hash for encrypt + * and hash then cipher then has for decrypt*/ + if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == crypto_direction) { + sessionSetupData.algChainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + } else { + sessionSetupData.algChainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + } + } + if (!isCrypto && !isHmac) { + *ppSessionCtx = NULL; + return CPA_STATUS_SUCCESS; + } + + /* Set flags for digest operations */ + sessionSetupData.digestIsAppended = CPA_FALSE; + sessionSetupData.verifyDigest = CPA_TRUE; + + /* Get the session context size based on the crypto and/or hash operations*/ + status = cpaCySymDpSessionCtxGetSize(cyInstanceHandle, &sessionSetupData, + &sessionCtxSizeInBytes); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: cpaCySymDpSessionCtxGetSize error, status: %"PRId32"\n", + status); + return CPA_STATUS_FAIL; + } + + *ppSessionCtx = alloc_memzone_region(sessionCtxSizeInBytes, lcore_id); + if (NULL == *ppSessionCtx) { + printf("Crypto: Failed to allocate memory for Session Context\n"); + return CPA_STATUS_FAIL; + } + + status = cpaCySymDpInitSession(cyInstanceHandle, &sessionSetupData, + *ppSessionCtx); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: cpaCySymDpInitSession failed with status %"PRId32"\n", status); + return CPA_STATUS_FAIL; + } + return CPA_STATUS_SUCCESS; +} + +static CpaStatus +initSessionDataTables(struct qa_core_conf *qaCoreConf,uint32_t lcore_id) +{ + Cpa32U i = 0, j = 0; + CpaStatus status = CPA_STATUS_FAIL; + for (i = 0; i < NUM_CRYPTO; i++) { + for (j = 0; j < NUM_HMAC; j++) { + if (((i == CIPHER_KASUMI_F8) && (j != NO_HASH) && (j != HASH_KASUMI_F9)) || + ((i != NO_CIPHER) && (i != CIPHER_KASUMI_F8) && (j == HASH_KASUMI_F9))) + continue; + status = initCySymSession(i, j, CPA_CY_SYM_HASH_MODE_AUTH, + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT, + &qaCoreConf->encryptSessionHandleTbl[i][j], + qaCoreConf->instanceHandle, + lcore_id); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: Failed to initialize Encrypt sessions\n"); + return CPA_STATUS_FAIL; + } + status = initCySymSession(i, j, CPA_CY_SYM_HASH_MODE_AUTH, + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT, + &qaCoreConf->decryptSessionHandleTbl[i][j], + qaCoreConf->instanceHandle, + lcore_id); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: Failed to initialize Decrypt sessions\n"); + return CPA_STATUS_FAIL; + } + } + } + return CPA_STATUS_SUCCESS; +} + +int +crypto_init(void) +{ + if (CPA_STATUS_SUCCESS != icp_sal_userStartMultiProcess("SSL",CPA_FALSE)) { + printf("Crypto: Could not start sal for user space\n"); + return CPA_STATUS_FAIL; + } + printf("Crypto: icp_sal_userStartMultiProcess(\"SSL\",CPA_FALSE)\n"); + return 0; +} + +/* + * Per core initialisation + */ +int +per_core_crypto_init(uint32_t lcore_id) +{ + CpaStatus status = CPA_STATUS_FAIL; + char memzone_name[RTE_MEMZONE_NAMESIZE]; + + int socketID = rte_lcore_to_socket_id(lcore_id); + + /* Allocate software ring for response messages. */ + + qaCoreConf[lcore_id].callbackQueue.head = 0; + qaCoreConf[lcore_id].callbackQueue.tail = 0; + qaCoreConf[lcore_id].callbackQueue.numEntries = 0; + qaCoreConf[lcore_id].kickFreq = 0; + qaCoreConf[lcore_id].qaOutstandingRequests = 0; + qaCoreConf[lcore_id].numResponseAttempts = 0; + + /* Initialise and reserve lcore memzone for virt2phys translation */ + snprintf(memzone_name, + RTE_MEMZONE_NAMESIZE, + "lcore_%u", + lcore_id); + + qaCoreConf[lcore_id].lcoreMemzone.memzone = rte_memzone_reserve( + memzone_name, + LCORE_MEMZONE_SIZE, + socketID, + 0); + if (NULL == qaCoreConf[lcore_id].lcoreMemzone.memzone) { + printf("Crypto: Error allocating memzone on lcore %u\n",lcore_id); + return -1; + } + qaCoreConf[lcore_id].lcoreMemzone.next_free_address = + qaCoreConf[lcore_id].lcoreMemzone.memzone->addr; + + qaCoreConf[lcore_id].pPacketIV = alloc_memzone_region(IV_LENGTH_16_BYTES, + lcore_id); + + if (NULL == qaCoreConf[lcore_id].pPacketIV ) { + printf("Crypto: Failed to allocate memory for Initialization Vector\n"); + return -1; + } + + memcpy(qaCoreConf[lcore_id].pPacketIV, &g_crypto_hash_keys.iv, + IV_LENGTH_16_BYTES); + + qaCoreConf[lcore_id].packetIVPhy = qa_v2p(qaCoreConf[lcore_id].pPacketIV); + if (0 == qaCoreConf[lcore_id].packetIVPhy) { + printf("Crypto: Invalid physical address for Initialization Vector\n"); + return -1; + } + + /* + * Obtain the instance handle that is mapped to the current lcore. + * This can fail if an instance is not mapped to a bank which has been + * affinitized to the current lcore. + */ + status = get_crypto_instance_on_core(&(qaCoreConf[lcore_id].instanceHandle), + lcore_id); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: get_crypto_instance_on_core failed with status: %"PRId32"\n", + status); + return -1; + } + + status = cpaCySymDpRegCbFunc(qaCoreConf[lcore_id].instanceHandle, + (CpaCySymDpCbFunc) qa_crypto_callback); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: cpaCySymDpRegCbFunc failed with status: %"PRId32"\n", status); + return -1; + } + + /* + * Set the address translation callback for virtual to physcial address + * mapping. This will be called by the QAT driver during initialisation only. + */ + status = cpaCySetAddressTranslation(qaCoreConf[lcore_id].instanceHandle, + (CpaVirtualToPhysical) qa_v2p); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: cpaCySetAddressTranslation failed with status: %"PRId32"\n", + status); + return -1; + } + + status = initSessionDataTables(&qaCoreConf[lcore_id],lcore_id); + if (CPA_STATUS_SUCCESS != status) { + printf("Crypto: Failed to allocate all session tables."); + return -1; + } + return 0; +} + +static CpaStatus +enqueueOp(CpaCySymDpOpData *opData, uint32_t lcore_id) +{ + + CpaStatus status; + + /* + * Assumption is there is no requirement to do load balancing between + * acceleration units - that is one acceleration unit is tied to a core. + */ + opData->instanceHandle = qaCoreConf[lcore_id].instanceHandle; + + if ((++qaCoreConf[lcore_id].kickFreq) % CRYPTO_BURST_TX == 0) { + status = cpaCySymDpEnqueueOp(opData, CPA_TRUE); + } else { + status = cpaCySymDpEnqueueOp(opData, CPA_FALSE); + } + + qaCoreConf[lcore_id].qaOutstandingRequests++; + + return status; +} + +void +crypto_flush_tx_queue(uint32_t lcore_id) +{ + + cpaCySymDpPerformOpNow(qaCoreConf[lcore_id].instanceHandle); +} + +enum crypto_result +crypto_encrypt(struct rte_mbuf *rte_buff, enum cipher_alg c, enum hash_alg h) +{ + CpaCySymDpOpData *opData = + rte_pktmbuf_mtod_offset(rte_buff, CpaCySymDpOpData *, + CRYPTO_OFFSET_TO_OPDATA); + uint32_t lcore_id; + + if (unlikely(c >= NUM_CRYPTO || h >= NUM_HMAC)) + return CRYPTO_RESULT_FAIL; + + lcore_id = rte_lcore_id(); + + memset(opData, 0, sizeof(CpaCySymDpOpData)); + + opData->srcBuffer = opData->dstBuffer = PACKET_DATA_START_PHYS(rte_buff); + opData->srcBufferLen = opData->dstBufferLen = rte_buff->data_len; + opData->sessionCtx = qaCoreConf[lcore_id].encryptSessionHandleTbl[c][h]; + opData->thisPhys = PACKET_DATA_START_PHYS(rte_buff) + + CRYPTO_OFFSET_TO_OPDATA; + opData->pCallbackTag = rte_buff; + + /* if no crypto or hash operations are specified return fail */ + if (NO_CIPHER == c && NO_HASH == h) + return CRYPTO_RESULT_FAIL; + + if (NO_CIPHER != c) { + opData->pIv = qaCoreConf[lcore_id].pPacketIV; + opData->iv = qaCoreConf[lcore_id].packetIVPhy; + + if (CIPHER_AES_CBC_128 == c) + opData->ivLenInBytes = IV_LENGTH_16_BYTES; + else + opData->ivLenInBytes = IV_LENGTH_8_BYTES; + + opData->cryptoStartSrcOffsetInBytes = CRYPTO_START_OFFSET; + opData->messageLenToCipherInBytes = rte_buff->data_len + - CRYPTO_START_OFFSET; + /* + * Work around for padding, message length has to be a multiple of + * block size. + */ + opData->messageLenToCipherInBytes -= opData->messageLenToCipherInBytes + % CIPHER_BLOCK_DEFAULT_SIZE; + } + + if (NO_HASH != h) { + + opData->hashStartSrcOffsetInBytes = HASH_START_OFFSET; + opData->messageLenToHashInBytes = rte_buff->data_len + - HASH_START_OFFSET; + /* + * Work around for padding, message length has to be a multiple of block + * size. + */ + opData->messageLenToHashInBytes -= opData->messageLenToHashInBytes + % HASH_BLOCK_DEFAULT_SIZE; + + /* + * Assumption: Ok ignore the passed digest pointer and place HMAC at end + * of packet. + */ + opData->digestResult = rte_buff->buf_physaddr + rte_buff->data_len; + } + + if (CPA_STATUS_SUCCESS != enqueueOp(opData, lcore_id)) { + /* + * Failed to place a packet on the hardware queue. + * Most likely because the QA hardware is busy. + */ + return CRYPTO_RESULT_FAIL; + } + return CRYPTO_RESULT_IN_PROGRESS; +} + +enum crypto_result +crypto_decrypt(struct rte_mbuf *rte_buff, enum cipher_alg c, enum hash_alg h) +{ + + CpaCySymDpOpData *opData = rte_pktmbuf_mtod_offset(rte_buff, void *, + CRYPTO_OFFSET_TO_OPDATA); + uint32_t lcore_id; + + if (unlikely(c >= NUM_CRYPTO || h >= NUM_HMAC)) + return CRYPTO_RESULT_FAIL; + + lcore_id = rte_lcore_id(); + + memset(opData, 0, sizeof(CpaCySymDpOpData)); + + opData->dstBuffer = opData->srcBuffer = PACKET_DATA_START_PHYS(rte_buff); + opData->dstBufferLen = opData->srcBufferLen = rte_buff->data_len; + opData->thisPhys = PACKET_DATA_START_PHYS(rte_buff) + + CRYPTO_OFFSET_TO_OPDATA; + opData->sessionCtx = qaCoreConf[lcore_id].decryptSessionHandleTbl[c][h]; + opData->pCallbackTag = rte_buff; + + /* if no crypto or hmac operations are specified return fail */ + if (NO_CIPHER == c && NO_HASH == h) + return CRYPTO_RESULT_FAIL; + + if (NO_CIPHER != c) { + opData->pIv = qaCoreConf[lcore_id].pPacketIV; + opData->iv = qaCoreConf[lcore_id].packetIVPhy; + + if (CIPHER_AES_CBC_128 == c) + opData->ivLenInBytes = IV_LENGTH_16_BYTES; + else + opData->ivLenInBytes = IV_LENGTH_8_BYTES; + + opData->cryptoStartSrcOffsetInBytes = CRYPTO_START_OFFSET; + opData->messageLenToCipherInBytes = rte_buff->data_len + - CRYPTO_START_OFFSET; + + /* + * Work around for padding, message length has to be a multiple of block + * size. + */ + opData->messageLenToCipherInBytes -= opData->messageLenToCipherInBytes + % CIPHER_BLOCK_DEFAULT_SIZE; + } + if (NO_HASH != h) { + opData->hashStartSrcOffsetInBytes = HASH_START_OFFSET; + opData->messageLenToHashInBytes = rte_buff->data_len + - HASH_START_OFFSET; + /* + * Work around for padding, message length has to be a multiple of block + * size. + */ + opData->messageLenToHashInBytes -= opData->messageLenToHashInBytes + % HASH_BLOCK_DEFAULT_SIZE; + opData->digestResult = rte_buff->buf_physaddr + rte_buff->data_len; + } + + if (CPA_STATUS_SUCCESS != enqueueOp(opData, lcore_id)) { + /* + * Failed to place a packet on the hardware queue. + * Most likely because the QA hardware is busy. + */ + return CRYPTO_RESULT_FAIL; + } + return CRYPTO_RESULT_IN_PROGRESS; +} + +void * +crypto_get_next_response(void) +{ + uint32_t lcore_id; + lcore_id = rte_lcore_id(); + struct qa_callbackQueue *callbackQ = &(qaCoreConf[lcore_id].callbackQueue); + void *entry = NULL; + + if (callbackQ->numEntries) { + entry = callbackQ->qaCallbackRing[callbackQ->tail]; + callbackQ->tail++; + callbackQ->numEntries--; + } + + /* If there are no outstanding requests no need to poll, return entry */ + if (qaCoreConf[lcore_id].qaOutstandingRequests == 0) + return entry; + + if (callbackQ->numEntries < CRYPTO_QUEUED_RESP_POLL_THRESHOLD + && qaCoreConf[lcore_id].numResponseAttempts++ + % GET_NEXT_RESPONSE_FREQ == 0) { + /* + * Only poll the hardware when there is less than + * CRYPTO_QUEUED_RESP_POLL_THRESHOLD elements in the software queue + */ + icp_sal_CyPollDpInstance(qaCoreConf[lcore_id].instanceHandle, + CRYPTO_MAX_RESPONSE_QUOTA); + } + return entry; +} diff --git a/examples/dpdk_qat/crypto.h b/examples/dpdk_qat/crypto.h new file mode 100644 index 00000000..f68b0b65 --- /dev/null +++ b/examples/dpdk_qat/crypto.h @@ -0,0 +1,90 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CRYPTO_H_ +#define CRYPTO_H_ + +/* Pass Labels/Values to crypto units */ +enum cipher_alg { + /* Option to not do any cryptography */ + NO_CIPHER, + CIPHER_DES, + CIPHER_DES_CBC, + CIPHER_DES3, + CIPHER_DES3_CBC, + CIPHER_AES, + CIPHER_AES_CBC_128, + CIPHER_KASUMI_F8, + NUM_CRYPTO, +}; + +enum hash_alg { + /* Option to not do any hash */ + NO_HASH, + HASH_MD5, + HASH_SHA1, + HASH_SHA1_96, + HASH_SHA224, + HASH_SHA256, + HASH_SHA384, + HASH_SHA512, + HASH_AES_XCBC, + HASH_AES_XCBC_96, + HASH_KASUMI_F9, + NUM_HMAC, +}; + +/* Return value from crypto_{encrypt/decrypt} */ +enum crypto_result { + /* Packet was successfully put into crypto queue */ + CRYPTO_RESULT_IN_PROGRESS, + /* Cryptography has failed in some way */ + CRYPTO_RESULT_FAIL, +}; + +extern enum crypto_result crypto_encrypt(struct rte_mbuf *pkt, enum cipher_alg c, + enum hash_alg h); +extern enum crypto_result crypto_decrypt(struct rte_mbuf *pkt, enum cipher_alg c, + enum hash_alg h); + +extern int crypto_init(void); + +extern int per_core_crypto_init(uint32_t lcore_id); + +extern void crypto_exit(void); + +extern void *crypto_get_next_response(void); + +extern void crypto_flush_tx_queue(uint32_t lcore_id); + +#endif /* CRYPTO_H_ */ diff --git a/examples/dpdk_qat/main.c b/examples/dpdk_qat/main.c new file mode 100644 index 00000000..dc68989a --- /dev/null +++ b/examples/dpdk_qat/main.c @@ -0,0 +1,824 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <inttypes.h> +#include <sys/types.h> +#include <string.h> +#include <sys/queue.h> +#include <stdarg.h> +#include <errno.h> +#include <getopt.h> + +#include <rte_common.h> +#include <rte_byteorder.h> +#include <rte_log.h> +#include <rte_memory.h> +#include <rte_memzone.h> +#include <rte_eal.h> +#include <rte_per_lcore.h> +#include <rte_launch.h> +#include <rte_atomic.h> +#include <rte_cycles.h> +#include <rte_prefetch.h> +#include <rte_lcore.h> +#include <rte_per_lcore.h> +#include <rte_branch_prediction.h> +#include <rte_interrupts.h> +#include <rte_pci.h> +#include <rte_random.h> +#include <rte_debug.h> +#include <rte_ether.h> +#include <rte_ethdev.h> +#include <rte_ring.h> +#include <rte_mempool.h> +#include <rte_mbuf.h> +#include <rte_ip.h> +#include <rte_string_fns.h> + +#include "crypto.h" + +#define NB_MBUF (32 * 1024) + +#define MAX_PKT_BURST 32 +#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ + +#define TX_QUEUE_FLUSH_MASK 0xFFFFFFFF +#define TSC_COUNT_LIMIT 1000 + +#define ACTION_ENCRYPT 1 +#define ACTION_DECRYPT 2 + +/* + * Configurable number of RX/TX ring descriptors + */ +#define RTE_TEST_RX_DESC_DEFAULT 128 +#define RTE_TEST_TX_DESC_DEFAULT 512 +static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; +static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; + +/* ethernet addresses of ports */ +static struct ether_addr ports_eth_addr[RTE_MAX_ETHPORTS]; + +/* mask of enabled ports */ +static unsigned enabled_port_mask = 0; +static int promiscuous_on = 1; /**< Ports set in promiscuous mode on by default. */ + +/* list of enabled ports */ +static uint32_t dst_ports[RTE_MAX_ETHPORTS]; + +struct mbuf_table { + uint16_t len; + struct rte_mbuf *m_table[MAX_PKT_BURST]; +}; + +struct lcore_rx_queue { + uint8_t port_id; + uint8_t queue_id; +}; + +#define MAX_RX_QUEUE_PER_LCORE 16 + +#define MAX_LCORE_PARAMS 1024 +struct lcore_params { + uint8_t port_id; + uint8_t queue_id; + uint8_t lcore_id; +}; + +static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; +static struct lcore_params lcore_params_array_default[] = { + {0, 0, 2}, + {0, 1, 2}, + {0, 2, 2}, + {1, 0, 2}, + {1, 1, 2}, + {1, 2, 2}, + {2, 0, 2}, + {3, 0, 3}, + {3, 1, 3}, +}; + +static struct lcore_params * lcore_params = lcore_params_array_default; +static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / + sizeof(lcore_params_array_default[0]); + +static struct rte_eth_conf port_conf = { + .rxmode = { + .mq_mode = ETH_MQ_RX_RSS, + .split_hdr_size = 0, + .header_split = 0, /**< Header Split disabled */ + .hw_ip_checksum = 1, /**< IP checksum offload enabled */ + .hw_vlan_filter = 0, /**< VLAN filtering disabled */ + .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ + .hw_strip_crc = 0, /**< CRC stripped by hardware */ + }, + .rx_adv_conf = { + .rss_conf = { + .rss_key = NULL, + .rss_hf = ETH_RSS_IP, + }, + }, + .txmode = { + .mq_mode = ETH_MQ_TX_NONE, + }, +}; + +static struct rte_mempool * pktmbuf_pool[RTE_MAX_NUMA_NODES]; + +struct lcore_conf { + uint64_t tsc; + uint64_t tsc_count; + uint32_t tx_mask; + uint16_t n_rx_queue; + uint16_t rx_queue_list_pos; + struct lcore_rx_queue rx_queue_list[MAX_RX_QUEUE_PER_LCORE]; + uint16_t tx_queue_id[RTE_MAX_ETHPORTS]; + struct mbuf_table rx_mbuf; + uint32_t rx_mbuf_pos; + uint32_t rx_curr_queue; + struct mbuf_table tx_mbufs[RTE_MAX_ETHPORTS]; +} __rte_cache_aligned; + +static struct lcore_conf lcore_conf[RTE_MAX_LCORE]; + +static inline struct rte_mbuf * +nic_rx_get_packet(struct lcore_conf *qconf) +{ + struct rte_mbuf *pkt; + + if (unlikely(qconf->n_rx_queue == 0)) + return NULL; + + /* Look for the next queue with packets; return if none */ + if (unlikely(qconf->rx_mbuf_pos == qconf->rx_mbuf.len)) { + uint32_t i; + + qconf->rx_mbuf_pos = 0; + for (i = 0; i < qconf->n_rx_queue; i++) { + qconf->rx_mbuf.len = rte_eth_rx_burst( + qconf->rx_queue_list[qconf->rx_curr_queue].port_id, + qconf->rx_queue_list[qconf->rx_curr_queue].queue_id, + qconf->rx_mbuf.m_table, MAX_PKT_BURST); + + qconf->rx_curr_queue++; + if (unlikely(qconf->rx_curr_queue == qconf->n_rx_queue)) + qconf->rx_curr_queue = 0; + if (likely(qconf->rx_mbuf.len > 0)) + break; + } + if (unlikely(i == qconf->n_rx_queue)) + return NULL; + } + + /* Get the next packet from the current queue; if last packet, go to next queue */ + pkt = qconf->rx_mbuf.m_table[qconf->rx_mbuf_pos]; + qconf->rx_mbuf_pos++; + + return pkt; +} + +static inline void +nic_tx_flush_queues(struct lcore_conf *qconf) +{ + uint8_t portid; + + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { + struct rte_mbuf **m_table = NULL; + uint16_t queueid, len; + uint32_t n, i; + + if (likely((qconf->tx_mask & (1 << portid)) == 0)) + continue; + + len = qconf->tx_mbufs[portid].len; + if (likely(len == 0)) + continue; + + queueid = qconf->tx_queue_id[portid]; + m_table = qconf->tx_mbufs[portid].m_table; + + n = rte_eth_tx_burst(portid, queueid, m_table, len); + for (i = n; i < len; i++){ + rte_pktmbuf_free(m_table[i]); + } + + qconf->tx_mbufs[portid].len = 0; + } + + qconf->tx_mask = TX_QUEUE_FLUSH_MASK; +} + +static inline void +nic_tx_send_packet(struct rte_mbuf *pkt, uint8_t port) +{ + struct lcore_conf *qconf; + uint32_t lcoreid; + uint16_t len; + + if (unlikely(pkt == NULL)) { + return; + } + + lcoreid = rte_lcore_id(); + qconf = &lcore_conf[lcoreid]; + + len = qconf->tx_mbufs[port].len; + qconf->tx_mbufs[port].m_table[len] = pkt; + len++; + + /* enough pkts to be sent */ + if (unlikely(len == MAX_PKT_BURST)) { + uint32_t n, i; + uint16_t queueid; + + queueid = qconf->tx_queue_id[port]; + n = rte_eth_tx_burst(port, queueid, qconf->tx_mbufs[port].m_table, MAX_PKT_BURST); + for (i = n; i < MAX_PKT_BURST; i++){ + rte_pktmbuf_free(qconf->tx_mbufs[port].m_table[i]); + } + + qconf->tx_mask &= ~(1 << port); + len = 0; + } + + qconf->tx_mbufs[port].len = len; +} + +/* main processing loop */ +static __attribute__((noreturn)) int +main_loop(__attribute__((unused)) void *dummy) +{ + uint32_t lcoreid; + struct lcore_conf *qconf; + const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * BURST_TX_DRAIN_US; + + lcoreid = rte_lcore_id(); + qconf = &lcore_conf[lcoreid]; + + printf("Thread %u starting...\n", lcoreid); + + for (;;) { + struct rte_mbuf *pkt; + uint32_t pkt_from_nic_rx = 0; + uint8_t port; + + /* Flush TX queues */ + qconf->tsc_count++; + if (unlikely(qconf->tsc_count == TSC_COUNT_LIMIT)) { + uint64_t tsc, diff_tsc; + + tsc = rte_rdtsc(); + + diff_tsc = tsc - qconf->tsc; + if (unlikely(diff_tsc > drain_tsc)) { + nic_tx_flush_queues(qconf); + crypto_flush_tx_queue(lcoreid); + qconf->tsc = tsc; + } + + qconf->tsc_count = 0; + } + + /* + * Check the Intel QuickAssist queues first + * + ***/ + pkt = (struct rte_mbuf *) crypto_get_next_response(); + if (pkt == NULL) { + pkt = nic_rx_get_packet(qconf); + pkt_from_nic_rx = 1; + } + if (pkt == NULL) + continue; + /* Send packet to either QAT encrypt, QAT decrypt or NIC TX */ + if (pkt_from_nic_rx) { + struct ipv4_hdr *ip = rte_pktmbuf_mtod_offset(pkt, + struct ipv4_hdr *, + sizeof(struct ether_hdr)); + if (ip->src_addr & rte_cpu_to_be_32(ACTION_ENCRYPT)) { + if (CRYPTO_RESULT_FAIL == crypto_encrypt(pkt, + (enum cipher_alg)((ip->src_addr >> 16) & 0xFF), + (enum hash_alg)((ip->src_addr >> 8) & 0xFF))) + rte_pktmbuf_free(pkt); + continue; + } + + if (ip->src_addr & rte_cpu_to_be_32(ACTION_DECRYPT)) { + if(CRYPTO_RESULT_FAIL == crypto_decrypt(pkt, + (enum cipher_alg)((ip->src_addr >> 16) & 0xFF), + (enum hash_alg)((ip->src_addr >> 8) & 0xFF))) + rte_pktmbuf_free(pkt); + continue; + } + } + + port = dst_ports[pkt->port]; + + /* Transmit the packet */ + nic_tx_send_packet(pkt, (uint8_t)port); + } +} + +static inline unsigned +get_port_max_rx_queues(uint8_t port_id) +{ + struct rte_eth_dev_info dev_info; + + rte_eth_dev_info_get(port_id, &dev_info); + return dev_info.max_rx_queues; +} + +static inline unsigned +get_port_max_tx_queues(uint8_t port_id) +{ + struct rte_eth_dev_info dev_info; + + rte_eth_dev_info_get(port_id, &dev_info); + return dev_info.max_tx_queues; +} + +static int +check_lcore_params(void) +{ + uint16_t i; + + for (i = 0; i < nb_lcore_params; ++i) { + if (lcore_params[i].queue_id >= get_port_max_rx_queues(lcore_params[i].port_id)) { + printf("invalid queue number: %hhu\n", lcore_params[i].queue_id); + return -1; + } + if (!rte_lcore_is_enabled(lcore_params[i].lcore_id)) { + printf("error: lcore %hhu is not enabled in lcore mask\n", + lcore_params[i].lcore_id); + return -1; + } + } + return 0; +} + +static int +check_port_config(const unsigned nb_ports) +{ + unsigned portid; + uint16_t i; + + for (i = 0; i < nb_lcore_params; ++i) { + portid = lcore_params[i].port_id; + if ((enabled_port_mask & (1 << portid)) == 0) { + printf("port %u is not enabled in port mask\n", portid); + return -1; + } + if (portid >= nb_ports) { + printf("port %u is not present on the board\n", portid); + return -1; + } + } + return 0; +} + +static uint8_t +get_port_n_rx_queues(const uint8_t port) +{ + int queue = -1; + uint16_t i; + + for (i = 0; i < nb_lcore_params; ++i) { + if (lcore_params[i].port_id == port && lcore_params[i].queue_id > queue) + queue = lcore_params[i].queue_id; + } + return (uint8_t)(++queue); +} + +static int +init_lcore_rx_queues(void) +{ + uint16_t i, nb_rx_queue; + uint8_t lcore; + + for (i = 0; i < nb_lcore_params; ++i) { + lcore = lcore_params[i].lcore_id; + nb_rx_queue = lcore_conf[lcore].n_rx_queue; + if (nb_rx_queue >= MAX_RX_QUEUE_PER_LCORE) { + printf("error: too many queues (%u) for lcore: %u\n", + (unsigned)nb_rx_queue + 1, (unsigned)lcore); + return -1; + } + lcore_conf[lcore].rx_queue_list[nb_rx_queue].port_id = + lcore_params[i].port_id; + lcore_conf[lcore].rx_queue_list[nb_rx_queue].queue_id = + lcore_params[i].queue_id; + lcore_conf[lcore].n_rx_queue++; + } + return 0; +} + +/* display usage */ +static void +print_usage(const char *prgname) +{ + printf ("%s [EAL options] -- -p PORTMASK [--no-promisc]" + " [--config '(port,queue,lcore)[,(port,queue,lcore)]'\n" + " -p PORTMASK: hexadecimal bitmask of ports to configure\n" + " --no-promisc: disable promiscuous mode (default is ON)\n" + " --config '(port,queue,lcore)': rx queues configuration\n", + prgname); +} + +static unsigned +parse_portmask(const char *portmask) +{ + char *end = NULL; + unsigned pm; + + /* parse hexadecimal string */ + pm = strtoul(portmask, &end, 16); + if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) + return 0; + + return pm; +} + +static int +parse_config(const char *q_arg) +{ + char s[256]; + const char *p, *p_end = q_arg; + char *end; + enum fieldnames { + FLD_PORT = 0, + FLD_QUEUE, + FLD_LCORE, + _NUM_FLD + }; + unsigned long int_fld[_NUM_FLD]; + char *str_fld[_NUM_FLD]; + int i; + unsigned size; + + nb_lcore_params = 0; + + while ((p = strchr(p_end,'(')) != NULL) { + if (nb_lcore_params >= MAX_LCORE_PARAMS) { + printf("exceeded max number of lcore params: %hu\n", + nb_lcore_params); + return -1; + } + ++p; + if((p_end = strchr(p,')')) == NULL) + return -1; + + size = p_end - p; + if(size >= sizeof(s)) + return -1; + + snprintf(s, sizeof(s), "%.*s", size, p); + if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != _NUM_FLD) + return -1; + for (i = 0; i < _NUM_FLD; i++) { + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) + return -1; + } + lcore_params_array[nb_lcore_params].port_id = (uint8_t)int_fld[FLD_PORT]; + lcore_params_array[nb_lcore_params].queue_id = (uint8_t)int_fld[FLD_QUEUE]; + lcore_params_array[nb_lcore_params].lcore_id = (uint8_t)int_fld[FLD_LCORE]; + ++nb_lcore_params; + } + lcore_params = lcore_params_array; + return 0; +} + +/* Parse the argument given in the command line of the application */ +static int +parse_args(int argc, char **argv) +{ + int opt, ret; + char **argvopt; + int option_index; + char *prgname = argv[0]; + static struct option lgopts[] = { + {"config", 1, 0, 0}, + {"no-promisc", 0, 0, 0}, + {NULL, 0, 0, 0} + }; + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, "p:", + lgopts, &option_index)) != EOF) { + + switch (opt) { + /* portmask */ + case 'p': + enabled_port_mask = parse_portmask(optarg); + if (enabled_port_mask == 0) { + printf("invalid portmask\n"); + print_usage(prgname); + return -1; + } + break; + + /* long options */ + case 0: + if (strcmp(lgopts[option_index].name, "config") == 0) { + ret = parse_config(optarg); + if (ret) { + printf("invalid config\n"); + print_usage(prgname); + return -1; + } + } + if (strcmp(lgopts[option_index].name, "no-promisc") == 0) { + printf("Promiscuous mode disabled\n"); + promiscuous_on = 0; + } + break; + default: + print_usage(prgname); + return -1; + } + } + + if (enabled_port_mask == 0) { + printf("portmask not specified\n"); + print_usage(prgname); + return -1; + } + + if (optind >= 0) + argv[optind-1] = prgname; + + ret = optind-1; + optind = 0; /* reset getopt lib */ + return ret; +} + +static void +print_ethaddr(const char *name, const struct ether_addr *eth_addr) +{ + char buf[ETHER_ADDR_FMT_SIZE]; + ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, eth_addr); + printf("%s%s", name, buf); +} + +static int +init_mem(void) +{ + int socketid; + unsigned lcoreid; + char s[64]; + + RTE_LCORE_FOREACH(lcoreid) { + socketid = rte_lcore_to_socket_id(lcoreid); + if (socketid >= RTE_MAX_NUMA_NODES) { + printf("Socket %d of lcore %u is out of range %d\n", + socketid, lcoreid, RTE_MAX_NUMA_NODES); + return -1; + } + if (pktmbuf_pool[socketid] == NULL) { + snprintf(s, sizeof(s), "mbuf_pool_%d", socketid); + pktmbuf_pool[socketid] = + rte_pktmbuf_pool_create(s, NB_MBUF, 32, 0, + RTE_MBUF_DEFAULT_BUF_SIZE, socketid); + if (pktmbuf_pool[socketid] == NULL) { + printf("Cannot init mbuf pool on socket %d\n", socketid); + return -1; + } + printf("Allocated mbuf pool on socket %d\n", socketid); + } + } + return 0; +} + +int +main(int argc, char **argv) +{ + struct lcore_conf *qconf; + struct rte_eth_link link; + int ret; + unsigned nb_ports; + uint16_t queueid; + unsigned lcoreid; + uint32_t nb_tx_queue; + uint8_t portid, nb_rx_queue, queue, socketid, last_port; + unsigned nb_ports_in_mask = 0; + + /* init EAL */ + ret = rte_eal_init(argc, argv); + if (ret < 0) + return -1; + argc -= ret; + argv += ret; + + /* parse application arguments (after the EAL ones) */ + ret = parse_args(argc, argv); + if (ret < 0) + return -1; + + if (check_lcore_params() < 0) + rte_panic("check_lcore_params failed\n"); + + ret = init_lcore_rx_queues(); + if (ret < 0) + return -1; + + ret = init_mem(); + if (ret < 0) + return -1; + + nb_ports = rte_eth_dev_count(); + if (nb_ports > RTE_MAX_ETHPORTS) + nb_ports = RTE_MAX_ETHPORTS; + + if (check_port_config(nb_ports) < 0) + rte_panic("check_port_config failed\n"); + + /* reset dst_ports */ + for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) + dst_ports[portid] = 0; + last_port = 0; + + /* + * Each logical core is assigned a dedicated TX queue on each port. + */ + for (portid = 0; portid < nb_ports; portid++) { + /* skip ports that are not enabled */ + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + + if (nb_ports_in_mask % 2) { + dst_ports[portid] = last_port; + dst_ports[last_port] = portid; + } + else + last_port = portid; + + nb_ports_in_mask++; + } + if (nb_ports_in_mask % 2) { + printf("Notice: odd number of ports in portmask.\n"); + dst_ports[last_port] = last_port; + } + + /* initialize all ports */ + for (portid = 0; portid < nb_ports; portid++) { + /* skip ports that are not enabled */ + if ((enabled_port_mask & (1 << portid)) == 0) { + printf("\nSkipping disabled port %d\n", portid); + continue; + } + + /* init port */ + printf("Initializing port %d ... ", portid ); + fflush(stdout); + + nb_rx_queue = get_port_n_rx_queues(portid); + if (nb_rx_queue > get_port_max_rx_queues(portid)) + rte_panic("Number of rx queues %d exceeds max number of rx queues %u" + " for port %d\n", nb_rx_queue, get_port_max_rx_queues(portid), + portid); + nb_tx_queue = rte_lcore_count(); + if (nb_tx_queue > get_port_max_tx_queues(portid)) + rte_panic("Number of lcores %u exceeds max number of tx queues %u" + " for port %d\n", nb_tx_queue, get_port_max_tx_queues(portid), + portid); + printf("Creating queues: nb_rxq=%d nb_txq=%u... ", + nb_rx_queue, (unsigned)nb_tx_queue ); + ret = rte_eth_dev_configure(portid, nb_rx_queue, + (uint16_t)nb_tx_queue, &port_conf); + if (ret < 0) + rte_panic("Cannot configure device: err=%d, port=%d\n", + ret, portid); + + rte_eth_macaddr_get(portid, &ports_eth_addr[portid]); + print_ethaddr(" Address:", &ports_eth_addr[portid]); + printf(", "); + + /* init one TX queue per couple (lcore,port) */ + queueid = 0; + RTE_LCORE_FOREACH(lcoreid) { + socketid = (uint8_t)rte_lcore_to_socket_id(lcoreid); + printf("txq=%u,%d,%d ", lcoreid, queueid, socketid); + fflush(stdout); + ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, + socketid, + NULL); + if (ret < 0) + rte_panic("rte_eth_tx_queue_setup: err=%d, " + "port=%d\n", ret, portid); + + qconf = &lcore_conf[lcoreid]; + qconf->tx_queue_id[portid] = queueid; + queueid++; + } + printf("\n"); + } + + RTE_LCORE_FOREACH(lcoreid) { + qconf = &lcore_conf[lcoreid]; + printf("\nInitializing rx queues on lcore %u ... ", lcoreid ); + fflush(stdout); + /* init RX queues */ + for(queue = 0; queue < qconf->n_rx_queue; ++queue) { + portid = qconf->rx_queue_list[queue].port_id; + queueid = qconf->rx_queue_list[queue].queue_id; + socketid = (uint8_t)rte_lcore_to_socket_id(lcoreid); + printf("rxq=%d,%d,%d ", portid, queueid, socketid); + fflush(stdout); + + ret = rte_eth_rx_queue_setup(portid, queueid, nb_rxd, + socketid, + NULL, + pktmbuf_pool[socketid]); + if (ret < 0) + rte_panic("rte_eth_rx_queue_setup: err=%d," + "port=%d\n", ret, portid); + } + } + + printf("\n"); + + /* start ports */ + for (portid = 0; portid < nb_ports; portid++) { + if ((enabled_port_mask & (1 << portid)) == 0) + continue; + /* Start device */ + ret = rte_eth_dev_start(portid); + if (ret < 0) + rte_panic("rte_eth_dev_start: err=%d, port=%d\n", + ret, portid); + + printf("done: Port %d ", portid); + + /* get link status */ + rte_eth_link_get(portid, &link); + if (link.link_status) + printf(" Link Up - speed %u Mbps - %s\n", + (unsigned) link.link_speed, + (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? + ("full-duplex") : ("half-duplex\n")); + else + printf(" Link Down\n"); + /* + * If enabled, put device in promiscuous mode. + * This allows IO forwarding mode to forward packets + * to itself through 2 cross-connected ports of the + * target machine. + */ + if (promiscuous_on) + rte_eth_promiscuous_enable(portid); + } + printf("Crypto: Initializing Crypto...\n"); + if (crypto_init() != 0) + return -1; + + RTE_LCORE_FOREACH(lcoreid) { + if (per_core_crypto_init(lcoreid) != 0) { + printf("Crypto: Cannot init lcore crypto on lcore %u\n", (unsigned)lcoreid); + return -1; + } + } + printf("Crypto: Initialization complete\n"); + /* launch per-lcore init on every lcore */ + rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); + RTE_LCORE_FOREACH_SLAVE(lcoreid) { + if (rte_eal_wait_lcore(lcoreid) < 0) + return -1; + } + + return 0; +} |