[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-523] Statistics Request API and Timer Based... 57/11657/5
authorlal.harshita <Harshita.Lal@radisys.com>
Mon, 21 Aug 2023 15:00:02 +0000 (20:30 +0530)
committerlal.harshita <Harshita.Lal@radisys.com>
Wed, 23 Aug 2023 11:39:18 +0000 (17:09 +0530)
Change-Id: If23ab70473a2a028c425fa8c9c1e3031eb0406dc
Signed-off-by: lal.harshita <Harshita.Lal@radisys.com>
34 files changed:
src/5gnrmac/mac_cfg_hdl.c
src/5gnrmac/mac_msg_router.c
src/5gnrmac/rg_env.h
src/5gnrmac/rg_lmm.c
src/5gnrrlc/rlc_tmr.c
src/5gnrsch/sch.c
src/5gnrsch/sch.h
src/5gnrsch/sch_common.c
src/5gnrsch/sch_crc.c
src/5gnrsch/sch_fcfs.c
src/5gnrsch/sch_harq_dl.c
src/5gnrsch/sch_harq_ul.c
src/5gnrsch/sch_msg_router.c
src/5gnrsch/sch_rach.c
src/5gnrsch/sch_slice_based.c
src/5gnrsch/sch_slot_ind.c
src/5gnrsch/sch_tmr.c
src/5gnrsch/sch_tmr.h [new file with mode: 0644]
src/5gnrsch/sch_ue_mgr.c
src/5gnrsch/sch_utils.c
src/cm/common_def.h
src/cm/du_app_mac_inf.c
src/cm/du_app_mac_inf.h
src/cm/mac_sch_interface.h
src/du_app/du_e2ap_mgr.h
src/du_app/du_e2ap_msg_hdl.c
src/du_app/du_e2ap_msg_hdl.h
src/du_app/du_mgr.h
src/du_app/du_mgr_main.c
src/du_app/du_msg_hdl.c
src/du_app/du_tmr.c
src/du_app/du_tmr.h
src/mt/mt_ss.c
src/mt/mt_ss.h

index fee5f4f..fa17ba0 100644 (file)
@@ -1014,6 +1014,105 @@ 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 valid, 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. TBD in next gerrit */
+   }
+   return ret;
+}
+
 /**********************************************************************
   End of file
  **********************************************************************/
index 1ed8fb3..62b25d3 100755 (executable)
@@ -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;
index 192d806..199b808 100755 (executable)
 //uint32_t wrSmDfltNumCells;
 #define RGSCH_MAX_UE_PER_DL_SF 32
 #define RGSCH_MAX_RARNTI_PER_DL_SF 4
-#define SCH_INST_START 1
 #define RGSCH_MAX_INST 2
 /*MCELL changes*/
 #define RG_MAX_INST 4
index a31bd23..69fad5b 100755 (executable)
@@ -169,9 +169,6 @@ Reason reason          /* reason */
    SAttachSRngBuf(SS_RNG_BUF_ULMAC_TO_ULRLC, SS_RBUF_ENT_ULRLC,SS_RNG_RX);
 #endif
 
-   /* Initialize Scheduler as well */
-   schActvInit(ENTMAC, SCH_INST_START, DFLT_REGION, PWR_UP);
-
    /* Initialize lower mac */
    lwrMacLayerInit(region, 0);
 
index 0c7234e..2f3a187 100755 (executable)
  * @brief RLC Timer Module
 */
 
-/**
- * @def RLC_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 RLC_TMR_CALCUATE_WAIT(_wait, _tmrVal, _timerRes)       \
-{                                                             \
-   (_wait) = ((_tmrVal) * SS_TICKS_SEC)/((_timerRes) * 1000); \
-   if((0 != (_tmrVal)) && (0 == (_wait)))                     \
-   {                                                          \
-      (_wait) = 1;                                            \
-   }                                                          \
-}
-
 /* private function declarations */
 static Void rlcBndTmrExpiry(PTR cb);
 
@@ -113,7 +91,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 +101,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 +111,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 +123,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 +135,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 +147,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 +159,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 +167,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 +175,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;
index 293add2..563cb5a 100644 (file)
 #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"
 
