mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Fix handling of selected PLMN in NGAP
selectedPLMN-Identity IE in RRCSetupComplete is an Index (long) of the PLMN selected by the UE from the plmn-IdentityInfoList (SIB1) (see 3GPP TS 38.331) while Selected PLMN Identity in NGAP INITIAL UE MESSAGE Indicates the selected PLMN id for the non-3GPP access (PLMN Identity ID carrying MNC, MCC and MNC size, 9.2.5.1 3GPP TS 38.413) The legacy code was setting Selected PLMN Identity in the latter to an ID value as the former, however in NGAP the IE to be encoded is PLMN Identity 9.3.3.5 therefore: * set plmn type plmn_id_t in ngap_nas_first_req_t * check whether received selectedPLMN-Identity is within bounds * select PLMN from gNB_RrcConfigurationReq by selectedPLMN-Identity ID note: this commit is assuming that the plmn-IdentityInfoList in SIB1 is matching the PLMN list in gNB_RrcConfigurationReq * in NGAP: store the PLMN in the NGAP UE context, no need to fetch the PLMN in the NGAP instance since the UE context already tells what PLMN was selected Closes #801
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user