DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism
@ 2016-01-30 13:10 Declan Doherty
  2016-02-02 17:38 ` De Lara Guarch, Pablo
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Declan Doherty @ 2016-01-30 13:10 UTC (permalink / raw)
  To: dev

This patch add a mechanism for discovery of crypto device features and supported
crypto operations and algorithms. It also provides a method for a crypto PMD to
publish any data range limitations it may have for the operations and algorithms
it supports.

The parameter feature_flags added to rte_cryptodev struct is used to capture
features such as operations supported (symmetric crypto, operation chaining etc)
as well parameter such as whether the device is hardware accelerated or uses
SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported operations
with any limitation which that implementation may have.

Finally the rte_cryptodev_info struct has been extended to allow retrieval of
these parameter using the existing rte_cryptodev_info_get() API.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c     |  19 ++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c |  83 +++++++++++++++++
 drivers/crypto/qat/qat_crypto.c                |  83 ++++++++++++++++-
 drivers/crypto/qat/rte_qat_cryptodev.c         |   2 +
 lib/librte_cryptodev/rte_crypto.h              |   7 ++
 lib/librte_cryptodev/rte_cryptodev.c           |  28 ++++++
 lib/librte_cryptodev/rte_cryptodev.h           | 123 +++++++++++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_version.map |   2 +-
 8 files changed, 345 insertions(+), 2 deletions(-)

diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index d8ccf05..a759829 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -572,6 +572,7 @@ aesni_mb_pmd_dequeue_burst(void *queue_pair,
 }
 
 
+
 static int cryptodev_aesni_mb_uninit(const char *name);
 
 static int
@@ -622,6 +623,24 @@ cryptodev_aesni_mb_create(const char *name, unsigned socket_id)
 	dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_MB_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
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 96d22f6..368a803 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -38,6 +38,87 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_MD5_HMAC, 64, 16, 12, { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA1_HMAC, 20, 64, 12, { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA224_HMAC, 28, 64, 14, { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA256_HMAC, 32, 64, 16, { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA384_HMAC, 48, 128, 24, { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA512_HMAC, 64, 128, 32, { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_AES_XCBC_MAC, 16, 16, 12,
+				.aad = { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.key = { 16, 16, 0 },
+				.iv = { 16, 16, 0 }
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -107,6 +188,8 @@ aesni_mb_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->max_nb_sessions = internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypto.c
index 47b257f..dce055f 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,86 @@
 #include "adf_transport_access_macros.h"
 
 
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_MD5_HMAC, 64, 16, 16, { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA1_HMAC, 64, 20, 20, { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA256_HMAC, 64, 32, 32, { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA384_HMAC, 128, 48, 48, { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_SHA512_HMAC, 128, 64, 64, { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_AUTH,
+			.auth = {
+				RTE_CRYPTO_AUTH_AES_XCBC_MAC, 16, 16, 16, { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.key = { 16, 16, 0 },
+				.iv = { 16, 16, 0 }
+			}
+		}
+	},
+	{	/* AES CTR */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.type = RTE_CRYPTO_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CTR,
+				.key = { 16, 16, 0 },
+				.iv = { 16, 16, 0 }
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
 
@@ -519,7 +599,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev *dev,
 		info->max_nb_queue_pairs =
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = qat_pmd_capabilities;
 		info->max_nb_sessions = internals->max_nb_sessions;
 		info->dev_type = RTE_CRYPTODEV_QAT_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index e500c1e..169ef24 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -95,6 +95,8 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 	cryptodev->enqueue_burst = qat_crypto_pkt_tx_burst;
 	cryptodev->dequeue_burst = qat_crypto_pkt_rx_burst;
 
+	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED;
 
 	internals = cryptodev->data->dev_private;
 	internals->max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS;
diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h
index 42343a8..3e39693 100644
--- a/lib/librte_cryptodev/rte_crypto.h
+++ b/lib/librte_cryptodev/rte_crypto.h
@@ -581,6 +581,13 @@ struct rte_crypto_op {
 };
 
 
+enum rte_crypto_op_type {
+	RTE_CRYPTO_OP_TYPE_UNDEFINED = 0,
+
+	RTE_CRYPTO_OP_TYPE_SYMMETRIC
+};
+
+
 /**
  * Reset the fields of a crypto operation to their default values.
  *
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index f09f67e..f8fd992 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -102,6 +102,34 @@ struct rte_cryptodev_callback {
 	uint32_t active;			/**< Callback is executing */
 };
 
+
+const char *
+rte_cryptodev_get_feature_name(uint64_t flag)
+{
+	switch (flag) {
+	case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
+		return "SYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
+		return "ASYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_OPERATION_CHAINING:
+		return "OPERATION_CHAINING";
+	case RTE_CRYPTODEV_FF_CPU_SSE:
+		return "CPU_SSE";
+	case RTE_CRYPTODEV_FF_CPU_AVX:
+		return "CPU_AVX";
+	case RTE_CRYPTODEV_FF_CPU_AVX2:
+		return "CPU_AVX2";
+	case RTE_CRYPTODEV_FF_CPU_AESNI:
+		return "CPU_AESNI";
+	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
+		return "HW_ACCELERATED";
+
+	default:
+		return NULL;
+	}
+}
+
+
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index 892375d..61a162b 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -91,12 +91,131 @@ enum rte_cryptodev_type {
 #define CDEV_PMD_TRACE(fmt, args...)
 #endif
 
+
+/**
+ * Symmetric Crypto Capability
+ */
+struct rte_cryptodev_symmetric_capability {
+	enum rte_crypto_xform_type type;
+	/**< Transform type : Authentication / Cipher */
+
+	union {
+		struct {
+			enum rte_crypto_auth_algorithm algo;
+			/**< authentication algorithm */
+			uint16_t block;
+			/**< algorithm block size */
+			uint16_t key;
+			/**< Key size supported */
+			uint16_t digest;
+			/**< Maximum digest size supported */
+			struct {
+				uint16_t min;	/**< minimum aad size */
+				uint16_t max;	/**< maximum aad size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} aad;
+			/**< Additional authentication data size range */
+		} auth;
+		/**< Symmetric Authentication transform capabilities */
+		struct {
+			enum rte_crypto_cipher_algorithm algo;
+			/**< cipher algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key;
+			/**< cipher key size range */
+			struct {
+				uint16_t min;	/**< minimum iv size */
+				uint16_t max;	/**< maximum iv size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} iv;
+			/**< Initialisation vector data size range */
+		} cipher;
+		/**< Symmetric Cipher transform capabilities */
+	};
+};
+
+/** Structure used to capture a capability of a crypto device */
+struct rte_cryptodev_capabilities {
+	enum rte_crypto_op_type op;
+	/**< Operation type */
+
+	union {
+		struct rte_cryptodev_symmetric_capability sym;
+		/**< Symmetric operation capability parameters */
+	};
+};
+
+/** Macro used at end of crypto PMD list */
+#define RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
+	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
+
+
+/**
+ * Crypto device supported feature flags
+ *
+ * Note:
+ * New features flags should be added to the end of the list
+ *
+ * Keep these flags synchronised with rte_cryptodev_get_feature_name()
+ */
+#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
+/**< Symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
+/**< Asymmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_OPERATION_CHAINING	(1ULL << 2)
+/**< Chaining crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
+/**< Utilises CPU SIMD SSE instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
+/**< Utilises CPU SIMD AVX instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
+/**< Utilises CPU SIMD AVX2 instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
+/**< Utilises CPU AES-NI instructions */
+#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
+/**< Operations are off-loaded to an external hardware accelerator */
+
+
+/**
+ * Get the name of a crypto device feature flag
+ *
+ * @param	mask	The mask describing the flag.
+ *
+ * @return
+ *   The name of this flag, or NULL if it's not a valid feature flag.
+ */
+
+extern const char *
+rte_cryptodev_get_feature_name(uint64_t flag);
+
 /**  Crypto device information */
 struct rte_cryptodev_info {
 	const char *driver_name;		/**< Driver name. */
 	enum rte_cryptodev_type dev_type;	/**< Device type */
 	struct rte_pci_device *pci_dev;		/**< PCI information. */
 
+	uint64_t feature_flags;			/**< Feature flags */
+
+	const struct rte_cryptodev_capabilities *capabilities;
+	/**< Array of devices supported capabilities */
+
 	unsigned max_nb_queue_pairs;
 	/**< Maximum number of queues pairs supported by device. */
 	unsigned max_nb_sessions;
@@ -449,6 +568,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp, struct rte_mbuf **pkts,
 /**< Enqueue packets for processing on queue pair of a device. */
 
 
+
+
 struct rte_cryptodev_callback;
 
 /** Structure to keep track of registered callbacks */
@@ -467,6 +588,8 @@ struct rte_cryptodev {
 	/**< Pointer to device data */
 	struct rte_cryptodev_ops *dev_ops;
 	/**< Functions exported by PMD */
+	uint64_t feature_flags;
+	/**< Supported features */
 	struct rte_pci_device *pci_dev;
 	/**< PCI info. supplied by probing */
 
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index ff8e93d..9cd12cf 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -10,6 +10,7 @@ DPDK_2.2 {
 	rte_cryptodev_configure;
 	rte_cryptodev_create_vdev;
 	rte_cryptodev_get_dev_id;
+	rte_cryptodev_get_feature_name;
 	rte_cryptodev_info_get;
 	rte_cryptodev_pmd_allocate;
 	rte_cryptodev_pmd_callback_process;
@@ -27,6 +28,5 @@ DPDK_2.2 {
 	rte_cryptodev_queue_pair_setup;
 	rte_cryptodev_queue_pair_start;
 	rte_cryptodev_queue_pair_stop;
-
 	local: *;
 };
\ No newline at end of file
-- 
2.5.0

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

* Re: [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism
  2016-01-30 13:10 [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism Declan Doherty
@ 2016-02-02 17:38 ` De Lara Guarch, Pablo
  2016-02-10 16:37 ` Trahe, Fiona
  2016-03-10 17:07 ` [dpdk-dev] [PATCH v2] " Pablo de Lara
  2 siblings, 0 replies; 13+ messages in thread
From: De Lara Guarch, Pablo @ 2016-02-02 17:38 UTC (permalink / raw)
  To: Doherty, Declan, dev

Hi Declan,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Declan Doherty
> Sent: Saturday, January 30, 2016 1:11 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH] cryptodev: add capabilities discovery
> mechanism

[...]

> --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
> +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
> @@ -572,6 +572,7 @@ aesni_mb_pmd_dequeue_burst(void *queue_pair,
>  }
> 
> 
> +

Remove this blank line.

>  static int cryptodev_aesni_mb_uninit(const char *name);
> 
>  static int
> @@ -622,6 +623,24 @@ cryptodev_aesni_mb_create(const char *name,
> unsigned socket_id)

[...]

