[dpdk-dev] [PATCH] crypto action

Zhang, Roy Fan roy.fan.zhang at intel.com
Tue Sep 11 12:27:38 CEST 2018


Hi,

Sorry about the spam but this patch was not intended to send to DPDK just yet.
I need further polish it and splits into a patchset as the v2 of http://patchwork.dpdk.org/patch/43919/
So I marked this patch as rejected in patchwork.

Regards,
Fan

> -----Original Message-----
> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Zhang, Roy Fan
> Sent: Monday, September 10, 2018 3:33 PM
> To: dev at dpdk.org
> Cc: Dumitrescu, Cristian <cristian.dumitrescu at intel.com>
> Subject: [dpdk-dev] [PATCH] crypto action
> 
> Change-Id: If1aecaac3335685f3bef79f47768ba8ae7765fbb
> Signed-off-by: Zhang, Roy Fan <roy.fan.zhang at intel.com>
> ---
>  examples/ip_pipeline/Makefile                 |   1 +
>  examples/ip_pipeline/action.c                 |  11 +
>  examples/ip_pipeline/action.h                 |   1 +
>  examples/ip_pipeline/cli.c                    | 744 +++++++++++++++++++++++++-
>  examples/ip_pipeline/examples/flow_crypto.cli |  76 +++
>  examples/ip_pipeline/main.c                   |  17 +
>  examples/ip_pipeline/mempool.c                |   2 +-
>  examples/ip_pipeline/mempool.h                |   1 +
>  examples/ip_pipeline/pipeline.c               |  61 +++
>  examples/ip_pipeline/pipeline.h               |  13 +
>  examples/ip_pipeline/sym_crypto.c             | 320 +++++++++++
>  examples/ip_pipeline/sym_crypto.h             | 104 ++++
>  examples/ip_pipeline/thread.c                 |  10 +
>  lib/librte_pipeline/rte_table_action.c        | 183 ++++---
>  lib/librte_pipeline/rte_table_action.h        |  28 +-
>  15 files changed, 1472 insertions(+), 100 deletions(-)
>  create mode 100644 examples/ip_pipeline/examples/flow_crypto.cli
>  create mode 100644 examples/ip_pipeline/sym_crypto.c
>  create mode 100644 examples/ip_pipeline/sym_crypto.h
> 
> diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile
> index 3fb98ce3e..819625632 100644
> --- a/examples/ip_pipeline/Makefile
> +++ b/examples/ip_pipeline/Makefile
> @@ -18,6 +18,7 @@ SRCS-y += swq.c
>  SRCS-y += tap.c
>  SRCS-y += thread.c
>  SRCS-y += tmgr.c
> +SRCS-y += sym_crypto.c
> 
>  # Build using pkg-config variables if possible
>  $(shell pkg-config --exists libdpdk)
> diff --git a/examples/ip_pipeline/action.c b/examples/ip_pipeline/action.c
> index a29c2b368..d97423568 100644
> --- a/examples/ip_pipeline/action.c
> +++ b/examples/ip_pipeline/action.c
> @@ -333,6 +333,17 @@ table_action_profile_create(const char *name,
>  		}
>  	}
> 
> +	if (params->action_mask & (1LLU <<
> RTE_TABLE_ACTION_SYM_CRYPTO)) {
> +		status = rte_table_action_profile_action_register(ap,
> +			RTE_TABLE_ACTION_SYM_CRYPTO,
> +			&params->sym_crypto);
> +
> +		if (status) {
> +			rte_table_action_profile_free(ap);
> +			return NULL;
> +		}
> +	}
> +
>  	status = rte_table_action_profile_freeze(ap);
>  	if (status) {
>  		rte_table_action_profile_free(ap);
> diff --git a/examples/ip_pipeline/action.h b/examples/ip_pipeline/action.h
> index 417200e86..cde17e69a 100644
> --- a/examples/ip_pipeline/action.h
> +++ b/examples/ip_pipeline/action.h
> @@ -53,6 +53,7 @@ struct table_action_profile_params {
>  	struct rte_table_action_nat_config nat;
>  	struct rte_table_action_ttl_config ttl;
>  	struct rte_table_action_stats_config stats;
> +	struct rte_table_action_sym_crypto_config sym_crypto;
>  };
> 
>  struct table_action_profile {
> diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c
> index 102a1d6b7..c73403378 100644
> --- a/examples/ip_pipeline/cli.c
> +++ b/examples/ip_pipeline/cli.c
> @@ -17,6 +17,7 @@
>  #include "mempool.h"
>  #include "parser.h"
>  #include "pipeline.h"
> +#include "sym_crypto.h"
>  #include "swq.h"
>  #include "tap.h"
>  #include "thread.h"
> @@ -66,7 +67,7 @@ cmd_mempool(char **tokens,
>  	char *name;
>  	struct mempool *mempool;
> 
> -	if (n_tokens != 10) {
> +	if (n_tokens != 10 && n_tokens != 12) {
>  		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
>  		return;
>  	}
> @@ -113,6 +114,18 @@ cmd_mempool(char **tokens,
>  		return;
>  	}
> 
> +	if (n_tokens == 12) {
> +		if (strcmp(tokens[10], "priv") != 0) {
> +			snprintf(out, out_size, MSG_ARG_INVALID, "priv");
> +			return;
> +		}
> +
> +		if (parser_read_uint32(&p.priv_size, tokens[11]) != 0) {
> +			snprintf(out, out_size, MSG_ARG_INVALID, "priv");
> +			return;
> +		}
> +	}
> +
>  	mempool = mempool_create(name, &p);
>  	if (mempool == NULL) {
>  		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
> @@ -785,6 +798,569 @@ cmd_kni(char **tokens,
>  	}
>  }
> 
> +static const char cmd_sym_crypto_help[] =
> +"sym_crypto <sym_crypto_name>\n"
> +"   cryptodev <device_name> | cryptodev_id <device_id>\n"
> +"   q <n_queues> <queue_size>\n"
> +"   offset <crypto operation offset from start of mbuf>\n"
> +"   cpu <cpu_id>\n";
> +
> +static void
> +cmd_sym_crypto(char **tokens,
> +	uint32_t n_tokens,
> +	char *out,
> +	size_t out_size)
> +{
> +	struct sym_crypto_params params;
> +	char *name;
> +
> +	memset(&params, 0, sizeof(params));
> +	if (n_tokens != 11) {
> +		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
> +		return;
> +	}
> +
> +	name = tokens[1];
> +
> +	if (strcmp(tokens[2], "cryptodev") == 0)
> +		params.dev_name = tokens[3];
> +	else if (strcmp(tokens[2], "cryptodev_id") == 0) {
> +		if (parser_read_uint32(&params.cryptodev_id, tokens[3]) < 0)
> {
> +			snprintf(out, out_size,	MSG_ARG_INVALID,
> +				"cryptodev_id");
> +			return;
> +		}
> +	} else {
> +		snprintf(out, out_size,	MSG_ARG_INVALID,
> +			"cryptodev");
> +		return;
> +	}
> +
> +	if (strcmp(tokens[4], "q")) {
> +		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
> +			"4");
> +		return;
> +	}
> +
> +	if (parser_read_uint32(&params.n_queues, tokens[5]) < 0) {
> +		snprintf(out, out_size,	MSG_ARG_INVALID,
> +			"q");
> +		return;
> +	}
> +
> +	if (parser_read_uint32(&params.queue_size, tokens[6]) < 0) {
> +		snprintf(out, out_size,	MSG_ARG_INVALID,
> +			"queue_size");
> +		return;
> +	}
> +
> +	if (strcmp(tokens[7], "offset")) {
> +		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
> +			"offset");
> +		return;
> +	}
> +
> +	if (parser_read_uint32(&params.op_offset, tokens[8]) < 0) {
> +		snprintf(out, out_size,	MSG_ARG_INVALID,
> +			"offset");
> +		return;
> +	}
> +
> +	if (strcmp(tokens[9], "cpu")) {
> +		snprintf(out, out_size,	MSG_ARG_NOT_FOUND,
> +			"cpu");
> +		return;
> +	}
> +
> +	if (parser_read_uint32(&params.cpu_id, tokens[10]) < 0) {
> +		snprintf(out, out_size,	MSG_ARG_INVALID,
> +			"cpu");
> +		return;
> +	}
> +
> +	if (sym_crypto_create(name, &params) == NULL) {
> +		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
> +		return;
> +	}
> +}
> +
> +static const char cmd_sym_crypto_session_help[] =
> +"sym_crypto_session <sym_crypto_sesion_name>\n"
> +"   [create"
> +"   |  sym_crypto <sym_crypto_name>\n"
> +"   |  mempool_create <mempool_name> mempool_init
> <mempool_name>\n"
> +"   |  op
> <cipher_hash/hash_cipher/cipher_enc/cipher_dec/aead_enc/aead_dec\n"
> +"   |  [cipher_algo <ALGO> cipher_key <KEY> cipher_iv <IV>]\n"
> +"   |  [auth_algo <ALGO> auth_key <KEY>]\n"
> +"   |  [aead_algo <ALGO> aead_key <KEY> aead_iv <IV> aead_aad
> <AAD>]\n"
> +"   |  digest_size <SIZE>]\n"
> +"   [delete]\n";
> +
> +static void
> +cmd_sym_crypto_session(char **tokens,
> +	uint32_t n_tokens,
> +	char *out,
> +	size_t out_size)
> +{
> +	struct rte_crypto_sym_xform xforms[2];
> +	struct rte_crypto_cipher_xform *xform_cipher = NULL;
> +	struct rte_crypto_auth_xform *xform_auth = NULL;
> +	struct rte_crypto_aead_xform *xform_aead = NULL;
> +	struct sym_crypto_session_params p;
> +	struct sym_crypto *sym_crypto;
> +	struct mempool *mp;
> +	char *name;
> +	uint32_t i;
> +	uint32_t iv_offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
> +	int status = 0;
> +
> +	memset(&p, 0, sizeof(p));
> +	memset(xforms, 0, (sizeof(*xforms) * 2));
> +
> +	if (n_tokens == 3) {
> +		if (strcmp(tokens[2], "delete")) {
> +			snprintf(out, out_size, MSG_ARG_INVALID,
> tokens[0]);
> +			return;
> +		}
> +
> +		if (sym_crypto_session_delete(tokens[2]) < 0)
> +			snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
> +
> +		return;
> +	}
> +
> +	name = tokens[1];
> +
> +	if (strcmp(tokens[2], "create") || strcmp(tokens[3], "sym_crypto")
> ||
> +			strcmp(tokens[5], "mempool_create") ||
> +			strcmp(tokens[7], "mempool_init") ||
> +			strcmp(tokens[9], "op")) {
> +		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
> +		return;
> +	}
> +
> +	sym_crypto = sym_crypto_find(tokens[4]);
> +	if (sym_crypto == NULL) {
> +		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
> +		return;
> +	}
> +	p.cryptodev_id = sym_crypto->cryptodev_id;
> +
> +	mp = mempool_find(tokens[6]);
> +	if (mp == NULL) {
> +		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
> +		return;
> +	}
> +	p.mp_create = mp->m;
> +
> +	mp = mempool_find(tokens[8]);
> +	if (mp == NULL) {
> +		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
> +		return;
> +	}
> +	p.mp_init = mp->m;
> +
> +	if (strcmp(tokens[10], "cipher_auth") == 0) {
> +		xforms[0].next = &xforms[1];
> +
> +		xforms[0].type = RTE_CRYPTO_SYM_XFORM_CIPHER;
> +		xform_cipher = &xforms[0].cipher;
> +		xform_cipher->op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
> +
> +		xforms[1].type = RTE_CRYPTO_SYM_XFORM_AUTH;
> +		xform_auth = &xforms[1].auth;
> +		xform_auth->op = RTE_CRYPTO_AUTH_OP_GENERATE;
> +
> +	} else if (strcmp(tokens[10], "auth_cipher") == 0) {
> +		xforms[0].next = &xforms[1];
> +
> +		xforms[0].type = RTE_CRYPTO_SYM_XFORM_AUTH;
> +		xform_auth = &xforms[0].auth;
> +		xform_auth->op = RTE_CRYPTO_AUTH_OP_VERIFY;
> +
> +		xforms[1].type = RTE_CRYPTO_SYM_XFORM_CIPHER;
> +		xform_cipher = &xforms[1].cipher;
> +		xform_cipher->op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
> +
> +	} else if (strcmp(tokens[10], "cipher_enc") == 0) {
> +		xform_cipher = &xforms[0].cipher;
> +		xforms[0].type = RTE_CRYPTO_SYM_XFORM_CIPHER;
> +		xform_cipher->op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
> +
> +	} else if (strcmp(tokens[10], "cipher_dec") == 0) {
> +		xform_cipher = &xforms[0].cipher;
> +		xforms[0].type = RTE_CRYPTO_SYM_XFORM_CIPHER;
> +		xform_cipher->op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
> +
> +	} else if (strcmp(tokens[10], "aead_enc") == 0) {
> +		xforms[0].type = RTE_CRYPTO_SYM_XFORM_AEAD;
> +		xform_aead = &xforms[0].aead;
> +		xform_aead->op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
> +
> +	} else if (strcmp(tokens[10], "aead_dec") == 0) {
> +		xforms[0].type = RTE_CRYPTO_SYM_XFORM_AEAD;
> +		xform_aead = &xforms[0].aead;
> +		xform_aead->op = RTE_CRYPTO_AEAD_OP_DECRYPT;
> +
> +	} else {
> +		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
> +		return;
> +	}
> +
> +	for (i = 11; i < n_tokens; i++) {
> +		if (strcmp(tokens[i], "cipher_algo") == 0) {
> +			if (xform_cipher == NULL || xform_aead ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			status = rte_cryptodev_get_cipher_algo_enum(
> +				&xform_cipher->algo, tokens[i + 1]);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "cipher_key") == 0) {
> +			size_t len;
> +
> +			if (xform_cipher == NULL || xform_aead ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			len = strlen(tokens[i + 1]);
> +			xform_cipher->key.data = calloc(1, len / 2 + 1);
> +			if (xform_cipher->key.data == NULL) {
> +				snprintf(out, out_size,
> MSG_OUT_OF_MEMORY);
> +				goto error_exit;
> +			}
> +
> +			status = parse_hex_string(tokens[i + 1],
> +					xform_cipher->key.data,
> +					(uint32_t *)&len);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			xform_cipher->key.length = (uint16_t)len;
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "cipher_iv") == 0) {
> +			size_t len;
> +
> +			if (xform_cipher == NULL || xform_aead ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			len = strlen(tokens[i + 1]);
> +
> +			p.cipher_iv = calloc(1, len / 2 + 1);
> +			if (p.cipher_iv == NULL) {
> +				snprintf(out, out_size,
> MSG_OUT_OF_MEMORY);
> +				goto error_exit;
> +			}
> +
> +			status = parse_hex_string(tokens[i + 1], p.cipher_iv,
> +					(uint32_t *)&len);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			xform_cipher->iv.length = (uint16_t)len;
> +			p.cipher_iv_len = (uint32_t)len;
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "auth_algo") == 0) {
> +			if (xform_auth == NULL || xform_aead ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			status = rte_cryptodev_get_auth_algo_enum(&
> +				xform_auth->algo, tokens[i + 1]);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "auth_key") == 0) {
> +			size_t len;
> +
> +			if (xform_auth == NULL || xform_aead ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			len = strlen(tokens[i + 1]);
> +			xform_auth->key.data = calloc(1, len / 2 + 1);
> +			if (xform_auth->key.data == NULL) {
> +				snprintf(out, out_size,
> MSG_OUT_OF_MEMORY);
> +				goto error_exit;
> +			}
> +
> +			status = parse_hex_string(tokens[i + 1],
> +					xform_auth->key.data, (uint32_t
> *)&len);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			xform_auth->key.length = (uint16_t)len;
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "auth_iv") == 0) {
> +			size_t len;
> +
> +			if (xform_auth == NULL || xform_aead ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			len = strlen(tokens[i + 1]);
> +
> +			p.auth_iv = calloc(1, len / 2 + 1);
> +			if (p.auth_iv == NULL) {
> +				snprintf(out, out_size,
> MSG_OUT_OF_MEMORY);
> +				goto error_exit;
> +			}
> +
> +			status = parse_hex_string(tokens[i + 1], p.auth_iv,
> +					(uint32_t *)&len);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			xform_auth->iv.length = (uint16_t)len;
> +			p.auth_iv_len = (uint32_t)len;
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "aead_algo") == 0) {
> +			if (xform_aead == NULL || xform_cipher ||
> xform_auth ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			status = rte_cryptodev_get_aead_algo_enum(&
> +				xform_aead->algo, tokens[i + 1]);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "aead_key") == 0) {
> +			size_t len;
> +
> +			if (xform_aead == NULL || xform_cipher ||
> xform_auth ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			len = strlen(tokens[i + 1]);
> +
> +			xform_aead->key.data = calloc(1, len / 2 + 1);
> +			if (xform_aead->key.data == NULL) {
> +				snprintf(out, out_size,
> MSG_OUT_OF_MEMORY);
> +				goto error_exit;
> +			}
> +
> +			status = parse_hex_string(tokens[i + 1],
> +					xform_aead->key.data, (uint32_t
> *)&len);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			xform_aead->key.length = (uint16_t)len;
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "aead_iv") == 0) {
> +			size_t len;
> +
> +			if (xform_aead == NULL || xform_cipher ||
> xform_auth ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			len = strlen(tokens[i + 1]);
> +
> +			p.aead_iv = calloc(1, len / 2 + 1);
> +			if (p.aead_iv == NULL) {
> +				snprintf(out, out_size,
> MSG_OUT_OF_MEMORY);
> +				goto error_exit;
> +			}
> +
> +			status = parse_hex_string(tokens[i + 1], p.aead_iv,
> +					(uint32_t *)&len);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			xform_aead->iv.length = (uint16_t)len;
> +			p.aead_iv_len = (uint32_t)len;
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "aead_aad") == 0) {
> +			size_t len;
> +
> +			if (xform_aead == NULL || xform_cipher ||
> xform_auth ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			len = strlen(tokens[i + 1]);
> +
> +			p.aead_aad = calloc(1, len / 2 + 1);
> +			if (p.aead_aad == NULL) {
> +				snprintf(out, out_size,
> MSG_OUT_OF_MEMORY);
> +				goto error_exit;
> +			}
> +
> +			status = parse_hex_string(tokens[i + 1], p.aead_aad,
> +					(uint32_t *)&len);
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			xform_aead->aad_length = (uint16_t)len;
> +			p.aead_aad_len = (uint32_t)len;
> +
> +			i++;
> +			continue;
> +		}
> +
> +		if (strcmp(tokens[i], "digest_size") == 0) {
> +			if ((xform_aead == NULL && xform_auth == NULL) ||
> +					n_tokens < i + 2) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			if (xform_auth)
> +				status = parser_read_uint16(
> +					&xform_auth->digest_length,
> +					tokens[i + 1]);
> +			else
> +				status = parser_read_uint16(
> +					&xform_aead->digest_length,
> +					tokens[i + 1]);
> +
> +			if (status < 0) {
> +				snprintf(out, out_size, MSG_ARG_INVALID,
> +						tokens[0]);
> +				goto error_exit;
> +			}
> +
> +			i++;
> +			continue;
> +		}
> +
> +		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
> +		goto error_exit;
> +	}
> +
> +	if (xform_cipher)
> +		xform_cipher->iv.offset = iv_offset;
> +
> +	if (xform_aead)
> +		xform_aead->iv.offset = iv_offset;
> +
> +	if (xform_auth && (xform_auth->iv.length > 0)) {
> +		if (xform_cipher)
> +			xform_auth->iv.offset = iv_offset +
> +					xform_cipher->iv.length;
> +		else
> +			xform_auth->iv.offset = iv_offset;
> +	}
> +
> +	p.xforms = xforms;
> +
> +	if (sym_crypto_session_create(name, &p) == NULL)
> +		snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
> +
> +error_exit:
> +	if (xform_cipher && xform_cipher->key.data)
> +		free(xform_cipher->key.data);
> +	if (xform_auth && xform_auth->key.data)
> +		free(xform_auth->key.data);
> +	if (xform_aead && xform_aead->key.data)
> +		free(xform_aead->key.data);
> +	if (p.cipher_iv)
> +		free(p.cipher_iv);
> +	if (p.auth_iv)
> +		free(p.auth_iv);
> +	if (p.aead_iv)
> +		free(p.aead_iv);
> +	if (p.aead_aad)
> +		free(p.aead_aad);
> +}
> 
>  static const char cmd_port_in_action_profile_help[] =
>  "port in action profile <profile_name>\n"
> @@ -967,7 +1543,8 @@ static const char cmd_table_action_profile_help[] =
>  "   [ttl drop | fwd\n"
>  "       stats none | pkts]\n"
>  "   [stats pkts | bytes | both]\n"
> -"   [time]\n";
> +"   [time]\n"
> +"   [sym_crypto <SYM_CRYPTO_NAME>]\n";
> 
>  static void
>  cmd_table_action_profile(char **tokens,
> @@ -1285,6 +1862,30 @@ cmd_table_action_profile(char **tokens,
>  		t0 += 1;
>  	} /* time */
> 
> +	if ((t0 < n_tokens) && (strcmp(tokens[t0], "sym_crypto") == 0)) {
> +		struct sym_crypto *sym_crypto;
> +
> +		if (n_tokens < t0 + 2) {
> +			snprintf(out, out_size, MSG_ARG_MISMATCH,
> +				"table action profile sym_crypto");
> +			return;
> +		}
> +
> +		sym_crypto = sym_crypto_find(tokens[t0 + 1]);
> +		if (sym_crypto == NULL) {
> +			snprintf(out, out_size, MSG_ARG_INVALID,
> +				"table action profile sym_crypto");
> +			return;
> +		}
> +
> +		p.sym_crypto.cryptodev_id = sym_crypto->cryptodev_id;
> +		p.sym_crypto.op_offset = sym_crypto->op_offset;
> +
> +		p.action_mask |= 1LLU <<
> RTE_TABLE_ACTION_SYM_CRYPTO;
> +
> +		t0 += 5;
> +	} /* sym_crypto */
> +
>  	if (t0 < n_tokens) {
>  		snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
>  		return;
> @@ -1366,6 +1967,7 @@ static const char cmd_pipeline_port_in_help[] =
>  "   | tap <tap_name> mempool <mempool_name> mtu <mtu>\n"
>  "   | kni <kni_name>\n"
>  "   | source mempool <mempool_name> file <file_name> bpp
> <n_bytes_per_pkt>\n"
> +"   | sym_crypto <sym_crypto_name> rxq <queue_id>\n"
>  "   [action <port_in_action_profile_name>]\n"
>  "   [disabled]\n";
> 
> @@ -1538,6 +2140,27 @@ cmd_pipeline_port_in(char **tokens,
>  		}
> 
>  		t0 += 7;
> +	} else if (strcmp(tokens[t0], "sym_crypto") == 0) {
> +		if (n_tokens < t0 + 3) {
> +			snprintf(out, out_size, MSG_ARG_MISMATCH,
> +				"pipeline port in sym_crypto");
> +			return;
> +		}
> +
> +		p.dev_name = tokens[t0 + 1];
> +		if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0)
> {
> +			snprintf(out, out_size, MSG_ARG_INVALID,
> +				"rxq");
> +			return;
> +		}
> +
> +		/** TODO: different callback functions */
> +		p.sym_crypto.arg_callback = NULL;
> +		p.sym_crypto.f_callback = NULL;
> +
> +		p.type = PORT_IN_SYM_CRYPTO;
> +
> +		t0 += 4;
>  	} else {
>  		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
>  		return;
> @@ -1584,7 +2207,8 @@ static const char cmd_pipeline_port_out_help[] =
>  "   | tmgr <tmgr_name>\n"
>  "   | tap <tap_name>\n"
>  "   | kni <kni_name>\n"
> -"   | sink [file <file_name> pkts <max_n_pkts>]\n";
> +"   | sink [file <file_name> pkts <max_n_pkts>]\n"
> +"   | sym_crypto <sym_crypto_name> txq <txq_id> offset
> <crypto_op_offset>\n";
> 
>  static void
>  cmd_pipeline_port_out(char **tokens,
> @@ -1718,6 +2342,39 @@ cmd_pipeline_port_out(char **tokens,
>  				return;
>  			}
>  		}
> +
> +	} else if (strcmp(tokens[6], "sym_crypto") == 0) {
> +		if (n_tokens != 12) {
> +			snprintf(out, out_size, MSG_ARG_MISMATCH,
> +				"pipeline port out sym_crypto");
> +			return;
> +		}
> +
> +		p.type = PORT_OUT_SYM_CRYPTO;
> +
> +		p.dev_name = tokens[7];
> +
> +		if (strcmp(tokens[8], "txq") != 0) {
> +			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
> "txq");
> +			return;
> +		}
> +
> +		if (parser_read_uint16(&p.sym_crypto.queue_id, tokens[9])
> +				!= 0) {
> +			snprintf(out, out_size, MSG_ARG_INVALID,
> "queue_id");
> +			return;
> +		}
> +
> +		if (strcmp(tokens[10], "offset") != 0) {
> +			snprintf(out, out_size, MSG_ARG_NOT_FOUND,
> "offset");
> +			return;
> +		}
> +
> +		if (parser_read_uint32(&p.sym_crypto.crypto_op_offset,
> +				tokens[11]) != 0) {
> +			snprintf(out, out_size, MSG_ARG_INVALID, "offset");
> +			return;
> +		}
>  	} else {
>  		snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
>  		return;
> @@ -2866,6 +3523,7 @@ parse_match(char **tokens,
>   *    [ttl dec | keep]
>   *    [stats]
>   *    [time]
> + *    [sym_crypto data_offset <data_offset> session <session_name>]
>   *
>   * where:
>   *    <pa> ::= g | y | r | drop
> @@ -3349,6 +4007,52 @@ parse_table_action_time(char **tokens,
>  }
> 
>  static uint32_t
> +parse_table_action_sym_crypto(char **tokens,
> +	uint32_t n_tokens,
> +	struct table_rule_action *a)
> +{
> +	struct rte_table_action_sym_crypto_params *p = &a->sym_crypto;
> +	struct sym_crypto_session *sym_crypto_session;
> +	int status;
> +
> +	if ((n_tokens < 5) ||
> +		strcmp(tokens[0], "sym_crypto") ||
> +		strcmp(tokens[1], "data_offset") ||
> +		strcmp(tokens[3], "session"))
> +		return 0;
> +
> +	sym_crypto_session = sym_crypto_session_find(tokens[4]);
> +	if (sym_crypto_session == NULL)
> +		return 0;
> +
> +	memset(p, 0, sizeof(*p));
> +
> +	status = parser_read_uint32(&p->data_offset, tokens[2]);
> +	if (status < 0)
> +		return 0;
> +
> +	p->xform = sym_crypto_session->xforms;
> +	p->session = sym_crypto_session->session;
> +
> +	if (p->xform->type != RTE_CRYPTO_SYM_XFORM_AEAD) {
> +		p->cipher_auth.cipher_iv.val = sym_crypto_session-
> >cipher_iv;
> +		p->cipher_auth.cipher_iv.length =
> +				sym_crypto_session->cipher_iv_len;
> +		p->cipher_auth.auth_iv.val = sym_crypto_session->auth_iv;
> +		p->cipher_auth.auth_iv.length = sym_crypto_session-
> >auth_iv_len;
> +	} else {
> +		p->aead.iv.val = sym_crypto_session->aead_iv;
> +		p->aead.iv.length = sym_crypto_session->aead_iv_len;
> +		p->aead.aad.val = sym_crypto_session->aead_aad;
> +		p->aead.aad.length = sym_crypto_session->aead_aad_len;
> +	}
> +
> +	a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO;
> +
> +	return 5;
> +}
> +
> +static uint32_t
>  parse_table_action(char **tokens,
>  	uint32_t n_tokens,
>  	char *out,
> @@ -3492,6 +4196,20 @@ parse_table_action(char **tokens,
>  		n_tokens -= n;
>  	}
> 
> +	if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) {
> +		uint32_t n;
> +
> +		n = parse_table_action_sym_crypto(tokens, n_tokens, a);
> +		if (n == 0) {
> +			snprintf(out, out_size, MSG_ARG_INVALID,
> +				"action sym_crypto");
> +			return 0;
> +		}
> +
> +		tokens += n;
> +		n_tokens -= n;
> +	}
> +
>  	if (n_tokens0 - n_tokens == 1) {
>  		snprintf(out, out_size, MSG_ARG_INVALID, "action");
>  		return 0;
> @@ -4570,6 +5288,16 @@ cmd_help(char **tokens, uint32_t n_tokens, char
> *out, size_t out_size)
>  		return;
>  	}
> 
> +	if (strcmp(tokens[0], "sym_crypto") == 0) {
> +		snprintf(out, out_size, "\n%s\n", cmd_sym_crypto_help);
> +		return;
> +	}
> +
> +	if (strcmp(tokens[0], "sym_crypto_session") == 0) {
> +		snprintf(out, out_size, "\n%s\n",
> cmd_sym_crypto_session_help);
> +		return;
> +	}
> +
>  	if ((n_tokens == 4) &&
>  		(strcmp(tokens[0], "port") == 0) &&
>  		(strcmp(tokens[1], "in") == 0) &&
> @@ -4860,6 +5588,16 @@ cli_process(char *in, char *out, size_t out_size)
>  		return;
>  	}
> 
> +	if (strcmp(tokens[0], "sym_crypto") == 0) {
> +		cmd_sym_crypto(tokens, n_tokens, out, out_size);
> +		return;
> +	}
> +
> +	if (strcmp(tokens[0], "sym_crypto_session") == 0) {
> +		cmd_sym_crypto_session(tokens, n_tokens, out, out_size);
> +		return;
> +	}
> +
>  	if (strcmp(tokens[0], "port") == 0) {
>  		cmd_port_in_action_profile(tokens, n_tokens, out,
> out_size);
>  		return;
> diff --git a/examples/ip_pipeline/examples/flow_crypto.cli
> b/examples/ip_pipeline/examples/flow_crypto.cli
> new file mode 100644
> index 000000000..68b79060e
> --- /dev/null
> +++ b/examples/ip_pipeline/examples/flow_crypto.cli
> @@ -0,0 +1,76 @@
> +; SPDX-License-Identifier: BSD-3-Clause
> +; Copyright(c) 2010-2018 Intel Corporation
> +
> +;                 ________________
> +; LINK0 RXQ0 --->|                |---> LINK0 TXQ0
> +;                |                |
> +; LINK1 RXQ0 --->|                |---> LINK1 TXQ0
> +;                |      Flow      |
> +; LINK2 RXQ0 --->| Classification |---> LINK2 TXQ0
> +;                |                |
> +; LINK3 RXQ0 --->|                |---> LINK3 TXQ0
> +;                |________________|
> +;                        |
> +;                        +-----------> SINK0 (flow lookup miss)
> +;
> +; Input packet: Ethernet/IPv4
> +;
> +; Packet buffer layout:
> +; #   Field Name       Offset (Bytes)   Size (Bytes)
> +; 0   Mbuf             0                128
> +; 1   Headroom         128              128
> +; 2   Priv             256              32
> +; 3   Ethernet header  288              14
> +; 4   IPv4 header      302              20
> +; 5   TCP header       322              48
> +;
> +
> +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 priv 32
> +#mempool MEMPOOL_SESSION0 buffer 1024 pool 1024 cache 128 cpu 0
> +mempool MEMPOOL_SESSION0 buffer 1024 pool 1024 cache 128 cpu 1
> +
> +link LINK0 dev 0000:07:00.0 rxq 1 128 MEMPOOL0 txq 1 512 promiscuous on
> +#sym_crypto CRYPTO0 cryptodev crypto_aesni_gcm0 q 1 1024 offset 128
> cpu 0
> +sym_crypto CRYPTO0 cryptodev 0000:88:01.0_qat_sym q 1 1024 offset 128
> cpu 1
> +
> +#AES-CBC-128 encrypt
> +#sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op cipher_enc cipher_algo aes-cbc cipher_key
> 000102030405060708090a0b0c0d0e0f cipher_iv
> 000102030405060708090a0b0c0d0e0f
> +#AES-CBC-128 decrypt
> +#sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op cipher_dec cipher_algo aes-cbc cipher_key
> 000102030405060708090a0b0c0d0e0f cipher_iv
> 000102030405060708090a0b0c0d0e0f
> +#AES-CBC-128-SHA1 encrypt AESNI-MB
> +#sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op cipher_auth cipher_algo aes-cbc cipher_key
> 000102030405060708090a0b0c0d0e0f cipher_iv
> 000102030405060708090a0b0c0d0e0f auth_algo sha1-hmac auth_key
> 000102030405060708090a0b0c0d0e0f10111213 digest_size 12
> +#AES-CBC-128-SHA1 encrypt QAT
> +#sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op cipher_auth cipher_algo aes-cbc cipher_key
> 000102030405060708090a0b0c0d0e0f cipher_iv
> 000102030405060708090a0b0c0d0e0f auth_algo sha1-hmac auth_key
> 000102030405060708090a0b0c0d0e0f10111213 digest_size 20
> +#AES-CBC-128-SHA1 decrypt AESNI-MB
> +#sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op auth_cipher cipher_algo aes-cbc cipher_key
> 000102030405060708090a0b0c0d0e0f cipher_iv
> 000102030405060708090a0b0c0d0e0f auth_algo sha1-hmac auth_key
> 000102030405060708090a0b0c0d0e0f10111213 digest_size 12
> +#AES-CBC-128-SHA1 decrypt QAT
> +#sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op auth_cipher cipher_algo aes-cbc cipher_key
> 000102030405060708090a0b0c0d0e0f cipher_iv
> 000102030405060708090a0b0c0d0e0f auth_algo sha1-hmac auth_key
> 000102030405060708090a0b0c0d0e0f10111213 digest_size 20
> +#AES-GCM encrypt
> +sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op aead_enc aead_algo aes-gcm aead_key
> 000102030405060708090a0b0c0d0e0f aead_iv 000102030405060708090a0b
> aead_aad 000102030405060708090a0b0c0d0e0f digest_size 8
> +#AES-GCM decrypt
> +#sym_crypto_session SESSION0 create sym_crypto CRYPTO0
> mempool_create MEMPOOL_SESSION0 mempool_init MEMPOOL_SESSION0
> op aead_dec aead_algo aes-gcm aead_key
> 000102030405060708090a0b0c0d0e0f aead_iv 000102030405060708090a0b
> aead_aad 000102030405060708090a0b0c0d0e0f digest_size 8
> +
> +table action profile AP0 ipv4 offset 302 fwd sym_crypto CRYPTO0
> +table action profile AP1 ipv4 offset 302 fwd
> +
> +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0
> +
> +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0
> +pipeline PIPELINE0 port in bsz 32 sym_crypto CRYPTO0 rxq 0
> +
> +pipeline PIPELINE0 port out bsz 32 sym_crypto CRYPTO0 txq 0 offset 128
> +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0
> +pipeline PIPELINE0 port out bsz 32 sink
> +
> +pipeline PIPELINE0 table match hash ext key 8 mask FFFFFFFF00000000
> offset 314 buckets 16K size 65K action AP0
> +pipeline PIPELINE0 table match stub action AP1
> +
> +pipeline PIPELINE0 port in 0 table 0
> +pipeline PIPELINE0 port in 1 table 1
> +
> +thread 1 pipeline PIPELINE0 enable
> +
> +pipeline PIPELINE0 table 0 rule add match default action fwd port 2
> +pipeline PIPELINE0 table 0 rule add match hash ipv4_addr 100.0.0.10 action
> fwd port 0 sym_crypto data_offset 20 session SESSION0
> +pipeline PIPELINE0 table 1 rule add match default action fwd port 1
> +
> diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c
> index a69faceef..2de7f399b 100644
> --- a/examples/ip_pipeline/main.c
> +++ b/examples/ip_pipeline/main.c
> @@ -19,6 +19,7 @@
>  #include "pipeline.h"
>  #include "swq.h"
>  #include "tap.h"
> +#include "sym_crypto.h"
>  #include "thread.h"
>  #include "tmgr.h"
> 
> @@ -210,6 +211,22 @@ main(int argc, char **argv)
>  		return status;
>  	}
> 
> +	/* Sym Crypto */
> +	status = sym_crypto_init();
> +	if (status) {
> +		printf("Error: Sym Crypto initialization failed (%d)\n",
> +				status);
> +		return status;
> +	}
> +
> +	/* Sym Crypto Session */
> +	status = sym_crypto_session_init();
> +	if (status) {
> +		printf("Error: Sym Crypto initialization failed (%d)\n",
> +				status);
> +		return status;
> +	}
> +
>  	/* Action */
>  	status = port_in_action_profile_init();
>  	if (status) {
> diff --git a/examples/ip_pipeline/mempool.c
> b/examples/ip_pipeline/mempool.c
> index f5d2a7d10..9e95a3764 100644
> --- a/examples/ip_pipeline/mempool.c
> +++ b/examples/ip_pipeline/mempool.c
> @@ -56,7 +56,7 @@ mempool_create(const char *name, struct
> mempool_params *params)
>  		name,
>  		params->pool_size,
>  		params->cache_size,
> -		0,
> +		params->priv_size,
>  		params->buffer_size - sizeof(struct rte_mbuf),
>  		params->cpu_id);
> 
> diff --git a/examples/ip_pipeline/mempool.h
> b/examples/ip_pipeline/mempool.h
> index bd46a11ca..fb405de32 100644
> --- a/examples/ip_pipeline/mempool.h
> +++ b/examples/ip_pipeline/mempool.h
> @@ -32,6 +32,7 @@ struct mempool_params {
>  	uint32_t pool_size;
>  	uint32_t cache_size;
>  	uint32_t cpu_id;
> +	uint32_t priv_size;
>  };
> 
>  struct mempool *
> diff --git a/examples/ip_pipeline/pipeline.c
> b/examples/ip_pipeline/pipeline.c
> index 43fe8677a..a947dc144 100644
> --- a/examples/ip_pipeline/pipeline.c
> +++ b/examples/ip_pipeline/pipeline.c
> @@ -18,6 +18,7 @@
>  #include <rte_port_source_sink.h>
>  #include <rte_port_fd.h>
>  #include <rte_port_sched.h>
> +#include <rte_port_sym_crypto.h>
> 
>  #include <rte_table_acl.h>
>  #include <rte_table_array.h>
> @@ -35,6 +36,7 @@
>  #include "tap.h"
>  #include "tmgr.h"
>  #include "swq.h"
> +#include "sym_crypto.h"
> 
>  #include "hash_func.h"
> 
> @@ -163,6 +165,7 @@ pipeline_port_in_create(const char *pipeline_name,
>  		struct rte_port_kni_reader_params kni;
>  #endif
>  		struct rte_port_source_params source;
> +		struct rte_port_sym_crypto_reader_params sym_crypto;
>  	} pp;
> 
>  	struct pipeline *pipeline;
> @@ -296,6 +299,27 @@ pipeline_port_in_create(const char *pipeline_name,
>  		break;
>  	}
> 
> +	case PORT_IN_SYM_CRYPTO:
> +	{
> +		struct sym_crypto *sym_crypto;
> +
> +		sym_crypto = sym_crypto_find(params->dev_name);
> +		if (sym_crypto == NULL)
> +			return -1;
> +
> +		if (params->rxq.queue_id > (sym_crypto->n_queues - 1))
> +			return -1;
> +
> +		pp.sym_crypto.cryptodev_id = sym_crypto->cryptodev_id;
> +		pp.sym_crypto.queue_id = params->rxq.queue_id;
> +		pp.sym_crypto.f_callback = params->sym_crypto.f_callback;
> +		pp.sym_crypto.arg_callback = params-
> >sym_crypto.arg_callback;
> +		p.ops = &rte_port_sym_crypto_reader_ops;
> +		p.arg_create = &pp.sym_crypto;
> +
> +		break;
> +	}
> +
>  	default:
>  		return -1;
>  	}
> @@ -385,6 +409,7 @@ pipeline_port_out_create(const char *pipeline_name,
>  		struct rte_port_kni_writer_params kni;
>  #endif
>  		struct rte_port_sink_params sink;
> +		struct rte_port_sym_crypto_writer_params sym_crypto;
>  	} pp;
> 
>  	union {
> @@ -394,6 +419,7 @@ pipeline_port_out_create(const char *pipeline_name,
>  #ifdef RTE_LIBRTE_KNI
>  		struct rte_port_kni_writer_nodrop_params kni;
>  #endif
> +		struct rte_port_sym_crypto_writer_nodrop_params
> sym_crypto;
>  	} pp_nodrop;
> 
>  	struct pipeline *pipeline;
> @@ -549,6 +575,41 @@ pipeline_port_out_create(const char
> *pipeline_name,
>  		break;
>  	}
> 
> +	case PORT_OUT_SYM_CRYPTO:
> +	{
> +		struct sym_crypto *sym_crypto;
> +
> +		sym_crypto = sym_crypto_find(params->dev_name);
> +		if (sym_crypto == NULL)
> +			return -1;
> +
> +		if (params->sym_crypto.queue_id > (sym_crypto-
> >n_queues - 1))
> +			return -1;
> +
> +		pp.sym_crypto.cryptodev_id = sym_crypto->cryptodev_id;
> +		pp.sym_crypto.queue_id = params->txq.queue_id;
> +		pp.sym_crypto.tx_burst_sz = params->burst_size;
> +		pp.sym_crypto.crypto_op_offset =
> +				params->sym_crypto.crypto_op_offset;
> +
> +		pp_nodrop.sym_crypto.cryptodev_id = sym_crypto-
> >cryptodev_id;
> +		pp_nodrop.sym_crypto.queue_id = params->txq.queue_id;
> +		pp_nodrop.sym_crypto.tx_burst_sz = params->burst_size;
> +		pp_nodrop.sym_crypto.n_retries = params->retry;
> +		pp_nodrop.sym_crypto.crypto_op_offset =
> +				params->sym_crypto.crypto_op_offset;
> +
> +		if (params->retry == 0) {
> +			p.ops = &rte_port_sym_crypto_writer_ops;
> +			p.arg_create = &pp.sym_crypto;
> +		} else {
> +			p.ops = &rte_port_sym_crypto_writer_nodrop_ops;
> +			p.arg_create = &pp_nodrop.sym_crypto;
> +		}
> +
> +		break;
> +	}
> +
>  	default:
>  		return -1;
>  	}
> diff --git a/examples/ip_pipeline/pipeline.h
> b/examples/ip_pipeline/pipeline.h
> index a953a29fa..b8a420f51 100644
> --- a/examples/ip_pipeline/pipeline.h
> +++ b/examples/ip_pipeline/pipeline.h
> @@ -27,6 +27,7 @@ enum port_in_type {
>  	PORT_IN_TAP,
>  	PORT_IN_KNI,
>  	PORT_IN_SOURCE,
> +	PORT_IN_SYM_CRYPTO,
>  };
> 
>  struct port_in_params {
> @@ -48,6 +49,11 @@ struct port_in_params {
>  			const char *file_name;
>  			uint32_t n_bytes_per_pkt;
>  		} source;
> +
> +		struct {
> +			void *f_callback;
> +			void *arg_callback;
> +		} sym_crypto;
>  	};
>  	uint32_t burst_size;
> 
> @@ -62,6 +68,7 @@ enum port_out_type {
>  	PORT_OUT_TAP,
>  	PORT_OUT_KNI,
>  	PORT_OUT_SINK,
> +	PORT_OUT_SYM_CRYPTO,
>  };
> 
>  struct port_out_params {
> @@ -76,6 +83,11 @@ struct port_out_params {
>  			const char *file_name;
>  			uint32_t max_n_pkts;
>  		} sink;
> +
> +		struct {
> +			uint16_t queue_id;
> +			uint32_t crypto_op_offset;
> +		} sym_crypto;
>  	};
>  	uint32_t burst_size;
>  	int retry;
> @@ -268,6 +280,7 @@ struct table_rule_action {
>  	struct rte_table_action_ttl_params ttl;
>  	struct rte_table_action_stats_params stats;
>  	struct rte_table_action_time_params time;
> +	struct rte_table_action_sym_crypto_params sym_crypto;
>  };
> 
>  int
> diff --git a/examples/ip_pipeline/sym_crypto.c
> b/examples/ip_pipeline/sym_crypto.c
> new file mode 100644
> index 000000000..88045e163
> --- /dev/null
> +++ b/examples/ip_pipeline/sym_crypto.c
> @@ -0,0 +1,320 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include <rte_cryptodev.h>
> +#include <rte_cryptodev_pmd.h>
> +#include <rte_string_fns.h>
> +
> +#include "sym_crypto.h"
> +
> +static struct sym_crypto_list sym_crypto_list;
> +
> +int
> +sym_crypto_init(void)
> +{
> +	TAILQ_INIT(&sym_crypto_list);
> +
> +	return 0;
> +}
> +
> +struct sym_crypto *
> +sym_crypto_find(const char *name)
> +{
> +	struct sym_crypto *sym_crypto;
> +
> +	if (name == NULL)
> +		return NULL;
> +
> +	TAILQ_FOREACH(sym_crypto, &sym_crypto_list, node)
> +		if (strcmp(sym_crypto->name, name) == 0)
> +			return sym_crypto;
> +
> +	return NULL;
> +}
> +
> +struct sym_crypto *
> +sym_crypto_next(struct sym_crypto *sym_crypto)
> +{
> +	return (sym_crypto == NULL) ?
> +			TAILQ_FIRST(&sym_crypto_list) :
> +			TAILQ_NEXT(sym_crypto, node);
> +}
> +
> +struct sym_crypto *
> +sym_crypto_create(const char *name, struct sym_crypto_params *params)
> +{
> +	struct rte_cryptodev_info dev_info;
> +	struct rte_cryptodev_config dev_conf;
> +	struct rte_cryptodev_qp_conf queue_conf;
> +	struct sym_crypto *sym_crypto;
> +	uint32_t cryptodev_id, i;
> +	int status;
> +
> +	/* Check input params */
> +	if ((name == NULL) ||
> +		sym_crypto_find(name) ||
> +		(params->n_queues == 0) ||
> +		(params->queue_size == 0))
> +		return NULL;
> +
> +	if (params->dev_name) {
> +		status = rte_cryptodev_get_dev_id(params->dev_name);
> +		if (status == -1)
> +			return NULL;
> +
> +		cryptodev_id = (uint32_t)status;
> +	} else {
> +		if (rte_cryptodev_pmd_is_valid_dev(params->cryptodev_id)
> == 0)
> +			return NULL;
> +
> +		cryptodev_id = params->cryptodev_id;
> +	}
> +
> +	rte_cryptodev_info_get(cryptodev_id, &dev_info);
> +	if (dev_info.max_nb_queue_pairs < params->n_queues)
> +		return NULL;
> +	if ((dev_info.feature_flags &
> RTE_CRYPTODEV_FF_HW_ACCELERATED) &&
> +		(params->cpu_id !=
> +			(uint32_t)rte_cryptodev_socket_id(cryptodev_id)))
> +		return NULL;
> +
> +	dev_conf.socket_id = params->cpu_id;
> +	dev_conf.nb_queue_pairs = params->n_queues;
> +
> +	status = rte_cryptodev_configure(cryptodev_id, &dev_conf);
> +	if (status < 0)
> +		return NULL;
> +
> +	queue_conf.nb_descriptors = params->queue_size;
> +	for (i = 0; i < params->n_queues; i++) {
> +		status = rte_cryptodev_queue_pair_setup(cryptodev_id, i,
> +				&queue_conf, params->cpu_id, NULL);
> +		if (status < 0)
> +			return NULL;
> +	}
> +
> +	if (rte_cryptodev_start(cryptodev_id) < 0)
> +		return NULL;
> +
> +	sym_crypto = calloc(1, sizeof(struct sym_crypto));
> +	if (sym_crypto == NULL) {
> +		rte_cryptodev_stop(cryptodev_id);
> +		return NULL;
> +	}
> +
> +	strlcpy(sym_crypto->name, name, sizeof(sym_crypto->name));
> +	sym_crypto->cryptodev_id = cryptodev_id;
> +	sym_crypto->n_queues = params->n_queues;
> +	sym_crypto->op_offset = params->op_offset;
> +
> +	TAILQ_INSERT_TAIL(&sym_crypto_list, sym_crypto, node);
> +
> +	return sym_crypto;
> +}
> +
> +int
> +sym_crypto_is_up(const char *name)
> +{
> +	struct sym_crypto *sym_crypto;
> +	struct rte_cryptodev *dev;
> +
> +	/* Check input params */
> +	if (name == NULL)
> +		return 0;
> +
> +	sym_crypto = sym_crypto_find(name);
> +	if (sym_crypto == NULL)
> +		return 0;
> +
> +	/* Resource */
> +	dev = &rte_cryptodevs[sym_crypto->cryptodev_id];
> +
> +	return (int)dev->data->dev_started;
> +}
> +
> +static struct sym_crypto_session_list sym_crypto_session_list;
> +
> +int
> +sym_crypto_session_init(void)
> +{
> +	TAILQ_INIT(&sym_crypto_session_list);
> +
> +	return 0;
> +}
> +
> +struct sym_crypto_session *
> +sym_crypto_session_find(const char *name)
> +{
> +	struct sym_crypto_session *sym_crypto_session;
> +
> +	if (name == NULL)
> +		return NULL;
> +
> +	TAILQ_FOREACH(sym_crypto_session, &sym_crypto_session_list,
> node)
> +		if (strcmp(sym_crypto_session->name, name) == 0)
> +			return sym_crypto_session;
> +
> +	return NULL;
> +}
> +
> +struct sym_crypto_session *
> +sym_crypto_session_next(struct sym_crypto_session
> *sym_crypto_session)
> +{
> +	return (sym_crypto_session == NULL) ?
> +			TAILQ_FIRST(&sym_crypto_session_list) :
> +			TAILQ_NEXT(sym_crypto_session, node);
> +}
> +
> +struct sym_crypto_session *
> +sym_crypto_session_create(const char *name,
> +		struct sym_crypto_session_params *params)
> +{
> +	struct sym_crypto_session *sym_crypto_session;
> +	struct rte_cryptodev_sym_session *session;
> +	uint32_t cryptodev_id;
> +	int status;
> +
> +	/* Check input params */
> +	if ((name == NULL) ||
> +		sym_crypto_find(name) ||
> +		(params->mp_create == NULL) ||
> +		(params->mp_init == NULL) ||
> +		(params->xforms == NULL))
> +		return NULL;
> +
> +	if (params->dev_name) {
> +		status = rte_cryptodev_get_dev_id(params->dev_name);
> +		if (status == -1)
> +			return NULL;
> +
> +		cryptodev_id = (uint32_t)status;
> +	} else {
> +		if (rte_cryptodev_pmd_is_valid_dev(params->cryptodev_id)
> == 0)
> +			return NULL;
> +
> +		cryptodev_id = params->cryptodev_id;
> +	}
> +
> +	session = rte_cryptodev_sym_session_create(params->mp_create);
> +	if (session == NULL)
> +		return NULL;
> +
> +	status = rte_cryptodev_sym_session_init(cryptodev_id, session,
> +			params->xforms, params->mp_init);
> +	if (status < 0) {
> +		rte_cryptodev_sym_session_free(session);
> +		return NULL;
> +	}
> +
> +	sym_crypto_session = calloc(1, sizeof(struct sym_crypto_session));
> +	if (sym_crypto_session == NULL) {
> +		rte_cryptodev_sym_session_clear(cryptodev_id, session);
> +		rte_cryptodev_sym_session_free(session);
> +		return NULL;
> +	}
> +
> +	strlcpy(sym_crypto_session->name, name,
> +			sizeof(sym_crypto_session->name));
> +	sym_crypto_session->cryptodev_id = cryptodev_id;
> +	sym_crypto_session->session = session;
> +
> +	if (params->cipher_iv_len) {
> +		sym_crypto_session->cipher_iv = calloc(1,
> +				params->cipher_iv_len);
> +		if (sym_crypto_session->cipher_iv == NULL) {
> +			rte_cryptodev_sym_session_clear(cryptodev_id,
> session);
> +			rte_cryptodev_sym_session_free(session);
> +			free(sym_crypto_session);
> +			return NULL;
> +		}
> +		memcpy(sym_crypto_session->cipher_iv, params->cipher_iv,
> +				params->cipher_iv_len);
> +		sym_crypto_session->cipher_iv_len = params-
> >cipher_iv_len;
> +	}
> +
> +	if (params->auth_iv_len) {
> +		sym_crypto_session->auth_iv = calloc(1, params-
> >auth_iv_len);
> +		if (sym_crypto_session->auth_iv == NULL) {
> +			rte_cryptodev_sym_session_clear(cryptodev_id,
> session);
> +			rte_cryptodev_sym_session_free(session);
> +			free(sym_crypto_session);
> +			return NULL;
> +		}
> +		memcpy(sym_crypto_session->auth_iv, params->auth_iv,
> +				params->auth_iv_len);
> +		sym_crypto_session->auth_iv_len = params->auth_iv_len;
> +	}
> +
> +	if (params->aead_iv_len) {
> +		sym_crypto_session->aead_iv = calloc(1, params-
> >aead_iv_len);
> +		if (sym_crypto_session->aead_iv == NULL) {
> +			rte_cryptodev_sym_session_clear(cryptodev_id,
> session);
> +			rte_cryptodev_sym_session_free(session);
> +			free(sym_crypto_session);
> +			return NULL;
> +		}
> +		memcpy(sym_crypto_session->aead_iv, params->aead_iv,
> +				params->aead_iv_len);
> +		sym_crypto_session->aead_iv_len = params->aead_iv_len;
> +	}
> +
> +	if (params->aead_aad_len) {
> +		sym_crypto_session->aead_aad = calloc(1, params-
> >aead_aad_len);
> +		if (sym_crypto_session->aead_aad == NULL) {
> +			rte_cryptodev_sym_session_clear(cryptodev_id,
> session);
> +			rte_cryptodev_sym_session_free(session);
> +			free(sym_crypto_session);
> +			return NULL;
> +		}
> +		memcpy(sym_crypto_session->aead_aad, params-
> >aead_aad,
> +				params->aead_aad_len);
> +		sym_crypto_session->aead_aad_len = params-
> >aead_aad_len;
> +	}
> +
> +	memcpy(&sym_crypto_session->xforms[0], params->xforms,
> +			sizeof(struct rte_crypto_sym_xform));
> +	if (params->xforms->next) {
> +		memcpy(&sym_crypto_session->xforms[1], params-
> >xforms->next,
> +			sizeof(struct rte_crypto_sym_xform));
> +		sym_crypto_session->xforms[0].next =
> +				&sym_crypto_session->xforms[1];
> +	}
> +
> +	TAILQ_INSERT_TAIL(&sym_crypto_session_list, sym_crypto_session,
> node);
> +
> +	return sym_crypto_session;
> +}
> +
> +int
> +sym_crypto_session_delete(const char *name)
> +{
> +	struct sym_crypto_session *sym_crypto_session =
> +			sym_crypto_session_find(name);
> +
> +	if (sym_crypto_session == NULL)
> +		return -1;
> +
> +	rte_cryptodev_sym_session_clear(sym_crypto_session-
> >cryptodev_id,
> +			sym_crypto_session->session);
> +	rte_cryptodev_sym_session_free(sym_crypto_session->session);
> +
> +	if (sym_crypto_session->cipher_iv)
> +		free(sym_crypto_session->cipher_iv);
> +
> +	if (sym_crypto_session->auth_iv)
> +		free(sym_crypto_session->auth_iv);
> +
> +	if (sym_crypto_session->aead_iv)
> +		free(sym_crypto_session->aead_iv);
> +
> +	if (sym_crypto_session->aead_aad)
> +		free(sym_crypto_session->aead_aad);
> +
> +	memset(sym_crypto_session, 0, sizeof(*sym_crypto_session));
> +
> +	return 0;
> +}
> diff --git a/examples/ip_pipeline/sym_crypto.h
> b/examples/ip_pipeline/sym_crypto.h
> new file mode 100644
> index 000000000..b9c5e442e
> --- /dev/null
> +++ b/examples/ip_pipeline/sym_crypto.h
> @@ -0,0 +1,104 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(c) 2018 Intel Corporation
> + */
> +
> +#ifndef _INCLUDE_SYM_C_H_
> +#define _INCLUDE_SYM_C_H_
> +
> +#include <stdint.h>
> +#include <sys/queue.h>
> +
> +#include <rte_cryptodev.h>
> +
> +#include "common.h"
> +
> +struct sym_crypto {
> +	TAILQ_ENTRY(sym_crypto) node;
> +	char name[NAME_SIZE];
> +	uint16_t cryptodev_id;
> +	uint32_t op_offset;
> +	uint32_t n_queues;
> +};
> +
> +TAILQ_HEAD(sym_crypto_list, sym_crypto);
> +
> +int
> +sym_crypto_init(void);
> +
> +struct sym_crypto *
> +sym_crypto_find(const char *name);
> +
> +struct sym_crypto *
> +sym_crypto_next(struct sym_crypto *sym_crypto);
> +
> +struct sym_crypto_params {
> +	const char *dev_name;
> +	uint32_t cryptodev_id; /**< Valid only when *dev_name* is NULL.
> */
> +	uint32_t n_queues;
> +	uint32_t queue_size;
> +	uint32_t cpu_id;
> +	uint32_t op_offset;
> +};
> +
> +struct sym_crypto *
> +sym_crypto_create(const char *name, struct sym_crypto_params
> *params);
> +
> +int
> +sym_crypto_is_up(const char *name);
> +
> +struct sym_crypto_session {
> +	TAILQ_ENTRY(sym_crypto_session) node;
> +	char name[NAME_SIZE];
> +	uint32_t cryptodev_id;
> +	struct rte_crypto_sym_xform xforms[2];
> +	/** Cipher IV */
> +	uint8_t *cipher_iv;
> +	uint32_t cipher_iv_len;
> +	uint8_t *auth_iv;
> +	uint32_t auth_iv_len;
> +	uint8_t *aead_iv;
> +	uint32_t aead_iv_len;
> +	uint8_t *aead_aad;
> +	uint32_t aead_aad_len;
> +	uint32_t data_offset;
> +	struct rte_cryptodev_sym_session *session;
> +};
> +
> +TAILQ_HEAD(sym_crypto_session_list, sym_crypto_session);
> +
> +int
> +sym_crypto_session_init(void);
> +
> +struct sym_crypto_session *
> +sym_crypto_session_find(const char *name);
> +
> +struct sym_crypto_session *
> +sym_crypto_session_next(struct sym_crypto_session
> *sym_crypto_session);
> +
> +struct sym_crypto_session_params {
> +	const char *dev_name;
> +	uint32_t cryptodev_id; /**< Valid only when *dev_name* is NULL.
> */
> +
> +	struct rte_crypto_sym_xform *xforms;
> +	struct rte_mempool *mp_create;
> +	struct rte_mempool *mp_init;
> +	/** Cipher IV */
> +	uint8_t *cipher_iv;
> +	uint32_t cipher_iv_len;
> +	uint8_t *auth_iv;
> +	uint32_t auth_iv_len;
> +	uint8_t *aead_iv;
> +	uint32_t aead_iv_len;
> +	uint8_t *aead_aad;
> +	uint32_t aead_aad_len;
> +	uint32_t data_offset;
> +};
> +
> +struct sym_crypto_session *
> +sym_crypto_session_create(const char *name,
> +		struct sym_crypto_session_params *params);
> +
> +int
> +sym_crypto_session_delete(const char *name);
> +
> +#endif
> diff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c
> index 7fc03332e..ca741952a 100644
> --- a/examples/ip_pipeline/thread.c
> +++ b/examples/ip_pipeline/thread.c
> @@ -2476,6 +2476,16 @@ action_convert(struct rte_table_action *a,
>  			return status;
>  	}
> 
> +	if (action->action_mask & (1LLU <<
> RTE_TABLE_ACTION_SYM_CRYPTO)) {
> +		status = rte_table_action_apply(a,
> +			data,
> +			RTE_TABLE_ACTION_SYM_CRYPTO,
> +			&action->sym_crypto);
> +
> +		if (status)
> +			return status;
> +	}
> +
>  	return 0;
>  }
> 
> diff --git a/lib/librte_pipeline/rte_table_action.c
> b/lib/librte_pipeline/rte_table_action.c
> index a958aa82a..866a714a8 100644
> --- a/lib/librte_pipeline/rte_table_action.c
> +++ b/lib/librte_pipeline/rte_table_action.c
> @@ -1,7 +1,6 @@
>  /* SPDX-License-Identifier: BSD-3-Clause
>   * Copyright(c) 2010-2018 Intel Corporation
>   */
> -
>  #include <stdlib.h>
>  #include <string.h>
> 
> @@ -1228,8 +1227,6 @@ pkt_work_time(struct time_data *data,
>  #define CRYPTO_OP_MASK_CIPHER	0x1
>  #define CRYPTO_OP_MASK_AUTH	0x2
>  #define CRYPTO_OP_MASK_AEAD	0x4
> -#define CRYPTO_IV_OFFSET						\
> -	sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op)
> 
>  struct crypto_op_sym_iv_aad {
>  	struct rte_crypto_op op;
> @@ -1312,21 +1309,17 @@ struct sym_crypto_data {
>  	/** Session pointer. */
>  	struct rte_cryptodev_sym_session *session;
> 
> -	/** Private data size to store cipher iv / aad. */
> -	uint8_t iv_aad_data[0];
> -
>  	/** Direction of crypto, encrypt or decrypt */
>  	uint16_t direction;
> 
> +	/** Private data size to store cipher iv / aad. */
> +	uint8_t iv_aad_data[32];
> +
>  } __attribute__((__packed__));
> 
>  static int
>  sym_crypto_cfg_check(struct rte_table_action_sym_crypto_config *cfg)
>  {
> -	if (cfg->mempool_session_create == NULL ||
> -			cfg->mempool_session_init == NULL)
> -		return -EINVAL;
> -
>  	if (cfg->cryptodev_id >= rte_cryptodev_count())
>  		return -EINVAL;
> 
> @@ -1336,18 +1329,20 @@ sym_crypto_cfg_check(struct
> rte_table_action_sym_crypto_config *cfg)
>  static int
>  get_block_size(const struct rte_crypto_sym_xform *xform, uint8_t cdev_id)
>  {
> -	unsigned int i = 0;
>  	struct rte_cryptodev_info dev_info;
>  	const struct rte_cryptodev_capabilities *cap;
> +	uint32_t i;
> 
>  	rte_cryptodev_info_get(cdev_id, &dev_info);
> -	cap = &dev_info.capabilities[0];
> 
> -	while (cap->op != RTE_CRYPTO_OP_TYPE_UNDEFINED) {
> +	for (i = 0;; i++) {
> +		cap = &dev_info.capabilities[i];
> +		if (!cap)
> +			break;
> +
>  		if (cap->sym.xform_type != xform->type)
>  			continue;
> 
> -
>  		if ((xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) &&
>  				(cap->sym.cipher.algo == xform-
> >cipher.algo))
>  			return cap->sym.cipher.block_size;
> @@ -1356,7 +1351,8 @@ get_block_size(const struct rte_crypto_sym_xform
> *xform, uint8_t cdev_id)
>  				(cap->sym.aead.algo == xform->aead.algo))
>  			return cap->sym.aead.block_size;
> 
> -		cap = &dev_info.capabilities[++i];
> +		if (xform->type ==
> RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED)
> +			break;
>  	}
> 
>  	return -1;
> @@ -1367,11 +1363,10 @@ sym_crypto_apply(struct sym_crypto_data *data,
>  	struct rte_table_action_sym_crypto_config *cfg,
>  	struct rte_table_action_sym_crypto_params *p)
>  {
> -	struct rte_cryptodev_sym_session *sess;
> -	struct rte_crypto_sym_xform *xform = p->xform;
> -	struct rte_crypto_cipher_xform *cipher_xform = NULL;
> -	struct rte_crypto_auth_xform *auth_xform = NULL;
> -	struct rte_crypto_aead_xform *aead_xform = NULL;
> +	const struct rte_crypto_sym_xform *xform = p->xform;
> +	const struct rte_crypto_cipher_xform *cipher_xform = NULL;
> +	const struct rte_crypto_auth_xform *auth_xform = NULL;
> +	const struct rte_crypto_aead_xform *aead_xform = NULL;
>  	int ret;
> 
>  	memset(data, 0, sizeof(*data));
> @@ -1383,6 +1378,9 @@ sym_crypto_apply(struct sym_crypto_data *data,
>  			if (cipher_xform->iv.length >
> 
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX)
>  			return -ENOMEM;
> +			if (cipher_xform->iv.offset !=
> +
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET)
> +				return -EINVAL;
> 
>  			ret = get_block_size(xform, cfg->cryptodev_id);
>  			if (ret < 0)
> @@ -1390,12 +1388,12 @@ sym_crypto_apply(struct sym_crypto_data *data,
>  			data->block_size = (uint16_t)ret;
>  			data->op_mask |= CRYPTO_OP_MASK_CIPHER;
> 
> -			data->cipher_auth.cipher_iv_data_offset = (uint16_t)
> -					p->cipher_auth.cipher_iv.offset;
>  			data->cipher_auth.cipher_iv_len =
>  					cipher_xform->iv.length;
> +			data->cipher_auth.cipher_iv_data_offset = (uint16_t)
> +					p-
> >cipher_auth.cipher_iv_update.offset;
>  			data->cipher_auth.cipher_iv_update_len = (uint16_t)
> -					p->cipher_auth.cipher_iv.length;
> +					p-
> >cipher_auth.cipher_iv_update.length;
> 
>  			rte_memcpy(data->iv_aad_data,
>  					p->cipher_auth.cipher_iv.val,
> @@ -1403,8 +1401,6 @@ sym_crypto_apply(struct sym_crypto_data *data,
> 
>  			data->direction = cipher_xform->op;
> 
> -			cipher_xform->iv.offset = CRYPTO_IV_OFFSET;
> -
>  		} else if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
> {
>  			auth_xform = &xform->auth;
>  			if (auth_xform->iv.length >
> @@ -1412,17 +1408,13 @@ sym_crypto_apply(struct sym_crypto_data *data,
>  				return -ENOMEM;
>  			data->op_mask |= CRYPTO_OP_MASK_AUTH;
> 
> -			data->cipher_auth.auth_iv_data_offset =
> -					(uint16_t)p-
> >cipher_auth.auth_iv.offset;
>  			data->cipher_auth.auth_iv_len = auth_xform-
> >iv.length;
> +			data->cipher_auth.auth_iv_data_offset = (uint16_t)
> +					p-
> >cipher_auth.auth_iv_update.offset;
>  			data->cipher_auth.auth_iv_update_len = (uint16_t)
> -					p->cipher_auth.auth_iv.length;
> +					p-
> >cipher_auth.auth_iv_update.length;
>  			data->digest_len = auth_xform->digest_length;
> 
> -			if (auth_xform->iv.length)
> -				auth_xform->iv.offset = CRYPTO_IV_OFFSET
> +
> -
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX;
> -
>  			data->direction = (auth_xform->op ==
>  					RTE_CRYPTO_AUTH_OP_GENERATE) ?
>  					RTE_CRYPTO_CIPHER_OP_ENCRYPT :
> @@ -1436,26 +1428,28 @@ sym_crypto_apply(struct sym_crypto_data *data,
>  				aead_xform->aad_length >
> 
> 	RTE_TABLE_ACTION_SYM_CRYPTO_AAD_SIZE_MAX))
>  				return -EINVAL;
> +			if (aead_xform->iv.offset !=
> +
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET)
> +				return -EINVAL;
> 
>  			ret = get_block_size(xform, cfg->cryptodev_id);
>  			if (ret < 0)
>  				return -1;
>  			data->block_size = (uint16_t)ret;
>  			data->op_mask |= CRYPTO_OP_MASK_AEAD;
> -			data->digest_len = aead_xform->digest_length;
> 
> -			data->aead.iv_data_offset = (uint16_t)p-
> >aead.iv.offset;
> +			data->digest_len = aead_xform->digest_length;
>  			data->aead.iv_len = aead_xform->iv.length;
> -			data->aead.iv_update_len = (uint16_t)p-
> >aead.iv.length;
> -
> -			data->aead.aad_data_offset = (uint16_t)
> -					p->aead.aad.offset;
>  			data->aead.aad_len = aead_xform->aad_length;
> -			data->aead.aad_update_len =
> -					(uint16_t)p->aead.aad.length;
> 
> -			if (aead_xform->iv.length)
> -				aead_xform->iv.offset = CRYPTO_IV_OFFSET;
> +			data->aead.iv_data_offset = (uint16_t)
> +					p->aead.iv_update.offset;
> +			data->aead.iv_update_len = (uint16_t)
> +					p->aead.iv_update.length;
> +			data->aead.aad_data_offset = (uint16_t)
> +					p->aead.aad_update.offset;
> +			data->aead.aad_update_len = (uint16_t)
> +					p->aead.aad_update.length;
> 
>  			rte_memcpy(data->iv_aad_data,
>  					p->aead.iv.val,
> @@ -1475,22 +1469,25 @@ sym_crypto_apply(struct sym_crypto_data *data,
>  		xform = xform->next;
>  	}
> 
> -	data->data_offset = (uint16_t)p->data_offset;
> -
> -	sess = rte_cryptodev_sym_session_create(cfg-
> >mempool_session_create);
> -	if (!sess) {
> -		memset(data, 0, sizeof(*data));
> -		return -ENOMEM;
> -	}
> +	if (auth_xform && auth_xform->iv.length) {
> +		if (cipher_xform) {
> +			if (auth_xform->iv.offset !=
> +
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET +
> +					cipher_xform->iv.length)
> +				return -EINVAL;
> 
> -	ret = rte_cryptodev_sym_session_init(cfg->cryptodev_id, sess,
> xform,
> -			cfg->mempool_session_init);
> -	if (ret < 0) {
> -		memset(data, 0, sizeof(*data));
> -		return ret;
> +			rte_memcpy(data->iv_aad_data + cipher_xform-
> >iv.length,
> +					p->cipher_auth.auth_iv.val,
> +					p->cipher_auth.auth_iv.length);
> +		} else {
> +			rte_memcpy(data->iv_aad_data,
> +					p->cipher_auth.auth_iv.val,
> +					p->cipher_auth.auth_iv.length);
> +		}
>  	}
> 
> -	data->session = sess;
> +	data->data_offset = (uint16_t)p->data_offset;
> +	data->session = p->session;
> 
>  	return 0;
>  }
> @@ -1503,36 +1500,39 @@ pkt_work_sym_crypto(struct rte_mbuf *mbuf,
> struct sym_crypto_data *data,
>  	struct crypto_op_sym_iv_aad *crypto_op = (struct
> crypto_op_sym_iv_aad *)
>  			RTE_MBUF_METADATA_UINT8_PTR(mbuf, cfg-
> >op_offset);
>  	struct rte_crypto_op *op = &crypto_op->op;
> -	uint16_t rel_ip_offset = ip_offset - mbuf->data_off;
> -	uint16_t payload_len = 0;
> +	struct rte_crypto_sym_op *sym = op->sym;
> +	uint16_t rel_ip_offset = ip_offset - mbuf->data_off - mbuf-
> >priv_size -
> +			RTE_PKTMBUF_HEADROOM;
> +	uint32_t payload_len = mbuf->pkt_len - rel_ip_offset -
> +			data->data_offset;
> 
> -	op->sym->m_src = mbuf;
> -	op->sym->m_dst = NULL;
>  	op->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;
>  	op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
> -	op->phys_addr = rte_pktmbuf_iova_offset(mbuf, cfg->op_offset);
> +	op->phys_addr = mbuf->buf_iova + cfg->op_offset - sizeof(*mbuf);
>  	op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
> -	op->sym->session = data->session;
> +	sym->m_src = mbuf;
> +	sym->m_dst = NULL;
> +	sym->session = data->session;
> 
>  	/** pad the packet */
>  	if (data->direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT) {
> -		payload_len = RTE_ALIGN_CEIL(rte_pktmbuf_pkt_len(mbuf)
> -
> -				(data->data_offset + rel_ip_offset),
> -				data->block_size) -
> rte_pktmbuf_pkt_len(mbuf);
> +		uint32_t append_len = RTE_ALIGN_CEIL(payload_len,
> +				data->block_size) - payload_len;
> 
> -		if (unlikely(rte_pktmbuf_append(mbuf, payload_len +
> +		if (unlikely(rte_pktmbuf_append(mbuf, append_len +
>  				data->digest_len) == NULL))
>  			return 1;
> -	}
> 
> -	payload_len = rte_pktmbuf_pkt_len(mbuf);
> +		payload_len += append_len;
> +	} else
> +		payload_len -= data->digest_len;
> 
>  	if (data->op_mask & CRYPTO_OP_MASK_CIPHER) {
>  		/** prepare cipher op */
>  		uint8_t *iv = crypto_op->iv_aad.cipher_auth.cipher_iv;
> 
> -		op->sym->cipher.data.length = payload_len;
> -		op->sym->cipher.data.offset = data->data_offset +
> rel_ip_offset;
> +		sym->cipher.data.length = payload_len;
> +		sym->cipher.data.offset = rel_ip_offset + data->data_offset;
> 
>  		if (data->cipher_auth.cipher_iv_update_len) {
>  			uint8_t *pkt_iv =
> RTE_MBUF_METADATA_UINT8_PTR(mbuf,
> @@ -1556,12 +1556,12 @@ pkt_work_sym_crypto(struct rte_mbuf *mbuf,
> struct sym_crypto_data *data,
>  	}
> 
>  	if (data->op_mask & CRYPTO_OP_MASK_AUTH) {
> -		op->sym->auth.data.offset = rel_ip_offset;
> -		op->sym->auth.data.length = payload_len;
> -		op->sym->auth.digest.data =
> rte_pktmbuf_mtod_offset(mbuf,
> +		sym->auth.data.offset = rel_ip_offset;
> +		sym->auth.data.length = payload_len + data->data_offset;
> +		sym->auth.digest.data = rte_pktmbuf_mtod_offset(mbuf,
>  				uint8_t *, rte_pktmbuf_pkt_len(mbuf) -
>  				data->digest_len);
> -		op->sym->auth.digest.phys_addr =
> rte_pktmbuf_iova_offset(mbuf,
> +		sym->auth.digest.phys_addr =
> rte_pktmbuf_iova_offset(mbuf,
>  				rte_pktmbuf_pkt_len(mbuf) - data-
> >digest_len);
> 
>  		if (data->cipher_auth.auth_iv_update_len) {
> @@ -1593,17 +1593,19 @@ pkt_work_sym_crypto(struct rte_mbuf *mbuf,
> struct sym_crypto_data *data,
>  		uint8_t *iv = crypto_op->iv_aad.aead_iv_aad.iv;
>  		uint8_t *aad = crypto_op->iv_aad.aead_iv_aad.aad;
> 
> -		op->sym->aead.aad.data = aad;
> -		op->sym->aead.aad.phys_addr = op->phys_addr +
> -				CRYPTO_IV_OFFSET +
> -
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX;
> -		op->sym->aead.digest.data =
> rte_pktmbuf_mtod_offset(mbuf,
> +		sym->aead.aad.data = aad;
> +		sym->aead.aad.phys_addr = rte_pktmbuf_iova_offset(mbuf,
> +				aad - rte_pktmbuf_mtod(mbuf, uint8_t *));
> +		/*sym->aead.aad.phys_addr = op->phys_addr +
> +
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET +
> +
> 	RTE_TABLE_ACTION_SYM_CRYPTO_IV_SIZE_MAX;*/
> +		sym->aead.digest.data = rte_pktmbuf_mtod_offset(mbuf,
>  				uint8_t *, rte_pktmbuf_pkt_len(mbuf) -
>  				data->digest_len);
> -		op->sym->aead.digest.phys_addr =
> rte_pktmbuf_iova_offset(mbuf,
> +		sym->aead.digest.phys_addr =
> rte_pktmbuf_iova_offset(mbuf,
>  				rte_pktmbuf_pkt_len(mbuf) - data-
> >digest_len);
> -		op->sym->aead.data.offset = data->data_offset +
> rel_ip_offset;
> -		op->sym->aead.data.length = payload_len;
> +		sym->aead.data.offset = data->data_offset + rel_ip_offset;
> +		sym->aead.data.length = payload_len;
> 
>  		if (data->aead.iv_update_len) {
>  			uint8_t *pkt_iv =
> RTE_MBUF_METADATA_UINT8_PTR(mbuf,
> @@ -1678,7 +1680,7 @@ struct ap_config {
>  	struct rte_table_action_nat_config nat;
>  	struct rte_table_action_ttl_config ttl;
>  	struct rte_table_action_stats_config stats;
> -	struct rte_table_action_sym_crypto_config crypto;
> +	struct rte_table_action_sym_crypto_config sym_crypto;
>  };
> 
>  static size_t
> @@ -1733,7 +1735,7 @@ action_cfg_get(struct ap_config *ap_config,
>  		return &ap_config->stats;
> 
>  	case RTE_TABLE_ACTION_SYM_CRYPTO:
> -		return &ap_config->crypto;
> +		return &ap_config->sym_crypto;
>  	default:
>  		return NULL;
>  	}
> @@ -1790,6 +1792,9 @@ action_data_size(enum rte_table_action_type
> action,
>  	case RTE_TABLE_ACTION_TIME:
>  		return sizeof(struct time_data);
> 
> +	case RTE_TABLE_ACTION_SYM_CRYPTO:
> +		return (sizeof(struct sym_crypto_data));
> +
>  	default:
>  		return 0;
>  	}
> @@ -2044,7 +2049,7 @@ rte_table_action_apply(struct rte_table_action
> *action,
> 
>  	case RTE_TABLE_ACTION_SYM_CRYPTO:
>  		return sym_crypto_apply(action_data,
> -				&action->cfg.crypto,
> +				&action->cfg.sym_crypto,
>  				action_params);
> 
>  	default:
> @@ -2408,7 +2413,7 @@ pkt_work(struct rte_mbuf *mbuf,
>  		void *data = action_data_get(table_entry, action,
>  				RTE_TABLE_ACTION_SYM_CRYPTO);
> 
> -		drop_mask |= pkt_work_sym_crypto(mbuf, data, &cfg-
> >crypto,
> +		drop_mask |= pkt_work_sym_crypto(mbuf, data, &cfg-
> >sym_crypto,
>  				ip_offset);
>  	}
> 
> @@ -2710,13 +2715,13 @@ pkt4_work(struct rte_mbuf **mbufs,
>  		void *data3 = action_data_get(table_entry3, action,
>  				RTE_TABLE_ACTION_SYM_CRYPTO);
> 
> -		drop_mask0 |= pkt_work_sym_crypto(mbuf0, data0, &cfg-
> >crypto,
> +		drop_mask0 |= pkt_work_sym_crypto(mbuf0, data0, &cfg-
> >sym_crypto,
>  				ip_offset);
> -		drop_mask1 |= pkt_work_sym_crypto(mbuf1, data1, &cfg-
> >crypto,
> +		drop_mask1 |= pkt_work_sym_crypto(mbuf1, data1, &cfg-
> >sym_crypto,
>  				ip_offset);
> -		drop_mask2 |= pkt_work_sym_crypto(mbuf2, data2, &cfg-
> >crypto,
> +		drop_mask2 |= pkt_work_sym_crypto(mbuf2, data2, &cfg-
> >sym_crypto,
>  				ip_offset);
> -		drop_mask3 |= pkt_work_sym_crypto(mbuf3, data3, &cfg-
> >crypto,
> +		drop_mask3 |= pkt_work_sym_crypto(mbuf3, data3, &cfg-
> >sym_crypto,
>  				ip_offset);
>  	}
> 
> diff --git a/lib/librte_pipeline/rte_table_action.h
> b/lib/librte_pipeline/rte_table_action.h
> index 897f42308..cf47ebfc9 100644
> --- a/lib/librte_pipeline/rte_table_action.h
> +++ b/lib/librte_pipeline/rte_table_action.h
> @@ -910,12 +910,6 @@ struct rte_table_action_sym_crypto_config {
>  	/** Target Cryptodev ID. */
>  	uint8_t cryptodev_id;
> 
> -	/** Crypto Session mempool. */
> -	struct rte_mempool *mempool_session_create;
> -
> -	/** Crypto session init mempool, used for init cryptodev session. */
> -	struct rte_mempool *mempool_session_init;
> -
>  	/** The offset to fetch rte_crypto_op. */
>  	uint32_t op_offset;
>  };
> @@ -928,6 +922,11 @@ struct rte_table_action_sym_crypto_config {
>  #define RTE_TABLE_ACTION_SYM_CRYPTO_AAD_SIZE_MAX	(16)
>  #endif
> 
> +#ifndef RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET
> +#define RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET
> 		\
> +	sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op)
> +#endif
> +
>  /** Common action structure to store the data's value, length, and offset */
>  struct rte_table_action_vlo {
>  	uint8_t *val;
> @@ -939,7 +938,10 @@ struct rte_table_action_vlo {
>  struct rte_table_action_sym_crypto_params {
> 
>  	/** Xform pointer contains all relevant information */
> -	struct rte_crypto_sym_xform *xform;
> +	const struct rte_crypto_sym_xform *xform;
> +
> +	/** Application created cryptodev symmetric session */
> +	struct rte_cryptodev_sym_session *session;
> 
>  	/**
>  	 * Offset from start of IP packet to the first packet byte to be
> @@ -952,9 +954,15 @@ struct rte_table_action_sym_crypto_params {
>  			/** Cipher iv data, offset from start of ip header */
>  			struct rte_table_action_vlo cipher_iv;
> 
> +			/** Cipher iv data, offset from start of ip header */
> +			struct rte_table_action_vlo cipher_iv_update;
> +
>  			/** Auth iv data, offset from start of ip header */
>  			struct rte_table_action_vlo auth_iv;
> 
> +			/** Auth iv data, offset from start of ip header */
> +			struct rte_table_action_vlo auth_iv_update;
> +
>  		} cipher_auth;
> 
>  		struct {
> @@ -964,6 +972,12 @@ struct rte_table_action_sym_crypto_params {
>  			/** AEAD iv data, offset from start of ip header */
>  			struct rte_table_action_vlo iv;
> 
> +			/** AEAD AAD data, offset from start of ip header */
> +			struct rte_table_action_vlo aad_update;
> +
> +			/** AEAD iv data, offset from start of ip header */
> +			struct rte_table_action_vlo iv_update;
> +
>  		} aead;
>  	};
>  };
> --
> 2.13.6



More information about the dev mailing list