From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <min.cao@intel.com>
Received: from mga01.intel.com (mga01.intel.com [192.55.52.88])
 by dpdk.org (Postfix) with ESMTP id 348D2532C
 for <dev@dpdk.org>; Mon, 14 Mar 2016 09:26:59 +0100 (CET)
Received: from fmsmga001.fm.intel.com ([10.253.24.23])
 by fmsmga101.fm.intel.com with ESMTP; 14 Mar 2016 01:27:00 -0700
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.24,334,1455004800"; d="scan'208";a="923460115"
Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206])
 by fmsmga001.fm.intel.com with ESMTP; 14 Mar 2016 01:26:57 -0700
Received: from fmsmsx119.amr.corp.intel.com (10.18.124.207) by
 FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS)
 id 14.3.248.2; Mon, 14 Mar 2016 01:26:56 -0700
Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by
 FMSMSX119.amr.corp.intel.com (10.18.124.207) with Microsoft SMTP Server (TLS)
 id 14.3.248.2; Mon, 14 Mar 2016 01:26:56 -0700
Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.24]) by
 SHSMSX104.ccr.corp.intel.com ([169.254.5.132]) with mapi id 14.03.0248.002;
 Mon, 14 Mar 2016 16:26:54 +0800
From: "Cao, Min" <min.cao@intel.com>
To: "De Lara Guarch, Pablo" <pablo.de.lara.guarch@intel.com>, "dev@dpdk.org"
 <dev@dpdk.org>
Thread-Topic: [dpdk-dev] [PATCH v2] cryptodev: add capabilities discovery
 mechanism
Thread-Index: AQHReu8V+Wgg5XXrokegCoUaNdyK8p9YoEGg
Date: Mon, 14 Mar 2016 08:26:54 +0000
Message-ID: <B6059B2012717B4390714544B1F509E114F0B9E8@SHSMSX103.ccr.corp.intel.com>
References: <1454159457-6857-1-git-send-email-declan.doherty@intel.com>
 <1457629646-17224-1-git-send-email-pablo.de.lara.guarch@intel.com>
In-Reply-To: <1457629646-17224-1-git-send-email-pablo.de.lara.guarch@intel.com>
Accept-Language: zh-CN, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-originating-ip: [10.239.127.40]
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
Subject: Re: [dpdk-dev] [PATCH v2] cryptodev: add capabilities
	discovery	mechanism
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: patches and discussions about DPDK <dev.dpdk.org>
List-Unsubscribe: <http://dpdk.org/ml/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://dpdk.org/ml/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <http://dpdk.org/ml/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Mon, 14 Mar 2016 08:27:00 -0000

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=20
    Total 45 cases, 45 passed, 0 failed

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

- test case 3: l2fwd-crypto=20
    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 mechan=
ism

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

This patch add a mechanism for discovery of crypto device features and supp=
orted crypto operations and algorithms. It also provides a method for a cry=
pto PMD to publish any data range limitations it may have for the operation=
s and algorithms it supports.

The parameter feature_flags added to rte_cryptodev struct is used to captur=
e features such as operations supported (symmetric crypto, operation chaini=
ng etc) as well parameter such as whether the device is hardware accelerate=
d or uses SIMD instructions.

The capabilities parameter allows a PMD to define an array of supported ope=
rations 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 operatio=
ns" 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/aesn=
i_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 =3D aesni_gcm_pmd_dequeue_burst;
 	dev->enqueue_burst =3D aesni_gcm_pmd_enqueue_burst;
=20
+	dev->feature_flags =3D 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 |=3D RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_GCM_AVX:
+		dev->feature_flags |=3D RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_GCM_AVX2:
+		dev->feature_flags |=3D RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals =3D dev->data->dev_private;
=20
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 @@
=20
 #include "aesni_gcm_pmd_private.h"
