From 39fcf25e0d1dfb080de3ed7d6fb39b741a6d9bd6 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 6 Dec 2019 11:49:01 +0000 Subject: [PATCH] added extra tests for handover. Did a some refactoring to move boilerplate out of the test mobility function --- srsenb/src/stack/rrc/rrc_mobility.cc | 2 +- srsenb/src/stack/upper/s1ap.cc | 1 + srsenb/test/common/dummy_classes.h | 16 ++ srsenb/test/upper/rrc_mobility_test.cc | 255 ++++++++++++++++--------- 4 files changed, 180 insertions(+), 94 deletions(-) diff --git a/srsenb/src/stack/rrc/rrc_mobility.cc b/srsenb/src/stack/rrc/rrc_mobility.cc index 329e4d403..19414bbe9 100644 --- a/srsenb/src/stack/rrc/rrc_mobility.cc +++ b/srsenb/src/stack/rrc/rrc_mobility.cc @@ -963,7 +963,7 @@ srslte::proc_outcome_t rrc::ue::rrc_mobility::sourceenb_ho_proc_t::react(ho_prep /* Send HO Command to UE */ parent->rrc_ue->send_dl_dcch(&dl_dcch_msg); - procInfo("Handover command of rnti=0x%x handled successfully.\n", parent->rrc_ue->rnti); + procInfo("HandoverCommand of rnti=0x%x handled successfully.\n", parent->rrc_ue->rnti); return srslte::proc_outcome_t::success; } diff --git a/srsenb/src/stack/upper/s1ap.cc b/srsenb/src/stack/upper/s1ap.cc index 91d7f7373..714e3a395 100644 --- a/srsenb/src/stack/upper/s1ap.cc +++ b/srsenb/src/stack/upper/s1ap.cc @@ -60,6 +60,7 @@ srslte::proc_outcome_t s1ap::ue::ho_prep_proc_t::init(uint32_t return srslte::proc_outcome_t::error; } + // Start HO preparation timer ue_ptr->ts1_reloc_prep.run(); return srslte::proc_outcome_t::yield; diff --git a/srsenb/test/common/dummy_classes.h b/srsenb/test/common/dummy_classes.h index 7f5c21e10..6b0524b5e 100644 --- a/srsenb/test/common/dummy_classes.h +++ b/srsenb/test/common/dummy_classes.h @@ -26,6 +26,22 @@ namespace srsenb { +class mac_dummy : public mac_interface_rrc +{ +public: + int cell_cfg(sched_interface::cell_cfg_t* cell_cfg) override { return 0; } + void reset() override {} + int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override { return 0; } + int ue_rem(uint16_t rnti) override { return 0; } + int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) override { return 0; } + int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) override { return 0; } + int set_dl_ant_info(uint16_t rnti, asn1::rrc::phys_cfg_ded_s::ant_info_c_* dl_ant_info) override { return 0; } + void phy_config_enabled(uint16_t rnti, bool enabled) override {} + void write_mcch(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s* mcch) override + { + } +}; + class rlc_dummy : public rlc_interface_rrc { public: diff --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index 1d228d2c8..d556c4ee5 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -91,24 +91,25 @@ public: } }; -} // namespace test_dummies - -class mac_dummy : public mac_interface_rrc +class pdcp_mobility_dummy : public pdcp_dummy { public: - int cell_cfg(sched_interface::cell_cfg_t* cell_cfg) override { return 0; } - void reset() override {} - int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override { return 0; } - int ue_rem(uint16_t rnti) override { return 0; } - int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t* cfg) override { return 0; } - int bearer_ue_rem(uint16_t rnti, uint32_t lc_id) override { return 0; } - int set_dl_ant_info(uint16_t rnti, asn1::rrc::phys_cfg_ded_s::ant_info_c_* dl_ant_info) override { return 0; } - void phy_config_enabled(uint16_t rnti, bool enabled) override {} - void write_mcch(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s* mcch) override + struct last_sdu_t { + uint16_t rnti; + uint32_t lcid; + srslte::unique_byte_buffer_t sdu; + } last_sdu; + + void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) override { + last_sdu.rnti = rnti; + last_sdu.lcid = lcid; + last_sdu.sdu = std::move(sdu); } }; +} // namespace test_dummies + meas_cell_cfg_t generate_cell1() { meas_cell_cfg_t cell1{}; @@ -317,51 +318,43 @@ int test_correct_meascfg_calculation() return SRSLTE_SUCCESS; } -int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args) -{ - args = {}; - *rrc_cfg = {}; - args.enb_files.sib_config = argparse::repository_dir + "/sib.conf.example"; - args.enb_files.rr_config = argparse::repository_dir + "/rr.conf.example"; - args.enb_files.drb_config = argparse::repository_dir + "/drb.conf.example"; - log_h.debug("sib file path=%s\n", args.enb_files.sib_config.c_str()); +namespace test_helpers { - args.enb.dl_earfcn = 3400; - args.enb.n_prb = 50; - TESTASSERT(srslte::string_to_mcc("001", &args.stack.s1ap.mcc)); - TESTASSERT(srslte::string_to_mnc("01", &args.stack.s1ap.mnc)); - args.enb.transmission_mode = 1; - args.enb.nof_ports = 1; - args.general.eia_pref_list = "EIA2, EIA1, EIA0"; - args.general.eea_pref_list = "EEA0, EEA2, EEA1"; +int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args); +void copy_msg_to_buffer(srslte::unique_byte_buffer_t& pdu, uint8_t* msg, size_t nof_bytes); +int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, uint16_t rnti); - phy_cfg_t phy_cfg; - - return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &phy_cfg); -} +} // namespace test_helpers struct mobility_test_params { - enum class test_fail_at { never, wrong_measreport } fail_at; + enum class test_fail_at { success, wrong_measreport, concurrent_ho, ho_prep_failure } fail_at; + const char* to_string() + { + switch (fail_at) { + case test_fail_at::success: + return "success"; + case test_fail_at::wrong_measreport: + return "wrong measreport"; + case test_fail_at::concurrent_ho: + return "measreport while in handover"; + case test_fail_at::ho_prep_failure: + return "ho preparation failure"; + default: + return "none"; + } + } }; int test_mobility_class(mobility_test_params test_params) { - log_h.info("----- TEST: test_mobility_class() -----\n"); - srslte::log_filter s1ap_log("S1AP"); + printf("\n===== TEST: test_mobility_class() for event \"%s\" =====\n", test_params.to_string()); srslte::scoped_tester_log rrc_log("RRC "); srslte::timer_handler timers; - srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); srslte::unique_byte_buffer_t pdu; - auto copy_msg_to_buffer = [pool](srslte::unique_byte_buffer_t& pdu, uint8_t* msg, size_t nof_bytes) { - pdu = srslte::allocate_unique_buffer(*pool, true); - memcpy(pdu->msg, msg, nof_bytes); - pdu->N_bytes = nof_bytes; - }; - srsenb::all_args_t args; rrc_cfg_t cfg; - TESTASSERT(parse_default_cfg(&cfg, args) == SRSLTE_SUCCESS); + TESTASSERT(test_helpers::parse_default_cfg(&cfg, args) == SRSLTE_SUCCESS); report_cfg_eutra_s rep = generate_rep1(); cfg.meas_cfg.meas_reports.push_back(rep); meas_cell_cfg_t cell2 = generate_cell1(); @@ -372,14 +365,12 @@ int test_mobility_class(mobility_test_params test_params) srsenb::rrc rrc; mac_dummy mac; rlc_dummy rlc; - pdcp_dummy pdcp; + test_dummies::pdcp_mobility_dummy pdcp; phy_dummy phy; test_dummies::s1ap_mobility_dummy s1ap; gtpu_dummy gtpu; - rrc_log.set_level(srslte::LOG_LEVEL_INFO); + rrc_log.set_level(srslte::LOG_LEVEL_NONE); rrc_log.set_hex_limit(1024); - s1ap_log.set_level(srslte::LOG_LEVEL_INFO); - s1ap_log.set_hex_limit(1024); rrc.init(&cfg, &phy, &mac, &rlc, &pdcp, &s1ap, >pu, &timers, &rrc_log); auto tic = [&timers, &rrc] { @@ -390,65 +381,42 @@ int test_mobility_class(mobility_test_params test_params) uint16_t rnti = 0x46; rrc.add_user(rnti); - // Send RRCConnectionRequest - uint8_t rrc_conn_request[] = {0x40, 0x12, 0xf6, 0xfb, 0xe2, 0xc6}; - copy_msg_to_buffer(pdu, rrc_conn_request, sizeof(rrc_conn_request)); - rrc.write_pdu(rnti, 0, std::move(pdu)); - tic(); + // Do all the handshaking until the first RRC Connection Reconf + test_helpers::bring_rrc_to_reconf_state(rrc, timers, rnti); - // Send RRCConnectionSetupComplete - uint8_t rrc_conn_setup_complete[] = {0x20, 0x00, 0x40, 0x2e, 0x90, 0x50, 0x49, 0xe8, 0x06, 0x0e, 0x82, 0xa2, - 0x17, 0xec, 0x13, 0xe2, 0x0f, 0x00, 0x02, 0x02, 0x5e, 0xdf, 0x7c, 0x58, - 0x05, 0xc0, 0xc0, 0x00, 0x08, 0x04, 0x03, 0xa0, 0x23, 0x23, 0xc0}; - copy_msg_to_buffer(pdu, rrc_conn_setup_complete, sizeof(rrc_conn_setup_complete)); - rrc.write_pdu(rnti, 1, std::move(pdu)); - tic(); - - // S1AP receives InitialContextSetupRequest and forwards it to RRC - uint8_t s1ap_init_ctxt_setup_req[] = { - 0x00, 0x09, 0x00, 0x80, 0xc6, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x08, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x42, 0x00, 0x0a, 0x18, 0x3b, 0x9a, 0xca, 0x00, 0x60, 0x3b, 0x9a, 0xca, 0x00, 0x00, 0x18, 0x00, 0x78, - 0x00, 0x00, 0x34, 0x00, 0x73, 0x45, 0x00, 0x09, 0x3c, 0x0f, 0x80, 0x0a, 0x00, 0x21, 0xf0, 0xb7, 0x36, 0x1c, 0x56, - 0x64, 0x27, 0x3e, 0x5b, 0x04, 0xb7, 0x02, 0x07, 0x42, 0x02, 0x3e, 0x06, 0x00, 0x09, 0xf1, 0x07, 0x00, 0x07, 0x00, - 0x37, 0x52, 0x66, 0xc1, 0x01, 0x09, 0x1b, 0x07, 0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, - 0x30, 0x37, 0x30, 0x06, 0x6d, 0x63, 0x63, 0x39, 0x30, 0x31, 0x04, 0x67, 0x70, 0x72, 0x73, 0x05, 0x01, 0xc0, 0xa8, - 0x03, 0x02, 0x27, 0x0e, 0x80, 0x80, 0x21, 0x0a, 0x03, 0x00, 0x00, 0x0a, 0x81, 0x06, 0x08, 0x08, 0x08, 0x08, 0x50, - 0x0b, 0xf6, 0x09, 0xf1, 0x07, 0x80, 0x01, 0x01, 0xf6, 0x7e, 0x72, 0x69, 0x13, 0x09, 0xf1, 0x07, 0x00, 0x01, 0x23, - 0x05, 0xf4, 0xf6, 0x7e, 0x72, 0x69, 0x00, 0x6b, 0x00, 0x05, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x49, 0x00, 0x20, - 0x45, 0x25, 0xe4, 0x9a, 0x77, 0xc8, 0xd5, 0xcf, 0x26, 0x33, 0x63, 0xeb, 0x5b, 0xb9, 0xc3, 0x43, 0x9b, 0x9e, 0xb3, - 0x86, 0x1f, 0xa8, 0xa7, 0xcf, 0x43, 0x54, 0x07, 0xae, 0x42, 0x2b, 0x63, 0xb9}; - LIBLTE_S1AP_S1AP_PDU_STRUCT s1ap_pdu; - LIBLTE_BYTE_MSG_STRUCT byte_buf; - byte_buf.N_bytes = sizeof(s1ap_init_ctxt_setup_req); - memcpy(byte_buf.msg, s1ap_init_ctxt_setup_req, byte_buf.N_bytes); - liblte_s1ap_unpack_s1ap_pdu(&byte_buf, &s1ap_pdu); - rrc.setup_ue_ctxt(rnti, &s1ap_pdu.choice.initiatingMessage.choice.InitialContextSetupRequest); - tic(); - - // Send SecurityModeComplete - uint8_t sec_mode_complete[] = {0x28, 0x00}; - copy_msg_to_buffer(pdu, sec_mode_complete, sizeof(sec_mode_complete)); - rrc.write_pdu(rnti, 1, std::move(pdu)); - tic(); + rrc_log.set_level(srslte::LOG_LEVEL_INFO); /* Receive MeasReport from UE (correct if PCI=2) */ if (test_params.fail_at == mobility_test_params::test_fail_at::wrong_measreport) { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x0D, 0xBC, 0x80}; // PCI == 3 - copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); + test_helpers::copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); } else { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x09, 0xBC, 0x80}; // PCI == 2 - copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); + test_helpers::copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); } rrc.write_pdu(rnti, 1, std::move(pdu)); tic(); + /* Test Case: the MeasReport is not valid */ if (test_params.fail_at == mobility_test_params::test_fail_at::wrong_measreport) { TESTASSERT(s1ap.last_ho_required.rrc_container == nullptr); TESTASSERT(rrc_log.error_counter == 1); return SRSLTE_SUCCESS; } - // Check HO Required was sent to S1AP + /* Test Case: Multiple concurrent MeasReports arrived. Only one HO procedure should be running */ + if (test_params.fail_at == mobility_test_params::test_fail_at::concurrent_ho) { + s1ap.last_ho_required = {}; + uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x09, 0xBC, 0x80}; // PCI == 2 + test_helpers::copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); + rrc.write_pdu(rnti, 1, std::move(pdu)); + tic(); + TESTASSERT(s1ap.last_ho_required.rrc_container == nullptr); + TESTASSERT(rrc_log.error_counter == 1); + return SRSLTE_SUCCESS; + } + + /* Check HO Required was sent to S1AP */ TESTASSERT(s1ap.last_ho_required.rnti == rnti); TESTASSERT(s1ap.last_ho_required.target_eci == cell2.eci); TESTASSERT(s1ap.last_ho_required.target_plmn.to_string() == "00101"); @@ -463,8 +431,20 @@ int test_mobility_class(mobility_test_params test_params) TESTASSERT(hoprepr8.as_cfg.source_rr_cfg.drb_to_add_mod_list[0].drb_id == 1); } - // MME returns back an HandoverCommand - // TODO + /* Test Case: HandoverPreparation has failed */ + if (test_params.fail_at == mobility_test_params::test_fail_at::ho_prep_failure) { + rrc.ho_preparation_complete(rnti, false, nullptr); + TESTASSERT(rrc_log.error_counter == 1); + return SRSLTE_SUCCESS; + } + + /* MME returns back an HandoverCommand, S1AP unwraps the RRC container */ + uint8_t ho_cmd_rrc_container[] = {0x01, 0xa9, 0x00, 0xd9, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x22, 0x04, 0x00, 0x00, + 0x01, 0x48, 0x04, 0xbc, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0xa0, 0x07, 0xa0, + 0x10, 0x00, 0x01, 0x00, 0x05, 0x00, 0xa7, 0xd0, 0xc1, 0xf6, 0xaf, 0x3e, 0x12, 0xcc, + 0x86, 0x0d, 0x30, 0x00, 0x0b, 0x5a, 0x02, 0x17, 0x86, 0x00, 0x05, 0xa0, 0x20}; + test_helpers::copy_msg_to_buffer(pdu, ho_cmd_rrc_container, sizeof(ho_cmd_rrc_container)); + rrc.ho_preparation_complete(rnti, true, std::move(pdu)); TESTASSERT(rrc_log.error_counter == 0); return SRSLTE_SUCCESS; @@ -482,10 +462,99 @@ int main(int argc, char** argv) TESTASSERT(test_correct_insertion() == 0); TESTASSERT(test_correct_meascfg_calculation() == 0); - TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::never}) == 0); TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::wrong_measreport}) == 0); + TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::concurrent_ho}) == 0); + TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::ho_prep_failure}) == 0); + TESTASSERT(test_mobility_class(mobility_test_params{mobility_test_params::test_fail_at::success}) == 0); - printf("Success\n"); + printf("\nSuccess\n"); return 0; } + +namespace test_helpers { + +int parse_default_cfg(rrc_cfg_t* rrc_cfg, srsenb::all_args_t& args) +{ + args = {}; + *rrc_cfg = {}; + args.enb_files.sib_config = argparse::repository_dir + "/sib.conf.example"; + args.enb_files.rr_config = argparse::repository_dir + "/rr.conf.example"; + args.enb_files.drb_config = argparse::repository_dir + "/drb.conf.example"; + log_h.debug("sib file path=%s\n", args.enb_files.sib_config.c_str()); + + args.enb.dl_earfcn = 3400; + args.enb.n_prb = 50; + TESTASSERT(srslte::string_to_mcc("001", &args.stack.s1ap.mcc)); + TESTASSERT(srslte::string_to_mnc("01", &args.stack.s1ap.mnc)); + args.enb.transmission_mode = 1; + args.enb.nof_ports = 1; + args.general.eia_pref_list = "EIA2, EIA1, EIA0"; + args.general.eea_pref_list = "EEA0, EEA2, EEA1"; + + phy_cfg_t phy_cfg; + + return enb_conf_sections::parse_cfg_files(&args, rrc_cfg, &phy_cfg); +} + +void copy_msg_to_buffer(srslte::unique_byte_buffer_t& pdu, uint8_t* msg, size_t nof_bytes) +{ + srslte::byte_buffer_pool* pool = srslte::byte_buffer_pool::get_instance(); + pdu = srslte::allocate_unique_buffer(*pool, true); + memcpy(pdu->msg, msg, nof_bytes); + pdu->N_bytes = nof_bytes; +}; + +int bring_rrc_to_reconf_state(srsenb::rrc& rrc, srslte::timer_handler& timers, uint16_t rnti) +{ + srslte::unique_byte_buffer_t pdu; + + // Send RRCConnectionRequest + uint8_t rrc_conn_request[] = {0x40, 0x12, 0xf6, 0xfb, 0xe2, 0xc6}; + copy_msg_to_buffer(pdu, rrc_conn_request, sizeof(rrc_conn_request)); + rrc.write_pdu(rnti, 0, std::move(pdu)); + timers.step_all(); + rrc.tti_clock(); + + // Send RRCConnectionSetupComplete + uint8_t rrc_conn_setup_complete[] = {0x20, 0x00, 0x40, 0x2e, 0x90, 0x50, 0x49, 0xe8, 0x06, 0x0e, 0x82, 0xa2, + 0x17, 0xec, 0x13, 0xe2, 0x0f, 0x00, 0x02, 0x02, 0x5e, 0xdf, 0x7c, 0x58, + 0x05, 0xc0, 0xc0, 0x00, 0x08, 0x04, 0x03, 0xa0, 0x23, 0x23, 0xc0}; + copy_msg_to_buffer(pdu, rrc_conn_setup_complete, sizeof(rrc_conn_setup_complete)); + rrc.write_pdu(rnti, 1, std::move(pdu)); + timers.step_all(); + rrc.tti_clock(); + + // S1AP receives InitialContextSetupRequest and forwards it to RRC + uint8_t s1ap_init_ctxt_setup_req[] = { + 0x00, 0x09, 0x00, 0x80, 0xc6, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x02, 0x00, 0x64, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x42, 0x00, 0x0a, 0x18, 0x3b, 0x9a, 0xca, 0x00, 0x60, 0x3b, 0x9a, 0xca, 0x00, 0x00, 0x18, 0x00, 0x78, + 0x00, 0x00, 0x34, 0x00, 0x73, 0x45, 0x00, 0x09, 0x3c, 0x0f, 0x80, 0x0a, 0x00, 0x21, 0xf0, 0xb7, 0x36, 0x1c, 0x56, + 0x64, 0x27, 0x3e, 0x5b, 0x04, 0xb7, 0x02, 0x07, 0x42, 0x02, 0x3e, 0x06, 0x00, 0x09, 0xf1, 0x07, 0x00, 0x07, 0x00, + 0x37, 0x52, 0x66, 0xc1, 0x01, 0x09, 0x1b, 0x07, 0x74, 0x65, 0x73, 0x74, 0x31, 0x32, 0x33, 0x06, 0x6d, 0x6e, 0x63, + 0x30, 0x37, 0x30, 0x06, 0x6d, 0x63, 0x63, 0x39, 0x30, 0x31, 0x04, 0x67, 0x70, 0x72, 0x73, 0x05, 0x01, 0xc0, 0xa8, + 0x03, 0x02, 0x27, 0x0e, 0x80, 0x80, 0x21, 0x0a, 0x03, 0x00, 0x00, 0x0a, 0x81, 0x06, 0x08, 0x08, 0x08, 0x08, 0x50, + 0x0b, 0xf6, 0x09, 0xf1, 0x07, 0x80, 0x01, 0x01, 0xf6, 0x7e, 0x72, 0x69, 0x13, 0x09, 0xf1, 0x07, 0x00, 0x01, 0x23, + 0x05, 0xf4, 0xf6, 0x7e, 0x72, 0x69, 0x00, 0x6b, 0x00, 0x05, 0x18, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x49, 0x00, 0x20, + 0x45, 0x25, 0xe4, 0x9a, 0x77, 0xc8, 0xd5, 0xcf, 0x26, 0x33, 0x63, 0xeb, 0x5b, 0xb9, 0xc3, 0x43, 0x9b, 0x9e, 0xb3, + 0x86, 0x1f, 0xa8, 0xa7, 0xcf, 0x43, 0x54, 0x07, 0xae, 0x42, 0x2b, 0x63, 0xb9}; + LIBLTE_S1AP_S1AP_PDU_STRUCT s1ap_pdu; + LIBLTE_BYTE_MSG_STRUCT byte_buf; + byte_buf.N_bytes = sizeof(s1ap_init_ctxt_setup_req); + memcpy(byte_buf.msg, s1ap_init_ctxt_setup_req, byte_buf.N_bytes); + liblte_s1ap_unpack_s1ap_pdu(&byte_buf, &s1ap_pdu); + rrc.setup_ue_ctxt(rnti, &s1ap_pdu.choice.initiatingMessage.choice.InitialContextSetupRequest); + timers.step_all(); + rrc.tti_clock(); + + // Send SecurityModeComplete + uint8_t sec_mode_complete[] = {0x28, 0x00}; + copy_msg_to_buffer(pdu, sec_mode_complete, sizeof(sec_mode_complete)); + rrc.write_pdu(rnti, 1, std::move(pdu)); + timers.step_all(); + rrc.tti_clock(); + + return SRSLTE_SUCCESS; +} + +} // namespace test_helpers