DPDK patches and discussions
 help / color / mirror / Atom feed
From: Akhil Goyal <gakhil@marvell.com>
To: Anoob Joseph <anoobj@marvell.com>,
	Thomas Monjalon <thomas@monjalon.net>,
	 Jerin Jacob Kollanukkaran <jerinj@marvell.com>,
	Konstantin Ananyev <konstantin.v.ananyev@yandex.ru>,
	Bernard Iremonger <bernard.iremonger@intel.com>
Cc: "Hemant Agrawal" <hemant.agrawal@nxp.com>,
	"Mattias Rönnblom" <mattias.ronnblom@ericsson.com>,
	"Kiran Kumar Kokkilagadda" <kirankumark@marvell.com>,
	"Volodymyr Fialko" <vfialko@marvell.com>,
	"dev@dpdk.org" <dev@dpdk.org>,
	"Olivier Matz" <olivier.matz@6wind.com>
Subject: RE: [PATCH 2/5] lib: add pdcp protocol
Date: Wed, 18 Jan 2023 16:26:40 +0000	[thread overview]
Message-ID: <CO6PR18MB4484FD2705D3C473A56E8985D8C79@CO6PR18MB4484.namprd18.prod.outlook.com> (raw)
In-Reply-To: <20221222092522.1628-3-anoobj@marvell.com>

Hi Anoob,

Please see inline comments.
> Subject: [PATCH 2/5] lib: add pdcp protocol
> 
> Add Packet Data Convergence Protocol (PDCP) processing library.
> 
> The library is similar to lib_ipsec which provides IPsec processing
> capabilities in DPDK.
> 
> PDCP would involve roughly the following options,
> 1. Transfer of user plane data
> 2. Transfer of control plane data
> 3. Header compression
> 4. Uplink data compression
> 5. Ciphering and integrity protection
> 
> PDCP library provides following control path APIs that is used to
> configure various PDCP entities,
> 1. rte_pdcp_entity_establish()
> 2. rte_pdcp_entity_suspend()
> 3. rte_pdcp_entity_release()
> 
> PDCP process is split into 2 parts. One before crypto processing
> (rte_pdcp_pkt_pre_process()) and one after crypto processing
> (rte_pdcp_pkt_post_process()). Since cryptodev dequeue can return crypto
> operations belonging to multiple entities, rte_pdcp_pkt_crypto_group()
> is added to help grouping crypto operations belonging to same entity.
> 
> Signed-off-by: Anoob Joseph <anoobj@marvell.com>
> Signed-off-by: Kiran Kumar K <kirankumark@marvell.com>
> Signed-off-by: Volodymyr Fialko <vfialko@marvell.com>
> ---
>  doc/api/doxy-api-index.md |    3 +-
>  doc/api/doxy-api.conf.in  |    1 +
>  lib/meson.build           |    1 +
>  lib/pdcp/meson.build      |    8 +
>  lib/pdcp/pdcp_crypto.c    |  240 ++++++++
>  lib/pdcp/pdcp_crypto.h    |   20 +
>  lib/pdcp/pdcp_entity.h    |  218 +++++++
>  lib/pdcp/pdcp_process.c   | 1195 +++++++++++++++++++++++++++++++++++++
>  lib/pdcp/pdcp_process.h   |   13 +
>  lib/pdcp/rte_pdcp.c       |  136 +++++
>  lib/pdcp/rte_pdcp.h       |  263 ++++++++
>  lib/pdcp/rte_pdcp_group.h |  133 +++++
>  lib/pdcp/version.map      |   13 +
>  13 files changed, 2243 insertions(+), 1 deletion(-)
>  create mode 100644 lib/pdcp/meson.build
>  create mode 100644 lib/pdcp/pdcp_crypto.c
>  create mode 100644 lib/pdcp/pdcp_crypto.h
>  create mode 100644 lib/pdcp/pdcp_entity.h
>  create mode 100644 lib/pdcp/pdcp_process.c
>  create mode 100644 lib/pdcp/pdcp_process.h
>  create mode 100644 lib/pdcp/rte_pdcp.c
>  create mode 100644 lib/pdcp/rte_pdcp.h
>  create mode 100644 lib/pdcp/rte_pdcp_group.h
>  create mode 100644 lib/pdcp/version.map
> 
> diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md
> index ae4b107240..6014bee079 100644
> --- a/doc/api/doxy-api-index.md
> +++ b/doc/api/doxy-api-index.md
> @@ -126,7 +126,8 @@ The public API headers are grouped by topics:
>    [eCPRI](@ref rte_ecpri.h),
>    [L2TPv2](@ref rte_l2tpv2.h),
>    [PPP](@ref rte_ppp.h),
> -  [PDCP hdr](@ref rte_pdcp_hdr.h)
> +  [PDCP hdr](@ref rte_pdcp_hdr.h),
> +  [PDCP](@ref rte_pdcp.h),
> 
>  - **QoS**:
>    [metering](@ref rte_meter.h),
> diff --git a/doc/api/doxy-api.conf.in b/doc/api/doxy-api.conf.in
> index f0886c3bd1..01314b087e 100644
> --- a/doc/api/doxy-api.conf.in
> +++ b/doc/api/doxy-api.conf.in
> @@ -61,6 +61,7 @@ INPUT                   = @TOPDIR@/doc/api/doxy-api-
> index.md \
>                            @TOPDIR@/lib/net \
>                            @TOPDIR@/lib/pcapng \
>                            @TOPDIR@/lib/pci \
> +                          @TOPDIR@/lib/pdcp \
>                            @TOPDIR@/lib/pdump \
>                            @TOPDIR@/lib/pipeline \
>                            @TOPDIR@/lib/port \
> diff --git a/lib/meson.build b/lib/meson.build
> index fd55925340..a827006d29 100644
> --- a/lib/meson.build
> +++ b/lib/meson.build
> @@ -63,6 +63,7 @@ libraries = [
>          'flow_classify', # flow_classify lib depends on pkt framework table lib
>          'graph',
>          'node',
> +        'pdcp', # pdcp lib depends on crypto and security
>  ]
> 
>  optional_libs = [
> diff --git a/lib/pdcp/meson.build b/lib/pdcp/meson.build
> new file mode 100644
> index 0000000000..a7f5a408cf
> --- /dev/null
> +++ b/lib/pdcp/meson.build
> @@ -0,0 +1,8 @@
> +# SPDX-License-Identifier: BSD-3-Clause
> +# Copyright(C) 2022 Marvell.
> +#
Extra # here.

Do we support compilation on Windows as well?
Check missing here.

> +
> +sources = files('pdcp_crypto.c', 'pdcp_process.c', 'rte_pdcp.c')
> +headers = files('rte_pdcp.h')

Do we need to add the indirect header as well for lib/pdcp/rte_pdcp_group.h?

> +
> +deps += ['security']

Crypto not needed as dependency?

> diff --git a/lib/pdcp/pdcp_crypto.c b/lib/pdcp/pdcp_crypto.c
> new file mode 100644
> index 0000000000..7ffb8a07a7
> --- /dev/null
> +++ b/lib/pdcp/pdcp_crypto.c
> @@ -0,0 +1,240 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#include <rte_crypto.h>
> +#include <rte_crypto_sym.h>
> +#include <rte_cryptodev.h>
> +#include <rte_pdcp.h>
> +
> +#include "pdcp_crypto.h"
> +#include "pdcp_entity.h"
> +
> +static int
> +pdcp_crypto_caps_cipher_verify(uint8_t dev_id, const struct
> rte_crypto_sym_xform *c_xfrm)
> +{
> +	const struct rte_cryptodev_symmetric_capability *cap;
> +	struct rte_cryptodev_sym_capability_idx cap_idx;
> +	int ret;
> +
> +	cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
> +	cap_idx.algo.cipher = c_xfrm->cipher.algo;
> +
> +	cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
> +	if (cap == NULL)
> +		return -1;
> +
> +	ret = rte_cryptodev_sym_capability_check_cipher(cap, c_xfrm-
> >cipher.key.length,
> +							c_xfrm-
> >cipher.iv.length);
> +
> +	return ret;
> +}
> +
> +static int
> +pdcp_crypto_caps_auth_verify(uint8_t dev_id, const struct
> rte_crypto_sym_xform *a_xfrm)
> +{
> +	const struct rte_cryptodev_symmetric_capability *cap;
> +	struct rte_cryptodev_sym_capability_idx cap_idx;
> +	int ret;
> +
> +	cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH;
> +	cap_idx.algo.auth = a_xfrm->auth.algo;
> +
> +	cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx);
> +	if (cap == NULL)
> +		return -1;
> +
> +	ret = rte_cryptodev_sym_capability_check_auth(cap, a_xfrm-
> >auth.key.length,
> +						      a_xfrm-
> >auth.digest_length,
> +						      a_xfrm->auth.iv.length);
> +
> +	return ret;
> +}
> +
> +static int
> +pdcp_crypto_xfrm_validate(const struct rte_pdcp_entity_conf *conf,
> +				 const struct rte_crypto_sym_xform *c_xfrm,
> +				 const struct rte_crypto_sym_xform *a_xfrm,
> +				 bool is_auth_then_cipher)
> +{
> +	uint16_t ciph_iv_len, auth_digest_len, auth_iv_len;
> +	int ret;
> +
> +	/*
> +	 * Uplink means PDCP entity is configured for transmit. Downlink means
> PDCP entity is
> +	 * configured for receive. When integrity protection is enabled, PDCP
> always performs
> +	 * digest-encrypted or auth-gen-encrypt for uplink (and decrypt-auth-
> verify for downlink).
> +	 * So for uplink, crypto chain would be auth-cipher while for downlink it
> would be
> +	 * cipher-auth.
> +	 *
> +	 * When integrity protection is not required, xform would be cipher only.
> +	 */
> +
> +	if (c_xfrm == NULL)
> +		return -EINVAL;
> +
> +	if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK) {
> +
> +		/* With UPLINK, if auth is enabled, it should be before cipher */
> +		if (a_xfrm != NULL && !is_auth_then_cipher)
> +			return -EINVAL;
> +
> +		/* With UPLINK, cipher operation must be encrypt */
> +		if (c_xfrm->cipher.op != RTE_CRYPTO_CIPHER_OP_ENCRYPT)
> +			return -EINVAL;
> +
> +		/* With UPLINK, auth operation (if present) must be generate */
> +		if (a_xfrm != NULL && a_xfrm->auth.op !=
> RTE_CRYPTO_AUTH_OP_GENERATE)
> +			return -EINVAL;
> +
> +	} else if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
> {
> +
> +		/* With DOWNLINK, if auth is enabled, it should be after cipher
> */
> +		if (a_xfrm != NULL && is_auth_then_cipher)
> +			return -EINVAL;
> +
> +		/* With DOWNLINK, cipher operation must be decrypt */
> +		if (c_xfrm->cipher.op != RTE_CRYPTO_CIPHER_OP_DECRYPT)
> +			return -EINVAL;
> +
> +		/* With DOWNLINK, auth operation (if present) must be verify
> */
> +		if (a_xfrm != NULL && a_xfrm->auth.op !=
> RTE_CRYPTO_AUTH_OP_VERIFY)
> +			return -EINVAL;
> +
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	if ((c_xfrm->cipher.algo != RTE_CRYPTO_CIPHER_NULL) &&
> +	    (c_xfrm->cipher.algo != RTE_CRYPTO_CIPHER_AES_CTR) &&
> +	    (c_xfrm->cipher.algo != RTE_CRYPTO_CIPHER_ZUC_EEA3) &&
> +	    (c_xfrm->cipher.algo != RTE_CRYPTO_CIPHER_SNOW3G_UEA2))
> +		return -EINVAL;
> +
> +	if (c_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_NULL)
> +		ciph_iv_len = 0;
> +	else
> +		ciph_iv_len = PDCP_IV_LENGTH;
> +
> +	if (ciph_iv_len != c_xfrm->cipher.iv.length)
> +		return -EINVAL;
> +
> +	if (a_xfrm != NULL) {
> +		if ((a_xfrm->auth.algo != RTE_CRYPTO_AUTH_NULL) &&
> +		    (a_xfrm->auth.algo != RTE_CRYPTO_AUTH_AES_CMAC) &&
> +		    (a_xfrm->auth.algo != RTE_CRYPTO_AUTH_ZUC_EIA3) &&
> +		    (a_xfrm->auth.algo != RTE_CRYPTO_AUTH_SNOW3G_UIA2))
> +			return -EINVAL;
> +
> +		if (a_xfrm->auth.algo == RTE_CRYPTO_AUTH_NULL)
> +			auth_digest_len = 0;
> +		else
> +			auth_digest_len = 4;

If we have a macro for IV length, why not for digest also?
Moreover, for NULL integrity, digest length is also 4 with all 0s.
Refer Annex D.1 in https://www.etsi.org/deliver/etsi_ts/133500_133599/133501/15.04.00_60/ts_133501v150400p.pdf

Digest len would be 0 only in case of a_xfrm == NULL

> +
> +		if (auth_digest_len != a_xfrm->auth.digest_length)
> +			return -EINVAL;
> +
> +		if ((a_xfrm->auth.algo == RTE_CRYPTO_AUTH_ZUC_EIA3) ||
> +		    (a_xfrm->auth.algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2))
> +			auth_iv_len = PDCP_IV_LENGTH;
> +		else
> +			auth_iv_len = 0;
> +
> +		if (a_xfrm->auth.iv.length != auth_iv_len)
> +			return -EINVAL;
> +	}
> +
> +	if (!rte_cryptodev_is_valid_dev(conf->dev_id))
> +		return -EINVAL;
> +
> +	ret = pdcp_crypto_caps_cipher_verify(conf->dev_id, c_xfrm);
> +	if (ret)
> +		return -ENOTSUP;
> +
> +	if (a_xfrm != NULL) {
> +		ret = pdcp_crypto_caps_auth_verify(conf->dev_id, a_xfrm);
> +		if (ret)
> +			return -ENOTSUP;
> +	}
> +
> +	return 0;
> +}
> +
> +int
> +pdcp_crypto_sess_create(struct rte_pdcp_entity *entity, const struct
> rte_pdcp_entity_conf *conf)
> +{
> +	struct rte_crypto_sym_xform *c_xfrm, *a_xfrm;
> +	struct entity_priv *en_priv;
> +	bool is_auth_then_cipher;
> +	int ret;
> +
> +	if (entity == NULL || conf == NULL || conf->crypto_xfrm == NULL)
> +		return -EINVAL;
> +
> +	en_priv = entity_priv_get(entity);
> +
> +	en_priv->dev_id = conf->dev_id;
> +
> +	if (conf->crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
> +		c_xfrm = conf->crypto_xfrm;
> +		a_xfrm = conf->crypto_xfrm->next;
> +		is_auth_then_cipher = false;
> +	} else if (conf->crypto_xfrm->type ==
> RTE_CRYPTO_SYM_XFORM_AUTH) {
> +		a_xfrm = conf->crypto_xfrm;
> +		c_xfrm = conf->crypto_xfrm->next;
> +		is_auth_then_cipher = true;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	ret = pdcp_crypto_xfrm_validate(conf, c_xfrm, a_xfrm,
> is_auth_then_cipher);
> +	if (ret)
> +		return ret;
> +
> +	if (c_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_NULL)
> +		c_xfrm->cipher.iv.offset = 0;
> +	else
> +		c_xfrm->cipher.iv.offset = PDCP_IV_OFFSET;
> +
> +	if (a_xfrm != NULL) {
> +		if (a_xfrm->auth.algo == RTE_CRYPTO_AUTH_NULL)
> +			a_xfrm->auth.iv.offset = 0;
> +		else
> +			if (c_xfrm->cipher.iv.offset)
> +				a_xfrm->auth.iv.offset = PDCP_IV_OFFSET +
> PDCP_IV_LENGTH;
> +			else
> +				a_xfrm->auth.iv.offset = PDCP_IV_OFFSET;
> +	}
> +
> +	if (conf->sess_mpool == NULL)
> +		return -EINVAL;
> +
> +	en_priv->crypto_sess = rte_cryptodev_sym_session_create(conf-
> >dev_id, conf->crypto_xfrm,
> +								conf-
> >sess_mpool);
> +	if (en_priv->crypto_sess == NULL) {
> +		/* API returns positive values as error codes */
> +		return -rte_errno;
> +	}
> +
> +	rte_cryptodev_sym_session_opaque_data_set(en_priv->crypto_sess,
> (uint64_t)entity);
> +
> +	return 0;
> +}
> +
> +int
> +pdcp_crypto_sess_destroy(struct rte_pdcp_entity *entity)
> +{
> +	struct entity_priv *en_priv;
> +
> +	if (entity == NULL)
> +		return -EINVAL;
> +
> +	en_priv = entity_priv_get(entity);
> +
> +	if (en_priv->crypto_sess != NULL) {
> +		rte_cryptodev_sym_session_free(en_priv->dev_id, en_priv-
> >crypto_sess);
> +		en_priv->crypto_sess = NULL;
> +	}
> +
> +	return 0;
> +}
> diff --git a/lib/pdcp/pdcp_crypto.h b/lib/pdcp/pdcp_crypto.h
> new file mode 100644
> index 0000000000..dc625b35d0
> --- /dev/null
> +++ b/lib/pdcp/pdcp_crypto.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#ifndef _PDCP_CRYPTO_H_
> +#define _PDCP_CRYPTO_H_
> +
> +#include <rte_crypto.h>
> +#include <rte_crypto_sym.h>
> +#include <rte_pdcp.h>
> +
> +#define PDCP_IV_OFFSET (sizeof(struct rte_crypto_op) + sizeof(struct
> rte_crypto_sym_op))
> +#define PDCP_IV_LENGTH 16
> +
> +int pdcp_crypto_sess_create(struct rte_pdcp_entity *entity,
> +			    const struct rte_pdcp_entity_conf *conf);
> +
> +int pdcp_crypto_sess_destroy(struct rte_pdcp_entity *entity);
> +
> +#endif /* _PDCP_CRYPTO_H_ */
> diff --git a/lib/pdcp/pdcp_entity.h b/lib/pdcp/pdcp_entity.h
> new file mode 100644
> index 0000000000..e312fd4a8c
> --- /dev/null
> +++ b/lib/pdcp/pdcp_entity.h
> @@ -0,0 +1,218 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#ifndef _PDCP_ENTITY_H_
> +#define _PDCP_ENTITY_H_
> +
> +#include <rte_common.h>
> +#include <rte_crypto_sym.h>
> +#include <rte_mempool.h>
> +#include <rte_pdcp.h>
> +#include <rte_security.h>
> +
> +struct entity_priv;
> +
> +#define PDCP_PDU_HDR_SIZE_SN_12 (RTE_ALIGN_MUL_CEIL(12, 8) / 8)
> +#define PDCP_PDU_HDR_SIZE_SN_18 (RTE_ALIGN_MUL_CEIL(18, 8) / 8)
> +
> +#define PDCP_GET_SN_12_FROM_COUNT(c) ((c) & 0xfff)
> +#define PDCP_GET_SN_18_FROM_COUNT(c) ((c) & 0x3ffff)
> +
> +#define PDCP_GET_HFN_SN_12_FROM_COUNT(c) (((c) >> 12) & 0xfffff)
> +#define PDCP_GET_HFN_SN_18_FROM_COUNT(c) (((c) >> 18) & 0x3fff)
> +
> +#define PDCP_SET_COUNT_FROM_HFN_SN_12(h, s) ((((h) & 0xfffff) << 12) | ((s)
> & 0xfff))
> +#define PDCP_SET_COUNT_FROM_HFN_SN_18(h, s) ((((h) & 0x3fff) << 18) | ((s)
> & 0x3ffff))
> +
> +#define PDCP_SN_12_WINDOW_SZ 0x800
> +#define PDCP_SN_18_WINDOW_SZ 0x20000
> +
> +#define PDCP_SN_12_HFN_MAX ((1 << (32 - 12)) - 1)
> +#define PDCP_SN_12_HFN_MIN 0
> +#define PDCP_SN_18_HFN_MAX ((1 << (32 - 18)) - 1)
> +#define PDCP_SN_18_HFN_MIN 0
> +

