From 6bd517aac8dc6e3166389be3f468c58ba56d5608 Mon Sep 17 00:00:00 2001 From: "lal.harshita" Date: Thu, 27 Oct 2022 23:37:14 +0530 Subject: [PATCH] [Epic-ID: ODUHIGH-462][Task-ID: ODUHIGH-472] Implementation of drx timer [Onduration timer, short cycle timer, in active drx timer] Signed-off-by: lal.harshita Change-Id: Id2c5b1bb4bdd290a91f57f2d7233f925891270c4 Signed-off-by: lal.harshita --- src/5gnrmac/mac_ue_mgr.c | 8 +- src/5gnrsch/sch.c | 11 + src/5gnrsch/sch.h | 80 ++++ src/5gnrsch/sch_common.c | 10 + src/5gnrsch/sch_crc.c | 51 +- src/5gnrsch/sch_drx.c | 1007 +++++++++++++++++++++++++++++++++++++++ src/5gnrsch/sch_drx.h | 55 +++ src/5gnrsch/sch_slot_ind.c | 36 +- src/5gnrsch/sch_ue_mgr.c | 60 ++- src/cm/du_app_mac_inf.h | 4 + src/cm/mac_sch_interface.h | 4 + src/cu_stub/cu_f1ap_msg_hdl.c | 70 ++- src/cu_stub/cu_stub.h | 7 + src/du_app/du_f1ap_msg_hdl.c | 205 ++++---- src/du_app/du_mgr.h | 1 + src/du_app/du_mgr_main.c | 12 +- src/du_app/du_ue_mgr.c | 5 + src/phy_stub/phy_stub_msg_hdl.c | 3 +- 18 files changed, 1480 insertions(+), 149 deletions(-) create mode 100644 src/5gnrsch/sch_drx.c create mode 100644 src/5gnrsch/sch_drx.h diff --git a/src/5gnrmac/mac_ue_mgr.c b/src/5gnrmac/mac_ue_mgr.c index b83130e5e..2e7e9d69b 100644 --- a/src/5gnrmac/mac_ue_mgr.c +++ b/src/5gnrmac/mac_ue_mgr.c @@ -138,7 +138,7 @@ uint8_t fillMacCellGroupCfg(MacCellGrpCfg macCellGrp, SchMacCellGrpCfg *macCell #ifdef NR_DRX /* Copy Drx configuration */ - + macCellGrpCfg->drxCfgPresent = true; macCellGrpCfg->drxCfg.drxOnDurationTimer.onDurationTimerValInMs = macCellGrp.drxCfg.drxOnDurationTimer.onDurationTimerValInMs; if(!macCellGrp.drxCfg.drxOnDurationTimer.onDurationTimerValInMs) macCellGrpCfg->drxCfg.drxOnDurationTimer.onDurationtimerValue.subMilliSeconds = \ @@ -1710,6 +1710,12 @@ uint8_t fillSchUeCfg(Pst *pst, SchUeCfg *schUeCfg, MacUeCfg *ueCfg) DU_LOG("\nERROR --> MAC : Failed to copy LCs at fillSchUeCfg()"); return ret; } +#ifdef NR_DRX + if(ueCfg->drxConfigIndicatorRelease) + { + schUeCfg->drxConfigIndicatorRelease = true; + } +#endif return ret; } diff --git a/src/5gnrsch/sch.c b/src/5gnrsch/sch.c index 3e485c4a5..2e9a16c85 100644 --- a/src/5gnrsch/sch.c +++ b/src/5gnrsch/sch.c @@ -666,6 +666,10 @@ uint8_t schInitCellCb(Inst inst, SchCellCfg *schCellCfg) cell->firstSib1Transmitted = false; fillSsbStartSymb(cell); cmLListInit(&cell->ueToBeScheduled); + +#ifdef NR_DRX + memset(cell->drxCb, 0, MAX_DRX_SIZE*sizeof(SchDrxCb)); +#endif schCb[inst].cells[inst] = cell; DU_LOG("\nINFO --> SCH : Cell init completed for cellId:%d", cell->cellId); @@ -1114,6 +1118,13 @@ uint8_t MacSchSrUciInd(Pst *pst, SrUciIndInfo *uciInd) DU_LOG("\nINFO --> SCH: UL Data transmission not allowed for UE %d", ueCb->ueCfg.ueId); return ROK; } +#ifdef NR_DRX + if(ueCb->ueDrxInfoPres) + { + if(!ueCb->drxUeCb.drxUlUeActiveStatus) + ueCb->drxUeCb.drxUlUeActiveStatus = true; + } +#endif if(uciInd->numSrBits) { ueCb->srRcvd = true; diff --git a/src/5gnrsch/sch.h b/src/5gnrsch/sch.h index 4281ef808..11248c12c 100644 --- a/src/5gnrsch/sch.h +++ b/src/5gnrsch/sch.h @@ -69,6 +69,13 @@ #define HQ_NACK 1 #define HQ_DTX 2 +#ifdef NR_DRX +/* As per 38.331 the largest offset which can be used in of size 10240. + * But using this much size of array can cause memory related issue so thats why + * taking this size which are a multiple of the larger size */ +#define MAX_DRX_SIZE 512 +#endif + typedef struct schDlHqProcCb SchDlHqProcCb; typedef struct schUlHqEnt SchUlHqEnt; typedef struct schRaReq SchRaReq; @@ -92,6 +99,7 @@ typedef enum SCH_UE_HANDIN_IN_PROGRESS }SchUeState; + typedef enum { SCH_RA_STATE_MSG2_HANDLE, @@ -178,6 +186,17 @@ typedef struct schDlHqTbCb uint8_t statsBitmap; }SchDlHqTbCb; +#ifdef NR_DRX +typedef struct schDrxHarqCb +{ + uint32_t retxStrtIndex; + uint32_t rttIndex; + uint32_t retxIndex; + int16_t retxExpDistance; + uint8_t retxTmrReduction; +}SchDrxHarqCb; +#endif + typedef struct schUlHqProcCb { uint8_t procId; /*!< HARQ Process ID */ @@ -196,6 +215,9 @@ typedef struct schUlHqProcCb uint8_t dmrsMappingType; uint8_t nrOfDmrsSymbols; uint8_t dmrsAddPos; +#ifdef NR_DRX + SchDrxHarqCb drxHarqCb; +#endif }SchUlHqProcCb; struct schDlHqProcCb @@ -209,6 +231,9 @@ struct schDlHqProcCb uint8_t k1; SchLcPrbEstimate dlLcPrbEst; /*DL PRB Alloc Estimate among different LC*/ CmLList dlHqProcLink; +#ifdef NR_DRX + SchDrxHarqCb drxHarqCb; +#endif }; struct schUlHqEnt { @@ -385,6 +410,38 @@ typedef struct schHqUlMap CmLListCp hqList; }SchHqUlMap; +#ifdef NR_DRX +typedef struct schDrxUeCb +{ + bool drxDlUeActiveStatus; /* This variable is used to store the status about downlink active status */ + bool drxUlUeActiveStatus; /* This variable is used to store the status about uplink active status */ + uint32_t onDurationLen; /* on duration value recived from ue cfg/recfg */ + uint32_t inActvTimerLen; /* inActvTimer value recived from ue cfg/recfg */ + uint8_t harqRttDlTimerLen; /* harqRttDlTimer value recived from ue cfg/recfg */ + uint8_t harqRttUlTimerLen; /* harqRttUlTimer value recived from ue cfg/recfg */ + uint32_t retransDlTimerLen; /* retransDlTimer value recived from ue cfg/recfg */ + uint32_t retransUlTimerLen; /* retransUlTimer value recived from ue cfg/recfg */ + uint32_t longCycleLen; /* long Cycle value recived from ue cfg/recfg */ + bool longCycleToBeUsed; /* long cycle should be used once the short cycle gets expires */ + uint32_t drxStartOffset; /* drxStartOffset value recived from ue cfg/recfg */ + bool shortCyclePresent; /* shortCyclePresent value recived from ue cfg/recfg */ + uint32_t shortCycleLen; /* short Cycle value recived from ue cfg/recfg */ + uint32_t shortCycleTmrLen; /* shortCycleTmr value recived from ue cfg/recfg */ + uint32_t drxSlotOffset; /* drxSlotOffset value recived from ue cfg/recfg */ + uint32_t onDurationStartIndex; /* Index at which UE is stored in onDuration starts list */ + uint32_t onDurationExpiryIndex; /* Index at which UE is stored in onDuration expires in the list */ + uint32_t inActvExpiryIndex; /* Index at which UE is stored in inActvTimer expires in the list */ + uint32_t shortCycleExpiryIndex; /* Index at which UE is stored in shortCycle expires in the list */ + int32_t shortCycleDistance; /* Distance after how many slot short cycle tmr gets expire */ + int32_t onDurationStartDistance;/* Distance after how many slot on Duration Start tmr gets expire */ + int32_t onDurationExpiryDistance;/* Distance after how many slot on Duration tmr gets expire */ + int32_t inActiveTmrExpiryDistance;/* Distance after how many slot inActive tmr gets expire */ + CmLList *onDurationStartNodeInfo; + CmLList *onDurationExpiryNodeInfo; + CmLList *inActvTimerExpiryNodeInfo; + CmLList *shortCycleTmrExpiryNodeInfo; +}SchDrxUeCb; +#endif /** * @brief * UE control block @@ -410,6 +467,10 @@ typedef struct schUeCb SchHqUlMap **hqUlmap; CmLListCp ulRetxHqList; CmLListCp dlRetxHqList; +#ifdef NR_DRX + bool ueDrxInfoPres; + SchDrxUeCb drxUeCb; +#endif }SchUeCb; /** @@ -448,6 +509,22 @@ typedef struct schPageCb SchPagingOcc pagMonOcc[MAX_PO_PER_PF]; /*Paging Occasion Slot/FrameOffset are stored*/ }SchPageCb; +#ifdef NR_DRX +typedef struct schDrxCb +{ + CmLListCp onDurationStartList; /*!< Tracks the start of onDuration Timer. */ + CmLListCp onDurationExpiryList; /*!< Tracks the Expiry of onDuration Timer. */ + CmLListCp inActvTmrExpiryList; /*!< Tracks the Expiry of drx-InactivityTimer. */ + CmLListCp shortCycleExpiryList; /*!< Tracks the Expiry of DRX Short Cycle. */ + CmLListCp dlHarqRttExpiryList; /*!< Tracks the Expiry of DL HARQ RTT timer. */ + CmLListCp dlRetransExpiryList; /*!< Tracks the Expiry of DL Re-Transmission timer. */ + CmLListCp ulHarqRttExpiryList; /*!< Tracks the Expiry of UL HARQ RTT timer. */ + CmLListCp ulRetransExpiryList; /*!< Tracks the Expiry of UL Re-Transmission timer. */ + CmLListCp dlRetransTmrStartList; /*!< It has list of DL harq procs for */ + CmLListCp ulRetransTmrStartList; /*!< It has list of UL harq procs for */ +}SchDrxCb; +#endif + /** * @brief * Cell Control block per cell. @@ -479,6 +556,9 @@ typedef struct schCellCb uint32_t slotFrmtBitMap; /*!< 2 bits must be read together to determine D/U/S slots. 00-D, 01-U, 10-S */ uint32_t symbFrmtBitMap; /*!< 2 bits must be read together to determine D/U/S symbols. 00-D, 01-U, 10-S */ #endif +#ifdef NR_DRX + SchDrxCb drxCb[MAX_DRX_SIZE]; /*!< Drx cb*/ +#endif }SchCellCb; diff --git a/src/5gnrsch/sch_common.c b/src/5gnrsch/sch_common.c index bc5ca0f15..204affa50 100644 --- a/src/5gnrsch/sch_common.c +++ b/src/5gnrsch/sch_common.c @@ -470,6 +470,7 @@ uint16_t fillPucchResourceInfo(SchPucchInfo *schPucchInfo, Inst inst, SlotTiming uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst) { int ret = ROK; + SchUeCb *ueCb; UlSchedInfo ulSchedInfo; SchUlSlotInfo *schUlSlotInfo = NULLP; SlotTimingInfo ulTimingInfo; @@ -491,6 +492,15 @@ uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst) if(schUlSlotInfo->schPuschInfo) { ulSchedInfo.crnti = schUlSlotInfo->schPuschInfo->crnti; + /* Check the ue drx status if the UE is active for uplink scheduling or not */ +#ifdef NR_DRX + ueCb = schGetUeCb(cell, ulSchedInfo.crnti); + if(ueCb->ueDrxInfoPres) + { + if(ueCb->drxUeCb.drxUlUeActiveStatus) + return RFAILED; + } +#endif ulSchedInfo.dataType |= SCH_DATATYPE_PUSCH; memcpy(&ulSchedInfo.schPuschInfo, schUlSlotInfo->schPuschInfo, sizeof(SchPuschInfo)); diff --git a/src/5gnrsch/sch_crc.c b/src/5gnrsch/sch_crc.c index 4aa9f81c1..406d67f4f 100644 --- a/src/5gnrsch/sch_crc.c +++ b/src/5gnrsch/sch_crc.c @@ -76,35 +76,38 @@ uint8_t schProcessCrcInd(CrcIndInfo *crcInd, Inst schInst) } else { - if (cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList.count == 0) + if(cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]) { - DU_LOG("\n ERROR no harq stored in ul hq map at slot %d ue id %d\n",crcInd->timingInfo.slot, ueId); - continue; - } - if (cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList.first == 0) - { - DU_LOG("\n ERROR NULL harq stored in ul hq map at slot %d ue id %d\n",crcInd->timingInfo.slot, ueId); - continue; - } - hqP = (SchUlHqProcCb*) cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList.first->node; - if(hqP == NULLP) - { - continue; - } - else - { - if (crcInd->crcInd[count]) - { - /* failure case*/ - schUlHqProcessNack(hqP); + if (cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList.count == 0) + { + DU_LOG("\n ERROR no harq stored in ul hq map at slot %d ue id %d\n",crcInd->timingInfo.slot, ueId); + continue; + } + if (cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList.first == 0) + { + DU_LOG("\n ERROR NULL harq stored in ul hq map at slot %d ue id %d\n",crcInd->timingInfo.slot, ueId); + continue; + } + hqP = (SchUlHqProcCb*) cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList.first->node; + if(hqP == NULLP) + { + continue; } else { - /* pass case*/ - schUlHqProcessAck(hqP); + if (crcInd->crcInd[count]) + { + /* failure case*/ + schUlHqProcessNack(hqP); + } + else + { + /* pass case*/ + schUlHqProcessAck(hqP); + } } + cmLListDelFrm(&(cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList), &hqP->ulSlotLnk); } - cmLListDelFrm(&(cell->ueCb[ueId-1].hqUlmap[crcInd->timingInfo.slot]->hqList), &hqP->ulSlotLnk); } count++; } @@ -112,4 +115,4 @@ uint8_t schProcessCrcInd(CrcIndInfo *crcInd, Inst schInst) } /********************************************************************** End of file - **********************************************************************/ \ No newline at end of file + **********************************************************************/ diff --git a/src/5gnrsch/sch_drx.c b/src/5gnrsch/sch_drx.c new file mode 100644 index 000000000..66ab9d0a9 --- /dev/null +++ b/src/5gnrsch/sch_drx.c @@ -0,0 +1,1007 @@ + +/******************************************************************************* +################################################################################ +# 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. # +################################################################################ + *******************************************************************************/ +#ifdef NR_DRX +#include "common_def.h" +#include "tfu.h" +#include "lrg.h" +#include "tfu.x" +#include "lrg.x" +#include "du_log.h" +#include "du_app_mac_inf.h" +#include "mac_sch_interface.h" +#include "sch.h" +#include "sch_utils.h" +#include "sch_drx.h" + +/** + * @brief intialize the SchDrxHarqCb structre + * + * @details + * + * Function :schInitDrxHarqCb + * + * intialize the SchDrxHarqCb structre + * + * @param[in] SchDrxHarqCb *hqCb + * @return + * -# ROK + * -# RFAILED + **/ +void schInitDrxHarqCb(SchDrxHarqCb *hqDrxCb) +{ + memset(hqDrxCb, 0, sizeof(SchDrxHarqCb)); + hqDrxCb->retxExpDistance = SCH_DRX_INVALID_DISTANCE; + hqDrxCb->retxStrtIndex = SCH_DRX_INVALID_INDEX; + hqDrxCb->rttIndex = SCH_DRX_INVALID_INDEX; + hqDrxCb->retxIndex = SCH_DRX_INVALID_INDEX; +} + +/** + * @brief intialize the SchDrxUeCb structre + * + * @details + * + * Function : schInitDrxUeCb + * + * intialize the SchDrxUeCb structre + * + * @param[in] SchUeCb *ueCb + * @return + * -# ROK + * -# RFAILED + **/ +void schInitDrxUeCb(SchUeCb *ueCb) +{ + memset(&ueCb->drxUeCb, 0, sizeof(SchDrxUeCb)); + ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX; + ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX; + ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX; + ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX; + ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE; + ueCb->drxUeCb.onDurationExpiryDistance = SCH_DRX_INVALID_DISTANCE; + ueCb->drxUeCb.inActiveTmrExpiryDistance = SCH_DRX_INVALID_DISTANCE; + ueCb->drxUeCb.drxDlUeActiveStatus = false; + ueCb->drxUeCb.drxUlUeActiveStatus = false; +} +#if 0 +/* will uncomment this function in next gerrit */ +/** + * @brief delete Dl harq drx timers and information + * + * @details + * + * Function : schDeleteDlHarqDrxTimer + * + * delete Dl harq drx timers and information + * + * @param[in] SchCellCb *cell, SchUeCb *ueCb + * @return + * -# ROK + * -# RFAILED + **/ + void schDeleteDlHarqDrxTimer(SchCellCb *cell, SchDlHqEnt *dlHqEnt) + { + uint8_t idx, numHqPrcs; + uint16_t tmrIdx = 0; + SchDlHqProcCb *procs; + CmLList *node = NULLP; + + numHqPrcs = dlHqEnt->numHqPrcs; + for(idx =0; idxprocs[idx]; + tmrIdx = procs->drxHarqCb.retxStrtIndex; + CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node); + if(node) + { + cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransTmrStartList, node); + SCH_FREE(node, sizeof(CmLList)); + } + + tmrIdx = procs->drxHarqCb.rttIndex; + CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node); + if(node) + { + cmLListDelFrm(&cell->drxCb[tmrIdx].dlHarqRttExpiryList, node); + SCH_FREE(node, sizeof(CmLList)); + } + + tmrIdx = procs->drxHarqCb.retxIndex; + CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].dlRetransExpiryList, node); + if(node) + { + cmLListDelFrm(&cell->drxCb[tmrIdx].dlRetransExpiryList, node); + SCH_FREE(node, sizeof(CmLList)); + } + schInitDrxHarqCb(&procs->drxHarqCb); + } + } + +/** + * @brief delete UL harq drx timers and information + * + * @details + * + * Function : schDeleteUlHarqDrxTimer + * + * delete Ul harq drx timers and information + * + * @param[in] SchCellCb *cell, SchUeCb *ueCb + * @return + * -# ROK + * -# RFAILED + **/ + void schDeleteUlHarqDrxTimer(SchCellCb *cell, SchUlHqEnt *ulHqEnt) + { + uint8_t idx, numHqPrcs; + uint16_t tmrIdx = 0; + CmLList *node = NULLP; + SchUlHqProcCb *procs; + + numHqPrcs = ulHqEnt->numHqPrcs; + for(idx =0; idxprocs[idx]; + tmrIdx = procs->drxHarqCb.retxStrtIndex; + CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node); + if(node) + { + cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransTmrStartList, node); + SCH_FREE(node, sizeof(CmLList)); + } + + tmrIdx = procs->drxHarqCb.rttIndex; + CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node); + if(node) + { + cmLListDelFrm(&cell->drxCb[tmrIdx].ulHarqRttExpiryList, node); + SCH_FREE(node, sizeof(CmLList)); + } + + tmrIdx = procs->drxHarqCb.retxIndex; + CM_LLIST_FIRST_NODE(&cell->drxCb[tmrIdx].ulRetransExpiryList, node); + if(node) + { + cmLListDelFrm(&cell->drxCb[tmrIdx].ulRetransExpiryList, node); + SCH_FREE(node, sizeof(CmLList)); + } + schInitDrxHarqCb(&procs->drxHarqCb); + } + } +#endif +/** + * @brief delete UE drx timers and information + * + * @details + * + * Function : schDeleteUeDrxInfo + * + * delete UE drx timers and information + * + * @param[in] SchCellCb *cell, SchUeCb *ueCb + * @return + * -# ROK + * -# RFAILED + **/ +void schDeleteUeDrxInfo(SchCellCb *cell, SchUeCb *ueCb) +{ + SchDrxUeCb *drxUeCb; + + if(ueCb->ueDrxInfoPres == true) + { + drxUeCb = &ueCb->drxUeCb; + + /* delete on duration start timer from ueCb */ + if(drxUeCb->onDurationStartIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationStartIndex].onDurationStartList, drxUeCb->onDurationStartNodeInfo); + SCH_FREE(drxUeCb->onDurationStartNodeInfo, sizeof(CmLList)); + } + + /* delete on duration expiry timer from ueCb */ + if(drxUeCb->onDurationExpiryIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[drxUeCb->onDurationExpiryIndex].onDurationExpiryList, drxUeCb->onDurationExpiryNodeInfo); + SCH_FREE(drxUeCb->onDurationExpiryNodeInfo, sizeof(CmLList)); + } + + /* delete inActv Expiry Index timer from ueCb */ + if(drxUeCb->inActvExpiryIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[drxUeCb->inActvExpiryIndex].inActvTmrExpiryList, drxUeCb->inActvTimerExpiryNodeInfo); + SCH_FREE(drxUeCb->inActvTimerExpiryNodeInfo, sizeof(CmLList)); + } + + /* delete short cycle expiry timer from ueCb */ + if(drxUeCb->shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[drxUeCb->shortCycleExpiryIndex].shortCycleExpiryList, drxUeCb->shortCycleTmrExpiryNodeInfo); + SCH_FREE(drxUeCb->shortCycleTmrExpiryNodeInfo, sizeof(CmLList)); + } + /* TODO - will uncomment this function in next gerrit */ + //schDeleteDlHarqDrxTimer(cell, &ueCb->dlHqEnt); + //schDeleteUlHarqDrxTimer(cell, &ueCb->ulHqEnt); + schInitDrxUeCb(ueCb); + } +} + +/** + * @brief fill drxUeCb structure with the help of ue cfg/recfg information + * + * @details + * + * Function : schFillDrxUeCb + * + * fill drxUeCb structure with the help of ue cfg/recfg information + * + * @param[in] SchDrxCfg drxCfg ->configuration received from ue cfg/recfg api + * SchDrxUeCb *drxUeCb -> structure that need to be fill + * @return + * -# ROK + * -# RFAILED + **/ +void schFillDrxUeCb(uint8_t numerology, SchDrxCfg drxCfg, SchDrxUeCb *drxUeCb) +{ + if(drxCfg.drxOnDurationTimer.onDurationTimerValInMs) + { + SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.milliSeconds, numerology); + } + else + { + SCH_CNVRT_MS_TO_SLOT(drxUeCb->onDurationLen, drxCfg.drxOnDurationTimer.onDurationtimerValue.subMilliSeconds, numerology); + drxUeCb->onDurationLen = drxUeCb->onDurationLen >> 5; + } + SCH_CNVRT_MS_TO_SLOT(drxUeCb->inActvTimerLen, drxCfg.drxInactivityTimer, numerology); + SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttDlTimerLen, drxCfg.drxHarqRttTimerDl); + SCH_CNVRT_SYMBL_TO_SLOT(drxUeCb->harqRttUlTimerLen, drxCfg.drxHarqRttTimerUl); + SCH_CNVRT_MS_TO_SLOT(drxUeCb->retransDlTimerLen, drxCfg.drxRetransmissionTimerDl, numerology); + SCH_CNVRT_MS_TO_SLOT(drxUeCb->retransUlTimerLen, drxCfg.drxRetransmissionTimerUl, numerology); + SCH_CNVRT_MS_TO_SLOT(drxUeCb->longCycleLen, drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetChoice, numerology); + drxUeCb->drxStartOffset = drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetVal; + if(drxCfg.shortDrxPres) + { + drxUeCb->shortCyclePresent = true; + SCH_CNVRT_MS_TO_SLOT(drxUeCb->shortCycleLen, drxCfg.shortDrx.drxShortCycle, numerology); + drxUeCb->shortCycleTmrLen = drxCfg.shortDrx.drxShortCycleTimer; + } + else + drxUeCb->longCycleToBeUsed = true; + SCH_CNVRT_MS_TO_SLOT(drxUeCb->drxSlotOffset, drxCfg.drxSlotOffset, numerology); + drxUeCb->drxSlotOffset = drxUeCb->drxSlotOffset>>5; +} + +/** + * @brief Add new entry into the drx timer list + * + * @details + * + * Function : schAddDrxTimerIntoList + * + * Add new entry into the drx timer list + * + * @param[in] CmLListCp *drxTimerList -> List in which new entery have to add + * void * ueInfo -> ue information which is need to the added into list + * @return + * -# ROK + * -# RFAILED + **/ +uint8_t schAddDrxTimerIntoList(CmLListCp *drxTimerList,void * nodeInfo, CmLList *drxNodeInfo) +{ + CmLList *currentNodeInfo = NULLP; + + SCH_ALLOC(currentNodeInfo, sizeof(CmLList)); + if(!currentNodeInfo) + { + DU_LOG("\nERROR --> SCH : schAddDrxTimerIntoList() : Memory allocation failed"); + return RFAILED; + } + + currentNodeInfo->node = (PTR)nodeInfo; + + cmLListAdd2Tail(drxTimerList, currentNodeInfo); + drxNodeInfo = currentNodeInfo; + return ROK; +} + +/** + * @brief This function is used to find the next onduration start timing + * + * @details + * + * Function : findNextOndurationOccurance + * + * This function is used to find the next onduration start timing + * + * @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur, + * uint8_t delta + * + * @return + * -# void + **/ +void findNextOndurationOccurance(SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur, uint8_t delta) +{ + uint16_t resultX, reusltY, idx; + uint32_t curTime, cycleLen, nxtDist; + SlotTimingInfo tmpTime; + + if (ueDrxCb->longCycleToBeUsed == true) + { + cycleLen = ueDrxCb->longCycleLen; + } + else + { + cycleLen = ueDrxCb->shortCycleLen; + } + + /* Add delta to current time */ + ADD_DELTA_TO_TIME(cell->slotInfo, tmpTime, delta); + + /* Convert tmpTime to number of slots */ + curTime = ((tmpTime.sfn * MAX_SLOTS) + tmpTime.slot); + + /* as per 38.321, if the criterion below is satisfied, then that sfn and + * slot are the correct ones for the on-duration timer. + * if the Short DRX Cycle is used, and [(SFN × 10) + subframe number] modulo + * (drx-ShortCycle) = (drxStartOffset) modulo (drx-ShortCycle); or + * if the Long DRX Cycle is used, and [(SFN × 10) + subframe number] modulo + * (drx-LongCycle) = drxStartOffset */ + for(idx =1; idxshortCyclePresent) + reusltY = ueDrxCb->drxStartOffset; + else + reusltY = ueDrxCb->drxStartOffset % cycleLen; + if(resultX == reusltY) + { + memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo)); + nxtDist = ((nxtOnDur->sfn * MAX_SLOTS) + nxtOnDur->slot); + break; + } + else + { + ADD_DELTA_TO_TIME(tmpTime, tmpTime, 1); + } + } + + /* If slot offset is non-zero then Add slot offset to the calculated onDur + * distance */ + if(ueDrxCb->drxSlotOffset) + { + nxtDist = nxtDist + ueDrxCb->drxSlotOffset; + ADD_DELTA_TO_TIME(tmpTime, tmpTime, ueDrxCb->drxSlotOffset); + memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo)); + } + /*If next On Duration is less than DL DELTA ahead, we will miss it and + * hence need to move to the On-Duration after that.*/ + if((nxtDist - (curTime - delta)) <= SCH_DRX_MAX_DELTA) + { + ADD_DELTA_TO_TIME(tmpTime, tmpTime, cycleLen); + memcpy(nxtOnDur, &tmpTime, sizeof(SlotTimingInfo)); + } +} + +/** + * @brief Add entry into the on duration list and short cycle list + * + * @details + * + * Function : schDrxUeReCfgTimer + * + * This function is used to Add entry into the on duration list and short + * cycle list + * + * @param[in] SchCellCb *cell, SchUeCb *ueCb + * uint8_t delta + * + * @return + **/ +void schDrxUeReCfgTimer(SchCellCb *cell, SchUeCb *ueCb) +{ + uint8_t onDurIndx, currentSlotIndx; + uint32_t onDurTime, onDurExpSlotTime, currentSlotTime; + uint32_t cycleLen; + SlotTimingInfo onDurationOccurance; + + if(ueCb->drxUeCb.shortCyclePresent == false) + { + /* if short cycle configuration are not recived as a part of UE Recfg then if there is any entry present in short cycle timer list + * remove the entry from the list */ + if(ueCb->drxUeCb.shortCycleExpiryIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.shortCycleExpiryIndex ].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo); + SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX; + ueCb->drxUeCb.shortCycleDistance = SCH_DRX_INVALID_DISTANCE; + } + } + /* If there is any entry present in on duration start list then remove the + * entry from the list and recaluate the nect onduration cucurance */ + if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo); + SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX; + ueCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE; + } + + findNextOndurationOccurance(cell, &ueCb->drxUeCb, &onDurationOccurance, 0); + onDurTime = onDurationOccurance.sfn*MAX_SLOTS+onDurationOccurance.slot; + onDurIndx = onDurTime%MAX_DRX_SIZE; + /* If Onduration timer of old configuration is already running then next onduration + * starts once it expires*/ + if((ueCb->drxUeCb.onDurationExpiryDistance != SCH_DRX_INVALID_DISTANCE) && (ueCb->drxUeCb.onDurationExpiryIndex == SCH_DRX_INVALID_INDEX)) + { + currentSlotTime = cell->slotInfo.sfn * MAX_SLOTS + cell->slotInfo.slot; + currentSlotIndx = (currentSlotTime + PHY_DELTA_DL + SCHED_DELTA)%MAX_DRX_SIZE; + if(currentSlotIndx >= ueCb->drxUeCb.onDurationExpiryIndex ) + { + onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance +1) * MAX_DRX_SIZE) + (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA); + } + else + { + + onDurExpSlotTime = currentSlotTime + ((ueCb->drxUeCb.onDurationExpiryDistance) * MAX_DRX_SIZE) + (ueCb->drxUeCb.onDurationExpiryIndex - currentSlotIndx + PHY_DELTA_DL + SCHED_DELTA); + } + if(onDurTime <= onDurExpSlotTime) + { + if(ueCb->drxUeCb.longCycleToBeUsed == true) + cycleLen = ueCb->drxUeCb.longCycleLen; + else + cycleLen = ueCb->drxUeCb.shortCycleLen; + + onDurTime = onDurTime + ((onDurExpSlotTime - onDurTime)/cycleLen + 1) * cycleLen; + } + } + onDurIndx = onDurTime%MAX_DRX_SIZE; + ueCb->drxUeCb.onDurationStartIndex = onDurIndx; + ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, MAX_SLOTS)/MAX_DRX_SIZE; + schAddDrxTimerIntoList(&cell->drxCb[onDurIndx].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo); + if((TRUE == ueCb->drxUeCb.shortCyclePresent) &&(ueCb->drxUeCb.longCycleToBeUsed == false)) + { + /* Starting Short Cycle Timer */ + ueCb->drxUeCb.shortCycleDistance = (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen) / MAX_DRX_SIZE; + ueCb->drxUeCb.shortCycleExpiryIndex = (onDurTime + (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen)) % MAX_DRX_SIZE; + schAddDrxTimerIntoList(&cell->drxCb[ ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo); + DU_LOG("\nPBORLA ShortCycleE Added %d",ueCb->drxUeCb.shortCycleExpiryIndex); + } +} +/** + * @brief Add entry into the on duration list and short cycle list + * + * @details + * + * Function : schAddUeInOndurationAndShortCycleList + * + * This function is used to Add entry into the on duration list and short + * cycle list + * + * @param[in] SchCellCb *cell, SchDrxUeCb *ueDrxCb, SlotTimingInfo *nxtOnDur, + * uint8_t delta + * + * @return + * -# void + **/ +void schAddUeInOndurationAndShortCycleList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta) +{ + uint8_t onDurIndx; + uint32_t onDurTime; + SlotTimingInfo onDurationOccurance; + + if(ueCb->ueDrxInfoPres) + { + findNextOndurationOccurance(cell, &ueCb->drxUeCb, &onDurationOccurance, delta); + onDurTime = onDurationOccurance.sfn*MAX_SLOTS+onDurationOccurance.slot; + onDurIndx = onDurTime%MAX_DRX_SIZE; + ueCb->drxUeCb.onDurationStartIndex = onDurIndx; + ueCb->drxUeCb.onDurationStartDistance = SCH_CALC_SLOT_DIFF(onDurationOccurance, cell->slotInfo, MAX_SLOTS)/MAX_DRX_SIZE; + schAddDrxTimerIntoList(&cell->drxCb[onDurIndx].onDurationStartList, ueCb, ueCb->drxUeCb.onDurationStartNodeInfo); + + if((TRUE == ueCb->drxUeCb.shortCyclePresent) &&(ueCb->drxUeCb.longCycleToBeUsed == false)) + { + /* Starting Short Cycle Timer */ + ueCb->drxUeCb.shortCycleDistance = (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen) / MAX_DRX_SIZE; + ueCb->drxUeCb.shortCycleExpiryIndex = (onDurTime + (ueCb->drxUeCb.shortCycleTmrLen * ueCb->drxUeCb.shortCycleLen)) % MAX_DRX_SIZE; + schAddDrxTimerIntoList(&cell->drxCb[ ueCb->drxUeCb.shortCycleExpiryIndex].shortCycleExpiryList, ueCb, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo); + DU_LOG("\nPBORLA ShortCycleE Added %d",ueCb->drxUeCb.shortCycleExpiryIndex); + } + } +} +/** + * @brief Handling of On duration drx start timer + * + * @details + * + * Function : schHdlDrxOnDurStrtTimerForUlandDlDirection + * + * Handling of On duration drx start timer + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxOnDurStrtTimerForUlandDlDirection(SchCellCb *cell, uint16_t currListIndx, bool isDlDirection) +{ + uint16_t onDurationExpiry=0; + CmLList *drxCurrNode = NULLP; + SchUeCb *ueCb = NULLP; + + drxCurrNode = cell->drxCb[currListIndx].onDurationStartList.first; + if(drxCurrNode) + { + /* Handling of dl On duration drx start list */ + while(drxCurrNode) + { + ueCb = (SchUeCb*)drxCurrNode->node; + ueCb->drxUeCb.onDurationStartDistance--; + if(ueCb->drxUeCb.onDurationStartDistance != SCH_DRX_INVALID_DISTANCE) + { + continue; + } + else + { + if(isDlDirection == true) + ueCb->drxUeCb.drxDlUeActiveStatus = true; + else + ueCb->drxUeCb.drxUlUeActiveStatus = true; + + DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__); + + /* If there is any entery present in onDurationExpiry list remove + * the entery from the list and recalculate the + * onDurationExpiry time and add it to list */ + if(ueCb->drxUeCb.onDurationExpiryIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationExpiryIndex].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo); + SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX; + } + + /* onDurationExpiry = (current slot + onduration length) % MAX_DRX_SIZE*/ + onDurationExpiry = (currListIndx + ueCb->drxUeCb.onDurationLen)%MAX_DRX_SIZE; + ueCb->drxUeCb.onDurationExpiryDistance = (ueCb->drxUeCb.onDurationLen)/MAX_DRX_SIZE; + schAddDrxTimerIntoList(&cell->drxCb[onDurationExpiry].onDurationExpiryList, ueCb, ueCb->drxUeCb.onDurationExpiryNodeInfo); + ueCb->drxUeCb.onDurationExpiryIndex = onDurationExpiry; + + /* if there is any entry present in onduration list remove the entry from the list */ + DU_LOG("\nPBORLA ONDURATION START HIT %d %d startIndx %d [%d %d]",\ + currListIndx, ueCb->drxUeCb.onDurationStartDistance,ueCb->drxUeCb.onDurationStartIndex, cell->slotInfo.sfn,cell->slotInfo.slot); + cmLListDelFrm(&cell->drxCb[currListIndx].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo); + SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX; + /* if there long cycle length is used as the cycle length for onduration calculation then based on that calculating next onduration occurance + * other wise next onduration is calcuated based on short cycle + * timer */ + if(ueCb->drxUeCb.longCycleToBeUsed) + { + schAddUeInOndurationAndShortCycleList(cell, ueCb, 0); + } + } + drxCurrNode = drxCurrNode->next; + } + } +} +/** + * @brief Handling of On duration drx start timer + * + * @details + * + * Function : schHdlDrxOnDurStrtTimer + * + * Handling of On duration drx start timer + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxOnDurStrtTimer(SchCellCb *cell) +{ + uint16_t dlIndx = 0, ulIndx=0; + SlotTimingInfo dlSlotInfo, ulSlotInfo; + + ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA); + ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA); + + dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE; + ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE; + schHdlDrxOnDurStrtTimerForUlandDlDirection(cell, dlIndx, true); + schHdlDrxOnDurStrtTimerForUlandDlDirection(cell, ulIndx, false); +} +/** + * @brief Handling of short cycle drx start timer + * + * @details + * + * Function : schHdlDrxStartShortCycleTimer + * + * Handling of short cycle drx start timer + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ + void schHdlDrxStartShortCycleTimer(SchCellCb *cell, SchUeCb *ueCb) + { + ueCb->drxUeCb.longCycleToBeUsed = false; + schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + } +/** + * @brief Handling of the DRX inactv timers start + * + * @details + * + * Function : schHdlDrxInActvStrtTmr + * + * Handling of DRX in active timers start + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ + void schHdlDrxInActvStrtTmr(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta) + { + uint16_t slotIndx = 0; + SlotTimingInfo tmpSlotInfo; + + if(ueCb->drxUeCb.inActvTimerLen == 0) + { + return; + } + ADD_DELTA_TO_TIME(cell->slotInfo, tmpSlotInfo, delta); + slotIndx = (tmpSlotInfo.sfn*MAX_SLOTS+tmpSlotInfo.slot)%MAX_DRX_SIZE; + + DU_LOG("\nPBORLA IN ACTV START HIT %d %d", cell->slotInfo.sfn, cell->slotInfo.slot); + /* if there is nay old entry present in the list remove the entry*/ + if(ueCb->drxUeCb.inActvExpiryIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo); + SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.inActvExpiryIndex= SCH_DRX_INVALID_INDEX; + ueCb->drxUeCb.inActiveTmrExpiryDistance= SCH_DRX_INVALID_DISTANCE; + } + /* Adding the new entry in in activity timer list */ + ueCb->drxUeCb.inActvExpiryIndex = (slotIndx + ueCb->drxUeCb.inActvTimerLen) % MAX_DRX_SIZE; + ueCb->drxUeCb.inActiveTmrExpiryDistance = (ueCb->drxUeCb.inActvTimerLen) / MAX_DRX_SIZE; + schAddDrxTimerIntoList(&cell->drxCb[ueCb->drxUeCb.inActvExpiryIndex].inActvTmrExpiryList, ueCb, ueCb->drxUeCb.inActvTimerExpiryNodeInfo); + + /* Set the UE active for UL And Dl transfer */ + ueCb->drxUeCb.drxDlUeActiveStatus = true; + ueCb->drxUeCb.drxUlUeActiveStatus = true; + DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__); + + } +/** + * @brief Handling of the DRX timers start + * + * @details + * + * Function : schHandleStartDrxTimer + * + * Handling of DRX timers start + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHandleStartDrxTimer(SchCellCb *cell) +{ + /* Handling the onduration start timea*/ + schHdlDrxOnDurStrtTimer(cell); +} + +/** + * @brief Handling of the expiry ShortCycle DRX timers + * + * @details + * + * Function : schHdlDrxShortCycleExpiryTimerForUlandDlDirection + * + * Handling of expiry ShortCycle + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxShortCycleExpiryTimerForUlandDlDirection(SchCellCb *cell, uint16_t currListIndx, bool isDlDirection) +{ + CmLList *drxCurrNode = NULLP; + SchUeCb *ueCb = NULLP; + SchUeCb *tempUeCb = NULLP; + + drxCurrNode = cell->drxCb[currListIndx].shortCycleExpiryList.first; + if(drxCurrNode) + { + /* Handling of dl On duration drx start list */ + while(drxCurrNode) + { + ueCb = (SchUeCb*)drxCurrNode->node; + if(ueCb->ueDrxInfoPres) + { + if(ueCb->drxUeCb.shortCycleDistance != SCH_DRX_INVALID_DISTANCE) + ueCb->drxUeCb.shortCycleDistance--; + + if(ueCb->drxUeCb.shortCycleDistance== SCH_DRX_INVALID_DISTANCE) + { + DU_LOG("\nPBORLA ShortCycleE EXP HIT %d",currListIndx); + ueCb->drxUeCb.longCycleToBeUsed = true; + /* Remove Short Cycle timer from the list */ + cmLListDelFrm(&cell->drxCb[currListIndx].shortCycleExpiryList, ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo); + SCH_FREE(ueCb->drxUeCb.shortCycleTmrExpiryNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.shortCycleExpiryIndex = SCH_DRX_INVALID_INDEX; + + /* calculating the next duration event  + If another entry is found in the On duration list, it must first be removed + before the next On duration occurrences may be calculated */ + if(ueCb->drxUeCb.onDurationStartIndex != SCH_DRX_INVALID_INDEX) + { + cmLListDelFrm(&cell->drxCb[ueCb->drxUeCb.onDurationStartIndex].onDurationStartList, ueCb->drxUeCb.onDurationStartNodeInfo); + SCH_FREE(ueCb->drxUeCb.onDurationStartNodeInfo, sizeof(CmLList)); + tempUeCb->drxUeCb.onDurationStartDistance = SCH_DRX_INVALID_DISTANCE; + tempUeCb->drxUeCb.onDurationStartIndex = SCH_DRX_INVALID_INDEX; + } + if(isDlDirection == true) + schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + else + schAddUeInOndurationAndShortCycleList(cell, ueCb, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + + } + else + continue; + } + drxCurrNode = drxCurrNode->next; + } + } +} + + +/** + * @brief Handling of the expiry ShortCycle DRX timers + * + * @details + * + * Function :schHdlDrxShortCycleExpiryTimer + * + * Handling of expiry ShortCycle + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxShortCycleExpiryTimer(SchCellCb *cell) +{ + uint16_t dlIndx = 0, ulIndx= 0; + SlotTimingInfo dlSlotInfo, ulSlotInfo; + + ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE; + ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE; + + schHdlDrxShortCycleExpiryTimerForUlandDlDirection(cell, dlIndx, true); + schHdlDrxShortCycleExpiryTimerForUlandDlDirection(cell, ulIndx, false); +} + +/** + * @brief Handling of the expiry onduration DRX timers for specific direction + * + * @details + * + * Function :schHdlDrxOnDurExpiryTimerForUlandDlDirection + * + * Handling of expiry onduration DRX timers + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxOnDurExpiryTimerForUlandDlDirection(SchCellCb *cell, uint16_t currListIndx, bool isDlDirection) +{ + CmLList *drxCurrNode; + SchUeCb *ueCb = NULLP; + + drxCurrNode = cell->drxCb[currListIndx].onDurationExpiryList.first; + if(drxCurrNode) + { + /* Handling of dl On duration drx start list */ + while(drxCurrNode) + { + ueCb = (SchUeCb*)drxCurrNode->node; + if(ueCb->ueDrxInfoPres) + { + ueCb->drxUeCb.onDurationExpiryDistance--; + + if(ueCb->drxUeCb.onDurationExpiryDistance== SCH_DRX_INVALID_DISTANCE) + { + + DU_LOG("\nPBORLA ONDURATION EXP HIT %d[%d:%d]",currListIndx, cell->slotInfo.sfn, cell->slotInfo.slot); + + /* delete on duration expiry timer from ueCb */ + if(drxCurrNode->node) + { + cmLListDelFrm(&cell->drxCb[currListIndx].onDurationExpiryList, ueCb->drxUeCb.onDurationExpiryNodeInfo); + SCH_FREE(ueCb->drxUeCb.onDurationExpiryNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.onDurationExpiryIndex = SCH_DRX_INVALID_INDEX; + } + if(isDlDirection == true) + ueCb->drxUeCb.drxDlUeActiveStatus = false; + else + ueCb->drxUeCb.drxUlUeActiveStatus = false; + DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__); + } + else + continue; + } + drxCurrNode = drxCurrNode->next; + } + } +} + + +/** + * @brief Handling of the expiry onduration DRX timers + * + * @details + * + * Function : schHdlDrxOnDurExpiryTimer + * + * Handling of expiry onduration DRX timers + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxOnDurExpiryTimer(SchCellCb *cell) +{ + uint16_t dlIndx = 0, ulIndx = 0; + SlotTimingInfo dlSlotInfo, ulSlotInfo; + + ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE; + ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE; + + schHdlDrxOnDurExpiryTimerForUlandDlDirection(cell, dlIndx, true); + schHdlDrxOnDurExpiryTimerForUlandDlDirection(cell, ulIndx, false); +} +/** + * @brief Handling of the expiry in active DRX timers in Dl and Ul direction + * + * @details + * + * Function : schHdlDrxInActvExpiryTimerForUlandDlDirection + * + * Handling of expiry in active DRX timers in DLand Ul direction + * + * @param[in] SchCellCb *cell, uint16_t dlIndx + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxInActvExpiryTimerForUlandDlDirection(SchCellCb *cell, uint16_t listIndx, bool isDlDirection) +{ + CmLList *drxNode; + SchUeCb *ueCb = NULLP; + + drxNode = cell->drxCb[listIndx].inActvTmrExpiryList.first; + if(drxNode) + { + /* Handling of dl On duration drx start list */ + while(drxNode) + { + ueCb = (SchUeCb*)drxNode->node; + ueCb->drxUeCb.inActiveTmrExpiryDistance--; + + if(ueCb->drxUeCb.onDurationExpiryDistance== SCH_DRX_INVALID_DISTANCE) + { + DU_LOG("\nPBORLA IN ACTV EXP HIT %d[%d:%d]",listIndx, cell->slotInfo.sfn, cell->slotInfo.slot); + /*Delete the current entry from list */ + if(drxNode->node) + { + cmLListDelFrm(&cell->drxCb[listIndx].inActvTmrExpiryList, ueCb->drxUeCb.inActvTimerExpiryNodeInfo); + SCH_FREE(ueCb->drxUeCb.inActvTimerExpiryNodeInfo, sizeof(CmLList)); + ueCb->drxUeCb.inActvExpiryIndex = SCH_DRX_INVALID_INDEX; + } + + /* If short cycle is configured then start the short cycle timer */ + if(ueCb->drxUeCb.shortCyclePresent) + { + schHdlDrxStartShortCycleTimer(cell, ueCb); + } + else + { + ueCb->drxUeCb.longCycleToBeUsed = true; + } + /* Set the drx ue status as inactive once the in active timer gets + * expire */ + if(isDlDirection == true) + ueCb->drxUeCb.drxDlUeActiveStatus = false; + else + ueCb->drxUeCb.drxUlUeActiveStatus = false; + DU_LOG("\nPBORLA drxUeCb.drxUlUeActiveStatus drxUeCb.drxDlUeActiveStatus [%d:%d] line %d", ueCb->drxUeCb.drxUlUeActiveStatus, ueCb->drxUeCb.drxDlUeActiveStatus,__LINE__); + + } + else + continue; + drxNode = drxNode->next; + } + } + +} +/** + * @brief Handling of the expiry in active DRX timers + * + * @details + * + * Function :schHdlDrxInActvExpiryTimer + * + * Handling of expiry in active DRX timers + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHdlDrxInActvExpiryTimer(SchCellCb *cell) +{ + uint16_t dlIndx = 0, ulIndx = 0; + SlotTimingInfo dlSlotInfo, ulSlotInfo; + + ADD_DELTA_TO_TIME(cell->slotInfo, dlSlotInfo, PHY_DELTA_DL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + ADD_DELTA_TO_TIME(cell->slotInfo, ulSlotInfo, PHY_DELTA_UL + SCHED_DELTA + SCH_DRX_TMRS_EXP_DELTA); + dlIndx = (dlSlotInfo.sfn*MAX_SLOTS+dlSlotInfo.slot)%MAX_DRX_SIZE; + ulIndx = (ulSlotInfo.sfn*MAX_SLOTS+ulSlotInfo.slot)%MAX_DRX_SIZE; + + schHdlDrxInActvExpiryTimerForUlandDlDirection(cell, dlIndx, true); + schHdlDrxInActvExpiryTimerForUlandDlDirection(cell, ulIndx, false); +}/** + * @brief Handling of the expiry DRX timers + * + * @details + * + * Function : schHandleExpiryDrxTimer + * + * Handling of expiry DRX timers + * + * @param[in] SchCellCb *cell + * @return + * -# ROK + * -# RFAILED + **/ +void schHandleExpiryDrxTimer(SchCellCb *cell) +{ + /* Handling the onduration start timer */ + schHdlDrxShortCycleExpiryTimer(cell); + schHdlDrxOnDurExpiryTimer(cell); + schHdlDrxInActvExpiryTimer(cell); +} + + +#endif +/********************************************************************** + End of file + **********************************************************************/ diff --git a/src/5gnrsch/sch_drx.h b/src/5gnrsch/sch_drx.h new file mode 100644 index 000000000..c4679d109 --- /dev/null +++ b/src/5gnrsch/sch_drx.h @@ -0,0 +1,55 @@ +/******************************************************************************* +################################################################################ +# 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 SCH_DRX_INVALID_DISTANCE -1 +#define SCH_DRX_INVALID_INDEX 0xFFFFFF +#define SCH_DRX_MAX_DELTA 1 +#define SCH_DRX_TMRS_EXP_DELTA 1 + +/** @brief Macro to convert milli second to slots */ +#define SCH_CNVRT_MS_TO_SLOT(_numSlot, _numMs, _mu)\ +{\ + _numSlot = _numMs * (1 << _mu);\ +} + +/** @brief Macro to convert number symbols to slots */ +#define SCH_CNVRT_SYMBL_TO_SLOT(_numSlot, _numSymbl)\ +{\ + _numSlot = _numSymbl/14; \ +} + +/** @brief Macro to find the slot difference */ +#define SCH_CALC_SLOT_DIFF(_newTime, _oldTime, _numOfSlotsPerRadioFrame)\ +((_newTime.sfn*_numOfSlotsPerRadioFrame+_newTime.slot) >= (_oldTime.sfn*_numOfSlotsPerRadioFrame+_oldTime.slot)?\ +(_newTime.sfn*_numOfSlotsPerRadioFrame+_newTime.slot) - (_oldTime.sfn*_numOfSlotsPerRadioFrame+_oldTime.slot) : \ +(_newTime.sfn*_numOfSlotsPerRadioFrame+_newTime.slot) + (1024*_numOfSlotsPerRadioFrame - (_oldTime.sfn*_numOfSlotsPerRadioFrame+_oldTime.slot))) + +void schInitDrxUeCb(SchUeCb *ueCb); +void schFillDrxUeCb(uint8_t numerology, SchDrxCfg drxCfg, SchDrxUeCb *drxUeCb); +void schDeleteUeDrxInfo(SchCellCb *cell, SchUeCb *ueCb); +void schHandleStartDrxTimer(SchCellCb *cell); +void schHdlDrxInActvStrtTmr(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta); +void schInitDrxHarqCb(SchDrxHarqCb *hqCb); +void schAddUeInOndurationAndShortCycleList(SchCellCb *cell, SchUeCb *ueCb, uint8_t delta); +void schDrxUeReCfgTimer(SchCellCb *cell, SchUeCb *ueCb); +void schHdlDrxShortCycleExpiryTimer(SchCellCb *cell); +void schHdlDrxOnDurExpiryTimer(SchCellCb *cell); +void schHandleExpiryDrxTimer(SchCellCb *cell); +/********************************************************************** + End of file + **********************************************************************/ diff --git a/src/5gnrsch/sch_slot_ind.c b/src/5gnrsch/sch_slot_ind.c index 12a387cb0..052a930e7 100644 --- a/src/5gnrsch/sch_slot_ind.c +++ b/src/5gnrsch/sch_slot_ind.c @@ -41,6 +41,9 @@ File: sch_slot_ind.c #include "mac_sch_interface.h" #include "sch.h" #include "sch_utils.h" +#ifdef NR_DRX +#include "sch_drx.h" +#endif SchMacDlAllocFunc schMacDlAllocOpts[] = { @@ -793,6 +796,10 @@ uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst) dlSchedInfo.cellId = cell->cellId; slot = dlSchedInfo.schSlotValue.broadcastTime.slot; +#ifdef NR_DRX + schHandleStartDrxTimer(cell); +#endif + /* Check for SSB occassion */ dlBrdcstAlloc->ssbTrans = schCheckSsbOcc(cell, dlSchedInfo.schSlotValue.broadcastTime); if(dlBrdcstAlloc->ssbTrans) @@ -838,6 +845,7 @@ uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst) { ueNode = (uint8_t *)pendingUeNode->node; ueId = *(uint8_t *)(pendingUeNode->node); + /* If RAR is pending for this UE, schedule PDCCH,PDSCH to send RAR and * PUSCH to receive MSG3 as per k0-k2 configuration*/ if(cell->raReq[ueId-1] != NULLP) @@ -852,6 +860,14 @@ uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst) schMsg3RetxSchedulingForUe(&(cell->raCb[ueId-1])); } +#ifdef NR_DRX + if(!(cell->ueCb[ueId-1].ueDrxInfoPres) && !(cell->ueCb[ueId-1].drxUeCb.drxDlUeActiveStatus))//&& !(cell->ueCb[ueId-1].drxUeCb.drxUlUeActiveStatus)) + { + cmLListAdd2Tail(&cell->ueToBeScheduled, cmLListDelFrm(&cell->ueToBeScheduled, pendingUeNode)); + } + else +#endif + { /* If MSG4 is pending for this UE, schedule PDCCH,PDSCH to send MSG4 and * PUCCH to receive UL msg as per k0-k1 configuration */ if (cell->ueCb[ueId-1].retxMsg4HqProc) //should work from dlmap later tbd @@ -913,6 +929,13 @@ uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst) /* If DL scheduling failed, free the newly assigned HARQ process */ if(!isDlMsgScheduled) schDlReleaseHqProcess(hqP); + else + { +#ifdef NR_DRX + if(cell->ueCb[ueId-1].ueDrxInfoPres) + schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], PHY_DELTA_DL + SCHED_DELTA); +#endif + } } } @@ -934,6 +957,13 @@ uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst) isUlGrantScheduled = schProcessSrOrBsrReq(cell, *slotInd, ueId, FALSE, &ulHqP); if(!isUlGrantScheduled) schUlReleaseHqProcess(ulHqP, FALSE); + else + { +#ifdef NR_DRX + if(cell->ueCb[ueId-1].ueDrxInfoPres) + schHdlDrxInActvStrtTmr(cell, &cell->ueCb[ueId-1], PHY_DELTA_UL + SCHED_DELTA); +#endif + } } } @@ -950,7 +980,7 @@ uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst) SCH_FREE(ueNode, sizeof(uint8_t)); deleteNodeFromLList(&cell->ueToBeScheduled, pendingUeNode); } - } + }} } /* Check if any PDU is scheduled at this slot for any UE */ @@ -992,7 +1022,9 @@ uint8_t schProcessSlotInd(SlotTimingInfo *slotInd, Inst schInst) schInitDlSlot(cell->schDlSlotInfo[slot]); schUlResAlloc(cell, schInst); - +#ifdef NR_DRX + schHandleExpiryDrxTimer(cell); +#endif return ret; } diff --git a/src/5gnrsch/sch_ue_mgr.c b/src/5gnrsch/sch_ue_mgr.c index aa74c06b5..db1510825 100644 --- a/src/5gnrsch/sch_ue_mgr.c +++ b/src/5gnrsch/sch_ue_mgr.c @@ -28,6 +28,9 @@ #include "mac_sch_interface.h" #include "sch.h" #include "sch_utils.h" +#ifdef NR_DRX +#include "sch_drx.h" +#endif /* local defines */ SchUeCfgRspFunc SchUeCfgRspOpts[] = @@ -256,8 +259,56 @@ uint8_t fillSchUeCb(Inst inst, SchUeCb *ueCb, SchUeCfg *ueCfg) { memcpy(&ueCb->ueCfg.macCellGrpCfg , &ueCfg->macCellGrpCfg, sizeof(SchMacCellGrpCfg)); ueCb->ueCfg.macCellGrpCfgPres = true; +#ifdef NR_DRX + if(ueCfg->macCellGrpCfg.drxCfgPresent == true) + { + if(ueCb->ueDrxInfoPres == false) + { + ueCb->ueDrxInfoPres = true; + /* intialize the drxUeCb */ + schInitDrxUeCb(ueCb); + + /* intialize the Dl drxHarqCb */ + for(idx =0; idxdlHqEnt.numHqPrcs; idx++) + { + schInitDrxHarqCb(&ueCb->dlHqEnt.procs[idx].drxHarqCb); + } + /* intialize the Ul drxHarqCb */ + for(idx =0; idxulHqEnt.numHqPrcs; idx++) + { + schInitDrxHarqCb(&ueCb->ulHqEnt.procs[idx].drxHarqCb); + } + /* convert all the drx configuration recived in ms/subms into number of slots and store into the drxUeCb */ + schFillDrxUeCb(ueCb->cellCb->cellCfg.numerology, ueCfg->macCellGrpCfg.drxCfg, &ueCb->drxUeCb); + /* Calculate the onduration timer and short cycle timer (if shortcycle configuration is present) as soon as we + * recived ueCfg request */ + schAddUeInOndurationAndShortCycleList(ueCb->cellCb, ueCb, 0); + + } + else + { + /* convert all the drx configuration recived in ms/subms into number + * of slots and store into the drxUeCb */ + schFillDrxUeCb(ueCb->cellCb->cellCfg.numerology, ueCfg->macCellGrpCfg.drxCfg, &ueCb->drxUeCb); + + /* Recalculate/Restart timer based on their presence */ + schDrxUeReCfgTimer(ueCb->cellCb, ueCb); + } + } +#endif } +#ifdef NR_DRX + if(ueCfg->drxConfigIndicatorRelease == true) + { + if(ueCb->ueDrxInfoPres == true) + { + schDeleteUeDrxInfo(ueCb->cellCb, ueCb); + ueCb->ueDrxInfoPres = false; + } + } +#endif + if(ueCfg->phyCellGrpCfgPres == true) { memcpy(&ueCb->ueCfg.phyCellGrpCfg , &ueCfg->phyCellGrpCfg, sizeof(SchPhyCellGrpCfg)); @@ -1139,7 +1190,14 @@ void deleteSchUeCb(SchUeCb *ueCb) SCH_FREE(ueCb->ulInfo.ulLcCtxt[ueLcIdx].snssai, sizeof(Snssai)); SCH_FREE(ueCb->dlInfo.dlLcCtxt[ueLcIdx].snssai, sizeof(Snssai)); } - +#ifdef NR_DRX + if(ueCb->ueDrxInfoPres) + { + /* Removing all the calculated drx configuration timer list */ + schDeleteUeDrxInfo(ueCb->cellCb, ueCb); + ueCb->ueDrxInfoPres = false; + } +#endif memset(ueCb, 0, sizeof(SchUeCb)); } } diff --git a/src/cm/du_app_mac_inf.h b/src/cm/du_app_mac_inf.h index 9020815d4..cbb8935b0 100644 --- a/src/cm/du_app_mac_inf.h +++ b/src/cm/du_app_mac_inf.h @@ -843,6 +843,7 @@ typedef struct macCellGrpCfg bool phrCfgSetupPres; /* true/false: phrCfgSetup/phrCfgRelease */ PhrCfg phrCfg; #ifdef NR_DRX + bool drxCfgPresent; DrxCfg drxCfg; #endif }MacCellGrpCfg; @@ -1300,6 +1301,9 @@ typedef struct macUeCfg LcCfg lcCfgList[MAX_NUM_LC]; UeCfgState macUeCfgState; /* InActive / Completed */ DataTransmissionAction transmissionAction; +#ifdef NR_DRX + bool drxConfigIndicatorRelease; +#endif }MacUeCfg; typedef struct nrcgi diff --git a/src/cm/mac_sch_interface.h b/src/cm/mac_sch_interface.h index 0d1ab67a9..a38e4077a 100644 --- a/src/cm/mac_sch_interface.h +++ b/src/cm/mac_sch_interface.h @@ -1200,6 +1200,7 @@ typedef struct schMacCellGrpCfg SchTagCfg tagCfg; SchPhrCfg phrCfg; /* To be used only if phrCfgSetupPres is true */ #ifdef NR_DRX + bool drxCfgPresent; SchDrxCfg drxCfg; /* Drx configuration */ #endif }SchMacCellGrpCfg; @@ -1654,6 +1655,9 @@ typedef struct schUeCfg uint8_t numLcs; SchLcCfg schLcCfg[MAX_NUM_LC]; SchDataTransmission dataTransmissionInfo; +#ifdef NR_DRX + bool drxConfigIndicatorRelease; +#endif }SchUeCfg; typedef struct schUeCfgRsp diff --git a/src/cu_stub/cu_f1ap_msg_hdl.c b/src/cu_stub/cu_f1ap_msg_hdl.c index 4e2e2f5fa..4920f8bc3 100644 --- a/src/cu_stub/cu_f1ap_msg_hdl.c +++ b/src/cu_stub/cu_f1ap_msg_hdl.c @@ -1954,25 +1954,22 @@ void fillLongCycleOffsetValue(DrxLongCycleStartOffset *drxLongCycleStartOffset, * ****************************************************************/ void storeDrxCfgInUeCb(struct DRX_ConfigRrc *drxSetup, DrxCfg *drxCfg) { - if(drxSetup) + switch(drxSetup->drx_onDurationTimer.present) { - switch(drxSetup->drx_onDurationTimer.present) - { - case DRX_ConfigRrc__drx_onDurationTimer_PR_NOTHING: + case DRX_ConfigRrc__drx_onDurationTimer_PR_NOTHING: + break; + case DRX_ConfigRrc__drx_onDurationTimer_PR_milliSeconds: + { + drxCfg->drxOnDurationTimer.onDurationTimerValInMs = true; + drxCfg->drxOnDurationTimer.onDurationtimerValue.milliSeconds=drxSetup->drx_onDurationTimer.choice.milliSeconds; break; - case DRX_ConfigRrc__drx_onDurationTimer_PR_milliSeconds: - { - drxCfg->drxOnDurationTimer.onDurationTimerValInMs = true; - drxCfg->drxOnDurationTimer.onDurationtimerValue.milliSeconds=drxSetup->drx_onDurationTimer.choice.milliSeconds; - break; - } - case DRX_ConfigRrc__drx_onDurationTimer_PR_subMilliSeconds: - { - drxCfg->drxOnDurationTimer.onDurationTimerValInMs = false; - drxCfg->drxOnDurationTimer.onDurationtimerValue.subMilliSeconds = drxSetup->drx_onDurationTimer.choice.subMilliSeconds; - break; - } - } + } + case DRX_ConfigRrc__drx_onDurationTimer_PR_subMilliSeconds: + { + drxCfg->drxOnDurationTimer.onDurationTimerValInMs = false; + drxCfg->drxOnDurationTimer.onDurationtimerValue.subMilliSeconds = drxSetup->drx_onDurationTimer.choice.subMilliSeconds; + break; + } } fillLongCycleOffsetValue(&drxCfg->drxLongCycleStartOffset, &drxSetup->drx_LongCycleStartOffset); drxCfg->drxInactivityTimer = drxSetup->drx_InactivityTimer; @@ -2049,7 +2046,11 @@ uint8_t extractCellGroupConfig(CuUeCb *ueCb, CellGroupConfigRrc_t *cellGrpCfg) case MAC_CellGroupConfig__drx_ConfigRrc_PR_setup: { - storeDrxCfgInUeCb(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup, &ueCb->drxCfg); + if(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup) + { + ueCb->drxCfgPresent = true; + storeDrxCfgInUeCb(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup, &ueCb->drxCfg); + } break; } @@ -10937,14 +10938,18 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ueContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest; if(action == MODIFY_UE) - elementCnt = 4; + elementCnt = 5; else if(action == QUERY_CONFIG) elementCnt = 3; else if(action == RRC_RECONFIG_COMPLETE_IND) elementCnt = 3; else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX)) elementCnt = 5; - + +#ifdef NR_DRX + if(DRX_TO_BE_RELEASE) + elementCnt++; +#endif ueContextModifyReq->protocolIEs.list.count = elementCnt; ueContextModifyReq->protocolIEs.list.size = elementCnt*sizeof(UEContextModificationRequest_t *); @@ -11070,6 +11075,20 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true; } +#ifdef NR_DRX + if(DRX_TO_BE_RELEASE) + { + /* DRX Configuration Indicator */ + ieIdx++; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRXConfigurationIndicator; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_DRXConfigurationIndicator; + ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.DRXConfigurationIndicator = DRXConfigurationIndicator_release; + ueCb->drxCfgPresent = false; + memset(&ueCb->drxCfg, 0, sizeof(DrxCfg)); + } +#endif + xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg); /* Encode the F1SetupRequest type as APER */ @@ -11678,7 +11697,7 @@ uint8_t procServedCellPlmnList(ServedPLMNs_List_t *srvPlmn) * ****************************************************************/ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { - uint8_t idx=0, duIdx=0; + uint8_t idx=0, duIdx=0, countiX =1; uint8_t duUeF1apId = 0, cuUeF1apId = 0; DuDb *duDb = NULLP; CuUeCb *ueCb = NULLP; @@ -11764,7 +11783,14 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) } } } - +#ifdef NR_DRX + if(countiX == 1) + { + countiX++; + DU_LOG("\nPBORLA INFO --> F1AP: Sending UE Context Modification Request to MODIFY_UE"); + //BuildAndSendUeContextModificationReq(duId, ueCb, MODIFY_UE); + } +#endif return ROK; } diff --git a/src/cu_stub/cu_stub.h b/src/cu_stub/cu_stub.h index fed791c2b..f6cb5c70e 100644 --- a/src/cu_stub/cu_stub.h +++ b/src/cu_stub/cu_stub.h @@ -95,6 +95,12 @@ }\ } +#ifdef NR_DRX +/* Set this parameter true of false as per the need to enable or disable drx of + * a particular UE */ +#define DRX_TO_BE_RELEASE true +#endif + typedef enum { CELL_INACTIVE, @@ -304,6 +310,7 @@ typedef struct cuUeCb F1apMsgDb f1apMsgDb; UeState state; #ifdef NR_DRX + bool drxCfgPresent; DrxCfg drxCfg; #endif HandoverInfo hoInfo; diff --git a/src/du_app/du_f1ap_msg_hdl.c b/src/du_app/du_f1ap_msg_hdl.c index a44829db0..d9151a4d1 100644 --- a/src/du_app/du_f1ap_msg_hdl.c +++ b/src/du_app/du_f1ap_msg_hdl.c @@ -13406,62 +13406,72 @@ void freeAperDecodeF1UeContextSetupReq(UEContextSetupRequest_t *ueSetReq) { for(ieIdx = 0; ieIdx < ueSetReq->protocolIEs.list.count; ieIdx++) { - if(ueSetReq->protocolIEs.list.array[ieIdx]) - { - switch(ueSetReq->protocolIEs.list.array[ieIdx]->id) - { - case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: - break; - case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: - break; - case ProtocolIE_ID_id_SpCell_ID: - freeAperDecodeNrcgi(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.NRCGI); - break; - case ProtocolIE_ID_id_ServCellIndex: - break; - case ProtocolIE_ID_id_SpCellULConfigured: - break; - case ProtocolIE_ID_id_CUtoDURRCInformation: + if(ueSetReq->protocolIEs.list.array[ieIdx]) + { + switch(ueSetReq->protocolIEs.list.array[ieIdx]->id) + { + case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + break; + case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + break; + case ProtocolIE_ID_id_SpCell_ID: + freeAperDecodeNrcgi(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.NRCGI); + break; + case ProtocolIE_ID_id_ServCellIndex: + break; + case ProtocolIE_ID_id_SpCellULConfigured: + break; + case ProtocolIE_ID_id_CUtoDURRCInformation: - freeAperDecodeCuToDuInfo(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.CUtoDURRCInformation); - break; - case ProtocolIE_ID_id_SCell_ToBeSetup_List: + freeAperDecodeCuToDuInfo(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.CUtoDURRCInformation); + break; + case ProtocolIE_ID_id_SCell_ToBeSetup_List: - freeAperDecodeSplCellList(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.SCell_ToBeSetup_List); - break; - case ProtocolIE_ID_id_SRBs_ToBeSetup_List: + freeAperDecodeSplCellList(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.SCell_ToBeSetup_List); + break; + case ProtocolIE_ID_id_SRBs_ToBeSetup_List: - freeAperDecodeSRBSetup(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.SRBs_ToBeSetup_List); - break; - case ProtocolIE_ID_id_DRBs_ToBeSetup_List: + freeAperDecodeSRBSetup(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.SRBs_ToBeSetup_List); + break; + case ProtocolIE_ID_id_DRBs_ToBeSetup_List: - freeAperDecodeDRBSetup(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.DRBs_ToBeSetup_List); - break; - case ProtocolIE_ID_id_RRCContainer: - { + freeAperDecodeDRBSetup(&ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.DRBs_ToBeSetup_List); + break; + case ProtocolIE_ID_id_RRCContainer: + { - if(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf != NULLP) - { + if(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf != NULLP) + { - free(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf); - } - break; - } - case ProtocolIE_ID_id_RRCDeliveryStatusRequest: - break; - case ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL: - { - if(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.BitRate.buf) - { - free(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.BitRate.buf); - } - break; - } - default: - DU_LOG("\nERROR --> F1AP: Invalid event type %ld " ,ueSetReq->protocolIEs.list.array[ieIdx]->id); - } - free(ueSetReq->protocolIEs.list.array[ieIdx]); - } + free(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf); + } + break; + } + case ProtocolIE_ID_id_RRCDeliveryStatusRequest: + break; + case ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL: + { + if(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.BitRate.buf) + { + free(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.BitRate.buf); + } + break; + } +#ifdef NR_DRX + case ProtocolIE_ID_id_DRXCycle: + { + if(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.DRXCycle.shortDRXCycleLength) + free(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.DRXCycle.shortDRXCycleLength); + if(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.DRXCycle.shortDRXCycleTimer) + free(ueSetReq->protocolIEs.list.array[ieIdx]->value.choice.DRXCycle.shortDRXCycleTimer); + break; + } +#endif + default: + DU_LOG("\nERROR --> F1AP: Invalid event type %ld " ,ueSetReq->protocolIEs.list.array[ieIdx]->id); + } + free(ueSetReq->protocolIEs.list.array[ieIdx]); + } } free(ueSetReq->protocolIEs.list.array); } @@ -13840,50 +13850,52 @@ void FreeUeContextSetupRsp(F1AP_PDU_t *f1apMsg) { if(f1apMsg->choice.successfulOutcome) { - ueSetRsp = &f1apMsg->choice.successfulOutcome->value.choice.\ - UEContextSetupResponse; - if(ueSetRsp->protocolIEs.list.array) - { - for(idx = 0; idx < ueSetRsp->protocolIEs.list.count; idx++) - { - if(ueSetRsp->protocolIEs.list.array[idx]) - { - switch(ueSetRsp->protocolIEs.list.array[idx]->id) - { - case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: - break; - case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: - break; - case ProtocolIE_ID_id_DUtoCURRCInformation: - { - CellGroupConfig_t *cellGrpCfg = NULLP; - cellGrpCfg = &ueSetRsp->protocolIEs.list.array[idx]->value.choice.\ - DUtoCURRCInformation.cellGroupConfig; - if(cellGrpCfg->buf != NULLP) - { - DU_FREE(cellGrpCfg->buf, cellGrpCfg->size); - cellGrpCfg = NULLP; - } - break; - } - case ProtocolIE_ID_id_DRBs_Setup_List: - { + ueSetRsp = &f1apMsg->choice.successfulOutcome->value.choice.\ + UEContextSetupResponse; + if(ueSetRsp->protocolIEs.list.array) + { + for(idx = 0; idx < ueSetRsp->protocolIEs.list.count; idx++) + { + if(ueSetRsp->protocolIEs.list.array[idx]) + { + switch(ueSetRsp->protocolIEs.list.array[idx]->id) + { + case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + break; + case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + break; + case ProtocolIE_ID_id_C_RNTI: + break; + case ProtocolIE_ID_id_DUtoCURRCInformation: + { + CellGroupConfig_t *cellGrpCfg = NULLP; + cellGrpCfg = &ueSetRsp->protocolIEs.list.array[idx]->value.choice.\ + DUtoCURRCInformation.cellGroupConfig; + if(cellGrpCfg->buf != NULLP) + { + DU_FREE(cellGrpCfg->buf, cellGrpCfg->size); + cellGrpCfg = NULLP; + } + break; + } + case ProtocolIE_ID_id_DRBs_Setup_List: + { freeDrbSetupList(&ueSetRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List); break; - } - default: - DU_LOG("\nERROR --> DUAPP: Invalid Id %ld at FreeUeContextSetupRsp()",\ - ueSetRsp->protocolIEs.list.array[idx]->id); - break; - } - DU_FREE(ueSetRsp->protocolIEs.list.array[idx],\ - sizeof(UEContextSetupResponseIEs_t)); - } - } - DU_FREE(ueSetRsp->protocolIEs.list.array, \ - ueSetRsp->protocolIEs.list.size); - } - DU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t)); + } + default: + DU_LOG("\nERROR --> DUAPP: Invalid Id %ld at FreeUeContextSetupRsp()",\ + ueSetRsp->protocolIEs.list.array[idx]->id); + break; + } + DU_FREE(ueSetRsp->protocolIEs.list.array[idx],\ + sizeof(UEContextSetupResponseIEs_t)); + } + } + DU_FREE(ueSetRsp->protocolIEs.list.array, \ + ueSetRsp->protocolIEs.list.size); + } + DU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t)); } DU_FREE(f1apMsg, sizeof(F1AP_PDU_t)); } @@ -15940,6 +15952,8 @@ uint8_t BuildAndSendUeContextModRsp(DuUeCb *ueCb) break; } FreeUeContextModResp(f1apMsg); + //sleep(5); + //BuildAndSendDUConfigUpdate(SERV_CELL_TO_DELETE); return ret; } /******************************************************************* @@ -16360,6 +16374,13 @@ uint8_t procF1UeContextModificationReq(F1AP_PDU_t *f1apMsg) } break; } +#ifdef NR_DRX + case ProtocolIE_ID_id_DRXConfigurationIndicator: + { + duUeCb->f1UeDb->duUeCfg.drxConfigIndicatorRelease = true; + break; + } +#endif } } diff --git a/src/du_app/du_mgr.h b/src/du_app/du_mgr.h index c2604087e..e7345f58d 100644 --- a/src/du_app/du_mgr.h +++ b/src/du_app/du_mgr.h @@ -157,6 +157,7 @@ typedef struct duUeCfg #ifdef NR_DRX bool drxCyclePres; DrxCycle drxCycle; + bool drxConfigIndicatorRelease; #endif }DuUeCfg; diff --git a/src/du_app/du_mgr_main.c b/src/du_app/du_mgr_main.c index ba89f0be0..0d171a510 100644 --- a/src/du_app/du_mgr_main.c +++ b/src/du_app/du_mgr_main.c @@ -548,7 +548,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) @@ -556,7 +556,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) @@ -566,7 +566,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) @@ -574,7 +574,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) @@ -582,7 +582,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) @@ -590,7 +590,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_ue_mgr.c b/src/du_app/du_ue_mgr.c index b77b231a8..cae946ec5 100644 --- a/src/du_app/du_ue_mgr.c +++ b/src/du_app/du_ue_mgr.c @@ -1283,6 +1283,11 @@ uint8_t fillMacUeCfg(uint16_t cellId, uint8_t gnbDuUef1apId, uint16_t crnti, DuU } #ifdef NR_DRX + if(ueCfgDb->drxConfigIndicatorRelease == true) + { + macUeCfg->drxConfigIndicatorRelease = true; + } + if(ueCfgDb->drxCyclePres) { macUeCfg->macCellGrpCfg.drxCfg.drxLongCycleStartOffset.drxLongCycleStartOffsetChoice = ueCfgDb->drxCycle.drxLongCycleLength; diff --git a/src/phy_stub/phy_stub_msg_hdl.c b/src/phy_stub/phy_stub_msg_hdl.c index b88a260d3..19ecc8c70 100644 --- a/src/phy_stub/phy_stub_msg_hdl.c +++ b/src/phy_stub/phy_stub_msg_hdl.c @@ -886,7 +886,8 @@ S16 l1HdlDlTtiReq(uint16_t msgLen, void *msg) } else if(dlTtiReq->pdus[pduCount].pduType == 0) { - DU_LOG("\nINFO --> PHY_STUB: PDCCH PDU"); + //DU_LOG("\nINFO --> PHY_STUB: PDCCH PDU"); + DU_LOG("\nINFO --> PHY_STUB: PDCCH PDU sfn=%d slot=%d",dlTtiReq->sfn,dlTtiReq->slot); } else if(dlTtiReq->pdus[pduCount].pduType == 1) { -- 2.16.6