JIRA ID: ODUHIGH-381 : DL packets Scheduling as per RRM Policy
[o-du/l2.git] / src / 5gnrsch / sch_common.c
index 2db25f0..75a65f7 100644 (file)
@@ -43,12 +43,6 @@ File:     sch_common.c
 #include "sch.h"
 #include "sch_utils.h"
 
-SchCb schCb[SCH_MAX_INST];
-uint16_t prachCfgIdxTable[MAX_PRACH_CONFIG_IDX][8];
-uint16_t numRbForPrachTable[MAX_RACH_NUM_RB_IDX][5];
-uint8_t pucchResourceSet[MAX_PUCCH_RES_SET_IDX][4];
-uint8_t puschDeltaTable[MAX_MU_PUSCH];
-
 SchMacUlSchInfoFunc schMacUlSchInfoOpts[] =
 {
    packSchMacUlSchInfo,
@@ -77,10 +71,21 @@ uint8_t schBroadcastSsbAlloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstA
    SchDlSlotInfo *schDlSlotInfo;
    SsbInfo ssbInfo;
 
+   if(cell == NULL)
+   {
+      DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : Cell is NULL");
+      return RFAILED;
+   }
+
+   if(dlBrdcstAlloc == NULL)
+   {
+      DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : dlBrdcstAlloc is NULL");
+      return RFAILED;
+   }
+
    schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
    ssbStartPrb = cell->cellCfg.ssbSchCfg.ssbOffsetPointA; //+Kssb
-   ssbStartSymb = cell->ssbStartSymbArr[dlBrdcstAlloc->ssbIdxSupported-1]; /*since we are
-                                                                             supporting only 1 ssb beam */
+   ssbStartSymb = cell->ssbStartSymbArr[dlBrdcstAlloc->ssbIdxSupported-1]; /*since we are supporting only 1 ssb beam */
 
    /* Assign interface structure */
    for(idx=0; idx<dlBrdcstAlloc->ssbIdxSupported; idx++)
@@ -121,11 +126,47 @@ uint8_t schBroadcastSsbAlloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstA
  **/
 uint8_t schBroadcastSib1Alloc(SchCellCb *cell, SlotTimingInfo slotTime, DlBrdcstAlloc *dlBrdcstAlloc)
 {
-   FreqDomainAlloc freqAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc;
-   TimeDomainAlloc timeAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschTimeAlloc.timeAlloc;
-   SchDlSlotInfo *schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
+   uint8_t dmrsStartSymbol, startSymbol, numSymbol ;
+   DmrsInfo dmrs;
+   FreqDomainAlloc freqAlloc;
+   TimeDomainAlloc timeAlloc;
+   SchDlSlotInfo *schDlSlotInfo = NULLP;
 
-   if((allocatePrbDl(cell, slotTime, timeAlloc.startSymb, timeAlloc.numSymb, &freqAlloc.startPrb, freqAlloc.numPrb)) != ROK)
+   if(cell == NULL)
+   {
+      DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : Cell is NULL");
+      return RFAILED;
+   }
+
+   if(dlBrdcstAlloc == NULL)
+   {
+      DU_LOG("\nERROR  -->  SCH: schBroadcastSsbAlloc() : dlBrdcstAlloc is NULL");
+      return RFAILED;
+   }
+
+   dmrs = cell->cellCfg.sib1SchCfg.sib1PdschCfg.dmrs;
+   freqAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschFreqAlloc.freqAlloc;
+   timeAlloc = cell->cellCfg.sib1SchCfg.sib1PdschCfg.pdschTimeAlloc.timeAlloc;
+   schDlSlotInfo = cell->schDlSlotInfo[slotTime.slot];
+
+   /* Find total symbols used including DMRS */
+   /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
+    * in that case only PDSCH symbols are marked as occupied */
+   dmrsStartSymbol = findDmrsStartSymbol(dmrs.dlDmrsSymbPos);   
+   if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
+   {
+      startSymbol = timeAlloc.startSymb;
+      numSymbol = timeAlloc.numSymb;
+   }
+   /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
+   else
+   {
+      startSymbol = dmrsStartSymbol;
+      numSymbol = dmrs.nrOfDmrsSymbols + timeAlloc.numSymb;
+   }
+
+   /* Allocate PRB */
+   if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol, &freqAlloc.startPrb, freqAlloc.numPrb)) != ROK)
    {
        DU_LOG("\nERROR  -->  SCH: PRB allocation failed for SIB1 in SFN:Slot [%d : %d]", slotTime.sfn, slotTime.slot);
        return RFAILED;
@@ -165,105 +206,6 @@ int sendUlSchInfoToMac(UlSchedInfo *ulSchedInfo, Inst inst)
 
    return(*schMacUlSchInfoOpts[pst.selector])(&pst, ulSchedInfo);
 }
