[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-529] RIC Indication 33/11833/5
authorlal.harshita <Harshita.Lal@radisys.com>
Thu, 28 Sep 2023 17:45:32 +0000 (23:15 +0530)
committerlal.harshita <Harshita.Lal@radisys.com>
Fri, 29 Sep 2023 15:04:24 +0000 (20:34 +0530)
Change-Id: I7ef47c0aa49d0c4908617b74fe0550653b7db7b8
Signed-off-by: lal.harshita <Harshita.Lal@radisys.com>
src/du_app/du_e2_conversions.c
src/du_app/du_e2_conversions.h
src/du_app/du_e2ap_mgr.c
src/du_app/du_e2ap_mgr.h
src/du_app/du_e2ap_msg_hdl.c
src/du_app/du_e2ap_msg_hdl.h
src/du_app/du_msg_hdl.c
src/du_app/du_tmr.c
src/du_app/du_tmr.h
src/ric_stub/ric_e2ap_msg_hdl.c
src/ric_stub/ric_stub.h

index 497223c..098223d 100644 (file)
@@ -155,6 +155,51 @@ uint8_t convertInterfaceToE2ComponentInterfaceType(uint8_t interface)
    return RFAILED;
 }
 
+/*******************************************************************
+ *
+ * @brief Converts MAC-specific Measurement type to E2 interface
+ *        specific measurement type
+ *
+ * @details
+ *
+ *    Function : convertMacMeasTypeToE2MeasType
+ *
+ *    Functionality: Converts MAC-specific Measurement type to E2 
+ *       interface specific measurement type
+ *
+ * @params[in] MAC specific measurement type
+ *             E2 interface specific measurement type
+ *
+ * @return uint8_t
+ *
+ * ****************************************************************/
+uint8_t convertMacMeasTypeToE2MeasType(MacMeasurementType macMeasName, char *e2MeasName)
+{
+   uint8_t measNameLen = 0;
+
+   switch(macMeasName)
+   {
+      case MAC_DL_TOTAL_PRB_USAGE:
+         {
+            measNameLen = strlen("RRU.PrbTotDl");
+            memcpy(e2MeasName, "RRU.PrbTotDl", measNameLen+1);
+            break;
+         }
+      case MAC_UL_TOTAL_PRB_USAGE:
+         {
+            measNameLen = strlen("RRU.PrbTotUl");
+            memcpy(e2MeasName, "RRU.PrbTotUl", measNameLen+1);
+            break;
+         }
+      default:
+         {
+             DU_LOG("\nERROR  -->  E2AP : MAC mesurement type [%d] not supported", macMeasName);
+             return RFAILED;
+         }
+   }
+   return ROK;
+}
+
 /**********************************************************************
   End of file
  **********************************************************************/
index 329b4fa..40d3b7c 100644 (file)
@@ -21,6 +21,7 @@
 void convertDuCauseToE2Cause(CauseOfResult l2Cause, E2FailureCause *failureCause);
 uint8_t convertInterfaceToE2ComponentInterfaceType(uint8_t interface);
 uint8_t convertE2WaitTimerEnumToValue(uint8_t timerToWait);
+uint8_t convertMacMeasTypeToE2MeasType(MacMeasurementType macMeasName, char *e2MeasName);
 
 /**********************************************************************
   End of file
index 58f5845..e5816fe 100644 (file)
@@ -16,6 +16,7 @@
 ################################################################################
 *******************************************************************************/
 #include "common_def.h"
+#include <sys/time.h>
 #include "du_tmr.h"
 #include "lrg.h"
 #include "lkw.x"
@@ -121,6 +122,72 @@ void encodeSubscriptionId(uint64_t *subscriptionId, uint16_t ranFuncId, RicReque
    *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
@@ -141,13 +208,13 @@ void encodeSubscriptionId(uint64_t *subscriptionId, uint16_t ranFuncId, RicReque
 ActionInfo *fetchActionInfoFromActionId(uint8_t actionId, RicSubscription *ricSubscriptionInfo)
 {
    ActionInfo *actionInfoDb = NULLP;
-   if(ricSubscriptionInfo->actionSequence[actionId-1].id == actionId)
+   if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId)
    {
-      actionInfoDb = &ricSubscriptionInfo->actionSequence[actionId-1];
+      actionInfoDb = &ricSubscriptionInfo->actionSequence[actionId];
    }
    else
    {
-      DU_LOG("\nERROR  -->  DU_APP : fetchActionInfoFromActionId: Action Id [%d] not found in \
+      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);
 
@@ -193,7 +260,7 @@ RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *r
 
    if(!ricSubscriptionInfo)
    {
-      DU_LOG("\nERROR  -->  DU_APP : fetchSubsInfoFromRicReqId: Subscription not found for Requestor ID [%d] \
+      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);
    }
 
@@ -227,7 +294,7 @@ RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId)
    }
    else
    {
-      DU_LOG("\nERROR  -->  DU_APP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId);
+      DU_LOG("\nERROR  -->  E2AP : fetchRanFuncFromRanFuncId: Invalid RAN Function ID[%d]", ranFuncId);
    }
 
    return ranFuncDb;
@@ -396,14 +463,13 @@ uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause)
  *       Request
  *
  * @params[in] MAC Statistics Request to be filled
- *             RAN Function ID
  *             RIC Subscription Info
  *
  * @return ROK     - success
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, uint16_t ranFuncId, RicSubscription* ricSubscriptionInfo)
+uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo)
 {
    uint8_t    actionIdx = 0, grpIdx = 0, statsIdx = 0;
    uint64_t   subscriptionId = 0;
@@ -411,15 +477,15 @@ uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, uint16_t ranFuncId, R
    ActionDefFormat1 *format1Action = NULLP;
 
    /* Generate subscription ID using RIC Request ID and RAN Function ID */
-   encodeSubscriptionId(&subscriptionId, ranFuncId, ricSubscriptionInfo->requestId);
+   encodeSubscriptionId(&subscriptionId, ricSubscriptionInfo->ranFuncId, ricSubscriptionInfo->requestId);
 
    macStatsReq->subscriptionId = subscriptionId;
-   for(actionIdx = 0; actionIdx < ricSubscriptionInfo->numOfActions; actionIdx++)
+   for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
    {
       if(ricSubscriptionInfo->actionSequence[actionIdx].action == CONFIG_ADD)
       {
          actionDb = &ricSubscriptionInfo->actionSequence[actionIdx];
-         macStatsReq->statsGrpList[grpIdx].groupId = actionDb->id;
+         macStatsReq->statsGrpList[grpIdx].groupId = actionDb->actionId;
          switch(actionDb->definition.formatType)
          {
             case 1:
@@ -449,7 +515,7 @@ uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, uint16_t ranFuncId, R
                            }
                         default:
                            {
-                              DU_LOG("\nERROR  -->  DU_APP : Invalid measurement name");
+                              DU_LOG("\nERROR  -->  E2AP : Invalid measurement name");
                               break;
                            }
                      }
@@ -460,7 +526,7 @@ uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, uint16_t ranFuncId, R
                }
             default:
                {
-                  DU_LOG("\nERROR  -->  DU_APP : BuildAndSendStatsReqToMac: Only Action Definition Format 1 supported");
+                  DU_LOG("\nERROR  -->  E2AP : fillRicSubsInMacStatsReq: Only Action Definition Format 1 supported");
                   break;
                }
          }
@@ -531,16 +597,17 @@ uint8_t rejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode
  *       reporting period timer for this subscription request
  *       from RIC
  *
- * @params[in]
+ * @params[in] Statistics response received from MAC
  *
  * @return ROK     - success
  *         RFAILED - failure
  *
  * ****************************************************************/
-void e2ProcStatsRsp(MacStatsRsp *statsRsp)
+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;
@@ -550,8 +617,8 @@ void e2ProcStatsRsp(MacStatsRsp *statsRsp)
    /* Fetch RAN Function and Subscription DB using subscription Id received in statistics response */
    if(fetchSubsInfoFromSubsId(statsRsp->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
    {
-      DU_LOG("\nERROR  -->  DU_APP : DuProcMacStatsRsp: Failed to fetch subscriprtion details");
-      return;
+      DU_LOG("\nERROR  -->  E2AP : DuProcMacStatsRsp: Failed to fetch subscriprtion details");
+      return RFAILED;
    }
 
    /* Fetch pre-stored statistics response info by DU APP */
@@ -574,6 +641,34 @@ void e2ProcStatsRsp(MacStatsRsp *statsRsp)
    }
    else
    {
+      /* 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:
@@ -600,9 +695,9 @@ void e2ProcStatsRsp(MacStatsRsp *statsRsp)
       for(idx=0; idx<statsRsp->numGrpRejected; idx++)
       {
          actionId = statsRsp->statsGrpRejectedList[idx].groupId;
-         if(ricSubscriptionInfo->actionSequence[actionId-1].id == actionId)
+         if(ricSubscriptionInfo->actionSequence[actionId].actionId == actionId)
          {
-            memset(&ricSubscriptionInfo->actionSequence[actionId-1], 0, sizeof(ActionInfo));
+            memset(&ricSubscriptionInfo->actionSequence[actionId], 0, sizeof(ActionInfo));
             ricSubscriptionInfo->numOfActions--;
 
             pendingSubsRsp->rejectedActionList[pendingSubsRsp->numOfRejectedActions].id = actionId;
@@ -616,6 +711,7 @@ void e2ProcStatsRsp(MacStatsRsp *statsRsp)
       BuildAndSendRicSubscriptionRsp(pendingSubsRsp);
    }
    memset(pendingSubsRsp, 0, sizeof(PendingSubsRspInfo));
+   return ROK;
 }
 
 /*******************************************************************
@@ -631,14 +727,23 @@ void e2ProcStatsRsp(MacStatsRsp *statsRsp)
  *       action
  *
  * @params[in] Statistics Indication message received from MAC
- * @return void
+ * @return ROK-success
+ *         RFAILED-failure
  *
  * ****************************************************************/
-void e2ProcStatsInd(MacStatsInd *statsInd)
+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
@@ -651,7 +756,128 @@ void e2ProcStatsInd(MacStatsInd *statsInd)
     * in statistics response */
    if(fetchSubsInfoFromSubsId(statsInd->subscriptionId, &ranFuncDb, &ricSubscriptionNode, &ricSubscriptionInfo) != ROK)
    {
-      DU_LOG("\nERROR  -->  DU_APP : extractStatsMeasurement: Failed to fetch subscriprtion details");
+      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;
    }
 }
index e1195d5..c018f57 100644 (file)
 #define MAX_E2_SETUP_TMR 1
 #define MAX_E2_NODE_CONFIG_UPDATE_TMR 1
 #define MAX_RIC_SERVICE_UPDATE_TMR 1
+#define MAX_RIC_SUBSCRIPTION_REPORTING_TMR 1
 
 #define EVENT_E2_SETUP_TMR 1
 #define EVENT_RIC_SERVICE_UPDATE_TMR 2
 #define EVENT_E2_NODE_CONFIG_UPDATE_TMR 3
+#define EVENT_RIC_SUBSCRIPTION_REPORTING_TMR 4
 
 #define MAX_NUM_TRANSACTION 256 /* As per, O-RAN WG3 E2AP v3.0, section 9.2.33 */
 #define MAX_RAN_FUNCTION 256        /* O-RAN.WG3.E2AP-R003-v03.00 : Section 9.1.2.2 : maxofRANfunctionID */
@@ -292,10 +294,17 @@ typedef struct
    uint16_t instanceId;
 }RicRequestId;
 
+typedef struct reportStartTime
+{
+   uint32_t timeInSec;
+   uint32_t timeInMilliSec;
+}ReportStartTime;
+
 /* O-RAN.WG3.E2SM-KPM-R003-v03.00 : Section 8.2.1.1.1 */
 typedef struct
 {
    uint32_t reportingPeriod; /* In milliseconds */
+   ReportStartTime startTime;
 }EventTriggerFormat1;
 
 /* O-RAN.WG3.E2SM-KPM-R003-v03.00 : Section 8.2.1.1 */
@@ -378,7 +387,7 @@ typedef struct
 /* O-RAN.WG3.E2AP-R003-v03.00 : Section 9.1.1.1 : maxofRICActionID */
 typedef struct
 {
-   uint8_t           id;
+   int16_t           actionId;     /* O-RAN.WG3.E2AP-R003-v03.00 Section 9.2.10. Valid action id range = 0..255 */
    ActionType        type;
    ActionDefinition  definition;
    ConfigType        action;
@@ -388,9 +397,11 @@ typedef struct
 typedef struct
 {
    RicRequestId           requestId;
+   uint16_t               ranFuncId;
    EventTriggerDefinition eventTriggerDefinition;
    uint8_t                numOfActions;
    ActionInfo             actionSequence[MAX_RIC_ACTION];  
+   CmTimer                ricSubsReportTimer;
 }RicSubscription;
 
 typedef struct rejectedAction
@@ -482,9 +493,10 @@ RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId);
 uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \
    RicSubscription **ricSubscriptionInfo);
 
-uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, uint16_t ranFuncId, RicSubscription* ricSubscriptionInfo);
-void e2ProcStatsRsp(MacStatsRsp *statsRsp);
-void e2ProcStatsInd(MacStatsInd *statsInd);
+uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo);
+uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp);
+uint8_t e2ProcStatsInd(MacStatsInd *statsInd);
+void E2apHdlRicSubsReportTmrExp(RicSubscription *ricSubscription);
 
 uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause);
 uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize);
index 1c8843a..bef81af 100644 (file)
 #include "E2SM-KPM-ActionDefinition-Format1.h"
 #include "MeasurementInfoItem.h"
 #include "RANfunctionsIDcause-List.h"
+#include "MeasurementRecord.h"
+#include "MeasurementData.h"
+#include "MeasurementRecordItem.h"
+#include "MeasurementDataItem.h"
+#include "E2SM-KPM-IndicationMessage-Format1.h"
+#include "E2SM-KPM-IndicationMessage.h"
+#include "E2SM-KPM-IndicationHeader.h"
+#include "E2SM-KPM-IndicationHeader-Format1.h"
+#include "LabelInfoItem.h"
 
 /*******************************************************************
  *
@@ -2729,13 +2738,13 @@ uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSu
 
                   if(actionItem->value.choice.RICaction_ToBeSetup_Item.ricActionType == RICactionType_report)
                   {
-                     ricSubscriptionInfo->actionSequence[ricActionId-1].id = ricActionId;
-                     ricSubscriptionInfo->actionSequence[ricActionId-1].type = REPORT;
+                     ricSubscriptionInfo->actionSequence[ricActionId].actionId = ricActionId;
+                     ricSubscriptionInfo->actionSequence[ricActionId].type = REPORT;
 
-                     if(extractRicActionDef(ranFuncDb, &ricSubscriptionInfo->actionSequence[ricActionId-1].definition, \
+                     if(extractRicActionDef(ranFuncDb, &ricSubscriptionInfo->actionSequence[ricActionId].definition, \
                         actionItem->value.choice.RICaction_ToBeSetup_Item.ricActionDefinition, failureCause) == ROK)
                      {
-                        ricSubscriptionInfo->actionSequence[ricActionId-1].action = CONFIG_ADD;
+                        ricSubscriptionInfo->actionSequence[ricActionId].action = CONFIG_ADD;
                         ricSubscriptionInfo->numOfActions++;
                         break;
                      }
@@ -2743,7 +2752,9 @@ uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSu
 
                   /* In case of any failure, action is rejected
                    * Added to rejected-action-list in subscription response */
