[dpdk-dev] [PATCH] crypto action

Zhang, Roy Fan roy.fan.zhang at intel.com
Mon Sep 10 16:33:22 CEST 2018


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