[Epic-ID: ODUHIGH-406][Task-ID: ODUHIGH-423]Filled ReconfigurationWithSync IE,
[o-du/l2.git] / src / cu_stub / cu_f1ap_msg_hdl.c
index ba37520..a98fb75 100644 (file)
@@ -1960,6 +1960,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));
@@ -2629,7 +2632,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To
       ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[0] = 0;
       ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[1] = 0;
       ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[2] = 0;
-      ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[3] = cuCb.cuCfgParams.egtpParams.egtpAssoc[duId-1].currTunnelId++;
+      ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[3] = cuCb.cuCfgParams.egtpParams.currTunnelId++;
 
       ulUpTnlInfo->teId[0] = ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[0];
       ulUpTnlInfo->teId[1] = ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[1];
@@ -8442,13 +8445,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;
 }
@@ -9265,10 +9283,12 @@ uint8_t procDrbSetupList(uint32_t duId, 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;
+   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;
@@ -9277,10 +9297,37 @@ 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:
@@ -9292,6 +9339,8 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
          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)
                 {
@@ -9302,7 +9351,58 @@ 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;
+      }
+   }
    return ROK;
 }
 
@@ -9754,7 +9854,7 @@ uint8_t BuildUlTnlInfoforSetupMod(uint32_t duId, uint8_t ueId, uint8_t drbId, Tn
    else
    {
       ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
-        gTP_TEID.buf[3] = cuCb.cuCfgParams.egtpParams.egtpAssoc[duId-1].currTunnelId++;
+        gTP_TEID.buf[3] = cuCb.cuCfgParams.egtpParams.currTunnelId++;
    }
 
    ulTnlInfo->teId[0] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[0];
@@ -10504,7 +10604,6 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
    CuUeCb     *ueCb = (CuUeCb *)cuUeCb;
    F1AP_PDU_t *f1apMsg = NULLP;
    UEContextModificationRequest_t *ueContextModifyReq = NULLP;
-   action =RESTART_DATA_TX;
    asn_enc_rval_t         encRetVal;
    DU_LOG("\nINFO  -->  F1AP : Building Ue context modification request\n");
    while(1)
@@ -10644,6 +10743,7 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt
             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;
@@ -10680,10 +10780,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 */
@@ -11026,13 +11131,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;
 }
 
@@ -11266,9 +11372,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);
@@ -11278,6 +11385,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;
@@ -11310,10 +11422,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, 0, NULLP)) != ROK)
+            {
+               DU_LOG("\nERROR  ->  F1AP : Failed at BuildAndSendUeContextSetupReq");
+               return RFAILED;
+            }
+         }
+      }
    }
    
    return ROK;
@@ -11396,6 +11539,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++;
                               }
                            }
@@ -11461,16 +11605,22 @@ void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg)
             {
                gnbDuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID;
                ueCb = &duDb->ueCb[gnbDuUeF1apId-1];
-               
-               for(ueIdx = 0; ueIdx < ueCb->cellCb->numUe; ueIdx++)
+               for(ueIdx = 0; ueIdx <MAX_NUM_UE; ueIdx++)
                {
-                  if((ueCb->cellCb->ueCb[ueIdx]->gnbCuUeF1apId == gnbCuUeF1apId) &&
-                        (ueCb->cellCb->ueCb[ueIdx]->gnbDuUeF1apId == gnbDuUeF1apId))
+                  if(ueCb->cellCb && ueCb->cellCb->ueCb[ueIdx])
                   {
-                     ueCb->cellCb->ueCb[ueIdx] = NULLP;
-                     ueCb->cellCb->numUe--;
-                     break;
-
+                     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));