Epic-ID: ODUHIGH-463][Task-ID: ODUHIGH-504]Dummy Handover Request/Response and UE... 64/10964/5
authorlal.harshita <Harshita.Lal@radisys.com>
Thu, 20 Apr 2023 14:07:56 +0000 (19:37 +0530)
committerlal.harshita <Harshita.Lal@radisys.com>
Mon, 24 Apr 2023 16:16:18 +0000 (21:46 +0530)
Change-Id: I4813a36690fe4a9895074f3821f2533f36f87a57
Signed-off-by: lal.harshita <Harshita.Lal@radisys.com>
src/cm/common_def.c
src/cm/common_def.h
src/cu_stub/cu_f1ap_msg_hdl.c
src/cu_stub/cu_stub.c
src/cu_stub/cu_stub.h
src/cu_stub/cu_xnap_msg_hdl.c

index 11d80b2..4b974c3 100644 (file)
@@ -484,7 +484,7 @@ uint32_t convertFreqToArfcn(uint32_t freq)
 
    for(indexTable = 0; indexTable < 3; indexTable++)
    {
-      if(freq < arfcnFreqTable[indexTable][0])
+      if(freq < (arfcnFreqTable[indexTable][0] * 1000))
       {
          arfcn = arfcnFreqTable[indexTable][3] + ((freq - (arfcnFreqTable[indexTable][2] * 1000)) / (arfcnFreqTable[indexTable][1]));
          return (arfcn);
index 1bdb4a1..c58d28a 100644 (file)
 #define ODU_PRINT_MSG SPrntMsg
 #define ODU_REM_PRE_MSG SRemPreMsg
 #define ODU_REM_PRE_MSG_MULT SRemPreMsgMult
+#define ODU_REM_POST_MSG_MULT SRemPstMsgMult
 #define ODU_REG_TMR_MT SRegTmrMt
 #define ODU_SEGMENT_MSG SSegMsg
 #define ODU_CAT_MSG SCatMsg
index 601637b..a40b865 100644 (file)
@@ -2566,9 +2566,9 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint
       return RFAILED;
    }
    
-   if(hoInProgress)
+   if(hoInProgress == Inter_DU_HO)
       drbQos->qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI = qosInfo->nonDynFiveQI ;
-   else
+   else if(hoInProgress == false || hoInProgress == Xn_Based_Inter_CU_HO)
    {
       /*FiveQI*/
       if(actionType == ProtocolIE_ID_id_DRBs_ToBeModified_Item)
@@ -2607,7 +2607,7 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint
       drbQos->nGRANallocationRetentionPriority.pre_emptionCapability = qosInfo->preemptionCapability;
       drbQos->nGRANallocationRetentionPriority.pre_emptionVulnerability = qosInfo->preemptionVulnerability;
    }
-   else
+   else if((hoInProgress == false) || (hoInProgress == Xn_Based_Inter_CU_HO))
    {
       drbQos->nGRANallocationRetentionPriority.priorityLevel = PriorityLevel_lowest;
       drbQos->nGRANallocationRetentionPriority.pre_emptionCapability = Pre_emptionCapability_may_trigger_pre_emption;
@@ -2693,6 +2693,12 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint
 uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bool hoInProgress)
 {
    /*SNSSAI*/
+   /* In case of non-HO UE context creation and Xn Based HO, DRB's SNSSAI
+    * configuration is not known beforehand. In these 2 case, the following
+    * condition will hit */
+   if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO))
+      drbInfo->snssai = snssaiToCopy;
+
    /*ssT*/
    snssai->sST.size = sizeof(uint8_t);
    CU_ALLOC(snssai->sST.buf, snssai->sST.size);
@@ -2700,10 +2706,7 @@ uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bo
    {
       return RFAILED;
    }
-   if(!hoInProgress)
-      memcpy(snssai->sST.buf, &snssaiToCopy->sst, snssai->sST.size);
-   else
-      memcpy(snssai->sST.buf, &drbInfo->snssai->sst, snssai->sST.size);
+   memcpy(snssai->sST.buf, &drbInfo->snssai->sst, snssai->sST.size);
 
    /*sD*/
    CU_ALLOC(snssai->sD, sizeof(OCTET_STRING_t));
@@ -2717,13 +2720,8 @@ uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bo
    {
       return RFAILED;
    }
-   if(!hoInProgress)
-      memcpy(snssai->sD->buf, snssaiToCopy->sd, snssai->sD->size);
-   else
-      memcpy(snssai->sD->buf, drbInfo->snssai->sd, snssai->sD->size);
+   memcpy(snssai->sD->buf, drbInfo->snssai->sd, snssai->sD->size);
 
-   if(!hoInProgress)
-      drbInfo->snssai = snssaiToCopy;
    return ROK;
 }/*End of BuildSNSSAI*/
 
@@ -2748,10 +2746,14 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui
    uint8_t  ret = ROK, idx = 0, flowCnt = 0, flowIdx = 0;
    FlowsMapped *qosFlow;
 
-   if(!hoInProgress)
+   /* In case of non-HO UE context creation and Xn Based HO, DRB's SNSSAI
+    * configuration is not known beforehand. In these 2 case, the following
+    * condition will hit */
+   if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO))
       flowCnt = 1;
    else
       flowCnt = drbInfo->numFlowMap;
+
    flowMap->list.count = flowCnt;
    flowMap->list.size = flowCnt * sizeof(Flows_Mapped_To_DRB_Item_t *);
    CU_ALLOC(flowMap->list.array,flowMap->list.size);
