+ != 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+check_capabilities(struct l2fwd_crypto_options *options, uint8_t cdev_id)
+{
+ struct rte_cryptodev_info dev_info;
+ const struct rte_cryptodev_capabilities *cap;
+
+ rte_cryptodev_info_get(cdev_id, &dev_info);
+
+ /* Set AEAD parameters */
+ if (options->xform_chain == L2FWD_CRYPTO_AEAD) {
+ /* Check if device supports AEAD algo */
+ cap = check_device_support_aead_algo(options, &dev_info,
+ cdev_id);
+ if (cap == NULL)
+ return -1;
+
+ if (check_iv_param(&cap->sym.aead.iv_size,
+ options->aead_iv_param,
+ options->aead_iv_random_size,
+ options->aead_iv.length) != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support IV length\n",
+ cdev_id);
+ return -1;
+ }
+
+ /*
+ * Check if length of provided AEAD key is supported
+ * by the algorithm chosen.
+ */
+ if (options->aead_key_param) {
+ if (check_supported_size(
+ options->aead_xform.aead.key.length,
+ cap->sym.aead.key_size.min,
+ cap->sym.aead.key_size.max,
+ cap->sym.aead.key_size.increment)
+ != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support "
+ "AEAD key length\n",
+ cdev_id);
+ return -1;
+ }
+ /*
+ * Check if length of the aead key to be randomly generated
+ * is supported by the algorithm chosen.
+ */
+ } else if (options->aead_key_random_size != -1) {
+ if (check_supported_size(options->aead_key_random_size,
+ cap->sym.aead.key_size.min,
+ cap->sym.aead.key_size.max,
+ cap->sym.aead.key_size.increment)
+ != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support "
+ "AEAD key length\n",
+ cdev_id);
+ return -1;
+ }
+ }
+
+
+ /*
+ * Check if length of provided AAD is supported
+ * by the algorithm chosen.
+ */
+ if (options->aad_param) {
+ if (check_supported_size(options->aad.length,
+ cap->sym.aead.aad_size.min,
+ cap->sym.aead.aad_size.max,
+ cap->sym.aead.aad_size.increment)
+ != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support "
+ "AAD length\n",
+ cdev_id);
+ return -1;
+ }
+ /*
+ * Check if length of AAD to be randomly generated
+ * is supported by the algorithm chosen.
+ */
+ } else if (options->aad_random_size != -1) {
+ if (check_supported_size(options->aad_random_size,
+ cap->sym.aead.aad_size.min,
+ cap->sym.aead.aad_size.max,
+ cap->sym.aead.aad_size.increment)
+ != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support "
+ "AAD length\n",
+ cdev_id);
+ return -1;
+ }
+ }
+
+ /* Check if digest size is supported by the algorithm. */
+ if (options->digest_size != -1) {
+ if (check_supported_size(options->digest_size,
+ cap->sym.aead.digest_size.min,
+ cap->sym.aead.digest_size.max,
+ cap->sym.aead.digest_size.increment)
+ != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support "
+ "digest length\n",
+ cdev_id);
+ return -1;
+ }
+ }
+ }
+
+ /* Set cipher parameters */
+ if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
+ options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
+ options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) {
+
+ /* Check if device supports cipher algo. 8< */
+ cap = check_device_support_cipher_algo(options, &dev_info,
+ cdev_id);
+ if (cap == NULL)
+ return -1;
+
+ if (check_iv_param(&cap->sym.cipher.iv_size,
+ options->cipher_iv_param,
+ options->cipher_iv_random_size,
+ options->cipher_iv.length) != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support IV length\n",
+ cdev_id);
+ return -1;
+ }
+ /* >8 End of check if device supports cipher algo. */
+
+ /* Check if capable cipher is supported. 8< */
+
+ /*
+ * Check if length of provided cipher key is supported
+ * by the algorithm chosen.
+ */
+ if (options->ckey_param) {
+ if (check_supported_size(
+ options->cipher_xform.cipher.key.length,
+ cap->sym.cipher.key_size.min,
+ cap->sym.cipher.key_size.max,
+ cap->sym.cipher.key_size.increment)
+ != 0) {
+ if (dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_CIPHER_WRAPPED_KEY) {
+ RTE_LOG(DEBUG, USER1,
+ "Key length does not match the device "
+ "%u capability. Key may be wrapped\n",
+ cdev_id);
+ } else {
+ RTE_LOG(DEBUG, USER1,
+ "Key length does not match the device "
+ "%u capability\n",
+ cdev_id);
+ return -1;
+ }
+ }
+
+ /*
+ * Check if length of the cipher key to be randomly generated
+ * is supported by the algorithm chosen.
+ */
+ } else if (options->ckey_random_size != -1) {
+ if (check_supported_size(options->ckey_random_size,
+ cap->sym.cipher.key_size.min,
+ cap->sym.cipher.key_size.max,
+ cap->sym.cipher.key_size.increment)
+ != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support cipher "
+ "key length\n",
+ cdev_id);
+ return -1;
+ }
+ }
+
+ if (options->cipher_xform.cipher.dataunit_len > 0) {
+ if (!(dev_info.feature_flags &
+ RTE_CRYPTODEV_FF_CIPHER_MULTIPLE_DATA_UNITS)) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support "
+ "cipher multiple data units\n",
+ cdev_id);
+ return -1;
+ }
+ if (cap->sym.cipher.dataunit_set != 0) {
+ int ret = 0;
+
+ switch (options->cipher_xform.cipher.dataunit_len) {
+ case 512:
+ if (!(cap->sym.cipher.dataunit_set &
+ RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_512_BYTES))
+ ret = -1;
+ break;
+ case 4096:
+ if (!(cap->sym.cipher.dataunit_set &
+ RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_4096_BYTES))
+ ret = -1;
+ break;
+ case 1048576:
+ if (!(cap->sym.cipher.dataunit_set &
+ RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_1_MEGABYTES))
+ ret = -1;
+ break;
+ default:
+ ret = -1;
+ }
+ if (ret == -1) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support "
+ "data-unit length %u\n",
+ cdev_id,
+ options->cipher_xform.cipher.dataunit_len);
+ return -1;
+ }
+ }
+ }
+ /* >8 End of checking if cipher is supported. */
+ }
+
+ /* Set auth parameters */
+ if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH ||
+ options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER ||
+ options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) {
+ /* Check if device supports auth algo */
+ cap = check_device_support_auth_algo(options, &dev_info,
+ cdev_id);
+ if (cap == NULL)
+ return -1;
+
+ if (check_iv_param(&cap->sym.auth.iv_size,
+ options->auth_iv_param,
+ options->auth_iv_random_size,
+ options->auth_iv.length) != 0) {
+ RTE_LOG(DEBUG, USER1,
+ "Device %u does not support IV length\n",
+ cdev_id);