1 /*******************************************************************************
2 ################################################################################
3 # Copyright (c) [2017-2019] [Radisys] #
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 #
9 # http://www.apache.org/licenses/LICENSE-2.0 #
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 *******************************************************************************/
19 /**********************************************************************
25 Desc: Source code for PDCP Downlink module.
26 This file contains following functions
44 **********************************************************************/
46 static const char* RLOG_MODULE_NAME="PDCP";
47 static int RLOG_FILE_ID=241;
48 static int RLOG_MODULE_ID=1024;
50 @brief PDCP Downlink module
53 /* header (.h) include files */
54 #include "envopt.h" /* environment options */
55 #include "envdep.h" /* environment dependent */
56 #include "envind.h" /* environment independent */
58 #include "gen.h" /* general */
59 #include "ssi.h" /* system services interface */
60 #include "cm5.h" /* Timer Functions */
61 #include "cm_lte.h" /* common LTE header file */
62 #include "cm_hash.h" /* common hash module file */
63 #include "cm_llist.h" /* common list header file */
64 #include "cpj.h" /* RRC layer */
65 #include "pju.h" /* PDCP service user */
66 #include "lpj.h" /* LPJ defines */
67 #include "pj_env.h" /* RLC environment options */
68 #include "pj.h" /* RLC layer */
72 #ifndef TENB_T2K3K_SPECIFIC_CHANGES
73 void prc_trace_format_string(U32 group_mask, U16 level, const char *format, ...);
77 /* header/extern include files (.x) */
78 #include "gen.x" /* general */
79 #include "ssi.x" /* system services interface */
80 #include "cm_lib.x" /* common library */
81 #include "cm5.x" /* Timer Functions */
82 #include "cm_hash.x" /* common hash module */
83 #include "cm_lte.x" /* common LTE file */
84 #include "cm_llist.x" /* common list header file */
85 #include "cpj.x" /* RRC layer */
86 #include "pju.x" /* PDCP service user */
87 #include "lpj.x" /* LPJ defines */
88 #include "pj.x" /* RLC layer */
94 EXTERN U32 pjTotDlPckCntPerCell;
95 #ifdef TENB_AS_SECURITY
96 EXTERN U8 isSecBatchMode;
100 #ifdef TENB_T2K3K_SPECIFIC_CHANGES
101 EXTERN Ticks SGetT2KTtiCount(Void);
103 /* kw005.201 Moved definition of PJ_ASYNC_WIN to kw.h file */
104 /** @addtogroup dldata */
106 EXTERN S16 pjUtlChekTxEnqReq ARGS(( PjCb *gCb, PjDlRbCb *pjRbCb, PjTxEnt *txEnt));
108 PRIVATE S16 pjDlmBldPdu(PjCb *gCb,PjDlRbCb *pjRbCb,PjTxEnt *txEnt);
109 PRIVATE Void pjDlmDelTxEntUptoFmc ARGS ((PjCb *gCb, PjDlRbCb *pjRbCb, U32 fmc, PjuDatCfmInfo *datCfm));
115 * Handler to free all sdus present in datCfmQ till the First Missing
118 * @param[in] pjRbCb PDCP control block.
119 * @param[in] fmc First Missing Segment count
120 * @param[in] datCfm datCfm
127 PRIVATE Void pjDlmDelTxEntUptoFmc
132 PjuDatCfmInfo *datCfm
135 PRIVATE Void pjDlmDelTxEntUptoFmc(gCb, pjRbCb, count, datCfm)
139 PjuDatCfmInfo *datCfm;
145 cmLListFirst(&pjRbCb->dlCb.txBuf.datCfmQ);
146 while (cmLListCrnt(&pjRbCb->dlCb.txBuf.datCfmQ))
148 txEnt = (PjTxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.txBuf.datCfmQ));
151 if (txEnt->count < count)
153 if (pjRbCb->dlCb.cfmReqd && datCfm!= NULLP)
155 /* As of now, DATCFM is sent only for the 1st 25 PDUs. Once we */
156 /* enable cfmReqd, we need to add code to send for all PDUs in loop */
157 if(datCfm->numSdus < PJU_MAX_SDU_CFM)
159 datCfm->cfmSta[datCfm->numSdus].sduId = txEnt->sduId;
160 datCfm->cfmSta[datCfm->numSdus].status = PJ_CFM_OK;
164 pjDbmDelTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt->count);
168 /* fmc reached break out of the loop */
172 cmLListNext(&pjRbCb->dlCb.txBuf.datCfmQ);
182 * Handler to process the SDU received from upper layer, form a PDU
183 * and send the PDU to the lower layer.
187 * 1. This function places the SDU in the transmission buffer and performs
188 * Compression for DRB SDUs and Integrity Protection for SRB SDUs. @n
189 * 2. After compression/integrity protection, it performs ciphering and then
190 * constructs the PDU and sends it to the lower layer. @n
191 * 3. The first DL message of SRBs is not ciphered and is just integrity
193 * 4. This function checks the UE CB control block to check the flag for the
194 * first DL message and performs only integrity protection and unsets
197 * @param[in] pjRbCb PDCP control block.
198 * @param[in] sdu SDU to be processed.
199 * @param[in] sduId SDU ID.
209 PUBLIC S16 pjDlmProcessSdus
212 PjDlRbCb *pjRbCb, /* !< PDCP Control Block */
213 Buffer *sdu, /* !< SDU to be processed */
214 U32 sduId, /* !< PDCP SDU ID */
215 U32 count /* !< count to be assigned */
218 PUBLIC S16 pjDlmProcessSdus(gCb, pjRbCb, sdu, sduId, count)
220 PjDlRbCb *pjRbCb; /* !< PDCP Control Block */
221 Buffer *sdu; /* !< SDU to be processed */
222 U32 sduId; /* !< PDCP SDU ID */
223 U32 count; /* !< count to be assigned */
226 S16 ret; /* Return Value */
227 PjTxEnt *txEnt; /* Transmission Entity for sdu*/
229 U8 hashKey; /* Computed HashKey */
233 TRC2(pjDlmProcessSdus)
236 PJDBGP(gCb,(PJ_DBGMASK_DLM | PJ_DBGMASK_BRIEF | PJ_DBGMASK_DL),
237 (gCb->init.prntBuf, "pjDlmProcessSdus(pjRbCb(%d), sdu, sduId(%ld), \
238 txHfn) \n)", pjRbCb->rbId, sduId));
240 PJDBGP(gCb,(PJ_DBGMASK_DLM | PJ_DBGMASK_BRIEF | PJ_DBGMASK_DL),
241 (gCb->init.prntBuf, "pjDlmProcessSdus(pjRbCb(%d), sdu, sduId(%d), \
242 txHfn) \n)", pjRbCb->rbId, sduId));
248 /* Allocate the transmission entity */
249 PJ_ALLOC(gCb,txEnt, sizeof(PjTxEnt));
251 #if (ERRCLASS & ERRCLS_ADD_RES)
254 RLOG0(L_FATAL, "Memory Allocation failed.");
258 #endif /* ERRCLASS & ERRCLS_RES */
260 /* Update COUNT to the current count in dlCb*/
261 pjRbCb->dlCb.count = count;
262 /* Fill TxEnt values */
263 PJ_DLM_GET_SN(pjRbCb,count,txEnt->sn);
264 //txEnt->count = count;
265 //txEnt->txHfn = txHfn;
266 txEnt->count = count;
267 txEnt->state = PJ_SDU_RECEIVED;
268 txEnt->sduId = sduId;
269 /* The received buffer is stored in the SDU and the output from
270 * Compression/Ciphering is stored in the PDU.
275 /* Process the SDU based on rbType */
276 if (pjRbCb->rbType == PJ_SRB)
278 /* Insert TxEnt into the transmission buffer */
279 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
280 ret = pjDlmProcSrb(gCb, pjRbCb, txEnt);
284 #ifndef RGL_SPECIFIC_CHANGES
287 EXTERN U32 dlrate_pju;
289 SFndLenMsg(sdu, (MsgLen *) &len);
294 #ifndef L2_PDCP_OPTMZ
295 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
297 /* Fix for NULL ciphering. For null ciphering add PDUs to sduSubmitQ*/
298 if(pjRbCb->ueCb->secInfo.secAct && pjRbCb->ueCb->secInfo.cipherInfo.algoType != 0)
300 txEnt->datCfmEnt.node = NULLP;
301 txEnt->reEstPktEnt.node = NULLP;
302 txEnt->sduSubmitEnt.node = (PTR)NULLP;
304 buf=&(pjRbCb->dlCb.txBuf);
305 hashKey = (U8)PJ_HASH_FN(buf, txEnt->count); /*KW_FIX*/
307 txEnt->lstEnt.node = (PTR)txEnt;
308 cmLListAdd2Tail(&buf->datQ[hashKey], &txEnt->lstEnt);
310 /* Dont add PDUs to datCfmQ in case of UM mode*/
311 if (pjRbCb->mode == PJ_DRB_AM )
313 txEnt->datCfmEnt.node = (PTR)txEnt;
314 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.datCfmQ, &txEnt->datCfmEnt);
316 txEnt->state = PJ_PDU_SUBMITTED;
320 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
323 ret = pjDlmProcDrb(gCb, pjRbCb, txEnt);
333 * Handler to Re-establish a SRB.
337 * 1. This function is called when re-establishment request is
338 * received for a SRB. @n
339 * 2. The stored PDUs and SDUs are freed and the variables are reset. @n
341 * @param[in] pjRbCb PDCP control block.
346 PUBLIC Void pjDlmRbDataResume
352 PUBLIC Void pjDlmRbDataResume(gCb, pjRbCb)
359 TRC3(pjDlmRbDataResume)
361 RLOG_ARG0(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmRbDataResume(pjRbCb ()) ");
363 cmLListFirst(&pjRbCb->dlCb.txBuf.reEstPktQ);
364 while (cmLListCrnt(&pjRbCb->dlCb.txBuf.reEstPktQ))
366 txEnt = (PjTxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.txBuf.reEstPktQ));
367 #if (ERRCLASS & ERRCLS_DEBUG) /* KW_FIX */
370 RLOG_ARG0(L_ERROR,DBG_RBID,pjRbCb->rbId,
371 "pjDlmRbDataResume:Transmission Entity is NULL ");
372 /*ccpu00136858 : Void function returning RFAILED */
375 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
376 /* Free the existing PDU and cpy the SDU to PDU */
378 #ifdef FLAT_BUFFER_OPT
379 #ifndef XEON_SPECIFIC_CHANGES
381 /* Check whether the spacc q has space to hold
382 this packet.. else dropping */
383 if(FALSE == (pjMsCheckSpaccQueue(FALSE)))
386 extern U32 spaccDropCount;
389 PJ_FREE_FLAT_BUF(pjCb[1],&(txEnt->fb));
390 gPdcpStats.numPdcpSdusDiscarded++;
391 PJ_UPD_L2_DLDISC_STS(pjCb[1], pjRbCb);
393 if(txEnt->pdu != NULL)
394 printf("PDU is not null while deletion");
396 if(txEnt->sdu != NULL)
397 printf("SDU is not null while deletion");
398 pjDbmDelTxEnt(pjCb[1], &(pjRbCb->dlCb.txBuf), txEnt->count);
399 //txEnt->reEstPktEnt.node = NULLP;
400 //cmLListDelFrm(&pjRbCb->dlCb.txBuf.reEstPktQ, &txEnt->reEstPktEnt);
402 cmLListFirst(&pjRbCb->dlCb.txBuf.reEstPktQ);
408 #ifdef FLAT_BUFFER_OPT
409 if(txEnt->sdu == NULLP)
411 PJ_FREE_BUF(txEnt->pdu);
415 if ( txEnt->pdu != txEnt->sdu )
417 PJ_FREE_BUF(txEnt->pdu);
424 txEnt->state = PJ_PDU_SUBMITTED;
426 txEnt->state = PJ_SDU_RECEIVED;
428 /* Fix for ccpu00135798 */
429 txEnt->reEstPktEnt.node = NULLP;
430 cmLListDelFrm(&pjRbCb->dlCb.txBuf.reEstPktQ, &txEnt->reEstPktEnt);
431 #ifndef L2_PDCP_OPTMZ
432 txEnt->sduSubmitEnt.node = (PTR)txEnt;
433 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.sduSubmitQ, &txEnt->sduSubmitEnt);
435 if( pjRbCb->mode == PJ_DRB_AM)
437 txEnt->datCfmEnt.node = (PTR)txEnt;
438 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.datCfmQ, &txEnt->datCfmEnt);
442 ret = pjDlmProcDrb(gCb, pjRbCb, txEnt);
445 RLOG_ARG0(L_ERROR,DBG_RBID,pjRbCb->rbId,
446 "pjDlmRbDataResume: pjDlmProcDrb Failed ");
448 cmLListFirst(&pjRbCb->dlCb.txBuf.reEstPktQ);
451 pjDlmProcessDlPktQ(gCb,pjRbCb);
456 #ifdef FLAT_BUFFER_OPT
462 * Handler to process the SDU received from upper layer, form a PDU
463 * and send the PDU to the lower layer.
467 * 1. This function places the SDU in the transmission buffer and performs
468 * Compression for DRB SDUs and Integrity Protection for SRB SDUs. @n
469 * 2. After compression/integrity protection, it performs ciphering and then
470 * constructs the PDU and sends it to the lower layer. @n
471 * 3. The first DL message of SRBs is not ciphered and is just integrity
473 * 4. This function checks the UE CB control block to check the flag for the
474 * first DL message and performs only integrity protection and unsets
477 * @param[in] pjRbCb PDCP control block.
478 * @param[in] sdu SDU to be processed.
479 * @param[in] sduId SDU ID.
487 PUBLIC S16 pjDlmProcessSdusFB
489 PjCb *gCb, /* !< Global control Block*/
490 PjDlRbCb *pjRbCb, /* !< PDCP Control Block */
491 FlatBuffer *sdu, /* !< SDU to be processed */
492 U32 sduId, /* !< PDCP SDU ID */
493 U32 count /* !< TX_HFN to be assigned */
496 PUBLIC S16 pjDlmProcessSdusFB(gCb, pjRbCb, sdu, sduId, count)
497 PjCb *gCb; /* !< Global control Block*/
498 PjDlRbCb *pjRbCb; /* !< PDCP Control Block */
499 FlatBuffer *sdu; /* !< SDU to be processed */
500 U32 sduId; /* !< PDCP SDU ID */
501 U32 count; /* !< TX_HFN to be assigned */
504 S16 ret; /* Return Value */
505 PjTxEnt *txEnt; /* Transmission Entity for sdu*/
507 U8 hashKey; /* Computed HashKey */
512 TRC2(pjDlmProcessSdusFB)
515 RLOG_ARG2(L_DEBUG,DBG_RBID,pjRbCb->rbId,
516 "pjDlmProcessSdusFB(pjRbCb(), sdu, sduId(%ld), count(%ld) )",
519 RLOG_ARG2(L_DEBUG,DBG_RBID,pjRbCb->rbId,
520 "pjDlmProcessSdusFB(pjRbCb(), sdu, sduId(%d), count(%d) )",
527 /* Allocate the transmission entity */
528 PJ_ALLOC(gCb,txEnt, sizeof(PjTxEnt));
530 #if (ERRCLASS & ERRCLS_ADD_RES)
533 RLOG0(L_FATAL, "Memory Allocation failed.");
534 PJ_FREE_FLAT_BUF(gCb,sdu);
537 #endif /* ERRCLASS & ERRCLS_RES */
539 /* Update COUNT to the current count in dlCb*/
541 PJ_DLM_UPD_VAR(pjRbCb,txEnt->count);
542 PJ_DLM_GET_SN(pjRbCb,txEnt->count,txEnt->sn);
543 pjRbCb->dlCb.count = txEnt->count;
544 /* Fill TxEnt values */
545 txEnt->state = PJ_SDU_RECEIVED;
546 txEnt->sduId = sduId;
547 /* The received buffer is stored in the SDU and the output from
548 * Compression/Ciphering is stored in the PDU.
553 /* Insert TxEnt into the transmission buffer */
554 /* kw005.201 added support for L2 Measurement */
555 #ifndef L2_PDCP_OPTMZ
556 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
558 /* Fix for NULL ciphering. For null ciphering add PDUs to sduSubmitQ*/
559 if(pjRbCb->ueCb->secInfo.secAct && pjRbCb->ueCb->secInfo.cipherInfo.algoType != 0)
561 txEnt->datCfmEnt.node = NULLP;
562 txEnt->reEstPktEnt.node = NULLP;
563 txEnt->sduSubmitEnt.node = (PTR)NULLP;
565 buf=&(pjRbCb->dlCb.txBuf);
566 hashKey = (U8)PJ_HASH_FN(buf, txEnt->count); /*KW_FIX*/
568 txEnt->lstEnt.node = (PTR)txEnt;
569 cmLListAdd2Tail(&buf->datQ[hashKey], &txEnt->lstEnt);
572 /* Dont add PDUs to datCfmQ in case of UM mode*/
573 if (pjRbCb->mode == PJ_DRB_AM )
575 txEnt->datCfmEnt.node = (PTR)txEnt;
576 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.datCfmQ, &txEnt->datCfmEnt);
579 txEnt->state = PJ_PDU_SUBMITTED;
583 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
587 /* Process the SDU based on rbType */
589 #ifndef RGL_SPECIFIC_CHANGES
592 extern U32 dlrate_pju;
593 dlrate_pju += sdu->len;
597 ret = pjDlmProcDrb(gCb, pjRbCb, txEnt);
608 * Handler to construct a data PDU/Control PDU.
612 * 1. This function constructs the PDU header based on the SN length
614 * 2. The header is inserted at the start of the PDU and
615 * the constructed PDU is returned to the calling function. @n
617 * @param[in] pjRbCb PDCP control block.
618 * @param[in] txEnt Transmission Entity.
626 PRIVATE S16 pjDlmBldPdu
633 PRIVATE S16 pjDlmBldPdu(gCb,pjRbCb,txEnt)
639 U32 hdr; /* Header field */
640 S16 ret; /* Return Value */
641 U32 numBytes; /* Number of bytes to be added to the PDU */
645 PJDBGP(gCb,(PJ_DBGMASK_DLM | PJ_DBGMASK_BRIEF | PJ_DBGMASK_DL),
646 (gCb->init.prntBuf, "pjDlmBldPdu(pjRbCb, txEnt (%ld)) \n", txEnt->sduId));
648 PJDBGP(gCb,(PJ_DBGMASK_DLM | PJ_DBGMASK_BRIEF | PJ_DBGMASK_DL),
649 (gCb->init.prntBuf, "pjDlmBldPdu(pjRbCb, txEnt (%d)) \n", txEnt->sduId));
654 numBytes = 2; /* for SRB it is 1 byte and even for 7 bit SN on DRB it is 1 byte */
658 /* Build a Data PDU */
659 if ( pjRbCb->rbType != PJ_SRB )
662 /* The two byte header has the SN and MSB as '1' */
663 if (pjRbCb->snLen == PJ_12_BIT_SN)
665 hdr |= PJ_DRB_12BIT_SN_HDR;
668 else if (pjRbCb->snLen == PJ_18_BIT_SN)
670 hdr |= PJ_DRB_18BIT_SN_HDR;
675 /* Add the hdr(based on numBytes) at the start of the PDU */
676 PJ_ADD_PRE_MSG( txEnt->pdu, hdr, numBytes, ret);
678 #if (ERRCLASS & ERRCLS_ADD_RES)
681 RLOG_ARG1(L_ERROR, DBG_RBID, pjRbCb->rbId,
682 "SAddPreMsg failed SN [%u]",
686 #endif /* ERRCLASS & ERRCLS_RES */
694 * Handler to Re-establish a SRB.
698 * 1. This function is called when re-establishment request is
699 * received for a SRB. @n
700 * 2. The stored PDUs and SDUs are freed and the variables are reset. @n
702 * @param[in] pjRbCb PDCP control block.
707 PUBLIC Void pjDlmReEstSrb
713 PUBLIC Void pjDlmReEstSrb(gCb, pjRbCb)
721 RLOG_ARG0(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmResetSrb(pjRbCb ()) ");
724 /* Stop the off-board and discard timer if running */
725 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
726 if (pjRbCb->dlCb.obdTmr.tmrEvnt == PJ_EVT_DL_OBD_TMR)
728 pjStopTmr(gCb, (PTR)pjRbCb, PJ_EVT_DL_OBD_TMR);
731 /* Clean up all the SDUs present */
732 pjDbmTxDelAll(gCb, &(pjRbCb->dlCb.txBuf));
734 /* Reset the variables in rbCb */
735 PJ_RESET_ALL_VAR(pjRbCb);
736 /*kw004.201 Adding of Missing Trace in LTE RLC PDCP*/
744 * Handler to Re-establish a UM DRB.
748 * 1. This function is called when re-establishment request is
749 * received for a UM DRB. @n
750 * 2. The stored PDUs are freed and the variables are reset. @n
751 * 3. The PDUs which were associated with a SN and were not sent
752 * to the lower layer are now sent with the new ciphering
753 * algorithm and keys. @n
755 * @param[in] pjRbCb PDCP control block.
764 PUBLIC S16 pjDlmReEstDrbUm
770 PUBLIC S16 pjDlmReEstDrbUm(gCb,pjRbCb)
775 S16 ret; /* Return Value */
776 PjTxEnt *txEnt; /* Transmission Entity */
777 PjBuf tmpTxBuf; /* Tx Buffer */
779 TRC3(pjDlmReEstDrbUm)
781 RLOG_ARG0(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmReEstDrbUm(pjRbCb ()) ");
782 ret = ROK; /* KW_FIX */
785 /* Reset all the variable */
786 PJ_RESET_ALL_VAR(pjRbCb);
787 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
788 /* Stop the off board timer if running */
789 if (pjRbCb->dlCb.obdTmr.tmrEvnt == PJ_EVT_DL_OBD_TMR)
791 pjStopTmr(gCb, (PTR)pjRbCb, PJ_EVT_DL_OBD_TMR);
795 if(pjRbCb->dlCb.txBuf.numEntries == 0)
800 /* Create the new buffer list and store the old pointer in datQ */
801 PJ_CREATE_NEW_LIST(gCb,pjRbCb, tmpTxBuf, ret);
802 #if (ERRCLASS & ERRCLS_ADD_RES)
805 RLOG0(L_FATAL, "Memory Allocation failed");
808 #endif /* ERRCLASS & ERRCLS_RES */
810 /* Process all the existing PDUs as received from above layer */
811 cmLListFirst(&tmpTxBuf.sduSubmitQ);
812 while (cmLListCrnt(&tmpTxBuf.sduSubmitQ))
815 txEnt = (PjTxEnt *) cmLListNode(cmLListCrnt(&tmpTxBuf.sduSubmitQ));
816 /* Assign the new SN, TX_HFN and insert in the new transmission
819 if ( txEnt != NULLP )
821 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
822 if ( txEnt->pdu != txEnt->sdu )
824 PJ_FREE_BUF(txEnt->pdu);
831 hashKey = (U8)PJ_HASH_FN((&tmpTxBuf), txEnt->count);
832 PJ_DLM_UPD_VAR(pjRbCb,txEnt->count);
833 PJ_DLM_GET_SN(pjRbCb,txEnt->count,txEnt->sn);
834 pjRbCb->dlCb.count = txEnt->count;
835 txEnt->state = PJ_SDU_RECEIVED;
838 cmLListDelFrm(&tmpTxBuf.datQ[hashKey], &txEnt->lstEnt);
839 cmLListDelFrm(&tmpTxBuf.sduSubmitQ, &txEnt->sduSubmitEnt);
841 tmpTxBuf.numEntries --;
843 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
845 txEnt->reEstPktEnt.node = (PTR)txEnt;
846 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.reEstPktQ, &txEnt->reEstPktEnt);
848 txEnt->sduSubmitEnt.node=NULLP;
849 cmLListDelFrm(&pjRbCb->dlCb.txBuf.sduSubmitQ, &txEnt->sduSubmitEnt);
851 cmLListFirst(&tmpTxBuf.sduSubmitQ);
853 /* Free up the old transmission buffer */
854 pjDbmTxDeInit(gCb,&tmpTxBuf);
862 * Handler to Re-establish a AM DRB.
866 * 1. This function is called when re-establishment request is
867 * received for a AM DRB. @n
868 * 2. The stored PDUs are freed. @n
869 * 3. The PDUs which were not submitted to the lower
870 * layer and for which a confirm has not been received
871 * are now sent with the new ciphering algorithm and keys. @n
873 * @param[in] pjRbCb PDCP control block.
881 PUBLIC S16 pjDlmReEstDrbAm
887 PUBLIC S16 pjDlmReEstDrbAm(gCb,pjRbCb)
894 TRC3(pjDlmReEstDrbAm)
896 RLOG_ARG0(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmReEstDrbAm(pjRbCb ()) ");
899 if (pjRbCb->dlCb.txBuf.numEntries == 0)
904 cmLListFirst(&pjRbCb->dlCb.txBuf.datCfmQ);
905 while (cmLListCrnt(&pjRbCb->dlCb.txBuf.datCfmQ))
907 txEnt = (PjTxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.txBuf.datCfmQ));
908 #if (ERRCLASS & ERRCLS_DEBUG) /* KW_FIX */
911 RLOG_ARG0(L_ERROR,DBG_RBID,pjRbCb->rbId,
912 "pjDlmReEstDrbAm:Transmission Entity is NULL ");
915 #endif /* (ERRCLASS & ERRCLS_DEBUG) */
918 txEnt->reEstPktEnt.node = (PTR)txEnt;
919 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.reEstPktQ, &txEnt->reEstPktEnt);
920 pjTotDlPckCntPerCell--;
922 txEnt->datCfmEnt.node = NULLP;
923 cmLListDelFrm(&pjRbCb->dlCb.txBuf.datCfmQ, &txEnt->datCfmEnt);
924 cmLListFirst(&pjRbCb->dlCb.txBuf.datCfmQ);
927 cmLListFirst(&pjRbCb->dlCb.txBuf.sduSubmitQ);
928 while (cmLListCrnt(&pjRbCb->dlCb.txBuf.sduSubmitQ))
930 txEnt = (PjTxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.txBuf.sduSubmitQ));
931 if (txEnt != NULLP) /*KW_FIX : ccpu00136902*/
933 txEnt->reEstPktEnt.node = (PTR)txEnt;
934 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.reEstPktQ, &txEnt->reEstPktEnt);
935 txEnt->sduSubmitEnt.node=NULLP;
936 cmLListDelFrm(&pjRbCb->dlCb.txBuf.sduSubmitQ, &txEnt->sduSubmitEnt);
937 cmLListFirst(&pjRbCb->dlCb.txBuf.sduSubmitQ);
941 RLOG_ARG0(L_ERROR,DBG_RBID,pjRbCb->rbId, "This should not be hit ");
953 * Handler to send data confirmation to RRC.
957 * 1. This function is called when a status indication or a confirm is
958 * received from the lower layer. @n
959 * 2. The confirm type can be a success or failure. @n
960 * 3. The corresponding SDUs and PDUs are cleaned up and
961 * if cfmReqd is configured, a confirm is sent to the upper layer. @n
963 * @param[in] pjRbCb PDCP control block.
964 * @param[in] staInd Status Indication Information.
965 * @param[in] cfmType Confirm Type can be SUCCESS or FAILURE.
976 PUBLIC S16 pjDlmProcessCfm
984 PUBLIC S16 pjDlmProcessCfm(gCb,pjRbCb,pjDatCfm,cfmType)
991 PjuDatCfmInfo *datCfm; /* Data Cfm to be sent to upper layer */
992 U32 cnt; /* Counter for number of SDUs in datCfm*/
993 U16 datCfmCnt; /* Counter for number of SDUs in datCfm*/ /*KW_FIX*/
994 PjPjuSapCb *pjuSap; /* Upper Sap of PDCP User */
995 CmLtePdcpId *pdcpId; /* PDCP ID */
996 PjTxEnt *txEnt; /* Transmission entity */
998 TRC3(pjDlmProcessCfm)
1000 gCb->pjPerfSts.pjSduRcvCnt += pjDatCfm->numSdu;
1008 /* If cfmReqd flag is sent a confirmation is sent to the above layer.
1009 * For each SDU, get the sduId and status and fill in the datCfm
1010 * structure and discard the txEnt. Also update cfmExp count.
1012 if ( (pjRbCb->dlCb.cfmReqd) || (PJ_CFM_NOK == cfmType))
1014 PjuDatCfmInfo datCfmTmp;
1015 CmLtePdcpId pdcpIdTmp;
1016 datCfm = &datCfmTmp;
1017 pdcpId = &pdcpIdTmp;
1018 pdcpId->rbId = pjRbCb->rbId;
1019 pdcpId->rbType = pjRbCb->rbType;
1020 pdcpId->ueId = pjRbCb->ueCb->key.ueId;
1021 pdcpId->cellId = pjRbCb->ueCb->key.cellId;
1023 if (pjRbCb->rbType == PJ_SRB)
1024 pjuSap = &(gCb->u.dlCb->pjuSap[PJ_SRB_SAP]);
1026 pjuSap = &(gCb->u.dlCb->pjuSap[PJ_DRB_SAP]);
1029 for ( cnt = 0; cnt < pjDatCfm->numSdu; cnt++)
1031 txEnt = (PjTxEnt *)pjDbmGetTxEnt(gCb,&(pjRbCb->dlCb.txBuf),
1032 pjDatCfm->sduId[cnt]);
1033 if ( txEnt != NULLP )
1035 datCfm->cfmSta[datCfmCnt].sduId = txEnt->sduId;
1036 /* RLC_DL_MAX_RETX fix */
1037 if (PJ_CFM_OK != cfmType)
1039 datCfm->cfmSta[datCfmCnt].status = PJU_RLC_TRANS_FAIL;
1043 datCfm->cfmSta[datCfmCnt].status = cfmType;
1046 datCfm->cfmSta[datCfmCnt].status = cfmType;
1048 pjDbmDelTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt->count);
1051 datCfm->numSdus = datCfmCnt;
1054 /* If trace flag is enabled send the trace indication */
1055 if(gCb->init.trc == TRUE)
1057 /* Populate the trace params */
1058 pjLmmSendTrc(gCb, EVTPJUDATCFM, NULLP);
1061 PjUiPjuDatCfm(&pjuSap->pst, pjuSap->suId, pdcpId, datCfm);
1064 /* If cfmReqd is not set, discard the txEnts and update the cfmExp count */
1067 for ( cnt = 0; cnt < pjDatCfm->numSdu; cnt++)
1069 pjDbmDelTxEnt(gCb, &(pjRbCb->dlCb.txBuf), pjDatCfm->sduId[cnt]);
1081 * Handler to send process the status report.
1085 * 1. This function is called when a status report is received from the
1087 * 2. This function process the status report and sends a confirmation
1088 * to the above layer and removes the PDUs and SDUs for which positive
1089 * acknowledgement is received. @n
1091 * @param[in] pjRbCb PDCP control block.
1092 * @param[in] staPdu Status report.
1101 PUBLIC S16 pjDlmHndlStaRep
1109 PUBLIC S16 pjDlmHndlStaRep(gCb,pjRbCb,fmc,staPdu)
1116 PjuDatCfmInfo *datCfm; /* Dat Cfm to be sent to the upper layer */
1117 PjuDatCfmInfo datCfmTmp; /* Tmp variable allocated to assign local memory to the datCfm pointer */
1118 CmLtePdcpId pdcpIdTmp; /* Tmp variable allocated to assign local memory to the pdcpId pointer */
1119 S16 ret; /* Return Value */
1120 PjPjuSapCb *pjuSap; /* PJU SAP Control Block */
1121 CmLtePdcpId *pdcpId; /* PDCP ID */
1122 U32 bitPos; /* Bit position in the Status PDU */
1123 U8 cnt; /* Counter for the bits in a byte */
1124 U8 sduSta; /* SDU Status of reception at the Peer */
1125 PjTxEnt *txEnt; /* Transmission entity */
1126 U8 byte; /* One Byte of a Status Pdu */
1127 MsgLen bMapLen; /* StaPdu Length in bytes */
1128 PjSn count; /* count of the PDU */
1130 TRC3(pjDlmHndlStaRep)
1132 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmHndlStaRep(pjRbCb (), fmc (%lu), staPdu) ",fmc);
1140 /* Allocate for datCfm structure is cfmReqd is set */
1141 if ( pjRbCb->dlCb.cfmReqd )
1143 datCfm = &datCfmTmp;
1146 /* Fills the confirm information for all the PDUs whose COUNT < COUNT(FMC)
1147 * and sets cfmExp to fmc
1149 pjDlmDelTxEntUptoFmc(gCb, pjRbCb, fmc, datCfm);
1156 SFndLenMsg(staPdu, &bMapLen);
1158 /* Read one byte at a time from Status PDU */
1159 while ( bMapLen != 0 )
1161 ret = SRemPreMsg(&byte,staPdu);
1162 #if (ERRCLASS & ERRCLS_ADD_RES)
1165 RLOG0(L_ERROR, "SRemPreMsg Failed for staPdu");
1166 PJ_FREE_BUF(staPdu);
1169 #endif /* ERRCLASS & ERRCLS_RES */
1171 /* Check if each bit in a byte is set or not.
1172 * If cfmReqd is set fill in the cfm info.
1173 * Discard the txEnt if the bit is set to 1.
1175 for ( cnt = 0; cnt < PJ_BYTE_LEN; cnt++, bitPos++ )
1177 sduSta = (byte << cnt) & PJ_FIRST_BIT;
1180 count = (fmc + bitPos) % PJ_TX_BUF_LEN;
1181 txEnt = (PjTxEnt *)pjDbmGetTxEnt(gCb, &(pjRbCb->dlCb.txBuf), count);
1182 if ( txEnt != NULLP )
1184 if ((pjRbCb->dlCb.cfmReqd)&& (datCfm->numSdus < PJU_MAX_SDU_CFM))
1187 datCfm->cfmSta[datCfm->numSdus].sduId = txEnt->sduId;
1188 datCfm->cfmSta[datCfm->numSdus].status = sduSta;
1191 pjDbmDelTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt->count);
1197 /* Send a confirmation to the upper layer */
1198 if ((pjRbCb->dlCb.cfmReqd) && (datCfm->numSdus > 0))
1200 pdcpId = &pdcpIdTmp;
1202 pdcpId->rbId = pjRbCb->rbId;
1203 pdcpId->rbType = pjRbCb->rbType;
1204 pdcpId->ueId = pjRbCb->ueCb->key.ueId;
1205 pdcpId->cellId = pjRbCb->ueCb->key.cellId;
1207 pjuSap = &gCb->u.dlCb->pjuSap[PJ_DRB_SAP];
1208 /* If trace flag is enabled send the trace indication */
1209 if(gCb->init.trc == TRUE)
1211 /* Populate the trace params */
1212 pjLmmSendTrc(gCb, EVTPJUDATCFM, NULLP);
1214 PjUiPjuDatCfm(&pjuSap->pst, pjuSap->suId, pdcpId, datCfm);
1217 PJ_FREE_BUF(staPdu);
1226 * Handler to forward the downlink data to the upper layer.
1230 * 1. This function is used to send the downlink data to the upper layer
1231 * during handover. @n
1232 * 2. The unacknowledged data SDUs are sent to the upper
1235 * @param[in] pjRbCb PDCP control block.
1244 PUBLIC S16 pjDlmReEstHoDrbAm
1250 PUBLIC S16 pjDlmReEstHoDrbAm(gCb,pjRbCb)
1255 TRC3(pjDlmReEstHoDrbAm)
1257 RLOG_ARG0(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmReEstHoDrbAm(pjRbCb ()) ");
1260 pjRbCb->pktAdmitCnt = 0;
1261 pjRbCb->ueCb->hoInfo->hoCfmInfo[pjRbCb->rbId].pres = TRUE;
1262 pjRbCb->ueCb->hoInfo->hoCfmInfo[pjRbCb->rbId].rbId = pjRbCb->rbId;
1263 pjRbCb->ueCb->hoInfo->hoCfmInfo[pjRbCb->rbId].dir = PJ_DIR_DL;
1264 pjRbCb->ueCb->hoInfo->hoCfmInfo[pjRbCb->rbId].count = pjRbCb->dlCb.count + 1;
1274 * Handler to forward the downlink data to the upper layer.
1278 * 1. This function is used to send the downlink data to the upper layer
1279 * during handover. @n
1280 * 2. The unacknowledged data SDUs are sent to the upper
1283 * @param[in] pjRbCb PDCP control block.
1292 PUBLIC S16 pjDlmStartDataFrwdPerRb
1298 PUBLIC S16 pjDlmStartDataFrwdPerRb(gCb,pjRbCb)
1305 U16 count; /*KW_FIX*/
1306 U32 numSduCnt =0,numSduTx = 0;
1307 PjTxEnt *txEnt = NULLP;
1308 PjuDatFwdIndInfo *datFwdInd = NULLP;
1310 PjDlPkt *pkt = NULLP;
1312 TRC3(pjDlmStartDataFrwdPerRb)
1314 RLOG_ARG0(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmStartDataFrwdPerRb(pjRbCb ()) ");
1316 pjuSap = &(gCb->u.dlCb->pjuSap[PJ_DRB_SAP]);
1317 /* Update hoCfmInfo, used to fill SduStaCfm */
1318 if(pjRbCb->dlCb.txNext == 0)
1320 // PJ_ALLOC(gCb,datFwdInd, sizeof(PjuDatFwdIndInfo));
1321 if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,(Data **)&datFwdInd,
1322 sizeof (PjuDatFwdIndInfo)) != ROK)
1324 #if (ERRCLASS & ERRCLS_ADD_RES)
1325 if (datFwdInd == NULLP)
1328 RLOG0(L_FATAL, "Memory Allocation failed.");
1330 #endif /* ERRCLASS & ERRCLS_ADD_RES */
1333 datFwdInd->dir = PJ_DIR_DL;
1334 datFwdInd->numSdus = 0;
1335 datFwdInd->isLastDatFwdInd = TRUE;
1337 /* sending DatFwdInd even if numSdu is zero */
1338 pjUtlDlSndDatFwdInd(gCb,pjRbCb, datFwdInd);
1342 /* Find the total count of the txEnts present */
1343 numSdu = pjRbCb->dlCb.txBuf.numEntries + pjRbCb->dlCb.dlPktQ.count;
1346 /* This was added from Hotfix branch when Data Fwding was not supported */
1348 cmLListFirst(&pjRbCb->dlCb.txBuf.datCfmQ);
1349 cmLListFirst(&pjRbCb->dlCb.txBuf.sduSubmitQ);
1350 cmLListFirst(&pjRbCb->dlCb.dlPktQ);
1356 /* For BRDCM PJ_FWD_MAX_SDU_CNT = 16, for MSPD PJ_FWD_MAX_SDU_CNT=1 */
1358 if(numSduCnt > PJ_FWD_MAX_SDU_CNT)
1360 numSduTx = PJ_FWD_MAX_SDU_CNT;
1361 numSduCnt = numSduCnt - PJ_FWD_MAX_SDU_CNT;
1365 numSduTx = numSduCnt;
1369 if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,(Data **)&datFwdInd,
1370 sizeof (PjuDatFwdIndInfo)) != ROK)
1373 RLOG0(L_FATAL, "Memory Allocation failed.");
1377 if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,(Data **)&datFwdInd->datFwdInfo,
1378 (sizeof(PjuDatFwdInfo) * numSduTx)) != ROK)
1380 /* Free memory for DatFwdInfo */
1381 PJ_PST_FREE(pjuSap->pst.region, pjuSap->pst.pool,datFwdInd->datFwdInfo,
1382 numSdu * sizeof(PjuDatFwdIndInfo));
1383 RLOG0(L_FATAL, "Memory Allocation failed.");
1390 if(NULLP != cmLListCrnt(&pjRbCb->dlCb.txBuf.datCfmQ))
1392 txEnt = (PjTxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.txBuf.datCfmQ));
1393 datFwdInd->datFwdInfo[count].sduId = txEnt->sduId;
1394 datFwdInd->datFwdInfo[count].sn = txEnt->sn;
1396 datFwdInd->datFwdInfo[count].sdu = txEnt->sdu;
1398 #ifdef FLAT_BUFFER_OPT
1399 if(txEnt->sdu == NULLP)
1401 pjUtlCopyFbToBuf(gCb, &(txEnt->fb), &(datFwdInd->datFwdInfo[count].sdu));
1406 SCpyMsgMsg(txEnt->sdu, 0, 0, &datFwdInd->datFwdInfo[count].sdu);
1409 cmLListNext(&pjRbCb->dlCb.txBuf.datCfmQ);
1416 if(NULLP != cmLListCrnt(&pjRbCb->dlCb.txBuf.sduSubmitQ))
1418 txEnt = (PjTxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.txBuf.sduSubmitQ));
1419 datFwdInd->datFwdInfo[count].sduId = txEnt->sduId;
1420 datFwdInd->datFwdInfo[count].sn = txEnt->sn;
1422 datFwdInd->datFwdInfo[count].sdu = txEnt->sdu;
1424 #ifdef FLAT_BUFFER_OPT
1425 if(txEnt->sdu == NULLP)
1427 pjUtlCopyFbToBuf(gCb, &(txEnt->fb), &(datFwdInd->datFwdInfo[count].sdu));
1432 SCpyMsgMsg(txEnt->sdu, 0, 0, &datFwdInd->datFwdInfo[count].sdu);
1435 cmLListNext(&pjRbCb->dlCb.txBuf.sduSubmitQ);
1442 if(NULLP != cmLListCrnt(&pjRbCb->dlCb.dlPktQ))
1444 pkt = (PjDlPkt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.dlPktQ));
1445 datFwdInd->datFwdInfo[count].sduId = pkt->sduId;
1446 datFwdInd->datFwdInfo[count].sn = pkt->sn;
1448 datFwdInd->datFwdInfo[count].sdu = pkt->pdu;
1450 #ifdef FLAT_BUFFER_OPT
1451 if(pkt->pdu == NULLP)
1453 pjUtlCopyFbToBuf(gCb, &(pkt->fb), &(datFwdInd->datFwdInfo[count].sdu));
1458 SCpyMsgMsg(pkt->pdu, 0, 0, &datFwdInd->datFwdInfo[count].sdu);
1462 cmLListNext(&pjRbCb->dlCb.dlPktQ);
1468 datFwdInd->dir = PJ_DIR_DL;
1469 datFwdInd->numSdus = count;
1470 datFwdInd->isLastDatFwdInd = FALSE;
1471 pjUtlDlSndDatFwdInd(gCb,pjRbCb, datFwdInd);
1474 pjuSap = &(gCb->u.dlCb->pjuSap[PJ_DRB_SAP]);
1475 if(SGetSBuf(pjuSap->pst.region,pjuSap->pst.pool,(Data **)&datFwdInd,
1476 sizeof (PjuDatFwdIndInfo)) != ROK)
1479 RLOG0(L_FATAL, "Memory Allocation failed.");
1482 datFwdInd->dir = PJ_DIR_DL;
1483 datFwdInd->numSdus = 0;
1484 datFwdInd->isLastDatFwdInd = TRUE;
1486 /* sending DatFwdInd even if numSdu is zero */
1487 pjUtlDlSndDatFwdInd(gCb,pjRbCb, datFwdInd);
1497 * Handler to process the forwarded data received from upper layer.
1501 * 1. This function is used to process the SDUs received from the upper
1502 * layer as part of handover. @n
1503 * 2. This function calls pjDlmProcessSdus function with the correct
1504 * SN and HFN values. @n
1506 * @param[in] gCb PDCP Instance control block.
1507 * @param[in] pjRbCb Rb control block.
1508 * @param[in] datFwdReq Data Forward Info.
1516 PUBLIC S16 pjDlmHndlDatFwdReq
1520 PjuDatFwdReqInfo *datFwdReq
1523 PUBLIC S16 pjDlmHndlDatFwdReq(gCb,pjRbCb,datFwdReq)
1526 PjuDatFwdReqInfo *datFwdReq;
1530 U32 sduCount; /* Number of received SDUs */
1531 U32 numSdus; /* Counter for SDUs */
1532 //U32 txHfn; /* TX_HFN of a SDU */
1533 PjTxEnt *txEnt; /* Transmission Entity */
1534 #ifdef L2_PDCP_OPTMZ
1535 U8 hashKey; /* Computed HashKey */
1539 TRC3(pjDlmHdlDatFwdReq)
1541 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmHndlDatFwdReq(pjRbCb (),datFwdReq(%d)) ",
1542 datFwdReq->numSdus);
1544 sduCount = datFwdReq->numSdus;
1545 //txHfn = pjRbCb->dlCb.txHfn;
1548 /* FIXME is this required , TC 11.10 */
1549 /* FIXME NOT a proper fix also */
1550 if(pjRbCb->dlCb.txNext == 0)
1552 //pjRbCb->dlCb.nxtTxSn = datFwdReq->datFwdInfo[sduCount - 1].sn;
1553 pjRbCb->dlCb.count = datFwdReq->datFwdInfo[sduCount - 1].sn;
1555 gCb->pjGenSts.numPktsRcvd += sduCount;
1556 /* Process each of the SDUs with received SN and sduId */
1557 for ( numSdus = 0; numSdus < sduCount; numSdus++ )
1560 The variables nxtTxSn and COUNT are assumed to be
1561 already updated in dlCb to continue with the
1562 transmission ( in the target eNodeB ).
1564 PJ_ALLOC(gCb,txEnt, sizeof(PjTxEnt));
1566 #if (ERRCLASS & ERRCLS_ADD_RES)
1569 RLOG0(L_FATAL, "Memory Allocation failed.");
1570 PJ_FREE_BUF(datFwdReq->datFwdInfo[numSdus].sdu);
1573 #endif /* ERRCLASS & ERRCLS_RES */
1576 /* Fill TxEnt values */
1577 txEnt->sn = datFwdReq->datFwdInfo[numSdus].sn;
1578 txEnt->sduId = datFwdReq->datFwdInfo[numSdus].sduId;
1579 txEnt->state = PJ_SDU_RECEIVED;
1580 txEnt->sdu = datFwdReq->datFwdInfo[numSdus].sdu;
1583 #ifndef L2_PDCP_OPTMZ
1584 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
1586 /* Fix for NULL ciphering. For null ciphering add PDUs to sduSubmitQ*/
1587 if(pjRbCb->ueCb->secInfo.secAct && pjRbCb->ueCb->secInfo.cipherInfo.algoType != 0)
1589 txEnt->datCfmEnt.node = NULLP;
1590 txEnt->reEstPktEnt.node = NULLP;
1591 txEnt->sduSubmitEnt.node = (PTR)NULLP;
1593 buf=&(pjRbCb->dlCb.txBuf);
1594 hashKey = (U8)PJ_HASH_FN(buf, txEnt->count); /*KW_FIX*/
1596 txEnt->lstEnt.node = (PTR)txEnt;
1597 cmLListAdd2Tail(&buf->datQ[hashKey], &txEnt->lstEnt);
1600 /* Dont add PDUs to datCfmQ in case of UM mode*/
1601 if (pjRbCb->mode == PJ_DRB_AM )
1603 txEnt->datCfmEnt.node = (PTR)txEnt;
1604 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.datCfmQ, &txEnt->datCfmEnt);
1607 txEnt->state = PJ_PDU_SUBMITTED;
1611 pjDbmInsTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt);
1614 pjDlmProcDrb(gCb,pjRbCb,txEnt);
1626 * Handler to construct a PDU and send it to the lower layer.
1630 * 1. This function is used to deliver a PDU to the lower layer.@n
1631 * 2. It calls pjDlmBldPdu function and sends the PDU to
1632 * the lower layer using pjDlmSendDatReq function. @n
1633 * 3. The txBuf is freed up if the cfmReqd is not configured or
1634 * if the rbType is UM.@n
1636 * @param[in] pjRbCb PDCP control block.
1637 * @param[in] txEnt Transmission Entity.
1638 * @param[in] mBuf The PDU to be transmitted.
1639 * @param[in] pduType Type of the PDU.
1646 PUBLIC S16 pjDlmDeliverPdu
1653 PUBLIC S16 pjDlmDeliverPdu(gCb,pjRbCb,txEnt)
1659 S16 ret; /* Return Value */
1660 S16 ret1; /* Return Value */
1661 PjTxEnt *txFirstEntity;
1664 TRC3(pjDlmDeliverPdu)
1670 /* Constructs a PDU */
1671 if ( txEnt->state != PJ_PDU_CONSTRUCTED )
1673 ret = pjDlmBldPdu(gCb, pjRbCb, txEnt);
1678 RLOG_ARG2(L_ERROR, DBG_RBID, pjRbCb->rbId, "PDCP DL Build PDU Failed SN [%u] , Count [%lu]",
1679 txEnt->sn, txEnt->count);
1680 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
1681 if ( pjRbCb->dlCb.cfmReqd)
1683 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJ_PDU_CONSTRUCT_FAILED);
1687 txEnt->state = PJ_PDU_CONSTRUCTED;
1689 /* Deliver the PDU to the lower layer only if it is nxtToSub.
1690 * Also deliver the consecutive PDUs if they are constructed.
1691 * If not just store the PDU.
1693 cmLListFirst(&pjRbCb->dlCb.txBuf.sduSubmitQ);
1695 while (cmLListCrnt(&pjRbCb->dlCb.txBuf.sduSubmitQ))
1697 txFirstEntity = (PjTxEnt *) cmLListNode(cmLListCrnt(&pjRbCb->dlCb.txBuf.sduSubmitQ));
1698 if (txFirstEntity->state == PJ_PDU_CONSTRUCTED )
1701 pjDlmSendDatReq(gCb, pjRbCb, txFirstEntity->count,
1702 txFirstEntity->pdu);
1703 gCb->pjGenSts.txPdus++;
1704 txFirstEntity->pdu = NULLP;
1705 txFirstEntity->state = PJ_PDU_SUBMITTED;
1707 txFirstEntity->sduSubmitEnt.node = (PTR)NULLP;
1708 cmLListDelFrm(&pjRbCb->dlCb.txBuf.sduSubmitQ, &txFirstEntity->sduSubmitEnt);
1710 if ((pjRbCb->mode == PJ_DRB_UM )
1711 || (!(pjRbCb->dlCb.cfmReqd) && pjRbCb->rbType == PJ_SRB)
1714 pjDbmDelTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txFirstEntity->count);
1718 /* Add to the DatCfm Q */
1719 txFirstEntity->datCfmEnt.node = (PTR)txEnt;
1720 cmLListAdd2Tail(&pjRbCb->dlCb.txBuf.datCfmQ, &txFirstEntity->datCfmEnt);
1721 pjTotDlPckCntPerCell++;
1723 cmLListFirst(&pjRbCb->dlCb.txBuf.sduSubmitQ);
1737 * Handler to construct a process a SRB SDU.
1741 * 1. This function performs integrity protection if it is
1743 * 2. The first DL message of SRBs is not ciphered and is just integrity
1745 * 3. This function checks the UE CB control block to check the flag for the
1746 * first DL message and performs only integrity protection and unsets
1748 * 4. Ciphering is performed if applicable.
1749 * 5. The PDU is constructed and then delivered to the lower
1752 * @param[in] pjRbCb PDCP control block.
1753 * @param[in] txEnt Transmission Entity.
1763 PUBLIC S16 pjDlmProcSrb
1770 PUBLIC S16 pjDlmProcSrb(gCb, pjRbCb, txEnt)
1776 S16 ret; /* Return Value */
1777 U32 macI; /* MAC-I value to be padded to the PDU */
1778 Buffer *pdu; /* Pointer for the PDU in txEnt */
1782 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmProcSrb(pjRbCb (), txEnt(%ld)) ",
1785 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmProcSrb(pjRbCb (), txEnt(%d)) ",
1794 /* Perform security operation only if configured */
1795 if ( pjRbCb->ueCb->secInfo.secAct && pjRbCb->ueCb->secInfo.intInfo.algoType != 0)
1797 /* Perform integrity/ciphering */
1798 ret = pjDlmHdlIntProt(gCb, pjRbCb, txEnt);
1801 RLOG_ARG2(L_ERROR, DBG_RBID, pjRbCb->rbId, "Integrity Prot failed SN [%u] TXNEXT [%lu]", txEnt->sn, txEnt->count);
1806 /* If security is not configured, pad the PDU with 4 bytes
1807 * and deliver to the lower layer
1809 PJ_PACK_MACI(pdu, macI);
1810 ret = pjDlmHdlCiph(gCb, pjRbCb, txEnt);
1811 /* ret = pjDlmDeliverPdu(gCb, pjRbCb, txEnt);*/
1822 * Handler to construct a process a DRB SDU.
1826 * 1. This function performs header compression if it is
1828 * 2. If security is configured, ciphering is performed. @n
1829 * 3. The PDU is constructed and then delivered to the lower
1832 * @param[in] pjRbCb PDCP control block.
1833 * @param[in] txEnt Transmission Entity.
1842 PUBLIC S16 pjDlmProcDrb
1849 PUBLIC S16 pjDlmProcDrb(gCb,pjRbCb,txEnt)
1857 RLOG_ARG1(L_UNUSED,DBG_RBID,pjRbCb->rbId,
1858 "pjDlmProcDrb(pjRbCb (), txEnt(%ld)) ", txEnt->count);
1860 RLOG_ARG1(L_UNUSED,DBG_RBID,pjRbCb->rbId,
1861 "pjDlmProcDrb(pjRbCb (), txEnt(%d)) ", txEnt->count);
1864 RETVALUE(pjDlmHdlCmp(gCb, pjRbCb, txEnt));
1871 * Handler to process the Integrity Protection Request
1875 * 1. This function performs integrity protection
1876 * of a SDU by prepending the header. @n
1877 * 2. If ciphering is applicable, it is performed after removing
1879 * 3. The PDU is constructed and then delivered to the lower
1882 * @param[in] pjRbCb PDCP control block.
1883 * @param[in] txEnt Transmission Entity.
1892 PUBLIC S16 pjDlmHdlIntProt
1899 PUBLIC S16 pjDlmHdlIntProt(gCb,pjRbCb,txEnt)
1905 S16 ret; /* Return Value */
1906 U32 hdr; /* Header Value */
1907 #ifndef TENB_AS_SECURITY
1908 U32 macI = 0; /* MAC-I value to be padded to the PDU */
1910 Buffer *pdu = NULLP; /* Pointer for the PDU in txEnt */
1911 PjSecInp secInp; /* Security Input for Ciphering and Int Prot */
1913 TRC3(pjDlmHdlIntProt)
1915 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId,
1916 "pjDlmHdlIntProt(pjRbCb (), txEnt (%ld)) ", txEnt->count);
1918 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId,
1919 "pjDlmHdlIntProt(pjRbCb (), txEnt (%d)) ", txEnt->count);
1927 /* If firstDL msg after secCfg, unset the ueCb flag ans set
1928 * rbCb flag and set the SN
1930 if (pjRbCb->ueCb->secInfo.selSecAct == TRUE &&
1931 pjRbCb->ueCb->secInfo.firstMsg == TRUE )
1933 pjRbCb->firstDlMsg = TRUE;
1934 pjRbCb->firstSn = txEnt->sn;
1935 pjRbCb->ueCb->secInfo.firstMsg = FALSE;
1937 secInp.dir = PJ_SEC_DIR_DL;
1938 secInp.rbId = pjRbCb->rbId;
1939 secInp.count= txEnt->count;
1941 /* Add the header and then send it for Integrity Protection */
1943 PJ_ADD_PRE_MSG(pdu, hdr, 2, ret);
1944 #ifndef TENB_T2K3K_SPECIFIC_CHANGES
1948 #if (ERRCLASS & ERRCLS_ADD_RES)
1951 RLOG1(L_ERROR, "SAddPreMsg failed Tx Count[%lu]", txEnt->count);
1952 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
1953 if ( pjRbCb->dlCb.cfmReqd)
1955 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJ_REM_MSG_FAILED);
1961 txEnt->state = PJ_WAIT_FOR_INTPROT;
1962 ret = pjUtlIntProtReq(gCb, pjRbCb, secInp, &pdu);
1967 RLOG1(L_ERROR, "Integrity Protection Req failed Tx Count[%lu]", txEnt->count);
1968 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
1969 if ( pjRbCb->dlCb.cfmReqd)
1971 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJU_INTPROT_FAILED);
1973 gCb->pjGenSts.numIntgPrtFails++;
1977 if (pjRbCb->ueCb->secInfo.intInfo.algoType == 0)
1980 #ifndef PJ_SEC_ASYNC
1981 /* Append the macI at the end */
1982 #ifdef TENB_AS_SECURITY
1983 /*PJ_PACK_MACI(pdu, macI);*/
1985 PJ_PACK_MACI(pdu, macI);
1989 #ifndef TENB_T2K3K_SPECIFIC_CHANGES
1991 // prc_trace_format_string(0x40,3,"[%ld] ",macI);
1996 /* Remove the header and then only send for ciphering */
1997 ret = SRemPreMsg((Data *)&hdr, txEnt->pdu);
1998 #if (ERRCLASS & ERRCLS_ADD_RES)
2001 RLOG1(L_ERROR, "SRemPreMsg failed Tx Count [%lu]", txEnt->count);
2002 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2003 if ( pjRbCb->dlCb.cfmReqd)
2005 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJ_REM_MSG_FAILED);
2009 #endif /* ERRCLASS & ERRCLS_RES */
2010 ret = SRemPreMsg((Data *)&hdr, txEnt->pdu);
2011 #if (ERRCLASS & ERRCLS_ADD_RES)
2014 RLOG1(L_ERROR, "SRemPreMsg failed Tx Count [%lu]", txEnt->count);
2015 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2016 if ( pjRbCb->dlCb.cfmReqd)
2018 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJ_REM_MSG_FAILED);
2022 #endif /* ERRCLASS & ERRCLS_RES */
2024 /* If rbCb flag is set => firstDL msg. So skip ciphering */
2025 if ( pjRbCb->firstDlMsg == TRUE && pjRbCb->firstSn == txEnt->sn)
2027 pjRbCb->firstDlMsg = FALSE;
2029 PJ_FREE_BUF(txEnt->sdu);
2032 ret = pjDlmDeliverPdu(gCb, pjRbCb, txEnt);
2036 ret = pjDlmHdlCiph(gCb, pjRbCb, txEnt);
2048 * Handler to process NULL Ciphering.
2051 * This function handles the PDU for NULL ciphering.
2053 * @param[in] gCb Global control block.
2054 * @param[in] pjRbCb RB control block.
2055 * @param[in] txEnt Transmission Entity.
2062 PUBLIC S16 pjDlmHdlNullCiph
2069 PUBLIC S16 pjDlmHdlNullCiph(gCb,pjRbCb,txEnt)
2075 S16 ret; /* Return Value */
2077 TRC3(pjDlmHdlNullCiph);
2081 /* If Ciphering is enabled, txEnt->pdu will point to a mBuf */
2082 #ifdef FLAT_BUFFER_OPT
2083 if(txEnt->sdu == NULLP)
2085 ret = pjUtlCopyFbToBuf(gCb, &(txEnt->fb), &(txEnt->pdu));
2088 RLOG1(L_ERROR, "Cpoying to Flat Buf Failed Tx Count [%lu]", txEnt->count);
2089 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2090 if ( pjRbCb->dlCb.cfmReqd)
2092 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJ_CPY_MSG_FAILED);
2099 if (txEnt->pdu == NULLP )
2101 if ( pjRbCb->mode == PJ_DRB_AM
2102 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
2103 || pjRbCb->mode == PJ_DRB_UM
2107 PJ_CPY_MSG(gCb,txEnt->sdu, &(txEnt->pdu), ret);
2108 #if (ERRCLASS & ERRCLS_ADD_RES)
2111 RLOG1(L_ERROR, "SAddMsgRef Failed Tx Count [%lu]", txEnt->count);
2113 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2114 if ( pjRbCb->dlCb.cfmReqd)
2116 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJ_CPY_MSG_FAILED);
2124 txEnt->pdu = txEnt->sdu;
2136 * Handler to process the Compression Request.
2140 * 1. This function performs header compression if configured. @n
2141 * 2. If ciphering is applicable, it is performed. @n
2142 * 3. The PDU is constructed and then delivered to the lower
2145 * @param[in] pjRbCb PDCP control block.
2146 * @param[in] txEnt Transmission Entity.
2156 PUBLIC S16 pjDlmHdlCmp
2163 PUBLIC S16 pjDlmHdlCmp(gCb,pjRbCb,txEnt)
2169 S16 ret; /* Return Value */
2170 Buffer *opSdu; /* Pointer for Output of Compression */
2171 U32 macI; /* MAC-I value to be padded to the PDU */
2174 RLOG_ARG1(L_UNUSED,DBG_RBID,pjRbCb->rbId, "pjDlmHdlCmp(pjRbCb (), txEnt (%ld)) ",
2177 RLOG_ARG1(L_UNUSED,DBG_RBID,pjRbCb->rbId, "pjDlmHdlCmp(pjRbCb (), txEnt (%d)) ",
2184 /* Perform compression if ocnfigured */
2185 if ( pjRbCb->rohc.hdrCmpUsed )
2187 txEnt->pdu = txEnt->sdu;
2188 txEnt->state = PJ_WAIT_FOR_CMP;
2189 ret = pjUtlCmpReq(gCb, pjRbCb, txEnt->pdu, &opSdu, txEnt->count);
2193 RLOG1(L_ERROR, "Compression Req Failed Tx Count [%lu]", txEnt->count);
2194 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2195 if ( pjRbCb->dlCb.cfmReqd)
2197 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJU_COMP_FAILED);
2199 gCb->pjGenSts.numCmpFails++;
2208 if(pjRbCb->ueCb->secInfo.intProtEnbForDrb)
2211 PJ_PACK_MACI(txEnt->sdu, macI);
2213 /* Perform ciphering if security is configured */
2214 ret = pjDlmHdlCiph(gCb, pjRbCb, txEnt);
2220 * @brief This fn cheks whether the RING buffer is used and therefore DL pkts
2221 * need to be enqueued before forwarding it for ciphering.
2222 * Note: It acts as a dummy fn so far in case of Mindspeed pltfm
2225 * Function : pjUtlChekTxEnqReq
2232 * -# Failure : RFAILED
2235 PUBLIC S16 pjUtlChekTxEnqReq
2242 PUBLIC S16 pjUtlChekTxEnqReq(gCb,pjRbCb, txEnt)
2255 * Handler to process the Ciphering Request.
2259 * 1. This function performs ciphering. @n
2260 * 2. If asynchronous flag is defined, the function returns . @n
2261 * 3. Else the function updates the PDU field in txEnt and returns. @n
2263 * @param[in] pjRbCb PDCP control block.
2264 * @param[in] txEnt Transmission Entity.
2272 PUBLIC S16 pjDlmHdlCiph
2279 PUBLIC S16 pjDlmHdlCiph(gCb,pjRbCb,txEnt)
2285 S16 ret; /* Return Value */
2286 Buffer *ciphSdu; /* Pointer for Output of Ciphering */
2292 pjUtlChekTxEnqReq(gCb, pjRbCb, txEnt);
2299 RLOG_ARG1(L_UNUSED,DBG_RBID,pjRbCb->rbId, "pjDlmHdlCiph(pjRbCb (), txEnt (%ld)) ",
2302 RLOG_ARG1(L_UNUSED,DBG_RBID,pjRbCb->rbId, "pjDlmHdlCiph(pjRbCb (), txEnt (%d)) ",
2307 #ifndef L2_PDCP_OPTMZ
2308 txEnt->state = PJ_WAIT_FOR_CIPHER;
2312 secInfo = &(pjRbCb->ueCb->secInfo);
2314 if ( secInfo->secAct && secInfo->cipherInfo.algoType != 0) /* If its not NULL Ciphering and Security is enabled */
2316 if ( txEnt->pdu == NULLP )
2318 txEnt->pdu = txEnt->sdu;
2320 /* Note: FB is only for DRB data in DL direction. SRB data after */
2321 /* integrity protection will use the NON-FB version of code. */
2322 /* The below "if" check is to identify whether it is for SRB data */
2324 #ifdef CIPH_BATCH_PROC
2326 pjUtlChekTxEnqReq(gCb, pjRbCb, txEnt);
2331 #ifdef FLAT_BUFFER_OPT
2332 if (txEnt->sdu == NULLP)
2334 ret = pjUtlCipherReqFB(gCb, pjRbCb, txEnt->count, &(txEnt->fb), &ciphSdu);
2339 ret = pjUtlCipherReq(gCb, pjRbCb, txEnt->count, txEnt->pdu, &ciphSdu);
2342 /*There can be failures in creating the input for SPACC*/
2345 RLOG1(L_ERROR, "Ciphering Req failed Tx Count [%lu]", txEnt->count);
2346 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2347 if ( pjRbCb->dlCb.cfmReqd)
2349 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJU_CIPHER_FAILED);
2351 gCb->pjGenSts.numCiphFails++;
2357 //printf("Ciphered PDU\n");
2358 //SPrntMsg(ciphSdu,0,0);
2361 PJ_FREE_BUF(txEnt->pdu);
2363 txEnt->pdu = ciphSdu;
2367 PJLOGERROR(gCb, ERRCLS_ADD_RES, EPJXXX, (ErrVal)sduId,
2368 "pjSendToSwCipherFB:Ciphering failed for txEnt\n");
2369 pjDbmDelTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt->count);
2374 #ifdef TENB_AS_SECURITY
2377 txEnt->state = PJ_PDU_SUBMITTED;
2378 #ifdef L2_PDCP_OPTMZ
2379 /* Delete Tx entity in case of UM mode*/
2380 if (pjRbCb->mode == PJ_DRB_UM )
2382 pjDbmDelTxEnt(gCb, &(pjRbCb->dlCb.txBuf), txEnt->count);
2390 txEnt->pdu = ciphSdu;
2396 #ifdef L2_PDCP_OPTMZ
2397 txEnt->state = PJ_WAIT_FOR_CIPHER;
2403 ret = pjDlmHdlNullCiph(gCb, pjRbCb, txEnt);
2406 txEnt->state = PJ_PDU_SUBMITTED;
2407 ret = pjDlmDeliverPdu(gCb, pjRbCb, txEnt);
2413 #ifdef FLAT_BUFFER_OPT
2418 * Handler to process the Ciphering Request.
2422 * 1. This function performs ciphering. @n
2423 * 2. If asynchronous flag is defined, the function returns . @n
2424 * 3. Else the function updates the PDU field in txEnt and returns. @n
2426 * @param[in] pjRbCb PDCP control block.
2427 * @param[in] txEnt Transmission Entity.
2436 PUBLIC S16 pjDlmHdlCiphFB
2443 PUBLIC S16 pjDlmHdlCiphFB(gCb,pjRbCb,txEnt)
2449 S16 ret; /* Return Value */
2450 Buffer *ciphSdu; /* Pointer for Output of Ciphering */
2452 TRC3(pjDlmHdlCiphFB)
2454 PJDBGP(gCb,(PJ_DBGMASK_DLM | PJ_DBGMASK_BRIEF | PJ_DBGMASK_DL),
2455 (gCb->init.prntBuf, "pjDlmHdlCiphFB(pjRbCb (%d), txEnt (%ld)) \n",
2456 pjRbCb->rbId, txEnt->count));
2458 PJDBGP(gCb,(PJ_DBGMASK_DLM | PJ_DBGMASK_BRIEF | PJ_DBGMASK_DL),
2459 (gCb->init.prntBuf, "pjDlmHdlCiphFB(pjRbCb (%d), txEnt (%d)) \n",
2460 pjRbCb->rbId, txEnt->count));
2465 txEnt->state = PJ_WAIT_FOR_CIPHER;
2466 ret = pjUtlCipherReqFB(gCb, pjRbCb, txEnt->count, &(txEnt->fb), &ciphSdu);
2468 /*There can be failures in creating the input for SPACC*/
2471 RLOG1(L_ERROR, "Ciphering Req failed Tx Count [%lu]", txEnt->count);
2472 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2473 if ( pjRbCb->dlCb.cfmReqd)
2475 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJU_CIPHER_FAILED);
2477 gCb->pjGenSts.numCiphFails++;
2482 txEnt->state = PJ_PDU_SUBMITTED;
2494 * @param[in] pjRbCb PDCP control block.
2495 @param[in] PjRxEnt *rxEnt
2501 PUBLIC Void pjDlmEnqueueDlPkt
2504 PjDlRbCb *pjRbCb, /* !< PDCP Control Block */
2506 PjuDatFwdReqInfo *datFwd, /* !< SN value of PDU */
2508 Buffer *pdu /* !< PDU message buffer */
2511 PUBLIC Void pjDlmEnqueueDlPkt(gCb,pjRbCb,datType,datFwd,suId,pdu)
2513 PjDlRbCb *pjRbCb; /* !< PDCP Control Block */
2515 PjuDatFwdReqInfo *datFwd; /* !< SN value of PDU */
2517 Buffer *pdu; /* !< PDU message buffer */
2523 TRC2(pjDlmEnqueueDlPkt)
2525 if (datType == PJ_DATA_FWD_PKT)
2527 for (numSdu=0; numSdu < datFwd->numSdus; numSdu++)
2529 PJ_ALLOC(gCb, pkt, sizeof(PjDlPkt));
2532 pkt->type = datType;
2533 pkt->sn = datFwd->datFwdInfo[numSdu].sn;
2534 pkt->sduId = datFwd->datFwdInfo[numSdu].sduId;
2535 pkt->pdu = datFwd->datFwdInfo[numSdu].sdu;
2536 pkt->lnk.node = (PTR)pkt;
2537 cmLListAdd2Tail (&pjRbCb->dlCb.dlPktQ, &pkt->lnk);
2543 PJ_ALLOC(gCb, pkt, sizeof(PjDlPkt));
2546 pkt->type = datType;
2549 pkt->lnk.node = (PTR)pkt;
2550 cmLListAdd2Tail (&pjRbCb->dlCb.dlPktQ, &pkt->lnk);
2554 RLOG0(L_FATAL, "Memory Allocation failed.");
2560 }/* end of pjDlmEnqueueHoPkt */
2562 #ifdef FLAT_BUFFER_OPT
2567 * @param[in] pjRbCb PDCP control block.
2568 @param[in] PjRxEnt *rxEnt
2573 PUBLIC Void pjDlmEnqueueDlPktFB
2576 PjDlRbCb *pjRbCb, /* !< PDCP Control Block */
2578 PjuDatFwdReqInfo *datFwd, /* !< SN value of PDU */
2580 FlatBuffer *pdu /* !< Flat Buffer PDU */
2583 PUBLIC Void pjDlmEnqueueDlPktFB(gCb,pjRbCb,datType,datFwd,suId,pdu)
2585 PjDlRbCb *pjRbCb; /* !< PDCP Control Block */
2587 PjuDatFwdReqInfo *datFwd; /* !< SN value of PDU */
2589 FlatBuffer *pdu; /* !< Flat Buffer PDU */
2594 TRC2(pjDlmEnqueueDlPktFB)
2596 if (datType == PJ_DATA_FWD_PKT)
2598 /* printf("pjDlmEnqueueDlPktFB: datType = PJ_DATA_FWD_PKT. TODO !!!!! "); */
2602 PJ_ALLOC(gCb, pkt, sizeof(PjDlPkt));
2605 pkt->type = datType;
2606 pkt->fb.startAddr = pdu->startAddr;
2607 pkt->fb.ptr = pdu->ptr;
2608 pkt->fb.len = pdu->len;
2611 pkt->lnk.node = (PTR)pkt;
2612 cmLListAdd2Tail (&pjRbCb->dlCb.dlPktQ, &pkt->lnk);
2613 /*printf("pjDlmEnqueueDlPktFB: Enqueue DL Flat Buffer Packets. Sdu Id is %d ",
2618 RLOG0(L_FATAL, "Memory Allocation failed.");
2619 PJ_FREE_FLAT_BUF(gCb, pdu);
2624 }/* end of pjDlmEnqueueDlPktFB */
2629 * @brief It processes the packets queued up in DLPktQ
2632 * This DlPktQ queues the Normal and forwarded message during
2633 * reestablishment/handover.
2635 * @param[in] pjCb PDCP Instance control block.
2636 * @param[in] pjRbCb Rb Control block
2641 PUBLIC Void pjDlmProcessDlPktQ
2644 PjDlRbCb *pjRbCb /* !< PDCP Control Block */
2647 PUBLIC Void pjDlmProcessDlPktQ(gCb, pjRbCb)
2649 PjDlRbCb *pjRbCb; /* !< PDCP Control Block */
2656 TRC2(pjDlmProcessDlPktQ)
2658 /* first send the status report if any enqueued */
2660 if (pjRbCb->dlCb.staRep != NULL)
2662 pjDlmSendDatReq(gCb, pjRbCb, 0xffffffff, pjRbCb->dlCb.staRep);
2663 pjRbCb->dlCb.staRep = NULL;
2666 CM_LLIST_FIRST_NODE(&(pjRbCb->dlCb.dlPktQ), node);
2667 while (node != NULLP)
2669 pkt = (PjDlPkt *) node->node;
2670 if (pkt->type == PJ_DATA_FWD_PKT)
2672 PjuDatFwdReqInfo datFwdReq;
2673 PjuDatFwdInfo datFwd;
2674 datFwdReq.numSdus = 1;
2675 datFwd.sn = pkt->sn;
2676 datFwd.sdu = pkt->pdu;
2677 datFwd.sduId = pkt->sduId;
2678 datFwdReq.datFwdInfo = &datFwd;
2679 pjDlmHndlDatFwdReq(gCb, pjRbCb, &datFwdReq);
2685 #ifdef FLAT_BUFFER_OPT
2686 #ifndef XEON_SPECIFIC_CHANGES
2688 /* Check whether the spacc q has space to hold
2689 this packet.. else dropping */
2690 if(FALSE == (pjMsCheckSpaccQueue(FALSE)))
2692 PJ_FREE_FLAT_BUF(pjCb[1],&(pkt->fb));
2693 gPdcpStats.numPdcpSdusDiscarded++;
2694 PJ_UPD_L2_DLDISC_STS(pjCb[1], pjRbCb);
2696 cmLListDelFrm(&(pjRbCb->dlCb.dlPktQ), node);
2697 PJ_FREE(gCb, pkt, sizeof (PjDlPkt));
2699 CM_LLIST_FIRST_NODE(&(pjRbCb->dlCb.dlPktQ), node);
2704 if((pkt->fb.len !=0) && (pkt->fb.ptr != NULLP))
2706 ret = pjDlmProcessSdusFB(gCb, pjRbCb, &(pkt->fb), pkt->sduId, pjRbCb->dlCb.txNext);
2711 ret = pjDlmProcessSdus(gCb, pjRbCb, pkt->pdu, pkt->sduId, pjRbCb->dlCb.txNext);
2715 #if (ERRCLASS & ERRCLS_INT_PAR)
2716 RLOG_ARG1(L_ERROR, DBG_RBID, pjRbCb->rbId, "Processing of SDU [%lu] failed", pkt->sduId);
2717 #endif /* ERRCLASS & ERRCLS_INT_PAR */
2721 cmLListDelFrm(&(pjRbCb->dlCb.dlPktQ), node);
2722 PJ_FREE(gCb, pkt, sizeof (PjDlPkt));
2724 CM_LLIST_FIRST_NODE(&(pjRbCb->dlCb.dlPktQ), node);
2728 }/* end of pjDlmProcessDlPktQ */
2733 #if (defined(PJ_SEC_ASYNC) || defined(PJ_CMP_ASYNC))
2736 * @brief Handler for downlink off-board timer expiry.
2740 * This function is called when the off-board timer expires.
2741 * This function discards the txEnt of dlCb.obdCount if it is
2742 * is not submitted and sends the constructed PDUs to the lower
2743 * layer and start the timer for the next valid txEnt.
2745 * @param[in] pjRbCb PDCP control block.
2752 PUBLIC S16 pjDlmObdTmrExp
2758 PUBLIC S16 pjDlmObdTmrExp(gCb, pjRbCb)
2766 PjuDatCfmInfo *datCfm;
2769 TRC3(pjDlmObdTmrExp)
2771 RLOG_ARG0(L_DEBUG,DBG_RBID,pjRbCb->rbId, "pjDlmObdTmrExp(pjRbCb()) ");
2773 count = pjRbCb->dlCb.obdCount;
2774 curCount = pjRbCb->dlCb.count;
2775 txEnt = pjDbmGetTxEnt(gCb, &(pjRbCb->dlCb.txBuf), count);
2779 if ( txEnt && txEnt->state != PJ_PDU_SUBMITTED )
2782 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId,
2783 "pjDlmObdTmrExp(pjRbCb()) : discarding txEnt withcount(%ld)",
2786 RLOG_ARG1(L_DEBUG,DBG_RBID,pjRbCb->rbId,
2787 "pjDlmObdTmrExp(pjRbCb()) : discarding txEnt withcount(%d)",
2790 PJ_UPD_DL_VAR(gCb, pjRbCb, txEnt->count);
2791 PJ_SND_CFM(gCb,pjRbCb, txEnt, PJ_OBD_TIMEOUT);
2792 gCb->pjGenSts.numSdusDiscObdTmrExp++;
2794 while ( count <= curCount )
2796 txEnt = pjDbmGetTxEnt(gCb, &(pjRbCb->dlCb.txBuf), count);
2797 if ( txEnt != NULLP )
2799 if ( txEnt->state == PJ_PDU_CONSTRUCTED )
2801 ret = pjDlmDeliverPdu(gCb, pjRbCb, txEnt);
2802 count = pjRbCb->dlCb.nxtToSub;
2808 PJ_UPD_DL_VAR(gCb, pjRbCb, count);
2815 count = pjRbCb->dlCb.nxtToSub;
2817 if ( pjDbmGetTxEnt(gCb, &(pjRbCb->dlCb.txBuf), count) != NULLP )
2819 pjRbCb->dlCb.obdCount = count;
2820 pjStartTmr(gCb, (PTR)pjRbCb, PJ_EVT_DL_OBD_TMR);
2829 /********************************************************************30**
2831 **********************************************************************/