xref: /dpdk/lib/pdcp/pdcp_ctrl_pdu.c (revision 37d395316dc335eac09ff6f6d73914ad03c3cb29)
13a3e8931SAnoob Joseph /* SPDX-License-Identifier: BSD-3-Clause
23a3e8931SAnoob Joseph  * Copyright(C) 2023 Marvell.
33a3e8931SAnoob Joseph  */
43a3e8931SAnoob Joseph 
53a3e8931SAnoob Joseph #include <rte_byteorder.h>
63a3e8931SAnoob Joseph #include <rte_mbuf.h>
73a3e8931SAnoob Joseph #include <rte_pdcp_hdr.h>
83a3e8931SAnoob Joseph 
93a3e8931SAnoob Joseph #include "pdcp_ctrl_pdu.h"
103a3e8931SAnoob Joseph #include "pdcp_entity.h"
11*37d39531SVolodymyr Fialko #include "pdcp_cnt.h"
12*37d39531SVolodymyr Fialko 
13*37d39531SVolodymyr Fialko static inline uint16_t
round_up_bits(uint32_t bits)14*37d39531SVolodymyr Fialko round_up_bits(uint32_t bits)
15*37d39531SVolodymyr Fialko {
16*37d39531SVolodymyr Fialko 	/* round up to the next multiple of 8 */
17*37d39531SVolodymyr Fialko 	return RTE_ALIGN_MUL_CEIL(bits, 8) / 8;
18*37d39531SVolodymyr Fialko }
193a3e8931SAnoob Joseph 
203a3e8931SAnoob Joseph static __rte_always_inline void
pdcp_hdr_fill(struct rte_pdcp_up_ctrl_pdu_hdr * pdu_hdr,uint32_t rx_deliv)213a3e8931SAnoob Joseph pdcp_hdr_fill(struct rte_pdcp_up_ctrl_pdu_hdr *pdu_hdr, uint32_t rx_deliv)
223a3e8931SAnoob Joseph {
233a3e8931SAnoob Joseph 	pdu_hdr->d_c = RTE_PDCP_PDU_TYPE_CTRL;
243a3e8931SAnoob Joseph 	pdu_hdr->pdu_type = RTE_PDCP_CTRL_PDU_TYPE_STATUS_REPORT;
253a3e8931SAnoob Joseph 	pdu_hdr->r = 0;
263a3e8931SAnoob Joseph 	pdu_hdr->fmc = rte_cpu_to_be_32(rx_deliv);
273a3e8931SAnoob Joseph }
283a3e8931SAnoob Joseph 
293a3e8931SAnoob Joseph int
pdcp_ctrl_pdu_status_gen(struct entity_priv * en_priv,struct entity_priv_dl_part * dl,struct rte_mbuf * m)30*37d39531SVolodymyr Fialko pdcp_ctrl_pdu_status_gen(struct entity_priv *en_priv, struct entity_priv_dl_part *dl,
31*37d39531SVolodymyr Fialko 			 struct rte_mbuf *m)
323a3e8931SAnoob Joseph {
333a3e8931SAnoob Joseph 	struct rte_pdcp_up_ctrl_pdu_hdr *pdu_hdr;
34*37d39531SVolodymyr Fialko 	uint32_t rx_deliv, actual_sz;
35*37d39531SVolodymyr Fialko 	uint16_t pdu_sz, bitmap_sz;
36*37d39531SVolodymyr Fialko 	uint8_t *data;
373a3e8931SAnoob Joseph 
383a3e8931SAnoob Joseph 	if (!en_priv->flags.is_status_report_required)
393a3e8931SAnoob Joseph 		return -EINVAL;
403a3e8931SAnoob Joseph 
413a3e8931SAnoob Joseph 	pdu_sz = sizeof(struct rte_pdcp_up_ctrl_pdu_hdr);
423a3e8931SAnoob Joseph 
433a3e8931SAnoob Joseph 	rx_deliv = en_priv->state.rx_deliv;
443a3e8931SAnoob Joseph 
453a3e8931SAnoob Joseph 	/* Zero missing PDUs - status report contains only FMC */
463a3e8931SAnoob Joseph 	if (rx_deliv >= en_priv->state.rx_next) {
473a3e8931SAnoob Joseph 		pdu_hdr = (struct rte_pdcp_up_ctrl_pdu_hdr *)rte_pktmbuf_append(m, pdu_sz);
483a3e8931SAnoob Joseph 		if (pdu_hdr == NULL)
493a3e8931SAnoob Joseph 			return -ENOMEM;
503a3e8931SAnoob Joseph 		pdcp_hdr_fill(pdu_hdr, rx_deliv);
513a3e8931SAnoob Joseph 
523a3e8931SAnoob Joseph 		return 0;
533a3e8931SAnoob Joseph 	}
543a3e8931SAnoob Joseph 
55*37d39531SVolodymyr Fialko 	actual_sz = RTE_MIN(round_up_bits(en_priv->state.rx_next - rx_deliv - 1),
56*37d39531SVolodymyr Fialko 			RTE_PDCP_CTRL_PDU_SIZE_MAX - pdu_sz);
57*37d39531SVolodymyr Fialko 	bitmap_sz = pdcp_cnt_get_bitmap_size(actual_sz);
58*37d39531SVolodymyr Fialko 
59*37d39531SVolodymyr Fialko 	data = (uint8_t *)rte_pktmbuf_append(m, pdu_sz + bitmap_sz);
60*37d39531SVolodymyr Fialko 	if (data == NULL)
61*37d39531SVolodymyr Fialko 		return -ENOMEM;
62*37d39531SVolodymyr Fialko 
63*37d39531SVolodymyr Fialko 	m->pkt_len = pdu_sz + actual_sz;
64*37d39531SVolodymyr Fialko 	m->data_len = pdu_sz + actual_sz;
65*37d39531SVolodymyr Fialko 
66*37d39531SVolodymyr Fialko 	pdcp_hdr_fill((struct rte_pdcp_up_ctrl_pdu_hdr *)data, rx_deliv);
67*37d39531SVolodymyr Fialko 
68*37d39531SVolodymyr Fialko 	data = RTE_PTR_ADD(data, pdu_sz);
69*37d39531SVolodymyr Fialko 	pdcp_cnt_report_fill(dl->bitmap, en_priv->state, data, bitmap_sz);
70*37d39531SVolodymyr Fialko 
71*37d39531SVolodymyr Fialko 	return 0;
723a3e8931SAnoob Joseph }
73