@@ -2769,7 +2771,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui
          return RFAILED;
       }
       
-      if(!hoInProgress)
+      if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO))
       {
          flowMap->list.array[idx]->qoSFlowIdentifier = 0;
          if(actionType == ProtocolIE_ID_id_DRBs_ToBeModified_Item)
@@ -2803,7 +2805,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui
          return RFAILED;
       }
 
-      if((!hoInProgress) && (actionType != ProtocolIE_ID_id_DRBs_ToBeModified_Item))
+      if(((!hoInProgress) && (actionType != ProtocolIE_ID_id_DRBs_ToBeModified_Item)) || (hoInProgress == Xn_Based_Inter_CU_HO))
          drbInfo->numFlowMap++;
    }
    return ROK;
@@ -2866,7 +2868,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To
       return RFAILED;
    }
 
-   if(!hoInProgress)
+   if((!hoInProgress) || (hoInProgress == Xn_Based_Inter_CU_HO))
    {
       /* NOTE: Below IP address must be changed if running on different IP configuration */
       ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf[0] = 192;
@@ -2899,7 +2901,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To
       return RFAILED;
    }
    
-   if(!hoInProgress)
+   if((!hoInProgress) || (hoInProgress == Xn_Based_Inter_CU_HO))
    {
       ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[0] = 0;
       ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[1] = 0;
@@ -3000,7 +3002,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet
                choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, FALSE);
       else
          BuildQOSInforet =  BuildQOSInfo(&ueCb->drbList[idx].qos, &drbSetItem->qoSInformation.choice.\
-               choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, TRUE);
+               choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, ueCb->hoInfo.HOType);
       if(BuildQOSInforet != ROK)
       {
          DU_LOG("\nERROR  -->  F1AP : Failed to build QOS Info in BuildDRBSetup");
@@ -3014,7 +3016,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet
                choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[snssaiIdx], FALSE);
       else
          BuildSNSSAIret = BuildSNSSAI(&ueCb->drbList[idx], &drbSetItem->qoSInformation.choice.\
-               choice_extension->value.choice.DRB_Information.sNSSAI, NULLP, TRUE);
+               choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[snssaiIdx], ueCb->hoInfo.HOType);
       if(BuildSNSSAIret != ROK)
       {
          DU_LOG("\nERROR  -->  F1AP : Failed to build SNSSAI Info in BuildDRBSetup");
@@ -3027,7 +3029,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet
                value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, FALSE);
       else
          BuildFlowsMapret = BuildFlowsMap(&ueCb->drbList[idx], &drbSetItem->qoSInformation.choice.choice_extension->\
-               value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, TRUE);
+               value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, ueCb->hoInfo.HOType);
       if(BuildFlowsMapret != ROK)
       {
          DU_LOG("\nERROR  -->  F1AP : Failed to build Flow Map Info in BuildDRBSetup");
@@ -3040,7 +3042,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet
                FALSE);
       else
          BuildULTnlInforet = BuildULTnlInfo(duId, &ueCb->drbList[idx].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\
-               TRUE);
+               ueCb->hoInfo.HOType);
       if(BuildULTnlInforet != ROK)
       {
          DU_LOG("\nERROR  -->  F1AP : Failed to build tunnel Info in BuildDRBSetup");
@@ -3048,7 +3050,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet
       }
 
       /*RLCMode*/
-      if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+      if((ueCb->state != UE_HANDOVER_IN_PROGRESS) || (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO))
       {
          drbSetItem->rLCMode = RLCMode_rlc_um_bidirectional;
          ueCb->drbList[ueCb->numDrb].rlcMode = drbSetItem->rLCMode;
@@ -9228,6 +9230,7 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb)
    uint8_t   elementCnt;
    uint8_t   idx, idx1, bufLen, duIdx;
    uint32_t  spCellId;
+   uint32_t  targetDuId;
    DuDb      *targetDuDb = NULLP;
    F1AP_PDU_t          *f1apMsg = NULLP;
    UEContextSetupRequest_t *ueSetReq = NULLP;
@@ -9313,16 +9316,23 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb)
       ueSetReq->protocolIEs.list.array[idx]->id        = ProtocolIE_ID_id_SpCell_ID;
       ueSetReq->protocolIEs.list.array[idx]->criticality       =       Criticality_reject;
       ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_NRCGI;
+
+      /* Spec 38.473 Sec 9.2.2.1 : For handover case, this IE shall be considered as target cell. */
       if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
       {
-         /* Spec 38.473 Sec 9.2.2.1 : For handover case, this IE shall be considered as target cell. */
-         SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetId, targetDuDb);
+         if(ueCb->hoInfo.HOType == Inter_DU_HO)
+            targetDuId = ueCb->hoInfo.tgtNodeId;
+         else
+            targetDuId = duId;
+
+         SEARCH_DU_DB(duIdx, targetDuId, targetDuDb);
          /* Since we are supporting only one cell per DU, accessing 0th index to
           * get target cell info */
          spCellId = targetDuDb->cellCb[0].nrCellId;
       }
       else
          spCellId = ueCb->cellCb->nrCellId;
