Merge remote-tracking branch 'origin/issue-801' into integration_2025_w23 (!3302)
Enhance UE identity management in Initial UE Message and other NGAP improvements This MR improves the Initial UE Message procedures by supporting simultaneous presence of both 5G-S-TMSI and GUAMI. Previously, only one identity could be used, leading to potential AMF selection failures. Now the presenceMask allows both identities. The AMF selection is prioritizing GUAMI first, then falling back to 5G-S-TMSI, and finally using PLMN or highest capacity. Also, fix handling of selected PLMN identity in NGAP. Refactoring: - Select the AMF based on (1) absence of UE Identity (2) Presence of GUAMI (3) Presence of 5G-S-TMSI - Also refactored the AMF selection logic for better readability and reliability. - Refactor and cleanup rrc_gNB_send_NGAP_NAS_FIRST_REQ - Replace ngap_pdu_t with byte_array_t - Add guami_t to ngran_types.h: refactor NGAP and RRC code to use one common GUAMI type instead of two identical ones Also: - Bugfix in ngap_gNB_handle_ng_setup_response: use correct count for PLMNSupportList Closes issue #801
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
#include "common/platform_types.h"
|
||||
#include "common/5g_platform_types.h"
|
||||
#include "s1ap_messages_types.h"
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
// Defines to access message fields.
|
||||
#define NGAP_REGISTER_GNB_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_gnb_req
|
||||
@@ -199,15 +200,6 @@ typedef struct pdusession_level_qos_parameter_s {
|
||||
ngap_allocation_retention_priority_t allocation_retention_priority;
|
||||
} pdusession_level_qos_parameter_t;
|
||||
|
||||
typedef struct ngap_guami_s {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_len;
|
||||
uint8_t amf_region_id;
|
||||
uint16_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
} ngap_guami_t;
|
||||
|
||||
typedef struct fiveg_s_tmsi_s {
|
||||
uint16_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
@@ -225,7 +217,6 @@ typedef struct ngap_ue_paging_identity_s {
|
||||
} ngap_ue_paging_identity_t;
|
||||
|
||||
typedef enum ngap_ue_identities_presenceMask_e {
|
||||
NGAP_UE_IDENTITIES_NONE = 0,
|
||||
NGAP_UE_IDENTITIES_FiveG_s_tmsi = 1 << 1,
|
||||
NGAP_UE_IDENTITIES_guami = 1 << 2,
|
||||
} ngap_ue_identities_presenceMask_t;
|
||||
@@ -233,16 +224,9 @@ typedef enum ngap_ue_identities_presenceMask_e {
|
||||
typedef struct ngap_ue_identity_s {
|
||||
ngap_ue_identities_presenceMask_t presenceMask;
|
||||
fiveg_s_tmsi_t s_tmsi;
|
||||
ngap_guami_t guami;
|
||||
nr_guami_t guami;
|
||||
} ngap_ue_identity_t;
|
||||
|
||||
typedef struct ngap_nas_pdu_s {
|
||||
/* Octet string data */
|
||||
uint8_t *buffer;
|
||||
/* Length of the octet string */
|
||||
uint32_t length;
|
||||
} ngap_pdu_t;
|
||||
|
||||
typedef struct ngap_mobility_restriction_s{
|
||||
ngap_plmn_identity_t serving_plmn;
|
||||
}ngap_mobility_restriction_t;
|
||||
@@ -258,8 +242,8 @@ typedef enum pdu_session_type_e {
|
||||
typedef struct pdusession_s {
|
||||
/* Unique pdusession_id for the UE. */
|
||||
int pdusession_id;
|
||||
ngap_pdu_t nas_pdu;
|
||||
ngap_pdu_t pdusessionTransfer;
|
||||
byte_array_t nas_pdu;
|
||||
byte_array_t pdusessionTransfer;
|
||||
uint8_t nb_qos;
|
||||
/* Quality of service for this pdusession */
|
||||
pdusession_level_qos_parameter_t qos[QOSFLOW_MAX_VALUE];
|
||||
@@ -506,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 */
|
||||
ngap_pdu_t nas_pdu;
|
||||
|
||||
/* If this flag is set NGAP layer is expecting the GUAMI. If = 0,
|
||||
* the temporary s-tmsi is used.
|
||||
*/
|
||||
// NAS-PDU (mandatory)
|
||||
byte_array_t nas_pdu;
|
||||
// UE identity: 5G-S-TMSI, GUAMI
|
||||
ngap_ue_identity_t ue_identity;
|
||||
} ngap_nas_first_req_t;
|
||||
|
||||
@@ -529,12 +507,12 @@ typedef struct ngap_uplink_nas_s {
|
||||
/* Unique UE identifier within an gNB */
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
/* NAS pdu */
|
||||
ngap_pdu_t nas_pdu;
|
||||
byte_array_t nas_pdu;
|
||||
} ngap_uplink_nas_t;
|
||||
|
||||
typedef struct ngap_ue_cap_info_ind_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
ngap_pdu_t ue_radio_cap;
|
||||
byte_array_t ue_radio_cap;
|
||||
} ngap_ue_cap_info_ind_t;
|
||||
|
||||
typedef struct ngap_initial_context_setup_resp_s {
|
||||
@@ -561,7 +539,7 @@ typedef struct ngap_initial_context_setup_fail_s {
|
||||
|
||||
typedef struct ngap_nas_non_delivery_ind_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
ngap_pdu_t nas_pdu;
|
||||
byte_array_t nas_pdu;
|
||||
/* TODO: add cause */
|
||||
} ngap_nas_non_delivery_ind_t;
|
||||
|
||||
@@ -599,7 +577,7 @@ typedef struct ngap_downlink_nas_s {
|
||||
/* UE id for initial connection to NGAP */
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
/* NAS pdu */
|
||||
ngap_pdu_t nas_pdu;
|
||||
byte_array_t nas_pdu;
|
||||
} ngap_downlink_nas_t;
|
||||
|
||||
|
||||
@@ -613,7 +591,7 @@ typedef struct ngap_initial_context_setup_req_s {
|
||||
ngap_ambr_t ue_ambr;
|
||||
|
||||
/* guami */
|
||||
ngap_guami_t guami;
|
||||
nr_guami_t guami;
|
||||
|
||||
/* allowed nssai */
|
||||
uint8_t nb_allowed_nssais;
|
||||
@@ -636,7 +614,7 @@ typedef struct ngap_initial_context_setup_req_s {
|
||||
|
||||
/* Nas Pdu */
|
||||
uint8_t nas_pdu_flag;
|
||||
ngap_pdu_t nas_pdu;
|
||||
byte_array_t nas_pdu;
|
||||
} ngap_initial_context_setup_req_t;
|
||||
|
||||
|
||||
@@ -665,8 +643,8 @@ typedef struct ngap_paging_ind_s {
|
||||
typedef struct {
|
||||
/* Unique pdusession_id for the UE. */
|
||||
int pdusession_id;
|
||||
ngap_pdu_t nas_pdu;
|
||||
ngap_pdu_t pdusessionTransfer;
|
||||
byte_array_t nas_pdu;
|
||||
byte_array_t pdusessionTransfer;
|
||||
} pdusession_setup_req_t;
|
||||
|
||||
typedef struct ngap_pdusession_setup_req_s {
|
||||
@@ -719,7 +697,7 @@ typedef struct ngap_path_switch_req_s {
|
||||
/* AMF UE id */
|
||||
uint64_t amf_ue_ngap_id;
|
||||
|
||||
ngap_guami_t ue_guami;
|
||||
nr_guami_t ue_guami;
|
||||
|
||||
uint16_t ue_initial_id;
|
||||
/* Security algorithms */
|
||||
@@ -792,7 +770,7 @@ typedef struct ngap_ue_release_command_s {
|
||||
typedef struct pdusession_release_s {
|
||||
/* Unique pdusession_id for the UE. */
|
||||
uint8_t pdusession_id;
|
||||
ngap_pdu_t data;
|
||||
byte_array_t data;
|
||||
} pdusession_release_t;
|
||||
|
||||
typedef struct ngap_ue_release_req_s {
|
||||
@@ -840,7 +818,7 @@ typedef struct ngap_pdusession_release_command_s {
|
||||
uint32_t gNB_ue_ngap_id;
|
||||
|
||||
/* The NAS PDU should be forwarded by the RRC layer to the NAS layer */
|
||||
ngap_pdu_t nas_pdu;
|
||||
byte_array_t nas_pdu;
|
||||
|
||||
/* Number of pdusession to be released in the list */
|
||||
uint8_t nb_pdusessions_torelease;
|
||||
|
||||
@@ -86,15 +86,6 @@ typedef struct nr_e_rab_param_s {
|
||||
uint8_t xid; // transaction_id
|
||||
} __attribute__ ((__packed__)) nr_e_rab_param_t;
|
||||
|
||||
typedef struct nr_rrc_guami_s {
|
||||
uint16_t mcc;
|
||||
uint16_t mnc;
|
||||
uint8_t mnc_len;
|
||||
uint8_t amf_region_id;
|
||||
uint16_t amf_set_id;
|
||||
uint8_t amf_pointer;
|
||||
} nr_rrc_guami_t;
|
||||
|
||||
typedef enum pdu_session_satus_e {
|
||||
PDU_SESSION_STATUS_NEW,
|
||||
PDU_SESSION_STATUS_DONE,
|
||||
@@ -217,7 +208,8 @@ typedef struct gNB_RRC_UE_s {
|
||||
uint64_t nr_cellid;
|
||||
uint32_t rrc_ue_id;
|
||||
uint64_t amf_ue_ngap_id;
|
||||
nr_rrc_guami_t ue_guami;
|
||||
// Globally Unique AMF Identifier
|
||||
nr_guami_t ue_guami;
|
||||
|
||||
ngap_security_capabilities_t security_capabilities;
|
||||
//NSA block
|
||||
@@ -247,7 +239,7 @@ typedef struct gNB_RRC_UE_s {
|
||||
pdusession_t *initial_pdus;
|
||||
|
||||
/* Nas Pdu */
|
||||
ngap_pdu_t nas_pdu;
|
||||
byte_array_t nas_pdu;
|
||||
|
||||
/* hack, see rrc_gNB_process_NGAP_PDUSESSION_SETUP_REQ() for more info */
|
||||
int max_delays_pdu_session;
|
||||
|
||||
+36
-51
@@ -95,6 +95,7 @@
|
||||
#include "E1AP/lib/e1ap_bearer_context_management.h"
|
||||
#include "E1AP/lib/e1ap_interface_management.h"
|
||||
#include "NR_DL-DCCH-Message.h"
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
#ifdef E2_AGENT
|
||||
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
|
||||
@@ -123,17 +124,6 @@ static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_i
|
||||
data->rrc->mac_rrc.ue_context_release_command(data->assoc_id, data->release_cmd);
|
||||
}
|
||||
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
///---------------------------------------------------------------------------------------------------------------///
|
||||
|
||||
static void clear_nas_pdu(ngap_pdu_t *pdu)
|
||||
{
|
||||
DevAssert(pdu != NULL);
|
||||
free(pdu->buffer); // does nothing if NULL
|
||||
pdu->buffer = NULL;
|
||||
pdu->length = 0;
|
||||
}
|
||||
|
||||
static void freeDRBlist(NR_DRB_ToAddModList_t *list)
|
||||
{
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_DRB_ToAddModList, list);
|
||||
@@ -648,13 +638,11 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
|
||||
struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList));
|
||||
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
|
||||
if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) {
|
||||
if (ue_p->pduSession[i].param.nas_pdu.buf != NULL) {
|
||||
asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, msg);
|
||||
OCTET_STRING_fromBuf(msg,
|
||||
(char *)ue_p->pduSession[i].param.nas_pdu.buffer,
|
||||
ue_p->pduSession[i].param.nas_pdu.length);
|
||||
OCTET_STRING_fromBuf(msg, (char *)ue_p->pduSession[i].param.nas_pdu.buf, ue_p->pduSession[i].param.nas_pdu.len);
|
||||
|
||||
LOG_D(NR_RRC, "add NAS info with size %d (pdusession idx %d)\n", ue_p->pduSession[i].param.nas_pdu.length, i);
|
||||
LOG_D(NR_RRC, "add NAS info with size %ld (pdusession idx %d)\n", ue_p->pduSession[i].param.nas_pdu.len, i);
|
||||
ue_p->pduSession[i].xid = xid;
|
||||
}
|
||||
if (ue_p->pduSession[i].status < PDU_SESSION_STATUS_ESTABLISHED) {
|
||||
@@ -662,9 +650,9 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
|
||||
}
|
||||
}
|
||||
|
||||
if (ue_p->nas_pdu.length) {
|
||||
if (ue_p->nas_pdu.len) {
|
||||
asn1cSequenceAdd(dedicatedNAS_MessageList->list, NR_DedicatedNAS_Message_t, msg);
|
||||
OCTET_STRING_fromBuf(msg, (char *)ue_p->nas_pdu.buffer, ue_p->nas_pdu.length);
|
||||
OCTET_STRING_fromBuf(msg, (char *)ue_p->nas_pdu.buf, ue_p->nas_pdu.len);
|
||||
}
|
||||
|
||||
/* If list is empty free the list and reset the address */
|
||||
@@ -675,7 +663,7 @@ static void rrc_gNB_generate_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_
|
||||
|
||||
/* Free all NAS PDUs */
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++)
|
||||
clear_nas_pdu(&ue_p->pduSession[i].param.nas_pdu);
|
||||
FREE_AND_ZERO_BYTE_ARRAY(ue_p->pduSession[i].param.nas_pdu);
|
||||
|
||||
uint8_t buffer[NR_RRC_BUF_SIZE] = {0};
|
||||
// TODO refactor dedicatedNAS_MessageList
|
||||
@@ -697,16 +685,17 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
CALLOC(1, sizeof(*dedicatedNAS_MessageList));
|
||||
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++) {
|
||||
rrc_pdu_session_param_t *session = &ue_p->pduSession[i];
|
||||
// bypass the new and already configured pdu sessions
|
||||
if (ue_p->pduSession[i].status >= PDU_SESSION_STATUS_DONE) {
|
||||
ue_p->pduSession[i].xid = xid;
|
||||
if (session->status >= PDU_SESSION_STATUS_DONE) {
|
||||
session->xid = xid;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ue_p->pduSession[i].cause.type != NGAP_CAUSE_NOTHING) {
|
||||
if (session->cause.type != NGAP_CAUSE_NOTHING) {
|
||||
// set xid of failure pdu session
|
||||
ue_p->pduSession[i].xid = xid;
|
||||
ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
|
||||
session->xid = xid;
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -714,21 +703,21 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
int j;
|
||||
for (j = 0; i < MAX_DRBS_PER_UE; j++) {
|
||||
if (ue_p->established_drbs[j].status != DRB_INACTIVE
|
||||
&& ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == ue_p->pduSession[i].param.pdusession_id)
|
||||
&& ue_p->established_drbs[j].cnAssociation.sdap_config.pdusession_id == session->param.pdusession_id)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == MAX_DRBS_PER_UE) {
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_unspecified};
|
||||
ue_p->pduSession[i].xid = xid;
|
||||
ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
|
||||
ue_p->pduSession[i].cause = cause;
|
||||
session->xid = xid;
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
session->cause = cause;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reference TS23501 Table 5.7.4-1: Standardized 5QI to QoS characteristics mapping
|
||||
for (qos_flow_index = 0; qos_flow_index < ue_p->pduSession[i].param.nb_qos; qos_flow_index++) {
|
||||
switch (ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI) {
|
||||
for (qos_flow_index = 0; qos_flow_index < session->param.nb_qos; qos_flow_index++) {
|
||||
switch (session->param.qos[qos_flow_index].fiveQI) {
|
||||
case 1: //100ms
|
||||
case 2: //150ms
|
||||
case 3: //50ms
|
||||
@@ -742,27 +731,23 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_E(NR_RRC, "not supported 5qi %lu\n", ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI);
|
||||
LOG_E(NR_RRC, "not supported 5qi %lu\n", session->param.qos[qos_flow_index].fiveQI);
|
||||
ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CauseRadioNetwork_not_supported_5QI_value};
|
||||
ue_p->pduSession[i].status = PDU_SESSION_STATUS_FAILED;
|
||||
ue_p->pduSession[i].xid = xid;
|
||||
ue_p->pduSession[i].cause = cause;
|
||||
session->status = PDU_SESSION_STATUS_FAILED;
|
||||
session->xid = xid;
|
||||
session->cause = cause;
|
||||
continue;
|
||||
}
|
||||
LOG_I(NR_RRC,
|
||||
"index %d, QOS flow %d, 5QI %ld \n",
|
||||
i,
|
||||
qos_flow_index,
|
||||
ue_p->pduSession[i].param.qos[qos_flow_index].fiveQI);
|
||||
LOG_I(NR_RRC, "index %d, QOS flow %d, 5QI %ld \n", i, qos_flow_index, session->param.qos[qos_flow_index].fiveQI);
|
||||
}
|
||||
|
||||
ue_p->pduSession[i].status = PDU_SESSION_STATUS_DONE;
|
||||
ue_p->pduSession[i].xid = xid;
|
||||
session->status = PDU_SESSION_STATUS_DONE;
|
||||
session->xid = xid;
|
||||
|
||||
if (ue_p->pduSession[i].param.nas_pdu.buffer != NULL) {
|
||||
if (session->param.nas_pdu.buf != NULL) {
|
||||
asn1cSequenceAdd(dedicatedNAS_MessageList->list,NR_DedicatedNAS_Message_t, dedicatedNAS_Message);
|
||||
OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)ue_p->pduSession[i].param.nas_pdu.buffer, ue_p->pduSession[i].param.nas_pdu.length);
|
||||
LOG_I(NR_RRC, "add NAS info with size %d (pdusession id %d)\n", ue_p->pduSession[i].param.nas_pdu.length, ue_p->pduSession[i].param.pdusession_id);
|
||||
OCTET_STRING_fromBuf(dedicatedNAS_Message, (char *)session->param.nas_pdu.buf, session->param.nas_pdu.len);
|
||||
LOG_I(NR_RRC, "add NAS info with size %ld (pdusession id %d)\n", session->param.nas_pdu.len, session->param.pdusession_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,7 +775,7 @@ void rrc_gNB_modify_dedicatedRRCReconfiguration(gNB_RRC_INST *rrc, gNB_RRC_UE_t
|
||||
|
||||
/* Free all NAS PDUs */
|
||||
for (int i = 0; i < ue_p->nb_of_pdusessions; i++)
|
||||
clear_nas_pdu(&ue_p->pduSession[i].param.nas_pdu);
|
||||
FREE_AND_ZERO_BYTE_ARRAY(ue_p->pduSession[i].param.nas_pdu);
|
||||
|
||||
LOG_I(NR_RRC, "UE %d: Generate RRCReconfiguration (bytes %d)\n", ue_p->rrc_ue_id, size);
|
||||
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration;
|
||||
@@ -1571,21 +1556,21 @@ static int handle_rrcReestablishmentComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE
|
||||
*/
|
||||
void rrc_forward_ue_nas_message(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE)
|
||||
{
|
||||
if (UE->nas_pdu.buffer == NULL || UE->nas_pdu.length == 0)
|
||||
if (UE->nas_pdu.buf == NULL || UE->nas_pdu.len == 0)
|
||||
return; // no problem: the UE will re-request a NAS PDU
|
||||
|
||||
LOG_UE_DL_EVENT(UE, "Send DL Information Transfer [%d bytes]\n", UE->nas_pdu.length);
|
||||
LOG_UE_DL_EVENT(UE, "Send DL Information Transfer [%ld bytes]\n", UE->nas_pdu.len);
|
||||
|
||||
uint8_t buffer[4096];
|
||||
unsigned int xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id);
|
||||
uint32_t length = do_NR_DLInformationTransfer(buffer, sizeof(buffer), xid, UE->nas_pdu.length, UE->nas_pdu.buffer);
|
||||
uint32_t length = do_NR_DLInformationTransfer(buffer, sizeof(buffer), xid, UE->nas_pdu.len, UE->nas_pdu.buf);
|
||||
LOG_DUMPMSG(NR_RRC, DEBUG_RRC, buffer, length, "[MSG] RRC DL Information Transfer\n");
|
||||
rb_id_t srb_id = UE->Srb[2].Active ? DL_SCH_LCID_DCCH1 : DL_SCH_LCID_DCCH;
|
||||
const uint32_t msg_id = NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer;
|
||||
nr_rrc_transfer_protected_rrc_message(rrc, UE, srb_id, msg_id, buffer, length);
|
||||
// no need to free UE->nas_pdu.buffer, do_NR_DLInformationTransfer() did that
|
||||
UE->nas_pdu.buffer = NULL;
|
||||
UE->nas_pdu.length = 0;
|
||||
// no need to free UE->nas_pdu.buf, do_NR_DLInformationTransfer() did that
|
||||
UE->nas_pdu.buf = NULL;
|
||||
UE->nas_pdu.len = 0;
|
||||
}
|
||||
|
||||
static void handle_ueCapabilityInformation(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_UECapabilityInformation_t *ue_cap_info)
|
||||
|
||||
@@ -148,67 +148,78 @@ void nr_rrc_pdcp_config_security(gNB_RRC_UE_t *UE, bool enable_ciphering)
|
||||
nr_pdcp_config_set_security(UE->rrc_ue_id, DL_SCH_LCID_DCCH, true, &security_parameters);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
* Initial UE NAS message on S1AP.
|
||||
*/
|
||||
/** @brief Process AMF Identifier and fill GUAMI struct members */
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare the Initial UE Message (Uplink NAS) to be forwarded to the AMF over N2
|
||||
* extracts NAS PDU, Selected PLMN and Registered AMF from the RRCSetupComplete
|
||||
*/
|
||||
void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRCSetupComplete_IEs_t *rrcSetupComplete)
|
||||
//------------------------------------------------------------------------------
|
||||
{
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_RRC_GNB, rrc->module_id, NGAP_NAS_FIRST_REQ);
|
||||
ngap_nas_first_req_t *req = &NGAP_NAS_FIRST_REQ(message_p);
|
||||
memset(req, 0, sizeof(*req));
|
||||
|
||||
// RAN UE NGAP ID
|
||||
req->gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
|
||||
// RRC Establishment Cause
|
||||
/* Assume that cause is coded in the same way in RRC and NGap, just check that the value is in NGap range */
|
||||
AssertFatal(UE->establishment_cause < NGAP_RRC_CAUSE_LAST, "Establishment cause invalid (%jd/%d)!", UE->establishment_cause, NGAP_RRC_CAUSE_LAST);
|
||||
req->establishment_cause = UE->establishment_cause;
|
||||
|
||||
/* Forward NAS message */
|
||||
req->nas_pdu.length = rrcSetupComplete->dedicatedNAS_Message.size;
|
||||
req->nas_pdu.buffer = malloc(req->nas_pdu.length);
|
||||
AssertFatal(req->nas_pdu.buffer != NULL, "out of memory\n");
|
||||
memcpy(req->nas_pdu.buffer, rrcSetupComplete->dedicatedNAS_Message.buf, req->nas_pdu.length);
|
||||
// extract_imsi(NGAP_NAS_FIRST_REQ (message_p).nas_pdu.buffer,
|
||||
// NGAP_NAS_FIRST_REQ (message_p).nas_pdu.length,
|
||||
// ue_context_pP);
|
||||
// NAS-PDU
|
||||
req->nas_pdu = create_byte_array(rrcSetupComplete->dedicatedNAS_Message.size, rrcSetupComplete->dedicatedNAS_Message.buf);
|
||||
|
||||
/* 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);
|
||||
/* 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);
|
||||
|
||||
req->selected_plmn_identity = 0; /* always zero because we only support one */
|
||||
|
||||
/* Fill UE identities with available information */
|
||||
/* 5G-S-TMSI */
|
||||
if (UE->Initialue_identity_5g_s_TMSI.presence) {
|
||||
/* Fill s-TMSI */
|
||||
req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_FiveG_s_tmsi;
|
||||
req->ue_identity.presenceMask |= NGAP_UE_IDENTITIES_FiveG_s_tmsi;
|
||||
req->ue_identity.s_tmsi.amf_set_id = UE->Initialue_identity_5g_s_TMSI.amf_set_id;
|
||||
req->ue_identity.s_tmsi.amf_pointer = UE->Initialue_identity_5g_s_TMSI.amf_pointer;
|
||||
req->ue_identity.s_tmsi.m_tmsi = UE->Initialue_identity_5g_s_TMSI.fiveg_tmsi;
|
||||
} else if (rrcSetupComplete->registeredAMF != NULL) {
|
||||
}
|
||||
|
||||
/* Process Registered AMF IE */
|
||||
if (rrcSetupComplete->registeredAMF != NULL) {
|
||||
/* Fetch the AMF-Identifier from the registeredAMF IE
|
||||
* The IE AMF-Identifier (AMFI) comprises of an AMF Region ID (8b),
|
||||
* an AMF Set ID (10b) and an AMF Pointer (6b)
|
||||
* as specified in TS 23.003 [21], clause 2.10.1. */
|
||||
NR_RegisteredAMF_t *r_amf = rrcSetupComplete->registeredAMF;
|
||||
req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_guami;
|
||||
|
||||
/* The IE AMF-Identifier (AMFI) comprises of an AMF Region ID (8b), an AMF Set ID (10b) and an AMF Pointer (6b) as specified in TS 23.003 [21], clause 2.10.1. */
|
||||
req->ue_identity.presenceMask |= NGAP_UE_IDENTITIES_guami;
|
||||
uint32_t amf_Id = BIT_STRING_to_uint32(&r_amf->amf_Identifier);
|
||||
req->ue_identity.guami.amf_region_id = (amf_Id >> 16) & 0xff;
|
||||
req->ue_identity.guami.amf_set_id = (amf_Id >> 6) & 0x3ff;
|
||||
req->ue_identity.guami.amf_pointer = amf_Id & 0x3f;
|
||||
|
||||
UE->ue_guami.amf_region_id = req->ue_identity.guami.amf_region_id;
|
||||
UE->ue_guami.amf_set_id = req->ue_identity.guami.amf_set_id;
|
||||
UE->ue_guami.amf_pointer = req->ue_identity.guami.amf_pointer;
|
||||
|
||||
UE->ue_guami = req->ue_identity.guami = get_guami(amf_Id, req->plmn);
|
||||
LOG_I(NGAP,
|
||||
"Build NGAP_NAS_FIRST_REQ adding in s_TMSI: GUAMI amf_set_id %u amf_region_id %u ue %x\n",
|
||||
"GUAMI in NGAP_NAS_FIRST_REQ (UE %04x): AMF Set ID %u, Region ID %u, Pointer %u\n",
|
||||
UE->rnti,
|
||||
req->ue_identity.guami.amf_set_id,
|
||||
req->ue_identity.guami.amf_region_id,
|
||||
UE->rnti);
|
||||
} else {
|
||||
req->ue_identity.presenceMask = NGAP_UE_IDENTITIES_NONE;
|
||||
req->ue_identity.guami.amf_pointer);
|
||||
}
|
||||
|
||||
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, message_p);
|
||||
@@ -247,8 +258,13 @@ static int decodePDUSessionResourceSetup(pdusession_t *session)
|
||||
{
|
||||
NGAP_PDUSessionResourceSetupRequestTransfer_t *pdusessionTransfer = NULL;
|
||||
asn_codec_ctx_t st = {.max_stack_size = 100 * 1000};
|
||||
asn_dec_rval_t dec_rval =
|
||||
aper_decode(&st, &asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer, (void **)&pdusessionTransfer, session->pdusessionTransfer.buffer, session->pdusessionTransfer.length, 0, 0);
|
||||
asn_dec_rval_t dec_rval = aper_decode(&st,
|
||||
&asn_DEF_NGAP_PDUSessionResourceSetupRequestTransfer,
|
||||
(void **)&pdusessionTransfer,
|
||||
session->pdusessionTransfer.buf,
|
||||
session->pdusessionTransfer.len,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_E(NR_RRC, "can not decode PDUSessionResourceSetupRequestTransfer\n");
|
||||
@@ -491,14 +507,8 @@ int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t
|
||||
|
||||
UE->amf_ue_ngap_id = req->amf_ue_ngap_id;
|
||||
|
||||
/* store guami in gNB_RRC_UE_t context;
|
||||
* we copy individual members because the guami types are different (nr_rrc_guami_t and ngap_guami_t) */
|
||||
UE->ue_guami.mcc = req->guami.mcc;
|
||||
UE->ue_guami.mnc = req->guami.mnc;
|
||||
UE->ue_guami.mnc_len = req->guami.mnc_len;
|
||||
UE->ue_guami.amf_region_id = req->guami.amf_region_id;
|
||||
UE->ue_guami.amf_set_id = req->guami.amf_set_id;
|
||||
UE->ue_guami.amf_pointer = req->guami.amf_pointer;
|
||||
// Directly copy the entire guami structure
|
||||
UE->ue_guami = req->guami;
|
||||
|
||||
/* NAS PDU */
|
||||
// this is malloced pointers, we pass it for later free()
|
||||
@@ -713,8 +723,7 @@ int rrc_gNB_process_NGAP_DOWNLINK_NAS(MessageDef *msg_p, instance_t instance, mu
|
||||
msg_fail_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_NAS_NON_DELIVERY_IND);
|
||||
ngap_nas_non_delivery_ind_t *msg = &NGAP_NAS_NON_DELIVERY_IND(msg_fail_p);
|
||||
msg->gNB_ue_ngap_id = req->gNB_ue_ngap_id;
|
||||
msg->nas_pdu.length = req->nas_pdu.length;
|
||||
msg->nas_pdu.buffer = req->nas_pdu.buffer;
|
||||
msg->nas_pdu = req->nas_pdu;
|
||||
// TODO add failure cause when defined!
|
||||
itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p);
|
||||
return (-1);
|
||||
@@ -746,8 +755,8 @@ void rrc_gNB_send_NGAP_UPLINK_NAS(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const NR_
|
||||
memcpy(buf, nas->buf, nas->size);
|
||||
MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, rrc->module_id, NGAP_UPLINK_NAS);
|
||||
NGAP_UPLINK_NAS(msg_p).gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
NGAP_UPLINK_NAS(msg_p).nas_pdu.length = nas->size;
|
||||
NGAP_UPLINK_NAS(msg_p).nas_pdu.buffer = buf;
|
||||
NGAP_UPLINK_NAS(msg_p).nas_pdu.len = nas->size;
|
||||
NGAP_UPLINK_NAS(msg_p).nas_pdu.buf = buf;
|
||||
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, msg_p);
|
||||
}
|
||||
|
||||
@@ -972,10 +981,16 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s
|
||||
session->nb_qos = qos->list.count;
|
||||
}
|
||||
|
||||
static void decodePDUSessionResourceModify(pdusession_t *param, const ngap_pdu_t pdu)
|
||||
static void decodePDUSessionResourceModify(pdusession_t *param, const byte_array_t pdu)
|
||||
{
|
||||
NGAP_PDUSessionResourceModifyRequestTransfer_t *pdusessionTransfer = NULL;
|
||||
asn_dec_rval_t dec_rval = aper_decode(NULL, &asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, (void **)&pdusessionTransfer, pdu.buffer, pdu.length, 0, 0);
|
||||
asn_dec_rval_t dec_rval = aper_decode(NULL,
|
||||
&asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer,
|
||||
(void **)&pdusessionTransfer,
|
||||
pdu.buf,
|
||||
pdu.len,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_E(NR_RRC, "could not decode PDUSessionResourceModifyRequestTransfer\n");
|
||||
@@ -1074,7 +1089,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ(MessageDef *msg_p, instance_t ins
|
||||
sess->status = PDU_SESSION_STATUS_NEW;
|
||||
sess->param.pdusession_id = sessMod->pdusession_id;
|
||||
sess->cause.type = NGAP_CAUSE_NOTHING;
|
||||
if (sessMod->nas_pdu.buffer != NULL) {
|
||||
if (sessMod->nas_pdu.buf != NULL) {
|
||||
UE->pduSession[i].param.nas_pdu = sessMod->nas_pdu;
|
||||
}
|
||||
// Save new pdu session parameters, qos, upf addr, teid
|
||||
@@ -1347,8 +1362,8 @@ void rrc_gNB_send_NGAP_UE_CAPABILITIES_IND(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE,
|
||||
ngap_ue_cap_info_ind_t *ind = &NGAP_UE_CAPABILITIES_IND(msg_p);
|
||||
memset(ind, 0, sizeof(*ind));
|
||||
ind->gNB_ue_ngap_id = UE->rrc_ue_id;
|
||||
ind->ue_radio_cap.length = encoded;
|
||||
ind->ue_radio_cap.buffer = buf2;
|
||||
ind->ue_radio_cap.len = encoded;
|
||||
ind->ue_radio_cap.buf = buf2;
|
||||
itti_send_msg_to_task (TASK_NGAP, rrc->module_id, msg_p);
|
||||
LOG_I(NR_RRC,"Send message to ngap: NGAP_UE_CAPABILITIES_IND\n");
|
||||
}
|
||||
@@ -1427,7 +1442,7 @@ int rrc_gNB_process_NGAP_PDUSESSION_RELEASE_COMMAND(MessageDef *msg_p, instance_
|
||||
if (found) {
|
||||
// TODO RRCReconfiguration To UE
|
||||
LOG_I(NR_RRC, "Send RRCReconfiguration To UE \n");
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration_release(rrc, UE, xid, cmd->nas_pdu.length, cmd->nas_pdu.buffer);
|
||||
rrc_gNB_generate_dedicatedRRCReconfiguration_release(rrc, UE, xid, cmd->nas_pdu.len, cmd->nas_pdu.buf);
|
||||
} else {
|
||||
// gtp tunnel delete
|
||||
LOG_I(NR_RRC, "gtp tunnel delete all tunnels for UE %04x\n", UE->rnti);
|
||||
|
||||
Reference in New Issue
Block a user