/* * Copyright 2013-2020 Software Radio Systems Limited * * This file is part of srsLTE. * * srsLTE 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. * * srsLTE 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 SRSENB_RRC_H #define SRSENB_RRC_H #include "rrc_bearer_cfg.h" #include "rrc_cell_cfg.h" #include "rrc_metrics.h" #include "srsenb/hdr/stack/upper/common_enb.h" #include "srslte/common/block_queue.h" #include "srslte/common/buffer_pool.h" #include "srslte/common/common.h" #include "srslte/common/logmap.h" #include "srslte/common/stack_procedure.h" #include "srslte/common/timeout.h" #include "srslte/interfaces/enb_interfaces.h" #include #include namespace srsenb { static const char rrc_state_text[RRC_STATE_N_ITEMS][100] = {"IDLE", "WAIT FOR CON SETUP COMPLETE", "WAIT FOR SECURITY MODE COMPLETE", "WAIT FOR UE CAPABILITIY INFORMATION", "WAIT FOR CON RECONF COMPLETE", "RRC CONNECTED", "RELEASE REQUEST"}; class rrc final : public rrc_interface_pdcp, public rrc_interface_mac, public rrc_interface_rlc, public rrc_interface_s1ap { public: rrc(); ~rrc(); void init(const rrc_cfg_t& cfg_, phy_interface_rrc_lte* phy, mac_interface_rrc* mac, rlc_interface_rrc* rlc, pdcp_interface_rrc* pdcp, s1ap_interface_rrc* s1ap, gtpu_interface_rrc* gtpu, srslte::timer_handler* timers_); void stop(); void get_metrics(rrc_metrics_t& m); void tti_clock(); // rrc_interface_mac void rl_failure(uint16_t rnti) override; void add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) override; void upd_user(uint16_t new_rnti, uint16_t old_rnti) override; void set_activity_user(uint16_t rnti) override; bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) override; uint8_t* read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index) override; // rrc_interface_rlc void read_pdu_pcch(uint8_t* payload, uint32_t buffer_size) override; void max_retx_attempted(uint16_t rnti) override; // rrc_interface_s1ap void write_dl_info(uint16_t rnti, srslte::unique_byte_buffer_t sdu) override; void release_complete(uint16_t rnti) override; bool setup_ue_ctxt(uint16_t rnti, const asn1::s1ap::init_context_setup_request_s& msg) override; bool modify_ue_ctxt(uint16_t rnti, const asn1::s1ap::ue_context_mod_request_s& msg) override; bool setup_ue_erabs(uint16_t rnti, const asn1::s1ap::erab_setup_request_s& msg) override; bool release_erabs(uint32_t rnti) override; void add_paging_id(uint32_t ueid, const asn1::s1ap::ue_paging_id_c& UEPagingID) override; void ho_preparation_complete(uint16_t rnti, bool is_success, srslte::unique_byte_buffer_t rrc_container) override; // rrc_interface_pdcp void write_pdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu) override; uint32_t get_nof_users(); // logging typedef enum { Rx = 0, Tx } direction_t; template void log_rrc_message(const std::string& source, const direction_t dir, const srslte::byte_buffer_t* pdu, const T& msg, const std::string& msg_type) { if (rrc_log->get_level() == srslte::LOG_LEVEL_INFO) { rrc_log->info("%s - %s %s (%d B)\n", source.c_str(), dir == Tx ? "Tx" : "Rx", msg_type.c_str(), pdu->N_bytes); } else if (rrc_log->get_level() >= srslte::LOG_LEVEL_DEBUG) { asn1::json_writer json_writer; msg.to_json(json_writer); rrc_log->debug_hex(pdu->msg, pdu->N_bytes, "%s - %s %s (%d B)\n", source.c_str(), dir == Tx ? "Tx" : "Rx", msg_type.c_str(), pdu->N_bytes); rrc_log->debug_long("Content:\n%s\n", json_writer.to_string().c_str()); } } private: class ue; // args srslte::timer_handler* timers = nullptr; srslte::byte_buffer_pool* pool = nullptr; phy_interface_rrc_lte* phy = nullptr; mac_interface_rrc* mac = nullptr; rlc_interface_rrc* rlc = nullptr; pdcp_interface_rrc* pdcp = nullptr; gtpu_interface_rrc* gtpu = nullptr; s1ap_interface_rrc* s1ap = nullptr; srslte::log_ref rrc_log; // derived params std::unique_ptr cell_common_list; // state std::unique_ptr pucch_res_list; std::map > users; // NOTE: has to have fixed addr std::map pending_paging; void process_release_complete(uint16_t rnti); void process_rl_failure(uint16_t rnti); void rem_user(uint16_t rnti); uint32_t generate_sibs(); void configure_mbsfn_sibs(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13); void config_mac(); void parse_ul_dcch(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t pdu); void parse_ul_ccch(uint16_t rnti, srslte::unique_byte_buffer_t pdu); srslte::byte_buffer_t byte_buf_paging; typedef struct { uint16_t rnti; uint32_t lcid; srslte::unique_byte_buffer_t pdu; } rrc_pdu; const static uint32_t LCID_EXIT = 0xffff0000; const static uint32_t LCID_REM_USER = 0xffff0001; const static uint32_t LCID_REL_USER = 0xffff0002; const static uint32_t LCID_RLF_USER = 0xffff0003; const static uint32_t LCID_ACT_USER = 0xffff0004; bool running = false; static const int RRC_THREAD_PRIO = 65; srslte::block_queue rx_pdu_queue; asn1::rrc::mcch_msg_s mcch; bool enable_mbms = false; rrc_cfg_t cfg = {}; uint32_t nof_si_messages = 0; asn1::rrc::sib_type7_s sib7; class enb_mobility_handler; std::unique_ptr enb_mobility_cfg; void rem_user_thread(uint16_t rnti); std::mutex paging_mutex; }; } // namespace srsenb #endif // SRSENB_RRC_H