[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-532] RIC Subscription Delete Required 61/11861/6
authorlal.harshita <Harshita.Lal@radisys.com>
Fri, 6 Oct 2023 08:48:22 +0000 (14:18 +0530)
committerlal.harshita <Harshita.Lal@radisys.com>
Tue, 10 Oct 2023 09:50:16 +0000 (15:20 +0530)
Change-Id: I26df256e824d5202b50f4a015d23b5bff4347abb
Signed-off-by: lal.harshita <Harshita.Lal@radisys.com>
src/du_app/du_cfg.c
src/du_app/du_e2ap_mgr.c
src/du_app/du_e2ap_mgr.h
src/du_app/du_e2ap_msg_hdl.c
src/ric_stub/ric_e2ap_msg_hdl.c
src/ric_stub/ric_stub.h

index 762a5c2..766c032 100644 (file)
@@ -735,6 +735,8 @@ uint8_t readCfg()
       
       duCb.e2apDb.ranFunction[ranFuncIdx].ricIndicationHeaderFormat = RIC_INDICATION_HEADER_FORMAT;
       duCb.e2apDb.ranFunction[ranFuncIdx].ricIndicationMessageFormat = RIC_INDICATION_MESSAGE_FORMAT; 
+
+      cmLListInit(&duCb.e2apDb.ranFunction[ranFuncIdx].subscriptionList);
    }
    memset(duCb.e2apDb.e2TransInfo.e2InitTransaction, 0, MAX_NUM_TRANSACTION * sizeof(E2TransInfo));
    memset(duCb.e2apDb.e2TransInfo.ricInitTransaction, 0, MAX_NUM_TRANSACTION * sizeof(E2TransInfo));
