diff --git a/lib/include/srsran/interfaces/enb_interfaces.h b/lib/include/srsran/interfaces/enb_interfaces.h index b8e831203..1e7d3cd4c 100644 --- a/lib/include/srsran/interfaces/enb_interfaces.h +++ b/lib/include/srsran/interfaces/enb_interfaces.h @@ -14,6 +14,8 @@ #include "srsran/common/interfaces_common.h" #include "srsran/srsran.h" +#include "srsran/interfaces/enb_rrc_interfaces.h" + #ifndef SRSRAN_ENB_INTERFACES_H #define SRSRAN_ENB_INTERFACES_H @@ -27,8 +29,6 @@ public: virtual void remove_eps_bearers(uint16_t rnti) = 0; }; -class stack_interface_phy_lte; - } // namespace srsenb #endif // SRSRAN_ENB_INTERFACES_H diff --git a/lib/include/srsran/interfaces/enb_mac_interfaces.h b/lib/include/srsran/interfaces/enb_mac_interfaces.h index ba13e75dc..6ee722a1d 100644 --- a/lib/include/srsran/interfaces/enb_mac_interfaces.h +++ b/lib/include/srsran/interfaces/enb_mac_interfaces.h @@ -258,8 +258,6 @@ public: // Combined interface for PHY to access stack (MAC and RRC) class stack_interface_phy_lte : public mac_interface_phy_lte { -public: - virtual void tti_clock() = 0; }; } // namespace srsenb diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index e1ac72d33..e8edb0499 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -120,67 +120,6 @@ public: virtual void notify_pdcp_integrity_error(uint16_t rnti, uint32_t lcid) = 0; }; -// RRC interfaces for NSA operation - -/// X2AP inspired interface to allow EUTRA RRC to call NR RRC -class rrc_nr_interface_rrc -{ -public: - struct sgnb_addition_req_params_t { - uint32_t eps_bearer_id; - // add configuration check - // E-RAB Parameters, Tunnel address (IP address, TEID) - // QCI, security, etc - }; - - /// Request addition of NR carrier for UE - virtual int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) = 0; - - /// Provide information whether the requested configuration was applied successfully by the UE - virtual int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) = 0; -}; - -/// X2AP inspired interface for response from NR RRC to EUTRA RRC -class rrc_eutra_interface_rrc_nr -{ -public: - /** - * @brief List of parameters included in the SgNB addition Ack message - * @param nr_secondary_cell_group_cfg_r15 Encoded part of the RRC Reconfiguration - * @param nr_radio_bearer_cfg1_r15 Encoded part of the RRC Reconfiguration - * @param eps_bearer_id ID of the transfered bearer - */ - struct sgnb_addition_ack_params_t { - uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // RNTI that was assigned to the UE - asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; - asn1::dyn_octstring nr_radio_bearer_cfg1_r15; - uint32_t eps_bearer_id = 0; // (list of) successfully transfered EPS bearers - }; - - /** - * @brief Signal successful addition of UE - * - * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - * @param params Parameter list - */ - virtual void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) = 0; - - /** - * @brief Signal unsuccessful SgNB addition - * - * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - */ - virtual void sgnb_addition_reject(uint16_t eutra_rnti) = 0; - - /** - * @brief Signal completion of SgNB addition after UE (with new NR identity) has attached - * - * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition - * @param nr_rnti The RNTI that has been assigned to the UE on the SgNB - */ - virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; -}; - } // namespace srsenb #endif // SRSRAN_ENB_RRC_INTERFACES_H diff --git a/lib/include/srsran/interfaces/enb_time_interface.h b/lib/include/srsran/interfaces/enb_time_interface.h new file mode 100644 index 000000000..e1ef79d90 --- /dev/null +++ b/lib/include/srsran/interfaces/enb_time_interface.h @@ -0,0 +1,31 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#ifndef SRSRAN_ENB_TIME_INTERFACE_H +#define SRSRAN_ENB_TIME_INTERFACE_H + +namespace srsenb { + +// RAT-agnostic interface to provide timing information to upper layers +class enb_time_interface +{ +public: + /** + * @brief Called for every tick (currently every ms) + * + */ + virtual void tti_clock() = 0; +}; + +} // namespace srsenb + +#endif // SRSRAN_ENB_TIME_INTERFACE_H diff --git a/lib/include/srsran/interfaces/enb_x2_interfaces.h b/lib/include/srsran/interfaces/enb_x2_interfaces.h new file mode 100644 index 000000000..a5b503ee3 --- /dev/null +++ b/lib/include/srsran/interfaces/enb_x2_interfaces.h @@ -0,0 +1,101 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +#include "srsran/interfaces/enb_pdcp_interfaces.h" +#include "srsran/interfaces/enb_rrc_interface_types.h" + +#ifndef SRSRAN_ENB_X2_INTERFACES_H +#define SRSRAN_ENB_X2_INTERFACES_H + +namespace srsenb { + +/** + * @brief Set of X2AP inspired interfaces to support 5G NSA + * + */ + +/// X2AP inspired interface to allow EUTRA RRC to call NR RRC +class rrc_nr_interface_rrc +{ +public: + struct sgnb_addition_req_params_t { + uint32_t eps_bearer_id; + // add configuration check + // E-RAB Parameters, Tunnel address (IP address, TEID) + // QCI, security, etc + }; + + /// Request addition of NR carrier for UE + virtual int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) = 0; + + /// Provide information whether the requested configuration was applied successfully by the UE + virtual int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) = 0; +}; + +/// X2AP inspired interface for response from NR RRC to EUTRA RRC +class rrc_eutra_interface_rrc_nr +{ +public: + /** + * @brief List of parameters included in the SgNB addition Ack message + * @param nr_secondary_cell_group_cfg_r15 Encoded part of the RRC Reconfiguration + * @param nr_radio_bearer_cfg1_r15 Encoded part of the RRC Reconfiguration + * @param eps_bearer_id ID of the transfered bearer + */ + struct sgnb_addition_ack_params_t { + uint16_t nr_rnti = SRSRAN_INVALID_RNTI; // RNTI that was assigned to the UE + asn1::dyn_octstring nr_secondary_cell_group_cfg_r15; + asn1::dyn_octstring nr_radio_bearer_cfg1_r15; + uint32_t eps_bearer_id = 0; // (list of) successfully transfered EPS bearers + }; + + /** + * @brief Signal successful addition of UE + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + * @param params Parameter list + */ + virtual void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) = 0; + + /** + * @brief Signal unsuccessful SgNB addition + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + */ + virtual void sgnb_addition_reject(uint16_t eutra_rnti) = 0; + + /** + * @brief Signal completion of SgNB addition after UE (with new NR identity) has attached + * + * @param eutra_rnti The RNTI that the EUTRA RRC used to request the SgNB addition + * @param nr_rnti The RNTI that has been assigned to the UE on the SgNB + */ + virtual void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) = 0; +}; + +class stack_nr_interface_stack_eutra +{ +public: + /// Helper method to provide time signal to NR-RRC (PHY only sends TTI ticks to EUTRA stack) + virtual void tti_clock() = 0; +}; + +// combined interface used by X2 adapter +class x2_interface : public rrc_nr_interface_rrc, + public rrc_eutra_interface_rrc_nr, + public stack_nr_interface_stack_eutra, + public pdcp_interface_gtpu +{}; + +} // namespace srsenb + +#endif // SRSRAN_ENB_X2_INTERFACES_H diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 890862759..cf5901e84 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -24,12 +24,14 @@ #include #include "phy/phy.h" +#include "x2_adapter.h" #include "srsran/radio/radio.h" #include "srsenb/hdr/phy/enb_phy_base.h" #include "srsenb/hdr/stack/enb_stack_base.h" #include "srsenb/hdr/stack/rrc/rrc_config.h" +#include "srsenb/hdr/stack/rrc/rrc_config_nr.h" #include "srsenb/hdr/stack/mac/sched_interface.h" #include "srsran/common/bcd_helpers.h" @@ -39,6 +41,7 @@ #include "srsran/common/security.h" #include "srsran/interfaces/enb_command_interface.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/interfaces/ue_interfaces.h" #include "srsran/srslog/srslog.h" #include "srsran/system/sys_metrics_processor.h" @@ -117,7 +120,7 @@ struct rrc_cfg_t; Main eNB class *******************************************************************************/ -class enb : public enb_metrics_interface, enb_command_interface +class enb : public enb_metrics_interface, enb_command_interface, enb_time_interface { public: enb(srslog::sink& log_sink); @@ -140,6 +143,8 @@ public: void toggle_padding() override; + void tti_clock() override; + private: const static int ENB_POOL_SIZE = 1024 * 10; @@ -151,10 +156,12 @@ private: all_args_t args = {}; bool started = false; - phy_cfg_t phy_cfg = {}; - rrc_cfg_t rrc_cfg = {}; + phy_cfg_t phy_cfg = {}; + rrc_cfg_t rrc_cfg = {}; + rrc_nr_cfg_t rrc_nr_cfg = {}; // eNB components + x2_adapter x2; std::unique_ptr eutra_stack = nullptr; std::unique_ptr nr_stack = nullptr; std::unique_ptr radio = nullptr; diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 66cf9ddbc..4c816e577 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -71,7 +71,6 @@ private: int get_mch_sched(uint32_t tti, bool is_mcch, dl_sched_list_t& dl_sched_res) override { return 0; } int get_ul_sched(uint32_t tti, ul_sched_list_t& ul_sched_res) override { return 0; } void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override {} - void tti_clock() override {} }; srsran::phy_common_interface& common; diff --git a/srsenb/hdr/phy/phy.h b/srsenb/hdr/phy/phy.h index ca19eb7a4..95a1cbb00 100644 --- a/srsenb/hdr/phy/phy.h +++ b/srsenb/hdr/phy/phy.h @@ -18,6 +18,7 @@ #include "srsenb/hdr/phy/enb_phy_base.h" #include "srsran/common/trace.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/interfaces/radio_interfaces.h" #include "srsran/radio/radio.h" #include "srsran/srslog/srslog.h" @@ -37,12 +38,14 @@ public: int init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, - stack_interface_phy_lte* stack_); + stack_interface_phy_lte* stack_, + enb_time_interface* enb_); int init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, stack_interface_phy_lte* stack_lte_, - stack_interface_phy_nr& stack_nr_); + stack_interface_phy_nr& stack_nr_, + enb_time_interface* enb_); void stop() override; std::string get_type() override { return "lte"; }; diff --git a/srsenb/hdr/phy/txrx.h b/srsenb/hdr/phy/txrx.h index b3deaa3f0..105410369 100644 --- a/srsenb/hdr/phy/txrx.h +++ b/srsenb/hdr/phy/txrx.h @@ -18,6 +18,7 @@ #include "srsenb/hdr/phy/lte/worker_pool.h" #include "srsenb/hdr/phy/nr/worker_pool.h" #include "srsran/config.h" +#include "srsran/interfaces/enb_time_interface.h" #include "srsran/phy/channel/channel.h" #include "srsran/radio/radio.h" #include @@ -28,7 +29,7 @@ class txrx final : public srsran::thread { public: txrx(srslog::basic_logger& logger); - bool init(stack_interface_phy_lte* stack_, + bool init(enb_time_interface* enb_, srsran::radio_interface_phy* radio_handler, lte::worker_pool* lte_workers_, phy_common* worker_com, @@ -40,7 +41,7 @@ public: private: void run_thread() override; - stack_interface_phy_lte* stack = nullptr; + enb_time_interface* enb = nullptr; srsran::radio_interface_phy* radio_h = nullptr; srslog::basic_logger& logger; lte::worker_pool* lte_workers = nullptr; diff --git a/srsenb/hdr/stack/enb_stack_base.h b/srsenb/hdr/stack/enb_stack_base.h index b9d6bebb5..5d0932a15 100644 --- a/srsenb/hdr/stack/enb_stack_base.h +++ b/srsenb/hdr/stack/enb_stack_base.h @@ -85,6 +85,8 @@ public: virtual void toggle_padding() = 0; // eNB metrics interface virtual bool get_metrics(stack_metrics_t* metrics) = 0; + + virtual void tti_clock() = 0; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index b01ea3a20..2ec367b67 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -19,9 +19,7 @@ #define SRSRAN_ENB_STACK_LTE_H #include "mac/mac.h" -#include "mac/nr/mac_nr.h" #include "rrc/rrc.h" -#include "rrc/rrc_nr.h" #include "s1ap/s1ap.h" #include "srsran/common/task_scheduler.h" #include "upper/gtpu.h" @@ -40,7 +38,7 @@ class gtpu_pdcp_adapter; class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, - public stack_interface_phy_nr, + public rrc_eutra_interface_rrc_nr, public srsran::thread { public: @@ -48,12 +46,7 @@ public: ~enb_stack_lte() final; // eNB stack base interface - int init(const stack_args_t& args_, - const rrc_cfg_t& rrc_cfg_, - phy_interface_stack_lte* phy_, - phy_interface_stack_nr* phy_nr_); - int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_); - int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_); + int init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, x2_interface* x2_); void stop() final; std::string get_type() final; bool get_metrics(stack_metrics_t* metrics) final; @@ -115,25 +108,16 @@ public: void toggle_padding() override { mac.toggle_padding(); } void tti_clock() override; - // mac_interface_phy_nr - int slot_indication(const srsran_slot_cfg_t& slot_cfg) override { return mac_nr.slot_indication(slot_cfg); } - int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::dl_sched_t& dl_sched) override + // rrc_eutra_interface_rrc_nr + void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) final { - return mac_nr.get_dl_sched(slot_cfg, dl_sched); + rrc.sgnb_addition_ack(eutra_rnti, params); } - int get_ul_sched(const srsran_slot_cfg_t& slot_cfg, srsenb::mac_interface_phy_nr::ul_sched_t& ul_sched) override + void sgnb_addition_reject(uint16_t eutra_rnti) final { rrc.sgnb_addition_reject(eutra_rnti); } + void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) final { - return mac_nr.get_ul_sched(slot_cfg, ul_sched); + rrc.sgnb_addition_complete(eutra_rnti, nr_rnti); } - int pucch_info(const srsran_slot_cfg_t& slot_cfg, const pucch_info_t& pucch_info) override - { - return mac_nr.pucch_info(slot_cfg, pucch_info); - } - int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override - { - return mac_nr.pusch_info(slot_cfg, pusch_info); - } - void rach_detected(const rach_info_t& rach_info) override { mac_nr.rach_detected(rach_info); } private: static const int STACK_MAIN_THREAD_PRIO = 4; @@ -155,10 +139,6 @@ private: srslog::basic_logger& s1ap_logger; srslog::basic_logger& gtpu_logger; srslog::basic_logger& stack_logger; - srslog::basic_logger& rrc_nr_logger; - srslog::basic_logger& mac_nr_logger; - srslog::basic_logger& rlc_nr_logger; - srslog::basic_logger& pdcp_nr_logger; // PCAP and trace option srsran::mac_pcap mac_pcap; @@ -180,15 +160,8 @@ private: srsenb::gtpu gtpu; srsenb::s1ap s1ap; - // NR components for NSA mode - srsenb::mac_nr mac_nr; - srsenb::rlc rlc_nr; - srsenb::pdcp pdcp_nr; - srsenb::rrc_nr rrc_nr; - // RAT-specific interfaces phy_interface_stack_lte* phy = nullptr; - phy_interface_stack_nr* phy_nr = nullptr; // state std::atomic started{false}; diff --git a/srsenb/hdr/stack/gnb_stack_nr.h b/srsenb/hdr/stack/gnb_stack_nr.h index 48102f5d9..d20135c7a 100644 --- a/srsenb/hdr/stack/gnb_stack_nr.h +++ b/srsenb/hdr/stack/gnb_stack_nr.h @@ -18,16 +18,15 @@ #ifndef SRSRAN_GNB_STACK_NR_H #define SRSRAN_GNB_STACK_NR_H -#include "s1ap/s1ap.h" #include "srsenb/hdr/stack/mac/nr/mac_nr.h" #include "srsenb/hdr/stack/rrc/rrc_nr.h" #include "srsenb/hdr/stack/upper/pdcp_nr.h" #include "srsenb/hdr/stack/upper/rlc_nr.h" -#include "upper/gtpu.h" +#include "upper/pdcp.h" +#include "upper/rlc.h" #include "upper/sdap.h" #include "enb_stack_base.h" -#include "srsenb/hdr/enb.h" #include "srsran/interfaces/gnb_interfaces.h" // This is needed for GW @@ -40,14 +39,18 @@ class gnb_stack_nr final : public srsenb::enb_stack_base, public stack_interface_phy_nr, public stack_interface_mac, public srsue::stack_interface_gw, + public rrc_nr_interface_rrc, + public pdcp_interface_gtpu, // for user-plane over X2 public srsran::thread { public: - explicit gnb_stack_nr(); + explicit gnb_stack_nr(srslog::sink& log_sink); ~gnb_stack_nr() final; - int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_); - int init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_); + int init(const srsenb::stack_args_t& args_, + const rrc_nr_cfg_t& rrc_cfg_, + phy_interface_stack_nr* phy_, + x2_interface* x2_); // eNB stack base interface void stop() final; @@ -62,12 +65,12 @@ public: void write_sdu(uint32_t lcid, srsran::unique_byte_buffer_t sdu) override; bool has_active_radio_bearer(uint32_t eps_bearer_id) override; bool switch_on(); - void run_tti(uint32_t tti); + void tti_clock() override; // MAC interface to trigger processing of received PDUs void process_pdus() final; - void toggle_padding() override { srsran::console("padding not available for NR\n"); } + void toggle_padding() override {} int slot_indication(const srsran_slot_cfg_t& slot_cfg) override; int get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) override; @@ -76,15 +79,40 @@ public: int pusch_info(const srsran_slot_cfg_t& slot_cfg, pusch_info_t& pusch_info) override; void rach_detected(const rach_info_t& rach_info) override; + // X2 interface + + // control plane, i.e. rrc_nr_interface_rrc + int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) final + { + return rrc.sgnb_addition_request(eutra_rnti, params); + }; + int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) final + { + return rrc.sgnb_reconfiguration_complete(eutra_rnti, reconfig_response); + }; + // X2 data interface + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) final + { + pdcp.write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) final + { + return pdcp.get_buffered_pdus(rnti, lcid); + } + private: void run_thread() final; - void run_tti_impl(uint32_t tti); + void tti_clock_impl(); // args srsenb::stack_args_t args = {}; phy_interface_stack_nr* phy = nullptr; + srslog::basic_logger& rrc_logger; + srslog::basic_logger& mac_logger; srslog::basic_logger& rlc_logger; + srslog::basic_logger& pdcp_logger; + srslog::basic_logger& stack_logger; // task scheduling static const int STACK_MAIN_THREAD_PRIO = 4; @@ -92,18 +120,14 @@ private: srsran::task_multiqueue::queue_handle sync_task_queue, ue_task_queue, gw_task_queue, mac_task_queue; // derived - std::unique_ptr m_mac; - std::unique_ptr m_rlc; - std::unique_ptr m_pdcp; - std::unique_ptr m_sdap; - std::unique_ptr m_rrc; - std::unique_ptr m_gw; - // std::unique_ptr m_ngap; - // std::unique_ptr m_gtpu; + srsenb::mac_nr mac; + srsenb::rlc rlc; + srsenb::pdcp pdcp; + srsenb::rrc_nr rrc; + // std::unique_ptr m_sdap; // state - bool running = false; - uint32_t current_tti = 10240; + std::atomic running = {false}; }; } // namespace srsenb diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index 332ef793e..25ee18bb2 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -26,6 +26,7 @@ #include "srsran/common/task_scheduler.h" #include "srsran/common/timeout.h" #include "srsran/interfaces/enb_rrc_interfaces.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/srslog/srslog.h" #include diff --git a/srsenb/hdr/stack/rrc/rrc_nr.h b/srsenb/hdr/stack/rrc/rrc_nr.h index 5b3200edc..15b01e7f5 100644 --- a/srsenb/hdr/stack/rrc/rrc_nr.h +++ b/srsenb/hdr/stack/rrc/rrc_nr.h @@ -27,6 +27,7 @@ #include "srsran/interfaces/enb_pdcp_interfaces.h" #include "srsran/interfaces/enb_rlc_interfaces.h" #include "srsran/interfaces/enb_rrc_interfaces.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/interfaces/gnb_interfaces.h" #include "srsran/interfaces/gnb_mac_interfaces.h" #include "srsran/interfaces/gnb_ngap_interfaces.h" diff --git a/srsenb/hdr/x2_adapter.h b/srsenb/hdr/x2_adapter.h new file mode 100644 index 000000000..047533af8 --- /dev/null +++ b/srsenb/hdr/x2_adapter.h @@ -0,0 +1,120 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2021 Software Radio Systems Limited + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the distribution. + * + */ + +/** + * @brief Dummy X2AP implementation + * + * Dummy X2 adapter to facilitate communication between EUTRA RRC and NR RRC + * for EN-DC procedures. + * + * The class uses direct function calls instead of real X2AP ASN1 encoded + * messages. It mainly focuses on Sec 9.1.4 of TS 36.423 Rel. 15.11 + * for E-UTRAN-NR Dual Connectivity Procedures, i.e. SgNB-* + * + * It furthermore provide an interface for the GTPU adapter to + * write DL PDUs, which it then forwards to the NR PDCP. + * + * It also provides a method to allow the eNB to foward timing + * signal, i.e. TTI tics, to the NR stack. + */ + +#ifndef SRSENB_X2_ADAPTER_H +#define SRSENB_X2_ADAPTER_H + +#include "srsran/interfaces/enb_x2_interfaces.h" +#include "stack/enb_stack_lte.h" +#include "stack/gnb_stack_nr.h" + +namespace srsenb { + +class x2_adapter final : public x2_interface +{ +public: + x2_adapter() = default; + + // init functions to set handle to stacks + void set_eutra_stack(enb_stack_lte* eutra_stack_) { eutra_stack = eutra_stack_; } + + void set_nr_stack(gnb_stack_nr* nr_stack_) { nr_stack = nr_stack_; } + + /// rrc_nr_interface_rrc + int sgnb_addition_request(uint16_t eutra_rnti, const sgnb_addition_req_params_t& params) + { + if (nr_stack == nullptr) { + return SRSRAN_ERROR; + } + return nr_stack->sgnb_addition_request(eutra_rnti, params); + } + int sgnb_reconfiguration_complete(uint16_t eutra_rnti, asn1::dyn_octstring reconfig_response) + { + if (nr_stack == nullptr) { + return SRSRAN_ERROR; + } + return nr_stack->sgnb_reconfiguration_complete(eutra_rnti, reconfig_response); + } + + /// rrc_eutra_interface_rrc_nr + void sgnb_addition_ack(uint16_t eutra_rnti, sgnb_addition_ack_params_t params) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_ack(eutra_rnti, params); + } + void sgnb_addition_reject(uint16_t eutra_rnti) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_reject(eutra_rnti); + } + void sgnb_addition_complete(uint16_t eutra_rnti, uint16_t nr_rnti) + { + if (eutra_stack == nullptr) { + return; + } + eutra_stack->sgnb_addition_complete(eutra_rnti, nr_rnti); + } + + // stack_nr_interface_stack_eutra + void tti_clock() + { + if (nr_stack == nullptr) { + return; + } + nr_stack->tti_clock(); + } + + // pdcp_interface_gtpu + void write_sdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t sdu, int pdcp_sn = -1) + { + if (nr_stack == nullptr) { + return; + } + nr_stack->write_sdu(rnti, lcid, std::move(sdu), pdcp_sn); + } + std::map get_buffered_pdus(uint16_t rnti, uint32_t lcid) + { + if (nr_stack == nullptr) { + return {}; + } + return nr_stack->get_buffered_pdus(rnti, lcid); + } + +private: + enb_stack_lte* eutra_stack = nullptr; + gnb_stack_nr* nr_stack = nullptr; +}; + +} // namespace srsenb + +#endif // SRSENB_X2_ADAPTER_H diff --git a/srsenb/src/enb.cc b/srsenb/src/enb.cc index 009a09c1b..da2bbdc2d 100644 --- a/srsenb/src/enb.cc +++ b/srsenb/src/enb.cc @@ -59,36 +59,46 @@ int enb::init(const all_args_t& args_) srsran::console("Error creating EUTRA stack.\n"); return SRSRAN_ERROR; } + x2.set_eutra_stack(tmp_eutra_stack.get()); } std::unique_ptr tmp_nr_stack; if (not rrc_cfg.cell_list_nr.empty()) { // add NR stack - tmp_nr_stack.reset(new gnb_stack_nr()); + tmp_nr_stack.reset(new gnb_stack_nr(log_sink)); if (tmp_nr_stack == nullptr) { srsran::console("Error creating NR stack.\n"); return SRSRAN_ERROR; } + x2.set_nr_stack(tmp_nr_stack.get()); } - // Radio is RAT agnostic + // Radio and PHY are RAT agnostic std::unique_ptr tmp_radio = std::unique_ptr(new srsran::radio); if (tmp_radio == nullptr) { srsran::console("Error creating radio multi instance.\n"); return SRSRAN_ERROR; } - // PHY is RAT agnostic too std::unique_ptr tmp_phy = std::unique_ptr(new srsenb::phy(log_sink)); if (tmp_phy == nullptr) { srsran::console("Error creating PHY instance.\n"); return SRSRAN_ERROR; } - // initialize layers - if (tmp_eutra_stack->init(args.stack, rrc_cfg, tmp_phy.get(), tmp_phy.get()) != SRSRAN_SUCCESS) { - srsran::console("Error initializing stack.\n"); - ret = SRSRAN_ERROR; + // initialize layers, if they exist + if (tmp_eutra_stack) { + if (tmp_eutra_stack->init(args.stack, rrc_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) { + srsran::console("Error initializing EUTRA stack.\n"); + ret = SRSRAN_ERROR; + } + } + + if (tmp_nr_stack) { + if (tmp_nr_stack->init(args.stack, rrc_nr_cfg, tmp_phy.get(), &x2) != SRSRAN_SUCCESS) { + srsran::console("Error initializing NR stack.\n"); + ret = SRSRAN_ERROR; + } } // Init Radio @@ -99,7 +109,7 @@ int enb::init(const all_args_t& args_) // Only Init PHY if radio could be initialized if (ret == SRSRAN_SUCCESS) { - if (tmp_phy->init(args.phy, phy_cfg, tmp_radio.get(), tmp_eutra_stack.get(), *tmp_eutra_stack)) { + if (tmp_phy->init(args.phy, phy_cfg, tmp_radio.get(), tmp_eutra_stack.get(), *tmp_nr_stack, this)) { srsran::console("Error initializing PHY.\n"); ret = SRSRAN_ERROR; } @@ -221,7 +231,19 @@ std::string enb::get_build_string() void enb::toggle_padding() { - eutra_stack->toggle_padding(); + if (eutra_stack) { + eutra_stack->toggle_padding(); + } +} + +void enb::tti_clock() +{ + if (eutra_stack) { + eutra_stack->tti_clock(); + } + if (nr_stack) { + nr_stack->tti_clock(); + } } } // namespace srsenb diff --git a/srsenb/src/phy/phy.cc b/srsenb/src/phy/phy.cc index cd2f48ec9..a466b8b99 100644 --- a/srsenb/src/phy/phy.cc +++ b/srsenb/src/phy/phy.cc @@ -97,9 +97,10 @@ int phy::init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, stack_interface_phy_lte* stack_lte_, - stack_interface_phy_nr& stack_nr_) + stack_interface_phy_nr& stack_nr_, + enb_time_interface* enb_) { - if (init(args, cfg, radio_, stack_lte_) != SRSRAN_SUCCESS) { + if (init(args, cfg, radio_, stack_lte_, enb_) != SRSRAN_SUCCESS) { phy_log.error("Couldn't initialize LTE PHY"); return SRSRAN_ERROR; } @@ -115,7 +116,8 @@ int phy::init(const phy_args_t& args, int phy::init(const phy_args_t& args, const phy_cfg_t& cfg, srsran::radio_interface_phy* radio_, - stack_interface_phy_lte* stack_) + stack_interface_phy_lte* stack_lte_, + enb_time_interface* enb_) { if (cfg.phy_cell_cfg.size() > SRSRAN_MAX_CARRIERS) { phy_log.error( @@ -142,7 +144,7 @@ int phy::init(const phy_args_t& args, workers_common.params = args; - workers_common.init(cfg.phy_cell_cfg, cfg.phy_cell_cfg_nr, radio, stack_); + workers_common.init(cfg.phy_cell_cfg, cfg.phy_cell_cfg_nr, radio, stack_lte_); parse_common_config(cfg); @@ -154,13 +156,18 @@ int phy::init(const phy_args_t& args, // For each carrier, initialise PRACH worker for (uint32_t cc = 0; cc < cfg.phy_cell_cfg.size(); cc++) { prach_cfg.root_seq_idx = cfg.phy_cell_cfg[cc].root_seq_idx; - prach.init( - cc, cfg.phy_cell_cfg[cc].cell, prach_cfg, stack_, phy_log, PRACH_WORKER_THREAD_PRIO, args.nof_prach_threads); + prach.init(cc, + cfg.phy_cell_cfg[cc].cell, + prach_cfg, + stack_lte_, + phy_log, + PRACH_WORKER_THREAD_PRIO, + args.nof_prach_threads); } prach.set_max_prach_offset_us(args.max_prach_offset_us); // Warning this must be initialized after all workers have been added to the pool - tx_rx.init(stack_, radio, <e_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); + tx_rx.init(enb_, radio, <e_workers, &workers_common, &prach, SF_RECV_THREAD_PRIO); initialized = true; diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 6712b5603..193486d05 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -39,14 +39,14 @@ txrx::txrx(srslog::basic_logger& logger) : thread("TXRX"), logger(logger), runni /* Do nothing */ } -bool txrx::init(stack_interface_phy_lte* stack_, +bool txrx::init(enb_time_interface* enb_, srsran::radio_interface_phy* radio_h_, lte::worker_pool* lte_workers_, phy_common* worker_com_, prach_worker_pool* prach_, uint32_t prio_) { - stack = stack_; + enb = enb_; radio_h = radio_h_; lte_workers = lte_workers_; worker_com = worker_com_; @@ -213,8 +213,8 @@ void txrx::run_thread() lte_workers->start_worker(lte_worker); } - // Advance stack in time - stack->tti_clock(); + // Advance in time + enb->tti_clock(); } } diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index 766920b65..ec25ad053 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -13,8 +13,8 @@ #include "srsenb/hdr/stack/enb_stack_lte.h" #include "srsenb/hdr/common/rnti_pool.h" #include "srsenb/hdr/enb.h" -#include "srsenb/hdr/stack/rrc/rrc_config_nr.h" #include "srsran/interfaces/enb_metrics_interface.h" +#include "srsran/interfaces/enb_x2_interfaces.h" #include "srsran/rlc/bearer_mem_pool.h" #include "srsran/srslog/event_trace.h" @@ -27,10 +27,10 @@ class gtpu_pdcp_adapter final : public gtpu_interface_pdcp, public pdcp_interfac public: gtpu_pdcp_adapter(srslog::basic_logger& logger_, pdcp* pdcp_lte, - pdcp* pdcp_nr, + pdcp_interface_gtpu* pdcp_x2, gtpu* gtpu_, enb_bearer_manager& bearers_) : - logger(logger_), pdcp_obj(pdcp_lte), pdcp_nr_obj(pdcp_nr), gtpu_obj(gtpu_), bearers(&bearers_) + logger(logger_), pdcp_obj(pdcp_lte), pdcp_x2_obj(pdcp_x2), gtpu_obj(gtpu_), bearers(&bearers_) {} /// Converts LCID to EPS-BearerID and sends corresponding PDU to GTPU @@ -50,7 +50,7 @@ public: if (bearer.rat == srsran_rat_t::lte) { pdcp_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else if (bearer.rat == srsran_rat_t::nr) { - pdcp_nr_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); + pdcp_x2_obj->write_sdu(rnti, bearer.lcid, std::move(sdu), pdcp_sn); } else { logger.warning("Can't deliver SDU for EPS bearer %d. Dropping it.", eps_bearer_id); } @@ -62,7 +62,7 @@ public: if (bearer.rat == srsran_rat_t::lte) { return pdcp_obj->get_buffered_pdus(rnti, bearer.lcid); } else if (bearer.rat == srsran_rat_t::nr) { - return pdcp_nr_obj->get_buffered_pdus(rnti, bearer.lcid); + return pdcp_x2_obj->get_buffered_pdus(rnti, bearer.lcid); } logger.error("Bearer rnti=0x%x, eps-BearerID=%d not found", rnti, eps_bearer_id); return {}; @@ -72,34 +72,26 @@ private: srslog::basic_logger& logger; gtpu* gtpu_obj = nullptr; pdcp* pdcp_obj = nullptr; - pdcp* pdcp_nr_obj = nullptr; + pdcp_interface_gtpu* pdcp_x2_obj = nullptr; enb_bearer_manager* bearers = nullptr; }; enb_stack_lte::enb_stack_lte(srslog::sink& log_sink) : thread("STACK"), mac_logger(srslog::fetch_basic_logger("MAC", log_sink)), - mac_nr_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)), rlc_logger(srslog::fetch_basic_logger("RLC", log_sink, false)), - rlc_nr_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)), pdcp_logger(srslog::fetch_basic_logger("PDCP", log_sink, false)), - pdcp_nr_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)), rrc_logger(srslog::fetch_basic_logger("RRC", log_sink, false)), - rrc_nr_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)), s1ap_logger(srslog::fetch_basic_logger("S1AP", log_sink, false)), gtpu_logger(srslog::fetch_basic_logger("GTPU", log_sink, false)), stack_logger(srslog::fetch_basic_logger("STCK", log_sink, false)), task_sched(512, 128), pdcp(&task_sched, pdcp_logger), - pdcp_nr(&task_sched, pdcp_nr_logger), mac(&task_sched, mac_logger), - mac_nr(&task_sched), rlc(rlc_logger), - rlc_nr(rlc_nr_logger), gtpu(&task_sched, gtpu_logger, &rx_sockets), s1ap(&task_sched, s1ap_logger, &rx_sockets), rrc(&task_sched, bearers), - rrc_nr(&task_sched), mac_pcap(), pending_stack_metrics(64) { @@ -122,30 +114,11 @@ std::string enb_stack_lte::get_type() int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_, - phy_interface_stack_nr* phy_nr_) -{ - phy_nr = phy_nr_; - if (init(args_, rrc_cfg_, phy_)) { - return SRSRAN_ERROR; - } - - return SRSRAN_SUCCESS; -} - -int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, phy_interface_stack_lte* phy_) -{ - phy = phy_; - if (init(args_, rrc_cfg_)) { - return SRSRAN_ERROR; - } - - return SRSRAN_SUCCESS; -} - -int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) + x2_interface* x2_) { args = args_; rrc_cfg = rrc_cfg_; + phy = phy_; // Init RNTI and bearer memory pools reserve_rnti_memblocks(args.mac.nof_prealloc_ues); @@ -154,25 +127,17 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) // setup logging for each layer mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); - mac_nr_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); - rlc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); - pdcp_nr_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); - rrc_nr_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); gtpu_logger.set_level(srslog::str_to_basic_level(args.log.gtpu_level)); s1ap_logger.set_level(srslog::str_to_basic_level(args.log.s1ap_level)); stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); - mac_nr_logger.set_hex_dump_max_size(args.log.mac_hex_limit); rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); - rlc_nr_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); - pdcp_nr_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); - rrc_nr_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); gtpu_logger.set_hex_dump_max_size(args.log.gtpu_hex_limit); s1ap_logger.set_hex_dump_max_size(args.log.s1ap_hex_limit); stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); @@ -200,7 +165,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) sync_task_queue = task_sched.make_task_queue(args.sync_queue_size); // setup bearer managers - gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, &pdcp_nr, >pu, bearers)); + gtpu_adapter.reset(new gtpu_pdcp_adapter(stack_logger, &pdcp, x2_, >pu, bearers)); // Init all LTE layers if (!mac.init(args.mac, rrc_cfg.cell_list, phy, &rlc, &rrc)) { @@ -209,7 +174,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) } rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); pdcp.init(&rlc, &rrc, gtpu_adapter.get()); - if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, &rrc_nr) != SRSRAN_SUCCESS) { + if (rrc.init(rrc_cfg, phy, &mac, &rlc, &pdcp, &s1ap, >pu, x2_) != SRSRAN_SUCCESS) { stack_logger.error("Couldn't initialize RRC"); return SRSRAN_ERROR; } @@ -218,25 +183,6 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) return SRSRAN_ERROR; } - // NR layers - mac_nr_args_t mac_args = {}; - mac_args.fixed_dl_mcs = 28; - mac_args.fixed_ul_mcs = 10; - mac_args.pcap = args.mac_pcap; - mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap"; - if (mac_nr.init(mac_args, phy_nr, nullptr, &rlc_nr, &rrc_nr) != SRSRAN_SUCCESS) { - stack_logger.error("Couldn't initialize MAC-NR"); - return SRSRAN_ERROR; - } - - rrc_nr_cfg_t rrc_cfg_nr = {}; - if (rrc_nr.init(rrc_cfg_nr, phy_nr, &mac_nr, &rlc_nr, &pdcp_nr, nullptr, nullptr, &rrc) != SRSRAN_SUCCESS) { - stack_logger.error("Couldn't initialize RRC-NR"); - return SRSRAN_ERROR; - } - rlc_nr.init(&pdcp_nr, &rrc_nr, &mac_nr, task_sched.get_timer_handler()); - pdcp_nr.init(&rlc_nr, &rrc_nr, gtpu_adapter.get()); - gtpu_args_t gtpu_args; gtpu_args.embms_enable = args.embms.enable; gtpu_args.embms_m1u_multiaddr = args.embms.m1u_multiaddr; diff --git a/srsenb/src/stack/gnb_stack_nr.cc b/srsenb/src/stack/gnb_stack_nr.cc index 205aed2a4..fad435c01 100644 --- a/srsenb/src/stack/gnb_stack_nr.cc +++ b/srsenb/src/stack/gnb_stack_nr.cc @@ -11,21 +11,25 @@ */ #include "srsenb/hdr/stack/gnb_stack_nr.h" +#include "srsran/common/standard_streams.h" #include "srsran/srsran.h" #include namespace srsenb { -gnb_stack_nr::gnb_stack_nr() : task_sched{512, 128}, thread("gNB"), rlc_logger(srslog::fetch_basic_logger("RLC-NR")) +gnb_stack_nr::gnb_stack_nr(srslog::sink& log_sink) : + task_sched{512, 128}, + thread("gNB"), + mac_logger(srslog::fetch_basic_logger("MAC-NR", log_sink)), + rlc_logger(srslog::fetch_basic_logger("RLC-NR", log_sink, false)), + pdcp_logger(srslog::fetch_basic_logger("PDCP-NR", log_sink, false)), + rrc_logger(srslog::fetch_basic_logger("RRC-NR", log_sink, false)), + stack_logger(srslog::fetch_basic_logger("STCK-NR", log_sink, false)), + mac(&task_sched), + rrc(&task_sched), + pdcp(&task_sched, pdcp_logger), + rlc(rlc_logger) { - m_mac.reset(new mac_nr(&task_sched)); - m_rlc.reset(new rlc_nr("RLC-NR")); - m_pdcp.reset(new pdcp_nr(&task_sched, "PDCP-NR")); - m_rrc.reset(new rrc_nr(&task_sched)); - m_sdap.reset(new sdap()); - m_gw.reset(new srsue::gw(srslog::fetch_basic_logger("GW"))); - // m_gtpu.reset(new srsenb::gtpu()); - ue_task_queue = task_sched.make_task_queue(); sync_task_queue = task_sched.make_task_queue(); gw_task_queue = task_sched.make_task_queue(); @@ -42,46 +46,48 @@ std::string gnb_stack_nr::get_type() return "nr"; } -int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_, phy_interface_stack_nr* phy_) +int gnb_stack_nr::init(const srsenb::stack_args_t& args_, + const rrc_nr_cfg_t& rrc_cfg_, + phy_interface_stack_nr* phy_, + x2_interface* x2_) { + args = args_; + // rrc_cfg = rrc_cfg_; phy = phy_; - if (init(args_, rrc_cfg_)) { - return SRSRAN_ERROR; - } - return SRSRAN_SUCCESS; -} -int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rrc_cfg_) -{ - args = args_; + // setup logging + mac_logger.set_level(srslog::str_to_basic_level(args.log.mac_level)); + rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); + pdcp_logger.set_level(srslog::str_to_basic_level(args.log.pdcp_level)); + rrc_logger.set_level(srslog::str_to_basic_level(args.log.rrc_level)); + stack_logger.set_level(srslog::str_to_basic_level(args.log.stack_level)); - // verify configuration correctness - // gtpu_log.init("GTPU", logger); - // gtpu_log.set_level(args.log.gtpu_level); - // gtpu_log.set_hex_limit(args.log.gtpu_hex_limit); + mac_logger.set_hex_dump_max_size(args.log.mac_hex_limit); + rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); + pdcp_logger.set_hex_dump_max_size(args.log.pdcp_hex_limit); + rrc_logger.set_hex_dump_max_size(args.log.rrc_hex_limit); + stack_logger.set_hex_dump_max_size(args.log.stack_hex_limit); // Init all layers mac_nr_args_t mac_args = {}; + mac_args.fixed_dl_mcs = 28; + mac_args.fixed_ul_mcs = 10; mac_args.pcap = args.mac_pcap; - m_mac->init(mac_args, phy, this, nullptr, m_rrc.get()); - - rlc_logger.set_level(srslog::str_to_basic_level(args.log.rlc_level)); - rlc_logger.set_hex_dump_max_size(args.log.rlc_hex_limit); - m_rlc->init(m_pdcp.get(), m_rrc.get(), m_mac.get(), task_sched.get_timer_handler()); - - pdcp_nr_args_t pdcp_args = {}; - pdcp_args.log_level = args.log.pdcp_level; - pdcp_args.log_hex_limit = args.log.pdcp_hex_limit; - m_pdcp->init(pdcp_args, m_rlc.get(), m_rrc.get(), m_sdap.get()); - - m_rrc->init(rrc_cfg_, phy, m_mac.get(), nullptr, nullptr, nullptr, nullptr, nullptr); + mac_args.pcap.filename = "/tmp/enb_mac_nr.pcap"; + if (mac.init(mac_args, phy, nullptr, &rlc, &rrc) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize MAC-NR"); + return SRSRAN_ERROR; + } - m_sdap->init(m_pdcp.get(), nullptr, m_gw.get()); + rlc.init(&pdcp, &rrc, &mac, task_sched.get_timer_handler()); + pdcp.init(&rlc, &rrc, nullptr); - srsue::gw_args_t gw_args = {}; - m_gw->init(gw_args, this); + if (rrc.init(rrc_cfg_, phy, &mac, &rlc, &pdcp, nullptr, nullptr, x2_) != SRSRAN_SUCCESS) { + stack_logger.error("Couldn't initialize RRC"); + return SRSRAN_ERROR; + } - // TODO: add NGAP + // TODO: add SDAP, NGAP // m_gtpu->init(args.s1ap.gtp_bind_addr, args.s1ap.mme_addr, // args.expert.m1u_multiaddr, args.expert.m1u_if_addr, nullptr, >pu_log, // args.expert.enable_mbsfn); @@ -96,11 +102,9 @@ int gnb_stack_nr::init(const srsenb::stack_args_t& args_, const rrc_nr_cfg_t& rr void gnb_stack_nr::stop() { if (running) { - m_gw->stop(); - // m_gtpu->stop(); - m_rrc->stop(); - m_pdcp->stop(); - m_mac->stop(); + rrc.stop(); + pdcp.stop(); + mac.stop(); srsran::get_background_workers().stop(); running = false; @@ -120,13 +124,12 @@ void gnb_stack_nr::run_thread() } } -void gnb_stack_nr::run_tti(uint32_t tti) +void gnb_stack_nr::tti_clock() { - current_tti = tti; - sync_task_queue.push([this, tti]() { run_tti_impl(tti); }); + sync_task_queue.push([this]() { tti_clock_impl(); }); } -void gnb_stack_nr::run_tti_impl(uint32_t tti) +void gnb_stack_nr::tti_clock_impl() { // m_ngap->run_tti(); task_sched.tic(); @@ -144,8 +147,8 @@ void gnb_stack_nr::process_pdus() bool gnb_stack_nr::get_metrics(srsenb::stack_metrics_t* metrics) { - m_mac->get_metrics(metrics->mac); - m_rrc->get_metrics(metrics->rrc); + mac.get_metrics(metrics->mac); + rrc.get_metrics(metrics->rrc); return true; } @@ -161,25 +164,28 @@ bool gnb_stack_nr::has_active_radio_bearer(uint32_t eps_bearer_id) } int gnb_stack_nr::slot_indication(const srsran_slot_cfg_t& slot_cfg) { - return m_mac->slot_indication(slot_cfg); + return mac.slot_indication(slot_cfg); } int gnb_stack_nr::get_dl_sched(const srsran_slot_cfg_t& slot_cfg, dl_sched_t& dl_sched) { - return m_mac->get_dl_sched(slot_cfg, dl_sched); + return mac.get_dl_sched(slot_cfg, dl_sched); } int gnb_stack_nr::get_ul_sched(const srsran_slot_cfg_t& slot_cfg, ul_sched_t& ul_sched) { - return m_mac->get_ul_sched(slot_cfg, ul_sched); + return mac.get_ul_sched(slot_cfg, ul_sched); } int gnb_stack_nr::pucch_info(const srsran_slot_cfg_t& slot_cfg, const mac_interface_phy_nr::pucch_info_t& pucch_info) { - return m_mac->pucch_info(slot_cfg, pucch_info); + return mac.pucch_info(slot_cfg, pucch_info); } int gnb_stack_nr::pusch_info(const srsran_slot_cfg_t& slot_cfg, mac_interface_phy_nr::pusch_info_t& pusch_info) { - return m_mac->pusch_info(slot_cfg, pusch_info); + return mac.pusch_info(slot_cfg, pusch_info); } -void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) {} +void gnb_stack_nr::rach_detected(const rach_info_t& rach_info) +{ + mac.rach_detected(rach_info); +} -} // namespace srsenb +} // namespace srsenb \ No newline at end of file diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index 64c6f3fde..a18948d43 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -710,7 +710,7 @@ public: return SRSRAN_SUCCESS; } void set_sched_dl_tti_mask(uint8_t* tti_mask, uint32_t nof_sfs) override { notify_set_sched_dl_tti_mask(); } - void tti_clock() override { notify_tti_clock(); } + void tti_clock() { notify_tti_clock(); } int run_tti(bool enable_assert) { std::lock_guard lock(phy_mac_mutex); @@ -1150,7 +1150,7 @@ typedef std::unique_ptr unique_dummy_ue_phy_t; typedef std::unique_ptr unique_srsenb_phy_t; -class phy_test_bench +class phy_test_bench : public srsenb::enb_time_interface { public: struct args_t { @@ -1328,7 +1328,7 @@ public: stack->set_active_cell_list(args.ue_cell_list); /// Initiate eNb PHY with the given RNTI - if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get()) < 0) { + if (enb_phy->init(phy_args, phy_cfg, radio.get(), stack.get(), this) < 0) { return SRSRAN_ERROR; } enb_phy->set_config(args.rnti, phy_rrc_cfg); @@ -1350,7 +1350,7 @@ public: enb_phy->stop(); } - ~phy_test_bench() = default; + virtual ~phy_test_bench() = default; int run_tti() { @@ -1422,6 +1422,11 @@ public: return ret; } + + void tti_clock() final + { + // nothing to do + } }; typedef std::unique_ptr unique_phy_test_bench;