From f09c6fbd0d68e9ac3eaf7b5e343b53fce78ccd6b Mon Sep 17 00:00:00 2001
From: Xue Song <xuesong@cn.fujitsu.com>
Date: Tue, 22 Dec 2020 01:29:23 +0000
Subject: [PATCH] Add RCconfig_NR_DU_F1 Initialize F1AP

---
 openair2/F1AP/f1ap_cu_task.c                  |   6 +-
 openair2/F1AP/f1ap_du_ue_context_management.c |   2 +-
 openair2/GNB_APP/gnb_app.c                    |  53 ++++++---
 openair2/GNB_APP/gnb_config.c                 | 104 +++++++++++++++++-
 openair2/GNB_APP/gnb_config.h                 |   1 +
 openair2/RRC/NR/rrc_gNB.c                     |  22 ++--
 6 files changed, 158 insertions(+), 30 deletions(-)

diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c
index 9a115a06e2c..9ff119aaf45 100644
--- a/openair2/F1AP/f1ap_cu_task.c
+++ b/openair2/F1AP/f1ap_cu_task.c
@@ -107,7 +107,11 @@ void cu_task_send_sctp_init_req(instance_t enb_id) {
   message_p->ittiMsg.sctp_init.ipv4 = 1;
   message_p->ittiMsg.sctp_init.ipv6 = 0;
   message_p->ittiMsg.sctp_init.nb_ipv4_addr = 1;
-  message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+  if (RC.nrrrc[0]->node_type == ngran_gNB_CU) {
+    message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.nrrrc[enb_id]->eth_params_s.my_addr);
+  } else{
+    message_p->ittiMsg.sctp_init.ipv4_address[0] = inet_addr(RC.rrc[enb_id]->eth_params_s.my_addr);
+  }
   /*
    * SR WARNING: ipv6 multi-homing fails sometimes for localhost.
    * * * * Disable it for now.
diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c
index b236f7fa6f6..3ac99d62dc9 100644
--- a/openair2/F1AP/f1ap_du_ue_context_management.c
+++ b/openair2/F1AP/f1ap_du_ue_context_management.c
@@ -160,7 +160,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t       instance,
     f1ap_ue_context_setup_req->rrc_container = malloc(ie->value.choice.RRCContainer.size);
     memcpy(f1ap_ue_context_setup_req->rrc_container, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size);
   } else {
-    LOG_E(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %d \n", F1AP_ProtocolIE_ID_id_RRCContainer);
+    LOG_E(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer);
   }
 
   AssertFatal(0, "check configuration, send to appropriate handler\n");
diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c
index 01d7a3b833a..a5891eca902 100644
--- a/openair2/GNB_APP/gnb_app.c
+++ b/openair2/GNB_APP/gnb_app.c
@@ -80,24 +80,34 @@ static uint32_t gNB_app_register(uint32_t gnb_id_start, uint32_t gnb_id_end)//,
 
   for (gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) {
     {
-      if(NGAP_CONF_MODE){
-        ngap_register_gnb_req_t *ngap_register_gNB; //Type Temporarily reuse
-        
-        // note:  there is an implicit relationship between the data structure and the message name 
-        msg_p = itti_alloc_new_message (TASK_GNB_APP, NGAP_REGISTER_GNB_REQ); //Message Temporarily reuse
+      if (NODE_IS_DU(RC.nrrrc[gnb_id]->node_type)) { // F1AP registration
+        // configure F1AP here for F1C
+        LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n");
+        msg_p = itti_alloc_new_message (TASK_GNB_APP, F1AP_SETUP_REQ);
+        RCconfig_DU_F1(msg_p, gnb_id);
 
-        RCconfig_NR_NG(msg_p, gnb_id);
-		
-        ngap_register_gNB = &NGAP_REGISTER_GNB_REQ(msg_p); //Message Temporarily reuse
+        LOG_I(GNB_APP,"[gNB %d] gNB_app_register via F1AP for instance %d\n", gnb_id, GNB_MODULE_ID_TO_INSTANCE(gnb_id));
+        itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
+        // configure GTPu here for F1U
+      } else {
+        if(NGAP_CONF_MODE){
+          ngap_register_gnb_req_t *ngap_register_gNB; //Type Temporarily reuse
+          
+          // note:  there is an implicit relationship between the data structure and the message name 
+          msg_p = itti_alloc_new_message (TASK_GNB_APP, NGAP_REGISTER_GNB_REQ); //Message Temporarily reuse
 
-		LOG_I(GNB_APP,"default drx %d\n",ngap_register_gNB->default_drx);
+          RCconfig_NR_NG(msg_p, gnb_id);
 
-		itti_send_msg_to_task (TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
-	  }
+          ngap_register_gNB = &NGAP_REGISTER_GNB_REQ(msg_p); //Message Temporarily reuse
 
-      if (gnb_id == 0) RCconfig_nr_gtpu();
+          LOG_I(GNB_APP,"default drx %d\n",ngap_register_gNB->default_drx);
 
-	  LOG_I(GNB_APP,"[gNB %d] gNB_app_register for instance %d\n", gnb_id, GNB_MODULE_ID_TO_INSTANCE(gnb_id));
+          itti_send_msg_to_task (TASK_NGAP, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
+        }
+        if (gnb_id == 0) RCconfig_nr_gtpu();
+      }
+
+      LOG_I(GNB_APP,"[gNB %d] gNB_app_register for instance %d\n", gnb_id, GNB_MODULE_ID_TO_INSTANCE(gnb_id));
 
       register_gnb_pending++;
     }
@@ -181,9 +191,20 @@ void *gNB_app_task(void *args_p)
   //registered_gnb = 0;
   __attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end);//, gnb_properties_p);
   } else {
-  /* Start L2L1 task */
-    msg_p = itti_alloc_new_message(TASK_GNB_APP, INITIALIZE_MESSAGE);
-    itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
+    for (gnb_id = gnb_id_start; (gnb_id < gnb_id_end) ; gnb_id++) {
+      if (!NODE_IS_DU(RC.nrrrc[gnb_id]->node_type)) {
+        /* Start L2L1 task */
+        msg_p = itti_alloc_new_message(TASK_GNB_APP, INITIALIZE_MESSAGE);
+        itti_send_msg_to_task(TASK_L2L1, INSTANCE_DEFAULT, msg_p);
+      } else {
+        // configure F1AP here for F1C
+        LOG_I(GNB_APP,"ngran_gNB_DU: Allocating ITTI message for F1AP_SETUP_REQ\n");
+        msg_p = itti_alloc_new_message (TASK_GNB_APP, F1AP_SETUP_REQ);
+        RCconfig_DU_F1(msg_p, gnb_id);
+
+        itti_send_msg_to_task (TASK_DU_F1, GNB_MODULE_ID_TO_INSTANCE(gnb_id), msg_p);
+      }
+    }
   }
 
   do {
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 98870d93392..0e0c8318fb0 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -628,10 +628,10 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
       // Note: we will have to handle the case of ngran_ng_gNB_DU
       if (macrlc_has_f1 == 0) {
         rrc->node_type = ngran_gNB;
-        LOG_I(RRC,"Setting node_type to ngran_eNB\n");
+        LOG_I(NR_RRC,"Setting node_type to ngran_gNB\n");
       } else {
         rrc->node_type = ngran_gNB_DU;
-        LOG_I(RRC,"Setting node_type to ngran_eNB_DU\n");
+        LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n");
       }
     }
 