=20
+static const struct rte_cryptodev_capabilities aesni_gcm_pmd_capabilities[=
] =3D {
+	{	/* AES GCM (AUTH) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 32,
+					.increment =3D 8
+				},
+				.digest_size =3D {
+					.min =3D 8,
+					.max =3D 16,
+					.increment =3D 4
+				},
+				.aad_size =3D {
+					.min =3D 8,
+					.max =3D 12,
+					.increment =3D 4
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher =3D {
+				.algo =3D RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 32,
+					.increment =3D 8
+				},
+				.iv_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 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_ae=
sni_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 s=
ocket_id)
 	dev->dequeue_burst =3D aesni_mb_pmd_dequeue_burst;
 	dev->enqueue_burst =3D aesni_mb_pmd_enqueue_burst;
=20
+	dev->feature_flags =3D 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 |=3D RTE_CRYPTODEV_FF_CPU_SSE;
+		break;
+	case RTE_AESNI_MB_AVX:
+		dev->feature_flags |=3D RTE_CRYPTODEV_FF_CPU_AVX;
+		break;
+	case RTE_AESNI_MB_AVX2:
+		dev->feature_flags |=3D RTE_CRYPTODEV_FF_CPU_AVX2;
+		break;
+	default:
+		break;
+	}
+
 	/* Set vector instructions mode supported */
 	internals =3D dev->data->dev_private;
=20
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/drivers/crypt=
o/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 @@
=20
 #include "rte_aesni_mb_pmd_private.h"
=20
+
+static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[]=
 =3D {
+	{	/* MD5 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_MD5_HMAC,
+				.block_size =3D 64,
+				.key_size =3D {
+					.min =3D 64,
+					.max =3D 64,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 12,
+					.max =3D 12,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* SHA1 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size =3D 64,
+				.key_size =3D {
+					.min =3D 64,
+					.max =3D 64,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 12,
+					.max =3D 12,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* SHA224 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA224_HMAC,
+				.block_size =3D 64,
+				.key_size =3D {
+					.min =3D 64,
+					.max =3D 64,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 14,
+					.max =3D 14,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size =3D 64,
+				.key_size =3D {
+					.min =3D 64,
+					.max =3D 64,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* SHA384 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA384_HMAC,
+				.block_size =3D 128,
+				.key_size =3D {
+					.min =3D 128,
+					.max =3D 128,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 24,
+					.max =3D 24,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size =3D 128,
+				.key_size =3D {
+					.min =3D 128,
+					.max =3D 128,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 32,
+					.max =3D 32,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 12,
+					.max =3D 12,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher =3D {
+				.algo =3D RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 32,
+					.increment =3D 8
+				},
+				.iv_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 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,
=20
 	if (dev_info !=3D NULL) {
 		dev_info->dev_type =3D dev->dev_type;
+		dev_info->feature_flags =3D dev->feature_flags;
+		dev_info->capabilities =3D aesni_mb_pmd_capabilities;
 		dev_info->max_nb_queue_pairs =3D internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions =3D internals->max_nb_sessions;
 	}
diff --git a/drivers/crypto/null/null_crypto_pmd.c b/drivers/crypto/null/nu=
ll_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 =3D null_crypto_pmd_dequeue_burst;
 	dev->enqueue_burst =3D null_crypto_pmd_enqueue_burst;
=20
+	dev->feature_flags =3D RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
+
 	internals =3D dev->data->dev_private;
=20
 	internals->max_nb_qpairs =3D init_params->max_nb_queue_pairs; diff --git =
a/drivers/crypto/null/null_crypto_pmd_ops.c b/drivers/crypto/null/null_cryp=
to_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 @@
=20
 #include "null_crypto_pmd_private.h"
=20
+static const struct rte_cryptodev_capabilities null_crypto_pmd_capabilitie=
s[] =3D {
+	{	/* NULL (AUTH) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_NULL,
+				.block_size =3D 1,
+				.key_size =3D {
+					.min =3D 0,
+					.max =3D 0,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 0,
+					.max =3D 0,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* NULL (CIPHER) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher =3D {
+				.algo =3D RTE_CRYPTO_CIPHER_NULL,
+				.block_size =3D 1,
+				.key_size =3D {
+					.min =3D 0,
+					.max =3D 0,
+					.increment =3D 8
+				},
+				.iv_size =3D {
+					.min =3D 0,
+					.max =3D 0,
+					.increment =3D 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 =3D dev->dev_type;
 		dev_info->max_nb_queue_pairs =3D internals->max_nb_qpairs;
 		dev_info->sym.max_nb_sessions =3D internals->max_nb_sessions;
+		dev_info->feature_flags =3D dev->feature_flags;
+		dev_info->capabilities =3D null_crypto_pmd_capabilities;
 	}
 }
=20
diff --git a/drivers/crypto/qat/qat_crypto.c b/drivers/crypto/qat/qat_crypt=
o.c index f267da5..29c1fe5 100644
--- a/drivers/crypto/qat/qat_crypto.c
+++ b/drivers/crypto/qat/qat_crypto.c
@@ -68,6 +68,204 @@
=20
 #define BYTE_LENGTH    8
=20
+static const struct rte_cryptodev_capabilities qat_pmd_capabilities[] =3D =
{
+	{	/* SHA1 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA1_HMAC,
+				.block_size =3D 64,
+				.key_size =3D {
+					.min =3D 64,
+					.max =3D 64,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 20,
+					.max =3D 20,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* SHA256 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA256_HMAC,
+				.block_size =3D 64,
+				.key_size =3D {
+					.min =3D 64,
+					.max =3D 64,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 32,
+					.max =3D 32,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* SHA512 HMAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SHA512_HMAC,
+				.block_size =3D 128,
+				.key_size =3D {
+					.min =3D 128,
+					.max =3D 128,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 64,
+					.max =3D 64,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* AES XCBC MAC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_AES_XCBC_MAC,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.aad_size =3D { 0 }
+			}
+		}
+	},
+	{	/* AES GCM (AUTH) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_AES_GCM,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 32,
+					.increment =3D 8
+				},
+				.digest_size =3D {
+					.min =3D 8,
+					.max =3D 16,
+					.increment =3D 4
+				},
+				.aad_size =3D {
+					.min =3D 8,
+					.max =3D 12,
+					.increment =3D 4
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UIA2) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 4,
+					.max =3D 4,
+					.increment =3D 0
+				},
+				.aad_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				}
+			}
+		}
+	},
+	{	/* AES GCM (CIPHER) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher =3D {
+				.algo =3D RTE_CRYPTO_CIPHER_AES_GCM,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 32,
+					.increment =3D 8
+				},
+				.iv_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				}
+			}
+		}
+	},
+	{	/* AES CBC */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher =3D {
+				RTE_CRYPTO_CIPHER_AES_CBC,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 32,
+					.increment =3D 8
+				},
+				.iv_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher =3D {
+				.algo =3D RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.iv_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				}
+			}
+		}
+	},
+	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
+};
+
 static inline uint32_t
 adf_modulo(uint32_t data, uint32_t shift);
