diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index e54bc46d09..52cd919338 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -490,22 +490,16 @@ typedef struct ngap_deregistered_gnb_ind_s { * will be the unique identifier used between RRC and NGAP. */ typedef struct ngap_nas_first_req_s { - /* UE id for initial connection to NGAP */ + // RAN UE NGAP ID (mandatory) uint32_t gNB_ue_ngap_id; - - /* the chosen PLMN identity as index, see TS 36.331 6.2.2 RRC Connection - * Setup Complete. This index here is zero-based, unlike the standard! */ - int selected_plmn_identity; - - /* Establishment cause as sent by UE */ + /* PLMN: Selected PLMN Identity (optional) + * User Location Information (mandatory) */ + plmn_id_t plmn; + // RRC Establishment Cause (mandatory) ngap_rrc_establishment_cause_t establishment_cause; - - /* NAS PDU */ + // NAS-PDU (mandatory) byte_array_t nas_pdu; - - /* If this flag is set NGAP layer is expecting the GUAMI. If = 0, - * the temporary s-tmsi is used. - */ + // UE identity: 5G-S-TMSI, GUAMI ngap_ue_identity_t ue_identity; } ngap_nas_first_req_t; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 879141144e..5dc101411c 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -149,12 +149,15 @@ void nr_rrc_pdcp_config_security(gNB_RRC_UE_t *UE, bool enable_ciphering) } /** @brief Process AMF Identifier and fill GUAMI struct members */ -static nr_guami_t get_guami(const uint32_t amf_Id) +static nr_guami_t get_guami(const uint32_t amf_Id, const plmn_id_t plmn) { nr_guami_t guami = {0}; guami.amf_region_id = (amf_Id >> 16) & 0xff; guami.amf_set_id = (amf_Id >> 6) & 0x3ff; guami.amf_pointer = amf_Id & 0x3f; + guami.mcc = plmn.mcc; + guami.mnc = plmn.mnc; + guami.mnc_len = plmn.mnc_digit_length; return guami; } @@ -179,13 +182,19 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC // NAS-PDU req->nas_pdu = create_byte_array(rrcSetupComplete->dedicatedNAS_Message.size, rrcSetupComplete->dedicatedNAS_Message.buf); - // Selected PLMN Identity: indicates the selected PLMN id for the non-3GPP access - /* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */ - int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1; - if (selected_plmn_identity != 0) - LOG_E(NGAP, "UE %u: sent selected PLMN identity %ld, but only one PLMN supported\n", req->gNB_ue_ngap_id, rrcSetupComplete->selectedPLMN_Identity); - - req->selected_plmn_identity = 0; /* always zero because we only support one */ + /* Selected PLMN Identity (Optional) + * selectedPLMN-Identity in RRCSetupComplete: Index of the PLMN selected by the UE from the plmn-IdentityInfoList (SIB1) + * Selected PLMN Identity in INITIAL UE MESSAGE: Indicates the selected PLMN id for the non-3GPP access.*/ + if (rrcSetupComplete->selectedPLMN_Identity > rrc->configuration.num_plmn) { + LOG_E(NGAP, + "Failed to send Initial UE Message: selected PLMN (%ld) identity is out of bounds (%d)\n", + rrcSetupComplete->selectedPLMN_Identity, + rrc->configuration.num_plmn); + return; + } + int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1; // Convert 1-based PLMN Identity IE to 0-based index + req->plmn = rrc->configuration.plmn[selected_plmn_identity]; // Select from the stored list + LOG_I(NGAP, "Selected PLMN in the NG Initial UE Message: MCC %u, MNC %u\n", req->plmn.mcc, req->plmn.mnc); /* 5G-S-TMSI */ if (UE->Initialue_identity_5g_s_TMSI.presence) { @@ -204,7 +213,7 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC NR_RegisteredAMF_t *r_amf = rrcSetupComplete->registeredAMF; req->ue_identity.presenceMask |= NGAP_UE_IDENTITIES_guami; uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier); - UE->ue_guami = req->ue_identity.guami = get_guami(amf_Id); + UE->ue_guami = req->ue_identity.guami = get_guami(amf_Id, req->plmn); LOG_I(NGAP, "GUAMI in NGAP_NAS_FIRST_REQ (UE %04x): AMF Set ID %u, Region ID %u, Pointer %u\n", UE->rnti, diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index 36e9934384..7729ffa4f2 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -107,16 +107,15 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng if (amf == NULL) { if (msg->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) { const fiveg_s_tmsi_t *fgs_tmsi = &msg->ue_identity.s_tmsi; - amf = ngap_gNB_nnsf_select_amf_by_amf_setid(instance_p, msg->establishment_cause, msg->selected_plmn_identity, fgs_tmsi->amf_set_id); + amf = ngap_gNB_nnsf_select_amf_by_amf_setid(instance_p, msg->establishment_cause, msg->plmn, fgs_tmsi->amf_set_id); if (amf) { - NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN Identity index %d MCC %d MNC %d\n", + NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN MCC %d MNC %d\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id, fgs_tmsi->amf_set_id, - msg->selected_plmn_identity, - instance_p->plmn[msg->selected_plmn_identity].plmn.mcc, - instance_p->plmn[msg->selected_plmn_identity].plmn.mnc); + msg->plmn.mcc, + msg->plmn.mnc); return amf; } } @@ -125,15 +124,14 @@ static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ng // No UE identity (5G-S-TMSI or GUAMI) is present if (msg->ue_identity.presenceMask == 0) { // Select the AMF based on the selected PLMN identity received through RRCSetupComplete - amf = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, msg->establishment_cause, msg->selected_plmn_identity); + amf = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, msg->establishment_cause, msg->plmn); if (amf) { - NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n", + NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN MCC %d MNC %d\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id, - msg->selected_plmn_identity, - instance_p->plmn[msg->selected_plmn_identity].plmn.mcc, - instance_p->plmn[msg->selected_plmn_identity].plmn.mnc); + msg->plmn.mcc, + msg->plmn.mnc); return amf; } else { // Select the AMF with the highest capacity @@ -185,7 +183,7 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf ue_desc_p->amf_ref = amf; ue_desc_p->gNB_ue_ngap_id = UEfirstReq->gNB_ue_ngap_id; ue_desc_p->gNB_instance = instance_p; - ue_desc_p->selected_plmn_identity = UEfirstReq->selected_plmn_identity; + ue_desc_p->selected_plmn_identity = UEfirstReq->plmn; ngap_store_ue_context(ue_desc_p); // RAN UE NGAP ID (M) @@ -220,7 +218,7 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf 0, // Cell ID &userinfo_nr_p->nR_CGI.nRCellIdentity); - plmn_id_t *plmn = &instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn; + plmn_id_t *plmn = &ue_desc_p->selected_plmn_identity; MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->nR_CGI.pLMNIdentity); /* In case of network sharing, @@ -444,17 +442,12 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_ MACRO_GNB_ID_TO_CELL_IDENTITY(ngap_gNB_instance_p->gNB_id, 0, // Cell ID &userinfo_nr_p->nR_CGI.nRCellIdentity); - MCC_MNC_TO_TBCD(ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mcc, - ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc, - ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc_digit_length, - &userinfo_nr_p->nR_CGI.pLMNIdentity); + plmn_id_t *plmn = &ue_context_p->selected_plmn_identity; + MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->nR_CGI.pLMNIdentity); /* Set TAI */ INT24_TO_OCTET_STRING(ngap_gNB_instance_p->tac, &userinfo_nr_p->tAI.tAC); - MCC_MNC_TO_PLMNID(ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mcc, - ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc, - ngap_gNB_instance_p->plmn[ue_context_p->selected_plmn_identity].plmn.mnc_digit_length, - &userinfo_nr_p->tAI.pLMNIdentity); + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->tAI.pLMNIdentity); } if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { NGAP_ERROR("Failed to encode uplink NAS transport\n"); diff --git a/openair3/NGAP/ngap_gNB_nnsf.c b/openair3/NGAP/ngap_gNB_nnsf.c index 648d455bea..77cc7866e1 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.c +++ b/openair3/NGAP/ngap_gNB_nnsf.c @@ -86,7 +86,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, c ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, - const int selected_plmn_identity) + const plmn_id_t selected_plmn_identity) { struct ngap_gNB_amf_data_s *amf_data_p = NULL; struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL; @@ -132,8 +132,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *in /* Looking for served GUAMI PLMN Identity selected matching the one provided by the UE */ STAILQ_FOREACH(guami_p, &amf_data_p->served_guami, next) { STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { - if ((served_plmn_p->mcc == instance_p->plmn[selected_plmn_identity].plmn.mcc) - && (served_plmn_p->mnc == instance_p->plmn[selected_plmn_identity].plmn.mnc)) { + if ((served_plmn_p->mcc == selected_plmn_identity.mcc) && (served_plmn_p->mnc == selected_plmn_identity.mnc)) { break; } } @@ -155,7 +154,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *in ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, - const int selected_plmn_identity, + const plmn_id_t selected_plmn_identity, uint8_t amf_setid) { struct ngap_gNB_amf_data_s *amf_data_p = NULL; @@ -203,8 +202,7 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t * struct plmn_identity_s *served_plmn_p = NULL; STAILQ_FOREACH(served_plmn_p, &guami_p->served_plmns, next) { - if ((served_plmn_p->mcc == instance_p->plmn[selected_plmn_identity].plmn.mcc) - && (served_plmn_p->mnc == instance_p->plmn[selected_plmn_identity].plmn.mnc)) { + if ((served_plmn_p->mcc == selected_plmn_identity.mcc) && (served_plmn_p->mnc == selected_plmn_identity.mnc)) { break; } } diff --git a/openair3/NGAP/ngap_gNB_nnsf.h b/openair3/NGAP/ngap_gNB_nnsf.h index 074b163f75..8a87ecfce2 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.h +++ b/openair3/NGAP/ngap_gNB_nnsf.h @@ -38,11 +38,11 @@ ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, c ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, - const int selected_plmn_identity); + const plmn_id_t selected_plmn_identity); ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause, - const int selected_plmn_identity, + const plmn_id_t selected_plmn_identity, uint8_t amf_setid); ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p, diff --git a/openair3/NGAP/ngap_gNB_ue_context.h b/openair3/NGAP/ngap_gNB_ue_context.h index 2ca75141ef..4c0c63239f 100644 --- a/openair3/NGAP/ngap_gNB_ue_context.h +++ b/openair3/NGAP/ngap_gNB_ue_context.h @@ -72,7 +72,7 @@ typedef struct ngap_gNB_ue_context_s { /* Signaled by the UE in RRC Connection Setup Complete and used in NAS Uplink * to route NAS messages correctly. 0-based, not 1-based as in TS 36.331 * 6.2.2 RRC Connection Setup Complete! */ - int selected_plmn_identity; + plmn_id_t selected_plmn_identity; /* Reference to gNB data this UE is attached to */ ngap_gNB_instance_t *gNB_instance;