xref: /dpdk/lib/pdcp/rte_pdcp.c (revision 08966fe7f79fdaa5019b7559eebe84a1e3787b89)
1a702bd09SAnoob Joseph /* SPDX-License-Identifier: BSD-3-Clause
2a702bd09SAnoob Joseph  * Copyright(C) 2023 Marvell.
3a702bd09SAnoob Joseph  */
4a702bd09SAnoob Joseph 
5*08966fe7STyler Retzlaff #include <stdalign.h>
6*08966fe7STyler Retzlaff 
7a702bd09SAnoob Joseph #include <rte_errno.h>
8a702bd09SAnoob Joseph #include <rte_pdcp.h>
9a702bd09SAnoob Joseph #include <rte_malloc.h>
10a702bd09SAnoob Joseph 
113a3e8931SAnoob Joseph #include "pdcp_cnt.h"
12a702bd09SAnoob Joseph #include "pdcp_crypto.h"
133a3e8931SAnoob Joseph #include "pdcp_ctrl_pdu.h"
14a702bd09SAnoob Joseph #include "pdcp_entity.h"
15a702bd09SAnoob Joseph #include "pdcp_process.h"
16a702bd09SAnoob Joseph 
177741560dSAnoob Joseph #define RTE_PDCP_DYNFIELD_NAME "rte_pdcp_dynfield"
187741560dSAnoob Joseph 
19af42b2d1SVolodymyr Fialko struct entity_layout {
20af42b2d1SVolodymyr Fialko 	size_t bitmap_offset;
21af42b2d1SVolodymyr Fialko 	size_t bitmap_size;
22af42b2d1SVolodymyr Fialko 
23af42b2d1SVolodymyr Fialko 	size_t reorder_buf_offset;
24af42b2d1SVolodymyr Fialko 	size_t reorder_buf_size;
25af42b2d1SVolodymyr Fialko 
26af42b2d1SVolodymyr Fialko 	size_t total_size;
27af42b2d1SVolodymyr Fialko };
2837d39531SVolodymyr Fialko 
297741560dSAnoob Joseph int rte_pdcp_dynfield_offset = -1;
307741560dSAnoob Joseph 
317741560dSAnoob Joseph static int
pdcp_dynfield_register(void)327741560dSAnoob Joseph pdcp_dynfield_register(void)
337741560dSAnoob Joseph {
347741560dSAnoob Joseph 	const struct rte_mbuf_dynfield dynfield_desc = {
357741560dSAnoob Joseph 		.name = RTE_PDCP_DYNFIELD_NAME,
367741560dSAnoob Joseph 		.size = sizeof(rte_pdcp_dynfield_t),
37*08966fe7STyler Retzlaff 		.align = alignof(rte_pdcp_dynfield_t),
387741560dSAnoob Joseph 	};
397741560dSAnoob Joseph 
407741560dSAnoob Joseph 	if (rte_pdcp_dynfield_offset != -1)
417741560dSAnoob Joseph 		return rte_pdcp_dynfield_offset;
427741560dSAnoob Joseph 
437741560dSAnoob Joseph 	rte_pdcp_dynfield_offset = rte_mbuf_dynfield_register(&dynfield_desc);
447741560dSAnoob Joseph 	return rte_pdcp_dynfield_offset;
457741560dSAnoob Joseph }
467741560dSAnoob Joseph 
47a702bd09SAnoob Joseph static int
pdcp_entity_layout_get(const struct rte_pdcp_entity_conf * conf,struct entity_layout * layout)48af42b2d1SVolodymyr Fialko pdcp_entity_layout_get(const struct rte_pdcp_entity_conf *conf, struct entity_layout *layout)
49a702bd09SAnoob Joseph {
50af42b2d1SVolodymyr Fialko 	size_t size;
51af42b2d1SVolodymyr Fialko 	const uint32_t window_size = pdcp_window_size_get(conf->pdcp_xfrm.sn_size);
52a702bd09SAnoob Joseph 
53a702bd09SAnoob Joseph 	size = sizeof(struct rte_pdcp_entity) + sizeof(struct entity_priv);
54a702bd09SAnoob Joseph 
5537d39531SVolodymyr Fialko 	if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) {
56a702bd09SAnoob Joseph 		size += sizeof(struct entity_priv_dl_part);
57af42b2d1SVolodymyr Fialko 		/* Bitmap require memory to be cache aligned */
5837d39531SVolodymyr Fialko 		size = RTE_CACHE_LINE_ROUNDUP(size);
59af42b2d1SVolodymyr Fialko 		layout->bitmap_offset = size;
60af42b2d1SVolodymyr Fialko 		layout->bitmap_size = pdcp_cnt_bitmap_get_memory_footprint(conf);
61af42b2d1SVolodymyr Fialko 		size += layout->bitmap_size;
62af42b2d1SVolodymyr Fialko 		layout->reorder_buf_offset = size;
63af42b2d1SVolodymyr Fialko 		layout->reorder_buf_size = pdcp_reorder_memory_footprint_get(window_size);
64af42b2d1SVolodymyr Fialko 		size += layout->reorder_buf_size;
6537d39531SVolodymyr Fialko 	} else if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_UPLINK)
66a702bd09SAnoob Joseph 		size += sizeof(struct entity_priv_ul_part);
67a702bd09SAnoob Joseph 	else
68a702bd09SAnoob Joseph 		return -EINVAL;
69a702bd09SAnoob Joseph 
70af42b2d1SVolodymyr Fialko 	layout->total_size = size;
71af42b2d1SVolodymyr Fialko 
72af42b2d1SVolodymyr Fialko 	return 0;
73a702bd09SAnoob Joseph }
74a702bd09SAnoob Joseph 
75c12cfe62SVolodymyr Fialko static int
pdcp_dl_establish(struct rte_pdcp_entity * entity,const struct rte_pdcp_entity_conf * conf,const struct entity_layout * layout)76af42b2d1SVolodymyr Fialko pdcp_dl_establish(struct rte_pdcp_entity *entity, const struct rte_pdcp_entity_conf *conf,
77af42b2d1SVolodymyr Fialko 		  const struct entity_layout *layout)
78c12cfe62SVolodymyr Fialko {
79c12cfe62SVolodymyr Fialko 	const uint32_t window_size = pdcp_window_size_get(conf->pdcp_xfrm.sn_size);
80c12cfe62SVolodymyr Fialko 	struct entity_priv_dl_part *dl = entity_dl_part_get(entity);
81af42b2d1SVolodymyr Fialko 	void *memory;
8237d39531SVolodymyr Fialko 	int ret;
83c12cfe62SVolodymyr Fialko 
84c12cfe62SVolodymyr Fialko 	entity->max_pkt_cache = RTE_MAX(entity->max_pkt_cache, window_size);
8579576518SVolodymyr Fialko 	dl->t_reorder.handle = conf->t_reordering;
86c12cfe62SVolodymyr Fialko 
87af42b2d1SVolodymyr Fialko 	memory = RTE_PTR_ADD(entity, layout->reorder_buf_offset);
88af42b2d1SVolodymyr Fialko 	ret = pdcp_reorder_create(&dl->reorder, window_size, memory, layout->reorder_buf_size);
8937d39531SVolodymyr Fialko 	if (ret)
9037d39531SVolodymyr Fialko 		return ret;
9137d39531SVolodymyr Fialko 
92af42b2d1SVolodymyr Fialko 	memory = RTE_PTR_ADD(entity, layout->bitmap_offset);
93af42b2d1SVolodymyr Fialko 	ret = pdcp_cnt_bitmap_create(dl, window_size, memory, layout->bitmap_size);
94af42b2d1SVolodymyr Fialko 	if (ret)
9537d39531SVolodymyr Fialko 		return ret;
9637d39531SVolodymyr Fialko 
9737d39531SVolodymyr Fialko 	return 0;
98c12cfe62SVolodymyr Fialko }
99c12cfe62SVolodymyr Fialko 
100a702bd09SAnoob Joseph struct rte_pdcp_entity *
rte_pdcp_entity_establish(const struct rte_pdcp_entity_conf * conf)101a702bd09SAnoob Joseph rte_pdcp_entity_establish(const struct rte_pdcp_entity_conf *conf)
102a702bd09SAnoob Joseph {
103af42b2d1SVolodymyr Fialko 	struct entity_layout entity_layout = { 0 };
104a702bd09SAnoob Joseph 	struct rte_pdcp_entity *entity = NULL;
105a702bd09SAnoob Joseph 	struct entity_priv *en_priv;
106a702bd09SAnoob Joseph 	uint32_t count;
107af42b2d1SVolodymyr Fialko 	int ret;
108a702bd09SAnoob Joseph 
1097741560dSAnoob Joseph 	if (pdcp_dynfield_register() < 0)
1107741560dSAnoob Joseph 		return NULL;
1117741560dSAnoob Joseph 
1123a3e8931SAnoob Joseph 	if (conf == NULL || conf->cop_pool == NULL || conf->ctrl_pdu_pool == NULL) {
113a702bd09SAnoob Joseph 		rte_errno = EINVAL;
114a702bd09SAnoob Joseph 		return NULL;
115a702bd09SAnoob Joseph 	}
116a702bd09SAnoob Joseph 
117a702bd09SAnoob Joseph 	if (conf->pdcp_xfrm.en_ordering || conf->pdcp_xfrm.remove_duplicates || conf->is_slrb ||
118a702bd09SAnoob Joseph 	    conf->en_sec_offload) {
119a702bd09SAnoob Joseph 		rte_errno = ENOTSUP;
120a702bd09SAnoob Joseph 		return NULL;
121a702bd09SAnoob Joseph 	}
122a702bd09SAnoob Joseph 
123a702bd09SAnoob Joseph 	/*
124a702bd09SAnoob Joseph 	 * 6.3.2 PDCP SN
125a702bd09SAnoob Joseph 	 * Length: 12 or 18 bits as indicated in table 6.3.2-1. The length of the PDCP SN is
126a702bd09SAnoob Joseph 	 * configured by upper layers (pdcp-SN-SizeUL, pdcp-SN-SizeDL, or sl-PDCP-SN-Size in
127a702bd09SAnoob Joseph 	 * TS 38.331 [3])
128a702bd09SAnoob Joseph 	 */
129a702bd09SAnoob Joseph 	if ((conf->pdcp_xfrm.sn_size != RTE_SECURITY_PDCP_SN_SIZE_12) &&
130a702bd09SAnoob Joseph 	    (conf->pdcp_xfrm.sn_size != RTE_SECURITY_PDCP_SN_SIZE_18)) {
131a702bd09SAnoob Joseph 		rte_errno = ENOTSUP;
132a702bd09SAnoob Joseph 		return NULL;
133a702bd09SAnoob Joseph 	}
134a702bd09SAnoob Joseph 
135a702bd09SAnoob Joseph 	if (conf->pdcp_xfrm.hfn_threshold) {
136a702bd09SAnoob Joseph 		rte_errno = EINVAL;
137a702bd09SAnoob Joseph 		return NULL;
138a702bd09SAnoob Joseph 	}
139a702bd09SAnoob Joseph 
140af42b2d1SVolodymyr Fialko 	ret = pdcp_entity_layout_get(conf, &entity_layout);
141af42b2d1SVolodymyr Fialko 	if (ret < 0) {
142a702bd09SAnoob Joseph 		rte_errno = EINVAL;
143a702bd09SAnoob Joseph 		return NULL;
144a702bd09SAnoob Joseph 	}
145a702bd09SAnoob Joseph 
146af42b2d1SVolodymyr Fialko 	entity = rte_zmalloc_socket("pdcp_entity", entity_layout.total_size, RTE_CACHE_LINE_SIZE,
147af42b2d1SVolodymyr Fialko 				    SOCKET_ID_ANY);
148a702bd09SAnoob Joseph 	if (entity == NULL) {
149a702bd09SAnoob Joseph 		rte_errno = ENOMEM;
150a702bd09SAnoob Joseph 		return NULL;
151a702bd09SAnoob Joseph 	}
152a702bd09SAnoob Joseph 
153a702bd09SAnoob Joseph 	en_priv = entity_priv_get(entity);
154a702bd09SAnoob Joseph 
155a702bd09SAnoob Joseph 	count = pdcp_count_from_hfn_sn_get(conf->pdcp_xfrm.hfn, conf->sn, conf->pdcp_xfrm.sn_size);
156a702bd09SAnoob Joseph 
157a702bd09SAnoob Joseph 	en_priv->state.rx_deliv = count;
158a702bd09SAnoob Joseph 	en_priv->state.tx_next = count;
159a702bd09SAnoob Joseph 	en_priv->cop_pool = conf->cop_pool;
1603a3e8931SAnoob Joseph 	en_priv->ctrl_pdu_pool = conf->ctrl_pdu_pool;
161a702bd09SAnoob Joseph 
162a702bd09SAnoob Joseph 	/* Setup crypto session */
163a702bd09SAnoob Joseph 	ret = pdcp_crypto_sess_create(entity, conf);
164a702bd09SAnoob Joseph 	if (ret)
165a702bd09SAnoob Joseph 		goto entity_free;
166a702bd09SAnoob Joseph 
167a702bd09SAnoob Joseph 	ret = pdcp_process_func_set(entity, conf);
168a702bd09SAnoob Joseph 	if (ret)
169a702bd09SAnoob Joseph 		goto crypto_sess_destroy;
170a702bd09SAnoob Joseph 
171c12cfe62SVolodymyr Fialko 	if (conf->pdcp_xfrm.pkt_dir == RTE_SECURITY_PDCP_DOWNLINK) {
172af42b2d1SVolodymyr Fialko 		ret = pdcp_dl_establish(entity, conf, &entity_layout);
173c12cfe62SVolodymyr Fialko 		if (ret)
174c12cfe62SVolodymyr Fialko 			goto crypto_sess_destroy;
175c12cfe62SVolodymyr Fialko 	}
176c12cfe62SVolodymyr Fialko 
177a702bd09SAnoob Joseph 	return entity;
178a702bd09SAnoob Joseph 
179a702bd09SAnoob Joseph crypto_sess_destroy:
180a702bd09SAnoob Joseph 	pdcp_crypto_sess_destroy(entity);
181a702bd09SAnoob Joseph entity_free:
182a702bd09SAnoob Joseph 	rte_free(entity);
183a702bd09SAnoob Joseph 	rte_errno = -ret;
184a702bd09SAnoob Joseph 	return NULL;
185a702bd09SAnoob Joseph }
186a702bd09SAnoob Joseph 
187c12cfe62SVolodymyr Fialko static int
pdcp_dl_release(struct rte_pdcp_entity * entity,struct rte_mbuf * out_mb[])188c12cfe62SVolodymyr Fialko pdcp_dl_release(struct rte_pdcp_entity *entity, struct rte_mbuf *out_mb[])
189c12cfe62SVolodymyr Fialko {
190c12cfe62SVolodymyr Fialko 	struct entity_priv_dl_part *dl = entity_dl_part_get(entity);
191c12cfe62SVolodymyr Fialko 	struct entity_priv *en_priv = entity_priv_get(entity);
192c12cfe62SVolodymyr Fialko 	int nb_out;
193c12cfe62SVolodymyr Fialko 
194c12cfe62SVolodymyr Fialko 	nb_out = pdcp_reorder_up_to_get(&dl->reorder, out_mb, entity->max_pkt_cache,
195c12cfe62SVolodymyr Fialko 			en_priv->state.rx_next);
196c12cfe62SVolodymyr Fialko 
197c12cfe62SVolodymyr Fialko 	return nb_out;
198c12cfe62SVolodymyr Fialko }
199c12cfe62SVolodymyr Fialko 
200a702bd09SAnoob Joseph int
rte_pdcp_entity_release(struct rte_pdcp_entity * pdcp_entity,struct rte_mbuf * out_mb[])201a702bd09SAnoob Joseph rte_pdcp_entity_release(struct rte_pdcp_entity *pdcp_entity, struct rte_mbuf *out_mb[])
202a702bd09SAnoob Joseph {
203c12cfe62SVolodymyr Fialko 	struct entity_priv *en_priv;
204c12cfe62SVolodymyr Fialko 	int nb_out = 0;
205c12cfe62SVolodymyr Fialko 
206a702bd09SAnoob Joseph 	if (pdcp_entity == NULL)
207a702bd09SAnoob Joseph 		return -EINVAL;
208a702bd09SAnoob Joseph 
209c12cfe62SVolodymyr Fialko 	en_priv = entity_priv_get(pdcp_entity);
210c12cfe62SVolodymyr Fialko 
211c12cfe62SVolodymyr Fialko 	if (!en_priv->flags.is_ul_entity)
212c12cfe62SVolodymyr Fialko 		nb_out = pdcp_dl_release(pdcp_entity, out_mb);
213c12cfe62SVolodymyr Fialko 
214a702bd09SAnoob Joseph 	/* Teardown crypto sessions */
215a702bd09SAnoob Joseph 	pdcp_crypto_sess_destroy(pdcp_entity);
216a702bd09SAnoob Joseph 
217a702bd09SAnoob Joseph 	rte_free(pdcp_entity);
218a702bd09SAnoob Joseph 
219c12cfe62SVolodymyr Fialko 	return nb_out;
220a702bd09SAnoob Joseph }
221a702bd09SAnoob Joseph 
222a702bd09SAnoob Joseph int
rte_pdcp_entity_suspend(struct rte_pdcp_entity * pdcp_entity,struct rte_mbuf * out_mb[])223a702bd09SAnoob Joseph rte_pdcp_entity_suspend(struct rte_pdcp_entity *pdcp_entity,
224a702bd09SAnoob Joseph 			struct rte_mbuf *out_mb[])
225a702bd09SAnoob Joseph {
226c12cfe62SVolodymyr Fialko 	struct entity_priv_dl_part *dl;
227a702bd09SAnoob Joseph 	struct entity_priv *en_priv;
228c12cfe62SVolodymyr Fialko 	int nb_out = 0;
229a702bd09SAnoob Joseph 
230a702bd09SAnoob Joseph 	if (pdcp_entity == NULL)
231a702bd09SAnoob Joseph 		return -EINVAL;
232a702bd09SAnoob Joseph 
233a702bd09SAnoob Joseph 	en_priv = entity_priv_get(pdcp_entity);
234a702bd09SAnoob Joseph 
235a702bd09SAnoob Joseph 	if (en_priv->flags.is_ul_entity) {
236a702bd09SAnoob Joseph 		en_priv->state.tx_next = 0;
237a702bd09SAnoob Joseph 	} else {
238c12cfe62SVolodymyr Fialko 		dl = entity_dl_part_get(pdcp_entity);
239c12cfe62SVolodymyr Fialko 		nb_out = pdcp_reorder_up_to_get(&dl->reorder, out_mb, pdcp_entity->max_pkt_cache,
240c12cfe62SVolodymyr Fialko 				en_priv->state.rx_next);
241c12cfe62SVolodymyr Fialko 		pdcp_reorder_stop(&dl->reorder);
242a702bd09SAnoob Joseph 		en_priv->state.rx_next = 0;
243a702bd09SAnoob Joseph 		en_priv->state.rx_deliv = 0;
244a702bd09SAnoob Joseph 	}
245a702bd09SAnoob Joseph 
246c12cfe62SVolodymyr Fialko 	return nb_out;
247a702bd09SAnoob Joseph }
2483a3e8931SAnoob Joseph 
2493a3e8931SAnoob Joseph struct rte_mbuf *
rte_pdcp_control_pdu_create(struct rte_pdcp_entity * pdcp_entity,enum rte_pdcp_ctrl_pdu_type type)2503a3e8931SAnoob Joseph rte_pdcp_control_pdu_create(struct rte_pdcp_entity *pdcp_entity,
2513a3e8931SAnoob Joseph 			    enum rte_pdcp_ctrl_pdu_type type)
2523a3e8931SAnoob Joseph {
25337d39531SVolodymyr Fialko 	struct entity_priv_dl_part *dl;
2543a3e8931SAnoob Joseph 	struct entity_priv *en_priv;
2553a3e8931SAnoob Joseph 	struct rte_mbuf *m;
2563a3e8931SAnoob Joseph 	int ret;
2573a3e8931SAnoob Joseph 
2583a3e8931SAnoob Joseph 	if (pdcp_entity == NULL) {
2593a3e8931SAnoob Joseph 		rte_errno = EINVAL;
2603a3e8931SAnoob Joseph 		return NULL;
2613a3e8931SAnoob Joseph 	}
2623a3e8931SAnoob Joseph 
2633a3e8931SAnoob Joseph 	en_priv = entity_priv_get(pdcp_entity);
26437d39531SVolodymyr Fialko 	dl = entity_dl_part_get(pdcp_entity);
2653a3e8931SAnoob Joseph 
2663a3e8931SAnoob Joseph 	m = rte_pktmbuf_alloc(en_priv->ctrl_pdu_pool);
2673a3e8931SAnoob Joseph 	if (m == NULL) {
2683a3e8931SAnoob Joseph 		rte_errno = ENOMEM;
2693a3e8931SAnoob Joseph 		return NULL;
2703a3e8931SAnoob Joseph 	}
2713a3e8931SAnoob Joseph 
2723a3e8931SAnoob Joseph 	switch (type) {
2733a3e8931SAnoob Joseph 	case RTE_PDCP_CTRL_PDU_TYPE_STATUS_REPORT:
27437d39531SVolodymyr Fialko 		ret = pdcp_ctrl_pdu_status_gen(en_priv, dl, m);
2753a3e8931SAnoob Joseph 		break;
2763a3e8931SAnoob Joseph 	default:
2773a3e8931SAnoob Joseph 		ret = -ENOTSUP;
2783a3e8931SAnoob Joseph 	}
2793a3e8931SAnoob Joseph 
2803a3e8931SAnoob Joseph 	if (ret) {
2813a3e8931SAnoob Joseph 		rte_pktmbuf_free(m);
2823a3e8931SAnoob Joseph 		rte_errno = -ret;
2833a3e8931SAnoob Joseph 		return NULL;
2843a3e8931SAnoob Joseph 	}
2853a3e8931SAnoob Joseph 
2863a3e8931SAnoob Joseph 	return m;
2873a3e8931SAnoob Joseph }
288f381ac0fSVolodymyr Fialko 
289f381ac0fSVolodymyr Fialko uint16_t
rte_pdcp_t_reordering_expiry_handle(const struct rte_pdcp_entity * entity,struct rte_mbuf * out_mb[])290f381ac0fSVolodymyr Fialko rte_pdcp_t_reordering_expiry_handle(const struct rte_pdcp_entity *entity, struct rte_mbuf *out_mb[])
291f381ac0fSVolodymyr Fialko {
292f381ac0fSVolodymyr Fialko 	struct entity_priv_dl_part *dl = entity_dl_part_get(entity);
293f381ac0fSVolodymyr Fialko 	struct entity_priv *en_priv = entity_priv_get(entity);
294f381ac0fSVolodymyr Fialko 	uint16_t capacity = entity->max_pkt_cache;
295f381ac0fSVolodymyr Fialko 	uint16_t nb_out, nb_seq;
296f381ac0fSVolodymyr Fialko 
297f381ac0fSVolodymyr Fialko 	/* 5.2.2.2 Actions when a t-Reordering expires */
298f381ac0fSVolodymyr Fialko 
299f381ac0fSVolodymyr Fialko 	/*
300f381ac0fSVolodymyr Fialko 	 * - deliver to upper layers in ascending order of the associated COUNT value after
301f381ac0fSVolodymyr Fialko 	 *   performing header decompression, if not decompressed before:
302f381ac0fSVolodymyr Fialko 	 */
303f381ac0fSVolodymyr Fialko 
304f381ac0fSVolodymyr Fialko 	/*   - all stored PDCP SDU(s) with associated COUNT value(s) < RX_REORD; */
305f381ac0fSVolodymyr Fialko 	nb_out = pdcp_reorder_up_to_get(&dl->reorder, out_mb, capacity, en_priv->state.rx_reord);
306f381ac0fSVolodymyr Fialko 	capacity -= nb_out;
307f381ac0fSVolodymyr Fialko 	out_mb = &out_mb[nb_out];
308f381ac0fSVolodymyr Fialko 
309f381ac0fSVolodymyr Fialko 	/*
310f381ac0fSVolodymyr Fialko 	 *   - all stored PDCP SDU(s) with consecutively associated COUNT value(s) starting from
311f381ac0fSVolodymyr Fialko 	 *     RX_REORD;
312f381ac0fSVolodymyr Fialko 	 */
313f381ac0fSVolodymyr Fialko 	nb_seq = pdcp_reorder_get_sequential(&dl->reorder, out_mb, capacity);
314f381ac0fSVolodymyr Fialko 	nb_out += nb_seq;
315f381ac0fSVolodymyr Fialko 
316f381ac0fSVolodymyr Fialko 	/*
317f381ac0fSVolodymyr Fialko 	 * - update RX_DELIV to the COUNT value of the first PDCP SDU which has not been delivered
318f381ac0fSVolodymyr Fialko 	 *   to upper layers, with COUNT value >= RX_REORD;
319f381ac0fSVolodymyr Fialko 	 */
32037d39531SVolodymyr Fialko 	pdcp_rx_deliv_set(entity, en_priv->state.rx_reord + nb_seq);
321f381ac0fSVolodymyr Fialko 
322f381ac0fSVolodymyr Fialko 	/*
323f381ac0fSVolodymyr Fialko 	 * - if RX_DELIV < RX_NEXT:
324f381ac0fSVolodymyr Fialko 	 *   - update RX_REORD to RX_NEXT;
325f381ac0fSVolodymyr Fialko 	 *   - start t-Reordering.
326f381ac0fSVolodymyr Fialko 	 */
327f381ac0fSVolodymyr Fialko 	if (en_priv->state.rx_deliv < en_priv->state.rx_next) {
328f381ac0fSVolodymyr Fialko 		en_priv->state.rx_reord = en_priv->state.rx_next;
329f381ac0fSVolodymyr Fialko 		dl->t_reorder.state = TIMER_RUNNING;
330f381ac0fSVolodymyr Fialko 		dl->t_reorder.handle.start(dl->t_reorder.handle.timer, dl->t_reorder.handle.args);
331f381ac0fSVolodymyr Fialko 	} else {
332f381ac0fSVolodymyr Fialko 		dl->t_reorder.state = TIMER_EXPIRED;
333f381ac0fSVolodymyr Fialko 	}
334f381ac0fSVolodymyr Fialko 
335f381ac0fSVolodymyr Fialko 	return nb_out;
336f381ac0fSVolodymyr Fialko }
337