diff --git a/lib/include/srsran/interfaces/enb_rrc_interfaces.h b/lib/include/srsran/interfaces/enb_rrc_interfaces.h index 5c23a4b3f..b5133af9d 100644 --- a/lib/include/srsran/interfaces/enb_rrc_interfaces.h +++ b/lib/include/srsran/interfaces/enb_rrc_interfaces.h @@ -102,7 +102,9 @@ public: /* Radio Link failure */ virtual int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) = 0; virtual void upd_user(uint16_t new_rnti, uint16_t old_rnti) = 0; - virtual void set_activity_user(uint16_t rnti, bool ack_info) = 0; + virtual void set_activity_user(uint16_t rnti) = 0; + virtual void set_radiolink_dl_state(uint16_t rnti, bool crc_res) = 0; + virtual void set_radiolink_ul_state(uint16_t rnti, bool crc_res) = 0; virtual bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) = 0; ///< Provide packed SIB to MAC (buffer is managed by RRC) diff --git a/srsenb/hdr/enb.h b/srsenb/hdr/enb.h index 97e7b16d7..b38d8397b 100644 --- a/srsenb/hdr/enb.h +++ b/srsenb/hdr/enb.h @@ -94,6 +94,7 @@ struct general_args_t { std::string eia_pref_list; std::string eea_pref_list; uint32_t max_mac_dl_kos; + uint32_t max_mac_ul_kos; }; struct all_args_t { diff --git a/srsenb/hdr/stack/rrc/rrc.h b/srsenb/hdr/stack/rrc/rrc.h index c43638768..cf3efaa34 100644 --- a/srsenb/hdr/stack/rrc/rrc.h +++ b/srsenb/hdr/stack/rrc/rrc.h @@ -68,7 +68,9 @@ public: // rrc_interface_mac int 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, bool ack_info) override; + void set_activity_user(uint16_t rnti) override; + void set_radiolink_dl_state(uint16_t rnti, bool crc_res) override; + void set_radiolink_ul_state(uint16_t rnti, bool crc_res) 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; @@ -184,6 +186,7 @@ private: typedef struct { uint16_t rnti; uint32_t lcid; + uint32_t arg; srsran::unique_byte_buffer_t pdu; } rrc_pdu; @@ -192,7 +195,8 @@ private: const static uint32_t LCID_REL_USER = 0xffff0002; const static uint32_t LCID_ACT_USER = 0xffff0004; const static uint32_t LCID_RTX_USER = 0xffff0005; - const static uint32_t LCID_MAC_KO_USER = 0xffff0006; + const static uint32_t LCID_RADLINK_DL = 0xffff0006; + const static uint32_t LCID_RADLINK_UL = 0xffff0007; bool running = false; srsran::dyn_blocking_queue rx_pdu_queue; diff --git a/srsenb/hdr/stack/rrc/rrc_config.h b/srsenb/hdr/stack/rrc/rrc_config.h index dc25d3930..041f492e8 100644 --- a/srsenb/hdr/stack/rrc/rrc_config.h +++ b/srsenb/hdr/stack/rrc/rrc_config.h @@ -60,6 +60,7 @@ struct rrc_cfg_t { cell_list_t cell_list; cell_list_t cell_list_nr; uint32_t max_mac_dl_kos; + uint32_t max_mac_ul_kos; }; constexpr uint32_t UE_PCELL_CC_IDX = 0; diff --git a/srsenb/hdr/stack/rrc/rrc_ue.h b/srsenb/hdr/stack/rrc/rrc_ue.h index 6801b6ace..8e48c7816 100644 --- a/srsenb/hdr/stack/rrc/rrc_ue.h +++ b/srsenb/hdr/stack/rrc/rrc_ue.h @@ -42,7 +42,8 @@ public: void set_activity_timeout(const activity_timeout_type_t type); void set_rlf_timeout(); void set_activity(); - void mac_ko_activity(); + void set_radiolink_dl_state(bool crc_res); + void set_radiolink_ul_state(bool crc_res); void activity_timer_expired(const activity_timeout_type_t type); void rlf_timer_expired(); void max_retx_reached(); @@ -185,7 +186,9 @@ private: const static uint32_t UE_PCELL_CC_IDX = 0; - uint32_t consecutive_kos = 0; + // consecutive KO counter for DL and UL + uint32_t consecutive_kos_dl = 0; + uint32_t consecutive_kos_ul = 0; ue_cell_ded_list ue_cell_list; bearer_cfg_handler bearer_list; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 94af5ffb8..fb1912067 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1147,6 +1147,7 @@ int set_derived_args(all_args_t* args_, rrc_cfg_t* rrc_cfg_, phy_cfg_t* phy_cfg_ // Set max number of KOs rrc_cfg_->max_mac_dl_kos = args_->general.max_mac_dl_kos; + rrc_cfg_->max_mac_ul_kos = args_->general.max_mac_ul_kos; // Set sync queue capacity to 1 for ZMQ if (args_->rf.device_name == "zmq") { diff --git a/srsenb/src/main.cc b/srsenb/src/main.cc index 78cbc9ab8..123a3c4eb 100644 --- a/srsenb/src/main.cc +++ b/srsenb/src/main.cc @@ -214,7 +214,9 @@ void parse_args(all_args_t* args, int argc, char* argv[]) ("expert.eea_pref_list", bpo::value(&args->general.eea_pref_list)->default_value("EEA0, EEA2, EEA1"), "Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).") ("expert.eia_pref_list", bpo::value(&args->general.eia_pref_list)->default_value("EIA2, EIA1, EIA0"), "Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0).") ("expert.max_nof_ues", bpo::value(&args->stack.mac.max_nof_ues)->default_value(8), "Maximum number of connected UEs") - ("expert.max_mac_dl_kos", bpo::value(&args->general.max_mac_dl_kos)->default_value(100), "Maximum number of consecutive KOs before triggering the UE's release") + ("expert.max_mac_dl_kos", bpo::value(&args->general.max_mac_dl_kos)->default_value(100), "Maximum number of consecutive KOs in DL before triggering the UE's release") + ("expert.max_mac_ul_kos", bpo::value(&args->general.max_mac_ul_kos)->default_value(100), "Maximum number of consecutive KOs in UL before triggering the UE's release") + // eMBMS section ("embms.enable", bpo::value(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB") diff --git a/srsenb/src/stack/mac/mac.cc b/srsenb/src/stack/mac/mac.cc index 994d0831e..b3f5d3fcc 100644 --- a/srsenb/src/stack/mac/mac.cc +++ b/srsenb/src/stack/mac/mac.cc @@ -301,14 +301,8 @@ int mac::ack_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t int nof_bytes = scheduler.dl_ack_info(tti_rx, rnti, enb_cc_idx, tb_idx, ack); ue_db[rnti]->metrics_tx(ack, nof_bytes); - if (ack) { - if (nof_bytes > 64) { // do not count RLC status messages only - rrc_h->set_activity_user(rnti, true); - logger.info("DL activity rnti=0x%x, n_bytes=%d", rnti, nof_bytes); - } - } else { - rrc_h->set_activity_user(rnti, false); - } + rrc_h->set_radiolink_dl_state(rnti, ack); + return SRSRAN_SUCCESS; } @@ -324,6 +318,8 @@ int mac::crc_info(uint32_t tti_rx, uint16_t rnti, uint32_t enb_cc_idx, uint32_t ue_db[rnti]->set_tti(tti_rx); ue_db[rnti]->metrics_rx(crc, nof_bytes); + rrc_h->set_radiolink_ul_state(rnti, crc); + // Scheduler uses eNB's CC mapping return scheduler.ul_crc_info(tti_rx, rnti, enb_cc_idx, crc); } diff --git a/srsenb/src/stack/mac/ue.cc b/srsenb/src/stack/mac/ue.cc index 0803ad0f1..4cbd7d66c 100644 --- a/srsenb/src/stack/mac/ue.cc +++ b/srsenb/src/stack/mac/ue.cc @@ -383,9 +383,9 @@ void ue::process_pdu(uint8_t* pdu, uint32_t nof_bytes, srsran::pdu_queue::channe // Indicate scheduler to update BSR counters // sched->ul_recv_len(rnti, mac_msg_ul.get()->get_sdu_lcid(), mac_msg_ul.get()->get_payload_size()); - // Indicate RRC about successful activity if valid RLC message is received - if (mac_msg_ul.get()->get_payload_size() > 64) { // do not count RLC status messages only - rrc->set_activity_user(rnti, true); + // Indicate DRB activity in UL to RRC + if (mac_msg_ul.get()->get_sdu_lcid() > 2) { + rrc->set_activity_user(rnti); logger.debug("UL activity rnti=0x%x, n_bytes=%d", rnti, nof_bytes); } @@ -517,6 +517,13 @@ void ue::allocate_sdu(srsran::sch_pdu* pdu, uint32_t lcid, uint32_t total_sdu_le if (n > 0) { // new SDU could be added sdu_len -= n; logger.debug("SDU: rnti=0x%x, lcid=%d, nbytes=%d, rem_len=%d", rnti, lcid, n, sdu_len); + + // Indicate DRB activity in DL to RRC + if (lcid > 2) { + rrc->set_activity_user(rnti); + logger.debug("DL activity rnti=0x%x, n_bytes=%d", rnti, sdu_len); + } + } else { logger.debug("Could not add SDU lcid=%d nbytes=%d, space=%d", lcid, sdu_len, sdu_space); pdu->del_subh(); diff --git a/srsenb/src/stack/rrc/rrc.cc b/srsenb/src/stack/rrc/rrc.cc index 5e404fb6f..c4015e277 100644 --- a/srsenb/src/stack/rrc/rrc.cc +++ b/srsenb/src/stack/rrc/rrc.cc @@ -90,7 +90,7 @@ void rrc::stop() { if (running) { running = false; - rrc_pdu p = {0, LCID_EXIT, nullptr}; + rrc_pdu p = {0, LCID_EXIT, false, nullptr}; rx_pdu_queue.push_blocking(std::move(p)); } users.clear(); @@ -126,14 +126,29 @@ uint8_t* rrc::read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index return nullptr; } -void rrc::set_activity_user(uint16_t rnti, bool ack_info) +void rrc::set_radiolink_dl_state(uint16_t rnti, bool crc_res) { - rrc_pdu p; - if (ack_info) { - p = {rnti, LCID_ACT_USER, nullptr}; - } else { - p = {rnti, LCID_MAC_KO_USER, nullptr}; + // embed parameters in arg value + rrc_pdu p = {rnti, LCID_RADLINK_DL, crc_res, nullptr}; + + if (not rx_pdu_queue.try_push(std::move(p))) { + logger.error("Failed to push UE activity command to RRC queue"); + } +} + +void rrc::set_radiolink_ul_state(uint16_t rnti, bool crc_res) +{ + // embed parameters in arg value + rrc_pdu p = {rnti, LCID_RADLINK_UL, crc_res, nullptr}; + + if (not rx_pdu_queue.try_push(std::move(p))) { + logger.error("Failed to push UE activity command to RRC queue"); } +} + +void rrc::set_activity_user(uint16_t rnti) +{ + rrc_pdu p = {rnti, LCID_ACT_USER, false, nullptr}; if (not rx_pdu_queue.try_push(std::move(p))) { logger.error("Failed to push UE activity command to RRC queue"); @@ -142,7 +157,7 @@ void rrc::set_activity_user(uint16_t rnti, bool ack_info) void rrc::rem_user_thread(uint16_t rnti) { - rrc_pdu p = {rnti, LCID_REM_USER, nullptr}; + rrc_pdu p = {rnti, LCID_REM_USER, false, nullptr}; if (not rx_pdu_queue.try_push(std::move(p))) { logger.error("Failed to push UE remove command to RRC queue"); } @@ -155,7 +170,7 @@ uint32_t rrc::get_nof_users() void rrc::max_retx_attempted(uint16_t rnti) { - rrc_pdu p = {rnti, LCID_RTX_USER, nullptr}; + rrc_pdu p = {rnti, LCID_RTX_USER, false, nullptr}; if (not rx_pdu_queue.try_push(std::move(p))) { logger.error("Failed to push max Retx event to RRC queue"); } @@ -253,7 +268,7 @@ void rrc::send_rrc_connection_reject(uint16_t rnti) *******************************************************************************/ void rrc::write_pdu(uint16_t rnti, uint32_t lcid, srsran::unique_byte_buffer_t pdu) { - rrc_pdu p = {rnti, lcid, std::move(pdu)}; + rrc_pdu p = {rnti, lcid, false, std::move(pdu)}; if (not rx_pdu_queue.try_push(std::move(p))) { logger.error("Failed to push Release command to RRC queue"); } @@ -290,7 +305,7 @@ void rrc::write_dl_info(uint16_t rnti, srsran::unique_byte_buffer_t sdu) void rrc::release_ue(uint16_t rnti) { - rrc_pdu p = {rnti, LCID_REL_USER, nullptr}; + rrc_pdu p = {rnti, LCID_REL_USER, false, nullptr}; if (not rx_pdu_queue.try_push(std::move(p))) { logger.error("Failed to push Release command to RRC queue"); } @@ -1007,8 +1022,11 @@ void rrc::tti_clock() case LCID_ACT_USER: user_it->second->set_activity(); break; - case LCID_MAC_KO_USER: - user_it->second->mac_ko_activity(); + case LCID_RADLINK_DL: + user_it->second->set_radiolink_dl_state(p.arg); + break; + case LCID_RADLINK_UL: + user_it->second->set_radiolink_ul_state(p.arg); break; case LCID_RTX_USER: user_it->second->max_retx_reached(); diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 8e82ba875..fefdb70e6 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -88,15 +88,24 @@ void rrc::ue::set_activity() { // re-start activity timer with current timeout value activity_timer.run(); - rlf_timer.stop(); - consecutive_kos = 0; if (parent) { parent->logger.debug("Activity registered for rnti=0x%x (timeout_value=%dms)", rnti, activity_timer.duration()); } } -void rrc::ue::mac_ko_activity() +void rrc::ue::set_radiolink_dl_state(bool crc_res) { + parent->logger.debug( + "Radio-Link downlink state for rnti=0x%x: crc_res=%d, consecutive_ko=%d", rnti, crc_res, consecutive_kos_dl); + + // If received OK, restart counter and stop RLF timer + if (crc_res) { + consecutive_kos_dl = 0; + consecutive_kos_ul = 0; + rlf_timer.stop(); + return; + } + // Count KOs in MAC and trigger release if it goes above a certain value. // This is done to detect out-of-coverage UEs if (rlf_timer.is_running()) { @@ -104,9 +113,36 @@ void rrc::ue::mac_ko_activity() return; } - consecutive_kos++; - if (consecutive_kos > parent->cfg.max_mac_dl_kos) { - parent->logger.info("Max KOs reached, triggering release rnti=0x%x", rnti); + consecutive_kos_dl++; + if (consecutive_kos_dl > parent->cfg.max_mac_dl_kos) { + parent->logger.info("Max KOs in DL reached, triggering release rnti=0x%x", rnti); + max_retx_reached(); + } +} + +void rrc::ue::set_radiolink_ul_state(bool crc_res) +{ + parent->logger.debug( + "Radio-Link uplink state for rnti=0x%x: crc_res=%d, consecutive_ko=%d", rnti, crc_res, consecutive_kos_ul); + + // If received OK, restart counter and stop RLF timer + if (crc_res) { + consecutive_kos_dl = 0; + consecutive_kos_ul = 0; + rlf_timer.stop(); + return; + } + + // Count KOs in MAC and trigger release if it goes above a certain value. + // This is done to detect out-of-coverage UEs + if (rlf_timer.is_running()) { + // RLF timer already running, no need to count KOs + return; + } + + consecutive_kos_ul++; + if (consecutive_kos_ul > parent->cfg.max_mac_ul_kos) { + parent->logger.info("Max KOs in UL reached, triggering release rnti=0x%x", rnti); max_retx_reached(); } } @@ -227,8 +263,6 @@ bool rrc::ue::is_idle() void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) { - set_activity(); - ul_dcch_msg_s ul_dcch_msg; asn1::cbit_ref bref(pdu->msg, pdu->N_bytes); if (ul_dcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or @@ -252,10 +286,12 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu) case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_setup_complete: save_ul_message(std::move(original_pdu)); handle_rrc_con_setup_complete(&ul_dcch_msg.msg.c1().rrc_conn_setup_complete(), std::move(pdu)); + set_activity(); break; case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete: save_ul_message(std::move(original_pdu)); handle_rrc_con_reest_complete(&ul_dcch_msg.msg.c1().rrc_conn_reest_complete(), std::move(pdu)); + set_activity(); break; case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer: pdu->N_bytes = ul_dcch_msg.msg.c1() diff --git a/srsenb/test/mac/sched_test_common.h b/srsenb/test/mac/sched_test_common.h index 17ddbb703..591d4656d 100644 --- a/srsenb/test/mac/sched_test_common.h +++ b/srsenb/test/mac/sched_test_common.h @@ -34,7 +34,9 @@ struct rrc_dummy : public rrc_interface_mac { public: int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) { return SRSRAN_SUCCESS; } void upd_user(uint16_t new_rnti, uint16_t old_rnti) {} - void set_activity_user(uint16_t rnti, bool ack_info) {} + void set_activity_user(uint16_t rnti) {} + void set_radiolink_ul_state(uint16_t rnti, bool crc_res) {} + void set_radiolink_dl_state(uint16_t rnti, bool crc_res) {} bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) { return false; } uint8_t* read_pdu_bcch_dlsch(const uint8_t enb_cc_idx, const uint32_t sib_index) { return nullptr; } };