index 6bdbe58..f813ef0 100644 (file)
@@ -640,6 +640,9 @@ uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp)
    }
    else
    {
+      /* Once RIC subscription is successful, mark the config action as unknown */
+      ricSubscriptionInfo->action = CONFIG_UNKNOWN;
+
       /* Start RIC Subscription reporting timer */
       switch(ricSubscriptionInfo->eventTriggerDefinition.formatType)
       {
@@ -1058,7 +1061,6 @@ void deleteMeasuredValueList(CmLListCp *measuredValueList)
  * @return void 
  *
  * ****************************************************************/
-
 void deleteMeasurementInfoList(CmLListCp *measInfoList)
 {
    CmLList *measInfoNode = NULLP;
@@ -1117,6 +1119,7 @@ void deleteActionSequence(ActionInfo *action)
    memset(action, 0, sizeof(ActionInfo));
    action->actionId = -1;
 }
+
 /******************************************************************
  *
  * @brief Delete Ric subscription node 
@@ -1132,7 +1135,6 @@ void deleteActionSequence(ActionInfo *action)
  * @return void 
  *
  * ****************************************************************/
-
 void deleteRicSubscriptionNode(CmLList *subscriptionNode)
 {
    uint8_t actionIdx=0;
@@ -1174,8 +1176,6 @@ void deleteRicSubscriptionNode(CmLList *subscriptionNode)
  * @return void 
  *
  * ****************************************************************/
-
-
 void deleteRicSubscriptionList(CmLListCp *subscriptionList)
 {
    CmLList *subscriptionNode=NULLP;
@@ -1190,6 +1190,53 @@ void deleteRicSubscriptionList(CmLListCp *subscriptionList)
    }
 }
 
+/*******************************************************************
+ *
+ * @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;
+         }
+      }
+   }
+}
+
 /**********************************************************************
   End of file
  **********************************************************************/
index d7f9de7..3102c01 100644 (file)
@@ -403,6 +403,8 @@ typedef struct
    uint8_t                numOfActions;
    ActionInfo             actionSequence[MAX_RIC_ACTION];  
    CmTimer                ricSubsReportTimer;
+   ConfigType             action;
+   E2FailureCause         failureCause; /* Used only when a subscription is required to be deleted */
 }RicSubscription;
 
 typedef struct rejectedAction
@@ -493,6 +495,7 @@ RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *r
 RanFunction *fetchRanFuncFromRanFuncId(uint16_t ranFuncId);
 uint8_t fetchSubsInfoFromSubsId(uint64_t subscriptionId, RanFunction **ranFuncDb, CmLList **ricSubscriptionNode, \
    RicSubscription **ricSubscriptionInfo);
+void fetchRicSubsToBeDeleted(CmLListCp *ricSubsToBeDelList);
 
 uint8_t fillRicSubsInMacStatsReq(MacStatsReq *macStatsReq, RicSubscription* ricSubscriptionInfo);
 uint8_t e2ProcStatsRsp(MacStatsRsp *statsRsp);
index 6f366b6..acb06a8 100644 (file)
@@ -2540,8 +2540,8 @@ uint8_t extractMeasInfoList(CmLListCp *measInfoSupportedList, MeasurementInfoLis
 {
    uint8_t elementIdx = 0;
    MeasurementInfoForAction *measInfoSupportedDb = NULLP;
-   MeasurementInfo *measInfoSubscribedDb = NULLP, *measInfoToDel = NULLP;
-   CmLList *supportedMeasNode = NULLP, *measToAddNode = NULLP, *measToDelNode = NULLP;;
+   MeasurementInfo *measInfoSubscribedDb = NULLP;
+   CmLList *supportedMeasNode = NULLP, *measToAddNode = NULLP;
    MeasurementInfoItem_t *measItem = NULLP;
 
    /* Validate Measurement list is supported by E2 node. 
@@ -2975,6 +2975,7 @@ uint8_t procRicSubscriptionRequest(E2AP_PDU_t *e2apMsg)
    if(ret == ROK)
    {
       cmInitTimers(&(ricSubscriptionInfo->ricSubsReportTimer), 1);
+      ricSubscriptionInfo->action = CONFIG_ADD;
 
       /* Add RAN subcription detail to RAN function */
       DU_ALLOC(ricSubscriptionNode, sizeof(CmLList));
@@ -6747,6 +6748,284 @@ void procRicSubscriptionModificationRefuse(E2AP_PDU_t *e2apMsg)
    return;
 }
 
+/*******************************************************************
+ *
+ * @brief Free RIC Subscription Delete Required Message
+ *
+ * @details
+ *
+ *    Function : FreeRicSubscriptionDeleteRequired
+ *
+ * Functionality:  Free RIC Subscription Delete Required
+ *
+ * @param  E2AP Message PDU
+ * @return void
+ *
+ ******************************************************************/
+void FreeRicSubscriptionDeleteRequired(E2AP_PDU_t *e2apMsg, CmLListCp *ricSubsToBeDelList)
+{
+   uint8_t ieIdx = 0, arrIdx = 0;
+   RICsubscriptionDeleteRequired_t *ricSubsDelRqd = NULLP;
+   RICsubscriptionDeleteRequired_IEs_t *ricSubsDelRqdIe = NULLP;
+   RICsubscription_List_withCause_t *ricSubsList = NULLP;
+   CmLList *subsNode = NULLP;
+
+   if(e2apMsg)
+   {
+      if(e2apMsg->choice.initiatingMessage)
+      {
+         ricSubsDelRqd = &e2apMsg->choice.initiatingMessage->value.choice.RICsubscriptionDeleteRequired;
+         if(ricSubsDelRqd->protocolIEs.list.array)
+         {
+            for(ieIdx = 0; ieIdx < ricSubsDelRqd->protocolIEs.list.count; ieIdx++)
+            {
+               if(ricSubsDelRqd->protocolIEs.list.array[ieIdx])
+               {
+                  ricSubsDelRqdIe = ricSubsDelRqd->protocolIEs.list.array[ieIdx];
+                  switch(ricSubsDelRqdIe->id)
+                  {
+                     case ProtocolIE_IDE2_id_RICsubscriptionToBeRemoved:
+                        {
+                           ricSubsList = &ricSubsDelRqdIe->value.choice.RICsubscription_List_withCause;
+                           if(ricSubsList->list.array)
+                           {
+                              for(arrIdx = 0; arrIdx < ricSubsList->list.count; arrIdx++)
+                              {
+                                 DU_FREE(ricSubsList->list.array[ieIdx], sizeof(RICsubscription_withCause_ItemIEs_t));
+                              }
+                              DU_FREE(ricSubsList->list.array, ricSubsList->list.size);
+                           }
+                           break;
+                        }
+                  }
+                  DU_FREE(ricSubsDelRqd->protocolIEs.list.array[ieIdx], sizeof(RICsubscriptionDeleteRequired_IEs_t));
+               }
+            }
+            DU_FREE(ricSubsDelRqd->protocolIEs.list.array, ricSubsDelRqd->protocolIEs.list.size);
+         }
+         DU_FREE(e2apMsg->choice.initiatingMessage, sizeof(InitiatingMessageE2_t));
+      }
+      DU_FREE(e2apMsg, sizeof(E2AP_PDU_t));;
+   }
+
+   if(ricSubsToBeDelList)
+   {
+      CM_LLIST_FIRST_NODE(ricSubsToBeDelList, subsNode);
+      while(subsNode)
+      {
+         cmLListDelFrm(ricSubsToBeDelList, subsNode);
+         DU_FREE(subsNode, sizeof(CmLList));
+         CM_LLIST_FIRST_NODE(ricSubsToBeDelList, subsNode);
+      }
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Fill list of RIC subscriptions required to be deleted
+ *    with the cause of deletion
+ *
+ * @details
+ *
+ *    Function : fillRicSubsListWithCause
+ *
+ * Functionality:  Fill list of RIC subscriptions required to be 
+ *    deleted with the cause of deletion
+ *
+ * @param  E2AP Message PDU
+ * @return void
+ *
+ ******************************************************************/
+uint8_t fillRicSubsListWithCause(RICsubscription_List_withCause_t *ricSubsList, CmLListCp ricSubsToBeDelList)
+{
+   uint16_t ieIdx = 0;
+   CmLList *subsNode = NULLP;
+   RicSubscription *subsInfo = NULLP;
+   RICsubscription_withCause_ItemIEs_t *subsItemIe = NULLP;
+   RICsubscription_withCause_Item_t *subsItem = NULLP;
+
+   ricSubsList->list.count = ricSubsToBeDelList.count;
+   ricSubsList->list.size = ricSubsList->list.count * sizeof(RICsubscription_withCause_ItemIEs_t *);
+   DU_ALLOC(ricSubsList->list.array, ricSubsList->list.size);
+   if(!ricSubsList->list.array)
+   {
+      DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation for E2AP-PDU failed at line %d",__func__, __LINE__);
+      return RFAILED;
+   }
+
+   CM_LLIST_FIRST_NODE(&ricSubsToBeDelList, subsNode);
+   while(subsNode && (ieIdx < ricSubsList->list.count))
+   {
+      subsInfo = (RicSubscription *)subsNode->node;
+      DU_ALLOC(ricSubsList->list.array[ieIdx], sizeof(RICsubscription_withCause_ItemIEs_t));
+      if(!ricSubsList->list.array[ieIdx])
+      {
+         DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation for E2AP-PDU failed at line %d",__func__, __LINE__);
+         return RFAILED;
+      }
+
+      subsItemIe = (RICsubscription_withCause_ItemIEs_t *)ricSubsList->list.array[ieIdx];
+      subsItemIe->id = ProtocolIE_IDE2_id_RICsubscription_withCause_Item;
+      subsItemIe->criticality = CriticalityE2_ignore;
+      subsItemIe->value.present = RICsubscription_withCause_ItemIEs__value_PR_RICsubscription_withCause_Item;
+
+      subsItem = & subsItemIe->value.choice.RICsubscription_withCause_Item;
+      subsItem->ricRequestID.ricRequestorID = subsInfo->requestId.requestorId;
+      subsItem->ricRequestID.ricInstanceID = subsInfo->requestId.instanceId;
+      subsItem->ranFunctionID = subsInfo->ranFuncId;
+      fillE2Cause(&subsItem->cause, subsInfo->failureCause);
+
+      ieIdx++;
+      subsNode = subsNode->next;
+   }
+
+   return ROK;   
+}
+
+/*******************************************************************
+ *
+ * @brief Builds and Send RIC Subscription delete required
+ *
+ * @details
+ *
+ *    Function : BuildAndSendRicSubscriptionDeleteRequired
+ *
+ * Functionality: Build and send RIC subscription delete required.
+ *    There can be 2 approaches to trigger following. One of these
+ *    approaches may/may not be implemented in future:
+ *    1. It can be triggerred immediately when a RIC subscription's
+ *       End Time has expired. In this case, only this subscription's
+ *       info will be sent in this message.
+ *       Since we have not yet added support to execute RIC 
+ *       Subscription based on Start Time and End Timer, this message is 
+ *       not triggered anywhere from DU APP yet.
+ *    2. Another approach is to have a periodic timer to check subscription
+ *       status running in background.
+ *       When RIC Subscription End Time expires, this subscription is
+ *       marked to be deleted. Later when this background timer expires,
+ *       a RIC Subscription delete required is sent with all the 
+ *       subscription's info which is marked to be deleted.
+ *    The following function is implemented keeping in mind the second 
+ *    approach.
+ *
+ * @params[in] 
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t BuildAndSendRicSubscriptionDeleteRequired()
+{
+   uint8_t elementCnt = 0, ieIdx = 0, ret = RFAILED;
+   E2AP_PDU_t         *e2apMsg = NULLP;
+   RICsubscriptionDeleteRequired_t *ricSubsDelRqd = NULLP;
+   RICsubscriptionDeleteRequired_IEs_t *ricSubsDelRqdIe = NULLP;
+   asn_enc_rval_t     encRetVal;        /* Encoder return value */
+   CmLListCp ricSubsToBeDelList;
+
+   while(true)
+   {
+      /* Check if there are any RIC subscriptions to be deleted */
+      cmLListInit(&ricSubsToBeDelList);
+      fetchRicSubsToBeDeleted(&ricSubsToBeDelList);
+      if(ricSubsToBeDelList.count == 0)
+      {
+         DU_LOG("\nDEBUG  -->  E2AP : %s: No RIC subscriptions are required to be deleted", __func__);
+         return ROK;
+      }
+
+      DU_LOG("\nINFO   -->  E2AP : Building RIC Subscription Delete Required Message\n");
+
+      DU_ALLOC(e2apMsg, sizeof(E2AP_PDU_t));
+      if(e2apMsg == NULLP)
+      {
+         DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation for E2AP-PDU failed at line %d",__func__, __LINE__);
+         break;
+      }
+
+      e2apMsg->present = E2AP_PDU_PR_initiatingMessage;
+      DU_ALLOC(e2apMsg->choice.initiatingMessage, sizeof(InitiatingMessageE2_t));
+      if(e2apMsg->choice.initiatingMessage == NULLP)
+      {
+         DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation for E2AP-PDU failed at line %d",__func__, __LINE__);
+         break;
+      }
+      e2apMsg->choice.initiatingMessage->procedureCode = ProcedureCodeE2_id_RICsubscriptionDeleteRequired;
+      e2apMsg->choice.initiatingMessage->criticality = CriticalityE2_reject;
+      e2apMsg->choice.initiatingMessage->value.present = InitiatingMessageE2__value_PR_RICsubscriptionDeleteRequired;
+
+      ricSubsDelRqd = &e2apMsg->choice.initiatingMessage->value.choice.RICsubscriptionDeleteRequired;
+      
+      elementCnt = 1;
+      ricSubsDelRqd->protocolIEs.list.count = elementCnt;
+      ricSubsDelRqd->protocolIEs.list.size = elementCnt * sizeof(RICsubscriptionDeleteRequired_IEs_t *);
+
+      DU_ALLOC(ricSubsDelRqd->protocolIEs.list.array, ricSubsDelRqd->protocolIEs.list.size);
+      if(ricSubsDelRqd->protocolIEs.list.array == NULLP)
+      {
+         DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation failed for array elements at line %d",__func__, __LINE__);
+         break;
+      }
+      
+      for(ieIdx = 0; ieIdx < elementCnt; ieIdx++)
+      {
+         DU_ALLOC(ricSubsDelRqd->protocolIEs.list.array[ieIdx], sizeof(RICsubscriptionDeleteRequired_IEs_t));
+         if(ricSubsDelRqd->protocolIEs.list.array[ieIdx] == NULLP)
+         {
+            DU_LOG("\nERROR  -->  E2AP : %s: Memory allocation failed for index [%d] at line %d", \
+               __func__, ieIdx, __LINE__);
+            break;
+         }
+      }
+      if(ieIdx < elementCnt)
+         break;
+
+      ieIdx = 0;
+      ricSubsDelRqdIe = ricSubsDelRqd->protocolIEs.list.array[ieIdx];
+      ricSubsDelRqdIe->id = ProtocolIE_IDE2_id_RICsubscriptionToBeRemoved;
+      ricSubsDelRqdIe->criticality = CriticalityE2_ignore;
+      ricSubsDelRqdIe->value.present = RICsubscriptionDeleteRequired_IEs__value_PR_RICsubscription_List_withCause;
+      if(fillRicSubsListWithCause(&ricSubsDelRqdIe->value.choice.RICsubscription_List_withCause, ricSubsToBeDelList)\
+            != ROK)
+      {
+         DU_LOG("\nERROR  -->  E2AP : %s: Failed to fill RIC Subscription list with cause", __func__);
+         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);
+      if(encRetVal.encoded == ENCODE_FAIL)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Could not encode RIC Subscription Delete Required Message (at %s)\n",\
+               encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+         break;
+      }
+      else
+      {
+         DU_LOG("\nDEBUG  -->  E2AP : Created APER encoded buffer for RIC Subscription Delete Required Message \n");
+#ifdef DEBUG_ASN_PRINT
+         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("\nERROR   -->  E2AP : Failed to send RIC Susbcription Delete Required Message");      
+
+      }
+      ret = ROK;
+      break;
+   }
+
+   FreeRicSubscriptionDeleteRequired(e2apMsg, &ricSubsToBeDelList);    
+   return ret;
+}
+
 /*******************************************************************
  *
  * @brief Handles received E2AP message and sends back response  
index e648cf6..8a6244c 100644 (file)
@@ -176,20 +176,30 @@ RanFunction *fetchRanFuncFromRanFuncId(DuDb *duDb, uint16_t ranFuncId)
  *         NULL, in case of failure
  *
  * ****************************************************************/
-RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb)
+RicSubscription *fetchSubsInfoFromRicReqId(RicRequestId ricReqId, RanFunction *ranFuncDb, CmLList **ricSubscriptionNode)
 {
-   uint8_t subsIdx = 0;
    RicSubscription *ricSubscriptionInfo = NULLP;
 
-   for(subsIdx = 0; subsIdx < ranFuncDb->numOfSubscription; subsIdx++)
+   /* Fetch subscription detail in RAN Function DB */
+   CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, *ricSubscriptionNode);
+   while(*ricSubscriptionNode)
    {
-      if((ranFuncDb->subscriptionList[subsIdx].requestId.requestorId == ricReqId.requestorId) &&
-            (ranFuncDb->subscriptionList[subsIdx].requestId.instanceId == ricReqId.instanceId))
+      ricSubscriptionInfo = (RicSubscription *)((*ricSubscriptionNode)->node);
+      if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) &&
+            (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId))
       {
-         ricSubscriptionInfo = &ranFuncDb->subscriptionList[subsIdx];
          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;
 }
 