-/**
- * @brief Task Initiation function. 
- *
- * @details
- *
- *     Function : schActvInit
- *     
- *     This function is supplied as one of parameters during MAC's 
- *     task registration. MAC will invoke this function once, after
- *     it creates and attaches this TAPA Task to a system task.
- *     
- *  @param[in]  Ent Entity, the entity ID of this task.     
- *  @param[in]  Inst Inst, the instance ID of this task.
- *  @param[in]  Region Region, the region ID registered for memory 
- *              usage of this task.
- *  @param[in]  Reason Reason.
- *  @return  int
- *      -# ROK
- **/
-uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason)
-{
-   Inst inst = (instId  - SCH_INST_START);
-
-   /* Initialize the MAC TskInit structure to zero */
-   memset ((uint8_t *)&schCb[inst], 0, sizeof(schCb));
-
-   /* Initialize the MAC TskInit with received values */
-   schCb[inst].schInit.ent = entity;
-   schCb[inst].schInit.inst = inst;
-   schCb[inst].schInit.region = region;
-   schCb[inst].schInit.pool = 0;
-   schCb[inst].schInit.reason = reason;
-   schCb[inst].schInit.cfgDone = FALSE;
-   schCb[inst].schInit.acnt = FALSE;
-   schCb[inst].schInit.usta = FALSE;
-   schCb[inst].schInit.trc = FALSE;
-   schCb[inst].schInit.procId = ODU_GET_PROCID();
-
-   return ROK;
-} /* schActvInit */
-
 /**
  * @brief Scheduler All Apis initialized. 
  *
@@ -150,28 +110,27 @@ 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.");
+      DU_LOG("\nERROR  -->  SCH : SchInstCfg(): Failed to register timer.");
       return (LCM_REASON_MEM_NOAVAIL);
    }   
-              
+
    /* Set Config done in TskInit */
    schCb[inst].schInit.cfgDone = TRUE;
    DU_LOG("\nINFO   -->  SCH : Scheduler gen config done");
@@ -1422,6 +1381,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 +1519,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 +2501,150 @@ uint8_t SchProcPhrInd(Pst *pst, SchPwrHeadroomInd *schPhrInd)
    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;
+               cmInitTimers(&(schCb[inst].statistics.dlTotalPrbUsage->periodTimer), 1);
+
+               /* 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;
+               cmInitTimers(&(schCb[inst].statistics.ulTotalPrbUsage->periodTimer), 1);
+
+               /* 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));
+
+   /* TODO : in next gerrit */
+   //SchSendStatsRspToMac(inst, rsp, cause);
+
+   return ROK;
+} /* End of SchProcStatsReq */
+
 /**********************************************************************
   End of file
  **********************************************************************/
index 4feaa18..537ed31 100644 (file)
@@ -17,8 +17,6 @@
  *******************************************************************************/
 
 /* macros */
-#define SCH_INST_START 1
-#define SCH_MAX_INST 1
 #define SCH_MU0_NUM_SLOTS 10 
 #define SCH_MU1_NUM_SLOTS 20 
 #define SCH_MU2_NUM_SLOTS 30 
@@ -47,7 +45,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 +77,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 +278,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 +302,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 +600,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 +660,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 +675,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]; /*!<List of All Scheduler Type dependent Function pointers*/
    SchCellCb              *cells[MAX_NUM_CELL];  /* Array to store cellCb ptr */
    CmLListCp              sliceCfg;              /* Linklist to Store Slice configuration */
+   SchStatistics          statistics;            /* Statistics configuration and calculated values */
 }SchCb;
 
 /* Declaration for scheduler control blocks */