+
       Nrcgiret = BuildNrcgi(&ueSetReq->protocolIEs.list.array[idx]->value.choice.NRCGI, spCellId);
       if(Nrcgiret != ROK)
       {
@@ -9618,7 +9628,7 @@ uint8_t procDrbSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_Setup_List_t *drbSetu
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
+uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, char *recvBuf, MsgLen recvBufLen)
 {
    uint8_t duIdx = 0, idx = 0, ueIdx = 0, rrcMsgType=0;
    uint8_t duUeF1apId = 0, cuUeF1apId = 0;
@@ -9650,11 +9660,24 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
                 {
                    /* Creating UE context in target DU */
                    memset(ueCb, 0, sizeof(CuUeCb));
-                   ueCb->cellCb = &duDb->cellCb[0];
-                   ueCb->gnbDuUeF1apId = duUeF1apId;
-                   ueCb->gnbCuUeF1apId = cuUeF1apId;
-                   ueCb->state = UE_HANDOVER_IN_PROGRESS;
-                   ueCb->hoInfo.targetId = duId; 
+
+                   /* Check if UE is under Inter-CU handover */
+                   if(duDb->tempUeCtxtInHo && (duDb->tempUeCtxtInHo->gnbCuUeF1apId == cuUeF1apId))
+                   {
+                      memcpy(ueCb, duDb->tempUeCtxtInHo, sizeof(CuUeCb));
+                      ueCb->gnbDuUeF1apId = duUeF1apId;
+                      CU_FREE(duDb->tempUeCtxtInHo, sizeof(CuUeCb));
+                   }
+                   else
+                   {
+                      /* In case of Inter DU Handover */
+                      ueCb->cellCb = &duDb->cellCb[0];
+                      ueCb->gnbDuUeF1apId = duUeF1apId;
+                      ueCb->gnbCuUeF1apId = cuUeF1apId;
+                      ueCb->state = UE_HANDOVER_IN_PROGRESS;
+                      ueCb->hoInfo.HOType = Inter_DU_HO;
+                      ueCb->hoInfo.tgtNodeId = duId; 
+                   }
                    (duDb->numUe)++;
 
                    ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb;
@@ -9689,65 +9712,73 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
       }
    }
    
-   /* If the UE is in handover, UE context modification request is to be sent to
-    * source DU once UE context setup response is received from target DU */
-   if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
+   if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
    {
-      DuDb *srcDuDb = NULLP;
-      CuUeCb *ueCbInSrcDu = NULLP;
+      ueCb->f1apMsgDb.dlRrcMsgCount++;
+      rrcMsgType = setDlRRCMsgType(ueCb);
 
-      /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we
-       * need to find Source DU and UE CB in source DU using CU UE F1AP ID */
-      for(duIdx=0; duIdx < cuCb.numDu; duIdx++)
+      DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for RRC reconfiguration");
+      if(BuildAndSendDLRRCMessageTransfer(duId, ueCb, SRB1, rrcMsgType) != ROK)
+      {     
+         DU_LOG("\nINFO  -->  F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration");
+         return RFAILED;
+      }     
+   }
+   else if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
+   {
+      if(ueCb->hoInfo.HOType == Inter_DU_HO)
       {
-         /* UE context setup response is received from target DU. Search all
-          * DUs to find source DU except this target DU Id.*/
-         if(cuCb.duInfo[duIdx].duId != duId)
+         /* If the UE is in Inter-DU handover, UE context modification request is to be sent to
+          * source DU once UE context setup response is received from target DU */
+
+         DuDb *srcDuDb = NULLP;
+         CuUeCb *ueCbInSrcDu = NULLP;
+
+         /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we
+          * need to find Source DU and UE CB in source DU using CU UE F1AP ID */
+         for(duIdx=0; duIdx < cuCb.numDu; duIdx++)
          {
-            for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
+            /* UE context setup response is received from target DU. Search all
+             * DUs to find source DU except this target DU Id.*/
+            if(cuCb.duInfo[duIdx].duId != duId)
             {
-               /* Check following:
-                * 1. CU UE F1AP ID in srcDU->ueCb should be same as cuUeF1apId
-                * received in UE context setup response since CU UE F1AP ID does not
-                * change for UE in handover.
-                * 2. srcDU->UeCb->uestate should be UE_HANDOVER_IN_PROGRESS
-                */
-               if((cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) &&
-                     (cuCb.duInfo[duIdx].ueCb[ueIdx].state == UE_HANDOVER_IN_PROGRESS))
+               for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
                {
-                  srcDuDb = &cuCb.duInfo[duIdx];
-                  ueCbInSrcDu = &cuCb.duInfo[duIdx].ueCb[ueIdx];
+                  /* Check following:
+                   * 1. CU UE F1AP ID in srcDU->ueCb should be same as cuUeF1apId
+                   * received in UE context setup response since CU UE F1AP ID does not
+                   * change for UE in handover.
+                   * 2. srcDU->UeCb->uestate should be UE_HANDOVER_IN_PROGRESS
+                   */
+                  if((cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) &&
+                        (cuCb.duInfo[duIdx].ueCb[ueIdx].state == UE_HANDOVER_IN_PROGRESS))
+                  {
+                     srcDuDb = &cuCb.duInfo[duIdx];
+                     ueCbInSrcDu = &cuCb.duInfo[duIdx].ueCb[ueIdx];
 
-                  /* Store source DU info in the new UE context created in
-                   * tareget DU */
-                  ueCb->hoInfo.sourceId = srcDuDb->duId;
+                     /* Store source DU info in the new UE context created in
+                      * tareget DU */
+                     ueCb->hoInfo.srcNodeId = srcDuDb->duId;
 
-                  /* Copy the received container to UeCb */
-                  memcpy(&ueCbInSrcDu->f1apMsgDb.duToCuContainer, duToCuRrcContainer, sizeof(OCTET_STRING_t));
+                     /* Copy the received container to UeCb */
+                     memcpy(&ueCbInSrcDu->f1apMsgDb.duToCuContainer, duToCuRrcContainer, sizeof(OCTET_STRING_t));
 
-                  if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK)
-                  {
-                     DU_LOG("\nERROR  ->  F1AP : Failed at BuildAndSendUeContextModificationReq()");
-                     return RFAILED;
+                     if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK)
+                     {
+                        DU_LOG("\nERROR  ->  F1AP : Failed at BuildAndSendUeContextModificationReq()");
+                        return RFAILED;
+                     }
+                     break;
                   }
-                  break;
                }
             }
+            if(srcDuDb && ueCbInSrcDu)
+               break;
          }
-         if(srcDuDb && ueCbInSrcDu)
-            break;
       }
