Compare commits

...

12 Commits

Author SHA1 Message Date
Guido Casati
2e505b7460 Print PLMN identity in registeredAMF if present 2025-03-10 18:38:53 +01:00
Guido Casati
d5648ccba2 Handle both 5G-S-TMSI and GUAMI in the NGAP Initial UE Message procedures
* use bitmask to select presence of either 5G-S-TMSI or GUAMI
* select the AMF based on
(1) absence of UE Identity (2) Presence of GUAMI (3) Presence of 5G-S-TMSI

Related to #801
2025-03-10 18:38:53 +01:00
Guido Casati
f69353f684 Refactor and cleanup rrc_gNB_send_NGAP_NAS_FIRST_REQ
* add function to process AMF Identifier
* add function to select AMF
* set const parameters in utility nnsf functions
* adopt utilities for memory allocation
* improve readability and maintainability
* improve logging
2025-03-10 18:38:53 +01:00
Guido Casati
2cca2920c1 Replace ngap_pdu_t with byte_array_t 2025-03-10 18:38:53 +01:00
Guido Casati
96cf72433b Add guami_t to ngran_types.h
* refactor NGAP and RRC code to use one common GUAMI type
  instead of two identical ones
2025-03-10 18:38:53 +01:00
Guido Casati
214379da8c Minor improvements to ngap_gNB_register_amf
* use calloc_or_fail
* check array boundaries
* improve logging
2025-03-10 18:38:52 +01:00
Guido Casati
48fdbb0939 Remove obsolete code in ngap_gNB_handle_error_indication 2025-03-10 18:38:52 +01:00
Guido Casati
bd83a7754d Use decode_ng_setup_response in stack 2025-03-10 18:38:52 +01:00
Guido Casati
ae1d943550 Add library file for NGAP Interface Management enc/dec
* Improve NG Setup Request: use calloc_or_fail,
  explicit memory allocation, improve logging, formatting
* Add NG Setup Response decoder
* Add message type for NG Setup Response
* Move NG Overload Procedures to NGAP Interface Management lib
* Move NG Setup Request to NGAP Interface Management lib
2025-03-10 18:38:52 +01:00
Guido Casati
cd2f2d9722 Bugfix in ngap_gNB_handle_ng_setup_response: use correct count for PLMNSupportList 2025-03-10 18:38:52 +01:00
Guido Casati
d1e5b14fd3 Migrate ngap_gNB_ue_context.c content to NGAP utils
* the original content represents utility functions to handle
  the UE context in NGAP, so they can be migrated to the utils file
* the goal is to restructure the NGAP library,
  reduce the number of files, improve maintainability
* also the original naming ngap_gNB_ue_context can be misleading
  and be confused with the NGAP UE Context Management library
2025-03-10 18:33:47 +01:00
Guido Casati
d0e4ddda7e Refactor ngap_gNB_management_procedures.c/.h
* updated the naming to reflect the content of the file, i.e. utility
  NGAP library functions. The NGAP Interface Management library
  shall contain the functions related to the message in 9.2.6 of 3GPP TS 38.413
* cleaned up unused functions
2025-03-10 16:08:21 +01:00
23 changed files with 744 additions and 940 deletions

View File

@@ -352,12 +352,11 @@ add_library(ngap
${NGAP_DIR}/ngap_gNB_encoder.c
${NGAP_DIR}/ngap_gNB_handlers.c
${NGAP_DIR}/ngap_gNB_itti_messaging.c
${NGAP_DIR}/ngap_gNB_management_procedures.c
${NGAP_DIR}/ngap_gNB_utils.c
${NGAP_DIR}/ngap_gNB_nas_procedures.c
${NGAP_DIR}/ngap_gNB_nnsf.c
${NGAP_DIR}/ngap_gNB_overload.c
${NGAP_DIR}/ngap_gNB_interface_management.c
${NGAP_DIR}/ngap_gNB_trace.c
${NGAP_DIR}/ngap_gNB_ue_context.c
)
target_link_libraries(ngap PUBLIC asn1_ngap)
target_link_libraries(ngap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)

1
NOTES.md Normal file
View File

@@ -0,0 +1 @@
* consider to use plmn_identity_t instead of ngap_plmn_identity_t

View File

@@ -29,6 +29,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

View File

@@ -30,6 +30,8 @@
* \warning
*/
#include <stdint.h>
#ifndef __NGRAN_TYPES_H__
#define __NGRAN_TYPES_H__

View File

@@ -1040,12 +1040,12 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB_default_values.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/S1AP/s1ap_eNB.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_nnsf.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_management_procedures.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_utils.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_nnsf.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_management_procedures.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_utils.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_context_management_procedures.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_nas_procedures.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_overload.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_interface_management.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_ue_context.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_handlers.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB.c \
@@ -1064,7 +1064,7 @@ INPUT = \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_nas_procedures.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_decoder.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_ue_context.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_overload.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_interface_management.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NGAP/ngap_gNB_default_values.h \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/SECU/secu_defs.c \
@CMAKE_CURRENT_SOURCE_DIR@/../openair3/SECU/sha_256_hmac.h \

View File

@@ -34,6 +34,7 @@
#include "common/platform_types.h"
#include "common/5g_platform_types.h"
#include "s1ap_messages_types.h"
#include "common/utils/ds/byte_array.h"
// Defines to access message fields.
#define NGAP_REGISTER_GNB_REQ(mSGpTR) (mSGpTR)->ittiMsg.ngap_register_gnb_req
@@ -202,15 +203,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;
@@ -236,16 +228,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;
@@ -261,8 +246,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];
@@ -522,7 +507,7 @@ typedef struct ngap_nas_first_req_s {
ngap_rrc_establishment_cause_t establishment_cause;
/* NAS PDU */
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
/* If this flag is set NGAP layer is expecting the GUAMI. If = 0,
* the temporary s-tmsi is used.
@@ -534,12 +519,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 {
@@ -566,7 +551,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;
@@ -604,7 +589,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;
@@ -618,7 +603,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;
@@ -641,7 +626,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;
@@ -670,8 +655,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 {
@@ -724,7 +709,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 */
@@ -797,7 +782,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 {
@@ -845,7 +830,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;

View File

@@ -92,15 +92,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,
@@ -223,7 +214,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
@@ -253,7 +245,7 @@ typedef struct gNB_RRC_UE_s {
pdusession_t *initial_pdus;
/* Nas Pdu */
ngap_pdu_t nas_pdu;
byte_array_t nas_pdu;
} gNB_RRC_UE_t;

View File

@@ -121,12 +121,12 @@ static void rrc_deliver_ue_ctxt_release_cmd(void *deliver_pdu_data, ue_id_t ue_i
///---------------------------------------------------------------------------------------------------------------///
///---------------------------------------------------------------------------------------------------------------///
static void clear_nas_pdu(ngap_pdu_t *pdu)
static void clear_nas_pdu(byte_array_t *pdu)
{
DevAssert(pdu != NULL);
free(pdu->buffer); // does nothing if NULL
pdu->buffer = NULL;
pdu->length = 0;
free(pdu->buf);
pdu->buf = NULL;
pdu->len = 0;
}
static void freeDRBlist(NR_DRB_ToAddModList_t *list)
@@ -537,13 +537,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) {
@@ -551,9 +549,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 */
@@ -585,16 +583,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;
}
@@ -602,21 +601,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
@@ -630,27 +629,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);
}
}
@@ -1429,20 +1424,20 @@ 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;
nr_rrc_transfer_protected_rrc_message(rrc, UE, srb_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)

View File