@@ -773,6 +793,10 @@ void schUpdateHarqFdbk(SchUeCb *ueCb, uint8_t numHarq, uint8_t *harqPayload,Slot
 uint8_t schFillUlDciForMsg3Retx(SchRaCb *raCb, SchPuschInfo *puschInfo, DciInfo *dciInfo);
 bool schGetMsg3K2(SchCellCb *cell, SchUlHqProcCb* msg3HqProc, uint16_t dlTime, SlotTimingInfo *msg3Time, bool isRetx);
 void schMsg4Complete(SchUeCb *ueCb);
+
+/* Statistics Function */
+uint8_t SchProcStatsReq(Pst *pst, SchStatsReq *statsReq);
+
 /**********************************************************************
   End of file
  **********************************************************************/
index da6fd9c..d7b4016 100644 (file)
@@ -41,6 +41,7 @@ File:     sch_common.c
 #include "du_app_mac_inf.h"
 #include "mac_sch_interface.h"
 #include "sch.h"
+#include "sch_tmr.h"
 #include "sch_utils.h"
 
 /**
@@ -535,13 +536,21 @@ uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst)
       memset(&schUlSlotInfo->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;
 }
index 3730988..abd9f4d 100644 (file)
@@ -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"
 
 /**
index edfad66..09e2c64 100644 (file)
@@ -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 
index 1ec31bc..f058cdc 100644 (file)
@@ -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
index 343859a..c5433f9 100644 (file)
@@ -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"
index edb21b8..ca15f65 100755 (executable)
 #include "rgr.x"           /* layer management typedefs for MAC */
 #include "rg_sch_inf.x"         /* typedefs for Scheduler */
 #include "sch.h"
+#include "sch_tmr.h"
+
+/**
+ * @brief Task Initiation function. 
+ *
+ * @details
+ *
+ *     Function : schActvInit
+ *     
+ *     This function is supplied as one of parameters during MAC's 
+ *     task registration. MAC will invoke this function once, after
+ *     it creates and attaches this TAPA Task to a system task.
+ *     
+ *  @param[in]  Ent Entity, the entity ID of this task.     
+ *  @param[in]  Inst Inst, the instance ID of this task.
+ *  @param[in]  Region Region, the region ID registered for memory 
+ *              usage of this task.
+ *  @param[in]  Reason Reason.
+ *  @return  int
+ *      -# ROK
+ **/
+uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason)
+{
+   Inst inst = (instId  - SCH_INST_START);
+
+   /* Initialize the MAC TskInit structure to zero */
+   memset ((uint8_t *)&schCb[inst], 0, sizeof(schCb));
+
+   /* Initialize the MAC TskInit with received values */
+   schCb[inst].schInit.ent = entity;
+   schCb[inst].schInit.inst = inst;
+   schCb[inst].schInit.region = region;
+   schCb[inst].schInit.pool = 0;
+   schCb[inst].schInit.reason = reason;
+   schCb[inst].schInit.cfgDone = FALSE;
+   schCb[inst].schInit.acnt = FALSE;
+   schCb[inst].schInit.usta = FALSE;
+   schCb[inst].schInit.trc = FALSE;
+   schCb[inst].schInit.procId = ODU_GET_PROCID();
+
+   return ROK;
+} /* schActvInit */
+
+/**
+ * @brief Task Activation callback function.
+ *
+ * @details
+ *
+ *     Function : schActvTsk
+ *
+ *     Primitives invoked by SCH's users/providers through
+ *     a loosely coupled interface arrive here by means of
+ *     SSI's message handling. This API is registered with
+ *     SSI during the Task Registration of SCH.
+ *
+ *  @param[in]  Pst     *pst, Post structure of the primitive.
+ *  @param[in]  Buffer *mBuf, Packed primitive parameters in the buffer.
+ *  @param[in]  Reason reason.
+ *  @return  uint8_t
+ *      -# ROK
+ **/
+uint8_t schActvTsk(Pst *pst, Buffer *mBuf)
+{
+   SchMessageRouter(pst, (void *)mBuf);
+
+   ODU_EXIT_TASK();
+   return ROK;
+}
 
 #ifdef CALL_FLOW_DEBUG_LOG
 /**
@@ -176,6 +244,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 +371,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);
index 8d5b79c..e4f6fb4 100644 (file)
@@ -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"
 
 /**
index 149e7d9..ece81a0 100644 (file)
@@ -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 
index 00ea9b9..5051095 100644 (file)
@@ -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;
 }
 
index e880db0..e31c518 100644 (file)
 #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;
+
+   DU_LOG("\nINFO   -->  SCH : Starting Timer Event [%d] with Wait Time [%d] ms", \
+      tmrEvnt, timerValue);
+   
+   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;
+
+   DU_LOG("\nINFO   -->  SCH : Stopping Timer Event [%d]", tmrType);
+
+   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 = 0;
+
+   if(dlTotalPrbUsage->totalPrbAvailForTx)
+      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 = 0;
+
+   if(ulTotalPrbUsage->totalPrbAvailForTx)
+      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.
  *     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 */
