diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 2555adc2f..e00a85834 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -596,8 +596,8 @@ void rrc::ue::send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu) } apply_reconf_phy_config(reconfig_r8); - phy_cfg->sched_request_cfg.setup().sr_cfg_idx = cell_ded_list.get_sr_res()->sr_I; - phy_cfg->sched_request_cfg.setup().sr_cfg_idx = cell_ded_list.get_sr_res()->sr_N_pucch; + phy_cfg->sched_request_cfg.setup().sr_cfg_idx = cell_ded_list.get_sr_res()->sr_I; + phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx = cell_ded_list.get_sr_res()->sr_N_pucch; pdu->clear(); diff --git a/srsenb/test/upper/rrc_mobility_test.cc b/srsenb/test/upper/rrc_mobility_test.cc index 6a98bd0a4..2a10ed0a8 100644 --- a/srsenb/test/upper/rrc_mobility_test.cc +++ b/srsenb/test/upper/rrc_mobility_test.cc @@ -238,20 +238,29 @@ int test_correct_meascfg_calculation() } struct mobility_test_params { - enum class test_fail_at { success, wrong_measreport, concurrent_ho, ho_prep_failure, recover } fail_at; + enum class test_event { + success, + wrong_measreport, + concurrent_ho, + ho_prep_failure, + duplicate_crnti_ce, + recover + } fail_at; const char* to_string() { switch (fail_at) { - case test_fail_at::success: + case test_event::success: return "success"; - case test_fail_at::wrong_measreport: + case test_event::wrong_measreport: return "wrong measreport"; - case test_fail_at::concurrent_ho: + case test_event::concurrent_ho: return "measreport while in handover"; - case test_fail_at::ho_prep_failure: + case test_event::ho_prep_failure: return "ho preparation failure"; - case test_fail_at::recover: + case test_event::recover: return "fail and success"; + case test_event::duplicate_crnti_ce: + return "duplicate CRNTI CE"; default: return "none"; } @@ -282,8 +291,8 @@ struct mobility_tester { rrc_cfg_t cfg; srsenb::rrc rrc; - mac_dummy mac; - rlc_dummy rlc; + test_dummies::mac_mobility_dummy mac; + test_dummies::rlc_mobility_dummy rlc; test_dummies::pdcp_mobility_dummy pdcp; phy_dummy phy; test_dummies::s1ap_mobility_dummy s1ap; @@ -364,7 +373,7 @@ int test_s1ap_mobility(mobility_test_params test_params) test_dummies::s1ap_mobility_dummy& s1ap = tester.s1ap; /* Receive MeasReport from UE (correct if PCI=2) */ - if (test_params.fail_at == mobility_test_params::test_fail_at::wrong_measreport) { + if (test_params.fail_at == mobility_test_params::test_event::wrong_measreport) { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x0D, 0xBC, 0x80}; // PCI == 3 test_helpers::copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); } else { @@ -375,7 +384,7 @@ int test_s1ap_mobility(mobility_test_params test_params) tester.tic(); /* Test Case: the MeasReport is not valid */ - if (test_params.fail_at == mobility_test_params::test_fail_at::wrong_measreport) { + if (test_params.fail_at == mobility_test_params::test_event::wrong_measreport) { TESTASSERT(s1ap.last_ho_required.rrc_container == nullptr); TESTASSERT(tester.rrc_log->warn_counter == 1); return SRSLTE_SUCCESS; @@ -383,7 +392,7 @@ int test_s1ap_mobility(mobility_test_params test_params) TESTASSERT(s1ap.last_ho_required.rrc_container != nullptr); /* 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) { + if (test_params.fail_at == mobility_test_params::test_event::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)); @@ -409,7 +418,7 @@ int test_s1ap_mobility(mobility_test_params test_params) } /* Test Case: HandoverPreparation has failed */ - if (test_params.fail_at == mobility_test_params::test_fail_at::ho_prep_failure) { + if (test_params.fail_at == mobility_test_params::test_event::ho_prep_failure) { tester.rrc.ho_preparation_complete(tester.rnti, false, nullptr); // TESTASSERT(rrc_log->error_counter == 1); TESTASSERT(not s1ap.last_enb_status.status_present); @@ -444,9 +453,10 @@ int test_intraenb_mobility(mobility_test_params test_params) TESTASSERT(tester.setup_rrc() == SRSLTE_SUCCESS); TESTASSERT(tester.run_preamble() == SRSLTE_SUCCESS); tester.pdcp.last_sdu.sdu = nullptr; + tester.rlc.test_reset_all(); /* Receive MeasReport from UE (correct if PCI=2) */ - if (test_params.fail_at == mobility_test_params::test_fail_at::wrong_measreport) { + if (test_params.fail_at == mobility_test_params::test_event::wrong_measreport) { uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x0D, 0xBC, 0x80}; // PCI == 3 test_helpers::copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); } else { @@ -458,7 +468,7 @@ int test_intraenb_mobility(mobility_test_params test_params) TESTASSERT(tester.s1ap.last_ho_required.rrc_container == nullptr); /* Test Case: the MeasReport is not valid */ - if (test_params.fail_at == mobility_test_params::test_fail_at::wrong_measreport) { + if (test_params.fail_at == mobility_test_params::test_event::wrong_measreport) { TESTASSERT(tester.rrc_log->warn_counter == 1); TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); return SRSLTE_SUCCESS; @@ -468,7 +478,7 @@ int test_intraenb_mobility(mobility_test_params test_params) TESTASSERT(not tester.s1ap.last_enb_status.status_present); /* 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) { + if (test_params.fail_at == mobility_test_params::test_event::concurrent_ho) { tester.pdcp.last_sdu = {}; 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)); @@ -488,6 +498,54 @@ int test_intraenb_mobility(mobility_test_params test_params) TESTASSERT(recfg_r8.mob_ctrl_info_present); TESTASSERT(recfg_r8.mob_ctrl_info.new_ue_id.to_number() == tester.rnti); TESTASSERT(recfg_r8.mob_ctrl_info.target_pci == 2); + TESTASSERT(recfg_r8.rr_cfg_ded_present); + TESTASSERT(recfg_r8.rr_cfg_ded.phys_cfg_ded_present); + const asn1::rrc::phys_cfg_ded_s& phy_cfg_ded = recfg_r8.rr_cfg_ded.phys_cfg_ded; + TESTASSERT(phy_cfg_ded.sched_request_cfg_present); + TESTASSERT(phy_cfg_ded.cqi_report_cfg_present); + + /* Test Case: The UE sends a C-RNTI CE. Bearers are reestablished */ + tester.pdcp.last_sdu.sdu = nullptr; + tester.rrc.upd_user(tester.rnti + 1, tester.rnti); + TESTASSERT(tester.rlc.ue_db[tester.rnti].reest_sdu_counter == 0); + TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); + + /* Test Case: The UE receives a duplicate C-RNTI CE. Nothing should happen */ + if (test_params.fail_at == mobility_test_params::test_event::duplicate_crnti_ce) { + TESTASSERT(tester.rlc.ue_db[tester.rnti].reest_sdu_counter == 0); + tester.rrc.upd_user(tester.rnti + 2, tester.rnti); + TESTASSERT(tester.rlc.ue_db[tester.rnti].reest_sdu_counter == 0); + TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); + TESTASSERT(tester.rlc.ue_db[tester.rnti].last_sdu == nullptr); // No Reject sent + } + + /* Test Case: Terminate first Handover. No extra messages should be sent DL. SR/CQI resources match recfg message */ + uint8_t recfg_complete[] = {0x10, 0x00}; + test_helpers::copy_msg_to_buffer(pdu, recfg_complete, sizeof(recfg_complete)); + tester.rrc.write_pdu(tester.rnti, rb_id_t::RB_ID_SRB2, std::move(pdu)); + TESTASSERT(tester.pdcp.last_sdu.sdu == nullptr); + sched_interface::ue_cfg_t& ue_cfg = tester.mac.ue_db[tester.rnti]; + TESTASSERT(ue_cfg.pucch_cfg.sr_configured); + TESTASSERT(ue_cfg.pucch_cfg.n_pucch_sr == phy_cfg_ded.sched_request_cfg.setup().sr_pucch_res_idx); + TESTASSERT(ue_cfg.pucch_cfg.I_sr == phy_cfg_ded.sched_request_cfg.setup().sr_cfg_idx); + TESTASSERT(ue_cfg.dl_cfg.cqi_report.pmi_idx == + phy_cfg_ded.cqi_report_cfg.cqi_report_periodic.setup().cqi_pmi_cfg_idx); + TESTASSERT(ue_cfg.pucch_cfg.n_pucch == phy_cfg_ded.cqi_report_cfg.cqi_report_periodic.setup().cqi_pucch_res_idx); + + /* Test Case: The RRC should be able to start a new handover */ + uint8_t meas_report[] = {0x08, 0x10, 0x38, 0x74, 0x00, 0x05, 0xBC, 0x80}; // PCI == 1 + test_helpers::copy_msg_to_buffer(pdu, meas_report, sizeof(meas_report)); + tester.rrc.write_pdu(tester.rnti, 1, std::move(pdu)); + tester.tic(); + TESTASSERT(tester.s1ap.last_ho_required.rrc_container == nullptr); + TESTASSERT(tester.pdcp.last_sdu.sdu != nullptr); + TESTASSERT(tester.s1ap.last_ho_required.rrc_container == nullptr); + TESTASSERT(not tester.s1ap.last_enb_status.status_present); + TESTASSERT(test_helpers::unpack_asn1(ho_cmd, tester.pdcp.last_sdu.sdu)); + recfg_r8 = ho_cmd.msg.c1().rrc_conn_recfg().crit_exts.c1().rrc_conn_recfg_r8(); + TESTASSERT(recfg_r8.mob_ctrl_info_present); + TESTASSERT(recfg_r8.mob_ctrl_info.new_ue_id.to_number() == tester.rnti); + TESTASSERT(recfg_r8.mob_ctrl_info.target_pci == 1); return SRSLTE_SUCCESS; } @@ -495,7 +553,7 @@ int test_intraenb_mobility(mobility_test_params test_params) int main(int argc, char** argv) { srslte::logmap::set_default_log_level(srslte::LOG_LEVEL_INFO); - using fail_at = mobility_test_params::test_fail_at; + using event = mobility_test_params::test_event; if (argc < 3) { argparse::usage(argv[0]); @@ -506,15 +564,16 @@ int main(int argc, char** argv) TESTASSERT(test_correct_meascfg_calculation() == 0); // S1AP Handover - TESTASSERT(test_s1ap_mobility(mobility_test_params{fail_at::wrong_measreport}) == 0); - TESTASSERT(test_s1ap_mobility(mobility_test_params{fail_at::concurrent_ho}) == 0); - TESTASSERT(test_s1ap_mobility(mobility_test_params{fail_at::ho_prep_failure}) == 0); - TESTASSERT(test_s1ap_mobility(mobility_test_params{fail_at::success}) == 0); + TESTASSERT(test_s1ap_mobility(mobility_test_params{event::wrong_measreport}) == 0); + TESTASSERT(test_s1ap_mobility(mobility_test_params{event::concurrent_ho}) == 0); + TESTASSERT(test_s1ap_mobility(mobility_test_params{event::ho_prep_failure}) == 0); + TESTASSERT(test_s1ap_mobility(mobility_test_params{event::success}) == 0); // intraeNB Handover - TESTASSERT(test_intraenb_mobility(mobility_test_params{fail_at::wrong_measreport}) == 0); - TESTASSERT(test_intraenb_mobility(mobility_test_params{fail_at::concurrent_ho}) == 0); - TESTASSERT(test_intraenb_mobility(mobility_test_params{fail_at::success}) == 0); + TESTASSERT(test_intraenb_mobility(mobility_test_params{event::wrong_measreport}) == 0); + TESTASSERT(test_intraenb_mobility(mobility_test_params{event::concurrent_ho}) == 0); + TESTASSERT(test_intraenb_mobility(mobility_test_params{event::duplicate_crnti_ce}) == 0); + TESTASSERT(test_intraenb_mobility(mobility_test_params{event::success}) == 0); printf("\nSuccess\n"); diff --git a/srsenb/test/upper/test_helpers.h b/srsenb/test/upper/test_helpers.h index 30886cb47..8223c76a5 100644 --- a/srsenb/test/upper/test_helpers.h +++ b/srsenb/test/upper/test_helpers.h @@ -122,6 +122,44 @@ public: } }; +class rlc_mobility_dummy : public rlc_dummy +{ +public: + struct ue_ctxt { + int nof_pdcp_sdus = 0, reest_sdu_counter = 0; + uint32_t last_lcid = 0; + srslte::unique_byte_buffer_t last_sdu; + }; + std::map ue_db; + + void test_reset_all() + { + for (auto& u : ue_db) { + u.second = {}; + } + } + + void write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu) override + { + ue_db[rnti].nof_pdcp_sdus++; + ue_db[rnti].reest_sdu_counter++; + ue_db[rnti].last_lcid = lcid; + ue_db[rnti].last_sdu = std::move(sdu); + } + void reestablish(uint16_t rnti) final { ue_db[rnti].reest_sdu_counter = 0; } +}; + +class mac_mobility_dummy : public mac_dummy +{ +public: + int ue_cfg(uint16_t rnti, sched_interface::ue_cfg_t* cfg) override + { + ue_db[rnti] = *cfg; + return 0; + } + std::map ue_db; +}; + } // namespace test_dummies namespace test_helpers {