From b44372faae527de47aea42c3226cb5b5cb79380b Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 3 Nov 2021 15:19:08 +0100 Subject: [PATCH 01/35] crash_handler: write backtrace to stderr instead of backtrace file the backtrace file is hard to collect in some environment but the stdout and stderr is usually captured by default. --- lib/src/common/crash_handler.cc | 42 ++++++++++++++------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/lib/src/common/crash_handler.cc b/lib/src/common/crash_handler.cc index 93b6f6466..432e0e9d5 100644 --- a/lib/src/common/crash_handler.cc +++ b/lib/src/common/crash_handler.cc @@ -28,38 +28,32 @@ void srsran_debug_handle_crash(int argc, char** argv) #include "srsran/common/backtrace.h" #include "srsran/version.h" -const static char crash_file_name[] = "./srsRAN.backtrace.crash"; -static int bt_argc; -static char** bt_argv; +static int bt_argc; +static char** bt_argv; static void crash_handler(int sig) { - FILE* f = fopen(crash_file_name, "a"); - if (!f) { - printf("srsRAN crashed... we could not save backtrace in '%s'...\n", crash_file_name); - } else { - time_t lnTime; - struct tm stTime; - char strdate[32]; + FILE* f = stderr; + time_t lnTime; + struct tm stTime; + char strdate[32]; - time(&lnTime); - gmtime_r(&lnTime, &stTime); + time(&lnTime); + gmtime_r(&lnTime, &stTime); - strftime(strdate, sizeof(strdate), "%d/%m/%Y %H:%M:%S", &stTime); + strftime(strdate, sizeof(strdate), "%d/%m/%Y %H:%M:%S", &stTime); - fprintf(f, "--- command='"); - for (int i = 0; i < bt_argc; i++) { - fprintf(f, "%s%s", (i == 0) ? "" : " ", bt_argv[i]); - } - fprintf(f, "' version=%s signal=%d date='%s' ---\n", SRSRAN_VERSION_STRING, sig, strdate); + fprintf(f, "--- command='"); + for (int i = 0; i < bt_argc; i++) { + fprintf(f, "%s%s", (i == 0) ? "" : " ", bt_argv[i]); + } + fprintf(f, "' version=%s signal=%d date='%s' ---\n", SRSRAN_VERSION_STRING, sig, strdate); - srsran_backtrace_print(f); - fprintf(f, "\n"); + srsran_backtrace_print(f); - printf("srsRAN crashed... backtrace saved in '%s'...\n", crash_file_name); - fclose(f); - } - printf("--- exiting ---\n"); + fprintf(f, "srsRAN crashed. Please send this backtrace to the developers ...\n"); + + fprintf(f, "--- exiting ---\n"); exit(1); } From 1ead159f3fcd9a9a2885c14c221beeb7eb1e15ac Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 3 Nov 2021 15:21:38 +0100 Subject: [PATCH 02/35] backward: make signalhandler object static having the sh a normal stack variable made the backtrace disappear in some runs. --- lib/src/common/crash_handler.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/common/crash_handler.cc b/lib/src/common/crash_handler.cc index 432e0e9d5..0941daba8 100644 --- a/lib/src/common/crash_handler.cc +++ b/lib/src/common/crash_handler.cc @@ -22,7 +22,7 @@ using namespace backward; void srsran_debug_handle_crash(int argc, char** argv) { - backward::SignalHandling sh; + static backward::SignalHandling sh; } #else // HAVE_BACKWARD #include "srsran/common/backtrace.h" From dab6e8bdcdddbfb9cf7c49471784b64bcdaf0bcd Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 3 Nov 2021 15:46:28 +0000 Subject: [PATCH 03/35] nr,gnb: updates in parsing and phy files to allow the splitting of NR and LTE stacks --- lib/include/srsran/common/network_utils.h | 6 ++ srsenb/hdr/stack/enb_stack_lte.h | 2 - srsenb/hdr/stack/gnb_stack_nr.h | 18 +++-- srsenb/hdr/stack/ngap/ngap.h | 6 +- srsenb/src/enb_cfg_parser.cc | 80 +++++++++++++---------- srsenb/src/phy/phy.cc | 4 +- srsenb/src/stack/enb_stack_lte.cc | 6 +- srsenb/src/stack/gnb_stack_nr.cc | 32 +++++++-- 8 files changed, 99 insertions(+), 55 deletions(-) diff --git a/lib/include/srsran/common/network_utils.h b/lib/include/srsran/common/network_utils.h index 9ec7a19c9..8e3de4ac1 100644 --- a/lib/include/srsran/common/network_utils.h +++ b/lib/include/srsran/common/network_utils.h @@ -187,6 +187,12 @@ make_sctp_sdu_handler(srslog::basic_logger& logger, srsran::task_queue_handle& q socket_manager_itf::recv_callback_t make_sdu_handler(srslog::basic_logger& logger, srsran::task_queue_handle& queue, recvfrom_callback_t rx_callback); +inline socket_manager& get_rx_io_manager() +{ + static socket_manager io; + return io; +} + } // namespace srsran #endif // SRSRAN_RX_SOCKET_HANDLER_H diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 1f3cb8e34..45893891c 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -149,8 +149,6 @@ private: stack_args_t args = {}; rrc_cfg_t rrc_cfg = {}; - srsran::socket_manager rx_sockets; - srslog::basic_logger& mac_logger; srslog::basic_logger& rlc_logger; srslog::basic_logger& pdcp_logger; diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 426046b45..b35e20bbc 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -29,9 +29,13 @@ namespace srsenb { +class ngap; +class gtpu; + struct gnb_stack_args_t { stack_log_args_t log; mac_nr_args_t mac; + ngap_args_t ngap; }; class gnb_stack_nr final : public srsenb::enb_stack_base, @@ -121,6 +125,8 @@ private: srslog::basic_logger& mac_logger; srslog::basic_logger& rlc_logger; srslog::basic_logger& pdcp_logger; + srslog::basic_logger& ngap_logger; + srslog::basic_logger& gtpu_logger; srslog::basic_logger& stack_logger; // task scheduling @@ -133,11 +139,13 @@ private: std::mutex metrics_mutex; std::condition_variable metrics_cvar; - // derived - srsenb::mac_nr mac; - srsenb::rlc rlc; - srsenb::pdcp pdcp; - srsenb::rrc_nr rrc; + // layers + srsenb::mac_nr mac; + srsenb::rlc rlc; + srsenb::pdcp pdcp; + srsenb::rrc_nr rrc; + std::unique_ptr ngap; + std::unique_ptr gtpu; // std::unique_ptr m_sdap; // state diff --git a/srsenb/hdr/stack/ngap/ngap.h b/srsenb/hdr/stack/ngap/ngap.h index 7fb014e28..63bd0e423 100644 --- a/srsenb/hdr/stack/ngap/ngap.h +++ b/srsenb/hdr/stack/ngap/ngap.h @@ -26,16 +26,16 @@ #include "srsran/common/standard_streams.h" #include "srsran/common/task_scheduler.h" #include "srsran/common/threads.h" +#include "srsran/interfaces/enb_gtpu_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" -#include "srsran/interfaces/enb_gtpu_interfaces.h" #include "srsran/srslog/srslog.h" #include #include namespace srsenb { -class ngap : public ngap_interface_rrc_nr +class ngap final : public ngap_interface_rrc_nr { public: class ue; @@ -70,7 +70,7 @@ public: // Stack interface bool - handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); + handle_amf_rx_msg(srsran::unique_byte_buffer_t pdu, const sockaddr_in& from, const sctp_sndrcvinfo& sri, int flags); void get_metrics(ngap_metrics_t& m); void get_args(ngap_args_t& args_); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 863fac877..e74763497 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1176,15 +1176,24 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr // update number of NR cells rrc_cfg_->num_nr_cells = rrc_nr_cfg_->cell_list.size(); args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_nr_cfg_->cell_list.size(); - - // update EUTRA RRC params for ENDC - if (rrc_nr_cfg_->cell_list.size() == 1) { - rrc_cfg_->endc_cfg.abs_frequency_ssb = rrc_nr_cfg_->cell_list.at(0).ssb_absolute_freq_point; - rrc_cfg_->endc_cfg.nr_band = rrc_nr_cfg_->cell_list.at(0).band; - rrc_cfg_->endc_cfg.ssb_period_offset.set_sf10_r15(); - rrc_cfg_->endc_cfg.ssb_duration = asn1::rrc::mtc_ssb_nr_r15_s::ssb_dur_r15_opts::sf1; - rrc_cfg_->endc_cfg.ssb_ssc = asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz15; - rrc_cfg_->endc_cfg.act_from_b1_event = true; // ENDC will only be activated from B1 measurment + ASSERT_VALID_CFG(args_->rf.nof_carriers > 0, "There must be at least one NR or LTE cell"); + if (rrc_nr_cfg_->cell_list.size() > 0) { + // NR cells available. + if (rrc_cfg_->cell_list.size() == 0) { + // SA mode. Update NGAP args + args_->nr_stack.ngap.gnb_id = args_->enb.enb_id; + args_->nr_stack.ngap.cell_id = rrc_nr_cfg_->cell_list[0].phy_cell.cell_id; + args_->nr_stack.ngap.tac = rrc_nr_cfg_->cell_list[0].tac; + } else { + // NSA mode. + // update EUTRA RRC params for ENDC + rrc_cfg_->endc_cfg.abs_frequency_ssb = rrc_nr_cfg_->cell_list.at(0).ssb_absolute_freq_point; + rrc_cfg_->endc_cfg.nr_band = rrc_nr_cfg_->cell_list.at(0).band; + rrc_cfg_->endc_cfg.ssb_period_offset.set_sf10_r15(); + rrc_cfg_->endc_cfg.ssb_duration = asn1::rrc::mtc_ssb_nr_r15_s::ssb_dur_r15_opts::sf1; + rrc_cfg_->endc_cfg.ssb_ssc = asn1::rrc::rs_cfg_ssb_nr_r15_s::subcarrier_spacing_ssb_r15_opts::khz15; + rrc_cfg_->endc_cfg.act_from_b1_event = true; // ENDC will only be activated from B1 measurment + } } return SRSRAN_SUCCESS; @@ -1193,41 +1202,42 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_, const srsran_cell_t& cell_cfg_) { // Sanity checks - ASSERT_VALID_CFG(not rrc_cfg_->cell_list.empty(), "No cell specified in rr.conf."); ASSERT_VALID_CFG(args_->stack.mac.nof_prealloc_ues <= SRSENB_MAX_UES, "mac.nof_prealloc_ues=%d must be within [0, %d]", args_->stack.mac.nof_prealloc_ues, SRSENB_MAX_UES); // Check for a forced DL EARFCN or frequency (only valid for a single cell config (Xico's favorite feature)) - if (rrc_cfg_->cell_list.size() == 1) { - auto& cfg = rrc_cfg_->cell_list.at(0); - if (args_->enb.dl_earfcn > 0 and args_->enb.dl_earfcn != cfg.dl_earfcn) { - cfg.dl_earfcn = args_->enb.dl_earfcn; - ERROR("Force DL EARFCN for cell PCI=%d to %d", cfg.pci, cfg.dl_earfcn); - } - if (args_->rf.dl_freq > 0) { - cfg.dl_freq_hz = args_->rf.dl_freq; - ERROR("Force DL freq for cell PCI=%d to %f MHz", cfg.pci, cfg.dl_freq_hz / 1e6f); - } - if (args_->rf.ul_freq > 0) { - cfg.ul_freq_hz = args_->rf.ul_freq; - ERROR("Force UL freq for cell PCI=%d to %f MHz", cfg.pci, cfg.ul_freq_hz / 1e6f); - } - } else { - // If more than one cell is defined, single EARFCN or DL freq will be ignored - if (args_->enb.dl_earfcn > 0 || args_->rf.dl_freq > 0) { - INFO("Multiple cells defined in rr.conf. Ignoring single EARFCN and/or frequency config."); + if (rrc_cfg_->cell_list.size() > 1) { + if (rrc_cfg_->cell_list.size() == 1) { + auto& cfg = rrc_cfg_->cell_list.at(0); + if (args_->enb.dl_earfcn > 0 and args_->enb.dl_earfcn != cfg.dl_earfcn) { + cfg.dl_earfcn = args_->enb.dl_earfcn; + ERROR("Force DL EARFCN for cell PCI=%d to %d", cfg.pci, cfg.dl_earfcn); + } + if (args_->rf.dl_freq > 0) { + cfg.dl_freq_hz = args_->rf.dl_freq; + ERROR("Force DL freq for cell PCI=%d to %f MHz", cfg.pci, cfg.dl_freq_hz / 1e6f); + } + if (args_->rf.ul_freq > 0) { + cfg.ul_freq_hz = args_->rf.ul_freq; + ERROR("Force UL freq for cell PCI=%d to %f MHz", cfg.pci, cfg.ul_freq_hz / 1e6f); + } + } else { + // If more than one cell is defined, single EARFCN or DL freq will be ignored + if (args_->enb.dl_earfcn > 0 || args_->rf.dl_freq > 0) { + INFO("Multiple cells defined in rr.conf. Ignoring single EARFCN and/or frequency config."); + } } - } - // set config for RRC's base cell - rrc_cfg_->cell = cell_cfg_; + // set config for RRC's base cell + rrc_cfg_->cell = cell_cfg_; - // Set S1AP related params from cell list - args_->stack.s1ap.enb_id = args_->enb.enb_id; - args_->stack.s1ap.cell_id = rrc_cfg_->cell_list.at(0).cell_id; - args_->stack.s1ap.tac = rrc_cfg_->cell_list.at(0).tac; + // Set S1AP related params from cell list + args_->stack.s1ap.enb_id = args_->enb.enb_id; + args_->stack.s1ap.cell_id = rrc_cfg_->cell_list.at(0).cell_id; + args_->stack.s1ap.tac = rrc_cfg_->cell_list.at(0).tac; + } // Create dedicated cell configuration from RRC configuration for (auto it = rrc_cfg_->cell_list.begin(); it != rrc_cfg_->cell_list.end(); ++it) { diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index d3d5ec8be..aba1cfa30 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -85,7 +85,7 @@ void phy::parse_common_config(const phy_cfg_t& cfg) prach_cfg.root_seq_idx = cfg.prach_cnfg.root_seq_idx; prach_cfg.zero_corr_zone = cfg.prach_cnfg.prach_cfg_info.zero_correlation_zone_cfg; prach_cfg.freq_offset = cfg.prach_cnfg.prach_cfg_info.prach_freq_offset; - prach_cfg.num_ra_preambles = cfg.phy_cell_cfg.at(0).num_ra_preambles; + prach_cfg.num_ra_preambles = cfg.phy_cell_cfg.empty() ? 0 : cfg.phy_cell_cfg.at(0).num_ra_preambles; // DMRS workers_common.dmrs_pusch_cfg.cyclic_shift = cfg.pusch_cnfg.ul_ref_sigs_pusch.cyclic_shift; workers_common.dmrs_pusch_cfg.delta_ss = cfg.pusch_cnfg.ul_ref_sigs_pusch.group_assign_pusch; @@ -160,7 +160,7 @@ int phy::init_lte(const phy_args_t& args, phy_log.set_hex_dump_max_size(args.log.phy_hex_limit); radio = radio_; - nof_workers = args.nof_phy_threads; + nof_workers = cfg.phy_cell_cfg.empty() ? 0 : args.nof_phy_threads; workers_common.params = args; diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 7b698831d..eb4a90c2f 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -89,8 +89,8 @@ enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : pdcp(&task_sched, pdcp_logger), mac(&task_sched, mac_logger), rlc(rlc_logger), - gtpu(&task_sched, gtpu_logger, &rx_sockets), - s1ap(&task_sched, s1ap_logger, &rx_sockets), + gtpu(&task_sched, gtpu_logger, &get_rx_io_manager()), + s1ap(&task_sched, s1ap_logger, &get_rx_io_manager()), rrc(&task_sched, bearers), mac_pcap(), pending_stack_metrics(64) @@ -229,7 +229,7 @@ void enb_stack_lte::stop() void enb_stack_lte::stop_impl() { - rx_sockets.stop(); + get_rx_io_manager().stop(); s1ap.stop(); gtpu.stop(); diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index c228abac2..d325d4b5b 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -11,6 +11,9 @@ */ #include "srsenb/hdr/stack/gnb_stack_nr.h" +#include "srsenb/hdr/stack/ngap/ngap.h" +#include "srsenb/hdr/stack/upper/gtpu.h" +#include "srsran/common/network_utils.h" #include "srsran/common/standard_streams.h" #include "srsran/srsran.h" #include @@ -25,6 +28,8 @@ gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) : 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)), + gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)), + ngap_logger(srslog::fetch_basic_logger("NGAP", log_sink, false)), mac(&task_sched), rrc(&task_sched), pdcp(&task_sched, pdcp_logger), @@ -61,12 +66,21 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, 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)); + ngap_logger.set_level(srslog::str_to_basic_level(args.log.s1ap_level)); + gtpu_logger.set_level(srslog::str_to_basic_level(args.log.gtpu_level)); 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); + ngap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit); + gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit); + + if (x2_ != nullptr) { + ngap.reset(new srsenb::ngap(&task_sched, ngap_logger, &srsran::get_rx_io_manager())); + gtpu.reset(new srsenb::gtpu(&task_sched, gtpu_logger, &srsran::get_rx_io_manager())); + } // Init all layers if (mac.init(args.mac, phy, nullptr, &rlc, &rrc) != SRSRAN_SUCCESS) { @@ -77,15 +91,21 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); pdcp.init(&rlc, &rrc, x2_); - if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, nullptr, nullptr, x2_) != SRSRAN_SUCCESS) { + if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, ngap.get(), nullptr, x2_) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); return SRSRAN_ERROR; } - // 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); + if (ngap != nullptr) { + ngap->init(args.ngap, &rrc, nullptr); + gtpu_args_t gtpu_args; + gtpu_args.embms_enable = false; + gtpu_args.mme_addr = args.ngap.amf_addr; + gtpu_args.gtp_bind_addr = args.ngap.gtp_bind_addr; + gtpu->init(gtpu_args, &pdcp); + } + + // TODO: add SDAP running = true; @@ -104,6 +124,8 @@ void gnb_stack_nr::stop() void gnb_stack_nr::stop_impl() { + srsran::get_rx_io_manager().stop(); + rrc.stop(); pdcp.stop(); mac.stop(); From fa600ebda1be0280cc398feae9fccf2846c06ec3 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 3 Nov 2021 17:30:31 +0100 Subject: [PATCH 04/35] update sampling rate calculation from prb for nr --- lib/src/phy/common/phy_common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/src/phy/common/phy_common.c b/lib/src/phy/common/phy_common.c index f5b5a8f05..8822d2c13 100644 --- a/lib/src/phy/common/phy_common.c +++ b/lib/src/phy/common/phy_common.c @@ -361,11 +361,11 @@ int srsran_symbol_sz(uint32_t nof_prb) return 256; } else if (nof_prb <= 25) { return 384; - } else if (nof_prb <= 50) { + } else if (nof_prb <= 52) { return 768; - } else if (nof_prb <= 75) { + } else if (nof_prb <= 79) { return 1024; - } else if (nof_prb <= 110) { + } else if (nof_prb <= 106) { return 1536; } else { return SRSRAN_ERROR; From d5c235635fe95b753fb7d615f19dbb1cad0215c9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Wed, 3 Nov 2021 17:30:50 +0100 Subject: [PATCH 05/35] check lteworker is not null in log line --- srsenb/src/phy/txrx.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 193486d05..09a0f55d8 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -176,7 +176,7 @@ void txrx::run_thread() tti, timestamp.get(0).full_secs, timestamp.get(0).frac_secs, - lte_worker->get_id()); + lte_worker ? lte_worker->get_id() : 0); // Trigger prach worker execution for (uint32_t cc = 0; cc < worker_com->get_nof_carriers_lte(); cc++) { From 7e7f7b4c0161292b5b46638e8d48995859adc91e Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 4 Nov 2021 14:19:15 +0000 Subject: [PATCH 06/35] nr: fix failing unit tests --- lib/src/phy/common/phy_common.c | 2 +- srsenb/src/enb_cfg_parser.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/phy/common/phy_common.c b/lib/src/phy/common/phy_common.c index 8822d2c13..48dafa568 100644 --- a/lib/src/phy/common/phy_common.c +++ b/lib/src/phy/common/phy_common.c @@ -365,7 +365,7 @@ int srsran_symbol_sz(uint32_t nof_prb) return 768; } else if (nof_prb <= 79) { return 1024; - } else if (nof_prb <= 106) { + } else if (nof_prb <= 110) { return 1536; } else { return SRSRAN_ERROR; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index e74763497..1e172839c 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1208,7 +1208,7 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ SRSENB_MAX_UES); // Check for a forced DL EARFCN or frequency (only valid for a single cell config (Xico's favorite feature)) - if (rrc_cfg_->cell_list.size() > 1) { + if (rrc_cfg_->cell_list.size() > 0) { if (rrc_cfg_->cell_list.size() == 1) { auto& cfg = rrc_cfg_->cell_list.at(0); if (args_->enb.dl_earfcn > 0 and args_->enb.dl_earfcn != cfg.dl_earfcn) { From 0ac3f8b2427f1d14226a7c6423e589abd8aca13b Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 4 Nov 2021 14:24:41 +0000 Subject: [PATCH 07/35] nr: fix ngap initialization in case of NR SA --- srsenb/src/stack/gnb_stack_nr.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index d325d4b5b..cbd145c58 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -77,7 +77,8 @@ int gnb_stack_nr::init(const gnb_stack_args_t& args_, ngap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit); gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit); - if (x2_ != nullptr) { + if (x2_ == nullptr) { + // SA mode ngap.reset(new srsenb::ngap(&task_sched, ngap_logger, &srsran::get_rx_io_manager())); gtpu.reset(new srsenb::gtpu(&task_sched, gtpu_logger, &srsran::get_rx_io_manager())); } From f93d428e490c17e2d74b014d2068f1ebd111d21c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 1 Oct 2021 16:52:29 +0100 Subject: [PATCH 08/35] Moved RLC AM data structures to their own file --- lib/include/srsran/rlc/rlc_am_data_structs.h | 217 +++++++++++++++++++ lib/include/srsran/rlc/rlc_am_lte.h | 196 +---------------- lib/include/srsran/rlc/rlc_common.h | 1 + lib/src/rlc/rlc_am_lte.cc | 14 -- 4 files changed, 224 insertions(+), 204 deletions(-) create mode 100644 lib/include/srsran/rlc/rlc_am_data_structs.h diff --git a/lib/include/srsran/rlc/rlc_am_data_structs.h b/lib/include/srsran/rlc/rlc_am_data_structs.h new file mode 100644 index 000000000..f7d0ad131 --- /dev/null +++ b/lib/include/srsran/rlc/rlc_am_data_structs.h @@ -0,0 +1,217 @@ +/** + * + * \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_RLC_AM_DATA_STRUCTS_H +#define SRSRAN_RLC_AM_DATA_STRUCTS_H + +#include "srsran/adt/circular_buffer.h" +#include "srsran/adt/circular_map.h" +#include "srsran/adt/intrusive_list.h" +#include +#include + +namespace srsran { + +class rlc_amd_tx_pdu; +class pdcp_pdu_info; + +/// Pool that manages the allocation of RLC AM PDU Segments to RLC PDUs and tracking of segments ACK state +struct rlc_am_pdu_segment_pool { + const static size_t MAX_POOL_SIZE = 16384; + using rlc_list_tag = default_intrusive_tag; + struct free_list_tag {}; + + /// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state + struct segment_resource : public intrusive_forward_list_element, + public intrusive_forward_list_element, + public intrusive_double_linked_list_element<> { + const static uint32_t invalid_rlc_sn = std::numeric_limits::max(); + const static uint32_t invalid_pdcp_sn = std::numeric_limits::max() - 1; // -1 for Status Report + + int id() const; + void release_pdcp_sn(); + void release_rlc_sn(); + uint32_t rlc_sn() const { return rlc_sn_; } + uint32_t pdcp_sn() const { return pdcp_sn_; } + bool empty() const { return rlc_sn_ == invalid_rlc_sn and pdcp_sn_ == invalid_pdcp_sn; } + + private: + friend struct rlc_am_pdu_segment_pool; + uint32_t rlc_sn_ = invalid_rlc_sn; + uint32_t pdcp_sn_ = invalid_pdcp_sn; + rlc_am_pdu_segment_pool* parent_pool = nullptr; + }; + + rlc_am_pdu_segment_pool(); + rlc_am_pdu_segment_pool(const rlc_am_pdu_segment_pool&) = delete; + rlc_am_pdu_segment_pool(rlc_am_pdu_segment_pool&&) = delete; + rlc_am_pdu_segment_pool& operator=(const rlc_am_pdu_segment_pool&) = delete; + rlc_am_pdu_segment_pool& operator=(rlc_am_pdu_segment_pool&&) = delete; + bool has_segments() const { return not free_list.empty(); } + bool make_segment(rlc_amd_tx_pdu& rlc_list, pdcp_pdu_info& pdcp_info); + +private: + intrusive_forward_list free_list; + std::array segments; +}; + +/// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state +using rlc_am_pdu_segment = rlc_am_pdu_segment_pool::segment_resource; + +/// Class that contains the parameters and state (e.g. unACKed segments) of a PDCP PDU +class pdcp_pdu_info +{ + using list_type = intrusive_double_linked_list; + + list_type list; // List of unACKed RLC PDUs that contain segments that belong to the PDCP PDU. + +public: + const static uint32_t status_report_sn = std::numeric_limits::max(); + const static uint32_t invalid_pdcp_sn = std::numeric_limits::max() - 1; + + using iterator = typename list_type::iterator; + using const_iterator = typename list_type::const_iterator; + + // Copy is forbidden to avoid multiple PDCP SN references to the same segment + pdcp_pdu_info() = default; + pdcp_pdu_info(pdcp_pdu_info&&) noexcept = default; + pdcp_pdu_info(const pdcp_pdu_info&) noexcept = delete; + pdcp_pdu_info& operator=(const pdcp_pdu_info&) noexcept = delete; + pdcp_pdu_info& operator=(pdcp_pdu_info&&) noexcept = default; + ~pdcp_pdu_info() { clear(); } + + uint32_t sn = invalid_pdcp_sn; + bool fully_txed = false; // Boolean indicating if the SDU is fully transmitted. + + bool fully_acked() const { return fully_txed and list.empty(); } + bool valid() const { return sn != invalid_pdcp_sn; } + + // Interface for list of unACKed RLC segments of the PDCP PDU + void add_segment(rlc_am_pdu_segment& segment) { list.push_front(&segment); } + void ack_segment(rlc_am_pdu_segment& segment); + void clear() + { + sn = invalid_pdcp_sn; + fully_txed = false; + while (not list.empty()) { + ack_segment(list.front()); + } + } + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } +}; + +template +struct rlc_ringbuffer_t { + T& add_pdu(size_t sn) + { + srsran_expect(not has_sn(sn), "The same SN=%zd should not be added twice", sn); + window.overwrite(sn, T(sn)); + return window[sn]; + } + void remove_pdu(size_t sn) + { + srsran_expect(has_sn(sn), "The removed SN=%zd is not in the window", sn); + window.erase(sn); + } + T& operator[](size_t sn) { return window[sn]; } + size_t size() const { return window.size(); } + bool empty() const { return window.empty(); } + void clear() { window.clear(); } + + bool has_sn(uint32_t sn) const { return window.contains(sn); } + + // Return the sum data bytes of all active PDUs (check PDU is non-null) + uint32_t get_buffered_bytes() + { + uint32_t buff_size = 0; + for (const auto& pdu : window) { + if (pdu.second.buf != nullptr) { + buff_size += pdu.second.buf->N_bytes; + } + } + return buff_size; + } + +private: + srsran::static_circular_map window; +}; + +struct buffered_pdcp_pdu_list { +public: + explicit buffered_pdcp_pdu_list() : buffered_pdus(buffered_pdcp_pdu_list::buffer_size) { clear(); } + + void clear() + { + count = 0; + for (pdcp_pdu_info& b : buffered_pdus) { + b.clear(); + } + } + + void add_pdcp_sdu(uint32_t sn) + { + srsran_expect(sn <= max_pdcp_sn or sn == status_report_sn, "Invalid PDCP SN=%d", sn); + srsran_assert(not has_pdcp_sn(sn), "Cannot re-add same PDCP SN twice"); + pdcp_pdu_info& pdu = get_pdu_(sn); + if (pdu.valid()) { + pdu.clear(); + count--; + } + pdu.sn = sn; + count++; + } + void clear_pdcp_sdu(uint32_t sn) + { + pdcp_pdu_info& pdu = get_pdu_(sn); + if (not pdu.valid()) { + return; + } + pdu.clear(); + count--; + } + + pdcp_pdu_info& operator[](uint32_t sn) + { + srsran_expect(has_pdcp_sn(sn), "Invalid access to non-existent PDCP SN=%d", sn); + return get_pdu_(sn); + } + bool has_pdcp_sn(uint32_t pdcp_sn) const + { + srsran_expect(pdcp_sn <= max_pdcp_sn or pdcp_sn == status_report_sn, "Invalid PDCP SN=%d", pdcp_sn); + return get_pdu_(pdcp_sn).sn == pdcp_sn; + } + uint32_t nof_sdus() const { return count; } + +private: + const static size_t max_pdcp_sn = 262143u; + const static size_t buffer_size = 4096u; + const static uint32_t status_report_sn = pdcp_pdu_info::status_report_sn; + + pdcp_pdu_info& get_pdu_(uint32_t sn) + { + return (sn == status_report_sn) ? status_report_pdu : buffered_pdus[static_cast(sn % buffer_size)]; + } + const pdcp_pdu_info& get_pdu_(uint32_t sn) const + { + return (sn == status_report_sn) ? status_report_pdu : buffered_pdus[static_cast(sn % buffer_size)]; + } + + // size equal to buffer_size + std::vector buffered_pdus; + pdcp_pdu_info status_report_pdu; + uint32_t count = 0; +}; + +} // namespace srsran + +#endif // SRSRAN_BEARER_MEM_POOL_H diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index 7c98771f9..a669b0cd7 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -16,13 +16,13 @@ #include "srsran/adt/accumulators.h" #include "srsran/adt/circular_array.h" #include "srsran/adt/circular_map.h" -#include "srsran/adt/intrusive_list.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" #include "srsran/common/task_scheduler.h" #include "srsran/common/timeout.h" #include "srsran/interfaces/pdcp_interface_types.h" #include "srsran/rlc/rlc_am_base.h" +#include "srsran/rlc/rlc_am_data_structs.h" #include "srsran/rlc/rlc_common.h" #include "srsran/support/srsran_assert.h" #include "srsran/upper/byte_buffer_queue.h" @@ -34,52 +34,6 @@ namespace srsran { #undef RLC_AM_BUFFER_DEBUG -class rlc_amd_tx_pdu; -class pdcp_pdu_info; - -/// Pool that manages the allocation of RLC AM PDU Segments to RLC PDUs and tracking of segments ACK state -struct rlc_am_pdu_segment_pool { - const static size_t MAX_POOL_SIZE = 16384; - using rlc_list_tag = default_intrusive_tag; - struct free_list_tag {}; - - /// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state - struct segment_resource : public intrusive_forward_list_element, - public intrusive_forward_list_element, - public intrusive_double_linked_list_element<> { - const static uint32_t invalid_rlc_sn = std::numeric_limits::max(); - const static uint32_t invalid_pdcp_sn = std::numeric_limits::max() - 1; // -1 for Status Report - - int id() const; - void release_pdcp_sn(); - void release_rlc_sn(); - uint32_t rlc_sn() const { return rlc_sn_; } - uint32_t pdcp_sn() const { return pdcp_sn_; } - bool empty() const { return rlc_sn_ == invalid_rlc_sn and pdcp_sn_ == invalid_pdcp_sn; } - - private: - friend struct rlc_am_pdu_segment_pool; - uint32_t rlc_sn_ = invalid_rlc_sn; - uint32_t pdcp_sn_ = invalid_pdcp_sn; - rlc_am_pdu_segment_pool* parent_pool = nullptr; - }; - - rlc_am_pdu_segment_pool(); - rlc_am_pdu_segment_pool(const rlc_am_pdu_segment_pool&) = delete; - rlc_am_pdu_segment_pool(rlc_am_pdu_segment_pool&&) = delete; - rlc_am_pdu_segment_pool& operator=(const rlc_am_pdu_segment_pool&) = delete; - rlc_am_pdu_segment_pool& operator=(rlc_am_pdu_segment_pool&&) = delete; - bool has_segments() const { return not free_list.empty(); } - bool make_segment(rlc_amd_tx_pdu& rlc_list, pdcp_pdu_info& pdcp_info); - -private: - intrusive_forward_list free_list; - std::array segments; -}; - -/// RLC AM PDU Segment, containing the PDCP SN and RLC SN it has been assigned to, and its current ACK state -using rlc_am_pdu_segment = rlc_am_pdu_segment_pool::segment_resource; - struct rlc_amd_rx_pdu { rlc_amd_pdu_header_t header; unique_byte_buffer_t buf; @@ -137,144 +91,6 @@ struct rlc_sn_info_t { bool is_acked; }; -/// Class that contains the parameters and state (e.g. unACKed segments) of a PDCP PDU -class pdcp_pdu_info -{ - using list_type = intrusive_double_linked_list; - - list_type list; // List of unACKed RLC PDUs that contain segments that belong to the PDCP PDU. - -public: - const static uint32_t status_report_sn = std::numeric_limits::max(); - const static uint32_t invalid_pdcp_sn = std::numeric_limits::max() - 1; - - using iterator = typename list_type::iterator; - using const_iterator = typename list_type::const_iterator; - - // Copy is forbidden to avoid multiple PDCP SN references to the same segment - pdcp_pdu_info() = default; - pdcp_pdu_info(pdcp_pdu_info&&) noexcept = default; - pdcp_pdu_info(const pdcp_pdu_info&) noexcept = delete; - pdcp_pdu_info& operator=(const pdcp_pdu_info&) noexcept = delete; - pdcp_pdu_info& operator=(pdcp_pdu_info&&) noexcept = default; - ~pdcp_pdu_info() { clear(); } - - uint32_t sn = invalid_pdcp_sn; - bool fully_txed = false; // Boolean indicating if the SDU is fully transmitted. - - bool fully_acked() const { return fully_txed and list.empty(); } - bool valid() const { return sn != invalid_pdcp_sn; } - - // Interface for list of unACKed RLC segments of the PDCP PDU - void add_segment(rlc_am_pdu_segment& segment) { list.push_front(&segment); } - void ack_segment(rlc_am_pdu_segment& segment); - void clear() - { - sn = invalid_pdcp_sn; - fully_txed = false; - while (not list.empty()) { - ack_segment(list.front()); - } - } - const_iterator begin() const { return list.begin(); } - const_iterator end() const { return list.end(); } -}; - -template -struct rlc_ringbuffer_t { - T& add_pdu(size_t sn) - { - srsran_expect(not has_sn(sn), "The same SN=%zd should not be added twice", sn); - window.overwrite(sn, T(sn)); - return window[sn]; - } - void remove_pdu(size_t sn) - { - srsran_expect(has_sn(sn), "The removed SN=%zd is not in the window", sn); - window.erase(sn); - } - T& operator[](size_t sn) { return window[sn]; } - size_t size() const { return window.size(); } - bool empty() const { return window.empty(); } - void clear() { window.clear(); } - - bool has_sn(uint32_t sn) const { return window.contains(sn); } - - // Return the sum data bytes of all active PDUs (check PDU is non-null) - uint32_t get_buffered_bytes() - { - uint32_t buff_size = 0; - for (const auto& pdu : window) { - if (pdu.second.buf != nullptr) { - buff_size += pdu.second.buf->N_bytes; - } - } - return buff_size; - } - -private: - srsran::static_circular_map window; -}; - -struct buffered_pdcp_pdu_list { -public: - explicit buffered_pdcp_pdu_list(); - void clear(); - - void add_pdcp_sdu(uint32_t sn) - { - srsran_expect(sn <= max_pdcp_sn or sn == status_report_sn, "Invalid PDCP SN=%d", sn); - srsran_assert(not has_pdcp_sn(sn), "Cannot re-add same PDCP SN twice"); - pdcp_pdu_info& pdu = get_pdu_(sn); - if (pdu.valid()) { - pdu.clear(); - count--; - } - pdu.sn = sn; - count++; - } - void clear_pdcp_sdu(uint32_t sn) - { - pdcp_pdu_info& pdu = get_pdu_(sn); - if (not pdu.valid()) { - return; - } - pdu.clear(); - count--; - } - - pdcp_pdu_info& operator[](uint32_t sn) - { - srsran_expect(has_pdcp_sn(sn), "Invalid access to non-existent PDCP SN=%d", sn); - return get_pdu_(sn); - } - bool has_pdcp_sn(uint32_t pdcp_sn) const - { - srsran_expect(pdcp_sn <= max_pdcp_sn or pdcp_sn == status_report_sn, "Invalid PDCP SN=%d", pdcp_sn); - return get_pdu_(pdcp_sn).sn == pdcp_sn; - } - uint32_t nof_sdus() const { return count; } - -private: - const static size_t max_pdcp_sn = 262143u; - const static size_t buffer_size = 4096u; - const static uint32_t status_report_sn = pdcp_pdu_info::status_report_sn; - - pdcp_pdu_info& get_pdu_(uint32_t sn) - { - return (sn == status_report_sn) ? status_report_pdu : buffered_pdus[static_cast(sn % buffer_size)]; - } - const pdcp_pdu_info& get_pdu_(uint32_t sn) const - { - return (sn == status_report_sn) ? status_report_pdu : buffered_pdus[static_cast(sn % buffer_size)]; - } - - // size equal to buffer_size - std::vector buffered_pdus; - pdcp_pdu_info status_report_pdu; - uint32_t count = 0; -}; - class pdu_retx_queue { public: @@ -458,9 +274,9 @@ private: bsr_callback_t bsr_callback; // Tx windows - rlc_ringbuffer_t tx_window; - pdu_retx_queue retx_queue; - pdcp_sn_vector_t notify_info_vec; + rlc_ringbuffer_t tx_window; + pdu_retx_queue retx_queue; + pdcp_sn_vector_t notify_info_vec; // Mutexes std::mutex mutex; @@ -532,8 +348,8 @@ private: std::mutex mutex; // Rx windows - rlc_ringbuffer_t rx_window; - std::map rx_segments; + rlc_ringbuffer_t rx_window; + std::map rx_segments; bool poll_received = false; std::atomic do_status = {false}; // light-weight access from Tx entity diff --git a/lib/include/srsran/rlc/rlc_common.h b/lib/include/srsran/rlc/rlc_common.h index c15c915ae..561fde19a 100644 --- a/lib/include/srsran/rlc/rlc_common.h +++ b/lib/include/srsran/rlc/rlc_common.h @@ -26,6 +26,7 @@ namespace srsran { * Ref: 3GPP TS 36.322 v10.0.0 ***************************************************************************/ +#define MOD 1024 #define RLC_AM_WINDOW_SIZE 512 #define RLC_MAX_SDU_SIZE ((1 << 11) - 1) // Length of LI field is 11bits #define RLC_AM_MIN_DATA_PDU_SIZE (3) // AMD PDU with 10 bit SN (length of LI field is 11 bits) (No LI) diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index e4006171c..5585d8d2d 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -17,7 +17,6 @@ #include "srsran/srslog/event_trace.h" #include -#define MOD 1024 #define RX_MOD_BASE(x) (((x)-vr_r) % 1024) #define TX_MOD_BASE(x) (((x)-vt_a) % 1024) #define LCID (parent->lcid) @@ -2260,19 +2259,6 @@ void rlc_am_lte::rlc_am_lte_rx::debug_state() logger.debug("%s vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d", RB_NAME, vr_r, vr_mr, vr_x, vr_ms, vr_h); } -buffered_pdcp_pdu_list::buffered_pdcp_pdu_list() : buffered_pdus(buffered_pdcp_pdu_list::buffer_size) -{ - clear(); -} - -void buffered_pdcp_pdu_list::clear() -{ - count = 0; - for (pdcp_pdu_info& b : buffered_pdus) { - b.clear(); - } -} - /**************************************************************************** * Header pack/unpack helper functions * Ref: 3GPP TS 36.322 v10.0.0 Section 6.2.1 From 2bb249bf090d482c688cb7df68f13c8be545dc8a Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Fri, 1 Oct 2021 11:38:33 +0100 Subject: [PATCH 09/35] Moved RLC AM LTE and NR packing functions to their own file. --- lib/include/srsran/rlc/rlc_am_lte.h | 83 +---- lib/include/srsran/rlc/rlc_am_lte_packing.h | 135 ++++++++ lib/include/srsran/rlc/rlc_am_nr.h | 37 +- lib/include/srsran/rlc/rlc_am_nr_packing.h | 75 +++++ lib/include/srsran/rlc/rlc_common.h | 21 -- lib/src/rlc/CMakeLists.txt | 4 +- lib/src/rlc/rlc_am_lte.cc | 355 +------------------- lib/src/rlc/rlc_am_lte_packing.cc | 339 +++++++++++++++++++ lib/src/rlc/rlc_am_nr.cc | 241 +------------ lib/src/rlc/rlc_am_nr_packing.cc | 250 ++++++++++++++ lib/test/rlc/rlc_am_nr_pdu_test.cc | 2 +- 11 files changed, 816 insertions(+), 726 deletions(-) create mode 100644 lib/include/srsran/rlc/rlc_am_lte_packing.h create mode 100644 lib/include/srsran/rlc/rlc_am_nr_packing.h create mode 100644 lib/src/rlc/rlc_am_lte_packing.cc create mode 100644 lib/src/rlc/rlc_am_nr_packing.cc diff --git a/lib/include/srsran/rlc/rlc_am_lte.h b/lib/include/srsran/rlc/rlc_am_lte.h index a669b0cd7..30263a1a7 100644 --- a/lib/include/srsran/rlc/rlc_am_lte.h +++ b/lib/include/srsran/rlc/rlc_am_lte.h @@ -23,6 +23,7 @@ #include "srsran/interfaces/pdcp_interface_types.h" #include "srsran/rlc/rlc_am_base.h" #include "srsran/rlc/rlc_am_data_structs.h" +#include "srsran/rlc/rlc_am_lte_packing.h" #include "srsran/rlc/rlc_common.h" #include "srsran/support/srsran_assert.h" #include "srsran/upper/byte_buffer_queue.h" @@ -34,63 +35,6 @@ namespace srsran { #undef RLC_AM_BUFFER_DEBUG -struct rlc_amd_rx_pdu { - rlc_amd_pdu_header_t header; - unique_byte_buffer_t buf; - uint32_t rlc_sn; - - rlc_amd_rx_pdu() = default; - explicit rlc_amd_rx_pdu(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {} -}; - -struct rlc_amd_rx_pdu_segments_t { - std::list segments; -}; - -/// Class that contains the parameters and state (e.g. segments) of a RLC PDU -class rlc_amd_tx_pdu -{ - using list_type = intrusive_forward_list; - const static uint32_t invalid_rlc_sn = std::numeric_limits::max(); - - list_type list; - -public: - using iterator = typename list_type::iterator; - using const_iterator = typename list_type::const_iterator; - - const uint32_t rlc_sn = invalid_rlc_sn; - uint32_t retx_count = 0; - rlc_amd_pdu_header_t header; - unique_byte_buffer_t buf; - - explicit rlc_amd_tx_pdu(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {} - rlc_amd_tx_pdu(const rlc_amd_tx_pdu&) = delete; - rlc_amd_tx_pdu(rlc_amd_tx_pdu&& other) noexcept = default; - rlc_amd_tx_pdu& operator=(const rlc_amd_tx_pdu& other) = delete; - rlc_amd_tx_pdu& operator=(rlc_amd_tx_pdu&& other) = delete; - ~rlc_amd_tx_pdu(); - - // Segment List Interface - void add_segment(rlc_am_pdu_segment& segment) { list.push_front(&segment); } - const_iterator begin() const { return list.begin(); } - const_iterator end() const { return list.end(); } - iterator begin() { return list.begin(); } - iterator end() { return list.end(); } -}; - -struct rlc_amd_retx_t { - uint32_t sn; - bool is_segment; - uint32_t so_start; - uint32_t so_end; -}; - -struct rlc_sn_info_t { - uint32_t sn; - bool is_acked; -}; - class pdu_retx_queue { public: @@ -383,31 +327,6 @@ private: rlc_bearer_metrics_t metrics = {}; }; -/**************************************************************************** - * Header pack/unpack helper functions - * Ref: 3GPP TS 36.322 v10.0.0 Section 6.2.1 - ***************************************************************************/ -void rlc_am_read_data_pdu_header(byte_buffer_t* pdu, rlc_amd_pdu_header_t* header); -void rlc_am_read_data_pdu_header(uint8_t** payload, uint32_t* nof_bytes, rlc_amd_pdu_header_t* header); -void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, byte_buffer_t* pdu); -void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, uint8_t** payload); -void rlc_am_read_status_pdu(byte_buffer_t* pdu, rlc_status_pdu_t* status); -void rlc_am_read_status_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_status_pdu_t* status); -void rlc_am_write_status_pdu(rlc_status_pdu_t* status, byte_buffer_t* pdu); -int rlc_am_write_status_pdu(rlc_status_pdu_t* status, uint8_t* payload); - -uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t* header); -uint32_t rlc_am_packed_length(rlc_status_pdu_t* status); -uint32_t rlc_am_packed_length(rlc_amd_retx_t retx); -bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status, uint32_t rx_win_min = 0); -bool rlc_am_is_pdu_segment(uint8_t* payload); -std::string rlc_am_undelivered_sdu_info_to_string(const std::map& info_queue); -void log_rlc_amd_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_amd_pdu_header_t& header); -bool rlc_am_start_aligned(const uint8_t fi); -bool rlc_am_end_aligned(const uint8_t fi); -bool rlc_am_is_unaligned(const uint8_t fi); -bool rlc_am_not_start_aligned(const uint8_t fi); - } // namespace srsran #endif // SRSRAN_RLC_AM_LTE_H diff --git a/lib/include/srsran/rlc/rlc_am_lte_packing.h b/lib/include/srsran/rlc/rlc_am_lte_packing.h new file mode 100644 index 000000000..f4d2d5ea5 --- /dev/null +++ b/lib/include/srsran/rlc/rlc_am_lte_packing.h @@ -0,0 +1,135 @@ +/** + * + * \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_RLC_AM_LTE_PACKING_H +#define SRSRAN_RLC_AM_LTE_PACKING_H + +#include "srsran/common/string_helpers.h" +#include "srsran/rlc/rlc_am_base.h" +#include "srsran/rlc/rlc_am_data_structs.h" // required for rlc_am_pdu_segment +#include + +namespace srsran { + +/// Class that contains the parameters and state (e.g. segments) of a RLC PDU +class rlc_amd_tx_pdu +{ + using list_type = intrusive_forward_list; + const static uint32_t invalid_rlc_sn = std::numeric_limits::max(); + + list_type list; + +public: + using iterator = typename list_type::iterator; + using const_iterator = typename list_type::const_iterator; + + const uint32_t rlc_sn = invalid_rlc_sn; + uint32_t retx_count = 0; + rlc_amd_pdu_header_t header; + unique_byte_buffer_t buf; + + explicit rlc_amd_tx_pdu(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {} + rlc_amd_tx_pdu(const rlc_amd_tx_pdu&) = delete; + rlc_amd_tx_pdu(rlc_amd_tx_pdu&& other) noexcept = default; + rlc_amd_tx_pdu& operator=(const rlc_amd_tx_pdu& other) = delete; + rlc_amd_tx_pdu& operator=(rlc_amd_tx_pdu&& other) = delete; + ~rlc_amd_tx_pdu(); + + // Segment List Interface + void add_segment(rlc_am_pdu_segment& segment) { list.push_front(&segment); } + const_iterator begin() const { return list.begin(); } + const_iterator end() const { return list.end(); } + iterator begin() { return list.begin(); } + iterator end() { return list.end(); } +}; + +struct rlc_amd_retx_t { + uint32_t sn; + bool is_segment; + uint32_t so_start; + uint32_t so_end; +}; + +struct rlc_sn_info_t { + uint32_t sn; + bool is_acked; +}; + +struct rlc_amd_rx_pdu { + rlc_amd_pdu_header_t header; + unique_byte_buffer_t buf; + uint32_t rlc_sn; + + rlc_amd_rx_pdu() = default; + explicit rlc_amd_rx_pdu(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {} +}; + +struct rlc_amd_rx_pdu_segments_t { + std::list segments; +}; + +/**************************************************************************** + * Header pack/unpack helper functions + * Ref: 3GPP TS 36.322 v10.0.0 Section 6.2.1 + ***************************************************************************/ +void rlc_am_read_data_pdu_header(byte_buffer_t* pdu, rlc_amd_pdu_header_t* header); +void rlc_am_read_data_pdu_header(uint8_t** payload, uint32_t* nof_bytes, rlc_amd_pdu_header_t* header); +void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, byte_buffer_t* pdu); +void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, uint8_t** payload); +void rlc_am_read_status_pdu(byte_buffer_t* pdu, rlc_status_pdu_t* status); +void rlc_am_read_status_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_status_pdu_t* status); +void rlc_am_write_status_pdu(rlc_status_pdu_t* status, byte_buffer_t* pdu); +int rlc_am_write_status_pdu(rlc_status_pdu_t* status, uint8_t* payload); + +uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t* header); +uint32_t rlc_am_packed_length(rlc_status_pdu_t* status); +uint32_t rlc_am_packed_length(rlc_amd_retx_t retx); +bool rlc_am_is_pdu_segment(uint8_t* payload); +bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status, uint32_t rx_win_min = 0); +std::string rlc_am_undelivered_sdu_info_to_string(const std::map& info_queue); +void log_rlc_amd_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_amd_pdu_header_t& header); +bool rlc_am_start_aligned(const uint8_t fi); +bool rlc_am_end_aligned(const uint8_t fi); +bool rlc_am_is_unaligned(const uint8_t fi); +bool rlc_am_not_start_aligned(const uint8_t fi); + +/** + * Logs Status PDU into provided log channel, using fmt_str as format string + */ +template +void log_rlc_am_status_pdu_to_string(srslog::log_channel& log_ch, + const char* fmt_str, + rlc_status_pdu_t* status, + Args&&... args) +{ + if (not log_ch.enabled()) { + return; + } + fmt::memory_buffer buffer; + fmt::format_to(buffer, "ACK_SN = {}, N_nack = {}", status->ack_sn, status->N_nack); + if (status->N_nack > 0) { + fmt::format_to(buffer, ", NACK_SN = "); + for (uint32_t i = 0; i < status->N_nack; ++i) { + if (status->nacks[i].has_so) { + fmt::format_to( + buffer, "[{} {}:{}]", status->nacks[i].nack_sn, status->nacks[i].so_start, status->nacks[i].so_end); + } else { + fmt::format_to(buffer, "[{}]", status->nacks[i].nack_sn); + } + } + } + log_ch(fmt_str, std::forward(args)..., to_c_str(buffer)); +} + +} // namespace srsran + +#endif // SRSRAN_RLC_AM_NR_H diff --git a/lib/include/srsran/rlc/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h index c1ac15bf1..cd03e78cb 100644 --- a/lib/include/srsran/rlc/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -15,6 +15,7 @@ #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" +#include "srsran/common/timers.h" #include "srsran/rlc/rlc_am_base.h" #include "srsran/upper/byte_buffer_queue.h" #include @@ -24,41 +25,7 @@ namespace srsran { -typedef struct { - rlc_am_nr_pdu_header_t header; - unique_byte_buffer_t buf; -} rlc_amd_pdu_nr_t; - -///< add class here - -/**************************************************************************** - * Header pack/unpack helper functions for NR - * Ref: 3GPP TS 38.322 v15.3.0 Section 6.2.2.3 - ***************************************************************************/ -uint32_t rlc_am_nr_read_data_pdu_header(const byte_buffer_t* pdu, - const rlc_am_nr_sn_size_t sn_size, - rlc_am_nr_pdu_header_t* header); - -uint32_t rlc_am_nr_read_data_pdu_header(const uint8_t* payload, - const uint32_t nof_bytes, - const rlc_am_nr_sn_size_t sn_size, - rlc_am_nr_pdu_header_t* header); - -uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu); - -uint32_t rlc_am_nr_packed_length(const rlc_am_nr_pdu_header_t& header); - -uint32_t -rlc_am_nr_read_status_pdu(const byte_buffer_t* pdu, const rlc_am_nr_sn_size_t sn_size, rlc_am_nr_status_pdu_t* status); - -uint32_t rlc_am_nr_read_status_pdu(const uint8_t* payload, - const uint32_t nof_bytes, - const rlc_am_nr_sn_size_t sn_size, - rlc_am_nr_status_pdu_t* status); - -int32_t rlc_am_nr_write_status_pdu(const rlc_am_nr_status_pdu_t& status_pdu, - const rlc_am_nr_sn_size_t sn_size, - byte_buffer_t* pdu); +// TODO } // namespace srsran diff --git a/lib/include/srsran/rlc/rlc_am_nr_packing.h b/lib/include/srsran/rlc/rlc_am_nr_packing.h new file mode 100644 index 000000000..f31aa2c42 --- /dev/null +++ b/lib/include/srsran/rlc/rlc_am_nr_packing.h @@ -0,0 +1,75 @@ +/** + * + * \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_RLC_AM_NR_PACKING_H +#define SRSRAN_RLC_AM_NR_PACKING_H + +#include "srsran/rlc/rlc_am_base.h" + +namespace srsran { + +///< AM NR PDU header +typedef struct { + rlc_dc_field_t dc; ///< Data/Control (D/C) field + uint8_t p; ///< Polling bit + rlc_nr_si_field_t si; ///< Segmentation info + rlc_am_nr_sn_size_t sn_size; ///< Sequence number size (12 or 18 bits) + uint32_t sn; ///< Sequence number + uint16_t so; ///< Sequence offset +} rlc_am_nr_pdu_header_t; + +struct rlc_amd_pdu_nr_t { + rlc_am_nr_pdu_header_t header; + unique_byte_buffer_t buf; +}; + +///< AM NR Status PDU header (perhaps merge with LTE version) +typedef struct { + rlc_am_nr_control_pdu_type_t cpt; + uint32_t ack_sn; ///< SN of the next not received RLC Data PDU + uint16_t N_nack; ///< number of NACKs + uint8_t nack_range; ///< number of consecutively lost RLC SDUs starting from and including NACK_SN + rlc_status_nack_t nacks[RLC_AM_WINDOW_SIZE]; +} rlc_am_nr_status_pdu_t; + +/**************************************************************************** + * Header pack/unpack helper functions for NR + * Ref: 3GPP TS 38.322 v15.3.0 Section 6.2.2.3 + ***************************************************************************/ +uint32_t rlc_am_nr_read_data_pdu_header(const byte_buffer_t* pdu, + const rlc_am_nr_sn_size_t sn_size, + rlc_am_nr_pdu_header_t* header); + +uint32_t rlc_am_nr_read_data_pdu_header(const uint8_t* payload, + const uint32_t nof_bytes, + const rlc_am_nr_sn_size_t sn_size, + rlc_am_nr_pdu_header_t* header); + +uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu); + +uint32_t rlc_am_nr_packed_length(const rlc_am_nr_pdu_header_t& header); + +uint32_t +rlc_am_nr_read_status_pdu(const byte_buffer_t* pdu, const rlc_am_nr_sn_size_t sn_size, rlc_am_nr_status_pdu_t* status); + +uint32_t rlc_am_nr_read_status_pdu(const uint8_t* payload, + const uint32_t nof_bytes, + const rlc_am_nr_sn_size_t sn_size, + rlc_am_nr_status_pdu_t* status); + +int32_t rlc_am_nr_write_status_pdu(const rlc_am_nr_status_pdu_t& status_pdu, + const rlc_am_nr_sn_size_t sn_size, + byte_buffer_t* pdu); + +} // namespace srsran + +#endif // SRSRAN_RLC_AM_NR_H diff --git a/lib/include/srsran/rlc/rlc_common.h b/lib/include/srsran/rlc/rlc_common.h index 561fde19a..bb5848e2c 100644 --- a/lib/include/srsran/rlc/rlc_common.h +++ b/lib/include/srsran/rlc/rlc_common.h @@ -176,27 +176,6 @@ struct rlc_status_pdu_t { } }; -/** RLC AM NR structs */ - -///< AM NR PDU header -typedef struct { - rlc_dc_field_t dc; ///< Data/Control (D/C) field - uint8_t p; ///< Polling bit - rlc_nr_si_field_t si; ///< Segmentation info - rlc_am_nr_sn_size_t sn_size; ///< Sequence number size (12 or 18 bits) - uint32_t sn; ///< Sequence number - uint16_t so; ///< Sequence offset -} rlc_am_nr_pdu_header_t; - -///< AM NR Status PDU header (perhaps merge with LTE version) -typedef struct { - rlc_am_nr_control_pdu_type_t cpt; - uint32_t ack_sn; ///< SN of the next not received RLC Data PDU - uint16_t N_nack; ///< number of NACKs - uint8_t nack_range; ///< number of consecutively lost RLC SDUs starting from and including NACK_SN - rlc_status_nack_t nacks[RLC_AM_WINDOW_SIZE]; -} rlc_am_nr_status_pdu_t; - typedef std::function bsr_callback_t; /**************************************************************************** diff --git a/lib/src/rlc/CMakeLists.txt b/lib/src/rlc/CMakeLists.txt index ed6e085fe..89b44fba6 100644 --- a/lib/src/rlc/CMakeLists.txt +++ b/lib/src/rlc/CMakeLists.txt @@ -10,10 +10,12 @@ set(SOURCES rlc.cc rlc_tm.cc rlc_um_base.cc rlc_um_lte.cc + rlc_um_nr.cc rlc_am_base.cc rlc_am_lte.cc - rlc_um_nr.cc rlc_am_nr.cc + rlc_am_lte_packing.cc + rlc_am_nr_packing.cc bearer_mem_pool.cc) add_library(srsran_rlc STATIC ${SOURCES}) diff --git a/lib/src/rlc/rlc_am_lte.cc b/lib/src/rlc/rlc_am_lte.cc index 5585d8d2d..add79c851 100644 --- a/lib/src/rlc/rlc_am_lte.cc +++ b/lib/src/rlc/rlc_am_lte.cc @@ -11,9 +11,9 @@ */ #include "srsran/rlc/rlc_am_lte.h" -#include "srsran/common/string_helpers.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/rlc/rlc_am_lte_packing.h" #include "srsran/srslog/event_trace.h" #include @@ -25,38 +25,6 @@ namespace srsran { -/******************************* - * Helper methods - ******************************/ - -/** - * Logs Status PDU into provided log channel, using fmt_str as format string - */ -template -void log_rlc_am_status_pdu_to_string(srslog::log_channel& log_ch, - const char* fmt_str, - rlc_status_pdu_t* status, - Args&&... args) -{ - if (not log_ch.enabled()) { - return; - } - fmt::memory_buffer buffer; - fmt::format_to(buffer, "ACK_SN = {}, N_nack = {}", status->ack_sn, status->N_nack); - if (status->N_nack > 0) { - fmt::format_to(buffer, ", NACK_SN = "); - for (uint32_t i = 0; i < status->N_nack; ++i) { - if (status->nacks[i].has_so) { - fmt::format_to( - buffer, "[{} {}:{}]", status->nacks[i].nack_sn, status->nacks[i].so_start, status->nacks[i].so_end); - } else { - fmt::format_to(buffer, "[{}]", status->nacks[i].nack_sn); - } - } - } - log_ch(fmt_str, std::forward(args)..., to_c_str(buffer)); -} - /******************************* * RLC AM Segments ******************************/ @@ -2259,325 +2227,4 @@ void rlc_am_lte::rlc_am_lte_rx::debug_state() logger.debug("%s vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d", RB_NAME, vr_r, vr_mr, vr_x, vr_ms, vr_h); } -/**************************************************************************** - * Header pack/unpack helper functions - * Ref: 3GPP TS 36.322 v10.0.0 Section 6.2.1 - ***************************************************************************/ - -// Read header from pdu struct, don't strip header -void rlc_am_read_data_pdu_header(byte_buffer_t* pdu, rlc_amd_pdu_header_t* header) -{ - uint8_t* ptr = pdu->msg; - uint32_t n = 0; - rlc_am_read_data_pdu_header(&ptr, &n, header); -} - -// Read header from raw pointer, strip header -void rlc_am_read_data_pdu_header(uint8_t** payload, uint32_t* nof_bytes, rlc_amd_pdu_header_t* header) -{ - uint8_t ext; - uint8_t* ptr = *payload; - - header->dc = static_cast((*ptr >> 7) & 0x01); - - if (RLC_DC_FIELD_DATA_PDU == header->dc) { - // Fixed part - header->rf = ((*ptr >> 6) & 0x01); - header->p = ((*ptr >> 5) & 0x01); - header->fi = static_cast((*ptr >> 3) & 0x03); - ext = ((*ptr >> 2) & 0x01); - header->sn = (*ptr & 0x03) << 8; // 2 bits SN - ptr++; - header->sn |= (*ptr & 0xFF); // 8 bits SN - ptr++; - - if (header->rf) { - header->lsf = ((*ptr >> 7) & 0x01); - header->so = (*ptr & 0x7F) << 8; // 7 bits of SO - ptr++; - header->so |= (*ptr & 0xFF); // 8 bits of SO - ptr++; - } - - // Extension part - header->N_li = 0; - while (ext) { - if (header->N_li % 2 == 0) { - ext = ((*ptr >> 7) & 0x01); - header->li[header->N_li] = (*ptr & 0x7F) << 4; // 7 bits of LI - ptr++; - header->li[header->N_li] |= (*ptr & 0xF0) >> 4; // 4 bits of LI - header->N_li++; - } else { - ext = (*ptr >> 3) & 0x01; - header->li[header->N_li] = (*ptr & 0x07) << 8; // 3 bits of LI - ptr++; - header->li[header->N_li] |= (*ptr & 0xFF); // 8 bits of LI - header->N_li++; - ptr++; - } - } - - // Account for padding if N_li is odd - if (header->N_li % 2 == 1) { - ptr++; - } - - *nof_bytes -= ptr - *payload; - *payload = ptr; - } -} - -// Write header to pdu struct -void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, byte_buffer_t* pdu) -{ - uint8_t* ptr = pdu->msg; - rlc_am_write_data_pdu_header(header, &ptr); - pdu->N_bytes += ptr - pdu->msg; -} - -// Write header to pointer & move pointer -void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, uint8_t** payload) -{ - uint32_t i; - uint8_t ext = (header->N_li > 0) ? 1 : 0; - - uint8_t* ptr = *payload; - - // Fixed part - *ptr = (header->dc & 0x01) << 7; - *ptr |= (header->rf & 0x01) << 6; - *ptr |= (header->p & 0x01) << 5; - *ptr |= (header->fi & 0x03) << 3; - *ptr |= (ext & 0x01) << 2; - - *ptr |= (header->sn & 0x300) >> 8; // 2 bits SN - ptr++; - *ptr = (header->sn & 0xFF); // 8 bits SN - ptr++; - - // Segment part - if (header->rf) { - *ptr = (header->lsf & 0x01) << 7; - *ptr |= (header->so & 0x7F00) >> 8; // 7 bits of SO - ptr++; - *ptr = (header->so & 0x00FF); // 8 bits of SO - ptr++; - } - - // Extension part - i = 0; - while (i < header->N_li) { - ext = ((i + 1) == header->N_li) ? 0 : 1; - *ptr = (ext & 0x01) << 7; // 1 bit header - *ptr |= (header->li[i] & 0x7F0) >> 4; // 7 bits of LI - ptr++; - *ptr = (header->li[i] & 0x00F) << 4; // 4 bits of LI - i++; - if (i < header->N_li) { - ext = ((i + 1) == header->N_li) ? 0 : 1; - *ptr |= (ext & 0x01) << 3; // 1 bit header - *ptr |= (header->li[i] & 0x700) >> 8; // 3 bits of LI - ptr++; - *ptr = (header->li[i] & 0x0FF); // 8 bits of LI - ptr++; - i++; - } - } - // Pad if N_li is odd - if (header->N_li % 2 == 1) { - ptr++; - } - - *payload = ptr; -} - -void rlc_am_read_status_pdu(byte_buffer_t* pdu, rlc_status_pdu_t* status) -{ - rlc_am_read_status_pdu(pdu->msg, pdu->N_bytes, status); -} - -void rlc_am_read_status_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_status_pdu_t* status) -{ - uint32_t i; - uint8_t ext1, ext2; - bit_buffer_t tmp; - uint8_t* ptr = tmp.msg; - - srsran_bit_unpack_vector(payload, tmp.msg, nof_bytes * 8); - tmp.N_bits = nof_bytes * 8; - - rlc_dc_field_t dc = static_cast(srsran_bit_pack(&ptr, 1)); - - if (RLC_DC_FIELD_CONTROL_PDU == dc) { - uint8_t cpt = srsran_bit_pack(&ptr, 3); // 3-bit Control PDU Type (0 == status) - if (0 == cpt) { - status->ack_sn = srsran_bit_pack(&ptr, 10); // 10 bits ACK_SN - ext1 = srsran_bit_pack(&ptr, 1); // 1 bits E1 - status->N_nack = 0; - while (ext1) { - status->nacks[status->N_nack].nack_sn = srsran_bit_pack(&ptr, 10); - ext1 = srsran_bit_pack(&ptr, 1); // 1 bits E1 - ext2 = srsran_bit_pack(&ptr, 1); // 1 bits E2 - if (ext2) { - status->nacks[status->N_nack].has_so = true; - status->nacks[status->N_nack].so_start = srsran_bit_pack(&ptr, 15); - status->nacks[status->N_nack].so_end = srsran_bit_pack(&ptr, 15); - } - status->N_nack++; - } - } - } -} - -void rlc_am_write_status_pdu(rlc_status_pdu_t* status, byte_buffer_t* pdu) -{ - pdu->N_bytes = rlc_am_write_status_pdu(status, pdu->msg); -} - -int rlc_am_write_status_pdu(rlc_status_pdu_t* status, uint8_t* payload) -{ - uint32_t i; - uint8_t ext1; - bit_buffer_t tmp; - uint8_t* ptr = tmp.msg; - - srsran_bit_unpack(RLC_DC_FIELD_CONTROL_PDU, &ptr, 1); // D/C - srsran_bit_unpack(0, &ptr, 3); // CPT (0 == STATUS) - srsran_bit_unpack(status->ack_sn, &ptr, 10); // 10 bit ACK_SN - ext1 = (status->N_nack == 0) ? 0 : 1; - srsran_bit_unpack(ext1, &ptr, 1); // E1 - for (i = 0; i < status->N_nack; i++) { - srsran_bit_unpack(status->nacks[i].nack_sn, &ptr, 10); // 10 bit NACK_SN - ext1 = ((status->N_nack - 1) == i) ? 0 : 1; - srsran_bit_unpack(ext1, &ptr, 1); // E1 - if (status->nacks[i].has_so) { - srsran_bit_unpack(1, &ptr, 1); // E2 - srsran_bit_unpack(status->nacks[i].so_start, &ptr, 15); - srsran_bit_unpack(status->nacks[i].so_end, &ptr, 15); - } else { - srsran_bit_unpack(0, &ptr, 1); // E2 - } - } - - // Pad - tmp.N_bits = ptr - tmp.msg; - uint8_t n_pad = 8 - (tmp.N_bits % 8); - srsran_bit_unpack(0, &ptr, n_pad); - tmp.N_bits = ptr - tmp.msg; - - // Pack bits - srsran_bit_pack_vector(tmp.msg, payload, tmp.N_bits); - return tmp.N_bits / 8; -} - -bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status, uint32_t rx_win_min) -{ - // check if ACK_SN is inside Rx window - if ((MOD + status.ack_sn - rx_win_min) % MOD > RLC_AM_WINDOW_SIZE) { - return false; - } - - for (uint32_t i = 0; i < status.N_nack; ++i) { - // NACK can't be larger than ACK - if ((MOD + status.ack_sn - status.nacks[i].nack_sn) % MOD > RLC_AM_WINDOW_SIZE) { - return false; - } - // Don't NACK the ACK SN - if (status.nacks[i].nack_sn == status.ack_sn) { - return false; - } - } - return true; -} - -uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t* header) -{ - uint32_t len = 2; // Fixed part is 2 bytes - if (header->rf) { - len += 2; // Segment header is 2 bytes - } - len += header->N_li * 1.5 + 0.5; // Extension part - integer rounding up - return len; -} - -uint32_t rlc_am_packed_length(rlc_status_pdu_t* status) -{ - uint32_t len_bits = 15; // Fixed part is 15 bits - for (uint32_t i = 0; i < status->N_nack; i++) { - if (status->nacks[i].has_so) { - len_bits += 42; // 10 bits SN, 2 bits ext, 15 bits so_start, 15 bits so_end - } else { - len_bits += 12; // 10 bits SN, 2 bits ext - } - } - - return (len_bits + 7) / 8; // Convert to bytes - integer rounding up -} - -bool rlc_am_is_pdu_segment(uint8_t* payload) -{ - return ((*(payload) >> 6) & 0x01) == 1; -} - -void rlc_am_undelivered_sdu_info_to_string(fmt::memory_buffer& buffer, const std::vector& info_queue) -{ - fmt::format_to(buffer, "\n"); - for (const auto& pdcp_pdu : info_queue) { - fmt::format_to(buffer, "\tPDCP_SN = {}, undelivered RLC SNs = [", pdcp_pdu.sn); - for (const auto& nacked_segment : pdcp_pdu) { - fmt::format_to(buffer, "{} ", nacked_segment.rlc_sn()); - } - fmt::format_to(buffer, "]\n"); - } -} - -void log_rlc_amd_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_amd_pdu_header_t& header) -{ - if (not log_ch.enabled()) { - return; - } - fmt::memory_buffer buffer; - fmt::format_to(buffer, - "[{}, RF={}, P={}, FI={}, SN={}, LSF={}, SO={}, N_li={}", - rlc_dc_field_text[header.dc], - (header.rf ? "1" : "0"), - (header.p ? "1" : "0"), - (header.fi ? "1" : "0"), - header.sn, - (header.lsf ? "1" : "0"), - header.so, - header.N_li); - if (header.N_li > 0) { - fmt::format_to(buffer, " ({}", header.li[0]); - for (uint32_t i = 1; i < header.N_li; ++i) { - fmt::format_to(buffer, ", {}", header.li[i]); - } - fmt::format_to(buffer, ")"); - } - fmt::format_to(buffer, "]"); - - log_ch("%s", to_c_str(buffer)); -} - -bool rlc_am_start_aligned(const uint8_t fi) -{ - return (fi == RLC_FI_FIELD_START_AND_END_ALIGNED || fi == RLC_FI_FIELD_NOT_END_ALIGNED); -} - -bool rlc_am_end_aligned(const uint8_t fi) -{ - return (fi == RLC_FI_FIELD_START_AND_END_ALIGNED || fi == RLC_FI_FIELD_NOT_START_ALIGNED); -} - -bool rlc_am_is_unaligned(const uint8_t fi) -{ - return (fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED); -} - -bool rlc_am_not_start_aligned(const uint8_t fi) -{ - return (fi == RLC_FI_FIELD_NOT_START_ALIGNED || fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED); -} - } // namespace srsran diff --git a/lib/src/rlc/rlc_am_lte_packing.cc b/lib/src/rlc/rlc_am_lte_packing.cc new file mode 100644 index 000000000..02643f3fc --- /dev/null +++ b/lib/src/rlc/rlc_am_lte_packing.cc @@ -0,0 +1,339 @@ +/** + * + * \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/rlc/rlc_am_lte_packing.h" +#include + +namespace srsran { + +/**************************************************************************** + * Header pack/unpack helper functions + * Ref: 3GPP TS 36.322 v10.0.0 Section 6.2.1 + ***************************************************************************/ + +// Read header from pdu struct, don't strip header +void rlc_am_read_data_pdu_header(byte_buffer_t* pdu, rlc_amd_pdu_header_t* header) +{ + uint8_t* ptr = pdu->msg; + uint32_t n = 0; + rlc_am_read_data_pdu_header(&ptr, &n, header); +} + +// Read header from raw pointer, strip header +void rlc_am_read_data_pdu_header(uint8_t** payload, uint32_t* nof_bytes, rlc_amd_pdu_header_t* header) +{ + uint8_t ext; + uint8_t* ptr = *payload; + + header->dc = static_cast((*ptr >> 7) & 0x01); + + if (RLC_DC_FIELD_DATA_PDU == header->dc) { + // Fixed part + header->rf = ((*ptr >> 6) & 0x01); + header->p = ((*ptr >> 5) & 0x01); + header->fi = static_cast((*ptr >> 3) & 0x03); + ext = ((*ptr >> 2) & 0x01); + header->sn = (*ptr & 0x03) << 8; // 2 bits SN + ptr++; + header->sn |= (*ptr & 0xFF); // 8 bits SN + ptr++; + + if (header->rf) { + header->lsf = ((*ptr >> 7) & 0x01); + header->so = (*ptr & 0x7F) << 8; // 7 bits of SO + ptr++; + header->so |= (*ptr & 0xFF); // 8 bits of SO + ptr++; + } + + // Extension part + header->N_li = 0; + while (ext) { + if (header->N_li % 2 == 0) { + ext = ((*ptr >> 7) & 0x01); + header->li[header->N_li] = (*ptr & 0x7F) << 4; // 7 bits of LI + ptr++; + header->li[header->N_li] |= (*ptr & 0xF0) >> 4; // 4 bits of LI + header->N_li++; + } else { + ext = (*ptr >> 3) & 0x01; + header->li[header->N_li] = (*ptr & 0x07) << 8; // 3 bits of LI + ptr++; + header->li[header->N_li] |= (*ptr & 0xFF); // 8 bits of LI + header->N_li++; + ptr++; + } + } + + // Account for padding if N_li is odd + if (header->N_li % 2 == 1) { + ptr++; + } + + *nof_bytes -= ptr - *payload; + *payload = ptr; + } +} + +// Write header to pdu struct +void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, byte_buffer_t* pdu) +{ + uint8_t* ptr = pdu->msg; + rlc_am_write_data_pdu_header(header, &ptr); + pdu->N_bytes += ptr - pdu->msg; +} + +// Write header to pointer & move pointer +void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t* header, uint8_t** payload) +{ + uint32_t i; + uint8_t ext = (header->N_li > 0) ? 1 : 0; + + uint8_t* ptr = *payload; + + // Fixed part + *ptr = (header->dc & 0x01) << 7; + *ptr |= (header->rf & 0x01) << 6; + *ptr |= (header->p & 0x01) << 5; + *ptr |= (header->fi & 0x03) << 3; + *ptr |= (ext & 0x01) << 2; + + *ptr |= (header->sn & 0x300) >> 8; // 2 bits SN + ptr++; + *ptr = (header->sn & 0xFF); // 8 bits SN + ptr++; + + // Segment part + if (header->rf) { + *ptr = (header->lsf & 0x01) << 7; + *ptr |= (header->so & 0x7F00) >> 8; // 7 bits of SO + ptr++; + *ptr = (header->so & 0x00FF); // 8 bits of SO + ptr++; + } + + // Extension part + i = 0; + while (i < header->N_li) { + ext = ((i + 1) == header->N_li) ? 0 : 1; + *ptr = (ext & 0x01) << 7; // 1 bit header + *ptr |= (header->li[i] & 0x7F0) >> 4; // 7 bits of LI + ptr++; + *ptr = (header->li[i] & 0x00F) << 4; // 4 bits of LI + i++; + if (i < header->N_li) { + ext = ((i + 1) == header->N_li) ? 0 : 1; + *ptr |= (ext & 0x01) << 3; // 1 bit header + *ptr |= (header->li[i] & 0x700) >> 8; // 3 bits of LI + ptr++; + *ptr = (header->li[i] & 0x0FF); // 8 bits of LI + ptr++; + i++; + } + } + // Pad if N_li is odd + if (header->N_li % 2 == 1) { + ptr++; + } + + *payload = ptr; +} + +void rlc_am_read_status_pdu(byte_buffer_t* pdu, rlc_status_pdu_t* status) +{ + rlc_am_read_status_pdu(pdu->msg, pdu->N_bytes, status); +} + +void rlc_am_read_status_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_status_pdu_t* status) +{ + uint32_t i; + uint8_t ext1, ext2; + bit_buffer_t tmp; + uint8_t* ptr = tmp.msg; + + srsran_bit_unpack_vector(payload, tmp.msg, nof_bytes * 8); + tmp.N_bits = nof_bytes * 8; + + rlc_dc_field_t dc = static_cast(srsran_bit_pack(&ptr, 1)); + + if (RLC_DC_FIELD_CONTROL_PDU == dc) { + uint8_t cpt = srsran_bit_pack(&ptr, 3); // 3-bit Control PDU Type (0 == status) + if (0 == cpt) { + status->ack_sn = srsran_bit_pack(&ptr, 10); // 10 bits ACK_SN + ext1 = srsran_bit_pack(&ptr, 1); // 1 bits E1 + status->N_nack = 0; + while (ext1) { + status->nacks[status->N_nack].nack_sn = srsran_bit_pack(&ptr, 10); + ext1 = srsran_bit_pack(&ptr, 1); // 1 bits E1 + ext2 = srsran_bit_pack(&ptr, 1); // 1 bits E2 + if (ext2) { + status->nacks[status->N_nack].has_so = true; + status->nacks[status->N_nack].so_start = srsran_bit_pack(&ptr, 15); + status->nacks[status->N_nack].so_end = srsran_bit_pack(&ptr, 15); + } + status->N_nack++; + } + } + } +} + +void rlc_am_write_status_pdu(rlc_status_pdu_t* status, byte_buffer_t* pdu) +{ + pdu->N_bytes = rlc_am_write_status_pdu(status, pdu->msg); +} + +int rlc_am_write_status_pdu(rlc_status_pdu_t* status, uint8_t* payload) +{ + uint32_t i; + uint8_t ext1; + bit_buffer_t tmp; + uint8_t* ptr = tmp.msg; + + srsran_bit_unpack(RLC_DC_FIELD_CONTROL_PDU, &ptr, 1); // D/C + srsran_bit_unpack(0, &ptr, 3); // CPT (0 == STATUS) + srsran_bit_unpack(status->ack_sn, &ptr, 10); // 10 bit ACK_SN + ext1 = (status->N_nack == 0) ? 0 : 1; + srsran_bit_unpack(ext1, &ptr, 1); // E1 + for (i = 0; i < status->N_nack; i++) { + srsran_bit_unpack(status->nacks[i].nack_sn, &ptr, 10); // 10 bit NACK_SN + ext1 = ((status->N_nack - 1) == i) ? 0 : 1; + srsran_bit_unpack(ext1, &ptr, 1); // E1 + if (status->nacks[i].has_so) { + srsran_bit_unpack(1, &ptr, 1); // E2 + srsran_bit_unpack(status->nacks[i].so_start, &ptr, 15); + srsran_bit_unpack(status->nacks[i].so_end, &ptr, 15); + } else { + srsran_bit_unpack(0, &ptr, 1); // E2 + } + } + + // Pad + tmp.N_bits = ptr - tmp.msg; + uint8_t n_pad = 8 - (tmp.N_bits % 8); + srsran_bit_unpack(0, &ptr, n_pad); + tmp.N_bits = ptr - tmp.msg; + + // Pack bits + srsran_bit_pack_vector(tmp.msg, payload, tmp.N_bits); + return tmp.N_bits / 8; +} + +uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t* header) +{ + uint32_t len = 2; // Fixed part is 2 bytes + if (header->rf) { + len += 2; // Segment header is 2 bytes + } + len += header->N_li * 1.5 + 0.5; // Extension part - integer rounding up + return len; +} + +uint32_t rlc_am_packed_length(rlc_status_pdu_t* status) +{ + uint32_t len_bits = 15; // Fixed part is 15 bits + for (uint32_t i = 0; i < status->N_nack; i++) { + if (status->nacks[i].has_so) { + len_bits += 42; // 10 bits SN, 2 bits ext, 15 bits so_start, 15 bits so_end + } else { + len_bits += 12; // 10 bits SN, 2 bits ext + } + } + + return (len_bits + 7) / 8; // Convert to bytes - integer rounding up +} + +bool rlc_am_is_pdu_segment(uint8_t* payload) +{ + return ((*(payload) >> 6) & 0x01) == 1; +} + +bool rlc_am_is_valid_status_pdu(const rlc_status_pdu_t& status, uint32_t rx_win_min) +{ + // check if ACK_SN is inside Rx window + if ((MOD + status.ack_sn - rx_win_min) % MOD > RLC_AM_WINDOW_SIZE) { + return false; + } + + for (uint32_t i = 0; i < status.N_nack; ++i) { + // NACK can't be larger than ACK + if ((MOD + status.ack_sn - status.nacks[i].nack_sn) % MOD > RLC_AM_WINDOW_SIZE) { + return false; + } + // Don't NACK the ACK SN + if (status.nacks[i].nack_sn == status.ack_sn) { + return false; + } + } + return true; +} + +void rlc_am_undelivered_sdu_info_to_string(fmt::memory_buffer& buffer, const std::vector& info_queue) +{ + fmt::format_to(buffer, "\n"); + for (const auto& pdcp_pdu : info_queue) { + fmt::format_to(buffer, "\tPDCP_SN = {}, undelivered RLC SNs = [", pdcp_pdu.sn); + for (const auto& nacked_segment : pdcp_pdu) { + fmt::format_to(buffer, "{} ", nacked_segment.rlc_sn()); + } + fmt::format_to(buffer, "]\n"); + } +} + +bool rlc_am_start_aligned(const uint8_t fi) +{ + return (fi == RLC_FI_FIELD_START_AND_END_ALIGNED || fi == RLC_FI_FIELD_NOT_END_ALIGNED); +} + +bool rlc_am_end_aligned(const uint8_t fi) +{ + return (fi == RLC_FI_FIELD_START_AND_END_ALIGNED || fi == RLC_FI_FIELD_NOT_START_ALIGNED); +} + +bool rlc_am_is_unaligned(const uint8_t fi) +{ + return (fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED); +} + +bool rlc_am_not_start_aligned(const uint8_t fi) +{ + return (fi == RLC_FI_FIELD_NOT_START_ALIGNED || fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED); +} + +void log_rlc_amd_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_amd_pdu_header_t& header) +{ + if (not log_ch.enabled()) { + return; + } + fmt::memory_buffer buffer; + fmt::format_to(buffer, + "[{}, RF={}, P={}, FI={}, SN={}, LSF={}, SO={}, N_li={}", + rlc_dc_field_text[header.dc], + (header.rf ? "1" : "0"), + (header.p ? "1" : "0"), + (header.fi ? "1" : "0"), + header.sn, + (header.lsf ? "1" : "0"), + header.so, + header.N_li); + if (header.N_li > 0) { + fmt::format_to(buffer, " ({}", header.li[0]); + for (uint32_t i = 1; i < header.N_li; ++i) { + fmt::format_to(buffer, ", {}", header.li[i]); + } + fmt::format_to(buffer, ")"); + } + fmt::format_to(buffer, "]"); + + log_ch("%s", to_c_str(buffer)); +} + +} // namespace srsran diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index 1dedca3c8..cef2d1935 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -11,240 +11,17 @@ */ #include "srsran/rlc/rlc_am_nr.h" -#include +#include "srsran/common/string_helpers.h" +#include "srsran/interfaces/ue_pdcp_interfaces.h" +#include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/srslog/event_trace.h" +#include namespace srsran { -/**************************************************************************** - * Header pack/unpack helper functions - * Ref: 3GPP TS 38.322 v15.3.0 Section 6.2.2.4 - ***************************************************************************/ - -uint32_t rlc_am_nr_read_data_pdu_header(const byte_buffer_t* pdu, - const rlc_am_nr_sn_size_t sn_size, - rlc_am_nr_pdu_header_t* header) -{ - return rlc_am_nr_read_data_pdu_header(pdu->msg, pdu->N_bytes, sn_size, header); -} - -uint32_t rlc_am_nr_read_data_pdu_header(const uint8_t* payload, - const uint32_t nof_bytes, - const rlc_am_nr_sn_size_t sn_size, - rlc_am_nr_pdu_header_t* header) -{ - uint8_t* ptr = const_cast(payload); - - header->sn_size = sn_size; - - // Fixed part - header->dc = (rlc_dc_field_t)((*ptr >> 7) & 0x01); // 1 bit D/C field - header->p = (*ptr >> 6) & 0x01; // 1 bit P flag - header->si = (rlc_nr_si_field_t)((*ptr >> 4) & 0x03); // 2 bits SI - - if (sn_size == rlc_am_nr_sn_size_t::size12bits) { - header->sn = (*ptr & 0x0F) << 8; // first 4 bits SN - ptr++; - - header->sn |= (*ptr & 0xFF); // last 8 bits SN - ptr++; - } else if (sn_size == rlc_am_nr_sn_size_t::size18bits) { - // sanity check - if ((*ptr & 0x0c) != 0) { - fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); - return 0; - } - header->sn = (*ptr & 0x03) << 16; // first 4 bits SN - ptr++; - header->sn |= (*ptr & 0xFF) << 8; // bit 2-10 of SN - ptr++; - header->sn |= (*ptr & 0xFF); // last 8 bits SN - ptr++; - } else { - fprintf(stderr, "Unsupported SN length\n"); - return 0; - } - - // Read optional part - if (header->si == rlc_nr_si_field_t::last_segment || - header->si == rlc_nr_si_field_t::neither_first_nor_last_segment) { - // read SO - header->so = (*ptr & 0xFF) << 8; - ptr++; - header->so |= (*ptr & 0xFF); - ptr++; - } - - // return consumed bytes - return (ptr - payload); -} - -uint32_t rlc_am_nr_packed_length(const rlc_am_nr_pdu_header_t& header) -{ - uint32_t len = 0; - if (header.si == rlc_nr_si_field_t::full_sdu || header.si == rlc_nr_si_field_t::first_segment) { - len = 2; - if (header.sn_size == rlc_am_nr_sn_size_t::size18bits) { - len++; - } - } else { - // PDU contains SO - len = 4; - if (header.sn_size == rlc_am_nr_sn_size_t::size18bits) { - len++; - } - } - return len; -} - -uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu) -{ - // Make room for the header - uint32_t len = rlc_am_nr_packed_length(header); - pdu->msg -= len; - uint8_t* ptr = pdu->msg; - - // fixed header part - *ptr = (header.dc & 0x01) << 7; ///< 1 bit D/C field - *ptr |= (header.p & 0x01) << 6; ///< 1 bit P flag - *ptr |= (header.si & 0x03) << 4; ///< 2 bits SI - - if (header.sn_size == rlc_am_nr_sn_size_t::size12bits) { - // write first 4 bit of SN - *ptr |= (header.sn >> 8) & 0x0f; // 4 bit SN - ptr++; - *ptr = header.sn & 0xff; // remaining 8 bit of SN - ptr++; - } else { - // 18bit SN - *ptr |= (header.sn >> 16) & 0x3; // 2 bit SN - ptr++; - *ptr = header.sn >> 8; // bit 3 - 10 of SN - ptr++; - *ptr = (header.sn & 0xff); // remaining 8 bit of SN - ptr++; - } - - if (header.so) { - // write SO - *ptr = header.so >> 8; // first part of SO - ptr++; - *ptr = (header.so & 0xff); // second part of SO - ptr++; - } - - pdu->N_bytes += ptr - pdu->msg; - - return len; -} - -uint32_t -rlc_am_nr_read_status_pdu(const byte_buffer_t* pdu, const rlc_am_nr_sn_size_t sn_size, rlc_am_nr_status_pdu_t* status) -{ - return rlc_am_nr_read_status_pdu(pdu->msg, pdu->N_bytes, sn_size, status); -} - -uint32_t rlc_am_nr_read_status_pdu(const uint8_t* payload, - const uint32_t nof_bytes, - const rlc_am_nr_sn_size_t sn_size, - rlc_am_nr_status_pdu_t* status) -{ - uint8_t* ptr = const_cast(payload); - - // fixed part - status->cpt = (rlc_am_nr_control_pdu_type_t)((*ptr >> 4) & 0x07); // 3 bits CPT - - // sanity check - if (status->cpt != rlc_am_nr_control_pdu_type_t::status_pdu) { - fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); - return 0; - } - - if (sn_size == rlc_am_nr_sn_size_t::size12bits) { - status->ack_sn = (*ptr & 0x0F) << 8; // first 4 bits SN - ptr++; - - status->ack_sn |= (*ptr & 0xFF); // last 8 bits SN - ptr++; - - // read E1 flag - uint8_t e1 = *ptr & 0x80; - - // sanity check for reserved bits - if ((*ptr & 0x7f) != 0) { - fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); - return 0; - } - - // all good, continue with next byte depending on E1 - ptr++; - - // reset number of acks - status->N_nack = 0; - - if (e1) { - // E1 flag set, read a NACK_SN - rlc_status_nack_t nack = {}; - nack.nack_sn = (*ptr & 0xff) << 4; - ptr++; - // uint8_t len2 = (*ptr & 0xF0) >> 4; - nack.nack_sn |= (*ptr & 0xF0) >> 4; - status->nacks[status->N_nack] = nack; - - status->N_nack++; - } - } - - return SRSRAN_SUCCESS; -} - -/** - * Write a RLC AM NR status PDU to a PDU buffer and eets the length of the generate PDU accordingly - * @param status_pdu The status PDU - * @param pdu A pointer to a unique bytebuffer - * @return SRSRAN_SUCCESS if PDU was written, SRSRAN_ERROR otherwise - */ -int32_t rlc_am_nr_write_status_pdu(const rlc_am_nr_status_pdu_t& status_pdu, - const rlc_am_nr_sn_size_t sn_size, - byte_buffer_t* pdu) -{ - uint8_t* ptr = pdu->msg; - - // fixed header part - *ptr = 0; ///< 1 bit D/C field and 3bit CPT are all zero - - if (sn_size == rlc_am_nr_sn_size_t::size12bits) { - // write first 4 bit of ACK_SN - *ptr |= (status_pdu.ack_sn >> 8) & 0x0f; // 4 bit ACK_SN - ptr++; - *ptr = status_pdu.ack_sn & 0xff; // remaining 8 bit of SN - ptr++; - - // write E1 flag in octet 3 - *ptr = (status_pdu.N_nack > 0) ? 0x80 : 0x00; - ptr++; - - if (status_pdu.N_nack > 0) { - // write first 8 bit of NACK_SN - *ptr = (status_pdu.nacks[0].nack_sn >> 4) & 0xff; - ptr++; - - // write remaining 4 bits of NACK_SN - *ptr = status_pdu.nacks[0].nack_sn & 0xf0; - ptr++; - } - } else { - // 18bit SN - *ptr |= (status_pdu.ack_sn >> 14) & 0x0f; // 4 bit ACK_SN - ptr++; - *ptr = status_pdu.ack_sn >> 8; // bit 3 - 10 of SN - ptr++; - *ptr = (status_pdu.ack_sn & 0xff); // remaining 6 bit of SN - ptr++; - } - - pdu->N_bytes = ptr - pdu->msg; - - return SRSRAN_SUCCESS; -} +/******************************* + * RLC AM NR class + ******************************/ +// TODO } // namespace srsran diff --git a/lib/src/rlc/rlc_am_nr_packing.cc b/lib/src/rlc/rlc_am_nr_packing.cc new file mode 100644 index 000000000..b2f976f8f --- /dev/null +++ b/lib/src/rlc/rlc_am_nr_packing.cc @@ -0,0 +1,250 @@ +/** + * + * \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/rlc/rlc_am_nr_packing.h" +#include + +namespace srsran { + +/**************************************************************************** + * Header pack/unpack helper functions + * Ref: 3GPP TS 38.322 v15.3.0 Section 6.2.2.4 + ***************************************************************************/ + +uint32_t rlc_am_nr_read_data_pdu_header(const byte_buffer_t* pdu, + const rlc_am_nr_sn_size_t sn_size, + rlc_am_nr_pdu_header_t* header) +{ + return rlc_am_nr_read_data_pdu_header(pdu->msg, pdu->N_bytes, sn_size, header); +} + +uint32_t rlc_am_nr_read_data_pdu_header(const uint8_t* payload, + const uint32_t nof_bytes, + const rlc_am_nr_sn_size_t sn_size, + rlc_am_nr_pdu_header_t* header) +{ + uint8_t* ptr = const_cast(payload); + + header->sn_size = sn_size; + + // Fixed part + header->dc = (rlc_dc_field_t)((*ptr >> 7) & 0x01); // 1 bit D/C field + header->p = (*ptr >> 6) & 0x01; // 1 bit P flag + header->si = (rlc_nr_si_field_t)((*ptr >> 4) & 0x03); // 2 bits SI + + if (sn_size == rlc_am_nr_sn_size_t::size12bits) { + header->sn = (*ptr & 0x0F) << 8; // first 4 bits SN + ptr++; + + header->sn |= (*ptr & 0xFF); // last 8 bits SN + ptr++; + } else if (sn_size == rlc_am_nr_sn_size_t::size18bits) { + // sanity check + if ((*ptr & 0x0c) != 0) { + fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); + return 0; + } + header->sn = (*ptr & 0x03) << 16; // first 4 bits SN + ptr++; + header->sn |= (*ptr & 0xFF) << 8; // bit 2-10 of SN + ptr++; + header->sn |= (*ptr & 0xFF); // last 8 bits SN + ptr++; + } else { + fprintf(stderr, "Unsupported SN length\n"); + return 0; + } + + // Read optional part + if (header->si == rlc_nr_si_field_t::last_segment || + header->si == rlc_nr_si_field_t::neither_first_nor_last_segment) { + // read SO + header->so = (*ptr & 0xFF) << 8; + ptr++; + header->so |= (*ptr & 0xFF); + ptr++; + } + + // return consumed bytes + return (ptr - payload); +} + +uint32_t rlc_am_nr_packed_length(const rlc_am_nr_pdu_header_t& header) +{ + uint32_t len = 0; + if (header.si == rlc_nr_si_field_t::full_sdu || header.si == rlc_nr_si_field_t::first_segment) { + len = 2; + if (header.sn_size == rlc_am_nr_sn_size_t::size18bits) { + len++; + } + } else { + // PDU contains SO + len = 4; + if (header.sn_size == rlc_am_nr_sn_size_t::size18bits) { + len++; + } + } + return len; +} + +uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu) +{ + // Make room for the header + uint32_t len = rlc_am_nr_packed_length(header); + pdu->msg -= len; + uint8_t* ptr = pdu->msg; + + // fixed header part + *ptr = (header.dc & 0x01) << 7; ///< 1 bit D/C field + *ptr |= (header.p & 0x01) << 6; ///< 1 bit P flag + *ptr |= (header.si & 0x03) << 4; ///< 2 bits SI + + if (header.sn_size == rlc_am_nr_sn_size_t::size12bits) { + // write first 4 bit of SN + *ptr |= (header.sn >> 8) & 0x0f; // 4 bit SN + ptr++; + *ptr = header.sn & 0xff; // remaining 8 bit of SN + ptr++; + } else { + // 18bit SN + *ptr |= (header.sn >> 16) & 0x3; // 2 bit SN + ptr++; + *ptr = header.sn >> 8; // bit 3 - 10 of SN + ptr++; + *ptr = (header.sn & 0xff); // remaining 8 bit of SN + ptr++; + } + + if (header.so) { + // write SO + *ptr = header.so >> 8; // first part of SO + ptr++; + *ptr = (header.so & 0xff); // second part of SO + ptr++; + } + + pdu->N_bytes += ptr - pdu->msg; + + return len; +} + +uint32_t +rlc_am_nr_read_status_pdu(const byte_buffer_t* pdu, const rlc_am_nr_sn_size_t sn_size, rlc_am_nr_status_pdu_t* status) +{ + return rlc_am_nr_read_status_pdu(pdu->msg, pdu->N_bytes, sn_size, status); +} + +uint32_t rlc_am_nr_read_status_pdu(const uint8_t* payload, + const uint32_t nof_bytes, + const rlc_am_nr_sn_size_t sn_size, + rlc_am_nr_status_pdu_t* status) +{ + uint8_t* ptr = const_cast(payload); + + // fixed part + status->cpt = (rlc_am_nr_control_pdu_type_t)((*ptr >> 4) & 0x07); // 3 bits CPT + + // sanity check + if (status->cpt != rlc_am_nr_control_pdu_type_t::status_pdu) { + fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); + return 0; + } + + if (sn_size == rlc_am_nr_sn_size_t::size12bits) { + status->ack_sn = (*ptr & 0x0F) << 8; // first 4 bits SN + ptr++; + + status->ack_sn |= (*ptr & 0xFF); // last 8 bits SN + ptr++; + + // read E1 flag + uint8_t e1 = *ptr & 0x80; + + // sanity check for reserved bits + if ((*ptr & 0x7f) != 0) { + fprintf(stderr, "Malformed PDU, reserved bits are set.\n"); + return 0; + } + + // all good, continue with next byte depending on E1 + ptr++; + + // reset number of acks + status->N_nack = 0; + + if (e1) { + // E1 flag set, read a NACK_SN + rlc_status_nack_t nack = {}; + nack.nack_sn = (*ptr & 0xff) << 4; + ptr++; + // uint8_t len2 = (*ptr & 0xF0) >> 4; + nack.nack_sn |= (*ptr & 0xF0) >> 4; + status->nacks[status->N_nack] = nack; + + status->N_nack++; + } + } + + return SRSRAN_SUCCESS; +} + +/** + * Write a RLC AM NR status PDU to a PDU buffer and eets the length of the generate PDU accordingly + * @param status_pdu The status PDU + * @param pdu A pointer to a unique bytebuffer + * @return SRSRAN_SUCCESS if PDU was written, SRSRAN_ERROR otherwise + */ +int32_t rlc_am_nr_write_status_pdu(const rlc_am_nr_status_pdu_t& status_pdu, + const rlc_am_nr_sn_size_t sn_size, + byte_buffer_t* pdu) +{ + uint8_t* ptr = pdu->msg; + + // fixed header part + *ptr = 0; ///< 1 bit D/C field and 3bit CPT are all zero + + if (sn_size == rlc_am_nr_sn_size_t::size12bits) { + // write first 4 bit of ACK_SN + *ptr |= (status_pdu.ack_sn >> 8) & 0x0f; // 4 bit ACK_SN + ptr++; + *ptr = status_pdu.ack_sn & 0xff; // remaining 8 bit of SN + ptr++; + + // write E1 flag in octet 3 + *ptr = (status_pdu.N_nack > 0) ? 0x80 : 0x00; + ptr++; + + if (status_pdu.N_nack > 0) { + // write first 8 bit of NACK_SN + *ptr = (status_pdu.nacks[0].nack_sn >> 4) & 0xff; + ptr++; + + // write remaining 4 bits of NACK_SN + *ptr = status_pdu.nacks[0].nack_sn & 0xf0; + ptr++; + } + } else { + // 18bit SN + *ptr |= (status_pdu.ack_sn >> 14) & 0x0f; // 4 bit ACK_SN + ptr++; + *ptr = status_pdu.ack_sn >> 8; // bit 3 - 10 of SN + ptr++; + *ptr = (status_pdu.ack_sn & 0xff); // remaining 6 bit of SN + ptr++; + } + + pdu->N_bytes = ptr - pdu->msg; + + return SRSRAN_SUCCESS; +} + +} // namespace srsran diff --git a/lib/test/rlc/rlc_am_nr_pdu_test.cc b/lib/test/rlc/rlc_am_nr_pdu_test.cc index 6b72a6fc2..a2257c9d9 100644 --- a/lib/test/rlc/rlc_am_nr_pdu_test.cc +++ b/lib/test/rlc/rlc_am_nr_pdu_test.cc @@ -12,7 +12,7 @@ #include "srsran/config.h" #include "srsran/rlc/rlc.h" -#include "srsran/rlc/rlc_am_nr.h" +#include "srsran/rlc/rlc_am_nr_packing.h" #include #include From d528d8af4c08f9fd5982a2366a9644d1b566f6f5 Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Mon, 28 Jun 2021 18:52:58 +0100 Subject: [PATCH 10/35] Added initial skeleton for RLC AM NR entity --- lib/include/srsran/rlc/rlc_am_data_structs.h | 2 +- lib/include/srsran/rlc/rlc_am_lte_packing.h | 2 +- lib/include/srsran/rlc/rlc_am_nr.h | 108 ++++++++++- lib/include/srsran/rlc/rlc_am_nr_packing.h | 2 +- lib/src/rlc/rlc_am_nr.cc | 191 ++++++++++++++++++- 5 files changed, 300 insertions(+), 5 deletions(-) diff --git a/lib/include/srsran/rlc/rlc_am_data_structs.h b/lib/include/srsran/rlc/rlc_am_data_structs.h index f7d0ad131..2a5800125 100644 --- a/lib/include/srsran/rlc/rlc_am_data_structs.h +++ b/lib/include/srsran/rlc/rlc_am_data_structs.h @@ -214,4 +214,4 @@ private: } // namespace srsran -#endif // SRSRAN_BEARER_MEM_POOL_H +#endif // SRSRAN_RLC_AM_DATA_STRUCTS_H diff --git a/lib/include/srsran/rlc/rlc_am_lte_packing.h b/lib/include/srsran/rlc/rlc_am_lte_packing.h index f4d2d5ea5..19215d4e4 100644 --- a/lib/include/srsran/rlc/rlc_am_lte_packing.h +++ b/lib/include/srsran/rlc/rlc_am_lte_packing.h @@ -132,4 +132,4 @@ void log_rlc_am_status_pdu_to_string(srslog::log_channel& log_ch, } // namespace srsran -#endif // SRSRAN_RLC_AM_NR_H +#endif // SRSRAN_RLC_AM_LTE_PACKING_H diff --git a/lib/include/srsran/rlc/rlc_am_nr.h b/lib/include/srsran/rlc/rlc_am_nr.h index cd03e78cb..49d0dddc3 100644 --- a/lib/include/srsran/rlc/rlc_am_nr.h +++ b/lib/include/srsran/rlc/rlc_am_nr.h @@ -25,7 +25,113 @@ namespace srsran { -// TODO +class rlc_am_nr : public rlc_common +{ +public: + rlc_am_nr(srslog::basic_logger& logger, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srsran::timer_handler* timers_); + bool configure(const rlc_config_t& cfg_) final; + void stop() final; + + rlc_mode_t get_mode() final; + uint32_t get_bearer() final; + + void reestablish() final; + void empty_queue() final; + void set_bsr_callback(bsr_callback_t callback) final; + + // PDCP interface + void write_sdu(unique_byte_buffer_t sdu) final; + void discard_sdu(uint32_t pdcp_sn) final; + bool sdu_queue_is_full() final; + + // MAC interface + bool has_data() final; + uint32_t get_buffer_state() final; + void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) final; + uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes) final; + void write_pdu(uint8_t* payload, uint32_t nof_bytes) final; + + rlc_bearer_metrics_t get_metrics() final; + void reset_metrics() final; + +private: + // Transmitter sub-class + class rlc_am_nr_tx + { + public: + explicit rlc_am_nr_tx(rlc_am_nr* parent_); + ~rlc_am_nr_tx() = default; + + bool configure(const rlc_am_config_t& cfg_); + void stop(); + + int write_sdu(unique_byte_buffer_t sdu); + uint32_t read_pdu(uint8_t* payload, uint32_t nof_bytes); + void discard_sdu(uint32_t discard_sn); + bool sdu_queue_is_full(); + + bool has_data(); + uint32_t get_buffer_state(); + + rlc_am_nr* parent = nullptr; + srslog::basic_logger& logger; + + private: + byte_buffer_pool* pool = nullptr; + + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 38.322 v10.0.0 Section 7.4 + ***************************************************************************/ + rlc_am_config_t cfg = {}; + }; + + // Receiver sub-class + class rlc_am_nr_rx + { + public: + explicit rlc_am_nr_rx(rlc_am_nr* parent_); + ~rlc_am_nr_rx() = default; + + bool configure(const rlc_am_config_t& cfg_); + void stop(); + + void write_pdu(uint8_t* payload, uint32_t nof_bytes); + + rlc_am_nr* parent = nullptr; + srslog::basic_logger& logger; + + private: + byte_buffer_pool* pool = nullptr; + + /**************************************************************************** + * Configurable parameters + * Ref: 3GPP TS 38.322 v10.0.0 Section 7.4 + ***************************************************************************/ + rlc_am_config_t cfg = {}; + }; + + // Common variables needed/provided by parent class + srsue::rrc_interface_rlc* rrc = nullptr; + srslog::basic_logger& logger; + srsue::pdcp_interface_rlc* pdcp = nullptr; + srsran::timer_handler* timers = nullptr; + uint32_t lcid = 0; + rlc_config_t cfg = {}; + std::string rb_name; + + static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested + + // Rx and Tx objects + rlc_am_nr_tx tx; + rlc_am_nr_rx rx; + + rlc_bearer_metrics_t metrics = {}; +}; } // namespace srsran diff --git a/lib/include/srsran/rlc/rlc_am_nr_packing.h b/lib/include/srsran/rlc/rlc_am_nr_packing.h index f31aa2c42..80f55042a 100644 --- a/lib/include/srsran/rlc/rlc_am_nr_packing.h +++ b/lib/include/srsran/rlc/rlc_am_nr_packing.h @@ -72,4 +72,4 @@ int32_t rlc_am_nr_write_status_pdu(const rlc_am_nr_status_pdu_t& status_pdu, } // namespace srsran -#endif // SRSRAN_RLC_AM_NR_H +#endif // SRSRAN_RLC_AM_NR_PACKING_H diff --git a/lib/src/rlc/rlc_am_nr.cc b/lib/src/rlc/rlc_am_nr.cc index cef2d1935..4b96e5724 100644 --- a/lib/src/rlc/rlc_am_nr.cc +++ b/lib/src/rlc/rlc_am_nr.cc @@ -22,6 +22,195 @@ namespace srsran { /******************************* * RLC AM NR class ******************************/ -// TODO +rlc_am_nr::rlc_am_nr(srslog::basic_logger& logger, + uint32_t lcid_, + srsue::pdcp_interface_rlc* pdcp_, + srsue::rrc_interface_rlc* rrc_, + srsran::timer_handler* timers_) : + logger(logger), rrc(rrc_), pdcp(pdcp_), timers(timers_), lcid(lcid_), tx(this), rx(this) +{} + +// Applies new configuration. Must be just reestablished or initiated +bool rlc_am_nr::configure(const rlc_config_t& cfg_) +{ + // determine bearer name and configure Rx/Tx objects + rb_name = rrc->get_rb_name(lcid); + + // store config + cfg = cfg_; + + if (not rx.configure(cfg.am)) { + logger.error("Error configuring bearer (RX)"); + return false; + } + + if (not tx.configure(cfg.am)) { + logger.error("Error configuring bearer (TX)"); + return false; + } + + logger.info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, " + "t_reordering=%d, t_status_prohibit=%d", + rb_name.c_str(), + cfg.am.t_poll_retx, + cfg.am.poll_pdu, + cfg.am.poll_byte, + cfg.am.max_retx_thresh, + cfg.am.t_reordering, + cfg.am.t_status_prohibit); + return true; +} + +void rlc_am_nr::stop() {} + +rlc_mode_t rlc_am_nr::get_mode() +{ + return rlc_mode_t::am; +} + +uint32_t rlc_am_nr::get_bearer() +{ + return 0; +} + +void rlc_am_nr::reestablish() {} + +void rlc_am_nr::empty_queue() {} + +void rlc_am_nr::set_bsr_callback(bsr_callback_t callback) {} + +rlc_bearer_metrics_t rlc_am_nr::get_metrics() +{ + return {}; +} + +void rlc_am_nr::reset_metrics() {} + +/**************************************************************************** + * PDCP interface + ***************************************************************************/ +void rlc_am_nr::write_sdu(unique_byte_buffer_t sdu) +{ + if (tx.write_sdu(std::move(sdu)) == SRSRAN_SUCCESS) { + metrics.num_tx_sdus++; + } +} + +void rlc_am_nr::discard_sdu(uint32_t pdcp_sn) +{ + tx.discard_sdu(pdcp_sn); + metrics.num_lost_sdus++; +} + +bool rlc_am_nr::sdu_queue_is_full() +{ + return tx.sdu_queue_is_full(); +} + +/**************************************************************************** + * MAC interface + ***************************************************************************/ + +bool rlc_am_nr::has_data() +{ + return tx.has_data(); +} + +uint32_t rlc_am_nr::get_buffer_state() +{ + return tx.get_buffer_state(); +} + +void rlc_am_nr::get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) +{ + // TODO + tx_queue = tx.get_buffer_state(); + prio_tx_queue = 0; +} + +uint32_t rlc_am_nr::read_pdu(uint8_t* payload, uint32_t nof_bytes) +{ + uint32_t read_bytes = tx.read_pdu(payload, nof_bytes); + metrics.num_tx_pdus++; + metrics.num_tx_pdu_bytes += read_bytes; + return read_bytes; +} + +void rlc_am_nr::write_pdu(uint8_t* payload, uint32_t nof_bytes) +{ + rx.write_pdu(payload, nof_bytes); + metrics.num_rx_pdus++; + metrics.num_rx_pdu_bytes += nof_bytes; +} + +/**************************************************************************** + * Tx subclass implementation + ***************************************************************************/ +rlc_am_nr::rlc_am_nr_tx::rlc_am_nr_tx(rlc_am_nr* parent_) : + parent(parent_), logger(parent_->logger), pool(byte_buffer_pool::get_instance()) +{} + +bool rlc_am_nr::rlc_am_nr_tx::configure(const rlc_am_config_t& cfg_) +{ + /* + if (cfg_.tx_queue_length > MAX_SDUS_PER_RLC_PDU) { + logger.error("Configuring Tx queue length of %d PDUs too big. Maximum value is %d.", + cfg_.tx_queue_length, + MAX_SDUS_PER_RLC_PDU); + return false; + } + */ + cfg = cfg_; + + return true; +} + +int rlc_am_nr::rlc_am_nr_tx::write_sdu(unique_byte_buffer_t sdu) +{ + return 0; +} + +void rlc_am_nr::rlc_am_nr_tx::discard_sdu(uint32_t sn) +{ + return; +} + +bool rlc_am_nr::rlc_am_nr_tx::sdu_queue_is_full() +{ + return false; +} + +bool rlc_am_nr::rlc_am_nr_tx::has_data() +{ + return true; +} + +uint32_t rlc_am_nr::rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes) +{ + return 0; +} + +uint32_t rlc_am_nr::rlc_am_nr_tx::get_buffer_state() +{ + return 0; +} + +/**************************************************************************** + * Rx subclass implementation + ***************************************************************************/ +rlc_am_nr::rlc_am_nr_rx::rlc_am_nr_rx(rlc_am_nr* parent_) : + parent(parent_), pool(byte_buffer_pool::get_instance()), logger(parent_->logger) +{} + +bool rlc_am_nr::rlc_am_nr_rx::configure(const rlc_am_config_t& cfg_) +{ + cfg = cfg_; + + return true; +} + +void rlc_am_nr::rlc_am_nr_rx::stop() {} + +void rlc_am_nr::rlc_am_nr_rx::write_pdu(uint8_t* payload, uint32_t nof_bytes) {} } // namespace srsran From 2a5d21164f68359abe1e0810898208aaa1989bbf Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Thu, 8 Jul 2021 18:10:37 +0100 Subject: [PATCH 11/35] Adding RLC AM NR unit tests --- lib/test/rlc/CMakeLists.txt | 10 +- .../{rlc_am_test.cc => rlc_am_lte_test.cc} | 58 +--------- lib/test/rlc/rlc_am_nr_test.cc | 109 ++++++++++++++++++ lib/test/rlc/rlc_test_common.h | 78 +++++++++++-- 4 files changed, 185 insertions(+), 70 deletions(-) rename lib/test/rlc/{rlc_am_test.cc => rlc_am_lte_test.cc} (98%) create mode 100644 lib/test/rlc/rlc_am_nr_test.cc diff --git a/lib/test/rlc/CMakeLists.txt b/lib/test/rlc/CMakeLists.txt index 6b0f6bf45..dc57c224e 100644 --- a/lib/test/rlc/CMakeLists.txt +++ b/lib/test/rlc/CMakeLists.txt @@ -16,9 +16,13 @@ add_executable(rlc_am_control_test rlc_am_control_test.cc) target_link_libraries(rlc_am_control_test srsran_rlc srsran_phy) add_lte_test(rlc_am_control_test rlc_am_control_test) -add_executable(rlc_am_test rlc_am_test.cc) -target_link_libraries(rlc_am_test srsran_rlc srsran_phy srsran_common) -add_lte_test(rlc_am_test rlc_am_test) +add_executable(rlc_am_lte_test rlc_am_lte_test.cc) +target_link_libraries(rlc_am_lte_test srsran_rlc srsran_phy srsran_common) +add_lte_test(rlc_am_lte_test rlc_am_lte_test) + +add_executable(rlc_am_nr_test rlc_am_nr_test.cc) +target_link_libraries(rlc_am_nr_test srsran_rlc srsran_phy srsran_common) +add_nr_test(rlc_am_nr_test rlc_am_nr_test) add_executable(rlc_am_nr_pdu_test rlc_am_nr_pdu_test.cc) target_link_libraries(rlc_am_nr_pdu_test srsran_rlc srsran_phy) diff --git a/lib/test/rlc/rlc_am_test.cc b/lib/test/rlc/rlc_am_lte_test.cc similarity index 98% rename from lib/test/rlc/rlc_am_test.cc rename to lib/test/rlc/rlc_am_lte_test.cc index 8b020ba67..d7dbc71af 100644 --- a/lib/test/rlc/rlc_am_test.cc +++ b/lib/test/rlc/rlc_am_lte_test.cc @@ -10,6 +10,7 @@ * */ +#include "rlc_test_common.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/rlc_pcap.h" #include "srsran/common/test_common.h" @@ -25,63 +26,6 @@ using namespace srsue; using namespace srsran; -bool rx_is_tx(const rlc_bearer_metrics_t& rlc1_metrics, const rlc_bearer_metrics_t& rlc2_metrics) -{ - if (rlc1_metrics.num_tx_pdu_bytes != rlc2_metrics.num_rx_pdu_bytes) { - return false; - } - - if (rlc2_metrics.num_tx_pdu_bytes != rlc1_metrics.num_rx_pdu_bytes) { - return false; - } - return true; -} - -class rlc_am_tester : public pdcp_interface_rlc, public rrc_interface_rlc -{ -public: - rlc_am_tester(rlc_pcap* pcap_ = NULL) : pcap(pcap_) {} - - // PDCP interface - void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu) - { - assert(lcid == 1); - sdus.push_back(std::move(sdu)); - } - void write_pdu_bcch_bch(unique_byte_buffer_t sdu) {} - void write_pdu_bcch_dlsch(unique_byte_buffer_t sdu) {} - void write_pdu_pcch(unique_byte_buffer_t sdu) {} - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) {} - void notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn_vec) - { - assert(lcid == 1); - for (uint32_t pdcp_sn : pdcp_sn_vec) { - if (notified_counts.find(pdcp_sn) == notified_counts.end()) { - notified_counts[pdcp_sn] = 0; - } - notified_counts[pdcp_sn] += 1; - } - } - void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn_vec) - { - assert(lcid == 1); - // TODO - } - - // RRC interface - void max_retx_attempted() { max_retx_triggered = true; } - void protocol_failure() { protocol_failure_triggered = true; } - - const char* get_rb_name(uint32_t lcid) { return ""; } - - std::vector sdus; - rlc_pcap* pcap = nullptr; - bool max_retx_triggered = false; - bool protocol_failure_triggered = false; - - std::map notified_counts; // Map of PDCP SNs to number of notifications -}; - class ul_writer : public thread { public: diff --git a/lib/test/rlc/rlc_am_nr_test.cc b/lib/test/rlc/rlc_am_nr_test.cc new file mode 100644 index 000000000..039901cee --- /dev/null +++ b/lib/test/rlc/rlc_am_nr_test.cc @@ -0,0 +1,109 @@ +/** + * + * \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 "rlc_test_common.h" +#include "srsran/common/buffer_pool.h" +#include "srsran/common/rlc_pcap.h" +#include "srsran/common/test_common.h" +#include "srsran/common/threads.h" +#include "srsran/interfaces/ue_pdcp_interfaces.h" +#include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/rlc/rlc_am_nr.h" + +#define NBUFS 5 +#define HAVE_PCAP 0 +#define SDU_SIZE 500 + +using namespace srsue; +using namespace srsran; + +int basic_test_tx(rlc_am_nr* rlc, byte_buffer_t pdu_bufs[NBUFS]) +{ + // Push 5 SDUs into RLC1 + unique_byte_buffer_t sdu_bufs[NBUFS]; + for (int i = 0; i < NBUFS; i++) { + sdu_bufs[i] = srsran::make_byte_buffer(); + sdu_bufs[i]->msg[0] = i; // Write the index into the buffer + sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte + sdu_bufs[i]->md.pdcp_sn = i; // PDCP SN for notifications + rlc->write_sdu(std::move(sdu_bufs[i])); + } + + TESTASSERT(13 == rlc->get_buffer_state()); // 2 Bytes for fixed header + 6 for LIs + 5 for payload + + // Read 5 PDUs from RLC1 (1 byte each) + for (int i = 0; i < NBUFS; i++) { + uint32_t len = rlc->read_pdu(pdu_bufs[i].msg, 3); // 2 bytes for header + 1 byte payload + pdu_bufs[i].N_bytes = len; + TESTASSERT(3 == len); + } + + TESTASSERT(0 == rlc->get_buffer_state()); + return SRSRAN_SUCCESS; +} + +int basic_test() +{ + rlc_am_tester tester; + timer_handler timers(8); + byte_buffer_t pdu_bufs[NBUFS]; + + rlc_am_nr rlc1(srslog::fetch_basic_logger("RLC_AM_1"), 1, &tester, &tester, &timers); + rlc_am_nr rlc2(srslog::fetch_basic_logger("RLC_AM_2"), 1, &tester, &tester, &timers); + + // before configuring entity + TESTASSERT(0 == rlc1.get_buffer_state()); + + if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) { + return -1; + } + + if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) { + return -1; + } + + // basic_test_tx(&rlc1, pdu_bufs); + return SRSRAN_SUCCESS; +} + +int main(int argc, char** argv) +{ + // Setup the log message spy to intercept error and warning log entries from RLC + if (!srslog::install_custom_sink(srsran::log_sink_message_spy::name(), + std::unique_ptr( + new srsran::log_sink_message_spy(srslog::get_default_log_formatter())))) { + return SRSRAN_ERROR; + } + + auto* spy = static_cast(srslog::find_sink(srsran::log_sink_message_spy::name())); + if (spy == nullptr) { + return SRSRAN_ERROR; + } + srslog::set_default_sink(*spy); + + auto& logger_rlc1 = srslog::fetch_basic_logger("RLC_NR_AM_1", *spy, false); + auto& logger_rlc2 = srslog::fetch_basic_logger("RLC_NR_AM_2", *spy, false); + logger_rlc1.set_hex_dump_max_size(100); + logger_rlc2.set_hex_dump_max_size(100); + logger_rlc1.set_level(srslog::basic_levels::debug); + logger_rlc2.set_level(srslog::basic_levels::debug); + + // start log backend + srslog::init(); + + if (basic_test()) { + printf("basic_test failed\n"); + exit(-1); + }; + + return SRSRAN_SUCCESS; +} diff --git a/lib/test/rlc/rlc_test_common.h b/lib/test/rlc/rlc_test_common.h index 494a09a60..519103243 100644 --- a/lib/test/rlc/rlc_test_common.h +++ b/lib/test/rlc/rlc_test_common.h @@ -14,8 +14,10 @@ #define SRSRAN_RLC_TEST_COMMON_H #include "srsran/common/byte_buffer.h" +#include "srsran/common/rlc_pcap.h" #include "srsran/interfaces/ue_pdcp_interfaces.h" #include "srsran/interfaces/ue_rrc_interfaces.h" +#include "srsran/rlc/rlc_metrics.h" #include namespace srsran { @@ -23,10 +25,10 @@ namespace srsran { class rlc_um_tester : public srsue::pdcp_interface_rlc, public srsue::rrc_interface_rlc { public: - rlc_um_tester() {} + rlc_um_tester() = default; // PDCP interface - void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu) + void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu) final { // check length if (lcid != 3 && sdu->N_bytes != expected_sdu_len) { @@ -47,16 +49,16 @@ public: // srsran_vec_fprint_byte(stdout, sdu->msg, sdu->N_bytes); sdus.push_back(std::move(sdu)); } - void write_pdu_bcch_bch(unique_byte_buffer_t sdu) {} - void write_pdu_bcch_dlsch(unique_byte_buffer_t sdu) {} - void write_pdu_pcch(unique_byte_buffer_t sdu) {} - void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) { sdus.push_back(std::move(sdu)); } - void notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) {} - void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) {} + void write_pdu_bcch_bch(unique_byte_buffer_t sdu) final {} + void write_pdu_bcch_dlsch(unique_byte_buffer_t sdu) final {} + void write_pdu_pcch(unique_byte_buffer_t sdu) final {} + void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t sdu) final { sdus.push_back(std::move(sdu)); } + void notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) final {} + void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sns) final {} // RRC interface - void max_retx_attempted() {} - void protocol_failure() {} + void max_retx_attempted() final {} + void protocol_failure() final {} const char* get_rb_name(uint32_t lcid) { return ""; } void set_expected_sdu_len(uint32_t len) { expected_sdu_len = len; } @@ -67,6 +69,62 @@ public: uint32_t expected_sdu_len = 0; }; +class rlc_am_tester : public srsue::pdcp_interface_rlc, public srsue::rrc_interface_rlc +{ +public: + rlc_am_tester(rlc_pcap* pcap_ = NULL) : pcap(pcap_) {} + + // PDCP interface + void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu) + { + assert(lcid == 1); + sdus.push_back(std::move(sdu)); + } + void write_pdu_bcch_bch(unique_byte_buffer_t sdu) {} + void write_pdu_bcch_dlsch(unique_byte_buffer_t sdu) {} + void write_pdu_pcch(unique_byte_buffer_t sdu) {} + void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) {} + void notify_delivery(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn_vec) + { + assert(lcid == 1); + for (uint32_t pdcp_sn : pdcp_sn_vec) { + if (notified_counts.find(pdcp_sn) == notified_counts.end()) { + notified_counts[pdcp_sn] = 0; + } + notified_counts[pdcp_sn] += 1; + } + } + void notify_failure(uint32_t lcid, const srsran::pdcp_sn_vector_t& pdcp_sn_vec) + { + assert(lcid == 1); + // TODO + } + + // RRC interface + void max_retx_attempted() { max_retx_triggered = true; } + void protocol_failure() { protocol_failure_triggered = true; } + + const char* get_rb_name(uint32_t lcid) { return ""; } + + std::vector sdus; + rlc_pcap* pcap = nullptr; + bool max_retx_triggered = false; + bool protocol_failure_triggered = false; + + std::map notified_counts; // Map of PDCP SNs to number of notifications +}; + +bool rx_is_tx(const rlc_bearer_metrics_t& rlc1_metrics, const rlc_bearer_metrics_t& rlc2_metrics) +{ + if (rlc1_metrics.num_tx_pdu_bytes != rlc2_metrics.num_rx_pdu_bytes) { + return false; + } + + if (rlc2_metrics.num_tx_pdu_bytes != rlc1_metrics.num_rx_pdu_bytes) { + return false; + } + return true; +} } // namespace srsran #endif // SRSRAN_RLC_TEST_COMMON_H From 96fd3aae3c749926b55558e3cbfde4e3c5e672cc Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 4 Nov 2021 15:01:13 +0000 Subject: [PATCH 12/35] nr,gnb: small gnb interface refactors and fix of byte buffer operator= --- lib/include/srsran/asn1/rrc_nr_utils.h | 6 --- lib/include/srsran/common/byte_buffer.h | 2 +- .../srsran/interfaces/gnb_interfaces.h | 4 +- .../srsran/interfaces/gnb_rrc_nr_interfaces.h | 10 ++--- lib/src/asn1/rrc_nr_utils.cc | 29 ------------- srsenb/hdr/stack/rrc/rrc_nr.h | 4 +- srsenb/src/stack/mac/nr/mac_nr.cc | 2 +- srsenb/src/stack/rrc/rrc_nr.cc | 42 ++++--------------- srsenb/test/common/dummy_classes_nr.h | 4 +- 9 files changed, 21 insertions(+), 82 deletions(-) diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index 9b39785e7..18d284646 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -13,7 +13,6 @@ #ifndef SRSRAN_RRC_NR_UTILS_H #define SRSRAN_RRC_NR_UTILS_H -#include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/phy_cfg_nr.h" #include "srsran/interfaces/mac_interface_types.h" #include "srsran/interfaces/pdcp_interface_types.h" @@ -143,9 +142,4 @@ pdcp_config_t make_drb_pdcp_config_t(const uint8_t bearer_id, bool is_ue, const } // namespace srsran -namespace srsenb { - -int set_sched_cell_cfg_sib1(srsenb::sched_interface::cell_cfg_t* sched_cfg, const asn1::rrc_nr::sib1_s& sib1); -} - #endif // SRSRAN_RRC_NR_UTILS_H diff --git a/lib/include/srsran/common/byte_buffer.h b/lib/include/srsran/common/byte_buffer.h index f6d2e6479..5a8027423 100644 --- a/lib/include/srsran/common/byte_buffer.h +++ b/lib/include/srsran/common/byte_buffer.h @@ -119,7 +119,7 @@ public: // avoid self assignment if (&buf == this) return *this; - msg = &buffer[SRSRAN_BUFFER_HEADER_OFFSET]; + msg = &buffer[buf.msg - &(*buf.buffer)]; N_bytes = buf.N_bytes; md = buf.md; memcpy(msg, buf.msg, N_bytes); diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 68dbf1ee8..b902829e6 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -132,8 +132,8 @@ class rrc_interface_mac_nr { public: // Provides MIB packed message - virtual int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) = 0; - virtual int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) = 0; + virtual int read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) = 0; + virtual int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) = 0; /// User management virtual int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg) = 0; diff --git a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h index 883749d37..03c0041c4 100644 --- a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h @@ -27,10 +27,10 @@ public: virtual int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) = 0; virtual int start_security_mode_procedure(uint16_t rnti) = 0; virtual int - establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) = 0; - virtual int allocate_lcid(uint16_t rnti) = 0; - virtual int release_bearers(uint16_t rnti) = 0; - virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0; + establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid) = 0; + virtual int allocate_lcid(uint16_t rnti) = 0; + virtual int release_bearers(uint16_t rnti) = 0; + virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0; }; // Cell/Sector configuration for NR cells @@ -51,4 +51,4 @@ typedef std::vector rrc_cell_list_nr_t; } // namespace srsenb -#endif // SRSRAN_GNB_RRC_NR_INTERFACES_H \ No newline at end of file +#endif // SRSRAN_GNB_RRC_NR_INTERFACES_H diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index b1c120726..e11633519 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -1595,32 +1595,3 @@ bool fill_phy_pdcch_cfg_common(const asn1::rrc_nr::pdcch_cfg_common_s& pdcch_cfg } } // namespace srsran - -namespace srsenb { - -int set_sched_cell_cfg_sib1(srsenb::sched_interface::cell_cfg_t* sched_cfg, const asn1::rrc_nr::sib1_s& sib1) -{ - bzero(sched_cfg, sizeof(srsenb::sched_interface::cell_cfg_t)); - - // set SIB1 and SIB2+ period - sched_cfg->sibs[0].period_rf = 16; // SIB1 is always 16 rf - for (uint32_t i = 0; i < sib1.si_sched_info.sched_info_list.size(); i++) { - sched_cfg->sibs[i + 1].period_rf = sib1.si_sched_info.sched_info_list[i].si_periodicity.to_number(); - } - - // si-WindowLength - sched_cfg->si_window_ms = sib1.si_sched_info.si_win_len.to_number(); - - // setup PRACH - if (not sib1.si_sched_info.si_request_cfg.rach_occasions_si_present) { - asn1::log_warning("rach_occasions_si option not present"); - return SRSRAN_ERROR; - } - sched_cfg->prach_rar_window = sib1.si_sched_info.si_request_cfg.rach_occasions_si.rach_cfg_si.ra_resp_win.to_number(); - sched_cfg->prach_freq_offset = sib1.si_sched_info.si_request_cfg.rach_occasions_si.rach_cfg_si.msg1_freq_start; - sched_cfg->maxharq_msg3tx = sib1.si_sched_info.si_request_cfg.rach_occasions_si.rach_cfg_si.preamb_trans_max; - - return SRSRAN_SUCCESS; -} - -} // namespace srsenb diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 75fe397fa..2e8305f27 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -65,8 +65,8 @@ public: void config_phy(); void config_mac(); int32_t generate_sibs(); - int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) final; - int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) final; + int read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) final; + int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) final; /// User manegement int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg); diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsenb/src/stack/mac/nr/mac_nr.cc index 8bf7a4577..496cc7c6a 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsenb/src/stack/mac/nr/mac_nr.cc @@ -117,7 +117,7 @@ int mac_nr::cell_cfg(const std::vector& logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); return SRSRAN_ERROR; } - if (rrc->read_pdu_bcch_dlsch(sib.index, sib.payload) != SRSRAN_SUCCESS) { + if (rrc->read_pdu_bcch_dlsch(sib.index, *sib.payload) != SRSRAN_SUCCESS) { logger.error("Couldn't read SIB %d from RRC", sib.index); } diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 7d8bd5f15..50ac298bd 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -307,22 +307,6 @@ void rrc_nr::config_mac() ret2 = srsran::make_duplex_cfg_from_serv_cell(base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common, &cell.duplex); srsran_assert(ret2, "Invalid NR cell configuration."); - // FIXME: entire SI configuration, etc needs to be ported to NR - sched_interface::cell_cfg_t cell_cfg; - set_sched_cell_cfg_sib1(&cell_cfg, cfg.sib1); - - // set SIB length - for (uint32_t i = 0; i < nof_si_messages + 1; i++) { - cell_cfg.sibs[i].len = sib_buffer[i]->N_bytes; - } - - // PUCCH width - cell_cfg.nrb_pucch = SRSRAN_MAX(cfg.sr_cfg.nof_prb, /* TODO: where is n_rb2 in NR? */ 0); - logger.info("Allocating %d PRBs for PUCCH", cell_cfg.nrb_pucch); - - // Copy Cell configuration - // cell_cfg.cell = cfg.cell; - // Configure MAC/scheduler mac->cell_cfg(sched_cells_cfg); } @@ -397,33 +381,23 @@ int32_t rrc_nr::generate_sibs() MAC interface *******************************************************************************/ -int rrc_nr::read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) +int rrc_nr::read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) { - if (mib_buffer == nullptr || buffer->get_tailroom() < mib_buffer->N_bytes) { + if (mib_buffer == nullptr || buffer.get_tailroom() < mib_buffer->N_bytes) { return SRSRAN_ERROR; } - memcpy(buffer->msg, mib_buffer->msg, mib_buffer->N_bytes); - buffer->N_bytes = mib_buffer->N_bytes; + buffer = *mib_buffer; return SRSRAN_SUCCESS; } -int rrc_nr::read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) +int rrc_nr::read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) { if (sib_index >= sib_buffer.size()) { logger.error("SIB %d is not a configured SIB.", sib_index); return SRSRAN_ERROR; } - if (buffer->get_tailroom() < sib_buffer[sib_index]->N_bytes) { - logger.error("Not enough space to fit SIB %d into buffer (%d < %d)", - sib_index, - buffer->get_tailroom(), - sib_buffer[sib_index]->N_bytes); - return SRSRAN_ERROR; - } - - memcpy(buffer->msg, sib_buffer[sib_index]->msg, sib_buffer[sib_index]->N_bytes); - buffer->N_bytes = sib_buffer[sib_index]->N_bytes; + buffer = *sib_buffer[sib_index]; return SRSRAN_SUCCESS; } @@ -527,9 +501,9 @@ void rrc_nr::sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_ uecfg.carriers[0].cc = 0; uecfg.ue_bearers[0].direction = mac_lc_ch_cfg_t::BOTH; srsran::phy_cfg_nr_default_t::reference_cfg_t ref_args{}; - ref_args.duplex = cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_TDD - ? srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4 - : srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_FDD; + ref_args.duplex = cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_TDD + ? srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4 + : srsran::phy_cfg_nr_default_t::reference_cfg_t::R_DUPLEX_FDD; uecfg.phy_cfg = srsran::phy_cfg_nr_default_t{ref_args}; uecfg.phy_cfg.csi = {}; // disable CSI until RA is complete diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsenb/test/common/dummy_classes_nr.h index 018599afa..362946324 100644 --- a/srsenb/test/common/dummy_classes_nr.h +++ b/srsenb/test/common/dummy_classes_nr.h @@ -21,8 +21,8 @@ namespace srsenb { class rrc_nr_dummy : public rrc_interface_mac_nr { public: - int read_pdu_bcch_bch(const uint32_t tti, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } - int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::unique_byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } + int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) { return SRSRAN_SUCCESS; } int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg) { return SRSRAN_SUCCESS; } int update_user(uint16_t new_rnti, uint16_t old_rnti) { return SRSRAN_SUCCESS; } void set_activity_user(uint16_t rnti) {} From 5f3afffd05d9e4a800914abf5c8ee82321045cd7 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 4 Nov 2021 15:18:06 +0000 Subject: [PATCH 13/35] nr,gnb: implementation of sib and mib asn1 generation functions --- .../srsran/interfaces/gnb_rrc_nr_interfaces.h | 17 -- lib/include/srsran/rrc/nr/rrc_nr_cfg_utils.h | 43 ++++ lib/src/CMakeLists.txt | 1 + lib/src/rrc/CMakeLists.txt | 10 + lib/src/rrc/nr/rrc_nr_cfg_utils.cc | 239 ++++++++++++++++++ srsenb/hdr/stack/rrc/nr/cell_asn1_config.h | 5 +- srsenb/hdr/stack/rrc/nr/rrc_config_nr.h | 18 ++ srsenb/src/stack/rrc/CMakeLists.txt | 1 + srsenb/src/stack/rrc/nr/cell_asn1_config.cc | 19 ++ 9 files changed, 335 insertions(+), 18 deletions(-) create mode 100644 lib/include/srsran/rrc/nr/rrc_nr_cfg_utils.h create mode 100644 lib/src/rrc/CMakeLists.txt create mode 100644 lib/src/rrc/nr/rrc_nr_cfg_utils.cc diff --git a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h index 03c0041c4..20c00d21d 100644 --- a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h @@ -12,7 +12,6 @@ #ifndef SRSRAN_GNB_RRC_NR_INTERFACES_H #define SRSRAN_GNB_RRC_NR_INTERFACES_H -#include "srsenb/hdr/phy/phy_interfaces.h" #include "srsran/asn1/ngap.h" #include "srsran/common/byte_buffer.h" @@ -33,22 +32,6 @@ public: virtual void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) = 0; }; -// Cell/Sector configuration for NR cells -struct rrc_cell_cfg_nr_t { - phy_cell_cfg_nr_t phy_cell; // already contains all PHY-related parameters (i.e. RF port, PCI, etc.) - uint32_t tac; // Tracking area code - uint32_t dl_arfcn; // DL freq already included in phy_cell - uint32_t ul_arfcn; // UL freq also in phy_cell - uint32_t dl_absolute_freq_point_a; // derived from DL ARFCN - uint32_t ul_absolute_freq_point_a; // derived from UL ARFCN - uint32_t ssb_absolute_freq_point; // derived from DL ARFCN - uint32_t band; - srsran_duplex_mode_t duplex_mode; - srsran_ssb_cfg_t ssb_cfg; -}; - -typedef std::vector rrc_cell_list_nr_t; - } // namespace srsenb #endif // SRSRAN_GNB_RRC_NR_INTERFACES_H diff --git a/lib/include/srsran/rrc/nr/rrc_nr_cfg_utils.h b/lib/include/srsran/rrc/nr/rrc_nr_cfg_utils.h new file mode 100644 index 000000000..003ed238f --- /dev/null +++ b/lib/include/srsran/rrc/nr/rrc_nr_cfg_utils.h @@ -0,0 +1,43 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_RRC_NR_CFG_UTILS_H +#define SRSRAN_RRC_NR_CFG_UTILS_H + +#include "srsran/asn1/rrc_nr.h" +#include "srsran/interfaces/gnb_rrc_nr_interfaces.h" + +namespace srsran { + +struct basic_cell_args_t { + uint32_t cell_id = 0x19B01; + uint32_t nof_prbs = 52; + uint32_t scs = 15; + bool is_standalone = true; + bool is_fdd = true; + std::string plmn = "90170"; + uint32_t tac = 7; +}; + +void generate_default_pdcch_cfg_common(asn1::rrc_nr::pdcch_cfg_common_s& cfg, const basic_cell_args_t& args = {}); +void generate_default_init_dl_bwp(asn1::rrc_nr::bwp_dl_common_s& cfg, const basic_cell_args_t& args = {}); +void generate_default_dl_cfg_common(asn1::rrc_nr::dl_cfg_common_s& cfg, const basic_cell_args_t& args = {}); + +void generate_default_mib(const basic_cell_args_t& args, asn1::rrc_nr::mib_s& cfg); + +void generate_default_serv_cell_cfg_common_sib(const basic_cell_args_t& args, + asn1::rrc_nr::serving_cell_cfg_common_sib_s& cfg); +void generate_default_sib1(const basic_cell_args_t& args, asn1::rrc_nr::sib1_s& cfg); + +} // namespace srsran + +#endif // SRSRAN_RRC_NR_CFG_UTILS_H diff --git a/lib/src/CMakeLists.txt b/lib/src/CMakeLists.txt index d6bb50635..603cb6f0b 100644 --- a/lib/src/CMakeLists.txt +++ b/lib/src/CMakeLists.txt @@ -11,6 +11,7 @@ add_subdirectory(common) add_subdirectory(mac) add_subdirectory(phy) add_subdirectory(radio) +add_subdirectory(rrc) add_subdirectory(rlc) add_subdirectory(pdcp) add_subdirectory(gtpu) diff --git a/lib/src/rrc/CMakeLists.txt b/lib/src/rrc/CMakeLists.txt new file mode 100644 index 000000000..4eceb4106 --- /dev/null +++ b/lib/src/rrc/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# 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. +# + +set(SOURCES nr/rrc_nr_cfg_utils.cc) +add_library(srsran_rrc_nr STATIC ${SOURCES}) diff --git a/lib/src/rrc/nr/rrc_nr_cfg_utils.cc b/lib/src/rrc/nr/rrc_nr_cfg_utils.cc new file mode 100644 index 000000000..205ac9ba9 --- /dev/null +++ b/lib/src/rrc/nr/rrc_nr_cfg_utils.cc @@ -0,0 +1,239 @@ +/** + * + * \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/rrc/nr/rrc_nr_cfg_utils.h" +#include "srsran/asn1/rrc_nr.h" +#include "srsran/asn1/rrc_nr_utils.h" + +using namespace asn1::rrc_nr; + +namespace srsran { + +void generate_default_pdcch_cfg_common(const basic_cell_args_t& args, pdcch_cfg_common_s& cfg) +{ + cfg.ctrl_res_set_zero_present = true; + cfg.ctrl_res_set_zero = 0; + cfg.common_ctrl_res_set_present = false; + + cfg.search_space_zero_present = true; + cfg.search_space_zero = 0; + + cfg.common_search_space_list_present = true; + cfg.common_search_space_list.resize(1); + search_space_s& ss = cfg.common_search_space_list[0]; + ss.search_space_id = 1; + ss.ctrl_res_set_id_present = true; + ss.ctrl_res_set_id = 0; + ss.monitoring_slot_periodicity_and_offset_present = true; + ss.monitoring_slot_periodicity_and_offset.set_sl1(); + ss.monitoring_symbols_within_slot_present = true; + ss.monitoring_symbols_within_slot.from_number(0x2000); + ss.nrof_candidates_present = true; + ss.nrof_candidates.aggregation_level1.value = search_space_s::nrof_candidates_s_::aggregation_level1_opts::n0; + ss.nrof_candidates.aggregation_level2.value = search_space_s::nrof_candidates_s_::aggregation_level2_opts::n0; + ss.nrof_candidates.aggregation_level4.value = search_space_s::nrof_candidates_s_::aggregation_level4_opts::n1; + ss.nrof_candidates.aggregation_level8.value = search_space_s::nrof_candidates_s_::aggregation_level8_opts::n0; + ss.nrof_candidates.aggregation_level16.value = search_space_s::nrof_candidates_s_::aggregation_level16_opts::n0; + ss.search_space_type_present = true; + auto& common = ss.search_space_type.set_common(); + common.dci_format0_minus0_and_format1_minus0_present = true; + + cfg.search_space_sib1_present = true; + cfg.search_space_sib1 = 0; + cfg.search_space_other_sys_info_present = true; + cfg.search_space_other_sys_info = 1; + cfg.paging_search_space_present = true; + cfg.paging_search_space = 1; + cfg.ra_search_space_present = true; + cfg.ra_search_space = 1; +} + +void generate_default_pdsch_cfg_common(const basic_cell_args_t& args, pdsch_cfg_common_s& cfg) +{ + cfg.pdsch_time_domain_alloc_list_present = true; + cfg.pdsch_time_domain_alloc_list.resize(1); + cfg.pdsch_time_domain_alloc_list[0].map_type.value = pdsch_time_domain_res_alloc_s::map_type_opts::type_a; + cfg.pdsch_time_domain_alloc_list[0].start_symbol_and_len = 40; +} + +void generate_default_init_dl_bwp(const basic_cell_args_t& args, bwp_dl_common_s& cfg) +{ + cfg.generic_params.location_and_bw = 14025; + asn1::number_to_enum(cfg.generic_params.subcarrier_spacing, args.scs); + + cfg.pdcch_cfg_common_present = true; + generate_default_pdcch_cfg_common(args, cfg.pdcch_cfg_common.set_setup()); + cfg.pdsch_cfg_common_present = true; + generate_default_pdsch_cfg_common(args, cfg.pdsch_cfg_common.set_setup()); +} + +void generate_default_dl_cfg_common(dl_cfg_common_s& cfg, const basic_cell_args_t& args) +{ + cfg.init_dl_bwp_present = true; + generate_default_init_dl_bwp(args, cfg.init_dl_bwp); +} + +void generate_default_dl_cfg_common_sib(const basic_cell_args_t& args, dl_cfg_common_sib_s& cfg) +{ + cfg.freq_info_dl.freq_band_list.resize(1); + cfg.freq_info_dl.freq_band_list[0].freq_band_ind_nr_present = true; + cfg.freq_info_dl.freq_band_list[0].freq_band_ind_nr = 20; + cfg.freq_info_dl.offset_to_point_a = 24; + cfg.freq_info_dl.scs_specific_carrier_list.resize(1); + cfg.freq_info_dl.scs_specific_carrier_list[0].offset_to_carrier = 0; + asn1::number_to_enum(cfg.freq_info_dl.scs_specific_carrier_list[0].subcarrier_spacing, args.scs); + cfg.freq_info_dl.scs_specific_carrier_list[0].carrier_bw = args.nof_prbs; + + generate_default_init_dl_bwp(args, cfg.init_dl_bwp); + // disable InitialBWP-Only fields + cfg.init_dl_bwp.pdcch_cfg_common.setup().ctrl_res_set_zero_present = false; + cfg.init_dl_bwp.pdcch_cfg_common.setup().search_space_zero_present = false; + + cfg.bcch_cfg.mod_period_coeff.value = bcch_cfg_s::mod_period_coeff_opts::n4; + + cfg.pcch_cfg.default_paging_cycle.value = paging_cycle_opts::rf128; + cfg.pcch_cfg.nand_paging_frame_offset.set_one_t(); + cfg.pcch_cfg.ns.value = pcch_cfg_s::ns_opts::one; +} + +void generate_default_rach_cfg_common(const basic_cell_args_t& args, rach_cfg_common_s& cfg) +{ + cfg.rach_cfg_generic.prach_cfg_idx = 16; + cfg.rach_cfg_generic.msg1_fdm.value = rach_cfg_generic_s::msg1_fdm_opts::one; + cfg.rach_cfg_generic.msg1_freq_start = 0; + cfg.rach_cfg_generic.zero_correlation_zone_cfg = 15; + cfg.rach_cfg_generic.preamb_rx_target_pwr = -110; + cfg.rach_cfg_generic.preamb_trans_max.value = rach_cfg_generic_s::preamb_trans_max_opts::n7; + cfg.rach_cfg_generic.pwr_ramp_step.value = rach_cfg_generic_s::pwr_ramp_step_opts::db4; + cfg.rach_cfg_generic.ra_resp_win.value = rach_cfg_generic_s::ra_resp_win_opts::sl10; + cfg.ssb_per_rach_occasion_and_cb_preambs_per_ssb_present = true; + cfg.ssb_per_rach_occasion_and_cb_preambs_per_ssb.set_one().value = + rach_cfg_common_s::ssb_per_rach_occasion_and_cb_preambs_per_ssb_c_::one_opts::n8; + cfg.ra_contention_resolution_timer.value = rach_cfg_common_s::ra_contention_resolution_timer_opts::sf64; + cfg.prach_root_seq_idx.set_l839() = 1; + cfg.restricted_set_cfg.value = rach_cfg_common_s::restricted_set_cfg_opts::unrestricted_set; +} + +void generate_default_ul_cfg_common_sib(const basic_cell_args_t& args, ul_cfg_common_sib_s& cfg) +{ + cfg.freq_info_ul.scs_specific_carrier_list.resize(1); + cfg.freq_info_ul.scs_specific_carrier_list[0].offset_to_carrier = 0; + asn1::number_to_enum(cfg.freq_info_ul.scs_specific_carrier_list[0].subcarrier_spacing, args.scs); + cfg.freq_info_ul.scs_specific_carrier_list[0].carrier_bw = args.nof_prbs; + + cfg.init_ul_bwp.generic_params.location_and_bw = 14025; + asn1::number_to_enum(cfg.init_ul_bwp.generic_params.subcarrier_spacing, args.scs); + + cfg.init_ul_bwp.rach_cfg_common_present = true; + generate_default_rach_cfg_common(args, cfg.init_ul_bwp.rach_cfg_common.set_setup()); + + cfg.init_ul_bwp.pusch_cfg_common_present = true; + pusch_cfg_common_s& pusch = cfg.init_ul_bwp.pusch_cfg_common.set_setup(); + pusch.pusch_time_domain_alloc_list_present = true; + pusch.pusch_time_domain_alloc_list.resize(1); + pusch.pusch_time_domain_alloc_list[0].k2_present = true; + pusch.pusch_time_domain_alloc_list[0].k2 = 4; + pusch.pusch_time_domain_alloc_list[0].map_type.value = pusch_time_domain_res_alloc_s::map_type_opts::type_a; + pusch.pusch_time_domain_alloc_list[0].start_symbol_and_len = 27; + pusch.p0_nominal_with_grant_present = true; + pusch.p0_nominal_with_grant = -76; + + cfg.init_ul_bwp.pucch_cfg_common_present = true; + pucch_cfg_common_s& pucch = cfg.init_ul_bwp.pucch_cfg_common.set_setup(); + pucch.pucch_res_common_present = true; + pucch.pucch_res_common = 11; + pucch.pucch_group_hop.value = pucch_cfg_common_s::pucch_group_hop_opts::neither; + pucch.p0_nominal_present = true; + pucch.p0_nominal = -90; + + cfg.time_align_timer_common.value = time_align_timer_opts::infinity; +} + +void generate_default_serv_cell_cfg_common_sib(const basic_cell_args_t& args, serving_cell_cfg_common_sib_s& cfg) +{ + generate_default_dl_cfg_common_sib(args, cfg.dl_cfg_common); + + cfg.ul_cfg_common_present = true; + generate_default_ul_cfg_common_sib(args, cfg.ul_cfg_common); + + cfg.ssb_positions_in_burst.in_one_group.from_number(0x80); + + cfg.ssb_periodicity_serving_cell.value = serving_cell_cfg_common_sib_s::ssb_periodicity_serving_cell_opts::ms20; + + cfg.ss_pbch_block_pwr = -16; +} + +void generate_default_mib(const basic_cell_args_t& args, mib_s& cfg) +{ + asn1::number_to_enum(cfg.sub_carrier_spacing_common, args.scs); + cfg.ssb_subcarrier_offset = 0; + cfg.intra_freq_resel.value = mib_s::intra_freq_resel_opts::allowed; + cfg.cell_barred.value = mib_s::cell_barred_opts::not_barred; + cfg.pdcch_cfg_sib1.search_space_zero = 0; + cfg.pdcch_cfg_sib1.ctrl_res_set_zero = 0; + cfg.dmrs_type_a_position.value = mib_s::dmrs_type_a_position_opts::pos2; + cfg.sys_frame_num.from_number(0); +} + +void generate_default_sib1(const basic_cell_args_t& args, sib1_s& cfg) +{ + cfg.cell_sel_info_present = true; + cfg.cell_sel_info.q_rx_lev_min = -70; + cfg.cell_sel_info.q_qual_min_present = true; + cfg.cell_sel_info.q_qual_min = -20; + + cfg.cell_access_related_info.plmn_id_list.resize(1); + cfg.cell_access_related_info.plmn_id_list[0].plmn_id_list.resize(1); + srsran::plmn_id_t plmn; + plmn.from_string(args.plmn); + srsran::to_asn1(&cfg.cell_access_related_info.plmn_id_list[0].plmn_id_list[0], plmn); + cfg.cell_access_related_info.plmn_id_list[0].tac_present = true; + cfg.cell_access_related_info.plmn_id_list[0].tac.from_number(args.tac); + cfg.cell_access_related_info.plmn_id_list[0].cell_id.from_number(args.cell_id); + cfg.cell_access_related_info.plmn_id_list[0].cell_reserved_for_oper.value = + plmn_id_info_s::cell_reserved_for_oper_opts::not_reserved; + + cfg.conn_est_fail_ctrl_present = true; + cfg.conn_est_fail_ctrl.conn_est_fail_count.value = conn_est_fail_ctrl_s::conn_est_fail_count_opts::n1; + cfg.conn_est_fail_ctrl.conn_est_fail_offset_validity.value = + conn_est_fail_ctrl_s::conn_est_fail_offset_validity_opts::s30; + cfg.conn_est_fail_ctrl.conn_est_fail_offset_present = true; + cfg.conn_est_fail_ctrl.conn_est_fail_offset = 1; + + // cfg.si_sched_info_present = true; + // cfg.si_sched_info.si_request_cfg.rach_occasions_si_present = true; + // cfg.si_sched_info.si_request_cfg.rach_occasions_si.rach_cfg_si.ra_resp_win.value = + // rach_cfg_generic_s::ra_resp_win_opts::sl8; + // cfg.si_sched_info.si_win_len.value = si_sched_info_s::si_win_len_opts::s20; + // cfg.si_sched_info.sched_info_list.resize(1); + // cfg.si_sched_info.sched_info_list[0].si_broadcast_status.value = + // sched_info_s::si_broadcast_status_opts::broadcasting; cfg.si_sched_info.sched_info_list[0].si_periodicity.value = + // sched_info_s::si_periodicity_opts::rf16; cfg.si_sched_info.sched_info_list[0].sib_map_info.resize(1); + // // scheduling of SI messages + // cfg.si_sched_info.sched_info_list[0].sib_map_info[0].type.value = sib_type_info_s::type_opts::sib_type2; + // cfg.si_sched_info.sched_info_list[0].sib_map_info[0].value_tag_present = true; + // cfg.si_sched_info.sched_info_list[0].sib_map_info[0].value_tag = 0; + + cfg.serving_cell_cfg_common_present = true; + generate_default_serv_cell_cfg_common_sib(args, cfg.serving_cell_cfg_common); + + cfg.ue_timers_and_consts_present = true; + cfg.ue_timers_and_consts.t300.value = ue_timers_and_consts_s::t300_opts::ms1000; + cfg.ue_timers_and_consts.t301.value = ue_timers_and_consts_s::t301_opts::ms1000; + cfg.ue_timers_and_consts.t310.value = ue_timers_and_consts_s::t310_opts::ms1000; + cfg.ue_timers_and_consts.n310.value = ue_timers_and_consts_s::n310_opts::n1; + cfg.ue_timers_and_consts.t311.value = ue_timers_and_consts_s::t311_opts::ms30000; + cfg.ue_timers_and_consts.n311.value = ue_timers_and_consts_s::n311_opts::n1; + cfg.ue_timers_and_consts.t319.value = ue_timers_and_consts_s::t319_opts::ms1000; +} + +} // namespace srsran diff --git a/srsenb/hdr/stack/rrc/nr/cell_asn1_config.h b/srsenb/hdr/stack/rrc/nr/cell_asn1_config.h index f204cfd3b..b9a2d8f06 100644 --- a/srsenb/hdr/stack/rrc/nr/cell_asn1_config.h +++ b/srsenb/hdr/stack/rrc/nr/cell_asn1_config.h @@ -20,6 +20,9 @@ namespace srsenb { int fill_sp_cell_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, asn1::rrc_nr::sp_cell_cfg_s& sp_cell); -} +int fill_mib_from_enb_cfg(const rrc_nr_cfg_t& cfg, asn1::rrc_nr::mib_s& mib); +int fill_sib1_from_enb_cfg(const rrc_nr_cfg_t& cfg, asn1::rrc_nr::sib1_s& sib1); + +} // namespace srsenb #endif // SRSRAN_CELL_ASN1_CONFIG_H diff --git a/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h b/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h index d7cfb6284..94bc5bbe3 100644 --- a/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h +++ b/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h @@ -14,6 +14,7 @@ #define SRSRAN_RRC_CONFIG_NR_H #include "../rrc_config_common.h" +#include "srsenb/hdr/phy/phy_interfaces.h" #include "srsran/asn1/rrc_nr.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include "srsue/hdr/phy/phy_common.h" @@ -29,6 +30,22 @@ struct rrc_nr_cfg_sr_t { uint32_t nof_subframes; }; +// Cell/Sector configuration for NR cells +struct rrc_cell_cfg_nr_t { + phy_cell_cfg_nr_t phy_cell; // already contains all PHY-related parameters (i.e. RF port, PCI, etc.) + uint32_t tac; // Tracking area code + uint32_t dl_arfcn; // DL freq already included in phy_cell + uint32_t ul_arfcn; // UL freq also in phy_cell + uint32_t dl_absolute_freq_point_a; // derived from DL ARFCN + uint32_t ul_absolute_freq_point_a; // derived from UL ARFCN + uint32_t ssb_absolute_freq_point; // derived from DL ARFCN + uint32_t band; + srsran_duplex_mode_t duplex_mode; + srsran_ssb_cfg_t ssb_cfg; +}; + +typedef std::vector rrc_cell_list_nr_t; + struct rrc_nr_cfg_t { asn1::rrc_nr::mib_s mib; asn1::rrc_nr::sib1_s sib1; @@ -39,6 +56,7 @@ struct rrc_nr_cfg_t { rrc_cell_list_nr_t cell_list; asn1::rrc_nr::rach_cfg_common_s rach_cfg_common; uint16_t prach_root_seq_idx_type; + bool is_standalone; std::string log_name = "RRC-NR"; std::string log_level; diff --git a/srsenb/src/stack/rrc/CMakeLists.txt b/srsenb/src/stack/rrc/CMakeLists.txt index 6a3db8506..ef93b47a1 100644 --- a/srsenb/src/stack/rrc/CMakeLists.txt +++ b/srsenb/src/stack/rrc/CMakeLists.txt @@ -11,3 +11,4 @@ add_library(srsenb_rrc STATIC ${SOURCES}) set(SOURCES rrc_nr.cc nr/cell_asn1_config.cc) add_library(srsgnb_rrc STATIC ${SOURCES}) +target_link_libraries(srsgnb_rrc srsran_rrc_nr) diff --git a/srsenb/src/stack/rrc/nr/cell_asn1_config.cc b/srsenb/src/stack/rrc/nr/cell_asn1_config.cc index 931e211b9..09e39751b 100644 --- a/srsenb/src/stack/rrc/nr/cell_asn1_config.cc +++ b/srsenb/src/stack/rrc/nr/cell_asn1_config.cc @@ -11,6 +11,7 @@ */ #include "srsenb/hdr/stack/rrc/nr/cell_asn1_config.h" +#include "srsran/rrc/nr/rrc_nr_cfg_utils.h" #include using namespace asn1::rrc_nr; @@ -590,4 +591,22 @@ int fill_sp_cell_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, sp_cell_ return SRSRAN_SUCCESS; } +int fill_mib_from_enb_cfg(const rrc_nr_cfg_t& cfg, asn1::rrc_nr::mib_s& mib) +{ + srsran::basic_cell_args_t args; + args.scs = cfg.cell_list[0].phy_cell.carrier.scs; + srsran::generate_default_mib(args, mib); + return SRSRAN_SUCCESS; +} + +int fill_sib1_from_enb_cfg(const rrc_nr_cfg_t& cfg, asn1::rrc_nr::sib1_s& sib1) +{ + srsran::basic_cell_args_t args; + args.is_standalone = cfg.is_standalone; + args.scs = subcarrier_spacing_e{(subcarrier_spacing_opts::options)cfg.cell_list[0].phy_cell.carrier.scs}.to_number(); + args.is_fdd = cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD; + srsran::generate_default_sib1(args, sib1); + return SRSRAN_SUCCESS; +} + } // namespace srsenb From 2d6ce768c7373fe82738ea404c9fd46f1f135259 Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 4 Nov 2021 15:54:26 +0000 Subject: [PATCH 14/35] nr,gnb,rrc: generation of MIB/SIB1 inside rrc_nr class and test to verify the correct output --- srsenb/hdr/stack/mac/nr/sched_nr_interface.h | 7 ++ srsenb/hdr/stack/rrc/nr/rrc_config_nr.h | 16 ++- srsenb/hdr/stack/rrc/rrc_nr.h | 27 ++--- srsenb/src/enb_cfg_parser.cc | 2 + srsenb/src/stack/rrc/rrc_nr.cc | 106 +++++++------------ srsenb/test/common/dummy_classes_nr.h | 8 +- srsenb/test/rrc/rrc_nr_test.cc | 52 ++++++--- srsenb/test/rrc/test_helpers.cc | 2 + srsenb/test/rrc/test_helpers.h | 5 +- 9 files changed, 116 insertions(+), 109 deletions(-) diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 35230b4c8..8db73f1b0 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -50,6 +50,7 @@ class sched_nr_interface { public: static const size_t MAX_GRANTS = mac_interface_phy_nr::MAX_GRANTS; + static const size_t MAX_SIBS = 2; ///// Configuration ///// @@ -63,11 +64,17 @@ public: uint32_t numerology_idx = 0; }; + struct cell_cfg_sib_t { + uint32_t len; + uint32_t period_rf; + }; + struct cell_cfg_t { srsran_carrier_nr_t carrier = {}; srsran_duplex_config_nr_t duplex = {}; srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {}; srsran::bounded_vector bwps{1}; // idx0 for BWP-common + srsran::bounded_vector sibs; }; struct sched_args_t { diff --git a/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h b/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h index 94bc5bbe3..0dfec758f 100644 --- a/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h +++ b/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h @@ -47,16 +47,12 @@ struct rrc_cell_cfg_nr_t { typedef std::vector rrc_cell_list_nr_t; struct rrc_nr_cfg_t { - asn1::rrc_nr::mib_s mib; - asn1::rrc_nr::sib1_s sib1; - asn1::rrc_nr::sys_info_ies_s::sib_type_and_info_item_c_ sibs[ASN1_RRC_NR_MAX_SIB]; - uint32_t nof_sibs; - rrc_nr_cfg_sr_t sr_cfg; - rrc_cfg_cqi_t cqi_cfg; - rrc_cell_list_nr_t cell_list; - asn1::rrc_nr::rach_cfg_common_s rach_cfg_common; - uint16_t prach_root_seq_idx_type; - bool is_standalone; + rrc_nr_cfg_sr_t sr_cfg; + rrc_cfg_cqi_t cqi_cfg; + rrc_cell_list_nr_t cell_list; + asn1::rrc_nr::rach_cfg_common_s rach_cfg_common; + uint16_t prach_root_seq_idx_type; + bool is_standalone; std::string log_name = "RRC-NR"; std::string log_level; diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 2e8305f27..c03694ba2 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -61,12 +61,11 @@ public: void get_metrics(srsenb::rrc_metrics_t& m); - rrc_nr_cfg_t update_default_cfg(const rrc_nr_cfg_t& rrc_cfg); - void config_phy(); - void config_mac(); - int32_t generate_sibs(); - int read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) final; - int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) final; + void config_phy(); + void config_mac(); + int32_t generate_sibs(); + int read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) final; + int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) final; /// User manegement int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg); @@ -245,12 +244,16 @@ private: asn1::rrc_nr::sp_cell_cfg_s base_sp_cell_cfg; // vars - std::map > users; - bool running = false; - std::vector sib_buffer; - srsran::unique_byte_buffer_t mib_buffer = nullptr; - - uint32_t nof_si_messages = 0; + struct cell_ctxt_t { + asn1::rrc_nr::mib_s mib; + asn1::rrc_nr::sib1_s sib1; + asn1::rrc_nr::sys_info_ies_s::sib_type_and_info_l_ sibs; + srsran::unique_byte_buffer_t mib_buffer = nullptr; + std::vector sib_buffer; + }; + std::unique_ptr cell_ctxt; + std::map > users; + bool running = false; /// Private Methods void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 1e172839c..68f847d79 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1181,11 +1181,13 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr // NR cells available. if (rrc_cfg_->cell_list.size() == 0) { // SA mode. Update NGAP args + rrc_nr_cfg_->is_standalone = true; args_->nr_stack.ngap.gnb_id = args_->enb.enb_id; args_->nr_stack.ngap.cell_id = rrc_nr_cfg_->cell_list[0].phy_cell.cell_id; args_->nr_stack.ngap.tac = rrc_nr_cfg_->cell_list[0].tac; } else { // NSA mode. + rrc_nr_cfg_->is_standalone = false; // update EUTRA RRC params for ENDC rrc_cfg_->endc_cfg.abs_frequency_ssb = rrc_nr_cfg_->cell_list.at(0).ssb_absolute_freq_point; rrc_cfg_->endc_cfg.nr_band = rrc_nr_cfg_->cell_list.at(0).band; diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index 50ac298bd..0a50b9f84 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -44,8 +44,9 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, gtpu = gtpu_; rrc_eutra = rrc_eutra_; - // TODO: overwriting because we are not passing config right now - cfg = update_default_cfg(cfg_); + cfg = cfg_; + + cell_ctxt.reset(new cell_ctxt_t{}); // derived slot_dur_ms = 1; @@ -132,54 +133,6 @@ void rrc_nr::log_rrc_message(const std::string& source, } } -rrc_nr_cfg_t rrc_nr::update_default_cfg(const rrc_nr_cfg_t& current) -{ - // NOTE: This function is temporary. - rrc_nr_cfg_t cfg_default = current; - - // Fill MIB - cfg_default.mib.sub_carrier_spacing_common.value = mib_s::sub_carrier_spacing_common_opts::scs15or60; - cfg_default.mib.ssb_subcarrier_offset = 0; - cfg_default.mib.intra_freq_resel.value = mib_s::intra_freq_resel_opts::allowed; - cfg_default.mib.cell_barred.value = mib_s::cell_barred_opts::not_barred; - cfg_default.mib.pdcch_cfg_sib1.search_space_zero = 0; - cfg_default.mib.pdcch_cfg_sib1.ctrl_res_set_zero = 0; - cfg_default.mib.dmrs_type_a_position.value = mib_s::dmrs_type_a_position_opts::pos2; - cfg_default.mib.sys_frame_num.from_number(0); - - // Fill SIB1 - cfg_default.sib1.cell_access_related_info.plmn_id_list.resize(1); - cfg_default.sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list.resize(1); - srsran::plmn_id_t plmn; - plmn.from_string("90170"); - srsran::to_asn1(&cfg_default.sib1.cell_access_related_info.plmn_id_list[0].plmn_id_list[0], plmn); - cfg_default.sib1.cell_access_related_info.plmn_id_list[0].cell_id.from_number(1); - cfg_default.sib1.cell_access_related_info.plmn_id_list[0].cell_reserved_for_oper.value = - plmn_id_info_s::cell_reserved_for_oper_opts::not_reserved; - cfg_default.sib1.si_sched_info_present = true; - cfg_default.sib1.si_sched_info.si_request_cfg.rach_occasions_si_present = true; - cfg_default.sib1.si_sched_info.si_request_cfg.rach_occasions_si.rach_cfg_si.ra_resp_win.value = - rach_cfg_generic_s::ra_resp_win_opts::sl8; - cfg_default.sib1.si_sched_info.si_win_len.value = si_sched_info_s::si_win_len_opts::s20; - cfg_default.sib1.si_sched_info.sched_info_list.resize(1); - cfg_default.sib1.si_sched_info.sched_info_list[0].si_broadcast_status.value = - sched_info_s::si_broadcast_status_opts::broadcasting; - cfg_default.sib1.si_sched_info.sched_info_list[0].si_periodicity.value = sched_info_s::si_periodicity_opts::rf16; - cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info.resize(1); - // scheduling of SI messages - cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info[0].type.value = sib_type_info_s::type_opts::sib_type2; - cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info[0].value_tag_present = true; - cfg_default.sib1.si_sched_info.sched_info_list[0].sib_map_info[0].value_tag = 0; - - // Fill SIB2+ - cfg_default.nof_sibs = 1; - sib2_s& sib2 = cfg_default.sibs[0].set_sib2(); - sib2.cell_resel_info_common.q_hyst.value = sib2_s::cell_resel_info_common_s_::q_hyst_opts::db5; - // TODO: Fill SIB2 values - - return cfg_default; -} - /* @brief PRIVATE function, gets called by sgnb_addition_request * * This function WILL NOT TRIGGER the RX MSG3 activity timer @@ -307,6 +260,17 @@ void rrc_nr::config_mac() ret2 = srsran::make_duplex_cfg_from_serv_cell(base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common, &cell.duplex); srsran_assert(ret2, "Invalid NR cell configuration."); + // Set SIB1 and SI messages + cell.sibs.resize(cell_ctxt->sib_buffer.size()); + for (uint32_t i = 0; i < cell_ctxt->sib_buffer.size(); i++) { + cell.sibs[i].len = cell_ctxt->sib_buffer[i]->N_bytes; + if (i == 0) { + cell.sibs[i].period_rf = 16; // SIB1 is always 16 rf + } else { + cell.sibs[i].period_rf = cell_ctxt->sib1.si_sched_info.sched_info_list[i - 1].si_periodicity.to_number(); + } + } + // Configure MAC/scheduler mac->cell_cfg(sched_cells_cfg); } @@ -314,9 +278,9 @@ void rrc_nr::config_mac() int32_t rrc_nr::generate_sibs() { // MIB packing + fill_mib_from_enb_cfg(cfg, cell_ctxt->mib); bcch_bch_msg_s mib_msg; - mib_s& mib = mib_msg.msg.set_mib(); - mib = cfg.mib; + mib_msg.msg.set_mib() = cell_ctxt->mib; { srsran::unique_byte_buffer_t mib_buf = srsran::make_byte_buffer(); if (mib_buf == nullptr) { @@ -330,19 +294,27 @@ int32_t rrc_nr::generate_sibs() } mib_buf->N_bytes = bref.distance_bytes(); logger.debug(mib_buf->msg, mib_buf->N_bytes, "MIB payload (%d B)", mib_buf->N_bytes); - mib_buffer = std::move(mib_buf); + cell_ctxt->mib_buffer = std::move(mib_buf); } - si_sched_info_s::sched_info_list_l_& sched_info = cfg.sib1.si_sched_info.sched_info_list; - uint32_t nof_messages = cfg.sib1.si_sched_info_present ? cfg.sib1.si_sched_info.sched_info_list.size() : 0; + // SIB1 packing + fill_sib1_from_enb_cfg(cfg, cell_ctxt->sib1); + si_sched_info_s::sched_info_list_l_& sched_info = cell_ctxt->sib1.si_sched_info.sched_info_list; + + // SI messages packing + cell_ctxt->sibs.resize(1); + sib2_s& sib2 = cell_ctxt->sibs[0].set_sib2(); + sib2.cell_resel_info_common.q_hyst.value = asn1::rrc_nr::sib2_s::cell_resel_info_common_s_::q_hyst_opts::db5; // msg is array of SI messages, each SI message msg[i] may contain multiple SIBs // all SIBs in a SI message msg[i] share the same periodicity - sib_buffer.reserve(nof_messages + 1); + const uint32_t nof_messages = + cell_ctxt->sib1.si_sched_info_present ? cell_ctxt->sib1.si_sched_info.sched_info_list.size() : 0; + cell_ctxt->sib_buffer.reserve(nof_messages + 1); asn1::dyn_array msg(nof_messages + 1); // Copy SIB1 to first SI message - msg[0].msg.set_c1().set_sib_type1() = cfg.sib1; + msg[0].msg.set_c1().set_sib_type1() = cell_ctxt->sib1; // Copy rest of SIBs for (uint32_t sched_info_elem = 0; sched_info_elem < nof_messages; sched_info_elem++) { @@ -353,27 +325,25 @@ int32_t rrc_nr::generate_sibs() for (uint32_t mapping = 0; mapping < sched_info[sched_info_elem].sib_map_info.size(); ++mapping) { uint32_t sibidx = sched_info[sched_info_elem].sib_map_info[mapping].type; // SIB2 == 0 - sib_list.push_back(cfg.sibs[sibidx]); + sib_list.push_back(cell_ctxt->sibs[sibidx]); } } // Pack payload for all messages for (uint32_t msg_index = 0; msg_index < nof_messages + 1; msg_index++) { - srsran::unique_byte_buffer_t sib = pack_into_pdu(msg[msg_index]); - if (sib == nullptr) { + srsran::unique_byte_buffer_t sib_pdu = pack_into_pdu(msg[msg_index]); + if (sib_pdu == nullptr) { logger.error("Failed to pack SIB"); return SRSRAN_ERROR; } - sib_buffer.push_back(std::move(sib)); + cell_ctxt->sib_buffer.push_back(std::move(sib_pdu)); // Log SIBs in JSON format fmt::memory_buffer strbuf; fmt::format_to(strbuf, "SI message={} payload", msg_index); - log_rrc_message(fmt::to_string(strbuf), Tx, *sib_buffer.back().get(), msg[msg_index], ""); + log_rrc_message(fmt::to_string(strbuf), Tx, *cell_ctxt->sib_buffer.back(), msg[msg_index], ""); } - nof_si_messages = sib_buffer.size() - 1; - return SRSRAN_SUCCESS; } @@ -383,21 +353,21 @@ int32_t rrc_nr::generate_sibs() int rrc_nr::read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) { - if (mib_buffer == nullptr || buffer.get_tailroom() < mib_buffer->N_bytes) { + if (cell_ctxt->mib_buffer == nullptr || buffer.get_tailroom() < cell_ctxt->mib_buffer->N_bytes) { return SRSRAN_ERROR; } - buffer = *mib_buffer; + buffer = *cell_ctxt->mib_buffer; return SRSRAN_SUCCESS; } int rrc_nr::read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) { - if (sib_index >= sib_buffer.size()) { + if (sib_index >= cell_ctxt->sib_buffer.size()) { logger.error("SIB %d is not a configured SIB.", sib_index); return SRSRAN_ERROR; } - buffer = *sib_buffer[sib_index]; + buffer = *cell_ctxt->sib_buffer[sib_index]; return SRSRAN_SUCCESS; } diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsenb/test/common/dummy_classes_nr.h index 362946324..76ba164c6 100644 --- a/srsenb/test/common/dummy_classes_nr.h +++ b/srsenb/test/common/dummy_classes_nr.h @@ -39,14 +39,18 @@ public: class mac_nr_dummy : public mac_interface_rrc_nr { public: - int cell_cfg(const std::vector& nr_cells) override { return SRSRAN_SUCCESS; } + int cell_cfg(const std::vector& nr_cells_) override + { + nr_cells = nr_cells_; + return SRSRAN_SUCCESS; + } uint16_t reserve_rnti(uint32_t enb_cc_idx, const sched_nr_ue_cfg_t& uecfg) override { return 0x4601; } int ue_cfg(uint16_t rnti, const sched_nr_interface::ue_cfg_t& ue_cfg) override { return SRSRAN_SUCCESS; } int remove_ue(uint16_t rnti) override { return SRSRAN_SUCCESS; } - srsenb::sched_interface::cell_cfg_t cellcfgobj; + std::vector nr_cells; }; class phy_nr_dummy : public phy_interface_stack_nr diff --git a/srsenb/test/rrc/rrc_nr_test.cc b/srsenb/test/rrc/rrc_nr_test.cc index 8f012f556..a7a024955 100644 --- a/srsenb/test/rrc/rrc_nr_test.cc +++ b/srsenb/test/rrc/rrc_nr_test.cc @@ -41,27 +41,51 @@ int test_sib_generation() { srsran::task_scheduler task_sched; + phy_nr_dummy phy_obj; mac_nr_dummy mac_obj; rlc_dummy rlc_obj; pdcp_dummy pdcp_obj; rrc_nr rrc_obj(&task_sched); // set cfg - rrc_nr_cfg_t default_cfg = {}; - rrc_nr_cfg_t rrc_cfg = rrc_obj.update_default_cfg(default_cfg); - auto& sched_elem = rrc_cfg.sib1.si_sched_info.sched_info_list[0]; + all_args_t args{}; + phy_cfg_t phy_cfg{}; + rrc_nr_cfg_t rrc_cfg_nr = {}; + rrc_cfg_nr.cell_list.emplace_back(); + rrc_cfg_nr.cell_list[0].phy_cell.carrier.pci = 500; + rrc_cfg_nr.cell_list[0].dl_arfcn = 634240; + rrc_cfg_nr.cell_list[0].band = 78; + rrc_cfg_nr.is_standalone = true; + args.enb.n_prb = 50; + enb_conf_sections::set_derived_args_nr(&args, &rrc_cfg_nr, &phy_cfg); - TESTASSERT(rrc_obj.init(rrc_cfg, nullptr, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) == + TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) == SRSRAN_SUCCESS); - TESTASSERT(test_cell_cfg(mac_obj.cellcfgobj) == SRSRAN_SUCCESS); - // TEMP tests - TESTASSERT(mac_obj.cellcfgobj.sibs[1].len > 0); - TESTASSERT(mac_obj.cellcfgobj.sibs[1].period_rf == sched_elem.si_periodicity.to_number()); - for (int i = 2; i < 16; ++i) { - TESTASSERT(mac_obj.cellcfgobj.sibs[i].len == 0); + const sched_nr_interface::cell_cfg_t& nrcell = mac_obj.nr_cells.at(0); + + TESTASSERT(nrcell.sibs.size() > 0); + + // TEST SIB1 + TESTASSERT(nrcell.sibs[0].len > 0); + TESTASSERT_EQ(16, nrcell.sibs[0].period_rf); + + srsran::unique_byte_buffer_t pdu = srsran::make_byte_buffer(); + TESTASSERT_EQ(SRSRAN_SUCCESS, rrc_obj.read_pdu_bcch_dlsch(0, *pdu)); + TESTASSERT(pdu->size() > 0); + asn1::rrc_nr::bcch_dl_sch_msg_s msg; + { + asn1::cbit_ref bref{pdu->data(), pdu->size()}; + TESTASSERT_EQ(SRSRAN_SUCCESS, msg.unpack(bref)); } - TESTASSERT(mac_obj.cellcfgobj.cell.nof_prb == 25); + TESTASSERT_EQ(bcch_dl_sch_msg_type_c::types_opts::c1, msg.msg.type().value); + TESTASSERT_EQ(bcch_dl_sch_msg_type_c::c1_c_::types_opts::sib_type1, msg.msg.c1().type().value); + asn1::rrc_nr::sib1_s& sib1 = msg.msg.c1().sib_type1(); + TESTASSERT(sib1.serving_cell_cfg_common_present); + + pdcch_cfg_common_s& pdcch = sib1.serving_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); + TESTASSERT(not pdcch.ctrl_res_set_zero_present); // CORESET#0 id is passed in MIB + TESTASSERT(not pdcch.search_space_zero_present); // SS#0 id is passed in MIB return SRSRAN_SUCCESS; } @@ -79,11 +103,12 @@ int test_rrc_setup() // set cfg all_args_t args{}; phy_cfg_t phy_cfg{}; - rrc_nr_cfg_t rrc_cfg_nr = rrc_obj.update_default_cfg(rrc_nr_cfg_t{}); + rrc_nr_cfg_t rrc_cfg_nr = rrc_nr_cfg_t{}; rrc_cfg_nr.cell_list.emplace_back(); rrc_cfg_nr.cell_list[0].phy_cell.carrier.pci = 500; rrc_cfg_nr.cell_list[0].dl_arfcn = 634240; rrc_cfg_nr.cell_list[0].band = 78; + rrc_cfg_nr.is_standalone = false; args.enb.n_prb = 50; enb_conf_sections::set_derived_args_nr(&args, &rrc_cfg_nr, &phy_cfg); TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, nullptr, nullptr, nullptr) == @@ -115,8 +140,7 @@ int main(int argc, char** argv) } argparse::parse_args(argc, argv); - // FIXME: disabled temporarily until SIB generation is fixed - // TESTASSERT(srsenb::test_sib_generation() == SRSRAN_SUCCESS); + TESTASSERT(srsenb::test_sib_generation() == SRSRAN_SUCCESS); TESTASSERT(srsenb::test_rrc_setup() == SRSRAN_SUCCESS); return SRSRAN_SUCCESS; diff --git a/srsenb/test/rrc/test_helpers.cc b/srsenb/test/rrc/test_helpers.cc index e9756c188..2987cb2bd 100644 --- a/srsenb/test/rrc/test_helpers.cc +++ b/srsenb/test/rrc/test_helpers.cc @@ -14,6 +14,8 @@ #include "srsenb/hdr/enb.h" #include "srsran/common/test_common.h" +using namespace asn1::rrc; + namespace argparse { std::string repository_dir; diff --git a/srsenb/test/rrc/test_helpers.h b/srsenb/test/rrc/test_helpers.h index c315fbe7a..03a164a27 100644 --- a/srsenb/test/rrc/test_helpers.h +++ b/srsenb/test/rrc/test_helpers.h @@ -19,7 +19,6 @@ #include "srsran/adt/span.h" using namespace srsenb; -using namespace asn1::rrc; namespace argparse { @@ -229,9 +228,9 @@ namespace srsenb { meas_cell_cfg_t generate_cell1(); -report_cfg_eutra_s generate_rep1(); +asn1::rrc::report_cfg_eutra_s generate_rep1(); -bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cell); +bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const asn1::rrc::cells_to_add_mod_s& cell); } // namespace srsenb From 951fea5f6145cb48a061af0187315fda0cc407e3 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 5 Nov 2021 12:18:14 +0100 Subject: [PATCH 15/35] bearer_manager,rlc: reduce log level of message to warning level relevant for the UE when it receives 2nd reconfiguration it could be that the bearers are added again. in this case the handling is fine and everything will work as expected. No reason to log error. --- lib/src/common/bearer_manager.cc | 2 +- lib/src/rlc/rlc.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/common/bearer_manager.cc b/lib/src/common/bearer_manager.cc index 773a3b5a0..3114a0c5e 100644 --- a/lib/src/common/bearer_manager.cc +++ b/lib/src/common/bearer_manager.cc @@ -86,7 +86,7 @@ void ue_bearer_manager::add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat logger.info( "Bearers: Registered EPS bearer ID %d for lcid=%d over %s-PDCP", eps_bearer_id, lcid, to_string(rat).c_str()); } else { - logger.error("Bearers: EPS bearer ID %d already registered", eps_bearer_id); + logger.warning("Bearers: EPS bearer ID %d already registered", eps_bearer_id); } } diff --git a/lib/src/rlc/rlc.cc b/lib/src/rlc/rlc.cc index 624145116..f0243882e 100644 --- a/lib/src/rlc/rlc.cc +++ b/lib/src/rlc/rlc.cc @@ -383,7 +383,7 @@ int rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg) rwlock_write_guard lock(rwlock); if (valid_lcid(lcid)) { - logger.error("LCID %d already exists", lcid); + logger.warning("LCID %d already exists", lcid); return SRSRAN_ERROR; } From 0967cda042e3a82d4bbfb9920970be7fcd1e4b62 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 5 Nov 2021 14:23:00 +0100 Subject: [PATCH 16/35] gnb,stack: move gNB components into own folder * move RRC, MAC, NGAP, SDAP into gnb folder * move testing code below respective layers --- CMakeLists.txt | 7 ++++--- .../srsran/interfaces/gnb_mac_interfaces.h | 2 +- srsenb/hdr/enb.h | 2 +- srsenb/hdr/x2_adapter.h | 2 +- srsenb/src/CMakeLists.txt | 2 +- srsenb/src/enb.cc | 2 +- srsenb/src/stack/CMakeLists.txt | 7 +------ srsenb/src/stack/mac/CMakeLists.txt | 4 +--- srsenb/src/stack/rrc/CMakeLists.txt | 5 +---- srsenb/src/stack/upper/CMakeLists.txt | 5 +---- srsenb/test/CMakeLists.txt | 1 - srsenb/test/mac/CMakeLists.txt | 4 +--- srsenb/test/rrc/CMakeLists.txt | 4 ---- srsgnb/CMakeLists.txt | 9 +++++++++ {srsenb => srsgnb}/hdr/stack/gnb_stack_nr.h | 12 ++++++------ .../hdr/stack/mac}/harq_softbuffer.h | 0 .../mac/nr => srsgnb/hdr/stack/mac}/mac_nr.h | 2 +- .../mac/nr => srsgnb/hdr/stack/mac}/sched_nr.h | 0 .../nr => srsgnb/hdr/stack/mac}/sched_nr_bwp.h | 0 .../nr => srsgnb/hdr/stack/mac}/sched_nr_cfg.h | 0 .../hdr/stack/mac}/sched_nr_grant_allocator.h | 2 +- .../hdr/stack/mac}/sched_nr_harq.h | 2 +- .../hdr/stack/mac}/sched_nr_helpers.h | 0 .../hdr/stack/mac}/sched_nr_interface.h | 0 .../hdr/stack/mac}/sched_nr_pdcch.h | 2 +- .../nr => srsgnb/hdr/stack/mac}/sched_nr_rb.h | 2 +- .../hdr/stack/mac}/sched_nr_signalling.h | 0 .../hdr/stack/mac}/sched_nr_time_rr.h | 0 .../nr => srsgnb/hdr/stack/mac}/sched_nr_ue.h | 0 .../hdr/stack/mac}/sched_nr_worker.h | 0 .../mac/nr => srsgnb/hdr/stack/mac}/ue_nr.h | 2 +- {srsenb => srsgnb}/hdr/stack/ngap/ngap.h | 0 .../hdr/stack/ngap/ngap_interfaces.h | 0 .../hdr/stack/ngap/ngap_metrics.h | 0 {srsenb => srsgnb}/hdr/stack/ngap/ngap_ue.h | 0 .../hdr/stack/ngap/ngap_ue_bearer_manager.h | 0 .../hdr/stack/ngap/ngap_ue_proc.h | 2 +- .../hdr/stack/ngap/ngap_ue_utils.h | 0 .../hdr/stack/rrc}/cell_asn1_config.h | 0 .../hdr/stack/rrc}/rrc_config_nr.h | 2 +- {srsenb => srsgnb}/hdr/stack/rrc/rrc_nr.h | 6 +++--- .../upper => srsgnb/hdr/stack/sdap}/sdap.h | 0 srsgnb/src/CMakeLists.txt | 9 +++++++++ srsgnb/src/stack/CMakeLists.txt | 18 ++++++++++++++++++ {srsenb => srsgnb}/src/stack/gnb_stack_nr.cc | 4 ++-- .../nr => srsgnb/src/stack/mac}/CMakeLists.txt | 3 +++ .../src/stack/mac}/harq_softbuffer.cc | 2 +- .../mac/nr => srsgnb/src/stack/mac}/mac_nr.cc | 4 ++-- .../nr => srsgnb/src/stack/mac}/sched_nr.cc | 8 ++++---- .../src/stack/mac}/sched_nr_bwp.cc | 2 +- .../src/stack/mac}/sched_nr_cfg.cc | 4 ++-- .../src/stack/mac}/sched_nr_grant_allocator.cc | 6 +++--- .../src/stack/mac}/sched_nr_harq.cc | 2 +- .../src/stack/mac}/sched_nr_helpers.cc | 8 ++++---- .../src/stack/mac}/sched_nr_pdcch.cc | 2 +- .../nr => srsgnb/src/stack/mac}/sched_nr_rb.cc | 2 +- .../src/stack/mac}/sched_nr_signalling.cc | 2 +- .../src/stack/mac}/sched_nr_time_rr.cc | 2 +- .../nr => srsgnb/src/stack/mac}/sched_nr_ue.cc | 4 ++-- .../src/stack/mac}/sched_nr_worker.cc | 4 ++-- .../src/stack/mac/test}/CMakeLists.txt | 0 .../stack/mac/test}/sched_nr_cfg_generators.h | 2 +- .../stack/mac/test}/sched_nr_common_test.cc | 2 +- .../src/stack/mac/test}/sched_nr_common_test.h | 2 +- .../src/stack/mac/test}/sched_nr_prb_test.cc | 2 +- .../src/stack/mac/test}/sched_nr_rar_test.cc | 2 +- .../src/stack/mac/test}/sched_nr_sim_ue.cc | 0 .../src/stack/mac/test}/sched_nr_sim_ue.h | 4 ++-- .../src/stack/mac/test}/sched_nr_test.cc | 0 .../mac/test}/sched_nr_ue_ded_test_suite.cc | 2 +- .../mac/test}/sched_nr_ue_ded_test_suite.h | 0 .../mac/nr => srsgnb/src/stack/mac}/ue_nr.cc | 2 +- .../src/stack/ngap/CMakeLists.txt | 0 {srsenb => srsgnb}/src/stack/ngap/ngap.cc | 4 ++-- {srsenb => srsgnb}/src/stack/ngap/ngap_ue.cc | 6 +++--- .../src/stack/ngap/ngap_ue_bearer_manager.cc | 2 +- .../src/stack/ngap/ngap_ue_proc.cc | 2 +- .../src/stack/ngap/test}/CMakeLists.txt | 0 .../src/stack/ngap/test}/ngap_test.cc | 0 srsgnb/src/stack/rrc/CMakeLists.txt | 15 +++++++++++++++ .../src/stack/rrc}/cell_asn1_config.cc | 2 +- {srsenb => srsgnb}/src/stack/rrc/rrc_nr.cc | 6 +++--- srsgnb/src/stack/rrc/test/CMakeLists.txt | 11 +++++++++++ .../src/stack/rrc/test}/rrc_nr_test.cc | 2 +- srsgnb/src/stack/sdap/CMakeLists.txt | 10 ++++++++++ .../upper => srsgnb/src/stack/sdap}/sdap.cc | 2 +- test/phy/dummy_gnb_stack.h | 6 +++--- 87 files changed, 159 insertions(+), 103 deletions(-) create mode 100644 srsgnb/CMakeLists.txt rename {srsenb => srsgnb}/hdr/stack/gnb_stack_nr.h (95%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/harq_softbuffer.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/mac_nr.h (99%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_bwp.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_cfg.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_grant_allocator.h (98%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_harq.h (98%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_helpers.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_interface.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_pdcch.h (98%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_rb.h (99%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_signalling.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_time_rr.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_ue.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/sched_nr_worker.h (100%) rename {srsenb/hdr/stack/mac/nr => srsgnb/hdr/stack/mac}/ue_nr.h (98%) rename {srsenb => srsgnb}/hdr/stack/ngap/ngap.h (100%) rename {srsenb => srsgnb}/hdr/stack/ngap/ngap_interfaces.h (100%) rename {srsenb => srsgnb}/hdr/stack/ngap/ngap_metrics.h (100%) rename {srsenb => srsgnb}/hdr/stack/ngap/ngap_ue.h (100%) rename {srsenb => srsgnb}/hdr/stack/ngap/ngap_ue_bearer_manager.h (100%) rename {srsenb => srsgnb}/hdr/stack/ngap/ngap_ue_proc.h (98%) rename {srsenb => srsgnb}/hdr/stack/ngap/ngap_ue_utils.h (100%) rename {srsenb/hdr/stack/rrc/nr => srsgnb/hdr/stack/rrc}/cell_asn1_config.h (100%) rename {srsenb/hdr/stack/rrc/nr => srsgnb/hdr/stack/rrc}/rrc_config_nr.h (97%) rename {srsenb => srsgnb}/hdr/stack/rrc/rrc_nr.h (98%) rename {srsenb/hdr/stack/upper => srsgnb/hdr/stack/sdap}/sdap.h (100%) create mode 100644 srsgnb/src/CMakeLists.txt create mode 100644 srsgnb/src/stack/CMakeLists.txt rename {srsenb => srsgnb}/src/stack/gnb_stack_nr.cc (98%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/CMakeLists.txt (91%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/harq_softbuffer.cc (97%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/mac_nr.cc (99%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr.cc (98%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_bwp.cc (99%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_cfg.cc (97%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_grant_allocator.cc (98%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_harq.cc (98%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_helpers.cc (97%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_pdcch.cc (99%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_rb.cc (98%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_signalling.cc (98%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_time_rr.cc (97%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_ue.cc (97%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/sched_nr_worker.cc (98%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/CMakeLists.txt (100%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_cfg_generators.h (98%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_common_test.cc (98%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_common_test.h (95%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_prb_test.cc (98%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_rar_test.cc (98%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_sim_ue.cc (100%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_sim_ue.h (98%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_test.cc (100%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_ue_ded_test_suite.cc (96%) rename {srsenb/test/mac/nr => srsgnb/src/stack/mac/test}/sched_nr_ue_ded_test_suite.h (100%) rename {srsenb/src/stack/mac/nr => srsgnb/src/stack/mac}/ue_nr.cc (99%) rename {srsenb => srsgnb}/src/stack/ngap/CMakeLists.txt (100%) rename {srsenb => srsgnb}/src/stack/ngap/ngap.cc (99%) rename {srsenb => srsgnb}/src/stack/ngap/ngap_ue.cc (98%) rename {srsenb => srsgnb}/src/stack/ngap/ngap_ue_bearer_manager.cc (98%) rename {srsenb => srsgnb}/src/stack/ngap/ngap_ue_proc.cc (99%) rename {srsenb/test/ngap => srsgnb/src/stack/ngap/test}/CMakeLists.txt (100%) rename {srsenb/test/ngap => srsgnb/src/stack/ngap/test}/ngap_test.cc (100%) create mode 100644 srsgnb/src/stack/rrc/CMakeLists.txt rename {srsenb/src/stack/rrc/nr => srsgnb/src/stack/rrc}/cell_asn1_config.cc (99%) rename {srsenb => srsgnb}/src/stack/rrc/rrc_nr.cc (99%) create mode 100644 srsgnb/src/stack/rrc/test/CMakeLists.txt rename {srsenb/test/rrc => srsgnb/src/stack/rrc/test}/rrc_nr_test.cc (99%) create mode 100644 srsgnb/src/stack/sdap/CMakeLists.txt rename {srsenb/src/stack/upper => srsgnb/src/stack/sdap}/sdap.cc (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0eb8df40e..49870cec0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -658,13 +658,14 @@ if(RF_FOUND) endif(ENABLE_SRSUE) if(ENABLE_SRSENB) - message(STATUS "Building with srsENB") + message(STATUS "Building with srsENB/srsGNB") add_subdirectory(srsenb) + add_subdirectory(srsgnb) else(ENABLE_SRSENB) - message(STATUS "srsENB build disabled") + message(STATUS "srsENB/srsGNB build disabled") endif(ENABLE_SRSENB) else(RF_FOUND) - message(STATUS "srsUE and srsENB builds disabled due to missing RF driver") + message(STATUS "srsUE and srsENB/srsGNB builds disabled due to missing RF driver") endif(RF_FOUND) if(ENABLE_SRSEPC) diff --git a/lib/include/srsran/interfaces/gnb_mac_interfaces.h b/lib/include/srsran/interfaces/gnb_mac_interfaces.h index bd1f29136..e25f3953a 100644 --- a/lib/include/srsran/interfaces/gnb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_mac_interfaces.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_GNB_MAC_INTERFACES_H #define SRSRAN_GNB_MAC_INTERFACES_H -#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" +#include "srsgnb/hdr/stack/mac/sched_nr_interface.h" namespace srsenb { diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 0edb56925..44ceac557 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -31,8 +31,8 @@ #include "srsenb/hdr/stack/enb_stack_base.h" #include "srsenb/hdr/stack/rrc/rrc_config.h" -#include "srsenb/hdr/stack/gnb_stack_nr.h" #include "srsenb/hdr/stack/mac/sched_interface.h" +#include "srsgnb/hdr/stack/gnb_stack_nr.h" #include "srsran/common/bcd_helpers.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/interfaces_common.h" diff --git a/srsenb/hdr/x2_adapter.h b/srsenb/hdr/x2_adapter.h index ee6eb10c7..2c4f5becf 100644 --- a/srsenb/hdr/x2_adapter.h +++ b/srsenb/hdr/x2_adapter.h @@ -30,9 +30,9 @@ #ifndef SRSENB_X2_ADAPTER_H #define SRSENB_X2_ADAPTER_H +#include "srsgnb/hdr/stack/gnb_stack_nr.h" #include "srsran/interfaces/enb_x2_interfaces.h" #include "stack/enb_stack_lte.h" -#include "stack/gnb_stack_nr.h" namespace srsenb { diff --git a/srsenb/src/CMakeLists.txt b/srsenb/src/CMakeLists.txt index e4e26793d..ae3250670 100644 --- a/srsenb/src/CMakeLists.txt +++ b/srsenb/src/CMakeLists.txt @@ -29,7 +29,7 @@ add_executable(srsenb main.cc enb.cc metrics_stdout.cc metrics_csv.cc metrics_js set(SRSENB_SOURCES srsenb_phy srsenb_stack srsenb_common srsenb_s1ap srsenb_upper srsenb_mac srsenb_rrc srslog system) set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_gtpu srsran_rlc srsran_pdcp srsran_radio rrc_asn1 s1ap_asn1 enb_cfg_parser srslog support system) -set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_stack srsgnb_ngap srsgnb_upper srsgnb_mac srsgnb_rrc) +set(SRSENB_SOURCES ${SRSENB_SOURCES} srsgnb_stack srsgnb_ngap srsgnb_mac srsgnb_rrc) set(SRSRAN_SOURCES ${SRSRAN_SOURCES} rrc_nr_asn1 ngap_nr_asn1) target_link_libraries(srsenb ${SRSENB_SOURCES} diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 7babf6a28..215a0354e 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -12,9 +12,9 @@ #include "srsenb/hdr/enb.h" #include "srsenb/hdr/stack/enb_stack_lte.h" -#include "srsenb/hdr/stack/gnb_stack_nr.h" #include "srsenb/hdr/x2_adapter.h" #include "srsenb/src/enb_cfg_parser.h" +#include "srsgnb/hdr/stack/gnb_stack_nr.h" #include "srsran/build_info.h" #include "srsran/common/enb_events.h" #include "srsran/radio/radio_null.h" diff --git a/srsenb/src/stack/CMakeLists.txt b/srsenb/src/stack/CMakeLists.txt index d5c67cc0f..54c0d2c43 100644 --- a/srsenb/src/stack/CMakeLists.txt +++ b/srsenb/src/stack/CMakeLists.txt @@ -9,13 +9,8 @@ add_subdirectory(mac) add_subdirectory(rrc) add_subdirectory(s1ap) -add_subdirectory(ngap) add_subdirectory(upper) set(SOURCES enb_stack_lte.cc) -add_library(srsenb_stack STATIC ${SOURCES}) -target_link_libraries(srsenb_stack) - -add_library(srsgnb_stack STATIC gnb_stack_nr.cc) -target_link_libraries(srsgnb_stack srsue_upper) +add_library(srsenb_stack STATIC ${SOURCES}) \ No newline at end of file diff --git a/srsenb/src/stack/mac/CMakeLists.txt b/srsenb/src/stack/mac/CMakeLists.txt index 44bea9de7..2a08dc6ee 100644 --- a/srsenb/src/stack/mac/CMakeLists.txt +++ b/srsenb/src/stack/mac/CMakeLists.txt @@ -15,6 +15,4 @@ set(SOURCES mac.cc ue.cc sched.cc sched_carrier.cc sched_grid.cc sched_ue_ctrl/s sched_phy_ch/sf_cch_allocator.cc sched_phy_ch/sched_dci.cc sched_phy_ch/sched_phy_resource.cc sched_helpers.cc) add_library(srsenb_mac STATIC ${SOURCES} $) -target_link_libraries(srsenb_mac srsenb_mac_common) - -add_subdirectory(nr) \ No newline at end of file +target_link_libraries(srsenb_mac srsenb_mac_common) \ No newline at end of file diff --git a/srsenb/src/stack/rrc/CMakeLists.txt b/srsenb/src/stack/rrc/CMakeLists.txt index ef93b47a1..58d0cd511 100644 --- a/srsenb/src/stack/rrc/CMakeLists.txt +++ b/srsenb/src/stack/rrc/CMakeLists.txt @@ -8,7 +8,4 @@ set(SOURCES rrc.cc rrc_ue.cc rrc_mobility.cc rrc_cell_cfg.cc rrc_bearer_cfg.cc mac_controller.cc ue_rr_cfg.cc ue_meas_cfg.cc rrc_endc.cc) add_library(srsenb_rrc STATIC ${SOURCES}) - -set(SOURCES rrc_nr.cc nr/cell_asn1_config.cc) -add_library(srsgnb_rrc STATIC ${SOURCES}) -target_link_libraries(srsgnb_rrc srsran_rrc_nr) + \ No newline at end of file diff --git a/srsenb/src/stack/upper/CMakeLists.txt b/srsenb/src/stack/upper/CMakeLists.txt index 53637962a..21e1b1b4d 100644 --- a/srsenb/src/stack/upper/CMakeLists.txt +++ b/srsenb/src/stack/upper/CMakeLists.txt @@ -8,7 +8,4 @@ set(SOURCES gtpu.cc pdcp.cc rlc.cc) add_library(srsenb_upper STATIC ${SOURCES}) -target_link_libraries(srsenb_upper srsran_asn1 srsran_gtpu) - -set(SOURCES sdap.cc) -add_library(srsgnb_upper STATIC ${SOURCES}) \ No newline at end of file +target_link_libraries(srsenb_upper srsran_asn1 srsran_gtpu) \ No newline at end of file diff --git a/srsenb/test/CMakeLists.txt b/srsenb/test/CMakeLists.txt index a7d93ea1f..b648a8e05 100644 --- a/srsenb/test/CMakeLists.txt +++ b/srsenb/test/CMakeLists.txt @@ -11,7 +11,6 @@ add_subdirectory(phy) add_subdirectory(upper) add_subdirectory(rrc) add_subdirectory(s1ap) -add_subdirectory(ngap) add_executable(enb_metrics_test enb_metrics_test.cc ../src/metrics_stdout.cc ../src/metrics_csv.cc) target_link_libraries(enb_metrics_test srsran_phy srsran_common) diff --git a/srsenb/test/mac/CMakeLists.txt b/srsenb/test/mac/CMakeLists.txt index 2d3806231..ddde6de06 100644 --- a/srsenb/test/mac/CMakeLists.txt +++ b/srsenb/test/mac/CMakeLists.txt @@ -73,6 +73,4 @@ add_test(sched_cqi_test sched_cqi_test) add_executable(sched_phy_resource_test sched_phy_resource_test.cc) target_link_libraries(sched_phy_resource_test srsran_common srsenb_mac srsran_mac sched_test_common) -add_test(sched_phy_resource_test sched_phy_resource_test) - -add_subdirectory(nr) \ No newline at end of file +add_test(sched_phy_resource_test sched_phy_resource_test) \ No newline at end of file diff --git a/srsenb/test/rrc/CMakeLists.txt b/srsenb/test/rrc/CMakeLists.txt index 6861842bd..06ecb4221 100644 --- a/srsenb/test/rrc/CMakeLists.txt +++ b/srsenb/test/rrc/CMakeLists.txt @@ -9,10 +9,6 @@ add_library(test_helpers test_helpers.cc) target_link_libraries(test_helpers srsenb_rrc srsenb_common rrc_asn1 rrc_nr_asn1 s1ap_asn1 srsran_common enb_cfg_parser ${LIBCONFIGPP_LIBRARIES}) -add_executable(rrc_nr_test rrc_nr_test.cc) -target_link_libraries(rrc_nr_test srsgnb_rrc test_helpers ${ATOMIC_LIBS}) -add_test(rrc_nr_test rrc_nr_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) - add_executable(rrc_meascfg_test rrc_meascfg_test.cc) target_link_libraries(rrc_meascfg_test test_helpers ${ATOMIC_LIBS}) diff --git a/srsgnb/CMakeLists.txt b/srsgnb/CMakeLists.txt new file mode 100644 index 000000000..a3bed30f1 --- /dev/null +++ b/srsgnb/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# 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. +# + +add_subdirectory(src) \ No newline at end of file diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsgnb/hdr/stack/gnb_stack_nr.h similarity index 95% rename from srsenb/hdr/stack/gnb_stack_nr.h rename to srsgnb/hdr/stack/gnb_stack_nr.h index b35e20bbc..85d68bc1f 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsgnb/hdr/stack/gnb_stack_nr.h @@ -18,13 +18,13 @@ #ifndef SRSRAN_GNB_STACK_NR_H #define SRSRAN_GNB_STACK_NR_H -#include "srsenb/hdr/stack/mac/nr/mac_nr.h" -#include "srsenb/hdr/stack/rrc/rrc_nr.h" -#include "upper/pdcp.h" -#include "upper/rlc.h" -#include "upper/sdap.h" +#include "srsenb/hdr/stack/upper/pdcp.h" +#include "srsenb/hdr/stack/upper/rlc.h" +#include "srsgnb/hdr/stack/mac/mac_nr.h" +#include "srsgnb/hdr/stack/rrc/rrc_nr.h" +#include "srsgnb/hdr/stack/sdap/sdap.h" -#include "enb_stack_base.h" +#include "srsenb/hdr/stack/enb_stack_base.h" #include "srsran/interfaces/gnb_interfaces.h" namespace srsenb { diff --git a/srsenb/hdr/stack/mac/nr/harq_softbuffer.h b/srsgnb/hdr/stack/mac/harq_softbuffer.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/harq_softbuffer.h rename to srsgnb/hdr/stack/mac/harq_softbuffer.h diff --git a/srsenb/hdr/stack/mac/nr/mac_nr.h b/srsgnb/hdr/stack/mac/mac_nr.h similarity index 99% rename from srsenb/hdr/stack/mac/nr/mac_nr.h rename to srsgnb/hdr/stack/mac/mac_nr.h index eaecbcb4e..9306272ed 100644 --- a/srsenb/hdr/stack/mac/nr/mac_nr.h +++ b/srsgnb/hdr/stack/mac/mac_nr.h @@ -18,7 +18,7 @@ #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/stack/enb_stack_base.h" -#include "srsenb/hdr/stack/mac/nr/ue_nr.h" +#include "srsgnb/hdr/stack/mac/ue_nr.h" #include "srsran/common/task_scheduler.h" #include "srsran/interfaces/enb_metrics_interface.h" #include "srsran/interfaces/enb_rlc_interfaces.h" diff --git a/srsenb/hdr/stack/mac/nr/sched_nr.h b/srsgnb/hdr/stack/mac/sched_nr.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr.h rename to srsgnb/hdr/stack/mac/sched_nr.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_bwp.h b/srsgnb/hdr/stack/mac/sched_nr_bwp.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_bwp.h rename to srsgnb/hdr/stack/mac/sched_nr_bwp.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_cfg.h b/srsgnb/hdr/stack/mac/sched_nr_cfg.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_cfg.h rename to srsgnb/hdr/stack/mac/sched_nr_cfg.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h similarity index 98% rename from srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h rename to srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h index d1d6fb98a..8ff63de58 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h +++ b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h @@ -13,12 +13,12 @@ #ifndef SRSRAN_SCHED_NR_GRANT_ALLOCATOR_H #define SRSRAN_SCHED_NR_GRANT_ALLOCATOR_H -#include "../sched_common.h" #include "lib/include/srsran/adt/circular_array.h" #include "sched_nr_helpers.h" #include "sched_nr_interface.h" #include "sched_nr_pdcch.h" #include "sched_nr_ue.h" +#include "srsenb/hdr/stack/mac/sched_common.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h b/srsgnb/hdr/stack/mac/sched_nr_harq.h similarity index 98% rename from srsenb/hdr/stack/mac/nr/sched_nr_harq.h rename to srsgnb/hdr/stack/mac/sched_nr_harq.h index 5ab33d932..7d88a4b71 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_harq.h +++ b/srsgnb/hdr/stack/mac/sched_nr_harq.h @@ -14,7 +14,7 @@ #define SRSRAN_SCHED_NR_HARQ_H #include "sched_nr_cfg.h" -#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h" +#include "srsgnb/hdr/stack/mac/harq_softbuffer.h" #include "srsran/common/slot_point.h" #include diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_helpers.h b/srsgnb/hdr/stack/mac/sched_nr_helpers.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_helpers.h rename to srsgnb/hdr/stack/mac/sched_nr_helpers.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsgnb/hdr/stack/mac/sched_nr_interface.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_interface.h rename to srsgnb/hdr/stack/mac/sched_nr_interface.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h similarity index 98% rename from srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h rename to srsgnb/hdr/stack/mac/sched_nr_pdcch.h index 8526d9635..8e13d2608 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h +++ b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_PDCCH_H #define SRSRAN_SCHED_NR_PDCCH_H -#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" +#include "srsgnb/hdr/stack/mac/sched_nr_cfg.h" #include "srsran/adt/bounded_bitset.h" #include "srsran/adt/bounded_vector.h" #include "srsran/phy/common/phy_common_nr.h" diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_rb.h b/srsgnb/hdr/stack/mac/sched_nr_rb.h similarity index 99% rename from srsenb/hdr/stack/mac/nr/sched_nr_rb.h rename to srsgnb/hdr/stack/mac/sched_nr_rb.h index 9ccf1d251..ec0af28a6 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_rb.h +++ b/srsgnb/hdr/stack/mac/sched_nr_rb.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_RB_H #define SRSRAN_SCHED_NR_RB_H -#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" +#include "srsgnb/hdr/stack/mac/sched_nr_interface.h" #include "srsran/adt/bounded_bitset.h" #include "srsran/phy/common/phy_common_nr.h" diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_signalling.h b/srsgnb/hdr/stack/mac/sched_nr_signalling.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_signalling.h rename to srsgnb/hdr/stack/mac/sched_nr_signalling.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_time_rr.h b/srsgnb/hdr/stack/mac/sched_nr_time_rr.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_time_rr.h rename to srsgnb/hdr/stack/mac/sched_nr_time_rr.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsgnb/hdr/stack/mac/sched_nr_ue.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_ue.h rename to srsgnb/hdr/stack/mac/sched_nr_ue.h diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_worker.h b/srsgnb/hdr/stack/mac/sched_nr_worker.h similarity index 100% rename from srsenb/hdr/stack/mac/nr/sched_nr_worker.h rename to srsgnb/hdr/stack/mac/sched_nr_worker.h diff --git a/srsenb/hdr/stack/mac/nr/ue_nr.h b/srsgnb/hdr/stack/mac/ue_nr.h similarity index 98% rename from srsenb/hdr/stack/mac/nr/ue_nr.h rename to srsgnb/hdr/stack/mac/ue_nr.h index e5576cbe0..3282a85b1 100644 --- a/srsenb/hdr/stack/mac/nr/ue_nr.h +++ b/srsgnb/hdr/stack/mac/ue_nr.h @@ -14,7 +14,7 @@ #define SRSENB_UE_NR_H #include "srsenb/hdr/stack/mac/common/mac_metrics.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" +#include "srsgnb/hdr/stack/mac/sched_nr_interface.h" #include "srsran/common/block_queue.h" #include "srsran/common/interfaces_common.h" #include "srsran/interfaces/enb_rlc_interfaces.h" diff --git a/srsenb/hdr/stack/ngap/ngap.h b/srsgnb/hdr/stack/ngap/ngap.h similarity index 100% rename from srsenb/hdr/stack/ngap/ngap.h rename to srsgnb/hdr/stack/ngap/ngap.h diff --git a/srsenb/hdr/stack/ngap/ngap_interfaces.h b/srsgnb/hdr/stack/ngap/ngap_interfaces.h similarity index 100% rename from srsenb/hdr/stack/ngap/ngap_interfaces.h rename to srsgnb/hdr/stack/ngap/ngap_interfaces.h diff --git a/srsenb/hdr/stack/ngap/ngap_metrics.h b/srsgnb/hdr/stack/ngap/ngap_metrics.h similarity index 100% rename from srsenb/hdr/stack/ngap/ngap_metrics.h rename to srsgnb/hdr/stack/ngap/ngap_metrics.h diff --git a/srsenb/hdr/stack/ngap/ngap_ue.h b/srsgnb/hdr/stack/ngap/ngap_ue.h similarity index 100% rename from srsenb/hdr/stack/ngap/ngap_ue.h rename to srsgnb/hdr/stack/ngap/ngap_ue.h diff --git a/srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h b/srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h similarity index 100% rename from srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h rename to srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h diff --git a/srsenb/hdr/stack/ngap/ngap_ue_proc.h b/srsgnb/hdr/stack/ngap/ngap_ue_proc.h similarity index 98% rename from srsenb/hdr/stack/ngap/ngap_ue_proc.h rename to srsgnb/hdr/stack/ngap/ngap_ue_proc.h index 3d1cad5e1..36f2e57fc 100644 --- a/srsenb/hdr/stack/ngap/ngap_ue_proc.h +++ b/srsgnb/hdr/stack/ngap/ngap_ue_proc.h @@ -16,7 +16,7 @@ #include "ngap_interfaces.h" #include "ngap_ue_utils.h" -#include "srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h" +#include "srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h" #include "srsran/asn1/asn1_utils.h" #include "srsran/asn1/ngap.h" #include "srsran/common/buffer_pool.h" diff --git a/srsenb/hdr/stack/ngap/ngap_ue_utils.h b/srsgnb/hdr/stack/ngap/ngap_ue_utils.h similarity index 100% rename from srsenb/hdr/stack/ngap/ngap_ue_utils.h rename to srsgnb/hdr/stack/ngap/ngap_ue_utils.h diff --git a/srsenb/hdr/stack/rrc/nr/cell_asn1_config.h b/srsgnb/hdr/stack/rrc/cell_asn1_config.h similarity index 100% rename from srsenb/hdr/stack/rrc/nr/cell_asn1_config.h rename to srsgnb/hdr/stack/rrc/cell_asn1_config.h diff --git a/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h b/srsgnb/hdr/stack/rrc/rrc_config_nr.h similarity index 97% rename from srsenb/hdr/stack/rrc/nr/rrc_config_nr.h rename to srsgnb/hdr/stack/rrc/rrc_config_nr.h index 0dfec758f..5a67958f5 100644 --- a/srsenb/hdr/stack/rrc/nr/rrc_config_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_config_nr.h @@ -13,8 +13,8 @@ #ifndef SRSRAN_RRC_CONFIG_NR_H #define SRSRAN_RRC_CONFIG_NR_H -#include "../rrc_config_common.h" #include "srsenb/hdr/phy/phy_interfaces.h" +#include "srsenb/hdr/stack/rrc/rrc_config_common.h" #include "srsran/asn1/rrc_nr.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include "srsue/hdr/phy/phy_common.h" diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h similarity index 98% rename from srsenb/hdr/stack/rrc/rrc_nr.h rename to srsgnb/hdr/stack/rrc/rrc_nr.h index c03694ba2..267764daa 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -13,10 +13,10 @@ #ifndef SRSENB_RRC_NR_H #define SRSENB_RRC_NR_H -#include "rrc_config_common.h" -#include "rrc_metrics.h" #include "srsenb/hdr/stack/enb_stack_base.h" -#include "srsenb/hdr/stack/rrc/nr/rrc_config_nr.h" +#include "srsenb/hdr/stack/rrc/rrc_config_common.h" +#include "srsenb/hdr/stack/rrc/rrc_metrics.h" +#include "srsgnb/hdr/stack/rrc/rrc_config_nr.h" #include "srsran/asn1/rrc_nr.h" #include "srsran/common/block_queue.h" #include "srsran/common/buffer_pool.h" diff --git a/srsenb/hdr/stack/upper/sdap.h b/srsgnb/hdr/stack/sdap/sdap.h similarity index 100% rename from srsenb/hdr/stack/upper/sdap.h rename to srsgnb/hdr/stack/sdap/sdap.h diff --git a/srsgnb/src/CMakeLists.txt b/srsgnb/src/CMakeLists.txt new file mode 100644 index 000000000..51071b535 --- /dev/null +++ b/srsgnb/src/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# 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. +# + +add_subdirectory(stack) \ No newline at end of file diff --git a/srsgnb/src/stack/CMakeLists.txt b/srsgnb/src/stack/CMakeLists.txt new file mode 100644 index 000000000..369888e94 --- /dev/null +++ b/srsgnb/src/stack/CMakeLists.txt @@ -0,0 +1,18 @@ +# +# 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_directories(${PROJECT_SOURCE_DIR}) + +add_subdirectory(mac) +add_subdirectory(ngap) +add_subdirectory(rrc) +add_subdirectory(sdap) + +set(SOURCES gnb_stack_nr.cc) + +add_library(srsgnb_stack STATIC ${SOURCES}) \ No newline at end of file diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsgnb/src/stack/gnb_stack_nr.cc similarity index 98% rename from srsenb/src/stack/gnb_stack_nr.cc rename to srsgnb/src/stack/gnb_stack_nr.cc index cbd145c58..1cb69ecd9 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsgnb/src/stack/gnb_stack_nr.cc @@ -10,9 +10,9 @@ * */ -#include "srsenb/hdr/stack/gnb_stack_nr.h" -#include "srsenb/hdr/stack/ngap/ngap.h" +#include "srsgnb/hdr/stack/gnb_stack_nr.h" #include "srsenb/hdr/stack/upper/gtpu.h" +#include "srsgnb/hdr/stack/ngap/ngap.h" #include "srsran/common/network_utils.h" #include "srsran/common/standard_streams.h" #include "srsran/srsran.h" diff --git a/srsenb/src/stack/mac/nr/CMakeLists.txt b/srsgnb/src/stack/mac/CMakeLists.txt similarity index 91% rename from srsenb/src/stack/mac/nr/CMakeLists.txt rename to srsgnb/src/stack/mac/CMakeLists.txt index 995f067d7..9164d1551 100644 --- a/srsenb/src/stack/mac/nr/CMakeLists.txt +++ b/srsgnb/src/stack/mac/CMakeLists.txt @@ -24,3 +24,6 @@ set(SOURCES mac_nr.cc add_library(srsgnb_mac STATIC ${SOURCES}) target_link_libraries(srsgnb_mac srsenb_mac_common) +include_directories(${PROJECT_SOURCE_DIR}) + +add_subdirectory(test) \ No newline at end of file diff --git a/srsenb/src/stack/mac/nr/harq_softbuffer.cc b/srsgnb/src/stack/mac/harq_softbuffer.cc similarity index 97% rename from srsenb/src/stack/mac/nr/harq_softbuffer.cc rename to srsgnb/src/stack/mac/harq_softbuffer.cc index b60465d8f..6035b1c69 100644 --- a/srsenb/src/stack/mac/nr/harq_softbuffer.cc +++ b/srsgnb/src/stack/mac/harq_softbuffer.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h" +#include "srsgnb/hdr/stack/mac/harq_softbuffer.h" #include "srsran/adt/pool/obj_pool.h" namespace srsenb { diff --git a/srsenb/src/stack/mac/nr/mac_nr.cc b/srsgnb/src/stack/mac/mac_nr.cc similarity index 99% rename from srsenb/src/stack/mac/nr/mac_nr.cc rename to srsgnb/src/stack/mac/mac_nr.cc index 496cc7c6a..2a837db8f 100644 --- a/srsenb/src/stack/mac/nr/mac_nr.cc +++ b/srsgnb/src/stack/mac/mac_nr.cc @@ -10,8 +10,8 @@ * */ -#include "srsenb/hdr/stack/mac/nr/mac_nr.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsgnb/hdr/stack/mac/mac_nr.h" +#include "srsgnb/hdr/stack/mac/sched_nr.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/rwlock_guard.h" diff --git a/srsenb/src/stack/mac/nr/sched_nr.cc b/srsgnb/src/stack/mac/sched_nr.cc similarity index 98% rename from srsenb/src/stack/mac/nr/sched_nr.cc rename to srsgnb/src/stack/mac/sched_nr.cc index 348680053..c99121abc 100644 --- a/srsenb/src/stack/mac/nr/sched_nr.cc +++ b/srsgnb/src/stack/mac/sched_nr.cc @@ -10,11 +10,11 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsgnb/hdr/stack/mac/sched_nr.h" #include "srsenb/hdr/stack/mac/common/mac_metrics.h" -#include "srsenb/hdr/stack/mac/nr/harq_softbuffer.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" +#include "srsgnb/hdr/stack/mac/harq_softbuffer.h" +#include "srsgnb/hdr/stack/mac/sched_nr_bwp.h" +#include "srsgnb/hdr/stack/mac/sched_nr_worker.h" #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/string_helpers.h" #include "srsran/common/thread_pool.h" diff --git a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc b/srsgnb/src/stack/mac/sched_nr_bwp.cc similarity index 99% rename from srsenb/src/stack/mac/nr/sched_nr_bwp.cc rename to srsgnb/src/stack/mac/sched_nr_bwp.cc index 77fdf35cb..2b82b1d0d 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_bwp.cc +++ b/srsgnb/src/stack/mac/sched_nr_bwp.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" +#include "srsgnb/hdr/stack/mac/sched_nr_bwp.h" #include "srsran/common/standard_streams.h" #include "srsran/common/string_helpers.h" diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsgnb/src/stack/mac/sched_nr_cfg.cc similarity index 97% rename from srsenb/src/stack/mac/nr/sched_nr_cfg.cc rename to srsgnb/src/stack/mac/sched_nr_cfg.cc index 7da89466e..46a90096c 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsgnb/src/stack/mac/sched_nr_cfg.cc @@ -10,8 +10,8 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" +#include "srsgnb/hdr/stack/mac/sched_nr_cfg.h" +#include "srsgnb/hdr/stack/mac/sched_nr_helpers.h" #include "srsran/adt/optional_array.h" extern "C" { #include "srsran/phy/phch/ra_ul_nr.h" diff --git a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc similarity index 98% rename from srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc rename to srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index e94090a81..95aa5f1cf 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -10,9 +10,9 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" +#include "srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h" +#include "srsgnb/hdr/stack/mac/sched_nr_bwp.h" +#include "srsgnb/hdr/stack/mac/sched_nr_helpers.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/src/stack/mac/nr/sched_nr_harq.cc b/srsgnb/src/stack/mac/sched_nr_harq.cc similarity index 98% rename from srsenb/src/stack/mac/nr/sched_nr_harq.cc rename to srsgnb/src/stack/mac/sched_nr_harq.cc index b4160a61f..a70c8f877 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_harq.cc +++ b/srsgnb/src/stack/mac/sched_nr_harq.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" +#include "srsgnb/hdr/stack/mac/sched_nr_harq.h" #include "srsran/common/buffer_pool.h" namespace srsenb { diff --git a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc b/srsgnb/src/stack/mac/sched_nr_helpers.cc similarity index 97% rename from srsenb/src/stack/mac/nr/sched_nr_helpers.cc rename to srsgnb/src/stack/mac/sched_nr_helpers.cc index 9d881f2b3..d3707be10 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_helpers.cc +++ b/srsgnb/src/stack/mac/sched_nr_helpers.cc @@ -10,10 +10,10 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_helpers.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_harq.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" +#include "srsgnb/hdr/stack/mac/sched_nr_helpers.h" +#include "srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h" +#include "srsgnb/hdr/stack/mac/sched_nr_harq.h" +#include "srsgnb/hdr/stack/mac/sched_nr_ue.h" #include "srsran/common/string_helpers.h" namespace srsenb { diff --git a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc b/srsgnb/src/stack/mac/sched_nr_pdcch.cc similarity index 99% rename from srsenb/src/stack/mac/nr/sched_nr_pdcch.cc rename to srsgnb/src/stack/mac/sched_nr_pdcch.cc index df438a989..78709bf42 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_pdcch.cc +++ b/srsgnb/src/stack/mac/sched_nr_pdcch.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsgnb/hdr/stack/mac/sched_nr_pdcch.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/src/stack/mac/nr/sched_nr_rb.cc b/srsgnb/src/stack/mac/sched_nr_rb.cc similarity index 98% rename from srsenb/src/stack/mac/nr/sched_nr_rb.cc rename to srsgnb/src/stack/mac/sched_nr_rb.cc index e24844b7f..db77d4221 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_rb.cc +++ b/srsgnb/src/stack/mac/sched_nr_rb.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_rb.h" +#include "srsgnb/hdr/stack/mac/sched_nr_rb.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/src/stack/mac/nr/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc similarity index 98% rename from srsenb/src/stack/mac/nr/sched_nr_signalling.cc rename to srsgnb/src/stack/mac/sched_nr_signalling.cc index 5d125b5e8..df738a0b0 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_signalling.h" +#include "srsgnb/hdr/stack/mac/sched_nr_signalling.h" #define POS_IN_BURST_FIRST_BIT_IDX 0 #define POS_IN_BURST_SECOND_BIT_IDX 1 diff --git a/srsenb/src/stack/mac/nr/sched_nr_time_rr.cc b/srsgnb/src/stack/mac/sched_nr_time_rr.cc similarity index 97% rename from srsenb/src/stack/mac/nr/sched_nr_time_rr.cc rename to srsgnb/src/stack/mac/sched_nr_time_rr.cc index b46ed63cb..34b7f3806 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_time_rr.cc +++ b/srsgnb/src/stack/mac/sched_nr_time_rr.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_time_rr.h" +#include "srsgnb/hdr/stack/mac/sched_nr_time_rr.h" namespace srsenb { namespace sched_nr_impl { diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsgnb/src/stack/mac/sched_nr_ue.cc similarity index 97% rename from srsenb/src/stack/mac/nr/sched_nr_ue.cc rename to srsgnb/src/stack/mac/sched_nr_ue.cc index 1a41fb5c0..41f73f60b 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsgnb/src/stack/mac/sched_nr_ue.cc @@ -10,8 +10,8 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_ue.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsgnb/hdr/stack/mac/sched_nr_ue.h" +#include "srsgnb/hdr/stack/mac/sched_nr_pdcch.h" #include "srsran/common/string_helpers.h" namespace srsenb { diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsgnb/src/stack/mac/sched_nr_worker.cc similarity index 98% rename from srsenb/src/stack/mac/nr/sched_nr_worker.cc rename to srsgnb/src/stack/mac/sched_nr_worker.cc index b981c1404..c4ac886c5 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsgnb/src/stack/mac/sched_nr_worker.cc @@ -10,9 +10,9 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_worker.h" +#include "srsgnb/hdr/stack/mac/sched_nr_worker.h" #include "srsenb/hdr/stack/mac/common/mac_metrics.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_signalling.h" +#include "srsgnb/hdr/stack/mac/sched_nr_signalling.h" #include "srsran/common/string_helpers.h" namespace srsenb { diff --git a/srsenb/test/mac/nr/CMakeLists.txt b/srsgnb/src/stack/mac/test/CMakeLists.txt similarity index 100% rename from srsenb/test/mac/nr/CMakeLists.txt rename to srsgnb/src/stack/mac/test/CMakeLists.txt diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h similarity index 98% rename from srsenb/test/mac/nr/sched_nr_cfg_generators.h rename to srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h index 93e927612..37d425705 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_CFG_GENERATORS_H #define SRSRAN_SCHED_NR_CFG_GENERATORS_H -#include "srsenb/hdr/stack/mac/nr/sched_nr_interface.h" +#include "srsgnb/hdr/stack/mac/sched_nr_interface.h" #include "srsran/common/phy_cfg_nr_default.h" namespace srsenb { diff --git a/srsenb/test/mac/nr/sched_nr_common_test.cc b/srsgnb/src/stack/mac/test/sched_nr_common_test.cc similarity index 98% rename from srsenb/test/mac/nr/sched_nr_common_test.cc rename to srsgnb/src/stack/mac/test/sched_nr_common_test.cc index a5fb89906..0ab6f9a35 100644 --- a/srsenb/test/mac/nr/sched_nr_common_test.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_common_test.cc @@ -11,7 +11,7 @@ */ #include "sched_nr_common_test.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_cfg.h" +#include "srsgnb/hdr/stack/mac/sched_nr_cfg.h" #include "srsran/support/srsran_test.h" namespace srsenb { diff --git a/srsenb/test/mac/nr/sched_nr_common_test.h b/srsgnb/src/stack/mac/test/sched_nr_common_test.h similarity index 95% rename from srsenb/test/mac/nr/sched_nr_common_test.h rename to srsgnb/src/stack/mac/test/sched_nr_common_test.h index 096a0d3d4..a835ba8f9 100644 --- a/srsenb/test/mac/nr/sched_nr_common_test.h +++ b/srsgnb/src/stack/mac/test/sched_nr_common_test.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_SCHED_NR_COMMON_TEST_H #define SRSRAN_SCHED_NR_COMMON_TEST_H -#include "srsenb/hdr/stack/mac/nr/sched_nr_pdcch.h" +#include "srsgnb/hdr/stack/mac/sched_nr_pdcch.h" #include "srsran/adt/span.h" namespace srsenb { diff --git a/srsenb/test/mac/nr/sched_nr_prb_test.cc b/srsgnb/src/stack/mac/test/sched_nr_prb_test.cc similarity index 98% rename from srsenb/test/mac/nr/sched_nr_prb_test.cc rename to srsgnb/src/stack/mac/test/sched_nr_prb_test.cc index 25d3c65d4..bd619eec1 100644 --- a/srsenb/test/mac/nr/sched_nr_prb_test.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_prb_test.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/mac/nr/sched_nr_rb.h" +#include "srsgnb/hdr/stack/mac/sched_nr_rb.h" #include "srsran/common/test_common.h" using namespace srsenb; diff --git a/srsenb/test/mac/nr/sched_nr_rar_test.cc b/srsgnb/src/stack/mac/test/sched_nr_rar_test.cc similarity index 98% rename from srsenb/test/mac/nr/sched_nr_rar_test.cc rename to srsgnb/src/stack/mac/test/sched_nr_rar_test.cc index 991950c5a..dbd0870c4 100644 --- a/srsenb/test/mac/nr/sched_nr_rar_test.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_rar_test.cc @@ -12,7 +12,7 @@ #include "sched_nr_cfg_generators.h" #include "sched_nr_common_test.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_bwp.h" +#include "srsgnb/hdr/stack/mac/sched_nr_bwp.h" #include "srsran/common/test_common.h" #include "srsran/support/srsran_test.h" #include diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.cc b/srsgnb/src/stack/mac/test/sched_nr_sim_ue.cc similarity index 100% rename from srsenb/test/mac/nr/sched_nr_sim_ue.cc rename to srsgnb/src/stack/mac/test/sched_nr_sim_ue.cc diff --git a/srsenb/test/mac/nr/sched_nr_sim_ue.h b/srsgnb/src/stack/mac/test/sched_nr_sim_ue.h similarity index 98% rename from srsenb/test/mac/nr/sched_nr_sim_ue.h rename to srsgnb/src/stack/mac/test/sched_nr_sim_ue.h index d70f9f396..6ed98e4bc 100644 --- a/srsenb/test/mac/nr/sched_nr_sim_ue.h +++ b/srsgnb/src/stack/mac/test/sched_nr_sim_ue.h @@ -13,8 +13,8 @@ #ifndef SRSRAN_SCHED_NR_SIM_UE_H #define SRSRAN_SCHED_NR_SIM_UE_H -#include "../sched_sim_ue.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr.h" +#include "srsenb/test/mac/sched_sim_ue.h" +#include "srsgnb/hdr/stack/mac/sched_nr.h" #include "srsran/adt/circular_array.h" #include #include diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsgnb/src/stack/mac/test/sched_nr_test.cc similarity index 100% rename from srsenb/test/mac/nr/sched_nr_test.cc rename to srsgnb/src/stack/mac/test/sched_nr_test.cc diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc b/srsgnb/src/stack/mac/test/sched_nr_ue_ded_test_suite.cc similarity index 96% rename from srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc rename to srsgnb/src/stack/mac/test/sched_nr_ue_ded_test_suite.cc index 5b76f6098..13d934a78 100644 --- a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.cc +++ b/srsgnb/src/stack/mac/test/sched_nr_ue_ded_test_suite.cc @@ -11,7 +11,7 @@ */ #include "sched_nr_ue_ded_test_suite.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr_grant_allocator.h" +#include "srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h" #include "srsran/common/test_common.h" namespace srsenb { diff --git a/srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.h b/srsgnb/src/stack/mac/test/sched_nr_ue_ded_test_suite.h similarity index 100% rename from srsenb/test/mac/nr/sched_nr_ue_ded_test_suite.h rename to srsgnb/src/stack/mac/test/sched_nr_ue_ded_test_suite.h diff --git a/srsenb/src/stack/mac/nr/ue_nr.cc b/srsgnb/src/stack/mac/ue_nr.cc similarity index 99% rename from srsenb/src/stack/mac/nr/ue_nr.cc rename to srsgnb/src/stack/mac/ue_nr.cc index 35e99cea4..c6fe7d3ee 100644 --- a/srsenb/src/stack/mac/nr/ue_nr.cc +++ b/srsgnb/src/stack/mac/ue_nr.cc @@ -15,7 +15,7 @@ #include #include -#include "srsenb/hdr/stack/mac/nr/ue_nr.h" +#include "srsgnb/hdr/stack/mac/ue_nr.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/string_helpers.h" #include "srsran/interfaces/gnb_interfaces.h" diff --git a/srsenb/src/stack/ngap/CMakeLists.txt b/srsgnb/src/stack/ngap/CMakeLists.txt similarity index 100% rename from srsenb/src/stack/ngap/CMakeLists.txt rename to srsgnb/src/stack/ngap/CMakeLists.txt diff --git a/srsenb/src/stack/ngap/ngap.cc b/srsgnb/src/stack/ngap/ngap.cc similarity index 99% rename from srsenb/src/stack/ngap/ngap.cc rename to srsgnb/src/stack/ngap/ngap.cc index fcfb9adf1..c57f13f39 100644 --- a/srsenb/src/stack/ngap/ngap.cc +++ b/srsgnb/src/stack/ngap/ngap.cc @@ -10,8 +10,8 @@ * */ -#include "srsenb/hdr/stack/ngap/ngap.h" -#include "srsenb/hdr/stack/ngap/ngap_ue.h" +#include "srsgnb/hdr/stack/ngap/ngap.h" +#include "srsgnb/hdr/stack/ngap/ngap_ue.h" #include "srsran/common/int_helpers.h" using srsran::s1ap_mccmnc_to_plmn; diff --git a/srsenb/src/stack/ngap/ngap_ue.cc b/srsgnb/src/stack/ngap/ngap_ue.cc similarity index 98% rename from srsenb/src/stack/ngap/ngap_ue.cc rename to srsgnb/src/stack/ngap/ngap_ue.cc index 3d9d0608a..1efcf8d4a 100644 --- a/srsenb/src/stack/ngap/ngap_ue.cc +++ b/srsgnb/src/stack/ngap/ngap_ue.cc @@ -10,9 +10,9 @@ * */ -#include "srsenb/hdr/stack/ngap/ngap_ue.h" -#include "srsenb/hdr/stack/ngap/ngap.h" -#include "srsenb/hdr/stack/ngap/ngap_ue_proc.h" +#include "srsgnb/hdr/stack/ngap/ngap_ue.h" +#include "srsgnb/hdr/stack/ngap/ngap.h" +#include "srsgnb/hdr/stack/ngap/ngap_ue_proc.h" #include "srsran/common/int_helpers.h" using namespace asn1::ngap_nr; diff --git a/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc b/srsgnb/src/stack/ngap/ngap_ue_bearer_manager.cc similarity index 98% rename from srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc rename to srsgnb/src/stack/ngap/ngap_ue_bearer_manager.cc index 55ceb18c2..ad336df4c 100644 --- a/srsenb/src/stack/ngap/ngap_ue_bearer_manager.cc +++ b/srsgnb/src/stack/ngap/ngap_ue_bearer_manager.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/ngap/ngap_ue_bearer_manager.h" +#include "srsgnb/hdr/stack/ngap/ngap_ue_bearer_manager.h" namespace srsenb { ngap_ue_bearer_manager::ngap_ue_bearer_manager(gtpu_interface_rrc* gtpu_, srslog::basic_logger& logger_) : diff --git a/srsenb/src/stack/ngap/ngap_ue_proc.cc b/srsgnb/src/stack/ngap/ngap_ue_proc.cc similarity index 99% rename from srsenb/src/stack/ngap/ngap_ue_proc.cc rename to srsgnb/src/stack/ngap/ngap_ue_proc.cc index 750cf5ac9..9c2ba883a 100644 --- a/srsenb/src/stack/ngap/ngap_ue_proc.cc +++ b/srsgnb/src/stack/ngap/ngap_ue_proc.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/ngap/ngap_ue_proc.h" +#include "srsgnb/hdr/stack/ngap/ngap_ue_proc.h" using namespace srsran; diff --git a/srsenb/test/ngap/CMakeLists.txt b/srsgnb/src/stack/ngap/test/CMakeLists.txt similarity index 100% rename from srsenb/test/ngap/CMakeLists.txt rename to srsgnb/src/stack/ngap/test/CMakeLists.txt diff --git a/srsenb/test/ngap/ngap_test.cc b/srsgnb/src/stack/ngap/test/ngap_test.cc similarity index 100% rename from srsenb/test/ngap/ngap_test.cc rename to srsgnb/src/stack/ngap/test/ngap_test.cc diff --git a/srsgnb/src/stack/rrc/CMakeLists.txt b/srsgnb/src/stack/rrc/CMakeLists.txt new file mode 100644 index 000000000..58ee3867c --- /dev/null +++ b/srsgnb/src/stack/rrc/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# 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. +# + +set(SOURCES rrc_nr.cc cell_asn1_config.cc) +add_library(srsgnb_rrc STATIC ${SOURCES}) +target_link_libraries(srsgnb_rrc srsran_rrc_nr) + +include_directories(${PROJECT_SOURCE_DIR}) + +add_subdirectory(test) \ No newline at end of file diff --git a/srsenb/src/stack/rrc/nr/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc similarity index 99% rename from srsenb/src/stack/rrc/nr/cell_asn1_config.cc rename to srsgnb/src/stack/rrc/cell_asn1_config.cc index 09e39751b..c6535f280 100644 --- a/srsenb/src/stack/rrc/nr/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/rrc/nr/cell_asn1_config.h" +#include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" #include "srsran/rrc/nr/rrc_nr_cfg_utils.h" #include diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc similarity index 99% rename from srsenb/src/stack/rrc/rrc_nr.cc rename to srsgnb/src/stack/rrc/rrc_nr.cc index 0a50b9f84..e2069af70 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -10,10 +10,10 @@ * */ -#include "srsenb/hdr/stack/rrc/rrc_nr.h" +#include "srsgnb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/common/common_enb.h" -#include "srsenb/hdr/stack/rrc/nr/cell_asn1_config.h" -#include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" +#include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" +#include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/common_nr.h" #include "srsran/common/phy_cfg_nr_default.h" diff --git a/srsgnb/src/stack/rrc/test/CMakeLists.txt b/srsgnb/src/stack/rrc/test/CMakeLists.txt new file mode 100644 index 000000000..798e2556d --- /dev/null +++ b/srsgnb/src/stack/rrc/test/CMakeLists.txt @@ -0,0 +1,11 @@ +# +# 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. +# + +add_executable(rrc_nr_test rrc_nr_test.cc) +target_link_libraries(rrc_nr_test srsgnb_rrc test_helpers ${ATOMIC_LIBS}) +add_test(rrc_nr_test rrc_nr_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) \ No newline at end of file diff --git a/srsenb/test/rrc/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc similarity index 99% rename from srsenb/test/rrc/rrc_nr_test.cc rename to srsgnb/src/stack/rrc/test/rrc_nr_test.cc index a7a024955..dc56df1f2 100644 --- a/srsenb/test/rrc/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -11,10 +11,10 @@ */ #include "srsenb/hdr/enb.h" -#include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/test/common/dummy_classes_common.h" #include "srsenb/test/common/dummy_classes_nr.h" #include "srsenb/test/rrc/test_helpers.h" +#include "srsgnb/hdr/stack/rrc/rrc_nr.h" #include "srsran/common/test_common.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include diff --git a/srsgnb/src/stack/sdap/CMakeLists.txt b/srsgnb/src/stack/sdap/CMakeLists.txt new file mode 100644 index 000000000..245242ee5 --- /dev/null +++ b/srsgnb/src/stack/sdap/CMakeLists.txt @@ -0,0 +1,10 @@ +# +# 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. +# + +set(SOURCES sdap.cc) +add_library(srsgnb_sdap STATIC ${SOURCES}) \ No newline at end of file diff --git a/srsenb/src/stack/upper/sdap.cc b/srsgnb/src/stack/sdap/sdap.cc similarity index 95% rename from srsenb/src/stack/upper/sdap.cc rename to srsgnb/src/stack/sdap/sdap.cc index 64935aae3..54394b5a3 100644 --- a/srsenb/src/stack/upper/sdap.cc +++ b/srsgnb/src/stack/sdap/sdap.cc @@ -10,7 +10,7 @@ * */ -#include "srsenb/hdr/stack/upper/sdap.h" +#include "srsgnb/hdr/stack/sdap/sdap.h" namespace srsenb { diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 51a616d50..790547448 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -15,11 +15,11 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" -#include "srsenb/hdr/stack/mac/nr/mac_nr.h" -#include "srsenb/hdr/stack/mac/nr/sched_nr.h" #include "srsenb/test/common/dummy_classes_nr.h" #include "srsenb/test/common/rlc_test_dummy.h" -#include "srsenb/test/mac/nr/sched_nr_cfg_generators.h" +#include "srsgnb/hdr/stack/mac/mac_nr.h" +#include "srsgnb/hdr/stack/mac/sched_nr.h" +#include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" #include "srsran/srslog/srslog.h" #include #include From 9734f2e3930bc288534ab6e8492c53e3f7b89315 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 5 Nov 2021 13:52:26 +0000 Subject: [PATCH 17/35] adt: fix optional_vector ctor, and add emplace method --- lib/include/srsran/adt/optional_array.h | 29 ++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/lib/include/srsran/adt/optional_array.h b/lib/include/srsran/adt/optional_array.h index edacb104c..2bdaf53b5 100644 --- a/lib/include/srsran/adt/optional_array.h +++ b/lib/include/srsran/adt/optional_array.h @@ -83,6 +83,10 @@ public: using iterator = iterator_impl; using const_iterator = iterator_impl; + base_optional_span() = default; + base_optional_span(Vec&& v, size_t nof_elems_) : vec(std::move(v)), nof_elems(nof_elems_) {} + base_optional_span(const Vec& v, size_t nof_elems_) : vec(v), nof_elems(nof_elems_) {} + // Find first position that is empty size_t find_first_empty(size_t start_guess = 0) { @@ -134,6 +138,16 @@ public: this->nof_elems += this->contains(idx) ? 0 : 1; this->vec[idx] = std::forward(u); } + + template + void emplace(size_t idx, Args&&... args) + { + srsran_assert(idx < this->vec.size(), "Out-of-bounds access to array: %zd>=%zd", idx, this->vec.size()); + if (not this->contains(idx)) { + this->nof_elems++; + } + this->vec[idx].emplace(std::forward(args)...); + } }; template @@ -148,8 +162,7 @@ public: base_optional_vector() = default; base_optional_vector(const base_optional_vector&) = default; - base_optional_vector(base_optional_vector&& other) noexcept : base_t::vec(std::move(other.vec)), - base_t::nof_elems(other.nof_elems) + base_optional_vector(base_optional_vector&& other) noexcept : base_t(std::move(other.vec), other.size()) { other.nof_elems = 0; } @@ -158,7 +171,7 @@ public: { this->vec = std::move(other.vec); this->nof_elems = other.nof_elems; - this->nof_elems = 0; + other.nof_elems = 0; return *this; } }; @@ -196,6 +209,16 @@ public: } base_t::insert(idx, std::forward(u)); } + + /// May allocate and cause pointer invalidation + template + void emplace(size_t idx, Args&&... args) + { + if (idx >= this->vec.size()) { + this->vec.resize(idx + 1); + } + base_t::emplace(idx, std::forward(args)...); + } }; template From 30c0ffe3e5e41bd31168f2101238b9490159d5ca Mon Sep 17 00:00:00 2001 From: Francisco Date: Thu, 4 Nov 2021 12:30:55 +0000 Subject: [PATCH 18/35] nr,gnb,mac: decouple UL PDU decoding from the UE object --- srsgnb/hdr/stack/mac/mac_nr.h | 13 +-- srsgnb/hdr/stack/mac/ue_nr.h | 5 - srsgnb/src/stack/mac/mac_nr.cc | 164 +++++++++++++++++++++++++++++++-- srsgnb/src/stack/mac/ue_nr.cc | 127 ------------------------- 4 files changed, 161 insertions(+), 148 deletions(-) diff --git a/srsgnb/hdr/stack/mac/mac_nr.h b/srsgnb/hdr/stack/mac/mac_nr.h index 9306272ed..c700f50bd 100644 --- a/srsgnb/hdr/stack/mac/mac_nr.h +++ b/srsgnb/hdr/stack/mac/mac_nr.h @@ -35,6 +35,7 @@ struct mac_nr_args_t { }; class sched_nr; +class mac_nr_rx; class mac_nr final : public mac_interface_phy_nr, public mac_interface_rrc_nr, public mac_interface_rlc_nr { @@ -82,10 +83,7 @@ private: bool is_rnti_active_nolock(uint16_t rnti); // handle UCI data from either PUCCH or PUSCH - bool handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value); - - // PDU processing - int handle_pdu(srsran::unique_byte_buffer_t pdu); + bool handle_uci_data(uint16_t rnti, const srsran_uci_cfg_nr_t& cfg, const srsran_uci_value_nr_t& value); // Metrics processing void get_metrics_nolock(srsenb::mac_metrics_t& metrics); @@ -101,8 +99,8 @@ private: rrc_interface_mac_nr* rrc = nullptr; // args - srsran::task_sched_handle task_sched; - srsran::task_multiqueue::queue_handle stack_task_queue; + srsran::task_sched_handle task_sched; + srsran::task_queue_handle stack_task_queue; std::unique_ptr pcap = nullptr; mac_nr_args_t args = {}; @@ -132,6 +130,9 @@ private: // Number of rach preambles detected for a CC std::vector detected_rachs; + + // Decoding of UL PDUs + std::unique_ptr rx; }; } // namespace srsenb diff --git a/srsgnb/hdr/stack/mac/ue_nr.h b/srsgnb/hdr/stack/mac/ue_nr.h index 3282a85b1..4b0fd7440 100644 --- a/srsgnb/hdr/stack/mac/ue_nr.h +++ b/srsgnb/hdr/stack/mac/ue_nr.h @@ -50,7 +50,6 @@ public: bool is_active() const { return active_state.load(std::memory_order_relaxed); } int generate_pdu(srsran::byte_buffer_t* pdu, uint32_t grant_size); - int process_pdu(srsran::unique_byte_buffer_t pdu); std::mutex metrics_mutex = {}; void metrics_read(mac_ue_metrics_t* metrics_); @@ -69,10 +68,6 @@ public: uint32_t read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) final; private: - // helper methods - uint32_t buff_size_field_to_bytes(uint32_t buff_size_index, const srsran::bsr_format_nr_t& format); - int process_ce_subpdu(const srsran::mac_sch_subpdu_nr& subpdu); - rlc_interface_mac* rlc = nullptr; rrc_interface_mac_nr* rrc = nullptr; phy_interface_stack_nr* phy = nullptr; diff --git a/srsgnb/src/stack/mac/mac_nr.cc b/srsgnb/src/stack/mac/mac_nr.cc index 2a837db8f..426678a87 100644 --- a/srsgnb/src/stack/mac/mac_nr.cc +++ b/srsgnb/src/stack/mac/mac_nr.cc @@ -22,6 +22,155 @@ namespace srsenb { +class mac_nr_rx +{ +public: + explicit mac_nr_rx(rlc_interface_mac* rlc_, + rrc_interface_mac_nr* rrc_, + srsran::task_queue_handle& stack_task_queue_, + sched_nr_interface* sched_, + srslog::basic_logger& logger_) : + task_queue(stack_task_queue_), rlc(rlc_), rrc(rrc_), sched(sched_), logger(logger_) + {} + + void handle_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu) + { + task_queue.push(std::bind( + [this, rnti](srsran::unique_byte_buffer_t& pdu) { handle_pdu_impl(rnti, std::move(pdu)); }, std::move(pdu))); + } + +private: + int handle_pdu_impl(uint16_t rnti, srsran::unique_byte_buffer_t pdu) + { + pdu_ul.init_rx(true); + if (pdu_ul.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + if (logger.info.enabled()) { + fmt::memory_buffer str_buffer; + pdu_ul.to_string(str_buffer); + logger.info("Rx PDU: rnti=0x%x, %s", rnti, srsran::to_c_str(str_buffer)); + } + + // Process MAC CRNTI CE first, if it exists + uint32_t crnti_ce_pos = pdu_ul.get_num_subpdus(); + for (uint32_t n = pdu_ul.get_num_subpdus(); n > 0; --n) { + srsran::mac_sch_subpdu_nr& subpdu = pdu_ul.get_subpdu(n - 1); + if (subpdu.get_lcid() == srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CRNTI) { + if (process_ce_subpdu(rnti, subpdu) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + crnti_ce_pos = n - 1; + } + } + + // Process SDUs and remaining MAC CEs + for (uint32_t n = 0; n < pdu_ul.get_num_subpdus(); ++n) { + srsran::mac_sch_subpdu_nr& subpdu = pdu_ul.get_subpdu(n); + if (subpdu.is_sdu()) { + rrc->set_activity_user(rnti); + rlc->write_pdu(rnti, subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); + } else if (n != crnti_ce_pos) { + if (process_ce_subpdu(rnti, subpdu) != SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + } + } + + return SRSRAN_SUCCESS; + } + + int process_ce_subpdu(uint16_t& rnti, const srsran::mac_sch_subpdu_nr& subpdu) + { + // Handle MAC CEs + switch (subpdu.get_lcid()) { + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CRNTI: { + uint16_t ce_crnti = subpdu.get_c_rnti(); + uint16_t prev_rnti = rnti; + rnti = ce_crnti; + rrc->update_user(prev_rnti, rnti); + sched->ul_sr_info(rnti); // provide UL grant regardless of other BSR content for UE to complete RA + } break; + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::SHORT_BSR: + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::SHORT_TRUNC_BSR: { + srsran::mac_sch_subpdu_nr::lcg_bsr_t sbsr = subpdu.get_sbsr(); + uint32_t buffer_size_bytes = buff_size_field_to_bytes(sbsr.buffer_size, srsran::SHORT_BSR); + // Assume all LCGs are 0 if reported SBSR is 0 + if (buffer_size_bytes == 0) { + for (uint32_t j = 0; j <= SCHED_NR_MAX_LC_GROUP; j++) { + sched->ul_bsr(rnti, j, 0); + } + } else { + sched->ul_bsr(rnti, sbsr.lcg_id, buffer_size_bytes); + } + } break; + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::LONG_BSR: + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::LONG_TRUNC_BSR: { + srsran::mac_sch_subpdu_nr::lbsr_t lbsr = subpdu.get_lbsr(); + for (auto& lb : lbsr.list) { + sched->ul_bsr(rnti, lb.lcg_id, buff_size_field_to_bytes(lb.buffer_size, srsran::LONG_BSR)); + } + } break; + case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::PADDING: + break; + default: + logger.warning("Unhandled subPDU with LCID=%d", subpdu.get_lcid()); + } + + return SRSRAN_SUCCESS; + } + + /** Converts the buffer size field of a BSR (5 or 8-bit Buffer Size field) into Bytes + * @param buff_size_field The buffer size field contained in the MAC PDU + * @param format The BSR format that determines the buffer size field length + * @return uint32_t The actual buffer size level in Bytes + */ + static uint32_t buff_size_field_to_bytes(uint32_t buff_size_index, const srsran::bsr_format_nr_t& format) + { + using namespace srsran; + + // early exit + if (buff_size_index == 0) { + return 0; + } + + const uint32_t max_offset = 1; // make the reported value bigger than the 2nd biggest + + switch (format) { + case SHORT_BSR: + case SHORT_TRUNC_BSR: + if (buff_size_index >= buffer_size_levels_5bit_max_idx) { + return buffer_size_levels_5bit[buffer_size_levels_5bit_max_idx] + max_offset; + } else { + return buffer_size_levels_5bit[buff_size_index]; + } + break; + case LONG_BSR: + case LONG_TRUNC_BSR: + if (buff_size_index > buffer_size_levels_8bit_max_idx) { + return buffer_size_levels_8bit[buffer_size_levels_8bit_max_idx] + max_offset; + } else { + return buffer_size_levels_8bit[buff_size_index]; + } + break; + default: + break; + } + return 0; + } + + rlc_interface_mac* rlc; + rrc_interface_mac_nr* rrc; + sched_nr_interface* sched; + srslog::basic_logger& logger; + srsran::task_queue_handle& task_queue; + + srsran::mac_sch_pdu_nr pdu_ul; +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + mac_nr::mac_nr(srsran::task_sched_handle task_sched_) : logger(srslog::fetch_basic_logger("MAC-NR")), task_sched(task_sched_), @@ -126,6 +275,8 @@ int mac_nr::cell_cfg(const std::vector& } } + rx.reset(new mac_nr_rx{rlc, rrc, stack_task_queue, sched.get(), logger}); + return SRSRAN_SUCCESS; } @@ -373,7 +524,7 @@ int mac_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_ph return SRSRAN_SUCCESS; } -bool mac_nr::handle_uci_data(const uint16_t rnti, const srsran_uci_cfg_nr_t& cfg_, const srsran_uci_value_nr_t& value) +bool mac_nr::handle_uci_data(uint16_t rnti, const srsran_uci_cfg_nr_t& cfg_, const srsran_uci_value_nr_t& value) { // Process HARQ-ACK for (uint32_t i = 0; i < cfg_.ack.count; i++) { @@ -422,15 +573,8 @@ int mac_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr:: pusch_info.pdu->msg, pusch_info.pdu->N_bytes, pusch_info.rnti, pusch_info.pid, slot_cfg.idx); } - auto process_pdu_task = [this, rnti](srsran::unique_byte_buffer_t& pdu) { - srsran::rwlock_read_guard lock(rwmutex); - if (is_rnti_active_nolock(rnti)) { - ue_db[rnti]->process_pdu(std::move(pdu)); - } else { - logger.debug("Discarding PDU rnti=0x%x", rnti); - } - }; - stack_task_queue.try_push(std::bind(process_pdu_task, std::move(pusch_info.pdu))); + // Decode and send PDU to upper layers + rx->handle_pdu(rnti, std::move(pusch_info.pdu)); } srsran::rwlock_read_guard rw_lock(rwmutex); if (ue_db.contains(rnti)) { diff --git a/srsgnb/src/stack/mac/ue_nr.cc b/srsgnb/src/stack/mac/ue_nr.cc index c6fe7d3ee..5c5d465d0 100644 --- a/srsgnb/src/stack/mac/ue_nr.cc +++ b/srsgnb/src/stack/mac/ue_nr.cc @@ -59,96 +59,6 @@ void ue_nr::set_tti(uint32_t tti) last_tti = tti; } -int ue_nr::process_pdu(srsran::unique_byte_buffer_t pdu) -{ - logger.debug(pdu->msg, pdu->N_bytes, "Handling MAC PDU (%d B)", pdu->N_bytes); - - mac_pdu_ul.init_rx(true); - if (mac_pdu_ul.unpack(pdu->msg, pdu->N_bytes) != SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - - if (logger.info.enabled()) { - fmt::memory_buffer str_buffer; - mac_pdu_ul.to_string(str_buffer); - logger.info("Rx PDU: rnti=0x%x, %s", rnti, srsran::to_c_str(str_buffer)); - } - - // Process MAC CRNTI CE first, if it exists - uint32_t crnti_ce_pos = mac_pdu_ul.get_num_subpdus(); - for (uint32_t n = mac_pdu_ul.get_num_subpdus(); n > 0; --n) { - srsran::mac_sch_subpdu_nr& subpdu = mac_pdu_ul.get_subpdu(n - 1); - if (subpdu.get_lcid() == srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CRNTI) { - if (process_ce_subpdu(subpdu) != SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - crnti_ce_pos = n - 1; - } - } - - // Process SDUs and remaining MAC CEs - for (uint32_t n = 0; n < mac_pdu_ul.get_num_subpdus(); ++n) { - srsran::mac_sch_subpdu_nr& subpdu = mac_pdu_ul.get_subpdu(n); - if (subpdu.is_sdu()) { - rrc->set_activity_user(rnti); - rlc->write_pdu(rnti, subpdu.get_lcid(), subpdu.get_sdu(), subpdu.get_sdu_length()); - } else if (n != crnti_ce_pos) { - if (process_ce_subpdu(subpdu) != SRSRAN_SUCCESS) { - return SRSRAN_ERROR; - } - } - } - - return SRSRAN_SUCCESS; -} - -int ue_nr::process_ce_subpdu(const srsran::mac_sch_subpdu_nr& subpdu) -{ - // Handle MAC CEs - switch (subpdu.get_lcid()) { - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::CRNTI: { - uint16_t c_rnti = subpdu.get_c_rnti(); - if (true /*sched->ue_exists(c_crnti)*/) { - rrc->update_user(rnti, c_rnti); - rnti = c_rnti; - sched->ul_sr_info(rnti); // provide UL grant regardless of other BSR content for UE to complete RA - } else { - logger.warning("Updating user C-RNTI: rnti=0x%x already released.", c_rnti); - // Disable scheduling for all bearers. The new rnti will be removed on msg3 timer expiry in the RRC - for (uint32_t lcid = 0; lcid < sched_interface::MAX_LC; ++lcid) { - // sched->bearer_ue_rem(rnti, lcid); - } - } - } break; - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::SHORT_BSR: - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::SHORT_TRUNC_BSR: { - srsran::mac_sch_subpdu_nr::lcg_bsr_t sbsr = subpdu.get_sbsr(); - uint32_t buffer_size_bytes = buff_size_field_to_bytes(sbsr.buffer_size, srsran::SHORT_BSR); - // Assume all LCGs are 0 if reported SBSR is 0 - if (buffer_size_bytes == 0) { - for (uint32_t j = 0; j <= SCHED_NR_MAX_LC_GROUP; j++) { - sched->ul_bsr(rnti, j, 0); - } - } else { - sched->ul_bsr(rnti, sbsr.lcg_id, buffer_size_bytes); - } - } break; - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::LONG_BSR: - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::LONG_TRUNC_BSR: { - srsran::mac_sch_subpdu_nr::lbsr_t lbsr = subpdu.get_lbsr(); - for (auto& lb : lbsr.list) { - sched->ul_bsr(rnti, lb.lcg_id, buff_size_field_to_bytes(lb.buffer_size, srsran::LONG_BSR)); - } - } break; - case srsran::mac_sch_subpdu_nr::nr_lcid_sch_t::PADDING: - break; - default: - logger.warning("Unhandled subPDU with LCID=%d", subpdu.get_lcid()); - } - - return SRSRAN_SUCCESS; -} - uint32_t ue_nr::read_pdu(uint32_t lcid, uint8_t* payload, uint32_t requested_bytes) { return rlc->read_pdu(rnti, lcid, payload, requested_bytes); @@ -326,41 +236,4 @@ void ue_nr::metrics_pusch_sinr(float sinr) } } -/** Converts the buffer size field of a BSR (5 or 8-bit Buffer Size field) into Bytes - * @param buff_size_field The buffer size field contained in the MAC PDU - * @param format The BSR format that determines the buffer size field length - * @return uint32_t The actual buffer size level in Bytes - */ -uint32_t ue_nr::buff_size_field_to_bytes(uint32_t buff_size_index, const srsran::bsr_format_nr_t& format) -{ - using namespace srsran; - - // early exit - if (buff_size_index == 0) { - return 0; - } - - const uint32_t max_offset = 1; // make the reported value bigger than the 2nd biggest - - switch (format) { - case SHORT_BSR: - case SHORT_TRUNC_BSR: - if (buff_size_index >= buffer_size_levels_5bit_max_idx) { - return buffer_size_levels_5bit[buffer_size_levels_5bit_max_idx] + max_offset; - } else { - return buffer_size_levels_5bit[buff_size_index]; - } - break; - case LONG_BSR: - case LONG_TRUNC_BSR: - if (buff_size_index > buffer_size_levels_8bit_max_idx) { - return buffer_size_levels_8bit[buffer_size_levels_8bit_max_idx] + max_offset; - } else { - return buffer_size_levels_8bit[buff_size_index]; - } - break; - } - return 0; -} - } // namespace srsenb From 60d4d1207005f28e44af84c84c28addd949b44aa Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 2 Nov 2021 20:13:18 +0000 Subject: [PATCH 19/35] nr,gnb,mac: implement basic sib1 scheduling --- srsgnb/hdr/stack/mac/mac_nr.h | 5 +- srsgnb/hdr/stack/mac/sched_nr_bwp.h | 26 +--- .../hdr/stack/mac/sched_nr_grant_allocator.h | 16 ++- srsgnb/hdr/stack/mac/sched_nr_helpers.h | 2 + srsgnb/hdr/stack/mac/sched_nr_interface.h | 4 +- srsgnb/hdr/stack/mac/sched_nr_signalling.h | 35 +++++- srsgnb/src/stack/mac/mac_nr.cc | 7 +- srsgnb/src/stack/mac/sched_nr_bwp.cc | 62 +--------- .../src/stack/mac/sched_nr_grant_allocator.cc | 58 ++++++--- srsgnb/src/stack/mac/sched_nr_pdcch.cc | 1 - srsgnb/src/stack/mac/sched_nr_signalling.cc | 113 ++++++++++++++++-- srsgnb/src/stack/mac/sched_nr_worker.cc | 8 +- 12 files changed, 210 insertions(+), 127 deletions(-) diff --git a/srsgnb/hdr/stack/mac/mac_nr.h b/srsgnb/hdr/stack/mac/mac_nr.h index c700f50bd..1b26be4c5 100644 --- a/srsgnb/hdr/stack/mac/mac_nr.h +++ b/srsgnb/hdr/stack/mac/mac_nr.h @@ -89,8 +89,9 @@ private: void get_metrics_nolock(srsenb::mac_metrics_t& metrics); // Encoding - srsran::byte_buffer_t* assemble_rar(srsran::const_span grants); - srsran::unique_byte_buffer_t rar_pdu_buffer = nullptr; + srsran::byte_buffer_t* assemble_rar(srsran::const_span grants); + + srsran::unique_byte_buffer_t rar_pdu_buffer; // Interaction with other components phy_interface_stack_nr* phy = nullptr; diff --git a/srsgnb/hdr/stack/mac/sched_nr_bwp.h b/srsgnb/hdr/stack/mac/sched_nr_bwp.h index 5f00b058e..3b9a3c7e4 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_bwp.h +++ b/srsgnb/hdr/stack/mac/sched_nr_bwp.h @@ -15,36 +15,13 @@ #include "sched_nr_cfg.h" #include "sched_nr_grant_allocator.h" +#include "sched_nr_signalling.h" #include "sched_nr_time_rr.h" #include "srsran/adt/pool/cached_alloc.h" namespace srsenb { namespace sched_nr_impl { -/// SIB scheduler -class si_sched -{ -public: - explicit si_sched(const bwp_params_t& bwp_cfg_); - - void run_slot(bwp_slot_allocator& slot_alloc); - -private: - const bwp_params_t* bwp_cfg = nullptr; - srslog::basic_logger& logger; - - struct sched_si_t { - uint32_t n = 0; - uint32_t len = 0; - uint32_t win_len = 0; - uint32_t period = 0; - uint32_t n_tx = 0; - alloc_result result = alloc_result::invalid_coderate; - slot_point win_start; - }; - srsran::bounded_vector pending_sis; -}; - using dl_sched_rar_info_t = sched_nr_interface::rar_info_t; /// RAR/Msg3 scheduler @@ -87,6 +64,7 @@ public: const bwp_params_t* cfg; // channel-specific schedulers + si_sched si; ra_sched ra; std::unique_ptr data_sched; diff --git a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h index 8ff63de58..b295a0987 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h +++ b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h @@ -54,6 +54,8 @@ struct bwp_slot_grid { slot_coreset_list coresets; harq_ack_list_t pending_acks; + srsran::bounded_vector sib_idxs; + srsran::unique_pool_ptr rar_softbuffer; bwp_slot_grid() = default; @@ -98,11 +100,14 @@ public: alloc_result alloc_pdsch(slot_ue& ue, const prb_grant& dl_grant); alloc_result alloc_pusch(slot_ue& ue, const prb_grant& dl_mask); - slot_point get_pdcch_tti() const { return pdcch_slot; } - slot_point get_tti_rx() const { return pdcch_slot - TX_ENB_DELAY; } - const bwp_res_grid& res_grid() const { return bwp_grid; } + slot_point get_pdcch_tti() const { return pdcch_slot; } + slot_point get_tti_rx() const { return pdcch_slot - TX_ENB_DELAY; } + const bwp_res_grid& res_grid() const { return bwp_grid; } + const bwp_slot_grid& tx_slot_grid() const { return bwp_grid[pdcch_slot]; } + bwp_slot_grid& tx_slot_grid() { return bwp_grid[pdcch_slot]; } - const bwp_params_t& cfg; + srslog::basic_logger& logger; + const bwp_params_t& cfg; private: alloc_result @@ -110,8 +115,7 @@ private: alloc_result verify_pusch_space(bwp_slot_grid& pusch_grid, bwp_slot_grid* pdcch_grid = nullptr) const; alloc_result verify_ue_cfg(const ue_carrier_params_t& ue_cfg, harq_proc* harq) const; - srslog::basic_logger& logger; - bwp_res_grid& bwp_grid; + bwp_res_grid& bwp_grid; slot_point pdcch_slot; slot_ue_map_t& slot_ues; diff --git a/srsgnb/hdr/stack/mac/sched_nr_helpers.h b/srsgnb/hdr/stack/mac/sched_nr_helpers.h index 81265827c..ed47bf3b2 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_helpers.h +++ b/srsgnb/hdr/stack/mac/sched_nr_helpers.h @@ -25,6 +25,8 @@ struct bwp_res_grid; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool fill_dci_sib(prb_interval interv, uint32_t sib_idx, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci); + bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci); bool fill_dci_msg3(const slot_ue& ue, const bwp_params_t& bwp_cfg, srsran_dci_ul_nr_t& dci); diff --git a/srsgnb/hdr/stack/mac/sched_nr_interface.h b/srsgnb/hdr/stack/mac/sched_nr_interface.h index 8db73f1b0..8ff4ca3fa 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_interface.h +++ b/srsgnb/hdr/stack/mac/sched_nr_interface.h @@ -89,7 +89,7 @@ public: using ue_cc_cfg_t = sched_nr_ue_cc_cfg_t; using ue_cfg_t = sched_nr_ue_cfg_t; - ////// RA procedure ////// + ////// RA signalling ////// struct rar_info_t { uint32_t preamble_idx; // is this the RAPID? @@ -117,6 +117,8 @@ public: struct dl_res_t { dl_sched_t phy; sched_rar_list_t rar; + + srsran::bounded_vector sib_idxs; }; virtual ~sched_nr_interface() = default; diff --git a/srsgnb/hdr/stack/mac/sched_nr_signalling.h b/srsgnb/hdr/stack/mac/sched_nr_signalling.h index d3188469a..5a4f804d7 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_signalling.h +++ b/srsgnb/hdr/stack/mac/sched_nr_signalling.h @@ -13,12 +13,15 @@ #ifndef SRSRAN_SCHED_NR_SIGNALLING_H #define SRSRAN_SCHED_NR_SIGNALLING_H +#include "../sched_common.h" #include "sched_nr_cfg.h" #include "sched_nr_interface.h" namespace srsenb { namespace sched_nr_impl { +class bwp_slot_allocator; + /// Schedule NZP-CSI-RS resources for given slot void sched_nzp_csi_rs(srsran::const_span nzp_csi_rs_sets, const srsran_slot_cfg_t& slot_cfg, @@ -41,11 +44,35 @@ void sched_nzp_csi_rs(srsran::const_span nzp_csi_rs_set */ void sched_ssb_basic(const slot_point& sl_point, uint32_t ssb_periodicity, ssb_list& ssb_list); +/// Fill DCI fields with SIB info +bool fill_dci_sib(prb_interval interv, uint32_t sib_idx, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci); + /// For a given BWP and slot, schedule SSB, NZP CSI RS and SIBs -void sched_dl_signalling(const bwp_params_t& bwp_params, - slot_point sl_pdcch, - ssb_list& ssb_list, - nzp_csi_rs_list& nzp_csi_rs); +void sched_dl_signalling(bwp_slot_allocator& bwp_alloc); + +/// scheduler for SIBs +class si_sched +{ +public: + explicit si_sched(const bwp_params_t& bwp_cfg_); + + void run_slot(bwp_slot_allocator& slot_alloc); + +private: + const bwp_params_t* bwp_cfg = nullptr; + srslog::basic_logger& logger; + + struct si_msg_ctxt_t { + uint32_t n = 0; /// index in schedulingInfoList in si-SchedulingInfo in SIB1 + uint32_t len = 0; + uint32_t win_len = 0; + uint32_t period = 0; + uint32_t n_tx = 0; + alloc_result result = alloc_result::invalid_coderate; /// last attempt to schedule SI + slot_point win_start; /// start of SI window, invalid if outside + }; + srsran::bounded_vector pending_sis; +}; } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsgnb/src/stack/mac/mac_nr.cc b/srsgnb/src/stack/mac/mac_nr.cc index 426678a87..d3a60acff 100644 --- a/srsgnb/src/stack/mac/mac_nr.cc +++ b/srsgnb/src/stack/mac/mac_nr.cc @@ -260,7 +260,7 @@ int mac_nr::cell_cfg(const std::vector& if (true) { sib_info_t sib = {}; sib.index = i; - sib.periodicity = 4; // TODO: read period_rf from config + sib.periodicity = 160; // TODO: read period_rf from config sib.payload = srsran::make_byte_buffer(); if (sib.payload == nullptr) { logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); @@ -460,7 +460,7 @@ mac_nr::dl_sched_t* mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg) } // Generate MAC DL PDUs - uint32_t rar_count = 0; + uint32_t rar_count = 0, si_count = 0; srsran::rwlock_read_guard rw_lock(rwmutex); for (pdsch_t& pdsch : dl_res->phy.pdsch) { if (pdsch.sch.grant.rnti_type == srsran_rnti_type_c) { @@ -484,6 +484,9 @@ mac_nr::dl_sched_t* mac_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg) sched_nr_interface::rar_t& rar = dl_res->rar[rar_count++]; // for RARs we could actually move the byte_buffer to the PHY, as there are no retx pdsch.data[0] = assemble_rar(rar.grants); + } else if (pdsch.sch.grant.rnti_type == srsran_rnti_type_si) { + uint32_t sib_idx = dl_res->sib_idxs[si_count++]; + pdsch.data[0] = bcch_dlsch_payload[sib_idx].payload.get(); } } for (auto& u : ue_db) { diff --git a/srsgnb/src/stack/mac/sched_nr_bwp.cc b/srsgnb/src/stack/mac/sched_nr_bwp.cc index 2b82b1d0d..c198a4a9a 100644 --- a/srsgnb/src/stack/mac/sched_nr_bwp.cc +++ b/srsgnb/src/stack/mac/sched_nr_bwp.cc @@ -17,66 +17,6 @@ namespace srsenb { namespace sched_nr_impl { -si_sched::si_sched(const bwp_params_t& bwp_cfg_) : - bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) -{} - -void si_sched::run_slot(bwp_slot_allocator& slot_alloc) -{ - const uint32_t si_aggr_level = 2; - slot_point pdcch_slot = slot_alloc.get_pdcch_tti(); - const prb_bitmap& prbs = slot_alloc.res_grid()[pdcch_slot].dl_prbs.prbs(); - - // Update SI windows - uint32_t N = bwp_cfg->slots.size(); - for (sched_si_t& si : pending_sis) { - uint32_t x = (si.n - 1) * si.win_len; - - if (not si.win_start.valid() and (pdcch_slot.sfn() % si.period == x / N) and - pdcch_slot.slot_idx() == x % bwp_cfg->slots.size()) { - // If start o SI message window - si.win_start = pdcch_slot; - } else if (si.win_start.valid() and si.win_start + si.win_len >= pdcch_slot) { - // If end of SI message window - logger.warning( - "SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); - si.win_start.clear(); - } - } - - // Schedule pending SIs - if (bwp_cfg->slots[pdcch_slot.slot_idx()].is_dl) { - for (sched_si_t& si : pending_sis) { - if (not si.win_start.valid()) { - continue; - } - - // TODO: NOTE 2: The UE is not required to monitor PDCCH monitoring occasion(s) corresponding to each transmitted - // SSB in SI-window. - - // Attempt grants with increasing number of PRBs (if the number of PRBs is too low, the coderate is invalid) - si.result = alloc_result::invalid_coderate; - uint32_t prb_start_idx = 0; - for (uint32_t nprbs = 4; nprbs < bwp_cfg->cfg.rb_width and si.result == alloc_result::invalid_coderate; ++nprbs) { - prb_interval grant = find_empty_interval_of_length(prbs, nprbs, prb_start_idx); - prb_start_idx = grant.start(); - if (grant.length() != nprbs) { - si.result = alloc_result::no_sch_space; - break; - } - si.result = slot_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant); - if (si.result == alloc_result::success) { - // SIB scheduled successfully - si.win_start.clear(); - si.n_tx++; - } - } - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - ra_sched::ra_sched(const bwp_params_t& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) {} @@ -221,7 +161,7 @@ int ra_sched::dl_rach_info(const dl_sched_rar_info_t& rar_info) } bwp_manager::bwp_manager(const bwp_params_t& bwp_cfg) : - cfg(&bwp_cfg), ra(bwp_cfg), grid(bwp_cfg), data_sched(new sched_nr_time_rr()) + cfg(&bwp_cfg), ra(bwp_cfg), si(bwp_cfg), grid(bwp_cfg), data_sched(new sched_nr_time_rr()) {} } // namespace sched_nr_impl diff --git a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index 95aa5f1cf..82a06e17e 100644 --- a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -47,6 +47,7 @@ void bwp_slot_grid::reset() dl.phy.pdcch_ul.clear(); dl.phy.pdsch.clear(); dl.rar.clear(); + dl.sib_idxs.clear(); ul.pusch.clear(); ul.pucch.clear(); pending_acks.clear(); @@ -68,20 +69,42 @@ bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_, slot_point pdcch alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, uint32_t si_ntx, const prb_interval& prbs) { bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_slot]; - if (not bwp_pdcch_slot.is_dl()) { - logger.warning("SCHED: Trying to allocate PDSCH in TDD non-DL slot index=%d", bwp_pdcch_slot.slot_idx); - return alloc_result::no_sch_space; - } - pdcch_dl_list_t& pdsch_grants = bwp_pdcch_slot.dl.phy.pdcch_dl; - if (pdsch_grants.full()) { - logger.warning("SCHED: Maximum number of DL allocations reached"); - return alloc_result::no_grant_space; + alloc_result ret = verify_pdsch_space(bwp_pdcch_slot, bwp_pdcch_slot); + if (ret != alloc_result::success) { + return ret; } if (bwp_pdcch_slot.dl_prbs.collides(prbs)) { return alloc_result::sch_collision; } - // TODO: Allocate PDCCH and PDSCH + const uint32_t coreset_id = 0; + const uint32_t ss_id = 0; + if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::sib, aggr_idx, ss_id)) { + logger.warning("SCHED: Cannot allocate SIB1."); + return alloc_result::no_cch_space; + } + + // RAR allocation successful. + bwp_pdcch_slot.dl_prbs |= prbs; + // Generate DCI for RAR with given RA-RNTI + pdcch_dl_t& pdcch = bwp_pdcch_slot.dl.phy.pdcch_dl.back(); + if (not fill_dci_sib(prbs, si_idx, *bwp_grid.cfg, pdcch.dci)) { + // Cancel on-going PDCCH allocation + bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); + return alloc_result::invalid_coderate; + } + + // Generate PDSCH + bwp_pdcch_slot.dl.phy.pdsch.emplace_back(); + pdsch_t& pdsch = bwp_pdcch_slot.dl.phy.pdsch.back(); + srsran_slot_cfg_t slot_cfg; + slot_cfg.idx = pdcch_slot.to_uint(); + int code = srsran_ra_dl_dci_to_grant_nr( + &cfg.cell_cfg.carrier, &slot_cfg, &cfg.cfg.pdsch, &pdcch.dci, &pdsch.sch, &pdsch.sch.grant); + srsran_assert(code == SRSRAN_SUCCESS, "Error converting DCI to grant"); + + // Store SI msg index + bwp_pdcch_slot.sib_idxs.push_back(si_idx); return alloc_result::success; } @@ -104,6 +127,11 @@ alloc_result bwp_slot_allocator::alloc_rar_and_msg3(uint16_t if (ret != alloc_result::success) { return ret; } + if (not bwp_pdcch_slot.dl.phy.ssb.empty()) { + // TODO: support concurrent PDSCH and SSB + logger.debug("SCHED: skipping RAR allocation. Cause: concurrent PDSCH and SSB not yet supported"); + return alloc_result::no_sch_space; + } if (pending_rachs.size() > bwp_pdcch_slot.dl.rar.capacity() - bwp_pdcch_slot.dl.rar.size()) { logger.error("SCHED: Trying to allocate too many Msg3 grants in a single slot (%zd)", pending_rachs.size()); return alloc_result::invalid_grant_params; @@ -210,6 +238,11 @@ alloc_result bwp_slot_allocator::alloc_pdsch(slot_ue& ue, const prb_grant& dl_gr if (result != alloc_result::success) { return result; } + if (not bwp_pdsch_slot.dl.phy.ssb.empty()) { + // TODO: support concurrent PDSCH and SSB + logger.debug("SCHED: skipping PDSCH allocation. Cause: concurrent PDSCH and SSB not yet supported"); + return alloc_result::no_sch_space; + } if (bwp_pdsch_slot.dl_prbs.collides(dl_grant)) { return alloc_result::sch_collision; } @@ -386,11 +419,6 @@ alloc_result bwp_slot_allocator::verify_pdsch_space(bwp_slot_grid& pdsch_grid, return alloc_result::no_grant_space; } } - if (not pdsch_grid.dl.phy.ssb.empty()) { - // TODO: support concurrent PDSCH and SSB - logger.debug("SCHED: skipping PDSCH allocation. Cause: concurrent PDSCH and SSB not yet supported"); - return alloc_result::no_sch_space; - } return alloc_result::success; } @@ -433,4 +461,4 @@ alloc_result bwp_slot_allocator::verify_ue_cfg(const ue_carrier_params_t& ue_cfg } } // namespace sched_nr_impl -} // namespace srsenb \ No newline at end of file +} // namespace srsenb diff --git a/srsgnb/src/stack/mac/sched_nr_pdcch.cc b/srsgnb/src/stack/mac/sched_nr_pdcch.cc index 78709bf42..bed4c0c6a 100644 --- a/srsgnb/src/stack/mac/sched_nr_pdcch.cc +++ b/srsgnb/src/stack/mac/sched_nr_pdcch.cc @@ -55,7 +55,6 @@ bool coreset_region::alloc_dci(pdcch_grant_type_t alloc_type, srsran_assert((user == nullptr) xor (alloc_type == pdcch_grant_type_t::dl_data or alloc_type == pdcch_grant_type_t::ul_data), "UE should be only provided for DL or UL data allocations"); - srsran_assert(not dci_list.full(), "SCHED: Unable to allocate DCI"); saved_dfs_tree.clear(); alloc_record record; diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index df738a0b0..15b0321aa 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -11,6 +11,7 @@ */ #include "srsgnb/hdr/stack/mac/sched_nr_signalling.h" +#include "srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h" #define POS_IN_BURST_FIRST_BIT_IDX 0 #define POS_IN_BURST_SECOND_BIT_IDX 1 @@ -83,23 +84,119 @@ void sched_ssb_basic(const slot_point& sl_point, uint32_t ssb_periodicity, ssb_l } } -void sched_dl_signalling(const bwp_params_t& bwp_params, - slot_point sl_pdcch, - ssb_list& ssb_list, - nzp_csi_rs_list& nzp_csi_rs) +void sched_dl_signalling(bwp_slot_allocator& bwp_alloc) { + const bwp_params_t& bwp_params = bwp_alloc.cfg; + slot_point sl_pdcch = bwp_alloc.get_pdcch_tti(); + bwp_slot_grid& sl_grid = bwp_alloc.tx_slot_grid(); + srsran_slot_cfg_t cfg; cfg.idx = sl_pdcch.to_uint(); // Schedule SSB - sched_ssb_basic(sl_pdcch, bwp_params.cell_cfg.ssb.periodicity_ms, ssb_list); + sched_ssb_basic(sl_pdcch, bwp_params.cell_cfg.ssb.periodicity_ms, sl_grid.dl.phy.ssb); // Schedule NZP-CSI-RS - sched_nzp_csi_rs(bwp_params.cfg.pdsch.nzp_csi_rs_sets, cfg, nzp_csi_rs); + sched_nzp_csi_rs(bwp_params.cfg.pdsch.nzp_csi_rs_sets, cfg, sl_grid.dl.phy.nzp_csi_rs); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +bool fill_dci_sib(prb_interval interv, uint32_t sib_id, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci) +{ + dci.mcs = 5; + dci.ctx.format = srsran_dci_format_nr_1_0; + dci.ctx.ss_type = srsran_search_space_type_common_0; + dci.ctx.rnti_type = srsran_rnti_type_si; + dci.ctx.rnti = SRSRAN_SIRNTI; + dci.ctx.coreset_id = 0; + dci.freq_domain_assigment = srsran_ra_nr_type1_riv(bwp_cfg.cfg.rb_width, interv.start(), interv.length()); + dci.time_domain_assigment = 0; + dci.tpc = 1; + dci.bwp_id = bwp_cfg.bwp_id; + dci.cc_id = bwp_cfg.cc; + dci.rv = 0; + dci.sii = sib_id == 1 ? 0 : 1; + + return true; +} + +si_sched::si_sched(const bwp_params_t& bwp_cfg_) : + bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) +{} + +void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) +{ + if (true) { + // CORESET#0 must be present, otherwise SIs are not allocated + // TODO: provide proper config + return; + } + const uint32_t si_aggr_level = 2; + slot_point sl_pdcch = bwp_alloc.get_pdcch_tti(); + const prb_bitmap& prbs = bwp_alloc.res_grid()[sl_pdcch].dl_prbs.prbs(); + + // SIB1 case + if (sl_pdcch.to_uint() % 160 == 0) { + // TODO: compute if SIB1 slot based on config + const uint32_t aggr_lvl_idx = 2; + const uint32_t sib_id = 1; + const uint32_t sib1len = 77; // TODO: extract from config + alloc_result ret = bwp_alloc.alloc_si(aggr_lvl_idx, sib_id, sib1len, prb_interval{0, 7}); + if (ret != alloc_result::success) { + bwp_alloc.logger.warning("SCHED: Cannot allocate SIB1."); + } + } + + // Update SI windows + uint32_t N = bwp_cfg->slots.size(); + for (si_msg_ctxt_t& si : pending_sis) { + uint32_t x = (si.n - 1) * si.win_len; + + if (not si.win_start.valid() and (sl_pdcch.sfn() % si.period == x / N) and + sl_pdcch.slot_idx() == x % bwp_cfg->slots.size()) { + // If start of SI message window + si.win_start = sl_pdcch; + } else if (si.win_start.valid() and si.win_start + si.win_len >= sl_pdcch) { + // If end of SI message window + logger.warning( + "SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); + si.win_start.clear(); + } + } + + // Schedule pending SIs + if (bwp_cfg->slots[sl_pdcch.slot_idx()].is_dl) { + for (si_msg_ctxt_t& si : pending_sis) { + if (not si.win_start.valid()) { + continue; + } - // Schedule SIBs - // TODO + // TODO: NOTE 2: The UE is not required to monitor PDCCH monitoring occasion(s) corresponding to each transmitted + // SSB in SI-window. + + // Attempt grants with increasing number of PRBs (if the number of PRBs is too low, the coderate is invalid) + si.result = alloc_result::invalid_coderate; + uint32_t prb_start_idx = 0; + for (uint32_t nprbs = 4; nprbs < bwp_cfg->cfg.rb_width and si.result == alloc_result::invalid_coderate; ++nprbs) { + prb_interval grant = find_empty_interval_of_length(prbs, nprbs, prb_start_idx); + prb_start_idx = grant.start(); + if (grant.length() != nprbs) { + si.result = alloc_result::no_sch_space; + break; + } + si.result = bwp_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant); + if (si.result == alloc_result::success) { + // SIB scheduled successfully + si.win_start.clear(); + si.n_tx++; + } + } + } + } } +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsgnb/src/stack/mac/sched_nr_worker.cc b/srsgnb/src/stack/mac/sched_nr_worker.cc index c4ac886c5..1792d6d26 100644 --- a/srsgnb/src/stack/mac/sched_nr_worker.cc +++ b/srsgnb/src/stack/mac/sched_nr_worker.cc @@ -69,8 +69,10 @@ dl_sched_res_t* cc_worker::run_slot(slot_point pdcch_slot, ue_map_t& ue_db) log_sched_slot_ues(logger, pdcch_slot, cfg.cc, slot_ues); // Allocate cell DL signalling - bwp_slot_grid& bwp_pdcch_slot = bwps[0].grid[pdcch_slot]; - sched_dl_signalling(*bwps[0].cfg, pdcch_slot, bwp_pdcch_slot.dl.phy.ssb, bwp_pdcch_slot.dl.phy.nzp_csi_rs); + sched_dl_signalling(bwp_alloc); + + // Allocate pending SIBs + bwps[0].si.run_slot(bwp_alloc); // Allocate pending RARs bwps[0].ra.run_slot(bwp_alloc); @@ -88,7 +90,7 @@ dl_sched_res_t* cc_worker::run_slot(slot_point pdcch_slot, ue_map_t& ue_db) // releases UE resources slot_ues.clear(); - return &bwp_pdcch_slot.dl; + return &bwp_alloc.tx_slot_grid().dl; } ul_sched_t* cc_worker::get_ul_sched(slot_point sl) From 72c2129cd39bd6f8ad96aeb58dc5fc03b18e8388 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 3 Nov 2021 09:45:09 +0000 Subject: [PATCH 20/35] nr,gnb,sched: fix sib1 window derivation in NR sched --- srsgnb/hdr/stack/mac/sched_nr_signalling.h | 4 +- srsgnb/src/stack/mac/sched_nr_signalling.cc | 102 +++++++++++--------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/srsgnb/hdr/stack/mac/sched_nr_signalling.h b/srsgnb/hdr/stack/mac/sched_nr_signalling.h index 5a4f804d7..46745dd72 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_signalling.h +++ b/srsgnb/hdr/stack/mac/sched_nr_signalling.h @@ -63,7 +63,7 @@ private: srslog::basic_logger& logger; struct si_msg_ctxt_t { - uint32_t n = 0; /// index in schedulingInfoList in si-SchedulingInfo in SIB1 + uint32_t n = 0; /// 0 for SIB1, n/index in schedulingInfoList in si-SchedulingInfo in SIB1 uint32_t len = 0; uint32_t win_len = 0; uint32_t period = 0; @@ -71,7 +71,7 @@ private: alloc_result result = alloc_result::invalid_coderate; /// last attempt to schedule SI slot_point win_start; /// start of SI window, invalid if outside }; - srsran::bounded_vector pending_sis; + srsran::bounded_vector pending_sis; /// configured SIB1 and SI messages }; } // namespace sched_nr_impl diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index 15b0321aa..259007373 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -123,7 +123,14 @@ bool fill_dci_sib(prb_interval interv, uint32_t sib_id, const bwp_params_t& bwp_ si_sched::si_sched(const bwp_params_t& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) -{} +{ + // TODO: Get SIB1 other SI msgs config from RRC + pending_sis.emplace_back(); + pending_sis[0].n = 0; + pending_sis[0].len = 77; + pending_sis[0].period = 160; + pending_sis[0].win_len = 1; +} void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) { @@ -136,60 +143,67 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) slot_point sl_pdcch = bwp_alloc.get_pdcch_tti(); const prb_bitmap& prbs = bwp_alloc.res_grid()[sl_pdcch].dl_prbs.prbs(); - // SIB1 case - if (sl_pdcch.to_uint() % 160 == 0) { - // TODO: compute if SIB1 slot based on config - const uint32_t aggr_lvl_idx = 2; - const uint32_t sib_id = 1; - const uint32_t sib1len = 77; // TODO: extract from config - alloc_result ret = bwp_alloc.alloc_si(aggr_lvl_idx, sib_id, sib1len, prb_interval{0, 7}); - if (ret != alloc_result::success) { - bwp_alloc.logger.warning("SCHED: Cannot allocate SIB1."); - } - } - // Update SI windows uint32_t N = bwp_cfg->slots.size(); for (si_msg_ctxt_t& si : pending_sis) { uint32_t x = (si.n - 1) * si.win_len; - if (not si.win_start.valid() and (sl_pdcch.sfn() % si.period == x / N) and - sl_pdcch.slot_idx() == x % bwp_cfg->slots.size()) { - // If start of SI message window - si.win_start = sl_pdcch; - } else if (si.win_start.valid() and si.win_start + si.win_len >= sl_pdcch) { + if (not si.win_start.valid()) { + bool start_window; + if (si.n == 0) { + // SIB1 + start_window = sl_pdcch.to_uint() % si.period == 0; + } else { + // SI messages + start_window = (sl_pdcch.sfn() % si.period == x / N) and sl_pdcch.slot_idx() == x % bwp_cfg->slots.size(); + } + if (start_window) { + // If start of SI message window + si.win_start = sl_pdcch; + } + } else if (si.win_start + si.win_len >= sl_pdcch) { // If end of SI message window - logger.warning( - "SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); + if (si.n == 0) { + logger.error("SCHED: Could not allocate SIB1, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); + } else { + logger.warning( + "SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); + } si.win_start.clear(); } } - // Schedule pending SIs - if (bwp_cfg->slots[sl_pdcch.slot_idx()].is_dl) { - for (si_msg_ctxt_t& si : pending_sis) { - if (not si.win_start.valid()) { - continue; - } + // Schedule pending SIBs + if (not bwp_cfg->slots[sl_pdcch.slot_idx()].is_dl) { + return; + } + for (si_msg_ctxt_t& si : pending_sis) { + if (not si.win_start.valid()) { + continue; + } - // TODO: NOTE 2: The UE is not required to monitor PDCCH monitoring occasion(s) corresponding to each transmitted - // SSB in SI-window. - - // Attempt grants with increasing number of PRBs (if the number of PRBs is too low, the coderate is invalid) - si.result = alloc_result::invalid_coderate; - uint32_t prb_start_idx = 0; - for (uint32_t nprbs = 4; nprbs < bwp_cfg->cfg.rb_width and si.result == alloc_result::invalid_coderate; ++nprbs) { - prb_interval grant = find_empty_interval_of_length(prbs, nprbs, prb_start_idx); - prb_start_idx = grant.start(); - if (grant.length() != nprbs) { - si.result = alloc_result::no_sch_space; - break; - } - si.result = bwp_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant); - if (si.result == alloc_result::success) { - // SIB scheduled successfully - si.win_start.clear(); - si.n_tx++; + // TODO: NOTE 2: The UE is not required to monitor PDCCH monitoring occasion(s) corresponding to each transmitted + // SSB in SI-window. + + // Attempt grants with increasing number of PRBs (if the number of PRBs is too low, the coderate is invalid) + si.result = alloc_result::invalid_coderate; + uint32_t prb_start_idx = 0; + for (uint32_t nprbs = 4; nprbs < bwp_cfg->cfg.rb_width and si.result == alloc_result::invalid_coderate; ++nprbs) { + prb_interval grant = find_empty_interval_of_length(prbs, nprbs, prb_start_idx); + prb_start_idx = grant.start(); + if (grant.length() != nprbs) { + si.result = alloc_result::no_sch_space; + break; + } + si.result = bwp_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant); + if (si.result == alloc_result::success) { + // SIB scheduled successfully + si.win_start.clear(); + si.n_tx++; + if (si.n == 0) { + logger.debug("SCHED: Allocated SIB1, len=%d.", si.n, si.len); + } else { + logger.debug("SCHED: Allocated SI message idx=%d, len=%d.", si.n, si.len); } } } From 9a267d7ed031308ef1ae78778a62532da6e725fd Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 5 Nov 2021 09:40:28 +0000 Subject: [PATCH 21/35] nr,gnb,sched: fix SIB1 periodicity derivation in NR sched --- srsgnb/src/stack/mac/sched_nr_signalling.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index 259007373..1b73f15df 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -19,6 +19,7 @@ #define POS_IN_BURST_FOURTH_BIT_IDX 3 #define DEFAULT_SSB_PERIODICITY 5 +#define MAX_SIB_TX 4 namespace srsenb { namespace sched_nr_impl { @@ -152,7 +153,7 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) bool start_window; if (si.n == 0) { // SIB1 - start_window = sl_pdcch.to_uint() % si.period == 0; + start_window = sl_pdcch.slot_idx() == 0 and sl_pdcch.sfn() % 2 == 0; } else { // SI messages start_window = (sl_pdcch.sfn() % si.period == x / N) and sl_pdcch.slot_idx() == x % bwp_cfg->slots.size(); @@ -160,6 +161,7 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) if (start_window) { // If start of SI message window si.win_start = sl_pdcch; + si.n_tx = 0; } } else if (si.win_start + si.win_len >= sl_pdcch) { // If end of SI message window @@ -178,13 +180,10 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) return; } for (si_msg_ctxt_t& si : pending_sis) { - if (not si.win_start.valid()) { + if (not si.win_start.valid() or si.n_tx >= MAX_SIB_TX) { continue; } - // TODO: NOTE 2: The UE is not required to monitor PDCCH monitoring occasion(s) corresponding to each transmitted - // SSB in SI-window. - // Attempt grants with increasing number of PRBs (if the number of PRBs is too low, the coderate is invalid) si.result = alloc_result::invalid_coderate; uint32_t prb_start_idx = 0; From 87635fe8c57ee5a187fe9203f27dc32016a2e0cd Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 5 Nov 2021 10:51:06 +0000 Subject: [PATCH 22/35] nr,gnb,sched: fix sib nof_retxs. Log SIB scheduling --- srsgnb/src/stack/mac/mac_nr.cc | 2 +- srsgnb/src/stack/mac/sched_nr_helpers.cc | 23 +++++++++++++++++---- srsgnb/src/stack/mac/sched_nr_signalling.cc | 4 ++-- srsgnb/src/stack/rrc/rrc_nr.cc | 6 +++++- 4 files changed, 27 insertions(+), 8 deletions(-) diff --git a/srsgnb/src/stack/mac/mac_nr.cc b/srsgnb/src/stack/mac/mac_nr.cc index d3a60acff..220e16942 100644 --- a/srsgnb/src/stack/mac/mac_nr.cc +++ b/srsgnb/src/stack/mac/mac_nr.cc @@ -270,7 +270,7 @@ int mac_nr::cell_cfg(const std::vector& logger.error("Couldn't read SIB %d from RRC", sib.index); } - logger.info("Including SIB %d into SI scheduling", sib.index); + logger.info("Including SIB %d into SI scheduling", sib.index + 1); bcch_dlsch_payload.push_back(std::move(sib)); } } diff --git a/srsgnb/src/stack/mac/sched_nr_helpers.cc b/srsgnb/src/stack/mac/sched_nr_helpers.cc index d3707be10..184953753 100644 --- a/srsgnb/src/stack/mac/sched_nr_helpers.cc +++ b/srsgnb/src/stack/mac/sched_nr_helpers.cc @@ -138,7 +138,7 @@ void log_sched_bwp_result(srslog::basic_logger& logger, const slot_ue_map_t& slot_ues) { const bwp_slot_grid& bwp_slot = res_grid[pdcch_slot]; - size_t rar_count = 0; + size_t rar_count = 0, si_count = 0; for (const pdcch_dl_t& pdcch : bwp_slot.dl.phy.pdcch_dl) { fmt::memory_buffer fmtbuf; if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_c) { @@ -173,11 +173,26 @@ void log_sched_bwp_result(srslog::basic_logger& logger, pdcch_slot + res_grid.cfg->pusch_ra_list[0].msg3_delay, bwp_slot.dl.rar[rar_count].grants.size()); rar_count++; - } else { - fmt::format_to(fmtbuf, "SCHED: unknown format"); + } else if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_si) { + if (logger.debug.enabled()) { + const pdsch_t& pdsch = bwp_slot.dl.phy.pdsch[std::distance(bwp_slot.dl.phy.pdcch_dl.data(), &pdcch)]; + srsran::const_span prbs{pdsch.sch.grant.prb_idx, pdsch.sch.grant.prb_idx + pdsch.sch.grant.nof_prb}; + uint32_t start_idx = std::distance(prbs.begin(), std::find(prbs.begin(), prbs.end(), true)); + uint32_t end_idx = std::distance(prbs.begin(), std::find(prbs.begin() + start_idx, prbs.end(), false)); + fmt::format_to(fmtbuf, + "SCHED: SI{}, cc={}, prbs={}, pdsch_slot={}", + pdcch.dci.sii == 0 ? "B" : " message", + res_grid.cfg->cc, + pdcch.dci.ctx.rnti, + srsran::interval{start_idx, end_idx}, + pdcch_slot); + si_count++; + } } - logger.info("%s", srsran::to_c_str(fmtbuf)); + if (fmtbuf.size() > 0) { + logger.info("%s", srsran::to_c_str(fmtbuf)); + } } for (const pdcch_ul_t& pdcch : bwp_slot.dl.phy.pdcch_ul) { fmt::memory_buffer fmtbuf; diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index 1b73f15df..2cc45a8bc 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -19,7 +19,7 @@ #define POS_IN_BURST_FOURTH_BIT_IDX 3 #define DEFAULT_SSB_PERIODICITY 5 -#define MAX_SIB_TX 4 +#define MAX_SIB_TX 8 namespace srsenb { namespace sched_nr_impl { @@ -135,7 +135,7 @@ si_sched::si_sched(const bwp_params_t& bwp_cfg_) : void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) { - if (true) { + if (not bwp_alloc.cfg.cfg.pdcch.coreset_present[0]) { // CORESET#0 must be present, otherwise SIs are not allocated // TODO: provide proper config return; diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index e2069af70..2310ba8c2 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -340,7 +340,11 @@ int32_t rrc_nr::generate_sibs() // Log SIBs in JSON format fmt::memory_buffer strbuf; - fmt::format_to(strbuf, "SI message={} payload", msg_index); + if (msg_index == 0) { + fmt::format_to(strbuf, "SIB1 payload"); + } else { + fmt::format_to(strbuf, "SI message={} payload", msg_index + 1); + } log_rrc_message(fmt::to_string(strbuf), Tx, *cell_ctxt->sib_buffer.back(), msg[msg_index], ""); } From 2fc41acd9a0504aaeb14ec1f85c0361e2c5fc2c2 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 5 Nov 2021 13:50:22 +0000 Subject: [PATCH 23/35] nr,gnb: generation of CORESET#0 and SearchSpace#0 parameters in rrc. Passing CORESET#0/SS#0 to scheduler --- srsgnb/hdr/stack/mac/sched_nr_cfg.h | 3 ++ srsgnb/hdr/stack/mac/sched_nr_pdcch.h | 4 +- srsgnb/src/stack/mac/sched_nr_cfg.cc | 18 ++++++++ .../src/stack/mac/sched_nr_grant_allocator.cc | 9 +++- srsgnb/src/stack/mac/sched_nr_pdcch.cc | 5 ++- srsgnb/src/stack/mac/sched_nr_signalling.cc | 4 +- srsgnb/src/stack/rrc/rrc_nr.cc | 42 +++++++++++++++++-- 7 files changed, 75 insertions(+), 10 deletions(-) diff --git a/srsgnb/hdr/stack/mac/sched_nr_cfg.h b/srsgnb/hdr/stack/mac/sched_nr_cfg.h index 39683e465..1f3ab955c 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_cfg.h +++ b/srsgnb/hdr/stack/mac/sched_nr_cfg.h @@ -16,6 +16,7 @@ #include "sched_nr_interface.h" #include "sched_nr_rb.h" #include "srsenb/hdr/common/common_enb.h" +#include "srsran/adt/optional_array.h" namespace srsenb { @@ -91,6 +92,8 @@ struct bwp_params_t { bwp_cce_pos_list rar_cce_list; + srsran::optional_vector common_cce_list; + bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg_, uint32_t cc, uint32_t bwp_id); }; diff --git a/srsgnb/hdr/stack/mac/sched_nr_pdcch.h b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h index 8e13d2608..99841ac7d 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_pdcch.h +++ b/srsgnb/hdr/stack/mac/sched_nr_pdcch.h @@ -63,7 +63,9 @@ private: uint32_t coreset_id; uint32_t slot_idx; uint32_t nof_freq_res = 0; - const bwp_cce_pos_list& rar_cce_list; + + const bwp_cce_pos_list& rar_cce_list; + const srsran::optional_vector& common_cce_list; // List of PDCCH grants struct alloc_record { diff --git a/srsgnb/src/stack/mac/sched_nr_cfg.cc b/srsgnb/src/stack/mac/sched_nr_cfg.cc index 46a90096c..e02ff06b6 100644 --- a/srsgnb/src/stack/mac/sched_nr_cfg.cc +++ b/srsgnb/src/stack/mac/sched_nr_cfg.cc @@ -89,6 +89,24 @@ bwp_params_t::bwp_params_t(const cell_cfg_t& cell, const sched_args_t& sched_cfg rar_cce_list[sl][agg_idx].resize(n); } } + + for (uint32_t ss_id = 0; ss_id < SRSRAN_UE_DL_NR_MAX_NOF_SEARCH_SPACE; ++ss_id) { + if (cell_cfg.bwps[0].pdcch.search_space_present[ss_id]) { + auto& ss = cell_cfg.bwps[0].pdcch.search_space[ss_id]; + auto& coreset = cell_cfg.bwps[0].pdcch.coreset[ss.coreset_id]; + common_cce_list.emplace(ss_id); + bwp_cce_pos_list& ss_cce_list = common_cce_list[ss_id]; + for (uint32_t sl = 0; sl < SRSRAN_NOF_SF_X_FRAME; ++sl) { + for (uint32_t agg_idx = 0; agg_idx < MAX_NOF_AGGR_LEVELS; ++agg_idx) { + ss_cce_list[sl][agg_idx].resize(SRSRAN_SEARCH_SPACE_MAX_NOF_CANDIDATES_NR); + int n = srsran_pdcch_nr_locations_coreset( + &coreset, &ss, SRSRAN_SIRNTI, agg_idx, sl, ss_cce_list[sl][agg_idx].data()); + srsran_assert(n >= 0, "Failed to configure DCI locations of search space id=%d", ss_id); + ss_cce_list[sl][agg_idx].resize(n); + } + } + } + } } cell_params_t::cell_params_t(uint32_t cc_, const cell_cfg_t& cell, const sched_args_t& sched_cfg_) : diff --git a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index 82a06e17e..e53cab838 100644 --- a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -80,7 +80,7 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, ui const uint32_t coreset_id = 0; const uint32_t ss_id = 0; if (not bwp_pdcch_slot.coresets[coreset_id]->alloc_dci(pdcch_grant_type_t::sib, aggr_idx, ss_id)) { - logger.warning("SCHED: Cannot allocate SIB1."); + logger.warning("SCHED: Cannot allocate SIB1 due to lack of PDCCH space."); return alloc_result::no_cch_space; } @@ -101,7 +101,12 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, ui slot_cfg.idx = pdcch_slot.to_uint(); int code = srsran_ra_dl_dci_to_grant_nr( &cfg.cell_cfg.carrier, &slot_cfg, &cfg.cfg.pdsch, &pdcch.dci, &pdsch.sch, &pdsch.sch.grant); - srsran_assert(code == SRSRAN_SUCCESS, "Error converting DCI to grant"); + if (code != SRSRAN_SUCCESS) { + logger.warning("Error generating SIB PDSCH grant."); + bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); + bwp_pdcch_slot.dl.phy.pdsch.pop_back(); + return alloc_result::other_cause; + } // Store SI msg index bwp_pdcch_slot.sib_idxs.push_back(si_idx); diff --git a/srsgnb/src/stack/mac/sched_nr_pdcch.cc b/srsgnb/src/stack/mac/sched_nr_pdcch.cc index bed4c0c6a..3fd35746c 100644 --- a/srsgnb/src/stack/mac/sched_nr_pdcch.cc +++ b/srsgnb/src/stack/mac/sched_nr_pdcch.cc @@ -25,7 +25,8 @@ coreset_region::coreset_region(const bwp_params_t& bwp_cfg_, slot_idx(slot_idx_), pdcch_dl_list(dl_list_), pdcch_ul_list(ul_list_), - rar_cce_list(bwp_cfg_.rar_cce_list) + rar_cce_list(bwp_cfg_.rar_cce_list), + common_cce_list(bwp_cfg_.common_cce_list) { const bool* res_active = &coreset_cfg->freq_resources[0]; nof_freq_res = std::count(res_active, res_active + SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE, true); @@ -182,6 +183,8 @@ srsran::span coreset_region::get_cce_loc_table(const alloc_recor return record.ue->cce_pos_list(record.ss_id, slot_idx, record.aggr_idx); case pdcch_grant_type_t::rar: return rar_cce_list[slot_idx][record.aggr_idx]; + case pdcch_grant_type_t::sib: + return common_cce_list[record.ss_id][slot_idx][record.aggr_idx]; default: break; } diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index 2cc45a8bc..1c12081a6 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -130,7 +130,7 @@ si_sched::si_sched(const bwp_params_t& bwp_cfg_) : pending_sis[0].n = 0; pending_sis[0].len = 77; pending_sis[0].period = 160; - pending_sis[0].win_len = 1; + pending_sis[0].win_len = 160; } void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) @@ -166,7 +166,7 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) } else if (si.win_start + si.win_len >= sl_pdcch) { // If end of SI message window if (si.n == 0) { - logger.error("SCHED: Could not allocate SIB1, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); + logger.error("SCHED: Could not allocate SIB1, len=%d. Cause: %s", si.len, to_string(si.result)); } else { logger.warning( "SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 2310ba8c2..c94a89d02 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -45,6 +45,31 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, rrc_eutra = rrc_eutra_; cfg = cfg_; + if (cfg.is_standalone) { + // Generate parameters of Coreset#0 and SS#0 + // Taken from TS 38.211, Section 7.3.2.2 + cfg.cell_list[0].phy_cell.pdcch.coreset_present[0] = true; + cfg.cell_list[0].phy_cell.pdcch.coreset[0].id = 0; + cfg.cell_list[0].phy_cell.pdcch.coreset[0].mapping_type = srsran_coreset_mapping_type_interleaved; + cfg.cell_list[0].phy_cell.pdcch.coreset[0].reg_bundle_size = srsran_coreset_bundle_size_n6; + cfg.cell_list[0].phy_cell.pdcch.coreset[0].interleaver_size = srsran_coreset_bundle_size_n2; + cfg.cell_list[0].phy_cell.pdcch.coreset[0].shift_index = cfg.cell_list[0].phy_cell.cell_id; + cfg.cell_list[0].phy_cell.pdcch.coreset[0].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; + for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { + cfg.cell_list[0].phy_cell.pdcch.coreset[0].freq_resources[i] = true; + } + cfg.cell_list[0].phy_cell.pdcch.coreset[0].duration = 1; + cfg.cell_list[0].phy_cell.pdcch.search_space_present[0] = true; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].id = 0; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].coreset_id = 0; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].type = srsran_search_space_type_common_0; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_candidates[0] = 1; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_candidates[1] = 1; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_candidates[2] = 1; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].formats[0] = srsran_dci_format_nr_1_0; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].nof_formats = 1; + cfg.cell_list[0].phy_cell.pdcch.search_space[0].duration = 1; + } cell_ctxt.reset(new cell_ctxt_t{}); @@ -60,10 +85,15 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, int ret = fill_sp_cell_cfg_from_enb_cfg(cfg, UE_PSCELL_CC_IDX, base_sp_cell_cfg); srsran_assert(ret == SRSRAN_SUCCESS, "Failed to configure cell"); - // Fill rrc_nr_cfg with UE-specific search spaces and coresets - bool ret2 = srsran::fill_phy_pdcch_cfg_common( - base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(), - &cfg.cell_list[0].phy_cell.pdcch); + pdcch_cfg_common_s* asn1_pdcch; + if (not cfg.is_standalone) { + // Fill rrc_nr_cfg with UE-specific search spaces and coresets + asn1_pdcch = + &base_sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); + } else { + asn1_pdcch = &cell_ctxt->sib1.serving_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); + } + bool ret2 = srsran::fill_phy_pdcch_cfg_common(*asn1_pdcch, &cfg.cell_list[0].phy_cell.pdcch); srsran_assert(ret2, "Invalid NR cell configuration."); ret2 = srsran::fill_phy_pdcch_cfg(base_sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.pdcch_cfg.setup(), &cfg.cell_list[0].phy_cell.pdcch); @@ -297,6 +327,10 @@ int32_t rrc_nr::generate_sibs() cell_ctxt->mib_buffer = std::move(mib_buf); } + if (not cfg.is_standalone) { + return SRSRAN_SUCCESS; + } + // SIB1 packing fill_sib1_from_enb_cfg(cfg, cell_ctxt->sib1); si_sched_info_s::sched_info_list_l_& sched_info = cell_ctxt->sib1.si_sched_info.sched_info_list; From a137835d0740a9428950639ca8127979d0bb7921 Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 5 Nov 2021 15:16:37 +0000 Subject: [PATCH 24/35] gnb,rrc: use phy helper to generate coreset#0 --- srsgnb/src/stack/rrc/rrc_nr.cc | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index c94a89d02..0d0cda0a9 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -47,18 +47,23 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, cfg = cfg_; if (cfg.is_standalone) { // Generate parameters of Coreset#0 and SS#0 - // Taken from TS 38.211, Section 7.3.2.2 - cfg.cell_list[0].phy_cell.pdcch.coreset_present[0] = true; - cfg.cell_list[0].phy_cell.pdcch.coreset[0].id = 0; - cfg.cell_list[0].phy_cell.pdcch.coreset[0].mapping_type = srsran_coreset_mapping_type_interleaved; - cfg.cell_list[0].phy_cell.pdcch.coreset[0].reg_bundle_size = srsran_coreset_bundle_size_n6; - cfg.cell_list[0].phy_cell.pdcch.coreset[0].interleaver_size = srsran_coreset_bundle_size_n2; - cfg.cell_list[0].phy_cell.pdcch.coreset[0].shift_index = cfg.cell_list[0].phy_cell.cell_id; - cfg.cell_list[0].phy_cell.pdcch.coreset[0].precoder_granularity = srsran_coreset_precoder_granularity_reg_bundle; - for (uint32_t i = 0; i < SRSRAN_CORESET_FREQ_DOMAIN_RES_SIZE; i++) { - cfg.cell_list[0].phy_cell.pdcch.coreset[0].freq_resources[i] = true; - } - cfg.cell_list[0].phy_cell.pdcch.coreset[0].duration = 1; + const uint32_t coreset0_idx = 7; + cfg.cell_list[0].phy_cell.pdcch.coreset_present[0] = true; + // Get pointA and SSB absolute frequencies + double pointA_abs_freq_Hz = cfg.cell_list[0].phy_cell.carrier.dl_center_frequency_hz - + cfg.cell_list[0].phy_cell.carrier.nof_prb * SRSRAN_NRE * + SRSRAN_SUBC_SPACING_NR(cfg.cell_list[0].phy_cell.carrier.scs) / 2; + double ssb_abs_freq_Hz = cfg.cell_list[0].phy_cell.carrier.ssb_center_freq_hz; + // Calculate integer SSB to pointA frequency offset in Hz + uint32_t ssb_pointA_freq_offset_Hz = + (ssb_abs_freq_Hz > pointA_abs_freq_Hz) ? (uint32_t)(ssb_abs_freq_Hz - pointA_abs_freq_Hz) : 0; + int ret = srsran_coreset_zero(cfg.cell_list[0].phy_cell.cell_id, + ssb_pointA_freq_offset_Hz, + cfg.cell_list[0].ssb_cfg.scs, + cfg.cell_list[0].phy_cell.carrier.scs, + coreset0_idx, + &cfg.cell_list[0].phy_cell.pdcch.coreset[0]); + srsran_assert(ret == SRSRAN_SUCCESS, "Failed to generate CORESET#0"); cfg.cell_list[0].phy_cell.pdcch.search_space_present[0] = true; cfg.cell_list[0].phy_cell.pdcch.search_space[0].id = 0; cfg.cell_list[0].phy_cell.pdcch.search_space[0].coreset_id = 0; From a34a1f3f6b65e8dbe16c95d69259aeea930d879b Mon Sep 17 00:00:00 2001 From: Francisco Date: Fri, 5 Nov 2021 15:33:31 +0000 Subject: [PATCH 25/35] fix failing compilation due to rebase --- srsgnb/hdr/stack/mac/sched_nr_signalling.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srsgnb/hdr/stack/mac/sched_nr_signalling.h b/srsgnb/hdr/stack/mac/sched_nr_signalling.h index 46745dd72..adeb0fb46 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_signalling.h +++ b/srsgnb/hdr/stack/mac/sched_nr_signalling.h @@ -13,9 +13,9 @@ #ifndef SRSRAN_SCHED_NR_SIGNALLING_H #define SRSRAN_SCHED_NR_SIGNALLING_H -#include "../sched_common.h" #include "sched_nr_cfg.h" #include "sched_nr_interface.h" +#include "srsenb/hdr/stack/mac/sched_common.h" namespace srsenb { namespace sched_nr_impl { From 360f718a5e88daf2b0cf4becb888c5438d3193d9 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Sat, 6 Nov 2021 18:32:41 +0100 Subject: [PATCH 26/35] Add PHY resource allocation calculation for SIB common 0 search space --- lib/src/phy/phch/ra_dl_nr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index c656889e1..53ce78ddb 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -140,7 +140,8 @@ int srsran_ra_dl_nr_time(const srsran_sch_hl_cfg_nr_t* cfg, // Determine which PDSCH Time domain RA configuration to apply (TS 38.214 Table 5.1.2.1.1-1) if (rnti_type == srsran_rnti_type_si && ss_type == srsran_search_space_type_common_0) { // Row 1 - ERROR("Row not implemented"); + // Note: Only Default A is supported, which corresponds SS/PBCH block and coreset mux pattern 1 + srsran_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant); } else if (rnti_type == srsran_rnti_type_si && ss_type == srsran_search_space_type_common_0A) { // Row 2 ERROR("Row not implemented"); From 1807ba1e374403bf840ecbe81e47d05e06ef2f4b Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 8 Nov 2021 10:48:17 +0000 Subject: [PATCH 27/35] nr,gnb,sched: fix si softbuffer allocation. Add extra comments --- .../hdr/stack/mac/sched_nr_grant_allocator.h | 8 ++++--- srsgnb/hdr/stack/mac/sched_nr_helpers.h | 6 ++++- srsgnb/hdr/stack/mac/sched_nr_signalling.h | 19 +++++++++------ .../src/stack/mac/sched_nr_grant_allocator.cc | 11 ++++++--- srsgnb/src/stack/mac/sched_nr_signalling.cc | 23 +++++++++++-------- 5 files changed, 44 insertions(+), 23 deletions(-) diff --git a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h index b295a0987..4aa1f93e2 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h +++ b/srsgnb/hdr/stack/mac/sched_nr_grant_allocator.h @@ -54,8 +54,6 @@ struct bwp_slot_grid { slot_coreset_list coresets; harq_ack_list_t pending_acks; - srsran::bounded_vector sib_idxs; - srsran::unique_pool_ptr rar_softbuffer; bwp_slot_grid() = default; @@ -92,7 +90,11 @@ class bwp_slot_allocator public: explicit bwp_slot_allocator(bwp_res_grid& bwp_grid_, slot_point pdcch_slot_, slot_ue_map_t& ues_); - alloc_result alloc_si(uint32_t aggr_idx, uint32_t si_idx, uint32_t si_ntx, const prb_interval& prbs); + alloc_result alloc_si(uint32_t aggr_idx, + uint32_t si_idx, + uint32_t si_ntx, + const prb_interval& prbs, + tx_harq_softbuffer& softbuffer); alloc_result alloc_rar_and_msg3(uint16_t ra_rnti, uint32_t aggr_idx, prb_interval interv, diff --git a/srsgnb/hdr/stack/mac/sched_nr_helpers.h b/srsgnb/hdr/stack/mac/sched_nr_helpers.h index ed47bf3b2..c6aaa9d0d 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_helpers.h +++ b/srsgnb/hdr/stack/mac/sched_nr_helpers.h @@ -25,7 +25,11 @@ struct bwp_res_grid; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool fill_dci_sib(prb_interval interv, uint32_t sib_idx, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci); +bool fill_dci_sib(prb_interval interv, + uint32_t sib_idx, + uint32_t si_ntx, + const bwp_params_t& bwp_cfg, + srsran_dci_dl_nr_t& dci); bool fill_dci_rar(prb_interval interv, uint16_t ra_rnti, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci); diff --git a/srsgnb/hdr/stack/mac/sched_nr_signalling.h b/srsgnb/hdr/stack/mac/sched_nr_signalling.h index adeb0fb46..68fef4640 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_signalling.h +++ b/srsgnb/hdr/stack/mac/sched_nr_signalling.h @@ -13,6 +13,7 @@ #ifndef SRSRAN_SCHED_NR_SIGNALLING_H #define SRSRAN_SCHED_NR_SIGNALLING_H +#include "harq_softbuffer.h" #include "sched_nr_cfg.h" #include "sched_nr_interface.h" #include "srsenb/hdr/stack/mac/sched_common.h" @@ -63,13 +64,17 @@ private: srslog::basic_logger& logger; struct si_msg_ctxt_t { - uint32_t n = 0; /// 0 for SIB1, n/index in schedulingInfoList in si-SchedulingInfo in SIB1 - uint32_t len = 0; - uint32_t win_len = 0; - uint32_t period = 0; - uint32_t n_tx = 0; - alloc_result result = alloc_result::invalid_coderate; /// last attempt to schedule SI - slot_point win_start; /// start of SI window, invalid if outside + // args + uint32_t n = 0; /// 0 for SIB1, n/index in schedulingInfoList in si-SchedulingInfo in SIB1 + uint32_t len = 0; /// length in bytes of SIB1 / SI message + uint32_t win_len = 0; /// window length in slots + uint32_t period = 0; /// periodicity of SIB1/SI window + + // state + uint32_t n_tx = 0; /// nof transmissions of the same SIB1 / SI message + alloc_result result = alloc_result::invalid_coderate; /// last attempt to schedule SI + slot_point win_start; /// start of SI window, invalid if outside + srsran::unique_pool_ptr si_softbuffer; }; srsran::bounded_vector pending_sis; /// configured SIB1 and SI messages }; diff --git a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc index e53cab838..91cf89d07 100644 --- a/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc +++ b/srsgnb/src/stack/mac/sched_nr_grant_allocator.cc @@ -66,7 +66,11 @@ bwp_slot_allocator::bwp_slot_allocator(bwp_res_grid& bwp_grid_, slot_point pdcch logger(bwp_grid_.cfg->logger), cfg(*bwp_grid_.cfg), bwp_grid(bwp_grid_), pdcch_slot(pdcch_slot_), slot_ues(ues_) {} -alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, uint32_t si_ntx, const prb_interval& prbs) +alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, + uint32_t si_idx, + uint32_t si_ntx, + const prb_interval& prbs, + tx_harq_softbuffer& softbuffer) { bwp_slot_grid& bwp_pdcch_slot = bwp_grid[pdcch_slot]; alloc_result ret = verify_pdsch_space(bwp_pdcch_slot, bwp_pdcch_slot); @@ -88,7 +92,7 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, ui bwp_pdcch_slot.dl_prbs |= prbs; // Generate DCI for RAR with given RA-RNTI pdcch_dl_t& pdcch = bwp_pdcch_slot.dl.phy.pdcch_dl.back(); - if (not fill_dci_sib(prbs, si_idx, *bwp_grid.cfg, pdcch.dci)) { + if (not fill_dci_sib(prbs, si_idx, si_ntx, *bwp_grid.cfg, pdcch.dci)) { // Cancel on-going PDCCH allocation bwp_pdcch_slot.coresets[coreset_id]->rem_last_dci(); return alloc_result::invalid_coderate; @@ -107,9 +111,10 @@ alloc_result bwp_slot_allocator::alloc_si(uint32_t aggr_idx, uint32_t si_idx, ui bwp_pdcch_slot.dl.phy.pdsch.pop_back(); return alloc_result::other_cause; } + pdsch.sch.grant.tb[0].softbuffer.tx = softbuffer.get(); // Store SI msg index - bwp_pdcch_slot.sib_idxs.push_back(si_idx); + bwp_pdcch_slot.dl.sib_idxs.push_back(si_idx); return alloc_result::success; } diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index 1c12081a6..c4d8f68f2 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -103,7 +103,11 @@ void sched_dl_signalling(bwp_slot_allocator& bwp_alloc) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -bool fill_dci_sib(prb_interval interv, uint32_t sib_id, const bwp_params_t& bwp_cfg, srsran_dci_dl_nr_t& dci) +bool fill_dci_sib(prb_interval interv, + uint32_t sib_id, + uint32_t si_ntx, + const bwp_params_t& bwp_cfg, + srsran_dci_dl_nr_t& dci) { dci.mcs = 5; dci.ctx.format = srsran_dci_format_nr_1_0; @@ -117,7 +121,7 @@ bool fill_dci_sib(prb_interval interv, uint32_t sib_id, const bwp_params_t& bwp_ dci.bwp_id = bwp_cfg.bwp_id; dci.cc_id = bwp_cfg.cc; dci.rv = 0; - dci.sii = sib_id == 1 ? 0 : 1; + dci.sii = sib_id == 0 ? 0 : 1; return true; } @@ -127,10 +131,11 @@ si_sched::si_sched(const bwp_params_t& bwp_cfg_) : { // TODO: Get SIB1 other SI msgs config from RRC pending_sis.emplace_back(); - pending_sis[0].n = 0; - pending_sis[0].len = 77; - pending_sis[0].period = 160; - pending_sis[0].win_len = 160; + pending_sis[0].n = 0; + pending_sis[0].len = 77; + pending_sis[0].period = 160; + pending_sis[0].win_len = 160; + pending_sis[0].si_softbuffer = harq_softbuffer_pool::get_instance().get_tx(bwp_cfg->nof_prb()); } void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) @@ -152,10 +157,10 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) if (not si.win_start.valid()) { bool start_window; if (si.n == 0) { - // SIB1 + // SIB1 (slot index zero of even frames) start_window = sl_pdcch.slot_idx() == 0 and sl_pdcch.sfn() % 2 == 0; } else { - // SI messages + // 5.2.2.3.2 - Acquisition of SI message start_window = (sl_pdcch.sfn() % si.period == x / N) and sl_pdcch.slot_idx() == x % bwp_cfg->slots.size(); } if (start_window) { @@ -194,7 +199,7 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) si.result = alloc_result::no_sch_space; break; } - si.result = bwp_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant); + si.result = bwp_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant, *si.si_softbuffer.get()); if (si.result == alloc_result::success) { // SIB scheduled successfully si.win_start.clear(); From 5766ddfa3862f6d05a1561bb24501543fc820401 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 8 Nov 2021 11:26:16 +0000 Subject: [PATCH 28/35] nr,gnb,sched: fix nr_phy_tests. The default sched cell config was not being correctly generated --- .../stack/mac/test/sched_nr_cfg_generators.h | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h index 37d425705..fdbd02589 100644 --- a/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h +++ b/srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h @@ -45,24 +45,6 @@ inline sched_nr_interface::cell_cfg_t get_default_cell_cfg( cell_cfg.bwps[0].pusch = phy_cfg.pusch; cell_cfg.bwps[0].rb_width = phy_cfg.carrier.nof_prb; - cell_cfg.bwps[0].pdcch.coreset_present[0] = true; - cell_cfg.bwps[0].pdcch.coreset[0] = get_default_coreset0(phy_cfg.carrier.nof_prb); - cell_cfg.bwps[0].pdcch.search_space_present[0] = true; - auto& ss = cell_cfg.bwps[0].pdcch.search_space[0]; - ss.id = 0; - ss.coreset_id = 0; - ss.duration = 1; - ss.type = srsran_search_space_type_common_0; - ss.nof_candidates[0] = 1; - ss.nof_candidates[1] = 1; - ss.nof_candidates[2] = 1; - ss.nof_candidates[3] = 0; - ss.nof_candidates[4] = 0; - ss.nof_formats = 1; - ss.formats[0] = srsran_dci_format_nr_1_0; - cell_cfg.bwps[0].pdcch.ra_search_space_present = true; - cell_cfg.bwps[0].pdcch.ra_search_space = cell_cfg.bwps[0].pdcch.search_space[1]; - return cell_cfg; } From ae4071a3df717a1ed2820602ceb349e8cd88cdbf Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 8 Nov 2021 13:38:18 +0000 Subject: [PATCH 29/35] nr,gnb,rrc: propagate RRC SIB configurations to mac and scheduler --- srsgnb/hdr/stack/mac/sched_nr_interface.h | 1 + srsgnb/hdr/stack/mac/sched_nr_signalling.h | 8 +++--- srsgnb/src/stack/mac/mac_nr.cc | 31 ++++++++++----------- srsgnb/src/stack/mac/sched_nr_signalling.cc | 31 +++++++++++---------- srsgnb/src/stack/rrc/rrc_nr.cc | 8 ++++-- 5 files changed, 41 insertions(+), 38 deletions(-) diff --git a/srsgnb/hdr/stack/mac/sched_nr_interface.h b/srsgnb/hdr/stack/mac/sched_nr_interface.h index 8ff4ca3fa..fc4a10766 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_interface.h +++ b/srsgnb/hdr/stack/mac/sched_nr_interface.h @@ -67,6 +67,7 @@ public: struct cell_cfg_sib_t { uint32_t len; uint32_t period_rf; + uint32_t si_window_slots; }; struct cell_cfg_t { diff --git a/srsgnb/hdr/stack/mac/sched_nr_signalling.h b/srsgnb/hdr/stack/mac/sched_nr_signalling.h index 68fef4640..2ddf60eb1 100644 --- a/srsgnb/hdr/stack/mac/sched_nr_signalling.h +++ b/srsgnb/hdr/stack/mac/sched_nr_signalling.h @@ -65,10 +65,10 @@ private: struct si_msg_ctxt_t { // args - uint32_t n = 0; /// 0 for SIB1, n/index in schedulingInfoList in si-SchedulingInfo in SIB1 - uint32_t len = 0; /// length in bytes of SIB1 / SI message - uint32_t win_len = 0; /// window length in slots - uint32_t period = 0; /// periodicity of SIB1/SI window + uint32_t n = 0; /// 0 for SIB1, n/index in schedulingInfoList in si-SchedulingInfo in SIB1 + uint32_t len_bytes = 0; /// length in bytes of SIB1 / SI message + uint32_t win_len_slots = 0; /// window length in slots + uint32_t period_frames = 0; /// periodicity of SIB1/SI window in frames // state uint32_t n_tx = 0; /// nof transmissions of the same SIB1 / SI message diff --git a/srsgnb/src/stack/mac/mac_nr.cc b/srsgnb/src/stack/mac/mac_nr.cc index 220e16942..fe59ff938 100644 --- a/srsgnb/src/stack/mac/mac_nr.cc +++ b/srsgnb/src/stack/mac/mac_nr.cc @@ -255,24 +255,21 @@ int mac_nr::cell_cfg(const std::vector& detected_rachs.resize(nr_cells.size()); // read SIBs from RRC (SIB1 for now only) - for (int i = 0; i < 1 /* srsenb::sched_interface::MAX_SIBS */; i++) { - // TODO: add flag for SIBs into cell config - if (true) { - sib_info_t sib = {}; - sib.index = i; - sib.periodicity = 160; // TODO: read period_rf from config - sib.payload = srsran::make_byte_buffer(); - if (sib.payload == nullptr) { - logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); - return SRSRAN_ERROR; - } - if (rrc->read_pdu_bcch_dlsch(sib.index, *sib.payload) != SRSRAN_SUCCESS) { - logger.error("Couldn't read SIB %d from RRC", sib.index); - } - - logger.info("Including SIB %d into SI scheduling", sib.index + 1); - bcch_dlsch_payload.push_back(std::move(sib)); + for (uint32_t i = 0; i < nr_cells[0].sibs.size(); i++) { + sib_info_t sib = {}; + sib.index = i; + sib.periodicity = 160; // TODO: read period_rf from config + sib.payload = srsran::make_byte_buffer(); + if (sib.payload == nullptr) { + logger.error("Couldn't allocate PDU in %s().", __FUNCTION__); + return SRSRAN_ERROR; + } + if (rrc->read_pdu_bcch_dlsch(sib.index, *sib.payload) != SRSRAN_SUCCESS) { + logger.error("Couldn't read SIB %d from RRC", sib.index); } + + logger.info("Including SIB %d into SI scheduling", sib.index + 1); + bcch_dlsch_payload.push_back(std::move(sib)); } rx.reset(new mac_nr_rx{rlc, rrc, stack_task_queue, sched.get(), logger}); diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index c4d8f68f2..5ca008215 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -129,13 +129,15 @@ bool fill_dci_sib(prb_interval interv, si_sched::si_sched(const bwp_params_t& bwp_cfg_) : bwp_cfg(&bwp_cfg_), logger(srslog::fetch_basic_logger(bwp_cfg_.sched_cfg.logger_name)) { - // TODO: Get SIB1 other SI msgs config from RRC - pending_sis.emplace_back(); - pending_sis[0].n = 0; - pending_sis[0].len = 77; - pending_sis[0].period = 160; - pending_sis[0].win_len = 160; - pending_sis[0].si_softbuffer = harq_softbuffer_pool::get_instance().get_tx(bwp_cfg->nof_prb()); + for (uint32_t i = 0; i < bwp_cfg->cell_cfg.sibs.size(); ++i) { + pending_sis.emplace_back(); + si_msg_ctxt_t& si = pending_sis.back(); + si.n = i; + si.len_bytes = bwp_cfg->cell_cfg.sibs[i].len; + si.period_frames = bwp_cfg->cell_cfg.sibs[i].period_rf; + si.win_len_slots = bwp_cfg->cell_cfg.sibs[i].si_window_slots; + si.si_softbuffer = harq_softbuffer_pool::get_instance().get_tx(bwp_cfg->nof_prb()); + } } void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) @@ -152,7 +154,7 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) // Update SI windows uint32_t N = bwp_cfg->slots.size(); for (si_msg_ctxt_t& si : pending_sis) { - uint32_t x = (si.n - 1) * si.win_len; + uint32_t x = (si.n - 1) * si.win_len_slots; if (not si.win_start.valid()) { bool start_window; @@ -161,20 +163,21 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) start_window = sl_pdcch.slot_idx() == 0 and sl_pdcch.sfn() % 2 == 0; } else { // 5.2.2.3.2 - Acquisition of SI message - start_window = (sl_pdcch.sfn() % si.period == x / N) and sl_pdcch.slot_idx() == x % bwp_cfg->slots.size(); + start_window = + (sl_pdcch.sfn() % si.period_frames == x / N) and sl_pdcch.slot_idx() == x % bwp_cfg->slots.size(); } if (start_window) { // If start of SI message window si.win_start = sl_pdcch; si.n_tx = 0; } - } else if (si.win_start + si.win_len >= sl_pdcch) { + } else if (si.win_start + si.win_len_slots >= sl_pdcch) { // If end of SI message window if (si.n == 0) { - logger.error("SCHED: Could not allocate SIB1, len=%d. Cause: %s", si.len, to_string(si.result)); + logger.error("SCHED: Could not allocate SIB1, len=%d. Cause: %s", si.len_bytes, to_string(si.result)); } else { logger.warning( - "SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len, to_string(si.result)); + "SCHED: Could not allocate SI message idx=%d, len=%d. Cause: %s", si.n, si.len_bytes, to_string(si.result)); } si.win_start.clear(); } @@ -205,9 +208,9 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) si.win_start.clear(); si.n_tx++; if (si.n == 0) { - logger.debug("SCHED: Allocated SIB1, len=%d.", si.n, si.len); + logger.debug("SCHED: Allocated SIB1, len=%d.", si.n, si.len_bytes); } else { - logger.debug("SCHED: Allocated SI message idx=%d, len=%d.", si.n, si.len); + logger.debug("SCHED: Allocated SI message idx=%d, len=%d.", si.n, si.len_bytes); } } } diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 0d0cda0a9..6f3758f29 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -300,9 +300,11 @@ void rrc_nr::config_mac() for (uint32_t i = 0; i < cell_ctxt->sib_buffer.size(); i++) { cell.sibs[i].len = cell_ctxt->sib_buffer[i]->N_bytes; if (i == 0) { - cell.sibs[i].period_rf = 16; // SIB1 is always 16 rf + cell.sibs[i].period_rf = 16; // SIB1 is always 16 rf + cell.sibs[i].si_window_slots = 160; } else { - cell.sibs[i].period_rf = cell_ctxt->sib1.si_sched_info.sched_info_list[i - 1].si_periodicity.to_number(); + cell.sibs[i].period_rf = cell_ctxt->sib1.si_sched_info.sched_info_list[i - 1].si_periodicity.to_number(); + cell.sibs[i].si_window_slots = cell_ctxt->sib1.si_sched_info.si_win_len.to_number(); } } @@ -406,7 +408,7 @@ int rrc_nr::read_pdu_bcch_bch(const uint32_t tti, srsran::byte_buffer_t& buffer) int rrc_nr::read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) { if (sib_index >= cell_ctxt->sib_buffer.size()) { - logger.error("SIB %d is not a configured SIB.", sib_index); + logger.error("SI%s%d is not a configured SIB.", sib_index == 0 ? "B" : "", sib_index + 1); return SRSRAN_ERROR; } From aba3ac9ddf76250d92c90a0a43413a1f166125b2 Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 8 Nov 2021 15:29:11 +0000 Subject: [PATCH 30/35] nr,gnb,sched: increase SIB grant size in PRBs, to ensure it fits the message --- srsgnb/src/stack/mac/sched_nr_signalling.cc | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index 5ca008215..2019f5a70 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -193,15 +193,10 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) } // Attempt grants with increasing number of PRBs (if the number of PRBs is too low, the coderate is invalid) - si.result = alloc_result::invalid_coderate; - uint32_t prb_start_idx = 0; - for (uint32_t nprbs = 4; nprbs < bwp_cfg->cfg.rb_width and si.result == alloc_result::invalid_coderate; ++nprbs) { - prb_interval grant = find_empty_interval_of_length(prbs, nprbs, prb_start_idx); - prb_start_idx = grant.start(); - if (grant.length() != nprbs) { - si.result = alloc_result::no_sch_space; - break; - } + si.result = alloc_result::invalid_coderate; + uint32_t nprbs = 8; + prb_interval grant = find_empty_interval_of_length(prbs, nprbs, 0); + if (grant.length() >= nprbs) { si.result = bwp_alloc.alloc_si(si_aggr_level, si.n, si.n_tx, grant, *si.si_softbuffer.get()); if (si.result == alloc_result::success) { // SIB scheduled successfully @@ -214,6 +209,9 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) } } } + if (si.result != alloc_result::success) { + logger.warning("SCHED: Failed to allocate SI%s%d ntx=%d", si.n == 0 ? "B" : " message idx=", si.n + 1, si.n_tx); + } } } From 89ca761680b4967bb2454248c152e01a277a0bdb Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 9 Nov 2021 11:47:01 +0000 Subject: [PATCH 31/35] nr,gnb,sched: small fixes in sched sib allocation logging --- srsgnb/src/stack/mac/sched_nr_helpers.cc | 7 +++++-- srsgnb/src/stack/mac/sched_nr_signalling.cc | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/srsgnb/src/stack/mac/sched_nr_helpers.cc b/srsgnb/src/stack/mac/sched_nr_helpers.cc index 184953753..5e2071dcc 100644 --- a/srsgnb/src/stack/mac/sched_nr_helpers.cc +++ b/srsgnb/src/stack/mac/sched_nr_helpers.cc @@ -183,7 +183,6 @@ void log_sched_bwp_result(srslog::basic_logger& logger, "SCHED: SI{}, cc={}, prbs={}, pdsch_slot={}", pdcch.dci.sii == 0 ? "B" : " message", res_grid.cfg->cc, - pdcch.dci.ctx.rnti, srsran::interval{start_idx, end_idx}, pdcch_slot); si_count++; @@ -191,7 +190,11 @@ void log_sched_bwp_result(srslog::basic_logger& logger, } if (fmtbuf.size() > 0) { - logger.info("%s", srsran::to_c_str(fmtbuf)); + if (pdcch.dci.ctx.rnti_type == srsran_rnti_type_si) { + logger.debug("%s", srsran::to_c_str(fmtbuf)); + } else { + logger.info("%s", srsran::to_c_str(fmtbuf)); + } } } for (const pdcch_ul_t& pdcch : bwp_slot.dl.phy.pdcch_ul) { diff --git a/srsgnb/src/stack/mac/sched_nr_signalling.cc b/srsgnb/src/stack/mac/sched_nr_signalling.cc index 2019f5a70..020d0aff1 100644 --- a/srsgnb/src/stack/mac/sched_nr_signalling.cc +++ b/srsgnb/src/stack/mac/sched_nr_signalling.cc @@ -203,7 +203,7 @@ void si_sched::run_slot(bwp_slot_allocator& bwp_alloc) si.win_start.clear(); si.n_tx++; if (si.n == 0) { - logger.debug("SCHED: Allocated SIB1, len=%d.", si.n, si.len_bytes); + logger.debug("SCHED: Allocated SIB1, len=%d.", si.len_bytes); } else { logger.debug("SCHED: Allocated SI message idx=%d, len=%d.", si.n, si.len_bytes); } From fd7c5e375c0fb2905615f8e3476c7416ddfafc62 Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 9 Nov 2021 18:26:37 +0000 Subject: [PATCH 32/35] nr,gnb,rrc: implement NR RRCSetup in RRC and wrote unit test --- .../hdr/stack/common/test/dummy_nr_classes.h | 23 ++ srsgnb/hdr/stack/rrc/rrc_nr.h | 58 ++-- srsgnb/src/stack/rrc/cell_asn1_config.cc | 9 +- srsgnb/src/stack/rrc/rrc_nr.cc | 252 ++++++++++++------ srsgnb/src/stack/rrc/test/CMakeLists.txt | 4 +- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 40 ++- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 65 +++++ .../src/stack/rrc/test/rrc_nr_test_helpers.h | 60 +++++ test/phy/dummy_gnb_stack.h | 2 +- 9 files changed, 391 insertions(+), 122 deletions(-) rename srsenb/test/common/dummy_classes_nr.h => srsgnb/hdr/stack/common/test/dummy_nr_classes.h (65%) create mode 100644 srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc create mode 100644 srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h diff --git a/srsenb/test/common/dummy_classes_nr.h b/srsgnb/hdr/stack/common/test/dummy_nr_classes.h similarity index 65% rename from srsenb/test/common/dummy_classes_nr.h rename to srsgnb/hdr/stack/common/test/dummy_nr_classes.h index 76ba164c6..90e4f9906 100644 --- a/srsenb/test/common/dummy_classes_nr.h +++ b/srsgnb/hdr/stack/common/test/dummy_nr_classes.h @@ -15,9 +15,32 @@ #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_mac_interfaces.h" +#include "srsran/interfaces/gnb_ngap_interfaces.h" namespace srsenb { +class ngap_dummy : public ngap_interface_rrc_nr +{ + void initial_ue(uint16_t rnti, + uint32_t gnb_cc_idx, + asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu) + {} + void initial_ue(uint16_t rnti, + uint32_t gnb_cc_idx, + asn1::ngap_nr::rrcestablishment_cause_e cause, + srsran::unique_byte_buffer_t pdu, + uint32_t m_tmsi) + {} + + void write_pdu(uint16_t rnti, srsran::unique_byte_buffer_t pdu) {} + bool user_exists(uint16_t rnti) { return true; } + void user_mod(uint16_t old_rnti, uint16_t new_rnti) {} + bool user_release(uint16_t rnti, asn1::ngap_nr::cause_radio_network_e cause_radio) { return true; } + bool is_amf_connected() { return true; } + void ue_notify_rrc_reconf_complete(uint16_t rnti, bool outcome) {} +}; + class rrc_nr_dummy : public rrc_interface_mac_nr { public: diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index 267764daa..9c9efe00d 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -103,18 +103,11 @@ public: // logging typedef enum { Rx = 0, Tx } direction_t; template - void log_rrc_message(const std::string& source, - const direction_t dir, - const asn1::dyn_octstring& oct, - const T& msg, - const std::string& msg_type); - - template - void log_rrc_message(const std::string& source, - const direction_t dir, - const srsran::byte_buffer_t& pdu, - const T& msg, - const std::string& msg_type); + void log_rrc_message(const char* source, + const direction_t dir, + srsran::const_byte_span pdu, + const T& msg, + const char* msg_type); class ue { public: @@ -128,12 +121,17 @@ public: /// @param [in] start_msg3_timer: indicates whether the UE is created as part of a RACH process ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer = true); - void send_connection_setup(); - void send_dl_ccch(asn1::rrc_nr::dl_ccch_msg_s* dl_dcch_msg); + void send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_dcch_msg); + + /* TS 38.331 - 5.3.3 RRC connection establishment */ + void send_rrc_setup(); + void send_rrc_reject(uint8_t reject_wait_time_secs); int handle_sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params); void crnti_ce_received(); + void handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg); + // getters bool is_connected() { return state == rrc_nr_state_t::RRC_CONNECTED; } bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; } @@ -156,8 +154,6 @@ public: private: rrc_nr* parent = nullptr; uint16_t rnti = SRSRAN_INVALID_RNTI; - /// for basic DL/UL activity timeout - srsran::unique_timer activity_timer; int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig); int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config); @@ -201,12 +197,19 @@ public: int add_drb(); // logging helpers - template - void log_rrc_message(const direction_t dir, const M& pdu, const T& msg, const std::string& msg_type); + template + void log_rrc_message(srsran::nr_srb srb, + const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type); + template + void log_rrc_container(const direction_t dir, srsran::const_byte_span pdu, const M& msg, const char* msg_type); // state - rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; - uint8_t transaction_id = 0; + rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; + uint8_t transaction_id = 0; + srsran::unique_timer activity_timer; /// for basic DL/UL activity timeout // RRC configs for UEs asn1::rrc_nr::cell_group_cfg_s cell_group_cfg; @@ -251,18 +254,25 @@ private: srsran::unique_byte_buffer_t mib_buffer = nullptr; std::vector sib_buffer; }; - std::unique_ptr cell_ctxt; - std::map > users; - bool running = false; + std::unique_ptr cell_ctxt; + rnti_map_t > users; + bool running = false; /// Private Methods - void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu); + void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu); + void parse_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu); + void handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_setup_request_s& msg); /// This gets called by rrc_nr::sgnb_addition_request and WILL NOT TRIGGER the RX MSG3 activity timer int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer); // Helper to create PDU from RRC message template srsran::unique_byte_buffer_t pack_into_pdu(const T& msg); + void log_rx_pdu_fail(uint16_t rnti, + uint32_t lcid, + srsran::const_byte_span pdu, + const char* cause_str, + bool log_hex = true); }; } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index c6535f280..379ef7f57 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -299,14 +299,7 @@ int fill_pdcch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pdcch_cfg_ (search_space_cfg.type == srsran_search_space_type_common_3)) { search_spaces[0].search_space_type.set_common(); - if ((search_space_cfg.formats[0] == srsran_dci_format_nr_0_0) and - (search_space_cfg.formats[1] == srsran_dci_format_nr_1_0)) { - search_spaces[ss_mod_list_idx].search_space_type.common().dci_format0_minus0_and_format1_minus0_present = - true; - } else { - get_logger(cfg).error("Config Error: Unsupported dci nr formats."); - return SRSRAN_ERROR; - } + search_spaces[ss_mod_list_idx].search_space_type.common().dci_format0_minus0_and_format1_minus0_present = true; } else { get_logger(cfg).error("Config Error: Unsupported search space type."); return SRSRAN_ERROR; diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 6f3758f29..84258ec08 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -18,6 +18,7 @@ #include "srsran/common/common_nr.h" #include "srsran/common/phy_cfg_nr_default.h" #include "srsran/common/standard_streams.h" +#include "srsran/common/string_helpers.h" using namespace asn1::rrc_nr; @@ -123,48 +124,33 @@ void rrc_nr::stop() } template -void rrc_nr::log_rrc_message(const std::string& source, - const direction_t dir, - const asn1::dyn_octstring& oct, - const T& msg, - const std::string& msg_type) +void rrc_nr::log_rrc_message(const char* source, + const direction_t dir, + srsran::const_byte_span pdu, + const T& msg, + const char* msg_type) { if (logger.debug.enabled()) { asn1::json_writer json_writer; msg.to_json(json_writer); - logger.debug(oct.data(), - oct.size(), - "%s - %s %s (%d B)", - source.c_str(), - dir == Tx ? "Tx" : "Rx", - msg_type.c_str(), - oct.size()); - logger.debug("Content:\n%s", json_writer.to_string().c_str()); + logger.debug(pdu.data(), pdu.size(), "%s - %s %s (%d B)", source, (dir == Rx) ? "Rx" : "Tx", msg_type, pdu.size()); + logger.debug("Content:%s", json_writer.to_string().c_str()); } else if (logger.info.enabled()) { - logger.info("%s - %s %s (%d B)", source.c_str(), dir == Tx ? "Tx" : "Rx", msg_type.c_str(), oct.size()); + logger.info(pdu.data(), pdu.size(), "%s - %s %s (%d B)", source, (dir == Rx) ? "Rx" : "Tx", msg_type, pdu.size()); } } -template -void rrc_nr::log_rrc_message(const std::string& source, - const direction_t dir, - const srsran::byte_buffer_t& pdu, - const T& msg, - const std::string& msg_type) +void rrc_nr::log_rx_pdu_fail(uint16_t rnti, + uint32_t lcid, + srsran::const_byte_span pdu, + const char* cause_str, + bool log_hex) { - if (logger.debug.enabled()) { - asn1::json_writer json_writer; - msg.to_json(json_writer); - logger.debug(pdu.msg, - pdu.N_bytes, - "%s - %s %s (%d B)", - source.c_str(), - (dir == Rx) ? "Rx" : "Tx", - msg_type.c_str(), - pdu.N_bytes); - logger.debug("Content:%s", json_writer.to_string().c_str()); - } else if (logger.info.enabled()) { - logger.info("%s - %s %s (%d B)", source.c_str(), (dir == Rx) ? "Rx" : "Tx", msg_type.c_str(), pdu.N_bytes); + if (log_hex) { + logger.error( + pdu.data(), pdu.size(), "Rx %s PDU, rnti=0x%x - Discarding. Cause: %s", get_rb_name(lcid), rnti, cause_str); + } else { + logger.error("Rx %s PDU, rnti=0x%x - Discarding. Cause: %s", get_rb_name(lcid), rnti, cause_str); } } @@ -174,9 +160,9 @@ void rrc_nr::log_rrc_message(const std::string& source, */ int rrc_nr::add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer) { - if (users.count(rnti) == 0) { + if (users.contains(rnti) == 0) { // If in the ue ctor, "start_msg3_timer" is set to true, this will start the MSG3 RX TIMEOUT at ue creation - users.insert(std::make_pair(rnti, std::unique_ptr(new ue(this, rnti, uecfg, start_msg3_timer)))); + users.insert(rnti, std::unique_ptr(new ue(this, rnti, uecfg, start_msg3_timer))); rlc->add_user(rnti); pdcp->add_user(rnti); logger.info("Added new user rnti=0x%x", rnti); @@ -386,7 +372,7 @@ int32_t rrc_nr::generate_sibs() } else { fmt::format_to(strbuf, "SI message={} payload", msg_index + 1); } - log_rrc_message(fmt::to_string(strbuf), Tx, *cell_ctxt->sib_buffer.back(), msg[msg_index], ""); + log_rrc_message("BCCH", Tx, *cell_ctxt->sib_buffer.back(), msg[msg_index], srsran::to_c_str(strbuf)); } return SRSRAN_SUCCESS; @@ -428,36 +414,78 @@ void rrc_nr::get_metrics(srsenb::rrc_metrics_t& m) } } -void rrc_nr::handle_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) +void rrc_nr::handle_pdu(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu) { - if (pdu) { - logger.info(pdu->msg, pdu->N_bytes, "Rx %s PDU", get_rb_name(lcid)); + logger.info(pdu.data(), pdu.size(), "Rx %s PDU", get_rb_name(lcid)); + + switch (static_cast(lcid)) { + case srsran::nr_srb::srb0: + parse_ul_ccch(rnti, pdu); + break; + case srsran::nr_srb::srb1: + case srsran::nr_srb::srb2: + // parse_ul_dcch(p.rnti, p.lcid, std::move(p.pdu)); + break; + default: + std::string errcause = fmt::format("Invalid LCID=%d", lcid); + log_rx_pdu_fail(rnti, lcid, pdu, errcause.c_str()); + break; } +} - if (users.count(rnti) == 1) { - switch (static_cast(lcid)) { - case srsran::nr_srb::srb0: - // parse_ul_ccch(rnti, std::move(pdu)); - break; - case srsran::nr_srb::srb1: - case srsran::nr_srb::srb2: - // parse_ul_dcch(p.rnti, p.lcid, std::move(p.pdu)); - break; - default: - logger.error("Rx PDU with invalid bearer id: %d", lcid); - break; +void rrc_nr::parse_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu) +{ + // Parse UL-CCCH + ul_ccch_msg_s ul_ccch_msg; + { + asn1::cbit_ref bref(pdu.data(), pdu.size()); + if (ul_ccch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or + ul_ccch_msg.msg.type().value != ul_ccch_msg_type_c::types_opts::c1) { + log_rx_pdu_fail(rnti, srb_to_lcid(lte_srb::srb0), pdu, "Failed to unpack UL-CCCH message", true); + return; } - } else { - logger.warning("Discarding PDU for removed rnti=0x%x", rnti); + } + + // Log Rx message + fmt::memory_buffer fmtbuf, fmtbuf2; + fmt::format_to(fmtbuf, "rnti=0x{:x}, SRB0", rnti); + fmt::format_to(fmtbuf2, "UL-CCCH.{}", ul_ccch_msg.msg.c1().type().to_string()); + log_rrc_message(srsran::to_c_str(fmtbuf), Rx, pdu, ul_ccch_msg, srsran::to_c_str(fmtbuf2)); + + // Handle message + switch (ul_ccch_msg.msg.c1().type().value) { + case ul_ccch_msg_type_c::c1_c_::types_opts::rrc_setup_request: + handle_rrc_setup_request(rnti, ul_ccch_msg.msg.c1().rrc_setup_request()); + break; + default: + log_rx_pdu_fail(rnti, srb_to_lcid(lte_srb::srb0), pdu, "Unsupported UL-CCCH message type"); + // TODO Remove user } } +void rrc_nr::handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_setup_request_s& msg) +{ + auto ue_it = users.find(rnti); + + // TODO: Defer creation of ue to this point + if (ue_it == users.end()) { + logger.error("%s received for inexistent rnti=0x%x", "UL-CCCH", rnti); + return; + } + ue& u = *ue_it->second; + u.handle_rrc_setup_request(msg); +} + /******************************************************************************* PDCP interface *******************************************************************************/ void rrc_nr::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) { - handle_pdu(rnti, lcid, std::move(pdu)); + if (pdu == nullptr or pdu->N_bytes == 0) { + logger.error("Rx %s PDU, rnti=0x%x - Discarding. Cause: PDU is empty", srsenb::get_rb_name(lcid), rnti); + return; + } + handle_pdu(rnti, lcid, *pdu); } void rrc_nr::notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) {} @@ -652,39 +680,18 @@ std::string rrc_nr::ue::to_string(const activity_timeout_type_t& type) return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type); } -void rrc_nr::ue::send_connection_setup() -{ - dl_ccch_msg_s dl_ccch_msg; - dl_ccch_msg.msg.set_c1().set_rrc_setup().rrc_transaction_id = ((transaction_id++) % 4u); - rrc_setup_ies_s& setup = dl_ccch_msg.msg.c1().rrc_setup().crit_exts.set_rrc_setup(); - radio_bearer_cfg_s& rr_cfg = setup.radio_bearer_cfg; - - // Add DRB1 to cfg - rr_cfg.drb_to_add_mod_list_present = true; - rr_cfg.drb_to_add_mod_list.resize(1); - auto& drb_item = rr_cfg.drb_to_add_mod_list[0]; - drb_item.drb_id = 1; - drb_item.pdcp_cfg_present = true; - drb_item.pdcp_cfg.ciphering_disabled_present = true; - // drb_item.cn_assoc_present = true; - // drb_item.cn_assoc.set_eps_bearer_id() = ; - drb_item.recover_pdcp_present = false; - - // TODO: send config to RLC/PDCP - - send_dl_ccch(&dl_ccch_msg); -} - -void rrc_nr::ue::send_dl_ccch(dl_ccch_msg_s* dl_ccch_msg) +void rrc_nr::ue::send_dl_ccch(const dl_ccch_msg_s& dl_ccch_msg) { // Allocate a new PDU buffer, pack the message and send to PDCP - srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(*dl_ccch_msg); + srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(dl_ccch_msg); if (pdu == nullptr) { parent->logger.error("Failed to send DL-CCCH"); return; } - log_rrc_message(Tx, *pdu.get(), *dl_ccch_msg, "DL-CCCH"); - parent->rlc->write_sdu(rnti, (uint32_t)srsran::nr_srb::srb0, std::move(pdu)); + fmt::memory_buffer fmtbuf; + fmt::format_to(fmtbuf, "DL-CCCH.{}", dl_ccch_msg.msg.c1().type().to_string()); + log_rrc_message(srsran::nr_srb::srb0, Tx, *pdu.get(), dl_ccch_msg, srsran::to_c_str(fmtbuf)); + parent->rlc->write_sdu(rnti, srsran::srb_to_lcid(srsran::nr_srb::srb0), std::move(pdu)); } template @@ -1234,7 +1241,7 @@ int rrc_nr::ue::pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_second } packed_secondary_cell_config.resize(bref_pack.distance_bytes()); - log_rrc_message(Tx, packed_secondary_cell_config, cell_group_cfg_pack, "nr-SecondaryCellGroupConfig-r15"); + log_rrc_container(Tx, packed_secondary_cell_config, cell_group_cfg_pack, "nr-SecondaryCellGroupConfig-r15"); return SRSRAN_SUCCESS; } @@ -1291,7 +1298,7 @@ int rrc_nr::ue::pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_beare // resize to packed length packed_nr_bearer_config.resize(bref_pack.distance_bytes()); - log_rrc_message(Tx, packed_nr_bearer_config, radio_bearer_cfg_pack, "nr-RadioBearerConfig1-r15"); + log_rrc_container(Tx, packed_nr_bearer_config, radio_bearer_cfg_pack, "nr-RadioBearerConfig1-r15"); return SRSRAN_SUCCESS; } @@ -1446,6 +1453,62 @@ int rrc_nr::ue::add_drb() return SRSRAN_SUCCESS; } +void rrc_nr::ue::handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg) +{ + if (not parent->ngap->is_amf_connected()) { + parent->logger.error("MME isn't connected. Sending Connection Reject"); + const uint8_t max_wait_time_secs = 16; + send_rrc_reject(max_wait_time_secs); // See TS 38.331, RejectWaitTime + return; + } + + // TODO: Allocate PUCCH resources and reject if not available + + switch (msg.rrc_setup_request.ue_id.type().value) { + case asn1::rrc_nr::init_ue_id_c::types_opts::ng_minus5_g_s_tmsi_part1: + // TODO: communicate with NGAP + break; + case asn1::rrc_nr::init_ue_id_c::types_opts::random_value: + // TODO: communicate with NGAP + break; + default: + parent->logger.error("Unsupported RRCSetupRequest"); + } + + send_rrc_setup(); + set_activity_timeout(UE_INACTIVITY_TIMEOUT); +} + +/// TS 38.331, RRCReject message +void rrc_nr::ue::send_rrc_reject(uint8_t reject_wait_time_secs) +{ + dl_ccch_msg_s msg; + rrc_reject_ies_s& reject = msg.msg.set_c1().set_rrc_reject().crit_exts.set_rrc_reject(); + if (reject_wait_time_secs > 0) { + reject.wait_time_present = true; + reject.wait_time = reject_wait_time_secs; + } + send_dl_ccch(msg); +} + +/// TS 38.331, RRCSetup +void rrc_nr::ue::send_rrc_setup() +{ + dl_ccch_msg_s msg; + rrc_setup_s& setup = msg.msg.set_c1().set_rrc_setup(); + setup.rrc_transaction_id = (uint8_t)((transaction_id++) % 4); + rrc_setup_ies_s& setup_ies = setup.crit_exts.set_rrc_setup(); + + // Fill RRC Setup + // Note: See 5.3.5.6.3 - SRB addition/modification + setup_ies.radio_bearer_cfg.srb_to_add_mod_list_present = true; + setup_ies.radio_bearer_cfg.srb_to_add_mod_list.resize(1); + srb_to_add_mod_s& srb1 = setup_ies.radio_bearer_cfg.srb_to_add_mod_list[0]; + srb1.srb_id = 1; + + send_dl_ccch(msg); +} + /** * @brief Deactivate all Bearers (MAC logical channel) for this specific RNTI * @@ -1462,12 +1525,27 @@ void rrc_nr::ue::deactivate_bearers() parent->mac->ue_cfg(rnti, uecfg); } -template -void rrc_nr::ue::log_rrc_message(const direction_t dir, const M& pdu, const T& msg, const std::string& msg_type) +template +void rrc_nr::ue::log_rrc_message(srsran::nr_srb srb, + const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type) +{ + fmt::memory_buffer strbuf; + fmt::format_to(strbuf, "rnti=0x{:x}, {}", rnti, srsran::get_srb_name(srb)); + parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); +} + +template +void rrc_nr::ue::log_rrc_container(const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type) { fmt::memory_buffer strbuf; - fmt::format_to(strbuf, "rnti=0x{:x}", rnti); - parent->log_rrc_message(fmt::to_string(strbuf), Tx, pdu, msg, msg_type); + fmt::format_to(strbuf, "rnti=0x{:x}, container", rnti); + parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/CMakeLists.txt b/srsgnb/src/stack/rrc/test/CMakeLists.txt index 798e2556d..9716fdaac 100644 --- a/srsgnb/src/stack/rrc/test/CMakeLists.txt +++ b/srsgnb/src/stack/rrc/test/CMakeLists.txt @@ -6,6 +6,8 @@ # the distribution. # +add_library(rrc_nr_test_helpers rrc_nr_test_helpers.cc) + add_executable(rrc_nr_test rrc_nr_test.cc) -target_link_libraries(rrc_nr_test srsgnb_rrc test_helpers ${ATOMIC_LIBS}) +target_link_libraries(rrc_nr_test srsgnb_rrc test_helpers rrc_nr_test_helpers) add_test(rrc_nr_test rrc_nr_test -i ${CMAKE_CURRENT_SOURCE_DIR}/../..) \ No newline at end of file diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index dc56df1f2..3bcca174b 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -10,11 +10,13 @@ * */ +#include "rrc_nr_test_helpers.h" #include "srsenb/hdr/enb.h" #include "srsenb/test/common/dummy_classes_common.h" -#include "srsenb/test/common/dummy_classes_nr.h" #include "srsenb/test/rrc/test_helpers.h" +#include "srsgnb/hdr/stack/common/test/dummy_nr_classes.h" #include "srsgnb/hdr/stack/rrc/rrc_nr.h" +#include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" #include "srsran/common/test_common.h" #include "srsran/interfaces/gnb_rrc_nr_interfaces.h" #include @@ -125,12 +127,47 @@ int test_rrc_setup() return SRSRAN_SUCCESS; } +void test_rrc_sa_connection() +{ + srsran::task_scheduler task_sched; + + phy_nr_dummy phy_obj; + mac_nr_dummy mac_obj; + rlc_nr_rrc_tester rlc_obj; + pdcp_nr_rrc_tester pdcp_obj; + ngap_dummy ngap_obj; + + rrc_nr rrc_obj(&task_sched); + + // set cfg + all_args_t args{}; + phy_cfg_t phy_cfg{}; + rrc_nr_cfg_t rrc_cfg_nr = rrc_nr_cfg_t{}; + rrc_cfg_nr.cell_list.emplace_back(); + rrc_cfg_nr.cell_list[0].phy_cell.carrier.pci = 500; + rrc_cfg_nr.cell_list[0].dl_arfcn = 634240; + rrc_cfg_nr.cell_list[0].band = 78; + rrc_cfg_nr.is_standalone = true; + args.enb.n_prb = 50; + enb_conf_sections::set_derived_args_nr(&args, &rrc_cfg_nr, &phy_cfg); + + TESTASSERT(rrc_obj.init(rrc_cfg_nr, &phy_obj, &mac_obj, &rlc_obj, &pdcp_obj, &ngap_obj, nullptr, nullptr) == + SRSRAN_SUCCESS); + + sched_nr_ue_cfg_t uecfg = get_default_ue_cfg(1); + TESTASSERT_SUCCESS(rrc_obj.add_user(0x4601, uecfg)); + + TESTASSERT_SUCCESS(test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, 0x4601)); +} + } // namespace srsenb int main(int argc, char** argv) { auto& logger = srslog::fetch_basic_logger("ASN1"); logger.set_level(srslog::basic_levels::info); + auto& rrc_logger = srslog::fetch_basic_logger("RRC-NR"); + rrc_logger.set_level(srslog::basic_levels::info); srslog::init(); @@ -142,6 +179,7 @@ int main(int argc, char** argv) TESTASSERT(srsenb::test_sib_generation() == SRSRAN_SUCCESS); TESTASSERT(srsenb::test_rrc_setup() == SRSRAN_SUCCESS); + srsenb::test_rrc_sa_connection(); return SRSRAN_SUCCESS; } diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc new file mode 100644 index 000000000..3fbdb3aa6 --- /dev/null +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -0,0 +1,65 @@ +/** + * + * \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 "rrc_nr_test_helpers.h" +#include "srsran/common/test_common.h" + +using namespace asn1::rrc_nr; + +namespace srsenb { + +int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + rlc_nr_rrc_tester& rlc, + uint16_t rnti) +{ + srsran::unique_byte_buffer_t pdu; + + // Send RRCSetupRequest + ul_ccch_msg_s setup_msg; + rrc_setup_request_ies_s& setup = setup_msg.msg.set_c1().set_rrc_setup_request().rrc_setup_request; + setup.establishment_cause.value = establishment_cause_opts::mo_data; + setup.ue_id.set_random_value().from_number(0); + { + pdu = srsran::make_byte_buffer(); + asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()}; + TESTASSERT_SUCCESS(setup_msg.pack(bref)); + pdu->N_bytes = bref.distance_bytes(); + } + + rrc_obj.write_pdu(rnti, 0, std::move(pdu)); + task_sched.tic(); + + TESTASSERT_EQ(rnti, rlc.last_sdu_rnti); + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb0), rlc.last_sdu_lcid); + TESTASSERT(rlc.last_sdu->size() > 0); + dl_ccch_msg_s dl_ccch_msg; + { + asn1::cbit_ref bref{rlc.last_sdu->data(), rlc.last_sdu->size()}; + TESTASSERT_SUCCESS(dl_ccch_msg.unpack(bref)); + } + TESTASSERT_EQ(dl_ccch_msg_type_c::types_opts::c1, dl_ccch_msg.msg.type().value); + TESTASSERT_EQ(dl_ccch_msg_type_c::c1_c_::types_opts::rrc_setup, dl_ccch_msg.msg.c1().type().value); + TESTASSERT_EQ(asn1::rrc_nr::rrc_setup_s::crit_exts_c_::types_opts::rrc_setup, + dl_ccch_msg.msg.c1().rrc_setup().crit_exts.type().value); + + const rrc_setup_ies_s& setup_ies = dl_ccch_msg.msg.c1().rrc_setup().crit_exts.rrc_setup(); + TESTASSERT(setup_ies.radio_bearer_cfg.srb_to_add_mod_list_present); + TESTASSERT_EQ(1, setup_ies.radio_bearer_cfg.srb_to_add_mod_list.size()); + + const srb_to_add_mod_s& srb1 = setup_ies.radio_bearer_cfg.srb_to_add_mod_list[0]; + TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), srb1.srb_id); + + return SRSRAN_SUCCESS; +} + +} // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h new file mode 100644 index 000000000..92539e11f --- /dev/null +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -0,0 +1,60 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_RRC_NR_TEST_HELPERS_H +#define SRSRAN_RRC_NR_TEST_HELPERS_H + +#include "srsenb/test/common/dummy_classes_common.h" +#include "srsgnb/hdr/stack/common/test/dummy_nr_classes.h" +#include "srsgnb/hdr/stack/rrc/rrc_nr.h" + +namespace srsenb { + +class pdcp_nr_rrc_tester : public pdcp_dummy +{ +public: + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) override + { + last_sdu_rnti = rnti; + last_sdu_lcid = lcid; + last_sdu = std::move(sdu); + } + + uint16_t last_sdu_rnti = SRSRAN_INVALID_RNTI; + uint32_t last_sdu_lcid = srsran::MAX_NR_NOF_BEARERS; + srsran::unique_byte_buffer_t last_sdu; +}; + +class rlc_nr_rrc_tester : public rlc_dummy +{ +public: + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu) + { + last_sdu_rnti = rnti; + last_sdu_lcid = lcid; + last_sdu = std::move(sdu); + } + + uint16_t last_sdu_rnti; + uint32_t last_sdu_lcid; + srsran::unique_byte_buffer_t last_sdu; +}; + +/// Run TS 38.331, 5.3.3 "RRC connection establishment" to completion +int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + rlc_nr_rrc_tester& rlc, + uint16_t rnti); + +} // namespace srsenb + +#endif // SRSRAN_RRC_NR_TEST_HELPERS_H diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 790547448..d363ea9cd 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -15,8 +15,8 @@ #include "dummy_rx_harq_proc.h" #include "dummy_tx_harq_proc.h" -#include "srsenb/test/common/dummy_classes_nr.h" #include "srsenb/test/common/rlc_test_dummy.h" +#include "srsgnb/hdr/stack/common/test/dummy_nr_classes.h" #include "srsgnb/hdr/stack/mac/mac_nr.h" #include "srsgnb/hdr/stack/mac/sched_nr.h" #include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" From 16753a006aae0eb5833e50f327be8aa0c09f005c Mon Sep 17 00:00:00 2001 From: Francisco Date: Tue, 9 Nov 2021 20:32:18 +0000 Subject: [PATCH 33/35] nr,gnb,rrc: add test logger delimiter; handle rrc setup complete --- lib/include/srsran/common/test_common.h | 28 ++++++++++ srsenb/src/stack/rrc/rrc.cc | 4 +- srsgnb/hdr/stack/rrc/rrc_nr.h | 20 ++++--- srsgnb/src/stack/rrc/cell_asn1_config.cc | 2 +- srsgnb/src/stack/rrc/rrc_nr.cc | 54 ++++++++++++++++--- srsgnb/src/stack/rrc/test/rrc_nr_test.cc | 47 ++++++++-------- .../src/stack/rrc/test/rrc_nr_test_helpers.cc | 22 +++++--- .../src/stack/rrc/test/rrc_nr_test_helpers.h | 20 +++++-- 8 files changed, 146 insertions(+), 51 deletions(-) diff --git a/lib/include/srsran/common/test_common.h b/lib/include/srsran/common/test_common.h index 8c6f8d5f7..9acfcbadc 100644 --- a/lib/include/srsran/common/test_common.h +++ b/lib/include/srsran/common/test_common.h @@ -137,6 +137,7 @@ inline void test_init(int argc, char** argv) srsran_debug_handle_crash(argc, argv); srslog::fetch_basic_logger("ALL").set_level(srslog::basic_levels::info); + srslog::fetch_basic_logger("TEST").set_level(srslog::basic_levels::info); // Start the log backend. srslog::init(); @@ -153,6 +154,33 @@ inline void copy_msg_to_buffer(unique_byte_buffer_t& pdu, const_byte_span msg) pdu->N_bytes = msg.size(); } +class test_delimit_logger +{ + const size_t delimiter_length = 128; + +public: + template + explicit test_delimit_logger(const char* test_name_fmt, Args&&... args) + { + test_name = fmt::format(test_name_fmt, std::forward(args)...); + std::string name_str = fmt::format("[ Test \"{}\" ]", test_name); + double nof_repeats = (delimiter_length - name_str.size()) / 2.0; + fmt::print("{0:=>{1}}{2}{0:=>{3}}\n", "", (int)floor(nof_repeats), name_str, (int)ceil(nof_repeats)); + } + test_delimit_logger(const test_delimit_logger&) = delete; + test_delimit_logger(test_delimit_logger&&) = delete; + test_delimit_logger& operator=(const test_delimit_logger&) = delete; + test_delimit_logger& operator=(test_delimit_logger&&) = delete; + ~test_delimit_logger() + { + srslog::flush(); + fmt::print("{:=>{}}\n", "", delimiter_length); + } + +private: + std::string test_name; +}; + } // namespace srsran #define CONDERROR(cond, fmt, ...) srsran_assert(not(cond), fmt, ##__VA_ARGS__) diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index bf93dcfeb..74002f586 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -634,7 +634,7 @@ void rrc::sgnb_release_ack(uint16_t eutra_rnti) void rrc::parse_ul_ccch(ue& ue, srsran::unique_byte_buffer_t pdu) { - srsran_assert(pdu != nullptr, "parse_ul_ccch called for empty message"); + srsran_assert(pdu != nullptr, "handle_ul_ccch called for empty message"); ul_ccch_msg_s ul_ccch_msg; asn1::cbit_ref bref(pdu->msg, pdu->N_bytes); @@ -667,7 +667,7 @@ void rrc::parse_ul_ccch(ue& ue, srsran::unique_byte_buffer_t pdu) ///< User mutex must be hold by caller void rrc::parse_ul_dcch(ue& ue, uint32_t lcid, srsran::unique_byte_buffer_t pdu) { - srsran_assert(pdu != nullptr, "parse_ul_dcch called for empty message"); + srsran_assert(pdu != nullptr, "handle_ul_dcch called for empty message"); ue.parse_ul_dcch(lcid, std::move(pdu)); } diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index 9c9efe00d..bb21b0fb2 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -123,15 +123,9 @@ public: void send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_dcch_msg); - /* TS 38.331 - 5.3.3 RRC connection establishment */ - void send_rrc_setup(); - void send_rrc_reject(uint8_t reject_wait_time_secs); - int handle_sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params); void crnti_ce_received(); - void handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg); - // getters bool is_connected() { return state == rrc_nr_state_t::RRC_CONNECTED; } bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; } @@ -151,10 +145,18 @@ public: void set_activity(bool enabled = true); void activity_timer_expired(const activity_timeout_type_t type); + /* TS 38.331 - 5.3.3 RRC connection establishment */ + void handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg); + void handle_rrc_setup_complete(const asn1::rrc_nr::rrc_setup_complete_s& msg); + private: rrc_nr* parent = nullptr; uint16_t rnti = SRSRAN_INVALID_RNTI; + /* TS 38.331 - 5.3.3 RRC connection establishment */ + void send_rrc_setup(); + void send_rrc_reject(uint8_t reject_wait_time_secs); + int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig); int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config); @@ -260,8 +262,12 @@ private: /// Private Methods void handle_pdu(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu); - void parse_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu); + void handle_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu); + void handle_ul_dcch(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu); + + // TS 38.331, 5.3.3 - RRC connection establishment void handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_setup_request_s& msg); + /// This gets called by rrc_nr::sgnb_addition_request and WILL NOT TRIGGER the RX MSG3 activity timer int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer); diff --git a/srsgnb/src/stack/rrc/cell_asn1_config.cc b/srsgnb/src/stack/rrc/cell_asn1_config.cc index 379ef7f57..56a329d89 100644 --- a/srsgnb/src/stack/rrc/cell_asn1_config.cc +++ b/srsgnb/src/stack/rrc/cell_asn1_config.cc @@ -297,7 +297,7 @@ int fill_pdcch_cfg_from_enb_cfg(const rrc_nr_cfg_t& cfg, uint32_t cc, pdcch_cfg_ (search_space_cfg.type == srsran_search_space_type_common_1) or (search_space_cfg.type == srsran_search_space_type_common_2) or (search_space_cfg.type == srsran_search_space_type_common_3)) { - search_spaces[0].search_space_type.set_common(); + search_spaces[ss_mod_list_idx].search_space_type.set_common(); search_spaces[ss_mod_list_idx].search_space_type.common().dci_format0_minus0_and_format1_minus0_present = true; } else { diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 84258ec08..661fe69a4 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -108,8 +108,6 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, config_phy(); // if PHY is not yet initialized, config will be stored and applied on initialization config_mac(); - logger.info("Started"); - running = true; return SRSRAN_SUCCESS; @@ -416,15 +414,14 @@ void rrc_nr::get_metrics(srsenb::rrc_metrics_t& m) void rrc_nr::handle_pdu(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu) { - logger.info(pdu.data(), pdu.size(), "Rx %s PDU", get_rb_name(lcid)); - switch (static_cast(lcid)) { case srsran::nr_srb::srb0: - parse_ul_ccch(rnti, pdu); + handle_ul_ccch(rnti, pdu); break; case srsran::nr_srb::srb1: case srsran::nr_srb::srb2: - // parse_ul_dcch(p.rnti, p.lcid, std::move(p.pdu)); + case srsran::nr_srb::srb3: + handle_ul_dcch(rnti, lcid, std::move(pdu)); break; default: std::string errcause = fmt::format("Invalid LCID=%d", lcid); @@ -433,7 +430,7 @@ void rrc_nr::handle_pdu(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pd } } -void rrc_nr::parse_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu) +void rrc_nr::handle_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu) { // Parse UL-CCCH ul_ccch_msg_s ul_ccch_msg; @@ -463,6 +460,43 @@ void rrc_nr::parse_ul_ccch(uint16_t rnti, srsran::const_byte_span pdu) } } +void rrc_nr::handle_ul_dcch(uint16_t rnti, uint32_t lcid, srsran::const_byte_span pdu) +{ + // Parse UL-DCCH + ul_dcch_msg_s ul_dcch_msg; + { + asn1::cbit_ref bref(pdu.data(), pdu.size()); + if (ul_dcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or + ul_dcch_msg.msg.type().value != ul_dcch_msg_type_c::types_opts::c1) { + log_rx_pdu_fail(rnti, lcid, pdu, "Failed to unpack UL-DCCH message"); + return; + } + } + + // Verify UE exists + auto ue_it = users.find(rnti); + if (ue_it == users.end()) { + log_rx_pdu_fail(rnti, lcid, pdu, "Inexistent rnti"); + } + ue& u = *ue_it->second; + + // Log Rx message + fmt::memory_buffer fmtbuf, fmtbuf2; + fmt::format_to(fmtbuf, "rnti=0x{:x}, {}", rnti, srsran::get_srb_name(srsran::nr_lcid_to_srb(lcid))); + fmt::format_to(fmtbuf2, "UL-DCCH.{}", ul_dcch_msg.msg.c1().type().to_string()); + log_rrc_message(srsran::to_c_str(fmtbuf), Rx, pdu, ul_dcch_msg, srsran::to_c_str(fmtbuf2)); + + // Handle message + switch (ul_dcch_msg.msg.c1().type().value) { + case ul_dcch_msg_type_c::c1_c_::types_opts::rrc_setup_complete: + u.handle_rrc_setup_complete(ul_dcch_msg.msg.c1().rrc_setup_complete()); + break; + default: + log_rx_pdu_fail(rnti, srb_to_lcid(lte_srb::srb0), pdu, "Unsupported UL-CCCH message type", false); + // TODO Remove user + } +} + void rrc_nr::handle_rrc_setup_request(uint16_t rnti, const asn1::rrc_nr::rrc_setup_request_s& msg) { auto ue_it = users.find(rnti); @@ -1509,6 +1543,12 @@ void rrc_nr::ue::send_rrc_setup() send_dl_ccch(msg); } +/// TS 38.331, RRCSetupComplete +void rrc_nr::ue::handle_rrc_setup_complete(const asn1::rrc_nr::rrc_setup_complete_s& msg) +{ + // TODO: handle RRCSetupComplete +} + /** * @brief Deactivate all Bearers (MAC logical channel) for this specific RNTI * diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc index 3bcca174b..828ecd988 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test.cc @@ -39,15 +39,16 @@ int test_cell_cfg(const srsenb::sched_interface::cell_cfg_t& cellcfg) * Test 1 - Test default SIB generation * Description: Check whether the SIBs were set correctly */ -int test_sib_generation() +void test_sib_generation() { - srsran::task_scheduler task_sched; + srsran::test_delimit_logger test_logger{"SIB generation"}; - phy_nr_dummy phy_obj; - mac_nr_dummy mac_obj; - rlc_dummy rlc_obj; - pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&task_sched); + srsran::task_scheduler task_sched; + phy_nr_dummy phy_obj; + mac_nr_dummy mac_obj; + rlc_dummy rlc_obj; + pdcp_dummy pdcp_obj; + rrc_nr rrc_obj(&task_sched); // set cfg all_args_t args{}; @@ -88,19 +89,18 @@ int test_sib_generation() pdcch_cfg_common_s& pdcch = sib1.serving_cell_cfg_common.dl_cfg_common.init_dl_bwp.pdcch_cfg_common.setup(); TESTASSERT(not pdcch.ctrl_res_set_zero_present); // CORESET#0 id is passed in MIB TESTASSERT(not pdcch.search_space_zero_present); // SS#0 id is passed in MIB - - return SRSRAN_SUCCESS; } int test_rrc_setup() { - srsran::task_scheduler task_sched; + srsran::test_delimit_logger test_logger{"NSA RRC"}; - phy_nr_dummy phy_obj; - mac_nr_dummy mac_obj; - rlc_dummy rlc_obj; - pdcp_dummy pdcp_obj; - rrc_nr rrc_obj(&task_sched); + srsran::task_scheduler task_sched; + phy_nr_dummy phy_obj; + mac_nr_dummy mac_obj; + rlc_dummy rlc_obj; + pdcp_dummy pdcp_obj; + rrc_nr rrc_obj(&task_sched); // set cfg all_args_t args{}; @@ -129,13 +129,14 @@ int test_rrc_setup() void test_rrc_sa_connection() { - srsran::task_scheduler task_sched; + srsran::test_delimit_logger test_logger{"SA RRCConnectionEstablishment"}; - phy_nr_dummy phy_obj; - mac_nr_dummy mac_obj; - rlc_nr_rrc_tester rlc_obj; - pdcp_nr_rrc_tester pdcp_obj; - ngap_dummy ngap_obj; + srsran::task_scheduler task_sched; + phy_nr_dummy phy_obj; + mac_nr_dummy mac_obj; + rlc_nr_rrc_tester rlc_obj; + pdcp_nr_rrc_tester pdcp_obj; + ngap_dummy ngap_obj; rrc_nr rrc_obj(&task_sched); @@ -157,7 +158,7 @@ void test_rrc_sa_connection() sched_nr_ue_cfg_t uecfg = get_default_ue_cfg(1); TESTASSERT_SUCCESS(rrc_obj.add_user(0x4601, uecfg)); - TESTASSERT_SUCCESS(test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, 0x4601)); + test_rrc_nr_connection_establishment(task_sched, rrc_obj, rlc_obj, 0x4601); } } // namespace srsenb @@ -177,7 +178,7 @@ int main(int argc, char** argv) } argparse::parse_args(argc, argv); - TESTASSERT(srsenb::test_sib_generation() == SRSRAN_SUCCESS); + srsenb::test_sib_generation(); TESTASSERT(srsenb::test_rrc_setup() == SRSRAN_SUCCESS); srsenb::test_rrc_sa_connection(); diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc index 3fbdb3aa6..7d4a8a62a 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.cc @@ -17,10 +17,10 @@ using namespace asn1::rrc_nr; namespace srsenb { -int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, - rrc_nr& rrc_obj, - rlc_nr_rrc_tester& rlc, - uint16_t rnti) +void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + rlc_nr_rrc_tester& rlc, + uint16_t rnti) { srsran::unique_byte_buffer_t pdu; @@ -49,7 +49,7 @@ int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, } TESTASSERT_EQ(dl_ccch_msg_type_c::types_opts::c1, dl_ccch_msg.msg.type().value); TESTASSERT_EQ(dl_ccch_msg_type_c::c1_c_::types_opts::rrc_setup, dl_ccch_msg.msg.c1().type().value); - TESTASSERT_EQ(asn1::rrc_nr::rrc_setup_s::crit_exts_c_::types_opts::rrc_setup, + TESTASSERT_EQ(rrc_setup_s::crit_exts_c_::types_opts::rrc_setup, dl_ccch_msg.msg.c1().rrc_setup().crit_exts.type().value); const rrc_setup_ies_s& setup_ies = dl_ccch_msg.msg.c1().rrc_setup().crit_exts.rrc_setup(); @@ -59,7 +59,17 @@ int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, const srb_to_add_mod_s& srb1 = setup_ies.radio_bearer_cfg.srb_to_add_mod_list[0]; TESTASSERT_EQ(srsran::srb_to_lcid(srsran::nr_srb::srb1), srb1.srb_id); - return SRSRAN_SUCCESS; + ul_dcch_msg_s ul_dcch_msg; + rrc_setup_complete_s& complete = ul_dcch_msg.msg.set_c1().set_rrc_setup_complete(); + complete.rrc_transaction_id = dl_ccch_msg.msg.c1().rrc_setup().rrc_transaction_id; + rrc_setup_complete_ies_s& complete_ies = complete.crit_exts.set_rrc_setup_complete(); + { + pdu = srsran::make_byte_buffer(); + asn1::bit_ref bref{pdu->data(), pdu->get_tailroom()}; + TESTASSERT_SUCCESS(ul_dcch_msg.pack(bref)); + pdu->N_bytes = bref.distance_bytes(); + } + rrc_obj.write_pdu(rnti, 1, std::move(pdu)); } } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h index 92539e11f..b82bef20b 100644 --- a/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h +++ b/srsgnb/src/stack/rrc/test/rrc_nr_test_helpers.h @@ -49,11 +49,21 @@ public: srsran::unique_byte_buffer_t last_sdu; }; -/// Run TS 38.331, 5.3.3 "RRC connection establishment" to completion -int test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, - rrc_nr& rrc_obj, - rlc_nr_rrc_tester& rlc, - uint16_t rnti); +/** + * Run TS 38.331, 5.3.3 "RRC connection establishment" to completion + * RRC actions: + * - Rx RRCSetupRequest + * - Tx RRCSetup to lower layers + * - Tx RRCSetupComplete + * Checks: + * - the RRC sends RRCSetup as reply to RRCSetupRequest + * - verify that RRCSetup rnti, lcid are correct + * - verify that RRCSetup adds an SRB1 + */ +void test_rrc_nr_connection_establishment(srsran::task_scheduler& task_sched, + rrc_nr& rrc_obj, + rlc_nr_rrc_tester& rlc, + uint16_t rnti); } // namespace srsenb From 174648e4870cdf570d101acee408a5a43665307c Mon Sep 17 00:00:00 2001 From: Pedro Alvarez Date: Wed, 10 Nov 2021 14:06:26 +0000 Subject: [PATCH 34/35] Restart S1AP on SCTP_ERROR event --- srsenb/src/stack/s1ap/s1ap.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/srsenb/src/stack/s1ap/s1ap.cc b/srsenb/src/stack/s1ap/s1ap.cc index b714f8b65..f64b6a2a9 100644 --- a/srsenb/src/stack/s1ap/s1ap.cc +++ b/srsenb/src/stack/s1ap/s1ap.cc @@ -564,6 +564,10 @@ bool s1ap::handle_mme_rx_msg(srsran::unique_byte_buffer_t pdu, logger.info("SCTP peer addres unreachable. Association: %d", sri.sinfo_assoc_id); srsran::console("SCTP peer address unreachable. Association: %d\n", sri.sinfo_assoc_id); restart_s1 = true; + } else if (notification->sn_header.sn_type == SCTP_REMOTE_ERROR) { + logger.info("SCTP remote error. Association: %d", sri.sinfo_assoc_id); + srsran::console("SCTP remote error. Association: %d\n", sri.sinfo_assoc_id); + restart_s1 = true; } else if (notification->sn_header.sn_type == SCTP_ASSOC_CHANGE) { logger.info("SCTP association changed. Association: %d", sri.sinfo_assoc_id); srsran::console("SCTP association changed. Association: %d\n", sri.sinfo_assoc_id); From f3b427cbd7b476fd50c1d65e6acd11a95f68d9ef Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 10 Nov 2021 11:59:01 +0000 Subject: [PATCH 35/35] nr,gnb,rrc: separate rrc_nr::ue into its own file --- srsgnb/hdr/stack/rrc/rrc_nr.h | 156 +---- srsgnb/hdr/stack/rrc/rrc_nr_ue.h | 141 ++++ srsgnb/src/stack/rrc/CMakeLists.txt | 2 +- srsgnb/src/stack/rrc/rrc_nr.cc | 966 +-------------------------- srsgnb/src/stack/rrc/rrc_nr_ue.cc | 971 ++++++++++++++++++++++++++++ 5 files changed, 1154 insertions(+), 1082 deletions(-) create mode 100644 srsgnb/hdr/stack/rrc/rrc_nr_ue.h create mode 100644 srsgnb/src/stack/rrc/rrc_nr_ue.cc diff --git a/srsgnb/hdr/stack/rrc/rrc_nr.h b/srsgnb/hdr/stack/rrc/rrc_nr.h index bb21b0fb2..ab3cd2a3b 100644 --- a/srsgnb/hdr/stack/rrc/rrc_nr.h +++ b/srsgnb/hdr/stack/rrc/rrc_nr.h @@ -47,6 +47,7 @@ class rrc_nr final : public rrc_interface_pdcp_nr, { public: explicit rrc_nr(srsran::task_sched_handle task_sched_); + ~rrc_nr(); int32_t init(const rrc_nr_cfg_t& cfg, phy_interface_stack_nr* phy, @@ -68,37 +69,40 @@ public: int read_pdu_bcch_dlsch(uint32_t sib_index, srsran::byte_buffer_t& buffer) final; /// User manegement - int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg); + int add_user(uint16_t rnti, const sched_nr_ue_cfg_t& uecfg) final; void rem_user(uint16_t rnti); - int update_user(uint16_t new_rnti, uint16_t old_rnti); - void set_activity_user(uint16_t rnti); + int update_user(uint16_t new_rnti, uint16_t old_rnti) final; + void set_activity_user(uint16_t rnti) final; // RLC interface // TODO - void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) {} - void max_retx_attempted(uint16_t rnti) {} - void protocol_failure(uint16_t rnti) {} - const char* get_rb_name(uint32_t lcid) { return "invalid"; } + void read_pdu_pcch(uint8_t* payload, uint32_t payload_size) final {} + void max_retx_attempted(uint16_t rnti) final {} + void protocol_failure(uint16_t rnti) final {} + const char* get_rb_name(uint32_t lcid) final { return "invalid"; } // PDCP interface void write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) final; void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) final; // Interface for EUTRA RRC - void sgnb_addition_request(uint16_t rnti, const sgnb_addition_req_params_t& params); + void sgnb_addition_request(uint16_t rnti, const sgnb_addition_req_params_t& params) final; void sgnb_reconfiguration_complete(uint16_t rnti, const asn1::dyn_octstring& reconfig_response) final; void sgnb_release_request(uint16_t nr_rnti) final; // Interfaces for NGAP - int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key); - int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates); - int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps); - int start_security_mode_procedure(uint16_t rnti); - int establish_rrc_bearer(uint16_t rnti, uint16_t pdu_session_id, srsran::const_byte_span nas_pdu, uint32_t lcid); - int release_bearers(uint16_t rnti); - void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu); - int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates); - int allocate_lcid(uint16_t rnti); + int ue_set_security_cfg_key(uint16_t rnti, const asn1::fixed_bitstring<256, false, true>& key) final; + int ue_set_bitrates(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) final; + int ue_set_security_cfg_capabilities(uint16_t rnti, const asn1::ngap_nr::ue_security_cap_s& caps) final; + int start_security_mode_procedure(uint16_t rnti) final; + int establish_rrc_bearer(uint16_t rnti, + uint16_t pdu_session_id, + srsran::const_byte_span nas_pdu, + uint32_t lcid) final; + int release_bearers(uint16_t rnti) final; + void write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) final; + int set_aggregate_max_bitrate(uint16_t rnti, const asn1::ngap_nr::ue_aggregate_maximum_bit_rate_s& rates) final; + int allocate_lcid(uint16_t rnti) final; // logging typedef enum { Rx = 0, Tx } direction_t; @@ -108,124 +112,8 @@ public: srsran::const_byte_span pdu, const T& msg, const char* msg_type); - class ue - { - public: - enum activity_timeout_type_t { - MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs - UE_INACTIVITY_TIMEOUT, ///< (currently unused) UE inactivity timeout (usually bigger than reestablishment timeout) - MSG5_RX_TIMEOUT, ///< (currently unused) for receiving RRCConnectionSetupComplete/RRCReestablishmentComplete - nulltype - }; - /// @param [in] start_msg3_timer: indicates whether the UE is created as part of a RACH process - ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer = true); - - void send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_dcch_msg); - - int handle_sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params); - void crnti_ce_received(); - - // getters - bool is_connected() { return state == rrc_nr_state_t::RRC_CONNECTED; } - bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; } - bool is_inactive() { return state == rrc_nr_state_t::RRC_INACTIVE; } - bool is_endc() { return endc; } - uint16_t get_eutra_rnti() { return eutra_rnti; } - void get_metrics(rrc_ue_metrics_t& ue_metrics) { ue_metrics = {}; /*TODO fill RRC metrics*/ }; - - // setters - - int pack_rrc_reconfiguration(); - void deactivate_bearers(); - - /// methods to handle activity timer - std::string to_string(const activity_timeout_type_t& type); - void set_activity_timeout(activity_timeout_type_t type); - void set_activity(bool enabled = true); - void activity_timer_expired(const activity_timeout_type_t type); - - /* TS 38.331 - 5.3.3 RRC connection establishment */ - void handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg); - void handle_rrc_setup_complete(const asn1::rrc_nr::rrc_setup_complete_s& msg); - - private: - rrc_nr* parent = nullptr; - uint16_t rnti = SRSRAN_INVALID_RNTI; - - /* TS 38.331 - 5.3.3 RRC connection establishment */ - void send_rrc_setup(); - void send_rrc_reject(uint8_t reject_wait_time_secs); - - int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig); - int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config); - - int pack_secondary_cell_group_rlc_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_secondary_cell_group_mac_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_secondary_cell_group_sp_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_sp_cell_cfg_ded(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_sp_cell_cfg_ded_init_dl_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_sp_cell_cfg_ded_init_dl_bwp_pdsch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_sp_cell_cfg_ded_init_dl_bwp_radio_link_monitoring(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_sp_cell_cfg_ded_ul_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pucch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pusch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_sp_cell_cfg_ded_pdcch_serving_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_recfg_with_sync(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_recfg_with_sync_sp_cell_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common_phy_cell_group_cfg( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp_pdsch_cfg_common( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - int pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp_pusch_cfg_common( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); - - int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config); - - int add_drb(); - - // logging helpers - template - void log_rrc_message(srsran::nr_srb srb, - const direction_t dir, - srsran::const_byte_span pdu, - const M& msg, - const char* msg_type); - template - void log_rrc_container(const direction_t dir, srsran::const_byte_span pdu, const M& msg, const char* msg_type); - - // state - rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; - uint8_t transaction_id = 0; - srsran::unique_timer activity_timer; /// for basic DL/UL activity timeout - - // RRC configs for UEs - asn1::rrc_nr::cell_group_cfg_s cell_group_cfg; - asn1::rrc_nr::radio_bearer_cfg_s radio_bearer_cfg; - - // MAC controller - sched_nr_interface::ue_cfg_t uecfg{}; - - const uint32_t drb1_lcid = 4; - - // NSA specific variables - bool endc = false; - uint16_t eutra_rnti = SRSRAN_INVALID_RNTI; - }; + class ue; private: static constexpr uint32_t UE_PSCELL_CC_IDX = 0; // first NR cell is always Primary Secondary Cell for UE diff --git a/srsgnb/hdr/stack/rrc/rrc_nr_ue.h b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h new file mode 100644 index 000000000..cc2c38569 --- /dev/null +++ b/srsgnb/hdr/stack/rrc/rrc_nr_ue.h @@ -0,0 +1,141 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_RRC_NR_UE_H +#define SRSRAN_RRC_NR_UE_H + +#include "rrc_nr.h" + +namespace srsenb { + +class rrc_nr::ue +{ +public: + enum activity_timeout_type_t { + MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs + UE_INACTIVITY_TIMEOUT, ///< (currently unused) UE inactivity timeout (usually bigger than reestablishment timeout) + MSG5_RX_TIMEOUT, ///< (currently unused) for receiving RRCConnectionSetupComplete/RRCReestablishmentComplete + nulltype + }; + + /// @param [in] start_msg3_timer: indicates whether the UE is created as part of a RACH process + ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg, bool start_msg3_timer = true); + ~ue(); + + void send_dl_ccch(const asn1::rrc_nr::dl_ccch_msg_s& dl_dcch_msg); + + int handle_sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params); + void crnti_ce_received(); + + // getters + bool is_connected() { return state == rrc_nr_state_t::RRC_CONNECTED; } + bool is_idle() { return state == rrc_nr_state_t::RRC_IDLE; } + bool is_inactive() { return state == rrc_nr_state_t::RRC_INACTIVE; } + bool is_endc() { return endc; } + uint16_t get_eutra_rnti() { return eutra_rnti; } + void get_metrics(rrc_ue_metrics_t& ue_metrics) { ue_metrics = {}; /*TODO fill RRC metrics*/ }; + + // setters + + void deactivate_bearers(); + + /// methods to handle activity timer + std::string to_string(const activity_timeout_type_t& type); + void set_activity_timeout(activity_timeout_type_t type); + void set_activity(bool enabled = true); + void activity_timer_expired(const activity_timeout_type_t type); + + /* TS 38.331 - 5.3.3 RRC connection establishment */ + void handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg); + void handle_rrc_setup_complete(const asn1::rrc_nr::rrc_setup_complete_s& msg); + +private: + rrc_nr* parent = nullptr; + uint16_t rnti = SRSRAN_INVALID_RNTI; + + /* TS 38.331 - 5.3.3 RRC connection establishment */ + void send_rrc_setup(); + void send_rrc_reject(uint8_t reject_wait_time_secs); + + int pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig); + int pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config); + + int pack_secondary_cell_group_rlc_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_secondary_cell_group_mac_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_secondary_cell_group_sp_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_sp_cell_cfg_ded(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_sp_cell_cfg_ded_init_dl_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_sp_cell_cfg_ded_init_dl_bwp_pdsch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_sp_cell_cfg_ded_init_dl_bwp_radio_link_monitoring(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_sp_cell_cfg_ded_ul_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pucch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pusch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_sp_cell_cfg_ded_pdcch_serving_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_recfg_with_sync(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_recfg_with_sync_sp_cell_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common_phy_cell_group_cfg( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp_pdsch_cfg_common( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + int pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp_pusch_cfg_common( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack); + + int pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config); + + int add_drb(); + + // logging helpers + template + void log_rrc_message(srsran::nr_srb srb, + const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type); + template + void log_rrc_container(const direction_t dir, srsran::const_byte_span pdu, const M& msg, const char* msg_type); + + // state + rrc_nr_state_t state = rrc_nr_state_t::RRC_IDLE; + uint8_t transaction_id = 0; + srsran::unique_timer activity_timer; /// for basic DL/UL activity timeout + + // RRC configs for UEs + asn1::rrc_nr::cell_group_cfg_s cell_group_cfg; + asn1::rrc_nr::radio_bearer_cfg_s radio_bearer_cfg; + + // MAC controller + sched_nr_interface::ue_cfg_t uecfg{}; + + const uint32_t drb1_lcid = 4; + + // NSA specific variables + bool endc = false; + uint16_t eutra_rnti = SRSRAN_INVALID_RNTI; +}; + +} // namespace srsenb + +#endif // SRSRAN_RRC_NR_UE_H diff --git a/srsgnb/src/stack/rrc/CMakeLists.txt b/srsgnb/src/stack/rrc/CMakeLists.txt index 58ee3867c..0e63798ee 100644 --- a/srsgnb/src/stack/rrc/CMakeLists.txt +++ b/srsgnb/src/stack/rrc/CMakeLists.txt @@ -6,7 +6,7 @@ # the distribution. # -set(SOURCES rrc_nr.cc cell_asn1_config.cc) +set(SOURCES rrc_nr.cc rrc_nr_ue.cc cell_asn1_config.cc) add_library(srsgnb_rrc STATIC ${SOURCES}) target_link_libraries(srsgnb_rrc srsran_rrc_nr) diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 661fe69a4..906cb1593 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -13,6 +13,7 @@ #include "srsgnb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/common/common_enb.h" #include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" +#include "srsgnb/hdr/stack/rrc/rrc_nr_ue.h" #include "srsgnb/src/stack/mac/test/sched_nr_cfg_generators.h" #include "srsran/asn1/rrc_nr_utils.h" #include "srsran/common/common_nr.h" @@ -28,6 +29,8 @@ rrc_nr::rrc_nr(srsran::task_sched_handle task_sched_) : logger(srslog::fetch_basic_logger("RRC-NR")), task_sched(task_sched_) {} +rrc_nr::~rrc_nr() {} + int rrc_nr::init(const rrc_nr_cfg_t& cfg_, phy_interface_stack_nr* phy_, mac_interface_rrc_nr* mac_, @@ -137,6 +140,21 @@ void rrc_nr::log_rrc_message(const char* source, logger.info(pdu.data(), pdu.size(), "%s - %s %s (%d B)", source, (dir == Rx) ? "Rx" : "Tx", msg_type, pdu.size()); } } +template void rrc_nr::log_rrc_message(const char* source, + const direction_t dir, + srsran::const_byte_span pdu, + const dl_ccch_msg_s& msg, + const char* msg_type); +template void rrc_nr::log_rrc_message(const char* source, + const direction_t dir, + srsran::const_byte_span pdu, + const cell_group_cfg_s& msg, + const char* msg_type); +template void rrc_nr::log_rrc_message(const char* source, + const direction_t dir, + srsran::const_byte_span pdu, + const radio_bearer_cfg_s& msg, + const char* msg_type); void rrc_nr::log_rx_pdu_fail(uint16_t rnti, uint32_t lcid, @@ -623,111 +641,6 @@ void rrc_nr::sgnb_release_request(uint16_t nr_rnti) } } -/******************************************************************************* - UE class - - Every function in UE class is called from a mutex environment thus does not - need extra protection. -*******************************************************************************/ -rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg_, bool start_msg3_timer) : - parent(parent_), rnti(rnti_), uecfg(uecfg_) -{ - // Derive UE cfg from rrc_cfg_nr_t - uecfg.phy_cfg.pdcch = parent->cfg.cell_list[0].phy_cell.pdcch; - - // Set timer for MSG3_RX_TIMEOUT or UE_INACTIVITY_TIMEOUT - activity_timer = parent->task_sched.get_unique_timer(); - start_msg3_timer ? set_activity_timeout(MSG3_RX_TIMEOUT) : set_activity_timeout(MSG5_RX_TIMEOUT); -} - -void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type) -{ - uint32_t deadline_ms = 0; - - switch (type) { - case MSG3_RX_TIMEOUT: - // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 100ms - deadline_ms = 100; - break; - case MSG5_RX_TIMEOUT: - // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 1s - deadline_ms = 5000; - break; - case UE_INACTIVITY_TIMEOUT: - // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 5s - deadline_ms = 10000; - break; - default: - parent->logger.error("Unknown timeout type %d", type); - return; - } - - activity_timer.set(deadline_ms, [this, type](uint32_t tid) { activity_timer_expired(type); }); - parent->logger.debug("Setting timer for %s for rnti=0x%x to %dms", to_string(type).c_str(), rnti, deadline_ms); - - set_activity(); -} - -void rrc_nr::ue::set_activity(bool enabled) -{ - if (not enabled) { - if (activity_timer.is_running()) { - parent->logger.debug("Inactivity timer interrupted for rnti=0x%x", rnti); - } - activity_timer.stop(); - return; - } - - // re-start activity timer with current timeout value - activity_timer.run(); - parent->logger.debug("Activity registered for rnti=0x%x (timeout_value=%dms)", rnti, activity_timer.duration()); -} - -void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type) -{ - parent->logger.info("Activity timer for rnti=0x%x expired after %d ms", rnti, activity_timer.time_elapsed()); - - switch (type) { - case MSG5_RX_TIMEOUT: - case UE_INACTIVITY_TIMEOUT: - state = rrc_nr_state_t::RRC_INACTIVE; - parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti); - break; - case MSG3_RX_TIMEOUT: { - // MSG3 timeout, no need to notify NGAP or LTE stack. Just remove UE - state = rrc_nr_state_t::RRC_IDLE; - uint32_t rnti_to_rem = rnti; - parent->task_sched.defer_task([this, rnti_to_rem]() { parent->rem_user(rnti_to_rem); }); - break; - } - default: - // Unhandled activity timeout, just remove UE and log an error - parent->rem_user(rnti); - parent->logger.error( - "Unhandled reason for activity timer expiration. rnti=0x%x, cause %d", rnti, static_cast(type)); - } -} - -std::string rrc_nr::ue::to_string(const activity_timeout_type_t& type) -{ - constexpr static const char* options[] = {"Msg3 reception", "UE inactivity", "Msg5 reception"}; - return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type); -} - -void rrc_nr::ue::send_dl_ccch(const dl_ccch_msg_s& dl_ccch_msg) -{ - // Allocate a new PDU buffer, pack the message and send to PDCP - srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(dl_ccch_msg); - if (pdu == nullptr) { - parent->logger.error("Failed to send DL-CCCH"); - return; - } - fmt::memory_buffer fmtbuf; - fmt::format_to(fmtbuf, "DL-CCCH.{}", dl_ccch_msg.msg.c1().type().to_string()); - log_rrc_message(srsran::nr_srb::srb0, Tx, *pdu.get(), dl_ccch_msg, srsran::to_c_str(fmtbuf)); - parent->rlc->write_sdu(rnti, srsran::srb_to_lcid(srsran::nr_srb::srb0), std::move(pdu)); -} - template srsran::unique_byte_buffer_t rrc_nr::pack_into_pdu(const T& msg) { @@ -745,847 +658,6 @@ srsran::unique_byte_buffer_t rrc_nr::pack_into_pdu(const T& msg) pdu->N_bytes = bref.distance_bytes(); return pdu; } - -int rrc_nr::ue::pack_secondary_cell_group_rlc_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // 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); - auto& rlc_bearer = cell_group_cfg_pack.rlc_bearer_to_add_mod_list[0]; - rlc_bearer.lc_ch_id = drb1_lcid; - rlc_bearer.served_radio_bearer_present = true; - rlc_bearer.served_radio_bearer.set_drb_id(); - rlc_bearer.served_radio_bearer.drb_id() = 1; - rlc_bearer.rlc_cfg_present = true; - rlc_bearer.rlc_cfg.set_um_bi_dir(); - rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present = true; - rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_um_opts::size12; - rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present = true; - rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_um_opts::size12; - rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.t_reassembly = t_reassembly_opts::ms50; - - // MAC logical channel config - rlc_bearer.mac_lc_ch_cfg_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.prio = 11; - rlc_bearer.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_bearer.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_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group = 6; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id = 0; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_secondary_cell_group_mac_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // mac-CellGroup-Config for BSR and SR - 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 - mac_cell_group.tag_cfg_present = false; - mac_cell_group.tag_cfg.tag_to_add_mod_list_present = true; - mac_cell_group.tag_cfg.tag_to_add_mod_list.resize(1); - mac_cell_group.tag_cfg.tag_to_add_mod_list[0].tag_id = 0; - mac_cell_group.tag_cfg.tag_to_add_mod_list[0].time_align_timer = time_align_timer_opts::infinity; - - mac_cell_group.phr_cfg_present = false; - mac_cell_group.phr_cfg.set_setup(); - mac_cell_group.phr_cfg.setup().phr_periodic_timer = asn1::rrc_nr::phr_cfg_s::phr_periodic_timer_opts::sf500; - mac_cell_group.phr_cfg.setup().phr_prohibit_timer = asn1::rrc_nr::phr_cfg_s::phr_prohibit_timer_opts::sf200; - mac_cell_group.phr_cfg.setup().phr_tx_pwr_factor_change = asn1::rrc_nr::phr_cfg_s::phr_tx_pwr_factor_change_opts::db3; - mac_cell_group.phr_cfg.setup().multiple_phr = true; - mac_cell_group.phr_cfg.setup().dummy = false; - mac_cell_group.phr_cfg.setup().phr_type2_other_cell = false; - mac_cell_group.phr_cfg.setup().phr_mode_other_cg = asn1::rrc_nr::phr_cfg_s::phr_mode_other_cg_opts::real; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_init_dl_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present = true; - - pack_sp_cell_cfg_ded_init_dl_bwp_pdsch_cfg(cell_group_cfg_pack); - pack_sp_cell_cfg_ded_init_dl_bwp_radio_link_monitoring(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_init_dl_bwp_radio_link_monitoring( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.radio_link_monitoring_cfg_present = true; - auto& radio_link_monitoring = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.radio_link_monitoring_cfg; - radio_link_monitoring.set_setup().fail_detection_res_to_add_mod_list_present = true; - - // add resource to detect RLF - radio_link_monitoring.set_setup().fail_detection_res_to_add_mod_list.resize(1); - auto& fail_detec_res_elem = radio_link_monitoring.set_setup().fail_detection_res_to_add_mod_list[0]; - fail_detec_res_elem.radio_link_monitoring_rs_id = 0; - fail_detec_res_elem.purpose = asn1::rrc_nr::radio_link_monitoring_rs_s::purpose_opts::rlf; - fail_detec_res_elem.detection_res.set_ssb_idx() = 0; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_init_dl_bwp_pdsch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - 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 = false; - 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 = false; - 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); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pucch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // PUCCH - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pucch_cfg_present = true; - auto& pucch_cfg = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pucch_cfg; - - pucch_cfg.set_setup(); - pucch_cfg.setup().format2_present = true; - pucch_cfg.setup().format2.set_setup(); - pucch_cfg.setup().format2.setup().max_code_rate_present = true; - pucch_cfg.setup().format2.setup().max_code_rate = pucch_max_code_rate_opts::zero_dot25; - - // SR resources - pucch_cfg.setup().sched_request_res_to_add_mod_list_present = true; - pucch_cfg.setup().sched_request_res_to_add_mod_list.resize(1); - auto& sr_res1 = 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() = 8; - sr_res1.res_present = true; - sr_res1.res = 2; // PUCCH resource for SR - - // DL data - pucch_cfg.setup().dl_data_to_ul_ack_present = true; - - if (parent->cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { - pucch_cfg.setup().dl_data_to_ul_ack.resize(1); - pucch_cfg.setup().dl_data_to_ul_ack[0] = 4; - } else { - pucch_cfg.setup().dl_data_to_ul_ack.resize(6); - pucch_cfg.setup().dl_data_to_ul_ack[0] = 6; - pucch_cfg.setup().dl_data_to_ul_ack[1] = 5; - pucch_cfg.setup().dl_data_to_ul_ack[2] = 4; - pucch_cfg.setup().dl_data_to_ul_ack[3] = 4; - pucch_cfg.setup().dl_data_to_ul_ack[4] = 4; - pucch_cfg.setup().dl_data_to_ul_ack[5] = 4; - } - - // PUCCH Resource for format 1 - srsran_pucch_nr_resource_t resource_small = {}; - resource_small.starting_prb = 0; - resource_small.format = SRSRAN_PUCCH_NR_FORMAT_1; - resource_small.initial_cyclic_shift = 0; - resource_small.nof_symbols = 14; - resource_small.start_symbol_idx = 0; - resource_small.time_domain_occ = 0; - - // PUCCH Resource for format 2 - srsran_pucch_nr_resource_t resource_big = {}; - resource_big.starting_prb = 51; - resource_big.format = SRSRAN_PUCCH_NR_FORMAT_2; - resource_big.nof_prb = 1; - resource_big.nof_symbols = 2; - resource_big.start_symbol_idx = 12; - - // Resource for SR - srsran_pucch_nr_resource_t resource_sr = {}; - resource_sr.starting_prb = 51; - resource_sr.format = SRSRAN_PUCCH_NR_FORMAT_1; - resource_sr.initial_cyclic_shift = 0; - resource_sr.nof_symbols = 14; - resource_sr.start_symbol_idx = 0; - resource_sr.time_domain_occ = 0; - - // Make 3 possible resources - pucch_cfg.setup().res_to_add_mod_list_present = true; - pucch_cfg.setup().res_to_add_mod_list.resize(3); - if (not srsran::make_phy_res_config(resource_small, pucch_cfg.setup().res_to_add_mod_list[0], 0)) { - parent->logger.warning("Failed to create 1-2 bit NR PUCCH resource"); - } - if (not srsran::make_phy_res_config(resource_big, pucch_cfg.setup().res_to_add_mod_list[1], 1)) { - parent->logger.warning("Failed to create >2 bit NR PUCCH resource"); - } - if (not srsran::make_phy_res_config(resource_sr, pucch_cfg.setup().res_to_add_mod_list[2], 2)) { - parent->logger.warning("Failed to create SR NR PUCCH resource"); - } - - // Make 2 PUCCH resource sets - pucch_cfg.setup().res_set_to_add_mod_list_present = true; - pucch_cfg.setup().res_set_to_add_mod_list.resize(2); - - // Make PUCCH resource set for 1-2 bit - pucch_cfg.setup().res_set_to_add_mod_list[0].pucch_res_set_id = 0; - pucch_cfg.setup().res_set_to_add_mod_list[0].res_list.resize(8); - for (auto& e : pucch_cfg.setup().res_set_to_add_mod_list[0].res_list) { - e = 0; - } - - // Make PUCCH resource set for >2 bit - pucch_cfg.setup().res_set_to_add_mod_list[1].pucch_res_set_id = 1; - pucch_cfg.setup().res_set_to_add_mod_list[1].res_list.resize(8); - for (auto& e : pucch_cfg.setup().res_set_to_add_mod_list[1].res_list) { - e = 1; - } - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pusch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // PUSCH config - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pusch_cfg_present = true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pusch_cfg.set_setup(); - auto& pusch_cfg_ded = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.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; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp_present = true; - - pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pucch_cfg(cell_group_cfg_pack); - pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pusch_cfg(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // UL config dedicated - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; - - pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp(cell_group_cfg_pack); - - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.first_active_ul_bwp_id_present = true; - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.first_active_ul_bwp_id = 0; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded_pdcch_serving_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - 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; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_sp_cell_cfg_ded(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // 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.first_active_dl_bwp_id_present = true; - - if (parent->cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0; - } else { - cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; - } - - pack_sp_cell_cfg_ded_ul_cfg(cell_group_cfg_pack); - pack_sp_cell_cfg_ded_init_dl_bwp(cell_group_cfg_pack); - - // Serving cell config (only to setup) - pack_sp_cell_cfg_ded_pdcch_serving_cell_cfg(cell_group_cfg_pack); - - // spCellConfig - if (fill_sp_cell_cfg_from_enb_cfg(parent->cfg, UE_PSCELL_CC_IDX, cell_group_cfg_pack.sp_cell_cfg) != SRSRAN_SUCCESS) { - parent->logger.error("Failed to pack spCellConfig for rnti=0x%x", rnti); - } - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common_phy_cell_group_cfg( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - cell_group_cfg_pack.phys_cell_group_cfg_present = true; - cell_group_cfg_pack.phys_cell_group_cfg.pdsch_harq_ack_codebook = - phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::dynamic_value; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp_pdsch_cfg_common( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // 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; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp_present = true; - auto& init_dl_bwp = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp; - - init_dl_bwp.generic_params.location_and_bw = 14025; - init_dl_bwp.generic_params.subcarrier_spacing = subcarrier_spacing_opts::khz15; - - pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp_pdsch_cfg_common(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // DL config - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; - - pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common_phy_cell_group_cfg(cell_group_cfg_pack); - pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp_pusch_cfg_common( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // 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_present = true; - pusch_cfg_common_pack.setup().p0_nominal_with_grant = -60; - - // 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 = -60; - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - 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; - - pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp_pusch_cfg_common(cell_group_cfg_pack); - - return SRSRAN_ERROR; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common( - asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // 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; - - pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - auto& pscell_cfg = parent->cfg.cell_list.at(UE_PSCELL_CC_IDX); - - if (pscell_cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD) { - cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); - } - - // DL config - pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common(cell_group_cfg_pack); - - // UL config - pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_recfg_with_sync(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - // Reconfig with Sync - cell_group_cfg_pack.cell_group_id = 1; // 0 identifies the MCG. Other values identify SCGs. - - 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.t304 = recfg_with_sync_s::t304_opts::ms1000; - - pack_recfg_with_sync_sp_cell_cfg_common(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::pack_secondary_cell_group_sp_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) -{ - cell_group_cfg_pack.sp_cell_cfg_present = true; - cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx_present = true; - cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx = 1; // Serving cell ID of a PSCell. The PCell of the MCG uses ID 0. - - pack_sp_cell_cfg_ded(cell_group_cfg_pack); - pack_recfg_with_sync(cell_group_cfg_pack); - - return SRSRAN_SUCCESS; -} - -// Helper for the RRC Reconfiguration sender to pack hard-coded config -int rrc_nr::ue::pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config) -{ - auto& cell_group_cfg_pack = cell_group_cfg; - - pack_secondary_cell_group_rlc_cfg(cell_group_cfg_pack); - pack_secondary_cell_group_mac_cfg(cell_group_cfg_pack); - pack_secondary_cell_group_sp_cell_cfg(cell_group_cfg_pack); - - // 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()); - - log_rrc_container(Tx, packed_secondary_cell_config, cell_group_cfg_pack, "nr-SecondaryCellGroupConfig-r15"); - - return SRSRAN_SUCCESS; -} - -// Packs a hard-coded RRC Reconfiguration with fixed params for all layers (for now) -int rrc_nr::ue::pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig) -{ - rrc_recfg_s reconfig; - reconfig.rrc_transaction_id = ((transaction_id++) % 4u); - rrc_recfg_ies_s& recfg_ies = reconfig.crit_exts.set_rrc_recfg(); - - // add secondary cell group config - recfg_ies.secondary_cell_group_present = true; - - if (pack_secondary_cell_group_cfg(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { - parent->logger.error("Failed to pack secondary cell group"); - return SRSRAN_ERROR; - } - - // now pack .. - packed_rrc_reconfig.resize(512); - asn1::bit_ref bref_pack(packed_rrc_reconfig.data(), packed_rrc_reconfig.size()); - if (reconfig.pack(bref_pack) != asn1::SRSASN_SUCCESS) { - parent->logger.error("Failed to pack RRC Reconfiguration"); - return SRSRAN_ERROR; - } - packed_rrc_reconfig.resize(bref_pack.distance_bytes()); - - return SRSRAN_SUCCESS; -} - -// Packs a hard-coded NR radio bearer config with fixed params for RLC/PDCP (for now) -int rrc_nr::ue::pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config) -{ - // set security config - auto& radio_bearer_cfg_pack = radio_bearer_cfg; - radio_bearer_cfg_pack.security_cfg_present = true; - auto& sec_cfg = radio_bearer_cfg_pack.security_cfg; - sec_cfg.key_to_use_present = true; - sec_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary; - sec_cfg.security_algorithm_cfg_present = true; - sec_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea0; - sec_cfg.security_algorithm_cfg.integrity_prot_algorithm_present = true; - sec_cfg.security_algorithm_cfg.integrity_prot_algorithm = integrity_prot_algorithm_opts::nia0; - - // pack it - packed_nr_bearer_config.resize(128); - asn1::bit_ref bref_pack(packed_nr_bearer_config.data(), packed_nr_bearer_config.size()); - if (radio_bearer_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) { - parent->logger.error("Failed to pack NR radio bearer config"); - return SRSRAN_ERROR; - } - - // resize to packed length - packed_nr_bearer_config.resize(bref_pack.distance_bytes()); - - log_rrc_container(Tx, packed_nr_bearer_config, radio_bearer_cfg_pack, "nr-RadioBearerConfig1-r15"); - - return SRSRAN_SUCCESS; -} - -int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti_, const sgnb_addition_req_params_t& req_params) -{ - // Add DRB1 to RLC and PDCP - if (add_drb() != SRSRAN_SUCCESS) { - parent->logger.error("Failed to configure DRB"); - parent->rrc_eutra->sgnb_addition_reject(eutra_rnti_); - return SRSRAN_ERROR; - } - - // provide hard-coded NR configs - rrc_eutra_interface_rrc_nr::sgnb_addition_ack_params_t ack_params = {}; - if (pack_rrc_reconfiguration(ack_params.nr_secondary_cell_group_cfg_r15) == SRSRAN_ERROR) { - parent->logger.error("Failed to pack RRC Reconfiguration. Sending SgNB addition reject."); - parent->rrc_eutra->sgnb_addition_reject(eutra_rnti_); - return SRSRAN_ERROR; - } - - if (pack_nr_radio_bearer_config(ack_params.nr_radio_bearer_cfg1_r15) == SRSRAN_ERROR) { - parent->logger.error("Failed to pack NR radio bearer config. Sending SgNB addition reject."); - parent->rrc_eutra->sgnb_addition_reject(eutra_rnti_); - return SRSRAN_ERROR; - } - - // send response to EUTRA - ack_params.nr_rnti = rnti; - ack_params.eps_bearer_id = req_params.eps_bearer_id; - parent->rrc_eutra->sgnb_addition_ack(eutra_rnti_, ack_params); - - // recognize RNTI as ENDC user - endc = true; - eutra_rnti = eutra_rnti_; - - return SRSRAN_SUCCESS; -} - -void rrc_nr::ue::crnti_ce_received() -{ - // Assume NSA mode active - if (endc) { - // send SgNB addition complete for ENDC users - parent->rrc_eutra->sgnb_addition_complete(eutra_rnti, rnti); - - // stop RX MSG3/MSG5 activity timer on MAC CE RNTI reception - set_activity_timeout(UE_INACTIVITY_TIMEOUT); - parent->logger.debug("Received MAC CE-RNTI for 0x%x - stopping MSG3/MSG5 timer, starting inactivity timer", rnti); - - // Add DRB1 to MAC - for (auto& drb : cell_group_cfg.rlc_bearer_to_add_mod_list) { - uecfg.ue_bearers[drb.lc_ch_id].direction = mac_lc_ch_cfg_t::BOTH; - uecfg.ue_bearers[drb.lc_ch_id].group = drb.mac_lc_ch_cfg.ul_specific_params.lc_ch_group; - } - - // Update UE phy params - srsran::make_pdsch_cfg_from_serv_cell(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded, &uecfg.phy_cfg.pdsch); - srsran::make_csi_cfg_from_serv_cell(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded, &uecfg.phy_cfg.csi); - srsran::make_phy_ssb_cfg(parent->cfg.cell_list[0].phy_cell.carrier, - cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common, - &uecfg.phy_cfg.ssb); - srsran::make_duplex_cfg_from_serv_cell(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common, - &uecfg.phy_cfg.duplex); - - parent->mac->ue_cfg(rnti, uecfg); - } -} - -/** - * @brief Set DRB configuration - * - * The function sets and configures all relavant fields for the DRB configuration (MAC, RLC, PDCP) in the - * cellGroupConfig and also adds the bearer to the local RLC and PDCP entities. - * - * @return int SRSRAN_SUCCESS on success - */ -int rrc_nr::ue::add_drb() -{ - // RLC for DRB1 (with fixed LCID) inside cell_group_cfg - auto& cell_group_cfg_pack = cell_group_cfg; - - 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_bearer = cell_group_cfg_pack.rlc_bearer_to_add_mod_list[0]; - rlc_bearer.lc_ch_id = drb1_lcid; - rlc_bearer.served_radio_bearer_present = true; - rlc_bearer.served_radio_bearer.set_drb_id(); - rlc_bearer.served_radio_bearer.drb_id() = 1; - rlc_bearer.rlc_cfg_present = true; - rlc_bearer.rlc_cfg.set_um_bi_dir(); - rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present = true; - rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_um_opts::size12; - rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present = true; - rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_um_opts::size12; - rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.t_reassembly = t_reassembly_opts::ms50; - - // add RLC bearer - srsran::rlc_config_t rlc_cfg; - /// NOTE, we need to pass the radio-bearer to the rlc_config - if (srsran::make_rlc_config_t(cell_group_cfg.rlc_bearer_to_add_mod_list[0].rlc_cfg, - rlc_bearer.served_radio_bearer.drb_id(), - &rlc_cfg) != SRSRAN_SUCCESS) { - parent->logger.error("Failed to build RLC config"); - return SRSRAN_ERROR; - } - parent->rlc->add_bearer(rnti, drb1_lcid, rlc_cfg); - - // MAC logical channel config - rlc_bearer.mac_lc_ch_cfg_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.prio = 11; - rlc_bearer.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_bearer.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_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group = 3; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id_present = true; - rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id = 0; - // TODO: add LC config to MAC - - // PDCP config goes into radio_bearer_cfg - auto& radio_bearer_cfg_pack = radio_bearer_cfg; - radio_bearer_cfg_pack.drb_to_add_mod_list_present = true; - radio_bearer_cfg_pack.drb_to_add_mod_list.resize(1); - - // configure fixed DRB1 - auto& drb_item = radio_bearer_cfg_pack.drb_to_add_mod_list[0]; - drb_item.drb_id = 1; - drb_item.cn_assoc_present = true; - drb_item.cn_assoc.set_eps_bearer_id() = 5; - drb_item.pdcp_cfg_present = true; - drb_item.pdcp_cfg.ciphering_disabled_present = true; - drb_item.pdcp_cfg.drb_present = true; - drb_item.pdcp_cfg.drb.pdcp_sn_size_dl_present = true; - drb_item.pdcp_cfg.drb.pdcp_sn_size_dl = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_dl_opts::len18bits; - drb_item.pdcp_cfg.drb.pdcp_sn_size_ul_present = true; - drb_item.pdcp_cfg.drb.pdcp_sn_size_ul = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_ul_opts::len18bits; - drb_item.pdcp_cfg.drb.discard_timer_present = true; - drb_item.pdcp_cfg.drb.discard_timer = asn1::rrc_nr::pdcp_cfg_s::drb_s_::discard_timer_opts::ms100; - drb_item.pdcp_cfg.drb.hdr_compress.set_not_used(); - drb_item.pdcp_cfg.t_reordering_present = true; - drb_item.pdcp_cfg.t_reordering = asn1::rrc_nr::pdcp_cfg_s::t_reordering_opts::ms0; - - // Add DRB1 to PDCP - srsran::pdcp_config_t pdcp_cnfg = srsran::make_drb_pdcp_config_t(drb_item.drb_id, false, drb_item.pdcp_cfg); - parent->pdcp->add_bearer(rnti, rlc_bearer.lc_ch_id, pdcp_cnfg); - - // Note: DRB1 is only activated in the MAC when the C-RNTI CE is received - - return SRSRAN_SUCCESS; -} - -void rrc_nr::ue::handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg) -{ - if (not parent->ngap->is_amf_connected()) { - parent->logger.error("MME isn't connected. Sending Connection Reject"); - const uint8_t max_wait_time_secs = 16; - send_rrc_reject(max_wait_time_secs); // See TS 38.331, RejectWaitTime - return; - } - - // TODO: Allocate PUCCH resources and reject if not available - - switch (msg.rrc_setup_request.ue_id.type().value) { - case asn1::rrc_nr::init_ue_id_c::types_opts::ng_minus5_g_s_tmsi_part1: - // TODO: communicate with NGAP - break; - case asn1::rrc_nr::init_ue_id_c::types_opts::random_value: - // TODO: communicate with NGAP - break; - default: - parent->logger.error("Unsupported RRCSetupRequest"); - } - - send_rrc_setup(); - set_activity_timeout(UE_INACTIVITY_TIMEOUT); -} - -/// TS 38.331, RRCReject message -void rrc_nr::ue::send_rrc_reject(uint8_t reject_wait_time_secs) -{ - dl_ccch_msg_s msg; - rrc_reject_ies_s& reject = msg.msg.set_c1().set_rrc_reject().crit_exts.set_rrc_reject(); - if (reject_wait_time_secs > 0) { - reject.wait_time_present = true; - reject.wait_time = reject_wait_time_secs; - } - send_dl_ccch(msg); -} - -/// TS 38.331, RRCSetup -void rrc_nr::ue::send_rrc_setup() -{ - dl_ccch_msg_s msg; - rrc_setup_s& setup = msg.msg.set_c1().set_rrc_setup(); - setup.rrc_transaction_id = (uint8_t)((transaction_id++) % 4); - rrc_setup_ies_s& setup_ies = setup.crit_exts.set_rrc_setup(); - - // Fill RRC Setup - // Note: See 5.3.5.6.3 - SRB addition/modification - setup_ies.radio_bearer_cfg.srb_to_add_mod_list_present = true; - setup_ies.radio_bearer_cfg.srb_to_add_mod_list.resize(1); - srb_to_add_mod_s& srb1 = setup_ies.radio_bearer_cfg.srb_to_add_mod_list[0]; - srb1.srb_id = 1; - - send_dl_ccch(msg); -} - -/// TS 38.331, RRCSetupComplete -void rrc_nr::ue::handle_rrc_setup_complete(const asn1::rrc_nr::rrc_setup_complete_s& msg) -{ - // TODO: handle RRCSetupComplete -} - -/** - * @brief Deactivate all Bearers (MAC logical channel) for this specific RNTI - * - * The function iterates over the bearers or MAC logical channels and deactivates them by setting each one to IDLE - */ -void rrc_nr::ue::deactivate_bearers() -{ - // Iterate over the bearers (MAC LC CH) and set each of them to IDLE - for (auto& ue_bearer : uecfg.ue_bearers) { - ue_bearer.direction = mac_lc_ch_cfg_t::IDLE; - } - - // No need to check the returned value, as the function ue_cfg will return SRSRAN_SUCCESS (it asserts if it fails) - parent->mac->ue_cfg(rnti, uecfg); -} - -template -void rrc_nr::ue::log_rrc_message(srsran::nr_srb srb, - const direction_t dir, - srsran::const_byte_span pdu, - const M& msg, - const char* msg_type) -{ - fmt::memory_buffer strbuf; - fmt::format_to(strbuf, "rnti=0x{:x}, {}", rnti, srsran::get_srb_name(srb)); - parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); -} - -template -void rrc_nr::ue::log_rrc_container(const direction_t dir, - srsran::const_byte_span pdu, - const M& msg, - const char* msg_type) -{ - fmt::memory_buffer strbuf; - fmt::format_to(strbuf, "rnti=0x{:x}, container", rnti); - parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); -} +template srsran::unique_byte_buffer_t rrc_nr::pack_into_pdu(const dl_ccch_msg_s& msg); } // namespace srsenb diff --git a/srsgnb/src/stack/rrc/rrc_nr_ue.cc b/srsgnb/src/stack/rrc/rrc_nr_ue.cc new file mode 100644 index 000000000..c7107f0d9 --- /dev/null +++ b/srsgnb/src/stack/rrc/rrc_nr_ue.cc @@ -0,0 +1,971 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsgnb/hdr/stack/rrc/rrc_nr_ue.h" +#include "srsgnb/hdr/stack/rrc/cell_asn1_config.h" +#include "srsran/asn1/rrc_nr_utils.h" +#include "srsran/common/string_helpers.h" + +using namespace asn1::rrc_nr; + +namespace srsenb { + +/******************************************************************************* + UE class + +Every function in UE class is called from a mutex environment thus does not + need extra protection. + *******************************************************************************/ +rrc_nr::ue::ue(rrc_nr* parent_, uint16_t rnti_, const sched_nr_ue_cfg_t& uecfg_, bool start_msg3_timer) : + parent(parent_), rnti(rnti_), uecfg(uecfg_) +{ + // Derive UE cfg from rrc_cfg_nr_t + uecfg.phy_cfg.pdcch = parent->cfg.cell_list[0].phy_cell.pdcch; + + // Set timer for MSG3_RX_TIMEOUT or UE_INACTIVITY_TIMEOUT + activity_timer = parent->task_sched.get_unique_timer(); + start_msg3_timer ? set_activity_timeout(MSG3_RX_TIMEOUT) : set_activity_timeout(MSG5_RX_TIMEOUT); +} + +rrc_nr::ue::~ue() {} + +void rrc_nr::ue::set_activity_timeout(activity_timeout_type_t type) +{ + uint32_t deadline_ms = 0; + + switch (type) { + case MSG3_RX_TIMEOUT: + // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 100ms + deadline_ms = 100; + break; + case MSG5_RX_TIMEOUT: + // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 1s + deadline_ms = 5000; + break; + case UE_INACTIVITY_TIMEOUT: + // TODO: Retrieve the parameters from somewhere(RRC?) - Currently hardcoded to 5s + deadline_ms = 10000; + break; + default: + parent->logger.error("Unknown timeout type %d", type); + return; + } + + activity_timer.set(deadline_ms, [this, type](uint32_t tid) { activity_timer_expired(type); }); + parent->logger.debug("Setting timer for %s for rnti=0x%x to %dms", to_string(type).c_str(), rnti, deadline_ms); + + set_activity(); +} + +void rrc_nr::ue::set_activity(bool enabled) +{ + if (not enabled) { + if (activity_timer.is_running()) { + parent->logger.debug("Inactivity timer interrupted for rnti=0x%x", rnti); + } + activity_timer.stop(); + return; + } + + // re-start activity timer with current timeout value + activity_timer.run(); + parent->logger.debug("Activity registered for rnti=0x%x (timeout_value=%dms)", rnti, activity_timer.duration()); +} + +void rrc_nr::ue::activity_timer_expired(const activity_timeout_type_t type) +{ + parent->logger.info("Activity timer for rnti=0x%x expired after %d ms", rnti, activity_timer.time_elapsed()); + + switch (type) { + case MSG5_RX_TIMEOUT: + case UE_INACTIVITY_TIMEOUT: + state = rrc_nr_state_t::RRC_INACTIVE; + parent->rrc_eutra->sgnb_inactivity_timeout(eutra_rnti); + break; + case MSG3_RX_TIMEOUT: { + // MSG3 timeout, no need to notify NGAP or LTE stack. Just remove UE + state = rrc_nr_state_t::RRC_IDLE; + uint32_t rnti_to_rem = rnti; + parent->task_sched.defer_task([this, rnti_to_rem]() { parent->rem_user(rnti_to_rem); }); + break; + } + default: + // Unhandled activity timeout, just remove UE and log an error + parent->rem_user(rnti); + parent->logger.error( + "Unhandled reason for activity timer expiration. rnti=0x%x, cause %d", rnti, static_cast(type)); + } +} + +std::string rrc_nr::ue::to_string(const activity_timeout_type_t& type) +{ + constexpr static const char* options[] = {"Msg3 reception", "UE inactivity", "Msg5 reception"}; + return srsran::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type); +} + +void rrc_nr::ue::send_dl_ccch(const dl_ccch_msg_s& dl_ccch_msg) +{ + // Allocate a new PDU buffer, pack the message and send to PDCP + srsran::unique_byte_buffer_t pdu = parent->pack_into_pdu(dl_ccch_msg); + if (pdu == nullptr) { + parent->logger.error("Failed to send DL-CCCH"); + return; + } + fmt::memory_buffer fmtbuf; + fmt::format_to(fmtbuf, "DL-CCCH.{}", dl_ccch_msg.msg.c1().type().to_string()); + log_rrc_message(srsran::nr_srb::srb0, Tx, *pdu.get(), dl_ccch_msg, srsran::to_c_str(fmtbuf)); + parent->rlc->write_sdu(rnti, srsran::srb_to_lcid(srsran::nr_srb::srb0), std::move(pdu)); +} + +int rrc_nr::ue::pack_secondary_cell_group_rlc_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // 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); + auto& rlc_bearer = cell_group_cfg_pack.rlc_bearer_to_add_mod_list[0]; + rlc_bearer.lc_ch_id = drb1_lcid; + rlc_bearer.served_radio_bearer_present = true; + rlc_bearer.served_radio_bearer.set_drb_id(); + rlc_bearer.served_radio_bearer.drb_id() = 1; + rlc_bearer.rlc_cfg_present = true; + rlc_bearer.rlc_cfg.set_um_bi_dir(); + rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present = true; + rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present = true; + rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.t_reassembly = t_reassembly_opts::ms50; + + // MAC logical channel config + rlc_bearer.mac_lc_ch_cfg_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.prio = 11; + rlc_bearer.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_bearer.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_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group = 6; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id = 0; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_secondary_cell_group_mac_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // mac-CellGroup-Config for BSR and SR + 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 + mac_cell_group.tag_cfg_present = false; + mac_cell_group.tag_cfg.tag_to_add_mod_list_present = true; + mac_cell_group.tag_cfg.tag_to_add_mod_list.resize(1); + mac_cell_group.tag_cfg.tag_to_add_mod_list[0].tag_id = 0; + mac_cell_group.tag_cfg.tag_to_add_mod_list[0].time_align_timer = time_align_timer_opts::infinity; + + mac_cell_group.phr_cfg_present = false; + mac_cell_group.phr_cfg.set_setup(); + mac_cell_group.phr_cfg.setup().phr_periodic_timer = asn1::rrc_nr::phr_cfg_s::phr_periodic_timer_opts::sf500; + mac_cell_group.phr_cfg.setup().phr_prohibit_timer = asn1::rrc_nr::phr_cfg_s::phr_prohibit_timer_opts::sf200; + mac_cell_group.phr_cfg.setup().phr_tx_pwr_factor_change = asn1::rrc_nr::phr_cfg_s::phr_tx_pwr_factor_change_opts::db3; + mac_cell_group.phr_cfg.setup().multiple_phr = true; + mac_cell_group.phr_cfg.setup().dummy = false; + mac_cell_group.phr_cfg.setup().phr_type2_other_cell = false; + mac_cell_group.phr_cfg.setup().phr_mode_other_cg = asn1::rrc_nr::phr_cfg_s::phr_mode_other_cg_opts::real; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_init_dl_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp_present = true; + + pack_sp_cell_cfg_ded_init_dl_bwp_pdsch_cfg(cell_group_cfg_pack); + pack_sp_cell_cfg_ded_init_dl_bwp_radio_link_monitoring(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_init_dl_bwp_radio_link_monitoring( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.radio_link_monitoring_cfg_present = true; + auto& radio_link_monitoring = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.init_dl_bwp.radio_link_monitoring_cfg; + radio_link_monitoring.set_setup().fail_detection_res_to_add_mod_list_present = true; + + // add resource to detect RLF + radio_link_monitoring.set_setup().fail_detection_res_to_add_mod_list.resize(1); + auto& fail_detec_res_elem = radio_link_monitoring.set_setup().fail_detection_res_to_add_mod_list[0]; + fail_detec_res_elem.radio_link_monitoring_rs_id = 0; + fail_detec_res_elem.purpose = asn1::rrc_nr::radio_link_monitoring_rs_s::purpose_opts::rlf; + fail_detec_res_elem.detection_res.set_ssb_idx() = 0; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_init_dl_bwp_pdsch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + 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 = false; + 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 = false; + 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); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pucch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // PUCCH + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pucch_cfg_present = true; + auto& pucch_cfg = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pucch_cfg; + + pucch_cfg.set_setup(); + pucch_cfg.setup().format2_present = true; + pucch_cfg.setup().format2.set_setup(); + pucch_cfg.setup().format2.setup().max_code_rate_present = true; + pucch_cfg.setup().format2.setup().max_code_rate = pucch_max_code_rate_opts::zero_dot25; + + // SR resources + pucch_cfg.setup().sched_request_res_to_add_mod_list_present = true; + pucch_cfg.setup().sched_request_res_to_add_mod_list.resize(1); + auto& sr_res1 = 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() = 8; + sr_res1.res_present = true; + sr_res1.res = 2; // PUCCH resource for SR + + // DL data + pucch_cfg.setup().dl_data_to_ul_ack_present = true; + + if (parent->cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { + pucch_cfg.setup().dl_data_to_ul_ack.resize(1); + pucch_cfg.setup().dl_data_to_ul_ack[0] = 4; + } else { + pucch_cfg.setup().dl_data_to_ul_ack.resize(6); + pucch_cfg.setup().dl_data_to_ul_ack[0] = 6; + pucch_cfg.setup().dl_data_to_ul_ack[1] = 5; + pucch_cfg.setup().dl_data_to_ul_ack[2] = 4; + pucch_cfg.setup().dl_data_to_ul_ack[3] = 4; + pucch_cfg.setup().dl_data_to_ul_ack[4] = 4; + pucch_cfg.setup().dl_data_to_ul_ack[5] = 4; + } + + // PUCCH Resource for format 1 + srsran_pucch_nr_resource_t resource_small = {}; + resource_small.starting_prb = 0; + resource_small.format = SRSRAN_PUCCH_NR_FORMAT_1; + resource_small.initial_cyclic_shift = 0; + resource_small.nof_symbols = 14; + resource_small.start_symbol_idx = 0; + resource_small.time_domain_occ = 0; + + // PUCCH Resource for format 2 + srsran_pucch_nr_resource_t resource_big = {}; + resource_big.starting_prb = 51; + resource_big.format = SRSRAN_PUCCH_NR_FORMAT_2; + resource_big.nof_prb = 1; + resource_big.nof_symbols = 2; + resource_big.start_symbol_idx = 12; + + // Resource for SR + srsran_pucch_nr_resource_t resource_sr = {}; + resource_sr.starting_prb = 51; + resource_sr.format = SRSRAN_PUCCH_NR_FORMAT_1; + resource_sr.initial_cyclic_shift = 0; + resource_sr.nof_symbols = 14; + resource_sr.start_symbol_idx = 0; + resource_sr.time_domain_occ = 0; + + // Make 3 possible resources + pucch_cfg.setup().res_to_add_mod_list_present = true; + pucch_cfg.setup().res_to_add_mod_list.resize(3); + if (not srsran::make_phy_res_config(resource_small, pucch_cfg.setup().res_to_add_mod_list[0], 0)) { + parent->logger.warning("Failed to create 1-2 bit NR PUCCH resource"); + } + if (not srsran::make_phy_res_config(resource_big, pucch_cfg.setup().res_to_add_mod_list[1], 1)) { + parent->logger.warning("Failed to create >2 bit NR PUCCH resource"); + } + if (not srsran::make_phy_res_config(resource_sr, pucch_cfg.setup().res_to_add_mod_list[2], 2)) { + parent->logger.warning("Failed to create SR NR PUCCH resource"); + } + + // Make 2 PUCCH resource sets + pucch_cfg.setup().res_set_to_add_mod_list_present = true; + pucch_cfg.setup().res_set_to_add_mod_list.resize(2); + + // Make PUCCH resource set for 1-2 bit + pucch_cfg.setup().res_set_to_add_mod_list[0].pucch_res_set_id = 0; + pucch_cfg.setup().res_set_to_add_mod_list[0].res_list.resize(8); + for (auto& e : pucch_cfg.setup().res_set_to_add_mod_list[0].res_list) { + e = 0; + } + + // Make PUCCH resource set for >2 bit + pucch_cfg.setup().res_set_to_add_mod_list[1].pucch_res_set_id = 1; + pucch_cfg.setup().res_set_to_add_mod_list[1].res_list.resize(8); + for (auto& e : pucch_cfg.setup().res_set_to_add_mod_list[1].res_list) { + e = 1; + } + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pusch_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // PUSCH config + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pusch_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp.pusch_cfg.set_setup(); + auto& pusch_cfg_ded = cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.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; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.init_ul_bwp_present = true; + + pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pucch_cfg(cell_group_cfg_pack); + pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp_pusch_cfg(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_ul_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // UL config dedicated + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg_present = true; + + pack_sp_cell_cfg_ded_ul_cfg_init_ul_bwp(cell_group_cfg_pack); + + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.first_active_ul_bwp_id_present = true; + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.ul_cfg.first_active_ul_bwp_id = 0; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded_pdcch_serving_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + 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; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_sp_cell_cfg_ded(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // 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.first_active_dl_bwp_id_present = true; + + if (parent->cfg.cell_list[0].duplex_mode == SRSRAN_DUPLEX_MODE_FDD) { + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 0; + } else { + cell_group_cfg_pack.sp_cell_cfg.sp_cell_cfg_ded.first_active_dl_bwp_id = 1; + } + + pack_sp_cell_cfg_ded_ul_cfg(cell_group_cfg_pack); + pack_sp_cell_cfg_ded_init_dl_bwp(cell_group_cfg_pack); + + // Serving cell config (only to setup) + pack_sp_cell_cfg_ded_pdcch_serving_cell_cfg(cell_group_cfg_pack); + + // spCellConfig + if (fill_sp_cell_cfg_from_enb_cfg(parent->cfg, UE_PSCELL_CC_IDX, cell_group_cfg_pack.sp_cell_cfg) != SRSRAN_SUCCESS) { + parent->logger.error("Failed to pack spCellConfig for rnti=0x%x", rnti); + } + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common_phy_cell_group_cfg( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + cell_group_cfg_pack.phys_cell_group_cfg_present = true; + cell_group_cfg_pack.phys_cell_group_cfg.pdsch_harq_ack_codebook = + phys_cell_group_cfg_s::pdsch_harq_ack_codebook_opts::dynamic_value; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp_pdsch_cfg_common( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // 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; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp_present = true; + auto& init_dl_bwp = cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common.init_dl_bwp; + + init_dl_bwp.generic_params.location_and_bw = 14025; + init_dl_bwp.generic_params.subcarrier_spacing = subcarrier_spacing_opts::khz15; + + pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp_pdsch_cfg_common(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // DL config + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common.dl_cfg_common_present = true; + + pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common_phy_cell_group_cfg(cell_group_cfg_pack); + pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_init_dl_bwp(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp_pusch_cfg_common( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // 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_present = true; + pusch_cfg_common_pack.setup().p0_nominal_with_grant = -60; + + // 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 = -60; + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + 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; + + pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp_pusch_cfg_common(cell_group_cfg_pack); + + return SRSRAN_ERROR; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common( + asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // 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; + + pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common_init_ul_bwp(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync_sp_cell_cfg_common(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + auto& pscell_cfg = parent->cfg.cell_list.at(UE_PSCELL_CC_IDX); + + if (pscell_cfg.duplex_mode == SRSRAN_DUPLEX_MODE_TDD) { + cell_group_cfg_pack.sp_cell_cfg.recfg_with_sync.smtc.release(); + } + + // DL config + pack_recfg_with_sync_sp_cell_cfg_common_dl_cfg_common(cell_group_cfg_pack); + + // UL config + pack_recfg_with_sync_sp_cell_cfg_common_ul_cfg_common(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_recfg_with_sync(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + // Reconfig with Sync + cell_group_cfg_pack.cell_group_id = 1; // 0 identifies the MCG. Other values identify SCGs. + + 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.t304 = recfg_with_sync_s::t304_opts::ms1000; + + pack_recfg_with_sync_sp_cell_cfg_common(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::pack_secondary_cell_group_sp_cell_cfg(asn1::rrc_nr::cell_group_cfg_s& cell_group_cfg_pack) +{ + cell_group_cfg_pack.sp_cell_cfg_present = true; + cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx_present = true; + cell_group_cfg_pack.sp_cell_cfg.serv_cell_idx = 1; // Serving cell ID of a PSCell. The PCell of the MCG uses ID 0. + + pack_sp_cell_cfg_ded(cell_group_cfg_pack); + pack_recfg_with_sync(cell_group_cfg_pack); + + return SRSRAN_SUCCESS; +} + +// Helper for the RRC Reconfiguration sender to pack hard-coded config +int rrc_nr::ue::pack_secondary_cell_group_cfg(asn1::dyn_octstring& packed_secondary_cell_config) +{ + auto& cell_group_cfg_pack = cell_group_cfg; + + pack_secondary_cell_group_rlc_cfg(cell_group_cfg_pack); + pack_secondary_cell_group_mac_cfg(cell_group_cfg_pack); + pack_secondary_cell_group_sp_cell_cfg(cell_group_cfg_pack); + + // 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()); + + log_rrc_container(Tx, packed_secondary_cell_config, cell_group_cfg_pack, "nr-SecondaryCellGroupConfig-r15"); + + return SRSRAN_SUCCESS; +} + +// Packs a hard-coded RRC Reconfiguration with fixed params for all layers (for now) +int rrc_nr::ue::pack_rrc_reconfiguration(asn1::dyn_octstring& packed_rrc_reconfig) +{ + rrc_recfg_s reconfig; + reconfig.rrc_transaction_id = ((transaction_id++) % 4u); + rrc_recfg_ies_s& recfg_ies = reconfig.crit_exts.set_rrc_recfg(); + + // add secondary cell group config + recfg_ies.secondary_cell_group_present = true; + + if (pack_secondary_cell_group_cfg(recfg_ies.secondary_cell_group) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack secondary cell group"); + return SRSRAN_ERROR; + } + + // now pack .. + packed_rrc_reconfig.resize(512); + asn1::bit_ref bref_pack(packed_rrc_reconfig.data(), packed_rrc_reconfig.size()); + if (reconfig.pack(bref_pack) != asn1::SRSASN_SUCCESS) { + parent->logger.error("Failed to pack RRC Reconfiguration"); + return SRSRAN_ERROR; + } + packed_rrc_reconfig.resize(bref_pack.distance_bytes()); + + return SRSRAN_SUCCESS; +} + +// Packs a hard-coded NR radio bearer config with fixed params for RLC/PDCP (for now) +int rrc_nr::ue::pack_nr_radio_bearer_config(asn1::dyn_octstring& packed_nr_bearer_config) +{ + // set security config + auto& radio_bearer_cfg_pack = radio_bearer_cfg; + radio_bearer_cfg_pack.security_cfg_present = true; + auto& sec_cfg = radio_bearer_cfg_pack.security_cfg; + sec_cfg.key_to_use_present = true; + sec_cfg.key_to_use = asn1::rrc_nr::security_cfg_s::key_to_use_opts::secondary; + sec_cfg.security_algorithm_cfg_present = true; + sec_cfg.security_algorithm_cfg.ciphering_algorithm = ciphering_algorithm_opts::nea0; + sec_cfg.security_algorithm_cfg.integrity_prot_algorithm_present = true; + sec_cfg.security_algorithm_cfg.integrity_prot_algorithm = integrity_prot_algorithm_opts::nia0; + + // pack it + packed_nr_bearer_config.resize(128); + asn1::bit_ref bref_pack(packed_nr_bearer_config.data(), packed_nr_bearer_config.size()); + if (radio_bearer_cfg_pack.pack(bref_pack) != asn1::SRSASN_SUCCESS) { + parent->logger.error("Failed to pack NR radio bearer config"); + return SRSRAN_ERROR; + } + + // resize to packed length + packed_nr_bearer_config.resize(bref_pack.distance_bytes()); + + log_rrc_container(Tx, packed_nr_bearer_config, radio_bearer_cfg_pack, "nr-RadioBearerConfig1-r15"); + + return SRSRAN_SUCCESS; +} + +int rrc_nr::ue::handle_sgnb_addition_request(uint16_t eutra_rnti_, const sgnb_addition_req_params_t& req_params) +{ + // Add DRB1 to RLC and PDCP + if (add_drb() != SRSRAN_SUCCESS) { + parent->logger.error("Failed to configure DRB"); + parent->rrc_eutra->sgnb_addition_reject(eutra_rnti_); + return SRSRAN_ERROR; + } + + // provide hard-coded NR configs + rrc_eutra_interface_rrc_nr::sgnb_addition_ack_params_t ack_params = {}; + if (pack_rrc_reconfiguration(ack_params.nr_secondary_cell_group_cfg_r15) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack RRC Reconfiguration. Sending SgNB addition reject."); + parent->rrc_eutra->sgnb_addition_reject(eutra_rnti_); + return SRSRAN_ERROR; + } + + if (pack_nr_radio_bearer_config(ack_params.nr_radio_bearer_cfg1_r15) == SRSRAN_ERROR) { + parent->logger.error("Failed to pack NR radio bearer config. Sending SgNB addition reject."); + parent->rrc_eutra->sgnb_addition_reject(eutra_rnti_); + return SRSRAN_ERROR; + } + + // send response to EUTRA + ack_params.nr_rnti = rnti; + ack_params.eps_bearer_id = req_params.eps_bearer_id; + parent->rrc_eutra->sgnb_addition_ack(eutra_rnti_, ack_params); + + // recognize RNTI as ENDC user + endc = true; + eutra_rnti = eutra_rnti_; + + return SRSRAN_SUCCESS; +} + +void rrc_nr::ue::crnti_ce_received() +{ + // Assume NSA mode active + if (endc) { + // send SgNB addition complete for ENDC users + parent->rrc_eutra->sgnb_addition_complete(eutra_rnti, rnti); + + // stop RX MSG3/MSG5 activity timer on MAC CE RNTI reception + set_activity_timeout(UE_INACTIVITY_TIMEOUT); + parent->logger.debug("Received MAC CE-RNTI for 0x%x - stopping MSG3/MSG5 timer, starting inactivity timer", rnti); + + // Add DRB1 to MAC + for (auto& drb : cell_group_cfg.rlc_bearer_to_add_mod_list) { + uecfg.ue_bearers[drb.lc_ch_id].direction = mac_lc_ch_cfg_t::BOTH; + uecfg.ue_bearers[drb.lc_ch_id].group = drb.mac_lc_ch_cfg.ul_specific_params.lc_ch_group; + } + + // Update UE phy params + srsran::make_pdsch_cfg_from_serv_cell(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded, &uecfg.phy_cfg.pdsch); + srsran::make_csi_cfg_from_serv_cell(cell_group_cfg.sp_cell_cfg.sp_cell_cfg_ded, &uecfg.phy_cfg.csi); + srsran::make_phy_ssb_cfg(parent->cfg.cell_list[0].phy_cell.carrier, + cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common, + &uecfg.phy_cfg.ssb); + srsran::make_duplex_cfg_from_serv_cell(cell_group_cfg.sp_cell_cfg.recfg_with_sync.sp_cell_cfg_common, + &uecfg.phy_cfg.duplex); + + parent->mac->ue_cfg(rnti, uecfg); + } +} + +/** + * @brief Set DRB configuration + * + * The function sets and configures all relavant fields for the DRB configuration (MAC, RLC, PDCP) in the + * cellGroupConfig and also adds the bearer to the local RLC and PDCP entities. + * + * @return int SRSRAN_SUCCESS on success + */ +int rrc_nr::ue::add_drb() +{ + // RLC for DRB1 (with fixed LCID) inside cell_group_cfg + auto& cell_group_cfg_pack = cell_group_cfg; + + 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_bearer = cell_group_cfg_pack.rlc_bearer_to_add_mod_list[0]; + rlc_bearer.lc_ch_id = drb1_lcid; + rlc_bearer.served_radio_bearer_present = true; + rlc_bearer.served_radio_bearer.set_drb_id(); + rlc_bearer.served_radio_bearer.drb_id() = 1; + rlc_bearer.rlc_cfg_present = true; + rlc_bearer.rlc_cfg.set_um_bi_dir(); + rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len_present = true; + rlc_bearer.rlc_cfg.um_bi_dir().ul_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len_present = true; + rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.sn_field_len = sn_field_len_um_opts::size12; + rlc_bearer.rlc_cfg.um_bi_dir().dl_um_rlc.t_reassembly = t_reassembly_opts::ms50; + + // add RLC bearer + srsran::rlc_config_t rlc_cfg; + /// NOTE, we need to pass the radio-bearer to the rlc_config + if (srsran::make_rlc_config_t(cell_group_cfg.rlc_bearer_to_add_mod_list[0].rlc_cfg, + rlc_bearer.served_radio_bearer.drb_id(), + &rlc_cfg) != SRSRAN_SUCCESS) { + parent->logger.error("Failed to build RLC config"); + return SRSRAN_ERROR; + } + parent->rlc->add_bearer(rnti, drb1_lcid, rlc_cfg); + + // MAC logical channel config + rlc_bearer.mac_lc_ch_cfg_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.prio = 11; + rlc_bearer.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_bearer.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_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.lc_ch_group = 3; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id_present = true; + rlc_bearer.mac_lc_ch_cfg.ul_specific_params.sched_request_id = 0; + // TODO: add LC config to MAC + + // PDCP config goes into radio_bearer_cfg + auto& radio_bearer_cfg_pack = radio_bearer_cfg; + radio_bearer_cfg_pack.drb_to_add_mod_list_present = true; + radio_bearer_cfg_pack.drb_to_add_mod_list.resize(1); + + // configure fixed DRB1 + auto& drb_item = radio_bearer_cfg_pack.drb_to_add_mod_list[0]; + drb_item.drb_id = 1; + drb_item.cn_assoc_present = true; + drb_item.cn_assoc.set_eps_bearer_id() = 5; + drb_item.pdcp_cfg_present = true; + drb_item.pdcp_cfg.ciphering_disabled_present = true; + drb_item.pdcp_cfg.drb_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_dl_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_dl = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_dl_opts::len18bits; + drb_item.pdcp_cfg.drb.pdcp_sn_size_ul_present = true; + drb_item.pdcp_cfg.drb.pdcp_sn_size_ul = asn1::rrc_nr::pdcp_cfg_s::drb_s_::pdcp_sn_size_ul_opts::len18bits; + drb_item.pdcp_cfg.drb.discard_timer_present = true; + drb_item.pdcp_cfg.drb.discard_timer = asn1::rrc_nr::pdcp_cfg_s::drb_s_::discard_timer_opts::ms100; + drb_item.pdcp_cfg.drb.hdr_compress.set_not_used(); + drb_item.pdcp_cfg.t_reordering_present = true; + drb_item.pdcp_cfg.t_reordering = asn1::rrc_nr::pdcp_cfg_s::t_reordering_opts::ms0; + + // Add DRB1 to PDCP + srsran::pdcp_config_t pdcp_cnfg = srsran::make_drb_pdcp_config_t(drb_item.drb_id, false, drb_item.pdcp_cfg); + parent->pdcp->add_bearer(rnti, rlc_bearer.lc_ch_id, pdcp_cnfg); + + // Note: DRB1 is only activated in the MAC when the C-RNTI CE is received + + return SRSRAN_SUCCESS; +} + +void rrc_nr::ue::handle_rrc_setup_request(const asn1::rrc_nr::rrc_setup_request_s& msg) +{ + if (not parent->ngap->is_amf_connected()) { + parent->logger.error("MME isn't connected. Sending Connection Reject"); + const uint8_t max_wait_time_secs = 16; + send_rrc_reject(max_wait_time_secs); // See TS 38.331, RejectWaitTime + return; + } + + // TODO: Allocate PUCCH resources and reject if not available + + switch (msg.rrc_setup_request.ue_id.type().value) { + case asn1::rrc_nr::init_ue_id_c::types_opts::ng_minus5_g_s_tmsi_part1: + // TODO: communicate with NGAP + break; + case asn1::rrc_nr::init_ue_id_c::types_opts::random_value: + // TODO: communicate with NGAP + break; + default: + parent->logger.error("Unsupported RRCSetupRequest"); + } + + send_rrc_setup(); + set_activity_timeout(UE_INACTIVITY_TIMEOUT); +} + +/// TS 38.331, RRCReject message +void rrc_nr::ue::send_rrc_reject(uint8_t reject_wait_time_secs) +{ + dl_ccch_msg_s msg; + rrc_reject_ies_s& reject = msg.msg.set_c1().set_rrc_reject().crit_exts.set_rrc_reject(); + if (reject_wait_time_secs > 0) { + reject.wait_time_present = true; + reject.wait_time = reject_wait_time_secs; + } + send_dl_ccch(msg); +} + +/// TS 38.331, RRCSetup +void rrc_nr::ue::send_rrc_setup() +{ + dl_ccch_msg_s msg; + rrc_setup_s& setup = msg.msg.set_c1().set_rrc_setup(); + setup.rrc_transaction_id = (uint8_t)((transaction_id++) % 4); + rrc_setup_ies_s& setup_ies = setup.crit_exts.set_rrc_setup(); + + // Fill RRC Setup + // Note: See 5.3.5.6.3 - SRB addition/modification + setup_ies.radio_bearer_cfg.srb_to_add_mod_list_present = true; + setup_ies.radio_bearer_cfg.srb_to_add_mod_list.resize(1); + srb_to_add_mod_s& srb1 = setup_ies.radio_bearer_cfg.srb_to_add_mod_list[0]; + srb1.srb_id = 1; + + send_dl_ccch(msg); +} + +/// TS 38.331, RRCSetupComplete +void rrc_nr::ue::handle_rrc_setup_complete(const asn1::rrc_nr::rrc_setup_complete_s& msg) +{ + // TODO: handle RRCSetupComplete +} + +/** + * @brief Deactivate all Bearers (MAC logical channel) for this specific RNTI + * + * The function iterates over the bearers or MAC logical channels and deactivates them by setting each one to IDLE + */ +void rrc_nr::ue::deactivate_bearers() +{ + // Iterate over the bearers (MAC LC CH) and set each of them to IDLE + for (auto& ue_bearer : uecfg.ue_bearers) { + ue_bearer.direction = mac_lc_ch_cfg_t::IDLE; + } + + // No need to check the returned value, as the function ue_cfg will return SRSRAN_SUCCESS (it asserts if it fails) + parent->mac->ue_cfg(rnti, uecfg); +} + +template +void rrc_nr::ue::log_rrc_message(srsran::nr_srb srb, + const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type) +{ + fmt::memory_buffer strbuf; + fmt::format_to(strbuf, "rnti=0x{:x}, {}", rnti, srsran::get_srb_name(srb)); + parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); +} + +template +void rrc_nr::ue::log_rrc_container(const direction_t dir, + srsran::const_byte_span pdu, + const M& msg, + const char* msg_type) +{ + fmt::memory_buffer strbuf; + fmt::format_to(strbuf, "rnti=0x{:x}, container", rnti); + parent->log_rrc_message(srsran::to_c_str(strbuf), Tx, pdu, msg, msg_type); +} + +} // namespace srsenb \ No newline at end of file