=20
@@ -652,7 +850,8 @@ void qat_dev_info_get(__rte_unused struct rte_cryptodev=
 *dev,
 		info->max_nb_queue_pairs =3D
 				ADF_NUM_SYM_QPS_PER_BUNDLE *
 				ADF_NUM_BUNDLES_PER_DEV;
-
+		info->feature_flags =3D dev->feature_flags;
+		info->capabilities =3D qat_pmd_capabilities;
 		info->sym.max_nb_sessions =3D internals->max_nb_sessions;
 		info->dev_type =3D RTE_CRYPTODEV_QAT_SYM_PMD;
 	}
diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rt=
e_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_cr=
yptodev_driver *crypto_
 	cryptodev->enqueue_burst =3D qat_pmd_enqueue_op_burst;
 	cryptodev->dequeue_burst =3D qat_pmd_dequeue_op_burst;
=20
+	cryptodev->feature_flags =3D RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_HW_ACCELERATED |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
=20
 	internals =3D cryptodev->data->dev_private;
 	internals->max_nb_sessions =3D RTE_QAT_PMD_MAX_NB_SESSIONS; diff --git a/=
drivers/crypto/snow3g/rte_snow3g_pmd.c b/drivers/crypto/snow3g/rte_snow3g_p=
md.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 =3D snow3g_pmd_dequeue_burst;
 	dev->enqueue_burst =3D snow3g_pmd_enqueue_burst;
=20
+	dev->feature_flags =3D RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
+			RTE_CRYPTODEV_FF_OPERATION_CHAINING;
+
 	internals =3D dev->data->dev_private;
=20
 	internals->max_nb_queue_pairs =3D init_params->max_nb_queue_pairs; diff -=
-git a/drivers/crypto/snow3g/rte_snow3g_pmd_ops.c b/drivers/crypto/snow3g/r=
te_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 @@
=20
 #include "rte_snow3g_pmd_private.h"
=20
+static const struct rte_cryptodev_capabilities snow3g_pmd_capabilities[] =
=3D {
+	{	/* SNOW3G (UIA2) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_AUTH,
+			.auth =3D {
+				.algo =3D RTE_CRYPTO_AUTH_SNOW3G_UIA2,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.digest_size =3D {
+					.min =3D 4,
+					.max =3D 4,
+					.increment =3D 0
+				},
+				.aad_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				}
+			}
+		}
+	},
+	{	/* SNOW3G (UEA2) */
+		.op =3D RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		.sym =3D {
+			.xform_type =3D RTE_CRYPTO_SYM_XFORM_CIPHER,
+			.cipher =3D {
+				.algo =3D RTE_CRYPTO_CIPHER_SNOW3G_UEA2,
+				.block_size =3D 16,
+				.key_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 0
+				},
+				.iv_size =3D {
+					.min =3D 16,
+					.max =3D 16,
+					.increment =3D 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 =3D dev->dev_type;
 		dev_info->max_nb_queue_pairs =3D internals->max_nb_queue_pairs;
 		dev_info->sym.max_nb_sessions =3D internals->max_nb_sessions;
+		dev_info->feature_flags =3D dev->feature_flags;
+		dev_info->capabilities =3D snow3g_pmd_capabilities;
 	}
 }
=20
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rt=
e_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 */
 };
=20
+
+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 --gi=
t a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptod=
ev.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
=20
+/**
+ * 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=20
+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=20
+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() =20
+*/
+#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. */
=20
+	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. */
=20
@@ -540,6 +673,8 @@ typedef uint16_t (*enqueue_pkt_burst_t)(void *qp,  /**<=
 Enqueue packets for processing on queue pair of a device. */
=20
=20
+
+
 struct rte_cryptodev_callback;
=20
 /** 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 */
=20
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cr=
yptodev/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