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;
};
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
{
public:

@ -29,144 +29,264 @@
#ifndef SRSLTE_TIMERS_H
#define SRSLTE_TIMERS_H
#include <stdio.h>
#include <algorithm>
#include <functional>
#include <limits>
#include <queue>
#include <stdint.h>
#include <vector>
#include <stdio.h>
#include <time.h>
#include <vector>
#include "srslte/srslte.h"
namespace srslte {
class timer_callback
class timer_callback
{
public:
virtual void timer_expired(uint32_t timer_id) = 0;
};
class timers
public:
virtual void timer_expired(uint32_t timer_id) = 0;
};
class timer_handler
{
constexpr static uint32_t MAX_TIMER_DURATION = std::numeric_limits<uint32_t>::max() / 4;
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_)
{
if (duration_ > MAX_TIMER_DURATION) {
ERROR("Error: timer durations above %u are not supported\n", MAX_TIMER_DURATION);
return false;
}
if (not active) {
ERROR("Error: setting inactive timer id=%d\n", id());
return false;
}
duration = duration_;
if (is_running()) {
// if already running, just extends timer lifetime
run();
}
return true;
}
bool set(uint32_t duration_, std::function<void(int)> callback_)
{
if (set(duration_)) {
callback = std::move(callback_);
return true;
}
return false;
}
void run()
{
if (not active) {
ERROR("Error: calling run() for inactive timer id=%d\n", id());
return;
}
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());
}
running = false;
}
}
};
public:
class timer
class unique_timer
{
public:
timer(uint32_t id_=0) {id = id_; counter = 0; timeout = 0; running = false; callback = NULL; }
void set(timer_callback *callback_, uint32_t timeout_) {
callback = callback_;
timeout = timeout_;
reset();
}
bool is_running() {
return (counter < timeout) && running;
}
bool is_expired() {
return (timeout > 0) && (counter >= timeout);
}
uint32_t get_timeout() {
return timeout;
}
void reset() {
counter = 0;
}
uint32_t value() {
return counter;
}
void step() {
if (running) {
counter++;
if (is_expired()) {
running = false;
if (callback) {
callback->timer_expired(id);
}
}
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)
{
other.parent = nullptr;
}
~unique_timer()
{
if (parent) {
// does not call callback
impl()->clear();
}
}
void stop() {
running = false;
unique_timer& operator=(const unique_timer&) = delete;
unique_timer& operator=(unique_timer&& other) noexcept
{
if (this != &other) {
timer_id = other.timer_id;
parent = other.parent;
other.parent = nullptr;
}
return *this;
}
void run() {
running = true;
bool is_valid() const { return parent != nullptr; }
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;
private:
timer_callback *callback;
uint32_t timeout;
uint32_t counter;
bool running;
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;
};
timers(uint32_t nof_timers_) : timer_list(nof_timers_), used_timers(nof_timers_)
explicit timer_handler(uint32_t capacity = 64)
{
nof_timers = nof_timers_;
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;
}
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 step_all() {
for (uint32_t i=0;i<nof_timers;i++) {
get(i)->step();
void step_all()
{
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 stop_all() {
for (uint32_t i=0;i<nof_timers;i++) {
get(i)->stop();
void stop_all()
{
// does not call callback
while (not running_timers.empty()) {
running_timers.pop();
}
}
void run_all() {
for (uint32_t i=0;i<nof_timers;i++) {
get(i)->run();
for (auto& i : timer_list) {
i.running = false;
}
}
void reset_all() {
for (uint32_t i=0;i<nof_timers;i++) {
get(i)->reset();
unique_timer get_unique_timer()
{
uint32_t i = 0;
for (; i < timer_list.size(); ++i) {
if (not timer_list[i].active) {
break;
}
}
}
timer *get(uint32_t i) {
if (i < nof_timers) {
return &timer_list[i];
} else {
printf("Error accessing invalid timer %d (Only %d timers available)\n", i, nof_timers);
return NULL;
if (i == timer_list.size()) {
timer_list.emplace_back(this);
}
timer_list[i].active = true;
return unique_timer(this, i);
}
void release_id(uint32_t i) {
if (nof_used_timers > 0 && i < nof_timers) {
used_timers[i] = false;
nof_used_timers--;
} else {
ERROR("Error releasing timer id=%d: nof_used_timers=%d, nof_timers=%d\n", i, nof_used_timers, nof_timers);
}
uint32_t get_cur_time() const { return cur_time; }
uint32_t nof_timers() const
{
return std::count_if(timer_list.begin(), timer_list.end(), [](const timer_impl& t) { return t.active; });
}
uint32_t get_unique_id() {
if (nof_used_timers >= nof_timers) {
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;
}
}
ERROR("Error getting unique timer id: no more timers available but nof_used_timers=%d, nof_timers=%d\n",
nof_used_timers,
nof_timers);
return 0;
}
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:
uint32_t next_timer;
uint32_t nof_used_timers;
uint32_t nof_timers;
std::vector<timer> timer_list;
std::vector<bool> used_timers;
struct timer_run {
uint32_t timer_id;
uint32_t timeout;
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

@ -45,7 +45,10 @@ class rlc
public:
rlc(log* rlc_log_);
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 get_metrics(rlc_metrics_t& m);
@ -85,11 +88,11 @@ public:
private:
void reset_metrics();
byte_buffer_pool* pool = nullptr;
srslte::log* rlc_log = nullptr;
srsue::pdcp_interface_rlc* pdcp = nullptr;
srsue::rrc_interface_rlc* rrc = nullptr;
srslte::timers* timers = nullptr;
byte_buffer_pool* pool = nullptr;
srslte::log* rlc_log = nullptr;
srsue::pdcp_interface_rlc* pdcp = nullptr;
srsue::rrc_interface_rlc* rrc = nullptr;
srslte::timer_handler* timers = nullptr;
typedef std::map<uint16_t, rlc_common*> rlc_map_t;
typedef std::pair<uint16_t, rlc_common*> rlc_map_pair_t;

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

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

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

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

@ -36,7 +36,7 @@ rlc_am::rlc_am(srslte::log* log_,
uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_) :
srslte::timer_handler* timers_) :
log(log_),
rrc(rrc_),
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_) :
parent(parent_),
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);
}
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);
}
@ -192,18 +182,19 @@ bool rlc_am::rlc_am_tx::configure(rlc_config_t cfg_)
cfg = cfg_.am;
// 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");
return false;
}
// configure timers
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) {
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);
@ -221,12 +212,12 @@ void rlc_am::rlc_am_tx::stop()
tx_enabled = false;
if (parent->timers != NULL && poll_retx_timer != NULL) {
poll_retx_timer->stop();
if (parent->timers != nullptr && poll_retx_timer.is_valid()) {
poll_retx_timer.stop();
}
if (parent->timers != NULL && status_prohibit_timer != NULL) {
status_prohibit_timer->stop();
if (parent->timers != nullptr && status_prohibit_timer.is_valid()) {
status_prohibit_timer.stop();
}
vt_a = 0;
@ -274,9 +265,9 @@ bool rlc_am::rlc_am_tx::do_status()
// Function is supposed to return as fast as possible
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
(not retx_queue.empty()) || // if we have a retransmission
(tx_sdu != NULL) || // if we are currently transmitting a SDU
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
(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
}
@ -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",
RB_NAME,
do_status(),
status_prohibit_timer->is_running(),
status_prohibit_timer ? "yes" : "no");
status_prohibit_timer.is_running(),
status_prohibit_timer.is_valid() ? "yes" : "no");
// 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();
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
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);
goto unlock_and_exit;
}
@ -423,8 +414,8 @@ unlock_and_exit:
void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id)
{
pthread_mutex_lock(&mutex);
if (poll_retx_timer != NULL && 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());
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.duration());
// Section 5.2.2.3 in TS 36.311, schedule random PDU for retransmission if
// (a) both tx and retx buffer are empty, or
// (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;
}
if (poll_retx_timer != NULL) {
if (poll_retx_timer->is_expired()) {
if (poll_retx_timer.is_valid()) {
if (poll_retx_timer.is_expired()) {
// 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;
}
}
@ -511,19 +501,17 @@ 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);
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)) {
log->info("%s Tx status PDU - %s\n",
RB_NAME, rlc_am_status_pdu_to_string(&tx_status).c_str());
log->info("%s Tx status PDU - %s\n", RB_NAME, rlc_am_status_pdu_to_string(&tx_status).c_str());
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
status_prohibit_timer->reset();
status_prohibit_timer->run();
status_prohibit_timer.run();
}
debug_state();
pdu_len = rlc_am_write_status_pdu(&tx_status, payload);
} else{
} else {
log->info("%s Cannot tx status PDU - %d bytes available, %d bytes required\n", RB_NAME, nof_bytes, pdu_len);
pdu_len = 0;
}
@ -579,13 +567,12 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s;
pdu_without_poll = 0;
byte_without_poll = 0;
if (poll_retx_timer != NULL) {
poll_retx_timer->reset();
poll_retx_timer->run();
if (poll_retx_timer.is_valid()) {
poll_retx_timer.run();
}
}
uint8_t *ptr = payload;
uint8_t* ptr = payload;
rlc_am_write_data_pdu_header(&new_header, &ptr);
memcpy(ptr, tx_window[retx.sn].buf->msg, tx_window[retx.sn].buf->N_bytes);
@ -626,24 +613,23 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
new_header.dc = RLC_DC_FIELD_DATA_PDU;
new_header.rf = 1;
new_header.fi = RLC_FI_FIELD_NOT_START_OR_END_ALIGNED;
new_header.sn = old_header.sn;
new_header.lsf = 0;
new_header.so = retx.so_start;
new_header.sn = old_header.sn;
new_header.lsf = 0;
new_header.so = retx.so_start;
new_header.N_li = 0;
new_header.p = 0;
new_header.p = 0;
if (poll_required()) {
log->debug("%s setting poll bit to request status\n", RB_NAME);
new_header.p = 1;
poll_sn = vt_s;
pdu_without_poll = 0;
new_header.p = 1;
poll_sn = vt_s;
pdu_without_poll = 0;
byte_without_poll = 0;
if (poll_retx_timer != NULL) {
poll_retx_timer->reset();
poll_retx_timer->run();
if (poll_retx_timer.is_valid()) {
poll_retx_timer.run();
}
}
uint32_t head_len = 0;
uint32_t head_len = 0;
uint32_t pdu_space = 0;
head_len = rlc_am_packed_length(&new_header);
@ -894,9 +880,8 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s;
pdu_without_poll = 0;
byte_without_poll = 0;
if (poll_retx_timer != NULL) {
poll_retx_timer->reset();
poll_retx_timer->run();
if (poll_retx_timer.is_valid()) {
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());
if (poll_retx_timer != NULL) {
poll_retx_timer->stop();
if (poll_retx_timer.is_valid()) {
poll_retx_timer.stop();
}
// 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_) :
parent(parent_),
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);
}
rlc_am::rlc_am_rx::~rlc_am_rx()
{
reordering_timer->stop();
parent->timers->release_id(reordering_timer_id);
pthread_mutex_destroy(&mutex);
}
@ -1140,14 +1120,14 @@ bool rlc_am::rlc_am_rx::configure(rlc_am_config_t cfg_)
cfg = cfg_;
// check timers
if (reordering_timer == NULL) {
if (not reordering_timer.is_valid()) {
log->error("Configuring RLC AM TX: timers not configured\n");
return false;
}
// configure timer
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;
@ -1162,8 +1142,8 @@ void rlc_am::rlc_am_rx::stop()
{
pthread_mutex_lock(&mutex);
if (parent->timers != NULL && reordering_timer != NULL) {
reordering_timer->stop();
if (parent->timers != nullptr && reordering_timer.is_valid()) {
reordering_timer.stop();
}
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();
// Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3)
if (reordering_timer != NULL) {
if (reordering_timer->is_running()) {
if(vr_x == vr_r || (!inside_rx_window(vr_x) && vr_x != vr_mr)) {
if (reordering_timer.is_valid()) {
if (reordering_timer.is_running()) {
if (vr_x == vr_r || (!inside_rx_window(vr_x) && vr_x != vr_mr)) {
log->debug("Stopping reordering timer.\n");
reordering_timer->stop();
reordering_timer.stop();
} else {
log->debug("Leave reordering timer running.\n");
}
debug_state();
}
if (not reordering_timer->is_running()) {
if(RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) {
if (not reordering_timer.is_running()) {
if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) {
log->debug("Starting reordering timer.\n");
reordering_timer->reset();
reordering_timer->run();
reordering_timer.run();
vr_x = vr_h;
} else {
log->debug("Leave reordering timer stopped.\n");
@ -1578,16 +1557,16 @@ 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)
{
pthread_mutex_lock(&mutex);
if (reordering_timer != NULL && reordering_timer_id == timeout_id) {
reordering_timer->reset();
if (reordering_timer.is_valid() and reordering_timer.id() == timeout_id) {
// reordering_timer.run(); // FIXME: It was reset() before
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
vr_ms = vr_x;
vr_ms = vr_x;
std::map<uint32_t, rlc_amd_rx_pdu_t>::iterator it = rx_window.find(vr_ms);
while (rx_window.end() != it) {
vr_ms = (vr_ms + 1) % MOD;
it = rx_window.find(vr_ms);
it = rx_window.find(vr_ms);
}
if (poll_received) {
@ -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)) {
reordering_timer->reset();
reordering_timer->run();
reordering_timer.run();
vr_x = vr_h;
}

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

@ -32,7 +32,7 @@ rlc_um::rlc_um(srslte::log* log_,
uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_) :
srslte::timer_handler* timers_) :
lcid(lcid_),
pool(byte_buffer_pool::get_instance()),
rrc(rrc_),
@ -96,8 +96,8 @@ bool rlc_um::rlc_um_rx::configure(rlc_config_t cnfg_, std::string rb_name_)
}
// set reordering timer
if (reordering_timer != NULL) {
reordering_timer->set(this, cfg.um.t_reordering);
if (reordering_timer.is_valid()) {
reordering_timer.set(cfg.um.t_reordering, [this](uint32_t tid) { timer_expired(tid); });
}
} else {
if (cfg.um_nr.mod == 0) {
@ -609,31 +609,26 @@ rlc_um::rlc_um_rx::rlc_um_rx(srslte::log* log_,
uint32_t lcid_,
srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srslte::timers* timers_) :
srslte::timer_handler* timers_) :
pool(byte_buffer_pool::get_instance()),
log(log_),
pdcp(pdcp_),
rrc(rrc_),
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()
{
reordering_timer->stop();
timers->release_id(reordering_timer_id);
}
rlc_um::rlc_um_rx::~rlc_um_rx() {}
void rlc_um::rlc_um_rx::reestablish()
{
// try to reassemble any SDUs if possible
if (reordering_timer != NULL) {
if (reordering_timer->is_running()) {
reordering_timer->stop();
timer_expired(reordering_timer_id);
if (reordering_timer.is_valid()) {
if (reordering_timer.is_running()) {
reordering_timer.stop();
timer_expired(reordering_timer.id());
}
}
@ -642,12 +637,12 @@ void rlc_um::rlc_um_rx::reestablish()
rx_enabled = true;
}
void rlc_um::rlc_um_rx::stop()
{
std::lock_guard<std::mutex> lock(mutex);
reset();
reordering_timer->stop();
reordering_timer.stop();
}
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");
// Update reordering variables and timers
if(reordering_timer->is_running()) {
if(RX_MOD_BASE(vr_ux) <= RX_MOD_BASE(vr_ur) ||
(!inside_reordering_window(vr_ux) && vr_ux != vr_uh))
{
reordering_timer->stop();
if (reordering_timer.is_running()) {
if (RX_MOD_BASE(vr_ux) <= RX_MOD_BASE(vr_ur) || (!inside_reordering_window(vr_ux) && vr_ux != vr_uh)) {
reordering_timer.stop();
}
}
if(!reordering_timer->is_running()) {
if(RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) {
reordering_timer->reset();
reordering_timer->run();
if (!reordering_timer.is_running()) {
if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) {
reordering_timer.run();
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)
{
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
log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n",
get_rb_name());
log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", get_rb_name());
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)) {
reordering_timer->reset();
reordering_timer->run();
reordering_timer.run();
vr_ux = vr_uh;
}

@ -75,3 +75,6 @@ add_test(stack_procedure_test stack_procedure_test)
add_executable(queue_test queue_test.cc)
target_link_libraries(queue_test srslte_common ${CMAKE_THREAD_LIBS_INIT})
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);
rlc_am_tester tester;
timers timers(8);
timer_handler timers(8);
byte_buffer_t pdu_bufs[NBUFS];
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -199,8 +199,8 @@ bool concat_test()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
rlc_am_tester tester;
srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -264,9 +264,9 @@ bool segment_test(bool in_seq_rx)
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
int len = 0;
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -359,7 +359,7 @@ bool retx_test()
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
timers timers(8);
timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -453,7 +453,7 @@ bool resegment_test_1()
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
timers timers(8);
timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -559,7 +559,7 @@ bool resegment_test_2()
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
timers timers(8);
timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -661,8 +661,8 @@ bool resegment_test_3()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
rlc_am_tester tester;
srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -758,8 +758,8 @@ bool resegment_test_4()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
rlc_am_tester tester;
srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -857,8 +857,8 @@ bool resegment_test_5()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
rlc_am_tester tester;
srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -956,9 +956,9 @@ bool resegment_test_6()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
int len = 0;
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -1090,11 +1090,11 @@ bool resegment_test_7()
#if HAVE_PCAP
rlc_pcap pcap;
pcap.open("rlc_am_test7.pcap", 0);
rlc_am_tester tester(&pcap);
rlc_am_tester tester(&pcap);
#else
rlc_am_tester tester(NULL);
#endif
srslte::timers timers(8);
srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -1263,11 +1263,11 @@ bool resegment_test_8()
#if HAVE_PCAP
rlc_pcap pcap;
pcap.open("rlc_am_test8.pcap", 0);
rlc_am_tester tester(&pcap);
rlc_am_tester tester(&pcap);
#else
rlc_am_tester tester(NULL);
#endif
srslte::timers timers(8);
srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);
@ -1410,9 +1410,9 @@ bool reset_test()
srslte::log_filter log1("RLC_AM_1");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
int len = 0;
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -1455,9 +1455,9 @@ bool resume_test()
srslte::log_filter log1("RLC_AM_1");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
int len = 0;
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -1500,8 +1500,8 @@ bool stop_test()
srslte::log_filter log1("RLC_AM_1");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
rlc_am_tester tester;
srslte::timer_handler timers(8);
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
@ -1532,9 +1532,9 @@ bool status_pdu_test()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
srslte::timers timers(8);
int len = 0;
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
rlc_am rlc1(&log1, 1, &tester, &tester, &timers);
rlc_am rlc2(&log2, 1, &tester, &tester, &timers);

@ -79,8 +79,8 @@ int basic_test()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_tester tester;
srslte::timers timers(1);
rlc_tester tester;
srslte::timer_handler timers(1);
int len = 0;

@ -118,7 +118,7 @@ public:
rlc_interface_mac* rlc2_,
stress_test_args_t args_,
uint32_t lcid_,
timers* timers_,
timer_handler* timers_,
rlc_pcap* pcap_ = NULL) :
run_enable(true),
rlc1(rlc1_),
@ -196,25 +196,21 @@ private:
}
}
rlc_interface_mac *rlc1;
rlc_interface_mac *rlc2;
rlc_interface_mac* rlc1;
rlc_interface_mac* rlc2;
bool run_enable;
stress_test_args_t args;
rlc_pcap* pcap;
uint32_t lcid;
srslte::log_filter log;
srslte::timers* timers = nullptr;
bool run_enable;
stress_test_args_t args;
rlc_pcap* pcap;
uint32_t lcid;
srslte::log_filter log;
srslte::timer_handler* timers = nullptr;
std::mt19937 mt19937;
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:
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);
}
srslte::timers timers(8);
srslte::timer_handler timers(8);
rlc rlc1(&log1);
rlc rlc2(&log2);

@ -85,10 +85,10 @@ int rlc_um_nr_test1()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_um_tester tester;
srslte::timers timers(16);
const uint32_t num_sdus = 5;
int len = 0;
rlc_um_tester tester;
srslte::timer_handler timers(16);
const uint32_t num_sdus = 5;
int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
rlc_um rlc2(&log2, 3, &tester, &tester, &timers);
@ -139,11 +139,11 @@ int rlc_um_nr_test2()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_um_tester tester;
srslte::timers timers(16);
const uint32_t num_sdus = 1;
const uint32_t sdu_size = 100;
int len = 0;
rlc_um_tester tester;
srslte::timer_handler timers(16);
const uint32_t num_sdus = 1;
const uint32_t sdu_size = 100;
int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
rlc_um rlc2(&log2, 3, &tester, &tester, &timers);

@ -47,9 +47,9 @@ int basic_test()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_um_tester tester;
srslte::timers timers(16);
int len = 0;
rlc_um_tester tester;
srslte::timer_handler timers(16);
int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
rlc_um rlc2(&log2, 3, &tester, &tester, &timers);
@ -116,9 +116,9 @@ int loss_test()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_um_tester tester;
srslte::timers timers(16);
int len = 0;
rlc_um_tester tester;
srslte::timer_handler timers(16);
int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
rlc_um rlc2(&log2, 3, &tester, &tester, &timers);
@ -161,8 +161,11 @@ int loss_test()
}
// Step the reordering timer until expiry
while (!timers.get(1)->is_expired())
timers.get(1)->step();
// while (!timers.get(1)->is_expired())
// timers.get(1)->step();
while (timers.nof_running_timers() != 0) {
timers.step_all();
}
TESTASSERT(NBUFS - 1 == tester.sdus.size());
@ -177,9 +180,9 @@ int basic_mbsfn_test()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_um_tester tester;
srslte::timers timers(16);
int len = 0;
rlc_um_tester tester;
srslte::timer_handler timers(16);
int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
rlc_um rlc2(&log2, 3, &tester, &tester, &timers);
@ -248,9 +251,9 @@ int reassmble_test()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_um_tester tester;
srslte::timers timers(16);
int len = 0;
rlc_um_tester tester;
srslte::timer_handler timers(16);
int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
rlc_um rlc2(&log2, 3, &tester, &tester, &timers);
@ -357,9 +360,9 @@ int reassmble_test2()
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_um_tester tester;
srslte::timers timers(16);
int len = 0;
rlc_um_tester tester;
srslte::timer_handler timers(16);
int len = 0;
rlc_um rlc1(&log1, 3, &tester, &tester, &timers);
rlc_um rlc2(&log2, 3, &tester, &tester, &timers);

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

@ -44,11 +44,7 @@ public:
virtual bool process_pdus() = 0;
};
class mac : public mac_interface_phy_lte,
public mac_interface_rlc,
public mac_interface_rrc,
public srslte::mac_interface_timers,
public pdu_process_handler
class mac : public mac_interface_phy_lte, public mac_interface_rlc, public mac_interface_rrc, public pdu_process_handler
{
public:
mac();
@ -104,16 +100,11 @@ public:
int bearer_ue_cfg(uint16_t rnti, uint32_t lc_id, sched_interface::ue_bearer_cfg_t *cfg);
int bearer_ue_rem(uint16_t rnti, uint32_t lc_id);
int rlc_buffer_state(uint16_t rnti, uint32_t lc_id, uint32_t tx_queue, uint32_t retx_queue);
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();
bool process_pdus();
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);
private:
@ -176,30 +167,31 @@ private:
asn1::rrc::sib_type13_r9_s sib13;
const static int mtch_payload_len = 10000;
uint8_t mtch_payload_buffer[mtch_payload_len];
uint8_t mtch_payload_buffer[mtch_payload_len];
/* Functions for MAC Timers */
srslte::timers timers_db;
void setup_timers();
srslte::timer_handler timers_db;
void setup_timers();
// pointer to MAC PCAP object
srslte::mac_pcap* pcap;
/* Class to run upper-layer timers with normal priority */
class timer_thread : public thread {
class timer_thread : public thread
{
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 stop();
private:
void run_thread();
srslte::tti_sync_cv ttisync;
srslte::timers *timers;
srslte::timer_handler *timers;
mac *parent;
bool running;
};
timer_thread timers_thread;
timer_thread timers_thread;
/* Class to process MAC PDUs from DEMUX unit */
class pdu_process : public thread {

@ -31,21 +31,19 @@ typedef struct {
uint32_t lcid;
uint32_t plmn;
uint16_t mtch_stop;
uint8_t *payload;
}mch_service_t;
uint8_t* payload;
} mch_service_t;
namespace srsenb {
class rlc : public rlc_interface_mac,
public rlc_interface_rrc,
public rlc_interface_pdcp
class rlc : public rlc_interface_mac, public rlc_interface_rrc, public rlc_interface_pdcp
{
public:
void init(pdcp_interface_rlc* pdcp_,
rrc_interface_rlc* rrc_,
mac_interface_rlc* mac_,
srslte::timers* timers_,
srslte::log* log_h);
void init(pdcp_interface_rlc* pdcp_,
rrc_interface_rlc* rrc_,
mac_interface_rlc* mac_,
srslte::timer_handler* timers_,
srslte::log* log_h);
void stop();
// rlc_interface_rrc
@ -88,15 +86,15 @@ private:
pthread_rwlock_t rwlock;
std::map<uint32_t,user_interface> users;
std::vector<mch_service_t> mch_services;
mac_interface_rlc *mac;
pdcp_interface_rlc *pdcp;
rrc_interface_rlc* rrc;
srslte::log* log_h;
srslte::byte_buffer_pool* pool;
srslte::timers* timers;
std::map<uint32_t, user_interface> users;
std::vector<mch_service_t> mch_services;
mac_interface_rlc* mac;
pdcp_interface_rlc* pdcp;
rrc_interface_rlc* rrc;
srslte::log* log_h;
srslte::byte_buffer_pool* pool;
srslte::timer_handler* timers;
};
} // namespace srsenb

@ -841,28 +841,6 @@ void mac::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

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

@ -44,10 +44,10 @@ class demux : public srslte::pdu_queue::process_callback
{
public:
demux(srslte::log* log_);
void init(phy_interface_mac_common* phy_h_,
rlc_interface_mac* rlc,
mac_interface_demux* mac,
srslte::timers::timer* time_alignment_timer);
void init(phy_interface_mac_common* phy_h_,
rlc_interface_mac* rlc,
mac_interface_demux* mac,
srslte::timer_handler::unique_timer* time_alignment_timer);
bool process_pdus();
uint8_t* request_buffer(uint32_t len);
@ -77,18 +77,18 @@ private:
void process_sch_pdu(srslte::sch_pdu* pdu);
void process_mch_pdu(srslte::mch_pdu* pdu);
bool process_ce(srslte::sch_subh *subheader);
bool process_ce(srslte::sch_subh* subheader);
bool is_uecrid_successful;
phy_interface_mac_common* phy_h = nullptr;
srslte::log* log_h = nullptr;
srslte::timers::timer* time_alignment_timer = nullptr;
rlc_interface_mac* rlc = nullptr;
mac_interface_demux* mac = nullptr;
phy_interface_mac_common* phy_h = nullptr;
srslte::log* log_h = nullptr;
srslte::timer_handler::unique_timer* time_alignment_timer = nullptr;
rlc_interface_mac* rlc = nullptr;
mac_interface_demux* mac = nullptr;
// Buffer of PDUs
srslte::pdu_queue pdus;
srslte::pdu_queue pdus;
};
} // namespace srsue

@ -40,10 +40,10 @@ class dl_harq_entity
public:
dl_harq_entity();
bool init(srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis,
srslte::timers::timer* timer_aligment_timer,
demux* demux_unit);
bool init(srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis,
srslte::timer_handler::unique_timer* timer_aligment_timer,
demux* demux_unit);
void reset();
void start_pcap(srslte::mac_pcap* pcap_);
@ -117,20 +117,20 @@ private:
uint32_t get_harq_sps_pid(uint32_t tti);
dl_sps dl_sps_assig;
dl_sps dl_sps_assig;
std::vector<dl_harq_process> proc;
dl_harq_process bcch_proc;
srslte::timers::timer *timer_aligment_timer;
demux *demux_unit;
srslte::log *log_h;
srslte::mac_pcap* pcap;
mac_interface_rrc::ue_rnti_t* rntis;
uint16_t last_temporal_crnti;
int si_window_start;
std::vector<dl_harq_process> proc;
dl_harq_process bcch_proc;
srslte::timer_handler::unique_timer* timer_aligment_timer = nullptr;
demux* demux_unit;
srslte::log* log_h;
srslte::mac_pcap* pcap;
mac_interface_rrc::ue_rnti_t* rntis;
uint16_t last_temporal_crnti;
int si_window_start;
float average_retx;
uint64_t nof_pkts;
float average_retx;
uint64_t nof_pkts;
};
typedef std::unique_ptr<dl_harq_entity> dl_harq_entity_ptr;

@ -45,7 +45,6 @@ namespace srsue {
class mac : public mac_interface_phy_lte,
public mac_interface_rrc,
public srslte::timer_callback,
public srslte::mac_interface_timers,
public mac_interface_demux
{
public:
@ -54,7 +53,7 @@ public:
bool init(phy_interface_mac_lte* phy,
rlc_interface_mac* rlc,
rrc_interface_mac* rrc,
srslte::timers* timers_,
srslte::timer_handler* timers_,
stack_interface_mac* stack);
void stop();
@ -109,15 +108,10 @@ public:
void start_pcap(srslte::mac_pcap* pcap);
// Timer callback interface
void timer_expired(uint32_t timer_id);
void timer_expired(uint32_t timer_id);
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:
void clear_rntis();
@ -169,10 +163,10 @@ private:
srslte::mch_pdu mch_msg;
/* Functions for MAC Timers */
uint32_t timer_alignment = 0;
void setup_timers(int time_alignment_timer);
void timer_alignment_expire();
srslte::timers* timers = nullptr;
srslte::timer_handler::unique_timer timer_alignment;
void setup_timers(int time_alignment_timer);
void timer_alignment_expire();
srslte::timer_handler* timers = nullptr;
// pointer to MAC PCAP object
srslte::mac_pcap* pcap = nullptr;

@ -55,8 +55,8 @@ class bsr_proc : public srslte::timer_callback, public bsr_interface_mux
{
public:
bsr_proc();
void init(rlc_interface_mac* rlc, srslte::log* log_h, srslte::timers* timers_db);
void step(uint32_t tti);
void init(rlc_interface_mac* rlc, srslte::log* log_h, srslte::timer_handler* timers_db);
void step(uint32_t tti);
void reset();
void set_config(srslte::bsr_cfg_t& bsr_cfg);
@ -73,14 +73,14 @@ private:
pthread_mutex_t mutex;
bool reset_sr;
srslte::timers *timers_db;
srslte::log *log_h;
rlc_interface_mac *rlc;
bool reset_sr;
srslte::timer_handler* timers_db;
srslte::log* log_h;
rlc_interface_mac* rlc;
srslte::bsr_cfg_t bsr_cfg;
bool initiated;
bool initiated;
const static int NOF_LCG = 4;
@ -109,11 +109,11 @@ private:
bool check_any_channel();
uint32_t get_buffer_state_lcg(uint32_t lcg);
bool generate_bsr(bsr_t* bsr, uint32_t nof_padding_bytes);
char* bsr_type_tostring(triggered_bsr_type_t type);
char* bsr_format_tostring(bsr_format_t format);
char* bsr_type_tostring(triggered_bsr_type_t type);
char* bsr_format_tostring(bsr_format_t format);
uint32_t timer_periodic_id;
uint32_t timer_retx_id;
srslte::timer_handler::unique_timer timer_periodic;
srslte::timer_handler::unique_timer timer_retx;
};
} // namespace srsue

@ -37,32 +37,30 @@ class phr_proc : public srslte::timer_callback
{
public:
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 step(uint32_t tti);
void reset();
bool generate_phr_on_ul_grant(float *phr);
bool generate_phr_on_ul_grant(float* phr);
bool is_extended();
void timer_expired(uint32_t timer_id);
void start_timer();
private:
bool pathloss_changed();
srslte::log* log_h;
phy_interface_mac_lte* phy_h;
srslte::timers* timers_db;
srslte::phr_cfg_t phr_cfg;
bool initiated;
int last_pathloss_db;
bool phr_is_triggered;
bool pathloss_changed();
uint32_t timer_periodic_id;
uint32_t timer_prohibit_id;
srslte::log* log_h;
phy_interface_mac_lte* phy_h;
srslte::timer_handler* timers_db;
srslte::phr_cfg_t phr_cfg;
bool initiated;
int last_pathloss_db;
bool phr_is_triggered;
srslte::timer_handler::unique_timer timer_periodic;
srslte::timer_handler::unique_timer timer_prohibit;
};
} // namespace srsue

@ -59,24 +59,21 @@ public:
started_by_pdcch = false;
rar_grant_nbytes = 0;
noncontention_enabled = false;
next_preamble_idx = 0;
next_prach_mask = 0;
time_alignment_timer = NULL;
contention_resolution_timer = NULL;
noncontention_enabled = false;
next_preamble_idx = 0;
next_prach_mask = 0;
};
~ra_proc();
void init(phy_interface_mac_lte* phy_h,
rrc_interface_mac* rrc_,
srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis,
srslte::timers::timer* time_alignment_timer_,
srslte::timers::timer* contention_resolution_timer_,
mux* mux_unit,
stack_interface_mac* stack_);
void init(phy_interface_mac_lte* phy_h,
rrc_interface_mac* rrc_,
srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis,
srslte::timer_handler::unique_timer* time_alignment_timer_,
srslte::timer_handler::unique_timer contention_resolution_timer_,
mux* mux_unit,
stack_interface_mac* stack_);
void reset();
@ -171,17 +168,17 @@ private:
rrc_interface_mac* rrc;
stack_interface_mac* stack;
srslte::timers::timer* time_alignment_timer;
srslte::timers::timer* contention_resolution_timer;
srslte::timer_handler::unique_timer* time_alignment_timer = nullptr;
srslte::timer_handler::unique_timer contention_resolution_timer;
mac_interface_rrc::ue_rnti_t *rntis;
mac_interface_rrc::ue_rnti_t* rntis;
uint64_t transmitted_contention_id;
uint16_t transmitted_crnti;
uint64_t transmitted_contention_id;
uint16_t transmitted_crnti;
std::mutex mutex;
bool ra_is_ho;
bool ra_is_ho;
bool started_by_pdcch;
uint32_t rar_grant_nbytes;
bool rar_received;

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

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

@ -40,7 +40,7 @@ namespace srsue {
class nas : public nas_interface_rrc, public nas_interface_ue, public srslte::timer_callback
{
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 stop();
void run_tti(uint32_t tti) final;
@ -131,9 +131,9 @@ private:
uint8_t transaction_id = 0;
// timers
srslte::timers* timers = nullptr;
uint32_t t3410 = 0; // started when attach request is sent, on expiry, start t3411
uint32_t t3411 = 0; // started when attach failed
srslte::timer_handler* timers = nullptr;
srslte::timer_handler::unique_timer t3410; // started when attach request is sent, on expiry, start t3411
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 t3411_duration_ms = 10 * 1000; // 10s according to TS 24.301 Sec 10.2

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

@ -44,15 +44,15 @@ dl_harq_entity::dl_harq_entity() : proc(SRSLTE_MAX_HARQ_PROC)
nof_pkts = 0;
}
bool dl_harq_entity::init(srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis,
srslte::timers::timer* timer_aligment_timer,
demux* demux_unit)
bool dl_harq_entity::init(srslte::log* log_h,
mac_interface_rrc::ue_rnti_t* rntis,
srslte::timer_handler::unique_timer* timer_aligment_timer_,
demux* demux_unit)
{
this->timer_aligment_timer = timer_aligment_timer;
this->demux_unit = demux_unit;
this->log_h = log_h;
this->rntis = rntis;
timer_aligment_timer = timer_aligment_timer_;
this->demux_unit = demux_unit;
this->log_h = log_h;
this->rntis = rntis;
for (uint32_t i = 0; i < SRSLTE_MAX_HARQ_PROC; i++) {
if (!proc[i].init(i, this)) {

@ -68,7 +68,7 @@ mac::~mac()
bool mac::init(phy_interface_mac_lte* phy,
rlc_interface_mac* rlc,
rrc_interface_mac* rrc,
srslte::timers* timers_,
srslte::timer_handler* timers_,
stack_interface_mac* stack_)
{
phy_h = phy;
@ -77,26 +77,20 @@ bool mac::init(phy_interface_mac_lte* phy,
timers = timers_;
stack_h = stack_;
timer_alignment = timers->get_unique_id();
uint32_t contention_resolution_timer = timers->get_unique_id();
timer_alignment = timers->get_unique_timer();
srslte::timer_handler::unique_timer contention_resolution_timer = timers->get_unique_timer();
bsr_procedure.init(rlc_h, log_h, timers);
phr_procedure.init(phy_h, log_h, timers);
mux_unit.init(rlc_h, &bsr_procedure, &phr_procedure);
demux_unit.init(phy_h, rlc_h, this, timers->get(timer_alignment));
ra_procedure.init(phy_h,
rrc,
log_h,
&uernti,
timers->get(timer_alignment),
timers->get(contention_resolution_timer),
&mux_unit,
stack_h);
demux_unit.init(phy_h, rlc_h, this, &timer_alignment);
ra_procedure.init(
phy_h, rrc, log_h, &uernti, &timer_alignment, std::move(contention_resolution_timer), &mux_unit, stack_h);
sr_procedure.init(phy_h, rrc, log_h);
// Create UL/DL unique HARQ pointers
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();
@ -143,7 +137,7 @@ void mac::reconfiguration(const uint32_t& cc_idx, const bool& enable)
}
while (dl_harq.size() < cc_idx + 1) {
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) {
dl->start_pcap(pcap);
@ -170,7 +164,7 @@ void mac::reset()
Info("Resetting MAC\n");
timers->get(timer_alignment)->stop();
timer_alignment.stop();
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)
{
// stop currently running time alignment timer
if (timers->get(timer_alignment)->is_running()) {
timers->get(timer_alignment)->stop();
if (timer_alignment.is_running()) {
timer_alignment.stop();
}
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)
{
if(timer_id == timer_alignment) {
if (timer_id == timer_alignment.id()) {
timer_alignment_expire();
} else {
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);
}
/********************************************************
*
* 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

@ -42,14 +42,14 @@ bsr_proc::bsr_proc()
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_;
rlc = rlc_;
log_h = log_h_;
rlc = rlc_;
timers_db = timers_db_;
timer_periodic_id = timers_db->get_unique_id();
timer_retx_id = timers_db->get_unique_id();
timer_periodic = timers_db->get_unique_timer();
timer_retx = timers_db->get_unique_timer();
reset();
initiated = true;
@ -63,13 +63,11 @@ void bsr_proc::set_trigger(srsue::bsr_proc::triggered_bsr_type_t new_trigger)
void bsr_proc::reset()
{
timers_db->get(timer_periodic_id)->stop();
timers_db->get(timer_periodic_id)->reset();
timers_db->get(timer_retx_id)->stop();
timers_db->get(timer_retx_id)->reset();
reset_sr = false;
sr_is_sent = false;
timer_periodic.stop();
timer_retx.stop();
reset_sr = false;
sr_is_sent = false;
triggered_bsr_type = NONE;
trigger_tti = 0;
@ -82,27 +80,28 @@ void bsr_proc::set_config(srslte::bsr_cfg_t& bsr_cfg)
this->bsr_cfg = bsr_cfg;
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);
}
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);
}
pthread_mutex_unlock(&mutex);
}
/* 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);
// periodicBSR-Timer
if (timer_id == timer_periodic_id) {
if (timer_id == timer_periodic.id()) {
if (triggered_bsr_type == NONE) {
set_trigger(PERIODIC);
Debug("BSR: Triggering Periodic BSR\n");
}
// 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
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
@ -237,19 +236,22 @@ bool bsr_proc::generate_bsr(bsr_t* bsr, uint32_t nof_padding_bytes)
bsr->format = LONG_BSR;
}
} else {
bsr->format = SHORT_BSR;
bsr->format = SHORT_BSR;
if (nof_lcg > 1) {
bsr->format = LONG_BSR;
}
}
}
Info("BSR: Type %s, Format %s, Value=%d,%d,%d,%d\n",
bsr_type_tostring(triggered_bsr_type), bsr_format_tostring(bsr->format),
bsr->buff_size[0], bsr->buff_size[1], bsr->buff_size[2], bsr->buff_size[3]);
bsr_type_tostring(triggered_bsr_type),
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
if (timers_db->get(timer_periodic_id)->get_timeout() && bsr->format != TRUNC_BSR) {
timers_db->get(timer_periodic_id)->reset();
timers_db->get(timer_periodic_id)->run();
if (timer_periodic.duration() && bsr->format != TRUNC_BSR) {
timer_periodic.run();
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;
// Restart or Start ReTX timer upon indication of a grant
if (timers_db->get(timer_retx_id)->get_timeout()) {
timers_db->get(timer_retx_id)->reset();
timers_db->get(timer_retx_id)->run();
if (timer_retx.duration()) {
timer_retx.run();
Debug("BSR: Started retxBSR-Timer\n");
}
pthread_mutex_unlock(&mutex);

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

@ -56,14 +56,14 @@ uint32_t backoff_table[16] = {0, 10, 20, 30, 40, 60, 80, 120, 160, 240, 320, 480
int delta_preamble_db_table[5] = {0, 0, -3, -3, 8};
// Initializes memory and pointers to other objects
void ra_proc::init(phy_interface_mac_lte* phy_h_,
rrc_interface_mac* rrc_,
srslte::log* log_h_,
mac_interface_rrc::ue_rnti_t* rntis_,
srslte::timers::timer* time_alignment_timer_,
srslte::timers::timer* contention_resolution_timer_,
mux* mux_unit_,
stack_interface_mac* stack_)
void ra_proc::init(phy_interface_mac_lte* phy_h_,
rrc_interface_mac* rrc_,
srslte::log* log_h_,
mac_interface_rrc::ue_rnti_t* rntis_,
srslte::timer_handler::unique_timer* time_alignment_timer_,
srslte::timer_handler::unique_timer contention_resolution_timer_,
mux* mux_unit_,
stack_interface_mac* stack_)
{
phy_h = phy_h_;
log_h = log_h_;
@ -73,22 +73,23 @@ void ra_proc::init(phy_interface_mac_lte* phy_h_,
stack = stack_;
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);
reset();
}
ra_proc::~ra_proc() {
ra_proc::~ra_proc()
{
srslte_softbuffer_rx_free(&softbuffer_rar);
}
void ra_proc::reset() {
state = IDLE;
void ra_proc::reset()
{
state = IDLE;
started_by_pdcch = false;
contention_resolution_timer->stop();
contention_resolution_timer->reset();
contention_resolution_timer.stop();
}
void ra_proc::start_pcap(srslte::mac_pcap* pcap_)
@ -125,10 +126,10 @@ void ra_proc::read_params()
}
phy_interface_mac_lte::prach_info_t prach_info = phy_h->prach_get_info();
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) {
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()
{
// 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
rInfo("Starting ContentionResolutionTimer=%d ms\n", contention_resolution_timer->get_timeout());
contention_resolution_timer->reset();
contention_resolution_timer->run();
rInfo("Starting ContentionResolutionTimer=%d ms\n", contention_resolution_timer.duration());
contention_resolution_timer.run();
}
}
@ -350,7 +350,6 @@ void ra_proc::process_timeadv_cmd(uint32_t ta)
phy_h->set_timeadv_rar(ta);
// Only if timer is running reset the timer
if (time_alignment_timer->is_running()) {
time_alignment_timer->reset();
time_alignment_timer->run();
}
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");
// 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) {
// 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");
if ((!started_by_pdcch && is_new_uplink_transmission) || started_by_pdcch) {
rDebug("PDCCH for C-RNTI received\n");
contention_resolution_timer->stop();
contention_resolution_timer.stop();
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)
void ra_proc::harq_retx()
{
rInfo("Restarting ContentionResolutionTimer=%d ms\n", contention_resolution_timer->get_timeout());
contention_resolution_timer->reset();
rInfo("Restarting ContentionResolutionTimer=%d ms\n", contention_resolution_timer.duration());
contention_resolution_timer.run();
}
void ra_proc::harq_max_retx()

@ -107,7 +107,7 @@ void rrc::init(phy_interface_rrc_lte* phy_,
nas_interface_rrc* nas_,
usim_interface_rrc* usim_,
gw_interface_rrc* gw_,
srslte::timers* timers_,
srslte::timer_handler* timers_,
stack_interface_rrc* stack_,
const rrc_args_t& args_)
{
@ -130,12 +130,12 @@ void rrc::init(phy_interface_rrc_lte* phy_,
security_is_activated = false;
t300 = timers->get_unique_id();
t301 = timers->get_unique_id();
t302 = timers->get_unique_id();
t310 = timers->get_unique_id();
t311 = timers->get_unique_id();
t304 = timers->get_unique_id();
t300 = timers->get_unique_timer();
t301 = timers->get_unique_timer();
t302 = timers->get_unique_timer();
t310 = timers->get_unique_timer();
t311 = timers->get_unique_timer();
t304 = timers->get_unique_timer();
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,
// T301, T304 nor T311 is running:
if (state == RRC_STATE_CONNECTED) {
if (!timers->get(t300)->is_running() && !timers->get(t301)->is_running() && !timers->get(t304)->is_running() &&
!timers->get(t310)->is_running() && !timers->get(t311)->is_running()) {
if (!t300.is_running() && !t301.is_running() && !t304.is_running() && !t310.is_running() && !t311.is_running()) {
rrc_log->info("Received out-of-sync while in state %s. n310=%d, t311=%s, t310=%s\n",
rrc_state_text[state],
n310_cnt,
timers->get(t311)->is_running() ? "running" : "stop",
timers->get(t310)->is_running() ? "running" : "stop");
t311.is_running() ? "running" : "stop",
t310.is_running() ? "running" : "stop");
n310_cnt++;
if (n310_cnt == N310) {
rrc_log->info("Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n",
N310,
timers->get(t310)->get_timeout());
timers->get(t310)->reset();
timers->get(t310)->run();
rrc_log->info(
"Detected %d out-of-sync from PHY. Trying to resync. Starting T310 timer %d ms\n", N310, t310.duration());
t310.run();
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
serving_cell->in_sync = true;
if (timers->get(t310)->is_running()) {
if (t310.is_running()) {
n311_cnt++;
if (n311_cnt == N311) {
timers->get(t310)->stop();
t310.stop();
n311_cnt = 0;
rrc_log->info("Detected %d in-sync from PHY. Stopping T310 timer\n", N311);
}
@ -819,50 +816,44 @@ void rrc::max_retx_attempted() {
cmd_q.push(std::move(msg));
}
void rrc::timer_expired(uint32_t timeout_id) {
if (timeout_id == t310) {
void rrc::timer_expired(uint32_t timeout_id)
{
if (timeout_id == t310.id()) {
rrc_log->info("Timer T310 expired: Radio Link Failure\n");
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");
start_go_idle();
} else if (timeout_id == t301) {
} else if (timeout_id == t301.id()) {
if (state == RRC_STATE_IDLE) {
rrc_log->info("Timer T301 expired: Already in IDLE.\n");
} else {
rrc_log->info("Timer T301 expired: Going to RRC IDLE\n");
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");
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()
} else if (timeout_id == t304) {
} else if (timeout_id == t304.id()) {
rrc_log->console("Timer T304 expired: Handover failed\n");
ho_failed();
// fw to measurement
// fw to measurement
} else if (!measurements.timer_expired(timeout_id)) {
rrc_log->error("Timeout from unknown timer id %d\n", timeout_id);
}
}
/*******************************************************************************
*
*
*
* Connection Control: Establishment, Reconfiguration, Reestablishment and Release
*
*
*
*******************************************************************************/
*
*
*
* Connection Control: Establishment, Reconfiguration, Reestablishment and Release
*
*
*
*******************************************************************************/
void rrc::send_con_request(srslte::establishment_cause_t cause)
{
@ -1067,8 +1058,8 @@ bool rrc::ho_prepare()
}
// Section 5.3.5.4
timers->get(t310)->stop();
timers->get(t304)->set(this, mob_ctrl_info->t304.to_number());
t310.stop();
t304.set(mob_ctrl_info->t304.to_number(), [this](uint32_t tid) { timer_expired(tid); });
// Save serving cell and current configuration
ho_src_cell = *serving_cell;
@ -1153,12 +1144,12 @@ void rrc::ho_ra_completed(bool ra_successful)
measurements.parse_meas_config(&mob_reconf_r8->meas_cfg);
}
timers->get(t304)->stop();
t304.stop();
}
// T304 will expiry and send ho_failure
rrc_log->info("HO %ssuccessful\n", ra_successful?"":"un");
rrc_log->console("HO %ssuccessful\n", ra_successful?"":"un");
rrc_log->info("HO %ssuccessful\n", ra_successful ? "" : "un");
rrc_log->console("HO %ssuccessful\n", ra_successful ? "" : "un");
pending_mob_reconf = false;
} else {
@ -1348,11 +1339,11 @@ void rrc::leave_connected()
void rrc::stop_timers()
{
timers->get(t300)->stop();
timers->get(t301)->stop();
timers->get(t310)->stop();
timers->get(t311)->stop();
timers->get(t304)->stop();
t300.stop();
t301.stop();
t310.stop();
t311.stop();
t304.stop();
}
/* 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");
// stop timer T310, if running;
timers->get(t310)->stop();
t310.stop();
// start timer T311;
timers->get(t311)->reset();
timers->get(t311)->run();
t311.run();
// Suspend all RB except SRB0
for (int i = 1; i < SRSLTE_N_RADIO_BEARERS; i++) {
@ -1432,7 +1422,7 @@ void rrc::proc_con_restablish_request()
}
// Check timer...
if (timers->get(t311)->is_running()) {
if (t311.is_running()) {
// 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()) {
// 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
// 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",
timers->get(t311)->value());
t311.value());
// stop timer T311;
timers->get(t301)->reset();
t311.stop();
// start timer T301;
timers->get(t301)->run();
t301.run();
// apply the timeAlignmentTimerCommon included in SystemInformationBlockType2;
timers->get(t311)->stop();
// TODO
// initiate transmission of the RRCConnectionReestablishmentRequest message in accordance with 5.3.7.4;
send_con_restablish_request();
@ -1659,20 +1649,21 @@ void rrc::handle_sib2()
log_rr_config_common();
timers->get(t300)->set(this, sib2->ue_timers_and_consts.t300.to_number());
timers->get(t301)->set(this, sib2->ue_timers_and_consts.t301.to_number());
timers->get(t310)->set(this, sib2->ue_timers_and_consts.t310.to_number());
timers->get(t311)->set(this, sib2->ue_timers_and_consts.t311.to_number());
auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); };
t300.set(sib2->ue_timers_and_consts.t300.to_number(), timer_expire_func);
t301.set(sib2->ue_timers_and_consts.t301.to_number(), timer_expire_func);
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();
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",
N310,
N311,
timers->get(t300)->get_timeout(),
timers->get(t301)->get_timeout(),
timers->get(t310)->get_timeout(),
timers->get(t311)->get_timeout());
t300.duration(),
t301.duration(),
t310.duration(),
t311.duration());
}
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->console("Received ConnectionReject. Wait time: %d\n", reject_r8->wait_time);
timers->get(t300)->stop();
t300.stop();
if (reject_r8->wait_time) {
nas->set_barring(nas_interface_rrc::BARRING_ALL);
timers->get(t302)->set(this, reject_r8->wait_time * 1000u);
timers->get(t302)->run();
t302.set(reject_r8->wait_time * 1000, [this](uint32_t tid) { timer_expired(tid); });
t302.run();
} else {
// Perform the actions upon expiry of T302 if wait time is zero
nas->set_barring(nas_interface_rrc::BARRING_NONE);
@ -2543,19 +2534,20 @@ bool rrc::apply_rr_config_dedicated(rr_cfg_ded_s* cnfg)
// TODO
}
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());
timers->get(t310)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t310_r9.to_number());
timers->get(t311)->set(this, cnfg->rlf_timers_and_consts_r9->setup().t311_r9.to_number());
auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); };
t301.set(cnfg->rlf_timers_and_consts_r9->setup().t301_r9.to_number(), timer_expire_func);
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();
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",
N310,
N311,
timers->get(t300)->get_timeout(),
timers->get(t301)->get_timeout(),
timers->get(t310)->get_timeout(),
timers->get(t311)->get_timeout());
t300.duration(),
t301.duration(),
t310.duration(),
t311.duration());
}
for (uint32_t i = 0; i < cnfg->srb_to_add_mod_list.size(); i++) {
// TODO: handle SRB modification
@ -2635,8 +2627,8 @@ void rrc::handle_con_setup(rrc_conn_setup_s* setup)
{
// Must enter CONNECT before stopping T300
state = RRC_STATE_CONNECTED;
timers->get(t300)->stop();
timers->get(t302)->stop();
t300.stop();
t302.stop();
rrc_log->console("RRC Connected\n");
// 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 */
void rrc::handle_con_reest(rrc_conn_reest_s* setup)
{
timers->get(t301)->stop();
t301.stop();
// Reestablish PDCP and RLC for SRB1
pdcp->reestablish(1);
@ -2848,10 +2840,11 @@ void rrc::set_mac_default() {
void rrc::set_rrc_default()
{
N310 = 1;
N311 = 1;
timers->get(t310)->set(this, 1000);
timers->get(t311)->set(this, 1000);
N310 = 1;
N311 = 1;
auto timer_expire_func = [this](uint32_t tid) { timer_expired(tid); };
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;
m->nof_reports_sent++;
timers->get(m->periodic_timer)->stop();
m->periodic_timer.stop();
if (m->nof_reports_sent < cfg->amount) {
timers->get(m->periodic_timer)->reset();
timers->get(m->periodic_timer)->run();
m->periodic_timer.run();
} else {
if (cfg->trigger_type == report_cfg_t::PERIODIC) {
m->triggered = false;
@ -3063,11 +3055,11 @@ bool rrc::rrc_meas::process_event(eutra_event_s* event, uint32_t tti, bool enter
} else if (exit_condition) {
if (!cell->timer_exit_triggered) {
cell->timer_exit_triggered = true;
cell->exit_tti = tti;
cell->exit_tti = tti;
} else if (srslte_tti_interval(tti, cell->exit_tti) >= event->time_to_trigger) {
m->triggered = false;
cell->triggered = false;
timers->get(m->periodic_timer)->stop();
m->periodic_timer.stop();
if (event) {
if (event->event_id.type() == eutra_event_s::event_id_c_::types::event_a3 &&
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
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) {
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);
generate_report(iter->first);
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)
{
timers->get(m->periodic_timer)->stop();
m->periodic_timer.stop();
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) {
if (iter->second.object_id == object_id) {
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)
{
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);
active.erase(measId);
} 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)
{
timers->get(it->second.periodic_timer)->stop();
timers->release_id(it->second.periodic_timer);
log_h->info("MEAS: Removed measId=%d\n", it->first);
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
bool is_new = false;
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 {
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].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",
is_new ? "Added" : "Updated", meas_id->meas_id, meas_id->meas_obj_id, meas_id->report_cfg_id,
active[meas_id->meas_id].periodic_timer, active[meas_id->meas_id].cell_values.size());
is_new ? "Added" : "Updated",
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;
}
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");
rrc_ptr->nas->set_barring(nas_interface_rrc::BARRING_MO_DATA);
return proc_outcome_t::error;
@ -600,8 +600,7 @@ proc_outcome_t rrc::connection_request_proc::step()
return proc_outcome_t::error;
}
rrc_ptr->timers->get(rrc_ptr->t300)->reset();
rrc_ptr->timers->get(rrc_ptr->t300)->run();
rrc_ptr->t300.run();
// Send connectionRequest message to lower layers
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) {
// 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;
}
if (rrc_ptr->state == RRC_STATE_CONNECTED) {
// Received ConnectionSetup
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
Warning("Timer T300 expired: ConnectionRequest timed out\n");
rrc_ptr->mac->reset();

@ -68,8 +68,7 @@ void nas::plmn_search_proc::then(const srslte::proc_state_t& result)
// start T3411
nas_ptr->nas_log->debug("Starting T3411\n");
nas_ptr->timers->get(nas_ptr->t3411)->reset();
nas_ptr->timers->get(nas_ptr->t3411)->run();
nas_ptr->t3411.run();
if (result.is_error()) {
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(srslte::log* log_, srslte::timers* timers_) :
nas::nas(srslte::log* log_, srslte::timer_handler* timers_) :
nas_log(log_),
pool(byte_buffer_pool::get_instance()),
plmn_searcher(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
t3410 = timers->get_unique_id();
timers->get(t3410)->set(this, t3410_duration_ms);
t3411 = timers->get_unique_id();
timers->get(t3411)->set(this, t3411_duration_ms);
t3410.set(t3410_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
t3411.set(t3411_duration_ms, [this](uint32_t tid) { timer_expired(tid); });
running = true;
}
@ -318,11 +317,10 @@ void nas::run_tti(uint32_t tti)
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");
timers->get(t3411)->reset();
timers->get(t3411)->run();
} else if (timeout_id == t3411) {
t3411.run();
} else if (timeout_id == t3411.id()) {
nas_log->info("Timer T3411 expired: trying to attach again\n");
start_attach_request(nullptr, srslte::establishment_cause_t::mo_sig);
} else {
@ -346,12 +344,11 @@ void nas::start_attach_request(srslte::proc_state_t* result, srslte::establishme
// start T3410
nas_log->debug("Starting T3410\n");
timers->get(t3410)->reset();
timers->get(t3410)->run();
t3410.run();
// stop T3411
if (timers->get(t3411)->is_running()) {
timers->get(t3411)->stop();
if (t3411.is_running()) {
t3411.stop();
}
// 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");
// stop T3410
if (timers->get(t3410)->is_running()) {
timers->get(t3410)->stop();
if (t3410.is_running()) {
t3410.stop();
}
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);
// stop T3410
if (timers->get(t3410)->is_running()) {
timers->get(t3410)->stop();
if (t3410.is_running()) {
t3410.stop();
}
enter_emm_deregistered();
@ -1599,9 +1596,9 @@ void nas::gen_attach_request(byte_buffer_t* msg)
}
// stop T3411
if (timers->get(t3411)->is_running()) {
if (t3411.is_running()) {
nas_log->debug("Stopping T3411\n");
timers->get(t3411)->stop();
t3411.stop();
}
}

@ -369,9 +369,9 @@ int mac_unpack_test()
0xc3, 0xb3, 0x5c, 0xa3, 0x23, 0xad, 0x00, 0x03, 0x20, 0x1b, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x13, 0x89, 0x00, 0x00};
srslte::log_filter rlc_log("RLC");
srslte::log_filter mac_log("MAC");
srslte::timers timers(64);
srslte::log_filter rlc_log("RLC");
srslte::log_filter mac_log("MAC");
srslte::timer_handler timers(64);
mac_log.set_level(srslte::LOG_LEVEL_DEBUG);
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
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_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
phy_dummy phy;
@ -1188,7 +1188,7 @@ struct ra_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;
@ -1365,7 +1365,7 @@ int mac_random_access_test()
rlc_log.set_level(srslte::LOG_LEVEL_DEBUG);
rlc_log.set_hex_limit(100000);
srslte::timers timers(64);
srslte::timer_handler timers(64);
// dummy layers
phy_dummy phy;

@ -765,12 +765,6 @@ public:
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 add_srb(uint32_t lcid, pdcp_config_t pdcp_config)
@ -918,7 +912,7 @@ private:
uint32_t prach_preamble_index = 0;
uint16_t dl_rnti = 0;
uint16_t crnti = TTCN3_CRNTI;
srslte::timers timers;
srslte::timer_handler timers;
bool last_dl_ndi[2 * FDD_HARQ_DELAY_MS] = {};
bool last_ul_ndi[2 * FDD_HARQ_DELAY_MS] = {};

@ -206,17 +206,17 @@ int security_command_test()
nas_log.set_hex_limit(100000);
rrc_log.set_hex_limit(100000);
srslte::timers timers(10);
srslte::timer_handler timers(10);
rrc_dummy rrc_dummy;
gw_dummy gw;
gw_dummy gw;
usim_args_t args;
args.algo = "xor";
args.imei = "353490069873319";
args.imsi = "001010123456789";
args.k = "00112233445566778899aabbccddeeff";
args.op = "63BFA50EE6523365FF14C1F45F88737D";
args.algo = "xor";
args.imei = "353490069873319";
args.imsi = "001010123456789";
args.k = "00112233445566778899aabbccddeeff";
args.op = "63BFA50EE6523365FF14C1F45F88737D";
args.using_op = true;
// init USIM
@ -278,9 +278,9 @@ int mme_attach_request_test()
usim_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;
srsue::usim usim(&usim_log);
@ -358,10 +358,10 @@ int esm_info_request_test()
nas_log.set_hex_limit(100000);
rrc_log.set_hex_limit(100000);
srslte::timers timers(10);
srslte::timer_handler timers(10);
rrc_dummy rrc_dummy;
gw_dummy gw;
gw_dummy gw;
usim_args_t args;
args.algo = "xor";
@ -417,7 +417,7 @@ int dedicated_eps_bearer_test()
nas_log.set_hex_limit(100000);
rrc_log.set_hex_limit(100000);
srslte::timers timers(10);
srslte::timer_handler timers(10);
rrc_dummy rrc_dummy;
gw_dummy gw;

Loading…
Cancel
Save