mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Assisted-by: Gemini:Flash-3.5 Signed-off-by: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
426 lines
16 KiB
C
426 lines
16 KiB
C
/*
|
|
* SPDX-License-Identifier: LicenseRef-CSSL-1.0
|
|
*/
|
|
|
|
/*
|
|
* \brief Test functions for XnAP encoding/decoding library
|
|
*/
|
|
|
|
#include <arpa/inet.h>
|
|
#include "common/utils/assertions.h"
|
|
#include "openair2/XNAP/lib/xnap_lib_common.h"
|
|
#include "openair2/XNAP/lib/xnap_gNB_interface_management.h"
|
|
#include "openair2/XNAP/lib/xnap_gNB_mobility_management.h"
|
|
|
|
#include "common/config/config_userapi.h"
|
|
|
|
configmodule_interface_t *uniqCfg = NULL;
|
|
|
|
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
|
{
|
|
UNUSED(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__);
|
|
}
|
|
|
|
/**
|
|
* 4. Xn Handover Request
|
|
*/
|
|
static void test_xn_handover_request(void)
|
|
{
|
|
/* ---------- Common identifiers ---------- */
|
|
plmn_id_t plmn0 = {.mcc = 208, .mnc = 95, .mnc_digit_length = 2};
|
|
|
|
/* ---------- Transport Layer Address (IPv4) ---------- */
|
|
transport_layer_addr_t tnl_addr_source = {.length = 4, .buffer = {192, 168, 1, 100}};
|
|
|
|
transport_layer_addr_t tnl_addr_n3 = {.length = 4, .buffer = {10, 0, 0, 1}};
|
|
|
|
/* ---------- S-NSSAI ---------- */
|
|
nssai_t nssai0 = {.sst = 1, .sd = 0x000001};
|
|
|
|
/* ---------- QoS Flow Level QoS Parameters ---------- */
|
|
xnap_qos_flow_param_t qos_params = {.qos_type = NON_DYNAMIC,
|
|
.nondyn = {.fiveQI = 9},
|
|
.arp = {.priority_level = 2,
|
|
.pre_emp_capability = PEC_SHALL_NOT_TRIGGER_PREEMPTION,
|
|
.pre_emp_vulnerability = PEV_NOT_PREEMPTABLE}};
|
|
|
|
/* ---------- QoS Flows To Be Setup List (Internet) ---------- */
|
|
xnap_qos_flow_tobe_setup_item_t *qos_list = calloc_or_fail(2, sizeof(*qos_list));
|
|
|
|
qos_list[0].qfi = 1;
|
|
qos_list[0].qos_params = qos_params;
|
|
|
|
qos_list[1].qfi = 2;
|
|
qos_list[1].qos_params = qos_params;
|
|
qos_list[1].qos_params.nondyn.fiveQI = 5;
|
|
|
|
/* ---------- QoS Flows (IMS) ---------- */
|
|
xnap_qos_flow_tobe_setup_item_t *qos_list_ims = calloc_or_fail(1, sizeof(*qos_list_ims));
|
|
|
|
qos_list_ims[0].qfi = 5;
|
|
qos_list_ims[0].qos_params = qos_params;
|
|
qos_list_ims[0].qos_params.nondyn.fiveQI = 2;
|
|
|
|
/* ---------- PDU Session Resources ---------- */
|
|
xnap_pdusession_resources_tobe_setup_item_t *pdusession_list = calloc_or_fail(2, sizeof(*pdusession_list));
|
|
|
|
/* ----- PDU Session 1 (Internet) ----- */
|
|
pdusession_list[0].pdusession_id = 1;
|
|
|
|
pdusession_list[0].nssai = calloc_or_fail(1, sizeof(nssai_t));
|
|
*pdusession_list[0].nssai = nssai0;
|
|
|
|
pdusession_list[0].n3_incoming = (gtpu_tunnel_t){.teid = 0x12345678, .addr = tnl_addr_n3};
|
|
|
|
pdusession_list[0].pdu_session_type = PDUSessionType_ipv4;
|
|
pdusession_list[0].num_qos = 2;
|
|
pdusession_list[0].qos_list = qos_list;
|
|
|
|
/* ----- PDU Session 2 (IMS) ----- */
|
|
nssai_t nssai_ims = {.sst = 1, .sd = 0x000002};
|
|
|
|
pdusession_list[1].pdusession_id = 2;
|
|
|
|
pdusession_list[1].nssai = calloc_or_fail(1, sizeof(nssai_t));
|
|
*pdusession_list[1].nssai = nssai_ims;
|
|
|
|
pdusession_list[1].n3_incoming = (gtpu_tunnel_t){.teid = 0x87654321, .addr = tnl_addr_n3};
|
|
|
|
pdusession_list[1].pdu_session_type = PDUSessionType_ipv4;
|
|
pdusession_list[1].num_qos = 1;
|
|
pdusession_list[1].qos_list = qos_list_ims;
|
|
|
|
/* ---------- UE Security Capabilities ---------- */
|
|
xnap_security_capabilities_t security_cap = {.nRencryption_algorithms = 0xC000,
|
|
.nRintegrity_algorithms = 0xC000,
|
|
.eUTRAencryption_algorithms = 0xC000,
|
|
.eUTRAintegrity_algorithms = 0xC000};
|
|
|
|
/* ---------- AS Security Key ---------- */
|
|
uint8_t as_key[32];
|
|
for (int i = 0; i < 32; i++)
|
|
as_key[i] = i;
|
|
|
|
/* ---------- RRC Context ---------- */
|
|
uint8_t rrc_data[] = {1, 2, 3, 4, 5};
|
|
byte_array_t rrc_context = {.buf = calloc_or_fail(5, sizeof(uint8_t)), .len = 5};
|
|
memcpy(rrc_context.buf, rrc_data, 5);
|
|
|
|
/* ---------- UE Context ---------- */
|
|
xnap_ue_context_info_t ue_context = {.ngc_ue_sig_ref = 0x123456789,
|
|
.cp_tnl_ip_source = tnl_addr_source,
|
|
.security_capabilities = security_cap,
|
|
.as_security_ncc = 1,
|
|
.ue_ambr = {.br_ul = 100000000, .br_dl = 200000000},
|
|
.rrc_context = rrc_context,
|
|
.num_pdu = 2,
|
|
.pdusession_resources_tobe_setup_list = pdusession_list};
|
|
|
|
memcpy(ue_context.as_security_key_ranstar, as_key, 32);
|
|
|
|
/* ---------- UE History Information ---------- */
|
|
ue_history_info_t *history_list = calloc_or_fail(1, sizeof(*history_list));
|
|
history_list[0].xnap_cell_type = XNAP_LastVisitedCell_Item_PR_nG_RAN_Cell;
|
|
|
|
uint8_t history_buf[] = {0x01, 0x02, 0x03, 0x04};
|
|
history_list[0].last_visited_cell_info.buf = calloc_or_fail(sizeof(history_buf), 1);
|
|
|
|
memcpy(history_list[0].last_visited_cell_info.buf, history_buf, sizeof(history_buf));
|
|
|
|
history_list[0].last_visited_cell_info.len = sizeof(history_buf);
|
|
|
|
/* ---------- GUAMI ---------- */
|
|
nr_guami_t guami = {.plmn = plmn0, .amf_region_id = 0x01, .amf_set_id = 0x0001, .amf_pointer = 0x01};
|
|
|
|
/* ---------- Target CGI ---------- */
|
|
xnap_ngran_cgi_t target_cgi = {.plmn_id = plmn0, .nrcell_id = 0x123456789};
|
|
|
|
/* ---------- Create message ---------- */
|
|
xnap_handover_req_t orig = {
|
|
.s_ng_node_ue_xnap_id = 0xABCD,
|
|
.cause = {.type = XNAP_CAUSE_RADIO_NETWORK, .value = XNAP_CAUSE_RADIO_NETWORK_LAYER_HANDOVER_DESIRABLE_FOR_RADIO_REASONS},
|
|
.target_cgi = target_cgi,
|
|
.guami = guami,
|
|
.ue_context = ue_context,
|
|
.num_last_visited_cells = 1,
|
|
.ue_history_info = history_list};
|
|
|
|
/* ---------- Encode ---------- */
|
|
XNAP_XnAP_PDU_t *xnenc = encode_xnap_handover_request(&orig);
|
|
XNAP_XnAP_PDU_t *xndec = xnap_encode_decode(xnenc);
|
|
xnap_msg_free(xnenc);
|
|
|
|
/* ---------- Decode ---------- */
|
|
xnap_handover_req_t decoded = {0};
|
|
bool ret = decode_xnap_handover_request(&decoded, xndec);
|
|
AssertFatal(ret, "decode_xnap_handover_request failed");
|
|
xnap_msg_free(xndec);
|
|
|
|
/* ---------- Equality ---------- */
|
|
ret = eq_xnap_handover_request(&orig, &decoded);
|
|
AssertFatal(ret, "Xn Handover Request mismatch\n");
|
|
|
|
/* ---------- Cleanup ---------- */
|
|
free_xnap_handover_request(&decoded);
|
|
free_xnap_handover_request(&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();
|
|
|
|
/* Xn Handover Testing*/
|
|
test_xn_handover_request();
|
|
|
|
printf("All XnAP tests passed!\n");
|
|
return 0;
|
|
}
|