Can we have common defines for SN-12 and SN-18 and take SN as parameter?
We can have something like this.

#define PDCP_PDU_HDR_SIZE(sn_size) (RTE_ALIGN_MUL_CEIL((sn_size), 8) / 8)
#define PDCP_GET_SN_FROM_COUNT(c, sn_size) ((c) & ((1<<sn_size)-1))
#define PDCP_GET_HFN_FROM_COUNT(c, sn_size) (((c) >> sn_size) & ((1 << (32 - sn_size)) - 1))
#define PDCP_SET_COUNT_FROM_HFN_SN(h, s, sn_size) ((((h) & ((1 << (32 - sn_size)) - 1)) << sn_size) | ((s) & ((1<<sn_size)-1)))
#define PDCP_HFN_MAX(sn_size) ((1 << (32 - (sn_size))) - 1)
#define PDCP_HFN_MIN 0

> +/* IV generation function based on the entity configuration */
> +typedef void (*iv_gen_t)(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv,
> +			 uint32_t count);
> +
> +enum pdcp_pdu_type {
> +	PDCP_PDU_TYPE_CTRL = 0,
> +	PDCP_PDU_TYPE_DATA = 1,
> +};
> +
> +enum pdcp_up_ctrl_pdu_type {
> +	PDCP_UP_CTRL_PDU_TYPE_STATUS_REPORT,
> +	PDCP_UP_CTRL_PDU_TYPE_ROHC_FEEDBACK,
> +	PDCP_UP_CTRL_PDU_TYPE_EHC_FEEDBACK,
> +	PDCP_UP_CRTL_PDU_TYPE_UDC_FEEDBACK
> +};
> +
> +struct entity_state {
> +	uint32_t rx_next;
> +	uint32_t tx_next;
> +	uint32_t rx_deliv;
> +	uint32_t rx_reord;
> +};
> +
> +union auth_iv_partial {
> +	/* For AES-CMAC, there is no IV, but message gets prepended */
> +	struct {
> +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
> +		uint64_t count : 32;
> +		uint64_t zero_38_39 : 2;
> +		uint64_t direction : 1;
> +		uint64_t bearer : 5;
> +		uint64_t zero_40_63 : 24;
> +#else
> +		uint64_t count : 32;
> +		uint64_t bearer : 5;
> +		uint64_t direction : 1;
> +		uint64_t zero_38_39 : 2;
> +		uint64_t zero_40_63 : 24;
> +#endif
> +	} aes_cmac;
> +	struct {
> +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
> +		uint64_t count : 32;
> +		uint64_t zero_37_39 : 3;
> +		uint64_t bearer : 5;
> +		uint64_t zero_40_63 : 24;
> +
> +		uint64_t rsvd_65_71 : 7;
> +		uint64_t direction_64 : 1;
> +		uint64_t rsvd_72_111 : 40;
> +		uint64_t rsvd_113_119 : 7;
> +		uint64_t direction_112 : 1;
> +		uint64_t rsvd_120_127 : 8;
> +#else
> +		uint64_t count : 32;
> +		uint64_t bearer : 5;
> +		uint64_t zero_37_39 : 3;
> +		uint64_t zero_40_63 : 24;
> +
> +		uint64_t direction_64 : 1;
> +		uint64_t rsvd_65_71 : 7;
> +		uint64_t rsvd_72_111 : 40;
> +		uint64_t direction_112 : 1;
> +		uint64_t rsvd_113_119 : 7;
> +		uint64_t rsvd_120_127 : 8;
> +#endif
> +	} zs;
> +	uint64_t u64[2];
> +};
> +
> +union cipher_iv_partial {
> +	struct {
> +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
> +		uint64_t count : 32;
> +		uint64_t zero_38_39 : 2;
> +		uint64_t direction : 1;
> +		uint64_t bearer : 5;
> +		uint64_t zero_40_63 : 24;
> +
> +		uint64_t zero_64_127;
> +#else
> +		uint64_t count : 32;
> +		uint64_t bearer : 5;
> +		uint64_t direction : 1;
> +		uint64_t zero_38_39 : 2;
> +		uint64_t zero_40_63 : 24;
> +
> +		uint64_t zero_64_127;

Can we take zero_64_127 out of #if-else

> +#endif
> +	} aes_ctr;
> +	struct {
> +#if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
> +		uint64_t count : 32;
> +		uint64_t zero_38_39 : 2;
> +		uint64_t direction : 1;
> +		uint64_t bearer : 5;
> +		uint64_t zero_40_63 : 24;
> +
> +		uint64_t rsvd_64_127;
> +#else
> +		uint64_t count : 32;
> +		uint64_t bearer : 5;
> +		uint64_t direction : 1;
> +		uint64_t zero_38_39 : 2;
> +		uint64_t zero_40_63 : 24;
> +
> +		uint64_t rsvd_64_127;
> +#endif

rsvd_64_127 can also be out of #if-else

> +	} zs;
> +	uint64_t u64[2];
> +};
> +
> +/*
> + * Layout of PDCP entity: [rte_pdcp_entity] [entity_priv] [entity_dl/ul]

If the layout is fixed, can we have 0 length array in rte_pdcp_entity for entity_priv and in entity_priv for entity_dl/ul.
I see that entity_dl/ul are not completely defined. You can define them later when they are supported.

> + */
> +

Extra line

> +struct entity_priv {
> +	/** Crypto sym session. */
> +	struct rte_cryptodev_sym_session *crypto_sess;
> +	/** Entity specific IV generation function. */
> +	iv_gen_t iv_gen;
> +	/** Pre-prepared auth IV. */
> +	union auth_iv_partial auth_iv_part;
> +	/** Pre-prepared cipher IV. */
> +	union cipher_iv_partial cipher_iv_part;
> +	/** Entity state variables. */
> +	struct entity_state state;
> +	/** Flags. */
> +	struct {
> +		/** PDCP PDU has 4 byte MAC-I. */
> +		uint64_t is_authenticated : 1;
> +		/** Cipher offset & length in bits. */
> +		uint64_t is_ciph_in_bits : 1;
> +		/** Auth offset & length in bits. */
> +		uint64_t is_auth_in_bits : 1;
> +		/** Is UL/transmitting PDCP entity */
> +		uint64_t is_ul_entity : 1;
> +	} flags;
> +	/** Crypto op pool. */
> +	struct rte_mempool *cop_pool;
> +	/** PDCP header size. */
> +	uint8_t hdr_sz;
> +	/** PDCP AAD size. For AES-CMAC, additional message is prepended for
> the operation. */
> +	uint8_t aad_sz;
> +	/** Device ID of the device to be used for offload. */
> +	uint8_t dev_id;
> +};
> +
> +struct entity_priv_dl_part {
> +	/* TODO - when in-order-delivery is supported, post PDCP packets
> would need to cached. */
> +	uint8_t dummy;
> +};
> +
> +struct entity_priv_ul_part {
> +	/*
> +	 * TODO - when re-establish is supported, both plain & post PDCP
> packets would need to be
> +	 * cached.
> +	 */
> +	uint8_t dummy;
> +};
> +
> +static inline struct entity_priv *
> +entity_priv_get(const struct rte_pdcp_entity *entity) {
> +	return RTE_PTR_ADD(entity, sizeof(struct rte_pdcp_entity));
> +}
> +
> +static inline struct entity_priv_dl_part *
> +entity_dl_part_get(const struct rte_pdcp_entity *entity) {
> +	return RTE_PTR_ADD(entity, sizeof(struct rte_pdcp_entity) +
> sizeof(struct entity_priv));
> +}
> +
> +static inline struct entity_priv_ul_part *
> +entity_ul_part_get(const struct rte_pdcp_entity *entity) {
> +	return RTE_PTR_ADD(entity, sizeof(struct rte_pdcp_entity) +
> sizeof(struct entity_priv));
> +}

Above inline functions may not be needed also if we have 0 len arrays.

> +
> +static inline int
> +pdcp_hdr_size_get(enum rte_security_pdcp_sn_size sn_size)
> +{
> +	return RTE_ALIGN_MUL_CEIL(sn_size, 8) / 8;
> +}

PDCP_PDU_HDR_SIZE is same as this inline function.
Can we get away with this one?

