[Epic-ID: ODUHIGH-516][Task-ID: ODUHIGH-528] RIC Subscription Failure 07/11807/4
authorlal.harshita <Harshita.Lal@radisys.com>
Thu, 21 Sep 2023 18:41:52 +0000 (00:11 +0530)
committerlal.harshita <Harshita.Lal@radisys.com>
Fri, 22 Sep 2023 11:59:46 +0000 (17:29 +0530)
Change-Id: I2a6e936d0fb0faa49e2156acd0c85faafe10d69e
Signed-off-by: lal.harshita <Harshita.Lal@radisys.com>
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/ric_stub/ric_e2ap_msg_hdl.c

index 7c834cd..104c69b 100644 (file)
@@ -135,12 +135,12 @@ uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize)
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t ResetE2Request(E2ProcedureDirection dir, E2CauseType type, E2Cause cause)
+uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause)
 {
    /* Send Reset Request to RIC if DU detects any abnormal failure */
    if(dir == E2_NODE_INITIATED)
    {
-      if(BuildAndSendE2ResetRequest(type, cause) != ROK)
+      if(BuildAndSendE2ResetRequest(resetCause) != ROK)
       {
          DU_LOG("\nERROR  -->  E2AP : BuildAndSendE2ResetRequest failed");
          return RFAILED;
index e337f80..1cdb2f4 100644 (file)
@@ -423,9 +423,14 @@ typedef struct
    E2TimersInfo     e2TimersInfo;
 }E2apDb;
 
+typedef struct e2FailureCause
+{
+   E2CauseType causeType;
+   uint8_t     cause;
+}E2FailureCause;
 
 uint8_t assignTransactionId();
-uint8_t ResetE2Request(E2ProcedureDirection dir, E2CauseType type, E2Cause cause);
+uint8_t ResetE2Request(E2ProcedureDirection dir, E2FailureCause resetCause);
 uint8_t SendE2APMsg(Region region, Pool pool, char *encBuf, int encBufSize);
 /**********************************************************************
   End of file
index e952c5f..ac86380 100644 (file)
 #include "MeasurementInfoItem.h"
 #include "RANfunctionsIDcause-List.h"
 
+/*******************************************************************
+ *
+ * @brief Fill E2 Failure Cause
+ *
+ * @details
+ *
+ *    Function : fillE2Cause
+ *
+ *    Functionality: Fill E2 Failure Cause
+ *
+ * @params[in] E2 Cause pointer to be filled in
+ *             E2 Cause to be filled from 
+ * @return void
+ *
+ ******************************************************************/
+void fillE2Cause(CauseE2_t *e2Cause, E2FailureCause failureCause)
+{
+   e2Cause->present = failureCause.causeType;
+   switch(e2Cause->present)
+   {
+      case CauseE2_PR_ricRequest:
+         {
+            e2Cause->choice.ricRequest = failureCause.cause;
+            break;
+         }
+      case CauseE2_PR_ricService:
+         {
+            e2Cause->choice.ricService = failureCause.cause;
+            break;
+         }
+      case CauseE2_PR_e2Node:
+         {
+            e2Cause->choice.e2Node = failureCause.cause;
+            break;
+         }
+      case CauseE2_PR_transport:
+         {
+            e2Cause->choice.transport = failureCause.cause;
+            break;
+         }
+      case CauseE2_PR_protocol:
+         {
+            e2Cause->choice.protocol = failureCause.cause;
+            break;
+         }
+      case CauseE2_PR_misc:
+         {
+            e2Cause->choice.misc = failureCause.cause;
+            break;
+         }
+      case CauseE2_PR_NOTHING:
+      default:
+         break;
+   }
+}
+
 /*******************************************************************
  *
  * @brief Builds Global gNodeB Params
@@ -1737,7 +1793,8 @@ void  freeAperDecodingOfEventTriggerDef(E2SM_KPM_EventTriggerDefinition_t *event
  *         RFAILED - failure
  *
  ******************************************************************/
-uint8_t extractEventTriggerDef(RanFunction *ranFuncDb, RicSubscription *ricSubscriptionInfo, RICeventTriggerDefinition_t *ricEventTriggerDef)
+uint8_t extractEventTriggerDef(RanFunction *ranFuncDb, RicSubscription *ricSubscriptionInfo, \
+   RICeventTriggerDefinition_t *ricEventTriggerDef, E2FailureCause *failureCause)
 {
    uint8_t ret = RFAILED;
    uint8_t eventIdx = 0;
@@ -1753,6 +1810,8 @@ uint8_t extractEventTriggerDef(RanFunction *ranFuncDb, RicSubscription *ricSubsc
    if(rval.code == RC_FAIL || rval.code == RC_WMORE)
    {
       DU_LOG("\nERROR  -->  E2AP : ASN decode failed for E2SM-KPM Event Trigger Definition");
+      failureCause->causeType = E2_PROTOCOL; 
+      failureCause->cause = E2_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED_MESSAGE;
       return RFAILED;
    }
    printf("\n");
@@ -1774,6 +1833,11 @@ uint8_t extractEventTriggerDef(RanFunction *ranFuncDb, RicSubscription *ricSubsc
       }
    }
 
+   if(ret == RFAILED)
+   {
+      failureCause->causeType = E2_RIC_REQUEST;
+      failureCause->cause = E2_EVENT_TRIGGER_NOT_SUPPORTED;
+   }
    /* Free E2SM_KPM_EventTriggerDefinition_t */
    freeAperDecodingOfEventTriggerDef(eventTiggerDefPtr);
    return ret;
@@ -1997,7 +2061,8 @@ uint8_t extractMeasInfoList(CmLListCp *measInfoSupportedList, MeasurementInfoLis
  *         RFAILED - failure
  *
  ******************************************************************/
-uint8_t extractRicActionDef(RanFunction *ranFuncDb, ActionDefinition *actionDefDb, RICactionDefinition_t *ricActionDef)
+uint8_t extractRicActionDef(RanFunction *ranFuncDb, ActionDefinition *actionDefDb, RICactionDefinition_t *ricActionDef,\
+   E2FailureCause *failureCause)
 {
    bool memFailure = false;
    uint8_t styleIdx = 0;
@@ -2017,6 +2082,8 @@ uint8_t extractRicActionDef(RanFunction *ranFuncDb, ActionDefinition *actionDefD
    if(rval.code == RC_FAIL || rval.code == RC_WMORE)
    {
       DU_LOG("\nERROR  -->  E2AP : ASN decode failed for E2SM-KPM Action Definition");
+      failureCause->causeType = E2_PROTOCOL;
+      failureCause->cause = E2_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED_MESSAGE;
       return RFAILED;
    }
    printf("\n");
@@ -2069,12 +2136,22 @@ uint8_t extractRicActionDef(RanFunction *ranFuncDb, ActionDefinition *actionDefD
       }
 
       if(memFailure)
+      {
+         failureCause->causeType = E2_MISCELLANEOUS;
+         failureCause->cause = E2_MISCELLANEOUS_CAUSE_UNSPECIFIED; 
          break;
+      }
    } /* End of for loop, traversing Report-styles-supported list in E2 node */
 
    /* Memset action Db and Free E2SM_KPM_ActionDefinition_t */
    memset(actionDefDb, 0, sizeof(ActionDefinition));
    freeAperDecodingOfRicActionDefinition(actionDefPtr);
+
+   if(failureCause->causeType == E2_NOTHING)
+   {
+      failureCause->causeType = E2_RIC_REQUEST;
+      failureCause->cause = E2_ACTION_NOT_SUPPORTED;
+   }
    return RFAILED;
 }
 
@@ -2097,7 +2174,8 @@ uint8_t extractRicActionDef(RanFunction *ranFuncDb, ActionDefinition *actionDefD
  *         RFAILED - failure
  *
  ******************************************************************/
-uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSubscriptionInfo, RICactions_ToBeSetup_List_t *actionList)
+uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSubscriptionInfo, \
+   RICactions_ToBeSetup_List_t *actionList, E2FailureCause *failureCause)
 {
    uint8_t actionIdx = 0;
    uint8_t ricActionId = 0;
@@ -2123,7 +2201,7 @@ uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSu
                      ricSubscriptionInfo->actionSequence[ricActionId-1].type = REPORT;
 
                      if(extractRicActionDef(ranFuncDb, &ricSubscriptionInfo->actionSequence[ricActionId-1].definition, \
-                        actionItem->value.choice.RICaction_ToBeSetup_Item.ricActionDefinition) == ROK)
+                        actionItem->value.choice.RICaction_ToBeSetup_Item.ricActionDefinition, failureCause) == ROK)
                      {
                         ricSubscriptionInfo->actionSequence[ricActionId-1].action = CONFIG_ADD;
                         ricSubscriptionInfo->numOfActions++;
@@ -2148,6 +2226,11 @@ uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSu
    if(ricSubscriptionInfo->numOfActions)
       return ROK;
 
+   if(failureCause->causeType == E2_NOTHING)
+   {
+      failureCause->causeType = E2_RIC_REQUEST;
+      failureCause->cause = E2_ACTION_NOT_SUPPORTED;
+   }
    return RFAILED;
 }
 
@@ -2157,30 +2240,34 @@ uint8_t extractRicActionToBeSetup(RanFunction *ranFuncDb, RicSubscription *ricSu
  *
  * @details
  *
- *    Function : procRicSubsReq
+ *    Function : procRicSubscriptionRequest
  *
- *    Functionality: Processes E2 Setup Response sent by CU
+ *    Functionality: Processes RIC Subscription Request from RIC
  *
  * @params[in] E2AP_PDU_t ASN decoded E2AP message
  * @return ROK     - success
  *         RFAILED - failure
  *
  * ****************************************************************/
-
-uint8_t procRicSubsReq(E2AP_PDU_t *e2apMsg)
+uint8_t procRicSubscriptionRequest(E2AP_PDU_t *e2apMsg)
 {
    uint8_t idx = 0; 
    uint8_t ret = ROK;
    uint16_t ranFuncId = 0;
+   RicRequestId ricReqId;
    CmLList  *ricSubscriptionNode = NULLP;
    RanFunction *ranFuncDb = NULLP;
    RICsubscriptionRequest_t *ricSubsReq = NULLP;
    RICsubscriptionDetails_t *subsDetails = NULLP;
    RicSubscription *ricSubscriptionInfo = NULLP;
+   E2FailureCause failureCause;
 
    DU_LOG("\nINFO   -->  E2AP : RIC Subscription request received"); 
-   ricSubsReq = &e2apMsg->choice.initiatingMessage->value.choice.RICsubscriptionRequest;
 
+   memset(&failureCause, 0, sizeof(E2FailureCause));
+   memset(&ricReqId, 0, sizeof(RicRequestId));
+
+   ricSubsReq = &e2apMsg->choice.initiatingMessage->value.choice.RICsubscriptionRequest;
    for(idx=0; idx<ricSubsReq->protocolIEs.list.count; idx++)
    {
       if(ricSubsReq->protocolIEs.list.array[idx])
@@ -2189,15 +2276,8 @@ uint8_t procRicSubsReq(E2AP_PDU_t *e2apMsg)
          {
             case ProtocolIE_IDE2_id_RICrequestID:
                {
-                  DU_ALLOC(ricSubscriptionInfo, sizeof(RicSubscription));
-                  if(!ricSubscriptionInfo)
-                  {
-                     DU_LOG("\nERROR  -->  E2AP : Memory allocation failed for ricSubscriptionInfo");
-                     ret = RFAILED;
-                     break;
-                  }
-                  ricSubscriptionInfo->requestId.requestorId = ricSubsReq->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricRequestorID;
-                  ricSubscriptionInfo->requestId.instanceId = ricSubsReq->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricInstanceID;
+                  ricReqId.requestorId = ricSubsReq->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricRequestorID;
+                  ricReqId.instanceId  = ricSubsReq->protocolIEs.list.array[idx]->value.choice.RICrequestID.ricInstanceID;
 
                   break;
                }
@@ -2210,10 +2290,23 @@ uint8_t procRicSubsReq(E2AP_PDU_t *e2apMsg)
                   if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId)
                   {
                      ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1];
+
+                     DU_ALLOC(ricSubscriptionInfo, sizeof(RicSubscription));
+                     if(!ricSubscriptionInfo)
+                     {
+                        DU_LOG("\nERROR  -->  E2AP : Memory allocation failed for ricSubscriptionInfo");
+                        failureCause.causeType = E2_MISCELLANEOUS;
+                        failureCause.cause = E2_MISCELLANEOUS_CAUSE_UNSPECIFIED;
+                        ret = RFAILED;
+                        break;
+                     }
+                     ricSubscriptionInfo->requestId.requestorId = ricReqId.requestorId;
+                     ricSubscriptionInfo->requestId.instanceId = ricReqId.instanceId;
                   }
                   else
                   {
-                     /* TODO : Send RAN Subcription Failure */
+                     failureCause.causeType = E2_RIC_REQUEST;
+                     failureCause.cause = E2_RAN_FUNCTION_ID_INVALID;
                      ret = RFAILED;
                   }
                   break;
@@ -2224,17 +2317,17 @@ uint8_t procRicSubsReq(E2AP_PDU_t *e2apMsg)
                   subsDetails = &ricSubsReq->protocolIEs.list.array[idx]->value.choice.RICsubscriptionDetails;
 
                   /* Decode, Validate and record Event Trigger Definition */
-                  if(extractEventTriggerDef(ranFuncDb, ricSubscriptionInfo, &subsDetails->ricEventTriggerDefinition) != ROK)
+                  if(extractEventTriggerDef(ranFuncDb, ricSubscriptionInfo, &subsDetails->ricEventTriggerDefinition, \
+                     &failureCause) != ROK)
                   {
-                     /* TODO : Send RAN Subcription Failure */
                      ret = RFAILED;
                      break;
                   }
 
                   /* Decode, Validate and record RIC actions */
-                  if(extractRicActionToBeSetup(ranFuncDb, ricSubscriptionInfo, &subsDetails->ricAction_ToBeSetup_List) != ROK)
+                  if(extractRicActionToBeSetup(ranFuncDb, ricSubscriptionInfo, &subsDetails->ricAction_ToBeSetup_List, \
+                     &failureCause) != ROK)
                   {
-                     /* TODO : Send RAN Subcription Failure */
                      ret = RFAILED;
                      break;
                   }
@@ -2277,10 +2370,186 @@ uint8_t procRicSubsReq(E2AP_PDU_t *e2apMsg)
          BuildAndSendRicIndication(ricSubscriptionInfo);
       }
    }
+   else
+   {
+      DU_FREE(ricSubscriptionInfo, sizeof(RicSubscription));
+
+      /* Send RIC Subcription Failure */
+      BuildAndSendRicSubscriptionFailure(ricReqId, ranFuncId, failureCause);
+   }
 
    return ret;
 }
 
+/******************************************************************
+ *
+ * @brief Free RIC Subscription Failure
+ *
+ * @details
+ *
+ *    Function : FreeRicSubscriptionFailure
+ *
+ *    Functionality: Free RIC Subscription Failure
+ *
+ * @params[in] E2AP PDU
+ * @return void
+ *
+ * ****************************************************************/
+void FreeRicSubscriptionFailure(E2AP_PDU_t *e2apMsg)
+{
+   uint8_t elemIdx = 0;
+   RICsubscriptionFailure_t *ricSubscriptionFailure = NULLP;
+
+   if(e2apMsg)
+   {
+      if(e2apMsg->choice.unsuccessfulOutcome)
+      {
+         ricSubscriptionFailure = &e2apMsg->choice.unsuccessfulOutcome->value.choice.RICsubscriptionFailure;
+         if(ricSubscriptionFailure->protocolIEs.list.array)
+         {
+            for(elemIdx = 0; elemIdx < ricSubscriptionFailure->protocolIEs.list.count; elemIdx++)
+            {
+               DU_ALLOC(ricSubscriptionFailure->protocolIEs.list.array[elemIdx], sizeof(RICsubscriptionFailure_IEs_t));
+            }
+            DU_ALLOC(ricSubscriptionFailure->protocolIEs.list.array, ricSubscriptionFailure->protocolIEs.list.size);
+         }
+         DU_ALLOC(e2apMsg->choice.unsuccessfulOutcome, sizeof(UnsuccessfulOutcomeE2_t));
+      }
+      DU_ALLOC(e2apMsg, sizeof(E2AP_PDU_t));
+   }
+}
+
+/******************************************************************
+ *
+ * @brief Fill and Send RIC Subscription Failure to RIC
+ *
+ * @details
+ *
+ *    Function : BuildAndSendRicSubscriptionFailure
+ *
+ *    Functionality: Fill and Send RIC Subscription Failure to RIC
+ *
+ * @params[in] RIC Request ID
+ *             RAN Function ID
+ *             Cause of Failure
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t BuildAndSendRicSubscriptionFailure(RicRequestId ricReqId, uint16_t ranFuncId, E2FailureCause failureCause)
+{
+   uint8_t          ret = RFAILED;
+   uint8_t          elementCnt = 0, elemIdx = 0;
+   E2AP_PDU_t       *e2apMsg = NULLP;
+   asn_enc_rval_t   encRetVal;        /* Encoder return value */
+   RICsubscriptionFailure_t *ricSubscriptionFailure = NULLP;
+   RICsubscriptionFailure_IEs_t *ricSubsFailIe = NULLP;
+
+   while(true)
+   {
+      DU_LOG("\nINFO   -->  E2AP : Building RIC Subscription Failure\n");
+
+      DU_ALLOC(e2apMsg, sizeof(E2AP_PDU_t));
+      if(e2apMsg == NULLP)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation at [%s] : Line [%d]", __func__, __LINE__); 
+         break;
+      }
+
+      e2apMsg->present = E2AP_PDU_PR_unsuccessfulOutcome;
+      DU_ALLOC(e2apMsg->choice.unsuccessfulOutcome, sizeof(UnsuccessfulOutcomeE2_t));
+      if(e2apMsg->choice.unsuccessfulOutcome == NULLP)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation at [%s] : Line [%d]", __func__, __LINE__); 
+         break;
+      }
+      e2apMsg->choice.unsuccessfulOutcome->procedureCode = ProcedureCodeE2_id_RICsubscription;
+      e2apMsg->choice.unsuccessfulOutcome->criticality = CriticalityE2_reject;
+      e2apMsg->choice.unsuccessfulOutcome->value.present = UnsuccessfulOutcomeE2__value_PR_RICsubscriptionFailure;
+
+      ricSubscriptionFailure = &e2apMsg->choice.unsuccessfulOutcome->value.choice.RICsubscriptionFailure;
+
+      elementCnt = 3;
+      ricSubscriptionFailure->protocolIEs.list.count = elementCnt;
+      ricSubscriptionFailure->protocolIEs.list.size = elementCnt * sizeof(RICsubscriptionFailure_IEs_t *);
+      DU_ALLOC(ricSubscriptionFailure->protocolIEs.list.array, ricSubscriptionFailure->protocolIEs.list.size);
+      if(!ricSubscriptionFailure->protocolIEs.list.array)
+      {
+         DU_LOG("\nERROR  -->  E2AP : Memory allocation at [%s] : Line [%d]", __func__, __LINE__); 
+         break;
+      }
+
+      for(elemIdx = 0; elemIdx < elementCnt; elemIdx++)
+      {
+         DU_ALLOC(ricSubscriptionFailure->protocolIEs.list.array[elemIdx], sizeof(RICsubscriptionFailure_IEs_t));
+         if(!ricSubscriptionFailure->protocolIEs.list.array[elemIdx])
+         {
+            DU_LOG("\nERROR  -->  E2AP : Memory allocation at [%s] : Line [%d] for IE at index [%d]", \
+               __func__, __LINE__, elemIdx);
+            break;
+         }
+      }
+      if(elemIdx < elementCnt)
+         break;
+
+      elemIdx = 0;
+
+      /* RIC Request ID */
+      ricSubsFailIe = ricSubscriptionFailure->protocolIEs.list.array[elemIdx++];
+      ricSubsFailIe->id = ProtocolIE_IDE2_id_RICrequestID;
+      ricSubsFailIe->criticality = CriticalityE2_reject;
+      ricSubsFailIe->value.present = RICsubscriptionFailure_IEs__value_PR_RICrequestID;
+      ricSubsFailIe->value.choice.RICrequestID.ricRequestorID = ricReqId.requestorId;
+      ricSubsFailIe->value.choice.RICrequestID.ricInstanceID = ricReqId.instanceId;
+
+      /* RAN Function ID */
+      ricSubsFailIe = ricSubscriptionFailure->protocolIEs.list.array[elemIdx++];
+      ricSubsFailIe->id = ProtocolIE_IDE2_id_RANfunctionID;
+      ricSubsFailIe->criticality = CriticalityE2_reject;
+      ricSubsFailIe->value.present = RICsubscriptionFailure_IEs__value_PR_RANfunctionID;
+      ricSubsFailIe->value.choice.RANfunctionID = ranFuncId;
+
+      /* Cause */
+      ricSubsFailIe = ricSubscriptionFailure->protocolIEs.list.array[elemIdx++];
+      ricSubsFailIe->id = ProtocolIE_IDE2_id_CauseE2;
+      ricSubsFailIe->criticality = CriticalityE2_reject;
+      ricSubsFailIe->value.present = RICsubscriptionFailure_IEs__value_PR_CauseE2;
+      fillE2Cause(&ricSubsFailIe->value.choice.CauseE2, failureCause);
+
+      /* 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 Failure 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 Failure 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("\nINFO   -->  E2AP : Sending RIC Subscription Failure");
+
+      }
+      ret = ROK;
+      break;
+   }
+   FreeRicSubscriptionFailure(e2apMsg);
+   return ret;
+}
+
 /*******************************************************************
  *
  * @brief Free the RicIndication Message
@@ -2771,7 +3040,7 @@ void FreeE2ResetRequest(E2AP_PDU_t *e2apMsg)
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t BuildAndSendE2ResetRequest(E2CauseType failureType, E2Cause failureCause)
+uint8_t BuildAndSendE2ResetRequest(E2FailureCause resetCause)
 {
    uint8_t ieIdx = 0, elementCnt = 0, transId = 0;
    uint8_t ret = RFAILED;
@@ -2841,30 +3110,7 @@ uint8_t BuildAndSendE2ResetRequest(E2CauseType failureType, E2Cause failureCause
       resetReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_IDE2_id_CauseE2;
       resetReq->protocolIEs.list.array[ieIdx]->criticality = CriticalityE2_ignore;
       resetReq->protocolIEs.list.array[ieIdx]->value.present = ResetRequestIEs__value_PR_CauseE2;
-      resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.present = failureType;
-      switch(resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.present)
-      {
-         case CauseE2_PR_NOTHING:
-            break;
-         case CauseE2_PR_ricRequest:
-            resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.choice.ricRequest = failureCause;
-            break;
-         case CauseE2_PR_ricService:
-            resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.choice.ricService = failureCause;
-            break;
-         case CauseE2_PR_e2Node:
-            resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.choice.e2Node = failureCause;
-            break;
-         case CauseE2_PR_transport:
-            resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.choice.transport = failureCause;
-            break;
-         case CauseE2_PR_protocol:
-            resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.choice.protocol = failureCause;
-            break;
-         case CauseE2_PR_misc:
-            resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2.choice.misc = failureCause;
-            break;
-      }
+      fillE2Cause(&resetReq->protocolIEs.list.array[ieIdx]->value.choice.CauseE2, resetCause);
 
       /* Prints the Msg formed */
       xer_fprint(stdout, &asn_DEF_E2AP_PDU, e2apMsg);
