From dcf178a8a5333eefb363d34792326664abfdda92 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 19 Jan 2022 12:49:22 +0100 Subject: [PATCH 01/41] sched_nr: change wording when logging UE access to unknown RNTI streamline with RRC logs for same event, facilitate parsing an accept list entry in KPI analyzer --- srsgnb/src/stack/mac/sched_nr.cc | 6 +++--- srsgnb/src/stack/mac/sched_nr_ue.cc | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/srsgnb/src/stack/mac/sched_nr.cc b/srsgnb/src/stack/mac/sched_nr.cc index 1ab467390..9176611a3 100644 --- a/srsgnb/src/stack/mac/sched_nr.cc +++ b/srsgnb/src/stack/mac/sched_nr.cc @@ -124,7 +124,7 @@ public: for (ue_event_t& ev : current_slot_ue_events) { auto ue_it = ues.find(ev.rnti); if (ue_it == ues.end()) { - sched_logger.warning("SCHED: \"%s\" called for inexistent rnti=0x%x.", ev.event_name, ev.rnti); + sched_logger.warning("SCHED: \"%s\" called for unknown rnti=0x%x.", ev.event_name, ev.rnti); ev.rnti = SRSRAN_INVALID_RNTI; } else if (ue_it->second->has_ca()) { // events specific to existing UEs with CA @@ -152,7 +152,7 @@ public: } auto ue_it = ues.find(ev.rnti); if (ue_it == ues.end()) { - sched_logger.warning("SCHED: \"%s\" called for inexistent rnti=0x%x.", ev.event_name, ev.rnti); + sched_logger.warning("SCHED: \"%s\" called for unknown rnti=0x%x.", ev.event_name, ev.rnti); ev.rnti = SRSRAN_INVALID_RNTI; } else if (not ue_it->second->has_ca() and ue_it->second->carriers[cc] != nullptr) { ev.callback(*ue_it->second, evlogger); @@ -165,7 +165,7 @@ public: if (ue_it != ues.end() and ue_it->second->carriers[cc] != nullptr) { ev.callback(*ue_it->second->carriers[cc], evlogger); } else { - sched_logger.warning("SCHED: \"%s\" called for inexistent rnti=0x%x,cc=%d.", ev.event_name, ev.rnti, ev.cc); + sched_logger.warning("SCHED: \"%s\" called for unknown rnti=0x%x,cc=%d.", ev.event_name, ev.rnti, ev.cc); } } } diff --git a/srsgnb/src/stack/mac/sched_nr_ue.cc b/srsgnb/src/stack/mac/sched_nr_ue.cc index 530d3ab3d..8f9b78ef6 100644 --- a/srsgnb/src/stack/mac/sched_nr_ue.cc +++ b/srsgnb/src/stack/mac/sched_nr_ue.cc @@ -226,7 +226,7 @@ void ue::new_slot(slot_point pdcch_slot) slot_ue ue::make_slot_ue(slot_point pdcch_slot, uint32_t cc) { - srsran_assert(carriers[cc] != nullptr, "make_slot_ue() called for inexistent rnti=0x%x,cc=%d", rnti, cc); + srsran_assert(carriers[cc] != nullptr, "make_slot_ue() called for unknown rnti=0x%x,cc=%d", rnti, cc); return slot_ue(*carriers[cc], pdcch_slot); } From 12cc7cb4d7d1f2cfb0f873849366b3bd98f60058 Mon Sep 17 00:00:00 2001 From: Fabian Eckermann Date: Wed, 12 Jan 2022 15:01:47 +0100 Subject: [PATCH 02/41] Add support for RRC redirect. --- .../srsran/interfaces/ue_nas_interfaces.h | 2 +- .../srsran/interfaces/ue_phy_interfaces.h | 3 +- lib/include/srsran/test/ue_test_interfaces.h | 2 +- srsue/hdr/phy/dummy_phy.h | 2 +- srsue/hdr/phy/phy.h | 2 +- srsue/hdr/phy/sync.h | 2 +- srsue/hdr/stack/rrc/phy_controller.h | 8 ++-- srsue/hdr/stack/rrc/rrc.h | 6 ++- srsue/hdr/stack/upper/nas.h | 18 ++++----- srsue/src/phy/phy.cc | 8 ++-- srsue/src/phy/sync.cc | 39 ++++++++++++------- srsue/src/phy/test/ue_phy_test.cc | 2 +- srsue/src/stack/rrc/phy_controller.cc | 8 ++-- srsue/src/stack/rrc/rrc.cc | 35 ++++++++++++++++- srsue/src/stack/rrc/rrc_procedures.cc | 21 +++++----- srsue/src/stack/rrc/test/rrc_meas_test.cc | 2 +- srsue/src/stack/rrc/test/rrc_phy_ctrl_test.cc | 2 +- srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h | 2 +- srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc | 2 +- 19 files changed, 107 insertions(+), 59 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_nas_interfaces.h b/lib/include/srsran/interfaces/ue_nas_interfaces.h index 75459dd22..386270aa2 100644 --- a/lib/include/srsran/interfaces/ue_nas_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nas_interfaces.h @@ -64,7 +64,7 @@ public: class nas_5g_interface_procedures { public: - virtual int send_registration_request() = 0; + virtual int send_registration_request() = 0; virtual int send_pdu_session_establishment_request(uint32_t transaction_identity, uint16_t pdu_session_id, const pdu_session_cfg_t& pdu_session) = 0; diff --git a/lib/include/srsran/interfaces/ue_phy_interfaces.h b/lib/include/srsran/interfaces/ue_phy_interfaces.h index 58786eb0b..06dac7979 100644 --- a/lib/include/srsran/interfaces/ue_phy_interfaces.h +++ b/lib/include/srsran/interfaces/ue_phy_interfaces.h @@ -96,7 +96,6 @@ struct phy_args_t { srsran::channel::args_t dl_channel_args; srsran::channel::args_t ul_channel_args; - }; /* RAT agnostic Interface MAC -> PHY */ @@ -158,7 +157,7 @@ public: virtual void meas_stop() = 0; /* Cell search and selection procedures */ - virtual bool cell_search() = 0; + virtual bool cell_search(int earfcn) = 0; virtual bool cell_select(phy_cell_t cell) = 0; virtual bool cell_is_camping() = 0; }; diff --git a/lib/include/srsran/test/ue_test_interfaces.h b/lib/include/srsran/test/ue_test_interfaces.h index 196a39e45..a2b86bf83 100644 --- a/lib/include/srsran/test/ue_test_interfaces.h +++ b/lib/include/srsran/test/ue_test_interfaces.h @@ -76,7 +76,7 @@ class phy_dummy_interface : public phy_interface_rrc_lte void meas_stop() override {} /* Cell search and selection procedures */ - bool cell_search() override { return true; } + bool cell_search(int earfcn) override { return true; } bool cell_select(phy_cell_t cell) override { return true; } bool cell_is_camping() override { return false; } }; diff --git a/srsue/hdr/phy/dummy_phy.h b/srsue/hdr/phy/dummy_phy.h index 6073abaed..b286921a3 100644 --- a/srsue/hdr/phy/dummy_phy.h +++ b/srsue/hdr/phy/dummy_phy.h @@ -53,7 +53,7 @@ public: void meas_stop() final {} /* Cell search and selection procedures */ - bool cell_search() final { return false; } + bool cell_search(int earfcn) final { return false; } bool cell_select(phy_cell_t cell) final { return false; } bool cell_is_camping() final { return false; } diff --git a/srsue/hdr/phy/phy.h b/srsue/hdr/phy/phy.h index d4f873a69..cbc3cddf9 100644 --- a/srsue/hdr/phy/phy.h +++ b/srsue/hdr/phy/phy.h @@ -68,7 +68,7 @@ public: /********** RRC INTERFACE ********************/ - bool cell_search() final; + bool cell_search(int earfcn) final; bool cell_select(phy_cell_t cell) final; // Sets the new PHY configuration for the given CC. The configuration is applied in the background. The notify() diff --git a/srsue/hdr/phy/sync.h b/srsue/hdr/phy/sync.h index 73c2fd48d..92a489518 100644 --- a/srsue/hdr/phy/sync.h +++ b/srsue/hdr/phy/sync.h @@ -68,7 +68,7 @@ public: // RRC interface for controling the SYNC state bool cell_search_init(); - rrc_interface_phy_lte::cell_search_ret_t cell_search_start(phy_cell_t* cell); + rrc_interface_phy_lte::cell_search_ret_t cell_search_start(phy_cell_t* cell, int earfcn); bool cell_select_init(phy_cell_t cell); bool cell_select_start(phy_cell_t cell); bool cell_is_camping(); diff --git a/srsue/hdr/stack/rrc/phy_controller.h b/srsue/hdr/stack/rrc/phy_controller.h index 481dcc626..9c07d5d2e 100644 --- a/srsue/hdr/stack/rrc/phy_controller.h +++ b/srsue/hdr/stack/rrc/phy_controller.h @@ -40,7 +40,9 @@ public: struct cell_sel_cmd { phy_cell_t phy_cell; }; - struct cell_search_cmd {}; + struct cell_search_cmd { + int earfcn; + }; struct in_sync_ev { static const bool log_verbose = false; }; @@ -52,7 +54,7 @@ public: // PHY procedures interfaces bool start_cell_select(const phy_cell_t& phy_cell, srsran::event_observer observer = {}); - bool start_cell_search(srsran::event_observer observer); + bool start_cell_search(srsran::event_observer observer, int earfcn); void cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t found_cell); void cell_selection_completed(bool outcome); void in_sync(); @@ -117,7 +119,7 @@ public: // clang-format on }; struct searching_cell { - void enter(phy_controller* f); + void enter(phy_controller* f, const cell_search_cmd& ev); }; private: diff --git a/srsue/hdr/stack/rrc/rrc.h b/srsue/hdr/stack/rrc/rrc.h index 09ab8d8dc..81ddc371e 100644 --- a/srsue/hdr/stack/rrc/rrc.h +++ b/srsue/hdr/stack/rrc/rrc.h @@ -211,6 +211,9 @@ private: meas_cell_list meas_cells_nr; + // if this is set to a valid earfcn, this earfcn will be used for cell search + int cell_search_earfcn = -1; + bool initiated = false; asn1::rrc::reest_cause_e m_reest_cause = asn1::rrc::reest_cause_e::nulltype; uint16_t m_reest_rnti = 0; @@ -328,7 +331,8 @@ private: bool con_reconfig_ho(const asn1::rrc::rrc_conn_recfg_s& reconfig); void ho_failed(); void start_go_idle(); - void rrc_connection_release(const std::string& cause); + void handle_rrc_connection_release(const asn1::rrc::rrc_conn_release_s& release); + void start_rrc_redirect(uint32_t new_dl_earfcn); void radio_link_failure_push_cmd(); void radio_link_failure_process(); void leave_connected(); diff --git a/srsue/hdr/stack/upper/nas.h b/srsue/hdr/stack/upper/nas.h index 3832c0259..a63e2eec5 100644 --- a/srsue/hdr/stack/upper/nas.h +++ b/srsue/hdr/stack/upper/nas.h @@ -80,9 +80,9 @@ public: void timer_expired(uint32_t timeout_id) override; private: - rrc_interface_nas* rrc = nullptr; - usim_interface_nas* usim = nullptr; - gw_interface_nas* gw = nullptr; + rrc_interface_nas* rrc = nullptr; + usim_interface_nas* usim = nullptr; + gw_interface_nas* gw = nullptr; bool running = false; @@ -108,10 +108,10 @@ private: typedef std::pair eps_bearer_map_pair_t; eps_bearer_map_t eps_bearer; - bool have_guti = false; - bool have_ctxt = false; - bool auth_request = false; - uint8_t current_sec_hdr = LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS; + bool have_guti = false; + bool have_ctxt = false; + bool auth_request = false; + uint8_t current_sec_hdr = LIBLTE_MME_SECURITY_HDR_TYPE_PLAIN_NAS; const uint32_t max_attach_attempts = 5; // Sec. 5.5.1.2.6 uint32_t attach_attempt_counter = 0; @@ -144,8 +144,8 @@ private: const uint8_t ue_svn_oct2 = 0x3; // Security - bool eia_caps[8] = {}; - bool eea_caps[8] = {}; + bool eia_caps[8] = {}; + bool eea_caps[8] = {}; // Airplane mode simulation typedef enum { DISABLED = 0, ENABLED } airplane_mode_state_t; diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 9d97d4396..3b5c7a3f9 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -342,12 +342,12 @@ bool phy::cell_select(phy_cell_t cell) // This function executes one part of the procedure immediatly and returns to continue in the background. // When it returns, the caller thread can expect the PHY to have switched to IDLE and have stopped all DL/UL/PRACH -// processing. -bool phy::cell_search() +// processing. If a valid EARFCN (>0) is given, this is used for cell search. +bool phy::cell_search(int earfcn) { sfsync.scell_sync_stop(); if (sfsync.cell_search_init()) { - cmd_worker_cell.add_cmd([this]() { + cmd_worker_cell.add_cmd([this, earfcn]() { // Wait SYNC transitions to IDLE sfsync.wait_idle(); @@ -355,7 +355,7 @@ bool phy::cell_search() reset(); phy_cell_t found_cell = {}; - rrc_interface_phy_lte::cell_search_ret_t ret = sfsync.cell_search_start(&found_cell); + rrc_interface_phy_lte::cell_search_ret_t ret = sfsync.cell_search_start(&found_cell, earfcn); stack->cell_search_complete(ret, found_cell); }); } else { diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 3440f66ad..e46ae3f34 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -179,10 +179,10 @@ void sync::reset() * */ -/* A call to cell_search() finds the strongest cell in the set of supported EARFCNs. When the first cell is found, - * returns 1 and stores cell information and RSRP values in the pointers (if provided). If a cell is not found in the - * current frequency it moves to the next one and the next call to cell_search() will look in the next EARFCN in the - * set. If no cells are found in any frequency it returns 0. If error returns -1. +/* A call to cell_search() finds the strongest cell at a given EARFCN or in the set of supported EARFCNs. When the first + * cell is found, returns 1 and stores cell information and RSRP values in the pointers (if provided). If a cell is not + * found in the current frequency it moves to the next one and the next call to cell_search() will look in the next + * EARFCN in the set. If no cells are found in any frequency it returns 0. If error returns -1. * * The first part of the procedure (call to _init()) moves the PHY To IDLE, ensuring that no UL/DL/PRACH will happen * @@ -197,7 +197,6 @@ bool sync::cell_search_init() } // Move state to IDLE - Info("Cell Search: Start EARFCN index=%u/%zd", cellsearch_earfcn_index, worker_com->args->dl_earfcn_list.size()); phy_state.go_idle(); // Stop all intra-frequency measurement before changing frequency @@ -208,10 +207,16 @@ bool sync::cell_search_init() return true; } -rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* found_cell) +rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* found_cell, int earfcn) { std::unique_lock ul(rrc_mutex); + if (earfcn < 0) { + Info("Cell Search: Start EARFCN index=%u/%zd", cellsearch_earfcn_index, worker_com->args->dl_earfcn_list.size()); + } else { + Info("Cell Search: Start EARFCN=%d", earfcn); + } + rrc_interface_phy_lte::cell_search_ret_t ret = {}; ret.found = rrc_interface_phy_lte::cell_search_ret_t::ERROR; ret.last_freq = rrc_interface_phy_lte::cell_search_ret_t::NO_MORE_FREQS; @@ -229,16 +234,20 @@ rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* fou Info("SYNC: Setting Cell Search sampling rate"); } - try { - if (current_earfcn != (int)worker_com->args->dl_earfcn_list.at(cellsearch_earfcn_index)) { - current_earfcn = (int)worker_com->args->dl_earfcn_list[cellsearch_earfcn_index]; - Info("Cell Search: changing frequency to EARFCN=%d", current_earfcn); - set_frequency(); + if (earfcn < 0) { + try { + if (current_earfcn != (int)worker_com->args->dl_earfcn_list.at(cellsearch_earfcn_index)) { + current_earfcn = (int)worker_com->args->dl_earfcn_list[cellsearch_earfcn_index]; + } + } catch (const std::out_of_range& oor) { + Error("Index %d is not a valid EARFCN element.", cellsearch_earfcn_index); + return ret; } - } catch (const std::out_of_range& oor) { - Error("Index %d is not a valid EARFCN element.", cellsearch_earfcn_index); - return ret; + } else { + current_earfcn = earfcn; } + Info("Cell Search: changing frequency to EARFCN=%d", current_earfcn); + set_frequency(); // Move to CELL SEARCH and wait to finish Info("Cell Search: Setting Cell search state"); @@ -266,7 +275,7 @@ rrc_interface_phy_lte::cell_search_ret_t sync::cell_search_start(phy_cell_t* fou } cellsearch_earfcn_index++; - if (cellsearch_earfcn_index >= worker_com->args->dl_earfcn_list.size()) { + if (cellsearch_earfcn_index >= worker_com->args->dl_earfcn_list.size() or earfcn < 0) { Info("Cell Search: No more frequencies in the current EARFCN set"); cellsearch_earfcn_index = 0; ret.last_freq = rrc_interface_phy_lte::cell_search_ret_t::NO_MORE_FREQS; diff --git a/srsue/src/phy/test/ue_phy_test.cc b/srsue/src/phy/test/ue_phy_test.cc index b2e4881c6..6bcc6b790 100644 --- a/srsue/src/phy/test/ue_phy_test.cc +++ b/srsue/src/phy/test/ue_phy_test.cc @@ -508,7 +508,7 @@ int main(int argc, char** argv) phy_test->start(); // 1. Cell search - TESTASSERT(phy_test->get_phy_interface_rrc()->cell_search()); + TESTASSERT(phy_test->get_phy_interface_rrc()->cell_search(-1)); TESTASSERT(phy_test->get_stack()->wait_cell_search(default_timeout)); TESTASSERT(phy_test->get_stack()->cell_search_ret.found == srsue::rrc_interface_phy_lte::cell_search_ret_t::CELL_FOUND); diff --git a/srsue/src/stack/rrc/phy_controller.cc b/srsue/src/stack/rrc/phy_controller.cc index 8b9dfa999..4d02c10bb 100644 --- a/srsue/src/stack/rrc/phy_controller.cc +++ b/srsue/src/stack/rrc/phy_controller.cc @@ -166,13 +166,13 @@ void phy_controller::selecting_cell::wait_in_sync::enter(selecting_cell* f) *************************************/ //! Searches for a cell in the current frequency and retrieves SIB1 if not retrieved yet -bool phy_controller::start_cell_search(srsran::event_observer observer) +bool phy_controller::start_cell_search(srsran::event_observer observer, int earfcn) { if (is_in_state()) { fsmInfo("Cell search already launched."); return true; } - trigger(cell_search_cmd{}); + trigger(cell_search_cmd{earfcn}); if (not is_in_state()) { fsmWarning("Failed to launch cell search"); return false; @@ -186,10 +186,10 @@ void phy_controller::cell_search_completed(cell_search_ret_t cs_ret, phy_cell_t trigger(cell_srch_res{cs_ret, found_cell}); } -void phy_controller::searching_cell::enter(phy_controller* f) +void phy_controller::searching_cell::enter(phy_controller* f, const cell_search_cmd& ev) { otherfsmInfo(f, "Initiating Cell search"); - f->phy->cell_search(); + f->phy->cell_search(ev.earfcn); } void phy_controller::handle_cell_search_res(searching_cell& s, const cell_srch_res& result) diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index e0fc30ed5..481c62501 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -1153,8 +1153,9 @@ void rrc::handle_rrc_con_reconfig(uint32_t lcid, const rrc_conn_recfg_s& reconfi } /* Actions upon reception of RRCConnectionRelease 5.3.8.3 */ -void rrc::rrc_connection_release(const std::string& cause) +void rrc::handle_rrc_connection_release(const asn1::rrc::rrc_conn_release_s& release) { + std::string cause = release.crit_exts.c1().rrc_conn_release_r8().release_cause.to_string(); // Save idleModeMobilityControlInfo, etc. srsran::console("Received RRC Connection Release (releaseCause: %s)\n", cause.c_str()); @@ -1164,6 +1165,36 @@ void rrc::rrc_connection_release(const std::string& cause) // delay actions by 60ms as per 5.3.8.3 task_sched.defer_callback(60, [this]() { start_go_idle(); }); + + uint32_t earfcn = 0; + if (release.crit_exts.c1().rrc_conn_release_r8().redirected_carrier_info_present) { + switch (release.crit_exts.c1().rrc_conn_release_r8().redirected_carrier_info.type()) { + case asn1::rrc::redirected_carrier_info_c::types_opts::options::eutra: + earfcn = release.crit_exts.c1().rrc_conn_release_r8().redirected_carrier_info.eutra(); + break; + default: + srsran::console("Ignoring RedirectedCarrierInfo with unsupported type (%s)\n", + release.crit_exts.c1().rrc_conn_release_r8().redirected_carrier_info.type().to_string()); + break; + } + if (earfcn != 0) { + srsran::console("RedirectedCarrierInfo present (type %s, earfcn: %d) - Redirecting\n", + release.crit_exts.c1().rrc_conn_release_r8().redirected_carrier_info.type().to_string(), + earfcn); + logger.info("RedirectedCarrierInfo present (type %s, earfcn: %d) - Redirecting", + release.crit_exts.c1().rrc_conn_release_r8().redirected_carrier_info.type().to_string(), + earfcn); + + // delay actions by 60ms as per 5.3.8.3 + task_sched.defer_callback(60, [this, earfcn]() { start_rrc_redirect(earfcn); }); + } + } +} + +void rrc::start_rrc_redirect(uint32_t new_dl_earfcn) +{ + cell_search_earfcn = (int)new_dl_earfcn; + plmn_search(); } /// TS 36.331, 5.3.12 - UE actions upon leaving RRC_CONNECTED @@ -1818,7 +1849,7 @@ void rrc::parse_dl_dcch(uint32_t lcid, unique_byte_buffer_t pdu) handle_ue_capability_enquiry(c1->ue_cap_enquiry()); break; case dl_dcch_msg_type_c::c1_c_::types::rrc_conn_release: - rrc_connection_release(c1->rrc_conn_release().crit_exts.c1().rrc_conn_release_r8().release_cause.to_string()); + handle_rrc_connection_release(c1->rrc_conn_release()); break; case dl_dcch_msg_type_c::c1_c_::types::ue_info_request_r9: transaction_id = c1->ue_info_request_r9().rrc_transaction_id; diff --git a/srsue/src/stack/rrc/rrc_procedures.cc b/srsue/src/stack/rrc/rrc_procedures.cc index 6b7bcb87a..23cf181ad 100644 --- a/srsue/src/stack/rrc/rrc_procedures.cc +++ b/srsue/src/stack/rrc/rrc_procedures.cc @@ -41,7 +41,7 @@ proc_outcome_t rrc::cell_search_proc::init() { Info("Starting..."); state = state_t::phy_cell_search; - if (not rrc_ptr->phy_ctrl->start_cell_search(rrc_ptr->cell_searcher)) { + if (not rrc_ptr->phy_ctrl->start_cell_search(rrc_ptr->cell_searcher, rrc_ptr->cell_search_earfcn)) { Warning("Failed to initiate Cell Search."); return proc_outcome_t::error; } @@ -1256,11 +1256,14 @@ proc_outcome_t rrc::go_idle_proc::step() void rrc::go_idle_proc::then(const srsran::proc_state_t& result) { - if (rrc_ptr->nas->is_registered() and not rrc_ptr->cell_reselector.launch()) { - rrc_ptr->logger.error("Failed to initiate a Cell Reselection procedure..."); - return; + // only start cell reselection if no RRC redirect is present (redirect will trigger a cell search) + if (rrc_ptr->cell_search_earfcn < 0) { + if (rrc_ptr->nas->is_registered() and not rrc_ptr->cell_reselector.launch()) { + rrc_ptr->logger.error("Failed to initiate a Cell Reselection procedure..."); + return; + } + rrc_ptr->callback_list.add_proc(rrc_ptr->cell_reselector); } - rrc_ptr->callback_list.add_proc(rrc_ptr->cell_reselector); } /************************************** @@ -1362,7 +1365,7 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) { // Save Current RNTI before MAC Reset uint16_t crnti = rrc_ptr->mac->get_crnti(); - size_t nof_scells_active = rrc_ptr->phy_ctrl->current_config_scells().count(); + size_t nof_scells_active = rrc_ptr->phy_ctrl->current_config_scells().count(); // 5.3.7.1 - Conditions for Reestablishment procedure if (not rrc_ptr->security_is_activated or rrc_ptr->state != RRC_STATE_CONNECTED or crnti == SRSRAN_INVALID_RNTI) { @@ -1384,9 +1387,9 @@ proc_outcome_t rrc::connection_reest_proc::init(asn1::rrc::reest_cause_e cause) reest_cellid = rrc_ptr->meas_cells.find_cell(reest_source_freq, reest_source_pci)->get_cell_id(); Info("Starting... cause: \"%s\", UE context: {C-RNTI=0x%x, PCI=%d, CELL ID=%d}", - reest_cause == asn1::rrc::reest_cause_opts::recfg_fail - ? "Reconfiguration failure" - : cause == asn1::rrc::reest_cause_opts::ho_fail ? "Handover failure" : "Other failure", + reest_cause == asn1::rrc::reest_cause_opts::recfg_fail ? "Reconfiguration failure" + : cause == asn1::rrc::reest_cause_opts::ho_fail ? "Handover failure" + : "Other failure", reest_rnti, reest_source_pci, reest_cellid); diff --git a/srsue/src/stack/rrc/test/rrc_meas_test.cc b/srsue/src/stack/rrc/test/rrc_meas_test.cc index 13f7cc135..1d39fcbc7 100644 --- a/srsue/src/stack/rrc/test/rrc_meas_test.cc +++ b/srsue/src/stack/rrc/test/rrc_meas_test.cc @@ -40,7 +40,7 @@ public: void set_config_mbsfn_sib2(srsran::mbsfn_sf_cfg_t* cfg_list, uint32_t nof_cfgs) override {} void set_config_mbsfn_sib13(const srsran::sib13_t& sib13) override {} void set_config_mbsfn_mcch(const srsran::mcch_msg_t& mcch) override {} - bool cell_search() override { return true; } + bool cell_search(int earfcn) override { return true; } bool cell_is_camping() override { return true; } void deactivate_scells() override {} bool cell_select(phy_cell_t cell) override diff --git a/srsue/src/stack/rrc/test/rrc_phy_ctrl_test.cc b/srsue/src/stack/rrc/test/rrc_phy_ctrl_test.cc index 3943a8f36..5313ed6c2 100644 --- a/srsue/src/stack/rrc/test/rrc_phy_ctrl_test.cc +++ b/srsue/src/stack/rrc/test/rrc_phy_ctrl_test.cc @@ -81,7 +81,7 @@ int test_phy_ctrl_fsm() TESTASSERT(phy_ctrl.is_in_sync()); // TEST: Correct initiation of Cell Search state - TESTASSERT(phy_ctrl.start_cell_search(csearch_tester)); + TESTASSERT(phy_ctrl.start_cell_search(csearch_tester, -1)); TESTASSERT(not phy_ctrl.is_in_sync()); // TEST: Cell Search only listens to a cell search result event diff --git a/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h b/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h index 10e5c42f7..ca1034a8f 100644 --- a/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h +++ b/srsue/src/test/ttcn3/hdr/lte_ttcn3_phy.h @@ -69,7 +69,7 @@ public: void set_mch_period_stop(uint32_t stop) override{}; // Cell search and selection procedures - bool cell_search() override; + bool cell_search(int earfcn) override; bool cell_select(phy_cell_t cell) override; bool cell_is_camping() override; diff --git a/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc b/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc index ce1be9e53..5d507929a 100644 --- a/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc +++ b/srsue/src/test/ttcn3/src/lte_ttcn3_phy.cc @@ -87,7 +87,7 @@ void lte_ttcn3_phy::meas_stop() {} // configured by the SS, including the ones that we should not even detect because // their power is too weak. The cell search should only report the cells that // are actually visible though. -bool lte_ttcn3_phy::cell_search() +bool lte_ttcn3_phy::cell_search(int earfcn) { std::lock_guard lock(phy_mutex); From ab9fe90d3a519abb00eb99445618c15ebbc92528 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 21 Jan 2022 12:40:29 +0000 Subject: [PATCH 03/41] rrc,nr: create DU configuration manager in RRC NR class to handle the generation of SIBs and other cell-specific parameters --- srsgnb/hdr/stack/mac/sched_nr_interface.h | 6 +- srsgnb/hdr/stack/rrc/rrc_nr.h | 3 +- srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h | 62 ++++++++++++ srsgnb/src/stack/mac/sched_nr_cfg.cc | 8 +- .../src/stack/mac/sched_nr_interface_utils.cc | 25 +++-- .../stack/mac/test/sched_nr_cfg_generators.h | 15 ++- srsgnb/src/stack/rrc/CMakeLists.txt | 2 +- srsgnb/src/stack/rrc/cell_asn1_config.cc | 30 ++++-- srsgnb/src/stack/rrc/rrc_nr.cc | 73 ++++++-------- srsgnb/src/stack/rrc/rrc_nr_du_manager.cc | 96 +++++++++++++++++++ 10 files changed, 235 insertions(+), 85 deletions(-) create mode 100644 srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h create mode 100644 srsgnb/src/stack/rrc/rrc_nr_du_manager.cc diff --git a/srsgnb/hdr/stack/mac/sched_nr_interface.h b/srsgnb/hdr/stack/mac/sched_nr_interface.h index 1d5e11d0a..edb14fdcd 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_interface.h +++ b/srsgnb/hdr/stack/mac/sched_nr_interface.h @@ -83,8 +83,8 @@ struct sched_nr_cell_cfg_t { uint32_t pci; uint32_t dl_cell_nof_prb; uint32_t ul_cell_nof_prb; - asn1::copy_ptr dl_cfg_common; - asn1::copy_ptr ul_cfg_common; + asn1::rrc_nr::dl_cfg_common_sib_s dl_cfg_common; + asn1::rrc_nr::ul_cfg_common_sib_s ul_cfg_common; srsran::optional tdd_ul_dl_cfg_common; ssb_positions_in_burst_t ssb_positions_in_burst; uint32_t ssb_periodicity_ms = 0; @@ -98,8 +98,6 @@ struct sched_nr_cell_cfg_t { double dl_center_frequency_hz; double ul_center_frequency_hz; double ssb_center_freq_hz; - uint32_t offset_to_carrier; - srsran_subcarrier_spacing_t scs; }; class sched_nr_interface diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index 8da7ccc03..969671baa 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -37,6 +37,7 @@ namespace srsenb { class enb_bearer_manager; +class du_config_manager; enum class rrc_nr_state_t { RRC_IDLE, RRC_INACTIVE, RRC_CONNECTED }; @@ -142,8 +143,8 @@ private: asn1::rrc_nr::sp_cell_cfg_s base_sp_cell_cfg; // vars + std::unique_ptr du_cfg; struct cell_ctxt_t { - asn1::rrc_nr::mib_s mib; asn1::rrc_nr::sib1_s sib1; asn1::rrc_nr::sys_info_ies_s::sib_type_and_info_l_ sibs; srsran::unique_byte_buffer_t mib_buffer = nullptr; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h b/srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h new file mode 100644 index 000000000..eef6e75aa --- /dev/null +++ b/srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h @@ -0,0 +1,62 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_RRC_NR_DU_MANAGER_H +#define SRSRAN_RRC_NR_DU_MANAGER_H + +#include "rrc_nr_config.h" +#include "srsgnb/hdr/stack/mac/sched_nr_interface.h" +#include "srsran/asn1/rrc_nr.h" + +namespace srsenb { + +class du_cell_config +{ +public: + uint32_t cc; + uint32_t pci; + + asn1::rrc_nr::mib_s mib; + srsran::unique_byte_buffer_t packed_mib; + + asn1::rrc_nr::sib1_s sib1; + srsran::unique_byte_buffer_t packed_sib1; + + /// SI messages (index=0 for SIB1) + srsran::const_byte_span packed_si_msg(uint32_t idx) { return srsran::make_span(packed_sib1); } + size_t nof_si_msgs() const { return 1; } +}; + +class du_config_manager +{ +public: + du_config_manager(const rrc_nr_cfg_t& cfg); + ~du_config_manager(); + + int add_cell(); + + const du_cell_config& cell(uint32_t cc) const + { + srsran_assert(cc < cells.size(), "Unknown DU Cell Index=%d", cc); + return *cells[cc]; + } + +private: + const rrc_nr_cfg_t& cfg; + srslog::basic_logger& logger; + + std::vector > cells; +}; + +} // namespace srsenb + +#endif // SRSRAN_RRC_NR_DU_MANAGER_H diff --git a/srsgnb/src/stack/mac/sched_nr_cfg.cc b/srsgnb/src/stack/mac/sched_nr_cfg.cc index 3d5bf248f..532af8c95 100644 --- a/srsgnb/src/stack/mac/sched_nr_cfg.cc +++ b/srsgnb/src/stack/mac/sched_nr_cfg.cc @@ -140,15 +140,11 @@ cell_config_manager::cell_config_manager(uint32_t cc_, carrier.dl_center_frequency_hz = cell.dl_center_frequency_hz; carrier.ul_center_frequency_hz = cell.ul_center_frequency_hz; carrier.ssb_center_freq_hz = cell.ssb_center_freq_hz; - carrier.offset_to_carrier = cell.offset_to_carrier; - carrier.scs = cell.scs; carrier.nof_prb = cell.dl_cell_nof_prb; carrier.start = 0; // TODO: Check carrier.max_mimo_layers = cell.nof_layers; - if (cell.dl_cfg_common.is_present()) { - carrier.offset_to_carrier = cell.dl_cfg_common->freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier; - carrier.scs = (srsran_subcarrier_spacing_t)cell.dl_cfg_common->init_dl_bwp.generic_params.subcarrier_spacing.value; - } + carrier.offset_to_carrier = cell.dl_cfg_common.freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier; + carrier.scs = (srsran_subcarrier_spacing_t)cell.dl_cfg_common.init_dl_bwp.generic_params.subcarrier_spacing.value; // TDD-UL-DL-ConfigCommon duplex.mode = SRSRAN_DUPLEX_MODE_FDD; diff --git a/srsgnb/src/stack/mac/sched_nr_interface_utils.cc b/srsgnb/src/stack/mac/sched_nr_interface_utils.cc index 69f94e516..c50e572b2 100644 --- a/srsgnb/src/stack/mac/sched_nr_interface_utils.cc +++ b/srsgnb/src/stack/mac/sched_nr_interface_utils.cc @@ -25,9 +25,9 @@ uint32_t coreset_nof_cces(const srsran_coreset_t& coreset) void make_mib_cfg(const sched_nr_cell_cfg_t& cfg, srsran_mib_nr_t* mib) { - *mib = {}; - mib->scs_common = cfg.scs; - mib->ssb_offset = 6; // TODO + *mib = {}; + mib->scs_common = (srsran_subcarrier_spacing_t)cfg.dl_cfg_common.init_dl_bwp.generic_params.subcarrier_spacing.value; + mib->ssb_offset = 6; // TODO mib->dmrs_typeA_pos = (srsran_dmrs_sch_typeA_pos_t)cfg.dmrs_type_a_position.value; mib->coreset0_idx = cfg.pdcch_cfg_sib1.ctrl_res_set_zero; mib->ss0_idx = cfg.pdcch_cfg_sib1.search_space_zero; @@ -53,12 +53,10 @@ void make_ssb_cfg(const sched_nr_cell_cfg_t& cfg, srsran::phy_cfg_nr_t::ssb_cfg_ } ssb->scs = (srsran_subcarrier_spacing_t)cfg.ssb_scs.value; ssb->pattern = SRSRAN_SSB_PATTERN_A; - if (cfg.dl_cfg_common.is_present()) { - if (cfg.dl_cfg_common->freq_info_dl.freq_band_list.size() > 0 and - cfg.dl_cfg_common->freq_info_dl.freq_band_list[0].freq_band_ind_nr_present) { - uint32_t band = cfg.dl_cfg_common->freq_info_dl.freq_band_list[0].freq_band_ind_nr; - ssb->pattern = srsran::srsran_band_helper::get_ssb_pattern(band, ssb->scs); - } + if (cfg.dl_cfg_common.freq_info_dl.freq_band_list.size() > 0 and + cfg.dl_cfg_common.freq_info_dl.freq_band_list[0].freq_band_ind_nr_present) { + uint32_t band = cfg.dl_cfg_common.freq_info_dl.freq_band_list[0].freq_band_ind_nr; + ssb->pattern = srsran::srsran_band_helper::get_ssb_pattern(band, ssb->scs); } } @@ -84,10 +82,11 @@ srsran::phy_cfg_nr_t get_common_ue_phy_cfg(const sched_nr_cell_cfg_t& cfg) ue_phy_cfg.carrier.dl_center_frequency_hz = cfg.dl_center_frequency_hz; ue_phy_cfg.carrier.ul_center_frequency_hz = cfg.ul_center_frequency_hz; ue_phy_cfg.carrier.ssb_center_freq_hz = cfg.ssb_center_freq_hz; - ue_phy_cfg.carrier.offset_to_carrier = cfg.offset_to_carrier; - ue_phy_cfg.carrier.scs = cfg.scs; - ue_phy_cfg.carrier.nof_prb = cfg.dl_cell_nof_prb; - ue_phy_cfg.carrier.max_mimo_layers = cfg.nof_layers; + ue_phy_cfg.carrier.offset_to_carrier = cfg.dl_cfg_common.freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier; + ue_phy_cfg.carrier.scs = + (srsran_subcarrier_spacing_t)cfg.dl_cfg_common.init_dl_bwp.generic_params.subcarrier_spacing.value; + ue_phy_cfg.carrier.nof_prb = cfg.dl_cell_nof_prb; + ue_phy_cfg.carrier.max_mimo_layers = cfg.nof_layers; make_ssb_cfg(cfg, &ue_phy_cfg.ssb); // remove UE-specific SearchSpaces (they will be added later via RRC) diff --git a/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h index 4f7c2b42b..dc7744224 100644 --- a/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h +++ b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h @@ -53,11 +53,16 @@ inline sched_nr_cell_cfg_t get_default_cell_cfg(const srsran::phy_cfg_nr_t& phy_ cell_cfg.dl_center_frequency_hz = phy_cfg.carrier.dl_center_frequency_hz; cell_cfg.ul_center_frequency_hz = phy_cfg.carrier.ul_center_frequency_hz; cell_cfg.ssb_center_freq_hz = phy_cfg.carrier.ssb_center_freq_hz; - cell_cfg.offset_to_carrier = phy_cfg.carrier.offset_to_carrier; - cell_cfg.scs = phy_cfg.carrier.scs; - cell_cfg.dl_cell_nof_prb = phy_cfg.carrier.nof_prb; - cell_cfg.nof_layers = phy_cfg.carrier.max_mimo_layers; - cell_cfg.ssb_periodicity_ms = phy_cfg.ssb.periodicity_ms; + cell_cfg.dl_cfg_common.freq_info_dl.scs_specific_carrier_list.resize(1); + cell_cfg.dl_cfg_common.freq_info_dl.scs_specific_carrier_list[0].subcarrier_spacing = + (asn1::rrc_nr::subcarrier_spacing_opts::options)phy_cfg.carrier.scs; + cell_cfg.dl_cfg_common.freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier = + phy_cfg.carrier.offset_to_carrier; + cell_cfg.dl_cfg_common.init_dl_bwp.generic_params.subcarrier_spacing = + (asn1::rrc_nr::subcarrier_spacing_opts::options)phy_cfg.carrier.scs; + cell_cfg.dl_cell_nof_prb = phy_cfg.carrier.nof_prb; + cell_cfg.nof_layers = phy_cfg.carrier.max_mimo_layers; + cell_cfg.ssb_periodicity_ms = phy_cfg.ssb.periodicity_ms; for (uint32_t i = 0; i < cell_cfg.ssb_positions_in_burst.in_one_group.length(); ++i) { cell_cfg.ssb_positions_in_burst.in_one_group.set(i, phy_cfg.ssb.position_in_burst[i]); } diff --git a/srsgnb/src/stack/rrc/CMakeLists.txt b/srsgnb/src/stack/rrc/CMakeLists.txt index d2c57ff9a..d9af16719 100644 --- a/srsgnb/src/stack/rrc/CMakeLists.txt +++ b/srsgnb/src/stack/rrc/CMakeLists.txt @@ -10,7 +10,7 @@ set(SOURCES rrc_nr_config_utils.cc) add_library(srsgnb_rrc_config_utils STATIC ${SOURCES}) target_link_libraries(srsgnb_rrc_config_utils srsran_phy) -set(SOURCES rrc_nr.cc rrc_nr_ue.cc rrc_nr_security_context.cc cell_asn1_config.cc) +set(SOURCES rrc_nr.cc rrc_nr_ue.cc rrc_nr_security_context.cc cell_asn1_config.cc rrc_nr_du_manager.cc) add_library(srsgnb_rrc STATIC ${SOURCES}) target_link_libraries(srsgnb_rrc srsgnb_rrc_config_utils) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 294c8021a..94d225749 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -122,6 +122,18 @@ void set_rach_cfg_common(const srsran_prach_cfg_t& prach_cfg, asn1::rrc_nr::rach //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void fill_tdd_ul_dl_config_common(const rrc_cell_cfg_nr_t& cfg, asn1::rrc_nr::tdd_ul_dl_cfg_common_s& tdd) +{ + srsran_assert(cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD, "This function should only be called for TDD configs"); + // TDD UL-DL config + tdd.ref_subcarrier_spacing.value = (asn1::rrc_nr::subcarrier_spacing_opts::options)cfg.phy_cell.carrier.scs; + tdd.pattern1.dl_ul_tx_periodicity = asn1::rrc_nr::tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10; + tdd.pattern1.nrof_dl_slots = 6; + tdd.pattern1.nrof_dl_symbols = 0; + tdd.pattern1.nrof_ul_slots = 4; + tdd.pattern1.nrof_ul_symbols = 0; +} + /// Fill list of CSI-ReportConfig with gNB config int fill_csi_report_from_enb_cfg(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_meas_cfg) { @@ -888,13 +900,7 @@ int fill_serv_cell_common_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, ser if (cfg.cell_list[cc].duplex_mode == SRSRAN_DUPLEX_MODE_TDD) { // TDD UL-DL config serv_common.tdd_ul_dl_cfg_common_present = true; - auto& tdd_config = serv_common.tdd_ul_dl_cfg_common; - tdd_config.ref_subcarrier_spacing = subcarrier_spacing_e::khz15; - tdd_config.pattern1.dl_ul_tx_periodicity = asn1::rrc_nr::tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10; - tdd_config.pattern1.nrof_dl_slots = 6; - tdd_config.pattern1.nrof_dl_symbols = 0; - tdd_config.pattern1.nrof_ul_slots = 4; - tdd_config.pattern1.nrof_ul_symbols = 0; + fill_tdd_ul_dl_config_common(cfg.cell_list[cc], serv_common.tdd_ul_dl_cfg_common); } serv_common.ul_cfg_common_present = true; @@ -1135,7 +1141,7 @@ void fill_dl_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, dl_cfg_common_sib uint32_t offset_point_a_prbs = offset_point_a_hz / prb_bw; cfg.freq_info_dl.offset_to_point_a = offset_point_a_prbs; cfg.freq_info_dl.scs_specific_carrier_list.resize(1); - cfg.freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier = 0; + cfg.freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier = cell_cfg.phy_cell.carrier.offset_to_carrier; cfg.freq_info_dl.scs_specific_carrier_list[0].subcarrier_spacing = (subcarrier_spacing_opts::options)cell_cfg.phy_cell.carrier.scs; cfg.freq_info_dl.scs_specific_carrier_list[0].carrier_bw = cell_cfg.phy_cell.carrier.nof_prb; @@ -1165,7 +1171,7 @@ void fill_ul_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, ul_cfg_common_sib band_helper.get_abs_freq_point_a_arfcn(cell_cfg.phy_cell.carrier.nof_prb, cell_cfg.ul_arfcn); cfg.freq_info_ul.scs_specific_carrier_list.resize(1); - cfg.freq_info_ul.scs_specific_carrier_list[0].offset_to_carrier = 0; + cfg.freq_info_ul.scs_specific_carrier_list[0].offset_to_carrier = cell_cfg.phy_cell.carrier.offset_to_carrier; cfg.freq_info_ul.scs_specific_carrier_list[0].subcarrier_spacing = (subcarrier_spacing_opts::options)cell_cfg.phy_cell.carrier.scs; cfg.freq_info_ul.scs_specific_carrier_list[0].carrier_bw = cell_cfg.phy_cell.carrier.nof_prb; @@ -1212,6 +1218,12 @@ void fill_serv_cell_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, serving_ce cfg.ssb_periodicity_serving_cell.value = serving_cell_cfg_common_sib_s::ssb_periodicity_serving_cell_opts::ms20; + // TDD UL-DL config + if (cell_cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD) { + cfg.tdd_ul_dl_cfg_common_present = true; + fill_tdd_ul_dl_config_common(cell_cfg, cfg.tdd_ul_dl_cfg_common); + } + cfg.ss_pbch_block_pwr = cell_cfg.phy_cell.pdsch.rs_power; } diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index ddd65fe38..b241958a6 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -14,6 +14,7 @@ #include "srsenb/hdr/common/common_enb.h" #include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" #include "srsgnb/hdr/stack/rrc/rrc_nr_config_utils.h" +#include "srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h" #include "srsgnb/hdr/stack/rrc/rrc_nr_ue.h" #include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" #include "srsran/asn1/rrc_nr_utils.h" @@ -68,6 +69,11 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, cell.ssb_absolute_freq_point); } + du_cfg = std::make_unique(cfg); + for (uint32_t i = 0; i < cfg.cell_list.size(); ++i) { + du_cfg->add_cell(); + } + // Generate cell config structs cell_ctxt.reset(new cell_ctxt_t{}); if (cfg.is_standalone) { @@ -293,54 +299,49 @@ void rrc_nr::config_phy() void rrc_nr::config_mac() { + uint32_t cc = 0; // Fill MAC scheduler configuration for SIBs // TODO: use parsed cell NR cfg configuration srsran::phy_cfg_nr_default_t::reference_cfg_t ref_args{}; - ref_args.duplex = cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_TDD + ref_args.duplex = cfg.cell_list[cc].duplex_mode == SRSRAN_DUPLEX_MODE_TDD ? srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4 : srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_FDD; std::vector sched_cells_cfg(1, get_default_cell_cfg(srsran::phy_cfg_nr_default_t{ref_args})); - sched_nr_cell_cfg_t& cell = sched_cells_cfg[0]; + sched_nr_cell_cfg_t& cell = sched_cells_cfg[cc]; // Derive cell config from rrc_nr_cfg_t - cell.bwps[0].pdcch = cfg.cell_list[0].phy_cell.pdcch; - cell.pci = cfg.cell_list[0].phy_cell.carrier.pci; - cell.nof_layers = cfg.cell_list[0].phy_cell.carrier.max_mimo_layers; - cell.dl_cell_nof_prb = cfg.cell_list[0].phy_cell.carrier.nof_prb; - cell.ul_cell_nof_prb = cfg.cell_list[0].phy_cell.carrier.nof_prb; - cell.dl_center_frequency_hz = cfg.cell_list[0].phy_cell.carrier.dl_center_frequency_hz; - cell.ul_center_frequency_hz = cfg.cell_list[0].phy_cell.carrier.ul_center_frequency_hz; - cell.ssb_center_freq_hz = cfg.cell_list[0].phy_cell.carrier.ssb_center_freq_hz; - cell.offset_to_carrier = cfg.cell_list[0].phy_cell.carrier.offset_to_carrier; - cell.scs = cfg.cell_list[0].phy_cell.carrier.scs; + cell.bwps[0].pdcch = cfg.cell_list[cc].phy_cell.pdcch; + cell.pci = cfg.cell_list[cc].phy_cell.carrier.pci; + cell.nof_layers = cfg.cell_list[cc].phy_cell.carrier.max_mimo_layers; + cell.dl_cell_nof_prb = cfg.cell_list[cc].phy_cell.carrier.nof_prb; + cell.ul_cell_nof_prb = cfg.cell_list[cc].phy_cell.carrier.nof_prb; + cell.dl_center_frequency_hz = cfg.cell_list[cc].phy_cell.carrier.dl_center_frequency_hz; + cell.ul_center_frequency_hz = cfg.cell_list[cc].phy_cell.carrier.ul_center_frequency_hz; + cell.ssb_center_freq_hz = cfg.cell_list[cc].phy_cell.carrier.ssb_center_freq_hz; + cell.dmrs_type_a_position = du_cfg->cell(cc).mib.dmrs_type_a_position; + cell.pdcch_cfg_sib1 = du_cfg->cell(cc).mib.pdcch_cfg_sib1; + if (du_cfg->cell(cc).sib1.serving_cell_cfg_common.tdd_ul_dl_cfg_common_present) { + cell.tdd_ul_dl_cfg_common.emplace(du_cfg->cell(cc).sib1.serving_cell_cfg_common.tdd_ul_dl_cfg_common); + } + cell.dl_cfg_common = du_cfg->cell(cc).sib1.serving_cell_cfg_common.dl_cfg_common; + cell.ul_cfg_common = du_cfg->cell(cc).sib1.serving_cell_cfg_common.ul_cfg_common; + cell.ss_pbch_block_power = du_cfg->cell(cc).sib1.serving_cell_cfg_common.ss_pbch_block_pwr; if (not cfg.is_standalone) { const serving_cell_cfg_common_s& serv_cell = base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common; // Derive cell config from ASN1 bool valid_cfg = srsran::make_pdsch_cfg_from_serv_cell(base_sp_cell_cfg.sp_cell_cfg_ded, &cell.bwps[0].pdsch); srsran_assert(valid_cfg, "Invalid NR cell configuration."); - if (serv_cell.tdd_ul_dl_cfg_common_present) { - cell.tdd_ul_dl_cfg_common.emplace(serv_cell.tdd_ul_dl_cfg_common); - } cell.ssb_positions_in_burst.in_one_group.set(0, true); - cell.ssb_periodicity_ms = serv_cell.ssb_periodicity_serving_cell.to_number(); - cell.ssb_scs = serv_cell.ssb_subcarrier_spacing; - cell.ss_pbch_block_power = serv_cell.ss_pbch_block_pwr; + cell.ssb_periodicity_ms = serv_cell.ssb_periodicity_serving_cell.to_number(); + cell.ssb_scs = serv_cell.ssb_subcarrier_spacing; } else { const serving_cell_cfg_common_sib_s& serv_cell = cell_ctxt->sib1.serving_cell_cfg_common; cell.bwps[0].pdsch.p_zp_csi_rs_set = {}; bzero(cell.bwps[0].pdsch.nzp_csi_rs_sets, sizeof(cell.bwps[0].pdsch.nzp_csi_rs_sets)); - cell.dl_cfg_common.reset(new dl_cfg_common_sib_s{serv_cell.dl_cfg_common}); - cell.ul_cfg_common.reset(new ul_cfg_common_sib_s{serv_cell.ul_cfg_common}); - if (serv_cell.tdd_ul_dl_cfg_common_present) { - cell.tdd_ul_dl_cfg_common.emplace(serv_cell.tdd_ul_dl_cfg_common); - } cell.ssb_positions_in_burst = serv_cell.ssb_positions_in_burst; cell.ssb_periodicity_ms = serv_cell.ssb_periodicity_serving_cell.to_number(); cell.ssb_scs.value = (subcarrier_spacing_e::options)cfg.cell_list[0].phy_cell.carrier.scs; - cell.ss_pbch_block_power = serv_cell.ss_pbch_block_pwr; } - cell.dmrs_type_a_position = cell_ctxt->mib.dmrs_type_a_position; - cell.pdcch_cfg_sib1 = cell_ctxt->mib.pdcch_cfg_sib1; // Set SIB1 and SI messages cell.sibs.resize(cell_ctxt->sib_buffer.size()); @@ -364,26 +365,6 @@ void rrc_nr::config_mac() int32_t rrc_nr::generate_sibs() { - // MIB packing - fill_mib_from_enb_cfg(cfg.cell_list[0], cell_ctxt->mib); - bcch_bch_msg_s mib_msg; - mib_msg.msg.set_mib() = cell_ctxt->mib; - { - srsran::unique_byte_buffer_t mib_buf = srsran::make_byte_buffer(); - if (mib_buf == nullptr) { - logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); - return SRSRAN_ERROR; - } - asn1::bit_ref bref(mib_buf->msg, mib_buf->get_tailroom()); - if (mib_msg.pack(bref) != asn1::SRSASN_SUCCESS) { - logger.error("Couldn't pack mib msg"); - return SRSRAN_ERROR; - } - mib_buf->N_bytes = bref.distance_bytes(); - logger.debug(mib_buf->msg, mib_buf->N_bytes, "MIB payload (%d B)", mib_buf->N_bytes); - cell_ctxt->mib_buffer = std::move(mib_buf); - } - if (not cfg.is_standalone) { return SRSRAN_SUCCESS; } diff --git a/srsgnb/src/stack/rrc/rrc_nr_du_manager.cc b/srsgnb/src/stack/rrc/rrc_nr_du_manager.cc new file mode 100644 index 000000000..7faf37b17 --- /dev/null +++ b/srsgnb/src/stack/rrc/rrc_nr_du_manager.cc @@ -0,0 +1,96 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h" +#include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" +#include "srsran/common/string_helpers.h" + +using namespace asn1::rrc_nr; + +namespace srsenb { + +du_config_manager::du_config_manager(const rrc_nr_cfg_t& cfg_) : cfg(cfg_), logger(srslog::fetch_basic_logger("RRC-NR")) +{} + +du_config_manager::~du_config_manager() {} + +int du_config_manager::add_cell() +{ + // add cell + std::unique_ptr obj = std::make_unique(); + du_cell_config& cell = *obj; + cell.cc = cells.size(); + + // Fill general cell params + cell.pci = cfg.cell_list[cell.cc].phy_cell.carrier.pci; + + // fill MIB ASN.1 + if (fill_mib_from_enb_cfg(cfg.cell_list[cell.cc], cell.mib) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + // Pack MIB + cell.packed_mib = srsran::make_byte_buffer(); + if (cell.packed_mib == nullptr) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + { + asn1::bit_ref bref(cell.packed_mib->msg, cell.packed_mib->get_tailroom()); + bcch_bch_msg_s bch_msg; + bch_msg.msg.set_mib() = cell.mib; + if (bch_msg.pack(bref) != asn1::SRSASN_SUCCESS) { + logger.error("Couldn't pack mib msg"); + return SRSRAN_ERROR; + } + cell.packed_mib->N_bytes = bref.distance_bytes(); + } + logger.info( + cell.packed_mib->data(), cell.packed_mib->size(), "BCCH-BCH Message (with MIB) (%d B)", cell.packed_mib->size()); + asn1::json_writer js; + cell.mib.to_json(js); + logger.info("MIB content: %s", js.to_string().c_str()); + + // fill SIB1 ASN.1 + if (fill_sib1_from_enb_cfg(cfg, cell.cc, cell.sib1) != SRSRAN_SUCCESS) { + logger.error("Couldn't generate SIB1"); + return SRSRAN_ERROR; + } + + // Pack SIB1 + cell.packed_sib1 = srsran::make_byte_buffer(); + if (cell.packed_sib1 == nullptr) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + { + asn1::bit_ref bref(cell.packed_sib1->msg, cell.packed_sib1->get_tailroom()); + bcch_dl_sch_msg_s bcch_msg; + bcch_msg.msg.set_c1().set_sib_type1() = cell.sib1; + if (bcch_msg.pack(bref) != asn1::SRSASN_SUCCESS) { + logger.error("Couldn't pack SIB1 msg"); + return SRSRAN_ERROR; + } + cell.packed_sib1->N_bytes = bref.distance_bytes(); + } + logger.info(cell.packed_sib1->data(), + cell.packed_sib1->size(), + "BCCH-DL-SCH-Message (with SIB1) (%d B)", + cell.packed_sib1->size()); + cell.sib1.to_json(js); + logger.info("SIB1 content: %s", js.to_string().c_str()); + + cells.push_back(std::move(obj)); + return SRSRAN_SUCCESS; +} + +} // namespace srsenb \ No newline at end of file From e6af64c147c7dd00bbb954bdb45fafddc72059d3 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 21 Jan 2022 13:48:39 +0000 Subject: [PATCH 04/41] rrc,nr: removal of ssb config from the rrc_nr_cfg_t --- srsgnb/hdr/stack/rrc/rrc_nr_config.h | 24 ++++++------ srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h | 10 ++++- srsgnb/src/stack/rrc/cell_asn1_config.cc | 19 +++++----- srsgnb/src/stack/rrc/rrc_nr.cc | 29 +++++++++------ srsgnb/src/stack/rrc/rrc_nr_config_utils.cc | 41 +++++++-------------- 5 files changed, 61 insertions(+), 62 deletions(-) diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_config.h b/srsgnb/hdr/stack/rrc/rrc_nr_config.h index dc38c1659..0bf40b583 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_config.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_config.h @@ -32,17 +32,19 @@ struct rrc_nr_cfg_sr_t { // Cell/Sector configuration for NR cells struct rrc_cell_cfg_nr_t { - phy_cell_cfg_nr_t phy_cell; // already contains all PHY-related parameters (i.e. RF port, PCI, etc.) - uint32_t tac; // Tracking area code - uint32_t dl_arfcn; // DL freq already included in phy_cell - uint32_t ul_arfcn; // UL freq also in phy_cell - uint32_t dl_absolute_freq_point_a; // derived from DL ARFCN - uint32_t ul_absolute_freq_point_a; // derived from UL ARFCN - uint32_t ssb_absolute_freq_point; // derived from DL ARFCN (SSB arfcn) - uint32_t band; - uint32_t coreset0_idx; // Table 13-{1,...15} row index - srsran_duplex_mode_t duplex_mode; - srsran_ssb_cfg_t ssb_cfg; + phy_cell_cfg_nr_t phy_cell; // already contains all PHY-related parameters (i.e. RF port, PCI, etc.) + uint32_t tac; // Tracking area code + uint32_t dl_arfcn; // DL freq already included in phy_cell + uint32_t ul_arfcn; // UL freq also in phy_cell + uint32_t dl_absolute_freq_point_a; // derived from DL ARFCN + uint32_t ul_absolute_freq_point_a; // derived from UL ARFCN + uint32_t band; + uint32_t coreset0_idx; // Table 13-{1,...15} row index + srsran_duplex_mode_t duplex_mode; + double ssb_freq_hz; + uint32_t ssb_absolute_freq_point; // derived from DL ARFCN (SSB arfcn) + srsran_subcarrier_spacing_t ssb_scs; + srsran_ssb_patern_t ssb_pattern; }; typedef std::vector rrc_cell_list_nr_t; diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h b/srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h index eef6e75aa..05e063e4f 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_du_manager.h @@ -31,6 +31,11 @@ public: asn1::rrc_nr::sib1_s sib1; srsran::unique_byte_buffer_t packed_sib1; + const asn1::rrc_nr::serving_cell_cfg_common_sib_s& serv_cell_cfg_common() const + { + return sib1.serving_cell_cfg_common; + } + /// SI messages (index=0 for SIB1) srsran::const_byte_span packed_si_msg(uint32_t idx) { return srsran::make_span(packed_sib1); } size_t nof_si_msgs() const { return 1; } @@ -39,9 +44,11 @@ public: class du_config_manager { public: - du_config_manager(const rrc_nr_cfg_t& cfg); + explicit du_config_manager(const rrc_nr_cfg_t& cfg); ~du_config_manager(); + const rrc_nr_cfg_t& cfg; + int add_cell(); const du_cell_config& cell(uint32_t cc) const @@ -51,7 +58,6 @@ public: } private: - const rrc_nr_cfg_t& cfg; srslog::basic_logger& logger; std::vector > cells; diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 94d225749..1dce59a6d 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -868,18 +868,15 @@ int fill_serv_cell_common_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, ser serv_common.ss_pbch_block_pwr = cell_cfg.phy_cell.pdsch.rs_power; serv_common.n_timing_advance_offset_present = true; - serv_common.n_timing_advance_offset = asn1::rrc_nr::serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0; + serv_common.n_timing_advance_offset = serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0; serv_common.n_timing_advance_offset_present = true; - serv_common.dmrs_type_a_position = asn1::rrc_nr::serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2; + serv_common.dmrs_type_a_position = serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2; serv_common.pci_present = true; serv_common.pci = cell_cfg.phy_cell.carrier.pci; serv_common.ssb_periodicity_serving_cell_present = true; - if (not asn1::number_to_enum(serv_common.ssb_periodicity_serving_cell, cell_cfg.ssb_cfg.periodicity_ms)) { - get_logger(cfg).error("Config Error: Invalid SSB periodicity = %d\n", cell_cfg.ssb_cfg.periodicity_ms); - return SRSRAN_ERROR; - } + serv_common.ssb_periodicity_serving_cell.value = serving_cell_cfg_common_s::ssb_periodicity_serving_cell_opts::ms10; // Fill SSB config serv_common.ssb_positions_in_burst_present = true; @@ -1136,7 +1133,7 @@ void fill_dl_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, dl_cfg_common_sib cfg.freq_info_dl.freq_band_list.resize(1); cfg.freq_info_dl.freq_band_list[0].freq_band_ind_nr_present = true; cfg.freq_info_dl.freq_band_list[0].freq_band_ind_nr = cell_cfg.band; - double ssb_freq_start = cell_cfg.ssb_cfg.ssb_freq_hz - SRSRAN_SSB_BW_SUBC * scs_hz / 2; + double ssb_freq_start = cell_cfg.ssb_freq_hz - SRSRAN_SSB_BW_SUBC * scs_hz / 2; double offset_point_a_hz = ssb_freq_start - band_helper.nr_arfcn_to_freq(cell_cfg.dl_absolute_freq_point_a); uint32_t offset_point_a_prbs = offset_point_a_hz / prb_bw; cfg.freq_info_dl.offset_to_point_a = offset_point_a_prbs; @@ -1207,7 +1204,7 @@ void fill_ul_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, ul_cfg_common_sib cfg.time_align_timer_common.value = time_align_timer_opts::infinity; } -void fill_serv_cell_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, serving_cell_cfg_common_sib_s& cfg) +int fill_serv_cell_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, serving_cell_cfg_common_sib_s& cfg) { fill_dl_cfg_common_sib(cell_cfg, cfg.dl_cfg_common); @@ -1216,7 +1213,7 @@ void fill_serv_cell_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, serving_ce cfg.ssb_positions_in_burst.in_one_group.from_number(0x80); - cfg.ssb_periodicity_serving_cell.value = serving_cell_cfg_common_sib_s::ssb_periodicity_serving_cell_opts::ms20; + cfg.ssb_periodicity_serving_cell.value = serving_cell_cfg_common_sib_s::ssb_periodicity_serving_cell_opts::ms10; // TDD UL-DL config if (cell_cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD) { @@ -1225,6 +1222,8 @@ void fill_serv_cell_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, serving_ce } cfg.ss_pbch_block_pwr = cell_cfg.phy_cell.pdsch.rs_power; + + return SRSRAN_SUCCESS; } int fill_sib1_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1::rrc_nr::sib1_s& sib1) @@ -1269,7 +1268,7 @@ int fill_sib1_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1::rrc_nr::s // sib1.si_sched_info.sched_info_list[0].sib_map_info[0].value_tag = 0; sib1.serving_cell_cfg_common_present = true; - fill_serv_cell_cfg_common_sib(cell_cfg, sib1.serving_cell_cfg_common); + HANDLE_ERROR(fill_serv_cell_cfg_common_sib(cell_cfg, sib1.serving_cell_cfg_common)); sib1.ue_timers_and_consts_present = true; sib1.ue_timers_and_consts.t300.value = ue_timers_and_consts_s::t300_opts::ms1000; diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index b241958a6..676ba17b7 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -95,13 +95,13 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, int ret = fill_sp_cell_cfg_from_enb_cfg(cfg, UE_PSCELL_CC_IDX, base_sp_cell_cfg); srsran_assert(ret == SRSRAN_SUCCESS, "Failed to configure cell"); - pdcch_cfg_common_s* asn1_pdcch; + const pdcch_cfg_common_s* asn1_pdcch; if (not cfg.is_standalone) { // Fill rrc_nr_cfg with UE-specific search spaces and coresets asn1_pdcch = &base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); } else { - asn1_pdcch = &cell_ctxt->sib1.serving_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); + asn1_pdcch = &du_cfg->cell(0).serv_cell_cfg_common().dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); } srsran_assert(check_nr_phy_cell_cfg_valid(cfg.cell_list[0].phy_cell) == SRSRAN_SUCCESS, "Invalid PhyCell Config"); @@ -290,7 +290,13 @@ void rrc_nr::config_phy() common_cfg.pdcch = cfg.cell_list[0].phy_cell.pdcch; common_cfg.prach = cfg.cell_list[0].phy_cell.prach; common_cfg.duplex_mode = cfg.cell_list[0].duplex_mode; - common_cfg.ssb = cfg.cell_list[0].ssb_cfg; + common_cfg.ssb = {}; + common_cfg.ssb.center_freq_hz = cfg.cell_list[0].phy_cell.dl_freq_hz; + common_cfg.ssb.ssb_freq_hz = cfg.cell_list[0].ssb_freq_hz; + common_cfg.ssb.scs = cfg.cell_list[0].ssb_scs; + common_cfg.ssb.pattern = cfg.cell_list[0].ssb_pattern; + common_cfg.ssb.duplex_mode = cfg.cell_list[0].duplex_mode; + common_cfg.ssb.periodicity_ms = du_cfg->cell(0).serv_cell_cfg_common().ssb_periodicity_serving_cell.to_number(); if (phy->set_common_cfg(common_cfg) < SRSRAN_SUCCESS) { logger.error("Couldn't set common PHY config"); return; @@ -320,12 +326,12 @@ void rrc_nr::config_mac() cell.ssb_center_freq_hz = cfg.cell_list[cc].phy_cell.carrier.ssb_center_freq_hz; cell.dmrs_type_a_position = du_cfg->cell(cc).mib.dmrs_type_a_position; cell.pdcch_cfg_sib1 = du_cfg->cell(cc).mib.pdcch_cfg_sib1; - if (du_cfg->cell(cc).sib1.serving_cell_cfg_common.tdd_ul_dl_cfg_common_present) { - cell.tdd_ul_dl_cfg_common.emplace(du_cfg->cell(cc).sib1.serving_cell_cfg_common.tdd_ul_dl_cfg_common); + if (du_cfg->cell(cc).serv_cell_cfg_common().tdd_ul_dl_cfg_common_present) { + cell.tdd_ul_dl_cfg_common.emplace(du_cfg->cell(cc).serv_cell_cfg_common().tdd_ul_dl_cfg_common); } - cell.dl_cfg_common = du_cfg->cell(cc).sib1.serving_cell_cfg_common.dl_cfg_common; - cell.ul_cfg_common = du_cfg->cell(cc).sib1.serving_cell_cfg_common.ul_cfg_common; - cell.ss_pbch_block_power = du_cfg->cell(cc).sib1.serving_cell_cfg_common.ss_pbch_block_pwr; + cell.dl_cfg_common = du_cfg->cell(cc).serv_cell_cfg_common().dl_cfg_common; + cell.ul_cfg_common = du_cfg->cell(cc).serv_cell_cfg_common().ul_cfg_common; + cell.ss_pbch_block_power = du_cfg->cell(cc).serv_cell_cfg_common().ss_pbch_block_pwr; if (not cfg.is_standalone) { const serving_cell_cfg_common_s& serv_cell = base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common; // Derive cell config from ASN1 @@ -335,11 +341,10 @@ void rrc_nr::config_mac() cell.ssb_periodicity_ms = serv_cell.ssb_periodicity_serving_cell.to_number(); cell.ssb_scs = serv_cell.ssb_subcarrier_spacing; } else { - const serving_cell_cfg_common_sib_s& serv_cell = cell_ctxt->sib1.serving_cell_cfg_common; - cell.bwps[0].pdsch.p_zp_csi_rs_set = {}; + cell.bwps[0].pdsch.p_zp_csi_rs_set = {}; bzero(cell.bwps[0].pdsch.nzp_csi_rs_sets, sizeof(cell.bwps[0].pdsch.nzp_csi_rs_sets)); - cell.ssb_positions_in_burst = serv_cell.ssb_positions_in_burst; - cell.ssb_periodicity_ms = serv_cell.ssb_periodicity_serving_cell.to_number(); + cell.ssb_positions_in_burst = du_cfg->cell(cc).serv_cell_cfg_common().ssb_positions_in_burst; + cell.ssb_periodicity_ms = du_cfg->cell(cc).serv_cell_cfg_common().ssb_periodicity_serving_cell.to_number(); cell.ssb_scs.value = (subcarrier_spacing_e::options)cfg.cell_list[0].phy_cell.carrier.scs; } diff --git a/srsgnb/src/stack/rrc/rrc_nr_config_utils.cc b/srsgnb/src/stack/rrc/rrc_nr_config_utils.cc index d1c008755..77ac0e6dd 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_config_utils.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_config_utils.cc @@ -108,7 +108,7 @@ int derive_coreset0_params(rrc_cell_cfg_nr_t& cell) (ssb_abs_freq_Hz > pointA_abs_freq_Hz) ? (uint32_t)(ssb_abs_freq_Hz - pointA_abs_freq_Hz) : 0; int ret = srsran_coreset_zero(cell.phy_cell.carrier.pci, ssb_pointA_freq_offset_Hz, - cell.ssb_cfg.scs, + cell.ssb_scs, cell.phy_cell.carrier.scs, cell.coreset0_idx, &cell.phy_cell.pdcch.coreset[0]); @@ -122,7 +122,7 @@ int derive_ssb_params(bool is_sa, srsran_subcarrier_spacing_t pdcch_scs, uint32_t coreset0_idx, uint32_t nof_prb, - srsran_ssb_cfg_t& ssb) + rrc_cell_cfg_nr_t& cell) { // Verify essential parameters are specified and valid ERROR_IF_NOT(dl_arfcn > 0, "Invalid DL ARFCN=%d", dl_arfcn); @@ -136,20 +136,17 @@ int derive_ssb_params(bool is_sa, double dl_freq_hz = band_helper.nr_arfcn_to_freq(dl_arfcn); uint32_t dl_absolute_freq_point_a = band_helper.get_abs_freq_point_a_arfcn(nof_prb, dl_arfcn); - ssb.center_freq_hz = dl_freq_hz; - ssb.duplex_mode = band_helper.get_duplex_mode(band); - // derive SSB pattern and scs - ssb.pattern = band_helper.get_ssb_pattern(band, srsran_subcarrier_spacing_15kHz); - if (ssb.pattern == SRSRAN_SSB_PATTERN_A) { + cell.ssb_pattern = band_helper.get_ssb_pattern(band, srsran_subcarrier_spacing_15kHz); + if (cell.ssb_pattern == SRSRAN_SSB_PATTERN_A) { // 15kHz SSB SCS - ssb.scs = srsran_subcarrier_spacing_15kHz; + cell.ssb_scs = srsran_subcarrier_spacing_15kHz; } else { // try to optain SSB pattern for same band with 30kHz SCS - ssb.pattern = band_helper.get_ssb_pattern(band, srsran_subcarrier_spacing_30kHz); - if (ssb.pattern == SRSRAN_SSB_PATTERN_B || ssb.pattern == SRSRAN_SSB_PATTERN_C) { + cell.ssb_pattern = band_helper.get_ssb_pattern(band, srsran_subcarrier_spacing_30kHz); + if (cell.ssb_pattern == SRSRAN_SSB_PATTERN_B || cell.ssb_pattern == SRSRAN_SSB_PATTERN_C) { // SSB SCS is 30 kHz - ssb.scs = srsran_subcarrier_spacing_30kHz; + cell.ssb_scs = srsran_subcarrier_spacing_30kHz; } else { srsran_terminate("Can't derive SSB pattern from band %d", band); } @@ -159,29 +156,20 @@ int derive_ssb_params(bool is_sa, int coreset0_rb_offset = 0; if (is_sa) { // Get offset in RBs between CORESET#0 and SSB - coreset0_rb_offset = srsran_coreset0_ssb_offset(coreset0_idx, ssb.scs, pdcch_scs); + coreset0_rb_offset = srsran_coreset0_ssb_offset(coreset0_idx, cell.ssb_scs, pdcch_scs); ERROR_IF_NOT(coreset0_rb_offset >= 0, "Failed to compute RB offset between CORESET#0 and SSB"); } else { // TODO: Verify if specified SSB frequency is valid } uint32_t ssb_abs_freq_point = - band_helper.get_abs_freq_ssb_arfcn(band, ssb.scs, dl_absolute_freq_point_a, coreset0_rb_offset); + band_helper.get_abs_freq_ssb_arfcn(band, cell.ssb_scs, dl_absolute_freq_point_a, coreset0_rb_offset); ERROR_IF_NOT(ssb_abs_freq_point > 0, "Can't derive SSB freq point for dl_arfcn=%d and band %d", band_helper.freq_to_nr_arfcn(dl_freq_hz), band); // Convert to frequency for PHY - ssb.ssb_freq_hz = band_helper.nr_arfcn_to_freq(ssb_abs_freq_point); - - ssb.periodicity_ms = 10; // TODO: make a param - ssb.beta_pss = 0.0; - ssb.beta_sss = 0.0; - ssb.beta_pbch = 0.0; - ssb.beta_pbch_dmrs = 0.0; - // set by PHY layer in worker_pool::set_common_cfg - ssb.srate_hz = 0.0; - ssb.scaling = 0.0; + cell.ssb_freq_hz = band_helper.nr_arfcn_to_freq(ssb_abs_freq_point); return SRSRAN_SUCCESS; } @@ -250,9 +238,9 @@ int set_derived_nr_cell_params(bool is_sa, rrc_cell_cfg_nr_t& cell) cell.phy_cell.carrier.scs, cell.coreset0_idx, cell.phy_cell.carrier.nof_prb, - cell.ssb_cfg); - cell.phy_cell.carrier.ssb_center_freq_hz = cell.ssb_cfg.ssb_freq_hz; - cell.ssb_absolute_freq_point = band_helper.freq_to_nr_arfcn(cell.ssb_cfg.ssb_freq_hz); + cell); + cell.phy_cell.carrier.ssb_center_freq_hz = cell.ssb_freq_hz; + cell.ssb_absolute_freq_point = band_helper.freq_to_nr_arfcn(cell.ssb_freq_hz); // Derive remaining config params if (is_sa) { @@ -337,7 +325,6 @@ int set_derived_nr_rrc_params(rrc_nr_cfg_t& rrc_cfg) int check_nr_cell_cfg_valid(const rrc_cell_cfg_nr_t& cell, bool is_sa) { // verify SSB params are consistent - ERROR_IF_NOT(cell.ssb_cfg.center_freq_hz == cell.phy_cell.dl_freq_hz, "Invalid SSB param generation"); HANDLE_ERROR(check_nr_phy_cell_cfg_valid(cell.phy_cell)); if (is_sa) { From a9591f1d4551a701911729526b6d8723603eed7b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 19 Jan 2022 18:33:55 +0100 Subject: [PATCH 05/41] Avoid poping queue if empty --- lib/include/srsran/common/tti_sempahore.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/common/tti_sempahore.h b/lib/include/srsran/common/tti_sempahore.h index 3815349f2..887658d44 100644 --- a/lib/include/srsran/common/tti_sempahore.h +++ b/lib/include/srsran/common/tti_sempahore.h @@ -75,8 +75,10 @@ public: { std::unique_lock lock(mutex); - // Pop first element - fifo.pop_front(); + // If the FIFO is not empty pop first element + if (not fifo.empty()) { + fifo.pop_front(); + } // Notify release cvar.notify_all(); From 57b50edbe277001820d0b78b897ae716d9f1b6a9 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 19 Jan 2022 18:34:58 +0100 Subject: [PATCH 06/41] Fix initial buffer data and removed unimplemented method --- srsue/hdr/phy/nr/cell_search.h | 2 -- srsue/src/phy/sync_sa.cc | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/srsue/hdr/phy/nr/cell_search.h b/srsue/hdr/phy/nr/cell_search.h index 7333cd7a9..ec983ac14 100644 --- a/srsue/hdr/phy/nr/cell_search.h +++ b/srsue/hdr/phy/nr/cell_search.h @@ -49,8 +49,6 @@ public: bool start(const cfg_t& cfg); ret_t run_slot(const cf_t* buffer, uint32_t slot_sz); - void reset(); - private: srslog::basic_logger& logger; srsran_ssb_t ssb = {}; diff --git a/srsue/src/phy/sync_sa.cc b/srsue/src/phy/sync_sa.cc index ae658db65..23460d3d0 100644 --- a/srsue/src/phy/sync_sa.cc +++ b/srsue/src/phy/sync_sa.cc @@ -215,6 +215,11 @@ void sync_sa::run_state_idle() void sync_sa::run_state_cell_search() { + // Initialise buffer + if (cell_search_nof_trials == 0) { + srsran_vec_cf_zero(rx_buffer, slot_sz); + } + // Receive samples srsran::rf_buffer_t rf_buffer = {}; rf_buffer.set_nof_samples(slot_sz); From f3fa0d6d467752d127b56a924b2d45aa7a861bbd Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 21 Jan 2022 11:40:52 +0100 Subject: [PATCH 07/41] ue,rrc_nr: add RRC Reconfig Complete sender --- srsue/hdr/stack/rrc_nr/rrc_nr.h | 1 + srsue/src/stack/rrc_nr/rrc_nr.cc | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/srsue/hdr/stack/rrc_nr/rrc_nr.h b/srsue/hdr/stack/rrc_nr/rrc_nr.h index 59c21a4d6..fc9b3c6cc 100644 --- a/srsue/hdr/stack/rrc_nr/rrc_nr.h +++ b/srsue/hdr/stack/rrc_nr/rrc_nr.h @@ -137,6 +137,7 @@ private: // senders void send_setup_request(srsran::nr_establishment_cause_t cause); void send_con_setup_complete(srsran::unique_byte_buffer_t nas_msg); + void send_rrc_reconfig_complete(); void send_ul_info_transfer(srsran::unique_byte_buffer_t nas_msg); void send_ul_ccch_msg(const asn1::rrc_nr::ul_ccch_msg_s& msg); void send_ul_dcch_msg(uint32_t lcid, const asn1::rrc_nr::ul_dcch_msg_s& msg); diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index 33767f5dd..0b14f61a5 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -683,6 +683,16 @@ void rrc_nr::send_con_setup_complete(srsran::unique_byte_buffer_t nas_msg) send_ul_dcch_msg(srb_to_lcid(nr_srb::srb1), ul_dcch_msg); } +void rrc_nr::send_rrc_reconfig_complete() +{ + logger.debug("Preparing RRC Connection Reconfig Complete"); + + asn1::rrc_nr::ul_dcch_msg_s ul_dcch_msg; + auto& rrc_reconfig_complete = ul_dcch_msg.msg.set_c1().set_rrc_recfg_complete().crit_exts.set_rrc_recfg_complete(); + + send_ul_dcch_msg(srb_to_lcid(nr_srb::srb1), ul_dcch_msg); +} + // EUTRA-RRC interface int rrc_nr::get_eutra_nr_capabilities(srsran::byte_buffer_t* eutra_nr_caps_pdu) { From b5a39f9d9f05df9f420735fd67eb6743ad25ad1f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 21 Jan 2022 11:41:33 +0100 Subject: [PATCH 08/41] ue,rrc_nr_proc: if bug connection_setup_proc that cause procedure to fail --- srsue/src/stack/rrc_nr/rrc_nr_procedures.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc index 020e07be0..a17a302d4 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc @@ -308,7 +308,7 @@ srsran::proc_outcome_t rrc_nr::connection_setup_proc::init(const asn1::rrc_nr::r { Info("Starting..."); - if (dedicated_info_nas_) { + if (dedicated_info_nas_ == nullptr) { logger.error("Connection Setup Failed, no dedicatedInfoNAS available"); return proc_outcome_t::error; } From 9c9db176d53e5a2405c289290ce926683f190ce0 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 21 Jan 2022 11:42:10 +0100 Subject: [PATCH 09/41] ue: set NAS-5G args in ue module using NAS-LTE arguments --- srsue/src/stack/ue_stack_lte.cc | 2 -- srsue/src/ue.cc | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 4680f9f0b..9a0414e7e 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -228,8 +228,6 @@ int ue_stack_lte::init(const stack_args_t& args_) args.rrc_nr); rrc.init(phy, &mac, &rlc, &pdcp, &nas, usim.get(), gw, &rrc_nr, args.rrc); - args.nas_5g.ia5g = "0,1,2,3"; - args.nas_5g.ea5g = "0,1,2,3"; nas_5g.init(usim.get(), &rrc_nr, gw, args.nas_5g); running = true; diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index ec7726fa7..765f964f6 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -276,6 +276,11 @@ int ue::parse_args(const all_args_t& args_) return SRSRAN_ERROR; } + // Update NAS-5G args + args.stack.nas_5g.ia5g = args.stack.nas.eia; + args.stack.nas_5g.ea5g = args.stack.nas.eea; + args.stack.nas_5g.pdu_session_cfgs.push_back({args.stack.nas.apn_name}); + return SRSRAN_SUCCESS; } From 4f8991e41af4eaa3e998b601f6d4fd6bf17764e2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 21 Jan 2022 11:46:55 +0100 Subject: [PATCH 10/41] ue,rrc_nr: temporarily add hard-coded SIB1 message for cell select this will be remove shortly when SI reception is implemented but its required right now to have the PLMN read correctly and to avoid changes in the meas_cell_list class, etc. that require valid values. --- srsue/src/stack/rrc/rrc_cell.cc | 6 ++++++ srsue/src/stack/rrc_nr/rrc_nr.cc | 5 +++++ srsue/src/stack/rrc_nr/rrc_nr_procedures.cc | 11 +++++++++++ 3 files changed, 22 insertions(+) diff --git a/srsue/src/stack/rrc/rrc_cell.cc b/srsue/src/stack/rrc/rrc_cell.cc index e12e52410..cdd0b6693 100644 --- a/srsue/src/stack/rrc/rrc_cell.cc +++ b/srsue/src/stack/rrc/rrc_cell.cc @@ -71,6 +71,12 @@ void meas_cell_eutra::set_sib13(const asn1::rrc::sib_type13_r9_s& sib13_) has_valid_sib13 = true; } +void meas_cell_nr::set_sib1(const asn1::rrc_nr::sib1_s& sib1_) +{ + sib1 = sib1_; + has_valid_sib1 = true; +} + bool meas_cell::is_sib_scheduled(uint32_t sib_index) const { return sib_info_map.find(sib_index) != sib_info_map.end(); diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index 0b14f61a5..951f2d0cd 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -340,6 +340,11 @@ void rrc_nr::handle_sib1(const sib1_s& sib1) { logger.info("SIB1 received, CellID=%d", meas_cells.serving_cell().get_cell_id() & 0xfff); + meas_cells.serving_cell().set_sib1(sib1); + + // TODO: config basic config and remove early exit + return; + // clang-format off // unhandled fields: // - cellSelectionInfo diff --git a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc index a17a302d4..63a8c2fa8 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc @@ -427,6 +427,17 @@ rrc_nr::cell_selection_proc::handle_cell_search_result(const rrc_interface_phy_n // until cell selection is done, update PHY config to take the last found PCI rrc_handle.phy_cfg.carrier.pci = result.pci; + // Until SI acquisition is implemented, provide hard-coded SIB for now + uint8_t msg[] = {0x74, 0x81, 0x01, 0x70, 0x10, 0x40, 0x04, 0x02, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x33, 0x60, 0x38, + 0x05, 0x01, 0x00, 0x40, 0x1a, 0x00, 0x00, 0x06, 0x6c, 0x6d, 0x92, 0x21, 0xf3, 0x70, 0x40, 0x20, + 0x00, 0x00, 0x80, 0x80, 0x00, 0x41, 0x06, 0x80, 0xa0, 0x90, 0x9c, 0x20, 0x08, 0x55, 0x19, 0x40, + 0x00, 0x00, 0x33, 0xa1, 0xc6, 0xd9, 0x22, 0x40, 0x00, 0x00, 0x20, 0xb8, 0x94, 0x63, 0xc0, 0x09, + 0x28, 0x44, 0x1b, 0x7e, 0xad, 0x8e, 0x1d, 0x00, 0x9e, 0x2d, 0xa3, 0x0a}; + srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + memcpy(pdu->msg, msg, sizeof(msg)); + pdu->N_bytes = sizeof(msg); + rrc_handle.write_pdu_bcch_dlsch(std::move(pdu)); + if (not rrc_handle.phy->start_cell_select(cs_args)) { Error("Could not set start cell search."); return proc_outcome_t::error; From d035a57ed595412f30f9ec35b7ae9b58983488ee Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 21 Jan 2022 11:49:18 +0100 Subject: [PATCH 11/41] ue,rrc_nr: various smaller refactors to allow SA attach --- srsue/src/stack/rrc_nr/rrc_nr.cc | 38 ++++++++++++++------- srsue/src/stack/rrc_nr/rrc_nr_procedures.cc | 36 ++++++++++--------- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index 951f2d0cd..ad720f727 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -62,9 +62,15 @@ int rrc_nr::init(phy_interface_rrc_nr* phy_, stack = stack_; args = args_; - plmn_is_selected = true; // short-cut SA test - + // allocate RRC timers t300 = task_sched.get_unique_timer(); + t301 = task_sched.get_unique_timer(); + t302 = task_sched.get_unique_timer(); + t304 = task_sched.get_unique_timer(); + t310 = task_sched.get_unique_timer(); + t311 = task_sched.get_unique_timer(); + + plmn_is_selected = true; // short-cut SA test running = true; sim_measurement_timer = task_sched.get_unique_timer(); @@ -246,7 +252,7 @@ void rrc_nr::decode_dl_ccch(unique_byte_buffer_t pdu) case dl_ccch_msg_type_c::c1_c_::types::rrc_reject: { // 5.3.15 const auto& reject = c1->rrc_reject(); - srsran::console("Received RRC Reject"); + srsran::console("Received RRC Reject\n"); t300.stop(); @@ -266,7 +272,6 @@ void rrc_nr::decode_dl_ccch(unique_byte_buffer_t pdu) task_sched.defer_task([this, rrc_setup_copy]() { handle_rrc_setup(rrc_setup_copy); }); break; } - default: logger.error("The provided DL-CCCH message type is not recognized"); break; @@ -607,7 +612,7 @@ void rrc_nr::send_setup_request(srsran::nr_establishment_cause_t cause) for (uint i = 0; i < 5; i++) { // fill random ID bytewise, 40 bits = 5 bytes random_id |= ((uint64_t)rand() & 0xFF) << i * 8; } - rrc_setup_req->ue_id.random_value().from_number(random_id); + rrc_setup_req->ue_id.random_value().from_number(random_id, rrc_setup_req->ue_id.random_value().length()); rrc_setup_req->establishment_cause = (establishment_cause_opts::options)cause; send_ul_ccch_msg(ul_ccch_msg); @@ -1909,12 +1914,24 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) return false; } - if (!(drb_cfg.cn_assoc.type() == drb_to_add_mod_s::cn_assoc_c_::types_opts::eps_bearer_id)) { - logger.error("CN association type not supported %s ", drb_cfg.cn_assoc.type().to_string()); + if (drb_cfg.cn_assoc.type() == drb_to_add_mod_s::cn_assoc_c_::types_opts::eps_bearer_id) { + // register EPS bearer over NR PDCP + uint32_t eps_bearer_id = drb_cfg.cn_assoc.eps_bearer_id(); + drb_eps_bearer_id[drb_cfg.drb_id] = eps_bearer_id; + stack->add_eps_bearer(eps_bearer_id, srsran::srsran_rat_t::nr, lcid); + } else if (drb_cfg.cn_assoc.type() == drb_to_add_mod_s::cn_assoc_c_::types_opts::sdap_cfg) { + const auto& sdap_cfg = drb_cfg.cn_assoc.sdap_cfg(); + if (sdap_cfg.sdap_hdr_dl == asn1::rrc_nr::sdap_cfg_s::sdap_hdr_dl_opts::present || + sdap_cfg.sdap_hdr_ul == asn1::rrc_nr::sdap_cfg_s::sdap_hdr_ul_opts::present) { + logger.error("SDAP currently not supported."); + return false; + } + // TODO: configure SDAP accordingly + uint32_t pdu_session_id = drb_cfg.cn_assoc.sdap_cfg().pdu_session; + } else { + logger.error("CN association type not supported %s", drb_cfg.cn_assoc.type().to_string()); return false; } - uint32_t eps_bearer_id = drb_cfg.cn_assoc.eps_bearer_id(); - drb_eps_bearer_id[drb_cfg.drb_id] = eps_bearer_id; if (drb_cfg.pdcp_cfg.drb.pdcp_sn_size_dl_present && drb_cfg.pdcp_cfg.drb.pdcp_sn_size_ul_present && (drb_cfg.pdcp_cfg.drb.pdcp_sn_size_ul.to_number() != drb_cfg.pdcp_cfg.drb.pdcp_sn_size_dl.to_number())) { @@ -1925,9 +1942,6 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) srsran::pdcp_config_t pdcp_cfg = make_drb_pdcp_config_t(drb_cfg.drb_id, true, drb_cfg.pdcp_cfg); pdcp->add_bearer(lcid, pdcp_cfg); - // register EPS bearer over NR PDCP - stack->add_eps_bearer(eps_bearer_id, srsran::srsran_rat_t::nr, lcid); - return true; } diff --git a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc index 63a8c2fa8..dea59e9f7 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr_procedures.cc @@ -91,23 +91,6 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator } } - if (rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list.size() > 0) { - srsran::unique_byte_buffer_t nas_sdu; - for (uint32_t i = 0; i < rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list.size(); ++i) { - nas_sdu = srsran::make_byte_buffer(); - if (nas_sdu != nullptr) { - memcpy(nas_sdu->msg, - rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list[i].data(), - rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list[i].size()); - nas_sdu->N_bytes = rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list[i].size(); - rrc_handle.write_sdu(std::move(nas_sdu)); - } else { - rrc_handle.logger.error("Couldn't allocate SDU in %s.", __FUNCTION__); - return proc_outcome_t::error; - } - } - } - if (rrc_nr_reconf.crit_exts.rrc_recfg().radio_bearer_cfg_present) { Info("Applying Radio Bearer Cfg."); if (!rrc_handle.apply_radio_bearer_cfg(rrc_nr_reconf.crit_exts.rrc_recfg().radio_bearer_cfg)) { @@ -115,6 +98,25 @@ proc_outcome_t rrc_nr::connection_reconf_no_ho_proc::init(const reconf_initiator } } + rrc_handle.send_rrc_reconfig_complete(); + + // Handle NAS messages + if (rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list.size() > 0) { + for (uint32_t i = 0; i < rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list.size(); ++i) { + srsran::unique_byte_buffer_t nas_pdu = srsran::make_byte_buffer(); + if (nas_pdu != nullptr) { + memcpy(nas_pdu->msg, + rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list[i].data(), + rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list[i].size()); + nas_pdu->N_bytes = rrc_nr_reconf.crit_exts.rrc_recfg().non_crit_ext.ded_nas_msg_list[i].size(); + rrc_handle.nas->write_pdu(std::move(nas_pdu)); + } else { + rrc_handle.logger.error("Couldn't allocate SDU in %s.", __FUNCTION__); + return proc_outcome_t::error; + } + } + } + return proc_outcome_t::success; } From 366dfca7ffc4dd2100521cd021ffd549bb6f294f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sun, 23 Jan 2022 11:27:55 +0100 Subject: [PATCH 12/41] gnb,rrc: refactor AS security updates refactor security updater to extra function and make sure the config is applied to all active RBs, also DRBs --- srsgnb/hdr/stack/rrc/rrc_nr_ue.h | 3 + srsgnb/src/stack/rrc/rrc_nr_ue.cc | 83 ++++++++++++++++-------- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 1 + 3 files changed, 59 insertions(+), 28 deletions(-) diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h index dabfead70..4240ed82a 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h @@ -108,6 +108,9 @@ private: /// Update MAC based on ASN1 message int update_mac(const asn1::rrc_nr::cell_group_cfg_s& cell_group_config, bool is_config_complete); + /// Update AS security config on active RB + int update_as_security(uint32_t lcid, bool enable_integrity, bool enable_ciphering); + int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig); int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config); diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index ea8ad540b..8c411f15f 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1108,20 +1108,8 @@ void rrc_nr::ue::handle_rrc_setup_complete(const asn1::rrc_nr::rrc_setup_complet /// TS 38.331, SecurityModeCommand void rrc_nr::ue::send_security_mode_command(srsran::unique_byte_buffer_t nas_pdu) { - // FIXME: Currently we are using the PDCP-LTE, so we need to convert from nr_as_security_cfg to as_security_config. - // When we start using PDCP-NR we can avoid this step. - srsran::nr_as_security_config_t tmp_cnfg = sec_ctx.get_as_sec_cfg(); - srsran::as_security_config_t pdcp_cnfg = {}; - pdcp_cnfg.k_rrc_int = tmp_cnfg.k_nr_rrc_int; - pdcp_cnfg.k_rrc_enc = tmp_cnfg.k_nr_rrc_enc; - pdcp_cnfg.k_up_int = tmp_cnfg.k_nr_up_int; - pdcp_cnfg.k_up_enc = tmp_cnfg.k_nr_up_enc; - pdcp_cnfg.integ_algo = (srsran::INTEGRITY_ALGORITHM_ID_ENUM)tmp_cnfg.integ_algo; - pdcp_cnfg.cipher_algo = (srsran::CIPHERING_ALGORITHM_ID_ENUM)tmp_cnfg.cipher_algo; - - // Setup SRB1 security/integrity. Encryption is set on completion - parent->pdcp->config_security(rnti, srb_to_lcid(srsran::nr_srb::srb1), pdcp_cnfg); - parent->pdcp->enable_integrity(rnti, srb_to_lcid(srsran::nr_srb::srb1)); + // apply selected security config and enable integrity on SRB1 before generating security mode command + update_as_security(srb_to_lcid(srsran::nr_srb::srb1), true, false); if (nas_pdu != nullptr) { nas_pdu_queue.push_back(std::move(nas_pdu)); @@ -1139,11 +1127,58 @@ void rrc_nr::ue::send_security_mode_command(srsran::unique_byte_buffer_t nas_pdu } } +/** + * @brief Internal helper to update the security configuration of a PDCP bearer + * + * If no valid AS security config is present (yet) the method doesn't modify the + * PDCP config and returns SRSRAN_ERROR. In some cases, however, + * for example during RRC Setup, this is in fact the expected behaviour as + * AS security isn't established yet. + * + * @param lcid Logical channel ID of the bearer + * @param enable_integrity Whether to enable integrity protection for the bearer + * @param enable_ciphering Whether to enable ciphering for the bearer + * @return int SRSRAN_SUCCESS if a valid AS security config was found and the security was configured + */ +int rrc_nr::ue::update_as_security(uint32_t lcid, bool enable_integrity = true, bool enable_ciphering = true) +{ + if (not sec_ctx.is_as_sec_cfg_valid()) { + parent->logger.error("Invalid AS security configuration. Skipping configuration for lcid=%d", lcid); + return SRSRAN_ERROR; + } + + // FIXME: Currently we are using the PDCP-LTE, so we need to convert from nr_as_security_cfg to as_security_config. + // When we start using PDCP-NR we can avoid this step. + srsran::nr_as_security_config_t tmp_cnfg = sec_ctx.get_as_sec_cfg(); + srsran::as_security_config_t pdcp_cnfg = {}; + pdcp_cnfg.k_rrc_int = tmp_cnfg.k_nr_rrc_int; + pdcp_cnfg.k_rrc_enc = tmp_cnfg.k_nr_rrc_enc; + pdcp_cnfg.k_up_int = tmp_cnfg.k_nr_up_int; + pdcp_cnfg.k_up_enc = tmp_cnfg.k_nr_up_enc; + pdcp_cnfg.integ_algo = (srsran::INTEGRITY_ALGORITHM_ID_ENUM)tmp_cnfg.integ_algo; + pdcp_cnfg.cipher_algo = (srsran::CIPHERING_ALGORITHM_ID_ENUM)tmp_cnfg.cipher_algo; + + // configure algorithm and keys + parent->pdcp->config_security(rnti, lcid, pdcp_cnfg); + + if (enable_integrity) { + parent->pdcp->enable_integrity(rnti, lcid); + } + + if (enable_ciphering) { + parent->pdcp->enable_encryption(rnti, lcid); + } + + return SRSRAN_SUCCESS; +} + /// TS 38.331, SecurityModeComplete void rrc_nr::ue::handle_security_mode_complete(const asn1::rrc_nr::security_mode_complete_s& msg) { parent->logger.info("SecurityModeComplete transaction ID: %d", msg.rrc_transaction_id); - parent->pdcp->enable_encryption(rnti, srb_to_lcid(srsran::nr_srb::srb1)); + + // finally, also enable ciphering on SRB1 + update_as_security(srb_to_lcid(srsran::nr_srb::srb1), false, true); send_rrc_reconfiguration(); // Note: Skip UE capabilities @@ -1357,20 +1392,8 @@ int rrc_nr::ue::update_pdcp_bearers(const asn1::rrc_nr::radio_bearer_cfg_s& radi } parent->pdcp->add_bearer(rnti, rlc_bearer->lc_ch_id, pdcp_cnfg); - // enable security config if (sec_ctx.is_as_sec_cfg_valid()) { - srsran::nr_as_security_config_t tmp_cnfg = sec_ctx.get_as_sec_cfg(); - srsran::as_security_config_t pdcp_cnfg = {}; - pdcp_cnfg.k_rrc_int = tmp_cnfg.k_nr_rrc_int; - pdcp_cnfg.k_rrc_enc = tmp_cnfg.k_nr_rrc_enc; - pdcp_cnfg.k_up_int = tmp_cnfg.k_nr_up_int; - pdcp_cnfg.k_up_enc = tmp_cnfg.k_nr_up_enc; - pdcp_cnfg.integ_algo = (srsran::INTEGRITY_ALGORITHM_ID_ENUM)tmp_cnfg.integ_algo; - pdcp_cnfg.cipher_algo = (srsran::CIPHERING_ALGORITHM_ID_ENUM)tmp_cnfg.cipher_algo; - - // Setup SRB1 security/integrity. Encryption is set on completion - parent->pdcp->config_security(rnti, srb_to_lcid(srsran::nr_srb::srb1), pdcp_cnfg); - parent->pdcp->enable_integrity(rnti, srb_to_lcid(srsran::nr_srb::srb1)); + update_as_security(rlc_bearer->lc_ch_id); } } @@ -1390,6 +1413,10 @@ int rrc_nr::ue::update_pdcp_bearers(const asn1::rrc_nr::radio_bearer_cfg_s& radi return SRSRAN_ERROR; } parent->pdcp->add_bearer(rnti, rlc_bearer->lc_ch_id, pdcp_cnfg); + + if (sec_ctx.is_as_sec_cfg_valid()) { + update_as_security(rlc_bearer->lc_ch_id); + } } return SRSRAN_SUCCESS; diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index d7a29392c..88b61800e 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -170,6 +170,7 @@ void test_rrc_sa_connection() SRSRAN_SUCCESS); TESTASSERT_SUCCESS(rrc_obj.add_user(0x4601, 0)); + TESTASSERT_SUCCESS(rrc_obj.ue_set_security_cfg_key(0x4601, {})); test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, mac_obj, ngap_obj, 0x4601); test_rrc_nr_info_transfer(task_sched, rrc_obj, pdcp_obj, ngap_obj, 0x4601); From 44a00feccbe5ada3b02008253497e2039a3b5800 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 19 Jan 2022 18:22:32 +0100 Subject: [PATCH 13/41] pdcp_entity_base: fix log typo --- lib/include/srsran/upper/pdcp_entity_base.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/include/srsran/upper/pdcp_entity_base.h b/lib/include/srsran/upper/pdcp_entity_base.h index ab3513fe7..e70be88eb 100644 --- a/lib/include/srsran/upper/pdcp_entity_base.h +++ b/lib/include/srsran/upper/pdcp_entity_base.h @@ -89,7 +89,7 @@ public: } else { encryption_direction = direction; } - logger.debug("LCID=%d encryption=%s", lcid, srsran_direction_text[integrity_direction]); + logger.debug("LCID=%d, encryption=%s", lcid, srsran_direction_text[integrity_direction]); } void enable_security_timed(srsran_direction_t direction, uint32_t sn) From a8eaf1cdd8b28827b00ae3db0d71ed5e4734cfee Mon Sep 17 00:00:00 2001 From: Bedran Karakoc Date: Thu, 20 Jan 2022 17:40:13 +0100 Subject: [PATCH 14/41] ue,nas_5g: Add get_k_amf() helper function and security context flag --- lib/include/srsran/interfaces/ue_nas_interfaces.h | 1 + srsue/hdr/stack/upper/nas_5g.h | 5 +++-- srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc | 1 + srsue/src/stack/upper/nas_5g.cc | 15 +++++++++++++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_nas_interfaces.h b/lib/include/srsran/interfaces/ue_nas_interfaces.h index 386270aa2..7cb81b666 100644 --- a/lib/include/srsran/interfaces/ue_nas_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nas_interfaces.h @@ -59,6 +59,7 @@ class nas_5g_interface_rrc_nr { public: virtual int write_pdu(srsran::unique_byte_buffer_t pdu) = 0; + virtual int get_k_amf(srsran::as_key_t& k_amf) = 0; }; class nas_5g_interface_procedures diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index c0bf9e5fa..f317ca9ae 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -58,6 +58,7 @@ public: // Stack+RRC interface bool is_registered(); + int get_k_amf(srsran::as_key_t& k_amf); int write_pdu(srsran::unique_byte_buffer_t pdu); @@ -79,8 +80,8 @@ private: usim_interface_nas* usim = nullptr; gw_interface_nas* gw = nullptr; - bool running = false; - + bool running = false; + bool has_sec_ctxt = false; bool initial_sec_command = false; srsran::nas_5g::mobile_identity_5gs_t::guti_5g_s guti_5g; diff --git a/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc index 29e03fbab..e4fa5e7a8 100644 --- a/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc @@ -110,6 +110,7 @@ class dummy_eutra : public rrc_eutra_interface_rrc_nr class dummy_nas : public nas_5g_interface_rrc_nr { int write_pdu(srsran::unique_byte_buffer_t pdu) { return SRSRAN_SUCCESS; }; + int get_k_amf(srsran::as_key_t& k_amf) { return SRSRAN_SUCCESS; }; }; class dummy_sim : public usim_interface_rrc_nr diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc index ba2ac08d0..4dc468bd9 100644 --- a/srsue/src/stack/upper/nas_5g.cc +++ b/srsue/src/stack/upper/nas_5g.cc @@ -453,6 +453,7 @@ int nas_5g::send_security_mode_complete(const srsran::nas_5g::security_mode_comm pcap->write_nas(pdu.get()->msg, pdu.get()->N_bytes); } + has_sec_ctxt = true; logger.info("Sending Security Mode Complete"); rrc_nr->write_sdu(std::move(pdu)); ctxt_base.tx_count++; @@ -798,6 +799,7 @@ int nas_5g::handle_registration_accept(registration_accept_t& registration_accep int nas_5g::handle_registration_reject(registration_reject_t& registration_reject) { logger.info("Handling Registration Reject"); + has_sec_ctxt = false; ctxt_base.rx_count++; state.set_deregistered(mm5g_state_t::deregistered_substate_t::plmn_search); @@ -888,6 +890,7 @@ int nas_5g::handle_authentication_request(authentication_request_t& authenticati int nas_5g::handle_authentication_reject(srsran::nas_5g::authentication_reject_t& authentication_reject) { logger.info("Handling Authentication Reject"); + has_sec_ctxt = false; ctxt_base.rx_count++; state.set_deregistered(mm5g_state_t::deregistered_substate_t::plmn_search); return SRSRAN_SUCCESS; @@ -911,6 +914,7 @@ int nas_5g::handle_service_accept(srsran::nas_5g::service_accept_t& service_acce int nas_5g::handle_service_reject(srsran::nas_5g::service_reject_t& service_reject) { logger.info("Handling Service Reject"); + has_sec_ctxt = false; ctxt_base.rx_count++; return SRSRAN_SUCCESS; } @@ -1106,6 +1110,17 @@ void nas_5g::get_metrics(nas_5g_metrics_t& metrics) metrics.state = state.get_state(); } +int nas_5g::get_k_amf(as_key_t& k_amf) +{ + if (not has_sec_ctxt) { + logger.error("K_amf requested before a valid NAS security context was established"); + return SRSRAN_ERROR; + } + + std::copy(std::begin(ctxt_5g.k_amf), std::end(ctxt_5g.k_amf), k_amf.begin()); + return SRSRAN_SUCCESS; +} + /******************************************************************************* * Helpers ******************************************************************************/ From cabdd05cb885e6b79ba383d0e10a55d0e044f123 Mon Sep 17 00:00:00 2001 From: Bedran Karakoc Date: Fri, 21 Jan 2022 04:05:57 +0100 Subject: [PATCH 15/41] gnb,rrc: Fix typo in logging for NR UP integrity key --- srsgnb/src/stack/rrc/rrc_nr_security_context.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsgnb/src/stack/rrc/rrc_nr_security_context.cc b/srsgnb/src/stack/rrc/rrc_nr_security_context.cc index a23329dc4..b84366afd 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_security_context.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_security_context.cc @@ -183,7 +183,7 @@ void nr_security_context::generate_as_keys() logger.info(sec_cfg.k_nr_rrc_enc.data(), 32, "NR RRC Encryption Key (k_nr_rrc_enc)"); logger.info(sec_cfg.k_nr_rrc_int.data(), 32, "NR RRC Integrity Key (k_nr_rrc_int)"); logger.info(sec_cfg.k_nr_up_enc.data(), 32, "NR UP Encryption Key (k_nr_up_enc)"); - logger.info(sec_cfg.k_nr_up_int.data(), 32, "NR UP Encryption Key (k_nr_up_enc)"); + logger.info(sec_cfg.k_nr_up_int.data(), 32, "NR UP Integrity Key (k_nr_up_int)"); } void nr_security_context::regenerate_keys_handover(uint32_t new_pci, uint32_t new_dl_arfcn) From efa13290a95ffb3aa5b6ee606ff1a663fe2bb738 Mon Sep 17 00:00:00 2001 From: Bedran Karakoc Date: Mon, 24 Jan 2022 17:27:37 +0100 Subject: [PATCH 16/41] ue,rrc_nr,nas_5g: Introduce NR AS Key derivation and update context handling in 5G NAS --- lib/include/srsran/common/security.h | 3 ++ .../srsran/interfaces/ue_nas_interfaces.h | 5 ++- .../srsran/interfaces/ue_usim_interfaces.h | 24 ++++++------ lib/src/common/security.cc | 27 +++++++++++++- srsue/hdr/stack/upper/nas_5g.h | 7 +++- srsue/hdr/stack/upper/nas_base.h | 3 +- srsue/hdr/stack/upper/usim_base.h | 3 ++ srsue/src/stack/rrc_nr/rrc_nr.cc | 11 +++--- srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc | 6 ++- srsue/src/stack/upper/nas_5g.cc | 20 ++++++++-- srsue/src/stack/upper/usim_base.cc | 37 +++++++++++++++++++ 11 files changed, 118 insertions(+), 28 deletions(-) diff --git a/lib/include/srsran/common/security.h b/lib/include/srsran/common/security.h index 035501770..f346725c4 100644 --- a/lib/include/srsran/common/security.h +++ b/lib/include/srsran/common/security.h @@ -97,6 +97,7 @@ struct k_enb_context_t { }; struct k_gnb_context_t { + as_key_t k_gnb; as_key_t sk_gnb; }; @@ -180,6 +181,8 @@ uint8_t security_generate_k_amf(const uint8_t* k_seaf, uint8_t security_generate_k_seaf(const uint8_t* k_ausf, const char* serving_network_name, uint8_t* k_seaf); +uint8_t security_generate_k_gnb(const as_key_t& k_amf, const uint32_t nas_count, as_key_t& k_gnb); + uint8_t security_generate_k_enb(const uint8_t* k_asme, const uint32_t nas_count, uint8_t* k_enb); uint8_t security_generate_k_nb_star_common(uint8_t fc, diff --git a/lib/include/srsran/interfaces/ue_nas_interfaces.h b/lib/include/srsran/interfaces/ue_nas_interfaces.h index 7cb81b666..a96f1372a 100644 --- a/lib/include/srsran/interfaces/ue_nas_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nas_interfaces.h @@ -58,8 +58,9 @@ public: class nas_5g_interface_rrc_nr { public: - virtual int write_pdu(srsran::unique_byte_buffer_t pdu) = 0; - virtual int get_k_amf(srsran::as_key_t& k_amf) = 0; + virtual int write_pdu(srsran::unique_byte_buffer_t pdu) = 0; + virtual int get_k_amf(srsran::as_key_t& k_amf) = 0; + virtual uint32_t get_ul_nas_count() = 0; }; class nas_5g_interface_procedures diff --git a/lib/include/srsran/interfaces/ue_usim_interfaces.h b/lib/include/srsran/interfaces/ue_usim_interfaces.h index 5a7fd84bc..7869ab90a 100644 --- a/lib/include/srsran/interfaces/ue_usim_interfaces.h +++ b/lib/include/srsran/interfaces/ue_usim_interfaces.h @@ -24,24 +24,24 @@ enum auth_result_t { AUTH_OK, AUTH_FAILED, AUTH_SYNCH_FAILURE }; class usim_interface_nas { public: - virtual std::string get_imsi_str() = 0; - virtual std::string get_imei_str() = 0; - virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0; - virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0; - virtual bool get_home_plmn_id(srsran::plmn_id_t* home_plmn_id) = 0; + virtual std::string get_imsi_str() = 0; + virtual std::string get_imei_str() = 0; + virtual bool get_imsi_vec(uint8_t* imsi_, uint32_t n) = 0; + virtual bool get_imei_vec(uint8_t* imei_, uint32_t n) = 0; + virtual bool get_home_plmn_id(srsran::plmn_id_t* home_plmn_id) = 0; // Get the home mcc as bytes array - virtual bool get_home_mcc_bytes(uint8_t* mcc_, uint32_t n) = 0; + virtual bool get_home_mcc_bytes(uint8_t* mcc_, uint32_t n) = 0; // Get the home mnc as byte array - virtual bool get_home_mnc_bytes(uint8_t* mnc_, uint32_t n) = 0; + virtual bool get_home_mnc_bytes(uint8_t* mnc_, uint32_t n) = 0; // Get the home msin in bytes array encoded as bcd - virtual bool get_home_msin_bcd(uint8_t* msin_, uint32_t n) = 0; + virtual bool get_home_msin_bcd(uint8_t* msin_, uint32_t n) = 0; virtual auth_result_t generate_authentication_response(uint8_t* rand, uint8_t* autn_enb, uint16_t mcc, uint16_t mnc, uint8_t* res, int* res_len, - uint8_t* k_asme) = 0; + uint8_t* k_asme) = 0; virtual auth_result_t generate_authentication_response_5g(uint8_t* rand, uint8_t* autn_enb, @@ -77,8 +77,10 @@ public: class usim_interface_rrc_nr { public: - virtual bool generate_nr_context(uint16_t sk_counter, srsran::as_security_config_t* sec_cfg) = 0; - virtual bool update_nr_context(srsran::as_security_config_t* sec_cfg) = 0; + virtual void + generate_nr_as_keys(srsran::as_key_t& k_amf, uint32_t count_ul, srsran::as_security_config_t* sec_cfg) = 0; + virtual bool generate_nr_context(uint16_t sk_counter, srsran::as_security_config_t* sec_cfg) = 0; + virtual bool update_nr_context(srsran::as_security_config_t* sec_cfg) = 0; }; } // namespace srsue diff --git a/lib/src/common/security.cc b/lib/src/common/security.cc index 8affa0848..82d7f0088 100644 --- a/lib/src/common/security.cc +++ b/lib/src/common/security.cc @@ -15,7 +15,6 @@ #include "srsran/common/s3g.h" #include "srsran/common/ssl.h" #include "srsran/config.h" - #include #ifdef HAVE_MBEDTLS @@ -195,6 +194,32 @@ uint8_t security_generate_k_amf(const uint8_t* k_seaf, return SRSRAN_SUCCESS; } +uint8_t security_generate_k_gnb(const as_key_t& k_amf, const uint32_t nas_count_, as_key_t& k_gnb) +{ + if (k_amf.empty()) { + log_error("Invalid inputs"); + return SRSRAN_ERROR; + } + + // NAS Count + std::vector nas_count; + nas_count.resize(4); + nas_count[0] = (nas_count_ >> 24) & 0xFF; + nas_count[1] = (nas_count_ >> 16) & 0xFF; + nas_count[2] = (nas_count_ >> 8) & 0xFF; + nas_count[3] = nas_count_ & 0xFF; + + // Access Type Distinguisher 3GPP access = 0x01 (TS 33501 Annex A.9) + std::vector access_type_distinguisher = {1}; + + if (kdf_common(FC_5G_KGNB_KN3IWF_DERIVATION, k_amf, nas_count, access_type_distinguisher, k_gnb.data()) != + SRSRAN_SUCCESS) { + log_error("Failed to run kdf_common"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; +} + uint8_t security_generate_k_enb(const uint8_t* k_asme, const uint32_t nas_count_, uint8_t* k_enb) { if (k_asme == NULL || k_enb == NULL) { diff --git a/srsue/hdr/stack/upper/nas_5g.h b/srsue/hdr/stack/upper/nas_5g.h index f317ca9ae..0c57a64b9 100644 --- a/srsue/hdr/stack/upper/nas_5g.h +++ b/srsue/hdr/stack/upper/nas_5g.h @@ -57,8 +57,9 @@ public: void run_tti(); // Stack+RRC interface - bool is_registered(); - int get_k_amf(srsran::as_key_t& k_amf); + bool is_registered(); + int get_k_amf(srsran::as_key_t& k_amf); + uint32_t get_ul_nas_count(); int write_pdu(srsran::unique_byte_buffer_t pdu); @@ -94,6 +95,8 @@ private: bool ia5g_caps[8] = {}; bool ea5g_caps[8] = {}; + void set_k_gnb_count(uint32_t count); + // TS 23.003 Sec. 6.2.2 IMEISV's last two octets are Software Version Number (SVN) // which identifies the software version number of the mobile equipment const uint8_t ue_svn_oct1 = 0x5; diff --git a/srsue/hdr/stack/upper/nas_base.h b/srsue/hdr/stack/upper/nas_base.h index 5bcc61c03..602be07c4 100644 --- a/srsue/hdr/stack/upper/nas_base.h +++ b/srsue/hdr/stack/upper/nas_base.h @@ -60,6 +60,7 @@ protected: struct nas_5g_sec_ctxt { uint8_t ksi; uint8_t k_amf[32]; + uint32_t k_gnb_count; }; nas_sec_base_ctxt ctxt_base = {}; @@ -70,7 +71,7 @@ protected: // Security void - integrity_generate(uint8_t* key_128, uint32_t count, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac); + integrity_generate(uint8_t* key_128, uint32_t count, uint8_t direction, uint8_t* msg, uint32_t msg_len, uint8_t* mac); bool integrity_check(srsran::byte_buffer_t* pdu); void cipher_encrypt(srsran::byte_buffer_t* pdu); void cipher_decrypt(srsran::byte_buffer_t* pdu); diff --git a/srsue/hdr/stack/upper/usim_base.h b/srsue/hdr/stack/upper/usim_base.h index f9516073f..b2bc23e81 100644 --- a/srsue/hdr/stack/upper/usim_base.h +++ b/srsue/hdr/stack/upper/usim_base.h @@ -97,6 +97,7 @@ public: void restore_keys_from_failed_ho(srsran::as_security_config_t* as_ctx) final; // NR RRC interface + void generate_nr_as_keys(srsran::as_key_t& k_amf, uint32_t count_ul, srsran::as_security_config_t* sec_cfg) final; bool generate_nr_context(uint16_t sk_counter, srsran::as_security_config_t* sec_cfg) final; bool update_nr_context(srsran::as_security_config_t* sec_cfg) final; @@ -140,6 +141,8 @@ protected: uint8_t k_enb_initial[KEY_LEN] = {}; uint8_t auts[AKA_AUTS_LEN] = {}; + srsran::as_key_t k_gnb_initial = {}; + // Current K_eNB context (K_eNB, NH and NCC) srsran::k_enb_context_t k_enb_ctx = {}; srsran::k_gnb_context_t k_gnb_ctx = {}; diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index ad720f727..9b101cbd5 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -2114,12 +2114,11 @@ void rrc_nr::handle_security_mode_command(const asn1::rrc_nr::security_mode_cmd_ // Security helper used by Security Mode Command and Mobility handling routines void rrc_nr::generate_as_keys() { - uint8_t k_asme[32] = {}; - // FIXME: need to add - // nas->get_k_asme(k_asme, 32); - logger.debug(k_asme, 32, "UE K_asme"); - // logger.debug("Generating K_enb with UL NAS COUNT: %d", nas->get_k_enb_count()); - // usim->generate_as_keys(k_asme, nas->get_k_enb_count(), &sec_cfg); + as_key_t k_amf = {}; + nas->get_k_amf(k_amf); + logger.debug(k_amf.data(), 32, "UE K_amf"); + logger.debug("Generating K_gnb with UL NAS COUNT: %d", nas->get_ul_nas_count()); + usim->generate_nr_as_keys(k_amf, nas->get_ul_nas_count(), &sec_cfg); logger.info(sec_cfg.k_rrc_enc.data(), 32, "RRC encryption key - k_rrc_enc"); logger.info(sec_cfg.k_rrc_int.data(), 32, "RRC integrity key - k_rrc_int"); logger.info(sec_cfg.k_up_enc.data(), 32, "UP encryption key - k_up_enc"); diff --git a/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc b/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc index e4fa5e7a8..da85d7c05 100644 --- a/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc +++ b/srsue/src/stack/rrc_nr/test/ue_rrc_nr_test.cc @@ -109,12 +109,14 @@ class dummy_eutra : public rrc_eutra_interface_rrc_nr class dummy_nas : public nas_5g_interface_rrc_nr { - int write_pdu(srsran::unique_byte_buffer_t pdu) { return SRSRAN_SUCCESS; }; - int get_k_amf(srsran::as_key_t& k_amf) { return SRSRAN_SUCCESS; }; + int write_pdu(srsran::unique_byte_buffer_t pdu) { return SRSRAN_SUCCESS; }; + int get_k_amf(srsran::as_key_t& k_amf) { return SRSRAN_SUCCESS; }; + uint32_t get_ul_nas_count() { return SRSRAN_SUCCESS; }; }; class dummy_sim : public usim_interface_rrc_nr { + void generate_nr_as_keys(srsran::as_key_t& k_amf, uint32_t count_ul, srsran::as_security_config_t* sec_cfg){}; bool generate_nr_context(uint16_t sk_counter, srsran::as_security_config_t* sec_cfg) { return true; } bool update_nr_context(srsran::as_security_config_t* sec_cfg) { return true; } }; diff --git a/srsue/src/stack/upper/nas_5g.cc b/srsue/src/stack/upper/nas_5g.cc index 4dc468bd9..9478bfac5 100644 --- a/srsue/src/stack/upper/nas_5g.cc +++ b/srsue/src/stack/upper/nas_5g.cc @@ -293,6 +293,11 @@ int nas_5g::send_registration_request() } } + if (has_sec_ctxt) { + set_k_gnb_count(ctxt_base.tx_count); + ctxt_base.tx_count++; + } + state.set_registered_initiated(); return SRSRAN_SUCCESS; @@ -847,6 +852,7 @@ int nas_5g::handle_authentication_request(authentication_request_t& authenticati return SRSRAN_ERROR; } + initial_sec_command = true; uint8_t res_star[16]; logger.info(authentication_request.authentication_parameter_rand.rand.data(), @@ -936,10 +942,8 @@ int nas_5g::handle_security_mode_command(security_mode_command_t& security_m return SRSRAN_ERROR; } - initial_sec_command = false; // TODO - if (initial_sec_command) { - ctxt_base.rx_count = 0; + set_k_gnb_count(0); ctxt_base.tx_count = 0; initial_sec_command = false; } @@ -1121,6 +1125,16 @@ int nas_5g::get_k_amf(as_key_t& k_amf) return SRSRAN_SUCCESS; } +uint32_t nas_5g::get_ul_nas_count() +{ + return ctxt_5g.k_gnb_count; +} + +void nas_5g::set_k_gnb_count(uint32_t count) +{ + ctxt_5g.k_gnb_count = count; +} + /******************************************************************************* * Helpers ******************************************************************************/ diff --git a/srsue/src/stack/upper/usim_base.cc b/srsue/src/stack/upper/usim_base.cc index 479ed6b3d..6d1260a4a 100644 --- a/srsue/src/stack/upper/usim_base.cc +++ b/srsue/src/stack/upper/usim_base.cc @@ -222,6 +222,7 @@ void usim_base::generate_nas_keys(uint8_t* k_asme, /* * RRC Interface */ + void usim_base::generate_as_keys(uint8_t* k_asme_, uint32_t count_ul, srsran::as_security_config_t* sec_cfg) { if (!initiated) { @@ -367,6 +368,42 @@ bool usim_base::generate_nas_keys_5g(uint8_t* k_amf, * NR RRC Interface */ +void usim_base::generate_nr_as_keys(srsran::as_key_t& k_amf, uint32_t count_ul, srsran::as_security_config_t* sec_cfg) +{ + if (!initiated) { + logger.error("USIM not initiated!"); + return; + } + + logger.info("Generating NR AS Keys. NAS UL COUNT %d", count_ul); + logger.debug(k_amf.data(), 32, "K_amf"); + + // Generate K_gnb + srsran::security_generate_k_gnb(k_amf, count_ul, k_gnb_ctx.k_gnb); + logger.info(k_gnb_ctx.k_gnb.data(), 32, "K_gnb"); + + // Save initial k_gnb + k_gnb_initial = k_gnb_ctx.k_gnb; + + security_generate_k_nr_rrc(k_gnb_ctx.k_gnb.data(), + sec_cfg->cipher_algo, + sec_cfg->integ_algo, + sec_cfg->k_rrc_enc.data(), + sec_cfg->k_rrc_int.data()); + + security_generate_k_nr_up(k_gnb_ctx.k_gnb.data(), + sec_cfg->cipher_algo, + sec_cfg->integ_algo, + sec_cfg->k_up_enc.data(), + sec_cfg->k_up_int.data()); + + logger.info(k_gnb_ctx.k_gnb.data(), 32, "Initial K_gnb"); + logger.info(sec_cfg->k_rrc_int.data(), sec_cfg->k_rrc_int.size(), "NR K_RRC_int"); + logger.info(sec_cfg->k_rrc_enc.data(), sec_cfg->k_rrc_enc.size(), "NR K_RRC_enc"); + logger.info(sec_cfg->k_up_int.data(), sec_cfg->k_up_int.size(), "NR K_UP_int"); + logger.info(sec_cfg->k_up_enc.data(), sec_cfg->k_up_enc.size(), "NR K_UP_enc"); +} + bool usim_base::generate_nr_context(uint16_t sk_counter, srsran::as_security_config_t* sec_cfg) { if (!initiated) { From 70084cf9cc2c73c6959f5ebc204afae116de3e79 Mon Sep 17 00:00:00 2001 From: Bedran Karakoc Date: Mon, 24 Jan 2022 17:30:54 +0100 Subject: [PATCH 17/41] Added unit test for K_gnb derivation --- lib/test/common/test_security_kdf.cc | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/test/common/test_security_kdf.cc b/lib/test/common/test_security_kdf.cc index 06612fd30..b45372728 100644 --- a/lib/test/common/test_security_kdf.cc +++ b/lib/test/common/test_security_kdf.cc @@ -158,6 +158,26 @@ int test_generate_k_nas() return SRSRAN_SUCCESS; } +int test_generate_k_gnb() +{ + auto& logger = srslog::fetch_basic_logger("LOG", false); + + as_key_t k_gnb_o; + + as_key_t k_gnb = {0x49, 0x3a, 0x16, 0xc5, 0x8b, 0x77, 0xb6, 0x27, 0xfa, 0x3f, 0x1a, 0xc6, 0x34, 0x4c, 0x18, 0x30, + 0x39, 0xf0, 0x1b, 0xa0, 0xcb, 0x76, 0x36, 0xbb, 0xcc, 0xc4, 0x36, 0x5b, 0x02, 0x3b, 0xd5, 0x62}; + + as_key_t k_amf = {0xd6, 0x55, 0xf1, 0x61, 0x42, 0x03, 0x5d, 0x4d, 0x72, 0xca, 0x39, 0x58, 0x3d, 0x22, 0x8d, 0x2d, + 0xd2, 0xec, 0x0c, 0xa7, 0x92, 0x9a, 0xd0, 0x07, 0xf5, 0x3b, 0x38, 0x2d, 0x05, 0x54, 0x44, 0x05}; + + uint32_t nas_ul_count = 0; + + TESTASSERT(srsran::security_generate_k_gnb(k_amf, nas_ul_count, k_gnb_o) == SRSRAN_SUCCESS); + TESTASSERT(k_gnb_o == k_gnb); + + return SRSRAN_SUCCESS; +} + int test_generate_k_enb() { auto& logger = srslog::fetch_basic_logger("LOG", false); @@ -433,7 +453,7 @@ int main(int argc, char** argv) TESTASSERT(test_generate_up_keys() == SRSRAN_SUCCESS); TESTASSERT(test_generate_k_enb_star() == SRSRAN_SUCCESS); TESTASSERT(test_generate_k_nh() == SRSRAN_SUCCESS); - + TESTASSERT(test_generate_k_gnb() == SRSRAN_SUCCESS); TESTASSERT(test_generate_res_star() == SRSRAN_SUCCESS); TESTASSERT(test_generate_k_ausf() == SRSRAN_SUCCESS); TESTASSERT(test_generate_k_seaf() == SRSRAN_SUCCESS); From 256bba0fd355d4cc188a8aa8f79a1b507b377ea1 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 24 Jan 2022 19:54:26 +0100 Subject: [PATCH 18/41] Handle NAN in NR PBCH reception and add unit test case --- lib/src/phy/phch/pbch_nr.c | 13 ++++ lib/src/phy/sync/test/ssb_decode_test.c | 97 ++++++++++++++++++++++--- 2 files changed, 101 insertions(+), 9 deletions(-) diff --git a/lib/src/phy/phch/pbch_nr.c b/lib/src/phy/phch/pbch_nr.c index 557704b67..022077b59 100644 --- a/lib/src/phy/phch/pbch_nr.c +++ b/lib/src/phy/phch/pbch_nr.c @@ -628,10 +628,23 @@ int srsran_pbch_nr_decode(srsran_pbch_nr_t* q, return SRSRAN_ERROR; } + // Avoid NAN getting into the demodulator + for (uint32_t i = 0; i < PBCH_NR_M; i++) { + if (isnan(__real__ symbols[i]) || isnan(__imag__ symbols[i])) { + symbols[i] = 0.0f; + } + } + // 7.3.3.2 Modulation int8_t llr[PBCH_NR_E]; srsran_demod_soft_demodulate_b(SRSRAN_MOD_QPSK, symbols, llr, PBCH_NR_M); + // If all LLR are zero, no message could be received + if (srsran_vec_avg_power_bf(llr, PBCH_NR_E) == 0) { + SRSRAN_MEM_ZERO(msg, srsran_pbch_msg_nr_t, 1); + return SRSRAN_SUCCESS; + } + // TS 38.211 7.3.3 Physical broadcast channel // 7.3.3.1 Scrambling pbch_nr_scramble_rx(cfg, cfg->ssb_idx, llr, llr); diff --git a/lib/src/phy/sync/test/ssb_decode_test.c b/lib/src/phy/sync/test/ssb_decode_test.c index c59982551..0ffacaed5 100644 --- a/lib/src/phy/sync/test/ssb_decode_test.c +++ b/lib/src/phy/sync/test/ssb_decode_test.c @@ -20,6 +20,9 @@ #include #include +#define SSB_DECODE_TEST_PCI_STRIDE 53 +#define SSB_DECODE_TEST_SSB_STRIDE 3 + // NR parameters static uint32_t carrier_nof_prb = 52; static srsran_subcarrier_spacing_t carrier_scs = srsran_subcarrier_spacing_15kHz; @@ -119,7 +122,7 @@ static void gen_pbch_msg(srsran_pbch_msg_nr_t* pbch_msg, uint32_t ssb_idx) pbch_msg->crc = true; } -static int test_case_1(srsran_ssb_t* ssb) +static int test_case_true(srsran_ssb_t* ssb) { // For benchmarking purposes uint64_t t_encode_usec = 0; @@ -138,8 +141,8 @@ static int test_case_1(srsran_ssb_t* ssb) // For each PCI... uint64_t count = 0; - for (uint32_t pci = 0; pci < SRSRAN_NOF_NID_NR; pci += 23) { - for (uint32_t ssb_idx = 0; ssb_idx < ssb->Lmax; ssb_idx++, count++) { + for (uint32_t pci = 0; pci < SRSRAN_NOF_NID_NR; pci += SSB_DECODE_TEST_PCI_STRIDE) { + for (uint32_t ssb_idx = 0; ssb_idx < ssb->Lmax; ssb_idx += SSB_DECODE_TEST_SSB_STRIDE, count++) { struct timeval t[3] = {}; // Build PBCH message @@ -149,7 +152,7 @@ static int test_case_1(srsran_ssb_t* ssb) // Print encoded PBCH message char str[512] = {}; srsran_pbch_msg_info(&pbch_msg_tx, str, sizeof(str)); - INFO("test_case_1 - encoded pci=%d %s", pci, str); + INFO("test_case_true - encoded pci=%d %s", pci, str); // Initialise baseband srsran_vec_cf_zero(buffer, hf_len); @@ -175,7 +178,7 @@ static int test_case_1(srsran_ssb_t* ssb) // Print decoded PBCH message srsran_pbch_msg_info(&pbch_msg_rx, str, sizeof(str)); - INFO("test_case_1 - decoded pci=%d %s crc=%s", pci, str, pbch_msg_rx.crc ? "OK" : "KO"); + INFO("test_case_true - decoded pci=%d %s crc=%s", pci, str, pbch_msg_rx.crc ? "OK" : "KO"); // Assert PBCH message CRC TESTASSERT(pbch_msg_rx.crc); @@ -191,7 +194,7 @@ static int test_case_1(srsran_ssb_t* ssb) // Print decoded PBCH message srsran_pbch_msg_info(&res.pbch_msg, str, sizeof(str)); - INFO("test_case_1 - found pci=%d %s crc=%s", res.N_id, str, res.pbch_msg.crc ? "OK" : "KO"); + INFO("test_case_true - found pci=%d %s crc=%s", res.N_id, str, res.pbch_msg.crc ? "OK" : "KO"); // Assert PBCH message CRC TESTASSERT(res.pbch_msg.crc); @@ -200,11 +203,11 @@ static int test_case_1(srsran_ssb_t* ssb) } if (!count) { - ERROR("Error in test case 1: undefined division"); + ERROR("Error in test case true: undefined division"); return SRSRAN_ERROR; } - INFO("test_case_1 - %.1f usec/encode; %.1f usec/decode; %.1f usec/decode;", + INFO("test_case_true - %.1f usec/encode; %.1f usec/decode; %.1f usec/decode;", (double)t_encode_usec / (double)(count), (double)t_decode_usec / (double)(count), (double)t_search_usec / (double)(count)); @@ -212,6 +215,77 @@ static int test_case_1(srsran_ssb_t* ssb) return SRSRAN_SUCCESS; } +static int test_case_false(srsran_ssb_t* ssb) +{ + // For benchmarking purposes + uint64_t t_decode_usec = 0; + uint64_t t_search_usec = 0; + + // SSB configuration + srsran_ssb_cfg_t ssb_cfg = {}; + ssb_cfg.srate_hz = srate_hz; + ssb_cfg.center_freq_hz = carrier_freq_hz; + ssb_cfg.ssb_freq_hz = ssb_freq_hz; + ssb_cfg.scs = ssb_scs; + ssb_cfg.pattern = ssb_pattern; + + TESTASSERT(srsran_ssb_set_cfg(ssb, &ssb_cfg) == SRSRAN_SUCCESS); + + // For each PCI... + uint32_t count = 0; + for (uint32_t pci = 0; pci < SRSRAN_NOF_NID_NR; pci += SSB_DECODE_TEST_PCI_STRIDE, count++) { + struct timeval t[3] = {}; + + // Initialise baseband + srsran_vec_cf_zero(buffer, hf_len); + + // Channel, as it is zero it only adds noise + srsran_channel_awgn_run_c(&awgn, buffer, buffer, hf_len); + + // Decode + gettimeofday(&t[1], NULL); + srsran_pbch_msg_nr_t pbch_msg_rx = {}; + TESTASSERT(srsran_ssb_decode_pbch(ssb, pci, false, 0, buffer, &pbch_msg_rx) == SRSRAN_SUCCESS); + gettimeofday(&t[2], NULL); + get_time_interval(t); + t_decode_usec += t[0].tv_usec + t[0].tv_sec * 1000000UL; + + // Print decoded PBCH message + char str[512] = {}; + srsran_pbch_msg_info(&pbch_msg_rx, str, sizeof(str)); + INFO("test_case_false - decoded pci=%d %s crc=%s", pci, str, pbch_msg_rx.crc ? "OK" : "KO"); + + // Assert PBCH message CRC is not okay + TESTASSERT(!pbch_msg_rx.crc); + + // Search + srsran_ssb_search_res_t res = {}; + gettimeofday(&t[1], NULL); + TESTASSERT(srsran_ssb_search(ssb, buffer, hf_len, &res) == SRSRAN_SUCCESS); + gettimeofday(&t[2], NULL); + get_time_interval(t); + t_search_usec += t[0].tv_usec + t[0].tv_sec * 1000000UL; + + // Print decoded PBCH message + srsran_pbch_msg_info(&res.pbch_msg, str, sizeof(str)); + INFO("test_case_false - false found pci=%d %s crc=%s", res.N_id, str, res.pbch_msg.crc ? "OK" : "KO"); + + // Assert PBCH message CRC + TESTASSERT(!res.pbch_msg.crc); + } + + if (!count) { + ERROR("Error in test case true: undefined division"); + return SRSRAN_ERROR; + } + + INFO("test_case_false - %.1f usec/decode; %.1f usec/decode;", + (double)t_decode_usec / (double)(count), + (double)t_search_usec / (double)(count)); + + return SRSRAN_SUCCESS; +} + int main(int argc, char** argv) { int ret = SRSRAN_ERROR; @@ -248,7 +322,12 @@ int main(int argc, char** argv) goto clean_exit; } - if (test_case_1(&ssb) != SRSRAN_SUCCESS) { + if (test_case_true(&ssb) != SRSRAN_SUCCESS) { + ERROR("test case failed"); + goto clean_exit; + } + + if (test_case_false(&ssb) != SRSRAN_SUCCESS) { ERROR("test case failed"); goto clean_exit; } From 9cda4e058d9b3cdd7fc875324728651edef7850e Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 25 Jan 2022 12:32:56 +0100 Subject: [PATCH 19/41] Disable srsgnb time in advance offset --- srsgnb/src/stack/rrc/cell_asn1_config.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 1dce59a6d..1f2befe77 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -1215,6 +1215,10 @@ int fill_serv_cell_cfg_common_sib(const rrc_cell_cfg_nr_t& cell_cfg, serving_cel cfg.ssb_periodicity_serving_cell.value = serving_cell_cfg_common_sib_s::ssb_periodicity_serving_cell_opts::ms10; + // The time advance offset is not supported by the current PHY + cfg.n_timing_advance_offset_present = true; + cfg.n_timing_advance_offset = serving_cell_cfg_common_sib_s::n_timing_advance_offset_opts::n0; + // TDD UL-DL config if (cell_cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD) { cfg.tdd_ul_dl_cfg_common_present = true; From dfe5cca7fb096911b547a79d08c4bbba5254350b Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Thu, 6 Jan 2022 18:19:23 +0100 Subject: [PATCH 20/41] rrc-nr: adapt csi-meas_config to new source Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/cell_asn1_config.cc | 58 ++++++++++++++++++------ 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 1f2befe77..aaa49f720 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -176,11 +176,8 @@ int fill_csi_report_from_enb_cfg(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_me csi_report.cqi_table = asn1::rrc_nr::csi_report_cfg_s::cqi_table_opts::table2; csi_report.subband_size = asn1::rrc_nr::csi_report_cfg_s::subband_size_opts::value1; - if (cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 9; - } else { - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 7; - } + if (cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 1; } else { csi_meas_cfg.csi_report_cfg_to_add_mod_list.resize(1); @@ -215,6 +212,41 @@ int fill_csi_report_from_enb_cfg(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_me } } + // the code below would be for NSA, even though this function was never called for NSA +#if 0 + csi_meas_cfg.csi_report_cfg_to_add_mod_list_present = true; + csi_meas_cfg.csi_report_cfg_to_add_mod_list.resize(1); + + auto& csi_report = csi_meas_cfg.csi_report_cfg_to_add_mod_list[0]; + csi_report.report_cfg_id = 0; + csi_report.res_for_ch_meas = 0; + csi_report.csi_im_res_for_interference_present = true; + csi_report.csi_im_res_for_interference = 1; + csi_report.report_cfg_type.set_periodic(); + csi_report.report_cfg_type.periodic().report_slot_cfg.set_slots80(); + csi_report.report_cfg_type.periodic().pucch_csi_res_list.resize(1); + csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].ul_bw_part_id = 0; + csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 1; // was 17 in orig PCAP + csi_report.report_quant.set_cri_ri_pmi_cqi(); + // Report freq config (optional) + csi_report.report_freq_cfg_present = true; + csi_report.report_freq_cfg.cqi_format_ind_present = true; + csi_report.report_freq_cfg.cqi_format_ind = csi_report_cfg_s::report_freq_cfg_s_::cqi_format_ind_opts::wideband_cqi; + csi_report.time_restrict_for_ch_meass = csi_report_cfg_s::time_restrict_for_ch_meass_opts::not_cfgured; + csi_report.time_restrict_for_interference_meass = + asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_interference_meass_opts::not_cfgured; + csi_report.group_based_beam_report.set_disabled(); + // Skip CQI table (optional) + csi_report.cqi_table_present = true; + csi_report.cqi_table = asn1::rrc_nr::csi_report_cfg_s::cqi_table_opts::table2; + csi_report.subband_size = asn1::rrc_nr::csi_report_cfg_s::subband_size_opts::value1; + + if (cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5; + } else { + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 7; + } +#endif return SRSRAN_SUCCESS; } @@ -227,11 +259,11 @@ void fill_nzp_csi_rs_from_enb_cfg(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_m auto& nzp_csi_res = csi_meas_cfg.nzp_csi_rs_res_to_add_mod_list; // item 0 nzp_csi_res[0].nzp_csi_rs_res_id = 0; - nzp_csi_res[0].res_map.freq_domain_alloc.set_other(); - nzp_csi_res[0].res_map.freq_domain_alloc.other().from_number(0b100000); - nzp_csi_res[0].res_map.nrof_ports.value = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p2; + nzp_csi_res[0].res_map.freq_domain_alloc.set_row2(); + nzp_csi_res[0].res_map.freq_domain_alloc.row2().from_number(0x800); + nzp_csi_res[0].res_map.nrof_ports.value = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; nzp_csi_res[0].res_map.first_ofdm_symbol_in_time_domain = 4; - nzp_csi_res[0].res_map.cdm_type.value = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::fd_cdm2; + nzp_csi_res[0].res_map.cdm_type.value = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; nzp_csi_res[0].res_map.density.set_one(); nzp_csi_res[0].res_map.freq_band.start_rb = 0; nzp_csi_res[0].res_map.freq_band.nrof_rbs = 52; @@ -249,7 +281,7 @@ void fill_nzp_csi_rs_from_enb_cfg(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_m nzp_csi_res[1] = nzp_csi_res[0]; nzp_csi_res[1].nzp_csi_rs_res_id = 1; nzp_csi_res[1].res_map.freq_domain_alloc.set_row1(); - nzp_csi_res[1].res_map.freq_domain_alloc.row1().from_number(0b0001); + nzp_csi_res[1].res_map.freq_domain_alloc.row1().from_number(0x1); nzp_csi_res[1].res_map.nrof_ports.value = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; nzp_csi_res[1].res_map.cdm_type.value = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; nzp_csi_res[1].res_map.density.set_three(); @@ -428,8 +460,8 @@ void fill_csi_resource_cfg_to_add(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_m csi_meas_cfg.csi_res_cfg_to_add_mod_list[0].res_type.value = csi_res_cfg_s::res_type_opts::periodic; csi_meas_cfg.csi_res_cfg_to_add_mod_list[1].csi_res_cfg_id = 1; - auto& imres = csi_meas_cfg.csi_res_cfg_to_add_mod_list[1].csi_rs_res_set_list.set_csi_im_res_set_list(); - imres.push_back(0); + auto& im_res = csi_meas_cfg.csi_res_cfg_to_add_mod_list[1].csi_rs_res_set_list.set_csi_im_res_set_list(); + im_res.push_back(0); csi_meas_cfg.csi_res_cfg_to_add_mod_list[1].bwp_id = 0; csi_meas_cfg.csi_res_cfg_to_add_mod_list[1].res_type.value = csi_res_cfg_s::res_type_opts::periodic; @@ -1052,7 +1084,7 @@ int fill_master_cell_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1 out.sp_cell_cfg.recfg_with_sync_present = false; // The current CSI config make the PUCCH decoding fail. We temporarily disable it until further investigation - out.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = false; + // out.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = false; return SRSRAN_SUCCESS; } From fa761e7f3bbe6f88b33c829c9ceb193c17de43e7 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 7 Jan 2022 10:15:55 +0100 Subject: [PATCH 21/41] rrc-nr: enable zp_csi in rrc_setup msg Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/cell_asn1_config.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index aaa49f720..7f8c8619a 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -593,7 +593,7 @@ void fill_pdsch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pdsch_cfg out.zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true; out.zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80() = 1; - out.p_zp_csi_rs_res_set_present = false; // TEMP + out.p_zp_csi_rs_res_set_present = true; // TEMP out.p_zp_csi_rs_res_set.set_setup(); out.p_zp_csi_rs_res_set.setup().zp_csi_rs_res_set_id = 0; out.p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.resize(1); From 378e14826e9a7afb1122b168deb6af9eb0a93bd2 Mon Sep 17 00:00:00 2001 From: Francisco Paisana Date: Fri, 7 Jan 2022 16:26:28 +0100 Subject: [PATCH 22/41] rrc,nr: fix conversion of csi meas cfg to phy cfg flat struct --- lib/src/asn1/rrc_nr_utils.cc | 56 ++++++++++++++++++++----------- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 2 ++ 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index a94fa7bfe..50cc836e7 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -571,42 +571,41 @@ bool make_phy_csi_report(const csi_report_cfg_s& csi_report_cfg, } if (srsran_csi_hl_report_cfg.type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) { - srsran_csi_hl_report_cfg.periodic.period = - csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.type().to_number(); - switch (csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.type()) { + const auto& csi_periodic = csi_report_cfg.report_cfg_type.periodic(); + srsran_csi_hl_report_cfg.periodic.period = csi_periodic.report_slot_cfg.type().to_number(); + switch (csi_periodic.report_slot_cfg.type()) { case csi_report_periodicity_and_offset_c::types_opts::slots4: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots4(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots4(); break; case csi_report_periodicity_and_offset_c::types_opts::slots5: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots5(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots5(); break; case csi_report_periodicity_and_offset_c::types_opts::slots8: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots8(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots8(); break; case csi_report_periodicity_and_offset_c::types_opts::slots10: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots10(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots10(); break; case csi_report_periodicity_and_offset_c::types_opts::slots16: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots16(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots16(); break; case csi_report_periodicity_and_offset_c::types_opts::slots20: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots20(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots20(); break; case csi_report_periodicity_and_offset_c::types_opts::slots40: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots40(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots40(); break; case csi_report_periodicity_and_offset_c::types_opts::slots80: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots80(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots80(); break; case csi_report_periodicity_and_offset_c::types_opts::slots160: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots160(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots160(); break; case csi_report_periodicity_and_offset_c::types_opts::slots320: - srsran_csi_hl_report_cfg.periodic.offset = csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.slots320(); + srsran_csi_hl_report_cfg.periodic.offset = csi_periodic.report_slot_cfg.slots320(); break; default: - asn1::log_warning("Invalid option for report_slot_cfg %s", - csi_report_cfg.report_cfg_type.periodic().report_slot_cfg.type().to_string()); + asn1::log_warning("Invalid option for report_slot_cfg %s", csi_periodic.report_slot_cfg.type().to_string()); return false; } } @@ -690,6 +689,7 @@ bool make_phy_csi_report(const csi_report_cfg_s& csi_report_cfg, asn1::log_warning("Invalid option for cqi_table %s", csi_report_cfg.cqi_table.to_string()); return false; } + *in_srsran_csi_hl_report_cfg = srsran_csi_hl_report_cfg; return true; } @@ -1632,10 +1632,28 @@ bool make_csi_cfg_from_serv_cell(const asn1::rrc_nr::serving_cell_cfg_s& serv_ce auto& setup = serv_cell.csi_meas_cfg.setup(); // Configure CSI-Report - for (uint32_t i = 0; i < setup.csi_report_cfg_to_add_mod_list.size(); ++i) { - const auto& csi_rep = setup.csi_report_cfg_to_add_mod_list[i]; - if (not make_phy_csi_report(csi_rep, &csi_hl->reports[i])) { - return false; + if (setup.csi_report_cfg_to_add_mod_list_present) { + for (uint32_t i = 0; i < setup.csi_report_cfg_to_add_mod_list.size(); ++i) { + const auto& csi_rep = setup.csi_report_cfg_to_add_mod_list[i]; + if (not make_phy_csi_report(csi_rep, &csi_hl->reports[i])) { + return false; + } + if (csi_rep.report_cfg_type.type().value == csi_report_cfg_s::report_cfg_type_c_::types_opts::periodic) { + const auto& pucch_setup = serv_cell.ul_cfg.init_ul_bwp.pucch_cfg.setup(); + srsran_pucch_nr_resource_t& resource = csi_hl->reports[i].periodic.resource; + uint32_t pucch_resource_id = csi_rep.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res; + const auto& asn1_resource = pucch_setup.res_to_add_mod_list[pucch_resource_id]; + uint32_t format2_rate = 0; + if (pucch_setup.format2_present and + pucch_setup.format2.type().value == + asn1::rrc_nr::setup_release_c::types_opts::setup and + pucch_setup.format2.setup().max_code_rate_present) { + format2_rate = pucch_setup.format2.setup().max_code_rate.to_number(); + } + if (not make_phy_res_config(asn1_resource, format2_rate, &resource)) { + return false; + } + } } } } diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 8c411f15f..1151e1964 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1481,9 +1481,11 @@ int rrc_nr::ue::update_mac(const cell_group_cfg_s& cell_group_config, bool is_co } } + uecfg.sp_cell_cfg.reset(new sp_cell_cfg_s{cell_group_cfg.sp_cell_cfg}); uecfg.mac_cell_group_cfg.reset(new mac_cell_group_cfg_s{cell_group_cfg.mac_cell_group_cfg}); uecfg.phy_cell_group_cfg.reset(new phys_cell_group_cfg_s{cell_group_cfg.phys_cell_group_cfg}); + srsran::make_csi_cfg_from_serv_cell(cell_group_config.sp_cell_cfg.sp_cell_cfg_ded, &uecfg.phy_cfg.csi); parent->mac->ue_cfg(rnti, uecfg); return SRSRAN_SUCCESS; From 49e01584ac9f1adcfdbfcf4449cb07018435c688 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Mon, 24 Jan 2022 19:49:17 +0100 Subject: [PATCH 23/41] rrc-nr: fix rebase issue Signed-off-by: Carlo Galiotto --- lib/src/asn1/rrc_nr_utils.cc | 37 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 50cc836e7..3ec5905b2 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -1632,27 +1632,24 @@ bool make_csi_cfg_from_serv_cell(const asn1::rrc_nr::serving_cell_cfg_s& serv_ce auto& setup = serv_cell.csi_meas_cfg.setup(); // Configure CSI-Report - if (setup.csi_report_cfg_to_add_mod_list_present) { - for (uint32_t i = 0; i < setup.csi_report_cfg_to_add_mod_list.size(); ++i) { - const auto& csi_rep = setup.csi_report_cfg_to_add_mod_list[i]; - if (not make_phy_csi_report(csi_rep, &csi_hl->reports[i])) { - return false; + for (uint32_t i = 0; i < setup.csi_report_cfg_to_add_mod_list.size(); ++i) { + const auto& csi_rep = setup.csi_report_cfg_to_add_mod_list[i]; + if (not make_phy_csi_report(csi_rep, &csi_hl->reports[i])) { + return false; + } + if (csi_rep.report_cfg_type.type().value == csi_report_cfg_s::report_cfg_type_c_::types_opts::periodic) { + const auto& pucch_setup = serv_cell.ul_cfg.init_ul_bwp.pucch_cfg.setup(); + srsran_pucch_nr_resource_t& resource = csi_hl->reports[i].periodic.resource; + uint32_t pucch_resource_id = csi_rep.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res; + const auto& asn1_resource = pucch_setup.res_to_add_mod_list[pucch_resource_id]; + uint32_t format2_rate = 0; + if (pucch_setup.format2_present and + pucch_setup.format2.type().value == asn1::setup_release_c::types_opts::setup and + pucch_setup.format2.setup().max_code_rate_present) { + format2_rate = pucch_setup.format2.setup().max_code_rate.to_number(); } - if (csi_rep.report_cfg_type.type().value == csi_report_cfg_s::report_cfg_type_c_::types_opts::periodic) { - const auto& pucch_setup = serv_cell.ul_cfg.init_ul_bwp.pucch_cfg.setup(); - srsran_pucch_nr_resource_t& resource = csi_hl->reports[i].periodic.resource; - uint32_t pucch_resource_id = csi_rep.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res; - const auto& asn1_resource = pucch_setup.res_to_add_mod_list[pucch_resource_id]; - uint32_t format2_rate = 0; - if (pucch_setup.format2_present and - pucch_setup.format2.type().value == - asn1::rrc_nr::setup_release_c::types_opts::setup and - pucch_setup.format2.setup().max_code_rate_present) { - format2_rate = pucch_setup.format2.setup().max_code_rate.to_number(); - } - if (not make_phy_res_config(asn1_resource, format2_rate, &resource)) { - return false; - } + if (not make_phy_res_config(asn1_resource, format2_rate, &resource)) { + return false; } } } From 290fdd068edde6587c1c396a2e3f8d9ea91fcd1c Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Wed, 12 Jan 2022 11:27:38 +0100 Subject: [PATCH 24/41] TMP: test CSI config with disabled zp, p_zp Signed-off-by: Carlo Galiotto --- srsgnb/src/stack/rrc/cell_asn1_config.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 7f8c8619a..812764660 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -176,8 +176,11 @@ int fill_csi_report_from_enb_cfg(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_me csi_report.cqi_table = asn1::rrc_nr::csi_report_cfg_s::cqi_table_opts::table2; csi_report.subband_size = asn1::rrc_nr::csi_report_cfg_s::subband_size_opts::value1; - if (cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 1; + if (cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 1; + } else { + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 7; + } } else { csi_meas_cfg.csi_report_cfg_to_add_mod_list.resize(1); @@ -593,7 +596,7 @@ void fill_pdsch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pdsch_cfg out.zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true; out.zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80() = 1; - out.p_zp_csi_rs_res_set_present = true; // TEMP + out.p_zp_csi_rs_res_set_present = false; // TEMP out.p_zp_csi_rs_res_set.set_setup(); out.p_zp_csi_rs_res_set.setup().zp_csi_rs_res_set_id = 0; out.p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.resize(1); From a53e7c9673f9733efe117391525d02fa97a1afe5 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 14 Jan 2022 17:49:42 +0100 Subject: [PATCH 25/41] TMP WIP Signed-off-by: Carlo Galiotto --- lib/src/phy/phch/ra_ul_nr.c | 4 ++++ srsenb/src/phy/nr/slot_worker.cc | 4 ++++ srsgnb/src/stack/rrc/cell_asn1_config.cc | 7 +++++-- srsgnb/src/stack/rrc/rrc_nr.cc | 4 ++++ test/phy/nr_phy_test.cc | 11 +++++++++++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index 92ff87088..443725ab6 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -619,6 +619,10 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } + if (uci_cfg->ack.count > 0 && uci_cfg->nof_csi == 1 && uci_cfg->csi[0].cfg.type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) { + printf("This is point where we fail"); + } + // If a UE does not have dedicated PUCCH resource configuration, provided by PUCCH-ResourceSet in PUCCH-Config, // a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size // transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs. diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 0dba28c1b..8735243b6 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -182,6 +182,10 @@ bool slot_worker::work_ul() for (uint32_t i = 0; i < (uint32_t)pucch.candidates.size(); i++) { pucch_info[i].uci_data.cfg = pucch.candidates[i].uci_cfg; + if (pucch_info[i].uci_data.cfg.nof_csi == 1 && pucch_info[i].uci_data.cfg.ack.count > 0) { + printf("Stop here"); + } + // Decode PUCCH if (srsran_gnb_ul_get_pucch(&gnb_ul, &ul_slot_cfg, diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 812764660..a231b8267 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -641,8 +641,8 @@ void fill_pucch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pucch_cfg uint32_t j = 0, j2 = 0; for (uint32_t i = 0; i < out.res_to_add_mod_list.size(); ++i) { out.res_to_add_mod_list[i].pucch_res_id = i; - out.res_to_add_mod_list[i].intra_slot_freq_hop_present = true; - out.res_to_add_mod_list[i].second_hop_prb_present = true; + out.res_to_add_mod_list[i].intra_slot_freq_hop_present = false; + out.res_to_add_mod_list[i].second_hop_prb_present = false; if (i < 8 or i == 16) { out.res_to_add_mod_list[i].start_prb = 51; out.res_to_add_mod_list[i].second_hop_prb = 0; @@ -675,6 +675,9 @@ void fill_pucch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pucch_cfg out.format2.set_setup(); out.format2.setup().max_code_rate_present = true; out.format2.setup().max_code_rate = pucch_max_code_rate_opts::zero_dot25; + // NOTE: IMPORTANT!! The gNB expects the CSI to be reported along with HARQ-ACK + // If simul_harq_ack_csi_present = false, PUCCH might not be decoded properly when CSI is reported + out.format2.setup().simul_harq_ack_csi_present = true; // SR resources out.sched_request_res_to_add_mod_list.resize(1); diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 676ba17b7..30371d011 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -342,10 +342,14 @@ void rrc_nr::config_mac() cell.ssb_scs = serv_cell.ssb_subcarrier_spacing; } else { cell.bwps[0].pdsch.p_zp_csi_rs_set = {}; + bzero(cell.bwps[0].pdsch.nzp_csi_rs_sets, sizeof(cell.bwps[0].pdsch.nzp_csi_rs_sets)); cell.ssb_positions_in_burst = du_cfg->cell(cc).serv_cell_cfg_common().ssb_positions_in_burst; cell.ssb_periodicity_ms = du_cfg->cell(cc).serv_cell_cfg_common().ssb_periodicity_serving_cell.to_number(); cell.ssb_scs.value = (subcarrier_spacing_e::options)cfg.cell_list[0].phy_cell.carrier.scs; + // bzero(cell.bwps[0].pdsch.nzp_csi_rs_sets, sizeof(cell.bwps[0].pdsch.nzp_csi_rs_sets)); + bool valid_cfg = srsran::make_pdsch_cfg_from_serv_cell(base_sp_cell_cfg.sp_cell_cfg_ded, &cell.bwps[0].pdsch); + srsran_assert(valid_cfg, "Invalid NR cell configuration."); } // Set SIB1 and SI messages diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 2d163128e..bf9247106 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -171,6 +171,17 @@ test_bench::args_t::args_t(int argc, char** argv) // Load default reference configuration phy_cfg = srsran::phy_cfg_nr_default_t(srsran::phy_cfg_nr_default_t::reference_cfg_t(reference_cfg_str)); +#if 0 + // configure nzp + auto& uecfg_set_0 = phy_cfg.pdsch.nzp_csi_rs_sets[0]; + uecfg_set_0.trs_info = true; + uecfg_set_0.count = 1; + + auto& res_0 = uecfg_set_0.data[0]; + res_0.id = 0; + res_0.resource_mapping.row = srsran_csi_rs_resource_mapping_row_2; +#endif + // Calculate the DL signal power from the number of PRBs dl_channel.awgn_signal_power_dBfs = srsran_gnb_dl_get_maximum_signal_power_dBfs(phy_cfg.carrier.nof_prb); From 362abfe3c9ae51a2d64b508349e03bb1148184c3 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Fri, 21 Jan 2022 20:37:06 +0100 Subject: [PATCH 26/41] rrc-nr: add conversion for pucch_cfg Signed-off-by: Carlo Galiotto --- lib/include/srsran/asn1/rrc_nr_utils.h | 2 + lib/src/asn1/rrc_nr_utils.cc | 61 ++++++++++++++++++++++++ lib/src/phy/phch/ra_ul_nr.c | 21 ++++++++ srsenb/src/phy/nr/slot_worker.cc | 4 ++ srsgnb/src/stack/mac/sched_nr_worker.cc | 4 ++ srsgnb/src/stack/rrc/cell_asn1_config.cc | 35 -------------- test/phy/nr_phy_test.cc | 2 +- 7 files changed, 93 insertions(+), 36 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 53ada8e9e..c9ca67aab 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -61,6 +61,7 @@ struct pdcch_cfg_common_s; struct pdcch_cfg_s; struct pdsch_cfg_common_s; struct pucch_cfg_common_s; +struct pucch_cfg_s; struct pusch_cfg_common_s; struct mib_s; @@ -135,6 +136,7 @@ void fill_phy_pdcch_cfg_common(const asn1::rrc_nr::pdcch_cfg_common_s& pdcch_cfg bool fill_phy_pdcch_cfg(const asn1::rrc_nr::pdcch_cfg_s& pdcch_cfg, srsran_pdcch_cfg_nr_t* pdcch); bool fill_phy_pdsch_cfg_common(const asn1::rrc_nr::pdsch_cfg_common_s& pdsch_cfg, srsran_sch_hl_cfg_nr_t* pdsch); void fill_phy_pucch_cfg_common(const asn1::rrc_nr::pucch_cfg_common_s& pucch_cfg, srsran_pucch_nr_common_cfg_t* pucch); +bool fill_phy_pucch_cfg(const asn1::rrc_nr::pucch_cfg_s& pucch_cfg, srsran_pucch_nr_hl_cfg_t* pucch); bool fill_phy_pusch_cfg_common(const asn1::rrc_nr::pusch_cfg_common_s& pusch_cfg, srsran_sch_hl_cfg_nr_t* pusch); void fill_phy_carrier_cfg(const asn1::rrc_nr::serving_cell_cfg_common_sib_s& serv_cell_cfg, srsran_carrier_nr_t* carrier_nr); diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 3ec5905b2..0c7065132 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -1726,6 +1726,67 @@ void fill_phy_pucch_cfg_common(const asn1::rrc_nr::pucch_cfg_common_s& pucch_cfg } } +bool fill_phy_pucch_cfg(const asn1::rrc_nr::pucch_cfg_s& pucch_cfg, srsran_pucch_nr_hl_cfg_t* pucch) +{ + // sanity check to avoid pucch->sets[n] goes out of bound + if (pucch_cfg.res_set_to_add_mod_list.size() > SRSRAN_PUCCH_NR_MAX_NOF_SETS) { + return false; + } + + // iterate over the sets of resourceSetToAddModList + for (size_t n = 0; n < pucch_cfg.res_set_to_add_mod_list.size() and + pucch_cfg.res_set_to_add_mod_list.size() <= SRSRAN_PUCCH_NR_MAX_NOF_SETS; + n++) { + auto& res_set = pucch_cfg.res_set_to_add_mod_list[n]; + pucch->sets[n].nof_resources = res_set.res_list.size(); + if (res_set.max_payload_size_present) { + pucch->sets[n].max_payload_size = res_set.max_payload_size; + } + // NOTE: res_set.pucch_res_set_id does not have a corresponding field in the PHY struct + + // for each set, iterate over the elements (an element is an index). For each of the element or index, find the + // corresponding pucch_res_s object in the pucch_cfg.res_to_add_mod_list + for (size_t res_idx = 0; res_idx < res_set.res_list.size(); res_idx++) { + size_t pucch_resource_id = res_set.res_list[res_idx]; + + // Find the pucch_res_s object corresponding to pucch_resource_id in the pucch_cfg.res_to_add_mod_list + size_t m = 0; + while (m <= pucch_cfg.res_to_add_mod_list.size()) { + if (m == pucch_cfg.res_to_add_mod_list.size()) { + // if we get here, the list pucch_cfg.res_to_add_mod_list does not contain any object corresponding to + // pucch_resource_id + return false; + } + if (pucch_cfg.res_to_add_mod_list[m].pucch_res_id == pucch_resource_id) { + break; // item found, exit the loop + } + m++; + } + + // Below is the object corresponding to pucch_resource_id in the pucch_cfg.res_to_add_mod_list + const auto& asn1_resource = pucch_cfg.res_to_add_mod_list[m]; + + // sanity check to avoid pucch->sets[n].resources[res_idx] goes out of bound; + if (res_idx >= SRSRAN_PUCCH_NR_MAX_NOF_RESOURCES_PER_SET) { + return false; + } + + auto& resource = pucch->sets[n].resources[res_idx]; + uint32_t format2_rate = 0; + if (pucch_cfg.format2_present and + pucch_cfg.format2.type().value == asn1::setup_release_c::types_opts::setup and + pucch_cfg.format2.setup().max_code_rate_present) { + format2_rate = pucch_cfg.format2.setup().max_code_rate.to_number(); + } + if (not make_phy_res_config(asn1_resource, format2_rate, &resource)) { + return false; + } + } + } + + return true; +} + bool fill_phy_pdsch_cfg_common(const asn1::rrc_nr::pdsch_cfg_common_s& pdsch_cfg, srsran_sch_hl_cfg_nr_t* pdsch) { for (uint32_t i = 0; i < pdsch_cfg.pdsch_time_domain_alloc_list.size(); i++) { diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index 443725ab6..d6a154490 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -551,6 +551,27 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } + for (size_t n = 0; n < SRSRAN_PUCCH_NR_MAX_NOF_SETS; n++) { + if (pucch_cfg->sets[n].nof_resources > 0) { + printf("\n ==== Set index number %zu: =====\n", n); + for (size_t k = 0; k < pucch_cfg->sets[n].nof_resources; k++) { + printf("\n PUCCH resource ID %zu", k); + printf("\n Format %u", pucch_cfg->sets[n].resources[k].format); + printf("\n Starting PRB %u", pucch_cfg->sets[n].resources[k].starting_prb); + printf("\n Second PRB %u", pucch_cfg->sets[n].resources[k].second_hop_prb); + if (pucch_cfg->sets[n].resources[k].format == SRSRAN_PUCCH_NR_FORMAT_1) { + printf("\n Num of symbols %u", pucch_cfg->sets[n].resources[k].nof_symbols); + printf("\n ICS %u \n", pucch_cfg->sets[n].resources[k].initial_cyclic_shift); + } + if (pucch_cfg->sets[n].resources[k].format == SRSRAN_PUCCH_NR_FORMAT_2) { + printf("\n Num of PRBs %u", pucch_cfg->sets[n].resources[k].nof_prb); + printf("\n Start symb idx %u", pucch_cfg->sets[n].resources[k].start_symbol_idx); + printf("\n Num of symbols %u \n", pucch_cfg->sets[n].resources[k].nof_symbols); + } + } + } + } + // Use SR PUCCH resource // - At least one positive SR // - up to 2 HARQ-ACK diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 8735243b6..ddbdfc2cf 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -186,6 +186,10 @@ bool slot_worker::work_ul() printf("Stop here"); } + if (pucch_info[i].uci_data.cfg.nof_csi == 1 && pucch_info[i].uci_data.cfg.ack.count > 0) { + printf("Stop here"); + } + // Decode PUCCH if (srsran_gnb_ul_get_pucch(&gnb_ul, &ul_slot_cfg, diff --git a/srsgnb/src/stack/mac/sched_nr_worker.cc b/srsgnb/src/stack/mac/sched_nr_worker.cc index 861047a60..9533f6480 100644 --- a/srsgnb/src/stack/mac/sched_nr_worker.cc +++ b/srsgnb/src/stack/mac/sched_nr_worker.cc @@ -185,6 +185,10 @@ void cc_worker::postprocess_decisions(bwp_slot_allocator& bwp_alloc) continue; } + if (uci_cfg.nof_csi == 1 and uci_cfg.ack.count == 1) { + printf("Stop here"); + } + // If this slot has a SR opportunity and the selected PUCCH format is 1, consider positive SR. if (uci_cfg.o_sr > 0 and uci_cfg.ack.count > 0 and pucch.candidates.back().resource.format == SRSRAN_PUCCH_NR_FORMAT_1) { diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index a231b8267..8a4fd8522 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -215,41 +215,6 @@ int fill_csi_report_from_enb_cfg(const rrc_nr_cfg_t& cfg, csi_meas_cfg_s& csi_me } } - // the code below would be for NSA, even though this function was never called for NSA -#if 0 - csi_meas_cfg.csi_report_cfg_to_add_mod_list_present = true; - csi_meas_cfg.csi_report_cfg_to_add_mod_list.resize(1); - - auto& csi_report = csi_meas_cfg.csi_report_cfg_to_add_mod_list[0]; - csi_report.report_cfg_id = 0; - csi_report.res_for_ch_meas = 0; - csi_report.csi_im_res_for_interference_present = true; - csi_report.csi_im_res_for_interference = 1; - csi_report.report_cfg_type.set_periodic(); - csi_report.report_cfg_type.periodic().report_slot_cfg.set_slots80(); - csi_report.report_cfg_type.periodic().pucch_csi_res_list.resize(1); - csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].ul_bw_part_id = 0; - csi_report.report_cfg_type.periodic().pucch_csi_res_list[0].pucch_res = 1; // was 17 in orig PCAP - csi_report.report_quant.set_cri_ri_pmi_cqi(); - // Report freq config (optional) - csi_report.report_freq_cfg_present = true; - csi_report.report_freq_cfg.cqi_format_ind_present = true; - csi_report.report_freq_cfg.cqi_format_ind = csi_report_cfg_s::report_freq_cfg_s_::cqi_format_ind_opts::wideband_cqi; - csi_report.time_restrict_for_ch_meass = csi_report_cfg_s::time_restrict_for_ch_meass_opts::not_cfgured; - csi_report.time_restrict_for_interference_meass = - asn1::rrc_nr::csi_report_cfg_s::time_restrict_for_interference_meass_opts::not_cfgured; - csi_report.group_based_beam_report.set_disabled(); - // Skip CQI table (optional) - csi_report.cqi_table_present = true; - csi_report.cqi_table = asn1::rrc_nr::csi_report_cfg_s::cqi_table_opts::table2; - csi_report.subband_size = asn1::rrc_nr::csi_report_cfg_s::subband_size_opts::value1; - - if (cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5; - } else { - csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 7; - } -#endif return SRSRAN_SUCCESS; } diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index bf9247106..581c1f4a4 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -171,8 +171,8 @@ test_bench::args_t::args_t(int argc, char** argv) // Load default reference configuration phy_cfg = srsran::phy_cfg_nr_default_t(srsran::phy_cfg_nr_default_t::reference_cfg_t(reference_cfg_str)); -#if 0 // configure nzp +#if 0 auto& uecfg_set_0 = phy_cfg.pdsch.nzp_csi_rs_sets[0]; uecfg_set_0.trs_info = true; uecfg_set_0.count = 1; From fe6500bd55d1c96cbab72e23da11af572f400cf7 Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Mon, 24 Jan 2022 13:53:31 +0100 Subject: [PATCH 27/41] rrc: copy PUCCH cnf from RRCSetup to PHY structs Signed-off-by: Carlo Galiotto --- lib/src/asn1/rrc_nr_utils.cc | 4 ++++ lib/src/phy/phch/ra_ul_nr.c | 13 ++++++++++--- srsenb/src/phy/nr/slot_worker.cc | 2 ++ srsgnb/src/stack/mac/sched_nr_worker.cc | 2 ++ srsgnb/src/stack/rrc/cell_asn1_config.cc | 4 +++- srsgnb/src/stack/rrc/rrc_nr.cc | 2 ++ srsgnb/src/stack/rrc/rrc_nr_ue.cc | 9 ++++++++- 7 files changed, 31 insertions(+), 5 deletions(-) diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 0c7065132..33c799975 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -796,6 +796,10 @@ bool make_phy_res_config(const pucch_res_s& pucch_res, { srsran_pucch_nr_resource_t srsran_pucch_nr_resource = {}; srsran_pucch_nr_resource.starting_prb = pucch_res.start_prb; + srsran_pucch_nr_resource.intra_slot_hopping = pucch_res.intra_slot_freq_hop_present; + if (pucch_res.second_hop_prb_present) { + srsran_pucch_nr_resource.second_hop_prb = pucch_res.second_hop_prb; + } switch (pucch_res.format.type()) { case pucch_res_s::format_c_::types_opts::format0: srsran_pucch_nr_resource.format = SRSRAN_PUCCH_NR_FORMAT_0; diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index d6a154490..fed0fa4ed 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -551,6 +551,7 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } +#if 0 for (size_t n = 0; n < SRSRAN_PUCCH_NR_MAX_NOF_SETS; n++) { if (pucch_cfg->sets[n].nof_resources > 0) { printf("\n ==== Set index number %zu: =====\n", n); @@ -558,19 +559,23 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, printf("\n PUCCH resource ID %zu", k); printf("\n Format %u", pucch_cfg->sets[n].resources[k].format); printf("\n Starting PRB %u", pucch_cfg->sets[n].resources[k].starting_prb); + printf("\n Intra slot hopping %s", pucch_cfg->sets[n].resources[k].intra_slot_hopping ? "True" : "False"); printf("\n Second PRB %u", pucch_cfg->sets[n].resources[k].second_hop_prb); if (pucch_cfg->sets[n].resources[k].format == SRSRAN_PUCCH_NR_FORMAT_1) { + printf("\n ICS %u", pucch_cfg->sets[n].resources[k].initial_cyclic_shift); printf("\n Num of symbols %u", pucch_cfg->sets[n].resources[k].nof_symbols); - printf("\n ICS %u \n", pucch_cfg->sets[n].resources[k].initial_cyclic_shift); + printf("\n Starting sym idx %u", pucch_cfg->sets[n].resources[k].start_symbol_idx); + printf("\n Time domain OCC %u \n", pucch_cfg->sets[n].resources[k].time_domain_occ); } if (pucch_cfg->sets[n].resources[k].format == SRSRAN_PUCCH_NR_FORMAT_2) { printf("\n Num of PRBs %u", pucch_cfg->sets[n].resources[k].nof_prb); - printf("\n Start symb idx %u", pucch_cfg->sets[n].resources[k].start_symbol_idx); - printf("\n Num of symbols %u \n", pucch_cfg->sets[n].resources[k].nof_symbols); + printf("\n Num of symbols %u", pucch_cfg->sets[n].resources[k].nof_symbols); + printf("\n Start symb idx %u \n", pucch_cfg->sets[n].resources[k].start_symbol_idx); } } } } +#endif // Use SR PUCCH resource // - At least one positive SR @@ -640,9 +645,11 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } +#if 0 if (uci_cfg->ack.count > 0 && uci_cfg->nof_csi == 1 && uci_cfg->csi[0].cfg.type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) { printf("This is point where we fail"); } +#endif // If a UE does not have dedicated PUCCH resource configuration, provided by PUCCH-ResourceSet in PUCCH-Config, // a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index ddbdfc2cf..c7829e23c 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -182,6 +182,7 @@ bool slot_worker::work_ul() for (uint32_t i = 0; i < (uint32_t)pucch.candidates.size(); i++) { pucch_info[i].uci_data.cfg = pucch.candidates[i].uci_cfg; +#if 0 if (pucch_info[i].uci_data.cfg.nof_csi == 1 && pucch_info[i].uci_data.cfg.ack.count > 0) { printf("Stop here"); } @@ -189,6 +190,7 @@ bool slot_worker::work_ul() if (pucch_info[i].uci_data.cfg.nof_csi == 1 && pucch_info[i].uci_data.cfg.ack.count > 0) { printf("Stop here"); } +#endif // Decode PUCCH if (srsran_gnb_ul_get_pucch(&gnb_ul, diff --git a/srsgnb/src/stack/mac/sched_nr_worker.cc b/srsgnb/src/stack/mac/sched_nr_worker.cc index 9533f6480..223e4bdd2 100644 --- a/srsgnb/src/stack/mac/sched_nr_worker.cc +++ b/srsgnb/src/stack/mac/sched_nr_worker.cc @@ -185,9 +185,11 @@ void cc_worker::postprocess_decisions(bwp_slot_allocator& bwp_alloc) continue; } +#if 0 if (uci_cfg.nof_csi == 1 and uci_cfg.ack.count == 1) { printf("Stop here"); } +#endif // If this slot has a SR opportunity and the selected PUCCH format is 1, consider positive SR. if (uci_cfg.o_sr > 0 and uci_cfg.ack.count > 0 and diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 8a4fd8522..d2a879931 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -607,9 +607,9 @@ void fill_pucch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pucch_cfg for (uint32_t i = 0; i < out.res_to_add_mod_list.size(); ++i) { out.res_to_add_mod_list[i].pucch_res_id = i; out.res_to_add_mod_list[i].intra_slot_freq_hop_present = false; - out.res_to_add_mod_list[i].second_hop_prb_present = false; if (i < 8 or i == 16) { out.res_to_add_mod_list[i].start_prb = 51; + out.res_to_add_mod_list[i].second_hop_prb_present = true; out.res_to_add_mod_list[i].second_hop_prb = 0; out.res_to_add_mod_list[i].format.set_format1().init_cyclic_shift = (4 * (j % 3)); out.res_to_add_mod_list[i].format.format1().nrof_symbols = 14; @@ -618,6 +618,7 @@ void fill_pucch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pucch_cfg j++; } else if (i < 15) { out.res_to_add_mod_list[i].start_prb = 1; + out.res_to_add_mod_list[i].second_hop_prb_present = true; out.res_to_add_mod_list[i].second_hop_prb = 50; out.res_to_add_mod_list[i].format.set_format2().nrof_prbs = 1; out.res_to_add_mod_list[i].format.format2().nrof_symbols = 2; @@ -625,6 +626,7 @@ void fill_pucch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pucch_cfg j2++; } else { out.res_to_add_mod_list[i].start_prb = 50; + out.res_to_add_mod_list[i].second_hop_prb_present = true; out.res_to_add_mod_list[i].second_hop_prb = 1; out.res_to_add_mod_list[i].format.set_format2().nrof_prbs = 1; out.res_to_add_mod_list[i].format.format2().nrof_symbols = 2; diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 30371d011..016e219b0 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -347,9 +347,11 @@ void rrc_nr::config_mac() cell.ssb_positions_in_burst = du_cfg->cell(cc).serv_cell_cfg_common().ssb_positions_in_burst; cell.ssb_periodicity_ms = du_cfg->cell(cc).serv_cell_cfg_common().ssb_periodicity_serving_cell.to_number(); cell.ssb_scs.value = (subcarrier_spacing_e::options)cfg.cell_list[0].phy_cell.carrier.scs; +#if 1 // bzero(cell.bwps[0].pdsch.nzp_csi_rs_sets, sizeof(cell.bwps[0].pdsch.nzp_csi_rs_sets)); bool valid_cfg = srsran::make_pdsch_cfg_from_serv_cell(base_sp_cell_cfg.sp_cell_cfg_ded, &cell.bwps[0].pdsch); srsran_assert(valid_cfg, "Invalid NR cell configuration."); +#endif } // Set SIB1 and SI messages diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc index 1151e1964..194e36d1a 100644 --- a/srsgnb/src/stack/rrc/rrc_nr_ue.cc +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -1467,6 +1467,14 @@ int rrc_nr::ue::update_mac(const cell_group_cfg_s& cell_group_config, bool is_co // TODO: remaining fields } } + + if (cell_group_config.sp_cell_cfg_present and cell_group_config.sp_cell_cfg.sp_cell_cfg_ded_present and + cell_group_config.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present and + cell_group_config.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp_present and + cell_group_config.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pucch_cfg_present) { + auto& pucch_cfg = cell_group_config.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pucch_cfg.setup(); + srsran::fill_phy_pucch_cfg(pucch_cfg, &uecfg.phy_cfg.pucch); + } } else { auto& pdcch = cell_group_config.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg.setup(); for (auto& ss : pdcch.search_spaces_to_add_mod_list) { @@ -1481,7 +1489,6 @@ int rrc_nr::ue::update_mac(const cell_group_cfg_s& cell_group_config, bool is_co } } - uecfg.sp_cell_cfg.reset(new sp_cell_cfg_s{cell_group_cfg.sp_cell_cfg}); uecfg.mac_cell_group_cfg.reset(new mac_cell_group_cfg_s{cell_group_cfg.mac_cell_group_cfg}); uecfg.phy_cell_group_cfg.reset(new phys_cell_group_cfg_s{cell_group_cfg.phys_cell_group_cfg}); From d5859fb60b415ad9ebb11c3114bee0c849a1d1bd Mon Sep 17 00:00:00 2001 From: Carlo Galiotto Date: Tue, 25 Jan 2022 16:43:38 +0100 Subject: [PATCH 28/41] rrc-nr: remove comments/dead code Signed-off-by: Carlo Galiotto --- lib/src/phy/phch/ra_ul_nr.c | 32 ------------------------ srsenb/src/phy/nr/slot_worker.cc | 10 -------- srsgnb/src/stack/mac/sched_nr_worker.cc | 6 ----- srsgnb/src/stack/rrc/cell_asn1_config.cc | 3 --- srsgnb/src/stack/rrc/rrc_nr.cc | 6 ----- test/phy/nr_phy_test.cc | 11 -------- 6 files changed, 68 deletions(-) diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index fed0fa4ed..92ff87088 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -551,32 +551,6 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } -#if 0 - for (size_t n = 0; n < SRSRAN_PUCCH_NR_MAX_NOF_SETS; n++) { - if (pucch_cfg->sets[n].nof_resources > 0) { - printf("\n ==== Set index number %zu: =====\n", n); - for (size_t k = 0; k < pucch_cfg->sets[n].nof_resources; k++) { - printf("\n PUCCH resource ID %zu", k); - printf("\n Format %u", pucch_cfg->sets[n].resources[k].format); - printf("\n Starting PRB %u", pucch_cfg->sets[n].resources[k].starting_prb); - printf("\n Intra slot hopping %s", pucch_cfg->sets[n].resources[k].intra_slot_hopping ? "True" : "False"); - printf("\n Second PRB %u", pucch_cfg->sets[n].resources[k].second_hop_prb); - if (pucch_cfg->sets[n].resources[k].format == SRSRAN_PUCCH_NR_FORMAT_1) { - printf("\n ICS %u", pucch_cfg->sets[n].resources[k].initial_cyclic_shift); - printf("\n Num of symbols %u", pucch_cfg->sets[n].resources[k].nof_symbols); - printf("\n Starting sym idx %u", pucch_cfg->sets[n].resources[k].start_symbol_idx); - printf("\n Time domain OCC %u \n", pucch_cfg->sets[n].resources[k].time_domain_occ); - } - if (pucch_cfg->sets[n].resources[k].format == SRSRAN_PUCCH_NR_FORMAT_2) { - printf("\n Num of PRBs %u", pucch_cfg->sets[n].resources[k].nof_prb); - printf("\n Num of symbols %u", pucch_cfg->sets[n].resources[k].nof_symbols); - printf("\n Start symb idx %u \n", pucch_cfg->sets[n].resources[k].start_symbol_idx); - } - } - } - } -#endif - // Use SR PUCCH resource // - At least one positive SR // - up to 2 HARQ-ACK @@ -645,12 +619,6 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } -#if 0 - if (uci_cfg->ack.count > 0 && uci_cfg->nof_csi == 1 && uci_cfg->csi[0].cfg.type == SRSRAN_CSI_REPORT_TYPE_PERIODIC) { - printf("This is point where we fail"); - } -#endif - // If a UE does not have dedicated PUCCH resource configuration, provided by PUCCH-ResourceSet in PUCCH-Config, // a PUCCH resource set is provided by pucch-ResourceCommon through an index to a row of Table 9.2.1-1 for size // transmission of HARQ-ACK information on PUCCH in an initial UL BWP of N BWP PRBs. diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index c7829e23c..0dba28c1b 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -182,16 +182,6 @@ bool slot_worker::work_ul() for (uint32_t i = 0; i < (uint32_t)pucch.candidates.size(); i++) { pucch_info[i].uci_data.cfg = pucch.candidates[i].uci_cfg; -#if 0 - if (pucch_info[i].uci_data.cfg.nof_csi == 1 && pucch_info[i].uci_data.cfg.ack.count > 0) { - printf("Stop here"); - } - - if (pucch_info[i].uci_data.cfg.nof_csi == 1 && pucch_info[i].uci_data.cfg.ack.count > 0) { - printf("Stop here"); - } -#endif - // Decode PUCCH if (srsran_gnb_ul_get_pucch(&gnb_ul, &ul_slot_cfg, diff --git a/srsgnb/src/stack/mac/sched_nr_worker.cc b/srsgnb/src/stack/mac/sched_nr_worker.cc index 223e4bdd2..861047a60 100644 --- a/srsgnb/src/stack/mac/sched_nr_worker.cc +++ b/srsgnb/src/stack/mac/sched_nr_worker.cc @@ -185,12 +185,6 @@ void cc_worker::postprocess_decisions(bwp_slot_allocator& bwp_alloc) continue; } -#if 0 - if (uci_cfg.nof_csi == 1 and uci_cfg.ack.count == 1) { - printf("Stop here"); - } -#endif - // If this slot has a SR opportunity and the selected PUCCH format is 1, consider positive SR. if (uci_cfg.o_sr > 0 and uci_cfg.ack.count > 0 and pucch.candidates.back().resource.format == SRSRAN_PUCCH_NR_FORMAT_1) { diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index d2a879931..d94fbdf62 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -1056,9 +1056,6 @@ int fill_master_cell_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1 fill_sp_cell_cfg_from_enb_cfg(cfg, cc, out.sp_cell_cfg); out.sp_cell_cfg.recfg_with_sync_present = false; - // The current CSI config make the PUCCH decoding fail. We temporarily disable it until further investigation - // out.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = false; - return SRSRAN_SUCCESS; } diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 016e219b0..676ba17b7 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -342,16 +342,10 @@ void rrc_nr::config_mac() cell.ssb_scs = serv_cell.ssb_subcarrier_spacing; } else { cell.bwps[0].pdsch.p_zp_csi_rs_set = {}; - bzero(cell.bwps[0].pdsch.nzp_csi_rs_sets, sizeof(cell.bwps[0].pdsch.nzp_csi_rs_sets)); cell.ssb_positions_in_burst = du_cfg->cell(cc).serv_cell_cfg_common().ssb_positions_in_burst; cell.ssb_periodicity_ms = du_cfg->cell(cc).serv_cell_cfg_common().ssb_periodicity_serving_cell.to_number(); cell.ssb_scs.value = (subcarrier_spacing_e::options)cfg.cell_list[0].phy_cell.carrier.scs; -#if 1 - // bzero(cell.bwps[0].pdsch.nzp_csi_rs_sets, sizeof(cell.bwps[0].pdsch.nzp_csi_rs_sets)); - bool valid_cfg = srsran::make_pdsch_cfg_from_serv_cell(base_sp_cell_cfg.sp_cell_cfg_ded, &cell.bwps[0].pdsch); - srsran_assert(valid_cfg, "Invalid NR cell configuration."); -#endif } // Set SIB1 and SI messages diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 581c1f4a4..2d163128e 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -171,17 +171,6 @@ test_bench::args_t::args_t(int argc, char** argv) // Load default reference configuration phy_cfg = srsran::phy_cfg_nr_default_t(srsran::phy_cfg_nr_default_t::reference_cfg_t(reference_cfg_str)); - // configure nzp -#if 0 - auto& uecfg_set_0 = phy_cfg.pdsch.nzp_csi_rs_sets[0]; - uecfg_set_0.trs_info = true; - uecfg_set_0.count = 1; - - auto& res_0 = uecfg_set_0.data[0]; - res_0.id = 0; - res_0.resource_mapping.row = srsran_csi_rs_resource_mapping_row_2; -#endif - // Calculate the DL signal power from the number of PRBs dl_channel.awgn_signal_power_dBfs = srsran_gnb_dl_get_maximum_signal_power_dBfs(phy_cfg.carrier.nof_prb); From aea7a11e53777c8de90051a4af7d33105a47037d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 26 Jan 2022 11:12:09 +0100 Subject: [PATCH 29/41] Fix SKIQ compilation with gcc-11 --- lib/src/phy/rf/rf_skiq_imp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/rf/rf_skiq_imp.c b/lib/src/phy/rf/rf_skiq_imp.c index 96ad18ee1..483241496 100644 --- a/lib/src/phy/rf/rf_skiq_imp.c +++ b/lib/src/phy/rf/rf_skiq_imp.c @@ -876,7 +876,7 @@ int rf_skiq_send_timed(void* h, } int rf_skiq_send_timed_multi(void* h_, - void** data_, + void* data_[SRSRAN_MAX_PORTS], int nsamples, time_t secs, double frac_secs, From 569f5c1a6f94aa3802f5aaa01414cb6154d49fbc Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 26 Jan 2022 11:17:48 +0100 Subject: [PATCH 30/41] Protect input buffer SSB demodulation in search/find and skip PBCH decoding if PBCH DMRS correlation does not reach threshold --- lib/src/phy/sync/ssb.c | 65 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/lib/src/phy/sync/ssb.c b/lib/src/phy/sync/ssb.c index 5492862c8..bc473151b 100644 --- a/lib/src/phy/sync/ssb.c +++ b/lib/src/phy/sync/ssb.c @@ -965,6 +965,11 @@ int srsran_ssb_csi_search(srsran_ssb_t* q, t_offset = 0; } + // Make sure SSB time offset is in bounded in the input buffer + if (t_offset + q->ssb_sz > nof_samples) { + return SRSRAN_SUCCESS; + } + // Demodulate cf_t ssb_grid[SRSRAN_SSB_NOF_RE] = {}; if (ssb_demodulate(q, in, t_offset, coarse_cfo_hz, ssb_grid) < SRSRAN_SUCCESS) { @@ -1034,11 +1039,12 @@ int srsran_ssb_csi_measure(srsran_ssb_t* q, return SRSRAN_SUCCESS; } -static int ssb_select_pbch(srsran_ssb_t* q, - uint32_t N_id, - const cf_t ssb_grid[SRSRAN_SSB_NOF_RE], - uint32_t* found_n_hf, - uint32_t* found_ssb_idx_4lsb) +static int ssb_select_pbch(srsran_ssb_t* q, + uint32_t N_id, + const cf_t ssb_grid[SRSRAN_SSB_NOF_RE], + uint32_t* found_n_hf, + uint32_t* found_ssb_idx_4lsb, + srsran_dmrs_pbch_meas_t* pbch_meas) { // Prepare PBCH DMRS configuration srsran_dmrs_pbch_cfg_t pbch_dmrs_cfg = {}; @@ -1080,6 +1086,7 @@ static int ssb_select_pbch(srsran_ssb_t* q, // Save findings *found_n_hf = best_n_hf; *found_ssb_idx_4lsb = best_ssb_idx; + *pbch_meas = best_meas; return SRSRAN_SUCCESS; } @@ -1177,6 +1184,9 @@ int srsran_ssb_search(srsran_ssb_t* q, const cf_t* in, uint32_t nof_samples, srs return SRSRAN_ERROR; } + // Set the SSB search result with default value with PBCH CRC unmatched, meaning no cell is found + SRSRAN_MEM_ZERO(res, srsran_ssb_search_res_t, 1); + // Search for PSS in time domain uint32_t N_id_2 = 0; uint32_t t_offset = 0; @@ -1193,6 +1203,11 @@ int srsran_ssb_search(srsran_ssb_t* q, const cf_t* in, uint32_t nof_samples, srs t_offset = 0; } + // Make sure SSB time offset is in bounded in the input buffer + if (t_offset + q->ssb_sz > nof_samples) { + return SRSRAN_SUCCESS; + } + // Demodulate cf_t ssb_grid[SRSRAN_SSB_NOF_RE] = {}; if (ssb_demodulate(q, in, t_offset, coarse_cfo_hz, ssb_grid) < SRSRAN_SUCCESS) { @@ -1212,20 +1227,32 @@ int srsran_ssb_search(srsran_ssb_t* q, const cf_t* in, uint32_t nof_samples, srs uint32_t N_id = SRSRAN_NID_NR(N_id_1, N_id_2); // Select the most suitable SSB candidate - uint32_t n_hf = 0; - uint32_t ssb_idx = 0; - if (ssb_select_pbch(q, N_id, ssb_grid, &n_hf, &ssb_idx) < SRSRAN_SUCCESS) { + uint32_t n_hf = 0; + uint32_t ssb_idx = 0; + srsran_dmrs_pbch_meas_t pbch_meas = {}; + if (ssb_select_pbch(q, N_id, ssb_grid, &n_hf, &ssb_idx, &pbch_meas) < SRSRAN_SUCCESS) { ERROR("Error selecting PBCH"); return SRSRAN_ERROR; } - // Compute PBCH channel estimates + // Avoid decoding if the selected PBCH DMRS do not reach the minimum threshold + if (pbch_meas.corr < q->args.pbch_dmrs_thr) { + return SRSRAN_SUCCESS; + } + + // Decode PBCH srsran_pbch_msg_nr_t pbch_msg = {}; if (ssb_decode_pbch(q, N_id, n_hf, ssb_idx, ssb_grid, &pbch_msg) < SRSRAN_SUCCESS) { ERROR("Error decoding PBCH"); return SRSRAN_ERROR; } + // If PBCH was not decoded, skip measurements + if (!pbch_msg.crc) { + return SRSRAN_SUCCESS; + } + + // Perform measurements from PSS and SSS srsran_csi_trs_measurements_t measurements = {}; if (ssb_measure(q, ssb_grid, N_id, &measurements) < SRSRAN_SUCCESS) { ERROR("Error measuring"); @@ -1327,6 +1354,9 @@ int srsran_ssb_find(srsran_ssb_t* q, return SRSRAN_ERROR; } + // Set the PBCH message result with default value (CRC unmatched), meaning no cell is found + SRSRAN_MEM_ZERO(pbch_msg, srsran_pbch_msg_nr_t, 1); + // Copy tail from previous execution into the start of this srsran_vec_cf_copy(q->sf_buffer, &q->sf_buffer[q->sf_sz], q->ssb_sz); @@ -1347,6 +1377,11 @@ int srsran_ssb_find(srsran_ssb_t* q, t_offset = 0; } + // Make sure SSB time offset is in bounded in the input buffer + if (t_offset > q->sf_sz) { + return SRSRAN_SUCCESS; + } + // Demodulate cf_t ssb_grid[SRSRAN_SSB_NOF_RE] = {}; if (ssb_demodulate(q, q->sf_buffer, t_offset, 0.0f, ssb_grid) < SRSRAN_SUCCESS) { @@ -1361,13 +1396,19 @@ int srsran_ssb_find(srsran_ssb_t* q, } // Select the most suitable SSB candidate - uint32_t n_hf = 0; - uint32_t ssb_idx = 0; // SSB candidate index - if (ssb_select_pbch(q, N_id, ssb_grid, &n_hf, &ssb_idx) < SRSRAN_SUCCESS) { + uint32_t n_hf = 0; + uint32_t ssb_idx = 0; // SSB candidate index + srsran_dmrs_pbch_meas_t pbch_meas = {}; + if (ssb_select_pbch(q, N_id, ssb_grid, &n_hf, &ssb_idx, &pbch_meas) < SRSRAN_SUCCESS) { ERROR("Error selecting PBCH"); return SRSRAN_ERROR; } + // Avoid decoding if the selected PBCH DMRS do not reach the minimum threshold + if (pbch_meas.corr < q->args.pbch_dmrs_thr) { + return SRSRAN_SUCCESS; + } + // Calculate the SSB offset in the subframe uint32_t ssb_offset = srsran_ssb_candidate_sf_offset(q, ssb_idx); From e3f8b75652ef8f73d1f81f0274971df74c176b68 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 24 Jan 2022 13:11:22 +0100 Subject: [PATCH 31/41] SSB search uses correlation power to normalise --- lib/src/phy/sync/ssb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/sync/ssb.c b/lib/src/phy/sync/ssb.c index bc473151b..2dcfb4d48 100644 --- a/lib/src/phy/sync/ssb.c +++ b/lib/src/phy/sync/ssb.c @@ -856,8 +856,9 @@ static int ssb_pss_search(srsran_ssb_t* q, // Find maximum uint32_t peak_idx = srsran_vec_max_abs_ci(q->tmp_time, q->corr_window); - // Average power, skip window if value is invalid (0.0, nan or inf) - float avg_pwr_corr = srsran_vec_avg_power_cf(&q->tmp_time[peak_idx], q->symbol_sz); + // Average power, take total power of the frequency domain signal after filtering, skip correlation window if + // value is invalid (0.0, nan or inf) + float avg_pwr_corr = srsran_vec_avg_power_cf(q->tmp_corr, q->corr_sz); if (!isnormal(avg_pwr_corr)) { continue; } From 2df371fdd6216ca9268d3ca524363e4fd112e326 Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Tue, 25 Jan 2022 15:47:56 +0100 Subject: [PATCH 32/41] Provide PRACH NR performance test --- lib/src/phy/phch/test/CMakeLists.txt | 4 + lib/src/phy/phch/test/prach_nr_test_perf.c | 245 +++++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 lib/src/phy/phch/test/prach_nr_test_perf.c diff --git a/lib/src/phy/phch/test/CMakeLists.txt b/lib/src/phy/phch/test/CMakeLists.txt index cd65b1ddb..8ce5df6dd 100644 --- a/lib/src/phy/phch/test/CMakeLists.txt +++ b/lib/src/phy/phch/test/CMakeLists.txt @@ -629,6 +629,10 @@ if(RF_FOUND) target_link_libraries(prach_test_usrp srsran_rf srsran_phy pthread) endif(RF_FOUND) +add_executable(prach_nr_test_perf EXCLUDE_FROM_ALL prach_nr_test_perf.c) +target_link_libraries(prach_nr_test_perf srsran_phy) +# this is just for performance evaluation, not for unit testing + ######################################################################## # NR ######################################################################## diff --git a/lib/src/phy/phch/test/prach_nr_test_perf.c b/lib/src/phy/phch/test/prach_nr_test_perf.c new file mode 100644 index 000000000..2339d8a2c --- /dev/null +++ b/lib/src/phy/phch/test/prach_nr_test_perf.c @@ -0,0 +1,245 @@ +/** + * \copyright Copyright 2013-2021 Software Radio Systems Limited + * + * \copyright By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +/** + * \file prach_nr_test_perf.c + * \brief Performance test for PRACH NR. + * + * This program simulates several PRACH preamble transmissions (so far, burst format 0 only) + * to estimate the probability of detection and of false alarm. The probability of detection + * is the conditional probability of detecting the preamble when the preamble is present. + * An error consists in detecting no preambles, detecting only preambles different from the + * reference one, or detecting the correct preamble with a timing error beyond tolerance. + * The probability of false alarm is the probability of detecting any preamble when input + * is only noise. + * + * The simulation setup can be controlled by means of the following arguments. + * - -N num: sets the number of experiments to \c num. + * - -n num: sets the total number of UL PRBs to \c num. + * - -f num: sets the preamble format to \c num (for now, format 0 only). + * - -s val: sets the nominal SNR to \c val dB. + * - -v : activates verbose output. + * + * Example: + * \code{.cpp} + * prach_nr_test_perf -n 52 -s -14.6 + * \endcode + * + * \todo Restricted preamble formats not implemented yet. Fading channel and SIMO. + */ + +#include +#include +#include +#include +#include + +#include "srsran/srsran.h" + +#define MAX_LEN 70176 + +static uint32_t nof_prb = 52; +static uint32_t config_idx = 0; +static int nof_runs = 100; +static float snr_dB = -14.5F; +static bool is_verbose = false; + +static void usage(char* prog) +{ + printf("Usage: %s\n", prog); + printf("\t-N Number of experiments [Default %d]\n", nof_runs); + printf("\t-n Uplink number of PRB [Default %d]\n", nof_prb); + printf("\t-f Preamble format [Default %d]\n", config_idx); + printf("\t-s SNR in dB [Default %.2f]\n", snr_dB); + printf("\t-v Activate verbose output [Default %s]\n", is_verbose ? "true" : "false"); +} + +static void parse_args(int argc, char** argv) +{ + int opt = 0; + while ((opt = getopt(argc, argv, "N:n:f:s:v")) != -1) { + switch (opt) { + case 'N': + nof_runs = (int)strtol(optarg, NULL, 10); + break; + case 'n': + nof_prb = (uint32_t)strtol(optarg, NULL, 10); + break; + case 'f': + config_idx = (uint32_t)strtol(optarg, NULL, 10); + break; + case 's': + snr_dB = strtof(optarg, NULL); + break; + case 'v': + is_verbose = true; + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +int main(int argc, char** argv) +{ + parse_args(argc, argv); + if (config_idx != 0) { + ERROR("Preamble format not yet implemented"); + return SRSRAN_ERROR; + } + srsran_prach_t prach; + + const int fft_size = srsran_symbol_sz(nof_prb); + const float main_scs_kHz = 15; // UL subcarrier spacing (i.e., Delta f) + const float sampling_time_us = 1000.0F / (main_scs_kHz * (float)fft_size); + const int slot_length = 15 * fft_size; // number of samples in a slot + + if (srsran_prach_init(&prach, fft_size)) { + ERROR("Initializing PRACH"); + srsran_prach_free(&prach); + return SRSRAN_ERROR; + } + + cf_t preamble[MAX_LEN]; + memset(preamble, 0, sizeof(cf_t) * MAX_LEN); + + srsran_prach_cfg_t prach_cfg; + ZERO_OBJECT(prach_cfg); + + // Setup according to TS38.104 Section 8.4 + prach_cfg.is_nr = true; + prach_cfg.config_idx = 0; // preamble format 0 + prach_cfg.hs_flag = false; // no high speed + prach_cfg.freq_offset = 0; + prach_cfg.root_seq_idx = 22; // logical (root sequence) index i + prach_cfg.zero_corr_zone = 1; // zero correlation zone -> implies Ncs = 13 + prach_cfg.num_ra_preambles = 0; // use default + const uint32_t seq_index = 32; // sequence index "v" + const float prach_scs_kHz = 1.25F; // PRACH subcarrier spacing (i.e., Delta f^RA) + const float max_time_error_us = 1.04F; // time error tolerance + const int nof_offset_steps = 10; + + if (srsran_prach_set_cfg(&prach, &prach_cfg, nof_prb)) { + ERROR("Error initiating PRACH object"); + srsran_prach_free(&prach); + return SRSRAN_ERROR; + } + + if (srsran_prach_gen(&prach, seq_index, 0, preamble) < SRSRAN_SUCCESS) { + ERROR("Generating PRACH preamble"); + srsran_prach_free(&prach); + return SRSRAN_ERROR; + } + + const uint32_t preamble_length = prach.N_seq; + const uint32_t ZC_length = prach.N_zc; // Zadoff-Chu sequence length (i.e., L_RA) + const float base_time_offset_us = (float)prach.N_cs * 1000 / (2.0F * (float)ZC_length * prach_scs_kHz); + + float prach_pwr = srsran_vec_avg_power_cf(preamble, preamble_length); + srsran_vec_sc_prod_cfc(preamble, 1.0F / sqrtf(prach_pwr), preamble, preamble_length); + + int vector_length = 2 * slot_length; + cf_t symbols[vector_length]; + cf_t noise_vec[vector_length]; + + uint32_t indices[64] = {0}; + float offset_est[64] = {0}; + uint32_t n_indices = 0; + + float time_offset_us = 0; + int offset_samples = 0; + float noise_var = srsran_convert_dB_to_power(-snr_dB); + int ok_detection = 0; + int missed_detection = 0; + int false_detection_signal_tmp = 0; + int false_detection_signal = 0; + int false_detection_noise = 0; + int offset_est_error = 0; + + int step = SRSRAN_MAX(nof_runs / 100, 1); + for (int i_run = 0; i_run < nof_runs; i_run++) { + // show we are doing something + if (i_run % (20 * step) == 0) { + printf("\n"); + } + if (i_run % step == 0) { + printf("*"); + fflush(stdout); + } + + srsran_vec_cf_zero(noise_vec, vector_length); + srsran_ch_awgn_c(noise_vec, noise_vec, noise_var, vector_length); + if (is_verbose) { + prach_pwr = srsran_vec_avg_power_cf(preamble, preamble_length); + float noise_pwr = srsran_vec_avg_power_cf(noise_vec, vector_length); + printf(" Tx power: %.3f\n", prach_pwr); + printf(" Noise power: %.3f\n", noise_pwr); + printf(" Target/measured SNR: %.3f / %.3f dB\n", snr_dB, srsran_convert_power_to_dB(prach_pwr / noise_pwr)); + } + for (int i = 0; i < nof_offset_steps; i++) { + time_offset_us = base_time_offset_us + (float)i * 0.1F; + offset_samples = (int)roundf(time_offset_us / sampling_time_us); + srsran_vec_cf_copy(symbols, noise_vec, vector_length); + for (int j = 0; j < preamble_length; j++) { + symbols[j + offset_samples] += preamble[j]; + } + + srsran_prach_detect_offset(&prach, 0, &symbols[prach.N_cp], slot_length, indices, offset_est, NULL, &n_indices); + false_detection_signal_tmp = 0; + for (int j = 0; j < n_indices; j++) { + if (indices[j] != seq_index) { + false_detection_signal_tmp++; + } else if (fabsf(offset_est[j] * 1.0e6F - time_offset_us) > max_time_error_us) { + offset_est_error++; + } else { + ok_detection++; + } + } + false_detection_signal += (n_indices > 1 || false_detection_signal_tmp == 1); + // Missed detection if no preamble was detected or no detected preamble is the right one + missed_detection += (n_indices == 0 || n_indices == false_detection_signal_tmp); + } + + srsran_prach_detect_offset(&prach, 0, &noise_vec[prach.N_cp], slot_length, indices, offset_est, NULL, &n_indices); + false_detection_noise += (n_indices > 0); + } + int total_runs = nof_offset_steps * nof_runs; + if (missed_detection + ok_detection + offset_est_error != total_runs) { + srsran_prach_free(&prach); + ERROR("Counting detection errors"); + return SRSRAN_ERROR; + } + + printf("\n\nPRACH performance test: format 0, %d PRB, AWGN channel, SNR=%.1f dB\n", nof_prb, snr_dB); + printf("\nMissed detection probability: %.3e (%d out of %d)\n", + (float)missed_detection / (float)total_runs, + missed_detection, + total_runs); + printf("Probability of timing error: %.3e (%d out of %d)\n", + (float)offset_est_error / (float)total_runs, + offset_est_error, + total_runs); + printf("Probability of OK detection: %.3e (%d out of %d)\n", + (float)ok_detection / (float)total_runs, + ok_detection, + total_runs); + printf("\nProbability of false detection with preamble: %.3e (%d out of %d)\n", + (float)false_detection_signal / (float)total_runs, + false_detection_signal, + total_runs); + printf("Probability of false detection without preamble: %.3e (%d out of %d)\n", + (float)false_detection_noise / (float)nof_runs, + false_detection_noise, + nof_runs); + + srsran_prach_free(&prach); + + printf("Done\n"); +} From cac62e01e00a8d866aa5989851b114bc042ac83b Mon Sep 17 00:00:00 2001 From: dvdgrgrtt Date: Wed, 26 Jan 2022 09:00:07 +0100 Subject: [PATCH 33/41] Improve coding style --- lib/src/phy/phch/test/prach_nr_test_perf.c | 26 +++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/src/phy/phch/test/prach_nr_test_perf.c b/lib/src/phy/phch/test/prach_nr_test_perf.c index 2339d8a2c..e1a6ccdf6 100644 --- a/lib/src/phy/phch/test/prach_nr_test_perf.c +++ b/lib/src/phy/phch/test/prach_nr_test_perf.c @@ -108,7 +108,7 @@ int main(int argc, char** argv) } cf_t preamble[MAX_LEN]; - memset(preamble, 0, sizeof(cf_t) * MAX_LEN); + srsran_vec_cf_zero(preamble, MAX_LEN); srsran_prach_cfg_t prach_cfg; ZERO_OBJECT(prach_cfg); @@ -138,12 +138,15 @@ int main(int argc, char** argv) return SRSRAN_ERROR; } - const uint32_t preamble_length = prach.N_seq; - const uint32_t ZC_length = prach.N_zc; // Zadoff-Chu sequence length (i.e., L_RA) - const float base_time_offset_us = (float)prach.N_cs * 1000 / (2.0F * (float)ZC_length * prach_scs_kHz); + const uint32_t preamble_length = prach.N_seq; - float prach_pwr = srsran_vec_avg_power_cf(preamble, preamble_length); - srsran_vec_sc_prod_cfc(preamble, 1.0F / sqrtf(prach_pwr), preamble, preamble_length); + float prach_pwr_sqrt = sqrtf(srsran_vec_avg_power_cf(preamble, preamble_length)); + if (!isnormal(prach_pwr_sqrt)) { + ERROR("PRACH preamble power is not a finite, nonzero value"); + srsran_prach_free(&prach); + return SRSRAN_ERROR; + } + srsran_vec_sc_prod_cfc(preamble, 1.0F / prach_pwr_sqrt, preamble, preamble_length); int vector_length = 2 * slot_length; cf_t symbols[vector_length]; @@ -163,6 +166,10 @@ int main(int argc, char** argv) int false_detection_noise = 0; int offset_est_error = 0; + // Timing offset base value is equivalent to N_cs/2 + const uint32_t ZC_length = prach.N_zc; // Zadoff-Chu sequence length (i.e., L_RA) + const float base_time_offset_us = (float)prach.N_cs * 1000 / (2.0F * (float)ZC_length * prach_scs_kHz); + int step = SRSRAN_MAX(nof_runs / 100, 1); for (int i_run = 0; i_run < nof_runs; i_run++) { // show we are doing something @@ -177,19 +184,18 @@ int main(int argc, char** argv) srsran_vec_cf_zero(noise_vec, vector_length); srsran_ch_awgn_c(noise_vec, noise_vec, noise_var, vector_length); if (is_verbose) { - prach_pwr = srsran_vec_avg_power_cf(preamble, preamble_length); + float prach_pwr = srsran_vec_avg_power_cf(preamble, preamble_length); float noise_pwr = srsran_vec_avg_power_cf(noise_vec, vector_length); printf(" Tx power: %.3f\n", prach_pwr); printf(" Noise power: %.3f\n", noise_pwr); printf(" Target/measured SNR: %.3f / %.3f dB\n", snr_dB, srsran_convert_power_to_dB(prach_pwr / noise_pwr)); } + // Cycle timing offset with a 0.1-us step starting from the base value for (int i = 0; i < nof_offset_steps; i++) { time_offset_us = base_time_offset_us + (float)i * 0.1F; offset_samples = (int)roundf(time_offset_us / sampling_time_us); srsran_vec_cf_copy(symbols, noise_vec, vector_length); - for (int j = 0; j < preamble_length; j++) { - symbols[j + offset_samples] += preamble[j]; - } + srsran_vec_sum_ccc(&symbols[offset_samples], preamble, &symbols[offset_samples], preamble_length); srsran_prach_detect_offset(&prach, 0, &symbols[prach.N_cp], slot_length, indices, offset_est, NULL, &n_indices); false_detection_signal_tmp = 0; From fbf178e958349c53e0044bc0b8c95d2ea8b69a42 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 26 Jan 2022 18:01:02 +0100 Subject: [PATCH 34/41] Decrease PBCH-DMRS threshold to pass test --- lib/src/phy/sync/ssb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/sync/ssb.c b/lib/src/phy/sync/ssb.c index 2dcfb4d48..72e894afe 100644 --- a/lib/src/phy/sync/ssb.c +++ b/lib/src/phy/sync/ssb.c @@ -37,7 +37,7 @@ /* * Default NR-PBCH DMRS normalised correlation (RSRP/EPRE) threshold */ -#define SSB_PBCH_DMRS_DEFAULT_CORR_THR 0.6f +#define SSB_PBCH_DMRS_DEFAULT_CORR_THR 0.5f static int ssb_init_corr(srsran_ssb_t* q) { From b4bbbc902a8e9a29a3e921fd2684173d40e6be3b Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Tue, 16 Nov 2021 16:48:33 +0100 Subject: [PATCH 35/41] zmq: fix scaling of samples when decimation is applied --- lib/src/phy/rf/rf_zmq_imp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/rf/rf_zmq_imp.c b/lib/src/phy/rf/rf_zmq_imp.c index 6b4c34fd4..2b501a32d 100644 --- a/lib/src/phy/rf/rf_zmq_imp.c +++ b/lib/src/phy/rf/rf_zmq_imp.c @@ -785,7 +785,7 @@ int rf_zmq_recv_with_time_multi(void* h, void** data, uint32_t nsamples, bool bl for (int j = 0; j < decim_factor; j++, n++) { avg += ptr[n]; } - dst[i] = avg; + dst[i] = avg; // divide by decim_factor later via scale } rf_zmq_info(handler->id, @@ -801,6 +801,10 @@ int rf_zmq_recv_with_time_multi(void* h, void** data, uint32_t nsamples, bool bl pthread_mutex_lock(&handler->rx_gain_mutex); float scale = srsran_convert_dB_to_amplitude(handler->rx_gain); pthread_mutex_unlock(&handler->rx_gain_mutex); + // scale shall also incorporate decim_factor + if (decim_factor > 0) { + scale = scale / decim_factor; + } for (uint32_t c = 0; c < handler->nof_channels; c++) { if (buffers[c]) { srsran_vec_sc_prod_cfc(buffers[c], scale, buffers[c], nsamples); From cceae6895888bdbfef5cc9a3463b09876d7d761b Mon Sep 17 00:00:00 2001 From: Robert Falkenberg Date: Wed, 26 Jan 2022 11:23:43 +0100 Subject: [PATCH 36/41] zmq: extend test to 4 trx, w/wo decimation --- lib/src/phy/rf/rf_zmq_test.c | 183 +++++++++++++++++++++++------------ 1 file changed, 121 insertions(+), 62 deletions(-) diff --git a/lib/src/phy/rf/rf_zmq_test.c b/lib/src/phy/rf/rf_zmq_test.c index d9a99335f..19c7c50c1 100644 --- a/lib/src/phy/rf/rf_zmq_test.c +++ b/lib/src/phy/rf/rf_zmq_test.c @@ -17,18 +17,22 @@ #include #include #include +#include #include #include -#define NOF_RX_ANT 1 +#define PRINT_SAMPLES 1 +#define COMPARE_BITS 0 +#define COMPARE_EPSILON (1e-6f) +#define NOF_RX_ANT 4 #define NUM_SF (500) #define SF_LEN (1920) #define RF_BUFFER_SIZE (SF_LEN * NUM_SF) #define TX_OFFSET_MS (4) -static cf_t ue_rx_buffer[RF_BUFFER_SIZE]; -static cf_t enb_tx_buffer[RF_BUFFER_SIZE]; -static cf_t enb_rx_buffer[RF_BUFFER_SIZE]; +static cf_t ue_rx_buffer[NOF_RX_ANT][RF_BUFFER_SIZE]; +static cf_t enb_tx_buffer[NOF_RX_ANT][RF_BUFFER_SIZE]; +static cf_t enb_rx_buffer[NOF_RX_ANT][RF_BUFFER_SIZE]; static srsran_rf_t ue_radio, enb_radio; pthread_t rx_thread; @@ -53,13 +57,15 @@ void* ue_rx_thread_function(void* args) uint32_t num_rxed_samps = 0; for (uint32_t i = 0; i < num_slots; ++i) { void* data_ptr[SRSRAN_MAX_PORTS] = {NULL}; - data_ptr[0] = &ue_rx_buffer[i * num_samps_per_slot]; + for (uint32_t c = 0; c < NOF_RX_ANT; c++) { + data_ptr[c] = &ue_rx_buffer[c][i * num_samps_per_slot]; + } num_rxed_samps += srsran_rf_recv_with_time_multi(&ue_radio, data_ptr, num_samps_per_slot, true, NULL, NULL); } printf("received %d samples.\n", num_rxed_samps); - printf("closing ue norf device\n"); + printf("closing ue zmq device\n"); srsran_rf_close(&ue_radio); return NULL; @@ -78,17 +84,24 @@ void enb_tx_function(const char* tx_args, bool timed_tx) } // generate random tx data - for (int i = 0; i < RF_BUFFER_SIZE; i++) { - enb_tx_buffer[i] = ((float)rand() / (float)RAND_MAX) + _Complex_I * ((float)rand() / (float)RAND_MAX); + for (int c = 0; c < NOF_RX_ANT; c++) { + for (int i = 0; i < RF_BUFFER_SIZE; i++) { + enb_tx_buffer[c][i] = ((float)rand() / (float)RAND_MAX) + _Complex_I * ((float)rand() / (float)RAND_MAX); + } } // send data subframe per subframe uint32_t num_txed_samples = 0; + // initial transmission without ts void* data_ptr[SRSRAN_MAX_PORTS] = {NULL}; - data_ptr[0] = &enb_tx_buffer[num_txed_samples]; - int ret = srsran_rf_send_multi(&enb_radio, (void**)data_ptr, SF_LEN, true, true, false); + cf_t tx_buffer[NOF_RX_ANT][SF_LEN]; + for (int c = 0; c < NOF_RX_ANT; c++) { + memcpy(&tx_buffer[c], &enb_tx_buffer[c][num_txed_samples], SF_LEN * sizeof (cf_t)); + data_ptr[c] = &tx_buffer[c][0]; + } + int ret = srsran_rf_send_multi(&enb_radio, (void**)data_ptr, SF_LEN, true, true, false); num_txed_samples += SF_LEN; // from here on, all transmissions are timed relative to the last rx time @@ -96,11 +109,16 @@ void enb_tx_function(const char* tx_args, bool timed_tx) for (uint32_t i = 0; i < NUM_SF - ((timed_tx) ? TX_OFFSET_MS : 1); ++i) { // first recv samples - data_ptr[0] = enb_rx_buffer; + for (int c = 0; c < NOF_RX_ANT; c++) { + data_ptr[c] = enb_rx_buffer[c]; + } srsran_rf_recv_with_time_multi(&enb_radio, data_ptr, SF_LEN, true, &rx_time.full_secs, &rx_time.frac_secs); // prepare data buffer - data_ptr[0] = &enb_tx_buffer[num_txed_samples]; + for (int c = 0; c < NOF_RX_ANT; c++) { + memcpy(&tx_buffer[c], &enb_tx_buffer[c][num_txed_samples], SF_LEN * sizeof (cf_t)); + data_ptr[c] = &tx_buffer[c][0]; + } if (timed_tx) { // timed tx relative to receive time (this will cause a cap in the rx'ed samples at the UE resulting in 3 zero @@ -148,25 +166,46 @@ int run_test(const char* rx_args, const char* tx_args, bool timed_tx) // wait for rx thread pthread_join(rx_thread, NULL); - // subframe-wise compare tx'ed and rx'ed data (stop 3 subframes earlier for timed tx) - for (uint32_t i = 0; i < NUM_SF - (timed_tx ? 3 : 0); ++i) { - uint32_t sf_offet = 0; - if (timed_tx && i >= 1) { - // for timed transmission, the enb inserts 3 zero subframes after the first untimed tx - sf_offet = (TX_OFFSET_MS - 1) * SF_LEN; - } + // channel-wise comparison + for (int c = 0; c < NOF_RX_ANT; c++) { + // subframe-wise compare tx'ed and rx'ed data (stop 3 subframes earlier for timed tx) + for (uint32_t i = 0; i < NUM_SF - (timed_tx ? 3 : 0); ++i) { + uint32_t sf_offet = 0; + if (timed_tx && i >= 1) { + // for timed transmission, the enb inserts 3 zero subframes after the first untimed tx + sf_offet = (TX_OFFSET_MS - 1) * SF_LEN; + } -#if 0 - // print first 3 samples for each SF - printf("enb_tx_buffer sf%d:\n", i); - srsran_vec_fprint_c(stdout, &enb_tx_buffer[i * SF_LEN], 3); - printf("ue_rx_buffer sf%d:\n", i); - srsran_vec_fprint_c(stdout, &ue_rx_buffer[sf_offet + i * SF_LEN], 3); +#if PRINT_SAMPLES + // print first 10 samples for each SF + printf("enb_tx_buffer sf%d:\n", i); + srsran_vec_fprint_c(stdout, &enb_tx_buffer[c][i * SF_LEN], 10); + printf("ue_rx_buffer sf%d:\n", i); + srsran_vec_fprint_c(stdout, &ue_rx_buffer[c][sf_offet + i * SF_LEN], 10); #endif - if (memcmp(&ue_rx_buffer[sf_offet + i * SF_LEN], &enb_tx_buffer[i * SF_LEN], SF_LEN) != 0) { - fprintf(stderr, "data mismatch in subframe %d\n", i); - goto exit; +#if COMPARE_BITS + int d = memcmp(&ue_rx_buffer[sf_offet + i * SF_LEN], &enb_tx_buffer[i * SF_LEN], SF_LEN); + if (d) { + d = d > 0 ? d : -d; + fprintf(stderr, "data mismatch in subframe %d, sample %d\n", i, d); + printf("enb_tx_buffer sf%d:\n", i); + srsran_vec_fprint_c(stdout, &enb_tx_buffer[i * SF_LEN + d], 10); + printf("ue_rx_buffer sf%d:\n", i); + srsran_vec_fprint_c(stdout, &ue_rx_buffer[sf_offet + i * SF_LEN + d], 10); + goto exit; + } +#else + srsran_vec_sub_ccc(&ue_rx_buffer[c][sf_offet + i * SF_LEN], + &enb_tx_buffer[c][i * SF_LEN], + &ue_rx_buffer[c][sf_offet + i * SF_LEN], + SF_LEN); + uint32_t max_ix = srsran_vec_max_abs_ci(&ue_rx_buffer[c][sf_offet + i * SF_LEN], SF_LEN); + if (cabsf(ue_rx_buffer[c][sf_offet + i * SF_LEN + max_ix]) > COMPARE_EPSILON) { + fprintf(stderr, "data mismatch in subframe %d\n", i); + goto exit; + } +#endif } } @@ -195,56 +234,76 @@ int param_test(const char* args_param, const int num_channels) int main() { - // two Rx ports - if (param_test("rx_port=ipc://dl0,rx_port1=ipc://dl1", 2)) { - fprintf(stderr, "Param test failed!\n"); - return SRSRAN_ERROR; - } +// // two Rx ports +// if (param_test("rx_port=ipc://dl0,rx_port1=ipc://dl1", 2)) { +// fprintf(stderr, "Param test failed!\n"); +// return SRSRAN_ERROR; +// } - // multiple rx ports, no channel index provided - if (param_test("rx_port=ipc://dl0,rx_port=ipc://dl1,rx_port=ipc://dl2,rx_port=ipc://dl3,base_srate=1.92e6", 4)) { - fprintf(stderr, "Param test failed!\n"); - return SRSRAN_ERROR; - } +// // multiple rx ports, no channel index provided +// if (param_test("rx_port=ipc://dl0,rx_port=ipc://dl1,rx_port=ipc://dl2,rx_port=ipc://dl3,base_srate=1.92e6", 4)) { +// fprintf(stderr, "Param test failed!\n"); +// return SRSRAN_ERROR; +// } - // One Rx, one Tx and all generic options - if (param_test("rx_port0=tcp://" - "localhost:2000,rx_format=sc16,tx_format=sc16,tx_type=pub,rx_type=sub,base_srate=1.92e6,id=test", - 1)) { - fprintf(stderr, "Param test failed!\n"); - return SRSRAN_ERROR; - } +// // One Rx, one Tx and all generic options +// if (param_test("rx_port0=tcp://" +// "localhost:2000,rx_format=sc16,tx_format=sc16,tx_type=pub,rx_type=sub,base_srate=1.92e6,id=test", +// 1)) { +// fprintf(stderr, "Param test failed!\n"); +// return SRSRAN_ERROR; +// } - // 1 port, 2 antennas, MIMO freq config - if (param_test( - "tx_port0=tcp://*:2001,tx_port1=tcp://*:2003,rx_port0=tcp://localhost:2000,rx_port1=tcp://" - "localhost:2002,id=ue,base_srate=23.04e6,tx_freq0=2510e6,tx_freq1=2510e6,rx_freq0=2630e6,,rx_freq1=2630e6", - 2)) { - fprintf(stderr, "Param test failed!\n"); - return SRSRAN_ERROR; - } +// // 1 port, 2 antennas, MIMO freq config +// if (param_test( +// "tx_port0=tcp://*:2001,tx_port1=tcp://*:2003,rx_port0=tcp://localhost:2000,rx_port1=tcp://" +// "localhost:2002,id=ue,base_srate=23.04e6,tx_freq0=2510e6,tx_freq1=2510e6,rx_freq0=2630e6,,rx_freq1=2630e6", +// 2)) { +// fprintf(stderr, "Param test failed!\n"); +// return SRSRAN_ERROR; +// } +#if NOF_RX_ANT == 1 // single tx, single rx with continuous transmissions (no timed tx) using IPC transport if (run_test("rx_port=ipc://link1,id=ue,base_srate=1.92e6", "tx_port=ipc://link1,id=enb,base_srate=1.92e6", false) != SRSRAN_SUCCESS) { fprintf(stderr, "Single tx, single rx test failed!\n"); return -1; } +#endif - // two trx radios with continous tx (no timed tx) using TCP transport for both directions - if (run_test("tx_port=tcp://*:5554,rx_port=tcp://" - "localhost:5555,id=ue,base_srate=1.92e6,log_trx_timeout=true,trx_timeout_ms=1000", - "rx_port=tcp://localhost:5554,tx_port=tcp://*:5555,id=enb,base_srate=1.92e6", + // up to 4 trx radios with continous tx (no decimation, no timed tx) + if (run_test("tx_port=tcp://*:5554,tx_port=tcp://*:5556,tx_port=tcp://*:5558,tx_port=tcp://*:5560,rx_port=tcp://" + "localhost:5555,rx_port=tcp://localhost:5557,rx_port=tcp://localhost:5559,rx_port=tcp://" + "localhost:5561,id=ue,base_srate=1.92e6,log_trx_timeout=true,trx_timeout_ms=1000", + "rx_port=tcp://localhost:5554,rx_port=tcp://localhost:5556,rx_port=tcp://localhost:5558,rx_port=tcp://" + "localhost:5560,tx_port=tcp://*:5555,tx_port=tcp://*:5557,tx_port=tcp://*:5559,tx_port=tcp://" + "*:5561,id=enb,base_srate=1.92e6", false) != SRSRAN_SUCCESS) { - fprintf(stderr, "Two TRx radio test failed!\n"); + fprintf(stderr, "Multi TRx radio test failed!\n"); return -1; } - // two trx radios with continous tx (no timed tx) using TCP for UL (UE tx) and IPC for eNB DL (eNB tx) - if (run_test("tx_port=tcp://*:5554,rx_port=ipc://dl,id=ue,base_srate=1.92e6", - "rx_port=tcp://localhost:5554,tx_port=ipc://dl,id=enb,base_srate=1.92e6", + // up to 4 trx radios with continous tx (timed tx) using TCP for UL (UE tx) and IPC for eNB DL (eNB tx) + if (run_test("tx_port=tcp://*:5554,tx_port=tcp://*:5556,tx_port=tcp://*:5558,tx_port=tcp://*:5560,rx_port=ipc://" + "dl0,rx_port=ipc://dl1,rx_port=ipc://dl2,rx_port=ipc://dl3,id=ue,base_srate=1.92e6", + "rx_port=tcp://localhost:5554,rx_port=tcp://localhost:5556,rx_port=tcp://localhost:5558,rx_port=tcp://" + "localhost:5560,tx_port=ipc://dl0,tx_port=ipc://dl1,tx_port=ipc://dl2,tx_port=ipc://" + "dl3,id=enb,base_srate=1.92e6", true) != SRSRAN_SUCCESS) { - fprintf(stderr, "Two TRx radio test with timed tx failed!\n"); + fprintf(stderr, "Multi TRx radio test with timed tx failed!\n"); + return -1; + } + + // up to 4 trx radios with continous tx (timed tx) using TCP for UL (UE tx) and IPC for eNB DL (eNB tx) + // with decimation 23.04e6 <-> 1.92e6 + if (run_test("tx_port=tcp://*:5554,tx_port=tcp://*:5556,tx_port=tcp://*:5558,tx_port=tcp://*:5560,rx_port=ipc://" + "dl0,rx_port=ipc://dl1,rx_port=ipc://dl2,rx_port=ipc://dl3,id=ue,base_srate=23.04e6", + "rx_port=tcp://localhost:5554,rx_port=tcp://localhost:5556,rx_port=tcp://localhost:5558,rx_port=tcp://" + "localhost:5560,tx_port=ipc://dl0,tx_port=ipc://dl1,tx_port=ipc://dl2,tx_port=ipc://" + "dl3,id=enb,base_srate=23.04e6", + true) != SRSRAN_SUCCESS) { + fprintf(stderr, "Multi TRx radio test with timed tx and decimation failed!\n"); return -1; } From c3596cc684904c5935520cf11dc2fb920cfa2349 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 26 Jan 2022 18:54:54 +0100 Subject: [PATCH 37/41] ue_nas_interfaces.h: set default APN type to ipv4 --- lib/include/srsran/interfaces/ue_nas_interfaces.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/include/srsran/interfaces/ue_nas_interfaces.h b/lib/include/srsran/interfaces/ue_nas_interfaces.h index a96f1372a..c658fce50 100644 --- a/lib/include/srsran/interfaces/ue_nas_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nas_interfaces.h @@ -29,7 +29,7 @@ class pdu_session_cfg_t { public: std::string apn_name; - apn_types apn_type; + apn_types apn_type = ipv4; std::string apn_user; std::string apn_pass; }; From d71f4152cd55843ed77da00e0d813e3d6678cfd6 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 26 Jan 2022 18:55:39 +0100 Subject: [PATCH 38/41] ue: register PDU session at bearer manager to NAS doesn't trigger service request * forward service request to NAS 5G in SA mode * register PDU session at bearer manager so service request isn't triggered in the first place * remove [TTI] from GW logs --- srsue/src/stack/rrc_nr/rrc_nr.cc | 2 ++ srsue/src/stack/ue_stack_lte.cc | 8 +++++++- srsue/src/ue.cc | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index 9b101cbd5..2dbde5a8c 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -1928,6 +1928,8 @@ bool rrc_nr::apply_drb_add_mod(const drb_to_add_mod_s& drb_cfg) } // TODO: configure SDAP accordingly uint32_t pdu_session_id = drb_cfg.cn_assoc.sdap_cfg().pdu_session; + // Register PDU session as "EPS bearer" in bearer manager + stack->add_eps_bearer(pdu_session_id, srsran::srsran_rat_t::nr, lcid); } else { logger.error("CN association type not supported %s", drb_cfg.cn_assoc.type().to_string()); return false; diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 9a0414e7e..15bff495b 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -328,7 +328,13 @@ bool ue_stack_lte::disable_data() bool ue_stack_lte::start_service_request() { if (running) { - ue_task_queue.try_push([this]() { nas.start_service_request(srsran::establishment_cause_t::mo_data); }); + ue_task_queue.try_push([this]() { + if (args.attach_on_nr) { + nas_5g.start_service_request(); + } else { + nas.start_service_request(srsran::establishment_cause_t::mo_data); + } + }); } return true; } diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 765f964f6..50a728095 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -62,7 +62,7 @@ int ue::init(const all_args_t& args_) return SRSRAN_ERROR; } - std::unique_ptr gw_ptr(new gw(srslog::fetch_basic_logger("GW"))); + std::unique_ptr gw_ptr(new gw(srslog::fetch_basic_logger("GW", false))); if (!gw_ptr) { srsran::console("Error creating a GW instance.\n"); return SRSRAN_ERROR; From 4890ee98758f4b37a90db6903d986510cc123b48 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 25 Jan 2022 21:43:42 +0100 Subject: [PATCH 39/41] ue,rrc: add RRC metrics and fix stdout --- srsue/hdr/stack/rrc_nr/rrc_nr.h | 11 +-------- srsue/hdr/stack/rrc_nr/rrc_nr_metrics.h | 32 +++++++++++++++++++++++++ srsue/hdr/ue_metrics_interface.h | 3 ++- srsue/src/metrics_stdout.cc | 23 +++++++++++------- srsue/src/stack/rrc_nr/rrc_nr.cc | 8 +++++-- srsue/src/stack/ue_stack_lte.cc | 1 + 6 files changed, 56 insertions(+), 22 deletions(-) create mode 100644 srsue/hdr/stack/rrc_nr/rrc_nr_metrics.h diff --git a/srsue/hdr/stack/rrc_nr/rrc_nr.h b/srsue/hdr/stack/rrc_nr/rrc_nr.h index fc9b3c6cc..f01525f4b 100644 --- a/srsue/hdr/stack/rrc_nr/rrc_nr.h +++ b/srsue/hdr/stack/rrc_nr/rrc_nr.h @@ -15,6 +15,7 @@ #include "../rrc/rrc_cell.h" #include "rrc_nr_config.h" +#include "rrc_nr_metrics.h" #include "srsran/adt/circular_map.h" #include "srsran/asn1/rrc_nr.h" #include "srsran/asn1/rrc_nr_utils.h" @@ -35,8 +36,6 @@ class usim_interface_rrc_nr; class pdcp_interface_rrc; class rlc_interface_rrc; -struct rrc_nr_metrics_t {}; - class rrc_nr final : public rrc_interface_phy_nr, public rrc_interface_pdcp, public rrc_interface_rlc, @@ -185,14 +184,6 @@ private: uint32_t sim_measurement_carrier_freq_r15; srsran::timer_handler::unique_timer sim_measurement_timer; - /// RRC states (3GPP 38.331 v15.5.1 Sec 4.2.1) - enum rrc_nr_state_t { - RRC_NR_STATE_IDLE = 0, - RRC_NR_STATE_CONNECTED, - RRC_NR_STATE_CONNECTED_INACTIVE, - RRC_NR_STATE_N_ITEMS, - }; - const static char* rrc_nr_state_text[RRC_NR_STATE_N_ITEMS]; rrc_nr_state_t state = RRC_NR_STATE_IDLE; uint8_t transaction_id = 0; diff --git a/srsue/hdr/stack/rrc_nr/rrc_nr_metrics.h b/srsue/hdr/stack/rrc_nr/rrc_nr_metrics.h new file mode 100644 index 000000000..a224f9708 --- /dev/null +++ b/srsue/hdr/stack/rrc_nr/rrc_nr_metrics.h @@ -0,0 +1,32 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSUE_RRC_NR_METRICS_H +#define SRSUE_RRC_NR_METRICS_H + +namespace srsue { + +/// RRC states (3GPP 38.331 v15.5.1 Sec 4.2.1) +enum rrc_nr_state_t { + RRC_NR_STATE_IDLE = 0, + RRC_NR_STATE_CONNECTED, + RRC_NR_STATE_CONNECTED_INACTIVE, + RRC_NR_STATE_N_ITEMS, +}; + +struct rrc_nr_metrics_t { + rrc_nr_state_t state; +}; + +} // namespace srsue + +#endif // SRSUE_RRC_NR_METRICS_H diff --git a/srsue/hdr/ue_metrics_interface.h b/srsue/hdr/ue_metrics_interface.h index 7a42cc3f1..0fdf09957 100644 --- a/srsue/hdr/ue_metrics_interface.h +++ b/srsue/hdr/ue_metrics_interface.h @@ -22,6 +22,7 @@ #include "srsran/system/sys_metrics.h" #include "stack/mac/mac_metrics.h" #include "stack/rrc/rrc_metrics.h" +#include "stack/rrc_nr/rrc_nr_metrics.h" #include "stack/upper/gw_metrics.h" #include "stack/upper/nas_metrics.h" @@ -34,7 +35,7 @@ typedef struct { srsran::rlc_metrics_t rlc; nas_metrics_t nas; rrc_metrics_t rrc; - rrc_metrics_t rrc_nr; + rrc_nr_metrics_t rrc_nr; } stack_metrics_t; typedef struct { diff --git a/srsue/src/metrics_stdout.cc b/srsue/src/metrics_stdout.cc index 3f7533df9..b03f760a1 100644 --- a/srsue/src/metrics_stdout.cc +++ b/srsue/src/metrics_stdout.cc @@ -181,7 +181,7 @@ void metrics_stdout::set_metrics(const ue_metrics_t& metrics, const uint32_t per return; } - if (metrics.stack.rrc.state != RRC_STATE_CONNECTED) { + if (metrics.stack.rrc.state != RRC_STATE_CONNECTED && metrics.stack.rrc_nr.state != RRC_NR_STATE_CONNECTED) { fmt::print("--- disconnected ---\n"); return; } @@ -193,25 +193,30 @@ void metrics_stdout::set_metrics(const ue_metrics_t& metrics, const uint32_t per display_neighbours |= metrics.stack.rrc.neighbour_cells.size() > 0; } - bool is_nr = metrics.phy_nr.nof_active_cc > 0; + bool has_lte = metrics.phy.nof_active_cc > 0; + bool has_nr = metrics.phy_nr.nof_active_cc > 0; // print table header every 10 reports if (++n_reports > 10) { - print_table(display_neighbours, is_nr); + print_table(display_neighbours, has_nr); } // also print table header if neighbours are added/removed in between if (display_neighbours != table_has_neighbours) { - print_table(display_neighbours, is_nr); + print_table(display_neighbours, has_nr); } - for (uint32_t r = 0; r < metrics.phy.nof_active_cc; r++) { - set_metrics_helper(metrics.phy, metrics.stack.mac, metrics.stack.rrc, display_neighbours, r, false, !is_nr); + if (has_lte) { + for (uint32_t r = 0; r < metrics.phy.nof_active_cc; r++) { + set_metrics_helper(metrics.phy, metrics.stack.mac, metrics.stack.rrc, display_neighbours, r, false, !has_nr); + } } - for (uint32_t r = 0; r < metrics.phy_nr.nof_active_cc; r++) { - // Assumption LTE is followed by the NR carriers. - set_metrics_helper(metrics.phy_nr, metrics.stack.mac_nr, metrics.stack.rrc, display_neighbours, r, true, !is_nr); + if (has_nr) { + for (uint32_t r = 0; r < metrics.phy_nr.nof_active_cc; r++) { + // Assumption LTE is followed by the NR carriers. + set_metrics_helper(metrics.phy_nr, metrics.stack.mac_nr, metrics.stack.rrc, display_neighbours, r, true, !has_nr); + } } if (metrics.rf.rf_error) { diff --git a/srsue/src/stack/rrc_nr/rrc_nr.cc b/srsue/src/stack/rrc_nr/rrc_nr.cc index 2dbde5a8c..581641188 100644 --- a/srsue/src/stack/rrc_nr/rrc_nr.cc +++ b/srsue/src/stack/rrc_nr/rrc_nr.cc @@ -25,7 +25,7 @@ using namespace asn1; using namespace srsran; namespace srsue { -const char* rrc_nr::rrc_nr_state_text[] = {"IDLE", "CONNECTED", "CONNECTED-INACTIVE"}; +const static char* rrc_nr_state_text[] = {"IDLE", "CONNECTED", "CONNECTED-INACTIVE"}; rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : logger(srslog::fetch_basic_logger("RRC-NR")), @@ -101,7 +101,11 @@ void rrc_nr::init_core_less() pdcp->add_bearer(args.coreless.drb_lcid, pdcp_cnfg); return; } -void rrc_nr::get_metrics(rrc_nr_metrics_t& m) {} + +void rrc_nr::get_metrics(rrc_nr_metrics_t& m) +{ + m.state = state; +} const char* rrc_nr::get_rb_name(uint32_t lcid) { diff --git a/srsue/src/stack/ue_stack_lte.cc b/srsue/src/stack/ue_stack_lte.cc index 15bff495b..63ddada6e 100644 --- a/srsue/src/stack/ue_stack_lte.cc +++ b/srsue/src/stack/ue_stack_lte.cc @@ -350,6 +350,7 @@ bool ue_stack_lte::get_metrics(stack_metrics_t* metrics) rlc.get_metrics(metrics.rlc, metrics.mac[0].nof_tti); nas.get_metrics(&metrics.nas); rrc.get_metrics(metrics.rrc); + rrc_nr.get_metrics(metrics.rrc_nr); pending_stack_metrics.push(metrics); }); // wait for result From e3b95de5e0d8ffc427afd9a84a950fa89c8a7157 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 27 Jan 2022 11:43:43 +0100 Subject: [PATCH 40/41] ue,metrics_test: add testcases for EUTRA,NSA, and SA mode --- srsue/src/test/metrics_test.cc | 134 +++++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 25 deletions(-) diff --git a/srsue/src/test/metrics_test.cc b/srsue/src/test/metrics_test.cc index d1d9bc1be..b68b4d341 100644 --- a/srsue/src/test/metrics_test.cc +++ b/srsue/src/test/metrics_test.cc @@ -11,7 +11,7 @@ */ #include "srsran/common/metrics_hub.h" -#include "srsran/srsran.h" +#include "srsran/common/test_common.h" #include "srsue/hdr/metrics_csv.h" #include "srsue/hdr/metrics_stdout.h" #include "srsue/hdr/ue_metrics_interface.h" @@ -25,10 +25,12 @@ using namespace srsue; namespace srsue { -char* csv_file_name = NULL; +static char* csv_file_name = NULL; +static float period = 1.0; +static int duration_s = 5; // fake classes -class ue_dummy : public ue_metrics_interface +class eutra_ue_dummy : public ue_metrics_interface { public: bool get_metrics(ue_metrics_t* m) @@ -63,6 +65,51 @@ public: m->phy.nof_active_cc = 1; m->phy.ch[0].rsrp = -10.0f; m->phy.ch[0].pathloss = 32; + + m->stack.rrc.state = (rand() % 2 == 0) ? RRC_STATE_CONNECTED : RRC_STATE_IDLE; + + return true; + } +}; + +class nsa_ue_dummy : public ue_metrics_interface +{ +public: + bool get_metrics(ue_metrics_t* m) + { + *m = {}; + + // fill dummy values + m->rf.rf_o = 10; + m->phy.nof_active_cc = 1; + m->phy.ch[0].rsrp = -10.0f; + m->phy.ch[0].pathloss = 74; + m->stack.mac[0].rx_pkts = 100; + m->stack.mac[0].rx_errors = 0; + m->stack.mac[0].rx_brate = 200; + m->stack.mac[0].nof_tti = 1; + + m->phy.info[1].pci = UINT32_MAX; + m->stack.mac[1].rx_pkts = 100; + m->stack.mac[1].rx_errors = 100; + m->stack.mac[1].rx_brate = 150; + m->stack.mac[1].nof_tti = 1; + + // random neighbour cells + if (rand() % 2 == 0) { + phy_meas_t neighbor = {}; + neighbor.pci = 8; + neighbor.rsrp = -33; + m->stack.rrc.neighbour_cells.push_back(neighbor); + m->stack.rrc.neighbour_cells.push_back(neighbor); // need to add twice since we use CA + } + + m->phy.nof_active_cc = 1; + m->phy.ch[0].rsrp = -10.0f; + m->phy.ch[0].pathloss = 32; + + // NR + m->phy_nr.nof_active_cc = 1; m->stack.mac_nr[0].rx_pkts = 100; m->stack.mac_nr[0].rx_errors = 2; m->stack.mac_nr[0].rx_brate = 223; @@ -74,6 +121,31 @@ public: } }; +class sa_ue_dummy : public ue_metrics_interface +{ +public: + bool get_metrics(ue_metrics_t* m) + { + *m = {}; + + // fill dummy values + m->rf.rf_o = 10; + m->phy.nof_active_cc = 0; + + // NR + m->phy_nr.nof_active_cc = 1; + m->phy_nr.info[0].pci = 501; + m->stack.mac_nr[0].rx_pkts = 100; + m->stack.mac_nr[0].rx_errors = 2; + m->stack.mac_nr[0].rx_brate = 223; + m->stack.mac_nr[0].nof_tti = 1; + + m->stack.rrc_nr.state = (rand() % 2 == 0) ? RRC_NR_STATE_CONNECTED : RRC_NR_STATE_IDLE; + + return true; + } +}; + } // namespace srsue void usage(char* prog) @@ -101,11 +173,35 @@ void parse_args(int argc, char** argv) } } +int ue_test(std::string name, ue_metrics_interface* ue) +{ + // the default metrics type for stdout output + metrics_stdout metrics_screen; + metrics_screen.set_ue_handle(ue); + + // the CSV file writer + metrics_csv metrics_file(csv_file_name); + metrics_file.set_ue_handle(ue); + + // create metrics hub and register metrics for stdout + srsran::metrics_hub metricshub; + metricshub.init(ue, period); + metricshub.add_listener(&metrics_screen); + metricshub.add_listener(&metrics_file); + + // enable printing + metrics_screen.toggle_print(true); + + std::cout << "Running " << name << " UE test for " << duration_s << " seconds .." << std::endl; + usleep(duration_s * 1e6); + + metricshub.stop(); + + return SRSRAN_SUCCESS; +} + int main(int argc, char** argv) { - float period = 1.0; - ue_dummy ue; - if (argc < 3) { usage(argv[0]); exit(-1); @@ -113,26 +209,14 @@ int main(int argc, char** argv) parse_args(argc, argv); - // the default metrics type for stdout output - metrics_stdout metrics_screen; - metrics_screen.set_ue_handle(&ue); + eutra_ue_dummy eutra_ue; + TESTASSERT_SUCCESS(ue_test("EUTRA", &eutra_ue)); - // the CSV file writer - metrics_csv metrics_file(csv_file_name); - metrics_file.set_ue_handle(&ue); + nsa_ue_dummy nsa_ue; + TESTASSERT_SUCCESS(ue_test("NSA", &nsa_ue)); - // create metrics hub and register metrics for stdout - srsran::metrics_hub metricshub; - metricshub.init(&ue, period); - metricshub.add_listener(&metrics_screen); - metricshub.add_listener(&metrics_file); + sa_ue_dummy sa_ue; + TESTASSERT_SUCCESS(ue_test("SA", &sa_ue)); - // enable printing - metrics_screen.toggle_print(true); - - std::cout << "Running for 5 seconds .." << std::endl; - usleep(5e6); - - metricshub.stop(); - return 0; + return SRSRAN_SUCCESS; } From c99ecd80095421de49f0fe606a367fc4f1d20bbd Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 26 Jan 2022 18:17:21 +0000 Subject: [PATCH 41/41] enb,s1ap: make sure we don't processa the ICS request if there is an ICS already on-going. --- srsenb/hdr/stack/s1ap/s1ap.h | 3 ++- srsenb/src/stack/s1ap/s1ap.cc | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/srsenb/hdr/stack/s1ap/s1ap.h b/srsenb/hdr/stack/s1ap/s1ap.h index 0f37ef5ae..0698dbc08 100644 --- a/srsenb/hdr/stack/s1ap/s1ap.h +++ b/srsenb/hdr/stack/s1ap/s1ap.h @@ -107,7 +107,7 @@ public: // Stack interface bool - handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); void start_pcap(srsran::s1ap_pcap* pcap_); private: @@ -261,6 +261,7 @@ private: void set_state(s1ap_proc_id_t state, const erab_id_list& erabs_updated, const erab_item_list& erabs_failed_to_update); + s1ap_proc_id_t get_state() const { return current_state; } ue_ctxt_t ctxt = {}; uint16_t stream_id = 1; diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index 27dc1ecc4..6bb4174a8 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -776,6 +776,14 @@ bool s1ap::handle_initialctxtsetuprequest(const init_context_setup_request_s& ms return false; } + if (u->get_state() == s1ap_proc_id_t::init_context_setup_request) { + logger.warning("Initial Context Setup Request already in progress. Ignoring ICS request."); + asn1::s1ap::cause_c cause; + cause.set_protocol().value = cause_protocol_opts::msg_not_compatible_with_receiver_state; + send_error_indication(cause, msg->enb_ue_s1ap_id.value.value, msg->mme_ue_s1ap_id.value.value); + return false; + } + // Setup UE ctxt in RRC if (not rrc->setup_ue_ctxt(u->ctxt.rnti, msg)) { return false; @@ -1990,6 +1998,9 @@ s1ap::ue* s1ap::handle_s1apmsg_ue_id(uint32_t enb_id, uint32_t mme_id) ue* user_ptr = users.find_ue_enbid(enb_id); ue* user_mme_ptr = nullptr; cause_c cause; + + logger.info("Checking UE S1 logical connection. eNB UE S1AP ID=%d, MME UE S1AP ID=%d", enb_id, mme_id); + if (user_ptr != nullptr) { if (user_ptr->ctxt.mme_ue_s1ap_id == mme_id) { // No ID inconsistency found