> +
> +#endif /* _PDCP_ENTITY_H_ */
> diff --git a/lib/pdcp/pdcp_process.c b/lib/pdcp/pdcp_process.c
> new file mode 100644
> index 0000000000..282cf38ec4
> --- /dev/null
> +++ b/lib/pdcp/pdcp_process.c
> @@ -0,0 +1,1195 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#include <rte_crypto.h>
> +#include <rte_crypto_sym.h>
> +#include <rte_cryptodev.h>
> +#include <rte_memcpy.h>
> +#include <rte_pdcp.h>
> +#include <rte_pdcp_hdr.h>
> +
> +#include "pdcp_crypto.h"
> +#include "pdcp_entity.h"
> +#include "pdcp_process.h"
> +
> +#define PDCP_MAC_I_LEN 4

Can you define it at same place where PDCP_IV_LENGTH is defined and use this in xform validate.

> +
> +/* Enum of supported algorithms for ciphering */
> +enum pdcp_cipher_algo {
> +	PDCP_CIPHER_ALGO_NULL,
> +	PDCP_CIPHER_ALGO_AES,
> +	PDCP_CIPHER_ALGO_ZUC,
> +	PDCP_CIPHER_ALGO_SNOW3G,
> +	PDCP_CIPHER_ALGO_MAX
> +};
> +
> +/* Enum of supported algorithms for integrity */
> +enum pdcp_auth_algo {
> +	PDCP_AUTH_ALGO_NULL,
> +	PDCP_AUTH_ALGO_AES,
> +	PDCP_AUTH_ALGO_ZUC,
> +	PDCP_AUTH_ALGO_SNOW3G,
> +	PDCP_AUTH_ALGO_MAX
> +};
> +
> +/* IV generation functions based on type of operation (cipher - auth) */
> +
> +static void
> +pdcp_iv_gen_null_null(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv, uint32_t count)
> +{
> +	/* No IV required for NULL cipher + NULL auth */
> +	RTE_SET_USED(cop);
> +	RTE_SET_USED(en_priv);
> +	RTE_SET_USED(count);
> +}
> +
> +static void
> +pdcp_iv_gen_null_aes_cmac(struct rte_crypto_op *cop, const struct
> entity_priv *en_priv,
> +			  uint32_t count)
> +{
> +	struct rte_crypto_sym_op *op = cop->sym;
> +	struct rte_mbuf *mb = op->m_src;
> +	uint8_t *m_ptr;
> +	uint64_t m;
> +
> +	/* AES-CMAC requires message to be prepended with info on count etc
> */
> +
> +	/* Prepend by 8 bytes to add custom message */
> +	m_ptr = (uint8_t *)rte_pktmbuf_prepend(mb, 8);
> +
> +	m = en_priv->auth_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +
> +	rte_memcpy(m_ptr, &m, 8);
> +}
> +
> +static void
> +pdcp_iv_gen_null_zs(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv, uint32_t count)
> +{
> +	uint64_t iv_u64[2];
> +	uint8_t *iv;
> +
> +	iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
> +
> +	iv_u64[0] = en_priv->auth_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(iv, &iv_u64[0], 8);
> +
> +	iv_u64[1] = iv_u64[0] ^ en_priv->auth_iv_part.u64[1];
> +	rte_memcpy(iv + 8, &iv_u64[1], 8);
> +}
> +
> +static void
> +pdcp_iv_gen_aes_ctr_null(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv,
> +			 uint32_t count)
> +{
> +	uint64_t iv_u64[2];
> +	uint8_t *iv;
> +
> +	iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
> +
> +	iv_u64[0] = en_priv->cipher_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	iv_u64[1] = 0;
> +	rte_memcpy(iv, iv_u64, 16);
> +}
> +
> +static void
> +pdcp_iv_gen_zs_null(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv, uint32_t count)
> +{
> +	uint64_t iv_u64;
> +	uint8_t *iv;
> +
> +	iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
> +
> +	iv_u64 = en_priv->cipher_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(iv, &iv_u64, 8);
> +	rte_memcpy(iv + 8, &iv_u64, 8);
> +}
> +
> +static void
> +pdcp_iv_gen_zs_zs(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv, uint32_t count)
> +{
> +	uint64_t iv_u64[2];
> +	uint8_t *iv;
> +
> +	iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
> +
> +	/* Generating cipher IV */
> +	iv_u64[0] = en_priv->cipher_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(iv, &iv_u64[0], 8);
> +	rte_memcpy(iv + 8, &iv_u64[0], 8);
> +
> +	iv += PDCP_IV_LENGTH;
> +
> +	/* Generating auth IV */
> +	iv_u64[0] = en_priv->auth_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(iv, &iv_u64[0], 8);
> +
> +	iv_u64[1] = iv_u64[0] ^ en_priv->auth_iv_part.u64[1];
> +	rte_memcpy(iv + 8, &iv_u64[1], 8);
> +}
> +
> +static void
> +pdcp_iv_gen_zs_aes_cmac(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv,
> +			uint32_t count)
> +{
> +	struct rte_crypto_sym_op *op = cop->sym;
> +	struct rte_mbuf *mb = op->m_src;
> +	uint8_t *m_ptr, *iv;
> +	uint64_t iv_u64[2];
> +	uint64_t m;
> +
> +	iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
> +	iv_u64[0] = en_priv->cipher_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(iv, &iv_u64[0], 8);
> +	rte_memcpy(iv + 8, &iv_u64[0], 8);
> +
> +	m_ptr = (uint8_t *)rte_pktmbuf_prepend(mb, 8);
> +	m = en_priv->auth_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(m_ptr, &m, 8);
> +}
> +
> +static void
> +pdcp_iv_gen_aes_ctr_aes_cmac(struct rte_crypto_op *cop, const struct
> entity_priv *en_priv,
> +			    uint32_t count)
> +{
> +	struct rte_crypto_sym_op *op = cop->sym;
> +	struct rte_mbuf *mb = op->m_src;
> +	uint8_t *m_ptr, *iv;
> +	uint64_t iv_u64[2];
> +	uint64_t m;
> +
> +	iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
> +
> +	iv_u64[0] = en_priv->cipher_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	iv_u64[1] = 0;
> +	rte_memcpy(iv, iv_u64, PDCP_IV_LENGTH);
> +
> +	m_ptr = (uint8_t *)rte_pktmbuf_prepend(mb, 8);
> +	m = en_priv->auth_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(m_ptr, &m, 8);
> +}
> +
> +static void
> +pdcp_iv_gen_aes_ctr_zs(struct rte_crypto_op *cop, const struct entity_priv
> *en_priv, uint32_t count)
> +{
> +	uint64_t iv_u64[2];
> +	uint8_t *iv;
> +
> +	iv = rte_crypto_op_ctod_offset(cop, uint8_t *, PDCP_IV_OFFSET);
> +
> +	iv_u64[0] = en_priv->cipher_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	iv_u64[1] = 0;
> +	rte_memcpy(iv, iv_u64, PDCP_IV_LENGTH);
> +
> +	iv += PDCP_IV_LENGTH;
> +
> +	iv_u64[0] = en_priv->auth_iv_part.u64[0] |
> ((uint64_t)(rte_cpu_to_be_32(count)));
> +	rte_memcpy(iv, &iv_u64[0], 8);
> +
> +	iv_u64[1] = iv_u64[0] ^ en_priv->auth_iv_part.u64[1];
> +	rte_memcpy(iv + 8, &iv_u64[1], 8);
> +}
> +
> +static int
> +pdcp_crypto_xfrm_get(const struct rte_pdcp_entity_conf *conf, struct
> rte_crypto_sym_xform **c_xfrm,
> +		     struct rte_crypto_sym_xform **a_xfrm)
> +{
> +	*c_xfrm = NULL;
> +	*a_xfrm = NULL;
> +
> +	if (conf->crypto_xfrm == NULL)
> +		return -EINVAL;
> +
> +	if (conf->crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
> +		*c_xfrm = conf->crypto_xfrm;
> +		*a_xfrm = conf->crypto_xfrm->next;
> +	} else if (conf->crypto_xfrm->type ==
> RTE_CRYPTO_SYM_XFORM_AUTH) {
> +		*a_xfrm = conf->crypto_xfrm;
> +		*c_xfrm = conf->crypto_xfrm->next;
> +	} else {
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int
> +pdcp_iv_gen_func_set(struct rte_pdcp_entity *entity, const struct
> rte_pdcp_entity_conf *conf)
> +{
> +	struct rte_crypto_sym_xform *c_xfrm, *a_xfrm;
> +	enum rte_security_pdcp_direction direction;
> +	enum pdcp_cipher_algo ciph_algo;
> +	enum pdcp_auth_algo auth_algo;
> +	struct entity_priv *en_priv;
> +	int ret;
> +
> +	en_priv = entity_priv_get(entity);
> +
> +	direction = conf->pdcp_xfrm.pkt_dir;
> +	if (conf->reverse_iv_direction)
> +		direction = !direction;
> +
> +	ret = pdcp_crypto_xfrm_get(conf, &c_xfrm, &a_xfrm);
> +	if (ret)
> +		return ret;
> +
> +	if (c_xfrm == NULL)
> +		return -EINVAL;
> +
> +	memset(&en_priv->auth_iv_part, 0, sizeof(en_priv->auth_iv_part));
> +	memset(&en_priv->cipher_iv_part, 0, sizeof(en_priv->cipher_iv_part));
> +
> +	switch (c_xfrm->cipher.algo) {
> +	case RTE_CRYPTO_CIPHER_NULL:
> +		ciph_algo = PDCP_CIPHER_ALGO_NULL;
> +		break;
> +	case RTE_CRYPTO_CIPHER_AES_CTR:
> +		ciph_algo = PDCP_CIPHER_ALGO_AES;
> +		en_priv->cipher_iv_part.aes_ctr.bearer = conf-
> >pdcp_xfrm.bearer;
> +		en_priv->cipher_iv_part.aes_ctr.direction = direction;
> +		break;
> +	case RTE_CRYPTO_CIPHER_SNOW3G_UEA2:
> +		ciph_algo = PDCP_CIPHER_ALGO_SNOW3G;
> +		en_priv->cipher_iv_part.zs.bearer = conf->pdcp_xfrm.bearer;
> +		en_priv->cipher_iv_part.zs.direction = direction;
> +		break;
> +	case RTE_CRYPTO_CIPHER_ZUC_EEA3:
> +		ciph_algo = PDCP_CIPHER_ALGO_ZUC;
> +		en_priv->cipher_iv_part.zs.bearer = conf->pdcp_xfrm.bearer;
> +		en_priv->cipher_iv_part.zs.direction = direction;
> +		break;
> +	default:
> +		return -ENOTSUP;
> +	}
> +
> +	if (a_xfrm != NULL) {
> +		switch (a_xfrm->auth.algo) {
> +		case RTE_CRYPTO_AUTH_NULL:
> +			auth_algo = PDCP_AUTH_ALGO_NULL;
> +			break;
> +		case RTE_CRYPTO_AUTH_AES_CMAC:
> +			auth_algo = PDCP_AUTH_ALGO_AES;
> +			en_priv->auth_iv_part.aes_cmac.bearer = conf-
> >pdcp_xfrm.bearer;
> +			en_priv->auth_iv_part.aes_cmac.direction = direction;
> +			break;
> +		case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
> +			auth_algo = PDCP_AUTH_ALGO_SNOW3G;
> +			en_priv->auth_iv_part.zs.bearer = conf-
> >pdcp_xfrm.bearer;
> +			en_priv->auth_iv_part.zs.direction_64 = direction;
> +			en_priv->auth_iv_part.zs.direction_112 = direction;
> +			break;
> +		case RTE_CRYPTO_AUTH_ZUC_EIA3:
> +			auth_algo = PDCP_AUTH_ALGO_ZUC;
> +			en_priv->auth_iv_part.zs.bearer = conf-
> >pdcp_xfrm.bearer;
> +			en_priv->auth_iv_part.zs.direction_64 = direction;
> +			en_priv->auth_iv_part.zs.direction_112 = direction;
> +			break;
> +		default:
> +			return -ENOTSUP;
> +		}
> +	} else {
> +		auth_algo = PDCP_AUTH_ALGO_NULL;
> +	}
> +
> +	static const iv_gen_t
> iv_gen_map[PDCP_CIPHER_ALGO_MAX][PDCP_AUTH_ALGO_MAX] = {
> +		[PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_NULL] =
> pdcp_iv_gen_null_null,
> +		[PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_AES] =
> pdcp_iv_gen_null_aes_cmac,
> +		[PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_SNOW3G] =
> pdcp_iv_gen_null_zs,
> +		[PDCP_CIPHER_ALGO_NULL][PDCP_AUTH_ALGO_ZUC] =
> pdcp_iv_gen_null_zs,
> +
> +		[PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_NULL] =
> pdcp_iv_gen_aes_ctr_null,
> +		[PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_AES] =
> pdcp_iv_gen_aes_ctr_aes_cmac,
> +		[PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_SNOW3G] =
> pdcp_iv_gen_aes_ctr_zs,
> +		[PDCP_CIPHER_ALGO_AES][PDCP_AUTH_ALGO_ZUC] =
> pdcp_iv_gen_aes_ctr_zs,
> +
> +		[PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_NULL] =
> pdcp_iv_gen_zs_null,
> +		[PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_AES] =
> pdcp_iv_gen_zs_aes_cmac,
> +
> 	[PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_SNOW3G] =
> pdcp_iv_gen_zs_zs,
> +		[PDCP_CIPHER_ALGO_SNOW3G][PDCP_AUTH_ALGO_ZUC] =
> pdcp_iv_gen_zs_zs,
> +
> +		[PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_NULL] =
> pdcp_iv_gen_zs_null,
> +		[PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_AES] =
> pdcp_iv_gen_zs_aes_cmac,
> +		[PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_SNOW3G] =
> pdcp_iv_gen_zs_zs,
> +		[PDCP_CIPHER_ALGO_ZUC][PDCP_AUTH_ALGO_ZUC] =
> pdcp_iv_gen_zs_zs,
> +	};
> +
> +	en_priv->iv_gen = iv_gen_map[ciph_algo][auth_algo];
> +
> +	return 0;
> +}
> +
> +static inline void
> +cop_prepare(const struct entity_priv *en_priv, struct rte_mbuf *mb, struct
> rte_crypto_op *cop,
> +	    uint8_t data_offset, uint32_t count, const bool is_auth)
> +{
> +	const struct rte_crypto_op cop_init = {
> +		.type = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
> +		.status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED,
> +		.sess_type = RTE_CRYPTO_OP_WITH_SESSION,
> +	};
> +	struct rte_crypto_sym_op *op;
> +	uint32_t pkt_len;
> +
> +	const uint8_t ciph_shift = 3 * en_priv->flags.is_ciph_in_bits;
> +	const uint8_t auth_shift = 3 * en_priv->flags.is_auth_in_bits;
> +
> +	op = cop->sym;
> +	cop->raw = cop_init.raw;
> +	op->m_src = mb;
> +	op->m_dst = mb;
> +
> +	/* Set IV */
> +	en_priv->iv_gen(cop, en_priv, count);
> +
> +	/* Prepare op */
> +	pkt_len = rte_pktmbuf_pkt_len(mb);
> +	op->cipher.data.offset = data_offset << ciph_shift;
> +	op->cipher.data.length = (pkt_len - data_offset) << ciph_shift;
> +
> +	if (is_auth) {
> +		op->auth.data.offset = 0;
> +		op->auth.data.length = (pkt_len - PDCP_MAC_I_LEN) <<
> auth_shift;
> +		op->auth.digest.data = rte_pktmbuf_mtod_offset(mb, uint8_t
> *,
> +							       (pkt_len -
> PDCP_MAC_I_LEN));
> +	}
> +
> +	__rte_crypto_sym_op_attach_sym_session(op, en_priv->crypto_sess);
> +}
> +
> +static inline bool
> +pdcp_pre_process_uplane_sn_12_ul_set_sn(struct entity_priv *en_priv, struct
> rte_mbuf *mb,
> +					uint32_t *count)
> +{
> +	struct rte_pdcp_up_data_pdu_sn_12_hdr *pdu_hdr;
> +	const uint8_t hdr_sz = en_priv->hdr_sz;
> +	uint32_t sn;
> +
> +	/* Prepend PDU header */
> +	pdu_hdr = (struct rte_pdcp_up_data_pdu_sn_12_hdr
> *)rte_pktmbuf_prepend(mb, hdr_sz);
> +	if (unlikely(pdu_hdr == NULL))
> +		return false;
> +
> +	/* Update sequence num in the PDU header */
> +	*count = __atomic_fetch_add(&en_priv->state.tx_next, 1,
> __ATOMIC_RELAXED);
> +	sn = PDCP_GET_SN_12_FROM_COUNT(*count);
> +
> +	pdu_hdr->d_c = PDCP_PDU_TYPE_DATA;
> +	pdu_hdr->sn_11_8 = ((sn & 0xf00) >> 8);
> +	pdu_hdr->sn_7_0 = (sn & 0xff);
> +	pdu_hdr->r = 0;
> +	return true;
> +}
> +
> +static uint16_t
> +pdcp_pre_process_uplane_sn_12_ul(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				 struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	uint16_t nb_cop;
> +	uint32_t count;
> +	int i;
> +
> +	const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz;
> +
> +	nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool,
> RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
> +					  num);
> +
> +	if (en_priv->flags.is_authenticated) {
> +		for (i = 0; i < nb_cop; i++) {
> +			if (unlikely(rte_pktmbuf_append(mb[i],
> PDCP_MAC_I_LEN) == NULL))
> +				goto cop_free;
> +			if
> (unlikely(!pdcp_pre_process_uplane_sn_12_ul_set_sn(en_priv, mb[i],
> +
> &count)))
> +				goto cop_free;
> +			cop_prepare(en_priv, mb[i], cop[i], data_offset, count,
> true);
> +		}
> +	} else {
> +		for (i = 0; i < nb_cop; i++) {
> +			if
> (unlikely(!pdcp_pre_process_uplane_sn_12_ul_set_sn(en_priv, mb[i],
> +
> &count)))
> +				goto cop_free;
> +			cop_prepare(en_priv, mb[i], cop[i], data_offset, count,
> false);
> +		}
> +	}
> +
> +	*nb_err = num - nb_cop;
> +	return nb_cop;
> +cop_free:
> +	/* Using mempool API since crypto API is not providing bulk free */
> +	rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[i], nb_cop - i);
> +	*nb_err = num - i;
> +	return i;
> +}
> +
> +static inline bool
> +pdcp_pre_process_uplane_sn_18_ul_set_sn(struct entity_priv *en_priv, struct
> rte_mbuf *mb,
> +					uint32_t *count)
> +{
> +	struct rte_pdcp_up_data_pdu_sn_18_hdr *pdu_hdr;
> +	const uint8_t hdr_sz = en_priv->hdr_sz;
> +	uint32_t sn;
> +
> +	/* Prepend PDU header */
> +	pdu_hdr = (struct rte_pdcp_up_data_pdu_sn_18_hdr
> *)rte_pktmbuf_prepend(mb, hdr_sz);
> +	if (unlikely(pdu_hdr == NULL))
> +		return false;
> +
> +	/* Update sequence num in the PDU header */
> +	*count = __atomic_fetch_add(&en_priv->state.tx_next, 1,
> __ATOMIC_RELAXED);
> +	sn = PDCP_GET_SN_18_FROM_COUNT(*count);
> +
> +	pdu_hdr->d_c = PDCP_PDU_TYPE_DATA;
> +	pdu_hdr->sn_17_16 = ((sn & 0x30000) >> 16);
> +	pdu_hdr->sn_15_8 = ((sn & 0xff00) >> 8);
> +	pdu_hdr->sn_7_0 = (sn & 0xff);
> +	pdu_hdr->r = 0;
> +
> +	return true;
> +}
> +
> +static inline uint16_t
> +pdcp_pre_process_uplane_sn_18_ul(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				 struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	uint16_t nb_cop;
> +	uint32_t count;
> +	int i;
> +
> +	const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz;
> +
> +	nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool,
> RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
> +					  num);
> +
> +	if (en_priv->flags.is_authenticated) {
> +		for (i = 0; i < nb_cop; i++) {
> +			if (unlikely(rte_pktmbuf_append(mb[i],
> PDCP_MAC_I_LEN) == NULL))
> +				goto cop_free;
> +			if
> (unlikely(!pdcp_pre_process_uplane_sn_18_ul_set_sn(en_priv, mb[i],
> +
> &count)))
> +				goto cop_free;
> +			cop_prepare(en_priv, mb[i], cop[i], data_offset, count,
> true);
> +		}
> +	} else {
> +		for (i = 0; i < nb_cop; i++) {
> +			if
> (unlikely(!pdcp_pre_process_uplane_sn_18_ul_set_sn(en_priv, mb[i],
> +
> &count)))
> +				goto cop_free;
> +			cop_prepare(en_priv, mb[i], cop[i], data_offset, count,
> false);
> +		}
> +	}
> +
> +	*nb_err = num - nb_cop;
> +	return nb_cop;
> +
> +cop_free:
> +	/* Using mempool API since crypto API is not providing bulk free */
> +	rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[i], nb_cop - i);
> +	*nb_err = num - i;
> +	return i;
> +}
> +
> +static uint16_t
> +pdcp_pre_process_cplane_sn_12_ul(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				 struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	struct rte_pdcp_cp_data_pdu_sn_12_hdr *pdu_hdr;
> +	uint32_t count, sn;
> +	uint16_t nb_cop;
> +	int i;
> +
> +	const uint8_t hdr_sz = en_priv->hdr_sz;
> +	const uint8_t data_offset = hdr_sz + en_priv->aad_sz;
> +
> +	nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool,
> RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
> +					  num);
> +
> +	for (i = 0; i < nb_cop; i++) {
> +		/* Prepend PDU header */
> +		pdu_hdr = (struct rte_pdcp_cp_data_pdu_sn_12_hdr
> *)rte_pktmbuf_prepend(mb[i],
> +
> 	       hdr_sz);
> +		if (unlikely(pdu_hdr == NULL))
> +			goto cop_free;
> +		if (unlikely(rte_pktmbuf_append(mb[i], PDCP_MAC_I_LEN) ==
> NULL))
> +			goto cop_free;
> +
> +		/* Update sequence number in the PDU header */
> +		count = __atomic_fetch_add(&en_priv->state.tx_next, 1,
> __ATOMIC_RELAXED);
> +		sn = PDCP_GET_SN_12_FROM_COUNT(count);
> +
> +		pdu_hdr->sn_11_8 = ((sn & 0xf00) >> 8);
> +		pdu_hdr->sn_7_0 = (sn & 0xff);
> +		pdu_hdr->r = 0;
> +
> +		cop_prepare(en_priv, mb[i], cop[i], data_offset, count, true);
> +	}
> +
> +	*nb_err = num - nb_cop;
> +	return nb_cop;
> +
> +cop_free:
> +	/* Using mempool API since crypto API is not providing bulk free */
> +	rte_mempool_put_bulk(en_priv->cop_pool, (void *)&cop[i], nb_cop - i);
> +	*nb_err = num - i;
> +	return i;
> +}
> +
> +static uint16_t
> +pdcp_post_process_uplane_sn_12_ul(const struct rte_pdcp_entity *entity,
> +				  struct rte_mbuf *in_mb[],
> +				  struct rte_mbuf *out_mb[],
> +				  uint16_t num, uint16_t *nb_err_ret)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	const uint32_t hdr_trim_sz = en_priv->aad_sz;
> +	int i, nb_success = 0, nb_err = 0;
> +	struct rte_mbuf *err_mb[num];
> +	struct rte_mbuf *mb;
> +
> +	for (i = 0; i < num; i++) {
> +		mb = in_mb[i];
> +		if (unlikely(mb->ol_flags &
> RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) {
> +			err_mb[nb_err++] = mb;
> +			continue;
> +		}
> +
> +		if (hdr_trim_sz)
> +			rte_pktmbuf_adj(mb, hdr_trim_sz);
> +
> +		out_mb[nb_success++] = mb;
> +	}
> +
> +	if (unlikely(nb_err != 0))
> +		rte_memcpy(&out_mb[nb_success], err_mb, nb_err *
> sizeof(struct rte_mbuf *));
> +
> +	*nb_err_ret = nb_err;
> +	return nb_success;
> +}
> +
> +static uint16_t
> +pdcp_post_process_uplane_sn_18_ul(const struct rte_pdcp_entity *entity,
> +				  struct rte_mbuf *in_mb[],
> +				  struct rte_mbuf *out_mb[],
> +				  uint16_t num, uint16_t *nb_err_ret)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	const uint32_t hdr_trim_sz = en_priv->aad_sz;
> +	int i, nb_success = 0, nb_err = 0;
> +	struct rte_mbuf *err_mb[num];
> +	struct rte_mbuf *mb;
> +
> +	for (i = 0; i < num; i++) {
> +		mb = in_mb[i];
> +		if (unlikely(mb->ol_flags &
> RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) {
> +			err_mb[nb_err++] = mb;
> +			continue;
> +		}
> +
> +		if (hdr_trim_sz)
> +			rte_pktmbuf_adj(mb, hdr_trim_sz);
> +
> +		out_mb[nb_success++] = mb;
> +	}
> +
> +	if (unlikely(nb_err != 0))
> +		rte_memcpy(&out_mb[nb_success], err_mb, nb_err *
> sizeof(struct rte_mbuf *));
> +
> +	*nb_err_ret = nb_err;
> +	return nb_success;
> +}
> +
> +static uint16_t
> +pdcp_post_process_cplane_sn_12_ul(const struct rte_pdcp_entity *entity,
> +				  struct rte_mbuf *in_mb[],
> +				  struct rte_mbuf *out_mb[],
> +				  uint16_t num, uint16_t *nb_err_ret)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	const uint32_t hdr_trim_sz = en_priv->aad_sz;
> +	int i, nb_success = 0, nb_err = 0;
> +	struct rte_mbuf *mb, *err_mb[num];
> +
> +	for (i = 0; i < num; i++) {
> +		mb = in_mb[i];
> +		if (unlikely(mb->ol_flags &
> RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED)) {
> +			err_mb[nb_err++] = mb;
> +			continue;
> +		}
> +
> +		if (hdr_trim_sz)
> +			rte_pktmbuf_adj(mb, hdr_trim_sz);
> +
> +		out_mb[nb_success++] = mb;
> +	}
> +
> +	if (unlikely(nb_err != 0))
> +		rte_memcpy(&out_mb[nb_success], err_mb, nb_err *
> sizeof(struct rte_mbuf *));
> +
> +	*nb_err_ret = nb_err;
> +	return nb_success;
> +}
> +
> +static inline int
> +pdcp_sn_18_count_get(const struct rte_pdcp_entity *entity, int32_t rsn,
> uint32_t *count)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	uint32_t rhfn, rx_deliv;
> +
> +	rx_deliv = __atomic_load_n(&en_priv->state.rx_deliv,
> __ATOMIC_RELAXED);
> +	rhfn = PDCP_GET_HFN_SN_18_FROM_COUNT(rx_deliv);
> +
> +	if (rsn < (int32_t)(PDCP_GET_SN_18_FROM_COUNT(rx_deliv) -
> PDCP_SN_18_WINDOW_SZ)) {
> +		if (unlikely(rhfn == PDCP_SN_18_HFN_MAX))
> +			return -ERANGE;
> +		rhfn += 1;
> +	} else if ((uint32_t)rsn >= (PDCP_GET_SN_18_FROM_COUNT(rx_deliv) +
> PDCP_SN_18_WINDOW_SZ)) {
> +		if (unlikely(rhfn == PDCP_SN_18_HFN_MIN))
> +			return -ERANGE;
> +		rhfn -= 1;
> +	}
> +
> +	*count = PDCP_SET_COUNT_FROM_HFN_SN_18(rhfn, rsn);
> +
> +	return 0;
> +}
> +
> +static inline int
> +pdcp_sn_12_count_get(const struct rte_pdcp_entity *entity, int32_t rsn,
> uint32_t *count)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	uint32_t rhfn, rx_deliv;
> +
> +	rx_deliv = __atomic_load_n(&en_priv->state.rx_deliv,
> __ATOMIC_RELAXED);
> +	rhfn = PDCP_GET_HFN_SN_12_FROM_COUNT(rx_deliv);
> +
> +	if (rsn < (int32_t)(PDCP_GET_SN_12_FROM_COUNT(rx_deliv) -
> PDCP_SN_12_WINDOW_SZ)) {
> +		if (unlikely(rhfn == PDCP_SN_12_HFN_MAX))
> +			return -ERANGE;
> +		rhfn += 1;
> +	} else if ((uint32_t)rsn >= (PDCP_GET_SN_12_FROM_COUNT(rx_deliv) +
> PDCP_SN_12_WINDOW_SZ)) {
> +		if (unlikely(rhfn == PDCP_SN_12_HFN_MIN))
> +			return -ERANGE;
> +		rhfn -= 1;
> +	}
> +
> +	*count = PDCP_SET_COUNT_FROM_HFN_SN_12(rhfn, rsn);
> +
> +	return 0;
> +}
> +
> +static inline uint16_t
> +pdcp_pre_process_uplane_sn_12_dl_flags(const struct rte_pdcp_entity
> *entity, struct rte_mbuf *mb[],
> +				       struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err,
> +				       const bool is_integ_protected)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	struct rte_pdcp_up_data_pdu_sn_12_hdr *pdu_hdr;
> +	uint16_t nb_cop;
> +	int32_t rsn = 0;
> +	uint32_t count;
> +	int i;
> +
> +	const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz;
> +
> +	nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool,
> RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
> +					  num);
> +
> +	for (i = 0; i < nb_cop; i++) {
> +
> +		pdu_hdr = rte_pktmbuf_mtod(mb[i], struct
> rte_pdcp_up_data_pdu_sn_12_hdr *);
> +
> +		/* Check for PDU type */
> +		if (likely(pdu_hdr->d_c == PDCP_PDU_TYPE_DATA))
> +			rsn = ((pdu_hdr->sn_11_8 << 8) | (pdu_hdr->sn_7_0));
> +		else
> +			rte_panic("TODO: Control PDU not handled");
> +
> +		if (unlikely(pdcp_sn_12_count_get(entity, rsn, &count)))
> +			break;
> +		cop_prepare(en_priv, mb[i], cop[i], data_offset, count,
> is_integ_protected);
> +	}
> +
> +	*nb_err = num - nb_cop;
> +
> +	return nb_cop;
> +}
> +
> +static uint16_t
> +pdcp_pre_process_uplane_sn_12_dl_ip(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				    struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	return pdcp_pre_process_uplane_sn_12_dl_flags(entity, mb, cop, num,
> nb_err, true);
> +}
> +
> +static uint16_t
> +pdcp_pre_process_uplane_sn_12_dl(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				 struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	return pdcp_pre_process_uplane_sn_12_dl_flags(entity, mb, cop, num,
> nb_err, false);
> +}
> +
> +static inline uint16_t
> +pdcp_pre_process_uplane_sn_18_dl_flags(const struct rte_pdcp_entity
> *entity, struct rte_mbuf *mb[],
> +				       struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err,
> +				       const bool is_integ_protected)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	struct rte_pdcp_up_data_pdu_sn_18_hdr *pdu_hdr;
> +	uint16_t nb_cop;
> +	int32_t rsn = 0;
> +	uint32_t count;
> +	int i;
> +
> +	const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz;
> +	nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool,
> RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
> +					  num);
> +
> +	for (i = 0; i < nb_cop; i++) {
> +		pdu_hdr = rte_pktmbuf_mtod(mb[i], struct
> rte_pdcp_up_data_pdu_sn_18_hdr *);
> +
> +		/* Check for PDU type */
> +		if (likely(pdu_hdr->d_c == PDCP_PDU_TYPE_DATA))
> +			rsn = ((pdu_hdr->sn_17_16 << 16) | (pdu_hdr->sn_15_8
> << 8) |
> +			       (pdu_hdr->sn_7_0));
> +		else
> +			rte_panic("TODO: Control PDU not handled");
> +
> +		if (unlikely(pdcp_sn_18_count_get(entity, rsn, &count)))
> +			break;
> +		cop_prepare(en_priv, mb[i], cop[i], data_offset, count,
> is_integ_protected);
> +	}
> +
> +	*nb_err = num - nb_cop;
> +
> +	return nb_cop;
> +}
> +
> +static uint16_t
> +pdcp_pre_process_uplane_sn_18_dl_ip(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				    struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	return pdcp_pre_process_uplane_sn_18_dl_flags(entity, mb, cop, num,
> nb_err, true);
> +}
> +
> +static uint16_t
> +pdcp_pre_process_uplane_sn_18_dl(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				 struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	return pdcp_pre_process_uplane_sn_18_dl_flags(entity, mb, cop, num,
> nb_err, false);
> +}
> +
> +static uint16_t
> +pdcp_pre_process_cplane_sn_12_dl(const struct rte_pdcp_entity *entity,
> struct rte_mbuf *mb[],
> +				 struct rte_crypto_op *cop[], uint16_t num,
> uint16_t *nb_err)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	struct rte_pdcp_cp_data_pdu_sn_12_hdr *pdu_hdr;
> +	uint16_t nb_cop;
> +	uint32_t count;
> +	int32_t rsn;
> +	int i;
> +
> +	const uint8_t data_offset = en_priv->hdr_sz + en_priv->aad_sz;
> +
> +	nb_cop = rte_crypto_op_bulk_alloc(en_priv->cop_pool,
> RTE_CRYPTO_OP_TYPE_SYMMETRIC, cop,
> +					  num);
> +
> +	for (i = 0; i < nb_cop; i++) {
> +		pdu_hdr = rte_pktmbuf_mtod(mb[i], struct
> rte_pdcp_cp_data_pdu_sn_12_hdr *);
> +		rsn = ((pdu_hdr->sn_11_8 << 8) | (pdu_hdr->sn_7_0));
> +		if (unlikely(pdcp_sn_12_count_get(entity, rsn, &count)))
> +			break;
> +		cop_prepare(en_priv, mb[i], cop[i], data_offset, count, true);
> +	}
> +
> +	*nb_err = num - nb_cop;
> +	return nb_cop;
> +}
> +
> +static inline bool
> +pdcp_post_process_update_entity_state(const struct rte_pdcp_entity *entity,
> +				      const uint32_t count)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +
> +	if (count < __atomic_load_n(&en_priv->state.rx_deliv,
> __ATOMIC_RELAXED))
> +		return false;
> +
> +	/* t-Reordering timer is not supported - SDU will be delivered
> immediately.
> +	 * Update RX_DELIV to the COUNT value of the first PDCP SDU which
> has not
> +	 * been delivered to upper layers
> +	 */
> +	__atomic_store_n(&en_priv->state.rx_deliv, (count + 1),
> __ATOMIC_RELAXED);
> +
> +	if (count >= __atomic_load_n(&en_priv->state.rx_next,
> __ATOMIC_RELAXED))
> +		__atomic_store_n(&en_priv->state.rx_next, (count + 1),
> __ATOMIC_RELAXED);
> +
> +	return true;
> +}
> +
> +static inline uint16_t
> +pdcp_post_process_uplane_sn_12_dl_flags(const struct rte_pdcp_entity
> *entity,
> +					struct rte_mbuf *in_mb[],
> +					struct rte_mbuf *out_mb[],
> +					uint16_t num, uint16_t *nb_err_ret,
> +					const bool is_integ_protected)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	struct rte_pdcp_up_data_pdu_sn_12_hdr *pdu_hdr;
> +	int i, nb_success = 0, nb_err = 0, rsn = 0;
> +	const uint32_t aad_sz = en_priv->aad_sz;
> +	struct rte_mbuf *err_mb[num];
> +	struct rte_mbuf *mb;
> +	uint32_t count;
> +
> +	const uint32_t hdr_trim_sz = en_priv->hdr_sz + aad_sz;
> +
> +	for (i = 0; i < num; i++) {
> +		mb = in_mb[i];
> +		if (unlikely(mb->ol_flags &
> RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED))
> +			goto error;
> +		pdu_hdr = rte_pktmbuf_mtod_offset(mb, struct
> rte_pdcp_up_data_pdu_sn_12_hdr *,
> +						  aad_sz);
> +
> +		/* Check for PDU type */
> +		if (likely(pdu_hdr->d_c == PDCP_PDU_TYPE_DATA))
> +			rsn = ((pdu_hdr->sn_11_8 << 8) | (pdu_hdr->sn_7_0));
> +		else
> +			rte_panic("Control PDU should not be received");
> +
> +		if (unlikely(pdcp_sn_12_count_get(entity, rsn, &count)))
> +			goto error;
> +
> +		if (unlikely(!pdcp_post_process_update_entity_state(entity,
> count)))
> +			goto error;
> +
> +		rte_pktmbuf_adj(mb, hdr_trim_sz);
> +		if (is_integ_protected)
> +			rte_pktmbuf_trim(mb, PDCP_MAC_I_LEN);
> +		out_mb[nb_success++] = mb;
> +		continue;
> +
> +error:
> +		err_mb[nb_err++] = mb;
> +	}
> +
> +	if (unlikely(nb_err != 0))
> +		rte_memcpy(&out_mb[nb_success], err_mb, nb_err *
> sizeof(struct rte_mbuf *));
> +
> +	*nb_err_ret = nb_err;
> +	return nb_success;
> +}
> +
> +static uint16_t
> +pdcp_post_process_uplane_sn_12_dl_ip(const struct rte_pdcp_entity *entity,
> +				     struct rte_mbuf *in_mb[],
> +				     struct rte_mbuf *out_mb[],
> +				     uint16_t num, uint16_t *nb_err)
> +{
> +	return pdcp_post_process_uplane_sn_12_dl_flags(entity, in_mb,
> out_mb, num, nb_err, true);
> +}
> +
> +static uint16_t
> +pdcp_post_process_uplane_sn_12_dl(const struct rte_pdcp_entity *entity,
> +				  struct rte_mbuf *in_mb[],
> +				  struct rte_mbuf *out_mb[],
> +				  uint16_t num, uint16_t *nb_err)
> +{
> +	return pdcp_post_process_uplane_sn_12_dl_flags(entity, in_mb,
> out_mb, num, nb_err, false);
> +}
> +
> +static inline uint16_t
> +pdcp_post_process_uplane_sn_18_dl_flags(const struct rte_pdcp_entity
> *entity,
> +					struct rte_mbuf *in_mb[],
> +					struct rte_mbuf *out_mb[],
> +					uint16_t num, uint16_t *nb_err_ret,
> +					const bool is_integ_protected)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	struct rte_pdcp_up_data_pdu_sn_18_hdr *pdu_hdr;
> +	const uint32_t aad_sz = en_priv->aad_sz;
> +	int i, nb_success = 0, nb_err = 0;
> +	struct rte_mbuf *mb, *err_mb[num];
> +	int32_t rsn = 0;
> +	uint32_t count;
> +
> +	const uint32_t hdr_trim_sz = en_priv->hdr_sz + aad_sz;
> +
> +	for (i = 0; i < num; i++) {
> +		mb = in_mb[i];
> +		if (unlikely(mb->ol_flags &
> RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED))
> +			goto error;
> +
> +		pdu_hdr = rte_pktmbuf_mtod_offset(mb, struct
> rte_pdcp_up_data_pdu_sn_18_hdr *,
> +						  aad_sz);
> +
> +		/* Check for PDU type */
> +		if (likely(pdu_hdr->d_c == PDCP_PDU_TYPE_DATA))
> +			rsn = ((pdu_hdr->sn_17_16 << 16) | (pdu_hdr->sn_15_8
> << 8) |
> +			       (pdu_hdr->sn_7_0));
> +		else
> +			rte_panic("Control PDU should not be received");
> +
> +		if (unlikely(pdcp_sn_18_count_get(entity, rsn, &count)))
> +			goto error;
> +
> +		if (unlikely(!pdcp_post_process_update_entity_state(entity,
> count)))
> +			goto error;
> +
> +		rte_pktmbuf_adj(mb, hdr_trim_sz);
> +		if (is_integ_protected)
> +			rte_pktmbuf_trim(mb, PDCP_MAC_I_LEN);
> +		out_mb[nb_success++] = mb;
> +		continue;
> +
> +error:
> +		err_mb[nb_err++] = mb;
> +	}
> +
> +	if (unlikely(nb_err != 0))
> +		rte_memcpy(&out_mb[nb_success], err_mb, nb_err *
> sizeof(struct rte_mbuf *));
> +
> +	*nb_err_ret = nb_err;
> +	return nb_success;
> +}
> +
> +static uint16_t
> +pdcp_post_process_uplane_sn_18_dl_ip(const struct rte_pdcp_entity *entity,
> +				     struct rte_mbuf *in_mb[],
> +				     struct rte_mbuf *out_mb[],
> +				     uint16_t num, uint16_t *nb_err)
> +{
> +	return pdcp_post_process_uplane_sn_18_dl_flags(entity, in_mb,
> out_mb, num, nb_err, true);
> +}
> +
> +static uint16_t
> +pdcp_post_process_uplane_sn_18_dl(const struct rte_pdcp_entity *entity,
> +				  struct rte_mbuf *in_mb[],
> +				  struct rte_mbuf *out_mb[],
> +				  uint16_t num, uint16_t *nb_err)
> +{
> +	return pdcp_post_process_uplane_sn_18_dl_flags(entity, in_mb,
> out_mb, num, nb_err, false);
> +}
> +
> +static uint16_t
> +pdcp_post_process_cplane_sn_12_dl(const struct rte_pdcp_entity *entity,
> +				  struct rte_mbuf *in_mb[],
> +				  struct rte_mbuf *out_mb[],
> +				  uint16_t num, uint16_t *nb_err_ret)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +	struct rte_pdcp_cp_data_pdu_sn_12_hdr *pdu_hdr;
> +	const uint32_t aad_sz = en_priv->aad_sz;
> +	int i, nb_success = 0, nb_err = 0;
> +	struct rte_mbuf *err_mb[num];
> +	struct rte_mbuf *mb;
> +	uint32_t count;
> +	int32_t rsn;
> +
> +	const uint32_t hdr_trim_sz = en_priv->hdr_sz + aad_sz;
> +
> +	for (i = 0; i < num; i++) {
> +		mb = in_mb[i];
> +		if (unlikely(mb->ol_flags &
> RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED))
> +			goto error;
> +
> +		pdu_hdr = rte_pktmbuf_mtod_offset(mb, struct
> rte_pdcp_cp_data_pdu_sn_12_hdr *,
> +						  aad_sz);
> +		rsn = ((pdu_hdr->sn_11_8 << 8) | (pdu_hdr->sn_7_0));
> +
> +		if (unlikely(pdcp_sn_12_count_get(entity, rsn, &count)))
> +			goto error;
> +
> +		if (unlikely(!pdcp_post_process_update_entity_state(entity,
> count)))
> +			goto error;
> +
> +		rte_pktmbuf_adj(mb, hdr_trim_sz);
> +		rte_pktmbuf_trim(mb, PDCP_MAC_I_LEN);
> +		out_mb[nb_success++] = mb;
> +		continue;
> +
> +error:
> +		err_mb[nb_err++] = mb;
> +	}
> +
> +	if (unlikely(nb_err != 0))
> +		rte_memcpy(&out_mb[nb_success], err_mb, nb_err *
> sizeof(struct rte_mbuf *));
> +
> +	*nb_err_ret = nb_err;
> +	return nb_success;
> +}
> +
> +static int
> +pdcp_pre_process_func_set(struct rte_pdcp_entity *entity, const struct
> rte_pdcp_entity_conf *conf)
> +{
> +	struct entity_priv *en_priv = entity_priv_get(entity);
> +
> +	entity->pre_process = NULL;
> +	entity->post_process = NULL;
> +
> +	if ((conf->pdcp_xfrm.domain ==
> RTE_SECURITY_PDCP_MODE_CONTROL) &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)) {
> +		entity->pre_process = pdcp_pre_process_cplane_sn_12_ul;
> +		entity->post_process = pdcp_post_process_cplane_sn_12_ul;
> +	}
> +
> +	if ((conf->pdcp_xfrm.domain ==
> RTE_SECURITY_PDCP_MODE_CONTROL) &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)) {
> +		entity->pre_process = pdcp_pre_process_cplane_sn_12_dl;
> +		entity->post_process = pdcp_post_process_cplane_sn_12_dl;
> +	}
> +
> +	if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA)
> &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)) {
> +		entity->pre_process = pdcp_pre_process_uplane_sn_12_ul;
> +		entity->post_process = pdcp_post_process_uplane_sn_12_ul;
> +	}
> +
> +	if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA)
> &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_18) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)) {
> +		entity->pre_process = pdcp_pre_process_uplane_sn_18_ul;
> +		entity->post_process = pdcp_post_process_uplane_sn_18_ul;
> +	}
> +
> +	if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA)
> &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
> +	    (en_priv->flags.is_authenticated)) {
> +		entity->pre_process = pdcp_pre_process_uplane_sn_12_dl_ip;
> +		entity->post_process =
> pdcp_post_process_uplane_sn_12_dl_ip;
> +	}
> +
> +	if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA)
> &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_12) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
> +	    (!en_priv->flags.is_authenticated)) {
> +		entity->pre_process = pdcp_pre_process_uplane_sn_12_dl;
> +		entity->post_process = pdcp_post_process_uplane_sn_12_dl;
> +	}
> +
> +	if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA)
> &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_18) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
> +	    (en_priv->flags.is_authenticated)) {
> +		entity->pre_process = pdcp_pre_process_uplane_sn_18_dl_ip;
> +		entity->post_process =
> pdcp_post_process_uplane_sn_18_dl_ip;
> +	}
> +
> +	if ((conf->pdcp_xfrm.domain == RTE_SECURITY_PDCP_MODE_DATA)
> &&
> +	    (conf->pdcp_xfrm.sn_size == RTE_SECURITY_PDCP_SN_SIZE_18) &&
> +	    (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) &&
> +	    (!en_priv->flags.is_authenticated)) {
> +		entity->pre_process = pdcp_pre_process_uplane_sn_18_dl;
> +		entity->post_process = pdcp_post_process_uplane_sn_18_dl;
> +	}
> +
> +	if (entity->pre_process == NULL || entity->post_process == NULL)
> +		return -ENOTSUP;
> +
> +	return 0;
> +}
> +
> +static int
> +pdcp_entity_priv_populate(struct entity_priv *en_priv, const struct
> rte_pdcp_entity_conf *conf)
> +{
> +	struct rte_crypto_sym_xform *c_xfrm, *a_xfrm;
> +	int ret;
> +
> +	/**
> +	 * flags.is_authenticated
> +	 *
> +	 * MAC-I would be added in case of control plane packets and when
> authentication
> +	 * transform is not NULL.
> +	 */
> +
> +	if (conf->pdcp_xfrm.domain ==
> RTE_SECURITY_PDCP_MODE_CONTROL)
> +		en_priv->flags.is_authenticated = 1;
> +
> +	ret = pdcp_crypto_xfrm_get(conf, &c_xfrm, &a_xfrm);
> +	if (ret)
> +		return ret;
> +
> +	if (a_xfrm != NULL)
> +		en_priv->flags.is_authenticated = 1;
> +
> +	/**
> +	 * flags.is_ciph_in_bits
> +	 *
> +	 * For ZUC & SNOW3G cipher algos, offset & length need to be provided
> in bits.
> +	 */
> +
> +	if ((c_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_SNOW3G_UEA2) ||
> +	    (c_xfrm->cipher.algo == RTE_CRYPTO_CIPHER_ZUC_EEA3))
> +		en_priv->flags.is_ciph_in_bits = 1;
> +
> +	/**
> +	 * flags.is_auth_in_bits
> +	 *
> +	 * For ZUC & SNOW3G authentication algos, offset & length need to be
> provided in bits.
> +	 */
> +
> +	if (a_xfrm != NULL) {
> +		if ((a_xfrm->auth.algo == RTE_CRYPTO_AUTH_SNOW3G_UIA2)
> ||
> +		    (a_xfrm->auth.algo == RTE_CRYPTO_AUTH_ZUC_EIA3))
> +			en_priv->flags.is_auth_in_bits = 1;
> +	}
> +
> +	/**
> +	 * flags.is_ul_entity
> +	 *
> +	 * Indicate whether the entity is UL/transmitting PDCP entity.
> +	 */
> +	if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)
> +		en_priv->flags.is_ul_entity = 1;
> +
> +	/**
> +	 * hdr_sz
> +	 *
> +	 * PDCP header size of the entity
> +	 */
> +	en_priv->hdr_sz = pdcp_hdr_size_get(conf->pdcp_xfrm.sn_size);
> +
> +	/**
> +	 * aad_sz
> +	 *
> +	 * For AES-CMAC, additional message is prepended for processing. Need
> to be trimmed after
> +	 * crypto processing is done.
> +	 */
> +	if (a_xfrm != NULL && a_xfrm->auth.algo ==
> RTE_CRYPTO_AUTH_AES_CMAC)
> +		en_priv->aad_sz = 8;
> +	else
> +		en_priv->aad_sz = 0;
> +
> +	return 0;
> +}
> +
> +int
> +pdcp_process_func_set(struct rte_pdcp_entity *entity, const struct
> rte_pdcp_entity_conf *conf)
> +{
> +	struct entity_priv *en_priv;
> +	int ret;
> +
> +	if (entity == NULL || conf == NULL)
> +		return -EINVAL;
> +
> +	en_priv = entity_priv_get(entity);
> +
> +	ret = pdcp_iv_gen_func_set(entity, conf);
> +	if (ret)
> +		return ret;
> +
> +	ret = pdcp_entity_priv_populate(en_priv, conf);
> +	if (ret)
> +		return ret;
> +
> +	ret = pdcp_pre_process_func_set(entity, conf);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> diff --git a/lib/pdcp/pdcp_process.h b/lib/pdcp/pdcp_process.h
> new file mode 100644
> index 0000000000..c92ab34c40
> --- /dev/null
> +++ b/lib/pdcp/pdcp_process.h
> @@ -0,0 +1,13 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#ifndef _PDCP_PROCESS_H_
> +#define _PDCP_PROCESS_H_
> +
> +#include <rte_pdcp.h>
> +
> +int
> +pdcp_process_func_set(struct rte_pdcp_entity *entity, const struct
> rte_pdcp_entity_conf *conf);
> +
> +#endif /* _PDCP_PROCESS_H_ */
> diff --git a/lib/pdcp/rte_pdcp.c b/lib/pdcp/rte_pdcp.c
> new file mode 100644
> index 0000000000..b1533971c2
> --- /dev/null
> +++ b/lib/pdcp/rte_pdcp.c
> @@ -0,0 +1,136 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#include <rte_pdcp.h>
> +#include <rte_malloc.h>
> +
> +#include "pdcp_crypto.h"
> +#include "pdcp_entity.h"
> +#include "pdcp_process.h"
> +
> +static int
> +pdcp_entity_size_get(const struct rte_pdcp_entity_conf *conf)
> +{
> +	int size;
> +
> +	size = sizeof(struct rte_pdcp_entity) + sizeof(struct entity_priv);
> +
> +	if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK)
> +		size += sizeof(struct entity_priv_dl_part);
> +	else if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)
> +		size += sizeof(struct entity_priv_ul_part);
> +	else
> +		return -EINVAL;
> +
> +	return RTE_ALIGN_CEIL(size, RTE_CACHE_LINE_SIZE);
> +}
> +
> +struct rte_pdcp_entity *
> +rte_pdcp_entity_establish(const struct rte_pdcp_entity_conf *conf)
> +{
> +	struct rte_pdcp_entity *entity = NULL;
> +	struct entity_priv *en_priv;
> +	int ret;
> +
> +	if (conf == NULL || conf->cop_pool == NULL) {
> +		rte_errno = -EINVAL;
> +		return NULL;
> +	}
> +
> +	if (conf->pdcp_xfrm.en_ordering || conf-
> >pdcp_xfrm.remove_duplicates || conf->is_slrb ||
> +	    conf->en_sec_offload) {
> +		rte_errno = -ENOTSUP;
> +		return NULL;
> +	}
> +
> +	/*
> +	 * 6.3.2 PDCP SN
> +	 * Length: 12 or 18 bits as indicated in table 6.3.2-1. The length of the
> PDCP SN is
> +	 * configured by upper layers (pdcp-SN-SizeUL, pdcp-SN-SizeDL, or sl-
> PDCP-SN-Size in
> +	 * TS 38.331 [3])
> +	 */
> +	if ((conf->pdcp_xfrm.sn_size != RTE_SECURITY_PDCP_SN_SIZE_12) &&
> +	    (conf->pdcp_xfrm.sn_size != RTE_SECURITY_PDCP_SN_SIZE_18)) {
> +		rte_errno = -ENOTSUP;
> +		return NULL;
> +	}
> +
> +	if (conf->pdcp_xfrm.hfn || conf->pdcp_xfrm.hfn_threshold) {
> +		rte_errno = -EINVAL;
> +		return NULL;
> +	}
> +
> +	entity = rte_zmalloc_socket("pdcp_entity", pdcp_entity_size_get(conf),
> +				    RTE_CACHE_LINE_SIZE, SOCKET_ID_ANY);
> +	if (entity == NULL) {
> +		rte_errno = -ENOMEM;
> +		return NULL;
> +	}
> +
> +	en_priv = entity_priv_get(entity);
> +
> +	en_priv->state.rx_deliv = conf->count;
> +	en_priv->state.tx_next = conf->count;
> +	en_priv->cop_pool = conf->cop_pool;
> +
> +	/* Setup crypto session */
> +	ret = pdcp_crypto_sess_create(entity, conf);
> +	if (ret)
> +		goto entity_free;
> +
> +	ret = pdcp_process_func_set(entity, conf);
> +	if (ret)
> +		goto crypto_sess_destroy;
> +
> +	return entity;
> +
> +crypto_sess_destroy:
> +	pdcp_crypto_sess_destroy(entity);
> +entity_free:
> +	rte_free(entity);
> +	rte_errno = ret;
> +	return NULL;
> +}
> +
> +int
> +rte_pdcp_entity_release(struct rte_pdcp_entity *pdcp_entity, struct rte_mbuf
> *out_mb[])
> +{
> +	int ret;
> +
> +	if (pdcp_entity == NULL)
> +		return -EINVAL;
> +
> +	/* Teardown crypto sessions */
> +	ret = pdcp_crypto_sess_destroy(pdcp_entity);
> +	if (ret)
> +		return ret;
> +
> +	rte_free(pdcp_entity);
> +
> +	RTE_SET_USED(out_mb);
> +	return 0;
> +}
> +
> +int
> +rte_pdcp_entity_suspend(struct rte_pdcp_entity *pdcp_entity,
> +			struct rte_mbuf *out_mb[])
> +{
> +	struct entity_priv *en_priv;
> +
> +	if (pdcp_entity == NULL)
> +		return -EINVAL;
> +
> +	en_priv = entity_priv_get(pdcp_entity);
> +
> +	if (en_priv->flags.is_ul_entity) {
> +		en_priv->state.tx_next = 0;
> +	} else {
> +		en_priv->state.rx_next = 0;
> +		en_priv->state.rx_deliv = 0;
> +	}
> +
> +	RTE_SET_USED(out_mb);
> +
> +	return 0;
> +}
> diff --git a/lib/pdcp/rte_pdcp.h b/lib/pdcp/rte_pdcp.h
> new file mode 100644
> index 0000000000..b6c7f32c05
> --- /dev/null
> +++ b/lib/pdcp/rte_pdcp.h
> @@ -0,0 +1,263 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#ifndef _RTE_PDCP_H_
> +#define _RTE_PDCP_H_
> +
> +/**
> + * @file rte_pdcp.h
> + *
> + * RTE PDCP support.
> + *
> + * librte_pdcp provides a framework for PDCP protocol processing.
> + */
> +
> +#include <rte_compat.h>
> +#include <rte_common.h>
> +#include <rte_errno.h>
> +#include <rte_mempool.h>
> +#include <rte_security.h>

