Merge pull request #662 from softwareradiosystems/pr_new_timer

new timer class
master
Francisco Paisana 5 years ago committed by GitHub
commit 1c375d99e0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -102,17 +102,6 @@ public:
// bool do_rohc; // bool do_rohc;
}; };
class mac_interface_timers
{
public:
/* Timer services with ms resolution.
* timer_id must be lower than MAC_NOF_UPPER_TIMERS
*/
virtual timers::timer* timer_get(uint32_t timer_id) = 0;
virtual void timer_release_id(uint32_t timer_id) = 0;
virtual uint32_t timer_get_unique_id() = 0;
};
class read_pdu_interface class read_pdu_interface
{ {
public: public:

@ -29,10 +29,14 @@
#ifndef SRSLTE_TIMERS_H #ifndef SRSLTE_TIMERS_H
#define SRSLTE_TIMERS_H #define SRSLTE_TIMERS_H
#include <stdio.h> #include <algorithm>
#include <functional>
#include <limits>
#include <queue>
#include <stdint.h> #include <stdint.h>
#include <vector> #include <stdio.h>
#include <time.h> #include <time.h>
#include <vector>
#include "srslte/srslte.h" #include "srslte/srslte.h"
@ -44,129 +48,245 @@ class timer_callback
virtual void timer_expired(uint32_t timer_id) = 0; virtual void timer_expired(uint32_t timer_id) = 0;
}; };
class timers class timer_handler
{ {
public: constexpr static uint32_t MAX_TIMER_DURATION = std::numeric_limits<uint32_t>::max() / 4;
class timer constexpr static uint32_t MAX_TIMER_VALUE = std::numeric_limits<uint32_t>::max() / 2;
struct timer_impl {
timer_handler* parent;
uint32_t duration = 0, timeout = 0;
bool running = false;
bool active = false;
std::function<void(uint32_t)> callback;
explicit timer_impl(timer_handler* parent_) : parent(parent_) {}
uint32_t id() const { return std::distance((const timer_handler::timer_impl*)&parent->timer_list[0], this); }
bool is_running() const { return active and running and timeout > 0; }
bool is_expired() const { return active and not running and timeout > 0 and timeout <= parent->cur_time; }
uint32_t value() const { return parent->cur_time - (timeout - duration); }
bool set(uint32_t duration_)
{ {
public: if (duration_ > MAX_TIMER_DURATION) {
timer(uint32_t id_=0) {id = id_; counter = 0; timeout = 0; running = false; callback = NULL; } ERROR("Error: timer durations above %u are not supported\n", MAX_TIMER_DURATION);
void set(timer_callback *callback_, uint32_t timeout_) { return false;
callback = callback_;
timeout = timeout_;
reset();
} }
bool is_running() { if (not active) {
return (counter < timeout) && running; ERROR("Error: setting inactive timer id=%d\n", id());
return false;
} }
bool is_expired() { duration = duration_;
return (timeout > 0) && (counter >= timeout); if (is_running()) {
// if already running, just extends timer lifetime
run();
} }
uint32_t get_timeout() { return true;
return timeout;
} }
void reset() {
counter = 0; bool set(uint32_t duration_, std::function<void(int)> callback_)
{
if (set(duration_)) {
callback = std::move(callback_);
return true;
} }
uint32_t value() { return false;
return counter;
} }
void step() {
if (running) { void run()
counter++; {
if (is_expired()) { if (not active) {
running = false; ERROR("Error: calling run() for inactive timer id=%d\n", id());
if (callback) { return;
callback->timer_expired(id);
} }
timeout = parent->cur_time + duration;
parent->running_timers.emplace(id(), timeout);
running = true;
} }
void stop()
{
running = false; // invalidates trigger
if (not is_expired()) {
timeout = 0; // if it has already expired, then do not alter is_expired() state
}
}
void clear()
{
stop();
duration = 0;
active = false;
callback = std::function<void(uint32_t)>();
// leave run_id unchanged. Since the timeout was changed, we shall not get spurious triggering
} }
void trigger()
{
if (is_running()) {
if (callback) {
callback(id());
} }
void stop() {
running = false; running = false;
} }
void run() {
running = true;
} }
uint32_t id;
private:
timer_callback *callback;
uint32_t timeout;
uint32_t counter;
bool running;
}; };
timers(uint32_t nof_timers_) : timer_list(nof_timers_), used_timers(nof_timers_) public:
class unique_timer
{
public:
unique_timer() : parent(nullptr), timer_id(std::numeric_limits<decltype(timer_id)>::max()) {}
explicit unique_timer(timer_handler* parent_, uint32_t timer_id_) : parent(parent_), timer_id(timer_id_) {}
unique_timer(const unique_timer&) = delete;
unique_timer(unique_timer&& other) noexcept : parent(other.parent), timer_id(other.timer_id)
{ {
nof_timers = nof_timers_; other.parent = nullptr;
next_timer = 0;
nof_used_timers = 0;
for (uint32_t i = 0; i < nof_timers; i++) {
timer_list[i].id = i;
used_timers[i] = false;
} }
~unique_timer()
{
if (parent) {
// does not call callback
impl()->clear();
} }
}
unique_timer& operator=(const unique_timer&) = delete;
void step_all() { unique_timer& operator=(unique_timer&& other) noexcept
for (uint32_t i=0;i<nof_timers;i++) { {
get(i)->step(); if (this != &other) {
timer_id = other.timer_id;
parent = other.parent;
other.parent = nullptr;
} }
return *this;
} }
void stop_all() {
for (uint32_t i=0;i<nof_timers;i++) { bool is_valid() const { return parent != nullptr; }
get(i)->stop();
void set(uint32_t duration_, const std::function<void(int)>& callback_) { impl()->set(duration_, callback_); }
void set(uint32_t duration_) { impl()->set(duration_); }
bool is_running() const { return impl()->is_running(); }
bool is_expired() const { return impl()->is_expired(); }
uint32_t value() const { return impl()->value(); }
void run() { impl()->run(); }
void stop() { impl()->stop(); }
void release()
{
impl()->clear();
parent = nullptr;
} }
uint32_t id() const { return timer_id; }
uint32_t duration() const { return impl()->duration; }
private:
timer_impl* impl() { return &parent->timer_list[timer_id]; }
const timer_impl* impl() const { return &parent->timer_list[timer_id]; }
timer_handler* parent;
uint32_t timer_id;
};
explicit timer_handler(uint32_t capacity = 64)
{
timer_list.reserve(capacity);
// reserve a priority queue using a vector
std::vector<timer_run> v;
v.reserve(capacity);
std::priority_queue<timer_run> q(std::less<timer_run>(), std::move(v));
running_timers = std::move(q);
} }
void run_all() {
for (uint32_t i=0;i<nof_timers;i++) { void step_all()
get(i)->run(); {
cur_time++;
while (not running_timers.empty() and cur_time >= running_timers.top().timeout) {
timer_impl* ptr = &timer_list[running_timers.top().timer_id];
// if the timer_run and timer_impl timeouts do not match, it means that timer_impl::timeout was overwritten.
// in such case, do not trigger
if (ptr->timeout == running_timers.top().timeout) {
ptr->trigger();
} }
running_timers.pop();
} }
void reset_all() {
for (uint32_t i=0;i<nof_timers;i++) {
get(i)->reset();
} }
void stop_all()
{
// does not call callback
while (not running_timers.empty()) {
running_timers.pop();
} }
timer *get(uint32_t i) { for (auto& i : timer_list) {
if (i < nof_timers) { i.running = false;
return &timer_list[i];
} else {
printf("Error accessing invalid timer %d (Only %d timers available)\n", i, nof_timers);
return NULL;
} }
} }
void release_id(uint32_t i) {
if (nof_used_timers > 0 && i < nof_timers) { unique_timer get_unique_timer()
used_timers[i] = false; {
nof_used_timers--; uint32_t i = 0;
} else { for (; i < timer_list.size(); ++i) {
ERROR("Error releasing timer id=%d: nof_used_timers=%d, nof_timers=%d\n", i, nof_used_timers, nof_timers); if (not timer_list[i].active) {
break;
} }
} }
uint32_t get_unique_id() { if (i == timer_list.size()) {
if (nof_used_timers >= nof_timers) { timer_list.emplace_back(this);
ERROR("Error getting unique timer id: no more timers available\n");
return 0;
} else {
for (uint32_t i=0;i<nof_timers;i++) {
if (!used_timers[i]) {
used_timers[i] = true;
nof_used_timers++;
return i;
} }
timer_list[i].active = true;
return unique_timer(this, i);
} }
ERROR("Error getting unique timer id: no more timers available but nof_used_timers=%d, nof_timers=%d\n",
nof_used_timers, uint32_t get_cur_time() const { return cur_time; }
nof_timers);
return 0; uint32_t nof_timers() const
{
return std::count_if(timer_list.begin(), timer_list.end(), [](const timer_impl& t) { return t.active; });
} }
uint32_t nof_running_timers() const
{
return std::count_if(timer_list.begin(), timer_list.end(), [](const timer_impl& t) { return t.is_running(); });
} }
private: private:
uint32_t next_timer; struct timer_run {
uint32_t nof_used_timers; uint32_t timer_id;
uint32_t nof_timers; uint32_t timeout;
std::vector<timer> timer_list;
std::vector<bool> used_timers; timer_run(uint32_t timer_id_, uint32_t timeout_) : timer_id(timer_id_), timeout(timeout_) {}
bool operator<(const timer_run& other) const
{
// returns true, if other.timeout is lower than timeout, accounting for wrap around
if (timeout > other.timeout) {
return (timeout - other.timeout) < MAX_TIMER_VALUE / 2;
}
return (other.timeout - timeout) > MAX_TIMER_VALUE / 2;
}
};
std::vector<timer_impl> timer_list;
std::priority_queue<timer_run> running_timers;
uint32_t cur_time = 0;
}; };
} // namespace srslte } // namespace srslte

@ -45,7 +45,10 @@ class rlc
public: public:
rlc(log* rlc_log_); rlc(log* rlc_log_);
virtual ~rlc(); virtual ~rlc();
void init(srsue::pdcp_interface_rlc* pdcp_, srsue::rrc_interface_rlc* rrc_, srslte::timers* timers_, uint32_t lcid_); void init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srslte::timer_handler* timers_,
uint32_t lcid_);
void stop(); void stop();
void get_metrics(rlc_metrics_t& m); void get_metrics(rlc_metrics_t& m);
@ -89,7 +92,7 @@ private:
srslte::log* rlc_log = nullptr; srslte::log* rlc_log = nullptr;
srsue::pdcp_interface_rlc* pdcp = nullptr; srsue::pdcp_interface_rlc* pdcp = nullptr;
srsue::rrc_interface_rlc* rrc = nullptr; srsue::rrc_interface_rlc* rrc = nullptr;
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
typedef std::map<uint16_t, rlc_common*> rlc_map_t; typedef std::map<uint16_t, rlc_common*> rlc_map_t;
typedef std::pair<uint16_t, rlc_common*> rlc_map_pair_t; typedef std::pair<uint16_t, rlc_common*> rlc_map_pair_t;

@ -68,7 +68,7 @@ public:
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_); srslte::timer_handler* timers_);
bool configure(rlc_config_t cfg_); bool configure(rlc_config_t cfg_);
void reestablish(); void reestablish();
void stop(); void stop();
@ -176,11 +176,8 @@ private:
* Ref: 3GPP TS 36.322 v10.0.0 Section 7 * Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/ ***************************************************************************/
srslte::timers::timer* poll_retx_timer = nullptr; srslte::timer_handler::unique_timer poll_retx_timer;
uint32_t poll_retx_timer_id = 0; srslte::timer_handler::unique_timer status_prohibit_timer;
srslte::timers::timer* status_prohibit_timer = nullptr;
uint32_t status_prohibit_timer_id = 0;
// Tx windows // Tx windows
std::map<uint32_t, rlc_amd_tx_pdu_t> tx_window; std::map<uint32_t, rlc_amd_tx_pdu_t> tx_window;
@ -270,15 +267,14 @@ private:
* Ref: 3GPP TS 36.322 v10.0.0 Section 7 * Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/ ***************************************************************************/
srslte::timers::timer* reordering_timer = nullptr; srslte::timer_handler::unique_timer reordering_timer;
uint32_t reordering_timer_id = 0;
}; };
// Common variables needed/provided by parent class // Common variables needed/provided by parent class
srsue::rrc_interface_rlc* rrc = nullptr; srsue::rrc_interface_rlc* rrc = nullptr;
srslte::log* log = nullptr; srslte::log* log = nullptr;
srsue::pdcp_interface_rlc* pdcp = nullptr; srsue::pdcp_interface_rlc* pdcp = nullptr;
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
uint32_t lcid = 0; uint32_t lcid = 0;
rlc_config_t cfg = {}; rlc_config_t cfg = {};
std::string rb_name; std::string rb_name;

@ -38,7 +38,7 @@ public:
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_, srslte::timer_handler* timers_,
uint32_t queue_len = 16); uint32_t queue_len = 16);
~rlc_tm(); ~rlc_tm();
bool configure(rlc_config_t cnfg); bool configure(rlc_config_t cnfg);

@ -53,7 +53,7 @@ public:
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_); srslte::timer_handler* timers_);
~rlc_um(); ~rlc_um();
bool configure(rlc_config_t cnfg); bool configure(rlc_config_t cnfg);
void reestablish(); void reestablish();
@ -167,7 +167,7 @@ private:
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_); srslte::timer_handler* timers_);
~rlc_um_rx(); ~rlc_um_rx();
void stop(); void stop();
void reestablish(); void reestablish();
@ -187,7 +187,7 @@ private:
byte_buffer_pool* pool = nullptr; byte_buffer_pool* pool = nullptr;
srslte::log* log = nullptr; srslte::log* log = nullptr;
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
std::string rb_name; std::string rb_name;
/**************************************************************************** /****************************************************************************
@ -225,8 +225,7 @@ private:
* Timers * Timers
* Ref: 3GPP TS 36.322 v10.0.0 Section 7 * Ref: 3GPP TS 36.322 v10.0.0 Section 7
***************************************************************************/ ***************************************************************************/
srslte::timers::timer* reordering_timer = nullptr; srslte::timer_handler::unique_timer reordering_timer;
uint32_t reordering_timer_id = 0;
// helper functions // helper functions
void debug_state(); void debug_state();

