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 RLC Utility Module
26 This file contains following functions
36 **********************************************************************/
37 static const char* RLOG_MODULE_NAME="UTL";
38 static int RLOG_MODULE_ID=2048;
39 static int RLOG_FILE_ID=210;
42 @brief RLC Utility Module
45 /* header (.h) include files */
46 #include "envopt.h" /* environment options */
47 #include "envdep.h" /* environment dependent */
48 #include "envind.h" /* environment independent */
49 /* kw005.201 added support for L2 Measurement */
54 #include "gen.h" /* general */
55 #include "ssi.h" /* system services */
56 #include "cm5.h" /* common timer defines */
57 #include "cm_tkns.h" /* common tokens defines */
58 #include "cm_mblk.h" /* common memory allocation library defines */
59 #include "cm_llist.h" /* common link list defines */
60 #include "cm_hash.h" /* common hash list defines */
61 #include "cm_lte.h" /* common LTE defines */
62 #include "ckw.h" /* CKW defines */
63 #include "kwu.h" /* KWU defines */
64 #include "lkw.h" /* LKW defines */
65 #include "rgu.h" /* RGU defines */
67 #include "kw_env.h" /* RLC environment options */
68 #include "kw.h" /* RLC defines */
69 #include "kw_err.h" /* Error defines */
70 #include "kw_ul.h" /* RLC Uplink defines */
72 /* extern (.x) include files */
73 #include "gen.x" /* general */
74 #include "ssi.x" /* system services */
76 #include "cm5.x" /* common timer library */
77 #include "cm_tkns.x" /* common tokens */
78 #include "cm_mblk.x" /* common memory allocation */
79 #include "cm_llist.x" /* common link list */
80 #include "cm_hash.x" /* common hash list */
81 #include "cm_lte.x" /* common LTE includes */
82 #include "cm_lib.x" /* common memory allocation library */
83 #include "ckw.x" /* CKW includes */
84 #include "kwu.x" /* KWU includes */
85 #include "lkw.x" /* LKW includes */
86 #include "rgu.x" /* RGU includes */
88 #include "kw.x" /* RLC inlcudes */
89 #include "kw_ul.x" /* RLC uplink includes */
93 PUBLIC S16 SMrkUlPkt(Buffer *mbuf);
95 PUBLIC KwAmRecBuf* kwUtlGetRecBuf(CmLListCp *recBufLst, KwSn sn);
96 #define KW_MODULE (KW_DBGMASK_DUT | KW_DBGMASK_UL) /* for debugging purpose */
102 * Handler for receiving data for multiple logical channels from MAC.
105 * This function receives the data sent by MAC for one or more
106 * logical channels.It calls the UMM or AMM functions to process
107 * the PDUs and send them to the uppper layer.
109 * @param[in] gCb - RLC instance control block
110 * @param[in] datIndInfo - Data Indication Information containing the PDU(s)
111 * for one or more logical channels
119 PUBLIC S16 kwUtlRcvFrmLi
122 KwDatIndInfo *datIndInfo
125 PUBLIC S16 kwUtlRcvFrmLi(gCb,datIndInfo)
127 KwDatIndInfo *datIndInfo;
130 U32 count; /* Loop Counter */
131 KwPduInfo *pduInfo; /* PDU Information */
132 KwUlRbCb *rbCb; /* RB Control Block */
133 KwUlUeCb *ueCb; /* UE Control Block */
134 /* kw005.201 added support for L2 Measurement */
142 if( ROK != kwDbmFetchUlUeCb(gCb,datIndInfo->rnti,datIndInfo->cellId,&(ueCb)))
144 /* Fetch UeCb failed */
145 RLOG_ARG1(L_ERROR,DBG_CELLID,datIndInfo->cellId,
146 "UEID:%d UeCb not found",
148 /* free the buffers inside the datIndInfo */
150 for(i = 0; i< datIndInfo->numLch; i++)
152 for(j = 0; j < datIndInfo->lchData[i].pdu.numPdu; j++)
154 if(datIndInfo->lchData[i].pdu.mBuf[j])
156 KW_FREE_BUF_WC(datIndInfo->lchData[i].pdu.mBuf[j]);
166 if (RGU_L2M_UL_BURST_START == datIndInfo->burstInd)
168 ueCb->isUlBurstActive = TRUE;
172 ueCb->firstPacketTTI = 0;
173 ueCb->isUlBurstActive = FALSE;
176 for ( count = 0;count < datIndInfo->numLch; count++ )
178 rbCb = ueCb->lCh[datIndInfo->lchData[count].lcId - 1].ulRbCb;
179 /* kw002.201 Removed allocation of pduInfo */
180 pduInfo = &(datIndInfo->lchData[count].pdu);
181 /* Fix for CR ccpu00138374,sometimes rbCb is NULL in UL path,
182 * So inorder to avoid the crash, added this preventive check
187 for(j = 0; j < pduInfo->numPdu; j++)
191 KW_FREE_BUF_WC(pduInfo->mBuf[j]);
198 SMrkUlPkt(pduInfo->mBuf[0]);
200 if ( rbCb->mode == CM_LTE_MODE_UM )
202 /* kw005.201 added support for L2 Measurement */
204 kwUmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
206 kwUmmProcessPdus(gCb,rbCb,pduInfo);
209 else if (rbCb->mode == CM_LTE_MODE_AM )
211 /* kw005.201 added support for L2 Measurement */
213 kwAmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
215 kwAmmProcessPdus(gCb,rbCb,pduInfo);
225 * Handler for sending Data Indication to the upper layer.
228 * This function is used to send re-assembled SDU to the upper layer.
230 * @param[in] gCb - RLC instance Control Block
231 * @param[in] rbCb - RB Control Block
232 * @param[in] sdu - SDU to be sent to upper layer
238 PUBLIC S16 kwUtlSndDatInd
245 PUBLIC S16 kwUtlSndDatInd(gCb,rbCb,sdu)
252 KwKwuSapCb *kwKwSap; /* KWU SAP Information */
253 KwuDatIndInfo *datIndInfo; /* Data Indication Information */
254 KwuDatIndInfo datIndInfoTmp;
261 kwKwSap = gCb->u.ulCb->kwuUlSap + KW_UI_PDCP;
262 /* Creating static memory for KwuDatIndInfo. #else will be
263 * removed once the testing is done on all platforms */
264 datIndInfo = &datIndInfoTmp;
266 #if (ERRCLASS & ERRCLS_ADD_RES )
267 if ( datIndInfo == NULLP )
269 RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId,
270 "Memory allocation failed UEID:%d CELLID:%d",
276 #endif /* ERRCLASS & ERRCLS_ADD_RES */
278 KW_MEM_CPY(&(datIndInfo->rlcId),&(rbCb->rlcId),sizeof(CmLteRlcId));
279 /* Set the "isOutofSeq" flag for each packet
280 * If packets are in-sequence set flag as TRUE else FALSE */
281 datIndInfo->isOutOfSeq = rbCb->m.amUl.isOutOfSeq;
284 /* If trace flag is enabled send the trace indication */
285 if(gCb->init.trc == TRUE)
287 /* Populate the trace params */
288 kwLmmSendTrc(gCb,KWU_EVT_DAT_IND, sdu);
292 KwUiKwuDatInd(&kwKwSap->pst, kwKwSap->suId, datIndInfo, sdu);
295 } /* kwUtlSndDatInd */
298 PRIVATE Void dumpRLCUlRbInformation(KwUlRbCb* ulRbCb)
300 if(ulRbCb->mode == CM_LTE_MODE_UM)
303 U32 pdusInReceptionBuffer = 0;
304 U32 windSz = ulRbCb->m.umUl.umWinSz << 1;
306 for(i = 0; i< windSz; i++)
308 if(ulRbCb->m.umUl.recBuf[i] != NULLP)
310 pdusInReceptionBuffer++;
314 RLOG_ARG3(L_DEBUG,DBG_RBID,ulRbCb->rlcId.rbId,
315 "UM UL UEID:%d CELLID:%d Reception Buffer size = %d",
316 (int)ulRbCb->rlcId.ueId,
317 (int)ulRbCb->rlcId.cellId,
318 (int)pdusInReceptionBuffer);
320 else if(ulRbCb->mode == CM_LTE_MODE_AM)
323 U32 pdusInReceptionBuffer = 0;
325 U32 windSz = KW_AM_GET_WIN_SZ(ulRbCb->m.amUl.snLen) << 1;
327 for(i = 0; i< windSz; i++)
329 KwAmRecBuf *recBuf = kwUtlGetRecBuf(ulRbCb->m.amUl.recBufLst, i);
332 pdusInReceptionBuffer++;
333 totalSegs += (recBuf->segLst.count);
337 RLOG_ARG4(L_DEBUG,DBG_RBID,ulRbCb->rlcId.rbId,
338 "AM UL UEID:%d CELLID:%d Reception Buf size = %d"
340 (int)ulRbCb->rlcId.ueId,
341 (int)ulRbCb->rlcId.cellId,
342 (int)pdusInReceptionBuffer,
347 Void DumpRLCUlDebugInformation(Void)
349 KwCb* ulInst = kwCb[0]; /* TODO : Check whether UL is 0 or 1 */
350 KwUlCb* ulCb = ulInst->u.ulCb;
351 KwUlUeCb *ueCb = NULLP;
353 /* Until no more ueCb is ueLstCp hash list get and delete ueCb */
354 while (ROK == cmHashListGetNext(&ulCb->ueLstCp,
359 for(i = 0; i< KW_MAX_SRB_PER_UE; i++)
361 KwUlRbCb* ulRbCb = ueCb->srbCb[i];
364 dumpRLCUlRbInformation(ulRbCb);
367 for(i = 0; i< KW_MAX_DRB_PER_UE; i++)
369 KwUlRbCb* ulRbCb = ueCb->drbCb[i];
372 dumpRLCUlRbInformation(ulRbCb);
380 * kwUtlFreeUlRbCb() function is split into two functions
381 * - kwAmmFreeUlRbCb() ---> gp_amm_ul.c
382 * - kwUmmFreeUlRbCb() ---> gp_umm_ul.c
383 * and placed in respective files mentioned above
388 /* kw005.201 added support for L2 Measurement */
394 * Handler for initialisation of measurement
396 * @param[in] gCb - RLC instance Control Block
401 S16 kwUtlL2MeasUlInit(KwCb *gCb)
405 gCb->u.ulCb->kwL2Cb.kwNumMeas=0;
406 for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
408 cmMemset((U8 *)&(gCb->u.ulCb->kwL2Cb.kwL2EvtCb[cntr]), 0, sizeof(KwL2MeasEvtCb));
410 gCb->u.ulCb->kwL2Cb.kwL2EvtCb[KW_L2MEAS_UL_IP].measCb.measType = LKW_L2MEAS_UL_IP;
417 * Handler to calculate the Ul Ip throughput for a LCH
422 * @param[in] rbCb RB control block
423 * @param[in] pdu Pdu of LCH
429 PUBLIC Void kwUtlCalUlIpThrPutIncTTI
436 PUBLIC Void kwUtlCalUlIpThrPutIncTTI(gCb, rbCb, ttiCnt)
442 VOLATILE U32 startTime = 0;
443 TRC2(kwUtlCalUlIpThrPutIncTTI)
446 SStartTask(&startTime, PID_RLC_IP_TPT_INCTTI);
448 RLOG_ARG4(L_UNUSED, DBG_RBID,rbCb->rlcId.rbId,"Log for ul ip throughput:"
449 "RB_MeasOn:%d ttiCnt :%ld UEID:%d CELLID:%d",
450 rbCb->rbL2Cb.measOn,ttiCnt,
454 RLOG_ARG4(L_UNUSED,DBG_RBID,rbCb->rlcId.rbId, "Log for ul ip throughput:"
455 "RB_MeasOn:%d ttiCnt :%d UEID:%d CELLID:%d",
456 rbCb->rbL2Cb.measOn,ttiCnt,
461 /*Check if UL IP throughput measurement is ON for this RB or not*/
462 if(KW_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb,rbCb))
464 if (TRUE == rbCb->ueCb->isUlBurstActive)
466 if (ttiCnt < rbCb->l2MeasIpThruput.prevTtiCnt)
468 /*Removed Error Print*/
470 if (rbCb->l2MeasIpThruput.prevTtiCnt != 0)
472 rbCb->rbL2Cb.l2Sts[KW_L2MEAS_UL_IP]->ulIpThruput.timeSummation +=
473 (ttiCnt - rbCb->l2MeasIpThruput.prevTtiCnt);
477 rbCb->ueCb->firstPacketTTI = ttiCnt;
479 rbCb->l2MeasIpThruput.prevTtiCnt = ttiCnt;
483 rbCb->l2MeasIpThruput.prevTtiCnt = 0;
488 SStopTask(startTime, PID_RLC_IP_TPT_INCTTI);
489 } /* kwUtlCalUlIpThrPutIncTTI */
496 * Handler to calculate the Ul Ip throughput for a LCH
501 * @param[in] rbCb RB control block
502 * @param[in] pdu Pdu of LCH
508 PUBLIC Void kwUtlCalUlIpThrPut
516 PUBLIC Void kwUtlCalUlIpThrPut(gCb, rbCb, pdu, ttiCnt)
523 MsgLen rlcSduSz = 0; /*Holds length of Rlc Sdu*/
524 VOLATILE U32 startTime = 0;
525 TRC2(kwUtlCalUlIpThrPut)
529 SStartTask(&startTime, PID_RLC_IP_TPT_INCVOL);
531 /*Check if UL IP throughput measurement is ON for this RB or not*/
532 if(KW_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb, rbCb) &&
533 (TRUE == rbCb->ueCb->isUlBurstActive) &&
534 (rbCb->ueCb->firstPacketTTI) &&
535 (ttiCnt != rbCb->ueCb->firstPacketTTI))
537 SFndLenMsg(pdu, &rlcSduSz);
539 rbCb->rbL2Cb.l2Sts[KW_L2MEAS_UL_IP]->ulIpThruput.volSummation += rlcSduSz;
543 SStopTask(startTime, PID_RLC_IP_TPT_INCVOL);
544 } /* kwUtlCalUlIpThrPut */
549 * @brief Handler for L2 Measurement timer expiry.
553 * This function is called when the l2 measurement timer expires.
554 * This function sends a consolidates the mesaurements taken during
555 * this time and sends the confirm .
557 * @param[in] measEvtCb Measurement Event Control Block.
565 PUBLIC S16 kwUtlHdlL2TmrExp
568 KwL2MeasEvtCb *measEvtCb
571 PUBLIC S16 kwUtlHdlL2TmrExp(measEvtCb)
573 KwL2MeasEvtCb *measEvtCb;
576 TRC3(kwUtlHdlL2TmrExp)
578 #ifdef LTE_L2_MEAS_RLC
582 /* Clean up the RB data structures */
583 if((measEvtCb->measCb.measType & LKW_L2MEAS_ACT_UE) &&
584 (measEvtCb->measCb.val.nonIpThMeas.numSamples))
586 measCb = &measEvtCb->measCb;
588 for(qciIdx = 0; qciIdx < measCb->val.nonIpThMeas.numQci;qciIdx++)
590 measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.numActvUe +=
591 kwCb.kwL2Cb.numActUe[measCb->val.nonIpThMeas.qci[qciIdx]];
592 measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.sampOc++;
594 measEvtCb->val.nonIpThMeas.measCb.numSamples--;
595 kwStartTmr(gCb, (PTR)measEvtCb, KW_EVT_L2_TMR);
600 kwUtlSndUlL2MeasCfm(gCb, measEvtCb);
603 } /* kwUtlHdlL2TmrExp */
606 * @brief Handler for Sending L2 Measurement confirm.
610 * This function sends a consolidates the mesaurements taken during
611 * this time and sends the confirm .
613 * @param[in] measEvtCb Measurement Event Control Block.
621 PUBLIC S16 kwUtlSndUlL2MeasCfm
624 KwL2MeasEvtCb *measEvtCb
627 PUBLIC S16 kwUtlSndUlL2MeasCfm(gCb, measEvtCb)
629 KwL2MeasEvtCb *measEvtCb;
634 KwL2MeasCfmEvt measCfmEvt;
639 /* Discard new changes starts */
642 /* Discard new changes ends */
644 TRC3(kwUtlSndUlL2MeasCfm)
646 /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
648 RLOG1(L_DEBUG,"kwUtlSndUlL2MeasCfm(transId(%ld))", measEvtCb->transId);
650 RLOG1(L_DEBUG,"kwUtlSndUlL2MeasCfm(transId(%d))", measEvtCb->transId);
653 /* Clean up the RB data structures */
654 measCb = &measEvtCb->measCb;
656 cmMemset((U8*)&measCfmEvt, 0, sizeof(KwL2MeasCfmEvt));
657 measCfmEvt.transId = measEvtCb->transId;
659 measCfmEvt.measType = measCb->measType;
660 measCfmEvt.status.status = LCM_PRIM_OK;
661 measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
663 if( measCb->measType & LKW_L2MEAS_UL_IP)
665 KwL2MeasCbUeMeasInfo *pUeInfoLstCb = measCb->val.ipThMeas.ueInfoLst;
666 KwL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
667 for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)
669 pUeInfoLstCfm[cfmIdx].numCfm = 0;
670 if (pUeInfoLstCb[cntr].isValid == TRUE)
672 pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
673 pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
675 for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
677 qci = pUeInfoLstCb[cntr].qci[qciIdx];
678 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
680 if(measCb->measType & LKW_L2MEAS_UL_IP)
682 ulDataVol = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation;
683 ulTime = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation;
686 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = 0;
690 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = (ulDataVol / ulTime);
692 /* Converting it to kbps */
693 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut *= 8;
696 /* Reset the values after reporting to Application */
697 pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation = 0;
698 pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation = 0;
700 pUeInfoLstCfm[cfmIdx].numCfm++;
705 measCfmEvt.val.ipThMeas.numUes = cfmIdx;
707 KwMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
709 } /* kwUtlSndUlL2MeasCfm */
712 * @brief Handler for Sending Negative confirm .
716 * This function is called when the l2 measurement cannot be started
717 * This function sends negative confirm for all the requests
719 * @param[in] gCb - RLC instance control block
720 * @param[in] measReqEvt Measurement Req Structure
721 * @param[in] measCfmEvt Confirmation to be sent to layer manager
729 PUBLIC S16 kwUtlSndUlL2MeasNCfm
732 KwL2MeasReqEvt *measReqEvt,
733 KwL2MeasCfmEvt *measCfmEvt
736 PUBLIC S16 kwUtlSndUlL2MeasNCfm(gCb, measReqEvt, measCfmEvt)
738 KwL2MeasReqEvt *measReqEvt;
739 KwL2MeasCfmEvt *measCfmEvt;
742 TRC3(kwUtlSndUlL2MeasNCfm)
744 KwMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
746 } /* kwUtlSndL2MeasNCfm */
748 #ifdef LTE_L2_MEAS_RLC
750 * @brief Validates the measurement request parameters.
754 * Function :kwUtlValidateL2Meas
756 * @param[in] measReqEvt L2 measurement request received from layer manager.
757 * @param[out] measCfmEvt L2 measurement confirm to be prepared.
758 * @param[out] lChId List of LCh for the given Ue corresponding to QCIs
759 given in measurement request.
760 * @param[out] numLCh Number of LCh in array lChId.
764 PUBLIC S16 kwUtlValidateL2Meas
766 KwL2MeasReqEvt *measReqEvt,
767 KwL2MeasCfmEvt *measCfmEvt,
772 PUBLIC S16 kwUtlValidateL2Meas(measReqEvt, measCfmEvt, lChId, numLCh)
773 KwL2MeasReqEvt *measReqEvt;
774 KwL2MeasCfmEvt *measCfmEvt;
796 TRC3(kwUtlValidateL2Meas)
801 measType = measReqEvt->measReq.measType;
802 /* Check for the range of measType */
803 /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
804 if((measType == 0x00) ||
807 measCfmEvt->transId = measReqEvt->transId;
808 measCfmEvt->measType = measType;
809 measCfmEvt->status.status = LCM_PRIM_NOK;
810 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
813 /*User can either request for Active UE,*
814 *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
815 lsbNibble = measType & 0x0F;
816 msbNibble = measType & 0xF0;
818 if( (lsbNibble != 0) && (msbNibble != 0) )
820 measCfmEvt->transId = measReqEvt->transId;
821 measCfmEvt->measType = measType;
822 measCfmEvt->status.status = LCM_PRIM_NOK;
823 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
827 /* Check for total maximum number of Measurement Control Block */
828 if(kwCb.kwL2Cb.kwNumMeas >= LKW_MAX_L2MEAS )
830 measCfmEvt->transId = measReqEvt->transId;
831 measCfmEvt->measType = measType;
832 measCfmEvt->status.status = LCM_PRIM_NOK;
833 measCfmEvt->status.reason = LKW_CAUSE_EXCEED_NUMMEAS;
837 /* Check that number of samples should be a non-zero value */
838 if(((measType & LKW_L2MEAS_ACT_UE) &&
839 (measReqEvt->measReq.val.nonIpThMeas.numSamples == 0)))
841 measCfmEvt->transId = measReqEvt->transId;
842 measCfmEvt->measType = measType;
843 measCfmEvt->status.status = LCM_PRIM_NOK;
844 measCfmEvt->status.reason = LKW_CAUSE_ZERO_NUMSAM;
847 /* Check that measurement period should be completely divisible *
848 * number of sample. */
849 if(((measType & LKW_L2MEAS_ACT_UE) &&
850 ((measReqEvt->measPeriod %
851 measReqEvt->measReq.val.nonIpThMeas.numSamples) != 0)))
853 measCfmEvt->transId = measReqEvt->transId;
854 measCfmEvt->measType = measType;
855 measCfmEvt->status.status = LCM_PRIM_NOK;
856 measCfmEvt->status.reason = LKW_CAUSE_INVALID_NUMSAM;
860 numQci = measReqEvt->measReq.val.nonIpThMeas.numQci;
861 qciVal = measReqEvt->measReq.val.nonIpThMeas.qci;
863 /* Check whether qci is configured or not */
864 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
866 qci = qciVal[qciIdx];
867 ret = cmHashListFind(&(kwCb.kwL2Cb.qciHlCp),
868 (U8 *)&qci, (U16)sizeof(qci), 0, (PTR *)&rbCb);
871 measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
872 measCfmEvt->val.nonIpThMeas.numCfm++;
876 if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
878 measCfmEvt->status.status = LCM_PRIM_NOK;
879 measCfmEvt->status.reason = LKW_CAUSE_INVALID_QCI;
880 measCfmEvt->measType = measType;
881 measCfmEvt->transId = measReqEvt->transId;
885 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
887 if(kwCb.kwL2Cb.measOn[qci] & measReqEvt->measReq.measType)
889 /* measurement is already ongoing */
890 measCfmEvt->status.status = LCM_PRIM_NOK;
891 measCfmEvt->status.reason = LKW_CAUSE_MEAS_ALREADY_ENA;
892 measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
893 measCfmEvt->measType = measType;
894 measCfmEvt->val.nonIpThMeas.numCfm++;
898 if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
900 measCfmEvt->transId = measReqEvt->transId;
905 }/* kwUtlValidateL2Meas */
909 PUBLIC S16 kwUtlValidateIpThL2Meas
911 KwL2MeasReqEvt *measReqEvt,
912 KwL2MeasCfmEvt *measCfmEvt
915 PUBLIC S16 kwUtlValidateIpThL2Meas(measReqEvt, measCfmEvt)
916 KwL2MeasReqEvt *measReqEvt;
917 KwL2MeasCfmEvt *measCfmEvt;
924 TRC3(kwUtlValidateIpThL2Meas)
926 measType = measReqEvt->measReq.measType;
927 /* Check for the range of measType */
928 /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
929 if((measType == 0x00) ||
932 measCfmEvt->transId = measReqEvt->transId;
933 measCfmEvt->measType = measType;
934 measCfmEvt->status.status = LCM_PRIM_NOK;
935 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
938 /*User can either request for Active UE,*
939 *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
940 lsbNibble = measType & 0x0F;
941 msbNibble = measType & 0xF0;
943 if( (lsbNibble != 0) && (msbNibble != 0) )
945 measCfmEvt->transId = measReqEvt->transId;
946 measCfmEvt->measType = measType;
947 measCfmEvt->status.status = LCM_PRIM_NOK;
948 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
952 }/* kwUtlValidateL2Meas */
956 * @brief Handler for resetting the RB data structures
960 * This function resets the RB data structure after the expiry of
963 * @param[in] measCb Measurement Control Block.
970 PUBLIC Void kwUtlResetUlL2MeasInKwRb
977 PUBLIC Void kwUtlResetUlL2MeasInKwRb(measCb, measType)
986 KwUlUeCb *ueCb = NULL;
990 if (measCb->measType & LKW_L2MEAS_UL_IP)
992 for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
994 if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
996 for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
998 if (measType & LKW_L2MEAS_UL_IP)
1000 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.volSummation = 0;
1001 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.timeSummation = 0;
1005 if(ROK != kwDbmFetchUlUeCb(gCb, measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
1006 measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
1011 for (rbIdx = 0; rbIdx < KW_MAX_DRB_PER_UE; rbIdx++)
1013 if (ueCb->drbCb[rbIdx])
1015 ueCb->drbCb[rbIdx]->rbL2Cb.measOn &= ~measType;
1021 } /* kwUtlResetUlL2MeasInKwRb */
1025 * @brief Handler for storing address of MeasData in rbCb at right index
1029 * This function is called when LM sends measReq message to RLC.
1040 PUBLIC Void kwUtlPlcMeasDatInL2Sts
1043 KwL2MeasRbCb *rbL2Cb,
1047 PUBLIC Void kwUtlPlcMeasDatInL2Sts(measData, rbL2Cb, measType)
1049 KwL2MeasRbCb *rbL2Cb;
1053 TRC3(kwUtlPlcMeasDatInL2Sts)
1055 /* We should check the number of measType in the request. This can be done
1056 * by looking at each bit in the measType. Also store the measData in the
1057 * correct index of l2Sts in RbCb.
1060 if(measType & LKW_L2MEAS_ACT_UE)
1062 rbL2Cb->l2Sts[KW_L2MEAS_ACT_UE] = measData;
1064 if(measType & LKW_L2MEAS_UU_LOSS)
1066 rbL2Cb->l2Sts[KW_L2MEAS_UU_LOSS] = measData;
1068 if(measType & LKW_L2MEAS_DL_IP )
1070 rbL2Cb->l2Sts[KW_L2MEAS_DL_IP] = measData;
1072 if(measType & LKW_L2MEAS_UL_IP)
1074 rbL2Cb->l2Sts[KW_L2MEAS_UL_IP] = measData;
1076 if(measType & LKW_L2MEAS_DL_DISC)
1078 rbL2Cb->l2Sts[KW_L2MEAS_DL_DISC] = measData;
1080 if(measType & LKW_L2MEAS_DL_DELAY)
1082 rbL2Cb->l2Sts[KW_L2MEAS_DL_DELAY] = measData;
1084 }/* End of kwUtlPlcMeasDatInL2Sts */
1085 #endif /* LTE_L2_MEAS */
1089 * @brief Store the UL buffer in hashList
1094 * Use the SN % binSize as key and store the received UL buffer
1095 * @param[in] recBufLst List CP array
1096 * @param[in] recBuf received buffer
1097 * @param[in] sn sn of the received buffer
1103 PUBLIC Void kwUtlStoreRecBuf
1105 CmLListCp *recBufLst,
1110 PUBLIC Void kwUtlStoreRecBuf(recBufLst, recBuf, sn)
1111 CmLListCp *recBufLst;
1118 TRC3(kwUtlStoreRecBuf)
1120 hashKey = (sn % KW_RCV_BUF_BIN_SIZE );
1121 recBuf->lnk.node = (PTR)recBuf;
1122 cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1125 } /* kwUtlStoreRecBuf */
1129 * @brief Retrieve the UL buffer from the list
1134 * Use the SN % binSize as key and retrieve the UL buffer
1135 * @param[in] recBufLst List CP array
1136 * @param[in] sn sn of the received buffer
1142 PUBLIC KwAmRecBuf* kwUtlGetRecBuf
1144 CmLListCp *recBufLst,
1148 PUBLIC KwAmRecBuf* kwUtlGetRecBuf(recBufLst, sn)
1149 CmLListCp *recBufLst;
1154 CmLListCp *recBufLstCp;
1156 CmLList *node = NULLP;
1158 TRC3(kwUtlGetRecBuf)
1160 hashKey = (sn % KW_RCV_BUF_BIN_SIZE );
1162 recBufLstCp = &recBufLst[hashKey];
1163 CM_LLIST_FIRST_NODE(recBufLstCp, node);
1166 recBuf = (KwAmRecBuf *) node->node;
1167 if(recBuf->amHdr.sn == sn)
1171 CM_LLIST_NEXT_NODE(recBufLstCp, node);
1174 } /* kwUtlStoreRecBuf */
1177 * @brief Delete the UL buffer from the list
1182 * Use the SN % binSize as key and retrieve the UL buffer
1183 * @param[in] recBufLst List CP array
1184 * @param[in] sn sn of the received buffer
1190 PUBLIC Void kwUtlDelRecBuf
1192 CmLListCp *recBufLst,
1197 PUBLIC Void kwUtlDelRecBuf(recBufLst, recBufi, gCb)
1198 CmLListCp *recBufLst;
1204 CmLListCp *recBufLstCp;
1206 TRC3(kwUtlDelRecBuf)
1208 hashKey = (recBuf->amHdr.sn % KW_RCV_BUF_BIN_SIZE );
1210 recBufLstCp = &recBufLst[hashKey];
1211 cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1212 KW_FREE_WC(gCb, recBuf, sizeof(KwAmRecBuf));
1215 } /* kwUtlDelRecBuf */
1220 /********************************************************************30**
1222 **********************************************************************/