@@ -82,6 +82,7 @@
#include "rrc_messages_types.h"
#include "s1ap_messages_types.h"
#include "uper_encoder.h"
#include "ngap_gNB_interface_management.h"
#ifdef E2_AGENT
#include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h"
@@ -149,32 +150,38 @@ 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 void process_amf_Identifier(uint32_t amf_Id, nr_guami_t *guami)
{
guami->amf_region_id = (amf_Id >> 16) & 0xff;
guami->amf_set_id = (amf_Id >> 6) & 0x3ff;
guami->amf_pointer = amf_Id & 0x3f;
}
/**
* @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.len = rrcSetupComplete->dedicatedNAS_Message.size;
req->nas_pdu.buf = malloc_or_fail(req->nas_pdu.len);
memcpy(req->nas_pdu.buf, rrcSetupComplete->dedicatedNAS_Message.buf, req->nas_pdu.len);
// Selected PLMN Identity: indicates the selected PLMN id for the non-3GPP access
/* selected_plmn_identity: IE is 1-based, convert to 0-based (C array) */
int selected_plmn_identity = rrcSetupComplete->selectedPLMN_Identity - 1;
if (selected_plmn_identity != 0)
@@ -182,34 +189,41 @@ void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRC
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;
process_amf_Identifier(amf_Id, &req->ue_identity.guami);
UE->ue_guami = req->ue_identity.guami;
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);
// PLMN Identity
if (r_amf->plmn_Identity) {
char mnc_str[r_amf->plmn_Identity->mnc.list.count + 1];
for (int i = 0; i < r_amf->plmn_Identity->mnc.list.count; i++) {
mnc_str[i] = *r_amf->plmn_Identity->mnc.list.array[i];
}
mnc_str[r_amf->plmn_Identity->mnc.list.count] = '\0';
LOG_D(NGAP, "PLMN identity with MNC %s in the registeredAMF is present for RNTI %04x\n", mnc_str, UE->rnti);
}
}
itti_send_msg_to_task(TASK_NGAP, rrc->module_id, message_p);
@@ -249,7 +263,7 @@ 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);
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");
@@ -492,14 +506,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()
@@ -714,8 +722,8 @@ 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.len = req->nas_pdu.len;
msg->nas_pdu.buf = req->nas_pdu.buf;
// TODO add failure cause when defined!
itti_send_msg_to_task(TASK_NGAP, instance, msg_fail_p);
return (-1);
@@ -747,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);
}
@@ -915,10 +923,10 @@ 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");
@@ -1017,7 +1025,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
@@ -1288,8 +1296,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");
}
@@ -1372,7 +1380,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);

View File

@@ -48,12 +48,13 @@
#include "ngap_common.h"
#include "ngap_gNB.h"
#include "ngap_gNB_context_management_procedures.h"
#include "ngap_gNB_interface_management.h"
#include "ngap_gNB_default_values.h"
#include "ngap_gNB_defs.h"
#include "ngap_gNB_encoder.h"
#include "ngap_gNB_handlers.h"
#include "ngap_gNB_itti_messaging.h"
#include "ngap_gNB_management_procedures.h"
#include "ngap_gNB_utils.h"
#include "ngap_gNB_nas_procedures.h"
#include "ngap_messages_types.h"
#include "oai_asn1.h"
@@ -67,9 +68,6 @@
#include "oaisim_amf_test_s1c.h"
#endif
static int ngap_gNB_generate_ng_setup_request(
ngap_gNB_instance_t *instance_p, ngap_gNB_amf_data_t *ngap_amf_data_p);
void ngap_gNB_handle_register_gNB(instance_t instance, ngap_register_gnb_req_t *ngap_register_gNB);
void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp);
@@ -116,11 +114,14 @@ static void ngap_gNB_register_amf(ngap_gNB_instance_t *instance_p,
memcpy(&sctp_new_association_req_p->local_address,
local_ip_addr,
sizeof(*local_ip_addr));
NGAP_INFO("[gNB %ld] check the amf registration state\n",instance_p->instance);
NGAP_INFO("Registering AMF: IP=%s, in_streams=%d, out_streams=%d\n",
amf_ip_address->ipv4_address,
in_streams,
out_streams);
/* Create new AMF descriptor */
ngap_amf_data_p = calloc(1, sizeof(*ngap_amf_data_p));
DevAssert(ngap_amf_data_p != NULL);
ngap_amf_data_p = calloc_or_fail(1, sizeof(*ngap_amf_data_p));
ngap_amf_data_p->cnx_id = ngap_gNB_fetch_add_global_cnx_id();
sctp_new_association_req_p->ulp_cnx_id = ngap_amf_data_p->cnx_id;
ngap_amf_data_p->assoc_id = -1;
@@ -128,8 +129,12 @@ static void ngap_gNB_register_amf(ngap_gNB_instance_t *instance_p,
memcpy(&ngap_amf_data_p->amf_s1_ip,
amf_ip_address,
sizeof(*amf_ip_address));
for (int i = 0; i < broadcast_plmn_num; ++i)
ngap_amf_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i];
for (int i = 0; i < broadcast_plmn_num; ++i) {
if (i < sizeofArray(ngap_amf_data_p->broadcast_plmn_index))
ngap_amf_data_p->broadcast_plmn_index[i] = broadcast_plmn_index[i];
else
NGAP_WARN("Broadcast PLMN index %d out of bounds, ignoring\n", i);
}
ngap_amf_data_p->ngap_gNB_instance = instance_p;
STAILQ_INIT(&ngap_amf_data_p->served_guami);
@@ -258,7 +263,7 @@ void ngap_gNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
ngap_amf_data_p->out_streams = sctp_new_association_resp->out_streams;
/* Prepare new NG Setup Request */
LOG_A(NGAP, "Send NGSetupRequest to AMF\n");
ngap_gNB_generate_ng_setup_request(instance_p, ngap_amf_data_p);
encode_ng_setup_request(instance_p, ngap_amf_data_p);
}
static
@@ -385,125 +390,3 @@ void *ngap_gNB_task(void *arg) {
return NULL;
}
//-----------------------------------------------------------------------------
/*
* gNB generate a NG setup request towards AMF
*/
static int ngap_gNB_generate_ng_setup_request(
ngap_gNB_instance_t *instance_p,
ngap_gNB_amf_data_t *ngap_amf_data_p)
//-----------------------------------------------------------------------------
{
NGAP_NGAP_PDU_t pdu;
NGAP_NGSetupRequest_t *out = NULL;
NGAP_NGSetupRequestIEs_t *ie = NULL;
NGAP_SupportedTAItem_t *ta = NULL;
NGAP_BroadcastPLMNItem_t *plmn = NULL;
NGAP_SliceSupportItem_t *ssi = NULL;
uint8_t *buffer = NULL;
uint32_t len = 0;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(ngap_amf_data_p != NULL);
ngap_amf_data_p->state = NGAP_GNB_STATE_WAITING;
/* Prepare the NGAP message to encode */
memset(&pdu, 0, sizeof(pdu));
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage = CALLOC(1, sizeof(struct NGAP_InitiatingMessage));
pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_NGSetup;
pdu.choice.initiatingMessage->criticality = NGAP_Criticality_reject;
pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_NGSetupRequest;
out = &pdu.choice.initiatingMessage->value.choice.NGSetupRequest;
/* mandatory */
ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
ie->id = NGAP_ProtocolIE_ID_id_GlobalRANNodeID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_NGSetupRequestIEs__value_PR_GlobalRANNodeID;
ie->value.choice.GlobalRANNodeID.present = NGAP_GlobalRANNodeID_PR_globalGNB_ID;
ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID = CALLOC(1, sizeof(struct NGAP_GlobalGNB_ID));
MCC_MNC_TO_PLMNID(instance_p->plmn[ngap_amf_data_p->broadcast_plmn_index[0]].mcc,
instance_p->plmn[ngap_amf_data_p->broadcast_plmn_index[0]].mnc,
instance_p->plmn[ngap_amf_data_p->broadcast_plmn_index[0]].mnc_digit_length,
&(ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->pLMNIdentity));
ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.present = NGAP_GNB_ID_PR_gNB_ID;
MACRO_GNB_ID_TO_BIT_STRING(instance_p->gNB_id,
&ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID);
NGAP_INFO("%u -> %02x%02x%02x%02x\n", instance_p->gNB_id,
ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[0],
ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[1],
ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[2],
ie->value.choice.GlobalRANNodeID.choice.globalGNB_ID->gNB_ID.choice.gNB_ID.buf[3]);
asn1cSeqAdd(&out->protocolIEs.list, ie);
/* optional */
if (instance_p->gNB_name) {
ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
ie->id = NGAP_ProtocolIE_ID_id_RANNodeName;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_NGSetupRequestIEs__value_PR_RANNodeName;
OCTET_STRING_fromBuf(&ie->value.choice.RANNodeName, instance_p->gNB_name,
strlen(instance_p->gNB_name));
asn1cSeqAdd(&out->protocolIEs.list, ie);
}
/* mandatory */
ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
ie->id = NGAP_ProtocolIE_ID_id_SupportedTAList;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_NGSetupRequestIEs__value_PR_SupportedTAList;
{
ta = (NGAP_SupportedTAItem_t *)calloc(1, sizeof(NGAP_SupportedTAItem_t));
INT24_TO_OCTET_STRING(instance_p->tac, &ta->tAC);
{
for (int i = 0; i < ngap_amf_data_p->broadcast_plmn_num; ++i) {
plmn = (NGAP_BroadcastPLMNItem_t *)calloc(1, sizeof(NGAP_BroadcastPLMNItem_t));
ngap_plmn_t *plmn_req = &instance_p->plmn[ngap_amf_data_p->broadcast_plmn_index[i]];
MCC_MNC_TO_TBCD(plmn_req->mcc, plmn_req->mnc, plmn_req->mnc_digit_length, &plmn->pLMNIdentity);
for (int si = 0; si < plmn_req->num_nssai; si++) {
ssi = (NGAP_SliceSupportItem_t *)calloc(1, sizeof(NGAP_SliceSupportItem_t));
INT8_TO_OCTET_STRING(plmn_req->s_nssai[si].sst, &ssi->s_NSSAI.sST);
const uint32_t sd = plmn_req->s_nssai[si].sd;
if (sd != 0xffffff) {
ssi->s_NSSAI.sD = calloc(1, sizeof(NGAP_SD_t));
ssi->s_NSSAI.sD->buf = calloc(3, sizeof(uint8_t));
ssi->s_NSSAI.sD->size = 3;
ssi->s_NSSAI.sD->buf[0] = (sd & 0xff0000) >> 16;
ssi->s_NSSAI.sD->buf[1] = (sd & 0x00ff00) >> 8;
ssi->s_NSSAI.sD->buf[2] = (sd & 0x0000ff);
}
asn1cSeqAdd(&plmn->tAISliceSupportList.list, ssi);
}
asn1cSeqAdd(&ta->broadcastPLMNList.list, plmn);
}
}
asn1cSeqAdd(&ie->value.choice.SupportedTAList.list, ta);
}
asn1cSeqAdd(&out->protocolIEs.list, ie);
/* mandatory */
ie = (NGAP_NGSetupRequestIEs_t *)calloc(1, sizeof(NGAP_NGSetupRequestIEs_t));
ie->id = NGAP_ProtocolIE_ID_id_DefaultPagingDRX;
ie->criticality = NGAP_Criticality_ignore;
ie->value.present = NGAP_NGSetupRequestIEs__value_PR_PagingDRX;
ie->value.choice.PagingDRX = instance_p->default_drx;
asn1cSeqAdd(&out->protocolIEs.list, ie);
if (ngap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) {
NGAP_ERROR("Failed to encode NG setup request\n");
return -1;
}
/* Non UE-Associated signalling -> stream = 0 */
ngap_gNB_itti_send_sctp_data_req(instance_p->instance, ngap_amf_data_p->assoc_id, buffer, len, 0);
return ret;
}