-/**
- * @brief resource allocation for PRACH
- *
- * @details
- *
- *     Function : schPrachResAlloc
- *     
- *     This function handles PRACH allocation
- *     
- *  @param[in]  SchCellCb *cell, cell cb
- *  @param[in]  UlSchedInfo *ulSchedInfo, UL scheduling info
- *  @return  void
- **/
-void schPrachResAlloc(SchCellCb *cell, UlSchedInfo *ulSchedInfo, SlotTimingInfo prachOccasionTimingInfo)
-{
-   uint8_t  puschScs;
-   uint8_t  numPrachRb = 0;
-   uint8_t  numRa = 0;
-   uint8_t  freqStart = 0;
-   uint8_t  prachCfgIdx = 0;
-   uint8_t  prachFormat = 0;
-   uint8_t  x = 0;
-   uint8_t  y = 0;
-   uint16_t prachSubframe = 0;
-   uint8_t  prachStartSymbol = 0;
-   uint8_t  prachOcas = 0;
-   uint8_t  dataType = 0;
-   uint8_t  idx = 0;
-   uint8_t  subFrame = 0;
-   SchUlSlotInfo *schUlSlotInfo = NULLP;
-
-   puschScs      = cell->cellCfg.schInitialUlBwp.bwp.scs;
-   schUlSlotInfo = cell->schUlSlotInfo[prachOccasionTimingInfo.slot];
-   prachCfgIdx   = cell->cellCfg.schRachCfg.prachCfgIdx;
-
-   /* derive the prachCfgIdx table paramters */
-   x                = prachCfgIdxTable[prachCfgIdx][1];
-   y                = prachCfgIdxTable[prachCfgIdx][2];
-   prachSubframe    = prachCfgIdxTable[prachCfgIdx][3];
-
-   if((prachOccasionTimingInfo.sfn%x) == y)
-   {
-#ifdef NR_TDD
-      subFrame = prachOccasionTimingInfo.slot/2;
-#else
-      subFrame = prachOccasionTimingInfo.slot;
-#endif
-      /* check for subFrame number */
-      if ((1 << subFrame) & prachSubframe)
-      {
-         /* prach ocassion present in this subframe */
-#ifdef NR_TDD
-         if(UL_SLOT != schGetSlotSymbFrmt(prachOccasionTimingInfo.slot%cell->numSlotsInPeriodicity,\
-         cell->slotFrmtBitMap))
-         {
-            DU_LOG("\nERROR  --> SCH : PrachCfgIdx %d doesn't support UL slot", prachCfgIdx);
-         }
-         else
-#endif
-         {
-            prachFormat      = prachCfgIdxTable[prachCfgIdx][0];
-            prachStartSymbol = prachCfgIdxTable[prachCfgIdx][4];
-            prachOcas        = prachCfgIdxTable[prachCfgIdx][6];
-
-            /* freq domain resource determination for RACH*/
-            freqStart = cell->cellCfg.schRachCfg.msg1FreqStart;
-            /* numRa determined as 𝑛 belonging {0,1,.., M − 1}, 
-             * where M is given by msg1Fdm */
-            numRa = (cell->cellCfg.schRachCfg.msg1Fdm - 1);
-            for(idx=0; idx<MAX_RACH_NUM_RB_IDX; idx++)
-            {
-               if(numRbForPrachTable[idx][0] == cell->cellCfg.schRachCfg.rootSeqLen)
-               {
-                  if(numRbForPrachTable[idx][1] == cell->cellCfg.schRachCfg.prachSubcSpacing)
-                  {
-                     if(numRbForPrachTable[idx][2] == puschScs)
-                     {
-                        break;
-                     }
-                  }
-               }
-            }
-            numPrachRb = numRbForPrachTable[idx][3];
-            dataType |= SCH_DATATYPE_PRACH;
-            /* Considering first slot in the frame for PRACH */
-            idx = 0;
-            //schUlSlotInfo->assignedPrb[idx] = freqStart+numPrachRb;
-         }
-         ulSchedInfo->dataType = dataType;
-         /* prach info */
-         ulSchedInfo->prachSchInfo.numPrachOcas   = prachOcas;
-         ulSchedInfo->prachSchInfo.prachFormat    = prachFormat;
-         ulSchedInfo->prachSchInfo.numRa          = numRa;
-         ulSchedInfo->prachSchInfo.prachStartSymb = prachStartSymbol;
-         DU_LOG("\nINFO  --> SCH : RACH occassion set for slot %d", prachOccasionTimingInfo.slot);
-      }
-   }
-}
-
 
 /**
  * @brief Function to fill Pucch Format 0
@@ -572,32 +514,42 @@ uint8_t schUlResAlloc(SchCellCb *cell, Inst schInst)
 uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo slotTime, DlMsgAlloc *msg4Alloc)
 {
    uint8_t coreset0Idx = 0;
-   uint8_t numRbs = 0;
    uint8_t firstSymbol = 0;
    uint8_t numSymbols = 0;
-   uint8_t offset = 0;
-   uint8_t offsetPointA;
-   uint8_t FreqDomainResource[6] = {0};
+   uint8_t mcs = DEFAULT_MCS;                         /* MCS fixed to 4 */
+   uint8_t dmrsStartSymbol = 0, startSymbol = 0, numSymbol = 0;
    uint16_t tbSize = 0;
-   uint8_t mcs = 4;                         /* MCS fixed to 4 */
-   SchBwpDlCfg *initialBwp;
+   uint16_t numRbs;
+   SchBwpDlCfg *initialBwp = NULLP;
+   PdcchCfg *pdcch = NULLP;
+   PdschCfg *pdsch = NULLP;
+   BwpCfg *bwp = NULLP;
 
-   PdcchCfg *pdcch = &msg4Alloc->dlMsgPdcchCfg;
-   PdschCfg *pdsch = &msg4Alloc->dlMsgPdschCfg;
-   BwpCfg *bwp = &msg4Alloc->bwp;
+   if(cell == NULL)
+   {
+      DU_LOG("\nERROR  -->  SCH: schDlRsrcAllocMsg4() : Cell is NULL");
+      return RFAILED;
+   }
 
+   if(msg4Alloc == NULL)
+   {
+      DU_LOG("\nERROR  -->  SCH: schDlRsrcAllocMsg4() :  msg4Alloc is NULL");
+      return RFAILED;
+   }
+
+   pdcch = &msg4Alloc->dlMsgPdcchCfg;
+   pdsch = &msg4Alloc->dlMsgPdschCfg;
+   bwp = &msg4Alloc->bwp;
    initialBwp   = &cell->cellCfg.schInitialDlBwp;
-   offsetPointA = cell->cellCfg.ssbSchCfg.ssbOffsetPointA;
    coreset0Idx  = initialBwp->pdcchCommon.commonSearchSpace.coresetId;
 
    /* derive the sib1 coreset0 params from table 13-1 spec 38.213 */
