mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-14 13:10:28 +00:00
Compare commits
3 Commits
pre-commit
...
xn-handove
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14e75d44b8 | ||
|
|
5276af5a20 | ||
|
|
d350813138 |
@@ -456,6 +456,17 @@ add_library(x2ap
|
||||
target_link_libraries(x2ap PUBLIC asn1_x2ap)
|
||||
target_link_libraries(x2ap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
|
||||
|
||||
#XNAP
|
||||
##############
|
||||
set(XNAP_DIR ${OPENAIR2_DIR}/XNAP)
|
||||
add_library(xnap
|
||||
${XNAP_DIR}/xnap_common.c
|
||||
)
|
||||
target_include_directories(xnap PUBLIC XNAP_DIR)
|
||||
target_link_libraries(xnap PUBLIC asn1_xnap)
|
||||
target_link_libraries(xnap PRIVATE xnap_lib)
|
||||
target_include_directories(xnap PRIVATE ${XNAP_DIR}/lib)
|
||||
|
||||
# F1AP
|
||||
##############
|
||||
set(F1AP_DIR ${OPENAIR2_DIR}/F1AP)
|
||||
|
||||
@@ -162,6 +162,7 @@ static const char *const flag_name[] = {FOREACH_FLAG(FLAG_TEXT) ""};
|
||||
COMP_DEF(USIM, log) \
|
||||
COMP_DEF(F1U, ) \
|
||||
COMP_DEF(X2AP, ) \
|
||||
COMP_DEF(XNAP, ) \
|
||||
COMP_DEF(M2AP, ) \
|
||||
COMP_DEF(M3AP, ) \
|
||||
COMP_DEF(NGAP, ) \
|
||||
|
||||
@@ -607,6 +607,27 @@ ID = LEGACY_X2AP_TRACE
|
||||
GROUP = ALL:LEGACY_X2AP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_XNAP_INFO
|
||||
DESC = XNAP legacy logs - info level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_INFO:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_ERROR
|
||||
DESC = XNAP legacy logs - error level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_ERROR:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_WARNING
|
||||
DESC = XNAP legacy logs - warning level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_WARNING:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_DEBUG
|
||||
DESC = XNAP legacy logs - debug level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_DEBUG:LEGACY
|
||||
FORMAT = string,log
|
||||
ID = LEGACY_XNAP_TRACE
|
||||
DESC = XNAP legacy logs - trace level
|
||||
GROUP = ALL:LEGACY_XNAP:LEGACY_GROUP_TRACE:LEGACY
|
||||
FORMAT = string,log
|
||||
|
||||
ID = LEGACY_M2AP_INFO
|
||||
DESC = M2AP legacy logs - info level
|
||||
GROUP = ALL:LEGACY_M2AP:LEGACY_GROUP_INFO:LEGACY
|
||||
|
||||
188
openair2/COMMON/xnap_messages_types.h
Normal file
188
openair2/COMMON/xnap_messages_types.h
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* 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 xnap_messages_types.h
|
||||
* \author Sreeshma Shiv, Rakesh BB
|
||||
* \sreeshmau@iisc.ac.in, rakesh.bb@fsid-iisc.in
|
||||
* \date Jan, 2026
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_MESSAGES_TYPES_H_
|
||||
#define XNAP_MESSAGES_TYPES_H_
|
||||
|
||||
#include "ngap_messages_types.h"
|
||||
|
||||
typedef struct {
|
||||
// PLMN Identity
|
||||
plmn_id_t plmn;
|
||||
// Number of supported S-NSSAIs
|
||||
uint16_t num_nssai;
|
||||
// List of supported S-NSSAIs
|
||||
nssai_t *nssai;
|
||||
} xnap_plmn_support_t;
|
||||
|
||||
typedef struct {
|
||||
// Tracking Area Code
|
||||
uint32_t tac;
|
||||
// Number of supported PLMNs
|
||||
uint8_t num_plmn;
|
||||
// List of supported PLMNs
|
||||
xnap_plmn_support_t *plmn_support;
|
||||
} xnap_tai_support_t;
|
||||
|
||||
typedef struct {
|
||||
// PLMN Identity
|
||||
plmn_id_t plmn;
|
||||
// AMF Region Identifier
|
||||
uint8_t amf_region_id;
|
||||
} xnap_amf_region_info_t;
|
||||
|
||||
/* 3GPP TS 38.423 9.1.3.1 – Xn Setup Request */
|
||||
typedef struct {
|
||||
// Global NG-RAN Node ID (gNB_id+plmn) (M)
|
||||
uint32_t gNB_id;
|
||||
plmn_id_t plmn;
|
||||
// TAI Support List (M)
|
||||
uint16_t num_tai;
|
||||
xnap_tai_support_t *tai_support;
|
||||
// AMF Region Information (M)
|
||||
uint8_t num_amf_regions;
|
||||
xnap_amf_region_info_t *amf_region_info;
|
||||
} xnap_setup_req_t;
|
||||
|
||||
/* 3GPP TS 38.423 9.1.3.2 – Xn Setup Response */
|
||||
typedef struct {
|
||||
// Global NG-RAN Node ID (gNB_id+plmn) (M)
|
||||
uint32_t gNB_id;
|
||||
plmn_id_t plmn;
|
||||
// TAI Support List (M)
|
||||
uint16_t num_tai;
|
||||
xnap_tai_support_t *tai_support;
|
||||
} xnap_setup_resp_t;
|
||||
|
||||
typedef enum xnap_cause_radio_network_e {
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_CELL_NOT_AVAILABLE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_HANDOVER_DESIRABLE_FOR_RADIO_REASONS,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_HANDOVER_TARGET_NOT_ALLOWED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_INVALID_AMF_SET_ID,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_NO_RADIO_RESOURCES_AVAILABLE_IN_TARGET_CELL,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_PARTIAL_HANDOVER,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_REDUCE_LOAD_IN_SERVING_CELL,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCE_OPTIMISATION_HANDOVER,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_TIME_CRITICAL_HANDOVER,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_RELOCOVERALL_EXPIRY,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_RELOCPREP_EXPIRY,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_GUAMI_ID,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_LOCAL_NG_RAN_NODE_UE_XNAP_ID,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_INCONSISTENT_REMOTE_NG_RAN_NODE_UE_XNAP_ID,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_ENCRYPTION_AND_OR_INTEGRITY_PROTECTION_ALGORITHMS_NOT_SUPPORTED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_PROTECTION_ALGORITHMS_NOT_SUPPORTED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_MULTIPLE_PDU_SESSION_ID_INSTANCES,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_PDU_SESSION_ID,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_QOS_FLOW_ID,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_MULTIPLE_QOS_FLOW_ID_INSTANCES,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_SWITCH_OFF_ONGOING,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_NOT_SUPPORTED_5QI_VALUE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_DCOVERALL_EXPIRY,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_TXN_DCPREP_EXPIRY,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_ACTION_DESIRABLE_FOR_RADIO_REASONS,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_REDUCE_LOAD,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCE_OPTIMISATION,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_TIME_CRITICAL_ACTION,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_TARGET_NOT_ALLOWED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_NO_RADIO_RESOURCES_AVAILABLE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_INVALID_QOS_COMBINATION,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_ENCRYPTION_ALGORITHMS_NOT_SUPPORTED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_PROCEDURE_CANCELLED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_RRM_PURPOSE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_IMPROVE_USER_BIT_RATE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_USER_INACTIVITY,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_RADIO_CONNECTION_WITH_UE_LOST,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_FAILURE_IN_THE_RADIO_INTERFACE_PROCEDURE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_BEARER_OPTION_NOT_SUPPORTED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_INTEGRITY_PROTECTION_NOT_POSSIBLE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_CONFIDENTIALITY_PROTECTION_NOT_POSSIBLE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_RESOURCES_NOT_AVAILABLE_FOR_THE_SLICE_S,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UE_MAX_IP_DATA_RATE_REASON,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_CP_INTEGRITY_PROTECTION_FAILURE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UP_INTEGRITY_PROTECTION_FAILURE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_SLICE_NOT_SUPPORTED_BY_NG_RAN,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_MN_MOBILITY,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_SN_MOBILITY,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_COUNT_REACHES_MAX_VALUE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UNKNOWN_OLD_NG_RAN_NODE_UE_XNAP_ID,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_PDCP_OVERLOAD,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_DRB_ID_NOT_AVAILABLE,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UNSPECIFIED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_UE_CONTEXT_ID_NOT_KNOWN,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_NON_RELOCATION_OF_CONTEXT,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_CHO_CPC_RESOURCES_TOBECHANGED,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_RSN_NOT_AVAILABLE_FOR_THE_UP,
|
||||
XNAP_CAUSE_RADIO_NETWORK_LAYER_NPN_ACCESS_DENIED
|
||||
} xnap_cause_radio_network_t;
|
||||
|
||||
typedef enum xnap_cause_transport_layer_e {
|
||||
XNAP_CAUSE_TRANSPORT_LAYER_TRANSPORT_RESOURCE_UNAVAILABLE,
|
||||
XNAP_CAUSE_TRANSPORT_LAYER_UNSPECIFIED
|
||||
} xnap_cause_transport_layer_t;
|
||||
|
||||
typedef enum xnap_cause_protocol_e {
|
||||
XNAP_CAUSE_PROTOCOL_TRANSFER_SYNTAX_ERROR,
|
||||
XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_REJECT,
|
||||
XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_IGNORE_AND_NOTIFY,
|
||||
XNAP_CAUSE_PROTOCOL_MESSAGE_NOT_COMPATIBLE_WITH_RECEIVER_STATE,
|
||||
XNAP_CAUSE_PROTOCOL_SEMANTIC_ERROR,
|
||||
XNAP_CAUSE_PROTOCOL_ABSTRACT_SYNTAX_ERROR_FALSELY_CONSTRUCTED,
|
||||
XNAP_CAUSE_PROTOCOL_UNSPECIFIED
|
||||
} xnap_cause_protocol_t;
|
||||
|
||||
typedef enum xnap_cause_misc_e {
|
||||
XNAP_CAUSE_MISC_CONTROL_PROCESSING_OVERLOAD,
|
||||
XNAP_CAUSE_MISC_HARDWARE_FAILURE,
|
||||
XNAP_CAUSE_MISC_O_AND_M_INTERVENTION,
|
||||
XNAP_CAUSE_MISC_NOT_ENOUGH_USER_PLANE_PROCESSING_RESOURCES,
|
||||
XNAP_CAUSE_MISC_UNSPECIFIED
|
||||
} xnap_cause_misc_t;
|
||||
|
||||
typedef enum xnap_cause_group_e {
|
||||
XNAP_CAUSE_NOTHING,
|
||||
XNAP_CAUSE_RADIO_NETWORK,
|
||||
XNAP_CAUSE_TRANSPORT,
|
||||
XNAP_CAUSE_PROTOCOL,
|
||||
XNAP_CAUSE_MISC,
|
||||
} xnap_cause_group_t;
|
||||
|
||||
typedef struct xnap_cause_s {
|
||||
/* Cause group (e.g. radioNetwork, transport, protocol, misc) */
|
||||
xnap_cause_group_t type;
|
||||
/* Specific cause value within the selected cause group */
|
||||
uint8_t value;
|
||||
} xnap_cause_t;
|
||||
|
||||
/* 3GPP TS 38.423 9.1.3.3 – Xn Setup Failure */
|
||||
typedef struct {
|
||||
// Cause (M)
|
||||
xnap_cause_t cause;
|
||||
} xnap_setup_failure_t;
|
||||
|
||||
#endif /* XNAP_MESSAGES_TYPES_H_ */
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(MESSAGES)
|
||||
add_library(xnap xnap_common.c)
|
||||
target_link_libraries(xnap
|
||||
PUBLIC asn1_xnap
|
||||
PRIVATE nr_rrc)
|
||||
target_include_directories(xnap PUBLIC ${CMAKE_CURRENT_DIR})
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
15
openair2/XNAP/lib/CMakeLists.txt
Normal file
15
openair2/XNAP/lib/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
add_library(xnap_lib OBJECT
|
||||
xnap_lib_common.c
|
||||
xnap_gNB_interface_management.c
|
||||
)
|
||||
target_link_libraries(xnap_lib PUBLIC ngap nr_rrc asn1_xnap ds)
|
||||
target_include_directories(xnap_lib PUBLIC
|
||||
${OPENAIR2_DIR}/XNAP
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
|
||||
if(ENABLE_TESTS)
|
||||
target_compile_definitions(xnap_lib PRIVATE ENABLE_TESTS)
|
||||
endif()
|
||||
|
||||
479
openair2/XNAP/lib/xnap_gNB_interface_management.c
Normal file
479
openair2/XNAP/lib/xnap_gNB_interface_management.c
Normal file
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* 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 xnap_gNB_interface_management.c
|
||||
* \brief xnap handling interface procedures for gNB
|
||||
* \author Sreeshma Shiv, Rakesh BB
|
||||
* \email sreeshmau@iisc.ac.in, rakesh.bb@fsid-iisc.in
|
||||
* \date Jan 2026
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#include "xnap_gNB_interface_management.h"
|
||||
#include "xnap_lib_common.h"
|
||||
#include "xnap_lib_includes.h"
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Request encoding
|
||||
*/
|
||||
XNAP_XnAP_PDU_t *encode_xn_setup_request(const xnap_setup_req_t *msg)
|
||||
{
|
||||
XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
||||
|
||||
/* PDU type */
|
||||
pdu->present = XNAP_XnAP_PDU_PR_initiatingMessage;
|
||||
asn1cCalloc(pdu->choice.initiatingMessage, initMsg);
|
||||
initMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup;
|
||||
initMsg->criticality = XNAP_Criticality_reject;
|
||||
initMsg->value.present = XNAP_InitiatingMessage__value_PR_XnSetupRequest;
|
||||
|
||||
XNAP_XnSetupRequest_t *out = &initMsg->value.choice.XnSetupRequest;
|
||||
|
||||
/* Global NG-RAN Node ID (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC1);
|
||||
ieC1->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID;
|
||||
ieC1->criticality = XNAP_Criticality_reject;
|
||||
ieC1->value.present = XNAP_XnSetupRequest_IEs__value_PR_GlobalNG_RANNode_ID;
|
||||
|
||||
XNAP_GlobalNG_RANNode_ID_t *global = &ieC1->value.choice.GlobalNG_RANNode_ID;
|
||||
global->present = XNAP_GlobalNG_RANNode_ID_PR_gNB;
|
||||
asn1cCalloc(global->choice.gNB, gnb);
|
||||
|
||||
MCC_MNC_TO_PLMNID(msg->plmn.mcc, msg->plmn.mnc, msg->plmn.mnc_digit_length, &gnb->plmn_id);
|
||||
gnb->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID;
|
||||
MACRO_GNB_ID_TO_BIT_STRING(msg->gNB_id, &gnb->gnb_id.choice.gnb_ID);
|
||||
|
||||
/* TAI Support List (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC2);
|
||||
ieC2->id = XNAP_ProtocolIE_ID_id_TAISupport_list;
|
||||
ieC2->criticality = XNAP_Criticality_reject;
|
||||
ieC2->value.present = XNAP_XnSetupRequest_IEs__value_PR_TAISupport_List;
|
||||
|
||||
for (int i = 0; i < msg->num_tai; i++) {
|
||||
asn1cSequenceAdd(ieC2->value.choice.TAISupport_List.list, XNAP_TAISupport_Item_t, taiItem);
|
||||
INT24_TO_OCTET_STRING(msg->tai_support[i].tac, &taiItem->tac);
|
||||
|
||||
for (int j = 0; j < msg->tai_support[i].num_plmn; j++) {
|
||||
const xnap_plmn_support_t *plmn = &msg->tai_support[i].plmn_support[j];
|
||||
asn1cSequenceAdd(taiItem->broadcastPLMNs.list, XNAP_BroadcastPLMNinTAISupport_Item_t, plmnItem);
|
||||
MCC_MNC_TO_PLMNID(plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length, &plmnItem->plmn_id);
|
||||
|
||||
for (int k = 0; k < plmn->num_nssai; k++) {
|
||||
asn1cSequenceAdd(plmnItem->tAISliceSupport_List.list, XNAP_S_NSSAI_t, nssai);
|
||||
INT8_TO_OCTET_STRING(plmn->nssai[k].sst, &nssai->sst);
|
||||
if (plmn->nssai[k].sd) { asn1cCalloc(nssai->sd, sd); INT24_TO_OCTET_STRING(plmn->nssai[k].sd, sd); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* AMF Region Information (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupRequest_IEs_t, ieC3);
|
||||
ieC3->id = XNAP_ProtocolIE_ID_id_AMF_Region_Information;
|
||||
ieC3->criticality = XNAP_Criticality_reject;
|
||||
ieC3->value.present = XNAP_XnSetupRequest_IEs__value_PR_AMF_Region_Information;
|
||||
|
||||
for (int i = 0; i < msg->num_amf_regions; i++) {
|
||||
const xnap_amf_region_info_t *amf = &msg->amf_region_info[i];
|
||||
asn1cSequenceAdd(ieC3->value.choice.AMF_Region_Information.list, XNAP_GlobalAMF_Region_Information_t, amfItem);
|
||||
MCC_MNC_TO_PLMNID(amf->plmn.mcc, amf->plmn.mnc, amf->plmn.mnc_digit_length, &amfItem->plmn_ID);
|
||||
INT8_TO_OCTET_STRING(amf->amf_region_id, &amfItem->amf_region_id);
|
||||
}
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Request decoding
|
||||
*/
|
||||
bool decode_xn_setup_request(xnap_setup_req_t *out, const XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
/* Check presence of message type */
|
||||
_XN_EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_initiatingMessage);
|
||||
AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL");
|
||||
_XN_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, XNAP_ProcedureCode_id_xnSetup);
|
||||
_XN_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, XNAP_InitiatingMessage__value_PR_XnSetupRequest);
|
||||
/* XnSetupRequest container */
|
||||
XNAP_XnSetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.XnSetupRequest;
|
||||
|
||||
XNAP_XnSetupRequest_IEs_t *ie;
|
||||
/* Check presence of mandatory IEs */
|
||||
XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true);
|
||||
XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_TAISupport_list, true);
|
||||
XNAP_LIB_FIND_IE(XNAP_XnSetupRequest_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_AMF_Region_Information, true);
|
||||
|
||||
/* Loop over all IEs */
|
||||
for (int i = 0; i < in->protocolIEs.list.count; i++) {
|
||||
AssertError(in->protocolIEs.list.array[i] != NULL, return false, "protocolIEs.list.array[i] is NULL");
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
switch (ie->id) {
|
||||
case XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID: {
|
||||
/* Global NG-RAN Node ID (M) */
|
||||
_XN_EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_GlobalNG_RANNode_ID);
|
||||
XNAP_GlobalNG_RANNode_ID_t *global_id = &ie->value.choice.GlobalNG_RANNode_ID;
|
||||
AssertError(global_id->present == XNAP_GlobalNG_RANNode_ID_PR_gNB, return false, "Only gNB supported");
|
||||
AssertError(global_id->choice.gNB != NULL, return false, "gNB is NULL");
|
||||
/* Decode PLMN */
|
||||
PLMNID_TO_MCC_MNC(&global_id->choice.gNB->plmn_id,
|
||||
out->plmn.mcc,
|
||||
out->plmn.mnc,
|
||||
out->plmn.mnc_digit_length);
|
||||
/* Decode gNB ID */
|
||||
AssertError(global_id->choice.gNB->gnb_id.present == XNAP_GNB_ID_Choice_PR_gnb_ID, return false, "Unsupported gNB ID choice");
|
||||
MACRO_BIT_STRING_TO_GNB_ID(&global_id->choice.gNB->gnb_id.choice.gnb_ID, out->gNB_id);
|
||||
} break;
|
||||
|
||||
case XNAP_ProtocolIE_ID_id_TAISupport_list: {
|
||||
/* TAI Support List (M) */
|
||||
_XN_EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_TAISupport_List);
|
||||
int tai_count = ie->value.choice.TAISupport_List.list.count;
|
||||
out->num_tai = tai_count;
|
||||
out->tai_support = calloc_or_fail(tai_count, sizeof(*out->tai_support));
|
||||
for (int m = 0; m < tai_count; m++) {
|
||||
XNAP_TAISupport_Item_t *tai_item = ie->value.choice.TAISupport_List.list.array[m];
|
||||
/* TAC */
|
||||
OCTET_STRING_TO_INT24(&tai_item->tac, out->tai_support[m].tac);
|
||||
/* PLMN list */
|
||||
out->tai_support[m].num_plmn = tai_item->broadcastPLMNs.list.count;
|
||||
out->tai_support[m].plmn_support = calloc_or_fail(out->tai_support[m].num_plmn, sizeof(*out->tai_support[m].plmn_support));
|
||||
for (int j = 0; j < out->tai_support[m].num_plmn; j++) {
|
||||
XNAP_BroadcastPLMNinTAISupport_Item_t *plmn_item = tai_item->broadcastPLMNs.list.array[j];
|
||||
xnap_plmn_support_t *plmn = &out->tai_support[m].plmn_support[j];
|
||||
PLMNID_TO_MCC_MNC(&plmn_item->plmn_id,
|
||||
plmn->plmn.mcc,
|
||||
plmn->plmn.mnc,
|
||||
plmn->plmn.mnc_digit_length);
|
||||
/* NSSAI */
|
||||
plmn->num_nssai = plmn_item->tAISliceSupport_List.list.count;
|
||||
plmn->nssai = calloc_or_fail(plmn->num_nssai, sizeof(*plmn->nssai));
|
||||
for (int k = 0; k < plmn->num_nssai; k++) {
|
||||
OCTET_STRING_TO_INT8(&plmn_item->tAISliceSupport_List.list.array[k]->sst, plmn->nssai[k].sst);
|
||||
if (plmn_item->tAISliceSupport_List.list.array[k]->sd) {
|
||||
OCTET_STRING_TO_INT24(plmn_item->tAISliceSupport_List.list.array[k]->sd, plmn->nssai[k].sd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case XNAP_ProtocolIE_ID_id_AMF_Region_Information: {
|
||||
/* AMF Region Information (M) */
|
||||
_XN_EQ_CHECK_INT(ie->value.present, XNAP_XnSetupRequest_IEs__value_PR_AMF_Region_Information);
|
||||
out->num_amf_regions = ie->value.choice.AMF_Region_Information.list.count;
|
||||
out->amf_region_info = calloc_or_fail(out->num_amf_regions, sizeof(*out->amf_region_info));
|
||||
for (int a = 0; a < out->num_amf_regions; a++) {
|
||||
XNAP_GlobalAMF_Region_Information_t *amf = ie->value.choice.AMF_Region_Information.list.array[a];
|
||||
PLMNID_TO_MCC_MNC(&amf->plmn_ID,
|
||||
out->amf_region_info[a].plmn.mcc,
|
||||
out->amf_region_info[a].plmn.mnc,
|
||||
out->amf_region_info[a].plmn.mnc_digit_length);
|
||||
OCTET_STRING_TO_INT8(&amf->amf_region_id, out->amf_region_info[a].amf_region_id);
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
AssertError(0, return false, "Unknown XnAP IE id %ld\n", ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Request main equality check
|
||||
*/
|
||||
bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b)
|
||||
{
|
||||
_XN_EQ_CHECK_LONG(a->gNB_id, b->gNB_id);
|
||||
if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false;
|
||||
|
||||
_XN_EQ_CHECK_INT(a->num_tai, b->num_tai);
|
||||
for (int i = 0; i < a->num_tai; i++) {
|
||||
if (!eq_xnap_tai_support(&a->tai_support[i], &b->tai_support[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
_XN_EQ_CHECK_INT(a->num_amf_regions, b->num_amf_regions);
|
||||
for (int i = 0; i < a->num_amf_regions; i++) {
|
||||
if (!eq_xnap_plmn(&a->amf_region_info[i].plmn, &b->amf_region_info[i].plmn))
|
||||
return false;
|
||||
_XN_EQ_CHECK_INT(a->amf_region_info[i].amf_region_id, b->amf_region_info[i].amf_region_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void free_xnap_plmn_support(xnap_plmn_support_t *plmn_support, uint8_t num_plmn)
|
||||
{
|
||||
if (!plmn_support) return;
|
||||
for (int i = 0; i < num_plmn; i++) {
|
||||
free(plmn_support[i].nssai);
|
||||
}
|
||||
free(plmn_support);
|
||||
}
|
||||
|
||||
static void free_xnap_tai_support(xnap_tai_support_t *tai_support, uint16_t num_tai)
|
||||
{
|
||||
if (!tai_support) return;
|
||||
for (int i = 0; i < num_tai; i++) {
|
||||
free_xnap_plmn_support(tai_support[i].plmn_support,
|
||||
tai_support[i].num_plmn);
|
||||
}
|
||||
free(tai_support);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Request memory management
|
||||
*/
|
||||
void free_xnap_setup_request(const xnap_setup_req_t *msg)
|
||||
{
|
||||
DevAssert(msg != NULL);
|
||||
free_xnap_tai_support(msg->tai_support, msg->num_tai);
|
||||
free(msg->amf_region_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Response encoding
|
||||
*/
|
||||
XNAP_XnAP_PDU_t *encode_xn_setup_response(const xnap_setup_resp_t *resp)
|
||||
{
|
||||
XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
||||
|
||||
/* PDU type */
|
||||
pdu->present = XNAP_XnAP_PDU_PR_successfulOutcome;
|
||||
asn1cCalloc(pdu->choice.successfulOutcome, succMsg);
|
||||
succMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup;
|
||||
succMsg->criticality = XNAP_Criticality_reject;
|
||||
succMsg->value.present = XNAP_SuccessfulOutcome__value_PR_XnSetupResponse;
|
||||
|
||||
XNAP_XnSetupResponse_t *out = &succMsg->value.choice.XnSetupResponse;
|
||||
|
||||
/* Global NG-RAN Node ID (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupResponse_IEs_t, ie1);
|
||||
ie1->id = XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID;
|
||||
ie1->criticality = XNAP_Criticality_reject;
|
||||
ie1->value.present = XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID;
|
||||
|
||||
XNAP_GlobalNG_RANNode_ID_t *global = &ie1->value.choice.GlobalNG_RANNode_ID;
|
||||
global->present = XNAP_GlobalNG_RANNode_ID_PR_gNB;
|
||||
asn1cCalloc(global->choice.gNB, gnb);
|
||||
|
||||
MCC_MNC_TO_PLMNID(resp->plmn.mcc, resp->plmn.mnc, resp->plmn.mnc_digit_length, &gnb->plmn_id);
|
||||
gnb->gnb_id.present = XNAP_GNB_ID_Choice_PR_gnb_ID;
|
||||
MACRO_GNB_ID_TO_BIT_STRING(resp->gNB_id, &gnb->gnb_id.choice.gnb_ID);
|
||||
|
||||
/* TAI Support List (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupResponse_IEs_t, ie2);
|
||||
ie2->id = XNAP_ProtocolIE_ID_id_TAISupport_list;
|
||||
ie2->criticality = XNAP_Criticality_reject;
|
||||
ie2->value.present = XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List;
|
||||
|
||||
for (int i = 0; i < resp->num_tai; i++) {
|
||||
asn1cSequenceAdd(ie2->value.choice.TAISupport_List.list, XNAP_TAISupport_Item_t, taiItem);
|
||||
INT24_TO_OCTET_STRING(resp->tai_support[i].tac, &taiItem->tac);
|
||||
|
||||
for (int j = 0; j < resp->tai_support[i].num_plmn; j++) {
|
||||
const xnap_plmn_support_t *plmn = &resp->tai_support[i].plmn_support[j];
|
||||
asn1cSequenceAdd(taiItem->broadcastPLMNs.list, XNAP_BroadcastPLMNinTAISupport_Item_t, plmnItem);
|
||||
MCC_MNC_TO_PLMNID(plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length, &plmnItem->plmn_id);
|
||||
|
||||
for (int k = 0; k < plmn->num_nssai; k++) {
|
||||
asn1cSequenceAdd(plmnItem->tAISliceSupport_List.list, XNAP_S_NSSAI_t, nssai);
|
||||
INT8_TO_OCTET_STRING(plmn->nssai[k].sst, &nssai->sst);
|
||||
if (plmn->nssai[k].sd) { asn1cCalloc(nssai->sd, sd); INT24_TO_OCTET_STRING(plmn->nssai[k].sd, sd); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Response decoding
|
||||
*/
|
||||
bool decode_xn_setup_response(xnap_setup_resp_t *out, const XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
/* Check presence of message type */
|
||||
_XN_EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_successfulOutcome);
|
||||
AssertError(pdu->choice.successfulOutcome != NULL, return false, "successfulOutcome is NULL");
|
||||
_XN_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, XNAP_ProcedureCode_id_xnSetup);
|
||||
_XN_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, XNAP_SuccessfulOutcome__value_PR_XnSetupResponse);
|
||||
|
||||
/* XnSetupResponse container */
|
||||
XNAP_XnSetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.XnSetupResponse;
|
||||
XNAP_XnSetupResponse_IEs_t *ie;
|
||||
|
||||
/* Check presence of mandatory IEs */
|
||||
XNAP_LIB_FIND_IE(XNAP_XnSetupResponse_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID, true);
|
||||
XNAP_LIB_FIND_IE(XNAP_XnSetupResponse_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_TAISupport_list, true);
|
||||
|
||||
/* Loop over all IEs */
|
||||
for (int i = 0; i < in->protocolIEs.list.count; i++) {
|
||||
AssertError(in->protocolIEs.list.array[i] != NULL, return false, "protocolIEs.list.array[i] is NULL");
|
||||
ie = in->protocolIEs.list.array[i];
|
||||
|
||||
switch (ie->id) {
|
||||
|
||||
case XNAP_ProtocolIE_ID_id_GlobalNG_RAN_node_ID: {
|
||||
_XN_EQ_CHECK_INT(ie->value.present, XNAP_XnSetupResponse_IEs__value_PR_GlobalNG_RANNode_ID);
|
||||
XNAP_GlobalNG_RANNode_ID_t *global = &ie->value.choice.GlobalNG_RANNode_ID;
|
||||
AssertError(global->present == XNAP_GlobalNG_RANNode_ID_PR_gNB, return false, "Only gNB supported");
|
||||
AssertError(global->choice.gNB != NULL, return false, "gNB is NULL");
|
||||
|
||||
PLMNID_TO_MCC_MNC(&global->choice.gNB->plmn_id, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length);
|
||||
AssertError(global->choice.gNB->gnb_id.present == XNAP_GNB_ID_Choice_PR_gnb_ID, return false, "Unsupported gNB ID");
|
||||
MACRO_BIT_STRING_TO_GNB_ID(&global->choice.gNB->gnb_id.choice.gnb_ID, out->gNB_id);
|
||||
} break;
|
||||
|
||||
case XNAP_ProtocolIE_ID_id_TAISupport_list: {
|
||||
_XN_EQ_CHECK_INT(ie->value.present, XNAP_XnSetupResponse_IEs__value_PR_TAISupport_List);
|
||||
out->num_tai = ie->value.choice.TAISupport_List.list.count;
|
||||
out->tai_support = calloc_or_fail(out->num_tai, sizeof(*out->tai_support));
|
||||
|
||||
for (int m = 0; m < out->num_tai; m++) {
|
||||
XNAP_TAISupport_Item_t *tai = ie->value.choice.TAISupport_List.list.array[m];
|
||||
OCTET_STRING_TO_INT24(&tai->tac, out->tai_support[m].tac);
|
||||
|
||||
out->tai_support[m].num_plmn = tai->broadcastPLMNs.list.count;
|
||||
out->tai_support[m].plmn_support = calloc_or_fail(out->tai_support[m].num_plmn, sizeof(*out->tai_support[m].plmn_support));
|
||||
|
||||
for (int j = 0; j < out->tai_support[m].num_plmn; j++) {
|
||||
XNAP_BroadcastPLMNinTAISupport_Item_t *plmn_item = tai->broadcastPLMNs.list.array[j];
|
||||
xnap_plmn_support_t *plmn = &out->tai_support[m].plmn_support[j];
|
||||
|
||||
PLMNID_TO_MCC_MNC(&plmn_item->plmn_id, plmn->plmn.mcc, plmn->plmn.mnc, plmn->plmn.mnc_digit_length);
|
||||
|
||||
plmn->num_nssai = plmn_item->tAISliceSupport_List.list.count;
|
||||
plmn->nssai = calloc_or_fail(plmn->num_nssai, sizeof(*plmn->nssai));
|
||||
|
||||
for (int k = 0; k < plmn->num_nssai; k++) {
|
||||
OCTET_STRING_TO_INT8(&plmn_item->tAISliceSupport_List.list.array[k]->sst, plmn->nssai[k].sst);
|
||||
if (plmn_item->tAISliceSupport_List.list.array[k]->sd) {
|
||||
OCTET_STRING_TO_INT24(plmn_item->tAISliceSupport_List.list.array[k]->sd, plmn->nssai[k].sd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
AssertError(0, return false, "Unknown XnAP IE id %ld\n", ie->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Response main equality check
|
||||
*/
|
||||
bool eq_xnap_setup_response(const xnap_setup_resp_t *a, const xnap_setup_resp_t *b)
|
||||
{
|
||||
_XN_EQ_CHECK_LONG(a->gNB_id, b->gNB_id);
|
||||
if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false;
|
||||
|
||||
_XN_EQ_CHECK_INT(a->num_tai, b->num_tai);
|
||||
for (int i = 0; i < a->num_tai; i++) {
|
||||
if (!eq_xnap_tai_support(&a->tai_support[i], &b->tai_support[i]))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Response memory management
|
||||
*/
|
||||
void free_xnap_setup_response(const xnap_setup_resp_t *msg)
|
||||
{
|
||||
DevAssert(msg != NULL);
|
||||
free_xnap_tai_support(msg->tai_support, msg->num_tai);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Failure encoding
|
||||
*/
|
||||
XNAP_XnAP_PDU_t *encode_xn_setup_failure(const xnap_setup_failure_t *fail)
|
||||
{
|
||||
XNAP_XnAP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu));
|
||||
|
||||
/* Message type */
|
||||
pdu->present = XNAP_XnAP_PDU_PR_unsuccessfulOutcome;
|
||||
asn1cCalloc(pdu->choice.unsuccessfulOutcome, failMsg);
|
||||
failMsg->procedureCode = XNAP_ProcedureCode_id_xnSetup;
|
||||
failMsg->criticality = XNAP_Criticality_reject;
|
||||
failMsg->value.present = XNAP_UnsuccessfulOutcome__value_PR_XnSetupFailure;
|
||||
|
||||
XNAP_XnSetupFailure_t *out = &failMsg->value.choice.XnSetupFailure;
|
||||
|
||||
/* Cause (M) */
|
||||
asn1cSequenceAdd(out->protocolIEs.list, XNAP_XnSetupFailure_IEs_t, ie1);
|
||||
ie1->id = XNAP_ProtocolIE_ID_id_Cause;
|
||||
ie1->criticality = XNAP_Criticality_ignore;
|
||||
ie1->value.present = XNAP_XnSetupFailure_IEs__value_PR_Cause;
|
||||
xnap_gNB_set_cause(&ie1->value.choice.Cause, &fail->cause);
|
||||
|
||||
return pdu;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Failure decoding
|
||||
*/
|
||||
bool decode_xn_setup_failure(xnap_setup_failure_t *out, const XNAP_XnAP_PDU_t *pdu)
|
||||
{
|
||||
/* Check message type */
|
||||
_XN_EQ_CHECK_INT(pdu->present, XNAP_XnAP_PDU_PR_unsuccessfulOutcome);
|
||||
AssertError(pdu->choice.unsuccessfulOutcome != NULL, return false, "unsuccessfulOutcome is NULL");
|
||||
_XN_EQ_CHECK_LONG(pdu->choice.unsuccessfulOutcome->procedureCode, XNAP_ProcedureCode_id_xnSetup);
|
||||
_XN_EQ_CHECK_INT(pdu->choice.unsuccessfulOutcome->value.present, XNAP_UnsuccessfulOutcome__value_PR_XnSetupFailure);
|
||||
|
||||
/* XnSetupFailure container */
|
||||
XNAP_XnSetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.XnSetupFailure;
|
||||
XNAP_XnSetupFailure_IEs_t *ie;
|
||||
|
||||
/* Check presence of mandatory IE */
|
||||
XNAP_LIB_FIND_IE(XNAP_XnSetupFailure_IEs_t, ie, &in->protocolIEs.list, XNAP_ProtocolIE_ID_id_Cause, true);
|
||||
|
||||
/* Decode Cause */
|
||||
_XN_EQ_CHECK_INT(ie->value.present, XNAP_XnSetupFailure_IEs__value_PR_Cause);
|
||||
out->cause = decode_xnap_cause(&ie->value.choice.Cause);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Failure equality check
|
||||
*/
|
||||
bool eq_xnap_setup_failure(const xnap_setup_failure_t *a, const xnap_setup_failure_t *b)
|
||||
{
|
||||
return eq_xnap_cause(&a->cause, &b->cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief XnAP Setup Failure memory management
|
||||
*/
|
||||
void free_xnap_setup_failure(xnap_setup_failure_t *msg)
|
||||
{
|
||||
DevAssert(msg != NULL);
|
||||
/* No dynamic allocations inside xnap_setup_failure_t */
|
||||
memset(msg, 0, sizeof(*msg));
|
||||
}
|
||||
|
||||
|
||||
51
openair2/XNAP/lib/xnap_gNB_interface_management.h
Normal file
51
openair2/XNAP/lib/xnap_gNB_interface_management.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 xnap_gNB_interface_management.h
|
||||
* \brief xnap interface handler procedures for gNB
|
||||
* \date 2026 Jan
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
#ifndef XNAP_GNB_INTERFACE_MANAGEMENT_H_
|
||||
#define XNAP_GNB_INTERFACE_MANAGEMENT_H_
|
||||
|
||||
#include "xnap_messages_types.h"
|
||||
typedef struct XNAP_XnAP_PDU XNAP_XnAP_PDU_t;
|
||||
|
||||
XNAP_XnAP_PDU_t* encode_xn_setup_request(const xnap_setup_req_t *req);
|
||||
XNAP_XnAP_PDU_t *encode_xn_setup_response(const xnap_setup_resp_t *resp);
|
||||
XNAP_XnAP_PDU_t *encode_xn_setup_failure(const xnap_setup_failure_t *fail);
|
||||
|
||||
bool decode_xn_setup_request(xnap_setup_req_t *req, const XNAP_XnAP_PDU_t *pdu);
|
||||
bool decode_xn_setup_response(xnap_setup_resp_t *out, const XNAP_XnAP_PDU_t *pdu);
|
||||
bool decode_xn_setup_failure(xnap_setup_failure_t *out, const XNAP_XnAP_PDU_t *pdu);
|
||||
|
||||
bool eq_xnap_setup_request(const xnap_setup_req_t *a, const xnap_setup_req_t *b);
|
||||
bool eq_xnap_setup_response(const xnap_setup_resp_t *a, const xnap_setup_resp_t *b);
|
||||
bool eq_xnap_setup_failure(const xnap_setup_failure_t *a, const xnap_setup_failure_t *b);
|
||||
|
||||
void free_xnap_setup_request(const xnap_setup_req_t *msg);
|
||||
void free_xnap_setup_response(const xnap_setup_resp_t *msg);
|
||||
void free_xnap_setup_failure(xnap_setup_failure_t *msg);
|
||||
|
||||
#endif /* XNAP_GNB_INTERFACE_MANAGEMENT_H_ */
|
||||
|
||||
127
openair2/XNAP/lib/xnap_lib_common.c
Normal file
127
openair2/XNAP/lib/xnap_lib_common.c
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 "xnap_lib_common.h"
|
||||
#include "common/utils/assertions.h"
|
||||
#include "common/utils/utils.h"
|
||||
|
||||
int xnap_gNB_set_cause(XNAP_Cause_t *cause_p,const xnap_cause_t *in)
|
||||
{
|
||||
DevAssert(cause_p != NULL);
|
||||
switch (in->type) {
|
||||
case XNAP_CAUSE_RADIO_NETWORK:
|
||||
cause_p->present = XNAP_Cause_PR_radioNetwork;
|
||||
cause_p->choice.radioNetwork = in->value;
|
||||
break;
|
||||
case XNAP_CAUSE_TRANSPORT:
|
||||
cause_p->present = XNAP_Cause_PR_transport;
|
||||
cause_p->choice.transport = in->value;
|
||||
break;
|
||||
case XNAP_CAUSE_PROTOCOL:
|
||||
cause_p->present = XNAP_Cause_PR_protocol;
|
||||
cause_p->choice.protocol = in->value;
|
||||
break;
|
||||
case XNAP_CAUSE_MISC:
|
||||
cause_p->present = XNAP_Cause_PR_misc;
|
||||
cause_p->choice.misc = in->value;
|
||||
break;
|
||||
case XNAP_CAUSE_NOTHING:
|
||||
default:
|
||||
AssertFatal(false, "unknown cause value %d\n", in->type);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
xnap_cause_t decode_xnap_cause(const XNAP_Cause_t *in)
|
||||
{
|
||||
xnap_cause_t out = {0};
|
||||
switch (in->present) {
|
||||
case XNAP_Cause_PR_radioNetwork:
|
||||
out.type = XNAP_CAUSE_RADIO_NETWORK;
|
||||
out.value = in->choice.radioNetwork;
|
||||
break;
|
||||
|
||||
case XNAP_Cause_PR_transport:
|
||||
out.type = XNAP_CAUSE_TRANSPORT;
|
||||
out.value = in->choice.transport;
|
||||
break;
|
||||
|
||||
case XNAP_Cause_PR_protocol:
|
||||
out.type = XNAP_CAUSE_PROTOCOL;
|
||||
out.value = in->choice.protocol;
|
||||
break;
|
||||
|
||||
case XNAP_Cause_PR_misc:
|
||||
out.type = XNAP_CAUSE_MISC;
|
||||
out.value = in->choice.misc;
|
||||
break;
|
||||
case XNAP_Cause_PR_NOTHING:
|
||||
default:
|
||||
PRINT_XN_ERROR("received illegal XNAP cause %d\n", in->present);
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool eq_xnap_cause(const xnap_cause_t *a, const xnap_cause_t *b)
|
||||
{
|
||||
_XN_EQ_CHECK_INT(a->type, b->type);
|
||||
_XN_EQ_CHECK_INT(a->value, b->value);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b)
|
||||
{
|
||||
_XN_EQ_CHECK_INT(a->mcc, b->mcc);
|
||||
_XN_EQ_CHECK_INT(a->mnc, b->mnc);
|
||||
_XN_EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eq_xnap_snssai(const nssai_t *a, const nssai_t *b)
|
||||
{
|
||||
_XN_EQ_CHECK_INT(a->sst, b->sst);
|
||||
_XN_EQ_CHECK_LONG(a->sd, b->sd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eq_xnap_plmn_support(const xnap_plmn_support_t *a, const xnap_plmn_support_t *b)
|
||||
{
|
||||
if (!eq_xnap_plmn(&a->plmn, &b->plmn)) return false;
|
||||
_XN_EQ_CHECK_INT(a->num_nssai, b->num_nssai);
|
||||
for (int i = 0; i < a->num_nssai; i++) {
|
||||
if (!eq_xnap_snssai(&a->nssai[i], &b->nssai[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eq_xnap_tai_support(const xnap_tai_support_t *a, const xnap_tai_support_t *b)
|
||||
{
|
||||
_XN_EQ_CHECK_LONG(a->tac, b->tac);
|
||||
_XN_EQ_CHECK_INT(a->num_plmn, b->num_plmn);
|
||||
for (int i = 0; i < a->num_plmn; i++) {
|
||||
if (!eq_xnap_plmn_support(&a->plmn_support[i], &b->plmn_support[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
85
openair2/XNAP/lib/xnap_lib_common.h
Normal file
85
openair2/XNAP/lib/xnap_lib_common.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifndef XNAP_LIB_COMMON_H_
|
||||
#define XNAP_LIB_COMMON_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "openair3/UTILS/conversions.h"
|
||||
#include "common/utils/oai_asn1.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "xnap_messages_types.h"
|
||||
#include "xnap_lib_includes.h"
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
#define PRINT_XN_ERROR(fmt, ...) fprintf(stderr, "%s:%d: " fmt, __FILE__, __LINE__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define PRINT_XN_ERROR(...)
|
||||
#endif
|
||||
|
||||
/* macro to look up XnAP IE. If mandatory and not found, macro will print
|
||||
* descriptive debug message to stderr and force exit in calling function */
|
||||
|
||||
#define XNAP_LIB_FIND_IE(IE_TYPE, ie, IE_LIST, IE_ID, mandatory) \
|
||||
do { \
|
||||
ie = NULL; \
|
||||
for (IE_TYPE **ptr = (IE_LIST)->array; ptr < &(IE_LIST)->array[(IE_LIST)->count]; ptr++) { \
|
||||
if ((*ptr)->id == IE_ID) { \
|
||||
ie = *ptr; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
if ((mandatory) && (ie == NULL)) { \
|
||||
fprintf(stderr, "%s(): could not find XnAP IE " #IE_ID " of type " #IE_TYPE "\n", __func__); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Reusable Equality Macros */
|
||||
#define _XN_EQ_CHECK_GENERIC(condition, fmt, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
PRINT_XN_ERROR("XnAP Equality failed: " #condition " (" fmt " != " fmt ")\n", \
|
||||
##__VA_ARGS__); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define _XN_EQ_CHECK_LONG(A, B) _XN_EQ_CHECK_GENERIC(A == B, "%ld", (long)A, (long)B)
|
||||
#define _XN_EQ_CHECK_INT(A, B) _XN_EQ_CHECK_GENERIC(A == B, "%d", (int)A, (int)B)
|
||||
#define _XN_EQ_CHECK_STR(A, B) _XN_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B)
|
||||
|
||||
/* Function Prototypes */
|
||||
bool eq_xnap_plmn(const plmn_id_t *a, const plmn_id_t *b);
|
||||
bool eq_xnap_snssai(const nssai_t *a, const nssai_t *b);
|
||||
bool eq_xnap_tai_support(const xnap_tai_support_t *a, const xnap_tai_support_t *b);
|
||||
bool eq_xnap_plmn_support(const xnap_plmn_support_t *a, const xnap_plmn_support_t *b);
|
||||
bool eq_xnap_cause(const xnap_cause_t *a, const xnap_cause_t *b);
|
||||
|
||||
int xnap_gNB_set_cause(XNAP_Cause_t *cause_p,const xnap_cause_t *in);
|
||||
xnap_cause_t decode_xnap_cause(const XNAP_Cause_t *in);
|
||||
|
||||
#endif /* XNAP_LIB_COMMON_H_ */
|
||||
|
||||
52
openair2/XNAP/lib/xnap_lib_includes.h
Normal file
52
openair2/XNAP/lib/xnap_lib_includes.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 xnap_lib_includes.h
|
||||
* \brief XNAP ASN.1 message includes
|
||||
* \author Rakesh BB
|
||||
* \date 2025
|
||||
* \email: rakesh.bb@fsid-iisc.in
|
||||
* \version 1.0
|
||||
* @ingroup _xnap
|
||||
*
|
||||
* This header file contains the includes for the XNAP ASN.1 messages,
|
||||
* generated from the ASN.1 specifications.
|
||||
*/
|
||||
|
||||
#ifndef XNAP_LIB_INCLUDES_H
|
||||
#define XNAP_LIB_INCLUDES_H
|
||||
|
||||
#include "XNAP_XnAP-PDU.h"
|
||||
#include "XNAP_ProtocolIE-Field.h"
|
||||
#include "XNAP_InitiatingMessage.h"
|
||||
#include "XNAP_SuccessfulOutcome.h"
|
||||
#include "XNAP_UnsuccessfulOutcome.h"
|
||||
|
||||
#include "XNAP_GlobalgNB-ID.h"
|
||||
#include "XNAP_GlobalNG-RANNode-ID.h"
|
||||
#include "XNAP_GlobalAMF-Region-Information.h"
|
||||
#include "XNAP_TAISupport-Item.h"
|
||||
#include "XNAP_S-NSSAI.h"
|
||||
#include "XNAP_BroadcastPLMNinTAISupport-Item.h"
|
||||
#include "XNAP_Cause.h"
|
||||
|
||||
#endif // XNAP_LIB_INCLUDES_H
|
||||
|
||||
6
openair2/XNAP/tests/CMakeLists.txt
Normal file
6
openair2/XNAP/tests/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
add_executable(xnap_lib_test xnap_lib_test.c)
|
||||
add_dependencies(tests xnap_lib_test)
|
||||
add_test(NAME xnap_lib_test COMMAND xnap_lib_test)
|
||||
target_link_libraries(xnap_lib_test PRIVATE xnap_lib ds LOG)
|
||||
target_link_libraries(xnap_lib_test PRIVATE asn1_xnap)
|
||||
target_include_directories(xnap_lib_test PRIVATE ${CMAKE_SOURCE_DIR})
|
||||
316
openair2/XNAP/tests/xnap_lib_test.c
Normal file
316
openair2/XNAP/tests/xnap_lib_test.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* 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 xnap_lib_test.c
|
||||
* \brief Test functions for XnAP encoding/decoding library
|
||||
* \author Rakesh BB
|
||||
* \date 2026
|
||||
* \version 0.1
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "common/utils/assertions.h"
|
||||
#include "common/utils/utils.h"
|
||||
#include "xnap_messages_types.h"
|
||||
#include "lib/xnap_lib_common.h"
|
||||
#include "lib/xnap_gNB_interface_management.h"
|
||||
|
||||
#include "common/config/config_load_configmodule.h"
|
||||
configmodule_interface_t *uniqCfg = NULL;
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
{
|
||||
printf("detected error at %s:%d:%s: %s\n", file, line, function, s);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Helper for ASN.1 Encoding/Decoding loop */
|
||||
static XNAP_XnAP_PDU_t *xnap_encode_decode(const XNAP_XnAP_PDU_t *enc_pdu)
|
||||
{
|
||||
//xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, enc_pdu);
|
||||
DevAssert(enc_pdu != NULL);
|
||||
char errbuf[1024];
|
||||
size_t errlen = sizeof(errbuf);
|
||||
int ret = asn_check_constraints(&asn_DEF_XNAP_XnAP_PDU, enc_pdu, errbuf, &errlen);
|
||||
AssertFatal(ret == 0, "asn_check_constraints() failed: %s\n", errbuf);
|
||||
|
||||
uint8_t msgbuf[16384];
|
||||
// 1. Encode
|
||||
asn_enc_rval_t enc = aper_encode_to_buffer(&asn_DEF_XNAP_XnAP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf));
|
||||
AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n");
|
||||
|
||||
// 2. Decode
|
||||
XNAP_XnAP_PDU_t *dec_pdu = NULL;
|
||||
asn_codec_ctx_t st = {.max_stack_size = 100 * 1000};
|
||||
asn_dec_rval_t dec = aper_decode(&st, &asn_DEF_XNAP_XnAP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0);
|
||||
AssertFatal(dec.code == RC_OK, "aper_decode() failed\n");
|
||||
|
||||
//xer_fprint(stdout, &asn_DEF_XNAP_XnAP_PDU, dec_pdu);
|
||||
|
||||
return dec_pdu;
|
||||
}
|
||||
|
||||
static void xnap_msg_free(XNAP_XnAP_PDU_t *pdu) {
|
||||
ASN_STRUCT_FREE(asn_DEF_XNAP_XnAP_PDU, pdu);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 1. Xn Setup Request
|
||||
*/
|
||||
static void test_xn_setup_request(void)
|
||||
{
|
||||
/* ---------- Common PLMNs ---------- */
|
||||
plmn_id_t plmn0 = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 };
|
||||
plmn_id_t plmn1 = { .mcc = 208, .mnc = 93, .mnc_digit_length = 2 };
|
||||
|
||||
/* ---------- TAI support (2) ---------- */
|
||||
xnap_tai_support_t *tai_support =
|
||||
calloc_or_fail(2, sizeof(*tai_support));
|
||||
|
||||
/* ================= TAI 0 ================= */
|
||||
tai_support[0].tac = 1;
|
||||
tai_support[0].num_plmn = 2;
|
||||
tai_support[0].plmn_support =
|
||||
calloc_or_fail(2, sizeof(*tai_support[0].plmn_support));
|
||||
|
||||
/* ---- TAI 0 / PLMN 0 ---- */
|
||||
tai_support[0].plmn_support[0].plmn = plmn0;
|
||||
tai_support[0].plmn_support[0].num_nssai = 3;
|
||||
tai_support[0].plmn_support[0].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[0].plmn_support[0].nssai[0] = (nssai_t){ .sst = 1, .sd = 0x010203 };
|
||||
tai_support[0].plmn_support[0].nssai[1] = (nssai_t){ .sst = 1, .sd = 0x010204 };
|
||||
tai_support[0].plmn_support[0].nssai[2] = (nssai_t){ .sst = 1, .sd = 0x010205 };
|
||||
|
||||
/* ---- TAI 0 / PLMN 1 ---- */
|
||||
tai_support[0].plmn_support[1].plmn = plmn1;
|
||||
tai_support[0].plmn_support[1].num_nssai = 3;
|
||||
tai_support[0].plmn_support[1].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[0].plmn_support[1].nssai[0] = (nssai_t){ .sst = 2, .sd = 0x020203 };
|
||||
tai_support[0].plmn_support[1].nssai[1] = (nssai_t){ .sst = 2, .sd = 0x020204 };
|
||||
tai_support[0].plmn_support[1].nssai[2] = (nssai_t){ .sst = 2, .sd = 0x020205 };
|
||||
|
||||
/* ================= TAI 1 ================= */
|
||||
tai_support[1].tac = 2;
|
||||
tai_support[1].num_plmn = 2;
|
||||
tai_support[1].plmn_support =
|
||||
calloc_or_fail(2, sizeof(*tai_support[1].plmn_support));
|
||||
|
||||
/* ---- TAI 1 / PLMN 0 ---- */
|
||||
tai_support[1].plmn_support[0].plmn = plmn0;
|
||||
tai_support[1].plmn_support[0].num_nssai = 3;
|
||||
tai_support[1].plmn_support[0].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[1].plmn_support[0].nssai[0] = (nssai_t){ .sst = 3, .sd = 0x030203 };
|
||||
tai_support[1].plmn_support[0].nssai[1] = (nssai_t){ .sst = 3, .sd = 0x030204 };
|
||||
tai_support[1].plmn_support[0].nssai[2] = (nssai_t){ .sst = 3, .sd = 0x030205 };
|
||||
|
||||
/* ---- TAI 1 / PLMN 1 ---- */
|
||||
tai_support[1].plmn_support[1].plmn = plmn1;
|
||||
tai_support[1].plmn_support[1].num_nssai = 3;
|
||||
tai_support[1].plmn_support[1].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[1].plmn_support[1].nssai[0] = (nssai_t){ .sst = 4, .sd = 0x040203 };
|
||||
tai_support[1].plmn_support[1].nssai[1] = (nssai_t){ .sst = 4, .sd = 0x040204 };
|
||||
tai_support[1].plmn_support[1].nssai[2] = (nssai_t){ .sst = 4, .sd = 0x040205 };
|
||||
|
||||
/* ---------- AMF region info (2) ---------- */
|
||||
xnap_amf_region_info_t *amf_region_info =
|
||||
calloc_or_fail(2, sizeof(*amf_region_info));
|
||||
|
||||
amf_region_info[0].plmn = plmn0;
|
||||
amf_region_info[0].amf_region_id = 1;
|
||||
|
||||
amf_region_info[1].plmn = plmn1;
|
||||
amf_region_info[1].amf_region_id = 2;
|
||||
|
||||
/* ---------- create message ---------- */
|
||||
xnap_setup_req_t orig = {
|
||||
.gNB_id = 0xABCDE,
|
||||
.plmn = plmn0,
|
||||
.num_tai = 2,
|
||||
.tai_support = tai_support,
|
||||
.num_amf_regions = 2,
|
||||
.amf_region_info = amf_region_info,
|
||||
};
|
||||
/* ---------- encode ---------- */
|
||||
XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_request(&orig);
|
||||
XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc);
|
||||
xnap_msg_free(xnenc);
|
||||
|
||||
/* ---------- decode ---------- */
|
||||
xnap_setup_req_t decoded = {0};
|
||||
bool ret = decode_xn_setup_request(&decoded, xndec);
|
||||
AssertFatal(ret, "decode_xn_setup_request failed");
|
||||
xnap_msg_free(xndec);
|
||||
|
||||
/* ---------- equality ---------- */
|
||||
ret = eq_xnap_setup_request(&orig, &decoded);
|
||||
AssertFatal(ret, "Xn Setup Req mismatch\n");
|
||||
free_xnap_setup_request(&decoded);
|
||||
free_xnap_setup_request(&orig);
|
||||
printf("%s() successful \n", __func__);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 2. Xn Setup Response
|
||||
*/
|
||||
static void test_xn_setup_response(void)
|
||||
{
|
||||
/* ---------- Common PLMNs ---------- */
|
||||
plmn_id_t plmn0 = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 };
|
||||
plmn_id_t plmn1 = { .mcc = 208, .mnc = 93, .mnc_digit_length = 2 };
|
||||
|
||||
/* ---------- TAI support (2) ---------- */
|
||||
xnap_tai_support_t *tai_support =
|
||||
calloc_or_fail(2, sizeof(*tai_support));
|
||||
|
||||
/* ================= TAI 0 ================= */
|
||||
tai_support[0].tac = 1;
|
||||
tai_support[0].num_plmn = 2;
|
||||
tai_support[0].plmn_support =
|
||||
calloc_or_fail(2, sizeof(*tai_support[0].plmn_support));
|
||||
|
||||
/* ---- TAI 0 / PLMN 0 ---- */
|
||||
tai_support[0].plmn_support[0].plmn = plmn0;
|
||||
tai_support[0].plmn_support[0].num_nssai = 3;
|
||||
tai_support[0].plmn_support[0].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[0].plmn_support[0].nssai[0] = (nssai_t){ .sst = 1, .sd = 0x010203 };
|
||||
tai_support[0].plmn_support[0].nssai[1] = (nssai_t){ .sst = 1, .sd = 0x010204 };
|
||||
tai_support[0].plmn_support[0].nssai[2] = (nssai_t){ .sst = 1, .sd = 0x010205 };
|
||||
|
||||
/* ---- TAI 0 / PLMN 1 ---- */
|
||||
tai_support[0].plmn_support[1].plmn = plmn1;
|
||||
tai_support[0].plmn_support[1].num_nssai = 3;
|
||||
tai_support[0].plmn_support[1].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[0].plmn_support[1].nssai[0] = (nssai_t){ .sst = 2, .sd = 0x020203 };
|
||||
tai_support[0].plmn_support[1].nssai[1] = (nssai_t){ .sst = 2, .sd = 0x020204 };
|
||||
tai_support[0].plmn_support[1].nssai[2] = (nssai_t){ .sst = 2, .sd = 0x020205 };
|
||||
|
||||
/* ================= TAI 1 ================= */
|
||||
tai_support[1].tac = 2;
|
||||
tai_support[1].num_plmn = 2;
|
||||
tai_support[1].plmn_support =
|
||||
calloc_or_fail(2, sizeof(*tai_support[1].plmn_support));
|
||||
|
||||
/* ---- TAI 1 / PLMN 0 ---- */
|
||||
tai_support[1].plmn_support[0].plmn = plmn0;
|
||||
tai_support[1].plmn_support[0].num_nssai = 3;
|
||||
tai_support[1].plmn_support[0].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[1].plmn_support[0].nssai[0] = (nssai_t){ .sst = 3, .sd = 0x030203 };
|
||||
tai_support[1].plmn_support[0].nssai[1] = (nssai_t){ .sst = 3, .sd = 0x030204 };
|
||||
tai_support[1].plmn_support[0].nssai[2] = (nssai_t){ .sst = 3, .sd = 0x030205 };
|
||||
|
||||
/* ---- TAI 1 / PLMN 1 ---- */
|
||||
tai_support[1].plmn_support[1].plmn = plmn1;
|
||||
tai_support[1].plmn_support[1].num_nssai = 3;
|
||||
tai_support[1].plmn_support[1].nssai =
|
||||
calloc_or_fail(3, sizeof(nssai_t));
|
||||
|
||||
tai_support[1].plmn_support[1].nssai[0] = (nssai_t){ .sst = 4, .sd = 0x040203 };
|
||||
tai_support[1].plmn_support[1].nssai[1] = (nssai_t){ .sst = 4, .sd = 0x040204 };
|
||||
tai_support[1].plmn_support[1].nssai[2] = (nssai_t){ .sst = 4, .sd = 0x040205 };
|
||||
|
||||
/* ---------- create message ---------- */
|
||||
xnap_setup_resp_t orig = {
|
||||
.gNB_id = 0xABCDE,
|
||||
.plmn = plmn0,
|
||||
.num_tai = 2,
|
||||
.tai_support = tai_support,
|
||||
};
|
||||
/* ---------- encode ---------- */
|
||||
XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_response(&orig);
|
||||
XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc);
|
||||
xnap_msg_free(xnenc);
|
||||
|
||||
/* ---------- decode ---------- */
|
||||
xnap_setup_resp_t decoded = {0};
|
||||
bool ret = decode_xn_setup_response(&decoded, xndec);
|
||||
AssertFatal(ret, "decode_xn_setup_response failed");
|
||||
xnap_msg_free(xndec);
|
||||
|
||||
/* ---------- equality ---------- */
|
||||
ret = eq_xnap_setup_response(&orig, &decoded);
|
||||
AssertFatal(ret, "Xn Setup Response mismatch\n");
|
||||
free_xnap_setup_response(&decoded);
|
||||
free_xnap_setup_response(&orig);
|
||||
printf("%s() successful \n", __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. Xn Setup Failure
|
||||
*/
|
||||
static void test_xn_setup_failure(void)
|
||||
{
|
||||
/* ---------- create message ---------- */
|
||||
xnap_setup_failure_t orig = {
|
||||
.cause.type = XNAP_CAUSE_TRANSPORT,
|
||||
.cause.value = XNAP_CAUSE_TRANSPORT_LAYER_TRANSPORT_RESOURCE_UNAVAILABLE,
|
||||
};
|
||||
|
||||
/* ---------- encode ---------- */
|
||||
XNAP_XnAP_PDU_t *xnenc = encode_xn_setup_failure(&orig);
|
||||
XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc);
|
||||
xnap_msg_free(xnenc);
|
||||
|
||||
/* ---------- decode ---------- */
|
||||
xnap_setup_failure_t decoded = {0};
|
||||
bool ret = decode_xn_setup_failure(&decoded, xndec);
|
||||
AssertFatal(ret, "decode_xn_setup_failure failed");
|
||||
xnap_msg_free(xndec);
|
||||
|
||||
/* ---------- equality ---------- */
|
||||
ret = eq_xnap_setup_failure(&orig, &decoded);
|
||||
AssertFatal(ret, "Xn Setup Failure mismatch\n");
|
||||
free_xnap_setup_failure(&decoded);
|
||||
free_xnap_setup_failure(&orig);
|
||||
printf("%s() successful \n", __func__);
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("Starting XnAP Library Unit Tests...\n");
|
||||
|
||||
/* Xn Interface Testing */
|
||||
test_xn_setup_request();
|
||||
test_xn_setup_response();
|
||||
test_xn_setup_failure();
|
||||
|
||||
printf("All XnAP tests passed!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -497,6 +497,16 @@ do { \
|
||||
(bITsTRING)->bits_unused = 4; \
|
||||
} while(0)
|
||||
|
||||
#define MACRO_BIT_STRING_TO_GNB_ID(bITsTRING, oUT) \
|
||||
do { \
|
||||
uint8_t *_buf = (bITsTRING)->buf; \
|
||||
(oUT) = \
|
||||
((uint32_t)_buf[0] << 20) | \
|
||||
((uint32_t)_buf[1] << 12) | \
|
||||
((uint32_t)_buf[2] << 4) | \
|
||||
(((uint32_t)_buf[3] & 0xF0) >> 4); \
|
||||
} while (0)
|
||||
|
||||
/* TS 36.413 v10.9.0 section 9.2.1.38:
|
||||
* E-UTRAN CGI/Cell Identity
|
||||
* The leftmost bits of the Cell
|
||||
|
||||
Reference in New Issue
Block a user