@@ -1354,9 +1364,8 @@ uint8_t fillEventTriggerDef(RICeventTriggerDefinition_t *ricEventTriggerDef)
  *
  * ****************************************************************/
 
-uint8_t BuildRicSubsDetails(RICsubscriptionDetails_t *subsDetails, RicSubscription *ricSubsDb)
+uint8_t BuildRicSubsDetails(RICsubscriptionDetails_t *subsDetails, RicSubscription *ricSubsInfo)
 {
-   uint8_t actionIdx = 0;
    uint8_t elementCnt = 0;
    uint8_t elementIdx = 0;
 
@@ -1398,14 +1407,10 @@ 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)
+         ricSubsInfo) != ROK)
       {
          DU_LOG("\nERROR  -->  E2AP : Failed at [%s] : line [%d]", __func__, __LINE__);
          break;
@@ -1433,15 +1438,30 @@ uint8_t BuildRicSubsDetails(RICsubscriptionDetails_t *subsDetails, RicSubscripti
 uint8_t BuildAndSendRicSubscriptionReq(DuDb *duDb)
 {
    uint8_t         ret = RFAILED;
+   uint8_t         elementCnt = 0;
+   uint8_t         idx = 0;
+   uint8_t         actionIdx = 0;
+   asn_enc_rval_t  encRetVal;        /* Encoder return value */
    E2AP_PDU_t                 *e2apRicMsg = NULL;
    RICsubscriptionRequest_t   *ricSubscriptionReq;
-   uint8_t         elementCnt;
-   uint8_t         idx;
-   asn_enc_rval_t  encRetVal;        /* Encoder return value */
-   RanFunction     *ranFuncDb = &duDb->ranFunction[0];
+   RanFunction  *ranFuncDb = &duDb->ranFunction[0];
+   CmLList *ricSubsNode = NULLP;
+   RicSubscription *ricSubsInfo = NULLP;
 
    DU_LOG("\nINFO   -->  E2AP : Building RIC Subscription Request\n");
 
+   /* Allocate memory to store RIC subscription info in RIC DB */
+   RIC_ALLOC(ricSubsInfo, sizeof(RicSubscription));
+   if(!ricSubsInfo)
+   {
+      DU_LOG("\nERROR  -->  E2AP : Memory allocation failed at [%s] : line [%d]", __func__, __LINE__);
+      return RFAILED;
+   }
+   for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
+   {
+      ricSubsInfo->actionSequence[actionIdx].actionId = -1;
+   }
+
    while(true)
    {
       RIC_ALLOC(e2apRicMsg, sizeof(E2AP_PDU_t));
@@ -1495,7 +1515,7 @@ uint8_t BuildAndSendRicSubscriptionReq(DuDb *duDb)
       ricSubscriptionReq->protocolIEs.list.array[idx]->value.present =\
                                                                       RICsubscriptionRequest_IEs__value_PR_RICrequestID;
       if(BuildNewRicRequestId(&ricSubscriptionReq->protocolIEs.list.array[idx]->value.choice.RICrequestID, \
-         &ranFuncDb->subscriptionList[ranFuncDb->numOfSubscription].requestId) != ROK)
+         &ricSubsInfo->requestId) != ROK)
       {
          DU_LOG("\nERROR  -->  E2AP : Failed at [%s] : Line [%d]", __func__, __LINE__);
          break;
@@ -1517,7 +1537,7 @@ uint8_t BuildAndSendRicSubscriptionReq(DuDb *duDb)
       ricSubscriptionReq->protocolIEs.list.array[idx]->value.present =\
                                                                       RICsubscriptionRequest_IEs__value_PR_RICsubscriptionDetails;
       if(BuildRicSubsDetails(&(ricSubscriptionReq->protocolIEs.list.array[idx]->value.choice.RICsubscriptionDetails),\
-         &ranFuncDb->subscriptionList[ranFuncDb->numOfSubscription]) != ROK)
+         ricSubsInfo) != ROK)
       {
          DU_LOG("\nERROR  -->  E2AP : Failed at [%s] : Line [%d]", __func__, __LINE__);
          break;
@@ -1551,13 +1571,26 @@ uint8_t BuildAndSendRicSubscriptionReq(DuDb *duDb)
          break;
       }
 
-      ranFuncDb->numOfSubscription++;
+      /* Add RIC Subscription Info to RAN Function's RIC Subscription List */
+      RIC_ALLOC(ricSubsNode , sizeof(CmLList));
+      if(!ricSubsNode)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation failed at [%s] : line [%d]", __func__, __LINE__);
+         break;
+      }
+      ricSubsNode->node = (PTR)ricSubsInfo;
+      cmLListAdd2Tail(&ranFuncDb->subscriptionList, ricSubsNode);
+
       ret = ROK;
       break;
    }
 
    if(ret == RFAILED)
