[Task-ID: ODUHIGH-484] Support for NAS Authentication Messages
[o-du/l2.git] / src / cu_stub / cu_f1ap_msg_hdl.c
index 6404c4d..4f1858e 100644 (file)
@@ -224,10 +224,10 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId)
    uint8_t    idx,ieIdx;
    uint8_t    elementCnt,cellCnt;
    F1AP_PDU_t         *f1apMsg = NULL;
-   F1SetupResponse_t  *f1SetupRsp;
-   GNB_CU_Name_t      *cuName;
+   F1SetupResponse_t  *f1SetupRsp = NULL;
+   GNB_CU_Name_t      *cuName = NULL;
    Cells_to_be_Activated_List_t *cellToActivate;
-   RRC_Version_t      *rrcVer;
+   RRC_Version_t      *rrcVer = NULL;
    asn_enc_rval_t     encRetVal; 
    DU_LOG("\nINFO  -->  F1AP : Building F1 Setup Response\n");
 
@@ -254,7 +254,7 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId)
                                                       SuccessfulOutcome__value_PR_F1SetupResponse;
    f1SetupRsp = &f1apMsg->choice.successfulOutcome->value.choice.F1SetupResponse;
 
-   elementCnt = 4;
+   elementCnt = 3;
    f1SetupRsp->protocolIEs.list.count = elementCnt;
    f1SetupRsp->protocolIEs.list.size = elementCnt*sizeof(F1SetupResponseIEs_t *);
 
@@ -291,58 +291,54 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId)
                                                             F1SetupResponseIEs__value_PR_TransactionID;
    f1SetupRsp->protocolIEs.list.array[idx]->value.choice.TransactionID =\
                                                                         TRANS_ID;
-
+#if 0
+   /* CU name IE is of type printableString_t which wireshark is unable to decode.
+    * However this string is decoded successfully on online decoders.
+    * Since this is an optional IE and the value received in it are not
+    * used as of now, eliminating this IE for now to avoid wireshark error.
+    */
    /*CU Name*/
    idx++;
    f1SetupRsp->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_gNB_CU_Name;
    f1SetupRsp->protocolIEs.list.array[idx]->criticality = Criticality_ignore;
-   f1SetupRsp->protocolIEs.list.array[idx]->value.present = \
-                                                            F1SetupResponseIEs__value_PR_GNB_CU_Name;
+   f1SetupRsp->protocolIEs.list.array[idx]->value.present = F1SetupResponseIEs__value_PR_GNB_CU_Name;
    cuName = &f1SetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_Name;
-   cuName->size = sizeof(cuCb.cuCfgParams.cuName);
+   cuName->size = strlen((char *)cuCb.cuCfgParams.cuName);
 
-   CU_ALLOC(cuName->buf, sizeof(cuName->size)); 
+   CU_ALLOC(cuName->buf, cuName->size); 
    if(cuName->buf == NULLP)
    {
       for(ieIdx=0; ieIdx<elementCnt; ieIdx++)
       {
-         CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx],\
-               sizeof(F1SetupResponseIEs_t));
+         CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx], sizeof(F1SetupResponseIEs_t));
       }
-      CU_FREE(f1SetupRsp->protocolIEs.list.array,\
-            elementCnt * sizeof(F1SetupResponseIEs_t *));
-      CU_FREE(f1apMsg->choice.successfulOutcome,\
-            sizeof(SuccessfulOutcome_t));
+      CU_FREE(f1SetupRsp->protocolIEs.list.array, elementCnt * sizeof(F1SetupResponseIEs_t *));
+      CU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t));
       CU_FREE(f1apMsg, sizeof(F1AP_PDU_t));
       return RFAILED;
    }
    strcpy((char*)cuName->buf, (char*)cuCb.cuCfgParams.cuName);
+#endif
 
    /*Cells to be activated list*/
    idx++;
-   f1SetupRsp->protocolIEs.list.array[idx]->id = \
-                                                 ProtocolIE_ID_id_Cells_to_be_Activated_List ;
+   f1SetupRsp->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_Cells_to_be_Activated_List ;
    f1SetupRsp->protocolIEs.list.array[idx]->criticality = Criticality_reject;
-   f1SetupRsp->protocolIEs.list.array[idx]->value.present = \
-                                                            F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List;
-   cellToActivate = &f1SetupRsp->protocolIEs.list.array[idx]->value.choice.\
-                    Cells_to_be_Activated_List;
+   f1SetupRsp->protocolIEs.list.array[idx]->value.present = F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List;
+   cellToActivate = &f1SetupRsp->protocolIEs.list.array[idx]->value.choice.Cells_to_be_Activated_List;
+
    cellCnt=1;
    cellToActivate->list.count = cellCnt;