-   }
-   else
-   {
-      ueCb->f1apMsgDb.dlRrcMsgCount++;
-      rrcMsgType = setDlRRCMsgType(ueCb);
-
-      DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for RRC reconfiguration");
-      if(BuildAndSendDLRRCMessageTransfer(duId, ueCb, SRB1, rrcMsgType) != ROK)
+      else if(ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO)
       {
-         DU_LOG("\nINFO  -->  F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration");
-         return RFAILED;
+         BuildAndSendHOReqAck(ueCb, recvBuf, recvBufLen);
       }
    }
 
@@ -9816,7 +9847,7 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
                if(duDb->ueCb[duUeF1apId-1].state == UE_HANDOVER_IN_PROGRESS)
                {
                   uint8_t ueIdx = 0;
-                  uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.sourceId;
+                  uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.srcNodeId;
                   DuDb *srcDuDb = NULLP;
 
                   /* In target DU DB, mark UE as active and delete HO info */
@@ -11806,17 +11837,17 @@ uint8_t procDrbSetupModList(uint32_t duId, CuUeCb *ueCb, DRBs_SetupMod_List_t *d
 
             if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
             {
-            /* extracting teId */
-            teId  = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List);
-            if(teId > 0)
-            {
-              if(addDrbTunnels(duId, teId)== ROK)
-              {
-                DU_LOG("\nDEBUG  --> EGTP: Tunnel Added for TeId %d", teId);
-              }
-            }
-            else
-               return RFAILED;
+               /* extracting teId */
+               teId  = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List);
+               if(teId > 0)
+               {
+                  if(addDrbTunnels(duId, teId)== ROK)
+                  {
+                     DU_LOG("\nDEBUG  --> EGTP: Tunnel Added for TeId %d", teId);
+                  }
+               }
+               else
+                  return RFAILED;
             }
          }
       }
@@ -11908,6 +11939,10 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, ch
 
    SEARCH_DU_DB(duIdx, duId, duDb);
    ueCtxtModRsp = &f1apMsg->choice.successfulOutcome->value.choice.UEContextModificationResponse;
+
+   /* In case of Inter-CU Handover request received from peer CU */
+   if(duDb->tempUeCtxtInHo)
+      ueCb = duDb->tempUeCtxtInHo;
    
    for(idx=0; idx < ueCtxtModRsp->protocolIEs.list.count; idx++)
    {
@@ -11915,17 +11950,28 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, ch
       {
           case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
              {
-                cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID;
+                if(ueCb == NULLP)
+                {
+                   cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID;
+                }
+                else
+                {
+                   /* In case of Inter-CU Handover request received from peer CU */
+                   cuUeF1apId = ueCb->gnbCuUeF1apId;
+                }
                 break;
              }
           case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
              {
-                duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
-                ueCb = &duDb->ueCb[duUeF1apId-1];
-
-                if((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO))
+                if(!ueCb)
                 {
-                   BuildAndSendHOReq(ueCb, HO_REQ, recvBuf, recvBufLen);
+                   duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
+                   ueCb = &duDb->ueCb[duUeF1apId-1];
+
+                   if((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO))
+                   {
+                      BuildAndSendHOReq(ueCb, recvBuf, recvBufLen);
+                   }
                 }
                 break;
              }
@@ -11965,41 +12011,48 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, ch
     * UE context setup request to target DU */
    if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
    {
+      uint8_t ueIdx = 0;
+      uint8_t tgtDuId = 0;
+      DuDb *tgtDuDb = NULLP;
+      CuUeCb *ueCbInTgtDu = NULLP;
+
       if(ueCb->hoInfo.HOType == Inter_DU_HO)
       {
-         uint8_t ueIdx = 0;
-         DuDb *tgtDuDb = NULLP;
-         CuUeCb *ueCbInTgtDu = NULLP;
+         tgtDuId = ueCb->hoInfo.tgtNodeId;
+      }
+      else if (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO)
+      {
+         tgtDuId =  duId;
+      }
 
-         SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetId, tgtDuDb);
-         if(tgtDuDb)
+      SEARCH_DU_DB(duIdx, tgtDuId, tgtDuDb);
+      if(tgtDuDb)
+      {
+         /* Since DU UE F1AP ID assigned by target DU to this UE in handover is
+          * not known here, using CU UE F1AP ID to search for UE Cb in target DU
+          * DB */
+         for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
          {
-            /* Since DU UE F1AP ID assigned by target DU to this UE in handover is
-             * not known here, using CU UE F1AP ID to search for UE Cb in target DU
-             * DB */
-            for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
+            if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
             {
-               if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
-               {
-                  ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx];
-                  break;
-               }
+               ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx];
+               break;
             }
+         }
 
-            /* If UE context is not found in Target DU DU, send UE context setup
-             * request */
-            if(ueCbInTgtDu == NULLP)
+         /* If UE context is not found in Target DU, send UE context setup
+          * request */
+         if(ueCbInTgtDu == NULLP)
+         {
+            if((BuildAndSendUeContextSetupReq(tgtDuId, ueCb)) != ROK)
             {
-               if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetId, ueCb)) != ROK)
-               {
-                  DU_LOG("\nERROR  ->  F1AP : Failed at BuildAndSendUeContextSetupReq");
-                  return RFAILED;
-               }
+               DU_LOG("\nERROR  ->  F1AP : Failed at BuildAndSendUeContextSetupReq");
+               return RFAILED;
             }
          }
       }
    }