-                  memset(&ricSubscriptionInfo->actionSequence[ricActionId-1], 0, sizeof(ActionInfo));
+                  memset(&ricSubscriptionInfo->actionSequence[ricActionId], 0, sizeof(ActionInfo));
+                  ricSubscriptionInfo->actionSequence[ricActionId].actionId = -1;
+
                   subsRsp->rejectedActionList[subsRsp->numOfRejectedActions].id = ricActionId;
                   if(failureCause->causeType == E2_NOTHING)
                   {
@@ -2791,7 +2802,7 @@ uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSu
  * ****************************************************************/
 uint8_t procRicSubscriptionRequest(E2AP_PDU_t *e2apMsg)
 {
-   uint8_t idx = 0; 
+   uint8_t idx = 0, actionIdx = 0
    uint8_t ret = ROK;
    uint16_t ranFuncId = 0;
    RicRequestId ricReqId;
@@ -2856,6 +2867,12 @@ uint8_t procRicSubscriptionRequest(E2AP_PDU_t *e2apMsg)
                   }
                   ricSubscriptionInfo->requestId.requestorId = ricReqId.requestorId;
                   ricSubscriptionInfo->requestId.instanceId = ricReqId.instanceId;
+                  ricSubscriptionInfo->ranFuncId = ranFuncId;
+
+                  for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
+                  {
+                     ricSubscriptionInfo->actionSequence[actionIdx].actionId = -1;
+                  }
 
                   memset(&ranFuncDb->pendingSubsRspInfo[ranFuncDb->numPendingSubsRsp], 0, sizeof(PendingSubsRspInfo));
                   memcpy(&ranFuncDb->pendingSubsRspInfo[ranFuncDb->numPendingSubsRsp].requestId, 
@@ -2901,6 +2918,8 @@ uint8_t procRicSubscriptionRequest(E2AP_PDU_t *e2apMsg)
 
    if(ret == ROK)
    {
+      cmInitTimers(&(ricSubscriptionInfo->ricSubsReportTimer), 1);
+
       /* Add RAN subcription detail to RAN function */
       DU_ALLOC(ricSubscriptionNode, sizeof(CmLList));
       if(ricSubscriptionNode)
@@ -2913,13 +2932,8 @@ uint8_t procRicSubscriptionRequest(E2AP_PDU_t *e2apMsg)
 
 #ifdef KPI_CALCULATION
       /* Send statistics request to other DU entities */
-      BuildAndSendStatsReq(ranFuncId, ricSubscriptionInfo);
+      BuildAndSendStatsReq(ricSubscriptionInfo);
 #endif      
-
-      /* TODO : Trigger RIC Indication once statistics indication is
-       * received from MAC . 
-       * TBD in future gerrit */
-       //BuildAndSendRicIndication(ricSubscriptionInfo);
    }
    else
    {
@@ -3141,14 +3155,8 @@ void FreeRicIndication(E2AP_PDU_t  *e2apMsg)
                      switch(ricIndicationMsg->protocolIEs.list.array[idx]->id)
                      {
                         case ProtocolIE_IDE2_id_RICrequestID:
-                           break;
-
                         case ProtocolIE_IDE2_id_RANfunctionID:
-                           break;
-
                         case ProtocolIE_IDE2_id_RICactionID:
-                           break;
-
                         case ProtocolIE_IDE2_id_RICindicationType:
                            break;
 
@@ -3181,121 +3189,786 @@ void FreeRicIndication(E2AP_PDU_t  *e2apMsg)
 
 /*******************************************************************
  *
- * brief Fill the RicIndication Message
+ * @brief Free measurement record
  *
  * @details
  *
- *    Function : FillRicIndication
+ *    Function : freeMeasRecord
  *
- * Functionality:Fills the RicIndication Message
+ * Functionality: Free all measurement recorded for a measurement
+ *    within an action in a RIC subscription
+ *
+ * @param  Measurement data to be freed
+ * @return void
+ *
+ ******************************************************************/
+void freeMeasData(MeasurementData_t *measData)
+{
+   uint8_t measIdx = 0, measRecIdx = 0;
+   MeasurementRecord_t *measRecord = NULLP;
+
+   if(measData->list.array)
+   {
+      for(measIdx = 0; measIdx < measData->list.count; measIdx++)
+      {
+         if(measData->list.array[measIdx])
+         {
+            measRecord = &measData->list.array[measIdx]->measRecord;
+            if(measRecord->list.array)
+            {
+               for(measRecIdx = 0; measRecIdx < measRecord->list.count; measRecIdx++)
+               {
+                  DU_FREE(measRecord->list.array[measRecIdx], sizeof(MeasurementRecordItem_t));
+               }
+               DU_FREE(measRecord->list.array, measRecord->list.size);
+            }
+            DU_FREE(measData->list.array[measIdx], sizeof(MeasurementDataItem_t));
+         }
+      }
+      DU_FREE(measData->list.array, measData->list.size);
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Fill measurement info list
+ *
+ * @details
+ *
+ *    Function : freeMeasInfoList
+ *
+ * Functionality: Fills all measurement info within an action 
+ *    in a RIC subscription
+ *
+ * @param  Measurement Info list to be freed
+ * @return void
+ *
+ ******************************************************************/
+void freeMeasInfoList(MeasurementInfoList_t *measInfoList)
+{
+   uint8_t measInfoIdx = 0;
+
+   if(measInfoList->list.array)
+   {
+      for(measInfoIdx = 0; measInfoIdx < measInfoList->list.count; measInfoIdx++)
+      {
+         if(measInfoList->list.array[measInfoIdx])
+         {
+            DU_FREE(measInfoList->list.array[measInfoIdx]->measType.choice.measName.buf, \
+                  measInfoList->list.array[measInfoIdx]->measType.choice.measName.size);
+
+            DU_FREE(measInfoList->list.array[measInfoIdx], measInfoList->list.size);
+         }
+      }
+      DU_FREE(measInfoList->list.array, measInfoList->list.size);
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Free E2SM-KPM Indication Message
+ *
+ * @details
  *
+ *    Function : FreeE2smKpmIndicationMessage
+ *
+ * Functionality: Free E2SM-KPM Indication Message
+ *
+ * @param  E2SM-KPM Indication message to be freed
+ * @return void
+ *
+ ******************************************************************/
+void FreeE2smKpmIndicationMessage(E2SM_KPM_IndicationMessage_t *e2smKpmIndMsg)
+{
+   E2SM_KPM_IndicationMessage_Format1_t *format1Msg = NULLP;
+
+   switch(e2smKpmIndMsg->indicationMessage_formats.present)
+   {
+      case E2SM_KPM_IndicationMessage__indicationMessage_formats_PR_indicationMessage_Format1:
+         {
+            if(e2smKpmIndMsg->indicationMessage_formats.choice.indicationMessage_Format1)
+            {
+               format1Msg = e2smKpmIndMsg->indicationMessage_formats.choice.indicationMessage_Format1;
+               
+               /* Measurement Data */
+               freeMeasData(&format1Msg->measData);
+
+               /* Measurement Info List */
+               if(format1Msg->measInfoList)
+               {
+                  freeMeasInfoList(format1Msg->measInfoList);
+                  DU_FREE(format1Msg->measInfoList, sizeof(MeasurementInfoList_t));
+               }
+
+               /* Granularity Period */
+               DU_FREE(format1Msg->granulPeriod, sizeof(GranularityPeriod_t));
+
+               DU_FREE(format1Msg, sizeof(E2SM_KPM_IndicationMessage_Format1_t));
+            }
+            break;
+         }
+
+      case E2SM_KPM_IndicationMessage__indicationMessage_formats_PR_NOTHING:
+      case E2SM_KPM_IndicationMessage__indicationMessage_formats_PR_indicationMessage_Format2:
+      default:
+         break;
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Fill measurement record
+ *
+ * @details
+ *
+ *    Function : fillMeasRecord
+ *
+ * Functionality: Fills all measurement value for a measurement
+ *    within an action in a RIC subscription
+ *
+ * @param  Measurement record to be filled
+ *         Measurement database with measurement records
  * @return ROK     - success
  *         RFAILED - failure
  *
  ******************************************************************/
-uint8_t FillRicIndication(RICindication_t *ricIndicationMsg, RicSubscription *ricSubscriptionInfo)
+uint8_t fillMeasRecord(MeasurementRecord_t *measRecord, MeasurementInfo *measInfoDb)
 {
-   uint8_t elementCnt=0;
-   uint8_t idx=0;
+   uint8_t measRecIdx = 0;
+   CmLList *measValNode = NULLP;
+   double  measVal = 0;
+
+   measRecord->list.count = measInfoDb->measuredValue.count;
+   measRecord->list.size = measRecord->list.count * sizeof(MeasurementRecordItem_t *);
+
+   DU_ALLOC(measRecord->list.array, measRecord->list.size);
+   if(!measRecord->list.array)
+   {
+      DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+      return RFAILED;
+   }
+
+   for(measRecIdx = 0; measRecIdx < measRecord->list.count; measRecIdx++)
+   {
+      DU_ALLOC(measRecord->list.array[measRecIdx], sizeof(MeasurementRecordItem_t));
+      if(!measRecord->list.array[measRecIdx])
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+         return RFAILED;
+      }
+   }
+
+   measRecIdx = 0;
+   CM_LLIST_FIRST_NODE(&measInfoDb->measuredValue, measValNode);
+   while(measValNode)
+   {
+     measVal = *(double *)measValNode->node;
+     if(measVal == (int)measVal)
+     {
+        measRecord->list.array[measRecIdx]->present = MeasurementRecordItem_PR_integer;
+        measRecord->list.array[measRecIdx]->choice.integer = (int)measVal;
+     }
+     else
+     {
+         measRecord->list.array[measRecIdx]->present = MeasurementRecordItem_PR_real;
+         measRecord->list.array[measRecIdx]->choice.real = measVal;
+     }
+     measRecIdx++;
+
+     /* Once the measurement record is added to the message, delete it from DB */
+     cmLListDelFrm(&measInfoDb->measuredValue, measValNode);
+     DU_FREE(measValNode->node, sizeof(double));
+     DU_FREE(measValNode, sizeof(CmLList));
+
+     CM_LLIST_FIRST_NODE(&measInfoDb->measuredValue, measValNode);
+     measVal = 0;
+   }
+
+   return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills measuerement data
+ *
+ * @details
+ *
+ *    Function : fillMeasData
+ *
+ * Functionality: Fill all measurement recorded for all measurements
+ *    in an action in a RIC subscription
+ *
+ * @param  Measurement data to be filled
+ *         Measurement info list from an action DB
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t fillMeasData(MeasurementData_t *measData, CmLListCp *measInfoListDb)
+{
+  uint8_t measIdx = 0;
+  CmLList *measInfoNode = NULLP;
+  MeasurementInfo *measInfoDb = NULLP;
+  MeasurementRecord_t *measRecord = NULLP;
+
+  measData->list.count = measInfoListDb->count;
+  measData->list.size = measData->list.count * sizeof(MeasurementDataItem_t *);
+
+  DU_ALLOC(measData->list.array, measData->list.size);
+  if(!measData->list.array)
+  {
+     DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+     return RFAILED;
+  }
+
+  measIdx = 0;
+  CM_LLIST_FIRST_NODE(measInfoListDb, measInfoNode);
+  while(measInfoNode)
+  {
+     measInfoDb = (MeasurementInfo *)measInfoNode->node;
+     if(measInfoDb)
+     {
+        DU_ALLOC(measData->list.array[measIdx], sizeof(MeasurementDataItem_t));
+        if(!measData->list.array[measIdx])
+        {
+           DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+           return RFAILED;
+        }
+
+        measRecord = &measData->list.array[measIdx]->measRecord;
+        if(fillMeasRecord(measRecord, measInfoDb) != ROK)
+        {
+           DU_LOG("\nERROR  -->  E2AP : Failed to fill measurement record");
+           return RFAILED;
+        }
+        measIdx++;
+     }
+     measInfoNode = measInfoNode->next;
+  }
+
+  return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill all measurement info
+ *
+ * @details
+ *
+ *    Function : fillMeasInfoList
+ *
+ * Functionality: Fills all measurement info belonging to an action
+ *  in a RIC subscription
+ *
+ * @param   Measurement Info list to be filled
+ *          Measurement Info list from E2AP DB
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t fillMeasInfoList(MeasurementInfoList_t *measInfoList, CmLListCp *measInfoListDb)
+{
+   uint8_t measInfoIdx = 0;
+   CmLList *measInfoNode = NULLP;
+   MeasurementInfo *measInfoDb = NULLP;
+   MeasurementInfoItem_t *measInfoItem = NULLP;
+
+   measInfoList->list.count = measInfoListDb->count;
+   measInfoList->list.size = measInfoList->list.count * sizeof(MeasurementInfoItem_t *);
+
+   DU_ALLOC(measInfoList->list.array, measInfoList->list.size);
+   if(!measInfoList->list.array)
+   {
+      DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+      return RFAILED;
+   }
+
+   measInfoIdx = 0;
+   CM_LLIST_FIRST_NODE(measInfoListDb, measInfoNode);
+   while(measInfoNode)
+   {
+      DU_ALLOC(measInfoList->list.array[measInfoIdx], sizeof(MeasurementInfoItem_t));
+      if(!measInfoList->list.array[measInfoIdx])
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+         return RFAILED;
+      }
+
+      measInfoItem = measInfoList->list.array[measInfoIdx];
+      measInfoDb = (MeasurementInfo *)measInfoNode->node;
+      if(measInfoDb)
+      {
+         /* Measurement Type */
+         measInfoItem->measType.present = MeasurementType_PR_measName;
+         measInfoItem->measType.choice.measName.size = strlen(measInfoDb->measurementTypeName);
+
+         DU_ALLOC(measInfoItem->measType.choice.measName.buf, measInfoItem->measType.choice.measName.size);
+         if(!measInfoItem->measType.choice.measName.buf)
+         {
+            DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+            return RFAILED;
+         }
+
+         memcpy(measInfoItem->measType.choice.measName.buf, measInfoDb->measurementTypeName,\
+            measInfoItem->measType.choice.measName.size);
+
+         measInfoIdx++;
+      }
+      measInfoNode = measInfoNode->next;
+      measInfoDb = NULLP;
+   }
+
+   return ROK;
+}
+
+ /*******************************************************************
+ *
+ * @brief Fill E2SM-KPM Indication Message Format 1
+ *
+ * @details
+ *
+ *    Function : fillE2smKpmIndMsgFormat1
+ *
+ * Functionality: Fill E2SM-KPM Indication Message Format 1
+ *
+ * @param  Format 1 Message to be filled
+ *         Action Definition format 1 from E2AP DB
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t fillE2smKpmIndMsgFormat1(E2SM_KPM_IndicationMessage_Format1_t *format1Msg, ActionDefFormat1 *format1)
+{
+  /* Measurement Data */
+  if(fillMeasData(&format1Msg->measData, &format1->measurementInfoList) != ROK)
+  {
+     DU_LOG("\nERROR  -->  E2AP : Failed to fill measurement data");
+     return RFAILED;
+  }
+
+  /* Measurement Information */
+  DU_ALLOC(format1Msg->measInfoList, sizeof(MeasurementInfoList_t));
+  if(!format1Msg->measInfoList)
+  {
+     DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+     return RFAILED;
+  }
+
+  if(fillMeasInfoList(format1Msg->measInfoList, &format1->measurementInfoList) != ROK)
+  {
+     DU_LOG("\nERROR  -->  E2AP : Failed to fill measurement information list");
+     return RFAILED;
+  }
+
+  /* Granularity Period */
+  DU_ALLOC(format1Msg->granulPeriod, sizeof(GranularityPeriod_t));
+  if(!format1Msg->granulPeriod)
+  {
+     DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+     return RFAILED;
+  }
+  *(format1Msg->granulPeriod) = format1->granularityPeriod;
+
+  return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill RIC Indication Message buffer
+ *
+ * @details
+ *
+ *    Function : fillRicIndMsgBuf
+ *
+ * Functionality: Fill E2SM-KPM Indication Message
+ *    Encode this message and copy to RIC Indication Message buffer
+ * 
+ * @param  RIC Indication Message buffer to be filled
+ *         Source action info from E2AP DB
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t fillRicIndMsgBuf(RICindicationMessage_t *ricIndMsgBuf, ActionInfo *actionInfo)
+{
+   uint8_t ret = RFAILED;
+   bool failedInFormat = false;
+   E2SM_KPM_IndicationMessage_t e2smKpmIndMsg;
+   asn_enc_rval_t   encRetVal;        /* Encoder return value */
+
+   memset(&e2smKpmIndMsg, 0, sizeof(E2SM_KPM_IndicationMessage_t));
+
+   while(true)
+   {
+      /* E2SM-KPM Indication message format type */
+      e2smKpmIndMsg.indicationMessage_formats.present = actionInfo->definition.formatType;
+      switch(e2smKpmIndMsg.indicationMessage_formats.present)
+      {
+         case E2SM_KPM_IndicationMessage__indicationMessage_formats_PR_indicationMessage_Format1:
+            {
+               /* E2SM-KPM Indication message format 1 */
+               DU_ALLOC(e2smKpmIndMsg.indicationMessage_formats.choice.indicationMessage_Format1, \
+                     sizeof(E2SM_KPM_IndicationMessage_Format1_t));
+               if(!e2smKpmIndMsg.indicationMessage_formats.choice.indicationMessage_Format1)
+               {
+                  DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+                  failedInFormat = true;
+                  break;
+               }
+
+               if(fillE2smKpmIndMsgFormat1(e2smKpmIndMsg.indicationMessage_formats.choice.indicationMessage_Format1, \
+                  &actionInfo->definition.choice.format1) != ROK)
+               {
+                  DU_LOG("\nERROR  -->  E2AP : Failed to fill E2SM-KPM Indication message format 1");
+                  failedInFormat = true;
+                  break;
+               }
+               break;
+            }
+
+         case E2SM_KPM_IndicationMessage__indicationMessage_formats_PR_NOTHING:
+         case E2SM_KPM_IndicationMessage__indicationMessage_formats_PR_indicationMessage_Format2:
+         default:
+            {
+               DU_LOG("\nERROR  -->  E2AP : fillRicIndMsgBuf: Only Format 1 supported");
+               failedInFormat = true;
+               break;
+            }
+      }
+
+      if(failedInFormat)
+         break;
+
+      /* Encode E2SM-KPM Indication Message */
+      xer_fprint(stdout, &asn_DEF_E2SM_KPM_IndicationMessage, &e2smKpmIndMsg);
+      memset(encBuf, 0, ENC_BUF_MAX_LEN);
+      encBufSize = 0;
+      encRetVal = aper_encode(&asn_DEF_E2SM_KPM_IndicationMessage, 0, &e2smKpmIndMsg, PrepFinalEncBuf, encBuf);
+      if(encRetVal.encoded == ENCODE_FAIL)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Could not encode E2SM-KPM Indication Message (at %s)\n",\
+               encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+         break;
+      }
+      else
+      {
+         DU_LOG("\nDEBUG  -->  E2AP : Created APER encoded buffer for E2SM-KPM Indication Message \n");
+#ifdef DEBUG_ASN_PRINT
+         for(int i=0; i< encBufSize; i++)
+         {
+            printf("%x",encBuf[i]);
+         } 
+#endif
+      }
+
+      /* Copy encoded string to RIC Indication Message buffer */
+      ricIndMsgBuf->size = encBufSize;
+      DU_ALLOC(ricIndMsgBuf->buf, ricIndMsgBuf->size);
+      if(!ricIndMsgBuf->buf)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+         break;
+      }
+      memset(ricIndMsgBuf->buf, 0, ricIndMsgBuf->size);
+      memcpy(ricIndMsgBuf->buf, encBuf, encBufSize);
+
+      ret = ROK;
+      break;
+   }
+
+   /* Free E2SM-KPM Indication Message */
+   FreeE2smKpmIndicationMessage(&e2smKpmIndMsg);
+
+   return ret;
+}
+
+/*******************************************************************
+ *
+ * @brief Free E2SM-KPM Indication Header
+ *
+ * @details
+ *
+ *    Function : FreeE2smKpmIndicationHeader
+ *
+ * Functionality: Free E2SM-KPM Indication Header
+ * 
+ * @param  E2SM-KPM Indication Header to be free
+ * @return void
+ *
+ ******************************************************************/
+void FreeE2smKpmIndicationHeader(E2SM_KPM_IndicationHeader_t *e2smKpmIndHdr)
+{
+   E2SM_KPM_IndicationHeader_Format1_t *format1 = NULLP;
+
+   if(e2smKpmIndHdr)
+   {
+      switch(e2smKpmIndHdr->indicationHeader_formats.present)
+      {
+         case E2SM_KPM_IndicationHeader__indicationHeader_formats_PR_indicationHeader_Format1:
+            {
+               if(e2smKpmIndHdr->indicationHeader_formats.choice.indicationHeader_Format1)
+               {
+                  format1 = e2smKpmIndHdr->indicationHeader_formats.choice.indicationHeader_Format1;
+
+                  DU_FREE(format1->colletStartTime.buf, format1->colletStartTime.size);
+                  DU_FREE(format1, sizeof(E2SM_KPM_IndicationHeader_Format1_t));
+               }
+               break;
+            }
+         case E2SM_KPM_IndicationHeader__indicationHeader_formats_PR_NOTHING:
+         default:
+            break;
+      }
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Fill RIC Indication Header buffer
+ *
+ * @details
+ *
+ *    Function : fillRicIndHeader
+ *
+ * Functionality: Fill E2SM-KPM Indication Header
+ *    Encode this message and copy to RIC Indication Header buffer
+ * 
+ * @param  RIC Indication Header buffer to be filled
+ *         Source RIC subscription info from E2AP DB
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t fillRicIndHeader(RICindicationHeader_t *ricIndHdr, RicSubscription *ricSubsInfo)
+{
+   uint8_t ret = RFAILED;
+   uint8_t secBufIdx = 0, milliSecBufIdx = 0;
+   int8_t byteIdx = 0;
+   bool formatFailure = false;
+   RanFunction *ranFunc = NULLP;
+   ReportStartTime *startTime = NULLP;
+   E2SM_KPM_IndicationHeader_t e2smKpmIndHdr;
+   E2SM_KPM_IndicationHeader_Format1_t *format1 = NULLP;
+   asn_enc_rval_t   encRetVal;        /* Encoder return value */
+
+   while(true)
+   {
+      ranFunc = fetchRanFuncFromRanFuncId(ricSubsInfo->ranFuncId);
+      if(ranFunc == NULLP)
+      {
+         DU_LOG("\nERROR  -->  E2AP : RAN Function ID [%d] not found", ricSubsInfo->ranFuncId);
+         break;
+      }
+
+      memset(&e2smKpmIndHdr, 0, sizeof(E2SM_KPM_IndicationHeader_t));
+
+      e2smKpmIndHdr.indicationHeader_formats.present = ranFunc->ricIndicationHeaderFormat;
+      switch(e2smKpmIndHdr.indicationHeader_formats.present)
+      {
+         case E2SM_KPM_IndicationHeader__indicationHeader_formats_PR_indicationHeader_Format1:
+            {
+               DU_ALLOC(e2smKpmIndHdr.indicationHeader_formats.choice.indicationHeader_Format1, \
+                     sizeof(E2SM_KPM_IndicationHeader_Format1_t));
+               if(!e2smKpmIndHdr.indicationHeader_formats.choice.indicationHeader_Format1)
+               {
+                  DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+                  formatFailure = true;
+                  break;
+               }
+               format1 = e2smKpmIndHdr.indicationHeader_formats.choice.indicationHeader_Format1;
+
+               /* Fetch reporting period start time from DB */
+               switch(ricSubsInfo->eventTriggerDefinition.formatType)
+               {
+                  case 1:
+                  {
+                     startTime = &ricSubsInfo->eventTriggerDefinition.choice.format1.startTime;
+                  }
+               }
+
+               format1->colletStartTime.size = 8 * sizeof(uint8_t);
+               DU_ALLOC(format1->colletStartTime.buf, format1->colletStartTime.size);
+               if(!format1->colletStartTime.buf)
+               {
+                  DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+                  formatFailure = true;
+                  break;
+               }
+
+               /* As per O-RAN.WG3.E2SM-KPM-R003-v03.00, section 8.3.12 and
+                * RFC 5905, section 6 :
+                * Time stamp has a 64-bit format where first 32-bit is seconds
+                * and next 32-bit is fraction in picosecond-level.
+                * This fraction has been rounded in microseconds.
+                *
+                * Hence,
+                * Storing 32-bit seconds at MSB 0-3 and
+                * 32-bit milliseconds at next 4 bytes i.e. bytes 4-7
+                */
+               secBufIdx = 0;
+               milliSecBufIdx = 4;
+               for(byteIdx = 3; byteIdx >= 0; byteIdx--)
+               {
+                  format1->colletStartTime.buf[secBufIdx++] = startTime->timeInSec >> (8*byteIdx);
+                  format1->colletStartTime.buf[milliSecBufIdx++] = startTime->timeInMilliSec >> (8*byteIdx);
+               }
+               break;
+            }
+
+         case E2SM_KPM_IndicationHeader__indicationHeader_formats_PR_NOTHING:
+         default:
+         {
+             DU_LOG("\nERROR  -->  E2AP : Only E2SM-KPM Indication Header Format 1 supported");
+             formatFailure = true;
+             break;
+         }
+      }
+
+      if(formatFailure)
+         break;
+
+      /* Encode E2SM-KPM Indication Header */
+      xer_fprint(stdout, &asn_DEF_E2SM_KPM_IndicationHeader, &e2smKpmIndHdr);
+      memset(encBuf, 0, ENC_BUF_MAX_LEN);
+      encBufSize = 0;
+      encRetVal = aper_encode(&asn_DEF_E2SM_KPM_IndicationHeader, 0, &e2smKpmIndHdr, PrepFinalEncBuf, encBuf);
+      if(encRetVal.encoded == ENCODE_FAIL)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Could not encode E2SM-KPM Indication Header (at %s)\n",\
+               encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+         break;
+      }
+      else
+      {
+         DU_LOG("\nDEBUG  -->  E2AP : Created APER encoded buffer for E2SM-KPM Indication Header \n");
+#ifdef DEBUG_ASN_PRINT
+         for(int i=0; i< encBufSize; i++)
+         {
+            printf("%x",encBuf[i]);
+         } 
+#endif
+      }
+
+      /* Copy encoded string to RIC Indication Header buffer */
+      ricIndHdr->size = encBufSize;
+      DU_ALLOC(ricIndHdr->buf, ricIndHdr->size);
+      if(!ricIndHdr->buf)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+         break;
+      }
+      memset(ricIndHdr->buf, 0, ricIndHdr->size);
+      memcpy(ricIndHdr->buf, encBuf, encBufSize);
+      ret = ROK;
+      break;
+   }
+
+   /* Free E2SM-KPM Indication Header */
+   FreeE2smKpmIndicationHeader(&e2smKpmIndHdr);
+
+   return ret;
+}
+
+/*******************************************************************
+ *
+ * brief Fill the RIC Indication Message
+ *
+ * @details
+ *
+ *    Function : fillRicIndication
+ *
+ * Functionality: Fills the RIC Indication Message
+ *
+ * @param  RIC Indication Message to be filled
+ *         RIC Subscription DB
+ *         Action DB
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t fillRicIndication(RICindication_t *ricIndicationMsg, RicSubscription *ricSubscriptionInfo, ActionInfo *actionInfo)
+{
+   uint8_t elementCnt = 0, idx = 0;
    uint8_t ret = ROK;
+
    elementCnt = 6;
 
    ricIndicationMsg->protocolIEs.list.count = elementCnt;
-   ricIndicationMsg->protocolIEs.list.size  = elementCnt * sizeof(RICindication_t);
+   ricIndicationMsg->protocolIEs.list.size  = elementCnt * sizeof(RICindication_IEs_t *);
+
    /* Initialize the Ric Indication members */
-   DU_ALLOC(ricIndicationMsg->protocolIEs.list.array, \
-        ricIndicationMsg->protocolIEs.list.size);
+   DU_ALLOC(ricIndicationMsg->protocolIEs.list.array, ricIndicationMsg->protocolIEs.list.size);
    if(ricIndicationMsg->protocolIEs.list.array == NULLP)
    {
-      DU_LOG("\nERROR  -->  E2AP : Memory allocation for RICindicationIEs failed");
-      ret = RFAILED;
+      DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+      return RFAILED;
    }
-   else
+
+   for(idx=0; idx<elementCnt; idx++)
    {
-      for(idx=0; idx<elementCnt; idx++)
+      DU_ALLOC(ricIndicationMsg->protocolIEs.list.array[idx], sizeof(RICindication_IEs_t));
+      if(ricIndicationMsg->protocolIEs.list.array[idx] == NULLP)
       {
-        DU_ALLOC(ricIndicationMsg->protocolIEs.list.array[idx],\
-              sizeof(RICindication_IEs_t));
-        if(ricIndicationMsg->protocolIEs.list.array[idx] == NULLP)
-        {
-           DU_LOG("\nERROR  -->  E2AP : Memory allocation for RICindicationIEs failed");
-           ret = RFAILED;
-        }
-      }
-      if(ret != RFAILED)
-      {
-        idx = 0;
-
-        ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICrequestID;
-        ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.present = \
-                                                                       RICindication_IEs__value_PR_RICrequestID;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricRequestorID =ricSubscriptionInfo->requestId.requestorId;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricInstanceID = ricSubscriptionInfo->requestId.instanceId;
-
-        idx++;
-        ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RANfunctionID;
-        ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.present = \
-                                                                       RICindication_IEs__value_PR_RANfunctionID;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RANfunctionID = duCb.e2apDb.ranFunction[0].id;
-
-        idx++;
-        ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICactionID;
-        ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.present = \
-                                                                       RICindication_IEs__value_PR_RICactionID;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICactionID = ricSubscriptionInfo->actionSequence[0].id;
-
-        idx++;
-        ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICindicationType;
-        ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.present = \
-                                                                       RICindication_IEs__value_PR_RICindicationType;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationType = ricSubscriptionInfo->actionSequence[0].type;
-
-        idx++;
-        ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICindicationHeader;
-        ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.present = \
-                                                                       RICindication_IEs__value_PR_RICindicationHeader;
-        ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationHeader.size = 3 *
-           sizeof(uint8_t);
-        DU_ALLOC(ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationHeader.buf ,\
-              ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationHeader.size);
-        if(ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationHeader.buf == NULLP)
-        {
-           DU_LOG("\nERROR  -->  E2AP : Memory allocation for RICindicationIEs failed");
-           ret = RFAILED;
-        }
-        else
-        {
-           buildPlmnId(duCfgParam.srvdCellLst[0].duCellInfo.cellInfo.nrCgi.plmn, \
-                 ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationHeader.buf);
-           idx++;
-           /* TO BE CHANGED: RIC INDICATION DATA */
-           /* For now filling a dummy octect data, need to tested with PRBs*/
-           ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICindicationMessage;
-           ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
-           ricIndicationMsg->protocolIEs.list.array[idx]->value.present = \
-                                                                          RICindication_IEs__value_PR_RICindicationMessage;
-           ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationMessage.size = 3 *
-              sizeof(uint8_t);
-           DU_ALLOC(ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationMessage.buf ,\
-                 ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationMessage.size);
-           if(ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationMessage.buf == NULLP)
-           {
-              DU_LOG("\nERROR  -->  E2AP : Memory allocation for RICindicationIEs failed");
-              ret = RFAILED;
-           }
-           else
-           {
-              buildPlmnId(duCfgParam.srvdCellLst[0].duCellInfo.cellInfo.nrCgi.plmn, \
-                    ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationMessage.buf);
-           }
-        }
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation in [%s] at line [%d]", __func__, __LINE__);
+         return RFAILED;
       }
    }
+
+   /* RIC Request ID */
+   idx = 0;
+   ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICrequestID;
+   ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.present = RICindication_IEs__value_PR_RICrequestID;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricRequestorID = \
+      ricSubscriptionInfo->requestId.requestorId;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricInstanceID = \
+      ricSubscriptionInfo->requestId.instanceId;
+
+   /* RAN Function ID */
+   idx++;
+   ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RANfunctionID;
+   ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.present = RICindication_IEs__value_PR_RANfunctionID;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RANfunctionID = ricSubscriptionInfo->ranFuncId;
+
+   /* RIC Action ID */
+   idx++;
+   ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICactionID;
+   ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.present = RICindication_IEs__value_PR_RICactionID;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICactionID = actionInfo->actionId;
+
+   /* RIC Indication Type */
+   idx++;
+   ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICindicationType;
+   ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.present = RICindication_IEs__value_PR_RICindicationType;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationType = actionInfo->type;
+
+   /* RIC Indication Header */
+   idx++;
+   ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICindicationHeader;
+   ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.present = RICindication_IEs__value_PR_RICindicationHeader;
+   if(fillRicIndHeader(&ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationHeader, \
+      ricSubscriptionInfo) != ROK)
+   {
+      DU_LOG("\nERROR  -->  E2AP : Failed to fill RIC Indication header");
+      return RFAILED;
+   }
+
+   /* RIC Indication Message */
+   idx++;
+   ricIndicationMsg->protocolIEs.list.array[idx]->id = ProtocolIE_IDE2_id_RICindicationMessage;
+   ricIndicationMsg->protocolIEs.list.array[idx]->criticality = CriticalityE2_reject;
+   ricIndicationMsg->protocolIEs.list.array[idx]->value.present = RICindication_IEs__value_PR_RICindicationMessage;
+   if(fillRicIndMsgBuf(&ricIndicationMsg->protocolIEs.list.array[idx]->value.choice.RICindicationMessage, \
+      actionInfo) != ROK)
+   {
+      DU_LOG("\nERROR  -->  E2AP : Failed to fill RIC Indication Message");
+      return RFAILED;
+   }
+
    return ret;
 }
 
@@ -3314,13 +3987,12 @@ uint8_t FillRicIndication(RICindication_t *ricIndicationMsg, RicSubscription *ri
  *
  ******************************************************************/
 
-uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo)
+uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo, ActionInfo *actionInfo)
 {
-   E2AP_PDU_t                 *e2apMsg = NULLP;
-   RICindication_t            *ricIndicationMsg=NULLP;
-   asn_enc_rval_t             encRetVal;        /* Encoder return value */
-   uint8_t ret = RFAILED; 
-   uint8_t FillRicIndicationret = ROK;
+   uint8_t          ret = RFAILED; 
+   E2AP_PDU_t       *e2apMsg = NULLP;
+   RICindication_t  *ricIndicationMsg = NULLP;
+   asn_enc_rval_t   encRetVal;        /* Encoder return value */
 
    while(true)
    {
@@ -3329,16 +4001,16 @@ uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo)
       DU_ALLOC(e2apMsg, sizeof(E2AP_PDU_t));
       if(e2apMsg == NULLP)
       {
-        DU_LOG("\nERROR  -->  E2AP : Memory allocation for E2AP-PDU failed");
-        break;
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation for E2AP-PDU failed");
+         break;
       }
 
       e2apMsg->present = E2AP_PDU_PR_initiatingMessage;
       DU_ALLOC(e2apMsg->choice.initiatingMessage, sizeof(InitiatingMessageE2_t));
       if(e2apMsg->choice.initiatingMessage == NULLP)
       {
-        DU_LOG("\nERROR  -->  E2AP : Memory allocation for E2AP-PDU failed");
-        break;
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation for E2AP-PDU failed");
+         break;
       }
       e2apMsg->choice.initiatingMessage->procedureCode = ProcedureCodeE2_id_RICindication;
       e2apMsg->choice.initiatingMessage->criticality = CriticalityE2_reject;
@@ -3346,37 +4018,38 @@ uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo)
 
       ricIndicationMsg = &e2apMsg->choice.initiatingMessage->value.choice.RICindication;
 
-      FillRicIndicationret = FillRicIndication(ricIndicationMsg, ricSubscriptionInfo);
-      if(FillRicIndicationret != ROK)
+      if(fillRicIndication(ricIndicationMsg, ricSubscriptionInfo, actionInfo) != ROK)
       {
-        break;
+         DU_LOG("\nERROR  -->  E2AP : Failed to fill RIC Indication message");
+         break;
       }
+
       /* Prints the Msg formed */
       xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2apMsg);
       memset(encBuf, 0, ENC_BUF_MAX_LEN);
       encBufSize = 0;
       encRetVal = aper_encode(&asn_DEF_E2AP_PDU, 0, e2apMsg, PrepFinalEncBuf,\
-           encBuf);
+            encBuf);
       if(encRetVal.encoded == ENCODE_FAIL)
       {
-        DU_LOG("\nERROR  -->  E2AP : Could not encode RIC Indication Message (at %s)\n",\
-              encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
-        break;
+         DU_LOG("\nERROR  -->  E2AP : Could not encode RIC Indication Message (at %s)\n",\
+               encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+         break;
       }
       else
       {
-        DU_LOG("\nDEBUG  -->  E2AP : Created APER encoded buffer for RIC Indication Message \n");
+         DU_LOG("\nDEBUG  -->  E2AP : Created APER encoded buffer for RIC Indication Message \n");
 #ifdef DEBUG_ASN_PRINT
-        for(int i=0; i< encBufSize; i++)
-        {
-           printf("%x",encBuf[i]);
-        } 
+         for(int i=0; i< encBufSize; i++)
+         {
+            printf("%x",encBuf[i]);
+         
 #endif
       }
 
       if(SendE2APMsg(DU_APP_MEM_REGION, DU_POOL, encBuf, encBufSize) != ROK)
       {
-        DU_LOG("\nINFO   -->  E2AP : Sending RIC Indication Message");      
+         DU_LOG("\nINFO   -->  E2AP : Sending RIC Indication Message");      
 
       }
       ret = ROK;
index d2ef51b..f19fce3 100644 (file)
@@ -27,10 +27,10 @@ uint8_t BuildAndSendE2NodeConfigUpdate(E2NodeConfigList *recvList);
 uint8_t BuildAndSendRicServiceUpdate(RicServiceUpdate serviceUpdate);
 uint8_t duSendE2NodeConfigurationUpdate();
 
-uint8_t BuildAndSendStatsReq(uint16_t ranFuncId, RicSubscription *ricSubscriptionInfo);
+uint8_t BuildAndSendStatsReq(RicSubscription *ricSubscriptionInfo);
 uint8_t BuildAndSendRicSubscriptionRsp(PendingSubsRspInfo *subsRspInfo);
 uint8_t BuildAndSendRicSubscriptionFailure(RicRequestId ricReqId, uint16_t ranFuncId, E2FailureCause failureCause);
-uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo);
+uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo, ActionInfo *actionInfo);
 
 /**********************************************************************
   End of file
index c7d5328..a99b7db 100644 (file)
@@ -2094,7 +2094,7 @@ uint8_t DuProcRlcSliceMetrics(Pst *pst, SlicePmList *sliceStats)
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t BuildAndSendStatsReqToMac(uint16_t ranFuncId, RicSubscription *ricSubscriptionInfo)
+uint8_t BuildAndSendStatsReqToMac(RicSubscription *ricSubscriptionInfo)
 {
    Pst pst;
    MacStatsReq *macStatsReq = NULLP;
@@ -2108,7 +2108,7 @@ uint8_t BuildAndSendStatsReqToMac(uint16_t ranFuncId, RicSubscription *ricSubscr
    }
 
    /* Fill E2 Subscription Info in MAC Statistics Request and send to MAC */
-   if(fillRicSubsInMacStatsReq(macStatsReq, ranFuncId, ricSubscriptionInfo) == ROK)
+   if(fillRicSubsInMacStatsReq(macStatsReq, ricSubscriptionInfo) == ROK)
    {
       DU_LOG("\nDEBUG  -->  DU_APP: Sending Statistics Request to MAC ");
       FILL_PST_DUAPP_TO_MAC(pst, EVENT_MAC_STATISTICS_REQ);
@@ -2142,10 +2142,10 @@ uint8_t BuildAndSendStatsReqToMac(uint16_t ranFuncId, RicSubscription *ricSubscr
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t BuildAndSendStatsReq(uint16_t ranFuncId, RicSubscription *ricSubscriptionInfo)
+uint8_t BuildAndSendStatsReq(RicSubscription *ricSubscriptionInfo)
 {
    /* Build and sent subscription information to MAC in Statistics Request */
-   if(BuildAndSendStatsReqToMac(ranFuncId, ricSubscriptionInfo) != ROK)
+   if(BuildAndSendStatsReqToMac(ricSubscriptionInfo) != ROK)
    {
       DU_LOG("\nERROR  -->  DU_APP : Failed at BuildAndSendStatsReqToMac()");
       return RFAILED;   
@@ -2185,6 +2185,7 @@ uint8_t BuildAndSendStatsReq(uint16_t ranFuncId, RicSubscription *ricSubscriptio
  * ****************************************************************/
 uint8_t DuProcMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp)
 {
+   uint8_t ret = RFAILED;
    DU_LOG("\nINFO  -->  DU_APP : DuProcMacStatsRsp: Received Statistics Response from MAC");
 
    if(statsRsp)
@@ -2208,14 +2209,18 @@ uint8_t DuProcMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp)
 
       /* Check the list of accepted and rejected statistics group and send
        * Ric subscription response/failure accordingly */
-      e2ProcStatsRsp(statsRsp);
+      if((ret = e2ProcStatsRsp(statsRsp)) != ROK)
+      {
+         DU_LOG("\nERROR  -->  DU_APP : DuProcMacStatsRsp: Failed in %s at line %d", __func__, __LINE__);
+      }
 
       DU_FREE_SHRABL_BUF(pst->region, pst->pool, statsRsp, sizeof(MacStatsRsp));
-      return ROK;
    }
-
-   DU_LOG("\nERROR  -->  DU_APP : DuProcMacStatsRsp: Received NULL Pointer");
-   return RFAILED;
+   else
+   {
+      DU_LOG("\nERROR  -->  DU_APP : DuProcMacStatsRsp: Received NULL Pointer");
+   }
+   return ret;
 }
 
 /*******************************************************************
@@ -2236,6 +2241,8 @@ uint8_t DuProcMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp)
  * ****************************************************************/
 uint8_t DuProcMacStatsInd(Pst *pst, MacStatsInd *statsInd)
 {
+   uint8_t ret = RFAILED;
+
    if(statsInd)
    {
 #ifdef DEBUG_PRINT   
@@ -2250,15 +2257,19 @@ uint8_t DuProcMacStatsInd(Pst *pst, MacStatsInd *statsInd)
 #endif      
 
       /* Extract statistics from statistics indication message and store in E2 DB */
-      e2ProcStatsInd(statsInd);
+      if((ret = e2ProcStatsInd(statsInd)) != ROK)
+      {
+          DU_LOG("\nINFO  -->  DU_APP : Failed in %s at line %d", __func__, __LINE__);
+      }
 
       /* Free statistics indication */
       DU_FREE_SHRABL_BUF(pst->region, pst->pool, statsInd, sizeof(MacStatsInd));
-      return ROK;
    }
-   
-   DU_LOG("\nINFO  -->  DU_APP : DuProcMacStatsInd: Received NULL Pointer");
-   return RFAILED;
+   else
+   {
+      DU_LOG("\nINFO  -->  DU_APP : DuProcMacStatsInd: Received NULL Pointer");
+   }
+   return ret;
 }
 
 /**********************************************************************
index 4a1bda7..1ea0d77 100644 (file)
@@ -72,6 +72,15 @@ bool duChkTmr(PTR cb, int16_t tmrEvnt)
          }
          break;
       }
+      case EVENT_RIC_SUBSCRIPTION_REPORTING_TMR:
+      {
+         if(((RicSubscription *)cb)->ricSubsReportTimer.tmrEvnt == EVENT_RIC_SUBSCRIPTION_REPORTING_TMR)
+         {
+             DU_LOG("\nERROR  -->  DU_APP : duChkTmr: Timer already running for event [%d]", tmrEvnt);
+             return TRUE;
+         }
+         break;
+      }
       default:
       {
          DU_LOG("\nERROR  -->  DU_APP : duChkTmr: Invalid tmr Evnt [%d]", tmrEvnt);
@@ -91,7 +100,7 @@ bool duChkTmr(PTR cb, int16_t tmrEvnt)
  * @return  Void
 */
 
-void duStartTmr(PTR cb, int16_t tmrEvnt, uint8_t timerValue)
+void duStartTmr(PTR cb, int16_t tmrEvnt, uint32_t timerValue)
 {
    CmTmrArg arg;
    arg.wait = 0;
@@ -100,7 +109,7 @@ void duStartTmr(PTR cb, int16_t tmrEvnt, uint8_t timerValue)
    {
       case EVENT_E2_SETUP_TMR:
       {
-         CmTimer *e2SetupTimer;
+         CmTimer *e2SetupTimer = NULLP;
          e2SetupTimer = ((CmTimer *)cb);
          TMR_CALCUATE_WAIT(arg.wait, timerValue, duCb.duTimersInfo.tmrRes);
 
@@ -110,7 +119,7 @@ void duStartTmr(PTR cb, int16_t tmrEvnt, uint8_t timerValue)
       }
       case EVENT_RIC_SERVICE_UPDATE_TMR:
       {
-         RicServiceUpdateTimer *ricServiceUpdateTimer;
+         RicServiceUpdateTimer *ricServiceUpdateTimer = NULLP;
          ricServiceUpdateTimer= ((RicServiceUpdateTimer*)cb);
          TMR_CALCUATE_WAIT(arg.wait, timerValue, duCb.duTimersInfo.tmrRes);
 
@@ -128,9 +137,20 @@ void duStartTmr(PTR cb, int16_t tmrEvnt, uint8_t timerValue)
          arg.max = MAX_E2_NODE_CONFIG_UPDATE_TMR;
          break;
       }
+      case EVENT_RIC_SUBSCRIPTION_REPORTING_TMR:
+      {
+         RicSubscription *ricSubscription = NULLP;
+         ricSubscription = ((RicSubscription*)cb);
+         TMR_CALCUATE_WAIT(arg.wait, timerValue, duCb.duTimersInfo.tmrRes);
+
+         arg.timers = &ricSubscription->ricSubsReportTimer;
+         arg.max = MAX_RIC_SUBSCRIPTION_REPORTING_TMR;
+         break;
+      }
       default:
       {
          DU_LOG("\nERROR  -->  DU : duStartTmr: Invalid tmr Evnt [%d]", tmrEvnt);
+         return;
       }
    }
 
@@ -186,6 +206,14 @@ void duTmrExpiry(PTR cb,int16_t tmrEvnt)
          BuildAndSendE2NodeConfigUpdate(&cfgUpdateTimer->configList);
          break;
       }
+      case EVENT_RIC_SUBSCRIPTION_REPORTING_TMR:
+      {
+         RicSubscription *ricSubscription = NULLP;
+
+         ricSubscription = ((RicSubscription *)cb);
+         E2apHdlRicSubsReportTmrExp(ricSubscription);
+         break;
+      }
       default:
       {
          DU_LOG("\nERROR  -->  DU : duStartTmr: Invalid tmr Evnt [%d]", tmrEvnt);
index 809b087..54aced7 100644 (file)
@@ -21,7 +21,7 @@
 
 short int duActvTmr(Ent ent,Inst inst); 
 bool duChkTmr(PTR cb, int16_t tmrEvnt);
-void duStartTmr(PTR cb, int16_t tmrEvnt, uint8_t timerValue);
+void duStartTmr(PTR cb, int16_t tmrEvnt, uint32_t timerValue);
 
 /**********************************************************************
   End of file
index 0d8555c..0ee331c 100644 (file)
@@ -1107,8 +1107,8 @@ uint8_t fillActionToBeSetup(RICaction_ToBeSetup_ItemIEs_t *actionItem, RicSubscr
       actionItem->value.present =  RICaction_ToBeSetup_ItemIEs__value_PR_RICaction_ToBeSetup_Item;
       
       /* RIC Action ID */
-      actionItem->value.choice.RICaction_ToBeSetup_Item.ricActionID = ++ricActionId;
-      ricSubsDb->actionSequence[ricActionId-1].id = \
+      actionItem->value.choice.RICaction_ToBeSetup_Item.ricActionID = ricActionId++;
+      ricSubsDb->actionSequence[ricActionId].actionId = \
          actionItem->value.choice.RICaction_ToBeSetup_Item.ricActionID;
 
       /* RIC Action Type */
@@ -1131,7 +1131,8 @@ uint8_t fillActionToBeSetup(RICaction_ToBeSetup_ItemIEs_t *actionItem, RicSubscr
       return ROK;
    }
 
-   memset(&ricSubsDb->actionSequence[ricActionId-1], 0, sizeof(ActionInfo));
+   memset(&ricSubsDb->actionSequence[ricActionId], 0, sizeof(ActionInfo));
+   ricSubsDb->actionSequence[ricActionId].actionId = -1;
    return RFAILED;
 }
 
@@ -1253,6 +1254,7 @@ uint8_t fillEventTriggerDef(RICeventTriggerDefinition_t *ricEventTriggerDef)
 
 uint8_t BuildRicSubsDetails(RICsubscriptionDetails_t *subsDetails, RicSubscription *ricSubsDb)
 {
+   uint8_t actionIdx = 0;
    uint8_t elementCnt = 0;
    uint8_t elementIdx = 0;
 
@@ -1294,6 +1296,11 @@ uint8_t BuildRicSubsDetails(RICsubscriptionDetails_t *subsDetails, RicSubscripti
       if(elementIdx < elementCnt)
          break;
 
+      for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
+      {
+         ricSubsDb->actionSequence[actionIdx].actionId = -1;
+      }
+
       elementIdx = 0;
       if(fillActionToBeSetup((RICaction_ToBeSetup_ItemIEs_t *)subsDetails->ricAction_ToBeSetup_List.list.array[elementIdx], \
          ricSubsDb) != ROK)
@@ -1542,10 +1549,11 @@ void ProcRicSubscriptionResponse(uint32_t duId, RICsubscriptionResponse_t  *ricS
                                  if((ranFuncDb->subscriptionList[subsIdx].requestId.requestorId == ricReqId.requestorId) &&
                                        (ranFuncDb->subscriptionList[subsIdx].requestId.instanceId == ricReqId.instanceId))
                                  {
-                                    if(ranFuncDb->subscriptionList[subsIdx].actionSequence[actionId-1].id == actionId)
+                                    if(ranFuncDb->subscriptionList[subsIdx].actionSequence[actionId].actionId == actionId)
                                     {
-                                       memset(&ranFuncDb->subscriptionList[subsIdx].actionSequence[actionId-1], 0, \
+                                       memset(&ranFuncDb->subscriptionList[subsIdx].actionSequence[actionId], 0, \
                                           sizeof(ActionInfo));
+                                       ranFuncDb->subscriptionList[subsIdx].actionSequence[actionId].actionId = -1;
                                        ranFuncDb->subscriptionList[subsIdx].numOfActions--;
                                        break;
                                     }
@@ -3302,7 +3310,7 @@ void E2APMsgHdlr(uint32_t *duId, Buffer *mBuf)
                   }
                case InitiatingMessageE2__value_PR_RICindication:
                   {
-                     DU_LOG("\nINFO  -->  E2AP : RIC Indication Acknowledged");
+                     DU_LOG("\nINFO  -->  E2AP : RIC Indication received");
                      break;
                   }
                case InitiatingMessageE2__value_PR_RICserviceUpdate:
index c8e5217..b4c159e 100644 (file)
@@ -102,7 +102,7 @@ typedef struct
 
 typedef struct
 {
-   uint8_t           id;
+   int16_t         actionId;
 }ActionInfo;
 
 typedef struct ricSubscription