@@ -3973,7 +4219,7 @@ void E2APMsgHdlr(Buffer *mBuf)
             {
                case InitiatingMessageE2__value_PR_RICsubscriptionRequest: 
                   {
-                     procRicSubsReq(e2apMsg);
+                     procRicSubscriptionRequest(e2apMsg);
                      break;
                   }
                case InitiatingMessageE2__value_PR_RICserviceQuery:
index c5701c2..460355b 100644 (file)
 
 uint8_t  BuildAndSendE2SetupReq();
 uint8_t  BuildAndSendE2NodeConfigUpdate();
-uint8_t BuildAndSendE2ResetRequest(E2CauseType failureType, E2Cause failureCause);
+uint8_t BuildAndSendE2ResetRequest(E2FailureCause resetCause);
 void     E2APMsgHdlr(Buffer *mBuf);
 uint8_t BuildAndSendRicIndication(RicSubscription *ricSubscriptionInfo);
 uint8_t BuildAndSendRicServiceUpdate(RicServiceUpdate serviceUpdate);
 uint8_t BuildAndSendStatsReq(uint16_t ranFuncId, RicSubscription *ricSubscriptionInfo);
+uint8_t BuildAndSendRicSubscriptionFailure(RicRequestId ricReqId, uint16_t ranFuncId, E2FailureCause failureCause);
 /**********************************************************************
   End of file
  **********************************************************************/
index 6502840..0795850 100644 (file)
@@ -29,6 +29,7 @@
 #include "du_app_mac_inf.h"
 #include "du_app_rlc_inf.h"
 #include "du_e2ap_mgr.h"
+#include "du_e2ap_msg_hdl.h"
 #include "du_cfg.h"
 #include "du_app_rlc_inf.h"
 #include "du_mgr.h"
@@ -2272,6 +2273,90 @@ uint8_t BuildAndSendStatsReq(uint16_t ranFuncId, RicSubscription *ricSubscriptio
    return ROK;
 }
 
+/*******************************************************************
+ *
+ * @brief Converts DU specific failure cause to E2 interface
+ *        failure cause
+ *
+ * @details
+ *
+ *    Function : convertDuCauseToE2Cause
+ *
+ *    Functionality: Converts DU specific failure cause to E2 
+ *       interface failure cause
+ *
+ * @params[in] DU specific failure cause
+ *             E2 specific failure cause
+ *
+ * @return void
+ *
+ * ****************************************************************/
+void convertDuCauseToE2Cause(CauseOfResult l2Cause, E2FailureCause *failureCause)
+{
+   switch(l2Cause)
+   {
+      case PARAM_INVALID:
+         {
+            failureCause->causeType = E2_RIC_REQUEST;
+            failureCause->cause = E2_ACTION_NOT_SUPPORTED;
+            break;
+         }
+      case RESOURCE_UNAVAILABLE:
+         {
+            failureCause->causeType = E2_RIC_REQUEST;
+            failureCause->cause = E2_FUNCTION_RESOURCE_LIMIT;
+            break;
+         }
+      default:
+         {
+            failureCause->causeType = E2_RIC_REQUEST;
+            failureCause->cause = E2_RIC_REQUEST_CAUSE_UNSPECIFIED;
+            break;
+         }
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Rejects all actions received in a subscription request
+ *
+ * @details
+ *
+ *    Function : duRejectAllStatsGroup
+ *
+ *    Functionality: Rejects all actions received in a subscription
+ *       request by :
+ *       a. Removing the subscription entry from RAN function
+ *       b. Sending RIC Subscription Failure to RIC with appropriate
+ *          cause of failure
+ *
+ * @params[in] RAN Function DB
+ *             Subscription entry in RAN Function subscription list
+ *             Statistics Response from MAC
+ *
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t duRejectAllStatsGroup(RanFunction *ranFuncDb, CmLList *ricSubscriptionNode, MacStatsRsp *statsRsp)
+{
+   uint8_t ret = ROK;
+   RicRequestId  requestId;
+   E2FailureCause failureCause;
+
+   /* Delete subcription from RAN Function */
+   memcpy(&requestId, &((RicSubscription *)ricSubscriptionNode->node)->requestId, sizeof(RicRequestId));
+   cmLListDelFrm(&ranFuncDb->subscriptionList, ricSubscriptionNode);
+   DU_FREE(ricSubscriptionNode->node, sizeof(RicSubscription));
+   DU_FREE(ricSubscriptionNode, sizeof(CmLList));
+
+   convertDuCauseToE2Cause(statsRsp->statsGrpRejectedList[0].cause, &failureCause);
+
+   /* Send RIC subscription failure to RIC */
+   ret = BuildAndSendRicSubscriptionFailure(requestId, ranFuncDb->id, failureCause);
+   return ret;
+}
+
 /*******************************************************************
  *
  * @brief Process statistics response from MAC
@@ -2293,6 +2378,12 @@ uint8_t BuildAndSendStatsReq(uint16_t ranFuncId, RicSubscription *ricSubscriptio
  * ****************************************************************/
 uint8_t DuProcMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp)
 {
+   uint16_t ranFuncId = 0;
+   RicRequestId ricReqId;
+   RanFunction *ranFuncDb = NULLP;
+   CmLList *ricSubscriptionNode = NULLP;
+   RicSubscription *ricSubscriptionInfo = NULLP;
+
    DU_LOG("\nINFO  -->  DU_APP : DuProcMacStatsRsp: Received Statistics Response from MAC");
 
    if(statsRsp)
@@ -2313,8 +2404,62 @@ uint8_t DuProcMacStatsRsp(Pst *pst, MacStatsRsp *statsRsp)
          DU_LOG("\n    Group Id [%d]", statsRsp->statsGrpRejectedList[idx]);
       }
 #endif      
-     
+
+      /* Extract following from 64 bit subscription-ID :
+       *  First 16 MSB is unused
+       *  Next 16 MSB = RAN-Function-ID
+       *  Next 16 MSB = Requestor-ID in RIC-Request-ID
+       *  Last 16 LSB = Instance-ID in RIC-Request-ID
+       */
+      ricReqId.instanceId = statsRsp->subscriptionId & 0xFFFF;
+      ricReqId.requestorId = (statsRsp->subscriptionId >> 16) & 0xFFFF;
+      ranFuncId = (statsRsp->subscriptionId >> 32) & 0xFFFF;
+
+      /* Fetch RAN Function DB */
+      if(duCb.e2apDb.ranFunction[ranFuncId-1].id == ranFuncId)
+      {
+         ranFuncDb = &duCb.e2apDb.ranFunction[ranFuncId-1];
+      }
+      else
+      {
+         DU_LOG("\nERROR  -->  DU_APP : DuProcMacStatsRsp: Invalid RAN Function ID[%d]  with Subscription ID [%ld]", \
+            ranFuncId, statsRsp->subscriptionId);
+         DU_FREE_SHRABL_BUF(pst->region, pst->pool, statsRsp, sizeof(MacStatsRsp));
+         return RFAILED;
+      }
+
+      /* Fetch subscription detail in RAN Function DB */
+      CM_LLIST_FIRST_NODE(&ranFuncDb->subscriptionList, ricSubscriptionNode);
+      while(ricSubscriptionNode)
+      {
+         ricSubscriptionInfo = (RicSubscription *)ricSubscriptionNode->node;
+         if(ricSubscriptionInfo && (ricSubscriptionInfo->requestId.requestorId == ricReqId.requestorId) &&
+            (ricSubscriptionInfo->requestId.instanceId == ricReqId.instanceId))
+         {
+            break;
+         }
+         ricSubscriptionNode = ricSubscriptionNode->next;
+      }
+
+      if(ricSubscriptionNode == NULLP)
+      {
+         DU_LOG("\nERROR  -->  DU_APP : DuProcMacStatsRsp: Subscription not found for Requestor ID [%d] Instance ID [%d]",\
+            ricReqId.requestorId, ricReqId.instanceId);
+         DU_FREE_SHRABL_BUF(pst->region, pst->pool, statsRsp, sizeof(MacStatsRsp));
+         return RFAILED;
+      }
+
+      /* If no action is accepted
+       *  a. Remove subcription entry from RAN Function
+       *  b. Send RIC subscription failure */
+      if(statsRsp->numGrpAccepted == 0)
+      {
+         duRejectAllStatsGroup(ranFuncDb, ricSubscriptionNode, statsRsp);
+      }
+
       /* TODO :
+       * If even 1 action is accepted :
+       *
        * For accepted groups:
        *    Mark scubscrbed-action's -> action = CONFIG_UNKNOWN
        *    Add action ID to accpeted-action-list in Subscription response
index c399f89..8cc3806 100644 (file)
@@ -1493,8 +1493,8 @@ uint8_t ProcE2SetupReq(uint32_t *duId, E2setupRequest_t  *e2SetupReq)
                            {
                               ranFuncItemIe = (RANfunction_ItemIEs_t *) ranFunctionsList->list.array[ranFuncIdx]; 
                               ranFunItem = &ranFuncItemIe->value.choice.RANfunction_Item;
-                              duDb->ranFunction[duDb->numOfRanFunction].id = ranFunItem->ranFunctionID; 
-                              duDb->ranFunction[duDb->numOfRanFunction].revisionCounter = ranFunItem->ranFunctionRevision; 
+                              duDb->ranFunction[ranFunItem->ranFunctionID-1].id = ranFunItem->ranFunctionID; 
+                              duDb->ranFunction[ranFunItem->ranFunctionID-1].revisionCounter = ranFunItem->ranFunctionRevision; 
                               duDb->numOfRanFunction++;
                            }
                         }
@@ -2779,6 +2779,95 @@ void ProcRicServiceUpdate(uint32_t duId, RICserviceUpdate_t *ricServiceUpdate)
    }
 }
 
+/*******************************************************************
+ *
+ * @brief Processing RIC subscription failure from DU
+ *
+ * @details
+ *
+ *    Function : ProcRicSubscriptionFailure
+ *
+ * Functionality: Processing RIC subscription failure from DU
+ *
+ * @param  ID of DU from which message was sent
+ *         RIC Subscription failure message
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t ProcRicSubscriptionFailure(uint32_t duId, RICsubscriptionFailure_t *ricSubscriptionFailure)
+{
+   uint8_t ieIdx = 0, duIdx = 0, subsIdx = 0;
+   uint8_t ranFuncId = 0;
+   bool   ricReqIdDecoded = false;
+   DuDb    *duDb = NULLP;
+   RanFunction *ranFuncDb = NULLP;
+   RicRequestId ricReqId;
+   RICsubscriptionFailure_IEs_t *ricSubsFailIe = NULLP;
+
+   DU_LOG("\nINFO  -->  E2AP : Received RIC subscription failure");
+
+   SEARCH_DU_DB(duIdx, duId, duDb);
+   if(duDb == NULLP)
+   {
+      DU_LOG("\nERROR  -->  E2AP : duDb is not present for duId %d",duId);
+      return;
+   }
+
+   memset(&ricReqId, 0, sizeof(RicRequestId));
+   if(ricSubscriptionFailure)
+   {
+      if(ricSubscriptionFailure->protocolIEs.list.array)
+      {
+         for(ieIdx=0; ieIdx<ricSubscriptionFailure->protocolIEs.list.count; ieIdx++)
+         {
+            if(ricSubscriptionFailure->protocolIEs.list.array[ieIdx])
+            {
+               ricSubsFailIe = ricSubscriptionFailure->protocolIEs.list.array[ieIdx];
+               switch(ricSubscriptionFailure->protocolIEs.list.array[ieIdx]->id)
+               {
+                  case ProtocolIE_IDE2_id_RICrequestID:
+                  {
+                     ricReqId.requestorId = ricSubsFailIe->value.choice.RICrequestID.ricRequestorID;
+                     ricReqId.instanceId = ricSubsFailIe->value.choice.RICrequestID.ricInstanceID;
+                     ricReqIdDecoded = true;
+                     break;
+                  }
+                  case ProtocolIE_IDE2_id_RANfunctionID:
+                  {
+                     ranFuncId = ricSubsFailIe->value.choice.RANfunctionID;
+                     if(duDb->ranFunction[ranFuncId-1].id == ranFuncId)
+                     {
+                        ranFuncDb = &duDb->ranFunction[ranFuncId-1];
+                     }
+                     break; 
+                  }
+                  case ProtocolIE_IDE2_id_CauseE2:
+                  default:
+                     /* No handling required as of now since this is a stub */
+                     break;
+
+               }
+            }
+         }
+
+         /* Remove subscription entry from RAN Function */
+         if(ranFuncDb && ricReqIdDecoded)
+         {
+            for(subsIdx = 0; subsIdx < ranFuncDb->numOfSubscription; subsIdx++)
+            {
+               if((ranFuncDb->subscriptionList[subsIdx].requestId.requestorId == ricReqId.requestorId) &&
+                     (ranFuncDb->subscriptionList[subsIdx].requestId.instanceId == ricReqId.instanceId))
+               {
+                  memset(&ranFuncDb->subscriptionList[subsIdx], 0, sizeof(RicSubscription));
+                  break;
+               }
+            }
+         }
+      }
+   }
+   return ROK;
+}
 
 /*******************************************************************
 *
@@ -2908,6 +2997,25 @@ void E2APMsgHdlr(uint32_t *duId, Buffer *mBuf)
             }
             break; 
          }
+         case E2AP_PDU_PR_unsuccessfulOutcome:
+         {
+            switch(e2apMsg->choice.successfulOutcome->value.present)
+            {
+               case UnsuccessfulOutcomeE2__value_PR_RICsubscriptionFailure:
+                  {
+                     ProcRicSubscriptionFailure(*duId, \
+                        &e2apMsg->choice.unsuccessfulOutcome->value.choice.RICsubscriptionFailure);
+                     break;
+                  }
+               default:
+                  {
+                     DU_LOG("\nERROR  -->  E2AP : Invalid type of unsuccessfulOutcome message [%d]", \
+                        e2apMsg->choice.unsuccessfulOutcome->value.present);
+                     return;
+                  }
+            }
+            break;
+         }
       default:
          {
             DU_LOG("\nERROR  -->  E2AP : Invalid type message type ");