+   DU_LOG("\nINFO   -->  SCH : Timer Event [%d] expired", tmrEvnt);
+
+   struct timeval tp;
+   gettimeofday(&tp, 0);
+   time_t curtime = tp.tv_sec;
+   struct tm *t = localtime(&curtime);
+
+   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 +299,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 (file)
index 0000000..105346d
--- /dev/null
@@ -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 1
+
+#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
+ **********************************************************************/
+
index 1711ecb..d416a07 100644 (file)
@@ -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"
index 9d65480..7e849ab 100644 (file)
@@ -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"
 
index ffc921e..371a1d5 100644 (file)
@@ -53,6 +53,9 @@
 #include "cm_lib.x"
 #include "du_log.h"
 
+#define SCH_INST_START 1
+#define SCH_MAX_INST 1
+
 #define RADIO_FRAME_DURATION 10 /* Time duration of a radio frame in ms */
 /* MAX values */
 #define MAX_NUM_CELL 2 /* Changed to 2 to support cell Id 2 even if there is only one cell in DU */
 /*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
    _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 +260,8 @@ typedef enum
    UEID_INVALID, 
    RESOURCE_UNAVAILABLE,  
    SLICE_NOT_FOUND,
+   DUPLICATE_ENTRY,
+   PARAM_INVALID
 }CauseOfResult ;
 
 typedef enum
index 3ea1b0c..e5e18c9 100644 (file)
@@ -2318,6 +2318,85 @@ 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;
+}
+
 /**********************************************************************
   End of file
  **********************************************************************/
index 7cb7897..c7f88d6 100644 (file)
@@ -89,6 +89,7 @@
 #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 BSR_PERIODIC_TIMER_SF_10 10
 #define BSR_RETX_TIMER_SF_320 320
 #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 +583,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 +1853,20 @@ 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;
+
+/****************** FUNCTION POINTERS ********************************/
+
 /* DL broadcast req from DU APP to MAC*/
 typedef uint8_t (*DuMacDlBroadcastReq) ARGS((
          Pst           *pst,
@@ -1993,98 +2019,136 @@ 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));
 
+/******************** 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);
+
 #endif
 
 
index f3d4799..ca34970 100644 (file)
@@ -51,6 +51,8 @@
 #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
+
 /*macros*/
 #define MAX_SSB_IDX 1 /* forcing it as 1 for now. Right value is 64 */
 #define SCH_SSB_MASK_SIZE   1
@@ -448,6 +450,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,8 +2246,19 @@ 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;
+
 /* function declarations */
-uint8_t schActvInit(Ent entity, Inst instId, Region region, Reason reason);
 uint8_t MacMessageRouter(Pst *pst, void *msg);
 uint8_t SchMessageRouter(Pst *pst, void *msg);
 
index 5004628..9259ae8 100644 (file)
@@ -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,19 @@ typedef struct
       char     measurementTypeName[STRING_SIZE_150_BYTES];
       uint16_t measurementTypeId;
    }choice;
-   uint32_t    numOfLabels;
-   LabelInfo   LabelInfoList[MAX_LABEL_INFO];
+
+   /* As of now Labels are not used, hence it is not implemented completely */
+   //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 +317,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 */
index e340e43..d528b51 100644 (file)
@@ -1652,6 +1652,13 @@ uint8_t procRicSubsReq(E2AP_PDU_t *e2apMsg)
                      }
                      free(ricSubsReq->protocolIEs.list.array[idx]->value.choice.RICsubscriptionDetails.ricAction_ToBeSetup_List.\
                            list.array);
+
+                     /* This is a dummy trigger for statistics request. It will
+                      * be removed in next gerrit and actual statistics request
+                      * will be sent when RIC subscription request is received
+                      * from RIC */
+                     ricSubscriptionInfo->actionSequence[0].definition.styleType = 1;
+                     BuildAndSendStatsReq(ricSubscriptionInfo->actionSequence[0].definition);
                   }
                   break;
                }