View File

@@ -42,8 +42,7 @@
#include "ngap_gNB_defs.h"
#include "ngap_gNB_encoder.h"
#include "ngap_gNB_itti_messaging.h"
#include "ngap_gNB_management_procedures.h"
#include "ngap_gNB_ue_context.h"
#include "ngap_gNB_utils.h"
#include "oai_asn1.h"
int ngap_ue_context_release_complete(instance_t instance,

View File

@@ -31,6 +31,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include "INTEGER.h"
#include "ngap_msg_includes.h"
@@ -45,21 +46,21 @@
#include "ngap_common.h"
#include "ngap_gNB_decoder.h"
#include "ngap_gNB_defs.h"
#include "ngap_gNB_management_procedures.h"
#include "ngap_gNB_utils.h"
#include "ngap_gNB_nas_procedures.h"
#include "ngap_gNB_interface_management.h"
#include "ngap_gNB_trace.h"
#include "ngap_gNB_ue_context.h"
#include "ngap_messages_types.h"
#include "oai_asn1.h"
#include "queue.h"
static void allocCopy(ngap_pdu_t *out, OCTET_STRING_t in)
static void allocCopy(byte_array_t *out, const OCTET_STRING_t in)
{
if (in.size) {
out->buffer = malloc(in.size);
memcpy(out->buffer, in.buf, in.size);
out->buf = malloc_or_fail(in.size);
memcpy(out->buf, in.buf, in.size);
}
out->length = in.size;
out->len = in.size;
}
char *ngap_direction2String(int ngap_dir) {
@@ -146,14 +147,36 @@ static int ngap_gNB_handle_ng_setup_failure(sctp_assoc_t assoc_id, uint32_t stre
return 0;
}
static void update_amf_info(ngap_gNB_amf_data_t *amf_desc_p, ng_setup_response_t *msg)
{
for (int i = 0; i < msg->num_guami; i++) {
STAILQ_INSERT_TAIL(&amf_desc_p->served_guami, &msg->guami[i], next);
}
amf_desc_p->relative_amf_capacity = msg->relative_amf_capacity;
if (msg->amf_name) {
amf_desc_p->amf_name = strdup(msg->amf_name);
}
STAILQ_INIT(&amf_desc_p->plmn_supports);
for (int i = 0; i < msg->num_plmn; i++) {
STAILQ_INSERT_TAIL(&amf_desc_p->plmn_supports, &msg->plmn[i], next);
}
/* The association is now ready as gNB and AMF know parameters of each other.
* Mark the association as UP to enable UE contexts creation.
*/
amf_desc_p->state = NGAP_GNB_STATE_CONNECTED;
amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb++;
}
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;
NGAP_NGSetupResponseIEs_t *ie;
ngap_gNB_amf_data_t *amf_desc_p;
int i;
DevAssert(pdu != NULL);
container = &pdu->choice.successfulOutcome->value.choice.NGSetupResponse;
NGAP_NGSetupResponse_t *container = &pdu->choice.successfulOutcome->value.choice.NGSetupResponse;
/* NG Setup Response == Non UE-related procedure -> stream 0 */
if (stream != 0) {
@@ -168,132 +191,14 @@ static int ngap_gNB_handle_ng_setup_response(sctp_assoc_t assoc_id, uint32_t str
return -1;
}
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_ServedGUAMIList, true);
/* 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);
for (i = 0; i < ie->value.choice.ServedGUAMIList.list.count; i++) {
NGAP_ServedGUAMIItem_t *guami_item_p;
struct served_guami_s *new_guami_p;
guami_item_p = ie->value.choice.ServedGUAMIList.list.array[i];
new_guami_p = calloc(1, sizeof(struct served_guami_s));
STAILQ_INIT(&new_guami_p->served_plmns);
STAILQ_INIT(&new_guami_p->served_region_ids);
STAILQ_INIT(&new_guami_p->amf_set_ids);
STAILQ_INIT(&new_guami_p->amf_pointers);
NGAP_PLMNIdentity_t *plmn_identity_p;
struct plmn_identity_s *new_plmn_identity_p;
plmn_identity_p = &guami_item_p->gUAMI.pLMNIdentity;
new_plmn_identity_p = calloc(1, sizeof(struct plmn_identity_s));
TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc,
new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length);
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);
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);
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);
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);
ng_setup_response_t msg = {0};
if (decode_ng_setup_response(&msg, container) < 0) {
NGAP_ERROR("Failed to decode NG Setup Response");
return -1;
}
/* Set the capacity of this AMF */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_RelativeAMFCapacity, true);
update_amf_info(amf_desc_p, &msg);
amf_desc_p->relative_amf_capacity = ie->value.choice.RelativeAMFCapacity;
/* mandatory set the amf name */
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_AMFName, true);
if (ie) {
amf_desc_p->amf_name = malloc(ie->value.choice.AMFName.size + 1);
memcpy(amf_desc_p->amf_name, ie->value.choice.AMFName.buf, ie->value.choice.AMFName.size);
amf_desc_p->amf_name[ie->value.choice.AMFName.size] = '\0';
}
/* mandatory set the plmn supports */
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++) {
NGAP_PLMNSupportItem_t *plmn_support_item_p;
struct plmn_support_s *new_plmn_support_p;
NGAP_SliceSupportItem_t *slice_support_item_p;
struct slice_support_s *new_slice_support_p;
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);
DevAssert(plmn_support_item_p->sliceSupportList.list.count > 0);
DevAssert(plmn_support_item_p->sliceSupportList.list.count <= NGAP_maxnoofSliceItems);
STAILQ_INIT(&new_plmn_support_p->slice_supports);
for(int j=0; j<plmn_support_item_p->sliceSupportList.list.count; j++) {
slice_support_item_p = plmn_support_item_p->sliceSupportList.list.array[j];
new_slice_support_p = calloc(1, sizeof(struct slice_support_s));
OCTET_STRING_TO_INT8(&slice_support_item_p->s_NSSAI.sST, new_slice_support_p->sST);
if(slice_support_item_p->s_NSSAI.sD != NULL) {
new_slice_support_p->sD_flag = 1;
new_slice_support_p->sD[0] = slice_support_item_p->s_NSSAI.sD->buf[0];
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];
}
STAILQ_INSERT_TAIL(&new_plmn_support_p->slice_supports, new_slice_support_p, next);
}
STAILQ_INSERT_TAIL(&amf_desc_p->plmn_supports, new_plmn_support_p, next);
}
/* The association is now ready as gNB and AMF know parameters of each other.
* Mark the association as UP to enable UE contexts creation.
*/
amf_desc_p->state = NGAP_GNB_STATE_CONNECTED;
amf_desc_p->ngap_gNB_instance->ngap_amf_associated_nb ++;
ngap_handle_ng_setup_message(amf_desc_p, 0);
return 0;
@@ -663,16 +568,9 @@ static int ngap_gNB_handle_error_indication(sctp_assoc_t assoc_id, uint32_t stre
}
}
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_ErrorIndicationIEs_t, ie, container,
NGAP_ProtocolIE_ID_id_CriticalityDiagnostics, false);
if (ie) {
// TODO continue
}
// TODO continue
return 0;
}

