[Issue Id- ODUHIGH-451] Fixes in F1 Setup procedure and UE attach call flow
[o-du/l2.git] / src / cu_stub / cu_f1ap_msg_hdl.c
index 563ea45..e4ada4e 100644 (file)
 #include "MeasConfigRrc.h"
 #include "AS-Config.h"
 #include "RRCReconfiguration-v1530-IEs.h"
+#include "CNUEPagingIdentity.h"
+#include "PagingCell-Item.h"
+#include "UL-DCCH-Message.h"
 
 #include "cu_stub_sctp.h"
 #include "cu_stub_egtp.h"
@@ -186,31 +189,6 @@ S16 SendF1APMsg(Region region, Pool pool, uint32_t duId)
    return ROK;
 } /* SendF1APMsg */
 
-/*******************************************************************
- *
- * @brief Builds NRCell ID 
- *
- * @details
- *
- *    Function : BuildNrCellId
- *
- *    Functionality: Building the NR Cell ID
- *
- * @params[in] BIT_STRING_t *nrcell
- * @return ROK     - success
- *         RFAILED - failure
- *
- * ****************************************************************/
-
-S16 BuildNrCellId(BIT_STRING_t *nrcell)
-{
-   memset(nrcell->buf, 0, nrcell->size);
-   nrcell->buf[4]   = 16; 
-   nrcell->bits_unused = 4;
-   nrcell->size = 5 * sizeof(uint8_t);
-   return ROK;
-}
-
 /********************************************************************
  *
  * @brief Builds and sends the F1SetupResponse
@@ -416,10 +394,11 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId)
    buildPlmnId(cuCb.cuCfgParams.plmn , cellToActivate->list.array[0]->value.choice.\
          Cells_to_be_Activated_List_Item.nRCGI.pLMN_Identity.buf);
    cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.\
-      nRCGI.nRCellIdentity.size = 5;
+      nRCGI.nRCellIdentity.size = 5*sizeof(uint8_t);
    CU_ALLOC(cellToActivate->list.array[0]->value.choice.\
          Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity.buf,\
-         5*sizeof(uint8_t));
+         cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.\
+        nRCGI.nRCellIdentity.size);
    if(cellToActivate->list.array[0]->value.choice.\
          Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity.buf == NULLP)
    {
@@ -1179,6 +1158,22 @@ uint8_t fillDlCcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer)
    }
 }
 
+/*******************************************************************
+ *
+ * @brief Fills QOS flow configuration  
+ *
+ * @details
+ *
+ *    Function : fillQosFlowsToAdd
+ *
+ *    Functionality: Fills QOS flow configuration
+ *
+ * @params[in] struct SDAP_Config__mappedQoS_FlowsToAdd *qosFlow 
+ *
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
 uint8_t fillQosFlowsToAdd(struct SDAP_Config__mappedQoS_FlowsToAdd *qosFlow)
 {
    uint8_t idx, ied, elementCnt;
@@ -1516,9 +1511,28 @@ uint8_t  BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr
       if(ret == RFAILED)
          DU_LOG("\nERROR  -->  F1AP: Failed to fill DL-CCCH Msg at RRC SETUP");
    }
-   else if(rrcMsgType == REGISTRATION_ACCEPT)
+   else if(rrcMsgType == RRC_SETUP_COMPLETE)
+   {
+      DU_LOG("\nINFO --> F1AP : Sending Security mode command");
+      char secModeBuf[9]={0x00, 0x02, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00};
+      bufLen =9;
+      rrcContainer->size = bufLen;
+      CU_ALLOC(rrcContainer->buf, rrcContainer->size);
+      if(rrcContainer->buf != NULLP)
+      {
+         memset(rrcContainer->buf, 0, bufLen);
+         memcpy(rrcContainer->buf, secModeBuf, bufLen);
+      }
+      else
+      {
+         DU_LOG("\nERROR  -->  F1AP : Memory allocation failure for RRC Container buffer");
+         ret = RFAILED;
+      }
+   }
+   else if(rrcMsgType == SECURITY_MODE_COMPLETE)
    {
       /*Hardcoded RRC Container from reference logs*/
+      DU_LOG("\nINFO --> F1AP : Sending Registration accept");
       char buf[14] ={0x00, 0x03, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00};
       bufLen =14;
       rrcContainer->size = bufLen;
@@ -1534,9 +1548,9 @@ uint8_t   BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr
          ret = RFAILED;
       }
    }
-   else if(rrcMsgType == RRC_RECONFIG)
+   else if(rrcMsgType == UE_CONTEXT_SETUP_RSP)
    {
-      DU_LOG("\nDEBUG --> F1AP : Filling DL DCCH RRC Message ");
+      DU_LOG("\nINFO --> F1AP : Filling DL DCCH RRC Message for RRC Reconfiguration ");
       ret = fillDlDcchRrcMsg(ueCb, rrcContainer);
       if(ret == RFAILED)
          DU_LOG("\nERROR  -->  F1AP: Failed to fill DL-DCCH Msg for RRC Reconfiguration");
@@ -1750,24 +1764,21 @@ uint8_t setDlRRCMsgType(CuUeCb *ueCb)
       case RRC_SETUP:
          rrcMsgType = RRC_SETUP;
          break;
-      case REGISTRATION_ACCEPT:
-         rrcMsgType = REGISTRATION_ACCEPT;
-         break;
-      case UE_CONTEXT_SETUP_REQ:
-         rrcMsgType = UE_CONTEXT_SETUP_REQ;
+      case RRC_SETUP_COMPLETE:
+         rrcMsgType = RRC_SETUP_COMPLETE;
          break;
       case SECURITY_MODE_COMPLETE:
          rrcMsgType = SECURITY_MODE_COMPLETE;
          break;
-      case RRC_RECONFIG:
-         rrcMsgType = RRC_RECONFIG;
+      case REGISTRATION_COMPLETE:
+         rrcMsgType = REGISTRATION_COMPLETE;
+         break;
+      case UE_CONTEXT_SETUP_RSP:
+         rrcMsgType = UE_CONTEXT_SETUP_RSP;
          break;
       case RRC_RECONFIG_COMPLETE:
          rrcMsgType = RRC_RECONFIG_COMPLETE;
          break;
-      case UE_CONTEXT_MOD_REQ:
-         rrcMsgType = UE_CONTEXT_MOD_REQ;
-         break;
       default:
          break;
    }
@@ -1942,6 +1953,9 @@ uint8_t extractDuToCuRrcCont(CuUeCb *ueCb, OCTET_STRING_t rrcCont)
    CellGroupConfigRrc_t  cellGrpCfg, *cellGrpCfgMsg = NULLP;
    asn_dec_rval_t rval; /* Decoder return value */
 
+   /* Copy the received container to UeCb */
+   memcpy(&ueCb->f1apMsgDb.duToCuContainer, &rrcCont, sizeof(OCTET_STRING_t));
+
    /* Decoding DU to CU RRC container octet string to cell group config */
    cellGrpCfgMsg = &cellGrpCfg;
    memset(cellGrpCfgMsg, 0, sizeof(CellGroupConfigRrc_t));
@@ -1984,9 +1998,10 @@ uint8_t extractDuToCuRrcCont(CuUeCb *ueCb, OCTET_STRING_t rrcCont)
 
 uint8_t procInitULRRCMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
 {
-   uint8_t idx,cellIdx=0, duIdx=0, rrcMsgType, gnbDuUeF1apId;
+   uint8_t idx = 0, duIdx=0, rrcMsgType=0, gnbDuUeF1apId=0;
    uint8_t ret =ROK;
-   uint32_t nrCellId, crnti;
+   uint16_t cellIdx=0, nrCellId = 0;
+   uint32_t crnti;
    DuDb     *duDb;
    CuCellCb *cellCb;
    CuUeCb   *ueCb;
@@ -2006,8 +2021,7 @@ uint8_t procInitULRRCMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
             break;
 
          case ProtocolIE_ID_id_NRCGI:
-            nrCellId = initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity.buf[4] >>
-               initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity.bits_unused;
+            bitStringToInt(&initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity, &nrCellId);
             SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb);
             if(cellCb == NULLP)
                return RFAILED;
@@ -2099,7 +2113,6 @@ uint8_t BuildNrcgi(NRCGI_t *nrcgi, uint32_t nrCellId)
    uint8_t ret;
    uint8_t unused_bits = 4;
    uint8_t byteSize = 5;
