> Subject: [PATCH v2 12/22] pdcp: add control PDU handling > > Add control PDU handling and implement status report generation. Status > report generation works only when RX_DELIV = RX_NEXT. > > Signed-off-by: Anoob Joseph <ano...@marvell.com> > Signed-off-by: Volodymyr Fialko <vfia...@marvell.com> > --- > app/test/test_pdcp.c | 1 +
Separate out test app changes from library changes. > doc/guides/prog_guide/pdcp_lib.rst | 10 +++++++ > lib/pdcp/meson.build | 2 ++ > lib/pdcp/pdcp_cnt.c | 29 ++++++++++++++++++ > lib/pdcp/pdcp_cnt.h | 14 +++++++++ > lib/pdcp/pdcp_ctrl_pdu.c | 46 +++++++++++++++++++++++++++++ > lib/pdcp/pdcp_ctrl_pdu.h | 15 ++++++++++ > lib/pdcp/pdcp_entity.h | 15 ++++++++-- > lib/pdcp/pdcp_process.c | 13 +++++++++ > lib/pdcp/rte_pdcp.c | 47 +++++++++++++++++++++++++++++- > lib/pdcp/rte_pdcp.h | 31 ++++++++++++++++++++ > lib/pdcp/version.map | 2 ++ > 12 files changed, 222 insertions(+), 3 deletions(-) > create mode 100644 lib/pdcp/pdcp_cnt.c > create mode 100644 lib/pdcp/pdcp_cnt.h > create mode 100644 lib/pdcp/pdcp_ctrl_pdu.c > create mode 100644 lib/pdcp/pdcp_ctrl_pdu.h > > diff --git a/app/test/test_pdcp.c b/app/test/test_pdcp.c > index fc49947ba2..4ecb4d9572 100644 > --- a/app/test/test_pdcp.c > +++ b/app/test/test_pdcp.c > @@ -415,6 +415,7 @@ create_test_conf_from_index(const int index, struct > pdcp_test_conf *conf) > > conf->entity.sess_mpool = ts_params->sess_pool; > conf->entity.cop_pool = ts_params->cop_pool; > + conf->entity.ctr_pdu_pool = ts_params->mbuf_pool; > conf->entity.pdcp_xfrm.bearer = pdcp_test_bearer[index]; > conf->entity.pdcp_xfrm.en_ordering = 0; > conf->entity.pdcp_xfrm.remove_duplicates = 0; > diff --git a/doc/guides/prog_guide/pdcp_lib.rst > b/doc/guides/prog_guide/pdcp_lib.rst > index abd874f2cc..f23360dfc3 100644 > --- a/doc/guides/prog_guide/pdcp_lib.rst > +++ b/doc/guides/prog_guide/pdcp_lib.rst > @@ -67,6 +67,15 @@ Data PDUs are regular packets submitted by upper layers > for transmission to > other end. Such packets would need to be ciphered and authenticated based on > the entity configuration. > > +PDCP packet processing API for control PDU > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +Control PDUs are used in PDCP as a communication channel between > transmitting > +and receiving entities. When upper layer request for operations such > +re-establishment, receiving PDCP entity need to prepare a status report and > +send it to the other end. The API ``pdcp_ctrl_pdu_status_gen`` allows > +application to request the same. pdcp_ctrl_pdu_status_gen() - Is this a user visible API? I believe it is not exposed. How can application request that? > + > PDCP packet processing API for data PDU > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > @@ -228,6 +237,7 @@ Supported features > - Uplink & downlink traffic > - HFN increment > - IV generation as required per algorithm > +- Control PDU generation > > Supported ciphering algorithms > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > diff --git a/lib/pdcp/meson.build b/lib/pdcp/meson.build > index 08679b743a..75d476bf6d 100644 > --- a/lib/pdcp/meson.build > +++ b/lib/pdcp/meson.build > @@ -8,7 +8,9 @@ if is_windows > endif > > sources = files( > + 'pdcp_cnt.c', pdcp_cnt seems to be something related to count. And it is not related to this patch probably. > 'pdcp_crypto.c', > + 'pdcp_ctrl_pdu.c', > 'pdcp_process.c', > 'rte_pdcp.c', > ) > diff --git a/lib/pdcp/pdcp_cnt.c b/lib/pdcp/pdcp_cnt.c > new file mode 100644 > index 0000000000..c9b952184b > --- /dev/null > +++ b/lib/pdcp/pdcp_cnt.c > @@ -0,0 +1,29 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > + > +#include <rte_pdcp.h> > + > +#include "pdcp_cnt.h" > +#include "pdcp_entity.h" > + > +int > +pdcp_cnt_ring_create(struct rte_pdcp_entity *en, const struct > rte_pdcp_entity_conf *conf) > +{ > + struct entity_priv_dl_part *en_priv_dl; > + uint32_t window_sz; > + > + if (en == NULL || conf == NULL) > + return -EINVAL; > + > + if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK) > + return 0; > + > + en_priv_dl = entity_dl_part_get(en); > + window_sz = pdcp_window_size_get(conf->pdcp_xfrm.sn_size); > + > + RTE_SET_USED(window_sz); > + RTE_SET_USED(en_priv_dl); > + > + return 0; > +} > diff --git a/lib/pdcp/pdcp_cnt.h b/lib/pdcp/pdcp_cnt.h > new file mode 100644 > index 0000000000..bbda478b55 > --- /dev/null > +++ b/lib/pdcp/pdcp_cnt.h > @@ -0,0 +1,14 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > + > +#ifndef PDCP_CNT_H > +#define PDCP_CNT_H > + > +#include <rte_common.h> > + > +#include "pdcp_entity.h" > + > +int pdcp_cnt_ring_create(struct rte_pdcp_entity *en, const struct > rte_pdcp_entity_conf *conf); > + > +#endif /* PDCP_CNT_H */ > diff --git a/lib/pdcp/pdcp_ctrl_pdu.c b/lib/pdcp/pdcp_ctrl_pdu.c > new file mode 100644 > index 0000000000..feb05fd863 > --- /dev/null > +++ b/lib/pdcp/pdcp_ctrl_pdu.c > @@ -0,0 +1,46 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > + > +#include <rte_byteorder.h> > +#include <rte_mbuf.h> > +#include <rte_pdcp_hdr.h> > + > +#include "pdcp_ctrl_pdu.h" > +#include "pdcp_entity.h" > + > +static __rte_always_inline void > +pdcp_hdr_fill(struct rte_pdcp_up_ctrl_pdu_hdr *pdu_hdr, uint32_t rx_deliv) > +{ > + pdu_hdr->d_c = RTE_PDCP_PDU_TYPE_CTRL; > + pdu_hdr->pdu_type = RTE_PDCP_CTRL_PDU_TYPE_STATUS_REPORT; > + pdu_hdr->r = 0; > + pdu_hdr->fmc = rte_cpu_to_be_32(rx_deliv); > +} > + > +int > +pdcp_ctrl_pdu_status_gen(struct entity_priv *en_priv, struct rte_mbuf *m) > +{ > + struct rte_pdcp_up_ctrl_pdu_hdr *pdu_hdr; > + uint32_t rx_deliv; > + int pdu_sz; > + > + if (!en_priv->flags.is_status_report_required) > + return -EINVAL; > + > + pdu_sz = sizeof(struct rte_pdcp_up_ctrl_pdu_hdr); > + > + rx_deliv = en_priv->state.rx_deliv; > + > + /* Zero missing PDUs - status report contains only FMC */ > + if (rx_deliv >= en_priv->state.rx_next) { > + pdu_hdr = (struct rte_pdcp_up_ctrl_pdu_hdr > *)rte_pktmbuf_append(m, pdu_sz); > + if (pdu_hdr == NULL) > + return -ENOMEM; > + pdcp_hdr_fill(pdu_hdr, rx_deliv); > + > + return 0; > + } > + > + return -ENOTSUP; > +} > diff --git a/lib/pdcp/pdcp_ctrl_pdu.h b/lib/pdcp/pdcp_ctrl_pdu.h > new file mode 100644 > index 0000000000..a2424fbd10 > --- /dev/null > +++ b/lib/pdcp/pdcp_ctrl_pdu.h > @@ -0,0 +1,15 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2023 Marvell. > + */ > + > +#ifndef PDCP_CTRL_PDU_H > +#define PDCP_CTRL_PDU_H > + > +#include <rte_mbuf.h> > + > +#include "pdcp_entity.h" > + > +int > +pdcp_ctrl_pdu_status_gen(struct entity_priv *en_priv, struct rte_mbuf *m); > + > +#endif /* PDCP_CTRL_PDU_H */ > diff --git a/lib/pdcp/pdcp_entity.h b/lib/pdcp/pdcp_entity.h > index 3108795977..7b7e7f69dd 100644 > --- a/lib/pdcp/pdcp_entity.h > +++ b/lib/pdcp/pdcp_entity.h > @@ -109,6 +109,13 @@ union cipher_iv_partial { > uint64_t u64[2]; > }; > > +struct pdcp_cnt_bitmap { > + /** Number of entries that can be stored. */ > + uint32_t size; > + /** Bitmap of the count values already received.*/ > + struct rte_bitmap *bmp; > +}; This pdcp_cnt_bitmap is not related to control PDU. Right? I believe the patch split is not proper here. > + > /* > * Layout of PDCP entity: [rte_pdcp_entity] [entity_priv] [entity_dl/ul] > */ > @@ -136,9 +143,13 @@ struct entity_priv { > uint64_t is_ul_entity : 1; > /** Is NULL auth. */ > uint64_t is_null_auth : 1; > + /** Is status report required.*/ > + uint64_t is_status_report_required : 1; > } flags; > /** Crypto op pool. */ > struct rte_mempool *cop_pool; > + /** Control PDU pool. */ > + struct rte_mempool *ctr_pdu_pool; > /** PDCP header size. */ > uint8_t hdr_sz; > /** PDCP AAD size. For AES-CMAC, additional message is prepended for > the operation. */ > @@ -148,8 +159,8 @@ struct entity_priv { > }; > > struct entity_priv_dl_part { > - /* NOTE: when in-order-delivery is supported, post PDCP packets would > need to cached. */ > - uint8_t dummy; > + /** PDCP would need to track the count values that are already > received.*/ > + struct pdcp_cnt_bitmap bitmap; > }; > > struct entity_priv_ul_part { > diff --git a/lib/pdcp/pdcp_process.c b/lib/pdcp/pdcp_process.c > index 9c1a5e0669..267b3b7723 100644 > --- a/lib/pdcp/pdcp_process.c > +++ b/lib/pdcp/pdcp_process.c > @@ -1157,6 +1157,19 @@ pdcp_entity_priv_populate(struct entity_priv > *en_priv, const struct rte_pdcp_ent > if (a_xfrm != NULL && a_xfrm->auth.algo == > RTE_CRYPTO_AUTH_NULL) > en_priv->flags.is_null_auth = 1; > > + /** > + * flags.is_status_report_required > + * > + * Indicate whether status report is required. > + */ > + if (conf->status_report_required) { > + /** Status report is required only for DL entities. */ > + if (conf->pdcp_xfrm.pkt_dir != > RTE_SECURITY_PDCP_DOWNLINK) > + return -EINVAL; > + > + en_priv->flags.is_status_report_required = 1; > + } > + > /** > * hdr_sz > * > diff --git a/lib/pdcp/rte_pdcp.c b/lib/pdcp/rte_pdcp.c > index 8914548dbd..5cd3f5ca31 100644 > --- a/lib/pdcp/rte_pdcp.c > +++ b/lib/pdcp/rte_pdcp.c > @@ -6,7 +6,9 @@ > #include <rte_pdcp.h> > #include <rte_malloc.h> > > +#include "pdcp_cnt.h" > #include "pdcp_crypto.h" > +#include "pdcp_ctrl_pdu.h" > #include "pdcp_entity.h" > #include "pdcp_process.h" > > @@ -34,7 +36,7 @@ rte_pdcp_entity_establish(const struct > rte_pdcp_entity_conf *conf) > struct entity_priv *en_priv; > int ret, entity_size; > > - if (conf == NULL || conf->cop_pool == NULL) { > + if (conf == NULL || conf->cop_pool == NULL || conf->ctr_pdu_pool == > NULL) { > rte_errno = -EINVAL; > return NULL; > } > @@ -79,6 +81,7 @@ rte_pdcp_entity_establish(const struct > rte_pdcp_entity_conf *conf) > en_priv->state.rx_deliv = conf->count; > en_priv->state.tx_next = conf->count; > en_priv->cop_pool = conf->cop_pool; > + en_priv->ctr_pdu_pool = conf->ctr_pdu_pool; > > /* Setup crypto session */ > ret = pdcp_crypto_sess_create(entity, conf); > @@ -89,6 +92,10 @@ rte_pdcp_entity_establish(const struct > rte_pdcp_entity_conf *conf) > if (ret) > goto crypto_sess_destroy; > > + ret = pdcp_cnt_ring_create(entity, conf); > + if (ret) > + goto crypto_sess_destroy; > + > return entity; > > crypto_sess_destroy: > @@ -136,3 +143,41 @@ rte_pdcp_entity_suspend(struct rte_pdcp_entity > *pdcp_entity, > > return 0; > } > + > +struct rte_mbuf * > +rte_pdcp_control_pdu_create(struct rte_pdcp_entity *pdcp_entity, > + enum rte_pdcp_ctrl_pdu_type type) > +{ > + struct entity_priv *en_priv; > + struct rte_mbuf *m; > + int ret; > + > + if (pdcp_entity == NULL) { > + rte_errno = -EINVAL; rte_errno should be positive values. > + return NULL; > + } > + > + en_priv = entity_priv_get(pdcp_entity); > + > + m = rte_pktmbuf_alloc(en_priv->ctr_pdu_pool); > + if (m == NULL) { > + rte_errno = -ENOMEM; > + return NULL; > + } > + > + switch (type) { > + case RTE_PDCP_CTRL_PDU_TYPE_STATUS_REPORT: > + ret = pdcp_ctrl_pdu_status_gen(en_priv, m); > + break; > + default: > + ret = -ENOTSUP; > + } > + > + if (ret) { > + rte_pktmbuf_free(m); > + rte_errno = ret; > + return NULL; > + } > + > + return m; > +} > diff --git a/lib/pdcp/rte_pdcp.h b/lib/pdcp/rte_pdcp.h > index 54f88e3fd3..d2db25d7d9 100644 > --- a/lib/pdcp/rte_pdcp.h > +++ b/lib/pdcp/rte_pdcp.h > @@ -16,6 +16,7 @@ > #include <rte_compat.h> > #include <rte_common.h> > #include <rte_mempool.h> > +#include <rte_pdcp_hdr.h> > #include <rte_security.h> > > #ifdef __cplusplus > @@ -78,6 +79,8 @@ struct rte_pdcp_entity_conf { > struct rte_mempool *sess_mpool; > /** Crypto op pool.*/ > struct rte_mempool *cop_pool; > + /** Mbuf pool to be used for allocating control PDUs.*/ > + struct rte_mempool *ctr_pdu_pool; Please use same prefix for all control pdu stuff. I see cnt, ctr, ctrl, control is being used. I think "control" for top level API and "ctrl" for parameters should be fine. > /** > * 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. > @@ -91,6 +94,15 @@ struct rte_pdcp_entity_conf { > uint8_t dev_id; > /** Reverse direction during IV generation. Can be used to simulate UE > crypto processing.*/ > bool reverse_iv_direction; > + /** > + * Status report required (specified in TS 38.331). > + * > + * If PDCP entity is configured to send a PDCP status report, the upper > layer application > + * may request a receiving PDCP entity to generate a PDCP status report > using > + * ``rte_pdcp_ctrl_pdu_create``. In addition, PDCP status reports may be > generated during > + * operations such as entity re-establishment. > + */ > + bool status_report_required; rte_pdcp_ctrl_pdu_create -> rte_pdcp_control_pdu_create Please specify that a PDU will be generated for status report. Otherwise, it seems some structure would be returned for status report But there is no mention of that. This will avoid confusion. > }; > /* >8 End of structure rte_pdcp_entity_conf. */ > > @@ -169,6 +181,25 @@ 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 > + * > + * Create control PDU packet of the `type` specified. > + * > + * @param pdcp_entity > + * Pointer to the PDCP entity for which the control PDU need to be > generated. > + * @param type > + * Type of control PDU to be generated. > + * @return > + * - Control PDU generated, in case of success. > + * - NULL in case of failure. rte_errno will be set to error code. > + */ > +__rte_experimental > +struct rte_mbuf * > +rte_pdcp_control_pdu_create(struct rte_pdcp_entity *pdcp_entity, > + enum rte_pdcp_ctrl_pdu_type type); > + > /** > * @warning > * @b EXPERIMENTAL: this API may change without prior notice > diff --git a/lib/pdcp/version.map b/lib/pdcp/version.map > index f9ff30600a..d0cf338e1f 100644 > --- a/lib/pdcp/version.map > +++ b/lib/pdcp/version.map > @@ -6,6 +6,8 @@ EXPERIMENTAL { > rte_pdcp_entity_release; > rte_pdcp_entity_suspend; > > + rte_pdcp_control_pdu_create; > + > rte_pdcp_pkt_post_process; > rte_pdcp_pkt_pre_process; > > -- > 2.25.1