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 **********************************************************************/
38 /** @file rlc_utl_ul.c
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 */
53 #include "rlc_env.h" /* RLC environment options */
54 #include "rlc_err.h" /* Error defines */
57 /* extern (.x) include files */
58 #include "ckw.x" /* CKW includes */
59 #include "kwu.x" /* KWU includes */
60 #include "lkw.x" /* LKW includes */
61 #include "rgu.x" /* RGU includes */
63 #include "rlc_utils.h" /* RLC defines */
64 #include "rlc_ul.h" /* RLC Uplink defines */
65 #include "du_app_rlc_inf.h"
66 #include "rlc_upr_inf_api.h"
69 S16 SMrkUlPkt(Buffer *mbuf);
71 RlcAmRecBuf* rlcUtlGetRecBuf(CmLListCp *recBufLst, RlcSn sn);
72 #define RLC_MODULE (RLC_DBGMASK_DUT | RLC_DBGMASK_UL) /* for debugging purpose */
78 * Handler for receiving data for multiple logical channels from MAC.
81 * This function receives the data sent by MAC for one or more
82 * logical channels.It calls the UMM or AMM functions to process
83 * the PDUs and send them to the uppper layer.
85 * @param[in] gCb - RLC instance control block
86 * @param[in] datIndInfo - Data Indication Information containing the PDU(s)
87 * for one or more logical channels
94 uint8_t rlcUtlRcvFrmMac(RlcCb *gCb, KwDatIndInfo *datIndInfo)
96 uint32_t count; /* Loop Counter */
97 KwPduInfo *pduInfo; /* PDU Information */
98 RlcUlRbCb *rbCb; /* RB Control Block */
99 RlcUlUeCb *ueCb; /* UE Control Block */
104 if( ROK != rlcDbmFetchUlUeCb(gCb,datIndInfo->rnti,datIndInfo->cellId,&(ueCb)))
106 /* Fetch UeCb failed */
107 DU_LOG("\nERROR --> RLC_UL : rlcUtlRcvFrmMac : UEID:%d UeCb not found",
109 /* free the buffers inside the datIndInfo */
111 for(i = 0; i< datIndInfo->numLch; i++)
113 for(j = 0; j < datIndInfo->lchData[i].pdu.numPdu; j++)
115 if(datIndInfo->lchData[i].pdu.mBuf[j])
117 ODU_PUT_MSG_BUF(datIndInfo->lchData[i].pdu.mBuf[j]);
127 if (RGU_L2M_UL_BURST_START == datIndInfo->burstInd)
129 ueCb->isUlBurstActive = TRUE;
133 ueCb->firstPacketTTI = 0;
134 ueCb->isUlBurstActive = FALSE;
137 for ( count = 0;count < datIndInfo->numLch; count++ )
139 rbCb = ueCb->lCh[datIndInfo->lchData[count].lcId - 1].ulRbCb;
140 /* kw002.201 Removed allocation of pduInfo */
141 pduInfo = &(datIndInfo->lchData[count].pdu);
142 /* Fix for CR ccpu00138374,sometimes rbCb is NULL in UL path,
143 * So inorder to avoid the crash, added this preventive check
148 for(j = 0; j < pduInfo->numPdu; j++)
152 ODU_PUT_MSG_BUF(pduInfo->mBuf[j]);
159 SMrkUlPkt(pduInfo->mBuf[0]);
161 if ( rbCb->mode == RLC_MODE_UM )
163 /* kw005.201 added support for L2 Measurement */
165 rlcUmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
167 rlcUmmProcessPdus(gCb,rbCb,pduInfo);
170 else if (rbCb->mode == RLC_MODE_AM )
172 /* kw005.201 added support for L2 Measurement */
174 rlcAmmProcessPdus(gCb,rbCb, pduInfo, datIndInfo->ttiCnt);
176 rlcAmmProcessPdus(gCb,rbCb,pduInfo);
186 * Handler for sending Data Indication to the upper layer.
189 * This function is used to send re-assembled SDU to the upper layer.
191 * @param[in] gCb - RLC instance Control Block
192 * @param[in] rbCb - RB Control Block
193 * @param[in] sdu - SDU to be sent to upper layer
198 uint8_t rlcUtlSendUlDataToDu(RlcCb *gCb, RlcUlRbCb *rbCb, Buffer *sdu)
201 KwuDatIndInfo *datIndInfo = NULLP; /* Data Indication Information */
202 KwuDatIndInfo datIndInfoTmp;
204 RlcUlRrcMsgInfo *ulRrcMsgInfo = NULLP;
205 RlcUlUserDatInfo *ulUserDatInfo = NULLP;
206 uint16_t msgLen = 0, copyLen = 0;
210 /* Creating static memory for KwuDatIndInfo. #else will be
211 * removed once the testing is done on all platforms */
212 datIndInfo = &datIndInfoTmp;
213 if (datIndInfo == NULLP)
215 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed UEID:%d \
216 CELLID:%d", rbCb->rlcId.ueId, rbCb->rlcId.cellId);
217 ODU_PUT_MSG_BUF(sdu);
221 RLC_MEM_CPY(&(datIndInfo->rlcId),&(rbCb->rlcId),sizeof(CmLteRlcId));
222 /* Set the "isOutofSeq" flag for each packet
223 * If packets are in-sequence set flag as TRUE else FALSE */
224 datIndInfo->isOutOfSeq = rbCb->m.amUl.isOutOfSeq;
227 if(rbCb->rlcId.rbType == RB_TYPE_SRB)
229 /* Filling UL RRC Message Info if UL msg is not received on SRBs*/
230 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL,
231 ulRrcMsgInfo, sizeof(RlcUlRrcMsgInfo));
234 ulRrcMsgInfo->cellId = rbCb->rlcId.cellId;
235 ulRrcMsgInfo->ueIdx = rbCb->rlcId.ueId;
236 ulRrcMsgInfo->lcId = rbCb->lch.lChId;
237 ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
238 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL,
239 ulRrcMsgInfo->rrcMsg, msgLen);
240 if (ulRrcMsgInfo->rrcMsg)
242 ODU_COPY_MSG_TO_FIX_BUF(sdu, 0, msgLen, ulRrcMsgInfo->rrcMsg, (MsgLen *)©Len);
243 ulRrcMsgInfo->msgLen = msgLen;
245 /* Sending UL RRC Message transfeer to DU APP */
246 memset(&pst, 0, sizeof(Pst));
247 FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_UL_RRC_MSG_TRANS_TO_DU);
248 rlcSendUlRrcMsgToDu(&pst, ulRrcMsgInfo);
252 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for rrcMsg");
253 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulRrcMsgInfo, sizeof(RlcUlRrcMsgInfo));
259 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for ulRrcMsgInfo");
263 else if(rbCb->rlcId.rbType == RB_TYPE_DRB)
265 /* Filling UL User Data Info if UL msg is received on a DRB */
266 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo, sizeof(RlcUlUserDatInfo));
269 ulUserDatInfo->cellId = rbCb->rlcId.cellId;
270 ulUserDatInfo->ueIdx = rbCb->rlcId.ueId;
271 ulUserDatInfo->rbId = rbCb->rlcId.rbId;
272 ODU_GET_MSG_LEN(sdu, (MsgLen *)&msgLen);
273 RLC_ALLOC_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo->userData, msgLen);
274 if (ulUserDatInfo->userData)
276 ODU_COPY_MSG_TO_FIX_BUF(sdu, 0, msgLen, ulUserDatInfo->userData, (MsgLen *)©Len);
277 ulUserDatInfo->msgLen = msgLen;
279 DU_LOG("\nDEBUG --> RLC_UL -> DUAPP : UL DATA [DRB ID:%d]", ulUserDatInfo->rbId);
281 /* Sending UL RRC Message transfeer to DU APP */
282 memset(&pst, 0, sizeof(Pst));
283 FILL_PST_RLC_TO_DUAPP(pst, RLC_UL_INST, EVENT_UL_USER_DATA_TRANS_TO_DU);
284 rlcSendUlUserDataToDu(&pst, ulUserDatInfo);
288 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for user data");
289 RLC_FREE_SHRABL_BUF(RLC_MEM_REGION_UL, RLC_POOL, ulUserDatInfo, sizeof(RlcUlUserDatInfo));
295 DU_LOG("\nERROR --> RLC_UL: rlcUtlSendUlDataToDu: Memory allocation failed for ulUserDatInfo");
300 } /* rlcUtlSendUlDataToDu */
303 static Void dumpRLCUlRbInformation(RlcUlRbCb* ulRbCb)
305 if(ulRbCb->mode == RLC_MODE_UM)
308 uint32_t pdusInReceptionBuffer = 0;
309 uint32_t totalSegs = 0;
311 for(i = 0; i< RLC_RCV_BUF_BIN_SIZE; i++)
313 RlcUmRecBuf *recBuf = rlcUtlGetUmRecBuf(ulRbCb->m.umUl.recBufLst, i);
316 pdusInReceptionBuffer++;
317 totalSegs += (recBuf->segLst.count);
321 DU_LOG("\nDEBUG --> RLC_UL: UM UL UEID:%d CELLID:%d Reception Buffer size = %d Total segs = %d",
322 ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
324 else if(ulRbCb->mode == RLC_MODE_AM)
327 uint32_t pdusInReceptionBuffer = 0;
328 uint32_t totalSegs = 0;
329 uint32_t windSz = RLC_AM_GET_WIN_SZ(ulRbCb->m.amUl.snLen) << 1;
331 for(i = 0; i< windSz; i++)
333 RlcAmRecBuf *recBuf = rlcUtlGetRecBuf(ulRbCb->m.amUl.recBufLst, i);
336 pdusInReceptionBuffer++;
337 totalSegs += (recBuf->segLst.count);
341 DU_LOG("\nDEBUG --> RLC_UL: AM UL UEID:%d CELLID:%d Reception Buf size = %d total segs = %d",
342 ulRbCb->rlcId.ueId, ulRbCb->rlcId.cellId, pdusInReceptionBuffer, totalSegs);
346 Void DumpRLCUlDebugInformation(Void)
348 RlcCb* ulInst = rlcCb[0]; /* TODO : Check whether UL is 0 or 1 */
349 RlcUlCb* ulCb = ulInst->u.ulCb;
350 RlcUlUeCb *ueCb = NULLP;
352 /* Until no more ueCb is ueLstCp hash list get and delete ueCb */
353 while (ROK == cmHashListGetNext(&ulCb->ueLstCp,
358 for(i = 0; i< RLC_MAX_SRB_PER_UE; i++)
360 RlcUlRbCb* ulRbCb = ueCb->srbCb[i];
363 dumpRLCUlRbInformation(ulRbCb);
366 for(i = 0; i< RLC_MAX_DRB_PER_UE; i++)
368 RlcUlRbCb* ulRbCb = ueCb->drbCb[i];
371 dumpRLCUlRbInformation(ulRbCb);
379 * kwUtlFreeUlRbCb() function is split into two functions
380 * - rlcAmmFreeUlRbCb() ---> gp_amm_ul.c
381 * - rlcUmmFreeUlRbCb() ---> gp_umm_ul.c
382 * and placed in respective files mentioned above
387 /* kw005.201 added support for L2 Measurement */
393 * Handler for initialisation of measurement
395 * @param[in] gCb - RLC instance Control Block
400 S16 rlcUtlL2MeasUlInit(RlcCb *gCb)
404 gCb->u.ulCb->rlcL2Cb.rlcNumMeas=0;
405 for(cntr = 0; cntr < LKW_MAX_L2MEAS; cntr++)
407 memset(&(gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[cntr]), 0, sizeof(RlcL2MeasEvtCb));
409 gCb->u.ulCb->rlcL2Cb.rlcL2EvtCb[RLC_L2MEAS_UL_IP].measCb.measType = LKW_L2MEAS_UL_IP;
416 * Handler to calculate the Ul Ip throughput for a LCH
421 * @param[in] rbCb RB control block
422 * @param[in] pdu Pdu of LCH
427 Void rlcUtlCalUlIpThrPutIncTTI(RlcCb *gCb,RlcUlRbCb *rbCb,uint32_t ttiCnt)
429 volatile uint32_t startTime = 0;
432 SStartTask(&startTime, PID_RLC_IP_TPT_INCTTI);
434 DU_LOG("\nDEBUG --> RLC_UL : Log for ul ip throughput:"
435 "RB_MeasOn:%d ttiCnt :%ld UEID:%d CELLID:%d",
436 rbCb->rbL2Cb.measOn,ttiCnt,
440 DU_LOG("\nDEBUG --> RLC_UL : Log for ul ip throughput:"
441 "RB_MeasOn:%d ttiCnt :%d UEID:%d CELLID:%d",
442 rbCb->rbL2Cb.measOn,ttiCnt,
447 /*Check if UL IP throughput measurement is ON for this RB or not*/
448 if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb,rbCb))
450 if (TRUE == rbCb->ueCb->isUlBurstActive)
452 if (ttiCnt < rbCb->l2MeasIpThruput.prevTtiCnt)
454 /*Removed Error Print*/
456 if (rbCb->l2MeasIpThruput.prevTtiCnt != 0)
458 rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.timeSummation +=
459 (ttiCnt - rbCb->l2MeasIpThruput.prevTtiCnt);
463 rbCb->ueCb->firstPacketTTI = ttiCnt;
465 rbCb->l2MeasIpThruput.prevTtiCnt = ttiCnt;
469 rbCb->l2MeasIpThruput.prevTtiCnt = 0;
474 SStopTask(startTime, PID_RLC_IP_TPT_INCTTI);
475 } /* rlcUtlCalUlIpThrPutIncTTI */
482 * Handler to calculate the Ul Ip throughput for a LCH
487 * @param[in] rbCb RB control block
488 * @param[in] pdu Pdu of LCH
493 Void rlcUtlCalUlIpThrPut
501 MsgLen rlcSduSz = 0; /*Holds length of Rlc Sdu*/
502 volatile uint32_t startTime = 0;
505 SStartTask(&startTime, PID_RLC_IP_TPT_INCVOL);
507 /*Check if UL IP throughput measurement is ON for this RB or not*/
508 if(RLC_MEAS_IS_UL_IP_MEAS_ON_FOR_RB(gCb, rbCb) &&
509 (TRUE == rbCb->ueCb->isUlBurstActive) &&
510 (rbCb->ueCb->firstPacketTTI) &&
511 (ttiCnt != rbCb->ueCb->firstPacketTTI))
513 SFndLenMsg(pdu, &rlcSduSz);
515 rbCb->rbL2Cb.l2Sts[RLC_L2MEAS_UL_IP]->ulIpThruput.volSummation += rlcSduSz;
519 SStopTask(startTime, PID_RLC_IP_TPT_INCVOL);
520 } /* rlcUtlCalUlIpThrPut */
525 * @brief Handler for L2 Measurement timer expiry.
529 * This function is called when the l2 measurement timer expires.
530 * This function sends a consolidates the mesaurements taken during
531 * this time and sends the confirm .
533 * @param[in] measEvtCb Measurement Event Control Block.
540 S16 rlcUtlHdlL2TmrExp(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
543 #ifdef LTE_L2_MEAS_RLC
547 /* Clean up the RB data structures */
548 if((measEvtCb->measCb.measType & LKW_L2MEAS_ACT_UE) &&
549 (measEvtCb->measCb.val.nonIpThMeas.numSamples))
551 measCb = &measEvtCb->measCb;
553 for(qciIdx = 0; qciIdx < measCb->val.nonIpThMeas.numQci;qciIdx++)
555 measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.numActvUe +=
556 rlcCb.rlcL2Cb.numActUe[measCb->val.nonIpThMeas.qci[qciIdx]];
557 measCb->val.nonIpThMeas.measData[measCb->val.nonIpThMeas.qci[qciIdx]].actUe.sampOc++;
559 measEvtCb->val.nonIpThMeas.measCb.numSamples--;
560 rlcStartTmr(gCb, (PTR)measEvtCb, EVENT_RLC_L2_TMR);
565 rlcUtlSndUlL2MeasCfm(gCb, measEvtCb);
568 } /* rlcUtlHdlL2TmrExp */
571 * @brief Handler for Sending L2 Measurement confirm.
575 * This function sends a consolidates the mesaurements taken during
576 * this time and sends the confirm .
578 * @param[in] measEvtCb Measurement Event Control Block.
585 S16 rlcUtlSndUlL2MeasCfm(RlcCb *gCb,RlcL2MeasEvtCb *measEvtCb)
589 RlcL2MeasCfmEvt measCfmEvt;
593 /* Discard new changes starts */
596 /* Discard new changes ends */
598 /* kw006.201 ccpu00120058 emoved 64 bit compilation warning */
600 DU_LOG("\nDEBUG --> RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%ld))", measEvtCb->transId);
602 DU_LOG("\nDEBUG --> RLC_UL : rlcUtlSndUlL2MeasCfm(transId(%d))", measEvtCb->transId);
605 /* Clean up the RB data structures */
606 measCb = &measEvtCb->measCb;
608 memset(&measCfmEvt, 0, sizeof(RlcL2MeasCfmEvt));
609 measCfmEvt.transId = measEvtCb->transId;
611 measCfmEvt.measType = measCb->measType;
612 measCfmEvt.status.status = LCM_PRIM_OK;
613 measCfmEvt.status.reason = LCM_REASON_NOT_APPL;
615 if( measCb->measType & LKW_L2MEAS_UL_IP)
617 RlcL2MeasCbUeMeasInfo *pUeInfoLstCb = measCb->val.ipThMeas.ueInfoLst;
618 RlcL2MeasCfmUeInfoLst *pUeInfoLstCfm = measCfmEvt.val.ipThMeas.ueInfoLst;
619 for(cntr = 0;(cntr < measCb->val.ipThMeas.numUes) && (cntr < gCb->genCfg.maxUe);cntr++)
621 pUeInfoLstCfm[cfmIdx].numCfm = 0;
622 if (pUeInfoLstCb[cntr].isValid == TRUE)
624 pUeInfoLstCfm[cfmIdx].ueId = pUeInfoLstCb[cntr].ueId;
625 pUeInfoLstCfm[cfmIdx].cellId = pUeInfoLstCb[cntr].cellId;
627 for(qciIdx = 0; qciIdx < pUeInfoLstCb[cntr].numQci; qciIdx++)
629 qci = pUeInfoLstCb[cntr].qci[qciIdx];
630 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].qci = qci;
632 if(measCb->measType & LKW_L2MEAS_UL_IP)
634 ulDataVol = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation;
635 ulTime = pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation;
638 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = 0;
642 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut = (ulDataVol / ulTime);
644 /* Converting it to kbps */
645 pUeInfoLstCfm[cfmIdx].measCfm[pUeInfoLstCfm[cfmIdx].numCfm].val.ipThrput.ulIpThPut *= 8;
648 /* Reset the values after reporting to Application */
649 pUeInfoLstCb[cntr].measData[qci].ulIpThruput.volSummation = 0;
650 pUeInfoLstCb[cntr].measData[qci].ulIpThruput.timeSummation = 0;
652 pUeInfoLstCfm[cfmIdx].numCfm++;
657 measCfmEvt.val.ipThMeas.numUes = cfmIdx;
659 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, &measCfmEvt);
661 } /* rlcUtlSndUlL2MeasCfm */
664 * @brief Handler for Sending Negative confirm .
668 * This function is called when the l2 measurement cannot be started
669 * This function sends negative confirm for all the requests
671 * @param[in] gCb - RLC instance control block
672 * @param[in] measReqEvt Measurement Req Structure
673 * @param[in] measCfmEvt Confirmation to be sent to layer manager
680 S16 rlcUtlSndUlL2MeasNCfm(RlcCb *gCb,RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
683 RlcMiLkwL2MeasCfm(&gCb->genCfg.lmPst, measCfmEvt);
685 } /* kwUtlSndL2MeasNCfm */
687 #ifdef LTE_L2_MEAS_RLC
689 * @brief Validates the measurement request parameters.
693 * Function :rlcUtlValidateL2Meas
695 * @param[in] measReqEvt L2 measurement request received from layer manager.
696 * @param[out] measCfmEvt L2 measurement confirm to be prepared.
697 * @param[out] lChId List of LCh for the given Ue corresponding to QCIs
698 given in measurement request.
699 * @param[out] numLCh Number of LCh in array lChId.
702 S16 rlcUtlValidateL2Meas
704 RlcL2MeasReqEvt *measReqEvt,
705 RlcL2MeasCfmEvt *measCfmEvt,
721 uint8_t lsbNibble = 0;
722 uint8_t msbNibble = 0;
723 uint8_t numFaild = 0;
728 measType = measReqEvt->measReq.measType;
729 /* Check for the range of measType */
730 /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
731 if((measType == 0x00) ||
734 measCfmEvt->transId = measReqEvt->transId;
735 measCfmEvt->measType = measType;
736 measCfmEvt->status.status = LCM_PRIM_NOK;
737 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
740 /*User can either request for Active UE,*
741 *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
742 lsbNibble = measType & 0x0F;
743 msbNibble = measType & 0xF0;
745 if( (lsbNibble != 0) && (msbNibble != 0) )
747 measCfmEvt->transId = measReqEvt->transId;
748 measCfmEvt->measType = measType;
749 measCfmEvt->status.status = LCM_PRIM_NOK;
750 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
754 /* Check for total maximum number of Measurement Control Block */
755 if(rlcCb.rlcL2Cb.rlcNumMeas >= LKW_MAX_L2MEAS )
757 measCfmEvt->transId = measReqEvt->transId;
758 measCfmEvt->measType = measType;
759 measCfmEvt->status.status = LCM_PRIM_NOK;
760 measCfmEvt->status.reason = LKW_CAUSE_EXCEED_NUMMEAS;
764 /* Check that number of samples should be a non-zero value */
765 if(((measType & LKW_L2MEAS_ACT_UE) &&
766 (measReqEvt->measReq.val.nonIpThMeas.numSamples == 0)))
768 measCfmEvt->transId = measReqEvt->transId;
769 measCfmEvt->measType = measType;
770 measCfmEvt->status.status = LCM_PRIM_NOK;
771 measCfmEvt->status.reason = LKW_CAUSE_ZERO_NUMSAM;
774 /* Check that measurement period should be completely divisible *
775 * number of sample. */
776 if(((measType & LKW_L2MEAS_ACT_UE) &&
777 ((measReqEvt->measPeriod %
778 measReqEvt->measReq.val.nonIpThMeas.numSamples) != 0)))
780 measCfmEvt->transId = measReqEvt->transId;
781 measCfmEvt->measType = measType;
782 measCfmEvt->status.status = LCM_PRIM_NOK;
783 measCfmEvt->status.reason = LKW_CAUSE_INVALID_NUMSAM;
787 numQci = measReqEvt->measReq.val.nonIpThMeas.numQci;
788 qciVal = measReqEvt->measReq.val.nonIpThMeas.qci;
790 /* Check whether qci is configured or not */
791 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
793 qci = qciVal[qciIdx];
794 ret = cmHashListFind(&(rlcCb.rlcL2Cb.qciHlCp),
795 (uint8_t *)&qci, (uint16_t)sizeof(qci), 0, (PTR *)&rbCb);
798 measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
799 measCfmEvt->val.nonIpThMeas.numCfm++;
803 if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
805 measCfmEvt->status.status = LCM_PRIM_NOK;
806 measCfmEvt->status.reason = LKW_CAUSE_INVALID_QCI;
807 measCfmEvt->measType = measType;
808 measCfmEvt->transId = measReqEvt->transId;
812 for(qciIdx = 0; qciIdx < numQci; qciIdx++)
814 if(rlcCb.rlcL2Cb.measOn[qci] & measReqEvt->measReq.measType)
816 /* measurement is already ongoing */
817 measCfmEvt->status.status = LCM_PRIM_NOK;
818 measCfmEvt->status.reason = LKW_CAUSE_MEAS_ALREADY_ENA;
819 measCfmEvt->val.nonIpThMeas.measCfm[measCfmEvt->val.nonIpThMeas.numCfm].qci = qci;
820 measCfmEvt->measType = measType;
821 measCfmEvt->val.nonIpThMeas.numCfm++;
825 if(measCfmEvt->val.nonIpThMeas.numCfm > 0)
827 measCfmEvt->transId = measReqEvt->transId;
832 }/* rlcUtlValidateL2Meas */
835 S16 rlcUtlValidateIpThL2Meas(RlcL2MeasReqEvt *measReqEvt,RlcL2MeasCfmEvt *measCfmEvt)
838 uint8_t lsbNibble = 0;
839 uint8_t msbNibble = 0;
841 measType = measReqEvt->measReq.measType;
842 /* Check for the range of measType */
843 /* LKW_L2MEAS_DL_IP+ LKW_L2MEAS_UL_IP = 0x0030*/
844 if((measType == 0x00) ||
847 measCfmEvt->transId = measReqEvt->transId;
848 measCfmEvt->measType = measType;
849 measCfmEvt->status.status = LCM_PRIM_NOK;
850 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
853 /*User can either request for Active UE,*
854 *Dl delay, Dl discard, Uu Loss OR Dl ip throughput, Ul ip throughput. */
855 lsbNibble = measType & 0x0F;
856 msbNibble = measType & 0xF0;
858 if( (lsbNibble != 0) && (msbNibble != 0) )
860 measCfmEvt->transId = measReqEvt->transId;
861 measCfmEvt->measType = measType;
862 measCfmEvt->status.status = LCM_PRIM_NOK;
863 measCfmEvt->status.reason = LKW_CAUSE_INVALID_MEASTYPE;
867 }/* rlcUtlValidateL2Meas */
871 * @brief Handler for resetting the RB data structures
875 * This function resets the RB data structure after the expiry of
878 * @param[in] measCb Measurement Control Block.
884 Void rlcUtlResetUlL2MeasInRlcRb(RlcCb *gCb,RlcL2MeasCb *measCb,uint8_t measType)
889 RlcUlUeCb *ueCb = NULL;
893 if (measCb->measType & LKW_L2MEAS_UL_IP)
895 for(ueIdx = 0; ueIdx < measCb->val.ipThMeas.numUes; ueIdx++)
897 if (measCb->val.ipThMeas.ueInfoLst[ueIdx].isValid == TRUE)
899 for (qciIdx =0; qciIdx < measCb->val.ipThMeas.ueInfoLst[ueIdx].numQci; qciIdx++)
901 if (measType & LKW_L2MEAS_UL_IP)
903 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.volSummation = 0;
904 measCb->val.ipThMeas.ueInfoLst[ueIdx].measData[qciIdx].ulIpThruput.timeSummation = 0;
908 if(ROK != rlcDbmFetchUlUeCb(gCb, measCb->val.ipThMeas.ueInfoLst[ueIdx].ueId,
909 measCb->val.ipThMeas.ueInfoLst[ueIdx].cellId, &ueCb))
914 for (rbIdx = 0; rbIdx < RLC_MAX_DRB_PER_UE; rbIdx++)
916 if (ueCb->drbCb[rbIdx])
918 ueCb->drbCb[rbIdx]->rbL2Cb.measOn &= ~measType;
924 } /* rlcUtlResetUlL2MeasInRlcRb */
928 * @brief Handler for storing address of MeasData in rbCb at right index
932 * This function is called when LM sends measReq message to RLC.
942 Void rlcUtlPlcMeasDatInL2Sts(RlcL2Cntr *measData,RlcL2MeasRbCb *rbL2Cb,uint8_t measType)
944 /* We should check the number of measType in the request. This can be done
945 * by looking at each bit in the measType. Also store the measData in the
946 * correct index of l2Sts in RbCb.
949 if(measType & LKW_L2MEAS_ACT_UE)
951 rbL2Cb->l2Sts[RLC_L2MEAS_ACT_UE] = measData;
953 if(measType & LKW_L2MEAS_UU_LOSS)
955 rbL2Cb->l2Sts[RLC_L2MEAS_UU_LOSS] = measData;
957 if(measType & LKW_L2MEAS_DL_IP )
959 rbL2Cb->l2Sts[RLC_L2MEAS_DL_IP] = measData;
961 if(measType & LKW_L2MEAS_UL_IP)
963 rbL2Cb->l2Sts[RLC_L2MEAS_UL_IP] = measData;
965 if(measType & LKW_L2MEAS_DL_DISC)
967 rbL2Cb->l2Sts[RLC_L2MEAS_DL_DISC] = measData;
969 if(measType & LKW_L2MEAS_DL_DELAY)
971 rbL2Cb->l2Sts[RLC_L2MEAS_DL_DELAY] = measData;
973 }/* End of rlcUtlPlcMeasDatInL2Sts */
974 #endif /* LTE_L2_MEAS */
978 * @brief Store the UL buffer in hashList
983 * Use the SN % binSize as key and store the received UL buffer
984 * @param[in] recBufLst List CP array
985 * @param[in] recBuf received buffer
986 * @param[in] sn sn of the received buffer
991 void rlcUtlStoreRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcSn sn)
995 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
996 recBuf->lnk.node = (PTR)recBuf;
997 cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1000 } /* rlcUtlStoreRecBuf */
1004 * @brief Retrieve the UL buffer from the list
1009 * Use the SN % binSize as key and retrieve the UL buffer
1010 * @param[in] recBufLst List CP array
1011 * @param[in] sn sn of the received buffer
1016 RlcAmRecBuf* rlcUtlGetRecBuf(CmLListCp *recBufLst, RlcSn sn)
1019 CmLListCp *recBufLstCp;
1020 RlcAmRecBuf *recBuf;
1021 CmLList *node = NULLP;
1023 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
1025 recBufLstCp = &recBufLst[hashKey];
1026 CM_LLIST_FIRST_NODE(recBufLstCp, node);
1029 recBuf = (RlcAmRecBuf *) node->node;
1030 if(recBuf->amHdr.sn == sn)
1034 CM_LLIST_NEXT_NODE(recBufLstCp, node);
1037 } /* rlcUtlGetRecBuf */
1040 * @brief Delete the UL buffer from the list
1045 * Use the SN % binSize as key and retrieve the UL buffer
1046 * @param[in] recBufLst List CP array
1047 * @param[in] sn sn of the received buffer
1052 void rlcUtlDelRecBuf(CmLListCp *recBufLst, RlcAmRecBuf *recBuf, RlcCb *gCb)
1055 CmLListCp *recBufLstCp;
1057 hashKey = (recBuf->amHdr.sn % RLC_RCV_BUF_BIN_SIZE );
1059 recBufLstCp = &recBufLst[hashKey];
1060 cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1061 RLC_FREE(gCb, recBuf, sizeof(RlcAmRecBuf));
1064 } /* rlcUtlDelRecBuf */
1068 * @brief Store the UL buffer in hashList
1072 * Use the SN % binSize as key and store the received UL buffer
1073 * @param[in] recBufLst List CP array
1074 * @param[in] recBuf received buffer
1075 * @param[in] sn sn of the received buffer
1079 void rlcUtlStoreUmRecBuf(CmLListCp *recBufLst, RlcUmRecBuf *recBuf, RlcSn sn)
1083 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
1084 recBuf->lnk.node = (PTR)recBuf;
1085 cmLListAdd2Tail(&(recBufLst[hashKey]), &recBuf->lnk);
1088 } /* rlcUtlStoreUmRecBuf */
1092 * @brief Retrieve the UL buffer from the list
1096 * Use the SN % binSize as key and retrieve the UL buffer
1097 * @param[in] recBufLst List CP array
1098 * @param[in] sn sn of the received buffer
1102 RlcUmRecBuf* rlcUtlGetUmRecBuf(CmLListCp *recBufLst, RlcSn sn)
1105 CmLListCp *recBufLstCp;
1106 RlcUmRecBuf *recBuf;
1107 CmLList *node = NULLP;
1109 hashKey = (sn % RLC_RCV_BUF_BIN_SIZE );
1111 recBufLstCp = &recBufLst[hashKey];
1112 CM_LLIST_FIRST_NODE(recBufLstCp, node);
1115 recBuf = (RlcUmRecBuf *) node->node;
1116 if(recBuf->umHdr.sn == sn)
1120 CM_LLIST_NEXT_NODE(recBufLstCp, node);
1123 } /* rlcUtlGetUmRecBuf */
1127 * @brief Delete the UM Mode UL buffer from the list
1131 * Use the SN % binSize as key and retrieve the UL buffer
1133 * @param[in] *recBufLst List CP array
1134 * @param[in] *recBuf Received buffer
1138 void rlcUtlDelUmRecBuf(RlcCb *gCb, CmLListCp *recBufLst, RlcUmRecBuf *recBuf)
1141 CmLListCp *recBufLstCp;
1143 hashKey = (recBuf->sn % RLC_RCV_BUF_BIN_SIZE );
1144 recBufLstCp = &recBufLst[hashKey];
1145 cmLListDelFrm(recBufLstCp, &recBuf->lnk);
1146 RLC_FREE(gCb, recBuf, sizeof(RlcUmRecBuf));
1149 } /* rlcUtlDelUmRecBuf */
1151 /********************************************************************30**
1153 **********************************************************************/