diff --git a/ci-scripts/conf_files/gNB_SA_CU.conf b/ci-scripts/conf_files/gNB_SA_CU.conf index 27b079d02694bb031456b3edcfaeaf380650c226..14bf78a43a1dad89d949b28693b3cbb875c9fdbc 100644 --- a/ci-scripts/conf_files/gNB_SA_CU.conf +++ b/ci-scripts/conf_files/gNB_SA_CU.conf @@ -182,6 +182,17 @@ gNBs = } ); + E1_INTERFACE: + ( + { + type = "cu"; + ipv4_cucp = "192.168.100.1"; + port_cucp = 25; + ipv4_cuup = "192.168.100.2"; + port_cuup = 25; + } + ) + NETWORK_INTERFACES : { diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index bb41c94d3df6a745c514ca9fe56f5a38bb14c8f1..ea1d74a3f7ad1eb8e74cd9c7f18f871da3c61f27 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -1085,6 +1085,55 @@ void cuup_task_handle_sctp_association_resp(instance_t instance, sctp_new_associ e1apCUUP_send_SETUP_REQUEST(instance); } +void cucp_task_send_sctp_init_req(instance_t instance, char *my_addr) { + LOG_I(E1AP, "E1AP_CUCP_SCTP_REQ(create socket)\n"); + MessageDef *message_p = NULL; + message_p = itti_alloc_new_message (TASK_CUCP_E1, 0, SCTP_INIT_MSG); + message_p->ittiMsg.sctp_init.port = E1AP_PORT_NUMBER; + message_p->ittiMsg.sctp_init.ppid = E1AP_SCTP_PPID; + 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(my_addr); + /* + * SR WARNING: ipv6 multi-homing fails sometimes for localhost. + * * * * Disable it for now. + */ + message_p->ittiMsg.sctp_init.nb_ipv6_addr = 0; + message_p->ittiMsg.sctp_init.ipv6_address[0] = "0:0:0:0:0:0:0:1"; + itti_send_msg_to_task(TASK_SCTP, instance, message_p); +} + +void *E1AP_CUCP_task(void *arg) { + LOG_I(E1AP, "Starting E1AP at CU CP\n"); + MessageDef *msg = NULL; + int result; + + while (1) { + itti_receive_msg(TASK_CUCP_E1, &msg); + + switch (ITTI_MSG_ID(msg)) { + case E1AP_SETUP_REQ: + LOG_I(E1AP, "CUCP Task Received E1AP_SETUP_REQ for instance %ld. Initializing SCTP listener\n", + ITTI_MSG_DESTINATION_INSTANCE(msg)); + e1ap_setup_req_t *req = &E1AP_SETUP_REQ(msg); + char *ipaddr; + if (req->CUCP_e1_ip_address.ipv4 == 0) { + LOG_E(E1AP, "No IPv4 address configured\n"); + return -1; + } + else + ipaddr = req->CUCP_e1_ip_address.ipv4_address; + cucp_task_send_sctp_init_req(0, ipaddr); + break; + + default: + LOG_E(E1AP, "Unknown message received in TASK_CUCP_E1\n"); + break; + } + } +} + void *E1AP_CUUP_task(void *arg) { LOG_I(E1AP, "Starting E1AP at CU UP\n"); @@ -1112,6 +1161,10 @@ void *E1AP_CUUP_task(void *arg) { LOG_I(E1AP, "CUUP Task Received SCTP_DATA_IND\n"); cuup_task_handle_sctp_data_ind(instance, &msg->ittiMsg.sctp_data_ind); break; + + default: + LOG_E(E1AP, "Unknown message received in TASK_CUUP_E1\n"); + break; } } } diff --git a/openair2/E1AP/e1ap_common.h b/openair2/E1AP/e1ap_common.h index d05fc15129a08dd61bc5e853b5a8835c83b6b6d2..cf61b0fbecbdda6ae84ebf1e40e94784099106c8 100644 --- a/openair2/E1AP/e1ap_common.h +++ b/openair2/E1AP/e1ap_common.h @@ -30,6 +30,9 @@ #define E1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_req #define E1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.e1ap_setup_resp +#define E1AP_PORT_NUMBER 25 +#define E1AP_SCTP_PPID 63 + typedef f1ap_net_ip_address_t e1ap_net_ip_address_t; typedef int (*e1ap_message_processing_t)( @@ -49,7 +52,6 @@ typedef struct e1ap_setup_req_s { uint64_t gNB_cu_up_id; char * gNB_cu_up_name; uint64_t transac_id; - uint64_t cn_support; int supported_plmns; PLMN_ID_t plmns[E1AP_MAX_NUM_PLMNS]; uint16_t sctp_in_streams; diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 821e2def84afca4c56a60feffaef75f987423c9c..2965a6c29b77edb03bfae40c9c7dc0dcf53dd64e 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -67,6 +67,7 @@ static void configure_nr_rrc(uint32_t gnb_id) msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ); if (RC.nrrrc[gnb_id]) { + set_node_type(); RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]); LOG_I(GNB_APP, "RRC starting with node type %d\n", RC.nrrrc[gnb_id]->node_type); @@ -200,6 +201,30 @@ void *gNB_app_task(void *args_p) LOG_E(F1AP, "Create task for F1AP CU failed\n"); AssertFatal(1==0,"exiting"); } + + if (RC.nrrrc[0]->cu_type == CPtype) { + if (itti_create_task(TASK_CUCP_E1, E1AP_CUCP_task, NULL) < 0) { + LOG_E(E1AP, "Create task for E1AP CP failed\n"); + AssertFatal(1==0, "exiting"); + } + // To initialize SCTP listener + msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ); + RCconfig_NR_CU_E1(msg_p, 0); + + itti_send_msg_to_task(TASK_CUCP_E1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); + } else if (RC.nrrrc[0]->cu_type == UPtype) { + if (itti_create_task(TASK_CUUP_E1, E1AP_CUUP_task, NULL) < 0) { + LOG_E(E1AP, "Create task for E1AP UP failed\n"); + AssertFatal(1==0, "exiting"); + } + // configure E1AP here + LOG_I(GNB_APP, "ngran_gNB_CU: Allocating ITTI message for E1AP_SETUP_REQ\n"); + msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ); + RCconfig_NR_CU_E1(msg_p, 0); + + itti_send_msg_to_task(TASK_CUUP_E1, GNB_MODULE_ID_TO_INSTANCE(0), msg_p); + } + } if (NODE_IS_DU(RC.nrrrc[0]->node_type)) { diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 25df321b3a7d024fbcc68fb6a935657e1b24f642..9ffd3e2f3aa13b4d7e8bc27276f165f3d7e9cefa 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -1166,21 +1166,13 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) { rrc->eth_params_s.my_portd = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTD_IDX].uptr); rrc->eth_params_s.remote_portd = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTD_IDX].uptr); rrc->eth_params_s.transp_preference = ETH_UDP_MODE; - rrc->node_type = ngran_gNB_CU; rrc->sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); rrc->sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); - } else { - // set to ngran_gNB for now, it will get set to ngran_gNB_DU if macrlc entity which uses F1 is present - // 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(NR_RRC,"Setting node_type to ngran_gNB\n"); - } else { - rrc->node_type = ngran_gNB_DU; - LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n"); - } } + rrc->node_type = node_type; + rrc->cu_type = cu_type; + rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr); rrc->um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr); @@ -1836,6 +1828,54 @@ int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) { return 0; } +int RCconfig_NR_CU_E1(MessageDef *msg_p, uint32_t i) { + paramdef_t GNBSParams[] = GNBSPARAMS_DESC; + paramdef_t GNBParams[] = GNBPARAMS_DESC; + paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; + paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, 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) { + 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); + config_getlist(&GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), NULL); + e1ap_setup_req_t *e1Setup = &E1AP_SETUP_REQ(msg_p); + e1setup->gNB_cu_up_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr); + + 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); + int numPLMNs = PLMNParamList.numelt; + e1Setup->supported_plmns = numPLMNs; + + for (int I = 0; I < numPLMNs; I++) { + e1Setup->plmns[I].mcc = *PLMNParamList.paramarray[I][GNB_MOBILE_COUNTRY_CODE_IDX].uptr; + e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MOBILE_NETWORK_CODE_IDX].uptr; + e1Setup->plmns[I].mnc = *PLMNParamList.paramarray[I][GNB_MNC_DIGIT_LENGTH].u8ptr; + } + + strcpy(e1Setup->CUCP_e1_ip_address.ipv4_address, GNBE1PARAMList.paramarray[0][GNB_CONFIG_E1_IPV4_ADDRESS_CUCP].strptr); + e1Setup->port_cucp = *GNBE1PARAMList.paramarray[0][GNB_CONFIG_E1_PORT_CUCP].uptr; + strcpy(e1Setup->CUUP_e1_ip_address.ipv4_address, GNBE1PARAMList.paramarray[0][GNB_CONFIG_E1_IPV4_ADDRESS_CUUP].strptr); + e1Setup->port_cuup = *GNBE1PARAMList.paramarray[0][GNB_CONFIG_E1_PORT_CUUP].uptr; + + e1Setup->cn_support = *GNBE1PARAMList.Paramarray[0][GNB_CONFIG_E1_CN_SUPPORT].uptr; + } + + return 0; +} + int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i) { int k; paramdef_t GNBSParams[] = GNBSPARAMS_DESC; @@ -2269,9 +2309,12 @@ static ngran_node_t get_node_type(void) paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0}; paramdef_t GNBParams[] = GNBPARAMS_DESC; paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0}; + paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC; + paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0}; config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL); config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL); + config_getlist( &GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), NULL); if ( MacRLC_ParamList.numelt > 0) { RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt; @@ -2282,7 +2325,8 @@ static ngran_node_t get_node_type(void) } } - if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) + if ((strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) && + (strcmp(*(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CU_TYPE_IDX].strptr), "cu") == 0)) return ngran_gNB_CU; else if (macrlc_has_f1 == 0) return ngran_gNB; diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h index 9572d16d8f4c1fce65fee032bf6752b60d6bfdb4..13197fa39e5edd3a9a448b3df4a16166cd96e39b 100644 --- a/openair2/GNB_APP/gnb_paramdef.h +++ b/openair2/GNB_APP/gnb_paramdef.h @@ -365,6 +365,32 @@ typedef enum { /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* E1 configuration section */ +#define GNB_CONFIG_STRING_E1_PARAMETERS "E1_INTERFACE" + +#define GNB_CONFIG_E1_CU_TYPE_IDX 0 +#define GNB_CONFIG_E1_IPV4_ADDRESS_CUCP 1 +#define GNB_CONFIG_E1_PORT_CUCP 2 +#define GNB_CONFIG_E1_IPV4_ADDRESS_CUUP 3 +#define GNB_CONFIG_E1_PORT_CUUP 4 +#define GNB_CONFIG_E1_CN_SUPPORT 5 + +#define GNB_CONFIG_STRING_E1_CU_TYPE "type" +#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP "ipv4_cucp" +#define GNB_CONFIG_STRING_E1_PORT_CUCP "port_cucp" +#define GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP "ipv4_cuup" +#define GNB_CONFIG_STRING_E1_PORT_CUUP "port_cuup" +#define GNB_CONFIG_STRING_E1_CN_SUPPORT "cn_support" + +#define GNBE1PARAMS_DESC { \ + {GNB_CONFIG_STRING_E1_CU_TYPE, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUCP, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_PORT_CUCP, NULL, 0, uptr :NULL, defintval:25L, TYPE_UINT, 0}, \ + {GNB_CONFIG_STRING_E1_IPV4_ADDRESS_CUUP, NULL, 0, strptr:NULL, defstrval:NULL, TYPE_STRING, 0}, \ + {GNB_CONFIG_STRING_E1_PORT_CUUP, NULL, 0, uptr :NULL, defintval:25L, TYPE_UINT, 0} \ + {GNB_CONFIG_STRING_E1_CN_SUPPORT, NULL, 0, uptr :NULL, defintval:1L, TYPE_UNIT, 0} \ +} + /* L1 configuration section names */ #define CONFIG_STRING_L1_LIST "L1s" #define CONFIG_STRING_L1_CONFIG "l1_config"