@ -53,7 +53,7 @@ rlc::~rlc()
void rlc::init(srsue::pdcp_interface_rlc* pdcp_, void rlc::init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_, srslte::timer_handler* timers_,
uint32_t lcid_) uint32_t lcid_)
{ {
pdcp = pdcp_; pdcp = pdcp_;

@ -36,7 +36,7 @@ rlc_am::rlc_am(srslte::log* log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_) : srslte::timer_handler* timers_) :
log(log_), log(log_),
rrc(rrc_), rrc(rrc_),
pdcp(pdcp_), pdcp(pdcp_),
@ -164,25 +164,15 @@ void rlc_am::write_pdu(uint8_t *payload, uint32_t nof_bytes)
rlc_am::rlc_am_tx::rlc_am_tx(rlc_am* parent_) : rlc_am::rlc_am_tx::rlc_am_tx(rlc_am* parent_) :
parent(parent_), parent(parent_),
log(parent_->log), log(parent_->log),
pool(byte_buffer_pool::get_instance()) pool(byte_buffer_pool::get_instance()),
poll_retx_timer(parent_->timers->get_unique_timer()),
status_prohibit_timer(parent_->timers->get_unique_timer())
{ {
poll_retx_timer_id = parent->timers->get_unique_id();
poll_retx_timer = parent->timers->get(poll_retx_timer_id);
status_prohibit_timer_id = parent->timers->get_unique_id();
status_prohibit_timer = parent->timers->get(status_prohibit_timer_id);
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
} }
rlc_am::rlc_am_tx::~rlc_am_tx() rlc_am::rlc_am_tx::~rlc_am_tx()
{ {
poll_retx_timer->stop();
parent->timers->release_id(poll_retx_timer_id);
status_prohibit_timer->stop();
parent->timers->release_id(status_prohibit_timer_id);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
} }
@ -192,18 +182,19 @@ bool rlc_am::rlc_am_tx::configure(rlc_config_t cfg_)
cfg = cfg_.am; cfg = cfg_.am;
// check timers // check timers
if (poll_retx_timer == NULL or status_prohibit_timer == NULL) { if (not poll_retx_timer.is_valid() or not status_prohibit_timer.is_valid()) {
log->error("Configuring RLC AM TX: timers not configured\n"); log->error("Configuring RLC AM TX: timers not configured\n");
return false; return false;
} }
// configure timers // configure timers
if (cfg.t_status_prohibit > 0) { if (cfg.t_status_prohibit > 0) {
status_prohibit_timer->set(this, static_cast<uint32_t>(cfg.t_status_prohibit)); status_prohibit_timer.set(static_cast<uint32_t>(cfg.t_status_prohibit),
[this](uint32_t timerid) { timer_expired(timerid); });
} }
if (cfg.t_poll_retx > 0) { if (cfg.t_poll_retx > 0) {
poll_retx_timer->set(this, static_cast<uint32_t>(cfg.t_poll_retx)); poll_retx_timer.set(static_cast<uint32_t>(cfg.t_poll_retx), [this](uint32_t timerid) { timer_expired(timerid); });
} }
tx_sdu_queue.resize(cfg_.tx_queue_length); tx_sdu_queue.resize(cfg_.tx_queue_length);
@ -221,12 +212,12 @@ void rlc_am::rlc_am_tx::stop()
tx_enabled = false; tx_enabled = false;
if (parent->timers != NULL && poll_retx_timer != NULL) { if (parent->timers != nullptr && poll_retx_timer.is_valid()) {
poll_retx_timer->stop(); poll_retx_timer.stop();
} }
if (parent->timers != NULL && status_prohibit_timer != NULL) { if (parent->timers != nullptr && status_prohibit_timer.is_valid()) {
status_prohibit_timer->stop(); status_prohibit_timer.stop();
} }
vt_a = 0; vt_a = 0;
@ -274,7 +265,7 @@ bool rlc_am::rlc_am_tx::do_status()
// Function is supposed to return as fast as possible // Function is supposed to return as fast as possible
bool rlc_am::rlc_am_tx::has_data() bool rlc_am::rlc_am_tx::has_data()
{ {
return (((do_status() && not status_prohibit_timer->is_running())) || // if we have a status PDU to transmit return (((do_status() && not status_prohibit_timer.is_running())) || // if we have a status PDU to transmit
(not retx_queue.empty()) || // if we have a retransmission (not retx_queue.empty()) || // if we have a retransmission
(tx_sdu != NULL) || // if we are currently transmitting a SDU (tx_sdu != NULL) || // if we are currently transmitting a SDU
(not tx_sdu_queue.is_empty())); // or if there is a SDU queued up for transmission (not tx_sdu_queue.is_empty())); // or if there is a SDU queued up for transmission
@ -289,11 +280,11 @@ uint32_t rlc_am::rlc_am_tx::get_buffer_state()
log->debug("%s Buffer state - do_status=%d, status_prohibit=%d, timer=%s\n", log->debug("%s Buffer state - do_status=%d, status_prohibit=%d, timer=%s\n",
RB_NAME, RB_NAME,
do_status(), do_status(),
status_prohibit_timer->is_running(), status_prohibit_timer.is_running(),
status_prohibit_timer ? "yes" : "no"); status_prohibit_timer.is_valid() ? "yes" : "no");
// Bytes needed for status report // Bytes needed for status report
if (do_status() && not status_prohibit_timer->is_running()) { if (do_status() && not status_prohibit_timer.is_running()) {
n_bytes += parent->rx.get_status_pdu_length(); n_bytes += parent->rx.get_status_pdu_length();
log->debug("%s Buffer state - total status report: %d bytes\n", RB_NAME, n_bytes); log->debug("%s Buffer state - total status report: %d bytes\n", RB_NAME, n_bytes);
} }
@ -393,7 +384,7 @@ int rlc_am::rlc_am_tx::read_pdu(uint8_t *payload, uint32_t nof_bytes)
} }
// Tx STATUS if requested // Tx STATUS if requested
if (do_status() && not status_prohibit_timer->is_running()) { if (do_status() && not status_prohibit_timer.is_running()) {
pdu_size = build_status_pdu(payload, nof_bytes); pdu_size = build_status_pdu(payload, nof_bytes);
goto unlock_and_exit; goto unlock_and_exit;
} }
@ -423,8 +414,8 @@ unlock_and_exit:
void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id) void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (poll_retx_timer != NULL && poll_retx_timer_id == timeout_id) { if (poll_retx_timer.is_valid() && poll_retx_timer.id() == timeout_id) {
log->debug("Poll reTx timer expired for LCID=%d after %d ms\n", parent->lcid, poll_retx_timer->get_timeout()); log->debug("Poll reTx timer expired for LCID=%d after %d ms\n", parent->lcid, poll_retx_timer.duration());
// Section 5.2.2.3 in TS 36.311, schedule random PDU for retransmission if // Section 5.2.2.3 in TS 36.311, schedule random PDU for retransmission if
// (a) both tx and retx buffer are empty, or // (a) both tx and retx buffer are empty, or
// (b) no new data PDU can be transmitted (tx window is full) // (b) no new data PDU can be transmitted (tx window is full)
@ -477,11 +468,10 @@ bool rlc_am::rlc_am_tx::poll_required()
return true; return true;
} }
if (poll_retx_timer != NULL) { if (poll_retx_timer.is_valid()) {
if (poll_retx_timer->is_expired()) { if (poll_retx_timer.is_expired()) {
// re-arm timer (will be stopped when status PDU is received) // re-arm timer (will be stopped when status PDU is received)
poll_retx_timer->reset(); poll_retx_timer.run();
poll_retx_timer->run();
return true; return true;
} }
} }
@ -511,15 +501,13 @@ int rlc_am::rlc_am_tx::build_status_pdu(uint8_t *payload, uint32_t nof_bytes)
int pdu_len = parent->rx.get_status_pdu(&tx_status, nof_bytes); int pdu_len = parent->rx.get_status_pdu(&tx_status, nof_bytes);
log->debug("%s\n", rlc_am_status_pdu_to_string(&tx_status).c_str()); log->debug("%s\n", rlc_am_status_pdu_to_string(&tx_status).c_str());
if (pdu_len > 0 && nof_bytes >= static_cast<uint32_t>(pdu_len)) { if (pdu_len > 0 && nof_bytes >= static_cast<uint32_t>(pdu_len)) {
log->info("%s Tx status PDU - %s\n", log->info("%s Tx status PDU - %s\n", RB_NAME, rlc_am_status_pdu_to_string(&tx_status).c_str());
RB_NAME, rlc_am_status_pdu_to_string(&tx_status).c_str());
parent->rx.reset_status(); parent->rx.reset_status();
if (cfg.t_status_prohibit > 0 && status_prohibit_timer != NULL) { if (cfg.t_status_prohibit > 0 && status_prohibit_timer.is_valid()) {
// re-arm timer // re-arm timer
status_prohibit_timer->reset(); status_prohibit_timer.run();
status_prohibit_timer->run();
} }
debug_state(); debug_state();
pdu_len = rlc_am_write_status_pdu(&tx_status, payload); pdu_len = rlc_am_write_status_pdu(&tx_status, payload);
@ -579,9 +567,8 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s; poll_sn = vt_s;
pdu_without_poll = 0; pdu_without_poll = 0;
byte_without_poll = 0; byte_without_poll = 0;
if (poll_retx_timer != NULL) { if (poll_retx_timer.is_valid()) {
poll_retx_timer->reset(); poll_retx_timer.run();
poll_retx_timer->run();
} }
} }
@ -637,9 +624,8 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
poll_sn = vt_s; poll_sn = vt_s;
pdu_without_poll = 0; pdu_without_poll = 0;
byte_without_poll = 0; byte_without_poll = 0;
if (poll_retx_timer != NULL) { if (poll_retx_timer.is_valid()) {
poll_retx_timer->reset(); poll_retx_timer.run();
poll_retx_timer->run();
} }
} }
@ -894,9 +880,8 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s; poll_sn = vt_s;
pdu_without_poll = 0; pdu_without_poll = 0;
byte_without_poll = 0; byte_without_poll = 0;
if (poll_retx_timer != NULL) { if (poll_retx_timer.is_valid()) {
poll_retx_timer->reset(); poll_retx_timer.run();
poll_retx_timer->run();
} }
} }
@ -932,8 +917,8 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
log->info("%s Rx Status PDU: %s\n", RB_NAME, rlc_am_status_pdu_to_string(&status).c_str()); log->info("%s Rx Status PDU: %s\n", RB_NAME, rlc_am_status_pdu_to_string(&status).c_str());
if (poll_retx_timer != NULL) { if (poll_retx_timer.is_valid()) {
poll_retx_timer->stop(); poll_retx_timer.stop();
} }
// flush retx queue to avoid unordered SNs, we expect the Rx to request lost PDUs again // flush retx queue to avoid unordered SNs, we expect the Rx to request lost PDUs again
@ -1118,19 +1103,14 @@ bool rlc_am::rlc_am_tx::retx_queue_has_sn(uint32_t sn)
rlc_am::rlc_am_rx::rlc_am_rx(rlc_am* parent_) : rlc_am::rlc_am_rx::rlc_am_rx(rlc_am* parent_) :
parent(parent_), parent(parent_),
pool(byte_buffer_pool::get_instance()), pool(byte_buffer_pool::get_instance()),
log(parent_->log) log(parent_->log),
reordering_timer(parent_->timers->get_unique_timer())
{ {
reordering_timer_id = parent->timers->get_unique_id();
reordering_timer = parent->timers->get(reordering_timer_id);
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
} }
rlc_am::rlc_am_rx::~rlc_am_rx() rlc_am::rlc_am_rx::~rlc_am_rx()
{ {
reordering_timer->stop();
parent->timers->release_id(reordering_timer_id);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
} }
@ -1140,14 +1120,14 @@ bool rlc_am::rlc_am_rx::configure(rlc_am_config_t cfg_)
cfg = cfg_; cfg = cfg_;
// check timers // check timers
if (reordering_timer == NULL) { if (not reordering_timer.is_valid()) {
log->error("Configuring RLC AM TX: timers not configured\n"); log->error("Configuring RLC AM TX: timers not configured\n");
return false; return false;
} }
// configure timer // configure timer
if (cfg.t_reordering > 0) { if (cfg.t_reordering > 0) {
reordering_timer->set(this, static_cast<uint32_t>(cfg.t_reordering)); reordering_timer.set(static_cast<uint32_t>(cfg.t_reordering), [this](uint32_t tid) { timer_expired(tid); });
} }
return true; return true;
@ -1162,8 +1142,8 @@ void rlc_am::rlc_am_rx::stop()
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (parent->timers != NULL && reordering_timer != NULL) { if (parent->timers != nullptr && reordering_timer.is_valid()) {
reordering_timer->stop(); reordering_timer.stop();
} }
rx_sdu.reset(); rx_sdu.reset();
@ -1283,22 +1263,21 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
reassemble_rx_sdus(); reassemble_rx_sdus();
// Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3) // Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3)
if (reordering_timer != NULL) { if (reordering_timer.is_valid()) {
if (reordering_timer->is_running()) { if (reordering_timer.is_running()) {
if (vr_x == vr_r || (!inside_rx_window(vr_x) && vr_x != vr_mr)) { if (vr_x == vr_r || (!inside_rx_window(vr_x) && vr_x != vr_mr)) {
log->debug("Stopping reordering timer.\n"); log->debug("Stopping reordering timer.\n");
reordering_timer->stop(); reordering_timer.stop();
} else { } else {
log->debug("Leave reordering timer running.\n"); log->debug("Leave reordering timer running.\n");
} }
debug_state(); debug_state();
} }
if (not reordering_timer->is_running()) { if (not reordering_timer.is_running()) {
if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) { if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) {
log->debug("Starting reordering timer.\n"); log->debug("Starting reordering timer.\n");
reordering_timer->reset(); reordering_timer.run();
reordering_timer->run();
vr_x = vr_h; vr_x = vr_h;
} else { } else {
log->debug("Leave reordering timer stopped.\n"); log->debug("Leave reordering timer stopped.\n");
@ -1578,8 +1557,8 @@ void rlc_am::rlc_am_rx::write_pdu(uint8_t* payload, const uint32_t nof_bytes)
void rlc_am::rlc_am_rx::timer_expired(uint32_t timeout_id) void rlc_am::rlc_am_rx::timer_expired(uint32_t timeout_id)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (reordering_timer != NULL && reordering_timer_id == timeout_id) { if (reordering_timer.is_valid() and reordering_timer.id() == timeout_id) {
reordering_timer->reset(); // reordering_timer.run(); // FIXME: It was reset() before
log->debug("%s reordering timeout expiry - updating vr_ms (was %d)\n", RB_NAME, vr_ms); log->debug("%s reordering timeout expiry - updating vr_ms (was %d)\n", RB_NAME, vr_ms);
// 36.322 v10 Section 5.1.3.2.4 // 36.322 v10 Section 5.1.3.2.4
@ -1595,8 +1574,7 @@ void rlc_am::rlc_am_rx::timer_expired(uint32_t timeout_id)
} }
if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_ms)) { if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_ms)) {
reordering_timer->reset(); reordering_timer.run();
reordering_timer->run();
vr_x = vr_h; vr_x = vr_h;
} }

@ -27,7 +27,7 @@ rlc_tm::rlc_tm(srslte::log* log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_, srslte::timer_handler* timers_,
uint32_t queue_len_) : uint32_t queue_len_) :
ul_queue(queue_len_), ul_queue(queue_len_),
log(log_), log(log_),

