################################################################################
*******************************************************************************/
#include "common_def.h"
+#include <sys/time.h>
#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"
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
+ * Ric Action Node
+ * Config Type
+ * @return Action Info DB
+ * NULL, in case of failure
+ *
+ * ****************************************************************/
+ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo, CmLList ** actionNode, ConfigType cfgType)
+{
+ ActionInfo *actionInfoDb = NULLP;
+
+ CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, *actionNode);
+ while(*actionNode)
+ {
+ actionInfoDb = (ActionInfo*)((*actionNode)->node);
+ if(actionInfoDb && (actionInfoDb->actionId == actionId) && (actionInfoDb->action == cfgType))
+ {
+ break;
+ }
+ *actionNode= (*actionNode)->next;
+ actionInfoDb = NULLP;
+ }
+
+ if(!actionInfoDb)
+ {
+ 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
* 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;
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 grpIdx = 0, statsIdx = 0;
+ uint64_t subscriptionId = 0;
+ ActionInfo *actionDb = NULLP;
+ CmLList *actionNode = NULLP;
+ ActionDefFormat1 *format1Action = NULLP;
+
+ /* Generate subscription ID using RIC Request ID and RAN Function ID */
+ encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
+
+ macStatsReq->subscriptionId = subscriptionId;
+ CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, actionNode);
+ while(actionNode)
+ {
+ actionDb = (ActionInfo*)(actionNode->node);
+ if(actionDb->action == CONFIG_ADD)
+ {
+ 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++;
+ }
+ actionNode = actionNode->next;
+ }
+
+ 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 received for subscription
+ * modification req and send the ric subscription response msg
+ *
+ * @details
+ *
+ * Function : procStatsRspForSubsModReq
+ *
+ * Functionality: Processes statistics configuration response
+ * received for subscription modification req.
+ * [Step 1] - Fetch pendingSubsModRsp list from ran func db
+ * based on RIC request info.
+ * [Step 2] - Traverse each index of accepted list received in
+ * stats response.
+ * [Step 2.1] - Added each action related info in pending
+ * rsp's accepted list and mark action status CONFIG_UNKNOWN.
+ * [Step 3] - Traverse each index of rejected list received in
+ * stats response.
+ * [Step 3.1] - Added each action related info in pending
+ * rsp's rejected list and delete the action info from Db.
+ * [Step 4] - Set addActionCompleted true, and process the Pending
+ * Subscription modification rsp list.
+ *
+ * @params[in]
+ * Mac Stats Rsp
+ * Ran Function info
+ * Ric subscription info
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t procStatsRspForSubsModReq(MacStatsRsp *statsRsp, RanFunction *ranFuncDb, RicSubscription *ricSubscriptionInfo)
+{
+ uint8_t idx = 0;
+ uint8_t actionId = 0;
+ CmLList *actionNode = NULLP;
+ ActionInfo *actionInfoDb = NULLP;
+ PendingSubsModRspInfo *pendingSubsModRsp = NULLP;
+
+ /* Step - 1 */
+ for(idx=0; idx<ranFuncDb->numPendingSubsModRsp; idx++)
+ {
+ if((ranFuncDb->pendingSubsModRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
+ (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
+ {
+ pendingSubsModRsp = &ranFuncDb->pendingSubsModRspInfo[idx];
+ break;
+ }
+ }
+
+ if(pendingSubsModRsp == NULLP)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+
+ /* Step - 2 */
+ for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
+ {
+ actionInfoDb = NULLP;
+
+ actionId = statsRsp->statsGrpAcceptedList[idx];
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
+ if(actionInfoDb)
+ {
+ /* Step - 2.1 */
+ actionInfoDb->action = CONFIG_UNKNOWN;
+ pendingSubsModRsp->addActionStatus.acceptedActionList[pendingSubsModRsp->addActionStatus.numOfAcceptedActions++] = actionId;
+ }
+ }
+
+ /* Step - 3 */
+ for(idx=0; idx<statsRsp->numGrpRejected; idx++)
+ {
+ actionInfoDb = NULLP;
+ actionId = statsRsp->statsGrpRejectedList[idx].groupId;
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
+ if(actionInfoDb)
+ {
+ /* Step - 3.1 */
+ cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
+ deleteActionSequence(actionNode);
+ pendingSubsModRsp->addActionStatus.rejectedActionList[pendingSubsModRsp->addActionStatus.numOfRejectedActions].id = actionId;
+ convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
+ &pendingSubsModRsp->addActionStatus.rejectedActionList[pendingSubsModRsp->addActionStatus.numOfRejectedActions].failureCause);
+ pendingSubsModRsp->addActionStatus.numOfRejectedActions++;
+ }
+ }
+
+ /* Step - 4 */
+ pendingSubsModRsp->addActionCompleted =true;
+ if(duProcPendingSubsModRsp(ricSubscriptionInfo, pendingSubsModRsp) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Process statistics response for subscription req and
+ * send the ric subscription response msg
+ *
+ * @details
+ *
+ * Function : procStatsRspForSubsReq
+ *
+ * Functionality: Processes statistics configuration response
+ * received for subscription req.
+ * [Step 1] - Fetch PendingSubsRspInfo list from ran func db
+ * based on RIC request info.
+ * [Step 2] - If all stats group got rejected then send delete
+ * ric subs action info from db and send ric subscription delete
+ * message to ric
+ * [Step 3] - Store and start RIC Subscription reporting timer.
+ * [Step 4] - Traverse each index of accepted list received in
+ * stats response.
+ * [Step 4.1] - Added each action related info in pending
+ * rsp's accepted list and mark action status CONFIG_UNKNOWN.
+ * [Step 5] - Traverse each index of rejected list received in
+ * stats response.
+ * [Step 5.1] - Added each action related info in pending
+ * rsp's rejected list and delete the action info from Db.
+ * [Step 6] - Send subscription response with accepted and rejected
+ * action lists to RIC.
+ *
+ * @params[in]
+ * Mac Stats Rsp
+ * Ran Function info
+ * Ric subscription node
+ * Ric subscription info
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t procStatsRspForSubsReq(MacStatsRsp *statsRsp, RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, RicSubscription *ricSubscriptionInfo)
+{
+ uint8_t idx = 0;
+ uint8_t actionId = 0;
+ uint32_t reportingPeriod = 0;
+ CmLList *actionNode = NULLP;
+ ActionInfo *actionInfoDb = NULLP;
+ PendingSubsRspInfo *pendingSubsRsp = NULLP;
+
+ /* [Step 1] */
+ for(idx=0; idx<ranFuncDb->numPendingSubsRsp; idx++)
+ {
+ if((ranFuncDb->pendingSubsRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
+ (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
+ {
+ pendingSubsRsp = &ranFuncDb->pendingSubsRspInfo[idx];
+ break;
+ }
+ }
+
+ if(pendingSubsRsp == NULLP)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+
+ if(statsRsp->numGrpAccepted == 0)
+ {
+ /* [Step 2 ] */
+ rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
+ }
+ else
+ {
+ /* [Step 3 ] */
+ switch(ricSubscriptionInfo->eventTriggerDefinition.formatType)
+ {
+ case 1:
+ {
+ reportingPeriod = ricSubscriptionInfo->eventTriggerDefinition.choice.format1.reportingPeriod;
+ 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;
+ }
+
+
+ /* [ Step 4 ] */
+ for(idx=0; idx<statsRsp->numGrpAccepted; idx++)
+ {
+ actionInfoDb = NULLP;
+
+ actionId = statsRsp->statsGrpAcceptedList[idx];
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
+ if(actionInfoDb)
+ {
+ /* [ Step 4.1 ] */
+ actionInfoDb->action = CONFIG_UNKNOWN;
+ pendingSubsRsp->acceptedActionList[pendingSubsRsp->numOfAcceptedActions++] = actionId;
+ }
+ }
+
+ /* [ Step 5 ] */
+ for(idx=0; idx<statsRsp->numGrpRejected; idx++)
+ {
+ actionInfoDb = NULLP;
+ actionId = statsRsp->statsGrpRejectedList[idx].groupId;
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_ADD);
+ if(actionInfoDb)
+ {
+ /* [ Step 5.1 ] */
+ cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
+ deleteActionSequence(actionNode);
+ pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId;
+ convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[idx].cause, \
+ &pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].failureCause);
+ pendingSubsRsp->numOfRejectedActions++;
+ }
+ }
+
+ /* [ Step 6] */
+ if(BuildAndSendRicSubscriptionRsp(pendingSubsRsp) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : Failed to build and send RIC Subscription rsp");
+ return RFAILED;
+ }
+ }
+ memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo));
+ ricSubscriptionInfo->action = CONFIG_UNKNOWN;
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Process statistics response from MAC
+ *
+ * @details
+ *
+ * Function : e2ProcStatsRsp
+ *
+ * Functionality: Processes statistics configuration response
+ * from MAC.
+ * [Step -1]Fetch RAN Function and Subscription DB using
+ * subscription Id received in statistics response
+ * [Step -2]check ricSubscriptionInfo's action
+ * [Step 2.1]if action == CONFIG_ADD, if no group
+ * accepted then reject all stats group and send ric
+ * subscription failure. Else process stats rsp for
+ * RIC subscription response.
+ * [Step 2.1]if action == CONFIG_MOD, process stats rsp
+ * for RIC subscription modification response.
+ *
+ * @params[in] Statistics response received from MAC
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp)
+{
+ RanFunction *ranFuncDb = NULLP;
+ CmLList *ricSubscriptionNode = NULLP;
+ RicSubscription *ricSubscriptionInfo = NULLP;
+
+ /* [Step -1] */
+ if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+
+ /* [Step -2] */
+ if(ricSubscriptionInfo->action == CONFIG_ADD)
+ {
+ /* [Step -2.1] */
+ if(procStatsRspForSubsReq(statsRsp, ranFuncDb, ricSubscriptionNode, ricSubscriptionInfo) != ROK)
+ {
+ rejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
+ DU_LOG("\nERROR --> E2AP : Failed to build and send RIC Subscription rsp");
+ return RFAILED;
+ }
+ }
+ else if(ricSubscriptionInfo->action == CONFIG_MOD)
+ {
+ /* [Step -2.2] */
+ if(procStatsRspForSubsModReq(statsRsp, ranFuncDb, ricSubscriptionInfo) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : Failed to build and send RIC Subscription rsp");
+ return RFAILED;
+ }
+ }
+ 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;
+ CmLList *actionNode = 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 : %s : Failed to fetch subscriprtion details",__func__);
+ return RFAILED;
+ }
+
+ /* Fetch RIC subscription's action DB */
+ actionInfo = fetchActionInfoFromActionId(statsInd->groupId, ricSubscriptionInfo, &actionNode, CONFIG_UNKNOWN);
+ if(actionInfo == NULLP)
+ {
+ DU_LOG("\nERROR --> E2AP : %s: Failed to fetch action ID [%d]",__func__, statsInd->groupId);
+ return RFAILED;
+ }
+
+ /* Check Action format */
+ switch(actionInfo->definition.formatType)
+ {
+ case 1:
+ {
+ actionFormat = &actionInfo->definition.choice.format1;
+ break;
+ }
+ default:
+ {
+ DU_LOG("\nERROR --> E2AP : %s: Action Format [%d] is not supported", __func__,\
+ 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 : %s: Failed to convert measurement type from MAC-supported\
+ MAC-supported format to E2-supported format",__func__);
+ continue;
+ }
+
+ /* Fetch Measurement Info using E2-supported measurement type name */
+ measInfo = fetchMeasInfoFromMeasTypeName(e2MeasTypeName, &actionFormat->measurementInfoList, &measInfoNode);
+ if(measInfo == NULLP)
+ {
+ DU_LOG("\nERROR --> E2AP : %s: Measurement Type Name [%s] not found", __func__,e2MeasTypeName);
+ continue;
+ }
+
+ /* Store the measurement value in the measurement info DB fetched */
+ DU_ALLOC(measValue, sizeof(double));
+ if(!measValue)
+ {
+ DU_LOG("\nERROR --> E2AP : %s: Memory allocation failed at line [%d]",__func__, __LINE__);
+ return RFAILED;
+ }
+ *measValue = statsInd->measuredStatsList[statsIdx].value;
+
+ DU_ALLOC(measValueNode, sizeof(CmLList));
+ if(!measValueNode)
+ {
+ DU_LOG("\nERROR --> E2AP : %s : Memory allocation failed at line [%d]",__func__, __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)
+{
+ uint32_t reportingPeriod = 0;
+ ActionInfo *action=NULLP;
+ CmLList *actionNode=NULLP;
+
+ CM_LLIST_FIRST_NODE(&ricSubscription->actionSequence, actionNode);
+ while(actionNode)
+ {
+ action = (ActionInfo*)actionNode->node;
+ BuildAndSendRicIndication(ricSubscription, action);
+ actionNode = actionNode->next;
+ }
+
+ /* 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(CmLList *actionNode)
+{
+ ActionInfo *action = NULLP;
+ ActionDefinition *definition=NULLP;
+
+ if(actionNode)
+ {
+ action = (ActionInfo*)actionNode->node;
+ 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));
+ DU_FREE(actionNode->node, sizeof(ActionInfo));
+ DU_FREE(actionNode, sizeof(CmLList));
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Delete Ric subscription action list
+ *
+ * @details
+ *
+ * Function : deleteActionSequenceList
+ *
+ * Functionality: Delete Ric subscription action list
+ *
+ * @params[in] Action info list
+ *
+ * @return void
+ *
+ * ****************************************************************/
+void deleteActionSequenceList(CmLListCp *actionList)
+{
+ CmLList *actionNode=NULLP;
+
+ CM_LLIST_FIRST_NODE(actionList, actionNode);
+ while(actionNode)
+ {
+ cmLListDelFrm(actionList, actionNode);
+ deleteActionSequence(actionNode);
+ CM_LLIST_FIRST_NODE(actionList, actionNode);
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Delete Ric subscription node
+ *
+ * @details
+ *
+ * Function : deleteRicSubscriptionNode
+ *
+ * Functionality: Delete Ric subscription node
+ *
+ * @params[in] Ric subscription info
+ *
+ * @return void
+ *
+ * ****************************************************************/
+void deleteRicSubscriptionNode(CmLList *subscriptionNode)
+{
+ RicSubscription *ricSubscriptionInfo = NULLP;
+
+ ricSubscriptionInfo = (RicSubscription*)subscriptionNode->node;
+
+ deleteActionSequenceList(&ricSubscriptionInfo->actionSequence);
+ 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; ranFuncIdx<MAX_RAN_FUNCTION; ranFuncIdx++)
+ {
+ if(duCb.e2apDb.ranFunction[ranFuncIdx].id >0)
+ {
+ 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)
+{
+ RicRequestId requestId;
+ uint16_t ranFuncId;
+ 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;
+ }
+ ranFuncId = ricSubscriptionInfo->ranFuncId;
+ memcpy(&requestId, &ricSubscriptionInfo->requestId, sizeof(RicRequestId));
+
+ deleteRicSubscriptionNode(ricSubscriptionNode);
+
+ if(statsDeleteRsp->subsDelRsp == MAC_DU_APP_RSP_NOK)
+ {
+ if(statsDeleteRsp->subsDelCause == 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(ranFuncId, requestId, failureCause) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete failure");
+ return RFAILED;
+ }
+ }
+ else
+ {
+ if(BuildAndSendRicSubscriptionDeleteResponse(ranFuncId, requestId) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : e2ProcStatsDeleteRsp: failed to build and send ric subs delete rsp");
+ return RFAILED;
+ }
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Extract statistics received from DU layers and delete
+ * Ric subscription's action info
+ *
+ * @details
+ *
+ * Function : e2ProcActionDeleteRsp
+ *
+ * Functionality:
+ * [Step-1] Fetch RAN Function and Subscription DB using
+ * subscription Id received in statistics delete response.
+ * [Step-2] Fetch pending ric subs modification rsp info
+ * from ran func db based on ric request information.
+ * [Step 3] - Traverse each index of stats group delete list
+ * received in stats delete response.
+ * [Step 3.1] - If action deleted successfully, delete the
+ * node from DB and fill the action info in the pending ric
+ * subs modification rsp's accepted list.
+ * [Step 3.1] - Else fill the action info in the pending ric
+ * subs modification rsp's rejected list.
+ * [Step 4] - Set removeActionCompleted true and process the
+ * Pending Subscription modification rsp list.
+ *
+ *
+ * @params[in] Statistics delete rsp
+ * @return ROK-success
+ * RFAILED-failure
+ *
+ * ****************************************************************/
+uint8_t e2ProcActionDeleteRsp(MacStatsDeleteRsp *statsDeleteRsp)
+{
+ uint8_t idx = 0;
+ uint8_t actionId = 0;
+ uint8_t tmpIndex = 0;
+ CmLList *actionNode = NULLP;
+ ActionInfo *actionInfoDb = NULLP;
+ PendingSubsModRspInfo *pendingSubsModRsp = NULLP;
+ RanFunction *ranFuncDb = NULLP;
+ CmLList *ricSubscriptionNode = NULLP;
+ RicSubscription *ricSubscriptionInfo = NULLP;
+
+ /* [Step-1] */
+ if(fetchSubsInfoFromSubsId(statsDeleteRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+
+ /* [Step-2] */
+ for(idx=0; idx<ranFuncDb->numPendingSubsModRsp; idx++)
+ {
+ if((ranFuncDb->pendingSubsModRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
+ (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
+ {
+ pendingSubsModRsp = &ranFuncDb->pendingSubsModRspInfo[idx];
+ break;
+ }
+ }
+
+ if(pendingSubsModRsp == NULLP)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+
+ /* [Step-3] */
+ for(idx=0; idx<statsDeleteRsp->numStatsGroupDeleted; idx++)
+ {
+ actionInfoDb = NULLP;
+ actionId = statsDeleteRsp->statsGrpDelInfo[idx].groupId;
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_DEL);
+ if(actionInfoDb)
+ {
+ if(statsDeleteRsp->statsGrpDelInfo[idx].statsGrpDelRsp == MAC_DU_APP_RSP_OK)
+ {
+ /* [Step-3.1] */
+ tmpIndex = pendingSubsModRsp->removeActionStatus.numOfAcceptedActions;
+ actionInfoDb->action = CONFIG_UNKNOWN;
+ cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
+ deleteActionSequence(actionNode);
+ pendingSubsModRsp->removeActionStatus.acceptedActionList[tmpIndex] = actionId;
+ pendingSubsModRsp->removeActionStatus.numOfAcceptedActions++;
+ }
+ else
+ {
+ /* [Step-3.2] */
+ tmpIndex = pendingSubsModRsp->removeActionStatus.numOfRejectedActions;
+ pendingSubsModRsp->removeActionStatus.rejectedActionList[tmpIndex].id = actionId;
+ convertDuCauseToE2Cause(statsDeleteRsp->statsGrpDelInfo[idx].statsGrpDelCause,\
+ &pendingSubsModRsp->removeActionStatus.rejectedActionList[tmpIndex].failureCause);
+ pendingSubsModRsp->removeActionStatus.numOfRejectedActions++;
+ }
+ }
+ }
+
+ /* [Step-4] */
+ pendingSubsModRsp->removeActionCompleted = true;
+ if(duProcPendingSubsModRsp(ricSubscriptionInfo, pendingSubsModRsp) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : failed to process subscription modification rsp");
+ return RFAILED;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief du process pending ric subscription modification rsp
+ * recieved from the layers
+ *
+ * @details
+ *
+ * Function : duProcPendingSubsModRsp
+ *
+ * Functionality: Process pending subscription modification response
+ * If processing of add, mod and remove action completes
+ * then send the ric sub modification rsp
+ *
+ * @params[in]
+ * Ric subscription info
+ * Pending Subs modification rsp
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t duProcPendingSubsModRsp(RicSubscription *ricSubscriptionInfo, PendingSubsModRspInfo *pendingSubsModRsp)
+{
+ uint8_t ret = RFAILED;
+ uint32_t reportingPeriod = 0;
+
+ while(true)
+ {
+ if(pendingSubsModRsp->addActionCompleted && pendingSubsModRsp->removeActionCompleted && pendingSubsModRsp->modActionCompleted)
+ {
+ switch(ricSubscriptionInfo->eventTriggerDefinition.formatType)
+ {
+ case 1:
+ {
+ reportingPeriod = ricSubscriptionInfo->eventTriggerDefinition.choice.format1.reportingPeriod;
+ storeReportStartTime(&ricSubscriptionInfo->eventTriggerDefinition.choice.format1.startTime);
+ break;
+ }
+ default:
+ {
+ DU_LOG("\nERROR --> E2AP : Invalid event trigger format of RIC subscription");
+ break;
+ }
+ }
+ if(reportingPeriod == 0)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ break;
+ }
+
+ 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");
+ break;
+ }
+
+ if(BuildAndSendRicSubscriptionModificationResponse(pendingSubsModRsp) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ break;
+ }
+
+ memset(pendingSubsModRsp, 0, sizeof(PendingSubsModRspInfo));
+ DU_LOG("\nProcessing of RIC subscription modification completed");
+ ret = ROK;
+ break;
+ }
+ else
+ {
+ ret = ROK;
+ break;
+ }
+ }
+
+ if(ret == RFAILED)
+ {
+ memset(pendingSubsModRsp, 0, sizeof(PendingSubsModRspInfo));
+ }
+ return ret;
+}
+/*******************************************************************
+ *
+ * @brief Process statistics modification response from MAC
+ *
+ * @details
+ *
+ * Function : e2ProcStatsModificationRsp
+ *
+ * Functionality: Processes statistics modification configuration
+ * response from MAC.
+ * [Step-1] Fetch RAN Function and Subscription DB using subs Id
+ * received in statistics modification response.
+ * [Step-2] Fetch pre-stored statistics mod response info by DUAPP.
+ * [Step 3] - Traverse each index of accepted list received in
+ * stats modification response.
+ * [Step 3.1] - fetch action info from databse which is set
+ * as CONFIG_UNKNOWN and then delete the node.
+ * [Step 3.1] - Again fetch action info from databse which is
+ * set as CONFIG_MOD. Change the action status as CONFIG_UNKNOWN.
+ * fill the action in pending subscription modification rsp's
+ * accepted list.
+ * [Step 4] - Traverse each index of rejected list received in
+ * stats modification response.
+ * [Step 4.1] - fetch action info from databse and delete
+ * the action node which is set as CONFIG_MOD. and then
+ * fill the action in pending subscription modification rsp's
+ * rejected list.
+ * [Step 5] - Send subscription response with accepted and rejected
+ * @params[in] Statistics modification response received from MAC
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t e2ProcStatsModificationRsp(MacStatsModificationRsp *statsModificationRsp)
+{
+ uint8_t idx = 0;
+ uint8_t actionId = 0;
+ uint8_t tempCount = 0;
+ RanFunction *ranFuncDb = NULLP;
+ CmLList *actionNode = NULLP;
+ ActionInfo *actionInfoDb = NULLP;
+ CmLList *ricSubscriptionNode = NULLP;
+ RicSubscription *ricSubscriptionInfo = NULLP;
+ PendingSubsModRspInfo *pendingSubsModRsp = NULLP;
+
+
+ /* [Step-1] */
+ if(fetchSubsInfoFromSubsId(statsModificationRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+
+ /* [Step-2] */
+ for(idx=0; idx<ranFuncDb->numPendingSubsModRsp; idx++)
+ {
+ if((ranFuncDb->pendingSubsModRspInfo[idx].requestId.requestorId == ricSubscriptionInfo->requestId.requestorId) &&
+ (ricSubscriptionInfo->requestId.instanceId == ricSubscriptionInfo->requestId.instanceId))
+ {
+ pendingSubsModRsp = &ranFuncDb->pendingSubsModRspInfo[idx];
+ break;
+ }
+ }
+ if(pendingSubsModRsp == NULLP)
+ {
+ DU_LOG("\nERROR --> E2AP : failed in function %s at line %d",__func__,__LINE__);
+ return RFAILED;
+ }
+
+ /* [Step-3] */
+ for(idx=0; idx<statsModificationRsp->numGrpAccepted; idx++)
+ {
+ actionInfoDb = NULLP;
+ actionId = statsModificationRsp->statsGrpAcceptedList[idx];
+
+ /* [Step-3.1] */
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode,CONFIG_UNKNOWN);
+ if(actionInfoDb)
+ {
+ cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
+ deleteActionSequence(actionNode);
+ }
+
+ /* [Step-3.2] */
+ actionNode=NULLP;
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode,CONFIG_MOD);
+ if(actionInfoDb)
+ {
+ actionInfoDb->action = CONFIG_UNKNOWN;
+ }
+ pendingSubsModRsp->modActionStatus.acceptedActionList[pendingSubsModRsp->modActionStatus.numOfAcceptedActions++] = actionId;
+ }
+
+ /* [Step-4] */
+ for(idx=0; idx<statsModificationRsp->numGrpRejected; idx++)
+ {
+ actionInfoDb = NULLP;
+ actionId = statsModificationRsp->statsGrpRejectedList[idx].groupId;
+
+ /* [Step-4.1] */
+ actionInfoDb = fetchActionInfoFromActionId(actionId, ricSubscriptionInfo, &actionNode, CONFIG_MOD);
+ if(actionInfoDb)
+ {
+ cmLListDelFrm(&ricSubscriptionInfo->actionSequence, actionNode);
+ deleteActionSequence(actionNode);
+ tempCount = pendingSubsModRsp->modActionStatus.numOfRejectedActions;
+ pendingSubsModRsp->modActionStatus.rejectedActionList[tempCount].id = actionId;
+ convertDuCauseToE2Cause(statsModificationRsp->statsGrpRejectedList[idx].cause, \
+ &pendingSubsModRsp->modActionStatus.rejectedActionList[tempCount].failureCause);
+ pendingSubsModRsp->modActionStatus.numOfRejectedActions++;
+ }
+ }
+
+ /* [Step-5] */
+ pendingSubsModRsp->modActionCompleted = true;
+ if(duProcPendingSubsModRsp(ricSubscriptionInfo, pendingSubsModRsp) != ROK)
+ {
+ DU_LOG("\nERROR --> E2AP : failed to process subscription modification rsp");
+ return RFAILED;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill RIC Subscription datils in MAC Statistics
+ * ModificationRequest
+ *
+ * @details
+ *
+ * Function : fillRicSubsInMacStatsModificationReq
+ *
+ * Functionality: Fill RIC Subscription datils in MAC
+ * Modification Statistics Request
+ * [Step -1] Generate subscription ID using RIC Request ID and
+ * RAN Function ID
+ * [Step -2] Check all the action staus of each action present
+ * in the ric subscription. If action is CONFIG_MOD then fill
+ * the information in stats group list.
+ * [Step -3] Fill group related information in stats modification
+ * req's in stats group list
+ * [Step -4] fill measurement information in stats group list
+ * [Step -5] If the number of stats which needs to modify is
+ * greater then zero then return ROK else return RFAILED
+ *
+ * @params[in] MAC Statistics Modification Request to be filled
+ * RIC Subscription Info
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillRicSubsInMacStatsModificationReq(MacStatsModificationReq *macStatsModificationReq, RicSubscription* ricSubscriptionInfo)
+{
+ uint8_t grpIdx = 0;
+ uint8_t statsModifyReqIdx = 0;
+ uint64_t subscriptionId = 0;
+ CmLList *node = NULLP;
+ ActionInfo *actionDb = NULLP;
+ CmLList *actionNode = NULLP;
+ MeasurementInfo *measInfo = NULLP;
+ ActionDefFormat1 *format1Action = NULLP;
+
+ /* [Step -1] */
+ encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
+
+ macStatsModificationReq->subscriptionId = subscriptionId;
+ CM_LLIST_FIRST_NODE(&ricSubscriptionInfo->actionSequence, actionNode);
+ while(actionNode)
+ {
+ actionDb = (ActionInfo*)(actionNode->node);
+ /* [Step -2] */
+ if(actionDb->action == CONFIG_MOD)
+ {
+ /* [Step -3] */
+ macStatsModificationReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
+ switch(actionDb->definition.formatType)
+ {
+ case 1:
+ {
+ format1Action = &actionDb->definition.choice.format1;
+ macStatsModificationReq->statsGrpList[grpIdx].periodicity = format1Action->granularityPeriod;
+
+ statsModifyReqIdx = 0;
+ node = cmLListFirst(&format1Action->measurementInfoList);
+ while(node)
+ {
+ /* [Step -4] */
+ measInfo = (MeasurementInfo *)(node->node);
+ switch(measInfo->measurementTypeId)
+ {
+ case 1:
+ {
+ macStatsModificationReq->statsGrpList[grpIdx].statsList[statsModifyReqIdx++] = MAC_DL_TOTAL_PRB_USAGE;
+ break;
+ }
+ case 2:
+ {
+ macStatsModificationReq->statsGrpList[grpIdx].statsList[statsModifyReqIdx++] = MAC_UL_TOTAL_PRB_USAGE;
+ break;
+ }
+ default:
+ {
+ DU_LOG("\nERROR --> E2AP : Invalid measurement name");
+ break;
+ }
+ }
+ node = node->next;
+ }
+ macStatsModificationReq->statsGrpList[grpIdx].numStats = statsModifyReqIdx;
+ break;
+ }
+ default:
+ {
+ DU_LOG("\nERROR --> E2AP : fillRicSubsInMacStatsModificationReq: Only Action Definition Format 1 supported");
+ break;
+ }
+ }
+ if(macStatsModificationReq->statsGrpList[grpIdx].numStats)
+ grpIdx++;
+ }
+ actionNode = actionNode->next;
+ }
+
+ /* [Step -5] */
+ macStatsModificationReq->numStatsGroup = grpIdx;
+ if(macStatsModificationReq->numStatsGroup)
+ {
+ return ROK;
+ }
+ return RFAILED;
+}
+
/**********************************************************************
End of file
**********************************************************************/