NGAP: fix PLMN/cell location for InitialUE and UplinkNAS
This commit is removing the storage of selected PLMN in NGAP UE context. We store the Serving PLMN in the RRC UE context instead. The Selected PLMN is the PLMN that the UE chose (or was directed to) for registration and it is sent in the RRCSetupComplete. This is different from the selected PLMN mentioned in the NG INITIAL UE MESSAGE for network sharing. Selected PLMN: determines which core network and AMF the UE is registered with GUAMI = Identifies the serving AMF and includes the PLMN of that AMF Serving PLMN: the PLMN that is currently serving the UE (e.g. contained in GUAMI) The AMF’s PLMN may match the selected PLMN, or not (especially in network sharing or roaming). Regardless, the UE always have a Serving PLMN. Initial UE message does not have a TAI IE per se, but TAI is a mandatory member of the mandatory UserLocationInformation CHOICE. NR CGI is also mandatory and carried inside UserLocationInformation: in network sharing, the PLMN ID in TAI takes on additional significance: RAN is shared but CN are different, so in this case PLMN in TAI is needed for the AMF route the message to the correct operator’s core. If network sharing applies (e.g., shared RAN between PLMN-A and PLMN-B): the UE or network may select PLMN-B instead, and that PLMN identity is included in the Initial UE Message’s TAI IE. Conclusion: 1) UE always sends the selected PLMN during the registration, regardless of whether it is shared or not. 2) Selected PLMN Identity is an actual IE sent in the RRCSetupComplete while in NGAP there's no Selected PLMN Identity IE, only PLMN Identity IEs in both TAI and NR CGI. It is a subtle difference. 3) The serving PLMN of the UE needs to be stored in RRC UE Context for later use in NAS procedures. e.g. at initial registration it matches the Selected PLMN 4) No need to store PLMN in NGAP UE Context, params are passed by RRC 5) TAI and NR CGI, which contain the PLMN identity, are mandatory in UserLocationInformation IE CHOICE, and should reflect current status Changes - Initial UE Message: pass UE-selected PLMN and NR cell id from RRC to NGAP - Uplink NAS Transport: use PLMN, TAC, and cell id provided by the message; - Build NR CGI from gNB ID + cell id - Store UE-selected PLMN only in RRC UE context at NAS_FIRST_REQ for later Uplink NAS, stop storing PLMN in NGAP UE context
This commit is contained in:
@@ -421,6 +421,8 @@ typedef struct ngap_nas_first_req_s {
|
||||
/* PLMN: Selected PLMN Identity (optional)
|
||||
* User Location Information (mandatory) */
|
||||
plmn_id_t plmn;
|
||||
// NR Cell ID for NR CGI (mandatory)
|
||||
uint32_t nr_cell_id;
|
||||
// RRC Establishment Cause (mandatory)
|
||||
ngap_rrc_establishment_cause_t establishment_cause;
|
||||
// NAS-PDU (mandatory)
|
||||
@@ -434,6 +436,10 @@ typedef struct ngap_uplink_nas_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
/* NAS pdu */
|
||||
byte_array_t nas_pdu;
|
||||
/* UserLocationInformation (mandatory) */
|
||||
plmn_id_t plmn; // CGI and TAI
|
||||
uint32_t nr_cell_id; // CGI
|
||||
uint32_t tac; // TAI
|
||||
} ngap_uplink_nas_t;
|
||||
|
||||
typedef struct target_cell_id_s {
|
||||
|
||||
@@ -209,6 +209,8 @@ typedef struct gNB_RRC_UE_s {
|
||||
uint64_t amf_ue_ngap_id;
|
||||
// Globally Unique AMF Identifier
|
||||
nr_guami_t ue_guami;
|
||||
// Serving PLMN of the UE
|
||||
plmn_id_t serving_plmn;
|
||||
|
||||
ngap_security_capabilities_t security_capabilities;
|
||||
//NSA block
|
||||
|
||||
@@ -223,17 +223,22 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC
|
||||
req->nas_pdu = create_byte_array(rrcSetupComplete->dedicatedNAS_Message.size, rrcSetupComplete->dedicatedNAS_Message.buf);
|
||||
|
||||
/* 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) {
|
||||
* selectedPLMN-Identity in RRCSetupComplete: Index of the PLMN selected by the UE from the plmn-IdentityInfoList (SIB1) */
|
||||
int idx = rrcSetupComplete->selectedPLMN_Identity - 1; // Convert 1-based PLMN Identity IE to 0-based index
|
||||
if (idx < 0 || idx >= 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,
|
||||
"Failed to send Initial UE Message: selected PLMN index (%d) is out of bounds [0..%d)\n",
|
||||
idx,
|
||||
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
|
||||
req->plmn = rrc->configuration.plmn[idx]; // Select from the stored list
|
||||
/* UE is connected to only one PLMN at a time: store this as the serving PLMN */
|
||||
UE->serving_plmn = req->plmn;
|
||||
|
||||
// Cell ID (NR CGI)
|
||||
req->nr_cell_id = UE->nr_cellid;
|
||||
// PLMN (NR CGI and TAI)
|
||||
plmn_id_t *p = &req->plmn;
|
||||
LOG_I(NGAP, "Selected PLMN in the NG Initial UE Message: MCC=%03d MNC=%0*d\n", p->mcc, p->mnc_digit_length, p->mnc);
|
||||
|
||||
@@ -721,6 +726,10 @@ void rrc_gNB_send_NGAP_UPLINK_NAS(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_
|
||||
NGAP_UPLINK_NAS(msg_p).gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
NGAP_UPLINK_NAS(msg_p).nas_pdu.len = nas->size;
|
||||
NGAP_UPLINK_NAS(msg_p).nas_pdu.buf = buf;
|
||||
/* Fill PLMN and location info: use serving PLMN of the UE */
|
||||
NGAP_UPLINK_NAS(msg_p).plmn = UE->serving_plmn;
|
||||
NGAP_UPLINK_NAS(msg_p).nr_cell_id = rrc->nr_cellid;
|
||||
NGAP_UPLINK_NAS(msg_p).tac = rrc->configuration.tac;
|
||||
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p);
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,6 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
.amf_ref = amf,
|
||||
.gNB_ue_ngap_id = UEfirstReq->gNB_ue_ngap_id,
|
||||
.gNB_instance = instance_p,
|
||||
.selected_plmn_identity = UEfirstReq->plmn,
|
||||
};
|
||||
|
||||
// RAN UE NGAP ID (M)
|
||||
@@ -211,16 +210,14 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR;
|
||||
asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p);
|
||||
|
||||
/* Set nRCellIdentity. default userLocationInformationNR */
|
||||
MACRO_GNB_ID_TO_CELL_IDENTITY(instance_p->gNB_id,
|
||||
0, // Cell ID
|
||||
&userinfo_nr_p->nR_CGI.nRCellIdentity);
|
||||
/* NR CGI: use gNB ID and Cell ID passed from RRC */
|
||||
MACRO_GNB_ID_TO_CELL_IDENTITY(instance_p->gNB_id, UEfirstReq->nr_cell_id, &userinfo_nr_p->nR_CGI.nRCellIdentity);
|
||||
|
||||
plmn_id_t *plmn = &ue_desc_p.selected_plmn_identity;
|
||||
/* Use UE's selected PLMN for nR-CGI (from Initial UE Message) */
|
||||
plmn_id_t *plmn = &UEfirstReq->plmn;
|
||||
MCC_MNC_TO_TBCD(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->nR_CGI.pLMNIdentity);
|
||||
|
||||
/* In case of network sharing,
|
||||
the selected PLMN is indicated by the PLMN Identity IE within the TAI IE */
|
||||
/* Set TAI - use UE's selected PLMN */
|
||||
INT24_TO_OCTET_STRING(instance_p->tac, &userinfo_nr_p->tAI.tAC);
|
||||
MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &userinfo_nr_p->tAI.pLMNIdentity);
|
||||
}
|
||||
@@ -444,17 +441,20 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_
|
||||
ie->value.choice.UserLocationInformation.present = NGAP_UserLocationInformation_PR_userLocationInformationNR;
|
||||
asn1cCalloc(ie->value.choice.UserLocationInformation.choice.userLocationInformationNR, userinfo_nr_p);
|
||||
|
||||
/* Set nRCellIdentity. default userLocationInformationNR */
|
||||
/* Set nRCellIdentity: use gNB ID and Cell ID */
|
||||
MACRO_GNB_ID_TO_CELL_IDENTITY(ngap_gNB_instance_p->gNB_id,
|
||||
0, // Cell ID
|
||||
ngap_uplink_nas_p->nr_cell_id,
|
||||
&userinfo_nr_p->nR_CGI.nRCellIdentity);
|
||||
plmn_id_t *plmn = &ue_context_p->selected_plmn_identity;
|
||||
|
||||
/* NR CGI */
|
||||
plmn_id_t *plmn = &ngap_uplink_nas_p->plmn;
|
||||
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);
|
||||
/* TAI */
|
||||
INT24_TO_OCTET_STRING(ngap_uplink_nas_p->tac, &userinfo_nr_p->tAI.tAC);
|
||||
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");
|
||||
/* Encode procedure has failed... */
|
||||
|
||||
@@ -69,11 +69,6 @@ typedef struct ngap_gNB_ue_context_s {
|
||||
/* Reference to AMF data this UE is attached to */
|
||||
struct ngap_gNB_amf_data_s *amf_ref;
|
||||
|
||||
/* 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! */
|
||||
plmn_id_t selected_plmn_identity;
|
||||
|
||||
/* Reference to gNB data this UE is attached to */
|
||||
ngap_gNB_instance_t *gNB_instance;
|
||||
} ngap_gNB_ue_context_t;
|
||||
|
||||
Reference in New Issue
Block a user