From 8d802e2acae057d5bf5d64982269394783248c34 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 10:57:18 +0200 Subject: [PATCH 01/39] Fix a data race in the simulate_rf global variable. --- srsue/src/main.cc | 4 ++-- srsue/src/stack/rrc/rrc.cc | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 15a5a0c12..fa1f9825f 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -34,7 +34,7 @@ #include #include -extern bool simulate_rlf; +extern std::atomic simulate_rlf; using namespace std; using namespace srsue; @@ -639,7 +639,7 @@ static void* input_loop(void*) metrics_screen->toggle_print(do_metrics); } } else if (key == "rlf") { - simulate_rlf = true; + simulate_rlf.store(true, std::memory_order_relaxed); cout << "Sending Radio Link Failure" << endl; } else if (key == "q") { // let the signal handler do the job diff --git a/srsue/src/stack/rrc/rrc.cc b/srsue/src/stack/rrc/rrc.cc index 03d1d6843..0ce979318 100644 --- a/srsue/src/stack/rrc/rrc.cc +++ b/srsue/src/stack/rrc/rrc.cc @@ -32,7 +32,7 @@ #include #include -bool simulate_rlf = false; +std::atomic simulate_rlf{false}; using namespace srsran; using namespace asn1::rrc; @@ -203,9 +203,9 @@ void rrc::run_tti() return; } - if (simulate_rlf) { + if (simulate_rlf.load(std::memory_order_relaxed)) { radio_link_failure_process(); - simulate_rlf = false; + simulate_rlf.store(false, std::memory_order_relaxed); } // Process pending PHY measurements in IDLE/CONNECTED @@ -2779,7 +2779,7 @@ void rrc::release_drb(uint32_t drb_id) */ uint32_t rrc::get_lcid_for_drb_id(const uint32_t& drb_id) { - uint32_t lcid = 0; + uint32_t lcid = 0; if (drbs.find(drb_id) != drbs.end()) { asn1::rrc::drb_to_add_mod_s drb_cnfg = drbs[drb_id]; if (drb_cnfg.lc_ch_id_present) { From d009160ba6608af7b43f106b86b6dd332fe045f6 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 11:31:24 +0200 Subject: [PATCH 02/39] Fix data race in the metrics of the rlc. --- lib/include/srsran/rlc/rlc_am_lte.h | 2 ++ lib/src/rlc/rlc_am_lte.cc | 36 +++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index 468b5cab6..4d235bff2 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -328,6 +328,7 @@ public: srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srsran::timer_handler* timers_); + bool configure(const rlc_config_t& cfg_); void reestablish(); void stop(); @@ -555,6 +556,7 @@ private: rlc_am_lte_tx tx; rlc_am_lte_rx rx; + std::mutex metrics_mutex; rlc_bearer_metrics_t metrics = {}; }; diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index b5d691137..700d79265 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -203,13 +203,19 @@ uint32_t rlc_am_lte::get_bearer() rlc_bearer_metrics_t rlc_am_lte::get_metrics() { // update values that aren't calculated on the fly - metrics.rx_latency_ms = rx.get_sdu_rx_latency_ms(); - metrics.rx_buffered_bytes = rx.get_rx_buffered_bytes(); + uint32_t latency = rx.get_sdu_rx_latency_ms(); + uint32_t buffered_bytes = rx.get_rx_buffered_bytes(); + + std::lock_guard lock(metrics_mutex); + metrics.rx_latency_ms = latency; + metrics.rx_buffered_bytes = buffered_bytes; + return metrics; } void rlc_am_lte::reset_metrics() { + std::lock_guard lock(metrics_mutex); metrics = {}; } @@ -220,6 +226,7 @@ void rlc_am_lte::reset_metrics() void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu) { if (tx.write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) { + std::lock_guard lock(metrics_mutex); metrics.num_tx_sdus++; } } @@ -227,6 +234,8 @@ void rlc_am_lte::write_sdu(unique_byte_buffer_t sdu) void rlc_am_lte::discard_sdu(uint32_t discard_sn) { tx.discard_sdu(discard_sn); + + std::lock_guard lock(metrics_mutex); metrics.num_lost_sdus++; } @@ -252,14 +261,19 @@ uint32_t rlc_am_lte::get_buffer_state() uint32_t rlc_am_lte::read_pdu(uint8_t* payload, uint32_t nof_bytes) { uint32_t read_bytes = tx.read_pdu(payload, nof_bytes); + + std::lock_guard lock(metrics_mutex); metrics.num_tx_pdus++; metrics.num_tx_pdu_bytes += read_bytes; + return read_bytes; } void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes) { rx.write_pdu(payload, nof_bytes); + + std::lock_guard lock(metrics_mutex); metrics.num_rx_pdus++; metrics.num_rx_pdu_bytes += nof_bytes; } @@ -407,6 +421,8 @@ void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn) pdcp_sns.push_back(segment.pdcp_sn()); } parent->pdcp->notify_failure(parent->lcid, pdcp_sns); + + std::lock_guard lock(parent->metrics_mutex); parent->metrics.num_lost_pdus++; } } @@ -1758,7 +1774,10 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp()) .count()); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); - parent->metrics.num_rx_sdus++; + { + std::lock_guard lock(parent->metrics_mutex); + parent->metrics.num_rx_sdus++; + } rx_sdu = srsran::make_byte_buffer(); if (rx_sdu == nullptr) { @@ -1808,7 +1827,10 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus() std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp()) .count()); parent->pdcp->write_pdu(parent->lcid, std::move(rx_sdu)); - parent->metrics.num_rx_sdus++; + { + std::lock_guard lock(parent->metrics_mutex); + parent->metrics.num_rx_sdus++; + } rx_sdu = srsran::make_byte_buffer(); if (rx_sdu == NULL) { @@ -1985,9 +2007,9 @@ int rlc_am_lte::rlc_am_lte_rx::get_status_pdu_length() if (not lock.owns_lock()) { return 0; } - rlc_status_pdu_t status = {}; - status.ack_sn = vr_ms; - uint32_t i = vr_r; + rlc_status_pdu_t status = {}; + status.ack_sn = vr_ms; + uint32_t i = vr_r; while (RX_MOD_BASE(i) < RX_MOD_BASE(vr_ms) && status.N_nack < RLC_AM_WINDOW_SIZE) { if (not rx_window.has_sn(i)) { status.N_nack++; From d02012b58801631ddc7afb19c6d2a5864039ab6c Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 12:45:55 +0200 Subject: [PATCH 03/39] Fix data race in bsr_proc. --- srsue/src/stack/mac/proc_bsr.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsue/src/stack/mac/proc_bsr.cc b/srsue/src/stack/mac/proc_bsr.cc index a464b4318..4ac7a688b 100644 --- a/srsue/src/stack/mac/proc_bsr.cc +++ b/srsue/src/stack/mac/proc_bsr.cc @@ -113,6 +113,8 @@ void bsr_proc::timer_expired(uint32_t timer_id) uint32_t bsr_proc::get_buffer_state() { + std::lock_guard lock(mutex); + uint32_t buffer = 0; for (int i = 0; i < NOF_LCG; i++) { buffer += get_buffer_state_lcg(i); From 2b73beb3ddf282d8cb51b9354765fabd19f20678 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 12:58:53 +0200 Subject: [PATCH 04/39] Fix data race in ul_harq. --- srsue/hdr/stack/mac/ul_harq.h | 6 +++--- srsue/src/stack/mac/ul_harq.cc | 17 ++++++++++------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/srsue/hdr/stack/mac/ul_harq.h b/srsue/hdr/stack/mac/ul_harq.h index 7507a69d8..8b58a46a2 100644 --- a/srsue/hdr/stack/mac/ul_harq.h +++ b/srsue/hdr/stack/mac/ul_harq.h @@ -100,9 +100,9 @@ private: srsran::ul_harq_cfg_t harq_cfg = {}; - float average_retx = 0.0; - uint64_t nof_pkts = 0; - ra_proc* ra_procedure = nullptr; + std::atomic average_retx{0}; + uint64_t nof_pkts = 0; + ra_proc* ra_procedure = nullptr; uint8_t cc_idx = 0; }; diff --git a/srsue/src/stack/mac/ul_harq.cc b/srsue/src/stack/mac/ul_harq.cc index f7456a9ce..de968b511 100644 --- a/srsue/src/stack/mac/ul_harq.cc +++ b/srsue/src/stack/mac/ul_harq.cc @@ -103,7 +103,7 @@ int ul_harq_entity::get_current_tbs(uint32_t pid) float ul_harq_entity::get_average_retx() { - return average_retx; + return average_retx.load(std::memory_order_relaxed); } ul_harq_entity::ul_harq_process::ul_harq_process() : logger(srslog::fetch_basic_logger("MAC")) @@ -348,12 +348,15 @@ void ul_harq_entity::ul_harq_process::generate_new_tx(mac_interface_phy_lte::mac mac_interface_phy_lte::tb_action_ul_t* action) { // Compute average number of retransmissions per packet considering previous packet - harq_entity->average_retx = SRSRAN_VEC_CMA((float)current_tx_nb, harq_entity->average_retx, harq_entity->nof_pkts++); - cur_grant = grant; - harq_feedback = false; - is_grant_configured = true; - current_tx_nb = 0; - current_irv = 0; + harq_entity->average_retx.store(SRSRAN_VEC_CMA((float)current_tx_nb, + harq_entity->average_retx.load(std::memory_order_relaxed), + harq_entity->nof_pkts++), + std::memory_order_relaxed); + cur_grant = grant; + harq_feedback = false; + is_grant_configured = true; + current_tx_nb = 0; + current_irv = 0; action->is_rar = grant.is_rar || (grant.rnti == harq_entity->rntis->get_temp_rnti()); From 1796e120848d7776f059a8eb7f7f2b0a03777317 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 13:16:28 +0200 Subject: [PATCH 05/39] Fix data race in ul_harq_entity. --- srsue/hdr/stack/mac/ul_harq.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/stack/mac/ul_harq.h b/srsue/hdr/stack/mac/ul_harq.h index 8b58a46a2..b0726d161 100644 --- a/srsue/hdr/stack/mac/ul_harq.h +++ b/srsue/hdr/stack/mac/ul_harq.h @@ -100,9 +100,9 @@ private: srsran::ul_harq_cfg_t harq_cfg = {}; - std::atomic average_retx{0}; - uint64_t nof_pkts = 0; - ra_proc* ra_procedure = nullptr; + std::atomic average_retx{0}; + std::atomic nof_pkts{0}; + ra_proc* ra_procedure = nullptr; uint8_t cc_idx = 0; }; From 7dae4a491e072fb08f1bc2bb5cc696fee346d769 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 13:19:30 +0200 Subject: [PATCH 06/39] Fix data race in ue_stack_lte::ul_dropped_sdus. --- srsue/hdr/stack/ue_stack_lte.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/hdr/stack/ue_stack_lte.h b/srsue/hdr/stack/ue_stack_lte.h index 62aefd034..d7698a40d 100644 --- a/srsue/hdr/stack/ue_stack_lte.h +++ b/srsue/hdr/stack/ue_stack_lte.h @@ -234,7 +234,7 @@ private: ue_bearer_manager bearers; // helper to manage mapping between EPS and radio bearers // Metrics helper - uint32_t ul_dropped_sdus = 0; + std::atomic ul_dropped_sdus{0}; }; } // namespace srsue From f96ee097b4422e7068834cc93356d980bca80d22 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 13:32:30 +0200 Subject: [PATCH 07/39] Fix data race in ue mac metrics. --- srsue/src/stack/mac/mac.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/srsue/src/stack/mac/mac.cc b/srsue/src/stack/mac/mac.cc index 0cfe6b663..e15d3d116 100644 --- a/srsue/src/stack/mac/mac.cc +++ b/srsue/src/stack/mac/mac.cc @@ -146,7 +146,10 @@ void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable) // Implement Section 5.9 void mac::reset() { - bzero(&metrics, sizeof(mac_metrics_t)); + { + std::lock_guard lock(metrics_mutex); + bzero(&metrics, sizeof(mac_metrics_t)); + } Info("Resetting MAC"); @@ -201,6 +204,7 @@ void mac::run_tti(const uint32_t tti) ra_procedure.update_rar_window(ra_window); // Count TTI for metrics + std::lock_guard lock(metrics_mutex); for (uint32_t i = 0; i < SRSRAN_MAX_CARRIERS; i++) { metrics[i].nof_tti++; } @@ -346,10 +350,13 @@ void mac::mch_decoded(uint32_t len, bool crc) pcap->write_dl_mch(mch_payload_buffer, len, true, phy_h->get_current_tti(), 0); } + std::lock_guard lock(metrics_mutex); metrics[0].rx_brate += len * 8; } else { + std::lock_guard lock(metrics_mutex); metrics[0].rx_errors++; } + std::lock_guard lock(metrics_mutex); metrics[0].rx_pkts++; } From 1e3ba607ce30afcfc06b5e6e0e2da2921de603c5 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 13:45:06 +0200 Subject: [PATCH 08/39] Fix data race in is_pending_tx_end. --- srsue/hdr/phy/phy_common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index 88ce146a3..18cc46b7c 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -296,7 +296,7 @@ private: std::mutex mtch_mutex; std::condition_variable mtch_cvar; - bool is_pending_tx_end = false; + std::atomic is_pending_tx_end{false}; srsran::radio_interface_phy* radio_h = nullptr; srslog::basic_logger& logger; From 6b07e886b7a2e1fa78cdc1ebc1ffe76bcdca6502 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 13:45:27 +0200 Subject: [PATCH 09/39] Fix data race in is_first_ul_grant. --- srsue/hdr/stack/mac/mac.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srsue/hdr/stack/mac/mac.h b/srsue/hdr/stack/mac/mac.h index c71c131c7..554958702 100644 --- a/srsue/hdr/stack/mac/mac.h +++ b/srsue/hdr/stack/mac/mac.h @@ -149,8 +149,8 @@ private: srsran::task_multiqueue::queue_handle stack_task_dispatch_queue; // pointer to MAC PCAP object - srsran::mac_pcap* pcap = nullptr; - bool is_first_ul_grant = false; + srsran::mac_pcap* pcap = nullptr; + std::atomic is_first_ul_grant{false}; std::mutex metrics_mutex = {}; mac_metrics_t metrics[SRSRAN_MAX_CARRIERS] = {}; From c2b705c5cea63882e3f6755b605aa7440a722e4f Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 17:10:54 +0200 Subject: [PATCH 10/39] Fix several data races in proc_phr, class needs to be fully protected since most member variables are accessed by different threads. --- srsue/hdr/stack/mac/proc_phr.h | 2 ++ srsue/src/stack/mac/proc_phr.cc | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/srsue/hdr/stack/mac/proc_phr.h b/srsue/hdr/stack/mac/proc_phr.h index 792b40fe2..3cd12f6dc 100644 --- a/srsue/hdr/stack/mac/proc_phr.h +++ b/srsue/hdr/stack/mac/proc_phr.h @@ -52,6 +52,8 @@ private: srsran::timer_handler::unique_timer timer_periodic; srsran::timer_handler::unique_timer timer_prohibit; + + std::mutex mutex; }; } // namespace srsue diff --git a/srsue/src/stack/mac/proc_phr.cc b/srsue/src/stack/mac/proc_phr.cc index e604c6354..07415918a 100644 --- a/srsue/src/stack/mac/proc_phr.cc +++ b/srsue/src/stack/mac/proc_phr.cc @@ -41,6 +41,7 @@ void phr_proc::init(phy_interface_mac_lte* phy_h_, srsran::ext_task_sched_handle void phr_proc::reset() { + std::lock_guard lock(mutex); timer_periodic.stop(); timer_prohibit.stop(); phr_is_triggered = false; @@ -48,6 +49,8 @@ void phr_proc::reset() void phr_proc::set_config(srsran::phr_cfg_t& cfg) { + std::lock_guard lock(mutex); + phr_cfg = cfg; // First stop timers. If enabled==false or value is Inf, won't be re-started @@ -90,6 +93,7 @@ bool phr_proc::pathloss_changed() void phr_proc::start_periodic_timer() { + std::lock_guard lock(mutex); if (phr_cfg.enabled && phr_cfg.periodic_timer > 0) { timer_periodic.run(); } @@ -98,6 +102,7 @@ void phr_proc::start_periodic_timer() /* Trigger PHR when timers exires */ void phr_proc::timer_expired(uint32_t timer_id) { + std::lock_guard lock(mutex); if (!phr_cfg.enabled) { Warning("PHR: %s timer triggered but PHR has been disabled", timer_id == timer_periodic.id() ? "Periodic" : "Prohibit"); @@ -119,6 +124,8 @@ void phr_proc::timer_expired(uint32_t timer_id) void phr_proc::step() { + std::lock_guard lock(mutex); + if (phr_cfg.enabled && initiated) { if (pathloss_changed() && timer_prohibit.is_expired()) { Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d", last_pathloss_db); @@ -129,6 +136,7 @@ void phr_proc::step() bool phr_proc::generate_phr_on_ul_grant(float* phr) { + std::lock_guard lock(mutex); if (phr_is_triggered) { if (phr) { *phr = phy_h->get_phr(); @@ -149,6 +157,7 @@ bool phr_proc::generate_phr_on_ul_grant(float* phr) bool phr_proc::is_extended() { + std::lock_guard lock(mutex); return phr_cfg.extended; } } // namespace srsue From d2f09a8d3ce86bf341eb8eab1f255cd365de1a86 Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 17:39:53 +0200 Subject: [PATCH 11/39] Fix a nasty data race in the ue_bearer_manager class. The underlying std::map member was being accessed concurrently potentially corrupting memory. --- lib/include/srsran/common/bearer_manager.h | 22 +++++++++++++++++----- lib/src/common/bearer_manager.cc | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/include/srsran/common/bearer_manager.h b/lib/include/srsran/common/bearer_manager.h index ad4d07c12..c2bdfc2d4 100644 --- a/lib/include/srsran/common/bearer_manager.h +++ b/lib/include/srsran/common/bearer_manager.h @@ -104,11 +104,23 @@ public: /// All registered bearer are removed (e.g. after connection release) void reset(); - bool has_active_radio_bearer(uint32_t eps_bearer_id) { return impl.has_active_radio_bearer(eps_bearer_id); } - - radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id) { return impl.get_radio_bearer(eps_bearer_id); } - - radio_bearer_t get_lcid_bearer(uint32_t lcid) { return impl.get_lcid_bearer(lcid); } + bool has_active_radio_bearer(uint32_t eps_bearer_id) + { + srsran::rwlock_read_guard rw_lock(rwlock); + return impl.has_active_radio_bearer(eps_bearer_id); + } + + radio_bearer_t get_radio_bearer(uint32_t eps_bearer_id) + { + srsran::rwlock_read_guard rw_lock(rwlock); + return impl.get_radio_bearer(eps_bearer_id); + } + + radio_bearer_t get_lcid_bearer(uint32_t lcid) + { + srsran::rwlock_read_guard rw_lock(rwlock); + return impl.get_lcid_bearer(lcid); + } private: pthread_rwlock_t rwlock = {}; /// RW lock to protect access from RRC/GW threads diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc index 63cbbc92e..8510a1ebe 100644 --- a/lib/src/common/bearer_manager.cc +++ b/lib/src/common/bearer_manager.cc @@ -102,6 +102,7 @@ void ue_bearer_manager::remove_eps_bearer(uint8_t eps_bearer_id) void ue_bearer_manager::reset() { + srsran::rwlock_write_guard rw_lock(rwlock); impl.reset(); logger.info("Bearers: Reset EPS bearer manager"); } From 457dcf4de43d975af5fb0c59ca9f2d604c074fba Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 16:16:47 +0200 Subject: [PATCH 12/39] Fix data race in enb::ta class. --- srsenb/hdr/stack/mac/ta.h | 1 + 1 file changed, 1 insertion(+) diff --git a/srsenb/hdr/stack/mac/ta.h b/srsenb/hdr/stack/mac/ta.h index 1e7591dd9..cc29b0669 100644 --- a/srsenb/hdr/stack/mac/ta.h +++ b/srsenb/hdr/stack/mac/ta.h @@ -199,6 +199,7 @@ public: */ void start() { + std::lock_guard lock(mutex); // Transition to idle only if the current state is idle if (state == state_idle) { state = state_measure; From 8a2231251a3b09c280289f52402dfbe1a87acf5f Mon Sep 17 00:00:00 2001 From: faluco Date: Wed, 15 Sep 2021 16:17:12 +0200 Subject: [PATCH 13/39] Fix data race in enb::mac::ue class. --- srsenb/hdr/stack/mac/ue.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/srsenb/hdr/stack/mac/ue.h b/srsenb/hdr/stack/mac/ue.h index f9040ef5c..9f14d69de 100644 --- a/srsenb/hdr/stack/mac/ue.h +++ b/srsenb/hdr/stack/mac/ue.h @@ -160,20 +160,20 @@ public: srsran_softbuffer_tx_t* get_tx_softbuffer(uint32_t enb_cc_idx, uint32_t harq_process, uint32_t tb_idx); srsran_softbuffer_rx_t* get_rx_softbuffer(uint32_t enb_cc_idx, uint32_t tti); - uint8_t* request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len); - void process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t ue_cc_idx, uint32_t grant_nof_prbs); + uint8_t* request_buffer(uint32_t tti, uint32_t enb_cc_idx, uint32_t len); + void process_pdu(srsran::unique_byte_buffer_t pdu, uint32_t ue_cc_idx, uint32_t grant_nof_prbs); srsran::unique_byte_buffer_t release_pdu(uint32_t tti, uint32_t enb_cc_idx); void clear_old_buffers(uint32_t tti); std::mutex metrics_mutex = {}; - void metrics_read(mac_ue_metrics_t* metrics_); - void metrics_rx(bool crc, uint32_t tbs); - void metrics_tx(bool crc, uint32_t tbs); - void metrics_phr(float phr); - void metrics_dl_ri(uint32_t dl_cqi); - void metrics_dl_pmi(uint32_t dl_cqi); - void metrics_dl_cqi(uint32_t dl_cqi); - void metrics_cnt(); + void metrics_read(mac_ue_metrics_t* metrics_); + void metrics_rx(bool crc, uint32_t tbs); + void metrics_tx(bool crc, uint32_t tbs); + void metrics_phr(float phr); + void metrics_dl_ri(uint32_t dl_cqi); + void metrics_dl_pmi(uint32_t dl_cqi); + void metrics_dl_cqi(uint32_t dl_cqi); + void metrics_cnt(); uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) final; @@ -188,11 +188,11 @@ private: srslog::basic_logger& logger; sched_interface* sched = nullptr; - srsran::mac_pcap* pcap = nullptr; - srsran::mac_pcap_net* pcap_net = nullptr; - uint64_t conres_id = 0; - uint16_t rnti = 0; - uint32_t last_tti = 0; + srsran::mac_pcap* pcap = nullptr; + srsran::mac_pcap_net* pcap_net = nullptr; + uint64_t conres_id = 0; + uint16_t rnti = 0; + std::atomic last_tti{0}; uint32_t nof_failures = 0; std::atomic active_state{true}; From 8d49e580787a92bb71dd130c691a5896a31cc479 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 13 Sep 2021 15:55:43 +0200 Subject: [PATCH 14/39] enb: prepare split of EUTRA and NR stack classes this allows for a slimmer base station if only EUTRA or NR cells are used. also it seperates entities in a cleaner way --- srsenb/hdr/enb.h | 3 +- srsenb/src/enb.cc | 103 ++++++++++++++++++++++++++++------------------ 2 files changed, 64 insertions(+), 42 deletions(-) diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 57c400aee..890862759 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -155,7 +155,8 @@ private: rrc_cfg_t rrc_cfg = {}; // eNB components - std::unique_ptr stack = nullptr; + std::unique_ptr eutra_stack = nullptr; + std::unique_ptr nr_stack = nullptr; std::unique_ptr radio = nullptr; std::unique_ptr phy = nullptr; diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index b0c6fd851..009a09c1b 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -30,7 +30,8 @@ enb::enb(srslog::sink& log_sink) : enb::~enb() { - stack.reset(); + eutra_stack.reset(); + nr_stack.reset(); } int enb::init(const all_args_t& args_) @@ -50,54 +51,68 @@ int enb::init(const all_args_t& args_) srsran::byte_buffer_pool::get_instance()->enable_logger(true); // Create layers - if (args.stack.type == "lte") { - std::unique_ptr lte_stack(new enb_stack_lte(log_sink)); - if (!lte_stack) { - srsran::console("Error creating eNB stack.\n"); + std::unique_ptr tmp_eutra_stack; + if (not rrc_cfg.cell_list.empty()) { + // add EUTRA stack + tmp_eutra_stack.reset(new enb_stack_lte(log_sink)); + if (tmp_eutra_stack == nullptr) { + srsran::console("Error creating EUTRA stack.\n"); return SRSRAN_ERROR; } + } - std::unique_ptr lte_radio = std::unique_ptr(new srsran::radio); - if (!lte_radio) { - srsran::console("Error creating radio multi instance.\n"); + std::unique_ptr tmp_nr_stack; + if (not rrc_cfg.cell_list_nr.empty()) { + // add NR stack + tmp_nr_stack.reset(new gnb_stack_nr()); + if (tmp_nr_stack == nullptr) { + srsran::console("Error creating NR stack.\n"); return SRSRAN_ERROR; } + } - std::unique_ptr lte_phy = std::unique_ptr(new srsenb::phy(log_sink)); - if (!lte_phy) { - srsran::console("Error creating LTE PHY instance.\n"); - return SRSRAN_ERROR; - } + // Radio is RAT agnostic + std::unique_ptr tmp_radio = std::unique_ptr(new srsran::radio); + if (tmp_radio == nullptr) { + srsran::console("Error creating radio multi instance.\n"); + return SRSRAN_ERROR; + } - if (ret == SRSRAN_SUCCESS) { - if (lte_stack->init(args.stack, rrc_cfg, lte_phy.get(), lte_phy.get()) != SRSRAN_SUCCESS) { - srsran::console("Error initializing stack.\n"); - ret = SRSRAN_ERROR; - } - } + // PHY is RAT agnostic too + std::unique_ptr tmp_phy = std::unique_ptr(new srsenb::phy(log_sink)); + if (tmp_phy == nullptr) { + srsran::console("Error creating PHY instance.\n"); + return SRSRAN_ERROR; + } - // Init Radio - if (lte_radio->init(args.rf, lte_phy.get())) { - srsran::console("Error initializing radio.\n"); - return SRSRAN_ERROR; - } + // initialize layers + if (tmp_eutra_stack->init(args.stack, rrc_cfg, tmp_phy.get(), tmp_phy.get()) != SRSRAN_SUCCESS) { + srsran::console("Error initializing stack.\n"); + ret = SRSRAN_ERROR; + } - // Only Init PHY if radio could be initialized - if (ret == SRSRAN_SUCCESS) { - if (lte_phy->init(args.phy, phy_cfg, lte_radio.get(), lte_stack.get(), *lte_stack)) { - srsran::console("Error initializing PHY.\n"); - ret = SRSRAN_ERROR; - } - } + // Init Radio + if (tmp_radio->init(args.rf, tmp_phy.get())) { + srsran::console("Error initializing radio.\n"); + return SRSRAN_ERROR; + } - stack = std::move(lte_stack); - phy = std::move(lte_phy); - radio = std::move(lte_radio); + // Only Init PHY if radio could be initialized + if (ret == SRSRAN_SUCCESS) { + if (tmp_phy->init(args.phy, phy_cfg, tmp_radio.get(), tmp_eutra_stack.get(), *tmp_eutra_stack)) { + srsran::console("Error initializing PHY.\n"); + ret = SRSRAN_ERROR; + } + } - } else { - srsran::console("Stack type %s not supported.\n", args.stack.type.c_str()); - return SRSRAN_ERROR; + if (tmp_eutra_stack) { + eutra_stack = std::move(tmp_eutra_stack); + } + if (tmp_nr_stack) { + nr_stack = std::move(tmp_nr_stack); } + phy = std::move(tmp_phy); + radio = std::move(tmp_radio); started = true; // set to true in any case to allow stopping the eNB if an error happened @@ -127,8 +142,12 @@ void enb::stop() phy->stop(); } - if (stack) { - stack->stop(); + if (eutra_stack) { + eutra_stack->stop(); + } + + if (nr_stack) { + nr_stack->stop(); } if (radio) { @@ -167,7 +186,9 @@ bool enb::get_metrics(enb_metrics_t* m) { radio->get_metrics(&m->rf); phy->get_metrics(m->phy); - stack->get_metrics(&m->stack); + if (eutra_stack) { + eutra_stack->get_metrics(&m->stack); + } m->running = started; m->sys = sys_proc.get_metrics(); return true; @@ -200,7 +221,7 @@ std::string enb::get_build_string() void enb::toggle_padding() { - stack->toggle_padding(); + eutra_stack->toggle_padding(); } } // namespace srsenb From 1e9a4e3fba7a445a8cc69010553e1f8941e724a4 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 13 Sep 2021 15:58:05 +0200 Subject: [PATCH 15/39] enb: remove stack type variable --- srsenb/hdr/stack/enb_stack_base.h | 1 - srsenb/src/main.cc | 2 -- 2 files changed, 3 deletions(-) diff --git a/srsenb/hdr/stack/enb_stack_base.h b/srsenb/hdr/stack/enb_stack_base.h index 7af3f08c1..b9d6bebb5 100644 --- a/srsenb/hdr/stack/enb_stack_base.h +++ b/srsenb/hdr/stack/enb_stack_base.h @@ -60,7 +60,6 @@ typedef struct { } stack_log_args_t; typedef struct { - std::string type; uint32_t sync_queue_size; // Max allowed difference between PHY and Stack clocks (in TTI) uint32_t gtpu_indirect_tunnel_timeout_msec; mac_args_t mac; diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index bdc743716..33e88f917 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -66,8 +66,6 @@ void parse_args(all_args_t* args, int argc, char* argv[]) // Command line or config file options bpo::options_description common("Configuration options"); common.add_options() - - ("enb.stack", bpo::value(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]") ("enb.enb_id", bpo::value(&enb_id)->default_value("0x0"), "eNodeB ID") ("enb.name", bpo::value(&args->stack.s1ap.enb_name)->default_value("srsenb01"), "eNodeB Name") ("enb.mcc", bpo::value(&mcc)->default_value("001"), "Mobile Country Code") From 3fd47d2af4d76f239b703662c2428615a76f884d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 17 Sep 2021 13:20:43 +0200 Subject: [PATCH 16/39] enb: refactor L2/L3 and (re)move all NR components to gNB stack * decouple EUTRA and NR stack classes * implement dummy X2 interface with control and data plane methods * implement eNB time source interface that PHY calls --- .../srsran/interfaces/enb_interfaces.h | 4 +- .../srsran/interfaces/enb_mac_interfaces.h | 2 - .../srsran/interfaces/enb_rrc_interfaces.h | 61 --------- .../srsran/interfaces/enb_time_interface.h | 31 +++++ .../srsran/interfaces/enb_x2_interfaces.h | 101 +++++++++++++++ srsenb/hdr/enb.h | 13 +- srsenb/hdr/phy/nr/worker_pool.h | 1 - srsenb/hdr/phy/phy.h | 7 +- srsenb/hdr/phy/txrx.h | 5 +- srsenb/hdr/stack/enb_stack_base.h | 2 + srsenb/hdr/stack/enb_stack_lte.h | 43 ++----- srsenb/hdr/stack/gnb_stack_nr.h | 62 ++++++--- srsenb/hdr/stack/rrc/rrc.h | 1 + srsenb/hdr/stack/rrc/rrc_nr.h | 1 + srsenb/hdr/x2_adapter.h | 120 ++++++++++++++++++ srsenb/src/enb.cc | 40 ++++-- srsenb/src/phy/phy.cc | 21 ++- srsenb/src/phy/txrx.cc | 8 +- srsenb/src/stack/enb_stack_lte.cc | 74 ++--------- srsenb/src/stack/gnb_stack_nr.cc | 118 +++++++++-------- srsenb/test/phy/enb_phy_test.cc | 13 +- 21 files changed, 457 insertions(+), 271 deletions(-) create mode 100644 lib/include/srsran/interfaces/enb_time_interface.h create mode 100644 lib/include/srsran/interfaces/enb_x2_interfaces.h create mode 100644 srsenb/hdr/x2_adapter.h diff --git a/lib/include/srsran/interfaces/enb_interfaces.h b/lib/include/srsran/interfaces/enb_interfaces.h index b8e831203..1e7d3cd4c 100644 --- a/lib/include/srsran/interfaces/enb_interfaces.h +++ b/lib/include/srsran/interfaces/enb_interfaces.h @@ -14,6 +14,8 @@ #include "srsran/common/interfaces_common.h" #include "srsran/srsran.h" +#include "srsran/interfaces/enb_rrc_interfaces.h" + #ifndef SRSRAN_ENB_INTERFACES_H #define SRSRAN_ENB_INTERFACES_H @@ -27,8 +29,6 @@ public: virtual void remove_eps_bearers(uint16_t rnti) = 0; }; -class stack_interface_phy_lte; - } // namespace srsenb #endif // SRSRAN_ENB_INTERFACES_H diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index ba13e75dc..6ee722a1d 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -258,8 +258,6 @@ public: // Combined interface for PHY to access stack (MAC and RRC) class stack_interface_phy_lte : public mac_interface_phy_lte { -public: - virtual void tti_clock() = 0; }; } // namespace srsenb diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index e1ac72d33..e8edb0499 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -120,67 +120,6 @@ public: virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0; }; -// RRC interfaces for NSA operation - -/// X2AP inspired interface to allow EUTRA RRC to call NR RRC -class rrc_nr_interface_rrc -{ -public: - struct sgnb_addition_req_params_t { - uint32_t eps_bearer_id; - // add configuration check - // E-RAB Parameters, Tunnel address (IP address, TEID) - // QCI, security, etc - }; - - /// Request addition of NR carrier for UE - virtual int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) = 0; - - /// Provide information whether the requested configuration was applied successfully by the UE - virtual int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) = 0; -}; - -/// X2AP inspired interface for response from NR RRC to EUTRA RRC -class rrc_eutra_interface_rrc_nr -{ -public: - /** - * @brief List of parameters included in the SgNB addition Ack message - * @param nr_secondary_cell_group_cfg_r15 Encoded part of the RRC Reconfiguration - * @param nr_radio_bearer_cfg1_r15 Encoded part of the RRC Reconfiguration - * @param eps_bearer_id ID of the transfered bearer - */ - struct sgnb_addition_ack_params_t { - uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // RNTI that was assigned to the UE - asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; - asn1::dyn_octstring nr_radio_bearer_cfg1_r15; - uint32_t eps_bearer_id = 0; // (list of) successfully transfered EPS bearers - }; - - /** - * @brief Signal successful addition of UE - * - * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - * @param params Parameter list - */ - virtual void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) = 0; - - /** - * @brief Signal unsuccessful SgNB addition - * - * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - */ - virtual void sgnb_addition_reject(uint16_t eutra_rnti) = 0; - - /** - * @brief Signal completion of SgNB addition after UE (with new NR identity) has attached - * - * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - * @param nr_rnti The RNTI that has been assigned to the UE on the SgNB - */ - virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; -}; - } // namespace srsenb #endif // SRSRAN_ENB_RRC_INTERFACES_H diff --git a/lib/include/srsran/interfaces/enb_time_interface.h b/lib/include/srsran/interfaces/enb_time_interface.h new file mode 100644 index 000000000..e1ef79d90 --- /dev/null +++ b/lib/include/srsran/interfaces/enb_time_interface.h @@ -0,0 +1,31 @@ +/** + * + * \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_ENB_TIME_INTERFACE_H +#define SRSRAN_ENB_TIME_INTERFACE_H + +namespace srsenb { + +// RAT-agnostic interface to provide timing information to upper layers +class enb_time_interface +{ +public: + /** + * @brief Called for every tick (currently every ms) + * + */ + virtual void tti_clock() = 0; +}; + +} // namespace srsenb + +#endif // SRSRAN_ENB_TIME_INTERFACE_H diff --git a/lib/include/srsran/interfaces/enb_x2_interfaces.h b/lib/include/srsran/interfaces/enb_x2_interfaces.h new file mode 100644 index 000000000..a5b503ee3 --- /dev/null +++ b/lib/include/srsran/interfaces/enb_x2_interfaces.h @@ -0,0 +1,101 @@ +/** + * + * \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 "srsran/interfaces/enb_pdcp_interfaces.h" +#include "srsran/interfaces/enb_rrc_interface_types.h" + +#ifndef SRSRAN_ENB_X2_INTERFACES_H +#define SRSRAN_ENB_X2_INTERFACES_H + +namespace srsenb { + +/** + * @brief Set of X2AP inspired interfaces to support 5G NSA + * + */ + +/// X2AP inspired interface to allow EUTRA RRC to call NR RRC +class rrc_nr_interface_rrc +{ +public: + struct sgnb_addition_req_params_t { + uint32_t eps_bearer_id; + // add configuration check + // E-RAB Parameters, Tunnel address (IP address, TEID) + // QCI, security, etc + }; + + /// Request addition of NR carrier for UE + virtual int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) = 0; + + /// Provide information whether the requested configuration was applied successfully by the UE + virtual int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) = 0; +}; + +/// X2AP inspired interface for response from NR RRC to EUTRA RRC +class rrc_eutra_interface_rrc_nr +{ +public: + /** + * @brief List of parameters included in the SgNB addition Ack message + * @param nr_secondary_cell_group_cfg_r15 Encoded part of the RRC Reconfiguration + * @param nr_radio_bearer_cfg1_r15 Encoded part of the RRC Reconfiguration + * @param eps_bearer_id ID of the transfered bearer + */ + struct sgnb_addition_ack_params_t { + uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // RNTI that was assigned to the UE + asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; + asn1::dyn_octstring nr_radio_bearer_cfg1_r15; + uint32_t eps_bearer_id = 0; // (list of) successfully transfered EPS bearers + }; + + /** + * @brief Signal successful addition of UE + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + * @param params Parameter list + */ + virtual void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) = 0; + + /** + * @brief Signal unsuccessful SgNB addition + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + */ + virtual void sgnb_addition_reject(uint16_t eutra_rnti) = 0; + + /** + * @brief Signal completion of SgNB addition after UE (with new NR identity) has attached + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + * @param nr_rnti The RNTI that has been assigned to the UE on the SgNB + */ + virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; +}; + +class stack_nr_interface_stack_eutra +{ +public: + /// Helper method to provide time signal to NR-RRC (PHY only sends TTI ticks to EUTRA stack) + virtual void tti_clock() = 0; +}; + +// combined interface used by X2 adapter +class x2_interface : public rrc_nr_interface_rrc, + public rrc_eutra_interface_rrc_nr, + public stack_nr_interface_stack_eutra, + public pdcp_interface_gtpu +{}; + +} // namespace srsenb + +#endif // SRSRAN_ENB_X2_INTERFACES_H diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 890862759..cf5901e84 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -24,12 +24,14 @@ #include #include "phy/phy.h" +#include "x2_adapter.h" #include "srsran/radio/radio.h" #include "srsenb/hdr/phy/enb_phy_base.h" #include "srsenb/hdr/stack/enb_stack_base.h" #include "srsenb/hdr/stack/rrc/rrc_config.h" +#include "srsenb/hdr/stack/rrc/rrc_config_nr.h" #include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/bcd_helpers.h" @@ -39,6 +41,7 @@ #include "srsran/common/security.h" #include "srsran/interfaces/enb_command_interface.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/interfaces/ue_interfaces.h" #include "srsran/srslog/srslog.h" #include "srsran/system/sys_metrics_processor.h" @@ -117,7 +120,7 @@ struct rrc_cfg_t; Main eNB class *******************************************************************************/ -class enb : public enb_metrics_interface, enb_command_interface +class enb : public enb_metrics_interface, enb_command_interface, enb_time_interface { public: enb(srslog::sink& log_sink); @@ -140,6 +143,8 @@ public: void toggle_padding() override; + void tti_clock() override; + private: const static int ENB_POOL_SIZE = 1024 * 10; @@ -151,10 +156,12 @@ private: all_args_t args = {}; bool started = false; - phy_cfg_t phy_cfg = {}; - rrc_cfg_t rrc_cfg = {}; + phy_cfg_t phy_cfg = {}; + rrc_cfg_t rrc_cfg = {}; + rrc_nr_cfg_t rrc_nr_cfg = {}; // eNB components + x2_adapter x2; std::unique_ptr eutra_stack = nullptr; std::unique_ptr nr_stack = nullptr; std::unique_ptr radio = nullptr; diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 66cf9ddbc..4c816e577 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -71,7 +71,6 @@ private: int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) override { return 0; } int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; } void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override {} - void tti_clock() override {} }; srsran::phy_common_interface& common; diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index ca19eb7a4..95a1cbb00 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -18,6 +18,7 @@ #include "srsenb/hdr/phy/enb_phy_base.h" #include "srsran/common/trace.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/interfaces/radio_interfaces.h" #include "srsran/radio/radio.h" #include "srsran/srslog/srslog.h" @@ -37,12 +38,14 @@ public: int init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, - stack_interface_phy_lte* stack_); + stack_interface_phy_lte* stack_, + enb_time_interface* enb_); int init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, stack_interface_phy_lte* stack_lte_, - stack_interface_phy_nr& stack_nr_); + stack_interface_phy_nr& stack_nr_, + enb_time_interface* enb_); void stop() override; std::string get_type() override { return "lte"; }; diff --git a/srsenb/hdr/phy/txrx.h b/srsenb/hdr/phy/txrx.h index b3deaa3f0..105410369 100644 --- a/srsenb/hdr/phy/txrx.h +++ b/srsenb/hdr/phy/txrx.h @@ -18,6 +18,7 @@ #include "srsenb/hdr/phy/lte/worker_pool.h" #include "srsenb/hdr/phy/nr/worker_pool.h" #include "srsran/config.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/phy/channel/channel.h" #include "srsran/radio/radio.h" #include @@ -28,7 +29,7 @@ class txrx final : public srsran::thread { public: txrx(srslog::basic_logger& logger); - bool init(stack_interface_phy_lte* stack_, + bool init(enb_time_interface* enb_, srsran::radio_interface_phy* radio_handler, lte::worker_pool* lte_workers_, phy_common* worker_com, @@ -40,7 +41,7 @@ public: private: void run_thread() override; - stack_interface_phy_lte* stack = nullptr; + enb_time_interface* enb = nullptr; srsran::radio_interface_phy* radio_h = nullptr; srslog::basic_logger& logger; lte::worker_pool* lte_workers = nullptr; diff --git a/srsenb/hdr/stack/enb_stack_base.h b/srsenb/hdr/stack/enb_stack_base.h index b9d6bebb5..5d0932a15 100644 --- a/srsenb/hdr/stack/enb_stack_base.h +++ b/srsenb/hdr/stack/enb_stack_base.h @@ -85,6 +85,8 @@ public: virtual void toggle_padding() = 0; // eNB metrics interface virtual bool get_metrics(stack_metrics_t* metrics) = 0; + + virtual void tti_clock() = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index b01ea3a20..2ec367b67 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -19,9 +19,7 @@ #define SRSRAN_ENB_STACK_LTE_H #include "mac/mac.h" -#include "mac/nr/mac_nr.h" #include "rrc/rrc.h" -#include "rrc/rrc_nr.h" #include "s1ap/s1ap.h" #include "srsran/common/task_scheduler.h" #include "upper/gtpu.h" @@ -40,7 +38,7 @@ class gtpu_pdcp_adapter; class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, - public stack_interface_phy_nr, + public rrc_eutra_interface_rrc_nr, public srsran::thread { public: @@ -48,12 +46,7 @@ public: ~enb_stack_lte() final; // eNB stack base interface - int init(const stack_args_t& args_, - const rrc_cfg_t& rrc_cfg_, - phy_interface_stack_lte* phy_, - phy_interface_stack_nr* phy_nr_); - int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_); - int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_); + int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, x2_interface* x2_); void stop() final; std::string get_type() final; bool get_metrics(stack_metrics_t* metrics) final; @@ -115,25 +108,16 @@ public: void toggle_padding() override { mac.toggle_padding(); } void tti_clock() override; - // mac_interface_phy_nr - int slot_indication(const srsran_slot_cfg_t& slot_cfg) override { return mac_nr.slot_indication(slot_cfg); } - int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::dl_sched_t& dl_sched) override + // rrc_eutra_interface_rrc_nr + void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) final { - return mac_nr.get_dl_sched(slot_cfg, dl_sched); + rrc.sgnb_addition_ack(eutra_rnti, params); } - int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::ul_sched_t& ul_sched) override + void sgnb_addition_reject(uint16_t eutra_rnti) final { rrc.sgnb_addition_reject(eutra_rnti); } + void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) final { - return mac_nr.get_ul_sched(slot_cfg, ul_sched); + rrc.sgnb_addition_complete(eutra_rnti, nr_rnti); } - int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override - { - return mac_nr.pucch_info(slot_cfg, pucch_info); - } - int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override - { - return mac_nr.pusch_info(slot_cfg, pusch_info); - } - void rach_detected(const rach_info_t& rach_info) override { mac_nr.rach_detected(rach_info); } private: static const int STACK_MAIN_THREAD_PRIO = 4; @@ -155,10 +139,6 @@ private: srslog::basic_logger& s1ap_logger; srslog::basic_logger& gtpu_logger; srslog::basic_logger& stack_logger; - srslog::basic_logger& rrc_nr_logger; - srslog::basic_logger& mac_nr_logger; - srslog::basic_logger& rlc_nr_logger; - srslog::basic_logger& pdcp_nr_logger; // PCAP and trace option srsran::mac_pcap mac_pcap; @@ -180,15 +160,8 @@ private: srsenb::gtpu gtpu; srsenb::s1ap s1ap; - // NR components for NSA mode - srsenb::mac_nr mac_nr; - srsenb::rlc rlc_nr; - srsenb::pdcp pdcp_nr; - srsenb::rrc_nr rrc_nr; - // RAT-specific interfaces phy_interface_stack_lte* phy = nullptr; - phy_interface_stack_nr* phy_nr = nullptr; // state std::atomic started{false}; diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 48102f5d9..d20135c7a 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -18,16 +18,15 @@ #ifndef SRSRAN_GNB_STACK_NR_H #define SRSRAN_GNB_STACK_NR_H -#include "s1ap/s1ap.h" #include "srsenb/hdr/stack/mac/nr/mac_nr.h" #include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/stack/upper/pdcp_nr.h" #include "srsenb/hdr/stack/upper/rlc_nr.h" -#include "upper/gtpu.h" +#include "upper/pdcp.h" +#include "upper/rlc.h" #include "upper/sdap.h" #include "enb_stack_base.h" -#include "srsenb/hdr/enb.h" #include "srsran/interfaces/gnb_interfaces.h" // This is needed for GW @@ -40,14 +39,18 @@ class gnb_stack_nr final : public srsenb::enb_stack_base, public stack_interface_phy_nr, public stack_interface_mac, public srsue::stack_interface_gw, + public rrc_nr_interface_rrc, + public pdcp_interface_gtpu, // for user-plane over X2 public srsran::thread { public: - explicit gnb_stack_nr(); + explicit gnb_stack_nr(srslog::sink& log_sink); ~gnb_stack_nr() final; - int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_); - int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_); + int init(const srsenb::stack_args_t& args_, + const rrc_nr_cfg_t& rrc_cfg_, + phy_interface_stack_nr* phy_, + x2_interface* x2_); // eNB stack base interface void stop() final; @@ -62,12 +65,12 @@ public: void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override; bool has_active_radio_bearer(uint32_t eps_bearer_id) override; bool switch_on(); - void run_tti(uint32_t tti); + void tti_clock() override; // MAC interface to trigger processing of received PDUs void process_pdus() final; - void toggle_padding() override { srsran::console("padding not available for NR\n"); } + void toggle_padding() override {} int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; @@ -76,15 +79,40 @@ public: int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override; void rach_detected(const rach_info_t& rach_info) override; + // X2 interface + + // control plane, i.e. rrc_nr_interface_rrc + int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) final + { + return rrc.sgnb_addition_request(eutra_rnti, params); + }; + int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) final + { + return rrc.sgnb_reconfiguration_complete(eutra_rnti, reconfig_response); + }; + // X2 data interface + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) final + { + pdcp.write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) final + { + return pdcp.get_buffered_pdus(rnti, lcid); + } + private: void run_thread() final; - void run_tti_impl(uint32_t tti); + void tti_clock_impl(); // args srsenb::stack_args_t args = {}; phy_interface_stack_nr* phy = nullptr; + srslog::basic_logger& rrc_logger; + srslog::basic_logger& mac_logger; srslog::basic_logger& rlc_logger; + srslog::basic_logger& pdcp_logger; + srslog::basic_logger& stack_logger; // task scheduling static const int STACK_MAIN_THREAD_PRIO = 4; @@ -92,18 +120,14 @@ private: srsran::task_multiqueue::queue_handle sync_task_queue, ue_task_queue, gw_task_queue, mac_task_queue; // derived - std::unique_ptr m_mac; - std::unique_ptr m_rlc; - std::unique_ptr m_pdcp; - std::unique_ptr m_sdap; - std::unique_ptr m_rrc; - std::unique_ptr m_gw; - // std::unique_ptr m_ngap; - // std::unique_ptr m_gtpu; + srsenb::mac_nr mac; + srsenb::rlc rlc; + srsenb::pdcp pdcp; + srsenb::rrc_nr rrc; + // std::unique_ptr m_sdap; // state - bool running = false; - uint32_t current_tti = 10240; + std::atomic running = {false}; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 332ef793e..25ee18bb2 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -26,6 +26,7 @@ #include "srsran/common/task_scheduler.h" #include "srsran/common/timeout.h" #include "srsran/interfaces/enb_rrc_interfaces.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/srslog/srslog.h" #include diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 5b3200edc..15b01e7f5 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -27,6 +27,7 @@ #include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" diff --git a/srsenb/hdr/x2_adapter.h b/srsenb/hdr/x2_adapter.h new file mode 100644 index 000000000..047533af8 --- /dev/null +++ b/srsenb/hdr/x2_adapter.h @@ -0,0 +1,120 @@ +/** + * + * \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. + * + */ + +/** + * @brief Dummy X2AP implementation + * + * Dummy X2 adapter to facilitate communication between EUTRA RRC and NR RRC + * for EN-DC procedures. + * + * The class uses direct function calls instead of real X2AP ASN1 encoded + * messages. It mainly focuses on Sec 9.1.4 of TS 36.423 Rel. 15.11 + * for E-UTRAN-NR Dual Connectivity Procedures, i.e. SgNB-* + * + * It furthermore provide an interface for the GTPU adapter to + * write DL PDUs, which it then forwards to the NR PDCP. + * + * It also provides a method to allow the eNB to foward timing + * signal, i.e. TTI tics, to the NR stack. + */ + +#ifndef SRSENB_X2_ADAPTER_H +#define SRSENB_X2_ADAPTER_H + +#include "srsran/interfaces/enb_x2_interfaces.h" +#include "stack/enb_stack_lte.h" +#include "stack/gnb_stack_nr.h" + +namespace srsenb { + +class x2_adapter final : public x2_interface +{ +public: + x2_adapter() = default; + + // init functions to set handle to stacks + void set_eutra_stack(enb_stack_lte* eutra_stack_) { eutra_stack = eutra_stack_; } + + void set_nr_stack(gnb_stack_nr* nr_stack_) { nr_stack = nr_stack_; } + + /// rrc_nr_interface_rrc + int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) + { + if (nr_stack == nullptr) { + return SRSRAN_ERROR; + } + return nr_stack->sgnb_addition_request(eutra_rnti, params); + } + int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) + { + if (nr_stack == nullptr) { + return SRSRAN_ERROR; + } + return nr_stack->sgnb_reconfiguration_complete(eutra_rnti, reconfig_response); + } + + /// rrc_eutra_interface_rrc_nr + void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_ack(eutra_rnti, params); + } + void sgnb_addition_reject(uint16_t eutra_rnti) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_reject(eutra_rnti); + } + void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti); + } + + // stack_nr_interface_stack_eutra + void tti_clock() + { + if (nr_stack == nullptr) { + return; + } + nr_stack->tti_clock(); + } + + // pdcp_interface_gtpu + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) + { + if (nr_stack == nullptr) { + return; + } + nr_stack->write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) + { + if (nr_stack == nullptr) { + return {}; + } + return nr_stack->get_buffered_pdus(rnti, lcid); + } + +private: + enb_stack_lte* eutra_stack = nullptr; + gnb_stack_nr* nr_stack = nullptr; +}; + +} // namespace srsenb + +#endif // SRSENB_X2_ADAPTER_H diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 009a09c1b..da2bbdc2d 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -59,36 +59,46 @@ int enb::init(const all_args_t& args_) srsran::console("Error creating EUTRA stack.\n"); return SRSRAN_ERROR; } + x2.set_eutra_stack(tmp_eutra_stack.get()); } std::unique_ptr tmp_nr_stack; if (not rrc_cfg.cell_list_nr.empty()) { // add NR stack - tmp_nr_stack.reset(new gnb_stack_nr()); + tmp_nr_stack.reset(new gnb_stack_nr(log_sink)); if (tmp_nr_stack == nullptr) { srsran::console("Error creating NR stack.\n"); return SRSRAN_ERROR; } + x2.set_nr_stack(tmp_nr_stack.get()); } - // Radio is RAT agnostic + // Radio and PHY are RAT agnostic std::unique_ptr tmp_radio = std::unique_ptr(new srsran::radio); if (tmp_radio == nullptr) { srsran::console("Error creating radio multi instance.\n"); return SRSRAN_ERROR; } - // PHY is RAT agnostic too std::unique_ptr tmp_phy = std::unique_ptr(new srsenb::phy(log_sink)); if (tmp_phy == nullptr) { srsran::console("Error creating PHY instance.\n"); return SRSRAN_ERROR; } - // initialize layers - if (tmp_eutra_stack->init(args.stack, rrc_cfg, tmp_phy.get(), tmp_phy.get()) != SRSRAN_SUCCESS) { - srsran::console("Error initializing stack.\n"); - ret = SRSRAN_ERROR; + // initialize layers, if they exist + if (tmp_eutra_stack) { + if (tmp_eutra_stack->init(args.stack, rrc_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) { + srsran::console("Error initializing EUTRA stack.\n"); + ret = SRSRAN_ERROR; + } + } + + if (tmp_nr_stack) { + if (tmp_nr_stack->init(args.stack, rrc_nr_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) { + srsran::console("Error initializing NR stack.\n"); + ret = SRSRAN_ERROR; + } } // Init Radio @@ -99,7 +109,7 @@ int enb::init(const all_args_t& args_) // Only Init PHY if radio could be initialized if (ret == SRSRAN_SUCCESS) { - if (tmp_phy->init(args.phy, phy_cfg, tmp_radio.get(), tmp_eutra_stack.get(), *tmp_eutra_stack)) { + if (tmp_phy->init(args.phy, phy_cfg, tmp_radio.get(), tmp_eutra_stack.get(), *tmp_nr_stack, this)) { srsran::console("Error initializing PHY.\n"); ret = SRSRAN_ERROR; } @@ -221,7 +231,19 @@ std::string enb::get_build_string() void enb::toggle_padding() { - eutra_stack->toggle_padding(); + if (eutra_stack) { + eutra_stack->toggle_padding(); + } +} + +void enb::tti_clock() +{ + if (eutra_stack) { + eutra_stack->tti_clock(); + } + if (nr_stack) { + nr_stack->tti_clock(); + } } } // namespace srsenb diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index cd2f48ec9..a466b8b99 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -97,9 +97,10 @@ int phy::init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, stack_interface_phy_lte* stack_lte_, - stack_interface_phy_nr& stack_nr_) + stack_interface_phy_nr& stack_nr_, + enb_time_interface* enb_) { - if (init(args, cfg, radio_, stack_lte_) != SRSRAN_SUCCESS) { + if (init(args, cfg, radio_, stack_lte_, enb_) != SRSRAN_SUCCESS) { phy_log.error("Couldn't initialize LTE PHY"); return SRSRAN_ERROR; } @@ -115,7 +116,8 @@ int phy::init(const phy_args_t& args, int phy::init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, - stack_interface_phy_lte* stack_) + stack_interface_phy_lte* stack_lte_, + enb_time_interface* enb_) { if (cfg.phy_cell_cfg.size() > SRSRAN_MAX_CARRIERS) { phy_log.error( @@ -142,7 +144,7 @@ int phy::init(const phy_args_t& args, workers_common.params = args; - workers_common.init(cfg.phy_cell_cfg, cfg.phy_cell_cfg_nr, radio, stack_); + workers_common.init(cfg.phy_cell_cfg, cfg.phy_cell_cfg_nr, radio, stack_lte_); parse_common_config(cfg); @@ -154,13 +156,18 @@ int phy::init(const phy_args_t& args, // For each carrier, initialise PRACH worker for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) { prach_cfg.root_seq_idx = cfg.phy_cell_cfg[cc].root_seq_idx; - prach.init( - cc, cfg.phy_cell_cfg[cc].cell, prach_cfg, stack_, phy_log, PRACH_WORKER_THREAD_PRIO, args.nof_prach_threads); + prach.init(cc, + cfg.phy_cell_cfg[cc].cell, + prach_cfg, + stack_lte_, + phy_log, + PRACH_WORKER_THREAD_PRIO, + args.nof_prach_threads); } prach.set_max_prach_offset_us(args.max_prach_offset_us); // Warning this must be initialized after all workers have been added to the pool - tx_rx.init(stack_, radio, <e_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); + tx_rx.init(enb_, radio, <e_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); initialized = true; diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 6712b5603..193486d05 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -39,14 +39,14 @@ txrx::txrx(srslog::basic_logger& logger) : thread("TXRX"), logger(logger), runni /* Do nothing */ } -bool txrx::init(stack_interface_phy_lte* stack_, +bool txrx::init(enb_time_interface* enb_, srsran::radio_interface_phy* radio_h_, lte::worker_pool* lte_workers_, phy_common* worker_com_, prach_worker_pool* prach_, uint32_t prio_) { - stack = stack_; + enb = enb_; radio_h = radio_h_; lte_workers = lte_workers_; worker_com = worker_com_; @@ -213,8 +213,8 @@ void txrx::run_thread() lte_workers->start_worker(lte_worker); } - // Advance stack in time - stack->tti_clock(); + // Advance in time + enb->tti_clock(); } } diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 766920b65..ec25ad053 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -13,8 +13,8 @@ #include "srsenb/hdr/stack/enb_stack_lte.h" #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/enb.h" -#include "srsenb/hdr/stack/rrc/rrc_config_nr.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/rlc/bearer_mem_pool.h" #include "srsran/srslog/event_trace.h" @@ -27,10 +27,10 @@ class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interfac public: gtpu_pdcp_adapter(srslog::basic_logger& logger_, pdcp* pdcp_lte, - pdcp* pdcp_nr, + pdcp_interface_gtpu* pdcp_x2, gtpu* gtpu_, enb_bearer_manager& bearers_) : - logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_) + logger(logger_), pdcp_obj(pdcp_lte), pdcp_x2_obj(pdcp_x2), gtpu_obj(gtpu_), bearers(&bearers_) {} /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU @@ -50,7 +50,7 @@ public: if (bearer.rat == srsran_rat_t::lte) { pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else if (bearer.rat == srsran_rat_t::nr) { - pdcp_nr_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + pdcp_x2_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else { logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); } @@ -62,7 +62,7 @@ public: if (bearer.rat == srsran_rat_t::lte) { return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); } else if (bearer.rat == srsran_rat_t::nr) { - return pdcp_nr_obj->get_buffered_pdus(rnti, bearer.lcid); + return pdcp_x2_obj->get_buffered_pdus(rnti, bearer.lcid); } logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id); return {}; @@ -72,34 +72,26 @@ private: srslog::basic_logger& logger; gtpu* gtpu_obj = nullptr; pdcp* pdcp_obj = nullptr; - pdcp* pdcp_nr_obj = nullptr; + pdcp_interface_gtpu* pdcp_x2_obj = nullptr; enb_bearer_manager* bearers = nullptr; }; enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : thread("STACK"), mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), - mac_nr_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)), rlc_logger(srslog::fetch_basic_logger("RLC", log_sink, false)), - rlc_nr_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)), pdcp_logger(srslog::fetch_basic_logger("PDCP", log_sink, false)), - pdcp_nr_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)), rrc_logger(srslog::fetch_basic_logger("RRC", log_sink, false)), - rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)), s1ap_logger(srslog::fetch_basic_logger("S1AP", log_sink, false)), gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)), stack_logger(srslog::fetch_basic_logger("STCK", log_sink, false)), task_sched(512, 128), pdcp(&task_sched, pdcp_logger), - pdcp_nr(&task_sched, pdcp_nr_logger), mac(&task_sched, mac_logger), - mac_nr(&task_sched), rlc(rlc_logger), - rlc_nr(rlc_nr_logger), gtpu(&task_sched, gtpu_logger, &rx_sockets), s1ap(&task_sched, s1ap_logger, &rx_sockets), rrc(&task_sched, bearers), - rrc_nr(&task_sched), mac_pcap(), pending_stack_metrics(64) { @@ -122,30 +114,11 @@ std::string enb_stack_lte::get_type() int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, - phy_interface_stack_nr* phy_nr_) -{ - phy_nr = phy_nr_; - if (init(args_, rrc_cfg_, phy_)) { - return SRSRAN_ERROR; - } - - return SRSRAN_SUCCESS; -} - -int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_) -{ - phy = phy_; - if (init(args_, rrc_cfg_)) { - return SRSRAN_ERROR; - } - - return SRSRAN_SUCCESS; -} - -int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) + x2_interface* x2_) { args = args_; rrc_cfg = rrc_cfg_; + phy = phy_; // Init RNTI and bearer memory pools reserve_rnti_memblocks(args.mac.nof_prealloc_ues); @@ -154,25 +127,17 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) // setup logging for each layer mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); - mac_nr_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); - rlc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); - pdcp_nr_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); - rrc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); gtpu_logger.set_level(srslog::str_to_basic_level(args.log.gtpu_level)); s1ap_logger.set_level(srslog::str_to_basic_level(args.log.s1ap_level)); stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); - mac_nr_logger.set_hex_dump_max_size(args.log.mac_hex_limit); rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); - rlc_nr_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); - pdcp_nr_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); - rrc_nr_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit); s1ap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit); stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); @@ -200,7 +165,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); // setup bearer managers - gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, &pdcp_nr, >pu, bearers)); + gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, x2_, >pu, bearers)); // Init all LTE layers if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { @@ -209,7 +174,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) } rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); pdcp.init(&rlc, &rrc, gtpu_adapter.get()); - if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &rrc_nr) != SRSRAN_SUCCESS) { + if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, x2_) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); return SRSRAN_ERROR; } @@ -218,25 +183,6 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) return SRSRAN_ERROR; } - // NR layers - mac_nr_args_t mac_args = {}; - mac_args.fixed_dl_mcs = 28; - mac_args.fixed_ul_mcs = 10; - mac_args.pcap = args.mac_pcap; - mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap"; - if (mac_nr.init(mac_args, phy_nr, nullptr, &rlc_nr, &rrc_nr) != SRSRAN_SUCCESS) { - stack_logger.error("Couldn't initialize MAC-NR"); - return SRSRAN_ERROR; - } - - rrc_nr_cfg_t rrc_cfg_nr = {}; - if (rrc_nr.init(rrc_cfg_nr, phy_nr, &mac_nr, &rlc_nr, &pdcp_nr, nullptr, nullptr, &rrc) != SRSRAN_SUCCESS) { - stack_logger.error("Couldn't initialize RRC-NR"); - return SRSRAN_ERROR; - } - rlc_nr.init(&pdcp_nr, &rrc_nr, &mac_nr, task_sched.get_timer_handler()); - pdcp_nr.init(&rlc_nr, &rrc_nr, gtpu_adapter.get()); - gtpu_args_t gtpu_args; gtpu_args.embms_enable = args.embms.enable; gtpu_args.embms_m1u_multiaddr = args.embms.m1u_multiaddr; diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 205aed2a4..fad435c01 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -11,21 +11,25 @@ */ #include "srsenb/hdr/stack/gnb_stack_nr.h" +#include "srsran/common/standard_streams.h" #include "srsran/srsran.h" #include namespace srsenb { -gnb_stack_nr::gnb_stack_nr() : task_sched{512, 128}, thread("gNB"), rlc_logger(srslog::fetch_basic_logger("RLC-NR")) +gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) : + task_sched{512, 128}, + thread("gNB"), + mac_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)), + rlc_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)), + pdcp_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)), + rrc_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)), + stack_logger(srslog::fetch_basic_logger("STCK-NR", log_sink, false)), + mac(&task_sched), + rrc(&task_sched), + pdcp(&task_sched, pdcp_logger), + rlc(rlc_logger) { - m_mac.reset(new mac_nr(&task_sched)); - m_rlc.reset(new rlc_nr("RLC-NR")); - m_pdcp.reset(new pdcp_nr(&task_sched, "PDCP-NR")); - m_rrc.reset(new rrc_nr(&task_sched)); - m_sdap.reset(new sdap()); - m_gw.reset(new srsue::gw(srslog::fetch_basic_logger("GW"))); - // m_gtpu.reset(new srsenb::gtpu()); - ue_task_queue = task_sched.make_task_queue(); sync_task_queue = task_sched.make_task_queue(); gw_task_queue = task_sched.make_task_queue(); @@ -42,46 +46,48 @@ std::string gnb_stack_nr::get_type() return "nr"; } -int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_) +int gnb_stack_nr::init(const srsenb::stack_args_t& args_, + const rrc_nr_cfg_t& rrc_cfg_, + phy_interface_stack_nr* phy_, + x2_interface* x2_) { + args = args_; + // rrc_cfg = rrc_cfg_; phy = phy_; - if (init(args_, rrc_cfg_)) { - return SRSRAN_ERROR; - } - return SRSRAN_SUCCESS; -} -int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_) -{ - args = args_; + // setup logging + mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); + rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); + pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); + rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); + stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); - // verify configuration correctness - // gtpu_log.init("GTPU", logger); - // gtpu_log.set_level(args.log.gtpu_level); - // gtpu_log.set_hex_limit(args.log.gtpu_hex_limit); + mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); + rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); + pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); + rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); + stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); // Init all layers mac_nr_args_t mac_args = {}; + mac_args.fixed_dl_mcs = 28; + mac_args.fixed_ul_mcs = 10; mac_args.pcap = args.mac_pcap; - m_mac->init(mac_args, phy, this, nullptr, m_rrc.get()); - - rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); - rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); - m_rlc->init(m_pdcp.get(), m_rrc.get(), m_mac.get(), task_sched.get_timer_handler()); - - pdcp_nr_args_t pdcp_args = {}; - pdcp_args.log_level = args.log.pdcp_level; - pdcp_args.log_hex_limit = args.log.pdcp_hex_limit; - m_pdcp->init(pdcp_args, m_rlc.get(), m_rrc.get(), m_sdap.get()); - - m_rrc->init(rrc_cfg_, phy, m_mac.get(), nullptr, nullptr, nullptr, nullptr, nullptr); + mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap"; + if (mac.init(mac_args, phy, nullptr, &rlc, &rrc) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize MAC-NR"); + return SRSRAN_ERROR; + } - m_sdap->init(m_pdcp.get(), nullptr, m_gw.get()); + rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); + pdcp.init(&rlc, &rrc, nullptr); - srsue::gw_args_t gw_args = {}; - m_gw->init(gw_args, this); + if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, nullptr, nullptr, x2_) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize RRC"); + return SRSRAN_ERROR; + } - // TODO: add NGAP + // TODO: add SDAP, NGAP // m_gtpu->init(args.s1ap.gtp_bind_addr, args.s1ap.mme_addr, // args.expert.m1u_multiaddr, args.expert.m1u_if_addr, nullptr, >pu_log, // args.expert.enable_mbsfn); @@ -96,11 +102,9 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr void gnb_stack_nr::stop() { if (running) { - m_gw->stop(); - // m_gtpu->stop(); - m_rrc->stop(); - m_pdcp->stop(); - m_mac->stop(); + rrc.stop(); + pdcp.stop(); + mac.stop(); srsran::get_background_workers().stop(); running = false; @@ -120,13 +124,12 @@ void gnb_stack_nr::run_thread() } } -void gnb_stack_nr::run_tti(uint32_t tti) +void gnb_stack_nr::tti_clock() { - current_tti = tti; - sync_task_queue.push([this, tti]() { run_tti_impl(tti); }); + sync_task_queue.push([this]() { tti_clock_impl(); }); } -void gnb_stack_nr::run_tti_impl(uint32_t tti) +void gnb_stack_nr::tti_clock_impl() { // m_ngap->run_tti(); task_sched.tic(); @@ -144,8 +147,8 @@ void gnb_stack_nr::process_pdus() bool gnb_stack_nr::get_metrics(srsenb::stack_metrics_t* metrics) { - m_mac->get_metrics(metrics->mac); - m_rrc->get_metrics(metrics->rrc); + mac.get_metrics(metrics->mac); + rrc.get_metrics(metrics->rrc); return true; } @@ -161,25 +164,28 @@ bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id) } int gnb_stack_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { - return m_mac->slot_indication(slot_cfg); + return mac.slot_indication(slot_cfg); } int gnb_stack_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { - return m_mac->get_dl_sched(slot_cfg, dl_sched); + return mac.get_dl_sched(slot_cfg, dl_sched); } int gnb_stack_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) { - return m_mac->get_ul_sched(slot_cfg, ul_sched); + return mac.get_ul_sched(slot_cfg, ul_sched); } int gnb_stack_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pucch_info_t& pucch_info) { - return m_mac->pucch_info(slot_cfg, pucch_info); + return mac.pucch_info(slot_cfg, pucch_info); } int gnb_stack_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr::pusch_info_t& pusch_info) { - return m_mac->pusch_info(slot_cfg, pusch_info); + return mac.pusch_info(slot_cfg, pusch_info); } -void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) {} +void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) +{ + mac.rach_detected(rach_info); +} -} // namespace srsenb +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index 64c6f3fde..a18948d43 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -710,7 +710,7 @@ public: return SRSRAN_SUCCESS; } void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override { notify_set_sched_dl_tti_mask(); } - void tti_clock() override { notify_tti_clock(); } + void tti_clock() { notify_tti_clock(); } int run_tti(bool enable_assert) { std::lock_guard lock(phy_mac_mutex); @@ -1150,7 +1150,7 @@ typedef std::unique_ptr unique_dummy_ue_phy_t; typedef std::unique_ptr unique_srsenb_phy_t; -class phy_test_bench +class phy_test_bench : public srsenb::enb_time_interface { public: struct args_t { @@ -1328,7 +1328,7 @@ public: stack->set_active_cell_list(args.ue_cell_list); /// Initiate eNb PHY with the given RNTI - if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get()) < 0) { + if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get(), this) < 0) { return SRSRAN_ERROR; } enb_phy->set_config(args.rnti, phy_rrc_cfg); @@ -1350,7 +1350,7 @@ public: enb_phy->stop(); } - ~phy_test_bench() = default; + virtual ~phy_test_bench() = default; int run_tti() { @@ -1422,6 +1422,11 @@ public: return ret; } + + void tti_clock() final + { + // nothing to do + } }; typedef std::unique_ptr unique_phy_test_bench; From 39e00bdbe8215b0911c3f0487c3c97214687ae53 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Thu, 16 Sep 2021 15:41:19 +0200 Subject: [PATCH 17/39] enb,nsa: fix deriviation of UL ARFCN from DL ARFCN for FDD bands --- srsenb/src/enb_cfg_parser.cc | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index d7666ef84..388b321ca 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1194,12 +1194,9 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ // auto-detect UL frequency if (cfg.ul_earfcn == 0) { // derive UL ARFCN from given DL ARFCN - uint16_t nr_band = band_helper.get_band_from_dl_freq_Hz(phy_cell_cfg.dl_freq_hz); - srsran_duplex_mode_t nr_duplex = band_helper.get_duplex_mode(nr_band); - if (nr_duplex == SRSRAN_DUPLEX_MODE_TDD) { - cfg.ul_earfcn = cfg.dl_earfcn; - } else { - ERROR("Can't derive UL ARFCN from DL ARFCN"); + cfg.ul_earfcn = band_helper.get_ul_arfcn_from_dl_arfcn(cfg.dl_earfcn); + if (cfg.ul_earfcn == 0) { + ERROR("Can't derive UL ARFCN from DL ARFCN %d", cfg.dl_earfcn); return SRSRAN_ERROR; } } From e57ffca722cedd18ca19eed685103729d54c293e Mon Sep 17 00:00:00 2001 From: Fabian Eckermann <30895211+FabianEckermann@users.noreply.github.com> Date: Mon, 20 Sep 2021 14:29:25 +0200 Subject: [PATCH 18/39] gnss_sync: fix timestamp to TTI conversion * Improve reliability of timestamp to tti conversion Difftime is not reliable as it might use 32 bit calculation, depending on the system. This leads to wrong frame numbers and subframe indices. I encountered this Issue when testing the pssch_ue exampel on my system and the conversion from timestamp to frame number and sf idx was wrong. * Improve GNSS Sync Added loop to check for GNSS alignment while syncing. If the received GNSS signal is weak, synchronization errors might occur while syncing. --- lib/src/phy/ue/ue_sync.c | 72 +++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 38 deletions(-) diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index 82c5b00e1..3cbd03790 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -928,31 +928,44 @@ int srsran_ue_sync_run_find_gnss_mode(srsran_ue_sync_t* q, INFO("Calibration samples received start at %ld + %f", q->last_timestamp.full_secs, q->last_timestamp.frac_secs); // round to nearest second - srsran_timestamp_t ts_next_rx; + srsran_timestamp_t ts_next_rx, ts_next_rx_tmp, ts_tmp; srsran_timestamp_copy(&ts_next_rx, &q->last_timestamp); ts_next_rx.full_secs++; ts_next_rx.frac_secs = 0.0; - INFO("Next desired recv at %ld + %f", ts_next_rx.full_secs, ts_next_rx.frac_secs); + srsran_timestamp_copy(&ts_next_rx_tmp, &ts_next_rx); + INFO("Next desired recv at %ld + %f\n", ts_next_rx_tmp.full_secs, ts_next_rx_tmp.frac_secs); // get difference in time between second rx and now - srsran_timestamp_sub(&ts_next_rx, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); - srsran_timestamp_sub(&ts_next_rx, 0, 0.001); ///< account for samples that have already been rx'ed + srsran_timestamp_sub(&ts_next_rx_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); + srsran_timestamp_sub(&ts_next_rx_tmp, 0, 0.001); ///< account for samples that have already been rx'ed - uint64_t align_len = srsran_timestamp_uint64(&ts_next_rx, q->sf_len * 1000); + uint64_t align_len = srsran_timestamp_uint64(&ts_next_rx_tmp, q->sf_len * 1000); - DEBUG("Difference between first recv is %ld + %f, realigning %" PRIu64 " samples", - ts_next_rx.full_secs, - ts_next_rx.frac_secs, + DEBUG("Difference between first recv is %ld + %f, realigning %" PRIu64 " samples\n", + ts_next_rx_tmp.full_secs, + ts_next_rx_tmp.frac_secs, align_len); // receive align_len samples into dummy_buffer, make sure to not exceed buffer len uint32_t sample_count = 0; - while (sample_count < align_len) { - uint32_t actual_rx_len = SRSRAN_MIN(align_len, DUMMY_BUFFER_NUM_SAMPLES); - actual_rx_len = SRSRAN_MIN(align_len - sample_count, actual_rx_len); + while (align_len > q->sf_len) { + uint32_t actual_rx_len = SRSRAN_MIN(align_len, q->sf_len); q->recv_callback(q->stream, dummy_offset_buffer, actual_rx_len, &q->last_timestamp); - sample_count += actual_rx_len; + + srsran_timestamp_copy(&ts_tmp, &ts_next_rx); + srsran_timestamp_sub(&ts_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); + srsran_timestamp_sub(&ts_tmp, 0, 0.001); ///< account for samples that have already been rx'ed + align_len = srsran_timestamp_uint64(&ts_tmp, q->sf_len * 1000); + + if (align_len > q->sf_len * 1000) { + ts_next_rx.full_secs++; + ts_next_rx.frac_secs = 0.0; + srsran_timestamp_copy(&ts_tmp, &ts_next_rx); + srsran_timestamp_sub(&ts_tmp, q->last_timestamp.full_secs, q->last_timestamp.frac_secs); + srsran_timestamp_sub(&ts_tmp, 0, 0.001); ///< account for samples that have already been rx'ed + align_len = srsran_timestamp_uint64(&ts_tmp, q->sf_len * 1000); + } } DEBUG("Received %d samples during alignment", sample_count); @@ -1017,39 +1030,22 @@ int srsran_ue_sync_set_tti_from_timestamp(srsran_ue_sync_t* q, srsran_timestamp_ time_t t_cur = rx_timestamp->full_secs; DEBUG("t_cur=%ld", t_cur); - // time_t of reference UTC time on 1. Jan 1900 at 0:00 - // If we put this date in https://www.epochconverter.com it returns a negative number - time_t t_ref = {0}; -#if 0 - struct tm t = {0}; - t.tm_year = 1900; // year-1900 - t.tm_mday = 1; // first of January - // t.tm_isdst = 0; // Is DST on? 1 = yes, 0 = no, -1 = unknown - t_ref = mktime(&t); -#endif - - DEBUG("t_ref=%ld", t_ref); + // 3GPP Reference UTC time is 1. Jan 1900 at 0:00 + // If we put this date in https://www.epochconverter.com it returns a negative number (-2208988800) + // as epoch time starts at 1. Jan 1970 at 0:00 + uint64_t epoch_offset_3gpp = 2208988800; static const uint32_t MSECS_PER_SEC = 1000; - DEBUG("diff=%f", difftime(t_cur, t_ref)); - - double time_diff_secs = difftime(t_cur, t_ref); - - if (time_diff_secs < 0) { - fprintf(stderr, "Time diff between Rx timestamp and reference UTC is negative. Is the timestamp correct?\n"); - return SRSRAN_ERROR; - } - - DEBUG("time diff in s %f", time_diff_secs); + uint64_t time_3gpp_secs = t_cur + epoch_offset_3gpp; // convert to ms and add fractional part - double time_diff_msecs = time_diff_secs * MSECS_PER_SEC + rx_timestamp->frac_secs; - DEBUG("time diff in ms %f", time_diff_msecs); + uint64_t time_3gpp_msecs = (time_3gpp_secs + rx_timestamp->frac_secs) * MSECS_PER_SEC; + DEBUG("rx time with 3gpp base in ms %lu\n", time_3gpp_msecs); // calculate SFN and SF index according to TS 36.331 Sec. 5.10.14 - q->frame_number = ((uint32_t)floor(0.1 * (time_diff_msecs - q->sfn_offset))) % 1024; - q->sf_idx = ((uint32_t)floor(time_diff_msecs - q->sfn_offset)) % 10; + q->frame_number = (uint32_t)(((uint64_t)floor(0.1 * (time_3gpp_msecs - q->sfn_offset))) % 1024); + q->sf_idx = (uint32_t)(((uint64_t)floor(time_3gpp_msecs - q->sfn_offset)) % 10); return SRSRAN_SUCCESS; } From fb294c8b34fce0ccc7a5c1966fd9d4a7d21a766b Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 20 Sep 2021 18:28:52 +0200 Subject: [PATCH 19/39] Set default UE inactivity timeout after RRC Reestablishment complete --- srsenb/src/stack/rrc/rrc_ue.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 059d0f288..f9fc766b9 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -340,6 +340,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete: save_ul_message(std::move(original_pdu)); handle_rrc_con_reest_complete(&ul_dcch_msg.msg.c1().rrc_conn_reest_complete(), std::move(pdu)); + set_activity_timeout(UE_INACTIVITY_TIMEOUT); set_activity(); break; case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer: From 7ba5099bee74a8013a49e5b2d87abfc7efa222ab Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 20 Sep 2021 10:53:09 +0200 Subject: [PATCH 20/39] Implement CSI-RS resource mapping validation --- .../srsran/phy/ch_estimation/csi_rs_cfg.h | 2 ++ lib/src/asn1/rrc_nr_utils.cc | 17 ++++++++++++++ lib/src/phy/ch_estimation/csi_rs.c | 23 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h b/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h index 3da47d268..1be7edf90 100644 --- a/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h +++ b/lib/include/srsran/phy/ch_estimation/csi_rs_cfg.h @@ -128,4 +128,6 @@ typedef struct SRSRAN_API { uint32_t count; ///< Number of resources in the set } srsran_csi_rs_zp_set_t; +SRSRAN_API bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t *res); + #endif // SRSRAN_CSI_RS_CFG_H diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 32c386a74..679b38067 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -1070,6 +1070,15 @@ bool make_phy_zp_csi_rs_resource(const asn1::rrc_nr::zp_csi_rs_res_s& zp_csi_rs_ } zp_csi_rs_resource.resource_mapping.freq_band.nof_rb = zp_csi_rs_res.res_map.freq_band.nrof_rbs; zp_csi_rs_resource.resource_mapping.freq_band.start_rb = zp_csi_rs_res.res_map.freq_band.start_rb; + + // Validate CSI-RS resource mapping + if (not srsran_csi_rs_resource_mapping_is_valid(&zp_csi_rs_resource.resource_mapping)) { + asn1::json_writer json_writer; + zp_csi_rs_res.res_map.to_json(json_writer); + asn1::log_error("Resource mapping is invalid or not implemented: %s", json_writer.to_string()); + return false; + } + if (zp_csi_rs_res.periodicity_and_offset_present) { switch (zp_csi_rs_res.periodicity_and_offset.type()) { case csi_res_periodicity_and_offset_c::types_opts::options::slots4: @@ -1228,6 +1237,14 @@ bool make_phy_nzp_csi_rs_resource(const asn1::rrc_nr::nzp_csi_rs_res_s& asn1_nzp csi_rs_nzp_resource.resource_mapping.freq_band.nof_rb = asn1_nzp_csi_rs_res.res_map.freq_band.nrof_rbs; csi_rs_nzp_resource.resource_mapping.freq_band.start_rb = asn1_nzp_csi_rs_res.res_map.freq_band.start_rb; + // Validate CSI-RS resource mapping + if (not srsran_csi_rs_resource_mapping_is_valid(&csi_rs_nzp_resource.resource_mapping)) { + asn1::json_writer json_writer; + asn1_nzp_csi_rs_res.res_map.to_json(json_writer); + asn1::log_error("Resource mapping is invalid or not implemented: %s", json_writer.to_string()); + return false; + } + csi_rs_nzp_resource.power_control_offset = asn1_nzp_csi_rs_res.pwr_ctrl_offset; if (asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss_present) { csi_rs_nzp_resource.power_control_offset_ss = asn1_nzp_csi_rs_res.pwr_ctrl_offset_ss.to_number(); diff --git a/lib/src/phy/ch_estimation/csi_rs.c b/lib/src/phy/ch_estimation/csi_rs.c index cfe490705..6c7c3920b 100644 --- a/lib/src/phy/ch_estimation/csi_rs.c +++ b/lib/src/phy/ch_estimation/csi_rs.c @@ -232,6 +232,29 @@ static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resourc return SRSRAN_ERROR; } +bool srsran_csi_rs_resource_mapping_is_valid(const srsran_csi_rs_resource_mapping_t* res) +{ + if (res == NULL) { + return false; + } + + if (csi_rs_nof_cdm_groups(res) < 1) { + return false; + } + + uint32_t l_list[CSI_RS_MAX_SYMBOLS_SLOT] = {}; + if (csi_rs_location_get_l_list(res, 0, l_list) < SRSRAN_SUCCESS) { + return false; + } + + uint32_t k_list[CSI_RS_MAX_SUBC_PRB] = {}; + if (csi_rs_location_get_k_list(res, 0, k_list) < SRSRAN_SUCCESS) { + return false; + } + + return true; +} + uint32_t csi_rs_count(srsran_csi_rs_density_t density, uint32_t nprb) { switch (density) { From 63bb86bce1cb68da322da0f265979c3e6f46ffe6 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 20 Sep 2021 12:03:46 +0200 Subject: [PATCH 21/39] Added SS type conversion to string --- lib/include/srsran/phy/common/phy_common_nr.h | 7 +++++ lib/src/phy/common/phy_common_nr.c | 25 ++++++++++++++++ lib/src/phy/phch/ra_dl_nr.c | 3 +- lib/src/phy/ue/test/ue_dl_nr_file_test.c | 5 ++-- srsue/src/phy/nr/cc_worker.cc | 30 ++++++++++--------- 5 files changed, 52 insertions(+), 18 deletions(-) diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 5f50e650f..309cbfe92 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -492,6 +492,13 @@ SRSRAN_API const char* srsran_rnti_type_str(srsran_rnti_type_t rnti_type); */ SRSRAN_API const char* srsran_rnti_type_str_short(srsran_rnti_type_t rnti_type); +/** + * @brief Get the Search Space Type string for a given type + * @param ss_type The given Search Space Type + * @return The string describing the SS Type + */ +SRSRAN_API const char* srsran_ss_type_str(srsran_search_space_type_t ss_type); + /** * @brief Get the RNTI type name for NR * @param rnti_type RNTI type name diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index cb8b5e642..39269ee6d 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -63,6 +63,31 @@ const char* srsran_rnti_type_str_short(srsran_rnti_type_t rnti_type) return "unknown"; } +const char* srsran_ss_type_str(srsran_search_space_type_t ss_type) +{ + switch (ss_type) { + case srsran_search_space_type_common_0: + return "common0"; + case srsran_search_space_type_common_0A: + return "common0A"; + case srsran_search_space_type_common_1: + return "common1"; + case srsran_search_space_type_common_2: + return "common2"; + case srsran_search_space_type_common_3: + return "common3"; + case srsran_search_space_type_ue: + return "ue"; + case srsran_search_space_type_rar: + return "rar"; + case srsran_search_space_type_cg: + return "cg"; + default:; // Do nothing + break; + } + return "unknown"; +} + const char* srsran_dci_format_nr_string(srsran_dci_format_nr_t format) { switch (format) { diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index f6aebb3a3..c656889e1 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -177,7 +177,7 @@ int srsran_ra_dl_nr_time(const srsran_sch_hl_cfg_nr_t* cfg, srsran_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant); } } else { - ERROR("Unhandled case %s, ss_type=%d", srsran_rnti_type_str(rnti_type), ss_type); + ERROR("Unhandled case %s, ss_type=%s", srsran_rnti_type_str(rnti_type), srsran_ss_type_str(ss_type)); } // Validate S and L parameters @@ -340,4 +340,3 @@ uint32_t srsran_ra_nr_type1_riv(uint32_t N_prb, uint32_t start_rb, uint32_t leng { return srsran_sliv_from_s_and_l(N_prb, start_rb, length_rb); } - diff --git a/lib/src/phy/ue/test/ue_dl_nr_file_test.c b/lib/src/phy/ue/test/ue_dl_nr_file_test.c index 45ca71d7a..5372a3d0e 100644 --- a/lib/src/phy/ue/test/ue_dl_nr_file_test.c +++ b/lib/src/phy/ue/test/ue_dl_nr_file_test.c @@ -114,11 +114,12 @@ static int work_ue_dl(srsran_ue_dl_nr_t* ue_dl, srsran_slot_cfg_t* slot) // Print PDCCH blind search candidates for (uint32_t i = 0; i < ue_dl->pdcch_info_count; i++) { const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl->pdcch_info[i]; - INFO("PDCCH: rnti=0x%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " + INFO("PDCCH: %s-rnti=0x%x, crst_id=%d, ss_type=%s, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " "nof_bits=%d; crc=%s;", + srsran_rnti_type_str_short(info->dci_ctx.rnti_type), info->dci_ctx.rnti, info->dci_ctx.coreset_id, - info->dci_ctx.ss_type, + srsran_ss_type_str(info->dci_ctx.ss_type), info->dci_ctx.location.ncce, info->dci_ctx.location.L, info->measure.epre_dBfs, diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 337baa17e..6416399ef 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -175,20 +175,22 @@ void cc_worker::decode_pdcch_dl() if (logger.debug.enabled()) { for (uint32_t i = 0; i < ue_dl.pdcch_info_count; i++) { const srsran_ue_dl_nr_pdcch_info_t* info = &ue_dl.pdcch_info[i]; - logger.debug("PDCCH: dci=%s, rnti=%x, crst_id=%d, ss_type=%d, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " - "evm=%f; nof_bits=%d; crc=%s;", - srsran_dci_format_nr_string(info->dci_ctx.format), - info->dci_ctx.rnti, - info->dci_ctx.coreset_id, - info->dci_ctx.ss_type, - info->dci_ctx.location.ncce, - info->dci_ctx.location.L, - info->measure.epre_dBfs, - info->measure.rsrp_dBfs, - info->measure.norm_corr, - info->result.evm, - info->nof_bits, - info->result.crc ? "OK" : "KO"); + logger.debug( + "PDCCH: dci=%s, %s-rnti=%x, crst_id=%d, ss_type=%s, ncce=%d, al=%d, EPRE=%+.2f, RSRP=%+.2f, corr=%.3f; " + "evm=%f; nof_bits=%d; crc=%s;", + srsran_dci_format_nr_string(info->dci_ctx.format), + srsran_rnti_type_str_short(info->dci_ctx.rnti_type), + info->dci_ctx.rnti, + info->dci_ctx.coreset_id, + srsran_ss_type_str(info->dci_ctx.ss_type), + info->dci_ctx.location.ncce, + info->dci_ctx.location.L, + info->measure.epre_dBfs, + info->measure.rsrp_dBfs, + info->measure.norm_corr, + info->result.evm, + info->nof_bits, + info->result.crc ? "OK" : "KO"); } } } From de00b802287dc5562cf02d26c827e4a57ee7b6a3 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 20 Sep 2021 12:54:15 +0200 Subject: [PATCH 22/39] Review NR NSA CFO estimation and compensation --- lib/include/srsran/interfaces/ue_nr_interfaces.h | 1 + lib/src/phy/ch_estimation/csi_rs.c | 2 +- lib/src/phy/sync/ssb.c | 2 +- lib/src/phy/sync/test/ssb_measure_test.c | 2 +- lib/src/phy/ue/ue_ul_nr.c | 2 +- srsue/hdr/phy/nr/state.h | 9 ++++----- srsue/src/phy/nr/cc_worker.cc | 5 +++-- srsue/src/phy/nr/worker_pool.cc | 2 +- srsue/src/phy/sync.cc | 2 +- 9 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index 030082010..b67fe3372 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -180,6 +180,7 @@ struct phy_args_nr_t { bool store_pdsch_ko = false; float trs_epre_ema_alpha = 0.1f; ///< EPRE measurement exponential average alpha float trs_rsrp_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha + float trs_sinr_ema_alpha = 0.1f; ///< SINR measurement exponential average alpha float trs_cfo_ema_alpha = 0.1f; ///< RSRP measurement exponential average alpha bool enable_worker_cfo = true; ///< Enable/Disable open loop CFO correction at the workers diff --git a/lib/src/phy/ch_estimation/csi_rs.c b/lib/src/phy/ch_estimation/csi_rs.c index 6c7c3920b..75a77a9e8 100644 --- a/lib/src/phy/ch_estimation/csi_rs.c +++ b/lib/src/phy/ch_estimation/csi_rs.c @@ -719,7 +719,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier, float cfo_max = 0.0f; for (uint32_t i = 1; i < count; i++) { float time_diff = srsran_symbol_distance_s(measurements[i - 1].l0, measurements[i].l0, carrier->scs); - float phase_diff = cargf(measurements[i - 1].corr * conjf(measurements[i].corr)); + float phase_diff = cargf(measurements[i].corr * conjf(measurements[i - 1].corr)); float cfo_max_temp = 0.0f; // Avoid zero division diff --git a/lib/src/phy/sync/ssb.c b/lib/src/phy/sync/ssb.c index 357ab7710..7c2a859a0 100644 --- a/lib/src/phy/sync/ssb.c +++ b/lib/src/phy/sync/ssb.c @@ -697,7 +697,7 @@ ssb_measure(srsran_ssb_t* q, const cf_t ssb_grid[SRSRAN_SSB_NOF_RE], uint32_t N_ // Compute CFO in Hz float distance_s = srsran_symbol_distance_s(SRSRAN_PSS_NR_SYMBOL_IDX, SRSRAN_SSS_NR_SYMBOL_IDX, q->cfg.scs); float cfo_hz_max = 1.0f / distance_s; - float cfo_hz = cargf(corr_pss * conjf(corr_sss)) / (2.0f * M_PI) * cfo_hz_max; + float cfo_hz = cargf(corr_sss * conjf(corr_pss)) / (2.0f * M_PI) * cfo_hz_max; // Compute average RSRP float rsrp_pss = SRSRAN_CSQABS(corr_pss); diff --git a/lib/src/phy/sync/test/ssb_measure_test.c b/lib/src/phy/sync/test/ssb_measure_test.c index e6c328d59..d4e5b39c0 100644 --- a/lib/src/phy/sync/test/ssb_measure_test.c +++ b/lib/src/phy/sync/test/ssb_measure_test.c @@ -71,7 +71,7 @@ static void run_channel() } // CFO - srsran_vec_apply_cfo(buffer, -cfo_hz / srate_hz, buffer, sf_len); + srsran_vec_apply_cfo(buffer, cfo_hz / srate_hz, buffer, sf_len); // AWGN srsran_channel_awgn_run_c(&awgn, buffer, buffer, sf_len); diff --git a/lib/src/phy/ue/ue_ul_nr.c b/lib/src/phy/ue/ue_ul_nr.c index 38e8b0fb8..e92ea7974 100644 --- a/lib/src/phy/ue/ue_ul_nr.c +++ b/lib/src/phy/ue/ue_ul_nr.c @@ -101,7 +101,7 @@ void srsran_ue_ul_nr_set_freq_offset(srsran_ue_ul_nr_t* q, float freq_offset_hz) return; } - q->freq_offset_hz = freq_offset_hz; + q->freq_offset_hz = -freq_offset_hz; } int srsran_ue_ul_nr_encode_pusch(srsran_ue_ul_nr_t* q, diff --git a/srsue/hdr/phy/nr/state.h b/srsue/hdr/phy/nr/state.h index c6f8c3186..78891e68e 100644 --- a/srsue/hdr/phy/nr/state.h +++ b/srsue/hdr/phy/nr/state.h @@ -482,8 +482,8 @@ public: // Compute synch metrics and report it to the PHY state sync_metrics_t new_sync_metrics = {}; - new_sync_metrics.cfo = new_meas.cfo_hz; - set_sync_metrics(sync_metrics); + new_sync_metrics.cfo = new_meas.cfo_hz + ul_ext_cfo_hz; + set_sync_metrics(new_sync_metrics); // Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state srsran_csi_channel_measurements_t measurements = {}; @@ -499,11 +499,10 @@ public: trs_measurements_mutex.lock(); trs_measurements.rsrp_dB = SRSRAN_VEC_SAFE_EMA(new_meas.rsrp_dB, trs_measurements.rsrp_dB, args.trs_epre_ema_alpha); trs_measurements.epre_dB = SRSRAN_VEC_SAFE_EMA(new_meas.epre_dB, trs_measurements.epre_dB, args.trs_rsrp_ema_alpha); + trs_measurements.snr_dB = SRSRAN_VEC_SAFE_EMA(new_meas.snr_dB, trs_measurements.snr_dB, args.trs_sinr_ema_alpha); // Consider CFO measurement invalid if the SNR is negative. In this case, set CFO to 0. - if (trs_measurements.snr_dB > 0.0f) { + if (new_meas.snr_dB > 0.0f) { trs_measurements.cfo_hz = SRSRAN_VEC_SAFE_EMA(new_meas.cfo_hz, trs_measurements.cfo_hz, args.trs_cfo_ema_alpha); - } else { - trs_measurements.cfo_hz = 0.0f; } trs_measurements.nof_re++; trs_measurements_mutex.unlock(); diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 6416399ef..1d7d12f75 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -487,10 +487,11 @@ bool cc_worker::work_dl() // Compensate CFO from TRS measurements if (std::isnormal(phy.args.enable_worker_cfo)) { - float dl_cfo_hz = phy.get_dl_cfo(); + float dl_cfo_hz = phy.get_dl_cfo(); + float dl_cfo_norm = -dl_cfo_hz / (1000.0f * ue_ul.ifft.sf_sz); for (cf_t* b : rx_buffer) { if (b != nullptr and ue_ul.ifft.sf_sz != 0) { - srsran_vec_apply_cfo(b, dl_cfo_hz / (1000.0f * ue_ul.ifft.sf_sz), b, ue_ul.ifft.sf_sz); + srsran_vec_apply_cfo(b, dl_cfo_norm, b, ue_ul.ifft.sf_sz); } } } diff --git a/srsue/src/phy/nr/worker_pool.cc b/srsue/src/phy/nr/worker_pool.cc index d41183d4b..2c8b62493 100644 --- a/srsue/src/phy/nr/worker_pool.cc +++ b/srsue/src/phy/nr/worker_pool.cc @@ -79,7 +79,7 @@ sf_worker* worker_pool::wait_worker(uint32_t tti) if (prach_buffer->is_ready_to_send(tti, phy_state.cfg.carrier.pci)) { uint32_t nof_prach_sf = 0; float prach_target_power = 0.0f; - cf_t* prach_ptr = prach_buffer->generate(-phy_state.get_ul_cfo() / 15000, &nof_prach_sf, &prach_target_power); + cf_t* prach_ptr = prach_buffer->generate(phy_state.get_ul_cfo() / 15000, &nof_prach_sf, &prach_target_power); worker->set_prach(prach_ptr, prach_target_power); } diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 5d7c56608..c8fd3a81c 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -543,7 +543,7 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, // As UE sync compensates CFO externally based on LTE signal and the NR carrier may estimate the CFO from the LTE // signal. It is necessary setting an NR external CFO offset to compensate it. - nr_worker_pool->set_ul_ext_cfo(-srsran_ue_sync_get_cfo(&ue_sync)); + nr_worker_pool->set_ul_ext_cfo(srsran_ue_sync_get_cfo(&ue_sync)); // NR worker needs to be launched first, phy_common::worker_end expects first the NR worker and the LTE worker. worker_com->semaphore.push(nr_worker); From 51d6ab3b3fb6dd01844b9dcc95ad5e5a89c0126d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 20 Sep 2021 15:05:07 +0200 Subject: [PATCH 23/39] Disable CSI-RS resource mapping number of port check --- lib/src/phy/ch_estimation/csi_rs.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/src/phy/ch_estimation/csi_rs.c b/lib/src/phy/ch_estimation/csi_rs.c index 75a77a9e8..c4a77c78d 100644 --- a/lib/src/phy/ch_estimation/csi_rs.c +++ b/lib/src/phy/ch_estimation/csi_rs.c @@ -89,8 +89,7 @@ static int csi_rs_location_get_k_list(const srsran_csi_rs_resource_mapping_t* re } // Row 2 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { + if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) { if (resource->density == srsran_csi_rs_resource_mapping_density_one || resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { @@ -142,8 +141,7 @@ static int csi_rs_location_get_l_list(const srsran_csi_rs_resource_mapping_t* re } // Row 2 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { + if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) { if (resource->density == srsran_csi_rs_resource_mapping_density_one || resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { @@ -197,24 +195,14 @@ bool srsran_csi_rs_send(const srsran_csi_rs_period_and_offset_t* periodicity, co static int csi_rs_nof_cdm_groups(const srsran_csi_rs_resource_mapping_t* resource) { + // Row 1 if (resource->row == srsran_csi_rs_resource_mapping_row_1 && resource->nof_ports == 1 && resource->density == srsran_csi_rs_resource_mapping_density_three && resource->cdm == srsran_csi_rs_cdm_nocdm) { return 1; } - // Row 1 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { - if (resource->density == srsran_csi_rs_resource_mapping_density_one || - resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || - resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { - return 1; - } - } - // Row 2 - if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->nof_ports == 1 && - resource->cdm == srsran_csi_rs_cdm_nocdm) { + if (resource->row == srsran_csi_rs_resource_mapping_row_2 && resource->cdm == srsran_csi_rs_cdm_nocdm) { if (resource->density == srsran_csi_rs_resource_mapping_density_one || resource->density == srsran_csi_rs_resource_mapping_density_dot5_even || resource->density == srsran_csi_rs_resource_mapping_density_dot5_odd) { From ffba972fb7049eb29ca02ef3ac9846c1fc8c72ab Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 20 Sep 2021 17:41:27 +0200 Subject: [PATCH 24/39] Fix gnb amplitude --- lib/include/srsran/phy/gnb/gnb_dl.h | 2 ++ lib/src/phy/gnb/gnb_dl.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/include/srsran/phy/gnb/gnb_dl.h b/lib/include/srsran/phy/gnb/gnb_dl.h index 680fdacbe..77f0b07d0 100644 --- a/lib/include/srsran/phy/gnb/gnb_dl.h +++ b/lib/include/srsran/phy/gnb/gnb_dl.h @@ -67,6 +67,8 @@ SRSRAN_API int srsran_gnb_dl_pdsch_put(srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, uint8_t* data[SRSRAN_MAX_TB]); +SRSRAN_API float srsran_gnb_dl_get_maximum_signal_power_dBfs(uint32_t nof_prb); + SRSRAN_API int srsran_gnb_dl_pdsch_info(const srsran_gnb_dl_t* q, const srsran_sch_cfg_nr_t* cfg, char* str, uint32_t str_len); diff --git a/lib/src/phy/gnb/gnb_dl.c b/lib/src/phy/gnb/gnb_dl.c index 0f83f0233..b16a6bd3b 100644 --- a/lib/src/phy/gnb/gnb_dl.c +++ b/lib/src/phy/gnb/gnb_dl.c @@ -13,6 +13,11 @@ #include "srsran/phy/gnb/gnb_dl.h" #include +static float gnb_dl_get_norm_factor(uint32_t nof_prb) +{ + return 0.05f / sqrtf(nof_prb); +} + static int gnb_dl_alloc_prb(srsran_gnb_dl_t* q, uint32_t new_nof_prb) { if (q->max_prb < new_nof_prb) { @@ -162,11 +167,21 @@ void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q) return; } + float norm_factor = gnb_dl_get_norm_factor(q->pdcch.carrier.nof_prb); + for (uint32_t i = 0; i < q->nof_tx_antennas; i++) { srsran_ofdm_tx_sf(&q->fft[i]); + + srsran_vec_sc_prod_cfc(q->fft[i].cfg.out_buffer, norm_factor, q->fft[i].cfg.out_buffer, (uint32_t)q->fft[i].sf_sz); } } +float srsran_gnb_dl_get_maximum_signal_power_dBfs(uint32_t nof_prb) +{ + return srsran_convert_amplitude_to_dB(gnb_dl_get_norm_factor(nof_prb)) + + srsran_convert_power_to_dB((float)nof_prb * SRSRAN_NRE) + 3.0f; +} + int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q) { if (q == NULL) { From d59ebfce9d26e83e3448457f572235fdd2286f13 Mon Sep 17 00:00:00 2001 From: Fabian Eckermann Date: Mon, 20 Sep 2021 11:49:38 +0200 Subject: [PATCH 25/39] add lock for fftw wisdom --- lib/src/phy/dft/dft_fftw.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/dft/dft_fftw.c b/lib/src/phy/dft/dft_fftw.c index 0f5599612..8b4e4adef 100644 --- a/lib/src/phy/dft/dft_fftw.c +++ b/lib/src/phy/dft/dft_fftw.c @@ -50,7 +50,21 @@ __attribute__((constructor)) static void srsran_dft_load() #ifdef FFTW_WISDOM_FILE char full_path[256]; get_fftw_wisdom_file(full_path, sizeof(full_path)); - fftwf_import_wisdom_from_filename(full_path); + // lockf needs a file descriptor open for writing, so this must be r+ + FILE* fd = fopen(full_path, "r+"); + if (fd == NULL) { + return; + } + if (lockf(fileno(fd), F_LOCK, 0) == -1) { + perror("lockf()"); + return; + } + fftwf_import_wisdom_from_file(fd); + if (lockf(fileno(fd), F_ULOCK, 0) == -1) { + perror("u-lockf()"); + return; + } + fclose(fd); #else printf("Warning: FFTW Wisdom file not defined\n"); #endif @@ -62,7 +76,20 @@ __attribute__((destructor)) static void srsran_dft_exit() #ifdef FFTW_WISDOM_FILE char full_path[256]; get_fftw_wisdom_file(full_path, sizeof(full_path)); - fftwf_export_wisdom_to_filename(full_path); + FILE* fd = fopen(full_path, "w"); + if (fd == NULL) { + return; + } + if (lockf(fileno(fd), F_LOCK, 0) == -1) { + perror("lockf()"); + return; + } + fftwf_export_wisdom_to_file(fd); + if (lockf(fileno(fd), F_ULOCK, 0) == -1) { + perror("u-lockf()"); + return; + } + fclose(fd); #endif fftwf_cleanup(); } From ad646f436c446227f58c5c428e112969eb0ff9ac Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 20 Sep 2021 19:18:32 +0200 Subject: [PATCH 26/39] Ignore PDSCH during cell selection --- srsue/hdr/phy/phy_common.h | 2 ++ srsue/src/phy/lte/cc_worker.cc | 7 ++++++- srsue/src/phy/phy.cc | 8 ++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index 18cc46b7c..ede7de462 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -56,6 +56,8 @@ public: srsran::phy_cfg_mbsfn_t mbsfn_config = {}; + std::atomic cell_is_selecting = {false}; + // Secondary serving cell states scell::state cell_state; diff --git a/srsue/src/phy/lte/cc_worker.cc b/srsue/src/phy/lte/cc_worker.cc index 9fa2e921e..bf2352d34 100644 --- a/srsue/src/phy/lte/cc_worker.cc +++ b/srsue/src/phy/lte/cc_worker.cc @@ -280,7 +280,12 @@ bool cc_worker::work_dl_regular() // Decode PDSCH decode_pdsch(ack_resource, &dl_action, dl_ack); - // Informs Stack about the decoding status + // Informs Stack about the decoding status, send NACK if cell is in process of re-selection + if (phy->cell_is_selecting) { + for (uint32_t i = 0; i < SRSRAN_MAX_CODEWORDS; i++) { + dl_ack[i] = false; + } + } phy->stack->tb_decoded(cc_idx, mac_grant, dl_ack); } diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index c6fb51f3a..94672b253 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -306,6 +306,10 @@ bool phy::cell_select(phy_cell_t cell) if (sfsync.cell_select_init(cell)) { // Update PCI before starting the background command to make sure PRACH gets the updated value selected_cell.id = cell.pci; + + // Indicate workers that cell selection is in progress + common.cell_is_selecting = true; + cmd_worker_cell.add_cmd([this, cell]() { // Wait SYNC transitions to IDLE sfsync.wait_idle(); @@ -320,6 +324,10 @@ bool phy::cell_select(phy_cell_t cell) selected_cell = sync_cell; } stack->cell_select_complete(ret); + + // Indicate workers that cell selection has finished + common.cell_is_selecting = false; + }); return true; } else { From fbfca42ef3c5b2f3f887e3711413865ffb1c856c Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 21 Sep 2021 11:18:04 +0200 Subject: [PATCH 27/39] ue,mux_nr: add missing break --- srsue/src/stack/mac_nr/mux_nr.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/srsue/src/stack/mac_nr/mux_nr.cc b/srsue/src/stack/mac_nr/mux_nr.cc index 6aab037e5..eb9bfbe6f 100644 --- a/srsue/src/stack/mac_nr/mux_nr.cc +++ b/srsue/src/stack/mac_nr/mux_nr.cc @@ -178,6 +178,7 @@ void mux_nr::generate_bsr_mac_ce(const srsran::bsr_format_nr_t& format) break; case srsran::LONG_BSR: add_bsr_ce = lbsr_ce; + break; default: logger.error("MUX can only be instructred to generate short or long BSRs."); } From e0be361fdec0235bab3c3b4118f414e424779df4 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 16 Sep 2021 15:17:35 +0200 Subject: [PATCH 28/39] Corrected default rb.conf --- srsenb/rb.conf.example | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/srsenb/rb.conf.example b/srsenb/rb.conf.example index 27d997fc3..de1cb8f33 100644 --- a/srsenb/rb.conf.example +++ b/srsenb/rb.conf.example @@ -12,9 +12,9 @@ // t_reordering = 35; // t_status_prohibit = 0; // }; -// }; -// enb_specific = { -// dl_max_retx_thresh = 32; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; // }; // } @@ -30,9 +30,9 @@ // t_reordering = 35; // t_status_prohibit = 0; // }; -// }; -// enb_specific = { -// dl_max_retx_thresh = 32; +// enb_specific = { +// dl_max_retx_thresh = 32; +// }; // }; // } From 574683e3ef54bc8223dbc3efc9481e41ae867fc6 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 9 Sep 2021 16:48:32 +0200 Subject: [PATCH 29/39] Fix error message --- lib/src/pdcp/pdcp_entity_lte.cc | 2 +- lib/src/pdcp/pdcp_entity_nr.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/pdcp/pdcp_entity_lte.cc b/lib/src/pdcp/pdcp_entity_lte.cc index 5c73f6539..d616fb0cb 100644 --- a/lib/src/pdcp/pdcp_entity_lte.cc +++ b/lib/src/pdcp/pdcp_entity_lte.cc @@ -54,7 +54,7 @@ bool pdcp_entity_lte::configure(const pdcp_config_t& cnfg_) if (active) { // Already configured if (cnfg_ != cfg) { - logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid)); + logger.error("Bearer reconfiguration not supported. LCID=%s.", rrc->get_rb_name(lcid)); return false; } return true; diff --git a/lib/src/pdcp/pdcp_entity_nr.cc b/lib/src/pdcp/pdcp_entity_nr.cc index a7a7d8c62..ba354599d 100644 --- a/lib/src/pdcp/pdcp_entity_nr.cc +++ b/lib/src/pdcp/pdcp_entity_nr.cc @@ -46,7 +46,7 @@ bool pdcp_entity_nr::configure(const pdcp_config_t& cnfg_) if (active) { // Already configured if (cnfg_ != cfg) { - logger.error("Bearer reconfiguration not supported. LCID=%d.", rrc->get_rb_name(lcid)); + logger.error("Bearer reconfiguration not supported. LCID=%s.", rrc->get_rb_name(lcid)); return false; } return true; From 25a4c7db92bbb246bfb9019209c07990111e87c4 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 16 Sep 2021 09:13:20 +0200 Subject: [PATCH 30/39] SRSENB: make nr_cell_list optional --- srsenb/src/enb_cfg_parser.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 388b321ca..030d37c16 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -747,7 +747,9 @@ int parse_rr(all_args_t* args_, rrc_cfg_t* rrc_cfg_) cell_cnfg.add_field(new rr_sections::cell_list_section(args_, rrc_cfg_)); // NR RRC and cell config section + bool nr_cell_cnfg_present = false; parser::section nr_cell_cnfg("nr_cell_list"); + nr_cell_cnfg.set_optional(&nr_cell_cnfg_present); nr_cell_cnfg.add_field(new rr_sections::nr_cell_list_section(args_, rrc_cfg_)); // Run parser with two sections From 1f6c950dae7ef407cbf724bc7b14a7b63118eb25 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 14 Sep 2021 10:00:24 +0200 Subject: [PATCH 31/39] SRSUE: Fix speed and distance from TA metrics --- srsue/src/phy/sync.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index c8fd3a81c..4acf03daf 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -492,9 +492,11 @@ void sync::run_camping_in_sync_state(lte::sf_worker* lte_worker, Debug("SYNC: Worker %d synchronized", lte_worker->get_id()); // Collect and provide metrics from last successful sync - metrics.sfo = sfo; - metrics.cfo = cfo; - metrics.ta_us = worker_com->ta.get_usec(); + metrics.sfo = sfo; + metrics.cfo = cfo; + metrics.ta_us = worker_com->ta.get_usec(); + metrics.distance_km = worker_com->ta.get_km(); + metrics.speed_kmph = worker_com->ta.get_speed_kmph(tti); for (uint32_t i = 0; i < worker_com->args->nof_lte_carriers; i++) { worker_com->set_sync_metrics(i, metrics); } From 28b956d1286b1fddb2fad8707c7560bcd79681d7 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 20 Sep 2021 10:34:42 +0200 Subject: [PATCH 32/39] Limit PUCCH ACK resources to the max CCE from the configured max_ctrl_symbols instead of from MAX_CFI --- srsenb/src/stack/mac/sched_grid.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 1e5653846..9d4b07a4c 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -80,7 +80,8 @@ void sf_grid_t::init(const sched_cell_params_t& cell_params_) pucch_mask.resize(cc_cfg->nof_prb()); pucch_nrb = (cc_cfg->cfg.nrb_pucch > 0) ? (uint32_t)cc_cfg->cfg.nrb_pucch : 0; srsran_pucch_cfg_t pucch_cfg = cell_params_.pucch_cfg_common; - pucch_cfg.n_pucch = cc_cfg->nof_cce_table[SRSRAN_NOF_CFI - 1] - 1 + cc_cfg->cfg.n1pucch_an; + pucch_cfg.n_pucch = + cc_cfg->nof_cce_table[cell_params_.sched_cfg->max_nof_ctrl_symbols - 1] - 1 + cc_cfg->cfg.n1pucch_an; pucch_nrb = std::max(pucch_nrb, srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1); if (pucch_nrb > 0) { pucch_mask.fill(0, pucch_nrb); From 3eaf5c50cb47d08f262f437a8aaaaae8ed7f0d61 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Mon, 20 Sep 2021 11:08:19 +0200 Subject: [PATCH 33/39] Make PUCCH HARQ region a configurable parameter. Skip grants when ACK falls outside region --- srsenb/enb.conf.example | 7 ++++++- srsenb/hdr/stack/mac/sched_interface.h | 1 + srsenb/src/main.cc | 1 + srsenb/src/stack/mac/sched_grid.cc | 12 +++++++++--- .../src/stack/mac/sched_phy_ch/sf_cch_allocator.cc | 9 +++++++++ 5 files changed, 26 insertions(+), 4 deletions(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 45aaaff21..9938af746 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -170,7 +170,11 @@ enable = false # pusch_mcs: Optional fixed PUSCH MCS (ignores reported CQIs if specified) # pusch_max_mcs: Optional PUSCH MCS limit # min_nof_ctrl_symbols: Minimum number of control symbols -# max_nof_ctrl_symbols: Maximum number of control symbols +# max_nof_ctrl_symbols: Maximum number of control symbols +# pucch_multiplex_enable: Allow PUCCH HARQ to collide with PUSCH and other PUCCH +# pucch_harq_max_rb: Maximum number of RB to be used for PUCCH on the edges of the grid. +# If defined and greater than 0, the scheduler will avoid DL PDCCH allocations if +# PUCCH HARQ falls outside this region # target_bler: Target BLER (in decimal) to achieve via adaptive link # max_delta_dl_cqi: Maximum shift in CQI for adaptive DL link # max_delta_ul_snr: Maximum shift in UL SNR for adaptive UL link @@ -196,6 +200,7 @@ enable = false #min_nof_ctrl_symbols = 1 #max_nof_ctrl_symbols = 3 #pucch_multiplex_enable = false +#pucch_harq_max_rb = 1 #target_bler = 0.05 #max_delta_dl_cqi = 5 #max_delta_ul_snr = 5 diff --git a/srsenb/hdr/stack/mac/sched_interface.h b/srsenb/hdr/stack/mac/sched_interface.h index d6eafc012..4f5f166ea 100644 --- a/srsenb/hdr/stack/mac/sched_interface.h +++ b/srsenb/hdr/stack/mac/sched_interface.h @@ -58,6 +58,7 @@ public: int max_aggr_level = 3; bool adaptive_aggr_level = false; bool pucch_mux_enabled = false; + int pucch_harq_max_rb = 0; float target_bler = 0.05; float max_delta_dl_cqi = 5; float max_delta_ul_snr = 5; diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 33e88f917..37647a001 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -152,6 +152,7 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("scheduler.max_nof_ctrl_symbols", bpo::value(&args->stack.mac.sched.max_nof_ctrl_symbols)->default_value(3), "Number of control symbols") ("scheduler.min_nof_ctrl_symbols", bpo::value(&args->stack.mac.sched.min_nof_ctrl_symbols)->default_value(1), "Minimum number of control symbols") ("scheduler.pucch_multiplex_enable", bpo::value(&args->stack.mac.sched.pucch_mux_enabled)->default_value(false), "Enable PUCCH multiplexing") + ("scheduler.pucch_harq_max_rb", bpo::value(&args->stack.mac.sched.pucch_harq_max_rb)->default_value(0), "Maximum number of RB to be used for PUCCH on the edges of the grid") ("scheduler.target_bler", bpo::value(&args->stack.mac.sched.target_bler)->default_value(0.05), "Target BLER (in decimal) to achieve via adaptive link") ("scheduler.max_delta_dl_cqi", bpo::value(&args->stack.mac.sched.max_delta_dl_cqi)->default_value(5.0), "Maximum shift in CQI for adaptive DL link") ("scheduler.max_delta_ul_snr", bpo::value(&args->stack.mac.sched.max_delta_ul_snr)->default_value(5.0), "Maximum shift in UL SNR for adaptive UL link") diff --git a/srsenb/src/stack/mac/sched_grid.cc b/srsenb/src/stack/mac/sched_grid.cc index 9d4b07a4c..fba1acf28 100644 --- a/srsenb/src/stack/mac/sched_grid.cc +++ b/srsenb/src/stack/mac/sched_grid.cc @@ -80,9 +80,15 @@ void sf_grid_t::init(const sched_cell_params_t& cell_params_) pucch_mask.resize(cc_cfg->nof_prb()); pucch_nrb = (cc_cfg->cfg.nrb_pucch > 0) ? (uint32_t)cc_cfg->cfg.nrb_pucch : 0; srsran_pucch_cfg_t pucch_cfg = cell_params_.pucch_cfg_common; - pucch_cfg.n_pucch = - cc_cfg->nof_cce_table[cell_params_.sched_cfg->max_nof_ctrl_symbols - 1] - 1 + cc_cfg->cfg.n1pucch_an; - pucch_nrb = std::max(pucch_nrb, srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1); + uint32_t harq_pucch = 0; + if (cc_cfg->sched_cfg->pucch_harq_max_rb > 0) { + harq_pucch = cc_cfg->sched_cfg->pucch_harq_max_rb; + } else { + pucch_cfg.n_pucch = + cc_cfg->nof_cce_table[cell_params_.sched_cfg->max_nof_ctrl_symbols - 1] - 1 + cc_cfg->cfg.n1pucch_an; + harq_pucch = srsran_pucch_m(&pucch_cfg, cc_cfg->cfg.cell.cp) / 2 + 1; + } + pucch_nrb = std::max(pucch_nrb, harq_pucch); if (pucch_nrb > 0) { pucch_mask.fill(0, pucch_nrb); pucch_mask.fill(cc_cfg->nof_prb() - pucch_nrb, cc_cfg->nof_prb()); diff --git a/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc b/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc index 5482f354a..b7aa3543f 100644 --- a/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc +++ b/srsenb/src/stack/mac/sched_phy_ch/sf_cch_allocator.cc @@ -181,6 +181,15 @@ bool sf_cch_allocator::alloc_dfs_node(const alloc_record& record, uint32_t start // PUCCH allocation would collide with other PUCCH/PUSCH grants. Try another CCE position continue; } + int low_rb = node.pucch_n_prb < (int)cc_cfg->cfg.cell.nof_prb / 2 + ? node.pucch_n_prb + : cc_cfg->cfg.cell.nof_prb - node.pucch_n_prb - 1; + if (cc_cfg->sched_cfg->pucch_harq_max_rb > 0 && low_rb >= cc_cfg->sched_cfg->pucch_harq_max_rb) { + // PUCCH allocation would fall outside the maximum allowed PUCCH HARQ region. Try another CCE position + logger.info("Skipping PDCCH allocation for CCE=%d due to PUCCH HARQ falling outside region\n", + node.dci_pos.ncce); + continue; + } } node.current_mask.reset(); From 5d051d8832229f56024b2515141ba1c35a3c36c3 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 21 Sep 2021 11:39:05 +0200 Subject: [PATCH 34/39] Set default pucch_harq_max_rb to 0 --- srsenb/enb.conf.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/enb.conf.example b/srsenb/enb.conf.example index 9938af746..a76b90874 100644 --- a/srsenb/enb.conf.example +++ b/srsenb/enb.conf.example @@ -200,7 +200,7 @@ enable = false #min_nof_ctrl_symbols = 1 #max_nof_ctrl_symbols = 3 #pucch_multiplex_enable = false -#pucch_harq_max_rb = 1 +#pucch_harq_max_rb = 0 #target_bler = 0.05 #max_delta_dl_cqi = 5 #max_delta_ul_snr = 5 From dd8db1a9299fab8733b1b7f3314d55843c0eaa53 Mon Sep 17 00:00:00 2001 From: Fabian Eckermann Date: Fri, 10 Sep 2021 17:28:11 +0200 Subject: [PATCH 35/39] Replaced inet_addr() with inet_pton. --- lib/src/common/mac_pcap_net.cc | 8 +++-- lib/src/phy/io/netsink.c | 21 +++++++------ lib/src/phy/io/netsource.c | 25 ++++++++------- srsenb/src/stack/s1ap/s1ap.cc | 17 ++++++++-- srsenb/src/stack/upper/gtpu.cc | 24 +++++++++----- srsepc/src/mbms-gw/mbms-gw.cc | 31 +++++++++++++++---- srsepc/src/mme/nas.cc | 7 ++++- srsepc/src/mme/s1ap.cc | 24 +++++++------- srsepc/src/spgw/gtpc.cc | 13 ++++++-- srsepc/src/spgw/gtpu.cc | 22 +++++++++---- srsue/src/stack/ue_stack_nr.cc | 7 ++++- srsue/src/stack/upper/gw.cc | 16 +++++++--- srsue/src/stack/upper/test/gw_test.cc | 7 ++++- srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h | 9 +++--- 14 files changed, 161 insertions(+), 70 deletions(-) diff --git a/lib/src/common/mac_pcap_net.cc b/lib/src/common/mac_pcap_net.cc index 03984345f..c8a30204c 100644 --- a/lib/src/common/mac_pcap_net.cc +++ b/lib/src/common/mac_pcap_net.cc @@ -49,9 +49,11 @@ uint32_t mac_pcap_net::open(std::string client_ip_addr_, client_udp_port_, bind_addr_str.c_str(), bind_udp_port_); - client_addr.sin_family = AF_INET; - client_addr.sin_addr.s_addr = inet_addr(client_ip_addr_.c_str()); - client_addr.sin_port = htons(client_udp_port_); + + if (not net_utils::set_sockaddr(&client_addr, client_ip_addr_.c_str(), client_udp_port_)) { + logger.error("Invalid client_ip_addr: %s", client_ip_addr_.c_str()); + return SRSRAN_ERROR; + } running = true; ue_id = ue_id_; // start writer thread diff --git a/lib/src/phy/io/netsink.c b/lib/src/phy/io/netsink.c index 6a05d1d17..3a2cb5905 100644 --- a/lib/src/phy/io/netsink.c +++ b/lib/src/phy/io/netsink.c @@ -30,7 +30,7 @@ int srsran_netsink_init(srsran_netsink_t* q, const char* address, uint16_t port, q->sockfd = socket(AF_INET, type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0); if (q->sockfd < 0) { perror("socket"); - return -1; + return SRSRAN_ERROR; } int enable = 1; @@ -44,12 +44,15 @@ int srsran_netsink_init(srsran_netsink_t* q, const char* address, uint16_t port, #endif q->servaddr.sin_family = AF_INET; - q->servaddr.sin_addr.s_addr = inet_addr(address); + if (inet_pton(q->servaddr.sin_family, address, &q->servaddr.sin_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } q->servaddr.sin_port = htons(port); q->connected = false; q->type = type; - return 0; + return SRSRAN_SUCCESS; } void srsran_netsink_free(srsran_netsink_t* q) @@ -64,9 +67,9 @@ int srsran_netsink_set_nonblocking(srsran_netsink_t* q) { if (fcntl(q->sockfd, F_SETFL, O_NONBLOCK)) { perror("fcntl"); - return -1; + return SRSRAN_ERROR; } - return 0; + return SRSRAN_SUCCESS; } int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes) @@ -74,11 +77,11 @@ int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes) if (!q->connected) { if (connect(q->sockfd, &q->servaddr, sizeof(q->servaddr)) < 0) { if (errno == ECONNREFUSED || errno == EINPROGRESS) { - return 0; + return SRSRAN_SUCCESS; } else { perror("connect"); exit(-1); - return -1; + return SRSRAN_ERROR; } } else { q->connected = true; @@ -93,10 +96,10 @@ int srsran_netsink_write(srsran_netsink_t* q, void* buffer, int nof_bytes) q->sockfd = socket(AF_INET, q->type == SRSRAN_NETSINK_TCP ? SOCK_STREAM : SOCK_DGRAM, 0); if (q->sockfd < 0) { perror("socket"); - return -1; + return SRSRAN_ERROR; } q->connected = false; - return 0; + return SRSRAN_SUCCESS; } } } diff --git a/lib/src/phy/io/netsource.c b/lib/src/phy/io/netsource.c index a4f23066c..94453a000 100644 --- a/lib/src/phy/io/netsource.c +++ b/lib/src/phy/io/netsource.c @@ -30,7 +30,7 @@ int srsran_netsource_init(srsran_netsource_t* q, const char* address, uint16_t p if (q->sockfd < 0) { perror("socket"); - return -1; + return SRSRAN_ERROR; } // Make sockets reusable @@ -46,16 +46,19 @@ int srsran_netsource_init(srsran_netsource_t* q, const char* address, uint16_t p q->type = type; q->servaddr.sin_family = AF_INET; - q->servaddr.sin_addr.s_addr = inet_addr(address); + if (inet_pton(q->servaddr.sin_family, address, &q->servaddr.sin_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } q->servaddr.sin_port = htons(port); if (bind(q->sockfd, (struct sockaddr*)&q->servaddr, sizeof(struct sockaddr_in))) { perror("bind"); - return -1; + return SRSRAN_ERROR; } q->connfd = 0; - return 0; + return SRSRAN_SUCCESS; } void srsran_netsource_free(srsran_netsource_t* q) @@ -73,9 +76,9 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes) if (n == -1) { if (errno == EAGAIN) { - return 0; + return SRSRAN_SUCCESS; } else { - return -1; + return SRSRAN_ERROR; } } else { return n; @@ -88,7 +91,7 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes) q->connfd = accept(q->sockfd, (struct sockaddr*)&q->cliaddr, &clilen); if (q->connfd < 0) { perror("accept"); - return -1; + return SRSRAN_ERROR; } } int n = read(q->connfd, buffer, nbytes); @@ -96,7 +99,7 @@ int srsran_netsource_read(srsran_netsource_t* q, void* buffer, int nbytes) printf("Connection closed\n"); close(q->connfd); q->connfd = 0; - return 0; + return SRSRAN_SUCCESS; } if (n == -1) { perror("read"); @@ -127,7 +130,7 @@ int srsran_netsource_set_nonblocking(srsran_netsource_t* q) perror("fcntl"); return -1; } - return 0; + return SRSRAN_SUCCESS; } int srsran_netsource_set_timeout(srsran_netsource_t* q, uint32_t microseconds) @@ -137,7 +140,7 @@ int srsran_netsource_set_timeout(srsran_netsource_t* q, uint32_t microseconds) t.tv_usec = microseconds; if (setsockopt(q->sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(struct timeval))) { perror("setsockopt"); - return -1; + return SRSRAN_ERROR; } - return 0; + return SRSRAN_SUCCESS; } diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index 3e007acac..75657a0c0 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -52,7 +52,10 @@ asn1::bounded_bitstring<1, 160, true, true> addr_to_asn1(const char* addr_str) { asn1::bounded_bitstring<1, 160, true, true> transport_layer_addr(32); uint8_t addr[4]; - inet_pton(AF_INET, addr_str, addr); + if (inet_pton(AF_INET, addr_str, addr) != 1) { + srsran::console("Invalid addr_str: %s\n", addr_str); + perror("inet_pton"); + } for (uint32_t j = 0; j < 4; ++j) { transport_layer_addr.data()[j] = addr[3 - j]; } @@ -1726,9 +1729,17 @@ void s1ap::ue::get_erab_addr(uint16_t erab_id, transp_addr_t& transp_addr, asn1: transp_addr.resize(32); uint8_t addr[4]; if (!s1ap_ptr->args.gtp_advertise_addr.empty()) { - inet_pton(AF_INET, s1ap_ptr->args.gtp_advertise_addr.c_str(), addr); + if (inet_pton(AF_INET, s1ap_ptr->args.gtp_advertise_addr.c_str(), addr) != 1) { + logger.error("Invalid gtp_advertise_addr: %s", s1ap_ptr->args.gtp_advertise_addr.c_str()); + srsran::console("Invalid gtp_advertise_addr: %s\n", s1ap_ptr->args.gtp_advertise_addr.c_str()); + perror("inet_pton"); + } } else { - inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr); + if (inet_pton(AF_INET, s1ap_ptr->args.gtp_bind_addr.c_str(), addr) != 1) { + logger.error("Invalid gtp_bind_addr: %s", s1ap_ptr->args.gtp_bind_addr.c_str()); + srsran::console("Invalid gtp_bind_addr: %s\n", s1ap_ptr->args.gtp_bind_addr.c_str()); + perror("inet_pton"); + } } for (uint32_t j = 0; j < 4; ++j) { transp_addr.data()[j] = addr[3 - j]; diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index 8d8e946a5..f2d42c808 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -394,13 +394,9 @@ int gtpu::init(const gtpu_args_t& gtpu_args, pdcp_interface_gtpu* pdcp_) struct sockaddr_in bindaddr; bzero(&bindaddr, sizeof(struct sockaddr_in)); - bindaddr.sin_family = AF_INET; - bindaddr.sin_addr.s_addr = inet_addr(gtp_bind_addr.c_str()); - bindaddr.sin_port = htons(GTPU_PORT); - - if (bind(fd, (struct sockaddr*)&bindaddr, sizeof(struct sockaddr_in))) { + // Bind socket + if (not net_utils::bind_addr(fd, gtp_bind_addr.c_str(), GTPU_PORT, &bindaddr)) { snprintf(errbuf, sizeof(errbuf), "%s", strerror(errno)); - logger.error("Failed to bind on address %s, port %d: %s", gtp_bind_addr.c_str(), int(GTPU_PORT), errbuf); srsran::console("Failed to bind on address %s, port %d: %s\n", gtp_bind_addr.c_str(), int(GTPU_PORT), errbuf); return SRSRAN_ERROR; } @@ -925,8 +921,20 @@ bool gtpu::m1u_handler::init(std::string m1u_multiaddr_, std::string m1u_if_addr /* Send an ADD MEMBERSHIP message via setsockopt */ struct ip_mreq mreq {}; - mreq.imr_multiaddr.s_addr = inet_addr(m1u_multiaddr.c_str()); // Multicast address of the service - mreq.imr_interface.s_addr = inet_addr(m1u_if_addr.c_str()); // Address of the IF the socket will listen to. + // Multicast address of the service + if (inet_pton(AF_INET, m1u_multiaddr.c_str(), &mreq.imr_multiaddr) != 1) { + logger.error("Invalid m1u_multiaddr: %s", m1u_multiaddr.c_str()); + srsran::console("Invalid m1u_multiaddr: %s\n", m1u_multiaddr.c_str()); + perror("inet_pton"); + return false; + } + // Address of the IF the socket will listen to. + if (inet_pton(AF_INET, m1u_if_addr.c_str(), &mreq.imr_interface) != 1) { + logger.error("Invalid m1u_if_addr: %s", m1u_if_addr.c_str()); + srsran::console("Invalid m1u_if_addr: %s\n", m1u_if_addr.c_str()); + perror("inet_pton"); + return false; + } if (setsockopt(m1u_sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { logger.error("Register musticast group for M1-U"); logger.error("M1-U infterface IP: %s, M1-U Multicast Address %s", m1u_if_addr.c_str(), m1u_multiaddr.c_str()); diff --git a/srsepc/src/mbms-gw/mbms-gw.cc b/srsepc/src/mbms-gw/mbms-gw.cc index 9cbe182b0..6e7eafdb2 100644 --- a/srsepc/src/mbms-gw/mbms-gw.cc +++ b/srsepc/src/mbms-gw/mbms-gw.cc @@ -12,6 +12,7 @@ #include "srsepc/hdr/mbms-gw/mbms-gw.h" #include "srsran/common/standard_streams.h" +#include "srsran/common/network_utils.h" #include "srsran/upper/gtpu.h" #include #include @@ -152,9 +153,12 @@ int mbms_gw::init_sgi_mb_if(mbms_gw_args_t* args) // Set IP of the interface struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr(args->sgi_mb_if_addr.c_str()); - addr->sin_port = 0; + + if (not srsran::net_utils::set_sockaddr(addr, args->sgi_mb_if_addr.c_str(), 0)) { + m_logger.error("Invalid sgi_mb_if_addr: %s", args->sgi_mb_if_addr.c_str()); + srsran::console("Invalid sgi_mb_if_addr: %s\n", args->sgi_mb_if_addr.c_str()); + return SRSRAN_ERROR_CANT_START; + } if (ioctl(sgi_mb_sock, SIOCSIFADDR, &ifr) < 0) { m_logger.error( @@ -165,7 +169,12 @@ int mbms_gw::init_sgi_mb_if(mbms_gw_args_t* args) } ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(args->sgi_mb_if_mask.c_str()); + if (inet_pton(ifr.ifr_netmask.sa_family, args->sgi_mb_if_mask.c_str(), &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr ) != 1) { + m_logger.error("Invalid sgi_mb_if_mask: %s", args->sgi_mb_if_mask.c_str()); + srsran::console("Invalid sgi_mb_if_mask: %s\n", args->sgi_mb_if_mask.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } if (ioctl(sgi_mb_sock, SIOCSIFNETMASK, &ifr) < 0) { m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno)); close(m_sgi_mb_if); @@ -201,7 +210,12 @@ int mbms_gw::init_m1_u(mbms_gw_args_t* args) /* Set local interface for outbound multicast packets*/ /* The IP must be associated with a local multicast capable interface */ struct in_addr local_if; - local_if.s_addr = inet_addr(args->m1u_multi_if.c_str()); + if (inet_pton(AF_INET, args->m1u_multi_if.c_str(), &local_if.s_addr) != 1) { + m_logger.error("Invalid m1u_multi_if: %s", args->m1u_multi_if.c_str()); + srsran::console("Invalid m1u_multi_if: %s\n", args->m1u_multi_if.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } if (setsockopt(m_m1u, IPPROTO_IP, IP_MULTICAST_IF, (char*)&local_if, sizeof(struct in_addr)) < 0) { m_logger.error("Error %s setting multicast interface %s.", strerror(errno), args->m1u_multi_if.c_str()); return SRSRAN_ERROR_CANT_START; @@ -218,7 +232,12 @@ int mbms_gw::init_m1_u(mbms_gw_args_t* args) bzero(&m_m1u_multi_addr, sizeof(m_m1u_multi_addr)); m_m1u_multi_addr.sin_family = AF_INET; m_m1u_multi_addr.sin_port = htons(GTPU_RX_PORT + 1); - m_m1u_multi_addr.sin_addr.s_addr = inet_addr(args->m1u_multi_addr.c_str()); + if (inet_pton(m_m1u_multi_addr.sin_family, args->m1u_multi_addr.c_str(), &m_m1u_multi_addr.sin_addr.s_addr) != 1) { + m_logger.error("Invalid m1u_multi_addr: %s", args->m1u_multi_addr.c_str()); + srsran::console("Invalid m1u_multi_addr: %s\n", args->m1u_multi_addr.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } m_logger.info("Initialized M1-U"); return SRSRAN_SUCCESS; diff --git a/srsepc/src/mme/nas.cc b/srsepc/src/mme/nas.cc index e7fe1f304..2e64b926d 100644 --- a/srsepc/src/mme/nas.cc +++ b/srsepc/src/mme/nas.cc @@ -1538,7 +1538,12 @@ bool nas::pack_attach_accept(srsran::byte_buffer_t* nas_buffer) act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].len = 4; struct sockaddr_in dns_addr; - inet_pton(AF_INET, m_dns.c_str(), &(dns_addr.sin_addr)); + if (inet_pton(AF_INET, m_dns.c_str(), &(dns_addr.sin_addr)) != 1) { + m_logger.error("Invalid m_dns: %s", m_dns.c_str()); + srsran::console("Invalid m_dns: %s\n", m_dns.c_str()); + perror("inet_pton"); + return false; + } memcpy(act_def_eps_bearer_context_req.protocol_cnfg_opts.opt[0].contents, &dns_addr.sin_addr.s_addr, 4); // Make sure all unused options are set to false diff --git a/srsepc/src/mme/s1ap.cc b/srsepc/src/mme/s1ap.cc index 866202a5f..b652198c0 100644 --- a/srsepc/src/mme/s1ap.cc +++ b/srsepc/src/mme/s1ap.cc @@ -14,6 +14,7 @@ #include "srsran/asn1/gtpc.h" #include "srsran/common/bcd_helpers.h" #include "srsran/common/liblte_security.h" +#include "srsran/common/network_utils.h" #include #include // for printing uint64_t #include @@ -86,7 +87,7 @@ int s1ap::init(const s1ap_args_t& s1ap_args) m_pcap.open(s1ap_args.pcap_filename.c_str()); } m_logger.info("S1AP Initialized"); - return 0; + return SRSRAN_SUCCESS; } void s1ap::stop() @@ -143,7 +144,7 @@ int s1ap::enb_listen() sock_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP); if (sock_fd == -1) { srsran::console("Could not create SCTP socket\n"); - return -1; + return SRSRAN_ERROR; } // Sets the data_io_event to be able to use sendrecv_info @@ -154,20 +155,21 @@ int s1ap::enb_listen() if (setsockopt(sock_fd, IPPROTO_SCTP, SCTP_EVENTS, &evnts, sizeof(evnts))) { close(sock_fd); srsran::console("Subscribing to sctp_data_io_events failed\n"); - return -1; + return SRSRAN_ERROR; } // S1-MME bind bzero(&s1mme_addr, sizeof(s1mme_addr)); - s1mme_addr.sin_family = AF_INET; - inet_pton(AF_INET, m_s1ap_args.mme_bind_addr.c_str(), &(s1mme_addr.sin_addr)); - s1mme_addr.sin_port = htons(S1MME_PORT); - err = bind(sock_fd, (struct sockaddr*)&s1mme_addr, sizeof(s1mme_addr)); - if (err != 0) { + if (not srsran::net_utils::set_sockaddr(&s1mme_addr, m_s1ap_args.mme_bind_addr.c_str(), S1MME_PORT)) { + m_logger.error("Invalid mme_bind_addr: %s", m_s1ap_args.mme_bind_addr.c_str()); + srsran::console("Invalid mme_bind_addr: %s\n", m_s1ap_args.mme_bind_addr.c_str()); + return SRSRAN_ERROR; + } + if (not srsran::net_utils::bind_addr(sock_fd, s1mme_addr)) { close(sock_fd); m_logger.error("Error binding SCTP socket"); srsran::console("Error binding SCTP socket\n"); - return -1; + return SRSRAN_ERROR; } // Listen for connections @@ -176,7 +178,7 @@ int s1ap::enb_listen() close(sock_fd); m_logger.error("Error in SCTP socket listen"); srsran::console("Error in SCTP socket listen\n"); - return -1; + return SRSRAN_ERROR; } return sock_fd; @@ -556,7 +558,7 @@ uint64_t s1ap::find_imsi_from_m_tmsi(uint32_t m_tmsi) return it->second; } else { m_logger.debug("Could not find IMSI from M-TMSI 0x%x", m_tmsi); - return 0; + return SRSRAN_SUCCESS; } } diff --git a/srsepc/src/spgw/gtpc.cc b/srsepc/src/spgw/gtpc.cc index 113054308..9f321f25d 100644 --- a/srsepc/src/spgw/gtpc.cc +++ b/srsepc/src/spgw/gtpc.cc @@ -541,7 +541,10 @@ int spgw::gtpc::init_ue_ip(spgw_args_t* args, const std::map::const_iterator iter = ip_to_imsi.begin(); iter != ip_to_imsi.end(); ++iter) { struct in_addr in_addr; - in_addr.s_addr = inet_addr(iter->first.c_str()); + if (inet_pton(AF_INET, iter->first.c_str(), &in_addr.s_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } if (!m_imsi_to_ip.insert(std::make_pair(iter->second, in_addr)).second) { m_logger.error( "SPGW: duplicate imsi %015" PRIu64 " for static ip address %s.", iter->second, iter->first.c_str()); @@ -553,7 +556,13 @@ int spgw::gtpc::init_ue_ip(spgw_args_t* args, const std::mapsgi_if_addr.c_str()) + htonl(n); + if (inet_pton(AF_INET, args->sgi_if_addr.c_str(), &ue_addr.s_addr) != 1) { + m_logger.error("Invalid sgi_if_addr: %s", args->sgi_if_addr.c_str()); + srsran::console("Invalid sgi_if_addr: %s\n", args->sgi_if_addr.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR; + } + ue_addr.s_addr = ue_addr.s_addr + htonl(n); std::map::const_iterator iter = ip_to_imsi.find(inet_ntoa(ue_addr)); if (iter != ip_to_imsi.end()) { diff --git a/srsepc/src/spgw/gtpu.cc b/srsepc/src/spgw/gtpu.cc index e0d8d79bd..7cdc34c4c 100644 --- a/srsepc/src/spgw/gtpu.cc +++ b/srsepc/src/spgw/gtpu.cc @@ -13,6 +13,7 @@ #include "srsepc/hdr/spgw/gtpu.h" #include "srsepc/hdr/mme/mme_gtpc.h" #include "srsran/common/string_helpers.h" +#include "srsran/common/network_utils.h" #include "srsran/upper/gtpu.h" #include #include @@ -131,9 +132,11 @@ int spgw::gtpu::init_sgi(spgw_args_t* args) // Set IP of the interface struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr(args->sgi_if_addr.c_str()); - addr->sin_port = 0; + if (not srsran::net_utils::set_sockaddr(addr, args->sgi_if_addr.c_str(), 0)) { + m_logger.error("Invalid sgi_if_addr: %s", args->sgi_if_addr.c_str()); + srsran::console("Invalid sgi_if_addr: %s\n", args->sgi_if_addr.c_str()); + return SRSRAN_ERROR_CANT_START; + } if (ioctl(sgi_sock, SIOCSIFADDR, &ifr) < 0) { m_logger.error( @@ -143,8 +146,11 @@ int spgw::gtpu::init_sgi(spgw_args_t* args) return SRSRAN_ERROR_CANT_START; } - ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr("255.255.255.0"); + ifr.ifr_netmask.sa_family = AF_INET; + if (inet_pton(ifr.ifr_netmask.sa_family , "255.255.255.0", &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr) != 1) { + perror("inet_pton"); + return false; + } if (ioctl(sgi_sock, SIOCSIFNETMASK, &ifr) < 0) { m_logger.error("Failed to set TUN interface Netmask. Error: %s", strerror(errno)); close(m_sgi); @@ -170,7 +176,11 @@ int spgw::gtpu::init_s1u(spgw_args_t* args) // Bind the socket m_s1u_addr.sin_family = AF_INET; - m_s1u_addr.sin_addr.s_addr = inet_addr(args->gtpu_bind_addr.c_str()); + if (inet_pton(m_s1u_addr.sin_family, args->gtpu_bind_addr.c_str(), &m_s1u_addr.sin_addr.s_addr) != 1) { + m_logger.error("Invalid gtpu_bind_addr: %s", args->gtpu_bind_addr.c_str()); + srsran::console("Invalid gtpu_bind_addr: %s\n", args->gtpu_bind_addr.c_str()); + return SRSRAN_ERROR_CANT_START; + } m_s1u_addr.sin_port = htons(GTPU_RX_PORT); if (bind(m_s1u, (struct sockaddr*)&m_s1u_addr, sizeof(struct sockaddr_in))) { diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index bd52f665b..473e45706 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -111,7 +111,12 @@ bool ue_stack_nr::switch_on() { // statically setup TUN (will be done through RRC later) char* err_str = nullptr; - if (gw->setup_if_addr(5, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.1.3")), nullptr, err_str)) { + struct in_addr in_addr; + if (inet_pton(AF_INET, "192.168.1.3", &in_addr.s_addr) != 1) { + perror("inet_pton"); + return false; + } + if (gw->setup_if_addr(5, LIBLTE_MME_PDN_TYPE_IPV4, htonl(in_addr.s_addr), nullptr, err_str)) { printf("Error configuring TUN interface\n"); } return true; diff --git a/srsue/src/stack/upper/gw.cc b/srsue/src/stack/upper/gw.cc index 2df179468..76fc7d97c 100644 --- a/srsue/src/stack/upper/gw.cc +++ b/srsue/src/stack/upper/gw.cc @@ -53,8 +53,11 @@ int gw::init(const gw_args_t& args_, stack_interface_gw* stack_) return SRSRAN_ERROR; } - mbsfn_sock_addr.sin_family = AF_INET; - mbsfn_sock_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + mbsfn_sock_addr.sin_family = AF_INET; + if (inet_pton(mbsfn_sock_addr.sin_family, "127.0.0.1", &mbsfn_sock_addr.sin_addr.s_addr) != 1) { + perror("inet_pton"); + return false; + } return SRSRAN_SUCCESS; } @@ -453,8 +456,13 @@ int gw::setup_if_addr4(uint32_t ip_addr, char* err_str) close(tun_fd); return SRSRAN_ERROR_CANT_START; } - ifr.ifr_netmask.sa_family = AF_INET; - ((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = inet_addr(args.tun_dev_netmask.c_str()); + ifr.ifr_netmask.sa_family = AF_INET; + if (inet_pton(ifr.ifr_netmask.sa_family, args.tun_dev_netmask.c_str(), &((struct sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr) != 1) { + logger.error("Invalid tun_dev_netmask: %s", args.tun_dev_netmask.c_str()); + srsran::console("Invalid tun_dev_netmask: %s\n", args.tun_dev_netmask.c_str()); + perror("inet_pton"); + return SRSRAN_ERROR_CANT_START; + } if (0 > ioctl(sock, SIOCSIFNETMASK, &ifr)) { err_str = strerror(errno); logger.debug("Failed to set socket netmask: %s", err_str); diff --git a/srsue/src/stack/upper/test/gw_test.cc b/srsue/src/stack/upper/test/gw_test.cc index 0198e2e8a..ebc7214a2 100644 --- a/srsue/src/stack/upper/test/gw_test.cc +++ b/srsue/src/stack/upper/test/gw_test.cc @@ -43,7 +43,12 @@ int gw_test() char* err_str = nullptr; int rtn = 0; - rtn = gw.setup_if_addr(eps_bearer_id, LIBLTE_MME_PDN_TYPE_IPV4, htonl(inet_addr("192.168.56.32")), nullptr, err_str); + struct in_addr in_addr; + if (inet_pton(AF_INET, "192.168.56.32", &in_addr.s_addr) != 1) { + perror("inet_pton"); + return SRSRAN_ERROR; + } + rtn = gw.setup_if_addr(eps_bearer_id, LIBLTE_MME_PDN_TYPE_IPV4, htonl(in_addr.s_addr), nullptr, err_str); if (rtn != SRSRAN_SUCCESS) { srslog::fetch_basic_logger("TEST", false) diff --git a/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h b/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h index fab9ea656..5758e89af 100644 --- a/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h +++ b/srsue/src/test/ttcn3/hdr/ttcn3_port_handler.h @@ -20,6 +20,7 @@ #include "srsran/common/epoll_helper.h" #include "srsran/common/standard_streams.h" +#include "srsran/common/network_utils.h" #include "srsran/srslog/srslog.h" #include "ttcn3_common.h" #include @@ -179,10 +180,10 @@ public: // Port bind struct sockaddr_in bind_addr = {}; - bind_addr.sin_family = AF_INET; - inet_pton(AF_INET, net_ip.c_str(), &(bind_addr.sin_addr)); - bind_addr.sin_port = htons(net_port); - + if (not srsran::net_utils::set_sockaddr(&bind_addr, net_ip.c_str(), net_port)) { + srsran::console("Invalid net_ip: %s\n", net_ip.c_str()); + return SRSRAN_ERROR; + } int one = 1; setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); ret = bind(sock_fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr)); From 53bf29a5409494fc484d7539294558e95c43c15f Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 21 Sep 2021 15:08:38 +0200 Subject: [PATCH 36/39] Add nr label to MAC NR tests --- srsenb/test/mac/nr/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsenb/test/mac/nr/CMakeLists.txt index 87d48d68c..eab5855b1 100644 --- a/srsenb/test/mac/nr/CMakeLists.txt +++ b/srsenb/test/mac/nr/CMakeLists.txt @@ -15,7 +15,7 @@ target_link_libraries(sched_nr_test srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -add_test(sched_nr_test sched_nr_test) +add_nr_test(sched_nr_test sched_nr_test) add_executable(sched_nr_prb_test sched_nr_prb_test.cc) target_link_libraries(sched_nr_prb_test @@ -23,8 +23,8 @@ target_link_libraries(sched_nr_prb_test srsran_common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES}) -add_test(sched_nr_prb_test sched_nr_prb_test) +add_nr_test(sched_nr_prb_test sched_nr_prb_test) add_executable(sched_nr_rar_test sched_nr_rar_test.cc) target_link_libraries(sched_nr_rar_test srsgnb_mac sched_nr_test_suite srsran_common) -add_test(sched_nr_rar_test sched_nr_rar_test) \ No newline at end of file +add_nr_test(sched_nr_rar_test sched_nr_rar_test) \ No newline at end of file From 0324806d6c87b0d65ec0538143562c8552c77bad Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 21 Sep 2021 15:11:05 +0200 Subject: [PATCH 37/39] Packed NR TDD config in duplex configuration and created test case for FDD --- lib/include/srsran/asn1/rrc_nr_utils.h | 2 +- lib/include/srsran/common/phy_cfg_nr.h | 20 ++-- .../srsran/common/phy_cfg_nr_default.h | 25 +++-- lib/include/srsran/phy/common/phy_common_nr.h | 19 +++- lib/src/asn1/rrc_nr_utils.cc | 40 ++++---- lib/src/common/phy_cfg_nr_default.cc | 99 ++++++++++++------- lib/src/phy/common/phy_common_nr.c | 35 +++++-- lib/test/asn1/rrc_nr_utils_test.cc | 18 ++-- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 2 +- srsenb/src/stack/mac/nr/sched_nr_cfg.cc | 4 +- srsenb/src/stack/mac/nr/sched_nr_ue.cc | 6 +- srsenb/test/mac/nr/sched_nr_cfg_generators.h | 2 +- srsenb/test/mac/nr/sched_nr_test.cc | 4 +- srsue/src/phy/nr/cc_worker.cc | 4 +- srsue/src/stack/rrc/rrc_nr.cc | 8 +- test/phy/CMakeLists.txt | 29 +++--- test/phy/dummy_gnb_stack.h | 26 ++++- 17 files changed, 215 insertions(+), 128 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index bb5ad0326..53939bfd6 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -73,7 +73,7 @@ void to_asn1(asn1::rrc_nr::plmn_id_s* asn1_type, const plmn_id_t& cfg); bool make_phy_rach_cfg(const asn1::rrc_nr::rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* prach_cfg); bool make_phy_tdd_cfg(const asn1::rrc_nr::tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, - srsran_tdd_config_nr_t* srsran_tdd_config_nr); + srsran_duplex_config_nr_t* srsran_duplex_config_nr); bool make_phy_harq_ack_cfg(const asn1::rrc_nr::phys_cell_group_cfg_s& phys_cell_group_cfg, srsran_harq_ack_cfg_hl_t* srsran_ue_dl_nr_harq_ack_cfg); bool make_phy_coreset_cfg(const asn1::rrc_nr::ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* srsran_coreset); diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index e3985ce21..5a2f3d116 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -35,16 +35,16 @@ struct phy_cfg_nr_t { srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; }; - srsran_tdd_config_nr_t tdd = {}; - srsran_sch_hl_cfg_nr_t pdsch = {}; - srsran_sch_hl_cfg_nr_t pusch = {}; - srsran_pucch_nr_hl_cfg_t pucch = {}; - srsran_prach_cfg_t prach = {}; - srsran_pdcch_cfg_nr_t pdcch = {}; - srsran_harq_ack_cfg_hl_t harq_ack = {}; - srsran_csi_hl_cfg_t csi = {}; - srsran_carrier_nr_t carrier = {}; - ssb_cfg_t ssb; + srsran_duplex_config_nr_t duplex = {}; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; + srsran_pucch_nr_hl_cfg_t pucch = {}; + srsran_prach_cfg_t prach = {}; + srsran_pdcch_cfg_nr_t pdcch = {}; + srsran_harq_ack_cfg_hl_t harq_ack = {}; + srsran_csi_hl_cfg_t csi = {}; + srsran_carrier_nr_t carrier = {}; + ssb_cfg_t ssb; phy_cfg_nr_t() {} diff --git a/lib/include/srsran/common/phy_cfg_nr_default.h b/lib/include/srsran/common/phy_cfg_nr_default.h index b5758dd8f..82e9ef7a2 100644 --- a/lib/include/srsran/common/phy_cfg_nr_default.h +++ b/lib/include/srsran/common/phy_cfg_nr_default.h @@ -43,18 +43,23 @@ public: const std::array R_CARRIER_STRING = {{"10MHz", "20MHz"}}; enum { + /** + * @brief FDD, all slots for DL and UL + */ + R_DUPLEX_FDD = 0, + /** * @brief TDD custom reference 5 slot DL and 5 slot UL */ - R_TDD_CUSTOM_6_4 = 0, + R_DUPLEX_TDD_CUSTOM_6_4, /** * @brief TDD pattern FR1.15-1 defined in TS38.101-4 Table A.1.2-1 */ - R_TDD_FR1_15_1, - R_TDD_COUNT, - } tdd = R_TDD_CUSTOM_6_4; - const std::array R_TDD_STRING = {{"6D+4U", "FR1.15-1"}}; + R_DUPLEX_TDD_FR1_15_1, + R_DUPLEX_COUNT, + } duplex = R_DUPLEX_TDD_CUSTOM_6_4; + const std::array R_DUPLEX_STRING = {{"FDD", "6D+4U", "FR1.15-1"}}; enum { /** @@ -144,8 +149,8 @@ private: /** * TDD make helper methods */ - static void make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd); - static void make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd); + static void make_tdd_custom_6_4(srsran_duplex_config_nr_t& duplex); + static void make_tdd_fr1_15_1(srsran_duplex_config_nr_t& duplex); /** * PDCCH make helper methods @@ -171,9 +176,9 @@ private: /** * HARQ make helper methods */ - static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, - const srsran_carrier_nr_t& carrier, - const srsran_tdd_config_nr_t& tdd_cfg); + static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_duplex_config_nr_t& duplex_cfg); /** * PRACH make helper methods diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 309cbfe92..87a679fbd 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -458,6 +458,17 @@ typedef struct SRSRAN_API { srsran_tdd_pattern_t pattern2; } srsran_tdd_config_nr_t; +/** + * @brief Describes duplex configuration + */ +typedef struct SRSRAN_API { + srsran_duplex_mode_t mode; + union { + srsran_tdd_config_nr_t tdd; ///< TDD configuration + // ... add here other mode parameters + }; +} srsran_duplex_config_nr_t; + /** * @brief Describes a measurement based on NZP-CSI-RS or SSB-CSI * @note Used for tracking RSRP, SNR, CFO, SFO, and so on @@ -593,21 +604,21 @@ SRSRAN_API float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subca /** * @brief Decides whether a given slot is configured as Downlink - * @param cfg Provides TDD configuration + * @param cfg Provides the carrier duplex configuration * @param numerology Provides BWP numerology * @param slot_idx Slot index in the frame for the given numerology * @return true if the provided slot index is configured for Downlink */ -SRSRAN_API bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); +SRSRAN_API bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); /** * @brief Decides whether a given slot is configured as Uplink - * @param cfg Provides TDD configuration + * @param cfg Provides the carrier duplex configuration * @param numerology Provides BWP numerology * @param slot_idx Slot index in the frame for the given numerology * @return true if the provided slot index is configured for Uplink */ -SRSRAN_API bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); +SRSRAN_API bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); SRSRAN_API int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell); diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 679b38067..6d8e4d82a 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -271,21 +271,21 @@ bool make_phy_rach_cfg(const rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* p }; bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, - srsran_tdd_config_nr_t* in_srsran_tdd_config_nr) + srsran_duplex_config_nr_t* in_srsran_duplex_config_nr) { - srsran_tdd_config_nr_t srsran_tdd_config_nr = {}; + srsran_duplex_config_nr_t srsran_duplex_config_nr = {}; switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) { case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: - srsran_tdd_config_nr.pattern1.period_ms = 1; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 1; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: - srsran_tdd_config_nr.pattern1.period_ms = 2; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 2; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: - srsran_tdd_config_nr.pattern1.period_ms = 5; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 5; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: - srsran_tdd_config_nr.pattern1.period_ms = 10; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 10; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: @@ -297,12 +297,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity.to_string()); return false; } - srsran_tdd_config_nr.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots; - srsran_tdd_config_nr.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols; - srsran_tdd_config_nr.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots; - srsran_tdd_config_nr.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols; + srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots; + srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols; + srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots; + srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols; // Copy and return struct - *in_srsran_tdd_config_nr = srsran_tdd_config_nr; + *in_srsran_duplex_config_nr = srsran_duplex_config_nr; if (not tdd_ul_dl_cfg_common.pattern2_present) { return true; @@ -310,16 +310,16 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, switch (tdd_ul_dl_cfg_common.pattern2.dl_ul_tx_periodicity) { case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: - srsran_tdd_config_nr.pattern2.period_ms = 1; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 1; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: - srsran_tdd_config_nr.pattern2.period_ms = 2; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 2; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: - srsran_tdd_config_nr.pattern2.period_ms = 5; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 5; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: - srsran_tdd_config_nr.pattern2.period_ms = 10; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 10; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: @@ -332,12 +332,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, return false; } - srsran_tdd_config_nr.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots; - srsran_tdd_config_nr.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols; - srsran_tdd_config_nr.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots; - srsran_tdd_config_nr.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols; + srsran_duplex_config_nr.tdd.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots; + srsran_duplex_config_nr.tdd.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols; + srsran_duplex_config_nr.tdd.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots; + srsran_duplex_config_nr.tdd.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols; // Copy and return struct - *in_srsran_tdd_config_nr = srsran_tdd_config_nr; + *in_srsran_duplex_config_nr = srsran_duplex_config_nr; return true; } diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index 370e5ca57..487c92e73 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -44,13 +44,13 @@ phy_cfg_nr_default_t::reference_cfg_t::reference_cfg_t(const std::string& args) } } srsran_assert(carrier != R_CARRIER_COUNT, "Invalid carrier reference configuration '%s'", param.back().c_str()); - } else if (param.front() == "tdd") { - for (tdd = R_TDD_CUSTOM_6_4; tdd < R_TDD_COUNT; tdd = inc(tdd)) { - if (R_TDD_STRING[tdd] == param.back()) { + } else if (param.front() == "duplex") { + for (duplex = R_DUPLEX_FDD; duplex < R_DUPLEX_COUNT; duplex = inc(duplex)) { + if (R_DUPLEX_STRING[duplex] == param.back()) { break; } } - srsran_assert(tdd != R_TDD_COUNT, "Invalid TDD reference configuration '%s'", param.back().c_str()); + srsran_assert(duplex != R_DUPLEX_COUNT, "Invalid duplex reference configuration '%s'", param.back().c_str()); } else if (param.front() == "pdsch") { for (pdsch = R_PDSCH_DEFAULT; pdsch < R_PDSCH_COUNT; pdsch = inc(pdsch)) { if (R_PDSCH_STRING[pdsch] == param.back()) { @@ -86,8 +86,18 @@ void phy_cfg_nr_default_t::make_carrier_custom_20MHz(srsran_carrier_nr_t& carrie carrier.scs = srsran_subcarrier_spacing_15kHz; } -void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) +void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_duplex_config_nr_t& conf) { + // Set the duplex mode to TDD + conf.mode = SRSRAN_DUPLEX_MODE_TDD; + + // Select TDD config + srsran_tdd_config_nr_t& tdd = conf.tdd; + + // Initialise pattern + tdd = {}; + + // Enable pattern 1 tdd.pattern1.period_ms = 10; tdd.pattern1.nof_dl_slots = 6; tdd.pattern1.nof_dl_symbols = 0; @@ -98,8 +108,17 @@ void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) tdd.pattern2.period_ms = 0; } -void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd) -{ +void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_duplex_config_nr_t& conf) +{ // Set the duplex mode to TDD + conf.mode = SRSRAN_DUPLEX_MODE_TDD; + + // Select TDD config + srsran_tdd_config_nr_t& tdd = conf.tdd; + + // Initialise pattern + tdd = {}; + + // Enable pattern 1 tdd.pattern1.period_ms = 5; tdd.pattern1.nof_dl_slots = 3; tdd.pattern1.nof_dl_symbols = 10; @@ -319,32 +338,39 @@ void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch pucch.sr_resources[1].resource = resource_sr; } -void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, - const srsran_carrier_nr_t& carrier, - const srsran_tdd_config_nr_t& tdd_cfg) +void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_duplex_config_nr_t& duplex_cfg) { - // Generate as many entries as DL slots - harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); - if (tdd_cfg.pattern1.nof_dl_symbols > 0) { - harq.nof_dl_data_to_ul_ack++; - } + if (duplex_cfg.mode == SRSRAN_DUPLEX_MODE_TDD) { + const srsran_tdd_config_nr_t& tdd_cfg = duplex_cfg.tdd; - // Set PDSCH to ACK timing delay to 4 or more - for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { - // Set the first slots into the first UL slot - if (harq.nof_dl_data_to_ul_ack >= 4 and n < (harq.nof_dl_data_to_ul_ack - 4)) { - harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n; - continue; + // Generate as many entries as DL slots + harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); + if (tdd_cfg.pattern1.nof_dl_symbols > 0) { + harq.nof_dl_data_to_ul_ack++; } - // After that try if n+4 is UL slot - if (srsran_tdd_nr_is_ul(&tdd_cfg, carrier.scs, n + 4)) { - harq.dl_data_to_ul_ack[n] = 4; - continue; - } + // Set PDSCH to ACK timing delay to 4 or more + for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { + // Set the first slots into the first UL slot + if (harq.nof_dl_data_to_ul_ack >= 4 and n < (harq.nof_dl_data_to_ul_ack - 4)) { + harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n; + continue; + } + + // After that try if n+4 is UL slot + if (srsran_duplex_nr_is_ul(&duplex_cfg, carrier.scs, n + 4)) { + harq.dl_data_to_ul_ack[n] = 4; + continue; + } - // Otherwise set delay to the first UL slot of the next TDD period - harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n; + // Otherwise set delay to the first UL slot of the next TDD period + harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n; + } + } else { + harq.dl_data_to_ul_ack[0] = 4; + harq.nof_dl_data_to_ul_ack = 1; } // Zero the rest @@ -377,14 +403,17 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) srsran_assertion_failure("Invalid carrier reference"); } - switch (reference_cfg.tdd) { - case reference_cfg_t::R_TDD_CUSTOM_6_4: - make_tdd_custom_6_4(tdd); + switch (reference_cfg.duplex) { + case reference_cfg_t::R_DUPLEX_FDD: + duplex.mode = SRSRAN_DUPLEX_MODE_FDD; + break; + case reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4: + make_tdd_custom_6_4(duplex); break; - case reference_cfg_t::R_TDD_FR1_15_1: - make_tdd_fr1_15_1(tdd); + case reference_cfg_t::R_DUPLEX_TDD_FR1_15_1: + make_tdd_fr1_15_1(duplex); break; - case reference_cfg_t::R_TDD_COUNT: + case reference_cfg_t::R_DUPLEX_COUNT: srsran_assertion_failure("Invalid TDD reference"); } @@ -419,7 +448,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) switch (reference_cfg.harq) { case reference_cfg_t::R_HARQ_AUTO: - make_harq_auto(harq_ack, carrier, tdd); + make_harq_auto(harq_ack, carrier, duplex); break; } diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 39269ee6d..9a33ac176 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -283,13 +283,8 @@ float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subcarrier_spaci return srsran_symbol_offset_s(l1, scs) - srsran_symbol_offset_s(l0, scs); } -bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +static bool tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) { - // Protect NULL pointer access - if (cfg == NULL) { - return false; - } - // Prevent zero division if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { return false; @@ -312,13 +307,24 @@ bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, (slot_idx_period == pattern->nof_dl_slots && pattern->nof_dl_symbols != 0)); } -bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) + { // Protect NULL pointer access if (cfg == NULL) { return false; } + // In case of TDD + if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) { + return tdd_nr_is_dl(&cfg->tdd, numerology, slot_idx); + } + + return true; +} + +static bool tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ // Prevent zero division if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { return false; @@ -343,6 +349,21 @@ bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, return (slot_idx_period > start_ul || (slot_idx_period == start_ul && pattern->nof_ul_symbols != 0)); } +bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ + // Protect NULL pointer access + if (cfg == NULL) { + return false; + } + + // In case of TDD + if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) { + return tdd_nr_is_ul(&cfg->tdd, numerology, slot_idx); + } + + return true; +} + int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell) { // Protect memory access diff --git a/lib/test/asn1/rrc_nr_utils_test.cc b/lib/test/asn1/rrc_nr_utils_test.cc index 6dfc6b234..8f5eb999b 100644 --- a/lib/test/asn1/rrc_nr_utils_test.cc +++ b/lib/test/asn1/rrc_nr_utils_test.cc @@ -88,15 +88,15 @@ int make_phy_tdd_cfg_test() tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots = 2; tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols = 4; - srsran_tdd_config_nr_t srsran_tdd_config_nr; - TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_tdd_config_nr) == true); - - TESTASSERT(srsran_tdd_config_nr.pattern1.period_ms == 10); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_slots == 7); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_symbols == 6); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_slots == 2); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_symbols == 4); - TESTASSERT(srsran_tdd_config_nr.pattern2.period_ms == 0); + srsran_duplex_config_nr_t srsran_duplex_config_nr; + TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_duplex_config_nr) == true); + + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.period_ms == 10); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots == 7); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols == 6); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots == 2); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols == 4); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern2.period_ms == 0); return SRSRAN_SUCCESS; } diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 48ea5c197..b8fb7c94a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -60,7 +60,7 @@ public: struct cell_cfg_t { srsran_carrier_nr_t carrier = {}; - srsran_tdd_config_nr_t tdd = {}; + srsran_duplex_config_nr_t duplex = {}; srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {}; srsran::bounded_vector bwps{1}; // idx0 for BWP-common }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 1b42e8066..04f7ecaa6 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -37,8 +37,8 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx); for (size_t sl = 0; sl < nof_slots; ++sl) { slot_cfg sl_cfg{}; - sl_cfg.is_dl = srsran_tdd_nr_is_dl(&cell_cfg.tdd, cfg.numerology_idx, sl); - sl_cfg.is_ul = srsran_tdd_nr_is_ul(&cell_cfg.tdd, cfg.numerology_idx, sl); + sl_cfg.is_dl = srsran_duplex_nr_is_dl(&cell_cfg.duplex, cfg.numerology_idx, sl); + sl_cfg.is_ul = srsran_duplex_nr_is_ul(&cell_cfg.duplex, cfg.numerology_idx, sl); slots.push_back(sl_cfg); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index a0bb2177b..528f2d123 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -61,15 +61,15 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot, sfu.dl_pending_bytes = dl_pending_bytes; sfu.ul_pending_bytes = ul_pending_bytes; - const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd; - if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { + const srsran_duplex_config_nr_t& tdd_cfg = cell_params.cell_cfg.duplex; + if (srsran_duplex_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { // If DL enabled sfu.h_dl = harq_ent.find_pending_dl_retx(); if (sfu.h_dl == nullptr and sfu.dl_pending_bytes > 0) { sfu.h_dl = harq_ent.find_empty_dl_harq(); } } - if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) { + if (srsran_duplex_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) { // If UL enabled sfu.h_ul = harq_ent.find_pending_ul_retx(); if (sfu.h_ul == nullptr and sfu.ul_pending_bytes > 0) { diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index 310c63a6e..683e0d060 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -36,7 +36,7 @@ inline sched_nr_interface::cell_cfg_t get_default_cell_cfg( sched_nr_interface::cell_cfg_t cell_cfg{}; cell_cfg.carrier = phy_cfg.carrier; - cell_cfg.tdd = phy_cfg.tdd; + cell_cfg.duplex = phy_cfg.duplex; cell_cfg.bwps.resize(1); cell_cfg.bwps[0].pdcch = phy_cfg.pdcch; diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index fccf4ee9e..d793f0c4b 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -82,7 +82,7 @@ void sched_nr_cfg_serialized_test() uint32_t max_nof_ttis = 1000, nof_sectors = 4; task_job_manager tasks; - sched_nr_interface::sched_cfg_t cfg; + sched_nr_interface::sched_cfg_t cfg; cfg.auto_refill_buffer = true; std::vector cells_cfg = get_default_cells_cfg(nof_sectors); @@ -111,7 +111,7 @@ void sched_nr_cfg_serialized_test() sched_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); tasks.finish_cc(slot_rx, dl_res, ul_res); - TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or + TESTASSERT(not srsran_duplex_nr_is_dl(&cells_cfg[cc].duplex, 0, (slot_tx).slot_idx()) or dl_res.dl_sched.pdcch_dl.size() == 1); } } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 1d7d12f75..1abf645d4 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -475,7 +475,7 @@ bool cc_worker::work_dl() } // Check if it is a DL slot, if not skip - if (!srsran_tdd_nr_is_dl(&phy.cfg.tdd, 0, dl_slot_cfg.idx)) { + if (!srsran_duplex_nr_is_dl(&phy.cfg.duplex, 0, dl_slot_cfg.idx)) { return true; } @@ -523,7 +523,7 @@ bool cc_worker::work_ul() bool has_ul_ack = phy.get_pending_ack(ul_slot_cfg.idx, pdsch_ack); // Check if it is a UL slot, if not skip - if (!srsran_tdd_nr_is_ul(&phy.cfg.tdd, 0, ul_slot_cfg.idx)) { + if (!srsran_duplex_nr_is_ul(&phy.cfg.duplex, 0, ul_slot_cfg.idx)) { // No NR signal shall be transmitted srsran_vec_cf_zero(tx_buffer[0], ue_ul.ifft.sf_sz); diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 636534793..cc7d8a14b 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -1193,11 +1193,11 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) } if (recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present) { - srsran_tdd_config_nr_t tdd; - if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &tdd) == true) { - phy_cfg.tdd = tdd; + srsran_duplex_config_nr_t duplex; + if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &duplex) == true) { + phy_cfg.duplex = duplex; } else { - logger.warning("Warning while building tdd structure"); + logger.warning("Warning while building duplex structure"); return false; } } else { diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index f76226e2e..5644bffb2 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -25,15 +25,18 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${Boost_LIBRARIES} ${ATOMIC_LIBS}) + # For each supported bandwidth foreach (NR_PHY_TEST_BW "10MHz" "20MHz") - foreach (NR_PHY_TEST_TDD "6D+4U" "FR1.15-1") + # For each supported frame structure + foreach (NR_PHY_TEST_DUPLEX "FDD" "6D+4U" "FR1.15-1") set(NR_PHY_TEST_DURATION_MS 20) + # DL flooding only foreach (NR_PHY_TEST_PDSCH "default" "ts38101/5.2-1") - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD},pdsch=${NR_PHY_TEST_PDSCH} + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX},pdsch=${NR_PHY_TEST_PDSCH} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots + --gnb.stack.pdsch.slots=all --gnb.stack.pdsch.start=0 # Start at RB 0 --gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.mcs=27 # Maximum MCS @@ -43,11 +46,12 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ) endforeach () - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_ul_only nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} + # UL flooding + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_ul_only nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=6 # No PDSCH - --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots + --gnb.stack.pdsch.slots=none + --gnb.stack.pusch.slots=all --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS @@ -55,14 +59,15 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_bidir nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} + # DL and UL flooding + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_bidir nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots + --gnb.stack.pdsch.slots=all --gnb.stack.pdsch.start=0 # Start at RB 0 --gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.mcs=28 # Maximum MCS - --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots + --gnb.stack.pusch.slots=all --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 66ac4636b..d487e8aa4 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -360,10 +360,22 @@ public: ul.mcs = args.pusch.mcs; if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) { - srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); + if (args.pdsch.slots == "all") { + for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { + dl.slots.insert(n); + } + } else { + srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); + } } if (args.pusch.slots != "none" and not args.pusch.slots.empty()) { - srsran::string_parse_list(args.pusch.slots, ',', ul.slots); + if (args.pusch.slots == "all") { + for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { + ul.slots.insert(n); + } + } else { + srsran::string_parse_list(args.pusch.slots, ',', ul.slots); + } } // Select DCI locations @@ -405,7 +417,11 @@ public: // Setup DL Data to ACK timing for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { - dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.tdd.pattern1.period_ms]; + if (args.phy_cfg.duplex.mode == SRSRAN_DUPLEX_MODE_TDD) { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.duplex.tdd.pattern1.period_ms]; + } else { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.harq_ack.nof_dl_data_to_ul_ack]; + } } // If reached this point the configuration is valid @@ -441,7 +457,7 @@ public: } // Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip - if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) { + if (not srsran_duplex_nr_is_dl(&phy_cfg.duplex, phy_cfg.carrier.scs, slot_cfg.idx)) { return SRSRAN_SUCCESS; } @@ -451,7 +467,7 @@ public: } // Check if the UL slot is valid, if not skip UL scheduling - if (not srsran_tdd_nr_is_ul(&phy_cfg.tdd, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { + if (not srsran_duplex_nr_is_ul(&phy_cfg.duplex, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { return SRSRAN_SUCCESS; } From f44eb0534f82c054984bd68827531359cf941a29 Mon Sep 17 00:00:00 2001 From: Fabian Eckermann Date: Tue, 21 Sep 2021 14:57:02 +0200 Subject: [PATCH 38/39] Add RRC NR test for FDD --- lib/test/asn1/srsran_asn1_rrc_nr_test.cc | 614 ++++++++++++++++++++++- 1 file changed, 612 insertions(+), 2 deletions(-) diff --git a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc index 31dbe80af..c02864b28 100644 --- a/lib/test/asn1/srsran_asn1_rrc_nr_test.cc +++ b/lib/test/asn1/srsran_asn1_rrc_nr_test.cc @@ -285,7 +285,7 @@ int test_radio_bearer_config() return SRSRAN_SUCCESS; } -int test_cell_group_config() +int test_cell_group_config_tdd() { uint8_t cell_group_config_raw[] = "\x5c\x40\xb1\xc0\x33\xc8\x53\xe0\x12\x0f\x05\x38\x0f\x80\x41\x15" "\x07\xad\x40\x00\xba\x14\xe6\x37\xd1\xa4\xd3\xa0\x01\x34\x9a\x5f" @@ -905,6 +905,615 @@ int test_cell_group_config() return SRSRAN_SUCCESS; } +int test_cell_group_config_fdd() +{ + uint8_t cell_group_config_raw[] = "\x5c\x40\xb1\xc0\x7d\x48\x3a\x04\xc0\x3e\x01\x04\x54\x1e\xb5\x80" + "\x02\xe8\x53\xb8\x9f\x46\x85\x60\xa4\x00\x40\xab\x41\x00\x00\x00" + "\xcd\x8d\xb2\x44\xa2\x01\xff\x00\x00\x00\x00\x01\x1b\x82\x21\x00" + "\x01\x24\x04\x00\xd0\x14\x6c\x00\x10\x28\x9d\xc0\x00\x00\x33\x71" + "\xb6\x48\x90\x04\x00\x08\x2e\x25\x18\xf0\x02\x4a\x31\x06\xe1\x8d" + "\xb8\x44\x70\x01\x08\x4c\x23\x06\xdd\x40\x01\x01\xc0\x24\xb8\x19" + "\x50\x00\x2f\xf0\x00\x00\x00\x00\x10\x6e\x11\x04\x00\x01\x10\x24" + "\xa0\x04\x19\x04\x00\x00\x40\xd3\x02\x02\x8a\x14\x00\x1c\x90\x30" + "\x00\x02\x66\xaa\xc9\x08\x38\x00\x20\x81\x84\x0a\x18\x39\x38\x81" + "\x22\x85\x8c\x1a\x38\x79\x10\x00\x00\x85\x00\x00\x80\x0a\x50\x00" + "\x10\x00\xc5\x00\x01\x80\x08\x50\x10\x20\x00\xa5\x01\x02\x80\x0c" + "\x50\x10\x30\x00\x85\x02\x03\x80\x0a\x50\x20\x40\xcd\x04\x01\x23" + "\x34\x12\x05\x0c\xd0\x50\x16\x33\x41\x60\x60\xcd\x06\x01\xa3\x34" + "\x1a\x07\x0c\xd0\x70\x1e\x01\x41\x00\x80\x00\xc5\x02\x08\x80\x50" + "\x4a\x04\x84\x30\x28\x42\x01\x22\x80\x14\x92\x1e\x2e\xe0\x0c\x10" + "\xe0\x00\x00\x01\xff\xd2\x94\x98\xc6\x37\x28\x16\x00\x00\x21\x97" + "\x00\x00\x00\x00\x00\x00\x06\x2f\x00\xfa\x08\x48\xad\x54\x50\x04" + "\x70\x01\x80\x00\x82\x00\x0e\x21\x7d\x24\x08\x07\x01\x01\x08\x40" + "\x00\xe2\x17\xd1\xcb\x00\xe0\x40\x22\x08\x00\x1c\x42\xfa\x39\x60" + "\x1c\x0c\x04\x21\x00\x03\x88\x5f\x47\x30\x03\x82\x00\x88\x20\x00" + "\x71\x0b\xe8\xe6\x00\x04\x00\x00\x00\x41\x0c\x04\x08\x0c\x10\x0e" + "\x0d\x00\x00\xe4\x81\x00\x00\x00\x20\x04\x00\x08\x06\x00\x08\x09" + "\x00\x22\x00\xa4\x00\x00\x23\x85\x01\x13\x1c"; + + asn1::SRSASN_CODE err; + + cbit_ref bref(&cell_group_config_raw[0], sizeof(cell_group_config_raw)); + cell_group_cfg_s cell_group_cfg; + + TESTASSERT(cell_group_cfg.unpack(bref) == SRSASN_SUCCESS); + + TESTASSERT(test_pack_unpack_consistency(cell_group_cfg) == SRSASN_SUCCESS); + + TESTASSERT(cell_group_cfg.sp_cell_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.serv_cell_idx_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci == 500); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present == true); + TESTASSERT(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp_present == true); + TESTASSERT( + cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present == + true); + + TESTASSERT( + cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.type() == + asn1::rrc_nr::setup_release_c::types_opts::setup); + + asn1::rrc_nr::rach_cfg_common_s& rach_cfg_common = + cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common.setup(); + + TESTASSERT(rach_cfg_common.rach_cfg_generic.prach_cfg_idx == 16); + TESTASSERT(rach_cfg_common.rach_cfg_generic.msg1_fdm == asn1::rrc_nr::rach_cfg_generic_s::msg1_fdm_opts::one); + TESTASSERT(rach_cfg_common.rach_cfg_generic.zero_correlation_zone_cfg == 0); + TESTASSERT(rach_cfg_common.rach_cfg_generic.preamb_rx_target_pwr == -110); + TESTASSERT(rach_cfg_common.rach_cfg_generic.preamb_trans_max == + asn1::rrc_nr::rach_cfg_generic_s::preamb_trans_max_opts::n7); + TESTASSERT(rach_cfg_common.rach_cfg_generic.pwr_ramp_step == + asn1::rrc_nr::rach_cfg_generic_s::pwr_ramp_step_opts::db4); + TESTASSERT(rach_cfg_common.rach_cfg_generic.ra_resp_win == asn1::rrc_nr::rach_cfg_generic_s::ra_resp_win_opts::sl10); + TESTASSERT(rach_cfg_common.ssb_per_rach_occasion_and_cb_preambs_per_ssb_present == true); + +#if JSON_OUTPUT + asn1::json_writer json_writer; + cell_group_cfg.to_json(json_writer); + srslog::fetch_basic_logger("RRC").info("RRC Secondary Cell Group: Content: %s\n", json_writer.to_string().c_str()); +#endif + + // pack it again + cell_group_cfg_s cell_group_cfg_pack; + + // RLC for DRB1 + cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true; + cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1); + auto& rlc = cell_group_cfg_pack.rlc_bearer_to_add_mod_list[0]; + rlc.lc_ch_id = 4; + rlc.served_radio_bearer_present = true; + rlc.served_radio_bearer.set_drb_id(); + rlc.served_radio_bearer.drb_id() = 1; + rlc.rlc_cfg_present = true; + rlc.rlc_cfg.set_um_bi_dir(); + rlc.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present = true; + rlc.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present = true; + rlc.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc.rlc_cfg.um_bi_dir().dl_um_rlc.t_reassembly = t_reassembly_opts::ms50; + + // MAC logical channel config + rlc.mac_lc_ch_cfg_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params.prio = 11; + rlc.mac_lc_ch_cfg.ul_specific_params.prioritised_bit_rate = + asn1::rrc_nr::lc_ch_cfg_s::ul_specific_params_s_::prioritised_bit_rate_opts::kbps0; + rlc.mac_lc_ch_cfg.ul_specific_params.bucket_size_dur = + asn1::rrc_nr::lc_ch_cfg_s::ul_specific_params_s_::bucket_size_dur_opts::ms100; + rlc.mac_lc_ch_cfg.ul_specific_params.lc_ch_group_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params.lc_ch_group = 6; + rlc.mac_lc_ch_cfg.ul_specific_params.sched_request_id_present = true; + rlc.mac_lc_ch_cfg.ul_specific_params.sched_request_id = 0; + + // mac-CellGroup-Config + cell_group_cfg_pack.mac_cell_group_cfg_present = true; + auto& mac_cell_group = cell_group_cfg_pack.mac_cell_group_cfg; + mac_cell_group.sched_request_cfg_present = true; + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list_present = true; + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list.resize(1); + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list[0].sched_request_id = 0; + mac_cell_group.sched_request_cfg.sched_request_to_add_mod_list[0].sr_trans_max = + asn1::rrc_nr::sched_request_to_add_mod_s::sr_trans_max_opts::n64; + mac_cell_group.bsr_cfg_present = true; + mac_cell_group.bsr_cfg.periodic_bsr_timer = asn1::rrc_nr::bsr_cfg_s::periodic_bsr_timer_opts::sf20; + mac_cell_group.bsr_cfg.retx_bsr_timer = asn1::rrc_nr::bsr_cfg_s::retx_bsr_timer_opts::sf320; + // Skip TAG and PHR config + + cell_group_cfg_pack.sp_cell_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx_present = true; + + // SP Cell Dedicated config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present = true; + + // PDCCH config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg_present = true; + auto& pdcch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg; + pdcch_cfg_dedicated.set_setup(); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list_present = true; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list.resize(1); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].freq_domain_res.from_number( + 0b111111110000000000000000000000000000000000000); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].dur = 1; + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].cce_reg_map_type.set_non_interleaved(); + pdcch_cfg_dedicated.setup().ctrl_res_set_to_add_mod_list[0].precoder_granularity = + asn1::rrc_nr::ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle; + + // search spaces + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list.resize(1); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_id = 2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].ctrl_res_set_id = 2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].monitoring_symbols_within_slot.from_number( + 0b10000000000000); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level1 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level1_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level2 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level2_opts::n2; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level4 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level8 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].nrof_candidates.aggregation_level16 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type_present = true; + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.set_ue_specific(); + pdcch_cfg_dedicated.setup().search_spaces_to_add_mod_list[0].search_space_type.ue_specific().dci_formats = asn1:: + rrc_nr::search_space_s::search_space_type_c_::ue_specific_s_::dci_formats_opts::formats0_minus0_and_minus1_minus0; + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg_present = true; + auto& pdsch_cfg_dedicated = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdsch_cfg; + + pdsch_cfg_dedicated.set_setup(); + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a_present = true; + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.set_setup(); + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.setup().dmrs_add_position_present = true; + pdsch_cfg_dedicated.setup().dmrs_dl_for_pdsch_map_type_a.setup().dmrs_add_position = + asn1::rrc_nr::dmrs_dl_cfg_s::dmrs_add_position_opts::pos1; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list_present = true; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list.resize(1); + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].tci_state_id = 0; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.ref_sig.set_ssb(); + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.ref_sig.ssb() = 0; + pdsch_cfg_dedicated.setup().tci_states_to_add_mod_list[0].qcl_type1.qcl_type = + asn1::rrc_nr::qcl_info_s::qcl_type_opts::type_d; + pdsch_cfg_dedicated.setup().res_alloc = pdsch_cfg_s::res_alloc_opts::res_alloc_type1; + pdsch_cfg_dedicated.setup().rbg_size = asn1::rrc_nr::pdsch_cfg_s::rbg_size_opts::cfg1; + pdsch_cfg_dedicated.setup().prb_bundling_type.set_static_bundling(); + pdsch_cfg_dedicated.setup().prb_bundling_type.static_bundling().bundle_size_present = true; + pdsch_cfg_dedicated.setup().prb_bundling_type.static_bundling().bundle_size = + asn1::rrc_nr::pdsch_cfg_s::prb_bundling_type_c_::static_bundling_s_::bundle_size_opts::wideband; + + // ZP-CSI + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list_present = true; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list.resize(1); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].zp_csi_rs_res_id = 0; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.set_row4(); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_domain_alloc.row4().from_number(0b100); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.nrof_ports = + asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p4; + + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.first_ofdm_symbol_in_time_domain = 8; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.cdm_type = + asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::fd_cdm2; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.density.set_one(); + + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.start_rb = 0; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].res_map.freq_band.nrof_rbs = 52; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset_present = true; + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.set_slots80(); + pdsch_cfg_dedicated.setup().zp_csi_rs_res_to_add_mod_list[0].periodicity_and_offset.slots80() = 1; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set_present = true; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.set_setup(); + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_set_id = 0; + pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.resize(1); + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + // UL config dedicated + // PUCCH + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + ul_config.init_ul_bwp_present = true; + ul_config.init_ul_bwp.pucch_cfg_present = true; + ul_config.init_ul_bwp.pucch_cfg.set_setup(); + ul_config.init_ul_bwp.pucch_cfg.setup().format2_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().format2.set_setup(); + ul_config.init_ul_bwp.pucch_cfg.setup().format2.setup().max_code_rate_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().format2.setup().max_code_rate = pucch_max_code_rate_opts::zero_dot25; + + // SR resources + ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list.resize(1); + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + sr_res1.sched_request_res_id = 1; + sr_res1.sched_request_id = 0; + sr_res1.periodicity_and_offset_present = true; + sr_res1.periodicity_and_offset.set_sl40(); + sr_res1.periodicity_and_offset.sl40() = 4; + sr_res1.res_present = true; + sr_res1.res = 16; + + // DL data + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(1); + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 4; + + + //TODO? + // PUCCH resources (only one format1 for the moment) + ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list.resize(1); + auto& pucch_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().res_to_add_mod_list[0]; + pucch_res1.pucch_res_id = 0; + pucch_res1.start_prb = 0; + pucch_res1.format.set_format1(); + pucch_res1.format.format1().init_cyclic_shift = 0; + pucch_res1.format.format1().nrof_symbols = 14; + pucch_res1.format.format1().start_symbol_idx = 0; + pucch_res1.format.format1().time_domain_occ = 0; + + // PUSCH config + ul_config.init_ul_bwp.pusch_cfg_present = true; + ul_config.init_ul_bwp.pusch_cfg.set_setup(); + auto& pusch_cfg_ded = ul_config.init_ul_bwp.pusch_cfg.setup(); + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a_present = true; + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a.set_setup(); + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a.setup().dmrs_add_position_present = true; + pusch_cfg_ded.dmrs_ul_for_pusch_map_type_a.setup().dmrs_add_position = dmrs_ul_cfg_s::dmrs_add_position_opts::pos1; + // PUSH power control skipped + pusch_cfg_ded.res_alloc = pusch_cfg_s::res_alloc_opts::res_alloc_type1; + + // UCI + pusch_cfg_ded.uci_on_pusch_present = true; + pusch_cfg_ded.uci_on_pusch.set_setup(); + pusch_cfg_ded.uci_on_pusch.setup().beta_offsets_present = true; + pusch_cfg_ded.uci_on_pusch.setup().beta_offsets.set_semi_static(); + auto& beta_offset_semi_static = pusch_cfg_ded.uci_on_pusch.setup().beta_offsets.semi_static(); + beta_offset_semi_static.beta_offset_ack_idx1_present = true; + beta_offset_semi_static.beta_offset_ack_idx1 = 9; + beta_offset_semi_static.beta_offset_ack_idx2_present = true; + beta_offset_semi_static.beta_offset_ack_idx2 = 9; + beta_offset_semi_static.beta_offset_ack_idx3_present = true; + beta_offset_semi_static.beta_offset_ack_idx3 = 9; + beta_offset_semi_static.beta_offset_csi_part1_idx1_present = true; + beta_offset_semi_static.beta_offset_csi_part1_idx1 = 6; + beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true; + beta_offset_semi_static.beta_offset_csi_part1_idx2 = 6; + beta_offset_semi_static.beta_offset_csi_part2_idx1_present = true; + beta_offset_semi_static.beta_offset_csi_part2_idx1 = 6; + beta_offset_semi_static.beta_offset_csi_part2_idx2_present = true; + beta_offset_semi_static.beta_offset_csi_part2_idx2 = 6; + pusch_cfg_ded.uci_on_pusch.setup().scaling = uci_on_pusch_s::scaling_opts::f1; + + ul_config.first_active_ul_bwp_id_present = true; + ul_config.first_active_ul_bwp_id = 0; + + // Serving cell config (only to setup) + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdcch_serving_cell_cfg.set_setup(); + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.set_setup(); + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.setup().nrof_harq_processes_for_pdsch_present = + true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.pdsch_serving_cell_cfg.setup().nrof_harq_processes_for_pdsch = + pdsch_serving_cell_cfg_s::nrof_harq_processes_for_pdsch_opts::n16; + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.set_setup(); + + //TODO? + // nzp-CSI-RS Resource + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list.resize(1); + auto& nzp_csi_res = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; + nzp_csi_res.nzp_csi_rs_res_id = 0; + nzp_csi_res.res_map.freq_domain_alloc.set_row2(); + nzp_csi_res.res_map.freq_domain_alloc.row2().from_number(0b100000000000); + nzp_csi_res.res_map.nrof_ports = asn1::rrc_nr::csi_rs_res_map_s::nrof_ports_opts::p1; + nzp_csi_res.res_map.first_ofdm_symbol_in_time_domain = 4; + nzp_csi_res.res_map.cdm_type = asn1::rrc_nr::csi_rs_res_map_s::cdm_type_opts::no_cdm; + nzp_csi_res.res_map.density.set_one(); + nzp_csi_res.res_map.freq_band.start_rb = 0; + nzp_csi_res.res_map.freq_band.nrof_rbs = 52; + nzp_csi_res.pwr_ctrl_offset = 0; + // Skip pwr_ctrl_offset_ss_present + nzp_csi_res.scrambling_id = 500; + nzp_csi_res.periodicity_and_offset_present = true; + nzp_csi_res.periodicity_and_offset.set_slots80(); + nzp_csi_res.periodicity_and_offset.slots80() = 1; + // optional + nzp_csi_res.qcl_info_periodic_csi_rs_present = true; + nzp_csi_res.qcl_info_periodic_csi_rs = 0; + + //TODO? + // nzp-CSI-RS ResourceSet + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list_present = + true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1); + auto& nzp_csi_res_set = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; + nzp_csi_res_set.nzp_csi_res_set_id = 1; + nzp_csi_res_set.nzp_csi_rs_res.resize(1); + nzp_csi_res_set.nzp_csi_rs_res[0] = 1; + // Skip TRS info + + // CSI report config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list.resize(1); + auto& csi_report = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().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().report_slot_cfg.slots80() = 5; + 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 = 17; + csi_report.report_quant.set_cri_ri_pmi_cqi(); + 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 = + asn1::rrc_nr::csi_report_cfg_s::report_freq_cfg_s_::cqi_format_ind_opts::wideband_cqi; + csi_report.time_restrict_for_ch_meass = asn1::rrc_nr::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(); + 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; + + // Reconfig with Sync + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = 17933; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = -36; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dmrs_type_a_position = + asn1::rrc_nr::serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci = 500; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_subcarrier_spacing = + subcarrier_spacing_opts::khz30; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.n_timing_advance_offset = + asn1::rrc_nr::serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0; + + // DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .absolute_freq_ssb_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = + 176210; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list + .push_back(5); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + 175364; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .scs_specific_carrier_list.resize(1); + auto& dl_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl + .scs_specific_carrier_list[0]; + dl_carrier.offset_to_carrier = 0; + dl_carrier.subcarrier_spacing = subcarrier_spacing_opts::khz15; + dl_carrier.carrier_bw = 52; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.generic_params + .location_and_bw = 14025; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.generic_params + .subcarrier_spacing = subcarrier_spacing_opts::khz15; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdcch_cfg_common_present = true; + auto& pdcch_cfg_common = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common; + pdcch_cfg_common.set_setup(); + pdcch_cfg_common.setup().common_ctrl_res_set_present = true; + pdcch_cfg_common.setup().common_ctrl_res_set.ctrl_res_set_id = 1; + pdcch_cfg_common.setup().common_ctrl_res_set.freq_domain_res.from_number( + 0b111111110000000000000000000000000000000000000); + pdcch_cfg_common.setup().common_ctrl_res_set.dur = 1; + pdcch_cfg_common.setup().common_ctrl_res_set.cce_reg_map_type.set_non_interleaved(); + pdcch_cfg_common.setup().common_ctrl_res_set.precoder_granularity = + asn1::rrc_nr::ctrl_res_set_s::precoder_granularity_opts::same_as_reg_bundle; + + // common search space list + pdcch_cfg_common.setup().common_search_space_list_present = true; + pdcch_cfg_common.setup().common_search_space_list.resize(1); + pdcch_cfg_common.setup().common_search_space_list[0].search_space_id = 1; + pdcch_cfg_common.setup().common_search_space_list[0].ctrl_res_set_id_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].ctrl_res_set_id = 1; + pdcch_cfg_common.setup().common_search_space_list[0].search_space_type_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].search_space_type.set_common(); + pdcch_cfg_common.setup() + .common_search_space_list[0] + .search_space_type.common() + .dci_format0_minus0_and_format1_minus0_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level1 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level1_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level2 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level2_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level4 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level8 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; + pdcch_cfg_common.setup().common_search_space_list[0].nrof_candidates.aggregation_level16 = + asn1::rrc_nr::search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_slot_periodicity_and_offset_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_slot_periodicity_and_offset.set_sl1(); + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_symbols_within_slot_present = true; + pdcch_cfg_common.setup().common_search_space_list[0].monitoring_symbols_within_slot.from_number(0b10000000000000); + pdcch_cfg_common.setup().ra_search_space_present = true; + pdcch_cfg_common.setup().ra_search_space = 1; + + // PDSCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdsch_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdsch_cfg_common + .set_setup(); + auto& pdsch_cfg_common = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp + .pdsch_cfg_common.setup(); + pdsch_cfg_common.pdsch_time_domain_alloc_list_present = true; + pdsch_cfg_common.pdsch_time_domain_alloc_list.resize(1); + pdsch_cfg_common.pdsch_time_domain_alloc_list[0].map_type = pdsch_time_domain_res_alloc_s::map_type_opts::type_a; + pdsch_cfg_common.pdsch_time_domain_alloc_list[0].start_symbol_and_len = 40; + + // UL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.dummy = time_align_timer_opts::ms500; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul + .scs_specific_carrier_list.resize(1); + auto& ul_carrier = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.freq_info_ul + .scs_specific_carrier_list[0]; + ul_carrier.offset_to_carrier = 0; + ul_carrier.subcarrier_spacing = subcarrier_spacing_opts::khz15; + ul_carrier.carrier_bw = 52; + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.generic_params + .location_and_bw = 14025; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.generic_params + .subcarrier_spacing = subcarrier_spacing_opts::khz15; + + // RACH config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present = + true; + auto& rach_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; + + rach_cfg_common_pack.set_setup(); + rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 16; + rach_cfg_common_pack.setup().rach_cfg_generic.msg1_fdm = rach_cfg_generic_s::msg1_fdm_opts::one; + rach_cfg_common_pack.setup().rach_cfg_generic.msg1_freq_start = 1; + rach_cfg_common_pack.setup().rach_cfg_generic.zero_correlation_zone_cfg = 0; + rach_cfg_common_pack.setup().rach_cfg_generic.preamb_rx_target_pwr = -110; + rach_cfg_common_pack.setup().rach_cfg_generic.preamb_trans_max = + asn1::rrc_nr::rach_cfg_generic_s::preamb_trans_max_opts::n7; + rach_cfg_common_pack.setup().rach_cfg_generic.pwr_ramp_step = + asn1::rrc_nr::rach_cfg_generic_s::pwr_ramp_step_opts::db4; + rach_cfg_common_pack.setup().rach_cfg_generic.ra_resp_win = asn1::rrc_nr::rach_cfg_generic_s::ra_resp_win_opts::sl10; + rach_cfg_common_pack.setup().ra_contention_resolution_timer = + asn1::rrc_nr::rach_cfg_common_s::ra_contention_resolution_timer_opts::sf64; + rach_cfg_common_pack.setup().prach_root_seq_idx.set( + asn1::rrc_nr::rach_cfg_common_s::prach_root_seq_idx_c_::types_opts::l839); + rach_cfg_common_pack.setup().prach_root_seq_idx.set_l839() = 1; + rach_cfg_common_pack.setup().restricted_set_cfg = + asn1::rrc_nr::rach_cfg_common_s::restricted_set_cfg_opts::unrestricted_set; + + // PUSCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp + .pusch_cfg_common_present = true; + auto& pusch_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.pusch_cfg_common; + pusch_cfg_common_pack.set_setup(); + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list.resize(2); + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].k2_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].k2 = 4; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].map_type = + asn1::rrc_nr::pusch_time_domain_res_alloc_s::map_type_opts::type_a; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[0].start_symbol_and_len = 27; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].k2_present = true; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].k2 = 3; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].map_type = + asn1::rrc_nr::pusch_time_domain_res_alloc_s::map_type_opts::type_a; + pusch_cfg_common_pack.setup().pusch_time_domain_alloc_list[1].start_symbol_and_len = 27; + pusch_cfg_common_pack.setup().p0_nominal_with_grant = -90; + + // PUCCH config common + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp + .pucch_cfg_common_present = true; + auto& pucch_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.pucch_cfg_common; + pucch_cfg_common_pack.set_setup(); + pucch_cfg_common_pack.setup().pucch_group_hop = asn1::rrc_nr::pucch_cfg_common_s::pucch_group_hop_opts::neither; + pucch_cfg_common_pack.setup().p0_nominal_present = true; + pucch_cfg_common_pack.setup().p0_nominal = -90; + + // SSB config (optional) + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; + auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst; + ssb_pos_in_burst.set_short_bitmap().from_number(0b1000); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell = + serving_cell_cfg_common_s::ssb_periodicity_serving_cell_opts::ms20; + + // pack only cell group info + asn1::dyn_octstring packed_cell_group; + packed_cell_group.resize(256); + asn1::bit_ref bref_pack(packed_cell_group.data(), packed_cell_group.size()); + TESTASSERT(cell_group_cfg_pack.pack(bref_pack) == asn1::SRSASN_SUCCESS); + TESTASSERT(test_pack_unpack_consistency(cell_group_cfg_pack) == SRSASN_SUCCESS); + packed_cell_group.resize(bref_pack.distance_bytes()); + +#if JSON_OUTPUT + asn1::json_writer json_writer2; + cell_group_cfg_pack.to_json(json_writer2); + srslog::fetch_basic_logger("RRC").info(packed_cell_group.data(), + packed_cell_group.size(), + "Cell group config repacked (%d B): \n %s", + packed_cell_group.size(), + json_writer2.to_string().c_str()); +#endif + +#if HAVE_PCAP + // pack full DL-DCCH with RRC reconfig for PCAP output + dl_dcch_msg_s dcch; + dcch.msg.set_c1().set_rrc_recfg(); + rrc_recfg_s& reconfig = dcch.msg.c1().rrc_recfg(); + reconfig.rrc_transaction_id = 0; + reconfig.crit_exts.set_rrc_recfg(); + rrc_recfg_ies_s& recfg_ies = reconfig.crit_exts.rrc_recfg(); + recfg_ies.secondary_cell_group_present = true; + recfg_ies.secondary_cell_group = packed_cell_group; + + asn1::dyn_octstring packed_dcch; + packed_dcch.resize(1024); + asn1::bit_ref bref_dcch_pack(packed_dcch.data(), packed_dcch.size()); + TESTASSERT(dcch.pack(bref_dcch_pack) == asn1::SRSASN_SUCCESS); + packed_dcch.resize(bref_dcch_pack.distance_bytes() + 10); + + asn1::json_writer json_writer3; + dcch.to_json(json_writer3); + srslog::fetch_basic_logger("RRC").info(packed_dcch.data(), + packed_dcch.size(), + "Full DCCH repacked (%d B): \n %s", + packed_dcch.size(), + json_writer3.to_string().c_str()); + + srsran::write_pdcp_sdu_nr(1, packed_dcch.data(), packed_dcch.size()); +#endif + + return SRSRAN_SUCCESS; +} + + int main() { auto& asn1_logger = srslog::fetch_basic_logger("ASN1", false); @@ -926,7 +1535,8 @@ int main() TESTASSERT(test_ue_mrdc_capabilities() == SRSRAN_SUCCESS); TESTASSERT(test_ue_rrc_reconfiguration() == SRSRAN_SUCCESS); TESTASSERT(test_radio_bearer_config() == SRSRAN_SUCCESS); - TESTASSERT(test_cell_group_config() == SRSRAN_SUCCESS); + TESTASSERT(test_cell_group_config_tdd() == SRSRAN_SUCCESS); + TESTASSERT(test_cell_group_config_fdd() == SRSRAN_SUCCESS); srslog::flush(); From 651a76000e324e74240d9b990a3e5db974e439a6 Mon Sep 17 00:00:00 2001 From: Fabian Eckermann Date: Tue, 21 Sep 2021 14:57:35 +0200 Subject: [PATCH 39/39] Add function to pack secondary cell group config for FDD. --- srsenb/hdr/stack/rrc/rrc_nr.h | 4 +- srsenb/src/stack/rrc/rrc_nr.cc | 210 +++++++++++++++++++++++++++------ 2 files changed, 180 insertions(+), 34 deletions(-) diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 15b01e7f5..2b5c9932e 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -118,7 +118,9 @@ public: uint16_t rnti = SRSRAN_INVALID_RNTI; int pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfig); - int pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config); + int pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed_secondary_cell_config); + int pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed_secondary_cell_config); int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config); int add_drb(); diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index cb7213307..535f8a62e 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -492,10 +492,8 @@ void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) } // Helper for the RRC Reconfiguration sender to pack hard-coded config -int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_secondary_cell_config) +int rrc_nr::ue::pack_secondary_cell_group_config_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) { - auto& cell_group_cfg_pack = cell_group_cfg; - // RLC for DRB1 (with fixed LCID) cell_group_cfg_pack.rlc_bearer_to_add_mod_list_present = true; cell_group_cfg_pack.rlc_bearer_to_add_mod_list.resize(1); @@ -635,7 +633,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec pdsch_cfg_dedicated.setup().p_zp_csi_rs_res_set.setup().zp_csi_rs_res_id_list.resize(1); cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id_present = true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; // UL config dedicated @@ -657,19 +654,10 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec sr_res1.sched_request_id = 0; sr_res1.periodicity_and_offset_present = true; sr_res1.periodicity_and_offset.set_sl40(); - sr_res1.periodicity_and_offset.sl40() = 7; sr_res1.res_present = true; - sr_res1.res = 2; // PUCCH resource for SR // DL data ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(6); - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 6; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[1] = 5; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[2] = 4; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[3] = 4; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[4] = 4; - ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[5] = 4; // PUCCH Resource for format 1 srsran_pucch_nr_resource_t resource_small = {}; @@ -755,8 +743,8 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec beta_offset_semi_static.beta_offset_ack_idx3_present = true; beta_offset_semi_static.beta_offset_ack_idx3 = 9; beta_offset_semi_static.beta_offset_csi_part1_idx1_present = true; - beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true; beta_offset_semi_static.beta_offset_csi_part1_idx1 = 6; + beta_offset_semi_static.beta_offset_csi_part1_idx2_present = true; beta_offset_semi_static.beta_offset_csi_part1_idx2 = 6; beta_offset_semi_static.beta_offset_csi_part2_idx1_present = true; beta_offset_semi_static.beta_offset_csi_part2_idx1 = 6; @@ -796,10 +784,8 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec nzp_csi_res.res_map.freq_band.nrof_rbs = 52; nzp_csi_res.pwr_ctrl_offset = 0; // Skip pwr_ctrl_offset_ss_present - nzp_csi_res.scrambling_id = 0; nzp_csi_res.periodicity_and_offset_present = true; nzp_csi_res.periodicity_and_offset.set_slots80(); - nzp_csi_res.periodicity_and_offset.slots80() = 0; // optional nzp_csi_res.qcl_info_periodic_csi_rs_present = true; nzp_csi_res.qcl_info_periodic_csi_rs = 0; @@ -810,9 +796,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list.resize(1); auto& nzp_csi_res_set = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; - nzp_csi_res_set.nzp_csi_res_set_id = 0; nzp_csi_res_set.nzp_csi_rs_res.resize(1); - nzp_csi_res_set.nzp_csi_rs_res[0] = 0; // Skip TRS info // CSI report config @@ -826,7 +810,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec 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().report_slot_cfg.slots80() = 8; 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 = 0; // was 17 in orig PCAP @@ -848,11 +831,11 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec // Reconfig with Sync cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.new_ue_id = rnti; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.t304 = recfg_with_sync_s::t304_opts::ms1000; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.n_timing_advance_offset = + asn1::rrc_nr::serving_cell_cfg_common_s::n_timing_advance_offset_opts::n0; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dmrs_type_a_position = asn1::rrc_nr::serving_cell_cfg_common_s::dmrs_type_a_position_opts::pos2; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.pci_present = true; @@ -866,13 +849,7 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl .absolute_freq_ssb_present = true; - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = - 634176; // TODO: calculate from actual DL ARFCN - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list - .push_back(78); - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = - 633928; // TODO: calculate from actual DL ARFCN cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl .scs_specific_carrier_list.resize(1); @@ -896,7 +873,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec auto& pdcch_cfg_common = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common; pdcch_cfg_common.set_setup(); - pdcch_cfg_common.setup().ext = false; pdcch_cfg_common.setup().common_ctrl_res_set_present = true; pdcch_cfg_common.setup().common_ctrl_res_set.ctrl_res_set_id = 1; pdcch_cfg_common.setup().common_ctrl_res_set.freq_domain_res.from_number( @@ -973,7 +949,6 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; rach_cfg_common_pack.set_setup(); - rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0; rach_cfg_common_pack.setup().rach_cfg_generic.msg1_fdm = rach_cfg_generic_s::msg1_fdm_opts::one; rach_cfg_common_pack.setup().rach_cfg_generic.msg1_freq_start = 1; rach_cfg_common_pack.setup().rach_cfg_generic.zero_correlation_zone_cfg = 0; @@ -1024,12 +999,181 @@ int rrc_nr::ue::pack_secondary_cell_group_config(asn1::dyn_octstring& packed_sec // SSB config (optional) cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst; - ssb_pos_in_burst.set_medium_bitmap().from_number(0b10000000); cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell_present = true; cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_periodicity_serving_cell = serving_cell_cfg_common_s::ssb_periodicity_serving_cell_opts::ms20; - // TDD UL-DL config + return SRSRAN_SUCCESS; +} + +// Helper for the RRC Reconfiguration sender to pack hard-coded config +int rrc_nr::ue::pack_secondary_cell_group_config_fdd(asn1::dyn_octstring& packed_secondary_cell_config) +{ + + auto& cell_group_cfg_pack = cell_group_cfg; + pack_secondary_cell_group_config_common(cell_group_cfg); + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + // UL config dedicated + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + // SR resources + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + sr_res1.periodicity_and_offset.sl40() = 4; + sr_res1.res_present = true; + sr_res1.res = 16; // PUCCH resource for SR + + // DL data + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(1); + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 4; + + // nzp-CSI-RS Resource + auto& nzp_csi_res = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; + nzp_csi_res.scrambling_id = 500; + nzp_csi_res.periodicity_and_offset_present = true; + nzp_csi_res.periodicity_and_offset.set_slots80(); + nzp_csi_res.periodicity_and_offset.slots80() = 1; + + // nzp-CSI-RS ResourceSet + auto& nzp_csi_res_set = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; + nzp_csi_res_set.nzp_csi_res_set_id = 1; + nzp_csi_res_set.nzp_csi_rs_res[0] = 1; + + // CSI report config + auto& csi_report = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 5; + + // Reconfig with Sync + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = -36; + + // DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = + 176210; // TODO: calculate from actual DL ARFCN + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list + .push_back(5); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + 175364; // TODO: calculate from actual DL ARFCN + + // RACH config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present = + true; + auto& rach_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; + + rach_cfg_common_pack.set_setup(); + rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 16; + + // SSB config (optional) + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; + auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst; + ssb_pos_in_burst.set_short_bitmap().from_number(0b1000); + + // make sufficiant space + packed_secondary_cell_config.resize(256); + asn1::bit_ref bref_pack(packed_secondary_cell_config.data(), packed_secondary_cell_config.size()); + if (cell_group_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) { + parent->logger.error("Failed to pack NR secondary cell config"); + return SRSRAN_ERROR; + } + packed_secondary_cell_config.resize(bref_pack.distance_bytes()); + + return SRSRAN_SUCCESS; +} + +// Helper for the RRC Reconfiguration sender to pack hard-coded config +int rrc_nr::ue::pack_secondary_cell_group_config_tdd(asn1::dyn_octstring& packed_secondary_cell_config) +{ + + auto& cell_group_cfg_pack = cell_group_cfg; + pack_secondary_cell_group_config_common(cell_group_cfg); + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + // UL config dedicated + auto& ul_config = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg; + // SR resources + auto& sr_res1 = ul_config.init_ul_bwp.pucch_cfg.setup().sched_request_res_to_add_mod_list[0]; + // SR resources + sr_res1.periodicity_and_offset.sl40() = 7; + sr_res1.res_present = true; + sr_res1.res = 2; // PUCCH resource for SR + + // DL data + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack_present = true; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack.resize(6); + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[0] = 6; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[1] = 5; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[2] = 4; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[3] = 4; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[4] = 4; + ul_config.init_ul_bwp.pucch_cfg.setup().dl_data_to_ul_ack[5] = 4; + + // nzp-CSI-RS Resource + auto& nzp_csi_res = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_to_add_mod_list[0]; + nzp_csi_res.scrambling_id = 0; + nzp_csi_res.periodicity_and_offset_present = true; + nzp_csi_res.periodicity_and_offset.set_slots80(); + nzp_csi_res.periodicity_and_offset.slots80() = 0; + + // nzp-CSI-RS ResourceSet + auto& nzp_csi_res_set = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().nzp_csi_rs_res_set_to_add_mod_list[0]; + nzp_csi_res_set.nzp_csi_res_set_id = 0; + nzp_csi_res_set.nzp_csi_rs_res[0] = 0; + // Skip TRS info + + // CSI report config + auto& csi_report = + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.csi_meas_cfg.setup().csi_report_cfg_to_add_mod_list[0]; + csi_report.report_cfg_type.periodic().report_slot_cfg.slots80() = 8; + + // Reconfig with Sync + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ss_pbch_block_pwr = 0; + + // DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_ssb = + 634176; // TODO: calculate from actual DL ARFCN + + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.freq_band_list + .push_back(78); + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.freq_info_dl.absolute_freq_point_a = + 633928; // TODO: calculate from actual DL ARFCN + + auto& pdcch_cfg_common = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common; + pdcch_cfg_common.set_setup(); + pdcch_cfg_common.setup().ext = false; + + + // RACH config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common_present = + true; + auto& rach_cfg_common_pack = + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ul_cfg_common.init_ul_bwp.rach_cfg_common; + + rach_cfg_common_pack.set_setup(); + rach_cfg_common_pack.setup().rach_cfg_generic.prach_cfg_idx = 0; + + // SSB config (optional) + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst_present = true; + auto& ssb_pos_in_burst = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.ssb_positions_in_burst; + ssb_pos_in_burst.set_medium_bitmap().from_number(0b10000000); + + // // TDD UL-DL config cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present = true; auto& tdd_config = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common; tdd_config.ref_subcarrier_spacing = subcarrier_spacing_e::khz15; @@ -1060,8 +1204,8 @@ int rrc_nr::ue::pack_rrc_reconfiguraiton(asn1::dyn_octstring& packed_rrc_reconfi // add secondary cell group config recfg_ies.secondary_cell_group_present = true; - if (pack_secondary_cell_group_config(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { - parent->logger.error("Failed to pack RRC Reconfiguration"); + if (pack_secondary_cell_group_config_tdd(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack TDD RRC Reconfiguration"); return SRSRAN_ERROR; }