-   
+
 #ifdef START_DL_UL_DATA
    startDlData();
 #endif
@@ -12546,7 +12599,7 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId)
 
 /*******************************************************************
  *
- * @brief Handles received F1AP message and sends back response  
+ * @brief Decode received character string into F1AP message 
  *
  * @details
  *
@@ -12554,61 +12607,86 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId)
  *
  *    Functionality:
  *         - Decodes received F1AP control message
- *         - Prepares response message, encodes and sends to SCTP
  *
  * @params[in] 
  * @return ROK     - success
  *         RFAILED - failure
  *
  * ****************************************************************/
-void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf)
+uint8_t F1APDecodeMsg(F1AP_PDU_t *f1apMsg, Buffer *mBuf, char **recvBuf, MsgLen *recvBufLen)
 {
    int i;
-   char *recvBuf;
    MsgLen copyCnt;
-   MsgLen recvBufLen;
-   F1AP_PDU_t *f1apMsg = NULLP;
    asn_dec_rval_t rval; /* Decoder return value */
-   F1AP_PDU_t f1apasnmsg ;
-
-   DU_LOG("\nINFO  -->  F1AP : Received F1AP message buffer");
-   ODU_PRINT_MSG(mBuf, 0,0);
 
    /* Copy mBuf into char array to decode it */
-   ODU_GET_MSG_LEN(mBuf, &recvBufLen);
-   CU_ALLOC(recvBuf, (Size)recvBufLen);
-
-   if(recvBuf == NULLP)
+   ODU_GET_MSG_LEN(mBuf, recvBufLen);
+   CU_ALLOC(*recvBuf, (Size)(*recvBufLen));
+   if(*recvBuf == NULLP)
    {
       DU_LOG("\nERROR  -->  F1AP : Memory allocation failed");
-      return;
+      return RFAILED;
    }
-   if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, recvBufLen, (Data *)recvBuf, &copyCnt) != ROK)
+   if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, *recvBufLen, (Data *)*recvBuf, &copyCnt) != ROK)
    {
       DU_LOG("\nERROR  -->  F1AP : Failed while copying %d", copyCnt);
-      return;
+      return RFAILED;
    }
 
-   DU_LOG("\nDEBUG  -->  F1AP : Received flat buffer to be decoded : ");
-   for(i=0; i< recvBufLen; i++)
+   DU_LOG("\nDEBUG  -->  F1AP : Received flat buffer to be decoded : \n");
+   for(i=0; i< *recvBufLen; i++)
    {
-      DU_LOG("%x",recvBuf[i]);
+      DU_LOG("%x ",(*recvBuf)[i]);
    }
 
    /* Decoding flat buffer into F1AP messsage */
-   f1apMsg = &f1apasnmsg;
-   memset(f1apMsg, 0, sizeof(F1AP_PDU_t));
-
-   rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, recvBuf, recvBufLen, 0, 0);
-   CU_FREE(recvBuf, (Size)recvBufLen);
-
+   rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, *recvBuf, *recvBufLen, 0, 0);
    if(rval.code == RC_FAIL || rval.code == RC_WMORE)
    {
       DU_LOG("\nERROR  -->  F1AP : ASN decode failed");
-      return;
+      return RFAILED;
    }
+
+   /* Printing the decoded F1AP PDU */
    DU_LOG("\n");
    xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
+   return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Handles received F1AP message and sends back response  
+ *
+ * @details
+ *
+ *    Function : F1APMsgHdlr
+ *
+ *    Functionality:
+ *         - Decodes received F1AP control message
+ *         - Prepares response message, encodes and sends to SCTP
+ *
+ * @params[in] 
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf)
+{
+   char *recvBuf;
+   MsgLen recvBufLen;
+   F1AP_PDU_t *f1apMsg = NULLP;
+   F1AP_PDU_t f1apasnmsg ;
+
+   DU_LOG("\nINFO  -->  F1AP : Received F1AP message buffer");
+   ODU_PRINT_MSG(mBuf, 0,0);
+
+   f1apMsg = &f1apasnmsg;
+   memset(f1apMsg, 0, sizeof(F1AP_PDU_t));
+   if(F1APDecodeMsg(f1apMsg, mBuf, &recvBuf, &recvBufLen) != ROK)
+   {
+      DU_LOG("\nERROR  -->  F1AP : F1AP PDU decode failed");
+      return;
+   }
 
    switch(f1apMsg->present)
    {
@@ -12682,7 +12760,7 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf)
                case SuccessfulOutcome__value_PR_UEContextSetupResponse:
                   {
                      DU_LOG("\nINFO  -->  F1AP : UE ContextSetupResponse received");
-                     procUeContextSetupResponse(*duId, f1apMsg);
+                     procUeContextSetupResponse(*duId, f1apMsg, recvBuf, recvBufLen);
                      break;
                   }
                case SuccessfulOutcome__value_PR_UEContextModificationResponse:
@@ -12713,6 +12791,7 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf)
          }
    }/* End of switch(f1apMsg->present) */
 
