diff --git a/common/5g_platform_types.h b/common/5g_platform_types.h index 6f055e9305..a5b7b7a1fc 100644 --- a/common/5g_platform_types.h +++ b/common/5g_platform_types.h @@ -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 diff --git a/common/utils/ds/byte_array.c b/common/utils/ds/byte_array.c index d6ad97e324..99375bf2aa 100644 --- a/common/utils/ds/byte_array.c +++ b/common/utils/ds/byte_array.c @@ -23,15 +23,21 @@ #include #include +#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) diff --git a/common/utils/ds/byte_array.h b/common/utils/ds/byte_array.h index 18adb33047..e303d38e75 100644 --- a/common/utils/ds/byte_array.h +++ b/common/utils/ds/byte_array.h @@ -28,6 +28,13 @@ #include #include +#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 diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 588d7c5cba..52cd919338 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -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; diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 6cee7e6fa4..7e0789c4ad 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -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; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 213d4a8f8a..78e472ed60 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -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) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 6d0264152a..82aa7b5a86 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -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); diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 97f15ef658..ad8efce5a3 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -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); diff --git a/openair3/NGAP/ngap_gNB_itti_messaging.c b/openair3/NGAP/ngap_gNB_itti_messaging.c index 87eb93c8f6..b640f2e556 100644 --- a/openair3/NGAP/ngap_gNB_itti_messaging.c +++ b/openair3/NGAP/ngap_gNB_itti_messaging.c @@ -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); } diff --git a/openair3/NGAP/ngap_gNB_management_procedures.c b/openair3/NGAP/ngap_gNB_management_procedures.c index 9615dc6b2a..e82fd1401b 100644 --- a/openair3/NGAP/ngap_gNB_management_procedures.c +++ b/openair3/NGAP/ngap_gNB_management_procedures.c @@ -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; diff --git a/openair3/NGAP/ngap_gNB_management_procedures.h b/openair3/NGAP/ngap_gNB_management_procedures.h index fa62f53382..d71480da30 100644 --- a/openair3/NGAP/ngap_gNB_management_procedures.h +++ b/openair3/NGAP/ngap_gNB_management_procedures.h @@ -28,6 +28,8 @@ * @ingroup _ngap */ +#include "ds/byte_array.h" + #ifndef NGAP_GNB_MANAGEMENT_PROCEDURES_H_ #define NGAP_GNB_MANAGEMENT_PROCEDURES_H_ diff --git a/openair3/NGAP/ngap_gNB_nas_procedures.c b/openair3/NGAP/ngap_gNB_nas_procedures.c index a86ba83442..7729ffa4f2 100644 --- a/openair3/NGAP/ngap_gNB_nas_procedures.c +++ b/openair3/NGAP/ngap_gNB_nas_procedures.c @@ -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); } } diff --git a/openair3/NGAP/ngap_gNB_nnsf.c b/openair3/NGAP/ngap_gNB_nnsf.c index e9f23c6401..77cc7866e1 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.c +++ b/openair3/NGAP/ngap_gNB_nnsf.c @@ -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; diff --git a/openair3/NGAP/ngap_gNB_nnsf.h b/openair3/NGAP/ngap_gNB_nnsf.h index bf6c309af0..8a87ecfce2 100644 --- a/openair3/NGAP/ngap_gNB_nnsf.h +++ b/openair3/NGAP/ngap_gNB_nnsf.h @@ -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_ */ diff --git a/openair3/NGAP/ngap_gNB_ue_context.h b/openair3/NGAP/ngap_gNB_ue_context.h index 2ca75141ef..4c0c63239f 100644 --- a/openair3/NGAP/ngap_gNB_ue_context.h +++ b/openair3/NGAP/ngap_gNB_ue_context.h @@ -72,7 +72,7 @@ typedef struct ngap_gNB_ue_context_s { /* Signaled by the UE in RRC Connection Setup Complete and used in NAS Uplink * to route NAS messages correctly. 0-based, not 1-based as in TS 36.331 * 6.2.2 RRC Connection Setup Complete! */ - int selected_plmn_identity; + plmn_id_t selected_plmn_identity; /* Reference to gNB data this UE is attached to */ ngap_gNB_instance_t *gNB_instance;