View File

@@ -0,0 +1,264 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include "ngap_gNB_interface_management.h"
#include <stdint.h>
#include <stdio.h>
#include "assertions.h"
#include "conversions.h"
#include "utils.h"
#include "ngap_gNB_encoder.h"
#include "ngap_common.h"
#include "ngap_gNB_defs.h"
#include "ngap_gNB_utils.h"
#include "ngap_msg_includes.h"
#include "ngap_gNB_itti_messaging.h"
#include "oai_asn1.h"
/**************
* NGAP SETUP *
**************/
/** @brief NG Setup: encode NG Setup Request towards AMF (8.7.1. of 3GPP TS 38.413) */
int encode_ng_setup_request(ngap_gNB_instance_t *instance_p, ngap_gNB_amf_data_t *amf)
{
NGAP_NGAP_PDU_t pdu;
uint8_t *buffer = NULL;
uint32_t len = 0;
DevAssert(instance_p != NULL);
DevAssert(amf != NULL);
ngap_plmn_t *plmn = &instance_p->plmn[amf->broadcast_plmn_index[0]];
NGAP_INFO("Generating NG setup request. PLMN=%03d%02d, TAC=%02x\n", plmn->mcc, plmn->mnc, instance_p->tac);
amf->state = NGAP_GNB_STATE_WAITING;
memset(&pdu, 0, sizeof(pdu));
// Message Type (M)
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
pdu.choice.initiatingMessage = calloc_or_fail(1, sizeof(*pdu.choice.initiatingMessage));
pdu.choice.initiatingMessage->procedureCode = NGAP_ProcedureCode_id_NGSetup;
pdu.choice.initiatingMessage->criticality = NGAP_Criticality_reject;
pdu.choice.initiatingMessage->value.present = NGAP_InitiatingMessage__value_PR_NGSetupRequest;
NGAP_NGSetupRequest_t *out = &pdu.choice.initiatingMessage->value.choice.NGSetupRequest;
// Global RAN Node ID (M)
asn1cSequenceAdd(out->protocolIEs.list, NGAP_NGSetupRequestIEs_t, ie);
ie->id = NGAP_ProtocolIE_ID_id_GlobalRANNodeID;
ie->criticality = NGAP_Criticality_reject;
ie->value.present = NGAP_NGSetupRequestIEs__value_PR_GlobalRANNodeID;
NGAP_GlobalRANNodeID_t *id = &ie->value.choice.GlobalRANNodeID;
id->present = NGAP_GlobalRANNodeID_PR_globalGNB_ID;
id->choice.globalGNB_ID = calloc_or_fail(1, sizeof(*id->choice.globalGNB_ID));
MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &(id->choice.globalGNB_ID->pLMNIdentity));
NGAP_GNB_ID_t *gNB_ID = &id->choice.globalGNB_ID->gNB_ID;
gNB_ID->present = NGAP_GNB_ID_PR_gNB_ID;
MACRO_GNB_ID_TO_BIT_STRING(instance_p->gNB_id, &gNB_ID->choice.gNB_ID);
NGAP_INFO("[gNB %u] Global RAN Node ID (gNB ID): %02x%02x%02x%02x\n",
instance_p->gNB_id,
gNB_ID->choice.gNB_ID.buf[0],
gNB_ID->choice.gNB_ID.buf[1],
gNB_ID->choice.gNB_ID.buf[2],
gNB_ID->choice.gNB_ID.buf[3]);
// RAN Node Name (O)
if (instance_p->gNB_name) {
asn1cSequenceAdd(out->protocolIEs.list, NGAP_NGSetupRequestIEs_t, ie1);
ie1->id = NGAP_ProtocolIE_ID_id_RANNodeName;
ie1->criticality = NGAP_Criticality_ignore;
ie1->value.present = NGAP_NGSetupRequestIEs__value_PR_RANNodeName;
OCTET_STRING_fromBuf(&ie1->value.choice.RANNodeName, instance_p->gNB_name, strlen(instance_p->gNB_name));
}
// Supported TA List (M)
asn1cSequenceAdd(out->protocolIEs.list, NGAP_NGSetupRequestIEs_t, ie2);
ie2->id = NGAP_ProtocolIE_ID_id_SupportedTAList;
ie2->criticality = NGAP_Criticality_reject;
ie2->value.present = NGAP_NGSetupRequestIEs__value_PR_SupportedTAList;
asn1cSequenceAdd(ie2->value.choice.SupportedTAList.list, NGAP_SupportedTAItem_t, ta);
INT24_TO_OCTET_STRING(instance_p->tac, &ta->tAC);
for (int i = 0; i < amf->broadcast_plmn_num; ++i) {
asn1cSequenceAdd(ta->broadcastPLMNList.list, NGAP_BroadcastPLMNItem_t, p);
ngap_plmn_t *plmn_req = &instance_p->plmn[amf->broadcast_plmn_index[i]];
MCC_MNC_TO_TBCD(plmn_req->mcc, plmn_req->mnc, plmn_req->mnc_digit_length, &p->pLMNIdentity);
for (int si = 0; si < plmn_req->num_nssai; si++) {
asn1cSequenceAdd(p->tAISliceSupportList.list, NGAP_SliceSupportItem_t, ssi);
INT8_TO_OCTET_STRING(plmn_req->s_nssai[si].sst, &ssi->s_NSSAI.sST);
const uint32_t sd = plmn_req->s_nssai[si].sd;
if (sd != 0xffffff) {
ssi->s_NSSAI.sD = calloc_or_fail(1, sizeof(*ssi->s_NSSAI.sD));
ssi->s_NSSAI.sD->buf = calloc_or_fail(3, sizeof(*ssi->s_NSSAI.sD->buf));
ssi->s_NSSAI.sD->size = 3;
ssi->s_NSSAI.sD->buf[0] = (sd & 0xff0000) >> 16;
ssi->s_NSSAI.sD->buf[1] = (sd & 0x00ff00) >> 8;
ssi->s_NSSAI.sD->buf[2] = (sd & 0x0000ff);
}
}
}
// Default Paging DRX (M)
asn1cSequenceAdd(out->protocolIEs.list, NGAP_NGSetupRequestIEs_t, ie3);
ie3->id = NGAP_ProtocolIE_ID_id_DefaultPagingDRX;
ie3->criticality = NGAP_Criticality_ignore;
ie3->value.present = NGAP_NGSetupRequestIEs__value_PR_PagingDRX;
ie3->value.choice.PagingDRX = instance_p->default_drx;
if (ngap_gNB_encode_pdu(&pdu, &buffer, &len) < 0) {
NGAP_ERROR("Failed to encode NG setup request\n");
return -1;
}
/* Non UE-Associated signalling -> stream = 0 */
ngap_gNB_itti_send_sctp_data_req(instance_p->instance, amf->assoc_id, buffer, len, 0);
return 0;
}
/** @brief NG Setup Response decoder (9.2.6.2 3GPP TS 38.413) */
int decode_ng_setup_response(ng_setup_response_t *out, const NGAP_NGSetupResponse_t *container)
{
NGAP_NGSetupResponseIEs_t *ie;
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, NGAP_ProtocolIE_ID_id_ServedGUAMIList, true);
/* Served GUAMI List (M):
* 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);
out->num_guami = ie->value.choice.ServedGUAMIList.list.count;
for (int i = 0; i < out->num_guami; i++) {
struct served_guami_s *new_guami_p = &out->guami[i];
NGAP_ServedGUAMIItem_t *guami_item_p = ie->value.choice.ServedGUAMIList.list.array[i];
STAILQ_INIT(&new_guami_p->served_plmns);
STAILQ_INIT(&new_guami_p->served_region_ids);
STAILQ_INIT(&new_guami_p->amf_set_ids);
STAILQ_INIT(&new_guami_p->amf_pointers);
NGAP_PLMNIdentity_t *plmn_identity_p = &guami_item_p->gUAMI.pLMNIdentity;
struct plmn_identity_s *new_plmn_identity_p = calloc_or_fail(1, sizeof(struct plmn_identity_s));
TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc, new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length);
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 = &guami_item_p->gUAMI.aMFRegionID;
struct served_region_id_s *new_region_id_p = calloc_or_fail(1, sizeof(struct served_region_id_s));
OCTET_STRING_TO_INT8(amf_region_id_p, new_region_id_p->amf_region_id);
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 = &guami_item_p->gUAMI.aMFSetID;
struct amf_set_id_s *new_amf_set_id_p = calloc_or_fail(1, sizeof(struct amf_set_id_s));
OCTET_STRING_TO_INT16(amf_set_id_p, new_amf_set_id_p->amf_set_id);
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 = &guami_item_p->gUAMI.aMFPointer;
struct amf_pointer_s *new_amf_pointer_p = calloc_or_fail(1, sizeof(struct amf_pointer_s));
OCTET_STRING_TO_INT8(amf_pointer_p, new_amf_pointer_p->amf_pointer);
STAILQ_INSERT_TAIL(&new_guami_p->amf_pointers, new_amf_pointer_p, next);
new_guami_p->nb_amf_pointer++;
}
// Relative AMF Capacity (M)
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RelativeAMFCapacity, true);
out->relative_amf_capacity = ie->value.choice.RelativeAMFCapacity;
// AMF Name (M)
NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_NGSetupResponseIEs_t, ie, container, NGAP_ProtocolIE_ID_id_AMFName, true);
if (ie) {
out->amf_name = malloc_or_fail(ie->value.choice.AMFName.size + 1);
memcpy(out->amf_name, ie->value.choice.AMFName.buf, ie->value.choice.AMFName.size);
out->amf_name[ie->value.choice.AMFName.size] = '\0';
}
/// PLMN Support List (M)
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);
out->num_plmn = ie->value.choice.PLMNSupportList.list.count;
for (int i = 0; i < out->num_plmn; i++) {
NGAP_PLMNSupportItem_t *plmn_support_item_p = ie->value.choice.PLMNSupportList.list.array[i];
struct plmn_support_s *new_plmn_support_p = &out->plmn[i];
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);
DevAssert(plmn_support_item_p->sliceSupportList.list.count > 0);
DevAssert(plmn_support_item_p->sliceSupportList.list.count <= NGAP_maxnoofSliceItems);
STAILQ_INIT(&new_plmn_support_p->slice_supports);
for (int j = 0; j < plmn_support_item_p->sliceSupportList.list.count; j++) {
NGAP_SliceSupportItem_t *slice_support_item_p = plmn_support_item_p->sliceSupportList.list.array[j];
struct slice_support_s *new_slice_support_p = calloc_or_fail(1, sizeof(*new_slice_support_p));
OCTET_STRING_TO_INT8(&slice_support_item_p->s_NSSAI.sST, new_slice_support_p->sST);
if (slice_support_item_p->s_NSSAI.sD != NULL) {
new_slice_support_p->sD_flag = 1;
new_slice_support_p->sD[0] = slice_support_item_p->s_NSSAI.sD->buf[0];
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];
}
STAILQ_INSERT_TAIL(&new_plmn_support_p->slice_supports, new_slice_support_p, next);
}
}
return 0;
}
/*****************
* NGAP OVERLOAD *
*****************/
int ngap_gNB_handle_overload_stop(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
/* We received Overload stop message, meaning that the AMF is no more
* overloaded. This is an empty message, with only message header and no
* Information Element.
*/
DevAssert(pdu != NULL);
ngap_gNB_amf_data_t *amf_desc_p;
/* Non UE-associated signalling -> stream 0 */
DevCheck(stream == 0, stream, 0, 0);
if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
/* No AMF context associated */
return -1;
}
amf_desc_p->state = NGAP_GNB_STATE_CONNECTED;
amf_desc_p->overload_state = NGAP_NO_OVERLOAD;
return 0;
}

