mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 05:00:31 +00:00
Compare commits
12 Commits
pre-commit
...
ngap-impro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e505b7460 | ||
|
|
d5648ccba2 | ||
|
|
f69353f684 | ||
|
|
2cca2920c1 | ||
|
|
96cf72433b | ||
|
|
214379da8c | ||
|
|
48fdbb0939 | ||
|
|
bd83a7754d | ||
|
|
ae1d943550 | ||
|
|
cd2f2d9722 | ||
|
|
d1e5b14fd3 | ||
|
|
d0e4ddda7e |
@@ -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
1
NOTES.md
Normal file
@@ -0,0 +1 @@
|
||||
* consider to use plmn_identity_t instead of ngap_plmn_identity_t
|
||||
@@ -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
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __NGRAN_TYPES_H__
|
||||
#define __NGRAN_TYPES_H__
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
264
openair3/NGAP/ngap_gNB_interface_management.c
Normal file
264
openair3/NGAP/ngap_gNB_interface_management.c
Normal 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;
|
||||
}
|
||||
@@ -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_ */
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_ */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_ */
|
||||
Reference in New Issue
Block a user