index ed81ae0..18edc27 100644 (file)
@@ -25,6 +25,7 @@ uint8_t  BuildAndSendE2NodeConfigUpdate();
 uint8_t BuildAndSendE2ResetRequest(E2CauseType failureType, E2Cause failureCause);
 void     E2APMsgHdlr(Buffer *mBuf);
 uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo);
+uint8_t BuildAndSendStatsReq(ActionDefinition subscribedAction);
 /**********************************************************************
   End of file
  **********************************************************************/
index ba079db..fd73b05 100644 (file)
@@ -353,7 +353,6 @@ typedef struct duCb
    DuTimers      duTimersInfo;              /* Du timers queue */
 }DuCb;
 
-
 typedef struct duLSapCfg
 {
    SuId        suId;
@@ -372,6 +371,17 @@ typedef struct duLSapCfg
    TmrCfg      connTmr;
 }DuLSapCfg;
 
+/* Statistics Reported */
+typedef struct statistics
+{
+   /* As of now, KPI reporting is not implemented at RLC and DU APP.
+    * Below members are just for future reference*/
+   //DuAppStats   duAppStats;
+   //RlcStatsReq  rlcStatsReq;
+
+   MacStatsReq    macStatsReq;
+}Statistics;
+
 /* global variables */
 DuCb duCb;
 //DuCfgParams duCfgParam;
index dfcc198..f787284 100644 (file)
@@ -46,6 +46,8 @@ uint8_t rlcDlActvTsk (Pst *, Buffer *);
 uint8_t rlcDlActvInit (Ent, Inst, Region, Reason);
 uint8_t macActvTsk (Pst *, Buffer *);
 uint8_t macActvInit (Ent, Inst, Region, Reason);
+uint8_t schActvTsk (Pst *, Buffer *);
+uint8_t schActvInit(Ent, Inst, Region, Reason);
 uint8_t lwrMacActvTsk(Pst *, Buffer *);
 uint8_t lwrMacActvInit(Ent, Inst, Region, Reason);
 #ifndef INTEL_WLS_MEM
@@ -364,6 +366,7 @@ uint8_t sctpInit(SSTskId sysTskId)
          sysTskId);
    return ROK;
 }
+
 /*******************************************************************
  *
  * @brief Initializes RLC DL, MAC TAPA task
@@ -405,9 +408,41 @@ uint8_t rlcDlInit(SSTskId sysTskId)
    {
       return RFAILED;
    }
+ }
 
-   DU_LOG("\nINFO   -->  DU_APP : RLC DL and MAC TAPA task created and registered to \
-   %d sys task", sysTskId);
+/*******************************************************************
+ *
+ * @brief Initializes SCH TAPA task
+ *
+ * @details
+ *
+ *    Function : schInit
+ *
+ *    Functionality:
+ *       - Registers and attaches TAPA tasks for SCH
+ *
+ * @params[in] system task ID
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+ uint8_t schInit(SSTskId sysTskId)
+ {
+   /* Register SCH TAPA Task */
+   if(ODU_REG_TTSK((Ent)ENTMAC, (Inst)SCH_INST_START, (Ttype)TTNORM, (Prior)PRIOR0,
+            schActvInit, (ActvTsk)schActvTsk) != ROK)
+   {
+      return RFAILED;
+   }
+   /* Attach SCH Task */
+   if (ODU_ATTACH_TTSK((Ent)ENTMAC, (Inst)SCH_INST_START, sysTskId)!= ROK)
+   {
+      return RFAILED;
+   }
+
+
+   DU_LOG("\nINFO   -->  DU_APP : SCH TAPA task created and registered to \
+         %d sys task", sysTskId);
    return ROK;
 }
 
@@ -537,7 +572,7 @@ uint8_t phyStubInit(SSTskId sysTskId)
 uint8_t commonInit()
 {
    /* Declare system task Ids */
-   SSTskId du_app_stsk, egtp_stsk, sctp_stsk, rlc_ul_stsk, rlc_mac_cl_stsk, lwr_mac_stsk, phy_stub_slot_ind_stsk;
+   SSTskId du_app_stsk, egtp_stsk, sctp_stsk, rlc_ul_stsk, rlc_mac_cl_stsk, sch_stsk, lwr_mac_stsk, phy_stub_slot_ind_stsk;
 
    pthread_attr_t attr;
 
@@ -577,6 +612,14 @@ uint8_t commonInit()
       return RFAILED;
    }
    ODU_SET_THREAD_AFFINITY(&rlc_ul_stsk, SS_AFFINITY_MODE_EXCL, 22, 0);