View File

@@ -19,36 +19,31 @@
* contact@openairinterface.org
*/
/*! \file ngap_gNB_overload.h
* \brief ngap procedures for overload messages within gNB
* \author Yoshio INOUE, Masayuki HARADA
* \date 2020
* \version 0.1
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
*/
#ifndef NGAP_GNB_OVERLOAD_H_
#define NGAP_GNB_OVERLOAD_H_
#ifndef NGAP_GNB_INTERFACE_MANAGEMENT_H_
#define NGAP_GNB_INTERFACE_MANAGEMENT_H_
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <stdint.h>
#include "NGAP_NGAP-PDU.h"
#include "ngap_gNB_defs.h"
#include "ngap_msg_includes.h"
/**
* \brief Handle an overload start message
**/
// int ngap_gNB_handle_overload_start(gNB_amf_desc_t *gNB_desc_p,
// sctp_queue_item_t *packet_p,
// struct ngap_message_s *message_p);
int ngap_gNB_handle_overload_start(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu);
#define MAX_NUM_SERVED_GUAMI 256
#define MAX_NUM_PLMN 12
typedef struct {
struct served_guami_s guami[MAX_NUM_SERVED_GUAMI];
int num_guami;
struct plmn_support_s plmn[MAX_NUM_PLMN];
int num_plmn;
long relative_amf_capacity;
char *amf_name;
} ng_setup_response_t;
int encode_ng_setup_request(ngap_gNB_instance_t *instance_p, ngap_gNB_amf_data_t *amf);
int decode_ng_setup_response(ng_setup_response_t *out, const NGAP_NGSetupResponse_t *container);
/**
* \brief Handle an overload stop message
**/
// int ngap_gNB_handle_overload_stop(gNB_amf_desc_t *gNB_desc_p,
// sctp_queue_item_t *packet_p,
// struct ngap_message_s *message_p);
int ngap_gNB_handle_overload_stop(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu);
#endif /* NGAP_GNB_OVERLOAD_H_ */
#endif /* NGAP_GNB_INTERFACE_MANAGEMENT_H_ */