@ -32,7 +32,7 @@ rlc_um::rlc_um(srslte::log* log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_) : srslte::timer_handler* timers_) :
lcid(lcid_), lcid(lcid_),
pool(byte_buffer_pool::get_instance()), pool(byte_buffer_pool::get_instance()),
rrc(rrc_), rrc(rrc_),
@ -96,8 +96,8 @@ bool rlc_um::rlc_um_rx::configure(rlc_config_t cnfg_, std::string rb_name_)
} }
// set reordering timer // set reordering timer
if (reordering_timer != NULL) { if (reordering_timer.is_valid()) {
reordering_timer->set(this, cfg.um.t_reordering); reordering_timer.set(cfg.um.t_reordering, [this](uint32_t tid) { timer_expired(tid); });
} }
} else { } else {
if (cfg.um_nr.mod == 0) { if (cfg.um_nr.mod == 0) {
@ -609,31 +609,26 @@ rlc_um::rlc_um_rx::rlc_um_rx(srslte::log* log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_, srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_, srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_) : srslte::timer_handler* timers_) :
pool(byte_buffer_pool::get_instance()), pool(byte_buffer_pool::get_instance()),
log(log_), log(log_),
pdcp(pdcp_), pdcp(pdcp_),
rrc(rrc_), rrc(rrc_),
timers(timers_), timers(timers_),
lcid(lcid_) lcid(lcid_),
reordering_timer(timers_->get_unique_timer())
{ {
reordering_timer_id = timers->get_unique_id();
reordering_timer = timers->get(reordering_timer_id);
} }
rlc_um::rlc_um_rx::~rlc_um_rx() rlc_um::rlc_um_rx::~rlc_um_rx() {}
{
reordering_timer->stop();
timers->release_id(reordering_timer_id);
}
void rlc_um::rlc_um_rx::reestablish() void rlc_um::rlc_um_rx::reestablish()
{ {
// try to reassemble any SDUs if possible // try to reassemble any SDUs if possible
if (reordering_timer != NULL) { if (reordering_timer.is_valid()) {
if (reordering_timer->is_running()) { if (reordering_timer.is_running()) {
reordering_timer->stop(); reordering_timer.stop();
timer_expired(reordering_timer_id); timer_expired(reordering_timer.id());
} }
} }
@ -642,12 +637,12 @@ void rlc_um::rlc_um_rx::reestablish()
rx_enabled = true; rx_enabled = true;
} }
void rlc_um::rlc_um_rx::stop() void rlc_um::rlc_um_rx::stop()
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
reset(); reset();
reordering_timer->stop();
reordering_timer.stop();
} }
void rlc_um::rlc_um_rx::reset() void rlc_um::rlc_um_rx::reset()
@ -723,17 +718,14 @@ void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes)
log->debug("Finished reassemble from received PDU\n"); log->debug("Finished reassemble from received PDU\n");
// Update reordering variables and timers // Update reordering variables and timers
if(reordering_timer->is_running()) { if (reordering_timer.is_running()) {
if(RX_MOD_BASE(vr_ux) <= RX_MOD_BASE(vr_ur) || if (RX_MOD_BASE(vr_ux) <= RX_MOD_BASE(vr_ur) || (!inside_reordering_window(vr_ux) && vr_ux != vr_uh)) {
(!inside_reordering_window(vr_ux) && vr_ux != vr_uh)) reordering_timer.stop();
{
reordering_timer->stop();
} }
} }
if(!reordering_timer->is_running()) { if (!reordering_timer.is_running()) {
if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) { if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) {
reordering_timer->reset(); reordering_timer.run();
reordering_timer->run();
vr_ux = vr_uh; vr_ux = vr_uh;
} }
} }
@ -1023,10 +1015,9 @@ void rlc_um::rlc_um_rx::reset_metrics()
void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id) void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id)
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
if (reordering_timer != NULL && reordering_timer_id == timeout_id) { if (reordering_timer.is_valid() && reordering_timer.id() == timeout_id) {
// 36.322 v10 Section 5.1.2.2.4 // 36.322 v10 Section 5.1.2.2.4
log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", get_rb_name());
get_rb_name());
log->warning("Lost PDU SN: %d\n", vr_ur); log->warning("Lost PDU SN: %d\n", vr_ur);
@ -1043,8 +1034,7 @@ void rlc_um::rlc_um_rx::timer_expired(uint32_t timeout_id)
} }
if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) { if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) {
reordering_timer->reset(); reordering_timer.run();
reordering_timer->run();
vr_ux = vr_uh; vr_ux = vr_uh;
} }

@ -75,3 +75,6 @@ add_test(stack_procedure_test stack_procedure_test)
add_executable(queue_test queue_test.cc) add_executable(queue_test queue_test.cc)
target_link_libraries(queue_test srslte_common ${CMAKE_THREAD_LIBS_INIT}) target_link_libraries(queue_test srslte_common ${CMAKE_THREAD_LIBS_INIT})
add_test(queue_test queue_test) add_test(queue_test queue_test)
add_executable(timer_test timer_test.cc)
target_link_libraries(timer_test srslte_common)

@ -0,0 +1,204 @@
/*
* Copyright 2013-2019 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/.
*
*/
#include "srslte/common/timers.h"
#include <iostream>
#define TESTASSERT(cond) \
do { \
if (!(cond)) { \
std::cout << "[" << __FUNCTION__ << "][Line " << __LINE__ << "]: FAIL at " << (#cond) << std::endl; \
return -1; \
} \
} while (0)
using namespace srslte;
int timers2_test()
{
timer_handler timers;
uint32_t dur = 5;
{
timer_handler::unique_timer t = timers.get_unique_timer();
TESTASSERT(not t.is_running() and not t.is_expired());
TESTASSERT(t.id() == 0);
timer_handler::unique_timer t2 = timers.get_unique_timer();
TESTASSERT(not t2.is_running() and not t2.is_expired());
TESTASSERT(t2.id() == 1);
TESTASSERT(timers.nof_timers() == 2);
// TEST: Run multiple times with the same duration
bool callback_called = false;
t.set(dur, [&callback_called](int) { callback_called = true; });
TESTASSERT(timers.get_cur_time() == 0);
for (uint32_t runs = 0; runs < 3; ++runs) {
callback_called = false;
TESTASSERT(not t.is_running());
t.run();
TESTASSERT(t.is_running() and not t.is_expired());
for (uint32_t i = 0; i < dur - 1; ++i) {
timers.step_all();
TESTASSERT(t.is_running() and not t.is_expired());
}
timers.step_all();
TESTASSERT(not t.is_running() and t.is_expired());
TESTASSERT(callback_called);
}
TESTASSERT(timers.get_cur_time() == 3 * dur);
// TEST: interrupt a timer. check if callback was called
callback_called = false;
t.run();
timers.step_all();
TESTASSERT(t.is_running());
t.stop();
TESTASSERT(not t.is_running());
for (uint32_t i = 0; i < dur; ++i) {
timers.step_all();
TESTASSERT(not t.is_running());
}
TESTASSERT(not callback_called);
// TEST: call timer::run() when it is already running. Check if duration gets extended.
callback_called = false;
t.run();
timers.step_all();
TESTASSERT(t.is_running());
t.run(); // re-run
for (uint32_t i = 0; i < dur - 1; ++i) {
timers.step_all();
TESTASSERT(t.is_running());
}
timers.step_all();
TESTASSERT(not t.is_running());
TESTASSERT(callback_called);
// TEST: ordering of timers is respected
timer_handler::unique_timer t3 = timers.get_unique_timer();
TESTASSERT(t3.id() == 2);
int first_id = -1, last_id = -1;
auto callback = [&first_id, &last_id](int id) {
if (first_id < 0) {
printf("First timer id=%d\n", id);
first_id = id;
}
last_id = id;
};
t.set(4, callback);
t2.set(2, callback);
t3.set(6, callback);
t.run();
t2.run();
t3.run();
for (uint32_t i = 0; i < 5; ++i) {
timers.step_all();
TESTASSERT(i >= 3 or t.is_running());
TESTASSERT(i >= 1 or t2.is_running());
TESTASSERT(t3.is_running());
}
timers.step_all();
TESTASSERT(t.is_expired() and t2.is_expired() and t3.is_expired());
TESTASSERT(first_id == 1);
printf("Last timer id=%d\n", last_id);
TESTASSERT(last_id == 2);
}
// TEST: timer dtor is called and removes "timer" from "timers"
TESTASSERT(timers.nof_timers() == 0);
return SRSLTE_SUCCESS;
}
int timers2_test2()
{
/**
* Description:
* - calling stop() early, forbids the timer from getting expired
* - calling stop() after timer has expired should be a noop
*/
timer_handler timers;
uint32_t duration = 2;
auto utimer = timers.get_unique_timer();
auto utimer2 = timers.get_unique_timer();
utimer.set(duration);
utimer2.set(duration);
// TEST 1: call utimer.stop() early and check if timer expires
utimer.run();
utimer2.run();
TESTASSERT(utimer.is_running() and not utimer.is_expired());
utimer.stop();
TESTASSERT(not utimer.is_running() and not utimer.is_expired());
for (uint32_t i = 0; i < 5; ++i) {
timers.step_all();
}
TESTASSERT(not utimer.is_expired());
TESTASSERT(utimer2.is_expired());
// TEST 2: call utimer.stop() after it expires and assert it is still expired
utimer2.stop();
TESTASSERT(utimer2.is_expired());
return SRSLTE_SUCCESS;
}
int timers2_test3()
{
/**
* Description:
* - setting a new duration while the timer is already running should not stop timer, and should extend timeout
*/
timer_handler timers;
uint32_t duration = 5;
auto utimer = timers.get_unique_timer();
utimer.set(duration);
utimer.run();
for (uint32_t i = 0; i < 2 * duration + 1; ++i) {
timers.step_all();
if ((i % 2) == 0) {
// extends lifetime
utimer.set(duration);
}
TESTASSERT(utimer.is_running());
}
for (uint32_t i = 0; i < duration - 1; ++i) {
timers.step_all();
TESTASSERT(utimer.is_running());
}
timers.step_all();
TESTASSERT(not utimer.is_running());
return SRSLTE_SUCCESS;
}
int main()
{
TESTASSERT(timers2_test() == SRSLTE_SUCCESS);
TESTASSERT(timers2_test2() == SRSLTE_SUCCESS);
TESTASSERT(timers2_test3() == SRSLTE_SUCCESS);
printf("Success\n");
return 0;
}

@ -140,7 +140,7 @@ bool basic_test()
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
timers timers(8); timer_handler timers(8);
byte_buffer_t pdu_bufs[NBUFS]; byte_buffer_t pdu_bufs[NBUFS];
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -200,7 +200,7 @@ bool concat_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -265,7 +265,7 @@ bool segment_test(bool in_seq_rx)
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -359,7 +359,7 @@ bool retx_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
timers timers(8); timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -453,7 +453,7 @@ bool resegment_test_1()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
timers timers(8); timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -559,7 +559,7 @@ bool resegment_test_2()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
timers timers(8); timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -662,7 +662,7 @@ bool resegment_test_3()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -759,7 +759,7 @@ bool resegment_test_4()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -858,7 +858,7 @@ bool resegment_test_5()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -957,7 +957,7 @@ bool resegment_test_6()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -1094,7 +1094,7 @@ bool resegment_test_7()
#else #else
rlc_am_tester tester(NULL); rlc_am_tester tester(NULL);
#endif #endif
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -1267,7 +1267,7 @@ bool resegment_test_8()
#else #else
rlc_am_tester tester(NULL); rlc_am_tester tester(NULL);
#endif #endif
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers); rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -1411,7 +1411,7 @@ bool reset_test()
log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -1456,7 +1456,7 @@ bool resume_test()
log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -1501,7 +1501,7 @@ bool stop_test()
log1.set_level(srslte::LOG_LEVEL_DEBUG); log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -1533,7 +1533,7 @@ bool status_pdu_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_am_tester tester; rlc_am_tester tester;
srslte::timers timers(8); srslte::timer_handler timers(8);
int len = 0; int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers); rlc_am rlc1(&log1, 1, &tester, &tester, &timers);

@ -80,7 +80,7 @@ int basic_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_tester tester; rlc_tester tester;
srslte::timers timers(1); srslte::timer_handler timers(1);
int len = 0; int len = 0;

@ -118,7 +118,7 @@ public:
rlc_interface_mac* rlc2_, rlc_interface_mac* rlc2_,
stress_test_args_t args_, stress_test_args_t args_,
uint32_t lcid_, uint32_t lcid_,
timers* timers_, timer_handler* timers_,
rlc_pcap* pcap_ = NULL) : rlc_pcap* pcap_ = NULL) :
run_enable(true), run_enable(true),
rlc1(rlc1_), rlc1(rlc1_),
@ -204,17 +204,13 @@ private:
rlc_pcap* pcap; rlc_pcap* pcap;
uint32_t lcid; uint32_t lcid;
srslte::log_filter log; srslte::log_filter log;
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
std::mt19937 mt19937; std::mt19937 mt19937;
std::uniform_real_distribution<float> real_dist; std::uniform_real_distribution<float> real_dist;
}; };
class rlc_tester : public pdcp_interface_rlc, public rrc_interface_rlc, public thread
class rlc_tester
:public pdcp_interface_rlc
,public rrc_interface_rlc
,public thread
{ {
public: public:
rlc_tester(rlc_interface_pdcp* rlc_, std::string name_, stress_test_args_t args_, uint32_t lcid_) : rlc_tester(rlc_interface_pdcp* rlc_, std::string name_, stress_test_args_t args_, uint32_t lcid_) :
@ -339,7 +335,7 @@ void stress_test(stress_test_args_t args)
exit(-1); exit(-1);
} }
srslte::timers timers(8); srslte::timer_handler timers(8);
rlc rlc1(&log1); rlc rlc1(&log1);
rlc rlc2(&log2); rlc rlc2(&log2);

@ -86,7 +86,7 @@ int rlc_um_nr_test1()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_um_tester tester; rlc_um_tester tester;
srslte::timers timers(16); srslte::timer_handler timers(16);
const uint32_t num_sdus = 5; const uint32_t num_sdus = 5;
int len = 0; int len = 0;
@ -140,7 +140,7 @@ int rlc_um_nr_test2()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_um_tester tester; rlc_um_tester tester;
srslte::timers timers(16); srslte::timer_handler timers(16);
const uint32_t num_sdus = 1; const uint32_t num_sdus = 1;
const uint32_t sdu_size = 100; const uint32_t sdu_size = 100;
int len = 0; int len = 0;

@ -48,7 +48,7 @@ int basic_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_um_tester tester; rlc_um_tester tester;
srslte::timers timers(16); srslte::timer_handler timers(16);
int len = 0; int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
@ -117,7 +117,7 @@ int loss_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_um_tester tester; rlc_um_tester tester;
srslte::timers timers(16); srslte::timer_handler timers(16);
int len = 0; int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
@ -161,8 +161,11 @@ int loss_test()
} }
// Step the reordering timer until expiry // Step the reordering timer until expiry
while (!timers.get(1)->is_expired()) // while (!timers.get(1)->is_expired())
timers.get(1)->step(); // timers.get(1)->step();
while (timers.nof_running_timers() != 0) {
timers.step_all();
}
TESTASSERT(NBUFS - 1 == tester.sdus.size()); TESTASSERT(NBUFS - 1 == tester.sdus.size());
@ -178,7 +181,7 @@ int basic_mbsfn_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_um_tester tester; rlc_um_tester tester;
srslte::timers timers(16); srslte::timer_handler timers(16);
int len = 0; int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
@ -249,7 +252,7 @@ int reassmble_test()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_um_tester tester; rlc_um_tester tester;
srslte::timers timers(16); srslte::timer_handler timers(16);
int len = 0; int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
@ -358,7 +361,7 @@ int reassmble_test2()
log1.set_hex_limit(-1); log1.set_hex_limit(-1);
log2.set_hex_limit(-1); log2.set_hex_limit(-1);
rlc_um_tester tester; rlc_um_tester tester;
srslte::timers timers(16); srslte::timer_handler timers(16);
int len = 0; int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers); rlc_um rlc1(&log1, 3, &tester, &tester, &timers);