@@ -1270,4 +1270,104 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) {
   return 0;
 }
 
+int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i) {
+  int k;
+  paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
+  paramdef_t GNBParams[]  = GNBPARAMS_DESC;
+  paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
+  config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
+  int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
+  AssertFatal (i < num_gnbs,
+               "Failed to parse config file no %uth element in %s \n",i, GNB_CONFIG_STRING_ACTIVE_GNBS);
 
+  if (num_gnbs > 0) {
+    // Output a list of all eNBs.
+    config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
+    AssertFatal(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr != NULL,
+                "gNB id %u is not defined in configuration file\n",i);
+    F1AP_SETUP_REQ (msg_p).num_cells_available = 0;
+
+    for (k=0; k <num_gnbs ; k++) {
+      if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[k], *(GNBParamList.paramarray[i][GNB_GNB_NAME_IDX].strptr)) == 0) {
+        char aprefix[MAX_OPTNAME_SIZE*2 + 8];
+        sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
+        paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
+        paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
+        /* map parameter checking array instances to parameter definition array instances */
+        checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
+
+        for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
+          PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
+
+        config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
+        paramdef_t SCTPParams[]  = SCTPPARAMS_DESC;
+        F1AP_SETUP_REQ (msg_p).num_cells_available++;
+        F1AP_SETUP_REQ (msg_p).gNB_DU_id        = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr);
+        LOG_I(GNB_APP,"F1AP: gNB_DU_id[%d] %ld\n",k,F1AP_SETUP_REQ (msg_p).gNB_DU_id);
+        F1AP_SETUP_REQ (msg_p).gNB_DU_name      = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
+        LOG_I(GNB_APP,"F1AP: gNB_DU_name[%d] %s\n",k,F1AP_SETUP_REQ (msg_p).gNB_DU_name);
+        F1AP_SETUP_REQ (msg_p).tac[k]              = *GNBParamList.paramarray[i][GNB_TRACKING_AREA_CODE_IDX].uptr;
+        LOG_I(GNB_APP,"F1AP: tac[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).tac[k]);
+        F1AP_SETUP_REQ (msg_p).mcc[k]              = *PLMNParamList.paramarray[0][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
+        LOG_I(GNB_APP,"F1AP: mcc[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).mcc[k]);
+        F1AP_SETUP_REQ (msg_p).mnc[k]              = *PLMNParamList.paramarray[0][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
+        LOG_I(GNB_APP,"F1AP: mnc[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).mnc[k]);
+        F1AP_SETUP_REQ (msg_p).mnc_digit_length[k] = *PLMNParamList.paramarray[0][GNB_MNC_DIGIT_LENGTH].u8ptr;
+        LOG_I(GNB_APP,"F1AP: mnc_digit_length[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).mnc_digit_length[k]);
+        AssertFatal((F1AP_SETUP_REQ (msg_p).mnc_digit_length[k] == 2) ||
+                    (F1AP_SETUP_REQ (msg_p).mnc_digit_length[k] == 3),
+                    "BAD MNC DIGIT LENGTH %d",
+                    F1AP_SETUP_REQ (msg_p).mnc_digit_length[k]);
+        F1AP_SETUP_REQ (msg_p).nr_cellid[k] = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
+        LOG_I(GNB_APP,"F1AP: nr_cellid[%d] %ld\n",k,F1AP_SETUP_REQ (msg_p).nr_cellid[k]);
+        LOG_I(GNB_APP,"F1AP: CU_ip4_address in DU %s\n",RC.nrmac[k]->eth_params_n.remote_addr);
+        LOG_I(GNB_APP,"FIAP: CU_ip4_address in DU %p, strlen %d\n",F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4_address,(int)strlen(RC.nrmac[k]->eth_params_n.remote_addr));
+        F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv6 = 0;
+        F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4 = 1;
+        //strcpy(F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv6_address, "");
+        strcpy(F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4_address, RC.nrmac[k]->eth_params_n.remote_addr);
+        LOG_I(GNB_APP,"F1AP: DU_ip4_address in DU %s\n",RC.nrmac[k]->eth_params_n.my_addr);
+        LOG_I(GNB_APP,"FIAP: DU_ip4_address in DU %p, strlen %d\n",F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4_address,(int)strlen(RC.nrmac[k]->eth_params_n.my_addr));
+        F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv6 = 0;
+        F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4 = 1;
+        //strcpy(F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv6_address, "");
+        strcpy(F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4_address, RC.nrmac[k]->eth_params_n.my_addr);
+        //strcpy(F1AP_SETUP_REQ (msg_p).CU_ip_address[l].ipv6_address,*(F1ParamList.paramarray[l][ENB_CU_IPV6_ADDRESS_IDX].strptr));
+        sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_SCTP_CONFIG);
+        config_get(SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
+        F1AP_SETUP_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr);
+        F1AP_SETUP_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr);
+        gNB_RRC_INST *rrc = RC.nrrrc[k];
+        // wait until RRC cell information is configured
+        // int cell_info_configured=0;
+
+        // do {
+        //   LOG_I(GNB_APP,"ngran_gNB_DU: Waiting for basic cell configuration\n");
+        //   usleep(100000);
+        //   pthread_mutex_lock(&rrc->cell_info_mutex);
+        //   cell_info_configured = rrc->cell_info_configured;
+        //   pthread_mutex_unlock(&rrc->cell_info_mutex);
+        // } while (cell_info_configured ==0);
+
+        // rrc->configuration.mcc[0] = F1AP_SETUP_REQ (msg_p).mcc[k];
+        // rrc->configuration.mnc[0] = F1AP_SETUP_REQ (msg_p).mnc[k];
+        // rrc->configuration.tac    = F1AP_SETUP_REQ (msg_p).tac[k];
+        rrc->nr_cellid = F1AP_SETUP_REQ (msg_p).nr_cellid[k];
+        // F1AP_SETUP_REQ (msg_p).nr_pci[k]    = rrc->carrier.physCellId;
+        F1AP_SETUP_REQ (msg_p).num_ssi[k] = 0;
+
+        LOG_I(GNB_APP,"ngran_DU: Configuring Cell %d for TDD\n",k);
+        F1AP_SETUP_REQ (msg_p).fdd_flag = 0;
+
+        F1AP_SETUP_REQ (msg_p).measurement_timing_information[k]             = "0";
+        F1AP_SETUP_REQ (msg_p).ranac[k]                                      = 0;
+        F1AP_SETUP_REQ (msg_p).mib[k]                                        = rrc->carrier.MIB;
+        F1AP_SETUP_REQ (msg_p).sib1[k]                                       = rrc->carrier.SIB1;
+        F1AP_SETUP_REQ (msg_p).mib_length[k]                                 = rrc->carrier.sizeof_MIB;
+        F1AP_SETUP_REQ (msg_p).sib1_length[k]                                = rrc->carrier.sizeof_SIB1;
+        break;
+      }
+    }
+  }
+  return 0;
+}
diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h
index 0d965171ef0..a86a9b5e07a 100644
--- a/openair2/GNB_APP/gnb_config.h
+++ b/openair2/GNB_APP/gnb_config.h
@@ -105,6 +105,7 @@ extern void NRRCConfig(void);
 void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc);
 int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i);
 int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i);