+   
+   /* system task for SCH */
+   if(ODU_CREATE_TASK(PRIOR1, &sch_stsk) != ROK)
+   {
+      DU_LOG("\nERROR  -->  DU_APP : System Task creation for SCH failed");
+      return RFAILED;
+   }
+   ODU_SET_THREAD_AFFINITY(&sch_stsk, SS_AFFINITY_MODE_EXCL, 22, 0);
 
    /* system task for SCTP receiver thread */
    if(ODU_CREATE_TASK(PRIOR0, &sctp_stsk) != ROK)
@@ -635,6 +678,12 @@ uint8_t commonInit()
      return RFAILED;
    } 
 
+   if(schInit(sch_stsk) != ROK)
+   {
+      DU_LOG("\nERROR  -->  DU_APP : SCH Tapa Task initialization failed");
+      return RFAILED;
+   }
+
    if(lwrMacInit(lwr_mac_stsk) != ROK)
    {
       DU_LOG("\nERROR  -->  DU_APP : Lower MAC Tapa Task initialization failed");
index 5ab931b..e29aa3b 100644 (file)
@@ -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,147 @@ 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 RFAILED;
+      }
+   }
+   return ROK;  
+}
+
+/*******************************************************************
+ *
+ * @brief Fetch statistics details from Action Definition Format 1
+ *
+ * @details
+ *
+ *    Function : FetchStatsFromActionDefFormat1()
+ *
+ *    Functionality: Fetch statistics details from Action 
+ *       Definition Format 1 received in an E2 message from 
+ *       RIC.
+ *
+ * @params[in] ActionDefFormat1
+ *
+ * @return Statistics
+ *
+ * ****************************************************************/
+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 = 100;
+   stats.macStatsReq.statsList[1].type = MAC_UL_TOTAL_PRB_USAGE;
+   stats.macStatsReq.statsList[1].periodicity = 100;
+
+   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;
+}
+
 /**********************************************************************
   End of file
  **********************************************************************/
index 432a3d3..3d89d98 100644 (file)
@@ -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;
index d7529b7..809b087 100644 (file)
 #define DU_TIMER_RESOLUTION 1
 #define DU_TQ_SIZE 2
 
