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
31 --rlcUtlSendUlDataToDu
36 **********************************************************************/
39 @brief RLC Utility Module
42 /* header (.h) include files */
43 #include "common_def.h"
44 /* kw005.201 added support for L2 Measurement */
49 #include "ckw.h" /* CKW defines */
50 #include "kwu.h" /* KWU defines */
51 #include "lkw.h" /* LKW defines */
52 #include "rgu.h" /* RGU defines */
54 #include "kw_env.h" /* RLC environment options */
55 #include "kw.h" /* RLC defines */
56 #include "kw_err.h" /* Error defines */
57 #include "kw_ul.h" /* RLC Uplink defines */
59 /* extern (.x) include files */
60 #include "ckw.x" /* CKW includes */
61 #include "kwu.x" /* KWU includes */
62 #include "lkw.x" /* LKW includes */
63 #include "rgu.x" /* RGU includes */
65 #include "kw.x" /* RLC inlcudes */
66 #include "kw_ul.x" /* RLC uplink includes */
67 #include "rlc_utils.h"
68 #include "du_app_rlc_inf.h"
69 #include "rlc_upr_inf_api.h"
72 S16 SMrkUlPkt(Buffer *mbuf);
74 RlcAmRecBuf* rlcUtlGetRecBuf(CmLListCp *recBufLst, RlcSn sn);
75 #define RLC_MODULE (RLC_DBGMASK_DUT | RLC_DBGMASK_UL) /* for debugging purpose */
81 * Handler for receiving data for multiple logical channels from MAC.
84 * This function receives the data sent by MAC for one or more
85 * logical channels.It calls the UMM or AMM functions to process
86 * the PDUs and send them to the uppper layer.
88 * @param[in] gCb - RLC instance control block
89 * @param[in] datIndInfo - Data Indication Information containing the PDU(s)
90 * for one or more logical channels
97 uint8_t rlcUtlRcvFrmMac(RlcCb *gCb, KwDatIndInfo *datIndInfo)
99 uint32_t count; /* Loop Counter */
100 KwPduInfo *pduInfo; /* PDU Information */
101 RlcUlRbCb *rbCb; /* RB Control Block */
102 RlcUlUeCb *ueCb; /* UE Control Block */
107 if( ROK != rlcDbmFetchUlUeCb(gCb,datIndInfo->rnti,datIndInfo->cellId,&(ueCb)))
109 /* Fetch UeCb failed */
110 DU_LOG("\nERROR --> RLC_UL : rlcUtlRcvFrmMac : UEID:%d UeCb not found",
112 /* free the buffers inside the datIndInfo */
114 for(i = 0; i< datIndInfo->numLch; i++)
116 for(j = 0; j < datIndInfo->lchData[i].pdu.numPdu; j++)
118 if(datIndInfo->lchData[i].pdu.mBuf[j])
120 ODU_PUT_MSG_BUF(datIndInfo->lchData[i].pdu.mBuf[j]);
130 if (RGU_L2M_UL_BURST_START == datIndInfo->burstInd)
132 ueCb->isUlBurstActive = TRUE;
136 ueCb->firstPacketTTI = 0;
137 ueCb->isUlBurstActive = FALSE;
140 for ( count = 0;count < datIndInfo->numLch; count++ )
142 rbCb = ueCb->lCh[datIndInfo->lchData[count].lcId - 1].ulRbCb;
143 /* kw002.201 Removed allocation of pduInfo */
144 pduInfo = &(datIndInfo->lchData[count].pdu);
145 /* Fix for CR ccpu00138374,sometimes rbCb is NULL in UL path,
146 * So inorder to avoid the crash, added this preventive check
151 for(j = 0; j < pduInfo->numPdu; j++)
155 ODU_PUT_MSG_BUF(pduInfo->mBuf[j]);
162 SMrkUlPkt(pduInfo->mBuf[0]);
164 if ( rbCb->mode == RLC_MODE_UM )
166 /* kw005.201 added support for L2 Measurement */
168 rlcUmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
170 rlcUmmProcessPdus(gCb,rbCb,pduInfo);
173 else if (rbCb->mode == RLC_MODE_AM )
175 /* kw005.201 added support for L2 Measurement */
177 rlcAmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
179 rlcAmmProcessPdus(gCb,rbCb,pduInfo);
189 * Handler for sending Data Indication to the upper layer.
192 * This function is used to send re-assembled SDU to the upper layer.
194 * @param[in] gCb - RLC instance Control Block
195 * @param[in] rbCb - RB Control Block
196 * @param[in] sdu - SDU to be sent to upper layer
201 uint8_t rlcUtlSendUlDataToDu(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *sdu)
204 KwuDatIndInfo *datIndInfo; /* Data Indication Information */
205 KwuDatIndInfo datIndInfoTmp;
207 RlcUlRrcMsgInfo *ulRrcMsgInfo;
208 RlcUlUserDatInfo *ulUserDatInfo;
209 uint16_t msgLen, copyLen;
213 /* Creating static memory for KwuDatIndInfo. #else will be
214 * removed once the testing is done on all platforms */
215 datIndInfo = &datIndInfoTmp;
216 if (datIndInfo == NULLP)
218 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed UEID:%d \
219 CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
220 ODU_PUT_MSG_BUF(sdu);
224 RLC_MEM_CPY(&(datIndInfo->rlcId),&(rbCb->rlcId),sizeof(CmLteRlcId));
225 /* Set the "isOutofSeq" flag for each packet
226 * If packets are in-sequence set flag as TRUE else FALSE */
227 datIndInfo->isOutOfSeq = rbCb->m.amUl.isOutOfSeq;
230 if(rbCb->rlcId.rbType == RB_TYPE_SRB)
232 /* Filling UL RRC Message Info if UL msg is not received on SRBs*/
233 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL,
234 ulRrcMsgInfo, sizeof(RlcUlRrcMsgInfo));
237 ulRrcMsgInfo->cellId = rbCb->rlcId.cellId;
238 ulRrcMsgInfo->ueIdx = rbCb->rlcId.ueId;
239 ulRrcMsgInfo->lcId = rbCb->lch.lChId;
240 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL,
241 ulRrcMsgInfo->rrcMsg, msgLen);
242 if (ulRrcMsgInfo->rrcMsg)
244 ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
245 ODU_COPY_MSG_TO_FIX_BUF(sdu, 0, msgLen, ulRrcMsgInfo->rrcMsg, (MsgLen *)©Len);
246 ulRrcMsgInfo->msgLen = msgLen;
248 /* Sending UL RRC Message transfeer to DU APP */
249 memset(&pst, 0, sizeof(Pst));
250 FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_UL_RRC_MSG_TRANS_TO_DU);
251 rlcSendUlRrcMsgToDu(&pst, ulRrcMsgInfo);
255 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for rrcMsg");
256 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulRrcMsgInfo, sizeof(RlcUlRrcMsgInfo));
262 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for ulRrcMsgInfo");
266 else if(rbCb->rlcId.rbType == RB_TYPE_DRB)
268 /* Filling UL User Data Info if UL msg is received on a DRB */
269 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo, sizeof(RlcUlUserDatInfo));
272 ulUserDatInfo->cellId = rbCb->rlcId.cellId;
273 ulUserDatInfo->ueIdx = rbCb->rlcId.ueId;
274 ulUserDatInfo->rbId = rbCb->rlcId.rbId;
275 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo->userData, msgLen);
276 if (ulUserDatInfo->userData)
278 ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
279 ODU_COPY_MSG_TO_FIX_BUF(sdu, 0, msgLen, ulUserDatInfo->userData, (MsgLen *)©Len);
280 ulUserDatInfo->msgLen = msgLen;
282 /* Sending UL RRC Message transfeer to DU APP */
283 memset(&pst, 0, sizeof(Pst));
284 FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_UL_USER_DATA_TRANS_TO_DU);
285 rlcSendUlUserDataToDu(&pst, ulUserDatInfo);
289 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for user data");
290 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo, sizeof(RlcUlUserDatInfo));
296 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for ulUserDatInfo");
301 } /* rlcUtlSendUlDataToDu */
304 static Void dumpRLCUlRbInformation(RlcUlRbCb* ulRbCb)
306 if(ulRbCb->mode == RLC_MODE_UM)
309 uint32_t pdusInReceptionBuffer = 0;
310 uint32_t totalSegs = 0;
312 for(i = 0; i< RLC_RCV_BUF_BIN_SIZE; i++)
314 RlcUmRecBuf *recBuf = rlcUtlGetUmRecBuf(ulRbCb->m.umUl.recBufLst, i);
317 pdusInReceptionBuffer++;
318 totalSegs += (recBuf->segLst.count);
322 DU_LOG("\nDEBUG --> RLC_UL: UM UL UEID:%d CELLID:%d Reception Buffer size = %d Total segs = %d",
323 ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
325 else if(ulRbCb->mode == RLC_MODE_AM)
328 uint32_t pdusInReceptionBuffer = 0;
329 uint32_t totalSegs = 0;
330 uint32_t windSz = RLC_AM_GET_WIN_SZ(ulRbCb->m.amUl.snLen) << 1;
332 for(i = 0; i< windSz; i++)
334 RlcAmRecBuf *recBuf = rlcUtlGetRecBuf(ulRbCb->m.amUl.recBufLst, i);
337 pdusInReceptionBuffer++;
338 totalSegs += (recBuf->segLst.count);
342 DU_LOG("\nDEBUG --> RLC_UL: AM UL UEID:%d CELLID:%d Reception Buf size = %d total segs = %d",
343 ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
347 Void DumpRLCUlDebugInformation(Void)
349 RlcCb* ulInst = rlcCb[0]; /* TODO : Check whether UL is 0 or 1 */
350 RlcUlCb* ulCb = ulInst->u.ulCb;
351 RlcUlUeCb *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< RLC_MAX_SRB_PER_UE; i++)
361 RlcUlRbCb* ulRbCb = ueCb->srbCb[i];
364 dumpRLCUlRbInformation(ulRbCb);
367 for(i = 0; i< RLC_MAX_DRB_PER_UE; i++)
369 RlcUlRbCb* ulRbCb = ueCb->drbCb[i];
372 dumpRLCUlRbInformation(ulRbCb);
380 * kwUtlFreeUlRbCb() function is split into two functions
381 * - rlcAmmFreeUlRbCb() ---> gp_amm_ul.c
382 * - rlcUmmFreeUlRbCb() ---> 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 rlcUtlL2MeasUlInit(RlcCb *gCb)
405 gCb->u.ulCb->rlcL2Cb.rlcNumMeas=0;
406 for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
408 memset(&(gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[cntr]), 0, sizeof(RlcL2MeasEvtCb));
410 gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[RLC_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
428 Void rlcUtlCalUlIpThrPutIncTTI(RlcCb *gCb,RlcUlRbCb *rbCb,uint32_t ttiCnt)
430 volatile uint32_t startTime = 0;
433 SStartTask(&startTime, PID_RLC_IP_TPT_INCTTI);
435 DU_LOG("\nDEBUG --> RLC_UL : Log for ul ip throughput:"
436 "RB_MeasOn:%d ttiCnt :%ld UEID:%d CELLID:%d",
437 rbCb->rbL2Cb.measOn,ttiCnt,
441 DU_LOG("\nDEBUG --> RLC_UL : Log for ul ip throughput:"
442 "RB_MeasOn:%d ttiCnt :%d UEID:%d CELLID:%d",
443 rbCb->rbL2Cb.measOn,ttiCnt,
448 /*Check if UL IP throughput measurement is ON for this RB or not*/
449 if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb,rbCb))
451 if (TRUE == rbCb->ueCb->isUlBurstActive)
453 if (ttiCnt < rbCb->l2MeasIpThruput.prevTtiCnt)
455 /*Removed Error Print*/
457 if (rbCb->l2MeasIpThruput.prevTtiCnt != 0)
459 rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.timeSummation +=
460 (ttiCnt - rbCb->l2MeasIpThruput.prevTtiCnt);
464 rbCb->ueCb->firstPacketTTI = ttiCnt;
466 rbCb->l2MeasIpThruput.prevTtiCnt = ttiCnt;
470 rbCb->l2MeasIpThruput.prevTtiCnt = 0;
475 SStopTask(startTime, PID_RLC_IP_TPT_INCTTI);
476 } /* rlcUtlCalUlIpThrPutIncTTI */
483 * Handler to calculate the Ul Ip throughput for a LCH
488 * @param[in] rbCb RB control block
489 * @param[in] pdu Pdu of LCH
494 Void rlcUtlCalUlIpThrPut
502 MsgLen rlcSduSz = 0; /*Holds length of Rlc Sdu*/
503 volatile uint32_t startTime = 0;
506 SStartTask(&startTime, PID_RLC_IP_TPT_INCVOL);
508 /*Check if UL IP throughput measurement is ON for this RB or not*/
509 if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb, rbCb) &&
510 (TRUE == rbCb->ueCb->isUlBurstActive) &&
511 (rbCb->ueCb->firstPacketTTI) &&
512 (ttiCnt != rbCb->ueCb->firstPacketTTI))
514 SFndLenMsg(pdu, &rlcSduSz);
516 rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.volSummation += rlcSduSz;
520 SStopTask(startTime, PID_RLC_IP_TPT_INCVOL);
521 } /* rlcUtlCalUlIpThrPut */
526 * @brief Handler for L2 Measurement timer expiry.
530 * This function is called when the l2 measurement timer expires.
531 * This function sends a consolidates the mesaurements taken during
532 * this time and sends the confirm .
534 * @param[in] measEvtCb Measurement Event Control Block.
541 S16 rlcUtlHdlL2TmrExp(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
544 #ifdef LTE_L2_MEAS_RLC
548 /* Clean up the RB data structures */
549 if((measEvtCb->measCb.measType & LKW_L2MEAS_ACT_UE) &&
550 (measEvtCb->measCb.val.nonIpThMeas.numSamples))
552 measCb = &measEvtCb->measCb;
554 for(qciIdx = 0; qciIdx < measCb->val.nonIpThMeas.numQci;qciIdx++)
556 measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.numActvUe +=
557 rlcCb.rlcL2Cb.numActUe[measCb->val.nonIpThMeas.qci[qciIdx]];
558 measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.sampOc++;
560 measEvtCb->val.nonIpThMeas.measCb.numSamples--;
561 rlcStartTmr(gCb, (PTR)measEvtCb, EVENT_RLC_L2_TMR);
566 rlcUtlSndUlL2MeasCfm(gCb, measEvtCb);
569 } /* rlcUtlHdlL2TmrExp */
572 * @brief Handler for Sending L2 Measurement confirm.
576 * This function sends a consolidates the mesaurements taken during
577 * this time and sends the confirm .
579 * @param[in] measEvtCb Measurement Event Control Block.
586 S16 rlcUtlSndUlL2MeasCfm(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
590 RlcL2MeasCfmEvt measCfmEvt;
594 /* Discard new changes starts */
597 /* Discard new changes ends */
599 /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
601 DU_LOG("\nDEBUG --> RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%ld))", measEvtCb->transId);
603 DU_LOG("\nDEBUG --> RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%d))", measEvtCb->transId);
606 /* Clean up the RB data structures */
607 measCb = &measEvtCb->measCb;
609 memset(&measCfmEvt, 0, sizeof(RlcL2MeasCfmEvt));
610 measCfmEvt.transId = measEvtCb->transId;
612 measCfmEvt.measType = measCb->measType;
613 measCfmEvt.status.status = LCM_PRIM_OK;
614 measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
616 if( measCb->measType & LKW_L2MEAS_UL_IP)
618 RlcL2MeasCbUeMeasInfo *pUeInfoLstCb = measCb->val.ipThMeas.ueInfoLst;
619 RlcL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
620 for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)
622 pUeInfoLstCfm[cfmIdx].numCfm = 0;
623 if (pUeInfoLstCb[cntr].isValid == TRUE)
625 pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
626 pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
628 for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
630 qci = pUeInfoLstCb[cntr].qci[qciIdx];
631 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
633 if(measCb->measType & LKW_L2MEAS_UL_IP)
635 ulDataVol = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation;
636 ulTime = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation;
639 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = 0;
643 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = (ulDataVol / ulTime);
645 /* Converting it to kbps */
646 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut *= 8;
649 /* Reset the values after reporting to Application */
650 pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation = 0;
651 pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation = 0;
653 pUeInfoLstCfm[cfmIdx].numCfm++;
658 measCfmEvt.val.ipThMeas.numUes = cfmIdx;
660 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
662 } /* rlcUtlSndUlL2MeasCfm */
665 * @brief Handler for Sending Negative confirm .
669 * This function is called when the l2 measurement cannot be started
670 * This function sends negative confirm for all the requests
672 * @param[in] gCb - RLC instance control block
673 * @param[in] measReqEvt Measurement Req Structure
674 * @param[in] measCfmEvt Confirmation to be sent to layer manager
681 S16 rlcUtlSndUlL2MeasNCfm(RlcCb *gCb,RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
684 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
686 } /* kwUtlSndL2MeasNCfm */
688 #ifdef LTE_L2_MEAS_RLC
690 * @brief Validates the measurement request parameters.
694 * Function :rlcUtlValidateL2Meas
696 * @param[in] measReqEvt L2 measurement request received from layer manager.
697 * @param[out] measCfmEvt L2 measurement confirm to be prepared.
698 * @param[out] lChId List of LCh for the given Ue corresponding to QCIs
699 given in measurement request.
700 * @param[out] numLCh Number of LCh in array lChId.
703 S16 rlcUtlValidateL2Meas
705 RlcL2MeasReqEvt *measReqEvt,
706 RlcL2MeasCfmEvt *measCfmEvt,
722 uint8_t lsbNibble = 0;
723 uint8_t msbNibble = 0;
724 uint8_t numFaild = 0;
729 measType = measReqEvt->measReq.measType;
730 /* Check for the range of measType */
731 /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
732 if((measType == 0x00) ||
735 measCfmEvt->transId = measReqEvt->transId;
736 measCfmEvt->measType = measType;
737 measCfmEvt->status.status = LCM_PRIM_NOK;
738 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
741 /*User can either request for Active UE,*
742 *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
743 lsbNibble = measType & 0x0F;
744 msbNibble = measType & 0xF0;
746 if( (lsbNibble != 0) && (msbNibble != 0) )
748 measCfmEvt->transId = measReqEvt->transId;
749 measCfmEvt->measType = measType;
750 measCfmEvt->status.status = LCM_PRIM_NOK;
751 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
755 /* Check for total maximum number of Measurement Control Block */
756 if(rlcCb.rlcL2Cb.rlcNumMeas >= LKW_MAX_L2MEAS )
758 measCfmEvt->transId = measReqEvt->transId;
759 measCfmEvt->measType = measType;
760 measCfmEvt->status.status = LCM_PRIM_NOK;
761 measCfmEvt->status.reason = LKW_CAUSE_EXCEED_NUMMEAS;
765 /* Check that number of samples should be a non-zero value */
766 if(((measType & LKW_L2MEAS_ACT_UE) &&
767 (measReqEvt->measReq.val.nonIpThMeas.numSamples == 0)))
769 measCfmEvt->transId = measReqEvt->transId;
770 measCfmEvt->measType = measType;
771 measCfmEvt->status.status = LCM_PRIM_NOK;
772 measCfmEvt->status.reason = LKW_CAUSE_ZERO_NUMSAM;
775 /* Check that measurement period should be completely divisible *
776 * number of sample. */
777 if(((measType & LKW_L2MEAS_ACT_UE) &&
778 ((measReqEvt->measPeriod %
779 measReqEvt->measReq.val.nonIpThMeas.numSamples) != 0)))
781 measCfmEvt->transId = measReqEvt->transId;
782 measCfmEvt->measType = measType;
783 measCfmEvt->status.status = LCM_PRIM_NOK;
784 measCfmEvt->status.reason = LKW_CAUSE_INVALID_NUMSAM;
788 numQci = measReqEvt->measReq.val.nonIpThMeas.numQci;
789 qciVal = measReqEvt->measReq.val.nonIpThMeas.qci;
791 /* Check whether qci is configured or not */
792 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
794 qci = qciVal[qciIdx];
795 ret = cmHashListFind(&(rlcCb.rlcL2Cb.qciHlCp),
796 (uint8_t *)&qci, (uint16_t)sizeof(qci), 0, (PTR *)&rbCb);
799 measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
800 measCfmEvt->val.nonIpThMeas.numCfm++;
804 if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
806 measCfmEvt->status.status = LCM_PRIM_NOK;
807 measCfmEvt->status.reason = LKW_CAUSE_INVALID_QCI;
808 measCfmEvt->measType = measType;
809 measCfmEvt->transId = measReqEvt->transId;
813 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
815 if(rlcCb.rlcL2Cb.measOn[qci] & measReqEvt->measReq.measType)
817 /* measurement is already ongoing */
818 measCfmEvt->status.status = LCM_PRIM_NOK;
819 measCfmEvt->status.reason = LKW_CAUSE_MEAS_ALREADY_ENA;
820 measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
821 measCfmEvt->measType = measType;
822 measCfmEvt->val.nonIpThMeas.numCfm++;
826 if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
828 measCfmEvt->transId = measReqEvt->transId;
833 }/* rlcUtlValidateL2Meas */
836 S16 rlcUtlValidateIpThL2Meas(RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
839 uint8_t lsbNibble = 0;
840 uint8_t msbNibble = 0;
842 measType = measReqEvt->measReq.measType;
843 /* Check for the range of measType */
844 /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
845 if((measType == 0x00) ||
848 measCfmEvt->transId = measReqEvt->transId;
849 measCfmEvt->measType = measType;
850 measCfmEvt->status.status = LCM_PRIM_NOK;
851 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
854 /*User can either request for Active UE,*
855 *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
856 lsbNibble = measType & 0x0F;
857 msbNibble = measType & 0xF0;
859 if( (lsbNibble != 0) && (msbNibble != 0) )
861 measCfmEvt->transId = measReqEvt->transId;
862 measCfmEvt->measType = measType;
863 measCfmEvt->status.status = LCM_PRIM_NOK;
864 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
868 }/* rlcUtlValidateL2Meas */
872 * @brief Handler for resetting the RB data structures
876 * This function resets the RB data structure after the expiry of
879 * @param[in] measCb Measurement Control Block.
885 Void rlcUtlResetUlL2MeasInRlcRb(RlcCb *gCb,RlcL2MeasCb *measCb,uint8_t measType)
890 RlcUlUeCb *ueCb = NULL;
894 if (measCb->measType & LKW_L2MEAS_UL_IP)
896 for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
898 if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
900 for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
902 if (measType & LKW_L2MEAS_UL_IP)
904 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.volSummation = 0;
905 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.timeSummation = 0;
909 if(ROK != rlcDbmFetchUlUeCb(gCb, measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
910 measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
915 for (rbIdx = 0; rbIdx < RLC_MAX_DRB_PER_UE; rbIdx++)
917 if (ueCb->drbCb[rbIdx])
919 ueCb->drbCb[rbIdx]->rbL2Cb.measOn &= ~measType;
925 } /* rlcUtlResetUlL2MeasInRlcRb */
929 * @brief Handler for storing address of MeasData in rbCb at right index
933 * This function is called when LM sends measReq message to RLC.
943 Void rlcUtlPlcMeasDatInL2Sts(RlcL2Cntr *measData,RlcL2MeasRbCb *rbL2Cb,uint8_t measType)
945 /* We should check the number of measType in the request. This can be done
946 * by looking at each bit in the measType. Also store the measData in the
947 * correct index of l2Sts in RbCb.
950 if(measType & LKW_L2MEAS_ACT_UE)
952 rbL2Cb->l2Sts[RLC_L2MEAS_ACT_UE] = measData;
954 if(measType & LKW_L2MEAS_UU_LOSS)
956 rbL2Cb->l2Sts[RLC_L2MEAS_UU_LOSS] = measData;
958 if(measType & LKW_L2MEAS_DL_IP )
960 rbL2Cb->l2Sts[RLC_L2MEAS_DL_IP] = measData;
962 if(measType & LKW_L2MEAS_UL_IP)
964 rbL2Cb->l2Sts[RLC_L2MEAS_UL_IP] = measData;
966 if(measType & LKW_L2MEAS_DL_DISC)
968 rbL2Cb->l2Sts[RLC_L2MEAS_DL_DISC] = measData;
970 if(measType & LKW_L2MEAS_DL_DELAY)
972 rbL2Cb->l2Sts[RLC_L2MEAS_DL_DELAY] = measData;
974 }/* End of rlcUtlPlcMeasDatInL2Sts */
975 #endif /* LTE_L2_MEAS */
979 * @brief Store the UL buffer in hashList
984 * Use the SN % binSize as key and store the received UL buffer
985 * @param[in] recBufLst List CP array
986 * @param[in] recBuf received buffer
987 * @param[in] sn sn of the received buffer
992 void rlcUtlStoreRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcSn sn)
996 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
997 recBuf->lnk.node = (PTR)recBuf;
998 cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1001 } /* rlcUtlStoreRecBuf */
1005 * @brief Retrieve the UL buffer from the list
1010 * Use the SN % binSize as key and retrieve the UL buffer
1011 * @param[in] recBufLst List CP array
1012 * @param[in] sn sn of the received buffer
1017 RlcAmRecBuf* rlcUtlGetRecBuf(CmLListCp *recBufLst, RlcSn sn)
1020 CmLListCp *recBufLstCp;
1021 RlcAmRecBuf *recBuf;
1022 CmLList *node = NULLP;
1024 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
1026 recBufLstCp = &recBufLst[hashKey];
1027 CM_LLIST_FIRST_NODE(recBufLstCp, node);
1030 recBuf = (RlcAmRecBuf *) node->node;
1031 if(recBuf->amHdr.sn == sn)
1035 CM_LLIST_NEXT_NODE(recBufLstCp, node);
1038 } /* rlcUtlGetRecBuf */
1041 * @brief Delete the UL buffer from the list
1046 * Use the SN % binSize as key and retrieve the UL buffer
1047 * @param[in] recBufLst List CP array
1048 * @param[in] sn sn of the received buffer
1053 void rlcUtlDelRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcCb *gCb)
1056 CmLListCp *recBufLstCp;
1058 hashKey = (recBuf->amHdr.sn % RLC_RCV_BUF_BIN_SIZE );
1060 recBufLstCp = &recBufLst[hashKey];
1061 cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1062 RLC_FREE(gCb, recBuf, sizeof(RlcAmRecBuf));
1065 } /* rlcUtlDelRecBuf */
1069 * @brief Store the UL buffer in hashList
1073 * Use the SN % binSize as key and store the received UL buffer
1074 * @param[in] recBufLst List CP array
1075 * @param[in] recBuf received buffer
1076 * @param[in] sn sn of the received buffer
1080 void rlcUtlStoreUmRecBuf(CmLListCp *recBufLst, RlcUmRecBuf *recBuf, RlcSn sn)
1084 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
1085 recBuf->lnk.node = (PTR)recBuf;
1086 cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1089 } /* rlcUtlStoreUmRecBuf */
1093 * @brief Retrieve the UL buffer from the list
1097 * Use the SN % binSize as key and retrieve the UL buffer
1098 * @param[in] recBufLst List CP array
1099 * @param[in] sn sn of the received buffer
1103 RlcUmRecBuf* rlcUtlGetUmRecBuf(CmLListCp *recBufLst, RlcSn sn)
1106 CmLListCp *recBufLstCp;
1107 RlcUmRecBuf *recBuf;
1108 CmLList *node = NULLP;
1110 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
1112 recBufLstCp = &recBufLst[hashKey];
1113 CM_LLIST_FIRST_NODE(recBufLstCp, node);
1116 recBuf = (RlcUmRecBuf *) node->node;
1117 if(recBuf->umHdr.sn == sn)
1121 CM_LLIST_NEXT_NODE(recBufLstCp, node);
1124 } /* rlcUtlGetUmRecBuf */
1128 * @brief Delete the UM Mode UL buffer from the list
1132 * Use the SN % binSize as key and retrieve the UL buffer
1134 * @param[in] *recBufLst List CP array
1135 * @param[in] *recBuf Received buffer
1139 void rlcUtlDelUmRecBuf(RlcCb *gCb, CmLListCp *recBufLst, RlcUmRecBuf *recBuf)
1142 CmLListCp *recBufLstCp;
1144 hashKey = (recBuf->sn % RLC_RCV_BUF_BIN_SIZE );
1145 recBufLstCp = &recBufLst[hashKey];
1146 cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1147 RLC_FREE(gCb, recBuf, sizeof(RlcUmRecBuf));
1150 } /* rlcUtlDelUmRecBuf */
1152 /********************************************************************30**
1154 **********************************************************************/