|
| 1 | +/* |
| 2 | + * |
| 3 | + * Copyright 2021-2025 Software Radio Systems Limited |
| 4 | + * |
| 5 | + * By using this file, you agree to the terms and conditions set |
| 6 | + * forth in the LICENSE file which can be found at the top level of |
| 7 | + * the distribution. |
| 8 | + * |
| 9 | + */ |
| 10 | + |
| 11 | +#include "lib/e2/common/e2ap_asn1_packer.h" |
| 12 | +#include "lib/e2/e2sm/e2sm_kpm/e2sm_kpm_cu_meas_provider_impl.h" |
| 13 | +#include "lib/e2/e2sm/e2sm_kpm/e2sm_kpm_du_meas_provider_impl.h" |
| 14 | +#include "tests/unittests/e2/common/e2_test_helpers.h" |
| 15 | +#include "srsran/support/executors/task_worker.h" |
| 16 | +#include "srsran/support/srsran_test.h" |
| 17 | +#include <gtest/gtest.h> |
| 18 | + |
| 19 | +using namespace srsran; |
| 20 | + |
| 21 | +// Helper global variables to pass pcap_writer to all tests. |
| 22 | +bool g_enable_pcap = false; |
| 23 | +dlt_pcap* g_pcap = nullptr; |
| 24 | + |
| 25 | +class e2_agent_test_with_pcap : public e2_test_base_with_pcap |
| 26 | +{ |
| 27 | +protected: |
| 28 | + dlt_pcap* external_pcap_writer; |
| 29 | + |
| 30 | + void SetUp() override |
| 31 | + { |
| 32 | + external_pcap_writer = GetParam(); |
| 33 | + |
| 34 | + srslog::fetch_basic_logger("TEST").set_level(srslog::basic_levels::debug); |
| 35 | + srslog::init(); |
| 36 | + |
| 37 | + cfg = config_helpers::make_default_e2ap_config(); |
| 38 | + cfg.e2sm_kpm_enabled = true; |
| 39 | + |
| 40 | + gw = std::make_unique<dummy_network_gateway_data_handler>(); |
| 41 | + pcap = std::make_unique<dummy_e2ap_pcap>(); |
| 42 | + if (external_pcap_writer) { |
| 43 | + packer = std::make_unique<srsran::e2ap_asn1_packer>(*gw, *e2, *external_pcap_writer); |
| 44 | + } else { |
| 45 | + packer = std::make_unique<srsran::e2ap_asn1_packer>(*gw, *e2, *pcap); |
| 46 | + } |
| 47 | + e2_client = std::make_unique<dummy_e2_connection_client>(); |
| 48 | + du_metrics = std::make_unique<dummy_e2_du_metrics>(); |
| 49 | + f1ap_ue_id_mapper = std::make_unique<dummy_f1ap_ue_id_translator>(); |
| 50 | + factory = timer_factory{timers, task_worker}; |
| 51 | + du_rc_param_configurator = std::make_unique<dummy_du_configurator>(); |
| 52 | + e2agent = create_e2_du_agent(cfg, |
| 53 | + *e2_client, |
| 54 | + du_metrics.get(), |
| 55 | + f1ap_ue_id_mapper.get(), |
| 56 | + du_rc_param_configurator.get(), |
| 57 | + factory, |
| 58 | + task_worker); |
| 59 | + } |
| 60 | + |
| 61 | + void TearDown() override |
| 62 | + { |
| 63 | + // flush logger after each test |
| 64 | + srslog::flush(); |
| 65 | + pcap->close(); |
| 66 | + } |
| 67 | +}; |
| 68 | + |
| 69 | +TEST_P(e2_agent_test_with_pcap, e2_connection_update_failure) |
| 70 | +{ |
| 71 | + // We need this test to generate E2 Setup Request, so Wireshark can decode the following RIC indication messages. |
| 72 | + test_logger.info("Launch e2 setup request procedure with task worker..."); |
| 73 | + e2agent->start(); |
| 74 | + |
| 75 | + if (g_enable_pcap) { |
| 76 | + // Save E2 Setup Request |
| 77 | + packer->handle_message(e2_client->last_tx_e2_pdu); |
| 78 | + } |
| 79 | + |
| 80 | + // Need to send setup response, so the transaction can be completed. |
| 81 | + unsigned transaction_id = get_transaction_id(e2_client->last_tx_e2_pdu.pdu).value(); |
| 82 | + e2_message e2_setup_response = generate_e2_setup_response(transaction_id); |
| 83 | + e2_setup_response.pdu.successful_outcome() |
| 84 | + .value.e2setup_resp() |
| 85 | + ->ran_functions_accepted[0] |
| 86 | + ->ran_function_id_item() |
| 87 | + .ran_function_id = e2sm_kpm_asn1_packer::ran_func_id; |
| 88 | + test_logger.info("Injecting E2SetupResponse"); |
| 89 | + |
| 90 | + if (g_enable_pcap) { |
| 91 | + // Save E2 Setup Request (send to pcap) |
| 92 | + packer->handle_message(e2_setup_response); |
| 93 | + } |
| 94 | + e2agent->get_e2_interface().handle_message(e2_setup_response); |
| 95 | + |
| 96 | + // Inject packed E2 Connection Update. |
| 97 | + uint8_t e2_conn_upd[] = {0x00, 0x0b, 0x00, 0x1b, 0x00, 0x00, 0x02, 0x00, 0x31, 0x00, 0x02, |
| 98 | + 0x00, 0x03, 0x00, 0x2c, 0x00, 0x0e, 0x00, 0x00, 0x2b, 0x40, 0x09, |
| 99 | + 0x21, 0xf0, 0x0a, 0x2a, 0x00, 0x61, 0x8e, 0x45, 0x40}; |
| 100 | + byte_buffer e2_conn_upd_buf = byte_buffer::create(e2_conn_upd, e2_conn_upd + sizeof(e2_conn_upd)).value(); |
| 101 | + |
| 102 | + asn1::cbit_ref bref(e2_conn_upd_buf); |
| 103 | + e2_message e2_conn_upd_msg = {}; |
| 104 | + if (e2_conn_upd_msg.pdu.unpack(bref) != asn1::SRSASN_SUCCESS) { |
| 105 | + return; |
| 106 | + } |
| 107 | + if (g_enable_pcap) { |
| 108 | + // Save E2 Setup Request (send to pcap) |
| 109 | + packer->handle_message(e2_conn_upd_msg); |
| 110 | + } |
| 111 | + e2agent->get_e2_interface().handle_message(e2_conn_upd_msg); |
| 112 | + |
| 113 | + e2_message& msg = e2_client->last_tx_e2_pdu; |
| 114 | + if (g_enable_pcap) { |
| 115 | + // Save E2 Setup Request (send to pcap) |
| 116 | + packer->handle_message(msg); |
| 117 | + } |
| 118 | + |
| 119 | + // Currently, E2 Connection Update is not implemented, so always return failure. |
| 120 | + ASSERT_EQ(msg.pdu.type().value, asn1::e2ap::e2ap_pdu_c::types_opts::unsuccessful_outcome); |
| 121 | + ASSERT_EQ(msg.pdu.unsuccessful_outcome().value.type().value, |
| 122 | + asn1::e2ap::e2ap_elem_procs_o::unsuccessful_outcome_c::types_opts::e2conn_upd_fail); |
| 123 | + e2agent->stop(); |
| 124 | +} |
| 125 | + |
| 126 | +INSTANTIATE_TEST_SUITE_P(e2_agent_test_with_pcap, e2_agent_test_with_pcap, testing::Values(g_pcap)); |
| 127 | + |
| 128 | +int main(int argc, char** argv) |
| 129 | +{ |
| 130 | + // Check for '--enable_pcap' cmd line argument, do not use getopt as it interferes with gtest. |
| 131 | + for (int i = 1; i < argc; ++i) { |
| 132 | + std::string arg = argv[i]; |
| 133 | + if (arg == "--enable_pcap") { |
| 134 | + g_enable_pcap = true; |
| 135 | + } |
| 136 | + } |
| 137 | + |
| 138 | + srslog::init(); |
| 139 | + |
| 140 | + std::unique_ptr<task_worker_executor> pcap_exec; |
| 141 | + std::unique_ptr<task_worker> pcap_worker; |
| 142 | + std::unique_ptr<dlt_pcap> common_pcap_writer; |
| 143 | + |
| 144 | + if (g_enable_pcap) { |
| 145 | + pcap_worker = std::make_unique<task_worker>("pcap_worker", 128); |
| 146 | + pcap_exec = std::make_unique<task_worker_executor>(*pcap_worker); |
| 147 | + common_pcap_writer = create_e2ap_pcap("/tmp/e2_conn_upd_test.pcap", *pcap_exec); |
| 148 | + g_pcap = common_pcap_writer.get(); |
| 149 | + } |
| 150 | + |
| 151 | + ::testing::InitGoogleTest(&argc, argv); |
| 152 | + int ret = RUN_ALL_TESTS(); |
| 153 | + return ret; |
| 154 | +} |
0 commit comments