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:
@@ -35,6 +35,16 @@ typedef struct nssai_s {
|
||||
uint32_t sd;
|
||||
} nssai_t;
|
||||
|
||||
// Globally Unique AMF Identifier
|
||||
typedef struct nr_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_guami_t;
|
||||
|
||||
typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,15 +23,21 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "common/utils/utils.h" // for malloc_or_fail
|
||||
|
||||
byte_array_t create_byte_array(const size_t len, const uint8_t* buffer)
|
||||
{
|
||||
byte_array_t result = {.len = len};
|
||||
if (len) {
|
||||
result.buf = malloc_or_fail(len);
|
||||
memcpy(result.buf, buffer, len);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
byte_array_t copy_byte_array(byte_array_t src)
|
||||
{
|
||||
byte_array_t dst = {0};
|
||||
dst.buf = malloc(src.len);
|
||||
assert(dst.buf != NULL && "Memory exhausted");
|
||||
memcpy(dst.buf, src.buf, src.len);
|
||||
dst.len = src.len;
|
||||
return dst;
|
||||
return create_byte_array(src.len, src.buf);
|
||||
}
|
||||
|
||||
void free_byte_array(byte_array_t ba)
|
||||
|
||||
@@ -28,6 +28,13 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define FREE_AND_ZERO_BYTE_ARRAY(BA) \
|
||||
do { \
|
||||
free_byte_array(BA); \
|
||||
BA.buf = NULL; \
|
||||
BA.len = 0; \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
size_t len;
|
||||
uint8_t* buf;
|
||||
@@ -43,5 +50,6 @@ bool eq_byte_array(const byte_array_t* m0, const byte_array_t* m1);
|
||||
|
||||
byte_array_t cp_str_to_ba(const char* str);
|
||||
char* cp_ba_to_str(const byte_array_t ba);
|
||||
byte_array_t create_byte_array(const size_t len, const uint8_t* buffer);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -52,15 +52,6 @@
|
||||
#include "oai_asn1.h"
|
||||
#include "queue.h"
|
||||
|
||||
static void allocCopy(ngap_pdu_t *out, OCTET_STRING_t in)
|
||||
{
|
||||
if (in.size) {
|
||||
out->buffer = malloc(in.size);
|
||||
memcpy(out->buffer, in.buf, in.size);
|
||||
}
|
||||
out->length = in.size;
|
||||
}
|
||||
|
||||
char *ngap_direction2String(int ngap_dir) {
|
||||
static char *ngap_direction_String[] = {
|
||||
"", /* Nothing */
|
||||
@@ -145,6 +136,36 @@ static int ngap_gNB_handle_ng_setup_failure(sctp_assoc_t assoc_id, uint32_t stre
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ngap_dump_served_guami(const ngap_gNB_amf_data_t *amf_desc_p)
|
||||
{
|
||||
const struct served_guami_s *guami_p;
|
||||
const struct plmn_identity_s *plmn_p;
|
||||
const struct served_region_id_s *region_p;
|
||||
const struct amf_set_id_s *set_id_p;
|
||||
const struct amf_pointer_s *pointer_p;
|
||||
|
||||
NGAP_DEBUG("Served GUAMIs for AMF %s (assoc_id=%d):\n",
|
||||
amf_desc_p->amf_name ? amf_desc_p->amf_name : "(no name)",
|
||||
amf_desc_p->assoc_id);
|
||||
|
||||
STAILQ_FOREACH(guami_p, &amf_desc_p->served_guami, next)
|
||||
{
|
||||
NGAP_DEBUG(" GUAMI:\n");
|
||||
STAILQ_FOREACH(plmn_p, &guami_p->served_plmns, next) {
|
||||
NGAP_DEBUG(" PLMN: MCC=%03d, MNC=%0*d\n", plmn_p->mcc, plmn_p->mnc_digit_length, plmn_p->mnc);
|
||||
}
|
||||
STAILQ_FOREACH(region_p, &guami_p->served_region_ids, next) {
|
||||
NGAP_DEBUG(" AMF Region ID: %d\n", region_p->amf_region_id);
|
||||
}
|
||||
STAILQ_FOREACH(set_id_p, &guami_p->amf_set_ids, next) {
|
||||
NGAP_DEBUG(" AMF Set ID: %d\n", set_id_p->amf_set_id);
|
||||
}
|
||||
STAILQ_FOREACH(pointer_p, &guami_p->amf_pointers, next) {
|
||||
NGAP_DEBUG(" AMF Pointer: %d\n", pointer_p->amf_pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
|
||||
{
|
||||
NGAP_NGSetupResponse_t *container;
|
||||
@@ -173,7 +194,6 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
|
||||
/* The list of served guami can contain at most 256 elements.
|
||||
* NR related guami is the first element in the list, i.e with an id of 0.
|
||||
*/
|
||||
NGAP_DEBUG("servedGUAMIs.list.count %d\n", ie->value.choice.ServedGUAMIList.list.count);
|
||||
DevAssert(ie->value.choice.ServedGUAMIList.list.count > 0);
|
||||
DevAssert(ie->value.choice.ServedGUAMIList.list.count <= NGAP_maxnoofServedGUAMIs);
|
||||
|
||||
@@ -197,32 +217,27 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
|
||||
STAILQ_INSERT_TAIL(&new_guami_p->served_plmns, new_plmn_identity_p, next);
|
||||
new_guami_p->nb_served_plmns++;
|
||||
|
||||
NGAP_AMFRegionID_t *amf_region_id_p;
|
||||
struct served_region_id_s *new_region_id_p;
|
||||
amf_region_id_p = &guami_item_p->gUAMI.aMFRegionID;
|
||||
new_region_id_p = calloc(1, sizeof(struct served_region_id_s));
|
||||
OCTET_STRING_TO_INT8(amf_region_id_p, new_region_id_p->amf_region_id);
|
||||
new_region_id_p->amf_region_id = BIT_STRING_to_uint8(&guami_item_p->gUAMI.aMFRegionID);
|
||||
STAILQ_INSERT_TAIL(&new_guami_p->served_region_ids, new_region_id_p, next);
|
||||
new_guami_p->nb_region_id++;
|
||||
|
||||
NGAP_AMFSetID_t *amf_set_id_p;
|
||||
struct amf_set_id_s *new_amf_set_id_p;
|
||||
amf_set_id_p = &guami_item_p->gUAMI.aMFSetID;
|
||||
new_amf_set_id_p = calloc(1, sizeof(struct amf_set_id_s));
|
||||
OCTET_STRING_TO_INT16(amf_set_id_p, new_amf_set_id_p->amf_set_id);
|
||||
new_amf_set_id_p->amf_set_id = BIT_STRING_to_uint16(&guami_item_p->gUAMI.aMFSetID);
|
||||
STAILQ_INSERT_TAIL(&new_guami_p->amf_set_ids, new_amf_set_id_p, next);
|
||||
new_guami_p->nb_amf_set_id++;
|
||||
|
||||
NGAP_AMFPointer_t *amf_pointer_p;
|
||||
struct amf_pointer_s *new_amf_pointer_p;
|
||||
amf_pointer_p = &guami_item_p->gUAMI.aMFPointer;
|
||||
new_amf_pointer_p = calloc(1, sizeof(struct amf_pointer_s));
|
||||
OCTET_STRING_TO_INT8(amf_pointer_p, new_amf_pointer_p->amf_pointer);
|
||||
new_amf_pointer_p->amf_pointer = BIT_STRING_to_uint8(&guami_item_p->gUAMI.aMFPointer);
|
||||
STAILQ_INSERT_TAIL(&new_guami_p->amf_pointers, new_amf_pointer_p, next);
|
||||
new_guami_p->nb_amf_pointer++;
|
||||
|
||||
STAILQ_INSERT_TAIL(&amf_desc_p->served_guami, new_guami_p, next);
|
||||
}
|
||||
ngap_dump_served_guami(amf_desc_p);
|
||||
|
||||
/* Set the capacity of this AMF */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
|
||||
@@ -245,13 +260,12 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
|
||||
NGAP_ProtocolIE_ID_id_PLMNSupportList, true);
|
||||
|
||||
NGAP_DEBUG("PLMNSupportList.list.count %d\n", ie->value.choice.PLMNSupportList.list.count);
|
||||
DevAssert(ie->value.choice.PLMNSupportList.list.count > 0);
|
||||
DevAssert(ie->value.choice.PLMNSupportList.list.count <= NGAP_maxnoofPLMNs);
|
||||
|
||||
STAILQ_INIT(&amf_desc_p->plmn_supports);
|
||||
|
||||
for (i = 0; i < ie->value.choice.ServedGUAMIList.list.count; i++) {
|
||||
for (i = 0; i < ie->value.choice.PLMNSupportList.list.count; i++) {
|
||||
NGAP_PLMNSupportItem_t *plmn_support_item_p;
|
||||
struct plmn_support_s *new_plmn_support_p;
|
||||
NGAP_SliceSupportItem_t *slice_support_item_p;
|
||||
@@ -260,11 +274,10 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
|
||||
plmn_support_item_p = ie->value.choice.PLMNSupportList.list.array[i];
|
||||
|
||||
new_plmn_support_p = calloc(1, sizeof(struct plmn_support_s));
|
||||
|
||||
TBCD_TO_MCC_MNC(&plmn_support_item_p->pLMNIdentity, new_plmn_support_p->plmn_identity.mcc,
|
||||
new_plmn_support_p->plmn_identity.mnc, new_plmn_support_p->plmn_identity.mnc_digit_length);
|
||||
|
||||
NGAP_DEBUG("PLMNSupportList.list.count %d\n", plmn_support_item_p->sliceSupportList.list.count);
|
||||
struct plmn_identity_s *plmn = &new_plmn_support_p->plmn_identity;
|
||||
TBCD_TO_MCC_MNC(&plmn_support_item_p->pLMNIdentity, plmn->mcc, plmn->mnc, plmn->mnc_digit_length);
|
||||
NGAP_INFO("Supported PLMN %d: MCC=%03d MNC=%0*d\n", i, plmn->mcc, plmn->mnc_digit_length, plmn->mnc);
|
||||
DevAssert(plmn_support_item_p->sliceSupportList.list.count > 0);
|
||||
DevAssert(plmn_support_item_p->sliceSupportList.list.count <= NGAP_maxnoofSliceItems);
|
||||
|
||||
@@ -282,6 +295,12 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
|
||||
new_slice_support_p->sD[1] = slice_support_item_p->s_NSSAI.sD->buf[1];
|
||||
new_slice_support_p->sD[2] = slice_support_item_p->s_NSSAI.sD->buf[2];
|
||||
}
|
||||
NGAP_INFO("Supported slice (PLMN %d): SST=0x%02x SD=%d%d%d\n",
|
||||
i,
|
||||
new_slice_support_p->sST,
|
||||
new_slice_support_p->sD[0],
|
||||
new_slice_support_p->sD[1],
|
||||
new_slice_support_p->sD[2]);
|
||||
STAILQ_INSERT_TAIL(&new_plmn_support_p->slice_supports, new_slice_support_p, next);
|
||||
}
|
||||
|
||||
@@ -772,9 +791,10 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
|
||||
}
|
||||
|
||||
if (item_p->nAS_PDU) {
|
||||
allocCopy(&msg->pdusession_param[i].nas_pdu, *item_p->nAS_PDU);
|
||||
msg->pdusession_param[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
|
||||
}
|
||||
allocCopy(&msg->pdusession_param[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
|
||||
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
|
||||
msg->pdusession_param[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -841,7 +861,7 @@ static int ngap_gNB_handle_initial_context_request(sctp_assoc_t assoc_id, uint32
|
||||
NGAP_ProtocolIE_ID_id_NAS_PDU, false);
|
||||
|
||||
if (ie)
|
||||
allocCopy(&msg->nas_pdu, ie->value.choice.NAS_PDU);
|
||||
msg->nas_pdu = create_byte_array(ie->value.choice.NAS_PDU.size, ie->value.choice.NAS_PDU.buf);
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
|
||||
|
||||
@@ -985,9 +1005,9 @@ static int ngap_gNB_handle_pdusession_setup_request(sctp_assoc_t assoc_id, uint3
|
||||
} else {
|
||||
msg->pdusession_setup_params[i].nssai.sd = 0xffffff;
|
||||
}
|
||||
|
||||
allocCopy(&msg->pdusession_setup_params[i].nas_pdu, *item_p->pDUSessionNAS_PDU);
|
||||
allocCopy(&msg->pdusession_setup_params[i].pdusessionTransfer, item_p->pDUSessionResourceSetupRequestTransfer);
|
||||
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceSetupRequestTransfer;
|
||||
msg->pdusession_setup_params[i].nas_pdu = create_byte_array(item_p->pDUSessionNAS_PDU->size, item_p->pDUSessionNAS_PDU->buf);
|
||||
msg->pdusession_setup_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
|
||||
}
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
|
||||
|
||||
@@ -1164,8 +1184,9 @@ static int ngap_gNB_handle_pdusession_modify_request(sctp_assoc_t assoc_id, uint
|
||||
|
||||
// check for the NAS PDU
|
||||
if (item_p->nAS_PDU != NULL && item_p->nAS_PDU->size > 0) {
|
||||
allocCopy(&msg->pdusession_modify_params[i].nas_pdu, *item_p->nAS_PDU);
|
||||
allocCopy(&msg->pdusession_modify_params[i].pdusessionTransfer, item_p->pDUSessionResourceModifyRequestTransfer);
|
||||
msg->pdusession_modify_params[i].nas_pdu = create_byte_array(item_p->nAS_PDU->size, item_p->nAS_PDU->buf);
|
||||
OCTET_STRING_t *transfer = &item_p->pDUSessionResourceModifyRequestTransfer;
|
||||
msg->pdusession_modify_params[i].pdusessionTransfer = create_byte_array(transfer->size, transfer->buf);
|
||||
} else {
|
||||
LOG_W(NGAP, "received pdu session modify with void content for UE %u, pdu session %lu\n", msg->gNB_ue_ngap_id, item_p->pDUSessionID);
|
||||
continue;
|
||||
@@ -1241,7 +1262,7 @@ static int ngap_gNB_handle_pdusession_release_command(sctp_assoc_t assoc_id, uin
|
||||
NGAP_ProtocolIE_ID_id_NAS_PDU, false);
|
||||
|
||||
if (ie)
|
||||
allocCopy(&msg->nas_pdu, ie->value.choice.NAS_PDU);
|
||||
msg->nas_pdu = create_byte_array(ie->value.choice.NAS_PDU.size, ie->value.choice.NAS_PDU.buf);
|
||||
|
||||
/* id-PDUSessionResourceToReleaseListRelCmd */
|
||||
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_PDUSessionResourceReleaseCommandIEs_t, ie, container,
|
||||
@@ -1252,8 +1273,9 @@ static int ngap_gNB_handle_pdusession_release_command(sctp_assoc_t assoc_id, uin
|
||||
for (i = 0; i < ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.count; i++) {
|
||||
NGAP_PDUSessionResourceToReleaseItemRelCmd_t *item_p;
|
||||
item_p = ie->value.choice.PDUSessionResourceToReleaseListRelCmd.list.array[i];
|
||||
msg->pdusession_release_params[i].pdusession_id = item_p->pDUSessionID;
|
||||
allocCopy(&msg->pdusession_release_params[i].data, item_p->pDUSessionResourceReleaseCommandTransfer);
|
||||
pdusession_release_t *r = &msg->pdusession_release_params[i];
|
||||
r->pdusession_id = item_p->pDUSessionID;
|
||||
r->data = create_byte_array(item_p->pDUSessionResourceReleaseCommandTransfer.size, item_p->pDUSessionResourceReleaseCommandTransfer.buf);
|
||||
}
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, ue_desc_p->gNB_instance->instance, message_p);
|
||||
|
||||
@@ -64,9 +64,7 @@ void ngap_gNB_itti_send_nas_downlink_ind(instance_t instance, uint32_t gNB_ue_ng
|
||||
ngap_downlink_nas = &message_p->ittiMsg.ngap_downlink_nas;
|
||||
|
||||
ngap_downlink_nas->gNB_ue_ngap_id = gNB_ue_ngap_id;
|
||||
ngap_downlink_nas->nas_pdu.buffer = malloc(sizeof(uint8_t) * nas_pdu_length);
|
||||
memcpy(ngap_downlink_nas->nas_pdu.buffer, nas_pdu, nas_pdu_length);
|
||||
ngap_downlink_nas->nas_pdu.length = nas_pdu_length;
|
||||
ngap_downlink_nas->nas_pdu = create_byte_array(nas_pdu_length, nas_pdu);
|
||||
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "ngap_gNB_defs.h"
|
||||
#include "queue.h"
|
||||
#include "tree.h"
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
static ngap_gNB_internal_data_t ngap_gNB_internal_data;
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
* @ingroup _ngap
|
||||
*/
|
||||
|
||||
#include "ds/byte_array.h"
|
||||
|
||||
#ifndef NGAP_GNB_MANAGEMENT_PROCEDURES_H_
|
||||
#define NGAP_GNB_MANAGEMENT_PROCEDURES_H_
|
||||
|
||||
|
||||
@@ -58,15 +58,6 @@
|
||||
#include "s1ap_messages_types.h"
|
||||
#include "xer_encoder.h"
|
||||
|
||||
static void allocCopy(OCTET_STRING_t *out, ngap_pdu_t in)
|
||||
{
|
||||
if (in.length) {
|
||||
out->buf = malloc(in.length);
|
||||
memcpy(out->buf, in.buffer, in.length);
|
||||
}
|
||||
out->size = in.length;
|
||||
}
|
||||
|
||||
static void allocAddrCopy(BIT_STRING_t *out, transport_layer_addr_t in)
|
||||
{
|
||||
if (in.length) {
|
||||
@@ -77,20 +68,106 @@ static void allocAddrCopy(BIT_STRING_t *out, transport_layer_addr_t in)
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEfirstReq)
|
||||
//------------------------------------------------------------------------------
|
||||
/** @brief Selects the AMF instance for a given UE based on identity information.
|
||||
* It attempts to select an AMF using the following prioritized criteria:
|
||||
* 1. GUAMI, if provided and valid (via Region ID, Set ID, Pointer).
|
||||
* 2. 5G-S-TMSI, using AMF Set ID if GUAMI is unavailable or unusable.
|
||||
* 3. Selected PLMN identity and local PLMN configuration.
|
||||
* 4. Fallback to AMF with highest relative capacity, considering load balancing.
|
||||
* @ref AMF Discovery and Selection (3GPP TS 23.501 clause 6.3.5) */
|
||||
static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ngap_nas_first_req_t *msg)
|
||||
{
|
||||
ngap_gNB_instance_t *instance_p = NULL;
|
||||
struct ngap_gNB_amf_data_s *amf_desc_p = NULL;
|
||||
NGAP_NGAP_PDU_t pdu;
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length = 0;
|
||||
ngap_gNB_amf_data_t *amf = NULL;
|
||||
|
||||
// Select the AMF corresponding to the GUAMI from the RegisteredAMF IE
|
||||
if (msg->ue_identity.presenceMask & NGAP_UE_IDENTITIES_guami) {
|
||||
const nr_guami_t *guami = &msg->ue_identity.guami;
|
||||
NGAP_DEBUG("GUAMI is present: MCC=%03d MNC=%03d RegionID=%d SetID=%d Pointer=%d\n",
|
||||
guami->mcc,
|
||||
guami->mnc,
|
||||
guami->amf_region_id,
|
||||
guami->amf_set_id,
|
||||
guami->amf_pointer);
|
||||
amf = ngap_gNB_nnsf_select_amf_by_guami(instance_p, msg->establishment_cause, *guami);
|
||||
if (amf) {
|
||||
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through GUAMI MCC %d MNC %d AMFRI %d AMFSI %d AMFPT %d\n",
|
||||
msg->gNB_ue_ngap_id,
|
||||
amf->amf_name,
|
||||
amf->assoc_id,
|
||||
guami->mcc,
|
||||
guami->mnc,
|
||||
guami->amf_region_id,
|
||||
guami->amf_set_id,
|
||||
guami->amf_pointer);
|
||||
return amf;
|
||||
}
|
||||
}
|
||||
|
||||
// Select the AMF corresponding to the provided 5G-S-TMSI
|
||||
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->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 MCC %d MNC %d\n",
|
||||
msg->gNB_ue_ngap_id,
|
||||
amf->amf_name,
|
||||
amf->assoc_id,
|
||||
fgs_tmsi->amf_set_id,
|
||||
msg->plmn.mcc,
|
||||
msg->plmn.mnc);
|
||||
return amf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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->plmn);
|
||||
if (amf) {
|
||||
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->plmn.mcc,
|
||||
msg->plmn.mnc);
|
||||
return amf;
|
||||
} else {
|
||||
// Select the AMF with the highest capacity
|
||||
amf = ngap_gNB_nnsf_select_amf(instance_p, msg->establishment_cause);
|
||||
if (amf) {
|
||||
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through highest relative capacity\n", msg->gNB_ue_ngap_id, amf->amf_name, amf->assoc_id);
|
||||
return amf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return amf;
|
||||
}
|
||||
|
||||
/** @brief NAS Transport Messages: Initial UE Message
|
||||
* forward the first received (layer 3) uplink NAS message
|
||||
* from the radio interface to the AMF over N2
|
||||
* NG-RAN node -> AMF (9.2.5.1, 3GPP TS 38.413) */
|
||||
int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEfirstReq)
|
||||
{
|
||||
NGAP_NGAP_PDU_t pdu = {0};
|
||||
uint8_t *buffer = NULL;
|
||||
uint32_t length = 0;
|
||||
DevAssert(UEfirstReq != NULL);
|
||||
/* Retrieve the NGAP gNB instance associated with Mod_id */
|
||||
instance_p = ngap_gNB_get_instance(instance);
|
||||
ngap_gNB_instance_t *instance_p = ngap_gNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
|
||||
// AMF selection from the Initial UE message contents
|
||||
struct ngap_gNB_amf_data_s *amf = select_amf(instance_p, UEfirstReq);
|
||||
if (amf == NULL) {
|
||||
NGAP_WARN("No AMF is associated to the gNB\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Message Type (M)
|
||||
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu.choice.initiatingMessage, head);
|
||||
head->procedureCode = NGAP_ProcedureCode_id_InitialUEMessage;
|
||||
@@ -98,98 +175,18 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
head->value.present = NGAP_InitiatingMessage__value_PR_InitialUEMessage;
|
||||
NGAP_InitialUEMessage_t *out = &head->value.choice.InitialUEMessage;
|
||||
|
||||
/* Select the AMF corresponding to the provided GUAMI. */
|
||||
//TODO have not be test. it's should be test
|
||||
if (UEfirstReq->ue_identity.presenceMask & NGAP_UE_IDENTITIES_guami) {
|
||||
amf_desc_p = ngap_gNB_nnsf_select_amf_by_guami(instance_p, UEfirstReq->establishment_cause, UEfirstReq->ue_identity.guami);
|
||||
|
||||
if (amf_desc_p) {
|
||||
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through GUAMI MCC %d MNC %d AMFRI %d AMFSI %d AMFPT %d\n",
|
||||
UEfirstReq->gNB_ue_ngap_id,
|
||||
amf_desc_p->amf_name,
|
||||
amf_desc_p->assoc_id,
|
||||
UEfirstReq->ue_identity.guami.mcc,
|
||||
UEfirstReq->ue_identity.guami.mnc,
|
||||
UEfirstReq->ue_identity.guami.amf_region_id,
|
||||
UEfirstReq->ue_identity.guami.amf_set_id,
|
||||
UEfirstReq->ue_identity.guami.amf_pointer);
|
||||
}
|
||||
}
|
||||
|
||||
if (amf_desc_p == NULL) {
|
||||
/* Select the AMF corresponding to the provided s-TMSI. */
|
||||
//TODO have not be test. it's should be test
|
||||
if (UEfirstReq->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) {
|
||||
amf_desc_p = ngap_gNB_nnsf_select_amf_by_amf_setid(instance_p, UEfirstReq->establishment_cause, UEfirstReq->selected_plmn_identity, UEfirstReq->ue_identity.s_tmsi.amf_set_id);
|
||||
|
||||
if (amf_desc_p) {
|
||||
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",
|
||||
UEfirstReq->gNB_ue_ngap_id,
|
||||
amf_desc_p->amf_name,
|
||||
amf_desc_p->assoc_id,
|
||||
UEfirstReq->ue_identity.s_tmsi.amf_set_id,
|
||||
UEfirstReq->selected_plmn_identity,
|
||||
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mcc,
|
||||
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mnc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (amf_desc_p == NULL) {
|
||||
/* Select AMF based on the selected PLMN identity, received through RRC
|
||||
* Connection Setup Complete */
|
||||
//TODO have not be test. it's should be test
|
||||
amf_desc_p = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, UEfirstReq->establishment_cause, UEfirstReq->selected_plmn_identity);
|
||||
|
||||
if (amf_desc_p) {
|
||||
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n",
|
||||
UEfirstReq->gNB_ue_ngap_id,
|
||||
amf_desc_p->amf_name,
|
||||
amf_desc_p->assoc_id,
|
||||
UEfirstReq->selected_plmn_identity,
|
||||
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mcc,
|
||||
instance_p->plmn[UEfirstReq->selected_plmn_identity].plmn.mnc);
|
||||
}
|
||||
}
|
||||
|
||||
if (amf_desc_p == NULL) {
|
||||
/*
|
||||
* If no AMF corresponds to the GUAMI, the s-TMSI, or the selected PLMN
|
||||
* identity, selects the AMF with the highest capacity.
|
||||
*/
|
||||
//TODO have not be test. it's should be test
|
||||
amf_desc_p = ngap_gNB_nnsf_select_amf(instance_p, UEfirstReq->establishment_cause);
|
||||
|
||||
if (amf_desc_p) {
|
||||
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through highest relative capacity\n", UEfirstReq->gNB_ue_ngap_id, amf_desc_p->amf_name, amf_desc_p->assoc_id);
|
||||
}
|
||||
}
|
||||
|
||||
if (amf_desc_p == NULL) {
|
||||
/*
|
||||
* In case gNB has no AMF associated, the gNB should inform RRC and discard
|
||||
* this request.
|
||||
*/
|
||||
NGAP_WARN("No AMF is associated to the gNB\n");
|
||||
// TODO: Inform RRC
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The gNB should allocate a unique gNB UE NGAP ID for this UE. The value
|
||||
* will be used for the duration of the connectivity.
|
||||
*/
|
||||
struct ngap_gNB_ue_context_s *ue_desc_p = calloc(1, sizeof(*ue_desc_p));
|
||||
/* Store the UE context in NGAP with:
|
||||
* selected AMF, selected PLMN identity, gNB ID
|
||||
* the unique gNB UE NGAP ID, used for the duration of the connectivity */
|
||||
struct ngap_gNB_ue_context_s *ue_desc_p = calloc_or_fail(1, sizeof(*ue_desc_p));
|
||||
DevAssert(ue_desc_p != NULL);
|
||||
/* Keep a reference to the selected AMF */
|
||||
ue_desc_p->amf_ref = amf_desc_p;
|
||||
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;
|
||||
|
||||
// insert in master table
|
||||
ue_desc_p->selected_plmn_identity = UEfirstReq->plmn;
|
||||
ngap_store_ue_context(ue_desc_p);
|
||||
|
||||
/* mandatory */
|
||||
// RAN UE NGAP ID (M)
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
|
||||
@@ -197,47 +194,43 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_RAN_UE_NGAP_ID;
|
||||
ie->value.choice.RAN_UE_NGAP_ID = ue_desc_p->gNB_ue_ngap_id;
|
||||
}
|
||||
/* mandatory */
|
||||
|
||||
/* NAS-PDU (M): transferred transparently */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_NAS_PDU;
|
||||
allocCopy(&ie->value.choice.NAS_PDU, UEfirstReq->nas_pdu);
|
||||
OCTET_STRING_fromBuf(&ie->value.choice.NAS_PDU, (const char *)UEfirstReq->nas_pdu.buf, UEfirstReq->nas_pdu.len);
|
||||
}
|
||||
|
||||
/* mandatory */
|
||||
// User Location Information (M)
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_UserLocationInformation;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_InitialUEMessage_IEs__value_PR_UserLocationInformation;
|
||||
|
||||
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);
|
||||
MCC_MNC_TO_TBCD(instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mcc,
|
||||
instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mnc,
|
||||
instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mnc_digit_length,
|
||||
&userinfo_nr_p->nR_CGI.pLMNIdentity);
|
||||
|
||||
/* Set TAI */
|
||||
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,
|
||||
the selected PLMN is indicated by the PLMN Identity IE within the TAI IE */
|
||||
INT24_TO_OCTET_STRING(instance_p->tac, &userinfo_nr_p->tAI.tAC);
|
||||
MCC_MNC_TO_PLMNID(instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mcc,
|
||||
instance_p->plmn[ue_desc_p->selected_plmn_identity].plmn.mnc,
|
||||
instance_p->plmn[ue_desc_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);
|
||||
}
|
||||
|
||||
/* Set the establishment cause according to those provided by RRC */
|
||||
DevCheck(UEfirstReq->establishment_cause < NGAP_RRC_CAUSE_LAST, UEfirstReq->establishment_cause, NGAP_RRC_CAUSE_LAST, 0);
|
||||
|
||||
/* mandatory */
|
||||
// RRC Establishment Cause (M)
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_RRCEstablishmentCause;
|
||||
@@ -246,7 +239,7 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
ie->value.choice.RRCEstablishmentCause = UEfirstReq->establishment_cause;
|
||||
}
|
||||
|
||||
/* optional */
|
||||
// 5G-S-TMSI (O)
|
||||
if (UEfirstReq->ue_identity.presenceMask & NGAP_UE_IDENTITIES_FiveG_s_tmsi) {
|
||||
NGAP_DEBUG("FIVEG_S_TMSI_PRESENT\n");
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
|
||||
@@ -258,7 +251,8 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
M_TMSI_TO_OCTET_STRING(UEfirstReq->ue_identity.s_tmsi.m_tmsi, &ie->value.choice.FiveG_S_TMSI.fiveG_TMSI);
|
||||
}
|
||||
|
||||
/* optional */
|
||||
/* UE Context Request (O): instruct the AMF to trigger an
|
||||
Initial Context Setup procedure towards the NG-RAN node. */
|
||||
{
|
||||
asn1cSequenceAdd(out->protocolIEs.list, NGAP_InitialUEMessage_IEs_t, ie);
|
||||
ie->id = NGAP_ProtocolIE_ID_id_UEContextRequest;
|
||||
@@ -267,10 +261,8 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
ie->value.choice.UEContextRequest = NGAP_UEContextRequest_requested;
|
||||
}
|
||||
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) {
|
||||
/* Failed to encode message */
|
||||
DevMessage("Failed to encode initial UE message\n");
|
||||
}
|
||||
if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0)
|
||||
DevMessage("Failed to encode initial UE message\n");
|
||||
|
||||
/* Update the current NGAP UE state */
|
||||
ue_desc_p->ue_state = NGAP_UE_WAITING_CSR;
|
||||
@@ -286,16 +278,13 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
|
||||
* the stream should not be changed during the communication of the
|
||||
* UE-associated signalling.
|
||||
*/
|
||||
amf_desc_p->nextstream = (amf_desc_p->nextstream + 1) % amf_desc_p->out_streams;
|
||||
|
||||
if ((amf_desc_p->nextstream == 0) && (amf_desc_p->out_streams > 1)) {
|
||||
amf_desc_p->nextstream += 1;
|
||||
amf->nextstream = (amf->nextstream + 1) % amf->out_streams;
|
||||
if ((amf->nextstream == 0) && (amf->out_streams > 1)) {
|
||||
amf->nextstream += 1;
|
||||
}
|
||||
|
||||
ue_desc_p->tx_stream = amf_desc_p->nextstream;
|
||||
ue_desc_p->tx_stream = amf->nextstream;
|
||||
/* Send encoded message over sctp */
|
||||
ngap_gNB_itti_send_sctp_data_req(instance_p->instance, amf_desc_p->assoc_id,
|
||||
buffer, length, ue_desc_p->tx_stream);
|
||||
ngap_gNB_itti_send_sctp_data_req(instance_p->instance, amf->assoc_id, buffer, length, ue_desc_p->tx_stream);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -436,8 +425,8 @@ int ngap_gNB_nas_uplink(instance_t instance, ngap_uplink_nas_t *ngap_uplink_nas_
|
||||
ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU;
|
||||
ie->criticality = NGAP_Criticality_reject;
|
||||
ie->value.present = NGAP_UplinkNASTransport_IEs__value_PR_NAS_PDU;
|
||||
ie->value.choice.NAS_PDU.buf = ngap_uplink_nas_p->nas_pdu.buffer;
|
||||
ie->value.choice.NAS_PDU.size = ngap_uplink_nas_p->nas_pdu.length;
|
||||
ie->value.choice.NAS_PDU.buf = ngap_uplink_nas_p->nas_pdu.buf;
|
||||
ie->value.choice.NAS_PDU.size = ngap_uplink_nas_p->nas_pdu.len;
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
@@ -453,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");
|
||||
@@ -532,8 +516,8 @@ int ngap_gNB_nas_non_delivery_ind(instance_t instance,
|
||||
ie->id = NGAP_ProtocolIE_ID_id_NAS_PDU;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_NASNonDeliveryIndication_IEs__value_PR_NAS_PDU;
|
||||
ie->value.choice.NAS_PDU.buf = ngap_nas_non_delivery_ind->nas_pdu.buffer;
|
||||
ie->value.choice.NAS_PDU.size = ngap_nas_non_delivery_ind->nas_pdu.length;
|
||||
ie->value.choice.NAS_PDU.buf = ngap_nas_non_delivery_ind->nas_pdu.buf;
|
||||
ie->value.choice.NAS_PDU.size = ngap_nas_non_delivery_ind->nas_pdu.len;
|
||||
}
|
||||
/* mandatory */
|
||||
{
|
||||
@@ -861,8 +845,8 @@ int ngap_gNB_ue_capabilities(instance_t instance, ngap_ue_cap_info_ind_t *ue_cap
|
||||
ie->id = NGAP_ProtocolIE_ID_id_UERadioCapability;
|
||||
ie->criticality = NGAP_Criticality_ignore;
|
||||
ie->value.present = NGAP_UERadioCapabilityInfoIndicationIEs__value_PR_UERadioCapability;
|
||||
ie->value.choice.UERadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buffer;
|
||||
ie->value.choice.UERadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.length;
|
||||
ie->value.choice.UERadioCapability.buf = ue_cap_info_ind_p->ue_radio_cap.buf;
|
||||
ie->value.choice.UERadioCapability.size = ue_cap_info_ind_p->ue_radio_cap.len;
|
||||
}
|
||||
/* optional */
|
||||
//NGAP_UERadioCapabilityForPaging TBD
|
||||
@@ -1224,8 +1208,9 @@ int ngap_gNB_pdusession_release_resp(instance_t instance, ngap_pdusession_releas
|
||||
|
||||
for (i = 0; i < pdusession_release_resp_p->nb_of_pdusessions_released; i++) {
|
||||
asn1cSequenceAdd(ie->value.choice.PDUSessionResourceReleasedListRelRes.list, NGAP_PDUSessionResourceReleasedItemRelRes_t, item);
|
||||
item->pDUSessionID = pdusession_release_resp_p->pdusession_release[i].pdusession_id;
|
||||
allocCopy(&item->pDUSessionResourceReleaseResponseTransfer, pdusession_release_resp_p->pdusession_release[i].data);
|
||||
pdusession_release_t *r = &pdusession_release_resp_p->pdusession_release[i];
|
||||
item->pDUSessionID = r->pdusession_id;
|
||||
OCTET_STRING_fromBuf(&item->pDUSessionResourceReleaseResponseTransfer, (const char *)r->data.buf, r->data.len);
|
||||
NGAP_DEBUG("pdusession_release_resp: pdusession ID %ld\n", item->pDUSessionID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,9 +33,7 @@
|
||||
#include "queue.h"
|
||||
#include "tree.h"
|
||||
|
||||
struct ngap_gNB_amf_data_s *
|
||||
ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause)
|
||||
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause)
|
||||
{
|
||||
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
|
||||
struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL;
|
||||
@@ -86,10 +84,9 @@ ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p,
|
||||
return amf_highest_capacity_p;
|
||||
}
|
||||
|
||||
struct ngap_gNB_amf_data_s *
|
||||
ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause,
|
||||
int selected_plmn_identity)
|
||||
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 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;
|
||||
@@ -135,8 +132,7 @@ ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
@@ -156,11 +152,10 @@ ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
|
||||
return amf_highest_capacity_p;
|
||||
}
|
||||
|
||||
struct ngap_gNB_amf_data_s *
|
||||
ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause,
|
||||
int selected_plmn_identity,
|
||||
uint8_t amf_setid)
|
||||
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 plmn_id_t selected_plmn_identity,
|
||||
uint8_t amf_setid)
|
||||
{
|
||||
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
|
||||
|
||||
@@ -207,8 +202,7 @@ ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -234,10 +228,9 @@ ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ngap_gNB_amf_data_s *
|
||||
ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause,
|
||||
ngap_guami_t guami)
|
||||
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
|
||||
const ngap_rrc_establishment_cause_t cause,
|
||||
const nr_guami_t guami)
|
||||
{
|
||||
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
|
||||
|
||||
@@ -327,10 +320,7 @@ ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct ngap_gNB_amf_data_s *
|
||||
ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p,
|
||||
ngap_guami_t guami)
|
||||
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p, const nr_guami_t guami)
|
||||
{
|
||||
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
|
||||
struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL;
|
||||
|
||||
@@ -34,28 +34,21 @@
|
||||
#include "ngap_gNB_defs.h"
|
||||
#include "ngap_messages_types.h"
|
||||
|
||||
struct ngap_gNB_amf_data_s *
|
||||
ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause);
|
||||
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf(ngap_gNB_instance_t *instance_p, const ngap_rrc_establishment_cause_t cause);
|
||||
|
||||
struct ngap_gNB_amf_data_s *
|
||||
ngap_gNB_nnsf_select_amf_by_plmn_id(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause,
|
||||
int selected_plmn_identity);
|
||||
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 plmn_id_t selected_plmn_identity);
|
||||
|
||||
struct ngap_gNB_amf_data_s*
|
||||
ngap_gNB_nnsf_select_amf_by_amf_setid(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause,
|
||||
int selected_plmn_identity,
|
||||
uint8_t amf_setid);
|
||||
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 plmn_id_t selected_plmn_identity,
|
||||
uint8_t amf_setid);
|
||||
|
||||
struct ngap_gNB_amf_data_s*
|
||||
ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
|
||||
ngap_rrc_establishment_cause_t cause,
|
||||
ngap_guami_t guami);
|
||||
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami(ngap_gNB_instance_t *instance_p,
|
||||
const ngap_rrc_establishment_cause_t cause,
|
||||
const nr_guami_t guami);
|
||||
|
||||
struct ngap_gNB_amf_data_s*
|
||||
ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p,
|
||||
ngap_guami_t guami);
|
||||
ngap_gNB_amf_data_t *ngap_gNB_nnsf_select_amf_by_guami_no_cause(ngap_gNB_instance_t *instance_p, const nr_guami_t guami);
|
||||
|
||||
#endif /* NGAP_GNB_NNSF_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;
|
||||
|
||||
Reference in New Issue
Block a user