DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
@ 2020-04-10 14:27 David Coyle
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 1/4] raw/common: add multi-function interface David Coyle
                   ` (5 more replies)
  0 siblings, 6 replies; 92+ messages in thread
From: David Coyle @ 2020-04-10 14:27 UTC (permalink / raw)
  To: dev
  Cc: declan.doherty, fiona.trahe, pablo.de.lara.guarch, brendan.ryan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, ferruh.yigit,
	David Coyle

Introduction
============

This patchset adds a new AESNI-MB Multi-Function raw device PMD for
utilizing multi-function capabilities of the Intel IPSec Multi Buffer
library.

The aim of this rawdev PMD is to provide a way of combining one or more
common packet-processing functions into a single operation, focused on
DOCSIS and GPON MAC workloads. This allows these functions to be performed
in parallel by the Intel IPSec Multi Buffer library. These functions
include cryptography and CRC/BIP calculations. Performing these functions
in parallel as a single operation can enable a significant performance
improvement.


Background
==========

There are a number of byte-wise operations which are used across many
access network data-plane pipelines, such as Cipher, CRC and
Bit-Interleaved-Parity (BIP). Some prototyping has been done at Intel as
part of the 01.org access-network-dataplanes project to prove that a
significant performance improvement is possible when such byte-wise
operations are combined into a single pass of packet data processing. This
performance boost has been prototyped for both DOCSIS MAC data-plane and
GPON MAC data-plane pipelines based on DPDK.

The original prototypes on 01.org used some protocol-specific modifications
to the DPDK cryptodev library. In order to make this performance
optimization consumable for network access equipment vendors, a better
solution was required as CRC and BIP cannot be regarded as cryptographic
algorithms.

Hence, the introduction of an AESNI-MB Multi-Function rawdev PMD. This
PMD uses a new multi-function interface which allows different types of
operations be combined together. Initially, only symmetric crypto and error
detection (i.e. CRC and BIP) operations can be combined.

NOTE: In a future DPDK release, a QAT Multi-Function raw device will also
be added. As multiple raw devices will share the same interface, the
approach taken was to create a common interface (i.e. multi-function) which
can be used by these devices. This both cuts down on code duplication
across the devices and allows a DOCSIS or GPON MAC application to access
multiple devices using the same interface.


Use Cases
=========

The primary use cases for the AESNI-MB Multi-Function interface have
already been mentioned. These are:

- DOCSIS MAC: Crypto-CRC
        - Order:
                - Downstream: CRC, Encrypt
                - Upstream: Decrypt, CRC
        - Specifications:
                - Crypto: 128-bit AES-CFB encryption variant for DOCSIS as
                  described in section 11.1 of DOCSIS 3.1 Security
                  Specification
                  (https://apps.cablelabs.com/specification/CM-SP-SECv3.1)
                - CRC: Ethernet 32-bit CRC as defined in
                  Ethernet/[ISO/IEC 8802-3]

- GPON MAC: Crypto-CRC-BIP
        - Order:
                - Downstream: CRC, Encrypt, BIP
                - Upstream: BIP, Decrypt, CRC
        - Specifications:
                - Crypto: AES-128 [NIST FIPS-197] cipher, used in counter
                  mode (AES-CTR), as described in [NIST SP800-38A].
                - CRC: Ethernet 32-bit CRC as defined in
                  Ethernet/[ISO/IEC 8802-3]
                - BIP: 4-byte bit-interleaved even parity (BIP) field
                  computed over the entire FS frame, refer to
                  ITU-T G.989.3, sections 8.1.1.5 and 8.1.2.3
                  (https://www.itu.int/rec/dologin_pub.asp?lang=e&id=
                   T-REC-G.989.3-201510-I!!PDF-E)

Note that support for both these chained operations is already available in
the Intel IPSec Multi-Buffer library.


Architecture
============

The following diagram shows where the AESNI-MB Multi-Function rawdev PMD
fits in an overall application architecture.

  +------------------------------------------------+
  |                                                |
  |                  Application                   |
  |    (e.g. vCMTS (DOCSIS), vOLT (GPON), etc.)    |
  |                                                |
  +------------------------------------------------+
                          |
  +-----------------------|------------------------+
  |                       |                  DPDK  |
  |                       |                        |
  |             +---------------------+            |
  |             |                     |            |
  |             |     rte_rawdev      |            |
  |             |                     |            |            NOTE:
  |             +---------------------+        ____|______ 'MULTI-FUNCTION
  |                    /      \              /     |          INTERFACE'
  |                   /        \            /      |         is opaque to
  |                  /          \          /       |          rte_rawdev
  |       +--------------------------------+       |
  |       |    MULTI-FUNCTION INTERFACE    |       |
  |       +--------------------------------+       |
  |       +------------+      +------------+       |
  |       |  AESNI-MB  |      |    QAT     |       |
  |       |  MULTI-FN  |      |  MULTI-FN  |       |
  |       |   RAWDEV   |      |   RAWDEV   |       |
  |       |    PMD     |      |    PMD     |       |
  |       +------------+      +------------+       |           NOTE:
  |              |                  |     \________|______ 'QAT MULTI-FN
  |              |                  |              |         RAWDEV PMD'
  +--------------|------------------|--------------+      will be added in
                 |                  |                       later release
          +------------+      +------------+
          |  AESNI-MB  |      |   QAT HW   |
          |   SW LIB   |      |            |
          +------------+      +------------+

v2:
* moved unit tests under from test app to under aesni_mb rawdev.
* Added support to crypto-perf tool for multi-function processing.
* fixed checkpatch errors.
* general tidy-up and improvements.

v3:
* removed support from crypto-perf tool for multi-function processing.
* renamed driver to rawdev_mfn_aesni_mb.
* renamed files/directories/functions/etc. of new driver to have
  aesni_mb_mfn_ prefix.
* resolved review comments.
* updated documentation.

David Coyle (4):
  raw/common: add multi-function interface
  raw/aesni_mb_mfn: add aesni_mb_mfn raw device PMD
  test/rawdev: add aesni_mb_mfn raw device tests
  doc: update docs for aesni_mb_mfn raw device PMD

 MAINTAINERS                                   |    7 +
 app/test/test_rawdev.c                        |   18 +
 config/common_base                            |   11 +
 doc/api/doxy-api-index.md                     |    3 +-
 doc/api/doxy-api.conf.in                      |    1 +
 doc/guides/rawdevs/aesni_mb_mfn.rst           |  219 +++
 doc/guides/rawdevs/index.rst                  |    1 +
 doc/guides/rel_notes/release_20_05.rst        |    6 +
 drivers/meson.build                           |    5 +
 drivers/raw/Makefile                          |    3 +
 drivers/raw/aesni_mb_mfn/Makefile             |   50 +
 .../raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.c    | 1508 +++++++++++++++++
 .../raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.h    |  118 ++
 .../aesni_mb_mfn/aesni_mb_mfn_rawdev_test.c   | 1123 ++++++++++++
 .../aesni_mb_mfn_rawdev_test_vectors.h        | 1184 +++++++++++++
 drivers/raw/aesni_mb_mfn/meson.build          |   26 +
 .../rte_rawdev_aesni_mb_mfn_version.map       |    3 +
 drivers/raw/common/Makefile                   |    8 +
 drivers/raw/common/meson.build                |    7 +
 drivers/raw/common/multi_fn/Makefile          |   27 +
 drivers/raw/common/multi_fn/meson.build       |    9 +
 .../multi_fn/rte_common_multi_fn_version.map  |   12 +
 drivers/raw/common/multi_fn/rte_multi_fn.c    |  148 ++
 drivers/raw/common/multi_fn/rte_multi_fn.h    |  438 +++++
 .../raw/common/multi_fn/rte_multi_fn_driver.h |   97 ++
 drivers/raw/meson.build                       |    3 +-
 meson.build                                   |    4 +
 mk/rte.app.mk                                 |    3 +
 28 files changed, 5040 insertions(+), 2 deletions(-)
 create mode 100644 doc/guides/rawdevs/aesni_mb_mfn.rst
 create mode 100644 drivers/raw/aesni_mb_mfn/Makefile
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.c
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.h
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test.c
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test_vectors.h
 create mode 100644 drivers/raw/aesni_mb_mfn/meson.build
 create mode 100644 drivers/raw/aesni_mb_mfn/rte_rawdev_aesni_mb_mfn_version.map
 create mode 100644 drivers/raw/common/Makefile
 create mode 100644 drivers/raw/common/meson.build
 create mode 100644 drivers/raw/common/multi_fn/Makefile
 create mode 100644 drivers/raw/common/multi_fn/meson.build
 create mode 100644 drivers/raw/common/multi_fn/rte_common_multi_fn_version.map
 create mode 100644 drivers/raw/common/multi_fn/rte_multi_fn.c
 create mode 100644 drivers/raw/common/multi_fn/rte_multi_fn.h
 create mode 100644 drivers/raw/common/multi_fn/rte_multi_fn_driver.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 1/4] raw/common: add multi-function interface
  2020-04-10 14:27 [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing David Coyle
@ 2020-04-10 14:27 ` David Coyle
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 2/4] raw/aesni_mb_mfn: add aesni_mb_mfn raw device PMD David Coyle
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-04-10 14:27 UTC (permalink / raw)
  To: dev
  Cc: declan.doherty, fiona.trahe, pablo.de.lara.guarch, brendan.ryan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, ferruh.yigit,
	David Coyle, Mairtin o Loingsigh

The multi-function interface provides a way of combining one or
more different types of packet processing functions into a single
operation. The interface can be used by applications to send the
combined operations to a optimized software or hardware
accelerator via a raw device.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 config/common_base                            |   5 +
 drivers/meson.build                           |   5 +
 drivers/raw/Makefile                          |   1 +
 drivers/raw/common/Makefile                   |   8 +
 drivers/raw/common/meson.build                |   7 +
 drivers/raw/common/multi_fn/Makefile          |  27 ++
 drivers/raw/common/multi_fn/meson.build       |   9 +
 .../multi_fn/rte_common_multi_fn_version.map  |  12 +
 drivers/raw/common/multi_fn/rte_multi_fn.c    | 148 ++++++
 drivers/raw/common/multi_fn/rte_multi_fn.h    | 438 ++++++++++++++++++
 .../raw/common/multi_fn/rte_multi_fn_driver.h |  97 ++++
 meson.build                                   |   4 +
 mk/rte.app.mk                                 |   1 +
 13 files changed, 762 insertions(+)
 create mode 100644 drivers/raw/common/Makefile
 create mode 100644 drivers/raw/common/meson.build
 create mode 100644 drivers/raw/common/multi_fn/Makefile
 create mode 100644 drivers/raw/common/multi_fn/meson.build
 create mode 100644 drivers/raw/common/multi_fn/rte_common_multi_fn_version.map
 create mode 100644 drivers/raw/common/multi_fn/rte_multi_fn.c
 create mode 100644 drivers/raw/common/multi_fn/rte_multi_fn.h
 create mode 100644 drivers/raw/common/multi_fn/rte_multi_fn_driver.h

diff --git a/config/common_base b/config/common_base
index c31175f9d..27111c24c 100644
--- a/config/common_base
+++ b/config/common_base
@@ -818,6 +818,11 @@ CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_EP_RAWDEV=y
 #
 CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV=y
 
+#
+# Compile multi-fn raw device interface
+#
+CONFIG_RTE_LIBRTE_MULTI_FN_COMMON=y
+
 #
 # Compile librte_ring
 #
diff --git a/drivers/meson.build b/drivers/meson.build
index 5502bf992..4e0caeff3 100644
--- a/drivers/meson.build
+++ b/drivers/meson.build
@@ -10,6 +10,7 @@ dpdk_driver_classes = ['common',
 	       'bus',
 	       'mempool', # depends on common and bus.
 	       'net',     # depends on common, bus, mempool
+	       'raw/common',
 	       'raw',     # depends on common, bus and net.
 	       'crypto',  # depends on common, bus and mempool (net in future).
 	       'compress', # depends on common, bus, mempool.
@@ -212,5 +213,9 @@ foreach class:dpdk_driver_classes
 		endif # build
 	endforeach
 
+	if class.contains('/')
+		class_split = class.split('/')
+		class = '_'.join(class_split)
+	endif
 	set_variable(class + '_drivers', class_drivers)
 endforeach
diff --git a/drivers/raw/Makefile b/drivers/raw/Makefile
index 80b043eb1..e16da8d95 100644
--- a/drivers/raw/Makefile
+++ b/drivers/raw/Makefile
@@ -14,5 +14,6 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_IOAT_RAWDEV) += ioat
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += ntb
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_DMA_RAWDEV) += octeontx2_dma
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_EP_RAWDEV) += octeontx2_ep
+DIRS-y += common
 
 include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/drivers/raw/common/Makefile b/drivers/raw/common/Makefile
new file mode 100644
index 000000000..5c9ad399f
--- /dev/null
+++ b/drivers/raw/common/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+DIRS-$(CONFIG_RTE_LIBRTE_MULTI_FN_COMMON) += multi_fn
+
+include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/drivers/raw/common/meson.build b/drivers/raw/common/meson.build
new file mode 100644
index 000000000..1a8334348
--- /dev/null
+++ b/drivers/raw/common/meson.build
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation.
+
+drivers = ['multi_fn']
+std_deps = ['rawdev']
+config_flag_fmt = 'RTE_LIBRTE_@0@_COMMON'
+driver_name_fmt = 'rte_common_@0@'
diff --git a/drivers/raw/common/multi_fn/Makefile b/drivers/raw/common/multi_fn/Makefile
new file mode 100644
index 000000000..7ffbc6bb6
--- /dev/null
+++ b/drivers/raw/common/multi_fn/Makefile
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_multi_fn.a
+
+# build flags
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
+# versioning export map
+EXPORT_MAP := rte_common_multi_fn_version.map
+
+# external library dependencies
+LDLIBS += -lrte_eal
+LDLIBS += -lrte_mempool
+LDLIBS += -lrte_rawdev
+
+SRCS-y += rte_multi_fn.c
+
+SYMLINK-y-include += rte_multi_fn.h
+SYMLINK-y-include += rte_multi_fn_driver.h
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/raw/common/multi_fn/meson.build b/drivers/raw/common/multi_fn/meson.build
new file mode 100644
index 000000000..587168a0b
--- /dev/null
+++ b/drivers/raw/common/multi_fn/meson.build
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation.
+
+sources = files('rte_multi_fn.c')
+
+deps = ['rawdev', 'cryptodev']
+allow_experimental_apis = true
+
+install_headers('rte_multi_fn.h')
diff --git a/drivers/raw/common/multi_fn/rte_common_multi_fn_version.map b/drivers/raw/common/multi_fn/rte_common_multi_fn_version.map
new file mode 100644
index 000000000..e52af15e5
--- /dev/null
+++ b/drivers/raw/common/multi_fn/rte_common_multi_fn_version.map
@@ -0,0 +1,12 @@
+EXPERIMENTAL {
+	global:
+
+	rte_multi_fn_op_bulk_alloc;
+	rte_multi_fn_op_free;
+	rte_multi_fn_op_pool_create;
+	rte_multi_fn_session_create;
+	rte_multi_fn_session_destroy;
+	rte_multi_fn_xstat_names;
+
+	local: *;
+};
diff --git a/drivers/raw/common/multi_fn/rte_multi_fn.c b/drivers/raw/common/multi_fn/rte_multi_fn.c
new file mode 100644
index 000000000..07e6edecf
--- /dev/null
+++ b/drivers/raw/common/multi_fn/rte_multi_fn.c
@@ -0,0 +1,148 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#include <rte_log.h>
+
+#include "rte_multi_fn_driver.h"
+#include "rte_multi_fn.h"
+
+/* Dynamic log identifier */
+static int multi_fn_logtype;
+
+/* Logging Macros */
+#define MF_LOG(level, fmt, args...) \
+	rte_log(RTE_LOG_ ## level, multi_fn_logtype, \
+		"%s() line %u: " fmt "\n", \
+		__func__, __LINE__, ##args)
+#define MF_DEBUG(fmt, args...) \
+	MF_LOG(DEBUG, fmt, ## args)
+#define MF_INFO(fmt, args...) \
+	MF_LOG(INFO, fmt, ## args)
+#define MF_ERR(fmt, args...) \
+	MF_LOG(ERR, fmt, ## args)
+#define MF_WARN(fmt, args...) \
+	MF_LOG(WARNING, fmt, ## args)
+
+/* Multi-function xstat names */
+const char *
+rte_multi_fn_xstat_names[] = {
+	[RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_ENQUEUES] = "mfn_successful_enqueues",
+	[RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_DEQUEUES] = "mfn_successful_dequeues",
+	[RTE_MULTI_FN_XSTAT_ID_FAILED_ENQUEUES]     = "mfn_failed_enqueues",
+	[RTE_MULTI_FN_XSTAT_ID_FAILED_DEQUEUES]     = "mfn_failed_dequeues"
+};
+
+static void
+multi_fn_op_init(struct rte_mempool *mempool,
+		 __rte_unused void *opaque_arg,
+		 void *op_data,
+		 __rte_unused unsigned int i)
+{
+	struct rte_multi_fn_op *op = op_data;
+
+	memset(op_data, 0, mempool->elt_size);
+
+	op->overall_status = RTE_MULTI_FN_OP_STATUS_NOT_PROCESSED;
+	op->mempool = mempool;
+}
+
+struct rte_multi_fn_session *
+rte_multi_fn_session_create(uint16_t dev_id,
+			    struct rte_multi_fn_xform *xform,
+			    int socket_id)
+{
+	struct rte_rawdev *rawdev;
+	struct rte_rawdev_info info = {0};
+	struct rte_multi_fn_ops *mf_ops;
+
+	if (xform == NULL) {
+		MF_ERR("NULL xform for multi-function session create");
+		return NULL;
+	}
+
+	if (rte_rawdev_info_get(dev_id, &info) < 0) {
+		MF_ERR("Invalid dev_id=%d", dev_id);
+		return NULL;
+	}
+
+	rawdev = &rte_rawdevs[dev_id];
+
+	mf_ops = *((struct rte_multi_fn_ops **)(rawdev->dev_private));
+
+	RTE_FUNC_PTR_OR_ERR_RET(*mf_ops->session_create, NULL);
+	return (*mf_ops->session_create)(rawdev, xform, socket_id);
+}
+
+int
+rte_multi_fn_session_destroy(uint16_t dev_id, struct rte_multi_fn_session *sess)
+{
+	struct rte_rawdev *rawdev;
+	struct rte_rawdev_info info = {0};
+	struct rte_multi_fn_ops *mf_ops;
+
+	if (rte_rawdev_info_get(dev_id, &info) < 0) {
+		MF_ERR("Invalid dev_id=%d", dev_id);
+		return -EINVAL;
+	}
+
+	rawdev = &rte_rawdevs[dev_id];
+
+	mf_ops = *((struct rte_multi_fn_ops **)(rawdev->dev_private));
+
+	RTE_FUNC_PTR_OR_ERR_RET(*mf_ops->session_destroy, -ENOTSUP);
+	return (*mf_ops->session_destroy)(rawdev, sess);
+}
+
+struct rte_mempool *
+rte_multi_fn_op_pool_create(const char *name,
+			    uint32_t nb_elts,
+			    uint32_t cache_size,
+			    uint16_t priv_size,
+			    int socket_id)
+{
+	uint32_t elt_size = sizeof(struct rte_multi_fn_op) + priv_size;
+
+	/* Lookup mempool in case already allocated */
+	struct rte_mempool *mp = rte_mempool_lookup(name);
+
+	if (mp != NULL) {
+		if (mp->elt_size != elt_size ||
+				mp->cache_size < cache_size ||
+				mp->size < nb_elts) {
+			mp = NULL;
+			MF_ERR("Mempool %s already exists but with "
+			       "incompatible parameters",
+			       name);
+			return NULL;
+		}
+
+		return mp;
+	}
+
+	mp = rte_mempool_create(name,
+				nb_elts,
+				elt_size,
+				cache_size,
+				0,
+				NULL,
+				NULL,
+				multi_fn_op_init,
+				NULL,
+				socket_id,
+				0);
+
+	if (mp == NULL) {
+		MF_ERR("Failed to create mempool %s", name);
+		return NULL;
+	}
+
+	return mp;
+}
+
+RTE_INIT(rte_multi_fn_log_init)
+{
+	multi_fn_logtype = rte_log_register("pmd.raw.common.multi_fn");
+	if (multi_fn_logtype >= 0)
+		rte_log_set_level(multi_fn_logtype, RTE_LOG_INFO);
+}
diff --git a/drivers/raw/common/multi_fn/rte_multi_fn.h b/drivers/raw/common/multi_fn/rte_multi_fn.h
new file mode 100644
index 000000000..5aa16b0d5
--- /dev/null
+++ b/drivers/raw/common/multi_fn/rte_multi_fn.h
@@ -0,0 +1,438 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#ifndef _RTE_MULTI_FN_H_
+#define _RTE_MULTI_FN_H_
+
+/**
+ * @file rte_multi_fn.h
+ *
+ * RTE Multi Function APIs
+ *
+ * Defines Multi Function APIs for providing multi-function support to Rawdev
+ * PMDs
+ *
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_common.h>
+#include <rte_mbuf.h>
+#include <rte_mempool.h>
+#include <rte_crypto.h>
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Error Detection Algorithms
+ */
+enum rte_multi_fn_err_detect_algorithm {
+	RTE_MULTI_FN_ERR_DETECT_CRC32_ETH,
+	/**< CRC32 Ethernet */
+	RTE_MULTI_FN_ERR_DETECT_BIP32
+	/**< BIP32 */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Error Detection Operation Types
+ */
+enum rte_multi_fn_err_detect_operation {
+	RTE_MULTI_FN_ERR_DETECT_OP_VERIFY,
+	/**< Verify error detection result */
+	RTE_MULTI_FN_ERR_DETECT_OP_GENERATE
+	/**< Generate error detection result */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Error Detection Status
+ */
+enum rte_multi_fn_err_detect_op_status {
+	RTE_MULTI_FN_ERR_DETECT_OP_STATUS_SUCCESS,
+	/**< Operation completed successfully */
+	RTE_MULTI_FN_ERR_DETECT_OP_STATUS_NOT_PROCESSED,
+	/**< Operation has not yet been processed by a device */
+	RTE_MULTI_FN_ERR_DETECT_OP_STATUS_VERIFY_FAILED,
+	/**< Verification failed */
+	RTE_MULTI_FN_ERR_DETECT_OP_STATUS_ERROR
+	/**< Error handling operation */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Error Detection Transform Data
+ *
+ * This structure contains data relating to an error detection transform. The
+ * fields *op* and *algo* are common to all error detection transforms and
+ * MUST be set
+ */
+struct rte_multi_fn_err_detect_xform {
+	enum rte_multi_fn_err_detect_operation op;
+	/**< Error detection operation type */
+	enum rte_multi_fn_err_detect_algorithm algo;
+	/**< Error detection algorithm */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Error Detection Operation
+ */
+struct rte_multi_fn_err_detect_op {
+	struct {
+		uint16_t offset;
+		/**<
+		 * Starting point for error detection processing, specified
+		 * as the number of bytes from start of the packet in the
+		 * source mbuf
+		 */
+		uint16_t length;
+		/**<
+		 * The length, in bytes, of the source mbuf on which the error
+		 * detection operation will be computed
+		 */
+	} data; /**< Data offset and length for error detection */
+
+	struct {
+		uint8_t *data;
+		/**<
+		 * This points to the location where the error detection
+		 * result should be written (in the case of generation) or
+		 * where the purported result exists (in the case of
+		 * verification)
+		 *
+		 * The caller must ensure the required length of physically
+		 * contiguous memory is available at this address
+		 *
+		 * For a CRC, this may point into the mbuf packet data. For
+		 * an operation such as a BIP, this may point to a memory
+		 * location after the op
+		 *
+		 * For generation, the result will overwrite any data at this
+		 * location
+		 */
+		rte_iova_t phys_addr;
+		/**< Physical address of output data */
+	} output; /**< Output location */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Multi-Function Transform Types
+ */
+enum rte_multi_fn_xform_type {
+	RTE_MULTI_FN_XFORM_TYPE_UNDEFINED,
+	/**< Undefined transform type */
+	RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM,
+	/**< Symmetric crypto transform type */
+	RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT
+	/**< Error detection transform type */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Multi-Function Transform Data
+ *
+ * This structure is used to specify the multi-function transforms required.
+ * Multiple transforms can be chained together to specify a chain of transforms
+ * such as symmetric crypto followed by error detection, or vice versa. Each
+ * transform structure holds a single transform, with the type field specifying
+ * which transform is contained within the union.
+ */
+struct rte_multi_fn_xform {
+	struct rte_multi_fn_xform *next;
+	/**<
+	 * Next transform in the chain
+	 * - the last transform in the chain MUST set this to NULL
+	 */
+	enum rte_multi_fn_xform_type type;
+	/**< Transform type */
+
+	RTE_STD_C11
+	union {
+		struct rte_crypto_sym_xform crypto_sym;
+		/**< Symmetric crypto transform */
+		struct rte_multi_fn_err_detect_xform err_detect;
+		/**< Error detection transform */
+	};
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Multi-Function operation status
+ */
+enum rte_multi_fn_op_status {
+	RTE_MULTI_FN_OP_STATUS_SUCCESS,
+	/**< Operation completed successfully */
+	RTE_MULTI_FN_OP_STATUS_NOT_PROCESSED,
+	/**< Operation has not yet been processed by a device */
+	RTE_MULTI_FN_OP_STATUS_FAILURE,
+	/**< Operation completed with failure */
+	RTE_MULTI_FN_STATUS_INVALID_SESSION,
+	/**< Operation failed due to invalid session arguments */
+};
+
+/**
+ * @internal
+ *
+ * Multi-Function session data
+ */
+struct rte_multi_fn_session;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Multi-Function operation data
+ *
+ * This structure is used to specify the operations for a particular session.
+ * This includes specifying the source and, if required, destination mbufs and
+ * the lengths and offsets of the data within these mbufs on which the
+ * operations should be done. Multiple operations are chained together to
+ * specify the full set of operations to be performed.
+ *
+ * @note The order of the rte_multi_fn_op chain MUST match the order of the
+ * associated session's xform chain exactly
+ * @note The first rte_multi_fn_op element in the chain is the parent operation.
+ * The following fields MUST be set in this first operation before enqueuing and
+ * are ignored in the inner operations of the union and any subsequent
+ * rte_multi_fn_op chain elements:
+ * - *sess*
+ * - *m_src*
+ * - *m_dst* (if required)
+ * @note If *sess* or *m_src* is not set in the first rte_multi_fn_op, this
+ * operation is invalid and will cause an error when attempting to enqueue.
+ * @note The following fields MUST be set in ALL rte_multi_fn_op chain elements:
+ * - *next*
+ * - *mempool*
+ * - *type*
+ * @note After the operation has been dequeued, only the FIRST (i.e. the parent)
+ * rte_multi_fn_op in the chain will contain the *overall_status*. Each chain
+ * element will contain it's individual *op_status*, the value of which is
+ * relevant to the operation type (i.e. an ::rte_crypto_op_status or
+ * ::rte_multi_fn_err_detect_op_status)
+ *
+ */
+struct rte_multi_fn_op {
+	struct rte_multi_fn_op *next;
+	/**<
+	 * Next operation in the chain
+	 * - the last operation in the chain MUST set this to NULL
+	 */
+	struct rte_multi_fn_session *sess;
+	/**< Handle for the associated multi fn session */
+
+	struct rte_mempool *mempool;
+	/**< Mempool from which the operation is allocated */
+
+	struct rte_mbuf *m_src; /**< Source mbuf */
+	struct rte_mbuf *m_dst; /**< Destination mbuf */
+
+	enum rte_multi_fn_op_status overall_status;
+	/**<
+	 * Overall operation status
+	 * - indicates if all the operations in the chain succeeded or if any
+	 *   one of them failed
+	 */
+
+	uint8_t op_status;
+	/**<
+	 * Individual operation status
+	 * - indicates the status of the individual operation in the chain
+	 */
+
+	RTE_STD_C11
+	union {
+		struct rte_crypto_sym_op crypto_sym;
+		/**< Symmetric crypto operation */
+		struct rte_multi_fn_err_detect_op err_detect;
+		/**< Error detection operation */
+	};
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Device information structure
+ *
+ * This structure is returned from rte_rawdev_info_get() with information
+ * about the device
+ */
+struct rte_multi_fn_dev_info {
+	uint16_t max_nb_queues;
+	/**<
+	 * Maximum number of queue pairs that can be configured on the
+	 * device
+	 */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Device configuration structure
+ *
+ * This structure should be passed to rte_rawdev_configure() to configure
+ * a device
+ */
+struct rte_multi_fn_dev_config {
+	uint16_t nb_queues; /**< Number of queue pairs to configure */
+	unsigned int socket_id; /**< Socket to allocate queues on */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Queue pair configuration structure
+ *
+ * This should be passed to rte_rawdev_queue_setup() to configure a queue pair
+ */
+struct rte_multi_fn_qp_config {
+	uint32_t nb_descriptors; /**< Number of descriptors per queue pair */
+};
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Create multi-function session as specified by the transform chain
+ *
+ * @param   dev_id	The identifier of the device
+ * @param   xform	Pointer to the first element of the session transform
+ *			chain
+ * @param   socket_id	Socket to allocate the session on
+ *
+ * @return
+ *  - Pointer to session, if successful
+ *  - NULL, on failure
+ */
+__rte_experimental
+struct rte_multi_fn_session *
+rte_multi_fn_session_create(uint16_t dev_id,
+			    struct rte_multi_fn_xform *xform,
+			    int socket_id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Free memory associated with a multi-function session
+ *
+ * @param   dev_id	The identifier of the device
+ * @param   sess	Multi-function session to be freed
+ *
+ * @return
+ *  - 0, if successful
+ *  - -EINVAL, if session is NULL
+ *  - -EBUSY, if not all session data has been freed
+ */
+__rte_experimental
+int
+rte_multi_fn_session_destroy(uint16_t dev_id,
+			     struct rte_multi_fn_session *sess);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Create a multi-function operation pool
+ *
+ * @param   name	Pool name
+ * @param   nb_elts	Number of elements in pool
+ * @param   cache_size  Number of elements to cache on lcore, see
+ *                      *rte_mempool_create* for further details about
+ *                      cache size
+ * @param   priv_size	Size of private data to allocate with each
+ *                      operation
+ * @param   socket_id   Socket to allocate memory on
+ *
+ * @return
+ *  - Pointer to mempool, if successful
+ *  - NULL, on failure
+ */
+__rte_experimental
+struct rte_mempool *
+rte_multi_fn_op_pool_create(const char *name,
+			    uint32_t nb_elts,
+			    uint32_t cache_size,
+			    uint16_t priv_size,
+			    int socket_id);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Bulk allocate multi-function operations from a mempool with default
+ * parameters set
+ *
+ * @param   mempool	Multi-function operation mempool
+ * @param   ops		Array to place allocated multi-function operations
+ * @param   nb_ops	Number of multi-function operations to allocate
+ *
+ * @returns
+ * - nb_ops, if the number of operations requested were allocated
+ * - 0, if the requested number of ops are not available. None are allocated in
+ *   this case
+ */
+__rte_experimental
+static inline unsigned
+rte_multi_fn_op_bulk_alloc(struct rte_mempool *mempool,
+			   struct rte_multi_fn_op **ops,
+			   uint16_t nb_ops)
+{
+	int i;
+
+	if (rte_mempool_get_bulk(mempool, (void **)ops, nb_ops) == 0) {
+		for (i = 0; i < nb_ops; i++)
+			ops[i]->overall_status =
+				RTE_MULTI_FN_OP_STATUS_NOT_PROCESSED;
+
+		return nb_ops;
+	}
+
+	return 0;
+}
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice
+ *
+ * Free multi-function operation back to it's mempool
+ *
+ * @param   op		Multi-function operation
+ */
+__rte_experimental
+static inline void
+rte_multi_fn_op_free(struct rte_multi_fn_op *op)
+{
+	if (op != NULL && op->mempool != NULL)
+		rte_mempool_put(op->mempool, op);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MULTI_FN_H_ */
diff --git a/drivers/raw/common/multi_fn/rte_multi_fn_driver.h b/drivers/raw/common/multi_fn/rte_multi_fn_driver.h
new file mode 100644
index 000000000..9000f4e00
--- /dev/null
+++ b/drivers/raw/common/multi_fn/rte_multi_fn_driver.h
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#ifndef _RTE_MULTI_FN_DRIVER_H_
+#define _RTE_MULTI_FN_DRIVER_H_
+
+/**
+ * @file rte_multi_fn_driver.h
+ *
+ * RTE Multi Function PMD APIs
+ *
+ * @note
+ * These APIs are for rawdev PMDs only which support the multi-function
+ * interface and user applications should not call them directly.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <rte_rawdev.h>
+
+#include "rte_multi_fn.h"
+
+/** Multi-function device name prefix */
+#define RTE_MULTI_FN_DEV_NAME_PREFIX rawdev_mfn_
+/** Multi-function device name prefix string */
+#define RTE_MULTI_FN_DEV_NAME_PREFIX_STR RTE_STR(RTE_MULTI_FN_DEV_NAME_PREFIX)
+
+#define _CONCAT(x, y) x ## y
+#define CONCAT(x, y) _CONCAT(x, y)
+
+/** Create a full multi-function device name */
+#define RTE_MULTI_FN_DEV_NAME(x) CONCAT(RTE_MULTI_FN_DEV_NAME_PREFIX, x)
+
+/**
+ * Multi-function xstat IDs
+ */
+enum rte_multi_fn_xtsat_id {
+	RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_ENQUEUES = 0,
+	/**< Successful enqueues */
+	RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_DEQUEUES,
+	/**< Successful dequeues */
+	RTE_MULTI_FN_XSTAT_ID_FAILED_ENQUEUES,
+	/**< Failed enqueues */
+	RTE_MULTI_FN_XSTAT_ID_FAILED_DEQUEUES,
+	/**< Failed dequeues */
+	RTE_MULTI_FN_XSTAT_ID_NB
+	/**< Number of stats */
+};
+
+/**
+ * Multi-function xstat names
+ */
+extern const char *
+rte_multi_fn_xstat_names[];
+
+/**
+ * Multi-function session data
+ */
+struct rte_multi_fn_session {
+	void *sess_private_data;
+};
+
+/**
+ * Session create function pointer type
+ */
+typedef struct rte_multi_fn_session *(*multi_fn_session_create_t)(
+						struct rte_rawdev *,
+						struct rte_multi_fn_xform *,
+						int);
+
+/**
+ * Session destroy function pointer type
+ */
+typedef int (*multi_fn_session_destroy_t)(struct rte_rawdev *,
+					  struct rte_multi_fn_session *);
+
+/**
+ * Structure containing multi-function ops to create and destroy a session.
+ *
+ * This structure MUST be the first element of the device's private data
+ * structure pointed to by rte_rawdev->dev_private
+ */
+struct rte_multi_fn_ops {
+	multi_fn_session_create_t session_create;
+	/**< Create session function pointer */
+	multi_fn_session_destroy_t session_destroy;
+	/**< Destroy session function pointer */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_MULTI_FN_DRIVER_H_ */
diff --git a/meson.build b/meson.build
index d36580438..de952fa98 100644
--- a/meson.build
+++ b/meson.build
@@ -102,6 +102,10 @@ message(output_message + '\n')
 
 output_message = '\n===============\nDrivers Enabled\n===============\n'
 foreach class:dpdk_driver_classes
+	if class.contains('/')
+		class_split = class.split('/')
+		class = '_'.join(class_split)
+	endif
 	class_drivers = get_variable(class + '_drivers')
 	output_message += '\n' + class + ':\n\t'
 	output_count = 0
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index d295ca0a5..b836d220d 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -347,6 +347,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_IOAT_RAWDEV)   += -lrte_rawdev_ioat
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += -lrte_rawdev_ntb
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_DMA_RAWDEV) += -lrte_rawdev_octeontx2_dma
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_EP_RAWDEV) += -lrte_rawdev_octeontx2_ep
+_LDLIBS-$(CONFIG_RTE_LIBRTE_MULTI_FN_COMMON) += -lrte_multi_fn
 endif # CONFIG_RTE_LIBRTE_RAWDEV
 
 endif # !CONFIG_RTE_BUILD_SHARED_LIBS
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 2/4] raw/aesni_mb_mfn: add aesni_mb_mfn raw device PMD
  2020-04-10 14:27 [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing David Coyle
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 1/4] raw/common: add multi-function interface David Coyle
@ 2020-04-10 14:27 ` David Coyle
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 3/4] test/rawdev: add aesni_mb_mfn raw device tests David Coyle
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-04-10 14:27 UTC (permalink / raw)
  To: dev
  Cc: declan.doherty, fiona.trahe, pablo.de.lara.guarch, brendan.ryan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, ferruh.yigit,
	David Coyle, Mairtin o Loingsigh

Add an AESNI-MB Multi-Function raw device PMD, for utilizing
multi-function capabilities of the Intel IPSec Multi Buffer
library. This PMD uses the multi-function interface to allow
combined operations be sent to the Intel IPSec Multi Buffer
library.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 MAINTAINERS                                   |    7 +
 config/common_base                            |    6 +
 drivers/raw/Makefile                          |    2 +
 drivers/raw/aesni_mb_mfn/Makefile             |   50 +
 .../raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.c    | 1508 +++++++++++++++++
 .../raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.h    |  118 ++
 .../aesni_mb_mfn/aesni_mb_mfn_rawdev_test.c   | 1123 ++++++++++++
 .../aesni_mb_mfn_rawdev_test_vectors.h        | 1184 +++++++++++++
 drivers/raw/aesni_mb_mfn/meson.build          |   26 +
 .../rte_rawdev_aesni_mb_mfn_version.map       |    3 +
 drivers/raw/meson.build                       |    3 +-
 mk/rte.app.mk                                 |    2 +
 12 files changed, 4031 insertions(+), 1 deletion(-)
 create mode 100644 drivers/raw/aesni_mb_mfn/Makefile
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.c
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.h
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test.c
 create mode 100644 drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test_vectors.h
 create mode 100644 drivers/raw/aesni_mb_mfn/meson.build
 create mode 100644 drivers/raw/aesni_mb_mfn/rte_rawdev_aesni_mb_mfn_version.map

diff --git a/MAINTAINERS b/MAINTAINERS
index 4800f6884..c0169918c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1213,6 +1213,13 @@ F: doc/guides/rawdevs/ntb.rst
 F: examples/ntb/
 F: doc/guides/sample_app_ug/ntb.rst
 
+Intel AES-NI MB Multi-Function - EXPERIMENTAL
+M: David Coyle <david.coyle@intel.com>
+M: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
+F: drivers/raw/common/multi_fn/
+F: drivers/raw/aesni_mb_mfn/
+F: doc/guides/rawdevs/aesni_mb_mfn.rst
+
 
 Packet processing
 -----------------
diff --git a/config/common_base b/config/common_base
index 27111c24c..6215a4702 100644
--- a/config/common_base
+++ b/config/common_base
@@ -818,6 +818,12 @@ CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_EP_RAWDEV=y
 #
 CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV=y
 
+#
+# Compile PMD for AESNI-MB Multi-Function raw device
+#
+CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV=n
+CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV_DEBUG=n
+
 #
 # Compile multi-fn raw device interface
 #
diff --git a/drivers/raw/Makefile b/drivers/raw/Makefile
index e16da8d95..8d0277952 100644
--- a/drivers/raw/Makefile
+++ b/drivers/raw/Makefile
@@ -15,5 +15,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += ntb
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_DMA_RAWDEV) += octeontx2_dma
 DIRS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_EP_RAWDEV) += octeontx2_ep
 DIRS-y += common
+DIRS-$(CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV) += aesni_mb_mfn
+DEPDIRS-aesni_mb_mfn := common
 
 include $(RTE_SDK)/mk/rte.subdir.mk
diff --git a/drivers/raw/aesni_mb_mfn/Makefile b/drivers/raw/aesni_mb_mfn/Makefile
new file mode 100644
index 000000000..d14c5107f
--- /dev/null
+++ b/drivers/raw/aesni_mb_mfn/Makefile
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation.
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+# library name
+LIB = librte_rawdev_aesni_mb_mfn.a
+
+# build flags
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
+# versioning export map
+EXPORT_MAP := rte_rawdev_aesni_mb_mfn_version.map
+
+# external library dependencies
+LDLIBS += -lIPSec_MB
+LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
+LDLIBS += -lrte_rawdev
+LDLIBS += -lrte_bus_vdev
+LDLIBS += -lrte_multi_fn
+
+ifneq ($(CONFIG_RTE_LIBRTE_MULTI_FN_COMMON),y)
+$(error "RTE_LIBRTE_MULTI_FN_COMMON is required to build aesni_mb_mfn raw "
+	"device")
+endif
+
+IMB_HDR = $(shell echo '\#include <intel-ipsec-mb.h>' | \
+	$(CC) -E $(EXTRA_CFLAGS) - | grep 'intel-ipsec-mb.h' | \
+	head -n1 | cut -d'"' -f2)
+
+# Detect library version
+IMB_VERSION = $(shell grep -e "IMB_VERSION_STR" $(IMB_HDR) | cut -d'"' -f2)
+IMB_VERSION_NUM = $(shell grep -e "IMB_VERSION_NUM" $(IMB_HDR) | cut -d' ' -f3)
+
+ifeq ($(IMB_VERSION),)
+$(error "IPSec_MB version >= 0.54 is required to build aesni_mb_mfn raw "
+	"device")
+endif
+
+ifeq ($(shell expr $(IMB_VERSION_NUM) \< 0x3600), 1)
+$(error "IPSec_MB version >= 0.54 is required to build aesni_mb_mfn raw "
+	"device")
+endif
+
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV) += aesni_mb_mfn_rawdev.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV) += aesni_mb_mfn_rawdev_test.c
+
+include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.c b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.c
new file mode 100644
index 000000000..01f0d495a
--- /dev/null
+++ b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.c
@@ -0,0 +1,1508 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#include <stdbool.h>
+
+#include <intel-ipsec-mb.h>
+
+#include <rte_common.h>
+#include <rte_crypto.h>
+#include <rte_eal.h>
+#include <rte_bus_vdev.h>
+#include <rte_malloc.h>
+#include <rte_cpuflags.h>
+#include <rte_rawdev.h>
+#include <rte_rawdev_pmd.h>
+#include <rte_string_fns.h>
+#include <rte_multi_fn.h>
+#include <rte_ether.h>
+
+#include "aesni_mb_mfn_rawdev.h"
+
+#define MAX_QUEUES        (64)
+#define RING_NAME_MAX_LEN (64)
+
+#define GPON_BIP_LEN             (4)
+#define GPON_AUTH_TAG_CRC_OFFSET (4)
+
+static const uint16_t err_detect_output_byte_lengths[] = {
+	[IMB_AUTH_DOCSIS_CRC32] = RTE_ETHER_CRC_LEN,
+	[IMB_AUTH_PON_CRC_BIP] = (GPON_BIP_LEN + RTE_ETHER_CRC_LEN),
+};
+
+static const char *driver_name = AESNI_MB_MFN_PMD_RAWDEV_NAME_STR;
+
+static int
+qp_unique_name_set(struct rte_rawdev *rawdev, struct aesni_mb_mfn_qp *qp)
+{
+	unsigned int n = snprintf(qp->name,
+				  sizeof(qp->name),
+				  "%s_%u_qp_%u",
+				  driver_name,
+				  rawdev->dev_id,
+				  qp->id);
+
+	if (n >= sizeof(qp->name))
+		return -1;
+
+	return 0;
+}
+
+static struct rte_ring *
+qp_processed_ops_ring_create(struct aesni_mb_mfn_qp *qp,
+			     unsigned int ring_size,
+			     int socket_id)
+{
+	struct rte_ring *r;
+	char ring_name[RING_NAME_MAX_LEN];
+
+	unsigned int n = strlcpy(ring_name, qp->name, sizeof(ring_name));
+
+	if (n >= sizeof(ring_name))
+		return NULL;
+
+	r = rte_ring_lookup(ring_name);
+	if (r) {
+		if (rte_ring_get_size(r) >= ring_size) {
+			AESNI_MB_MFN_DEBUG("Reusing existing ring %s for "
+					   "processed ops",
+					   ring_name);
+			return r;
+		}
+
+		AESNI_MB_MFN_ERR("Unable to reuse existing ring %s for "
+				 "processed ops",
+				 ring_name);
+		return NULL;
+	}
+
+	return rte_ring_create(ring_name,
+			       ring_size,
+			       socket_id,
+			       RING_F_SP_ENQ | RING_F_SC_DEQ);
+}
+
+static uint16_t
+err_detect_output_byte_length_get(JOB_HASH_ALG algo)
+{
+	return err_detect_output_byte_lengths[algo];
+}
+
+static bool
+docsis_crc_crypto_encrypt_session_check(struct rte_multi_fn_xform *xform)
+{
+	struct rte_crypto_sym_xform *crypto_sym;
+	struct rte_multi_fn_err_detect_xform *err_detect;
+	struct rte_multi_fn_xform *next;
+
+	if (xform->type != RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT)
+		return false;
+
+	err_detect = &xform->err_detect;
+	next = xform->next;
+
+	if (err_detect->algo != RTE_MULTI_FN_ERR_DETECT_CRC32_ETH ||
+			err_detect->op != RTE_MULTI_FN_ERR_DETECT_OP_GENERATE ||
+			next == NULL ||
+			next->type != RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM)
+		return false;
+
+	crypto_sym = &next->crypto_sym;
+	next = next->next;
+
+	if (crypto_sym->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
+			crypto_sym->cipher.op != RTE_CRYPTO_CIPHER_OP_ENCRYPT ||
+			crypto_sym->cipher.algo !=
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI ||
+			crypto_sym->cipher.key.length !=
+					IMB_KEY_AES_128_BYTES ||
+			crypto_sym->cipher.iv.length != AES_BLOCK_SIZE ||
+			next != NULL)
+		return false;
+
+	return true;
+}
+
+static bool
+docsis_crypto_decrypt_crc_session_check(struct rte_multi_fn_xform *xform)
+{
+	struct rte_crypto_sym_xform *crypto_sym;
+	struct rte_multi_fn_err_detect_xform *err_detect;
+	struct rte_multi_fn_xform *next;
+
+	if (xform->type != RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM)
+		return false;
+
+	crypto_sym = &xform->crypto_sym;
+	next = xform->next;
+
+	if (crypto_sym->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
+			crypto_sym->cipher.op != RTE_CRYPTO_CIPHER_OP_DECRYPT ||
+			crypto_sym->cipher.algo !=
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI ||
+			crypto_sym->cipher.key.length !=
+					IMB_KEY_AES_128_BYTES ||
+			crypto_sym->cipher.iv.length != AES_BLOCK_SIZE ||
+			next == NULL ||
+			next->type != RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT)
+		return false;
+
+	err_detect = &next->err_detect;
+	next = next->next;
+
+	if (err_detect->algo != RTE_MULTI_FN_ERR_DETECT_CRC32_ETH ||
+			err_detect->op != RTE_MULTI_FN_ERR_DETECT_OP_VERIFY ||
+			next != NULL)
+		return false;
+
+	return true;
+}
+
+static bool
+gpon_crc_crypto_encrypt_bip_session_check(struct rte_multi_fn_xform *xform)
+{
+	struct rte_crypto_sym_xform *crypto_sym;
+	struct rte_multi_fn_err_detect_xform *err_detect;
+	struct rte_multi_fn_xform *next;
+
+	if (xform->type != RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT)
+		return false;
+
+	err_detect = &xform->err_detect;
+	next = xform->next;
+
+	if (err_detect->algo != RTE_MULTI_FN_ERR_DETECT_CRC32_ETH ||
+			err_detect->op != RTE_MULTI_FN_ERR_DETECT_OP_GENERATE ||
+			next == NULL ||
+			next->type != RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM)
+		return false;
+
+	crypto_sym = &next->crypto_sym;
+	next = next->next;
+
+	if (crypto_sym->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
+			crypto_sym->cipher.op != RTE_CRYPTO_CIPHER_OP_ENCRYPT ||
+			crypto_sym->cipher.algo != RTE_CRYPTO_CIPHER_AES_CTR ||
+			crypto_sym->cipher.key.length !=
+						IMB_KEY_AES_128_BYTES ||
+			crypto_sym->cipher.iv.length != AES_BLOCK_SIZE ||
+			next == NULL ||
+			next->type != RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT)
+		return false;
+
+	err_detect = &next->err_detect;
+	next = next->next;
+
+	if (err_detect->algo != RTE_MULTI_FN_ERR_DETECT_BIP32 ||
+			err_detect->op != RTE_MULTI_FN_ERR_DETECT_OP_GENERATE ||
+			next != NULL)
+		return false;
+
+	return true;
+}
+
+static bool
+gpon_bip_crypto_decrypt_crc_session_check(struct rte_multi_fn_xform *xform)
+{
+	struct rte_crypto_sym_xform *crypto_sym;
+	struct rte_multi_fn_err_detect_xform *err_detect;
+	struct rte_multi_fn_xform *next;
+
+	if (xform->type != RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT)
+		return false;
+
+	err_detect = &xform->err_detect;
+	next = xform->next;
+
+	if (err_detect->algo != RTE_MULTI_FN_ERR_DETECT_BIP32 ||
+			err_detect->op != RTE_MULTI_FN_ERR_DETECT_OP_GENERATE ||
+			next == NULL ||
+			next->type != RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM)
+		return false;
+
+	crypto_sym = &next->crypto_sym;
+	next = next->next;
+
+	if (crypto_sym->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
+			crypto_sym->cipher.op != RTE_CRYPTO_CIPHER_OP_DECRYPT ||
+			crypto_sym->cipher.algo != RTE_CRYPTO_CIPHER_AES_CTR ||
+			crypto_sym->cipher.key.length !=
+						IMB_KEY_AES_128_BYTES ||
+			crypto_sym->cipher.iv.length != AES_BLOCK_SIZE ||
+			next == NULL ||
+			next->type != RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT)
+		return false;
+
+	err_detect = &next->err_detect;
+	next = next->next;
+
+	if (err_detect->algo != RTE_MULTI_FN_ERR_DETECT_CRC32_ETH ||
+			err_detect->op != RTE_MULTI_FN_ERR_DETECT_OP_VERIFY ||
+			next != NULL)
+		return false;
+
+	return true;
+}
+
+static enum aesni_mb_mfn_op
+session_support_check(struct rte_multi_fn_xform *xform)
+{
+	enum aesni_mb_mfn_op op = AESNI_MB_MFN_OP_NOT_SUPPORTED;
+
+	if (docsis_crc_crypto_encrypt_session_check(xform))
+		op = AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO;
+	else if (docsis_crypto_decrypt_crc_session_check(xform))
+		op = AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC;
+	else if (gpon_crc_crypto_encrypt_bip_session_check(xform))
+		op = AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP;
+	else if (gpon_bip_crypto_decrypt_crc_session_check(xform))
+		op = AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC;
+
+	return op;
+}
+
+static int
+session_err_detect_parameters_set(struct aesni_mb_mfn_session *sess)
+{
+	switch (sess->op) {
+	case AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO:
+		sess->err_detect.operation =
+					RTE_MULTI_FN_ERR_DETECT_OP_GENERATE;
+		sess->err_detect.algo = IMB_AUTH_DOCSIS_CRC32;
+		break;
+	case AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC:
+		sess->err_detect.operation = RTE_MULTI_FN_ERR_DETECT_OP_VERIFY;
+		sess->err_detect.algo = IMB_AUTH_DOCSIS_CRC32;
+		break;
+	case AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP:
+		sess->err_detect.operation =
+					RTE_MULTI_FN_ERR_DETECT_OP_GENERATE;
+		sess->err_detect.algo = IMB_AUTH_PON_CRC_BIP;
+		break;
+	case AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC:
+		sess->err_detect.operation = RTE_MULTI_FN_ERR_DETECT_OP_VERIFY;
+		sess->err_detect.algo = IMB_AUTH_PON_CRC_BIP;
+		break;
+	default:
+		AESNI_MB_MFN_ERR("Unsupported operation for error detection");
+		return -ENOTSUP;
+	}
+
+	sess->err_detect.gen_output_len =
+		err_detect_output_byte_length_get(sess->err_detect.algo);
+
+	return 0;
+}
+
+static int
+session_cipher_parameters_set(const MB_MGR *mb_mgr,
+			      struct aesni_mb_mfn_session *sess,
+			      const struct rte_crypto_sym_xform *xform)
+{
+
+	if (xform == NULL) {
+		sess->cipher.mode = IMB_CIPHER_NULL;
+		return -EINVAL;
+	}
+
+	if (xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER) {
+		AESNI_MB_MFN_ERR("Crypto xform not of type cipher");
+		return -EINVAL;
+	}
+
+	/* Select cipher direction */
+	switch (sess->op) {
+	case AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO:
+		sess->cipher.direction = IMB_DIR_ENCRYPT;
+		sess->cipher.mode = IMB_CIPHER_DOCSIS_SEC_BPI;
+		break;
+	case AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC:
+		sess->cipher.direction = IMB_DIR_DECRYPT;
+		sess->cipher.mode = IMB_CIPHER_DOCSIS_SEC_BPI;
+		break;
+	case AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP:
+		sess->cipher.direction = IMB_DIR_ENCRYPT;
+		sess->cipher.mode = IMB_CIPHER_PON_AES_CNTR;
+		break;
+	case AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC:
+		sess->cipher.direction = IMB_DIR_DECRYPT;
+		sess->cipher.mode = IMB_CIPHER_PON_AES_CNTR;
+		break;
+	default:
+		AESNI_MB_MFN_ERR("Unsupported operation for cipher");
+		return -ENOTSUP;
+	}
+
+	/* Set IV parameters */
+	sess->iv.offset = xform->cipher.iv.offset;
+	sess->iv.length = xform->cipher.iv.length;
+
+	/* Check key length and choose key expansion function for AES */
+	switch (xform->cipher.key.length) {
+	case IMB_KEY_AES_128_BYTES:
+		sess->cipher.key_length_in_bytes = IMB_KEY_AES_128_BYTES;
+		IMB_AES_KEYEXP_128(mb_mgr,
+				   xform->cipher.key.data,
+				   sess->cipher.expanded_aes_keys.encode,
+				   sess->cipher.expanded_aes_keys.decode);
+		break;
+	case IMB_KEY_AES_256_BYTES:
+		sess->cipher.key_length_in_bytes = IMB_KEY_AES_256_BYTES;
+		IMB_AES_KEYEXP_256(mb_mgr,
+				   xform->cipher.key.data,
+				   sess->cipher.expanded_aes_keys.encode,
+				   sess->cipher.expanded_aes_keys.decode);
+		break;
+	default:
+		AESNI_MB_MFN_ERR("Invalid cipher key length");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static inline struct aesni_mb_mfn_session *
+session_get(struct rte_multi_fn_op *op)
+{
+	struct aesni_mb_mfn_session *sess = NULL;
+
+	if (likely(op->sess != NULL))
+		sess = op->sess->sess_private_data;
+	else
+		op->overall_status = RTE_MULTI_FN_STATUS_INVALID_SESSION;
+
+	return sess;
+}
+
+static inline int
+op_chain_parse(struct aesni_mb_mfn_session *sess,
+	       struct rte_multi_fn_op *op_chain,
+	       struct rte_multi_fn_op **cipher_op,
+	       struct rte_multi_fn_op **crc_op,
+	       struct rte_multi_fn_op **bip_op)
+{
+	*cipher_op = NULL;
+	*crc_op = NULL;
+	*bip_op = NULL;
+
+	switch (sess->op) {
+	case AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO:
+	case AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC:
+		if (unlikely(op_chain == NULL || op_chain->next == NULL)) {
+			return -EINVAL;
+		} else if (sess->op == AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO) {
+			*crc_op = op_chain;
+			*cipher_op = op_chain->next;
+		} else {
+			*cipher_op = op_chain;
+			*crc_op = op_chain->next;
+		}
+		break;
+	case AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP:
+	case AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC:
+		if (unlikely(op_chain == NULL ||
+				op_chain->next == NULL ||
+				op_chain->next->next == NULL)) {
+			return -EINVAL;
+		} else if (sess->op == AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP) {
+			*crc_op = op_chain;
+			*cipher_op = op_chain->next;
+			*bip_op = op_chain->next->next;
+		} else {
+			*bip_op = op_chain;
+			*cipher_op = op_chain->next;
+			*crc_op = op_chain->next->next;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static inline void
+op_statuses_set(struct rte_multi_fn_op *first_op,
+		struct rte_multi_fn_op *cipher_op,
+		struct rte_multi_fn_op *crc_op,
+		struct rte_multi_fn_op *bip_op,
+		enum rte_multi_fn_op_status overall_status,
+		uint8_t crypto_status,
+		uint8_t err_detect_status)
+{
+	first_op->overall_status = overall_status;
+
+	if (cipher_op != NULL)
+		cipher_op->op_status = crypto_status;
+	if (crc_op != NULL)
+		crc_op->op_status = err_detect_status;
+	if (bip_op != NULL)
+		bip_op->op_status = err_detect_status;
+}
+
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV_DEBUG
+#define DOCSIS_CIPHER_CRC_OFFSET_DIFF (RTE_ETHER_HDR_LEN - RTE_ETHER_TYPE_LEN)
+#define DOCSIS_CIPHER_CRC_LENGTH_DIFF (RTE_ETHER_HDR_LEN - \
+					RTE_ETHER_TYPE_LEN - \
+					RTE_ETHER_CRC_LEN)
+
+static inline int
+docsis_crypto_crc_op_check(struct rte_multi_fn_op *first_op,
+			   struct rte_multi_fn_op *cipher_op,
+			   struct rte_multi_fn_op *crc_op)
+{
+	struct rte_multi_fn_op *err_op = NULL;
+	uint8_t err_op_status;
+	const uint32_t offset_diff = DOCSIS_CIPHER_CRC_OFFSET_DIFF;
+	struct rte_crypto_sym_op *sym = &cipher_op->crypto_sym;
+	struct rte_multi_fn_err_detect_op *crc = &crc_op->err_detect;
+
+	if (sym->cipher.data.length && crc->data.length) {
+
+		/* Cipher offset must be at least 12 greater than CRC offset */
+		if (sym->cipher.data.offset <
+				((uint32_t)crc->data.offset + offset_diff)) {
+			err_op = crc_op;
+			err_op_status = RTE_MULTI_FN_ERR_DETECT_OP_STATUS_ERROR;
+
+		/*
+		 * Cipher length must be at least 8 less than CRC length, taking
+		 * known differences of what is ciphered and what is crc'ed into
+		 * account
+		 */
+		} else if ((sym->cipher.data.length +
+					DOCSIS_CIPHER_CRC_LENGTH_DIFF) >
+				crc->data.length) {
+			err_op = crc_op;
+			err_op_status = RTE_MULTI_FN_ERR_DETECT_OP_STATUS_ERROR;
+		}
+	}
+
+	if (err_op != NULL) {
+		err_op->op_status = err_op_status;
+		first_op->overall_status = RTE_MULTI_FN_OP_STATUS_FAILURE;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+#define GPON_FRAME_HDR_SIZE      (8U)
+#define GPON_FRAME_MULTIPLE_SIZE (4)
+#define GPON_PLI_SHIFT_BITS      (2)
+
+static inline int
+gpon_crypto_crc_bip_op_check(struct rte_multi_fn_op *first_op,
+			     struct rte_multi_fn_op *crc_op,
+			     struct rte_multi_fn_op *bip_op,
+			     struct rte_mbuf *m_src)
+{
+	struct rte_multi_fn_op *err_op = NULL;
+	uint8_t err_op_status;
+	struct rte_multi_fn_err_detect_op *crc = &crc_op->err_detect;
+	struct rte_multi_fn_err_detect_op *bip = &bip_op->err_detect;
+
+	/*
+	 * BIP length must be multiple of 4 and be at least a full GPON header
+	 * in size
+	 */
+	if (bip->data.length % GPON_FRAME_MULTIPLE_SIZE != 0 ||
+			bip->data.length < GPON_FRAME_HDR_SIZE) {
+		err_op = bip_op;
+		err_op_status = RTE_MULTI_FN_ERR_DETECT_OP_STATUS_ERROR;
+	}
+
+	/*
+	 * Check the PLI field in the GPON frame header matches the
+	 * CRC length
+	 */
+	uint16_t *pli_key_idx = rte_pktmbuf_mtod(m_src, uint16_t *);
+	uint16_t pli = rte_bswap16(*pli_key_idx) >> GPON_PLI_SHIFT_BITS;
+
+	if (crc->data.length != 0 &&
+			crc->data.length != (pli - RTE_ETHER_CRC_LEN)) {
+		err_op = crc_op;
+		err_op_status = RTE_MULTI_FN_ERR_DETECT_OP_STATUS_ERROR;
+	}
+
+	if (err_op != NULL) {
+		err_op->op_status = err_op_status;
+		first_op->overall_status = RTE_MULTI_FN_OP_STATUS_FAILURE;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif /* RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV_DEBUG */
+
+static inline int
+mb_job_params_set(JOB_AES_HMAC *job,
+		  struct aesni_mb_mfn_qp *qp,
+		  struct rte_multi_fn_op *op,
+		  uint8_t *output_idx)
+{
+	struct rte_mbuf *m_src, *m_dst;
+	struct rte_multi_fn_op *cipher_op;
+	struct rte_multi_fn_op *crc_op;
+	struct rte_multi_fn_op *bip_op;
+	uint32_t cipher_offset;
+	struct aesni_mb_mfn_session *session;
+	struct rte_crypto_sym_op *sym;
+	struct rte_multi_fn_err_detect_op *err;
+
+	session = session_get(op);
+	if (unlikely(session == NULL)) {
+		op->overall_status = RTE_MULTI_FN_STATUS_INVALID_SESSION;
+		return -EINVAL;
+	}
+
+	if (unlikely(op_chain_parse(session,
+				    op,
+				    &cipher_op,
+				    &crc_op,
+				    &bip_op) < 0)) {
+		op_statuses_set(
+			op,
+			cipher_op,
+			crc_op,
+			bip_op,
+			RTE_MULTI_FN_OP_STATUS_FAILURE,
+			RTE_CRYPTO_OP_STATUS_NOT_PROCESSED,
+			RTE_MULTI_FN_ERR_DETECT_OP_STATUS_NOT_PROCESSED);
+		return -EINVAL;
+	}
+
+	op_statuses_set(op,
+			cipher_op,
+			crc_op,
+			bip_op,
+			RTE_MULTI_FN_OP_STATUS_NOT_PROCESSED,
+			RTE_CRYPTO_OP_STATUS_NOT_PROCESSED,
+			RTE_MULTI_FN_ERR_DETECT_OP_STATUS_NOT_PROCESSED);
+
+	m_src = op->m_src;
+
+	if (unlikely(m_src == NULL)) {
+		op->overall_status = RTE_MULTI_FN_OP_STATUS_FAILURE;
+		return -EINVAL;
+	}
+
+	if (likely(op->m_dst == NULL || op->m_dst == op->m_src)) {
+		/* in-place operation */
+		m_dst = m_src;
+	} else {
+		/* out-of-place operation not supported */
+		op->overall_status = RTE_MULTI_FN_OP_STATUS_FAILURE;
+		return -EINVAL;
+	}
+
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV_DEBUG
+	switch (session->op) {
+	case AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO:
+	case AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC:
+		if (docsis_crypto_crc_op_check(op, cipher_op, crc_op) < 0)
+			return -EINVAL;
+		break;
+	case AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP:
+	case AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC:
+	/*
+	 * session->op is known to be ok at this point so ok to include
+	 * default case here
+	 */
+	default:
+		if (gpon_crypto_crc_bip_op_check(op, crc_op, bip_op, m_src) < 0)
+			return -EINVAL;
+		break;
+	}
+#endif /* RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV_DEBUG */
+
+	/* Set order */
+	job->chain_order = session->chain_order;
+
+	/* Set cipher parameters */
+	job->cipher_direction = session->cipher.direction;
+	job->cipher_mode = session->cipher.mode;
+
+	job->key_len_in_bytes = session->cipher.key_length_in_bytes;
+	job->enc_keys = session->cipher.expanded_aes_keys.encode;
+	job->dec_keys = session->cipher.expanded_aes_keys.decode;
+
+	/*
+	 * Set error detection parameters
+	 * In intel-ipsec-mb, error detection is treated as a hash algorithm
+	 */
+	job->hash_alg = session->err_detect.algo;
+
+	job->auth_tag_output = qp->temp_outputs[*output_idx];
+	*output_idx = (*output_idx + 1) % MAX_JOBS;
+
+	job->auth_tag_output_len_in_bytes = session->err_detect.gen_output_len;
+
+	/* Set data parameters */
+	sym = &cipher_op->crypto_sym;
+	cipher_offset = sym->cipher.data.offset;
+
+	job->src = rte_pktmbuf_mtod(m_src, uint8_t *);
+	job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *, cipher_offset);
+
+	job->cipher_start_src_offset_in_bytes =	cipher_offset;
+	job->msg_len_to_cipher_in_bytes = sym->cipher.data.length;
+
+	switch (session->op) {
+	case AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO:
+	case AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC:
+		err = &crc_op->err_detect;
+		job->hash_start_src_offset_in_bytes = err->data.offset;
+		job->msg_len_to_hash_in_bytes = err->data.length;
+
+		break;
+	case AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP:
+	case AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC:
+	/*
+	 * session->op is known to be ok at this point so ok to include
+	 * default case here
+	 */
+	default:
+		err = &bip_op->err_detect;
+		job->hash_start_src_offset_in_bytes = err->data.offset;
+		job->msg_len_to_hash_in_bytes = err->data.length;
+		break;
+	}
+
+	/* Set IV parameters */
+	job->iv_len_in_bytes = session->iv.length;
+	job->iv = (uint8_t *)cipher_op + session->iv.offset;
+
+	job->user_data = op;
+
+	return 0;
+}
+
+static inline void
+bip_copy(JOB_AES_HMAC *job, struct rte_multi_fn_op *bip_op)
+{
+	if (bip_op->err_detect.data.length == 0)
+		return;
+
+	/* Copy BIP to output location */
+	memcpy(bip_op->err_detect.output.data,
+	       job->auth_tag_output,
+	       GPON_BIP_LEN);
+}
+
+static inline void
+crc_verify(JOB_AES_HMAC *job,
+	   struct rte_multi_fn_op *crc_op,
+	   uint8_t auth_tag_crc_offset)
+{
+	if (crc_op->err_detect.data.length == 0)
+		return;
+
+	/* Verify CRC */
+	if (memcmp(job->auth_tag_output + auth_tag_crc_offset,
+		   crc_op->err_detect.output.data,
+		   RTE_ETHER_CRC_LEN) != 0)
+		crc_op->op_status =
+			RTE_MULTI_FN_ERR_DETECT_OP_STATUS_VERIFY_FAILED;
+}
+
+static inline struct rte_multi_fn_op *
+mb_job_post_process(JOB_AES_HMAC *job)
+{
+	struct rte_multi_fn_op *op = (struct rte_multi_fn_op *)job->user_data;
+	struct aesni_mb_mfn_session *sess = op->sess->sess_private_data;
+	struct rte_multi_fn_op *cipher_op;
+	struct rte_multi_fn_op *crc_op;
+	struct rte_multi_fn_op *bip_op;
+
+	if (unlikely(op_chain_parse(sess,
+				    op,
+				    &cipher_op,
+				    &crc_op,
+				    &bip_op) < 0)) {
+		op_statuses_set(
+			op,
+			cipher_op,
+			crc_op,
+			bip_op,
+			RTE_MULTI_FN_OP_STATUS_FAILURE,
+			RTE_CRYPTO_OP_STATUS_ERROR,
+			RTE_MULTI_FN_ERR_DETECT_OP_STATUS_ERROR);
+
+	} else if (op->overall_status ==
+				RTE_MULTI_FN_OP_STATUS_NOT_PROCESSED) {
+		switch (job->status) {
+		case STS_COMPLETED:
+			if (unlikely(job->hash_alg == IMB_AUTH_NULL))
+				break;
+
+			op_statuses_set(
+				op,
+				cipher_op,
+				crc_op,
+				bip_op,
+				RTE_MULTI_FN_OP_STATUS_SUCCESS,
+				RTE_CRYPTO_OP_STATUS_SUCCESS,
+				RTE_MULTI_FN_ERR_DETECT_OP_STATUS_SUCCESS);
+
+			if (job->hash_alg == IMB_AUTH_PON_CRC_BIP)
+				bip_copy(job, bip_op);
+
+			if (sess->err_detect.operation ==
+					RTE_MULTI_FN_ERR_DETECT_OP_VERIFY)
+				crc_verify(
+					job,
+					crc_op,
+					job->hash_alg == IMB_AUTH_PON_CRC_BIP ?
+						GPON_AUTH_TAG_CRC_OFFSET : 0);
+
+			if (crc_op->op_status !=
+				RTE_MULTI_FN_ERR_DETECT_OP_STATUS_SUCCESS)
+				op->overall_status =
+					RTE_MULTI_FN_OP_STATUS_FAILURE;
+			break;
+		default:
+			op_statuses_set(
+				op,
+				cipher_op,
+				crc_op,
+				bip_op,
+				RTE_MULTI_FN_OP_STATUS_FAILURE,
+				RTE_CRYPTO_OP_STATUS_ERROR,
+				RTE_MULTI_FN_ERR_DETECT_OP_STATUS_ERROR);
+			break;
+		}
+	}
+
+	return op;
+}
+
+static unsigned
+completed_jobs_handle(struct aesni_mb_mfn_qp *qp,
+		      JOB_AES_HMAC *job,
+		      struct rte_multi_fn_op **ops,
+		      uint16_t nb_ops)
+{
+	struct rte_multi_fn_op *op = NULL;
+	unsigned int processed_jobs = 0;
+
+	while (job != NULL) {
+		op = mb_job_post_process(job);
+
+		if (op) {
+			ops[processed_jobs++] = op;
+			qp->stats.dequeued_count++;
+		} else {
+			qp->stats.dequeue_err_count++;
+			break;
+		}
+		if (processed_jobs == nb_ops)
+			break;
+
+		job = IMB_GET_COMPLETED_JOB(qp->mb_mgr);
+	}
+
+	return processed_jobs;
+}
+
+static inline uint16_t
+mb_mgr_flush(struct aesni_mb_mfn_qp *qp,
+	     struct rte_multi_fn_op **ops,
+	     uint16_t nb_ops)
+{
+	int processed_ops = 0;
+
+	/* Flush the remaining jobs */
+	JOB_AES_HMAC *job = IMB_FLUSH_JOB(qp->mb_mgr);
+
+	if (job)
+		processed_ops += completed_jobs_handle(qp,
+						       job,
+						       &ops[processed_ops],
+						       nb_ops - processed_ops);
+
+	return processed_ops;
+}
+
+static inline JOB_AES_HMAC *
+mb_job_params_null_set(JOB_AES_HMAC *job, struct rte_multi_fn_op *op)
+{
+	job->chain_order = IMB_ORDER_HASH_CIPHER;
+	job->cipher_mode = IMB_CIPHER_NULL;
+	job->hash_alg = IMB_AUTH_NULL;
+	job->cipher_direction = IMB_DIR_DECRYPT;
+
+	/* Set user data to be multi-fn operation data struct */
+	job->user_data = op;
+
+	return job;
+}
+
+static int
+aesni_mb_mfn_pmd_config(const struct rte_rawdev *rawdev,
+			rte_rawdev_obj_t config)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct rte_multi_fn_dev_config *conf = config;
+	char name[RTE_MEMZONE_NAMESIZE];
+
+	aesni_mb_mfn_dev->nb_queue_pairs = conf->nb_queues;
+
+	snprintf(name, sizeof(name), "%s_qps", driver_name);
+	aesni_mb_mfn_dev->queue_pairs =
+			rte_zmalloc_socket(
+				name,
+				aesni_mb_mfn_dev->nb_queue_pairs *
+					sizeof(struct aesni_mb_mfn_qp *),
+				RTE_CACHE_LINE_SIZE,
+				rawdev->socket_id);
+
+	if (aesni_mb_mfn_dev->queue_pairs == NULL) {
+		AESNI_MB_MFN_ERR("Unable to allocate queue pairs");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void
+aesni_mb_mfn_pmd_info_get(struct rte_rawdev *rawdev,
+			  rte_rawdev_obj_t dev_info)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct rte_multi_fn_dev_info *info = dev_info;
+
+	if (info != NULL)
+		info->max_nb_queues = aesni_mb_mfn_dev->max_nb_queue_pairs;
+}
+
+static int
+aesni_mb_mfn_pmd_start(__rte_unused struct rte_rawdev *rawdev)
+{
+	return 0;
+}
+
+static void
+aesni_mb_mfn_pmd_stop(__rte_unused struct rte_rawdev *rawdev)
+{
+}
+
+static int
+aesni_mb_mfn_pmd_close(struct rte_rawdev *rawdev)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+
+	if (aesni_mb_mfn_dev->queue_pairs != NULL)
+		rte_free(aesni_mb_mfn_dev->queue_pairs);
+
+	return 0;
+}
+
+static int
+aesni_mb_mfn_pmd_qp_release(struct rte_rawdev *rawdev, uint16_t qp_id)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct aesni_mb_mfn_qp *qp = aesni_mb_mfn_dev->queue_pairs[qp_id];
+	struct rte_ring *r = NULL;
+
+	if (qp != NULL) {
+		r = rte_ring_lookup(qp->name);
+		if (r)
+			rte_ring_free(r);
+		if (qp->mb_mgr)
+			free_mb_mgr(qp->mb_mgr);
+		rte_free(qp);
+		aesni_mb_mfn_dev->queue_pairs[qp_id] = NULL;
+	}
+
+	return 0;
+}
+
+static int
+aesni_mb_mfn_pmd_qp_setup(struct rte_rawdev *rawdev,
+			  uint16_t qp_id,
+			  rte_rawdev_obj_t qp_c)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct aesni_mb_mfn_qp *qp = NULL;
+	const struct rte_multi_fn_qp_config *qp_conf =
+			(const struct rte_multi_fn_qp_config *)qp_c;
+	char name[RTE_MEMZONE_NAMESIZE];
+	int ret = -1;
+
+	if (qp_id >= aesni_mb_mfn_dev->max_nb_queue_pairs) {
+		AESNI_MB_MFN_ERR("Invalid queue pair id=%d", qp_id);
+		return -EINVAL;
+	}
+
+	/* Free memory prior to re-allocation if needed */
+	if (aesni_mb_mfn_dev->queue_pairs[qp_id] != NULL)
+		aesni_mb_mfn_pmd_qp_release(rawdev, qp_id);
+
+	/* Allocate the queue pair data structure */
+	snprintf(name, sizeof(name), "%s_qp", driver_name);
+	qp = rte_zmalloc_socket(name,
+				sizeof(struct aesni_mb_mfn_qp),
+				RTE_CACHE_LINE_SIZE,
+				rawdev->socket_id);
+	if (qp == NULL)
+		return -ENOMEM;
+
+	qp->id = qp_id;
+	aesni_mb_mfn_dev->queue_pairs[qp_id] = qp;
+
+	if (qp_unique_name_set(rawdev, qp))
+		goto qp_setup_cleanup;
+
+	qp->mb_mgr = alloc_mb_mgr(0);
+	if (qp->mb_mgr == NULL) {
+		ret = -ENOMEM;
+		goto qp_setup_cleanup;
+	}
+
+	switch (aesni_mb_mfn_dev->vector_mode) {
+	case AESNI_MB_MFN_SSE:
+		init_mb_mgr_sse(qp->mb_mgr);
+		break;
+	case AESNI_MB_MFN_AVX:
+		init_mb_mgr_avx(qp->mb_mgr);
+		break;
+	case AESNI_MB_MFN_AVX2:
+		init_mb_mgr_avx2(qp->mb_mgr);
+		break;
+	case AESNI_MB_MFN_AVX512:
+		init_mb_mgr_avx512(qp->mb_mgr);
+		break;
+	default:
+		AESNI_MB_MFN_ERR("Unsupported vector mode %u",
+				 aesni_mb_mfn_dev->vector_mode);
+		goto qp_setup_cleanup;
+	}
+
+	qp->ingress_queue = qp_processed_ops_ring_create(
+						qp,
+						qp_conf->nb_descriptors,
+						rawdev->socket_id);
+	if (qp->ingress_queue == NULL) {
+		ret = -1;
+		goto qp_setup_cleanup;
+	}
+
+	memset(&qp->stats, 0, sizeof(qp->stats));
+
+	return 0;
+
+qp_setup_cleanup:
+	if (qp) {
+		if (qp->mb_mgr)
+			free_mb_mgr(qp->mb_mgr);
+		rte_free(qp);
+	}
+
+	return ret;
+}
+
+static uint16_t
+aesni_mb_mfn_pmd_qp_count(struct rte_rawdev *rawdev)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+
+	return aesni_mb_mfn_dev->nb_queue_pairs;
+}
+
+static int
+aesni_mb_mfn_pmd_enq(struct rte_rawdev *rawdev,
+		     struct rte_rawdev_buf **ops,
+		     unsigned int nb_ops,
+		     rte_rawdev_obj_t q_id)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct aesni_mb_mfn_qp *qp;
+	unsigned int nb_enqueued;
+
+	qp = aesni_mb_mfn_dev->queue_pairs[*(uint16_t *)q_id];
+
+	nb_enqueued = rte_ring_enqueue_burst(qp->ingress_queue,
+					     (void **)ops,
+					     nb_ops,
+					     NULL);
+
+	qp->stats.enqueued_count += nb_enqueued;
+
+	return nb_enqueued;
+}
+
+static int
+aesni_mb_mfn_pmd_deq(struct rte_rawdev *rawdev,
+		     struct rte_rawdev_buf **ops,
+		     unsigned int nb_ops,
+		     rte_rawdev_obj_t q_id)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct aesni_mb_mfn_qp *qp;
+	struct rte_multi_fn_op *op;
+	JOB_AES_HMAC *job;
+	uint8_t output_idx;
+	unsigned int processed_jobs = 0;
+	int ret;
+
+	qp = aesni_mb_mfn_dev->queue_pairs[*(uint16_t *)q_id];
+
+	if (unlikely(nb_ops == 0))
+		return 0;
+
+	output_idx = qp->output_idx;
+
+	do {
+		/* Get next free mb job struct from mb manager */
+		job = IMB_GET_NEXT_JOB(qp->mb_mgr);
+		if (unlikely(job == NULL)) {
+			/* if no free mb job structs we need to flush mb_mgr */
+			processed_jobs += mb_mgr_flush(
+						qp,
+						(struct rte_multi_fn_op **)
+							&ops[processed_jobs],
+						nb_ops - processed_jobs);
+
+			if (nb_ops == processed_jobs)
+				break;
+
+			job = IMB_GET_NEXT_JOB(qp->mb_mgr);
+		}
+
+		/*
+		 * Get next operation to process from ingress queue.
+		 * There is no need to return the job to the MB_MGR if there
+		 * are no more operations to process, since the MB_MGR can use
+		 * that pointer again in next get_next calls.
+		 */
+		ret = rte_ring_dequeue(qp->ingress_queue, (void **)&op);
+		if (ret < 0)
+			break;
+
+		ret = mb_job_params_set(job, qp, op, &output_idx);
+		if (unlikely(ret != 0)) {
+			qp->stats.dequeue_err_count++;
+			mb_job_params_null_set(job, op);
+		}
+
+		/* Submit job to multi-buffer for processing */
+#ifdef RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV_DEBUG
+		job = IMB_SUBMIT_JOB(qp->mb_mgr);
+#else
+		job = IMB_SUBMIT_JOB_NOCHECK(qp->mb_mgr);
+#endif /* RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV_DEBUG */
+
+		/*
+		 * If submit returns a processed job then handle it,
+		 * before submitting subsequent jobs
+		 */
+		if (job)
+			processed_jobs += completed_jobs_handle(
+						qp,
+						job,
+						(struct rte_multi_fn_op **)
+							&ops[processed_jobs],
+						nb_ops - processed_jobs);
+
+	} while (processed_jobs < nb_ops);
+
+	qp->output_idx = output_idx;
+
+	if (processed_jobs < 1)
+		processed_jobs += mb_mgr_flush(qp,
+					       (struct rte_multi_fn_op **)
+							&ops[processed_jobs],
+					       nb_ops - processed_jobs);
+
+	return processed_jobs;
+}
+
+static int
+aesni_mb_mfn_pmd_xstats_get(const struct rte_rawdev *rawdev,
+			    const unsigned int ids[],
+			    uint64_t values[],
+			    unsigned int n)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct aesni_mb_mfn_qp *qp;
+	struct aesni_mb_mfn_stats stats = {0};
+	int qp_id;
+	unsigned int i;
+
+	for (qp_id = 0; qp_id < aesni_mb_mfn_dev->nb_queue_pairs; qp_id++) {
+		qp = aesni_mb_mfn_dev->queue_pairs[qp_id];
+
+		stats.enqueued_count += qp->stats.enqueued_count;
+		stats.dequeued_count += qp->stats.dequeued_count;
+
+		stats.enqueue_err_count += qp->stats.enqueue_err_count;
+		stats.dequeue_err_count += qp->stats.dequeue_err_count;
+	}
+
+	for (i = 0; i < n; i++) {
+		switch (ids[i]) {
+		case RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_ENQUEUES:
+			values[i] = stats.enqueued_count;
+			break;
+		case RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_DEQUEUES:
+			values[i] = stats.dequeued_count;
+			break;
+		case RTE_MULTI_FN_XSTAT_ID_FAILED_ENQUEUES:
+			values[i] = stats.enqueue_err_count;
+			break;
+		case RTE_MULTI_FN_XSTAT_ID_FAILED_DEQUEUES:
+			values[i] = stats.dequeue_err_count;
+			break;
+		default:
+			values[i] = 0;
+			break;
+		}
+	}
+
+	return n;
+}
+
+static int
+aesni_mb_mfn_pmd_xstats_get_names(__rte_unused const struct rte_rawdev *rawdev,
+				  struct rte_rawdev_xstats_name *names,
+				  unsigned int size)
+{
+	unsigned int i;
+
+	if (size < RTE_MULTI_FN_XSTAT_ID_NB)
+		return RTE_MULTI_FN_XSTAT_ID_NB;
+
+	for (i = 0; i < RTE_MULTI_FN_XSTAT_ID_NB; i++)
+		strlcpy(names[i].name,
+			rte_multi_fn_xstat_names[i],
+			sizeof(names[i]));
+
+	return RTE_MULTI_FN_XSTAT_ID_NB;
+}
+
+static int
+aesni_mb_mfn_pmd_xstats_reset(struct rte_rawdev *rawdev,
+			      const uint32_t *ids,
+			      uint32_t nb_ids)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct aesni_mb_mfn_qp *qp;
+	uint16_t nb_qps = aesni_mb_mfn_dev->nb_queue_pairs, qp_id;
+	unsigned int i;
+
+	if (!ids) {
+		for (qp_id = 0; qp_id < nb_qps; qp_id++) {
+			qp = aesni_mb_mfn_dev->queue_pairs[qp_id];
+			qp->stats.enqueued_count = 0;
+			qp->stats.dequeued_count = 0;
+			qp->stats.enqueue_err_count = 0;
+			qp->stats.dequeue_err_count = 0;
+		}
+
+		return 0;
+	}
+
+	for (i = 0; i < nb_ids; i++) {
+		switch (ids[i]) {
+		case RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_ENQUEUES:
+			for (qp_id = 0; qp_id < nb_qps; qp_id++) {
+				qp = aesni_mb_mfn_dev->queue_pairs[qp_id];
+				qp->stats.enqueued_count = 0;
+			}
+			break;
+		case RTE_MULTI_FN_XSTAT_ID_SUCCESSFUL_DEQUEUES:
+			for (qp_id = 0; qp_id < nb_qps; qp_id++) {
+				qp = aesni_mb_mfn_dev->queue_pairs[qp_id];
+				qp->stats.dequeued_count = 0;
+			}
+			break;
+		case RTE_MULTI_FN_XSTAT_ID_FAILED_ENQUEUES:
+			for (qp_id = 0; qp_id < nb_qps; qp_id++) {
+				qp = aesni_mb_mfn_dev->queue_pairs[qp_id];
+				qp->stats.enqueue_err_count = 0;
+			}
+			break;
+		case RTE_MULTI_FN_XSTAT_ID_FAILED_DEQUEUES:
+			for (qp_id = 0; qp_id < nb_qps; qp_id++) {
+				qp = aesni_mb_mfn_dev->queue_pairs[qp_id];
+				qp->stats.dequeue_err_count = 0;
+			}
+			break;
+		default:
+			AESNI_MB_MFN_ERR("Invalid xstat id - cannot reset");
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static int
+aesni_mb_mfn_pmd_selftest(uint16_t dev_id)
+{
+	return aesni_mb_mfn_test(dev_id);
+}
+
+static struct rte_multi_fn_session *
+aesni_mb_mfn_pmd_session_create(struct rte_rawdev *rawdev,
+				struct rte_multi_fn_xform *xform,
+				int socket_id)
+{
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev = rawdev->dev_private;
+	struct aesni_mb_mfn_session *aesni_sess = NULL;
+	struct rte_multi_fn_session *session;
+	struct rte_crypto_sym_xform *cipher_xform;
+	enum aesni_mb_mfn_op op;
+	char name[RTE_MEMZONE_NAMESIZE];
+	int ret;
+
+	op = session_support_check(xform);
+
+	/* Allocate Multi-Function session */
+	session = rte_zmalloc_socket("multi_fn_session",
+				     sizeof(struct rte_multi_fn_session),
+				     RTE_CACHE_LINE_MIN_SIZE,
+				     socket_id);
+
+	if (session == NULL) {
+		AESNI_MB_MFN_ERR("Multi-function session allocation failed");
+		return NULL;
+	}
+
+	/* Allocate AESNI-MB Multi-Function session */
+	snprintf(name, sizeof(name), "%s_session", driver_name);
+	aesni_sess = rte_zmalloc_socket(
+				name,
+				sizeof(struct aesni_mb_mfn_session),
+				RTE_CACHE_LINE_MIN_SIZE,
+				socket_id);
+
+	if (aesni_sess == NULL) {
+		AESNI_MB_MFN_ERR("AESNI-MB multi-function session allocation "
+				 "failed");
+		return NULL;
+	}
+
+	session->sess_private_data = aesni_sess;
+	aesni_sess->op = op;
+
+	switch (op) {
+	case AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO:
+	case AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP:
+		aesni_sess->chain_order = IMB_ORDER_HASH_CIPHER;
+		cipher_xform = &xform->next->crypto_sym;
+		break;
+	case AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC:
+		aesni_sess->chain_order = IMB_ORDER_CIPHER_HASH;
+		cipher_xform = &xform->crypto_sym;
+		break;
+	case AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC:
+		aesni_sess->chain_order = IMB_ORDER_CIPHER_HASH;
+		cipher_xform = &xform->next->crypto_sym;
+		break;
+	default:
+		AESNI_MB_MFN_ERR("Unsupported multi-function xform chain");
+		return NULL;
+	}
+
+	ret = session_err_detect_parameters_set(aesni_sess);
+
+	if (ret != 0) {
+		AESNI_MB_MFN_ERR("Invalid/unsupported error detect parameters");
+		return NULL;
+	}
+
+	ret = session_cipher_parameters_set(aesni_mb_mfn_dev->mb_mgr,
+					    aesni_sess,
+					    cipher_xform);
+
+	if (ret != 0) {
+		AESNI_MB_MFN_ERR("Invalid/unsupported cipher parameters");
+		return NULL;
+	}
+
+	return session;
+}
+
+static int
+aesni_mb_mfn_pmd_session_destroy(__rte_unused struct rte_rawdev *rawdev,
+				 struct rte_multi_fn_session *sess)
+{
+
+	if (sess) {
+		if (sess->sess_private_data)
+			rte_free(sess->sess_private_data);
+		rte_free(sess);
+	}
+
+	return 0;
+}
+
+static const struct rte_rawdev_ops aesni_mb_mfn_ops = {
+	.dev_configure = aesni_mb_mfn_pmd_config,
+	.dev_info_get = aesni_mb_mfn_pmd_info_get,
+	.dev_start = aesni_mb_mfn_pmd_start,
+	.dev_stop = aesni_mb_mfn_pmd_stop,
+	.dev_close = aesni_mb_mfn_pmd_close,
+	.queue_setup = aesni_mb_mfn_pmd_qp_setup,
+	.queue_release = aesni_mb_mfn_pmd_qp_release,
+	.queue_count = aesni_mb_mfn_pmd_qp_count,
+	.enqueue_bufs = aesni_mb_mfn_pmd_enq,
+	.dequeue_bufs = aesni_mb_mfn_pmd_deq,
+	.xstats_get = aesni_mb_mfn_pmd_xstats_get,
+	.xstats_get_names = aesni_mb_mfn_pmd_xstats_get_names,
+	.xstats_reset = aesni_mb_mfn_pmd_xstats_reset,
+	.dev_selftest = aesni_mb_mfn_pmd_selftest,
+};
+
+static const struct rte_multi_fn_ops mf_ops = {
+	.session_create = aesni_mb_mfn_pmd_session_create,
+	.session_destroy = aesni_mb_mfn_pmd_session_destroy,
+};
+
+static int
+aesni_mb_mfn_create(const char *name,
+		    struct rte_vdev_device *vdev,
+		    unsigned int socket_id)
+{
+	struct rte_rawdev *rawdev;
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev;
+	enum aesni_mb_mfn_vector_mode vector_mode;
+	MB_MGR *mb_mgr;
+
+	/* Allocate device structure */
+	rawdev = rte_rawdev_pmd_allocate(name,
+					 sizeof(struct aesni_mb_mfn_rawdev),
+					 socket_id);
+	if (!rawdev) {
+		AESNI_MB_MFN_ERR("Unable to allocate raw device");
+		return -EINVAL;
+	}
+
+	rawdev->dev_ops = &aesni_mb_mfn_ops;
+	rawdev->device = &vdev->device;
+	rawdev->driver_name = driver_name;
+
+	/* Check CPU for supported vector instruction set */
+	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F))
+		vector_mode = AESNI_MB_MFN_AVX512;
+	else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX2))
+		vector_mode = AESNI_MB_MFN_AVX2;
+	else if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX))
+		vector_mode = AESNI_MB_MFN_AVX;
+	else
+		vector_mode = AESNI_MB_MFN_SSE;
+
+	/* Check CPU for support for AES instruction set */
+	if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_AES))
+		AESNI_MB_MFN_WARN("AES instructions not supported by CPU");
+
+	mb_mgr = alloc_mb_mgr(0);
+
+	if (mb_mgr == NULL)
+		return -ENOMEM;
+
+	switch (vector_mode) {
+	case AESNI_MB_MFN_SSE:
+		init_mb_mgr_sse(mb_mgr);
+		break;
+	case AESNI_MB_MFN_AVX:
+		init_mb_mgr_avx(mb_mgr);
+		break;
+	case AESNI_MB_MFN_AVX2:
+		init_mb_mgr_avx2(mb_mgr);
+		break;
+	case AESNI_MB_MFN_AVX512:
+		init_mb_mgr_avx512(mb_mgr);
+		break;
+	default:
+		AESNI_MB_MFN_ERR("Unsupported vector mode %u", vector_mode);
+		free_mb_mgr(mb_mgr);
+		mb_mgr = NULL;
+		break;
+	}
+
+	if (mb_mgr == NULL) {
+		rte_rawdev_pmd_release(rawdev);
+		return -1;
+	}
+
+	/* Set the device's private data */
+	aesni_mb_mfn_dev = rawdev->dev_private;
+	aesni_mb_mfn_dev->mf_ops = &mf_ops;
+	aesni_mb_mfn_dev->vector_mode = vector_mode;
+	aesni_mb_mfn_dev->max_nb_queue_pairs = MAX_QUEUES;
+	aesni_mb_mfn_dev->mb_mgr = mb_mgr;
+
+	AESNI_MB_MFN_INFO("IPSec Multi-buffer library version used: %s",
+			  imb_get_version_str());
+
+	return 0;
+}
+
+static int
+aesni_mb_mfn_destroy(const char *name)
+{
+	struct rte_rawdev *rawdev;
+	struct aesni_mb_mfn_rawdev *aesni_mb_mfn_dev;
+	int ret;
+
+	rawdev = rte_rawdev_pmd_get_named_dev(name);
+	if (rawdev == NULL) {
+		AESNI_MB_MFN_ERR("Invalid device name (%s)", name);
+		return -EINVAL;
+	}
+
+	aesni_mb_mfn_dev = rawdev->dev_private;
+	free_mb_mgr(aesni_mb_mfn_dev->mb_mgr);
+
+	ret = rte_rawdev_pmd_release(rawdev);
+	if (ret)
+		AESNI_MB_MFN_DEBUG("Device cleanup failed");
+
+	return 0;
+}
+
+static int
+aesni_mb_mfn_probe(struct rte_vdev_device *vdev)
+{
+	const char *name;
+
+	name = rte_vdev_device_name(vdev);
+	if (name == NULL)
+		return -EINVAL;
+
+	AESNI_MB_MFN_INFO("Init %s on NUMA node %d", name, rte_socket_id());
+
+	return aesni_mb_mfn_create(name, vdev, rte_socket_id());
+}
+
+static int
+aesni_mb_mfn_remove(struct rte_vdev_device *vdev)
+{
+	const char *name;
+
+	name = rte_vdev_device_name(vdev);
+	if (name == NULL)
+		return -1;
+
+	AESNI_MB_MFN_INFO("Closing %s on NUMA node %d", name, rte_socket_id());
+
+	return aesni_mb_mfn_destroy(name);
+}
+
+static struct rte_vdev_driver aesni_mb_mfn_pmd_drv = {
+	.probe = aesni_mb_mfn_probe,
+	.remove = aesni_mb_mfn_remove
+};
+
+RTE_PMD_REGISTER_VDEV(AESNI_MB_MFN_PMD_RAWDEV_NAME, aesni_mb_mfn_pmd_drv);
+
+RTE_INIT(aesni_mb_mfn_raw_init_log)
+{
+	aesni_mb_mfn_logtype = rte_log_register(AESNI_MB_MFN_PMD_LOG_NAME);
+	if (aesni_mb_mfn_logtype >= 0)
+		rte_log_set_level(aesni_mb_mfn_logtype, RTE_LOG_INFO);
+}
diff --git a/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.h b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.h
new file mode 100644
index 000000000..8e0b2e7ea
--- /dev/null
+++ b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#ifndef _AESNI_MB_MFN_RAWDEV_H_
+#define _AESNI_MB_MFN_RAWDEV_H_
+
+#include <intel-ipsec-mb.h>
+
+#include <rte_multi_fn.h>
+#include <rte_multi_fn_driver.h>
+
+/* AESNI-MB Multi-Function Rawdev PMD logtype */
+int aesni_mb_mfn_logtype;
+
+/* Name of the device driver */
+#define AESNI_MB_MFN_PMD_RAWDEV_NAME RTE_MULTI_FN_DEV_NAME(aesni_mb)
+/* String reported as the device driver name by rte_rawdev_info_get() */
+#define AESNI_MB_MFN_PMD_RAWDEV_NAME_STR RTE_STR(AESNI_MB_MFN_PMD_RAWDEV_NAME)
+/* Name used to adjust the log level for this driver */
+#define AESNI_MB_MFN_PMD_LOG_NAME "rawdev.aesni_mb_mfn"
+
+#define AESNI_MB_MFN_LOG(level, fmt, args...)  \
+	rte_log(RTE_LOG_ ## level, aesni_mb_mfn_logtype,  \
+		"%s() line %u: " fmt "\n", \
+		__func__, __LINE__, ##args)
+#define AESNI_MB_MFN_DEBUG(fmt, args...) \
+	AESNI_MB_MFN_LOG(DEBUG, fmt, ## args)
+#define AESNI_MB_MFN_INFO(fmt, args...) \
+	AESNI_MB_MFN_LOG(INFO, fmt, ## args)
+#define AESNI_MB_MFN_ERR(fmt, args...) \
+	AESNI_MB_MFN_LOG(ERR, fmt, ## args)
+#define AESNI_MB_MFN_WARN(fmt, args...) \
+	AESNI_MB_MFN_LOG(WARNING, fmt, ## args)
+
+/* Maximum length for output */
+#define OUTPUT_LENGTH_MAX 8
+
+/* AESNI-MB Multi-Function supported operations */
+enum aesni_mb_mfn_op {
+	AESNI_MB_MFN_OP_DOCSIS_CRC_CRYPTO,   /* DOCSIS encrypt */
+	AESNI_MB_MFN_OP_DOCSIS_CRYPTO_CRC,   /* DOCSIS decrypt */
+	AESNI_MB_MFN_OP_GPON_CRC_CRYPTO_BIP, /* GPON encrypt */
+	AESNI_MB_MFN_OP_GPON_BIP_CRYPTO_CRC, /* GPON decrypt */
+	AESNI_MB_MFN_OP_NOT_SUPPORTED
+};
+
+/* AESNI-MB Multi-Function device statistics */
+struct aesni_mb_mfn_stats {
+	uint64_t enqueued_count;
+	uint64_t dequeued_count;
+	uint64_t enqueue_err_count;
+	uint64_t dequeue_err_count;
+};
+
+/* AESNI-MB Multi-Function queue pair */
+struct aesni_mb_mfn_qp {
+	uint16_t id;
+	char name[RTE_RAWDEV_NAME_MAX_LEN];
+	MB_MGR *mb_mgr;
+	struct rte_ring *ingress_queue;
+	struct aesni_mb_mfn_stats stats;
+	uint8_t output_idx;
+	uint8_t temp_outputs[MAX_JOBS][OUTPUT_LENGTH_MAX];
+} __rte_cache_aligned;
+
+/* AESNI-MB Multi-Function vector modes */
+enum aesni_mb_mfn_vector_mode {
+	AESNI_MB_MFN_NOT_SUPPORTED = 0,
+	AESNI_MB_MFN_SSE,
+	AESNI_MB_MFN_AVX,
+	AESNI_MB_MFN_AVX2,
+	AESNI_MB_MFN_AVX512
+};
+
+/* AESNI-MB Multi-Function device data */
+struct aesni_mb_mfn_rawdev {
+	const struct rte_multi_fn_ops *mf_ops; /* MUST be first */
+	MB_MGR *mb_mgr;
+	struct aesni_mb_mfn_qp **queue_pairs;
+	enum aesni_mb_mfn_vector_mode vector_mode;
+	uint16_t max_nb_queue_pairs;
+	uint16_t nb_queue_pairs;
+};
+
+/* AESNI-MB Multi-Function private session structure */
+struct aesni_mb_mfn_session {
+	enum aesni_mb_mfn_op op;
+	JOB_CHAIN_ORDER chain_order;
+	struct {
+		uint16_t length;
+		uint16_t offset;
+	} iv;
+	struct {
+		JOB_CIPHER_DIRECTION direction;
+		JOB_CIPHER_MODE mode;
+
+		uint64_t key_length_in_bytes;
+
+		union {
+			struct {
+				uint32_t encode[60] __rte_aligned(16);
+				uint32_t decode[60] __rte_aligned(16);
+			} expanded_aes_keys;
+		};
+	} cipher;
+	struct {
+		JOB_HASH_ALG algo;
+		enum rte_multi_fn_err_detect_operation operation;
+		uint16_t gen_output_len;
+
+	} err_detect;
+} __rte_cache_aligned;
+
+int
+aesni_mb_mfn_test(uint16_t dev_id);
+
+#endif /* _AESNI_MB_MFN_RAWDEV_H_ */
diff --git a/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test.c b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test.c
new file mode 100644
index 000000000..f74de508f
--- /dev/null
+++ b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test.c
@@ -0,0 +1,1123 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#include <rte_common.h>
+#include <rte_mbuf.h>
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_bus_vdev.h>
+#include <rte_rawdev.h>
+#include <rte_multi_fn.h>
+#include <rte_ether.h>
+#include <rte_test.h>
+
+#include "aesni_mb_mfn_rawdev.h"
+#include "aesni_mb_mfn_rawdev_test_vectors.h"
+
+#define TEST(setup, teardown, run, data, suffix) \
+	test_run(setup, teardown, run, data, RTE_STR(run)"_"suffix)
+
+#define TEST_SUCCESS (0)
+#define TEST_FAILED  (-1)
+
+#define QP_NB_DESC (4096)
+
+#define MBUF_POOL_NAME        "aesni_mb_mfn_mbuf_pool"
+#define MBUF_POOL_SIZE        (8191)
+#define MBUF_CACHE_SIZE       (256)
+#define MBUF_DATAPAYLOAD_SIZE (2048)
+#define MBUF_SIZE             (sizeof(struct rte_mbuf) + \
+				RTE_PKTMBUF_HEADROOM + MBUF_DATAPAYLOAD_SIZE)
+
+#define OP_POOL_NAME  "aesni_mb_mfn_op_pool"
+#define OP_POOL_SIZE  (8191)
+#define OP_PRIV_SIZE  (16)
+#define OP_CACHE_SIZE (256)
+
+#define MAX_OPS (3)
+
+static int eal_log_level;
+
+struct testsuite_params {
+	uint16_t dev_id;
+	struct rte_mempool *mbuf_pool;
+	struct rte_mempool *op_pool;
+};
+
+struct unittest_params {
+	struct rte_multi_fn_session *sess;
+	struct rte_multi_fn_op *ops[MAX_OPS];
+	struct rte_mbuf *ibuf;
+	struct rte_mbuf *obuf;
+};
+
+static struct testsuite_params testsuite_params;
+static struct unittest_params unittest_params;
+
+static int total;
+static int passed;
+static int failed;
+static int unsupported;
+
+static int
+testsuite_setup(uint16_t dev_id)
+{
+	struct testsuite_params *ts_params = &testsuite_params;
+	uint8_t count = rte_rawdev_count();
+
+	eal_log_level = rte_log_get_level(RTE_LOGTYPE_EAL);
+	rte_log_set_level(RTE_LOGTYPE_EAL, RTE_LOG_DEBUG);
+
+	memset(ts_params, 0, sizeof(*ts_params));
+
+	if (!count) {
+		AESNI_MB_MFN_INFO("No existing rawdev found - creating %s",
+				  AESNI_MB_MFN_PMD_RAWDEV_NAME_STR);
+		return rte_vdev_init(AESNI_MB_MFN_PMD_RAWDEV_NAME_STR, NULL);
+	}
+
+	ts_params->dev_id = dev_id;
+
+	ts_params->mbuf_pool = rte_mempool_lookup(MBUF_POOL_NAME);
+	if (ts_params->mbuf_pool == NULL) {
+		/* Not already created so create */
+		ts_params->mbuf_pool = rte_pktmbuf_pool_create(
+						MBUF_POOL_NAME,
+						MBUF_POOL_SIZE,
+						MBUF_CACHE_SIZE,
+						0,
+						MBUF_SIZE,
+						rte_socket_id());
+		if (ts_params->mbuf_pool == NULL) {
+			AESNI_MB_MFN_ERR("Cannot create AESNI-MB "
+					 "Multi-Function rawdev mbuf pool");
+			return TEST_FAILED;
+		}
+	}
+
+	ts_params->op_pool = rte_multi_fn_op_pool_create(OP_POOL_NAME,
+							  OP_POOL_SIZE,
+							  OP_CACHE_SIZE,
+							  OP_PRIV_SIZE,
+							  rte_socket_id());
+
+	if (ts_params->op_pool == NULL) {
+		AESNI_MB_MFN_ERR("Cannot create AESNI-MB Multi-Function "
+				 "rawdev operation pool");
+		return TEST_FAILED;
+	}
+
+	return TEST_SUCCESS;
+}
+
+static void
+testsuite_teardown(void)
+{
+	struct testsuite_params *ts_params = &testsuite_params;
+
+	if (ts_params->mbuf_pool != NULL) {
+		rte_mempool_free(ts_params->mbuf_pool);
+		ts_params->mbuf_pool = NULL;
+	}
+
+	if (ts_params->op_pool != NULL) {
+		rte_mempool_free(ts_params->op_pool);
+		ts_params->op_pool = NULL;
+	}
+
+	rte_vdev_uninit(AESNI_MB_MFN_PMD_RAWDEV_NAME_STR);
+
+	rte_log_set_level(RTE_LOGTYPE_EAL, eal_log_level);
+}
+
+static int
+test_setup(void)
+{
+	struct testsuite_params *ts_params = &testsuite_params;
+	struct unittest_params *ut_params = &unittest_params;
+
+	struct rte_rawdev_info info = {0};
+	struct rte_multi_fn_dev_config mf_dev_conf = {0};
+	struct rte_multi_fn_qp_config qp_conf = {0};
+	uint16_t qp_id;
+	int ret;
+
+	/* Clear unit test parameters before running test */
+	memset(ut_params, 0, sizeof(*ut_params));
+
+	/* Configure device and queue pairs */
+	mf_dev_conf.nb_queues = 1;
+	info.dev_private = &mf_dev_conf;
+	qp_conf.nb_descriptors = QP_NB_DESC;
+
+	ret = rte_rawdev_configure(ts_params->dev_id, &info);
+	RTE_TEST_ASSERT_SUCCESS(ret,
+				"Failed to configure rawdev %u",
+				ts_params->dev_id);
+
+	for (qp_id = 0; qp_id < mf_dev_conf.nb_queues; qp_id++) {
+		ret = rte_rawdev_queue_setup(ts_params->dev_id,
+					     qp_id,
+					     &qp_conf);
+		RTE_TEST_ASSERT_SUCCESS(ret,
+					"Failed to setup queue pair %u on "
+					"rawdev %u",
+					qp_id,
+					ts_params->dev_id);
+	}
+
+	ret = rte_rawdev_xstats_reset(ts_params->dev_id, NULL, 0);
+	RTE_TEST_ASSERT_SUCCESS(ret,
+				"Failed to reset stats on rawdev %u",
+				ts_params->dev_id);
+
+	/* Start the device */
+	ret = rte_rawdev_start(ts_params->dev_id);
+	RTE_TEST_ASSERT_SUCCESS(ret,
+				"Failed to start rawdev %u",
+				ts_params->dev_id);
+
+	return 0;
+}
+
+static void
+test_teardown(void)
+{
+	struct testsuite_params *ts_params = &testsuite_params;
+	struct unittest_params *ut_params = &unittest_params;
+
+	int i;
+
+	/* Free multi-function operations */
+	for (i = 0; i < MAX_OPS; i++) {
+		if (ut_params->ops[i] != NULL) {
+			rte_multi_fn_op_free(ut_params->ops[i]);
+			ut_params->ops[i] = NULL;
+		}
+	}
+
+	/* Free multi-function session */
+	if (ut_params->sess != NULL) {
+		rte_multi_fn_session_destroy(ts_params->dev_id,
+					     ut_params->sess);
+		ut_params->sess = NULL;
+	}
+
+	/*
+	 * Free mbuf - both obuf and ibuf are usually the same,
+	 * so check if they point at the same address is necessary,
+	 * to avoid freeing the mbuf twice.
+	 */
+	if (ut_params->obuf != NULL) {
+		rte_pktmbuf_free(ut_params->obuf);
+		if (ut_params->ibuf == ut_params->obuf)
+			ut_params->ibuf = NULL;
+		ut_params->obuf = NULL;
+	}
+	if (ut_params->ibuf != NULL) {
+		rte_pktmbuf_free(ut_params->ibuf);
+		ut_params->ibuf = NULL;
+	}
+
+	/* Stop the device */
+	rte_rawdev_stop(ts_params->dev_id);
+}
+
+static int
+test_docsis_encrypt(void *vtdata)
+{
+	struct docsis_test_data *tdata = (struct docsis_test_data *)vtdata;
+	struct testsuite_params *ts_params = &testsuite_params;
+	struct unittest_params *ut_params = &unittest_params;
+
+	/* Xforms */
+	struct rte_multi_fn_xform xform1 = {0};
+	struct rte_multi_fn_xform xform2 = {0};
+	struct rte_crypto_cipher_xform *xform_cipher;
+
+	/* Operations */
+	struct rte_multi_fn_op *result;
+	struct rte_crypto_sym_op *cipher_op;
+	struct rte_multi_fn_err_detect_op *crc_op;
+
+	/* Cipher params */
+	int cipher_len = 0;
+	uint8_t *iv_ptr;
+
+	/* CRC params */
+	int crc_len = 0, crc_data_len = 0;
+
+	/* Test data */
+	uint8_t *plaintext = NULL, *ciphertext = NULL;
+
+	/* Stats */
+	uint64_t stats[RTE_MULTI_FN_XSTAT_ID_NB] = {0};
+	struct rte_rawdev_xstats_name stats_names[RTE_MULTI_FN_XSTAT_ID_NB];
+	const unsigned int stats_id[RTE_MULTI_FN_XSTAT_ID_NB] = {0, 1, 2, 3};
+	int num_stats = 0, num_names = 0;
+
+	uint16_t qp_id = 0, nb_enq, nb_deq = 0, nb_ops;
+	int i, ret = TEST_SUCCESS;
+
+	memset(stats_names, 0, sizeof(stats_names));
+
+	/* Setup source mbuf */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	RTE_TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+				 "Failed to allocate source mbuf");
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *),
+	       0,
+	       rte_pktmbuf_tailroom(ut_params->ibuf));
+	plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+						  tdata->plaintext.len);
+	memcpy(plaintext, tdata->plaintext.data, tdata->plaintext.len);
+
+	/* Create session */
+	xform1.type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+	xform1.err_detect.algo = RTE_MULTI_FN_ERR_DETECT_CRC32_ETH;
+	xform1.err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_GENERATE;
+	xform1.next = &xform2;
+
+	xform2.type = RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM;
+	xform2.crypto_sym.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	xform_cipher = &xform2.crypto_sym.cipher;
+	xform_cipher->op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+	xform_cipher->algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	xform_cipher->key.data = tdata->key.data;
+	xform_cipher->key.length = tdata->key.len;
+	xform_cipher->iv.offset = sizeof(struct rte_multi_fn_op);
+	xform_cipher->iv.length = tdata->cipher_iv.len;
+	xform2.next = NULL;
+
+	ut_params->sess = rte_multi_fn_session_create(ts_params->dev_id,
+						      &xform1,
+						      rte_socket_id());
+
+	RTE_TEST_ASSERT((ut_params->sess != NULL &&
+			 ut_params->sess->sess_private_data != NULL),
+			"Failed to create multi-function session");
+
+	/* Create operations */
+	nb_ops = rte_multi_fn_op_bulk_alloc(ts_params->op_pool,
+					    ut_params->ops,
+					    2);
+	RTE_TEST_ASSERT_EQUAL(nb_ops,
+			      2,
+			      "Failed to allocate multi-function operations");
+
+	ut_params->ops[0]->next = ut_params->ops[1];
+	ut_params->ops[0]->m_src = ut_params->ibuf;
+	ut_params->ops[0]->m_dst = NULL;
+	ut_params->ops[1]->next = NULL;
+
+	/* CRC op config */
+	crc_len = tdata->plaintext.no_crc == false ?
+					(tdata->plaintext.len -
+					 tdata->plaintext.crc_offset -
+					 RTE_ETHER_CRC_LEN) :
+					0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	crc_data_len = crc_len == 0 ? 0 : RTE_ETHER_CRC_LEN;
+	crc_op = &ut_params->ops[0]->err_detect;
+	crc_op->data.offset = tdata->plaintext.crc_offset;
+	crc_op->data.length = crc_len;
+	crc_op->output.data = rte_pktmbuf_mtod_offset(
+						ut_params->ibuf,
+						uint8_t *,
+						ut_params->ibuf->data_len -
+							crc_data_len);
+
+	/* Cipher encrypt op config */
+	cipher_len = tdata->plaintext.no_cipher == false ?
+					(tdata->plaintext.len -
+					 tdata->plaintext.cipher_offset) :
+					0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	cipher_op = &ut_params->ops[1]->crypto_sym;
+	cipher_op->cipher.data.offset = tdata->plaintext.cipher_offset;
+	cipher_op->cipher.data.length = cipher_len;
+	iv_ptr = (uint8_t *)(ut_params->ops[1]) +
+				sizeof(struct rte_multi_fn_op);
+	rte_memcpy(iv_ptr, tdata->cipher_iv.data, tdata->cipher_iv.len);
+
+	/* Attach session to operation */
+	ut_params->ops[0]->sess = ut_params->sess;
+
+	/* Enqueue to device */
+	nb_enq = rte_rawdev_enqueue_buffers(
+				ts_params->dev_id,
+				(struct rte_rawdev_buf **)ut_params->ops,
+				1,
+				(rte_rawdev_obj_t)&qp_id);
+
+	RTE_TEST_ASSERT_EQUAL(nb_enq,
+			      1,
+			      "Failed to enqueue multi-function operations");
+
+	/* Dequeue from device */
+	do {
+		nb_deq = rte_rawdev_dequeue_buffers(
+					ts_params->dev_id,
+					(struct rte_rawdev_buf **)&result,
+					1,
+					(rte_rawdev_obj_t)&qp_id);
+	} while (nb_deq < 1);
+
+	RTE_TEST_ASSERT_EQUAL(nb_deq,
+			      1,
+			      "Failed to dequeue multi-function operations");
+
+	/* Check results */
+	ciphertext = plaintext;
+
+	/* Validate ciphertext */
+	ret = memcmp(ciphertext, tdata->ciphertext.data, tdata->ciphertext.len);
+	RTE_TEST_ASSERT_SUCCESS(ret, "Ciphertext not as expected");
+
+	RTE_TEST_ASSERT_EQUAL(result->overall_status,
+			      RTE_MULTI_FN_OP_STATUS_SUCCESS,
+			      "Multi-function op processing failed");
+
+	/* Print stats */
+	num_stats = rte_rawdev_xstats_get(ts_params->dev_id,
+					  stats_id,
+					  stats,
+					  RTE_MULTI_FN_XSTAT_ID_NB);
+	num_names = rte_rawdev_xstats_names_get(ts_params->dev_id,
+						stats_names,
+						RTE_MULTI_FN_XSTAT_ID_NB);
+	RTE_TEST_ASSERT_EQUAL(num_stats,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats");
+	RTE_TEST_ASSERT_EQUAL(num_names,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats names");
+
+	for (i = 0; i < num_stats; i++)
+		AESNI_MB_MFN_DEBUG("%s:  %"PRIu64,
+				   stats_names[i].name,
+				   stats[i]);
+
+	return 0;
+}
+
+static int
+test_docsis_decrypt(void *vtdata)
+{
+	struct docsis_test_data *tdata = (struct docsis_test_data *)vtdata;
+	struct testsuite_params *ts_params = &testsuite_params;
+	struct unittest_params *ut_params = &unittest_params;
+
+	/* Xforms */
+	struct rte_multi_fn_xform xform1 = {0};
+	struct rte_multi_fn_xform xform2 = {0};
+	struct rte_crypto_cipher_xform *xform_cipher;
+
+	/* Operations */
+	struct rte_multi_fn_op *result;
+	struct rte_crypto_sym_op *cipher_op;
+	struct rte_multi_fn_err_detect_op *crc_op;
+
+	/* Cipher params */
+	int cipher_len = 0;
+	uint8_t *iv_ptr;
+
+	/* CRC params */
+	int crc_len = 0, crc_data_len;
+
+	/* Test data */
+	uint8_t *plaintext = NULL, *ciphertext = NULL;
+
+	/* Stats */
+	uint64_t stats[RTE_MULTI_FN_XSTAT_ID_NB] = {0};
+	struct rte_rawdev_xstats_name stats_names[RTE_MULTI_FN_XSTAT_ID_NB];
+	const unsigned int stats_id[RTE_MULTI_FN_XSTAT_ID_NB] = {0, 1, 2, 3};
+	int num_stats = 0, num_names = 0;
+
+	uint16_t qp_id = 0, nb_enq, nb_deq = 0, nb_ops;
+	int i, ret = TEST_SUCCESS;
+
+	memset(stats_names, 0, sizeof(stats_names));
+
+	/* Setup source mbuf */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	RTE_TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+				 "Failed to allocate source mbuf");
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *),
+	       0,
+	       rte_pktmbuf_tailroom(ut_params->ibuf));
+	ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+						   tdata->ciphertext.len);
+	memcpy(ciphertext, tdata->ciphertext.data, tdata->ciphertext.len);
+
+	/* Create session */
+	xform1.type = RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM;
+	xform1.crypto_sym.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	xform_cipher = &xform1.crypto_sym.cipher;
+	xform_cipher->op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	xform_cipher->algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	xform_cipher->key.data = tdata->key.data;
+	xform_cipher->key.length = tdata->key.len;
+	xform_cipher->iv.offset = sizeof(struct rte_multi_fn_op);
+	xform_cipher->iv.length = tdata->cipher_iv.len;
+	xform1.next = &xform2;
+
+	xform2.type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+	xform2.err_detect.algo = RTE_MULTI_FN_ERR_DETECT_CRC32_ETH;
+	xform2.err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_VERIFY;
+	xform2.next = NULL;
+
+	ut_params->sess = rte_multi_fn_session_create(ts_params->dev_id,
+						      &xform1,
+						      rte_socket_id());
+
+	RTE_TEST_ASSERT((ut_params->sess != NULL &&
+			 ut_params->sess->sess_private_data != NULL),
+			"Failed to create multi-function session");
+
+	/* Create operations */
+	nb_ops = rte_multi_fn_op_bulk_alloc(ts_params->op_pool,
+					    ut_params->ops,
+					    2);
+	RTE_TEST_ASSERT_EQUAL(nb_ops,
+			      2,
+			      "Failed to allocate multi-function operations");
+
+	ut_params->ops[0]->next = ut_params->ops[1];
+	ut_params->ops[0]->m_src = ut_params->ibuf;
+	ut_params->ops[0]->m_dst = NULL;
+	ut_params->ops[1]->next = NULL;
+
+	/* Cipher decrypt op config */
+	cipher_len = tdata->ciphertext.no_cipher == false ?
+					(tdata->ciphertext.len -
+					 tdata->ciphertext.cipher_offset) :
+					0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	cipher_op = &ut_params->ops[0]->crypto_sym;
+	cipher_op->cipher.data.offset = tdata->ciphertext.cipher_offset;
+	cipher_op->cipher.data.length = cipher_len;
+	iv_ptr = (uint8_t *)(ut_params->ops[1]) +
+				sizeof(struct rte_multi_fn_op);
+	rte_memcpy(iv_ptr, tdata->cipher_iv.data, tdata->cipher_iv.len);
+
+	/* CRC op config */
+	crc_len = tdata->plaintext.no_crc == false ?
+					(tdata->ciphertext.len -
+					 tdata->ciphertext.crc_offset -
+					 RTE_ETHER_CRC_LEN) :
+					0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	crc_data_len = crc_len == 0 ? 0 : RTE_ETHER_CRC_LEN;
+	crc_op = &ut_params->ops[1]->err_detect;
+	crc_op->data.offset = tdata->ciphertext.crc_offset;
+	crc_op->data.length = crc_len;
+	crc_op->output.data = rte_pktmbuf_mtod_offset(
+						ut_params->ibuf,
+						uint8_t *,
+						ut_params->ibuf->data_len -
+							crc_data_len);
+
+	/* Attach session to operation */
+	ut_params->ops[0]->sess = ut_params->sess;
+
+	/* Enqueue to device */
+	nb_enq = rte_rawdev_enqueue_buffers(
+				ts_params->dev_id,
+				(struct rte_rawdev_buf **)ut_params->ops,
+				1,
+				(rte_rawdev_obj_t)&qp_id);
+
+	RTE_TEST_ASSERT_EQUAL(nb_enq,
+			      1,
+			      "Failed to enqueue multi-function operations");
+
+	/* Dequeue to device */
+	do {
+		nb_deq = rte_rawdev_dequeue_buffers(
+					ts_params->dev_id,
+					(struct rte_rawdev_buf **)&result,
+					1,
+					(rte_rawdev_obj_t)&qp_id);
+	} while (nb_deq < 1);
+
+	RTE_TEST_ASSERT_EQUAL(nb_deq,
+			      1,
+			      "Failed to dequeue multi-function operations");
+
+	/* Check results */
+	plaintext = ciphertext;
+
+	/* Validate plaintext */
+	ret = memcmp(plaintext,
+		     tdata->plaintext.data,
+		     /* Check only as far as CRC - CRC is checked internally */
+		     tdata->plaintext.len - crc_data_len);
+	RTE_TEST_ASSERT_SUCCESS(ret, "Plaintext not as expected");
+
+	RTE_TEST_ASSERT_EQUAL(result->overall_status,
+			      RTE_MULTI_FN_OP_STATUS_SUCCESS,
+			      "Multi-function op processing failed");
+
+	/* Print stats */
+	num_stats = rte_rawdev_xstats_get(ts_params->dev_id,
+					  stats_id,
+					  stats,
+					  RTE_MULTI_FN_XSTAT_ID_NB);
+	num_names = rte_rawdev_xstats_names_get(ts_params->dev_id,
+						stats_names,
+						RTE_MULTI_FN_XSTAT_ID_NB);
+	RTE_TEST_ASSERT_EQUAL(num_stats,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats");
+	RTE_TEST_ASSERT_EQUAL(num_names,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats names");
+
+	for (i = 0; i < num_stats; i++)
+		AESNI_MB_MFN_DEBUG("%s:  %"PRIu64,
+				   stats_names[i].name,
+				   stats[i]);
+
+	return 0;
+}
+
+static int
+test_gpon_encrypt(void *vtdata)
+{
+	struct gpon_test_data *tdata = (struct gpon_test_data *)vtdata;
+	struct testsuite_params *ts_params = &testsuite_params;
+	struct unittest_params *ut_params = &unittest_params;
+
+	/* Xforms */
+	struct rte_multi_fn_xform xform1 = {0};
+	struct rte_multi_fn_xform xform2 = {0};
+	struct rte_multi_fn_xform xform3 = {0};
+	struct rte_crypto_cipher_xform *xform_cipher;
+
+	/* Operations */
+	struct rte_multi_fn_op *result;
+	struct rte_crypto_sym_op *cipher_op;
+	struct rte_multi_fn_err_detect_op *crc_op;
+	struct rte_multi_fn_err_detect_op *bip_op;
+
+	/* Cipher params */
+	int cipher_len = 0;
+	uint8_t *iv_ptr;
+
+	/* CRC params */
+	int crc_len = 0, crc_data_len = 0;
+
+	/* BIP params */
+	int bip_len = 0;
+
+	/* Test data */
+	uint8_t *plaintext = NULL, *ciphertext = NULL;
+
+	/* Stats */
+	uint64_t stats[RTE_MULTI_FN_XSTAT_ID_NB] = {0};
+	struct rte_rawdev_xstats_name stats_names[RTE_MULTI_FN_XSTAT_ID_NB];
+	const unsigned int stats_id[RTE_MULTI_FN_XSTAT_ID_NB] = {0, 1, 2, 3};
+	int num_stats = 0, num_names = 0;
+
+	uint16_t qp_id = 0, nb_enq, nb_deq = 0, nb_ops;
+	int i, ret = TEST_SUCCESS;
+
+	memset(stats_names, 0, sizeof(stats_names));
+
+	/* Setup source mbuf */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	RTE_TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+				 "Failed to allocate source mbuf");
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *),
+	       0,
+	       rte_pktmbuf_tailroom(ut_params->ibuf));
+	plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+						  tdata->plaintext.len);
+	memcpy(plaintext, tdata->plaintext.data, tdata->plaintext.len);
+
+	/* Create session */
+	xform1.type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+	xform1.err_detect.algo = RTE_MULTI_FN_ERR_DETECT_CRC32_ETH;
+	xform1.err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_GENERATE;
+	xform1.next = &xform2;
+
+	xform2.type = RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM;
+	xform2.crypto_sym.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	xform_cipher = &xform2.crypto_sym.cipher;
+	xform_cipher->op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+	xform_cipher->algo = RTE_CRYPTO_CIPHER_AES_CTR;
+	xform_cipher->key.data = tdata->key.data;
+	xform_cipher->key.length = tdata->key.len;
+	xform_cipher->iv.offset = sizeof(struct rte_multi_fn_op);
+	xform_cipher->iv.length = tdata->cipher_iv.len;
+	xform2.next = &xform3;
+
+	xform3.type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+	xform3.err_detect.algo = RTE_MULTI_FN_ERR_DETECT_BIP32;
+	xform3.err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_GENERATE;
+	xform3.next = NULL;
+
+	ut_params->sess = rte_multi_fn_session_create(ts_params->dev_id,
+						      &xform1,
+						      rte_socket_id());
+
+	RTE_TEST_ASSERT((ut_params->sess != NULL &&
+			 ut_params->sess->sess_private_data != NULL),
+			"Failed to create multi-function session");
+
+	/* Create operations */
+	nb_ops = rte_multi_fn_op_bulk_alloc(ts_params->op_pool,
+					    ut_params->ops,
+					    3);
+	RTE_TEST_ASSERT_EQUAL(nb_ops,
+			      3,
+			      "Failed to allocate multi-function operations");
+
+	ut_params->ops[0]->next = ut_params->ops[1];
+	ut_params->ops[0]->m_src = ut_params->ibuf;
+	ut_params->ops[0]->m_dst = NULL;
+	ut_params->ops[1]->next = ut_params->ops[2];
+	ut_params->ops[2]->next = NULL;
+
+	/* CRC op config */
+	crc_len = tdata->plaintext.len -
+			tdata->plaintext.crc_offset -
+			tdata->plaintext.padding_len -
+			RTE_ETHER_CRC_LEN;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	crc_data_len = crc_len == 0 ? 0 : RTE_ETHER_CRC_LEN;
+	crc_op = &ut_params->ops[0]->err_detect;
+	crc_op->data.offset = tdata->plaintext.crc_offset;
+	crc_op->data.length = crc_len;
+	crc_op->output.data = rte_pktmbuf_mtod_offset(
+					ut_params->ibuf,
+					uint8_t *,
+					ut_params->ibuf->data_len -
+						tdata->plaintext.padding_len -
+						crc_data_len);
+
+	/* Cipher encrypt op config */
+	cipher_len = tdata->plaintext.no_cipher == false ?
+					(tdata->plaintext.len -
+					 tdata->plaintext.cipher_offset) :
+					0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	cipher_op = &ut_params->ops[1]->crypto_sym;
+	cipher_op->cipher.data.offset = tdata->plaintext.cipher_offset;
+	cipher_op->cipher.data.length = cipher_len;
+	iv_ptr = (uint8_t *)(ut_params->ops[1]) +
+				sizeof(struct rte_multi_fn_op);
+	rte_memcpy(iv_ptr, tdata->cipher_iv.data, tdata->cipher_iv.len);
+
+	/* BIP op config */
+	bip_len = tdata->plaintext.len - tdata->plaintext.bip_offset;
+	bip_len = bip_len > 0 ? bip_len : 0;
+	bip_op = &ut_params->ops[2]->err_detect;
+	bip_op->data.offset = tdata->plaintext.bip_offset;
+	bip_op->data.length = bip_len;
+	bip_op->output.data = (uint8_t *)(ut_params->ops[2]) +
+				sizeof(struct rte_multi_fn_op);
+
+	/* Attach session to op */
+	ut_params->ops[0]->sess = ut_params->sess;
+
+	/* Enqueue to device */
+	nb_enq = rte_rawdev_enqueue_buffers(
+				ts_params->dev_id,
+				(struct rte_rawdev_buf **)ut_params->ops,
+				1,
+				(rte_rawdev_obj_t)&qp_id);
+
+	RTE_TEST_ASSERT_EQUAL(nb_enq,
+			      1,
+			      "Failed to enqueue multi-function operations");
+
+	/* Dequeue from device */
+	do {
+		nb_deq = rte_rawdev_dequeue_buffers(
+					ts_params->dev_id,
+					(struct rte_rawdev_buf **)&result,
+					1,
+					(rte_rawdev_obj_t)&qp_id);
+	} while (nb_deq < 1);
+
+	/* Check results */
+	ciphertext = plaintext;
+
+	/* Validate ciphertext */
+	ret = memcmp(ciphertext, tdata->ciphertext.data, tdata->ciphertext.len);
+	RTE_TEST_ASSERT_SUCCESS(ret, "Ciphertext not as expected");
+
+	ret = memcmp(bip_op->output.data,
+		     tdata->output.data,
+		     tdata->output.len);
+	RTE_TEST_ASSERT_SUCCESS(ret, "BIP not as expected");
+
+	RTE_TEST_ASSERT_EQUAL(result->overall_status,
+			      RTE_MULTI_FN_OP_STATUS_SUCCESS,
+			      "Multi-function op processing failed");
+
+	/* Print stats */
+	num_stats = rte_rawdev_xstats_get(ts_params->dev_id,
+					  stats_id,
+					  stats,
+					  RTE_MULTI_FN_XSTAT_ID_NB);
+	num_names = rte_rawdev_xstats_names_get(ts_params->dev_id,
+						stats_names,
+						RTE_MULTI_FN_XSTAT_ID_NB);
+	RTE_TEST_ASSERT_EQUAL(num_stats,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats");
+	RTE_TEST_ASSERT_EQUAL(num_names,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats names");
+
+	for (i = 0; i < num_stats; i++)
+		AESNI_MB_MFN_DEBUG("%s:  %"PRIu64,
+				   stats_names[i].name,
+				   stats[i]);
+
+	return 0;
+}
+
+static int
+test_gpon_decrypt(void *vtdata)
+{
+	struct gpon_test_data *tdata = (struct gpon_test_data *)vtdata;
+	struct testsuite_params *ts_params = &testsuite_params;
+	struct unittest_params *ut_params = &unittest_params;
+
+	/* Xforms */
+	struct rte_multi_fn_xform xform1 = {0};
+	struct rte_multi_fn_xform xform2 = {0};
+	struct rte_multi_fn_xform xform3 = {0};
+	struct rte_crypto_cipher_xform *xform_cipher;
+
+	/* Operations */
+	struct rte_multi_fn_op *result;
+	struct rte_crypto_sym_op *cipher_op;
+	struct rte_multi_fn_err_detect_op *crc_op;
+	struct rte_multi_fn_err_detect_op *bip_op;
+
+	/* Cipher params */
+	int cipher_len = 0;
+	uint8_t *iv_ptr;
+
+	/* CRC params */
+	int crc_len = 0, crc_data_len = 0;
+
+	/* BIP params */
+	int bip_len = 0;
+
+	/* Test data */
+	uint8_t *plaintext = NULL, *ciphertext = NULL;
+
+	/* Stats */
+	uint64_t stats[RTE_MULTI_FN_XSTAT_ID_NB] = {0};
+	struct rte_rawdev_xstats_name stats_names[RTE_MULTI_FN_XSTAT_ID_NB];
+	const unsigned int stats_id[RTE_MULTI_FN_XSTAT_ID_NB] = {0, 1, 2, 3};
+	int num_stats = 0, num_names = 0;
+
+	uint16_t qp_id = 0, nb_enq, nb_deq = 0, nb_ops;
+	int i, ret = TEST_SUCCESS;
+
+	memset(stats_names, 0, sizeof(stats_names));
+
+	/* Setup source mbuf */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	RTE_TEST_ASSERT_NOT_NULL(ut_params->ibuf,
+				 "Failed to allocate source mbuf");
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *),
+	       0,
+	       rte_pktmbuf_tailroom(ut_params->ibuf));
+	ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+						   tdata->ciphertext.len);
+	memcpy(ciphertext, tdata->ciphertext.data, tdata->ciphertext.len);
+
+	/* Create session */
+	xform1.type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+	xform1.err_detect.algo = RTE_MULTI_FN_ERR_DETECT_BIP32;
+	xform1.err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_GENERATE;
+	xform1.next = &xform2;
+
+	xform2.type = RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM;
+	xform2.crypto_sym.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	xform_cipher = &xform2.crypto_sym.cipher;
+	xform_cipher->op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	xform_cipher->algo = RTE_CRYPTO_CIPHER_AES_CTR;
+	xform_cipher->key.data = tdata->key.data;
+	xform_cipher->key.length = tdata->key.len;
+	xform_cipher->iv.offset = sizeof(struct rte_multi_fn_op);
+	xform_cipher->iv.length = tdata->cipher_iv.len;
+	xform2.next = &xform3;
+
+	xform3.type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+	xform3.err_detect.algo = RTE_MULTI_FN_ERR_DETECT_CRC32_ETH;
+	xform3.err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_VERIFY;
+	xform3.next = NULL;
+
+	ut_params->sess = rte_multi_fn_session_create(ts_params->dev_id,
+						      &xform1,
+						      rte_socket_id());
+
+	RTE_TEST_ASSERT((ut_params->sess != NULL &&
+			 ut_params->sess->sess_private_data != NULL),
+			"Failed to create multi-function session");
+
+	/* Create operations */
+	nb_ops = rte_multi_fn_op_bulk_alloc(ts_params->op_pool,
+					    ut_params->ops,
+					    3);
+	RTE_TEST_ASSERT_EQUAL(nb_ops,
+			      3,
+			      "Failed to allocate multi-function operations");
+
+	ut_params->ops[0]->next = ut_params->ops[1];
+	ut_params->ops[0]->m_src = ut_params->ibuf;
+	ut_params->ops[0]->m_dst = NULL;
+	ut_params->ops[1]->next = ut_params->ops[2];
+	ut_params->ops[2]->next = NULL;
+
+	/* BIP op config */
+	bip_len = tdata->ciphertext.len - tdata->ciphertext.bip_offset;
+	bip_len = bip_len > 0 ? bip_len : 0;
+	bip_op = &ut_params->ops[0]->err_detect;
+	bip_op->data.offset = tdata->ciphertext.bip_offset;
+	bip_op->data.length = bip_len;
+	bip_op->output.data = (uint8_t *)(ut_params->ops[0]) +
+				sizeof(struct rte_multi_fn_op);
+
+	/* Cipher encrypt op config */
+	cipher_len = tdata->ciphertext.no_cipher == false ?
+					(tdata->ciphertext.len -
+					 tdata->ciphertext.cipher_offset) :
+					0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	cipher_op = &ut_params->ops[1]->crypto_sym;
+	cipher_op->cipher.data.offset = tdata->ciphertext.cipher_offset;
+	cipher_op->cipher.data.length = cipher_len;
+	iv_ptr = (uint8_t *)(ut_params->ops[1]) +
+				sizeof(struct rte_multi_fn_op);
+	rte_memcpy(iv_ptr, tdata->cipher_iv.data, tdata->cipher_iv.len);
+
+	/* CRC op config */
+	crc_len = tdata->ciphertext.len -
+			tdata->ciphertext.crc_offset -
+			tdata->ciphertext.padding_len -
+			RTE_ETHER_CRC_LEN;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	crc_data_len = crc_len == 0 ? 0 : RTE_ETHER_CRC_LEN;
+	crc_op = &ut_params->ops[2]->err_detect;
+	crc_op->data.offset = tdata->ciphertext.crc_offset;
+	crc_op->data.length = crc_len;
+	crc_op->output.data = rte_pktmbuf_mtod_offset(
+					ut_params->ibuf,
+					uint8_t *,
+					ut_params->ibuf->data_len -
+						tdata->ciphertext.padding_len -
+						crc_data_len);
+
+	/* Attach session to op */
+	ut_params->ops[0]->sess = ut_params->sess;
+
+	/* Enqueue to device */
+	nb_enq = rte_rawdev_enqueue_buffers(
+				ts_params->dev_id,
+				(struct rte_rawdev_buf **)ut_params->ops,
+				1,
+				(rte_rawdev_obj_t)&qp_id);
+
+	RTE_TEST_ASSERT_EQUAL(nb_enq,
+			      1,
+			      "Failed to enqueue multi-function operations");
+
+	/* Dequeue from device */
+	do {
+		nb_deq = rte_rawdev_dequeue_buffers(
+					ts_params->dev_id,
+					(struct rte_rawdev_buf **)&result,
+					1,
+					(rte_rawdev_obj_t)&qp_id);
+	} while (nb_deq < 1);
+
+	/* Check results */
+	plaintext = ciphertext;
+
+	/* Validate plaintext */
+	ret = memcmp(plaintext,
+		     tdata->plaintext.data,
+		     /* Check only as far as CRC - CRC is checked internally */
+		     tdata->plaintext.len -
+			tdata->plaintext.padding_len -
+			crc_data_len);
+	RTE_TEST_ASSERT_SUCCESS(ret, "Plaintext not as expected");
+
+	ret = memcmp(bip_op->output.data,
+		     tdata->output.data,
+		     tdata->output.len);
+	RTE_TEST_ASSERT_SUCCESS(ret, "BIP not as expected");
+
+	RTE_TEST_ASSERT_EQUAL(result->overall_status,
+			      RTE_MULTI_FN_OP_STATUS_SUCCESS,
+			      "Multi-function op processing failed");
+
+	/* Print stats */
+	num_stats = rte_rawdev_xstats_get(ts_params->dev_id,
+					  stats_id,
+					  stats,
+					  RTE_MULTI_FN_XSTAT_ID_NB);
+	num_names = rte_rawdev_xstats_names_get(ts_params->dev_id,
+						stats_names,
+						RTE_MULTI_FN_XSTAT_ID_NB);
+	RTE_TEST_ASSERT_EQUAL(num_stats,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats");
+	RTE_TEST_ASSERT_EQUAL(num_names,
+			      RTE_MULTI_FN_XSTAT_ID_NB,
+			      "Failed to get stats names");
+
+	for (i = 0; i < num_stats; i++)
+		AESNI_MB_MFN_DEBUG("%s:  %"PRIu64,
+				   stats_names[i].name,
+				   stats[i]);
+
+	return 0;
+}
+
+static void
+test_run(int (*setup)(void),
+	 void (*teardown)(void),
+	 int (*run)(void *),
+	 void *data,
+	 const char *name)
+{
+	int ret = 0;
+
+	if (setup != NULL) {
+		ret = setup();
+		if (ret < 0) {
+			AESNI_MB_MFN_INFO("Error setting up test %s", name);
+			unsupported++;
+		}
+	}
+
+	if (run != NULL) {
+		ret = run(data);
+		if (ret < 0) {
+			failed++;
+			AESNI_MB_MFN_INFO("%s Failed", name);
+		} else {
+			passed++;
+			AESNI_MB_MFN_INFO("%s Passed", name);
+		}
+	}
+
+	if (teardown != NULL)
+		teardown();
+
+	total++;
+}
+
+int
+aesni_mb_mfn_test(uint16_t dev_id)
+{
+	if (testsuite_setup(dev_id) != TEST_SUCCESS) {
+		AESNI_MB_MFN_ERR("Setup failed");
+		testsuite_teardown();
+		return TEST_FAILED;
+	}
+
+	/* DOCSIS: Crypto-CRC */
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_1, "1");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_2, "2");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_3, "3");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_4, "4");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_5, "5");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_6, "6");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_7, "7");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_8, "8");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_9, "9");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_10, "10");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_11, "11");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_12, "12");
+	TEST(test_setup, test_teardown, test_docsis_encrypt,
+	     &docsis_test_case_13, "13");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_1, "1");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_2, "2");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_3, "3");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_4, "4");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_5, "5");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_6, "6");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_7, "7");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_8, "8");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_9, "9");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_10, "10");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_11, "11");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_12, "12");
+	TEST(test_setup, test_teardown, test_docsis_decrypt,
+	     &docsis_test_case_13, "13");
+
+	/* GPON: Crypto-CRC-BIP */
+	TEST(test_setup, test_teardown, test_gpon_encrypt,
+	     &gpon_test_case_1, "1");
+	TEST(test_setup, test_teardown, test_gpon_encrypt,
+	     &gpon_test_case_2, "2");
+	TEST(test_setup, test_teardown, test_gpon_encrypt,
+	     &gpon_test_case_3, "3");
+	TEST(test_setup, test_teardown, test_gpon_encrypt,
+	     &gpon_test_case_4, "4");
+	TEST(test_setup, test_teardown, test_gpon_encrypt,
+	     &gpon_test_case_5, "5");
+	TEST(test_setup, test_teardown, test_gpon_encrypt,
+	     &gpon_test_case_6, "6");
+	TEST(test_setup, test_teardown, test_gpon_decrypt,
+	     &gpon_test_case_1, "1");
+	TEST(test_setup, test_teardown, test_gpon_decrypt,
+	     &gpon_test_case_2, "2");
+	TEST(test_setup, test_teardown, test_gpon_decrypt,
+	     &gpon_test_case_3, "3");
+	TEST(test_setup, test_teardown, test_gpon_decrypt,
+	     &gpon_test_case_4, "4");
+	TEST(test_setup, test_teardown, test_gpon_decrypt,
+	     &gpon_test_case_5, "5");
+	TEST(test_setup, test_teardown, test_gpon_decrypt,
+	     &gpon_test_case_6, "6");
+
+	testsuite_teardown();
+
+	printf("Total tests   : %d\n", total);
+	printf("Passed        : %d\n", passed);
+	printf("Failed        : %d\n", failed);
+	printf("Not supported : %d\n", unsupported);
+
+	if (failed)
+		return TEST_FAILED;
+
+	return TEST_SUCCESS;
+}
diff --git a/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test_vectors.h b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test_vectors.h
new file mode 100644
index 000000000..a42adb7dd
--- /dev/null
+++ b/drivers/raw/aesni_mb_mfn/aesni_mb_mfn_rawdev_test_vectors.h
@@ -0,0 +1,1184 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation.
+ */
+
+#ifndef _AESNI_MB_MFN_RAWDEV_TEST_VECTORS_H_
+#define _AESNI_MB_MFN_RAWDEV_TEST_VECTORS_H_
+
+#include <stdbool.h>
+
+/*
+ * DOCSIS test data and cases
+ * - encrypt direction: CRC-Crypto
+ * - decrypt direction: Crypto-CRC
+ */
+struct docsis_test_data {
+	struct {
+		uint8_t data[16];
+		unsigned int len;
+	} key;
+
+	struct {
+		uint8_t data[16] __rte_aligned(16);
+		unsigned int len;
+	} cipher_iv;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} plaintext;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} ciphertext;
+};
+
+struct docsis_test_data docsis_test_case_1 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x61, 0xF8, 0x63, 0x42
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_2 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0, 0xDF,
+			/* CRC */
+			0xFE, 0x12, 0x99, 0xE5
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_3 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xD6, 0xE2, 0x70, 0x5C,
+			0xE6, 0x4D, 0xCC, 0x8C, 0x47, 0xB7, 0x09, 0xD6,
+			/* CRC */
+			0x54, 0x85, 0xF8, 0x32
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_4 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x92, 0x6A, 0xC2, 0xDC,
+			0xEE, 0x3B, 0x31, 0xEC, 0x03, 0xDE, 0x95, 0x33,
+			0x5E,
+			/* CRC */
+			0xFE, 0x47, 0x3E, 0x22
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_5 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0x42, 0xF3, 0x71, 0xA9,
+			0x8A, 0xCD, 0x59, 0x77, 0x67, 0x11, 0x1A, 0x87,
+			/* CRC */
+			0xAB, 0xED, 0x2C, 0x26
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_6 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0xA4, 0x0C, 0xC2, 0xF0,
+			0x81, 0x49, 0xA8, 0xA6, 0x6C, 0x48, 0xEB, 0x1F,
+			0x4B,
+			/* CRC */
+			0x2F, 0xD4, 0x48, 0x18
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_7 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x11, 0xB4, 0x06, 0x33
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_8 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x8A, 0x0F, 0x74, 0xE8
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_9 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x5D, 0x2B, 0x12, 0xF4
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_10 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0x14, 0x08, 0xE8, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_11 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xB3, 0x60, 0xEB, 0x38
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_12 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_13 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+/*
+ * GPON test data and cases
+ * - encrypt direction: CRC-Crypto-BIP
+ * - decrypt direction: BIP-Crypto-CRC
+ */
+struct gpon_test_data {
+	struct {
+		uint8_t data[16];
+		unsigned int len;
+	} key;
+
+	struct {
+		uint8_t data[16] __rte_aligned(16);
+		unsigned int len;
+	} cipher_iv;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		unsigned int bip_offset;
+		unsigned int padding_len;
+		bool no_cipher;
+	} plaintext;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		unsigned int bip_offset;
+		unsigned int padding_len;
+		bool no_cipher;
+	} ciphertext;
+
+	struct {
+	uint8_t data[8];
+		unsigned int len;
+	} output;
+};
+
+struct gpon_test_data gpon_test_case_1 = {
+	.key = {
+		.data = {
+			0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+			0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x20, 0x27, 0x11, 0x00, 0x00, 0x21, 0x23,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04,
+			/* CRC */
+			0x05, 0x06, 0x01, 0x01
+		},
+		.len = 16,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = false
+	},
+	.ciphertext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x20, 0x27, 0x11, 0x00, 0x00, 0x21, 0x23,
+			/* Ethernet frame */
+			0xC7, 0x62, 0x82, 0xCA,
+			/* CRC */
+			0x3E, 0x92, 0xC8, 0x5A
+		},
+		.len = 16,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = false
+	},
+	.output = {
+		/* Expected BIP */
+		.data = {0xF9, 0xD0, 0x4C, 0xA2},
+		.len  = 4
+	}
+};
+
+struct gpon_test_data gpon_test_case_2 = {
+	.key = {
+		.data = {
+			0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+			0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x40, 0x27, 0x11, 0x00, 0x00, 0x29, 0x3C,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01,
+			/* CRC */
+			0x81, 0x00, 0x00, 0x01
+		},
+		.len = 24,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = false
+	},
+	.ciphertext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x40, 0x27, 0x11, 0x00, 0x00, 0x29, 0x3C,
+			/* Ethernet frame */
+			0xC7, 0x62, 0x82, 0xCA, 0xF6, 0x6F, 0xF5, 0xED,
+			0xB7, 0x90, 0x1E, 0x02,
+			/* CRC */
+			0xEA, 0x38, 0xA1, 0x78
+		},
+		.len = 24,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = false
+	},
+	.output = {
+		/* Expected BIP */
+		.data = {0x6C, 0xE5, 0xC6, 0x70},
+		.len  = 4
+	}
+};
+
+struct gpon_test_data gpon_test_case_3 = {
+	.key = {
+		.data = {
+			0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+			0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* XGEM header */
+			0x01, 0x00, 0x27, 0x11, 0x00, 0x00, 0x33, 0x0B,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x81, 0x00, 0x00, 0x01,
+			0x08, 0x00, 0x45, 0x00, 0x00, 0x6A, 0xB0, 0x7E,
+			0x00, 0x00, 0x04, 0x06, 0x83, 0xBD, 0xC0, 0xA8,
+			0x00, 0x01, 0xC0, 0xA8, 0x01, 0x01, 0x04, 0xD2,
+			0x16, 0x2E, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34,
+			0x56, 0x90, 0x50, 0x10, 0x20, 0x00, 0xA6, 0x33,
+			0x00, 0x00, 0x30, 0x31,
+			/* CRC */
+			0x32, 0x33, 0x34, 0x35
+		},
+		.len = 72,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = false
+	},
+	.ciphertext = {
+		.data = {
+			/* XGEM header */
+			0x01, 0x00, 0x27, 0x11, 0x00, 0x00, 0x33, 0x0B,
+			/* Ethernet frame */
+			0xC7, 0x62, 0x82, 0xCA, 0xF6, 0x6F, 0xF5, 0xED,
+			0xB7, 0x90, 0x1E, 0x02, 0x6B, 0x2C, 0x08, 0x7D,
+			0x3C, 0x90, 0xE8, 0x2C, 0x44, 0x30, 0x03, 0x29,
+			0x5F, 0x88, 0xA9, 0xD6, 0x1E, 0xF9, 0xD1, 0xF1,
+			0xD6, 0x16, 0x8C, 0x72, 0xA4, 0xCD, 0xD2, 0x8F,
+			0x63, 0x26, 0xC9, 0x66, 0xB0, 0x65, 0x24, 0x9B,
+			0x60, 0x5B, 0x18, 0x60, 0xBD, 0xD5, 0x06, 0x13,
+			0x40, 0xC9, 0x60, 0x64,
+			/* CRC */
+			0x36, 0x5F, 0x86, 0x8C
+		},
+		.len = 72,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = false
+	},
+	.output = {
+		/* Expected BIP */
+		.data = {0xDF, 0xE0, 0xAD, 0xFB},
+		.len  = 4
+	}
+};
+
+struct gpon_test_data gpon_test_case_4 = {
+	.key = {
+		.data = {
+			0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+			0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x39, 0x03, 0xFD, 0x00, 0x00, 0xB3, 0x6A,
+			/* Ethernet frame */
+			0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+			0x10, 0x11,
+			/* CRC */
+			0x20, 0x21, 0x22, 0x23,
+			/* Padding */
+			0x55, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 2,
+		.no_cipher = false
+	},
+	.ciphertext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x39, 0x03, 0xFD, 0x00, 0x00, 0xB3, 0x6A,
+			/* Ethernet frame */
+			0x73, 0xE0, 0x5D, 0x5D, 0x32, 0x9C, 0x3B, 0xFA,
+			0x6B, 0x66,
+			/* CRC */
+			0xF6, 0x8E, 0x5B, 0xD5,
+			/* Padding */
+			0xAB, 0xCD
+		},
+		.len = 24,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 2,
+		.no_cipher = false
+	},
+	.output = {
+		/* Expected BIP */
+		.data = {0x71, 0xF6, 0x8B, 0x73},
+		.len  = 4
+	}
+};
+
+struct gpon_test_data gpon_test_case_5 = {
+	.key = {
+		.data = {
+			0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+			0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x05, 0x03, 0xFD, 0x00, 0x00, 0xB9, 0xB4,
+			/* Ethernet frame */
+			0x08,
+			/* Padding */
+			0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55
+		},
+		.len = 16,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 7,
+		.no_cipher = false
+	},
+	.ciphertext = {
+		.data = {
+			/* XGEM header */
+			0x00, 0x05, 0x03, 0xFD, 0x00, 0x00, 0xB9, 0xB4,
+			/* Ethernet frame */
+			0x73,
+			/* Padding */
+			0xBC, 0x02, 0x03, 0x6B, 0xC4, 0x60, 0xA0
+		},
+		.len = 16,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 7,
+		.no_cipher = false
+	},
+	.output = {
+		/* Expected BIP */
+		.data = {0x18, 0x7D, 0xD8, 0xEA},
+		.len  = 4
+	}
+};
+
+struct gpon_test_data gpon_test_case_6 = {
+	.key = {
+		.data = {
+			0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
+			0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00
+		},
+		.len = 16
+	},
+	.cipher_iv = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* XGEM header */
+			0x01, 0x00, 0x27, 0x11, 0x00, 0x00, 0x33, 0x0B,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x81, 0x00, 0x00, 0x01,
+			0x08, 0x00, 0x45, 0x00, 0x00, 0x6A, 0xB0, 0x7E,
+			0x00, 0x00, 0x04, 0x06, 0x83, 0xBD, 0xC0, 0xA8,
+			0x00, 0x01, 0xC0, 0xA8, 0x01, 0x01, 0x04, 0xD2,
+			0x16, 0x2E, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34,
+			0x56, 0x90, 0x50, 0x10, 0x20, 0x00, 0xA6, 0x33,
+			0x00, 0x00, 0x30, 0x31,
+			/* CRC */
+			0x32, 0x33, 0x34, 0x35
+		},
+		.len = 72,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = true
+	},
+	.ciphertext = {
+		.data = {
+			/* XGEM header */
+			0x01, 0x00, 0x27, 0x11, 0x00, 0x00, 0x33, 0x0B,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x01, 0x01,
+			0x01, 0x01, 0x01, 0x01, 0x81, 0x00, 0x00, 0x01,
+			0x08, 0x00, 0x45, 0x00, 0x00, 0x6a, 0xb0, 0x7e,
+			0x00, 0x00, 0x04, 0x06, 0x83, 0xbd, 0xc0, 0xa8,
+			0x00, 0x01, 0xc0, 0xa8, 0x01, 0x01, 0x04, 0xd2,
+			0x16, 0x2e, 0x12, 0x34, 0x56, 0x78, 0x12, 0x34,
+			0x56, 0x90, 0x50, 0x10, 0x20, 0x00, 0xa6, 0x33,
+			0x00, 0x00, 0x30, 0x31,
+			/* CRC */
+			0x53, 0xC1, 0xE6, 0x0C
+		},
+		.len = 72,
+		.cipher_offset = 8,
+		.crc_offset = 8,
+		.bip_offset = 0,
+		.padding_len = 0,
+		.no_cipher = true
+	},
+	.output = {
+		/* Expected BIP */
+		.data = {0x6A, 0xD5, 0xC2, 0xAB},
+		.len  = 4
+	}
+};
+
+#endif /* _AESNI_MB_MFN_RAWDEV_TEST_VECTORS_H_ */
diff --git a/drivers/raw/aesni_mb_mfn/meson.build b/drivers/raw/aesni_mb_mfn/meson.build
new file mode 100644
index 000000000..ee96947c1
--- /dev/null
+++ b/drivers/raw/aesni_mb_mfn/meson.build
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation.
+
+IMB_required_ver = '0.54'
+lib = cc.find_library('IPSec_MB', required: false)
+if not lib.found()
+	build = false
+	reason = 'missing dependency, "libIPSec_MB"'
+else
+	ext_deps += lib
+
+	# version comes with quotes, so we split based on " and take the middle
+	imb_ver = cc.get_define('IMB_VERSION_STR',
+		prefix : '#include<intel-ipsec-mb.h>').split('"')[1]
+
+	if (imb_ver == '') or (imb_ver.version_compare('<' + IMB_required_ver))
+		reason = 'IPSec_MB version >= @0@ is required, found version @1@'.format(
+				IMB_required_ver, imb_ver)
+		build = false
+	endif
+
+endif
+
+sources = files('aesni_mb_mfn_rawdev.c', 'aesni_mb_mfn_rawdev_test.c')
+allow_experimental_apis = true
+deps += ['bus_vdev', 'net', 'rawdev', 'cryptodev', 'common_multi_fn']
diff --git a/drivers/raw/aesni_mb_mfn/rte_rawdev_aesni_mb_mfn_version.map b/drivers/raw/aesni_mb_mfn/rte_rawdev_aesni_mb_mfn_version.map
new file mode 100644
index 000000000..f9f17e4f6
--- /dev/null
+++ b/drivers/raw/aesni_mb_mfn/rte_rawdev_aesni_mb_mfn_version.map
@@ -0,0 +1,3 @@
+DPDK_20.0 {
+	local: *;
+};
diff --git a/drivers/raw/meson.build b/drivers/raw/meson.build
index bb5797760..a7a44cdbd 100644
--- a/drivers/raw/meson.build
+++ b/drivers/raw/meson.build
@@ -5,7 +5,8 @@ drivers = ['dpaa2_cmdif', 'dpaa2_qdma',
 	'ifpga', 'ioat', 'ntb',
 	'octeontx2_dma',
 	'octeontx2_ep',
-	'skeleton']
+	'skeleton',
+	'aesni_mb_mfn']
 std_deps = ['rawdev']
 config_flag_fmt = 'RTE_LIBRTE_PMD_@0@_RAWDEV'
 driver_name_fmt = 'rte_rawdev_@0@'
diff --git a/mk/rte.app.mk b/mk/rte.app.mk
index b836d220d..b7394d81e 100644
--- a/mk/rte.app.mk
+++ b/mk/rte.app.mk
@@ -347,6 +347,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_IOAT_RAWDEV)   += -lrte_rawdev_ioat
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_NTB_RAWDEV) += -lrte_rawdev_ntb
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_DMA_RAWDEV) += -lrte_rawdev_octeontx2_dma
 _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_OCTEONTX2_EP_RAWDEV) += -lrte_rawdev_octeontx2_ep
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV) += -lrte_rawdev_aesni_mb_mfn
+_LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV) += -lIPSec_MB
 _LDLIBS-$(CONFIG_RTE_LIBRTE_MULTI_FN_COMMON) += -lrte_multi_fn
 endif # CONFIG_RTE_LIBRTE_RAWDEV
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 3/4] test/rawdev: add aesni_mb_mfn raw device tests
  2020-04-10 14:27 [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing David Coyle
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 1/4] raw/common: add multi-function interface David Coyle
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 2/4] raw/aesni_mb_mfn: add aesni_mb_mfn raw device PMD David Coyle
@ 2020-04-10 14:27 ` David Coyle
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 4/4] doc: update docs for aesni_mb_mfn raw device PMD David Coyle
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-04-10 14:27 UTC (permalink / raw)
  To: dev
  Cc: declan.doherty, fiona.trahe, pablo.de.lara.guarch, brendan.ryan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, ferruh.yigit,
	David Coyle, Mairtin o Loingsigh

Add unit tests for the AESNI-MB Multi-Function raw device PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 app/test/test_rawdev.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/app/test/test_rawdev.c b/app/test/test_rawdev.c
index 524a9d5f3..eae88c20f 100644
--- a/app/test/test_rawdev.c
+++ b/app/test/test_rawdev.c
@@ -45,3 +45,21 @@ test_rawdev_selftest_ioat(void)
 }
 
 REGISTER_TEST_COMMAND(ioat_rawdev_autotest, test_rawdev_selftest_ioat);
+
+static int
+test_rawdev_selftest_aesni_mb_mfn(void)
+{
+	int ret;
+
+	ret = rte_vdev_init("rawdev_mfn_aesni_mb", NULL);
+	if (ret) {
+		printf("Failed to create AESNI-MB Multi-Function rawdev\n");
+		return ret;
+	}
+
+	return rte_rawdev_selftest(rte_rawdev_get_dev_id(
+						"rawdev_mfn_aesni_mb"));
+}
+
+REGISTER_TEST_COMMAND(rawdev_mfn_aesni_mb_autotest,
+				test_rawdev_selftest_aesni_mb_mfn);
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 4/4] doc: update docs for aesni_mb_mfn raw device PMD
  2020-04-10 14:27 [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing David Coyle
                   ` (2 preceding siblings ...)
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 3/4] test/rawdev: add aesni_mb_mfn raw device tests David Coyle
@ 2020-04-10 14:27 ` David Coyle
  2020-04-10 22:55 ` [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing Thomas Monjalon
  2020-06-04 15:13 ` [dpdk-dev] [PATCH 0/3] add support for DOCSIS protocol to security library David Coyle
  5 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-04-10 14:27 UTC (permalink / raw)
  To: dev
  Cc: declan.doherty, fiona.trahe, pablo.de.lara.guarch, brendan.ryan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, ferruh.yigit,
	David Coyle, Mairtin o Loingsigh

Update documentation for the AESNI-MB Multi-Function raw device
PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 doc/api/doxy-api-index.md              |   3 +-
 doc/api/doxy-api.conf.in               |   1 +
 doc/guides/rawdevs/aesni_mb_mfn.rst    | 219 +++++++++++++++++++++++++
 doc/guides/rawdevs/index.rst           |   1 +
 doc/guides/rel_notes/release_20_05.rst |   6 +
 5 files changed, 229 insertions(+), 1 deletion(-)
 create mode 100644 doc/guides/rawdevs/aesni_mb_mfn.rst

diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
index dff496be0..328d26991 100644
--- a/doc/api/doxy-api-index.md
+++ b/doc/api/doxy-api-index.md
@@ -49,7 +49,8 @@ The public API headers are grouped by topics:
   [dpaa2_mempool]      (@ref rte_dpaa2_mempool.h),
   [dpaa2_cmdif]        (@ref rte_pmd_dpaa2_cmdif.h),
   [dpaa2_qdma]         (@ref rte_pmd_dpaa2_qdma.h),
-  [crypto_scheduler]   (@ref rte_cryptodev_scheduler.h)
+  [crypto_scheduler]   (@ref rte_cryptodev_scheduler.h),
+  [multi_fn]           (@ref rte_multi_fn.h)
 
 - **memory**:
   [memseg]             (@ref rte_memory.h),
diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in
index 65e8146be..efae9795e 100644
--- a/doc/api/doxy-api.conf.in
+++ b/doc/api/doxy-api.conf.in
@@ -15,6 +15,7 @@ INPUT                   = @TOPDIR@/doc/api/doxy-api-index.md \
                           @TOPDIR@/drivers/net/ice \
                           @TOPDIR@/drivers/net/ixgbe \
                           @TOPDIR@/drivers/net/softnic \
+                          @TOPDIR@/drivers/raw/common/multi_fn \
                           @TOPDIR@/drivers/raw/dpaa2_cmdif \
                           @TOPDIR@/drivers/raw/dpaa2_qdma \
                           @TOPDIR@/lib/librte_eal/include \
diff --git a/doc/guides/rawdevs/aesni_mb_mfn.rst b/doc/guides/rawdevs/aesni_mb_mfn.rst
new file mode 100644
index 000000000..aaa8edd19
--- /dev/null
+++ b/doc/guides/rawdevs/aesni_mb_mfn.rst
@@ -0,0 +1,219 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2020 Intel Corporation.
+
+AES-NI Multi Buffer Multi-Function Rawdev Driver
+================================================
+
+The AES-NI MB Multi-Function Rawdev PMD is a poll mode driver which enables
+utilization of new multi-function processing capabilities in the Intel IPSec
+Multi Buffer library (see :doc:`../cryptodevs/aesni_mb` for more details on this
+library).
+
+This Rawdev PMD supports a new Multi-Function interface, which provides a way of
+combining one or more packet-processing functions into a single operation,
+thereby allowing these to be performed in parallel by the Intel IPSec Multi
+Buffer library. Through the multi-function interface, the following use-cases
+are supported by this PMD:
+
+* DOCSIS MAC: Crypto-CRC
+* GPON MAC: Crypto-CRC-BIP
+
+
+Features
+--------
+
+AES-NI MB Multi-Function Rawdev PMD currently supports the following:
+
+Cipher algorithms:
+
+* RTE_CRYPTO_CIPHER_AES_CTR (128 bit)
+* RTE_CRYPTO_CIPHER_AES_DOCSISBPI (128 bit)
+
+Error Detection algorithms:
+
+* RTE_MULTI_FN_ERR_DETECT_BIP32
+* RTE_MULTI_FN_ERR_DETECT_CRC32_ETH
+
+These algorithms may only be combined through the multi-function interface in
+the following specific orders for use by this PMD:
+
+* For DOCSIS Crypto-CRC (Encrypt direction)
+
+  1. RTE_MULTI_FN_ERR_DETECT_CRC32_ETH (Generate)
+  2. RTE_CRYPTO_CIPHER_AES_DOCSISBPI (Encrypt)
+
+
+* For DOCSIS Crypto-CRC (Decrypt direction)
+
+  1. RTE_CRYPTO_CIPHER_AES_DOCSISBPI (Decrypt)
+  2. RTE_MULTI_FN_ERR_DETECT_CRC32_ETH (Verify)
+
+
+* For GPON Crypto-CRC-BIP (Encrypt direction)
+
+  1. RTE_MULTI_FN_ERR_DETECT_CRC32_ETH (Generate)
+  2. RTE_CRYPTO_CIPHER_AES_CTR (Encrypt)
+  3. RTE_MULTI_FN_ERR_DETECT_BIP32 (Generate)
+
+
+* For GPON Crypto-CRC-BIP (Decrypt direction)
+
+  1. RTE_MULTI_FN_ERR_DETECT_BIP32 (Generate)
+  2. RTE_CRYPTO_CIPHER_AES_CTR (Decrypt)
+  3. RTE_MULTI_FN_ERR_DETECT_CRC32_ETH (Verify)
+
+
+Limitations
+-----------
+
+* Chained mbufs are not supported.
+* Out of place operation is not supported.
+* Only 128-bit keys for RTE_CRYPTO_CIPHER_AES_CTR and
+  RTE_CRYPTO_CIPHER_AES_DOCSISBPI are supported.
+
+
+Installation
+------------
+
+The AES-NI MB Multi-Function Rawdev PMD requires the Intel IPSec Multi Buffer
+library be installed on the system. For details on how to install this library,
+please see :doc:`../cryptodevs/aesni_mb`.
+
+.. note::
+
+   This PMD requires v0.54 or later of the Intel IPSec Multi Buffer library.
+
+
+Initialization
+--------------
+
+In order to enable the AES-NI MB Multi-Function Rawdev PMD, the user must:
+
+* Build the multi buffer library (as explained in Installation section).
+* Set CONFIG_RTE_LIBRTE_MULTI_FN_COMMON=y in config/common_base.
+* Set CONFIG_RTE_LIBRTE_PMD_AESNI_MB_MFN_RAWDEV=y in config/common_base.
+
+To enabled extra debug features such as extra parameter checking, the user must:
+
+* Set CONFIG_RTE_LIBRTE_PMD_AESNI_MB_RAWDEV_MFN_DEBUG=y in config/common_base.
+
+Note, however, that doing so will impact performance.
+
+To use the PMD in an application, the user must:
+
+* Call rte_vdev_init("rawdev_mfn_aesni_mb") within the application.
+* Use --vdev="rawdev_mfn_aesni_mb" in the EAL options, which will call
+  rte_vdev_init() internally.
+
+Example:
+
+.. code-block:: console
+
+    <application> -l 1 -n 4 --vdev="rawdev_mfn_aesni_mb" -- <application params>
+
+
+Device Configuration
+--------------------
+
+Configuring the AES-NI MB Multi-Function Rawdev PMD is done through a
+combination of the ``rte_rawdev_configure()`` API and the
+``struct rte_multi_fn_dev_config``  structure of the multi-function interface.
+
+The following code shows how the device is configured:
+
+.. code-block:: c
+
+    struct rte_multi_fn_dev_config mf_dev_conf = {
+                    .nb_queues = 1,
+                    .socket_id = 0
+    };
+    struct rte_rawdev_info rdev_info = {.dev_private = &mf_dev_conf};
+
+    rte_rawdev_configure(dev_id, (rte_rawdev_obj_t)&rdev_info);
+
+
+Queue Pair Configuration
+------------------------
+
+Configuring the queue pairs of the AES-NI MB Multi-Function Rawdev PMD is done
+through a combination of the ``rte_rawdev_queue_setup()`` API and the
+``struct rte_multi_fn_qp_config`` structure of the multi-function interface.
+
+The following code shows how the queue pairs are configured:
+
+.. code-block:: c
+
+    struct rte_multi_fn_qp_config qp_conf = {
+                    .nb_descriptors = 4096
+    };
+
+    rte_rawdev_queue_setup(dev_id, qp_id, (rte_rawdev_obj_t)&qp_conf);
+
+
+Multi-Function Session Creation
+-------------------------------
+
+Multi-function sessions are created on the AES-NI MB Multi-Function Rawdev PMD
+through the multi-function interface by chaining ``struct rte_multi_fn_xform``
+transforms together and calling the ``rte_multi_fn_session_create()`` API.
+
+The only transform chains supported by this PMD are listed in the Features
+section.
+
+The following code shows how a multi-function session is created, taking
+Crypto-CRC chaining as an example:
+
+.. code-block:: c
+
+    struct rte_multi_fn_xform xform[2] = {0};
+
+    xform[0].type = RTE_MULTI_FN_XFORM_TYPE_ERR_DETECT;
+    xform[0].err_detect.algo = RTE_MULTI_FN_ERR_DETECT_CRC32_ETH;
+    xform[0].err_detect.op = RTE_MULTI_FN_ERR_DETECT_OP_GENERATE;
+    xform[0].next = &xform[1];
+
+    xform[1].type = RTE_MULTI_FN_XFORM_TYPE_CRYPTO_SYM;
+    xform[1].crypto_sym.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+    xform[1].next = NULL;
+    /*
+     * setup reaminder of xform[1].crypto_sym.cipher fields here, including
+     * op, algo, key and iv
+     */
+
+    sess = rte_multi_fn_session_create(dev_id, &xform[0], rte_socket_id());
+
+
+Performing Multi-Function Operations
+------------------------------------
+
+Multi-function operations are performed on the AES-NI MB Multi-Function Rawdev
+PMD using the ``rte_rawdev_enqueue_buffers()`` and
+``rte_rawdev_dequeue_buffers()`` APIs. Chains of multi-function operations
+(``struct rte_multi_fn_op``) which are associated with an mbuf and a
+multi-function session are passed to these APIs.
+
+The following code shows how these APIs are used:
+
+
+.. code-block:: c
+
+    struct rte_multi_fn_op *ops[2];
+    rte_multi_fn_op_bulk_alloc(op_pool, ops, 2);
+
+    ops[0]->next = ops[1];
+    ops[0]->m_src = src;
+    ops[0]->sess = sess;
+    ops[1]->next = NULL;
+    /* setup remainder of ops here */
+
+    rte_rawdev_enqueue_buffers(dev_id,
+                               (struct rte_rawdev_buf **)ops,
+                               1,
+                               (rte_rawdev_obj_t)&qp_id);
+
+    do {
+        nb_deq = rte_rawdev_dequeue_buffers(dev_id,
+                                            (struct rte_rawdev_buf **)ops,
+                                            1,
+                                            (rte_rawdev_obj_t)&qp_id);
+    } while (nb_deq < 1);
diff --git a/doc/guides/rawdevs/index.rst b/doc/guides/rawdevs/index.rst
index f64ec4427..3e765adda 100644
--- a/doc/guides/rawdevs/index.rst
+++ b/doc/guides/rawdevs/index.rst
@@ -18,3 +18,4 @@ application through rawdev API.
     ntb
     octeontx2_dma
     octeontx2_ep
+    aesni_mb_mfn
diff --git a/doc/guides/rel_notes/release_20_05.rst b/doc/guides/rel_notes/release_20_05.rst
index 000bbf501..c969cd4aa 100644
--- a/doc/guides/rel_notes/release_20_05.rst
+++ b/doc/guides/rel_notes/release_20_05.rst
@@ -62,6 +62,12 @@ New Features
 
   * Added support for matching on IPv4 Time To Live and IPv6 Hop Limit.
 
+* **Added AES-NI MB Multi-Function rawdev PMD.**
+
+  Added a new AESNI-MB Multi-Function raw device PMD for utilizing
+  multi-function capabilities of the Intel IPSec Multi Buffer library. See
+  the :doc:`../rawdevs/aesni_mb_mfn` guide for more details on this new PMD.
+
 
 Removed Items
 -------------
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-10 14:27 [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing David Coyle
                   ` (3 preceding siblings ...)
  2020-04-10 14:27 ` [dpdk-dev] [PATCH v3 4/4] doc: update docs for aesni_mb_mfn raw device PMD David Coyle
@ 2020-04-10 22:55 ` Thomas Monjalon
  2020-04-14 10:21   ` Ferruh Yigit
  2020-06-04 15:13 ` [dpdk-dev] [PATCH 0/3] add support for DOCSIS protocol to security library David Coyle
  5 siblings, 1 reply; 92+ messages in thread
From: Thomas Monjalon @ 2020-04-10 22:55 UTC (permalink / raw)
  To: David Coyle
  Cc: dev, declan.doherty, fiona.trahe, pablo.de.lara.guarch,
	brendan.ryan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	ferruh.yigit, Anoob Joseph, Ruifeng Wang, Liron Himi,
	Nagadheeraj Rottela, Srikanth Jampala, Gagandeep Singh, Jay Zhou,
	Ravi Kumar

Hi,

Adding more people (crypto PMD maintainers) as Cc.

10/04/2020 16:27, David Coyle:
> Introduction
> ============
> 
> This patchset adds a new AESNI-MB Multi-Function raw device PMD for
> utilizing multi-function capabilities of the Intel IPSec Multi Buffer
> library.
> 
> The aim of this rawdev PMD is to provide a way of combining one or more
> common packet-processing functions into a single operation, focused on
> DOCSIS and GPON MAC workloads. This allows these functions to be performed
> in parallel by the Intel IPSec Multi Buffer library. These functions
> include cryptography and CRC/BIP calculations. Performing these functions
> in parallel as a single operation can enable a significant performance
> improvement.

I don't know crypto but I don't think using rawdev for crypto operations
is an API improvement.

Repeating the initial comments from v1 (because got no reply):
"
As a first impression, I feel it is not the right API.
DPDK is based on classes: ethdev, crypto, compress, baseband, regex
I want to understand why your features cannot fit in a class.

I feel we will need a lot of time to discuss the design.
If you don't see any consensus on the design in the mailing list,
you should request an opinion from the Technical Board.

This feature is not a priority for 20.05 release.
By the way, it has not been announced in any roadmap.
"

> Background
> ==========
> 
> There are a number of byte-wise operations which are used across many
> access network data-plane pipelines, such as Cipher, CRC and
> Bit-Interleaved-Parity (BIP). Some prototyping has been done at Intel as
> part of the 01.org access-network-dataplanes project to prove that a
> significant performance improvement is possible when such byte-wise
> operations are combined into a single pass of packet data processing. This
> performance boost has been prototyped for both DOCSIS MAC data-plane and
> GPON MAC data-plane pipelines based on DPDK.
> 
> The original prototypes on 01.org used some protocol-specific modifications
> to the DPDK cryptodev library. In order to make this performance
> optimization consumable for network access equipment vendors, a better
> solution was required as CRC and BIP cannot be regarded as cryptographic
> algorithms.

Why not part of crypto?
If not crypto, is it a new API class? Which one?
Please do not say rawdev.


> Hence, the introduction of an AESNI-MB Multi-Function rawdev PMD. This
> PMD uses a new multi-function interface which allows different types of
> operations be combined together. Initially, only symmetric crypto and error
> detection (i.e. CRC and BIP) operations can be combined.
> 
> NOTE: In a future DPDK release, a QAT Multi-Function raw device will also
> be added. As multiple raw devices will share the same interface, the
> approach taken was to create a common interface (i.e. multi-function) which
> can be used by these devices. This both cuts down on code duplication
> across the devices and allows a DOCSIS or GPON MAC application to access
> multiple devices using the same interface.
> 
> 
> Use Cases
> =========
> 
> The primary use cases for the AESNI-MB Multi-Function interface have
> already been mentioned. These are:
> 
> - DOCSIS MAC: Crypto-CRC
>         - Order:
>                 - Downstream: CRC, Encrypt
>                 - Upstream: Decrypt, CRC
>         - Specifications:
>                 - Crypto: 128-bit AES-CFB encryption variant for DOCSIS as
>                   described in section 11.1 of DOCSIS 3.1 Security
>                   Specification
>                   (https://apps.cablelabs.com/specification/CM-SP-SECv3.1)
>                 - CRC: Ethernet 32-bit CRC as defined in
>                   Ethernet/[ISO/IEC 8802-3]
> 
> - GPON MAC: Crypto-CRC-BIP
>         - Order:
>                 - Downstream: CRC, Encrypt, BIP
>                 - Upstream: BIP, Decrypt, CRC
>         - Specifications:
>                 - Crypto: AES-128 [NIST FIPS-197] cipher, used in counter
>                   mode (AES-CTR), as described in [NIST SP800-38A].
>                 - CRC: Ethernet 32-bit CRC as defined in
>                   Ethernet/[ISO/IEC 8802-3]
>                 - BIP: 4-byte bit-interleaved even parity (BIP) field
>                   computed over the entire FS frame, refer to
>                   ITU-T G.989.3, sections 8.1.1.5 and 8.1.2.3
>                   (https://www.itu.int/rec/dologin_pub.asp?lang=e&id=
>                    T-REC-G.989.3-201510-I!!PDF-E)
> 
> Note that support for both these chained operations is already available in
> the Intel IPSec Multi-Buffer library.
> 
> 
> Architecture
> ============
> 
> The following diagram shows where the AESNI-MB Multi-Function rawdev PMD
> fits in an overall application architecture.
> 
>   +------------------------------------------------+
>   |                                                |
>   |                  Application                   |
>   |    (e.g. vCMTS (DOCSIS), vOLT (GPON), etc.)    |
>   |                                                |
>   +------------------------------------------------+
>                           |
>   +-----------------------|------------------------+
>   |                       |                  DPDK  |
>   |                       |                        |
>   |             +---------------------+            |
>   |             |                     |            |
>   |             |     rte_rawdev      |            |
>   |             |                     |            |            NOTE:
>   |             +---------------------+        ____|______ 'MULTI-FUNCTION
>   |                    /      \              /     |          INTERFACE'
>   |                   /        \            /      |         is opaque to
>   |                  /          \          /       |          rte_rawdev
>   |       +--------------------------------+       |
>   |       |    MULTI-FUNCTION INTERFACE    |       |
>   |       +--------------------------------+       |
>   |       +------------+      +------------+       |
>   |       |  AESNI-MB  |      |    QAT     |       |
>   |       |  MULTI-FN  |      |  MULTI-FN  |       |
>   |       |   RAWDEV   |      |   RAWDEV   |       |
>   |       |    PMD     |      |    PMD     |       |
>   |       +------------+      +------------+       |           NOTE:
>   |              |                  |     \________|______ 'QAT MULTI-FN
>   |              |                  |              |         RAWDEV PMD'
>   +--------------|------------------|--------------+      will be added in
>                  |                  |                       later release
>           +------------+      +------------+
>           |  AESNI-MB  |      |   QAT HW   |
>           |   SW LIB   |      |            |
>           +------------+      +------------+
[...]
>  drivers/raw/common/Makefile                   |    8 +
>  drivers/raw/common/meson.build                |    7 +
>  drivers/raw/common/multi_fn/Makefile          |   27 +
>  drivers/raw/common/multi_fn/meson.build       |    9 +
>  .../multi_fn/rte_common_multi_fn_version.map  |   12 +
>  drivers/raw/common/multi_fn/rte_multi_fn.c    |  148 ++
>  drivers/raw/common/multi_fn/rte_multi_fn.h    |  438 +++++

From the explanations above, I don't understand what is the exact role
of the multi_fn interface. The comments in the patch 1 don't help either.
It just reminds me rte_security, which was, in my opinion, a bad design.



^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-10 22:55 ` [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing Thomas Monjalon
@ 2020-04-14 10:21   ` Ferruh Yigit
  2020-04-14 10:32     ` Thomas Monjalon
  0 siblings, 1 reply; 92+ messages in thread
From: Ferruh Yigit @ 2020-04-14 10:21 UTC (permalink / raw)
  To: Thomas Monjalon, David Coyle
  Cc: dev, declan.doherty, fiona.trahe, pablo.de.lara.guarch,
	brendan.ryan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar

On 4/10/2020 11:55 PM, Thomas Monjalon wrote:
> Hi,
> 
> Adding more people (crypto PMD maintainers) as Cc.
> 
> 10/04/2020 16:27, David Coyle:
>> Introduction
>> ============
>>
>> This patchset adds a new AESNI-MB Multi-Function raw device PMD for
>> utilizing multi-function capabilities of the Intel IPSec Multi Buffer
>> library.
>>
>> The aim of this rawdev PMD is to provide a way of combining one or more
>> common packet-processing functions into a single operation, focused on
>> DOCSIS and GPON MAC workloads. This allows these functions to be performed
>> in parallel by the Intel IPSec Multi Buffer library. These functions
>> include cryptography and CRC/BIP calculations. Performing these functions
>> in parallel as a single operation can enable a significant performance
>> improvement.
> 
> I don't know crypto but I don't think using rawdev for crypto operations
> is an API improvement.
> 
> Repeating the initial comments from v1 (because got no reply):
> "
> As a first impression, I feel it is not the right API.
> DPDK is based on classes: ethdev, crypto, compress, baseband, regex
> I want to understand why your features cannot fit in a class.

Hi Thomas,

I asked similar question, and there is already a detailed answer with some
background of the issue:
http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.namprd11.prod.outlook.com/

> 
> I feel we will need a lot of time to discuss the design.
> If you don't see any consensus on the design in the mailing list,
> you should request an opinion from the Technical Board.
> 
> This feature is not a priority for 20.05 release.
> By the way, it has not been announced in any roadmap.
> "

Is it an issue to not have it in the roadmap?

> 
>> Background
>> ==========
>>
>> There are a number of byte-wise operations which are used across many
>> access network data-plane pipelines, such as Cipher, CRC and
>> Bit-Interleaved-Parity (BIP). Some prototyping has been done at Intel as
>> part of the 01.org access-network-dataplanes project to prove that a
>> significant performance improvement is possible when such byte-wise
>> operations are combined into a single pass of packet data processing. This
>> performance boost has been prototyped for both DOCSIS MAC data-plane and
>> GPON MAC data-plane pipelines based on DPDK.
>>
>> The original prototypes on 01.org used some protocol-specific modifications
>> to the DPDK cryptodev library. In order to make this performance
>> optimization consumable for network access equipment vendors, a better
>> solution was required as CRC and BIP cannot be regarded as cryptographic
>> algorithms.
> 
> Why not part of crypto?
> If not crypto, is it a new API class? Which one?
> Please do not say rawdev.
> 
> 
>> Hence, the introduction of an AESNI-MB Multi-Function rawdev PMD. This
>> PMD uses a new multi-function interface which allows different types of
>> operations be combined together. Initially, only symmetric crypto and error
>> detection (i.e. CRC and BIP) operations can be combined.
>>
>> NOTE: In a future DPDK release, a QAT Multi-Function raw device will also
>> be added. As multiple raw devices will share the same interface, the
>> approach taken was to create a common interface (i.e. multi-function) which
>> can be used by these devices. This both cuts down on code duplication
>> across the devices and allows a DOCSIS or GPON MAC application to access
>> multiple devices using the same interface.
>>
>>
>> Use Cases
>> =========
>>
>> The primary use cases for the AESNI-MB Multi-Function interface have
>> already been mentioned. These are:
>>
>> - DOCSIS MAC: Crypto-CRC
>>         - Order:
>>                 - Downstream: CRC, Encrypt
>>                 - Upstream: Decrypt, CRC
>>         - Specifications:
>>                 - Crypto: 128-bit AES-CFB encryption variant for DOCSIS as
>>                   described in section 11.1 of DOCSIS 3.1 Security
>>                   Specification
>>                   (https://apps.cablelabs.com/specification/CM-SP-SECv3.1)
>>                 - CRC: Ethernet 32-bit CRC as defined in
>>                   Ethernet/[ISO/IEC 8802-3]
>>
>> - GPON MAC: Crypto-CRC-BIP
>>         - Order:
>>                 - Downstream: CRC, Encrypt, BIP
>>                 - Upstream: BIP, Decrypt, CRC
>>         - Specifications:
>>                 - Crypto: AES-128 [NIST FIPS-197] cipher, used in counter
>>                   mode (AES-CTR), as described in [NIST SP800-38A].
>>                 - CRC: Ethernet 32-bit CRC as defined in
>>                   Ethernet/[ISO/IEC 8802-3]
>>                 - BIP: 4-byte bit-interleaved even parity (BIP) field
>>                   computed over the entire FS frame, refer to
>>                   ITU-T G.989.3, sections 8.1.1.5 and 8.1.2.3
>>                   (https://www.itu.int/rec/dologin_pub.asp?lang=e&id=
>>                    T-REC-G.989.3-201510-I!!PDF-E)
>>
>> Note that support for both these chained operations is already available in
>> the Intel IPSec Multi-Buffer library.
>>
>>
>> Architecture
>> ============
>>
>> The following diagram shows where the AESNI-MB Multi-Function rawdev PMD
>> fits in an overall application architecture.
>>
>>   +------------------------------------------------+
>>   |                                                |
>>   |                  Application                   |
>>   |    (e.g. vCMTS (DOCSIS), vOLT (GPON), etc.)    |
>>   |                                                |
>>   +------------------------------------------------+
>>                           |
>>   +-----------------------|------------------------+
>>   |                       |                  DPDK  |
>>   |                       |                        |
>>   |             +---------------------+            |
>>   |             |                     |            |
>>   |             |     rte_rawdev      |            |
>>   |             |                     |            |            NOTE:
>>   |             +---------------------+        ____|______ 'MULTI-FUNCTION
>>   |                    /      \              /     |          INTERFACE'
>>   |                   /        \            /      |         is opaque to
>>   |                  /          \          /       |          rte_rawdev
>>   |       +--------------------------------+       |
>>   |       |    MULTI-FUNCTION INTERFACE    |       |
>>   |       +--------------------------------+       |
>>   |       +------------+      +------------+       |
>>   |       |  AESNI-MB  |      |    QAT     |       |
>>   |       |  MULTI-FN  |      |  MULTI-FN  |       |
>>   |       |   RAWDEV   |      |   RAWDEV   |       |
>>   |       |    PMD     |      |    PMD     |       |
>>   |       +------------+      +------------+       |           NOTE:
>>   |              |                  |     \________|______ 'QAT MULTI-FN
>>   |              |                  |              |         RAWDEV PMD'
>>   +--------------|------------------|--------------+      will be added in
>>                  |                  |                       later release
>>           +------------+      +------------+
>>           |  AESNI-MB  |      |   QAT HW   |
>>           |   SW LIB   |      |            |
>>           +------------+      +------------+
> [...]
>>  drivers/raw/common/Makefile                   |    8 +
>>  drivers/raw/common/meson.build                |    7 +
>>  drivers/raw/common/multi_fn/Makefile          |   27 +
>>  drivers/raw/common/multi_fn/meson.build       |    9 +
>>  .../multi_fn/rte_common_multi_fn_version.map  |   12 +
>>  drivers/raw/common/multi_fn/rte_multi_fn.c    |  148 ++
>>  drivers/raw/common/multi_fn/rte_multi_fn.h    |  438 +++++
> 
> From the explanations above, I don't understand what is the exact role
> of the multi_fn interface. The comments in the patch 1 don't help either.
> It just reminds me rte_security, which was, in my opinion, a bad design.
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-14 10:21   ` Ferruh Yigit
@ 2020-04-14 10:32     ` Thomas Monjalon
  2020-04-14 13:04       ` Trahe, Fiona
  0 siblings, 1 reply; 92+ messages in thread
From: Thomas Monjalon @ 2020-04-14 10:32 UTC (permalink / raw)
  To: Ferruh Yigit
  Cc: David Coyle, dev, declan.doherty, fiona.trahe,
	pablo.de.lara.guarch, brendan.ryan, shreyansh.jain,
	hemant.agrawal, akhil.goyal, Anoob Joseph, Ruifeng Wang,
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, bruce.richardson

14/04/2020 12:21, Ferruh Yigit:
> On 4/10/2020 11:55 PM, Thomas Monjalon wrote:
> > Hi,
> > 
> > Adding more people (crypto PMD maintainers) as Cc.
> > 
> > 10/04/2020 16:27, David Coyle:
> >> Introduction
> >> ============
> >>
> >> This patchset adds a new AESNI-MB Multi-Function raw device PMD for
> >> utilizing multi-function capabilities of the Intel IPSec Multi Buffer
> >> library.
> >>
> >> The aim of this rawdev PMD is to provide a way of combining one or more
> >> common packet-processing functions into a single operation, focused on
> >> DOCSIS and GPON MAC workloads. This allows these functions to be performed
> >> in parallel by the Intel IPSec Multi Buffer library. These functions
> >> include cryptography and CRC/BIP calculations. Performing these functions
> >> in parallel as a single operation can enable a significant performance
> >> improvement.
> > 
> > I don't know crypto but I don't think using rawdev for crypto operations
> > is an API improvement.
> > 
> > Repeating the initial comments from v1 (because got no reply):
> > "
> > As a first impression, I feel it is not the right API.
> > DPDK is based on classes: ethdev, crypto, compress, baseband, regex
> > I want to understand why your features cannot fit in a class.
> 
> Hi Thomas,
> 
> I asked similar question, and there is already a detailed answer with some
> background of the issue:

Good to see that you get some reply, Ferruh.

> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.namprd11.prod.outlook.com/

I am not convinced.
I don't like rawdev in general.
Rawdev is good only for hardware support which cannot be generic
like SoC, FPGA management or DMA engine.

Here the intent is to use rawdev because we don't find a good API.
API defeat is a no-go.


> > I feel we will need a lot of time to discuss the design.
> > If you don't see any consensus on the design in the mailing list,
> > you should request an opinion from the Technical Board.
> > 
> > This feature is not a priority for 20.05 release.
> > By the way, it has not been announced in any roadmap.
> > "
> 
> Is it an issue to not have it in the roadmap?

No roadmap is not mandatory.
But having it in the roadmap helps to remind something new will
require long review effort.



^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-14 10:32     ` Thomas Monjalon
@ 2020-04-14 13:04       ` Trahe, Fiona
  2020-04-14 13:24         ` Thomas Monjalon
  0 siblings, 1 reply; 92+ messages in thread
From: Trahe, Fiona @ 2020-04-14 13:04 UTC (permalink / raw)
  To: Thomas Monjalon, Yigit, Ferruh
  Cc: Coyle, David, dev, Doherty, Declan, De Lara Guarch, Pablo, Ryan,
	Brendan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar,
	Richardson, Bruce, Trahe, Fiona

Hi Thomas, David, Ferruh,

> -----Original Message-----
> Subject: Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
> 
> 14/04/2020 12:21, Ferruh Yigit:
> > On 4/10/2020 11:55 PM, Thomas Monjalon wrote:
> > > Hi,
> > >
> > > Adding more people (crypto PMD maintainers) as Cc.
> > >
> > > 10/04/2020 16:27, David Coyle:
> > >> Introduction
> > >> ============
> > >>
> > >> This patchset adds a new AESNI-MB Multi-Function raw device PMD for
> > >> utilizing multi-function capabilities of the Intel IPSec Multi Buffer
> > >> library.
> > >>
> > >> The aim of this rawdev PMD is to provide a way of combining one or more
> > >> common packet-processing functions into a single operation, focused on
> > >> DOCSIS and GPON MAC workloads. This allows these functions to be performed
> > >> in parallel by the Intel IPSec Multi Buffer library. These functions
> > >> include cryptography and CRC/BIP calculations. Performing these functions
> > >> in parallel as a single operation can enable a significant performance
> > >> improvement.
> > >
> > > I don't know crypto but I don't think using rawdev for crypto operations
> > > is an API improvement.
> > >
> > > Repeating the initial comments from v1 (because got no reply):
> > > "
> > > As a first impression, I feel it is not the right API.
> > > DPDK is based on classes: ethdev, crypto, compress, baseband, regex
> > > I want to understand why your features cannot fit in a class.
> >
> > Hi Thomas,
> >
> > I asked similar question, and there is already a detailed answer with some
> > background of the issue:
> 
> Good to see that you get some reply, Ferruh.
> 
> >
> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
> mprd11.prod.outlook.com/
> 
> I am not convinced.
> I don't like rawdev in general.
> Rawdev is good only for hardware support which cannot be generic
> like SoC, FPGA management or DMA engine.
[Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
So there is no class in DPDK that these readily fit into.
There was resistance to adding another xxxddev, and even if one had been added
for error_detection_dev, there would still have been another layer needed
to couple this with cryptodev. Various proposals for this have been discussed on the ML
in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API. 
So it seems that only Intel has software and hardware engines that provide this
specialised feature coupling. In that case rawdev seems like the most
appropriate vehicle to expose this.


> Here the intent is to use rawdev because we don't find a good API.
> API defeat is a no-go.
[Fiona] It's not that we haven't found a good API, but that there doesn't seem
to be a general requirement for such a specialised API
 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-14 13:04       ` Trahe, Fiona
@ 2020-04-14 13:24         ` Thomas Monjalon
  2020-04-14 14:02           ` Trahe, Fiona
  0 siblings, 1 reply; 92+ messages in thread
From: Thomas Monjalon @ 2020-04-14 13:24 UTC (permalink / raw)
  To: Yigit, Ferruh, Trahe, Fiona
  Cc: Coyle, David, dev, Doherty, Declan, De Lara Guarch, Pablo, Ryan,
	Brendan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar,
	Richardson, Bruce, Trahe, Fiona

14/04/2020 15:04, Trahe, Fiona:
> > 14/04/2020 12:21, Ferruh Yigit:
> > http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
> > mprd11.prod.outlook.com/
> > 
> > I am not convinced.
> > I don't like rawdev in general.
> > Rawdev is good only for hardware support which cannot be generic
> > like SoC, FPGA management or DMA engine.
> 
> [Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
> So there is no class in DPDK that these readily fit into.
> There was resistance to adding another xxxddev, and even if one had been added
> for error_detection_dev, there would still have been another layer needed
> to couple this with cryptodev. Various proposals for this have been discussed on the ML
> in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API. 
> So it seems that only Intel has software and hardware engines that provide this
> specialised feature coupling. In that case rawdev seems like the most
> appropriate vehicle to expose this.

Adding some vendor-specific API is not a good answer.
It will work in some cases, but it won't make DPDK better.
What's the purpose of DPDK if it's not solving a common problem
for different hardware?

> > Here the intent is to use rawdev because we don't find a good API.
> > API defeat is a no-go.
> 
> [Fiona] It's not that we haven't found a good API, but that there doesn't seem
> to be a general requirement for such a specialised API

There is a requirement to combine features of different classes.
In the past, rte_security was an "answer" to this issue with crypto and ethdev.
This is a real topic, please let's find a generic elegant solution.



^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-14 13:24         ` Thomas Monjalon
@ 2020-04-14 14:02           ` Trahe, Fiona
  2020-04-14 14:44             ` Thomas Monjalon
  0 siblings, 1 reply; 92+ messages in thread
From: Trahe, Fiona @ 2020-04-14 14:02 UTC (permalink / raw)
  To: Thomas Monjalon, Yigit, Ferruh
  Cc: Coyle, David, dev, Doherty, Declan, De Lara Guarch, Pablo, Ryan,
	Brendan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar,
	Richardson, Bruce, Trahe, Fiona

Hi Thomas,

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Tuesday, April 14, 2020 2:24 PM
> To: Yigit, Ferruh <ferruh.yigit@intel.com>; Trahe, Fiona <fiona.trahe@intel.com>
> Cc: Coyle, David <david.coyle@intel.com>; dev@dpdk.org; Doherty, Declan
> <declan.doherty@intel.com>; De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Ryan,
> Brendan <brendan.ryan@intel.com>; shreyansh.jain@nxp.com; hemant.agrawal@nxp.com;
> akhil.goyal@nxp.com; Anoob Joseph <anoobj@marvell.com>; Ruifeng Wang
> <ruifeng.wang@arm.com>; Liron Himi <lironh@marvell.com>; Nagadheeraj Rottela
> <rnagadheeraj@marvell.com>; Srikanth Jampala <jsrikanth@marvell.com>; Gagandeep Singh
> <g.singh@nxp.com>; Jay Zhou <jianjay.zhou@huawei.com>; Ravi Kumar <ravi1.kumar@amd.com>;
> Richardson, Bruce <bruce.richardson@intel.com>; Trahe, Fiona <fiona.trahe@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
> 
> 14/04/2020 15:04, Trahe, Fiona:
> > > 14/04/2020 12:21, Ferruh Yigit:
> > >
> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
> > > mprd11.prod.outlook.com/
> > >
> > > I am not convinced.
> > > I don't like rawdev in general.
> > > Rawdev is good only for hardware support which cannot be generic
> > > like SoC, FPGA management or DMA engine.
> >
> > [Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
> > So there is no class in DPDK that these readily fit into.
> > There was resistance to adding another xxxddev, and even if one had been added
> > for error_detection_dev, there would still have been another layer needed
> > to couple this with cryptodev. Various proposals for this have been discussed on the ML
> > in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API.
> > So it seems that only Intel has software and hardware engines that provide this
> > specialised feature coupling. In that case rawdev seems like the most
> > appropriate vehicle to expose this.
> 
> Adding some vendor-specific API is not a good answer.
> It will work in some cases, but it won't make DPDK better.
> What's the purpose of DPDK if it's not solving a common problem
> for different hardware?
[Fiona] Based on that logic rawdev should be deprecated.
But the community has agreed that it has a place.
And the common problem here is device exposure.
With a specialised service on top.


> > > Here the intent is to use rawdev because we don't find a good API.
> > > API defeat is a no-go.
> >
> > [Fiona] It's not that we haven't found a good API, but that there doesn't seem
> > to be a general requirement for such a specialised API
> 
> There is a requirement to combine features of different classes.
[Fiona] Can you point me to that requirement please?
We suggested it, but did not get community engagement and have 
dropped our generic API requirement, instead focussing on this specialised case.


> In the past, rte_security was an "answer" to this issue with crypto and ethdev.
> This is a real topic, please let's find a generic elegant solution.



^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-14 14:02           ` Trahe, Fiona
@ 2020-04-14 14:44             ` Thomas Monjalon
  2020-04-15 22:19               ` Doherty, Declan
  0 siblings, 1 reply; 92+ messages in thread
From: Thomas Monjalon @ 2020-04-14 14:44 UTC (permalink / raw)
  To: Yigit, Ferruh, Trahe, Fiona
  Cc: Coyle, David, dev, Doherty, Declan, De Lara Guarch, Pablo, Ryan,
	Brendan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar,
	Richardson, Bruce, Trahe, Fiona

14/04/2020 16:02, Trahe, Fiona:
> Hi Thomas,
> 
> From: Thomas Monjalon <thomas@monjalon.net>
> > 14/04/2020 15:04, Trahe, Fiona:
> > > > 14/04/2020 12:21, Ferruh Yigit:
> > > >
> > http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
> > > > mprd11.prod.outlook.com/
> > > >
> > > > I am not convinced.
> > > > I don't like rawdev in general.
> > > > Rawdev is good only for hardware support which cannot be generic
> > > > like SoC, FPGA management or DMA engine.
> > >
> > > [Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
> > > So there is no class in DPDK that these readily fit into.
> > > There was resistance to adding another xxxddev, and even if one had been added
> > > for error_detection_dev, there would still have been another layer needed
> > > to couple this with cryptodev. Various proposals for this have been discussed on the ML
> > > in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API.
> > > So it seems that only Intel has software and hardware engines that provide this
> > > specialised feature coupling. In that case rawdev seems like the most
> > > appropriate vehicle to expose this.
> > 
> > Adding some vendor-specific API is not a good answer.
> > It will work in some cases, but it won't make DPDK better.
> > What's the purpose of DPDK if it's not solving a common problem
> > for different hardware?
> 
> [Fiona] Based on that logic rawdev should be deprecated.
> But the community has agreed that it has a place.

No, as I said above, rawdev is good for SoC, FPGA management or DMA engine.

> And the common problem here is device exposure.
> With a specialised service on top.
> 
> 
> > > > Here the intent is to use rawdev because we don't find a good API.
> > > > API defeat is a no-go.
> > >
> > > [Fiona] It's not that we haven't found a good API, but that there doesn't seem
> > > to be a general requirement for such a specialised API
> > 
> > There is a requirement to combine features of different classes.
> 
> [Fiona] Can you point me to that requirement please?

Yes, rte_security is trying to address this exact issue.

> We suggested it, but did not get community engagement and have 
> dropped our generic API requirement, instead focussing on this specialised case.

I did not see such generic proposal, sorry.

> > In the past, rte_security was an "answer" to this issue with crypto and ethdev.
> > This is a real topic, please let's find a generic elegant solution.




^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-14 14:44             ` Thomas Monjalon
@ 2020-04-15 22:19               ` Doherty, Declan
  2020-04-15 22:33                 ` Thomas Monjalon
  0 siblings, 1 reply; 92+ messages in thread
From: Doherty, Declan @ 2020-04-15 22:19 UTC (permalink / raw)
  To: Thomas Monjalon, Yigit, Ferruh, Trahe, Fiona
  Cc: Coyle, David, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, Anoob Joseph,
	Ruifeng Wang, Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce

On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
> 14/04/2020 16:02, Trahe, Fiona:
>> Hi Thomas,
>>
>> From: Thomas Monjalon <thomas@monjalon.net>
>>> 14/04/2020 15:04, Trahe, Fiona:
>>>>> 14/04/2020 12:21, Ferruh Yigit:
>>>>>
>>> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
>>>>> mprd11.prod.outlook.com/
>>>>>
>>>>> I am not convinced.
>>>>> I don't like rawdev in general.
>>>>> Rawdev is good only for hardware support which cannot be generic
>>>>> like SoC, FPGA management or DMA engine.
>>>>
>>>> [Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
>>>> So there is no class in DPDK that these readily fit into.
>>>> There was resistance to adding another xxxddev, and even if one had been added
>>>> for error_detection_dev, there would still have been another layer needed
>>>> to couple this with cryptodev. Various proposals for this have been discussed on the ML
>>>> in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API.
>>>> So it seems that only Intel has software and hardware engines that provide this
>>>> specialised feature coupling. In that case rawdev seems like the most
>>>> appropriate vehicle to expose this.
>>>
>>> Adding some vendor-specific API is not a good answer.
>>> It will work in some cases, but it won't make DPDK better.
>>> What's the purpose of DPDK if it's not solving a common problem
>>> for different hardware?
>>
The current proposal in rawdev could easily be supported by any hardware 
which supports chaining multiple functions/services into a single 
operation, in this case symmetric crypto and error detection, but it 
could conceivably support chaining symmetric/asymmetric crypto 
operations or chaining symmetric crypto and compression operations.

>> [Fiona] Based on that logic rawdev should be deprecated.
>> But the community has agreed that it has a place.
> 
> No, as I said above, rawdev is good for SoC, FPGA management or DMA engine.

I distinctly remember when rawdev was being proposed one of the uses 
cases proposed was that a new classes of APIs could be prototyped and 
developed under rawdev and when a solid consensus was reached then 
migrated to a mainstream DPDK library. I think every effort has been 
made here to engage the community to develop a generic approach. As 
Fiona notes there hasn't really been much of an appetite for this.

Therefore I think the option to use rawdev makes sense, it allows an 
initial proposal to be deployed,  without a generic solution agreement, 
it will also give others in the community to see how this approach can 
work and hopefully lead to more engagement on a generic solution. Also 
as APIs in rawdev are essentially treated as private APIs the onus is on 
Intel to support this going forward.

> 
>> And the common problem here is device exposure.
>> With a specialised service on top.
>>
>>
>>>>> Here the intent is to use rawdev because we don't find a good API.
>>>>> API defeat is a no-go.
>>>>
>>>> [Fiona] It's not that we haven't found a good API, but that there doesn't seem
>>>> to be a general requirement for such a specialised API
>>>
>>> There is a requirement to combine features of different classes.
>>
>> [Fiona] Can you point me to that requirement please?
> 
> Yes, rte_security is trying to address this exact issue.
> 

I don't agree rte_security addresses the problem of different device 
types supporting the same services. The problem being addressed here is 
a single device which supports the chaining of multiple services (sym 
crypto & error detection)

>> We suggested it, but did not get community engagement and have
>> dropped our generic API requirement, instead focussing on this specialised case.
> 
> I did not see such generic proposal, sorry.
> 
>>> In the past, rte_security was an "answer" to this issue with crypto and ethdev.
>>> This is a real topic, please let's find a generic elegant solution.
> 
> 
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-15 22:19               ` Doherty, Declan
@ 2020-04-15 22:33                 ` Thomas Monjalon
  2020-04-21 16:46                   ` Doherty, Declan
  0 siblings, 1 reply; 92+ messages in thread
From: Thomas Monjalon @ 2020-04-15 22:33 UTC (permalink / raw)
  To: Yigit, Ferruh, Trahe, Fiona, Doherty, Declan
  Cc: Coyle, David, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, Anoob Joseph,
	Ruifeng Wang, Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, Stephen Hemminger, alexr

16/04/2020 00:19, Doherty, Declan:
> On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
> > 14/04/2020 16:02, Trahe, Fiona:
> >> From: Thomas Monjalon <thomas@monjalon.net>
> >>> 14/04/2020 15:04, Trahe, Fiona:
> >>>>> 14/04/2020 12:21, Ferruh Yigit:
> >>>>>
> >>> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
> >>>>> mprd11.prod.outlook.com/
> >>>>>
> >>>>> I am not convinced.
> >>>>> I don't like rawdev in general.
> >>>>> Rawdev is good only for hardware support which cannot be generic
> >>>>> like SoC, FPGA management or DMA engine.
> >>>>
> >>>> [Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
> >>>> So there is no class in DPDK that these readily fit into.
> >>>> There was resistance to adding another xxxddev, and even if one had been added
> >>>> for error_detection_dev, there would still have been another layer needed
> >>>> to couple this with cryptodev. Various proposals for this have been discussed on the ML
> >>>> in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API.
> >>>> So it seems that only Intel has software and hardware engines that provide this
> >>>> specialised feature coupling. In that case rawdev seems like the most
> >>>> appropriate vehicle to expose this.
> >>>
> >>> Adding some vendor-specific API is not a good answer.
> >>> It will work in some cases, but it won't make DPDK better.
> >>> What's the purpose of DPDK if it's not solving a common problem
> >>> for different hardware?
> >>
> The current proposal in rawdev could easily be supported by any hardware 
> which supports chaining multiple functions/services into a single 
> operation, in this case symmetric crypto and error detection, but it 
> could conceivably support chaining symmetric/asymmetric crypto 
> operations or chaining symmetric crypto and compression operations.
> 
> >> [Fiona] Based on that logic rawdev should be deprecated.
> >> But the community has agreed that it has a place.
> > 
> > No, as I said above, rawdev is good for SoC, FPGA management or DMA engine.
> 
> I distinctly remember when rawdev was being proposed one of the uses 
> cases proposed was that a new classes of APIs could be prototyped and 
> developed under rawdev and when a solid consensus was reached then 
> migrated to a mainstream DPDK library. I think every effort has been 
> made here to engage the community to develop a generic approach. As 
> Fiona notes there hasn't really been much of an appetite for this.
> 
> Therefore I think the option to use rawdev makes sense, it allows an 
> initial proposal to be deployed,  without a generic solution agreement, 
> it will also give others in the community to see how this approach can 
> work and hopefully lead to more engagement on a generic solution. Also 
> as APIs in rawdev are essentially treated as private APIs the onus is on 
> Intel to support this going forward.

Because hardware support is pending,
we should accept an Intel-only "temporary" solution,
opening the door to more vendor-specific APIs?

What is the benefit for the DPDK project?


> >> And the common problem here is device exposure.
> >> With a specialised service on top.
> >>
> >>
> >>>>> Here the intent is to use rawdev because we don't find a good API.
> >>>>> API defeat is a no-go.
> >>>>
> >>>> [Fiona] It's not that we haven't found a good API, but that there doesn't seem
> >>>> to be a general requirement for such a specialised API
> >>>
> >>> There is a requirement to combine features of different classes.
> >>
> >> [Fiona] Can you point me to that requirement please?
> > 
> > Yes, rte_security is trying to address this exact issue.
> > 
> 
> I don't agree rte_security addresses the problem of different device 
> types supporting the same services. The problem being addressed here is 
> a single device which supports the chaining of multiple services (sym 
> crypto & error detection)

Doing IPsec processing in Rx or Tx of a NIC is not chaining?


> >> We suggested it, but did not get community engagement and have
> >> dropped our generic API requirement, instead focussing on this specialised case.
> > 
> > I did not see such generic proposal, sorry.
> > 
> >>> In the past, rte_security was an "answer" to this issue with crypto and ethdev.
> >>> This is a real topic, please let's find a generic elegant solution.




^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-15 22:33                 ` Thomas Monjalon
@ 2020-04-21 16:46                   ` Doherty, Declan
  2020-04-21 17:23                     ` Coyle, David
  2020-04-21 17:25                     ` Thomas Monjalon
  0 siblings, 2 replies; 92+ messages in thread
From: Doherty, Declan @ 2020-04-21 16:46 UTC (permalink / raw)
  To: Thomas Monjalon, Yigit, Ferruh, Trahe, Fiona
  Cc: Coyle, David, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, Anoob Joseph,
	Ruifeng Wang, Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, Stephen Hemminger, alexr

On 15/04/2020 11:33 PM, Thomas Monjalon wrote:
> 16/04/2020 00:19, Doherty, Declan:
>> On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
>>> 14/04/2020 16:02, Trahe, Fiona:
>>>> From: Thomas Monjalon <thomas@monjalon.net>
>>>>> 14/04/2020 15:04, Trahe, Fiona:
>>>>>>> 14/04/2020 12:21, Ferruh Yigit:
>>>>>>>
>>>>> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
>>>>>>> mprd11.prod.outlook.com/
>>>>>>>
>>>>>>> I am not convinced.
>>>>>>> I don't like rawdev in general.
>>>>>>> Rawdev is good only for hardware support which cannot be generic
>>>>>>> like SoC, FPGA management or DMA engine.
>>>>>>
>>>>>> [Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
>>>>>> So there is no class in DPDK that these readily fit into.
>>>>>> There was resistance to adding another xxxddev, and even if one had been added
>>>>>> for error_detection_dev, there would still have been another layer needed
>>>>>> to couple this with cryptodev. Various proposals for this have been discussed on the ML
>>>>>> in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API.
>>>>>> So it seems that only Intel has software and hardware engines that provide this
>>>>>> specialised feature coupling. In that case rawdev seems like the most
>>>>>> appropriate vehicle to expose this.
>>>>>
>>>>> Adding some vendor-specific API is not a good answer.
>>>>> It will work in some cases, but it won't make DPDK better.
>>>>> What's the purpose of DPDK if it's not solving a common problem
>>>>> for different hardware?
>>>>
>> The current proposal in rawdev could easily be supported by any hardware
>> which supports chaining multiple functions/services into a single
>> operation, in this case symmetric crypto and error detection, but it
>> could conceivably support chaining symmetric/asymmetric crypto
>> operations or chaining symmetric crypto and compression operations.
>>
>>>> [Fiona] Based on that logic rawdev should be deprecated.
>>>> But the community has agreed that it has a place.
>>>
>>> No, as I said above, rawdev is good for SoC, FPGA management or DMA engine.
>>
>> I distinctly remember when rawdev was being proposed one of the uses
>> cases proposed was that a new classes of APIs could be prototyped and
>> developed under rawdev and when a solid consensus was reached then
>> migrated to a mainstream DPDK library. I think every effort has been
>> made here to engage the community to develop a generic approach. As
>> Fiona notes there hasn't really been much of an appetite for this.
>>
>> Therefore I think the option to use rawdev makes sense, it allows an
>> initial proposal to be deployed,  without a generic solution agreement,
>> it will also give others in the community to see how this approach can
>> work and hopefully lead to more engagement on a generic solution. Also
>> as APIs in rawdev are essentially treated as private APIs the onus is on
>> Intel to support this going forward.
> 
> Because hardware support is pending,
> we should accept an Intel-only "temporary" solution,
> opening the door to more vendor-specific APIs?
> 
> What is the benefit for the DPDK project?
> 
> 

Sorry I don't agree with this sentiment, David has made every attempt to 
solicit feedback an to engage the community in this.

I also don't agree in classifying this as a "temporary solution" as this 
is a solid proposal for an approach to chaining multiple operations 
together, but I guess the fact remains that we only currently have a 
single use-case, but it is difficult to generate a generic solution in 
this case.

While there is only a single use case it is targeting two devices so 
that drove the need for a common interface withing rawdev.

The advantage of using rawdev is that it allows this to be consumed 
through DPDK, which enables DPDK project consumers, but also leaves the 
door open to other contributors to have their say on how this should 
evolve. For example this exact process seems to be occurring with DMA 
engines in rawdev today, with a critical mass of implementations which 
now is giving the impetus to create a generic solution, as we would hope 
can occur here too in the future.


>>>> And the common problem here is device exposure.
>>>> With a specialised service on top.
>>>>
>>>>
>>>>>>> Here the intent is to use rawdev because we don't find a good API.
>>>>>>> API defeat is a no-go.
>>>>>>
>>>>>> [Fiona] It's not that we haven't found a good API, but that there doesn't seem
>>>>>> to be a general requirement for such a specialised API
>>>>>
>>>>> There is a requirement to combine features of different classes.
>>>>
>>>> [Fiona] Can you point me to that requirement please?
>>>
>>> Yes, rte_security is trying to address this exact issue.
>>>
>>
>> I don't agree rte_security addresses the problem of different device
>> types supporting the same services. The problem being addressed here is
>> a single device which supports the chaining of multiple services (sym
>> crypto & error detection)
> 
> Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> 
> 

I wouldn't consider an inline crypto offload or full IPsec offload a 
chained operation in the vein being proposed here where completely 
independent services (in the view of DPDK which are currently on 
independent devices and APIs) are linked together.

We did look at using rte_security here but it wasn't considered suitable 
for a chaining of non-crypto operations such as CRC or possibly 
compression in the future, as it would still run into the issue of 
having to use the cryptodev enq/deq API in the lookaside offload case.


>>>> We suggested it, but did not get community engagement and have
>>>> dropped our generic API requirement, instead focussing on this specialised case.
>>>
>>> I did not see such generic proposal, sorry.
>>>
>>>>> In the past, rte_security was an "answer" to this issue with crypto and ethdev.
>>>>> This is a real topic, please let's find a generic elegant solution.
> 
> 
> 

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-21 16:46                   ` Doherty, Declan
@ 2020-04-21 17:23                     ` Coyle, David
  2020-04-22 10:51                       ` Akhil Goyal
  2020-04-22 14:01                       ` Kevin Traynor
  2020-04-21 17:25                     ` Thomas Monjalon
  1 sibling, 2 replies; 92+ messages in thread
From: Coyle, David @ 2020-04-21 17:23 UTC (permalink / raw)
  To: Doherty, Declan, Thomas Monjalon, Yigit, Ferruh, Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, Anoob Joseph,
	Ruifeng Wang, Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, Stephen Hemminger, alexr

Thank you Thomas for your input.

We would like to request that the Tech-Board (CC'ed) also review the proposal to help us reach a consensus.
 
If the current proposal is not acceptable, we would welcome feedback from the board on how to rework our
proposal to something that would be acceptable.
 
For the benefit of the Tech-Board here is the back-ground to our proposal for Rawdev-based multi-function
processing:
- The primary objective is to support the AESNI MB combined Crypto-CRC processing capability in DPDK and
   in future to add support for combined Crypto-CRC support in QAT.
- The cryptodev API was considered unsuitable because CRC is not a cryptographic operation, and this would
   also preclude other non-crypto operations in the future such as compression.
- The rte_security API was also not considered suitable for chaining of non-crypto operations such as CRC,
   as Declan pointed out below.
- A new Accelerator API was proposed as an RFC but was not pursued due to community feedback that a
   new API would not be welcome for a single use-case.
- Using Rawdev for multi-function processing was then proposed and, initially, as there was no opposition
   we implemented a patch-set for this approach.
 
It was considered that a Rawdev-based multi-function approach would be suitable for the following reasons:
1) Multi-function processing for Crypto-CRC cases is not a good fit for any of the existing DPDK classes.
2) Rawdev was intended for such specialized acceleration processing that are not a good fit for existing DPDK
     classes.
3) Rawdev was also intended as somewhere that new use-cases like this could be prototyped and developed,
     such as Declan mentions below
4) The Rawdev-based multi-function proposal is extensible and we would hope that it can evolve to support
     new use-cases and target new devices in the future with the communities involvement.


> -----Original Message-----
> From: Doherty, Declan <declan.doherty@intel.com>
> Sent: Tuesday, April 21, 2020 5:46 PM
> 
> On 15/04/2020 11:33 PM, Thomas Monjalon wrote:
> > 16/04/2020 00:19, Doherty, Declan:
> >> On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
> >>> 14/04/2020 16:02, Trahe, Fiona:
> >>>> From: Thomas Monjalon <thomas@monjalon.net>
> >>>>> 14/04/2020 15:04, Trahe, Fiona:
> >>>>>>> 14/04/2020 12:21, Ferruh Yigit:
> >>>>>>>
> >>>>>
> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30
> @M
> >>>>> N2PR11MB3550.na
> >>>>>>> mprd11.prod.outlook.com/
> >>>>>>>
> >>>>>>> I am not convinced.
> >>>>>>> I don't like rawdev in general.
> >>>>>>> Rawdev is good only for hardware support which cannot be generic
> >>>>>>> like SoC, FPGA management or DMA engine.
> >>>>>>
> >>>>>> [Fiona] CRC and BIP are not crypto algorithms, they are error
> detection processes.
> >>>>>> So there is no class in DPDK that these readily fit into.
> >>>>>> There was resistance to adding another xxxddev, and even if one
> >>>>>> had been added for error_detection_dev, there would still have
> >>>>>> been another layer needed to couple this with cryptodev. Various
> >>>>>> proposals for this have been discussed on the ML in RFC and recent
> patches, there doesn't seem to be an appetite for this as a generic API.
> >>>>>> So it seems that only Intel has software and hardware engines
> >>>>>> that provide this specialised feature coupling. In that case
> >>>>>> rawdev seems like the most appropriate vehicle to expose this.
> >>>>>
> >>>>> Adding some vendor-specific API is not a good answer.
> >>>>> It will work in some cases, but it won't make DPDK better.
> >>>>> What's the purpose of DPDK if it's not solving a common problem
> >>>>> for different hardware?
> >>>>
> >> The current proposal in rawdev could easily be supported by any
> >> hardware which supports chaining multiple functions/services into a
> >> single operation, in this case symmetric crypto and error detection,
> >> but it could conceivably support chaining symmetric/asymmetric crypto
> >> operations or chaining symmetric crypto and compression operations.
> >>
> >>>> [Fiona] Based on that logic rawdev should be deprecated.
> >>>> But the community has agreed that it has a place.
> >>>
> >>> No, as I said above, rawdev is good for SoC, FPGA management or DMA
> engine.
> >>
> >> I distinctly remember when rawdev was being proposed one of the uses
> >> cases proposed was that a new classes of APIs could be prototyped and
> >> developed under rawdev and when a solid consensus was reached then
> >> migrated to a mainstream DPDK library. I think every effort has been
> >> made here to engage the community to develop a generic approach. As
> >> Fiona notes there hasn't really been much of an appetite for this.
> >>
> >> Therefore I think the option to use rawdev makes sense, it allows an
> >> initial proposal to be deployed,  without a generic solution
> >> agreement, it will also give others in the community to see how this
> >> approach can work and hopefully lead to more engagement on a generic
> >> solution. Also as APIs in rawdev are essentially treated as private
> >> APIs the onus is on Intel to support this going forward.
> >
> > Because hardware support is pending,
> > we should accept an Intel-only "temporary" solution, opening the door
> > to more vendor-specific APIs?
> >
> > What is the benefit for the DPDK project?
> >
> Sorry I don't agree with this sentiment, David has made every attempt to
> solicit feedback and to engage the community in this.
> 
> I also don't agree in classifying this as a "temporary solution" as this is a solid
> proposal for an approach to chaining multiple operations together, but I
> guess the fact remains that we only currently have a single use-case, but it is
> difficult to generate a generic solution in this case.
> 
> While there is only a single use case it is targeting two devices so that drove
> the need for a common interface within rawdev.
> 
> The advantage of using rawdev is that it allows this to be consumed through
> DPDK, which enables DPDK project consumers, but also leaves the door open
> to other contributors to have their say on how this should evolve. For
> example this exact process seems to be occurring with DMA engines in
> rawdev today, with a critical mass of implementations which now is giving the
> impetus to create a generic solution, as we would hope can occur here too in
> the future.
> 
> 
> >>>> And the common problem here is device exposure.
> >>>> With a specialised service on top.
> >>>>
> >>>>
> >>>>>>> Here the intent is to use rawdev because we don't find a good API.
> >>>>>>> API defeat is a no-go.
> >>>>>>
> >>>>>> [Fiona] It's not that we haven't found a good API, but that there
> >>>>>> doesn't seem to be a general requirement for such a specialised
> >>>>>> API
> >>>>>
> >>>>> There is a requirement to combine features of different classes.
> >>>>
> >>>> [Fiona] Can you point me to that requirement please?
> >>>
> >>> Yes, rte_security is trying to address this exact issue.
> >>>
> >>
> >> I don't agree rte_security addresses the problem of different device
> >> types supporting the same services. The problem being addressed here
> >> is a single device which supports the chaining of multiple services
> >> (sym crypto & error detection)
> >
> > Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> >
> I wouldn't consider an inline crypto offload or full IPsec offload a chained
> operation in the vein being proposed here where completely independent
> services (in the view of DPDK which are currently on independent devices
> and APIs) are linked together.
> 
> We did look at using rte_security here but it wasn't considered suitable for a
> chaining of non-crypto operations such as CRC or possibly compression in the
> future, as it would still run into the issue of having to use the cryptodev
> enq/deq API in the lookaside offload case.
> 
> 
> >>>> We suggested it, but did not get community engagement and have
> >>>> dropped our generic API requirement, instead focussing on this
> specialised case.
> >>>
> >>> I did not see such generic proposal, sorry.
> >>>
> >>>>> In the past, rte_security was an "answer" to this issue with crypto and
> ethdev.
> >>>>> This is a real topic, please let's find a generic elegant solution.
> >
> >
> >

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-21 16:46                   ` Doherty, Declan
  2020-04-21 17:23                     ` Coyle, David
@ 2020-04-21 17:25                     ` Thomas Monjalon
  2020-04-21 18:37                       ` Coyle, David
  1 sibling, 1 reply; 92+ messages in thread
From: Thomas Monjalon @ 2020-04-21 17:25 UTC (permalink / raw)
  To: Doherty, Declan, Coyle, David
  Cc: Yigit, Ferruh, Trahe, Fiona, dev, De Lara Guarch, Pablo, Ryan,
	Brendan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar,
	Richardson, Bruce, olivier.matz, honnappa.nagarahalli,
	Stephen Hemminger, alexr, jerinj, Pavan Nikhilesh

21/04/2020 18:46, Doherty, Declan:
> On 15/04/2020 11:33 PM, Thomas Monjalon wrote:
> > 16/04/2020 00:19, Doherty, Declan:
> >> On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
> >>> 14/04/2020 16:02, Trahe, Fiona:
> >>>> From: Thomas Monjalon <thomas@monjalon.net>
> >>>>> 14/04/2020 15:04, Trahe, Fiona:
> >>>>>>> 14/04/2020 12:21, Ferruh Yigit:
> >>>>>>>
> >>>>> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30@MN2PR11MB3550.na
> >>>>>>> mprd11.prod.outlook.com/
> >>>>>>>
> >>>>>>> I am not convinced.
> >>>>>>> I don't like rawdev in general.
> >>>>>>> Rawdev is good only for hardware support which cannot be generic
> >>>>>>> like SoC, FPGA management or DMA engine.
> >>>>>>
> >>>>>> [Fiona] CRC and BIP are not crypto algorithms, they are error detection processes.
> >>>>>> So there is no class in DPDK that these readily fit into.
> >>>>>> There was resistance to adding another xxxddev, and even if one had been added
> >>>>>> for error_detection_dev, there would still have been another layer needed
> >>>>>> to couple this with cryptodev. Various proposals for this have been discussed on the ML
> >>>>>> in RFC and recent patches, there doesn't seem to be an appetite for this as a generic API.
> >>>>>> So it seems that only Intel has software and hardware engines that provide this
> >>>>>> specialised feature coupling. In that case rawdev seems like the most
> >>>>>> appropriate vehicle to expose this.
> >>>>>
> >>>>> Adding some vendor-specific API is not a good answer.
> >>>>> It will work in some cases, but it won't make DPDK better.
> >>>>> What's the purpose of DPDK if it's not solving a common problem
> >>>>> for different hardware?
> >>>>
> >> The current proposal in rawdev could easily be supported by any hardware
> >> which supports chaining multiple functions/services into a single
> >> operation, in this case symmetric crypto and error detection, but it
> >> could conceivably support chaining symmetric/asymmetric crypto
> >> operations or chaining symmetric crypto and compression operations.
> >>
> >>>> [Fiona] Based on that logic rawdev should be deprecated.
> >>>> But the community has agreed that it has a place.
> >>>
> >>> No, as I said above, rawdev is good for SoC, FPGA management or DMA engine.
> >>
> >> I distinctly remember when rawdev was being proposed one of the uses
> >> cases proposed was that a new classes of APIs could be prototyped and
> >> developed under rawdev and when a solid consensus was reached then
> >> migrated to a mainstream DPDK library. I think every effort has been
> >> made here to engage the community to develop a generic approach. As
> >> Fiona notes there hasn't really been much of an appetite for this.
> >>
> >> Therefore I think the option to use rawdev makes sense, it allows an
> >> initial proposal to be deployed,  without a generic solution agreement,
> >> it will also give others in the community to see how this approach can
> >> work and hopefully lead to more engagement on a generic solution. Also
> >> as APIs in rawdev are essentially treated as private APIs the onus is on
> >> Intel to support this going forward.
> > 
> > Because hardware support is pending,
> > we should accept an Intel-only "temporary" solution,
> > opening the door to more vendor-specific APIs?
> > 
> > What is the benefit for the DPDK project?
> 
> Sorry I don't agree with this sentiment, David has made every attempt to 
> solicit feedback an to engage the community in this.

Really?

These are the recipients of the first patch:
	dev@dpdk.org, declan.doherty@intel.com, fiona.trahe@intel.com
In next patches, only Intel and NXP are Cc'ed.
Stephen and Jerin, who gave good comments on first patch,
were not Cc'ed in next versions.

Was it presented in an event?
Was it brought to the techboard?
Please don't exagerate and admit you are trying to push something
which is specific and convenient for Intel QuickAssist.


> I also don't agree in classifying this as a "temporary solution" as this 
> is a solid proposal for an approach to chaining multiple operations 
> together, but I guess the fact remains that we only currently have a 
> single use-case, but it is difficult to generate a generic solution in 
> this case.
> 
> While there is only a single use case it is targeting two devices so 
> that drove the need for a common interface withing rawdev.
> 
> The advantage of using rawdev is that it allows this to be consumed 
> through DPDK, which enables DPDK project consumers, but also leaves the 
> door open to other contributors to have their say on how this should 
> evolve. For example this exact process seems to be occurring with DMA 
> engines in rawdev today, with a critical mass of implementations which 
> now is giving the impetus to create a generic solution, as we would hope 
> can occur here too in the future.
> 
> 
> >>>> And the common problem here is device exposure.
> >>>> With a specialised service on top.
> >>>>
> >>>>
> >>>>>>> Here the intent is to use rawdev because we don't find a good API.
> >>>>>>> API defeat is a no-go.
> >>>>>>
> >>>>>> [Fiona] It's not that we haven't found a good API, but that there doesn't seem
> >>>>>> to be a general requirement for such a specialised API
> >>>>>
> >>>>> There is a requirement to combine features of different classes.
> >>>>
> >>>> [Fiona] Can you point me to that requirement please?
> >>>
> >>> Yes, rte_security is trying to address this exact issue.
> >>>
> >>
> >> I don't agree rte_security addresses the problem of different device
> >> types supporting the same services. The problem being addressed here is
> >> a single device which supports the chaining of multiple services (sym
> >> crypto & error detection)
> > 
> > Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> 
> I wouldn't consider an inline crypto offload or full IPsec offload a 
> chained operation in the vein being proposed here where completely 
> independent services (in the view of DPDK which are currently on 
> independent devices and APIs) are linked together.
> 
> We did look at using rte_security here but it wasn't considered suitable 
> for a chaining of non-crypto operations such as CRC or possibly 
> compression in the future, as it would still run into the issue of 
> having to use the cryptodev enq/deq API in the lookaside offload case.

Because rte_security is not a generic solution (that's why I don't like it).
I think a good approach would be to check how to offload in HW
the chaining done in frameworks like rte_pipeline or rte_graph.
Stephen and Jerin already talked about it, but it was rejected by David,
because harder to implement I think.
Even worst, the team working on this patch did zero review of rte_graph.

I think the chaining requirement is a real problem to solve,
and it deserves a good architecture and API.
Maybe this future API should be based on rte_graph.



^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-21 17:25                     ` Thomas Monjalon
@ 2020-04-21 18:37                       ` Coyle, David
  2020-04-21 21:51                         ` Thomas Monjalon
  0 siblings, 1 reply; 92+ messages in thread
From: Coyle, David @ 2020-04-21 18:37 UTC (permalink / raw)
  To: Thomas Monjalon, Doherty, Declan
  Cc: Yigit, Ferruh, Trahe, Fiona, dev, De Lara Guarch, Pablo, Ryan,
	Brendan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar,
	Richardson, Bruce, olivier.matz, honnappa.nagarahalli,
	Stephen Hemminger, alexr, jerinj, Pavan Nikhilesh

> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Tuesday, April 21, 2020 6:25 PM
 [PATCH v3 0/4] add AESNI-MB rawdev for multi-
> function processing
> 
> 21/04/2020 18:46, Doherty, Declan:
> > On 15/04/2020 11:33 PM, Thomas Monjalon wrote:
> > > 16/04/2020 00:19, Doherty, Declan:
> > >> On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
> > >>> 14/04/2020 16:02, Trahe, Fiona:
> > >>>> From: Thomas Monjalon <thomas@monjalon.net>
> > >>>>> 14/04/2020 15:04, Trahe, Fiona:
> > >>>>>>> 14/04/2020 12:21, Ferruh Yigit:
> > >>>>>>>
> > >>>>>
> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30
> > >>>>> @MN2PR11MB3550.na
> > >>>>>>> mprd11.prod.outlook.com/
> > >>>>>>>
> > >>>>>>> I am not convinced.
> > >>>>>>> I don't like rawdev in general.
> > >>>>>>> Rawdev is good only for hardware support which cannot be
> > >>>>>>> generic like SoC, FPGA management or DMA engine.
> > >>>>>>
> > >>>>>> [Fiona] CRC and BIP are not crypto algorithms, they are error
> detection processes.
> > >>>>>> So there is no class in DPDK that these readily fit into.
> > >>>>>> There was resistance to adding another xxxddev, and even if one
> > >>>>>> had been added for error_detection_dev, there would still have
> > >>>>>> been another layer needed to couple this with cryptodev.
> > >>>>>> Various proposals for this have been discussed on the ML in RFC
> and recent patches, there doesn't seem to be an appetite for this as a
> generic API.
> > >>>>>> So it seems that only Intel has software and hardware engines
> > >>>>>> that provide this specialised feature coupling. In that case
> > >>>>>> rawdev seems like the most appropriate vehicle to expose this.
> > >>>>>
> > >>>>> Adding some vendor-specific API is not a good answer.
> > >>>>> It will work in some cases, but it won't make DPDK better.
> > >>>>> What's the purpose of DPDK if it's not solving a common problem
> > >>>>> for different hardware?
> > >>>>
> > >> The current proposal in rawdev could easily be supported by any
> > >> hardware which supports chaining multiple functions/services into a
> > >> single operation, in this case symmetric crypto and error
> > >> detection, but it could conceivably support chaining
> > >> symmetric/asymmetric crypto operations or chaining symmetric crypto
> and compression operations.
> > >>
> > >>>> [Fiona] Based on that logic rawdev should be deprecated.
> > >>>> But the community has agreed that it has a place.
> > >>>
> > >>> No, as I said above, rawdev is good for SoC, FPGA management or
> DMA engine.
> > >>
> > >> I distinctly remember when rawdev was being proposed one of the
> > >> uses cases proposed was that a new classes of APIs could be
> > >> prototyped and developed under rawdev and when a solid consensus
> > >> was reached then migrated to a mainstream DPDK library. I think
> > >> every effort has been made here to engage the community to develop
> > >> a generic approach. As Fiona notes there hasn't really been much of an
> appetite for this.
> > >>
> > >> Therefore I think the option to use rawdev makes sense, it allows
> > >> an initial proposal to be deployed,  without a generic solution
> > >> agreement, it will also give others in the community to see how
> > >> this approach can work and hopefully lead to more engagement on a
> > >> generic solution. Also as APIs in rawdev are essentially treated as
> > >> private APIs the onus is on Intel to support this going forward.
> > >
> > > Because hardware support is pending, we should accept an Intel-only
> > > "temporary" solution, opening the door to more vendor-specific APIs?
> > >
> > > What is the benefit for the DPDK project?
> >
> > Sorry I don't agree with this sentiment, David has made every attempt
> > to solicit feedback an to engage the community in this.
> 
> Really?
> 
> These are the recipients of the first patch:
> 	dev@dpdk.org, declan.doherty@intel.com, fiona.trahe@intel.com In
> next patches, only Intel and NXP are Cc'ed.
> Stephen and Jerin, who gave good comments on first patch, were not Cc'ed
> in next versions.
> 
> Was it presented in an event?
> Was it brought to the techboard?
> Please don't exagerate and admit you are trying to push something which is
> specific and convenient for Intel QuickAssist.

[DC] This is being brought to the TechBoard tomorrow (22/04)

> 
> 
> > I also don't agree in classifying this as a "temporary solution" as
> > this is a solid proposal for an approach to chaining multiple
> > operations together, but I guess the fact remains that we only
> > currently have a single use-case, but it is difficult to generate a
> > generic solution in this case.
> >
> > While there is only a single use case it is targeting two devices so
> > that drove the need for a common interface withing rawdev.
> >
> > The advantage of using rawdev is that it allows this to be consumed
> > through DPDK, which enables DPDK project consumers, but also leaves
> > the door open to other contributors to have their say on how this
> > should evolve. For example this exact process seems to be occurring
> > with DMA engines in rawdev today, with a critical mass of
> > implementations which now is giving the impetus to create a generic
> > solution, as we would hope can occur here too in the future.
> >
> >
> > >>>> And the common problem here is device exposure.
> > >>>> With a specialised service on top.
> > >>>>
> > >>>>
> > >>>>>>> Here the intent is to use rawdev because we don't find a good
> API.
> > >>>>>>> API defeat is a no-go.
> > >>>>>>
> > >>>>>> [Fiona] It's not that we haven't found a good API, but that
> > >>>>>> there doesn't seem to be a general requirement for such a
> > >>>>>> specialised API
> > >>>>>
> > >>>>> There is a requirement to combine features of different classes.
> > >>>>
> > >>>> [Fiona] Can you point me to that requirement please?
> > >>>
> > >>> Yes, rte_security is trying to address this exact issue.
> > >>>
> > >>
> > >> I don't agree rte_security addresses the problem of different
> > >> device types supporting the same services. The problem being
> > >> addressed here is a single device which supports the chaining of
> > >> multiple services (sym crypto & error detection)
> > >
> > > Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> >
> > I wouldn't consider an inline crypto offload or full IPsec offload a
> > chained operation in the vein being proposed here where completely
> > independent services (in the view of DPDK which are currently on
> > independent devices and APIs) are linked together.
> >
> > We did look at using rte_security here but it wasn't considered
> > suitable for a chaining of non-crypto operations such as CRC or
> > possibly compression in the future, as it would still run into the
> > issue of having to use the cryptodev enq/deq API in the lookaside offload
> case.
> 
> Because rte_security is not a generic solution (that's why I don't like it).
> I think a good approach would be to check how to offload in HW the chaining
> done in frameworks like rte_pipeline or rte_graph.
> Stephen and Jerin already talked about it, but it was rejected by David,
> because harder to implement I think.
> Even worst, the team working on this patch did zero review of rte_graph.

[DC] The team working on this patch did review rte_graph and explained our reasoning
to Jerin as to why we felt it was not suitable.

While Jerin explained it would be possible to combine 2 nodes as a single optimized node at runtime,
he also agreed that it did NOT make sense to abstract what we are trying to do as a graph.

Please see http://mails.dpdk.org/archives/dev/2020-March/159238.html

> 
> I think the chaining requirement is a real problem to solve, and it deserves a
> good architecture and API.
> Maybe this future API should be based on rte_graph.
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-21 18:37                       ` Coyle, David
@ 2020-04-21 21:51                         ` Thomas Monjalon
  0 siblings, 0 replies; 92+ messages in thread
From: Thomas Monjalon @ 2020-04-21 21:51 UTC (permalink / raw)
  To: Doherty, Declan, Coyle, David
  Cc: Yigit, Ferruh, Trahe, Fiona, dev, De Lara Guarch, Pablo, Ryan,
	Brendan, shreyansh.jain, hemant.agrawal, akhil.goyal,
	Anoob Joseph, Ruifeng Wang, Liron Himi, Nagadheeraj Rottela,
	Srikanth Jampala, Gagandeep Singh, Jay Zhou, Ravi Kumar,
	Richardson, Bruce, olivier.matz, honnappa.nagarahalli,
	Stephen Hemminger, alexr, jerinj, Pavan Nikhilesh

21/04/2020 20:37, Coyle, David:
> From: Thomas Monjalon <thomas@monjalon.net>
> > 21/04/2020 18:46, Doherty, Declan:
> > > On 15/04/2020 11:33 PM, Thomas Monjalon wrote:
> > > > 16/04/2020 00:19, Doherty, Declan:
> > > >> On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
> > > >>> 14/04/2020 16:02, Trahe, Fiona:
> > > >>>> From: Thomas Monjalon <thomas@monjalon.net>
> > > >>>>> 14/04/2020 15:04, Trahe, Fiona:
> > > >>>>>>> 14/04/2020 12:21, Ferruh Yigit:
> > > >>>>>>>
> > > >>>>>
> > http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30
> > > >>>>> @MN2PR11MB3550.na
> > > >>>>>>> mprd11.prod.outlook.com/
> > > >>>>>>>
> > > >>>>>>> I am not convinced.
> > > >>>>>>> I don't like rawdev in general.
> > > >>>>>>> Rawdev is good only for hardware support which cannot be
> > > >>>>>>> generic like SoC, FPGA management or DMA engine.
> > > >>>>>>
> > > >>>>>> [Fiona] CRC and BIP are not crypto algorithms, they are error
> > detection processes.
> > > >>>>>> So there is no class in DPDK that these readily fit into.
> > > >>>>>> There was resistance to adding another xxxddev, and even if one
> > > >>>>>> had been added for error_detection_dev, there would still have
> > > >>>>>> been another layer needed to couple this with cryptodev.
> > > >>>>>> Various proposals for this have been discussed on the ML in RFC
> > and recent patches, there doesn't seem to be an appetite for this as a
> > generic API.
> > > >>>>>> So it seems that only Intel has software and hardware engines
> > > >>>>>> that provide this specialised feature coupling. In that case
> > > >>>>>> rawdev seems like the most appropriate vehicle to expose this.
> > > >>>>>
> > > >>>>> Adding some vendor-specific API is not a good answer.
> > > >>>>> It will work in some cases, but it won't make DPDK better.
> > > >>>>> What's the purpose of DPDK if it's not solving a common problem
> > > >>>>> for different hardware?
> > > >>>>
> > > >> The current proposal in rawdev could easily be supported by any
> > > >> hardware which supports chaining multiple functions/services into a
> > > >> single operation, in this case symmetric crypto and error
> > > >> detection, but it could conceivably support chaining
> > > >> symmetric/asymmetric crypto operations or chaining symmetric crypto
> > and compression operations.
> > > >>
> > > >>>> [Fiona] Based on that logic rawdev should be deprecated.
> > > >>>> But the community has agreed that it has a place.
> > > >>>
> > > >>> No, as I said above, rawdev is good for SoC, FPGA management or
> > DMA engine.
> > > >>
> > > >> I distinctly remember when rawdev was being proposed one of the
> > > >> uses cases proposed was that a new classes of APIs could be
> > > >> prototyped and developed under rawdev and when a solid consensus
> > > >> was reached then migrated to a mainstream DPDK library. I think
> > > >> every effort has been made here to engage the community to develop
> > > >> a generic approach. As Fiona notes there hasn't really been much of an
> > appetite for this.
> > > >>
> > > >> Therefore I think the option to use rawdev makes sense, it allows
> > > >> an initial proposal to be deployed,  without a generic solution
> > > >> agreement, it will also give others in the community to see how
> > > >> this approach can work and hopefully lead to more engagement on a
> > > >> generic solution. Also as APIs in rawdev are essentially treated as
> > > >> private APIs the onus is on Intel to support this going forward.
> > > >
> > > > Because hardware support is pending, we should accept an Intel-only
> > > > "temporary" solution, opening the door to more vendor-specific APIs?
> > > >
> > > > What is the benefit for the DPDK project?
> > >
> > > Sorry I don't agree with this sentiment, David has made every attempt
> > > to solicit feedback an to engage the community in this.
> > 
> > Really?
> > 
> > These are the recipients of the first patch:
> > 	dev@dpdk.org, declan.doherty@intel.com, fiona.trahe@intel.com In
> > next patches, only Intel and NXP are Cc'ed.
> > Stephen and Jerin, who gave good comments on first patch, were not Cc'ed
> > in next versions.
> > 
> > Was it presented in an event?
> > Was it brought to the techboard?
> > Please don't exagerate and admit you are trying to push something which is
> > specific and convenient for Intel QuickAssist.
> 
> [DC] This is being brought to the TechBoard tomorrow (22/04)
> 
> > 
> > 
> > > I also don't agree in classifying this as a "temporary solution" as
> > > this is a solid proposal for an approach to chaining multiple
> > > operations together, but I guess the fact remains that we only
> > > currently have a single use-case, but it is difficult to generate a
> > > generic solution in this case.
> > >
> > > While there is only a single use case it is targeting two devices so
> > > that drove the need for a common interface withing rawdev.
> > >
> > > The advantage of using rawdev is that it allows this to be consumed
> > > through DPDK, which enables DPDK project consumers, but also leaves
> > > the door open to other contributors to have their say on how this
> > > should evolve. For example this exact process seems to be occurring
> > > with DMA engines in rawdev today, with a critical mass of
> > > implementations which now is giving the impetus to create a generic
> > > solution, as we would hope can occur here too in the future.
> > >
> > >
> > > >>>> And the common problem here is device exposure.
> > > >>>> With a specialised service on top.
> > > >>>>
> > > >>>>
> > > >>>>>>> Here the intent is to use rawdev because we don't find a good
> > API.
> > > >>>>>>> API defeat is a no-go.
> > > >>>>>>
> > > >>>>>> [Fiona] It's not that we haven't found a good API, but that
> > > >>>>>> there doesn't seem to be a general requirement for such a
> > > >>>>>> specialised API
> > > >>>>>
> > > >>>>> There is a requirement to combine features of different classes.
> > > >>>>
> > > >>>> [Fiona] Can you point me to that requirement please?
> > > >>>
> > > >>> Yes, rte_security is trying to address this exact issue.
> > > >>>
> > > >>
> > > >> I don't agree rte_security addresses the problem of different
> > > >> device types supporting the same services. The problem being
> > > >> addressed here is a single device which supports the chaining of
> > > >> multiple services (sym crypto & error detection)
> > > >
> > > > Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> > >
> > > I wouldn't consider an inline crypto offload or full IPsec offload a
> > > chained operation in the vein being proposed here where completely
> > > independent services (in the view of DPDK which are currently on
> > > independent devices and APIs) are linked together.
> > >
> > > We did look at using rte_security here but it wasn't considered
> > > suitable for a chaining of non-crypto operations such as CRC or
> > > possibly compression in the future, as it would still run into the
> > > issue of having to use the cryptodev enq/deq API in the lookaside offload
> > case.
> > 
> > Because rte_security is not a generic solution (that's why I don't like it).
> > I think a good approach would be to check how to offload in HW the chaining
> > done in frameworks like rte_pipeline or rte_graph.
> > Stephen and Jerin already talked about it, but it was rejected by David,
> > because harder to implement I think.
> > Even worst, the team working on this patch did zero review of rte_graph.
> 
> [DC] The team working on this patch did review rte_graph and explained our reasoning
> to Jerin as to why we felt it was not suitable.

No, by review, I mean doing some comments in the rte_graph series
to help making the code, design or doc better.
You are complaining about the lack of attention to your patch,
that's why I point out that you didn't help other patches to progress.

> While Jerin explained it would be possible to combine 2 nodes as a single optimized node at runtime,
> he also agreed that it did NOT make sense to abstract what we are trying to do as a graph.

I think this exact point requires more discussion.

> Please see http://mails.dpdk.org/archives/dev/2020-March/159238.html

He did not say "it does not make sense" but
"In that way, it makes sense to not abstract as a graph."
This is slightly different.
Anyway, we should re-consider using a graph abstraction for chaining.

> > I think the chaining requirement is a real problem to solve, and it deserves a
> > good architecture and API.
> > Maybe this future API should be based on rte_graph.




^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-21 17:23                     ` Coyle, David
@ 2020-04-22 10:51                       ` Akhil Goyal
  2020-04-22 13:17                         ` Coyle, David
  2020-04-22 14:01                       ` Kevin Traynor
  1 sibling, 1 reply; 92+ messages in thread
From: Akhil Goyal @ 2020-04-22 10:51 UTC (permalink / raw)
  To: Coyle, David, Doherty, Declan, Thomas Monjalon, Yigit, Ferruh,
	Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, Hemant Agrawal, Anoob Joseph, Ruifeng Wang,
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, Stephen Hemminger, alexr

Hi David,
> > >>
> > >> I don't agree rte_security addresses the problem of different device
> > >> types supporting the same services. The problem being addressed here
> > >> is a single device which supports the chaining of multiple services
> > >> (sym crypto & error detection)
> > >
> > > Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> > >
> > I wouldn't consider an inline crypto offload or full IPsec offload a chained
> > operation in the vein being proposed here where completely independent
> > services (in the view of DPDK which are currently on independent devices
> > and APIs) are linked together.
> >
> > We did look at using rte_security here but it wasn't considered suitable for a
> > chaining of non-crypto operations such as CRC or possibly compression in the
> > future, as it would still run into the issue of having to use the cryptodev
> > enq/deq API in the lookaside offload case.
> >
> >
I did not look at your patches completely, but looking at the ops that you have added
For rawdev are pretty much same as that of a crypto device.

I see that there are 2 types of ops that you need
- session create/destroy
- enq/deq

On the first impression of your patchset, I see that you want to enq to driver only once for both
The operations - CRC and crypto.

So what is the issue in using the cryptodev_enqueue for processing in the existing AESNI-MB driver.
For session creation, the cryptodev layer will not give flexibility to add CRC+crypto kind of sessions.
But in case of rte_security, you can define your new session xform based on your requirement.

And while doing the cryptodev enq/deq, based on the session type, you can process the packet
Specific to your usecase in your aesni-mb PMD

Now if you want to add compression also along with crypto, then you can define another xform which
Will be combination of crypto+compression and the aesni-mb PMD can have another mode which
Can make sessions based on the new xform and the enq and deq can be done using the cryptodev enq/deq.
For all your cases you will be having only one action type - lookaside protocol and can define different
Protocols (that may not be standard).

So to conclude, your AESNI-MB will have 3 types of operations
- plain crypto
- crc+crypto
- compression+crypto

I believe this is doable or did I miss something very obvious?

Regards,
Akhil


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-22 10:51                       ` Akhil Goyal
@ 2020-04-22 13:17                         ` Coyle, David
  2020-04-22 13:44                           ` Akhil Goyal
  0 siblings, 1 reply; 92+ messages in thread
From: Coyle, David @ 2020-04-22 13:17 UTC (permalink / raw)
  To: Akhil Goyal, Doherty, Declan, Thomas Monjalon, Yigit, Ferruh,
	Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, Hemant Agrawal, Anoob Joseph, Ruifeng Wang,
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, Stephen Hemminger, alexr

Hi Akhil,

> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Wednesday, April 22, 2020 11:51 AM 
> Hi David,
> > > >>
> > > >> I don't agree rte_security addresses the problem of different
> > > >> device types supporting the same services. The problem being
> > > >> addressed here is a single device which supports the chaining of
> > > >> multiple services (sym crypto & error detection)
> > > >
> > > > Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> > > >
> > > I wouldn't consider an inline crypto offload or full IPsec offload a
> > > chained operation in the vein being proposed here where completely
> > > independent services (in the view of DPDK which are currently on
> > > independent devices and APIs) are linked together.
> > >
> > > We did look at using rte_security here but it wasn't considered
> > > suitable for a chaining of non-crypto operations such as CRC or
> > > possibly compression in the future, as it would still run into the
> > > issue of having to use the cryptodev enq/deq API in the lookaside offload
> case.
> > >
> > >
> I did not look at your patches completely, but looking at the ops that you
> have added For rawdev are pretty much same as that of a crypto device.
> 
> I see that there are 2 types of ops that you need
> - session create/destroy
> - enq/deq
> 
> On the first impression of your patchset, I see that you want to enq to driver
> only once for both The operations - CRC and crypto.
> 
> So what is the issue in using the cryptodev_enqueue for processing in the
> existing AESNI-MB driver.
> For session creation, the cryptodev layer will not give flexibility to add
> CRC+crypto kind of sessions.
> But in case of rte_security, you can define your new session xform based on
> your requirement.
> 
> And while doing the cryptodev enq/deq, based on the session type, you can
> process the packet Specific to your usecase in your aesni-mb PMD
> 
> Now if you want to add compression also along with crypto, then you can
> define another xform which Will be combination of crypto+compression and
> the aesni-mb PMD can have another mode which Can make sessions based
> on the new xform and the enq and deq can be done using the cryptodev
> enq/deq.
> For all your cases you will be having only one action type - lookaside protocol
> and can define different Protocols (that may not be standard).
> 
> So to conclude, your AESNI-MB will have 3 types of operations
> - plain crypto
> - crc+crypto
> - compression+crypto
> 
> I believe this is doable or did I miss something very obvious?

[DC] Thank you for this feedback

I have done this exact same analysis on rte_security and how we could use it.

The main issue of this approach (and it may be possible to easily overcome) is that ultimately crypto_op's need
to be enqueued into cryptodev. This means we can't easily control the CRC (or compression in the future) at the
operation level - application developers using this API would create a Crypto+CRC security xform session  for a
particular flow but may want to turn off the CRC part for some packets in that flow.

There are a number of ways this issue could possibly be overcome:
1) the auth offset/length fields in a rte_crypto_op could be overloaded to control the CRC part of the combined operation
    - this is not the cleanest approach
2) we add a "security" op struct of some type to the union at end of the rte_crypto_op
    - to avoid any circular dependencies, this would need to be opaque to rte_cryptodev
    - rte_cryptodev should not be aware of rte_security

Number 2 above is probably the cleaner and more preferable approach.

The other approach is that CRC is either on/off at the session level. That limitation would then need to be adhered
by application developers, which is something we would ideally like to avoid.

The rawdev multi-function approach did not have these issues which is one of the reasons we have pursued this
approach to date.

However, we think the rte_security approach is workable.
It still requires some deeper analysis but with your support, we think we can overcome the challenges.

> 
> Regards,
> Akhil


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-22 13:17                         ` Coyle, David
@ 2020-04-22 13:44                           ` Akhil Goyal
  2020-04-22 14:21                             ` Coyle, David
  2020-05-01 13:18                             ` Zhang, Roy Fan
  0 siblings, 2 replies; 92+ messages in thread
From: Akhil Goyal @ 2020-04-22 13:44 UTC (permalink / raw)
  To: Coyle, David, Doherty, Declan, Thomas Monjalon, Yigit, Ferruh,
	Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	Hemant Agrawal, Anoob Joseph, Ruifeng Wang, Liron Himi,
	Nagadheeraj Rottela, Srikanth Jampala, Gagandeep Singh, Jay Zhou,
	Ravi Kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, Stephen Hemminger, alexr

Hi David,
> Hi Akhil,
> 
> > -----Original Message-----
> > From: Akhil Goyal <akhil.goyal@nxp.com>
> > Sent: Wednesday, April 22, 2020 11:51 AM
> > Hi David,
> > > > >>
> > > > >> I don't agree rte_security addresses the problem of different
> > > > >> device types supporting the same services. The problem being
> > > > >> addressed here is a single device which supports the chaining of
> > > > >> multiple services (sym crypto & error detection)
> > > > >
> > > > > Doing IPsec processing in Rx or Tx of a NIC is not chaining?
> > > > >
> > > > I wouldn't consider an inline crypto offload or full IPsec offload a
> > > > chained operation in the vein being proposed here where completely
> > > > independent services (in the view of DPDK which are currently on
> > > > independent devices and APIs) are linked together.
> > > >
> > > > We did look at using rte_security here but it wasn't considered
> > > > suitable for a chaining of non-crypto operations such as CRC or
> > > > possibly compression in the future, as it would still run into the
> > > > issue of having to use the cryptodev enq/deq API in the lookaside offload
> > case.
> > > >
> > > >
> > I did not look at your patches completely, but looking at the ops that you
> > have added For rawdev are pretty much same as that of a crypto device.
> >
> > I see that there are 2 types of ops that you need
> > - session create/destroy
> > - enq/deq
> >
> > On the first impression of your patchset, I see that you want to enq to driver
> > only once for both The operations - CRC and crypto.
> >
> > So what is the issue in using the cryptodev_enqueue for processing in the
> > existing AESNI-MB driver.
> > For session creation, the cryptodev layer will not give flexibility to add
> > CRC+crypto kind of sessions.
> > But in case of rte_security, you can define your new session xform based on
> > your requirement.
> >
> > And while doing the cryptodev enq/deq, based on the session type, you can
> > process the packet Specific to your usecase in your aesni-mb PMD
> >
> > Now if you want to add compression also along with crypto, then you can
> > define another xform which Will be combination of crypto+compression and
> > the aesni-mb PMD can have another mode which Can make sessions based
> > on the new xform and the enq and deq can be done using the cryptodev
> > enq/deq.
> > For all your cases you will be having only one action type - lookaside protocol
> > and can define different Protocols (that may not be standard).
> >
> > So to conclude, your AESNI-MB will have 3 types of operations
> > - plain crypto
> > - crc+crypto
> > - compression+crypto
> >
> > I believe this is doable or did I miss something very obvious?
> 
> [DC] Thank you for this feedback
> 
> I have done this exact same analysis on rte_security and how we could use it.
> 
> The main issue of this approach (and it may be possible to easily overcome) is
> that ultimately crypto_op's need
> to be enqueued into cryptodev. This means we can't easily control the CRC (or
> compression in the future) at the
> operation level - application developers using this API would create a
> Crypto+CRC security xform session  for a
> particular flow but may want to turn off the CRC part for some packets in that
> flow.
> 
> There are a number of ways this issue could possibly be overcome:
> 1) the auth offset/length fields in a rte_crypto_op could be overloaded to
> control the CRC part of the combined operation
>     - this is not the cleanest approach
> 2) we add a "security" op struct of some type to the union at end of the
> rte_crypto_op
>     - to avoid any circular dependencies, this would need to be opaque to
> rte_cryptodev
>     - rte_cryptodev should not be aware of rte_security
> 
> Number 2 above is probably the cleaner and more preferable approach.

Yes, it is preferred, but it should be a union to rte_crypto_sym_op/rte_crypto_asym_op.
Crypto_op->type as RTE_CRYPTO_OP_TYPE_SECURITY and sess_type as
RTE_CRYPTO_OP_SECURITY_SESSION
The size of rte_crypto_op will remain as is and there will be no ABI breakage I guess.

One more thing that can be looked into is the recently added CPU crypto process API
If that could of any use, we may extend that if need be.

> 
> The other approach is that CRC is either on/off at the session level. That
> limitation would then need to be adhered
> by application developers, which is something we would ideally like to avoid.

You mean that CRC can be on/off per session as well as per packet?
I think that can also be handled when you are defining your own security_op for per packet.

> 
> The rawdev multi-function approach did not have these issues which is one of
> the reasons we have pursued this
> approach to date.
> 
> However, we think the rte_security approach is workable.
> It still requires some deeper analysis but with your support, we think we can
> overcome the challenges.
> 
Yes, please let me know where ever my help is required.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-21 17:23                     ` Coyle, David
  2020-04-22 10:51                       ` Akhil Goyal
@ 2020-04-22 14:01                       ` Kevin Traynor
  2020-04-22 14:41                         ` Coyle, David
  1 sibling, 1 reply; 92+ messages in thread
From: Kevin Traynor @ 2020-04-22 14:01 UTC (permalink / raw)
  To: Coyle, David, Doherty, Declan, Thomas Monjalon, Yigit, Ferruh,
	Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, Anoob Joseph,
	Ruifeng Wang, Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, Stephen Hemminger, alexr

Hi David,

On 21/04/2020 18:23, Coyle, David wrote:
> Thank you Thomas for your input.
> 
> We would like to request that the Tech-Board (CC'ed) also review the proposal to help us reach a consensus.
>  

The discussion on the mailing list still looks active and I think that's
where it should continue until there is no reasonable hope of consensus.
I'm not sure discussing over irc at TB will find a better technical
solution.

> If the current proposal is not acceptable, we would welcome feedback from the board on how to rework our
> proposal to something that would be acceptable.
>  
> For the benefit of the Tech-Board here is the back-ground to our proposal for Rawdev-based multi-function
> processing:
> - The primary objective is to support the AESNI MB combined Crypto-CRC processing capability in DPDK and
>    in future to add support for combined Crypto-CRC support in QAT.
> - The cryptodev API was considered unsuitable because CRC is not a cryptographic operation, and this would
>    also preclude other non-crypto operations in the future such as compression.
> - The rte_security API was also not considered suitable for chaining of non-crypto operations such as CRC,
>    as Declan pointed out below.
> - A new Accelerator API was proposed as an RFC but was not pursued due to community feedback that a
>    new API would not be welcome for a single use-case.
> - Using Rawdev for multi-function processing was then proposed and, initially, as there was no opposition
>    we implemented a patch-set for this approach.
>  
> It was considered that a Rawdev-based multi-function approach would be suitable for the following reasons:
> 1) Multi-function processing for Crypto-CRC cases is not a good fit for any of the existing DPDK classes.
> 2) Rawdev was intended for such specialized acceleration processing that are not a good fit for existing DPDK
>      classes.
> 3) Rawdev was also intended as somewhere that new use-cases like this could be prototyped and developed,
>      such as Declan mentions below
> 4) The Rawdev-based multi-function proposal is extensible and we would hope that it can evolve to support
>      new use-cases and target new devices in the future with the communities involvement.
> 

This is a useful summary and explaining your approach but it doesn't
mention the counter arguments, so it doesn't seem balanced. Of course
people can read that in the ML thread.

Kevin.

> 
>> -----Original Message-----
>> From: Doherty, Declan <declan.doherty@intel.com>
>> Sent: Tuesday, April 21, 2020 5:46 PM
>>
>> On 15/04/2020 11:33 PM, Thomas Monjalon wrote:
>>> 16/04/2020 00:19, Doherty, Declan:
>>>> On 14/04/2020 3:44 PM, Thomas Monjalon wrote:
>>>>> 14/04/2020 16:02, Trahe, Fiona:
>>>>>> From: Thomas Monjalon <thomas@monjalon.net>
>>>>>>> 14/04/2020 15:04, Trahe, Fiona:
>>>>>>>>> 14/04/2020 12:21, Ferruh Yigit:
>>>>>>>>>
>>>>>>>
>> http://inbox.dpdk.org/dev/MN2PR11MB35507D4B96677A41E66440C5E3C30
>> @M
>>>>>>> N2PR11MB3550.na
>>>>>>>>> mprd11.prod.outlook.com/
>>>>>>>>>
>>>>>>>>> I am not convinced.
>>>>>>>>> I don't like rawdev in general.
>>>>>>>>> Rawdev is good only for hardware support which cannot be generic
>>>>>>>>> like SoC, FPGA management or DMA engine.
>>>>>>>>
>>>>>>>> [Fiona] CRC and BIP are not crypto algorithms, they are error
>> detection processes.
>>>>>>>> So there is no class in DPDK that these readily fit into.
>>>>>>>> There was resistance to adding another xxxddev, and even if one
>>>>>>>> had been added for error_detection_dev, there would still have
>>>>>>>> been another layer needed to couple this with cryptodev. Various
>>>>>>>> proposals for this have been discussed on the ML in RFC and recent
>> patches, there doesn't seem to be an appetite for this as a generic API.
>>>>>>>> So it seems that only Intel has software and hardware engines
>>>>>>>> that provide this specialised feature coupling. In that case
>>>>>>>> rawdev seems like the most appropriate vehicle to expose this.
>>>>>>>
>>>>>>> Adding some vendor-specific API is not a good answer.
>>>>>>> It will work in some cases, but it won't make DPDK better.
>>>>>>> What's the purpose of DPDK if it's not solving a common problem
>>>>>>> for different hardware?
>>>>>>
>>>> The current proposal in rawdev could easily be supported by any
>>>> hardware which supports chaining multiple functions/services into a
>>>> single operation, in this case symmetric crypto and error detection,
>>>> but it could conceivably support chaining symmetric/asymmetric crypto
>>>> operations or chaining symmetric crypto and compression operations.
>>>>
>>>>>> [Fiona] Based on that logic rawdev should be deprecated.
>>>>>> But the community has agreed that it has a place.
>>>>>
>>>>> No, as I said above, rawdev is good for SoC, FPGA management or DMA
>> engine.
>>>>
>>>> I distinctly remember when rawdev was being proposed one of the uses
>>>> cases proposed was that a new classes of APIs could be prototyped and
>>>> developed under rawdev and when a solid consensus was reached then
>>>> migrated to a mainstream DPDK library. I think every effort has been
>>>> made here to engage the community to develop a generic approach. As
>>>> Fiona notes there hasn't really been much of an appetite for this.
>>>>
>>>> Therefore I think the option to use rawdev makes sense, it allows an
>>>> initial proposal to be deployed,  without a generic solution
>>>> agreement, it will also give others in the community to see how this
>>>> approach can work and hopefully lead to more engagement on a generic
>>>> solution. Also as APIs in rawdev are essentially treated as private
>>>> APIs the onus is on Intel to support this going forward.
>>>
>>> Because hardware support is pending,
>>> we should accept an Intel-only "temporary" solution, opening the door
>>> to more vendor-specific APIs?
>>>
>>> What is the benefit for the DPDK project?
>>>
>> Sorry I don't agree with this sentiment, David has made every attempt to
>> solicit feedback and to engage the community in this.
>>
>> I also don't agree in classifying this as a "temporary solution" as this is a solid
>> proposal for an approach to chaining multiple operations together, but I
>> guess the fact remains that we only currently have a single use-case, but it is
>> difficult to generate a generic solution in this case.
>>
>> While there is only a single use case it is targeting two devices so that drove
>> the need for a common interface within rawdev.
>>
>> The advantage of using rawdev is that it allows this to be consumed through
>> DPDK, which enables DPDK project consumers, but also leaves the door open
>> to other contributors to have their say on how this should evolve. For
>> example this exact process seems to be occurring with DMA engines in
>> rawdev today, with a critical mass of implementations which now is giving the
>> impetus to create a generic solution, as we would hope can occur here too in
>> the future.
>>
>>
>>>>>> And the common problem here is device exposure.
>>>>>> With a specialised service on top.
>>>>>>
>>>>>>
>>>>>>>>> Here the intent is to use rawdev because we don't find a good API.
>>>>>>>>> API defeat is a no-go.
>>>>>>>>
>>>>>>>> [Fiona] It's not that we haven't found a good API, but that there
>>>>>>>> doesn't seem to be a general requirement for such a specialised
>>>>>>>> API
>>>>>>>
>>>>>>> There is a requirement to combine features of different classes.
>>>>>>
>>>>>> [Fiona] Can you point me to that requirement please?
>>>>>
>>>>> Yes, rte_security is trying to address this exact issue.
>>>>>
>>>>
>>>> I don't agree rte_security addresses the problem of different device
>>>> types supporting the same services. The problem being addressed here
>>>> is a single device which supports the chaining of multiple services
>>>> (sym crypto & error detection)
>>>
>>> Doing IPsec processing in Rx or Tx of a NIC is not chaining?
>>>
>> I wouldn't consider an inline crypto offload or full IPsec offload a chained
>> operation in the vein being proposed here where completely independent
>> services (in the view of DPDK which are currently on independent devices
>> and APIs) are linked together.
>>
>> We did look at using rte_security here but it wasn't considered suitable for a
>> chaining of non-crypto operations such as CRC or possibly compression in the
>> future, as it would still run into the issue of having to use the cryptodev
>> enq/deq API in the lookaside offload case.
>>
>>
>>>>>> We suggested it, but did not get community engagement and have
>>>>>> dropped our generic API requirement, instead focussing on this
>> specialised case.
>>>>>
>>>>> I did not see such generic proposal, sorry.
>>>>>
>>>>>>> In the past, rte_security was an "answer" to this issue with crypto and
>> ethdev.
>>>>>>> This is a real topic, please let's find a generic elegant solution.
>>>
>>>
>>>


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-22 13:44                           ` Akhil Goyal
@ 2020-04-22 14:21                             ` Coyle, David
  2020-05-01 13:18                             ` Zhang, Roy Fan
  1 sibling, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-04-22 14:21 UTC (permalink / raw)
  To: Akhil Goyal, Doherty, Declan, Thomas Monjalon, Yigit, Ferruh,
	Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	Hemant Agrawal, Anoob Joseph, Ruifeng Wang, Liron Himi,
	Nagadheeraj Rottela, Srikanth Jampala, Gagandeep Singh, Jay Zhou,
	Ravi Kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, Stephen Hemminger, alexr

Hi Akhil

> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Wednesday, April 22, 2020 2:44 PM
> 
> Hi David,
> > Hi Akhil,
> >
> > > > >
> > > I did not look at your patches completely, but looking at the ops
> > > that you have added For rawdev are pretty much same as that of a crypto
> device.
> > >
> > > I see that there are 2 types of ops that you need
> > > - session create/destroy
> > > - enq/deq
> > >
> > > On the first impression of your patchset, I see that you want to enq
> > > to driver only once for both The operations - CRC and crypto.
> > >
> > > So what is the issue in using the cryptodev_enqueue for processing
> > > in the existing AESNI-MB driver.
> > > For session creation, the cryptodev layer will not give flexibility
> > > to add
> > > CRC+crypto kind of sessions.
> > > But in case of rte_security, you can define your new session xform
> > > based on your requirement.
> > >
> > > And while doing the cryptodev enq/deq, based on the session type,
> > > you can process the packet Specific to your usecase in your aesni-mb
> > > PMD
> > >
> > > Now if you want to add compression also along with crypto, then you
> > > can define another xform which Will be combination of
> > > crypto+compression and the aesni-mb PMD can have another mode
> which
> > > Can make sessions based on the new xform and the enq and deq can be
> > > done using the cryptodev enq/deq.
> > > For all your cases you will be having only one action type -
> > > lookaside protocol and can define different Protocols (that may not be
> standard).
> > >
> > > So to conclude, your AESNI-MB will have 3 types of operations
> > > - plain crypto
> > > - crc+crypto
> > > - compression+crypto
> > >
> > > I believe this is doable or did I miss something very obvious?
> >
> > [DC] Thank you for this feedback
> >
> > I have done this exact same analysis on rte_security and how we could use
> it.
> >
> > The main issue of this approach (and it may be possible to easily
> > overcome) is that ultimately crypto_op's need to be enqueued into
> > cryptodev. This means we can't easily control the CRC (or compression
> > in the future) at the operation level - application developers using
> > this API would create a
> > Crypto+CRC security xform session  for a
> > particular flow but may want to turn off the CRC part for some packets
> > in that flow.
> >
> > There are a number of ways this issue could possibly be overcome:
> > 1) the auth offset/length fields in a rte_crypto_op could be
> > overloaded to control the CRC part of the combined operation
> >     - this is not the cleanest approach
> > 2) we add a "security" op struct of some type to the union at end of
> > the rte_crypto_op
> >     - to avoid any circular dependencies, this would need to be opaque
> > to rte_cryptodev
> >     - rte_cryptodev should not be aware of rte_security
> >
> > Number 2 above is probably the cleaner and more preferable approach.
> 
> Yes, it is preferred, but it should be a union to
> rte_crypto_sym_op/rte_crypto_asym_op.
> Crypto_op->type as RTE_CRYPTO_OP_TYPE_SECURITY and sess_type as
> RTE_CRYPTO_OP_SECURITY_SESSION The size of rte_crypto_op will remain
> as is and there will be no ABI breakage I guess.

[DC]  Yes we would add to this union at the end of rte_crypto_op

        __extension__
        union {
                struct rte_crypto_sym_op sym[0];
                /**< Symmetric operation parameters */

                struct rte_crypto_asym_op asym[0];
                /**< Asymmetric operation parameters */

        }; /**< operation specific parameters */

I haven't figured out the finer details yet, but it should be straightforward to add some security element here.
As these are zero length arrays, we won't be affecting the size of rte_crypto_op if we add another zero length array.

We should not include rte_security.h and add something like struct rte_security_op sec[0] here though, as that would
cause a circular dependency between rte_cryptodev and rte_security.
This should be resolvable though

> 
> One more thing that can be looked into is the recently added CPU crypto
> process API If that could of any use, we may extend that if need be.

[DC] This is also being targeted at QAT and we would like to maintain the same
Interface for these use-cases for both AESNI-MB and QAT.

So I think the traditional enqueue/dequeue API is what we would initially use as it
means users of this API can easily switch between AESNI-MB and QAT. However, we
may look at the CPU crypto API for AESNI-MB in the future.

> 
> >
> > The other approach is that CRC is either on/off at the session level.
> > That limitation would then need to be adhered by application
> > developers, which is something we would ideally like to avoid.
> 
> You mean that CRC can be on/off per session as well as per packet?
> I think that can also be handled when you are defining your own security_op
> for per packet.

[DC] I meant that if we didn't take the approach defining a security_op, then
we would have turn on/off CRC at the session level and impose that limit on
the app developers. But yes, by defining a security_op, we can probably turn
it on/off at both session and op level.

> 
> >
> > The rawdev multi-function approach did not have these issues which is
> > one of the reasons we have pursued this approach to date.
> >
> > However, we think the rte_security approach is workable.
> > It still requires some deeper analysis but with your support, we think
> > we can overcome the challenges.
> >
> Yes, please let me know where ever my help is required.
[DC] Thank you, appreciate that

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-22 14:01                       ` Kevin Traynor
@ 2020-04-22 14:41                         ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-04-22 14:41 UTC (permalink / raw)
  To: Kevin Traynor, Doherty, Declan, Thomas Monjalon, Yigit, Ferruh,
	Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	shreyansh.jain, hemant.agrawal, akhil.goyal, Anoob Joseph,
	Ruifeng Wang, Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, Stephen Hemminger, alexr

Hi Kevin,

> -----Original Message-----
> From: Kevin Traynor <ktraynor@redhat.com>
> Sent: Wednesday, April 22, 2020 3:02 PM
> 
> Hi David,
> 
> On 21/04/2020 18:23, Coyle, David wrote:
> > Thank you Thomas for your input.
> >
> > We would like to request that the Tech-Board (CC'ed) also review the
> proposal to help us reach a consensus.
> >
> 
> The discussion on the mailing list still looks active and I think that's where it
> should continue until there is no reasonable hope of consensus.
> I'm not sure discussing over irc at TB will find a better technical solution.

[DC] Yes, there has been some further proposals and discussions today, mainly around the use
of rte_security. Although there are a few challenges to work around here, it is an approach we
had already considered and it would seem like a good compromise to the rawdev approach. 

With that in mind, we are happy to let this play out further on the mailing list for now.

If we can reach consensus on using rte_security, then we are happy to go with that and investigate
and develop it further.

> 
> > If the current proposal is not acceptable, we would welcome feedback
> > from the board on how to rework our proposal to something that would be
> acceptable.
> >
> > For the benefit of the Tech-Board here is the back-ground to our
> > proposal for Rawdev-based multi-function
> > processing:
> > - The primary objective is to support the AESNI MB combined Crypto-CRC
> processing capability in DPDK and
> >    in future to add support for combined Crypto-CRC support in QAT.
> > - The cryptodev API was considered unsuitable because CRC is not a
> cryptographic operation, and this would
> >    also preclude other non-crypto operations in the future such as
> compression.
> > - The rte_security API was also not considered suitable for chaining of non-
> crypto operations such as CRC,
> >    as Declan pointed out below.
> > - A new Accelerator API was proposed as an RFC but was not pursued due
> to community feedback that a
> >    new API would not be welcome for a single use-case.
> > - Using Rawdev for multi-function processing was then proposed and,
> initially, as there was no opposition
> >    we implemented a patch-set for this approach.
> >
> > It was considered that a Rawdev-based multi-function approach would be
> suitable for the following reasons:
> > 1) Multi-function processing for Crypto-CRC cases is not a good fit for any of
> the existing DPDK classes.
> > 2) Rawdev was intended for such specialized acceleration processing that
> are not a good fit for existing DPDK
> >      classes.
> > 3) Rawdev was also intended as somewhere that new use-cases like this
> could be prototyped and developed,
> >      such as Declan mentions below
> > 4) The Rawdev-based multi-function proposal is extensible and we would
> hope that it can evolve to support
> >      new use-cases and target new devices in the future with the
> communities involvement.
> >
> 
> This is a useful summary and explaining your approach but it doesn't mention
> the counter arguments, so it doesn't seem balanced. Of course people can
> read that in the ML thread.

[DC] That is a fair point, and something we will keep in mind for the future if
we need to come back to the tech-board.

> 
> Kevin.
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-04-22 13:44                           ` Akhil Goyal
  2020-04-22 14:21                             ` Coyle, David
@ 2020-05-01 13:18                             ` Zhang, Roy Fan
  2020-05-12 17:32                               ` Coyle, David
  1 sibling, 1 reply; 92+ messages in thread
From: Zhang, Roy Fan @ 2020-05-01 13:18 UTC (permalink / raw)
  To: Akhil Goyal, Coyle, David, Doherty, Declan, Thomas Monjalon,
	Yigit, Ferruh, Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	Hemant Agrawal, Anoob Joseph, Ruifeng Wang, Liron Himi,
	Nagadheeraj Rottela, Srikanth Jampala, Gagandeep Singh, Jay Zhou,
	Ravi Kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, Stephen Hemminger, alexr

Hi Akhil,

> -----Original Message-----
> From: dev <dev-bounces@dpdk.org> On Behalf Of Akhil Goyal
> Sent: Wednesday, April 22, 2020 2:44 PM
> To: Coyle, David <david.coyle@intel.com>; Doherty, Declan
> <declan.doherty@intel.com>; Thomas Monjalon <thomas@monjalon.net>;
> Yigit, Ferruh <ferruh.yigit@intel.com>; Trahe, Fiona <fiona.trahe@intel.com>
> Cc: techboard@dpdk.org; dev@dpdk.org; De Lara Guarch, Pablo
> <pablo.de.lara.guarch@intel.com>; Ryan, Brendan
> <brendan.ryan@intel.com>; Hemant Agrawal <hemant.agrawal@nxp.com>;
> Anoob Joseph <anoobj@marvell.com>; Ruifeng Wang
> <ruifeng.wang@arm.com>; Liron Himi <lironh@marvell.com>; Nagadheeraj
> Rottela <rnagadheeraj@marvell.com>; Srikanth Jampala
> <jsrikanth@marvell.com>; Gagandeep Singh <G.Singh@nxp.com>; Jay Zhou
> <jianjay.zhou@huawei.com>; Ravi Kumar <ravi1.kumar@amd.com>;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; Stephen Hemminger
> <stephen@networkplumber.org>; alexr@mellanox.com
> Subject: Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-
> function processing
...
> Yes, it is preferred, but it should be a union to
> rte_crypto_sym_op/rte_crypto_asym_op.
> Crypto_op->type as RTE_CRYPTO_OP_TYPE_SECURITY and sess_type as
> RTE_CRYPTO_OP_SECURITY_SESSION
> The size of rte_crypto_op will remain as is and there will be no ABI breakage I
> guess.
> 
[Fan: with this way the PMD will have to do rte_crypto_op.type check, and then look into rte_security_op field, only when it find the security_op type is crypto_crc, it will process the security_op data. Would that being too many reads and checking for a single op? Can we create a new API for rte_security to process rte_security_ops for Crypto_CRC or future needs?]
...
 
Regards,
Fan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing
  2020-05-01 13:18                             ` Zhang, Roy Fan
@ 2020-05-12 17:32                               ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-05-12 17:32 UTC (permalink / raw)
  To: Zhang, Roy Fan, Akhil Goyal, Doherty, Declan, Thomas Monjalon,
	Yigit, Ferruh, Trahe, Fiona
  Cc: techboard, dev, De Lara Guarch, Pablo, Ryan, Brendan,
	Hemant Agrawal, Anoob Joseph, Ruifeng Wang, Liron Himi,
	Nagadheeraj Rottela, Srikanth Jampala, Gagandeep Singh, Jay Zhou,
	Ravi Kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, Stephen Hemminger, alexr

Hi Fan & Akhil,

> -----Original Message-----
> From: Zhang, Roy Fan <roy.fan.zhang@intel.com>
> Sent: Friday, May 1, 2020 2:18 PM
> 
> Hi Akhil,
> 
> > -----Original Message-----
> > From: dev <dev-bounces@dpdk.org> On Behalf Of Akhil Goyal
> > Sent: Wednesday, April 22, 2020 2:44 PM
> > To: Coyle, David <david.coyle@intel.com>; Doherty, Declan
> > <declan.doherty@intel.com>; Thomas Monjalon
> <thomas@monjalon.net>;
> > Yigit, Ferruh <ferruh.yigit@intel.com>; Trahe, Fiona
> > <fiona.trahe@intel.com>
> > Cc: techboard@dpdk.org; dev@dpdk.org; De Lara Guarch, Pablo
> > <pablo.de.lara.guarch@intel.com>; Ryan, Brendan
> > <brendan.ryan@intel.com>; Hemant Agrawal
> <hemant.agrawal@nxp.com>;
> > Anoob Joseph <anoobj@marvell.com>; Ruifeng Wang
> > <ruifeng.wang@arm.com>; Liron Himi <lironh@marvell.com>; Nagadheeraj
> > Rottela <rnagadheeraj@marvell.com>; Srikanth Jampala
> > <jsrikanth@marvell.com>; Gagandeep Singh <G.Singh@nxp.com>; Jay
> Zhou
> > <jianjay.zhou@huawei.com>; Ravi Kumar <ravi1.kumar@amd.com>;
> > Richardson, Bruce <bruce.richardson@intel.com>;
> > olivier.matz@6wind.com; honnappa.nagarahalli@arm.com; Stephen
> > Hemminger <stephen@networkplumber.org>; alexr@mellanox.com
> > Subject: Re: [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-
> > function processing
> ...
> > Yes, it is preferred, but it should be a union to
> > rte_crypto_sym_op/rte_crypto_asym_op.
> > Crypto_op->type as RTE_CRYPTO_OP_TYPE_SECURITY and sess_type as
> > RTE_CRYPTO_OP_SECURITY_SESSION The size of rte_crypto_op will remain
> > as is and there will be no ABI breakage I guess.
> >
> [Fan: with this way the PMD will have to do rte_crypto_op.type check, and
> then look into rte_security_op field, only when it find the security_op type is
> crypto_crc, it will process the security_op data. Would that being too many
> reads and checking for a single op? Can we create a new API for rte_security
> to process rte_security_ops for Crypto_CRC or future needs?] ...

[DC] If we were to add new enqueue/dequeue APIs to rte_security, then this may
cause extra churn and extra paths of code in a customer's application. For the
DOCSIS Crypto-CRC use-case which is currently supported by IPSecMB, only the
AES-DOCSISBPI cipher algorithm is supported. For these Crypto-CRC ops, they would
create rte_security sessions, attach these to rte_security_ops and enqueue/dequeue
using the new APIs in rte_security.

However, the customer may also be using the legacy DES-DOCSISBPI cipher algorithm
for some subscribers, and this algorithm is not supported in the chained Crypto-CRC
functionality in IPSecMB (and most likely never will be). So for these the customer
would need to create cryptodev sessions, attach these to rte_crypto_ops and enqueue/
dequeue with the cryptodev enq/deq APIs. That is 2 different paths of code now in
the application datapath, where some packets in a batch need to be enqueued through
rte_security and some need to be enqueued through cryptodev.

If rte_crypto_ops are always used and enqueued/dequeued through cryptodev, then the
only thing that changes is the type of session that is created and either the security session
or the cryptodev session gets attached to the crypto_op.

Now, we could add support to rte_security for DES-DOCSISBPI too, but it would not be a
combined operation with CRC - it would be a simple cipher operation going through
rte_security. But that, to me, does not seem like a good use of rte_security.

For DOCSIS Crypto-CRC, we may also want to take advantage of the
rte_cryptodev_sym_cpu_crypto_process() API which was added to cryptodev recently to
avoid the enqueue/dequeue overhead. A similar API would also then need to be added
to rte_security.

Taking all of the above into account, I feel keeping the normal cryptodev enqueue/dequeue
would be best. Having said all that, we do need to consider performance in the PMD of the
extra op type checks. Take aesni_mb PMD as an example. It would need to check
rte_crypto_op->type and if it's not RTE_CRYPTO_OP_TYPE_SECURITY, then it can assume
it's an RTE_CRYPTO_OP_TYPE_SYMMETRIC op and carry on as normal for existing symmetric
operations. Security ops will need some extra parsing but this is new functionality. The impact
on existing functionality of the extra checks would certainly need to be tested though, but as
all the op data will be in the same cache line, I don't see any major impact.

Akhil & Fan (& others), I would be interested to hear your feedback on this.

Regards,
David

> 
> Regards,
> Fan

^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH 0/3] add support for DOCSIS protocol to security library
  2020-04-10 14:27 [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing David Coyle
                   ` (4 preceding siblings ...)
  2020-04-10 22:55 ` [dpdk-dev] [PATCH v3 0/4] add AESNI-MB rawdev for multi-function processing Thomas Monjalon
@ 2020-06-04 15:13 ` David Coyle
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 1/3] security: add support for DOCSIS protocol David Coyle
                     ` (3 more replies)
  5 siblings, 4 replies; 92+ messages in thread
From: David Coyle @ 2020-06-04 15:13 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle

Introduction
============

This patchset adds support for the DOCSIS protocol to the DPDK Security
API (rte_security), to be used by the AESNI-MB and QAT crypto devices to
combine and accelerate Crypto and CRC functions of the DOCSIS protocol
into a single operation.

Performing these functions in parallel as a single operation can enable a
significant performance improvement in a DPDK-based DOCSIS MAC pipeline.

PLEASE NOTE: this patchset only includes the proposed API changes. The
implementation will follow in the next version.

Background
==========

A number of approaches to combine DOCSIS Crypto and CRC functions have
been discussed in the DPDK community to date, namely:
1) adding a new rte_accelerator API, to provide a generic interface for
   combining operations of different types
2) using rawdev through a multi-function interface, again to provide a
   generic interface for combining operations of different types
3) adding support for DOCSIS Crypto-CRC to rte_security

The third option above is the preferred approach for the following
reasons:
- it addresses the immediate use case to add DOCSIS Crypto-CRC support to
  DPDK so that it can be consumed easily by cable equipment vendors
- it uses an already existing framework in DPDK
- it will mean much less code churn in DOCSIS applications, which already
  use rte_cryptodev for encryption/decryption


Use Cases
=========

The primary use case for this proposal has already been mentioned, namely
to add DOCSIS Crypto-CRC support to DPDK:

- DOCSIS MAC: Crypto-CRC
	- Order:
		- Downstream: CRC, Encrypt
		- Upstream: Decrypt, CRC
	- Specifications:
		- Crypto: 128-bit AES-CFB encryption variant for DOCSIS as
		  described in section 11.1 of DOCSIS 3.1 Security
		  Specification
		  (https://apps.cablelabs.com/specification/CM-SP-SECv3.1)
		- CRC: Ethernet 32-bit CRC as defined in
		  Ethernet/[ISO/IEC 8802-3]

Note that support for this chained operations is already available in the
Intel IPSec Multi-Buffer library.

However, other DOCSIS protocol functions could be optimized too in the
future using the same rte_security API for DOCSIS (e.g. Header Checksum
(HCS) calculation).

v1:
* added proposed API changes
* added security capabilities to aesni_mb crypto PMD

David Coyle (3):
  security: add support for DOCSIS protocol
  cryptodev: add security operation to crypto operation
  crypto/aesni_mb: add support for DOCSIS protocol

 drivers/crypto/aesni_mb/meson.build           |   2 +-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    |  63 ++++++++++
 lib/librte_cryptodev/rte_crypto.h             |  11 +-
 lib/librte_security/rte_security.h            | 114 ++++++++++++++++++
 4 files changed, 188 insertions(+), 2 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH 1/3] security: add support for DOCSIS protocol
  2020-06-04 15:13 ` [dpdk-dev] [PATCH 0/3] add support for DOCSIS protocol to security library David Coyle
@ 2020-06-04 15:13   ` David Coyle
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation David Coyle
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-06-04 15:13 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support for DOCSIS protocol to rte_security library. This support
currently comprises the combination of Crypto and CRC operations.

Please note this is API changes only. Implementation will follow in
next version.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 lib/librte_security/rte_security.h | 114 +++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/lib/librte_security/rte_security.h b/lib/librte_security/rte_security.h
index 747830d67..46ec4997a 100644
--- a/lib/librte_security/rte_security.h
+++ b/lib/librte_security/rte_security.h
@@ -293,6 +293,30 @@ struct rte_security_pdcp_xform {
 	uint32_t hfn_ovrd;
 };
 
+/** DOCSIS direction */
+enum rte_security_docsis_direction {
+	RTE_SECURITY_DOCSIS_UPLINK,
+	/**< Uplink
+	 * - Decryption, followed by CRC Verification
+	 */
+	RTE_SECURITY_DOCSIS_DOWNLINK,
+	/**< Downlink
+	 * - CRC Generation, followed by Encryption
+	 */
+};
+
+/**
+ * DOCSIS security session configuration.
+ *
+ * This structure contains data required to create a DOCSIS security session.
+ */
+struct rte_security_docsis_xform {
+	enum rte_security_docsis_direction direction;
+	/** DOCSIS direction */
+	uint16_t crc_size;
+	/**< CRC size in bytes */
+};
+
 /**
  * Security session action type.
  */
@@ -325,6 +349,8 @@ enum rte_security_session_protocol {
 	/**< MACSec Protocol */
 	RTE_SECURITY_PROTOCOL_PDCP,
 	/**< PDCP Protocol */
+	RTE_SECURITY_PROTOCOL_DOCSIS,
+	/**< DOCSIS Protocol */
 };
 
 /**
@@ -340,6 +366,7 @@ struct rte_security_session_conf {
 		struct rte_security_ipsec_xform ipsec;
 		struct rte_security_macsec_xform macsec;
 		struct rte_security_pdcp_xform pdcp;
+		struct rte_security_docsis_xform docsis;
 	};
 	/**< Configuration parameters for security session */
 	struct rte_crypto_sym_xform *crypto_xform;
@@ -355,6 +382,77 @@ struct rte_security_session {
 	/**< Opaque user defined data */
 };
 
+/**
+ * DOCSIS operation parameters
+ */
+struct rte_security_docsis_op {
+	struct rte_crypto_sym_op crypto_sym;
+	/**< Symmetric crypto operation parameters */
+
+	struct {
+		struct {
+			uint16_t offset;
+			/**<
+			 * Starting point for CRC processing, specified
+			 * as the number of bytes from start of the packet in
+			 * the source mbuf in crypto_sym
+			 */
+			uint16_t length;
+			/**<
+			 * The length, in bytes, of the source mbuf on which the
+			 * CRC will be computed
+			 */
+		} data;
+		/**< Data offset and length for CRC */
+
+		struct {
+			uint8_t *data;
+			/**<
+			 * This points to the location where the CRC should be
+			 * written (in the case of generation) or where the
+			 * purported result exists (in the case of
+			 * verification).
+			 *
+			 * The caller must ensure the required length of
+			 * physically contiguous memory is available at this
+			 * address.
+			 *
+			 * This may point into the mbuf packet data. For
+			 * generation, the result will overwrite any data at
+			 * this location.
+			 */
+			rte_iova_t phys_addr;
+			/**< Physical address of output data */
+		} output;
+		/**< Output location */
+	} crc;
+	/**< CRC operation parameters */
+
+	uint64_t reserved;
+	/**< Reserved for future use */
+};
+
+/**
+ * Security operation types
+ */
+enum rte_security_op_type {
+	RTE_SECURITY_OP_TYPE_DOCSIS = 1
+	/**< DOCSIS operation */
+};
+
+/**
+ * Security operation parameters
+ */
+struct rte_security_op {
+	enum rte_security_op_type type;
+	/**< Type of operation */
+	RTE_STD_C11
+	union {
+		struct rte_security_docsis_op docsis;
+	};
+	/**< Parameters for security operation */
+};
+
 /**
  * Create security session as specified by the session configuration
  *
@@ -523,6 +621,10 @@ struct rte_security_pdcp_stats {
 	uint64_t reserved;
 };
 
+struct rte_security_docsis_stats {
+	uint64_t reserved;
+};
+
 struct rte_security_stats {
 	enum rte_security_session_protocol protocol;
 	/**< Security protocol to be configured */
@@ -532,6 +634,7 @@ struct rte_security_stats {
 		struct rte_security_macsec_stats macsec;
 		struct rte_security_ipsec_stats ipsec;
 		struct rte_security_pdcp_stats pdcp;
+		struct rte_security_docsis_stats docsis;
 	};
 };
 
@@ -591,6 +694,13 @@ struct rte_security_capability {
 			/**< Capability flags, see RTE_SECURITY_PDCP_* */
 		} pdcp;
 		/**< PDCP capability */
+		struct {
+			enum rte_security_docsis_direction direction;
+			/**< DOCSIS direction */
+			uint16_t crc_size;
+			/**< CRC size in bytes */
+		} docsis;
+		/**< DOCSIS capability */
 	};
 
 	const struct rte_cryptodev_capabilities *crypto_capabilities;
@@ -649,6 +759,10 @@ struct rte_security_capability_idx {
 			enum rte_security_pdcp_domain domain;
 			uint32_t capa_flags;
 		} pdcp;
+		struct {
+			enum rte_security_docsis_direction direction;
+			uint16_t crc_size;
+		} docsis;
 	};
 };
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-04 15:13 ` [dpdk-dev] [PATCH 0/3] add support for DOCSIS protocol to security library David Coyle
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 1/3] security: add support for DOCSIS protocol David Coyle
@ 2020-06-04 15:13   ` David Coyle
  2020-06-09 13:23     ` Ananyev, Konstantin
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 3/3] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
  3 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-04 15:13 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add a new security operation structure to the crypto operation to allow
protocol specific parameters defined in rte_security be defined for a
crypto operation.

Please note this is API changes only. Implementation will follow in
next version.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 lib/librte_cryptodev/rte_crypto.h | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h
index fd5ef3a87..fbc1df791 100644
--- a/lib/librte_cryptodev/rte_crypto.h
+++ b/lib/librte_cryptodev/rte_crypto.h
@@ -31,8 +31,10 @@ enum rte_crypto_op_type {
 	/**< Undefined operation type */
 	RTE_CRYPTO_OP_TYPE_SYMMETRIC,
 	/**< Symmetric operation */
-	RTE_CRYPTO_OP_TYPE_ASYMMETRIC
+	RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
 	/**< Asymmetric operation */
+	RTE_CRYPTO_OP_TYPE_SECURITY
+	/**< Security operation */
 };
 
 /** Status of crypto operation */
@@ -121,6 +123,13 @@ struct rte_crypto_op {
 		struct rte_crypto_asym_op asym[0];
 		/**< Asymmetric operation parameters */
 
+#ifdef RTE_LIBRTE_SECURITY
+		uint8_t security[0];
+		/**< Security operation parameters
+		 * - Must be accessed through a rte_security_op pointer
+		 */
+#endif
+
 	}; /**< operation specific parameters */
 };
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH 3/3] crypto/aesni_mb: add support for DOCSIS protocol
  2020-06-04 15:13 ` [dpdk-dev] [PATCH 0/3] add support for DOCSIS protocol to security library David Coyle
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 1/3] security: add support for DOCSIS protocol David Coyle
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation David Coyle
@ 2020-06-04 15:13   ` David Coyle
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
  3 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-06-04 15:13 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support to the AESNI-MB PMD for the DOCSIS protocol, through the
rte_security API. This, therefore, includes adding support for the
rte_security API to this PMD.

Please note this is only a partial implementation, with just
capabilities structures populated. Full implementation will follow in
next version.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 drivers/crypto/aesni_mb/meson.build           |  2 +-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    | 63 +++++++++++++++++++
 2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/aesni_mb/meson.build b/drivers/crypto/aesni_mb/meson.build
index e557e0103..23f578fd3 100644
--- a/drivers/crypto/aesni_mb/meson.build
+++ b/drivers/crypto/aesni_mb/meson.build
@@ -22,4 +22,4 @@ else
 endif
 
 sources = files('rte_aesni_mb_pmd.c', 'rte_aesni_mb_pmd_ops.c')
-deps += ['bus_vdev']
+deps += ['bus_vdev', 'security']
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
index 8c5e0cd92..c637ddb5f 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -8,6 +8,9 @@
 #include <rte_common.h>
 #include <rte_malloc.h>
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security_driver.h>
+#endif
 
 #include "aesni_mb_pmd_private.h"
 
@@ -499,12 +502,72 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+#ifdef RTE_LIBRTE_SECURITY
+static const struct rte_cryptodev_capabilities
+					aesni_mb_pmd_security_crypto_cap[] = {
+	{	/* AES DOCSIS BPI */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		{.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			{.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+#if IMB_VERSION_NUM >= IMB_VERSION(0, 53, 3)
+					.max = 32,
+					.increment = 16
+#else
+					.max = 16,
+					.increment = 0
+#endif
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}, }
+		}, }
+	},
+
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability aesni_mb_pmd_security_cap[] = {
+	{ /* DOCSIS Uplink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_UPLINK,
+			.crc_size = 4
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{ /* DOCSIS downlink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK,
+			.crc_size = 4
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{
+		.action = RTE_SECURITY_ACTION_TYPE_NONE
+	}
+};
+#endif
 
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev,
 		__rte_unused struct rte_cryptodev_config *config)
 {
+#ifdef RTE_LIBRTE_SECURITY
+	/* Temporary to avoid compile issues */
+	(void)aesni_mb_pmd_security_cap;
+#endif
 	return 0;
 }
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation David Coyle
@ 2020-06-09 13:23     ` Ananyev, Konstantin
  2020-06-09 13:50       ` Coyle, David
  0 siblings, 1 reply; 92+ messages in thread
From: Ananyev, Konstantin @ 2020-06-09 13:23 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, De Lara Guarch,
	Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, Coyle, David,
	O'loingsigh, Mairtin


> 
> Add a new security operation structure to the crypto operation to allow
> protocol specific parameters defined in rte_security be defined for a
> crypto operation.
> 
> Please note this is API changes only. Implementation will follow in
> next version.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> ---
>  lib/librte_cryptodev/rte_crypto.h | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h
> index fd5ef3a87..fbc1df791 100644
> --- a/lib/librte_cryptodev/rte_crypto.h
> +++ b/lib/librte_cryptodev/rte_crypto.h
> @@ -31,8 +31,10 @@ enum rte_crypto_op_type {
>  	/**< Undefined operation type */
>  	RTE_CRYPTO_OP_TYPE_SYMMETRIC,
>  	/**< Symmetric operation */
> -	RTE_CRYPTO_OP_TYPE_ASYMMETRIC
> +	RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
>  	/**< Asymmetric operation */
> +	RTE_CRYPTO_OP_TYPE_SECURITY
> +	/**< Security operation */
>  };
> 
>  /** Status of crypto operation */
> @@ -121,6 +123,13 @@ struct rte_crypto_op {
>  		struct rte_crypto_asym_op asym[0];
>  		/**< Asymmetric operation parameters */
> 
> +#ifdef RTE_LIBRTE_SECURITY
> +		uint8_t security[0];
> +		/**< Security operation parameters
> +		 * - Must be accessed through a rte_security_op pointer
> +		 */
> +#endif
> +
>  	}; /**< operation specific parameters */
>  };

Is there any point to have this extra level of indirection?
Might be simply:

enum rte_crypto_op_type {
	....
+	RTE_CRYPTO_OP_TYPE_SEC_DOCSIS,
};
...
struct rte_crypto_op {
	....
	__extension__
        union {
                struct rte_crypto_sym_op sym[0];
                /**< Symmetric operation parameters */

                struct rte_crypto_asym_op asym[0];
                /**< Asymmetric operation parameters */

+	struct rte_security_docsis_op docsis[0];

        }; /**< operation specific parameters */
 
?


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-09 13:23     ` Ananyev, Konstantin
@ 2020-06-09 13:50       ` Coyle, David
  2020-06-10 10:40         ` Ananyev, Konstantin
  0 siblings, 1 reply; 92+ messages in thread
From: Coyle, David @ 2020-06-09 13:50 UTC (permalink / raw)
  To: Ananyev, Konstantin, akhil.goyal, Doherty, Declan,
	De Lara Guarch, Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi Konstantin, see below

> -----Original Message-----
> From: Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Sent: Tuesday, June 9, 2020 2:23 PM
> 
> 
> >
> >  /** Status of crypto operation */
> > @@ -121,6 +123,13 @@ struct rte_crypto_op {
> >  		struct rte_crypto_asym_op asym[0];
> >  		/**< Asymmetric operation parameters */
> >
> > +#ifdef RTE_LIBRTE_SECURITY
> > +		uint8_t security[0];
> > +		/**< Security operation parameters
> > +		 * - Must be accessed through a rte_security_op pointer
> > +		 */
> > +#endif
> > +
> >  	}; /**< operation specific parameters */  };
> 
> Is there any point to have this extra level of indirection?
> Might be simply:
> 
> enum rte_crypto_op_type {
> 	....
> +	RTE_CRYPTO_OP_TYPE_SEC_DOCSIS,
> };
> ...
> struct rte_crypto_op {
> 	....
> 	__extension__
>         union {
>                 struct rte_crypto_sym_op sym[0];
>                 /**< Symmetric operation parameters */
> 
>                 struct rte_crypto_asym_op asym[0];
>                 /**< Asymmetric operation parameters */
> 
> +	struct rte_security_docsis_op docsis[0];
> 
>         }; /**< operation specific parameters */
> 
> ?
[DC] This was to allow some form of extensibility and not to limit this to just DOCSIS.
If it's felt that having the extra level of indirection is overkill, it can be easily changed.

However, we cannot include a struct of type 'struct rte_security_docsis_op' (or 'struct rte_security_op')
directly here, without creating nasty circular dependency of includes between rte_cryptodev and
rte_security.

I had tried defining an opaque version 'struct rte_security_op' (i.e. no fields within the struct) here
in rte_crypto.h, but the compiler complained that it couldn't determine the size of the struct,
even though it's a zero length array.

That is why I had to use the uint8_t in 'uint8_t security[0];' - I don't like this, but I couldn't find
another way that kept the compiler happy and didn't create a circular dependency.



^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-09 13:50       ` Coyle, David
@ 2020-06-10 10:40         ` Ananyev, Konstantin
  2020-06-10 12:02           ` Coyle, David
  0 siblings, 1 reply; 92+ messages in thread
From: Ananyev, Konstantin @ 2020-06-10 10:40 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, De Lara Guarch,
	Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin



Hi David,

> >
> > >
> > >  /** Status of crypto operation */
> > > @@ -121,6 +123,13 @@ struct rte_crypto_op {
> > >  		struct rte_crypto_asym_op asym[0];
> > >  		/**< Asymmetric operation parameters */
> > >
> > > +#ifdef RTE_LIBRTE_SECURITY
> > > +		uint8_t security[0];
> > > +		/**< Security operation parameters
> > > +		 * - Must be accessed through a rte_security_op pointer
> > > +		 */
> > > +#endif
> > > +
> > >  	}; /**< operation specific parameters */  };
> >
> > Is there any point to have this extra level of indirection?
> > Might be simply:
> >
> > enum rte_crypto_op_type {
> > 	....
> > +	RTE_CRYPTO_OP_TYPE_SEC_DOCSIS,
> > };
> > ...
> > struct rte_crypto_op {
> > 	....
> > 	__extension__
> >         union {
> >                 struct rte_crypto_sym_op sym[0];
> >                 /**< Symmetric operation parameters */
> >
> >                 struct rte_crypto_asym_op asym[0];
> >                 /**< Asymmetric operation parameters */
> >
> > +	struct rte_security_docsis_op docsis[0];
> >
> >         }; /**< operation specific parameters */
> >
> > ?
> [DC] This was to allow some form of extensibility and not to limit this to just DOCSIS.
> If it's felt that having the extra level of indirection is overkill, it can be easily changed.
> 
> However, we cannot include a struct of type 'struct rte_security_docsis_op' (or 'struct rte_security_op')
> directly here, without creating nasty circular dependency of includes between rte_cryptodev and
> rte_security.
> 
> I had tried defining an opaque version 'struct rte_security_op' (i.e. no fields within the struct) here
> in rte_crypto.h, but the compiler complained that it couldn't determine the size of the struct,
> even though it's a zero length array.
> 
> That is why I had to use the uint8_t in 'uint8_t security[0];' - I don't like this, but I couldn't find
> another way that kept the compiler happy and didn't create a circular dependency.

I see... would it be an option to name this struct 'struct rte_sym_docsis_op and
and move actual definition inside lib/librte_cryptodev/rte_crypto_sym.h? 




^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-10 10:40         ` Ananyev, Konstantin
@ 2020-06-10 12:02           ` Coyle, David
  2020-06-11 12:21             ` Ananyev, Konstantin
  0 siblings, 1 reply; 92+ messages in thread
From: Coyle, David @ 2020-06-10 12:02 UTC (permalink / raw)
  To: Ananyev, Konstantin, akhil.goyal, Doherty, Declan,
	De Lara Guarch, Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi Konstantin,

> > >
> > > >
> > > >  /** Status of crypto operation */ @@ -121,6 +123,13 @@ struct
> > > > rte_crypto_op {
> > > >  		struct rte_crypto_asym_op asym[0];
> > > >  		/**< Asymmetric operation parameters */
> > > >
> > > > +#ifdef RTE_LIBRTE_SECURITY
> > > > +		uint8_t security[0];
> > > > +		/**< Security operation parameters
> > > > +		 * - Must be accessed through a rte_security_op pointer
> > > > +		 */
> > > > +#endif
> > > > +
> > > >  	}; /**< operation specific parameters */  };
> > >
> > > Is there any point to have this extra level of indirection?
> > > Might be simply:
> > >
> > > enum rte_crypto_op_type {
> > > 	....
> > > +	RTE_CRYPTO_OP_TYPE_SEC_DOCSIS,
> > > };
> > > ...
> > > struct rte_crypto_op {
> > > 	....
> > > 	__extension__
> > >         union {
> > >                 struct rte_crypto_sym_op sym[0];
> > >                 /**< Symmetric operation parameters */
> > >
> > >                 struct rte_crypto_asym_op asym[0];
> > >                 /**< Asymmetric operation parameters */
> > >
> > > +	struct rte_security_docsis_op docsis[0];
> > >
> > >         }; /**< operation specific parameters */
> > >
> > > ?
> > [DC] This was to allow some form of extensibility and not to limit this to just
> DOCSIS.
> > If it's felt that having the extra level of indirection is overkill, it can be easily
> changed.
> >
> > However, we cannot include a struct of type 'struct
> > rte_security_docsis_op' (or 'struct rte_security_op') directly here,
> > without creating nasty circular dependency of includes between
> rte_cryptodev and rte_security.
> >
> > I had tried defining an opaque version 'struct rte_security_op' (i.e.
> > no fields within the struct) here in rte_crypto.h, but the compiler
> > complained that it couldn't determine the size of the struct, even though
> it's a zero length array.
> >
> > That is why I had to use the uint8_t in 'uint8_t security[0];' - I
> > don't like this, but I couldn't find another way that kept the compiler happy
> and didn't create a circular dependency.
> 
> I see... would it be an option to name this struct 'struct rte_sym_docsis_op
> and and move actual definition inside
> lib/librte_cryptodev/rte_crypto_sym.h?
> 
[DC] It's certainly an option and would work but I don't think it's a good idea to be putting
protocol specific structs like this in rte_cryptodev - that's what rte_security is for.
Do you think it would be ok to do this?

I'd be interested to hear what cryptodev/security maintainers and others think too.
Akhil/Declan - any thoughts on best approach here?
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-10 12:02           ` Coyle, David
@ 2020-06-11 12:21             ` Ananyev, Konstantin
  2020-06-11 14:01               ` Coyle, David
  2020-06-23 18:38               ` Akhil Goyal
  0 siblings, 2 replies; 92+ messages in thread
From: Ananyev, Konstantin @ 2020-06-11 12:21 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, De Lara Guarch,
	Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi David,

> > > >
> > > > >
> > > > >  /** Status of crypto operation */ @@ -121,6 +123,13 @@ struct
> > > > > rte_crypto_op {
> > > > >  		struct rte_crypto_asym_op asym[0];
> > > > >  		/**< Asymmetric operation parameters */
> > > > >
> > > > > +#ifdef RTE_LIBRTE_SECURITY
> > > > > +		uint8_t security[0];
> > > > > +		/**< Security operation parameters
> > > > > +		 * - Must be accessed through a rte_security_op pointer
> > > > > +		 */
> > > > > +#endif
> > > > > +
> > > > >  	}; /**< operation specific parameters */  };
> > > >
> > > > Is there any point to have this extra level of indirection?
> > > > Might be simply:
> > > >
> > > > enum rte_crypto_op_type {
> > > > 	....
> > > > +	RTE_CRYPTO_OP_TYPE_SEC_DOCSIS,
> > > > };
> > > > ...
> > > > struct rte_crypto_op {
> > > > 	....
> > > > 	__extension__
> > > >         union {
> > > >                 struct rte_crypto_sym_op sym[0];
> > > >                 /**< Symmetric operation parameters */
> > > >
> > > >                 struct rte_crypto_asym_op asym[0];
> > > >                 /**< Asymmetric operation parameters */
> > > >
> > > > +	struct rte_security_docsis_op docsis[0];
> > > >
> > > >         }; /**< operation specific parameters */
> > > >
> > > > ?
> > > [DC] This was to allow some form of extensibility and not to limit this to just
> > DOCSIS.
> > > If it's felt that having the extra level of indirection is overkill, it can be easily
> > changed.
> > >
> > > However, we cannot include a struct of type 'struct
> > > rte_security_docsis_op' (or 'struct rte_security_op') directly here,
> > > without creating nasty circular dependency of includes between
> > rte_cryptodev and rte_security.
> > >
> > > I had tried defining an opaque version 'struct rte_security_op' (i.e.
> > > no fields within the struct) here in rte_crypto.h, but the compiler
> > > complained that it couldn't determine the size of the struct, even though
> > it's a zero length array.
> > >
> > > That is why I had to use the uint8_t in 'uint8_t security[0];' - I
> > > don't like this, but I couldn't find another way that kept the compiler happy
> > and didn't create a circular dependency.
> >
> > I see... would it be an option to name this struct 'struct rte_sym_docsis_op
> > and and move actual definition inside
> > lib/librte_cryptodev/rte_crypto_sym.h?
> >
> [DC] It's certainly an option and would work but I don't think it's a good idea to be putting
> protocol specific structs like this in rte_cryptodev - that's what rte_security is for.
> Do you think it would be ok to do this?

I personally don't see a problem with this.
In fact, as an extra  thought - why we can't have docsis xform defined in
lib/librte_cryptodev/rte_crypto_sym.h too, and then just have it  as a member
inside struct rte_crypto_sym_xform union?
Then we can have rte_cryptodev_sym_session that supports docsis stuff.

> 
> I'd be interested to hear what cryptodev/security maintainers and others think too.
> Akhil/Declan - any thoughts on best approach here?


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-11 12:21             ` Ananyev, Konstantin
@ 2020-06-11 14:01               ` Coyle, David
  2020-06-23 18:38               ` Akhil Goyal
  1 sibling, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-06-11 14:01 UTC (permalink / raw)
  To: Ananyev, Konstantin, akhil.goyal, Doherty, Declan,
	De Lara Guarch, Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi Konstantin,

> > > > >
> > > > > >
> > > > > >  /** Status of crypto operation */ @@ -121,6 +123,13 @@ struct
> > > > > > rte_crypto_op {
> > > > > >  		struct rte_crypto_asym_op asym[0];
> > > > > >  		/**< Asymmetric operation parameters */
> > > > > >
> > > > > > +#ifdef RTE_LIBRTE_SECURITY
> > > > > > +		uint8_t security[0];
> > > > > > +		/**< Security operation parameters
> > > > > > +		 * - Must be accessed through a rte_security_op
> pointer
> > > > > > +		 */
> > > > > > +#endif
> > > > > > +
> > > > > >  	}; /**< operation specific parameters */  };
> > > > >
> > > > > Is there any point to have this extra level of indirection?
> > > > > Might be simply:
> > > > >
> > > > > enum rte_crypto_op_type {
> > > > > 	....
> > > > > +	RTE_CRYPTO_OP_TYPE_SEC_DOCSIS,
> > > > > };
> > > > > ...
> > > > > struct rte_crypto_op {
> > > > > 	....
> > > > > 	__extension__
> > > > >         union {
> > > > >                 struct rte_crypto_sym_op sym[0];
> > > > >                 /**< Symmetric operation parameters */
> > > > >
> > > > >                 struct rte_crypto_asym_op asym[0];
> > > > >                 /**< Asymmetric operation parameters */
> > > > >
> > > > > +	struct rte_security_docsis_op docsis[0];
> > > > >
> > > > >         }; /**< operation specific parameters */
> > > > >
> > > > > ?
> > > > [DC] This was to allow some form of extensibility and not to limit
> > > > this to just
> > > DOCSIS.
> > > > If it's felt that having the extra level of indirection is
> > > > overkill, it can be easily
> > > changed.
> > > >
> > > > However, we cannot include a struct of type 'struct
> > > > rte_security_docsis_op' (or 'struct rte_security_op') directly
> > > > here, without creating nasty circular dependency of includes
> > > > between
> > > rte_cryptodev and rte_security.
> > > >
> > > > I had tried defining an opaque version 'struct rte_security_op' (i.e.
> > > > no fields within the struct) here in rte_crypto.h, but the
> > > > compiler complained that it couldn't determine the size of the
> > > > struct, even though
> > > it's a zero length array.
> > > >
> > > > That is why I had to use the uint8_t in 'uint8_t security[0];' - I
> > > > don't like this, but I couldn't find another way that kept the
> > > > compiler happy
> > > and didn't create a circular dependency.
> > >
> > > I see... would it be an option to name this struct 'struct
> > > rte_sym_docsis_op and and move actual definition inside
> > > lib/librte_cryptodev/rte_crypto_sym.h?
> > >
> > [DC] It's certainly an option and would work but I don't think it's a
> > good idea to be putting protocol specific structs like this in rte_cryptodev -
> that's what rte_security is for.
> > Do you think it would be ok to do this?
> 
> I personally don't see a problem with this.
> In fact, as an extra  thought - why we can't have docsis xform defined in
> lib/librte_cryptodev/rte_crypto_sym.h too, and then just have it  as a
> member inside struct rte_crypto_sym_xform union?
> Then we can have rte_cryptodev_sym_session that supports docsis stuff.
> 
[DC] Because DOCSIS protocol and CRC are not specifically crypto related is why
we initially went down the rawdev/multi-fn route and now the rte_security route.
I think adding docsis xforms/ops and CRC related data to cryptodev would be adding
too much non-crypto algorithm related stuff to this library. There would then be some
protocols like IPSec and PDCP with their definitions in rte_security and others like
DOCSIS in rte_cryptodev - that doesn't seem good to me.

Yes, from a DOCSIS equipment vendors point-of-view, who already use cryptodev
for just encryption/decryption, adding DOCSIS to cryptodev would be best
for them in order to get better DOCSIS support in DPDK as it would mean less
churn for their applications. However, from a DPDK point-of-view, I don't think it
would be correct to do this.

That's just my opinion, and again I'd be interested to hear other people's thoughts.

> >
> > I'd be interested to hear what cryptodev/security maintainers and others
> think too.
> > Akhil/Declan - any thoughts on best approach here?


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol
  2020-06-04 15:13 ` [dpdk-dev] [PATCH 0/3] add support for DOCSIS protocol to security library David Coyle
                     ` (2 preceding siblings ...)
  2020-06-04 15:13   ` [dpdk-dev] [PATCH 3/3] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
@ 2020-06-23 10:14   ` David Coyle
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 1/6] cryptodev: add security operation to crypto operation David Coyle
                       ` (7 more replies)
  3 siblings, 8 replies; 92+ messages in thread
From: David Coyle @ 2020-06-23 10:14 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle

Introduction
============

This patchset adds support for the DOCSIS protocol to the DPDK Security
API (rte_security), to be used by the AESNI-MB and QAT crypto devices to
combine and accelerate Crypto and CRC functions of the DOCSIS protocol
into a single operation.

Performing these functions in parallel as a single operation can enable a
significant performance improvement in a DPDK-based DOCSIS MAC pipeline.


Background
==========

A number of approaches to combine DOCSIS Crypto and CRC functions have
been discussed in the DPDK community to date, namely:
1) adding a new rte_accelerator API, to provide a generic interface for
   combining operations of different types
2) using rawdev through a multi-function interface, again to provide a
   generic interface for combining operations of different types
3) adding support for DOCSIS Crypto-CRC to rte_security

The third option above is the preferred approach for the following
reasons:
- it addresses the immediate use case to add DOCSIS Crypto-CRC support to
  DPDK so that it can be consumed easily by cable equipment vendors
- it uses an already existing framework in DPDK
- it will mean much less code churn in DOCSIS applications, which already
  use rte_cryptodev for encryption/decryption


Use Cases
=========

The primary use case for this proposal has already been mentioned, namely
to add DOCSIS Crypto-CRC support to DPDK:

- DOCSIS MAC: Crypto-CRC
	- Order:
		- Downstream: CRC, Encrypt
		- Upstream: Decrypt, CRC
	- Specifications:
		- Crypto: 128-bit and 256-bit AES-CFB encryption variant
		  for DOCSIS as described in section 11.1 of DOCSIS 3.1
		  Security Specification
		  (https://apps.cablelabs.com/specification/CM-SP-SECv3.1)
		- CRC: Ethernet 32-bit CRC as defined in
		  Ethernet/[ISO/IEC 8802-3]

Note that support for these chained operations is already available in
the Intel IPSec Multi-Buffer library.

However, other DOCSIS protocol functions could be optimized too in the
future using the same rte_security API for DOCSIS (e.g. Header Checksum
(HCS) calculation).

v1:
* added proposed API changes
* added security capabilities to aesni_mb crypto PMD

v2:
* added rte_security and rte_cryptodev code changes
* added AESNI MB crypto PMD code changes
* added QAT SYM crypto PMD code changes
* added crypto unit tests
* added security unit tests

David Coyle (6):
  cryptodev: add security operation to crypto operation
  security: add support for DOCSIS protocol
  crypto/aesni_mb: add support for DOCSIS protocol
  crypto/qat: add support for DOCSIS protocol
  test/crypto: add DOCSIS security test cases
  test/security: add DOCSIS capability check tests

 app/test/test_cryptodev.c                     |  552 ++++++
 ...t_cryptodev_security_docsis_test_vectors.h | 1544 +++++++++++++++++
 app/test/test_security.c                      |  139 ++
 drivers/common/qat/Makefile                   |    3 +
 .../crypto/aesni_mb/aesni_mb_pmd_private.h    |   19 +-
 drivers/crypto/aesni_mb/meson.build           |    2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c    |  316 +++-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    |  127 ++
 drivers/crypto/qat/meson.build                |    2 +
 drivers/crypto/qat/qat_sym.c                  |  139 +-
 drivers/crypto/qat/qat_sym.h                  |   82 +-
 drivers/crypto/qat/qat_sym_capabilities.h     |   44 +
 drivers/crypto/qat/qat_sym_pmd.c              |   53 +-
 drivers/crypto/qat/qat_sym_pmd.h              |    4 +
 drivers/crypto/qat/qat_sym_session.c          |  148 ++
 drivers/crypto/qat/qat_sym_session.h          |   12 +
 lib/librte_cryptodev/rte_crypto.h             |   19 +-
 lib/librte_cryptodev/rte_cryptodev.c          |    5 +-
 lib/librte_security/rte_security.c            |    7 +
 lib/librte_security/rte_security.h            |  116 +-
 20 files changed, 3271 insertions(+), 62 deletions(-)
 create mode 100644 app/test/test_cryptodev_security_docsis_test_vectors.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v2 1/6] cryptodev: add security operation to crypto operation
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
@ 2020-06-23 10:14     ` David Coyle
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol David Coyle
                       ` (6 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-06-23 10:14 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add a new security operation field to the crypto operation to allow
protocol specific parameters be defined for a crypto operation.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 lib/librte_cryptodev/rte_crypto.h    | 19 +++++++++++++++++--
 lib/librte_cryptodev/rte_cryptodev.c |  5 ++++-
 2 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h
index fd5ef3a87..da0635e73 100644
--- a/lib/librte_cryptodev/rte_crypto.h
+++ b/lib/librte_cryptodev/rte_crypto.h
@@ -31,8 +31,10 @@ enum rte_crypto_op_type {
 	/**< Undefined operation type */
 	RTE_CRYPTO_OP_TYPE_SYMMETRIC,
 	/**< Symmetric operation */
-	RTE_CRYPTO_OP_TYPE_ASYMMETRIC
+	RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
 	/**< Asymmetric operation */
+	RTE_CRYPTO_OP_TYPE_SECURITY
+	/**< Security operation */
 };
 
 /** Status of crypto operation */
@@ -121,9 +123,16 @@ struct rte_crypto_op {
 		struct rte_crypto_asym_op asym[0];
 		/**< Asymmetric operation parameters */
 
+		uint8_t security[0];
+		/**< Security operation parameters
+		 * - Must be accessed through a rte_security_op pointer
+		 */
 	}; /**< operation specific parameters */
 };
 
+/** Maximum size of security crypto op */
+#define RTE_CRYPTO_OP_SECURITY_MAX_SZ (88U)
+
 /**
  * Reset the fields of a crypto operation to their default values.
  *
@@ -143,7 +152,10 @@ __rte_crypto_op_reset(struct rte_crypto_op *op, enum rte_crypto_op_type type)
 		break;
 	case RTE_CRYPTO_OP_TYPE_ASYMMETRIC:
 		memset(op->asym, 0, sizeof(struct rte_crypto_asym_op));
-	break;
+		break;
+	case RTE_CRYPTO_OP_TYPE_SECURITY:
+		memset(op->security, 0, RTE_CRYPTO_OP_SECURITY_MAX_SZ);
+		break;
 	case RTE_CRYPTO_OP_TYPE_UNDEFINED:
 	default:
 		break;
@@ -317,6 +329,9 @@ __rte_crypto_op_get_priv_data(struct rte_crypto_op *op, uint32_t size)
 			if (op->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC)
 				return (void *)((uint8_t *)(op + 1) +
 					sizeof(struct rte_crypto_asym_op));
+			if (op->type == RTE_CRYPTO_OP_TYPE_SECURITY)
+				return (void *)((uint8_t *)(op + 1) +
+					RTE_CRYPTO_OP_SECURITY_MAX_SZ);
 		}
 	}
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index e37b83afd..41128f437 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -1871,9 +1871,12 @@ rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
 		elt_size += sizeof(struct rte_crypto_sym_op);
 	} else if (type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
 		elt_size += sizeof(struct rte_crypto_asym_op);
+	} else if (type == RTE_CRYPTO_OP_TYPE_SECURITY) {
+		elt_size += RTE_CRYPTO_OP_SECURITY_MAX_SZ;
 	} else if (type == RTE_CRYPTO_OP_TYPE_UNDEFINED) {
 		elt_size += RTE_MAX(sizeof(struct rte_crypto_sym_op),
-		                    sizeof(struct rte_crypto_asym_op));
+				    RTE_MAX(sizeof(struct rte_crypto_asym_op),
+					    RTE_CRYPTO_OP_SECURITY_MAX_SZ));
 	} else {
 		CDEV_LOG_ERR("Invalid op_type\n");
 		return NULL;
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 1/6] cryptodev: add security operation to crypto operation David Coyle
@ 2020-06-23 10:14     ` David Coyle
  2020-06-23 17:29       ` De Lara Guarch, Pablo
  2020-06-23 18:06       ` Akhil Goyal
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 3/6] crypto/aesni_mb: " David Coyle
                       ` (5 subsequent siblings)
  7 siblings, 2 replies; 92+ messages in thread
From: David Coyle @ 2020-06-23 10:14 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support for DOCSIS protocol to rte_security library. This support
currently comprises the combination of Crypto and CRC operations.

A security operation definition is also added. This allow security
protocol related parameters be specified at the operation level. For
DOCSIS, these parameters include CRC length and offset. The security
operation is accessed via a crypto operation.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 lib/librte_security/rte_security.c |   7 ++
 lib/librte_security/rte_security.h | 116 ++++++++++++++++++++++++++++-
 2 files changed, 120 insertions(+), 3 deletions(-)

diff --git a/lib/librte_security/rte_security.c b/lib/librte_security/rte_security.c
index dc9a3e89c..e3844bf7e 100644
--- a/lib/librte_security/rte_security.c
+++ b/lib/librte_security/rte_security.c
@@ -173,6 +173,13 @@ rte_security_capability_get(struct rte_security_ctx *instance,
 				if (capability->pdcp.domain ==
 							idx->pdcp.domain)
 					return capability;
+			} else if (idx->protocol ==
+						RTE_SECURITY_PROTOCOL_DOCSIS) {
+				if (capability->docsis.direction ==
+							idx->docsis.direction &&
+					capability->docsis.crc_size ==
+							idx->docsis.crc_size)
+					return capability;
 			}
 		}
 	}
diff --git a/lib/librte_security/rte_security.h b/lib/librte_security/rte_security.h
index 747830d67..25e3179e9 100644
--- a/lib/librte_security/rte_security.h
+++ b/lib/librte_security/rte_security.h
@@ -293,6 +293,30 @@ struct rte_security_pdcp_xform {
 	uint32_t hfn_ovrd;
 };
 
+/** DOCSIS direction */
+enum rte_security_docsis_direction {
+	RTE_SECURITY_DOCSIS_UPLINK,
+	/**< Uplink
+	 * - Decryption, followed by CRC Verification
+	 */
+	RTE_SECURITY_DOCSIS_DOWNLINK,
+	/**< Downlink
+	 * - CRC Generation, followed by Encryption
+	 */
+};
+
+/**
+ * DOCSIS security session configuration.
+ *
+ * This structure contains data required to create a DOCSIS security session.
+ */
+struct rte_security_docsis_xform {
+	enum rte_security_docsis_direction direction;
+	/** DOCSIS direction */
+	uint16_t crc_size;
+	/**< CRC size in bytes */
+};
+
 /**
  * Security session action type.
  */
@@ -325,6 +349,8 @@ enum rte_security_session_protocol {
 	/**< MACSec Protocol */
 	RTE_SECURITY_PROTOCOL_PDCP,
 	/**< PDCP Protocol */
+	RTE_SECURITY_PROTOCOL_DOCSIS,
+	/**< DOCSIS Protocol */
 };
 
 /**
@@ -340,6 +366,7 @@ struct rte_security_session_conf {
 		struct rte_security_ipsec_xform ipsec;
 		struct rte_security_macsec_xform macsec;
 		struct rte_security_pdcp_xform pdcp;
+		struct rte_security_docsis_xform docsis;
 	};
 	/**< Configuration parameters for security session */
 	struct rte_crypto_sym_xform *crypto_xform;
@@ -355,6 +382,63 @@ struct rte_security_session {
 	/**< Opaque user defined data */
 };
 
+/**
+ * DOCSIS operation parameters
+ */
+struct rte_security_docsis_op {
+	struct rte_crypto_sym_op crypto_sym;
+	/**< Symmetric crypto operation parameters */
+
+	struct {
+		uint16_t offset;
+		/**<
+		 * Starting point for CRC processing, specified
+		 * as the number of bytes from start of the packet in
+		 * the source mbuf in crypto_sym
+		 */
+		uint16_t length;
+		/**<
+		 * The length, in bytes, of the source mbuf on which the
+		 * CRC will be computed
+		 */
+	} crc;
+	/**< CRC operation parameters */
+
+	uint64_t reserved;
+	/**< Reserved for future use */
+};
+
+/**
+ * Security operation types
+ */
+enum rte_security_op_type {
+	RTE_SECURITY_OP_TYPE_DOCSIS = 1
+	/**< DOCSIS operation */
+};
+
+/**
+ * Security operation parameters
+ *
+ * @note If the size of this struct changes, it may be also necessary to update
+ * the RTE_CRYPTO_OP_SECURITY_MAX_SZ define
+ */
+struct rte_security_op {
+	enum rte_security_op_type type;
+	/**< Type of operation */
+	RTE_STD_C11
+	union {
+		struct rte_security_docsis_op docsis;
+	};
+	/**< Parameters for security operation */
+};
+
+/* Macro to check the size of a struct at compile time */
+#define _SECURITY_STRUCT_LEN_CHECK(n, X) enum security_static_assert_enum_##X \
+	{ security_static_assert_##X = (n)/((sizeof(struct X) <= (n)) ? 1 : 0) }
+
+/* Check the size of the rte_security_op struct */
+_SECURITY_STRUCT_LEN_CHECK(RTE_CRYPTO_OP_SECURITY_MAX_SZ, rte_security_op);
+
 /**
  * Create security session as specified by the session configuration
  *
@@ -496,12 +580,22 @@ static inline int
 rte_security_attach_session(struct rte_crypto_op *op,
 			    struct rte_security_session *sess)
 {
-	if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC))
-		return -EINVAL;
+	struct rte_security_op *s_op;
+	int ret = -EINVAL;
+
+	if (likely(op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
+		ret = __rte_security_attach_session(op->sym, sess);
+	} else if (op->type == RTE_CRYPTO_OP_TYPE_SECURITY) {
+		s_op = (struct rte_security_op *)&op->security;
+		if (s_op->type == RTE_SECURITY_OP_TYPE_DOCSIS)
+			ret = __rte_security_attach_session(
+						&s_op->docsis.crypto_sym,
+						sess);
+	}
 
 	op->sess_type =  RTE_CRYPTO_OP_SECURITY_SESSION;
 
-	return __rte_security_attach_session(op->sym, sess);
+	return ret;
 }
 
 struct rte_security_macsec_stats {
@@ -523,6 +617,10 @@ struct rte_security_pdcp_stats {
 	uint64_t reserved;
 };
 
+struct rte_security_docsis_stats {
+	uint64_t reserved;
+};
+
 struct rte_security_stats {
 	enum rte_security_session_protocol protocol;
 	/**< Security protocol to be configured */
@@ -532,6 +630,7 @@ struct rte_security_stats {
 		struct rte_security_macsec_stats macsec;
 		struct rte_security_ipsec_stats ipsec;
 		struct rte_security_pdcp_stats pdcp;
+		struct rte_security_docsis_stats docsis;
 	};
 };
 
@@ -591,6 +690,13 @@ struct rte_security_capability {
 			/**< Capability flags, see RTE_SECURITY_PDCP_* */
 		} pdcp;
 		/**< PDCP capability */
+		struct {
+			enum rte_security_docsis_direction direction;
+			/**< DOCSIS direction */
+			uint16_t crc_size;
+			/**< CRC size in bytes */
+		} docsis;
+		/**< DOCSIS capability */
 	};
 
 	const struct rte_cryptodev_capabilities *crypto_capabilities;
@@ -649,6 +755,10 @@ struct rte_security_capability_idx {
 			enum rte_security_pdcp_domain domain;
 			uint32_t capa_flags;
 		} pdcp;
+		struct {
+			enum rte_security_docsis_direction direction;
+			uint16_t crc_size;
+		} docsis;
 	};
 };
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v2 3/6] crypto/aesni_mb: add support for DOCSIS protocol
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 1/6] cryptodev: add security operation to crypto operation David Coyle
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol David Coyle
@ 2020-06-23 10:14     ` David Coyle
  2020-06-23 17:57       ` De Lara Guarch, Pablo
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 4/6] crypto/qat: " David Coyle
                       ` (4 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-23 10:14 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support to the AESNI-MB PMD for the DOCSIS protocol, through the
rte_security API. This, therefore, includes adding support for the
rte_security API to this PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 .../crypto/aesni_mb/aesni_mb_pmd_private.h    |  19 +-
 drivers/crypto/aesni_mb/meson.build           |   2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c    | 316 +++++++++++++++++-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    | 127 +++++++
 4 files changed, 457 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h b/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
index 347b4b7e0..b4ad27792 100644
--- a/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
+++ b/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
@@ -7,6 +7,12 @@
 
 #include <intel-ipsec-mb.h>
 
+#if defined(RTE_LIBRTE_SECURITY) && IMB_VERSION_NUM >= IMB_VERSION(0, 54, 0)
+#define AESNI_MB_DOCSIS_SEC_ENABLED 1
+#include <rte_security.h>
+#include <rte_security_driver.h>
+#endif
+
 enum aesni_mb_vector_mode {
 	RTE_AESNI_MB_NOT_SUPPORTED = 0,
 	RTE_AESNI_MB_SSE,
@@ -272,8 +278,19 @@ aesni_mb_set_session_parameters(const MB_MGR *mb_mgr,
 		struct aesni_mb_session *sess,
 		const struct rte_crypto_sym_xform *xform);
 
-/** device specific operations function pointer structure */
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+extern int
+aesni_mb_set_docsis_sec_session_parameters(
+		__rte_unused struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf,
+		void *sess);
+#endif
+
+/** device specific operations function pointer structures */
 extern struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops;
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+extern struct rte_security_ops *rte_aesni_mb_pmd_sec_ops;
+#endif
 
 extern uint32_t
 aesni_mb_cpu_crypto_process_bulk(struct rte_cryptodev *dev,
diff --git a/drivers/crypto/aesni_mb/meson.build b/drivers/crypto/aesni_mb/meson.build
index e557e0103..419b4743f 100644
--- a/drivers/crypto/aesni_mb/meson.build
+++ b/drivers/crypto/aesni_mb/meson.build
@@ -22,4 +22,4 @@ else
 endif
 
 sources = files('rte_aesni_mb_pmd.c', 'rte_aesni_mb_pmd_ops.c')
-deps += ['bus_vdev']
+deps += ['bus_vdev', 'net', 'security']
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 2d688f4d3..1fc0c83c3 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -12,6 +12,7 @@
 #include <rte_malloc.h>
 #include <rte_cpuflags.h>
 #include <rte_per_lcore.h>
+#include <rte_ether.h>
 
 #include "aesni_mb_pmd_private.h"
 
@@ -720,6 +721,136 @@ aesni_mb_set_session_parameters(const MB_MGR *mb_mgr,
 	return 0;
 }
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/** Check DOCSIS security session configuration is valid */
+static int
+check_docsis_sec_session(struct rte_security_session_conf *conf)
+{
+	struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
+	struct rte_security_docsis_xform *docsis = &conf->docsis;
+
+	/* CRC generate -> Cipher encrypt */
+	if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type ==	RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length == AES_128_BYTES ||
+		     crypto_sym->cipher.key.length == AES_256_BYTES) &&
+		    crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+		    crypto_sym->next == NULL &&
+		    docsis->crc_size == RTE_ETHER_CRC_LEN) {
+			return 0;
+		}
+	/* Cipher decrypt -> CRC verify */
+	} else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length == AES_128_BYTES ||
+		     crypto_sym->cipher.key.length == AES_256_BYTES) &&
+		    crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+		    crypto_sym->next == NULL &&
+		    docsis->crc_size == RTE_ETHER_CRC_LEN) {
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/** Set DOCSIS security session auth (CRC) parameters */
+static int
+aesni_mb_set_docsis_sec_session_auth_parameters(struct aesni_mb_session *sess,
+		struct rte_security_docsis_xform *xform)
+{
+	if (xform == NULL) {
+		AESNI_MB_LOG(ERR, "Invalid DOCSIS xform");
+		return -EINVAL;
+	}
+
+	/* Select CRC generate/verify */
+	if (xform->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+		sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY;
+	} else if (xform->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+		sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE;
+	} else {
+		AESNI_MB_LOG(ERR, "Unsupported DOCSIS direction");
+		return -ENOTSUP;
+	}
+
+	sess->auth.req_digest_len = xform->crc_size;
+	sess->auth.gen_digest_len = xform->crc_size;
+
+	return 0;
+}
+
+/**
+ * Parse DOCSIS security session configuration and set private session
+ * parameters
+ */
+int
+aesni_mb_set_docsis_sec_session_parameters(
+		__rte_unused struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf,
+		void *sess)
+{
+	struct rte_security_docsis_xform *docsis_xform;
+	struct rte_crypto_sym_xform *cipher_xform;
+	struct aesni_mb_session *aesni_sess = sess;
+	struct aesni_mb_private *internals = dev->data->dev_private;
+	int ret;
+
+	ret = check_docsis_sec_session(conf);
+	if (ret) {
+		AESNI_MB_LOG(ERR, "Unsupported DOCSIS security configuration");
+		return ret;
+	}
+
+	switch (conf->docsis.direction) {
+	case RTE_SECURITY_DOCSIS_UPLINK:
+		aesni_sess->chain_order = CIPHER_HASH;
+		docsis_xform = &conf->docsis;
+		cipher_xform = conf->crypto_xform;
+		break;
+	case RTE_SECURITY_DOCSIS_DOWNLINK:
+		aesni_sess->chain_order = HASH_CIPHER;
+		cipher_xform = conf->crypto_xform;
+		docsis_xform = &conf->docsis;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Default IV length = 0 */
+	aesni_sess->iv.length = 0;
+
+	ret = aesni_mb_set_docsis_sec_session_auth_parameters(aesni_sess,
+			docsis_xform);
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Invalid/unsupported DOCSIS parameters");
+		return -EINVAL;
+	}
+
+	ret = aesni_mb_set_session_cipher_parameters(internals->mb_mgr,
+			aesni_sess, cipher_xform);
+
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Invalid/unsupported cipher parameters");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
 /**
  * burst enqueue, place crypto operations on ingress queue for processing.
  *
@@ -1158,6 +1289,131 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
 	return 0;
 }
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/** Get multi buffer session for a security op */
+static inline struct aesni_mb_session *
+get_sec_op_session(struct rte_crypto_op *op,
+		struct rte_crypto_sym_op *crypto_sym)
+{
+	struct aesni_mb_session *sess = NULL;
+
+	if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+		if (likely(crypto_sym->sec_session != NULL))
+			sess = (struct aesni_mb_session *)
+					get_sec_session_private_data(
+						crypto_sym->sec_session);
+	}
+
+	if (unlikely(sess == NULL))
+		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
+
+	return sess;
+}
+
+/**
+ * Process a crypto operation containing a security op and complete a
+ * JOB_AES_HMAC job structure for submission to the multi buffer library for
+ * processing.
+ */
+static inline int
+set_sec_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
+		struct rte_crypto_op *op, uint8_t *digest_idx)
+{
+	struct rte_mbuf *m_src, *m_dst;
+	struct rte_security_op *s_op;
+	struct rte_security_docsis_op *d_op;
+	struct rte_crypto_sym_op *sym;
+	struct aesni_mb_session *session;
+
+	s_op = (struct rte_security_op *)&op->security;
+
+	/* Only DOCSIS protocol operations supported now */
+	if (s_op->type != RTE_SECURITY_OP_TYPE_DOCSIS) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return -1;
+	}
+
+	d_op = &s_op->docsis;
+	sym = &d_op->crypto_sym;
+
+	session = get_sec_op_session(op, sym);
+	if (unlikely(session == NULL)) {
+		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
+		return -1;
+	}
+
+	m_src = sym->m_src;
+
+	if (likely(sym->m_dst == NULL || sym->m_dst == m_src)) {
+		/* in-place operation */
+		m_dst = m_src;
+	} else {
+		/* out-of-place operation not supported */
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return -ENOTSUP;
+	}
+
+	/* Set crypto operation */
+	job->chain_order = session->chain_order;
+
+	/* Set cipher parameters */
+	job->cipher_direction = session->cipher.direction;
+	job->cipher_mode = session->cipher.mode;
+
+	job->aes_key_len_in_bytes = session->cipher.key_length_in_bytes;
+	job->aes_enc_key_expanded = session->cipher.expanded_aes_keys.encode;
+	job->aes_dec_key_expanded = session->cipher.expanded_aes_keys.decode;
+
+	/* Set IV parameters */
+	job->iv_len_in_bytes = session->iv.length;
+	job->iv = (uint8_t *)op + session->iv.offset;
+
+	/* Set authentication parameters */
+	job->hash_alg = session->auth.algo;
+
+	/* Set digest output location */
+	job->auth_tag_output = qp->temp_digests[*digest_idx];
+	*digest_idx = (*digest_idx + 1) % MAX_JOBS;
+
+	/* Set digest length */
+	job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
+
+	/* Set data parameters */
+	job->src = rte_pktmbuf_mtod(m_src, uint8_t *);
+	job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *,
+						sym->cipher.data.offset);
+
+	job->cipher_start_src_offset_in_bytes = sym->cipher.data.offset;
+	job->msg_len_to_cipher_in_bytes = sym->cipher.data.length;
+
+	job->hash_start_src_offset_in_bytes = d_op->crc.offset;
+	job->msg_len_to_hash_in_bytes = d_op->crc.length;
+
+	job->user_data = op;
+
+	return 0;
+}
+
+static inline void
+verify_docsis_sec_crc(JOB_AES_HMAC *job, uint16_t crc_len, uint8_t *status)
+{
+	uint16_t crc_offset;
+	uint8_t *crc;
+
+	if (!job->msg_len_to_hash_in_bytes)
+		return;
+
+	crc_offset = job->hash_start_src_offset_in_bytes +
+			job->msg_len_to_hash_in_bytes -
+			job->cipher_start_src_offset_in_bytes;
+	crc = job->dst + crc_offset;
+
+	/* Verify CRC (at the end of the message) */
+	if (memcmp(job->auth_tag_output, crc, crc_len) != 0)
+		*status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+}
+#endif
+
 static inline void
 verify_digest(JOB_AES_HMAC *job, void *digest, uint16_t len, uint8_t *status)
 {
@@ -1196,9 +1452,27 @@ static inline struct rte_crypto_op *
 post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)
 {
 	struct rte_crypto_op *op = (struct rte_crypto_op *)job->user_data;
-	struct aesni_mb_session *sess = get_sym_session_private_data(
-							op->sym->session,
-							cryptodev_driver_id);
+	struct aesni_mb_session *sess = NULL;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	struct rte_security_op *sec_op = NULL;
+
+	if (unlikely(op->type == RTE_CRYPTO_OP_TYPE_SECURITY)) {
+		/*
+		 * Assuming at this point that if it's a security type op, that
+		 * this is for DOCSIS
+		 */
+		sec_op = (struct rte_security_op *)&op->security;
+		struct rte_crypto_sym_op *crypto_sym =
+						&sec_op->docsis.crypto_sym;
+		sess = get_sec_session_private_data(crypto_sym->sec_session);
+	} else
+#endif
+	{
+		sess = get_sym_session_private_data(op->sym->session,
+						cryptodev_driver_id);
+	}
+
 	if (unlikely(sess == NULL)) {
 		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
 		return op;
@@ -1220,6 +1494,12 @@ post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)
 						op->sym->aead.digest.data,
 						sess->auth.req_digest_len,
 						&op->status);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+				else if (sec_op != NULL)
+					verify_docsis_sec_crc(job,
+						sess->auth.req_digest_len,
+						&op->status);
+#endif
 				else
 					verify_digest(job,
 						op->sym->auth.digest.data,
@@ -1382,7 +1662,14 @@ aesni_mb_pmd_dequeue_burst(void *queue_pair, struct rte_crypto_op **ops,
 		if (retval < 0)
 			break;
 
-		retval = set_mb_job_params(job, qp, op, &digest_idx);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+		if (unlikely(op->type == RTE_CRYPTO_OP_TYPE_SECURITY))
+			retval = set_sec_mb_job_params(job, qp, op,
+						&digest_idx);
+		else
+#endif
+			retval = set_mb_job_params(job, qp, op, &digest_idx);
+
 		if (unlikely(retval != 0)) {
 			qp->stats.dequeue_err_count++;
 			set_job_null_op(job, op);
@@ -1619,6 +1906,9 @@ cryptodev_aesni_mb_create(const char *name,
 	struct aesni_mb_private *internals;
 	enum aesni_mb_vector_mode vector_mode;
 	MB_MGR *mb_mgr;
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	struct rte_security_ctx *security_instance;
+#endif
 
 	dev = rte_cryptodev_pmd_create(name, &vdev->device, init_params);
 	if (dev == NULL) {
@@ -1647,7 +1937,23 @@ cryptodev_aesni_mb_create(const char *name,
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_SESSIONLESS;
+			RTE_CRYPTODEV_FF_SYM_SESSIONLESS
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+			| RTE_CRYPTODEV_FF_SECURITY
+#endif
+			;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	security_instance = rte_malloc("aesni_mb_sec",
+				sizeof(struct rte_security_ctx), 0);
+	if (security_instance == NULL)
+		AESNI_MB_LOG(ERR, "rte_security_ctx memory alloc failed\n");
+
+	security_instance->device = (void *)dev;
+	security_instance->ops = rte_aesni_mb_pmd_sec_ops;
+	security_instance->sess_cnt = 0;
+	dev->security_ctx = security_instance;
+#endif
 
 	/* Check CPU for support for AES instruction set */
 	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AES))
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
index 8c5e0cd92..4294d416c 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -7,6 +7,7 @@
 #include <rte_string_fns.h>
 #include <rte_common.h>
 #include <rte_malloc.h>
+#include <rte_ether.h>
 #include <rte_cryptodev_pmd.h>
 
 #include "aesni_mb_pmd_private.h"
@@ -499,6 +500,57 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+static const struct rte_cryptodev_capabilities
+					aesni_mb_pmd_security_crypto_cap[] = {
+	{	/* AES DOCSIS BPI */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		{.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			{.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 16
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}, }
+		}, }
+	},
+
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability aesni_mb_pmd_security_cap[] = {
+	{	/* DOCSIS Uplink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_UPLINK,
+			.crc_size = RTE_ETHER_CRC_LEN
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{	/* DOCSIS Downlink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK,
+			.crc_size = RTE_ETHER_CRC_LEN
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{
+		.action = RTE_SECURITY_ACTION_TYPE_NONE
+	}
+};
+#endif
 
 /** Configure device */
 static int
@@ -810,3 +862,78 @@ struct rte_cryptodev_ops aesni_mb_pmd_ops = {
 };
 
 struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops = &aesni_mb_pmd_ops;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/**
+ * Configure a aesni multi-buffer session from a security session
+ * configuration
+ */
+static int
+aesni_mb_pmd_sec_sess_create(void *dev, struct rte_security_session_conf *conf,
+		struct rte_security_session *sess,
+		struct rte_mempool *mempool)
+{
+	void *sess_private_data;
+	struct rte_cryptodev *cdev = (struct rte_cryptodev *)dev;
+	int ret;
+
+	if (rte_mempool_get(mempool, &sess_private_data)) {
+		AESNI_MB_LOG(ERR, "Couldn't get object from session mempool");
+		return -ENOMEM;
+	}
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_DOCSIS) {
+		AESNI_MB_LOG(ERR, "Invalid security protocol");
+		return -EINVAL;
+	}
+
+	ret = aesni_mb_set_docsis_sec_session_parameters(cdev, conf,
+			sess_private_data);
+
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Failed to configure session parameters");
+
+		/* Return session to mempool */
+		rte_mempool_put(mempool, sess_private_data);
+		return ret;
+	}
+
+	set_sec_session_private_data(sess, sess_private_data);
+
+	return ret;
+}
+
+/** Clear the memory of session so it doesn't leave key material behind */
+static int
+aesni_mb_pmd_sec_sess_destroy(void *dev __rte_unused,
+		struct rte_security_session *sess)
+{
+	void *sess_priv = get_sec_session_private_data(sess);
+
+	if (sess_priv) {
+		struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
+		memset(sess, 0, sizeof(struct aesni_mb_session));
+		set_sec_session_private_data(sess, NULL);
+		rte_mempool_put(sess_mp, sess_priv);
+	}
+	return 0;
+}
+
+/** Get security capabilities for aesni multi-buffer */
+static const struct rte_security_capability *
+aesni_mb_pmd_sec_capa_get(void *device __rte_unused)
+{
+	return aesni_mb_pmd_security_cap;
+}
+
+static struct rte_security_ops aesni_mb_pmd_sec_ops = {
+		.session_create = aesni_mb_pmd_sec_sess_create,
+		.session_update = NULL,
+		.session_stats_get = NULL,
+		.session_destroy = aesni_mb_pmd_sec_sess_destroy,
+		.set_pkt_metadata = NULL,
+		.capabilities_get = aesni_mb_pmd_sec_capa_get
+};
+
+struct rte_security_ops *rte_aesni_mb_pmd_sec_ops = &aesni_mb_pmd_sec_ops;
+#endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v2 4/6] crypto/qat: add support for DOCSIS protocol
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
                       ` (2 preceding siblings ...)
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 3/6] crypto/aesni_mb: " David Coyle
@ 2020-06-23 10:14     ` David Coyle
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 5/6] test/crypto: add DOCSIS security test cases David Coyle
                       ` (3 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-06-23 10:14 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support to the QAT SYM PMD for the DOCSIS protocol, through the
rte_security API. This, therefore, includes adding support for the
rte_security API to this PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 drivers/common/qat/Makefile               |   3 +
 drivers/crypto/qat/meson.build            |   2 +
 drivers/crypto/qat/qat_sym.c              | 139 ++++++++++++++------
 drivers/crypto/qat/qat_sym.h              |  82 ++++++++++--
 drivers/crypto/qat/qat_sym_capabilities.h |  44 +++++++
 drivers/crypto/qat/qat_sym_pmd.c          |  53 +++++++-
 drivers/crypto/qat/qat_sym_pmd.h          |   4 +
 drivers/crypto/qat/qat_sym_session.c      | 148 ++++++++++++++++++++++
 drivers/crypto/qat/qat_sym_session.h      |  12 ++
 9 files changed, 438 insertions(+), 49 deletions(-)

diff --git a/drivers/common/qat/Makefile b/drivers/common/qat/Makefile
index 28bd5668f..85d420709 100644
--- a/drivers/common/qat/Makefile
+++ b/drivers/common/qat/Makefile
@@ -35,6 +35,9 @@ endif
 ifeq ($(CONFIG_RTE_LIBRTE_PMD_QAT_SYM),y)
 	LDLIBS += -lrte_cryptodev
 	LDLIBS += -lcrypto
+ifeq ($(CONFIG_RTE_LIBRTE_SECURITY),y)
+	LDLIBS += -lrte_net
+endif
 	CFLAGS += -DBUILD_QAT_SYM
 	SRCS-y += qat_sym.c
 	SRCS-y += qat_sym_session.c
diff --git a/drivers/crypto/qat/meson.build b/drivers/crypto/qat/meson.build
index fc65923a7..a225f374a 100644
--- a/drivers/crypto/qat/meson.build
+++ b/drivers/crypto/qat/meson.build
@@ -8,6 +8,8 @@ reason = '' # sentinal value to suppress printout
 dep = dependency('libcrypto', required: false)
 qat_includes += include_directories('.')
 qat_deps += 'cryptodev'
+qat_deps += 'net'
+qat_deps += 'security'
 if dep.found()
 	# Add our sources files to the list
 	qat_sources += files('qat_sym_pmd.c',
diff --git a/drivers/crypto/qat/qat_sym.c b/drivers/crypto/qat/qat_sym.c
index 25b6dd5f4..98983c985 100644
--- a/drivers/crypto/qat/qat_sym.c
+++ b/drivers/crypto/qat/qat_sym.c
@@ -9,6 +9,9 @@
 #include <rte_crypto_sym.h>
 #include <rte_bus_pci.h>
 #include <rte_byteorder.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_net_crc.h>
+#endif
 
 #include "qat_sym.h"
 
@@ -44,11 +47,10 @@ bpi_cipher_decrypt(uint8_t *src, uint8_t *dst,
 
 
 static inline uint32_t
-qat_bpicipher_preprocess(struct qat_sym_session *ctx,
-				struct rte_crypto_op *op)
+qat_bpicipher_preprocess(struct qat_sym_session *ctx, struct rte_crypto_op *op,
+				struct rte_crypto_sym_op *sym_op)
 {
 	int block_len = qat_cipher_get_block_size(ctx->qat_cipher_alg);
-	struct rte_crypto_sym_op *sym_op = op->sym;
 	uint8_t last_block_len = block_len > 0 ?
 			sym_op->cipher.data.length % block_len : 0;
 
@@ -99,6 +101,29 @@ qat_bpicipher_preprocess(struct qat_sym_session *ctx,
 	return sym_op->cipher.data.length - last_block_len;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
+static inline void
+qat_crc_generate(struct qat_sym_session *ctx,
+			struct rte_security_docsis_op *doc_op,
+			struct rte_crypto_sym_op *sym_op)
+{
+	uint8_t *crc_data;
+	uint32_t *crc;
+
+	if (ctx->qat_dir == ICP_QAT_HW_CIPHER_ENCRYPT &&
+			doc_op != NULL &&
+			doc_op->crc.length != 0) {
+
+		crc_data = (uint8_t *) rte_pktmbuf_mtod_offset(
+				sym_op->m_src, uint8_t *,
+				doc_op->crc.offset);
+		crc = (uint32_t *)(crc_data + doc_op->crc.length);
+		*crc = rte_net_crc_calc(crc_data, doc_op->crc.length,
+				RTE_NET_CRC32_ETH);
+	}
+}
+#endif
+
 static inline void
 set_cipher_iv(uint16_t iv_length, uint16_t iv_offset,
 		struct icp_qat_fw_la_cipher_req_params *cipher_param,
@@ -162,25 +187,56 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 	uint8_t do_sgl = 0;
 	uint8_t in_place = 1;
 	int alignment_adjustment = 0;
+	struct rte_crypto_sym_op *sym;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_op *sec_op;
+	struct rte_security_docsis_op *doc_op = NULL;
+#endif
+
 	struct rte_crypto_op *op = (struct rte_crypto_op *)in_op;
 	struct qat_sym_op_cookie *cookie =
 				(struct qat_sym_op_cookie *)op_cookie;
 
-	if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
-		QAT_DP_LOG(ERR, "QAT PMD only supports symmetric crypto "
-				"operation requests, op (%p) is not a "
-				"symmetric operation.", op);
-		return -EINVAL;
-	}
-
 	if (unlikely(op->sess_type == RTE_CRYPTO_OP_SESSIONLESS)) {
 		QAT_DP_LOG(ERR, "QAT PMD only supports session oriented"
 				" requests, op (%p) is sessionless.", op);
 		return -EINVAL;
 	}
 
-	ctx = (struct qat_sym_session *)get_sym_session_private_data(
-			op->sym->session, cryptodev_qat_driver_id);
+	if (likely(op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+			op->sess_type == RTE_CRYPTO_OP_WITH_SESSION)) {
+		sym = op->sym;
+		ctx = (struct qat_sym_session *)get_sym_session_private_data(
+				sym->session, cryptodev_qat_driver_id);
+#ifdef RTE_LIBRTE_SECURITY
+	} else if (op->type == RTE_CRYPTO_OP_TYPE_SECURITY &&
+			op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+		sec_op = (struct rte_security_op *)&op->security;
+		if (sec_op->type == RTE_SECURITY_OP_TYPE_DOCSIS) {
+			doc_op = &sec_op->docsis;
+			sym = &doc_op->crypto_sym;
+			ctx = (struct qat_sym_session *)
+				get_sec_session_private_data(sym->sec_session);
+		} else {
+			QAT_DP_LOG(ERR, "QAT PMD only supports security"
+					" operation requests for DOCSIS, op"
+					" (%p) is not for DOCSIS.", op);
+			return -EINVAL;
+		}
+#endif
+	} else {
+		QAT_DP_LOG(ERR, "QAT PMD only supports symmetric crypto "
+				"%soperation requests, op (%p) is not a "
+				"symmetric %soperation or the associated "
+				"session type is invalid.",
+#ifdef RTE_LIBRTE_SECURITY
+				"and security ", op, "or security "
+#else
+				"", op, ""
+#endif
+				);
+		return -EINVAL;
+	}
 
 	if (unlikely(ctx == NULL)) {
 		QAT_DP_LOG(ERR, "Session was not created for this device");
@@ -231,27 +287,34 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 				ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3) {
 
 			if (unlikely(
-			    (op->sym->cipher.data.length % BYTE_LENGTH != 0) ||
-			    (op->sym->cipher.data.offset % BYTE_LENGTH != 0))) {
+			    (sym->cipher.data.length % BYTE_LENGTH != 0) ||
+			    (sym->cipher.data.offset % BYTE_LENGTH != 0))) {
 				QAT_DP_LOG(ERR,
 		  "SNOW3G/KASUMI/ZUC in QAT PMD only supports byte aligned values");
 				op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
 				return -EINVAL;
 			}
-			cipher_len = op->sym->cipher.data.length >> 3;
-			cipher_ofs = op->sym->cipher.data.offset >> 3;
+			cipher_len = sym->cipher.data.length >> 3;
+			cipher_ofs = sym->cipher.data.offset >> 3;
 
 		} else if (ctx->bpi_ctx) {
-			/* DOCSIS - only send complete blocks to device
+			/* DOCSIS processing */
+
+#ifdef RTE_LIBRTE_SECURITY
+			/* Calculate CRC */
+			qat_crc_generate(ctx, doc_op, sym);
+#endif
+
+			/* Only send complete blocks to device.
 			 * Process any partial block using CFB mode.
 			 * Even if 0 complete blocks, still send this to device
 			 * to get into rx queue for post-process and dequeuing
 			 */
-			cipher_len = qat_bpicipher_preprocess(ctx, op);
-			cipher_ofs = op->sym->cipher.data.offset;
+			cipher_len = qat_bpicipher_preprocess(ctx, op, sym);
+			cipher_ofs = sym->cipher.data.offset;
 		} else {
-			cipher_len = op->sym->cipher.data.length;
-			cipher_ofs = op->sym->cipher.data.offset;
+			cipher_len = sym->cipher.data.length;
+			cipher_ofs = sym->cipher.data.offset;
 		}
 
 		set_cipher_iv(ctx->cipher_iv.length, ctx->cipher_iv.offset,
@@ -428,58 +491,58 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 		min_ofs = op->sym->aead.data.offset;
 	}
 
-	if (op->sym->m_src->nb_segs > 1 ||
-			(op->sym->m_dst && op->sym->m_dst->nb_segs > 1))
+	if (sym->m_src->nb_segs > 1 ||
+			(sym->m_dst && sym->m_dst->nb_segs > 1))
 		do_sgl = 1;
 
 	/* adjust for chain case */
 	if (do_cipher && do_auth)
 		min_ofs = cipher_ofs < auth_ofs ? cipher_ofs : auth_ofs;
 
-	if (unlikely(min_ofs >= rte_pktmbuf_data_len(op->sym->m_src) && do_sgl))
+	if (unlikely(min_ofs >= rte_pktmbuf_data_len(sym->m_src) && do_sgl))
 		min_ofs = 0;
 
-	if (unlikely((op->sym->m_dst != NULL) &&
-			(op->sym->m_dst != op->sym->m_src))) {
+	if (unlikely((sym->m_dst != NULL) &&
+			(sym->m_dst != sym->m_src))) {
 		/* Out-of-place operation (OOP)
 		 * Don't align DMA start. DMA the minimum data-set
 		 * so as not to overwrite data in dest buffer
 		 */
 		in_place = 0;
 		src_buf_start =
-			rte_pktmbuf_iova_offset(op->sym->m_src, min_ofs);
+			rte_pktmbuf_iova_offset(sym->m_src, min_ofs);
 		dst_buf_start =
-			rte_pktmbuf_iova_offset(op->sym->m_dst, min_ofs);
+			rte_pktmbuf_iova_offset(sym->m_dst, min_ofs);
 
 	} else {
 		/* In-place operation
 		 * Start DMA at nearest aligned address below min_ofs
 		 */
 		src_buf_start =
-			rte_pktmbuf_iova_offset(op->sym->m_src, min_ofs)
+			rte_pktmbuf_iova_offset(sym->m_src, min_ofs)
 						& QAT_64_BTYE_ALIGN_MASK;
 
-		if (unlikely((rte_pktmbuf_iova(op->sym->m_src) -
-					rte_pktmbuf_headroom(op->sym->m_src))
+		if (unlikely((rte_pktmbuf_iova(sym->m_src) -
+					rte_pktmbuf_headroom(sym->m_src))
 							> src_buf_start)) {
 			/* alignment has pushed addr ahead of start of mbuf
 			 * so revert and take the performance hit
 			 */
 			src_buf_start =
-				rte_pktmbuf_iova_offset(op->sym->m_src,
+				rte_pktmbuf_iova_offset(sym->m_src,
 								min_ofs);
 		}
 		dst_buf_start = src_buf_start;
 
 		/* remember any adjustment for later, note, can be +/- */
 		alignment_adjustment = src_buf_start -
-			rte_pktmbuf_iova_offset(op->sym->m_src, min_ofs);
+			rte_pktmbuf_iova_offset(sym->m_src, min_ofs);
 	}
 
 	if (do_cipher || do_aead) {
 		cipher_param->cipher_offset =
 				(uint32_t)rte_pktmbuf_iova_offset(
-				op->sym->m_src, cipher_ofs) - src_buf_start;
+				sym->m_src, cipher_ofs) - src_buf_start;
 		cipher_param->cipher_length = cipher_len;
 	} else {
 		cipher_param->cipher_offset = 0;
@@ -557,8 +620,8 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 
 		ICP_QAT_FW_COMN_PTR_TYPE_SET(qat_req->comn_hdr.comn_req_flags,
 				QAT_COMN_PTR_TYPE_SGL);
-		ret = qat_sgl_fill_array(op->sym->m_src,
-		   (int64_t)(src_buf_start - rte_pktmbuf_iova(op->sym->m_src)),
+		ret = qat_sgl_fill_array(sym->m_src,
+		   (int64_t)(src_buf_start - rte_pktmbuf_iova(sym->m_src)),
 		   &cookie->qat_sgl_src,
 		   qat_req->comn_mid.src_length,
 		   QAT_SYM_SGL_MAX_NUMBER);
@@ -599,9 +662,9 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 
 	/* Handle Single-Pass GCM */
 	if (ctx->is_single_pass) {
-		cipher_param->spc_aad_addr = op->sym->aead.aad.phys_addr;
+		cipher_param->spc_aad_addr = sym->aead.aad.phys_addr;
 		cipher_param->spc_auth_res_addr =
-				op->sym->aead.digest.phys_addr;
+				sym->aead.digest.phys_addr;
 	}
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
diff --git a/drivers/crypto/qat/qat_sym.h b/drivers/crypto/qat/qat_sym.h
index bc6426c32..1a99a68fe 100644
--- a/drivers/crypto/qat/qat_sym.h
+++ b/drivers/crypto/qat/qat_sym.h
@@ -6,6 +6,9 @@
 #define _QAT_SYM_H_
 
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_net_crc.h>
+#endif
 
 #ifdef BUILD_QAT_SYM
 #include <openssl/evp.h>
@@ -76,10 +79,10 @@ bpi_cipher_encrypt(uint8_t *src, uint8_t *dst,
 
 static inline uint32_t
 qat_bpicipher_postprocess(struct qat_sym_session *ctx,
-				struct rte_crypto_op *op)
+				struct rte_crypto_op *op,
+				struct rte_crypto_sym_op *sym_op)
 {
 	int block_len = qat_cipher_get_block_size(ctx->qat_cipher_alg);
-	struct rte_crypto_sym_op *sym_op = op->sym;
 	uint8_t last_block_len = block_len > 0 ?
 			sym_op->cipher.data.length % block_len : 0;
 
@@ -132,14 +135,52 @@ qat_bpicipher_postprocess(struct qat_sym_session *ctx,
 	return sym_op->cipher.data.length - last_block_len;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
 static inline void
-qat_sym_process_response(void **op, uint8_t *resp)
+qat_crc_verify(struct qat_sym_session *ctx, struct rte_crypto_op *op,
+		struct rte_security_docsis_op *doc_op,
+		struct rte_crypto_sym_op *sym_op)
 {
+	uint32_t crc = 0;
+	uint8_t *crc_data;
+	uint32_t crc_offset;
+
+	if (ctx->qat_dir == ICP_QAT_HW_CIPHER_DECRYPT &&
+			doc_op != NULL &&
+			doc_op->crc.length != 0) {
+
+		crc_offset = doc_op->crc.offset;
+		crc_data = (uint8_t *) rte_pktmbuf_mtod_offset(
+				sym_op->m_src, uint8_t *, crc_offset);
+
+		if (unlikely((sym_op->m_dst != NULL)
+				&& (sym_op->m_dst != sym_op->m_src)))
+			/* out-of-place operation (OOP) */
+			crc_data = (uint8_t *) rte_pktmbuf_mtod_offset(
+					sym_op->m_dst, uint8_t *, crc_offset);
+
+		crc = rte_net_crc_calc(crc_data, doc_op->crc.length,
+				RTE_NET_CRC32_ETH);
 
+		if (crc != *(uint32_t *)(crc_data + doc_op->crc.length))
+			op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+	}
+}
+#endif
+
+static inline void
+qat_sym_process_response(void **op, uint8_t *resp)
+{
 	struct icp_qat_fw_comn_resp *resp_msg =
 			(struct icp_qat_fw_comn_resp *)resp;
 	struct rte_crypto_op *rx_op = (struct rte_crypto_op *)(uintptr_t)
 			(resp_msg->opaque_data);
+	struct rte_crypto_sym_op *sym_op;
+	struct qat_sym_session *sess;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_op *sec_op;
+	struct rte_security_docsis_op *doc_op = NULL;
+#endif
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	QAT_DP_HEXDUMP_LOG(DEBUG, "qat_response:", (uint8_t *)resp_msg,
@@ -152,15 +193,36 @@ qat_sym_process_response(void **op, uint8_t *resp)
 
 		rx_op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
 	} else {
-		struct qat_sym_session *sess = (struct qat_sym_session *)
-						get_sym_session_private_data(
-						rx_op->sym->session,
-						cryptodev_qat_driver_id);
-
+#ifdef RTE_LIBRTE_SECURITY
+		if (unlikely(rx_op->type == RTE_CRYPTO_OP_TYPE_SECURITY)) {
+			/*
+			 * Assuming at this point that if it's a security
+			 * op, that this is for DOCSIS
+			 */
+			sec_op = (struct rte_security_op *)&rx_op->security;
+			doc_op = &sec_op->docsis;
+			sess = (struct qat_sym_session *)
+					get_sec_session_private_data(
+					doc_op->crypto_sym.sec_session);
+			sym_op = &doc_op->crypto_sym;
+		} else
+#endif
+		{
+			sess = (struct qat_sym_session *)
+					get_sym_session_private_data(
+					rx_op->sym->session,
+					cryptodev_qat_driver_id);
+			sym_op = rx_op->sym;
+		}
 
-		if (sess->bpi_ctx)
-			qat_bpicipher_postprocess(sess, rx_op);
 		rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+
+		if (sess->bpi_ctx) {
+			qat_bpicipher_postprocess(sess, rx_op, sym_op);
+#ifdef RTE_LIBRTE_SECURITY
+			qat_crc_verify(sess, rx_op, doc_op, sym_op);
+#endif
+		}
 	}
 	*op = (void *)rx_op;
 }
diff --git a/drivers/crypto/qat/qat_sym_capabilities.h b/drivers/crypto/qat/qat_sym_capabilities.h
index ff691ce35..4c33188cb 100644
--- a/drivers/crypto/qat/qat_sym_capabilities.h
+++ b/drivers/crypto/qat/qat_sym_capabilities.h
@@ -699,4 +699,48 @@
 		}, }							\
 	}
 
+#ifdef RTE_LIBRTE_SECURITY
+#define QAT_SECURITY_SYM_CAPABILITIES					\
+	{	/* AES DOCSIS BPI */					\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,	\
+			{.cipher = {					\
+				.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,\
+				.block_size = 16,			\
+				.key_size = {				\
+					.min = 16,			\
+					.max = 32,			\
+					.increment = 16			\
+				},					\
+				.iv_size = {				\
+					.min = 16,			\
+					.max = 16,			\
+					.increment = 0			\
+				}					\
+			}, }						\
+		}, }							\
+	}
+
+#define QAT_SECURITY_CAPABILITIES(sym)					\
+	[0] = {	/* DOCSIS Uplink */					\
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,	\
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,		\
+		.docsis = {						\
+			.direction = RTE_SECURITY_DOCSIS_UPLINK,	\
+			.crc_size = RTE_ETHER_CRC_LEN			\
+		},							\
+		.crypto_capabilities = (sym)				\
+	},								\
+	[1] = {	/* DOCSIS Downlink */					\
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,	\
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,		\
+		.docsis = {						\
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK,	\
+			.crc_size = RTE_ETHER_CRC_LEN			\
+		},							\
+		.crypto_capabilities = (sym)				\
+	}
+#endif
+
 #endif /* _QAT_SYM_CAPABILITIES_H_ */
diff --git a/drivers/crypto/qat/qat_sym_pmd.c b/drivers/crypto/qat/qat_sym_pmd.c
index e887c880f..711d1585f 100644
--- a/drivers/crypto/qat/qat_sym_pmd.c
+++ b/drivers/crypto/qat/qat_sym_pmd.c
@@ -8,6 +8,9 @@
 #include <rte_malloc.h>
 #include <rte_pci.h>
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security_driver.h>
+#endif
 
 #include "qat_logs.h"
 #include "qat_sym.h"
@@ -29,6 +32,21 @@ static const struct rte_cryptodev_capabilities qat_gen2_sym_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+#ifdef RTE_LIBRTE_SECURITY
+static const struct rte_cryptodev_capabilities
+					qat_security_sym_capabilities[] = {
+	QAT_SECURITY_SYM_CAPABILITIES,
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability qat_security_capabilities[] = {
+	QAT_SECURITY_CAPABILITIES(qat_security_sym_capabilities),
+	{
+		.action = RTE_SECURITY_ACTION_TYPE_NONE
+	}
+};
+#endif
+
 static int qat_sym_qp_release(struct rte_cryptodev *dev,
 	uint16_t queue_pair_id);
 
@@ -237,6 +255,23 @@ static struct rte_cryptodev_ops crypto_qat_ops = {
 		.sym_session_clear	= qat_sym_session_clear
 };
 
+#ifdef RTE_LIBRTE_SECURITY
+static const struct rte_security_capability *
+qat_security_cap_get(void *device __rte_unused)
+{
+	return qat_security_capabilities;
+}
+
+static struct rte_security_ops security_qat_ops = {
+	.session_create = qat_security_session_create,
+	.session_update = NULL,
+	.session_stats_get = NULL,
+	.session_destroy = qat_security_session_destroy,
+	.set_pkt_metadata = NULL,
+	.capabilities_get = qat_security_cap_get
+};
+#endif
+
 static uint16_t
 qat_sym_pmd_enqueue_op_burst(void *qp, struct rte_crypto_op **ops,
 		uint16_t nb_ops)
@@ -276,6 +311,9 @@ qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
 	struct rte_cryptodev *cryptodev;
 	struct qat_sym_dev_private *internals;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_ctx *security_instance;
+#endif
 
 	snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN, "%s_%s",
 			qat_pci_dev->name, "sym");
@@ -308,7 +346,20 @@ qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
 			RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
-			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED;
+			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED |
+			RTE_CRYPTODEV_FF_SECURITY;
+
+#ifdef RTE_LIBRTE_SECURITY
+	security_instance = rte_malloc("qat_sec",
+				sizeof(struct rte_security_ctx), 0);
+	if (security_instance == NULL)
+		QAT_LOG(ERR, "rte_security_ctx memory alloc failed\n");
+
+	security_instance->device = (void *)cryptodev;
+	security_instance->ops = &security_qat_ops;
+	security_instance->sess_cnt = 0;
+	cryptodev->security_ctx = security_instance;
+#endif
 
 	internals = cryptodev->data->dev_private;
 	internals->qat_dev = qat_pci_dev;
diff --git a/drivers/crypto/qat/qat_sym_pmd.h b/drivers/crypto/qat/qat_sym_pmd.h
index a5a31e512..c625fef4a 100644
--- a/drivers/crypto/qat/qat_sym_pmd.h
+++ b/drivers/crypto/qat/qat_sym_pmd.h
@@ -7,7 +7,11 @@
 
 #ifdef BUILD_QAT_SYM
 
+#include <rte_ether.h>
 #include <rte_cryptodev.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_sym_capabilities.h"
 #include "qat_device.h"
diff --git a/drivers/crypto/qat/qat_sym_session.c b/drivers/crypto/qat/qat_sym_session.c
index 58bdbd343..0dc5a9ea9 100644
--- a/drivers/crypto/qat/qat_sym_session.c
+++ b/drivers/crypto/qat/qat_sym_session.c
@@ -14,6 +14,9 @@
 #include <rte_log.h>
 #include <rte_malloc.h>
 #include <rte_crypto_sym.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_logs.h"
 #include "qat_sym_session.h"
@@ -2092,3 +2095,148 @@ int qat_sym_validate_zuc_key(int key_len, enum icp_qat_hw_cipher_algo *alg)
 	}
 	return 0;
 }
+
+#ifdef RTE_LIBRTE_SECURITY
+static int
+qat_sec_session_check_docsis(struct rte_security_session_conf *conf)
+{
+	struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
+	struct rte_security_docsis_xform *docsis = &conf->docsis;
+
+	/* CRC generate -> Cipher encrypt */
+	if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_128_KEY_SZ ||
+		     crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_256_KEY_SZ) &&
+		    crypto_sym->cipher.iv.length == ICP_QAT_HW_AES_BLK_SZ &&
+		    crypto_sym->next == NULL &&
+		    docsis->crc_size == RTE_ETHER_CRC_LEN) {
+			return 0;
+		}
+	/* Cipher decrypt -> CRC verify */
+	} else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_128_KEY_SZ ||
+		     crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_256_KEY_SZ) &&
+		    crypto_sym->cipher.iv.length == ICP_QAT_HW_AES_BLK_SZ &&
+		    crypto_sym->next == NULL &&
+		    docsis->crc_size == RTE_ETHER_CRC_LEN) {
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int
+qat_sec_session_set_docsis_parameters(struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf, void *session_private)
+{
+	int ret;
+	int qat_cmd_id;
+	struct rte_crypto_sym_xform *xform = NULL;
+	struct qat_sym_session *session = session_private;
+
+	ret = qat_sec_session_check_docsis(conf);
+	if (ret) {
+		QAT_LOG(ERR, "Unsupported DOCSIS security configuration");
+		return ret;
+	}
+
+	xform = conf->crypto_xform;
+
+	/* Set context descriptor physical address */
+	session->cd_paddr = rte_mempool_virt2iova(session) +
+			offsetof(struct qat_sym_session, cd);
+
+	session->min_qat_dev_gen = QAT_GEN1;
+
+	/* Get requested QAT command id */
+	qat_cmd_id = qat_get_cmd_id(xform);
+	if (qat_cmd_id < 0 || qat_cmd_id >= ICP_QAT_FW_LA_CMD_DELIMITER) {
+		QAT_LOG(ERR, "Unsupported xform chain requested");
+		return -ENOTSUP;
+	}
+	session->qat_cmd = (enum icp_qat_fw_la_cmd_id)qat_cmd_id;
+	switch (session->qat_cmd) {
+	case ICP_QAT_FW_LA_CMD_CIPHER:
+		ret = qat_sym_session_configure_cipher(dev, xform, session);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+	QAT_LOG(ERR, "Unsupported Service %u",
+		session->qat_cmd);
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+int
+qat_security_session_create(void *dev,
+				struct rte_security_session_conf *conf,
+				struct rte_security_session *sess,
+				struct rte_mempool *mempool)
+{
+	void *sess_private_data;
+	struct rte_cryptodev *cdev = (struct rte_cryptodev *)dev;
+	int ret;
+
+	if (rte_mempool_get(mempool, &sess_private_data)) {
+		QAT_LOG(ERR, "Couldn't get object from session mempool");
+		return -ENOMEM;
+	}
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_DOCSIS) {
+		QAT_LOG(ERR, "Invalid security protocol");
+		return -EINVAL;
+	}
+
+	ret = qat_sec_session_set_docsis_parameters(cdev, conf,
+			sess_private_data);
+	if (ret != 0) {
+		QAT_LOG(ERR, "Failed to configure session parameters");
+		/* Return session to mempool */
+		rte_mempool_put(mempool, sess_private_data);
+		return ret;
+	}
+
+	set_sec_session_private_data(sess, sess_private_data);
+
+	return ret;
+}
+
+int
+qat_security_session_destroy(void *dev __rte_unused,
+				 struct rte_security_session *sess)
+{
+	void *sess_priv = get_sec_session_private_data(sess);
+	struct qat_sym_session *s = (struct qat_sym_session *)sess_priv;
+
+	if (sess_priv) {
+		if (s->bpi_ctx)
+			bpi_cipher_ctx_free(s->bpi_ctx);
+		memset(s, 0, qat_sym_session_get_private_size(dev));
+		struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
+
+		set_sec_session_private_data(sess, NULL);
+		rte_mempool_put(sess_mp, sess_priv);
+	}
+	return 0;
+}
+#endif
diff --git a/drivers/crypto/qat/qat_sym_session.h b/drivers/crypto/qat/qat_sym_session.h
index e6538f627..721f8fcd3 100644
--- a/drivers/crypto/qat/qat_sym_session.h
+++ b/drivers/crypto/qat/qat_sym_session.h
@@ -6,6 +6,9 @@
 
 #include <rte_crypto.h>
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_common.h"
 #include "icp_qat_hw.h"
@@ -156,4 +159,13 @@ qat_cipher_get_block_size(enum icp_qat_hw_cipher_algo qat_cipher_alg);
 int
 qat_sym_validate_zuc_key(int key_len, enum icp_qat_hw_cipher_algo *alg);
 
+#ifdef RTE_LIBRTE_SECURITY
+int
+qat_security_session_create(void *dev, struct rte_security_session_conf *conf,
+		struct rte_security_session *sess, struct rte_mempool *mempool);
+int
+qat_security_session_destroy(void *dev __rte_unused,
+		struct rte_security_session *sess);
+#endif
+
 #endif /* _QAT_SYM_SESSION_H_ */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v2 5/6] test/crypto: add DOCSIS security test cases
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
                       ` (3 preceding siblings ...)
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 4/6] crypto/qat: " David Coyle
@ 2020-06-23 10:14     ` David Coyle
  2020-06-23 18:04       ` De Lara Guarch, Pablo
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 6/6] test/security: add DOCSIS capability check tests David Coyle
                       ` (2 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-23 10:14 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add uplink and downlink DOCSIS unit test cases and vectors, to test
the combined DOCSIS Crypto-CRC support that has been added to the
rte_security and rte_cryptodev libraries.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 app/test/test_cryptodev.c                     |  552 ++++++
 ...t_cryptodev_security_docsis_test_vectors.h | 1544 +++++++++++++++++
 2 files changed, 2096 insertions(+)
 create mode 100644 app/test/test_cryptodev_security_docsis_test_vectors.h

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 8f631468b..59b12f596 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -11,6 +11,7 @@
 #include <rte_memcpy.h>
 #include <rte_pause.h>
 #include <rte_bus_vdev.h>
+#include <rte_ether.h>
 
 #include <rte_crypto.h>
 #include <rte_cryptodev.h>
@@ -42,6 +43,7 @@
 #ifdef RTE_LIBRTE_SECURITY
 #include "test_cryptodev_security_pdcp_test_vectors.h"
 #include "test_cryptodev_security_pdcp_test_func.h"
+#include "test_cryptodev_security_docsis_test_vectors.h"
 #endif
 
 #define VDEV_ARGS_SIZE 100
@@ -59,6 +61,9 @@ struct crypto_testsuite_params {
 	struct rte_mempool *mbuf_pool;
 	struct rte_mempool *large_mbuf_pool;
 	struct rte_mempool *op_mpool;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_mempool *security_op_mpool;
+#endif
 	struct rte_mempool *session_mpool;
 	struct rte_mempool *session_priv_mpool;
 	struct rte_cryptodev_config conf;
@@ -72,6 +77,9 @@ struct crypto_unittest_params {
 	struct rte_crypto_sym_xform cipher_xform;
 	struct rte_crypto_sym_xform auth_xform;
 	struct rte_crypto_sym_xform aead_xform;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_docsis_xform docsis_xform;
+#endif
 
 	union {
 		struct rte_cryptodev_sym_session *sess;
@@ -308,6 +316,19 @@ testsuite_setup(void)
 		return TEST_FAILED;
 	}
 
+#ifdef RTE_LIBRTE_SECURITY
+	ts_params->security_op_mpool = rte_crypto_op_pool_create(
+			"MBUF_SECURITY_OP_POOL",
+			RTE_CRYPTO_OP_TYPE_SECURITY,
+			NUM_MBUFS, MBUF_CACHE_SIZE,
+			MAXIMUM_IV_LENGTH,
+			rte_socket_id());
+	if (ts_params->security_op_mpool == NULL) {
+		RTE_LOG(ERR, USER1, "Can't create SECURITY_OP_POOL\n");
+		return TEST_FAILED;
+	}
+#endif
+
 	/* Create an AESNI MB device if required */
 	if (gbl_driver_id == rte_cryptodev_driver_id_get(
 			RTE_STR(CRYPTODEV_NAME_AESNI_MB_PMD))) {
@@ -7067,6 +7088,34 @@ test_authenticated_encryption(const struct aead_test_data *tdata)
 }
 
 #ifdef RTE_LIBRTE_SECURITY
+static int
+security_proto_supported(enum rte_security_session_protocol proto)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+	const struct rte_security_capability *capabilities;
+	const struct rte_security_capability *capability;
+	uint16_t i = 0;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+				rte_cryptodev_get_sec_ctx(
+				ts_params->valid_devs[0]);
+
+
+	capabilities = rte_security_capabilities_get(ctx);
+
+	if (capabilities == NULL)
+		return -ENOTSUP;
+
+	while ((capability = &capabilities[i++])->action !=
+			RTE_SECURITY_ACTION_TYPE_NONE) {
+		if (capability->protocol == proto)
+			return 0;
+	}
+
+	return -ENOTSUP;
+}
+
 /* Basic algorithm run function for async inplace mode.
  * Creates a session from input parameters and runs one operation
  * on input_vec. Checks the output of the crypto operation against
@@ -7670,6 +7719,9 @@ test_PDCP_PROTO_all(void)
 	if (!(feat_flags & RTE_CRYPTODEV_FF_SECURITY))
 		return -ENOTSUP;
 
+	if (security_proto_supported(RTE_SECURITY_PROTOCOL_PDCP) < 0)
+		return -ENOTSUP;
+
 	status = test_PDCP_PROTO_cplane_encap_all();
 	status += test_PDCP_PROTO_cplane_decap_all();
 	status += test_PDCP_PROTO_uplane_encap_all();
@@ -7684,6 +7736,504 @@ test_PDCP_PROTO_all(void)
 	else
 		return TEST_SUCCESS;
 }
+
+static int
+test_docsis_proto_uplink(int i, struct docsis_test_data *d_td)
+{
+	struct rte_security_op *sec_op;
+	struct rte_security_docsis_op *doc_op;
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	uint8_t *plaintext, *ciphertext;
+	uint8_t *iv_ptr;
+	int cipher_len = 0;
+	int crc_len = 0, crc_data_len;
+	int ret = TEST_SUCCESS;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(
+						ts_params->valid_devs[0]);
+
+	/* Verify the capabilities */
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	const struct rte_cryptodev_capabilities *crypto_cap;
+	const struct rte_cryptodev_symmetric_capability *sym_cap;
+	int j = 0;
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_DOCSIS;
+	sec_cap_idx.docsis.direction = RTE_SECURITY_DOCSIS_UPLINK;
+	sec_cap_idx.docsis.crc_size = RTE_ETHER_CRC_LEN;
+
+	sec_cap = rte_security_capability_get(ctx, &sec_cap_idx);
+	if (sec_cap == NULL)
+		return -ENOTSUP;
+
+	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+				crypto_cap->sym.xform_type ==
+					RTE_CRYPTO_SYM_XFORM_CIPHER &&
+				crypto_cap->sym.cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI) {
+			sym_cap = &crypto_cap->sym;
+			if (rte_cryptodev_sym_capability_check_cipher(sym_cap,
+						d_td->key.len,
+						d_td->iv.len) == 0)
+				break;
+		}
+	}
+
+	if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED)
+		return -ENOTSUP;
+
+	/* Setup source mbuf payload */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+			rte_pktmbuf_tailroom(ut_params->ibuf));
+
+	ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+			d_td->ciphertext.len);
+
+	memcpy(ciphertext, d_td->ciphertext.data, d_td->ciphertext.len);
+
+	/* Set session action type */
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	/* Setup cipher session parameters */
+	ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	ut_params->cipher_xform.cipher.key.data = d_td->key.data;
+	ut_params->cipher_xform.cipher.key.length = d_td->key.len;
+	ut_params->cipher_xform.cipher.iv.length = d_td->iv.len;
+	ut_params->cipher_xform.cipher.iv.offset = sizeof(struct rte_crypto_op)
+					+ sizeof(struct rte_security_op);
+	ut_params->cipher_xform.next = NULL;
+
+	/* Setup DOCSIS session parameters */
+	ut_params->docsis_xform.direction = RTE_SECURITY_DOCSIS_UPLINK;
+	ut_params->docsis_xform.crc_size = RTE_ETHER_CRC_LEN;
+
+	struct rte_security_session_conf sess_conf = {
+		.action_type = ut_params->type,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = ut_params->docsis_xform,
+		.crypto_xform = &ut_params->cipher_xform,
+	};
+
+	/* Create security session */
+	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
+					ts_params->session_priv_mpool);
+
+	if (!ut_params->sec_session) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "failed to allocate session");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Generate crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc(ts_params->security_op_mpool,
+				RTE_CRYPTO_OP_TYPE_SECURITY);
+	if (!ut_params->op) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to allocate security crypto operation");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Populate DOCSIS security operation */
+	sec_op = (struct rte_security_op *)&ut_params->op->security;
+	sec_op->type = RTE_SECURITY_OP_TYPE_DOCSIS;
+	doc_op = &sec_op->docsis;
+
+	/* Setup CRC operation parameters */
+	crc_len = d_td->ciphertext.no_crc == false ?
+			(d_td->ciphertext.len -
+				d_td->ciphertext.crc_offset -
+				RTE_ETHER_CRC_LEN) :
+			0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	crc_data_len = crc_len == 0 ? 0 : RTE_ETHER_CRC_LEN;
+	doc_op->crc.length = crc_len;
+	doc_op->crc.offset = d_td->ciphertext.crc_offset;
+
+	/* Setup cipher operation parameters */
+	cipher_len = d_td->ciphertext.no_cipher == false ?
+			(d_td->ciphertext.len -
+				d_td->ciphertext.cipher_offset) :
+			0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	doc_op->crypto_sym.cipher.data.length = cipher_len;
+	doc_op->crypto_sym.cipher.data.offset = d_td->ciphertext.cipher_offset;
+
+	/* Setup cipher IV */
+	iv_ptr = (uint8_t *)ut_params->op + sizeof(struct rte_crypto_op) +
+			sizeof(struct rte_security_op);
+	rte_memcpy(iv_ptr, d_td->iv.data, d_td->iv.len);
+
+	/* Attach session to operation */
+	rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+	/* Set crypto operation mbufs */
+	sec_op->docsis.crypto_sym.m_src = ut_params->ibuf;
+	sec_op->docsis.crypto_sym.m_dst = NULL;
+
+	/* Process crypto operation */
+	if (process_crypto_request(ts_params->valid_devs[0], ut_params->op) ==
+			NULL) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to process security crypto op");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "crypto op processing failed");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Validate plaintext */
+	plaintext = ciphertext;
+
+	if (memcmp(plaintext, d_td->plaintext.data,
+			d_td->plaintext.len - crc_data_len)) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "plaintext not as expected\n");
+		rte_hexdump(stdout, "expected", d_td->plaintext.data,
+				d_td->plaintext.len);
+		rte_hexdump(stdout, "actual", plaintext, d_td->plaintext.len);
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+on_err:
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	if (ut_params->sec_session)
+		rte_security_session_destroy(ctx, ut_params->sec_session);
+	ut_params->sec_session = NULL;
+
+	rte_pktmbuf_free(ut_params->ibuf);
+	ut_params->ibuf = NULL;
+
+	return ret;
+}
+
+static int
+test_docsis_proto_downlink(int i, struct docsis_test_data *d_td)
+{
+	struct rte_security_op *sec_op;
+	struct rte_security_docsis_op *doc_op;
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	uint8_t *plaintext, *ciphertext;
+	uint8_t *iv_ptr;
+	int cipher_len = 0;
+	int crc_len = 0;
+	int ret = TEST_SUCCESS;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(
+						ts_params->valid_devs[0]);
+
+	/* Verify the capabilities */
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	const struct rte_cryptodev_capabilities *crypto_cap;
+	const struct rte_cryptodev_symmetric_capability *sym_cap;
+	int j = 0;
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_DOCSIS;
+	sec_cap_idx.docsis.direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+	sec_cap_idx.docsis.crc_size = RTE_ETHER_CRC_LEN;
+
+	sec_cap = rte_security_capability_get(ctx, &sec_cap_idx);
+	if (sec_cap == NULL)
+		return -ENOTSUP;
+
+	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+				crypto_cap->sym.xform_type ==
+					RTE_CRYPTO_SYM_XFORM_CIPHER &&
+				crypto_cap->sym.cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI) {
+			sym_cap = &crypto_cap->sym;
+			if (rte_cryptodev_sym_capability_check_cipher(sym_cap,
+						d_td->key.len,
+						d_td->iv.len) == 0)
+				break;
+		}
+	}
+
+	if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED)
+		return -ENOTSUP;
+
+	/* Setup source mbuf payload */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+			rte_pktmbuf_tailroom(ut_params->ibuf));
+
+	plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+			d_td->plaintext.len);
+
+	memcpy(plaintext, d_td->plaintext.data, d_td->plaintext.len);
+
+	/* Set session action type */
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	/* Setup cipher session parameters */
+	ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+	ut_params->cipher_xform.cipher.key.data = d_td->key.data;
+	ut_params->cipher_xform.cipher.key.length = d_td->key.len;
+	ut_params->cipher_xform.cipher.iv.length = d_td->iv.len;
+	ut_params->cipher_xform.cipher.iv.offset = sizeof(struct rte_crypto_op)
+					+ sizeof(struct rte_security_op);
+	ut_params->cipher_xform.next = NULL;
+
+	/* Setup DOCSIS session parameters */
+	ut_params->docsis_xform.direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+	ut_params->docsis_xform.crc_size = RTE_ETHER_CRC_LEN;
+
+	struct rte_security_session_conf sess_conf = {
+		.action_type = ut_params->type,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = ut_params->docsis_xform,
+		.crypto_xform = &ut_params->cipher_xform,
+	};
+
+	/* Create security session */
+	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
+					ts_params->session_priv_mpool);
+
+	if (!ut_params->sec_session) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "failed to allocate session");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Generate crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc(ts_params->security_op_mpool,
+				RTE_CRYPTO_OP_TYPE_SECURITY);
+	if (!ut_params->op) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to allocate security crypto operation");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Populate DOCSIS security operation */
+	sec_op = (struct rte_security_op *)&ut_params->op->security;
+	sec_op->type = RTE_SECURITY_OP_TYPE_DOCSIS;
+	doc_op = &sec_op->docsis;
+
+	/* Setup CRC operation parameters */
+	crc_len = d_td->plaintext.no_crc == false ?
+			(d_td->plaintext.len -
+				d_td->plaintext.crc_offset -
+				RTE_ETHER_CRC_LEN) :
+			0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	doc_op->crc.length = crc_len;
+	doc_op->crc.offset = d_td->plaintext.crc_offset;
+
+	/* Setup cipher operation parameters */
+	cipher_len = d_td->plaintext.no_cipher == false ?
+			(d_td->plaintext.len -
+				d_td->plaintext.cipher_offset) :
+			0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	doc_op->crypto_sym.cipher.data.length = cipher_len;
+	doc_op->crypto_sym.cipher.data.offset = d_td->plaintext.cipher_offset;
+
+	/* Setup cipher IV */
+	iv_ptr = (uint8_t *)ut_params->op + sizeof(struct rte_crypto_op) +
+			sizeof(struct rte_security_op);
+	rte_memcpy(iv_ptr, d_td->iv.data, d_td->iv.len);
+
+	/* Attach session to operation */
+	rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+	/* Set crypto operation mbufs */
+	sec_op->docsis.crypto_sym.m_src = ut_params->ibuf;
+	sec_op->docsis.crypto_sym.m_dst = NULL;
+
+	/* Process crypto operation */
+	if (process_crypto_request(ts_params->valid_devs[0], ut_params->op) ==
+			NULL) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to process security crypto op");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "crypto op processing failed");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Validate ciphertext */
+	ciphertext = plaintext;
+
+	if (memcmp(ciphertext, d_td->ciphertext.data, d_td->ciphertext.len)) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "ciphertext not as expected\n");
+		rte_hexdump(stdout, "expected", d_td->ciphertext.data,
+				d_td->ciphertext.len);
+		rte_hexdump(stdout, "actual", ciphertext, d_td->ciphertext.len);
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+on_err:
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	if (ut_params->sec_session)
+		rte_security_session_destroy(ctx, ut_params->sec_session);
+	ut_params->sec_session = NULL;
+
+	rte_pktmbuf_free(ut_params->ibuf);
+	ut_params->ibuf = NULL;
+
+	return ret;
+}
+
+#define TEST_DOCSIS_COUNT(func) do {			\
+	int ret = func;					\
+	if (ret == TEST_SUCCESS)  {			\
+		printf("\t%2d)", n++);			\
+		printf("+++++ PASSED:" #func"\n");	\
+		p++;					\
+	} else if (ret == -ENOTSUP) {			\
+		printf("\t%2d)", n++);			\
+		printf("~~~~~ UNSUPP:" #func"\n");	\
+		u++;					\
+	} else {					\
+		printf("\t%2d)", n++);			\
+		printf("----- FAILED:" #func"\n");	\
+		f++;					\
+	}						\
+} while (0)
+
+static int
+test_DOCSIS_PROTO_uplink_all(void)
+{
+	int p = 0, u = 0, f = 0, n = 0;
+
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(1, &docsis_test_case_1));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(2, &docsis_test_case_2));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(3, &docsis_test_case_3));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(4, &docsis_test_case_4));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(5, &docsis_test_case_5));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(6, &docsis_test_case_6));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(7, &docsis_test_case_7));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(8, &docsis_test_case_8));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(9, &docsis_test_case_9));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(10, &docsis_test_case_10));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(11, &docsis_test_case_11));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(12, &docsis_test_case_12));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(13, &docsis_test_case_13));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(14, &docsis_test_case_14));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(15, &docsis_test_case_15));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(16, &docsis_test_case_16));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(17, &docsis_test_case_17));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(18, &docsis_test_case_18));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(19, &docsis_test_case_19));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(20, &docsis_test_case_20));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(21, &docsis_test_case_21));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(22, &docsis_test_case_22));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(23, &docsis_test_case_23));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(24, &docsis_test_case_24));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(25, &docsis_test_case_25));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(26, &docsis_test_case_26));
+
+	if (f)
+		printf("## %s: %d passed out of %d (%d unsupported)\n",
+			__func__, p, n, u);
+
+	return f;
+};
+
+static int
+test_DOCSIS_PROTO_downlink_all(void)
+{
+	int p = 0, u = 0, f = 0, n = 0;
+
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(1, &docsis_test_case_1));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(2, &docsis_test_case_2));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(3, &docsis_test_case_3));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(4, &docsis_test_case_4));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(5, &docsis_test_case_5));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(6, &docsis_test_case_6));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(7, &docsis_test_case_7));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(8, &docsis_test_case_8));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(9, &docsis_test_case_9));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(10, &docsis_test_case_10));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(11, &docsis_test_case_11));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(12, &docsis_test_case_12));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(13, &docsis_test_case_13));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(14, &docsis_test_case_14));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(15, &docsis_test_case_15));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(16, &docsis_test_case_16));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(17, &docsis_test_case_17));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(18, &docsis_test_case_18));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(19, &docsis_test_case_19));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(20, &docsis_test_case_20));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(21, &docsis_test_case_21));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(22, &docsis_test_case_22));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(23, &docsis_test_case_23));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(24, &docsis_test_case_24));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(25, &docsis_test_case_25));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(26, &docsis_test_case_26));
+
+	if (f)
+		printf("## %s: %d passed out of %d (%d unsupported)\n",
+			__func__, p, n, u);
+
+	return f;
+};
+
+static int
+test_DOCSIS_PROTO_all(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct rte_cryptodev_info dev_info;
+	int status;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	uint64_t feat_flags = dev_info.feature_flags;
+
+	if (!(feat_flags & RTE_CRYPTODEV_FF_SECURITY))
+		return -ENOTSUP;
+
+	if (security_proto_supported(RTE_SECURITY_PROTOCOL_DOCSIS) < 0)
+		return -ENOTSUP;
+
+	status = test_DOCSIS_PROTO_uplink_all();
+	status += test_DOCSIS_PROTO_downlink_all();
+
+	if (status)
+		return TEST_FAILED;
+	else
+		return TEST_SUCCESS;
+}
 #endif
 
 static int
@@ -12342,6 +12892,8 @@ static struct unit_test_suite cryptodev_testsuite  = {
 #ifdef RTE_LIBRTE_SECURITY
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_PDCP_PROTO_all),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_DOCSIS_PROTO_all),
 #endif
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
diff --git a/app/test/test_cryptodev_security_docsis_test_vectors.h b/app/test/test_cryptodev_security_docsis_test_vectors.h
new file mode 100644
index 000000000..2ed57bd56
--- /dev/null
+++ b/app/test/test_cryptodev_security_docsis_test_vectors.h
@@ -0,0 +1,1544 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_
+
+/*
+ * DOCSIS test data and cases
+ * - encrypt direction: CRC-Crypto
+ * - decrypt direction: Crypto-CRC
+ */
+
+struct docsis_test_data {
+	struct {
+		uint8_t data[32];
+		unsigned int len;
+	} key;
+
+	struct {
+		uint8_t data[16] __rte_aligned(16);
+		unsigned int len;
+	} iv;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} plaintext;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} ciphertext;
+};
+
+struct docsis_test_data docsis_test_case_1 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x61, 0xF8, 0x63, 0x42
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_2 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0, 0xDF,
+			/* CRC */
+			0xFE, 0x12, 0x99, 0xE5
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_3 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xD6, 0xE2, 0x70, 0x5C,
+			0xE6, 0x4D, 0xCC, 0x8C, 0x47, 0xB7, 0x09, 0xD6,
+			/* CRC */
+			0x54, 0x85, 0xF8, 0x32
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_4 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x92, 0x6A, 0xC2, 0xDC,
+			0xEE, 0x3B, 0x31, 0xEC, 0x03, 0xDE, 0x95, 0x33,
+			0x5E,
+			/* CRC */
+			0xFE, 0x47, 0x3E, 0x22
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_5 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0x42, 0xF3, 0x71, 0xA9,
+			0x8A, 0xCD, 0x59, 0x77, 0x67, 0x11, 0x1A, 0x87,
+			/* CRC */
+			0xAB, 0xED, 0x2C, 0x26
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_6 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0xA4, 0x0C, 0xC2, 0xF0,
+			0x81, 0x49, 0xA8, 0xA6, 0x6C, 0x48, 0xEB, 0x1F,
+			0x4B,
+			/* CRC */
+			0x2F, 0xD4, 0x48, 0x18
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_7 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x11, 0xB4, 0x06, 0x33
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_8 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x8A, 0x0F, 0x74, 0xE8
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_9 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x5D, 0x2B, 0x12, 0xF4
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_10 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0x14, 0x08, 0xE8, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_11 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xB3, 0x60, 0xEB, 0x38
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_12 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_13 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_14 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86,
+			/* CRC */
+			0x9B, 0xB3, 0x1A, 0x26
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_15 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86, 0x25,
+			/* CRC */
+			0xB5, 0x6B, 0xFD, 0xCB
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_16 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xF6, 0xA1, 0x2E, 0x0A,
+			0xBB, 0x27, 0x82, 0x4F, 0x99, 0x0A, 0xE2, 0x3F,
+			/* CRC */
+			0xEB, 0xB7, 0x89, 0xB0
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_17 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE1, 0x30, 0x38, 0xC8,
+			0xC4, 0x59, 0x8D, 0x43, 0x9A, 0xBE, 0xBE, 0x73,
+			0xC3,
+			/*CRC */
+			0x8C, 0xE1, 0x89, 0x8B
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_18 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE9, 0x12, 0x3B, 0x12,
+			0x36, 0x56, 0x95, 0xA6, 0x97, 0xF1, 0x74, 0x68,
+			0xBA, 0x58, 0x77, 0xEA, 0x43, 0x11, 0x85, 0xD4,
+			0x7A, 0xF8, 0x1C, 0x11, 0x50, 0xD1, 0xF1, 0xBD,
+			0x15, 0x4D, 0x99, 0xB5, 0x39, 0x74, 0x84, 0xDF,
+			0xD4, 0x8B, 0xDC, 0xB7, 0x58, 0x1B, 0x22, 0xAB,
+			0xF3, 0x29, 0xC6, 0xCB, 0x26, 0x07, 0x36, 0x6B,
+			0x8C, 0xAC, 0x6E, 0x99, 0x37, 0x94, 0xDF, 0x31,
+			/* CRC */
+			0xA1, 0x7D, 0x70, 0xBB
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_19 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE9, 0x12, 0x3B, 0x12,
+			0x36, 0x56, 0x95, 0xA6, 0x97, 0xF1, 0x74, 0x68,
+			0xBA, 0x58, 0x77, 0xEA, 0x43, 0x11, 0x85, 0xD4,
+			0x7A, 0xF8, 0x1C, 0x11, 0x50, 0xD1, 0xF1, 0xBD,
+			0x15, 0x4D, 0x99, 0xB5, 0x39, 0x74, 0x84, 0xDF,
+			0xD4, 0x8B, 0xDC, 0xB7, 0x58, 0x1B, 0x22, 0xAB,
+			0xF3, 0x29, 0xC6, 0xCB, 0x13, 0xED, 0x08, 0xF5,
+			0x1B, 0x4B, 0xD8, 0x79, 0x93, 0x26, 0x69, 0x03,
+			0x23,
+			/* CRC */
+			0xC8, 0x8E, 0x02, 0x3A
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_20 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x54, 0xB4, 0x55, 0x68, 0x06, 0xBF,
+			0x00, 0x8B, 0x5F, 0x2C, 0x10, 0x4A, 0xBF, 0x5A,
+			0xF2, 0x20, 0xD9, 0x77, 0x7F, 0x2D, 0x2B, 0x11,
+			0xAC, 0xAF, 0x21, 0x36, 0xD2, 0xD4, 0x80, 0xF2,
+			0x4F, 0x14, 0xA0, 0x3A, 0x66, 0xE5, 0xC5, 0xE2,
+			0x15,
+			/* CRC */
+			0x0C, 0x89, 0x76, 0x26
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_21 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86,
+			/* CRC */
+			0x70, 0x44, 0x0D, 0x8C
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_22 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x54, 0xB4, 0x55, 0x68, 0x06, 0xBF,
+			0x00, 0x8B, 0x5F, 0x2C, 0x10, 0x4A, 0xBF, 0x5A,
+			0xF2, 0x20, 0xD9, 0x77, 0x7F, 0x2D, 0x2B, 0x11,
+			0xAC, 0xAF, 0x21, 0x36, 0xD2, 0xD4, 0x80, 0xF2,
+			0x4F, 0x14, 0xA0, 0x3A, 0x66, 0xE5, 0xC5, 0xE2,
+			0x15,
+			/* CRC */
+			0x40, 0x16, 0x62, 0xE1
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_23 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0x14, 0x08, 0xE8, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_24 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xB3, 0x60, 0xEB, 0x38
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_25 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_26 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+#endif /* TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_ */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v2 6/6] test/security: add DOCSIS capability check tests
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
                       ` (4 preceding siblings ...)
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 5/6] test/crypto: add DOCSIS security test cases David Coyle
@ 2020-06-23 10:14     ` David Coyle
  2020-06-23 14:51     ` [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol David Marchand
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
  7 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-06-23 10:14 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add unit tests for DOCSIS capabilitity checks.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 app/test/test_security.c | 139 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/app/test/test_security.c b/app/test/test_security.c
index 3076a4c5a..1ea0cb10b 100644
--- a/app/test/test_security.c
+++ b/app/test/test_security.c
@@ -6,6 +6,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_mempool.h>
+#include <rte_ether.h>
 #include <rte_security.h>
 #include <rte_security_driver.h>
 
@@ -2268,6 +2269,138 @@ test_capability_get_pdcp_match(void)
 	return TEST_SUCCESS;
 }
 
+/**
+ * Test execution of rte_security_capability_get when capabilities table does
+ * not contain entry with matching DOCSIS direction field
+ */
+static int
+test_capability_get_docsis_mismatch_direction(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx idx = {
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK,
+			.crc_size = RTE_ETHER_CRC_LEN,
+		},
+	};
+	struct rte_security_capability capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			.docsis = {
+					.direction =
+						RTE_SECURITY_DOCSIS_UPLINK,
+					.crc_size = RTE_ETHER_CRC_LEN,
+			},
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE,
+		},
+	};
+
+	mock_capabilities_get_exp.device = NULL;
+	mock_capabilities_get_exp.ret = capabilities;
+
+	const struct rte_security_capability *ret;
+	ret = rte_security_capability_get(&ut_params->ctx, &idx);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+			ret, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table does
+ * not contain entry with matching DOCSIS CRC length
+ */
+static int
+test_capability_get_docsis_mismatch_crc_len(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx idx = {
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK,
+			.crc_size = 0,
+		},
+	};
+	struct rte_security_capability capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			.docsis = {
+					.direction =
+						RTE_SECURITY_DOCSIS_DOWNLINK,
+					.crc_size = RTE_ETHER_CRC_LEN,
+			},
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE,
+		},
+	};
+
+	mock_capabilities_get_exp.device = NULL;
+	mock_capabilities_get_exp.ret = capabilities;
+
+	const struct rte_security_capability *ret;
+	ret = rte_security_capability_get(&ut_params->ctx, &idx);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+			ret, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * contains matching DOCSIS entry
+ */
+static int
+test_capability_get_docsis_match(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx idx = {
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_UPLINK,
+			.crc_size = RTE_ETHER_CRC_LEN,
+		},
+	};
+	struct rte_security_capability capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			.docsis = {
+					.direction =
+						RTE_SECURITY_DOCSIS_UPLINK,
+					.crc_size = RTE_ETHER_CRC_LEN,
+			},
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE,
+		},
+	};
+
+	mock_capabilities_get_exp.device = NULL;
+	mock_capabilities_get_exp.ret = capabilities;
+
+	const struct rte_security_capability *ret;
+	ret = rte_security_capability_get(&ut_params->ctx, &idx);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+			ret, &capabilities[1], "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+	return TEST_SUCCESS;
+}
+
 /**
  * Declaration of testcases
  */
@@ -2410,6 +2543,12 @@ static struct unit_test_suite security_testsuite  = {
 				test_capability_get_pdcp_mismatch_domain),
 		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
 				test_capability_get_pdcp_match),
+		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+				test_capability_get_docsis_mismatch_direction),
+		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+				test_capability_get_docsis_mismatch_crc_len),
+		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+				test_capability_get_docsis_match),
 
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
                       ` (5 preceding siblings ...)
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 6/6] test/security: add DOCSIS capability check tests David Coyle
@ 2020-06-23 14:51     ` David Marchand
  2020-06-23 15:18       ` Coyle, David
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
  7 siblings, 1 reply; 92+ messages in thread
From: David Marchand @ 2020-06-23 14:51 UTC (permalink / raw)
  To: David Coyle
  Cc: Akhil Goyal, Declan Doherty, Pablo de Lara, Trahe, Fiona,
	Fan Zhang, Ananyev, Konstantin, dev, Thomas Monjalon, Yigit,
	Ferruh, brendan.ryan, Hemant Agrawal, Anoob Joseph,
	Ruifeng Wang (Arm Technology China),
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Bruce Richardson,
	Olivier Matz, Honnappa Nagarahalli, Stephen Hemminger, alexr,
	Jerin Jacob Kollanukkaran

On Tue, Jun 23, 2020 at 12:36 PM David Coyle <david.coyle@intel.com> wrote:
> A number of approaches to combine DOCSIS Crypto and CRC functions have
> been discussed in the DPDK community to date, namely:
> 1) adding a new rte_accelerator API, to provide a generic interface for
>    combining operations of different types
> 2) using rawdev through a multi-function interface, again to provide a
>    generic interface for combining operations of different types
> 3) adding support for DOCSIS Crypto-CRC to rte_security
>
> The third option above is the preferred approach for the following
> reasons:
> - it addresses the immediate use case to add DOCSIS Crypto-CRC support to
>   DPDK so that it can be consumed easily by cable equipment vendors
> - it uses an already existing framework in DPDK
> - it will mean much less code churn in DOCSIS applications, which already
>   use rte_cryptodev for encryption/decryption

I guess https://patchwork.dpdk.org/project/dpdk/list/?series=9304 can
be marked Superseded then.
Thanks.

-- 
David Marchand


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol
  2020-06-23 14:51     ` [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol David Marchand
@ 2020-06-23 15:18       ` Coyle, David
  2020-06-23 15:38         ` David Marchand
  0 siblings, 1 reply; 92+ messages in thread
From: Coyle, David @ 2020-06-23 15:18 UTC (permalink / raw)
  To: David Marchand
  Cc: Akhil Goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin, dev, Thomas Monjalon,
	Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal, Anoob Joseph,
	Ruifeng Wang (Arm Technology China),
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	Olivier Matz, Honnappa Nagarahalli, Stephen Hemminger, alexr,
	Jerin Jacob Kollanukkaran



> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Tuesday, June 23, 2020 3:52 PM
> 
> > A number of approaches to combine DOCSIS Crypto and CRC functions
> have
> > been discussed in the DPDK community to date, namely:
> > 1) adding a new rte_accelerator API, to provide a generic interface for
> >    combining operations of different types
> > 2) using rawdev through a multi-function interface, again to provide a
> >    generic interface for combining operations of different types
> > 3) adding support for DOCSIS Crypto-CRC to rte_security
> >
> > The third option above is the preferred approach for the following
> > reasons:
> > - it addresses the immediate use case to add DOCSIS Crypto-CRC support to
> >   DPDK so that it can be consumed easily by cable equipment vendors
> > - it uses an already existing framework in DPDK
> > - it will mean much less code churn in DOCSIS applications, which already
> >   use rte_cryptodev for encryption/decryption
> 
> I guess https://patchwork.dpdk.org/project/dpdk/list/?series=9304 can be
> marked Superseded then.
> Thanks.

[DC] Yes it can - I have tried to set it to Superseded but don't have permissions to
do that - guess one of the Maintainers needs to do that.
> 
> --
> David Marchand


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol
  2020-06-23 15:18       ` Coyle, David
@ 2020-06-23 15:38         ` David Marchand
  2020-06-23 15:56           ` Coyle, David
  0 siblings, 1 reply; 92+ messages in thread
From: David Marchand @ 2020-06-23 15:38 UTC (permalink / raw)
  To: Coyle, David
  Cc: Akhil Goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin, dev, Thomas Monjalon,
	Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal, Anoob Joseph,
	Ruifeng Wang (Arm Technology China),
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	Olivier Matz, Honnappa Nagarahalli, Stephen Hemminger, alexr,
	Jerin Jacob Kollanukkaran

On Tue, Jun 23, 2020 at 5:18 PM Coyle, David <david.coyle@intel.com> wrote:
> > I guess https://patchwork.dpdk.org/project/dpdk/list/?series=9304 can be
> > marked Superseded then.
> > Thanks.
>
> [DC] Yes it can - I have tried to set it to Superseded but don't have permissions to
> do that - guess one of the Maintainers needs to do that.

You need to be logged in patchwork and have the same mail address that
sent the series attached to your account.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol
  2020-06-23 15:38         ` David Marchand
@ 2020-06-23 15:56           ` Coyle, David
  2020-06-23 16:22             ` David Marchand
  0 siblings, 1 reply; 92+ messages in thread
From: Coyle, David @ 2020-06-23 15:56 UTC (permalink / raw)
  To: David Marchand
  Cc: Akhil Goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin, dev, Thomas Monjalon,
	Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal, Anoob Joseph,
	Ruifeng Wang (Arm Technology China),
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	Olivier Matz, Honnappa Nagarahalli, Stephen Hemminger, alexr,
	Jerin Jacob Kollanukkaran

> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Tuesday, June 23, 2020 4:39 PM
> > > I guess https://patchwork.dpdk.org/project/dpdk/list/?series=9304
> > > can be marked Superseded then.
> > > Thanks.
> >
> > [DC] Yes it can - I have tried to set it to Superseded but don't have
> > permissions to do that - guess one of the Maintainers needs to do that.
> 
> You need to be logged in patchwork and have the same mail address that
> sent the series attached to your account.
> 
[DC] I have tried attach my email address to my account but I think Intel has some
blocker on emails coming from patchwork, so I'm not receiving the confirmation email.
This same problem with emails getting blocked also hit me before when I originally signed
up to patchwork.

Thanks for the info on this btw.


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol
  2020-06-23 15:56           ` Coyle, David
@ 2020-06-23 16:22             ` David Marchand
  2020-06-23 16:27               ` Coyle, David
  0 siblings, 1 reply; 92+ messages in thread
From: David Marchand @ 2020-06-23 16:22 UTC (permalink / raw)
  To: Coyle, David
  Cc: Akhil Goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin, dev, Thomas Monjalon,
	Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal, Anoob Joseph,
	Ruifeng Wang (Arm Technology China),
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	Olivier Matz, Honnappa Nagarahalli, Stephen Hemminger, alexr,
	Jerin Jacob Kollanukkaran

On Tue, Jun 23, 2020 at 5:56 PM Coyle, David <david.coyle@intel.com> wrote:
>
> > -----Original Message-----
> > From: David Marchand <david.marchand@redhat.com>
> > Sent: Tuesday, June 23, 2020 4:39 PM
> > > > I guess https://patchwork.dpdk.org/project/dpdk/list/?series=9304
> > > > can be marked Superseded then.
> > > > Thanks.
> > >
> > > [DC] Yes it can - I have tried to set it to Superseded but don't have
> > > permissions to do that - guess one of the Maintainers needs to do that.
> >
> > You need to be logged in patchwork and have the same mail address that
> > sent the series attached to your account.
> >
> [DC] I have tried attach my email address to my account but I think Intel has some
> blocker on emails coming from patchwork, so I'm not receiving the confirmation email.
> This same problem with emails getting blocked also hit me before when I originally signed
> up to patchwork.

I saw some offlist exchanges about this.
It might be the right time to push your IT about this issue :-).

I marked the series as superseded.


-- 
David Marchand


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol
  2020-06-23 16:22             ` David Marchand
@ 2020-06-23 16:27               ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-06-23 16:27 UTC (permalink / raw)
  To: David Marchand
  Cc: Akhil Goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin, dev, Thomas Monjalon,
	Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal, Anoob Joseph,
	Ruifeng Wang (Arm Technology China),
	Liron Himi, Nagadheeraj Rottela, Srikanth Jampala,
	Gagandeep Singh, Jay Zhou, Ravi Kumar, Richardson, Bruce,
	Olivier Matz, Honnappa Nagarahalli, Stephen Hemminger, alexr,
	Jerin Jacob Kollanukkaran

> -----Original Message-----
> From: David Marchand <david.marchand@redhat.com>
> Sent: Tuesday, June 23, 2020 5:22 PM
> To: Coyle, David <david.coyle@intel.com>
> > > > > I guess
> > > > > https://patchwork.dpdk.org/project/dpdk/list/?series=9304
> > > > > can be marked Superseded then.
> > > > > Thanks.
> > > >
> > > > [DC] Yes it can - I have tried to set it to Superseded but don't
> > > > have permissions to do that - guess one of the Maintainers needs to do
> that.
> > >
> > > You need to be logged in patchwork and have the same mail address
> > > that sent the series attached to your account.
> > >
> > [DC] I have tried attach my email address to my account but I think
> > Intel has some blocker on emails coming from patchwork, so I'm not
> receiving the confirmation email.
> > This same problem with emails getting blocked also hit me before when
> > I originally signed up to patchwork.
> 
> I saw some offlist exchanges about this.
> It might be the right time to push your IT about this issue :-).
[DC] I think you are right - I will try get this resolved.
> 
> I marked the series as superseded.
[DC] Thank you for doing that and apologies for the inconvenience.


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol David Coyle
@ 2020-06-23 17:29       ` De Lara Guarch, Pablo
  2020-06-26 15:15         ` Coyle, David
  2020-06-23 18:06       ` Akhil Goyal
  1 sibling, 1 reply; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-06-23 17:29 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin



> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Tuesday, June 23, 2020 11:14 AM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v2 2/6] security: add support for DOCSIS protocol
> 
> Add support for DOCSIS protocol to rte_security library. This support currently
> comprises the combination of Crypto and CRC operations.
> 
> A security operation definition is also added. This allow security protocol related
> parameters be specified at the operation level. For DOCSIS, these parameters
> include CRC length and offset. The security operation is accessed via a crypto
> operation.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>

...

> +++ b/lib/librte_security/rte_security.h
> @@ -293,6 +293,30 @@ struct rte_security_pdcp_xform {
>  	uint32_t hfn_ovrd;
>  };
> 
> +/** DOCSIS direction */
> +enum rte_security_docsis_direction {
> +	RTE_SECURITY_DOCSIS_UPLINK,
> +	/**< Uplink
> +	 * - Decryption, followed by CRC Verification
> +	 */
> +	RTE_SECURITY_DOCSIS_DOWNLINK,
> +	/**< Downlink
> +	 * - CRC Generation, followed by Encryption
> +	 */
> +};
> +
> +/**
> + * DOCSIS security session configuration.
> + *
> + * This structure contains data required to create a DOCSIS security session.
> + */
> +struct rte_security_docsis_xform {
> +	enum rte_security_docsis_direction direction;
> +	/** DOCSIS direction */

Missing "<" here.



^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/6] crypto/aesni_mb: add support for DOCSIS protocol
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 3/6] crypto/aesni_mb: " David Coyle
@ 2020-06-23 17:57       ` De Lara Guarch, Pablo
  2020-06-26 15:13         ` Coyle, David
  0 siblings, 1 reply; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-06-23 17:57 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi David,

> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Tuesday, June 23, 2020 11:14 AM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v2 3/6] crypto/aesni_mb: add support for DOCSIS protocol
> 
> Add support to the AESNI-MB PMD for the DOCSIS protocol, through the
> rte_security API. This, therefore, includes adding support for the rte_security API
> to this PMD.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>

...

> +static inline void
> +verify_docsis_sec_crc(JOB_AES_HMAC *job, uint16_t crc_len, uint8_t
> +*status) {
> +	uint16_t crc_offset;
> +	uint8_t *crc;
> +
> +	if (!job->msg_len_to_hash_in_bytes)
> +		return;
> +
> +	crc_offset = job->hash_start_src_offset_in_bytes +
> +			job->msg_len_to_hash_in_bytes -
> +			job->cipher_start_src_offset_in_bytes;
> +	crc = job->dst + crc_offset;
> +
> +	/* Verify CRC (at the end of the message) */
> +	if (memcmp(job->auth_tag_output, crc, crc_len) != 0)

I'd say we can use direct RTE_ETHER_CRC_LEN here, as there is no other possible case, right?
It should perform better.

> +		*status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; } #endif
> +
>  static inline void
>  verify_digest(JOB_AES_HMAC *job, void *digest, uint16_t len, uint8_t *status)  {
> @@ -1196,9 +1452,27 @@ static inline struct rte_crypto_op *
> post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)  {
>  	struct rte_crypto_op *op = (struct rte_crypto_op *)job->user_data;
> -	struct aesni_mb_session *sess = get_sym_session_private_data(
> -							op->sym->session,
> -							cryptodev_driver_id);
> +	struct aesni_mb_session *sess = NULL;
> +
> +#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
> +	struct rte_security_op *sec_op = NULL;
> +
> +	if (unlikely(op->type == RTE_CRYPTO_OP_TYPE_SECURITY)) {

Not sure if this unlikely is actually needed. I don't expect to have multiple types enqueued in the same queue,
so this or the other branch will always be taken.

> +		/*
> +		 * Assuming at this point that if it's a security type op, that
> +		 * this is for DOCSIS
> +		 */
> +		sec_op = (struct rte_security_op *)&op->security;
> +		struct rte_crypto_sym_op *crypto_sym =
> +						&sec_op->docsis.crypto_sym;
> +		sess = get_sec_session_private_data(crypto_sym-
> >sec_session);

...

> -		retval = set_mb_job_params(job, qp, op, &digest_idx);
> +#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
> +		if (unlikely(op->type == RTE_CRYPTO_OP_TYPE_SECURITY))

Same comment as above.

> +			retval = set_sec_mb_job_params(job, qp, op,
> +						&digest_idx);
> +		else
> +#endif


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] test/crypto: add DOCSIS security test cases
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 5/6] test/crypto: add DOCSIS security test cases David Coyle
@ 2020-06-23 18:04       ` De Lara Guarch, Pablo
  2020-06-26 15:14         ` Coyle, David
  0 siblings, 1 reply; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-06-23 18:04 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi David,

> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Tuesday, June 23, 2020 11:14 AM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v2 5/6] test/crypto: add DOCSIS security test cases
> 
> Add uplink and downlink DOCSIS unit test cases and vectors, to test
> the combined DOCSIS Crypto-CRC support that has been added to the
> rte_security and rte_cryptodev libraries.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>

...

> +static int
> +test_docsis_proto_uplink(int i, struct docsis_test_data *d_td)
> +{
> +	struct rte_security_op *sec_op;
> +	struct rte_security_docsis_op *doc_op;
> +	struct crypto_testsuite_params *ts_params = &testsuite_params;
> +	struct crypto_unittest_params *ut_params = &unittest_params;
> +	uint8_t *plaintext, *ciphertext;
> +	uint8_t *iv_ptr;
> +	int cipher_len = 0;
> +	int crc_len = 0, crc_data_len;

Minor comment. These "int" should be "unsigned int", as they are not going to hold a negative value.

> +	int ret = TEST_SUCCESS;

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol
  2020-06-23 10:14     ` [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol David Coyle
  2020-06-23 17:29       ` De Lara Guarch, Pablo
@ 2020-06-23 18:06       ` Akhil Goyal
  2020-06-24 14:25         ` Coyle, David
  1 sibling, 1 reply; 92+ messages in thread
From: Akhil Goyal @ 2020-06-23 18:06 UTC (permalink / raw)
  To: David Coyle, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, Hemant Agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, Gagandeep Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj,
	Mairtin o Loingsigh

Hi David,

> +/** DOCSIS direction */
> +enum rte_security_docsis_direction {
> +	RTE_SECURITY_DOCSIS_UPLINK,
> +	/**< Uplink
> +	 * - Decryption, followed by CRC Verification
> +	 */
> +	RTE_SECURITY_DOCSIS_DOWNLINK,
> +	/**< Downlink
> +	 * - CRC Generation, followed by Encryption
> +	 */
> +};
> +
> +/**
> + * DOCSIS security session configuration.
> + *
> + * This structure contains data required to create a DOCSIS security session.
> + */
> +struct rte_security_docsis_xform {
> +	enum rte_security_docsis_direction direction;
> +	/** DOCSIS direction */
> +	uint16_t crc_size;
> +	/**< CRC size in bytes */
> +};
> +
>  /**
>   * Security session action type.
>   */
> @@ -325,6 +349,8 @@ enum rte_security_session_protocol {
>  	/**< MACSec Protocol */
>  	RTE_SECURITY_PROTOCOL_PDCP,
>  	/**< PDCP Protocol */
> +	RTE_SECURITY_PROTOCOL_DOCSIS,
> +	/**< DOCSIS Protocol */
>  };
> 
>  /**
> @@ -340,6 +366,7 @@ struct rte_security_session_conf {
>  		struct rte_security_ipsec_xform ipsec;
>  		struct rte_security_macsec_xform macsec;
>  		struct rte_security_pdcp_xform pdcp;
> +		struct rte_security_docsis_xform docsis;
>  	};
>  	/**< Configuration parameters for security session */
>  	struct rte_crypto_sym_xform *crypto_xform;
> @@ -355,6 +382,63 @@ struct rte_security_session {
>  	/**< Opaque user defined data */
>  };
> 
> +/**
> + * DOCSIS operation parameters
> + */
> +struct rte_security_docsis_op {
> +	struct rte_crypto_sym_op crypto_sym;
> +	/**< Symmetric crypto operation parameters */
> +
> +	struct {
> +		uint16_t offset;
> +		/**<
> +		 * Starting point for CRC processing, specified
> +		 * as the number of bytes from start of the packet in
> +		 * the source mbuf in crypto_sym
> +		 */
> +		uint16_t length;
> +		/**<
> +		 * The length, in bytes, of the source mbuf on which the
> +		 * CRC will be computed
> +		 */
> +	} crc;
> +	/**< CRC operation parameters */

As per my understanding, CRC is a kind of authentication. Can we reuse the fields of rte_crypto_sym_op
Auth.data.offset and auth.data.length. This way you can save the unnecessary 4 bytes here. Probably add
Comment in the structure definition that it can be used as offset and length for CRC.

And if you feel that reserved field is needed in near future, then you can add a proper name to it or else
You can do away with the rte_security_docsis_op itself as there will be no other fields in it.

> +
> +	uint64_t reserved;
> +	/**< Reserved for future use */
> +};
> +
> +/**
> + * Security operation types
> + */
> +enum rte_security_op_type {
> +	RTE_SECURITY_OP_TYPE_DOCSIS = 1
> +	/**< DOCSIS operation */
> +};
> +
> +/**
> + * Security operation parameters
> + *
> + * @note If the size of this struct changes, it may be also necessary to update
> + * the RTE_CRYPTO_OP_SECURITY_MAX_SZ define
> + */
> +struct rte_security_op {
> +	enum rte_security_op_type type;
> +	/**< Type of operation */
> +	RTE_STD_C11
> +	union {
> +		struct rte_security_docsis_op docsis;
> +	};
> +	/**< Parameters for security operation */
> +};
> +
> +/* Macro to check the size of a struct at compile time */
> +#define _SECURITY_STRUCT_LEN_CHECK(n, X) enum
> security_static_assert_enum_##X \
> +	{ security_static_assert_##X = (n)/((sizeof(struct X) <= (n)) ? 1 : 0) }
> +
> +/* Check the size of the rte_security_op struct */
> +_SECURITY_STRUCT_LEN_CHECK(RTE_CRYPTO_OP_SECURITY_MAX_SZ,
> rte_security_op);
> +
>  /**
>   * Create security session as specified by the session configuration
>   *
> @@ -496,12 +580,22 @@ static inline int
>  rte_security_attach_session(struct rte_crypto_op *op,
>  			    struct rte_security_session *sess)
>  {
> -	if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC))
> -		return -EINVAL;
> +	struct rte_security_op *s_op;
> +	int ret = -EINVAL;
> +
> +	if (likely(op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC)) {
> +		ret = __rte_security_attach_session(op->sym, sess);
> +	} else if (op->type == RTE_CRYPTO_OP_TYPE_SECURITY) {
> +		s_op = (struct rte_security_op *)&op->security;
> +		if (s_op->type == RTE_SECURITY_OP_TYPE_DOCSIS)
> +			ret = __rte_security_attach_session(
> +						&s_op->docsis.crypto_sym,
> +						sess);
> +	}
> 
>  	op->sess_type =  RTE_CRYPTO_OP_SECURITY_SESSION;
> 
> -	return __rte_security_attach_session(op->sym, sess);
> +	return ret;
>  }
> 
>  struct rte_security_macsec_stats {
> @@ -523,6 +617,10 @@ struct rte_security_pdcp_stats {
>  	uint64_t reserved;
>  };
> 
> +struct rte_security_docsis_stats {
> +	uint64_t reserved;
> +};
> +
>  struct rte_security_stats {
>  	enum rte_security_session_protocol protocol;
>  	/**< Security protocol to be configured */
> @@ -532,6 +630,7 @@ struct rte_security_stats {
>  		struct rte_security_macsec_stats macsec;
>  		struct rte_security_ipsec_stats ipsec;
>  		struct rte_security_pdcp_stats pdcp;
> +		struct rte_security_docsis_stats docsis;
>  	};
>  };
> 
> @@ -591,6 +690,13 @@ struct rte_security_capability {
>  			/**< Capability flags, see RTE_SECURITY_PDCP_* */
>  		} pdcp;
>  		/**< PDCP capability */
> +		struct {
> +			enum rte_security_docsis_direction direction;
> +			/**< DOCSIS direction */
> +			uint16_t crc_size;
> +			/**< CRC size in bytes */
> +		} docsis;
> +		/**< DOCSIS capability */
>  	};
> 
>  	const struct rte_cryptodev_capabilities *crypto_capabilities;
> @@ -649,6 +755,10 @@ struct rte_security_capability_idx {
>  			enum rte_security_pdcp_domain domain;
>  			uint32_t capa_flags;
>  		} pdcp;
> +		struct {
> +			enum rte_security_docsis_direction direction;
> +			uint16_t crc_size;
> +		} docsis;
>  	};
>  };
> 
> --
> 2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-11 12:21             ` Ananyev, Konstantin
  2020-06-11 14:01               ` Coyle, David
@ 2020-06-23 18:38               ` Akhil Goyal
  2020-06-24 14:11                 ` Coyle, David
  1 sibling, 1 reply; 92+ messages in thread
From: Akhil Goyal @ 2020-06-23 18:38 UTC (permalink / raw)
  To: Ananyev, Konstantin, Coyle, David, Doherty, Declan,
	De Lara Guarch, Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth,
	Gagandeep Singh, jianjay.zhou, ravi1.kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, stephen, alexr, jerinj,
	O'loingsigh, Mairtin

Hi Konstantin/David,

> 
> Hi David,
> 
> > > > >
> > > > > >
> > > > > >  /** Status of crypto operation */ @@ -121,6 +123,13 @@ struct
> > > > > > rte_crypto_op {
> > > > > >  		struct rte_crypto_asym_op asym[0];
> > > > > >  		/**< Asymmetric operation parameters */
> > > > > >
> > > > > > +#ifdef RTE_LIBRTE_SECURITY
> > > > > > +		uint8_t security[0];
> > > > > > +		/**< Security operation parameters
> > > > > > +		 * - Must be accessed through a rte_security_op pointer
> > > > > > +		 */
> > > > > > +#endif
> > > > > > +
> > > > > >  	}; /**< operation specific parameters */  };
> > > > >
> > > > > Is there any point to have this extra level of indirection?
> > > > > Might be simply:
> > > > >
> > > > > enum rte_crypto_op_type {
> > > > > 	....
> > > > > +	RTE_CRYPTO_OP_TYPE_SEC_DOCSIS,
> > > > > };
> > > > > ...
> > > > > struct rte_crypto_op {
> > > > > 	....
> > > > > 	__extension__
> > > > >         union {
> > > > >                 struct rte_crypto_sym_op sym[0];
> > > > >                 /**< Symmetric operation parameters */
> > > > >
> > > > >                 struct rte_crypto_asym_op asym[0];
> > > > >                 /**< Asymmetric operation parameters */
> > > > >
> > > > > +	struct rte_security_docsis_op docsis[0];
> > > > >
> > > > >         }; /**< operation specific parameters */
> > > > >
> > > > > ?
> > > > [DC] This was to allow some form of extensibility and not to limit this to
> just
> > > DOCSIS.
> > > > If it's felt that having the extra level of indirection is overkill, it can be easily
> > > changed.
> > > >
> > > > However, we cannot include a struct of type 'struct
> > > > rte_security_docsis_op' (or 'struct rte_security_op') directly here,
> > > > without creating nasty circular dependency of includes between
> > > rte_cryptodev and rte_security.
> > > >
> > > > I had tried defining an opaque version 'struct rte_security_op' (i.e.
> > > > no fields within the struct) here in rte_crypto.h, but the compiler
> > > > complained that it couldn't determine the size of the struct, even though
> > > it's a zero length array.
> > > >
> > > > That is why I had to use the uint8_t in 'uint8_t security[0];' - I
> > > > don't like this, but I couldn't find another way that kept the compiler happy
> > > and didn't create a circular dependency.
> > >
> > > I see... would it be an option to name this struct 'struct rte_sym_docsis_op
> > > and and move actual definition inside
> > > lib/librte_cryptodev/rte_crypto_sym.h?
> > >
> > [DC] It's certainly an option and would work but I don't think it's a good idea to
> be putting
> > protocol specific structs like this in rte_cryptodev - that's what rte_security is
> for.
> > Do you think it would be ok to do this?
> 
> I personally don't see a problem with this.
> In fact, as an extra  thought - why we can't have docsis xform defined in
> lib/librte_cryptodev/rte_crypto_sym.h too, and then just have it  as a member
> inside struct rte_crypto_sym_xform union?
> Then we can have rte_cryptodev_sym_session that supports docsis stuff.

Adding DOCSIS alone is not an issue in the cryptodev. The intent of this patchset and 
Previous RFCs was chaining of two - DOCSIS and CRC which are supposed to be separate
Blocks and we need a way to combine the two and use it in the application.
rte_security provides a way to handle such protocols for algo combinations. 
However, IMO we do not really need a separate rte_security_docsis_op structure,
As it has parameters which are already there in the rte_crypto_sym_op. This new op
Struct is just adding extra bytes which can be avoided if we use sym_op->auth.data.offset 
And sym_op->auth.data.length in place of crc offset and crc length.
We may just need to add comment in the struct definition about its usage for CRC cases.

> 
> >
> > I'd be interested to hear what cryptodev/security maintainers and others think
> too.
> > Akhil/Declan - any thoughts on best approach here?


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH 2/3] cryptodev: add security operation to crypto operation
  2020-06-23 18:38               ` Akhil Goyal
@ 2020-06-24 14:11                 ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-06-24 14:11 UTC (permalink / raw)
  To: Akhil Goyal, Ananyev, Konstantin, Doherty, Declan,
	De Lara Guarch, Pablo, Trahe, Fiona, Zhang, Roy Fan
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth,
	Gagandeep Singh, jianjay.zhou, ravi1.kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, stephen, alexr, jerinj,
	O'loingsigh, Mairtin

Hi Akhil

> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Tuesday, June 23, 2020 7:38 PM
> > > >
> > > [DC] It's certainly an option and would work but I don't think it's
> > > a good idea to
> > be putting
> > > protocol specific structs like this in rte_cryptodev - that's what
> > > rte_security is
> > for.
> > > Do you think it would be ok to do this?
> >
> > I personally don't see a problem with this.
> > In fact, as an extra  thought - why we can't have docsis xform defined
> > in lib/librte_cryptodev/rte_crypto_sym.h too, and then just have it
> > as a member inside struct rte_crypto_sym_xform union?
> > Then we can have rte_cryptodev_sym_session that supports docsis stuff.
> 
> Adding DOCSIS alone is not an issue in the cryptodev. The intent of this
> patchset and Previous RFCs was chaining of two - DOCSIS and CRC which are
> supposed to be separate Blocks and we need a way to combine the two and
> use it in the application.
> rte_security provides a way to handle such protocols for algo combinations.
> However, IMO we do not really need a separate rte_security_docsis_op
> structure, As it has parameters which are already there in the
> rte_crypto_sym_op. This new op Struct is just adding extra bytes which can
> be avoided if we use sym_op->auth.data.offset And sym_op-
> >auth.data.length in place of crc offset and crc length.
> We may just need to add comment in the struct definition about its usage for
> CRC cases.
> 
[DC] I take your point that introducing the rte_security_docsis_op (and the outer
rte_security_op) structure is just adding extra bytes and as Konstantin mentioned,
unnecessary levels of indirection. I am happy to go with the approach of using the
auth offset and length from the sym_op for the CRC values, if there are no major
objections from others on this. This simplifies things and also means we can now
remove the 'uint8_t security[0]' field from rte_crypto_op which was never a nice
thing.

Konstantin also suggested moving the docsis xform to cryptodev. However, I
feel this would be a step too far for cryptodev and propose we keep the docsis
xform in rte_security. It is then consistent with the other protocols like IPSec.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol
  2020-06-23 18:06       ` Akhil Goyal
@ 2020-06-24 14:25         ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-06-24 14:25 UTC (permalink / raw)
  To: Akhil Goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth,
	Gagandeep Singh, jianjay.zhou, ravi1.kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, stephen, alexr, jerinj,
	O'loingsigh, Mairtin

Hi Akhil,

> -----Original Message-----
> From: Akhil Goyal <akhil.goyal@nxp.com>
> Sent: Tuesday, June 23, 2020 7:07 PM
> >
> > +/**
> > + * DOCSIS operation parameters
> > + */
> > +struct rte_security_docsis_op {
> > +	struct rte_crypto_sym_op crypto_sym;
> > +	/**< Symmetric crypto operation parameters */
> > +
> > +	struct {
> > +		uint16_t offset;
> > +		/**<
> > +		 * Starting point for CRC processing, specified
> > +		 * as the number of bytes from start of the packet in
> > +		 * the source mbuf in crypto_sym
> > +		 */
> > +		uint16_t length;
> > +		/**<
> > +		 * The length, in bytes, of the source mbuf on which the
> > +		 * CRC will be computed
> > +		 */
> > +	} crc;
> > +	/**< CRC operation parameters */
> 
> As per my understanding, CRC is a kind of authentication. Can we reuse the
> fields of rte_crypto_sym_op Auth.data.offset and auth.data.length. This way
> you can save the unnecessary 4 bytes here. Probably add Comment in the
> structure definition that it can be used as offset and length for CRC.
> 
> And if you feel that reserved field is needed in near future, then you can add
> a proper name to it or else You can do away with the rte_security_docsis_op
> itself as there will be no other fields in it.

[DC] As per my reply on the v1 patchset, I am happy to use the auth offset and
length fields for CRC if there are no objections from others on this approach.

Strictly speaking, a CRC is not an authentication algorithm like the other auth
algos in cryptodev - if it were we would have just added CRC as a new auth algo.
However, using the auth offset and length fields of the crypto op does simplify
things, removes unnecessary bytes and levels of indirection. It also means the
'uint8_t security[0]' field can be removed from rte_crypto_op.

The 'reserved' field was to accommodate other DOCSIS protocol features which
could be offloaded in the future - such as the DOCSIS header checksum. For this
feature, we would need to know the DOCSIS header length. The header length
though is equal to the CRC offset, so we can get the header length that way.
The reserved field and the entire rte_security_docsis_op can therefore be
removed

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/6] crypto/aesni_mb: add support for DOCSIS protocol
  2020-06-23 17:57       ` De Lara Guarch, Pablo
@ 2020-06-26 15:13         ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-06-26 15:13 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, akhil.goyal, Doherty, Declan, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi Pablo, thank you for the comments

> -----Original Message-----
> From: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>
> Sent: Tuesday, June 23, 2020 6:57 PM
> 
> > +static inline void
> > +verify_docsis_sec_crc(JOB_AES_HMAC *job, uint16_t crc_len, uint8_t
> > +*status) {
> > +	uint16_t crc_offset;
> > +	uint8_t *crc;
> > +
> > +	if (!job->msg_len_to_hash_in_bytes)
> > +		return;
> > +
> > +	crc_offset = job->hash_start_src_offset_in_bytes +
> > +			job->msg_len_to_hash_in_bytes -
> > +			job->cipher_start_src_offset_in_bytes;
> > +	crc = job->dst + crc_offset;
> > +
> > +	/* Verify CRC (at the end of the message) */
> > +	if (memcmp(job->auth_tag_output, crc, crc_len) != 0)
> 
> I'd say we can use direct RTE_ETHER_CRC_LEN here, as there is no other
> possible case, right?
> It should perform better.

[DC] You are correct - I have changed this to use RTE_ETHER_CRC_LEN.

I had been thinking about removing the crc_size from the rte_security_docsis_xform
and the docsis capabilities completely and your comment here has made me realize
I should do this, as there is only 1 CRC length that can be used for DOCSIS.
So these have been removed.

These changes will be in v3 early next week

> 
> > +		*status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; } #endif
> > +
> >  static inline void
> >  verify_digest(JOB_AES_HMAC *job, void *digest, uint16_t len, uint8_t
> > *status)  { @@ -1196,9 +1452,27 @@ static inline struct rte_crypto_op
> > * post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)  {
> >  	struct rte_crypto_op *op = (struct rte_crypto_op *)job->user_data;
> > -	struct aesni_mb_session *sess = get_sym_session_private_data(
> > -							op->sym->session,
> > -							cryptodev_driver_id);
> > +	struct aesni_mb_session *sess = NULL;
> > +
> > +#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
> > +	struct rte_security_op *sec_op = NULL;
> > +
> > +	if (unlikely(op->type == RTE_CRYPTO_OP_TYPE_SECURITY)) {
> 
> Not sure if this unlikely is actually needed. I don't expect to have multiple
> types enqueued in the same queue, so this or the other branch will always
> be taken.

[DC] That's a fair point - I have removed the unlikely
Again, the change will be available in v3

> 
> > +		/*
> > +		 * Assuming at this point that if it's a security type op, that
> > +		 * this is for DOCSIS
> > +		 */
> > +		sec_op = (struct rte_security_op *)&op->security;
> > +		struct rte_crypto_sym_op *crypto_sym =
> > +						&sec_op-
> >docsis.crypto_sym;
> > +		sess = get_sec_session_private_data(crypto_sym-
> > >sec_session);
> 
> ...
> 
> > -		retval = set_mb_job_params(job, qp, op, &digest_idx);
> > +#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
> > +		if (unlikely(op->type == RTE_CRYPTO_OP_TYPE_SECURITY))
> 
> Same comment as above.
[DC] Same reply as above. :)
> 
> > +			retval = set_sec_mb_job_params(job, qp, op,
> > +						&digest_idx);
> > +		else
> > +#endif


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 5/6] test/crypto: add DOCSIS security test cases
  2020-06-23 18:04       ` De Lara Guarch, Pablo
@ 2020-06-26 15:14         ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-06-26 15:14 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, akhil.goyal, Doherty, Declan, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi Pablo

> -----Original Message-----
> From: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>
> Sent: Tuesday, June 23, 2020 7:04 PM
> 
> > +static int
> > +test_docsis_proto_uplink(int i, struct docsis_test_data *d_td) {
> > +	struct rte_security_op *sec_op;
> > +	struct rte_security_docsis_op *doc_op;
> > +	struct crypto_testsuite_params *ts_params = &testsuite_params;
> > +	struct crypto_unittest_params *ut_params = &unittest_params;
> > +	uint8_t *plaintext, *ciphertext;
> > +	uint8_t *iv_ptr;
> > +	int cipher_len = 0;
> > +	int crc_len = 0, crc_data_len;
> 
> Minor comment. These "int" should be "unsigned int", as they are not going
> to hold a negative value.
[DC] Kind of correct, but not fully.

There are some calculations further down which subtract cipher_offset, crc_offset
and RTE_ETHER_CRC_LEN from the overall buffer size, which could (if test cases aren't
setup correctly) make the results negative. These results get put into the cipher_len and
crc_len variables. If the result is negative, it just gets reset to 0. This was just handier than
having if/else checks below. I don't see any major issue with this.

The crc_data_len variable can only have positive values though, so I have changed that
to a uint32_t

Updates will be in v3 early next week

> 
> > +	int ret = TEST_SUCCESS;

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/6] security: add support for DOCSIS protocol
  2020-06-23 17:29       ` De Lara Guarch, Pablo
@ 2020-06-26 15:15         ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-06-26 15:15 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, akhil.goyal, Doherty, Declan, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin

Hi Pablo

> -----Original Message-----
> From: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>
> > +/**
> > + * DOCSIS security session configuration.
> > + *
> > + * This structure contains data required to create a DOCSIS security
> session.
> > + */
> > +struct rte_security_docsis_xform {
> > +	enum rte_security_docsis_direction direction;
> > +	/** DOCSIS direction */
> 
> Missing "<" here.

[DC] Very good spot... will be fixed in v3
> 


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 0/8] add support for DOCSIS protocol
  2020-06-23 10:14   ` [dpdk-dev] [PATCH v2 0/6] " David Coyle
                       ` (6 preceding siblings ...)
  2020-06-23 14:51     ` [dpdk-dev] [PATCH v2 0/6] add support for DOCSIS protocol David Marchand
@ 2020-06-30 16:30     ` David Coyle
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 1/8] security: " David Coyle
                         ` (8 more replies)
  7 siblings, 9 replies; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle

Introduction
============

This patchset adds support for the DOCSIS protocol to the DPDK Security
API (rte_security), to be used by the AESNI-MB and QAT crypto devices to
combine and accelerate Crypto and CRC functions of the DOCSIS protocol
into a single operation.

Performing these functions in parallel as a single operation can enable a
significant performance improvement in a DPDK-based DOCSIS MAC pipeline.


Background
==========

A number of approaches to combine DOCSIS Crypto and CRC functions have
been discussed in the DPDK community to date, namely:
1) adding a new rte_accelerator API, to provide a generic interface for
   combining operations of different types
2) using rawdev through a multi-function interface, again to provide a
   generic interface for combining operations of different types
3) adding support for DOCSIS Crypto-CRC to rte_security

The third option above is the preferred approach for the following
reasons:
- it addresses the immediate use case to add DOCSIS Crypto-CRC support to
  DPDK so that it can be consumed easily by cable equipment vendors
- it uses an already existing framework in DPDK
- it will mean much less code churn in DOCSIS applications, which already
  use rte_cryptodev for encryption/decryption


Use Cases
=========

The primary use case for this proposal has already been mentioned, namely
to add DOCSIS Crypto-CRC support to DPDK:

- DOCSIS MAC: Crypto-CRC
	- Order:
		- Downstream: CRC, Encrypt
		- Upstream: Decrypt, CRC
	- Specifications:
		- Crypto: 128-bit and 256-bit AES-CFB encryption variant
		  for DOCSIS as described in section 11.1 of DOCSIS 3.1
		  Security Specification
		  (https://apps.cablelabs.com/specification/CM-SP-SECv3.1)
		- CRC: Ethernet 32-bit CRC as defined in
		  Ethernet/[ISO/IEC 8802-3]

Note that support for these chained operations is already available in
the Intel IPSec Multi-Buffer library.

However, other DOCSIS protocol functions could be optimized too in the
future using the same rte_security API for DOCSIS (e.g. Header Checksum
(HCS) calculation).

v3:
* removed rte_security_op definition
  * now using rte_crypto_sym_op->auth.data fields for CRC offset and
    length as suggested by feedback from Akhil and Konstantin
* addressed Pablo's comments
* removed support for out-of-place for DOCSIS protocol from QAT PMD
* updated dpdk-crypto-perf-test tool for DOCSIS
* updated documentation

v2:
* added rte_security and rte_cryptodev code changes
* added AESNI MB crypto PMD code changes
* added QAT SYM crypto PMD code changes
* added crypto unit tests
* added security unit tests

v1:
* added proposed API changes
* added security capabilities to aesni_mb crypto PMD

David Coyle (8):
  security: add support for DOCSIS protocol
  cryptodev: add a note regarding DOCSIS protocol support
  crypto/aesni_mb: add support for DOCSIS protocol
  crypto/qat: add support for DOCSIS protocol
  test/crypto: add DOCSIS security test cases
  test/security: add DOCSIS capability check tests
  app/crypto-perf: add support for DOCSIS protocol
  doc: add doc updates for DOCSIS security protocol

 app/test-crypto-perf/cperf_ops.c              |   82 +-
 app/test-crypto-perf/cperf_options.h          |    5 +-
 app/test-crypto-perf/cperf_options_parsing.c  |   67 +-
 app/test-crypto-perf/cperf_test_throughput.c  |    3 +-
 app/test-crypto-perf/cperf_test_vectors.c     |    3 +-
 app/test-crypto-perf/main.c                   |    5 +-
 app/test-crypto-perf/meson.build              |    2 +-
 app/test/test_cryptodev.c                     |  513 ++++++
 ...t_cryptodev_security_docsis_test_vectors.h | 1544 +++++++++++++++++
 app/test/test_security.c                      |   88 +
 doc/guides/cryptodevs/aesni_mb.rst            |    8 +
 doc/guides/cryptodevs/features/aesni_mb.ini   |    1 +
 doc/guides/cryptodevs/features/qat.ini        |    1 +
 doc/guides/cryptodevs/qat.rst                 |    7 +
 doc/guides/prog_guide/rte_security.rst        |  114 +-
 doc/guides/rel_notes/release_20_08.rst        |   16 +
 doc/guides/tools/cryptoperf.rst               |    5 +
 drivers/common/qat/Makefile                   |    3 +
 .../crypto/aesni_mb/aesni_mb_pmd_private.h    |   19 +-
 drivers/crypto/aesni_mb/meson.build           |    2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c    |  293 +++-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    |  125 ++
 drivers/crypto/qat/meson.build                |    2 +
 drivers/crypto/qat/qat_sym.c                  |   70 +-
 drivers/crypto/qat/qat_sym.h                  |   69 +-
 drivers/crypto/qat/qat_sym_capabilities.h     |   42 +
 drivers/crypto/qat/qat_sym_pmd.c              |   53 +-
 drivers/crypto/qat/qat_sym_pmd.h              |    4 +
 drivers/crypto/qat/qat_sym_session.c          |  146 ++
 drivers/crypto/qat/qat_sym_session.h          |   12 +
 lib/librte_cryptodev/rte_crypto_sym.h         |   14 +
 lib/librte_security/rte_security.c            |    5 +
 lib/librte_security/rte_security.h            |   38 +
 33 files changed, 3328 insertions(+), 33 deletions(-)
 create mode 100644 app/test/test_cryptodev_security_docsis_test_vectors.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 1/8] security: add support for DOCSIS protocol
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-07-01 21:41         ` Akhil Goyal
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 2/8] cryptodev: add a note regarding DOCSIS protocol support David Coyle
                         ` (7 subsequent siblings)
  8 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support for DOCSIS protocol to rte_security library. This support
currently comprises the combination of Crypto and CRC operations.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 lib/librte_security/rte_security.c |  5 ++++
 lib/librte_security/rte_security.h | 38 ++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/lib/librte_security/rte_security.c b/lib/librte_security/rte_security.c
index dc9a3e89c..515c29e04 100644
--- a/lib/librte_security/rte_security.c
+++ b/lib/librte_security/rte_security.c
@@ -173,6 +173,11 @@ rte_security_capability_get(struct rte_security_ctx *instance,
 				if (capability->pdcp.domain ==
 							idx->pdcp.domain)
 					return capability;
+			} else if (idx->protocol ==
+						RTE_SECURITY_PROTOCOL_DOCSIS) {
+				if (capability->docsis.direction ==
+							idx->docsis.direction)
+					return capability;
 			}
 		}
 	}
diff --git a/lib/librte_security/rte_security.h b/lib/librte_security/rte_security.h
index 747830d67..16839e539 100644
--- a/lib/librte_security/rte_security.h
+++ b/lib/librte_security/rte_security.h
@@ -293,6 +293,28 @@ struct rte_security_pdcp_xform {
 	uint32_t hfn_ovrd;
 };
 
+/** DOCSIS direction */
+enum rte_security_docsis_direction {
+	RTE_SECURITY_DOCSIS_UPLINK,
+	/**< Uplink
+	 * - Decryption, followed by CRC Verification
+	 */
+	RTE_SECURITY_DOCSIS_DOWNLINK,
+	/**< Downlink
+	 * - CRC Generation, followed by Encryption
+	 */
+};
+
+/**
+ * DOCSIS security session configuration.
+ *
+ * This structure contains data required to create a DOCSIS security session.
+ */
+struct rte_security_docsis_xform {
+	enum rte_security_docsis_direction direction;
+	/**< DOCSIS direction */
+};
+
 /**
  * Security session action type.
  */
@@ -325,6 +347,8 @@ enum rte_security_session_protocol {
 	/**< MACSec Protocol */
 	RTE_SECURITY_PROTOCOL_PDCP,
 	/**< PDCP Protocol */
+	RTE_SECURITY_PROTOCOL_DOCSIS,
+	/**< DOCSIS Protocol */
 };
 
 /**
@@ -340,6 +364,7 @@ struct rte_security_session_conf {
 		struct rte_security_ipsec_xform ipsec;
 		struct rte_security_macsec_xform macsec;
 		struct rte_security_pdcp_xform pdcp;
+		struct rte_security_docsis_xform docsis;
 	};
 	/**< Configuration parameters for security session */
 	struct rte_crypto_sym_xform *crypto_xform;
@@ -523,6 +548,10 @@ struct rte_security_pdcp_stats {
 	uint64_t reserved;
 };
 
+struct rte_security_docsis_stats {
+	uint64_t reserved;
+};
+
 struct rte_security_stats {
 	enum rte_security_session_protocol protocol;
 	/**< Security protocol to be configured */
@@ -532,6 +561,7 @@ struct rte_security_stats {
 		struct rte_security_macsec_stats macsec;
 		struct rte_security_ipsec_stats ipsec;
 		struct rte_security_pdcp_stats pdcp;
+		struct rte_security_docsis_stats docsis;
 	};
 };
 
@@ -591,6 +621,11 @@ struct rte_security_capability {
 			/**< Capability flags, see RTE_SECURITY_PDCP_* */
 		} pdcp;
 		/**< PDCP capability */
+		struct {
+			enum rte_security_docsis_direction direction;
+			/**< DOCSIS direction */
+		} docsis;
+		/**< DOCSIS capability */
 	};
 
 	const struct rte_cryptodev_capabilities *crypto_capabilities;
@@ -649,6 +684,9 @@ struct rte_security_capability_idx {
 			enum rte_security_pdcp_domain domain;
 			uint32_t capa_flags;
 		} pdcp;
+		struct {
+			enum rte_security_docsis_direction direction;
+		} docsis;
 	};
 };
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 2/8] cryptodev: add a note regarding DOCSIS protocol support
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 1/8] security: " David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-07-01 21:42         ` Akhil Goyal
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 3/8] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
                         ` (6 subsequent siblings)
  8 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add a note to the rte_crypto_sym_op->auth.data fields to state that
for DOCSIS security protocol, these are used to specify the CRC offset
and length.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 lib/librte_cryptodev/rte_crypto_sym.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lib/librte_cryptodev/rte_crypto_sym.h b/lib/librte_cryptodev/rte_crypto_sym.h
index da961a19d..f29c98051 100644
--- a/lib/librte_cryptodev/rte_crypto_sym.h
+++ b/lib/librte_cryptodev/rte_crypto_sym.h
@@ -705,6 +705,14 @@ struct rte_crypto_sym_op {
 					  * For KASUMI @ RTE_CRYPTO_AUTH_KASUMI_F9,
 					  * this offset should be such that
 					  * data to authenticate starts at COUNT.
+					  *
+					  * @note
+					  * For DOCSIS security protocol, this
+					  * offset is the DOCSIS header length
+					  * and, therefore, also the CRC offset
+					  * i.e. the number of bytes into the
+					  * packet at which CRC calculation
+					  * should begin.
 					  */
 					uint32_t length;
 					 /**< The message length, in bytes, of the source
@@ -723,6 +731,12 @@ struct rte_crypto_sym_op {
 					  * the length should include the COUNT,
 					  * FRESH, message, direction bit and padding
 					  * (to be multiple of 8 bits).
+					  *
+					  * @note
+					  * For DOCSIS security protocol, this
+					  * is the CRC length i.e. the number of
+					  * bytes in the packet over which the
+					  * CRC should be calculated
 					  */
 				} data;
 				/**< Data offsets and length for authentication */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 3/8] crypto/aesni_mb: add support for DOCSIS protocol
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 1/8] security: " David Coyle
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 2/8] cryptodev: add a note regarding DOCSIS protocol support David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-07-01 17:04         ` Coyle, David
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 4/8] crypto/qat: " David Coyle
                         ` (5 subsequent siblings)
  8 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support to the AESNI-MB PMD for the DOCSIS protocol, through the
rte_security API. This, therefore, includes adding support for the
rte_security API to this PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 .../crypto/aesni_mb/aesni_mb_pmd_private.h    |  19 +-
 drivers/crypto/aesni_mb/meson.build           |   2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c    | 293 +++++++++++++++++-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    | 125 ++++++++
 4 files changed, 432 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h b/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
index 347b4b7e0..e0c7b4f7c 100644
--- a/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
+++ b/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
@@ -7,6 +7,12 @@
 
 #include <intel-ipsec-mb.h>
 
+#if defined(RTE_LIBRTE_SECURITY) && (IMB_VERSION_NUM) >= IMB_VERSION(0, 54, 0)
+#define AESNI_MB_DOCSIS_SEC_ENABLED 1
+#include <rte_security.h>
+#include <rte_security_driver.h>
+#endif
+
 enum aesni_mb_vector_mode {
 	RTE_AESNI_MB_NOT_SUPPORTED = 0,
 	RTE_AESNI_MB_SSE,
@@ -272,8 +278,19 @@ aesni_mb_set_session_parameters(const MB_MGR *mb_mgr,
 		struct aesni_mb_session *sess,
 		const struct rte_crypto_sym_xform *xform);
 
-/** device specific operations function pointer structure */
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+extern int
+aesni_mb_set_docsis_sec_session_parameters(
+		__rte_unused struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf,
+		void *sess);
+#endif
+
+/** device specific operations function pointer structures */
 extern struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops;
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+extern struct rte_security_ops *rte_aesni_mb_pmd_sec_ops;
+#endif
 
 extern uint32_t
 aesni_mb_cpu_crypto_process_bulk(struct rte_cryptodev *dev,
diff --git a/drivers/crypto/aesni_mb/meson.build b/drivers/crypto/aesni_mb/meson.build
index e557e0103..419b4743f 100644
--- a/drivers/crypto/aesni_mb/meson.build
+++ b/drivers/crypto/aesni_mb/meson.build
@@ -22,4 +22,4 @@ else
 endif
 
 sources = files('rte_aesni_mb_pmd.c', 'rte_aesni_mb_pmd_ops.c')
-deps += ['bus_vdev']
+deps += ['bus_vdev', 'net', 'security']
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 2d688f4d3..4b25c5e23 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -12,6 +12,7 @@
 #include <rte_malloc.h>
 #include <rte_cpuflags.h>
 #include <rte_per_lcore.h>
+#include <rte_ether.h>
 
 #include "aesni_mb_pmd_private.h"
 
@@ -720,6 +721,134 @@ aesni_mb_set_session_parameters(const MB_MGR *mb_mgr,
 	return 0;
 }
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/** Check DOCSIS security session configuration is valid */
+static int
+check_docsis_sec_session(struct rte_security_session_conf *conf)
+{
+	struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
+	struct rte_security_docsis_xform *docsis = &conf->docsis;
+
+	/* Downlink: CRC generate -> Cipher encrypt */
+	if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type ==	RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length == IMB_KEY_AES_128_BYTES ||
+		     crypto_sym->cipher.key.length == IMB_KEY_AES_256_BYTES) &&
+		    crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	/* Uplink: Cipher decrypt -> CRC verify */
+	} else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length == IMB_KEY_AES_128_BYTES ||
+		     crypto_sym->cipher.key.length == IMB_KEY_AES_256_BYTES) &&
+		    crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/** Set DOCSIS security session auth (CRC) parameters */
+static int
+aesni_mb_set_docsis_sec_session_auth_parameters(struct aesni_mb_session *sess,
+		struct rte_security_docsis_xform *xform)
+{
+	if (xform == NULL) {
+		AESNI_MB_LOG(ERR, "Invalid DOCSIS xform");
+		return -EINVAL;
+	}
+
+	/* Select CRC generate/verify */
+	if (xform->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+		sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY;
+	} else if (xform->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+		sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE;
+	} else {
+		AESNI_MB_LOG(ERR, "Unsupported DOCSIS direction");
+		return -ENOTSUP;
+	}
+
+	sess->auth.req_digest_len = RTE_ETHER_CRC_LEN;
+	sess->auth.gen_digest_len = RTE_ETHER_CRC_LEN;
+
+	return 0;
+}
+
+/**
+ * Parse DOCSIS security session configuration and set private session
+ * parameters
+ */
+int
+aesni_mb_set_docsis_sec_session_parameters(
+		__rte_unused struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf,
+		void *sess)
+{
+	struct rte_security_docsis_xform *docsis_xform;
+	struct rte_crypto_sym_xform *cipher_xform;
+	struct aesni_mb_session *aesni_sess = sess;
+	struct aesni_mb_private *internals = dev->data->dev_private;
+	int ret;
+
+	ret = check_docsis_sec_session(conf);
+	if (ret) {
+		AESNI_MB_LOG(ERR, "Unsupported DOCSIS security configuration");
+		return ret;
+	}
+
+	switch (conf->docsis.direction) {
+	case RTE_SECURITY_DOCSIS_UPLINK:
+		aesni_sess->chain_order = IMB_ORDER_CIPHER_HASH;
+		docsis_xform = &conf->docsis;
+		cipher_xform = conf->crypto_xform;
+		break;
+	case RTE_SECURITY_DOCSIS_DOWNLINK:
+		aesni_sess->chain_order = IMB_ORDER_HASH_CIPHER;
+		cipher_xform = conf->crypto_xform;
+		docsis_xform = &conf->docsis;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Default IV length = 0 */
+	aesni_sess->iv.length = 0;
+
+	ret = aesni_mb_set_docsis_sec_session_auth_parameters(aesni_sess,
+			docsis_xform);
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Invalid/unsupported DOCSIS parameters");
+		return -EINVAL;
+	}
+
+	ret = aesni_mb_set_session_cipher_parameters(internals->mb_mgr,
+			aesni_sess, cipher_xform);
+
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Invalid/unsupported cipher parameters");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
 /**
  * burst enqueue, place crypto operations on ingress queue for processing.
  *
@@ -758,6 +887,13 @@ get_session(struct aesni_mb_qp *qp, struct rte_crypto_op *op)
 					get_sym_session_private_data(
 					op->sym->session,
 					cryptodev_driver_id);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	} else if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+		if (likely(op->sym->sec_session != NULL))
+			sess = (struct aesni_mb_session *)
+					get_sec_session_private_data(
+						op->sym->sec_session);
+#endif
 	} else {
 		void *_sess = rte_cryptodev_sym_session_create(qp->sess_mp);
 		void *_sess_private_data = NULL;
@@ -1158,6 +1294,106 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
 	return 0;
 }
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/**
+ * Process a crypto operation containing a security op and complete a
+ * JOB_AES_HMAC job structure for submission to the multi buffer library for
+ * processing.
+ */
+static inline int
+set_sec_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
+		struct rte_crypto_op *op, uint8_t *digest_idx)
+{
+	struct rte_mbuf *m_src, *m_dst;
+	struct rte_crypto_sym_op *sym;
+	struct aesni_mb_session *session;
+
+	session = get_session(qp, op);
+	if (unlikely(session == NULL)) {
+		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
+		return -1;
+	}
+
+	/* Only DOCSIS protocol operations supported now */
+	if (session->cipher.mode != IMB_CIPHER_DOCSIS_SEC_BPI ||
+			session->auth.algo != IMB_AUTH_DOCSIS_CRC32) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return -1;
+	}
+
+	sym = op->sym;
+	m_src = sym->m_src;
+
+	if (likely(sym->m_dst == NULL || sym->m_dst == m_src)) {
+		/* in-place operation */
+		m_dst = m_src;
+	} else {
+		/* out-of-place operation not supported */
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return -ENOTSUP;
+	}
+
+	/* Set crypto operation */
+	job->chain_order = session->chain_order;
+
+	/* Set cipher parameters */
+	job->cipher_direction = session->cipher.direction;
+	job->cipher_mode = session->cipher.mode;
+
+	job->aes_key_len_in_bytes = session->cipher.key_length_in_bytes;
+	job->aes_enc_key_expanded = session->cipher.expanded_aes_keys.encode;
+	job->aes_dec_key_expanded = session->cipher.expanded_aes_keys.decode;
+
+	/* Set IV parameters */
+	job->iv_len_in_bytes = session->iv.length;
+	job->iv = (uint8_t *)op + session->iv.offset;
+
+	/* Set authentication parameters */
+	job->hash_alg = session->auth.algo;
+
+	/* Set digest output location */
+	job->auth_tag_output = qp->temp_digests[*digest_idx];
+	*digest_idx = (*digest_idx + 1) % MAX_JOBS;
+
+	/* Set digest length */
+	job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
+
+	/* Set data parameters */
+	job->src = rte_pktmbuf_mtod(m_src, uint8_t *);
+	job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *,
+						sym->cipher.data.offset);
+
+	job->cipher_start_src_offset_in_bytes = sym->cipher.data.offset;
+	job->msg_len_to_cipher_in_bytes = sym->cipher.data.length;
+
+	job->hash_start_src_offset_in_bytes = sym->auth.data.offset;
+	job->msg_len_to_hash_in_bytes = sym->auth.data.length;
+
+	job->user_data = op;
+
+	return 0;
+}
+
+static inline void
+verify_docsis_sec_crc(JOB_AES_HMAC *job, uint8_t *status)
+{
+	uint16_t crc_offset;
+	uint8_t *crc;
+
+	if (!job->msg_len_to_hash_in_bytes)
+		return;
+
+	crc_offset = job->hash_start_src_offset_in_bytes +
+			job->msg_len_to_hash_in_bytes -
+			job->cipher_start_src_offset_in_bytes;
+	crc = job->dst + crc_offset;
+
+	/* Verify CRC (at the end of the message) */
+	if (memcmp(job->auth_tag_output, crc, RTE_ETHER_CRC_LEN) != 0)
+		*status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+}
+#endif
+
 static inline void
 verify_digest(JOB_AES_HMAC *job, void *digest, uint16_t len, uint8_t *status)
 {
@@ -1196,9 +1432,25 @@ static inline struct rte_crypto_op *
 post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)
 {
 	struct rte_crypto_op *op = (struct rte_crypto_op *)job->user_data;
-	struct aesni_mb_session *sess = get_sym_session_private_data(
-							op->sym->session,
-							cryptodev_driver_id);
+	struct aesni_mb_session *sess = NULL;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	uint8_t is_docsis_sec = 0;
+
+	if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+		/*
+		 * Assuming at this point that if it's a security type op, that
+		 * this is for DOCSIS
+		 */
+		is_docsis_sec = 1;
+		sess = get_sec_session_private_data(op->sym->sec_session);
+	} else
+#endif
+	{
+		sess = get_sym_session_private_data(op->sym->session,
+						cryptodev_driver_id);
+	}
+
 	if (unlikely(sess == NULL)) {
 		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
 		return op;
@@ -1220,6 +1472,11 @@ post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)
 						op->sym->aead.digest.data,
 						sess->auth.req_digest_len,
 						&op->status);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+				else if (is_docsis_sec)
+					verify_docsis_sec_crc(job,
+						&op->status);
+#endif
 				else
 					verify_digest(job,
 						op->sym->auth.digest.data,
@@ -1382,7 +1639,14 @@ aesni_mb_pmd_dequeue_burst(void *queue_pair, struct rte_crypto_op **ops,
 		if (retval < 0)
 			break;
 
-		retval = set_mb_job_params(job, qp, op, &digest_idx);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+		if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION)
+			retval = set_sec_mb_job_params(job, qp, op,
+						&digest_idx);
+		else
+#endif
+			retval = set_mb_job_params(job, qp, op, &digest_idx);
+
 		if (unlikely(retval != 0)) {
 			qp->stats.dequeue_err_count++;
 			set_job_null_op(job, op);
@@ -1619,6 +1883,9 @@ cryptodev_aesni_mb_create(const char *name,
 	struct aesni_mb_private *internals;
 	enum aesni_mb_vector_mode vector_mode;
 	MB_MGR *mb_mgr;
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	struct rte_security_ctx *security_instance;
+#endif
 
 	dev = rte_cryptodev_pmd_create(name, &vdev->device, init_params);
 	if (dev == NULL) {
@@ -1647,7 +1914,23 @@ cryptodev_aesni_mb_create(const char *name,
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_SESSIONLESS;
+			RTE_CRYPTODEV_FF_SYM_SESSIONLESS
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+			| RTE_CRYPTODEV_FF_SECURITY
+#endif
+			;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	security_instance = rte_malloc("aesni_mb_sec",
+				sizeof(struct rte_security_ctx), 0);
+	if (security_instance == NULL)
+		AESNI_MB_LOG(ERR, "rte_security_ctx memory alloc failed\n");
+
+	security_instance->device = (void *)dev;
+	security_instance->ops = rte_aesni_mb_pmd_sec_ops;
+	security_instance->sess_cnt = 0;
+	dev->security_ctx = security_instance;
+#endif
 
 	/* Check CPU for support for AES instruction set */
 	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AES))
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
index 8c5e0cd92..ed93daec7 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -7,6 +7,7 @@
 #include <rte_string_fns.h>
 #include <rte_common.h>
 #include <rte_malloc.h>
+#include <rte_ether.h>
 #include <rte_cryptodev_pmd.h>
 
 #include "aesni_mb_pmd_private.h"
@@ -499,6 +500,55 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+static const struct rte_cryptodev_capabilities
+					aesni_mb_pmd_security_crypto_cap[] = {
+	{	/* AES DOCSIS BPI */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		{.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			{.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 16
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}, }
+		}, }
+	},
+
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability aesni_mb_pmd_security_cap[] = {
+	{	/* DOCSIS Uplink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_UPLINK
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{	/* DOCSIS Downlink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{
+		.action = RTE_SECURITY_ACTION_TYPE_NONE
+	}
+};
+#endif
 
 /** Configure device */
 static int
@@ -810,3 +860,78 @@ struct rte_cryptodev_ops aesni_mb_pmd_ops = {
 };
 
 struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops = &aesni_mb_pmd_ops;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/**
+ * Configure a aesni multi-buffer session from a security session
+ * configuration
+ */
+static int
+aesni_mb_pmd_sec_sess_create(void *dev, struct rte_security_session_conf *conf,
+		struct rte_security_session *sess,
+		struct rte_mempool *mempool)
+{
+	void *sess_private_data;
+	struct rte_cryptodev *cdev = (struct rte_cryptodev *)dev;
+	int ret;
+
+	if (rte_mempool_get(mempool, &sess_private_data)) {
+		AESNI_MB_LOG(ERR, "Couldn't get object from session mempool");
+		return -ENOMEM;
+	}
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_DOCSIS) {
+		AESNI_MB_LOG(ERR, "Invalid security protocol");
+		return -EINVAL;
+	}
+
+	ret = aesni_mb_set_docsis_sec_session_parameters(cdev, conf,
+			sess_private_data);
+
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Failed to configure session parameters");
+
+		/* Return session to mempool */
+		rte_mempool_put(mempool, sess_private_data);
+		return ret;
+	}
+
+	set_sec_session_private_data(sess, sess_private_data);
+
+	return ret;
+}
+
+/** Clear the memory of session so it doesn't leave key material behind */
+static int
+aesni_mb_pmd_sec_sess_destroy(void *dev __rte_unused,
+		struct rte_security_session *sess)
+{
+	void *sess_priv = get_sec_session_private_data(sess);
+
+	if (sess_priv) {
+		struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
+		memset(sess, 0, sizeof(struct aesni_mb_session));
+		set_sec_session_private_data(sess, NULL);
+		rte_mempool_put(sess_mp, sess_priv);
+	}
+	return 0;
+}
+
+/** Get security capabilities for aesni multi-buffer */
+static const struct rte_security_capability *
+aesni_mb_pmd_sec_capa_get(void *device __rte_unused)
+{
+	return aesni_mb_pmd_security_cap;
+}
+
+static struct rte_security_ops aesni_mb_pmd_sec_ops = {
+		.session_create = aesni_mb_pmd_sec_sess_create,
+		.session_update = NULL,
+		.session_stats_get = NULL,
+		.session_destroy = aesni_mb_pmd_sec_sess_destroy,
+		.set_pkt_metadata = NULL,
+		.capabilities_get = aesni_mb_pmd_sec_capa_get
+};
+
+struct rte_security_ops *rte_aesni_mb_pmd_sec_ops = &aesni_mb_pmd_sec_ops;
+#endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 4/8] crypto/qat: add support for DOCSIS protocol
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
                         ` (2 preceding siblings ...)
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 3/8] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-07-01 17:04         ` Coyle, David
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 5/8] test/crypto: add DOCSIS security test cases David Coyle
                         ` (4 subsequent siblings)
  8 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support to the QAT SYM PMD for the DOCSIS protocol, through the
rte_security API. This, therefore, includes adding support for the
rte_security API to this PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 drivers/common/qat/Makefile               |   3 +
 drivers/crypto/qat/meson.build            |   2 +
 drivers/crypto/qat/qat_sym.c              |  70 ++++++++++-
 drivers/crypto/qat/qat_sym.h              |  69 ++++++++--
 drivers/crypto/qat/qat_sym_capabilities.h |  42 +++++++
 drivers/crypto/qat/qat_sym_pmd.c          |  53 +++++++-
 drivers/crypto/qat/qat_sym_pmd.h          |   4 +
 drivers/crypto/qat/qat_sym_session.c      | 146 ++++++++++++++++++++++
 drivers/crypto/qat/qat_sym_session.h      |  12 ++
 9 files changed, 389 insertions(+), 12 deletions(-)

diff --git a/drivers/common/qat/Makefile b/drivers/common/qat/Makefile
index 28bd5668f..85d420709 100644
--- a/drivers/common/qat/Makefile
+++ b/drivers/common/qat/Makefile
@@ -35,6 +35,9 @@ endif
 ifeq ($(CONFIG_RTE_LIBRTE_PMD_QAT_SYM),y)
 	LDLIBS += -lrte_cryptodev
 	LDLIBS += -lcrypto
+ifeq ($(CONFIG_RTE_LIBRTE_SECURITY),y)
+	LDLIBS += -lrte_net
+endif
 	CFLAGS += -DBUILD_QAT_SYM
 	SRCS-y += qat_sym.c
 	SRCS-y += qat_sym_session.c
diff --git a/drivers/crypto/qat/meson.build b/drivers/crypto/qat/meson.build
index fc65923a7..a225f374a 100644
--- a/drivers/crypto/qat/meson.build
+++ b/drivers/crypto/qat/meson.build
@@ -8,6 +8,8 @@ reason = '' # sentinal value to suppress printout
 dep = dependency('libcrypto', required: false)
 qat_includes += include_directories('.')
 qat_deps += 'cryptodev'
+qat_deps += 'net'
+qat_deps += 'security'
 if dep.found()
 	# Add our sources files to the list
 	qat_sources += files('qat_sym_pmd.c',
diff --git a/drivers/crypto/qat/qat_sym.c b/drivers/crypto/qat/qat_sym.c
index 25b6dd5f4..cc4d2c2cd 100644
--- a/drivers/crypto/qat/qat_sym.c
+++ b/drivers/crypto/qat/qat_sym.c
@@ -9,6 +9,9 @@
 #include <rte_crypto_sym.h>
 #include <rte_bus_pci.h>
 #include <rte_byteorder.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_net_crc.h>
+#endif
 
 #include "qat_sym.h"
 
@@ -99,6 +102,30 @@ qat_bpicipher_preprocess(struct qat_sym_session *ctx,
 	return sym_op->cipher.data.length - last_block_len;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
+static inline void
+qat_crc_generate(struct qat_sym_session *ctx,
+			struct rte_crypto_op *op)
+{
+	struct rte_crypto_sym_op *sym_op = op->sym;
+	uint8_t *crc_data;
+	uint32_t *crc;
+	uint32_t crc_length;
+
+	if (ctx->qat_dir == ICP_QAT_HW_CIPHER_ENCRYPT &&
+			sym_op->auth.data.length != 0) {
+
+		crc_length = sym_op->auth.data.length;
+		crc_data = (uint8_t *) rte_pktmbuf_mtod_offset(
+				sym_op->m_src, uint8_t *,
+				sym_op->auth.data.offset);
+		crc = (uint32_t *)(crc_data + crc_length);
+		*crc = rte_net_crc_calc(crc_data, crc_length,
+				RTE_NET_CRC32_ETH);
+	}
+}
+#endif
+
 static inline void
 set_cipher_iv(uint16_t iv_length, uint16_t iv_offset,
 		struct icp_qat_fw_la_cipher_req_params *cipher_param,
@@ -161,6 +188,7 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 	uint64_t auth_data_end = 0;
 	uint8_t do_sgl = 0;
 	uint8_t in_place = 1;
+	uint8_t is_docsis_sec = 0;
 	int alignment_adjustment = 0;
 	struct rte_crypto_op *op = (struct rte_crypto_op *)in_op;
 	struct qat_sym_op_cookie *cookie =
@@ -177,11 +205,23 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 		QAT_DP_LOG(ERR, "QAT PMD only supports session oriented"
 				" requests, op (%p) is sessionless.", op);
 		return -EINVAL;
+	} else if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
+		ctx = (struct qat_sym_session *)get_sym_session_private_data(
+				op->sym->session, cryptodev_qat_driver_id);
+#ifdef RTE_LIBRTE_SECURITY
+	} else {
+		ctx = (struct qat_sym_session *)get_sec_session_private_data(
+				op->sym->sec_session);
+		if (ctx && ctx->bpi_ctx == NULL) {
+			QAT_DP_LOG(ERR, "QAT PMD only supports security"
+					" operation requests for DOCSIS, op"
+					" (%p) is not for DOCSIS.", op);
+			return -EINVAL;
+		}
+		is_docsis_sec = 1;
+#endif
 	}
 
-	ctx = (struct qat_sym_session *)get_sym_session_private_data(
-			op->sym->session, cryptodev_qat_driver_id);
-
 	if (unlikely(ctx == NULL)) {
 		QAT_DP_LOG(ERR, "Session was not created for this device");
 		return -EINVAL;
@@ -242,7 +282,29 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 			cipher_ofs = op->sym->cipher.data.offset >> 3;
 
 		} else if (ctx->bpi_ctx) {
-			/* DOCSIS - only send complete blocks to device
+			/* DOCSIS processing */
+#ifdef RTE_LIBRTE_SECURITY
+			if (is_docsis_sec) {
+				/* Check for OOP */
+				if (unlikely((op->sym->m_dst != NULL) &&
+						(op->sym->m_dst !=
+						op->sym->m_src))) {
+					QAT_DP_LOG(ERR,
+						"OOP not supported for DOCSIS "
+						"security");
+					op->status =
+					RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+					return -EINVAL;
+				}
+
+				/* Calculate CRC */
+				qat_crc_generate(ctx, op);
+			}
+#else
+			RTE_SET_USED(is_docsis_sec);
+#endif
+
+			/* Only send complete blocks to device.
 			 * Process any partial block using CFB mode.
 			 * Even if 0 complete blocks, still send this to device
 			 * to get into rx queue for post-process and dequeuing
diff --git a/drivers/crypto/qat/qat_sym.h b/drivers/crypto/qat/qat_sym.h
index bc6426c32..712a62856 100644
--- a/drivers/crypto/qat/qat_sym.h
+++ b/drivers/crypto/qat/qat_sym.h
@@ -6,6 +6,9 @@
 #define _QAT_SYM_H_
 
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_net_crc.h>
+#endif
 
 #ifdef BUILD_QAT_SYM
 #include <openssl/evp.h>
@@ -132,14 +135,45 @@ qat_bpicipher_postprocess(struct qat_sym_session *ctx,
 	return sym_op->cipher.data.length - last_block_len;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
 static inline void
-qat_sym_process_response(void **op, uint8_t *resp)
+qat_crc_verify(struct qat_sym_session *ctx, struct rte_crypto_op *op)
 {
+	struct rte_crypto_sym_op *sym_op = op->sym;
+	uint32_t crc = 0;
+	uint8_t *crc_data;
+	uint32_t crc_offset, crc_length;
+
+	if (ctx->qat_dir == ICP_QAT_HW_CIPHER_DECRYPT &&
+			sym_op->auth.data.length != 0) {
+
+		crc_offset = sym_op->auth.data.offset;
+		crc_length = sym_op->auth.data.length;
+		crc_data = (uint8_t *) rte_pktmbuf_mtod_offset(
+				sym_op->m_src, uint8_t *, crc_offset);
 
+		if (unlikely((sym_op->m_dst != NULL)
+				&& (sym_op->m_dst != sym_op->m_src)))
+			/* out-of-place operation (OOP) */
+			crc_data = (uint8_t *) rte_pktmbuf_mtod_offset(
+					sym_op->m_dst, uint8_t *, crc_offset);
+
+		crc = rte_net_crc_calc(crc_data, crc_length, RTE_NET_CRC32_ETH);
+
+		if (crc != *(uint32_t *)(crc_data + crc_length))
+			op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+	}
+}
+#endif
+
+static inline void
+qat_sym_process_response(void **op, uint8_t *resp)
+{
 	struct icp_qat_fw_comn_resp *resp_msg =
 			(struct icp_qat_fw_comn_resp *)resp;
 	struct rte_crypto_op *rx_op = (struct rte_crypto_op *)(uintptr_t)
 			(resp_msg->opaque_data);
+	struct qat_sym_session *sess;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	QAT_DP_HEXDUMP_LOG(DEBUG, "qat_response:", (uint8_t *)resp_msg,
@@ -152,15 +186,36 @@ qat_sym_process_response(void **op, uint8_t *resp)
 
 		rx_op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
 	} else {
-		struct qat_sym_session *sess = (struct qat_sym_session *)
-						get_sym_session_private_data(
-						rx_op->sym->session,
-						cryptodev_qat_driver_id);
+#ifdef RTE_LIBRTE_SECURITY
+		uint8_t is_docsis_sec = 0;
+
+		if (rx_op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+			/*
+			 * Assuming at this point that if it's a security
+			 * op, that this is for DOCSIS
+			 */
+			sess = (struct qat_sym_session *)
+					get_sec_session_private_data(
+					rx_op->sym->sec_session);
+			is_docsis_sec = 1;
+		} else
+#endif
+		{
+			sess = (struct qat_sym_session *)
+					get_sym_session_private_data(
+					rx_op->sym->session,
+					cryptodev_qat_driver_id);
+		}
 
+		rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
 
-		if (sess->bpi_ctx)
+		if (sess->bpi_ctx) {
 			qat_bpicipher_postprocess(sess, rx_op);
-		rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+#ifdef RTE_LIBRTE_SECURITY
+			if (is_docsis_sec)
+				qat_crc_verify(sess, rx_op);
+#endif
+		}
 	}
 	*op = (void *)rx_op;
 }
diff --git a/drivers/crypto/qat/qat_sym_capabilities.h b/drivers/crypto/qat/qat_sym_capabilities.h
index ff691ce35..7b8b13b4f 100644
--- a/drivers/crypto/qat/qat_sym_capabilities.h
+++ b/drivers/crypto/qat/qat_sym_capabilities.h
@@ -699,4 +699,46 @@
 		}, }							\
 	}
 
+#ifdef RTE_LIBRTE_SECURITY
+#define QAT_SECURITY_SYM_CAPABILITIES					\
+	{	/* AES DOCSIS BPI */					\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,	\
+			{.cipher = {					\
+				.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,\
+				.block_size = 16,			\
+				.key_size = {				\
+					.min = 16,			\
+					.max = 32,			\
+					.increment = 16			\
+				},					\
+				.iv_size = {				\
+					.min = 16,			\
+					.max = 16,			\
+					.increment = 0			\
+				}					\
+			}, }						\
+		}, }							\
+	}
+
+#define QAT_SECURITY_CAPABILITIES(sym)					\
+	[0] = {	/* DOCSIS Uplink */					\
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,	\
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,		\
+		.docsis = {						\
+			.direction = RTE_SECURITY_DOCSIS_UPLINK		\
+		},							\
+		.crypto_capabilities = (sym)				\
+	},								\
+	[1] = {	/* DOCSIS Downlink */					\
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,	\
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,		\
+		.docsis = {						\
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK	\
+		},							\
+		.crypto_capabilities = (sym)				\
+	}
+#endif
+
 #endif /* _QAT_SYM_CAPABILITIES_H_ */
diff --git a/drivers/crypto/qat/qat_sym_pmd.c b/drivers/crypto/qat/qat_sym_pmd.c
index e887c880f..711d1585f 100644
--- a/drivers/crypto/qat/qat_sym_pmd.c
+++ b/drivers/crypto/qat/qat_sym_pmd.c
@@ -8,6 +8,9 @@
 #include <rte_malloc.h>
 #include <rte_pci.h>
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security_driver.h>
+#endif
 
 #include "qat_logs.h"
 #include "qat_sym.h"
@@ -29,6 +32,21 @@ static const struct rte_cryptodev_capabilities qat_gen2_sym_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+#ifdef RTE_LIBRTE_SECURITY
+static const struct rte_cryptodev_capabilities
+					qat_security_sym_capabilities[] = {
+	QAT_SECURITY_SYM_CAPABILITIES,
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability qat_security_capabilities[] = {
+	QAT_SECURITY_CAPABILITIES(qat_security_sym_capabilities),
+	{
+		.action = RTE_SECURITY_ACTION_TYPE_NONE
+	}
+};
+#endif
+
 static int qat_sym_qp_release(struct rte_cryptodev *dev,
 	uint16_t queue_pair_id);
 
@@ -237,6 +255,23 @@ static struct rte_cryptodev_ops crypto_qat_ops = {
 		.sym_session_clear	= qat_sym_session_clear
 };
 
+#ifdef RTE_LIBRTE_SECURITY
+static const struct rte_security_capability *
+qat_security_cap_get(void *device __rte_unused)
+{
+	return qat_security_capabilities;
+}
+
+static struct rte_security_ops security_qat_ops = {
+	.session_create = qat_security_session_create,
+	.session_update = NULL,
+	.session_stats_get = NULL,
+	.session_destroy = qat_security_session_destroy,
+	.set_pkt_metadata = NULL,
+	.capabilities_get = qat_security_cap_get
+};
+#endif
+
 static uint16_t
 qat_sym_pmd_enqueue_op_burst(void *qp, struct rte_crypto_op **ops,
 		uint16_t nb_ops)
@@ -276,6 +311,9 @@ qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
 	struct rte_cryptodev *cryptodev;
 	struct qat_sym_dev_private *internals;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_ctx *security_instance;
+#endif
 
 	snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN, "%s_%s",
 			qat_pci_dev->name, "sym");
@@ -308,7 +346,20 @@ qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
 			RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
-			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED;
+			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED |
+			RTE_CRYPTODEV_FF_SECURITY;
+
+#ifdef RTE_LIBRTE_SECURITY
+	security_instance = rte_malloc("qat_sec",
+				sizeof(struct rte_security_ctx), 0);
+	if (security_instance == NULL)
+		QAT_LOG(ERR, "rte_security_ctx memory alloc failed\n");
+
+	security_instance->device = (void *)cryptodev;
+	security_instance->ops = &security_qat_ops;
+	security_instance->sess_cnt = 0;
+	cryptodev->security_ctx = security_instance;
+#endif
 
 	internals = cryptodev->data->dev_private;
 	internals->qat_dev = qat_pci_dev;
diff --git a/drivers/crypto/qat/qat_sym_pmd.h b/drivers/crypto/qat/qat_sym_pmd.h
index a5a31e512..c625fef4a 100644
--- a/drivers/crypto/qat/qat_sym_pmd.h
+++ b/drivers/crypto/qat/qat_sym_pmd.h
@@ -7,7 +7,11 @@
 
 #ifdef BUILD_QAT_SYM
 
+#include <rte_ether.h>
 #include <rte_cryptodev.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_sym_capabilities.h"
 #include "qat_device.h"
diff --git a/drivers/crypto/qat/qat_sym_session.c b/drivers/crypto/qat/qat_sym_session.c
index 58bdbd343..82ba2b47c 100644
--- a/drivers/crypto/qat/qat_sym_session.c
+++ b/drivers/crypto/qat/qat_sym_session.c
@@ -14,6 +14,9 @@
 #include <rte_log.h>
 #include <rte_malloc.h>
 #include <rte_crypto_sym.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_logs.h"
 #include "qat_sym_session.h"
@@ -2092,3 +2095,146 @@ int qat_sym_validate_zuc_key(int key_len, enum icp_qat_hw_cipher_algo *alg)
 	}
 	return 0;
 }
+
+#ifdef RTE_LIBRTE_SECURITY
+static int
+qat_sec_session_check_docsis(struct rte_security_session_conf *conf)
+{
+	struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
+	struct rte_security_docsis_xform *docsis = &conf->docsis;
+
+	/* CRC generate -> Cipher encrypt */
+	if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_128_KEY_SZ ||
+		     crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_256_KEY_SZ) &&
+		    crypto_sym->cipher.iv.length == ICP_QAT_HW_AES_BLK_SZ &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	/* Cipher decrypt -> CRC verify */
+	} else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_128_KEY_SZ ||
+		     crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_256_KEY_SZ) &&
+		    crypto_sym->cipher.iv.length == ICP_QAT_HW_AES_BLK_SZ &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int
+qat_sec_session_set_docsis_parameters(struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf, void *session_private)
+{
+	int ret;
+	int qat_cmd_id;
+	struct rte_crypto_sym_xform *xform = NULL;
+	struct qat_sym_session *session = session_private;
+
+	ret = qat_sec_session_check_docsis(conf);
+	if (ret) {
+		QAT_LOG(ERR, "Unsupported DOCSIS security configuration");
+		return ret;
+	}
+
+	xform = conf->crypto_xform;
+
+	/* Set context descriptor physical address */
+	session->cd_paddr = rte_mempool_virt2iova(session) +
+			offsetof(struct qat_sym_session, cd);
+
+	session->min_qat_dev_gen = QAT_GEN1;
+
+	/* Get requested QAT command id */
+	qat_cmd_id = qat_get_cmd_id(xform);
+	if (qat_cmd_id < 0 || qat_cmd_id >= ICP_QAT_FW_LA_CMD_DELIMITER) {
+		QAT_LOG(ERR, "Unsupported xform chain requested");
+		return -ENOTSUP;
+	}
+	session->qat_cmd = (enum icp_qat_fw_la_cmd_id)qat_cmd_id;
+	switch (session->qat_cmd) {
+	case ICP_QAT_FW_LA_CMD_CIPHER:
+		ret = qat_sym_session_configure_cipher(dev, xform, session);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+	QAT_LOG(ERR, "Unsupported Service %u",
+		session->qat_cmd);
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+int
+qat_security_session_create(void *dev,
+				struct rte_security_session_conf *conf,
+				struct rte_security_session *sess,
+				struct rte_mempool *mempool)
+{
+	void *sess_private_data;
+	struct rte_cryptodev *cdev = (struct rte_cryptodev *)dev;
+	int ret;
+
+	if (rte_mempool_get(mempool, &sess_private_data)) {
+		QAT_LOG(ERR, "Couldn't get object from session mempool");
+		return -ENOMEM;
+	}
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_DOCSIS) {
+		QAT_LOG(ERR, "Invalid security protocol");
+		return -EINVAL;
+	}
+
+	ret = qat_sec_session_set_docsis_parameters(cdev, conf,
+			sess_private_data);
+	if (ret != 0) {
+		QAT_LOG(ERR, "Failed to configure session parameters");
+		/* Return session to mempool */
+		rte_mempool_put(mempool, sess_private_data);
+		return ret;
+	}
+
+	set_sec_session_private_data(sess, sess_private_data);
+
+	return ret;
+}
+
+int
+qat_security_session_destroy(void *dev __rte_unused,
+				 struct rte_security_session *sess)
+{
+	void *sess_priv = get_sec_session_private_data(sess);
+	struct qat_sym_session *s = (struct qat_sym_session *)sess_priv;
+
+	if (sess_priv) {
+		if (s->bpi_ctx)
+			bpi_cipher_ctx_free(s->bpi_ctx);
+		memset(s, 0, qat_sym_session_get_private_size(dev));
+		struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
+
+		set_sec_session_private_data(sess, NULL);
+		rte_mempool_put(sess_mp, sess_priv);
+	}
+	return 0;
+}
+#endif
diff --git a/drivers/crypto/qat/qat_sym_session.h b/drivers/crypto/qat/qat_sym_session.h
index e6538f627..721f8fcd3 100644
--- a/drivers/crypto/qat/qat_sym_session.h
+++ b/drivers/crypto/qat/qat_sym_session.h
@@ -6,6 +6,9 @@
 
 #include <rte_crypto.h>
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_common.h"
 #include "icp_qat_hw.h"
@@ -156,4 +159,13 @@ qat_cipher_get_block_size(enum icp_qat_hw_cipher_algo qat_cipher_alg);
 int
 qat_sym_validate_zuc_key(int key_len, enum icp_qat_hw_cipher_algo *alg);
 
+#ifdef RTE_LIBRTE_SECURITY
+int
+qat_security_session_create(void *dev, struct rte_security_session_conf *conf,
+		struct rte_security_session *sess, struct rte_mempool *mempool);
+int
+qat_security_session_destroy(void *dev __rte_unused,
+		struct rte_security_session *sess);
+#endif
+
 #endif /* _QAT_SYM_SESSION_H_ */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 5/8] test/crypto: add DOCSIS security test cases
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
                         ` (3 preceding siblings ...)
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 4/8] crypto/qat: " David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-07-01 21:43         ` Akhil Goyal
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 6/8] test/security: add DOCSIS capability check tests David Coyle
                         ` (3 subsequent siblings)
  8 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add uplink and downlink DOCSIS unit test cases and vectors, to test
the combined DOCSIS Crypto-CRC support that has been added to the
rte_security library.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 app/test/test_cryptodev.c                     |  513 ++++++
 ...t_cryptodev_security_docsis_test_vectors.h | 1544 +++++++++++++++++
 2 files changed, 2057 insertions(+)
 create mode 100644 app/test/test_cryptodev_security_docsis_test_vectors.h

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 8f631468b..d11f60f3f 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -11,6 +11,7 @@
 #include <rte_memcpy.h>
 #include <rte_pause.h>
 #include <rte_bus_vdev.h>
+#include <rte_ether.h>
 
 #include <rte_crypto.h>
 #include <rte_cryptodev.h>
@@ -42,6 +43,7 @@
 #ifdef RTE_LIBRTE_SECURITY
 #include "test_cryptodev_security_pdcp_test_vectors.h"
 #include "test_cryptodev_security_pdcp_test_func.h"
+#include "test_cryptodev_security_docsis_test_vectors.h"
 #endif
 
 #define VDEV_ARGS_SIZE 100
@@ -72,6 +74,9 @@ struct crypto_unittest_params {
 	struct rte_crypto_sym_xform cipher_xform;
 	struct rte_crypto_sym_xform auth_xform;
 	struct rte_crypto_sym_xform aead_xform;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_docsis_xform docsis_xform;
+#endif
 
 	union {
 		struct rte_cryptodev_sym_session *sess;
@@ -7067,6 +7072,34 @@ test_authenticated_encryption(const struct aead_test_data *tdata)
 }
 
 #ifdef RTE_LIBRTE_SECURITY
+static int
+security_proto_supported(enum rte_security_session_protocol proto)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+	const struct rte_security_capability *capabilities;
+	const struct rte_security_capability *capability;
+	uint16_t i = 0;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+				rte_cryptodev_get_sec_ctx(
+				ts_params->valid_devs[0]);
+
+
+	capabilities = rte_security_capabilities_get(ctx);
+
+	if (capabilities == NULL)
+		return -ENOTSUP;
+
+	while ((capability = &capabilities[i++])->action !=
+			RTE_SECURITY_ACTION_TYPE_NONE) {
+		if (capability->protocol == proto)
+			return 0;
+	}
+
+	return -ENOTSUP;
+}
+
 /* Basic algorithm run function for async inplace mode.
  * Creates a session from input parameters and runs one operation
  * on input_vec. Checks the output of the crypto operation against
@@ -7670,6 +7703,9 @@ test_PDCP_PROTO_all(void)
 	if (!(feat_flags & RTE_CRYPTODEV_FF_SECURITY))
 		return -ENOTSUP;
 
+	if (security_proto_supported(RTE_SECURITY_PROTOCOL_PDCP) < 0)
+		return -ENOTSUP;
+
 	status = test_PDCP_PROTO_cplane_encap_all();
 	status += test_PDCP_PROTO_cplane_decap_all();
 	status += test_PDCP_PROTO_uplane_encap_all();
@@ -7684,6 +7720,481 @@ test_PDCP_PROTO_all(void)
 	else
 		return TEST_SUCCESS;
 }
+
+static int
+test_docsis_proto_uplink(int i, struct docsis_test_data *d_td)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	uint8_t *plaintext, *ciphertext;
+	uint8_t *iv_ptr;
+	int32_t cipher_len, crc_len;
+	uint32_t crc_data_len;
+	int ret = TEST_SUCCESS;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(
+						ts_params->valid_devs[0]);
+
+	/* Verify the capabilities */
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	const struct rte_cryptodev_capabilities *crypto_cap;
+	const struct rte_cryptodev_symmetric_capability *sym_cap;
+	int j = 0;
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_DOCSIS;
+	sec_cap_idx.docsis.direction = RTE_SECURITY_DOCSIS_UPLINK;
+
+	sec_cap = rte_security_capability_get(ctx, &sec_cap_idx);
+	if (sec_cap == NULL)
+		return -ENOTSUP;
+
+	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+				crypto_cap->sym.xform_type ==
+					RTE_CRYPTO_SYM_XFORM_CIPHER &&
+				crypto_cap->sym.cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI) {
+			sym_cap = &crypto_cap->sym;
+			if (rte_cryptodev_sym_capability_check_cipher(sym_cap,
+						d_td->key.len,
+						d_td->iv.len) == 0)
+				break;
+		}
+	}
+
+	if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED)
+		return -ENOTSUP;
+
+	/* Setup source mbuf payload */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+			rte_pktmbuf_tailroom(ut_params->ibuf));
+
+	ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+			d_td->ciphertext.len);
+
+	memcpy(ciphertext, d_td->ciphertext.data, d_td->ciphertext.len);
+
+	/* Set session action type */
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	/* Setup cipher session parameters */
+	ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	ut_params->cipher_xform.cipher.key.data = d_td->key.data;
+	ut_params->cipher_xform.cipher.key.length = d_td->key.len;
+	ut_params->cipher_xform.cipher.iv.length = d_td->iv.len;
+	ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+	ut_params->cipher_xform.next = NULL;
+
+	/* Setup DOCSIS session parameters */
+	ut_params->docsis_xform.direction = RTE_SECURITY_DOCSIS_UPLINK;
+
+	struct rte_security_session_conf sess_conf = {
+		.action_type = ut_params->type,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = ut_params->docsis_xform,
+		.crypto_xform = &ut_params->cipher_xform,
+	};
+
+	/* Create security session */
+	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
+					ts_params->session_priv_mpool);
+
+	if (!ut_params->sec_session) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "failed to allocate session");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Generate crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+				RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!ut_params->op) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to allocate symmetric crypto operation");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Setup CRC operation parameters */
+	crc_len = d_td->ciphertext.no_crc == false ?
+			(d_td->ciphertext.len -
+				d_td->ciphertext.crc_offset -
+				RTE_ETHER_CRC_LEN) :
+			0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	crc_data_len = crc_len == 0 ? 0 : RTE_ETHER_CRC_LEN;
+	ut_params->op->sym->auth.data.length = crc_len;
+	ut_params->op->sym->auth.data.offset = d_td->ciphertext.crc_offset;
+
+	/* Setup cipher operation parameters */
+	cipher_len = d_td->ciphertext.no_cipher == false ?
+			(d_td->ciphertext.len -
+				d_td->ciphertext.cipher_offset) :
+			0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	ut_params->op->sym->cipher.data.length = cipher_len;
+	ut_params->op->sym->cipher.data.offset = d_td->ciphertext.cipher_offset;
+
+	/* Setup cipher IV */
+	iv_ptr = (uint8_t *)ut_params->op + IV_OFFSET;
+	rte_memcpy(iv_ptr, d_td->iv.data, d_td->iv.len);
+
+	/* Attach session to operation */
+	rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+	/* Set crypto operation mbufs */
+	ut_params->op->sym->m_src = ut_params->ibuf;
+	ut_params->op->sym->m_dst = NULL;
+
+	/* Process crypto operation */
+	if (process_crypto_request(ts_params->valid_devs[0], ut_params->op) ==
+			NULL) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to process security crypto op");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "crypto op processing failed");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Validate plaintext */
+	plaintext = ciphertext;
+
+	if (memcmp(plaintext, d_td->plaintext.data,
+			d_td->plaintext.len - crc_data_len)) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "plaintext not as expected\n");
+		rte_hexdump(stdout, "expected", d_td->plaintext.data,
+				d_td->plaintext.len);
+		rte_hexdump(stdout, "actual", plaintext, d_td->plaintext.len);
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+on_err:
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	if (ut_params->sec_session)
+		rte_security_session_destroy(ctx, ut_params->sec_session);
+	ut_params->sec_session = NULL;
+
+	rte_pktmbuf_free(ut_params->ibuf);
+	ut_params->ibuf = NULL;
+
+	return ret;
+}
+
+static int
+test_docsis_proto_downlink(int i, struct docsis_test_data *d_td)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	uint8_t *plaintext, *ciphertext;
+	uint8_t *iv_ptr;
+	int32_t cipher_len, crc_len;
+	int ret = TEST_SUCCESS;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(
+						ts_params->valid_devs[0]);
+
+	/* Verify the capabilities */
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	const struct rte_cryptodev_capabilities *crypto_cap;
+	const struct rte_cryptodev_symmetric_capability *sym_cap;
+	int j = 0;
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_DOCSIS;
+	sec_cap_idx.docsis.direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+
+	sec_cap = rte_security_capability_get(ctx, &sec_cap_idx);
+	if (sec_cap == NULL)
+		return -ENOTSUP;
+
+	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+				crypto_cap->sym.xform_type ==
+					RTE_CRYPTO_SYM_XFORM_CIPHER &&
+				crypto_cap->sym.cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI) {
+			sym_cap = &crypto_cap->sym;
+			if (rte_cryptodev_sym_capability_check_cipher(sym_cap,
+						d_td->key.len,
+						d_td->iv.len) == 0)
+				break;
+		}
+	}
+
+	if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED)
+		return -ENOTSUP;
+
+	/* Setup source mbuf payload */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+			rte_pktmbuf_tailroom(ut_params->ibuf));
+
+	plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+			d_td->plaintext.len);
+
+	memcpy(plaintext, d_td->plaintext.data, d_td->plaintext.len);
+
+	/* Set session action type */
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	/* Setup cipher session parameters */
+	ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+	ut_params->cipher_xform.cipher.key.data = d_td->key.data;
+	ut_params->cipher_xform.cipher.key.length = d_td->key.len;
+	ut_params->cipher_xform.cipher.iv.length = d_td->iv.len;
+	ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+	ut_params->cipher_xform.next = NULL;
+
+	/* Setup DOCSIS session parameters */
+	ut_params->docsis_xform.direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+
+	struct rte_security_session_conf sess_conf = {
+		.action_type = ut_params->type,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = ut_params->docsis_xform,
+		.crypto_xform = &ut_params->cipher_xform,
+	};
+
+	/* Create security session */
+	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
+					ts_params->session_priv_mpool);
+
+	if (!ut_params->sec_session) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "failed to allocate session");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Generate crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+				RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!ut_params->op) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to allocate security crypto operation");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Setup CRC operation parameters */
+	crc_len = d_td->plaintext.no_crc == false ?
+			(d_td->plaintext.len -
+				d_td->plaintext.crc_offset -
+				RTE_ETHER_CRC_LEN) :
+			0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	ut_params->op->sym->auth.data.length = crc_len;
+	ut_params->op->sym->auth.data.offset = d_td->plaintext.crc_offset;
+
+	/* Setup cipher operation parameters */
+	cipher_len = d_td->plaintext.no_cipher == false ?
+			(d_td->plaintext.len -
+				d_td->plaintext.cipher_offset) :
+			0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	ut_params->op->sym->cipher.data.length = cipher_len;
+	ut_params->op->sym->cipher.data.offset = d_td->plaintext.cipher_offset;
+
+	/* Setup cipher IV */
+	iv_ptr = (uint8_t *)ut_params->op + IV_OFFSET;
+	rte_memcpy(iv_ptr, d_td->iv.data, d_td->iv.len);
+
+	/* Attach session to operation */
+	rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+	/* Set crypto operation mbufs */
+	ut_params->op->sym->m_src = ut_params->ibuf;
+	ut_params->op->sym->m_dst = NULL;
+
+	/* Process crypto operation */
+	if (process_crypto_request(ts_params->valid_devs[0], ut_params->op) ==
+			NULL) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to process security crypto op");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "crypto op processing failed");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Validate ciphertext */
+	ciphertext = plaintext;
+
+	if (memcmp(ciphertext, d_td->ciphertext.data, d_td->ciphertext.len)) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "ciphertext not as expected\n");
+		rte_hexdump(stdout, "expected", d_td->ciphertext.data,
+				d_td->ciphertext.len);
+		rte_hexdump(stdout, "actual", ciphertext, d_td->ciphertext.len);
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+on_err:
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	if (ut_params->sec_session)
+		rte_security_session_destroy(ctx, ut_params->sec_session);
+	ut_params->sec_session = NULL;
+
+	rte_pktmbuf_free(ut_params->ibuf);
+	ut_params->ibuf = NULL;
+
+	return ret;
+}
+
+#define TEST_DOCSIS_COUNT(func) do {			\
+	int ret = func;					\
+	if (ret == TEST_SUCCESS)  {			\
+		printf("\t%2d)", n++);			\
+		printf("+++++ PASSED:" #func"\n");	\
+		p++;					\
+	} else if (ret == -ENOTSUP) {			\
+		printf("\t%2d)", n++);			\
+		printf("~~~~~ UNSUPP:" #func"\n");	\
+		u++;					\
+	} else {					\
+		printf("\t%2d)", n++);			\
+		printf("----- FAILED:" #func"\n");	\
+		f++;					\
+	}						\
+} while (0)
+
+static int
+test_DOCSIS_PROTO_uplink_all(void)
+{
+	int p = 0, u = 0, f = 0, n = 0;
+
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(1, &docsis_test_case_1));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(2, &docsis_test_case_2));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(3, &docsis_test_case_3));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(4, &docsis_test_case_4));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(5, &docsis_test_case_5));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(6, &docsis_test_case_6));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(7, &docsis_test_case_7));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(8, &docsis_test_case_8));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(9, &docsis_test_case_9));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(10, &docsis_test_case_10));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(11, &docsis_test_case_11));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(12, &docsis_test_case_12));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(13, &docsis_test_case_13));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(14, &docsis_test_case_14));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(15, &docsis_test_case_15));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(16, &docsis_test_case_16));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(17, &docsis_test_case_17));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(18, &docsis_test_case_18));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(19, &docsis_test_case_19));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(20, &docsis_test_case_20));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(21, &docsis_test_case_21));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(22, &docsis_test_case_22));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(23, &docsis_test_case_23));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(24, &docsis_test_case_24));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(25, &docsis_test_case_25));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(26, &docsis_test_case_26));
+
+	if (f)
+		printf("## %s: %d passed out of %d (%d unsupported)\n",
+			__func__, p, n, u);
+
+	return f;
+};
+
+static int
+test_DOCSIS_PROTO_downlink_all(void)
+{
+	int p = 0, u = 0, f = 0, n = 0;
+
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(1, &docsis_test_case_1));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(2, &docsis_test_case_2));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(3, &docsis_test_case_3));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(4, &docsis_test_case_4));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(5, &docsis_test_case_5));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(6, &docsis_test_case_6));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(7, &docsis_test_case_7));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(8, &docsis_test_case_8));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(9, &docsis_test_case_9));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(10, &docsis_test_case_10));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(11, &docsis_test_case_11));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(12, &docsis_test_case_12));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(13, &docsis_test_case_13));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(14, &docsis_test_case_14));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(15, &docsis_test_case_15));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(16, &docsis_test_case_16));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(17, &docsis_test_case_17));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(18, &docsis_test_case_18));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(19, &docsis_test_case_19));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(20, &docsis_test_case_20));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(21, &docsis_test_case_21));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(22, &docsis_test_case_22));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(23, &docsis_test_case_23));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(24, &docsis_test_case_24));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(25, &docsis_test_case_25));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(26, &docsis_test_case_26));
+
+	if (f)
+		printf("## %s: %d passed out of %d (%d unsupported)\n",
+			__func__, p, n, u);
+
+	return f;
+};
+
+static int
+test_DOCSIS_PROTO_all(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct rte_cryptodev_info dev_info;
+	int status;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	uint64_t feat_flags = dev_info.feature_flags;
+
+	if (!(feat_flags & RTE_CRYPTODEV_FF_SECURITY))
+		return -ENOTSUP;
+
+	if (security_proto_supported(RTE_SECURITY_PROTOCOL_DOCSIS) < 0)
+		return -ENOTSUP;
+
+	status = test_DOCSIS_PROTO_uplink_all();
+	status += test_DOCSIS_PROTO_downlink_all();
+
+	if (status)
+		return TEST_FAILED;
+	else
+		return TEST_SUCCESS;
+}
 #endif
 
 static int
@@ -12342,6 +12853,8 @@ static struct unit_test_suite cryptodev_testsuite  = {
 #ifdef RTE_LIBRTE_SECURITY
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_PDCP_PROTO_all),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_DOCSIS_PROTO_all),
 #endif
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
diff --git a/app/test/test_cryptodev_security_docsis_test_vectors.h b/app/test/test_cryptodev_security_docsis_test_vectors.h
new file mode 100644
index 000000000..2ed57bd56
--- /dev/null
+++ b/app/test/test_cryptodev_security_docsis_test_vectors.h
@@ -0,0 +1,1544 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_
+
+/*
+ * DOCSIS test data and cases
+ * - encrypt direction: CRC-Crypto
+ * - decrypt direction: Crypto-CRC
+ */
+
+struct docsis_test_data {
+	struct {
+		uint8_t data[32];
+		unsigned int len;
+	} key;
+
+	struct {
+		uint8_t data[16] __rte_aligned(16);
+		unsigned int len;
+	} iv;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} plaintext;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} ciphertext;
+};
+
+struct docsis_test_data docsis_test_case_1 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x61, 0xF8, 0x63, 0x42
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_2 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0, 0xDF,
+			/* CRC */
+			0xFE, 0x12, 0x99, 0xE5
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_3 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xD6, 0xE2, 0x70, 0x5C,
+			0xE6, 0x4D, 0xCC, 0x8C, 0x47, 0xB7, 0x09, 0xD6,
+			/* CRC */
+			0x54, 0x85, 0xF8, 0x32
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_4 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x92, 0x6A, 0xC2, 0xDC,
+			0xEE, 0x3B, 0x31, 0xEC, 0x03, 0xDE, 0x95, 0x33,
+			0x5E,
+			/* CRC */
+			0xFE, 0x47, 0x3E, 0x22
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_5 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0x42, 0xF3, 0x71, 0xA9,
+			0x8A, 0xCD, 0x59, 0x77, 0x67, 0x11, 0x1A, 0x87,
+			/* CRC */
+			0xAB, 0xED, 0x2C, 0x26
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_6 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0xA4, 0x0C, 0xC2, 0xF0,
+			0x81, 0x49, 0xA8, 0xA6, 0x6C, 0x48, 0xEB, 0x1F,
+			0x4B,
+			/* CRC */
+			0x2F, 0xD4, 0x48, 0x18
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_7 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x11, 0xB4, 0x06, 0x33
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_8 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x8A, 0x0F, 0x74, 0xE8
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_9 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x5D, 0x2B, 0x12, 0xF4
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_10 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0x14, 0x08, 0xE8, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_11 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xB3, 0x60, 0xEB, 0x38
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_12 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_13 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_14 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86,
+			/* CRC */
+			0x9B, 0xB3, 0x1A, 0x26
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_15 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86, 0x25,
+			/* CRC */
+			0xB5, 0x6B, 0xFD, 0xCB
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_16 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xF6, 0xA1, 0x2E, 0x0A,
+			0xBB, 0x27, 0x82, 0x4F, 0x99, 0x0A, 0xE2, 0x3F,
+			/* CRC */
+			0xEB, 0xB7, 0x89, 0xB0
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_17 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE1, 0x30, 0x38, 0xC8,
+			0xC4, 0x59, 0x8D, 0x43, 0x9A, 0xBE, 0xBE, 0x73,
+			0xC3,
+			/*CRC */
+			0x8C, 0xE1, 0x89, 0x8B
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_18 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE9, 0x12, 0x3B, 0x12,
+			0x36, 0x56, 0x95, 0xA6, 0x97, 0xF1, 0x74, 0x68,
+			0xBA, 0x58, 0x77, 0xEA, 0x43, 0x11, 0x85, 0xD4,
+			0x7A, 0xF8, 0x1C, 0x11, 0x50, 0xD1, 0xF1, 0xBD,
+			0x15, 0x4D, 0x99, 0xB5, 0x39, 0x74, 0x84, 0xDF,
+			0xD4, 0x8B, 0xDC, 0xB7, 0x58, 0x1B, 0x22, 0xAB,
+			0xF3, 0x29, 0xC6, 0xCB, 0x26, 0x07, 0x36, 0x6B,
+			0x8C, 0xAC, 0x6E, 0x99, 0x37, 0x94, 0xDF, 0x31,
+			/* CRC */
+			0xA1, 0x7D, 0x70, 0xBB
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_19 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE9, 0x12, 0x3B, 0x12,
+			0x36, 0x56, 0x95, 0xA6, 0x97, 0xF1, 0x74, 0x68,
+			0xBA, 0x58, 0x77, 0xEA, 0x43, 0x11, 0x85, 0xD4,
+			0x7A, 0xF8, 0x1C, 0x11, 0x50, 0xD1, 0xF1, 0xBD,
+			0x15, 0x4D, 0x99, 0xB5, 0x39, 0x74, 0x84, 0xDF,
+			0xD4, 0x8B, 0xDC, 0xB7, 0x58, 0x1B, 0x22, 0xAB,
+			0xF3, 0x29, 0xC6, 0xCB, 0x13, 0xED, 0x08, 0xF5,
+			0x1B, 0x4B, 0xD8, 0x79, 0x93, 0x26, 0x69, 0x03,
+			0x23,
+			/* CRC */
+			0xC8, 0x8E, 0x02, 0x3A
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_20 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x54, 0xB4, 0x55, 0x68, 0x06, 0xBF,
+			0x00, 0x8B, 0x5F, 0x2C, 0x10, 0x4A, 0xBF, 0x5A,
+			0xF2, 0x20, 0xD9, 0x77, 0x7F, 0x2D, 0x2B, 0x11,
+			0xAC, 0xAF, 0x21, 0x36, 0xD2, 0xD4, 0x80, 0xF2,
+			0x4F, 0x14, 0xA0, 0x3A, 0x66, 0xE5, 0xC5, 0xE2,
+			0x15,
+			/* CRC */
+			0x0C, 0x89, 0x76, 0x26
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_21 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86,
+			/* CRC */
+			0x70, 0x44, 0x0D, 0x8C
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_22 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x54, 0xB4, 0x55, 0x68, 0x06, 0xBF,
+			0x00, 0x8B, 0x5F, 0x2C, 0x10, 0x4A, 0xBF, 0x5A,
+			0xF2, 0x20, 0xD9, 0x77, 0x7F, 0x2D, 0x2B, 0x11,
+			0xAC, 0xAF, 0x21, 0x36, 0xD2, 0xD4, 0x80, 0xF2,
+			0x4F, 0x14, 0xA0, 0x3A, 0x66, 0xE5, 0xC5, 0xE2,
+			0x15,
+			/* CRC */
+			0x40, 0x16, 0x62, 0xE1
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_23 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0x14, 0x08, 0xE8, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_24 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xB3, 0x60, 0xEB, 0x38
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_25 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_26 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+#endif /* TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_ */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 6/8] test/security: add DOCSIS capability check tests
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
                         ` (4 preceding siblings ...)
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 5/8] test/crypto: add DOCSIS security test cases David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 7/8] app/crypto-perf: add support for DOCSIS protocol David Coyle
                         ` (2 subsequent siblings)
  8 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add unit tests for DOCSIS capabilitity checks.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 app/test/test_security.c | 88 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/app/test/test_security.c b/app/test/test_security.c
index 3076a4c5a..77fd5adc6 100644
--- a/app/test/test_security.c
+++ b/app/test/test_security.c
@@ -6,6 +6,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_mempool.h>
+#include <rte_ether.h>
 #include <rte_security.h>
 #include <rte_security_driver.h>
 
@@ -2268,6 +2269,89 @@ test_capability_get_pdcp_match(void)
 	return TEST_SUCCESS;
 }
 
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching DOCSIS direction field
+ */
+static int
+test_capability_get_docsis_mismatch_direction(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx idx = {
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK
+		},
+	};
+	struct rte_security_capability capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			.docsis = {
+				.direction = RTE_SECURITY_DOCSIS_UPLINK
+			},
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE,
+		},
+	};
+
+	mock_capabilities_get_exp.device = NULL;
+	mock_capabilities_get_exp.ret = capabilities;
+
+	const struct rte_security_capability *ret;
+	ret = rte_security_capability_get(&ut_params->ctx, &idx);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+			ret, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * contains matching DOCSIS entry
+ */
+static int
+test_capability_get_docsis_match(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx idx = {
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_UPLINK
+		},
+	};
+	struct rte_security_capability capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			.docsis = {
+				.direction = RTE_SECURITY_DOCSIS_UPLINK
+			},
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE,
+		},
+	};
+
+	mock_capabilities_get_exp.device = NULL;
+	mock_capabilities_get_exp.ret = capabilities;
+
+	const struct rte_security_capability *ret;
+	ret = rte_security_capability_get(&ut_params->ctx, &idx);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+			ret, &capabilities[1], "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+	return TEST_SUCCESS;
+}
+
 /**
  * Declaration of testcases
  */
@@ -2410,6 +2494,10 @@ static struct unit_test_suite security_testsuite  = {
 				test_capability_get_pdcp_mismatch_domain),
 		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
 				test_capability_get_pdcp_match),
+		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+				test_capability_get_docsis_mismatch_direction),
+		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+				test_capability_get_docsis_match),
 
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 7/8] app/crypto-perf: add support for DOCSIS protocol
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
                         ` (5 preceding siblings ...)
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 6/8] test/security: add DOCSIS capability check tests David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-07-01 21:44         ` Akhil Goyal
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 8/8] doc: add doc updates for DOCSIS security protocol David Coyle
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
  8 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Update test-crypto-perf app to calculate DOCSIS throughput numbers.

1 new parameter is added for DOCSIS:
--docsis-hdr-sz <n>

./dpdk-test-crypto-perf -l 3,4 --socket-mem 2048,0
--vdev crypto_aesni_mb_pmd_1 -n 1 -- --devtype crypto_aesni_mb
--optype docsis --cipher-algo aes-docsisbpi --cipher-op encrypt
--cipher-key-sz 16 --cipher-iv-sz 16 --burst-sz 32 --total-ops 20000000
--buffer-sz 1024 --silent --docsis-hdr-sz 17

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 app/test-crypto-perf/cperf_ops.c             | 82 ++++++++++++++++++--
 app/test-crypto-perf/cperf_options.h         |  5 +-
 app/test-crypto-perf/cperf_options_parsing.c | 67 +++++++++++++++-
 app/test-crypto-perf/cperf_test_throughput.c |  3 +-
 app/test-crypto-perf/cperf_test_vectors.c    |  3 +-
 app/test-crypto-perf/main.c                  |  5 +-
 app/test-crypto-perf/meson.build             |  2 +-
 7 files changed, 155 insertions(+), 12 deletions(-)

diff --git a/app/test-crypto-perf/cperf_ops.c b/app/test-crypto-perf/cperf_ops.c
index 97584ceed..e06b59f55 100644
--- a/app/test-crypto-perf/cperf_ops.c
+++ b/app/test-crypto-perf/cperf_ops.c
@@ -3,6 +3,7 @@
  */
 
 #include <rte_cryptodev.h>
+#include <rte_ether.h>
 
 #include "cperf_ops.h"
 #include "cperf_test_vectors.h"
@@ -15,8 +16,7 @@ cperf_set_ops_security(struct rte_crypto_op **ops,
 		uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
 		const struct cperf_options *options __rte_unused,
 		const struct cperf_test_vector *test_vector __rte_unused,
-		uint16_t iv_offset __rte_unused,
-		uint32_t *imix_idx __rte_unused)
+		uint16_t iv_offset __rte_unused, uint32_t *imix_idx)
 {
 	uint16_t i;
 
@@ -24,14 +24,39 @@ cperf_set_ops_security(struct rte_crypto_op **ops,
 		struct rte_crypto_sym_op *sym_op = ops[i]->sym;
 		struct rte_security_session *sec_sess =
 			(struct rte_security_session *)sess;
+		uint32_t buf_sz;
 
 		ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 		rte_security_attach_session(ops[i], sec_sess);
 		sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
 							src_buf_offset);
-		sym_op->m_src->buf_len = options->segment_sz;
-		sym_op->m_src->data_len = options->test_buffer_size;
-		sym_op->m_src->pkt_len = sym_op->m_src->data_len;
+
+		if (options->op_type == CPERF_PDCP) {
+			sym_op->m_src->buf_len = options->segment_sz;
+			sym_op->m_src->data_len = options->test_buffer_size;
+			sym_op->m_src->pkt_len = sym_op->m_src->data_len;
+		}
+
+		if (options->op_type == CPERF_DOCSIS) {
+			if (options->imix_distribution_count) {
+				buf_sz = options->imix_buffer_sizes[*imix_idx];
+				*imix_idx = (*imix_idx + 1) % options->pool_sz;
+			} else
+				buf_sz = options->test_buffer_size;
+
+			/* DOCSIS header is not CRC'ed */
+			sym_op->auth.data.offset = options->docsis_hdr_sz;
+			sym_op->auth.data.length = buf_sz -
+				sym_op->auth.data.offset - RTE_ETHER_CRC_LEN;
+			/*
+			 * DOCSIS header and SRC and DST MAC addresses are not
+			 * ciphered
+			 */
+			sym_op->cipher.data.offset = sym_op->auth.data.offset +
+				RTE_ETHER_HDR_LEN - RTE_ETHER_TYPE_LEN;
+			sym_op->cipher.data.length = buf_sz -
+				sym_op->cipher.data.offset;
+		}
 
 		/* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
 		if (dst_buf_offset == 0)
@@ -589,6 +614,49 @@ cperf_create_session(struct rte_mempool *sess_mp,
 		return (void *)rte_security_session_create(ctx,
 					&sess_conf, sess_mp);
 	}
+	if (options->op_type == CPERF_DOCSIS) {
+		enum rte_security_docsis_direction direction;
+
+		cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+		cipher_xform.next = NULL;
+		cipher_xform.cipher.algo = options->cipher_algo;
+		cipher_xform.cipher.op = options->cipher_op;
+		cipher_xform.cipher.iv.offset = iv_offset;
+		if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+			cipher_xform.cipher.key.data =
+				test_vector->cipher_key.data;
+			cipher_xform.cipher.key.length =
+				test_vector->cipher_key.length;
+			cipher_xform.cipher.iv.length =
+				test_vector->cipher_iv.length;
+		} else {
+			cipher_xform.cipher.key.data = NULL;
+			cipher_xform.cipher.key.length = 0;
+			cipher_xform.cipher.iv.length = 0;
+		}
+		cipher_xform.next = NULL;
+
+		if (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
+			direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+		else
+			direction = RTE_SECURITY_DOCSIS_UPLINK;
+
+		struct rte_security_session_conf sess_conf = {
+			.action_type =
+				RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			{.docsis = {
+				.direction = direction,
+			} },
+			.crypto_xform = &cipher_xform
+		};
+		struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(dev_id);
+
+		/* Create security session */
+		return (void *)rte_security_session_create(ctx,
+					&sess_conf, priv_mp);
+	}
 #endif
 	sess = rte_cryptodev_sym_session_create(sess_mp);
 	/*
@@ -772,6 +840,10 @@ cperf_get_op_functions(const struct cperf_options *options,
 		op_fns->populate_ops = cperf_set_ops_security;
 		return 0;
 	}
+	if (options->op_type == CPERF_DOCSIS) {
+		op_fns->populate_ops = cperf_set_ops_security;
+		return 0;
+	}
 #endif
 	return -1;
 }
diff --git a/app/test-crypto-perf/cperf_options.h b/app/test-crypto-perf/cperf_options.h
index 1ed0a77e5..e5f1edffc 100644
--- a/app/test-crypto-perf/cperf_options.h
+++ b/app/test-crypto-perf/cperf_options.h
@@ -50,6 +50,7 @@
 #ifdef RTE_LIBRTE_SECURITY
 #define CPERF_PDCP_SN_SZ	("pdcp-sn-sz")
 #define CPERF_PDCP_DOMAIN	("pdcp-domain")
+#define CPERF_DOCSIS_HDR_SZ	("docsis-hdr-sz")
 #endif
 
 #define CPERF_CSV		("csv-friendly")
@@ -75,7 +76,8 @@ enum cperf_op_type {
 	CPERF_CIPHER_THEN_AUTH,
 	CPERF_AUTH_THEN_CIPHER,
 	CPERF_AEAD,
-	CPERF_PDCP
+	CPERF_PDCP,
+	CPERF_DOCSIS
 };
 
 extern const char *cperf_op_type_strs[];
@@ -122,6 +124,7 @@ struct cperf_options {
 #ifdef RTE_LIBRTE_SECURITY
 	uint16_t pdcp_sn_sz;
 	enum rte_security_pdcp_domain pdcp_domain;
+	uint16_t docsis_hdr_sz;
 #endif
 	char device_type[RTE_CRYPTODEV_NAME_MAX_LEN];
 	enum cperf_op_type op_type;
diff --git a/app/test-crypto-perf/cperf_options_parsing.c b/app/test-crypto-perf/cperf_options_parsing.c
index f43c5bede..20577a144 100644
--- a/app/test-crypto-perf/cperf_options_parsing.c
+++ b/app/test-crypto-perf/cperf_options_parsing.c
@@ -7,6 +7,7 @@
 
 #include <rte_cryptodev.h>
 #include <rte_malloc.h>
+#include <rte_ether.h>
 
 #include "cperf_options.h"
 
@@ -56,6 +57,9 @@ usage(char *progname)
 		" --pmd-cyclecount-delay-ms N: set delay between enqueue\n"
 		"           and dequeue in pmd-cyclecount benchmarking mode\n"
 		" --csv-friendly: enable test result output CSV friendly\n"
+#ifdef RTE_LIBRTE_SECURITY
+		" --docsis-hdr-sz: set DOCSIS header size\n"
+#endif
 		" -h: prints this help\n",
 		progname);
 }
@@ -446,6 +450,10 @@ parse_op_type(struct cperf_options *opts, const char *arg)
 		{
 			cperf_op_type_strs[CPERF_PDCP],
 			CPERF_PDCP
+		},
+		{
+			cperf_op_type_strs[CPERF_DOCSIS],
+			CPERF_DOCSIS
 		}
 	};
 
@@ -675,6 +683,12 @@ parse_pdcp_domain(struct cperf_options *opts, const char *arg)
 
 	return 0;
 }
+
+static int
+parse_docsis_hdr_sz(struct cperf_options *opts, const char *arg)
+{
+	return parse_uint16_t(&opts->docsis_hdr_sz, arg);
+}
 #endif
 
 static int
@@ -820,6 +834,7 @@ static struct option lgopts[] = {
 #ifdef RTE_LIBRTE_SECURITY
 	{ CPERF_PDCP_SN_SZ, required_argument, 0, 0 },
 	{ CPERF_PDCP_DOMAIN, required_argument, 0, 0 },
+	{ CPERF_DOCSIS_HDR_SZ, required_argument, 0, 0 },
 #endif
 	{ CPERF_CSV, no_argument, 0, 0},
 
@@ -890,6 +905,7 @@ cperf_options_default(struct cperf_options *opts)
 #ifdef RTE_LIBRTE_SECURITY
 	opts->pdcp_sn_sz = 12;
 	opts->pdcp_domain = RTE_SECURITY_PDCP_MODE_CONTROL;
+	opts->docsis_hdr_sz = 17;
 #endif
 }
 
@@ -929,6 +945,7 @@ cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
 #ifdef RTE_LIBRTE_SECURITY
 		{ CPERF_PDCP_SN_SZ,	parse_pdcp_sn_sz },
 		{ CPERF_PDCP_DOMAIN,	parse_pdcp_domain },
+		{ CPERF_DOCSIS_HDR_SZ,	parse_docsis_hdr_sz },
 #endif
 		{ CPERF_CSV,		parse_csv_friendly},
 		{ CPERF_PMDCC_DELAY_MS,	parse_pmd_cyclecount_delay_ms},
@@ -1031,10 +1048,44 @@ check_cipher_buffer_length(struct cperf_options *options)
 	return 0;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
+static int
+check_docsis_buffer_length(struct cperf_options *options)
+{
+	uint32_t buffer_size, buffer_size_idx = 0;
+
+	if (options->inc_buffer_size != 0)
+		buffer_size = options->min_buffer_size;
+	else
+		buffer_size = options->buffer_size_list[0];
+
+	while (buffer_size <= options->max_buffer_size) {
+		if (buffer_size < (uint32_t)(options->docsis_hdr_sz +
+				RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)) {
+			RTE_LOG(ERR, USER1, "Some of the buffer sizes are not "
+				"valid for DOCSIS\n");
+			return -EINVAL;
+		}
+
+		if (options->inc_buffer_size != 0)
+			buffer_size += options->inc_buffer_size;
+		else {
+			if (++buffer_size_idx == options->buffer_size_count)
+				break;
+			buffer_size =
+				options->buffer_size_list[buffer_size_idx];
+		}
+	}
+
+	return 0;
+}
+#endif
+
 int
 cperf_options_check(struct cperf_options *options)
 {
-	if (options->op_type == CPERF_CIPHER_ONLY)
+	if (options->op_type == CPERF_CIPHER_ONLY ||
+			options->op_type == CPERF_DOCSIS)
 		options->digest_sz = 0;
 
 	if (options->out_of_place &&
@@ -1151,6 +1202,13 @@ cperf_options_check(struct cperf_options *options)
 			return -EINVAL;
 	}
 
+#ifdef RTE_LIBRTE_SECURITY
+	if (options->op_type == CPERF_DOCSIS) {
+		if (check_docsis_buffer_length(options) < 0)
+			return -EINVAL;
+	}
+#endif
+
 	return 0;
 }
 
@@ -1236,4 +1294,11 @@ cperf_options_dump(struct cperf_options *opts)
 		printf("# aead aad size: %u\n", opts->aead_aad_sz);
 		printf("#\n");
 	}
+
+#ifdef RTE_LIBRTE_SECURITY
+	if (opts->op_type == CPERF_DOCSIS) {
+		printf("# docsis header size: %u\n", opts->docsis_hdr_sz);
+		printf("#\n");
+	}
+#endif
 }
diff --git a/app/test-crypto-perf/cperf_test_throughput.c b/app/test-crypto-perf/cperf_test_throughput.c
index 35c51026f..12d9ea4f9 100644
--- a/app/test-crypto-perf/cperf_test_throughput.c
+++ b/app/test-crypto-perf/cperf_test_throughput.c
@@ -36,7 +36,8 @@ cperf_throughput_test_free(struct cperf_throughput_ctx *ctx)
 		return;
 	if (ctx->sess) {
 #ifdef RTE_LIBRTE_SECURITY
-		if (ctx->options->op_type == CPERF_PDCP) {
+		if (ctx->options->op_type == CPERF_PDCP ||
+				ctx->options->op_type == CPERF_DOCSIS) {
 			struct rte_security_ctx *sec_ctx =
 				(struct rte_security_ctx *)
 				rte_cryptodev_get_sec_ctx(ctx->dev_id);
diff --git a/app/test-crypto-perf/cperf_test_vectors.c b/app/test-crypto-perf/cperf_test_vectors.c
index 41641650c..0af01ff91 100644
--- a/app/test-crypto-perf/cperf_test_vectors.c
+++ b/app/test-crypto-perf/cperf_test_vectors.c
@@ -469,7 +469,8 @@ cperf_test_vector_get_dummy(struct cperf_options *options)
 
 	if (options->op_type ==	CPERF_CIPHER_ONLY ||
 			options->op_type == CPERF_CIPHER_THEN_AUTH ||
-			options->op_type == CPERF_AUTH_THEN_CIPHER) {
+			options->op_type == CPERF_AUTH_THEN_CIPHER ||
+			options->op_type == CPERF_DOCSIS) {
 		if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
 			t_vec->cipher_key.length = 0;
 			t_vec->ciphertext.data = plaintext;
diff --git a/app/test-crypto-perf/main.c b/app/test-crypto-perf/main.c
index 7bb286ccb..edeea9c1b 100644
--- a/app/test-crypto-perf/main.c
+++ b/app/test-crypto-perf/main.c
@@ -39,7 +39,8 @@ const char *cperf_op_type_strs[] = {
 	[CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth",
 	[CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher",
 	[CPERF_AEAD] = "aead",
-	[CPERF_PDCP] = "pdcp"
+	[CPERF_PDCP] = "pdcp",
+	[CPERF_DOCSIS] = "docsis"
 };
 
 const struct cperf_test cperf_testmap[] = {
@@ -244,7 +245,7 @@ cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs)
 #endif
 		} else
 			sessions_needed = enabled_cdev_count *
-						opts->nb_qps;
+						opts->nb_qps * 2;
 
 		/*
 		 * A single session is required per queue pair
diff --git a/app/test-crypto-perf/meson.build b/app/test-crypto-perf/meson.build
index ef28cb5a0..f394b75ba 100644
--- a/app/test-crypto-perf/meson.build
+++ b/app/test-crypto-perf/meson.build
@@ -11,4 +11,4 @@ sources = files('cperf_ops.c',
 		'cperf_test_vectors.c',
 		'cperf_test_verify.c',
 		'main.c')
-deps += ['cryptodev', 'security']
+deps += ['cryptodev', 'net', 'security']
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v3 8/8] doc: add doc updates for DOCSIS security protocol
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
                         ` (6 preceding siblings ...)
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 7/8] app/crypto-perf: add support for DOCSIS protocol David Coyle
@ 2020-06-30 16:30       ` David Coyle
  2020-06-30 18:33         ` Akhil Goyal
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
  8 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-06-30 16:30 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Update Security library, AESNI-MB crypto PMD, QAT crypto PMD,
dpdk-test-crypto-perf tool and release note documentation for DOCSIS
protocol support.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 doc/guides/cryptodevs/aesni_mb.rst          |   8 ++
 doc/guides/cryptodevs/features/aesni_mb.ini |   1 +
 doc/guides/cryptodevs/features/qat.ini      |   1 +
 doc/guides/cryptodevs/qat.rst               |   7 ++
 doc/guides/prog_guide/rte_security.rst      | 114 +++++++++++++++++++-
 doc/guides/rel_notes/release_20_08.rst      |  16 +++
 doc/guides/tools/cryptoperf.rst             |   5 +
 7 files changed, 150 insertions(+), 2 deletions(-)

diff --git a/doc/guides/cryptodevs/aesni_mb.rst b/doc/guides/cryptodevs/aesni_mb.rst
index cc64f1243..15388d20a 100644
--- a/doc/guides/cryptodevs/aesni_mb.rst
+++ b/doc/guides/cryptodevs/aesni_mb.rst
@@ -55,10 +55,18 @@ AEAD algorithms:
 * RTE_CRYPTO_AEAD_AES_CCM
 * RTE_CRYPTO_AEAD_AES_GCM
 
+Protocol offloads:
+
+* RTE_SECURITY_PROTOCOL_DOCSIS
+
 Limitations
 -----------
 
 * Chained mbufs are not supported.
+* Out-of-place is not supported for combined Crypto-CRC DOCSIS security
+  protocol.
+* RTE_CRYPTO_CIPHER_DES_DOCSISBPI is not supported for combined Crypto-CRC
+  DOCSIS security protocol.
 
 
 Installation
diff --git a/doc/guides/cryptodevs/features/aesni_mb.ini b/doc/guides/cryptodevs/features/aesni_mb.ini
index 49cb82a39..38d255aff 100644
--- a/doc/guides/cryptodevs/features/aesni_mb.ini
+++ b/doc/guides/cryptodevs/features/aesni_mb.ini
@@ -6,6 +6,7 @@
 [Features]
 Symmetric crypto       = Y
 Sym operation chaining = Y
+Protocol offload       = Y
 CPU SSE                = Y
 CPU AVX                = Y
 CPU AVX2               = Y
diff --git a/doc/guides/cryptodevs/features/qat.ini b/doc/guides/cryptodevs/features/qat.ini
index a72241997..2d56b187a 100644
--- a/doc/guides/cryptodevs/features/qat.ini
+++ b/doc/guides/cryptodevs/features/qat.ini
@@ -7,6 +7,7 @@
 Symmetric crypto       = Y
 Sym operation chaining = Y
 HW Accelerated         = Y
+Protocol offload       = Y
 In Place SGL           = Y
 OOP SGL In SGL Out     = Y
 OOP SGL In LB  Out     = Y
diff --git a/doc/guides/cryptodevs/qat.rst b/doc/guides/cryptodevs/qat.rst
index c2cc3d5ca..ee873e7b8 100644
--- a/doc/guides/cryptodevs/qat.rst
+++ b/doc/guides/cryptodevs/qat.rst
@@ -76,6 +76,9 @@ Supported AEAD algorithms:
 * ``RTE_CRYPTO_AEAD_AES_GCM``
 * ``RTE_CRYPTO_AEAD_AES_CCM``
 
+Protocol offloads:
+
+* ``RTE_SECURITY_PROTOCOL_DOCSIS``
 
 Supported Chains
 ~~~~~~~~~~~~~~~~
@@ -126,6 +129,10 @@ Limitations
   generations in the same process if planning to use for GCM.
 * The mixed algo feature on GEN2 is not supported by all kernel drivers. Check
   the notes under the Available Kernel Drivers table below for specific details.
+* Out-of-place is not supported for combined Crypto-CRC DOCSIS security
+  protocol.
+* ``RTE_CRYPTO_CIPHER_DES_DOCSISBPI`` is not supported for combined Crypto-CRC
+  DOCSIS security protocol.
 
 Extra notes on KASUMI F9
 ~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/guides/prog_guide/rte_security.rst b/doc/guides/prog_guide/rte_security.rst
index 9b5d249de..af4281587 100644
--- a/doc/guides/prog_guide/rte_security.rst
+++ b/doc/guides/prog_guide/rte_security.rst
@@ -10,8 +10,9 @@ The security library provides a framework for management and provisioning
 of security protocol operations offloaded to hardware based devices. The
 library defines generic APIs to create and free security sessions which can
 support full protocol offload as well as inline crypto operation with
-NIC or crypto devices. The framework currently only supports the IPsec and PDCP
-protocol and associated operations, other protocols will be added in future.
+NIC or crypto devices. The framework currently only supports the IPsec, PDCP
+and DOCSIS protocols and associated operations, other protocols will be added
+in the future.
 
 Design Principles
 -----------------
@@ -296,6 +297,53 @@ Just like IPsec, in case of PDCP also header addition/deletion, cipher/
 de-cipher, integrity protection/verification is done based on the action
 type chosen.
 
+DOCSIS Protocol
+~~~~~~~~~~~~~~~
+
+The Data Over Cable Service Interface Specification (DOCSIS) support comprises
+the combination of encryption/decryption and CRC generation/verification, for
+use in a DOCSIS-MAC pipeline.
+
+.. code-block:: c
+
+
+               Downlink                       Uplink
+               --------                       ------
+
+            Ethernet frame                Ethernet frame
+           from core network              to core network
+                  |                              ^
+                  ~                              |
+                  |                              ~         ----+
+                  V                              |             |
+        +---------|----------+        +----------|---------+   |
+        |   CRC generation   |        |  CRC verification  |   |
+        +---------|----------+        +----------|---------+   |   combined
+                  |                              |             > Crypto + CRC
+        +---------|----------+        +----------|---------+   |
+        |     Encryption     |        |     Decryption     |   |
+        +---------|----------+        +----------|---------+   |
+                  |                              ^             |
+                  ~                              |         ----+
+                  |                              ~
+                  V                              |
+             DOCSIS frame                  DOCSIS frame
+            to Cable Modem               from Cable Modem
+
+The encryption/decryption is a combination of CBC and CFB modes using either AES
+or DES algorithms as specified in the DOCSIS Security Specification (from DPDK
+lib_rtecryptodev perspective, these are RTE_CRYPTO_CIPHER_AES_DOCSISBPI and
+RTE_CRYPTO_CIPHER_DES_DOCSISBPI).
+
+The CRC is Ethernet CRC-32 as specified in Ethernet/[ISO/IEC 8802-3].
+
+.. note::
+
+    * The CRC offset and length are specified via the auth offset and
+      length fields of the rte_crypto_sym_op.
+    * Other DOCSIS protocol functionality such as Header Checksum (HCS)
+      calculation may be added in the future.
+
 Device Features and Capabilities
 ---------------------------------
 
@@ -408,6 +456,56 @@ PMD which supports the IPsec and PDCP protocol.
         }
     }
 
+Below is an example of the capabilities for a PMD which supports the DOCSIS
+protocol.
+
+.. code-block:: c
+
+    static const struct rte_security_capability pmd_security_capabilities[] = {
+        { /* DOCSIS Uplink */
+                .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+                .protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+                .docsis = {
+                        .direction = RTE_SECURITY_DOCSIS_UPLINK
+                },
+                .crypto_capabilities = pmd_capabilities
+        },
+        { /* DOCSIS Downlink */
+                .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+                .protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+                .docsis = {
+                        .direction = RTE_SECURITY_DOCSIS_DOWNLINK
+                },
+                .crypto_capabilities = pmd_capabilities
+        },
+        {
+                .action = RTE_SECURITY_ACTION_TYPE_NONE
+        }
+    };
+    static const struct rte_cryptodev_capabilities pmd_capabilities[] = {
+        {    /* AES DOCSIS BPI */
+            .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+            .sym = {
+                .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+                .cipher = {
+                    .algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+                    .block_size = 16,
+                    .key_size = {
+                        .min = 16,
+                        .max = 32,
+                        .increment = 16
+                    },
+                    .iv_size = {
+                        .min = 16,
+                        .max = 16,
+                        .increment = 0
+                    }
+                }
+            }
+        },
+
+        RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+    };
 
 Capabilities Discovery
 ~~~~~~~~~~~~~~~~~~~~~~
@@ -491,6 +589,7 @@ Security Session configuration structure is defined as ``rte_security_session_co
                 struct rte_security_ipsec_xform ipsec;
                 struct rte_security_macsec_xform macsec;
                 struct rte_security_pdcp_xform pdcp;
+                struct rte_security_docsis_xform docsis;
         };
         /**< Configuration parameters for security session */
         struct rte_crypto_sym_xform *crypto_xform;
@@ -538,6 +637,8 @@ The ``rte_security_session_protocol`` is defined as
         /**< MACSec Protocol */
         RTE_SECURITY_PROTOCOL_PDCP,
         /**< PDCP Protocol */
+        RTE_SECURITY_PROTOCOL_DOCSIS,
+        /**< DOCSIS Protocol */
     };
 
 Currently the library defines configuration parameters for IPsec and PDCP only.
@@ -594,6 +695,15 @@ PDCP related configuration parameters are defined in ``rte_security_pdcp_xform``
         uint32_t hfn_threshold;
     };
 
+DOCSIS related configuration parameters are defined in ``rte_security_docsis_xform``
+
+.. code-block:: c
+
+    struct rte_security_docsis_xform {
+        enum rte_security_docsis_direction direction;
+        /**< DOCSIS direction */
+    };
+
 
 Security API
 ~~~~~~~~~~~~
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index 39064afbe..0e72a26b1 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -56,6 +56,22 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added support for DOCSIS protocol to rte_security.**
+
+  Added support for combined crypto and CRC operations for the DOCSIS protocol
+  to ``rte_security``. Test and test-crypto-perf applications have been updated
+  for unit testing.
+
+* **Updated the AESNI MB crypto PMD.**
+
+  Added support for lookaside protocol offload for DOCSIS through the
+  ``rte_security`` API.
+
+* **Updated the QuickAssist Technology (QAT) Crypto PMD.**
+
+  Added support for lookaside protocol offload for DOCSIS through the
+  ``rte_security`` API.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/tools/cryptoperf.rst b/doc/guides/tools/cryptoperf.rst
index a19ccb262..a8df8bc99 100644
--- a/doc/guides/tools/cryptoperf.rst
+++ b/doc/guides/tools/cryptoperf.rst
@@ -193,6 +193,7 @@ The following are the application command-line options:
            auth-then-cipher
            aead
            pdcp
+           docsis
 
         For GCM/CCM algorithms you should use aead flag.
 
@@ -342,6 +343,10 @@ The following are the application command-line options:
 
         Set PDCP domain to specify Control/user plane.
 
+* ``--docsis-hdr-sz <n>``
+
+        Set DOCSIS header size(n) in bytes.
+
 Test Vector File
 ~~~~~~~~~~~~~~~~
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 8/8] doc: add doc updates for DOCSIS security protocol
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 8/8] doc: add doc updates for DOCSIS security protocol David Coyle
@ 2020-06-30 18:33         ` Akhil Goyal
  2020-07-01 17:03           ` Coyle, David
  0 siblings, 1 reply; 92+ messages in thread
From: Akhil Goyal @ 2020-06-30 18:33 UTC (permalink / raw)
  To: David Coyle, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, Hemant Agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, Gagandeep Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj,
	Mairtin o Loingsigh

Hi David,

> Subject: [PATCH v3 8/8] doc: add doc updates for DOCSIS security protocol
> 
> Update Security library, AESNI-MB crypto PMD, QAT crypto PMD,
> dpdk-test-crypto-perf tool and release note documentation for DOCSIS
> protocol support.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>

Overall the patches looks good. However, I will do a detailed review soon.

> ---
>  doc/guides/cryptodevs/aesni_mb.rst          |   8 ++
>  doc/guides/cryptodevs/features/aesni_mb.ini |   1 +
>  doc/guides/cryptodevs/features/qat.ini      |   1 +
>  doc/guides/cryptodevs/qat.rst               |   7 ++
>  doc/guides/prog_guide/rte_security.rst      | 114 +++++++++++++++++++-
>  doc/guides/rel_notes/release_20_08.rst      |  16 +++
>  doc/guides/tools/cryptoperf.rst             |   5 +
>  7 files changed, 150 insertions(+), 2 deletions(-)

This patch should be split and merged to relevant other patches in the series.
rte_security related in 1/8
Like aesni-mb related changes should go in 3/8
qat related should be part of 4/8
crypto-perf should be part of 7/8
And release notes should also be split into 3 different entries and squashed into
Rte_security, qat and aesni-mb patches.

<snip>

> +The encryption/decryption is a combination of CBC and CFB modes using either
> AES
> +or DES algorithms as specified in the DOCSIS Security Specification (from DPDK
> +lib_rtecryptodev perspective, these are RTE_CRYPTO_CIPHER_AES_DOCSISBPI
> and
> +RTE_CRYPTO_CIPHER_DES_DOCSISBPI).
> +
> +The CRC is Ethernet CRC-32 as specified in Ethernet/[ISO/IEC 8802-3].
> +
> +.. note::
> +
> +    * The CRC offset and length are specified via the auth offset and
> +      length fields of the rte_crypto_sym_op.

The above note is not correct. It should be
* The offset and length of data for which CRC need to be computed are specified
    via the auth offset and length fields of the rte_crypto_sym_op.

> +    * Other DOCSIS protocol functionality such as Header Checksum (HCS)
> +      calculation may be added in the future.
> +
>  Device Features and Capabilities
>  ---------------------------------
> 

<snip>

> diff --git a/doc/guides/rel_notes/release_20_08.rst
> b/doc/guides/rel_notes/release_20_08.rst
> index 39064afbe..0e72a26b1 100644
> --- a/doc/guides/rel_notes/release_20_08.rst
> +++ b/doc/guides/rel_notes/release_20_08.rst
> @@ -56,6 +56,22 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =========================================================
> 
> +* **Added support for DOCSIS protocol to rte_security.**
> +
> +  Added support for combined crypto and CRC operations for the DOCSIS
> protocol
> +  to ``rte_security``. Test and test-crypto-perf applications have been updated
> +  for unit testing.

Split this release note entry into two, 1 for 1/8 and one for 7/8

> +
> +* **Updated the AESNI MB crypto PMD.**
> +
> +  Added support for lookaside protocol offload for DOCSIS through the
> +  ``rte_security`` API.
> +
> +* **Updated the QuickAssist Technology (QAT) Crypto PMD.**
> +
> +  Added support for lookaside protocol offload for DOCSIS through the
> +  ``rte_security`` API.
> +
> 

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 8/8] doc: add doc updates for DOCSIS security protocol
  2020-06-30 18:33         ` Akhil Goyal
@ 2020-07-01 17:03           ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-07-01 17:03 UTC (permalink / raw)
  To: Akhil Goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, Hemant Agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth,
	Gagandeep Singh, jianjay.zhou, ravi1.kumar, Richardson, Bruce,
	olivier.matz, honnappa.nagarahalli, stephen, alexr, jerinj,
	O'loingsigh, Mairtin

Hi Akhil, thank you for these comments

> 
> This patch should be split and merged to relevant other patches in the series.
> rte_security related in 1/8
> Like aesni-mb related changes should go in 3/8 qat related should be part of
> 4/8 crypto-perf should be part of 7/8 And release notes should also be split
> into 3 different entries and squashed into Rte_security, qat and aesni-mb
> patches.

[DC] I will make this change in v4.
I will wait until there are more comments before submitting v4.

> > +
> > +The CRC is Ethernet CRC-32 as specified in Ethernet/[ISO/IEC 8802-3].
> > +
> > +.. note::
> > +
> > +    * The CRC offset and length are specified via the auth offset and
> > +      length fields of the rte_crypto_sym_op.
> 
> The above note is not correct. It should be
> * The offset and length of data for which CRC need to be computed are
> specified
>     via the auth offset and length fields of the rte_crypto_sym_op.

[DC] Yes, that is a good clarification - I will make that update

> >
> > +* **Added support for DOCSIS protocol to rte_security.**
> > +
> > +  Added support for combined crypto and CRC operations for the DOCSIS
> > protocol
> > +  to ``rte_security``. Test and test-crypto-perf applications have
> > + been updated  for unit testing.
> 
> Split this release note entry into two, 1 for 1/8 and one for 7/8

[DC] I will make this change


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/8] crypto/aesni_mb: add support for DOCSIS protocol
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 3/8] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
@ 2020-07-01 17:04         ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-07-01 17:04 UTC (permalink / raw)
  To: akhil.goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin


> diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
> b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
> index 2d688f4d3..4b25c5e23 100644
> --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
> +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c

<snip>

> @@ -1647,7 +1914,23 @@ cryptodev_aesni_mb_create(const char *name,
>  			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
>  			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
>  			RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
> -			RTE_CRYPTODEV_FF_SYM_SESSIONLESS;
> +			RTE_CRYPTODEV_FF_SYM_SESSIONLESS
> +#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
> +			| RTE_CRYPTODEV_FF_SECURITY
> +#endif
> +			;
> +
> +#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
> +	security_instance = rte_malloc("aesni_mb_sec",
> +				sizeof(struct rte_security_ctx), 0);
> +	if (security_instance == NULL)
> +		AESNI_MB_LOG(ERR, "rte_security_ctx memory alloc
> failed\n");
> +
> +	security_instance->device = (void *)dev;

[DC] Possible NULL pointer dereference here... will fix in v4

> +	security_instance->ops = rte_aesni_mb_pmd_sec_ops;
> +	security_instance->sess_cnt = 0;
> +	dev->security_ctx = security_instance; #endif
> 

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/8] crypto/qat: add support for DOCSIS protocol
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 4/8] crypto/qat: " David Coyle
@ 2020-07-01 17:04         ` Coyle, David
  0 siblings, 0 replies; 92+ messages in thread
From: Coyle, David @ 2020-07-01 17:04 UTC (permalink / raw)
  To: akhil.goyal, Doherty, Declan, De Lara Guarch, Pablo, Trahe,
	Fiona, Zhang, Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin


> diff --git a/drivers/crypto/qat/qat_sym_pmd.c
> b/drivers/crypto/qat/qat_sym_pmd.c
> index e887c880f..711d1585f 100644
> --- a/drivers/crypto/qat/qat_sym_pmd.c
> +++ b/drivers/crypto/qat/qat_sym_pmd.c

<snip>

> @@ -308,7 +346,20 @@ qat_sym_dev_create(struct qat_pci_device
> *qat_pci_dev,
>  			RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
>  			RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
>  			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
> -			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED;
> +			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED |
> +			RTE_CRYPTODEV_FF_SECURITY;
> +
> +#ifdef RTE_LIBRTE_SECURITY
> +	security_instance = rte_malloc("qat_sec",
> +				sizeof(struct rte_security_ctx), 0);
> +	if (security_instance == NULL)
> +		QAT_LOG(ERR, "rte_security_ctx memory alloc failed\n");
> +
> +	security_instance->device = (void *)cryptodev;

[DC] Possible NULL pointer dereference here... will fix in v4

> +	security_instance->ops = &security_qat_ops;
> +	security_instance->sess_cnt = 0;
> +	cryptodev->security_ctx = security_instance; #endif
> 
>  	internals = cryptodev->data->dev_private;
>  	internals->qat_dev = qat_pci_dev;

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/8] security: add support for DOCSIS protocol
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 1/8] security: " David Coyle
@ 2020-07-01 21:41         ` Akhil Goyal
  0 siblings, 0 replies; 92+ messages in thread
From: Akhil Goyal @ 2020-07-01 21:41 UTC (permalink / raw)
  To: David Coyle, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, Hemant Agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, Gagandeep Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj,
	Mairtin o Loingsigh


> 
> Add support for DOCSIS protocol to rte_security library. This support
> currently comprises the combination of Crypto and CRC operations.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> ---
With the documentation comments in the last patch.
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/8] cryptodev: add a note regarding DOCSIS protocol support
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 2/8] cryptodev: add a note regarding DOCSIS protocol support David Coyle
@ 2020-07-01 21:42         ` Akhil Goyal
  0 siblings, 0 replies; 92+ messages in thread
From: Akhil Goyal @ 2020-07-01 21:42 UTC (permalink / raw)
  To: David Coyle, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, Hemant Agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, Gagandeep Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj,
	Mairtin o Loingsigh

> 
> Add a note to the rte_crypto_sym_op->auth.data fields to state that
> for DOCSIS security protocol, these are used to specify the CRC offset
> and length.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> ---
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 5/8] test/crypto: add DOCSIS security test cases
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 5/8] test/crypto: add DOCSIS security test cases David Coyle
@ 2020-07-01 21:43         ` Akhil Goyal
  0 siblings, 0 replies; 92+ messages in thread
From: Akhil Goyal @ 2020-07-01 21:43 UTC (permalink / raw)
  To: David Coyle, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, Hemant Agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, Gagandeep Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj,
	Mairtin o Loingsigh

> 
> Add uplink and downlink DOCSIS unit test cases and vectors, to test
> the combined DOCSIS Crypto-CRC support that has been added to the
> rte_security library.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> ---

Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v3 7/8] app/crypto-perf: add support for DOCSIS protocol
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 7/8] app/crypto-perf: add support for DOCSIS protocol David Coyle
@ 2020-07-01 21:44         ` Akhil Goyal
  0 siblings, 0 replies; 92+ messages in thread
From: Akhil Goyal @ 2020-07-01 21:44 UTC (permalink / raw)
  To: David Coyle, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, Hemant Agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, Gagandeep Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj,
	Mairtin o Loingsigh

> 
> Update test-crypto-perf app to calculate DOCSIS throughput numbers.
> 
> 1 new parameter is added for DOCSIS:
> --docsis-hdr-sz <n>
> 
> ./dpdk-test-crypto-perf -l 3,4 --socket-mem 2048,0
> --vdev crypto_aesni_mb_pmd_1 -n 1 -- --devtype crypto_aesni_mb
> --optype docsis --cipher-algo aes-docsisbpi --cipher-op encrypt
> --cipher-key-sz 16 --cipher-iv-sz 16 --burst-sz 32 --total-ops 20000000
> --buffer-sz 1024 --silent --docsis-hdr-sz 17
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> ---
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

Please do the documentation changes as suggested in the last patch.


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol
  2020-06-30 16:30     ` [dpdk-dev] [PATCH v3 0/8] " David Coyle
                         ` (7 preceding siblings ...)
  2020-06-30 16:30       ` [dpdk-dev] [PATCH v3 8/8] doc: add doc updates for DOCSIS security protocol David Coyle
@ 2020-07-03 12:39       ` David Coyle
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 1/7] security: " David Coyle
                           ` (7 more replies)
  8 siblings, 8 replies; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle

Introduction
============

This patchset adds support for the DOCSIS protocol to the DPDK Security
API (rte_security), to be used by the AESNI-MB and QAT crypto devices to
combine and accelerate Crypto and CRC functions of the DOCSIS protocol
into a single operation.

Performing these functions in parallel as a single operation can enable a
significant performance improvement in a DPDK-based DOCSIS MAC pipeline.


Background
==========

A number of approaches to combine DOCSIS Crypto and CRC functions have
been discussed in the DPDK community to date, namely:
1) adding a new rte_accelerator API, to provide a generic interface for
   combining operations of different types
2) using rawdev through a multi-function interface, again to provide a
   generic interface for combining operations of different types
3) adding support for DOCSIS Crypto-CRC to rte_security

The third option above is the preferred approach for the following
reasons:
- it addresses the immediate use case to add DOCSIS Crypto-CRC support to
  DPDK so that it can be consumed easily by cable equipment vendors
- it uses an already existing framework in DPDK
- it will mean much less code churn in DOCSIS applications, which already
  use rte_cryptodev for encryption/decryption


Use Cases
=========

The primary use case for this proposal has already been mentioned, namely
to add DOCSIS Crypto-CRC support to DPDK:

- DOCSIS MAC: Crypto-CRC
	- Order:
		- Downstream: CRC, Encrypt
		- Upstream: Decrypt, CRC
	- Specifications:
		- Crypto: 128-bit and 256-bit AES-CFB encryption variant
		  for DOCSIS as described in section 11.1 of DOCSIS 3.1
		  Security Specification
		  (https://apps.cablelabs.com/specification/CM-SP-SECv3.1)
		- CRC: Ethernet 32-bit CRC as defined in
		  Ethernet/[ISO/IEC 8802-3]

Note that support for these chained operations is already available in
the Intel IPSec Multi-Buffer library.

However, other DOCSIS protocol functions could be optimized too in the
future using the same rte_security API for DOCSIS (e.g. Header Checksum
(HCS) calculation).

v4:
* addressed Akhil's comments regarding documentation
* made some code fixes
  * fixed possible NULL pointer dereference when allocating security_ctx
    in AESNI-MB and QAT PMDs
  * freed security_ctx memory when exiting AESNI-MB and QAT PMDs
  * added session IOVA verification update when creating security
    sessions in QAT PMD

v3:
* removed rte_security_op definition
  * now using rte_crypto_sym_op->auth.data fields for CRC offset and
    length as suggested by feedback from Akhil and Konstantin
* addressed Pablo's comments
* removed support for out-of-place for DOCSIS protocol from QAT PMD
* updated dpdk-crypto-perf-test tool for DOCSIS
* updated documentation

v2:
* added rte_security and rte_cryptodev code changes
* added AESNI MB crypto PMD code changes
* added QAT SYM crypto PMD code changes
* added crypto unit tests
* added security unit tests

v1:
* added proposed API changes
* added security capabilities to aesni_mb crypto PMD

David Coyle (7):
  security: add support for DOCSIS protocol
  cryptodev: add a note regarding DOCSIS protocol support
  crypto/aesni_mb: add support for DOCSIS protocol
  crypto/qat: add support for DOCSIS protocol
  test/crypto: add DOCSIS security test cases
  test/security: add DOCSIS capability check tests
  app/crypto-perf: add support for DOCSIS protocol

 app/test-crypto-perf/cperf_ops.c              |   82 +-
 app/test-crypto-perf/cperf_options.h          |    5 +-
 app/test-crypto-perf/cperf_options_parsing.c  |   67 +-
 app/test-crypto-perf/cperf_test_throughput.c  |    3 +-
 app/test-crypto-perf/cperf_test_vectors.c     |    3 +-
 app/test-crypto-perf/main.c                   |    5 +-
 app/test-crypto-perf/meson.build              |    2 +-
 app/test/test_cryptodev.c                     |  513 ++++++
 ...t_cryptodev_security_docsis_test_vectors.h | 1544 +++++++++++++++++
 app/test/test_security.c                      |   88 +
 doc/guides/cryptodevs/aesni_mb.rst            |    8 +
 doc/guides/cryptodevs/features/aesni_mb.ini   |    1 +
 doc/guides/cryptodevs/features/qat.ini        |    1 +
 doc/guides/cryptodevs/qat.rst                 |    7 +
 doc/guides/prog_guide/rte_security.rst        |  114 +-
 doc/guides/rel_notes/release_20_08.rst        |   21 +
 doc/guides/tools/cryptoperf.rst               |    5 +
 drivers/common/qat/Makefile                   |    3 +
 .../crypto/aesni_mb/aesni_mb_pmd_private.h    |   19 +-
 drivers/crypto/aesni_mb/meson.build           |    2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c    |  301 +++-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    |  125 ++
 drivers/crypto/qat/meson.build                |    2 +
 drivers/crypto/qat/qat_sym.c                  |   71 +-
 drivers/crypto/qat/qat_sym.h                  |   62 +-
 drivers/crypto/qat/qat_sym_capabilities.h     |   42 +
 drivers/crypto/qat/qat_sym_pmd.c              |   61 +-
 drivers/crypto/qat/qat_sym_pmd.h              |    4 +
 drivers/crypto/qat/qat_sym_session.c          |  153 ++
 drivers/crypto/qat/qat_sym_session.h          |   11 +
 lib/librte_cryptodev/rte_crypto_sym.h         |   14 +
 lib/librte_security/rte_security.c            |    5 +
 lib/librte_security/rte_security.h            |   38 +
 33 files changed, 3348 insertions(+), 34 deletions(-)
 create mode 100644 app/test/test_cryptodev_security_docsis_test_vectors.h

-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 1/7] security: add support for DOCSIS protocol
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
@ 2020-07-03 12:39         ` David Coyle
  2020-07-03 17:50           ` De Lara Guarch, Pablo
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 2/7] cryptodev: add a note regarding DOCSIS protocol support David Coyle
                           ` (6 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support for DOCSIS protocol to rte_security library. This support
currently comprises the combination of Crypto and CRC operations.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
 doc/guides/prog_guide/rte_security.rst | 114 ++++++++++++++++++++++++-
 doc/guides/rel_notes/release_20_08.rst |   5 ++
 lib/librte_security/rte_security.c     |   5 ++
 lib/librte_security/rte_security.h     |  38 +++++++++
 4 files changed, 160 insertions(+), 2 deletions(-)

diff --git a/doc/guides/prog_guide/rte_security.rst b/doc/guides/prog_guide/rte_security.rst
index 9b5d249de..127da2e4f 100644
--- a/doc/guides/prog_guide/rte_security.rst
+++ b/doc/guides/prog_guide/rte_security.rst
@@ -10,8 +10,9 @@ The security library provides a framework for management and provisioning
 of security protocol operations offloaded to hardware based devices. The
 library defines generic APIs to create and free security sessions which can
 support full protocol offload as well as inline crypto operation with
-NIC or crypto devices. The framework currently only supports the IPsec and PDCP
-protocol and associated operations, other protocols will be added in future.
+NIC or crypto devices. The framework currently only supports the IPsec, PDCP
+and DOCSIS protocols and associated operations, other protocols will be added
+in the future.
 
 Design Principles
 -----------------
@@ -296,6 +297,53 @@ Just like IPsec, in case of PDCP also header addition/deletion, cipher/
 de-cipher, integrity protection/verification is done based on the action
 type chosen.
 
+DOCSIS Protocol
+~~~~~~~~~~~~~~~
+
+The Data Over Cable Service Interface Specification (DOCSIS) support comprises
+the combination of encryption/decryption and CRC generation/verification, for
+use in a DOCSIS-MAC pipeline.
+
+.. code-block:: c
+
+
+               Downlink                       Uplink
+               --------                       ------
+
+            Ethernet frame                Ethernet frame
+           from core network              to core network
+                  |                              ^
+                  ~                              |
+                  |                              ~         ----+
+                  V                              |             |
+        +---------|----------+        +----------|---------+   |
+        |   CRC generation   |        |  CRC verification  |   |
+        +---------|----------+        +----------|---------+   |   combined
+                  |                              |             > Crypto + CRC
+        +---------|----------+        +----------|---------+   |
+        |     Encryption     |        |     Decryption     |   |
+        +---------|----------+        +----------|---------+   |
+                  |                              ^             |
+                  ~                              |         ----+
+                  |                              ~
+                  V                              |
+             DOCSIS frame                  DOCSIS frame
+            to Cable Modem               from Cable Modem
+
+The encryption/decryption is a combination of CBC and CFB modes using either AES
+or DES algorithms as specified in the DOCSIS Security Specification (from DPDK
+lib_rtecryptodev perspective, these are RTE_CRYPTO_CIPHER_AES_DOCSISBPI and
+RTE_CRYPTO_CIPHER_DES_DOCSISBPI).
+
+The CRC is Ethernet CRC-32 as specified in Ethernet/[ISO/IEC 8802-3].
+
+.. note::
+
+    * The offset and length of data for which CRC needs to be computed are
+      specified via the auth offset and length fields of the rte_crypto_sym_op.
+    * Other DOCSIS protocol functionality such as Header Checksum (HCS)
+      calculation may be added in the future.
+
 Device Features and Capabilities
 ---------------------------------
 
@@ -408,6 +456,56 @@ PMD which supports the IPsec and PDCP protocol.
         }
     }
 
+Below is an example of the capabilities for a PMD which supports the DOCSIS
+protocol.
+
+.. code-block:: c
+
+    static const struct rte_security_capability pmd_security_capabilities[] = {
+        { /* DOCSIS Uplink */
+                .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+                .protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+                .docsis = {
+                        .direction = RTE_SECURITY_DOCSIS_UPLINK
+                },
+                .crypto_capabilities = pmd_capabilities
+        },
+        { /* DOCSIS Downlink */
+                .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+                .protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+                .docsis = {
+                        .direction = RTE_SECURITY_DOCSIS_DOWNLINK
+                },
+                .crypto_capabilities = pmd_capabilities
+        },
+        {
+                .action = RTE_SECURITY_ACTION_TYPE_NONE
+        }
+    };
+    static const struct rte_cryptodev_capabilities pmd_capabilities[] = {
+        {    /* AES DOCSIS BPI */
+            .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+            .sym = {
+                .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+                .cipher = {
+                    .algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+                    .block_size = 16,
+                    .key_size = {
+                        .min = 16,
+                        .max = 32,
+                        .increment = 16
+                    },
+                    .iv_size = {
+                        .min = 16,
+                        .max = 16,
+                        .increment = 0
+                    }
+                }
+            }
+        },
+
+        RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+    };
 
 Capabilities Discovery
 ~~~~~~~~~~~~~~~~~~~~~~
@@ -491,6 +589,7 @@ Security Session configuration structure is defined as ``rte_security_session_co
                 struct rte_security_ipsec_xform ipsec;
                 struct rte_security_macsec_xform macsec;
                 struct rte_security_pdcp_xform pdcp;
+                struct rte_security_docsis_xform docsis;
         };
         /**< Configuration parameters for security session */
         struct rte_crypto_sym_xform *crypto_xform;
@@ -538,6 +637,8 @@ The ``rte_security_session_protocol`` is defined as
         /**< MACSec Protocol */
         RTE_SECURITY_PROTOCOL_PDCP,
         /**< PDCP Protocol */
+        RTE_SECURITY_PROTOCOL_DOCSIS,
+        /**< DOCSIS Protocol */
     };
 
 Currently the library defines configuration parameters for IPsec and PDCP only.
@@ -594,6 +695,15 @@ PDCP related configuration parameters are defined in ``rte_security_pdcp_xform``
         uint32_t hfn_threshold;
     };
 
+DOCSIS related configuration parameters are defined in ``rte_security_docsis_xform``
+
+.. code-block:: c
+
+    struct rte_security_docsis_xform {
+        enum rte_security_docsis_direction direction;
+        /**< DOCSIS direction */
+    };
+
 
 Security API
 ~~~~~~~~~~~~
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index 5cbc4ce14..13f8f621e 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -56,6 +56,11 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Added support for DOCSIS protocol to rte_security.**
+
+  Added support for combined crypto and CRC operations for the DOCSIS protocol
+  to ``rte_security``.
+
 * **Updated PCAP driver.**
 
   Updated PCAP driver with new features and improvements, including:
diff --git a/lib/librte_security/rte_security.c b/lib/librte_security/rte_security.c
index dc9a3e89c..515c29e04 100644
--- a/lib/librte_security/rte_security.c
+++ b/lib/librte_security/rte_security.c
@@ -173,6 +173,11 @@ rte_security_capability_get(struct rte_security_ctx *instance,
 				if (capability->pdcp.domain ==
 							idx->pdcp.domain)
 					return capability;
+			} else if (idx->protocol ==
+						RTE_SECURITY_PROTOCOL_DOCSIS) {
+				if (capability->docsis.direction ==
+							idx->docsis.direction)
+					return capability;
 			}
 		}
 	}
diff --git a/lib/librte_security/rte_security.h b/lib/librte_security/rte_security.h
index 747830d67..16839e539 100644
--- a/lib/librte_security/rte_security.h
+++ b/lib/librte_security/rte_security.h
@@ -293,6 +293,28 @@ struct rte_security_pdcp_xform {
 	uint32_t hfn_ovrd;
 };
 
+/** DOCSIS direction */
+enum rte_security_docsis_direction {
+	RTE_SECURITY_DOCSIS_UPLINK,
+	/**< Uplink
+	 * - Decryption, followed by CRC Verification
+	 */
+	RTE_SECURITY_DOCSIS_DOWNLINK,
+	/**< Downlink
+	 * - CRC Generation, followed by Encryption
+	 */
+};
+
+/**
+ * DOCSIS security session configuration.
+ *
+ * This structure contains data required to create a DOCSIS security session.
+ */
+struct rte_security_docsis_xform {
+	enum rte_security_docsis_direction direction;
+	/**< DOCSIS direction */
+};
+
 /**
  * Security session action type.
  */
@@ -325,6 +347,8 @@ enum rte_security_session_protocol {
 	/**< MACSec Protocol */
 	RTE_SECURITY_PROTOCOL_PDCP,
 	/**< PDCP Protocol */
+	RTE_SECURITY_PROTOCOL_DOCSIS,
+	/**< DOCSIS Protocol */
 };
 
 /**
@@ -340,6 +364,7 @@ struct rte_security_session_conf {
 		struct rte_security_ipsec_xform ipsec;
 		struct rte_security_macsec_xform macsec;
 		struct rte_security_pdcp_xform pdcp;
+		struct rte_security_docsis_xform docsis;
 	};
 	/**< Configuration parameters for security session */
 	struct rte_crypto_sym_xform *crypto_xform;
@@ -523,6 +548,10 @@ struct rte_security_pdcp_stats {
 	uint64_t reserved;
 };
 
+struct rte_security_docsis_stats {
+	uint64_t reserved;
+};
+
 struct rte_security_stats {
 	enum rte_security_session_protocol protocol;
 	/**< Security protocol to be configured */
@@ -532,6 +561,7 @@ struct rte_security_stats {
 		struct rte_security_macsec_stats macsec;
 		struct rte_security_ipsec_stats ipsec;
 		struct rte_security_pdcp_stats pdcp;
+		struct rte_security_docsis_stats docsis;
 	};
 };
 
@@ -591,6 +621,11 @@ struct rte_security_capability {
 			/**< Capability flags, see RTE_SECURITY_PDCP_* */
 		} pdcp;
 		/**< PDCP capability */
+		struct {
+			enum rte_security_docsis_direction direction;
+			/**< DOCSIS direction */
+		} docsis;
+		/**< DOCSIS capability */
 	};
 
 	const struct rte_cryptodev_capabilities *crypto_capabilities;
@@ -649,6 +684,9 @@ struct rte_security_capability_idx {
 			enum rte_security_pdcp_domain domain;
 			uint32_t capa_flags;
 		} pdcp;
+		struct {
+			enum rte_security_docsis_direction direction;
+		} docsis;
 	};
 };
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 2/7] cryptodev: add a note regarding DOCSIS protocol support
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 1/7] security: " David Coyle
@ 2020-07-03 12:39         ` David Coyle
  2020-07-03 17:56           ` De Lara Guarch, Pablo
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
                           ` (5 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add a note to the rte_crypto_sym_op->auth.data fields to state that
for DOCSIS security protocol, these are used to specify the offset and
length of data over which the CRC is calculated.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
 lib/librte_cryptodev/rte_crypto_sym.h | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/lib/librte_cryptodev/rte_crypto_sym.h b/lib/librte_cryptodev/rte_crypto_sym.h
index da961a19d..f29c98051 100644
--- a/lib/librte_cryptodev/rte_crypto_sym.h
+++ b/lib/librte_cryptodev/rte_crypto_sym.h
@@ -705,6 +705,14 @@ struct rte_crypto_sym_op {
 					  * For KASUMI @ RTE_CRYPTO_AUTH_KASUMI_F9,
 					  * this offset should be such that
 					  * data to authenticate starts at COUNT.
+					  *
+					  * @note
+					  * For DOCSIS security protocol, this
+					  * offset is the DOCSIS header length
+					  * and, therefore, also the CRC offset
+					  * i.e. the number of bytes into the
+					  * packet at which CRC calculation
+					  * should begin.
 					  */
 					uint32_t length;
 					 /**< The message length, in bytes, of the source
@@ -723,6 +731,12 @@ struct rte_crypto_sym_op {
 					  * the length should include the COUNT,
 					  * FRESH, message, direction bit and padding
 					  * (to be multiple of 8 bits).
+					  *
+					  * @note
+					  * For DOCSIS security protocol, this
+					  * is the CRC length i.e. the number of
+					  * bytes in the packet over which the
+					  * CRC should be calculated
 					  */
 				} data;
 				/**< Data offsets and length for authentication */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 1/7] security: " David Coyle
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 2/7] cryptodev: add a note regarding DOCSIS protocol support David Coyle
@ 2020-07-03 12:39         ` David Coyle
  2020-07-03 17:56           ` De Lara Guarch, Pablo
  2020-07-04 19:55           ` Akhil Goyal
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 4/7] crypto/qat: " David Coyle
                           ` (4 subsequent siblings)
  7 siblings, 2 replies; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support to the AESNI-MB PMD for the DOCSIS protocol, through the
rte_security API. This, therefore, includes adding support for the
rte_security API to this PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 doc/guides/cryptodevs/aesni_mb.rst            |   8 +
 doc/guides/cryptodevs/features/aesni_mb.ini   |   1 +
 doc/guides/rel_notes/release_20_08.rst        |   5 +
 .../crypto/aesni_mb/aesni_mb_pmd_private.h    |  19 +-
 drivers/crypto/aesni_mb/meson.build           |   2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c    | 301 +++++++++++++++++-
 .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    | 125 ++++++++
 7 files changed, 454 insertions(+), 7 deletions(-)

diff --git a/doc/guides/cryptodevs/aesni_mb.rst b/doc/guides/cryptodevs/aesni_mb.rst
index cc64f1243..15388d20a 100644
--- a/doc/guides/cryptodevs/aesni_mb.rst
+++ b/doc/guides/cryptodevs/aesni_mb.rst
@@ -55,10 +55,18 @@ AEAD algorithms:
 * RTE_CRYPTO_AEAD_AES_CCM
 * RTE_CRYPTO_AEAD_AES_GCM
 
+Protocol offloads:
+
+* RTE_SECURITY_PROTOCOL_DOCSIS
+
 Limitations
 -----------
 
 * Chained mbufs are not supported.
+* Out-of-place is not supported for combined Crypto-CRC DOCSIS security
+  protocol.
+* RTE_CRYPTO_CIPHER_DES_DOCSISBPI is not supported for combined Crypto-CRC
+  DOCSIS security protocol.
 
 
 Installation
diff --git a/doc/guides/cryptodevs/features/aesni_mb.ini b/doc/guides/cryptodevs/features/aesni_mb.ini
index 49cb82a39..38d255aff 100644
--- a/doc/guides/cryptodevs/features/aesni_mb.ini
+++ b/doc/guides/cryptodevs/features/aesni_mb.ini
@@ -6,6 +6,7 @@
 [Features]
 Symmetric crypto       = Y
 Sym operation chaining = Y
+Protocol offload       = Y
 CPU SSE                = Y
 CPU AVX                = Y
 CPU AVX2               = Y
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index 13f8f621e..19fc043f2 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -96,6 +96,11 @@ New Features
 
   * Added support for DCF datapath configuration.
 
+* **Updated the AESNI MB crypto PMD.**
+
+  Added support for lookaside protocol offload for DOCSIS through the
+  ``rte_security`` API.
+
 * **Added support for BPF_ABS/BPF_IND load instructions.**
 
   Added support for two BPF non-generic instructions:
diff --git a/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h b/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
index 347b4b7e0..e0c7b4f7c 100644
--- a/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
+++ b/drivers/crypto/aesni_mb/aesni_mb_pmd_private.h
@@ -7,6 +7,12 @@
 
 #include <intel-ipsec-mb.h>
 
+#if defined(RTE_LIBRTE_SECURITY) && (IMB_VERSION_NUM) >= IMB_VERSION(0, 54, 0)
+#define AESNI_MB_DOCSIS_SEC_ENABLED 1
+#include <rte_security.h>
+#include <rte_security_driver.h>
+#endif
+
 enum aesni_mb_vector_mode {
 	RTE_AESNI_MB_NOT_SUPPORTED = 0,
 	RTE_AESNI_MB_SSE,
@@ -272,8 +278,19 @@ aesni_mb_set_session_parameters(const MB_MGR *mb_mgr,
 		struct aesni_mb_session *sess,
 		const struct rte_crypto_sym_xform *xform);
 
-/** device specific operations function pointer structure */
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+extern int
+aesni_mb_set_docsis_sec_session_parameters(
+		__rte_unused struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf,
+		void *sess);
+#endif
+
+/** device specific operations function pointer structures */
 extern struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops;
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+extern struct rte_security_ops *rte_aesni_mb_pmd_sec_ops;
+#endif
 
 extern uint32_t
 aesni_mb_cpu_crypto_process_bulk(struct rte_cryptodev *dev,
diff --git a/drivers/crypto/aesni_mb/meson.build b/drivers/crypto/aesni_mb/meson.build
index e557e0103..419b4743f 100644
--- a/drivers/crypto/aesni_mb/meson.build
+++ b/drivers/crypto/aesni_mb/meson.build
@@ -22,4 +22,4 @@ else
 endif
 
 sources = files('rte_aesni_mb_pmd.c', 'rte_aesni_mb_pmd_ops.c')
-deps += ['bus_vdev']
+deps += ['bus_vdev', 'net', 'security']
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 2d688f4d3..59e76fb8e 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -12,6 +12,7 @@
 #include <rte_malloc.h>
 #include <rte_cpuflags.h>
 #include <rte_per_lcore.h>
+#include <rte_ether.h>
 
 #include "aesni_mb_pmd_private.h"
 
@@ -720,6 +721,134 @@ aesni_mb_set_session_parameters(const MB_MGR *mb_mgr,
 	return 0;
 }
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/** Check DOCSIS security session configuration is valid */
+static int
+check_docsis_sec_session(struct rte_security_session_conf *conf)
+{
+	struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
+	struct rte_security_docsis_xform *docsis = &conf->docsis;
+
+	/* Downlink: CRC generate -> Cipher encrypt */
+	if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type ==	RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length == IMB_KEY_AES_128_BYTES ||
+		     crypto_sym->cipher.key.length == IMB_KEY_AES_256_BYTES) &&
+		    crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	/* Uplink: Cipher decrypt -> CRC verify */
+	} else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length == IMB_KEY_AES_128_BYTES ||
+		     crypto_sym->cipher.key.length == IMB_KEY_AES_256_BYTES) &&
+		    crypto_sym->cipher.iv.length == AES_BLOCK_SIZE &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+/** Set DOCSIS security session auth (CRC) parameters */
+static int
+aesni_mb_set_docsis_sec_session_auth_parameters(struct aesni_mb_session *sess,
+		struct rte_security_docsis_xform *xform)
+{
+	if (xform == NULL) {
+		AESNI_MB_LOG(ERR, "Invalid DOCSIS xform");
+		return -EINVAL;
+	}
+
+	/* Select CRC generate/verify */
+	if (xform->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+		sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY;
+	} else if (xform->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+		sess->auth.algo = IMB_AUTH_DOCSIS_CRC32;
+		sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE;
+	} else {
+		AESNI_MB_LOG(ERR, "Unsupported DOCSIS direction");
+		return -ENOTSUP;
+	}
+
+	sess->auth.req_digest_len = RTE_ETHER_CRC_LEN;
+	sess->auth.gen_digest_len = RTE_ETHER_CRC_LEN;
+
+	return 0;
+}
+
+/**
+ * Parse DOCSIS security session configuration and set private session
+ * parameters
+ */
+int
+aesni_mb_set_docsis_sec_session_parameters(
+		__rte_unused struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf,
+		void *sess)
+{
+	struct rte_security_docsis_xform *docsis_xform;
+	struct rte_crypto_sym_xform *cipher_xform;
+	struct aesni_mb_session *aesni_sess = sess;
+	struct aesni_mb_private *internals = dev->data->dev_private;
+	int ret;
+
+	ret = check_docsis_sec_session(conf);
+	if (ret) {
+		AESNI_MB_LOG(ERR, "Unsupported DOCSIS security configuration");
+		return ret;
+	}
+
+	switch (conf->docsis.direction) {
+	case RTE_SECURITY_DOCSIS_UPLINK:
+		aesni_sess->chain_order = IMB_ORDER_CIPHER_HASH;
+		docsis_xform = &conf->docsis;
+		cipher_xform = conf->crypto_xform;
+		break;
+	case RTE_SECURITY_DOCSIS_DOWNLINK:
+		aesni_sess->chain_order = IMB_ORDER_HASH_CIPHER;
+		cipher_xform = conf->crypto_xform;
+		docsis_xform = &conf->docsis;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Default IV length = 0 */
+	aesni_sess->iv.length = 0;
+
+	ret = aesni_mb_set_docsis_sec_session_auth_parameters(aesni_sess,
+			docsis_xform);
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Invalid/unsupported DOCSIS parameters");
+		return -EINVAL;
+	}
+
+	ret = aesni_mb_set_session_cipher_parameters(internals->mb_mgr,
+			aesni_sess, cipher_xform);
+
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Invalid/unsupported cipher parameters");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif
+
 /**
  * burst enqueue, place crypto operations on ingress queue for processing.
  *
@@ -758,6 +887,13 @@ get_session(struct aesni_mb_qp *qp, struct rte_crypto_op *op)
 					get_sym_session_private_data(
 					op->sym->session,
 					cryptodev_driver_id);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	} else if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+		if (likely(op->sym->sec_session != NULL))
+			sess = (struct aesni_mb_session *)
+					get_sec_session_private_data(
+						op->sym->sec_session);
+#endif
 	} else {
 		void *_sess = rte_cryptodev_sym_session_create(qp->sess_mp);
 		void *_sess_private_data = NULL;
@@ -1158,6 +1294,106 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
 	return 0;
 }
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/**
+ * Process a crypto operation containing a security op and complete a
+ * JOB_AES_HMAC job structure for submission to the multi buffer library for
+ * processing.
+ */
+static inline int
+set_sec_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp,
+		struct rte_crypto_op *op, uint8_t *digest_idx)
+{
+	struct rte_mbuf *m_src, *m_dst;
+	struct rte_crypto_sym_op *sym;
+	struct aesni_mb_session *session;
+
+	session = get_session(qp, op);
+	if (unlikely(session == NULL)) {
+		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
+		return -1;
+	}
+
+	/* Only DOCSIS protocol operations supported now */
+	if (session->cipher.mode != IMB_CIPHER_DOCSIS_SEC_BPI ||
+			session->auth.algo != IMB_AUTH_DOCSIS_CRC32) {
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return -1;
+	}
+
+	sym = op->sym;
+	m_src = sym->m_src;
+
+	if (likely(sym->m_dst == NULL || sym->m_dst == m_src)) {
+		/* in-place operation */
+		m_dst = m_src;
+	} else {
+		/* out-of-place operation not supported */
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+		return -ENOTSUP;
+	}
+
+	/* Set crypto operation */
+	job->chain_order = session->chain_order;
+
+	/* Set cipher parameters */
+	job->cipher_direction = session->cipher.direction;
+	job->cipher_mode = session->cipher.mode;
+
+	job->aes_key_len_in_bytes = session->cipher.key_length_in_bytes;
+	job->aes_enc_key_expanded = session->cipher.expanded_aes_keys.encode;
+	job->aes_dec_key_expanded = session->cipher.expanded_aes_keys.decode;
+
+	/* Set IV parameters */
+	job->iv_len_in_bytes = session->iv.length;
+	job->iv = (uint8_t *)op + session->iv.offset;
+
+	/* Set authentication parameters */
+	job->hash_alg = session->auth.algo;
+
+	/* Set digest output location */
+	job->auth_tag_output = qp->temp_digests[*digest_idx];
+	*digest_idx = (*digest_idx + 1) % MAX_JOBS;
+
+	/* Set digest length */
+	job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len;
+
+	/* Set data parameters */
+	job->src = rte_pktmbuf_mtod(m_src, uint8_t *);
+	job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *,
+						sym->cipher.data.offset);
+
+	job->cipher_start_src_offset_in_bytes = sym->cipher.data.offset;
+	job->msg_len_to_cipher_in_bytes = sym->cipher.data.length;
+
+	job->hash_start_src_offset_in_bytes = sym->auth.data.offset;
+	job->msg_len_to_hash_in_bytes = sym->auth.data.length;
+
+	job->user_data = op;
+
+	return 0;
+}
+
+static inline void
+verify_docsis_sec_crc(JOB_AES_HMAC *job, uint8_t *status)
+{
+	uint16_t crc_offset;
+	uint8_t *crc;
+
+	if (!job->msg_len_to_hash_in_bytes)
+		return;
+
+	crc_offset = job->hash_start_src_offset_in_bytes +
+			job->msg_len_to_hash_in_bytes -
+			job->cipher_start_src_offset_in_bytes;
+	crc = job->dst + crc_offset;
+
+	/* Verify CRC (at the end of the message) */
+	if (memcmp(job->auth_tag_output, crc, RTE_ETHER_CRC_LEN) != 0)
+		*status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+}
+#endif
+
 static inline void
 verify_digest(JOB_AES_HMAC *job, void *digest, uint16_t len, uint8_t *status)
 {
@@ -1196,9 +1432,25 @@ static inline struct rte_crypto_op *
 post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)
 {
 	struct rte_crypto_op *op = (struct rte_crypto_op *)job->user_data;
-	struct aesni_mb_session *sess = get_sym_session_private_data(
-							op->sym->session,
-							cryptodev_driver_id);
+	struct aesni_mb_session *sess = NULL;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	uint8_t is_docsis_sec = 0;
+
+	if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+		/*
+		 * Assuming at this point that if it's a security type op, that
+		 * this is for DOCSIS
+		 */
+		is_docsis_sec = 1;
+		sess = get_sec_session_private_data(op->sym->sec_session);
+	} else
+#endif
+	{
+		sess = get_sym_session_private_data(op->sym->session,
+						cryptodev_driver_id);
+	}
+
 	if (unlikely(sess == NULL)) {
 		op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
 		return op;
@@ -1220,6 +1472,11 @@ post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job)
 						op->sym->aead.digest.data,
 						sess->auth.req_digest_len,
 						&op->status);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+				else if (is_docsis_sec)
+					verify_docsis_sec_crc(job,
+						&op->status);
+#endif
 				else
 					verify_digest(job,
 						op->sym->auth.digest.data,
@@ -1382,7 +1639,14 @@ aesni_mb_pmd_dequeue_burst(void *queue_pair, struct rte_crypto_op **ops,
 		if (retval < 0)
 			break;
 
-		retval = set_mb_job_params(job, qp, op, &digest_idx);
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+		if (op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION)
+			retval = set_sec_mb_job_params(job, qp, op,
+						&digest_idx);
+		else
+#endif
+			retval = set_mb_job_params(job, qp, op, &digest_idx);
+
 		if (unlikely(retval != 0)) {
 			qp->stats.dequeue_err_count++;
 			set_job_null_op(job, op);
@@ -1619,6 +1883,9 @@ cryptodev_aesni_mb_create(const char *name,
 	struct aesni_mb_private *internals;
 	enum aesni_mb_vector_mode vector_mode;
 	MB_MGR *mb_mgr;
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	struct rte_security_ctx *security_instance;
+#endif
 
 	dev = rte_cryptodev_pmd_create(name, &vdev->device, init_params);
 	if (dev == NULL) {
@@ -1647,7 +1914,27 @@ cryptodev_aesni_mb_create(const char *name,
 			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
 			RTE_CRYPTODEV_FF_SYM_CPU_CRYPTO |
-			RTE_CRYPTODEV_FF_SYM_SESSIONLESS;
+			RTE_CRYPTODEV_FF_SYM_SESSIONLESS
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+			| RTE_CRYPTODEV_FF_SECURITY
+#endif
+			;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+	security_instance = rte_malloc("aesni_mb_sec",
+				sizeof(struct rte_security_ctx),
+				RTE_CACHE_LINE_SIZE);
+	if (security_instance == NULL) {
+		AESNI_MB_LOG(ERR, "rte_security_ctx memory alloc failed");
+		rte_cryptodev_pmd_destroy(dev);
+		return -ENOMEM;
+	}
+
+	security_instance->device = (void *)dev;
+	security_instance->ops = rte_aesni_mb_pmd_sec_ops;
+	security_instance->sess_cnt = 0;
+	dev->security_ctx = security_instance;
+#endif
 
 	/* Check CPU for support for AES instruction set */
 	if (rte_cpu_get_flag_enabled(RTE_CPUFLAG_AES))
@@ -1726,6 +2013,10 @@ cryptodev_aesni_mb_remove(struct rte_vdev_device *vdev)
 		RTE_PER_LCORE(sync_mb_mgr) = NULL;
 	}
 
+#ifdef RTE_LIBRTE_SECURITYY
+	rte_free(cryptodev->security_ctx);
+#endif
+
 	return rte_cryptodev_pmd_destroy(cryptodev);
 }
 
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
index 8c5e0cd92..ed93daec7 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -7,6 +7,7 @@
 #include <rte_string_fns.h>
 #include <rte_common.h>
 #include <rte_malloc.h>
+#include <rte_ether.h>
 #include <rte_cryptodev_pmd.h>
 
 #include "aesni_mb_pmd_private.h"
@@ -499,6 +500,55 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+static const struct rte_cryptodev_capabilities
+					aesni_mb_pmd_security_crypto_cap[] = {
+	{	/* AES DOCSIS BPI */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		{.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			{.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 16
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}, }
+		}, }
+	},
+
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability aesni_mb_pmd_security_cap[] = {
+	{	/* DOCSIS Uplink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_UPLINK
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{	/* DOCSIS Downlink */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK
+		},
+		.crypto_capabilities = aesni_mb_pmd_security_crypto_cap
+	},
+	{
+		.action = RTE_SECURITY_ACTION_TYPE_NONE
+	}
+};
+#endif
 
 /** Configure device */
 static int
@@ -810,3 +860,78 @@ struct rte_cryptodev_ops aesni_mb_pmd_ops = {
 };
 
 struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops = &aesni_mb_pmd_ops;
+
+#ifdef AESNI_MB_DOCSIS_SEC_ENABLED
+/**
+ * Configure a aesni multi-buffer session from a security session
+ * configuration
+ */
+static int
+aesni_mb_pmd_sec_sess_create(void *dev, struct rte_security_session_conf *conf,
+		struct rte_security_session *sess,
+		struct rte_mempool *mempool)
+{
+	void *sess_private_data;
+	struct rte_cryptodev *cdev = (struct rte_cryptodev *)dev;
+	int ret;
+
+	if (rte_mempool_get(mempool, &sess_private_data)) {
+		AESNI_MB_LOG(ERR, "Couldn't get object from session mempool");
+		return -ENOMEM;
+	}
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_DOCSIS) {
+		AESNI_MB_LOG(ERR, "Invalid security protocol");
+		return -EINVAL;
+	}
+
+	ret = aesni_mb_set_docsis_sec_session_parameters(cdev, conf,
+			sess_private_data);
+
+	if (ret != 0) {
+		AESNI_MB_LOG(ERR, "Failed to configure session parameters");
+
+		/* Return session to mempool */
+		rte_mempool_put(mempool, sess_private_data);
+		return ret;
+	}
+
+	set_sec_session_private_data(sess, sess_private_data);
+
+	return ret;
+}
+
+/** Clear the memory of session so it doesn't leave key material behind */
+static int
+aesni_mb_pmd_sec_sess_destroy(void *dev __rte_unused,
+		struct rte_security_session *sess)
+{
+	void *sess_priv = get_sec_session_private_data(sess);
+
+	if (sess_priv) {
+		struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
+		memset(sess, 0, sizeof(struct aesni_mb_session));
+		set_sec_session_private_data(sess, NULL);
+		rte_mempool_put(sess_mp, sess_priv);
+	}
+	return 0;
+}
+
+/** Get security capabilities for aesni multi-buffer */
+static const struct rte_security_capability *
+aesni_mb_pmd_sec_capa_get(void *device __rte_unused)
+{
+	return aesni_mb_pmd_security_cap;
+}
+
+static struct rte_security_ops aesni_mb_pmd_sec_ops = {
+		.session_create = aesni_mb_pmd_sec_sess_create,
+		.session_update = NULL,
+		.session_stats_get = NULL,
+		.session_destroy = aesni_mb_pmd_sec_sess_destroy,
+		.set_pkt_metadata = NULL,
+		.capabilities_get = aesni_mb_pmd_sec_capa_get
+};
+
+struct rte_security_ops *rte_aesni_mb_pmd_sec_ops = &aesni_mb_pmd_sec_ops;
+#endif
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 4/7] crypto/qat: add support for DOCSIS protocol
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
                           ` (2 preceding siblings ...)
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
@ 2020-07-03 12:39         ` David Coyle
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 5/7] test/crypto: add DOCSIS security test cases David Coyle
                           ` (3 subsequent siblings)
  7 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add support to the QAT SYM PMD for the DOCSIS protocol, through the
rte_security API. This, therefore, includes adding support for the
rte_security API to this PMD.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 doc/guides/cryptodevs/features/qat.ini    |   1 +
 doc/guides/cryptodevs/qat.rst             |   7 +
 doc/guides/rel_notes/release_20_08.rst    |   5 +
 drivers/common/qat/Makefile               |   3 +
 drivers/crypto/qat/meson.build            |   2 +
 drivers/crypto/qat/qat_sym.c              |  71 +++++++++-
 drivers/crypto/qat/qat_sym.h              |  62 ++++++++-
 drivers/crypto/qat/qat_sym_capabilities.h |  42 ++++++
 drivers/crypto/qat/qat_sym_pmd.c          |  61 ++++++++-
 drivers/crypto/qat/qat_sym_pmd.h          |   4 +
 drivers/crypto/qat/qat_sym_session.c      | 153 ++++++++++++++++++++++
 drivers/crypto/qat/qat_sym_session.h      |  11 ++
 12 files changed, 409 insertions(+), 13 deletions(-)

diff --git a/doc/guides/cryptodevs/features/qat.ini b/doc/guides/cryptodevs/features/qat.ini
index a72241997..2d56b187a 100644
--- a/doc/guides/cryptodevs/features/qat.ini
+++ b/doc/guides/cryptodevs/features/qat.ini
@@ -7,6 +7,7 @@
 Symmetric crypto       = Y
 Sym operation chaining = Y
 HW Accelerated         = Y
+Protocol offload       = Y
 In Place SGL           = Y
 OOP SGL In SGL Out     = Y
 OOP SGL In LB  Out     = Y
diff --git a/doc/guides/cryptodevs/qat.rst b/doc/guides/cryptodevs/qat.rst
index c2cc3d5ca..ee873e7b8 100644
--- a/doc/guides/cryptodevs/qat.rst
+++ b/doc/guides/cryptodevs/qat.rst
@@ -76,6 +76,9 @@ Supported AEAD algorithms:
 * ``RTE_CRYPTO_AEAD_AES_GCM``
 * ``RTE_CRYPTO_AEAD_AES_CCM``
 
+Protocol offloads:
+
+* ``RTE_SECURITY_PROTOCOL_DOCSIS``
 
 Supported Chains
 ~~~~~~~~~~~~~~~~
@@ -126,6 +129,10 @@ Limitations
   generations in the same process if planning to use for GCM.
 * The mixed algo feature on GEN2 is not supported by all kernel drivers. Check
   the notes under the Available Kernel Drivers table below for specific details.
+* Out-of-place is not supported for combined Crypto-CRC DOCSIS security
+  protocol.
+* ``RTE_CRYPTO_CIPHER_DES_DOCSISBPI`` is not supported for combined Crypto-CRC
+  DOCSIS security protocol.
 
 Extra notes on KASUMI F9
 ~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index 19fc043f2..4ff7911c0 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -101,6 +101,11 @@ New Features
   Added support for lookaside protocol offload for DOCSIS through the
   ``rte_security`` API.
 
+* **Updated the QuickAssist Technology (QAT) Crypto PMD.**
+
+  Added support for lookaside protocol offload for DOCSIS through the
+  ``rte_security`` API.
+
 * **Added support for BPF_ABS/BPF_IND load instructions.**
 
   Added support for two BPF non-generic instructions:
diff --git a/drivers/common/qat/Makefile b/drivers/common/qat/Makefile
index 28bd5668f..85d420709 100644
--- a/drivers/common/qat/Makefile
+++ b/drivers/common/qat/Makefile
@@ -35,6 +35,9 @@ endif
 ifeq ($(CONFIG_RTE_LIBRTE_PMD_QAT_SYM),y)
 	LDLIBS += -lrte_cryptodev
 	LDLIBS += -lcrypto
+ifeq ($(CONFIG_RTE_LIBRTE_SECURITY),y)
+	LDLIBS += -lrte_net
+endif
 	CFLAGS += -DBUILD_QAT_SYM
 	SRCS-y += qat_sym.c
 	SRCS-y += qat_sym_session.c
diff --git a/drivers/crypto/qat/meson.build b/drivers/crypto/qat/meson.build
index fc65923a7..a225f374a 100644
--- a/drivers/crypto/qat/meson.build
+++ b/drivers/crypto/qat/meson.build
@@ -8,6 +8,8 @@ reason = '' # sentinal value to suppress printout
 dep = dependency('libcrypto', required: false)
 qat_includes += include_directories('.')
 qat_deps += 'cryptodev'
+qat_deps += 'net'
+qat_deps += 'security'
 if dep.found()
 	# Add our sources files to the list
 	qat_sources += files('qat_sym_pmd.c',
diff --git a/drivers/crypto/qat/qat_sym.c b/drivers/crypto/qat/qat_sym.c
index 25b6dd5f4..55251d171 100644
--- a/drivers/crypto/qat/qat_sym.c
+++ b/drivers/crypto/qat/qat_sym.c
@@ -9,6 +9,9 @@
 #include <rte_crypto_sym.h>
 #include <rte_bus_pci.h>
 #include <rte_byteorder.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_net_crc.h>
+#endif
 
 #include "qat_sym.h"
 
@@ -99,6 +102,29 @@ qat_bpicipher_preprocess(struct qat_sym_session *ctx,
 	return sym_op->cipher.data.length - last_block_len;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
+static inline void
+qat_crc_generate(struct qat_sym_session *ctx,
+			struct rte_crypto_op *op)
+{
+	struct rte_crypto_sym_op *sym_op = op->sym;
+	uint32_t *crc, crc_length;
+	uint8_t *crc_data;
+
+	if (ctx->qat_dir == ICP_QAT_HW_CIPHER_ENCRYPT &&
+			sym_op->auth.data.length != 0) {
+
+		crc_length = sym_op->auth.data.length;
+		crc_data = rte_pktmbuf_mtod_offset(sym_op->m_src, uint8_t *,
+				sym_op->auth.data.offset);
+		crc = (uint32_t *)(crc_data + crc_length);
+
+		*crc = rte_net_crc_calc(crc_data, crc_length,
+				RTE_NET_CRC32_ETH);
+	}
+}
+#endif
+
 static inline void
 set_cipher_iv(uint16_t iv_length, uint16_t iv_offset,
 		struct icp_qat_fw_la_cipher_req_params *cipher_param,
@@ -149,7 +175,7 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 		void *op_cookie, enum qat_device_gen qat_dev_gen)
 {
 	int ret = 0;
-	struct qat_sym_session *ctx;
+	struct qat_sym_session *ctx = NULL;
 	struct icp_qat_fw_la_cipher_req_params *cipher_param;
 	struct icp_qat_fw_la_auth_req_params *auth_param;
 	register struct icp_qat_fw_la_bulk_req *qat_req;
@@ -161,6 +187,7 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 	uint64_t auth_data_end = 0;
 	uint8_t do_sgl = 0;
 	uint8_t in_place = 1;
+	uint8_t is_docsis_sec = 0;
 	int alignment_adjustment = 0;
 	struct rte_crypto_op *op = (struct rte_crypto_op *)in_op;
 	struct qat_sym_op_cookie *cookie =
@@ -177,11 +204,23 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 		QAT_DP_LOG(ERR, "QAT PMD only supports session oriented"
 				" requests, op (%p) is sessionless.", op);
 		return -EINVAL;
+	} else if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
+		ctx = (struct qat_sym_session *)get_sym_session_private_data(
+				op->sym->session, cryptodev_qat_driver_id);
+#ifdef RTE_LIBRTE_SECURITY
+	} else {
+		ctx = (struct qat_sym_session *)get_sec_session_private_data(
+				op->sym->sec_session);
+		if (ctx && ctx->bpi_ctx == NULL) {
+			QAT_DP_LOG(ERR, "QAT PMD only supports security"
+					" operation requests for DOCSIS, op"
+					" (%p) is not for DOCSIS.", op);
+			return -EINVAL;
+		}
+		is_docsis_sec = 1;
+#endif
 	}
 
-	ctx = (struct qat_sym_session *)get_sym_session_private_data(
-			op->sym->session, cryptodev_qat_driver_id);
-
 	if (unlikely(ctx == NULL)) {
 		QAT_DP_LOG(ERR, "Session was not created for this device");
 		return -EINVAL;
@@ -242,7 +281,29 @@ qat_sym_build_request(void *in_op, uint8_t *out_msg,
 			cipher_ofs = op->sym->cipher.data.offset >> 3;
 
 		} else if (ctx->bpi_ctx) {
-			/* DOCSIS - only send complete blocks to device
+			/* DOCSIS processing */
+#ifdef RTE_LIBRTE_SECURITY
+			if (is_docsis_sec) {
+				/* Check for OOP */
+				if (unlikely((op->sym->m_dst != NULL) &&
+						(op->sym->m_dst !=
+						op->sym->m_src))) {
+					QAT_DP_LOG(ERR,
+						"OOP not supported for DOCSIS "
+						"security");
+					op->status =
+					RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
+					return -EINVAL;
+				}
+
+				/* Calculate CRC */
+				qat_crc_generate(ctx, op);
+			}
+#else
+			RTE_SET_USED(is_docsis_sec);
+#endif
+
+			/* Only send complete blocks to device.
 			 * Process any partial block using CFB mode.
 			 * Even if 0 complete blocks, still send this to device
 			 * to get into rx queue for post-process and dequeuing
diff --git a/drivers/crypto/qat/qat_sym.h b/drivers/crypto/qat/qat_sym.h
index bc6426c32..02e72391d 100644
--- a/drivers/crypto/qat/qat_sym.h
+++ b/drivers/crypto/qat/qat_sym.h
@@ -6,6 +6,9 @@
 #define _QAT_SYM_H_
 
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_net_crc.h>
+#endif
 
 #ifdef BUILD_QAT_SYM
 #include <openssl/evp.h>
@@ -132,14 +135,38 @@ qat_bpicipher_postprocess(struct qat_sym_session *ctx,
 	return sym_op->cipher.data.length - last_block_len;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
 static inline void
-qat_sym_process_response(void **op, uint8_t *resp)
+qat_crc_verify(struct qat_sym_session *ctx, struct rte_crypto_op *op)
 {
+	struct rte_crypto_sym_op *sym_op = op->sym;
+	uint32_t crc_offset, crc_length, crc;
+	uint8_t *crc_data;
+
+	if (ctx->qat_dir == ICP_QAT_HW_CIPHER_DECRYPT &&
+			sym_op->auth.data.length != 0) {
+
+		crc_offset = sym_op->auth.data.offset;
+		crc_length = sym_op->auth.data.length;
+		crc_data = rte_pktmbuf_mtod_offset(sym_op->m_src, uint8_t *,
+				crc_offset);
 
+		crc = rte_net_crc_calc(crc_data, crc_length, RTE_NET_CRC32_ETH);
+
+		if (crc != *(uint32_t *)(crc_data + crc_length))
+			op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
+	}
+}
+#endif
+
+static inline void
+qat_sym_process_response(void **op, uint8_t *resp)
+{
 	struct icp_qat_fw_comn_resp *resp_msg =
 			(struct icp_qat_fw_comn_resp *)resp;
 	struct rte_crypto_op *rx_op = (struct rte_crypto_op *)(uintptr_t)
 			(resp_msg->opaque_data);
+	struct qat_sym_session *sess;
 
 #if RTE_LOG_DP_LEVEL >= RTE_LOG_DEBUG
 	QAT_DP_HEXDUMP_LOG(DEBUG, "qat_response:", (uint8_t *)resp_msg,
@@ -152,15 +179,36 @@ qat_sym_process_response(void **op, uint8_t *resp)
 
 		rx_op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
 	} else {
-		struct qat_sym_session *sess = (struct qat_sym_session *)
-						get_sym_session_private_data(
-						rx_op->sym->session,
-						cryptodev_qat_driver_id);
+#ifdef RTE_LIBRTE_SECURITY
+		uint8_t is_docsis_sec = 0;
+
+		if (rx_op->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
+			/*
+			 * Assuming at this point that if it's a security
+			 * op, that this is for DOCSIS
+			 */
+			sess = (struct qat_sym_session *)
+					get_sec_session_private_data(
+					rx_op->sym->sec_session);
+			is_docsis_sec = 1;
+		} else
+#endif
+		{
+			sess = (struct qat_sym_session *)
+					get_sym_session_private_data(
+					rx_op->sym->session,
+					cryptodev_qat_driver_id);
+		}
 
+		rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
 
-		if (sess->bpi_ctx)
+		if (sess->bpi_ctx) {
 			qat_bpicipher_postprocess(sess, rx_op);
-		rx_op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
+#ifdef RTE_LIBRTE_SECURITY
+			if (is_docsis_sec)
+				qat_crc_verify(sess, rx_op);
+#endif
+		}
 	}
 	*op = (void *)rx_op;
 }
diff --git a/drivers/crypto/qat/qat_sym_capabilities.h b/drivers/crypto/qat/qat_sym_capabilities.h
index ff691ce35..7b8b13b4f 100644
--- a/drivers/crypto/qat/qat_sym_capabilities.h
+++ b/drivers/crypto/qat/qat_sym_capabilities.h
@@ -699,4 +699,46 @@
 		}, }							\
 	}
 
+#ifdef RTE_LIBRTE_SECURITY
+#define QAT_SECURITY_SYM_CAPABILITIES					\
+	{	/* AES DOCSIS BPI */					\
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,			\
+		{.sym = {						\
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,	\
+			{.cipher = {					\
+				.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI,\
+				.block_size = 16,			\
+				.key_size = {				\
+					.min = 16,			\
+					.max = 32,			\
+					.increment = 16			\
+				},					\
+				.iv_size = {				\
+					.min = 16,			\
+					.max = 16,			\
+					.increment = 0			\
+				}					\
+			}, }						\
+		}, }							\
+	}
+
+#define QAT_SECURITY_CAPABILITIES(sym)					\
+	[0] = {	/* DOCSIS Uplink */					\
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,	\
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,		\
+		.docsis = {						\
+			.direction = RTE_SECURITY_DOCSIS_UPLINK		\
+		},							\
+		.crypto_capabilities = (sym)				\
+	},								\
+	[1] = {	/* DOCSIS Downlink */					\
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,	\
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,		\
+		.docsis = {						\
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK	\
+		},							\
+		.crypto_capabilities = (sym)				\
+	}
+#endif
+
 #endif /* _QAT_SYM_CAPABILITIES_H_ */
diff --git a/drivers/crypto/qat/qat_sym_pmd.c b/drivers/crypto/qat/qat_sym_pmd.c
index e887c880f..1561752b8 100644
--- a/drivers/crypto/qat/qat_sym_pmd.c
+++ b/drivers/crypto/qat/qat_sym_pmd.c
@@ -8,6 +8,9 @@
 #include <rte_malloc.h>
 #include <rte_pci.h>
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security_driver.h>
+#endif
 
 #include "qat_logs.h"
 #include "qat_sym.h"
@@ -29,6 +32,21 @@ static const struct rte_cryptodev_capabilities qat_gen2_sym_capabilities[] = {
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
 
+#ifdef RTE_LIBRTE_SECURITY
+static const struct rte_cryptodev_capabilities
+					qat_security_sym_capabilities[] = {
+	QAT_SECURITY_SYM_CAPABILITIES,
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+static const struct rte_security_capability qat_security_capabilities[] = {
+	QAT_SECURITY_CAPABILITIES(qat_security_sym_capabilities),
+	{
+		.action = RTE_SECURITY_ACTION_TYPE_NONE
+	}
+};
+#endif
+
 static int qat_sym_qp_release(struct rte_cryptodev *dev,
 	uint16_t queue_pair_id);
 
@@ -237,6 +255,24 @@ static struct rte_cryptodev_ops crypto_qat_ops = {
 		.sym_session_clear	= qat_sym_session_clear
 };
 
+#ifdef RTE_LIBRTE_SECURITY
+static const struct rte_security_capability *
+qat_security_cap_get(void *device __rte_unused)
+{
+	return qat_security_capabilities;
+}
+
+static struct rte_security_ops security_qat_ops = {
+
+		.session_create = qat_security_session_create,
+		.session_update = NULL,
+		.session_stats_get = NULL,
+		.session_destroy = qat_security_session_destroy,
+		.set_pkt_metadata = NULL,
+		.capabilities_get = qat_security_cap_get
+};
+#endif
+
 static uint16_t
 qat_sym_pmd_enqueue_op_burst(void *qp, struct rte_crypto_op **ops,
 		uint16_t nb_ops)
@@ -276,6 +312,9 @@ qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
 	char name[RTE_CRYPTODEV_NAME_MAX_LEN];
 	struct rte_cryptodev *cryptodev;
 	struct qat_sym_dev_private *internals;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_ctx *security_instance;
+#endif
 
 	snprintf(name, RTE_CRYPTODEV_NAME_MAX_LEN, "%s_%s",
 			qat_pci_dev->name, "sym");
@@ -308,7 +347,24 @@ qat_sym_dev_create(struct qat_pci_device *qat_pci_dev,
 			RTE_CRYPTODEV_FF_OOP_SGL_IN_LB_OUT |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_SGL_OUT |
 			RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
-			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED;
+			RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED |
+			RTE_CRYPTODEV_FF_SECURITY;
+
+#ifdef RTE_LIBRTE_SECURITY
+	security_instance = rte_malloc("qat_sec",
+				sizeof(struct rte_security_ctx),
+				RTE_CACHE_LINE_SIZE);
+	if (security_instance == NULL) {
+		QAT_LOG(ERR, "rte_security_ctx memory alloc failed");
+		rte_cryptodev_pmd_destroy(cryptodev);
+		return -ENOMEM;
+	}
+
+	security_instance->device = (void *)cryptodev;
+	security_instance->ops = &security_qat_ops;
+	security_instance->sess_cnt = 0;
+	cryptodev->security_ctx = security_instance;
+#endif
 
 	internals = cryptodev->data->dev_private;
 	internals->qat_dev = qat_pci_dev;
@@ -357,6 +413,9 @@ qat_sym_dev_destroy(struct qat_pci_device *qat_pci_dev)
 
 	/* free crypto device */
 	cryptodev = rte_cryptodev_pmd_get_dev(qat_pci_dev->sym_dev->sym_dev_id);
+#ifdef RTE_LIBRTE_SECURITY
+	rte_free(cryptodev->security_ctx);
+#endif
 	rte_cryptodev_pmd_destroy(cryptodev);
 	qat_pci_dev->sym_rte_dev.name = NULL;
 	qat_pci_dev->sym_dev = NULL;
diff --git a/drivers/crypto/qat/qat_sym_pmd.h b/drivers/crypto/qat/qat_sym_pmd.h
index a5a31e512..c625fef4a 100644
--- a/drivers/crypto/qat/qat_sym_pmd.h
+++ b/drivers/crypto/qat/qat_sym_pmd.h
@@ -7,7 +7,11 @@
 
 #ifdef BUILD_QAT_SYM
 
+#include <rte_ether.h>
 #include <rte_cryptodev.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_sym_capabilities.h"
 #include "qat_device.h"
diff --git a/drivers/crypto/qat/qat_sym_session.c b/drivers/crypto/qat/qat_sym_session.c
index 11b459ee8..c7c2d36c1 100644
--- a/drivers/crypto/qat/qat_sym_session.c
+++ b/drivers/crypto/qat/qat_sym_session.c
@@ -14,6 +14,9 @@
 #include <rte_log.h>
 #include <rte_malloc.h>
 #include <rte_crypto_sym.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_logs.h"
 #include "qat_sym_session.h"
@@ -2100,3 +2103,153 @@ int qat_sym_validate_zuc_key(int key_len, enum icp_qat_hw_cipher_algo *alg)
 	}
 	return 0;
 }
+
+#ifdef RTE_LIBRTE_SECURITY
+static int
+qat_sec_session_check_docsis(struct rte_security_session_conf *conf)
+{
+	struct rte_crypto_sym_xform *crypto_sym = conf->crypto_xform;
+	struct rte_security_docsis_xform *docsis = &conf->docsis;
+
+	/* CRC generate -> Cipher encrypt */
+	if (docsis->direction == RTE_SECURITY_DOCSIS_DOWNLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_128_KEY_SZ ||
+		     crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_256_KEY_SZ) &&
+		    crypto_sym->cipher.iv.length == ICP_QAT_HW_AES_BLK_SZ &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	/* Cipher decrypt -> CRC verify */
+	} else if (docsis->direction == RTE_SECURITY_DOCSIS_UPLINK) {
+
+		if (crypto_sym != NULL &&
+		    crypto_sym->type == RTE_CRYPTO_SYM_XFORM_CIPHER &&
+		    crypto_sym->cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT &&
+		    crypto_sym->cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI &&
+		    (crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_128_KEY_SZ ||
+		     crypto_sym->cipher.key.length ==
+					ICP_QAT_HW_AES_256_KEY_SZ) &&
+		    crypto_sym->cipher.iv.length == ICP_QAT_HW_AES_BLK_SZ &&
+		    crypto_sym->next == NULL) {
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int
+qat_sec_session_set_docsis_parameters(struct rte_cryptodev *dev,
+		struct rte_security_session_conf *conf, void *session_private)
+{
+	int ret;
+	int qat_cmd_id;
+	struct rte_crypto_sym_xform *xform = NULL;
+	struct qat_sym_session *session = session_private;
+
+	ret = qat_sec_session_check_docsis(conf);
+	if (ret) {
+		QAT_LOG(ERR, "Unsupported DOCSIS security configuration");
+		return ret;
+	}
+
+	xform = conf->crypto_xform;
+
+	/* Verify the session physical address is known */
+	rte_iova_t session_paddr = rte_mempool_virt2iova(session);
+	if (session_paddr == 0 || session_paddr == RTE_BAD_IOVA) {
+		QAT_LOG(ERR,
+			"Session physical address unknown. Bad memory pool.");
+		return -EINVAL;
+	}
+
+	/* Set context descriptor physical address */
+	session->cd_paddr = session_paddr +
+			offsetof(struct qat_sym_session, cd);
+
+	session->min_qat_dev_gen = QAT_GEN1;
+
+	/* Get requested QAT command id */
+	qat_cmd_id = qat_get_cmd_id(xform);
+	if (qat_cmd_id < 0 || qat_cmd_id >= ICP_QAT_FW_LA_CMD_DELIMITER) {
+		QAT_LOG(ERR, "Unsupported xform chain requested");
+		return -ENOTSUP;
+	}
+	session->qat_cmd = (enum icp_qat_fw_la_cmd_id)qat_cmd_id;
+	switch (session->qat_cmd) {
+	case ICP_QAT_FW_LA_CMD_CIPHER:
+		ret = qat_sym_session_configure_cipher(dev, xform, session);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+		QAT_LOG(ERR, "Unsupported Service %u", session->qat_cmd);
+		return -ENOTSUP;
+	}
+
+	return 0;
+}
+
+int
+qat_security_session_create(void *dev,
+				struct rte_security_session_conf *conf,
+				struct rte_security_session *sess,
+				struct rte_mempool *mempool)
+{
+	void *sess_private_data;
+	struct rte_cryptodev *cdev = (struct rte_cryptodev *)dev;
+	int ret;
+
+	if (rte_mempool_get(mempool, &sess_private_data)) {
+		QAT_LOG(ERR, "Couldn't get object from session mempool");
+		return -ENOMEM;
+	}
+
+	if (conf->protocol != RTE_SECURITY_PROTOCOL_DOCSIS) {
+		QAT_LOG(ERR, "Invalid security protocol");
+		return -EINVAL;
+	}
+
+	ret = qat_sec_session_set_docsis_parameters(cdev, conf,
+			sess_private_data);
+	if (ret != 0) {
+		QAT_LOG(ERR, "Failed to configure session parameters");
+		/* Return session to mempool */
+		rte_mempool_put(mempool, sess_private_data);
+		return ret;
+	}
+
+	set_sec_session_private_data(sess, sess_private_data);
+
+	return ret;
+}
+
+int
+qat_security_session_destroy(void *dev __rte_unused,
+				 struct rte_security_session *sess)
+{
+	void *sess_priv = get_sec_session_private_data(sess);
+	struct qat_sym_session *s = (struct qat_sym_session *)sess_priv;
+
+	if (sess_priv) {
+		if (s->bpi_ctx)
+			bpi_cipher_ctx_free(s->bpi_ctx);
+		memset(s, 0, qat_sym_session_get_private_size(dev));
+		struct rte_mempool *sess_mp = rte_mempool_from_obj(sess_priv);
+
+		set_sec_session_private_data(sess, NULL);
+		rte_mempool_put(sess_mp, sess_priv);
+	}
+	return 0;
+}
+#endif
diff --git a/drivers/crypto/qat/qat_sym_session.h b/drivers/crypto/qat/qat_sym_session.h
index e6538f627..9f1033baf 100644
--- a/drivers/crypto/qat/qat_sym_session.h
+++ b/drivers/crypto/qat/qat_sym_session.h
@@ -6,6 +6,9 @@
 
 #include <rte_crypto.h>
 #include <rte_cryptodev_pmd.h>
+#ifdef RTE_LIBRTE_SECURITY
+#include <rte_security.h>
+#endif
 
 #include "qat_common.h"
 #include "icp_qat_hw.h"
@@ -156,4 +159,12 @@ qat_cipher_get_block_size(enum icp_qat_hw_cipher_algo qat_cipher_alg);
 int
 qat_sym_validate_zuc_key(int key_len, enum icp_qat_hw_cipher_algo *alg);
 
+#ifdef RTE_LIBRTE_SECURITY
+int
+qat_security_session_create(void *dev, struct rte_security_session_conf *conf,
+		struct rte_security_session *sess, struct rte_mempool *mempool);
+int
+qat_security_session_destroy(void *dev, struct rte_security_session *sess);
+#endif
+
 #endif /* _QAT_SYM_SESSION_H_ */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 5/7] test/crypto: add DOCSIS security test cases
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
                           ` (3 preceding siblings ...)
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 4/7] crypto/qat: " David Coyle
@ 2020-07-03 12:39         ` David Coyle
  2020-07-03 17:56           ` De Lara Guarch, Pablo
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 6/7] test/security: add DOCSIS capability check tests David Coyle
                           ` (2 subsequent siblings)
  7 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add uplink and downlink DOCSIS unit test cases and vectors, to test
the combined DOCSIS Crypto-CRC support that has been added to the
rte_security library.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
 app/test/test_cryptodev.c                     |  513 ++++++
 ...t_cryptodev_security_docsis_test_vectors.h | 1544 +++++++++++++++++
 2 files changed, 2057 insertions(+)
 create mode 100644 app/test/test_cryptodev_security_docsis_test_vectors.h

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 8f631468b..d11f60f3f 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -11,6 +11,7 @@
 #include <rte_memcpy.h>
 #include <rte_pause.h>
 #include <rte_bus_vdev.h>
+#include <rte_ether.h>
 
 #include <rte_crypto.h>
 #include <rte_cryptodev.h>
@@ -42,6 +43,7 @@
 #ifdef RTE_LIBRTE_SECURITY
 #include "test_cryptodev_security_pdcp_test_vectors.h"
 #include "test_cryptodev_security_pdcp_test_func.h"
+#include "test_cryptodev_security_docsis_test_vectors.h"
 #endif
 
 #define VDEV_ARGS_SIZE 100
@@ -72,6 +74,9 @@ struct crypto_unittest_params {
 	struct rte_crypto_sym_xform cipher_xform;
 	struct rte_crypto_sym_xform auth_xform;
 	struct rte_crypto_sym_xform aead_xform;
+#ifdef RTE_LIBRTE_SECURITY
+	struct rte_security_docsis_xform docsis_xform;
+#endif
 
 	union {
 		struct rte_cryptodev_sym_session *sess;
@@ -7067,6 +7072,34 @@ test_authenticated_encryption(const struct aead_test_data *tdata)
 }
 
 #ifdef RTE_LIBRTE_SECURITY
+static int
+security_proto_supported(enum rte_security_session_protocol proto)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+
+	const struct rte_security_capability *capabilities;
+	const struct rte_security_capability *capability;
+	uint16_t i = 0;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+				rte_cryptodev_get_sec_ctx(
+				ts_params->valid_devs[0]);
+
+
+	capabilities = rte_security_capabilities_get(ctx);
+
+	if (capabilities == NULL)
+		return -ENOTSUP;
+
+	while ((capability = &capabilities[i++])->action !=
+			RTE_SECURITY_ACTION_TYPE_NONE) {
+		if (capability->protocol == proto)
+			return 0;
+	}
+
+	return -ENOTSUP;
+}
+
 /* Basic algorithm run function for async inplace mode.
  * Creates a session from input parameters and runs one operation
  * on input_vec. Checks the output of the crypto operation against
@@ -7670,6 +7703,9 @@ test_PDCP_PROTO_all(void)
 	if (!(feat_flags & RTE_CRYPTODEV_FF_SECURITY))
 		return -ENOTSUP;
 
+	if (security_proto_supported(RTE_SECURITY_PROTOCOL_PDCP) < 0)
+		return -ENOTSUP;
+
 	status = test_PDCP_PROTO_cplane_encap_all();
 	status += test_PDCP_PROTO_cplane_decap_all();
 	status += test_PDCP_PROTO_uplane_encap_all();
@@ -7684,6 +7720,481 @@ test_PDCP_PROTO_all(void)
 	else
 		return TEST_SUCCESS;
 }
+
+static int
+test_docsis_proto_uplink(int i, struct docsis_test_data *d_td)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	uint8_t *plaintext, *ciphertext;
+	uint8_t *iv_ptr;
+	int32_t cipher_len, crc_len;
+	uint32_t crc_data_len;
+	int ret = TEST_SUCCESS;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(
+						ts_params->valid_devs[0]);
+
+	/* Verify the capabilities */
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	const struct rte_cryptodev_capabilities *crypto_cap;
+	const struct rte_cryptodev_symmetric_capability *sym_cap;
+	int j = 0;
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_DOCSIS;
+	sec_cap_idx.docsis.direction = RTE_SECURITY_DOCSIS_UPLINK;
+
+	sec_cap = rte_security_capability_get(ctx, &sec_cap_idx);
+	if (sec_cap == NULL)
+		return -ENOTSUP;
+
+	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+				crypto_cap->sym.xform_type ==
+					RTE_CRYPTO_SYM_XFORM_CIPHER &&
+				crypto_cap->sym.cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI) {
+			sym_cap = &crypto_cap->sym;
+			if (rte_cryptodev_sym_capability_check_cipher(sym_cap,
+						d_td->key.len,
+						d_td->iv.len) == 0)
+				break;
+		}
+	}
+
+	if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED)
+		return -ENOTSUP;
+
+	/* Setup source mbuf payload */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+			rte_pktmbuf_tailroom(ut_params->ibuf));
+
+	ciphertext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+			d_td->ciphertext.len);
+
+	memcpy(ciphertext, d_td->ciphertext.data, d_td->ciphertext.len);
+
+	/* Set session action type */
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	/* Setup cipher session parameters */
+	ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+	ut_params->cipher_xform.cipher.key.data = d_td->key.data;
+	ut_params->cipher_xform.cipher.key.length = d_td->key.len;
+	ut_params->cipher_xform.cipher.iv.length = d_td->iv.len;
+	ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+	ut_params->cipher_xform.next = NULL;
+
+	/* Setup DOCSIS session parameters */
+	ut_params->docsis_xform.direction = RTE_SECURITY_DOCSIS_UPLINK;
+
+	struct rte_security_session_conf sess_conf = {
+		.action_type = ut_params->type,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = ut_params->docsis_xform,
+		.crypto_xform = &ut_params->cipher_xform,
+	};
+
+	/* Create security session */
+	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
+					ts_params->session_priv_mpool);
+
+	if (!ut_params->sec_session) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "failed to allocate session");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Generate crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+				RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!ut_params->op) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to allocate symmetric crypto operation");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Setup CRC operation parameters */
+	crc_len = d_td->ciphertext.no_crc == false ?
+			(d_td->ciphertext.len -
+				d_td->ciphertext.crc_offset -
+				RTE_ETHER_CRC_LEN) :
+			0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	crc_data_len = crc_len == 0 ? 0 : RTE_ETHER_CRC_LEN;
+	ut_params->op->sym->auth.data.length = crc_len;
+	ut_params->op->sym->auth.data.offset = d_td->ciphertext.crc_offset;
+
+	/* Setup cipher operation parameters */
+	cipher_len = d_td->ciphertext.no_cipher == false ?
+			(d_td->ciphertext.len -
+				d_td->ciphertext.cipher_offset) :
+			0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	ut_params->op->sym->cipher.data.length = cipher_len;
+	ut_params->op->sym->cipher.data.offset = d_td->ciphertext.cipher_offset;
+
+	/* Setup cipher IV */
+	iv_ptr = (uint8_t *)ut_params->op + IV_OFFSET;
+	rte_memcpy(iv_ptr, d_td->iv.data, d_td->iv.len);
+
+	/* Attach session to operation */
+	rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+	/* Set crypto operation mbufs */
+	ut_params->op->sym->m_src = ut_params->ibuf;
+	ut_params->op->sym->m_dst = NULL;
+
+	/* Process crypto operation */
+	if (process_crypto_request(ts_params->valid_devs[0], ut_params->op) ==
+			NULL) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to process security crypto op");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "crypto op processing failed");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Validate plaintext */
+	plaintext = ciphertext;
+
+	if (memcmp(plaintext, d_td->plaintext.data,
+			d_td->plaintext.len - crc_data_len)) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "plaintext not as expected\n");
+		rte_hexdump(stdout, "expected", d_td->plaintext.data,
+				d_td->plaintext.len);
+		rte_hexdump(stdout, "actual", plaintext, d_td->plaintext.len);
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+on_err:
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	if (ut_params->sec_session)
+		rte_security_session_destroy(ctx, ut_params->sec_session);
+	ut_params->sec_session = NULL;
+
+	rte_pktmbuf_free(ut_params->ibuf);
+	ut_params->ibuf = NULL;
+
+	return ret;
+}
+
+static int
+test_docsis_proto_downlink(int i, struct docsis_test_data *d_td)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+	uint8_t *plaintext, *ciphertext;
+	uint8_t *iv_ptr;
+	int32_t cipher_len, crc_len;
+	int ret = TEST_SUCCESS;
+
+	struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(
+						ts_params->valid_devs[0]);
+
+	/* Verify the capabilities */
+	struct rte_security_capability_idx sec_cap_idx;
+	const struct rte_security_capability *sec_cap;
+	const struct rte_cryptodev_capabilities *crypto_cap;
+	const struct rte_cryptodev_symmetric_capability *sym_cap;
+	int j = 0;
+
+	sec_cap_idx.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+	sec_cap_idx.protocol = RTE_SECURITY_PROTOCOL_DOCSIS;
+	sec_cap_idx.docsis.direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+
+	sec_cap = rte_security_capability_get(ctx, &sec_cap_idx);
+	if (sec_cap == NULL)
+		return -ENOTSUP;
+
+	while ((crypto_cap = &sec_cap->crypto_capabilities[j++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_SYMMETRIC &&
+				crypto_cap->sym.xform_type ==
+					RTE_CRYPTO_SYM_XFORM_CIPHER &&
+				crypto_cap->sym.cipher.algo ==
+					RTE_CRYPTO_CIPHER_AES_DOCSISBPI) {
+			sym_cap = &crypto_cap->sym;
+			if (rte_cryptodev_sym_capability_check_cipher(sym_cap,
+						d_td->key.len,
+						d_td->iv.len) == 0)
+				break;
+		}
+	}
+
+	if (crypto_cap->op == RTE_CRYPTO_OP_TYPE_UNDEFINED)
+		return -ENOTSUP;
+
+	/* Setup source mbuf payload */
+	ut_params->ibuf = rte_pktmbuf_alloc(ts_params->mbuf_pool);
+	memset(rte_pktmbuf_mtod(ut_params->ibuf, uint8_t *), 0,
+			rte_pktmbuf_tailroom(ut_params->ibuf));
+
+	plaintext = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+			d_td->plaintext.len);
+
+	memcpy(plaintext, d_td->plaintext.data, d_td->plaintext.len);
+
+	/* Set session action type */
+	ut_params->type = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL;
+
+	/* Setup cipher session parameters */
+	ut_params->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_DOCSISBPI;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+	ut_params->cipher_xform.cipher.key.data = d_td->key.data;
+	ut_params->cipher_xform.cipher.key.length = d_td->key.len;
+	ut_params->cipher_xform.cipher.iv.length = d_td->iv.len;
+	ut_params->cipher_xform.cipher.iv.offset = IV_OFFSET;
+	ut_params->cipher_xform.next = NULL;
+
+	/* Setup DOCSIS session parameters */
+	ut_params->docsis_xform.direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+
+	struct rte_security_session_conf sess_conf = {
+		.action_type = ut_params->type,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = ut_params->docsis_xform,
+		.crypto_xform = &ut_params->cipher_xform,
+	};
+
+	/* Create security session */
+	ut_params->sec_session = rte_security_session_create(ctx, &sess_conf,
+					ts_params->session_priv_mpool);
+
+	if (!ut_params->sec_session) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "failed to allocate session");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Generate crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc(ts_params->op_mpool,
+				RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!ut_params->op) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to allocate security crypto operation");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Setup CRC operation parameters */
+	crc_len = d_td->plaintext.no_crc == false ?
+			(d_td->plaintext.len -
+				d_td->plaintext.crc_offset -
+				RTE_ETHER_CRC_LEN) :
+			0;
+	crc_len = crc_len > 0 ? crc_len : 0;
+	ut_params->op->sym->auth.data.length = crc_len;
+	ut_params->op->sym->auth.data.offset = d_td->plaintext.crc_offset;
+
+	/* Setup cipher operation parameters */
+	cipher_len = d_td->plaintext.no_cipher == false ?
+			(d_td->plaintext.len -
+				d_td->plaintext.cipher_offset) :
+			0;
+	cipher_len = cipher_len > 0 ? cipher_len : 0;
+	ut_params->op->sym->cipher.data.length = cipher_len;
+	ut_params->op->sym->cipher.data.offset = d_td->plaintext.cipher_offset;
+
+	/* Setup cipher IV */
+	iv_ptr = (uint8_t *)ut_params->op + IV_OFFSET;
+	rte_memcpy(iv_ptr, d_td->iv.data, d_td->iv.len);
+
+	/* Attach session to operation */
+	rte_security_attach_session(ut_params->op, ut_params->sec_session);
+
+	/* Set crypto operation mbufs */
+	ut_params->op->sym->m_src = ut_params->ibuf;
+	ut_params->op->sym->m_dst = NULL;
+
+	/* Process crypto operation */
+	if (process_crypto_request(ts_params->valid_devs[0], ut_params->op) ==
+			NULL) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__,
+			"failed to process security crypto op");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	if (ut_params->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "crypto op processing failed");
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+	/* Validate ciphertext */
+	ciphertext = plaintext;
+
+	if (memcmp(ciphertext, d_td->ciphertext.data, d_td->ciphertext.len)) {
+		printf("TestCase %s(%d) line %d: %s\n",
+			__func__, i, __LINE__, "ciphertext not as expected\n");
+		rte_hexdump(stdout, "expected", d_td->ciphertext.data,
+				d_td->ciphertext.len);
+		rte_hexdump(stdout, "actual", ciphertext, d_td->ciphertext.len);
+		ret = TEST_FAILED;
+		goto on_err;
+	}
+
+on_err:
+	rte_crypto_op_free(ut_params->op);
+	ut_params->op = NULL;
+
+	if (ut_params->sec_session)
+		rte_security_session_destroy(ctx, ut_params->sec_session);
+	ut_params->sec_session = NULL;
+
+	rte_pktmbuf_free(ut_params->ibuf);
+	ut_params->ibuf = NULL;
+
+	return ret;
+}
+
+#define TEST_DOCSIS_COUNT(func) do {			\
+	int ret = func;					\
+	if (ret == TEST_SUCCESS)  {			\
+		printf("\t%2d)", n++);			\
+		printf("+++++ PASSED:" #func"\n");	\
+		p++;					\
+	} else if (ret == -ENOTSUP) {			\
+		printf("\t%2d)", n++);			\
+		printf("~~~~~ UNSUPP:" #func"\n");	\
+		u++;					\
+	} else {					\
+		printf("\t%2d)", n++);			\
+		printf("----- FAILED:" #func"\n");	\
+		f++;					\
+	}						\
+} while (0)
+
+static int
+test_DOCSIS_PROTO_uplink_all(void)
+{
+	int p = 0, u = 0, f = 0, n = 0;
+
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(1, &docsis_test_case_1));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(2, &docsis_test_case_2));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(3, &docsis_test_case_3));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(4, &docsis_test_case_4));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(5, &docsis_test_case_5));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(6, &docsis_test_case_6));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(7, &docsis_test_case_7));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(8, &docsis_test_case_8));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(9, &docsis_test_case_9));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(10, &docsis_test_case_10));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(11, &docsis_test_case_11));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(12, &docsis_test_case_12));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(13, &docsis_test_case_13));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(14, &docsis_test_case_14));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(15, &docsis_test_case_15));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(16, &docsis_test_case_16));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(17, &docsis_test_case_17));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(18, &docsis_test_case_18));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(19, &docsis_test_case_19));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(20, &docsis_test_case_20));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(21, &docsis_test_case_21));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(22, &docsis_test_case_22));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(23, &docsis_test_case_23));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(24, &docsis_test_case_24));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(25, &docsis_test_case_25));
+	TEST_DOCSIS_COUNT(test_docsis_proto_uplink(26, &docsis_test_case_26));
+
+	if (f)
+		printf("## %s: %d passed out of %d (%d unsupported)\n",
+			__func__, p, n, u);
+
+	return f;
+};
+
+static int
+test_DOCSIS_PROTO_downlink_all(void)
+{
+	int p = 0, u = 0, f = 0, n = 0;
+
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(1, &docsis_test_case_1));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(2, &docsis_test_case_2));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(3, &docsis_test_case_3));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(4, &docsis_test_case_4));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(5, &docsis_test_case_5));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(6, &docsis_test_case_6));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(7, &docsis_test_case_7));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(8, &docsis_test_case_8));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(9, &docsis_test_case_9));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(10, &docsis_test_case_10));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(11, &docsis_test_case_11));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(12, &docsis_test_case_12));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(13, &docsis_test_case_13));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(14, &docsis_test_case_14));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(15, &docsis_test_case_15));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(16, &docsis_test_case_16));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(17, &docsis_test_case_17));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(18, &docsis_test_case_18));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(19, &docsis_test_case_19));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(20, &docsis_test_case_20));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(21, &docsis_test_case_21));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(22, &docsis_test_case_22));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(23, &docsis_test_case_23));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(24, &docsis_test_case_24));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(25, &docsis_test_case_25));
+	TEST_DOCSIS_COUNT(test_docsis_proto_downlink(26, &docsis_test_case_26));
+
+	if (f)
+		printf("## %s: %d passed out of %d (%d unsupported)\n",
+			__func__, p, n, u);
+
+	return f;
+};
+
+static int
+test_DOCSIS_PROTO_all(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct rte_cryptodev_info dev_info;
+	int status;
+
+	rte_cryptodev_info_get(ts_params->valid_devs[0], &dev_info);
+	uint64_t feat_flags = dev_info.feature_flags;
+
+	if (!(feat_flags & RTE_CRYPTODEV_FF_SECURITY))
+		return -ENOTSUP;
+
+	if (security_proto_supported(RTE_SECURITY_PROTOCOL_DOCSIS) < 0)
+		return -ENOTSUP;
+
+	status = test_DOCSIS_PROTO_uplink_all();
+	status += test_DOCSIS_PROTO_downlink_all();
+
+	if (status)
+		return TEST_FAILED;
+	else
+		return TEST_SUCCESS;
+}
 #endif
 
 static int
@@ -12342,6 +12853,8 @@ static struct unit_test_suite cryptodev_testsuite  = {
 #ifdef RTE_LIBRTE_SECURITY
 		TEST_CASE_ST(ut_setup, ut_teardown,
 			test_PDCP_PROTO_all),
+		TEST_CASE_ST(ut_setup, ut_teardown,
+			test_DOCSIS_PROTO_all),
 #endif
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
diff --git a/app/test/test_cryptodev_security_docsis_test_vectors.h b/app/test/test_cryptodev_security_docsis_test_vectors.h
new file mode 100644
index 000000000..2ed57bd56
--- /dev/null
+++ b/app/test/test_cryptodev_security_docsis_test_vectors.h
@@ -0,0 +1,1544 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2020 Intel Corporation
+ */
+
+#ifndef TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_
+#define TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_
+
+/*
+ * DOCSIS test data and cases
+ * - encrypt direction: CRC-Crypto
+ * - decrypt direction: Crypto-CRC
+ */
+
+struct docsis_test_data {
+	struct {
+		uint8_t data[32];
+		unsigned int len;
+	} key;
+
+	struct {
+		uint8_t data[16] __rte_aligned(16);
+		unsigned int len;
+	} iv;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} plaintext;
+
+	struct {
+		uint8_t data[1024];
+		unsigned int len;
+		unsigned int cipher_offset;
+		unsigned int crc_offset;
+		bool no_cipher;
+		bool no_crc;
+	} ciphertext;
+};
+
+struct docsis_test_data docsis_test_case_1 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x61, 0xF8, 0x63, 0x42
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_2 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0, 0xDF,
+			/* CRC */
+			0xFE, 0x12, 0x99, 0xE5
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_3 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xD6, 0xE2, 0x70, 0x5C,
+			0xE6, 0x4D, 0xCC, 0x8C, 0x47, 0xB7, 0x09, 0xD6,
+			/* CRC */
+			0x54, 0x85, 0xF8, 0x32
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_4 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x92, 0x6A, 0xC2, 0xDC,
+			0xEE, 0x3B, 0x31, 0xEC, 0x03, 0xDE, 0x95, 0x33,
+			0x5E,
+			/* CRC */
+			0xFE, 0x47, 0x3E, 0x22
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_5 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0x42, 0xF3, 0x71, 0xA9,
+			0x8A, 0xCD, 0x59, 0x77, 0x67, 0x11, 0x1A, 0x87,
+			/* CRC */
+			0xAB, 0xED, 0x2C, 0x26
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_6 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x77, 0x74, 0x56, 0x05,
+			0xD1, 0x14, 0xA2, 0x8D, 0x2C, 0x9A, 0x11, 0xFC,
+			0x7D, 0xB0, 0xE7, 0x18, 0xCE, 0x75, 0x7C, 0x89,
+			0x14, 0x56, 0xE2, 0xF2, 0xB7, 0x47, 0x08, 0x27,
+			0xF7, 0x08, 0x7A, 0x13, 0x90, 0x81, 0x75, 0xB0,
+			0xC7, 0x91, 0x04, 0x83, 0xAD, 0x11, 0x46, 0x46,
+			0xF8, 0x54, 0x87, 0xA0, 0xA4, 0x0C, 0xC2, 0xF0,
+			0x81, 0x49, 0xA8, 0xA6, 0x6C, 0x48, 0xEB, 0x1F,
+			0x4B,
+			/* CRC */
+			0x2F, 0xD4, 0x48, 0x18
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_7 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x11, 0xB4, 0x06, 0x33
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_8 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x7A, 0xF0,
+			/* CRC */
+			0x8A, 0x0F, 0x74, 0xE8
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_9 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x3B, 0x9F, 0x72, 0x4C, 0xB5, 0x72,
+			0x3E, 0x56, 0x54, 0x49, 0x13, 0x53, 0xC4, 0xAA,
+			0xCD, 0xEA, 0x6A, 0x88, 0x99, 0x07, 0x86, 0xF4,
+			0xCF, 0x03, 0x4E, 0xDF, 0x65, 0x61, 0x47, 0x5B,
+			0x2F, 0x81, 0x09, 0x12, 0x9A, 0xC2, 0x24, 0x8C,
+			0x09,
+			/* CRC */
+			0x5D, 0x2B, 0x12, 0xF4
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_10 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0x14, 0x08, 0xE8, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_11 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xB3, 0x60, 0xEB, 0x38
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_12 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_13 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 16
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_14 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86,
+			/* CRC */
+			0x9B, 0xB3, 0x1A, 0x26
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_15 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86, 0x25,
+			/* CRC */
+			0xB5, 0x6B, 0xFD, 0xCB
+		},
+		.len = 25,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_16 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xF6, 0xA1, 0x2E, 0x0A,
+			0xBB, 0x27, 0x82, 0x4F, 0x99, 0x0A, 0xE2, 0x3F,
+			/* CRC */
+			0xEB, 0xB7, 0x89, 0xB0
+		},
+		.len = 34,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_17 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE1, 0x30, 0x38, 0xC8,
+			0xC4, 0x59, 0x8D, 0x43, 0x9A, 0xBE, 0xBE, 0x73,
+			0xC3,
+			/*CRC */
+			0x8C, 0xE1, 0x89, 0x8B
+		},
+		.len = 35,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_18 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE9, 0x12, 0x3B, 0x12,
+			0x36, 0x56, 0x95, 0xA6, 0x97, 0xF1, 0x74, 0x68,
+			0xBA, 0x58, 0x77, 0xEA, 0x43, 0x11, 0x85, 0xD4,
+			0x7A, 0xF8, 0x1C, 0x11, 0x50, 0xD1, 0xF1, 0xBD,
+			0x15, 0x4D, 0x99, 0xB5, 0x39, 0x74, 0x84, 0xDF,
+			0xD4, 0x8B, 0xDC, 0xB7, 0x58, 0x1B, 0x22, 0xAB,
+			0xF3, 0x29, 0xC6, 0xCB, 0x26, 0x07, 0x36, 0x6B,
+			0x8C, 0xAC, 0x6E, 0x99, 0x37, 0x94, 0xDF, 0x31,
+			/* CRC */
+			0xA1, 0x7D, 0x70, 0xBB
+		},
+		.len = 82,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_19 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0xE9, 0x12, 0x3B, 0x12,
+			0x36, 0x56, 0x95, 0xA6, 0x97, 0xF1, 0x74, 0x68,
+			0xBA, 0x58, 0x77, 0xEA, 0x43, 0x11, 0x85, 0xD4,
+			0x7A, 0xF8, 0x1C, 0x11, 0x50, 0xD1, 0xF1, 0xBD,
+			0x15, 0x4D, 0x99, 0xB5, 0x39, 0x74, 0x84, 0xDF,
+			0xD4, 0x8B, 0xDC, 0xB7, 0x58, 0x1B, 0x22, 0xAB,
+			0xF3, 0x29, 0xC6, 0xCB, 0x13, 0xED, 0x08, 0xF5,
+			0x1B, 0x4B, 0xD8, 0x79, 0x93, 0x26, 0x69, 0x03,
+			0x23,
+			/* CRC */
+			0xC8, 0x8E, 0x02, 0x3A
+		},
+		.len = 83,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_20 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x54, 0xB4, 0x55, 0x68, 0x06, 0xBF,
+			0x00, 0x8B, 0x5F, 0x2C, 0x10, 0x4A, 0xBF, 0x5A,
+			0xF2, 0x20, 0xD9, 0x77, 0x7F, 0x2D, 0x2B, 0x11,
+			0xAC, 0xAF, 0x21, 0x36, 0xD2, 0xD4, 0x80, 0xF2,
+			0x4F, 0x14, 0xA0, 0x3A, 0x66, 0xE5, 0xC5, 0xE2,
+			0x15,
+			/* CRC */
+			0x0C, 0x89, 0x76, 0x26
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_21 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x6A, 0x86,
+			/* CRC */
+			0x70, 0x44, 0x0D, 0x8C
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_22 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0x54, 0xB4, 0x55, 0x68, 0x06, 0xBF,
+			0x00, 0x8B, 0x5F, 0x2C, 0x10, 0x4A, 0xBF, 0x5A,
+			0xF2, 0x20, 0xD9, 0x77, 0x7F, 0x2D, 0x2B, 0x11,
+			0xAC, 0xAF, 0x21, 0x36, 0xD2, 0xD4, 0x80, 0xF2,
+			0x4F, 0x14, 0xA0, 0x3A, 0x66, 0xE5, 0xC5, 0xE2,
+			0x15,
+			/* CRC */
+			0x40, 0x16, 0x62, 0xE1
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = false,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_23 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0x14, 0x08, 0xE8, 0x55
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_24 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xB3, 0x60, 0xEB, 0x38
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = false
+	}
+};
+
+struct docsis_test_data docsis_test_case_25 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 24,
+		.cipher_offset = 18,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+struct docsis_test_data docsis_test_case_26 = {
+	.key = {
+		.data = {
+			0x00, 0x00, 0x00, 0x00, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
+			0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD,
+			0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55
+		},
+		.len = 32
+	},
+	.iv = {
+		.data = {
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
+			0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11
+		},
+		.len = 16
+	},
+	.plaintext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	},
+	.ciphertext = {
+		.data = {
+			/* DOCSIS header */
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			/* Ethernet frame */
+			0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x05,
+			0x04, 0x03, 0x02, 0x01, 0x08, 0x00, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+			0xAA,
+			/* CRC */
+			0xFF, 0xFF, 0xFF, 0xFF
+		},
+		.len = 83,
+		.cipher_offset = 40,
+		.crc_offset = 6,
+		.no_cipher = true,
+		.no_crc = true
+	}
+};
+
+#endif /* TEST_CRYPTODEV_SECURITY_DOCSIS_TEST_VECTORS_H_ */
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 6/7] test/security: add DOCSIS capability check tests
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
                           ` (4 preceding siblings ...)
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 5/7] test/crypto: add DOCSIS security test cases David Coyle
@ 2020-07-03 12:39         ` David Coyle
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 7/7] app/crypto-perf: add support for DOCSIS protocol David Coyle
  2020-07-04 19:54         ` [dpdk-dev] [PATCH v4 0/7] " Akhil Goyal
  7 siblings, 0 replies; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Add unit tests for DOCSIS capabilitity checks.

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
---
 app/test/test_security.c | 88 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/app/test/test_security.c b/app/test/test_security.c
index 3076a4c5a..77fd5adc6 100644
--- a/app/test/test_security.c
+++ b/app/test/test_security.c
@@ -6,6 +6,7 @@
 #include <rte_log.h>
 #include <rte_memory.h>
 #include <rte_mempool.h>
+#include <rte_ether.h>
 #include <rte_security.h>
 #include <rte_security_driver.h>
 
@@ -2268,6 +2269,89 @@ test_capability_get_pdcp_match(void)
 	return TEST_SUCCESS;
 }
 
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * does not contain entry with matching DOCSIS direction field
+ */
+static int
+test_capability_get_docsis_mismatch_direction(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx idx = {
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_DOWNLINK
+		},
+	};
+	struct rte_security_capability capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			.docsis = {
+				.direction = RTE_SECURITY_DOCSIS_UPLINK
+			},
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE,
+		},
+	};
+
+	mock_capabilities_get_exp.device = NULL;
+	mock_capabilities_get_exp.ret = capabilities;
+
+	const struct rte_security_capability *ret;
+	ret = rte_security_capability_get(&ut_params->ctx, &idx);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+			ret, NULL, "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+	return TEST_SUCCESS;
+}
+
+/**
+ * Test execution of rte_security_capability_get when capabilities table
+ * contains matching DOCSIS entry
+ */
+static int
+test_capability_get_docsis_match(void)
+{
+	struct security_unittest_params *ut_params = &unittest_params;
+	struct rte_security_capability_idx idx = {
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+		.docsis = {
+			.direction = RTE_SECURITY_DOCSIS_UPLINK
+		},
+	};
+	struct rte_security_capability capabilities[] = {
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			.docsis = {
+				.direction = RTE_SECURITY_DOCSIS_UPLINK
+			},
+		},
+		{
+			.action = RTE_SECURITY_ACTION_TYPE_NONE,
+		},
+	};
+
+	mock_capabilities_get_exp.device = NULL;
+	mock_capabilities_get_exp.ret = capabilities;
+
+	const struct rte_security_capability *ret;
+	ret = rte_security_capability_get(&ut_params->ctx, &idx);
+	TEST_ASSERT_MOCK_FUNCTION_CALL_RET(rte_security_capability_get,
+			ret, &capabilities[1], "%p");
+	TEST_ASSERT_MOCK_CALLS(mock_capabilities_get_exp, 1);
+
+	return TEST_SUCCESS;
+}
+
 /**
  * Declaration of testcases
  */
@@ -2410,6 +2494,10 @@ static struct unit_test_suite security_testsuite  = {
 				test_capability_get_pdcp_mismatch_domain),
 		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
 				test_capability_get_pdcp_match),
+		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+				test_capability_get_docsis_mismatch_direction),
+		TEST_CASE_ST(ut_setup_with_session, ut_teardown,
+				test_capability_get_docsis_match),
 
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* [dpdk-dev] [PATCH v4 7/7] app/crypto-perf: add support for DOCSIS protocol
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
                           ` (5 preceding siblings ...)
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 6/7] test/security: add DOCSIS capability check tests David Coyle
@ 2020-07-03 12:39         ` David Coyle
  2020-07-03 17:57           ` De Lara Guarch, Pablo
  2020-07-04 19:54         ` [dpdk-dev] [PATCH v4 0/7] " Akhil Goyal
  7 siblings, 1 reply; 92+ messages in thread
From: David Coyle @ 2020-07-03 12:39 UTC (permalink / raw)
  To: akhil.goyal, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, hemant.agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, David Coyle,
	Mairtin o Loingsigh

Update test-crypto-perf app to calculate DOCSIS throughput numbers.

1 new parameter is added for DOCSIS:
--docsis-hdr-sz <n>

./dpdk-test-crypto-perf -l 3,4 --socket-mem 2048,0
--vdev crypto_aesni_mb_pmd_1 -n 1 -- --devtype crypto_aesni_mb
--optype docsis --cipher-algo aes-docsisbpi --cipher-op encrypt
--cipher-key-sz 16 --cipher-iv-sz 16 --burst-sz 32 --total-ops 20000000
--buffer-sz 1024 --silent --docsis-hdr-sz 17

Signed-off-by: David Coyle <david.coyle@intel.com>
Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
 app/test-crypto-perf/cperf_ops.c             | 82 ++++++++++++++++++--
 app/test-crypto-perf/cperf_options.h         |  5 +-
 app/test-crypto-perf/cperf_options_parsing.c | 67 +++++++++++++++-
 app/test-crypto-perf/cperf_test_throughput.c |  3 +-
 app/test-crypto-perf/cperf_test_vectors.c    |  3 +-
 app/test-crypto-perf/main.c                  |  5 +-
 app/test-crypto-perf/meson.build             |  2 +-
 doc/guides/rel_notes/release_20_08.rst       |  6 ++
 doc/guides/tools/cryptoperf.rst              |  5 ++
 9 files changed, 166 insertions(+), 12 deletions(-)

diff --git a/app/test-crypto-perf/cperf_ops.c b/app/test-crypto-perf/cperf_ops.c
index 97584ceed..e06b59f55 100644
--- a/app/test-crypto-perf/cperf_ops.c
+++ b/app/test-crypto-perf/cperf_ops.c
@@ -3,6 +3,7 @@
  */
 
 #include <rte_cryptodev.h>
+#include <rte_ether.h>
 
 #include "cperf_ops.h"
 #include "cperf_test_vectors.h"
@@ -15,8 +16,7 @@ cperf_set_ops_security(struct rte_crypto_op **ops,
 		uint16_t nb_ops, struct rte_cryptodev_sym_session *sess,
 		const struct cperf_options *options __rte_unused,
 		const struct cperf_test_vector *test_vector __rte_unused,
-		uint16_t iv_offset __rte_unused,
-		uint32_t *imix_idx __rte_unused)
+		uint16_t iv_offset __rte_unused, uint32_t *imix_idx)
 {
 	uint16_t i;
 
@@ -24,14 +24,39 @@ cperf_set_ops_security(struct rte_crypto_op **ops,
 		struct rte_crypto_sym_op *sym_op = ops[i]->sym;
 		struct rte_security_session *sec_sess =
 			(struct rte_security_session *)sess;
+		uint32_t buf_sz;
 
 		ops[i]->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
 		rte_security_attach_session(ops[i], sec_sess);
 		sym_op->m_src = (struct rte_mbuf *)((uint8_t *)ops[i] +
 							src_buf_offset);
-		sym_op->m_src->buf_len = options->segment_sz;
-		sym_op->m_src->data_len = options->test_buffer_size;
-		sym_op->m_src->pkt_len = sym_op->m_src->data_len;
+
+		if (options->op_type == CPERF_PDCP) {
+			sym_op->m_src->buf_len = options->segment_sz;
+			sym_op->m_src->data_len = options->test_buffer_size;
+			sym_op->m_src->pkt_len = sym_op->m_src->data_len;
+		}
+
+		if (options->op_type == CPERF_DOCSIS) {
+			if (options->imix_distribution_count) {
+				buf_sz = options->imix_buffer_sizes[*imix_idx];
+				*imix_idx = (*imix_idx + 1) % options->pool_sz;
+			} else
+				buf_sz = options->test_buffer_size;
+
+			/* DOCSIS header is not CRC'ed */
+			sym_op->auth.data.offset = options->docsis_hdr_sz;
+			sym_op->auth.data.length = buf_sz -
+				sym_op->auth.data.offset - RTE_ETHER_CRC_LEN;
+			/*
+			 * DOCSIS header and SRC and DST MAC addresses are not
+			 * ciphered
+			 */
+			sym_op->cipher.data.offset = sym_op->auth.data.offset +
+				RTE_ETHER_HDR_LEN - RTE_ETHER_TYPE_LEN;
+			sym_op->cipher.data.length = buf_sz -
+				sym_op->cipher.data.offset;
+		}
 
 		/* Set dest mbuf to NULL if out-of-place (dst_buf_offset = 0) */
 		if (dst_buf_offset == 0)
@@ -589,6 +614,49 @@ cperf_create_session(struct rte_mempool *sess_mp,
 		return (void *)rte_security_session_create(ctx,
 					&sess_conf, sess_mp);
 	}
+	if (options->op_type == CPERF_DOCSIS) {
+		enum rte_security_docsis_direction direction;
+
+		cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+		cipher_xform.next = NULL;
+		cipher_xform.cipher.algo = options->cipher_algo;
+		cipher_xform.cipher.op = options->cipher_op;
+		cipher_xform.cipher.iv.offset = iv_offset;
+		if (options->cipher_algo != RTE_CRYPTO_CIPHER_NULL) {
+			cipher_xform.cipher.key.data =
+				test_vector->cipher_key.data;
+			cipher_xform.cipher.key.length =
+				test_vector->cipher_key.length;
+			cipher_xform.cipher.iv.length =
+				test_vector->cipher_iv.length;
+		} else {
+			cipher_xform.cipher.key.data = NULL;
+			cipher_xform.cipher.key.length = 0;
+			cipher_xform.cipher.iv.length = 0;
+		}
+		cipher_xform.next = NULL;
+
+		if (options->cipher_op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
+			direction = RTE_SECURITY_DOCSIS_DOWNLINK;
+		else
+			direction = RTE_SECURITY_DOCSIS_UPLINK;
+
+		struct rte_security_session_conf sess_conf = {
+			.action_type =
+				RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+			.protocol = RTE_SECURITY_PROTOCOL_DOCSIS,
+			{.docsis = {
+				.direction = direction,
+			} },
+			.crypto_xform = &cipher_xform
+		};
+		struct rte_security_ctx *ctx = (struct rte_security_ctx *)
+					rte_cryptodev_get_sec_ctx(dev_id);
+
+		/* Create security session */
+		return (void *)rte_security_session_create(ctx,
+					&sess_conf, priv_mp);
+	}
 #endif
 	sess = rte_cryptodev_sym_session_create(sess_mp);
 	/*
@@ -772,6 +840,10 @@ cperf_get_op_functions(const struct cperf_options *options,
 		op_fns->populate_ops = cperf_set_ops_security;
 		return 0;
 	}
+	if (options->op_type == CPERF_DOCSIS) {
+		op_fns->populate_ops = cperf_set_ops_security;
+		return 0;
+	}
 #endif
 	return -1;
 }
diff --git a/app/test-crypto-perf/cperf_options.h b/app/test-crypto-perf/cperf_options.h
index 1ed0a77e5..e5f1edffc 100644
--- a/app/test-crypto-perf/cperf_options.h
+++ b/app/test-crypto-perf/cperf_options.h
@@ -50,6 +50,7 @@
 #ifdef RTE_LIBRTE_SECURITY
 #define CPERF_PDCP_SN_SZ	("pdcp-sn-sz")
 #define CPERF_PDCP_DOMAIN	("pdcp-domain")
+#define CPERF_DOCSIS_HDR_SZ	("docsis-hdr-sz")
 #endif
 
 #define CPERF_CSV		("csv-friendly")
@@ -75,7 +76,8 @@ enum cperf_op_type {
 	CPERF_CIPHER_THEN_AUTH,
 	CPERF_AUTH_THEN_CIPHER,
 	CPERF_AEAD,
-	CPERF_PDCP
+	CPERF_PDCP,
+	CPERF_DOCSIS
 };
 
 extern const char *cperf_op_type_strs[];
@@ -122,6 +124,7 @@ struct cperf_options {
 #ifdef RTE_LIBRTE_SECURITY
 	uint16_t pdcp_sn_sz;
 	enum rte_security_pdcp_domain pdcp_domain;
+	uint16_t docsis_hdr_sz;
 #endif
 	char device_type[RTE_CRYPTODEV_NAME_MAX_LEN];
 	enum cperf_op_type op_type;
diff --git a/app/test-crypto-perf/cperf_options_parsing.c b/app/test-crypto-perf/cperf_options_parsing.c
index f43c5bede..20577a144 100644
--- a/app/test-crypto-perf/cperf_options_parsing.c
+++ b/app/test-crypto-perf/cperf_options_parsing.c
@@ -7,6 +7,7 @@
 
 #include <rte_cryptodev.h>
 #include <rte_malloc.h>
+#include <rte_ether.h>
 
 #include "cperf_options.h"
 
@@ -56,6 +57,9 @@ usage(char *progname)
 		" --pmd-cyclecount-delay-ms N: set delay between enqueue\n"
 		"           and dequeue in pmd-cyclecount benchmarking mode\n"
 		" --csv-friendly: enable test result output CSV friendly\n"
+#ifdef RTE_LIBRTE_SECURITY
+		" --docsis-hdr-sz: set DOCSIS header size\n"
+#endif
 		" -h: prints this help\n",
 		progname);
 }
@@ -446,6 +450,10 @@ parse_op_type(struct cperf_options *opts, const char *arg)
 		{
 			cperf_op_type_strs[CPERF_PDCP],
 			CPERF_PDCP
+		},
+		{
+			cperf_op_type_strs[CPERF_DOCSIS],
+			CPERF_DOCSIS
 		}
 	};
 
@@ -675,6 +683,12 @@ parse_pdcp_domain(struct cperf_options *opts, const char *arg)
 
 	return 0;
 }
+
+static int
+parse_docsis_hdr_sz(struct cperf_options *opts, const char *arg)
+{
+	return parse_uint16_t(&opts->docsis_hdr_sz, arg);
+}
 #endif
 
 static int
@@ -820,6 +834,7 @@ static struct option lgopts[] = {
 #ifdef RTE_LIBRTE_SECURITY
 	{ CPERF_PDCP_SN_SZ, required_argument, 0, 0 },
 	{ CPERF_PDCP_DOMAIN, required_argument, 0, 0 },
+	{ CPERF_DOCSIS_HDR_SZ, required_argument, 0, 0 },
 #endif
 	{ CPERF_CSV, no_argument, 0, 0},
 
@@ -890,6 +905,7 @@ cperf_options_default(struct cperf_options *opts)
 #ifdef RTE_LIBRTE_SECURITY
 	opts->pdcp_sn_sz = 12;
 	opts->pdcp_domain = RTE_SECURITY_PDCP_MODE_CONTROL;
+	opts->docsis_hdr_sz = 17;
 #endif
 }
 
@@ -929,6 +945,7 @@ cperf_opts_parse_long(int opt_idx, struct cperf_options *opts)
 #ifdef RTE_LIBRTE_SECURITY
 		{ CPERF_PDCP_SN_SZ,	parse_pdcp_sn_sz },
 		{ CPERF_PDCP_DOMAIN,	parse_pdcp_domain },
+		{ CPERF_DOCSIS_HDR_SZ,	parse_docsis_hdr_sz },
 #endif
 		{ CPERF_CSV,		parse_csv_friendly},
 		{ CPERF_PMDCC_DELAY_MS,	parse_pmd_cyclecount_delay_ms},
@@ -1031,10 +1048,44 @@ check_cipher_buffer_length(struct cperf_options *options)
 	return 0;
 }
 
+#ifdef RTE_LIBRTE_SECURITY
+static int
+check_docsis_buffer_length(struct cperf_options *options)
+{
+	uint32_t buffer_size, buffer_size_idx = 0;
+
+	if (options->inc_buffer_size != 0)
+		buffer_size = options->min_buffer_size;
+	else
+		buffer_size = options->buffer_size_list[0];
+
+	while (buffer_size <= options->max_buffer_size) {
+		if (buffer_size < (uint32_t)(options->docsis_hdr_sz +
+				RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN)) {
+			RTE_LOG(ERR, USER1, "Some of the buffer sizes are not "
+				"valid for DOCSIS\n");
+			return -EINVAL;
+		}
+
+		if (options->inc_buffer_size != 0)
+			buffer_size += options->inc_buffer_size;
+		else {
+			if (++buffer_size_idx == options->buffer_size_count)
+				break;
+			buffer_size =
+				options->buffer_size_list[buffer_size_idx];
+		}
+	}
+
+	return 0;
+}
+#endif
+
 int
 cperf_options_check(struct cperf_options *options)
 {
-	if (options->op_type == CPERF_CIPHER_ONLY)
+	if (options->op_type == CPERF_CIPHER_ONLY ||
+			options->op_type == CPERF_DOCSIS)
 		options->digest_sz = 0;
 
 	if (options->out_of_place &&
@@ -1151,6 +1202,13 @@ cperf_options_check(struct cperf_options *options)
 			return -EINVAL;
 	}
 
+#ifdef RTE_LIBRTE_SECURITY
+	if (options->op_type == CPERF_DOCSIS) {
+		if (check_docsis_buffer_length(options) < 0)
+			return -EINVAL;
+	}
+#endif
+
 	return 0;
 }
 
@@ -1236,4 +1294,11 @@ cperf_options_dump(struct cperf_options *opts)
 		printf("# aead aad size: %u\n", opts->aead_aad_sz);
 		printf("#\n");
 	}
+
+#ifdef RTE_LIBRTE_SECURITY
+	if (opts->op_type == CPERF_DOCSIS) {
+		printf("# docsis header size: %u\n", opts->docsis_hdr_sz);
+		printf("#\n");
+	}
+#endif
 }
diff --git a/app/test-crypto-perf/cperf_test_throughput.c b/app/test-crypto-perf/cperf_test_throughput.c
index 35c51026f..12d9ea4f9 100644
--- a/app/test-crypto-perf/cperf_test_throughput.c
+++ b/app/test-crypto-perf/cperf_test_throughput.c
@@ -36,7 +36,8 @@ cperf_throughput_test_free(struct cperf_throughput_ctx *ctx)
 		return;
 	if (ctx->sess) {
 #ifdef RTE_LIBRTE_SECURITY
-		if (ctx->options->op_type == CPERF_PDCP) {
+		if (ctx->options->op_type == CPERF_PDCP ||
+				ctx->options->op_type == CPERF_DOCSIS) {
 			struct rte_security_ctx *sec_ctx =
 				(struct rte_security_ctx *)
 				rte_cryptodev_get_sec_ctx(ctx->dev_id);
diff --git a/app/test-crypto-perf/cperf_test_vectors.c b/app/test-crypto-perf/cperf_test_vectors.c
index 41641650c..0af01ff91 100644
--- a/app/test-crypto-perf/cperf_test_vectors.c
+++ b/app/test-crypto-perf/cperf_test_vectors.c
@@ -469,7 +469,8 @@ cperf_test_vector_get_dummy(struct cperf_options *options)
 
 	if (options->op_type ==	CPERF_CIPHER_ONLY ||
 			options->op_type == CPERF_CIPHER_THEN_AUTH ||
-			options->op_type == CPERF_AUTH_THEN_CIPHER) {
+			options->op_type == CPERF_AUTH_THEN_CIPHER ||
+			options->op_type == CPERF_DOCSIS) {
 		if (options->cipher_algo == RTE_CRYPTO_CIPHER_NULL) {
 			t_vec->cipher_key.length = 0;
 			t_vec->ciphertext.data = plaintext;
diff --git a/app/test-crypto-perf/main.c b/app/test-crypto-perf/main.c
index 7bb286ccb..edeea9c1b 100644
--- a/app/test-crypto-perf/main.c
+++ b/app/test-crypto-perf/main.c
@@ -39,7 +39,8 @@ const char *cperf_op_type_strs[] = {
 	[CPERF_CIPHER_THEN_AUTH] = "cipher-then-auth",
 	[CPERF_AUTH_THEN_CIPHER] = "auth-then-cipher",
 	[CPERF_AEAD] = "aead",
-	[CPERF_PDCP] = "pdcp"
+	[CPERF_PDCP] = "pdcp",
+	[CPERF_DOCSIS] = "docsis"
 };
 
 const struct cperf_test cperf_testmap[] = {
@@ -244,7 +245,7 @@ cperf_initialize_cryptodev(struct cperf_options *opts, uint8_t *enabled_cdevs)
 #endif
 		} else
 			sessions_needed = enabled_cdev_count *
-						opts->nb_qps;
+						opts->nb_qps * 2;
 
 		/*
 		 * A single session is required per queue pair
diff --git a/app/test-crypto-perf/meson.build b/app/test-crypto-perf/meson.build
index ef28cb5a0..f394b75ba 100644
--- a/app/test-crypto-perf/meson.build
+++ b/app/test-crypto-perf/meson.build
@@ -11,4 +11,4 @@ sources = files('cperf_ops.c',
 		'cperf_test_vectors.c',
 		'cperf_test_verify.c',
 		'main.c')
-deps += ['cryptodev', 'security']
+deps += ['cryptodev', 'net', 'security']
diff --git a/doc/guides/rel_notes/release_20_08.rst b/doc/guides/rel_notes/release_20_08.rst
index 4ff7911c0..a07150e62 100644
--- a/doc/guides/rel_notes/release_20_08.rst
+++ b/doc/guides/rel_notes/release_20_08.rst
@@ -122,6 +122,12 @@ New Features
   * Dump ``rte_flow`` memory consumption.
   * Measure packet per second forwarding.
 
+* **Added support for DOCSIS protocol to dpdk-test-crypto-perf application.**
+
+  Updated the ``dpdk-test-crypto-perf`` application to support the DOCSIS
+  protocol in order to measure the throughput of combined crypto and CRC
+  operations.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/tools/cryptoperf.rst b/doc/guides/tools/cryptoperf.rst
index a19ccb262..a8df8bc99 100644
--- a/doc/guides/tools/cryptoperf.rst
+++ b/doc/guides/tools/cryptoperf.rst
@@ -193,6 +193,7 @@ The following are the application command-line options:
            auth-then-cipher
            aead
            pdcp
+           docsis
 
         For GCM/CCM algorithms you should use aead flag.
 
@@ -342,6 +343,10 @@ The following are the application command-line options:
 
         Set PDCP domain to specify Control/user plane.
 
+* ``--docsis-hdr-sz <n>``
+
+        Set DOCSIS header size(n) in bytes.
+
 Test Vector File
 ~~~~~~~~~~~~~~~~
 
-- 
2.17.1


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v4 1/7] security: add support for DOCSIS protocol
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 1/7] security: " David Coyle
@ 2020-07-03 17:50           ` De Lara Guarch, Pablo
  0 siblings, 0 replies; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-07-03 17:50 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin


> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Friday, July 3, 2020 1:39 PM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v4 1/7] security: add support for DOCSIS protocol
> 
> Add support for DOCSIS protocol to rte_security library. This support currently
> comprises the combination of Crypto and CRC operations.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>


^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v4 2/7] cryptodev: add a note regarding DOCSIS protocol support
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 2/7] cryptodev: add a note regarding DOCSIS protocol support David Coyle
@ 2020-07-03 17:56           ` De Lara Guarch, Pablo
  0 siblings, 0 replies; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-07-03 17:56 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin



> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Friday, July 3, 2020 1:39 PM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v4 2/7] cryptodev: add a note regarding DOCSIS protocol
> support
> 
> Add a note to the rte_crypto_sym_op->auth.data fields to state that for DOCSIS
> security protocol, these are used to specify the offset and length of data over
> which the CRC is calculated.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
@ 2020-07-03 17:56           ` De Lara Guarch, Pablo
  2020-07-04 19:55           ` Akhil Goyal
  1 sibling, 0 replies; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-07-03 17:56 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin



> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Friday, July 3, 2020 1:39 PM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol
> 
> Add support to the AESNI-MB PMD for the DOCSIS protocol, through the
> rte_security API. This, therefore, includes adding support for the rte_security API
> to this PMD.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>

Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v4 5/7] test/crypto: add DOCSIS security test cases
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 5/7] test/crypto: add DOCSIS security test cases David Coyle
@ 2020-07-03 17:56           ` De Lara Guarch, Pablo
  0 siblings, 0 replies; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-07-03 17:56 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin



> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Friday, July 3, 2020 1:40 PM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v4 5/7] test/crypto: add DOCSIS security test cases
> 
> Add uplink and downlink DOCSIS unit test cases and vectors, to test
> the combined DOCSIS Crypto-CRC support that has been added to the
> rte_security library.
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v4 7/7] app/crypto-perf: add support for DOCSIS protocol
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 7/7] app/crypto-perf: add support for DOCSIS protocol David Coyle
@ 2020-07-03 17:57           ` De Lara Guarch, Pablo
  0 siblings, 0 replies; 92+ messages in thread
From: De Lara Guarch, Pablo @ 2020-07-03 17:57 UTC (permalink / raw)
  To: Coyle, David, akhil.goyal, Doherty, Declan, Trahe, Fiona, Zhang,
	Roy Fan, Ananyev, Konstantin
  Cc: dev, thomas, Yigit, Ferruh, Ryan, Brendan, hemant.agrawal,
	anoobj, ruifeng.wang, lironh, rnagadheeraj, jsrikanth, G.Singh,
	jianjay.zhou, ravi1.kumar, Richardson, Bruce, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj, O'loingsigh,
	Mairtin



> -----Original Message-----
> From: Coyle, David <david.coyle@intel.com>
> Sent: Friday, July 3, 2020 1:40 PM
> To: akhil.goyal@nxp.com; Doherty, Declan <declan.doherty@intel.com>; De
> Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona
> <fiona.trahe@intel.com>; Zhang, Roy Fan <roy.fan.zhang@intel.com>;
> Ananyev, Konstantin <konstantin.ananyev@intel.com>
> Cc: dev@dpdk.org; thomas@monjalon.net; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Ryan, Brendan <brendan.ryan@intel.com>;
> hemant.agrawal@nxp.com; anoobj@marvell.com; ruifeng.wang@arm.com;
> lironh@marvell.com; rnagadheeraj@marvell.com; jsrikanth@marvell.com;
> G.Singh@nxp.com; jianjay.zhou@huawei.com; ravi1.kumar@amd.com;
> Richardson, Bruce <bruce.richardson@intel.com>; olivier.matz@6wind.com;
> honnappa.nagarahalli@arm.com; stephen@networkplumber.org;
> alexr@mellanox.com; jerinj@marvell.com; Coyle, David
> <david.coyle@intel.com>; O'loingsigh, Mairtin <mairtin.oloingsigh@intel.com>
> Subject: [PATCH v4 7/7] app/crypto-perf: add support for DOCSIS protocol
> 
> Update test-crypto-perf app to calculate DOCSIS throughput numbers.
> 
> 1 new parameter is added for DOCSIS:
> --docsis-hdr-sz <n>
> 
> ./dpdk-test-crypto-perf -l 3,4 --socket-mem 2048,0 --vdev
> crypto_aesni_mb_pmd_1 -n 1 -- --devtype crypto_aesni_mb --optype docsis --
> cipher-algo aes-docsisbpi --cipher-op encrypt --cipher-key-sz 16 --cipher-iv-sz 16
> --burst-sz 32 --total-ops 20000000 --buffer-sz 1024 --silent --docsis-hdr-sz 17
> 
> Signed-off-by: David Coyle <david.coyle@intel.com>
> Signed-off-by: Mairtin o Loingsigh <mairtin.oloingsigh@intel.com>
> Acked-by: Akhil Goyal <akhil.goyal@nxp.com>

Acked-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol
  2020-07-03 12:39       ` [dpdk-dev] [PATCH v4 0/7] add support for DOCSIS protocol David Coyle
                           ` (6 preceding siblings ...)
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 7/7] app/crypto-perf: add support for DOCSIS protocol David Coyle
@ 2020-07-04 19:54         ` Akhil Goyal
  7 siblings, 0 replies; 92+ messages in thread
From: Akhil Goyal @ 2020-07-04 19:54 UTC (permalink / raw)
  To: David Coyle, declan.doherty, pablo.de.lara.guarch, fiona.trahe,
	roy.fan.zhang, konstantin.ananyev
  Cc: dev, thomas, ferruh.yigit, brendan.ryan, Hemant Agrawal, anoobj,
	ruifeng.wang, lironh, rnagadheeraj, jsrikanth, Gagandeep Singh,
	jianjay.zhou, ravi1.kumar, bruce.richardson, olivier.matz,
	honnappa.nagarahalli, stephen, alexr, jerinj

> Introduction
> ============
> 
> This patchset adds support for the DOCSIS protocol to the DPDK Security
> API (rte_security), to be used by the AESNI-MB and QAT crypto devices to
> combine and accelerate Crypto and CRC functions of the DOCSIS protocol
> into a single operation.
> 
> Performing these functions in parallel as a single operation can enable a
> significant performance improvement in a DPDK-based DOCSIS MAC pipeline.
> 
> 
> Background
> ==========
> 
> A number of approaches to combine DOCSIS Crypto and CRC functions have
> been discussed in the DPDK community to date, namely:
> 1) adding a new rte_accelerator API, to provide a generic interface for
>    combining operations of different types
> 2) using rawdev through a multi-function interface, again to provide a
>    generic interface for combining operations of different types
> 3) adding support for DOCSIS Crypto-CRC to rte_security
> 
> The third option above is the preferred approach for the following
> reasons:
> - it addresses the immediate use case to add DOCSIS Crypto-CRC support to
>   DPDK so that it can be consumed easily by cable equipment vendors
> - it uses an already existing framework in DPDK
> - it will mean much less code churn in DOCSIS applications, which already
>   use rte_cryptodev for encryption/decryption
> 
> 
> Use Cases
> =========
> 
> The primary use case for this proposal has already been mentioned, namely
> to add DOCSIS Crypto-CRC support to DPDK:
> 
> - DOCSIS MAC: Crypto-CRC
> 	- Order:
> 		- Downstream: CRC, Encrypt
> 		- Upstream: Decrypt, CRC
> 	- Specifications:
> 		- Crypto: 128-bit and 256-bit AES-CFB encryption variant
> 		  for DOCSIS as described in section 11.1 of DOCSIS 3.1
> 		  Security Specification
> 
> (https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fapps.ca
> blelabs.com%2Fspecification%2FCM-SP-
> SECv3.1&amp;data=02%7C01%7Cakhil.goyal%40nxp.com%7C39c59476749d4f5
> ec88a08d81f5153d0%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6
> 37293781444756595&amp;sdata=W4YJl2bu8jsADjsLVDG2vXhYkOmbBhFY%2B4A
> a47onVak%3D&amp;reserved=0)
> 		- CRC: Ethernet 32-bit CRC as defined in
> 		  Ethernet/[ISO/IEC 8802-3]
> 
> Note that support for these chained operations is already available in
> the Intel IPSec Multi-Buffer library.
> 
> However, other DOCSIS protocol functions could be optimized too in the
> future using the same rte_security API for DOCSIS (e.g. Header Checksum
> (HCS) calculation).
> 
> v4:
> * addressed Akhil's comments regarding documentation
> * made some code fixes
>   * fixed possible NULL pointer dereference when allocating security_ctx
>     in AESNI-MB and QAT PMDs
>   * freed security_ctx memory when exiting AESNI-MB and QAT PMDs
>   * added session IOVA verification update when creating security
>     sessions in QAT PMD
> 
> v3:
> * removed rte_security_op definition
>   * now using rte_crypto_sym_op->auth.data fields for CRC offset and
>     length as suggested by feedback from Akhil and Konstantin
> * addressed Pablo's comments
> * removed support for out-of-place for DOCSIS protocol from QAT PMD
> * updated dpdk-crypto-perf-test tool for DOCSIS
> * updated documentation
> 
> v2:
> * added rte_security and rte_cryptodev code changes
> * added AESNI MB crypto PMD code changes
> * added QAT SYM crypto PMD code changes
> * added crypto unit tests
> * added security unit tests
> 
> v1:
> * added proposed API changes
> * added security capabilities to aesni_mb crypto PMD
> 
> David Coyle (7):
>   security: add support for DOCSIS protocol
>   cryptodev: add a note regarding DOCSIS protocol support
>   crypto/aesni_mb: add support for DOCSIS protocol
>   crypto/qat: add support for DOCSIS protocol
>   test/crypto: add DOCSIS security test cases
>   test/security: add DOCSIS capability check tests
>   app/crypto-perf: add support for DOCSIS protocol
> 
>  app/test-crypto-perf/cperf_ops.c              |   82 +-
>  app/test-crypto-perf/cperf_options.h          |    5 +-
>  app/test-crypto-perf/cperf_options_parsing.c  |   67 +-
>  app/test-crypto-perf/cperf_test_throughput.c  |    3 +-
>  app/test-crypto-perf/cperf_test_vectors.c     |    3 +-
>  app/test-crypto-perf/main.c                   |    5 +-
>  app/test-crypto-perf/meson.build              |    2 +-
>  app/test/test_cryptodev.c                     |  513 ++++++
>  ...t_cryptodev_security_docsis_test_vectors.h | 1544 +++++++++++++++++
>  app/test/test_security.c                      |   88 +
>  doc/guides/cryptodevs/aesni_mb.rst            |    8 +
>  doc/guides/cryptodevs/features/aesni_mb.ini   |    1 +
>  doc/guides/cryptodevs/features/qat.ini        |    1 +
>  doc/guides/cryptodevs/qat.rst                 |    7 +
>  doc/guides/prog_guide/rte_security.rst        |  114 +-
>  doc/guides/rel_notes/release_20_08.rst        |   21 +
>  doc/guides/tools/cryptoperf.rst               |    5 +
>  drivers/common/qat/Makefile                   |    3 +
>  .../crypto/aesni_mb/aesni_mb_pmd_private.h    |   19 +-
>  drivers/crypto/aesni_mb/meson.build           |    2 +-
>  drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c    |  301 +++-
>  .../crypto/aesni_mb/rte_aesni_mb_pmd_ops.c    |  125 ++
>  drivers/crypto/qat/meson.build                |    2 +
>  drivers/crypto/qat/qat_sym.c                  |   71 +-
>  drivers/crypto/qat/qat_sym.h                  |   62 +-
>  drivers/crypto/qat/qat_sym_capabilities.h     |   42 +
>  drivers/crypto/qat/qat_sym_pmd.c              |   61 +-
>  drivers/crypto/qat/qat_sym_pmd.h              |    4 +
>  drivers/crypto/qat/qat_sym_session.c          |  153 ++
>  drivers/crypto/qat/qat_sym_session.h          |   11 +
>  lib/librte_cryptodev/rte_crypto_sym.h         |   14 +
>  lib/librte_security/rte_security.c            |    5 +
>  lib/librte_security/rte_security.h            |   38 +
>  33 files changed, 3348 insertions(+), 34 deletions(-)
>  create mode 100644 app/test/test_cryptodev_security_docsis_test_vectors.h
> 
Some modifications are done in the release notes while merging. Please check.
Applied to dpdk-next-crypto

Thanks.

^ permalink raw reply	[flat|nested] 92+ messages in thread

* Re: [dpdk-dev] [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol
  2020-07-03 12:39         ` [dpdk-dev] [PATCH v4 3/7] crypto/aesni_mb: add support for DOCSIS protocol David Coyle
  2020-07-03 17:56           ` De Lara Guarch, Pablo
@ 2020-07-04 19:55           ` Akhil Goyal
  1 sibling, 0 replies; 92+ messages in thread
From: Akhil Goyal @ 2020-07-04 19:55 UTC (