Remove header file which is not needed.
I do not see use of rte_errno.h
I believe rte_common.h and rte_compat.h are also not needed.

> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/* Forward declarations */
> +struct rte_pdcp_entity;
> +
> +/* PDCP pre-process function based on entity configuration */
> +typedef uint16_t (*rte_pdcp_pre_p_t)(const struct rte_pdcp_entity *entity,
> +				     struct rte_mbuf *mb[],
> +				     struct rte_crypto_op *cop[],
> +				     uint16_t num, uint16_t *nb_err);
> +
> +/* PDCP post-process function based on entity configuration */
> +typedef uint16_t (*rte_pdcp_post_p_t)(const struct rte_pdcp_entity *entity,
> +				      struct rte_mbuf *in_mb[],
> +				      struct rte_mbuf *out_mb[],
> +				      uint16_t num, uint16_t *nb_err);
> +
> +/**
> + * PDCP entity.
> + */
> +struct rte_pdcp_entity {
> +	/** Entity specific pre-process handle. */
> +	rte_pdcp_pre_p_t pre_process;
> +	/** Entity specific post-process handle. */
> +	rte_pdcp_post_p_t post_process;
> +	/**
> +	 * PDCP entities may hold packets for purposes of in-order delivery (in
> +	 * case of receiving PDCP entity) and re-transmission (in case of
> +	 * transmitting PDCP entity).
> +	 *
> +	 * For receiving PDCP entity, it may hold packets when in-order
> +	 * delivery is enabled. The packets would be cached until either a
> +	 * packet that completes the sequence arrives or when discard timer
> +	 * expires.
> +	 *
> +	 * When post-processing of PDCP packet which completes a sequence is
> +	 * done, the API may return more packets than enqueued. Application is
> +	 * expected to provide *rte_pdcp_pkt_post_process()* with *out_mb*
> +	 * which can hold maximum number of packets which may be returned.
> +	 *
> +	 * For transmitting PDCP entity, during re-establishment (5.1.2),
> +	 * entity may be required to perform re-transmission of the buffers
> +	 * after applying new ciphering & integrity algorithms. For performing
> +	 * crypto operation, *rte_pdcp_entity_re_establish()* would return as
> +	 * many crypto_ops as the ones cached.
> +	 */
> +	uint16_t max_pkt_cache;
> +	/** User area for saving application data. */
> +	uint64_t user_area[2];
> +} __rte_cache_aligned;
> +
> +/**
> + * PDCP entity configuration to be used for establishing an entity.
> + */
> +struct rte_pdcp_entity_conf {
> +	/** PDCP transform for the entity. */
> +	struct rte_security_pdcp_xform pdcp_xfrm;
> +	/** Crypto transform applicable for the entity. */
> +	struct rte_crypto_sym_xform *crypto_xfrm;
> +	/** Mempool for crypto symmetric session. */
> +	struct rte_mempool *sess_mpool;
> +	/** Crypto op pool.*/
> +	struct rte_mempool *cop_pool;
> +	/**
> +	 * 32 bit count value (HFN + SN) to be used for the first packet.
> +	 * pdcp_xfrm.hfn would be ignored as the HFN would be derived from
> this value.
> +	 */
> +	uint32_t count;
> +	/** Indicate whether the PDCP entity belongs to Side Link Radio Bearer.
> */
> +	bool is_slrb;
> +	/** Enable security offload on the device specified. */
> +	bool en_sec_offload;
> +	/** Enable non-atomic usage of entity. */
> +	bool en_non_atomic;
> +	/** Device on which security/crypto session need to be created. */
> +	uint8_t dev_id;
> +	/** Reverse direction during IV generation. Can be used to simulate UE
> crypto processing.*/
> +	bool reverse_iv_direction;
> +};
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * 5.1.1 PDCP entity establishment
> + *
> + * Establish PDCP entity based on provided input configuration.
> + *
> + * @param conf
> + *   Parameters to be used for initializing PDCP entity object.
> + * @return
> + *   - Valid handle if success
> + *   - NULL in case of failure. rte_errno will be set to error code
> + */
> +__rte_experimental
> +struct rte_pdcp_entity *
> +rte_pdcp_entity_establish(const struct rte_pdcp_entity_conf *conf);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * 5.1.3 PDCP entity release
> + *
> + * Release PDCP entity.
> + *
> + * For UL/transmitting PDCP entity, all stored PDCP SDUs would be dropped.
> + * For DL/receiving PDCP entity, the stored PDCP SDUs would be returned in
> + * *out_mb* buffer. The buffer should be large enough to hold all cached
> + * packets in the entity.
> + *
> + * @param pdcp_entity
> + *   Pointer to the PDCP entity to be released.
> + * @param[out] out_mb
> + *   The address of an array that can hold up to
> *rte_pdcp_entity.max_pkt_cache*
> + *   pointers to *rte_mbuf* structures.
> + * @return
> + *   -  0: Success and no cached packets to return
> + *   - >0: Success and the number of packets returned in out_mb
> + *   - <0: Error code in case of failures
> + */
> +__rte_experimental
> +int
> +rte_pdcp_entity_release(struct rte_pdcp_entity *pdcp_entity,
> +			struct rte_mbuf *out_mb[]);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * 5.1.4 PDCP entity suspend
> + *
> + * Suspend PDCP entity.
> + *
> + * For DL/receiving PDCP entity, the stored PDCP SDUs would be returned in
> + * *out_mb* buffer. The buffer should be large enough to hold all cached
> + * packets in the entity.
> + *
> + * For UL/transmitting PDCP entity, *out_mb* buffer would be unused.
> + *
> + * @param pdcp_entity
> + *   Pointer to the PDCP entity to be suspended.
> + * @param[out] out_mb
> + *   The address of an array that can hold up to
> *rte_pdcp_entity.max_pkt_cache*
> + *   pointers to *rte_mbuf* structures.
> + * @return
> + *   -  0: Success and no cached packets to return
> + *   - >0: Success and the number of packets returned in out_mb
> + *   - <0: Error code in case of failures
> + */
> +__rte_experimental
> +int
> +rte_pdcp_entity_suspend(struct rte_pdcp_entity *pdcp_entity,
> +			struct rte_mbuf *out_mb[]);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * For input mbufs and given PDCP entity pre-process the mbufs and prepare
> + * crypto ops that can be enqueued to the cryptodev associated with given
> + * session. Only error packets would be moved returned in the input buffer,
> + * *mb*, and it is the responsibility of the application to free the same.
> + *
> + * @param entity
> + *   Pointer to the *rte_pdcp_entity* object the packets belong to.
> + * @param[in, out] mb
> + *   The address of an array of *num* pointers to *rte_mbuf* structures
> + *   which contain the input packets. Any error packets would be returned in the
> + *   same buffer.
> + * @param[out] cop
> + *   The address of an array that can hold up to *num* pointers to
> + *   *rte_crypto_op* structures. Crypto ops would be allocated by
> + *   ``rte_pdcp_pkt_pre_process`` API.
> + * @param num
> + *   The maximum number of packets to process.
> + * @param[out] nb_err
> + *   Pointer to return the number of error packets returned in *mb*
> + * @return
> + *   Count of crypto_ops prepared
> + */
> +__rte_experimental
> +static inline uint16_t
> +rte_pdcp_pkt_pre_process(const struct rte_pdcp_entity *entity,
> +			 struct rte_mbuf *mb[], struct rte_crypto_op *cop[],
> +			 uint16_t num, uint16_t *nb_err)
> +{
> +	return entity->pre_process(entity, mb, cop, num, nb_err);
> +}
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * For input mbufs and given PDCP entity, perform PDCP post-processing of the
> + * mbufs.
> + *
> + * Input mbufs are the ones retrieved from crypto_ops dequeued from
> cryptodev
> + * and grouped by *rte_pdcp_pkt_crypto_group()*.
> + *
> + * The post-processed packets would be returned in the *out_mb* buffer.
> + * The resultant mbufs would be grouped into success packets and error
> packets.
> + * Error packets would be grouped in the end of the array and it is the
> + * responsibility of the application to handle the same.
> + *
> + * When in-order delivery is enabled, PDCP entity may buffer packets and would
> + * deliver packets only when all prior packets have been post-processed. That
> + * would result in returning more/less packets than enqueued.
> + *
> + * @param entity
> + *   Pointer to the *rte_pdcp_entity* object the packets belong to.
> + * @param in_mb
> + *   The address of an array of *num* pointers to *rte_mbuf* structures.
> + * @param[out] out_mb
> + *   The address of an array of *num* pointers to *rte_mbuf* structures
> + *   to output packets after PDCP post-processing.
> + * @param num
> + *   The maximum number of packets to process.
> + * @param[out] nb_err
> + *   The number of error packets returned in *out_mb* buffer.
> + * @return
> + *   Count of packets returned in *out_mb* buffer.
> + */
> +__rte_experimental
> +static inline uint16_t
> +rte_pdcp_pkt_post_process(const struct rte_pdcp_entity *entity,
> +			  struct rte_mbuf *in_mb[],
> +			  struct rte_mbuf *out_mb[],
> +			  uint16_t num, uint16_t *nb_err)
> +{
> +	return entity->post_process(entity, in_mb, out_mb, num, nb_err);
> +}
> +
> +#include <rte_pdcp_group.h>
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_PDCP_H_ */
> diff --git a/lib/pdcp/rte_pdcp_group.h b/lib/pdcp/rte_pdcp_group.h
> new file mode 100644
> index 0000000000..2c01c19d4e
> --- /dev/null
> +++ b/lib/pdcp/rte_pdcp_group.h
> @@ -0,0 +1,133 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2022 Marvell.
> + */
> +
> +#ifndef _RTE_PDCP_GROUP_H_
> +#define _RTE_PDCP_GROUP_H_
> +
> +/**
> + * @file rte_pdcp_group.h
> + *
> + * RTE PDCP grouping support.
> + * It is not recommended to include this file directly, include <rte_pdcp.h>
> + * instead.
> + * Provides helper functions to process completed crypto-ops and group
> related
> + * packets by sessions they belong to.
> + */
> +
> +#include <rte_common.h>
> +#include <rte_crypto.h>
> +#include <rte_cryptodev.h>
> +#include <rte_security.h>

