diff --git a/lib/include/srslte/interfaces/enb_interfaces.h b/lib/include/srslte/interfaces/enb_interfaces.h index 05d4bad53..ce0351772 100644 --- a/lib/include/srslte/interfaces/enb_interfaces.h +++ b/lib/include/srslte/interfaces/enb_interfaces.h @@ -176,8 +176,9 @@ public: configure_mbsfn(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s mcch) = 0; typedef struct { - uint32_t cc_idx = 0; ///< eNb Cell index - srslte::phy_cfg_t phy_cfg = {}; ///< Dedicated physical layer configuration + bool active = false; ///< Indicates whether PHY shall consider using this or not + uint32_t cc_idx = 0; ///< eNb Cell index + srslte::phy_cfg_t phy_cfg = {}; ///< Dedicated physical layer configuration } phy_rrc_dedicated_t; typedef std::vector phy_rrc_dedicated_list_t; diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 0c5478d19..ca0085486 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -830,6 +830,11 @@ void srslte_ue_ul_pucch_resource_selection(srslte_cell_t* cell, uci_cfg->cqi.data_enable = false; } + // Set Scheduling request to true in UCI config if SR + if (uci_value && uci_value->scheduling_request) { + uci_cfg->is_scheduling_request_tti = true; + } + // Get PUCCH Resources cfg->format = srslte_pucch_select_format(cfg, uci_cfg, cell->cp); cfg->n_pucch = get_npucch(cfg, uci_cfg, uci_value, cell); diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 0ed8b79ed..1d8722fb7 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -344,7 +344,26 @@ public: int get_drbid_config(asn1::rrc::drb_to_add_mod_s* drb, int drbid); bool nas_pending = false; srslte::byte_buffer_t erab_info; - }; + + ///< UE's Physical layer dedicated configuration + phy_interface_rrc_lte::phy_rrc_dedicated_list_t phy_rrc_dedicated_list = {}; + + /** + * Setups the PCell physical layer dedicated configuration of the UE. This method shall be called from the + * connection setup only. + * @param phys_cfg_ded ASN1 Physical layer configuration dedicated + */ + void apply_setup_phy_config(const asn1::rrc::phys_cfg_ded_s& phys_cfg_ded); + + /** + * Reconfigures the PCell and SCell physical layer dedicated configuration of the UE. This method shall be called + * from the connection reconfiguration. `apply_setup_phy_config` shall not be called before/after. It automatically + * parses the PCell and SCell reconfiguration. + * + * @param reconfig_r8 ASN1 reconfiguration message + */ + void apply_reconf_phy_config(const asn1::rrc::rrc_conn_recfg_r8_ies_s& reconfig_r8); + }; // class ue private: // args diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index 93d59ec89..13d42e60e 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -256,22 +256,25 @@ void phy::get_metrics(phy_metrics_t metrics[ENB_METRICS_MAX_USERS]) void phy::set_config_dedicated(uint16_t rnti, const phy_rrc_dedicated_list_t& dedicated_list) { - // Create list - std::vector scell_idx_list(dedicated_list.size()); + // Create list, empty by default + std::vector scell_idx_list; for (uint32_t i = 0; i < dedicated_list.size(); i++) { auto& config = dedicated_list[i]; - // Set SCell index in list - scell_idx_list[i] = config.cc_idx; + // Configure only if active, ignore otherwise + if (config.active) { + // Set PCell/SCell index in list + scell_idx_list.push_back(config.cc_idx); - // Configure workers - for (uint32_t w = 0; w < nof_workers; w++) { - // Add RNTI to worker - workers[w].add_rnti(rnti, config.cc_idx, false); + // Configure workers + for (uint32_t w = 0; w < nof_workers; w++) { + // Add RNTI to worker + workers[w].add_rnti(rnti, config.cc_idx, false); - // Configure RNTI - workers[w].set_config_dedicated(rnti, config.cc_idx, config.phy_cfg); + // Configure RNTI + workers[w].set_config_dedicated(rnti, config.cc_idx, config.phy_cfg); + } } } diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index d09d9329a..2533d868a 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -1013,7 +1013,8 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_, const sched_interface::ue_cfg_t& sch parent(outer_rrc), rnti(rnti_), pool(srslte::byte_buffer_pool::get_instance()), - current_sched_ue_cfg(sched_ue_cfg) + current_sched_ue_cfg(sched_ue_cfg), + phy_rrc_dedicated_list(sched_ue_cfg.supported_cc_list.size()) { activity_timer = outer_rrc->timers->get_unique_timer(); set_activity_timeout(MSG3_RX_TIMEOUT); // next UE response is Msg3 @@ -1628,7 +1629,7 @@ void rrc::ue::send_connection_setup(bool is_setup) parent->pdcp->add_bearer(rnti, 1, srslte::make_srb_pdcp_config_t(1, false)); // Configure PHY layer - parent->phy->set_config_dedicated(rnti, phy_cfg); + apply_setup_phy_config(*phy_cfg); // It assumes SCell has not been set before parent->mac->phy_config_enabled(rnti, false); rr_cfg->drb_to_add_mod_list_present = false; @@ -1707,7 +1708,8 @@ void rrc::ue::send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu) rrc_conn_recfg->crit_exts.set_c1().set_rrc_conn_recfg_r8(); rrc_conn_recfg->crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded_present = true; - rr_cfg_ded_s* rr_cfg = &rrc_conn_recfg->crit_exts.c1().rrc_conn_recfg_r8().rr_cfg_ded; + auto& reconfig_r8 = rrc_conn_recfg->crit_exts.c1().rrc_conn_recfg_r8(); + rr_cfg_ded_s* rr_cfg = &reconfig_r8.rr_cfg_ded; rr_cfg->phys_cfg_ded_present = true; phys_cfg_ded_s* phy_cfg = &rr_cfg->phys_cfg_ded; @@ -1738,7 +1740,7 @@ void rrc::ue::send_connection_reconf_upd(srslte::unique_byte_buffer_t pdu) phy_cfg->cqi_report_cfg.cqi_report_mode_aperiodic = cqi_report_mode_aperiodic_e::rm30; } } - parent->phy->set_config_dedicated(rnti, phy_cfg); + apply_reconf_phy_config(reconfig_r8); sr_get(&phy_cfg->sched_request_cfg.setup().sr_cfg_idx, &phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx); @@ -1800,7 +1802,7 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu) phy_cfg->pdsch_cfg_ded_present = true; phy_cfg->pdsch_cfg_ded.p_a = parent->cfg.pdsch_cfg; - parent->phy->set_config_dedicated(rnti, phy_cfg); + apply_reconf_phy_config(*conn_reconf); current_sched_ue_cfg.dl_ant_info = srslte::make_ant_info_ded(phy_cfg->ant_info.explicit_value()); parent->mac->ue_cfg(rnti, ¤t_sched_ue_cfg); parent->mac->phy_config_enabled(rnti, false); @@ -2144,6 +2146,112 @@ void rrc::ue::send_dl_dcch(dl_dcch_msg_s* dl_dcch_msg, srslte::unique_byte_buffe } } +void rrc::ue::apply_setup_phy_config(const asn1::rrc::phys_cfg_ded_s& phys_cfg_ded) +{ + // Return if no cell is supported + if (phy_rrc_dedicated_list.empty()) { + return; + } + + // Set PCell index + phy_rrc_dedicated_list[0].active = true; + phy_rrc_dedicated_list[0].cc_idx = current_sched_ue_cfg.supported_cc_list[0].enb_cc_idx; + + // Load PCell dedicated configuration + srslte::set_phy_cfg_t_dedicated_cfg(&phy_rrc_dedicated_list[0].phy_cfg, phys_cfg_ded); + + // Deactivates eNb/Cells for this UE + for (uint32_t cc = 1; cc < phy_rrc_dedicated_list.size(); cc++) { + phy_rrc_dedicated_list[cc].active = false; + } + + // Send configuration to physical layer + if (parent->phy != nullptr) { + parent->phy->set_config_dedicated(rnti, phy_rrc_dedicated_list); + } +} + +void rrc::ue::apply_reconf_phy_config(const asn1::rrc::rrc_conn_recfg_r8_ies_s& reconfig_r8) +{ + // Return if no cell is supported + if (phy_rrc_dedicated_list.empty()) { + return; + } + + // Configure PCell if available configuration + if (reconfig_r8.rr_cfg_ded_present) { + auto& rr_cfg_ded = reconfig_r8.rr_cfg_ded; + if (rr_cfg_ded.phys_cfg_ded_present) { + auto& phys_cfg_ded = rr_cfg_ded.phys_cfg_ded; + srslte::set_phy_cfg_t_dedicated_cfg(&phy_rrc_dedicated_list[0].phy_cfg, phys_cfg_ded); + } + } + + // Parse extensions + if (reconfig_r8.non_crit_ext_present) { + auto& reconfig_r890 = reconfig_r8.non_crit_ext; + if (reconfig_r890.non_crit_ext_present) { + auto& reconfig_r920 = reconfig_r890.non_crit_ext; + if (reconfig_r920.non_crit_ext_present) { + auto& reconfig_r1020 = reconfig_r920.non_crit_ext; + + // Handle Add/Modify SCell list + if (reconfig_r1020.scell_to_add_mod_list_r10_present) { + for (const auto& scell_config : reconfig_r1020.scell_to_add_mod_list_r10) { + // UE SCell index + uint32_t scell_idx = scell_config.scell_idx_r10; + + // Check that the SCell index is correct. + if (scell_idx == 0) { + // SCell index is reserved for PCell + parent->rrc_log->error("SCell index (%d) is reserved for PCell\n", scell_idx); + + } else if (scell_idx < current_sched_ue_cfg.supported_cc_list.size()) { + // Get PHY configuration structure, create entry automatically + auto& phy_rrc_dedicated = phy_rrc_dedicated_list[scell_idx]; + + // Set eNb Cell/Carrier index + phy_rrc_dedicated.active = true; + phy_rrc_dedicated.cc_idx = current_sched_ue_cfg.supported_cc_list[scell_idx].enb_cc_idx; + + // Set SCell configuration + srslte::set_phy_cfg_t_scell_config(&phy_rrc_dedicated.phy_cfg, scell_config); + } else { + // Out of bounds, log error + parent->rrc_log->error("SCell index (%d) points out of the supported list (%ld)\n", + scell_idx, + current_sched_ue_cfg.supported_cc_list.size()); + } + } + } + + // Handle Remove SCell list + if (reconfig_r1020.scell_to_release_list_r10_present) { + for (auto& scell_to_release : reconfig_r1020.scell_to_release_list_r10) { + if (scell_to_release == 0) { + // SCell index is reserved for PCell + parent->rrc_log->error("SCell index (%d) is reserved for PCell\n", scell_to_release); + } else if (scell_to_release < current_sched_ue_cfg.supported_cc_list.size()) { + // Deactivate cell configuration + phy_rrc_dedicated_list[scell_to_release].active = false; + } else { + // Out of bounds, log error + parent->rrc_log->error("SCell index (%d) points out of the supported list (%ld)\n", + scell_to_release, + current_sched_ue_cfg.supported_cc_list.size()); + } + } + } + } + } + } + + // Send configuration to physical layer + if (parent->phy != nullptr) { + parent->phy->set_config_dedicated(rnti, phy_rrc_dedicated_list); + } +} + int rrc::ue::sr_free() { if (sr_allocated) { diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index fb97ef25f..c20411e80 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -287,8 +287,13 @@ private: uint32_t tb_idx; } tti_dl_info_t; + typedef struct { + uint32_t tti; + } tti_sr_info_t; + std::queue tti_dl_info_sched_queue; std::queue tti_dl_info_ack_queue; + std::queue tti_sr_info_queue; public: explicit dummy_stack(uint16_t rnti_) : log_h("STACK"), ue_rnti(rnti_), random_gen(srslte_random_init(0)) @@ -311,8 +316,14 @@ public: int sr_detected(uint32_t tti, uint16_t rnti) override { + tti_sr_info_t tti_sr_info = {}; + tti_sr_info.tti = tti; + tti_sr_info_queue.push(tti_sr_info); + notify_sr_detected(); - return 0; + + log_h.info("Received SR tti=%d; rnti=x%x\n", tti, rnti); + return SRSLTE_SUCCESS; } int rach_detected(uint32_t tti, uint32_t primary_cc_idx, uint32_t preamble_idx, uint32_t time_adv) override { @@ -372,7 +383,7 @@ public: dl_sched.cfi = 1; // Random decision on whether transmit or not - if (srslte_random_uniform_real_dist(random_gen, 0, 1) < prob_dl_grant) { + if (srslte_random_bool(random_gen, prob_dl_grant)) { dl_sched.nof_grants = 1; dl_sched.pdsch[0].softbuffer_tx[0] = &softbuffer_tx; dl_sched.pdsch[0].softbuffer_tx[1] = &softbuffer_tx; @@ -446,6 +457,24 @@ public: tti_dl_info_ack_queue.pop(); } + // Check SR match with TTI + while (tti_sr_info_queue.size() > 1) { + tti_sr_info_t tti_sr_info1 = tti_sr_info_queue.front(); + + // Check first TTI + TESTASSERT(tti_sr_info1.tti % 20 == 0); + + // POP first from queue + tti_sr_info_queue.pop(); + + // Get second, do not pop + tti_sr_info_t& tti_sr_info2 = tti_sr_info_queue.front(); + + // Make sure the TTI difference is 20 + uint32_t elapsed_tti = ((tti_sr_info2.tti + 10240) - tti_sr_info1.tti) % 10240; + TESTASSERT(elapsed_tti == 20); + } + return SRSLTE_SUCCESS; } }; @@ -600,10 +629,10 @@ public: for (uint32_t i = 0; i < buffers.size(); i++) { srslte_dci_dl_t dci_dl[SRSLTE_MAX_DCI_MSG] = {}; srslte_ue_dl_cfg_t ue_dl_cfg = {}; - ue_dl_cfg.cfg.cqi_report.periodic_configured = true; - ue_dl_cfg.cfg.cqi_report.periodic_mode = SRSLTE_CQI_MODE_12; - ue_dl_cfg.cfg.cqi_report.pmi_idx = 16 + i; - ue_dl_cfg.cfg.pdsch.rnti = rnti; + // ue_dl_cfg.cfg.cqi_report.periodic_configured = true; + // ue_dl_cfg.cfg.cqi_report.periodic_mode = SRSLTE_CQI_MODE_12; + // ue_dl_cfg.cfg.cqi_report.pmi_idx = 16 + i; + ue_dl_cfg.cfg.pdsch.rnti = rnti; srslte_ue_dl_decode_fft_estimate(ue_dl_v[i], &sf_dl_cfg, &ue_dl_cfg); @@ -647,9 +676,6 @@ public: srslte_ue_dl_gen_cqi_periodic(ue_dl_v[i], &ue_dl_cfg, 0x0f, sf_dl_cfg.tti, &uci_data); } - // Generate Acknowledgements - srslte_ue_dl_gen_ack(ue_dl_v[0], &sf_dl_cfg, &pdsch_ack, &uci_data); - // Work UL for (uint32_t i = 0; i < buffers.size(); i++) { srslte_ue_ul_cfg_t ue_ul_cfg = {}; @@ -657,6 +683,15 @@ public: ue_ul_cfg.ul_cfg.pusch.softbuffers.tx = &softbuffer_tx; ue_ul_cfg.ul_cfg.pucch.rnti = rnti; + // Generate + if (i == 0) { + // Generate scheduling request + srslte_ue_ul_gen_sr(&ue_ul_cfg, &sf_ul_cfg, &uci_data, (bool)(sf_ul_cfg.tti % 20 == 0)); + + // Generate Acknowledgements + srslte_ue_dl_gen_ack(ue_dl_v[0], &sf_dl_cfg, &pdsch_ack, &uci_data); + } + srslte_pusch_data_t pusch_data = {}; pusch_data.ptr = tx_data; @@ -699,7 +734,7 @@ private: dummy_ue ue_phy; srslte::log_filter log_h; srslte::logger_stdout logger_stdout; - uint32_t nof_carriers = 0; + uint32_t nof_carriers = 0; srslte::phy_cfg_t common_dedicated = {}; uint16_t rnti = 0; @@ -734,7 +769,13 @@ public: for (uint32_t i = 0; i < 4; i++) { common_dedicated.dl_cfg.cqi_report.pmi_idx = 16 + i; dedicated_list[i].cc_idx = (i + pcell_idx) % phy_cfg.phy_cell_cfg.size(); + dedicated_list[i].active = true; dedicated_list[i].phy_cfg = common_dedicated; + + // Disable SCell stuff + if (i != pcell_index) { + dedicated_list[i].phy_cfg.ul_cfg.pucch.sr_configured = false; + } } enb_phy.set_config_dedicated(rnti, dedicated_list); } @@ -795,15 +836,17 @@ int main(int argc, char** argv) dedicated.ul_cfg.pucch.delta_pucch_shift = 1; dedicated.ul_cfg.pucch.n_rb_2 = 0; dedicated.ul_cfg.pucch.N_cs = 0; - dedicated.ul_cfg.pucch.N_pucch_1 = 0; - dedicated.ul_cfg.pucch.n_pucch_2 = 0; - dedicated.ul_cfg.pucch.n_pucch_sr = 0; + dedicated.ul_cfg.pucch.n_pucch_sr = 1; + dedicated.ul_cfg.pucch.N_pucch_1 = 2; + dedicated.ul_cfg.pucch.n_pucch_2 = 3; dedicated.ul_cfg.pucch.simul_cqi_ack = true; + dedicated.ul_cfg.pucch.sr_configured = true; + dedicated.ul_cfg.pucch.I_sr = 5; std::unique_ptr test_bench = std::unique_ptr(new phy_test_bench(phy_args, phy_cfg, 0x1234, 0, dedicated)); - for (uint32_t i = 0; i < 32; i++) { + for (uint32_t i = 0; i < 128; i++) { TESTASSERT(test_bench->run_tti() >= SRSLTE_SUCCESS); }