View File

@@ -64,9 +64,9 @@ 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.buf = malloc_or_fail(sizeof(uint8_t) * nas_pdu_length);
memcpy(ngap_downlink_nas->nas_pdu.buf, nas_pdu, nas_pdu_length);
ngap_downlink_nas->nas_pdu.len = nas_pdu_length;
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
}

View File

@@ -1,48 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file ngap_gNB_management_procedures.h
* \brief NGAP gNB task
* \author Yoshio INOUE, Masayuki HARADA
* \date 2020
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
* \version 1.0
* @ingroup _ngap
*/
#ifndef NGAP_GNB_MANAGEMENT_PROCEDURES_H_
#define NGAP_GNB_MANAGEMENT_PROCEDURES_H_
struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF(ngap_gNB_instance_t *instance_p, sctp_assoc_t assoc_id, uint16_t cnx_id);
struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF_from_instance(ngap_gNB_instance_t *instance_p);
void ngap_gNB_remove_amf_desc(ngap_gNB_instance_t * instance);
void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p);
ngap_gNB_instance_t *ngap_gNB_get_instance(uint8_t mod_id);
uint16_t ngap_gNB_fetch_add_global_cnx_id(void);
void ngap_gNB_prepare_internal_data(void);
#endif /* NGAP_GNB_MANAGEMENT_PROCEDURES_H_ */

View File