Remove header files which are not needed.

> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/**
> + * Group packets belonging to same PDCP entity.
> + */
> +struct rte_pdcp_group {
> +	union {
> +		uint64_t val;
> +		void *ptr;
> +	} id; /**< Grouped by value */
> +	struct rte_mbuf **m;  /**< Start of the group */
> +	uint32_t cnt;         /**< Number of entries in the group */
> +	int32_t rc;           /**< Status code associated with the group */
> +};
> +
> +/**
> + * Take crypto-op as an input and extract pointer to related PDCP entity.
> + * @param cop
> + *   The address of an input *rte_crypto_op* structure.
> + * @return
> + *   The pointer to the related *rte_pdcp_entity* structure.
> + */
> +static inline struct rte_pdcp_entity *
> +rte_pdcp_en_from_cop(const struct rte_crypto_op *cop)
> +{
> +	void *sess = cop->sym[0].session;
> +
> +	if (cop->sess_type == RTE_CRYPTO_OP_SECURITY_SESSION) {
> +		return (struct rte_pdcp_entity *)(uintptr_t)
> +			rte_security_session_opaque_data_get(sess);
> +	} else if (cop->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
> +		return (struct rte_pdcp_entity *)(uintptr_t)
> +			rte_cryptodev_sym_session_opaque_data_get(sess);
> +	}

This patchset is not supporting security sessions, so it would be better to return NULL for that.
Moreover, we can directly call rte_cryptodev_sym_session_opaque_data_get(cop->sym[0].session)
From rte_pdcp_pkt_crypto_group. No need to have a wrapper.

> +
> +	return NULL;
> +}
> +
> +/**
> + * Take as input completed crypto ops, extract related mbufs and group them
> by
> + * *rte_pdcp_entity* they belong to. Mbuf for which the crypto operation has
> + * failed would be flagged using *RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED*
> flag
> + * in rte_mbuf.ol_flags. The crypto_ops would be freed after the grouping.
> + *
> + * Note that application must ensure only crypto-ops prepared by lib_pdcp is
> + * provided back to @see rte_pdcp_pkt_crypto_group().
> + *
> + * @param cop
> + *   The address of an array of *num* pointers to the input *rte_crypto_op*
> + *   structures.
> + * @param[out] mb
> + *   The address of an array of *num* pointers to output *rte_mbuf* structures.
> + * @param[out] grp
> + *   The address of an array of *num* to output *rte_pdcp_group* structures.
> + * @param num
> + *   The maximum number of crypto-ops to process.
> + * @return
> + *   Number of filled elements in *grp* array.
> + *
> + */
> +static inline uint16_t
> +rte_pdcp_pkt_crypto_group(struct rte_crypto_op *cop[], struct rte_mbuf
> *mb[],
> +			  struct rte_pdcp_group grp[], uint16_t num)
> +{
> +	uint32_t i, j = 0, n = 0;
> +	void *ns, *ps = NULL;
> +	struct rte_mbuf *m;
> +
> +	for (i = 0; i != num; i++) {
> +		m = cop[i]->sym[0].m_src;
> +		ns = cop[i]->sym[0].session;
> +
> +		m->ol_flags |= RTE_MBUF_F_RX_SEC_OFFLOAD;
> +		if (cop[i]->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
> +			m->ol_flags |=
> RTE_MBUF_F_RX_SEC_OFFLOAD_FAILED;
> +
> +		/* Different entity */
> +		if (ps != ns) {
> +
> +			/* Finalize open group and start a new one */
> +			if (ps != NULL) {
> +				grp[n].cnt = mb + j - grp[n].m;
> +				n++;
> +			}
> +
> +			/* Start new group */
> +			grp[n].m = mb + j;
> +			ps = ns;
> +			grp[n].id.ptr =	rte_pdcp_en_from_cop(cop[i]);
> +		}
> +
> +		mb[j++] = m;
> +		rte_crypto_op_free(cop[i]);
> +	}
> +
> +	/* Finalize last group */
> +	if (ps != NULL) {
> +		grp[n].cnt = mb + j - grp[n].m;
> +		n++;
> +	}
> +
> +	return n;
> +}
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif /* _RTE_PDCP_GROUP_H_ */
> diff --git a/lib/pdcp/version.map b/lib/pdcp/version.map
> new file mode 100644
> index 0000000000..8fa9d5d7cc
> --- /dev/null
> +++ b/lib/pdcp/version.map
> @@ -0,0 +1,13 @@
> +EXPERIMENTAL {
> +	global:
> +
> +	# added in 22.11

Change to 23.03

> +	rte_pdcp_entity_establish;
> +	rte_pdcp_entity_release;
> +	rte_pdcp_entity_suspend;
> +
> +	rte_pdcp_pkt_post_process;
> +	rte_pdcp_pkt_pre_process;
> +
> +	local: *;
> +};
> --
> 2.25.1


  reply	other threads:[~2023-01-18 16:26 UTC|newest]

Thread overview: 192+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-27  5:21 [RFC 0/1] " Anoob Joseph
2022-10-27  5:21 ` [RFC 1/1] " Anoob Joseph
2022-12-13  7:01 ` [RFC 0/1] " Akhil Goyal
2022-12-20 12:15   ` Anoob Joseph
2022-12-22  9:25 ` [PATCH 0/5] " Anoob Joseph
2022-12-22  9:25   ` [PATCH 1/5] net: add PDCP header Anoob Joseph
2023-01-18 16:36     ` Thomas Monjalon
2023-01-18 17:39       ` [EXT] " Anoob Joseph
2023-01-19  8:05         ` Thomas Monjalon
2023-01-23  9:21           ` Anoob Joseph
2023-01-23 15:31             ` Thomas Monjalon
2022-12-22  9:25   ` [PATCH 2/5] lib: add pdcp protocol Anoob Joseph
2023-01-18 16:26     ` Akhil Goyal [this message]
2023-02-13 10:59       ` Anoob Joseph
2022-12-22  9:25   ` [PATCH 3/5] app/test: add lib pdcp tests Anoob Joseph
2022-12-22  9:25   ` [PATCH 4/5] app/test: pdcp HFN tests in combined mode Anoob Joseph
2022-12-22  9:25   ` [PATCH 5/5] doc: add PDCP library guide Anoob Joseph
2023-01-18 16:39   ` [PATCH 0/5] lib: add pdcp protocol Thomas Monjalon
2023-01-23 17:36     ` Jerin Jacob
2023-04-14 17:44   ` [PATCH v2 00/22] " Anoob Joseph
2023-04-14 17:44     ` [PATCH v2 01/22] net: add PDCP header Anoob Joseph
2023-05-16 14:02       ` Akhil Goyal
2023-04-14 17:44     ` [PATCH v2 02/22] lib: add pdcp protocol Anoob Joseph
2023-05-16 15:30       ` Akhil Goyal
2023-05-18  6:53         ` Anoob Joseph
2023-05-18  7:40           ` Akhil Goyal
2023-05-18  8:32             ` Anoob Joseph
2023-05-18  8:46               ` Akhil Goyal
2023-05-22  7:03                 ` Anoob Joseph
2023-04-14 17:44     ` [PATCH v2 03/22] pdcp: add pre and post-process Anoob Joseph
2023-05-16 15:43       ` Akhil Goyal
2023-04-14 17:44     ` [PATCH v2 04/22] pdcp: add packet group Anoob Joseph
2023-05-16 15:56       ` Akhil Goyal
2023-05-18  8:12         ` Anoob Joseph
2023-04-14 17:44     ` [PATCH v2 05/22] pdcp: add crypto session create and destroy Anoob Joseph
2023-05-16 16:21       ` Akhil Goyal
2023-04-14 17:44     ` [PATCH v2 06/22] pdcp: add pre and post process for UL Anoob Joseph
2023-05-18  6:38       ` Akhil Goyal
2023-04-14 17:44     ` [PATCH v2 07/22] pdcp: add pre and post process for DL Anoob Joseph
2023-05-18  6:47       ` Akhil Goyal
2023-05-18  7:33         ` Anoob Joseph
2023-04-14 17:44     ` [PATCH v2 08/22] pdcp: add IV generation routines Anoob Joseph
2023-05-18  6:51       ` Akhil Goyal
2023-04-14 17:44     ` [PATCH v2 09/22] app/test: add lib pdcp tests Anoob Joseph
2023-05-18  8:03       ` Akhil Goyal
2023-05-18 11:31         ` Anoob Joseph
2023-05-18 12:06           ` Akhil Goyal
2023-05-19 10:31             ` Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 10/22] test/pdcp: pdcp HFN tests in combined mode Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 11/22] doc: add PDCP library guide Anoob Joseph
2023-05-18  8:26       ` Akhil Goyal
2023-05-22 10:22         ` Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 12/22] pdcp: add control PDU handling Anoob Joseph
2023-05-18  9:15       ` Akhil Goyal
2023-05-22 11:09         ` Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 13/22] pdcp: implement t-Reordering and packet buffering Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 14/22] test/pdcp: add in-order delivery cases Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 15/22] pdcp: add timer callback handlers Anoob Joseph
2023-05-18  9:37       ` Akhil Goyal
2023-04-14 17:45     ` [PATCH v2 16/22] pdcp: add timer expiry handle Anoob Joseph
2023-05-18  9:43       ` Akhil Goyal
2023-05-22 11:34         ` Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 17/22] test/pdcp: add timer expiry cases Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 18/22] test/pdcp: add timer restart case Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 19/22] pdcp: add support for status report Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 20/22] pdcp: allocate reorder buffer alongside with entity Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 21/22] pdcp: add thread safe processing Anoob Joseph
2023-04-14 17:45     ` [PATCH v2 22/22] test/pdcp: add PDCP status report cases Anoob Joseph
2023-05-24 16:00     ` [PATCH v3 00/22] lib: add pdcp protocol Anoob Joseph
2023-05-24 16:00       ` [PATCH v3 01/22] net: add PDCP header Anoob Joseph
2023-05-24 16:00       ` [PATCH v3 02/22] lib: add pdcp protocol Anoob Joseph
2023-05-24 16:00       ` [PATCH v3 03/22] pdcp: add pre and post-process Anoob Joseph
2023-05-24 16:00       ` [PATCH v3 04/22] pdcp: add packet group Anoob Joseph
2023-05-24 16:00       ` [PATCH v3 05/22] pdcp: add crypto session create and destroy Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 06/22] pdcp: add pre and post process for UL Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 07/22] pdcp: add pre and post process for DL Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 08/22] pdcp: add IV generation routines Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 09/22] app/test: add lib pdcp tests Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 10/22] test/pdcp: pdcp HFN tests in combined mode Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 11/22] doc: add PDCP library guide Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 12/22] pdcp: add control PDU handling for status report Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 13/22] pdcp: implement t-Reordering and packet buffering Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 14/22] test/pdcp: add in-order delivery cases Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 15/22] pdcp: add timer callback handlers Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 16/22] pdcp: add timer expiry handle Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 17/22] test/pdcp: add timer expiry cases Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 18/22] test/pdcp: add timer restart case Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 19/22] pdcp: add support for status report Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 20/22] pdcp: allocate reorder buffer alongside with entity Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 21/22] pdcp: add thread safe processing Anoob Joseph
2023-05-24 18:31         ` Stephen Hemminger
2023-05-25  8:15           ` [EXT] " Anoob Joseph
2023-05-25 15:25             ` Stephen Hemminger
2023-05-25 15:37               ` Anoob Joseph
2023-05-24 16:01       ` [PATCH v3 22/22] test/pdcp: add PDCP status report cases Anoob Joseph
2023-05-26 21:01       ` [PATCH v4 00/22] lib: add pdcp protocol Anoob Joseph
2023-05-26 21:01         ` [PATCH v4 01/22] net: add PDCP header Anoob Joseph
2023-05-26 21:01         ` [PATCH v4 02/22] lib: add pdcp protocol Anoob Joseph
2023-05-26 21:01         ` [PATCH v4 03/22] pdcp: add pre and post-process Anoob Joseph
2023-05-26 21:01         ` [PATCH v4 04/22] pdcp: add packet group Anoob Joseph
2023-05-26 21:01         ` [PATCH v4 05/22] pdcp: add crypto session create and destroy Anoob Joseph
2023-05-26 21:01         ` [PATCH v4 06/22] pdcp: add pre and post process for UL Anoob Joseph
2023-05-26 21:01         ` [PATCH v4 07/22] pdcp: add pre and post process for DL Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 08/22] pdcp: add IV generation routines Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 09/22] app/test: add lib pdcp tests Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 10/22] test/pdcp: pdcp HFN tests in combined mode Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 11/22] doc: add PDCP library guide Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 12/22] pdcp: add control PDU handling for status report Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 13/22] pdcp: implement t-Reordering and packet buffering Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 14/22] test/pdcp: add in-order delivery cases Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 15/22] pdcp: add timer callback handlers Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 16/22] pdcp: add timer expiry handle Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 17/22] test/pdcp: add timer expiry cases Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 18/22] test/pdcp: add timer restart case Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 19/22] pdcp: add support for status report Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 20/22] pdcp: allocate reorder buffer alongside with entity Anoob Joseph
2023-05-26 21:02         ` [PATCH v4 21/22] pdcp: add thread safe processing Anoob Joseph
2023-05-26 22:11           ` Stephen Hemminger
2023-05-27  5:24             ` [EXT] " Anoob Joseph
2023-05-27  7:17               ` Anoob Joseph
2023-05-26 22:15           ` Stephen Hemminger
2023-05-26 21:02         ` [PATCH v4 22/22] test/pdcp: add PDCP status report cases Anoob Joseph
2023-05-27  7:15         ` [PATCH v5 00/21] lib: add pdcp protocol Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 01/21] net: add PDCP header Anoob Joseph
2023-05-30  8:51             ` Akhil Goyal
2023-05-27  7:15           ` [PATCH v5 02/21] lib: add pdcp protocol Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 03/21] pdcp: add pre and post-process Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 04/21] pdcp: add packet group Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 05/21] pdcp: add crypto session create and destroy Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 06/21] pdcp: add pre and post process for UL Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 07/21] pdcp: add pre and post process for DL Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 08/21] pdcp: add IV generation routines Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 09/21] app/test: add lib pdcp tests Anoob Joseph
2023-05-27  7:15           ` [PATCH v5 10/21] test/pdcp: pdcp HFN tests in combined mode Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 11/21] doc: add PDCP library guide Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 12/21] pdcp: add control PDU handling for status report Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 13/21] pdcp: implement t-Reordering and packet buffering Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 14/21] test/pdcp: add in-order delivery cases Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 15/21] pdcp: add timer callback handlers Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 16/21] pdcp: add timer expiry handle Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 17/21] test/pdcp: add timer expiry cases Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 18/21] test/pdcp: add timer restart case Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 19/21] pdcp: add support for status report Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 20/21] pdcp: allocate reorder buffer alongside with entity Anoob Joseph
2023-05-27  7:16           ` [PATCH v5 21/21] test/pdcp: add PDCP status report cases Anoob Joseph
2023-05-27  8:58         ` [PATCH v5 00/21] lib: add pdcp protocol Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 01/21] net: add PDCP header Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 02/21] lib: add pdcp protocol Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 03/21] pdcp: add pre and post-process Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 04/21] pdcp: add packet group Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 05/21] pdcp: add crypto session create and destroy Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 06/21] pdcp: add pre and post process for UL Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 07/21] pdcp: add pre and post process for DL Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 08/21] pdcp: add IV generation routines Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 09/21] app/test: add lib pdcp tests Anoob Joseph
2023-05-27  8:58           ` [PATCH v5 10/21] test/pdcp: pdcp HFN tests in combined mode Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 11/21] doc: add PDCP library guide Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 12/21] pdcp: add control PDU handling for status report Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 13/21] pdcp: implement t-Reordering and packet buffering Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 14/21] test/pdcp: add in-order delivery cases Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 15/21] pdcp: add timer callback handlers Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 16/21] pdcp: add timer expiry handle Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 17/21] test/pdcp: add timer expiry cases Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 18/21] test/pdcp: add timer restart case Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 19/21] pdcp: add support for status report Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 20/21] pdcp: allocate reorder buffer alongside with entity Anoob Joseph
2023-05-27  8:59           ` [PATCH v5 21/21] test/pdcp: add PDCP status report cases Anoob Joseph
2023-05-30 10:01           ` [PATCH v6 00/21] lib: add pdcp protocol Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 01/21] net: add PDCP header Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 02/21] lib: add pdcp protocol Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 03/21] pdcp: add pre and post-process Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 04/21] pdcp: add packet group Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 05/21] pdcp: add crypto session create and destroy Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 06/21] pdcp: add pre and post process for UL Anoob Joseph
2023-06-10 22:50               ` Thomas Monjalon
2023-06-12  5:19                 ` [EXT] " Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 07/21] pdcp: add pre and post process for DL Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 08/21] pdcp: add IV generation routines Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 09/21] app/test: add lib pdcp tests Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 10/21] test/pdcp: pdcp HFN tests in combined mode Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 11/21] doc: add PDCP library guide Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 12/21] pdcp: add control PDU handling for status report Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 13/21] pdcp: implement t-Reordering and packet buffering Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 14/21] test/pdcp: add in-order delivery cases Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 15/21] pdcp: add timer callback handlers Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 16/21] pdcp: add timer expiry handle Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 17/21] test/pdcp: add timer expiry cases Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 18/21] test/pdcp: add timer restart case Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 19/21] pdcp: add support for status report Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 20/21] pdcp: allocate reorder buffer alongside with entity Anoob Joseph
2023-05-30 10:01             ` [PATCH v6 21/21] test/pdcp: add PDCP status report cases Anoob Joseph
2023-06-01  8:47             ` [PATCH v6 00/21] lib: add pdcp protocol Akhil Goyal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CO6PR18MB4484FD2705D3C473A56E8985D8C79@CO6PR18MB4484.namprd18.prod.outlook.com \
    --to=gakhil@marvell.com \
    --cc=anoobj@marvell.com \
    --cc=bernard.iremonger@intel.com \
    --cc=dev@dpdk.org \
    --cc=hemant.agrawal@nxp.com \
    --cc=jerinj@marvell.com \
    --cc=kirankumark@marvell.com \
    --cc=konstantin.v.ananyev@yandex.ru \
    --cc=mattias.ronnblom@ericsson.com \
    --cc=olivier.matz@6wind.com \
    --cc=thomas@monjalon.net \
    --cc=vfialko@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).