diff --git a/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h b/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h index de2e97931..dcbc57aed 100644 --- a/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h +++ b/srsue/test/ttcn3/hdr/lte_ttcn3_phy.h @@ -120,6 +120,8 @@ public: void run_tti(); private: + void select_pcell(); + srslte::logger* logger = nullptr; srslte::log_filter log; diff --git a/srsue/test/ttcn3/hdr/ttcn3_interfaces.h b/srsue/test/ttcn3/hdr/ttcn3_interfaces.h index 1b21bc87a..e0172cc70 100644 --- a/srsue/test/ttcn3/hdr/ttcn3_interfaces.h +++ b/srsue/test/ttcn3/hdr/ttcn3_interfaces.h @@ -41,7 +41,7 @@ public: class ss_sys_interface { public: - virtual void add_bcch_pdu(srslte::unique_byte_buffer_t pdu) = 0; + virtual void add_bcch_dlsch_pdu(const std::string cell_name, srslte::unique_byte_buffer_t pdu) = 0; virtual void add_pch_pdu(srslte::unique_byte_buffer_t pdu) = 0; virtual void set_cell_attenuation(std::string cell_name, const float attenuation) = 0; virtual void set_cell_config(std::string cell_name, uint32_t earfcn, srslte_cell_t cell, const float power) = 0; @@ -61,6 +61,7 @@ class ss_srb_interface public: virtual void add_ccch_pdu(srslte::unique_byte_buffer_t pdu) = 0; virtual void add_dcch_pdu(uint32_t lcid, srslte::unique_byte_buffer_t pdu) = 0; + virtual void reestablish_bearer(uint32_t lcid) = 0; }; class syssim_interface_phy diff --git a/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h b/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h index ec2d305b8..e90030bf5 100644 --- a/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h +++ b/srsue/test/ttcn3/hdr/ttcn3_srb_interface.h @@ -151,6 +151,11 @@ private: memcpy(pdu->msg, payload, pdu->N_bytes); syssim->add_ccch_pdu(std::move(pdu)); + + // FIXME: is there a better way to check for RRCConnectionReestablishment? + if (ccch_is_rrc_reestablishment(document)) { + syssim->reestablish_bearer(1); + } } // Todo: move to SYSSIM @@ -166,6 +171,19 @@ private: syssim->add_dcch_pdu(lcid, std::move(pdu)); } + bool ccch_is_rrc_reestablishment(Document& document) + { + const Value& dcch = document["RrcPdu"]["Ccch"]; + if (dcch.HasMember("message_")) { + if (dcch["message_"].HasMember("c1")) { + if (dcch["message_"]["c1"].HasMember("rrcConnectionReestablishment")) { + return true; + } + } + } + return false; + } + ss_srb_interface* syssim = nullptr; byte_buffer_pool* pool = nullptr; }; diff --git a/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h b/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h index e3575ee24..09424aa42 100644 --- a/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h +++ b/srsue/test/ttcn3/hdr/ttcn3_sys_interface.h @@ -103,8 +103,8 @@ private: sib->N_bytes = tb_len; // Push to main component - log->info_hex(sib->msg, sib->N_bytes, "Received BCCH DL-SCH\n"); - syssim->add_bcch_pdu(std::move(sib)); + log->info_hex(sib->msg, sib->N_bytes, "Received BCCH DL-SCH for %s\n", cell_name.GetString()); + syssim->add_bcch_dlsch_pdu(cell_name.GetString(), std::move(sib)); consumed_bytes = payload_ptr - payload; } diff --git a/srsue/test/ttcn3/hdr/ttcn3_syssim.h b/srsue/test/ttcn3/hdr/ttcn3_syssim.h index b21844dda..e6ddc3056 100644 --- a/srsue/test/ttcn3/hdr/ttcn3_syssim.h +++ b/srsue/test/ttcn3/hdr/ttcn3_syssim.h @@ -148,7 +148,7 @@ public: rlc.reset(); pdcp.reset(); cells.clear(); - pcell = {}; + pcell_idx = -1; } // Called from UT before starting testcase @@ -198,20 +198,22 @@ public: } } + // Called from UT to terminate the testcase void tc_end() { - std::lock_guard lock(mutex); + // ask periodic thread to stop before locking mutex + running = false; - if (ue != NULL) { - // ask periodic thread to stop - running = false; + std::lock_guard lock(mutex); + if (ue != nullptr) { log.info("Deinitializing UE ID=%d\n", run_id); log.console("Deinitializing UE ID=%d\n", run_id); ue->stop(); // wait until SS main thread has terminated before resetting UE wait_thread_finish(); + ue.reset(); // Reset SS' RLC and PDCP @@ -243,17 +245,16 @@ public: // Called from PHY but always from the SS main thread with lock being hold void prach_indication(uint32_t preamble_index_, const uint32_t& cell_id) { + // verify that UE intends to send PRACH on current Pcell + if (cells[pcell_idx]->cell.id != cell_id) { + log.error( + "UE is attempting to PRACH on pci=%d while current Pcell is pci=%d\n", cell_id, cells[pcell_idx]->cell.id); + return; + } + // store TTI for providing UL grant for Msg3 transmission prach_tti = tti; prach_preamble_index = preamble_index_; - - // update active pcell (chosen by UE) in syssim - for (auto& cell : cells) { - if (cell.cell.id == cell_id) { - pcell = cell; - break; - } - } } // Called from PHY but always from the SS main thread with lock being hold @@ -513,11 +514,11 @@ public: mac_interface_phy_lte::mac_grant_dl_t dl_grant = {}; dl_grant.pid = get_pid(tti); dl_grant.rnti = dl_rnti; - dl_grant.tb[0].tbs = sibs[sib_idx]->N_bytes; + dl_grant.tb[0].tbs = cells[pcell_idx]->sibs[sib_idx]->N_bytes; dl_grant.tb[0].ndi = get_ndi_for_new_dl_tx(tti); - ue->new_tb(dl_grant, sibs[sib_idx]->msg); - - sib_idx = (sib_idx + 1) % sibs.size(); + ue->new_tb(dl_grant, cells[pcell_idx]->sibs[sib_idx]->msg); + log.info("Delivered SIB%d for pcell_idx=%d\n", sib_idx, pcell_idx); + sib_idx = (sib_idx + 1) % cells[pcell_idx]->sibs.size(); } else if (SRSLTE_RNTI_ISRAR(dl_rnti)) { if (prach_tti != -1) { rar_tti = (prach_tti + 3) % 10240; @@ -634,12 +635,12 @@ public: if (not syssim_has_cell(name)) { // insert new cell log.info("Adding cell %s with cellId=%d and power=%.2f dBm\n", name.c_str(), cell_.id, power); - syssim_cell_t cell = {}; - cell.name = name; - cell.cell = cell_; - cell.initial_power = power; - cell.earfcn = earfcn_; - cells.push_back(cell); + unique_syssim_cell_t cell = unique_syssim_cell_t(new syssim_cell_t); + cell->name = name; + cell->cell = cell_; + cell->initial_power = power; + cell->earfcn = earfcn_; + cells.push_back(std::move(cell)); } else { // cell is already there log.info("Cell already there, reconfigure\n"); @@ -651,8 +652,8 @@ public: // internal function bool syssim_has_cell(std::string cell_name) { - for (uint32_t i = 0; i < cells.size(); ++i) { - if (cells[i].name == cell_name) { + for (auto& cell : cells) { + if (cell->name == cell_name) { return true; } } @@ -667,9 +668,9 @@ public: } // update cell's power - for (uint32_t i = 0; i < cells.size(); ++i) { - if (cells[i].name == cell_name) { - cells[i].attenuation = value; + for (auto& cell : cells) { + if (cell->name == cell_name) { + cell->attenuation = value; break; } } @@ -685,25 +686,51 @@ public: log.error("Can't configure cell. UE not initialized.\n"); } - // convert syssim cell list to phy cell list + // convert syssim cell list to phy cell list + { lte_ttcn3_phy::cell_list_t phy_cells; - for (uint32_t i = 0; i < cells.size(); ++i) { + for (auto& ss_cell : cells) { lte_ttcn3_phy::cell_t phy_cell = {}; - phy_cell.info = cells[i].cell; - phy_cell.power = cells[i].initial_power - cells[i].attenuation; - phy_cell.earfcn = cells[i].earfcn; - log.debug("Configuring cell %d with PCI=%d with TxPower=%f\n", i, phy_cell.info.id, phy_cell.power); + phy_cell.info = ss_cell->cell; + phy_cell.power = ss_cell->initial_power - ss_cell->attenuation; + phy_cell.earfcn = ss_cell->earfcn; + log.info("Configuring cell with PCI=%d with TxPower=%.2f\n", phy_cell.info.id, phy_cell.power); phy_cells.push_back(phy_cell); } // SYSSIM defines what cells the UE can connect to ue->set_cell_map(phy_cells); + } + + // reselect SS Pcell + float max_power = -145; + for (uint32_t i = 0; i < cells.size(); ++i) { + float actual_power = cells[i]->initial_power - cells[i]->attenuation; + if (actual_power > max_power) { + max_power = actual_power; + pcell_idx = i; + log.info("Selecting PCI=%d with TxPower=%.2f as Pcell\n", cells[pcell_idx]->cell.id, max_power); + } + } } - void add_bcch_pdu(unique_byte_buffer_t pdu) + bool have_valid_pcell() { return (pcell_idx >= 0 && pcell_idx < static_cast(cells.size())); } + + void add_bcch_dlsch_pdu(const string cell_name, unique_byte_buffer_t pdu) { std::lock_guard lock(mutex); - sibs.push_back(std::move(pdu)); + + if (not syssim_has_cell(cell_name)) { + log.error("Can't add BCCH to cell. Cell not found.\n"); + } + + // add SIB + for (auto& cell : cells) { + if (cell->name == cell_name) { + cell->sibs.push_back(std::move(pdu)); + break; + } + } } void add_ccch_pdu(unique_byte_buffer_t pdu) @@ -753,6 +780,14 @@ public: rlc.add_bearer(lcid, srslte::rlc_config_t::srb_config(lcid)); } + void reestablish_bearer(uint32_t lcid) + { + std::lock_guard lock(mutex); + log.info("Reestablishing LCID=%d\n", lcid); + pdcp.reestablish(lcid); + rlc.reestablish(lcid); + } + void del_srb(uint32_t lcid) { std::lock_guard lock(mutex); @@ -782,7 +817,7 @@ public: // prepend pcell PCID pdu->msg--; - *pdu->msg = static_cast(pcell.cell.id); + *pdu->msg = static_cast(cells[pcell_idx]->cell.id); pdu->N_bytes++; // push content to Titan @@ -832,6 +867,7 @@ public: const srslte::CIPHERING_ALGORITHM_ID_ENUM cipher_algo, const srslte::INTEGRITY_ALGORITHM_ID_ENUM integ_algo) { + log.info("Setting AS security for LCID=%d\n", lcid); pdcp.config_security(lcid, k_rrc_enc.data(), k_rrc_int.data(), k_up_enc.data(), cipher_algo, integ_algo); pdcp.enable_integrity(lcid); pdcp.enable_encryption(lcid); @@ -874,7 +910,6 @@ private: uint32_t run_id = 0; - std::vector sibs; int32_t tti = 0; int32_t prach_tti = -1; int32_t rar_tti = -1; @@ -890,13 +925,15 @@ private: // Map between the cellId (name) used by 3GPP test suite and srsLTE cell struct typedef struct { std::string name; - srslte_cell_t cell; - float initial_power; - float attenuation; - uint32_t earfcn; + srslte_cell_t cell = {}; + float initial_power = 0.0; + float attenuation = 0.0; + uint32_t earfcn = 0; + std::vector sibs; } syssim_cell_t; - std::vector cells; - syssim_cell_t pcell = {}; + typedef std::unique_ptr unique_syssim_cell_t; + std::vector cells; + int32_t pcell_idx = -1; srslte::pdu_queue pdus; srslte::sch_pdu mac_msg_dl, mac_msg_ul; diff --git a/srsue/test/ttcn3/hdr/ttcn3_ue.h b/srsue/test/ttcn3/hdr/ttcn3_ue.h index 46641a483..8f1370347 100644 --- a/srsue/test/ttcn3/hdr/ttcn3_ue.h +++ b/srsue/test/ttcn3/hdr/ttcn3_ue.h @@ -100,7 +100,13 @@ public: void stop() { - // nothing to do here + if (stack) { + stack->stop(); + } + + if (phy) { + phy->stop(); + } } bool switch_on() { return stack->switch_on(); } diff --git a/srsue/test/ttcn3/src/lte_ttcn3_phy.cc b/srsue/test/ttcn3/src/lte_ttcn3_phy.cc index 01b30315c..b7f04e0da 100644 --- a/srsue/test/ttcn3/src/lte_ttcn3_phy.cc +++ b/srsue/test/ttcn3/src/lte_ttcn3_phy.cc @@ -47,7 +47,7 @@ int lte_ttcn3_phy::init(const phy_args_t& args_, stack_interface_phy_lte* stack_ // ue_phy_base interface int lte_ttcn3_phy::init(const phy_args_t& args_) { - log.init("PHY ", logger); + log.init("PHY ", logger, true); log.set_level(args_.log.phy_level); return SRSLTE_SUCCESS; @@ -130,15 +130,8 @@ int lte_ttcn3_phy::meas_stop(uint32_t earfcn, int pci) return 0; }; - -/* Cell search and selection procedures */ -phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* found_cell) +void lte_ttcn3_phy::select_pcell() { - std::lock_guard lock(mutex); - - log.info("Running cell search in PHY\n"); - cell_search_ret_t ret = {}; - // select strongest cell as PCell float max_power = -145; int max_index = 0; @@ -148,11 +141,22 @@ phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* max_index = i; } } + pcell = cells[max_index]; + log.info("Setting PCell to EARFCN=%d CellId=%d with RS power=%.2f\n", pcell.earfcn, pcell.info.id, pcell.power); +} - // Consider cell found if above -100dBm - if (max_power >= MIN_IN_SYNC_POWER) { - pcell = cells[max_index]; - log.info("Setting PCell to EARFCN=%d CellId=%d with RS power=%.2f\n", pcell.earfcn, pcell.info.id, max_power); +/* Cell search and selection procedures */ +phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* found_cell) +{ + std::lock_guard lock(mutex); + + select_pcell(); + + log.info("Running cell search in PHY\n"); + cell_search_ret_t ret = {}; + + // Consider cell found if Pcell power >= -100dBm + if (pcell.power >= MIN_IN_SYNC_POWER) { if (found_cell) { found_cell->earfcn = pcell.earfcn; found_cell->cell = pcell.info; @@ -166,15 +170,22 @@ phy_interface_rrc_lte::cell_search_ret_t lte_ttcn3_phy::cell_search(phy_cell_t* return ret; }; -bool lte_ttcn3_phy::cell_select(phy_cell_t* cell) +bool lte_ttcn3_phy::cell_select(phy_cell_t* rrc_cell) { - log.debug("%s not implemented.\n", __FUNCTION__); - return true; + // try to find RRC cell in current cell map + for (auto& cell : cells) { + if (cell.info.id == rrc_cell->cell.id) { + pcell = cell; + return true; + } + } + + return false; }; bool lte_ttcn3_phy::cell_is_camping() { - return true; + return (pcell.power >= MIN_IN_SYNC_POWER); }; void lte_ttcn3_phy::reset() @@ -205,14 +216,11 @@ std::string lte_ttcn3_phy::get_type() phy_interface_mac_lte::prach_info_t lte_ttcn3_phy::prach_get_info() { std::lock_guard lock(mutex); - prach_info_t info = {}; if (prach_tti_tx != -1) { info.is_transmitted = true; info.tti_ra = prach_tti_tx; } - - log.info("Return prach_tti_tx=%d\n", prach_tti_tx); return info; }