@ -106,7 +106,7 @@ private:
srsenb::s1ap s1ap; srsenb::s1ap s1ap;
srslte::logger* logger = nullptr; srslte::logger* logger = nullptr;
srslte::timers timers; srslte::timer_handler timers;
// Radio and PHY log are in enb.cc // Radio and PHY log are in enb.cc
srslte::log_filter mac_log; srslte::log_filter mac_log;

@ -44,11 +44,7 @@ public:
virtual bool process_pdus() = 0; virtual bool process_pdus() = 0;
}; };
class mac : public mac_interface_phy_lte, class mac : public mac_interface_phy_lte, public mac_interface_rlc, public mac_interface_rrc, public pdu_process_handler
public mac_interface_rlc,
public mac_interface_rrc,
public srslte::mac_interface_timers,
public pdu_process_handler
{ {
public: public:
mac(); mac();
@ -107,11 +103,6 @@ public:
bool process_pdus(); bool process_pdus();
// Interface for upper-layer timers
srslte::timers::timer* timer_get(uint32_t timer_id);
void timer_release_id(uint32_t timer_id);
u_int32_t timer_get_unique_id();
uint32_t get_current_tti(); uint32_t get_current_tti();
void get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]); void get_metrics(mac_metrics_t metrics[ENB_METRICS_MAX_USERS]);
void write_mcch(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s* mcch); void write_mcch(asn1::rrc::sib_type2_s* sib2, asn1::rrc::sib_type13_r9_s* sib13, asn1::rrc::mcch_msg_s* mcch);
@ -179,23 +170,24 @@ private:
uint8_t mtch_payload_buffer[mtch_payload_len]; uint8_t mtch_payload_buffer[mtch_payload_len];
/* Functions for MAC Timers */ /* Functions for MAC Timers */
srslte::timers timers_db; srslte::timer_handler timers_db;
void setup_timers(); void setup_timers();
// pointer to MAC PCAP object // pointer to MAC PCAP object
srslte::mac_pcap* pcap; srslte::mac_pcap* pcap;
/* Class to run upper-layer timers with normal priority */ /* Class to run upper-layer timers with normal priority */
class timer_thread : public thread { class timer_thread : public thread
{
public: public:
timer_thread(mac* parent_, srslte::timers* t) : ttisync(10240), timers(t), running(false), parent(parent_), thread("MAC_TIMER") { start(); } timer_thread(mac* parent_, srslte::timer_handler* t) : ttisync(10240), timers(t), running(false), parent(parent_), thread("MAC_TIMER") { start(); }
void tti_clock(); void tti_clock();
void stop(); void stop();
private: private:
void run_thread(); void run_thread();
srslte::tti_sync_cv ttisync; srslte::tti_sync_cv ttisync;
srslte::timers *timers; srslte::timer_handler *timers;
mac *parent; mac *parent;
bool running; bool running;
}; };

@ -36,15 +36,13 @@ typedef struct {
namespace srsenb { namespace srsenb {
class rlc : public rlc_interface_mac, class rlc : public rlc_interface_mac, public rlc_interface_rrc, public rlc_interface_pdcp
public rlc_interface_rrc,
public rlc_interface_pdcp
{ {
public: public:
void init(pdcp_interface_rlc* pdcp_, void init(pdcp_interface_rlc* pdcp_,
rrc_interface_rlc* rrc_, rrc_interface_rlc* rrc_,
mac_interface_rlc* mac_, mac_interface_rlc* mac_,
srslte::timers* timers_, srslte::timer_handler* timers_,
srslte::log* log_h); srslte::log* log_h);
void stop(); void stop();
@ -96,7 +94,7 @@ private:
rrc_interface_rlc* rrc; rrc_interface_rlc* rrc;
srslte::log* log_h; srslte::log* log_h;
srslte::byte_buffer_pool* pool; srslte::byte_buffer_pool* pool;
srslte::timers* timers; srslte::timer_handler* timers;
}; };
} // namespace srsenb } // namespace srsenb

@ -841,28 +841,6 @@ void mac::tti_clock()
timers_thread.tti_clock(); timers_thread.tti_clock();
} }
/********************************************************
*
* Interface for upper layer timers
*
*******************************************************/
uint32_t mac::timer_get_unique_id()
{
return timers_db.get_unique_id();
}
void mac::timer_release_id(uint32_t timer_id)
{
timers_db.release_id(timer_id);
}
/* Front-end to upper-layer timers */
srslte::timers::timer* mac::timer_get(uint32_t timer_id)
{
return timers_db.get(timer_id);
}
/******************************************************** /********************************************************
* *
* Class to run timers with normal priority * Class to run timers with normal priority

@ -27,7 +27,7 @@ namespace srsenb {
void rlc::init(pdcp_interface_rlc* pdcp_, void rlc::init(pdcp_interface_rlc* pdcp_,
rrc_interface_rlc* rrc_, rrc_interface_rlc* rrc_,
mac_interface_rlc* mac_, mac_interface_rlc* mac_,
srslte::timers* timers_, srslte::timer_handler* timers_,
srslte::log* log_h_) srslte::log* log_h_)
{ {
pdcp = pdcp_; pdcp = pdcp_;

@ -47,7 +47,7 @@ public:
void init(phy_interface_mac_common* phy_h_, void init(phy_interface_mac_common* phy_h_,
rlc_interface_mac* rlc, rlc_interface_mac* rlc,
mac_interface_demux* mac, mac_interface_demux* mac,
srslte::timers::timer* time_alignment_timer); srslte::timer_handler::unique_timer* time_alignment_timer);
bool process_pdus(); bool process_pdus();
uint8_t* request_buffer(uint32_t len); uint8_t* request_buffer(uint32_t len);
@ -83,7 +83,7 @@ private:
phy_interface_mac_common* phy_h = nullptr; phy_interface_mac_common* phy_h = nullptr;
srslte::log* log_h = nullptr; srslte::log* log_h = nullptr;
srslte::timers::timer* time_alignment_timer = nullptr; srslte::timer_handler::unique_timer* time_alignment_timer = nullptr;
rlc_interface_mac* rlc = nullptr; rlc_interface_mac* rlc = nullptr;
mac_interface_demux* mac = nullptr; mac_interface_demux* mac = nullptr;

@ -42,7 +42,7 @@ public:
bool init(srslte::log* log_h, bool init(srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis, mac_interface_rrc::ue_rnti_t* rntis,
srslte::timers::timer* timer_aligment_timer, srslte::timer_handler::unique_timer* timer_aligment_timer,
demux* demux_unit); demux* demux_unit);
void reset(); void reset();
void start_pcap(srslte::mac_pcap* pcap_); void start_pcap(srslte::mac_pcap* pcap_);
@ -121,7 +121,7 @@ private:
std::vector<dl_harq_process> proc; std::vector<dl_harq_process> proc;
dl_harq_process bcch_proc; dl_harq_process bcch_proc;
srslte::timers::timer *timer_aligment_timer; srslte::timer_handler::unique_timer* timer_aligment_timer = nullptr;
demux* demux_unit; demux* demux_unit;
srslte::log* log_h; srslte::log* log_h;
srslte::mac_pcap* pcap; srslte::mac_pcap* pcap;

@ -45,7 +45,6 @@ namespace srsue {
class mac : public mac_interface_phy_lte, class mac : public mac_interface_phy_lte,
public mac_interface_rrc, public mac_interface_rrc,
public srslte::timer_callback, public srslte::timer_callback,
public srslte::mac_interface_timers,
public mac_interface_demux public mac_interface_demux
{ {
public: public:
@ -54,7 +53,7 @@ public:
bool init(phy_interface_mac_lte* phy, bool init(phy_interface_mac_lte* phy,
rlc_interface_mac* rlc, rlc_interface_mac* rlc,
rrc_interface_mac* rrc, rrc_interface_mac* rrc,
srslte::timers* timers_, srslte::timer_handler* timers_,
stack_interface_mac* stack); stack_interface_mac* stack);
void stop(); void stop();
@ -113,11 +112,6 @@ public:
uint32_t get_current_tti(); uint32_t get_current_tti();
// Interface for upper-layer timers
srslte::timers::timer* timer_get(uint32_t timer_id);
void timer_release_id(uint32_t timer_id);
uint32_t timer_get_unique_id();
private: private:
void clear_rntis(); void clear_rntis();
@ -169,10 +163,10 @@ private:
srslte::mch_pdu mch_msg; srslte::mch_pdu mch_msg;
/* Functions for MAC Timers */ /* Functions for MAC Timers */
uint32_t timer_alignment = 0; srslte::timer_handler::unique_timer timer_alignment;
void setup_timers(int time_alignment_timer); void setup_timers(int time_alignment_timer);
void timer_alignment_expire(); void timer_alignment_expire();
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
// pointer to MAC PCAP object // pointer to MAC PCAP object
srslte::mac_pcap* pcap = nullptr; srslte::mac_pcap* pcap = nullptr;

@ -55,7 +55,7 @@ class bsr_proc : public srslte::timer_callback, public bsr_interface_mux
{ {
public: public:
bsr_proc(); bsr_proc();
void init(rlc_interface_mac* rlc, srslte::log* log_h, srslte::timers* timers_db); void init(rlc_interface_mac* rlc, srslte::log* log_h, srslte::timer_handler* timers_db);
void step(uint32_t tti); void step(uint32_t tti);
void reset(); void reset();
void set_config(srslte::bsr_cfg_t& bsr_cfg); void set_config(srslte::bsr_cfg_t& bsr_cfg);
@ -74,7 +74,7 @@ private:
pthread_mutex_t mutex; pthread_mutex_t mutex;
bool reset_sr; bool reset_sr;
srslte::timers *timers_db; srslte::timer_handler* timers_db;
srslte::log* log_h; srslte::log* log_h;
rlc_interface_mac* rlc; rlc_interface_mac* rlc;
@ -112,8 +112,8 @@ private:
char* bsr_type_tostring(triggered_bsr_type_t type); char* bsr_type_tostring(triggered_bsr_type_t type);
char* bsr_format_tostring(bsr_format_t format); char* bsr_format_tostring(bsr_format_t format);
uint32_t timer_periodic_id; srslte::timer_handler::unique_timer timer_periodic;
uint32_t timer_retx_id; srslte::timer_handler::unique_timer timer_retx;
}; };
} // namespace srsue } // namespace srsue

@ -37,7 +37,7 @@ class phr_proc : public srslte::timer_callback
{ {
public: public:
phr_proc(); phr_proc();
void init(phy_interface_mac_lte* phy_h, srslte::log* log_h_, srslte::timers* timers_db_); void init(phy_interface_mac_lte* phy_h, srslte::log* log_h_, srslte::timer_handler* timers_db_);
void set_config(srslte::phr_cfg_t& cfg); void set_config(srslte::phr_cfg_t& cfg);
void step(uint32_t tti); void step(uint32_t tti);
void reset(); void reset();
@ -49,20 +49,18 @@ public:
void start_timer(); void start_timer();
private: private:
bool pathloss_changed(); bool pathloss_changed();
srslte::log* log_h; srslte::log* log_h;
phy_interface_mac_lte* phy_h; phy_interface_mac_lte* phy_h;
srslte::timers* timers_db; srslte::timer_handler* timers_db;
srslte::phr_cfg_t phr_cfg; srslte::phr_cfg_t phr_cfg;
bool initiated; bool initiated;
int last_pathloss_db; int last_pathloss_db;
bool phr_is_triggered; bool phr_is_triggered;
uint32_t timer_periodic_id; srslte::timer_handler::unique_timer timer_periodic;
uint32_t timer_prohibit_id; srslte::timer_handler::unique_timer timer_prohibit;
}; };
} // namespace srsue } // namespace srsue

@ -62,9 +62,6 @@ public:
noncontention_enabled = false; noncontention_enabled = false;
next_preamble_idx = 0; next_preamble_idx = 0;
next_prach_mask = 0; next_prach_mask = 0;
time_alignment_timer = NULL;
contention_resolution_timer = NULL;
}; };
~ra_proc(); ~ra_proc();
@ -73,8 +70,8 @@ public:
rrc_interface_mac* rrc_, rrc_interface_mac* rrc_,
srslte::log* log_h, srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis, mac_interface_rrc::ue_rnti_t* rntis,
srslte::timers::timer* time_alignment_timer_, srslte::timer_handler::unique_timer* time_alignment_timer_,
srslte::timers::timer* contention_resolution_timer_, srslte::timer_handler::unique_timer contention_resolution_timer_,
mux* mux_unit, mux* mux_unit,
stack_interface_mac* stack_); stack_interface_mac* stack_);
@ -171,8 +168,8 @@ private:
rrc_interface_mac* rrc; rrc_interface_mac* rrc;
stack_interface_mac* stack; stack_interface_mac* stack;
srslte::timers::timer* time_alignment_timer; srslte::timer_handler::unique_timer* time_alignment_timer = nullptr;
srslte::timers::timer* contention_resolution_timer; srslte::timer_handler::unique_timer contention_resolution_timer;
mac_interface_rrc::ue_rnti_t* rntis; mac_interface_rrc::ue_rnti_t* rntis;

@ -303,7 +303,7 @@ public:
nas_interface_rrc* nas_, nas_interface_rrc* nas_,
usim_interface_rrc* usim_, usim_interface_rrc* usim_,
gw_interface_rrc* gw_, gw_interface_rrc* gw_,
srslte::timers* timers_, srslte::timer_handler* timers_,
stack_interface_rrc* stack_, stack_interface_rrc* stack_,
const rrc_args_t& args_); const rrc_args_t& args_);
@ -419,10 +419,10 @@ private:
std::map<uint32_t, asn1::rrc::drb_to_add_mod_s> drbs; std::map<uint32_t, asn1::rrc::drb_to_add_mod_s> drbs;
// RRC constants and timers // RRC constants and timers
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
uint32_t n310_cnt = 0, N310 = 0; uint32_t n310_cnt, N310 = 0;
uint32_t n311_cnt = 0, N311 = 0; uint32_t n311_cnt, N311 = 0;
uint32_t t300 = 0, t301 = 0, t302 = 0, t310 = 0, t311 = 0, t304 = 0; srslte::timer_handler::unique_timer t300, t301, t302, t310, t311, t304;
// Radio bearers // Radio bearers
typedef enum { typedef enum {
@ -534,7 +534,7 @@ private:
uint32_t report_id; uint32_t report_id;
uint32_t object_id; uint32_t object_id;
bool triggered; bool triggered;
uint32_t periodic_timer; srslte::timer_handler::unique_timer periodic_timer;
std::map<uint32_t, meas_value_t> cell_values; // Value for each PCI in this object std::map<uint32_t, meas_value_t> cell_values; // Value for each PCI in this object
} meas_t; } meas_t;
@ -545,7 +545,7 @@ private:
rrc* parent = nullptr; rrc* parent = nullptr;
srslte::log* log_h = nullptr; srslte::log* log_h = nullptr;
phy_interface_rrc_lte* phy = nullptr; phy_interface_rrc_lte* phy = nullptr;
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
uint32_t filter_k_rsrp, filter_k_rsrq = 0; uint32_t filter_k_rsrp, filter_k_rsrq = 0;
float filter_a[NOF_MEASUREMENTS] = {}; float filter_a[NOF_MEASUREMENTS] = {};