-   uint8_t val = nrCellId << unused_bits;
 
    /* Allocate Buffer Memory */
    nrcgi->pLMN_Identity.size = 3 * sizeof(uint8_t);
@@ -2120,7 +2133,7 @@ uint8_t BuildNrcgi(NRCGI_t *nrcgi, uint32_t nrCellId)
    {
       return RFAILED;
    }
-   fillBitString(&nrcgi->nRCellIdentity, unused_bits, byteSize, val);
+   fillBitString(&nrcgi->nRCellIdentity, unused_bits, byteSize, nrCellId);
 
    return ROK;
 }
@@ -2533,7 +2546,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t BuildULTnlInfo(TnlInfo *ulUpTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, bool hoInProgress)
+uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, bool hoInProgress)
 {
    uint8_t idx;
    uint8_t ulCnt;
@@ -2645,7 +2658,7 @@ uint8_t BuildULTnlInfo(TnlInfo *ulUpTnlInfo, ULUPTNLInformation_ToBeSetup_List_t
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t BuildDRBSetup(CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet)
+uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet)
 {
    uint8_t idx = 0, extIeIdx = 0;
    uint8_t elementCnt = 0, drbCnt = 0;
@@ -2742,10 +2755,10 @@ uint8_t BuildDRBSetup(CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet)
 
       /*ULUPTNLInformation To Be Setup List*/
       if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
-         BuildULTnlInforet = BuildULTnlInfo(&ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\
+         BuildULTnlInforet = BuildULTnlInfo(duId, &ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\
                FALSE);
       else
-         BuildULTnlInforet = BuildULTnlInfo(&ueCb->drbList[idx].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\
+         BuildULTnlInforet = BuildULTnlInfo(duId, &ueCb->drbList[idx].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\
                TRUE);
       if(BuildULTnlInforet != ROK)
       {
@@ -6063,6 +6076,17 @@ uint8_t BuildRlcBearerToAddModList(CuUeCb *ueCb, struct CellGroupConfigRrc__rlc_
       }
    }
 
+   if(!elementCnt)
+   {
+      DU_LOG("INFO  --> F1AP : No  RLC Bearer available to add or modify");
+      return ROK;
+   }
+   CU_ALLOC(rlcBearerList, sizeof(struct CellGroupConfigRrc__rlc_BearerToAddModList));
+   if(!rlcBearerList)
+   {
+      DU_LOG("\nERROR  -->  F1AP : Memory allocation failure in CellGrpConfig");
+      return RFAILED;
+   }
    rlcBearerList->list.count = elementCnt;
    rlcBearerList->list.size  = elementCnt * sizeof(struct RLC_BearerConfig *);
 
@@ -6137,7 +6161,7 @@ uint8_t BuildRlcBearerToAddModList(CuUeCb *ueCb, struct CellGroupConfigRrc__rlc_
 
    for(drbIdx=0; drbIdx < ueCb->numDrb; drbIdx++)
    {
-      if(!updateAllRbCfg && ueCb->srbList[srbIdx].cfgSentToUe)
+      if(!updateAllRbCfg && ueCb->drbList[drbIdx].cfgSentToUe)
          continue;
 
       rlcBearerList->list.array[idx]->logicalChannelIdentity = ueCb->drbList[drbIdx].lcId;
@@ -6412,12 +6436,7 @@ uint8_t fillCellGrpCfg(CuUeCb *ueCb, OCTET_STRING_t *cellGrp, bool updateAllRbCf
       cellGrpCfg.cellGroupId = CELL_GRP_ID;
 
       cellGrpCfg.rlc_BearerToAddModList = NULLP;
-      CU_ALLOC(cellGrpCfg.rlc_BearerToAddModList, sizeof(struct CellGroupConfigRrc__rlc_BearerToAddModList));
-      if(!cellGrpCfg.rlc_BearerToAddModList)
-      {
-         DU_LOG("\nERROR  -->  F1AP : Memory allocation failure in CellGrpConfig");
-         break;
-      }
+      
       if(BuildRlcBearerToAddModList(ueCb, cellGrpCfg.rlc_BearerToAddModList, updateAllRbCfg) != ROK)
       {
          DU_LOG("\nERROR  -->  F1AP : fillCellGrpCfg failed");
@@ -7380,7 +7399,7 @@ void freeMeasIdToAddModList(MeasIdToAddModList_t *measIdList)
  * @return void
  *
  * ****************************************************************/
-uint8_t freeQuantityConfig(QuantityConfig_t *quantityCfg)
+void freeQuantityConfig(QuantityConfig_t *quantityCfg)
 {
    uint8_t quanCfgIdx;
    QuantityConfigNR_t *quantityCfgNr;
@@ -7533,7 +7552,7 @@ void freeSrbToAddModList(SRB_ToAddModList_t *srbToAddList)
  *
  * @details
  *
- *    Function : fillRadioBearerConfig
+ *    Function : freeRadioBearerConfig 
  *
  *    Functionality: Free Radio Bearer config
  *
@@ -7610,19 +7629,26 @@ void freeRrcReconfig(RRCReconfiguration_t *rrcReconfig)
  * ****************************************************************/
 uint8_t fillSrbToAddModList(CuUeCb *ueCb, SRB_ToAddModList_t *srbToAddList, bool updateAllRbCfg)
 {
-   uint8_t srbIdx, srbDbIdx;
+   uint8_t srbIdx, srbDbIdx, elementCnt = 0;
 
    if(updateAllRbCfg)
-      srbToAddList->list.count = ueCb->numSrb;
+      elementCnt = ueCb->numSrb;
    else
    {
-      srbToAddList->list.count = 0;
       for(srbDbIdx=0; srbDbIdx < ueCb->numSrb; srbDbIdx++)
       {
          if(ueCb->srbList[srbDbIdx].cfgSentToUe == false)
-            srbToAddList->list.count++;
+            elementCnt++;
       }
    }
+
+   if(!elementCnt)
+   {
+      DU_LOG("INFO  --> F1AP : No SRB available to add or modify");
+      return ROK;
+   }
+
+   srbToAddList->list.count = elementCnt;
    srbToAddList->list.size = srbToAddList->list.count * sizeof(SRB_ToAddMod_t *);
 
    CU_ALLOC(srbToAddList->list.array, srbToAddList->list.size);
@@ -7696,19 +7722,27 @@ uint8_t fillSrbToAddModList(CuUeCb *ueCb, SRB_ToAddModList_t *srbToAddList, bool
  * ****************************************************************/
 uint8_t fillDrbToAddModList(CuUeCb *ueCb, DRB_ToAddModList_t *drbToAddList, bool updateAllRbCfg)
 {
-   uint8_t drbIdx, drbDbIdx;
+   uint8_t drbIdx, drbDbIdx, elementCnt = 0;
 
    if(updateAllRbCfg)
-      drbToAddList->list.count = ueCb->numDrb;
+      elementCnt = ueCb->numDrb;
    else
    {
-      drbToAddList->list.count = 0;
       for(drbDbIdx=0; drbDbIdx < ueCb->numDrb; drbDbIdx++)
       {     
          if(ueCb->drbList[drbDbIdx].cfgSentToUe == false)
-            drbToAddList->list.count++;
+            elementCnt++;
       }     
    }
+
+   if(!elementCnt)
+   {
+      DU_LOG("INFO  --> F1AP : No DRB available to add or modify");
+      return ROK;
+   }
+   
+
+   drbToAddList->list.count = elementCnt;
    drbToAddList->list.size = drbToAddList->list.count * sizeof(DRB_ToAddMod_t *);
 
    CU_ALLOC(drbToAddList->list.array, drbToAddList->list.size);
@@ -7823,6 +7857,7 @@ uint8_t fillRadioBearerConfig(CuUeCb *ueCb, RadioBearerConfig_t *radioBearerConf
    }
    if(fillSrbToAddModList(ueCb, radioBearerConfig->srb_ToAddModList, updateAllRbCfg) != ROK)
    {
+      DU_LOG("\nERROR  -->  F1AP: failed to fill SRB to AddMod List");
       return RFAILED;
    }
 
@@ -7832,9 +7867,10 @@ uint8_t fillRadioBearerConfig(CuUeCb *ueCb, RadioBearerConfig_t *radioBearerConf
    {
       DU_LOG("\nERROR  -->  F1AP: Memory allocation failed for DRB to AddMod List in fillRadioBearerConfig");
       return RFAILED;
-   }
+    }
    if(fillDrbToAddModList(ueCb, radioBearerConfig->drb_ToAddModList, updateAllRbCfg) != ROK)
    {
+      DU_LOG("\nERROR  -->  F1AP: failed to fill DRB to AddMod List ");
       return RFAILED;
    }
 
@@ -8404,13 +8440,28 @@ uint8_t fillRrcReconfigNonCriticalExt(CuUeCb *ueCb, RRCReconfiguration_v1530_IEs
    CU_ALLOC(rrcRecfg->masterCellGroup, sizeof(OCTET_STRING_t));
    if(!rrcRecfg->masterCellGroup)
    {
+      DU_LOG("\nERROR  -->  F1AP : Memory allocation failed in fillRrcReconfigNonCriticalExt");
       return RFAILED;
    }
 
+   rrcRecfg->masterCellGroup->size = ueCb->f1apMsgDb.duToCuContainer.size;
+   CU_ALLOC(rrcRecfg->masterCellGroup->buf, rrcRecfg->masterCellGroup->size);
+   if(!rrcRecfg->masterCellGroup->buf)
+   {     
+      DU_LOG("\nERROR  -->  F1AP : Memory allocation failed in fillRrcReconfigNonCriticalExt");
+      return RFAILED;
+   }     
+   memcpy(rrcRecfg->masterCellGroup->buf, ueCb->f1apMsgDb.duToCuContainer.buf, rrcRecfg->masterCellGroup->size);
+
+#if 0
+   /* Use below code if masterCEllGroup is to be filled explicitly at CU rather than copying from DUToCURRCContainer 
+    * received from DU */
    if(fillCellGrpCfg(ueCb, rrcRecfg->masterCellGroup, updateAllRbCfg) != ROK)
    {
+      DU_LOG("\nERROR  -->  F1AP : Failed to fill CellGroupCfg in fillRrcReconfigNonCriticalExt");
       return RFAILED;
    }
+#endif
 
    return ROK;
 }
@@ -8618,6 +8669,12 @@ uint8_t fillHOPreparationInfoBuf(CuUeCb *ueCb, HandoverPreparationInformation_t
          return RFAILED;
       }
       ret = fillRrcReconfigBuf(ueCb, &hoPrepInfoIe->sourceConfig->rrcReconfiguration, true); 
+      
+      if(ret != ROK)
+      {
+         DU_LOG( "\nERROR  -->  F1AP : Failed to fill Rrc reconfiguration buffer");
+         return RFAILED;
+      }
 
       hoPrepInfoIe->rrm_Config = NULLP;
       hoPrepInfoIe->as_Context = NULLP;
@@ -8707,7 +8764,7 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg)
       CU_ALLOC(rrcMsg->iE_Extensions, sizeof(ProtocolExtensionContainer_4624P16_t));
       if(rrcMsg->iE_Extensions)
       {
-         elementCnt = 2;
+         elementCnt = 1;
          rrcMsg->iE_Extensions->list.count = elementCnt;
          rrcMsg->iE_Extensions->list.size = elementCnt * sizeof(CUtoDURRCInformation_ExtIEs_t *);
 
@@ -8731,16 +8788,16 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg)
          }
 
          idx = 0;
-
+#if 0
          /* Cell Group Configuration */
          rrcMsg->iE_Extensions->list.array[idx]->id = ProtocolIE_ID_id_CellGroupConfig;
          rrcMsg->iE_Extensions->list.array[idx]->criticality = Criticality_ignore; 
          rrcMsg->iE_Extensions->list.array[idx]->extensionValue.present  =\
                                                                           CUtoDURRCInformation_ExtIEs__extensionValue_PR_CellGroupConfig;
          ret = fillCellGrpCfg(ueCb, &rrcMsg->iE_Extensions->list.array[idx]->extensionValue.choice.CellGroupConfig, true);
-
-         /* Handover Preparation Information */
          idx++;
+#endif
+         /* Handover Preparation Information */
          rrcMsg->iE_Extensions->list.array[idx]->id = ProtocolIE_ID_id_HandoverPreparationInformation; 
          rrcMsg->iE_Extensions->list.array[idx]->criticality = Criticality_ignore;
          rrcMsg->iE_Extensions->list.array[idx]->extensionValue.present  = \
@@ -8832,7 +8889,7 @@ void FreeCuToDuInfo(CUtoDURRCInformation_t *rrcMsg)
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcContLen, uint8_t *rrcContainer)
+uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb)
 {
    uint8_t   Nrcgiret, SplCellListret, SrbSetupret;
    uint8_t   ret= RFAILED, ret1;
@@ -8873,7 +8930,7 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcC
       if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
          elementCnt = 7;
       else
-         elementCnt = 12;
+         elementCnt = 11;
       ueSetReq->protocolIEs.list.count = elementCnt;
       ueSetReq->protocolIEs.list.size = elementCnt * sizeof(UEContextSetupRequestIEs_t *);
 
@@ -8991,7 +9048,7 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcC
       ueSetReq->protocolIEs.list.array[idx]->id        = ProtocolIE_ID_id_DRBs_ToBeSetup_List;
       ueSetReq->protocolIEs.list.array[idx]->criticality       =       Criticality_reject;
       ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List;
-      ret1 = BuildDRBSetup(ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.DRBs_ToBeSetup_List);
+      ret1 = BuildDRBSetup(duId, ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.DRBs_ToBeSetup_List);
       if(ret1 != ROK)
       {        
          break;
@@ -8999,25 +9056,6 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcC
 
       if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
       {
-         /* RRC Container for security mode */
-         idx++;
-         ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_RRCContainer;
-         ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject;
-         ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_RRCContainer;
-
-         char secModeBuf[9]={0x00, 0x02, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00};
-         bufLen =9;
-         ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.size = bufLen;
-         CU_ALLOC(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf,
-               ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.size);
-         if(!ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf)
-         {
-            DU_LOG("\nERROR  -->  F1AP : Memory allocation for BuildAndSendUeContextSetupReq failed");
-            break;
-         }
-         memset(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, 0, bufLen);
-         memcpy(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, secModeBuf, bufLen);
-
          /* RRC delivery status request */
          idx++;
          ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
@@ -9138,7 +9176,7 @@ uint8_t extractTeId(DLUPTNLInformation_ToBeSetup_List_t *dlTnlInfo)
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t addDrbTunnels(uint8_t teId)
+uint8_t addDrbTunnels(uint32_t duId, uint8_t teId)
 {
    uint8_t ret = ROK;
    EgtpTnlEvt tnlEvt;
@@ -9151,7 +9189,7 @@ uint8_t addDrbTunnels(uint8_t teId)
    tnlEvt.action = EGTP_TNL_MGMT_ADD;
    tnlEvt.lclTeid = teId;
    tnlEvt.remTeid = teId;
-   ret = cuEgtpTnlMgmtReq(tnlEvt);
+   ret = cuEgtpTnlMgmtReq(duId, tnlEvt);
    if(ret != ROK)
    {
       DU_LOG("\nERROR  -->  EGTP : Tunnel management request failed for teId %x", teId);
@@ -9174,7 +9212,7 @@ uint8_t addDrbTunnels(uint8_t teId)
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList)
+uint8_t procDrbSetupList(uint32_t duId, DRBs_Setup_List_t *drbSetupList)
 {
    uint8_t arrIdx = 0;
    uint32_t teId = 0;
@@ -9191,7 +9229,7 @@ uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList)
             teId  = extractTeId(&drbItemIe->value.choice.DRBs_Setup_Item.dLUPTNLInformation_ToBeSetup_List);
             if(teId > 0)
             {
-              if(addDrbTunnels(teId)== ROK)
+              if(addDrbTunnels(duId, teId)== ROK)
               {
                 DU_LOG("\nDEBUG  --> EGTP: Tunnel Added for TeId %d", teId);
               }
@@ -9221,10 +9259,12 @@ uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList)
  * ****************************************************************/
 uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
 {
-   uint8_t duIdx=0, idx, duUeF1apId;
-   DuDb *duDb;
-   CuUeCb *ueCb;
+   uint8_t duIdx = 0, idx = 0, ueIdx = 0, rrcMsgType=0;
+   uint8_t duUeF1apId = 0, cuUeF1apId = 0;
+   DuDb *duDb = NULLP;
+   CuUeCb *ueCb = NULLP;
    UEContextSetupResponse_t *ueCtxtSetupRsp = NULLP;
+   OCTET_STRING_t *duToCuRrcContainer;
 
    SEARCH_DU_DB(duIdx, duId, duDb);
    ueCtxtSetupRsp = &f1apMsg->choice.successfulOutcome->value.choice.UEContextSetupResponse;
@@ -9233,21 +9273,50 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
    {
       switch(ueCtxtSetupRsp->protocolIEs.list.array[idx]->id)
       {
+          case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+             {
+               cuUeF1apId = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID;
+               break;
+             }
           case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
              {
                 duUeF1apId = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
                 ueCb = &duDb->ueCb[duUeF1apId-1];
+                /* If ue context is not present in du db, then create UE context
+                 * here. This flow is hit in case of UE handover where UE
+                 * context is created before UE performs RACH on target DU */
+                if(ueCb->gnbDuUeF1apId == 0)
+                {
+                   /* 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.targetDuId = duId; 
+                   (duDb->numUe)++;
+
+                   ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb;
+                   ueCb->cellCb->numUe++;
+                }
+                break;
+             }
+          case ProtocolIE_ID_id_C_RNTI:
+             {
+                ueCb->crnti = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.C_RNTI;
                 break;
              }
           case ProtocolIE_ID_id_DRBs_Setup_List:
              {
                 /* Adding Tunnels for successful DRB */
-                procDrbSetupList(&ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List);
+                procDrbSetupList(duId, &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List);
                 break; 
              }
          case ProtocolIE_ID_id_DUtoCURRCInformation:
              {
                 DU_LOG("\nINFO  -->  Received Du to Cu RRC Information ");
+                duToCuRrcContainer = &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.\
+                   DUtoCURRCInformation.cellGroupConfig;
                 if((extractDuToCuRrcCont(ueCb, ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.\
                    DUtoCURRCInformation.cellGroupConfig)) != ROK)
                 {
@@ -9258,7 +9327,69 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
              }
       }
    }
-   ueCb->f1apMsgDb.dlRrcMsgCount++; /* keeping DL RRC Msg Count */
+   
+   /* 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)
+   {
+      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++)
+      {
+         /* 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)
+         {
+            for(ueIdx = 0; ueIdx < MAX_NUM_UE; 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.sourceDuId = srcDuDb->duId;
+
+                  /* 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;
+                  }
+                  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)
+      {
+         DU_LOG("\nINFO  -->  F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration");
+         return RFAILED;
+      }
+   }
+
    return ROK;
 }
 
@@ -9320,6 +9451,10 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
                   return RFAILED;
                }
                memcpy(rrcContainer, ulRrcMsg->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, rrcContLen);
+
+               if(duDb->ueCb[duUeF1apId-1].state == UE_HANDOVER_IN_PROGRESS)
+                  return;
+
                break;
             }
 
@@ -9334,37 +9469,25 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
       ueCb = &duDb->ueCb[duUeF1apId-1];
       ueCb->f1apMsgDb.dlRrcMsgCount++;
       rrcMsgType = setDlRRCMsgType(ueCb);
-      if(rrcMsgType == REGISTRATION_ACCEPT)
+      if(rrcMsgType == RRC_SETUP_COMPLETE)
       {
-         DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for RRC Registration Accept"); 
+         DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for Security Mode Command"); 
          ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
       }
-      if(rrcMsgType == UE_CONTEXT_SETUP_REQ)
+      else if(rrcMsgType == SECURITY_MODE_COMPLETE)
       {
-         DU_LOG("\nINFO  -->  F1AP: Sending Ue Context Setup Req"); 
-         ret = BuildAndSendUeContextSetupReq(duId, ueCb, rrcContLen, rrcContainer);
+         DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for RRC Registration Accept");
+         BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
       }
-      if(rrcMsgType == SECURITY_MODE_COMPLETE)
+      else if(rrcMsgType == REGISTRATION_COMPLETE)
       {
-         /* To trigger the DL RRC Msg for RRC Reconfig */
-         ueCb->f1apMsgDb.dlRrcMsgCount++;
-         rrcMsgType = setDlRRCMsgType(ueCb);
-         if(rrcMsgType == RRC_RECONFIG)
-         {
-            DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for RRC Reconfig");
-            BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
-         }
+         DU_LOG("\nINFO  -->  F1AP: Sending Ue Context Setup Request"); 
+         ret = BuildAndSendUeContextSetupReq(duId, ueCb);
       }
-      if(rrcMsgType == RRC_RECONFIG_COMPLETE)
+      else if(rrcMsgType == RRC_RECONFIG_COMPLETE)
       {
-         ueCb->state = UE_ACTIVE;
-         ueCb->f1apMsgDb.dlRrcMsgCount++;
-         rrcMsgType = setDlRRCMsgType(ueCb);
-         if(rrcMsgType == UE_CONTEXT_MOD_REQ)
-         {
-            DU_LOG("\nINFO  -->  F1AP: Sending UE Context Modification Request");
-            BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND);
-         }
+         DU_LOG("\nINFO  -->  F1AP: Sending UE Context Modification Request");
+         BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND);
       }
    }
    return ret;
@@ -9578,7 +9701,7 @@ void FreeUlTnlInfoforDrb2(ULUPTNLInformation_ToBeSetup_List_t *ulInfo)
 *         RFAILED - failure
 *
 * ****************************************************************/
-uint8_t deleteEgtpTunnel(uint8_t *buf)
+uint8_t deleteEgtpTunnel(uint32_t duId, uint8_t *buf)
 {
    uint32_t teId = 0;
    EgtpTnlEvt tnlEvt;
@@ -9593,7 +9716,7 @@ uint8_t deleteEgtpTunnel(uint8_t *buf)
    tnlEvt.action = EGTP_TNL_MGMT_DEL;
    tnlEvt.lclTeid = teId;
    tnlEvt.remTeid = teId;
-   if((cuEgtpTnlMgmtReq(tnlEvt)) != ROK)
+   if((cuEgtpTnlMgmtReq(duId, tnlEvt)) != ROK)
    {
       DU_LOG("\nERROR  -->  EGTP : Failed to delete tunnel Id %d", teId);
    }
@@ -9616,7 +9739,7 @@ uint8_t deleteEgtpTunnel(uint8_t *buf)
 *         RFAILED - failure
 *
 * ****************************************************************/
-uint8_t BuildUlTnlInfoforSetupMod(uint8_t ueId, uint8_t drbId, TnlInfo *ulTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, uint8_t actionType)
+uint8_t BuildUlTnlInfoforSetupMod(uint32_t duId, uint8_t ueId, uint8_t drbId, TnlInfo *ulTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, uint8_t actionType)
 {
    uint8_t arrIdx;
    uint8_t ulCnt;
@@ -9821,7 +9944,7 @@ void FreeDrbItem(DRBs_ToBeSetupMod_Item_t *drbItem)
 *
 * ****************************************************************/
 
-uint8_t FillDrbItemToSetupMod(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_Item_t *drbItem)
+uint8_t FillDrbItemToSetupMod(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_Item_t *drbItem)
 {
    uint8_t ret = ROK;
 
@@ -9901,7 +10024,7 @@ uint8_t FillDrbItemToSetupMod(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_It
    }
    
    /*ULUPTNLInformation To Be Setup List*/
-   ret = BuildUlTnlInfoforSetupMod(ueCb->gnbCuUeF1apId, drbItem->dRBID, &ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, \
+   ret = BuildUlTnlInfoforSetupMod(duId, ueCb->gnbCuUeF1apId, drbItem->dRBID, &ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, \
       &drbItem->uLUPTNLInformation_ToBeSetup_List, ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item);
    if(ret != ROK)
    {
@@ -9934,13 +10057,13 @@ uint8_t FillDrbItemToSetupMod(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_It
 *
 * ****************************************************************/
 
-uint8_t FillDrbItemList(CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeSetupMod_ItemIEs *drbItemIe)
+uint8_t FillDrbItemList(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeSetupMod_ItemIEs *drbItemIe)
 {
    drbItemIe->id = ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item;
    drbItemIe->criticality = Criticality_reject;
    drbItemIe->value.present = DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item;
 
-   if(FillDrbItemToSetupMod(ueCb, arrIdx, (&(drbItemIe->value.choice.DRBs_ToBeSetupMod_Item))) != ROK)
+   if(FillDrbItemToSetupMod(duId, ueCb, arrIdx, (&(drbItemIe->value.choice.DRBs_ToBeSetupMod_Item))) != ROK)
    {
       DU_LOG("\nERROR  -->  F1AP : FillDrbItemToSetupMod failed"); 
       return RFAILED;
@@ -10004,7 +10127,7 @@ void FreeDrbToBeSetupModList(DRBs_ToBeSetupMod_List_t *drbSet)
 *
 * ****************************************************************/
 
-uint8_t BuildDrbToBeSetupList(CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet)
+uint8_t BuildDrbToBeSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet)
 {
    uint8_t ret = ROK;
    uint8_t arrIdx =0;
@@ -10029,7 +10152,7 @@ uint8_t BuildDrbToBeSetupList(CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet)
          return  RFAILED;
       }
 
-      ret = FillDrbItemList(ueCb, arrIdx, (DRBs_ToBeSetupMod_ItemIEs_t *)drbSet->list.array[arrIdx]);
+      ret = FillDrbItemList(duId, ueCb, arrIdx, (DRBs_ToBeSetupMod_ItemIEs_t *)drbSet->list.array[arrIdx]);
       if(ret != ROK)
       {
          DU_LOG("\nERROR  -->  F1AP : FillDrbItemList failed");
@@ -10056,7 +10179,7 @@ uint8_t BuildDrbToBeSetupList(CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet)
 *
 * ****************************************************************/
 
-uint8_t FillDrbToBeModItem(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_t *drbItem)
+uint8_t FillDrbToBeModItem(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_t *drbItem)
 {
    uint8_t ret = ROK;
    uint drbIdx=0;
@@ -10152,7 +10275,7 @@ uint8_t FillDrbToBeModItem(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_
    }/* End of QoS */
 
    /*ULUPTNLInformation To Be Setup List*/
-   ret = BuildUlTnlInfoforSetupMod(ueCb->gnbCuUeF1apId, drbItem->dRBID, &drbToBeMod->ulUpTnlInfo, &drbItem->uLUPTNLInformation_ToBeSetup_List,\
+   ret = BuildUlTnlInfoforSetupMod(duId, ueCb->gnbCuUeF1apId, drbItem->dRBID, &drbToBeMod->ulUpTnlInfo, &drbItem->uLUPTNLInformation_ToBeSetup_List,\
             ProtocolIE_ID_id_DRBs_ToBeModified_Item);
    if(ret != ROK)
    {
@@ -10179,12 +10302,12 @@ uint8_t FillDrbToBeModItem(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_
 *
 * ****************************************************************/
 
-uint8_t FillDrbToBeModItemList(CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeModified_ItemIEs *drbItemIe)
+uint8_t FillDrbToBeModItemList(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeModified_ItemIEs *drbItemIe)
 {
    drbItemIe->id = ProtocolIE_ID_id_DRBs_ToBeModified_Item;
    drbItemIe->criticality = Criticality_reject;
    drbItemIe->value.present = DRBs_ToBeModified_ItemIEs__value_PR_DRBs_ToBeModified_Item;
-   if(FillDrbToBeModItem(ueCb, arrIdx, &(drbItemIe->value.choice.DRBs_ToBeModified_Item)) != ROK)
+   if(FillDrbToBeModItem(duId, ueCb, arrIdx, &(drbItemIe->value.choice.DRBs_ToBeModified_Item)) != ROK)
    {
       DU_LOG("\nERROR  -->  F1AP : FillDrbToBeModItem failed"); 
       return RFAILED;
@@ -10210,7 +10333,7 @@ uint8_t FillDrbToBeModItemList(CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeMod
 *
 * ****************************************************************/
 
-uint8_t BuildDrbToBeModifiedList(CuUeCb *ueCb, DRBs_ToBeModified_List_t *drbSet)
+uint8_t BuildDrbToBeModifiedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeModified_List_t *drbSet)
 {
    uint8_t ret = ROK;
    uint8_t arrIdx =0;
@@ -10234,7 +10357,7 @@ uint8_t BuildDrbToBeModifiedList(CuUeCb *ueCb, DRBs_ToBeModified_List_t *drbSet)
          return  RFAILED;
       }
 
-      ret = FillDrbToBeModItemList(ueCb, arrIdx, (DRBs_ToBeModified_ItemIEs_t *)drbSet->list.array[arrIdx]);
+      ret = FillDrbToBeModItemList(duId, ueCb, arrIdx, (DRBs_ToBeModified_ItemIEs_t *)drbSet->list.array[arrIdx]);
       if(ret != ROK)
       {
          DU_LOG("\nERROR  -->  F1AP : FillDrbToBeModItemList failed");
@@ -10384,20 +10507,20 @@ void FreeDrbToBeModifiedList(DRBs_ToBeModified_List_t *drbSet)
 void FreeUeContextModicationRequest(F1AP_PDU_t *f1apMsg)
 {
    uint8_t arrIdx =0 , ieId=0; 
-   UEContextModificationRequest_t *UeContextModifyReq = NULLP;
+   UEContextModificationRequest_t *ueContextModifyReq = NULLP;
 
    if(f1apMsg)
    {
       if(f1apMsg->choice.initiatingMessage)
       {
-         UeContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest;
-         if(UeContextModifyReq->protocolIEs.list.array)
+         ueContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest;
+         if(ueContextModifyReq->protocolIEs.list.array)
          {
-            for( arrIdx = 0 ; arrIdx<UeContextModifyReq->protocolIEs.list.count ; arrIdx++)
+            for( arrIdx = 0 ; arrIdx<ueContextModifyReq->protocolIEs.list.count ; arrIdx++)
             {
-               if(UeContextModifyReq->protocolIEs.list.array[arrIdx])
+               if(ueContextModifyReq->protocolIEs.list.array[arrIdx])
                {
-                  ieId = UeContextModifyReq->protocolIEs.list.array[arrIdx]->id;
+                  ieId = ueContextModifyReq->protocolIEs.list.array[arrIdx]->id;
                   switch(ieId)
                   {
                      case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
@@ -10406,22 +10529,29 @@ void FreeUeContextModicationRequest(F1AP_PDU_t *f1apMsg)
                         break;
                      case ProtocolIE_ID_id_DRBs_ToBeSetupMod_List:
                         {
-                           FreeDrbToBeSetupModList(&UeContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
+                           FreeDrbToBeSetupModList(&ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
                                  choice.DRBs_ToBeSetupMod_List);
                            break;
                         }
                      case ProtocolIE_ID_id_DRBs_ToBeModified_List:
                         {
-                           FreeDrbToBeModifiedList(&UeContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
-                                 choice.DRBs_ToBeSetupMod_List);
+                           FreeDrbToBeModifiedList(&ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
+                                 choice.DRBs_ToBeModified_List);
                            break;
                         }
+                    case ProtocolIE_ID_id_TransmissionActionIndicator:
+                        break;
+                    case ProtocolIE_ID_id_RRCContainer:
+                    {
+                        CU_FREE(ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.choice.RRCContainer.buf,\
+                        ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.choice.RRCContainer.size);
+                    }
 
                   }
-                  CU_FREE(UeContextModifyReq->protocolIEs.list.array[arrIdx], sizeof(UEContextModificationRequest_t));
+                  CU_FREE(ueContextModifyReq->protocolIEs.list.array[arrIdx], sizeof(UEContextModificationRequest_t));
                }         
             }
-            CU_FREE(UeContextModifyReq->protocolIEs.list.array, UeContextModifyReq->protocolIEs.list.size);
+            CU_FREE(ueContextModifyReq->protocolIEs.list.array, ueContextModifyReq->protocolIEs.list.size);
          }
          CU_FREE(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t));
       }
@@ -10453,10 +10583,8 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
    CuUeCb     *ueCb = (CuUeCb *)cuUeCb;
    F1AP_PDU_t *f1apMsg = NULLP;
    UEContextModificationRequest_t *ueContextModifyReq = NULLP;
-
    asn_enc_rval_t         encRetVal;
    DU_LOG("\nINFO  -->  F1AP : Building Ue context modification request\n");
-
    while(1)
    {
       CU_ALLOC(f1apMsg, sizeof(F1AP_PDU_t));
@@ -10486,6 +10614,9 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
          elementCnt = 3;
       else if(action == RRC_RECONFIG_COMPLETE_IND)
          elementCnt = 3;
+      else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX)) 
+         elementCnt = 5;
+
       ueContextModifyReq->protocolIEs.list.count = elementCnt;
       ueContextModifyReq->protocolIEs.list.size = elementCnt*sizeof(UEContextModificationRequest_t *);
 
@@ -10529,7 +10660,7 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
          ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
          ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\
                                                                            UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List;
-         ret = BuildDrbToBeSetupList(ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
+         ret = BuildDrbToBeSetupList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
                   value.choice.DRBs_ToBeSetupMod_List));
 
          /* DRB to be modified list */
@@ -10538,15 +10669,18 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
          ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
          ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\
                                                                            UEContextModificationRequestIEs__value_PR_DRBs_ToBeModified_List;
-         ret = BuildDrbToBeModifiedList(ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
+         ret = BuildDrbToBeModifiedList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
                   value.choice.DRBs_ToBeModified_List));
 
          /* TODO: DRB to be release list */
 
          if(ret != ROK)
          {
+            DU_LOG("\nERROR  -->  F1AP : BuildAndSendUeContextModificationReq(): Failed to build drb to be modified list");
             break;
          }
+
+         /* TODO: fill the RRC reconfiguration information in RRC Contaiiner ie in case of MODIFY_UE  */
       }
       else if(action == QUERY_CONFIG)
       {
@@ -10567,6 +10701,46 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
          ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCReconfigurationCompleteIndicator = \
             RRCReconfigurationCompleteIndicator_true;
       }
+      else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX))
+      {
+         ieIdx++;
+         if(action == STOP_DATA_TX)
+         {
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_TransmissionActionIndicator;
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+            UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator;
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.TransmissionActionIndicator = \
+            TransmissionActionIndicator_stop;
+         }
+         else if (action == RESTART_DATA_TX)
+         {
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_TransmissionActionIndicator;
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+            UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator;
+            ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.TransmissionActionIndicator = \
+            TransmissionActionIndicator_restart;
+         }
+
+         ieIdx++;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCContainer;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+         UEContextModificationRequestIEs__value_PR_RRCContainer;
+         if(fillRrcReconfigBuf(ueCb, &ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer, true) != ROK)
+         {
+            DU_LOG( "\nERROR  -->  F1AP : Failed to fill Rrc reconfiguration buffer");
+            return RFAILED;
+         }
+
+         /* RRC delivery status request */
+         ieIdx++;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCDeliveryStatusRequest;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true;
+      }
 
       xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
 
@@ -10585,10 +10759,15 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
       else
       {
          DU_LOG("\nDEBUG  -->  F1AP : Created APER encodedbuffer for ueContextModifyReq\n");
+#if 0        
+         /* This for loop was going into an infinite loop even though encBufSize
+          * has a small value. Hence commented this
+          */
          for(ieIdx=0; ieIdx< encBufSize; ieIdx++)
          {
             DU_LOG("%x",encBuf[ieIdx]);
          }
+#endif
       }
 
       /* TODO : Hardcoding DU ID to 1 for messages other than F1 Setup Response. This will be made generic in future gerrit */
@@ -10899,8 +11078,7 @@ uint8_t procGnbDuUpdate(uint32_t duId, F1AP_PDU_t *f1apMsg)
                struct Served_Cells_To_Delete_ItemIEs *deleteItemIe = \
                   (struct Served_Cells_To_Delete_ItemIEs *)duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.\
                   Served_Cells_To_Delete_List.list.array[0];
-               nrCellId = deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity.buf[4] >>\
-                  deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity.bits_unused;
+               bitStringToInt(&deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity, &nrCellId); 
                cellToBeDelete = true;
                break;
             }
@@ -10931,13 +11109,14 @@ uint8_t procGnbDuUpdate(uint32_t duId, F1AP_PDU_t *f1apMsg)
    {
       SEARCH_DU_DB(duIdx, duId, duDb);
       SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb);
-      for(ueIdx = 0; ueIdx < cellCb->numUe; ueIdx++)
+      if(cellCb->numUe == 0)
       {
-         CU_FREE(cellCb->ueCb[ueIdx]->f1apMsgDb.duToCuContainer.buf, cellCb->ueCb[ueIdx]->f1apMsgDb.duToCuContainer.size);
-         memset(cellCb->ueCb[ueIdx], 0, sizeof(CuUeCb));
+         memset(cellCb, 0, sizeof(CuCellCb));
+         duDb->numCells--;
       }
+      else
+         cellCb->cellStatus = CELL_DELETION_IN_PROGRESS;
    }
-
    return ROK;
 }
 
@@ -11052,7 +11231,7 @@ uint8_t procSrbSetupModList(CuUeCb *ueCb, SRBs_SetupMod_List_t *srbSetupList)
  *         RFAILED - failure
  *
  * ****************************************************************/
-uint8_t procDrbSetupModList(CuUeCb *ueCb, DRBs_SetupMod_List_t *drbSetupList)
+uint8_t procDrbSetupModList(uint32_t duId, CuUeCb *ueCb, DRBs_SetupMod_List_t *drbSetupList)
 {
    uint8_t arrIdx = 0, drbIdx;
    uint32_t teId = 0;
@@ -11081,7 +11260,7 @@ uint8_t procDrbSetupModList(CuUeCb *ueCb, DRBs_SetupMod_List_t *drbSetupList)
             teId  = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List);
             if(teId > 0)
             {
-              if(addDrbTunnels(teId)== ROK)
+              if(addDrbTunnels(duId, teId)== ROK)
               {
                 DU_LOG("\nDEBUG  --> EGTP: Tunnel Added for TeId %d", teId);
               }
@@ -11171,9 +11350,10 @@ uint8_t procServedCellPlmnList(ServedPLMNs_List_t *srvPlmn)
  * ****************************************************************/
 uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
 {
-   uint8_t idx=0, duIdx=0, duUeF1apId;
-   DuDb *duDb;
-   CuUeCb *ueCb;
+   uint8_t idx=0, duIdx=0;
+   uint8_t duUeF1apId = 0, cuUeF1apId = 0;
+   DuDb *duDb = NULLP;
+   CuUeCb *ueCb = NULLP;
    UEContextModificationResponse_t *ueCtxtModRsp = NULLP;
 
    SEARCH_DU_DB(duIdx, duId, duDb);
@@ -11183,6 +11363,11 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
    {
       switch(ueCtxtModRsp->protocolIEs.list.array[idx]->id)
       {
+          case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+             {
+                cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID;
+                break;
+             }
           case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
              {
                 duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
@@ -11192,7 +11377,7 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
           case ProtocolIE_ID_id_DRBs_SetupMod_List:
              {
                 /* Adding Tunnels for successful DRB */
-                procDrbSetupModList(ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.DRBs_SetupMod_List);
+                procDrbSetupModList(duId, ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.DRBs_SetupMod_List);
                 break; 
 
              }
@@ -11215,10 +11400,41 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
 
       }
    }
+
+   /* If UE is in handover and UE context is not yet created at target DU, then send
+    * UE context setup request to target DU */
    if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
    {
-      BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetDuId, ueCb, 0, NULLP);
-      return ROK;
+      uint8_t ueIdx = 0;
+      DuDb *tgtDuDb = NULLP;
+      CuUeCb *ueCbInTgtDu = NULLP;
+
+      SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetDuId, 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++)
+         {
+            if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
+            {
+               ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx];
+               break;
+            }
+         }
+
+         /* If UE context is not found in Target DU DU, send UE context setup
+          * request */
+         if(ueCbInTgtDu == NULLP)
+         {
+            if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetDuId, ueCb)) != ROK)
+            {
+               DU_LOG("\nERROR  ->  F1AP : Failed at BuildAndSendUeContextSetupReq");
+               return RFAILED;
+            }
+         }
+      }
    }
    
    return ROK;
@@ -11293,7 +11509,8 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg)
                               srvCellItem =  &duServedCell->list.array[plmnidx]->value.choice.GNB_DU_Served_Cells_Item;
                               ret = procServedCellPlmnList(&srvCellItem->served_Cell_Information.servedPLMNs);
                               memcpy(&nrcellIdentity, &srvCellItem->served_Cell_Information.nRCGI.nRCellIdentity, sizeof(BIT_STRING_t));
-
+                              
+                              /* TODO : Use bitStringToInt */
                               nrCellId = nrcellIdentity.buf[4] >> nrcellIdentity.bits_unused;
                               SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb);
                               if(cellCb == NULLP)
@@ -11301,6 +11518,7 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg)
                                  cellCb = &duDb->cellCb[duDb->numCells];
                                  memset(cellCb, 0, sizeof(CuCellCb));
                                  cellCb->nrCellId = nrCellId;
+                                 cellCb->cellStatus = CELL_ACTIVE;
                                  duDb->numCells++;
                               }
                            }
@@ -11321,6 +11539,433 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg)
    }
 }
 
+/****************************************************************
+*
+* @brief processing of UE Context Release Complete
+*
+* @details
+*
+*    Function : procUeContextReleaseComplete
+*
+*    Functionality:
+*         - processing of UE Context Release Complete
+*
+* @params[in] F1AP_PDU_t *f1apMsg
+* @return ROK     - success
+*         RFAILED - failure
+*
+* ****************************************************************/
+void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg)
+{
+   uint8_t duIdx = 0, ieIdx = 0, ueIdx = 0;
+   uint8_t gnbDuUeF1apId = 0, gnbCuUeF1apId = 0;
+   DuDb *duDb = NULLP;
+   CuUeCb *ueCb = NULLP;
+   UEContextReleaseComplete_t *ueReleaseComplete = NULLP;
+
+   SEARCH_DU_DB(duIdx, duId, duDb);
+   if(!duDb)
+   {
+      DU_LOG("\nERROR  -->  F1AP : No entry found for DU ID [%d]", duId);
+      return;
+   }
+
+   ueReleaseComplete = &f1apMsg->choice.successfulOutcome->value.choice.UEContextReleaseComplete;
+   for(ieIdx=0; ieIdx < ueReleaseComplete->protocolIEs.list.count; ieIdx++)
+   {
+      switch(ueReleaseComplete->protocolIEs.list.array[ieIdx]->id)
+      {
+         case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+            {
+               gnbCuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_CU_UE_F1AP_ID;
+               break;
+            }
+         case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
+            {
+               gnbDuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID;
+               ueCb = &duDb->ueCb[gnbDuUeF1apId-1];
+               for(ueIdx = 0; ueIdx <MAX_NUM_UE; ueIdx++)
+               {
+                  if(ueCb->cellCb && ueCb->cellCb->ueCb[ueIdx])
+                  {
+                     if((ueCb->cellCb->ueCb[ueIdx]->gnbCuUeF1apId == gnbCuUeF1apId) &&
+                           (ueCb->cellCb->ueCb[ueIdx]->gnbDuUeF1apId == gnbDuUeF1apId))
+                     {
+                        ueCb->cellCb->ueCb[ueIdx] = NULLP;
+                        ueCb->cellCb->numUe--;
+                        if((ueCb->cellCb->numUe == 0) && (ueCb->cellCb->cellStatus == CELL_DELETION_IN_PROGRESS))
+                        {
+                           memset(ueCb->cellCb, 0, sizeof(CuCellCb));
+                           duDb->numCells--;
+                        }
+                        break;
+                     }
+                  }
+               }
+               memset(ueCb, 0, sizeof(CuUeCb));
+               duDb->numUe--;
+               break;
+            }
+      }
+   }
+}
+
+/*******************************************************************
+ *
+ * @brief Builds the Paging cell list 
+ *
+ * @details
+ *
+ *    Function : BuildPagingCellList
+ *
+ *    Functionality: Build the paging cell list 
+ *
+ * @params[in] PagingCell_list_t  *pagingCelllist,  
+ *
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t BuildPagingCellList(PagingCell_list_t *pagingCelllist, uint8_t numCells, CuCellCb *cellCb)
+{
+   uint8_t cellIdx =0;
+   PagingCell_ItemIEs_t *pagingCellItemIes; 
+   PagingCell_Item_t *pagingCellItem;
+
+   pagingCelllist->list.count = numCells;
+   pagingCelllist->list.size = pagingCelllist->list.count * (sizeof(PagingCell_ItemIEs_t*));
+   CU_ALLOC(pagingCelllist->list.array, pagingCelllist->list.size);
+   if(pagingCelllist->list.array == NULLP)
+   {
+      DU_LOG("\nERROR  -->  F1AP : BuildPagingCellList(): Memory allocation failed ");
+      return RFAILED;
+   }
+
+   for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++)
+   {
+      CU_ALLOC(pagingCelllist->list.array[cellIdx], sizeof(PagingCell_ItemIEs_t));
+      if(pagingCelllist->list.array[cellIdx] == NULLP)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildPagingCellList(): Memory allocation failed ");
+         return RFAILED;
+      }
+   }
+   
+   for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++)
+   {
+      pagingCellItemIes = (PagingCell_ItemIEs_t *)pagingCelllist->list.array[cellIdx];
+      pagingCellItemIes->id =  ProtocolIE_ID_id_PagingCell_Item;
+      pagingCellItemIes->criticality = Criticality_ignore;
+      pagingCellItemIes->value.present = PagingCell_ItemIEs__value_PR_PagingCell_Item; 
+      pagingCellItem = &pagingCellItemIes->value.choice.PagingCell_Item;
+   
+      /* Fill NrCgi Information */
+      BuildNrcgi(&pagingCellItem->nRCGI, cellCb[cellIdx].nrCellId);
+   }
+   
+   return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Deallocation of memory allocated in paging msg
+ *
+ * @details
+ *
+ *    Function :FreePagingMsg 
+ *
+ *    Functionality: Deallocation of memory allocated in paging msg
+ *
+ * @params[in] F1AP_PDU_t *f1apMsg
+ *
+ * @return void 
+ *
+ * ****************************************************************/
+void FreePagingMsg(F1AP_PDU_t *f1apMsg)
+{
+   uint8_t ieIdx, cellIdx;
+   Paging_t   *paging;
+   PagingCell_ItemIEs_t *pagingCellItemIes;
+   PagingCell_Item_t *pagingCellItem;
+   PagingCell_list_t  *pagingCelllist;
+
+   if(f1apMsg)
+   {
+      if(f1apMsg->choice.initiatingMessage)
+      {
+         paging = &f1apMsg->choice.initiatingMessage->value.choice.Paging;
+         if(paging->protocolIEs.list.array)
+         {
+            for(ieIdx=0 ; ieIdx<paging->protocolIEs.list.count; ieIdx++)
+            {
+               if(paging->protocolIEs.list.array[ieIdx])
+               {
+                  switch(paging->protocolIEs.list.array[ieIdx]->id)
+                  {
+                     case ProtocolIE_ID_id_UEIdentityIndexValue:
+                     {
+                        CU_FREE(paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.buf,\
+                        paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.size);
+                        break;
+                     }
+                     
+                     case ProtocolIE_ID_id_PagingIdentity:
+                     {
+                        if(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.present == PagingIdentity_PR_cNUEPagingIdentity)
+                        {
+                           if(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity)
+                           {  
+                              if(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->present == CNUEPagingIdentity_PR_fiveG_S_TMSI)
+                              {
+                                 CU_FREE(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.buf,\
+                                 paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.size);
+                              }
+                                CU_FREE(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity,\
+                                sizeof(struct CNUEPagingIdentity));
+                           }
+                        }
+                        break;
+                     }
+                     
+                     case ProtocolIE_ID_id_PagingCell_List:
+                     {
+                        pagingCelllist = &paging->protocolIEs.list.array[ieIdx]->value.choice.PagingCell_list;
+                        if(pagingCelllist->list.array)
+                        {
+                           for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++)
+                           {
+                              if(pagingCelllist->list.array[cellIdx])
+                              {
+                                  pagingCellItemIes = (PagingCell_ItemIEs_t *)pagingCelllist->list.array[cellIdx];
+                                  if(pagingCellItemIes->id == ProtocolIE_ID_id_PagingCell_Item)
+                                  {
+                                     pagingCellItem = &pagingCellItemIes->value.choice.PagingCell_Item;
+                                     CU_FREE(pagingCellItem->nRCGI.pLMN_Identity.buf, pagingCellItem->nRCGI.pLMN_Identity.size);
+                                     CU_FREE(pagingCellItem->nRCGI.nRCellIdentity.buf, pagingCellItem->nRCGI.nRCellIdentity.size);
+                                  }
+                                  CU_FREE(pagingCelllist->list.array[cellIdx], sizeof(PagingCell_ItemIEs_t));
+                              }
+                           }
+                           CU_FREE(pagingCelllist->list.array, pagingCelllist->list.size);
+                        }
+                        break;
+                     }
+                  }
+                  CU_FREE(paging->protocolIEs.list.array[ieIdx], sizeof(Paging_t));
+               }
+            }
+            CU_FREE(paging->protocolIEs.list.array, paging->protocolIEs.list.size);
+         }
+         CU_FREE(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t));
+      }
+      CU_FREE(f1apMsg, sizeof(F1AP_PDU_t));
+   }
+}
+/*******************************************************************
+ *
+ * @brief Builds and sends the paging message if UE is in idle mode
+ *
+ * @details
+ *
+ *    Function : BuildAndSendPagingMsg
+ *
+ *    Functionality: Builds and sends the paging message
+ *
+ * @params[in] uint32_t duId, uint8_t gsTmsi
+ *
+ * @return ROK     - success
+ *         RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId)
+{
+   bool       memAllocFailed = false;
+   uint8_t    ieIdx = 0, elementCnt = 0, ret = RFAILED;
+   uint16_t   ueId = 0, duIdx = 0;
+
+   /*As per 38.473 Sec 9.3.1.39, UE Identity Index Value (10bits) > 2 Bytes + 6 Unused Bits
+    *5G-S-TMSI :48 Bits  >> 6 Bytes and 0 UnusedBits */
+   uint8_t    totalByteInUeId = 2, totalByteInTmsi = 6;
+   uint8_t    unusedBitsInUeId = 6, unusedBitsInTmsi = 0;
+
+   F1AP_PDU_t *f1apMsg = NULLP;
+   Paging_t   *paging = NULLP;
+   DuDb       *duDb;
+   asn_enc_rval_t         encRetVal;
+
+   DU_LOG("\nINFO  -->  F1AP : Building PAGING Message command\n");
+
+   SEARCH_DU_DB(duIdx, duId, duDb);
+   if(duDb == NULLP)
+   {
+      DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): DuDb is empty");
+      return ret; 
+   }
+
+   while(true)
+   {
+      CU_ALLOC(f1apMsg, sizeof(F1AP_PDU_t));
+      if(f1apMsg == NULLP)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): Memory allocation for F1AP-PDU");
+         break;
+      }
+
+      f1apMsg->present =  F1AP_PDU_PR_initiatingMessage;
+
+      CU_ALLOC(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t));
+      if(f1apMsg->choice.initiatingMessage == NULLP)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): Memory allocation for F1AP-PDU failed ");
+         break;
+      }
+      f1apMsg->choice.initiatingMessage->procedureCode = ProcedureCode_id_Paging;
+      f1apMsg->choice.initiatingMessage->criticality = Criticality_reject;
+      f1apMsg->choice.initiatingMessage->value.present = InitiatingMessage__value_PR_Paging;
+
+      paging = &f1apMsg->choice.initiatingMessage->value.choice.Paging;
+
+      elementCnt = 5;
+      paging->protocolIEs.list.count = elementCnt;
+      paging->protocolIEs.list.size = elementCnt * sizeof(Paging_t*);
+
+      /* Initialize the Paging Message members */
+      CU_ALLOC(paging->protocolIEs.list.array, paging->protocolIEs.list.size);
+      if(paging->protocolIEs.list.array == NULLP)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg():Memory allocation failed");
+         break;
+      }
+
+      for(ieIdx=0 ; ieIdx<elementCnt; ieIdx++)
+      {
+         CU_ALLOC(paging->protocolIEs.list.array[ieIdx], sizeof(Paging_t));
+         if(paging->protocolIEs.list.array[ieIdx] == NULLP)
+         {
+            DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): Memory allocation failed ");
+            memAllocFailed = true;  
+            break;
+         }
+      }
+
+      if(memAllocFailed == true)
+      {
+         break;
+      }
+
+      /* UE Identity Index Value */
+      ieIdx=0;
+      paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_UEIdentityIndexValue;
+      paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+      paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_UEIdentityIndexValue;
+      paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.present = UEIdentityIndexValue_PR_indexLength10;
+      paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.size = totalByteInUeId*sizeof(uint8_t);
+      CU_ALLOC(paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.buf,\
+            paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.size);
+      if(paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.buf == NULLP)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): Memory allocation failed ");
+         break;
+      }
+
+      /*As per 3gpp Spec 38.304 Sec 7.1: UE_ID: 5G-S-TMSI mod 1024*/
+      ueId = gsTmsi % 1024;
+      fillBitString(&paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10, unusedBitsInUeId, totalByteInUeId, ueId);
+
+      /* Paging Identity */
+      ieIdx++;
+      paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingIdentity;
+      paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+      paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingIdentity;
+      paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.present = \
+                                                                                   PagingIdentity_PR_cNUEPagingIdentity;
+      CU_ALLOC(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity, \
+            sizeof(struct CNUEPagingIdentity));
+      if(!paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): Memory allocation failed ");
+         break;
+      }
+
+      paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->present = \
+                                                                                                              CNUEPagingIdentity_PR_fiveG_S_TMSI;
+
+      paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.size = totalByteInTmsi*sizeof(uint8_t);
+      CU_ALLOC(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.buf,\
+            paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.size);
+      if(!paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.buf)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): Memory allocation failed ");
+         break;
+      }
+
+      fillBitString(&paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI,\
+            unusedBitsInTmsi, totalByteInTmsi, gsTmsi);
+
+      /* Paging Drx */
+      ieIdx++;
+      paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingDRX;
+      paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+      paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingDRX;
+      paging->protocolIEs.list.array[ieIdx]->value.choice.PagingDRX = PagingDRX_v32;
+
+      /* Paging Priority */
+      ieIdx++;
+      paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingPriority;
+      paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+      paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingPriority;
+      paging->protocolIEs.list.array[ieIdx]->value.choice.PagingPriority = PagingPriority_priolevel2;
+
+      /* Paging Cell List */
+      ieIdx++;
+      paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingCell_List;
+      paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+      paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingCell_list;
+      if(BuildPagingCellList(&paging->protocolIEs.list.array[ieIdx]->value.choice.PagingCell_list, duDb->numCells, duDb->cellCb) != ROK)
+      {
+         DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): Failed to build Paging cell list "); 
+         break;
+      }
+
+      xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
+
+      /* Encode the UE Context Release Command type as APER */
+      memset(encBuf, 0, ENC_BUF_MAX_LEN);
+      encBufSize = 0;
+      encRetVal = aper_encode(&asn_DEF_F1AP_PDU, 0, f1apMsg, PrepFinalEncBuf,\
+            encBuf);
+
+      /* Encode results */
+      if(encRetVal.encoded == ENCODE_FAIL)
+      {
+         DU_LOG("\nERROR  -->  F1AP : Could not encode Release Command structure (at %s)\n",\
+               encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+         break;
+      }
+      else
+      {
+         DU_LOG("\nDEBUG  -->  F1AP : Created APER encoded buffer for Paging\n");
+         for(ieIdx=0; ieIdx< encBufSize; ieIdx++)
+         {
+            DU_LOG("%x",encBuf[ieIdx]);
+         }
+      }
+
+      if(SendF1APMsg(CU_APP_MEM_REG, CU_POOL, duId) != ROK)
+      {
+         DU_LOG("\nERROR  -->  F1AP : Sending Ue context Release Command failed");
+         break;
+      }
+
+      ret = ROK;
+      break;
+
+   }
+
+   FreePagingMsg(f1apMsg); 
+   return ret;
+}
+
 /*******************************************************************
  *
  * @brief Handles received F1AP message and sends back response  
@@ -11471,6 +12116,7 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf)
                case SuccessfulOutcome__value_PR_UEContextReleaseComplete:
                   {
                       DU_LOG("\nINFO  -->  F1AP : UE Context release complete received");
+                      procUeContextReleaseComplete(*duId, f1apMsg);
                       break;
                   }
                default: