xref: /dpdk/lib/pdcp/pdcp_ctrl_pdu.c (revision 7917b0d38e92e8b9ec5a870415b791420e10f11a)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2023 Marvell.
3  */
4 
5 #include <rte_byteorder.h>
6 #include <rte_mbuf.h>
7 #include <rte_pdcp_hdr.h>
8 
9 #include "pdcp_ctrl_pdu.h"
10 #include "pdcp_entity.h"
11 #include "pdcp_cnt.h"
12 
13 static inline uint16_t
14 round_up_bits(uint32_t bits)
15 {
16 	/* round up to the next multiple of 8 */
17 	return RTE_ALIGN_MUL_CEIL(bits, 8) / 8;
18 }
19 
20 static __rte_always_inline void
21 pdcp_hdr_fill(struct rte_pdcp_up_ctrl_pdu_hdr *pdu_hdr, uint32_t rx_deliv)
22 {
23 	pdu_hdr->d_c = RTE_PDCP_PDU_TYPE_CTRL;
24 	pdu_hdr->pdu_type = RTE_PDCP_CTRL_PDU_TYPE_STATUS_REPORT;
25 	pdu_hdr->r = 0;
26 	pdu_hdr->fmc = rte_cpu_to_be_32(rx_deliv);
27 }
28 
29 int
30 pdcp_ctrl_pdu_status_gen(struct entity_priv *en_priv, struct entity_priv_dl_part *dl,
31 			 struct rte_mbuf *m)
32 {
33 	struct rte_pdcp_up_ctrl_pdu_hdr *pdu_hdr;
34 	uint32_t rx_deliv, actual_sz;
35 	uint16_t pdu_sz, bitmap_sz;
36 	uint8_t *data;
37 
38 	if (!en_priv->flags.is_status_report_required)
39 		return -EINVAL;
40 
41 	pdu_sz = sizeof(struct rte_pdcp_up_ctrl_pdu_hdr);
42 
43 	rx_deliv = en_priv->state.rx_deliv;
44 
45 	/* Zero missing PDUs - status report contains only FMC */
46 	if (rx_deliv >= en_priv->state.rx_next) {
47 		pdu_hdr = (struct rte_pdcp_up_ctrl_pdu_hdr *)rte_pktmbuf_append(m, pdu_sz);
48 		if (pdu_hdr == NULL)
49 			return -ENOMEM;
50 		pdcp_hdr_fill(pdu_hdr, rx_deliv);
51 
52 		return 0;
53 	}
54 
55 	actual_sz = RTE_MIN(round_up_bits(en_priv->state.rx_next - rx_deliv - 1),
56 			RTE_PDCP_CTRL_PDU_SIZE_MAX - pdu_sz);
57 	bitmap_sz = pdcp_cnt_get_bitmap_size(actual_sz);
58 
59 	data = (uint8_t *)rte_pktmbuf_append(m, pdu_sz + bitmap_sz);
60 	if (data == NULL)
61 		return -ENOMEM;
62 
63 	m->pkt_len = pdu_sz + actual_sz;
64 	m->data_len = pdu_sz + actual_sz;
65 
66 	pdcp_hdr_fill((struct rte_pdcp_up_ctrl_pdu_hdr *)data, rx_deliv);
67 
68 	data = RTE_PTR_ADD(data, pdu_sz);
69 	pdcp_cnt_report_fill(dl->bitmap, en_priv->state, data, bitmap_sz);
70 
71 	return 0;
72 }
73