X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2F5gnrmac%2Frg_l2m.c;fp=src%2F5gnrmac%2Frg_l2m.c;h=2018b9b1b44afcffa98eed1871a360d0e8d0d052;hb=5625a52ad68f6ad93684e68bbbdbaef0d462cf9a;hp=0000000000000000000000000000000000000000;hpb=59f84608ec15c016958a6e0e0ddd813f376c0925;p=o-du%2Fl2.git diff --git a/src/5gnrmac/rg_l2m.c b/src/5gnrmac/rg_l2m.c new file mode 100755 index 000000000..2018b9b1b --- /dev/null +++ b/src/5gnrmac/rg_l2m.c @@ -0,0 +1,678 @@ +/******************************************************************************* +################################################################################ +# 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-MAC layer + + Type: C source file + + Desc: C source code for L2 Measurements in MAC + + File: rg_l2m.c + +**********************************************************************/ + +/** @file rg_l2m.c +@brief This file implements the schedulers main access to MAC layer code. +*/ + +/* header include files -- defines (.h) */ +#include "envopt.h" /* environment options */ +#include "envdep.h" /* environment dependent */ +#include "envind.h" /* environment independent */ +#include "gen.h" /* general layer */ +#include "ssi.h" /* system service interface */ +#include "cm_hash.h" /* common hash list */ +#include "cm_llist.h" /* common linked list library */ +#include "cm_err.h" /* common error */ +#include "cm_lte.h" /* common LTE */ +#include "lrg.h" +#include "crg.h" +#include "rgr.h" +#include "rgu.h" +#include "tfu.h" +#include "rg_env.h" +#include "rg_err.h" +#include "rg_sch_inf.h" +#include "rg.h" + +/* header/extern include files (.x) */ +#include "gen.x" /* general layer typedefs */ +#include "ssi.x" /* system services typedefs */ +#include "cm5.x" /* common timers */ +#include "cm_hash.x" /* common hash list */ +#include "cm_lib.x" /* common library */ +#include "cm_llist.x" /* common linked list */ +#include "cm_mblk.x" /* memory management */ +#include "cm_tkns.x" /* common tokens */ +#include "cm_lte.x" /* common tokens */ +#include "rgu.x" /* RGU types */ +#include "tfu.x" /* TFU types */ +#include "lrg.x" /* layer management typedefs for MAC */ +#include "rgr.x" /* layer management typedefs for MAC */ +#include "crg.x" /* layer management typedefs for MAC */ +#include "rg_sch_inf.x" /* typedefs for Scheduler */ +#include "rg_prg.x" /* typedefs for PRG interface */ +#include "rg.x" /* MAC types */ + +#ifdef LTE_L2_MEAS +static const char* RLOG_MODULE_NAME="MAC"; +static int RLOG_FILE_ID=183; +static int RLOG_MODULE_ID=4096; +#endif + +/* local defines */ +#ifdef LTE_L2_MEAS +PRIVATE S16 rgL2mInsertMeasCb ARGS(( + RgCellCb *cell, + RgL2MeasCb *measCb, + RgInfL2MeasReq *measInfo )); + +PRIVATE RgL2MeasCb * rgL2mAllocMeasCb ARGS(( + RgCellCb *cell, + RgInfL2MeasReq *measInfo, + RgErrInfo *err)); + +/* Function definitions */ + +/** @brief This function creates the measCb + * + * @details + * + * Function: rgL2mCreateMeasCb + * Processing steps: + * - Check the measType + * - Create measCb for every qci + * + * @param [in] RgCellCb *cell + * @param [in] RgInfL2MeasReq *measInfo + * @param [in] U8 measType + * @param [out] RgErrInfo *err + * @return S16 + * -# ROK + * -# RFAILED + * + */ +#ifdef ANSI +PUBLIC S16 rgL2mCreateMeasCb +( +RgCellCb *cell, +RgInfL2MeasReq *measInfo, +U8 measType, +RgErrInfo *err +) +#else +PUBLIC S16 rgL2mCreateMeasCb(cell, measInfo, measType, err) +RgCellCb *cell; +RgInfL2MeasReq *measInfo; +U8 measType; +RgErrInfo *err; +#endif +{ + // Inst inst = cell->macInst - RG_INST_START; + U32 idx; + RgL2MeasCb *measCb = NULLP; + U8 qciVal = 0; + + UNUSED(measType); + UNUSED(err); + + TRC3(rgL2mCreateMeasCb) + + if ((measCb = rgL2mAllocMeasCb(cell, measInfo, err)) == NULLP) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId,"Allocation of RgL2MeasCb failed"); + RETVALUE(RFAILED); + } + //Memcpy is already done in rgL2mAllocMeasCb + /*cmMemcpy((U8 *)&measCb->measReq, (CONSTANT U8 *)measInfo,\ + sizeof(RgInfL2MeasReq));*/ + rgL2mInsertMeasCb(cell, measCb, measInfo); + measCb->measReq.timePrd = measInfo->timePrd; + + if(measInfo->timePrd == 0) + { + cell->sndL2Meas = FALSE; + } + + for(idx = 0; idx < measInfo->t.prbReq.numQci; idx++) + { + if(measInfo->timePrd == 0) + { + qciVal = measInfo->t.prbReq.qci[idx]; + cell->qciArray[qciVal].qci = qciVal; + } + cell->qciArray[measInfo->t.prbReq.qci[idx]].mask = TRUE; + } + RETVALUE(ROK); +} /* rgL2mCreateMeasCb */ + + +/** + * @brief Layer Manager Measurement request handler. + * + * @details + * + * Function : rgL2mMeasReq + * + * This function handles measurement request received at MAC + * from the Scheduler. + * -# Measurement request will be stored in the list in descending order of + * there time period. + * + * @param[in] Pst *pst, the post structure + * @param[in] RgInfL2MeasReq *measInfo, the measurement request structure + * @param[out] RgErrInfo *err, error information + * @return S16 + * -# ROK + **/ +#ifdef ANSI +PUBLIC S16 rgL2mMeasReq +( +RgCellCb *cell, +RgInfL2MeasReq *measInfo, +RgErrInfo *err +) +#else +PUBLIC S16 rgL2mMeasReq(cell, measInfo, err) +RgCellCb *cell; +RgInfL2MeasReq *measInfo; +RgErrInfo *err; +#endif +{ + S16 ret=RFAILED; + + TRC3(rgL2mMeasReq) + /* Creaet MeasCb Insert in cell->l2mList and return*/ + if ( (ret = rgL2mCreateMeasCb(cell, measInfo, + LRG_L2MEAS_AVG_PRB_PER_QCI_UL, err)) != ROK) + { + /* Clear Downlink MeasCb created Above If exists*/ + RETVALUE(ret); + } + RETVALUE(ROK); +} /* rgL2mMeasReq */ +/** @brief This function sends the measurement confirm + * from mac to scheduler + * + * @details + * + * Function: rgSndL2MeasCfm + * + * @param [in] RgCellCb *cell + * @param [in] RgInfL2MeasCfm *measCfm + */ +#ifdef ANSI +PRIVATE Void rgSndL2MeasCfm +( +RgCellCb *cell, +RgInfL2MeasCfm *measCfm +) +#else +PRIVATE Void rgSndL2MeasCfm (cell, measCfm) +RgCellCb *cell; +RgInfL2MeasCfm *measCfm; +#endif +{ + Pst pst; + Inst macInst = cell->macInst - RG_INST_START; + TRC3(rgSndL2MeasCfm) + + cmMemset((U8 *)&pst, 0, sizeof(Pst)); + rgGetPstToInst(&pst,macInst, cell->schInstMap.schInst); + RgMacSchL2Meas(&pst, measCfm); + + RETVOID; +}/* rgSndL2MeasCfm */ + +/** @brief This function sends the measurement stop confirm + * from mac to scheduler + * + * @details + * + * Function: rgSndL2MeasStopCfm + * + * @param [in] RgCellCb *cell + * @param [in] RgInfL2MeasCfm *measCfm + */ +#ifdef ANSI +PRIVATE Void rgSndL2MeasStopCfm +( +RgCellCb *cell, +RgInfL2MeasCfm *measCfm +) +#else +PRIVATE Void rgSndL2MeasStopCfm (cell, measCfm) +RgCellCb *cell; +RgInfL2MeasCfm *measCfm; +#endif +{ + Pst pst; + Inst macInst = cell->macInst - RG_INST_START; + + TRC3(rgSndL2MeasStopCfm) + cmMemset((U8 *)&pst, 0, sizeof(Pst)); + rgGetPstToInst(&pst,macInst, cell->schInstMap.schInst); + RgMacSchL2MeasStop(&pst, measCfm); + + RETVOID; +}/* rgSndL2MeasStopCfm */ + +/** + * @brief L2 Measurement request handler.This function shall be called by + * scheduler to calculate average PRB usage Per Qci in Uplink + * + * @details + * + * Function : RgSchMacL2MeasReq + * + * @param[in] Pst *pst, the post structure + * @param[in] RgInfL2MeasReq *measInfo, L2 Measurement req structure + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 RgSchMacL2MeasReq +( +Pst *pst, /* post structure */ +RgInfL2MeasReq *measInfo /* Meas Req Info */ +) +#else +PUBLIC S16 RgSchMacL2MeasReq(pst, measInfo) +Pst *pst; /* post structure */ +RgInfL2MeasReq *measInfo; /* Meas Req Info */ +#endif +{ + Inst inst; + RgCellCb *cellCb = NULLP; + RgErrInfo err; + S16 ret = ROK; + RgInfL2MeasCfm measCfm; + + TRC3(RgSchMacL2MeasReq) + + + RG_IS_INST_VALID(pst->dstInst); + inst = pst->dstInst - RG_INST_START; + cellCb = rgCb[inst].cell; + /* Get the cell using cellId */ + if ((cellCb == NULLP) || + (cellCb->cellId != measInfo->cellId)) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,measInfo->cellId,"unable to get the cellCb"); + RETVALUE(RFAILED); + } + /* Call L2M Function to store Meas req */ + ret = rgL2mMeasReq(cellCb, measInfo, &err); + if (ret != ROK) + { + cmMemset((U8 *)&measCfm, 0, sizeof(RgInfL2MeasCfm)); + measCfm.transId = measInfo->transId; + measCfm.cellId = measInfo->cellId; + measCfm.measType = measInfo->measType; + measCfm.cfm.reason = LCM_REASON_INVALID_PAR_VAL; + measCfm.cfm.status = LCM_PRIM_NOK; + rgSndL2MeasCfm(cellCb, &measCfm); + RLOG_ARG2(L_ERROR,DBG_CELLID,measInfo->cellId, + "Meas req Failed errType(%d) errCause(%d)", + err.errType, err.errCause); + RETVALUE(RFAILED); + } + RETVALUE(ret); +} /* -- RgSchMacL2MeasReq-- */ + +/** + * @brief L2 Measurement request handler.This function shall be called by + * sch to to stop l2 measurement in MAC, + * + * @details + * + * Function : RgSchMacL2MeasStopReq + * + * @param[in] Pst *pst, the post structure + * @param[in] RgInfL2MeasReq *measInfo, L2 Measurement req structure + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 RgSchMacL2MeasStopReq +( +Pst *pst, /* post structure */ +RgInfL2MeasStopReq *measInfo /* Meas Req Info */ +) +#else +PUBLIC S16 RgSchMacL2MeasStopReq(pst, measInfo) +Pst *pst; /* post structure */ +RgInfL2MeasStopReq *measInfo; /* Meas Req Info */ +#endif +{ + S16 ret = ROK; + CmLList *node = NULLP; + RgL2MeasCb *measCb = NULLP; + U8 idx; + U8 qciVal; + Inst inst; + RgCellCb *cellCb = NULLP; + + RgInfL2MeasCfm measCfm; + + TRC3(RgSchMacL2MeasStopReq) + + + RG_IS_INST_VALID(pst->dstInst); + inst = pst->dstInst - RG_INST_START; + cellCb = rgCb[inst].cell; + /* Get the cell using cellId */ + if ((cellCb == NULLP) || + (cellCb->cellId != measInfo->cellId)) + { + + RLOG_ARG0(L_ERROR,DBG_CELLID,measInfo->cellId, + "Unable to get the cellCb"); + RETVALUE(RFAILED); + } + node = cellCb->l2mList.first; + while(node != NULLP) + { + measCb = (RgL2MeasCb *)(node)->node; + node = (node)->next; + /*L2 Meas off for qci in cell */ + for(idx = 0; idx < measCb->measReq.t.prbReq.numQci; idx++) + { + qciVal = measCb->measReq.t.prbReq.qci[idx]; + cellCb->qciArray[qciVal].mask = FALSE; + } + cmLListDelFrm(&cellCb->l2mList, &measCb->measLnk); + rgFreeSBuf(inst,(Data**)&measCb, sizeof(RgL2MeasCb)); + } + cmMemset((U8 *)&measCfm, 0, sizeof(RgInfL2MeasCfm)); + measCfm.transId = measInfo->transId; + measCfm.cellId = measInfo->cellId; + measCfm.measType = measInfo->measType; + measCfm.cfm.status = LCM_PRIM_OK; + rgSndL2MeasStopCfm(cellCb, &measCfm); + RETVALUE(ret); +} /* -- RgSchMacL2MeasStopReq-- */ + +/** + * @brief L2 Measurement request handler.This function shall be called by + * scheduler for sending L2 meas + * + * @details + * + * Function : RgSchMacL2MeasSendReq + * + * @param[in] Pst *pst, the post structure + * @param[in] RgInfL2MeasReq *measInfo, L2 Measurement req structure + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 RgSchMacL2MeasSendReq +( +Pst *pst, /* post structure */ +RgInfL2MeasSndReq *measInfo /* Meas Req Info */ +) +#else +PUBLIC S16 RgSchMacL2MeasSendReq(pst, measInfo) +Pst *pst; /* post structure */ +RgInfL2MeasSndReq *measInfo; /* Meas Req Info */ +#endif +{ + Inst inst; + RgCellCb *cellCb = NULLP; + S16 ret = ROK; + + TRC3(RgSchMacL2MeasSendReq) + + + RG_IS_INST_VALID(pst->dstInst); + inst = pst->dstInst - RG_INST_START; + cellCb = rgCb[inst].cell; + /* Get the cell using cellId */ + if ((cellCb == NULLP) || + (cellCb->cellId != measInfo->cellId)) + { + + RLOG_ARG0(L_ERROR,DBG_CELLID,measInfo->cellId, + "Unable to get the cellCb"); + RETVALUE(RFAILED); + } + /*set sndL2Meas as applicatoin sent l2 meas info request*/ + cellCb->sndL2Meas = TRUE; + + RETVALUE(ret); +}/*RgSchMacL2MeasSendReq*/ + +/** @brief This function inserts the MeasCb in to data base + * + * @details + * + * Function: rgL2mInsertMeasCb + * + * @param [in] RgCellCb *cell + * @param [in] RgL2MeasCb *measCb + * @param [in] RgInfMeasReq *measInfo + * @return S16 + * -# ROK + * -# RFAILED + */ +#ifdef ANSI +PRIVATE S16 rgL2mInsertMeasCb +( +RgCellCb *cell, +RgL2MeasCb *measCb, +RgInfL2MeasReq *measInfo +) +#else +PRIVATE S16 rgL2mInsertMeasCb(cell, measCb, measInfo) +RgCellCb *cell; +RgL2MeasCb *measCb; +RgInfL2MeasReq *measInfo; +#endif +{ + CmLList *lnk, *node; + RgL2MeasCb *oldMeasCb; + U16 diffTime; + + TRC3(rgL2mInsertMeasCb) + + /* + * 1. Check if l2mList has any entries. + * 2. If yes + * 1. Take the first entrie's time period and find the diff with + * cell->crntTime. + * 2. If the diff is > measInfo->timePeriod then insert before this + * entry. + * 3. Else take the next entry in list + * 4. If reached without adding to list . Append at the end of list. + * 3. If no entries in l2mList add at the first. + */ + lnk = cell->l2mList.first; + + node = &measCb->measLnk; + node->node = (PTR)measCb; + while(lnk != NULLP ) + { + oldMeasCb = (RgL2MeasCb *)lnk->node; + diffTime = (oldMeasCb->measReq.timePrd - + (RG_CALC_SF_DIFF(cell->crntTime, oldMeasCb->startTime))); + if (diffTime > measInfo->timePrd) + { + cell->l2mList.crnt = lnk; + cmLListInsCrnt(&(cell->l2mList), node); + RETVALUE(ROK); + } + else + { + lnk = lnk->next; + } + } /* End of While */ + + cmLListAdd2Tail(&(cell->l2mList), node); + RETVALUE(ROK); +} /* rgL2mInsertMeasCb */ + +/** @brief This function allocates memory from the heap + * + * @details + * + * Function: rgL2mAllocMeasCb + * + * @param [in] RgCellCb *cell + * @param [in] RgInfL2MeasReq *measInfo + * @param [out] RgErrInfo *err + * @return RgSchL2MeasCb * + */ +#ifdef ANSI +PRIVATE RgL2MeasCb * rgL2mAllocMeasCb +( +RgCellCb *cell, +RgInfL2MeasReq *measInfo, +RgErrInfo *err +) +#else +PRIVATE RgL2MeasCb * rgL2mAllocMeasCb(cell, measInfo, err) +RgCellCb *cell; +RgInfL2MeasReq *measInfo; +RgErrInfo *err; +#endif +{ + RgL2MeasCb *measCb = NULLP; + Inst inst = cell->macInst - RG_INST_START; + + TRC3(rgL2mAllocMeasCb) + + if((rgAllocSBuf(inst,(Data **)&(measCb), + sizeof(RgL2MeasCb))) == RFAILED) + { + RLOG_ARG0(L_ERROR,DBG_CELLID,cell->cellId, + "Allocation of RgL2MeasCb failed"); + err->errType = RGERR_L2M_MEASREQ; + err->errCause = RGERR_RAM_MEM_EXHAUST; + RETVALUE(NULLP); + } + cmMemcpy((U8 *)&measCb->measReq, (U8 *)measInfo, sizeof(RgInfL2MeasReq)); + RGCPYTIMEINFO(cell->crntTime, measCb->startTime); + + RETVALUE(measCb); +} /* rgL2mAllocMeasCb */ + + +/** + * @brief This function calculates the measurement for measType + * LRG_L2MEAS_AVG_PRB_PER_QCI_UL and send the end result to the + * MAC Scheduler. + * + * @details + * + * Function : rgL2Meas + * + * @param[in] RgCellCb *cell + * @return S16 + * -# ROK + * -# RFAILED + **/ +#ifdef ANSI +PUBLIC S16 rgL2Meas +( +RgCellCb *cell +) +#else +PUBLIC S16 rgL2Meas(cell) +RgCellCb *cell; +#endif +{ + CmLList *node = NULLP; + RgL2MeasCb *measCb = NULLP; + RgInfL2MeasCfm measCfm; + U8 idx = 0; + U8 qciVal = 0; + U32 measPrd; /*LTE_L2_MEAS_PHASE2*/ + CmLteTimingInfo crntTime; + Inst inst = cell->macInst - RG_INST_START; + + TRC3(rgL2Meas) + + node = cell->l2mList.first; + + while(node != NULLP) + { + measCb = (RgL2MeasCb *)node->node; + node = node->next; + crntTime = cell->crntTime; + + if(cell->crntTime.sfn == 0 && (cell->crntTime.subframe % RG_NUM_SUB_FRAMES) == 0) + { + measCb->sfnCycle++; + } + + measPrd = RG_CALC_SFN_SF_DIFF(cell->crntTime, + measCb->sfnCycle, measCb->startTime); + + /*LTE_L2_MEAS_PHASE2*/ + if (cell->sndL2Meas || measPrd == measCb->measReq.timePrd) + { + cmMemset((U8 *)&measCfm, 0, sizeof(RgInfL2MeasCfm)); + for(idx = 0; idx < measCb->measReq.t.prbReq.numQci; idx++) + { + qciVal = measCb->measReq.t.prbReq.qci[idx]; + measCfm.u.prbCfm.prbUsage[idx].qciValue = qciVal; + + measCfm.transId = measCb->measReq.transId; + measCfm.measType = measCb->measReq.measType; + measCfm.cellId = measCb->measReq.cellId; + + measCfm.u.prbCfm.prbUsage[idx].prbUsage = + cell->qciArray[qciVal].prbCount; + + cell->qciArray[qciVal].prbCount = 0; + measCfm.u.prbCfm.numQci++; + if(measCb->measReq.timePrd > 0) + { + cell->qciArray[qciVal].mask = FALSE; + } + } + rgSndL2MeasCfm(cell, &measCfm); + + if(measCb->measReq.timePrd > 0) + { + cmLListDelFrm(&cell->l2mList, &measCb->measLnk); + rgFreeSBuf(inst,(Data**)&measCb, sizeof(RgL2MeasCb)); + } + else /*if meas period is 0 then do not delette meascb , just reset l2 cntrs value to 0*/ + { + measCb->startTime = crntTime; + measCb->measReq.timePrd = 0; + cell->sndL2Meas = FALSE; + } + continue; + } + } + RETVALUE(ROK); +} /* rgL2MEas */ + +#endif /* LTE_L2_MEAS */ +/********************************************************************** + + End of file +**********************************************************************/