-   cellToActivate->list.size = \
-                               cellCnt*sizeof(struct Cells_to_be_Activated_List_ItemIEs  *);
-   CU_ALLOC(cellToActivate->list.array,\
-         sizeof(struct Cells_to_be_Activated_List_ItemIEs  *));
+   cellToActivate->list.size = cellCnt * sizeof(struct Cells_to_be_Activated_List_ItemIEs  *);
+   CU_ALLOC(cellToActivate->list.array, sizeof(struct Cells_to_be_Activated_List_ItemIEs  *));
    if(cellToActivate->list.array == NULLP)
    {
       CU_FREE(cuName->buf, sizeof(cuName->size));
       for(ieIdx=0; ieIdx<elementCnt; ieIdx++)
       {
-         CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx],\
-               sizeof(F1SetupResponseIEs_t));
+         CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx], sizeof(F1SetupResponseIEs_t));
       }
-      CU_FREE(f1SetupRsp->protocolIEs.list.array,\
-            elementCnt * sizeof(F1SetupResponseIEs_t *));
+      CU_FREE(f1SetupRsp->protocolIEs.list.array, elementCnt * sizeof(F1SetupResponseIEs_t *));
       CU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t));
       CU_FREE(f1apMsg, sizeof(F1AP_PDU_t));
       return RFAILED;
@@ -352,18 +348,14 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId)
       CU_ALLOC(cellToActivate->list.array[ieIdx],sizeof(struct Cells_to_be_Activated_List_ItemIEs ));
       if(cellToActivate->list.array[ieIdx] == NULLP)
       {
-         CU_FREE(cellToActivate->list.array,\
-               sizeof(struct Cells_to_be_Activated_List_ItemIEs  *));
+         CU_FREE(cellToActivate->list.array, sizeof(struct Cells_to_be_Activated_List_ItemIEs  *));
          CU_FREE(cuName->buf, sizeof(cuName->size));
          for(ieIdx=0; ieIdx<elementCnt; ieIdx++)
          {
-            CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx], \
-                  sizeof(F1SetupResponseIEs_t));
+            CU_FREE(f1SetupRsp->protocolIEs.list.array[ieIdx], sizeof(F1SetupResponseIEs_t));
          }
-         CU_FREE(f1SetupRsp->protocolIEs.list.array, \
-               elementCnt * sizeof(F1SetupResponseIEs_t *));
-         CU_FREE(f1apMsg->choice.successfulOutcome, \
-               sizeof(SuccessfulOutcome_t));
+         CU_FREE(f1SetupRsp->protocolIEs.list.array, elementCnt * sizeof(F1SetupResponseIEs_t *));
+         CU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t));
          CU_FREE(f1apMsg, sizeof(F1AP_PDU_t));
          return RFAILED;
       }
@@ -439,6 +431,7 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId)
       return RFAILED;
    }
    memcpy(&cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity, nrcellId, sizeof(BIT_STRING_t)); 
+
    /* RRC Version */
    idx++;
    f1SetupRsp->protocolIEs.list.array[idx]->id = \
@@ -573,8 +566,10 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId)
    encRetVal = aper_encode(&asn_DEF_F1AP_PDU, 0, f1apMsg, PrepFinalEncBuf, encBuf);
 
    /* Clean up */
-   CU_FREE(rrcVer->latest_RRC_Version.buf, sizeof(uint8_t));
-   CU_FREE(cuName->buf, sizeof(cuName->size));
+   if(rrcVer)
+      CU_FREE(rrcVer->latest_RRC_Version.buf, sizeof(uint8_t));
+   if(cuName)
+      CU_FREE(cuName->buf, cuName->size);
    for(idx=0; idx<elementCnt; idx++)
    {
       CU_FREE(f1SetupRsp->protocolIEs.list.array[idx], sizeof(F1SetupResponseIEs_t));
@@ -1113,7 +1108,7 @@ uint8_t fillDlCcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer)
                   xer_fprint(stdout, &asn_DEF_DL_CCCH_MessageType, &dl_CCCH_Msg);
                   memset(encBuf, 0, ENC_BUF_MAX_LEN);
                   encBufSize = 0;