-   numRbs        = coresetIdxTable[coreset0Idx][1];
-   numSymbols    = coresetIdxTable[coreset0Idx][2];
-   offset        = coresetIdxTable[coreset0Idx][3];
+   numRbs     = coresetIdxTable[coreset0Idx][1];
+   numSymbols = coresetIdxTable[coreset0Idx][2];
 
    /* calculate time domain parameters */
    uint16_t mask = 0x2000;
-   for(firstSymbol=0; firstSymbol<14;firstSymbol++)
+   for(firstSymbol=0; firstSymbol<MAX_SYMB_PER_SLOT; firstSymbol++)
    {
       if(initialBwp->pdcchCommon.commonSearchSpace.monitoringSymbol & mask)
         break;
@@ -605,9 +557,6 @@ uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo slotTime, DlMsgAlloc
         mask = mask>>1;
    }
 
-   /* calculate the PRBs */
-   freqDomRscAllocType0(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource);
-
    /* fill BWP */
    bwp->freqAlloc.numPrb   = initialBwp->bwp.freqAlloc.numPrb;
    bwp->freqAlloc.startPrb = initialBwp->bwp.freqAlloc.startPrb;
@@ -617,7 +566,9 @@ uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo slotTime, DlMsgAlloc
    /* fill the PDCCH PDU */
    pdcch->coresetCfg.startSymbolIndex = firstSymbol;
    pdcch->coresetCfg.durationSymbols = numSymbols;
-   memcpy(pdcch->coresetCfg.freqDomainResource,FreqDomainResource,6);
+   memcpy(pdcch->coresetCfg.freqDomainResource, \
+      cell->cellCfg.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc, FREQ_DOM_RSRC_SIZE);
+
    pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */
    pdcch->coresetCfg.regBundleSize = 6;    /* spec-38.211 sec 7.3.2.2 */
    pdcch->coresetCfg.interleaverSize = 2;  /* spec-38.211 sec 7.3.2.2 */
@@ -677,8 +628,24 @@ uint8_t schDlRsrcAllocMsg4(SchCellCb *cell, SlotTimingInfo slotTime, DlMsgAlloc
    pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, mcs, NUM_PDSCH_SYMBOL);
    pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
 
+   /* Find total symbols occupied including DMRS */
+   dmrsStartSymbol = findDmrsStartSymbol(pdsch->dmrs.dlDmrsSymbPos);
+   /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
+    * in that case only PDSCH symbols are marked as occupied */
+   if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
+   {
+      startSymbol = pdsch->pdschTimeAlloc.timeAlloc.startSymb;
+      numSymbol = pdsch->pdschTimeAlloc.timeAlloc.numSymb;
+   }
+   /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
+   else
+   {
+      startSymbol = dmrsStartSymbol;
+      numSymbol = pdsch->dmrs.nrOfDmrsSymbols + pdsch->pdschTimeAlloc.timeAlloc.numSymb;
+   }
+
    /* Allocate the number of PRBs required for RAR PDSCH */
