From 67f04d828a13114c4d0613b4a914be0e1b560be4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Apr 2025 13:13:57 +0200 Subject: [PATCH] Implement UE context addition in CU through F1 in do-ra/phy-test Add functionality to trigger the addition of a new RRC UE context (in the CU) for NSA modes, using F1. This commit makes do-ra and phy-test modes work. "True" NSA will work in the next commit, which also sends the X2 addition request answer message. --- openair2/LAYER2/NR_MAC_gNB/main.c | 22 --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 26 --- openair2/RRC/NR/MESSAGES/asn1_msg.h | 5 - openair2/RRC/NR/nr_rrc_proto.h | 5 +- openair2/RRC/NR/rrc_gNB.c | 39 +--- openair2/RRC/NR/rrc_gNB_du.c | 4 + openair2/RRC/NR/rrc_gNB_internode.c | 38 ---- openair2/RRC/NR/rrc_gNB_nsa.c | 288 ++++++++++++---------------- 8 files changed, 132 insertions(+), 295 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 1ca1da1dc2..3137ce0902 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -312,28 +312,6 @@ void mac_top_init_gNB(ngran_node_t node_type, // These should be out of here later if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init(); - - if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) { - // get default noS1 configuration - NR_RadioBearerConfig_t *rbconfig = NULL; - NR_RLC_BearerConfig_t *rlc_rbconfig = NULL; - fill_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig); - - /* Note! previously, in nr_DRB_preconfiguration(), we passed ENB_FLAG_NO - * if ENB_NAS_USE_TUN was *not* set. It seems to me that we could not set - * this flag anywhere in the code, hence we would always configure PDCP - * with ENB_FLAG_NO in nr_DRB_preconfiguration(). This makes sense for - * noS1, because the result of passing ENB_FLAG_NO to PDCP is that PDCP - * will output the packets at a local interface, which is in line with - * the noS1 mode. Hence, below, we simply hardcode ENB_FLAG_NO */ - // setup PDCP, RLC - nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0}; - nr_pdcp_add_drbs(ENB_FLAG_NO, 0x1234, rbconfig->drb_ToAddModList, &null_security_parameters); - - // free memory - free_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig); - } - } else { RC.nrmac = NULL; } diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 131b2694b6..586e2e7628 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -425,32 +425,6 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, return rbconfig; } -void fill_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig) -{ - /* the EPS bearer ID is arbitrary; the rb_id is 1/the first DRB, it needs to - * match the one in get_DRB_RLC_BearerConfig(). No ciphering is to be - * configured */ - *rbconfig = get_default_rbconfig(10, 1, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master); - AssertFatal(*rbconfig != NULL, "get_default_rbconfig() failed\n"); - /* LCID is 4 because the RLC layer requires it to be 3+rb_id; the rb_id 1 is - * common with get_default_rbconfig() (first RB). We pre-configure RLC UM - * Bi-directional, priority is 1 */ - *rlc_rbconfig = get_DRB_RLC_BearerConfig(4, 1, NR_RLC_Config_PR_um_Bi_Directional, 1); - AssertFatal(*rlc_rbconfig != NULL, "get_DRB_RLC_BearerConfig() failed\n"); -} - -void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig) -{ - ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig, *rbconfig); - *rbconfig = NULL; - if (rlc_rbconfig != NULL) { - ASN_STRUCT_FREE(asn_DEF_NR_RLC_BearerConfig, *rlc_rbconfig); - *rlc_rbconfig = NULL; - } -} - //------------------------------------------------------------------------------ int do_RRCSetup(uint8_t *const buffer, size_t buffer_size, diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 3d09a65bd0..344659afbb 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -80,11 +80,6 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, e_NR_CipheringAlgorithm ciphering_algorithm, e_NR_SecurityConfig__keyToUse key_to_use); -void fill_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig); -void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig); - int do_RRCSetup(uint8_t *const buffer, size_t buffer_size, const uint8_t transaction_id, diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index dc5e77bbc5..dbe1202e8c 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -41,9 +41,8 @@ #define NR_MAX_SUPPORTED_DL_LAYERS 4 -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t * cg_config_info); - -void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m); +void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m); +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp); void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index c8cec12375..aecf702f8d 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -255,41 +255,13 @@ void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *c RB_INIT(&rrc->cuups); RB_INIT(&rrc->dus); rrc->configuration = *configuration; - - if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { - AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n"); - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc); - LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p); - if (!NODE_IS_CU(rrc->node_type)) { - rrc_add_nsa_user(rrc,ue_context_p,NULL); - } - } } static void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m) { - struct NR_CG_ConfigInfo *cg_configinfo = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CG_ConfigInfo, - (void **)&cg_configinfo, - (uint8_t *)m->rrc_buffer, - (int) m->rrc_buffer_size);//m->rrc_buffer_size); - gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP]; - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"NR_UL_DCCH_MESSAGE decode error\n"); - // free the memory - SEQUENCE_free(&asn_DEF_NR_CG_ConfigInfo, cg_configinfo, 1); - return; - } - - xer_fprint(stdout,&asn_DEF_NR_CG_ConfigInfo, cg_configinfo); - // recreate enough of X2 EN-DC Container - AssertFatal(cg_configinfo->criticalExtensions.choice.c1->present == NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo, - "ueCapabilityInformation not present\n"); - parse_CG_ConfigInfo(rrc,cg_configinfo,m); - LOG_I(NR_RRC, "Successfully parsed CG_ConfigInfo of size %zu bits. (%zu bytes)\n", - dec_rval.consumed, (dec_rval.consumed +7/8)); + gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP]; + AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "NSA, phy_test, and do_ra only work in monolithic\n"); + rrc_add_nsa_user(rrc, m); } //----------------------------------------------------------------------------- @@ -2183,6 +2155,11 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); + if (!IS_SA_MODE(get_softmodem_params())) { + rrc_add_nsa_user_resp(rrc, UE, resp); + return; + } + if (resp->drbs_to_be_setup_length > 0) { int num_drb = get_number_active_drbs(UE); DevAssert(num_drb == 0 || num_drb == resp->drbs_to_be_setup_length); diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index d6e025309a..aff74fc984 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -437,6 +437,10 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (rrc->node_name != NULL) resp.gNB_CU_name = strdup(rrc->node_name); rrc->mac_rrc.f1_setup_response(assoc_id, &resp); + + /* we need to setup one default UE for phy-test and do-ra modes in the MAC */ + if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) + rrc_add_nsa_user(rrc, NULL); } static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) diff --git a/openair2/RRC/NR/rrc_gNB_internode.c b/openair2/RRC/NR/rrc_gNB_internode.c index 843eaca250..0fa7b92a90 100644 --- a/openair2/RRC/NR/rrc_gNB_internode.c +++ b/openair2/RRC/NR/rrc_gNB_internode.c @@ -46,44 +46,6 @@ #include "uper_encoder.h" #include "x2ap_messages_types.h" -int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m) { - if (CG_ConfigInfo->criticalExtensions.present == NR_CG_ConfigInfo__criticalExtensions_PR_c1) { - if (CG_ConfigInfo->criticalExtensions.choice.c1) { - if (CG_ConfigInfo->criticalExtensions.choice.c1->present == NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo) { - NR_CG_ConfigInfo_IEs_t *cg_ConfigInfo = CG_ConfigInfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo; - - if (cg_ConfigInfo->ue_CapabilityInfo) { - // Decode UE-CapabilityRAT-ContainerList - NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList=NULL; - UE_CapabilityRAT_ContainerList = calloc(1,sizeof(NR_UE_CapabilityRAT_ContainerList_t)); - asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_NR_UE_CapabilityRAT_ContainerList, - (void **)&UE_CapabilityRAT_ContainerList, - cg_ConfigInfo->ue_CapabilityInfo->buf, - cg_ConfigInfo->ue_CapabilityInfo->size, 0, 0); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"[InterNode] Failed to decode NR_UE_CapabilityRAT_ContainerList (%zu bits), size of OCTET_STRING %lu\n", - dec_rval.consumed, cg_ConfigInfo->ue_CapabilityInfo->size); - } - - rrc_parse_ue_capabilities(rrc,UE_CapabilityRAT_ContainerList, m,cg_ConfigInfo); - } - - if (cg_ConfigInfo->candidateCellInfoListMN) AssertFatal(1==0,"Can't handle candidateCellInfoListMN yet\n"); - } else AssertFatal(1==0,"c1 extension is not cg_ConfigInfo, returning\n"); - } else { - LOG_E(RRC,"c1 extension not found, returning\n"); - return(-1); - } - } else { - LOG_E(RRC,"Ignoring unknown CG_ConfigInfo extensions\n"); - return(-1); - } - - return(0); -} - NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig) { NR_CG_Config_t *cg_Config = calloc(1, sizeof(*cg_Config)); diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index eaab13796f..1248176535 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -61,6 +61,7 @@ #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "openair3/SECU/key_nas_deriver.h" +#include "rrc_gNB_du.h" #include "rlc.h" #include "s1ap_messages_types.h" #include "tree.h" @@ -70,114 +71,79 @@ #include "xer_decoder.h" #include "xer_encoder.h" -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) +// In case of phy-test and do-ra mode, read UE capabilities directly from file +// and put it into a CG-ConfigInfo field +static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) { - OCTET_STRING_t *ueCapabilityRAT_Container_nr=NULL; - OCTET_STRING_t *ueCapabilityRAT_Container_MRDC=NULL; - asn_dec_rval_t dec_rval; - int list_size=0; + NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); + cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; + cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); + cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; + NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); + cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; - AssertFatal(UE_CapabilityRAT_ContainerList!=NULL,"UE_CapabilityRAT_ContainerList is null\n"); - AssertFatal((list_size=UE_CapabilityRAT_ContainerList->list.count) >= 2, "UE_CapabilityRAT_ContainerList->list.size %d < 2\n",UE_CapabilityRAT_ContainerList->list.count); + if (uecap_file != NULL) { + LOG_I(NR_RRC, "creating CG-ConfigInfo from UE capability file %s\n", uecap_file); - for (int i=0; ilist.array[i]->rat_Type == NR_RAT_Type_nr) ueCapabilityRAT_Container_nr = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; - else if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_eutra_nr) ueCapabilityRAT_Container_MRDC = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; - } - - // decode and store capabilities - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc); - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - - if (ueCapabilityRAT_Container_nr != NULL) { - dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_NR_Capability, (void **)&UE->UE_Capability_nr, ueCapabilityRAT_Container_nr->buf, ueCapabilityRAT_Container_nr->size, 0, 0); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(RRC, "Failed to decode UE NR capabilities (%zu bytes) container size %lu\n", dec_rval.consumed,ueCapabilityRAT_Container_nr->size); - ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - UE->UE_Capability_nr = 0; - AssertFatal(1==0,"exiting\n"); + FILE *f = fopen(uecap_file, "r"); + if (!f) { + LOG_E(NR_RRC, "cannot open file %s, cannot read UE capabilities\n", uecap_file); + return 0; } - } - - if (ueCapabilityRAT_Container_MRDC != NULL) { - dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_MRDC_Capability, (void **)&UE->UE_Capability_MRDC, ueCapabilityRAT_Container_MRDC->buf, ueCapabilityRAT_Container_MRDC->size, 0, 0); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(RRC, "Failed to decode UE MRDC capabilities (%zu bytes)\n", dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - UE->UE_Capability_MRDC = 0; - AssertFatal(1==0,"exiting\n"); + char UE_NR_Capability_xer[65536]; + size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); + fclose(f); + if (size == 0 || size == sizeof UE_NR_Capability_xer) { + LOG_E(NR_RRC, "UE Capabilities XER file %s could not be read (read %ld bytes)\n", uecap_file, size); + return 0; } + NR_UE_NR_Capability_t *cap = calloc_or_fail(1, sizeof(*cap)); + asn_dec_rval_t dec_rval = xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&cap, UE_NR_Capability_xer, size); + DevAssert(dec_rval.code == RC_OK); + //xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, cap); + + OCTET_STRING_t *os_cap = calloc_or_fail(1, sizeof(*os_cap)); + os_cap->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&os_cap->buf); + cgci_ies->ue_CapabilityInfo = os_cap; } - // dump ue_capabilities - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_nr != NULL ) { - xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - } - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_MRDC != NULL ) { - xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - } - LOG_A(NR_RRC, "Successfully decoded UE NR capabilities (NR and MRDC)\n"); - - AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n"); - LOG_I(NR_RRC,"Adding new NSA user (%p)\n",ue_context_p); - rrc_add_nsa_user(rrc,ue_context_p, m); + //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); + asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); + DevAssert(rval.encoded > 0); + return (rval.encoded + 7) >> 3; } /* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */ RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries, rrc_gNB_compare_ue_rnti_id); -void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m) +void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m) { AssertFatal(!IS_SA_MODE(get_softmodem_params()), "%s() cannot be called in SA mode, it is intrinsically for NSA\n", __func__); - // generate nr-Config-r15 containers for LTE RRC : inside message for X2 EN-DC (CG-Config Message from 38.331) - const nr_mac_config_t *configuration = &RC.nrmac[0]->radio_config; - MessageDef *msg; - msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); - gtpv1u_enb_create_tunnel_req_t create_tunnel_req; - gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; - protocol_ctxt_t ctxt={0}; - nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; - int i; + AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "NSA, phy_test and do_ra only work in monolithic\n"); + + sctp_assoc_t assoc_id = -1; /* integrated DU, hardcoded: if multiple we would not know what to do? */ + /* all the 0 are DU-related info that we will fill later, see rrc_add_nsa_user_resp() below */ + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_create_ue_context(assoc_id, 0, rrc, 0, 0); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - // In case of phy-test and do-ra mode, read UE capabilities directly from file - if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { - NR_UE_NR_Capability_t* UE_Capability_nr = NULL; - char UE_NR_Capability_xer[65536]; - FILE *f = NULL; - if (uecap_file) - f = fopen(uecap_file, "r"); - if (f) { - size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); - if (size == 0 || size == sizeof UE_NR_Capability_xer) - LOG_E(NR_RRC,"UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size); - else { - UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); - asn_dec_rval_t dec_rval = xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&UE_Capability_nr, UE_NR_Capability_xer, size); - assert(dec_rval.code == RC_OK); - xer_fprint(stdout,&asn_DEF_NR_UE_NR_Capability,(void *)UE_Capability_nr); - } - fclose(f); - } - else - LOG_E(NR_RRC,"Could not open UE Capabilities input file. Not handling OAI UE Capabilities.\n"); - UE->UE_Capability_nr = UE_Capability_nr; - } + nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; - // NR RRCReconfiguration + uint8_t tmp[1024]; + uint8_t *cgci_buf = NULL; + uint32_t cgci_len = 0; if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { + DevAssert(m == NULL); UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master); + cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); + DevAssert(cgci_len > 0); + cgci_buf = tmp; } else { + DevAssert(m != NULL); + cgci_buf = m->rrc_buffer; + cgci_len = m->rrc_buffer_size; + /* TODO: handle more than one bearer */ - if (m == NULL) { - LOG_E(RRC, "fatal: m==NULL\n"); - exit(1); - } if (m->nb_e_rabs_tobeadded != 1) { LOG_E(RRC, "fatal: m->nb_e_rabs_tobeadded = %d, should be 1\n", m->nb_e_rabs_tobeadded); exit(1); @@ -195,7 +161,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a */ /* preset nea0 as fallback */ UE->ciphering_algorithm = 0; - for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) { + for (int i = 0; i < rrc->security.ciphering_algorithms_count; i++) { int nea_mask[4] = { 0, 0x8000, /* nea1 */ @@ -253,24 +219,10 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a UE->rb_config = get_default_rbconfig(m->e_rabs_tobeadded[0].e_rab_id, m->e_rabs_tobeadded[0].drb_ID, cipher_algo, NR_SecurityConfig__keyToUse_secondary); } - NR_ServingCellConfig_t *scc = RC.nrmac[0]->common_channels[0].pre_ServingCellConfig; - // The MAC has the ServingCellConfigCommon; the below code is incorrect: the - // CU should send a UE Context Setup Request to request the creating of the - // MAC Context - NR_ServingCellConfigCommon_t *sccc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; - NR_CellGroupConfig_t *secondaryCellGroup = - get_default_secondaryCellGroup(sccc, scc, UE->UE_Capability_nr, 1, 1, configuration, ue_context_p->ue_context.rrc_ue_id); - AssertFatal(secondaryCellGroup != NULL, "out of memory\n"); - - NR_RRCReconfiguration_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_t)); - reconfig->rrc_TransactionIdentifier = 0; - reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; - reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(secondaryCellGroup); - UE->rnti = secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; - - NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config); - if(m!=NULL) { + + gtpv1u_enb_create_tunnel_req_t create_tunnel_req = {0}; + gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp = {0}; if (m->nb_e_rabs_tobeadded>0) { for (int i=0; inb_e_rabs_tobeadded; i++) { // Add the new E-RABs at the corresponding rrc ue context of the gNB @@ -295,7 +247,6 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a create_tunnel_req.rnti = ue_context_p->ue_context.rrc_ue_id; create_tunnel_req.num_tunnels = m->nb_e_rabs_tobeadded; RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[rrc->module_id]->rrc_ue_head, ue_context_p); - memset(&create_tunnel_resp, 0, sizeof(create_tunnel_resp)); if (!IS_SOFTMODEM_NOS1) { gtpv1u_create_s1u_tunnel(rrc->module_id, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb); DevAssert(create_tunnel_resp.num_tunnels == 1); @@ -303,6 +254,67 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a UE->nsa_gtp_addrs[0] = create_tunnel_resp.enb_addr; UE->nsa_gtp_ebi[0] = create_tunnel_resp.eps_bearer_id[0]; } + } + } + + DevAssert(UE->rb_config != NULL); + nr_pdcp_add_drbs(GNB_FLAG_YES, + UE->rrc_ue_id, + UE->rb_config->drb_ToAddModList, + &security_parameters); + + cu_to_du_rrc_information_t cu2du = { + .cG_ConfigInfo = cgci_buf, + .cG_ConfigInfo_length = cgci_len, + }; + /* assumption: only a single bearer, see above */ + NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList; + AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count); + f1ap_drb_to_be_setup_t drbs = { + .drb_id = rb_list->list.array[0]->drb_Identity, + .rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now + // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, + .up_ul_tnl_length = 1, + }; + f1ap_ue_context_setup_t req = { + .gNB_CU_ue_id = UE->rrc_ue_id, + .gNB_DU_ue_id = 0xffffffff, /* not known yet */ + .plmn.mcc = rrc->configuration.plmn[0].mcc, + .plmn.mnc = rrc->configuration.plmn[0].mnc, + .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, + .drbs_to_be_setup_length = 1, + .drbs_to_be_setup = &drbs, + .cu_to_du_rrc_information = &cu2du, + }; + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req); +} + +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp) +{ + DevAssert(resp->crnti != NULL); + /* we did not fill any DU-related ID info in rrc_add_nsa_user() */ + UE->rnti = *resp->crnti; + DevAssert(cu_exists_f1_ue_data(UE->rrc_ue_id)); + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); + ue_data.secondary_ue = resp->gNB_DU_ue_id; + bool success = cu_update_f1_ue_data(UE->rrc_ue_id, &ue_data); + DevAssert(success); + + NR_RRCReconfiguration_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_t)); + reconfig->rrc_TransactionIdentifier = 0; + reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; + reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(UE->masterCellGroup); + + /*NR_CG_Config_t *CG_Config =*/ generate_CG_Config(reconfig, UE->rb_config); + + + /* + MessageDef *msg; + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).nb_e_rabs_admitted_tobeadded = m->nb_e_rabs_tobeadded; X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).target_assoc_id = m->target_assoc_id; @@ -343,72 +355,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a sizeof(X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer)); X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding - } + */ - // below we configure the stack. In SA, we fully adopted F1, meaning that - // layers use different IDs (MAC/RLC use RNTI as DU UE ID, above use NGAP ID - // as CU UE ID. - uint32_t du_ue_id = ue_context_p->ue_context.rnti; - uint32_t rrc_ue_id = ue_context_p->ue_context.rrc_ue_id; - f1_ue_data_t du_ue_data = {.secondary_ue = rrc_ue_id}; - bool success = du_add_f1_ue_data(du_ue_id, &du_ue_data); - DevAssert(success); - f1_ue_data_t cu_ue_data = {.secondary_ue = du_ue_id}; - success = cu_add_f1_ue_data(rrc_ue_id, &cu_ue_data); - DevAssert(success); - LOG_I(RRC, "Assign CU UE ID %d and DU UE ID %d to UE RNTI %04x\n", rrc_ue_id, du_ue_id, ue_context_p->ue_context.rnti); - - // configure MAC and RLC - bool ret = false; - if (get_softmodem_params()->phy_test) { - // phytest mode: we don't set up RA, etc - ret = nr_mac_add_test_ue(RC.nrmac[rrc->module_id], du_ue_id, secondaryCellGroup); - } else { - DevAssert(secondaryCellGroup->spCellConfig - && secondaryCellGroup->spCellConfig->reconfigurationWithSync - && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated - && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra); - gNB_MAC_INST *nrmac = RC.nrmac[rrc->module_id]; - NR_SCHED_LOCK(&nrmac->sched_lock); - NR_UE_info_t *UE_info = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, UE->rnti, secondaryCellGroup); - AssertFatal(UE_info != NULL, "cannot create UE context: list is full?\n"); - if (add_new_UE_RA(nrmac, UE_info)) { - ret = true; - nr_mac_prepare_ra_ue(nrmac, UE_info); - } else { - delete_nr_ue_data(UE_info, /* not used */ NULL, &nrmac->UE_info.uid_allocator); - } - NR_SCHED_UNLOCK(&nrmac->sched_lock); - } - AssertFatal(ret, "cannot add NSA UE in MAC, aborting\n"); - - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rrc_ue_id, 0, 0, rrc->module_id); - LOG_W(RRC, - "Calling RRC PDCP/RLC ASN1 request functions for protocol context %p with module_id %d, rnti %lx, frame %d, subframe %d eNB_index %d \n", - &ctxt, - ctxt.module_id, - ctxt.rntiMaybeUEid, - ctxt.frame, - ctxt.subframe, - ctxt.eNB_index); - - nr_pdcp_add_drbs(ctxt.enb_flag, - rrc_ue_id, - ue_context_p->ue_context.rb_config->drb_ToAddModList, - &security_parameters); - - ctxt.rntiMaybeUEid = du_ue_id; - // assume only a single bearer - const NR_DRB_ToAddModList_t *drb_list = ue_context_p->ue_context.rb_config->drb_ToAddModList; - DevAssert(drb_list->list.count == 1); - const NR_DRB_ToAddMod_t *drb = drb_list->list.array[0]; - const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list = secondaryCellGroup->rlc_BearerToAddModList; - const NR_RLC_BearerConfig_t *bearer = bearer_list->list.array[0]; - DevAssert(bearer_list->list.count == 1); - DevAssert(drb->drb_Identity == bearer->servedRadioBearer->choice.drb_Identity); - nr_rlc_add_drb(ctxt.rntiMaybeUEid, drb->drb_Identity, bearer); - - LOG_D(RRC, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %lx\n", __FUNCTION__, __LINE__, ctxt.rntiMaybeUEid); } void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) {