Release UE if no activity in DRB (#2658)

* Count user activity with DRB only and SRBs for initial procedures. Add counter to release user after max KO in UL.
master
Ismael Gomez 4 years ago committed by GitHub
parent 4838cd2f5e
commit 77b11b82ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -102,7 +102,9 @@ public:
/* Radio Link failure */ /* Radio Link failure */
virtual int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) = 0; 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 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; virtual bool is_paging_opportunity(uint32_t tti, uint32_t* payload_len) = 0;
///< Provide packed SIB to MAC (buffer is managed by RRC) ///< Provide packed SIB to MAC (buffer is managed by RRC)

@ -94,6 +94,7 @@ struct general_args_t {
std::string eia_pref_list; std::string eia_pref_list;
std::string eea_pref_list; std::string eea_pref_list;
uint32_t max_mac_dl_kos; uint32_t max_mac_dl_kos;
uint32_t max_mac_ul_kos;
}; };
struct all_args_t { struct all_args_t {

@ -68,7 +68,9 @@ public:
// rrc_interface_mac // rrc_interface_mac
int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) override; 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 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; 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; uint8_t* read_pdu_bcch_dlsch(const uint8_t cc_idx, const uint32_t sib_index) override;
@ -184,6 +186,7 @@ private:
typedef struct { typedef struct {
uint16_t rnti; uint16_t rnti;
uint32_t lcid; uint32_t lcid;
uint32_t arg;
srsran::unique_byte_buffer_t pdu; srsran::unique_byte_buffer_t pdu;
} rrc_pdu; } rrc_pdu;
@ -192,7 +195,8 @@ private:
const static uint32_t LCID_REL_USER = 0xffff0002; const static uint32_t LCID_REL_USER = 0xffff0002;
const static uint32_t LCID_ACT_USER = 0xffff0004; const static uint32_t LCID_ACT_USER = 0xffff0004;
const static uint32_t LCID_RTX_USER = 0xffff0005; 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; bool running = false;
srsran::dyn_blocking_queue<rrc_pdu> rx_pdu_queue; srsran::dyn_blocking_queue<rrc_pdu> rx_pdu_queue;

@ -60,6 +60,7 @@ struct rrc_cfg_t {
cell_list_t cell_list; cell_list_t cell_list;
cell_list_t cell_list_nr; cell_list_t cell_list_nr;
uint32_t max_mac_dl_kos; uint32_t max_mac_dl_kos;
uint32_t max_mac_ul_kos;
}; };
constexpr uint32_t UE_PCELL_CC_IDX = 0; constexpr uint32_t UE_PCELL_CC_IDX = 0;

@ -42,7 +42,8 @@ public:
void set_activity_timeout(const activity_timeout_type_t type); void set_activity_timeout(const activity_timeout_type_t type);
void set_rlf_timeout(); void set_rlf_timeout();
void set_activity(); 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 activity_timer_expired(const activity_timeout_type_t type);
void rlf_timer_expired(); void rlf_timer_expired();
void max_retx_reached(); void max_retx_reached();
@ -185,7 +186,9 @@ private:
const static uint32_t UE_PCELL_CC_IDX = 0; 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; ue_cell_ded_list ue_cell_list;
bearer_cfg_handler bearer_list; bearer_cfg_handler bearer_list;