> 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 96d22f6..368a803 100644
> --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
> +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
> @@ -38,6 +38,87 @@
> 
>  #include "rte_aesni_mb_pmd_private.h"
> 
> +
> +static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[]
> = {
> +	{	/* MD5 HMAC */
> +		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
> +		.sym = {
> +			.type = RTE_CRYPTO_XFORM_AUTH,
> +			.auth = {
> +				RTE_CRYPTO_AUTH_MD5_HMAC, 64, 16, 12,
> { 0 }

I would use the variable names to set the values,
it will be longer but I find it more readable.

> +			}
> +		}

[...]

> diff --git a/lib/librte_cryptodev/rte_cryptodev.h
> b/lib/librte_cryptodev/rte_cryptodev.h
> index 892375d..61a162b 100644
> --- a/lib/librte_cryptodev/rte_cryptodev.h
> +++ b/lib/librte_cryptodev/rte_cryptodev.h
> @@ -91,12 +91,131 @@ enum rte_cryptodev_type {
>  #define CDEV_PMD_TRACE(fmt, args...)
>  #endif
> 
> +
> +/**
> + * Symmetric Crypto Capability
> + */
> +struct rte_cryptodev_symmetric_capability {
> +	enum rte_crypto_xform_type type;
> +	/**< Transform type : Authentication / Cipher */
> +
> +	union {
> +		struct {
> +			enum rte_crypto_auth_algorithm algo;
> +			/**< authentication algorithm */
> +			uint16_t block;

Suggest to rename most variables to x_size (i.e. block_size).

> +			/**< algorithm block size */
> +			uint16_t key;
> +			/**< Key size supported */


In cipher structure, key size is a structure supporting a range of sizes,
authentication key does not need it?

> +			uint16_t digest;
> +			/**< Maximum digest size supported */
> +			struct {
> +				uint16_t min;	/**< minimum aad size */
> +				uint16_t max;	/**< maximum aad size */
> +				uint16_t increment;
> +				/**< if a range of sizes are supported,
> +				 * this parameter is used to indicate
> +				 * increments in byte size that are supported
> +				 * between the minimum and maximum */
> +			} aad;

[...]

> +/**
> + * Get the name of a crypto device feature flag
> + *
> + * @param	mask	The mask describing the flag.

Wrong parameter name.

> + *
> + * @return
> + *   The name of this flag, or NULL if it's not a valid feature flag.
> + */
> +
> +extern const char *
> +rte_cryptodev_get_feature_name(uint64_t flag);
> +

[...]

> diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map
> b/lib/librte_cryptodev/rte_cryptodev_version.map
> index ff8e93d..9cd12cf 100644
> --- a/lib/librte_cryptodev/rte_cryptodev_version.map
> +++ b/lib/librte_cryptodev/rte_cryptodev_version.map
> @@ -10,6 +10,7 @@ DPDK_2.2 {
>  	rte_cryptodev_configure;
>  	rte_cryptodev_create_vdev;
>  	rte_cryptodev_get_dev_id;
> +	rte_cryptodev_get_feature_name;
>  	rte_cryptodev_info_get;
>  	rte_cryptodev_pmd_allocate;
>  	rte_cryptodev_pmd_callback_process;
> @@ -27,6 +28,5 @@ DPDK_2.2 {
>  	rte_cryptodev_queue_pair_setup;
>  	rte_cryptodev_queue_pair_start;
>  	rte_cryptodev_queue_pair_stop;
> -

No need to remove the blank line here.

>  	local: *;
>  };
> \ No newline at end of file
> --
> 2.5.0

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

* Re: [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism
  2016-01-30 13:10 [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism Declan Doherty
  2016-02-02 17:38 ` De Lara Guarch, Pablo
@ 2016-02-10 16:37 ` Trahe, Fiona
  2016-03-10 17:07 ` [dpdk-dev] [PATCH v2] " Pablo de Lara
  2 siblings, 0 replies; 13+ messages in thread
From: Trahe, Fiona @ 2016-02-10 16:37 UTC (permalink / raw)
  To: Doherty, Declan, dev

Hi Declan,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Declan Doherty
> Sent: Saturday, January 30, 2016 1:11 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism
> 
> This patch add a mechanism for discovery of crypto device features and
> supported crypto operations and algorithms. It also provides a method for a
> crypto PMD to publish any data range limitations it may have for the operations
> and algorithms it supports.
> 
> The parameter feature_flags added to rte_cryptodev struct is used to capture
> features such as operations supported (symmetric crypto, operation chaining
> etc) as well parameter such as whether the device is hardware accelerated or
> uses SIMD instructions.
> 
> The capabilities parameter allows a PMD to define an array of supported
> operations with any limitation which that implementation may have.
> 
> Finally the rte_cryptodev_info struct has been extended to allow retrieval of
> these parameter using the existing rte_cryptodev_info_get() API.
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>


There's a lot of good data in the Capabilities struct, but is there a use-case for it?  Is it likely an application will call this API and validate everything?
Or is it more likely it would just check for algorithm support and if it then uses an unsupported block_size, key_size, etc it will get an invalid param from the PMD and handle this? 

Secondly, instead of spreading capabilities across 2 data elements (feature bitmask and op capabilities struct), see suggestion below to roll all into a single struct.

//snip//

> +
> +/**
> + * Symmetric Crypto Capability
> + */
> +struct rte_cryptodev_symmetric_capability {
> +	enum rte_crypto_xform_type type;
> +	/**< Transform type : Authentication / Cipher */
> +

It would be more helpful to call this xform_type

> +	union {
> +		struct {
> +			enum rte_crypto_auth_algorithm algo;
> +			/**< authentication algorithm */
> +			uint16_t block;
> +			/**< algorithm block size */
> +			uint16_t key;
> +			/**< Key size supported */
> +			uint16_t digest;
> +			/**< Maximum digest size supported */
> +			struct {
> +				uint16_t min;	/**< minimum aad size */
> +				uint16_t max;	/**< maximum aad size */
> +				uint16_t increment;
> +				/**< if a range of sizes are supported,
> +				 * this parameter is used to indicate
> +				 * increments in byte size that are supported
> +				 * between the minimum and maximum */
> +			} aad;
> +			/**< Additional authentication data size range */
> +		} auth;
> +		/**< Symmetric Authentication transform capabilities */
> +		struct {
> +			enum rte_crypto_cipher_algorithm algo;
> +			/**< cipher algorithm */
> +			uint16_t block_size;
> +			/**< algorithm block size */
> +			struct {
> +				uint16_t min;	/**< minimum key size */
> +				uint16_t max;	/**< maximum key size */
> +				uint16_t increment;
> +				/**< if a range of sizes are supported,
> +				 * this parameter is used to indicate
> +				 * increments in byte size that are supported
> +				 * between the minimum and maximum */
> +			} key;
> +			/**< cipher key size range */
> +			struct {
> +				uint16_t min;	/**< minimum iv size */
> +				uint16_t max;	/**< maximum iv size */
> +				uint16_t increment;
> +				/**< if a range of sizes are supported,
> +				 * this parameter is used to indicate
> +				 * increments in byte size that are supported
> +				 * between the minimum and maximum */
> +			} iv;
> +			/**< Initialisation vector data size range */
> +		} cipher;
> +		/**< Symmetric Cipher transform capabilities */
> +	};
> +};
> +
> +/** Structure used to capture a capability of a crypto device */ struct
> +rte_cryptodev_capabilities {
> +	enum rte_crypto_op_type op;
> +	/**< Operation type */
> +
> +	union {
> +		struct rte_cryptodev_symmetric_capability sym;
> +		/**< Symmetric operation capability parameters */
> +	};
> +};
> +
> +/** Macro used at end of crypto PMD list */ #define
> +RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
> +	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
> +
> +
> +/**
> + * Crypto device supported feature flags
> + *
> + * Note:
> + * New features flags should be added to the end of the list
> + *
> + * Keep these flags synchronised with rte_cryptodev_get_feature_name()
> +*/
> +#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
> +/**< Symmetric crypto operations are supported */
> +#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
> +/**< Asymmetric crypto operations are supported */
> +#define	RTE_CRYPTODEV_FF_OPERATION_CHAINING	(1ULL << 2)
> +/**< Chaining crypto operations are supported */

Should this flag be moved into the rte_cryptodev_symmetric_capability and have a more complex structure?
e.g. chaining of AES and SHA-HMAC could be supported, but not chaining of snow3g UEA2/UIA2?
But this leads to my overall comment - do we really need this level of detail in capabilities?

If keeping as a feature flag, then call it SYM_OP_CHAINING?


> +#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
> +/**< Utilises CPU SIMD SSE instructions */
> +#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
> +/**< Utilises CPU SIMD AVX instructions */
> +#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
> +/**< Utilises CPU SIMD AVX2 instructions */
> +#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
> +/**< Utilises CPU AES-NI instructions */
> +#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL
> << 7)
> +/**< Operations are off-loaded to an external hardware accelerator */
> +
> +
> +/**
> + * Get the name of a crypto device feature flag
> + *
> + * @param	mask	The mask describing the flag.
> + *
> + * @return
> + *   The name of this flag, or NULL if it's not a valid feature flag.
> + */
> +
> +extern const char *
> +rte_cryptodev_get_feature_name(uint64_t flag);
> +
>  /**  Crypto device information */
>  struct rte_cryptodev_info {
>  	const char *driver_name;		/**< Driver name. */
>  	enum rte_cryptodev_type dev_type;	/**< Device type */
>  	struct rte_pci_device *pci_dev;		/**< PCI information. */
> 
> +	uint64_t feature_flags;			/**< Feature flags */
> +
> +	const struct rte_cryptodev_capabilities *capabilities;
> +	/**< Array of devices supported capabilities */
> +

Instead of spreading capabilities across 2 data elements (feature_flags bitmask and op capabilities struct), I think it's better to roll all into a single struct.
i.e. feature-flags are just another type of capability, but a device capability rather than an op capability.
 
e.g.
/** Structure used to capture a capability of a crypto device */
struct rte_cryptodev_capabilities {
	enum rte_crypto_capability_type cap_type; /* this was enum rte_crypto_op_type op; */
	/**< Capability_type: device_cap/sym_op_cap/asym_op_cap     */

	union {
		struct rte_cryptodev_symmetric_capability sym_op_cap;
		/**< Symmetric operation capability parameters */
		struct rte_cryptodev_device_capability device_cap;
		/**< Device capability */
	};
};

struct rte_cryptodev_device_capability {
	enum rte_crypto_device_feature feature_id; 
	/**< same elements as the feature bitmask, but an enum, i.e. hw_acceleration, cpu_aesni, cpu_avx, sym_sy, asym_cy */
	const char rte_crypto_device_feature feature_name[MAX_FEATURE_NAME_LEN];
};




//snip//

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

* [dpdk-dev] [PATCH v2] cryptodev: add capabilities discovery mechanism
  2016-01-30 13:10 [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism Declan Doherty
  2016-02-02 17:38 ` De Lara Guarch, Pablo
  2016-02-10 16:37 ` Trahe, Fiona
@ 2016-03-10 17:07 ` Pablo de Lara
  2016-03-10 19:54   ` [dpdk-dev] [PATCH v3] " Pablo de Lara
  2016-03-14  8:26   ` [dpdk-dev] [PATCH v2] " Cao, Min
  2 siblings, 2 replies; 13+ messages in thread
From: Pablo de Lara @ 2016-03-10 17:07 UTC (permalink / raw)
  To: dev

From: Declan Doherty <declan.doherty@intel.com>

This patch add a mechanism for discovery of crypto device features and supported
crypto operations and algorithms. It also provides a method for a crypto PMD to
publish any data range limitations it may have for the operations and algorithms
it supports.

The parameter feature_flags added to rte_cryptodev struct is used to capture
features such as operations supported (symmetric crypto, operation chaining etc)
as well parameter such as whether the device is hardware accelerated or uses
SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported operations
with any limitation which that implementation may have.

Finally the rte_cryptodev_info struct has been extended to allow retrieval of
these parameter using the existing rte_cryptodev_info_get() API.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

---

This patch depends on "null_crypto_pmd: PMD to support null crypto operations" patch
(http://dpdk.org/dev/patchwork/patch/11428/)
and "snow3g: Bit-wise handling for Wireless Algorithm" patch
(http://dpdk.org/dev/patchwork/patch/11429/)

Changes in v2:

- Fixed incorrect values for sizes
- Renamed some fields in capabilities structure
- Added capabilities for new PMDs

 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c       |  18 +++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c   |  49 ++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c     |  18 +++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c | 175 +++++++++++++++++++++
 drivers/crypto/null/null_crypto_pmd.c          |   3 +
 drivers/crypto/null/null_crypto_pmd_ops.c      |  47 ++++++
 drivers/crypto/qat/qat_crypto.c                | 201 ++++++++++++++++++++++++-
 drivers/crypto/qat/rte_qat_cryptodev.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd_ops.c     |  51 +++++++
 lib/librte_cryptodev/rte_cryptodev.c           |  28 ++++
 lib/librte_cryptodev/rte_cryptodev.h           | 137 +++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_version.map |   1 +
 13 files changed, 733 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 83aa272..c94bb7d 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -445,6 +445,24 @@ aesni_gcm_create(const char *name,
 	dev->dequeue_burst = aesni_gcm_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_gcm_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_GCM_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_GCM_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_GCM_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
index f865e0d..af7907b 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "aesni_gcm_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 aesni_gcm_pmd_config(__rte_unused struct rte_cryptodev *dev)
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 9599cc4..bd273ec 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -640,6 +640,24 @@ cryptodev_aesni_mb_create(const char *name, unsigned socket_id)
 	dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_MB_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
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 b1dd103..5a439e6 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -38,6 +38,179 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 14,
+					.max = 14,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 24,
+					.max = 24,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -107,6 +280,8 @@ aesni_mb_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index a4bb152..5b8cb13 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -215,6 +215,9 @@ cryptodev_null_create(const char *name,
 	dev->dequeue_burst = null_crypto_pmd_dequeue_burst;
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_qpairs = init_params->max_nb_queue_pairs;
diff --git a/drivers/crypto/null/null_crypto_pmd_ops.c b/drivers/crypto/null/null_crypto_pmd_ops.c
index 6bf955e..39f8088 100644
--- a/drivers/crypto/null/null_crypto_pmd_ops.c
+++ b/drivers/crypto/null/null_crypto_pmd_ops.c
@@ -38,6 +38,51 @@
 
 #include "null_crypto_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilities[] = {
+	{	/* NULL (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* NULL (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 null_crypto_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -108,6 +153,8 @@ null_crypto_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_qpairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = null_crypto_pmd_capabilities;
 	}
 }
 
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypto.c
index f267da5..29c1fe5 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,204 @@
 
 #define BYTE_LENGTH    8
 
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] = {
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 20,
+					.max = 20,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC MAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
 
@@ -652,7 +850,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev *dev,
 		info->max_nb_queue_pairs =
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = qat_pmd_capabilities;
 		info->sym.max_nb_sessions = internals->max_nb_sessions;
 		info->dev_type = RTE_CRYPTODEV_QAT_SYM_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 5e51aca..ba1b06b 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -95,6 +95,9 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 	cryptodev->enqueue_burst = qat_pmd_enqueue_op_burst;
 	cryptodev->dequeue_burst = qat_pmd_dequeue_op_burst;
 
+	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
 
 	internals = cryptodev->data->dev_private;
 	internals->max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS;
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 6f84e5c..17175c7 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -490,6 +490,9 @@ cryptodev_snow3g_create(const char *name,
 	dev->dequeue_burst = snow3g_pmd_dequeue_burst;
 	dev->enqueue_burst = snow3g_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs;
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
index 5643323..74eee23 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "rte_snow3g_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities snow3g_pmd_capabilities[] = {
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 snow3g_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -109,6 +158,8 @@ snow3g_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = snow3g_pmd_capabilities;
 	}
 }
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 4632ca3..49af2fc 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -102,6 +102,34 @@ struct rte_cryptodev_callback {
 	uint32_t active;			/**< Callback is executing */
 };
 
+
+const char *
+rte_cryptodev_get_feature_name(uint64_t flag)
+{
+	switch (flag) {
+	case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
+		return "SYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
+		return "ASYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_OPERATION_CHAINING:
+		return "OPERATION_CHAINING";
+	case RTE_CRYPTODEV_FF_CPU_SSE:
+		return "CPU_SSE";
+	case RTE_CRYPTODEV_FF_CPU_AVX:
+		return "CPU_AVX";
+	case RTE_CRYPTODEV_FF_CPU_AVX2:
+		return "CPU_AVX2";
+	case RTE_CRYPTODEV_FF_CPU_AESNI:
+		return "CPU_AESNI";
+	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
+		return "HW_ACCELERATED";
+
+	default:
+		return NULL;
+	}
+}
+
+
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index eb85c46..b989f9c 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -98,12 +98,145 @@ extern const char **rte_cyptodev_names;
 #define CDEV_PMD_TRACE(fmt, args...)
 #endif
 
+/**
+ * Symmetric Crypto Capability
+ */
+struct rte_cryptodev_symmetric_capability {
+	enum rte_crypto_sym_xform_type xform_type;
+	/**< Transform type : Authentication / Cipher */
+	union {
+		struct {
+			enum rte_crypto_auth_algorithm algo;
+			/**< authentication algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< auth key size range */
+			struct {
+				uint16_t min;	/**< minimum digest size */
+				uint16_t max;	/**< maximum digest size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} digest_size;
+			/**< digest size range */
+			struct {
+				uint16_t min;	/**< minimum aad size */
+				uint16_t max;	/**< maximum aad size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} aad_size;
+			/**< Additional authentication data size range */
+		} auth;
+		/**< Symmetric Authentication transform capabilities */
+		struct {
+			enum rte_crypto_cipher_algorithm algo;
+			/**< cipher algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< cipher key size range */
+			struct {
+				uint16_t min;	/**< minimum iv size */
+				uint16_t max;	/**< maximum iv size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} iv_size;
+			/**< Initialisation vector data size range */
+		} cipher;
+		/**< Symmetric Cipher transform capabilities */
+	};
+};
+
+/** Structure used to capture a capability of a crypto device */
+struct rte_cryptodev_capabilities {
+	enum rte_crypto_op_type op;
+	/**< Operation type */
+
+	union {
+		struct rte_cryptodev_symmetric_capability sym;
+		/**< Symmetric operation capability parameters */
+	};
+};
+
+/** Macro used at end of crypto PMD list */
+#define RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
+	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
+
+
+/**
+ * Crypto device supported feature flags
+ *
+ * Note:
+ * New features flags should be added to the end of the list
+ *
+ * Keep these flags synchronised with rte_cryptodev_get_feature_name()
+ */
+#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
+/**< Symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
+/**< Asymmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_OPERATION_CHAINING	(1ULL << 2)
+/**< Chaining crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
+/**< Utilises CPU SIMD SSE instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
+/**< Utilises CPU SIMD AVX instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
+/**< Utilises CPU SIMD AVX2 instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
+/**< Utilises CPU AES-NI instructions */
+#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
+/**< Operations are off-loaded to an external hardware accelerator */
+
+
+/**
+ * Get the name of a crypto device feature flag
+ *
+ * @param	flag	The mask describing the flag.
+ *
+ * @return
+ *   The name of this flag, or NULL if it's not a valid feature flag.
+ */
+
+extern const char *
+rte_cryptodev_get_feature_name(uint64_t flag);
+
 /**  Crypto device information */
 struct rte_cryptodev_info {
 	const char *driver_name;		/**< Driver name. */
 	enum rte_cryptodev_type dev_type;	/**< Device type */
 	struct rte_pci_device *pci_dev;		/**< PCI information. */
 
+	uint64_t feature_flags;			/**< Feature flags */
+
+	const struct rte_cryptodev_capabilities *capabilities;
+	/**< Array of devices supported capabilities */
+
 	unsigned max_nb_queue_pairs;
 	/**< Maximum number of queues pairs supported by device. */
 
@@ -540,6 +673,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp,
 /**< Enqueue packets for processing on queue pair of a device. */
 
 
+
+
 struct rte_cryptodev_callback;
 
 /** Structure to keep track of registered callbacks */
@@ -558,6 +693,8 @@ struct rte_cryptodev {
 	/**< Pointer to device data */
 	struct rte_cryptodev_ops *dev_ops;
 	/**< Functions exported by PMD */
+	uint64_t feature_flags;
+	/**< Supported features */
 	struct rte_pci_device *pci_dev;
 	/**< PCI info. supplied by probing */
 
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 6de6c7d..41004e1 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -10,6 +10,7 @@ DPDK_16.04 {
 	rte_cryptodev_configure;
 	rte_cryptodev_create_vdev;
 	rte_cryptodev_get_dev_id;
+	rte_cryptodev_get_feature_name;
 	rte_cryptodev_info_get;
 	rte_cryptodev_pmd_allocate;
 	rte_cryptodev_pmd_callback_process;
-- 
2.5.0

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

* [dpdk-dev] [PATCH v3] cryptodev: add capabilities discovery mechanism
  2016-03-10 17:07 ` [dpdk-dev] [PATCH v2] " Pablo de Lara
@ 2016-03-10 19:54   ` Pablo de Lara
  2016-03-10 21:27     ` Trahe, Fiona
                       ` (3 more replies)
  2016-03-14  8:26   ` [dpdk-dev] [PATCH v2] " Cao, Min
  1 sibling, 4 replies; 13+ messages in thread
From: Pablo de Lara @ 2016-03-10 19:54 UTC (permalink / raw)
  To: dev

From: Declan Doherty <declan.doherty@intel.com>

This patch add a mechanism for discovery of crypto device features and supported
crypto operations and algorithms. It also provides a method for a crypto PMD to
publish any data range limitations it may have for the operations and algorithms
it supports.

The parameter feature_flags added to rte_cryptodev struct is used to capture
features such as operations supported (symmetric crypto, operation chaining etc)
as well parameter such as whether the device is hardware accelerated or uses
SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported operations
with any limitation which that implementation may have.

Finally the rte_cryptodev_info struct has been extended to allow retrieval of
these parameter using the existing rte_cryptodev_info_get() API.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---

This patch depends on "null_crypto_pmd: PMD to support null crypto operations" patch
(http://dpdk.org/dev/patchwork/patch/11428/)
and "snow3g: Bit-wise handling for Wireless Algorithm" patch
(http://dpdk.org/dev/patchwork/patch/11429/)

Changes in v3:

- Renamed macro to specify symmetric algo chaining

Changes in v2:

- Fixed incorrect values for sizes
- Renamed some fields in capabilities structure
- Added capabilities for new PMDs


 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c       |  18 +++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c   |  49 ++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c     |  18 +++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c | 175 +++++++++++++++++++++
 drivers/crypto/null/null_crypto_pmd.c          |   3 +
 drivers/crypto/null/null_crypto_pmd_ops.c      |  47 ++++++
 drivers/crypto/qat/qat_crypto.c                | 201 ++++++++++++++++++++++++-
 drivers/crypto/qat/rte_qat_cryptodev.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd_ops.c     |  51 +++++++
 lib/librte_cryptodev/rte_cryptodev.c           |  28 ++++
 lib/librte_cryptodev/rte_cryptodev.h           | 137 +++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_version.map |   1 +
 13 files changed, 733 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 83aa272..35577bc 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -445,6 +445,24 @@ aesni_gcm_create(const char *name,
 	dev->dequeue_burst = aesni_gcm_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_gcm_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_GCM_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_GCM_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_GCM_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
index f865e0d..af7907b 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "aesni_gcm_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 aesni_gcm_pmd_config(__rte_unused struct rte_cryptodev *dev)
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 9599cc4..4e3885c 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -640,6 +640,24 @@ cryptodev_aesni_mb_create(const char *name, unsigned socket_id)
 	dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_MB_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
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 b1dd103..5a439e6 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -38,6 +38,179 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 14,
+					.max = 14,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 24,
+					.max = 24,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -107,6 +280,8 @@ aesni_mb_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index a4bb152..82b990c 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -215,6 +215,9 @@ cryptodev_null_create(const char *name,
 	dev->dequeue_burst = null_crypto_pmd_dequeue_burst;
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_qpairs = init_params->max_nb_queue_pairs;
diff --git a/drivers/crypto/null/null_crypto_pmd_ops.c b/drivers/crypto/null/null_crypto_pmd_ops.c
index 6bf955e..39f8088 100644
--- a/drivers/crypto/null/null_crypto_pmd_ops.c
+++ b/drivers/crypto/null/null_crypto_pmd_ops.c
@@ -38,6 +38,51 @@
 
 #include "null_crypto_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilities[] = {
+	{	/* NULL (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* NULL (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 null_crypto_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -108,6 +153,8 @@ null_crypto_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_qpairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = null_crypto_pmd_capabilities;
 	}
 }
 
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypto.c
index f267da5..29c1fe5 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,204 @@
 
 #define BYTE_LENGTH    8
 
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] = {
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 20,
+					.max = 20,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC MAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
 
@@ -652,7 +850,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev *dev,
 		info->max_nb_queue_pairs =
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = qat_pmd_capabilities;
 		info->sym.max_nb_sessions = internals->max_nb_sessions;
 		info->dev_type = RTE_CRYPTODEV_QAT_SYM_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 5e51aca..a7912f5 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -95,6 +95,9 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 	cryptodev->enqueue_burst = qat_pmd_enqueue_op_burst;
 	cryptodev->dequeue_burst = qat_pmd_dequeue_op_burst;
 
+	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
 
 	internals = cryptodev->data->dev_private;
 	internals->max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS;
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 6f84e5c..97c7fb5 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -490,6 +490,9 @@ cryptodev_snow3g_create(const char *name,
 	dev->dequeue_burst = snow3g_pmd_dequeue_burst;
 	dev->enqueue_burst = snow3g_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs;
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
index 5643323..74eee23 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "rte_snow3g_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities snow3g_pmd_capabilities[] = {
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 snow3g_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -109,6 +158,8 @@ snow3g_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = snow3g_pmd_capabilities;
 	}
 }
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 4632ca3..2d72dd7 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -102,6 +102,34 @@ struct rte_cryptodev_callback {
 	uint32_t active;			/**< Callback is executing */
 };
 
+
+const char *
+rte_cryptodev_get_feature_name(uint64_t flag)
+{
+	switch (flag) {
+	case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
+		return "SYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
+		return "ASYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
+		return "SYM_OPERATION_CHAINING";
+	case RTE_CRYPTODEV_FF_CPU_SSE:
+		return "CPU_SSE";
+	case RTE_CRYPTODEV_FF_CPU_AVX:
+		return "CPU_AVX";
+	case RTE_CRYPTODEV_FF_CPU_AVX2:
+		return "CPU_AVX2";
+	case RTE_CRYPTODEV_FF_CPU_AESNI:
+		return "CPU_AESNI";
+	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
+		return "HW_ACCELERATED";
+
+	default:
+		return NULL;
+	}
+}
+
+
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index eb85c46..b599c95 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -98,12 +98,145 @@ extern const char **rte_cyptodev_names;
 #define CDEV_PMD_TRACE(fmt, args...)
 #endif
 
+/**
+ * Symmetric Crypto Capability
+ */
+struct rte_cryptodev_symmetric_capability {
+	enum rte_crypto_sym_xform_type xform_type;
+	/**< Transform type : Authentication / Cipher */
+	union {
+		struct {
+			enum rte_crypto_auth_algorithm algo;
+			/**< authentication algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< auth key size range */
+			struct {
+				uint16_t min;	/**< minimum digest size */
+				uint16_t max;	/**< maximum digest size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} digest_size;
+			/**< digest size range */
+			struct {
+				uint16_t min;	/**< minimum aad size */
+				uint16_t max;	/**< maximum aad size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} aad_size;
+			/**< Additional authentication data size range */
+		} auth;
+		/**< Symmetric Authentication transform capabilities */
+		struct {
+			enum rte_crypto_cipher_algorithm algo;
+			/**< cipher algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< cipher key size range */
+			struct {
+				uint16_t min;	/**< minimum iv size */
+				uint16_t max;	/**< maximum iv size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} iv_size;
+			/**< Initialisation vector data size range */
+		} cipher;
+		/**< Symmetric Cipher transform capabilities */
+	};
+};
+
+/** Structure used to capture a capability of a crypto device */
+struct rte_cryptodev_capabilities {
+	enum rte_crypto_op_type op;
+	/**< Operation type */
+
+	union {
+		struct rte_cryptodev_symmetric_capability sym;
+		/**< Symmetric operation capability parameters */
+	};
+};
+
+/** Macro used at end of crypto PMD list */
+#define RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
+	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
+
+
+/**
+ * Crypto device supported feature flags
+ *
+ * Note:
+ * New features flags should be added to the end of the list
+ *
+ * Keep these flags synchronised with rte_cryptodev_get_feature_name()
+ */
+#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
+/**< Symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
+/**< Asymmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING	(1ULL << 2)
+/**< Chaining symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
+/**< Utilises CPU SIMD SSE instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
+/**< Utilises CPU SIMD AVX instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
+/**< Utilises CPU SIMD AVX2 instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
+/**< Utilises CPU AES-NI instructions */
+#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
+/**< Operations are off-loaded to an external hardware accelerator */
+
+
+/**
+ * Get the name of a crypto device feature flag
+ *
+ * @param	flag	The mask describing the flag.
+ *
+ * @return
+ *   The name of this flag, or NULL if it's not a valid feature flag.
+ */
+
+extern const char *
+rte_cryptodev_get_feature_name(uint64_t flag);
+
 /**  Crypto device information */
 struct rte_cryptodev_info {
 	const char *driver_name;		/**< Driver name. */
 	enum rte_cryptodev_type dev_type;	/**< Device type */
 	struct rte_pci_device *pci_dev;		/**< PCI information. */
 
+	uint64_t feature_flags;			/**< Feature flags */
+
+	const struct rte_cryptodev_capabilities *capabilities;
+	/**< Array of devices supported capabilities */
+
 	unsigned max_nb_queue_pairs;
 	/**< Maximum number of queues pairs supported by device. */
 
@@ -540,6 +673,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp,
 /**< Enqueue packets for processing on queue pair of a device. */
 
 
+
+
 struct rte_cryptodev_callback;
 
 /** Structure to keep track of registered callbacks */
@@ -558,6 +693,8 @@ struct rte_cryptodev {
 	/**< Pointer to device data */
 	struct rte_cryptodev_ops *dev_ops;
 	/**< Functions exported by PMD */
+	uint64_t feature_flags;
+	/**< Supported features */
 	struct rte_pci_device *pci_dev;
 	/**< PCI info. supplied by probing */
 
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 6de6c7d..41004e1 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -10,6 +10,7 @@ DPDK_16.04 {
 	rte_cryptodev_configure;
 	rte_cryptodev_create_vdev;
 	rte_cryptodev_get_dev_id;
+	rte_cryptodev_get_feature_name;
 	rte_cryptodev_info_get;
 	rte_cryptodev_pmd_allocate;
 	rte_cryptodev_pmd_callback_process;
-- 
2.5.0

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

* Re: [dpdk-dev] [PATCH v3] cryptodev: add capabilities discovery mechanism
  2016-03-10 19:54   ` [dpdk-dev] [PATCH v3] " Pablo de Lara
@ 2016-03-10 21:27     ` Trahe, Fiona
  2016-03-11  1:20     ` Thomas Monjalon
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Trahe, Fiona @ 2016-03-10 21:27 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev



> -----Original Message-----
> From: De Lara Guarch, Pablo
> Sent: Thursday, March 10, 2016 7:55 PM
> To: dev@dpdk.org
> Cc: Doherty, Declan; Trahe, Fiona; De Lara Guarch, Pablo
> Subject: [PATCH v3] cryptodev: add capabilities discovery mechanism
> 
> From: Declan Doherty <declan.doherty@intel.com>
> 
> This patch add a mechanism for discovery of crypto device features and
> supported crypto operations and algorithms. It also provides a method for a
> crypto PMD to publish any data range limitations it may have for the operations
> and algorithms it supports.
> 
> The parameter feature_flags added to rte_cryptodev struct is used to capture
> features such as operations supported (symmetric crypto, operation chaining
> etc) as well parameter such as whether the device is hardware accelerated or
> uses SIMD instructions.
> 
> The capabilities parameter allows a PMD to define an array of supported
> operations with any limitation which that implementation may have.
> 
> Finally the rte_cryptodev_info struct has been extended to allow retrieval of
> these parameter using the existing rte_cryptodev_info_get() API.
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> ---
> 
> This patch depends on "null_crypto_pmd: PMD to support null crypto
> operations" patch
> (http://dpdk.org/dev/patchwork/patch/11428/)
> and "snow3g: Bit-wise handling for Wireless Algorithm" patch
> (http://dpdk.org/dev/patchwork/patch/11429/)
> 
> Changes in v3:
> 
> - Renamed macro to specify symmetric algo chaining
> 
> Changes in v2:
> 
> - Fixed incorrect values for sizes
> - Renamed some fields in capabilities structure
> - Added capabilities for new PMDs
> 
Acked-by: Fiona Trahe <fiona.trahe@intel.com>

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

* Re: [dpdk-dev] [PATCH v3] cryptodev: add capabilities discovery mechanism
  2016-03-10 19:54   ` [dpdk-dev] [PATCH v3] " Pablo de Lara
  2016-03-10 21:27     ` Trahe, Fiona
@ 2016-03-11  1:20     ` Thomas Monjalon
  2016-03-11  1:31       ` De Lara Guarch, Pablo
  2016-03-11  1:36     ` [dpdk-dev] [PATCH v4] " Pablo de Lara
  2016-03-14  8:25     ` [dpdk-dev] [PATCH v3] " Cao, Min
  3 siblings, 1 reply; 13+ messages in thread
From: Thomas Monjalon @ 2016-03-11  1:20 UTC (permalink / raw)
  To: Pablo de Lara; +Cc: dev

There is a clang error here:

> +static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {

drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c:41:48: fatal error:
	unused variable 'aesni_gcm_pmd_capabilities'

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

* Re: [dpdk-dev] [PATCH v3] cryptodev: add capabilities discovery mechanism
  2016-03-11  1:20     ` Thomas Monjalon
@ 2016-03-11  1:31       ` De Lara Guarch, Pablo
  0 siblings, 0 replies; 13+ messages in thread
From: De Lara Guarch, Pablo @ 2016-03-11  1:31 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev



> -----Original Message-----
> From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com]
> Sent: Friday, March 11, 2016 1:20 AM
> To: De Lara Guarch, Pablo
> Cc: dev@dpdk.org
> Subject: Re: [dpdk-dev] [PATCH v3] cryptodev: add capabilities discovery
> mechanism
> 
> There is a clang error here:
> 
> > +static const struct rte_cryptodev_capabilities
> aesni_gcm_pmd_capabilities[] = {
> 
> drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c:41:48: fatal error:
> 	unused variable 'aesni_gcm_pmd_capabilities'

Nice catch. Submitting a v4 shortly...

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

* [dpdk-dev] [PATCH v4] cryptodev: add capabilities discovery mechanism
  2016-03-10 19:54   ` [dpdk-dev] [PATCH v3] " Pablo de Lara
  2016-03-10 21:27     ` Trahe, Fiona
  2016-03-11  1:20     ` Thomas Monjalon
@ 2016-03-11  1:36     ` Pablo de Lara
  2016-03-11  9:35       ` Thomas Monjalon
  2016-03-14  8:13       ` Cao, Min
  2016-03-14  8:25     ` [dpdk-dev] [PATCH v3] " Cao, Min
  3 siblings, 2 replies; 13+ messages in thread
From: Pablo de Lara @ 2016-03-11  1:36 UTC (permalink / raw)
  To: dev

From: Declan Doherty <declan.doherty@intel.com>

This patch add a mechanism for discovery of crypto device features and supported
crypto operations and algorithms. It also provides a method for a crypto PMD to
publish any data range limitations it may have for the operations and algorithms
it supports.

The parameter feature_flags added to rte_cryptodev struct is used to capture
features such as operations supported (symmetric crypto, operation chaining etc)
as well parameter such as whether the device is hardware accelerated or uses
SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported operations
with any limitation which that implementation may have.

Finally the rte_cryptodev_info struct has been extended to allow retrieval of
these parameter using the existing rte_cryptodev_info_get() API.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Acked-by: Fiona Trahe <fiona.trahe@intel.com>
---

This patch depends on "null_crypto_pmd: PMD to support null crypto operations" patch
(http://dpdk.org/dev/patchwork/patch/11428/)
and "snow3g: Bit-wise handling for Wireless Algorithm" patch
(http://dpdk.org/dev/patchwork/patch/11429/)

Changes in v4:

 - Added missing capabilities information in device info
 
Changes in v3:

- Renamed macro to specify symmetric algo chaining

Changes in v2:

- Fixed incorrect values for sizes
- Renamed some fields in capabilities structure
- Added capabilities for new PMDs


 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c       |  18 +++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c   |  51 +++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c     |  18 +++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c | 175 +++++++++++++++++++++
 drivers/crypto/null/null_crypto_pmd.c          |   3 +
 drivers/crypto/null/null_crypto_pmd_ops.c      |  47 ++++++
 drivers/crypto/qat/qat_crypto.c                | 201 ++++++++++++++++++++++++-
 drivers/crypto/qat/rte_qat_cryptodev.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd_ops.c     |  51 +++++++
 lib/librte_cryptodev/rte_cryptodev.c           |  28 ++++
 lib/librte_cryptodev/rte_cryptodev.h           | 137 +++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_version.map |   1 +
 13 files changed, 735 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 83aa272..35577bc 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -445,6 +445,24 @@ aesni_gcm_create(const char *name,
 	dev->dequeue_burst = aesni_gcm_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_gcm_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_GCM_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_GCM_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_GCM_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
index f865e0d..387f8d1 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "aesni_gcm_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 aesni_gcm_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -107,6 +156,8 @@ aesni_gcm_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+                dev_info->feature_flags = dev->feature_flags;
+                dev_info->capabilities = aesni_gcm_pmd_capabilities;
 
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 9599cc4..4e3885c 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -640,6 +640,24 @@ cryptodev_aesni_mb_create(const char *name, unsigned socket_id)
 	dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_MB_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
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 b1dd103..5a439e6 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -38,6 +38,179 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 14,
+					.max = 14,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 24,
+					.max = 24,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -107,6 +280,8 @@ aesni_mb_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index a4bb152..82b990c 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -215,6 +215,9 @@ cryptodev_null_create(const char *name,
 	dev->dequeue_burst = null_crypto_pmd_dequeue_burst;
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_qpairs = init_params->max_nb_queue_pairs;
diff --git a/drivers/crypto/null/null_crypto_pmd_ops.c b/drivers/crypto/null/null_crypto_pmd_ops.c
index 6bf955e..39f8088 100644
--- a/drivers/crypto/null/null_crypto_pmd_ops.c
+++ b/drivers/crypto/null/null_crypto_pmd_ops.c
@@ -38,6 +38,51 @@
 
 #include "null_crypto_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilities[] = {
+	{	/* NULL (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* NULL (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 null_crypto_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -108,6 +153,8 @@ null_crypto_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_qpairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = null_crypto_pmd_capabilities;
 	}
 }
 
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypto.c
index f267da5..29c1fe5 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,204 @@
 
 #define BYTE_LENGTH    8
 
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] = {
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 20,
+					.max = 20,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC MAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
 
@@ -652,7 +850,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev *dev,
 		info->max_nb_queue_pairs =
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = qat_pmd_capabilities;
 		info->sym.max_nb_sessions = internals->max_nb_sessions;
 		info->dev_type = RTE_CRYPTODEV_QAT_SYM_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 5e51aca..a7912f5 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -95,6 +95,9 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 	cryptodev->enqueue_burst = qat_pmd_enqueue_op_burst;
 	cryptodev->dequeue_burst = qat_pmd_dequeue_op_burst;
 
+	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
 
 	internals = cryptodev->data->dev_private;
 	internals->max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS;
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 6f84e5c..97c7fb5 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -490,6 +490,9 @@ cryptodev_snow3g_create(const char *name,
 	dev->dequeue_burst = snow3g_pmd_dequeue_burst;
 	dev->enqueue_burst = snow3g_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs;
diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
index 5643323..74eee23 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "rte_snow3g_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities snow3g_pmd_capabilities[] = {
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 snow3g_pmd_config(__rte_unused struct rte_cryptodev *dev)
@@ -109,6 +158,8 @@ snow3g_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = snow3g_pmd_capabilities;
 	}
 }
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 4632ca3..2d72dd7 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -102,6 +102,34 @@ struct rte_cryptodev_callback {
 	uint32_t active;			/**< Callback is executing */
 };
 
+
+const char *
+rte_cryptodev_get_feature_name(uint64_t flag)
+{
+	switch (flag) {
+	case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
+		return "SYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
+		return "ASYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
+		return "SYM_OPERATION_CHAINING";
+	case RTE_CRYPTODEV_FF_CPU_SSE:
+		return "CPU_SSE";
+	case RTE_CRYPTODEV_FF_CPU_AVX:
+		return "CPU_AVX";
+	case RTE_CRYPTODEV_FF_CPU_AVX2:
+		return "CPU_AVX2";
+	case RTE_CRYPTODEV_FF_CPU_AESNI:
+		return "CPU_AESNI";
+	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
+		return "HW_ACCELERATED";
+
+	default:
+		return NULL;
+	}
+}
+
+
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)
 {
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index eb85c46..b599c95 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -98,12 +98,145 @@ extern const char **rte_cyptodev_names;
 #define CDEV_PMD_TRACE(fmt, args...)
 #endif
 
+/**
+ * Symmetric Crypto Capability
+ */
+struct rte_cryptodev_symmetric_capability {
+	enum rte_crypto_sym_xform_type xform_type;
+	/**< Transform type : Authentication / Cipher */
+	union {
+		struct {
+			enum rte_crypto_auth_algorithm algo;
+			/**< authentication algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< auth key size range */
+			struct {
+				uint16_t min;	/**< minimum digest size */
+				uint16_t max;	/**< maximum digest size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} digest_size;
+			/**< digest size range */
+			struct {
+				uint16_t min;	/**< minimum aad size */
+				uint16_t max;	/**< maximum aad size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} aad_size;
+			/**< Additional authentication data size range */
+		} auth;
+		/**< Symmetric Authentication transform capabilities */
+		struct {
+			enum rte_crypto_cipher_algorithm algo;
+			/**< cipher algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< cipher key size range */
+			struct {
+				uint16_t min;	/**< minimum iv size */
+				uint16_t max;	/**< maximum iv size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} iv_size;
+			/**< Initialisation vector data size range */
+		} cipher;
+		/**< Symmetric Cipher transform capabilities */
+	};
+};
+
+/** Structure used to capture a capability of a crypto device */
+struct rte_cryptodev_capabilities {
+	enum rte_crypto_op_type op;
+	/**< Operation type */
+
+	union {
+		struct rte_cryptodev_symmetric_capability sym;
+		/**< Symmetric operation capability parameters */
+	};
+};
+
+/** Macro used at end of crypto PMD list */
+#define RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
+	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
+
+
+/**
+ * Crypto device supported feature flags
+ *
+ * Note:
+ * New features flags should be added to the end of the list
+ *
+ * Keep these flags synchronised with rte_cryptodev_get_feature_name()
+ */
+#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
+/**< Symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
+/**< Asymmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING	(1ULL << 2)
+/**< Chaining symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
+/**< Utilises CPU SIMD SSE instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
+/**< Utilises CPU SIMD AVX instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
+/**< Utilises CPU SIMD AVX2 instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
+/**< Utilises CPU AES-NI instructions */
+#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
+/**< Operations are off-loaded to an external hardware accelerator */
+
+
+/**
+ * Get the name of a crypto device feature flag
+ *
+ * @param	flag	The mask describing the flag.
+ *
+ * @return
+ *   The name of this flag, or NULL if it's not a valid feature flag.
+ */
+
+extern const char *
+rte_cryptodev_get_feature_name(uint64_t flag);
+
 /**  Crypto device information */
 struct rte_cryptodev_info {
 	const char *driver_name;		/**< Driver name. */
 	enum rte_cryptodev_type dev_type;	/**< Device type */
 	struct rte_pci_device *pci_dev;		/**< PCI information. */
 
+	uint64_t feature_flags;			/**< Feature flags */
+
+	const struct rte_cryptodev_capabilities *capabilities;
+	/**< Array of devices supported capabilities */
+
 	unsigned max_nb_queue_pairs;
 	/**< Maximum number of queues pairs supported by device. */
 
@@ -540,6 +673,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp,
 /**< Enqueue packets for processing on queue pair of a device. */
 
 
+
+
 struct rte_cryptodev_callback;
 
 /** Structure to keep track of registered callbacks */
@@ -558,6 +693,8 @@ struct rte_cryptodev {
 	/**< Pointer to device data */
 	struct rte_cryptodev_ops *dev_ops;
 	/**< Functions exported by PMD */
+	uint64_t feature_flags;
+	/**< Supported features */
 	struct rte_pci_device *pci_dev;
 	/**< PCI info. supplied by probing */
 
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 6de6c7d..41004e1 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -10,6 +10,7 @@ DPDK_16.04 {
 	rte_cryptodev_configure;
 	rte_cryptodev_create_vdev;
 	rte_cryptodev_get_dev_id;
+	rte_cryptodev_get_feature_name;
 	rte_cryptodev_info_get;
 	rte_cryptodev_pmd_allocate;
 	rte_cryptodev_pmd_callback_process;
-- 
2.5.0

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

* Re: [dpdk-dev] [PATCH v4] cryptodev: add capabilities discovery mechanism
  2016-03-11  1:36     ` [dpdk-dev] [PATCH v4] " Pablo de Lara
@ 2016-03-11  9:35       ` Thomas Monjalon
  2016-03-14  8:13       ` Cao, Min
  1 sibling, 0 replies; 13+ messages in thread
From: Thomas Monjalon @ 2016-03-11  9:35 UTC (permalink / raw)
  To: Pablo de Lara; +Cc: dev

2016-03-11 01:36, Pablo de Lara:
> From: Declan Doherty <declan.doherty@intel.com>
> 
> This patch add a mechanism for discovery of crypto device features and supported
> crypto operations and algorithms. It also provides a method for a crypto PMD to
> publish any data range limitations it may have for the operations and algorithms
> it supports.
> 
> The parameter feature_flags added to rte_cryptodev struct is used to capture
> features such as operations supported (symmetric crypto, operation chaining etc)
> as well parameter such as whether the device is hardware accelerated or uses
> SIMD instructions.
> 
> The capabilities parameter allows a PMD to define an array of supported operations
> with any limitation which that implementation may have.
> 
> Finally the rte_cryptodev_info struct has been extended to allow retrieval of
> these parameter using the existing rte_cryptodev_info_get() API.
> 
> Signed-off-by: Declan Doherty <declan.doherty@intel.com>
> Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
> Acked-by: Fiona Trahe <fiona.trahe@intel.com>

Applied, thanks

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

* Re: [dpdk-dev] [PATCH v4] cryptodev: add capabilities discovery mechanism
  2016-03-11  1:36     ` [dpdk-dev] [PATCH v4] " Pablo de Lara
  2016-03-11  9:35       ` Thomas Monjalon
@ 2016-03-14  8:13       ` Cao, Min
  1 sibling, 0 replies; 13+ messages in thread
From: Cao, Min @ 2016-03-14  8:13 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev

Tested-by: Min Cao <min.cao@intel.com>

- Tested Commit: 94b0ad8e0aa556230183f4c4d06b68bfd145dce3
- OS: Fedora20 3.11.10-301.fc20.x86_64
- GCC: gcc (GCC) 4.8.3
- CPU: Intel(R) Xeon(R) CPU E5-2658 v3 @ 2.20GHz
- NIC: Niantic
- Default x86_64-native-linuxapp-gcc configuration
- Prerequisites:
- Total 56 cases, 56 passed, 0 failed

- test case 1: QAT Unit test 
    Total 45 cases, 45 passed, 0 failed

- test case 2: AES_NI Unit test 
    Total 10 cases, 10 passed, 0 failed

- test case 3: l2fwd-crypto 
    Total 1 cases, 1 passed, 0 failed
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Pablo de Lara
Sent: Friday, March 11, 2016 9:37 AM
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v4] cryptodev: add capabilities discovery mechanism

From: Declan Doherty <declan.doherty@intel.com>

This patch add a mechanism for discovery of crypto device features and supported crypto operations and algorithms. It also provides a method for a crypto PMD to publish any data range limitations it may have for the operations and algorithms it supports.

The parameter feature_flags added to rte_cryptodev struct is used to capture features such as operations supported (symmetric crypto, operation chaining etc) as well parameter such as whether the device is hardware accelerated or uses SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported operations with any limitation which that implementation may have.

Finally the rte_cryptodev_info struct has been extended to allow retrieval of these parameter using the existing rte_cryptodev_info_get() API.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
Acked-by: Fiona Trahe <fiona.trahe@intel.com>
---

This patch depends on "null_crypto_pmd: PMD to support null crypto operations" patch
(http://dpdk.org/dev/patchwork/patch/11428/)
and "snow3g: Bit-wise handling for Wireless Algorithm" patch
(http://dpdk.org/dev/patchwork/patch/11429/)

Changes in v4:

 - Added missing capabilities information in device info
 
Changes in v3:

- Renamed macro to specify symmetric algo chaining

Changes in v2:

- Fixed incorrect values for sizes
- Renamed some fields in capabilities structure
- Added capabilities for new PMDs


 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c       |  18 +++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c   |  51 +++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c     |  18 +++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c | 175 +++++++++++++++++++++
 drivers/crypto/null/null_crypto_pmd.c          |   3 +
 drivers/crypto/null/null_crypto_pmd_ops.c      |  47 ++++++
 drivers/crypto/qat/qat_crypto.c                | 201 ++++++++++++++++++++++++-
 drivers/crypto/qat/rte_qat_cryptodev.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd_ops.c     |  51 +++++++
 lib/librte_cryptodev/rte_cryptodev.c           |  28 ++++
 lib/librte_cryptodev/rte_cryptodev.h           | 137 +++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_version.map |   1 +
 13 files changed, 735 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 83aa272..35577bc 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -445,6 +445,24 @@ aesni_gcm_create(const char *name,
 	dev->dequeue_burst = aesni_gcm_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_gcm_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_GCM_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_GCM_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_GCM_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
index f865e0d..387f8d1 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "aesni_gcm_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 aesni_gcm_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -107,6 +156,8 @@ aesni_gcm_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+                dev_info->feature_flags = dev->feature_flags;
+                dev_info->capabilities = aesni_gcm_pmd_capabilities;
 
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions; diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 9599cc4..4e3885c 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -640,6 +640,24 @@ cryptodev_aesni_mb_create(const char *name, unsigned socket_id)
 	dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_MB_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
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 b1dd103..5a439e6 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -38,6 +38,179 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 14,
+					.max = 14,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 24,
+					.max = 24,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -107,6 +280,8 @@ aesni_mb_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index a4bb152..82b990c 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -215,6 +215,9 @@ cryptodev_null_create(const char *name,
 	dev->dequeue_burst = null_crypto_pmd_dequeue_burst;
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_qpairs = init_params->max_nb_queue_pairs; diff --git a/drivers/crypto/null/null_crypto_pmd_ops.c b/drivers/crypto/null/null_crypto_pmd_ops.c
index 6bf955e..39f8088 100644
--- a/drivers/crypto/null/null_crypto_pmd_ops.c
+++ b/drivers/crypto/null/null_crypto_pmd_ops.c
@@ -38,6 +38,51 @@
 
 #include "null_crypto_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilities[] = {
+	{	/* NULL (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* NULL (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 null_crypto_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -108,6 +153,8 @@ null_crypto_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_qpairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = null_crypto_pmd_capabilities;
 	}
 }
 
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypto.c index f267da5..29c1fe5 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,204 @@
 
 #define BYTE_LENGTH    8
 
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] = {
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 20,
+					.max = 20,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC MAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
 
@@ -652,7 +850,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev *dev,
 		info->max_nb_queue_pairs =
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = qat_pmd_capabilities;
 		info->sym.max_nb_sessions = internals->max_nb_sessions;
 		info->dev_type = RTE_CRYPTODEV_QAT_SYM_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 5e51aca..a7912f5 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -95,6 +95,9 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 	cryptodev->enqueue_burst = qat_pmd_enqueue_op_burst;
 	cryptodev->dequeue_burst = qat_pmd_dequeue_op_burst;
 
+	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
 
 	internals = cryptodev->data->dev_private;
 	internals->max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS; diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 6f84e5c..97c7fb5 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -490,6 +490,9 @@ cryptodev_snow3g_create(const char *name,
 	dev->dequeue_burst = snow3g_pmd_dequeue_burst;
 	dev->enqueue_burst = snow3g_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs; diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
index 5643323..74eee23 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "rte_snow3g_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities snow3g_pmd_capabilities[] = {
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 snow3g_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -109,6 +158,8 @@ snow3g_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = snow3g_pmd_capabilities;
 	}
 }
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 4632ca3..2d72dd7 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -102,6 +102,34 @@ struct rte_cryptodev_callback {
 	uint32_t active;			/**< Callback is executing */
 };
 
+
+const char *
+rte_cryptodev_get_feature_name(uint64_t flag) {
+	switch (flag) {
+	case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
+		return "SYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
+		return "ASYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
+		return "SYM_OPERATION_CHAINING";
+	case RTE_CRYPTODEV_FF_CPU_SSE:
+		return "CPU_SSE";
+	case RTE_CRYPTODEV_FF_CPU_AVX:
+		return "CPU_AVX";
+	case RTE_CRYPTODEV_FF_CPU_AVX2:
+		return "CPU_AVX2";
+	case RTE_CRYPTODEV_FF_CPU_AESNI:
+		return "CPU_AESNI";
+	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
+		return "HW_ACCELERATED";
+
+	default:
+		return NULL;
+	}
+}
+
+
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)  { diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index eb85c46..b599c95 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -98,12 +98,145 @@ extern const char **rte_cyptodev_names;  #define CDEV_PMD_TRACE(fmt, args...)  #endif
 
+/**
+ * Symmetric Crypto Capability
+ */
+struct rte_cryptodev_symmetric_capability {
+	enum rte_crypto_sym_xform_type xform_type;
+	/**< Transform type : Authentication / Cipher */
+	union {
+		struct {
+			enum rte_crypto_auth_algorithm algo;
+			/**< authentication algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< auth key size range */
+			struct {
+				uint16_t min;	/**< minimum digest size */
+				uint16_t max;	/**< maximum digest size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} digest_size;
+			/**< digest size range */
+			struct {
+				uint16_t min;	/**< minimum aad size */
+				uint16_t max;	/**< maximum aad size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} aad_size;
+			/**< Additional authentication data size range */
+		} auth;
+		/**< Symmetric Authentication transform capabilities */
+		struct {
+			enum rte_crypto_cipher_algorithm algo;
+			/**< cipher algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< cipher key size range */
+			struct {
+				uint16_t min;	/**< minimum iv size */
+				uint16_t max;	/**< maximum iv size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} iv_size;
+			/**< Initialisation vector data size range */
+		} cipher;
+		/**< Symmetric Cipher transform capabilities */
+	};
+};
+
+/** Structure used to capture a capability of a crypto device */ struct 
+rte_cryptodev_capabilities {
+	enum rte_crypto_op_type op;
+	/**< Operation type */
+
+	union {
+		struct rte_cryptodev_symmetric_capability sym;
+		/**< Symmetric operation capability parameters */
+	};
+};
+
+/** Macro used at end of crypto PMD list */ #define 
+RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
+	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
+
+
+/**
+ * Crypto device supported feature flags
+ *
+ * Note:
+ * New features flags should be added to the end of the list
+ *
+ * Keep these flags synchronised with rte_cryptodev_get_feature_name()  
+*/
+#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
+/**< Symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
+/**< Asymmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING	(1ULL << 2)
+/**< Chaining symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
+/**< Utilises CPU SIMD SSE instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
+/**< Utilises CPU SIMD AVX instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
+/**< Utilises CPU SIMD AVX2 instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
+/**< Utilises CPU AES-NI instructions */
+#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
+/**< Operations are off-loaded to an external hardware accelerator */
+
+
+/**
+ * Get the name of a crypto device feature flag
+ *
+ * @param	flag	The mask describing the flag.
+ *
+ * @return
+ *   The name of this flag, or NULL if it's not a valid feature flag.
+ */
+
+extern const char *
+rte_cryptodev_get_feature_name(uint64_t flag);
+
 /**  Crypto device information */
 struct rte_cryptodev_info {
 	const char *driver_name;		/**< Driver name. */
 	enum rte_cryptodev_type dev_type;	/**< Device type */
 	struct rte_pci_device *pci_dev;		/**< PCI information. */
 
+	uint64_t feature_flags;			/**< Feature flags */
+
+	const struct rte_cryptodev_capabilities *capabilities;
+	/**< Array of devices supported capabilities */
+
 	unsigned max_nb_queue_pairs;
 	/**< Maximum number of queues pairs supported by device. */
 
@@ -540,6 +673,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp,  /**< Enqueue packets for processing on queue pair of a device. */
 
 
+
+
 struct rte_cryptodev_callback;
 
 /** Structure to keep track of registered callbacks */ @@ -558,6 +693,8 @@ struct rte_cryptodev {
 	/**< Pointer to device data */
 	struct rte_cryptodev_ops *dev_ops;
 	/**< Functions exported by PMD */
+	uint64_t feature_flags;
+	/**< Supported features */
 	struct rte_pci_device *pci_dev;
 	/**< PCI info. supplied by probing */
 
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 6de6c7d..41004e1 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -10,6 +10,7 @@ DPDK_16.04 {
 	rte_cryptodev_configure;
 	rte_cryptodev_create_vdev;
 	rte_cryptodev_get_dev_id;
+	rte_cryptodev_get_feature_name;
 	rte_cryptodev_info_get;
 	rte_cryptodev_pmd_allocate;
 	rte_cryptodev_pmd_callback_process;
--
2.5.0

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

* Re: [dpdk-dev] [PATCH v3] cryptodev: add capabilities discovery mechanism
  2016-03-10 19:54   ` [dpdk-dev] [PATCH v3] " Pablo de Lara
                       ` (2 preceding siblings ...)
  2016-03-11  1:36     ` [dpdk-dev] [PATCH v4] " Pablo de Lara
@ 2016-03-14  8:25     ` Cao, Min
  3 siblings, 0 replies; 13+ messages in thread
From: Cao, Min @ 2016-03-14  8:25 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev

Tested-by: Min Cao <min.cao@intel.com>

- Tested Commit: 94b0ad8e0aa556230183f4c4d06b68bfd145dce3
- OS: Fedora20 3.11.10-301.fc20.x86_64
- GCC: gcc (GCC) 4.8.3
- CPU: Intel(R) Xeon(R) CPU E5-2658 v3 @ 2.20GHz
- NIC: Niantic
- Default x86_64-native-linuxapp-gcc configuration
- Prerequisites:
- Total 56 cases, 56 passed, 0 failed

- test case 1: QAT Unit test 
    Total 45 cases, 45 passed, 0 failed

- test case 2: AES_NI Unit test 
    Total 10 cases, 10 passed, 0 failed

- test case 3: l2fwd-crypto 
    Total 1 cases, 1 passed, 0 failed

-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Pablo de Lara
Sent: Friday, March 11, 2016 3:55 AM
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v3] cryptodev: add capabilities discovery mechanism

From: Declan Doherty <declan.doherty@intel.com>

This patch add a mechanism for discovery of crypto device features and supported crypto operations and algorithms. It also provides a method for a crypto PMD to publish any data range limitations it may have for the operations and algorithms it supports.

The parameter feature_flags added to rte_cryptodev struct is used to capture features such as operations supported (symmetric crypto, operation chaining etc) as well parameter such as whether the device is hardware accelerated or uses SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported operations with any limitation which that implementation may have.

Finally the rte_cryptodev_info struct has been extended to allow retrieval of these parameter using the existing rte_cryptodev_info_get() API.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>
---

This patch depends on "null_crypto_pmd: PMD to support null crypto operations" patch
(http://dpdk.org/dev/patchwork/patch/11428/)
and "snow3g: Bit-wise handling for Wireless Algorithm" patch
(http://dpdk.org/dev/patchwork/patch/11429/)

Changes in v3:

- Renamed macro to specify symmetric algo chaining

Changes in v2:

- Fixed incorrect values for sizes
- Renamed some fields in capabilities structure
- Added capabilities for new PMDs


 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c       |  18 +++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c   |  49 ++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c     |  18 +++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c | 175 +++++++++++++++++++++
 drivers/crypto/null/null_crypto_pmd.c          |   3 +
 drivers/crypto/null/null_crypto_pmd_ops.c      |  47 ++++++
 drivers/crypto/qat/qat_crypto.c                | 201 ++++++++++++++++++++++++-
 drivers/crypto/qat/rte_qat_cryptodev.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd_ops.c     |  51 +++++++
 lib/librte_cryptodev/rte_cryptodev.c           |  28 ++++
 lib/librte_cryptodev/rte_cryptodev.h           | 137 +++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_version.map |   1 +
 13 files changed, 733 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 83aa272..35577bc 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -445,6 +445,24 @@ aesni_gcm_create(const char *name,
 	dev->dequeue_burst = aesni_gcm_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_gcm_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_GCM_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_GCM_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_GCM_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
index f865e0d..af7907b 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "aesni_gcm_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 aesni_gcm_pmd_config(__rte_unused struct rte_cryptodev *dev) diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 9599cc4..4e3885c 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -640,6 +640,24 @@ cryptodev_aesni_mb_create(const char *name, unsigned socket_id)
 	dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_MB_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
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 b1dd103..5a439e6 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -38,6 +38,179 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 14,
+					.max = 14,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 24,
+					.max = 24,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -107,6 +280,8 @@ aesni_mb_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index a4bb152..82b990c 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -215,6 +215,9 @@ cryptodev_null_create(const char *name,
 	dev->dequeue_burst = null_crypto_pmd_dequeue_burst;
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_qpairs = init_params->max_nb_queue_pairs; diff --git a/drivers/crypto/null/null_crypto_pmd_ops.c b/drivers/crypto/null/null_crypto_pmd_ops.c
index 6bf955e..39f8088 100644
--- a/drivers/crypto/null/null_crypto_pmd_ops.c
+++ b/drivers/crypto/null/null_crypto_pmd_ops.c
@@ -38,6 +38,51 @@
 
 #include "null_crypto_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilities[] = {
+	{	/* NULL (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* NULL (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 null_crypto_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -108,6 +153,8 @@ null_crypto_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_qpairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = null_crypto_pmd_capabilities;
 	}
 }
 
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypto.c index f267da5..29c1fe5 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,204 @@
 
 #define BYTE_LENGTH    8
 
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] = {
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 20,
+					.max = 20,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC MAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
 
@@ -652,7 +850,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev *dev,
 		info->max_nb_queue_pairs =
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = qat_pmd_capabilities;
 		info->sym.max_nb_sessions = internals->max_nb_sessions;
 		info->dev_type = RTE_CRYPTODEV_QAT_SYM_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 5e51aca..a7912f5 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -95,6 +95,9 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 	cryptodev->enqueue_burst = qat_pmd_enqueue_op_burst;
 	cryptodev->dequeue_burst = qat_pmd_dequeue_op_burst;
 
+	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
 
 	internals = cryptodev->data->dev_private;
 	internals->max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS; diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 6f84e5c..97c7fb5 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -490,6 +490,9 @@ cryptodev_snow3g_create(const char *name,
 	dev->dequeue_burst = snow3g_pmd_dequeue_burst;
 	dev->enqueue_burst = snow3g_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs; diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
index 5643323..74eee23 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "rte_snow3g_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities snow3g_pmd_capabilities[] = {
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 snow3g_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -109,6 +158,8 @@ snow3g_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = snow3g_pmd_capabilities;
 	}
 }
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 4632ca3..2d72dd7 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -102,6 +102,34 @@ struct rte_cryptodev_callback {
 	uint32_t active;			/**< Callback is executing */
 };
 
+
+const char *
+rte_cryptodev_get_feature_name(uint64_t flag) {
+	switch (flag) {
+	case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
+		return "SYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
+		return "ASYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING:
+		return "SYM_OPERATION_CHAINING";
+	case RTE_CRYPTODEV_FF_CPU_SSE:
+		return "CPU_SSE";
+	case RTE_CRYPTODEV_FF_CPU_AVX:
+		return "CPU_AVX";
+	case RTE_CRYPTODEV_FF_CPU_AVX2:
+		return "CPU_AVX2";
+	case RTE_CRYPTODEV_FF_CPU_AESNI:
+		return "CPU_AESNI";
+	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
+		return "HW_ACCELERATED";
+
+	default:
+		return NULL;
+	}
+}
+
+
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)  { diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index eb85c46..b599c95 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -98,12 +98,145 @@ extern const char **rte_cyptodev_names;  #define CDEV_PMD_TRACE(fmt, args...)  #endif
 
+/**
+ * Symmetric Crypto Capability
+ */
+struct rte_cryptodev_symmetric_capability {
+	enum rte_crypto_sym_xform_type xform_type;
+	/**< Transform type : Authentication / Cipher */
+	union {
+		struct {
+			enum rte_crypto_auth_algorithm algo;
+			/**< authentication algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< auth key size range */
+			struct {
+				uint16_t min;	/**< minimum digest size */
+				uint16_t max;	/**< maximum digest size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} digest_size;
+			/**< digest size range */
+			struct {
+				uint16_t min;	/**< minimum aad size */
+				uint16_t max;	/**< maximum aad size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} aad_size;
+			/**< Additional authentication data size range */
+		} auth;
+		/**< Symmetric Authentication transform capabilities */
+		struct {
+			enum rte_crypto_cipher_algorithm algo;
+			/**< cipher algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< cipher key size range */
+			struct {
+				uint16_t min;	/**< minimum iv size */
+				uint16_t max;	/**< maximum iv size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} iv_size;
+			/**< Initialisation vector data size range */
+		} cipher;
+		/**< Symmetric Cipher transform capabilities */
+	};
+};
+
+/** Structure used to capture a capability of a crypto device */ struct 
+rte_cryptodev_capabilities {
+	enum rte_crypto_op_type op;
+	/**< Operation type */
+
+	union {
+		struct rte_cryptodev_symmetric_capability sym;
+		/**< Symmetric operation capability parameters */
+	};
+};
+
+/** Macro used at end of crypto PMD list */ #define 
+RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
+	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
+
+
+/**
+ * Crypto device supported feature flags
+ *
+ * Note:
+ * New features flags should be added to the end of the list
+ *
+ * Keep these flags synchronised with rte_cryptodev_get_feature_name()  
+*/
+#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
+/**< Symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
+/**< Asymmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING	(1ULL << 2)
+/**< Chaining symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
+/**< Utilises CPU SIMD SSE instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
+/**< Utilises CPU SIMD AVX instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
+/**< Utilises CPU SIMD AVX2 instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
+/**< Utilises CPU AES-NI instructions */
+#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
+/**< Operations are off-loaded to an external hardware accelerator */
+
+
+/**
+ * Get the name of a crypto device feature flag
+ *
+ * @param	flag	The mask describing the flag.
+ *
+ * @return
+ *   The name of this flag, or NULL if it's not a valid feature flag.
+ */
+
+extern const char *
+rte_cryptodev_get_feature_name(uint64_t flag);
+
 /**  Crypto device information */
 struct rte_cryptodev_info {
 	const char *driver_name;		/**< Driver name. */
 	enum rte_cryptodev_type dev_type;	/**< Device type */
 	struct rte_pci_device *pci_dev;		/**< PCI information. */
 
+	uint64_t feature_flags;			/**< Feature flags */
+
+	const struct rte_cryptodev_capabilities *capabilities;
+	/**< Array of devices supported capabilities */
+
 	unsigned max_nb_queue_pairs;
 	/**< Maximum number of queues pairs supported by device. */
 
@@ -540,6 +673,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp,  /**< Enqueue packets for processing on queue pair of a device. */
 
 
+
+
 struct rte_cryptodev_callback;
 
 /** Structure to keep track of registered callbacks */ @@ -558,6 +693,8 @@ struct rte_cryptodev {
 	/**< Pointer to device data */
 	struct rte_cryptodev_ops *dev_ops;
 	/**< Functions exported by PMD */
+	uint64_t feature_flags;
+	/**< Supported features */
 	struct rte_pci_device *pci_dev;
 	/**< PCI info. supplied by probing */
 
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 6de6c7d..41004e1 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -10,6 +10,7 @@ DPDK_16.04 {
 	rte_cryptodev_configure;
 	rte_cryptodev_create_vdev;
 	rte_cryptodev_get_dev_id;
+	rte_cryptodev_get_feature_name;
 	rte_cryptodev_info_get;
 	rte_cryptodev_pmd_allocate;
 	rte_cryptodev_pmd_callback_process;
--
2.5.0

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

* Re: [dpdk-dev] [PATCH v2] cryptodev: add capabilities discovery mechanism
  2016-03-10 17:07 ` [dpdk-dev] [PATCH v2] " Pablo de Lara
  2016-03-10 19:54   ` [dpdk-dev] [PATCH v3] " Pablo de Lara
@ 2016-03-14  8:26   ` Cao, Min
  1 sibling, 0 replies; 13+ messages in thread
From: Cao, Min @ 2016-03-14  8:26 UTC (permalink / raw)
  To: De Lara Guarch, Pablo, dev

Tested-by: Min Cao <min.cao@intel.com>

- Tested Commit: 94b0ad8e0aa556230183f4c4d06b68bfd145dce3
- OS: Fedora20 3.11.10-301.fc20.x86_64
- GCC: gcc (GCC) 4.8.3
- CPU: Intel(R) Xeon(R) CPU E5-2658 v3 @ 2.20GHz
- NIC: Niantic
- Default x86_64-native-linuxapp-gcc configuration
- Prerequisites:
- Total 56 cases, 56 passed, 0 failed

- test case 1: QAT Unit test 
    Total 45 cases, 45 passed, 0 failed

- test case 2: AES_NI Unit test 
    Total 10 cases, 10 passed, 0 failed

- test case 3: l2fwd-crypto 
    Total 1 cases, 1 passed, 0 failed

-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Pablo de Lara
Sent: Friday, March 11, 2016 1:07 AM
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v2] cryptodev: add capabilities discovery mechanism

From: Declan Doherty <declan.doherty@intel.com>

This patch add a mechanism for discovery of crypto device features and supported crypto operations and algorithms. It also provides a method for a crypto PMD to publish any data range limitations it may have for the operations and algorithms it supports.

The parameter feature_flags added to rte_cryptodev struct is used to capture features such as operations supported (symmetric crypto, operation chaining etc) as well parameter such as whether the device is hardware accelerated or uses SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported operations with any limitation which that implementation may have.

Finally the rte_cryptodev_info struct has been extended to allow retrieval of these parameter using the existing rte_cryptodev_info_get() API.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
Signed-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>

---

This patch depends on "null_crypto_pmd: PMD to support null crypto operations" patch
(http://dpdk.org/dev/patchwork/patch/11428/)
and "snow3g: Bit-wise handling for Wireless Algorithm" patch
(http://dpdk.org/dev/patchwork/patch/11429/)

Changes in v2:

- Fixed incorrect values for sizes
- Renamed some fields in capabilities structure
- Added capabilities for new PMDs

 drivers/crypto/aesni_gcm/aesni_gcm_pmd.c       |  18 +++
 drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c   |  49 ++++++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c     |  18 +++
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c | 175 +++++++++++++++++++++
 drivers/crypto/null/null_crypto_pmd.c          |   3 +
 drivers/crypto/null/null_crypto_pmd_ops.c      |  47 ++++++
 drivers/crypto/qat/qat_crypto.c                | 201 ++++++++++++++++++++++++-
 drivers/crypto/qat/rte_qat_cryptodev.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd.c         |   3 +
 drivers/crypto/snow3g/rte_snow3g_pmd_ops.c     |  51 +++++++
 lib/librte_cryptodev/rte_cryptodev.c           |  28 ++++
 lib/librte_cryptodev/rte_cryptodev.h           | 137 +++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev_version.map |   1 +
 13 files changed, 733 insertions(+), 1 deletion(-)

diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
index 83aa272..c94bb7d 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd.c
@@ -445,6 +445,24 @@ aesni_gcm_create(const char *name,
 	dev->dequeue_burst = aesni_gcm_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_gcm_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_GCM_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_GCM_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_GCM_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
diff --git a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
index f865e0d..af7907b 100644
--- a/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
+++ b/drivers/crypto/aesni_gcm/aesni_gcm_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "aesni_gcm_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[] = {
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 aesni_gcm_pmd_config(__rte_unused struct rte_cryptodev *dev) diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 9599cc4..bd273ec 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -640,6 +640,24 @@ cryptodev_aesni_mb_create(const char *name, unsigned socket_id)
 	dev->dequeue_burst = aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst = aesni_mb_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING |
+			RTE_CRYPTODEV_FF_CPU_AESNI;
+
+	switch (vector_mode) {
+	case RTE_AESNI_MB_SSE:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |= RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals = dev->data->dev_private;
 
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 b1dd103..5a439e6 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -38,6 +38,179 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = {
+	{	/* MD5 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_MD5_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA224_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 14,
+					.max = 14,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA384_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 24,
+					.max = 24,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 12,
+					.max = 12,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
+
 /** Configure device */
 static int
 aesni_mb_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -107,6 +280,8 @@ aesni_mb_pmd_info_get(struct rte_cryptodev *dev,
 
 	if (dev_info != NULL) {
 		dev_info->dev_type = dev->dev_type;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/null_crypto_pmd.c
index a4bb152..5b8cb13 100644
--- a/drivers/crypto/null/null_crypto_pmd.c
+++ b/drivers/crypto/null/null_crypto_pmd.c
@@ -215,6 +215,9 @@ cryptodev_null_create(const char *name,
 	dev->dequeue_burst = null_crypto_pmd_dequeue_burst;
 	dev->enqueue_burst = null_crypto_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_qpairs = init_params->max_nb_queue_pairs; diff --git a/drivers/crypto/null/null_crypto_pmd_ops.c b/drivers/crypto/null/null_crypto_pmd_ops.c
index 6bf955e..39f8088 100644
--- a/drivers/crypto/null/null_crypto_pmd_ops.c
+++ b/drivers/crypto/null/null_crypto_pmd_ops.c
@@ -38,6 +38,51 @@
 
 #include "null_crypto_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilities[] = {
+	{	/* NULL (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* NULL (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_NULL,
+				.block_size = 1,
+				.key_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 0,
+					.max = 0,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 null_crypto_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -108,6 +153,8 @@ null_crypto_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_qpairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = null_crypto_pmd_capabilities;
 	}
 }
 
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypto.c index f267da5..29c1fe5 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,204 @@
 
 #define BYTE_LENGTH    8
 
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] = {
+	{	/* SHA1 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 20,
+					.max = 20,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size = 64,
+				.key_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 32,
+					.max = 32,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size = 128,
+				.key_size = {
+					.min = 128,
+					.max = 128,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 64,
+					.max = 64,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC MAC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.aad_size = { 0 }
+			}
+		}
+	},
+	{	/* AES GCM (AUTH) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.digest_size = {
+					.min = 8,
+					.max = 16,
+					.increment = 4
+				},
+				.aad_size = {
+					.min = 8,
+					.max = 12,
+					.increment = 4
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 32,
+					.increment = 8
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
 
@@ -652,7 +850,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev *dev,
 		info->max_nb_queue_pairs =
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags = dev->feature_flags;
+		info->capabilities = qat_pmd_capabilities;
 		info->sym.max_nb_sessions = internals->max_nb_sessions;
 		info->dev_type = RTE_CRYPTODEV_QAT_SYM_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 5e51aca..ba1b06b 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -95,6 +95,9 @@ crypto_qat_dev_init(__attribute__((unused)) struct rte_cryptodev_driver *crypto_
 	cryptodev->enqueue_burst = qat_pmd_enqueue_op_burst;
 	cryptodev->dequeue_burst = qat_pmd_dequeue_op_burst;
 
+	cryptodev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
 
 	internals = cryptodev->data->dev_private;
 	internals->max_nb_sessions = RTE_QAT_PMD_MAX_NB_SESSIONS; diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_pmd.c
index 6f84e5c..17175c7 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd.c
@@ -490,6 +490,9 @@ cryptodev_snow3g_create(const char *name,
 	dev->dequeue_burst = snow3g_pmd_dequeue_burst;
 	dev->enqueue_burst = snow3g_pmd_enqueue_burst;
 
+	dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
+
 	internals = dev->data->dev_private;
 
 	internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs; diff --git a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
index 5643323..74eee23 100644
--- a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
+++ b/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c
@@ -38,6 +38,55 @@
 
 #include "rte_snow3g_pmd_private.h"
 
+static const struct rte_cryptodev_capabilities snow3g_pmd_capabilities[] = {
+	{	/* SNOW3G (UIA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth = {
+				.algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.digest_size = {
+					.min = 4,
+					.max = 4,
+					.increment = 0
+				},
+				.aad_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size = 16,
+				.key_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 16,
+					.max = 16,
+					.increment = 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 /** Configure device */
 static int
 snow3g_pmd_config(__rte_unused struct rte_cryptodev *dev) @@ -109,6 +158,8 @@ snow3g_pmd_info_get(struct rte_cryptodev *dev,
 		dev_info->dev_type = dev->dev_type;
 		dev_info->max_nb_queue_pairs = internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions = internals->max_nb_sessions;
+		dev_info->feature_flags = dev->feature_flags;
+		dev_info->capabilities = snow3g_pmd_capabilities;
 	}
 }
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 4632ca3..49af2fc 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -102,6 +102,34 @@ struct rte_cryptodev_callback {
 	uint32_t active;			/**< Callback is executing */
 };
 
+
+const char *
+rte_cryptodev_get_feature_name(uint64_t flag) {
+	switch (flag) {
+	case RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO:
+		return "SYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO:
+		return "ASYMMETRIC_CRYPTO";
+	case RTE_CRYPTODEV_FF_OPERATION_CHAINING:
+		return "OPERATION_CHAINING";
+	case RTE_CRYPTODEV_FF_CPU_SSE:
+		return "CPU_SSE";
+	case RTE_CRYPTODEV_FF_CPU_AVX:
+		return "CPU_AVX";
+	case RTE_CRYPTODEV_FF_CPU_AVX2:
+		return "CPU_AVX2";
+	case RTE_CRYPTODEV_FF_CPU_AESNI:
+		return "CPU_AESNI";
+	case RTE_CRYPTODEV_FF_HW_ACCELERATED:
+		return "HW_ACCELERATED";
+
+	default:
+		return NULL;
+	}
+}
+
+
 int
 rte_cryptodev_create_vdev(const char *name, const char *args)  { diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index eb85c46..b989f9c 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -98,12 +98,145 @@ extern const char **rte_cyptodev_names;  #define CDEV_PMD_TRACE(fmt, args...)  #endif
 
+/**
+ * Symmetric Crypto Capability
+ */
+struct rte_cryptodev_symmetric_capability {
+	enum rte_crypto_sym_xform_type xform_type;
+	/**< Transform type : Authentication / Cipher */
+	union {
+		struct {
+			enum rte_crypto_auth_algorithm algo;
+			/**< authentication algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< auth key size range */
+			struct {
+				uint16_t min;	/**< minimum digest size */
+				uint16_t max;	/**< maximum digest size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} digest_size;
+			/**< digest size range */
+			struct {
+				uint16_t min;	/**< minimum aad size */
+				uint16_t max;	/**< maximum aad size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} aad_size;
+			/**< Additional authentication data size range */
+		} auth;
+		/**< Symmetric Authentication transform capabilities */
+		struct {
+			enum rte_crypto_cipher_algorithm algo;
+			/**< cipher algorithm */
+			uint16_t block_size;
+			/**< algorithm block size */
+			struct {
+				uint16_t min;	/**< minimum key size */
+				uint16_t max;	/**< maximum key size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} key_size;
+			/**< cipher key size range */
+			struct {
+				uint16_t min;	/**< minimum iv size */
+				uint16_t max;	/**< maximum iv size */
+				uint16_t increment;
+				/**< if a range of sizes are supported,
+				 * this parameter is used to indicate
+				 * increments in byte size that are supported
+				 * between the minimum and maximum */
+			} iv_size;
+			/**< Initialisation vector data size range */
+		} cipher;
+		/**< Symmetric Cipher transform capabilities */
+	};
+};
+
+/** Structure used to capture a capability of a crypto device */ struct 
+rte_cryptodev_capabilities {
+	enum rte_crypto_op_type op;
+	/**< Operation type */
+
+	union {
+		struct rte_cryptodev_symmetric_capability sym;
+		/**< Symmetric operation capability parameters */
+	};
+};
+
+/** Macro used at end of crypto PMD list */ #define 
+RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
+	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
+
+
+/**
+ * Crypto device supported feature flags
+ *
+ * Note:
+ * New features flags should be added to the end of the list
+ *
+ * Keep these flags synchronised with rte_cryptodev_get_feature_name()  
+*/
+#define	RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO	(1ULL << 0)
+/**< Symmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_ASYMMETRIC_CRYPTO	(1ULL << 1)
+/**< Asymmetric crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_OPERATION_CHAINING	(1ULL << 2)
+/**< Chaining crypto operations are supported */
+#define	RTE_CRYPTODEV_FF_CPU_SSE		(1ULL << 3)
+/**< Utilises CPU SIMD SSE instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX		(1ULL << 4)
+/**< Utilises CPU SIMD AVX instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AVX2		(1ULL << 5)
+/**< Utilises CPU SIMD AVX2 instructions */
+#define	RTE_CRYPTODEV_FF_CPU_AESNI		(1ULL << 6)
+/**< Utilises CPU AES-NI instructions */
+#define	RTE_CRYPTODEV_FF_HW_ACCELERATED		(1ULL << 7)
+/**< Operations are off-loaded to an external hardware accelerator */
+
+
+/**
+ * Get the name of a crypto device feature flag
+ *
+ * @param	flag	The mask describing the flag.
+ *
+ * @return
+ *   The name of this flag, or NULL if it's not a valid feature flag.
+ */
+
+extern const char *
+rte_cryptodev_get_feature_name(uint64_t flag);
+
 /**  Crypto device information */
 struct rte_cryptodev_info {
 	const char *driver_name;		/**< Driver name. */
 	enum rte_cryptodev_type dev_type;	/**< Device type */
 	struct rte_pci_device *pci_dev;		/**< PCI information. */
 
+	uint64_t feature_flags;			/**< Feature flags */
+
+	const struct rte_cryptodev_capabilities *capabilities;
+	/**< Array of devices supported capabilities */
+
 	unsigned max_nb_queue_pairs;
 	/**< Maximum number of queues pairs supported by device. */
 
@@ -540,6 +673,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp,  /**< Enqueue packets for processing on queue pair of a device. */
 
 
+
+
 struct rte_cryptodev_callback;
 
 /** Structure to keep track of registered callbacks */ @@ -558,6 +693,8 @@ struct rte_cryptodev {
 	/**< Pointer to device data */
 	struct rte_cryptodev_ops *dev_ops;
 	/**< Functions exported by PMD */
+	uint64_t feature_flags;
+	/**< Supported features */
 	struct rte_pci_device *pci_dev;
 	/**< PCI info. supplied by probing */
 
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index 6de6c7d..41004e1 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -10,6 +10,7 @@ DPDK_16.04 {
 	rte_cryptodev_configure;
 	rte_cryptodev_create_vdev;
 	rte_cryptodev_get_dev_id;
+	rte_cryptodev_get_feature_name;
 	rte_cryptodev_info_get;
 	rte_cryptodev_pmd_allocate;
 	rte_cryptodev_pmd_callback_process;
--
2.5.0

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

end of thread, other threads:[~2016-03-14  8:26 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-30 13:10 [dpdk-dev] [PATCH] cryptodev: add capabilities discovery mechanism Declan Doherty
2016-02-02 17:38 ` De Lara Guarch, Pablo
2016-02-10 16:37 ` Trahe, Fiona
2016-03-10 17:07 ` [dpdk-dev] [PATCH v2] " Pablo de Lara
2016-03-10 19:54   ` [dpdk-dev] [PATCH v3] " Pablo de Lara
2016-03-10 21:27     ` Trahe, Fiona
2016-03-11  1:20     ` Thomas Monjalon
2016-03-11  1:31       ` De Lara Guarch, Pablo
2016-03-11  1:36     ` [dpdk-dev] [PATCH v4] " Pablo de Lara
2016-03-11  9:35       ` Thomas Monjalon
2016-03-14  8:13       ` Cao, Min
2016-03-14  8:25     ` [dpdk-dev] [PATCH v3] " Cao, Min
2016-03-14  8:26   ` [dpdk-dev] [PATCH v2] " Cao, Min

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).