-   if((allocatePrbDl(cell, slotTime, pdsch->pdschTimeAlloc.timeAlloc.startSymb, pdsch->pdschTimeAlloc.timeAlloc.numSymb,\
+   if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol,\
       &pdsch->pdschFreqAlloc.freqAlloc.startPrb, pdsch->pdschFreqAlloc.freqAlloc.numPrb)) != ROK)
    {
       DU_LOG("\nERROR  --> SCH : Resource allocation failed for MSG4");
@@ -709,15 +676,15 @@ uint16_t schAllocPucchResource(SchCellCb *cell, uint16_t crnti, uint16_t slot)
    if(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfgPres)
    {
       schPucchCfg = &(cell->ueCb[ueIdx].ueCfg.spCellCfg.servCellCfg.initUlBwp.pucchCfg);
-     if(schPucchCfg->dlDataToUlAck)
-     {
-        for(dlToUlAckIdx = 0; dlToUlAckIdx < schPucchCfg->dlDataToUlAck->dlDataToUlAckListCount; dlToUlAckIdx++)
-       {
-           //For now considering only the first value in the list
-           k1 = schPucchCfg->dlDataToUlAck->dlDataToUlAckList[dlToUlAckIdx];
-          break;
-       }
-     }
+      if(schPucchCfg->dlDataToUlAck)
+      {
+         for(dlToUlAckIdx = 0; dlToUlAckIdx < schPucchCfg->dlDataToUlAck->dlDataToUlAckListCount; dlToUlAckIdx++)
+         {
+            //For now considering only the first value in the list
+            k1 = schPucchCfg->dlDataToUlAck->dlDataToUlAckList[dlToUlAckIdx];
+            break;
+         }
+      }
    }
    
    pucchSlot = (slot + k1)  % cell->numSlots;
@@ -747,16 +714,16 @@ uint16_t schAllocPucchResource(SchCellCb *cell, uint16_t crnti, uint16_t slot)
  *
  * ****************************************************************/
 uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t crnti,
-      uint32_t *accumalatedSize, DlMsgAlloc *dlMsgAlloc)
+                uint32_t tbSize, DlMsgAlloc *dlMsgAlloc, uint16_t startPRB)
 {
    uint8_t ueIdx;
-   uint16_t tbSize = 0;
    PdcchCfg *pdcch = NULLP;
    PdschCfg *pdsch = NULLP;
    BwpCfg *bwp = NULLP;
    SchUeCb ueCb;
    SchControlRsrcSet coreset1;
    SchPdschConfig pdschCfg;
+   uint8_t dmrsStartSymbol, startSymbol, numSymbol;
 
    pdcch = &dlMsgAlloc->dlMsgPdcchCfg;
    pdsch = &dlMsgAlloc->dlMsgPdschCfg;
@@ -813,9 +780,8 @@ uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t c
       pdsch->codeword[cwCount].mcsIndex = ueCb.ueCfg.dlModInfo.mcsIndex;
       pdsch->codeword[cwCount].mcsTable = ueCb.ueCfg.dlModInfo.mcsTable;
       pdsch->codeword[cwCount].rvIndex = 0;
-      tbSize = schCalcTbSize(*accumalatedSize + TX_PAYLOAD_HDR_LEN);
-      if(tbSize < *accumalatedSize)
-         *accumalatedSize = tbSize - TX_PAYLOAD_HDR_LEN;
+
+      tbSize +=TX_PAYLOAD_HDR_LEN;
       pdsch->codeword[cwCount].tbSize = tbSize;
    }
    pdsch->dataScramblingId = cell->cellCfg.phyCellId;
@@ -837,12 +803,28 @@ uint8_t schDlRsrcAllocDlMsg(SchCellCb *cell, SlotTimingInfo slotTime, uint16_t c
 
    pdsch->pdschFreqAlloc.vrbPrbMapping = 0; /* non-interleaved */
    pdsch->pdschFreqAlloc.resourceAllocType = 1; /* RAT type-1 RIV format */
-   pdsch->pdschFreqAlloc.freqAlloc.startPrb = MAX_NUM_RB;
+   pdsch->pdschFreqAlloc.freqAlloc.startPrb = startPRB; /*Start PRB will be already known*/
    pdsch->pdschFreqAlloc.freqAlloc.numPrb = schCalcNumPrb(tbSize, ueCb.ueCfg.dlModInfo.mcsIndex, \
                   pdschCfg.timeDomRsrcAllociList[0].symbolLength);
 
+   /* Find total symbols occupied including DMRS */
+   dmrsStartSymbol = findDmrsStartSymbol(pdsch->dmrs.dlDmrsSymbPos);
+   /* If there are no DRMS symbols, findDmrsStartSymbol() returns MAX_SYMB_PER_SLOT,
+    * in that case only PDSCH symbols are marked as occupied */
+   if(dmrsStartSymbol == MAX_SYMB_PER_SLOT)
+   {
+      startSymbol = pdsch->pdschTimeAlloc.timeAlloc.startSymb;
+      numSymbol = pdsch->pdschTimeAlloc.timeAlloc.numSymb;
+   }
+   /* If DMRS symbol is found, mark DMRS and PDSCH symbols as occupied */
+   else
+   {
+      startSymbol = dmrsStartSymbol;
+      numSymbol = pdsch->dmrs.nrOfDmrsSymbols + pdsch->pdschTimeAlloc.timeAlloc.numSymb;
+   }
+
    /* Allocate the number of PRBs required for DL PDSCH */
-   if((allocatePrbDl(cell, slotTime, pdsch->pdschTimeAlloc.timeAlloc.startSymb, pdsch->pdschTimeAlloc.timeAlloc.numSymb,\
+   if((allocatePrbDl(cell, slotTime, startSymbol, numSymbol,\
       &pdsch->pdschFreqAlloc.freqAlloc.startPrb, pdsch->pdschFreqAlloc.freqAlloc.numPrb)) != ROK)
    {
       DU_LOG("\nERROR  --> SCH : allocatePrbDl() failed for DL MSG");
@@ -1112,7 +1094,7 @@ SchPdschConfig pdschDedCfg, uint8_t ulAckListCount, uint8_t *UlAckTbl)
                   }   
                   if(slotCfg == FLEXI_SLOT)
                   {
-                     for(checkSymbol = 0; checkSymbol<SCH_SYMBOL_PER_SLOT;checkSymbol++)
+                     for(checkSymbol = 0; checkSymbol< MAX_SYMB_PER_SLOT;checkSymbol++)
                      {
                         if(cell->cellCfg.tddCfg.slotCfg[tmpSlot][checkSymbol] == UL_SLOT)
                         {
@@ -1346,6 +1328,238 @@ SchK2TimingInfoTbl *msg3K2InfoTbl, SchK2TimingInfoTbl *k2InfoTbl)
    }
 }
 
+/*******************************************************************************************
+ *
+ * @brief Allocate the PRB using RRM policy
+ *
+ * @details
+ *
+ *    Function : prbAllocUsingRRMPolicy
+ *
+ *    Functionality:
+ *      [Step1]: Traverse each Node in the LC list
+ *      [Step2]: Check whether the LC has ZERO requirement then clean this LC
+ *      [Step3]: Calcualte the maxPRB for this LC.
+ *              a. For Dedicated LC, maxPRB = sum of remainingReservedPRB and
+ *              sharedPRB
+ *              b. For Default, just SharedPRB count
+ *      [Step4]: If the LC is the First one to be allocated for this UE then add
+ *      TX_PAYLODN_LEN to reqBO 
+ *      [Step5]: Calculate the estimate PRB and estimate BO to be allocated
+ *               based on reqBO and maxPRB left.
+ *      [Step6]: Based on calculated PRB, Update Reserved PRB and Shared PRB counts
+ *      [Step7]: Deduce the reqBO based on allocBO and move the LC node to last.
+ *      [Step8]: Continue the next loop from List->head
+ *
+ *      [Loop Exit]:
+ *        [Exit1]: If all the LCs are allocated in list
+ *        [Exit2]: If PRBs are exhausted
+ *
+ * @params[in] I/P > lcLinkList pointer (LcInfo list)
+ *             I/P > IsDedicatedPRB (Flag to indicate that RESERVED PRB to use 
+ *             I/P > mcsIdx and PDSCH symbols count 
+ *             I/P & O/P > Shared PRB , reserved PRB Count
+ *             I/P & O/P > Total TBS size accumulated
+ *             I/P & O/P > isTxPayloadLenAdded : Decision flag to add the TX_PAYLOAD_HDR_LEN
+ *
+ * @return void
+ *
+ * *******************************************************************************************/
+void prbAllocUsingRRMPolicy(CmLListCp *lcLL, bool isDedicatedPRB, uint16_t mcsIdx,uint8_t numSymbols,\
+                              uint16_t *sharedPRB, uint16_t *reservedPRB, bool *isTxPayloadLenAdded)
+{
+   CmLList *node = NULLP;
+   LcInfo *lcNode = NULLP;
+   uint16_t remReservedPRB = 0, estPrb = 0, maxPRB = 0;
+
+   if(lcLL == NULLP)
+   {
+      DU_LOG("\nERROR --> SCH: LcList not present");
+      return;
+   }
+   node = lcLL->first;
+
+   /*Only for Dedicated LcList, Valid value will be assigned to remReservedPRB
+    * For Other LcList, remReservedPRB = 0*/
+   if(reservedPRB != NULLP && isDedicatedPRB == TRUE)
+   {
+      remReservedPRB = *reservedPRB;
+   }
+
+   /*[Step1]*/
+   while(node)
+   {
+#if 0
+      /*For Debugging purpose*/
+      printLcLL(lcLL);
+#endif
+      lcNode = (LcInfo *)node->node;
+
+      /* [Step2]: Below condition will hit in rare case as it has been taken care during the cleaning 
+       * process of LCID which was fully allocated. Check is just for safety purpose*/
+      if(lcNode->reqBO == 0 && lcNode->allocBO == 0)
+      {
+         DU_LOG("\nERROR --> SCH: LCID:%d has no requirement, clearing this node",\
+               lcNode->lcId);
+         deleteNodeFromLList(lcLL, node);
+         SCH_FREE(lcNode, sizeof(LcInfo));
+         node = lcLL->first; 
+         continue;
+      }
+
+      /*[Exit1]: All LCs are allocated(allocBO = 0 for fully unallocated LC)*/
+      if(lcNode->allocBO != 0)
+      {
+         DU_LOG("\nWARNING --> SCH: All LC are allocated [SharedPRB:%d]",*sharedPRB);
+         return;
+      }
+
+      /*[Exit2]: If PRBs are exhausted*/
+      if(isDedicatedPRB)
+      {
+         /*Loop Exit: All resources exhausted*/
+         if(remReservedPRB == 0 && *sharedPRB == 0)
+         {
+            DU_LOG("\nWARNING --> SCH: Dedicated resources exhausted for LC:%d",lcNode->lcId);
+            return;
+         }
+      }
+      else
+      {
+         /*Loop Exit: All resources exhausted*/
+         if(*sharedPRB == 0)
+         {
+            DU_LOG("\nWARNING --> SCH: Default resources exhausted for LC:%d",lcNode->lcId);
+            return;
+         }
+      }
+
+      /*[Step3]*/
+      maxPRB = remReservedPRB + *sharedPRB;
+
+      /*[Step4]*/
+      if(!(*isTxPayloadLenAdded))
+      {
+         DU_LOG("\nINFO --> SCH: LC:%d is the First node to be allocated which includes TX_PAYLOAD_HDR_LEN",\
+               lcNode->lcId);
+         *isTxPayloadLenAdded = TRUE;
+         lcNode->allocBO = calculateEstimateTBSize((lcNode->reqBO + TX_PAYLOAD_HDR_LEN),\
+               mcsIdx, numSymbols, maxPRB, &estPrb);
+         lcNode->allocBO -=TX_PAYLOAD_HDR_LEN;
+      }
+      else
+      {
+         /*[Step4]*/
+         lcNode->allocBO = calculateEstimateTBSize(lcNode->reqBO,\
+               mcsIdx, numSymbols, maxPRB, &estPrb);
+      }
+
+      /*[Step6]:Re-adjust the reservedPRB pool count and *SharedPRB Count based on
+       * estimated PRB allocated*/
+      if((isDedicatedPRB == TRUE) && (estPrb <= remReservedPRB))
+      {
+         remReservedPRB = remReservedPRB - estPrb;
+      }
+      else   /*LC requirement need PRB share from SharedPRB*/
+      {
+         if(*sharedPRB <=  (estPrb - remReservedPRB))
+         {
+            DU_LOG("\nINFO --> SCH: SharedPRB is less");
+            *sharedPRB = 0;
+         }
+         else
+         {
+            *sharedPRB = *sharedPRB - (estPrb - remReservedPRB);
+         }
+         remReservedPRB = 0;
+      }
+
+      /*[Step7]*/
+      lcNode->reqBO -= lcNode->allocBO;  /*Update the reqBO with remaining bytes unallocated*/
+      lcNode->allocPRB = estPrb;
+      cmLListAdd2Tail(lcLL, cmLListDelFrm(lcLL, node));
+
+      /*[Step8]:Next loop: First LC to be picked from the list
+       * because Allocated Nodes are moved to the last*/
+      node = lcLL->first; 
+
+   }
+   return;
+}
+
+/*******************************************************************************************
+ *
+ * @brief Check the LC List and fill the LC and GrantSize to be sent to MAC as
+ * BO Report
+ *
+ * @details
+ *
+ *    Function : updateGrantSizeForBoRpt
+ *
+ *    Functionality:
+ *             Check the LC List and fill the LC and GrantSize to be sent to MAC as
+ *             BO Report in dlMsgAlloc Pointer
+ *
+ * @params[in] I/P > lcLinkList pointer (LcInfo list)
+ *             I/P & O/P > dlMsgAlloc(Pending LC to be added in this context) 
+ *             I/P & O/P > accumalatedBOSize
+ * @return void
+ *
+ * *******************************************************************************************/
+void updateGrantSizeForBoRpt(CmLListCp *lcLL, DlMsgAlloc *dlMsgAlloc, uint32_t *accumalatedBOSize)
+{
+   CmLList *node = NULLP, *next = NULLP;
+   LcInfo *lcNode = NULLP;
+
+   if(lcLL == NULLP)
+   {
+      DU_LOG("\nERROR --> SCH: LcList not present");
+      return;
+   }
+
+   if(lcLL->count)
+   {
+      node = lcLL->first;
+   }
+   else
+   {
+      /*lcLL is empty*/
+      return;
+   }
+
+   /*Traverse List*/
+   while(node)
+   {
+      next = node->next;
+      lcNode = (LcInfo *)node->node;
+      if(lcNode != NULLP)
+      {
+         DU_LOG("\nINFO  --> SCH : LcID:%d, [reqBO, allocBO, allocPRB]:[%d,%d,%d]",\
+               lcNode->lcId, lcNode->reqBO, lcNode->allocBO, lcNode->allocPRB);
+
+         /*Add this LC to dlMsgAlloc so that if this LC gets allocated, BO
+          * report for allocation can be sent to MAC*/
+         dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].lcId = lcNode->lcId;
+         dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].schBytes = lcNode->allocBO;
+
+         /*Calculate the Total Payload/BO size allocated*/
+         *accumalatedBOSize += dlMsgAlloc->lcSchInfo[dlMsgAlloc->numLc].schBytes; 
+
+         DU_LOG("\nINFO --> SCH: Added in MAC BO report: LCID:%d,reqBO:%d,Idx:%d, TotalBO Size:%d",\
+               lcNode->lcId,lcNode->reqBO, dlMsgAlloc->numLc, *accumalatedBOSize);
+
+         dlMsgAlloc->numLc++;
+         /*The LC has been fully allocated, clean it*/
+         if(lcNode->reqBO == 0)
+         {
+            handleLcLList(lcLL, lcNode->lcId, DELETE);
+         }
+      }
+      node = next;
+   }/*End of while*/
+   return;
+}
+
 /**********************************************************************
   End of file
  **********************************************************************/