@ -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 // Set max number of KOs
rrc_cfg_->max_mac_dl_kos = args_->general.max_mac_dl_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 // Set sync queue capacity to 1 for ZMQ
if (args_->rf.device_name == "zmq") { if (args_->rf.device_name == "zmq") {

@ -214,7 +214,9 @@ void parse_args(all_args_t* args, int argc, char* argv[])
("expert.eea_pref_list", bpo::value<string>(&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.eea_pref_list", bpo::value<string>(&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<string>(&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.eia_pref_list", bpo::value<string>(&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<uint32_t>(&args->stack.mac.max_nof_ues)->default_value(8), "Maximum number of connected UEs") ("expert.max_nof_ues", bpo::value<uint32_t>(&args->stack.mac.max_nof_ues)->default_value(8), "Maximum number of connected UEs")
("expert.max_mac_dl_kos", bpo::value<uint32_t>(&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<uint32_t>(&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<uint32_t>(&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 section
("embms.enable", bpo::value<bool>(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB") ("embms.enable", bpo::value<bool>(&args->stack.embms.enable)->default_value(false), "Enables MBMS in the eNB")

@ -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); int nof_bytes = scheduler.dl_ack_info(tti_rx, rnti, enb_cc_idx, tb_idx, ack);
ue_db[rnti]->metrics_tx(ack, nof_bytes); ue_db[rnti]->metrics_tx(ack, nof_bytes);
if (ack) { rrc_h->set_radiolink_dl_state(rnti, 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);
}
return SRSRAN_SUCCESS; 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]->set_tti(tti_rx);
ue_db[rnti]->metrics_rx(crc, nof_bytes); ue_db[rnti]->metrics_rx(crc, nof_bytes);
rrc_h->set_radiolink_ul_state(rnti, crc);
// Scheduler uses eNB's CC mapping // Scheduler uses eNB's CC mapping
return scheduler.ul_crc_info(tti_rx, rnti, enb_cc_idx, crc); return scheduler.ul_crc_info(tti_rx, rnti, enb_cc_idx, crc);
} }

@ -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 // 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()); // 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 // Indicate DRB activity in UL to RRC
if (mac_msg_ul.get()->get_payload_size() > 64) { // do not count RLC status messages only if (mac_msg_ul.get()->get_sdu_lcid() > 2) {
rrc->set_activity_user(rnti, true); rrc->set_activity_user(rnti);
logger.debug("UL activity rnti=0x%x, n_bytes=%d", rnti, nof_bytes); 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 if (n > 0) { // new SDU could be added
sdu_len -= n; sdu_len -= n;
logger.debug("SDU: rnti=0x%x, lcid=%d, nbytes=%d, rem_len=%d", rnti, lcid, n, sdu_len); 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 { } else {
logger.debug("Could not add SDU lcid=%d nbytes=%d, space=%d", lcid, sdu_len, sdu_space); logger.debug("Could not add SDU lcid=%d nbytes=%d, space=%d", lcid, sdu_len, sdu_space);
pdu->del_subh(); pdu->del_subh();

@ -90,7 +90,7 @@ void rrc::stop()
{ {
if (running) { if (running) {
running = false; 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)); rx_pdu_queue.push_blocking(std::move(p));
} }
users.clear(); 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; 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; // embed parameters in arg value
if (ack_info) { rrc_pdu p = {rnti, LCID_RADLINK_DL, crc_res, nullptr};
p = {rnti, LCID_ACT_USER, nullptr};
} else { if (not rx_pdu_queue.try_push(std::move(p))) {
p = {rnti, LCID_MAC_KO_USER, nullptr}; 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))) { if (not rx_pdu_queue.try_push(std::move(p))) {
logger.error("Failed to push UE activity command to RRC queue"); 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) 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))) { if (not rx_pdu_queue.try_push(std::move(p))) {
logger.error("Failed to push UE remove command to RRC queue"); 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) 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))) { if (not rx_pdu_queue.try_push(std::move(p))) {
logger.error("Failed to push max Retx event to RRC queue"); 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) 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))) { if (not rx_pdu_queue.try_push(std::move(p))) {
logger.error("Failed to push Release command to RRC queue"); 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) 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))) { if (not rx_pdu_queue.try_push(std::move(p))) {
logger.error("Failed to push Release command to RRC queue"); logger.error("Failed to push Release command to RRC queue");
} }
@ -1007,8 +1022,11 @@ void rrc::tti_clock()
case LCID_ACT_USER: case LCID_ACT_USER:
user_it->second->set_activity(); user_it->second->set_activity();
break; break;
case LCID_MAC_KO_USER: case LCID_RADLINK_DL:
user_it->second->mac_ko_activity(); user_it->second->set_radiolink_dl_state(p.arg);
break;
case LCID_RADLINK_UL:
user_it->second->set_radiolink_ul_state(p.arg);
break; break;
case LCID_RTX_USER: case LCID_RTX_USER:
user_it->second->max_retx_reached(); user_it->second->max_retx_reached();

@ -88,15 +88,24 @@ void rrc::ue::set_activity()
{ {
// re-start activity timer with current timeout value // re-start activity timer with current timeout value
activity_timer.run(); activity_timer.run();
rlf_timer.stop();
consecutive_kos = 0;
if (parent) { if (parent) {
parent->logger.debug("Activity registered for rnti=0x%x (timeout_value=%dms)", rnti, activity_timer.duration()); 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. // Count KOs in MAC and trigger release if it goes above a certain value.
// This is done to detect out-of-coverage UEs // This is done to detect out-of-coverage UEs
if (rlf_timer.is_running()) { if (rlf_timer.is_running()) {
@ -104,9 +113,36 @@ void rrc::ue::mac_ko_activity()
return; return;
} }
consecutive_kos++; consecutive_kos_dl++;
if (consecutive_kos > parent->cfg.max_mac_dl_kos) { if (consecutive_kos_dl > parent->cfg.max_mac_dl_kos) {
parent->logger.info("Max KOs reached, triggering release rnti=0x%x", rnti); 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(); 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) void rrc::ue::parse_ul_dcch(uint32_t lcid, srsran::unique_byte_buffer_t pdu)
{ {
set_activity();
ul_dcch_msg_s ul_dcch_msg; ul_dcch_msg_s ul_dcch_msg;
asn1::cbit_ref bref(pdu->msg, pdu->N_bytes); asn1::cbit_ref bref(pdu->msg, pdu->N_bytes);
if (ul_dcch_msg.unpack(bref) != asn1::SRSASN_SUCCESS or 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: case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_setup_complete:
save_ul_message(std::move(original_pdu)); save_ul_message(std::move(original_pdu));
handle_rrc_con_setup_complete(&ul_dcch_msg.msg.c1().rrc_conn_setup_complete(), std::move(pdu)); handle_rrc_con_setup_complete(&ul_dcch_msg.msg.c1().rrc_conn_setup_complete(), std::move(pdu));
set_activity();
break; break;
case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete: case ul_dcch_msg_type_c::c1_c_::types::rrc_conn_reest_complete:
save_ul_message(std::move(original_pdu)); save_ul_message(std::move(original_pdu));
handle_rrc_con_reest_complete(&ul_dcch_msg.msg.c1().rrc_conn_reest_complete(), std::move(pdu)); handle_rrc_con_reest_complete(&ul_dcch_msg.msg.c1().rrc_conn_reest_complete(), std::move(pdu));
set_activity();
break; break;
case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer: case ul_dcch_msg_type_c::c1_c_::types::ul_info_transfer:
pdu->N_bytes = ul_dcch_msg.msg.c1() pdu->N_bytes = ul_dcch_msg.msg.c1()

@ -34,7 +34,9 @@ struct rrc_dummy : public rrc_interface_mac {
public: public:
int add_user(uint16_t rnti, const sched_interface::ue_cfg_t& init_ue_cfg) { return SRSRAN_SUCCESS; } 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 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; } 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; } uint8_t* read_pdu_bcch_dlsch(const uint8_t enb_cc_idx, const uint32_t sib_index) { return nullptr; }
}; };

Loading…
Cancel
Save