From: lal.harshita Date: Wed, 9 Aug 2023 18:59:00 +0000 (+0530) Subject: [Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-523] Timer based KPI reporting X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F94%2F11594%2F5;p=o-du%2Fl2.git [Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-523] Timer based KPI reporting Change-Id: I5cdf0530457612f31c8200b2ffcabba979b92b9c Signed-off-by: lal.harshita --- diff --git a/src/5gnrmac/mac.h b/src/5gnrmac/mac.h index 647299f6d..a24535823 100644 --- a/src/5gnrmac/mac.h +++ b/src/5gnrmac/mac.h @@ -287,6 +287,9 @@ uint8_t MacProcUlSchInfo(Pst *pst, UlSchedInfo *ulSchedInfo); uint8_t MacProcSchRachRsrcRsp(Pst *pst, SchRachRsrcRsp *schRachRsrcRsp); uint8_t MacProcDlPageAlloc(Pst *pst, DlPageAlloc *dlPageAlloc); uint8_t MacProcSchCellDeleteRsp(Pst *pst, SchCellDeleteRsp *schCellDeleteRsp); + +uint8_t MacProcSchStatsRsp(Pst *pst, SchStatsRsp *schStatsRsp); +uint8_t MacProcSchStatsInd(Pst *pst, SchStatsInd *schStatsInd); #endif /********************************************************************** End of file diff --git a/src/5gnrmac/mac_cfg_hdl.c b/src/5gnrmac/mac_cfg_hdl.c index fee5f4f77..1fb207e6b 100644 --- a/src/5gnrmac/mac_cfg_hdl.c +++ b/src/5gnrmac/mac_cfg_hdl.c @@ -63,6 +63,14 @@ MacDuSliceRecfgRspFunc macDuSliceRecfgRspOpts[] = packDuMacSliceRecfgRsp /* packing for light weight loosly coupled */ }; +MacDuStatsRspFunc macDuStatsRspOpts[] = +{ + packDuMacStatsRsp, /* packing for loosely coupled */ + DuProcMacStatsRsp, /* packing for tightly coupled */ + packDuMacStatsRsp /* packing for light weight loosly coupled */ +}; + + /** * @brief Layer Manager Configuration request handler for Scheduler * @@ -1014,6 +1022,166 @@ uint8_t MacProcDlBroadcastReq(Pst *pst, MacDlBroadcastReq *dlBroadcastReq) } return ret; } + +/** + * @brief Mac process the statistics Req received from DUAPP + * + * @details + * + * Function : MacProcStatsReq + * + * This function process the statistics request from duapp + * + * @param[in] Pst *pst + * @param[in] StatsReq *statsReq + * @return int + * -# ROK + **/ +uint8_t MacProcStatsReq(Pst *pst, MacStatsReq *macStatsReq) +{ + uint8_t macStatsIdx = 0, schStatsIdx = 0; + uint8_t ret = RFAILED; + bool measTypeInvalid = false; + Pst schPst; + SchStatsReq *schStatsReq = NULLP; + CauseOfResult cause; + + if(macStatsReq) + { + DU_LOG("\nINFO --> MAC : Received Statistics Request from DU_APP"); + + MAC_ALLOC(schStatsReq, sizeof(SchStatsReq)); + if(schStatsReq == NULLP) + { + DU_LOG("\nERROR --> MAC : MacProcStatsReq: Failed to allocate memory"); + cause = RESOURCE_UNAVAILABLE; + } + else + { + schStatsReq->numStats = 0; + for(macStatsIdx=0; macStatsIdx < macStatsReq->numStats; macStatsIdx++) + { + /* Checking each measurement type to send only SCH related + * measurement config to SCH + * This will be useful in future when some measurement type will + * be configured for SCH and rest for only MAC */ + switch(macStatsReq->statsList[macStatsIdx].type) + { + case MAC_DL_TOTAL_PRB_USAGE: + { + schStatsReq->statsList[schStatsIdx].type = SCH_DL_TOTAL_PRB_USAGE; + break; + } + case MAC_UL_TOTAL_PRB_USAGE: + { + schStatsReq->statsList[schStatsIdx].type = SCH_UL_TOTAL_PRB_USAGE; + break; + } + default: + { + DU_LOG("\nERROR --> MAC : MacProcStatsReq: Invalid measurement type [%d]", \ + macStatsReq->statsList[macStatsIdx].type); + measTypeInvalid = true; + } + } + + if(!measTypeInvalid) + { + schStatsReq->statsList[schStatsIdx].periodicity = macStatsReq->statsList[macStatsIdx].periodicity; + schStatsIdx++; + measTypeInvalid = false; + } + } + schStatsReq->numStats = schStatsIdx; + + /* If no measurement types are valid, it is failure scenario. + * Even if one measurement type is value, send to SCH */ + if(schStatsReq->numStats) + { + FILL_PST_MAC_TO_SCH(schPst, EVENT_STATISTICS_REQ_TO_SCH); + ret = SchMessageRouter(&schPst, (void *)schStatsReq); + } + else + { + cause = PARAM_INVALID; + } + } + MAC_FREE_SHRABL_BUF(pst->region, pst->pool, macStatsReq, sizeof(MacStatsReq)); + } + else + { + DU_LOG("\nERROR --> MAC : MacProcStatsReq(): Received Null pointer"); + cause = PARAM_INVALID; + } + + if(ret == RFAILED) + { + /* Send negative acknowledgment to DU APP */ + Pst rspPst; + MacStatsRsp *macStatsRsp = NULLP; + + MAC_ALLOC_SHRABL_BUF(macStatsRsp, sizeof(MacStatsRsp)); + if(macStatsRsp == NULLP) + { + DU_LOG("\nERROR --> MAC : Failed to allocate memory in MacProcSchStatsRsp"); + return RFAILED; + } + macStatsRsp->rsp = MAC_DU_APP_RSP_NOK; + macStatsRsp->cause = cause; + + memset(&rspPst, 0, sizeof(Pst)); + FILL_PST_MAC_TO_DUAPP(rspPst, EVENT_MAC_STATISTICS_RSP); + return (*macDuStatsRspOpts[rspPst.selector])(&rspPst, macStatsRsp); + } + return ret; +} + +/** + * @brief Mac process the statistics rsp received from sch. + * + * @details + * + * Function : MacProcSchStatsRsp + * + * This function process the statistics response received from sch + * + * @param[in] Pst *pst + * @param[in] SchStatsRsp *schStatsRsp + * @return int + * -# ROK + **/ +uint8_t MacProcSchStatsRsp(Pst *pst, SchStatsRsp *schStatsRsp) +{ + Pst rspPst; + MacStatsRsp *macStatsRsp = NULLP; + + if(schStatsRsp) + { + MAC_ALLOC_SHRABL_BUF(macStatsRsp, sizeof(MacStatsRsp)); + if(macStatsRsp == NULLP) + { + DU_LOG("\nERROR --> MAC : Failed to allocate memory in MacProcSchStatsRsp"); + return RFAILED; + } + if(schStatsRsp->rsp == RSP_OK) + macStatsRsp->rsp = MAC_DU_APP_RSP_OK; + else + { + macStatsRsp->rsp = MAC_DU_APP_RSP_NOK; + } + macStatsRsp->cause = schStatsRsp->cause; + + memset(&rspPst, 0, sizeof(Pst)); + FILL_PST_MAC_TO_DUAPP(rspPst, EVENT_MAC_STATISTICS_RSP); + (*macDuStatsRspOpts[rspPst.selector])(&rspPst, macStatsRsp); + + MAC_FREE(schStatsRsp, sizeof(SchStatsRsp)); + return ROK; + } + + return RFAILED; +} + /********************************************************************** End of file **********************************************************************/ diff --git a/src/5gnrmac/mac_msg_hdl.c b/src/5gnrmac/mac_msg_hdl.c index b0779d95b..6436a5354 100644 --- a/src/5gnrmac/mac_msg_hdl.c +++ b/src/5gnrmac/mac_msg_hdl.c @@ -38,6 +38,14 @@ MacCb macCb; +MacDuStatsIndFunc macDuStatsIndOpts[] = +{ + packDuMacStatsInd, /* packing for loosely coupled */ + DuProcMacStatsInd, /* packing for tightly coupled */ + packDuMacStatsInd /* packing for light weight loosly coupled */ +}; + + /******************************************************************* * * @brief Sends DL BO Info to SCH @@ -1057,6 +1065,66 @@ uint8_t MacProcSliceRecfgReq(Pst *pst, MacSliceRecfgReq *macSliceRecfgReq) return ret; } +/** + * @brief Mac process the statistics indication received from sch. + * + * @details + * + * Function : MacProcSchStatsInd + * + * This function process the statistics indication received from sch + * + * @param[in] Pst *pst + * @param[in] SchStatsInd *schStatsInd + * @return int + * -# ROK + **/ +uint8_t MacProcSchStatsInd(Pst *pst, SchStatsInd *schStatsInd) +{ + Pst indPst; + MacStatsInd *macStatsInd; + + DU_LOG("\nINFO --> MAC : MacProcSchStatsInd: Received Statistics Indication from SCH"); + + if(schStatsInd == NULLP) + { + DU_LOG("\nERROR --> MAC : MacProcSchStatsInd: NULL pointer :schStatsInd"); + return RFAILED; + } + + MAC_ALLOC_SHRABL_BUF(macStatsInd, sizeof(MacStatsInd)); + if(macStatsInd == NULLP) + { + DU_LOG("\nERROR --> MAC : Failed to allocate memory in MacProcSchStatsInd"); + return RFAILED; + } + + switch(schStatsInd->type) + { + case SCH_DL_TOTAL_PRB_USAGE: + { + macStatsInd->type = MAC_DL_TOTAL_PRB_USAGE; + break; + } + case SCH_UL_TOTAL_PRB_USAGE: + { + macStatsInd->type = MAC_UL_TOTAL_PRB_USAGE; + break; + } + default: + { + DU_LOG("\nERROR --> MAC : MacProcSchStatsInd: Invalud measurement type [%d]", schStatsInd->type); + MAC_FREE_SHRABL_BUF(MAC_MEM_REGION, MAC_POOL, macStatsInd, sizeof(MacStatsInd)); + return RFAILED; + } + } + macStatsInd->value = schStatsInd->value; + + memset(&indPst, 0, sizeof(Pst)); + FILL_PST_MAC_TO_DUAPP(indPst, EVENT_MAC_STATISTICS_IND); + return (*macDuStatsIndOpts[indPst.selector])(&indPst, macStatsInd); +} + /********************************************************************** End of file **********************************************************************/ diff --git a/src/5gnrmac/mac_msg_router.c b/src/5gnrmac/mac_msg_router.c index 1ed8fb3b0..37f07ae6e 100755 --- a/src/5gnrmac/mac_msg_router.c +++ b/src/5gnrmac/mac_msg_router.c @@ -187,6 +187,12 @@ void MacHdlDuappEvents(Pst *pst, Buffer *mBuf) break; } + case EVENT_MAC_STATISTICS_REQ: + { + /* Process Statistics Request */ + unpackMacStatsReq(MacProcStatsReq, pst, mBuf); + } + default: RG_FREE_MSG(mBuf); break; @@ -337,6 +343,9 @@ void callFlowMacActvTsk(Pst *pst) case EVENT_MAC_SLICE_RECFG_REQ: strcpy(message,"EVENT_MAC_SLICE_RECFG_REQ"); break; + case EVENT_MAC_STATISTICS_REQ: + strcpy(message,"EVENT_MAC_STATISTICS_REQ"); + break; default: strcpy(message,"Invalid Event"); break; @@ -466,6 +475,16 @@ void callFlowMacActvTsk(Pst *pst) strcpy(message,"EVENT_DL_REL_HQ_PROC"); break; } + case EVENT_STATISTICS_RSP_TO_MAC: + { + strcpy(message,"EVENT_STATISTICS_RSP_TO_MAC"); + break; + } + case EVENT_STATISTICS_IND_TO_MAC: + { + strcpy(message,"EVENT_STATISTICS_IND_TO_MAC"); + break; + } default: strcpy(message,"Invalid Event"); break; @@ -610,6 +629,16 @@ uint8_t MacMessageRouter(Pst *pst, void *msg) MacSchReleaseDlHarqProc(pst, (SchRlsHqInfo *)msg); break; } + case EVENT_STATISTICS_RSP_TO_MAC: + { + MacProcSchStatsRsp(pst, (SchStatsRsp *)msg); + break; + } + case EVENT_STATISTICS_IND_TO_MAC: + { + MacProcSchStatsInd(pst, (SchStatsInd *)msg); + break; + } default: { return RFAILED; diff --git a/src/5gnrrlc/rlc_tmr.c b/src/5gnrrlc/rlc_tmr.c index 0c7234e64..6e7f049fa 100755 --- a/src/5gnrrlc/rlc_tmr.c +++ b/src/5gnrrlc/rlc_tmr.c @@ -60,6 +60,7 @@ * @brief RLC Timer Module */ +#if 0 /** * @def RLC_TMR_CALCUATE_WAIT * @@ -81,6 +82,7 @@ (_wait) = 1; \ } \ } +#endif /* private function declarations */ static Void rlcBndTmrExpiry(PTR cb); @@ -113,7 +115,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) { RlcUmUl* umUl = &(((RlcUlRbCb *)cb)->m.umUl); /* kw005.201 Changed wait calculation ccpu00117634*/ - RLC_TMR_CALCUATE_WAIT(arg.wait, umUl->reAsmblTmrInt, gCb->genCfg.timeRes); + TMR_CALCUATE_WAIT(arg.wait, umUl->reAsmblTmrInt, gCb->genCfg.timeRes); arg.timers = &umUl->reAsmblTmr; arg.max = RLC_MAX_UM_TMR; @@ -123,7 +125,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) { RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl); /* kw005.201 Changed wait calculation ccpu00117634*/ - RLC_TMR_CALCUATE_WAIT(arg.wait, amUl->reAsmblTmrInt, gCb->genCfg.timeRes); + TMR_CALCUATE_WAIT(arg.wait, amUl->reAsmblTmrInt, gCb->genCfg.timeRes); arg.timers = &amUl->reAsmblTmr; arg.max = RLC_MAX_AM_TMR; @@ -133,7 +135,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) { RlcAmUl* amUl = &(((RlcUlRbCb *)cb)->m.amUl); /* kw005.201 Changed wait calculation ccpu00117634*/ - RLC_TMR_CALCUATE_WAIT(arg.wait, + TMR_CALCUATE_WAIT(arg.wait, amUl->staProhTmrInt, gCb->genCfg.timeRes); @@ -145,7 +147,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) { RlcAmDl* amDl = &(((RlcDlRbCb *)cb)->m.amDl); /* kw005.201 Changed wait calculation ccpu00117634*/ - RLC_TMR_CALCUATE_WAIT(arg.wait, + TMR_CALCUATE_WAIT(arg.wait, amDl->pollRetxTmrInt, gCb->genCfg.timeRes); @@ -157,7 +159,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) { RlcRguSapCb* rguSap = (RlcRguSapCb *)cb; /* kw005.201 Changed wait calculation ccpu00117634*/ - RLC_TMR_CALCUATE_WAIT(arg.wait, rguSap->bndTmrInt, gCb->genCfg.timeRes); + TMR_CALCUATE_WAIT(arg.wait, rguSap->bndTmrInt, gCb->genCfg.timeRes); arg.timers = &rguSap->bndTmr; arg.max = RLC_MAX_RGUSAP_TMR; @@ -169,7 +171,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) { measEvtCb = (RlcL2MeasEvtCb *)cb; /* kw005.201 Changed wait calculation ccpu00117634*/ - RLC_TMR_CALCUATE_WAIT(arg.wait, + TMR_CALCUATE_WAIT(arg.wait, measEvtCb->l2TmrCfg.val, gCb->genCfg.timeRes); @@ -181,7 +183,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) case EVENT_RLC_UE_THROUGHPUT_TMR: { RlcThpt *thptCb = (RlcThpt *)cb; - RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes); + TMR_CALCUATE_WAIT(arg.wait, ODU_UE_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes); arg.timers = &thptCb->ueTputInfo.ueThptTmr; arg.max = RLC_MAX_THPT_TMR; break; @@ -189,7 +191,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) case EVENT_RLC_UE_DELETE_TMR: { RlcUlUeCb *ulUeCb = (RlcUlUeCb*)cb; - RLC_TMR_CALCUATE_WAIT(arg.wait, RLC_UE_DELETE_WAIT_TIME, gCb->genCfg.timeRes); + TMR_CALCUATE_WAIT(arg.wait, RLC_UE_DELETE_WAIT_TIME, gCb->genCfg.timeRes); arg.timers = &ulUeCb->ueDeleteInfo.ueDelTmr; arg.max = RLC_MAX_UE_TMR; break; @@ -197,7 +199,7 @@ void rlcStartTmr(RlcCb *gCb, PTR cb, int16_t tmrEvnt) case EVENT_RLC_SNSSAI_THROUGHPUT_TMR: { RlcThpt *thptCb = (RlcThpt *)cb; - RLC_TMR_CALCUATE_WAIT(arg.wait, ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes); + TMR_CALCUATE_WAIT(arg.wait, ODU_SNSSAI_THROUGHPUT_PRINT_TIME_INTERVAL, gCb->genCfg.timeRes); arg.timers = &thptCb->snssaiTputInfo.snssaiThptTmr; arg.max = RLC_MAX_THPT_TMR; break; diff --git a/src/5gnrsch/sch.c b/src/5gnrsch/sch.c index 293add2bb..e4b5f1f91 100644 --- a/src/5gnrsch/sch.c +++ b/src/5gnrsch/sch.c @@ -46,6 +46,7 @@ #include "rg_sch_inf.x" /* typedefs for Scheduler */ #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #include "sch_fcfs.h" #include "sch_slice_based.h" @@ -150,22 +151,22 @@ uint8_t SchInstCfg(RgCfg *cfg, Inst dInst) schCb[inst].schInit.region = cfg->s.schInstCfg.genCfg.mem.region; schCb[inst].schInit.pool = cfg->s.schInstCfg.genCfg.mem.pool; - schCb[inst].genCfg.tmrRes = cfg->s.schInstCfg.genCfg.tmrRes; #ifdef LTE_ADV schCb[inst].genCfg.forceCntrlSrbBoOnPCel = cfg->s.schInstCfg.genCfg.forceCntrlSrbBoOnPCel; schCb[inst].genCfg.isSCellActDeactAlgoEnable = cfg->s.schInstCfg.genCfg.isSCellActDeactAlgoEnable; #endif schCb[inst].genCfg.startCellId = cfg->s.schInstCfg.genCfg.startCellId; + schCb[inst].schTimersInfo.tmrRes = cfg->s.schInstCfg.genCfg.tmrRes; /* Initialzie the timer queue */ - memset(&schCb[inst].tmrTq, 0, sizeof(CmTqType) * SCH_TQ_SIZE); + memset(&schCb[inst].schTimersInfo.tmrTq, 0, sizeof(CmTqType) * SCH_TQ_SIZE); /* Initialize the timer control point */ - memset(&schCb[inst].tmrTqCp, 0, sizeof(CmTqCp)); - schCb[inst].tmrTqCp.tmrLen = RGSCH_TQ_SIZE; + memset(&schCb[inst].schTimersInfo.tmrTqCp, 0, sizeof(CmTqCp)); + schCb[inst].schTimersInfo.tmrTqCp.tmrLen = SCH_TQ_SIZE; /* SS_MT_TMR needs to be enabled as schActvTmr needs instance information */ /* Timer Registration request to system services */ - if (ODU_REG_TMR_MT(schCb[inst].schInit.ent, dInst, (int)schCb[inst].genCfg.tmrRes, schActvTmr) != ROK) + if (ODU_REG_TMR_MT(schCb[inst].schInit.ent, dInst, (int)schCb[inst].schTimersInfo.tmrRes, schActvTmr) != ROK) { DU_LOG("\nERROR --> SCH : SchInstCfg(): Failed to " "register timer."); @@ -1422,6 +1423,10 @@ uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, \ return RFAILED; } } + + /* Update statistics of PRB usage if stats calculation is enabled */ + if(schCb[cell->instIdx].statistics.dlTotalPrbUsage) + prbAlloc->numPrbAlloc += numPrb; /* Update the remaining number for free PRBs */ removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb); @@ -1556,6 +1561,10 @@ uint8_t allocatePrbUl(SchCellCb *cell, SlotTimingInfo slotTime, \ } } + /* Update statistics of PRB usage if stats calculation is enabled */ + if(schCb[cell->instIdx].statistics.ulTotalPrbUsage) + prbAlloc->numPrbAlloc += numPrb; + /* Update the remaining number for free PRBs */ removeAllocatedPrbFromFreePrbList(&prbAlloc->freePrbBlockList, freePrbNode, *startPrb, numPrb); @@ -2534,6 +2543,231 @@ uint8_t SchProcPhrInd(Pst *pst, SchPwrHeadroomInd *schPhrInd) return ret; } +/******************************************************************* + * + * @brief Fill and send statistics response to MAC + * + * @details + * + * Function : SchSendStatsRspToMac + * + * Functionality: Fill and send statistics response to MAC + * + * @params[in] Inst inst, SchMacRsp result + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t SchSendStatsRspToMac(Inst inst, SchMacRsp result, CauseOfResult cause) +{ + Pst rspPst; + uint8_t ret = ROK; + SchStatsRsp *statsRsp; + + DU_LOG("\nINFO --> SCH : Filling statistics response"); + SCH_ALLOC(statsRsp, sizeof(SchStatsRsp)); + memset(statsRsp, 0, sizeof(SchStatsRsp)); + statsRsp->rsp = result; + statsRsp->cause = cause; + + /* Filling response post */ + memset(&rspPst, 0, sizeof(Pst)); + FILL_PST_SCH_TO_MAC(rspPst, inst); + rspPst.event = EVENT_STATISTICS_RSP_TO_MAC; + + ret = MacMessageRouter(&rspPst, (void *)statsRsp); + if(ret == RFAILED) + { + DU_LOG("\nERROR --> SCH : SchSendStatsRspToMac(): Failed to send Statistics Response"); + return ret; + } + return ret; +} + +/******************************************************************* + * + * @brief Processes Statistics Request from MAC + * + * @details + * + * Function : SchProcStatsReq + * + * Functionality: + * Processes Statistics Request from MAC + * + * @params[in] + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t SchProcStatsReq(Pst *pst, SchStatsReq *statsReq) +{ + uint8_t idx; + Inst inst = pst->dstInst - SCH_INST_START; + SchMacRsp rsp = RSP_OK; + CauseOfResult cause = SUCCESSFUL; + bool isDlTotlPrbUseCfgd = false, isUlTotlPrbUseCfgd = false; + + DU_LOG("\nINFO --> SCH : Received Statistics Request from MAC"); + + for(idx=0; idx < statsReq->numStats; idx++) + { + switch(statsReq->statsList[idx].type) + { + case SCH_DL_TOTAL_PRB_USAGE: + { + /* Check if duplicate configuration */ + if(schCb[inst].statistics.dlTotalPrbUsage) + { + DU_LOG("\nERROR --> SCH : SCH_DL_TOTAL_PRB_USAGE stats already configured"); + rsp = RSP_NOK; + cause = DUPLICATE_ENTRY; + } + + /* Allocate memory */ + SCH_ALLOC(schCb[inst].statistics.dlTotalPrbUsage, sizeof(TotalPrbUsage)); + if(!schCb[inst].statistics.dlTotalPrbUsage) + { + DU_LOG("\nERROR --> SCH : Memory allocation failed for dlTotalPrbUsage in \ + SchProcStatsReq()"); + rsp = RSP_NOK; + cause = RESOURCE_UNAVAILABLE; + break; + } + + /* Initialize */ + memset(schCb[inst].statistics.dlTotalPrbUsage, 0, sizeof(TotalPrbUsage)); + + /* Configure */ + schCb[inst].statistics.dlTotalPrbUsage->schInst = inst; + schCb[inst].statistics.dlTotalPrbUsage->periodicity = statsReq->statsList[idx].periodicity; + + /* Start timer */ + schStartTmr(&schCb[inst], (PTR)(schCb[inst].statistics.dlTotalPrbUsage), \ + EVENT_DL_TOTAL_PRB_USAGE_TMR, schCb[inst].statistics.dlTotalPrbUsage->periodicity); + + isDlTotlPrbUseCfgd = true; + break; + } + + case SCH_UL_TOTAL_PRB_USAGE: + { + /* Check if duplicate configuration */ + if(schCb[inst].statistics.ulTotalPrbUsage) + { + DU_LOG("\nERROR --> SCH : SCH_UL_TOTAL_PRB_USAGE stats already configured"); + rsp = RSP_NOK; + cause = DUPLICATE_ENTRY; + } + + /* Allocate memory */ + SCH_ALLOC(schCb[inst].statistics.ulTotalPrbUsage, sizeof(TotalPrbUsage)); + if(!schCb[inst].statistics.ulTotalPrbUsage) + { + DU_LOG("\nERROR --> SCH : Memory allocation failed for ulTotalPrbUsage in \ + SchProcStatsReq()"); + rsp = RSP_NOK; + cause = RESOURCE_UNAVAILABLE; + break; + } + + /* Initialize */ + memset(schCb[inst].statistics.ulTotalPrbUsage, 0, sizeof(TotalPrbUsage)); + + /* Configure */ + schCb[inst].statistics.ulTotalPrbUsage->schInst = inst; + schCb[inst].statistics.ulTotalPrbUsage->periodicity = statsReq->statsList[idx].periodicity; + + /* Start timer */ + schStartTmr(&schCb[inst], (PTR)(schCb[inst].statistics.ulTotalPrbUsage), \ + EVENT_UL_TOTAL_PRB_USAGE_TMR, schCb[inst].statistics.ulTotalPrbUsage->periodicity); + + isUlTotlPrbUseCfgd = true; + break; + } + default: + { + DU_LOG("\nERROR --> SCH : Invalid statistics type [%d]", statsReq->statsList[idx].type); + rsp = RSP_NOK; + cause = PARAM_INVALID; + } + } /* End of switch */ + + if(rsp == RSP_NOK) + { + /* If failed to configure any KPI, then clear configuration of other + * KPIs that were configured successfully as part of this statsReq */ + if(isDlTotlPrbUseCfgd) + { + if((schChkTmr((PTR)(schCb[inst].statistics.dlTotalPrbUsage), EVENT_DL_TOTAL_PRB_USAGE_TMR)) == FALSE) + { + schStopTmr(&schCb[inst], (PTR)(schCb[inst].statistics.dlTotalPrbUsage), EVENT_DL_TOTAL_PRB_USAGE_TMR); + } + SCH_FREE(schCb[inst].statistics.dlTotalPrbUsage, sizeof(TotalPrbUsage)); + } + + if(isUlTotlPrbUseCfgd) + { + if((schChkTmr((PTR)(schCb[inst].statistics.ulTotalPrbUsage), EVENT_UL_TOTAL_PRB_USAGE_TMR)) == FALSE) + { + schStopTmr(&schCb[inst], (PTR)(schCb[inst].statistics.ulTotalPrbUsage), EVENT_UL_TOTAL_PRB_USAGE_TMR); + } + SCH_FREE(schCb[inst].statistics.ulTotalPrbUsage, sizeof(TotalPrbUsage)); + } + break; + } + } /* End of FOR */ + + SCH_FREE(statsReq, sizeof(SchStatsReq)); + + SchSendStatsRspToMac(inst, rsp, cause); + + return ROK; +} /* End of SchProcStatsReq */ + +/******************************************************************* + * + * @brief Fill and send statistics indication to MAC + * + * @details + * + * Function : SchSendStatsIndToMac + * + * Functionality: Fill and send statistics indication to MAC + * + * @params[in] SCH Instance + * Measurement Type + * Measurement Value + * Size of value parameter + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t SchSendStatsIndToMac(Inst inst, SchMeasurementType measType, uint32_t value) +{ + Pst pst; + uint8_t ret = ROK; + SchStatsInd statsInd; + + DU_LOG("\nINFO --> SCH : Filling statistics indication"); + memset(&statsInd, 0, sizeof(SchStatsInd)); + statsInd.type = measType; + statsInd.value = value; + + /* Filling post structure */ + memset(&pst, 0, sizeof(Pst)); + FILL_PST_SCH_TO_MAC(pst, inst); + pst.event = EVENT_STATISTICS_RSP_TO_MAC; + + ret = MacMessageRouter(&pst, (void *)&statsInd); + if(ret == RFAILED) + { + DU_LOG("\nERROR --> SCH : SchSendStatsIndToMac(): Failed to send Statistics Indication"); + } + return ret; +} + + /********************************************************************** End of file **********************************************************************/ diff --git a/src/5gnrsch/sch.h b/src/5gnrsch/sch.h index 4feaa1828..74c45d882 100644 --- a/src/5gnrsch/sch.h +++ b/src/5gnrsch/sch.h @@ -47,7 +47,6 @@ #define NUM_DMRS_SYMBOLS 1 #define DMRS_ADDITIONAL_POS 0 #define SCH_DEFAULT_K1 1 -#define SCH_TQ_SIZE 10 #define SSB_IDX_SUPPORTED 1 #define CRC_FAILED 0 @@ -80,6 +79,8 @@ #define NUM_SCH_TYPE 2 /*Supported number of Scheduler Algorithm types*/ +#define SCH_TQ_SIZE 10 + typedef struct schDlHqProcCb SchDlHqProcCb; typedef struct schUlHqEnt SchUlHqEnt; typedef struct schRaReq SchRaReq; @@ -279,7 +280,6 @@ struct schDlHqEnt */ typedef struct schGenCb { - uint8_t tmrRes; /*!< Timer resolution */ uint8_t startCellId; /*!< Starting Cell Id */ #ifdef LTE_ADV bool forceCntrlSrbBoOnPCel; /*!< value 1 means force scheduling @@ -304,6 +304,7 @@ typedef struct schPrbAlloc { CmLListCp freePrbBlockList; /*!< List of continuous blocks for available PRB */ uint64_t prbBitMap[ MAX_SYMB_PER_SLOT][PRB_BITMAP_MAX_IDX]; /*!< BitMap to store the allocated PRBs */ + uint16_t numPrbAlloc; }SchPrbAlloc; /** @@ -601,6 +602,21 @@ typedef struct PdschCfg sib1PdschCfg; }SchSib1Cfg; +typedef struct dlTotalPrbUsage +{ + Inst schInst; + uint16_t numPrbUsedForTx; + uint16_t totalPrbAvailForTx; + uint16_t periodicity; + CmTimer periodTimer; +}TotalPrbUsage; + +typedef struct schStatistics +{ + TotalPrbUsage *dlTotalPrbUsage; + TotalPrbUsage *ulTotalPrbUsage; +}SchStatistics; + /** * @brief * Cell Control block per cell. @@ -646,6 +662,12 @@ typedef struct schCellCb uint8_t maxMsg3Tx; /* MAximum num of msg3 tx*/ }SchCellCb; +typedef struct schTimer +{ + CmTqCp tmrTqCp; /*!< Timer Task Queue Cntrl Point */ + CmTqType tmrTq[SCH_TQ_SIZE]; /*!< Timer Task Queue */ + uint8_t tmrRes; /*!< Timer resolution */ +}SchTimer; /** * @brief @@ -655,11 +677,11 @@ typedef struct schCb { TskInit schInit; /*!< Task Init info */ SchGenCb genCfg; /*!< General Config info */ - CmTqCp tmrTqCp; /*!< Timer Task Queue Cntrl Point */ - CmTqType tmrTq[SCH_TQ_SIZE]; /*!< Timer Task Queue */ + SchTimer schTimersInfo; /*!< Sch timer queues and resolution */ SchAllApis allApis[NUM_SCH_TYPE]; /*!schPucchInfo, 0, sizeof(SchPucchInfo)); } - //send msg to MAC + /* Send msg to MAC */ ret = sendUlSchInfoToMac(&ulSchedInfo, schInst); if(ret != ROK) { DU_LOG("\nERROR --> SCH : Sending UL Sch info from SCH to MAC failed"); } + /* Update UL statistics */ + if(schCb[schInst].statistics.ulTotalPrbUsage) + { + schCb[schInst].statistics.ulTotalPrbUsage->numPrbUsedForTx += schUlSlotInfo->prbAlloc.numPrbAlloc; + schCb[schInst].statistics.ulTotalPrbUsage->totalPrbAvailForTx += MAX_NUM_RB; + } + + /* Re-initialize UL Slot */ schInitUlSlot(schUlSlotInfo); return ret; } diff --git a/src/5gnrsch/sch_crc.c b/src/5gnrsch/sch_crc.c index 3730988a6..abd9f4def 100644 --- a/src/5gnrsch/sch_crc.c +++ b/src/5gnrsch/sch_crc.c @@ -24,6 +24,7 @@ #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" /** diff --git a/src/5gnrsch/sch_fcfs.c b/src/5gnrsch/sch_fcfs.c index edfad6659..09e2c64b1 100644 --- a/src/5gnrsch/sch_fcfs.c +++ b/src/5gnrsch/sch_fcfs.c @@ -41,6 +41,7 @@ File: sch_fcfs.c #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #include "sch_fcfs.h" #ifdef NR_DRX diff --git a/src/5gnrsch/sch_harq_dl.c b/src/5gnrsch/sch_harq_dl.c index 1ec31bc5e..f058cdc0d 100644 --- a/src/5gnrsch/sch_harq_dl.c +++ b/src/5gnrsch/sch_harq_dl.c @@ -24,6 +24,7 @@ #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #include "cm_llist.h" #ifdef NR_DRX diff --git a/src/5gnrsch/sch_harq_ul.c b/src/5gnrsch/sch_harq_ul.c index 343859a8a..c5433f9fe 100644 --- a/src/5gnrsch/sch_harq_ul.c +++ b/src/5gnrsch/sch_harq_ul.c @@ -24,6 +24,7 @@ #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #ifdef NR_DRX #include "sch_drx.h" diff --git a/src/5gnrsch/sch_msg_router.c b/src/5gnrsch/sch_msg_router.c index edb21b881..f31bd5d4e 100755 --- a/src/5gnrsch/sch_msg_router.c +++ b/src/5gnrsch/sch_msg_router.c @@ -42,6 +42,7 @@ #include "rgr.x" /* layer management typedefs for MAC */ #include "rg_sch_inf.x" /* typedefs for Scheduler */ #include "sch.h" +#include "sch_tmr.h" #ifdef CALL_FLOW_DEBUG_LOG /** @@ -176,6 +177,11 @@ void callFlowSchMsgRouter(Pst *pst) strcpy(message,"EVENT_DL_HARQ_IND_TO_SCH"); break; } + case EVENT_STATISTICS_REQ_TO_SCH: + { + strcpy(message,"EVENT_STATISTICS_REQ_TO_SCH"); + break; + } default: strcpy(message,"Invalid Event"); break; @@ -298,6 +304,11 @@ uint8_t SchMessageRouter(Pst *pst, void *msg) SchProcDlHarqInd(pst, (DlHarqInd *)msg); break; } + case EVENT_STATISTICS_REQ_TO_SCH: + { + SchProcStatsReq(pst, (SchStatsReq *)msg); + break; + } default: { DU_LOG("\nERROR --> SCH : SchMessageRouter(): Invalid event [%d] received", pst->event); diff --git a/src/5gnrsch/sch_rach.c b/src/5gnrsch/sch_rach.c index 8d5b79ca7..e4f6fb468 100644 --- a/src/5gnrsch/sch_rach.c +++ b/src/5gnrsch/sch_rach.c @@ -40,6 +40,7 @@ #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" /** diff --git a/src/5gnrsch/sch_slice_based.c b/src/5gnrsch/sch_slice_based.c index 149e7d975..ece81a09b 100644 --- a/src/5gnrsch/sch_slice_based.c +++ b/src/5gnrsch/sch_slice_based.c @@ -40,6 +40,7 @@ File: sch_slice_based.c #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #include "sch_slice_based.h" #ifdef NR_DRX diff --git a/src/5gnrsch/sch_slot_ind.c b/src/5gnrsch/sch_slot_ind.c index 00ea9b933..4ffdc068c 100644 --- a/src/5gnrsch/sch_slot_ind.c +++ b/src/5gnrsch/sch_slot_ind.c @@ -40,6 +40,7 @@ File: sch_slot_ind.c #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #ifdef NR_DRX #include "sch_drx.h" @@ -749,11 +750,23 @@ uint8_t SchProcSlotInd(Pst *pst, SlotTimingInfo *slotInd) return (ret); } + /* Update DL statistics */ + if(schCb[schInst].statistics.dlTotalPrbUsage) + { + schCb[schInst]. statistics.dlTotalPrbUsage->numPrbUsedForTx += cell->schUlSlotInfo[slot]->prbAlloc.numPrbAlloc; + schCb[schInst].statistics.dlTotalPrbUsage->totalPrbAvailForTx += MAX_NUM_RB; + } + + /* Re-initialize DL slot */ schInitDlSlot(cell->schDlSlotInfo[slot]); + + /* Send UL Resource allocation to MAC */ schUlResAlloc(cell, schInst); + #ifdef NR_DRX schHandleExpiryDrxTimer(cell); #endif + return ret; } diff --git a/src/5gnrsch/sch_tmr.c b/src/5gnrsch/sch_tmr.c index e880db0ac..f38a2bc3f 100644 --- a/src/5gnrsch/sch_tmr.c +++ b/src/5gnrsch/sch_tmr.c @@ -21,6 +21,207 @@ #include "lrg.x" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" + +/** + * @brief Handler to check if the timer is running + * + * @param[in] cb Control block depending on the type of the timer event. + * @param[in] tmrEvnt Timer event to be started + * + * @return Bool indicating whether the timer is running or not + * -# ROK + * -# RFAILED +*/ +bool schChkTmr(PTR cb, int16_t tmrEvnt) +{ + switch (tmrEvnt) + { + case EVENT_DL_TOTAL_PRB_USAGE_TMR: + { + if(((TotalPrbUsage *)cb)->periodTimer.tmrEvnt == EVENT_DL_TOTAL_PRB_USAGE_TMR) + { + DU_LOG("\nDEBUG --> SCH : schChkTmr: Timer Evnt [%d] already running", tmrEvnt); + return TRUE; + } + break; + } + + case EVENT_UL_TOTAL_PRB_USAGE_TMR: + { + if(((TotalPrbUsage *)cb)->periodTimer.tmrEvnt == EVENT_UL_TOTAL_PRB_USAGE_TMR) + { + DU_LOG("\nDEBUG --> SCH : schChkTmr: Timer Evnt [%d] already running", tmrEvnt); + return TRUE; + } + break; + } + + default: + { + DU_LOG("\nERROR --> SCH : schChkTmr: Invalid tmr Evnt [%d]", tmrEvnt); + } + } + + return FALSE; +} + +/** + * @brief Handler to start timer + * + * @param[in] cb Control block depending on the type of the timer event. + * @param[in] tmrEvnt Timer event to be started + * + * @return Void +*/ +void schStartTmr(SchCb *gCb, PTR cb, int16_t tmrEvnt, uint8_t timerValue) +{ + TotalPrbUsage *dlTotalPrbUsage; + TotalPrbUsage *ulTotalPrbUsage; + CmTmrArg arg; + arg.wait = 0; + + switch (tmrEvnt) + { + case EVENT_DL_TOTAL_PRB_USAGE_TMR: + { + dlTotalPrbUsage = ((TotalPrbUsage *)cb); + TMR_CALCUATE_WAIT(arg.wait, timerValue, gCb->schTimersInfo.tmrRes); + + arg.timers = &dlTotalPrbUsage->periodTimer; + arg.max = MAX_TOTAL_PRB_USAGE_TMR; + break; + } + + case EVENT_UL_TOTAL_PRB_USAGE_TMR: + { + ulTotalPrbUsage = ((TotalPrbUsage *)cb); + TMR_CALCUATE_WAIT(arg.wait, timerValue, gCb->schTimersInfo.tmrRes); + + arg.timers = &ulTotalPrbUsage->periodTimer; + arg.max = MAX_TOTAL_PRB_USAGE_TMR; + break; + } + default: + { + DU_LOG("\nERROR --> SCH : schStartTmr: Invalid tmr Evnt [%d]", tmrEvnt); + } + } + + if(arg.wait != 0) + { + arg.tqCp = &(gCb->schTimersInfo.tmrTqCp); + arg.tq = gCb->schTimersInfo.tmrTq; + arg.cb = cb; + arg.evnt = tmrEvnt; + arg.tNum = 0; + + cmPlcCbTq(&arg); + } + return; +} + +/** + * @brief Handler to stop a timer + * + * @param[in] cb Control block depending on the type of the timer event. + * @param[in] tmrType Timer event to be started + * + * @return Void +*/ +void schStopTmr(SchCb *gCb, PTR cb, uint8_t tmrType) +{ + CmTmrArg arg; + + arg.timers = NULLP; + + switch (tmrType) + { + case EVENT_DL_TOTAL_PRB_USAGE_TMR: + { + arg.timers = &((TotalPrbUsage *)cb)->periodTimer; + arg.max = MAX_TOTAL_PRB_USAGE_TMR; + break; + } + case EVENT_UL_TOTAL_PRB_USAGE_TMR: + { + arg.timers = &((TotalPrbUsage *)cb)->periodTimer; + arg.max = MAX_TOTAL_PRB_USAGE_TMR; + break; + } + + default: + { + DU_LOG("\nERROR --> SCH : schStopTmr: Invalid tmr Evnt[%d]", tmrType); + break; + } + } + + if (tmrType != TMR0) + { + arg.tqCp = &gCb->schTimersInfo.tmrTqCp; + arg.tq = gCb->schTimersInfo.tmrTq; + arg.cb = cb; + arg.evnt = tmrType; + arg.wait = 0; + arg.tNum = 0; + cmRmvCbTq(&arg); + } + + return; +} + +/** + * @brief Handler to process Timer expiry of DL Total PRB Usage calculation + * + * @param[in] cb Control block depending on the type of the timer event. + * @param[in] tmrEvnt Timer event to be started + * + * @return Bool indicating whether the timer is running or not + * -# ROK + * -# RFAILED +*/ +uint8_t SchProcDlTotalPrbUsageTmrExp(TotalPrbUsage *dlTotalPrbUsage) +{ + uint8_t percentageOfTotalPrbUsed; + + percentageOfTotalPrbUsed = ((dlTotalPrbUsage->numPrbUsedForTx * 100) / dlTotalPrbUsage->totalPrbAvailForTx); + SchSendStatsIndToMac(dlTotalPrbUsage->schInst, SCH_DL_TOTAL_PRB_USAGE, percentageOfTotalPrbUsed); + + /* Restart Timer */ + dlTotalPrbUsage->numPrbUsedForTx = 0; + dlTotalPrbUsage->totalPrbAvailForTx = 0; + schStartTmr(&schCb[dlTotalPrbUsage->schInst], (PTR)(dlTotalPrbUsage), EVENT_DL_TOTAL_PRB_USAGE_TMR, \ + dlTotalPrbUsage->periodicity); + + return ROK; +} + +/** + * @brief Handler to check if the timer is running + * + * @param[in] cb Control block depending on the type of the timer event. + * @param[in] tmrEvnt Timer event to be started + * + * @return Bool indicating whether the timer is running or not + * -# ROK + * -# RFAILED +*/ +uint8_t SchProcUlTotalPrbUsageTmrExp(TotalPrbUsage *ulTotalPrbUsage) +{ + uint8_t percentageOfTotalPrbUsed; + + percentageOfTotalPrbUsed = ((ulTotalPrbUsage->numPrbUsedForTx * 100) / ulTotalPrbUsage->totalPrbAvailForTx); + SchSendStatsIndToMac(ulTotalPrbUsage->schInst, SCH_UL_TOTAL_PRB_USAGE, percentageOfTotalPrbUsed); + + /* Restart Timer */ + ulTotalPrbUsage->numPrbUsedForTx = 0; + ulTotalPrbUsage->totalPrbAvailForTx = 0; + schStartTmr(&schCb[ulTotalPrbUsage->schInst], (PTR)(ulTotalPrbUsage), EVENT_UL_TOTAL_PRB_USAGE_TMR, \ + ulTotalPrbUsage->periodicity); + + return ROK; +} /** * @brief Timer Expiry handler. @@ -34,13 +235,30 @@ * about tmrEvnt=Bind timer. * * @param[in] PTR cb, Entry for which Timer expired - * @param[in] S16 tmrEvnt, the Timer Event + * @param[in] uint8_t tmrEvnt, the Timer Event * @return uint8_t * -# ROK **/ uint8_t schTmrExpiry(PTR cb, uint8_t tmrEvnt) { - /* TODO : Handling of any timer event expiry */ + switch (tmrEvnt) + { + case EVENT_DL_TOTAL_PRB_USAGE_TMR: + { + SchProcDlTotalPrbUsageTmrExp((TotalPrbUsage*)cb); + break; + } + case EVENT_UL_TOTAL_PRB_USAGE_TMR: + { + SchProcUlTotalPrbUsageTmrExp((TotalPrbUsage*)cb); + break; + } + default: + { + DU_LOG("\nERROR --> DU : duStartTmr: Invalid tmr Evnt [%d]", tmrEvnt); + break; + } + } return ROK; } @@ -65,8 +283,7 @@ short int schActvTmr(Ent ent,Inst inst) Inst schInst = (inst - SCH_INST_START); /* Check if any timer in the scheduler instance has expired */ - cmPrcTmr(&schCb[schInst].tmrTqCp, - schCb[schInst].tmrTq, (PFV) schTmrExpiry); + cmPrcTmr(&schCb[schInst].schTimersInfo.tmrTqCp, schCb[schInst].schTimersInfo.tmrTq, (PFV) schTmrExpiry); return ROK; diff --git a/src/5gnrsch/sch_tmr.h b/src/5gnrsch/sch_tmr.h new file mode 100644 index 000000000..28f987311 --- /dev/null +++ b/src/5gnrsch/sch_tmr.h @@ -0,0 +1,31 @@ +/******************************************************************************* +################################################################################ +# 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. # +################################################################################ +*******************************************************************************/ + +#define MAX_TOTAL_PRB_USAGE_TMR 2 + +#define EVENT_DL_TOTAL_PRB_USAGE_TMR 1 +#define EVENT_UL_TOTAL_PRB_USAGE_TMR 2 + +bool schChkTmr(PTR cb, int16_t tmrEvnt); +void schStartTmr(SchCb *gCb, PTR cb, int16_t tmrEvnt, uint8_t timerValue); +void schStopTmr(SchCb *gCb, PTR cb, uint8_t tmrType); + +/********************************************************************** + End of file + **********************************************************************/ + diff --git a/src/5gnrsch/sch_ue_mgr.c b/src/5gnrsch/sch_ue_mgr.c index 1711ecbe4..d416a0749 100644 --- a/src/5gnrsch/sch_ue_mgr.c +++ b/src/5gnrsch/sch_ue_mgr.c @@ -27,6 +27,7 @@ #include "du_app_mac_inf.h" #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #ifdef NR_DRX #include "sch_drx.h" diff --git a/src/5gnrsch/sch_utils.c b/src/5gnrsch/sch_utils.c index 9d65480b6..7e849abb7 100644 --- a/src/5gnrsch/sch_utils.c +++ b/src/5gnrsch/sch_utils.c @@ -41,6 +41,7 @@ #include "lrg.x" /* layer management typedefs for MAC */ #include "mac_sch_interface.h" #include "sch.h" +#include "sch_tmr.h" #include "sch_utils.h" #include "math.h" diff --git a/src/cm/common_def.h b/src/cm/common_def.h index ffc921ea2..1a5814a5c 100644 --- a/src/cm/common_def.h +++ b/src/cm/common_def.h @@ -129,6 +129,8 @@ /*First SCS in kHz as per 3gpp spec 38.211 Table 4.2-1 */ #define BASE_SCS 15 +#define MAX_NUM_STATS 10 + /* Defining macros for common utility functions */ #define ODU_GET_MSG_BUF SGetMsg #define ODU_PUT_MSG_BUF SPutMsg @@ -226,6 +228,28 @@ _isLcidValid = ((_lcId >= SRB0_LCID && _lcId <= MAX_DRB_LCID) ? 1 : 0);\ } +/** + * @def TMR_CALCUATE_WAIT + * + * This macro calculates and assigns wait time based on the value of the + * timer and the timer resolution. Timer value of 0 signifies that the + * timer is not configured + * + * @param[out] _wait Time for which to arm the timer changed to proper + * value according to the resolution + * @param[in] _tmrVal Value of the timer + * @param[in] _timerRes Resolution of the timer + * +*/ +#define TMR_CALCUATE_WAIT(_wait, _tmrVal, _timerRes) \ +{ \ + (_wait) = ((_tmrVal) * SS_TICKS_SEC)/((_timerRes) * 1000); \ + if((0 != (_tmrVal)) && (0 == (_wait))) \ + { \ + (_wait) = 1; \ + } \ +} + typedef enum { SUCCESSFUL, @@ -233,6 +257,8 @@ typedef enum UEID_INVALID, RESOURCE_UNAVAILABLE, SLICE_NOT_FOUND, + DUPLICATE_ENTRY, + PARAM_INVALID }CauseOfResult ; typedef enum diff --git a/src/cm/du_app_mac_inf.c b/src/cm/du_app_mac_inf.c index 3ea1b0cce..52ea9dc02 100644 --- a/src/cm/du_app_mac_inf.c +++ b/src/cm/du_app_mac_inf.c @@ -2318,6 +2318,243 @@ void unsetBitInUeBitMap(uint16_t cellId, uint8_t bitPos) UNSET_ONE_BIT(bitPos, ueBitMapPerCell[cellIdx]); } +/******************************************************************* +* +* @brief Packs and Sends Statistics Request from DUAPP to MAC +* +* @details +* +* Function : packDuMacStatsReq +* +* Functionality: +* Packs and Sends statistics request from DUAPP to MAC +* +* +* @params[in] Post structure pointer +* StatsReq pointer +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +uint8_t packDuMacStatsReq(Pst *pst, MacStatsReq *statsReq) +{ + Buffer *mBuf = NULLP; + + if(pst->selector == ODU_SELECTOR_LWLC) + { + if (ODU_GET_MSG_BUF(pst->region, pst->pool, &mBuf) != ROK) + { + DU_LOG("\nERROR --> MAC : Memory allocation failed at packDuMacStatsReq"); + return RFAILED; + } + /* pack the address of the structure */ + CMCHKPK(oduPackPointer,(PTR)statsReq, mBuf); + } + else + { + DU_LOG("\nERROR --> MAC: Only LWLC supported for packDuMacStatsReq"); + return RFAILED; + } + return ODU_POST_TASK(pst,mBuf); +} + +/******************************************************************* +* +* @brief Unpacks Statistics Request received from DU APP +* +* @details +* +* Function : unpackMacStatsReq +* +* Functionality: +* Unpacks Statistics Request received from DU APP +* +* @params[in] Pointer to Handler +* Post structure pointer +* Message Buffer +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +uint8_t unpackMacStatsReq(DuMacStatsReqFunc func, Pst *pst, Buffer *mBuf) +{ + if(pst->selector == ODU_SELECTOR_LWLC) + { + MacStatsReq *statsReq; + + /* unpack the address of the structure */ + CMCHKUNPK(oduUnpackPointer, (PTR *)&statsReq, mBuf); + ODU_PUT_MSG_BUF(mBuf); + return (*func)(pst, statsReq); + } + else + { + /* Nothing to do for other selectors */ + DU_LOG("\nERROR --> DU APP : Only LWLC supported for Statistics Request "); + ODU_PUT_MSG_BUF(mBuf); + } + + return RFAILED; +} + +/******************************************************************* +* +* @brief Packs and Sends Statistics Response from MAC to DUAPP +* +* @details +* +* Function : packDuMacStatsRsp +* +* Functionality: +* Packs and Sends statistics response from MAC to DUAPP +* +* +* @params[in] Post structure pointer +* StatsRsp pointer +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +uint8_t packDuMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp) +{ + Buffer *mBuf = NULLP; + + if(pst->selector == ODU_SELECTOR_LWLC) + { + if (ODU_GET_MSG_BUF(pst->region, pst->pool, &mBuf) != ROK) + { + DU_LOG("\nERROR --> MAC : Memory allocation failed at packDuMacStatsRsp"); + return RFAILED; + } + /* pack the address of the structure */ + CMCHKPK(oduPackPointer,(PTR)statsRsp, mBuf); + } + else + { + DU_LOG("\nERROR --> MAC: Only LWLC supported for packDuMacStatsRsp"); + return RFAILED; + } + return ODU_POST_TASK(pst,mBuf); +} + +/******************************************************************* +* +* @brief Unpacks Statistics Response received from MAC +* +* @details +* +* Function : unpackDuMacStatsRsp +* +* Functionality: +* Unpacks Statistics Response received from MAC +* +* @params[in] Pointer to Handler +* Post structure pointer +* Message Buffer +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +uint8_t unpackDuMacStatsRsp(MacDuStatsRspFunc func, Pst *pst, Buffer *mBuf) +{ + if(pst->selector == ODU_SELECTOR_LWLC) + { + MacStatsRsp *statsRsp; + + /* unpack the address of the structure */ + CMCHKUNPK(oduUnpackPointer, (PTR *)&statsRsp, mBuf); + ODU_PUT_MSG_BUF(mBuf); + return (*func)(pst, statsRsp); + } + else + { + /* Nothing to do for other selectors */ + DU_LOG("\nERROR --> DU APP : Only LWLC supported for Statistics Response "); + ODU_PUT_MSG_BUF(mBuf); + } + + return RFAILED; +} + +/******************************************************************* +* +* @brief Packs and Sends Statistics Indication from MAC to DUAPP +* +* @details +* +* Function : packDuMacStatsInd +* +* Functionality: +* Packs and Sends statistics response from MAC to DUAPP +* +* +* @params[in] Post structure pointer +* StatsInd pointer +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +uint8_t packDuMacStatsInd(Pst *pst, MacStatsInd *statsInd) +{ + Buffer *mBuf = NULLP; + + if(pst->selector == ODU_SELECTOR_LWLC) + { + if (ODU_GET_MSG_BUF(pst->region, pst->pool, &mBuf) != ROK) + { + DU_LOG("\nERROR --> MAC : Memory allocation failed at packDuMacStatsInd"); + return RFAILED; + } + /* pack the address of the structure */ + CMCHKPK(oduPackPointer,(PTR)statsInd, mBuf); + } + else + { + DU_LOG("\nERROR --> MAC: Only LWLC supported for packDuMacStatsInd"); + return RFAILED; + } + return ODU_POST_TASK(pst,mBuf); +} + +/******************************************************************* +* +* @brief Unpacks Statistics Indication received from MAC +* +* @details +* +* Function : unpackDuMacStatsInd +* +* Functionality: +* Unpacks Statistics Indication received from MAC +* +* @params[in] Pointer to Handler +* Post structure pointer +* Message Buffer +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +uint8_t unpackDuMacStatsInd(MacDuStatsIndFunc func, Pst *pst, Buffer *mBuf) +{ + if(pst->selector == ODU_SELECTOR_LWLC) + { + MacStatsInd *statsInd; + + /* unpack the address of the structure */ + CMCHKUNPK(oduUnpackPointer, (PTR *)&statsInd, mBuf); + ODU_PUT_MSG_BUF(mBuf); + return (*func)(pst, statsInd); + } + else + { + /* Nothing to do for other selectors */ + DU_LOG("\nERROR --> DU APP : Only LWLC supported for Statistics Indication "); + ODU_PUT_MSG_BUF(mBuf); + } + + return RFAILED; +} + /********************************************************************** End of file **********************************************************************/ diff --git a/src/cm/du_app_mac_inf.h b/src/cm/du_app_mac_inf.h index 7cb789700..09c651845 100644 --- a/src/cm/du_app_mac_inf.h +++ b/src/cm/du_app_mac_inf.h @@ -89,6 +89,9 @@ #define EVENT_MAC_UE_RESET_RSP 226 #define EVENT_MAC_UE_SYNC_STATUS_IND 227 #define EVENT_MAC_DL_BROADCAST_REQ 228 +#define EVENT_MAC_STATISTICS_REQ 229 +#define EVENT_MAC_STATISTICS_RSP 230 +#define EVENT_MAC_STATISTICS_IND 231 #define BSR_PERIODIC_TIMER_SF_10 10 #define BSR_RETX_TIMER_SF_320 320 @@ -97,6 +100,10 @@ #define PAGING_SCHED_DELTA 4 #define MAX_PLMN 2 +/********************* Global Variable ********************/ +uint64_t ueBitMapPerCell[MAX_NUM_CELL]; /* Bit Map to store used/free UE-IDX per Cell */ + +/********************* Interface structure definition ********************/ typedef enum { SIB_TYPE2, @@ -578,6 +585,13 @@ typedef enum RESTART_TRANSMISSION }DataTransmissionAction; +/* Performance measurements from 3GPP TS 28.552 Release 15 */ +typedef enum +{ + MAC_DL_TOTAL_PRB_USAGE, + MAC_UL_TOTAL_PRB_USAGE +}MacMeasurementType; + typedef struct failureCause { CauseGrp type; @@ -1841,6 +1855,32 @@ typedef struct macDlBroadcastReq SiSchedulingInfo **siSchedulingInfo; }MacDlBroadcastReq; +typedef struct macStatsInfo +{ + MacMeasurementType type; + uint16_t periodicity; /* In milliseconds */ +}MacStatsInfo; + +typedef struct macStatsReq +{ + uint8_t numStats; + MacStatsInfo statsList[MAX_NUM_STATS]; +}MacStatsReq; + +typedef struct macStatsRsp +{ + MacRsp rsp; + CauseOfResult cause; +}MacStatsRsp; + +typedef struct macStatsInd +{ + MacMeasurementType type; + uint32_t value; +}MacStatsInd; + +/****************** FUNCTION POINTERS ********************************/ + /* DL broadcast req from DU APP to MAC*/ typedef uint8_t (*DuMacDlBroadcastReq) ARGS(( Pst *pst, @@ -1993,98 +2033,153 @@ typedef uint8_t (*MacDuUeSyncStatusIndFunc) ARGS(( Pst *pst, MacUeSyncStatusInd *syncStatusInd)); -uint64_t ueBitMapPerCell[MAX_NUM_CELL]; /* Bit Map to store used/free UE-IDX per Cell */ +/* Statitics Request from DU APP to MAC */ +typedef uint8_t (*DuMacStatsReqFunc) ARGS(( + Pst *pst, + MacStatsReq *statsReq)); + +/* Statistics Response from MAC to DU APP */ +typedef uint8_t (*MacDuStatsRspFunc) ARGS(( + Pst *pst, + MacStatsRsp *statsRsp)); + +/* Statistics Ind from MAC to DU APP */ +typedef uint8_t (*MacDuStatsIndFunc) ARGS(( + Pst *pst, + MacStatsInd *statsInd)); +/******************** FUNCTION DECLARATIONS ********************************/ uint8_t packMacCellUpInd(Pst *pst, OduCellId *cellId); uint8_t unpackMacCellUpInd(DuMacCellUpInd func, Pst *pst, Buffer *mBuf); uint8_t duHandleCellUpInd(Pst *pst, OduCellId *cellId); + uint8_t packMacCellStart(Pst *pst, CellStartInfo *cellStartInfo); uint8_t unpackMacCellStart(DuMacCellStart func, Pst *pst, Buffer *mBuf); uint8_t MacProcCellStart(Pst *pst, CellStartInfo *cellStartInfo); + uint8_t packMacCellStop(Pst *pst, CellStopInfo *cellStopInfo); uint8_t unpackMacCellStop(DuMacCellStop func, Pst *pst, Buffer *mBuf); uint8_t MacProcCellStop(Pst *pst, CellStopInfo *cellStopInfo); + uint8_t packMacCellCfg(Pst *pst, MacCellCfg *macCellCfg); uint8_t unpackDuMacCellCfg(DuMacCellCfgReq func, Pst *pst, Buffer *mBuf); uint8_t MacProcCellCfgReq(Pst *pst, MacCellCfg *macCellCfg); + uint8_t packMacCellCfgCfm(Pst *pst, MacCellCfgCfm *macCellCfgCfm); uint8_t unpackMacCellCfgCfm(DuMacCellCfgCfm func, Pst *pst, Buffer *mBuf); uint8_t duHandleMacCellCfgCfm(Pst *pst, MacCellCfgCfm *macCellCfgCfm); + uint8_t packMacStopInd(Pst *pst, OduCellId *cellId); uint8_t unpackMacStopInd(DuMacStopInd func, Pst *pst, Buffer *mBuf); uint8_t duHandleStopInd(Pst *pst, OduCellId *cellId); +uint8_t sendStopIndMacToDuApp(uint16_t cellId); + uint8_t packMacUlCcchInd(Pst *pst, UlCcchIndInfo *ulCcchIndInfo); uint8_t unpackMacUlCcchInd(DuMacUlCcchInd func, Pst *pst, Buffer *mBuf); uint8_t duHandleUlCcchInd(Pst *pst, UlCcchIndInfo *ulCcchIndInfo); + uint8_t packMacDlCcchInd(Pst *pst, DlCcchIndInfo *dlCcchIndInfo); uint8_t unpackMacDlCcchInd(DuMacDlCcchInd func, Pst *pst, Buffer *mBuf); uint8_t MacProcDlCcchInd(Pst *pst, DlCcchIndInfo *dlCcchIndInfo); + uint8_t packDuMacUeCreateReq(Pst *pst, MacUeCreateReq *ueCfg); uint8_t unpackMacUeCreateReq(DuMacUeCreateReq func, Pst *pst, Buffer *mBuf); uint8_t MacProcUeCreateReq(Pst *pst, MacUeCreateReq *ueCfg); -uint8_t sendStopIndMacToDuApp(uint16_t cellId); + uint8_t packDuMacUeCreateRsp(Pst *pst, MacUeCreateRsp *cfgRsp); uint8_t unpackDuMacUeCreateRsp(MacDuUeCreateRspFunc func, Pst *pst, Buffer *mBuf); uint8_t DuProcMacUeCreateRsp(Pst *pst, MacUeCreateRsp *cfgRsp); + uint8_t packDuMacUeReconfigReq(Pst *pst, MacUeRecfg *ueRecfg); uint8_t unpackMacUeReconfigReq(DuMacUeReconfigReq func, Pst *pst, Buffer *mBuf); uint8_t MacProcUeReconfigReq(Pst *pst, MacUeRecfg *ueRecfg); + uint8_t packDuMacUeRecfgRsp(Pst *pst, MacUeRecfgRsp *recfgRsp); uint8_t unpackDuMacUeRecfgRsp(MacDuUeRecfgRspFunc func, Pst *pst, Buffer *mBuf); uint8_t DuProcMacUeRecfgRsp(Pst *pst, MacUeRecfgRsp *recfgRsp); + uint8_t packDuMacRachRsrcReq(Pst *pst, MacRachRsrcReq *rachRsrcReq); uint8_t unpackMacRachRsrcReq(DuMacRachRsrcReq func, Pst *pst, Buffer *mBuf); uint8_t MacProcRachRsrcReq(Pst *pst, MacRachRsrcReq *rachRsrcReq); + uint8_t packDuMacRachRsrcRsp(Pst *pst, MacRachRsrcRsp *rachRsrcRsp); uint8_t unpackDuMacRachRsrcRsp(MacDuRachRsrcRspFunc func, Pst *pst, Buffer *mBuf); uint8_t DuProcMacRachRsrcRsp(Pst *pst, MacRachRsrcRsp *rachRsrcRsp); + uint8_t packDuMacRachRsrcRel(Pst *pst, MacRachRsrcRel *rachRsrcRel); uint8_t unpackMacRachRsrcRel(DuMacRachRsrcRel func, Pst *pst, Buffer *mBuf); uint8_t MacProcRachRsrcRel(Pst *pst, MacRachRsrcRel *rachRsrcRel); + uint8_t packDuMacUeDeleteReq(Pst *pst, MacUeDelete *ueDelete); uint8_t MacProcUeDeleteReq(Pst *pst, MacUeDelete *ueDelete); uint8_t unpackMacUeDeleteReq(DuMacUeDeleteReq func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacUeDeleteRsp(Pst *pst, MacUeDeleteRsp *deleteRsp); uint8_t DuProcMacUeDeleteRsp(Pst *pst, MacUeDeleteRsp *deleteRsp); uint8_t unpackDuMacUeDeleteRsp(MacDuUeDeleteRspFunc func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacCellDeleteReq(Pst *pst, MacCellDeleteReq *cellDelete); uint8_t MacProcCellDeleteReq(Pst *pst, MacCellDeleteReq *cellDelete); uint8_t unpackMacCellDeleteReq(DuMacCellDeleteReq func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacCellDeleteRsp(Pst *pst, MacCellDeleteRsp *cellDeleteRsp); uint8_t DuProcMacCellDeleteRsp(Pst *pst, MacCellDeleteRsp *cellDeleteRsp); uint8_t unpackDuMacCellDeleteRsp(MacDuCellDeleteRspFunc func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacSliceCfgReq(Pst *pst, MacSliceCfgReq *sliceCfgReq); uint8_t MacProcSliceCfgReq(Pst *pst, MacSliceCfgReq *sliceCfgReq); uint8_t unpackMacSliceCfgReq(DuMacSliceCfgReq func, Pst *pst, Buffer *mBuf); + uint8_t DuProcMacSliceCfgRsp(Pst *pst, MacSliceCfgRsp *cfgRsp); uint8_t packDuMacSliceCfgRsp(Pst *pst, MacSliceCfgRsp *cfgRsp); uint8_t unpackDuMacSliceCfgRsp(MacDuSliceCfgRspFunc func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacSliceRecfgReq(Pst *pst, MacSliceRecfgReq *sliceRecfgReq); uint8_t MacProcSliceRecfgReq(Pst *pst, MacSliceRecfgReq *sliceRecfgReq); uint8_t unpackMacSliceRecfgReq(DuMacSliceRecfgReq func, Pst *pst, Buffer *mBuf); + uint8_t DuProcMacSliceRecfgRsp(Pst *pst, MacSliceRecfgRsp *sliceRecfgRsp); uint8_t packDuMacSliceRecfgRsp(Pst *pst, MacSliceRecfgRsp *sliceRecfgRsp); uint8_t unpackDuMacSliceRecfgRsp(MacDuSliceRecfgRspFunc func, Pst *pst, Buffer *mBuf); + uint8_t duHandleSlotInd(Pst *pst, SlotTimingInfo *slotIndInfo); uint8_t packMacSlotInd(Pst *pst, SlotTimingInfo *slotIndInfo); uint8_t unpackDuMacSlotInd(DuMacSlotInd func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacDlPcchInd(Pst *pst, DlPcchInd *pcchInd); uint8_t MacProcDlPcchInd(Pst *pst, DlPcchInd *pcchInd); uint8_t unpackMacDlPcchInd(DuMacDlPcchInd func, Pst *pst, Buffer *mBuf); + int8_t getFreeBitFromUeBitMap(uint16_t cellId); void unsetBitInUeBitMap(uint16_t cellId, uint8_t bitPos); + uint8_t packDuMacUeResetReq(Pst *pst, MacUeResetReq *ueReset); uint8_t MacProcUeResetReq(Pst *pst, MacUeResetReq *ueReset); uint8_t unpackMacUeResetReq(DuMacUeResetReq func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacUeResetRsp(Pst *pst, MacUeResetRsp *resetRsp); uint8_t DuProcMacUeResetRsp(Pst *pst, MacUeResetRsp *resetRsp); uint8_t unpackDuMacUeResetRsp(MacDuUeResetRspFunc func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacUeSyncStatusInd(Pst *pst, MacUeSyncStatusInd *ueSyncStatusInd); uint8_t DuProcMacUeSyncStatusInd(Pst *pst, MacUeSyncStatusInd *ueSyncStatusInd); uint8_t unpackDuMacUeSyncStatusInd(MacDuUeSyncStatusIndFunc func, Pst *pst, Buffer *mBuf); + uint8_t packDuMacDlBroadcastReq(Pst *pst, MacDlBroadcastReq *dlBroadcastReq); uint8_t MacProcDlBroadcastReq(Pst *pst, MacDlBroadcastReq *dlBroadcastReq); uint8_t unpackMacDlBroadcastReq(DuMacDlBroadcastReq func, Pst *pst, Buffer *mBuf); + +uint8_t packDuMacStatsReq(Pst *pst, MacStatsReq *statsReq); +uint8_t MacProcStatsReq(Pst *pst, MacStatsReq *statsReq); +uint8_t unpackMacStatsReq(DuMacStatsReqFunc func, Pst *pst, Buffer *mBuf); + +uint8_t packDuMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp); +uint8_t DuProcMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp); +uint8_t unpackDuMacStatsRsp(MacDuStatsRspFunc func, Pst *pst, Buffer *mBuf); + +uint8_t packDuMacStatsInd(Pst *pst, MacStatsInd *statsRsp); +uint8_t DuProcMacStatsInd(Pst *pst, MacStatsInd *statsRsp); +uint8_t unpackDuMacStatsInd(MacDuStatsIndFunc func, Pst *pst, Buffer *mBuf); #endif diff --git a/src/cm/mac_sch_interface.h b/src/cm/mac_sch_interface.h index f3d4799d5..82d05bbd0 100644 --- a/src/cm/mac_sch_interface.h +++ b/src/cm/mac_sch_interface.h @@ -51,6 +51,10 @@ #define EVENT_DL_CQI_TO_SCH 32 #define EVENT_UL_CQI_TO_SCH 33 #define EVENT_PHR_IND_TO_SCH 34 +#define EVENT_STATISTICS_REQ_TO_SCH 35 +#define EVENT_STATISTICS_RSP_TO_MAC 36 +#define EVENT_STATISTICS_IND_TO_MAC 37 + /*macros*/ #define MAX_SSB_IDX 1 /* forcing it as 1 for now. Right value is 64 */ #define SCH_SSB_MASK_SIZE 1 @@ -448,6 +452,13 @@ typedef enum CQI_PUSCH }CqiUlReportType; +/* Performance measurements from 3GPP TS 28.552 Release 15 */ +typedef enum +{ + SCH_DL_TOTAL_PRB_USAGE, + SCH_UL_TOTAL_PRB_USAGE +}SchMeasurementType; + /*structures*/ typedef struct timeDomainAlloc { @@ -2237,6 +2248,30 @@ typedef struct schRlsHqInfo SchUeHqInfo *ueHqInfo; }SchRlsHqInfo; +typedef struct schStatsInfo +{ + SchMeasurementType type; + uint16_t periodicity; /* In milliseconds */ +}SchStatsInfo; + +typedef struct schStatsReq +{ + uint8_t numStats; + SchStatsInfo statsList[MAX_NUM_STATS]; +}SchStatsReq; + +typedef struct schStatsRsp +{ + SchMacRsp rsp; + CauseOfResult cause; +}SchStatsRsp; + +typedef struct schStatsInd +{ + SchMeasurementType type; + uint32_t value; +}SchStatsInd; + /* function declarations */ uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason); uint8_t MacMessageRouter(Pst *pst, void *msg); diff --git a/src/du_app/du_e2ap_mgr.h b/src/du_app/du_e2ap_mgr.h index 5004628ea..c86b113b0 100644 --- a/src/du_app/du_e2ap_mgr.h +++ b/src/du_app/du_e2ap_mgr.h @@ -246,7 +246,8 @@ typedef struct /* O-RAN.WG3.E2SM-KPM-R003-v03.00 : Section 8.3.11 */ typedef struct { - /* TODO : To be added when list of KPIs are finalised */ + /* TODO : To be added in future when subcounters for any + * measurment type is required */ }LabelInfo; /* O-RAN.WG3.E2SM-KPM-R003-v03.00 : Section 8.2.1.2.1 */ @@ -257,16 +258,18 @@ typedef struct char measurementTypeName[STRING_SIZE_150_BYTES]; uint16_t measurementTypeId; }choice; - uint32_t numOfLabels; - LabelInfo LabelInfoList[MAX_LABEL_INFO]; + + //uint32_t numOfLabels; + //LabelInfo LabelInfoList[MAX_LABEL_INFO]; + + CmLListCp measuredValue; /* To be filled when numOfLabels is 0, else values are calculated per Label */ }MeasurementInfo; /* O-RAN.WG3.E2SM-KPM-R003-v03.00 : Section 8.2.1.2.1 */ typedef struct { - uint16_t numOfMeasuermentInfo; - MeasurementInfo **measurementInfoList; - uint32_t granularityPeriod; /* In millisecond */ + CmLListCp measurementInfoList; /* Each node corresponds to MeasurementInfo */ + uint32_t granularityPeriod; /* In millisecond */ }ActionDefFormat1; /* O-RAN.WG3.E2SM-KPM-R003-v03.00 : Section 8.2.1.2.2 */ @@ -313,6 +316,7 @@ typedef struct uint8_t id; ActionType type; ActionDefinition definition; + ConfigType action; }ActionInfo; /* O-RAN.WG3.E2AP-R003-v03.00 : Section 9.1.1.1 : maxofRICActionID */ diff --git a/src/du_app/du_e2ap_msg_hdl.c b/src/du_app/du_e2ap_msg_hdl.c index e340e4363..912bb0184 100644 --- a/src/du_app/du_e2ap_msg_hdl.c +++ b/src/du_app/du_e2ap_msg_hdl.c @@ -1652,6 +1652,9 @@ uint8_t procRicSubsReq(E2AP_PDU_t *e2apMsg) } free(ricSubsReq->protocolIEs.list.array[idx]->value.choice.RICsubscriptionDetails.ricAction_ToBeSetup_List.\ list.array); + + ricSubscriptionInfo->actionSequence[0].definition.styleType = 1; + BuildAndSendStatsReq(ricSubscriptionInfo->actionSequence[0].definition); } break; } diff --git a/src/du_app/du_mgr.h b/src/du_app/du_mgr.h index ba079dbdc..f51ee9945 100644 --- a/src/du_app/du_mgr.h +++ b/src/du_app/du_mgr.h @@ -353,7 +353,6 @@ typedef struct duCb DuTimers duTimersInfo; /* Du timers queue */ }DuCb; - typedef struct duLSapCfg { SuId suId; @@ -372,6 +371,15 @@ typedef struct duLSapCfg TmrCfg connTmr; }DuLSapCfg; +/* Statistics Reported */ +typedef struct statistics +{ + //DuAppStats duAppStats; + //RlcStatsReq rlcStatsReq; + + MacStatsReq macStatsReq; +}Statistics; + /* global variables */ DuCb duCb; //DuCfgParams duCfgParam; diff --git a/src/du_app/du_mgr_main.c b/src/du_app/du_mgr_main.c index dfcc19816..40c1220a8 100644 --- a/src/du_app/du_mgr_main.c +++ b/src/du_app/du_mgr_main.c @@ -550,7 +550,7 @@ uint8_t commonInit() DU_LOG("\nERROR --> DU_APP : System Task creation for DU APP failed"); return RFAILED; } - ODU_SET_THREAD_AFFINITY(&du_app_stsk, SS_AFFINITY_MODE_EXCL, 16, 0); + //ODU_SET_THREAD_AFFINITY(&du_app_stsk, SS_AFFINITY_MODE_EXCL, 16, 0); /* system task for EGTP */ if(ODU_CREATE_TASK(PRIOR0, &egtp_stsk) != ROK) @@ -558,7 +558,7 @@ uint8_t commonInit() DU_LOG("\nERROR --> DU_APP : System Task creation for EGTP failed"); return RFAILED; } - ODU_SET_THREAD_AFFINITY(&egtp_stsk, SS_AFFINITY_MODE_EXCL, 27, 0); + //ODU_SET_THREAD_AFFINITY(&egtp_stsk, SS_AFFINITY_MODE_EXCL, 27, 0); /* system task for RLC_DL and MAC */ if(ODU_CREATE_TASK(PRIOR0, &rlc_mac_cl_stsk) != ROK) @@ -568,7 +568,7 @@ uint8_t commonInit() } pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - ODU_SET_THREAD_AFFINITY(&rlc_mac_cl_stsk, SS_AFFINITY_MODE_EXCL, 18, 0); + //ODU_SET_THREAD_AFFINITY(&rlc_mac_cl_stsk, SS_AFFINITY_MODE_EXCL, 18, 0); /* system task for RLC UL */ if(ODU_CREATE_TASK(PRIOR1, &rlc_ul_stsk) != ROK) @@ -576,7 +576,7 @@ uint8_t commonInit() DU_LOG("\nERROR --> DU_APP : System Task creation for RLC UL failed"); return RFAILED; } - ODU_SET_THREAD_AFFINITY(&rlc_ul_stsk, SS_AFFINITY_MODE_EXCL, 22, 0); + //ODU_SET_THREAD_AFFINITY(&rlc_ul_stsk, SS_AFFINITY_MODE_EXCL, 22, 0); /* system task for SCTP receiver thread */ if(ODU_CREATE_TASK(PRIOR0, &sctp_stsk) != ROK) @@ -584,7 +584,7 @@ uint8_t commonInit() DU_LOG("\nERROR --> DU_APP : System Task creation for SCTP failed"); return RFAILED; } - ODU_SET_THREAD_AFFINITY(&sctp_stsk, SS_AFFINITY_MODE_EXCL, 25, 0); + //ODU_SET_THREAD_AFFINITY(&sctp_stsk, SS_AFFINITY_MODE_EXCL, 25, 0); /* system task for lower-mac receiver thread */ if(ODU_CREATE_TASK(PRIOR0, &lwr_mac_stsk) != ROK) @@ -592,7 +592,7 @@ uint8_t commonInit() DU_LOG("\nERROR --> DU_APP : System Task creation for Lower MAC failed"); return RFAILED; } - ODU_SET_THREAD_AFFINITY(&lwr_mac_stsk, SS_AFFINITY_MODE_EXCL, 21, 0); + //ODU_SET_THREAD_AFFINITY(&lwr_mac_stsk, SS_AFFINITY_MODE_EXCL, 21, 0); #ifndef INTEL_WLS_MEM /* system task for phy stub's slot indication generator thread */ diff --git a/src/du_app/du_mgr_msg_router.c b/src/du_app/du_mgr_msg_router.c index 073b3e715..5acda22e9 100644 --- a/src/du_app/du_mgr_msg_router.c +++ b/src/du_app/du_mgr_msg_router.c @@ -287,6 +287,16 @@ void callFlowduActvTsk(Pst *pst) strcpy(message,"EVENT_MAC_SLICE_RECFG_RSP"); break; } + case EVENT_MAC_STATISTICS_RSP: + { + strcpy(message,"EVENT_MAC_STATISTICS_RSP"); + break; + } + case EVENT_MAC_STATISTICS_IND: + { + strcpy(message,"EVENT_MAC_STATISTICS_IND"); + break; + } default: { strcpy(message,"Invalid Event"); @@ -582,6 +592,16 @@ uint8_t duActvTsk(Pst *pst, Buffer *mBuf) ret = unpackDuMacUeResetRsp(DuProcMacUeResetRsp, pst, mBuf); break; } + case EVENT_MAC_STATISTICS_RSP: + { + ret = unpackDuMacStatsRsp(DuProcMacStatsRsp, pst, mBuf); + break; + } + case EVENT_MAC_STATISTICS_IND: + { + ret = unpackDuMacStatsInd(DuProcMacStatsInd, pst, mBuf); + break; + } default: { DU_LOG("\nERROR --> DU_APP : Invalid event received at duActvTsk from ENTMAC"); diff --git a/src/du_app/du_msg_hdl.c b/src/du_app/du_msg_hdl.c index 5ab931b81..dcc9a7e20 100644 --- a/src/du_app/du_msg_hdl.c +++ b/src/du_app/du_msg_hdl.c @@ -97,10 +97,18 @@ DuMacSliceCfgReq packMacSliceCfgReqOpts[] = DuMacSliceRecfgReq packMacSliceRecfgReqOpts[] = { - packDuMacSliceRecfgReq, /* Loose coupling */ - MacProcSliceRecfgReq, /* TIght coupling */ - packDuMacSliceRecfgReq /* Light weight-loose coupling */ + packDuMacSliceRecfgReq, /* Loose coupling */ + MacProcSliceRecfgReq, /* TIght coupling */ + packDuMacSliceRecfgReq /* Light weight-loose coupling */ }; + +DuMacStatsReqFunc packMacStatsReqOpts[]= +{ + packDuMacStatsReq, /* Loose Coupling */ + MacProcStatsReq, /* Tight Coupling */ + packDuMacStatsReq /* Light weight-loose coupling */ +}; + /************************************************************************** * @brief Function to fill configs required by RLC * @@ -726,7 +734,7 @@ uint8_t duBuildMacGenCfg() /*----------- Fill General Configuration Parameters ---------*/ genCfg->mem.region = MAC_MEM_REGION; genCfg->mem.pool = MAC_POOL; - genCfg->tmrRes = 10; + genCfg->tmrRes = 1; genCfg->numRguSaps = 2; genCfg->lmPst.dstProcId = DU_PROC; @@ -1299,7 +1307,7 @@ uint8_t duSendSchCfg() /* Filling of Gen config */ cfg->genCfg.mem.region = MAC_MEM_REGION; cfg->genCfg.mem.pool = MAC_POOL; - cfg->genCfg.tmrRes = 10; + cfg->genCfg.tmrRes = 1; #ifdef LTE_ADV cfg->genCfg.forceCntrlSrbBoOnPCel = FALSE; @@ -2068,6 +2076,227 @@ uint8_t DuProcRlcSliceMetrics(Pst *pst, SlicePmList *sliceStats) return ROK; } + +/******************************************************************* + * + * @brief Send Statistics request to MAC + * + * @details + * + * Function : BuildAndSendStatsReqToMac() + * + * Functionality: Send Statistics Request To Mac + * + * @params[in] + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t BuildAndSendStatsReqToMac(MacStatsReq duMacStatsReq) +{ + Pst pst; + MacStatsReq *macStatsReq = NULLP; + + DU_LOG("\nINFO --> DU_APP : Builds Statistics Request to send to MAC"); + + DU_ALLOC_SHRABL_BUF(macStatsReq, sizeof(MacStatsReq)); + if(macStatsReq == NULLP) + { + DU_LOG("\nERROR --> DU_APP : Memory allocation failed for macStatsReq in BuildAndSendStatsReqToMac"); + return RFAILED; + } + else + { + memcpy(macStatsReq, &duMacStatsReq, sizeof(MacStatsReq)); + + FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_STATISTICS_REQ); + + DU_LOG("\nDEBUG --> DU_APP: Sending Statistics Request to MAC "); + if( (*packMacStatsReqOpts[pst.selector])(&pst, macStatsReq) == RFAILED) + { + DU_LOG("\nERROR --> DU_APP: Failed to send Statistics Request to MAC"); + DU_FREE_SHRABL_BUF(DU_APP_MEM_REGION, DU_POOL, macStatsReq, sizeof(MacStatsReq)); + } + } + return ROK; +} + +/******************************************************************* + * + * @brief Send Statistics request to DU layers + * + * @details + * + * Function : BuildAndSendStatsReq() + * + * Functionality: Check if there is an update in statistics + * reporting configuration. If so, send the update to + * respective layer. + * + * @params[in] + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +Statistics FetchStatsFromActionDefFormat1(ActionDefFormat1 format1) +{ + Statistics stats; + + /* TODO : When E2AP subscription procedure is implemented: + * Measurement info list is traveresed + * Based on KPI type, stats.macStatsReq or stats.rlcstatsReq is filled */ + + /* Hardcoding values for now for testing purpose + * Will be removed in next gerrit */ + stats.macStatsReq.numStats = 2; + stats.macStatsReq.statsList[0].type = MAC_DL_TOTAL_PRB_USAGE; + stats.macStatsReq.statsList[0].periodicity = 10; + stats.macStatsReq.statsList[1].type = MAC_UL_TOTAL_PRB_USAGE; + stats.macStatsReq.statsList[1].periodicity = 10; + + return stats; +} + +/******************************************************************* + * + * @brief Send Statistics request to DU layers + * + * @details + * + * Function : BuildAndSendStatsReq() + * + * Functionality: Check if there is an update in statistics + * reporting configuration. If so, send the update to + * respective layer. + * + * @params[in] + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t BuildAndSendStatsReq(ActionDefinition subscribedAction) +{ + Statistics stats; + + switch(subscribedAction.styleType) + { + case 1: + stats = FetchStatsFromActionDefFormat1(subscribedAction.choice.format1); + case 2: + case 3: + case 4: + case 5: + default: + break; + } + + if(BuildAndSendStatsReqToMac(stats.macStatsReq) != ROK) + { + DU_LOG("\nERROR --> DU_APP : Failed at BuildAndSendStatsReqToMac()"); + return RFAILED; + } + +/* TODO : When KPI collection from RLC will be supported, this function will be + * called to configure KPIs to be colled */ +#if 0 + if(BuildAndSendStatsReqToRlc(macStatsReq->rlcStatsReq) != ROK) + { + DU_LOG("\nERROR --> DU_APP : Failed at BuildAndSendStatsReqToRlc()"); + return RFAILED; + } +#endif + + /* TODO : In the caller of this function, change ActionDefinition->action + * from CONFIG_ADD to CONFIG_UNKNOWN once configuration is sent + * To be done in next gerrit*/ + + + return ROK; +} + +/******************************************************************* + * + * @brief Process statistics response from MAC + * + * @details + * + * Function : DuProcMacStatsRsp + * + * Functionality: Processes statistics configuration response + * from MAC. If configuration is succsessful, DUAPP starts + * reporting period timer for this subscription request + * from RIC + * + * @params[in] + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t DuProcMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp) +{ + if(statsRsp) + { + if(statsRsp->rsp == MAC_DU_APP_RSP_OK) + { + DU_LOG("\nINFO --> DU_APP : Statistics configured successfully"); + /* TODO : Start Reporting period timer for this subscription request + * To be handled in next gerrit */ + } + else + { + DU_LOG("\nERROR --> DU_APP : Statistics configuration failed with cause [%d]", statsRsp->cause); + } + DU_FREE_SHRABL_BUF(DU_APP_MEM_REGION, DU_POOL, statsRsp, sizeof(MacStatsRsp)); + //BuildAndSendDUConfigUpdate(SERV_CELL_TO_DELETE); + return ROK; + } + + DU_LOG("\nINFO --> DU_APP : DuProcMacStatsRsp: Received NULL Pointer"); + return RFAILED; +} + +/******************************************************************* + * + * @brief Process statistics indication from MAC + * + * @details + * + * Function : DuProcMacStatsInd + * + * Functionality: Processes statistics indication from MAC. + * + * @params[in] + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t DuProcMacStatsInd(Pst *pst, MacStatsInd *statsInd) +{ + if(statsInd) + { + DU_LOG("\nINFO --> DU_APP : DuProcMacStatsInd: Received Statistics Indication"); + DU_LOG("\nMeasurement type [%d] Measurement Value [%d]", statsInd->type, statsInd->value); + + /* TODO : When stats indication is received + * DU APP searches for the message type in E2AP RIC subscription database + * and stores in the value in the list of subscribed measurements + * + * This will be implemented in next gerrit. + */ + + DU_FREE_SHRABL_BUF(DU_APP_MEM_REGION, DU_POOL, statsInd, sizeof(MacStatsInd)); + return ROK; + } + + DU_LOG("\nINFO --> DU_APP : DuProcMacStatsInd: Received NULL Pointer"); + return RFAILED; +} + /********************************************************************** End of file **********************************************************************/ diff --git a/src/du_app/du_tmr.c b/src/du_app/du_tmr.c index 432a3d368..3d89d9857 100644 --- a/src/du_app/du_tmr.c +++ b/src/du_app/du_tmr.c @@ -84,7 +84,7 @@ void duStartTmr(PTR cb, int16_t tmrEvnt, uint8_t timerValue) case EVENT_E2_SETUP_TMR: { e2apDb = ((E2apDb *)cb); - DU_TMR_CALCUATE_WAIT(arg.wait, timerValue, duCb.duTimersInfo.tmrRes); + TMR_CALCUATE_WAIT(arg.wait, timerValue, duCb.duTimersInfo.tmrRes); arg.timers = &e2apDb->e2TimersInfo.e2Timers.e2SetupTimer; arg.max = MAX_E2_SETUP_TMR; diff --git a/src/du_app/du_tmr.h b/src/du_app/du_tmr.h index d7529b77c..969724f58 100644 --- a/src/du_app/du_tmr.h +++ b/src/du_app/du_tmr.h @@ -19,6 +19,7 @@ #define DU_TIMER_RESOLUTION 1 #define DU_TQ_SIZE 2 +#if 0 /** * @def DU_TMR_CALCUATE_WAIT * @@ -40,6 +41,7 @@ (_wait) = 1; \ } \ } +#endif short int duActvTmr(Ent ent,Inst inst); bool duChkTmr(PTR cb, int16_t tmrEvnt); diff --git a/src/phy_stub/phy_stub_msg_hdl.c b/src/phy_stub/phy_stub_msg_hdl.c index 2e8378d3d..1b709ab15 100644 --- a/src/phy_stub/phy_stub_msg_hdl.c +++ b/src/phy_stub/phy_stub_msg_hdl.c @@ -1230,6 +1230,7 @@ S16 l1HdlUlTtiReq(uint16_t msgLen, void *msg) { DU_LOG("\nINFO --> PHY STUB: PRACH PDU"); +#if 0 /* Send RACH Ind to L2 for first UE */ if(phyDb.ueDb.ueCb[UE_IDX_0].rachIndSent == false) { @@ -1238,7 +1239,6 @@ S16 l1HdlUlTtiReq(uint16_t msgLen, void *msg) l1BuildAndSendRachInd(ulTtiReq->slot, ulTtiReq->sfn, CB_RA_PREAMBLE_IDX); phyDb.ueDb.numActvUe++; } -#if 0 /* Send RACH Ind to L2 for second UE */ if(phyDb.ueDb.ueCb[UE_IDX_1].rachIndSent == false && phyDb.ueDb.ueCb[UE_IDX_0].msgRrcReconfigComp == true) { diff --git a/tools/Memory_Leak_Detector/alloc.txt b/tools/Memory_Leak_Detector/alloc.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/tools/Memory_Leak_Detector/free.txt b/tools/Memory_Leak_Detector/free.txt deleted file mode 100644 index e69de29bb..000000000