/** * Copyright 2013-2021 Software Radio Systems Limited * * This file is part of srsRAN. * * srsRAN is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsRAN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #ifndef SRSUE_RRC_H #define SRSUE_RRC_H #include "rrc_cell.h" #include "rrc_config.h" #include "rrc_metrics.h" #include "rrc_rlf_report.h" #include "srsran/asn1/rrc_utils.h" #include "srsran/common/bcd_helpers.h" #include "srsran/common/block_queue.h" #include "srsran/common/buffer_pool.h" #include "srsran/common/common.h" #include "srsran/common/common_lte.h" #include "srsran/common/security.h" #include "srsran/common/stack_procedure.h" #include "srsran/interfaces/ue_interfaces.h" #include "srsran/rrc/rrc_common.h" #include "srsran/srslog/srslog.h" #include #include #include using srsran::byte_buffer_t; namespace srsue { class phy_controller; class usim_interface_rrc; class gw_interface_rrc; class pdcp_interface_rrc; class rlc_interface_rrc; class nas_interface_rrc; class phy_interface_rrc_lte; class rrc : public rrc_interface_nas, public rrc_interface_phy_lte, public rrc_interface_mac, public rrc_interface_pdcp, public rrc_eutra_interface_rrc_nr, public rrc_interface_rlc, public srsran::timer_callback { public: rrc(stack_interface_rrc* stack_, srsran::task_sched_handle task_sched_); ~rrc(); void init(phy_interface_rrc_lte* phy_, mac_interface_rrc* mac_, rlc_interface_rrc* rlc_, pdcp_interface_rrc* pdcp_, nas_interface_rrc* nas_, usim_interface_rrc* usim_, gw_interface_rrc* gw_, rrc_nr_interface_rrc* rrc_nr_, const rrc_args_t& args_); void stop(); void get_metrics(rrc_metrics_t& m); // Timeout callback interface void timer_expired(uint32_t timeout_id) final; void srsran_rrc_log(const char* str); typedef enum { Rx = 0, Tx } direction_t; 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); std::string print_mbms(); bool mbms_service_start(uint32_t serv, uint32_t port); // NAS interface void write_sdu(srsran::unique_byte_buffer_t sdu); void enable_capabilities(); uint16_t get_mcc(); uint16_t get_mnc(); bool plmn_search() final; void plmn_select(srsran::plmn_id_t plmn_id); bool connection_request(srsran::establishment_cause_t cause, srsran::unique_byte_buffer_t dedicated_info_nas); void set_ue_identity(srsran::s_tmsi_t s_tmsi); void paging_completed(bool outcome) final; bool has_nr_dc(); // NR interface void new_cell_meas_nr(const std::vector& meas); void nr_rrc_con_reconfig_complete(bool status); // PHY interface void in_sync() final; void out_of_sync() final; void new_cell_meas(const std::vector& meas); void cell_search_complete(cell_search_ret_t ret, phy_cell_t found_cell); void cell_select_complete(bool status); void set_config_complete(bool status); void set_scell_complete(bool status); // MAC interface void ra_completed() final; void release_pucch_srs(); void run_tti(); void ra_problem(); // GW interface bool is_connected() final; // this is also NAS interface bool have_drb(); // PDCP interface void write_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu); void write_pdu_bcch_bch(srsran::unique_byte_buffer_t pdu); void write_pdu_bcch_dlsch(srsran::unique_byte_buffer_t pdu); void write_pdu_pcch(srsran::unique_byte_buffer_t pdu); void write_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu); void notify_pdcp_integrity_error(uint32_t lcid); bool srbs_flushed(); //< Check if data on SRBs still needs to be sent protected: // Moved to protected to be accessible by unit tests void set_serving_cell(phy_cell_t phy_cell, bool discard_serving); bool has_neighbour_cell(uint32_t earfcn, uint32_t pci) const; bool is_serving_cell(uint32_t earfcn, uint32_t pci) const; int start_cell_select(); bool has_neighbour_cell_nr(uint32_t earfcn, uint32_t pci) const; private: typedef struct { enum { PCCH, RLF, RA_COMPLETE, STOP } command; srsran::unique_byte_buffer_t pdu; uint16_t lcid; } cmd_msg_t; bool running = false; srsran::block_queue cmd_q; void process_pcch(srsran::unique_byte_buffer_t pdu); stack_interface_rrc* stack = nullptr; srsran::task_sched_handle task_sched; srslog::basic_logger& logger; phy_interface_rrc_lte* phy = nullptr; mac_interface_rrc* mac = nullptr; rlc_interface_rrc* rlc = nullptr; pdcp_interface_rrc* pdcp = nullptr; nas_interface_rrc* nas = nullptr; usim_interface_rrc* usim = nullptr; gw_interface_rrc* gw = nullptr; rrc_nr_interface_rrc* rrc_nr = nullptr; srsran::unique_byte_buffer_t dedicated_info_nas; void send_ul_ccch_msg(const asn1::rrc::ul_ccch_msg_s& msg); void send_ul_dcch_msg(uint32_t lcid, const asn1::rrc::ul_dcch_msg_s& msg); rrc_state_t state = RRC_STATE_IDLE, last_state = RRC_STATE_IDLE; uint8_t transaction_id = 0; srsran::s_tmsi_t ue_identity; bool ue_identity_configured = false; // PHY controller state machine std::unique_ptr phy_ctrl; rrc_args_t args = {}; uint32_t cell_clean_cnt = 0; srsran::phy_cfg_t previous_phy_cfg = {}; srsran::mac_cfg_t current_mac_cfg, previous_mac_cfg = {}; void generate_as_keys(); srsran::as_security_config_t sec_cfg = {}; std::map srbs; std::map drbs; // RRC constants and timers uint32_t n310_cnt = 0, N310 = 0; uint32_t n311_cnt = 0, N311 = 0; srsran::timer_handler::unique_timer t300, t301, t302, t310, t311, t304; static const std::string rb_id_str[]; const char* get_rb_name(uint32_t lcid) { return srsran::is_lte_rb(lcid) ? rb_id_str[lcid].c_str() : "invalid RB"; } // Var-RLF-Report class rrc_rlf_report var_rlf_report; // Measurements private subclass class rrc_meas; std::unique_ptr measurements; // List of strongest neighbour cell using unique_cell_t = std::unique_ptr; meas_cell_list meas_cells; meas_cell_list meas_cells_nr; // if this is set to a valid earfcn, this earfcn will be used for cell search int cell_search_earfcn = -1; bool initiated = false; asn1::rrc::reest_cause_e m_reest_cause = asn1::rrc::reest_cause_e::nulltype; uint16_t m_reest_rnti = 0; uint16_t m_reest_source_pci = 0; bool reestablishment_started = false; bool reestablishment_successful = false; // Interface from rrc_meas void send_srb1_msg(const asn1::rrc::ul_dcch_msg_s& msg); std::set get_cells(const uint32_t earfcn); float get_cell_rsrp(const uint32_t earfcn, const uint32_t pci); float get_cell_rsrq(const uint32_t earfcn, const uint32_t pci); meas_cell_eutra* get_serving_cell(); std::set get_cells_nr(const uint32_t arfcn_nr); float get_cell_rsrp_nr(const uint32_t arfcn_nr, const uint32_t pci_nr); float get_cell_rsrq_nr(const uint32_t arfcn_nr, const uint32_t pci_nr); void process_cell_meas(); void process_new_cell_meas(const std::vector& meas); srsran::block_queue > cell_meas_q; void process_cell_meas_nr(); void process_new_cell_meas_nr(const std::vector& meas); srsran::block_queue > cell_meas_nr_q; // Cell selection/reselection functions/variables typedef struct { float Qrxlevmin; float Qrxlevminoffset; float Qqualmin; float Qqualminoffset; float s_intrasearchP; float q_hyst; float threshservinglow; } cell_resel_cfg_t; cell_resel_cfg_t cell_resel_cfg = {}; float get_srxlev(float Qrxlevmeas); float get_squal(float Qqualmeas); /******************** * RRC Procedures *******************/ enum class cs_result_t { changed_cell, same_cell, no_cell }; // RRC procedures (fwd declared) class cell_search_proc; class si_acquire_proc; class serving_cell_config_proc; class cell_selection_proc; class connection_setup_proc; class connection_request_proc; class connection_reconf_no_ho_proc; class plmn_search_proc; class process_pcch_proc; class go_idle_proc; class cell_reselection_proc; class connection_reest_proc; class ho_proc; srsran::proc_t cell_searcher; srsran::proc_t si_acquirer; srsran::proc_t serv_cell_cfg; srsran::proc_t cell_selector; srsran::proc_t idle_setter; srsran::proc_t pcch_processor; srsran::proc_t conn_req_proc; srsran::proc_t conn_setup_proc; srsran::proc_t plmn_searcher; srsran::proc_t cell_reselector; srsran::proc_t connection_reest; srsran::proc_t ho_handler; srsran::proc_t conn_recfg_proc; srsran::proc_manager_list_t callback_list; bool cell_selection_criteria(float rsrp, float rsrq = 0); void cell_reselection(float rsrp, float rsrq); std::vector ue_required_sibs; srsran::plmn_id_t selected_plmn_id = {}; bool plmn_is_selected = false; bool security_is_activated = false; // RLC interface void max_retx_attempted(); void protocol_failure(); // RRC NR interface void nr_scg_failure_information(const srsran::scg_failure_cause_t cause); void nr_notify_reconfiguration_failure(); // Senders void send_con_request(srsran::establishment_cause_t cause); void send_con_restablish_request(asn1::rrc::reest_cause_e cause, uint16_t rnti, uint16_t pci, uint32_t cellid); void send_con_restablish_complete(); void send_con_setup_complete(srsran::unique_byte_buffer_t nas_msg); void send_ul_info_transfer(srsran::unique_byte_buffer_t nas_msg); void send_security_mode_complete(); void send_rrc_con_reconfig_complete(bool contains_nr_complete = false); // Parsers void process_pdu(uint32_t lcid, srsran::unique_byte_buffer_t pdu); void parse_dl_ccch(srsran::unique_byte_buffer_t pdu); void parse_dl_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu); void parse_dl_info_transfer(uint32_t lcid, srsran::unique_byte_buffer_t pdu); void parse_pdu_bcch_dlsch(srsran::unique_byte_buffer_t pdu); void parse_pdu_mch(uint32_t lcid, srsran::unique_byte_buffer_t pdu); // Helpers void con_reconfig_failed(); bool con_reconfig_ho(const asn1::rrc::rrc_conn_recfg_s& reconfig); void ho_failed(); void start_go_idle(); void handle_rrc_connection_release(const asn1::rrc::rrc_conn_release_s& release); void start_rrc_redirect(uint32_t new_dl_earfcn); void radio_link_failure_push_cmd(); void radio_link_failure_process(); void leave_connected(); void stop_timers(); void start_con_restablishment(asn1::rrc::reest_cause_e cause); void log_rr_config_common(); void log_phy_config_dedicated(); void log_mac_config_dedicated(); void apply_rr_config_common(asn1::rrc::rr_cfg_common_s* config, bool send_lower_layers); bool apply_rr_config_dedicated(const asn1::rrc::rr_cfg_ded_s* cnfg, bool is_handover = false); bool apply_rr_config_dedicated_on_ho_complete(const asn1::rrc::rr_cfg_ded_s& cnfg); void apply_scell_config(asn1::rrc::rrc_conn_recfg_r8_ies_s* reconfig_r8, bool enable_cqi); bool apply_scell_config_on_ho_complete(const asn1::rrc::rrc_conn_recfg_r8_ies_s& reconfig_r8); void apply_phy_config_dedicated(const asn1::rrc::phys_cfg_ded_s& phy_cnfg, bool is_handover); void apply_phy_scell_config(const asn1::rrc::scell_to_add_mod_r10_s& scell_config, bool enable_cqi); void apply_mac_config_dedicated_default(); void handle_sib1(); void handle_sib2(); void handle_sib3(); void handle_sib13(); void handle_con_setup(const asn1::rrc::rrc_conn_setup_s& setup); void handle_con_reest(const asn1::rrc::rrc_conn_reest_s& setup); void handle_rrc_con_reconfig(uint32_t lcid, const asn1::rrc::rrc_conn_recfg_s& reconfig); void handle_ue_capability_enquiry(const asn1::rrc::ue_cap_enquiry_s& enquiry); void handle_ue_info_request(const ue_info_request_r9_s& request); void add_srb(const asn1::rrc::srb_to_add_mod_s& srb_cnfg); void add_drb(const asn1::rrc::drb_to_add_mod_s& drb_cnfg); void release_drb(uint32_t drb_id); uint32_t get_lcid_for_drb_id(const uint32_t& drb_id); uint32_t get_lcid_for_eps_bearer(const uint32_t& eps_bearer_id); uint32_t get_drb_id_for_eps_bearer(const uint32_t& eps_bearer_id); uint32_t get_eps_bearer_id_for_drb_id(const uint32_t& drb_id); void add_mrb(uint32_t lcid, uint32_t port); // Helpers for setting default values void set_phy_default_pucch_srs(); void set_phy_default(); void set_mac_default(); void set_rrc_default(); bool nr_reconfiguration_proc(const asn1::rrc::rrc_conn_recfg_r8_ies_s& rx_recfg, bool* has_5g_nr_reconfig); // Helpers for nr communicaiton asn1::rrc::ue_cap_rat_container_s get_eutra_nr_capabilities(); asn1::rrc::ue_cap_rat_container_s get_nr_capabilities(); }; } // namespace srsue #endif // SRSUE_RRC_H