-      memset(&ranFuncDb->subscriptionList[ranFuncDb->numOfSubscription], 0, sizeof(RicSubscription));
+   {
+      RIC_FREE(ricSubsInfo, sizeof(RicSubscription));
+      RIC_FREE(ricSubsNode , sizeof(CmLList));
+   }
+
    FreeRicSubscriptionReq(e2apRicMsg);
    return ret;
 }
@@ -1585,6 +1618,7 @@ void ProcRicSubscriptionResponse(uint32_t duId, RICsubscriptionResponse_t  *ricS
    RicRequestId ricReqId;
    RanFunction  *ranFuncDb = NULLP;
    RicSubscription *ricSubs = NULLP;
+   CmLList *ricSubsNode = NULLP;
    ActionInfo *action = NULLP;
    RICsubscriptionResponse_IEs_t *ricSubsRspIe = NULLP;
    RICaction_NotAdmitted_List_t *notAdmitList = NULLP;
@@ -1645,7 +1679,7 @@ void ProcRicSubscriptionResponse(uint32_t duId, RICsubscriptionResponse_t  *ricS
                               value.choice.RICaction_NotAdmitted_Item.ricActionID;
 
                            /* Remove action from RAN Function's subscription list */
-                           ricSubs = fetchSubsInfoFromRicReqId(ricReqId, ranFuncDb);
+                           ricSubs = fetchSubsInfoFromRicReqId(ricReqId, ranFuncDb, &ricSubsNode);
                            if(ricSubs)
                            {
                               action = fetchActionInfoFromActionId(actionId, ricSubs);
@@ -1903,6 +1937,7 @@ uint8_t ProcE2SetupReq(uint32_t *duId, E2setupRequest_t  *e2SetupReq)
                               ranFunItem = &ranFuncItemIe->value.choice.RANfunction_Item;
                               duDb->ranFunction[ranFunItem->ranFunctionID-1].id = ranFunItem->ranFunctionID; 
                               duDb->ranFunction[ranFunItem->ranFunctionID-1].revisionCounter = ranFunItem->ranFunctionRevision; 
+                              cmLListInit(&duDb->ranFunction[ranFunItem->ranFunctionID-1].subscriptionList);
                               duDb->numOfRanFunction++;
                            }
                         }
@@ -2987,11 +3022,12 @@ void ProcRicServiceUpdate(uint32_t duId, RICserviceUpdate_t *ricServiceUpdate)
  ******************************************************************/
 uint8_t ProcRicSubscriptionFailure(uint32_t duId, RICsubscriptionFailure_t *ricSubscriptionFailure)
 {
-   uint8_t ieIdx = 0, duIdx = 0, subsIdx = 0;
+   uint8_t ieIdx = 0, duIdx = 0;
    uint8_t ranFuncId = 0;
    DuDb    *duDb = NULLP;
    RanFunction *ranFuncDb = NULLP;
    RicSubscription *ricSubs = NULLP;
+   CmLList *ricSubsNode = NULLP;
    RicRequestId ricReqId;
    RICsubscriptionFailure_IEs_t *ricSubsFailIe = NULLP;
 
@@ -3034,10 +3070,11 @@ uint8_t ProcRicSubscriptionFailure(uint32_t duId, RICsubscriptionFailure_t *ricS
                      else
                      {
                         /* Remove subscription entry from RAN Function */
-                        ricSubs = fetchSubsInfoFromRicReqId(ricReqId, ranFuncDb);
+                        ricSubs = fetchSubsInfoFromRicReqId(ricReqId, ranFuncDb, &ricSubsNode);
                         if(ricSubs)
                         {
-                           memset(&ranFuncDb->subscriptionList[subsIdx], 0, sizeof(RicSubscription));
+                           cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubsNode);
+                           deleteRicSubscriptionNode(ricSubsNode);
                         }
                      }
                      break; 
@@ -3781,6 +3818,7 @@ uint8_t ProcRicSubsModReqd(uint32_t duId, RICsubscriptionModificationRequired_t
    RicRequestId ricReqId;
    RanFunction *ranFuncDb = NULLP;
    RicSubscription *ricSubs = NULLP;
+   CmLList *ricSubsNode = NULLP;
    ActionInfo *action = NULLP;
    RICsubscriptionModificationRequired_IEs_t *ricSubsModReqdIe = NULLP;
    RICactions_RequiredToBeModified_List_t *actionToBeModList = NULLP;
@@ -3823,7 +3861,7 @@ uint8_t ProcRicSubsModReqd(uint32_t duId, RICsubscriptionModificationRequired_t
                   return RFAILED;
                }
 
-               ricSubs = fetchSubsInfoFromRicReqId(ricReqId, ranFuncDb);
+               ricSubs = fetchSubsInfoFromRicReqId(ricReqId, ranFuncDb, &ricSubsNode);
                if(!ricSubs)
                {
                   /* If RAN Function not found, send RIC Subscription modification refuse to DU */
@@ -4265,36 +4303,65 @@ uint8_t BuildAndSendResetRequest(DuDb *duDb, CauseE2_PR causePresent, uint8_t re
    return ret;
 }
 
+/******************************************************************
+ *
+ * @brief Delete Ric subscription node
+ *
+ * @details
+ *
+ *    Function : deleteRicSubscriptionNode
+ *
+ *    Functionality: Delete Ric subscription node
+ *
+ * @params[in] Ric subscription info
+ *
+ * @return void
+ *
+ * ****************************************************************/
+void deleteRicSubscriptionNode(CmLList *subscriptionNode)
+{
+   uint8_t actionIdx=0;
+   RicSubscription *ricSubscriptionInfo = NULLP;
+
+   ricSubscriptionInfo = (RicSubscription*)subscriptionNode->node;
+
+   for(actionIdx = 0; actionIdx < MAX_RIC_ACTION; actionIdx++)
+   {
+      if(ricSubscriptionInfo->actionSequence[actionIdx].actionId > -1)
+      {
+         memset(&ricSubscriptionInfo->actionSequence[actionIdx], 0, sizeof(ActionInfo));
+      }
+   }
+   memset(ricSubscriptionInfo, 0, sizeof(RicSubscription));
+   RIC_FREE(subscriptionNode->node, sizeof(RicSubscription));
+   RIC_FREE(subscriptionNode, sizeof(CmLList));
+}
 
 /*******************************************************************
  *
- * @brief delete ric subscription information 
+ * @brief Delete RIC subscription List
  *
  * @details
  *
- *    Function : deleteRicSubscription 
+ *    Function : deleteRicSubscriptionList 
  *
- * Functionality: Process ric subscription information
+ * Functionality: Delete RIC subscription list
  *
- * @params[in] 
- *       Pointer to DU database 
+ * @params[in] RIC Subscription list
  * @return void
 
  *
  ******************************************************************/
-void deleteRicSubscription(DuDb **duDb)
+void deleteRicSubscriptionList(CmLListCp *subscriptionList)
 {
-   RanFunction *ranFuncDb = NULLP;
-   uint16_t ranFuncIdx=0;
-   
-   for(ranFuncIdx =0; ranFuncIdx<MAX_RAN_FUNCTION; ranFuncIdx++)
+   CmLList *subscriptionNode = NULLP;
+
+   CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
+   while(subscriptionNode)
    {
-      ranFuncDb = &(*duDb)->ranFunction[ranFuncIdx];
-      if(ranFuncDb->id > 0)
-      {
-         memset(&ranFuncDb->subscriptionList, 0,MAX_RIC_REQUEST*sizeof(RicSubscription));
-         ranFuncDb->numOfSubscription =0;
-      }
+      cmLListDelFrm(subscriptionList, subscriptionNode);
+      deleteRicSubscriptionNode(subscriptionNode);
+      CM_LLIST_FIRST_NODE(subscriptionList, subscriptionNode);
    }
 }
 
@@ -4319,6 +4386,8 @@ void ProcResetResponse(uint32_t duId, ResetResponseE2_t *resetRsp)
 {
    uint8_t ieIdx = 0, duIdx =0;
    DuDb *duDb = NULLP;
+   RanFunction *ranFuncDb = NULLP;
+   uint16_t ranFuncIdx = 0;
 
    SEARCH_DU_DB(duIdx, duId, duDb); 
    if(duDb == NULLP)
@@ -4347,7 +4416,14 @@ void ProcResetResponse(uint32_t duId, ResetResponseE2_t *resetRsp)
          {
             case ProtocolIE_IDE2_id_TransactionID:
                {
-                  deleteRicSubscription(&duDb);
+                  for(ranFuncIdx = 0; ranFuncIdx < MAX_RAN_FUNCTION; ranFuncIdx++)
+                  {
+                     ranFuncDb = &duDb->ranFunction[ranFuncIdx];
+                     if(ranFuncDb->id > 0)
+                     {
+                        deleteRicSubscriptionList(&ranFuncDb->subscriptionList);
+                     }
+                  }
                   break;
                }
             case ProtocolIE_IDE2_id_CriticalityDiagnosticsE2:
@@ -4381,6 +4457,8 @@ void ProcResetRequest(uint32_t duId, ResetRequestE2_t *resetReq)
 {
    uint8_t ieIdx = 0, duIdx =0, transId=0;
    DuDb *duDb = NULLP;
+   RanFunction *ranFuncDb = NULLP;
+   uint16_t ranFuncIdx = 0;
 
    SEARCH_DU_DB(duIdx, duId, duDb); 
    if(duDb == NULLP)
@@ -4414,7 +4492,14 @@ void ProcResetRequest(uint32_t duId, ResetRequestE2_t *resetReq)
                }
             case ProtocolIE_IDE2_id_CauseE2:
                {
-                  deleteRicSubscription(&duDb);
+                  for(ranFuncIdx = 0; ranFuncIdx < MAX_RAN_FUNCTION; ranFuncIdx++)
+                  {
+                     ranFuncDb = &duDb->ranFunction[ranFuncIdx];
+                     if(ranFuncDb->id > 0)
+                     {
+                        deleteRicSubscriptionList(&ranFuncDb->subscriptionList);
+                     }
+                  }
                   break;
                }
          }
@@ -4426,6 +4511,96 @@ void ProcResetRequest(uint32_t duId, ResetRequestE2_t *resetReq)
       DU_LOG("\nERROR  -->  E2AP : Failed to build and send reset response");
    }
 }
+/*******************************************************************
+ *
+ * @brief Processing of RIC Subscription Delete Required
+ *
+ * @details
+ *
+ *    Function : ProcRicSubsDeleteReqd
+ *
+ * Functionality: Processing of RIC Subscription Delete Required
+ *    When received, RIC stub will initiate the RIC subscription
+ *    deletion procedure towards DU
+ *
+ * @param  DU ID
+ *         RIC Subscription Delete Required IEs
+ * @return ROK-success
+ *         RFAILED-failure
+ *
+ ******************************************************************/
+uint8_t ProcRicSubsDeleteReqd(uint32_t duId, RICsubscriptionDeleteRequired_t *ricSubsDelRqd)
+{
+   uint8_t ieIdx = 0, arrIdx = 0, duIdx = 0;
+   DuDb *duDb = NULLP;
+   RicRequestId ricReqId;
+   RanFunction *ranFuncDb = NULLP;
+   RicSubscription *subsDb = NULLP;
+   CmLList *ricSubsNode = NULLP;
+   RICsubscriptionDeleteRequired_IEs_t *ricSubsDelRqdIe = NULLP;
+   RICsubscription_List_withCause_t *ricSubsList = NULLP;
+   RICsubscription_withCause_Item_t *subsItem = NULLP;
+
+   memset(&ricReqId, 0, sizeof(RicRequestId));
+
+   if(!ricSubsDelRqd)
+   {
+      DU_LOG("\nERROR  -->  E2AP : %s: Received NULL message", __func__);
+      return RFAILED;
+   }
+
+   SEARCH_DU_DB(duIdx, duId, duDb);
+   if(duDb == NULLP)
+   {
+      DU_LOG("\nERROR  -->  E2AP : duDb is not present for duId %d",duId);
+      return RFAILED;
+   }
+
+   for(ieIdx = 0; ieIdx < ricSubsDelRqd->protocolIEs.list.count; ieIdx++)
+   {
+      ricSubsDelRqdIe = ricSubsDelRqd->protocolIEs.list.array[ieIdx];
+      switch(ricSubsDelRqdIe->id)
+      {
+         case ProtocolIE_IDE2_id_RICsubscriptionToBeRemoved:
+         {
+            ricSubsList = &ricSubsDelRqdIe->value.choice.RICsubscription_List_withCause;
+            for(arrIdx = 0; arrIdx < ricSubsList->list.count; arrIdx++)
+            {
+               subsItem = &(((RICsubscription_withCause_ItemIEs_t *)ricSubsList->list.array[arrIdx])->\
+                  value.choice.RICsubscription_withCause_Item);
+               ranFuncDb = fetchRanFuncFromRanFuncId(duDb, subsItem->ranFunctionID);
+               if(!ranFuncDb)
+               {
+                  DU_LOG("\nERROR  -->  E2AP : %s: RAN Function ID [%ld] not found", __func__, subsItem->ranFunctionID);
+                  return RFAILED;
+               }
+               
+               ricReqId.requestorId = subsItem->ricRequestID.ricRequestorID;
+               ricReqId.instanceId = subsItem->ricRequestID.ricInstanceID;
+               subsDb = fetchSubsInfoFromRicReqId(ricReqId, ranFuncDb, &ricSubsNode);
+               if(!subsDb)
+               {
+                  DU_LOG("\nERROR  -->  E2AP : %s: RIC Subscription not found for Requestor_ID [%ld] Instance_ID [%ld]", \
+                     __func__, subsItem->ricRequestID.ricRequestorID, subsItem->ricRequestID.ricInstanceID);
+                  return RFAILED;
+               }
+               
+               /* Delete RIC Subcription from RAN Function */
+               cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubsNode);
+               deleteRicSubscriptionNode(ricSubsNode);
+            }
+            
+            break;
+         }
+         default:
+            break;
+      }
+   }  
+   
+   //BuildAndSendRicSubsDeleteRequest();
+   return ROK;
+}
+
 /*******************************************************************
 *
 * @brief Handles received E2AP message and sends back response  
@@ -4534,6 +4709,13 @@ void E2APMsgHdlr(uint32_t *duId, Buffer *mBuf)
                            &e2apMsg->choice.initiatingMessage->value.choice.RICsubscriptionModificationRequired);
                      break;
                   }
+               case InitiatingMessageE2__value_PR_RICsubscriptionDeleteRequired:
+                  {
+                      DU_LOG("\nINFO  -->  E2AP : RIC Subscription Delete Required");
+                      ProcRicSubsDeleteReqd(*duId, \
+                         &e2apMsg->choice.initiatingMessage->value.choice.RICsubscriptionDeleteRequired);
+                      break;
+                  }
 
                case InitiatingMessageE2__value_PR_ErrorIndicationE2:
                   {
index c09f71e..3c8695d 100644 (file)
@@ -116,8 +116,7 @@ typedef struct
 {
    uint16_t  id;
    uint16_t  revisionCounter;
-   uint8_t   numOfSubscription;
-   RicSubscription subscriptionList[MAX_RIC_REQUEST];
+   CmLListCp  subscriptionList;
 }RanFunction;
 
 typedef struct