+   CU_FREE(recvBuf, (Size)(recvBufLen));
 } /* End of F1APMsgHdlr */
 
 /**********************************************************************
index b817edf..6a9c7dd 100644 (file)
@@ -286,8 +286,8 @@ void initiateInterDuHandover(uint32_t sourceDuId, uint32_t targetDuId, uint32_t
    {
       ueCb->state = UE_HANDOVER_IN_PROGRESS;
       ueCb->hoInfo.HOType = Inter_DU_HO;
-      ueCb->hoInfo.sourceId = sourceDuId;
-      ueCb->hoInfo.targetId = targetDuId;
+      ueCb->hoInfo.srcNodeId = sourceDuId;
+      ueCb->hoInfo.tgtNodeId = targetDuId;
 
       BuildAndSendUeContextModificationReq(sourceDuId, ueCb, QUERY_CONFIG);
    }
@@ -316,13 +316,13 @@ void initiateInterDuHandover(uint32_t sourceDuId, uint32_t targetDuId, uint32_t
  *         RFAILED - failure
  *
  * ****************************************************************/
-void initiateInterCuHandover(uint32_t sourceCuId, uint32_t targetCuId, uint32_t cuUeF1apId)
+void initiateInterCuHandover(uint32_t targetCuId, uint32_t cellId, uint32_t cuUeF1apId)
 {
     uint8_t  duIdx, ueIdx;
     CuUeCb   *ueCb = NULLP;
 
-    DU_LOG("\nINFO  --> CU_STUB: Inter-CU Handover Started for ueId [%d] from CU ID [%d] to CU ID [%d]", \
-          cuUeF1apId, sourceCuId, targetCuId);
+    DU_LOG("\nINFO  --> CU_STUB: Inter-CU Handover Started for ueId [%d] to CU ID [%d]", \
+          cuUeF1apId, targetCuId);
 
     for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
     {
@@ -343,8 +343,11 @@ void initiateInterCuHandover(uint32_t sourceCuId, uint32_t targetCuId, uint32_t
     {   
        ueCb->state = UE_HANDOVER_IN_PROGRESS;
        ueCb->hoInfo.HOType = Xn_Based_Inter_CU_HO;
-       ueCb->hoInfo.sourceId = sourceCuId;
-       ueCb->hoInfo.targetId = targetCuId;
+       ueCb->hoInfo.srcNodeId = cuCb.cuCfgParams.cuId;
+       ueCb->hoInfo.tgtNodeId = targetCuId;
+       ueCb->hoInfo.tgtCellId = cellId;
+       ueCb->hoInfo.cuUeF1apIdSrc = ueCb->gnbCuUeF1apId;
+
        BuildAndSendUeContextModificationReq(cuCb.duInfo[duIdx].duId, ueCb, QUERY_CONFIG);
     }   
     else
@@ -485,32 +488,32 @@ void *cuConsoleHandler(void *args)
       else if(ch == 'h')
       {
          HandoverType hoType;
-         uint32_t sourceId, targetId, ueId;
+         uint32_t srcNodeId, tgtNodeId, targetCellId, ueId;
 
          DU_LOG("\n\nChoose the type of handover to initiate : \nEnter 1 for Inter-CU Handover over Xn interface\nEnter 2 for Inter-DU Handover\n");
          scanf("%d", &hoType);
 
          if(hoType == Xn_Based_Inter_CU_HO)
          {
-            DU_LOG("\nEnter Source CU ID for Inter-CU Handover : ");
-            scanf("%d", &sourceId);
             DU_LOG("\nEnter Target CU ID for Inter-CU Handover : ");
-            scanf("%d", &targetId);
+            scanf("%d", &tgtNodeId);
+            DU_LOG("\nEnter Target Physical Cell ID for Inter-CU Handover : ");
+            scanf("%d", &targetCellId);
             DU_LOG("\nEnter CU UE F1AP ID to be handed over : ");
             scanf("%d", &ueId);
 
-            initiateInterCuHandover(sourceId, targetId, ueId);
+            initiateInterCuHandover(tgtNodeId, targetCellId, ueId);
          }
          else if(hoType == Inter_DU_HO)
          {
             DU_LOG("\nEnter Source DU ID for Inter-DU Handover : ");
-            scanf("%d", &sourceId);
+            scanf("%d", &srcNodeId);
             DU_LOG("\nEnter Target DU ID for Inter-DU Handover : ");
-            scanf("%d", &targetId);
+            scanf("%d", &tgtNodeId);
             DU_LOG("\nEnter DU UE F1AP ID to be handed over : ");
             scanf("%d", &ueId);
 
-            initiateInterDuHandover(sourceId, targetId, ueId);
+            initiateInterDuHandover(srcNodeId, tgtNodeId, ueId);
          }
       }
       /* Start Idle mode paging when 'p' is received from console input */
index 08cb36b..b809981 100644 (file)
@@ -116,7 +116,8 @@ typedef enum
 {
    XN_SETUP_REQ,
    XN_SETUP_RSP,
-   HO_REQ
+   HO_REQ,
+   HO_REQ_ACK
 }XnEventType;
 
 typedef enum
@@ -153,8 +154,11 @@ typedef struct cuCfgParams
 typedef struct handoverInfo
 {
    HandoverType HOType;
-   uint32_t sourceId;   /* If Inter_DU HO, this is Source DU ID. In case of Inter CU HO, this is Source CU ID */
-   uint32_t targetId;   /* If Inter_DU HO, this is Taregt DU ID. In case of Inter CU HO, this is Target CU ID */
+   uint32_t srcNodeId;   /* If Inter_DU HO, this is Source DU ID. In case of Inter CU HO, this is Source CU ID */
+   uint32_t tgtNodeId;   /* If Inter_DU HO, this is Taregt DU ID. In case of Inter CU HO, this is Target CU ID */
+   uint32_t tgtCellId;   /* Cell Id in target node to which UE is to be handed over */
+   uint8_t  cuUeF1apIdSrc;  /* Used for Inter-CU HO. CU UE F1AP ID of UE in source CU */
+   uint8_t  cuUeF1apIdTgt;  /* Used for Inter-CU HO. CU UE F1AP ID of UE in target CU */
 }HandoverInfo;
 
 typedef struct dlAmCfg
@@ -352,6 +356,7 @@ typedef struct duDb
    CuCellCb cellCb[MAX_NUM_CELL];  
    uint8_t  numUe;
    CuUeCb   ueCb[MAX_NUM_CELL * MAX_NUM_UE];
+   CuUeCb   *tempUeCtxtInHo;
 }DuDb;
 
 typedef struct cuGlobalCb
index 26d7329..436809a 100644 (file)
@@ -21,6 +21,7 @@
 #include "cu_stub_sctp.h"
 #include "cu_stub_egtp.h"
 #include "OCTET_STRING.h"
+#include "F1AP-PDU.h"
 #include "cu_f1ap_msg_hdl.h"
 #include "cu_stub.h"
 
@@ -165,16 +166,18 @@ void XNAPProcXnSetupRsp(uint32_t *destId, Buffer *mBuf)
  * @return void
  *
  ******************************************************************/
-void BuildAndSendHOReq(CuUeCb *ueCb, XnEventType event, char *xnMsg, MsgLen xnMsgLen)
+void BuildAndSendHOReq(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen)
 {
    Buffer *mBuf = NULLP;
 
    if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
    {
       if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK)
-      {     
-         CMCHKPK(oduUnpackUInt8, event, mBuf);
-         if(sctpSend(XN_INTERFACE, ueCb->hoInfo.targetId, mBuf) != ROK)
+      {  
+         CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
+         CMCHKPK(oduUnpackUInt32, ueCb->hoInfo.tgtCellId, mBuf);
+         CMCHKPK(oduUnpackUInt8, HO_REQ, mBuf);
+         if(sctpSend(XN_INTERFACE, ueCb->hoInfo.tgtNodeId, mBuf) != ROK)
          {
             DU_LOG("\nERROR  -->  CU_STUB: Failed to send handover request to peer CU");
             ueCb->state = UE_ACTIVE;
@@ -184,6 +187,154 @@ void BuildAndSendHOReq(CuUeCb *ueCb, XnEventType event, char *xnMsg, MsgLen xnMs
    }
 }
 
+/*******************************************************************
+ *
+ * @brief Process received Handover Request
+ *
+ * @details
+ *
+ *    Function : XNAPProcHandoverReq
+ *
+ *    Functionality:
+ *       1. Unpack Cell Id from msg and find DU to which it belongs
+ *       2. Create UE context for UE in handover and store in DU DB
+ *       3. Decode the F1AP UE context modification msg received in 
+ *          XNAP message buffer and extract UE configurations
+ *       4. Send UE context setup request to DU with these configs 
+ *
+ * @params[in] Pointer to destination Id
+ *             Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPProcHandoverReq(uint32_t destId, Buffer *mBuf)
+{
+   uint8_t duIdx, cellIdx;
+   uint8_t cuUeF1apIdSrc;
+   uint32_t cellId;
+   DuDb *duDb;
+   CuCellCb *cellCb;
+
+   DU_LOG("\nINFO  -->  CU STUB : Received Handover Request");
+   
+   /* Find DU Db and Cell Cb from cellId */
+   CMCHKUNPK(oduPackUInt32, &(cellId), mBuf);
+   for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
+   {
+      duDb = &cuCb.duInfo[duIdx];
+      SEARCH_CELL_DB(cellIdx, duDb, cellId, cellCb)
+      if(cellCb)
+         break;
+   }
+   if(!cellCb)
+   {
+      DU_LOG("\nERROR  -->  CU_STUB: Failed to find Cell Id [%d] received in HO Request", cellId);
+      return;
+   }
+
+   /* Fetch CU UE F1AP ID of UE in handover assigned by source CU */
+   CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf);
+
+   /* Filling temporary UE context which will be used to create actual UE context at
+    * CU later */
+   CU_ALLOC(duDb->tempUeCtxtInHo, sizeof(CuUeCb));
+   if(!duDb->tempUeCtxtInHo)
+   {
+      DU_LOG("\nERROR  -->  XNAP : Failed to allocate memory to temporary UE context for UE in handover");
+      return;
+   }
+   memset(duDb->tempUeCtxtInHo, 0, sizeof(CuUeCb));
+   duDb->tempUeCtxtInHo->cellCb = cellCb;
+   duDb->tempUeCtxtInHo->gnbCuUeF1apId = ++cuCb.gnbCuUeF1apIdGenerator;
+   duDb->tempUeCtxtInHo->state = UE_HANDOVER_IN_PROGRESS;
+   duDb->tempUeCtxtInHo->hoInfo.HOType = Xn_Based_Inter_CU_HO;
+   duDb->tempUeCtxtInHo->hoInfo.srcNodeId = destId;
+   duDb->tempUeCtxtInHo->hoInfo.tgtNodeId = cuCb.cuCfgParams.cuId;
+   duDb->tempUeCtxtInHo->hoInfo.tgtCellId = cellId;
+   duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdSrc = cuUeF1apIdSrc;
+   duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdTgt = duDb->tempUeCtxtInHo->gnbCuUeF1apId;
+
+   /* Decode UE context modification response msg received in Xn Msg */
+   char *recvBuf;
+   MsgLen recvBufLen, copyLen;
+   F1AP_PDU_t *f1apMsg = NULLP;
+   F1AP_PDU_t f1apasnmsg ;
+
+   f1apMsg = &f1apasnmsg;
+   memset(f1apMsg, 0, sizeof(F1AP_PDU_t));
+   if(F1APDecodeMsg(f1apMsg, mBuf, &recvBuf, &recvBufLen) != ROK)
+   {
+      DU_LOG("\nERROR  -->  F1AP : F1AP PDU decode failed");
+      return;
+   }
+   CU_FREE(recvBuf, recvBufLen);
+   procUeContextModificationResponse(duDb->duId, f1apMsg, NULL, 0);
+}
+
+/*******************************************************************
+ *
+ * @brief Build And send dummy Handover request ack to Peer CU
+ *
+ * @details
+ *
+ *    Function : BuildAndSendHOReqAck
+ *
+ *    Functionality:
+ *       Build And send dummy Handover request ack to Peer CU
+ *
+ * @params[in] Pointer to UE Cb
+ *             Message to be sent
+ *             Message Length
+ * @return void
+ *
+ ******************************************************************/
+void BuildAndSendHOReqAck(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen)
+{
+   Buffer *mBuf = NULLP;
+
+   if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
+   {   
+      if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK)
+      {   
+         CMCHKPK(oduUnpackUInt8, ueCb->gnbCuUeF1apId, mBuf);
+         CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
+         CMCHKPK(oduUnpackUInt8, HO_REQ_ACK, mBuf);
+         if(sctpSend(XN_INTERFACE, ueCb->hoInfo.srcNodeId, mBuf) != ROK)
+         {
+            DU_LOG("\nERROR  -->  CU_STUB: Failed to send handover request ack to peer CU");
+         }
+      }
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Process received Handover Request Ack
+ *
+ * @details
+ *
+ *    Function : XNAPProcHandoverReqAck
+ *
+ *    Functionality:
+ *       1. Unpack CU UE F1AP ID (by SCU) and search for UE CB and
+ *          the corresponding DU DB (SDU)
+ *       2. Unpack CU UE F1AP ID (by TCU) and fill in UEcb->hoInfo
+ *       3. Decode the F1AP UE context setup response msg received in 
+ *          XNAP message buffer and extract UE configurations
+ *       4. Create RRC reconfig msg with these configurations
+ *       5. Send RRC Reconfig msg and Transmission Action = DO NOT TRANSMIT
+ *          in UE context modification request to S DU
+ *
+ * @params[in] Pointer to destination Id
+ *             Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPProcHandoverReqAck(uint32_t destId, Buffer *mBuf)
+{
+   DU_LOG("\nINFO  -->  CU STUB : Received Handover Request Acknowledgement");
+}
+
 /*******************************************************************
  *
  * @brief Handle incoming messages at Xn interface
@@ -223,56 +374,13 @@ void XNAPMsgHdlr(uint32_t *destId, Buffer *mBuf)
 
       case HO_REQ:
          {
-            DU_LOG("\nINFO  -->  CU STUB : Received Handover Request at XNAP");
-
-//Handling of HO Request to be added in next gerrit
-#if 0
-            char *recvBuf;
-            MsgLen copyCnt;
-            MsgLen recvBufLen;
-            F1AP_PDU_t *f1apMsg = NULLP;
-            asn_dec_rval_t rval; /* Decoder return value */
-            F1AP_PDU_t f1apasnmsg ;
-
-            ODU_PRINT_MSG(mBuf, 0,0); 
-
-            /* Copy mBuf into char array to decode it */
-            ODU_GET_MSG_LEN(mBuf, &recvBufLen);
-            CU_ALLOC(recvBuf, (Size)recvBufLen);
-
-            if(recvBuf == NULLP)
-            {
-               DU_LOG("\nERROR  -->  F1AP : Memory allocation failed");
-               return;
-            }
-            if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, recvBufLen, (Data *)recvBuf, &copyCnt) != ROK)
-            {
-               DU_LOG("\nERROR  -->  F1AP : Failed while copying %d", copyCnt);
-               return;
-            }
-
-            DU_LOG("\nDEBUG  -->  F1AP : Received flat buffer to be decoded : ");
-            for(i=0; i< recvBufLen; i++)
-            {
-               DU_LOG("%x",recvBuf[i]);
-            }
-
-            /* Decoding flat buffer into F1AP messsage */
-            f1apMsg = &f1apasnmsg;
-            memset(f1apMsg, 0, sizeof(F1AP_PDU_t));
-            rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, recvBuf, recvBufLen, 0, 0);
-            CU_FREE(recvBuf, (Size)recvBufLen);
-
-            if(rval.code == RC_FAIL || rval.code == RC_WMORE)
-            {
-               DU_LOG("\nERROR  -->  F1AP : ASN decode failed");
-               return;
-            }
-            DU_LOG("\n");
-            xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
-
-            procUeContextModificationResponse(0, f1apMsg, recvBuf, recvBufLen);      
-#endif            
+            XNAPProcHandoverReq(*destId, mBuf);
+            break;
+         }
+      
+      case HO_REQ_ACK:
+         {
+            XNAPProcHandoverReqAck(*destId, mBuf);
             break;
          }
       default: