mirror of https://github.com/PentHertz/srsLTE.git
make user activity handling independent of system time
this commit removes the getsystime() call from the activity handling. it uses a single timer per UE to handle its activity. three different timer values exist. one for the Msg3 reception. This is like before and is quite low to quickly remove fake UEs from the RRC. The second is a generic value (set to 1s for now) that covers the entire UE configuration phase where multiple messages are sent back and forth until the UE is fully set up and the default bearer runs. From there on, the UE inactivity timer is used which may be much bigger than 1s.
This commit is contained in:
parent
e5ed6ac870
commit
fef6893ce4
|
@ -196,14 +196,6 @@ public:
|
|||
const T& msg,
|
||||
const std::string& msg_type);
|
||||
|
||||
// Notifier for user connect
|
||||
class connect_notifier
|
||||
{
|
||||
public:
|
||||
virtual void user_connected(uint16_t rnti) = 0;
|
||||
};
|
||||
void set_connect_notifer(connect_notifier* cnotifier);
|
||||
|
||||
class ue
|
||||
{
|
||||
public:
|
||||
|
@ -212,8 +204,17 @@ public:
|
|||
ue(rrc* outer_rrc, uint16_t rnti);
|
||||
bool is_connected();
|
||||
bool is_idle();
|
||||
bool is_timeout();
|
||||
|
||||
typedef enum {
|
||||
MSG3_RX_TIMEOUT = 0, ///< Msg3 has its own timeout to quickly remove fake UEs from random PRACHs
|
||||
UE_RESPONSE_RX_TIMEOUT, ///< General purpose timeout for responses to eNB requests
|
||||
UE_INACTIVITY_TIMEOUT, ///< UE inactivity timeout
|
||||
nulltype
|
||||
} activity_timeout_type_t;
|
||||
std::string to_string(const activity_timeout_type_t& type);
|
||||
void set_activity_timeout(const activity_timeout_type_t type);
|
||||
void set_activity();
|
||||
void activity_timer_expired();
|
||||
|
||||
uint32_t rl_failure();
|
||||
|
||||
|
@ -283,8 +284,7 @@ public:
|
|||
private:
|
||||
// args
|
||||
srslte::byte_buffer_pool* pool = nullptr;
|
||||
struct timeval t_last_activity;
|
||||
struct timeval t_ue_init;
|
||||
srslte::timer_handler::unique_timer activity_timer;
|
||||
|
||||
// cached for ease of context transfer
|
||||
asn1::rrc::rrc_conn_recfg_r8_ies_s last_rrc_conn_recfg;
|
||||
|
@ -357,13 +357,9 @@ private:
|
|||
// state
|
||||
std::map<uint16_t, std::unique_ptr<ue> > users; // NOTE: has to have fixed addr
|
||||
std::map<uint32_t, LIBLTE_S1AP_UEPAGINGID_STRUCT> pending_paging;
|
||||
srslte::timer_handler::unique_timer activity_monitor_timer;
|
||||
|
||||
std::vector<srslte::unique_byte_buffer_t> sib_buffer;
|
||||
|
||||
// user connect notifier
|
||||
connect_notifier* cnotifier;
|
||||
|
||||
void process_release_complete(uint16_t rnti);
|
||||
void process_rl_failure(uint16_t rnti);
|
||||
void rem_user(uint16_t rnti);
|
||||
|
@ -384,8 +380,6 @@ private:
|
|||
void enable_integrity(uint16_t rnti, uint32_t lcid);
|
||||
void enable_encryption(uint16_t rnti, uint32_t lcid);
|
||||
|
||||
void monitor_activity();
|
||||
|
||||
srslte::byte_buffer_t byte_buf_paging;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -64,7 +64,7 @@ enb::~enb() {}
|
|||
int enb::init(const all_args_t& args_)
|
||||
{
|
||||
// Init UE log
|
||||
log.init("UE ", logger);
|
||||
log.init("ENB ", logger);
|
||||
log.set_level(srslte::LOG_LEVEL_INFO);
|
||||
log.info("%s", get_build_string().c_str());
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ string config_file;
|
|||
|
||||
void parse_args(all_args_t* args, int argc, char* argv[])
|
||||
{
|
||||
|
||||
string enb_id;
|
||||
string cell_id;
|
||||
string tac;
|
||||
|
@ -134,7 +133,6 @@ void parse_args(all_args_t* args, int argc, char* argv[])
|
|||
("scheduler.max_aggr_level", bpo::value<int>(&args->stack.mac.sched.max_aggr_level)->default_value(-1), "Optional maximum aggregation level index (l=log2(L)) ")
|
||||
("scheduler.nof_ctrl_symbols", bpo::value<int>(&args->stack.mac.sched.nof_ctrl_symbols)->default_value(3), "Number of control symbols")
|
||||
|
||||
|
||||
/* Downlink Channel emulator section */
|
||||
("channel.dl.enable", bpo::value<bool>(&args->phy.dl_channel_args.enable)->default_value(false), "Enable/Disable internal Downlink channel emulator")
|
||||
("channel.dl.fading.enable", bpo::value<bool>(&args->phy.dl_channel_args.fading_enable)->default_value(false), "Enable/Disable Fading model")
|
||||
|
|
|
@ -38,7 +38,7 @@ using namespace asn1::rrc;
|
|||
|
||||
namespace srsenb {
|
||||
|
||||
rrc::rrc() : cnotifier(nullptr), nof_si_messages(0)
|
||||
rrc::rrc()
|
||||
{
|
||||
pending_paging.clear();
|
||||
}
|
||||
|
@ -63,7 +63,6 @@ void rrc::init(rrc_cfg_t* cfg_,
|
|||
s1ap = s1ap_;
|
||||
rrc_log = log_rrc;
|
||||
timers = timers_;
|
||||
cnotifier = nullptr;
|
||||
|
||||
pool = srslte::byte_buffer_pool::get_instance();
|
||||
|
||||
|
@ -83,22 +82,9 @@ void rrc::init(rrc_cfg_t* cfg_,
|
|||
|
||||
bzero(&sr_sched, sizeof(sr_sched_t));
|
||||
|
||||
// run active monitor timer in a 10ms loop
|
||||
activity_monitor_timer = timers->get_unique_timer();
|
||||
activity_monitor_timer.set(10, [this](uint32_t tid) {
|
||||
monitor_activity();
|
||||
activity_monitor_timer.run();
|
||||
});
|
||||
activity_monitor_timer.run();
|
||||
|
||||
running = true;
|
||||
}
|
||||
|
||||
void rrc::set_connect_notifer(connect_notifier* cnotifier_)
|
||||
{
|
||||
cnotifier = cnotifier_;
|
||||
}
|
||||
|
||||
void rrc::stop()
|
||||
{
|
||||
if (running) {
|
||||
|
@ -932,42 +918,6 @@ void rrc::enable_encryption(uint16_t rnti, uint32_t lcid)
|
|||
pdcp->enable_encryption(rnti, lcid);
|
||||
}
|
||||
|
||||
void rrc::monitor_activity()
|
||||
{
|
||||
pthread_mutex_lock(&user_mutex);
|
||||
|
||||
uint16_t rem_rnti = 0;
|
||||
for (auto& user : users) {
|
||||
if (user.first == SRSLTE_MRNTI) {
|
||||
continue;
|
||||
}
|
||||
ue* u = user.second.get();
|
||||
uint16_t rnti = (uint16_t)user.first;
|
||||
|
||||
if (cnotifier && u->is_connected() && !u->connect_notified) {
|
||||
cnotifier->user_connected(rnti);
|
||||
u->connect_notified = true;
|
||||
}
|
||||
|
||||
if (u->is_timeout()) {
|
||||
rrc_log->info("User rnti=0x%x timed out. Exists in s1ap=%s\n", rnti, s1ap->user_exists(rnti) ? "yes" : "no");
|
||||
rem_rnti = rnti;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (rem_rnti > 0) {
|
||||
if (s1ap->user_exists(rem_rnti)) {
|
||||
s1ap->user_release(rem_rnti, LIBLTE_S1AP_CAUSERADIONETWORK_USER_INACTIVITY);
|
||||
} else {
|
||||
if (rem_rnti != SRSLTE_MRNTI) {
|
||||
rem_user_thread(rem_rnti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&user_mutex);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
RRC run tti method
|
||||
*******************************************************************************/
|
||||
|
@ -1037,10 +987,10 @@ rrc::ue::ue(rrc* outer_rrc, uint16_t rnti_) :
|
|||
rnti(rnti_),
|
||||
pool(srslte::byte_buffer_pool::get_instance())
|
||||
{
|
||||
set_activity();
|
||||
activity_timer = outer_rrc->timers->get_unique_timer();
|
||||
set_activity_timeout(MSG3_RX_TIMEOUT); // next UE response is Msg3
|
||||
integ_algo = srslte::INTEGRITY_ALGORITHM_ID_EIA0;
|
||||
cipher_algo = srslte::CIPHERING_ALGORITHM_ID_EEA0;
|
||||
gettimeofday(&t_ue_init, nullptr);
|
||||
mobility_handler.reset(new rrc_mobility(this));
|
||||
}
|
||||
|
||||
|
@ -1057,12 +1007,61 @@ uint32_t rrc::ue::rl_failure()
|
|||
|
||||
void rrc::ue::set_activity()
|
||||
{
|
||||
gettimeofday(&t_last_activity, nullptr);
|
||||
// re-start activity timer with current timeout value
|
||||
activity_timer.run();
|
||||
|
||||
if (parent && parent->rrc_log) {
|
||||
parent->rrc_log->debug("Activity registered for rnti=0x%x (timeout_value=%dms)\n", rnti, activity_timer.duration());
|
||||
}
|
||||
}
|
||||
|
||||
void rrc::ue::activity_timer_expired()
|
||||
{
|
||||
if (parent) {
|
||||
if (parent->rrc_log) {
|
||||
parent->rrc_log->debug("Activity registered rnti=0x%x\n", rnti);
|
||||
parent->rrc_log->warning("Activity timer for rnti=0x%x expired after %d ms\n", rnti, activity_timer.value());
|
||||
}
|
||||
|
||||
if (parent->s1ap->user_exists(rnti)) {
|
||||
parent->s1ap->user_release(rnti, LIBLTE_S1AP_CAUSERADIONETWORK_USER_INACTIVITY);
|
||||
} else {
|
||||
if (rnti != SRSLTE_MRNTI) {
|
||||
parent->rem_user_thread(rnti);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state = RRC_STATE_RELEASE_REQUEST;
|
||||
}
|
||||
|
||||
void rrc::ue::set_activity_timeout(const activity_timeout_type_t type)
|
||||
{
|
||||
uint32_t deadline_s = 0;
|
||||
uint32_t deadline_ms = 0;
|
||||
|
||||
switch (type) {
|
||||
case MSG3_RX_TIMEOUT:
|
||||
deadline_s = 0;
|
||||
deadline_ms = static_cast<uint32_t>((parent->sib2.rr_cfg_common.rach_cfg_common.max_harq_msg3_tx + 1) * 16);
|
||||
break;
|
||||
case UE_RESPONSE_RX_TIMEOUT:
|
||||
// Arbitrarily chosen value to complete each UE config step, i.e. security, bearer setup, etc.
|
||||
deadline_s = 1;
|
||||
deadline_ms = 0;
|
||||
break;
|
||||
case UE_INACTIVITY_TIMEOUT:
|
||||
deadline_s = parent->cfg.inactivity_timeout_ms / 1000;
|
||||
deadline_ms = parent->cfg.inactivity_timeout_ms % 1000;
|
||||
break;
|
||||
default:
|
||||
parent->rrc_log->error("Unknown timeout type %d", type);
|
||||
}
|
||||
|
||||
uint32_t deadline = deadline_s * 1e3 + deadline_ms;
|
||||
activity_timer.set(deadline, [this](uint32_t tid) { activity_timer_expired(); });
|
||||
parent->rrc_log->debug("Setting timer for %s for rnti=%x to %dms\n", to_string(type).c_str(), rnti, deadline);
|
||||
|
||||
set_activity();
|
||||
}
|
||||
|
||||
bool rrc::ue::is_connected()
|
||||
|
@ -1075,63 +1074,6 @@ bool rrc::ue::is_idle()
|
|||
return state == RRC_STATE_IDLE;
|
||||
}
|
||||
|
||||
bool rrc::ue::is_timeout()
|
||||
{
|
||||
if (!parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct timeval t[3];
|
||||
uint32_t deadline_s = 0;
|
||||
uint32_t deadline_us = 0;
|
||||
const char* deadline_str = nullptr;
|
||||
memcpy(&t[1], &t_last_activity, sizeof(struct timeval));
|
||||
gettimeofday(&t[2], nullptr);
|
||||
get_time_interval(t);
|
||||
|
||||
switch (state) {
|
||||
case RRC_STATE_IDLE:
|
||||
deadline_s = 0;
|
||||
deadline_us =
|
||||
static_cast<uint32_t>((parent->sib2.rr_cfg_common.rach_cfg_common.max_harq_msg3_tx + 1) * 16 * 1000);
|
||||
deadline_str = "RRCConnectionSetup";
|
||||
break;
|
||||
case RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE:
|
||||
deadline_s = 1;
|
||||
deadline_us = 0;
|
||||
deadline_str = "RRCConnectionSetupComplete";
|
||||
break;
|
||||
case RRC_STATE_RELEASE_REQUEST:
|
||||
deadline_s = 4;
|
||||
deadline_us = 0;
|
||||
deadline_str = "RRCReleaseRequest";
|
||||
break;
|
||||
default:
|
||||
deadline_s = parent->cfg.inactivity_timeout_ms / 1000;
|
||||
deadline_us = (parent->cfg.inactivity_timeout_ms % 1000) * 1000;
|
||||
deadline_str = "Activity";
|
||||
break;
|
||||
}
|
||||
|
||||
if (deadline_str) {
|
||||
int64_t deadline = deadline_s * 1e6 + deadline_us;
|
||||
int64_t elapsed = t[0].tv_sec * 1e6 + t[0].tv_usec;
|
||||
if (elapsed > deadline && elapsed > 0) {
|
||||
parent->rrc_log->warning("User rnti=0x%x expired %s deadline: %ld:%ld>%d:%d us\n",
|
||||
rnti,
|
||||
deadline_str,
|
||||
t[0].tv_sec,
|
||||
t[0].tv_usec,
|
||||
deadline_s,
|
||||
deadline_us);
|
||||
memcpy(&t_last_activity, &t[2], sizeof(struct timeval));
|
||||
state = RRC_STATE_RELEASE_REQUEST;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void rrc::ue::parse_ul_dcch(uint32_t lcid, srslte::unique_byte_buffer_t pdu)
|
||||
{
|
||||
set_activity();
|
||||
|
@ -1176,6 +1118,7 @@ void rrc::ue::parse_ul_dcch(uint32_t lcid, srslte::unique_byte_buffer_t pdu)
|
|||
handle_rrc_reconf_complete(&ul_dcch_msg.msg.c1().rrc_conn_recfg_complete(), std::move(pdu));
|
||||
parent->rrc_log->console("User 0x%x connected\n", rnti);
|
||||
state = RRC_STATE_REGISTERED;
|
||||
set_activity_timeout(UE_INACTIVITY_TIMEOUT);
|
||||
break;
|
||||
case ul_dcch_msg_type_c::c1_c_::types::security_mode_complete:
|
||||
handle_security_mode_complete(&ul_dcch_msg.msg.c1().security_mode_complete());
|
||||
|
@ -1217,7 +1160,6 @@ void rrc::ue::handle_rrc_con_req(rrc_conn_request_s* msg)
|
|||
send_connection_reject();
|
||||
}
|
||||
|
||||
set_activity();
|
||||
rrc_conn_request_r8_ies_s* msg_r8 = &msg->crit_exts.rrc_conn_request_r8();
|
||||
|
||||
if (msg_r8->ue_id.type() == init_ue_id_c::types::s_tmsi) {
|
||||
|
@ -1228,6 +1170,14 @@ void rrc::ue::handle_rrc_con_req(rrc_conn_request_s* msg)
|
|||
establishment_cause = msg_r8->establishment_cause;
|
||||
send_connection_setup();
|
||||
state = RRC_STATE_WAIT_FOR_CON_SETUP_COMPLETE;
|
||||
|
||||
set_activity_timeout(UE_RESPONSE_RX_TIMEOUT);
|
||||
}
|
||||
|
||||
std::string rrc::ue::to_string(const activity_timeout_type_t& type)
|
||||
{
|
||||
constexpr static const char* options[] = {"Msg3 reception", "UE response reception", "UE inactivity"};
|
||||
return srslte::enum_to_text(options, (uint32_t)activity_timeout_type_t::nulltype, (uint32_t)type);
|
||||
}
|
||||
|
||||
void rrc::ue::handle_rrc_con_reest_req(rrc_conn_reest_request_r8_ies_s* msg)
|
||||
|
@ -1552,7 +1502,7 @@ void rrc::ue::send_connection_setup(bool is_setup)
|
|||
if (sr_allocate(parent->cfg.sr_cfg.period,
|
||||
&phy_cfg->sched_request_cfg.setup().sr_cfg_idx,
|
||||
&phy_cfg->sched_request_cfg.setup().sr_pucch_res_idx)) {
|
||||
parent->rrc_log->error("Allocating SR resources for rnti=%d\n", rnti);
|
||||
parent->rrc_log->error("Allocating SR resources for rnti=0x%x\n", rnti);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
@ -2373,4 +2323,5 @@ int rrc::ue::ri_get(uint32_t m_ri, uint16_t* ri_idx)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace srsenb
|
||||
|
|
Loading…
Reference in New Issue