Committing in PDCP code
[o-du/l2.git] / src / 5gnrpdcp / pj_ulm.c
1 /*******************************************************************************
2 ################################################################################
3 #   Copyright (c) [2017-2019] [Radisys]                                        #
4 #                                                                              #
5 #   Licensed under the Apache License, Version 2.0 (the "License");            #
6 #   you may not use this file except in compliance with the License.           #
7 #   You may obtain a copy of the License at                                    #
8 #                                                                              #
9 #       http://www.apache.org/licenses/LICENSE-2.0                             #
10 #                                                                              #
11 #   Unless required by applicable law or agreed to in writing, software        #
12 #   distributed under the License is distributed on an "AS IS" BASIS,          #
13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
14 #   See the License for the specific language governing permissions and        #
15 #   limitations under the License.                                             #
16 ################################################################################
17 *******************************************************************************/
18
19 /**********************************************************************
20
21      Name:     LTE-PDCP Layer 
22   
23      Type:     C file
24   
25      Desc:     Source code for PDCP Uplink module.
26                This file contains following functions
27                   -- pjUlmHdlSrbPkt
28                   -- pjUlmHdlDrbPkt
29                   -- pjUlmProcessRb
30                   -- pjUlmDeliverSrb
31                   -- pjUlmDeliverDrbUm
32                   -- pjUlmDeliverDrbAm
33                   -- pjUlmReEstSrb
34                   -- pjUlmReEstDrbAm
35                   -- pjUlmBldStaRep
36                   -- pjUlmHdlDatFwdReq
37                   -- pjUlmHdlObdTmrExpiry
38
39      File:     pj_ulm.c
40
41 **********************************************************************/
42 static const char* RLOG_MODULE_NAME="PDCP";
43 static int RLOG_FILE_ID=245;
44 static int RLOG_MODULE_ID=1024;
45 /** @file pj_ulm.c
46 @brief PDCP Uplink module
47 */
48
49 /* header (.h) include files */
50 #include "envopt.h"             /* environment options */
51 #include "envdep.h"             /* environment dependent */
52 #include "envind.h"             /* environment independent */
53
54 #include "gen.h"                /* general */
55 #include "ssi.h"                /* system services interface */
56 #include "cm5.h"                /* Timer Functions */
57 #include "cm_lte.h"             /* common LTE header file */
58 #include "cm_hash.h"            /* common hash module  file */
59 #include "cm_llist.h"           /* common list header file */
60 #include "cpj.h"                /* RRC layer */
61 #include "pju.h"                /* PDCP service user */
62 #include "lpj.h"                /* RRC layer */
63 #include "pj_env.h"             /* RLC environment options */
64 #include "pj.h"                 /* RLC layer */
65 #include "pj_ul.h"
66 #include "pj_err.h"
67 #include "pj_ptsec.h"
68
69
70
71 /* header/extern include files (.x) */
72
73 #include "gen.x"                /* general */
74 #include "ssi.x"                /* system services interface */
75 #include "cm_lib.x"             /* common library */
76 #include "cm5.x"                /* Timer Functions */
77 #include "cm_hash.x"            /* common hash module */
78 #include "cm_lte.x"             /* common LTE file */
79 #include "cm_llist.x"           /* common list header file */
80 #include "cpj.x"                /* RRC layer */
81 #include "pju.x"                /* PDCP service user */
82 #include "lpj.x"                /* LM Interface */
83 #include "pj.h"                /* LM Interface */
84 #include "pj.x"                 /* RLC layer */
85 #include "pj_udx.h"
86 #include "pj_udx.x"
87 #include "pj_dl.x"
88 #include "pj_ul.x"
89  
90 \f
91 /* local defines */
92
93 /* local externs */
94 #ifdef TENB_AS_SECURITY
95 EXTERN U8 isSecBatchMode;
96 #endif
97
98 /* forward references */
99 PUBLIC S16 pjUtlChekTxEnqReq(PjCb *gCb, PjDlRbCb *pjRbCb, PjTxEnt *txEnt);
100 PUBLIC S16 pjUtlChekRxEnqReq(PjCb *gCb, PjUlRbCb *pjRbCb, PjRxEnt *rxEnt);
101
102 /* public variable declarations */
103
104 /* This structure holds all the global structs we need. */
105
106 /* private variable declarations */
107
108 /* private function declarations */
109
110 PRIVATE S16 pjUlmDrbFetchSn 
111 (
112 PjCb     *gCb,
113 PjUlRbCb *pjRbCb,               /* !< PDCP Control Block */      
114 Buffer   *pdu,                    /* !< PDU Buffer */ 
115 U8        hdrByte,               /* !< one byte extracted from pdu */
116 PjSn     *sn                     /* PDCP SN*/
117 );
118 PRIVATE S16 pjUlmProcessRb
119 (
120 PjCb     *gCb,
121 PjUlRbCb   *pjRbCb,          /* !< PDCP Control Block */   
122 PjSn       rcvdSn,               /* !< SN value of PDU */           
123 Buffer   *pdu,              /* !< PDU message buffer */           
124 Bool     isOutOfSeq         /* !< To indicate whether packet received is in-sequence or not */
125 );
126 /** @addtogroup uldata */
127 /*@{*/
128
129 /*****************************************************************************
130  *    HEADER PARSING FUNCTIONS
131  ****************************************************************************/
132
133 PRIVATE Void pjUlmEnqueueUlPkt ARGS(( PjCb *gCb, PjUlRbCb   *pjRbCb,PjSn      sn, Buffer   *pdu));
134
135
136
137 PUBLIC S16 pjUlmHndlDlFdbk ARGS ((
138 PjCb     *gCb,
139 PjUlRbCb   *pjRbCb,
140 Buffer   *mBuf
141 ));
142 /**
143  *
144  * @brief 
145  *
146  *        Function to extract the SRB header.
147  *
148  * @b Description: 
149  *
150  *        This function extracts the SN and the MAC-I from the pdu buffer and
151  *        places them in the SrbHdr structure.
152  *                                               
153  *  @param[in] pjRbCb   PDCP control block 
154  *  @param[in] pdu      PDU to be processed
155  *  @return  S16
156  *      -# ROK 
157  *      -# RFAILED
158  */
159
160 #ifdef ANSI
161 PUBLIC S16 pjUlmHdlSrbPkt
162 (
163 PjCb   *gCb,
164 PjUlRbCb *pjRbCb,               /* !< PDCP Control Block */  
165 Buffer *pdu                   /* !< PDU Buffer */ 
166 )
167 #else
168 PUBLIC S16 pjUlmHdlSrbPkt(gCb, pjRbCb, pdu)
169 PjCb    *gCb;
170 PjUlRbCb  *pjRbCb;               /* !< PDCP Control Block */      
171 Buffer  *pdu;                  /* !< PDU Buffer */ 
172 #endif
173 {
174    S16    ret     = ROK;    /* Return Value */
175    PjSn   sn;               /* SN value */
176    U8     hdrByte;          /* First byte storing hdr values */
177    U8     res;              /* Reserved values */
178
179    TRC2(pjUlmHdlSrbPkt);
180
181
182    /* Initialistaions */
183
184    /* Get the first byte */
185    ret = SRemPreMsg(&hdrByte, pdu);
186 #if (ERRCLASS & ERRCLS_DEBUG)
187    if (ret != ROK)
188    {
189       RLOG_ARG0(L_ERROR, DBG_UEID,pjRbCb->ueCb->key.ueId," SRemPreMsg Failed ");
190       PJ_FREE_BUF(pdu);
191       PJ_STS_INC_GEN_CNT(gCb,errorPdusRecv);
192       RETVALUE(RFAILED);
193    }
194 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
195
196    /* Verify that reserved values are zero */
197    res = (hdrByte >> 4);
198    if(res != 0)
199    {
200       RLOG_ARG0(L_ERROR,DBG_UEID,pjRbCb->ueCb->key.ueId,
201                      "Reserved Values Non-zero ");
202       PJ_FREE_BUF(pdu);
203       PJ_STS_INC_GEN_CNT(gCb,errorPdusRecv);
204       RETVALUE(RFAILED);
205    }
206
207    /* Directly assigning since the reserved values are zero */
208    sn = hdrByte;
209    sn = sn << PJ_BYTE_SIZE;
210    ret = SRemPreMsg(&hdrByte, pdu);
211 #if (ERRCLASS & ERRCLS_DEBUG)
212    if (ret != ROK)
213    {
214       PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_ERROR),
215             (gCb->init.prntBuf," SRemPreMsg Failed \n"));
216       RETVALUE(RFAILED);
217    }
218 #endif
219    sn |= hdrByte;
220
221    /* Start processing */
222    ret =  pjUlmProcessRb(gCb, pjRbCb, sn, pdu, FALSE);
223
224    RETVALUE(ret);
225 }/* pjUlmHdlSrbPkt */
226
227 /**
228  *
229  * @brief 
230  *
231  *        Handler to forward the status report to PDCP-DL.
232  *
233  * @b Description: 
234  *
235  *        1. This function is called when a status report is received from the
236  *        peer.    @n
237  *        2. This function forwards the status report to PDCP-DL.  @n
238  *            
239  *  @param[in] pjRbCb      PDCP control block. 
240  *  @param[in] staPdu      Status report.
241  *
242  *  @return  S16
243  *      -# ROK 
244  *      -# RFAILED
245  *
246  */
247
248 #ifdef ANSI
249 PUBLIC S16 pjUlmHndlDlStaRep
250 (
251 PjCb     *gCb,
252 PjUlRbCb   *pjRbCb,
253 PjSn     fmc,
254 Buffer   *staPdu
255 )
256 #else
257 PUBLIC S16 pjUlmHndlDlStaRep(gCb, pjRbCb, fmc, staPdu)
258 PjCb     *gCb;
259 PjUlRbCb   *pjRbCb;
260 PjSn     fmc,
261 Buffer   *staPdu;
262 #endif
263 {
264    UdxDlStaRepInfo      *staRep;
265    PjUdxUlSapCb         *udxSap;
266    S16                  ret = ROK;           /* Return Value */
267    
268    TRC3(pjUlmHndlDlStaRep)
269
270    udxSap = PJ_GET_UL_UDX_SAP(gCb);
271    PJ_ALLOC_BUF_SHRABL(udxSap->pst ,staRep,
272                      sizeof (UdxUlStaRepInfo), ret);
273    if(ret != ROK)
274    {
275       staRep = NULLP;
276    }
277
278    if (NULLP != staRep)
279    {
280       staRep->pdcpId.cellId = pjRbCb->ueCb->key.cellId;
281       staRep->pdcpId.ueId = pjRbCb->ueCb->key.ueId;
282       staRep->pdcpId.rbId = pjRbCb->rbId;
283       staRep->pdcpId.rbType = pjRbCb->rbType;
284       staRep->fmc = fmc;
285       staRep->staPdu = staPdu;
286       
287       PjUlUdxDlStaRep(&(udxSap->pst), udxSap->spId, staRep);
288    }
289    else
290    {
291       RETVALUE(RFAILED);
292    }
293
294    RETVALUE(ROK);
295 }
296
297 /**
298  *
299  * @brief 
300  *
301  *        Handler to forward the ROHC feedback packet received from UE to PDCP-DL.
302  *
303  * @b Description: 
304  *
305  *        1. This function is called when a ROHC feedback packet received from
306  *        peer.    @n
307  *        2. This function forwards the ROHC feedback packet to PDCP-DL.  @n
308  *            
309  *  @param[in] gCb           global control block.
310  *  @param[in] pjRbCb      PDCP control block. 
311  *  @param[in] mBuf         ROHC feedback packet.
312  *
313  *  @return  S16
314  *      -# ROK 
315  *      -# RFAILED
316  *
317  */
318
319 #ifdef ANSI
320 PUBLIC S16 pjUlmHndlDlFdbk
321 (
322 PjCb     *gCb,
323 PjUlRbCb   *pjRbCb,
324 Buffer   *mBuf
325 )
326 #else
327 PUBLIC S16 pjUlmHndlDlFdbk(gCb, pjRbCb, mBuf)
328 PjCb     *gCb;
329 PjUlRbCb   *pjRbCb;
330 Buffer   *mBuf;
331 #endif
332 {
333    UdxDlFdbkPktInfo *fbPkt;
334    PjUdxUlSapCb     *udxSap;
335    S16              ret = ROK;
336    
337    TRC3(pjUlmHndlDlFdbk)
338    
339    udxSap = PJ_GET_UL_UDX_SAP(gCb);
340
341    PJ_ALLOC_BUF_SHRABL(udxSap->pst, fbPkt,
342       sizeof (UdxDlFdbkPktInfo), ret);
343    if(ret != ROK)
344    {
345       fbPkt = NULLP;
346    }
347
348    if (NULLP != fbPkt)
349    {
350       fbPkt->pdcpId.cellId = pjRbCb->ueCb->key.cellId;
351       fbPkt->pdcpId.ueId = pjRbCb->ueCb->key.ueId;
352       fbPkt->pdcpId.rbId = pjRbCb->rbId;
353       fbPkt->pdcpId.rbType = pjRbCb->rbType;
354
355       fbPkt->fbPkt= mBuf;
356       
357       PjUlUdxDlFdbkPktInfo(&(udxSap->pst), udxSap->spId, fbPkt);
358    }
359    else
360    {
361       RETVALUE(RFAILED);
362    }
363
364    RETVALUE(ROK);
365 }
366
367 /**
368  *
369  * @brief 
370  *
371  *        Function to extract the DRB SN from hdr.
372  *
373  * @b Description: 
374  *
375  *        This function extracts the SN in case of a data packet 
376  *
377  *  @param[in] pjRbCb   PDCP control block 
378  *  @param[in] pdu      PDU to be processed
379  *  @return  S16
380  *      -# ROK 
381  *      -# RFAILED
382  */
383 #ifdef ANSI
384 PRIVATE S16 pjUlmDrbFetchSn 
385 (
386 PjCb     *gCb,
387 PjUlRbCb *pjRbCb,               /* !< PDCP Control Block */      
388 Buffer   *pdu,                    /* !< PDU Buffer */ 
389 U8        hdrByte,               /* !< one byte extracted from pdu */
390 PjSn     *sn                     /* PDCP SN*/
391 )
392 #else
393 PRIVATE S16 pjUlmDrbFetchSn(gCb, pjRbCb, pdu, hdrByte, sn)
394 PjCb     *gCb;
395 PjUlRbCb *pjRbCb;               /* !< PDCP Control Block */      
396 Buffer   *pdu;                    /* !< PDU Buffer */ 
397 U8        hdrByte;              /* !< one byte extracted from pdu */
398 PjSn     *sn;                   /* PDCP SN*/
399 #endif
400 {
401    U8     res;              /* Reserved values */
402    S16    ret     = ROK;    /* Return Value */
403    /* Pack the SN */
404
405    if (pjRbCb->snLen == PJ_12_BIT_SN) /* Its 12 bit */ 
406    {
407       /* Verify that reserved values are zero */
408       res = (hdrByte >> 4);
409       if (res != 8)
410       {
411          PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_ERROR),
412                (gCb->init.prntBuf," Reserved Values Non-zero \n"));
413          RETVALUE(RFAILED);
414       }
415
416       *sn = (hdrByte & PJ_12_BIT_SN_MSB_MASK); /*KW_FIX*/
417       *sn = *sn << PJ_BYTE_SIZE;
418       ret = SRemPreMsg(&hdrByte, pdu);
419 #if (ERRCLASS & ERRCLS_DEBUG)
420       if (ret != ROK)
421       {
422          PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_ERROR),
423                (gCb->init.prntBuf," SRemPreMsg Failed \n"));
424          RETVALUE(RFAILED);
425       }
426 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
427       *sn |= hdrByte;
428    }
429    else if (pjRbCb->snLen == PJ_18_BIT_SN)
430    {
431       *sn = ((hdrByte & PJ_18_BIT_SN_MSB_MASK)); /*KW_FIX*/
432       *sn = *sn << PJ_BYTE_SIZE;
433       ret = SRemPreMsg(&hdrByte, pdu);
434 #if (ERRCLASS & ERRCLS_DEBUG)
435       if (ret != ROK)
436       {
437          PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_ERROR),
438                (gCb->init.prntBuf," SRemPreMsg Failed \n"));
439          RETVALUE(RFAILED);
440       }
441 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
442       *sn |= hdrByte;
443       *sn = *sn << PJ_BYTE_SIZE;
444       ret = SRemPreMsg(&hdrByte, pdu);
445 #if (ERRCLASS & ERRCLS_DEBUG)
446       if (ret != ROK)
447       {
448          PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_ERROR),
449                (gCb->init.prntBuf," SRemPreMsg Failed \n"));
450          RETVALUE(RFAILED);
451       }
452 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
453       *sn |= hdrByte;
454    }
455
456    RETVALUE(ret);
457 }
458
459 /**
460  *
461  * @brief 
462  *
463  *        Function to extract the FMC.
464  *
465  * @b Description: 
466  *
467  *        This function extracts the FMC and Bitmap incase of a 
468  *        PDCP status packet places them in the DrbHdr structure.
469  *
470  *  @param[in] pjRbCb   PDCP control block 
471  *  @param[in] pdu      PDU to be processed
472  */
473 #ifdef ANSI
474 PUBLIC S16 pjUlmGetFmc
475 (
476 U8       hdrByte,
477 PjUlRbCb *pjRbCb,               /* !< PDCP Control Block */      
478 Buffer *pdu,                    /* !< PDU Buffer */ 
479 U32      *fmc              
480 )
481 #else
482 PUBLIC S16 pjUlmGetFmc(hdrByte,pjRbCb, pdu, fmc)
483 U8        hdrByte;
484 PjUlRbCb *pjRbCb;               /* !< PDCP Control Block */      
485 Buffer *pdu;                    /* !< PDU Buffer */ 
486 U32     *fmc;             
487 #endif
488 {
489    
490    S16    ret     = ROK;
491    TRC2(pjUlmGetFmc)
492    ret = SRemPreMsg(&hdrByte, pdu);
493 #if (ERRCLASS & ERRCLS_DEBUG)
494          if(ret != ROK)
495          {
496             RLOG_ARG0(L_DEBUG, DBG_UEID,pjRbCb->ueCb->key.ueId,"SRemPreMsg Failed");
497             PJ_FREE_BUF(pdu);
498             RETVALUE(RFAILED);
499          }
500 #endif
501          *fmc = hdrByte;
502          *fmc = *fmc << PJ_BYTE_SIZE;
503          ret = SRemPreMsg(&hdrByte, pdu);
504 #if (ERRCLASS & ERRCLS_DEBUG)
505          if(ret != ROK)
506          {
507             RLOG_ARG0(L_DEBUG, DBG_UEID,pjRbCb->ueCb->key.ueId,"SRemPreMsg Failed");
508
509             PJ_FREE_BUF(pdu);
510             RETVALUE(RFAILED);
511          }
512 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
513          *fmc   |=  hdrByte;
514          *fmc = *fmc << PJ_BYTE_SIZE;
515          ret = SRemPreMsg(&hdrByte, pdu);
516 #if (ERRCLASS & ERRCLS_DEBUG)
517          if(ret != ROK)
518          {
519             RLOG_ARG0(L_DEBUG, DBG_UEID,pjRbCb->ueCb->key.ueId,"SRemPreMsg Failed");
520
521             PJ_FREE_BUF(pdu);
522             RETVALUE(RFAILED);
523          }
524 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
525          *fmc   |=  hdrByte;
526          *fmc = *fmc << PJ_BYTE_SIZE;
527          ret = SRemPreMsg(&hdrByte, pdu);
528 #if (ERRCLASS & ERRCLS_DEBUG)
529          if(ret != ROK)
530          {
531             RLOG_ARG0(L_DEBUG, DBG_UEID,pjRbCb->ueCb->key.ueId,"SRemPreMsg Failed");
532
533             PJ_FREE_BUF(pdu);
534             RETVALUE(RFAILED);
535          }
536 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
537          *fmc   |=  hdrByte;
538          RETVALUE(ret);
539
540 }
541
542
543 \f
544 /**
545  *
546  * @brief 
547  *
548  *        Function to extract the DRB header.
549  *
550  * @b Description: 
551  *
552  *        This function extracts the SN in case of a data packet 
553  *        or feedback packet and the FMS and Bitmap incase of a 
554  *        PDCP status packet places them in the DrbHdr structure.
555  *
556  *  @param[in] pjRbCb   PDCP control block 
557  *  @param[in] pdu      PDU to be processed
558  *  @return  S16
559  *      -# ROK 
560  *      -# RFAILED
561  */
562 #ifdef ANSI
563 PUBLIC S16 pjUlmHdlDrbPkt
564 (
565 PjCb   *gCb,
566 PjUlRbCb *pjRbCb,               /* !< PDCP Control Block */      
567 Buffer *pdu,                    /* !< PDU Buffer */ 
568 Bool    isOutOfSeq              /*!< To indicate whether this packet is in-sequence or not */
569 )
570 #else
571 PUBLIC S16 pjUlmHdlDrbPkt(gCb, pjRbCb, pdu, isOutOfSeq)
572 PjCb   *gCb;
573 PjUlRbCb *pjRbCb;               /* !< PDCP Control Block */      
574 Buffer *pdu;                    /* !< PDU Buffer */ 
575 Bool    isOutOfSeq;             /* !< To indicate whether this packet is in-sequence or not */
576 #endif
577 {
578    S16    ret     = ROK;    /* Return Value */
579    PjSn   sn = 0;               /* SN value */
580    U8     hdrByte;          /* First byte storing hdr values */
581    U8     pduType;          /* Type of PDU */
582    U8     res;              /* Reserved values */
583    U32    fmc;              /*First Missing Count 5G Nr*/
584
585    TRC2(pjUlmHdlDrbPkt)
586 #ifndef RGL_SPECIFIC_CHANGES
587 #ifndef TENB_ACC
588 #ifndef LTE_PAL_ENB
589 extern U32 ulrate_kwu;
590 MsgLen len;
591 SFndLenMsg(pdu, &len);
592 ulrate_kwu += len;
593 #endif
594 #endif
595 #endif
596    /* Get the first byte */
597    ret = SRemPreMsg(&hdrByte, pdu);
598 #if (ERRCLASS & ERRCLS_DEBUG)
599    if (ret != ROK)
600    {
601       RLOG_ARG0(L_DEBUG, DBG_UEID,pjRbCb->ueCb->key.ueId," SRemPreMsg Failed ");
602       PJ_FREE_BUF(pdu);
603       PJ_STS_INC_GEN_CNT(gCb,errorPdusRecv);
604       RETVALUE(RFAILED);
605    }
606 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
607
608    /* check if its a data PDU */
609    if((hdrByte & PJ_TYPE_DRB_DATA) == PJ_TYPE_DRB_DATA)
610    {
611       ret = pjUlmDrbFetchSn (gCb, pjRbCb, pdu, hdrByte, &sn);
612 #if (ERRCLASS & ERRCLS_DEBUG)
613       if (ret != ROK)
614       {
615          PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_ERROR),
616                (gCb->init.prntBuf," Failed to extract SN from PDU\n"));
617          PJ_FREE_BUF(pdu);
618          PJ_STS_INC_GEN_CNT(gCb,errorPdusRecv);
619          RETVALUE(RFAILED);
620       }
621 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
622
623       /* Call the processing function */
624       if(pjRbCb->mode == PJ_DRB_AM)
625       {
626          if (pjRbCb->state == PJ_STATE_HO)
627          {
628              pjUlmEnqueueUlPkt(gCb,pjRbCb,sn,pdu);
629          }
630          else
631          {
632            ret = pjUlmProcessRb(gCb, pjRbCb, sn, pdu, isOutOfSeq);
633          }
634       }
635       else /* (pjRbCb->type == PJ_DRB_UM) */
636       {
637          ret = pjUlmProcessRb(gCb, pjRbCb, sn, pdu, FALSE);
638       }
639    }
640    else  /* Its a control PDU */
641    {
642
643       pduType =  (U8)((hdrByte & PJ_PDU_BIT_MASK) >> 4);  /*KW_FIX*/
644
645       if(pduType == PJ_TYPE_STATUS_REPORT)
646       {
647          pjUlmGetFmc(hdrByte,pjRbCb,pdu,&fmc);
648          ret = pjUlmHndlDlStaRep(gCb, pjRbCb, fmc, pdu);
649          if (ret != ROK)
650          {
651             RLOG_ARG0(L_DEBUG,DBG_UEID,pjRbCb->ueCb->key.ueId,
652                           " pjUlmHndlDlStaRep() returned Failed ");
653             PJ_FREE_BUF(pdu);
654             RETVALUE(RFAILED);
655          }
656       }
657       else if(pduType == PJ_TYPE_ROHC_FEEDBACK)
658       {
659
660          /* validate that reserved values are 0*/
661          res  =  (U8)(hdrByte & PJ_CPDU_RES_VAL_MASK);  /*KW_FIX*/
662          if(res != 0)
663          {
664             RLOG_ARG0(L_DEBUG,DBG_UEID,pjRbCb->ueCb->key.ueId,
665                         " Reserved values non-null ");
666             PJ_FREE_BUF(pdu);
667             PJ_STS_INC_GEN_CNT(gCb,errorPdusRecv);
668             RETVALUE(RFAILED);
669          }
670
671          ret = pjUlmHndlDlFdbk(gCb, pjRbCb, pdu);
672          if (ret != ROK)
673          {
674             RLOG_ARG0(L_DEBUG,DBG_UEID,pjRbCb->ueCb->key.ueId,
675                   " pjUlmHndlDlStaRep() returned Failed ");
676             PJ_FREE_BUF(pdu);
677             RETVALUE(RFAILED);
678          }
679       }
680       else
681       {
682          /* Invalid PDU type */
683          RLOG_ARG0(L_DEBUG,DBG_UEID,pjRbCb->ueCb->key.ueId,
684                          " Invalid PDU Type ");
685          PJ_FREE_BUF(pdu);
686          PJ_STS_INC_GEN_CNT(gCb,errorPdusRecv);
687          RETVALUE(RFAILED);
688       }
689    }
690    RETVALUE(ret);
691 }/* pjUlmHdlDrbPkt */
692
693 /*****************************************************************************
694  *          PROCESSING FUNCTIONS
695  ****************************************************************************/
696 /**
697  *
698  * @brief 
699  *
700  *        Function to process the PDCP RB Pdu and updates the state variables. 
701  *
702  * @b Description: 
703  *
704  *        This function performs the follwing steps:                       @n
705  *        1. Create and Insert the entry in the reception buffer.          @n
706  *        2. Check for firstSn in reestablish state.                       @n
707  *        3. Update nxtSubCnt and nxtSubDeCmp.                             @n
708  *        4. Call pjUtlDecipher to perform deciphering.                    @n
709  *        5. Call pjUtlDecomp to perform integrity verification.           @n
710  *        6. Call pjUlmDeliverDrbUm for performing state updations and 
711  *           submitting to upper layers.                                   @n
712  *                                               
713  *  @param[in] pjRbCb   PDCP control block 
714  *  @param[in] rcvdSn       SN value of the pdu
715  *  @param[in] pdu      PDU message buffer.
716  *
717  *  @return  S16
718  *      -# ROK 
719  *      -# RFAILED
720  */
721 #ifdef ANSI
722 PUBLIC S16 pjUlmProcessRb
723 (
724 PjCb     *gCb,
725 PjUlRbCb   *pjRbCb,          /* !< PDCP Control Block */   
726 PjSn       rcvdSn,               /* !< SN value of PDU */           
727 Buffer   *pdu,              /* !< PDU message buffer */           
728 Bool     isOutOfSeq         /* !< To indicate whether packet received is in-sequence or not */
729 )
730 #else
731 PUBLIC S16 pjUlmProcessRb(gCb, pjRbCb, rcvdSn, pdu, isOutOfSeq)
732 PjCb      *gCb;
733 PjUlRbCb    *pjRbCb;         /* !< PDCP Control Block */     
734 PjSn      rcvdSn;              /* !< SN value of PDU */           
735 Buffer   *pdu;             /* !< PDU message buffer */           
736 Bool     isOutOfSeq;         /* !< To indicate whether packet received is in-sequence or not */
737 #endif
738 {
739    PjUlCb       *ulCb;            /* PTR to UL Control Block     */
740    PjRxEnt      *rxEnt;           /* Ptr to Rx Entry             */
741    S16          ret      = ROK;   /* Return value                */
742    U32          rcvdCount;           /* Count value */
743    U32          rcvdHfn;
744    Bool         dupEntry;
745    U32          rxDelivHfn; 
746 #ifdef PJ_SEC_ASYNC
747    U32          oldRxCnt;        /* Old Count value used for decomp */
748 #endif
749     
750    TRC2(pjUlmProcessRb)
751
752    /* 1. Initialisations */
753    ulCb  = &pjRbCb->ulCb;
754
755    /*1.5G-NR Determine the Hfn and count value of the received PDCP data pdu*/
756    PJ_CALC_RCVD_HFN(rcvdSn,pjRbCb->snLen,ulCb->rxDeliv,rcvdHfn);
757
758    /*2.5G-NR Get the count value of the receiced PDCP data pdu from rcvdSn and rcvdHfn  */
759    PJ_GET_COUNT(rcvdCount, pjRbCb->snLen, rcvdSn, rcvdHfn);
760    
761
762    /* 3. Create the entry */
763    PJ_ALLOC(gCb,rxEnt, sizeof(PjRxEnt));
764 #if (ERRCLASS & ERRCLS_DEBUG)
765    if(rxEnt == NULLP)
766    {
767       RLOG0(L_FATAL, "Memory Allocation failed.");
768       RETVALUE(RFAILED);
769    }
770 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
771
772    /* 4. Fill values and Insert into hash list */
773    rxEnt->count   =  rcvdCount;
774    rxEnt->state   =  PJ_RDY_TO_DCIPHER;
775    rxEnt->mBuf    =  pdu;
776    rxEnt->lstEnt.next = NULLP;
777    rxEnt->lstEnt.prev = NULLP;
778    rxEnt->lstEnt.node = NULLP;
779    rxEnt->discFlag = rxEnt->dupEntry = 0;
780    rxEnt->isOutSeq = isOutOfSeq;
781    
782    PJ_GET_HFN(ulCb->rxDeliv,pjRbCb->snLen,rxDelivHfn)
783     
784    if((rcvdCount < ulCb->rxDeliv) &&(rxDelivHfn != PJ_MAX_HFN(pjRbCb->snLen)))
785    {
786       rxEnt->discFlag = TRUE;
787       PJ_FREE_BUF(rxEnt->mBuf);
788       PJ_FREE(gCb,rxEnt, sizeof(PjRxEnt));
789       RETVALUE(ROK);
790    }
791
792    ret = pjDbmInsRxEnt(gCb, &ulCb->recBuf, rxEnt, TRUE);
793    if(ret == ROKDUP)
794    {
795       /* Duplicates are not to be inserted */
796       /* marked to be freed up later */
797       rxEnt->dupEntry =  TRUE;
798    }
799    dupEntry = rxEnt->dupEntry;
800    
801    /* 7. Cleanup the duplicates */
802    if(dupEntry == TRUE)
803    {
804       /* duplicate entry, Need to add a counter to print it on console periodically */
805       PJ_FREE_BUF(rxEnt->mBuf);
806       PJ_FREE(gCb,rxEnt, sizeof(PjRxEnt));
807       RETVALUE(ROK);
808    }
809
810    /*3.Update the RX_NEXT */
811    PJ_ULM_UPDATE_RX_NEXT(pjRbCb,rxEnt);
812
813 #ifdef PJ_SEC_ASYNC
814    oldRxCnt = ulCb->rxNext; 
815    PJ_ULM_UPD_NXT2DCOMP(ulCb, (pjRbCb->snLen), rcvdCount,oldRxCnt);
816    PJ_ULM_UPD_NXT2SUB(ulCb, rcvdCount); 
817 #endif
818
819    /* 5. Update OBD count */
820    PJ_INC_OBD_COUNT(pjRbCb,rxEnt->count);
821
822    /* Check whether the received packet is in-sequence or not
823     * For every inSeq packet store the FMS Count value corresponding
824     * to the FMS + HFN now */
825    if((isOutOfSeq == FALSE) &&
826       (pjRbCb->rbType == PJ_DRB) &&  
827       (pjRbCb->mode == PJ_DRB_AM))
828    {
829       /*Need to be check again */
830       pjRbCb->ulCb.fmsCount = ulCb->rxNext ;  
831    }
832
833    /* 6. Send for deciphering */
834    ret = pjUlmHdlDecipher(gCb, pjRbCb, rxEnt);
835
836    RETVALUE(ret);
837 }/* pjUlmProcessRb */
838
839 \f
840 /**
841  *
842  * @brief 
843  *
844  *        Function is called when the offboard timer expires.
845  *
846  * @b Description: 
847  *
848  *    The function performs the following
849  *    1. If the SDU associated with the timer is not delivered, we 
850  *       delete the entry .                                              @n
851  *    2. A status indication is sent to the user with error cause.       @n
852  *    3. We associate the nextToSubmit value to the next SDU that has 
853  *       to be submitted.                                                @n
854  *    4. The timer is associated with the nextToSubmit SDU and restarted.@n
855  *                                               
856  *  @param[in] pjRbCb   PDCP control block 
857  *  @param[in] rxEnt    Rx Entry
858  *
859  *  @return  S16
860  *      -# ROK 
861  *      -# RFAILED
862  */
863 #ifdef ANSI
864 PUBLIC S16 pjUlmHdlDecipher
865 (
866 PjCb       *gCb,
867 PjUlRbCb     *pjRbCb,        /* !< PDCP Control Block */  
868 PjRxEnt    *rxEnt          /* !< Rx Entry */
869 )
870 #else
871 PUBLIC S16 pjUlmHdlDecipher(gCb, pjRbCb, rxEnt)
872 PjCb       *gCb;
873 PjUlRbCb     *pjRbCb;        /* !< PDCP Control Block */  
874 PjRxEnt    *rxEnt;         /* !< Rx Entry */
875 #endif
876 {
877    PjUlCb   *ulCb;            /* ULM Control Block        */
878    S16       ret     = ROK;   /* Return values            */
879    Buffer   *mBuf    = NULLP; /* Output Buffer            */
880    PjSec     *secInfo;
881    U32        macI = 0;       /*5G_NR for DRB, its a 4 byte field */
882    TRC2(pjUlmHdlDecipher);
883
884 #ifndef ALIGN_64BIT
885    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
886          (gCb->init.prntBuf, "pjUlmHdlDecipher(pjRbCb(%d,%d),rxEnt(%ld)) \n", \
887           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
888 #else
889    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
890          (gCb->init.prntBuf, "pjUlmHdlDecipher(pjRbCb(%d,%d),rxEnt(%d)) \n", \
891           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
892 #endif
893
894    /* 1. Initialistions */
895    ulCb  =  &pjRbCb->ulCb;
896
897    secInfo = &(pjRbCb->ueCb->secInfo); 
898    /* 2. Process for Deciphering */
899    if(secInfo->secAct == TRUE && secInfo->cipherInfo.algoType != 0)
900    {
901       /* 2.1 Check that it is not the first pkt, with selectively enabled */
902       if((pjRbCb->rbType == PJ_SRB) && 
903          (pjRbCb->ueCb->secInfo.firstMsg && pjRbCb->ueCb->secInfo.selSecAct))
904       {
905          /* first pkt */
906          pjRbCb->ueCb->secInfo.firstMsg   =  FALSE;
907       }
908       else
909       {
910 #ifndef TENB_ACC 
911 #ifndef LTE_PAL_ENB         
912          pjUtlChekRxEnqReq(gCb, pjRbCb, rxEnt);
913 #endif         
914 #endif         
915 #ifdef SS_RBUF
916          if(rxEnt->rbCb)
917          {
918             RETVALUE(ROK);
919          }
920 #endif
921          /* 2.3 call deciphering hook */
922          if( pjUtlDecipherReq(gCb, pjRbCb, rxEnt->count, rxEnt->mBuf, &mBuf) != ROK)
923          {
924             RLOG1(L_ERROR, "Deciphering Req failed Rx Count [%lu]", rxEnt->count);
925             PJ_SND_PJU_STA_IND(gCb,pjRbCb, rxEnt);
926             pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
927             PJ_STS_INC_GEN_CNT(gCb,numDeciphFails);
928             RETVALUE(RFAILED);
929          }
930
931          
932          /* 2.4 wait for output before processing further */
933     /* Batch Mode processing, Packets queued will be sent to spacc 
934        together upon trigger */
935 #ifdef TENB_AS_SECURITY
936          if(isSecBatchMode)
937          {
938             rxEnt->state   =  PJ_SENT_TO_DCIPHER;
939             RETVALUE(ROK);       
940          }
941 #endif
942
943 #if defined (PJ_SEC_ASYNC) || defined (INTEL_QAT_DP)
944          /* 2.4 wait for output before processing further */
945          rxEnt->state   =  PJ_SENT_TO_DCIPHER;
946          RETVALUE(ROK);
947 #else   /* PJ_SEC_ASYNC */
948          /* 2.3 Validate output of deciphering */
949          if(mBuf == NULLP)
950          {
951             RLOG1(L_ERROR, "Deciphering Req failed Rx Count [%lu]", rxEnt->count);
952             PJ_SND_PJU_STA_IND(gCb,pjRbCb, rxEnt);
953             pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
954             PJ_STS_INC_GEN_CNT(gCb,numDeciphFails);
955             RETVALUE(RFAILED);
956          }
957
958          /* 2.5 copy output buffer */
959 #ifdef TENB_AS_SECURITY
960          /* If not batch mode, free PDU. If batch mode, free will be done upon
961          SPAcc return */
962          if(!(isSecBatchMode))
963          {
964             PJ_FREE_BUF(rxEnt->mBuf);
965          }
966 #endif
967          rxEnt->mBuf     =  mBuf;
968 #endif
969       }
970    }
971 #ifdef TENB_DPDK_BUF
972    else if(pjRbCb->rbType == PJ_DRB)
973    {
974       pjUpdRxEntBuf(rxEnt);
975    }
976 #endif
977    /* 3. Post ciphering updations */
978    if(pjRbCb->rbType == PJ_DRB)
979    {
980       rxEnt->state   =  PJ_RDY_TO_DCOMP;
981       /*Adding MACI for 5G NR for DRB in case of intergrity protection is enabled*/
982       if(pjRbCb->ueCb->secInfo.intProtEnbForDrb)
983       {
984          PJ_UNPK_MACI(rxEnt->mBuf, macI);
985       }
986       ret = pjUlmHdlDeCmp(gCb, pjRbCb, rxEnt);
987    }
988    else
989    {
990       rxEnt->state   =  PJ_RDY_TO_INTVER;
991       ret = pjUlmHdlIntVer(gCb, pjRbCb, rxEnt);
992    }
993
994    RETVALUE(ret);
995 }/* end of pjUlmHdlDecipher */
996
997 \f
998 /**
999  *
1000  * @brief 
1001  *
1002  *        Function is called to perform integrity verification.
1003  *
1004  * @b Description: 
1005  *
1006  *    The function performs the following
1007  *    1. Extract the mac-I.
1008  *    2. Add sn to the buffer.
1009  *    3. Call Integrity Verification hook.
1010  *    4. Return in case of Async.
1011  *    5. Validate output and submit for delivery.
1012  *                                               
1013  *  @param[in] pjRbCb   PDCP control block 
1014  *  @param[in] rxEnt    Rx Entry
1015  *
1016  *  @return  S16
1017  *      -# ROK 
1018  *      -# RFAILED
1019  */
1020 #ifdef ANSI
1021 PUBLIC S16 pjUlmHdlIntVer
1022 (
1023 PjCb       *gCb,
1024 PjUlRbCb     *pjRbCb,        /* !< PDCP Control Block */  
1025 PjRxEnt    *rxEnt          /* !< Rx Entry */
1026 )
1027 #else
1028 PUBLIC S16 pjUlmHdlIntVer(gCb, pjRbCb, rxEnt)
1029 PjCb       *gCb;
1030 PjUlRbCb     *pjRbCb;        /* !< PDCP Control Block */  
1031 PjRxEnt    *rxEnt;         /* !< Rx Entry */
1032 #endif
1033 {
1034    PjUlCb  *ulCb;          /* ULM Control Block */
1035    PjSn     sn;            /* Sn Value */    /*KW_FIX*/
1036    S16      ret = ROK;     /* Return value */
1037    U32      macI = 0;      /* Mac-I value */
1038    PjSecInp inParam;       /* Input Params */
1039    Status   status = ROK;        /* Status of IntVer */
1040
1041    TRC2(pjUlmHdlIntVer);
1042
1043 #ifndef ALIGN_64BIT
1044    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1045          (gCb->init.prntBuf, "pjUlmHdlIntVer(pjRbCb(%d,%d),rxEnt(%ld)) \n", \
1046           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1047 #else
1048    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1049          (gCb->init.prntBuf, "pjUlmHdlIntVer(pjRbCb(%d,%d),rxEnt(%d)) \n", \
1050           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1051 #endif
1052
1053    /* 1. Initialistions */
1054    ulCb  =  &pjRbCb->ulCb;
1055
1056    /* 2. Xtract the last four bits irrescpective of whether you 
1057     * are going to do integrity verification or not */
1058
1059    /* RANGELEY  Fix */
1060 #ifndef INTEL_QAT_DP
1061    PJ_UNPK_MACI(rxEnt->mBuf, macI);
1062 #endif
1063
1064    /* 3. Process for Integrity Verification */
1065    if(pjRbCb->ueCb->secInfo.secAct == TRUE && pjRbCb->ueCb->secInfo.intInfo.algoType != 0)
1066    {
1067
1068       /* 3.1 Prepare the input Parameters */
1069       inParam.dir    =  PJ_SEC_DIR_UL;
1070       inParam.rbId   =  pjRbCb->rbId;
1071       inParam.count  =  rxEnt->count;
1072
1073       /* 3.2. Add the SN to the buffer */
1074       sn  =  (U32)(rxEnt->count % (1 << PJ_SRB_SN_LEN));  /*KW_FIX*/
1075       ret = SAddPreMsg((Data)sn, rxEnt->mBuf);
1076 #if (ERRCLASS & ERRCLS_DEBUG)
1077       if (ret != ROK)
1078       {
1079          RLOG_ARG0(L_ERROR, DBG_UEID,pjRbCb->ueCb->key.ueId,
1080                " pjUlmProcessRb: SRemPreMsgMult Failed ");
1081          pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
1082          RETVALUE(RFAILED);
1083       }
1084 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
1085
1086       /* 3.3 call deciphering hook */
1087       if( pjUtlIntVerReq(gCb, pjRbCb, inParam, rxEnt->mBuf, macI, &status) != ROK)
1088       {
1089          RLOG1(L_ERROR, "Integrity Verification Req failed Rx Count[%lu]", rxEnt->count);
1090          ret = SRemPreMsg((Data *)&sn, rxEnt->mBuf);
1091          if (ret != ROK)
1092          {
1093          }
1094          PJ_SND_PJU_STA_IND(gCb,pjRbCb, rxEnt);
1095          rxEnt->state = PJ_RX_INTVER_FAIL;
1096          pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
1097          PJ_STS_INC_GEN_CNT(gCb,numIntgVrfFails);
1098          RETVALUE(RFAILED);
1099       }
1100 #ifdef INTEL_QAT_DP   
1101       /* 3.5 wait for output before processing further */
1102       rxEnt->state   =  PJ_SENT_TO_INTVER;
1103       RETVALUE(ROK);
1104 #else
1105       /* 3.4. Remove the SN from the buffer */
1106       ret = SRemPreMsg((Data *)&sn, rxEnt->mBuf);
1107 #if (ERRCLASS & ERRCLS_DEBUG)
1108       if (ret != ROK)
1109       {
1110          RLOG1(L_ERROR, "SRemPreMsg failed  Rx Count [%lu]", rxEnt->count);
1111          PJ_FREE_BUF(rxEnt->mBuf);
1112          pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
1113          RETVALUE(RFAILED);
1114       }
1115 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
1116
1117 #ifdef PJ_SEC_ASYNC
1118       /* 3.5 wait for output before processing further */
1119       rxEnt->state   =  PJ_SENT_TO_INTVER;
1120       RETVALUE(ROK);
1121 #else
1122       /* 3.6 Post integrity verification updations */
1123       if(status != ROK)
1124       {
1125          RLOG1(L_ERROR, "Integrity Verification Req failed Rx Count[%lu]", rxEnt->count);
1126          PJ_SND_PJU_STA_IND(gCb,pjRbCb, rxEnt);
1127          pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
1128          PJ_STS_INC_GEN_CNT(gCb,numIntgVrfFails);
1129          RETVALUE(RFAILED);
1130       }
1131
1132 #endif /* PJ_SEC_ASYNC */
1133 #endif /*INTEL_QAT_DP */
1134    }
1135 #ifdef INTEL_QAT_DP
1136    else 
1137    {
1138 #endif
1139       /* 4. Update state and send for delivery */
1140       rxEnt->state   =  PJ_RDY_TO_SUBMIT;
1141       ret = pjUlmDeliverSrb(gCb, pjRbCb, rxEnt);
1142 #ifdef INTEL_QAT_DP
1143    }
1144 #endif
1145
1146    RETVALUE(ret);
1147 }/* end of pjUlmHdlIntVer */
1148
1149 \f
1150 /**
1151  *
1152  * @brief 
1153  *
1154  *        Function is called to handle decompression.
1155  *
1156  * @b Description: 
1157  *
1158  *    The function performs the following
1159  *    1. Call decompression handler function.
1160  *    2. For sync, validate output and submit for delivery.
1161  *                                               
1162  *  @param[in] pjRbCb   PDCP control block 
1163  *  @param[in] rxEnt    Rx Entry
1164  *
1165  *  @return  S16
1166  *      -# ROK 
1167  *      -# RFAILED
1168  */
1169 #ifdef ANSI
1170 PUBLIC S16 pjUlmHdlDeCmp
1171 (
1172 PjCb       *gCb,
1173 PjUlRbCb     *pjRbCb,        /* !< PDCP Control Block */  
1174 PjRxEnt    *rxEnt          /* !< Rx Entry */
1175 )
1176 #else
1177 PUBLIC S16 pjUlmHdlDeCmp(gCb, pjRbCb, rxEnt)
1178 PjCb       *gCb;
1179 PjUlRbCb     *pjRbCb;        /* !< PDCP Control Block */  
1180 PjRxEnt    *rxEnt;         /* !< Rx Entry */
1181 #endif
1182 {
1183    PjUlCb  *ulCb;          /* ULM Control Block */
1184    Buffer  *mBuf = NULLP;  /* Output Buffer */
1185
1186    TRC2(pjUlmHdlDeCmp);
1187
1188 #ifndef ALIGN_64BIT
1189    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1190           (gCb->init.prntBuf, "pjUlmHdlDeCmp(pjRbCb(%d,%d),rxEnt(%ld)) \n", \
1191             pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1192 #else
1193    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1194           (gCb->init.prntBuf, "pjUlmHdlDeCmp(pjRbCb(%d,%d),rxEnt(%d)) \n", \
1195             pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1196 #endif
1197
1198    /* 1. Initialistions */
1199    ulCb  =  &pjRbCb->ulCb;
1200
1201    /* 2. process for decompression */
1202    if(pjRbCb->rohc.hdrCmpUsed == TRUE)
1203    {
1204       /* 2.1 call decompression hook */
1205       if(pjUtlDeCmpReq(gCb, pjRbCb,rxEnt->count, rxEnt->mBuf, &mBuf) != ROK)
1206       {
1207          RLOG1(L_ERROR, "DeCompression Req failed Rx Count[%lu]", rxEnt->count);
1208          PJ_SND_PJU_STA_IND(gCb,pjRbCb, rxEnt);
1209          pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
1210          PJ_STS_INC_GEN_CNT(gCb,numDecmpFails);
1211          RETVALUE(RFAILED);
1212       }
1213
1214 #ifdef PJ_CMP_ASYNC
1215       /* 2.2 Wait for output before processing further */
1216       rxEnt->state   =  PJ_SENT_TO_DCOMP;
1217       RETVALUE(ROK);
1218 #else /* PJ_CMP_ASYNC */
1219
1220       /* 2.3 Validate output of decomp */
1221       if(mBuf == NULLP)
1222       {
1223          RLOG1(L_ERROR, "DeCompression Req failed Rx Count[%lu]", rxEnt->count);
1224          PJ_SND_PJU_STA_IND(gCb,pjRbCb, rxEnt);
1225          pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
1226          PJ_STS_INC_GEN_CNT(gCb,numDecmpFails);
1227          RETVALUE(RFAILED);
1228       }
1229
1230       /* 2.4 Copy output buffer */
1231       PJ_FREE_BUF(rxEnt->mBuf);
1232       rxEnt->mBuf     =  mBuf;
1233 #endif
1234    }
1235
1236    /* 3. Return for discardable entries */
1237    if((rxEnt->discFlag == TRUE) ||
1238       (rxEnt->dupEntry == TRUE))
1239    {
1240       RLOG2(L_ERROR,"Dropping packets...discflag is [%d], dupEntry is [%d]", rxEnt->discFlag, rxEnt->dupEntry);
1241       RETVALUE(ROK);
1242    }
1243
1244    /* 4. Post decomp updations */
1245    rxEnt->state   =  PJ_RDY_TO_SUBMIT;
1246    PJ_DEC_OBD_COUNT(gCb, pjRbCb, rxEnt->count);
1247    PJ_ULM_DELIVER_DRB(gCb,pjRbCb, rxEnt);
1248
1249    RETVALUE(ROK);
1250 }/* end of pjUlmHdlDeCmp */
1251
1252 #ifdef ANSI
1253 PUBLIC S16 pjUlmDeliverPdu
1254 (
1255 PjCb   *gCb,
1256 PjUlRbCb *pjRbCb,           /* !< PDCP Control Block */                  
1257 PjRxEnt *rxEnt            /* !< Recption Buffer Entry   */             
1258 )
1259 #else
1260 PUBLIC S16 pjUlmDeliverPdu(gCb,pjRbCb, rxEnt)
1261 PjCb    *gCb;
1262 PjUlRbCb *pjRbCb;           /* !< PDCP Control Block */                  
1263 PjRxEnt *rxEnt;           /* !< Recption Buffer Entry   */             
1264 #endif
1265 {
1266    PjUlCb   *ulCb;
1267    PjRxEnt *tmpEnt;      /* Temp Entry - loop counter */
1268    U32 rxReOrdHfn,rxNextHfn, rxDelivHfn;
1269
1270
1271    TRC2(pjUlmDeliverPdu)
1272
1273    /* Initialisations */
1274    ulCb           =  &pjRbCb->ulCb;
1275    if(rxEnt->state != PJ_RDY_TO_SUBMIT)
1276    {
1277       /* PDU still under processing, return */
1278       RETVALUE(ROK);
1279    }
1280    ulCb->outOfOrderDelivery = FALSE;
1281
1282    if(ulCb->outOfOrderDelivery == FALSE )
1283    {
1284
1285       /* submit to upper layers and delete entry */
1286       /* submit all the stored pdu's with consecutively associated COUNT value(s) starting from COUNT = RX_DELIV*/
1287       if(rxEnt->count == ulCb->rxDeliv)
1288       {
1289          cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
1290          if(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ))
1291          {
1292
1293              tmpEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ));
1294              do
1295              {
1296                      PJ_SND_PJU_DAT_IND(gCb,pjRbCb, tmpEnt);
1297                      pjDbmDelRxEnt(gCb, &ulCb->recBuf, tmpEnt->count);
1298                      /*updating the stateVariable*/
1299                      ulCb->rxDeliv      =   ulCb->rxDeliv + 1;
1300                      cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
1301                      if(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ) == NULLP)
1302                      {
1303                              break;
1304                      }
1305                      tmpEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ));
1306              }while(tmpEnt->count == ulCb->rxDeliv);
1307          }
1308       }
1309    }
1310    /*If out of order Delivery is configured*/
1311    else
1312    {
1313       PJ_SND_PJU_DAT_IND(gCb,pjRbCb, rxEnt);
1314       pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
1315       /*updating the stateVariable*/
1316       ulCb->rxDeliv      =   ulCb->rxDeliv + 1;
1317
1318    }
1319    
1320    /* Update the Reordering state variable reffer sec 5.2.2.2 of 38.323 */
1321    Bool   tmrRunning;
1322    PJ_GET_HFN(ulCb->rxDeliv,pjRbCb->snLen,rxDelivHfn);
1323    tmrRunning = pjChkTmr(gCb,(PTR)pjRbCb, PJ_EVT_UL_REORD_TMR);
1324    if (tmrRunning)
1325    {
1326       PJ_GET_HFN(ulCb->rxDeliv,pjRbCb->snLen,rxReOrdHfn);
1327      if ((ulCb->rxDeliv >= ulCb->rxReord) || 
1328          ((PJ_MAX_HFN(pjRbCb->snLen) == rxReOrdHfn) &&
1329           (0 == rxDelivHfn)))
1330      {
1331        pjStopTmr(gCb,(PTR)pjRbCb, PJ_EVT_UL_REORD_TMR);
1332        tmrRunning = FALSE;
1333      }
1334    }
1335    
1336   if (!tmrRunning)
1337   {
1338       PJ_GET_HFN(ulCb->rxNext, pjRbCb->snLen,rxNextHfn);
1339      if ((ulCb->rxDeliv < ulCb->rxNext) || 
1340          (((PJ_MAX_HFN(pjRbCb->snLen) == rxDelivHfn)) && 
1341            (0 == rxNextHfn)))
1342      {
1343         ulCb->rxReord = ulCb->rxNext;
1344         pjStartTmr(gCb,(PTR)pjRbCb, PJ_EVT_UL_REORD_TMR);
1345      }
1346   }
1347
1348 RETVALUE(ROK);
1349 }
1350
1351
1352 \f
1353 /**
1354  *
1355  * @brief 
1356  *
1357  *        Function to perform updations and deliver the SDU to the upper layer. 
1358  *        It is called for SRBs .
1359  *
1360  * @b Description: 
1361  *
1362  *        This function performs the following functions,                    @n
1363  *        1. Call PjUiPjuDatInd to deliver the SDU to the upper layer.       @n
1364  *        2. In async mode, check if any subsequent SDUs can also be sent up.@n
1365  *                                               
1366  *  @param[in] pjRbCb   PDCP control block 
1367  *  @param[in] rxEn     reception entry for the PDU
1368  *  @return  S16
1369  *      -# ROK 
1370  *      -# RFAILED
1371  */
1372 #ifdef ANSI
1373 PUBLIC S16 pjUlmDeliverSrb
1374 (
1375 PjCb   *gCb,
1376 PjUlRbCb *pjRbCb,          /* !< PDCP Control Block */     
1377 PjRxEnt *rxEnt           /* !< Recption Buffer Entry   */            
1378 )
1379 #else
1380 PUBLIC S16 pjUlmDeliverSrb(gCb, pjRbCb, rxEnt)
1381 PjCb   *gCb;
1382 PjUlRbCb *pjRbCb;          /* !< PDCP Control Block */                  
1383 PjRxEnt *rxEnt;          /* !< Recption Buffer Entry   */             
1384 #endif
1385 {
1386 #ifdef PJ_SEC_ASYNC
1387    PjUlCb     *ulCb;
1388    U32      count;        /* Count for looping through the entries */
1389    U32      nxtRxCnt;     /* Count for looping through the entries */
1390    PjRxEnt  *tmpEnt;      /* Temp var for looping through the entries */
1391 #endif
1392
1393    TRC2(pjUlmDeliverSrb);
1394 #ifndef ALIGN_64BIT
1395    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1396           (gCb->init.prntBuf, "pjUlmDeliverSrb(pjRbCb(%d,%d),rxEnt(%ld)) \n", \
1397             pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1398 #else
1399    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1400           (gCb->init.prntBuf, "pjUlmDeliverSrb(pjRbCb(%d,%d),rxEnt(%d)) \n", \
1401             pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1402 #endif
1403
1404    /* Post integrity verification updations */
1405 #ifdef PJ_SEC_ASYNC
1406    count          =  rxEnt->count;
1407    ulCb           =  &pjRbCb->ulCb;
1408 #endif
1409    pjUlmDeliverPdu(gCb,pjRbCb,rxEnt); 
1410    
1411 #ifdef PJ_SEC_ASYNC
1412    tmpEnt = NULLP;
1413    /* Search and see if any of the successive SDUs can 
1414     * also be sent to the upper layer */
1415    count++;
1416    nxtRxCnt  =  ulCb->rxNext;
1417
1418    /* Check till nxtRxCnt */
1419    while(count < nxtRxCnt) 
1420    {
1421       /* Get the next node */
1422       tmpEnt   =  (PjRxEnt *)pjDbmGetRxEnt(gCb, &ulCb->recBuf, count);
1423       count ++;
1424
1425       if(tmpEnt == NULLP)
1426       {
1427          /* Such an entry does not exist, search for the next */
1428          continue;
1429       }
1430       if(tmpEnt->state != PJ_RDY_TO_SUBMIT)
1431       {
1432          /* Integrity verification not yet done so we have to wait */
1433          ulCb->nxtSubCnt =  tmpEnt->count;
1434          /* Cant send anymore messages up, break*/
1435          break;
1436       }
1437       else
1438       {
1439          /* call the PJU Primitive to deliver it to upper layers */
1440          PJ_SND_PJU_DAT_IND(gCb,pjRbCb, tmpEnt);
1441
1442          /* cleanup the entry */
1443          pjDbmDelRxEnt(gCb, &ulCb->recBuf, tmpEnt->count);
1444       }
1445    }
1446
1447    if( ((count == nxtRxCnt) &&(tmpEnt != NULLP) &&(tmpEnt->state == PJ_RDY_TO_SUBMIT)) ||
1448        ((count == nxtRxCnt) &&(tmpEnt == NULLP)) )
1449    {
1450      if((pjChkTmr(gCb, (PTR)pjRbCb, PJ_EVT_UL_OBD_TMR)) == TRUE) 
1451      {                                                            
1452          pjStopTmr(gCb, (PTR)pjRbCb, PJ_EVT_UL_OBD_TMR);          
1453      }
1454    }
1455 #endif /* PJ_SEC_ASYNC */
1456
1457
1458    RETVALUE(ROK);
1459 }/* pjUlmDeliverSrb */
1460
1461 \f
1462 /**
1463  *
1464  * @brief 
1465  *
1466  *        Function to deliver the SDU to the upper layer. 
1467  *        It is called for DRB UM
1468  *
1469  * @b Description: 
1470  *
1471  *        This function performs the following functions.                  @n
1472  *        1. Deliver the SDU to the upper layer                            @n
1473  *        2. Clean up the hash list entry for this SDU.                    @n
1474  *        3. For asynchronous mode, it checks if any subsequent 
1475  *           messages can also be sent up.                                 @n
1476  *        4. Mark the next SDU to be submitted to the upper layers.        @n
1477  *                                               
1478  *  @param[in] pjRbCb   PDCP control block 
1479  *  @param[in] rxEnt    reception entry for the PDU
1480  *  @return  S16
1481  *      -# ROK 
1482  *      -# RFAILED
1483  */
1484 #ifdef ANSI
1485 PUBLIC S16 pjUlmDeliverDrbUm 
1486 (
1487 PjCb   *gCb,
1488 PjUlRbCb *pjRbCb,        /* !< PDCP Control Block */                  
1489 PjRxEnt *rxEnt         /* !< Recption Buffer Entry   */             
1490 )
1491 #else
1492 PUBLIC S16 pjUlmDeliverDrbUm(gCb, pjRbCb, rxEnt)
1493 PjCb   *gCb;
1494 PjUlRbCb *pjRbCb;        /* !< PDCP Control Block */                  
1495 PjRxEnt *rxEnt;        /* !< Recption Buffer Entry   */             
1496 #endif
1497 {
1498
1499 #ifdef PJ_CMP_ASYNC
1500    PjUlCb   *ulCb;     /* Uplink Cb Ptr */
1501    U32      nxtRxCnt;  /* Count for looping through the entries */
1502    PjRxEnt  *tmpEnt;   /* Temp var for looping through the entries */
1503    U32      count;     /* count varaible */ 
1504    ulCb  =  &pjRbCb->ulCb;
1505 #endif
1506
1507    TRC2(pjUlmDeliverDrbUm)
1508 #ifndef ALIGN_64BIT
1509    PJDBGP(gCb, (PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1510          (gCb->init.prntBuf, "pjUlmDeliverDrbUm(pjRbCb(%d,%d),rxEnt(%ld)) \n", \
1511           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1512 #else
1513    PJDBGP(gCb, (PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1514          (gCb->init.prntBuf, "pjUlmDeliverDrbUm(pjRbCb(%d,%d),rxEnt(%d)) \n", \
1515           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1516 #endif
1517
1518    /* Initialisations */
1519
1520    /* Update state */
1521    rxEnt->state   =  PJ_RDY_TO_SUBMIT;
1522
1523 #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
1524    if(rxEnt->count != ulCb->nxtSubCnt)
1525    {
1526       RETVALUE(ROK);
1527    }
1528 #endif /* (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC)) */
1529 #ifndef PJ_CMP_ASYNC
1530 #endif
1531 #ifndef RGL_SPECIFIC_CHANGES
1532 #ifndef TENB_ACC
1533 #ifndef LTE_PAL_ENB
1534    EXTERN U32 ulrate_pju;
1535       MsgLen len;
1536       SFndLenMsg(rxEnt->mBuf, &len);
1537       ulrate_pju += len;
1538 #endif      
1539 #endif      
1540 #endif
1541      
1542       pjUlmDeliverPdu(gCb,pjRbCb,rxEnt); 
1543
1544       
1545 #ifdef PJ_CMP_ASYNC
1546
1547    /* Search and see if any of the succeeding SNs can 
1548     * also be sent to the upper layer */
1549    nxtRxCnt  =  ulCb->rxNext;
1550
1551    /* Search till nextRxCnt */
1552    for(count = ulCb->nxtSubCnt + 1; count < nxtRxCnt; count++) 
1553    {
1554       /* Get the next node */
1555       tmpEnt   =  (PjRxEnt *)pjDbmGetRxEnt(gCb, &(ulCb->recBuf), count);
1556
1557       if(tmpEnt == NULLP)
1558       {
1559          /* pj005.201 added support for L2 Measurement */
1560          /* Such an entry does not exist, search for the next */
1561          continue;
1562       }
1563       if(tmpEnt->state != PJ_RDY_TO_SUBMIT)
1564       {
1565          /* Cant send anymore messages up, break*/
1566          break;
1567       }
1568       else
1569       {
1570          /* pj005.201 added support for L2 Measurement */
1571          /* call the PJU Primitive to deliver it to upper layers */
1572          PJ_SND_PJU_DAT_IND(gCb,pjRbCb, tmpEnt);
1573
1574          /* cleanup the entry */
1575          pjDbmDelRxEnt(gCb, &ulCb->recBuf, tmpEnt->count);
1576       }
1577    }/* end of while */
1578
1579    /* Update  nxtSubCnt */
1580    ulCb->nxtSubCnt =  count;
1581 #endif /* PJ_CMP_ASYNC */
1582
1583 #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
1584    if(pjRbCb->state != PJ_STATE_NORMAL)
1585    {
1586       /* start reestablishment procedures if last message has been processed */
1587       if((ulCb->transCmp == TRUE) && 
1588             (ulCb->obdCnt == 0))
1589       {
1590          /* It has received all messages from RLC and finished
1591           * processing them. Possibility only when the last last message
1592           * from deciphering fails. */
1593          PJ_ULM_DRBUM_REEST(gCb, pjRbCb);
1594       }
1595    }
1596 #endif /* (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC)) */
1597
1598    RETVALUE(ROK);
1599 }/* pjUlmDeliverDrbUm */
1600 \f
1601 /**
1602  *
1603  * @brief 
1604  *
1605  *        Function to deliver the SDU to the upper layer. It is called for DRB AM
1606  *
1607  * @b Description: 
1608  *
1609  *        This function performs the following functions.                                  @n
1610  *        1. Delete duplicates and SDUs marked for discard.                                @n
1611  *        2. Deliver the SDU to the upper layer                                            @n
1612  *        3. Perform sequential delivery for SDUs received during reestablishment.         @n
1613  *        4. Clean up the hash list entry for this SDU.                                    @n
1614  *        5. For asynchronous mode, check if any subsequent messages can also be sent up.  @n
1615  *        6. Mark the next SDU to be submitted to the upper layers.                        @n
1616  *                                               
1617  *  @param[in] pjRbCb   PDCP control block 
1618  *  @param[in] rxEnt    Rx Entry
1619  *
1620  *  @return  S16
1621  *      -# ROK 
1622  *      -# RFAILED
1623  */
1624 #ifdef ANSI
1625 PUBLIC S16 pjUlmDeliverDrbAm
1626 (
1627 PjCb   *gCb,
1628 PjUlRbCb *pjRbCb,           /* !< PDCP Control Block */                  
1629 PjRxEnt *rxEnt            /* !< Recption Buffer Entry   */             
1630 )
1631 #else
1632 PUBLIC S16 pjUlmDeliverDrbAm(gCb, pjRbCb, rxEnt)
1633 PjCb   *gCb;
1634 PjUlRbCb *pjRbCb;           /* !< PDCP Control Block */                  
1635 PjRxEnt *rxEnt;           /* !< Recption Buffer Entry   */             
1636 #endif
1637 {
1638 #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
1639    PjUlCb  *ulCb;        /* RB uplink Control Block */
1640 #endif   
1641    S16      ret;         /* Return value */
1642
1643    TRC2(pjUlmDeliverDrbAm)
1644 #ifndef ALIGN_64BIT
1645    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1646          (gCb->init.prntBuf, "pjUlmDeliverDrbAm(pjRbCb(%d,%d),rxEnt(%ld)) \n", \
1647           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1648 #else
1649    PJDBGP(gCb,(PJ_DBGMASK_ULM | PJ_DBGMASK_DETAIL ),
1650          (gCb->init.prntBuf, "pjUlmDeliverDrbAm(pjRbCb(%d,%d),rxEnt(%d)) \n", \
1651           pjRbCb->rbId, pjRbCb->rbType, rxEnt->count));
1652 #endif
1653
1654    /* Initialisations */
1655    ret         = ROK;
1656 #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
1657    ulCb        = &pjRbCb->ulCb;
1658 #endif   
1659 #ifndef RGL_SPECIFIC_CHANGES
1660 #ifndef TENB_ACC
1661 #ifndef LTE_PAL_ENB
1662 extern U32 ulrate_pju;
1663 MsgLen len;
1664 SFndLenMsg(rxEnt->mBuf, &len);
1665 ulrate_pju += len;
1666 #endif
1667 #endif
1668 #endif
1669       pjUlmDeliverPdu(gCb,pjRbCb,rxEnt);
1670       #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
1671    /* start reestablishment procedures if last message has been processed */
1672    if(pjRbCb->state != PJ_STATE_NORMAL)
1673    {
1674       if((ulCb->transCmp == TRUE) && 
1675          (ulCb->obdCnt == 0))
1676       {
1677          /* It has received all messages from RLC and finished
1678           * processing them. Possibility only when the last last message
1679           * from deciphering fails. */
1680          pjUlmReEstDrbAm(gCb, pjRbCb);
1681       }
1682    }
1683 #endif /* (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC)) */
1684
1685    RETVALUE(ret);
1686 }/* pjUlmDeliverDrbAm */
1687
1688 /*****************************************************************************
1689  *                      REESTABLISHMENT FUNCTIONS
1690  ****************************************************************************/
1691 \f
1692 /**
1693  *
1694  * @brief 
1695  *
1696  *        Function to is called to reestablish the SRB. It is called as when the 
1697  *        reestablishment request  is received.
1698  *
1699  * @b Description: 
1700  *
1701  *        This function performes the following.      @n
1702  *        1. Reset NEXT_PDCP_RX_SN and RX_HFN         @n
1703  *        2. Deinitialise the hashlist.               @n
1704  *                                               
1705  *  @param[in] pjRbCb   PDCP control block 
1706  *  @return  S16
1707  *      -# ROK 
1708  *      -# RFAILED
1709  */
1710 #ifdef ANSI
1711 PUBLIC S16 pjUlmReEstSrb
1712 (
1713 PjCb   *gCb,
1714 PjUlRbCb *pjRbCb       /*!< PDCP control block  */
1715 )
1716 #else
1717 PUBLIC S16 pjUlmReEstSrb(gCb,pjRbCb)
1718 PjCb   *gCb;
1719 PjUlRbCb *pjRbCb;      /*!< PDCP control block  */
1720 #endif
1721 {
1722    TRC2(pjUlmReEstSrb);
1723
1724    /* Reset NEXT_PDCP_RX_SN and RX_HFN */
1725    pjRbCb->ulCb.rxNext  =  0;
1726    pjRbCb->ulCb.rxDeliv  =  0;
1727
1728    /* Deinitialise the hashlist */
1729    pjDbmRxDelAll(gCb, &pjRbCb->ulCb.recBuf);
1730
1731    RETVALUE(ROK);
1732 }  /* pjUlmResetSrb */
1733
1734
1735 \f
1736 /**
1737  *
1738  * @brief 
1739  *
1740  *        Function to is called to reestablish the DRB .
1741  *
1742  * @b Description: 
1743  *
1744  *        This function is called after the last pdu is received from RLC
1745  *        as part of reestablishment procedures. This function builds the staPdu
1746  *        and store it
1747  *                                               
1748  *  @param[in] pjCb     PDCP Instance control block 
1749  *  @param[in] pjRbCb   PDCP control block 
1750  *  @return  S16
1751  *      -# ROK 
1752  *      -# RFAILED
1753  */
1754 #ifdef ANSI
1755 PUBLIC S16 pjUlmReEstDrbAm
1756 (
1757 PjCb       *gCb,
1758 PjUlRbCb   *pjRbCb   
1759 )
1760 #else
1761 PUBLIC S16 pjUlmReEstDrbAm(gCb, pjRbCb)
1762 PjCb       *gCb;
1763 PjUlRbCb   *pjRbCb;   
1764 #endif
1765 {
1766         U16               fms;               /* First Missing SN                 */
1767         PjUlCb           *ulCb;              /* RB uplink Control Block          */
1768         PjSn              sn;                /* temp sn                          */
1769         PjRxEnt          *tmpEnt    = NULLP; /* Temporary entity used in loop    */
1770         U32               count;             /* Counter variable                 */
1771         U32               idx;
1772         U16               byteIdx = 0;
1773         U8                bitIdx;
1774         U8                numBits = 0;   /*KW_FIX */
1775         Bool              nxtSnNotFnd;
1776         PjUlHoCfmInfo     *hoInfo = NULLP;   /* To store the numBits and bitMap  */
1777         U8                packByte[512] = {0};
1778
1779         TRC2(pjUlmReEstDrbAm);
1780
1781         RLOG2(L_DEBUG,"pjUlmReEstDrbAm(pjRbCb(%d,%d))",pjRbCb->rbId,pjRbCb->rbType);
1782
1783         /* Initialisations */
1784         ulCb  =  &pjRbCb->ulCb;
1785         PJ_MEM_SET(&(packByte), 0, (sizeof(packByte)));       /*KW_FIX : ccpu00136902*/
1786         /* Its DRB AM from now on */
1787         if(pjRbCb->state == PJ_STATE_REEST)
1788         {
1789                 /* if status report generation not necessary, quit */
1790                 if(ulCb->staRepReqd == FALSE)
1791                 {
1792                         RETVALUE(ROK);
1793                 }
1794         }
1795
1796         /* If out-of-seq Pkts are stored in datPktQ then process the
1797          * bitMap the following way */
1798         fms = (U16)(pjRbCb->ulCb.fmsCount & (0x0fff));   /*KW_FIX*/
1799         /* Setting the bitIdx to start from 8 */
1800         bitIdx = PJ_BYTE_SIZE;
1801         /* Initialize idx as 1 since Bitmap starts from FMS + 1 */
1802         idx = 1;
1803         cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
1804         while(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ))
1805         {
1806                 nxtSnNotFnd = TRUE;
1807                 tmpEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ));
1808                 /* Retrieve the SN from Count of RxEnt */
1809                 sn = (U16)((tmpEnt->count) & (0x0fff)); /*KW_FIX*/
1810                 if(tmpEnt->isOutSeq == FALSE)
1811                 {
1812                         /* This Packet is In-Seq so no need to compute this for Bitmap
1813                          * As this Packet should have SN less than FMS. */
1814                         cmLListNext(&pjRbCb->ulCb.recBuf.datPktQ);
1815                         continue;
1816                 }
1817                 while((nxtSnNotFnd == TRUE) && (byteIdx < 512))
1818                 {
1819                         /* BitMap start from FMS + 1 */
1820                         count = fms + idx;
1821                         if(count >= (1 << pjRbCb->snLen))
1822                         {
1823                                 count = count % (1 << pjRbCb->snLen);
1824                         }
1825                         if(count != sn)
1826                         {
1827                                 /* This SN is missing so set bitMap value to 0 */
1828                                 packByte[byteIdx] |= (0 << (--bitIdx));
1829                                 numBits++;
1830                                 idx++;
1831                         }
1832                         else
1833                         {
1834                                 /* This SN is present so set bitMap value to 1 */
1835                                 packByte[byteIdx] |= (1 << (--bitIdx));
1836                                 numBits++;
1837                                 idx++;
1838                                 nxtSnNotFnd = FALSE;
1839                                 cmLListNext(&pjRbCb->ulCb.recBuf.datPktQ);               
1840                         }
1841                         if(numBits % PJ_BYTE_SIZE == 0)
1842                         {
1843                                 byteIdx++;
1844                                 bitIdx = PJ_BYTE_SIZE;
1845                         }
1846                 }
1847                 if(byteIdx >= 512)
1848                         break;
1849         }
1850         /* if bitmap is not byte aligned, then append/pad 
1851          * with 0s (to indicate from here Packets not received)
1852          * to make it byte aligned and send to App */
1853         while(numBits % 8 != 0)
1854         {
1855                 packByte[byteIdx] |= (0 << (--bitIdx));
1856                 numBits++;
1857         }
1858
1859         /* Store the numOfBits and bitMap in ueCb */
1860         if(pjRbCb->state == PJ_STATE_REEST_HO)
1861         {
1862                 hoInfo = &pjRbCb->ueCb->hoInfo->hoCfmInfo[pjRbCb->rbId];
1863                 hoInfo->pres = TRUE;
1864                 hoInfo->rbId = pjRbCb->rbId;
1865                 hoInfo->dir |= PJ_DIR_UL;
1866                 /* numBits sent from PDCP is always a multiple of 8 */
1867                 hoInfo->numBits = numBits;
1868                 if (numBits > 0) 
1869                 {
1870                         RLOG_ARG1(L_DEBUG,DBG_UEID,pjRbCb->ueCb->key.ueId, 
1871                                         "pjUlmReEstDrbAm : OutOfSeq UL Pkts are present for rbId = %d ",
1872                                         pjRbCb->rbId);
1873                         /* ByteAlign the computed Bits, numBits is always a multiple of 8 */ 
1874 #ifndef XEON_SPECIFIC_CHANGES
1875       SGetStaticBuffer(gCb->init.region, gCb->init.pool, (Data **)&hoInfo->ulBitMap, sizeof(U8) * (numBits / 8), 0);
1876 #else
1877                         PJ_ALLOC(gCb, hoInfo->ulBitMap, sizeof(U8) * (numBits / 8));
1878 #endif
1879 #if (ERRCLASS & ERRCLS_DEBUG)
1880                         if(hoInfo->ulBitMap == NULLP)
1881                         {
1882                                 RLOG0(L_FATAL, "Memory Allocation failed.");
1883                                 RETVALUE(RFAILED);
1884                         }
1885 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
1886                         PJ_MEM_CPY(hoInfo->ulBitMap, packByte, (numBits / 8));
1887                 }
1888                 hoInfo->count = pjRbCb->ulCb.fmsCount;
1889         }
1890         else
1891         {
1892                 /* Send the status report only in case of Re-Establishment 
1893                  * not during Handover as this part is hit when eNB is Source */
1894                 RLOG_ARG0(L_DEBUG,DBG_UEID,pjRbCb->ueCb->key.ueId, 
1895                                 "pjUlmReEstDrbAm : Sending PDCP Status Report ");
1896                 pjUlmBldStaRep(gCb, pjRbCb, pjRbCb->ulCb.fmsCount, packByte, numBits);
1897         }
1898         /*No error check required here*/
1899
1900         RETVALUE(ROK);
1901 }  /* pjUlmReEstDrbAm */
1902
1903 \f
1904 /**
1905  *
1906  * @brief 
1907  *
1908  *        Function is called to build and send the SDU Status report.
1909  *
1910  * @b Description: 
1911  *
1912  *        This function is called to build the SDU status report and send it to the 
1913  *        lower layer after reestablishment.
1914  *                                               
1915  *  @param[in] pjRbCb   PDCP control block 
1916  *  @param[in] fms      First Missing sequence number
1917  *  @param[in] staReq   Buffer containing status report bitmap
1918  *  @return  S16
1919  *      -# ROK 
1920  *      -# RFAILED
1921  */
1922 #ifdef ANSI
1923 PUBLIC S16 pjUlmBldStaRep
1924 (
1925 PjCb       *gCb,
1926 PjUlRbCb   *pjRbCb,         
1927 PjSn       fmc,            
1928 U8         *bitMap,
1929 U16        bMapLen
1930 )
1931 #else
1932 PUBLIC S16 pjUlmBldStaRep(gCb, pjRbCb, fmc, bitMap, bMapLen)
1933 PjCb       *gCb;
1934 PjUlRbCb   *pjRbCb;      
1935 PjSn       fmc;         
1936 U8         *bitMap;
1937 U16        bMapLen;
1938 #endif
1939 {
1940    Buffer          *staRep = NULLP;
1941    U8              packByte = 0;         /* Temp Var for packing bytes */
1942    S16             ret      =  ROK;  /* Return value */
1943    U16             byteLen = 0;
1944
1945    TRC2(pjUlmBldStaRep);
1946
1947    RLOG2(L_DEBUG, "pjUlmBldStaRep(pjRbCb(%d,%d))",pjRbCb->rbId, pjRbCb->rbType);
1948
1949    PJ_ALLOC_BUF(gCb, staRep);
1950 #if (ERRCLASS & ERRCLS_DEBUG)
1951    if(staRep == NULLP)
1952    {
1953       RLOG0(L_FATAL, "Memory Allocation failed.");
1954       RETVALUE(RFAILED);
1955    }
1956 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
1957    SAddPstMsg(packByte, staRep);
1958    packByte = (U8)((fmc & 0xff000000) >> 24);
1959
1960    SAddPstMsg(packByte, staRep);
1961
1962    packByte = (U8)((fmc & 0x00ff0000) >> 16);
1963    SAddPstMsg(packByte, staRep);
1964
1965    packByte = (U8)((fmc & 0x0000ff00) >> 8);
1966    SAddPstMsg(packByte, staRep);
1967
1968    packByte = (U8)((fmc & 0x000000ff));
1969    SAddPstMsg(packByte, staRep);
1970
1971    /* Pack the bitmap */
1972    if(bMapLen != 0)
1973    {
1974       /* bMapLen will always be a multiple of 8 */
1975       byteLen = (U16)(bMapLen / 8);  /*KW_FIX*/
1976       SAddPstMsgMult(bitMap, byteLen, staRep);
1977    }
1978
1979    /*send the status report to DLPDCP */
1980
1981    pjUtlUlSndUlStaRep(gCb, pjRbCb, staRep);
1982
1983    RETVALUE(ret);
1984
1985 }/*pjUlmBldStaRep*/
1986
1987 \f
1988 /**
1989  *
1990  * @brief 
1991  *
1992  *        Function is called during handover to transfer the undeliverd SDUs
1993  *        at the target side.
1994  *
1995  * @b Description: 
1996  *
1997  *        This function performs the following.                           @n
1998  *        1. Calculate lastSubCnt.                                        @n
1999  *        2. Compute count for each SDU.                                  @n
2000  *        3. Create an rxEnt for each SDU and insert it into the hashlist.@n
2001  *                                               
2002  *  @param[in] pjRbCb      PDCP control block 
2003  *  @param[in] datFwdReq   Data Forward Request info
2004  *  @return  S16
2005  *      -# ROK 
2006  *      -# RFAILED
2007  */
2008 #ifdef ANSI
2009 PUBLIC S16 pjUlmHdlDatFwdReq  
2010 (
2011 PjCb           *gCb,
2012 PjUlRbCb         *pjRbCb,                       /* !< PDCP ID */        
2013 PjuDatFwdReqInfo   *datFwdReq                 /* !< DatFwdReq Info */
2014 )
2015 #else
2016 PUBLIC S16 pjUlmHdlDatFwdReq(gCb, pjRbCb, datFwdReq)
2017 PjCb           *gCb;
2018 PjUlRbCb         *pjRbCb;                       /* !< PDCP ID */        
2019 PjuDatFwdReqInfo   *datFwdReq;                /* !< DatFwdReq Info */ 
2020 #endif
2021 {
2022    U32            datFwdCnt;         /* Temp value to store SDU count    */
2023    PjRxEnt       *rxEnt     = NULLP; /* Rx Entry pointer                 */
2024    PjuDatFwdInfo *info;              /* Loop var - pointer to DatFwdInfo */
2025    PjUlCb        *ulCb      = NULLP; /* UL Control block                 */
2026    U8             sduIndex;          /* loop index                       */
2027    U32            rcvdHfn;
2028
2029    TRC2(pjUlmHdlDatFwdReq);
2030
2031    RLOG2(L_DEBUG, "pjUlmHdlDatFwdReq(pjRbCb(%d,%d), datFwdReq) ",
2032          pjRbCb->rbId, pjRbCb->rbType);
2033
2034    /* Initialisations */
2035    ulCb  =  &pjRbCb->ulCb;
2036
2037    /* Loop through all SDUs */
2038    for( sduIndex = 0; sduIndex < datFwdReq->numSdus; sduIndex++)
2039    {
2040       info  =  &datFwdReq->datFwdInfo[sduIndex];
2041       PJ_STS_INC_GEN_CNT(gCb,numPktsRcvd);
2042
2043       /*1.5G-NR Determine the Hfn and count value of the received PDCP data pdu*/
2044       PJ_CALC_RCVD_HFN((info->sn),pjRbCb->snLen,ulCb->rxDeliv,rcvdHfn);
2045       /*2.5G-NR Get the count value of the receiced PDCP data pdu from rcvdSn and rcvdHfn  */
2046       PJ_GET_COUNT(datFwdCnt, pjRbCb->snLen, (info->sn), rcvdHfn);
2047
2048 #ifdef PJ_SEC_ASYNC
2049       PJ_ULM_UPD_NXT2DCOMP(pjRbCb->ulCb, (pjRbCb->snLen), rcvdCount, oldRxCnt);
2050 #endif
2051
2052       /* PJ_ULM_UPD_RX_VAR(info->sn, pjRbCb); */
2053
2054       /* Create and insert the entry in the buffer */
2055       PJ_ALLOC(gCb,rxEnt, sizeof(PjRxEnt));
2056
2057 #if (ERRCLASS & ERRCLS_DEBUG)
2058       if(rxEnt == NULLP)
2059       {
2060          RLOG0(L_FATAL, "Memory Allocation failed.");
2061          RETVALUE(RFAILED);
2062       }
2063 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
2064
2065       rxEnt->count     = datFwdCnt;
2066       rxEnt->state     = PJ_RDY_TO_SUBMIT;
2067       rxEnt->mBuf      = info->sdu;
2068
2069       if(pjRbCb->state == PJ_STATE_HO) 
2070       {
2071          /* If RbCb State = PJ_STATE_HO, then this is Target and Forwarded Packets
2072           * are received before Status Transfer so buffer this Packet */
2073          rxEnt->isOutSeq = TRUE;
2074       }
2075       /* Insert the entry in the buffer */
2076       pjDbmInsRxEnt(gCb, &ulCb->recBuf, rxEnt, FALSE); 
2077    }
2078
2079    RETVALUE(ROK);
2080 }/*pjUlmHdlDatFwdReq*/
2081 \f
2082 /**
2083  *
2084  * @brief 
2085  *
2086  *        Function is called when 
2087  *        1. The offboard timer expires.
2088  *        2. Deciphering returns. 
2089  *
2090  * @b Description: 
2091  *
2092  *    The function is called when the pdu is next in line for decompression
2093  *    It performs the following.                                           @n
2094  *    1. Submit the pdu for decompression.                                 @n
2095  *    2. Check if any successive messages can be sent to for decompression @n
2096  *    3. Update the nxtSubDeCmp value appropriately .                      @n
2097  *                                               
2098  *  @param[in] pjRbCb   PDCP control block 
2099  *  @param[in] rxEnt    Reception Entry
2100  *
2101  *  @return  S16
2102  *      -# ROK 
2103  *      -# RFAILED
2104  */
2105 #ifdef ANSI
2106 PUBLIC S16 pjUlmSubmitForDecmp
2107 (
2108 PjCb       *gCb,
2109 PjUlRbCb     *pjRbCb,        /* !< PDCP Control Block */  
2110 PjRxEnt    *rxEnt          /* Ptr To Rx Entry */
2111 )
2112 #else
2113 PUBLIC S16 pjUlmSubmitForDecmp(gCb, pjRbCb, rxEnt)
2114 PjCb       *gCb;
2115 PjUlRbCb     *pjRbCb;        /* !< PDCP Control Block */  
2116 PjRxEnt    *rxEnt;         /* Ptr To Rx Entry */
2117 #endif
2118 {
2119    PjUlCb  *ulCb;          /* ULM Control Block */
2120 #ifdef PJ_SEC_ASYNC
2121    U32     count;          /* count to go through the list and check */
2122    U32     nxtRxCnt;       /* count of Sdu to receive next */
2123    PjRxEnt *tmpEnt;        /* Temporary variable for looping */
2124 #endif /* PJ_SEC_ASYNC */
2125    U32     macI=0;
2126
2127    TRC2(pjUlmSubmitForDecmp);
2128
2129 #ifndef ALIGN_64BIT
2130    RLOG3(L_DEBUG, "pjUlmSubmitForDecmp(pjRbCb(%d,%d),rxEnt(%ld)) ",
2131          pjRbCb->rbId, pjRbCb->rbType, rxEnt->count);
2132 #else
2133    RLOG3(L_DEBUG, "pjUlmSubmitForDecmp(pjRbCb(%d,%d),rxEnt(%d)) ",
2134          pjRbCb->rbId, pjRbCb->rbType, rxEnt->count);
2135 #endif
2136
2137    /* 1. Initialisations */
2138    ulCb  =  &pjRbCb->ulCb;
2139    rxEnt->state = PJ_RDY_TO_DCOMP;
2140    /*Adding MACI for 5G NR for DRB in case of intergrity protection is enabled*/
2141    if(pjRbCb->ueCb->secInfo.intProtEnbForDrb)
2142    {
2143       PJ_UNPK_MACI(rxEnt->mBuf, macI);
2144    }
2145
2146    /* 2. If decomp is disabled, start delivery procedures */
2147    if(pjRbCb->rohc.hdrCmpUsed != TRUE)
2148    {
2149       rxEnt->state   =  PJ_RDY_TO_SUBMIT;
2150       PJ_DEC_OBD_COUNT(gCb, pjRbCb, rxEnt->count);
2151       PJ_ULM_DELIVER_DRB(gCb,pjRbCb, rxEnt);
2152       RETVALUE(ROK);
2153    }
2154
2155    /* 3. If not the next in line for decompression, wait.. */
2156    if(ulCb->nxtSubDeCmp != rxEnt->count)
2157    {
2158       RETVALUE(ROK);
2159    }
2160
2161    /* 4. Calling decompression hook */
2162    if(pjUlmHdlDeCmp(gCb, pjRbCb, rxEnt) != ROK)
2163    {
2164       RETVALUE(RFAILED);
2165    }
2166
2167 #ifdef PJ_SEC_ASYNC
2168    /* 5. cycle through the subsequent entries to see if any of them are also 
2169     * available for decompression */
2170     nxtRxCnt = ulCb->rxNext;
2171
2172    for(count =  ulCb->nxtSubDeCmp + 1; count < nxtRxCnt; count ++)
2173    {
2174       /* 5.1 Get the next node */
2175       tmpEnt   =  pjDbmGetRxEnt(gCb, &ulCb->recBuf, count);
2176
2177       /* 5.2 If such an entry does not exist, search for the next */
2178       if(tmpEnt == NULLP)
2179       {
2180          continue;
2181       }
2182
2183       /* 5.3 During post reestablishment phase, there might me some PDUs in 
2184        * the Rx Buffer that were received prior to reestablishment and 
2185        * have been fully processed but are not sent up because they are 
2186        * waiting for the arrival of a previous PDU. We can  safely skip 
2187        * such an entry */
2188       if(tmpEnt->state == PJ_RDY_TO_SUBMIT)
2189       {
2190          continue;
2191       }
2192
2193       /* 5.4 Deciphering not yet done so we have to wait */
2194       if(tmpEnt->state != PJ_RDY_TO_DCOMP)
2195       {
2196          break;
2197       }
2198       
2199       /*Adding MACI for 5G NR for DRB in case of intergrity protection is enabled*/
2200       if(pjRbCb->ueCb->secInfo.intProtEnbForDrb)
2201       {
2202          PJ_UNPK_MACI(rxEnt->mBuf, macI);
2203       }
2204       /* 5.5 Send it to decompression */
2205       if(pjUlmHdlDeCmp(gCb, pjRbCb, tmpEnt) != ROK)
2206       {
2207          RETVALUE(RFAILED);
2208       }
2209
2210    } /* while(!((sn == ulCb->nxtRxSn)... */
2211
2212    /* 6. Update nxtSubDeCmp */
2213    ulCb->nxtSubDeCmp = count;
2214
2215 #endif /* PJ_SEC_ASYNC */
2216
2217    RETVALUE(ROK);
2218
2219 }/* end of pjUlmSubmitForDecmp */
2220 /**
2221  *
2222  * @brief 
2223  *
2224  *        Function is called when the offboard timer expires.
2225  *
2226  * @b Description: 
2227  *
2228  *    The function performs the following
2229  *    1. If the SDU associated with the timer is not delivered, we 
2230  *       delete the entry .                                              @n
2231  *    2. A status indication is sent to the user with error cause.       @n
2232  *    3. In case of failure call pjUlmHdlErrUpdates to recalculate
2233  *       nxtSubCnt and if necessary nxtSubDeCmp.                         @n
2234  *    4. The timer is associated with the nextToSubmit SDU and restarted.@n
2235  *                                               
2236  *  @param[in] pjRbCb   PDCP control block 
2237  *
2238  *  @return  S16
2239  *      -# ROK 
2240  *      -# RFAILED
2241  */
2242 #ifdef ANSI
2243 PUBLIC Void pjUlmHdlReordTmrExpiry 
2244 (
2245 PjCb       *gCb,
2246 PjUlRbCb     *pjRbCb         /* !< PDCP Control Block */  
2247 )
2248 #else
2249 PUBLIC Void pjUlmHdlReordTmrExpiry(gCb,pjRbCb)
2250 PjCb       *gCb;
2251 PjUlRbCb     *pjRbCb;        /* !< PDCP Control Block */  
2252 #endif
2253 {
2254    PjRxEnt *tmpEnt = NULLP;
2255    PjUlCb   *ulCb;
2256    U32 tmpNxtDelvrCnt;
2257    U32 rxReOrdHfn, tmpNxtDlvrHfn;
2258
2259    ulCb        = &pjRbCb->ulCb;
2260
2261    gPdcpStats.numPdcpCellReorderTmrExp++;
2262  
2263    cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
2264    if(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ))
2265    {
2266       tmpEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ));
2267
2268       /* all stored PDCP SDU(s) with associated COUNT value(s) < RX_REORD; */
2269       while(tmpEnt && (tmpEnt->count < ulCb->rxReord))
2270       {
2271          PJ_SND_PJU_DAT_IND(gCb,pjRbCb, tmpEnt);
2272          pjDbmDelRxEnt(gCb, &ulCb->recBuf, tmpEnt->count);
2273          cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
2274          if(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ) == NULLP)
2275          {
2276             break;
2277          }
2278          tmpEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ));
2279       }
2280    }
2281    
2282    tmpNxtDelvrCnt = ulCb->rxReord;
2283    cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
2284    if(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ))
2285    {
2286       tmpEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ));
2287       /* all stored PDCP SDU(s) with consecutively associated COUNT value(s) starting from RX_REORD */
2288       while(tmpEnt && ( tmpEnt->count == tmpNxtDelvrCnt )) 
2289       {
2290          PJ_SND_PJU_DAT_IND(gCb,pjRbCb, tmpEnt);
2291          tmpNxtDelvrCnt++;
2292          pjDbmDelRxEnt(gCb, &ulCb->recBuf, tmpEnt->count);
2293          cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
2294          if(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ) == NULLP)
2295          {
2296             break;
2297          }
2298          tmpEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ));
2299       }
2300    }
2301    
2302    /* update RX_DELIV to the COUNT value of the first PDCP SDU 
2303       which has not been delivered to upper layers, 
2304       with COUNT value >= RX_REORD;*/
2305       PJ_GET_HFN(ulCb->rxDeliv,pjRbCb->snLen,rxReOrdHfn);
2306       PJ_GET_HFN(tmpNxtDelvrCnt,pjRbCb->snLen,tmpNxtDlvrHfn);
2307    if ((tmpNxtDelvrCnt > ulCb->rxReord) || 
2308        ((PJ_MAX_HFN(pjRbCb->snLen) == rxReOrdHfn ) && (0 == tmpNxtDlvrHfn)))
2309    {
2310       ulCb->rxDeliv      =   tmpNxtDelvrCnt;
2311    }
2312    
2313    if (ulCb->rxDeliv < ulCb->rxNext)
2314    {
2315       ulCb->rxReord = ulCb->rxNext;
2316       pjStartTmr(gCb,(PTR)pjRbCb, PJ_EVT_UL_REORD_TMR);
2317    }
2318 }
2319
2320 \f
2321 #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
2322 /**
2323  *
2324  * @brief 
2325  *
2326  *        Function is called when the offboard timer expires.
2327  *
2328  * @b Description: 
2329  *
2330  *    The function performs the following
2331  *    1. If the SDU associated with the timer is not delivered, we 
2332  *       delete the entry .                                              @n
2333  *    2. A status indication is sent to the user with error cause.       @n
2334  *    3. In case of failure call pjUlmHdlErrUpdates to recalculate
2335  *       nxtSubCnt and if necessary nxtSubDeCmp.                         @n
2336  *    4. The timer is associated with the nextToSubmit SDU and restarted.@n
2337  *                                               
2338  *  @param[in] pjRbCb   PDCP control block 
2339  *
2340  *  @return  S16
2341  *      -# ROK 
2342  *      -# RFAILED
2343  */
2344 #ifdef ANSI
2345 PUBLIC Void pjUlmHdlObdTmrExpiry
2346 (
2347 PjCb       *gCb,
2348 PjUlRbCb     *pjRbCb         /* !< PDCP Control Block */  
2349 )
2350 #else
2351 PUBLIC Void pjUlmHdlObdTmrExpiry(gCb,pjRbCb)
2352 PjCb       *gCb;
2353 PjUlRbCb     *pjRbCb;        /* !< PDCP Control Block */  
2354 #endif
2355 {
2356    PjUlCb  *ulCb;          /* ULM Control Block */
2357    PjRxEnt *rxEnt;         /* Ptr To Rx Entry */
2358    U32      subCnt;        /* Count that was/will be submitted */
2359
2360    TRC2(pjUlmHdlObdTmrExpiry);
2361
2362    RLOG2(L_DEBUG, "pjUlmHdlObdTmrExpiry(pjRbCb(%d,%d)) ",
2363          pjRbCb->rbId, pjRbCb->rbType);
2364
2365    /* 1. Initialistions */
2366    ulCb  =  &pjRbCb->ulCb;
2367    PJ_STS_INC_GEN_CNT(gCb,numPdusDiscObdTmrExp);
2368
2369
2370    /* 2. For SDUs that have not yet been delivered */
2371    PJ_ULM_GET_SUBCNT(pjRbCb, subCnt, gCb);
2372    if(ulCb->obdPdu == subCnt)
2373    {
2374       /* 2.1 Send failure indication  and delete the entry */
2375       rxEnt =  (PjRxEnt *)pjDbmGetRxEnt(gCb, &(ulCb->recBuf), ulCb->obdPdu);
2376       if(rxEnt == NULLP)
2377       {
2378          if( ulCb->recBuf.numEntries == 0)
2379          {
2380             RETVOID;
2381          }
2382 #if (ERRCLASS & ERRCLS_DEBUG)
2383          RLOG1(L_ERROR, "rxEnt not found for subCnt [%lu]", subCnt);
2384 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
2385          RETVOID;
2386       }
2387       else
2388       {
2389          RLOG1(L_ERROR, "Obd Timer expires without reply for subCnt [%lu]", subCnt);
2390          PJ_SND_PJU_STA_IND(gCb,pjRbCb, rxEnt);
2391          pjDbmDelRxEnt(gCb, &ulCb->recBuf, rxEnt->count);
2392       }
2393
2394       /* 2.2 Update nxtSubCnt */
2395       pjUlmHdlErrUpdates(gCb, pjRbCb, ulCb->obdPdu);
2396
2397       /* 2.3 Restart timer if it has not been restarted already */
2398       if( ulCb->recBuf.numEntries != 0)
2399       {
2400          if((pjChkTmr(gCb, (PTR)pjRbCb, PJ_EVT_UL_OBD_TMR)) == FALSE)
2401          {
2402             PJ_ULM_GET_SUBCNT(pjRbCb, (ulCb->obdPdu), gCb);
2403             if(!PJ_DRBAM_ALL_PDU_RECVD(pjRbCb))
2404             {
2405                pjStartTmr(gCb, (PTR)pjRbCb, PJ_EVT_UL_OBD_TMR);
2406             }
2407          }
2408       }
2409    }
2410    /* 3. For SDUs that have been delivered */
2411    else
2412    {
2413       if( ulCb->recBuf.numEntries != 0)
2414       {
2415          /* 3.1 Associate the nxtToSub with the timer */
2416          PJ_ULM_GET_SUBCNT(pjRbCb, (ulCb->obdPdu), gCb);
2417          if(!PJ_DRBAM_ALL_PDU_RECVD(pjRbCb))
2418          {
2419             pjStartTmr(gCb, (PTR)pjRbCb, PJ_EVT_UL_OBD_TMR);
2420          }
2421       }
2422    }
2423
2424    RETVOID;
2425 }/* end of pjUlmHdlObdTmrExpiry */
2426 #endif /* (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC)) */
2427
2428
2429 /**
2430  *
2431  * @brief 
2432  *
2433  *        Function is called when 
2434  *        1. The offboard timer expires 
2435  *        2. The library functions fail.
2436  *
2437  * @b Description: 
2438  *
2439  *    The function performs the following
2440  *    1. Update nxtSubCnt if necessary.
2441  *    2. Update nxtSubDeCmp if necessary.
2442  *    3. Check if reestablishment has to be triggered.
2443  *                                               
2444  *  @param[in] pjRbCb   PDCP control block.
2445  *  @param[in] errCnt   Count of the error PDU.
2446  *
2447  *  @return  Void
2448  */
2449 #ifdef ANSI
2450 PUBLIC Void pjUlmHdlErrUpdates
2451 (
2452 PjCb       *gCb,
2453 PjUlRbCb     *pjRbCb,        /* !< PDCP Control Block */  
2454 U32         errCnt         /* !< Count of PDU that raises the error */
2455 )
2456 #else
2457 PUBLIC Void pjUlmHdlErrUpdates(gCb, pjRbCb, errCnt)
2458 PjCb       *gCb;
2459 PjUlRbCb     *pjRbCb;        /* !< PDCP Control Block */  
2460 U32         errCnt;        /* !< Count of PDU that raises the error */
2461 #endif
2462 {
2463 #ifdef PJ_SEC_ASYNC
2464    U32      nxtToDeCmp;
2465 #endif /* PJ_SEC_ASYNC */
2466
2467 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
2468    PjUlCb  *ulCb;          /* ULM Control Block */
2469    U32      nxtRxCnt;
2470    U32      nxtToSub;
2471    PjRxEnt *rxEnt = NULLP;   /* Ptr To Rx Entry */
2472 #endif /* (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC)) */
2473
2474    TRC2(pjUlmHdlErrUpdates);
2475
2476 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
2477    /* 1. Initialistions */
2478    ulCb       =  &pjRbCb->ulCb;
2479    nxtRxCnt  =  ulCb->rxNext;
2480
2481    /* 2. Decrement obd counter */
2482    PJ_DEC_OBD_COUNT(gCb, pjRbCb, errCnt);
2483
2484    /* 3. For DRB AM , check if we can deliver anything  */
2485    if((pjRbCb->rbType == PJ_DRB) &&  (pjRbCb->mode == PJ_DRB_AM))
2486    {
2487       /* if any successive entries can be sent up , send it */
2488       for(nxtToSub  =  ulCb->rxDeliv; nxtToSub < nxtRxCnt; nxtToSub++)
2489       {
2490          if( (rxEnt = pjDbmGetRxEnt(gCb, &ulCb->recBuf, nxtToSub)) != NULLP)
2491          {
2492             /* As soon as we get an entry, we break */
2493             if(rxEnt->state == PJ_RDY_TO_SUBMIT)
2494             {
2495                pjUlmDeliverDrbAm(gCb, pjRbCb, rxEnt);
2496             }
2497             break;
2498          }
2499
2500       }
2501       if(nxtToSub == nxtRxCnt)
2502       {
2503          /* This situation occurs, if this is the only pdu in the hashlist 
2504           * and obd fails for it. In this case, we have to trigger reestablishment
2505           * procedures */
2506          if(pjRbCb->state != PJ_STATE_NORMAL)
2507          {
2508             if((ulCb->transCmp == TRUE) && 
2509                   (ulCb->obdCnt == 0))
2510             {
2511                PJ_ULM_DRBUM_REEST(gCb, pjRbCb);
2512             }
2513          }
2514       }
2515    }
2516    /* 4. For SRB/DRB UM Update nxtSubCnt */
2517    else
2518    {
2519       if(errCnt ==  ulCb->nxtSubCnt)
2520       {
2521          for(nxtToSub  =  ulCb->nxtSubCnt + 1; nxtToSub < nxtRxCnt; nxtToSub++)
2522          {
2523             if( (rxEnt = pjDbmGetRxEnt(gCb, &ulCb->recBuf, nxtToSub)) != NULLP)
2524             {
2525                ulCb->nxtSubCnt = nxtToSub;
2526                break;
2527             }
2528          }
2529          if(nxtToSub == ulCb->nxtSubCnt )
2530          {
2531             if(rxEnt->state == PJ_RDY_TO_SUBMIT)
2532             {
2533                PJ_ULM_DELIVER_PDU(gCb, pjRbCb, rxEnt);
2534             }
2535          }
2536          else
2537          {
2538             /* Update nxtSubCnt to point to nxtRxCnt so that 
2539              * updations at pjUlmProcessRb can happen properly */
2540             ulCb->nxtSubCnt   =  nxtRxCnt;
2541
2542             /* Check if its necessary to reestablish */
2543             if(pjRbCb->state != PJ_STATE_NORMAL)
2544             {
2545                if((ulCb->transCmp == TRUE) && 
2546                      (ulCb->obdCnt == 0))
2547                {
2548                   PJ_ULM_DRBUM_REEST(gCb, pjRbCb);
2549                }
2550             }
2551          }
2552       }
2553    }
2554
2555 #endif /* (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC)) */
2556
2557    /* Notes : Update nxSubCnt first and then nxtSubDeCmp because we dont want a case
2558     * where nxtSubDeCmp becomes greater that nxtSubCnt */
2559 #ifdef PJ_SEC_ASYNC
2560    /* 5. Update nxtSubDeCmp */
2561    if((pjRbCb->rbType == PJ_DRB) && (errCnt == ulCb->nxtSubDeCmp))
2562    {
2563       nxtToDeCmp  =  ulCb->nxtSubDeCmp + 1;
2564
2565       for(; nxtToDeCmp < nxtRxCnt; nxtToDeCmp++)
2566       {
2567          rxEnt = pjDbmGetRxEnt(gCb, &ulCb->recBuf, nxtToDeCmp);
2568
2569          if(rxEnt == NULLP)
2570          {
2571             continue;
2572          }
2573
2574          /* A pdu existing after reestablishment */
2575          if(rxEnt->state == PJ_RDY_TO_SUBMIT)
2576          {
2577             continue;
2578          }
2579
2580          ulCb->nxtSubDeCmp = nxtToDeCmp;
2581          break;
2582       }
2583
2584       if(nxtToDeCmp == ulCb->nxtSubDeCmp)
2585       {
2586          if(rxEnt && (rxEnt->state == PJ_RDY_TO_DCOMP))
2587          {
2588             pjUlmSubmitForDecmp(gCb, pjRbCb, rxEnt);
2589          }
2590       }
2591       else
2592       {
2593          /* Update nxtSubDeCmp to point to nxtRxCnt so that 
2594           * updations at pjUlmProcessRb can happen properly */
2595          ulCb->nxtSubDeCmp =  nxtRxCnt;
2596
2597       }
2598    }
2599 #endif /* PJ_SEC_ASYNC */
2600
2601    RETVOID;
2602 }/* end of pjUlmHdlErrUpdates */
2603
2604 /**
2605  *
2606  * @brief 
2607  *
2608  *        Function is called when 
2609  *        1.  PjLiKwuReEstCmpInd received from RLC in case of Re-establishment and HO
2610  *
2611  * @b Description: 
2612  *
2613  *    The function performs the following
2614  *    1. Checks the RB state, if it is not equal to PJ_STATE_NORMAL calls
2615  *        PJ_ULM_DRBUM_REEST or pjUlmReEstDrbAm
2616  *                                               
2617  *  @param[in] tPjCb   PDCP control block.
2618  *  @param[in] tRbCb  RB control block.
2619  *
2620  *  @return  Void
2621  */
2622 #ifdef ANSI
2623 PUBLIC Void pjUlmReEstCmpInd
2624 (
2625 PjCb   *gCb,
2626 PjUlRbCb *tRbCb        /* !< RB control block */  
2627 )
2628 #else
2629 PUBLIC Void pjUlmReEstCmpInd(tPjCb, tRbCb)
2630 PjCb       *gCb;
2631 PjUlRbCb     *tRbCb;        /* !< PDCP Control Block */  
2632 #endif
2633 {
2634
2635    TRC3(pjUlmReEstCmpInd)
2636
2637    /* No need to update state for SRB */
2638    if(tRbCb->ueCb->libInfo.state == PJ_STATE_NORMAL)
2639    {
2640       RETVOID;
2641    }
2642
2643    if(tRbCb->rbType == PJ_SRB)
2644    {
2645       RETVOID;
2646    }
2647
2648 #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
2649    /* If Async mode, set variable to true and return */
2650    tRbCb->ulCb.transCmp = TRUE;
2651    if(tRbCb->ulCb.obdCnt == 0)
2652    {
2653 #endif /* (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC)) */
2654       /* In synchronous mode, we can proceed with reestablishment */
2655       if (tRbCb->mode  ==  PJ_DRB_UM)
2656       {
2657          tRbCb->ulCb.rxNext  =  0; 
2658          tRbCb->ulCb.rxDeliv   =  0;
2659 #ifdef LTE_L2_MEAS
2660          tRbCb->ulCb.nxtSubSn =  0; 
2661 #endif
2662       }
2663       else
2664       {
2665          (Void)pjUlmReEstDrbAm(gCb, tRbCb);
2666       }
2667
2668       pjUtlUlHdlRbReEstComplete(gCb,tRbCb);
2669
2670 #if (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC))
2671    }
2672 #endif /* (defined(PJ_SEC_ASYNC) || defined (PJ_CMP_ASYNC)) */
2673
2674    RETVOID;
2675 }
2676
2677
2678 /**
2679  *
2680  * @brief
2681  *
2682  *        Handler to forward the uplink data to the upper layer.
2683  *
2684  * @b Description:
2685  *
2686  *        1. This function is used to forward the uplink data to the upper layer
2687  *        during handover.  @n
2688  *        2. The out-of-sequene data SDUs are sent to the upper
2689  *        layer.    @n
2690  *
2691  *  @param[in] pjRbCb      PDCP control block.
2692  *
2693  *  @return  S16
2694  *      -# ROK
2695  *      -# RFAILED
2696  *
2697  */
2698 #ifdef ANSI
2699 PUBLIC S16 pjUlmStartDataFrwdPerRb
2700 (
2701 PjCb       *gCb,
2702 PjUlRbCb    *pjRbCb 
2703 )
2704 #else
2705 PUBLIC S16 pjUlmStartDataFrwdPerRb(gCb, pjRbCb)
2706 PjCb       *gCb;
2707 PjUlRbCb    *pjRbCb;
2708 #endif
2709 {
2710
2711    U32              numSdu =0;
2712    U16              count;
2713    U32              numSduCnt =0,numSduTx = 0;
2714    PjRxEnt  *tmpRxEnt = NULLP;              /* temporary Rx Entity */
2715    PjuDatFwdIndInfo *datFwdInd = NULLP;
2716    U32      numEntries = 0;
2717    U16      sn = 0;
2718    PjPjuSapCb   *pjuSap;
2719
2720    TRC3(pjUlmStartDataFrwdPerRb)
2721
2722    RLOG1(L_DEBUG, "pjUlmStartDataFrwdPerRb (%d )) ", pjRbCb->rbId);
2723
2724    pjuSap   = &(gCb->u.ulCb->pjuSap[PJ_DRB_SAP]);
2725    if((pjRbCb->ulCb.rxNext == 0))
2726    {
2727       if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,(Data **)&datFwdInd,
2728       sizeof (PjuDatFwdIndInfo)) != ROK)
2729       {
2730           datFwdInd = NULLP;
2731       }
2732 #if (ERRCLASS & ERRCLS_ADD_RES)
2733       if (datFwdInd == NULLP)
2734       {
2735          RLOG0(L_FATAL, "Memory Allocation failed.");
2736          RETVALUE(RFAILED);
2737       }
2738 #endif /* ERRCLASS & ERRCLS_ADD_RES */
2739       datFwdInd->dir = PJ_DIR_UL;
2740       datFwdInd->numSdus = 0;
2741       datFwdInd->isLastDatFwdInd = TRUE;
2742
2743       /* sending DatFwdInd even if numSdu is zero */
2744       pjUtlUlSndDatFwdInd(gCb,pjRbCb, datFwdInd);
2745
2746       RETVALUE(ROK);
2747    }
2748
2749    /* Find the total number of RxEnts present */
2750    numEntries = pjRbCb->ulCb.recBuf.numEntries;
2751    /* Find the total count of the txEnts present */
2752    numSduCnt = numSdu = numEntries;
2753
2754    /* Traverse the datPktQ and send the UL Packets to DAM */
2755    cmLListFirst(&pjRbCb->ulCb.recBuf.datPktQ);
2756
2757 while(numSduCnt >0)
2758 {
2759    count = 0;
2760    if(numSduCnt > PJ_FWD_MAX_SDU_CNT)
2761    {
2762       numSduTx  = PJ_FWD_MAX_SDU_CNT;
2763       numSduCnt = numSduCnt - PJ_FWD_MAX_SDU_CNT;
2764    }
2765    else
2766    {
2767       numSduTx = numSduCnt;
2768       numSduCnt = 0;
2769    }
2770
2771       if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,(Data **)&datFwdInd,
2772       sizeof (PjuDatFwdIndInfo)) != ROK)
2773       {
2774           datFwdInd = NULLP;
2775       }
2776 #if (ERRCLASS & ERRCLS_ADD_RES)
2777       if (datFwdInd == NULLP)
2778       {
2779          RLOG0(L_FATAL, "Memory Allocation failed.");
2780          RETVALUE(RFAILED);
2781       }
2782 #endif /* ERRCLASS & ERRCLS_ADD_RES */
2783
2784       if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,
2785          (Data **)&datFwdInd->datFwdInfo, (sizeof (PjuDatFwdInfo)* numSduTx)) != ROK)
2786       {
2787           datFwdInd->datFwdInfo = NULLP;
2788       }
2789 #if (ERRCLASS & ERRCLS_ADD_RES)
2790       if (datFwdInd->datFwdInfo == NULLP)
2791       {
2792          RLOG0(L_FATAL, "Memory Allocation failed.");
2793          RETVALUE(RFAILED);
2794       }
2795 #endif /* ERRCLASS & ERRCLS_ADD_RES */
2796
2797    while (numSduTx>0)
2798    {
2799       /* Retrieve the Packet Info by typecasting to RxEnt */
2800       tmpRxEnt = (PjRxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->ulCb.recBuf.datPktQ)); 
2801       sn = (U16)((tmpRxEnt->count) & (0x0fff)); /*KW_FIX*/
2802
2803       datFwdInd->datFwdInfo[count].sn = sn;
2804       /* Copy the SDU Buffer as it is into datFwdInfo */
2805 #ifdef SS_RBUF
2806      datFwdInd->datFwdInfo[count].sdu = tmpRxEnt->mBuf;
2807 #else
2808       SCpyMsgMsg(tmpRxEnt->mBuf, 0, 0,
2809             &datFwdInd->datFwdInfo[count].sdu);
2810 #endif
2811       cmLListNext(&pjRbCb->ulCb.recBuf.datPktQ);
2812       numSduTx--;
2813       count++;
2814    }
2815       /* Fill the datFwdInd struct and send it to DAM */
2816       datFwdInd->dir = PJ_DIR_UL;
2817       datFwdInd->numSdus = count;
2818       datFwdInd->isLastDatFwdInd = FALSE;
2819       /* Send the datFwdInd to DAM */
2820       pjUtlUlSndDatFwdInd(gCb,pjRbCb, datFwdInd);
2821
2822 }
2823
2824    if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,(Data **)&datFwdInd,
2825       sizeof (PjuDatFwdIndInfo)) != ROK)
2826    {
2827        datFwdInd = NULLP;
2828    }
2829 #if (ERRCLASS & ERRCLS_ADD_RES)
2830    if (datFwdInd == NULLP)
2831    {
2832       RLOG0(L_FATAL, "Memory Allocation failed.");
2833       RETVALUE(RFAILED);
2834    }
2835 #endif /* ERRCLASS & ERRCLS_ADD_RES */
2836    datFwdInd->dir = PJ_DIR_UL;
2837    datFwdInd->numSdus = 0;
2838    datFwdInd->isLastDatFwdInd = TRUE;
2839
2840    /* sending DatFwdInd even if numSdu is zero */
2841    pjUtlUlSndDatFwdInd(gCb,pjRbCb, datFwdInd);
2842
2843    RETVALUE(ROK);
2844 }
2845
2846
2847 /**
2848  *
2849  * @brief 
2850  *
2851  *        Handler to process the forwarded data received from upper layer.
2852  *
2853  * @b Description: 
2854  *
2855  *        1. This function is used to process the SDUs received from the upper
2856  *        layer as part of handover.   @n
2857  *        2. This function calls pjDlmProcessSdus function with the correct 
2858  *        SN and HFN values.     @n
2859  *            
2860  *  @param[in] gCb         PDCP Instance control block. 
2861  *  @param[in] pjUlRbCb    Uplink Rb control block. 
2862  *  @param[in] datFwdReq   Data Forward Info.
2863  *
2864  *  @return  S16
2865  *      -# ROK 
2866  *      -# RFAILED
2867  *
2868  */
2869 #ifdef ANSI
2870 PUBLIC S16 pjUlmHndlDatFwdReq
2871 (
2872 PjCb               *gCb,
2873 PjUlRbCb           *pjRbCb,
2874 PjuDatFwdReqInfo   *datFwdReq
2875 )
2876 #else
2877 PUBLIC S16 pjUlmHndlDatFwdReq(gCb,pjRbCb,datFwdReq)
2878 PjCb               *gCb;
2879 PjUlRbCb           *pjRbCb;
2880 PjuDatFwdReqInfo   *datFwdReq;
2881 #endif
2882 {
2883
2884    PjRxEnt  *rxEnt;              /* Transmission Entity */ 
2885    PjSn     sn;
2886    int      ret;
2887    U32      numSdus=0;
2888    U32      macI=0;
2889    U32     rcvdHfn;             /*Hfn for received PDU */
2890    U32     rcvdCount;           /*Count for received Pdu */
2891    PjUlCb       *ulCb;            /* PTR to UL Control Block     */
2892    U32          rxDelivHfn;     /*Hfn of the rxDeliv */
2893
2894    TRC3(pjUlmHndlDatFwdReq)
2895      
2896     /* 1. Initialisations */
2897     ulCb   = &pjRbCb->ulCb;
2898
2899   
2900    RLOG2(L_DEBUG, "pjDlmHndlDatFwdReq(pjRbCb (%d),datFwdReq(%d)) ", 
2901       pjRbCb->rbId, datFwdReq->numSdus);
2902
2903    ret      = ROK;
2904    sn       =datFwdReq->datFwdInfo[numSdus].sn;
2905    gCb->pjGenSts.numPktsRcvd += datFwdReq->numSdus;
2906    /* Process each of the SDUs with received SN and sduId */ 
2907    for ( numSdus = 0; numSdus < datFwdReq->numSdus; numSdus++ )
2908    {
2909       /* 
2910          The variables nxtTxSn and COUNT are assumed to be 
2911          already updated in dlCb to continue with the 
2912          transmission ( in the target eNodeB ).
2913       */
2914
2915       PJ_CALC_RCVD_HFN(sn,pjRbCb->snLen,ulCb->rxDeliv,rcvdHfn);
2916
2917       /* 2.5G-NR Get the count value of the receiced PDCP data pdu from rcvdSn and rcvdHfn  */
2918       PJ_GET_COUNT(rcvdCount, pjRbCb->snLen, sn, rcvdHfn);
2919
2920       /* 2. Allocate memory for the rxEnt */
2921       PJ_ALLOC(gCb,rxEnt, sizeof(PjRxEnt));
2922 #if (ERRCLASS & ERRCLS_DEBUG)
2923       if(rxEnt == NULLP)
2924       {
2925          RLOG0(L_FATAL, "Memory allocation failure");
2926          RETVALUE(RFAILED);
2927       }
2928 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
2929
2930       
2931       /* 4. Fill up the structures and insert into hashlist */
2932       rxEnt->count   =  rcvdCount;
2933       rxEnt->state   =  PJ_RDY_TO_DCIPHER;
2934       rxEnt->mBuf    =  datFwdReq->datFwdInfo[numSdus].sdu;
2935        
2936
2937       PJ_ULM_UPD_NXT2SUB(pjRbCb->ulCb, rxEnt->count); 
2938       ret = pjDbmInsRxEnt(gCb, &pjRbCb->ulCb.recBuf, rxEnt, TRUE); 
2939       if(ret == ROKDUP)
2940       {
2941          /* Duplicates are not to be inserted */
2942          /* marked to be freed up later */
2943          rxEnt->dupEntry =  TRUE;
2944       }
2945
2946       PJ_GET_HFN(pjRbCb->ulCb.rxDeliv,pjRbCb->snLen,rxDelivHfn)
2947       if((rcvdCount < ulCb->rxDeliv) && (rxDelivHfn != PJ_MAX_HFN(pjRbCb->snLen)))
2948       {
2949          rxEnt->discFlag = TRUE;
2950
2951       }
2952       if(rxEnt->dupEntry == TRUE)
2953       {
2954          /* duplicate entry */
2955          PJ_FREE_BUF(rxEnt->mBuf);
2956          PJ_FREE(gCb,rxEnt, sizeof(PjRxEnt));
2957       }
2958       else if(rxEnt->discFlag == TRUE)
2959       {
2960          /* duplicate entry */
2961          pjDbmDelRxEnt(gCb, &pjRbCb->ulCb.recBuf, rxEnt->count);
2962       }   
2963
2964       
2965       /*3.Update the RX_NEXT */
2966        PJ_ULM_UPDATE_RX_NEXT(pjRbCb,rxEnt);
2967
2968       if(pjRbCb->rbType == PJ_DRB)
2969       {
2970          rxEnt->state   =  PJ_RDY_TO_DCOMP;
2971          /*Adding MACI for 5G NR for DRB in case of intergrity protection is enabled*/
2972          if(pjRbCb->ueCb->secInfo.intProtEnbForDrb)
2973          {
2974             PJ_UNPK_MACI(rxEnt->mBuf, macI);
2975          }
2976          ret = pjUlmHdlDeCmp(gCb, pjRbCb, rxEnt);
2977       }
2978       else
2979       {
2980          rxEnt->state   =  PJ_RDY_TO_INTVER;
2981          ret = pjUlmHdlIntVer(gCb, pjRbCb, rxEnt);
2982       }
2983
2984    }
2985    RETVALUE(ROK);
2986 }
2987 /**
2988  *
2989  * @brief It processes the packets queued up in ULPktQ
2990  *
2991  * @Description
2992  *      This ulPktQ queues the forwarded message at targe enodeb 
2993  *      during handover. 
2994  *
2995  *  @param[in] pjCb     PDCP Instance control block.
2996  *  @param[in] pjUlRbCb  Uplink Rb Control block 
2997  *
2998  *  @return  Void
2999  */
3000 #ifdef ANSI
3001 PUBLIC Void pjUlmProcessUlPktQ
3002 (
3003 PjCb       *gCb,
3004 PjUlRbCb   *pjRbCb           /* !< PDCP Control Block */
3005 )
3006 #else
3007 PUBLIC Void pjUlmProcessUlPktQ(gCb, pjRbCb)
3008 PjCb       *gCb;
3009 PjUlRbCb   *pjRbCb;          /* !< PDCP Control Block */
3010 #endif
3011 {
3012    PjUlPkt *pkt;
3013    CmLList *node;
3014
3015    TRC2(pjUlmProcessUlPktQ);
3016
3017    CM_LLIST_FIRST_NODE(&(pjRbCb->ulCb.ulPktLst), node);
3018    while (node != NULLP)
3019    {
3020       pkt = (PjUlPkt *) node->node;
3021
3022       cmLListDelFrm(&(pjRbCb->ulCb.ulPktLst), node);
3023       pkt->lnk.node = NULLP;
3024       pjUlmProcessRb(gCb,pjRbCb, pkt->sn, pkt->pdu, TRUE);
3025       PJ_FREE(gCb,pkt, sizeof (PjUlPkt));
3026       
3027       CM_LLIST_FIRST_NODE(&(pjRbCb->ulCb.ulPktLst), node);
3028    }
3029
3030    RETVOID;
3031 }/* end of pjDlmProcessDlPktQ */
3032
3033 /**
3034  *
3035  * @brief
3036  *
3037  *  @param[in] pjRbCb   PDCP control block.
3038     @param[in] PjRxEnt  *rxEnt
3039  *
3040  *  @return  Void
3041  */
3042 #ifdef ANSI
3043 PRIVATE Void pjUlmEnqueueUlPkt
3044 (
3045 PjCb     *gCb,
3046 PjUlRbCb   *pjRbCb,           /* !< PDCP Control Block */
3047 PjSn      sn,               /* !< SN value of PDU */
3048 Buffer   *pdu              /* !< PDU message buffer */
3049 )
3050 #else
3051 PRIVATE Void pjUlmEnqueueUlPkt(gCb,pjRbCb, sn, pdu)
3052 PjCb     *gCb;
3053 PjUlRbCb   *pjRbCb;          /* !< PDCP Control Block */
3054 PjSn      sn;              /* !< SN value of PDU */
3055 Buffer   *pdu;             /* !< PDU message buffer */
3056 #endif
3057 {
3058    PjUlPkt    *pkt;
3059
3060    TRC2(pjUlmEnqueueUlPkt)
3061
3062    PJ_ALLOC(gCb,pkt, sizeof(PjUlPkt));
3063    if (pkt != NULLP)
3064    {
3065       pkt->sn = sn;
3066       pkt->pdu = pdu;
3067       pkt->type = PJ_DATA_NRM_PKT;
3068       pkt->lnk.node = (PTR)pkt;
3069       cmLListAdd2Tail (&pjRbCb->ulCb.ulPktLst, &pkt->lnk);
3070    }
3071    else
3072    {
3073       RLOG0(L_FATAL, "Memory allocation failure");
3074       PJ_FREE_BUF(pdu);
3075    }
3076
3077    RETVOID;
3078 }
3079                                                         
3080 /*@}*/
3081
3082 /********************************************************************30**
3083   
3084          End of file
3085 **********************************************************************/