+int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i);
 
 #endif /* GNB_CONFIG_H_ */
 /** @} */
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index d3ba2795ead..8a09359c653 100644
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -214,16 +214,18 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration
   rrc->carrier.sizeof_MIB      = do_MIB_NR(rrc,0);
   rrc->carrier.sizeof_SIB1      = do_SIB1_NR(&rrc->carrier,configuration);
   LOG_I(NR_RRC,"Done init_NR_SI\n");
-  rrc_mac_config_req_gNB(rrc->module_id,
-                         rrc->carrier.ssb_SubcarrierOffset,
-                         rrc->carrier.pdsch_AntennaPorts,
-                         rrc->carrier.pusch_TargetSNRx10,
-                         rrc->carrier.pucch_TargetSNRx10,
-                         (NR_ServingCellConfigCommon_t *)rrc->carrier.servingcellconfigcommon,
-                         0,
-                         0, // WIP hardcoded rnti
-                         (NR_CellGroupConfig_t *)NULL
-                        );
+  if (!NODE_IS_CU(RC.nrrrc[0]->node_type)){
+    rrc_mac_config_req_gNB(rrc->module_id,
+                          rrc->carrier.ssb_SubcarrierOffset,
+                          rrc->carrier.pdsch_AntennaPorts,
+                          rrc->carrier.pusch_TargetSNRx10,
+                          rrc->carrier.pucch_TargetSNRx10,
+                          (NR_ServingCellConfigCommon_t *)rrc->carrier.servingcellconfigcommon,
+                          0,
+                          0, // WIP hardcoded rnti
+                          (NR_CellGroupConfig_t *)NULL
+                          );
+  }
 
   if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) {
     // This is for phytest only, emulate first X2 message if uecap.raw file is present
-- 
GitLab