@ -132,7 +132,7 @@ private:
srsue::stack_args_t args; srsue::stack_args_t args;
// timers // timers
srslte::timers timers; srslte::timer_handler timers;
// UE stack logging // UE stack logging
srslte::logger* logger = nullptr; srslte::logger* logger = nullptr;

@ -40,7 +40,7 @@ namespace srsue {
class nas : public nas_interface_rrc, public nas_interface_ue, public srslte::timer_callback class nas : public nas_interface_rrc, public nas_interface_ue, public srslte::timer_callback
{ {
public: public:
nas(srslte::log* log_, srslte::timers* timers_); nas(srslte::log* log_, srslte::timer_handler* timers_);
void init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& args_); void init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_nas* gw_, const nas_args_t& args_);
void stop(); void stop();
void run_tti(uint32_t tti) final; void run_tti(uint32_t tti) final;
@ -131,9 +131,9 @@ private:
uint8_t transaction_id = 0; uint8_t transaction_id = 0;
// timers // timers
srslte::timers* timers = nullptr; srslte::timer_handler* timers = nullptr;
uint32_t t3410 = 0; // started when attach request is sent, on expiry, start t3411 srslte::timer_handler::unique_timer t3410; // started when attach request is sent, on expiry, start t3411
uint32_t t3411 = 0; // started when attach failed srslte::timer_handler::unique_timer t3411; // started when attach failed
const uint32_t t3410_duration_ms = 15 * 1000; // 15s according to TS 24.301 Sec 10.2 const uint32_t t3410_duration_ms = 15 * 1000; // 15s according to TS 24.301 Sec 10.2
const uint32_t t3411_duration_ms = 10 * 1000; // 10s according to TS 24.301 Sec 10.2 const uint32_t t3411_duration_ms = 10 * 1000; // 10s according to TS 24.301 Sec 10.2

@ -46,7 +46,7 @@ demux::demux(srslte::log* log_) :
void demux::init(phy_interface_mac_common* phy_, void demux::init(phy_interface_mac_common* phy_,
rlc_interface_mac* rlc_, rlc_interface_mac* rlc_,
mac_interface_demux* mac_, mac_interface_demux* mac_,
srslte::timers::timer* time_alignment_timer_) srslte::timer_handler::unique_timer* time_alignment_timer_)
{ {
phy_h = phy_; phy_h = phy_;
rlc = rlc_; rlc = rlc_;
@ -275,7 +275,6 @@ bool demux::process_ce(srslte::sch_subh *subh) {
Info("Received TA=%d\n", subh->get_ta_cmd()); Info("Received TA=%d\n", subh->get_ta_cmd());
// Start or restart timeAlignmentTimer only if running // Start or restart timeAlignmentTimer only if running
if (time_alignment_timer->is_running()) { if (time_alignment_timer->is_running()) {
time_alignment_timer->reset();
time_alignment_timer->run(); time_alignment_timer->run();
} }
break; break;

@ -46,10 +46,10 @@ dl_harq_entity::dl_harq_entity() : proc(SRSLTE_MAX_HARQ_PROC)
bool dl_harq_entity::init(srslte::log* log_h, bool dl_harq_entity::init(srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis, mac_interface_rrc::ue_rnti_t* rntis,
srslte::timers::timer* timer_aligment_timer, srslte::timer_handler::unique_timer* timer_aligment_timer_,
demux* demux_unit) demux* demux_unit)
{ {
this->timer_aligment_timer = timer_aligment_timer; timer_aligment_timer = timer_aligment_timer_;
this->demux_unit = demux_unit; this->demux_unit = demux_unit;
this->log_h = log_h; this->log_h = log_h;
this->rntis = rntis; this->rntis = rntis;

@ -68,7 +68,7 @@ mac::~mac()
bool mac::init(phy_interface_mac_lte* phy, bool mac::init(phy_interface_mac_lte* phy,
rlc_interface_mac* rlc, rlc_interface_mac* rlc,
rrc_interface_mac* rrc, rrc_interface_mac* rrc,
srslte::timers* timers_, srslte::timer_handler* timers_,
stack_interface_mac* stack_) stack_interface_mac* stack_)
{ {
phy_h = phy; phy_h = phy;
@ -77,26 +77,20 @@ bool mac::init(phy_interface_mac_lte* phy,
timers = timers_; timers = timers_;
stack_h = stack_; stack_h = stack_;
timer_alignment = timers->get_unique_id(); timer_alignment = timers->get_unique_timer();
uint32_t contention_resolution_timer = timers->get_unique_id(); srslte::timer_handler::unique_timer contention_resolution_timer = timers->get_unique_timer();
bsr_procedure.init(rlc_h, log_h, timers); bsr_procedure.init(rlc_h, log_h, timers);
phr_procedure.init(phy_h, log_h, timers); phr_procedure.init(phy_h, log_h, timers);
mux_unit.init(rlc_h, &bsr_procedure, &phr_procedure); mux_unit.init(rlc_h, &bsr_procedure, &phr_procedure);
demux_unit.init(phy_h, rlc_h, this, timers->get(timer_alignment)); demux_unit.init(phy_h, rlc_h, this, &timer_alignment);
ra_procedure.init(phy_h, ra_procedure.init(
rrc, phy_h, rrc, log_h, &uernti, &timer_alignment, std::move(contention_resolution_timer), &mux_unit, stack_h);
log_h,
&uernti,
timers->get(timer_alignment),
timers->get(contention_resolution_timer),
&mux_unit,
stack_h);
sr_procedure.init(phy_h, rrc, log_h); sr_procedure.init(phy_h, rrc, log_h);
// Create UL/DL unique HARQ pointers // Create UL/DL unique HARQ pointers
ul_harq.at(0)->init(log_h, &uernti, &ra_procedure, &mux_unit); ul_harq.at(0)->init(log_h, &uernti, &ra_procedure, &mux_unit);
dl_harq.at(0)->init(log_h, &uernti, timers->get(timer_alignment), &demux_unit); dl_harq.at(0)->init(log_h, &uernti, &timer_alignment, &demux_unit);
reset(); reset();
@ -143,7 +137,7 @@ void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable)
} }
while (dl_harq.size() < cc_idx + 1) { while (dl_harq.size() < cc_idx + 1) {
auto dl = dl_harq_entity_ptr(new dl_harq_entity()); auto dl = dl_harq_entity_ptr(new dl_harq_entity());
dl->init(log_h, &uernti, timers->get(timer_alignment), &demux_unit); dl->init(log_h, &uernti, &timer_alignment, &demux_unit);
if (pcap) { if (pcap) {
dl->start_pcap(pcap); dl->start_pcap(pcap);
@ -170,7 +164,7 @@ void mac::reset()
Info("Resetting MAC\n"); Info("Resetting MAC\n");
timers->get(timer_alignment)->stop(); timer_alignment.stop();
timer_alignment_expire(); timer_alignment_expire();
@ -529,18 +523,18 @@ void mac::new_mch_dl(srslte_pdsch_grant_t phy_grant, tb_action_dl_t* action)
void mac::setup_timers(int time_alignment_timer) void mac::setup_timers(int time_alignment_timer)
{ {
// stop currently running time alignment timer // stop currently running time alignment timer
if (timers->get(timer_alignment)->is_running()) { if (timer_alignment.is_running()) {
timers->get(timer_alignment)->stop(); timer_alignment.stop();
} }
if (time_alignment_timer > 0) { if (time_alignment_timer > 0) {
timers->get(timer_alignment)->set(this, time_alignment_timer); timer_alignment.set(time_alignment_timer, [this](uint32_t tid) { timer_expired(tid); });
} }
} }
void mac::timer_expired(uint32_t timer_id) void mac::timer_expired(uint32_t timer_id)
{ {
if(timer_id == timer_alignment) { if (timer_id == timer_alignment.id()) {
timer_alignment_expire(); timer_alignment_expire();
} else { } else {
Warning("Received callback from unknown timer_id=%d\n", timer_id); Warning("Received callback from unknown timer_id=%d\n", timer_id);
@ -669,24 +663,4 @@ void mac::get_metrics(mac_metrics_t m[SRSLTE_MAX_CARRIERS])
bzero(&metrics, sizeof(mac_metrics_t) * SRSLTE_MAX_CARRIERS); bzero(&metrics, sizeof(mac_metrics_t) * SRSLTE_MAX_CARRIERS);
} }
/********************************************************
*
* Interface for timers used by upper layers
*
*******************************************************/
srslte::timers::timer* mac::timer_get(uint32_t timer_id)
{
return timers->get(timer_id);
}
void mac::timer_release_id(uint32_t timer_id)
{
timers->release_id(timer_id);
}
uint32_t mac::timer_get_unique_id()
{
return timers->get_unique_id();
}
} // namespace srsue } // namespace srsue

@ -42,14 +42,14 @@ bsr_proc::bsr_proc()
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
} }
void bsr_proc::init(rlc_interface_mac* rlc_, srslte::log* log_h_, srslte::timers* timers_db_) void bsr_proc::init(rlc_interface_mac* rlc_, srslte::log* log_h_, srslte::timer_handler* timers_db_)
{ {
log_h = log_h_; log_h = log_h_;
rlc = rlc_; rlc = rlc_;
timers_db = timers_db_; timers_db = timers_db_;
timer_periodic_id = timers_db->get_unique_id(); timer_periodic = timers_db->get_unique_timer();
timer_retx_id = timers_db->get_unique_id(); timer_retx = timers_db->get_unique_timer();
reset(); reset();
initiated = true; initiated = true;
@ -63,10 +63,8 @@ void bsr_proc::set_trigger(srsue::bsr_proc::triggered_bsr_type_t new_trigger)
void bsr_proc::reset() void bsr_proc::reset()
{ {
timers_db->get(timer_periodic_id)->stop(); timer_periodic.stop();
timers_db->get(timer_periodic_id)->reset(); timer_retx.stop();
timers_db->get(timer_retx_id)->stop();
timers_db->get(timer_retx_id)->reset();
reset_sr = false; reset_sr = false;
sr_is_sent = false; sr_is_sent = false;
@ -82,27 +80,28 @@ void bsr_proc::set_config(srslte::bsr_cfg_t& bsr_cfg)
this->bsr_cfg = bsr_cfg; this->bsr_cfg = bsr_cfg;
if (bsr_cfg.periodic_timer > 0) { if (bsr_cfg.periodic_timer > 0) {
timers_db->get(timer_periodic_id)->set(this, bsr_cfg.periodic_timer); timer_periodic.set(bsr_cfg.periodic_timer, [this](uint32_t tid) { timer_expired(tid); });
Info("BSR: Configured timer periodic %d ms\n", bsr_cfg.periodic_timer); Info("BSR: Configured timer periodic %d ms\n", bsr_cfg.periodic_timer);
} }
if (bsr_cfg.retx_timer > 0) { if (bsr_cfg.retx_timer > 0) {
timers_db->get(timer_retx_id)->set(this, bsr_cfg.retx_timer); timer_retx.set(bsr_cfg.retx_timer, [this](uint32_t tid) { timer_expired(tid); });
Info("BSR: Configured timer reTX %d ms\n", bsr_cfg.retx_timer); Info("BSR: Configured timer reTX %d ms\n", bsr_cfg.retx_timer);
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
/* Process Periodic BSR */ /* Process Periodic BSR */
void bsr_proc::timer_expired(uint32_t timer_id) { void bsr_proc::timer_expired(uint32_t timer_id)
{
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
// periodicBSR-Timer // periodicBSR-Timer
if (timer_id == timer_periodic_id) { if (timer_id == timer_periodic.id()) {
if (triggered_bsr_type == NONE) { if (triggered_bsr_type == NONE) {
set_trigger(PERIODIC); set_trigger(PERIODIC);
Debug("BSR: Triggering Periodic BSR\n"); Debug("BSR: Triggering Periodic BSR\n");
} }
// retxBSR-Timer // retxBSR-Timer
} else if (timer_id == timer_retx_id) { } else if (timer_id == timer_retx.id()) {
// Enable reTx of SR only if periodic timer is not infinity // Enable reTx of SR only if periodic timer is not infinity
Debug("BSR: Timer BSR reTX expired, periodic=%d, channel=%d\n", bsr_cfg.periodic_timer, check_any_channel()); Debug("BSR: Timer BSR reTX expired, periodic=%d, channel=%d\n", bsr_cfg.periodic_timer, check_any_channel());
// Triger Regular BSR if UE has available data for transmission on any channel // Triger Regular BSR if UE has available data for transmission on any channel
@ -243,13 +242,16 @@ bool bsr_proc::generate_bsr(bsr_t* bsr, uint32_t nof_padding_bytes)
} }
} }
Info("BSR: Type %s, Format %s, Value=%d,%d,%d,%d\n", Info("BSR: Type %s, Format %s, Value=%d,%d,%d,%d\n",
bsr_type_tostring(triggered_bsr_type), bsr_format_tostring(bsr->format), bsr_type_tostring(triggered_bsr_type),
bsr->buff_size[0], bsr->buff_size[1], bsr->buff_size[2], bsr->buff_size[3]); bsr_format_tostring(bsr->format),
bsr->buff_size[0],
bsr->buff_size[1],
bsr->buff_size[2],
bsr->buff_size[3]);
// Restart or Start Periodic timer every time a BSR is generated and transmitted in an UL grant // Restart or Start Periodic timer every time a BSR is generated and transmitted in an UL grant
if (timers_db->get(timer_periodic_id)->get_timeout() && bsr->format != TRUNC_BSR) { if (timer_periodic.duration() && bsr->format != TRUNC_BSR) {
timers_db->get(timer_periodic_id)->reset(); timer_periodic.run();
timers_db->get(timer_periodic_id)->run();
Debug("BSR: Started periodicBSR-Timer\n"); Debug("BSR: Started periodicBSR-Timer\n");
} }
@ -360,9 +362,8 @@ bool bsr_proc::need_to_send_bsr_on_ul_grant(uint32_t grant_size, bsr_t* bsr)
reset_sr = true; reset_sr = true;
// Restart or Start ReTX timer upon indication of a grant // Restart or Start ReTX timer upon indication of a grant
if (timers_db->get(timer_retx_id)->get_timeout()) { if (timer_retx.duration()) {
timers_db->get(timer_retx_id)->reset(); timer_retx.run();
timers_db->get(timer_retx_id)->run();
Debug("BSR: Started retxBSR-Timer\n"); Debug("BSR: Started retxBSR-Timer\n");
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);

@ -38,23 +38,23 @@ phr_proc::phr_proc()
phr_cfg = {}; phr_cfg = {};
} }
void phr_proc::init(phy_interface_mac_lte* phy_h_, srslte::log* log_h_, srslte::timers* timers_db_) void phr_proc::init(phy_interface_mac_lte* phy_h_, srslte::log* log_h_, srslte::timer_handler* timers_db_)
{ {
phy_h = phy_h_; phy_h = phy_h_;
log_h = log_h_; log_h = log_h_;
timers_db = timers_db_; timers_db = timers_db_;
initiated = true; initiated = true;
timer_periodic_id = timers_db->get_unique_id(); timer_periodic = timers_db->get_unique_timer();
timer_prohibit_id = timers_db->get_unique_id(); timer_prohibit = timers_db->get_unique_timer();
reset(); reset();
} }
void phr_proc::reset() void phr_proc::reset()
{ {
timers_db->get(timer_periodic_id)->stop(); timer_periodic.stop();
timers_db->get(timer_prohibit_id)->stop(); timer_prohibit.stop();
phr_is_triggered = false; phr_is_triggered = false;
} }
@ -63,21 +63,21 @@ void phr_proc::set_config(srslte::phr_cfg_t& cfg)
phr_cfg = cfg; phr_cfg = cfg;
// First stop timers. If enabled==false or value is Inf, won't be re-started // First stop timers. If enabled==false or value is Inf, won't be re-started
timers_db->get(timer_periodic_id)->stop(); timer_periodic.stop();
timers_db->get(timer_prohibit_id)->stop(); timer_prohibit.stop();
if (cfg.enabled) { if (cfg.enabled) {
// Setup timers and trigger PHR when configuration changed by higher layers // Setup timers and trigger PHR when configuration changed by higher layers
if (phr_cfg.periodic_timer > 0) { if (phr_cfg.periodic_timer > 0) {
timers_db->get(timer_periodic_id)->set(this, phr_cfg.periodic_timer); timer_periodic.set(phr_cfg.periodic_timer, [this](uint32_t tid) { timer_expired(tid); });
timers_db->get(timer_periodic_id)->run(); timer_periodic.run();
phr_is_triggered = true; phr_is_triggered = true;
Info("PHR: Configured timer periodic %d ms\n", phr_cfg.periodic_timer); Info("PHR: Configured timer periodic %d ms\n", phr_cfg.periodic_timer);
} }
if (phr_cfg.prohibit_timer > 0) { if (phr_cfg.prohibit_timer > 0) {
timers_db->get(timer_prohibit_id)->set(this, phr_cfg.prohibit_timer); timer_prohibit.set(phr_cfg.prohibit_timer, [this](uint32_t tid) { timer_expired(tid); });
timers_db->get(timer_prohibit_id)->run(); timer_prohibit.run();
Info("PHR: Configured timer prohibit %d ms\n", phr_cfg.prohibit_timer); Info("PHR: Configured timer prohibit %d ms\n", phr_cfg.prohibit_timer);
phr_is_triggered = true; phr_is_triggered = true;
} }
@ -99,22 +99,23 @@ bool phr_proc::pathloss_changed() {
} }
} }
void phr_proc::start_timer() { void phr_proc::start_timer()
timers_db->get(timer_periodic_id)->run(); {
timer_periodic.run();
} }
/* Trigger PHR when timers exires */ /* Trigger PHR when timers exires */
void phr_proc::timer_expired(uint32_t timer_id) { void phr_proc::timer_expired(uint32_t timer_id)
{
if (!phr_cfg.enabled) { if (!phr_cfg.enabled) {
Warning("PHR: Timer triggered but PHR has been disabled\n"); Warning("PHR: Timer triggered but PHR has been disabled\n");
return; return;
} }
if (timer_id == timer_periodic_id) { if (timer_id == timer_periodic.id()) {
timers_db->get(timer_periodic_id)->reset(); timer_periodic.run();
timers_db->get(timer_periodic_id)->run();
Debug("PHR: Triggered by timer periodic (timer expired).\n"); Debug("PHR: Triggered by timer periodic (timer expired).\n");
phr_is_triggered = true; phr_is_triggered = true;
} else if (timer_id == timer_prohibit_id) { } else if (timer_id == timer_prohibit.id()) {
if (pathloss_changed()) { if (pathloss_changed()) {
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d (timer expired)\n", last_pathloss_db); Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d (timer expired)\n", last_pathloss_db);
phr_is_triggered = true; phr_is_triggered = true;
@ -127,7 +128,7 @@ void phr_proc::timer_expired(uint32_t timer_id) {
void phr_proc::step(uint32_t tti) void phr_proc::step(uint32_t tti)
{ {
if (phr_cfg.enabled && initiated) { if (phr_cfg.enabled && initiated) {
if (pathloss_changed() && timers_db->get(timer_prohibit_id)->is_expired()) { if (pathloss_changed() && timer_prohibit.is_expired()) {
Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d\n", last_pathloss_db); Info("PHR: Triggered by pathloss difference. cur_pathloss_db=%d\n", last_pathloss_db);
phr_is_triggered = true; phr_is_triggered = true;
} }
@ -144,10 +145,8 @@ bool phr_proc::generate_phr_on_ul_grant(float *phr)
Debug("PHR: Generating PHR=%f\n", phr ? *phr : 0.0); Debug("PHR: Generating PHR=%f\n", phr ? *phr : 0.0);
timers_db->get(timer_periodic_id)->reset(); timer_periodic.run();
timers_db->get(timer_prohibit_id)->reset(); timer_prohibit.run();
timers_db->get(timer_periodic_id)->run();
timers_db->get(timer_prohibit_id)->run();
phr_is_triggered = false; phr_is_triggered = false;

@ -60,8 +60,8 @@ void ra_proc::init(phy_interface_mac_lte* phy_h_,
rrc_interface_mac* rrc_, rrc_interface_mac* rrc_,
srslte::log* log_h_, srslte::log* log_h_,
mac_interface_rrc::ue_rnti_t* rntis_, mac_interface_rrc::ue_rnti_t* rntis_,
srslte::timers::timer* time_alignment_timer_, srslte::timer_handler::unique_timer* time_alignment_timer_,
srslte::timers::timer* contention_resolution_timer_, srslte::timer_handler::unique_timer contention_resolution_timer_,
mux* mux_unit_, mux* mux_unit_,
stack_interface_mac* stack_) stack_interface_mac* stack_)
{ {
@ -73,22 +73,23 @@ void ra_proc::init(phy_interface_mac_lte* phy_h_,
stack = stack_; stack = stack_;
time_alignment_timer = time_alignment_timer_; time_alignment_timer = time_alignment_timer_;
contention_resolution_timer = contention_resolution_timer_; contention_resolution_timer = std::move(contention_resolution_timer_);
srslte_softbuffer_rx_init(&softbuffer_rar, 10); srslte_softbuffer_rx_init(&softbuffer_rar, 10);
reset(); reset();
} }
ra_proc::~ra_proc() { ra_proc::~ra_proc()
{
srslte_softbuffer_rx_free(&softbuffer_rar); srslte_softbuffer_rx_free(&softbuffer_rar);
} }
void ra_proc::reset() { void ra_proc::reset()
{
state = IDLE; state = IDLE;
started_by_pdcch = false; started_by_pdcch = false;
contention_resolution_timer->stop(); contention_resolution_timer.stop();
contention_resolution_timer->reset();
} }
void ra_proc::start_pcap(srslte::mac_pcap* pcap_) void ra_proc::start_pcap(srslte::mac_pcap* pcap_)
@ -128,7 +129,7 @@ void ra_proc::read_params()
delta_preamble_db = delta_preamble_db_table[prach_info.preamble_format % 5]; delta_preamble_db = delta_preamble_db_table[prach_info.preamble_format % 5];
if (rach_cfg.contentionResolutionTimer > 0) { if (rach_cfg.contentionResolutionTimer > 0) {
contention_resolution_timer->set(this, rach_cfg.contentionResolutionTimer); contention_resolution_timer.set(rach_cfg.contentionResolutionTimer, [this](uint32_t tid) { timer_expired(tid); });
} }
} }
@ -222,11 +223,10 @@ void ra_proc::state_backoff_wait(uint32_t tti)
void ra_proc::state_contention_resolution() void ra_proc::state_contention_resolution()
{ {
// Once Msg3 is transmitted, start contention resolution timer // Once Msg3 is transmitted, start contention resolution timer
if (mux_unit->msg3_is_transmitted() && !contention_resolution_timer->is_running()) { if (mux_unit->msg3_is_transmitted() && !contention_resolution_timer.is_running()) {
// Start contention resolution timer // Start contention resolution timer
rInfo("Starting ContentionResolutionTimer=%d ms\n", contention_resolution_timer->get_timeout()); rInfo("Starting ContentionResolutionTimer=%d ms\n", contention_resolution_timer.duration());
contention_resolution_timer->reset(); contention_resolution_timer.run();
contention_resolution_timer->run();
} }
} }
@ -350,7 +350,6 @@ void ra_proc::process_timeadv_cmd(uint32_t ta)
phy_h->set_timeadv_rar(ta); phy_h->set_timeadv_rar(ta);
// Only if timer is running reset the timer // Only if timer is running reset the timer
if (time_alignment_timer->is_running()) { if (time_alignment_timer->is_running()) {
time_alignment_timer->reset();
time_alignment_timer->run(); time_alignment_timer->run();
} }
Debug("Applying RAR TA CMD %d\n", ta); Debug("Applying RAR TA CMD %d\n", ta);
@ -574,7 +573,7 @@ bool ra_proc::contention_resolution_id_received(uint64_t rx_contention_id)
rDebug("MAC PDU Contains Contention Resolution ID CE\n"); rDebug("MAC PDU Contains Contention Resolution ID CE\n");
// MAC PDU successfully decoded and contains MAC CE contention Id // MAC PDU successfully decoded and contains MAC CE contention Id
contention_resolution_timer->stop(); contention_resolution_timer.stop();
if (transmitted_contention_id == rx_contention_id) { if (transmitted_contention_id == rx_contention_id) {
// UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3 // UE Contention Resolution ID included in MAC CE matches the CCCH SDU transmitted in Msg3
@ -600,7 +599,7 @@ void ra_proc::pdcch_to_crnti(bool is_new_uplink_transmission)
rDebug("PDCCH to C-RNTI received %s new UL transmission\n", is_new_uplink_transmission ? "with" : "without"); rDebug("PDCCH to C-RNTI received %s new UL transmission\n", is_new_uplink_transmission ? "with" : "without");
if ((!started_by_pdcch && is_new_uplink_transmission) || started_by_pdcch) { if ((!started_by_pdcch && is_new_uplink_transmission) || started_by_pdcch) {
rDebug("PDCCH for C-RNTI received\n"); rDebug("PDCCH for C-RNTI received\n");
contention_resolution_timer->stop(); contention_resolution_timer.stop();
complete(); complete();
} }
} }
@ -626,8 +625,8 @@ bool ra_proc::update_rar_window(int* rar_window_start, int* rar_window_length)
// Restart timer at each Msg3 HARQ retransmission (5.1.5) // Restart timer at each Msg3 HARQ retransmission (5.1.5)
void ra_proc::harq_retx() void ra_proc::harq_retx()
{ {
rInfo("Restarting ContentionResolutionTimer=%d ms\n", contention_resolution_timer->get_timeout()); rInfo("Restarting ContentionResolutionTimer=%d ms\n", contention_resolution_timer.duration());
contention_resolution_timer->reset(); contention_resolution_timer.run();
} }
void ra_proc::harq_max_retx() void ra_proc::harq_max_retx()

@ -107,7 +107,7 @@ void rrc::init(phy_interface_rrc_lte* phy_,
nas_interface_rrc* nas_, nas_interface_rrc* nas_,
usim_interface_rrc* usim_, usim_interface_rrc* usim_,
gw_interface_rrc* gw_, gw_interface_rrc* gw_,
srslte::timers* timers_, srslte::timer_handler* timers_,
stack_interface_rrc* stack_, stack_interface_rrc* stack_,
const rrc_args_t& args_) const rrc_args_t& args_)
{ {
@ -130,12 +130,12 @@ void rrc::init(phy_interface_rrc_lte* phy_,
security_is_activated = false; security_is_activated = false;
t300 = timers->get_unique_id(); t300 = timers->get_unique_timer();
t301 = timers->get_unique_id(); t301 = timers->get_unique_timer();
t302 = timers->get_unique_id(); t302 = timers->get_unique_timer();
t310 = timers->get_unique_id(); t310 = timers->get_unique_timer();
t311 = timers->get_unique_id(); t311 = timers->get_unique_timer();
t304 = timers->get_unique_id(); t304 = timers->get_unique_timer();
ue_identity_configured = false; ue_identity_configured = false;
@ -434,20 +434,17 @@ void rrc::out_of_sync()
// upon receiving N310 consecutive "out-of-sync" indications for the PCell from lower layers while neither T300, // upon receiving N310 consecutive "out-of-sync" indications for the PCell from lower layers while neither T300,
// T301, T304 nor T311 is running: // T301, T304 nor T311 is running:
if (state == RRC_STATE_CONNECTED) { if (state == RRC_STATE_CONNECTED) {
if (!timers->get(t300)->is_running() && !timers->get(t301)->is_running() && !timers->get(t304)->is_running() && if (!t300.is_running() && !t301.is_running() && !t304.is_running() && !t310.is_running() && !t311.is_running()) {
!timers->get(t310)->is_running() && !timers->get(t311)->is_running()) {
rrc_log->info("Received out-of-sync while in state %s. n310=%d, t311=%s, t310=%s\n", rrc_log->info("Received out-of-sync while in state %s. n310=%d, t311=%s, t310=%s\n",
rrc_state_text[state], rrc_state_text[state],
n310_cnt, n310_cnt,
timers->get(t311)->is_running() ? "running" : "stop", t311.is_running() ? "running" : "stop",
timers->get(t310)->is_running() ? "running" : "stop"); t310.is_running() ? "running" : "stop");
n310_cnt++; n310_cnt++;
if (n310_cnt == N310) { if (n310_cnt == N310) {
rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", rrc_log->info(
N310, "Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", N310, t310.duration());
timers->get(t310)->get_timeout()); t310.run();
timers->get(t310)->reset();
timers->get(t310)->run();
n310_cnt = 0; n310_cnt = 0;
} }
} }
@ -460,10 +457,10 @@ void rrc::in_sync()
{ {
// CAUTION: We do not lock in this function since they are called from real-time threads // CAUTION: We do not lock in this function since they are called from real-time threads
serving_cell->in_sync = true; serving_cell->in_sync = true;
if (timers->get(t310)->is_running()) { if (t310.is_running()) {
n311_cnt++; n311_cnt++;
if (n311_cnt == N311) { if (n311_cnt == N311) {
timers->get(t310)->stop(); t310.stop();
n311_cnt = 0; n311_cnt = 0;
rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311); rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311);
} }
@ -819,26 +816,27 @@ void rrc::max_retx_attempted() {
cmd_q.push(std::move(msg)); cmd_q.push(std::move(msg));
} }
void rrc::timer_expired(uint32_t timeout_id) { void rrc::timer_expired(uint32_t timeout_id)
if (timeout_id == t310) { {
if (timeout_id == t310.id()) {
rrc_log->info("Timer T310 expired: Radio Link Failure\n"); rrc_log->info("Timer T310 expired: Radio Link Failure\n");
radio_link_failure(); radio_link_failure();
} else if (timeout_id == t311) { } else if (timeout_id == t311.id()) {
rrc_log->info("Timer T311 expired: Going to RRC IDLE\n"); rrc_log->info("Timer T311 expired: Going to RRC IDLE\n");
start_go_idle(); start_go_idle();
} else if (timeout_id == t301) { } else if (timeout_id == t301.id()) {
if (state == RRC_STATE_IDLE) { if (state == RRC_STATE_IDLE) {
rrc_log->info("Timer T301 expired: Already in IDLE.\n"); rrc_log->info("Timer T301 expired: Already in IDLE.\n");
} else { } else {
rrc_log->info("Timer T301 expired: Going to RRC IDLE\n"); rrc_log->info("Timer T301 expired: Going to RRC IDLE\n");
start_go_idle(); start_go_idle();
} }
} else if (timeout_id == t302) { } else if (timeout_id == t302.id()) {
rrc_log->info("Timer T302 expired. Informing NAS about barrier alleviation\n"); rrc_log->info("Timer T302 expired. Informing NAS about barrier alleviation\n");
nas->set_barring(nas_interface_rrc::BARRING_NONE); nas->set_barring(nas_interface_rrc::BARRING_NONE);
} else if (timeout_id == t300) { } else if (timeout_id == t300.id()) {
// Do nothing, handled in connection_request() // Do nothing, handled in connection_request()
} else if (timeout_id == t304) { } else if (timeout_id == t304.id()) {
rrc_log->console("Timer T304 expired: Handover failed\n"); rrc_log->console("Timer T304 expired: Handover failed\n");
ho_failed(); ho_failed();
// fw to measurement // fw to measurement
@ -847,13 +845,6 @@ void rrc::timer_expired(uint32_t timeout_id) {
} }
} }
/******************************************************************************* /*******************************************************************************
* *
* *
@ -1067,8 +1058,8 @@ bool rrc::ho_prepare()
} }
// Section 5.3.5.4 // Section 5.3.5.4
timers->get(t310)->stop(); t310.stop();
timers->get(t304)->set(this, mob_ctrl_info->t304.to_number()); t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { timer_expired(tid); });
// Save serving cell and current configuration // Save serving cell and current configuration
ho_src_cell = *serving_cell; ho_src_cell = *serving_cell;
@ -1153,7 +1144,7 @@ void rrc::ho_ra_completed(bool ra_successful)
measurements.parse_meas_config(&mob_reconf_r8->meas_cfg); measurements.parse_meas_config(&mob_reconf_r8->meas_cfg);
} }
timers->get(t304)->stop(); t304.stop();
} }
// T304 will expiry and send ho_failure // T304 will expiry and send ho_failure
@ -1348,11 +1339,11 @@ void rrc::leave_connected()
void rrc::stop_timers() void rrc::stop_timers()
{ {
timers->get(t300)->stop(); t300.stop();
timers->get(t301)->stop(); t301.stop();
timers->get(t310)->stop(); t310.stop();
timers->get(t311)->stop(); t311.stop();
timers->get(t304)->stop(); t304.stop();
} }
/* Implementation of procedure in 3GPP 36.331 Section 5.3.7.2: Initiation /* Implementation of procedure in 3GPP 36.331 Section 5.3.7.2: Initiation
@ -1402,11 +1393,10 @@ void rrc::proc_con_restablish_request()
rrc_log->info("Resetting timers and MAC in RRC Connection Reestablishment Procedure\n"); rrc_log->info("Resetting timers and MAC in RRC Connection Reestablishment Procedure\n");
// stop timer T310, if running; // stop timer T310, if running;
timers->get(t310)->stop(); t310.stop();
// start timer T311; // start timer T311;
timers->get(t311)->reset(); t311.run();
timers->get(t311)->run();
// Suspend all RB except SRB0 // Suspend all RB except SRB0
for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) { for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) {
@ -1432,7 +1422,7 @@ void rrc::proc_con_restablish_request()
} }
// Check timer... // Check timer...
if (timers->get(t311)->is_running()) { if (t311.is_running()) {
// Wait until we're synced and have obtained SIBs // Wait until we're synced and have obtained SIBs
if (serving_cell->in_sync && serving_cell->has_sib1() && serving_cell->has_sib2() && serving_cell->has_sib3()) { if (serving_cell->in_sync && serving_cell->has_sib1() && serving_cell->has_sib2() && serving_cell->has_sib3()) {
// Perform cell selection in accordance to 36.304 // Perform cell selection in accordance to 36.304
@ -1440,16 +1430,16 @@ void rrc::proc_con_restablish_request()
// Actions following cell reselection while T311 is running 5.3.7.3 // Actions following cell reselection while T311 is running 5.3.7.3
// Upon selecting a suitable E-UTRA cell, the UE shall: // Upon selecting a suitable E-UTRA cell, the UE shall:
rrc_log->info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n", rrc_log->info("Cell Selection criteria passed after %dms. Sending RRC Connection Reestablishment Request\n",
timers->get(t311)->value()); t311.value());
// stop timer T311; // stop timer T311;
timers->get(t301)->reset(); t311.stop();
// start timer T301; // start timer T301;
timers->get(t301)->run(); t301.run();
// apply the timeAlignmentTimerCommon included in SystemInformationBlockType2; // apply the timeAlignmentTimerCommon included in SystemInformationBlockType2;
timers->get(t311)->stop(); // TODO
// initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4; // initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4;
send_con_restablish_request(); send_con_restablish_request();
@ -1659,20 +1649,21 @@ void rrc::handle_sib2()
log_rr_config_common(); log_rr_config_common();
timers->get(t300)->set(this, sib2->ue_timers_and_consts.t300.to_number()); auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); };
timers->get(t301)->set(this, sib2->ue_timers_and_consts.t301.to_number()); t300.set(sib2->ue_timers_and_consts.t300.to_number(), timer_expire_func);
timers->get(t310)->set(this, sib2->ue_timers_and_consts.t310.to_number()); t301.set(sib2->ue_timers_and_consts.t301.to_number(), timer_expire_func);
timers->get(t311)->set(this, sib2->ue_timers_and_consts.t311.to_number()); t310.set(sib2->ue_timers_and_consts.t310.to_number(), timer_expire_func);
t311.set(sib2->ue_timers_and_consts.t311.to_number(), timer_expire_func);
N310 = sib2->ue_timers_and_consts.n310.to_number(); N310 = sib2->ue_timers_and_consts.n310.to_number();
N311 = sib2->ue_timers_and_consts.n311.to_number(); N311 = sib2->ue_timers_and_consts.n311.to_number();
rrc_log->info("Set Constants and Timers: N310=%d, N311=%d, t300=%d, t301=%d, t310=%d, t311=%d\n", rrc_log->info("Set Constants and Timers: N310=%d, N311=%d, t300=%d, t301=%d, t310=%d, t311=%d\n",
N310, N310,
N311, N311,
timers->get(t300)->get_timeout(), t300.duration(),
timers->get(t301)->get_timeout(), t301.duration(),
timers->get(t310)->get_timeout(), t310.duration(),
timers->get(t311)->get_timeout()); t311.duration());
} }
void rrc::handle_sib3() void rrc::handle_sib3()
@ -1914,12 +1905,12 @@ void rrc::parse_dl_ccch(unique_byte_buffer_t pdu)
rrc_log->info("Received ConnectionReject. Wait time: %d\n", reject_r8->wait_time); rrc_log->info("Received ConnectionReject. Wait time: %d\n", reject_r8->wait_time);
rrc_log->console("Received ConnectionReject. Wait time: %d\n", reject_r8->wait_time); rrc_log->console("Received ConnectionReject. Wait time: %d\n", reject_r8->wait_time);
timers->get(t300)->stop(); t300.stop();
if (reject_r8->wait_time) { if (reject_r8->wait_time) {
nas->set_barring(nas_interface_rrc::BARRING_ALL); nas->set_barring(nas_interface_rrc::BARRING_ALL);
timers->get(t302)->set(this, reject_r8->wait_time * 1000u); t302.set(reject_r8->wait_time * 1000, [this](uint32_t tid) { timer_expired(tid); });
timers->get(t302)->run(); t302.run();
} else { } else {
// Perform the actions upon expiry of T302 if wait time is zero // Perform the actions upon expiry of T302 if wait time is zero
nas->set_barring(nas_interface_rrc::BARRING_NONE); nas->set_barring(nas_interface_rrc::BARRING_NONE);
@ -2543,19 +2534,20 @@ bool rrc::apply_rr_config_dedicated(rr_cfg_ded_s* cnfg)
// TODO // TODO
} }
if (cnfg->rlf_timers_and_consts_r9.is_present() and cnfg->rlf_timers_and_consts_r9->type() == setup_e::setup) { if (cnfg->rlf_timers_and_consts_r9.is_present() and cnfg->rlf_timers_and_consts_r9->type() == setup_e::setup) {
timers->get(t301)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t301_r9.to_number()); auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); };
timers->get(t310)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t310_r9.to_number()); t301.set(cnfg->rlf_timers_and_consts_r9->setup().t301_r9.to_number(), timer_expire_func);
timers->get(t311)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t311_r9.to_number()); t310.set(cnfg->rlf_timers_and_consts_r9->setup().t310_r9.to_number(), timer_expire_func);
t311.set(cnfg->rlf_timers_and_consts_r9->setup().t311_r9.to_number(), timer_expire_func);
N310 = cnfg->rlf_timers_and_consts_r9->setup().n310_r9.to_number(); N310 = cnfg->rlf_timers_and_consts_r9->setup().n310_r9.to_number();
N311 = cnfg->rlf_timers_and_consts_r9->setup().n311_r9.to_number(); N311 = cnfg->rlf_timers_and_consts_r9->setup().n311_r9.to_number();
rrc_log->info("Updated Constants and Timers: N310=%d, N311=%d, t300=%u, t301=%u, t310=%u, t311=%u\n", rrc_log->info("Updated Constants and Timers: N310=%d, N311=%d, t300=%u, t301=%u, t310=%u, t311=%u\n",
N310, N310,
N311, N311,
timers->get(t300)->get_timeout(), t300.duration(),
timers->get(t301)->get_timeout(), t301.duration(),
timers->get(t310)->get_timeout(), t310.duration(),
timers->get(t311)->get_timeout()); t311.duration());
} }
for (uint32_t i = 0; i < cnfg->srb_to_add_mod_list.size(); i++) { for (uint32_t i = 0; i < cnfg->srb_to_add_mod_list.size(); i++) {
// TODO: handle SRB modification // TODO: handle SRB modification
@ -2635,8 +2627,8 @@ void rrc::handle_con_setup(rrc_conn_setup_s* setup)
{ {
// Must enter CONNECT before stopping T300 // Must enter CONNECT before stopping T300
state = RRC_STATE_CONNECTED; state = RRC_STATE_CONNECTED;
timers->get(t300)->stop(); t300.stop();
timers->get(t302)->stop(); t302.stop();
rrc_log->console("RRC Connected\n"); rrc_log->console("RRC Connected\n");
// Apply the Radio Resource configuration // Apply the Radio Resource configuration
@ -2654,7 +2646,7 @@ void rrc::handle_con_setup(rrc_conn_setup_s* setup)
/* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */ /* Reception of RRCConnectionReestablishment by the UE 5.3.7.5 */
void rrc::handle_con_reest(rrc_conn_reest_s* setup) void rrc::handle_con_reest(rrc_conn_reest_s* setup)
{ {
timers->get(t301)->stop(); t301.stop();
// Reestablish PDCP and RLC for SRB1 // Reestablish PDCP and RLC for SRB1
pdcp->reestablish(1); pdcp->reestablish(1);
@ -2850,8 +2842,9 @@ void rrc::set_rrc_default()
{ {
N310 = 1; N310 = 1;
N311 = 1; N311 = 1;
timers->get(t310)->set(this, 1000); auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); };
timers->get(t311)->set(this, 1000); t310.set(1000, timer_expire_func);
t311.set(1000, timer_expire_func);
} }
/************************************************************************ /************************************************************************
@ -3030,11 +3023,10 @@ void rrc::rrc_meas::generate_report(uint32_t meas_id)
report->meas_result_neigh_cells_present = neigh_list.size() > 0; report->meas_result_neigh_cells_present = neigh_list.size() > 0;
m->nof_reports_sent++; m->nof_reports_sent++;
timers->get(m->periodic_timer)->stop(); m->periodic_timer.stop();
if (m->nof_reports_sent < cfg->amount) { if (m->nof_reports_sent < cfg->amount) {
timers->get(m->periodic_timer)->reset(); m->periodic_timer.run();
timers->get(m->periodic_timer)->run();
} else { } else {
if (cfg->trigger_type == report_cfg_t::PERIODIC) { if (cfg->trigger_type == report_cfg_t::PERIODIC) {
m->triggered = false; m->triggered = false;
@ -3067,7 +3059,7 @@ bool rrc::rrc_meas::process_event(eutra_event_s* event, uint32_t tti, bool enter
} else if (srslte_tti_interval(tti, cell->exit_tti) >= event->time_to_trigger) { } else if (srslte_tti_interval(tti, cell->exit_tti) >= event->time_to_trigger) {
m->triggered = false; m->triggered = false;
cell->triggered = false; cell->triggered = false;
timers->get(m->periodic_timer)->stop(); m->periodic_timer.stop();
if (event) { if (event) {
if (event->event_id.type() == eutra_event_s::event_id_c_::types::event_a3 && if (event->event_id.type() == eutra_event_s::event_id_c_::types::event_a3 &&
event->event_id.event_a3().report_on_leave) { event->event_id.event_a3().report_on_leave) {
@ -3232,9 +3224,10 @@ void rrc::rrc_meas::ho_finish() {
} }
// 5.5.4.1 expiry of periodical reporting timer // 5.5.4.1 expiry of periodical reporting timer
bool rrc::rrc_meas::timer_expired(uint32_t timer_id) { bool rrc::rrc_meas::timer_expired(uint32_t timer_id)
{
for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) { for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) {
if (iter->second.periodic_timer == timer_id) { if (iter->second.periodic_timer.id() == timer_id) {
log_h->info("Generate report MeasId=%d, from timerId=%d\n", iter->first, timer_id); log_h->info("Generate report MeasId=%d, from timerId=%d\n", iter->first, timer_id);
generate_report(iter->first); generate_report(iter->first);
return true; return true;
@ -3245,11 +3238,12 @@ bool rrc::rrc_meas::timer_expired(uint32_t timer_id) {
void rrc::rrc_meas::stop_reports(meas_t* m) void rrc::rrc_meas::stop_reports(meas_t* m)
{ {
timers->get(m->periodic_timer)->stop(); m->periodic_timer.stop();
m->triggered = false; m->triggered = false;
} }
void rrc::rrc_meas::stop_reports_object(uint32_t object_id) { void rrc::rrc_meas::stop_reports_object(uint32_t object_id)
{
for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) { for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) {
if (iter->second.object_id == object_id) { if (iter->second.object_id == object_id) {
stop_reports(&iter->second); stop_reports(&iter->second);
@ -3282,8 +3276,6 @@ void rrc::rrc_meas::remove_meas_report(uint32_t report_id) {
void rrc::rrc_meas::remove_meas_id(uint32_t measId) void rrc::rrc_meas::remove_meas_id(uint32_t measId)
{ {
if (active.count(measId)) { if (active.count(measId)) {
timers->get(active[measId].periodic_timer)->stop();
timers->release_id(active[measId].periodic_timer);
log_h->info("MEAS: Removed measId=%d\n", measId); log_h->info("MEAS: Removed measId=%d\n", measId);
active.erase(measId); active.erase(measId);
} else { } else {
@ -3293,8 +3285,6 @@ void rrc::rrc_meas::remove_meas_id(uint32_t measId)
void rrc::rrc_meas::remove_meas_id(std::map<uint32_t, meas_t>::iterator it) void rrc::rrc_meas::remove_meas_id(std::map<uint32_t, meas_t>::iterator it)
{ {
timers->get(it->second.periodic_timer)->stop();
timers->release_id(it->second.periodic_timer);
log_h->info("MEAS: Removed measId=%d\n", it->first); log_h->info("MEAS: Removed measId=%d\n", it->first);
active.erase(it); active.erase(it);
} }
@ -3443,16 +3433,20 @@ bool rrc::rrc_meas::parse_meas_config(meas_cfg_s* cfg)
// Stop the timer if the entry exists or create the timer if not // Stop the timer if the entry exists or create the timer if not
bool is_new = false; bool is_new = false;
if (active.count(meas_id->meas_id)) { if (active.count(meas_id->meas_id)) {
timers->get(active[meas_id->meas_id].periodic_timer)->stop(); active[meas_id->meas_id].periodic_timer.stop();
} else { } else {
is_new = true; is_new = true;
active[meas_id->meas_id].periodic_timer = timers->get_unique_id(); active[meas_id->meas_id].periodic_timer = timers->get_unique_timer();
} }
active[meas_id->meas_id].object_id = meas_id->meas_obj_id; active[meas_id->meas_id].object_id = meas_id->meas_obj_id;
active[meas_id->meas_id].report_id = meas_id->report_cfg_id; active[meas_id->meas_id].report_id = meas_id->report_cfg_id;
log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, timer_id=%u, nof_values=%zd\n", log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, timer_id=%u, nof_values=%zd\n",
is_new ? "Added" : "Updated", meas_id->meas_id, meas_id->meas_obj_id, meas_id->report_cfg_id, is_new ? "Added" : "Updated",
active[meas_id->meas_id].periodic_timer, active[meas_id->meas_id].cell_values.size()); meas_id->meas_id,
meas_id->meas_obj_id,
meas_id->report_cfg_id,
active[meas_id->meas_id].periodic_timer.id(),
active[meas_id->meas_id].cell_values.size());
} }
} }

@ -562,7 +562,7 @@ proc_outcome_t rrc::connection_request_proc::init(srslte::establishment_cause_t
return proc_outcome_t::error; return proc_outcome_t::error;
} }
if (rrc_ptr->timers->get(rrc_ptr->t302)->is_running()) { if (rrc_ptr->t302.is_running()) {
Info("Requested RRC connection establishment while T302 is running\n"); Info("Requested RRC connection establishment while T302 is running\n");
rrc_ptr->nas->set_barring(nas_interface_rrc::BARRING_MO_DATA); rrc_ptr->nas->set_barring(nas_interface_rrc::BARRING_MO_DATA);
return proc_outcome_t::error; return proc_outcome_t::error;
@ -600,8 +600,7 @@ proc_outcome_t rrc::connection_request_proc::step()
return proc_outcome_t::error; return proc_outcome_t::error;
} }
rrc_ptr->timers->get(rrc_ptr->t300)->reset(); rrc_ptr->t300.run();
rrc_ptr->timers->get(rrc_ptr->t300)->run();
// Send connectionRequest message to lower layers // Send connectionRequest message to lower layers
rrc_ptr->send_con_request(cause); rrc_ptr->send_con_request(cause);
@ -618,14 +617,14 @@ proc_outcome_t rrc::connection_request_proc::step()
} else if (state == state_t::wait_t300) { } else if (state == state_t::wait_t300) {
// Wait until t300 stops due to RRCConnectionSetup/Reject or expiry // Wait until t300 stops due to RRCConnectionSetup/Reject or expiry
if (rrc_ptr->timers->get(rrc_ptr->t300)->is_running()) { if (rrc_ptr->t300.is_running()) {
return proc_outcome_t::yield; return proc_outcome_t::yield;
} }
if (rrc_ptr->state == RRC_STATE_CONNECTED) { if (rrc_ptr->state == RRC_STATE_CONNECTED) {
// Received ConnectionSetup // Received ConnectionSetup
return proc_outcome_t::success; return proc_outcome_t::success;
} else if (rrc_ptr->timers->get(rrc_ptr->t300)->is_expired()) { } else if (rrc_ptr->t300.is_expired()) {
// T300 is expired: 5.3.3.6 // T300 is expired: 5.3.3.6
Warning("Timer T300 expired: ConnectionRequest timed out\n"); Warning("Timer T300 expired: ConnectionRequest timed out\n");
rrc_ptr->mac->reset(); rrc_ptr->mac->reset();

@ -68,8 +68,7 @@ void nas::plmn_search_proc::then(const srslte::proc_state_t& result)
// start T3411 // start T3411
nas_ptr->nas_log->debug("Starting T3411\n"); nas_ptr->nas_log->debug("Starting T3411\n");
nas_ptr->timers->get(nas_ptr->t3411)->reset(); nas_ptr->t3411.run();
nas_ptr->timers->get(nas_ptr->t3411)->run();
if (result.is_error()) { if (result.is_error()) {
nas_ptr->enter_emm_deregistered(); nas_ptr->enter_emm_deregistered();
@ -225,12 +224,14 @@ proc_outcome_t nas::rrc_connect_proc::react(nas::rrc_connect_proc::connection_re
* NAS * NAS
********************************************************************/ ********************************************************************/
nas::nas(srslte::log* log_, srslte::timers* timers_) : nas::nas(srslte::log* log_, srslte::timer_handler* timers_) :
nas_log(log_), nas_log(log_),
pool(byte_buffer_pool::get_instance()), pool(byte_buffer_pool::get_instance()),
plmn_searcher(this), plmn_searcher(this),
rrc_connector(this), rrc_connector(this),
timers(timers_) timers(timers_),
t3410(timers_->get_unique_timer()),
t3411(timers_->get_unique_timer())
{ {
} }
@ -284,10 +285,8 @@ void nas::init(usim_interface_nas* usim_, rrc_interface_nas* rrc_, gw_interface_
} }
// Configure T3410 and T3411 // Configure T3410 and T3411
t3410 = timers->get_unique_id(); t3410.set(t3410_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
timers->get(t3410)->set(this, t3410_duration_ms); t3411.set(t3411_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
t3411 = timers->get_unique_id();
timers->get(t3411)->set(this, t3411_duration_ms);
running = true; running = true;
} }
@ -318,11 +317,10 @@ void nas::run_tti(uint32_t tti)
void nas::timer_expired(uint32_t timeout_id) void nas::timer_expired(uint32_t timeout_id)
{ {
if (timeout_id == t3410) { if (timeout_id == t3410.id()) {
nas_log->info("Timer T3410 expired: starting T3411\n"); nas_log->info("Timer T3410 expired: starting T3411\n");
timers->get(t3411)->reset(); t3411.run();
timers->get(t3411)->run(); } else if (timeout_id == t3411.id()) {
} else if (timeout_id == t3411) {
nas_log->info("Timer T3411 expired: trying to attach again\n"); nas_log->info("Timer T3411 expired: trying to attach again\n");
start_attach_request(nullptr, srslte::establishment_cause_t::mo_sig); start_attach_request(nullptr, srslte::establishment_cause_t::mo_sig);
} else { } else {
@ -346,12 +344,11 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme
// start T3410 // start T3410
nas_log->debug("Starting T3410\n"); nas_log->debug("Starting T3410\n");
timers->get(t3410)->reset(); t3410.run();
timers->get(t3410)->run();
// stop T3411 // stop T3411
if (timers->get(t3411)->is_running()) { if (t3411.is_running()) {
timers->get(t3411)->stop(); t3411.stop();
} }
// Todo: stop T3402 // Todo: stop T3402
@ -870,8 +867,8 @@ void nas::parse_attach_accept(uint32_t lcid, unique_byte_buffer_t pdu)
nas_log->info("Received Attach Accept\n"); nas_log->info("Received Attach Accept\n");
// stop T3410 // stop T3410
if (timers->get(t3410)->is_running()) { if (t3410.is_running()) {
timers->get(t3410)->stop(); t3410.stop();
} }
LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept = {}; LIBLTE_MME_ATTACH_ACCEPT_MSG_STRUCT attach_accept = {};
@ -1099,8 +1096,8 @@ void nas::parse_attach_reject(uint32_t lcid, unique_byte_buffer_t pdu)
nas_log->console("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause); nas_log->console("Received Attach Reject. Cause= %02X\n", attach_rej.emm_cause);
// stop T3410 // stop T3410
if (timers->get(t3410)->is_running()) { if (t3410.is_running()) {
timers->get(t3410)->stop(); t3410.stop();
} }
enter_emm_deregistered(); enter_emm_deregistered();
@ -1599,9 +1596,9 @@ void nas::gen_attach_request(byte_buffer_t* msg)
} }
// stop T3411 // stop T3411
if (timers->get(t3411)->is_running()) { if (t3411.is_running()) {
nas_log->debug("Stopping T3411\n"); nas_log->debug("Stopping T3411\n");
timers->get(t3411)->stop(); t3411.stop();
} }
} }

@ -371,7 +371,7 @@ int mac_unpack_test()
srslte::log_filter rlc_log("RLC"); srslte::log_filter rlc_log("RLC");
srslte::log_filter mac_log("MAC"); srslte::log_filter mac_log("MAC");
srslte::timers timers(64); srslte::timer_handler timers(64);
mac_log.set_level(srslte::LOG_LEVEL_DEBUG); mac_log.set_level(srslte::LOG_LEVEL_DEBUG);
mac_log.set_hex_limit(100000); mac_log.set_hex_limit(100000);
@ -435,7 +435,7 @@ int mac_ul_sch_pdu_test1()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -505,7 +505,7 @@ int mac_ul_logical_channel_prioritization_test1()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -620,7 +620,7 @@ int mac_ul_logical_channel_prioritization_test2()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -722,7 +722,7 @@ int mac_ul_logical_channel_prioritization_test3()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -812,7 +812,7 @@ int mac_ul_sch_pdu_with_short_bsr_test()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -900,7 +900,7 @@ int mac_ul_sch_pdu_with_padding_bsr_test()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -997,7 +997,7 @@ int mac_ul_sch_pdu_one_byte_test()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -1059,7 +1059,7 @@ int mac_ul_sch_pdu_two_byte_test()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -1121,7 +1121,7 @@ int mac_ul_sch_pdu_three_byte_test()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;
@ -1188,7 +1188,7 @@ struct ra_test {
struct ra_test test; struct ra_test test;
int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti_state, srslte::timers* timers) int run_mac_ra_test(struct ra_test test, mac* mac, phy_dummy* phy, uint32_t* tti_state, srslte::timer_handler* timers)
{ {
uint32_t tti = *tti_state; uint32_t tti = *tti_state;
@ -1365,7 +1365,7 @@ int mac_random_access_test()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG); rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000); rlc_log.set_hex_limit(100000);
srslte::timers timers(64); srslte::timer_handler timers(64);
// dummy layers // dummy layers
phy_dummy phy; phy_dummy phy;

@ -765,12 +765,6 @@ public:
ue->new_tb(dl_grant, (const uint8_t*)pdu->msg); ue->new_tb(dl_grant, (const uint8_t*)pdu->msg);
} }
srslte::timers::timer* timer_get(uint32_t timer_id) { return timers.get(timer_id); }
uint32_t timer_get_unique_id() { return timers.get_unique_id(); }
void timer_release_id(uint32_t timer_id) { timers.release_id(timer_id); }
void step_timer() { timers.step_all(); } void step_timer() { timers.step_all(); }
void add_srb(uint32_t lcid, pdcp_config_t pdcp_config) void add_srb(uint32_t lcid, pdcp_config_t pdcp_config)
@ -918,7 +912,7 @@ private:
uint32_t prach_preamble_index = 0; uint32_t prach_preamble_index = 0;
uint16_t dl_rnti = 0; uint16_t dl_rnti = 0;
uint16_t crnti = TTCN3_CRNTI; uint16_t crnti = TTCN3_CRNTI;
srslte::timers timers; srslte::timer_handler timers;
bool last_dl_ndi[2 * FDD_HARQ_DELAY_MS] = {}; bool last_dl_ndi[2 * FDD_HARQ_DELAY_MS] = {};
bool last_ul_ndi[2 * FDD_HARQ_DELAY_MS] = {}; bool last_ul_ndi[2 * FDD_HARQ_DELAY_MS] = {};

@ -206,7 +206,7 @@ int security_command_test()
nas_log.set_hex_limit(100000); nas_log.set_hex_limit(100000);
rrc_log.set_hex_limit(100000); rrc_log.set_hex_limit(100000);
srslte::timers timers(10); srslte::timer_handler timers(10);
rrc_dummy rrc_dummy; rrc_dummy rrc_dummy;
gw_dummy gw; gw_dummy gw;
@ -278,7 +278,7 @@ int mme_attach_request_test()
usim_log.set_hex_limit(100000); usim_log.set_hex_limit(100000);
gw_log.set_hex_limit(100000); gw_log.set_hex_limit(100000);
srslte::timers timers(10); srslte::timer_handler timers(10);
rrc_dummy rrc_dummy; rrc_dummy rrc_dummy;
pdcp_dummy pdcp_dummy; pdcp_dummy pdcp_dummy;
@ -358,7 +358,7 @@ int esm_info_request_test()
nas_log.set_hex_limit(100000); nas_log.set_hex_limit(100000);
rrc_log.set_hex_limit(100000); rrc_log.set_hex_limit(100000);
srslte::timers timers(10); srslte::timer_handler timers(10);
rrc_dummy rrc_dummy; rrc_dummy rrc_dummy;
gw_dummy gw; gw_dummy gw;
@ -417,7 +417,7 @@ int dedicated_eps_bearer_test()
nas_log.set_hex_limit(100000); nas_log.set_hex_limit(100000);
rrc_log.set_hex_limit(100000); rrc_log.set_hex_limit(100000);
srslte::timers timers(10); srslte::timer_handler timers(10);
rrc_dummy rrc_dummy; rrc_dummy rrc_dummy;
gw_dummy gw; gw_dummy gw;

Loading…
Cancel
Save