X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2F5gnrrlc%2Fkw_tmm_dl.c;fp=src%2F5gnrrlc%2Fkw_tmm_dl.c;h=730f3656b404acc3c2fbdaec77402ffc628cc29d;hb=5625a52ad68f6ad93684e68bbbdbaef0d462cf9a;hp=0000000000000000000000000000000000000000;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925;p=o-du%2Fl2.git diff --git a/src/5gnrrlc/kw_tmm_dl.c b/src/5gnrrlc/kw_tmm_dl.c new file mode 100755 index 000000000..730f3656b --- /dev/null +++ b/src/5gnrrlc/kw_tmm_dl.c @@ -0,0 +1,575 @@ +/******************************************************************************* +################################################################################ +# Copyright (c) [2017-2019] [Radisys] # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +################################################################################ +*******************************************************************************/ + +/********************************************************************** + + Name: LTE-RLC Layer + + Type: C file + + Desc: Source code for RLC Transparent mode assembly and + reassembly.This file contains following functions + + --kwTmmQSdu + --kwTmmSndToLi + --kwTmmRcvFrmLi + --kwTmmReEstablish + + File: kw_tmm_dl.c + +**********************************************************************/ +static const char* RLOG_MODULE_NAME="TMM"; +static int RLOG_MODULE_ID=2048; +static int RLOG_FILE_ID=200; +/** + * @file kw_tmm_dl.c + * @brief RLC Transparent Mode module +*/ + +/* header (.h) include files */ +#include "envopt.h" /* environment options */ +#include "envdep.h" /* environment dependent */ +#include "envind.h" /* environment independent */ + +#include "gen.h" /* general */ +#include "ssi.h" /* system services */ +#include "cm5.h" /* common timer defines */ +#include "cm_tkns.h" /* common tokens defines */ +#include "cm_mblk.h" /* common memory allocation library defines */ +#include "cm_llist.h" /* common link list defines */ +#include "cm_hash.h" /* common hash list defines */ +#include "cm_lte.h" /* common LTE defines */ +#include "lkw.h" /* LKW defines */ +#include "ckw.h" /* CKW defines */ +#include "kwu.h" /* KWU defines */ +#include "rgu.h" /* RGU defines */ +#include "kw_env.h" /* RLC environment options */ + +#include "kw.h" /* RLC defines */ +#include "kw_err.h" /* RLC defines */ +#include "kw_udx.h" +#include "kw_dl.h" + +/* extern (.x) include files */ +#include "gen.x" /* general */ +#include "ssi.x" /* system services */ + +#include "cm5.x" /* common timer library */ +#include "cm_tkns.x" /* common tokens */ +#include "cm_mblk.x" /* common memory allocation */ +#include "cm_llist.x" /* common link list */ +#include "cm_hash.x" /* common hash list */ +#include "cm_lte.x" /* common LTE includes */ +#include "cm_lib.x" /* common memory allocation library */ +#include "lkw.x" /* LKW */ +#include "ckw.x" /* CKW */ +#include "kwu.x" /* KWU */ +#include "rgu.x" /* RGU */ + +#include "kw.x" +#include "kw_udx.x" +#include "kw_dl.x" + +#define KW_MODULE (KW_DBGMASK_TM | KW_DBGMASK_DL) + +PRIVATE Void kwTmmSndStaRsp ARGS((KwCb *gCb, KwDlRbCb *rbCb, + MsgLen bo, KwuDatReqInfo *datReqInfo)); +extern U32 rgMacGT ; +/** @addtogroup tmmode */ +/*@{*/ + +/** + * @brief + * Handler to queue the SDU in the SDU queue and update BO and report it to + * the lower layer. + * + * @details + * This function is used to queue the received SDU in the SDU queue + * maintained in the radio bearer control block. After queuing the SDU, BO + * is updated and is reported to the lower layer. + * + * @param[in] rbCb RB control block. + * @param[in] datReqInfo Data Request Information. + * @param[in] mBuf SDU Buffer. + * + * @return S16 + * -# ROK + * -# RFAILED + */ +#ifdef ANSI +PUBLIC Void kwTmmQSdu +( +KwCb *gCb, +KwDlRbCb *rbCb, +KwuDatReqInfo *datReqInfo, +Buffer *mBuf +) +#else +PUBLIC Void kwTmmQSdu(gCb,rbCb,datReqInfo,mBuf) +KwCb *gCb; +KwDlRbCb *rbCb; +KwuDatReqInfo *datReqInfo; +Buffer *mBuf; +#endif +{ + KwSdu *sdu; + + TRC2(kwTmmQSdu) + + + KW_ALLOC(gCb,sdu,sizeof(KwSdu)); +#if (ERRCLASS & ERRCLS_ADD_RES) + if ( sdu == NULLP ) + { + RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId, + "Memory Allocation failed UEID:%d CELLID:%d", + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RETVOID; + } +#endif /* ERRCLASS & ERRCLS_ADD_RES */ +#ifdef CCPU_OPT + if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH || + rbCb->lch.lChType == CM_LTE_LCH_PCCH ) + { + sdu->mode.tm.sfn = datReqInfo->tm.tmg.sfn; + sdu->mode.tm.subframe = datReqInfo->tm.tmg.subframe; +#ifdef EMTC_ENABLE + if(rbCb->lch.lChType == CM_LTE_LCH_PCCH) + { + sdu->mode.tm.pnb = datReqInfo->pnb; + } +#endif + } + else + { + sdu->mode.tm.rnti = datReqInfo->tm.rnti; + } +#endif + sdu->arrTime = rgMacGT; + SFndLenMsg(mBuf,&sdu->sduSz); + sdu->mBuf = mBuf; + + cmLListAdd2Tail(&(rbCb->m.tm.sduQ), &(sdu->lstEnt)); + sdu->lstEnt.node = (PTR)sdu; + + kwTmmSndStaRsp(gCb, rbCb, sdu->sduSz, datReqInfo); + RETVOID; +} + +/** +* @brief +* Handler to form a pdu and send it to the lower layer. +* +* @details +* This function forms one pdu from the first SDU in the SDU queue and sends +* it to the lower layer. +* +* @param[in] gCb RLC Instance Control Block +* @param[in] rbCb RB control block. +* @param[in] staInd Status Indication of common logical channel +* +* @return S16 +* -# ROK +* -# RFAILED +*/ +#ifdef ANSI +PUBLIC Void kwTmmSndToLi +( +KwCb *gCb, +SuId suId, +KwDlRbCb *rbCb, +RguCStaIndInfo *staInd +) +#else +PUBLIC Void kwTmmSndToLi(gCb, suId, rbCb, staInd) +KwCb *gCb; +SuId suId; +KwDlRbCb *rbCb; +RguCStaIndInfo *staInd; +#endif +{ + CmLList *node; /* Current Link List Node */ + KwSdu *sdu; /* SDU */ + RguCDatReqInfo *cDatReqInfo; /* Data Request Information */ + S16 timeDiff = 0; + Ticks curTime = 0; + + TRC2(kwTmmSndToLi) + + + CM_LLIST_FIRST_NODE(&(rbCb->m.tm.sduQ), + node); + + /* (Sfn,subframe) at which the message should be transmitted is + * validated with alloted (sfn,subframe)in the MAC layer */ + while (node != NULLP) + { + sdu = (KwSdu *)(node->node); + if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH || + rbCb->lch.lChType == CM_LTE_LCH_PCCH ) + { + U16 sfn, subframe; + /* MS_FIX: syed sfn is of 10 bytes rather than 8 */ +#ifdef EMTC_ENABLE + /* As part of CATM feature cross subframe scheduling is implemented , so there is some delta(currently 2) + between MPDCCH and PDSCH,RLC expects cell crntTime of transmission of control dlsf, so one extra + information is provided in staInd, so that sfn,subframe should calculate from paging Timing information + in case of EMTC paging, instead of transId */ + if(staInd->isEmtcPaging) + { + sfn = staInd->pagingTimingInfo.sfn; + subframe = staInd->pagingTimingInfo.subframe; + } + else +#endif + { + sfn = (staInd->transId >> 8) & 0x3FF; + subframe = staInd->transId & 0xFF; + } + + /* Table + * tm.subframe - current subframe + * 0,sfn 7,sfn-1 + * 4,sfn 1,sfn + * 5,sfn 2,sfn + * 9,sfn 6,sfn + */ + /* MS_FIX: syed Incorrect sfn determination. + * Take care of SFN wraparound. TODO: It is better for RLC + * not to be aware of SCH DELTAs. So we should look for + * sending actual transmission time to RLC. */ + if ((subframe + TFU_DELTA) >= 10) + { + sfn = (sfn + 1)%1024; + } + + if ((sdu->mode.tm.sfn != sfn) || + (sdu->mode.tm.subframe != ((subframe+TFU_DELTA)%10))) + { + node = node->next; + RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, + "Releasing SDU of RNTI = %d for RNTI = %d UEID:%d CELLID:%d", + sdu->mode.tm.rnti, + staInd->rnti, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, + "sfn %d subframe %d UEID:%d CELLID:%d", + sfn, + subframe, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt); + KW_FREE_BUF(sdu->mBuf); + KW_FREE(gCb, sdu, sizeof(KwSdu)); + } + else + { + break; + } + } + else + { + curTime = rgMacGT; + if (curTime < sdu->arrTime) + { + timeDiff = (10240 - sdu->arrTime) + curTime; + } + else + { + timeDiff = curTime - sdu->arrTime; + } + RLOG_ARG4(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId, + "TMM: TmSdu Sta Indication received for Rnti %d Sdu Rnti %d " + " UEID:%d CELLID:%d", + staInd->rnti, + sdu->mode.tm.rnti, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RLOG_ARG4(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId, + "TMM: TmSdu Sta Indication received : timeDiff %d SduQCnt %lu" + " UEID:%d CELLID:%d", + timeDiff, + rbCb->m.tm.sduQ.count, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + if (timeDiff > 40) + { + /* Memory leak needs to be fixed */ + node = node->next; + RLOG_ARG3(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId, + " timeDiff greater than 40, so deleting the Sdu %u " + " UEID:%d CELLID:%d", + sdu->mode.tm.rnti, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + cmLListDelFrm(&(rbCb->m.tm.sduQ), &sdu->lstEnt); + KW_FREE_BUF(sdu->mBuf); + KW_FREE(gCb, sdu, sizeof(KwSdu)); + continue; + } + + if (sdu->mode.tm.rnti != staInd->rnti) + { + /* Memory leak needs to be fixed */ + node = node->next; + RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, + "TMM: Searching for Rnti %d Skipping Sdu for Rnti %d" + " UEID:%d CELLID:%d", + staInd->rnti, + sdu->mode.tm.rnti, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, + " timeDiff %d sdu->arrTime %d" + " UEID:%d CELLID:%d", + timeDiff, + sdu->arrTime, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RLOG_ARG4(L_DEBUG,DBG_RBID,rbCb->rlcId.rbId, + "curTime %d SduQCnt %lu and continuing" + " UEID:%d CELLID:%d", + curTime, + rbCb->m.tm.sduQ.count, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + continue; + } + else + { + RLOG_ARG3(L_DEBUG, DBG_RBID,rbCb->rlcId.rbId, + "TMM: TmSdu found %u UEID:%d CELLID:%d", + sdu->mode.tm.rnti, + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + break; + } + } + + } + if ( node == NULLP ) + { + RLOG_ARG2(L_ERROR,DBG_RBID,rbCb->rlcId.rbId, + "SDU not found TM Queue is empty UEID:%d CELLID:%d", + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RETVOID; + } + sdu = (KwSdu *)node->node; + + KW_ALLOC_SHRABL_BUF(gCb->u.dlCb->rguDlSap[suId].pst.region, + gCb->u.dlCb->rguDlSap[suId].pst.pool, + cDatReqInfo,(Size)sizeof(RguCDatReqInfo)); +#if (ERRCLASS & ERRCLS_ADD_RES) + if ( cDatReqInfo == NULLP ) + { + RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId, + "Memory Allocation failed UEID:%d CELLID:%d", + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RETVOID; + } +#endif /* ERRCLASS & ERRCLS_ADD_RES */ +#ifdef CCPU_OPT + if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH || + rbCb->lch.lChType == CM_LTE_LCH_PCCH ) + { + cDatReqInfo->u.timeToTx.sfn = sdu->mode.tm.sfn; + cDatReqInfo->u.timeToTx.subframe = sdu->mode.tm.subframe; +#ifdef EMTC_ENABLE + if(rbCb->lch.lChType == CM_LTE_LCH_PCCH) + { + cDatReqInfo->pnb = sdu->mode.tm.pnb; + } +#endif + } + else + { + cDatReqInfo->u.rnti = sdu->mode.tm.rnti; + } +#endif + cDatReqInfo->pdu = sdu->mBuf; + cDatReqInfo->transId = rbCb->transId; + cDatReqInfo->cellId = rbCb->rlcId.cellId; + cDatReqInfo->lcId = rbCb->lch.lChId; + cDatReqInfo->lcType = rbCb->lch.lChType; + + /* kw005.201 ccpu00117318, updating the statistics */ + gCb->genSts.bytesSent += sdu->sduSz; + gCb->genSts.pdusSent++; + + kwUtlIncrementKwuStsSduTx(gCb->u.dlCb->kwuDlSap + rbCb->kwuSapId); + + /* remove SDU from queue */ + sdu->mBuf = NULLP; + cmLListDelFrm(&(rbCb->m.tm.sduQ), + &sdu->lstEnt); + KW_FREE(gCb,sdu, sizeof(KwSdu)); + + /* If trace flag is enabled send the trace indication */ + if(gCb->init.trc == TRUE) + { + /* Populate the trace params */ + kwLmmSendTrc(gCb,EVTRGUCDATREQ, NULLP); + } + KwLiRguCDatReq (&(gCb->u.dlCb->rguDlSap[suId].pst), + gCb->u.dlCb->rguDlSap[suId].spId, + cDatReqInfo); + + RETVOID; +} + +/** + * + * @brief + * Handler to process the re-establishment request received from the upper + * layer. + * + * @details + * This function empties the SDU queue for the RB in the downlink. + * + * @param[in] gCb RLC Instance Control Block + * @param[in] rbCb RB control block. + * + * @return S16 + * -# ROK + */ +#ifdef ANSI +PUBLIC Void kwDlTmmReEstablish +( +KwCb *gCb, +KwDlRbCb *rbCb +) +#else +PUBLIC Void kwDlTmmReEstablish(gCb,rbCb) +KwCb *gCb; +KwDlRbCb *rbCb; +#endif +{ + TRC2(kwDlTmmReEstablish) + + +#ifdef LTE_L2_MEAS_RLC + kwUtlEmptySduQ(gCb, rbCb, &rbCb->m.tm.sduQ); +#else + kwUtlEmptySduQ(gCb,&rbCb->m.tm.sduQ); +#endif + + RETVOID; +} +/** + * + * @brief + * Handler to send Status Response to the lower layer. + * + * @details + * This function is used to the BO to the lower layer after receiving a data + * request from the upper layer. + * + * @param[in] gCb RLC Instance Control Block + * @param[in] rbCb RB control block. + * @param[in] bo Buffer Occupancy + * @param[in] datReqInfo Data Request Information. + * + * @return S16 + * -# ROK + * -# RFAILED + */ + +#ifdef ANSI +PRIVATE Void kwTmmSndStaRsp +( +KwCb *gCb, +KwDlRbCb *rbCb, +MsgLen bo, +KwuDatReqInfo *datReqInfo +) +#else +PRIVATE Void kwTmmSndStaRsp(rbCb,bo,datReqInfo) +KwCb *gCb; +KwDlRbCb *rbCb; +MsgLen bo; +KwuDatReqInfo *datReqInfo; +#endif +{ + RguCStaRspInfo *staRspInfo; /* Status Response Information */ + KwRguSapCb *rguSap; /* SAP Information */ + + TRC3(kwTmmSndStaRsp) + + + rguSap = &(gCb->u.dlCb->rguDlSap[rbCb->rguSapId]); + + KW_ALLOC_SHRABL_BUF(gCb->u.dlCb->rguDlSap[rbCb->rguSapId].pst.region, + gCb->u.dlCb->rguDlSap[rbCb->rguSapId].pst.pool, + staRspInfo,sizeof(RguCStaRspInfo)); +#if (ERRCLASS & ERRCLS_ADD_RES) + if ( staRspInfo == NULLP ) + { + RLOG_ARG2(L_FATAL,DBG_RBID,rbCb->rlcId.rbId, + "Memory Allocation failed UEID:%d CELLID:%d", + rbCb->rlcId.ueId, + rbCb->rlcId.cellId); + RETVOID; + } +#endif /* ERRCLASS & ERRCLS_ADD_RES */ + staRspInfo->bo = bo; + staRspInfo->cellId = rbCb->rlcId.cellId; + staRspInfo->lcId = rbCb->lch.lChId; + staRspInfo->lcType = rbCb->lch.lChType; +#ifdef CCPU_OPT + if ( rbCb->lch.lChType == CM_LTE_LCH_BCCH || + rbCb->lch.lChType == CM_LTE_LCH_PCCH ) + { + staRspInfo->u.timeToTx.sfn = datReqInfo->tm.tmg.sfn; + staRspInfo->u.timeToTx.subframe = datReqInfo->tm.tmg.subframe; +#ifdef EMTC_ENABLE + if(rbCb->lch.lChType == CM_LTE_LCH_PCCH) + { + staRspInfo->emtcDiReason = datReqInfo->emtcDiReason; + staRspInfo->pnb = datReqInfo->pnb; + } +#endif + } + else if ( rbCb->lch.lChType == CM_LTE_LCH_CCCH ) + { + staRspInfo->u.rnti = datReqInfo->tm.rnti; + } +#endif + + /* If trace flag is enabled send the trace indication */ + if(gCb->init.trc == TRUE) + { + /* Populate the trace params */ + kwLmmSendTrc(gCb,EVTRGUCSTARSP, NULLP); + } + + KwLiRguCStaRsp(&rguSap->pst,rguSap->spId,staRspInfo); + + RETVOID; +} + +#ifdef _cplusplus +} +#endif +/*@}*/ +/********************************************************************30** + End of file +**********************************************************************/