X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Fdu_app%2Fdu_e2ap_mgr.c;h=eabc0d6b2972908be725bdafa21b9eec01165eb8;hb=c371a26d48604a5d60686d9ca347e68671e69637;hp=7c834cd0aab9684a08c9ec8cf5167f93af162016;hpb=cdf2274ce07f8a5e066f1a49e92db156f1a92c66;p=o-du%2Fl2.git diff --git a/src/du_app/du_e2ap_mgr.c b/src/du_app/du_e2ap_mgr.c index 7c834cd0a..eabc0d6b2 100644 --- a/src/du_app/du_e2ap_mgr.c +++ b/src/du_app/du_e2ap_mgr.c @@ -16,14 +16,16 @@ ################################################################################ *******************************************************************************/ #include "common_def.h" +#include #include "du_tmr.h" #include "lrg.h" #include "lkw.x" #include "lrg.x" #include "legtp.h" -#include "du_e2ap_mgr.h" #include "du_app_mac_inf.h" #include "du_app_rlc_inf.h" +#include "du_e2ap_mgr.h" +#include "du_e2_conversions.h" #include "du_e2ap_msg_hdl.h" #include "du_cfg.h" #include "du_sctp.h" @@ -60,6 +62,294 @@ uint8_t assignTransactionId() return currTransId; } +/******************************************************************* + * + * @brief Decode subscription ID + * + * @details + * + * Function : decodeSubscriptionId + * + * Functionality: Decode subscription id to get RAN function ID + * and RIC Request ID + * + * @params[in] Subscription ID + * RAN Function ID to be extracted + * RIC Request ID to be extracted + * @return Void + * + * ****************************************************************/ +void decodeSubscriptionId(uint64_t subscriptionId, uint16_t *ranFuncId, RicRequestId *ricReqId) +{ + /* Extract following from 64 bit subscription-ID : + * First 16 MSB is unused + * Next 16 MSB = RAN-Function-ID + * Next 16 MSB = Requestor-ID in RIC-Request-ID + * Last 16 LSB = Instance-ID in RIC-Request-ID + */ + ricReqId->instanceId = subscriptionId & 0xFFFF; + ricReqId->requestorId = (subscriptionId >> 16) & 0xFFFF; + *ranFuncId = (subscriptionId >> 32) & 0xFFFF; +} + +/******************************************************************* + * + * @brief Encode subscription ID + * + * @details + * + * Function : encodeSubscriptionId + * + * Functionality: Encode subscription id to get RAN function ID + * and RIC Request ID + * + * @params[in] Subscription ID to be encoded + * RAN Function ID + * RIC Request ID + * @return Void + * + * ****************************************************************/ +void encodeSubscriptionId(uint64_t *subscriptionId, uint16_t ranFuncId, RicRequestId ricReqId) +{ + /* Calculate 64 bit subscription-ID : + * First 16 MSB is unused + * Next 16 MSB = RAN-Function-ID + * Next 16 MSB = Requestor-ID in RIC-Request-ID + * Last 16 LSB = Instance-ID in RIC-Request-ID + */ + *subscriptionId = ricReqId.instanceId; + *subscriptionId |= ((uint64_t)ricReqId.requestorId << 16); + *subscriptionId |= ((uint64_t)ranFuncId << 32); +} + +/******************************************************************* + * + * @brief Stores the current time at the start of reporting period + * + * @details + * + * Function : storeReportStartTime + * + * Functionality: Stores the current time at the start of + * reporting period + * + * @params[in] Start Timer to be stored + * @return Void + * + * ****************************************************************/ +void storeReportStartTime(ReportStartTime *startTime) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + startTime->timeInSec = tv.tv_sec; + startTime->timeInMilliSec = (tv.tv_usec/1000); +} + + +/******************************************************************* + * + * @brief Fetch Measurement Info using measurement type name + * + * @details + * + * Function : fetchMeasInfoFromMeasTypeName + * + * Functionality: Fetch Measurement Info using measurement type name + * + * @params[in] Measurement type name to search + * Measurement Info list to search from + * Measurement Info node found from list + * @return Measurement Info DB + * + * ****************************************************************/ +MeasurementInfo *fetchMeasInfoFromMeasTypeName(char *e2MeasTypeName, CmLListCp *measInfoList, CmLList **measInfoNode) +{ + MeasurementInfo *measInfo = NULLP; + + /* Fetch subscription detail in RAN Function DB */ + CM_LLIST_FIRST_NODE(measInfoList, *measInfoNode); + while(*measInfoNode) + { + measInfo = (MeasurementInfo *)((*measInfoNode)->node); + if(measInfo && !strcmp(e2MeasTypeName, measInfo->measurementTypeName)) + { + break; + } + *measInfoNode = (*measInfoNode)->next; + measInfo = NULLP; + } + + if(!measInfo) + { + DU_LOG("\nERROR --> E2AP : fetchMeasInfoFromMeasTypeName: Measurement [%s] not found", e2MeasTypeName); + } + + return measInfo; +} + +/******************************************************************* + * + * @brief Fetch Action details + * + * @details + * + * Function : fetchActionInfoFromActionId + * + * Functionality: Fetch action details from RIC subscription DB + * using action ID + * + * @params[in] Action ID + * RIC Subscription DB + * @return Action Info DB + * NULL, in case of failure + * + * ****************************************************************/ +ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo) +{ + ActionInfo *actionInfoDb = NULLP; + if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId) + { + actionInfoDb = &ricSubscriptionInfo->actionSequence[actionId]; + } + else + { + DU_LOG("\nERROR --> E2AP : fetchActionInfoFromActionId: Action Id [%d] not found in \ + subscription info [Requestor id : %d] [Instance Id : %d]", actionId,\ + ricSubscriptionInfo->requestId.requestorId, ricSubscriptionInfo->requestId.instanceId); + + } + return actionInfoDb; +} + +/******************************************************************* + * + * @brief Fetch subscripton DB + * + * @details + * + * Function : fetchSubsInfoFromRicReqId + * + * Functionality: Fetches subscription DB from RAN Function DB + * using RIC Request ID + * + * @params[in] RIC Request ID + * RAN Function DB + * Pointer to RIC Subscription node to be searched + * @return RIC Subscription from RAN Function's subcription list + * NULL, in case of failure + * + * ****************************************************************/ +RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb, CmLList **ricSubscriptionNode) +{ + RicSubscription *ricSubscriptionInfo = NULLP; + + /* Fetch subscription detail in RAN Function DB */ + CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, *ricSubscriptionNode); + while(*ricSubscriptionNode) + { + ricSubscriptionInfo = (RicSubscription *)((*ricSubscriptionNode)->node); + if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) && + (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId)) + { + break; + } + *ricSubscriptionNode = (*ricSubscriptionNode)->next; + ricSubscriptionInfo = NULLP; + } + + if(!ricSubscriptionInfo) + { + DU_LOG("\nERROR --> E2AP : fetchSubsInfoFromRicReqId: Subscription not found for Requestor ID [%d] \ + Instance ID [%d] in RAN Function ID [%d]", ricReqId.requestorId, ricReqId.instanceId, ranFuncDb->id); + } + + return ricSubscriptionInfo; +} + +/******************************************************************* + * + * @brief Fetches RAN Function DB + * + * @details + * + * Function : fetchRanFuncFromRanFuncId + * + * Functionality: Fetches RAN function DB from E2AP DB using + * RAN function ID + * + * @params[in] RAN Function ID + * @return RAN Function DB + * NULL, in case of failure + * + * ****************************************************************/ +RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId) +{ + RanFunction *ranFuncDb = NULLP; + + /* Fetch RAN Function DB */ + if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId) + { + ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1]; + } + else + { + DU_LOG("\nERROR --> E2AP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId); + } + + return ranFuncDb; +} + +/******************************************************************* + * + * @brief Fetches subscription info + * + * @details + * + * Function : fetchSubsInfoFromSubsId + * + * Functionality: + * 1. Firstly, RAN Function ID and RIC request ID is extracted + * from Subscription ID + * 2. Using RAN Function ID, RAN Function DB is searched + * 3. Using RIC Request ID, the subscription DB is searched in + * RAN Function DB + * + * @params[in] Subscription ID + * RAN Function DB + * RIC Subscription node from RAN Func's Subscription list + * @return ROK + * RFAILED + * + * ****************************************************************/ +uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \ + RicSubscription **ricSubscriptionInfo) +{ + uint16_t ranFuncId = 0; + RicRequestId ricReqId; + + memset(&ricReqId, 0, sizeof(RicRequestId)); + + /* Decode subscription ID o get RIC Request ID and RAN Function ID */ + decodeSubscriptionId(subscriptionId, &ranFuncId, &ricReqId); + + /* Fetch RAN Function DB using RAN Function ID */ + *ranFuncDb = fetchRanFuncFromRanFuncId(ranFuncId); + if((*ranFuncDb) == NULLP) + { + return RFAILED; + } + + /* Fetch Sunscription DB from RAN Function using RIC Request ID */ + *ricSubscriptionInfo = fetchSubsInfoFromRicReqId(ricReqId, *ranFuncDb, ricSubscriptionNode); + if((*ricSubscriptionInfo) == NULLP) + { + return RFAILED; + } + + return ROK; +} + /******************************************************************* * * @brief Sends E2 msg over SCTP @@ -135,12 +425,12 @@ uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize) * RFAILED - failure * * ****************************************************************/ -uint8_t ResetE2Request(E2ProcedureDirection dir, E2CauseType type, E2Cause cause) +uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause) { /* Send Reset Request to RIC if DU detects any abnormal failure */ if(dir == E2_NODE_INITIATED) { - if(BuildAndSendE2ResetRequest(type, cause) != ROK) + if(BuildAndSendE2ResetRequest(resetCause) != ROK) { DU_LOG("\nERROR --> E2AP : BuildAndSendE2ResetRequest failed"); return RFAILED; @@ -161,6 +451,1086 @@ uint8_t ResetE2Request(E2ProcedureDirection dir, E2CauseType type, E2Cause cause return ROK; } +/******************************************************************* + * + * @brief Fill RIC Subscription datils in MAC Statistics Request + * + * @details + * + * Function : fillRicSubsInMacStatsReq + * + * Functionality: Fill RIC Subscription datils in MAC Statistics + * Request + * + * @params[in] MAC Statistics Request to be filled + * RIC Subscription Info + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo) +{ + uint8_t actionIdx = 0, grpIdx = 0, statsIdx = 0; + uint64_t subscriptionId = 0; + ActionInfo *actionDb = NULLP; + ActionDefFormat1 *format1Action = NULLP; + + /* Generate subscription ID using RIC Request ID and RAN Function ID */ + encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId); + + macStatsReq->subscriptionId = subscriptionId; + for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++) + { + if(ricSubscriptionInfo->actionSequence[actionIdx].action == CONFIG_ADD) + { + actionDb = &ricSubscriptionInfo->actionSequence[actionIdx]; + macStatsReq->statsGrpList[grpIdx].groupId = actionDb->actionId; + switch(actionDb->definition.formatType) + { + case 1: + { + format1Action = &actionDb->definition.choice.format1; + macStatsReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod; + + CmLList *node = NULLP; + MeasurementInfo *measInfo = NULLP; + statsIdx = 0; + /* Update DL PRB Usage for all stats group which requested for DL Total PRB Usage */ + node = cmLListFirst(&format1Action->measurementInfoList); + while(node) + { + measInfo = (MeasurementInfo *)(node->node); + switch(measInfo->measurementTypeId) + { + case 1: + { + macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_DL_TOTAL_PRB_USAGE; + break; + } + case 2: + { + macStatsReq->statsGrpList[grpIdx].statsList[statsIdx++] = MAC_UL_TOTAL_PRB_USAGE; + break; + } + default: + { + DU_LOG("\nERROR --> E2AP : Invalid measurement name"); + break; + } + } + node = node->next; + } + macStatsReq->statsGrpList[grpIdx].numStats = statsIdx; + break; + } + default: + { + DU_LOG("\nERROR --> E2AP : fillRicSubsInMacStatsReq: Only Action Definition Format 1 supported"); + break; + } + } + if(macStatsReq->statsGrpList[grpIdx].numStats) + grpIdx++; + } + } + + macStatsReq->numStatsGroup = grpIdx; + if(macStatsReq->numStatsGroup) + { + return ROK; + } + return RFAILED; +} + +/******************************************************************* + * + * @brief Rejects all actions received in a subscription request + * + * @details + * + * Function : duRejectAllStatsGroup + * + * Functionality: Rejects all actions received in a subscription + * request by : + * a. Removing the subscription entry from RAN function + * b. Sending RIC Subscription Failure to RIC with appropriate + * cause of failure + * + * @params[in] RAN Function DB + * Subscription entry in RAN Function subscription list + * Statistics Response from MAC + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t rejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, MacStatsRsp *statsRsp) +{ + uint8_t ret = ROK; + RicRequestId requestId; + E2FailureCause failureCause; + + /* Delete subcription from RAN Function */ + memcpy(&requestId, &((RicSubscription *)ricSubscriptionNode->node)->requestId, sizeof(RicRequestId)); + cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubscriptionNode); + deleteRicSubscriptionNode(ricSubscriptionNode); + ricSubscriptionNode = NULLP; + convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[0].cause, &failureCause); + + /* Send RIC subscription failure to RIC */ + ret = BuildAndSendRicSubscriptionFailure(requestId, ranFuncDb->id, failureCause); + return ret; +} + +/******************************************************************* + * + * @brief Process statistics response from MAC + * + * @details + * + * Function : e2ProcStatsRsp + * + * Functionality: Processes statistics configuration response + * from MAC. If configuration is succsessful, DUAPP starts + * reporting period timer for this subscription request + * from RIC + * + * @params[in] Statistics response received from MAC + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp) +{ + uint8_t idx = 0; + uint8_t actionId = 0; + uint32_t reportingPeriod = 0; + RanFunction *ranFuncDb = NULLP; + CmLList *ricSubscriptionNode = NULLP; + RicSubscription *ricSubscriptionInfo = NULLP; + ActionInfo *actionInfoDb = NULLP; + PendingSubsRspInfo *pendingSubsRsp = NULLP; + + /* Fetch RAN Function and Subscription DB using subscription Id received in statistics response */ + if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK) + { + DU_LOG("\nERROR --> E2AP : DuProcMacStatsRsp: Failed to fetch subscriprtion details"); + return RFAILED; + } + + /* Fetch pre-stored statistics response info by DU APP */ + for(idx=0; idxnumPendingSubsRsp; idx++) + { + if((ranFuncDb->pendingSubsRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) && + (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId)) + { + pendingSubsRsp = &ranFuncDb->pendingSubsRspInfo[idx]; + break; + } + } + + /* If no action is accepted + * a. Remove subcription entry from RAN Function + * b. Send RIC subscription failure */ + if(statsRsp->numGrpAccepted == 0) + { + rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp); + } + else + { + /* Once RIC subscription is successful, mark the config action as unknown */ + ricSubscriptionInfo->action = CONFIG_UNKNOWN; + + /* Start RIC Subscription reporting timer */ + switch(ricSubscriptionInfo->eventTriggerDefinition.formatType) + { + case 1: + { + reportingPeriod = ricSubscriptionInfo->eventTriggerDefinition.choice.format1.reportingPeriod; + + /* Save the start time of reporting period */ + storeReportStartTime(&ricSubscriptionInfo->eventTriggerDefinition.choice.format1.startTime); + break; + } + default: + { + DU_LOG("\nERROR --> E2AP : Invalid event trigger format of RIC subscription"); + return RFAILED; + } + } + if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true) + { + duStartTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod); + } + else + { + DU_LOG("\nERROR --> E2AP : RIC Subscription reporting timer already running for RIC Subscription"); + return RFAILED; + } + + + /* If even 1 action is accepted : + * + * For accepted groups: + * Mark subscribed-action's -> action = CONFIG_UNKNOWN + * Add to accepted-action-list of subscription response + */ + for(idx=0; idxnumGrpAccepted; idx++) + { + actionInfoDb = NULLP; + + actionId = statsRsp->statsGrpAcceptedList[idx]; + actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo); + if(actionInfoDb && (actionInfoDb->action == CONFIG_ADD)) + { + actionInfoDb->action = CONFIG_UNKNOWN; + pendingSubsRsp->acceptedActionList[pendingSubsRsp->numOfAcceptedActions++] = actionId; + } + } + + /* For rejected groups: + * Remove entry from DU's RAN Function->subscription->actionList + * Add to rejected-action-list in subscription response + */ + for(idx=0; idxnumGrpRejected; idx++) + { + actionId = statsRsp->statsGrpRejectedList[idx].groupId; + if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId) + { + memset(&ricSubscriptionInfo->actionSequence[actionId], 0, sizeof(ActionInfo)); + ricSubscriptionInfo->numOfActions--; + + pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId; + convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \ + &pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].failureCause); + pendingSubsRsp->numOfRejectedActions++; + } + } + + /* Send subscription response with accepted and rejected action lists to RIC */ + BuildAndSendRicSubscriptionRsp(pendingSubsRsp); + } + memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo)); + return ROK; +} + +/******************************************************************* + * + * @brief Extract and store statistics received from DU layers + * + * @details + * + * Function : e2ProcStatsInd + * + * Functionality: Extract statistics received from DU layers + * and store in respective RAN function's subscription's + * action + * + * @params[in] Statistics Indication message received from MAC + * @return ROK-success + * RFAILED-failure + * + * ****************************************************************/ +uint8_t e2ProcStatsInd(MacStatsInd *statsInd) +{ + uint8_t statsIdx = 0; + RanFunction *ranFuncDb = NULLP; + CmLList *ricSubscriptionNode = NULLP; + RicSubscription *ricSubscriptionInfo = NULLP; + ActionInfo *actionInfo = NULLP; + ActionDefFormat1 *actionFormat = NULLP; + char e2MeasTypeName[STRING_SIZE_150_BYTES] = ""; + MeasurementInfo *measInfo = NULLP; + CmLList *measInfoNode = NULLP; + double *measValue = NULLP; + CmLList *measValueNode = NULLP; + + /* TODO : When stats indication is received + * DU APP searches for the message type in E2AP RIC subscription + * database and stores in the value in the list of subscribed measurements + * + * This will be implemented in next gerrit. + */ + + /* Fetch RAN Function and Subscription DB using subscription Id received + * in statistics response */ + if(fetchSubsInfoFromSubsId(statsInd->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK) + { + DU_LOG("\nERROR --> E2AP : extractStatsMeasurement: Failed to fetch subscriprtion details"); + return RFAILED; + } + + /* Fetch RIC subscription's action DB */ + actionInfo = fetchActionInfoFromActionId(statsInd->groupId, ricSubscriptionInfo); + if(actionInfo == NULLP) + { + DU_LOG("\nERROR --> E2AP : extractStatsMeasurement: Failed to fetch action ID [%d]", statsInd->groupId); + return RFAILED; + } + + /* Check Action format */ + switch(actionInfo->definition.formatType) + { + case 1: + { + actionFormat = &actionInfo->definition.choice.format1; + break; + } + default: + { + DU_LOG("\nERROR --> E2AP : extractStatsMeasurement: Action Format [%d] is not supported", \ + actionInfo->definition.formatType); + return RFAILED; + } + } + + /* Fetch each Measurement info from action info and store its reported value in DB */ + for(statsIdx = 0; statsIdx < statsInd->numStats; statsIdx++) + { + memset(e2MeasTypeName, 0, STRING_SIZE_150_BYTES); + measInfo = NULLP; + measInfoNode = NULLP; + + /* Convert Measurement type from MAC-supported format to E2-supported format */ + if(convertMacMeasTypeToE2MeasType(statsInd->measuredStatsList[statsIdx].type, e2MeasTypeName) != ROK) + { + DU_LOG("\nERROR --> E2AP : extractStatsMeasurement: Failed to convert measurement type from MAC-supported\ + MAC-supported format to E2-supported format"); + continue; + } + + /* Fetch Measurement Info using E2-supported measurement type name */ + measInfo = fetchMeasInfoFromMeasTypeName(e2MeasTypeName, &actionFormat->measurementInfoList, &measInfoNode); + if(measInfo == NULLP) + { + DU_LOG("\nERROR --> E2AP : extractStatsMeasurement: Measurement Type Name [%s] not found", e2MeasTypeName); + continue; + } + + /* Store the measurement value in the measurement info DB fetched */ + DU_ALLOC(measValue, sizeof(double)); + if(!measValue) + { + DU_LOG("\nERROR --> E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__); + return RFAILED; + } + *measValue = statsInd->measuredStatsList[statsIdx].value; + + DU_ALLOC(measValueNode, sizeof(CmLList)); + if(!measValueNode) + { + DU_LOG("\nERROR --> E2AP : extractStatsMeasurement: Memory allocation failed at line [%d]", __LINE__); + DU_FREE(measValue, sizeof(double)); + return RFAILED; + } + measValueNode->node = (PTR) measValue; + cmLListAdd2Tail(&measInfo->measuredValue, measValueNode); + } + return ROK; +} + +/******************************************************************* + * + * @brief Handle RIC Subscription reporting timer expry + * + * @details + * + * Function : E2apHdlRicSubsReportTmrExp + * + * Functionality: On expiry of RIC subscription reporting + * timer expiry, RIC indication is sent for all actions + * in RIC subscription + * + * @params[in] RIC subscription DB + * @return void + * + * ****************************************************************/ +void E2apHdlRicSubsReportTmrExp(RicSubscription *ricSubscription) +{ + uint8_t actionIdx = 0; + uint32_t reportingPeriod = 0; + + for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++) + { + if(ricSubscription->actionSequence[actionIdx].actionId >= 0) + { + BuildAndSendRicIndication(ricSubscription, &ricSubscription->actionSequence[actionIdx]); + } + } + + /* Start RIC Subscription reporting timer again */ + switch(ricSubscription->eventTriggerDefinition.formatType) + { + case 1: + { + reportingPeriod = ricSubscription->eventTriggerDefinition.choice.format1.reportingPeriod; + /* Save the start time of reporting period */ + storeReportStartTime(&ricSubscription->eventTriggerDefinition.choice.format1.startTime); + break; + } + default: + return; + } + if(duChkTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) != true) + { + duStartTmr((PTR)ricSubscription, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR, reportingPeriod); + } + else + { + DU_LOG("\nERROR --> E2AP : Failed in %s at line %d", __func__, __LINE__); + return; + } +} + +/****************************************************************** + * + * @brief Search E2 node component with the help of action type + * + * @details + * + * Function : fetchE2NodeComponentInfo + * + * Functionality: Search E2 node component with the help of action type + * + * @params[in] + * Type of interface + * Component Id + * Pointer to E2 component node to be searched + * @return CmLList + * + * ****************************************************************/ + +E2NodeComponent *fetchE2NodeComponentInfo(InterfaceType interfaceType, uint64_t componentId, CmLList **e2ComponentNode) +{ + E2NodeComponent *e2NodeComponentInfo=NULLP; + + if(duCb.e2apDb.e2NodeComponentList.count) + { + CM_LLIST_FIRST_NODE(&duCb.e2apDb.e2NodeComponentList, *e2ComponentNode); + while(*e2ComponentNode) + { + e2NodeComponentInfo = (E2NodeComponent*)((*e2ComponentNode)->node); + if((e2NodeComponentInfo->interfaceType == interfaceType) && (e2NodeComponentInfo->componentId == componentId)) + { + break; + } + + *e2ComponentNode = (*e2ComponentNode)->next; + e2NodeComponentInfo = NULLP; + } + } + return e2NodeComponentInfo; +} + +/******************************************************************* + * + * @brief fill E2 node component rsp info + * + * @details + * + * Function : fillE2NodeComponentRspInfo + * + * Functionality: fill E2 Node Component rsp info + * + * @parameter + * Type of interface + * Component action type + * Size of buffer which needs to be store + * buffer string which needs to be store + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ + +uint8_t fillE2NodeComponentRspInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString) +{ + E2NodeConfig *configInfo=NULLP; + E2NodeComponent *e2NodeComponentInfo= NULLP; + CmLList *node = NULLP; + + e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node); + if(!e2NodeComponentInfo) + { + DU_LOG("\nERROR --> E2AP : Unable to find the node"); + return RFAILED; + } + + switch(action) + { + case E2_NODE_COMPONENT_ADD: + { + configInfo = e2NodeComponentInfo->addConfiguration; + break; + } + case E2_NODE_COMPONENT_UPDATE: + { + configInfo = e2NodeComponentInfo->updateConfiguration; + break; + } + default: + { + DU_LOG("\nERROR --> E2AP : Invalid action %d received",action); + return RFAILED; + } + } + + if(configInfo->componentRequestPart== NULLP) + { + DU_LOG("\nERROR --> E2AP : E2 node Component request part is not present"); + return RFAILED; + } + + configInfo->rspBufSize = bufSize; + DU_ALLOC(configInfo->componentResponsePart, bufSize); + if(configInfo->componentResponsePart == NULLP) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed to store the encoding of rsp"); + return RFAILED; + } + memcpy(configInfo->componentResponsePart, bufString, configInfo->rspBufSize); + return ROK; +} + +/******************************************************************* + * + * @brief add E2 node component req info + * + * @details + * + * Function : addE2NodeComponent + * + * Functionality: add E2 node component req info + * + * @parameter + * Type of interface + * Component action type + * Size of buffer which needs to be store + * buffer string which needs to be store + * @return ROK - success + * RFAILED - failure + * + ******************************************************************/ + +uint8_t addE2NodeComponent(InterfaceType interfaceType, uint64_t componentId, uint8_t bufSize, char *bufString) +{ + E2NodeComponent *e2NodeComponentInfo= NULLP; + CmLList *node = NULLP; + + DU_ALLOC(e2NodeComponentInfo, sizeof(E2NodeComponent)); + if(!e2NodeComponentInfo) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at %d",__func__,__LINE__); + return RFAILED; + } + e2NodeComponentInfo->interfaceType =interfaceType; + e2NodeComponentInfo->componentId=componentId; + + DU_ALLOC(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig)); + if(!e2NodeComponentInfo->addConfiguration) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at %d",__func__,__LINE__); + return RFAILED; + } + + e2NodeComponentInfo->addConfiguration->reqBufSize = bufSize; + + DU_ALLOC(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize); + if(e2NodeComponentInfo->addConfiguration->componentRequestPart == NULLP) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at %d",__func__,__LINE__); + DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent)); + return RFAILED; + } + memcpy(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufString,\ + e2NodeComponentInfo->addConfiguration->reqBufSize); + + DU_ALLOC(node, sizeof(CmLList)); + if(node) + { + node->node = (PTR) e2NodeComponentInfo; + cmLListAdd2Tail(&duCb.e2apDb.e2NodeComponentList, node); + } + else + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at %d",__func__,__LINE__); + DU_FREE(e2NodeComponentInfo->addConfiguration->componentRequestPart, bufSize); + DU_FREE(e2NodeComponentInfo->addConfiguration, sizeof(E2NodeConfig)); + DU_FREE(e2NodeComponentInfo, sizeof(E2NodeComponent)); + return RFAILED; + } + return ROK; +} + +/******************************************************************* + * + * @brief update E2 node component req info + * + * @details + * + * Function : updateE2NodeComponent + * + * Functionality: update E2 node component req info + * + * @parameter + * Type of interface + * Size of buffer which needs to be store + * buffer string which needs to be store + * @return ROK - success + * RFAILED - failure + * + ******************************************************************/ + +uint8_t updateE2NodeComponent(InterfaceType interfaceType, uint64_t componentId, uint8_t bufSize, char *bufString) +{ + E2NodeComponent *e2NodeComponentInfo= NULLP; + CmLList *node = NULLP; + + e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node); + if(!e2NodeComponentInfo) + { + DU_LOG("\nERROR --> E2AP : Received null information in %s",__func__); + return RFAILED; + } + + DU_ALLOC(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig)); + if(!e2NodeComponentInfo->updateConfiguration) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at %d",__func__,__LINE__); + return RFAILED; + } + + e2NodeComponentInfo->updateConfiguration->reqBufSize = bufSize; + + DU_ALLOC(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufSize); + if(e2NodeComponentInfo->updateConfiguration->componentRequestPart == NULLP) + { + DU_LOG("\nERROR --> E2AP : Memory allocation failed in %s at %d",__func__,__LINE__); + DU_FREE(e2NodeComponentInfo->updateConfiguration, sizeof(E2NodeConfig)); + return RFAILED; + } + + memcpy(e2NodeComponentInfo->updateConfiguration->componentRequestPart, bufString,\ + e2NodeComponentInfo->updateConfiguration->reqBufSize); + return ROK; + +} + +/******************************************************************* + * + * @brief delete E2 node component req info + * + * @details + * + * Function : deleteE2NodeComponent + * + * Functionality: delete E2 node component req info + * + * @parameter + * Type of interface + * @return ROK - success + * RFAILED - failure + * + ******************************************************************/ + +uint8_t deleteE2NodeComponent(InterfaceType interfaceType, uint64_t componentId) +{ + E2NodeComponent *e2NodeComponentInfo= NULLP; + CmLList *node = NULLP; + + e2NodeComponentInfo = fetchE2NodeComponentInfo(interfaceType, componentId, &node); + if(!e2NodeComponentInfo) + { + DU_LOG("\nERROR --> E2AP : Received null information in %s",__func__); + return RFAILED; + } + + e2NodeComponentInfo->deleteConfiguration = true; + return ROK; +} + +/******************************************************************* + * + * @brief fill E2 node component req info + * + * @details + * + * Function : fillE2NodeComponentReqInfo + * + * Functionality: fill E2 node component req info + * + * @parameter + * Type of interface + * Component action type + * Size of buffer which needs to be store + * buffer string which needs to be store + * @return ROK - success + * RFAILED - failure + * + ******************************************************************/ + +uint8_t fillE2NodeComponentReqInfo(InterfaceType interfaceType, uint64_t componentId, uint8_t action, uint8_t bufSize, char *bufString) +{ + switch(action) + { + case E2_NODE_COMPONENT_ADD: + { + if(addE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK) + { + DU_LOG("\nERROR --> E2AP : Failed to add e2 node component"); + return RFAILED; + } + break; + } + case E2_NODE_COMPONENT_UPDATE: + { + if(updateE2NodeComponent(interfaceType, componentId, bufSize, bufString) != ROK) + { + DU_LOG("\nERROR --> E2AP : Failed to update e2 node component"); + return RFAILED; + } + break; + } + case E2_NODE_COMPONENT_DEL: + { + if(deleteE2NodeComponent(interfaceType, componentId) != ROK) + { + DU_LOG("\nERROR --> E2AP : Failed to delete e2 node component"); + return RFAILED; + } + break; + } + default: + { + DU_LOG("\nERROR --> E2AP : Invalid action %d received",action); + return RFAILED; + } + } + + return ROK; +} + +/****************************************************************** + * + * @brief Delete measured Value list + * + * @details + * + * Function : deleteMeasuredValueList + * + * Functionality: Delete measured Value list + * + * @params[in] List of measured Value + * + * @return void + * + * ****************************************************************/ +void deleteMeasuredValueList(CmLListCp *measuredValueList) +{ + CmLList *measValNode = NULLP; + + CM_LLIST_FIRST_NODE(measuredValueList, measValNode); + + while(measValNode) + { + cmLListDelFrm(measuredValueList, measValNode); + DU_FREE(measValNode->node, sizeof(double)); + DU_FREE(measValNode, sizeof(CmLList)); + CM_LLIST_FIRST_NODE(measuredValueList, measValNode); + } +} + +/****************************************************************** + * + * @brief Delete Measurement Info List + * + * @details + * + * Function : deleteMeasurementInfoList + * + * Functionality: Delete Measurement Info List + * + * @params[in] List of Measurement Info List + * + * @return void + * + * ****************************************************************/ +void deleteMeasurementInfoList(CmLListCp *measInfoList) +{ + CmLList *measInfoNode = NULLP; + MeasurementInfo *measInfo = NULLP; + + CM_LLIST_FIRST_NODE(measInfoList, measInfoNode); + while(measInfoNode) + { + measInfo = (MeasurementInfo *)measInfoNode->node; + cmLListDelFrm(measInfoList, measInfoNode); + deleteMeasuredValueList(&measInfo->measuredValue); + DU_FREE(measInfo, sizeof(MeasurementInfo)); + DU_FREE(measInfoNode, sizeof(CmLList)); + CM_LLIST_FIRST_NODE(measInfoList, measInfoNode); + } +} + +/****************************************************************** + * + * @brief Delete Ric subscription action + * + * @details + * + * Function : deleteActionSequence + * + * Functionality: Delete Ric subscription action + * + * @params[in] Action info + * + * @return void + * + * ****************************************************************/ +void deleteActionSequence(ActionInfo *action) +{ + ActionDefinition *definition=NULLP; + definition= &action->definition; + + switch(definition->formatType) + { + case 1: + { + deleteMeasurementInfoList(&definition->choice.format1.measurementInfoList); + break; + } + + case 2: + case 3: + case 4: + case 5: + default: + { + DU_LOG("\nERROR --> E2AP : Format %d does not supported", definition->formatType); + break; + } + } + memset(action, 0, sizeof(ActionInfo)); + action->actionId = -1; +} + +/****************************************************************** + * + * @brief Delete Ric subscription node + * + * @details + * + * Function : deleteRicSubscriptionNode + * + * Functionality: Delete Ric subscription node + * + * @params[in] Ric subscription info + * + * @return void + * + * ****************************************************************/ +void deleteRicSubscriptionNode(CmLList *subscriptionNode) +{ + uint8_t actionIdx=0; + RicSubscription *ricSubscriptionInfo = NULLP; + + ricSubscriptionInfo = (RicSubscription*)subscriptionNode->node; + + for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++) + { + if(ricSubscriptionInfo->actionSequence[actionIdx].actionId > -1) + { + deleteActionSequence(&ricSubscriptionInfo->actionSequence[actionIdx]); + } + } + + if(duChkTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR) == TRUE) + { + duStopTmr((PTR)ricSubscriptionInfo, EVENT_RIC_SUBSCRIPTION_REPORTING_TMR); + } + + memset(ricSubscriptionInfo, 0, sizeof(RicSubscription)); + DU_FREE(subscriptionNode->node, sizeof(RicSubscription)); + DU_FREE(subscriptionNode, sizeof(CmLList)); +} + +/****************************************************************** + * + * @brief Delete ric subscription list from the database + * + * @details + * + * Function : deleteRicSubscriptionList + * + * Functionality: Delete ric subscription list + * + * @params[in] + * Subscription List to be deleted + + * @return void + * + * ****************************************************************/ +void deleteRicSubscriptionList(CmLListCp *subscriptionList) +{ + CmLList *subscriptionNode=NULLP; + + CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode); + while(subscriptionNode) + { + /* TODO - Remove subscription information from MAC and SCH as well */ + cmLListDelFrm(subscriptionList, subscriptionNode); + deleteRicSubscriptionNode(subscriptionNode); + CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode); + } +} + +/******************************************************************* + * + * @brief Find all RIC subscriptions to be deleted in all RAN + * Functions + * + * @details + * + * Function : fetchRicSubsToBeDeleted + * + * Functionality: Find all RIC subscriptions to be deleted in all + * RAN functions and store in a temporary list + * + * @parameter Temporary list to store subscriptions to be deleted + * @return void + * + ******************************************************************/ +void fetchRicSubsToBeDeleted(CmLListCp *ricSubsToBeDelList) +{ + uint16_t ranFuncIdx = 0; + CmLList *subsNode = NULLP; + CmLList *subsToDelNode = NULLP; + + for(ranFuncIdx = 0; ranFuncIdx < MAX_RAN_FUNCTION; ranFuncIdx++) + { + if(duCb.e2apDb.ranFunction[ranFuncIdx].id > 0) + { + CM_LLIST_FIRST_NODE(&duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList, subsNode); + while(subsNode) + { + if(((RicSubscription *)subsNode->node)->action == CONFIG_DEL) + { + DU_ALLOC(subsToDelNode, sizeof(CmLList)); + if(!subsToDelNode) + { + DU_LOG("\nERROR --> E2AP : %s: Memory allocation failure at %d", __func__, __LINE__); + return; + } + subsToDelNode->node = subsNode->node; + cmLListAdd2Tail(ricSubsToBeDelList, subsToDelNode); + } + subsToDelNode = NULLP; + subsNode = subsNode->next; + } + } + } +} + +/****************************************************************** + * + * @brief Delete e2 node information from the database + * + * @details + * + * Function : removeE2NodeInformation + * + * Functionality: Delete e2 node information from the database + * + * @params[in] + * + * @return void + * +******************************************************************/ +void removeE2NodeInformation() +{ + uint16_t ranFuncIdx = 0; + + DU_LOG("\nINFO --> E2AP : Deleting all the E2 node configuration"); + for(ranFuncIdx=0; ranFuncIdx0) + { + deleteRicSubscriptionList(&(duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList)); + memset(&(duCb.e2apDb.ranFunction[ranFuncIdx].pendingSubsRspInfo), 0, MAX_PENDING_SUBSCRIPTION_RSP*sizeof(PendingSubsRspInfo)); + } + } + memset(&duCb.e2apDb.ricId, 0, sizeof(GlobalRicId)); + duCb.e2apDb.numOfTNLAssoc = 0; + memset(&duCb.e2apDb.tnlAssoc, 0, MAX_TNL_ASSOCIATION*sizeof(TNLAssociation)); + memset(&ricParams, 0, sizeof(DuSctpDestCb)); +} + +/******************************************************************* + * + * @brief Extract statistics received from DU layers and delete + * Ric subscription info + * + * @details + * + * Function :e2ProcStatsDeleteRsp + * + * Functionality: Extract statistics received from DU layers + * and delete ric subscription iformation form db + * + * @params[in] Statistics delete rsp from MAC + * @return ROK-success + * RFAILED-failure + * + * ****************************************************************/ +uint8_t e2ProcStatsDeleteRsp(MacStatsDeleteRsp *statsDeleteRsp) +{ + RanFunction *ranFuncDb = NULLP; + CmLList *ricSubscriptionNode = NULLP; + RicSubscription *ricSubscriptionInfo = NULLP; + E2FailureCause failureCause; + + /* Fetch RAN Function and Subscription DB using subscription Id received + * in statistics delete response */ + if(fetchSubsInfoFromSubsId(statsDeleteRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK) + { + DU_LOG("\nERROR --> E2AP : e2ProcStatsDeleteRsp: Failed to fetch subscriprtion details"); + return RFAILED; + } + + deleteRicSubscriptionNode(ricSubscriptionNode); + + if(statsDeleteRsp->result == MAC_DU_APP_RSP_NOK) + { + if(statsDeleteRsp->status == STATS_ID_NOT_FOUND) + { + failureCause.causeType =E2_RIC_REQUEST; + failureCause.cause = E2_REQUEST_INFORMATION_UNAVAILABLE; + } + else + { + failureCause.causeType = E2_MISCELLANEOUS; + failureCause.cause = E2_MISCELLANEOUS_CAUSE_UNSPECIFIED; + } + + if(BuildAndSendRicSubscriptionDeleteFailure(ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId, failureCause) != ROK) + { + DU_LOG("\nERROR --> E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete failure"); + return RFAILED; + } + } + else + { + if(BuildAndSendRicSubscriptionDeleteResponse(ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId) != ROK) + { + DU_LOG("\nERROR --> E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete rsp"); + return RFAILED; + } + } + + return ROK; +} + /********************************************************************** End of file **********************************************************************/