X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2F5gnrsch%2Fsch.c;h=e2b86d134aaf31b14967b0e8de9bb7e515d5421b;hb=e96cb439cd4a7a6f55e3fab7caed978e38bd62b4;hp=9017f924d0b98287fd31fcdf33def32638bcd57d;hpb=b3d5c17f74361fcdcb9b9febff450292197e3a57;p=o-du%2Fl2.git diff --git a/src/5gnrsch/sch.c b/src/5gnrsch/sch.c index 9017f924d..e2b86d134 100644 --- a/src/5gnrsch/sch.c +++ b/src/5gnrsch/sch.c @@ -595,7 +595,7 @@ uint8_t fillSchSib1Cfg(uint8_t mu, uint8_t bandwidth, uint8_t numSlots,SchPdcchC uint8_t mValue = 0; uint8_t firstSymbol = 0; /* need to calculate using formula mentioned in 38.213 */ uint8_t slotIndex = 0; - uint8_t FreqDomainResource[FREQ_DOM_RSRC_SIZE] = {0}; + uint8_t freqDomainResource[FREQ_DOM_RSRC_SIZE] = {0}; uint16_t tbSize = 0; uint8_t ssbIdx = 0; PdcchCfg *pdcch; @@ -655,8 +655,8 @@ uint8_t fillSchSib1Cfg(uint8_t mu, uint8_t bandwidth, uint8_t numSlots,SchPdcchC pdcch->coresetCfg.durationSymbols = numSymbols; /* Fill Bitmap for PRBs in coreset */ - fillCoresetFeqDomAllocMap(((offsetPointA-offset)/6), (numRbs/6), FreqDomainResource); - covertFreqDomRsrcMapToIAPIFormat(FreqDomainResource, pdcch->coresetCfg.freqDomainResource); + fillCoresetFeqDomAllocMap(((offsetPointA-offset)/6), (numRbs/6), freqDomainResource); + memcpy(pdcch->coresetCfg.freqDomainResource, freqDomainResource, FREQ_DOM_RSRC_SIZE); pdcch->coresetCfg.cceRegMappingType = 1; /* coreset0 is always interleaved */ pdcch->coresetCfg.regBundleSize = 6; /* spec-38.211 sec 7.3.2.2 */ @@ -665,21 +665,21 @@ uint8_t fillSchSib1Cfg(uint8_t mu, uint8_t bandwidth, uint8_t numSlots,SchPdcchC pdcch->coresetCfg.shiftIndex = pci; pdcch->coresetCfg.precoderGranularity = 0; /* sameAsRegBundle */ pdcch->numDlDci = 1; - pdcch->dci.rnti = SI_RNTI; - pdcch->dci.scramblingId = pci; - pdcch->dci.scramblingRnti = 0; - pdcch->dci.cceIndex = 0; - pdcch->dci.aggregLevel = 4; - pdcch->dci.beamPdcchInfo.numPrgs = 1; - pdcch->dci.beamPdcchInfo.prgSize = 1; - pdcch->dci.beamPdcchInfo.digBfInterfaces = 0; - pdcch->dci.beamPdcchInfo.prg[0].pmIdx = 0; - pdcch->dci.beamPdcchInfo.prg[0].beamIdx[0] = 0; - pdcch->dci.txPdcchPower.beta_pdcch_1_0= 0; - pdcch->dci.txPdcchPower.powerControlOffsetSS = 0; + pdcch->dci[0].rnti = SI_RNTI; + pdcch->dci[0].scramblingId = pci; + pdcch->dci[0].scramblingRnti = 0; + pdcch->dci[0].cceIndex = 0; + pdcch->dci[0].aggregLevel = 4; + pdcch->dci[0].beamPdcchInfo.numPrgs = 1; + pdcch->dci[0].beamPdcchInfo.prgSize = 1; + pdcch->dci[0].beamPdcchInfo.digBfInterfaces = 0; + pdcch->dci[0].beamPdcchInfo.prg[0].pmIdx = 0; + pdcch->dci[0].beamPdcchInfo.prg[0].beamIdx[0] = 0; + pdcch->dci[0].txPdcchPower.beta_pdcch_1_0= 0; + pdcch->dci[0].txPdcchPower.powerControlOffsetSS = 0; /* Storing pdschCfg pointer here. Required to access pdsch config while fillig up pdcch pdu */ - pdsch = &pdcch->dci.pdschCfg; + pdsch = &pdcch->dci[0].pdschCfg; /* fill the PDSCH PDU */ uint8_t cwCount = 0; @@ -782,9 +782,8 @@ uint8_t SchProcCellCfgReq(Pst *pst, SchCellCfg *schCellCfg) offset = coresetIdxTable[coreset0Idx][3]; fillCoresetFeqDomAllocMap(((cellCb->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA - offset)/6), \ (numRbs/6), freqDomainResource); - covertFreqDomRsrcMapToIAPIFormat(freqDomainResource, \ - cellCb->cellCfg.dlCfgCommon.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc); - + memcpy(cellCb->cellCfg.dlCfgCommon.schInitialDlBwp.pdcchCommon.commonSearchSpace.freqDomainRsrc,\ + freqDomainResource,FREQ_DOM_RSRC_SIZE); /* Fill K0 - K1 table for common cfg*/ BuildK0K1Table(cellCb, &cellCb->k0K1InfoTbl, true, cellCb->cellCfg.dlCfgCommon.schInitialDlBwp.pdschCommon, pdschCfg, DEFAULT_UL_ACK_LIST_COUNT, defaultUlAckTbl); @@ -887,6 +886,7 @@ uint8_t SchSendCellDeleteRspToMac(SchCellDeleteReq *ueDelete, Inst inst, SchMac void deleteSchCellCb(SchCellCb *cellCb) { uint8_t sliceIdx=0, slotIdx=0, plmnIdx = 0; + uint8_t ueIdx = 0; CmLListCp *list=NULL; CmLList *node=NULL, *next=NULL; SchPageInfo *tempNode = NULLP; @@ -904,6 +904,12 @@ void deleteSchCellCb(SchCellCb *cellCb) deleteNodeFromLList(list, node); node = next; } + for(ueIdx = 0; ueIdx< MAX_NUM_UE; ueIdx++) + { + SCH_FREE(cellCb->schDlSlotInfo[slotIdx]->rarAlloc[ueIdx], sizeof(RarAlloc)); + SCH_FREE(cellCb->schDlSlotInfo[slotIdx]->dlMsgAlloc[ueIdx], sizeof(DlMsgSchInfo)); + } + SCH_FREE(cellCb->schDlSlotInfo[slotIdx]->ulGrant, sizeof(DciInfo)); SCH_FREE(cellCb->schDlSlotInfo[slotIdx], sizeof(SchDlSlotInfo)); } SCH_FREE(cellCb->schDlSlotInfo, cellCb->numSlots *sizeof(SchDlSlotInfo*)); @@ -922,6 +928,10 @@ void deleteSchCellCb(SchCellCb *cellCb) deleteNodeFromLList(list, node); node = next; } + for(ueIdx = 0; ueIdx< MAX_NUM_UE; ueIdx++) + { + SCH_FREE(cellCb->schUlSlotInfo[slotIdx]->schPuschInfo[ueIdx], sizeof(SchPuschInfo)); + } SCH_FREE(cellCb->schUlSlotInfo[slotIdx], sizeof(SchUlSlotInfo)); } SCH_FREE(cellCb->schUlSlotInfo, cellCb->numSlots * sizeof(SchUlSlotInfo*)); @@ -929,13 +939,13 @@ void deleteSchCellCb(SchCellCb *cellCb) for(plmnIdx = 0; plmnIdx < MAX_PLMN; plmnIdx++) { - if(cellCb->cellCfg.plmnInfoList[plmnIdx].snssai) + if(cellCb->cellCfg.plmnInfoList[plmnIdx].suppSliceList.snssai) { - for(sliceIdx=0; sliceIdxcellCfg.plmnInfoList[plmnIdx].numSliceSupport; sliceIdx++) + for(sliceIdx=0; sliceIdxcellCfg.plmnInfoList[plmnIdx].suppSliceList.numSupportedSlices; sliceIdx++) { - SCH_FREE(cellCb->cellCfg.plmnInfoList[plmnIdx].snssai[sliceIdx], sizeof(Snssai)); + SCH_FREE(cellCb->cellCfg.plmnInfoList[plmnIdx].suppSliceList.snssai[sliceIdx], sizeof(Snssai)); } - SCH_FREE(cellCb->cellCfg.plmnInfoList[plmnIdx].snssai, cellCb->cellCfg.plmnInfoList[plmnIdx].numSliceSupport*sizeof(Snssai*)); + SCH_FREE(cellCb->cellCfg.plmnInfoList[plmnIdx].suppSliceList.snssai, cellCb->cellCfg.plmnInfoList[plmnIdx].suppSliceList.numSupportedSlices*sizeof(Snssai*)); } } @@ -1298,7 +1308,7 @@ uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, \ if(ssbOccasion && sib1Occasion) { broadcastPrbStart = cell->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA; - broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1; + broadcastPrbEnd = broadcastPrbStart + SCH_SSB_NUM_PRB + cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschFreqAlloc.numPrb -1; } else if(ssbOccasion) { @@ -1307,8 +1317,8 @@ uint8_t allocatePrbDl(SchCellCb *cell, SlotTimingInfo slotTime, \ } else if(sib1Occasion) { - broadcastPrbStart = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.startPrb; - broadcastPrbEnd = broadcastPrbStart + cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1; + broadcastPrbStart = cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschFreqAlloc.startPrb; + broadcastPrbEnd = broadcastPrbStart + cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschFreqAlloc.numPrb -1; } /* Iterate through all free PRB blocks */ @@ -1584,7 +1594,7 @@ uint16_t searchLargestFreeBlock(SchCellCb *cell, SlotTimingInfo slotTime,uint16_ { reservedPrbStart = cell->cellCfg.dlCfgCommon.schFreqInfoDlSib.offsetToPointA; reservedPrbEnd = reservedPrbStart + SCH_SSB_NUM_PRB + \ - cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1; + cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschFreqAlloc.numPrb -1; } else if(ssbOccasion) { @@ -1593,8 +1603,8 @@ uint16_t searchLargestFreeBlock(SchCellCb *cell, SlotTimingInfo slotTime,uint16_ } else if(sib1Occasion) { - reservedPrbStart = cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.startPrb; - reservedPrbEnd = reservedPrbStart + cell->sib1SchCfg.sib1PdcchCfg.dci.pdschCfg.pdschFreqAlloc.numPrb -1; + reservedPrbStart = cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschFreqAlloc.startPrb; + reservedPrbEnd = reservedPrbStart + cell->sib1SchCfg.sib1PdcchCfg.dci[0].pdschCfg.pdschFreqAlloc.numPrb -1; } else { @@ -1766,10 +1776,10 @@ uint8_t fillSliceCfgRsp(Inst inst, CmLListCp *storedSliceCfg, SchCellCb *cellCb, /* Here comparing the slice cfg request with the slice stored in cellCfg */ for(plmnIdx = 0; plmnIdx < MAX_PLMN; plmnIdx++) { - for(sliceIdx = 0; sliceIdxcellCfg.plmnInfoList[plmnIdx].numSliceSupport; sliceIdx++) + for(sliceIdx = 0; sliceIdxcellCfg.plmnInfoList[plmnIdx].suppSliceList.numSupportedSlices; sliceIdx++) { /* If we find the SliceCfgReq's SNSSAI in CellCb's SNSSAI DB, we mark this slice as configured and add it to Sch's DB. */ - if(!memcmp(&schSliceCfgReq->listOfSlices[cfgIdx]->snssai, cellCb->cellCfg.plmnInfoList[plmnIdx].snssai[sliceIdx], sizeof(Snssai))) + if(!memcmp(&schSliceCfgReq->listOfSlices[cfgIdx]->snssai, cellCb->cellCfg.plmnInfoList[plmnIdx].suppSliceList.snssai[sliceIdx], sizeof(Snssai))) { if(addSliceCfgInSchDb(storedSliceCfg, schSliceCfgReq->listOfSlices[cfgIdx]) == ROK) { @@ -2606,39 +2616,206 @@ uint8_t SchRejectAllStats(SchStatsReq *schStatsReq, CauseOfResult cause) * Instead, we can traverse through KPI-Active-List and update * all entries in this list. * - * @params[in] Statistics request from MAC - * Cause of rejection + * @params[in] Pointer to the prb usage info link list + * Pointer to the stats ccnfig which we need to add * @return ROK - success * RFAILED - failure * * ****************************************************************/ -uint8_t schAddToKpiActiveList(Inst inst, SchStatsGrp *grpInfo) +uint8_t schAddToKpiActiveList(CmLListCp *kpiList, PTR kpiStatsInfo) { CmLList *node = NULLP; - /* If DL Total PRB Usage configured for this stats group, add to list */ - if(grpInfo->kpiStats.dlTotalPrbUsage) + SCH_ALLOC(node, sizeof(CmLList)); + if(node) { - SCH_ALLOC(node, sizeof(CmLList)); - if(node) + node->node = kpiStatsInfo; + cmLListAdd2Tail(kpiList, node); + return ROK; + } + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at line %d",__func__, __LINE__); + return RFAILED; +} + + /******************************************************************* + * + * @brief add the stats group information in statistics's statsGrpList + * + * @details + * + * Function : schAddToStatsGrpList + * + * Functionality: add the stats group information in statsGrpList + * [Step 1] - Allocating the memory for the stats group in which + * we need to fill into the list as a node. + * [Step 2] - If allocation is successful then start traversing + * each measurment cfg index of received group info. + * [Step 2.1] Validate all measurements. If validation succeeds, go + * to [step 2.2]. Otherwise, reject the stats group and go to step 3. + * [Step 2.2] Add each KPI/measurementCfg into activeKpiList one by one. + * If it fails for any KPI, reject the whole statsGrp and go to step 3.. + * [Step 2.3] Fill other group related information + * [Step 2.4] Initialise and start timer + * [Step 2.5] Once all validation and configuration is successful, add + * statsGrp node into statistic's StatsGrpList. + * [Step 2.5.1] If node successfully added to the list, then + * fill the group related info in stats rsp's accepted list. + * [Step 2.5.2] Else goto step 3 + * [Step 3] - If failed fill the group related info in stats rsp's + * rejected list. + * + * @params[in] + * Inst + * Pointer to the stats rsp + * Subscription Id + * Stats Grp Info which needs to be store in the list + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ + +uint8_t schAddToStatsGrpList(Inst inst, struct schStatsRsp *statsRsp, uint64_t subscriptionId, SchStatsGrpInfo *grpInfo) +{ + uint8_t ret =ROK; + uint8_t grpIdx=0; + uint8_t reqMeasIdx=0; + CauseOfResult cause; + bool measTypeInvalid=false; + CmLList *statsGrpNode=NULLP; + SchStatsGrp *grpInfoDb = NULLP; + + /* Step 1 */ + SCH_ALLOC(grpInfoDb, sizeof(SchStatsGrp)); + if(grpInfoDb == NULLP) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at line %d",__func__, __LINE__); + cause = RESOURCE_UNAVAILABLE; + ret = RFAILED; + } + else + { + /* Step 2 */ + for(reqMeasIdx = 0; reqMeasIdx < grpInfo->numStats; reqMeasIdx++) + { + /* Step 2.1 */ + switch(grpInfo->statsList[reqMeasIdx]) + { + case SCH_DL_TOTAL_PRB_USAGE: + { + SCH_ALLOC(grpInfoDb->kpiStats.dlTotalPrbUsage, sizeof(TotalPrbUsage)); + if(!grpInfoDb->kpiStats.dlTotalPrbUsage) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at line %d",__func__, __LINE__); + measTypeInvalid = true; + cause = RESOURCE_UNAVAILABLE; + break; + } + break; + } + + case SCH_UL_TOTAL_PRB_USAGE: + { + SCH_ALLOC(grpInfoDb->kpiStats.ulTotalPrbUsage, sizeof(TotalPrbUsage)); + if(!grpInfoDb->kpiStats.ulTotalPrbUsage) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at line %d",__func__, __LINE__); + measTypeInvalid = true; + cause = RESOURCE_UNAVAILABLE; + break; + } + break; + } + + default: + { + DU_LOG("\nERROR --> SCH : SchProcStatsReq: Invalid measurement type [%d]", \ + grpInfo->statsList[reqMeasIdx]); + measTypeInvalid = true; + cause = PARAM_INVALID; + break; + } + } + + if(measTypeInvalid) + { + ret =RFAILED; + break; + } + } + + while(measTypeInvalid==false) { - node->node = (PTR)grpInfo->kpiStats.dlTotalPrbUsage; - cmLListAdd2Tail(&schCb[inst].statistics.activeKpiList.dlTotPrbUseList, node); + if(grpInfoDb->kpiStats.dlTotalPrbUsage) + { + /* Step 2.2 */ + if(schAddToKpiActiveList(&schCb[inst].statistics.activeKpiList.dlTotPrbUseList, (PTR)grpInfoDb->kpiStats.dlTotalPrbUsage)!=ROK) + { + DU_LOG("\nERROR --> E2AP : KPI addition failed in %s at %d",__func__,__LINE__); + cause = RESOURCE_UNAVAILABLE; + ret =RFAILED; + break; + } + } + + if(grpInfoDb->kpiStats.ulTotalPrbUsage) + { + /* Step 2.2 */ + if(schAddToKpiActiveList(&schCb[inst].statistics.activeKpiList.ulTotPrbUseList, (PTR)grpInfoDb->kpiStats.ulTotalPrbUsage) != ROK) + { + DU_LOG("\nERROR --> E2AP : KPI addition failed in %s at %d",__func__,__LINE__); + cause = RESOURCE_UNAVAILABLE; + ret =RFAILED; + break; + } + } + + /* Step 2.3 */ + grpInfoDb->schInst = inst; + grpInfoDb->groupId = grpInfo->groupId; + grpInfoDb->periodicity = grpInfo->periodicity; + grpInfoDb->subscriptionId = subscriptionId; + + /* Step 2.4 */ + cmInitTimers(&(grpInfoDb->periodTimer), 1); + schStartTmr(&schCb[inst], (PTR)(grpInfoDb), EVENT_STATISTICS_TMR, grpInfoDb->periodicity); + + /* Step 2.5 */ + SCH_ALLOC(statsGrpNode, sizeof(CmLList)); + if(statsGrpNode) + { + /* Step 2.5.1 */ + statsGrpNode->node = (PTR) grpInfoDb; + cmLListAdd2Tail(&schCb[inst].statistics.statsGrpList, statsGrpNode); + statsRsp->statsGrpAcceptedList[statsRsp->numGrpAccepted] = grpInfo->groupId; + statsRsp->numGrpAccepted++; + grpIdx++; + ret = ROK; + break; + } + else + { + /* Step 2.5.2 */ + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at %d",__func__,__LINE__); + cause = RESOURCE_UNAVAILABLE; + ret = RFAILED; + break; + } } } - /* If UL Total PRB Usage configured for this stats group, add to list */ - node = NULLP; - if(grpInfo->kpiStats.ulTotalPrbUsage) + if(ret != ROK) { - SCH_ALLOC(node, sizeof(CmLList)); - if(node) + /* Step 3 */ + if(grpInfoDb) { - node->node = (PTR)grpInfo->kpiStats.ulTotalPrbUsage; - cmLListAdd2Tail(&schCb[inst].statistics.activeKpiList.ulTotPrbUseList, node); + deleteStatsGrpInfo(inst, grpInfoDb); + SCH_FREE(grpInfoDb, sizeof(SchStatsGrp)); } + statsRsp->statsGrpRejectedList[statsRsp->numGrpRejected].groupId = grpInfo->groupId; + statsRsp->statsGrpRejectedList[statsRsp->numGrpRejected].cause = cause; + statsRsp->numGrpRejected++; + return RFAILED; } - return ROK; } @@ -2661,8 +2838,7 @@ uint8_t schAddToKpiActiveList(Inst inst, SchStatsGrp *grpInfo) * is not configured and it is added to stats-group-rejected-list in * sch-stats-response message. * [Step 4] If a group passes all validation, it is added to SCH database. - * A timer is started for this group. And the group is added to - * stats-group-accepted-list in sch-stats-response message. + * And the group is added to stats-group-accepted-list in sch-stats-response message. * [Step 5] sch-stats-response is sent to du app with stats-group-rejected-list * and stats-group-accepted-list. * @@ -2674,14 +2850,11 @@ uint8_t schAddToKpiActiveList(Inst inst, SchStatsGrp *grpInfo) * ****************************************************************/ uint8_t SchProcStatsReq(Pst *pst, SchStatsReq *statsReq) { - uint8_t grpIdx = 0, reqGrpIdx = 0, reqMeasIdx = 0; - Inst inst = pst->dstInst - SCH_INST_START; - bool measTypeInvalid; - CauseOfResult cause; - SchStatsInfo *statsInfo = NULLP; + bool allocFailed = false; + uint8_t grpIdx = 0, reqGrpIdx = 0; SchStatsGrpInfo *grpInfo = NULLP; - SchStatsGrp *grpInfoDb = NULLP; SchStatsRsp schStatsRsp; + Inst inst = pst->dstInst - SCH_INST_START; DU_LOG("\nINFO --> SCH : Received Statistics Request from MAC"); @@ -2691,10 +2864,8 @@ uint8_t SchProcStatsReq(Pst *pst, SchStatsReq *statsReq) return RFAILED; } - /* [Step 1] Basic validation. If fails, all stats group in stats request are rejected */ - - /* If maximum number of statistics already configured */ - if(schCb[inst].statistics.numOfStatsCfgd >= MAX_NUM_STATS_CFG) + /*Step -1*/ + if(schCb[inst].statistics.statsGrpList.count >= MAX_NUM_STATS_GRP) { DU_LOG("\nERROR --> SCH : SchProcStatsReq: Maximum number of statistics configured. \ Cannot process new request."); @@ -2705,123 +2876,40 @@ uint8_t SchProcStatsReq(Pst *pst, SchStatsReq *statsReq) memset(&schStatsRsp, 0, sizeof(SchStatsRsp)); - /* [Step 2] Traverse all stats group and validate each measurement types in each group */ - statsInfo = &schCb[inst].statistics.statsInfoList[schCb[inst].statistics.numOfStatsCfgd]; - statsInfo->numStatsGroup = 0; + /*Step -2*/ for(reqGrpIdx=0; reqGrpIdxnumStatsGroup && grpIdxstatsGrpList[reqGrpIdx]; - grpInfoDb = &statsInfo->statsGrpList[grpIdx]; - for(reqMeasIdx = 0; reqMeasIdx < grpInfo->numStats; reqMeasIdx++) - { - switch(grpInfo->statsList[reqMeasIdx]) - { - case SCH_DL_TOTAL_PRB_USAGE: - { - /* Allocate memory */ - SCH_ALLOC(grpInfoDb->kpiStats.dlTotalPrbUsage, sizeof(TotalPrbUsage)); - if(!grpInfoDb->kpiStats.dlTotalPrbUsage) - { - DU_LOG("\nERROR --> SCH : Memory allocation failed for dlTotalPrbUsage in \ - SchProcStatsReq()"); - measTypeInvalid = true; - cause = RESOURCE_UNAVAILABLE; - } - break; - } - - case SCH_UL_TOTAL_PRB_USAGE: - { - /* Allocate memory */ - SCH_ALLOC(grpInfoDb->kpiStats.ulTotalPrbUsage, sizeof(TotalPrbUsage)); - if(!grpInfoDb->kpiStats.ulTotalPrbUsage) - { - DU_LOG("\nERROR --> SCH : Memory allocation failed for dlTotalPrbUsage in \ - SchProcStatsReq()"); - measTypeInvalid = true; - cause = RESOURCE_UNAVAILABLE; - } - break; - } - - default: - { - DU_LOG("\nERROR --> SCH : SchProcStatsReq: Invalid measurement type [%d]", \ - grpInfo->statsList[reqMeasIdx]); - measTypeInvalid = true; - cause = PARAM_INVALID; - break; - } - } - - /* [Step 3 a] If any measurement type validation fails in a group, that group - * is not configured */ - if(measTypeInvalid) - { - SCH_FREE(grpInfoDb->kpiStats.dlTotalPrbUsage, sizeof(TotalPrbUsage)); - SCH_FREE(grpInfoDb->kpiStats.ulTotalPrbUsage, sizeof(TotalPrbUsage)); - memset(grpInfoDb, 0, sizeof(SchStatsGrp)); - break; - } - } - - /* [Step 4] If a group passes all validation, it is added to SCH database. - * A timer is started for this group. And the group is added to - * stats-group-accepted-list in sch-stats-response message. */ - if(!measTypeInvalid) - { - /* Add this group's configured KPIs to list of Active KPIs */ - if(schAddToKpiActiveList(inst, grpInfoDb) == ROK) - { - grpInfoDb->schInst = inst; - grpInfoDb->subscriptionId = statsReq->subscriptionId; - grpInfoDb->groupId = grpInfo->groupId; - grpInfoDb->periodicity = grpInfo->periodicity; - - - /* Start timer */ - cmInitTimers(&(grpInfoDb->periodTimer), 1); - schStartTmr(&schCb[inst], (PTR)(grpInfoDb), EVENT_STATISTICS_TMR, grpInfoDb->periodicity); - - schStatsRsp.statsGrpAcceptedList[schStatsRsp.numGrpAccepted] = grpInfo->groupId; - schStatsRsp.numGrpAccepted++; - grpIdx++; - } - else - { - memset(grpInfoDb, 0, sizeof(SchStatsGrp)); - } - } - else - { - /* [Step 3 b] The rejected group is added to stats-group-rejected-list in - * sch-stats-response message */ - memset(grpInfoDb, 0, sizeof(SchStatsGrp)); - schStatsRsp.statsGrpRejectedList[schStatsRsp.numGrpRejected].groupId = grpInfo->groupId; - schStatsRsp.statsGrpRejectedList[schStatsRsp.numGrpRejected].cause = cause; - schStatsRsp.numGrpRejected++; - } - } - statsInfo->numStatsGroup = grpIdx; - if(statsInfo->numStatsGroup) - { - schCb[inst].statistics.numOfStatsCfgd++; - } - else - { - memset(statsInfo, 0, sizeof(SchStatsInfo)); + grpInfo = &statsReq->statsGrpList[reqGrpIdx]; + /*Step -3 */ + if(allocFailed == true) + { + schStatsRsp.statsGrpRejectedList[schStatsRsp.numGrpRejected].groupId = grpInfo->groupId; + schStatsRsp.statsGrpRejectedList[schStatsRsp.numGrpRejected].cause = RESOURCE_UNAVAILABLE; + schStatsRsp.numGrpRejected++; + } + else + { + /*Step -4 */ + if(schAddToStatsGrpList(inst, &schStatsRsp, statsReq->subscriptionId, grpInfo) != ROK) + { + DU_LOG("\nERROR --> SCH : SchProcStatsReq(): Failed to fill the stats group list"); + if((schStatsRsp.statsGrpRejectedList[schStatsRsp.numGrpRejected-1].groupId == grpInfo->groupId &&\ + (schStatsRsp.statsGrpRejectedList[schStatsRsp.numGrpRejected-1].cause == RESOURCE_UNAVAILABLE))) + { + allocFailed = true; + } + } + } } - schStatsRsp.subscriptionId = statsReq->subscriptionId; + schStatsRsp.subscriptionId = statsReq->subscriptionId; SCH_FREE(statsReq, sizeof(SchStatsReq)); - - /* [Step 5] sch-stats-response is sent to du app with stats-group-rejected-list - * and stats-group-accepted-list. */ + + /*Step -5 */ SchSendStatsRspToMac(&schStatsRsp); return ROK; -} /* End of SchProcStatsReq */ +} /******************************************************************* * @@ -2945,6 +3033,555 @@ uint8_t schCalcAndSendGrpStats(SchStatsGrp *grpInfo) return SchSendStatsIndToMac(grpInfo->schInst, &statsInd); } +/******************************************************************* + * + * @brief Delete node from active kpi list + * + * @details + * + * Function :deleteNodeFrmKpiList + * + * Functionality: + * Delete statistics group + * + * @params[in] + * Kpi list from which a node needs to be deleted + * Nodes info which a node needs to be deleted + * @return void + * ****************************************************************/ + +void deleteNodeFrmKpiList(CmLListCp *kpiList, PTR kpiNodeInfoToDel) +{ + CmLList *kpiNode=NULLP; + + CM_LLIST_FIRST_NODE(kpiList, kpiNode); + while(kpiNode) + { + if(kpiNode->node == kpiNodeInfoToDel) + { + cmLListDelFrm(kpiList, kpiNode); + SCH_FREE(kpiNode, sizeof(CmLList)); + break; + } + kpiNode = kpiNode->next; + } + +} + +/******************************************************************* + * + * @brief Delete statistics group info + * + * @details + * + * Function : deleteStatsGrpInfo + * + * Functionality: + * Delete statistics group info + * + * @params[in] + * Inst + * Stats Grp info + * @return void + * + * ****************************************************************/ +void deleteStatsGrpInfo(Inst inst, SchStatsGrp *statsGrpInfo) +{ + if(statsGrpInfo) + { + if(statsGrpInfo->kpiStats.dlTotalPrbUsage) + { + deleteNodeFrmKpiList(&schCb[inst].statistics.activeKpiList.dlTotPrbUseList, (PTR) statsGrpInfo->kpiStats.dlTotalPrbUsage); + SCH_FREE(statsGrpInfo->kpiStats.dlTotalPrbUsage, sizeof(TotalPrbUsage)); + } + + if(statsGrpInfo->kpiStats.ulTotalPrbUsage) + { + deleteNodeFrmKpiList(&schCb[inst].statistics.activeKpiList.ulTotPrbUseList, (PTR) statsGrpInfo->kpiStats.ulTotalPrbUsage); + SCH_FREE(statsGrpInfo->kpiStats.ulTotalPrbUsage, sizeof(TotalPrbUsage)); + } + + if(schChkTmr((PTR)statsGrpInfo, EVENT_STATISTICS_TMR) == true) + { + schStopTmr(&schCb[inst], (PTR)statsGrpInfo, EVENT_STATISTICS_TMR); + } + + memset(statsGrpInfo, 0, sizeof(SchStatsGrp)); + } +} + +/******************************************************************* + * + * @brief Delete statistics group Node + * + * @details + * + * Function : deleteStatsGrpNode + * + * Functionality: + * Delete statistics group node + * + * @params[in] + * Inst + * Stats Grp Node + * @return void + * + * ****************************************************************/ +void deleteStatsGrpNode(Inst inst, CmLList *grpNode) +{ + SchStatsGrp *statsGrpInfo=NULLP; + + if(grpNode) + { + statsGrpInfo = (SchStatsGrp*)grpNode->node; + deleteStatsGrpInfo(inst, statsGrpInfo); + memset(statsGrpInfo, 0, sizeof(SchStatsGrp)); + SCH_FREE(grpNode->node, sizeof(SchStatsGrp)); + SCH_FREE(grpNode, sizeof(CmLList)); + } +} + +/****************************************************************** + * + * @brief Deletion of node from statistics group list + * + * @details + * + * Function : deleteFromStatsGrpList + * + * Functionality: Deletion of node from statistics group list + * [Step 1]: Traverse each and every node of stats group list + * stored in the database + * [Step 2]: Check if the node's subscription id is same + * as the subscription id received. If same then go to step 3 + * else move to the next node of the list. + * [Step 3]: If deleteAllGrp == true, then delete the node and + * move to the next node of the list. + * [Step 4]: If deleteAllGrp != true, then check if the node's group + * id is same as group id received then delete the node and mark the + * status found true else move to the next node of the list. + * [Step 5]: Once the traversing complete, + * if deleteAllGrp is true, then return successful rsp; + * else if status found is true, then return successful rsp; + * else return failure. + * @params[in] + * Inst + * Stats Grp List + * Subscription Id + * Group Id + * boolen of deleteAllGrp + * @return void + * + * ****************************************************************/ +uint8_t deleteFromStatsGrpList(Inst inst, CmLListCp *statsGrpList, uint64_t subscriptionId, uint8_t groupId, bool deleteAllGrp) +{ + bool statsFound=false; + SchStatsGrp *statsGrpInfo=NULLP; + CmLList *grpNode=NULLP; + + /* [Step 1] */ + CM_LLIST_FIRST_NODE(statsGrpList, grpNode); + while(grpNode) + { + statsGrpInfo = (SchStatsGrp*)grpNode->node; + + /* [Step 2] */ + if(statsGrpInfo->subscriptionId== subscriptionId) + { + if(deleteAllGrp == true) + { + /* [Step 3] */ + cmLListDelFrm(statsGrpList, grpNode); + deleteStatsGrpNode(inst, grpNode); + } + else + { + /* [Step 4] */ + if(statsGrpInfo->groupId== groupId) + { + cmLListDelFrm(statsGrpList, grpNode); + deleteStatsGrpNode(inst, grpNode); + statsFound = true; + } + } + } + CM_LLIST_FIRST_NODE(statsGrpList, grpNode); + } + + /* [Step 5] */ + if(deleteAllGrp == true) + { + return ROK; + } + else + { + if(statsFound == true) + return ROK; + } + return RFAILED; +} + +/******************************************************************* + * + * @brief Delete statistics information + * + * @details + * + * Function : deleteStatsInfo + * + * Functionality: + * Delete statistics information base on numStatsGroup + * Info- If numStatsGroup = 0' indicates the Deletion procedure triggered by + * 'SUBS_DELETION_REQ' wherein all the groups of this particular + * Subscription has to be removed + * else when numStatsGroup != 0 then this is + * for SUBS_MOD_REQ's actionToBeDeleted wherein particular action(s) has + * to be removed thus need to pass groupId belonging to that subscription + * which has to be deleted.' + * + * [Step-1] If numStatsGroup = 0, Deletion of all stats group belonging to + * received subscription Id. + * [Step-2] Else if numStatsGroup > 0, Deletion of individual stats group + * from list whose information are present in stats delete request. + * [Step-3] Fill the result of the stats deletion in the SCH stats delete + * response + * @params[in] + * Instance + * Subscription delete req + * Subscription delete rsp + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t deleteStatsInfo(Inst inst, SchStatsDeleteReq *statsDeleteReq, SchStatsDeleteRsp *schStatsDeleteRsp) +{ + uint8_t statsGrpIdx=0; + CmLListCp *statsGrpList =NULLP; + + statsGrpList = &schCb[inst].statistics.statsGrpList; + + if(!statsDeleteReq->numStatsGroupToBeDeleted) + { + /* [Step-1] */ + if(deleteFromStatsGrpList(inst,statsGrpList, statsDeleteReq->subscriptionId, 0, true) == ROK) + { + /* [Step 3]*/ + schStatsDeleteRsp->subsDelRsp = RSP_OK; + schStatsDeleteRsp->subsDelCause = SUCCESSFUL; + } + else + { + /* [Step-3]*/ + schStatsDeleteRsp->subsDelRsp = RSP_NOK; + schStatsDeleteRsp->subsDelCause = STATS_ID_NOT_FOUND; + } + } + else + { + for(statsGrpIdx=0; statsGrpIdxnumStatsGroupToBeDeleted; statsGrpIdx++) + { + /* [Step-2] */ + if(deleteFromStatsGrpList(inst, statsGrpList, statsDeleteReq->subscriptionId,\ + statsDeleteReq->statsGrpIdToBeDelList[statsGrpIdx], false) == ROK) + { + /* [Step-3]*/ + schStatsDeleteRsp->statsGrpDelInfo[statsGrpIdx].statsGrpDelRsp = RSP_OK; + schStatsDeleteRsp->statsGrpDelInfo[statsGrpIdx].statsGrpDelCause = SUCCESSFUL; + } + else + { + /* [Step-3]*/ + schStatsDeleteRsp->statsGrpDelInfo[statsGrpIdx].statsGrpDelRsp = RSP_NOK; + schStatsDeleteRsp->statsGrpDelInfo[statsGrpIdx].statsGrpDelCause = STATS_ID_NOT_FOUND; + } + } + schStatsDeleteRsp->numStatsGroupDeleted = statsDeleteReq->numStatsGroupToBeDeleted; + } + return ROK; +} + +/******************************************************************* + * + * @brief Processes Statistics Delete Request from MAC + * + * @details + * + * Function : SchProcStatsDeleteReq + * + * Functionality: + * This function process the statistics delete request from MAC: + * + * @params[in] Post structure + * Statistics Delete Request from MAC + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t SchProcStatsDeleteReq(Pst *pst, SchStatsDeleteReq *statsDeleteReq) +{ + Pst rspPst; + uint8_t ret =ROK; + SchStatsDeleteRsp *schStatsDeleteRsp; + Inst inst = pst->dstInst - SCH_INST_START; + + DU_LOG("\nINFO --> SCH : Received Statistics Delete Request from MAC"); + + if(statsDeleteReq == NULLP) + { + DU_LOG("\nERROR --> SCH : SchProcStatsDeleteReq(): Received Null pointer"); + return RFAILED; + } + + /* Process Stats delete request and fill stats delete response simultaneously */ + SCH_ALLOC(schStatsDeleteRsp, sizeof(SchStatsDeleteRsp)); + if(schStatsDeleteRsp == NULLP) + { + DU_LOG("\nERROR --> SCH : Failed to allocate memory in SchProcStatsDeleteReq()"); + return RFAILED; + } + schStatsDeleteRsp->subscriptionId=statsDeleteReq->subscriptionId; + deleteStatsInfo(inst, statsDeleteReq, schStatsDeleteRsp); + + memset(&rspPst, 0, sizeof(Pst)); + FILL_PST_SCH_TO_MAC(rspPst, inst); + rspPst.event = EVENT_STATISTICS_DELETE_RSP_TO_MAC; + + ret = MacMessageRouter(&rspPst, (void *)schStatsDeleteRsp); + if(ret == RFAILED) + { + DU_LOG("\nERROR --> SCH : SchProcStatsDeleteReq(): Failed to send Statistics Response"); + } + SCH_FREE(statsDeleteReq, sizeof(SchStatsDeleteReq)); + + return ret; +} /* End of SchProcStatsDeleteReq */ + +/******************************************************************* + * + * @brief Fill and send statistics modification response to MAC + * + * @details + * + * Function : SchSendStatsRspToMac + * + * Functionality: Fill and send statistics + * modification response to MAC + * + * @params[in] Inst inst, SchMacRsp result + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t SchSendStatsModificationRspToMac(SchStatsModificationRsp *tmpSchStatsModRsp) +{ + Pst rspPst; + uint8_t ret = ROK; + SchStatsModificationRsp *schStatsModificationRsp=NULLP; + + DU_LOG("\nINFO --> SCH : Filling statistics modification response"); + SCH_ALLOC(schStatsModificationRsp, sizeof(SchStatsModificationRsp)); + if(schStatsModificationRsp == NULLP) + { + DU_LOG("\nERROR --> SCH : Failed to allocate memory in SchSendStatsModificationRspToMac()"); + return RFAILED; + } + + memcpy(schStatsModificationRsp, tmpSchStatsModRsp, sizeof(SchStatsModificationRsp)); + memset(tmpSchStatsModRsp, 0, sizeof(SchStatsModificationRsp)); + + /* Filling response post */ + memset(&rspPst, 0, sizeof(Pst)); + FILL_PST_SCH_TO_MAC(rspPst, inst); + rspPst.event = EVENT_STATISTICS_MODIFY_RSP_TO_MAC; + + ret = MacMessageRouter(&rspPst, (void *)schStatsModificationRsp); + if(ret == RFAILED) + { + DU_LOG("\nERROR --> SCH : SchSendStatsModificationRspToMac(): Failed to send Statistics Modification Response"); + return ret; + } + return ret; +} + +/******************************************************************* + * + * @brief Rejects all statistics modification group requested by MAC + * + * @details + * + * Function : SchRejectAllStatsModification + * + * Functionality: Add all statistics modification group received in statistics + * request from MAC, to Reject-StatsModification-Group-List in statistics + * response to MAC + * + * @params[in] Statistics request from MAC + * Cause of rejection + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t SchRejectAllStatsModification(SchStatsModificationReq *statsModificationReq, CauseOfResult cause) +{ + uint8_t grpIdx = 0; + SchStatsModificationRsp statsModificationRsp; + + memset(&statsModificationRsp, 0, sizeof(SchStatsModificationRsp)); + + /* fill the subscriptionId and the rejected list in stats modification rsp */ + statsModificationRsp.subscriptionId = statsModificationReq->subscriptionId; + for(grpIdx = 0; grpIdx < statsModificationReq->numStatsGroup; grpIdx++) + { + statsModificationRsp.statsGrpRejectedList[grpIdx].groupId = statsModificationReq->statsGrpList[grpIdx].groupId; + statsModificationRsp.statsGrpRejectedList[grpIdx].cause = cause; + } + statsModificationRsp.numGrpRejected = statsModificationReq->numStatsGroup; + + return SchSendStatsModificationRspToMac(&statsModificationRsp); +} + +/**************************************************************************************** +* +* @brief Processes Statistics modification Request from MAC +* +* @details +* +* Function :SchProcStatsModificationReq +* +* Functionality: +* This function process the statistics modification request from MAC: +* [Step -1] Check the stored stats group list empty. +* [Step - 1.1] If empty Send the rejected group list to MAC as a stats +* modification response. +* [Step - 1.2] Else go to step 2. +* [Step -2] Traverse all stats group and validate each measurement types in +* each group. +* [Step -3] Check for any failure and if failed fill the remaining group's +* info in rejected list. +* [Step -4] Else Check if the received subscriptionId and groupId match the +* values with the database node. +* [Step -4.1] If matches then follow the below mentioned steps. +* [Step -4.1.1] Stop the timer. +* [Step -4.1.2] Reconfigure stats group by adding a new entry for this +* statsGroup with updated configuration in database. +* [Step -4.1.3] if configured successfully, store stats info into +* stats mod rsp's accepted list, restart timer and go to step 4.1.4 +* [Step -4.1.4] Delete the old entry of this stats group.. +* [Step -4.2] Else fill the group related info in stats modification rsp's +* rejected list. +* [Step -5] Send the stats modification rsp to MAC +* @params[in] Post structure +* Statistics modification Request from MAC +* @return ROK - success +* RFAILED - failure +* +* *******************************************************************************************/ +uint8_t SchProcStatsModificationReq(Pst *pst, SchStatsModificationReq *statsModificationReq) +{ + Inst inst; + uint8_t reqGrpIdx=0; + uint64_t subscriptionId =0; + bool allocFailed = false; + bool statsGrpFound= false; + CmLList *grpNode = NULLP; + SchStatsGrp *statsGrpInfo=NULLP; + SchStatsGrpInfo statsGrpToModify; + SchStatsModificationRsp statsModificationRsp; + + inst=pst->dstInst - SCH_INST_START; + + DU_LOG("\nINFO --> SCH : Received Statistics modification request from MAC"); + + if(statsModificationReq == NULLP) + { + DU_LOG("\nERROR --> SCH : SchProcStatsModificationReq(): Received Null pointer"); + return RFAILED; + } + memset(&statsModificationRsp, 0, sizeof(SchStatsRsp)); + + /* [Step -1] */ + if(schCb[inst].statistics.statsGrpList.count) + { + /* [Step -1.2] */ + subscriptionId = statsModificationReq->subscriptionId; + + /* [Step - 2] */ + for(reqGrpIdx=0; reqGrpIdxnumStatsGroup; reqGrpIdx++) + { + /* [Step - 3] */ + statsGrpToModify = statsModificationReq->statsGrpList[reqGrpIdx]; + if(allocFailed != true) + { + CM_LLIST_FIRST_NODE(&schCb[inst].statistics.statsGrpList, grpNode); + while(grpNode) + { + /* [Step - 4] */ + statsGrpInfo = (SchStatsGrp*)grpNode->node; + if((statsGrpInfo->subscriptionId== subscriptionId) && (statsGrpInfo->groupId== statsGrpToModify.groupId)) + { + statsGrpFound= true; + break; + } + grpNode = grpNode->next; + } + + /* [Step - 4.1] */ + if(statsGrpFound== true) + { + /* [Step - 4.1.1] */ + if(schChkTmr((PTR)statsGrpInfo, EVENT_STATISTICS_TMR) == true) + { + schStopTmr(&schCb[inst], (PTR)statsGrpInfo, EVENT_STATISTICS_TMR); + } + + /* [Step - 4.1.2] */ + if(schAddToStatsGrpList(inst, &statsModificationRsp, subscriptionId, &statsGrpToModify) != ROK) + { + DU_LOG("\nERROR --> SCH : SchProcStatsReq(): Failed to fill the stats group list"); + if(statsModificationRsp.statsGrpRejectedList[statsModificationRsp.numGrpRejected-1].groupId == statsGrpToModify.groupId) + { + /* [Step - 4.1.3] */ + schStartTmr(&schCb[inst], (PTR)(statsGrpInfo), EVENT_STATISTICS_TMR, statsGrpInfo->periodicity); + if(statsModificationRsp.statsGrpRejectedList[statsModificationRsp.numGrpRejected-1].cause == RESOURCE_UNAVAILABLE) + { + allocFailed = true; + break; + } + } + } + else + { + /* [Step - 4.1.4] */ + deleteStatsGrpNode(inst, grpNode); + } + } + else + { + /* [Step - 4.2] */ + statsModificationRsp.statsGrpRejectedList[statsModificationRsp.numGrpRejected].groupId = statsGrpToModify.groupId; + statsModificationRsp.statsGrpRejectedList[statsModificationRsp.numGrpRejected].cause = STATS_ID_NOT_FOUND; + statsModificationRsp.numGrpRejected++; + } + } + else + { + statsModificationRsp.statsGrpRejectedList[statsModificationRsp.numGrpRejected].groupId = statsGrpToModify.groupId; + statsModificationRsp.statsGrpRejectedList[statsModificationRsp.numGrpRejected].cause = RESOURCE_UNAVAILABLE; + statsModificationRsp.numGrpRejected++; + } + } + + statsModificationRsp.subscriptionId = statsModificationReq->subscriptionId; + SchSendStatsModificationRspToMac(&statsModificationRsp); + } + else + { + /* [Step -1.1] */ + SchRejectAllStatsModification(statsModificationReq, STATS_ID_NOT_FOUND); + } + SCH_FREE(statsModificationReq, sizeof(SchStatsModificationReq)); + return ROK; +} /********************************************************************** End of file **********************************************************************/