-/**
- * @def DU_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 DU_TMR_CALCUATE_WAIT(_wait, _tmrVal, _timerRes)       \
-{                                                             \
-   (_wait) = ((_tmrVal) * SS_TICKS_SEC)/((_timerRes) * 1000); \
-   if((0 != (_tmrVal)) && (0 == (_wait)))                     \
-   {                                                          \
-      (_wait) = 1;                                            \
-   }                                                          \
-}
-
 short int duActvTmr(Ent ent,Inst inst); 
 bool duChkTmr(PTR cb, int16_t tmrEvnt);
 void duStartTmr(PTR cb, int16_t tmrEvnt, uint8_t timerValue);
index b91b442..cb1ad0b 100644 (file)
@@ -501,11 +501,23 @@ SsRegCfg cfgRegInfo[SS_MAX_REGS] =
            { SS_POOL_DYNAMIC, MT_POOL_4_DSIZE },
            { SS_POOL_STATIC, 0 }
         }
+      },
+      {
+    SS_DFLT_REGION + 7, SS_MAX_POOLS_PER_REG - 1,
+    {
+       { SS_POOL_DYNAMIC, MT_POOL_0_DSIZE },
+       { SS_POOL_DYNAMIC, MT_POOL_1_DSIZE },
+       { SS_POOL_DYNAMIC, MT_POOL_2_DSIZE },
+       { SS_POOL_DYNAMIC, MT_POOL_3_DSIZE },
+       { SS_POOL_DYNAMIC, MT_POOL_4_DSIZE },
+       { SS_POOL_STATIC, 0 }
+    }
       }
+
 #ifndef INTEL_WLS_MEM
    ,
       {
-         SS_DFLT_REGION + 7, SS_MAX_POOLS_PER_REG - 1,
+         SS_DFLT_REGION + 8, SS_MAX_POOLS_PER_REG - 1,
          {
             { SS_POOL_DYNAMIC, MT_POOL_0_DSIZE },
             { SS_POOL_DYNAMIC, MT_POOL_1_DSIZE },
@@ -611,11 +623,23 @@ MtDynMemCfg mtDynMemoCfg =
            {SS_BLK_RELEASE_THRESHOLD, SS_BLK_ACQUIRE_THRESHOLD},
            {SS_BLK_RELEASE_THRESHOLD, SS_BLK_ACQUIRE_THRESHOLD}
         }
+      },
+      {
+    SS_DFLT_REGION + 7,                         /* region id */
+    MT_MAX_BKTS,                            /* number of buckets */
+    {
+       /* block size, no. of blocks, Upper threshold, lower threshold */
+       {SS_BLK_RELEASE_THRESHOLD, SS_BLK_ACQUIRE_THRESHOLD},
+       {SS_BLK_RELEASE_THRESHOLD, SS_BLK_ACQUIRE_THRESHOLD},
+       {SS_BLK_RELEASE_THRESHOLD, SS_BLK_ACQUIRE_THRESHOLD},
+       {SS_BLK_RELEASE_THRESHOLD, SS_BLK_ACQUIRE_THRESHOLD},
+       {SS_BLK_RELEASE_THRESHOLD, SS_BLK_ACQUIRE_THRESHOLD}
+    }
       }
 #ifndef INTEL_WLS_MEM
       ,
          {
-            SS_DFLT_REGION + 7,                         /* region id */
+            SS_DFLT_REGION + 8,                         /* region id */
             MT_MAX_BKTS,                            /* number of buckets */
             {
                /* block size, no. of blocks, Upper threshold, lower threshold */
@@ -792,11 +816,24 @@ MtMemCfg mtMemoCfg =
            {MT_BKT_3_DSIZE, MT_BKT_3_STATIC_NUMBLKS},    /* block size, no. of blocks */
            {MT_BKT_4_DSIZE, MT_BKT_4_STATIC_NUMBLKS}    /* block size, no. of blocks */
         }
+      },
+      {
+    SS_DFLT_REGION + 7,                         /* region id */
+    MT_MAX_BKTS,                            /* number of buckets */
+    MT_HEAP_SIZE,                           /* heap size */
+    {
+       {MT_BKT_0_DSIZE, MT_BKT_0_STATIC_NUMBLKS},   /* block size, no. of blocks */
+       {MT_BKT_1_DSIZE, MT_BKT_1_STATIC_NUMBLKS},    /* block size, no. of blocks */
+       {MT_BKT_2_DSIZE, MT_BKT_2_STATIC_NUMBLKS},   /* block size, no. of blocks */
+       {MT_BKT_3_DSIZE, MT_BKT_3_STATIC_NUMBLKS},    /* block size, no. of blocks */
+       {MT_BKT_4_DSIZE, MT_BKT_4_STATIC_NUMBLKS}    /* block size, no. of blocks */
+    }
       }
+
 #ifndef INTEL_WLS_MEM
       ,
          {
-            SS_DFLT_REGION + 7,                         /* region id */
+            SS_DFLT_REGION + 8,                         /* region id */
             MT_MAX_BKTS,                            /* number of buckets */
             MT_HEAP_SIZE,                           /* heap size */
             {
index 4c00256..68c0213 100755 (executable)
@@ -64,7 +64,7 @@
 #endif
 #else 
 #ifndef INTEL_WLS_MEM
-#define SS_MAX_STSKS                    8
+#define SS_MAX_STSKS                    9
 #else
 #define SS_MAX_STSKS                    7 
 #endif
@@ -94,7 +94,7 @@
 #ifdef SS_MULTICORE_SUPPORT
 #define SS_MAX_REGS SS_MAX_STSKS
 #else
-#define SS_MAX_REGS  7
+#define SS_MAX_REGS  8
 #endif
 
 #ifdef CMM_MAX_BKT_ENT