-                  encRetVal = aper_encode(&asn_DEF_DL_CCCH_MessageType, 0, &dl_CCCH_Msg, PrepFinalEncBuf, encBuf);
+                  encRetVal = uper_encode(&asn_DEF_DL_CCCH_MessageType, 0, &dl_CCCH_Msg, PrepFinalEncBuf, encBuf);
                   /* Encode results */
                   if(encRetVal.encoded == ENCODE_FAIL)
                   {
@@ -1406,7 +1401,7 @@ uint8_t fillRrcReconfigIE(RRCReconfiguration_IEs_t *rrcReconfigMsg)
  *
  * ****************************************************************/
 
-uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer)
+uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer, bool updateAllRbCfg)
 {
    uint8_t ret = ROK;
    uint16_t idx2 = 0, drbIdx = 0, srbIdx = 0;
@@ -1426,7 +1421,7 @@ uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer)
          if(dl_DCCH_Msg.message.choice.c1->choice.rrcReconfiguration != NULLP)
          {
             DU_LOG("\nDEBUG --> F1AP : Filling DL DCCH RRC Reconfiguration Message ");
-            fillRrcReconfig(ueCb, dl_DCCH_Msg.message.choice.c1->choice.rrcReconfiguration, false);
+            fillRrcReconfig(ueCb, dl_DCCH_Msg.message.choice.c1->choice.rrcReconfiguration, updateAllRbCfg);
             if(ret == ROK)
             {
                /* If RB configuration are filled successfully in RRC Reconfiguration, mark these
@@ -1446,7 +1441,7 @@ uint8_t fillDlDcchRrcMsg(CuUeCb *ueCb, RRCContainer_t *rrcContainer)
                xer_fprint(stdout, &asn_DEF_DL_DCCH_MessageType, &dl_DCCH_Msg);
                memset(encBuf, 0, ENC_BUF_MAX_LEN);
                encBufSize = 0;
-               encRetVal = aper_encode(&asn_DEF_DL_DCCH_MessageType, 0, &dl_DCCH_Msg, PrepFinalEncBuf, encBuf);
+               encRetVal = uper_encode(&asn_DEF_DL_DCCH_MessageType, 0, &dl_DCCH_Msg, PrepFinalEncBuf, encBuf);
                /* Encode results */
                if(encRetVal.encoded == ENCODE_FAIL)
                {
@@ -1524,9 +1519,31 @@ uint8_t  BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr
          DU_LOG("\nERROR  -->  F1AP: Failed to fill DL-CCCH Msg at RRC SETUP");
    }
    else if(rrcMsgType == RRC_SETUP_COMPLETE)
+   {
+      DU_LOG("\nINFO --> F1AP : Sending NAS Authentication Request");
+      char authReqBuf[51] = {0x00, ueCb->pdcpSn++, 0x2a, 0x85, 0x4f, 0xc0, 0x0a, 0xc0, 0x40, 0x40, 0x00, 0x04, 0x2f, 0x58, 0x39, 0x12,\
+                             0x37, 0x15, 0x74, 0x16, 0x4c, 0x8d, 0xd3, 0x95, 0xa6, 0x9e, 0x94, 0x03, 0x24, 0x02, 0x00, 0x6f,\
+                             0x0b, 0x39, 0x5e, 0xbc, 0xb0, 0x00, 0x1a, 0xb1, 0xc1, 0x3f, 0x84, 0x4f, 0x77, 0xe3, 0x20, 0x00,\
+                             0x00, 0x00, 0x00};
+      bufLen = 51;
+      rrcContainer->size = bufLen;
+      CU_ALLOC(rrcContainer->buf, rrcContainer->size);
+      if(rrcContainer->buf != NULLP)
+      {
+         memset(rrcContainer->buf, 0, bufLen); 
+         memcpy(rrcContainer->buf, authReqBuf, bufLen);
+      }
+      else
+      {
+         DU_LOG("\nERROR  -->  F1AP : Memory allocation failure for RRC Container buffer");
+         ret = RFAILED;
+
+      }     
+   }
+   else if(rrcMsgType == NAS_AUTHENTICATION_RSP)
    {
       DU_LOG("\nINFO --> F1AP : Sending NAS Security mode command");
-      char secModeBuf[30]={0x00, 0x02, 0x2e, 0x82, 0xaf, 0xc0, 0x7d, 0x1c, 0x4e, 0xfc, 0x80, 0x0f, 0xc0, 
+      char secModeBuf[30]={0x00, ueCb->pdcpSn++, 0x2e, 0x82, 0xaf, 0xc0, 0x7d, 0x1c, 0x4e, 0xfc, 0x80, 0x0f, 0xc0, 
                           0x0b, 0xa0, 0x20, 0x40, 0x9e, 0x0e, 0x1e, 0x0e, 0x1c, 0x26, 0xc0, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00};
       bufLen =30;
       rrcContainer->size = bufLen;
@@ -1545,7 +1562,7 @@ uint8_t   BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr
    else if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE)
    {
       DU_LOG("\nINFO --> F1AP : Sending RRC Security mode command");
-      char secModeBuf[9]={0x00, 0x03, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00};
+      char secModeBuf[9]={0x00, ueCb->pdcpSn++, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00};
       bufLen =9;
       rrcContainer->size = bufLen;
       CU_ALLOC(rrcContainer->buf, rrcContainer->size);
@@ -1564,7 +1581,7 @@ uint8_t   BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr
    {
       /*Hardcoded RRC Container from reference logs*/
       DU_LOG("\nINFO --> F1AP : Sending Registration accept");
-      char buf[14] ={0x00, 0x04, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00};
+      char buf[14] ={0x00, ueCb->pdcpSn++, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00};
       bufLen =14;
       rrcContainer->size = bufLen;
       CU_ALLOC(rrcContainer->buf, rrcContainer->size);
@@ -1581,8 +1598,22 @@ uint8_t  BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr
    }
    else if(rrcMsgType == UE_CONTEXT_SETUP_RSP)
    {
+      uint16_t tmpBufIdx = 0, bufIdx = 0;
+      RRCContainer_t rrcContainerTmp;
       DU_LOG("\nINFO --> F1AP : Filling DL DCCH RRC Message for RRC Reconfiguration ");
-      ret = fillDlDcchRrcMsg(ueCb, rrcContainer);
+      ret = fillDlDcchRrcMsg(ueCb, &rrcContainerTmp, false);
+      rrcContainer->size = rrcContainerTmp.size + 2;
+      CU_ALLOC(rrcContainer->buf, rrcContainer->size);
+      if(rrcContainer->buf != NULLP)
+      {
+         memset(rrcContainer->buf, 0, rrcContainer->size);
+         rrcContainer->buf[0] = 0x00;
+         rrcContainer->buf[1] = ueCb->pdcpSn++; //PDCP SN
+         for(bufIdx = 2, tmpBufIdx = 0; bufIdx < rrcContainer->size; bufIdx++, tmpBufIdx++)
+         {
+            rrcContainer->buf[bufIdx] = rrcContainerTmp.buf[tmpBufIdx];
+         }
+      }
       if(ret == RFAILED)
          DU_LOG("\nERROR  -->  F1AP: Failed to fill DL-DCCH Msg for RRC Reconfiguration");
    }
@@ -1798,6 +1829,9 @@ uint8_t setDlRRCMsgType(CuUeCb *ueCb)
       case RRC_SETUP_COMPLETE:
          rrcMsgType = RRC_SETUP_COMPLETE;
          break;
+      case NAS_AUTHENTICATION_RSP:
+         rrcMsgType = NAS_AUTHENTICATION_RSP;
+         break;
       case NAS_SECURITY_MODE_COMPLETE:
          rrcMsgType = NAS_SECURITY_MODE_COMPLETE;
          break;
@@ -1965,25 +1999,22 @@ void fillLongCycleOffsetValue(DrxLongCycleStartOffset *drxLongCycleStartOffset,
  * ****************************************************************/
 void storeDrxCfgInUeCb(struct DRX_ConfigRrc *drxSetup, DrxCfg *drxCfg)
 {
-   if(drxSetup)
+   switch(drxSetup->drx_onDurationTimer.present)
    {
-      switch(drxSetup->drx_onDurationTimer.present)
-      {
-         case DRX_ConfigRrc__drx_onDurationTimer_PR_NOTHING:
+      case DRX_ConfigRrc__drx_onDurationTimer_PR_NOTHING:
+         break;
+      case DRX_ConfigRrc__drx_onDurationTimer_PR_milliSeconds:
+         {
+            drxCfg->drxOnDurationTimer.onDurationTimerValInMs = true;
+            drxCfg->drxOnDurationTimer.onDurationtimerValue.milliSeconds=drxSetup->drx_onDurationTimer.choice.milliSeconds;
             break;
-         case DRX_ConfigRrc__drx_onDurationTimer_PR_milliSeconds:
-            {
-               drxCfg->drxOnDurationTimer.onDurationTimerValInMs = true;
-               drxCfg->drxOnDurationTimer.onDurationtimerValue.milliSeconds=drxSetup->drx_onDurationTimer.choice.milliSeconds;
-               break;
-            }
-         case DRX_ConfigRrc__drx_onDurationTimer_PR_subMilliSeconds:
-            {
-               drxCfg->drxOnDurationTimer.onDurationTimerValInMs = false;
-               drxCfg->drxOnDurationTimer.onDurationtimerValue.subMilliSeconds = drxSetup->drx_onDurationTimer.choice.subMilliSeconds;
-               break;
-            }
-      }
+         }
+      case DRX_ConfigRrc__drx_onDurationTimer_PR_subMilliSeconds:
+         {
+            drxCfg->drxOnDurationTimer.onDurationTimerValInMs = false;
+            drxCfg->drxOnDurationTimer.onDurationtimerValue.subMilliSeconds = drxSetup->drx_onDurationTimer.choice.subMilliSeconds;
+            break;
+         }
    }
    fillLongCycleOffsetValue(&drxCfg->drxLongCycleStartOffset, &drxSetup->drx_LongCycleStartOffset);
    drxCfg->drxInactivityTimer = drxSetup->drx_InactivityTimer;
@@ -2060,7 +2091,11 @@ uint8_t extractCellGroupConfig(CuUeCb *ueCb, CellGroupConfigRrc_t *cellGrpCfg)
 
             case MAC_CellGroupConfig__drx_ConfigRrc_PR_setup:
             {
-               storeDrxCfgInUeCb(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup, &ueCb->drxCfg);
+               if(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup)
+               {
+                  ueCb->drxCfgPresent = true;  
+                  storeDrxCfgInUeCb(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup, &ueCb->drxCfg);
+               }
                break;
             }
 
@@ -2204,7 +2239,7 @@ uint8_t extractDuToCuRrcCont(CuUeCb *ueCb, OCTET_STRING_t rrcCont)
    cellGrpCfgMsg = &cellGrpCfg;
    memset(cellGrpCfgMsg, 0, sizeof(CellGroupConfigRrc_t));
 
-   rval = aper_decode(0, &asn_DEF_CellGroupConfigRrc, (void **)&cellGrpCfgMsg, rrcCont.buf, rrcCont.size, 0, 0);
+   rval = uper_decode(0, &asn_DEF_CellGroupConfigRrc, (void **)&cellGrpCfgMsg, rrcCont.buf, rrcCont.size, 0, 0);
 
    if(rval.code == RC_FAIL || rval.code == RC_WMORE)
    {
@@ -6737,7 +6772,7 @@ uint8_t fillCellGrpCfg(CuUeCb *ueCb, OCTET_STRING_t *cellGrp, bool updateAllRbCf
       xer_fprint(stdout, &asn_DEF_CellGroupConfigRrc, &cellGrpCfg);
       cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
       encBufSize = 0;
-      encRetVal = aper_encode(&asn_DEF_CellGroupConfigRrc, 0, &cellGrpCfg, PrepFinalEncBuf, encBuf);
+      encRetVal = uper_encode(&asn_DEF_CellGroupConfigRrc, 0, &cellGrpCfg, PrepFinalEncBuf, encBuf);
       /* Encode results */
       if(encRetVal.encoded == ENCODE_FAIL)
       {
@@ -7125,7 +7160,7 @@ uint8_t fillUeCapRatCont(OCTET_STRING_t *ueCapRatContBuf)
       xer_fprint(stdout, &asn_DEF_UE_NR_Capability, &ueNrCap);
       cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
       encBufSize = 0;
-      encRetVal = aper_encode(&asn_DEF_UE_NR_Capability, 0, &ueNrCap, PrepFinalEncBuf, encBuf);
+      encRetVal = uper_encode(&asn_DEF_UE_NR_Capability, 0, &ueNrCap, PrepFinalEncBuf, encBuf);
    
       /* Encode results */
       if(encRetVal.encoded == ENCODE_FAIL)
@@ -7253,7 +7288,7 @@ uint8_t fillUeCapRatContListBuf(UE_CapabilityRAT_ContainerList_t *ueCapablityLis
       xer_fprint(stdout, &asn_DEF_UE_CapabilityRAT_ContainerListRRC, &ueCapablityList);
       cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
       encBufSize = 0;
-      encRetVal = aper_encode(&asn_DEF_UE_CapabilityRAT_ContainerListRRC, 0, \
+      encRetVal = uper_encode(&asn_DEF_UE_CapabilityRAT_ContainerListRRC, 0, \
             &ueCapablityList, PrepFinalEncBuf, encBuf);
 
       /* Encode results */
@@ -7451,7 +7486,7 @@ uint8_t fillMeasTimingConfigBuf(MeasConfig_t *measTimingConfigBuf)
       xer_fprint(stdout, &asn_DEF_MeasurementTimingConfigurationRrc, &measTimingConfig);
       cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
       encBufSize = 0;
-      encRetVal = aper_encode(&asn_DEF_MeasurementTimingConfigurationRrc, 0, &measTimingConfig, PrepFinalEncBuf, encBuf);
+      encRetVal = uper_encode(&asn_DEF_MeasurementTimingConfigurationRrc, 0, &measTimingConfig, PrepFinalEncBuf, encBuf);
 
       /* Encode results */
       if(encRetVal.encoded == ENCODE_FAIL)
@@ -8264,7 +8299,7 @@ uint8_t fillMeasObjToAddModList(MeasObjectToAddModList_t *measObjList)
 
    /* RSRQ offset for SSB */
    CU_ALLOC(measObject->offsetMO.rsrqOffsetSSB, sizeof(Q_OffsetRange_t));
-   if(!measObject->offsetMO.rsrpOffsetSSB)
+   if(!measObject->offsetMO.rsrqOffsetSSB)
    {
       DU_LOG("\nERROR  -->  F1AP: Memory allocation failed for SSB RSRQ offset in fillMeasObjToAddModList");
       return RFAILED;
@@ -8819,7 +8854,7 @@ uint8_t fillRrcReconfigBuf(CuUeCb *ueCb, OCTET_STRING_t  *rrcReconfigBuf, bool u
       xer_fprint(stdout, &asn_DEF_RRCReconfiguration, rrcReconfig);
       cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
       encBufSize = 0;
-      encRetVal = aper_encode(&asn_DEF_RRCReconfiguration, 0, rrcReconfig, PrepFinalEncBuf, encBuf);
+      encRetVal = uper_encode(&asn_DEF_RRCReconfiguration, 0, rrcReconfig, PrepFinalEncBuf, encBuf);
 
       /* Encode results */
       if(encRetVal.encoded == ENCODE_FAIL)
@@ -8930,7 +8965,7 @@ uint8_t fillHOPreparationInfoBuf(CuUeCb *ueCb, HandoverPreparationInformation_t
       xer_fprint(stdout, &asn_DEF_HandoverPreparationInformationRrc, &hoPrepInfo);
       cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
       encBufSize = 0;
-      encRetVal = aper_encode(&asn_DEF_HandoverPreparationInformationRrc, 0, \
+      encRetVal = uper_encode(&asn_DEF_HandoverPreparationInformationRrc, 0, \
             &hoPrepInfo, PrepFinalEncBuf, encBuf);
 
       /* Encode results */
@@ -8996,6 +9031,21 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg)
    }
    ret = fillUeCapRatContListBuf(rrcMsg->uE_CapabilityRAT_ContainerList);
 
+#if 0
+
+   /* Commenting this because:
+    * CUToDURRCInformation->MeasConfig contains measurement gap configurations.
+    * Howeever measurement gap is not supported in our code. Measurement Gap will
+    * be required if we want to support inter-RAT handover or handover to
+    * neighbouring cells operating on a different frequency than serving cell.
+    *
+    * In case we plan to use this IE in future, following fixes are required:
+    * As of now, we are filling MeasurementTimingConfigurationRrc_t into rrcMsg->measConfig.
+    * This is incorrect. We must fill MeasConfigRrc_t in rrcMsg->measConfig.
+    * MeasurementTimingConfigurationRrc_t should be filled in 
+    * rrcMsg->iE_Extensions->MeasurementTimingConfiguration, if required.
+    */
+
    CU_ALLOC(rrcMsg->measConfig, sizeof(MeasConfig_t));
    if(!rrcMsg->measConfig)
    {
@@ -9003,6 +9053,7 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg)
       return RFAILED;
    }
    ret = fillMeasTimingConfigBuf(rrcMsg->measConfig);
+#endif
 
    if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
    {
@@ -9071,7 +9122,7 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg)
  ******************************************************************/
 uint8_t BuildDrxCycle(DRXCycle_t *drxCycle)
 {
-   drxCycle->longDRXCycleLength = LongDRXCycleLength_ms40;
+   drxCycle->longDRXCycleLength = LongDRXCycleLength_ms80;
    CU_ALLOC(drxCycle->shortDRXCycleLength, sizeof(ShortDRXCycleLength_t));
    if(!drxCycle->shortDRXCycleLength)
    {
@@ -9803,22 +9854,7 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
       ueCb = &duDb->ueCb[duUeF1apId-1];
       ueCb->f1apMsgDb.dlRrcMsgCount++;
       rrcMsgType = setDlRRCMsgType(ueCb);
-      if(rrcMsgType == RRC_SETUP_COMPLETE)
-      {
-         DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for NAS Security Mode Command");
-         ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
-      }
-      if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE)
-      {
-         DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for RRC Security Mode Command"); 
-         ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
-      }
-      else if(rrcMsgType == RRC_SECURITY_MODE_COMPLETE)
-      {
-         DU_LOG("\nINFO  -->  F1AP: Sending DL RRC MSG for RRC Registration Accept");
-         BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
-      }
-      else if(rrcMsgType == REGISTRATION_COMPLETE)
+      if(rrcMsgType == REGISTRATION_COMPLETE)
       {
          DU_LOG("\nINFO  -->  F1AP: Sending Ue Context Setup Request"); 
          ret = BuildAndSendUeContextSetupReq(duId, ueCb);
@@ -9828,6 +9864,11 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
          DU_LOG("\nINFO  -->  F1AP: Sending UE Context Modification Request");
          BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND);
       }
+      else
+      {
+         /* In case rrcMsgType is RRC_SETUP_COMPLETE / NAS_AUTHENTICATION_RSP / NAS_SECURITY_MODE_COMPLETE / RRC_SECURITY_MODE_COMPLETE */
+         BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
+      }
    }
    return ret;
 }
@@ -10706,6 +10747,95 @@ uint8_t BuildDrbToBeModifiedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeModified_
    return ret;
 }
 
+/*******************************************************************
+*
+* @brief Builds the DRB to be released Item IE
+*
+* @details
+*
+*    Function : FillDrbToBeRelItemList
+*
+*    Functionality: Constructs the DRB to be modified Mod Item Ies
+*
+* @params[in] struct DRBs_ToBeReleased_ItemIEs *drbItemIe
+*
+* @return ROK     - success
+*         RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t FillDrbToBeRelItemList(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeReleased_ItemIEs *drbItemIe)
+{
+   uint8_t drbIdx;
+
+   drbItemIe->id = ProtocolIE_ID_id_DRBs_ToBeReleased_Item;
+   drbItemIe->criticality = Criticality_reject;
+   drbItemIe->value.present = DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item;
+   drbItemIe->value.choice.DRBs_ToBeReleased_Item.dRBID = DRB1 + arrIdx;
+
+   for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++)
+   {
+      if(ueCb->drbList[drbIdx].drbId == drbItemIe->value.choice.DRBs_ToBeReleased_Item.dRBID)
+      {
+         deleteEgtpTunnel(duId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId);
+         CU_FREE(ueCb->drbList[drbIdx].snssai, sizeof(Snssai));
+         break;
+      }
+   }
+   return ROK;
+}
+
+/*******************************************************************
+*
+* @brief Builds the DRB to be released list 
+*
+* @details
+*
+*    Function : BuildDrbToBeReleasedList 
+*
+*    Functionality: Constructs the DRB to be released list
+*
+* @params[in] DRBs_ToBeReleased_List_t *drbSet 
+*
+* @return ROK     - success
+*         RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t BuildDrbToBeReleasedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeReleased_List_t *drbSet)
+{
+   uint8_t ret = ROK;
+   uint8_t arrIdx =0;
+   uint8_t drbCnt =0;
+
+   drbCnt = MAX_DRB_MODIFIED_UE_MOD_REQ;
+   drbSet->list.count = drbCnt;
+   drbSet->list.size = drbCnt * sizeof(DRBs_ToBeReleased_ItemIEs_t *);
+   CU_ALLOC(drbSet->list.array, drbSet->list.size);
+   if(drbSet->list.array == NULLP)
+   {
+      DU_LOG("\nERROR  -->  F1AP : Memory allocation failed in BuildDrbToBeReleasedList");
+      return  RFAILED;
+   }
+   for(arrIdx=0; arrIdx<drbCnt; arrIdx++)
+   {
+      CU_ALLOC(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeReleased_ItemIEs_t));
+      if(drbSet->list.array[arrIdx] == NULLP)
+      {
+         DU_LOG("\nERROR  -->  F1AP : Memory allocation failed in BuildDrbToBeReleasedList");
+         return  RFAILED;
+      }
+
+      ret = FillDrbToBeRelItemList(duId, ueCb, arrIdx, (DRBs_ToBeReleased_ItemIEs_t *)drbSet->list.array[arrIdx]);
+      if(ret != ROK)
+      {
+         DU_LOG("\nERROR  -->  F1AP : FillDrbToBeRelItemList failed");
+      }
+   }
+
+   return ret;
+}
+
 /*******************************************************************
 *
 * @brief freeing the DRB  item
@@ -10827,6 +10957,40 @@ void FreeDrbToBeModifiedList(DRBs_ToBeModified_List_t *drbSet)
 
 }
 
+/*******************************************************************
+*
+* @brief free the DRB to be modfified list
+*
+* @details
+*
+*    Function : FreeDrbToBeReleasedList
+*
+*    Functionality: free the DRB to be Release list
+*
+* @params[in] FreeDrbToBeReleasedList_t *drbSet
+*
+* @return ROK     - success
+*         RFAILED - failure
+*
+* ****************************************************************/
+void FreeDrbToBeReleasedList(DRBs_ToBeReleased_List_t *drbSet)
+{
+   uint8_t arrIdx =0;
+   struct DRBs_ToBeReleased_ItemIEs *drbItemIe;
+
+   if(drbSet->list.array)
+   {
+      for(arrIdx=0; arrIdx<drbSet->list.count ; arrIdx++)
+      {
+         if(drbSet->list.array[arrIdx] != NULLP)
+         {
+            CU_FREE(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeReleased_ItemIEs_t));
+         }
+      }
+      CU_FREE(drbSet->list.array, drbSet->list.size);
+   }
+}
+
 /*******************************************************************
  *
  * @brief  free the UeContextModification Request 
@@ -10878,6 +11042,12 @@ void FreeUeContextModicationRequest(F1AP_PDU_t *f1apMsg)
                                  choice.DRBs_ToBeModified_List);
                            break;
                         }
+                     case ProtocolIE_ID_id_DRBs_ToBeReleased_List:
+                        {
+                           FreeDrbToBeReleasedList(&ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
+                                 choice.DRBs_ToBeReleased_List);
+                           break;
+                        }
                     case ProtocolIE_ID_id_TransmissionActionIndicator:
                         break;
                     case ProtocolIE_ID_id_RRCContainer:
@@ -10919,9 +11089,11 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
    uint8_t    ieIdx = 0;
    uint8_t    elementCnt = 0;
    uint8_t    ret = RFAILED;
+   uint16_t   tmpBufIdx = 0, bufIdx = 0;
    CuUeCb     *ueCb = (CuUeCb *)cuUeCb;
    F1AP_PDU_t *f1apMsg = NULLP;
    UEContextModificationRequest_t *ueContextModifyReq = NULLP;
+   RRCContainer_t rrcContainerTmp, *rrcContainer = NULLP;
    asn_enc_rval_t         encRetVal;
    DU_LOG("\nINFO  -->  F1AP : Building Ue context modification request\n");
    while(1)
@@ -10948,14 +11120,18 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
       ueContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest;
 
       if(action == MODIFY_UE)
-         elementCnt = 4;
+         elementCnt = 5;
       else if(action == QUERY_CONFIG)
          elementCnt = 3;
       else if(action == RRC_RECONFIG_COMPLETE_IND)
          elementCnt = 3;
       else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX)) 
          elementCnt = 5;
-
+      
+#ifdef NR_DRX
+      if(DRX_TO_BE_RELEASE && ueCb->drxCfgPresent)
+         elementCnt++;
+#endif      
       ueContextModifyReq->protocolIEs.list.count = elementCnt;
       ueContextModifyReq->protocolIEs.list.size = elementCnt*sizeof(UEContextModificationRequest_t *);
 
@@ -11011,15 +11187,26 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
          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  */
+         /* DRB to be released list */
+         ieIdx++;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRBs_ToBeReleased_List;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\
+                                                                 UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List;
+         ret = BuildDrbToBeReleasedList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
+                  value.choice.DRBs_ToBeReleased_List));
+
+         if(ret != ROK)
+         {
+            DU_LOG("\nERROR  -->  F1AP : BuildAndSendUeContextModificationReq(): Failed to build drb to be deleted list");
+            break;
+         }
       }
       else if(action == QUERY_CONFIG)
       {
@@ -11065,14 +11252,24 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
          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)
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCContainer;
+         if(fillDlDcchRrcMsg(ueCb, &rrcContainerTmp, true) != ROK)
          {
             DU_LOG( "\nERROR  -->  F1AP : Failed to fill Rrc reconfiguration buffer");
             return RFAILED;
          }
 
+         rrcContainer = &ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer;
+         rrcContainer->size = rrcContainerTmp.size + 2; /* 2 bytes of PDCP SN */
+         CU_ALLOC(rrcContainer->buf, rrcContainer->size);
+         memset(rrcContainer->buf, 0, rrcContainer->size);
+         rrcContainer->buf[0] = 0x00;
+         rrcContainer->buf[1] = ueCb->pdcpSn; //PDCP SN
+         for(bufIdx = 2, tmpBufIdx = 0; bufIdx < rrcContainer->size; bufIdx++, tmpBufIdx++)
+         {
+            rrcContainer->buf[bufIdx] = rrcContainerTmp.buf[tmpBufIdx];
+         }
+
          /* RRC delivery status request */
          ieIdx++;
          ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
@@ -11081,6 +11278,20 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
          ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true;
       }
 
+#ifdef NR_DRX
+      if(DRX_TO_BE_RELEASE && ueCb->drxCfgPresent)
+      {
+         /* DRX Configuration Indicator */
+         ieIdx++;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRXConfigurationIndicator;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_DRXConfigurationIndicator;
+         ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.DRXConfigurationIndicator = DRXConfigurationIndicator_release;
+         ueCb->drxCfgPresent = false;
+         memset(&ueCb->drxCfg, 0, sizeof(DrxCfg));
+      }
+#endif
+
       xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
 
       /* Encode the F1SetupRequest type as APER */
@@ -11720,6 +11931,11 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
                 break; 
 
              }
+             case ProtocolIE_ID_id_DRBs_Modified_List:
+             {
+                DU_LOG("\nINFO  -->  Received DRBs Modified List");
+                break;
+             }
           case ProtocolIE_ID_id_SRBs_SetupMod_List:
              {
                 procSrbSetupModList(ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.SRBs_SetupMod_List);
@@ -11776,6 +11992,10 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
       }
    }
    
+#ifdef START_DL_UL_DATA
+   startDlData();
+#endif
+
    return ROK;
 }
 
@@ -12142,6 +12362,11 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId)
       DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): DuDb is empty");
       return ret; 
    }
+   if(duDb->numCells == 0)
+   {
+      DU_LOG("\nERROR  -->  F1AP : BuildAndSendPagingMsg(): No CELL is UP!");
+      return ret; 
+   }
 
    while(true)
    {