@@ -52,20 +52,19 @@
#include "ngap_gNB_defs.h"
#include "ngap_gNB_encoder.h"
#include "ngap_gNB_itti_messaging.h"
#include "ngap_gNB_management_procedures.h"
#include "ngap_gNB_utils.h"
#include "ngap_gNB_nnsf.h"
#include "ngap_gNB_ue_context.h"
#include "oai_asn1.h"
#include "s1ap_messages_types.h"
#include "xer_encoder.h"
static void allocCopy(OCTET_STRING_t *out, ngap_pdu_t in)
static void allocCopy(OCTET_STRING_t *out, const byte_array_t in)
{
if (in.length) {
out->buf = malloc(in.length);
memcpy(out->buf, in.buffer, in.length);
if (in.len) {
out->buf = malloc_or_fail(in.len);
memcpy(out->buf, in.buf, in.len);
}
out->size = in.length;
out->size = in.len;
}
static void allocAddrCopy(BIT_STRING_t *out, transport_layer_addr_t in)
@@ -78,20 +77,91 @@ 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)
//------------------------------------------------------------------------------
static ngap_gNB_amf_data_t *select_amf(ngap_gNB_instance_t *instance_p, const ngap_nas_first_req_t *msg)
{
ngap_gNB_amf_data_t *amf = NULL;
// No UE identity (5G-S-TMSI or GUAMI) is present
if (msg->ue_identity.presenceMask & NGAP_UE_IDENTITIES_NONE) {
// Select the AMF based on the selected PLMN identity received through RRCSetupComplete
amf = ngap_gNB_nnsf_select_amf_by_plmn_id(instance_p, msg->establishment_cause, msg->selected_plmn_identity);
if (amf) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through selected PLMN Identity index %d MCC %d MNC %d\n",
msg->gNB_ue_ngap_id,
amf->amf_name,
amf->assoc_id,
msg->selected_plmn_identity,
instance_p->plmn[msg->selected_plmn_identity].mcc,
instance_p->plmn[msg->selected_plmn_identity].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;
}
}
}
// Select the AMF corresponding to the GUAMI from the RegisteredAMF IE
if (msg->ue_identity.presenceMask & NGAP_UE_IDENTITIES_guami) {
NGAP_DEBUG("GUAMI is present\n");
const nr_guami_t *guami = &msg->ue_identity.guami;
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->selected_plmn_identity, fgs_tmsi->amf_set_id);
if (amf) {
NGAP_INFO("UE %d: Chose AMF '%s' (assoc_id %d) through S-TMSI AMFSI %d and selected PLMN Identity index %d MCC %d MNC %d\n",
msg->gNB_ue_ngap_id,
amf->amf_name,
amf->assoc_id,
fgs_tmsi->amf_set_id,
msg->selected_plmn_identity,
instance_p->plmn[msg->selected_plmn_identity].mcc,
instance_p->plmn[msg->selected_plmn_identity].mnc);
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_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;
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));
// Message Type (M)
pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage;
asn1cCalloc(pdu.choice.initiatingMessage, head);
head->procedureCode = NGAP_ProcedureCode_id_InitialUEMessage;
@@ -99,75 +169,9 @@ 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].mcc,
instance_p->plmn[UEfirstReq->selected_plmn_identity].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].mcc,
instance_p->plmn[UEfirstReq->selected_plmn_identity].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) {
// AMF selection from the Initial UE message contents
struct ngap_gNB_amf_data_s *amf = select_amf(instance_p, UEfirstReq);
if (amf == NULL) {
/*
* In case gNB has no AMF associated, the gNB should inform RRC and discard
* this request.
@@ -177,21 +181,18 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
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
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;
@@ -199,7 +200,8 @@ 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;
@@ -208,38 +210,39 @@ int ngap_gNB_handle_nas_first_req(instance_t instance, ngap_nas_first_req_t *UEf
allocCopy(&ie->value.choice.NAS_PDU, UEfirstReq->nas_pdu);
}
/* 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].mcc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].mnc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].mnc_digit_length,
ngap_plmn_t *plmn = &instance_p->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);
/* Set TAI */
/* 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].mcc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].mnc,
instance_p->plmn[ue_desc_p->selected_plmn_identity].mnc_digit_length,
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;
@@ -248,7 +251,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);
@@ -260,7 +263,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;
@@ -269,10 +273,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;
@@ -288,16 +290,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;
}
@@ -438,8 +437,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 */
{
@@ -534,8 +533,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 */
{
@@ -863,8 +862,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

View File

@@ -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 int selected_plmn_identity)
{
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
struct ngap_gNB_amf_data_s *amf_highest_capacity_p = NULL;
@@ -156,11 +153,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 int selected_plmn_identity,
uint8_t amf_setid)
{
struct ngap_gNB_amf_data_s *amf_data_p = NULL;
@@ -234,10 +230,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 +322,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;

View File

@@ -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 int 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 int 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_ */

View File

@@ -1,64 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file ngap_gNB_overload.c
* \brief ngap procedures for overload messages within gNB
* \author Yoshio INOUE, Masayuki HARADA
* \date 2020
* \version 0.1
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
*/
#include "ngap_gNB_overload.h"
#include <stdint.h>
#include <stdio.h>
#include "assertions.h"
#include "ngap_gNB_defs.h"
#include "ngap_gNB_management_procedures.h"
int ngap_gNB_handle_overload_start(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
//TODO
return 0;
}
int ngap_gNB_handle_overload_stop(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu)
{
/* We received Overload stop message, meaning that the AMF is no more
* overloaded. This is an empty message, with only message header and no
* Information Element.
*/
DevAssert(pdu != NULL);
ngap_gNB_amf_data_t *amf_desc_p;
/* Non UE-associated signalling -> stream 0 */
DevCheck(stream == 0, stream, 0, 0);
if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) {
/* No AMF context associated */
return -1;
}
amf_desc_p->state = NGAP_GNB_STATE_CONNECTED;
amf_desc_p->overload_state = NGAP_NO_OVERLOAD;
return 0;
}

View File

@@ -1,86 +0,0 @@
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file ngap_gNB_ue_context.c
* \brief ngap UE context management within gNB
* \author Yoshio INOUE, Masayuki HARADA
* \date 2020
* \version 0.1
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
*/
#include "ngap_gNB_ue_context.h"
#include <stdint.h>
#include <stdio.h>
#include "PHY/defs_common.h"
#include "T.h"
#include "common/utils/T/T.h"
#include "ngap_common.h"
#include "tree.h"
/* Tree of UE ordered by gNB_ue_ngap_id's
* NO INSTANCE, the 32 bits id is large enough to handle all UEs, regardless the cell, gNB, ...
*/
static RB_HEAD(ngap_ue_map, ngap_gNB_ue_context_s) ngap_ue_head = RB_INITIALIZER(&ngap_ue_head);
/* Generate the tree management functions prototypes */
RB_PROTOTYPE(ngap_ue_map, ngap_gNB_ue_context_s, entries, ngap_gNB_compare_gNB_ue_ngap_id);
static int ngap_gNB_compare_gNB_ue_ngap_id(struct ngap_gNB_ue_context_s *p1, struct ngap_gNB_ue_context_s *p2)
{
if (p1->gNB_ue_ngap_id > p2->gNB_ue_ngap_id) {
return 1;
}
if (p1->gNB_ue_ngap_id < p2->gNB_ue_ngap_id) {
return -1;
}
return 0;
}
/* Generate the tree management functions */
RB_GENERATE(ngap_ue_map, ngap_gNB_ue_context_s, entries,
ngap_gNB_compare_gNB_ue_ngap_id);
void ngap_store_ue_context(struct ngap_gNB_ue_context_s *ue_desc_p)
{
if (RB_INSERT(ngap_ue_map, &ngap_ue_head, ue_desc_p))
LOG_E(NGAP, "Bug in UE uniq number allocation %u, we try to add a existing UE\n", ue_desc_p->gNB_ue_ngap_id);
return;
}
struct ngap_gNB_ue_context_s *ngap_get_ue_context(uint32_t gNB_ue_ngap_id)
{
ngap_gNB_ue_context_t temp = {.gNB_ue_ngap_id = gNB_ue_ngap_id};
return RB_FIND(ngap_ue_map, &ngap_ue_head, &temp);
}
struct ngap_gNB_ue_context_s *ngap_detach_ue_context(uint32_t gNB_ue_ngap_id)
{
struct ngap_gNB_ue_context_s *tmp = ngap_get_ue_context(gNB_ue_ngap_id);
if (tmp == NULL) {
NGAP_ERROR("Trying to free a NULL UE context, %u\n", gNB_ue_ngap_id);
return NULL;
}
RB_REMOVE(ngap_ue_map, &ngap_ue_head, tmp);
return tmp;
}

View File

@@ -19,15 +19,7 @@
* contact@openairinterface.org
*/
/*! \file ngap_gNB_management_procedures.c
* \brief NGAP gNB task
* \author Yoshio INOUE, Masayuki HARADA
* \date 2020
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
* \version 1.0
* @ingroup _ngap
*/
#include "ngap_gNB_utils.h"
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <stdint.h>
@@ -36,15 +28,80 @@
#include <string.h>
#include "assertions.h"
#include "ngap_gNB_defs.h"
#include "ngap_common.h"
#include "queue.h"
#include "tree.h"
/* NGAP gNB INTERNAL DATA */
static ngap_gNB_internal_data_t ngap_gNB_internal_data;
struct ngap_amf_map;
RB_GENERATE(ngap_amf_map, ngap_gNB_amf_data_s, entry, ngap_gNB_compare_assoc_id);
int ngap_gNB_compare_assoc_id(
struct ngap_gNB_amf_data_s *p1, struct ngap_gNB_amf_data_s *p2)
uint16_t ngap_gNB_fetch_add_global_cnx_id(void)
{
return ++ngap_gNB_internal_data.global_cnx_id;
}
void ngap_gNB_prepare_internal_data(void)
{
memset(&ngap_gNB_internal_data, 0, sizeof(ngap_gNB_internal_data));
STAILQ_INIT(&ngap_gNB_internal_data.ngap_gNB_instances_head);
}
void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p)
{
DevAssert(new_instance_p != NULL);
STAILQ_INSERT_TAIL(&ngap_gNB_internal_data.ngap_gNB_instances_head, new_instance_p, ngap_gNB_entries);
}
struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF(ngap_gNB_instance_t *instance_p, sctp_assoc_t assoc_id, uint16_t cnx_id)
{
struct ngap_gNB_amf_data_s temp;
struct ngap_gNB_amf_data_s *found;
memset(&temp, 0, sizeof(struct ngap_gNB_amf_data_s));
temp.assoc_id = assoc_id;
temp.cnx_id = cnx_id;
if (instance_p == NULL) {
STAILQ_FOREACH(instance_p, &ngap_gNB_internal_data.ngap_gNB_instances_head, ngap_gNB_entries)
{
found = RB_FIND(ngap_amf_map, &instance_p->ngap_amf_head, &temp);
if (found != NULL) {
return found;
}
}
} else {
return RB_FIND(ngap_amf_map, &instance_p->ngap_amf_head, &temp);
}
return NULL;
}
ngap_gNB_instance_t *ngap_gNB_get_instance(instance_t instance)
{
ngap_gNB_instance_t *temp = NULL;
STAILQ_FOREACH(temp, &ngap_gNB_internal_data.ngap_gNB_instances_head, ngap_gNB_entries)
{
if (temp->instance == instance) {
/* Matching occurence */
return temp;
}
}
return NULL;
}
/* ASSOCIATION ID UTILS */
int ngap_gNB_compare_assoc_id(struct ngap_gNB_amf_data_s *p1, struct ngap_gNB_amf_data_s *p2)
{
if (p1->assoc_id == -1) {
if (p1->cnx_id < p2->cnx_id) {
@@ -68,122 +125,52 @@ int ngap_gNB_compare_assoc_id(
return 0;
}
uint16_t ngap_gNB_fetch_add_global_cnx_id(void)
/* UE CONTEXT UTILS */
/* Tree of UE ordered by gNB_ue_ngap_id's
* NO INSTANCE, the 32 bits id is large enough to handle all UEs, regardless the cell, gNB, ...
*/
static RB_HEAD(ngap_ue_map, ngap_gNB_ue_context_s) ngap_ue_head = RB_INITIALIZER(&ngap_ue_head);
/* Generate the tree management functions prototypes */
RB_PROTOTYPE(ngap_ue_map, ngap_gNB_ue_context_s, entries, ngap_gNB_compare_gNB_ue_ngap_id);
static int ngap_gNB_compare_gNB_ue_ngap_id(struct ngap_gNB_ue_context_s *p1, struct ngap_gNB_ue_context_s *p2)
{
return ++ngap_gNB_internal_data.global_cnx_id;
}
void ngap_gNB_prepare_internal_data(void)
{
memset(&ngap_gNB_internal_data, 0, sizeof(ngap_gNB_internal_data));
STAILQ_INIT(&ngap_gNB_internal_data.ngap_gNB_instances_head);
}
void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p)
{
DevAssert(new_instance_p != NULL);
STAILQ_INSERT_TAIL(&ngap_gNB_internal_data.ngap_gNB_instances_head,
new_instance_p, ngap_gNB_entries);
}
struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF(ngap_gNB_instance_t *instance_p, sctp_assoc_t assoc_id, uint16_t cnx_id)
{
struct ngap_gNB_amf_data_s temp;
struct ngap_gNB_amf_data_s *found;
memset(&temp, 0, sizeof(struct ngap_gNB_amf_data_s));
temp.assoc_id = assoc_id;
temp.cnx_id = cnx_id;
if (instance_p == NULL) {
STAILQ_FOREACH(instance_p, &ngap_gNB_internal_data.ngap_gNB_instances_head,
ngap_gNB_entries) {
found = RB_FIND(ngap_amf_map, &instance_p->ngap_amf_head, &temp);
if (found != NULL) {
return found;
}
}
} else {
return RB_FIND(ngap_amf_map, &instance_p->ngap_amf_head, &temp);
if (p1->gNB_ue_ngap_id > p2->gNB_ue_ngap_id) {
return 1;
}
return NULL;
}
struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF_from_instance(
ngap_gNB_instance_t *instance_p)
{
struct ngap_gNB_amf_data_s *amf = NULL;
struct ngap_gNB_amf_data_s *amf_next = NULL;
for (amf = RB_MIN(ngap_amf_map, &instance_p->ngap_amf_head); amf!=NULL ; amf = amf_next) {
amf_next = RB_NEXT(ngap_amf_map, &instance_p->ngap_amf_head, amf);
if (amf->ngap_gNB_instance == instance_p) {
return amf;
}
if (p1->gNB_ue_ngap_id < p2->gNB_ue_ngap_id) {
return -1;
}
return NULL;
return 0;
}
ngap_gNB_instance_t *ngap_gNB_get_instance(instance_t instance)
{
ngap_gNB_instance_t *temp = NULL;
/* Generate the tree management functions */
RB_GENERATE(ngap_ue_map, ngap_gNB_ue_context_s, entries, ngap_gNB_compare_gNB_ue_ngap_id);
STAILQ_FOREACH(temp, &ngap_gNB_internal_data.ngap_gNB_instances_head,
ngap_gNB_entries) {
if (temp->instance == instance) {
/* Matching occurence */
return temp;
}
void ngap_store_ue_context(struct ngap_gNB_ue_context_s *ue_desc_p)
{
if (RB_INSERT(ngap_ue_map, &ngap_ue_head, ue_desc_p))
LOG_E(NGAP, "Bug in UE uniq number allocation %u, we try to add a existing UE\n", ue_desc_p->gNB_ue_ngap_id);
return;
}
struct ngap_gNB_ue_context_s *ngap_get_ue_context(uint32_t gNB_ue_ngap_id)
{
ngap_gNB_ue_context_t temp = {.gNB_ue_ngap_id = gNB_ue_ngap_id};
return RB_FIND(ngap_ue_map, &ngap_ue_head, &temp);
}
struct ngap_gNB_ue_context_s *ngap_detach_ue_context(uint32_t gNB_ue_ngap_id)
{
struct ngap_gNB_ue_context_s *tmp = ngap_get_ue_context(gNB_ue_ngap_id);
if (tmp == NULL) {
NGAP_ERROR("Trying to free a NULL UE context, %u\n", gNB_ue_ngap_id);
return NULL;
}
return NULL;
}
void ngap_gNB_remove_amf_desc(ngap_gNB_instance_t * instance)
{
struct ngap_gNB_amf_data_s *amf = NULL;
struct ngap_gNB_amf_data_s *amfNext = NULL;
struct plmn_identity_s* plmnInfo;
struct served_region_id_s* regionInfo;
struct served_guami_s* guamInfo;
struct amf_set_id_s* amfSet;
struct amf_pointer_s* amfPoint;
for (amf = RB_MIN(ngap_amf_map, &instance->ngap_amf_head); amf; amf = amfNext) {
amfNext = RB_NEXT(ngap_amf_map, &instance->ngap_amf_head, amf);
RB_REMOVE(ngap_amf_map, &instance->ngap_amf_head, amf);
while (!STAILQ_EMPTY(&amf->served_guami)) {
guamInfo = STAILQ_FIRST(&amf->served_guami);
STAILQ_REMOVE_HEAD(&amf->served_guami, next);
while (!STAILQ_EMPTY(&guamInfo->served_plmns)) {
plmnInfo = STAILQ_FIRST(&guamInfo->served_plmns);
STAILQ_REMOVE_HEAD(&guamInfo->served_plmns, next);
free(plmnInfo);
}
while (!STAILQ_EMPTY(&guamInfo->served_region_ids)) {
regionInfo = STAILQ_FIRST(&guamInfo->served_region_ids);
STAILQ_REMOVE_HEAD(&guamInfo->served_region_ids, next);
free(regionInfo);
}
while (!STAILQ_EMPTY(&guamInfo->amf_set_ids)) {
amfSet = STAILQ_FIRST(&guamInfo->amf_set_ids);
STAILQ_REMOVE_HEAD(&guamInfo->amf_set_ids, next);
free(amfSet);
}
while (!STAILQ_EMPTY(&guamInfo->amf_pointers)) {
amfPoint = STAILQ_FIRST(&guamInfo->amf_pointers);
STAILQ_REMOVE_HEAD(&guamInfo->amf_pointers, next);
free(amfPoint);
}
free(guamInfo);
}
free(amf);
}
RB_REMOVE(ngap_ue_map, &ngap_ue_head, tmp);
return tmp;
}

View File

@@ -18,25 +18,25 @@
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file ngap_gNB_ue_context.h
* \brief ngap UE context management within gNB
* \author Yoshio INOUE, Masayuki HARADA
* \date 2020
* \version 0.1
* \email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com (yoshio.inoue%40fujitsu.com%2cmasayuki.harada%40fujitsu.com)
*/
#include <stdint.h>
#include "ngap_gNB_defs.h"
#include "tree.h"
#ifndef NGAP_GNB_UE_CONTEXT_H_
#define NGAP_GNB_UE_CONTEXT_H_
#ifndef NGAP_GNB_UTILS_H_
#define NGAP_GNB_UTILS_H_
// Forward declarations
struct ngap_gNB_amf_data_s;
struct gNB_amf_desc_s;
struct ngap_gNB_amf_data_s *ngap_gNB_get_AMF(ngap_gNB_instance_t *instance_p, sctp_assoc_t assoc_id, uint16_t cnx_id);
void ngap_gNB_insert_new_instance(ngap_gNB_instance_t *new_instance_p);
ngap_gNB_instance_t *ngap_gNB_get_instance(instance_t mod_id);
uint16_t ngap_gNB_fetch_add_global_cnx_id(void);
void ngap_gNB_prepare_internal_data(void);
/* UE CONTEXT MANAGEMENT UTILS */
typedef enum {
/* UE has not been registered to a AMF or UE association has failed. */
@@ -83,4 +83,4 @@ void ngap_store_ue_context(ngap_gNB_ue_context_t *ue_desc_p);
ngap_gNB_ue_context_t *ngap_get_ue_context(uint32_t gNB_ue_ngap_id);
ngap_gNB_ue_context_t *ngap_detach_ue_context(uint32_t gNB_ue_ngap_id);
#endif /* NGAP_GNB_UE_CONTEXT_H_ */
#endif /* NGAP_GNB_UTILS_H_ */