fix RLC AM issues reported by clang-tidy

master
Andre Puschmann 6 years ago
parent 6764fdb964
commit 34535c7efb

@ -56,7 +56,7 @@ public:
log *rlc_log_, log *rlc_log_,
mac_interface_timers *mac_timers_, mac_interface_timers *mac_timers_,
uint32_t lcid_, uint32_t lcid_,
int buffer_size = -1); // -1 to use default buffer sizes int buffer_size_ = -1); // -1 to use default buffer sizes
void stop(); void stop();
void get_metrics(rlc_metrics_t &m); void get_metrics(rlc_metrics_t &m);

@ -71,12 +71,12 @@ class rlc_am : public rlc_common
public: public:
rlc_am(uint32_t queue_len = 16); rlc_am(uint32_t queue_len = 16);
~rlc_am(); ~rlc_am();
void init(log *rlc_entity_log_, void init(log *log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_, srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers); mac_interface_timers *mac_timers_);
bool configure(srslte_rlc_config_t cnfg); bool configure(srslte_rlc_config_t cfg_);
void reestablish(); void reestablish();
void stop(); void stop();
@ -104,7 +104,7 @@ private:
class rlc_am_tx : public timer_callback class rlc_am_tx : public timer_callback
{ {
public: public:
rlc_am_tx(rlc_am *parent_, uint32_t queue_len); rlc_am_tx(rlc_am *parent_, uint32_t queue_len_);
~rlc_am_tx(); ~rlc_am_tx();
void init(); void init();

@ -42,6 +42,7 @@ rlc::rlc()
mac_timers = NULL; mac_timers = NULL;
ue = NULL; ue = NULL;
default_lcid = 0; default_lcid = 0;
buffer_size = 0;
bzero(metrics_time, sizeof(metrics_time)); bzero(metrics_time, sizeof(metrics_time));
pthread_rwlock_init(&rwlock, NULL); pthread_rwlock_init(&rwlock, NULL);
} }
@ -327,7 +328,7 @@ void rlc::write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes)
{ {
rlc_log->info_hex(payload, nof_bytes, "BCCH BCH message received."); rlc_log->info_hex(payload, nof_bytes, "BCCH BCH message received.");
byte_buffer_t *buf = pool_allocate; byte_buffer_t *buf = pool_allocate;
if (buf) { if (buf != NULL) {
memcpy(buf->msg, payload, nof_bytes); memcpy(buf->msg, payload, nof_bytes);
buf->N_bytes = nof_bytes; buf->N_bytes = nof_bytes;
buf->set_timestamp(); buf->set_timestamp();
@ -342,7 +343,7 @@ void rlc::write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes)
{ {
rlc_log->info_hex(payload, nof_bytes, "BCCH TXSCH message received."); rlc_log->info_hex(payload, nof_bytes, "BCCH TXSCH message received.");
byte_buffer_t *buf = pool_allocate; byte_buffer_t *buf = pool_allocate;
if (buf) { if (buf != NULL) {
memcpy(buf->msg, payload, nof_bytes); memcpy(buf->msg, payload, nof_bytes);
buf->N_bytes = nof_bytes; buf->N_bytes = nof_bytes;
buf->set_timestamp(); buf->set_timestamp();
@ -357,7 +358,7 @@ void rlc::write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes)
{ {
rlc_log->info_hex(payload, nof_bytes, "PCCH message received."); rlc_log->info_hex(payload, nof_bytes, "PCCH message received.");
byte_buffer_t *buf = pool_allocate; byte_buffer_t *buf = pool_allocate;
if (buf) { if (buf != NULL) {
memcpy(buf->msg, payload, nof_bytes); memcpy(buf->msg, payload, nof_bytes);
buf->N_bytes = nof_bytes; buf->N_bytes = nof_bytes;
buf->set_timestamp(); buf->set_timestamp();
@ -394,7 +395,7 @@ void rlc::add_bearer(uint32_t lcid)
add_bearer(lcid, srslte_rlc_config_t()); add_bearer(lcid, srslte_rlc_config_t());
} else { } else {
// SRB1 and SRB2 are AM // SRB1 and SRB2 are AM
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg = {};
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45; cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY; cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY;
@ -472,10 +473,10 @@ void rlc::add_bearer_mrb(uint32_t lcid)
if (not valid_lcid_mrb(lcid)) { if (not valid_lcid_mrb(lcid)) {
rlc_entity = new rlc_um(); rlc_entity = new rlc_um();
if (rlc_entity) { if (rlc_entity != NULL) {
// configure and add to array // configure and add to array
rlc_entity->init(rlc_log, lcid, pdcp, rrc, mac_timers); rlc_entity->init(rlc_log, lcid, pdcp, rrc, mac_timers);
if (rlc_entity->configure(srslte_rlc_config_t::mch_config()) == false) { if (not rlc_entity->configure(srslte_rlc_config_t::mch_config())) {
rlc_log->error("Error configuring RLC entity\n."); rlc_log->error("Error configuring RLC entity\n.");
goto delete_and_exit; goto delete_and_exit;
} }
@ -494,7 +495,7 @@ void rlc::add_bearer_mrb(uint32_t lcid)
} }
delete_and_exit: delete_and_exit:
if (rlc_entity) { if (rlc_entity != NULL) {
delete(rlc_entity); delete(rlc_entity);
} }
@ -577,4 +578,4 @@ bool rlc::valid_lcid_mrb(uint32_t lcid)
return true; return true;
} }
} // namespace srsue } // namespace srslte

@ -31,8 +31,8 @@
#include <sstream> #include <sstream>
#define MOD 1024 #define MOD 1024
#define RX_MOD_BASE(x) ((x-vr_r)%1024) #define RX_MOD_BASE(x) (((x)-vr_r)%1024)
#define TX_MOD_BASE(x) ((x-vt_a)%1024) #define TX_MOD_BASE(x) (((x)-vt_a)%1024)
#define LCID (parent->lcid) #define LCID (parent->lcid)
#define RB_NAME (parent->rb_name.c_str()) #define RB_NAME (parent->rb_name.c_str())
@ -198,6 +198,7 @@ rlc_am::rlc_am_tx::rlc_am_tx(rlc_am* parent_, uint32_t queue_len_)
,tx_enabled(false) ,tx_enabled(false)
{ {
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
ZERO_OBJECT(tx_status);
} }
rlc_am::rlc_am_tx::~rlc_am_tx() rlc_am::rlc_am_tx::~rlc_am_tx()
@ -209,7 +210,7 @@ void rlc_am::rlc_am_tx::init()
{ {
log = parent->log; log = parent->log;
if (parent->mac_timers) { if (parent->mac_timers != NULL) {
poll_retx_timer_id = parent->mac_timers->timer_get_unique_id(); poll_retx_timer_id = parent->mac_timers->timer_get_unique_id();
poll_retx_timer = parent->mac_timers->timer_get(poll_retx_timer_id); poll_retx_timer = parent->mac_timers->timer_get(poll_retx_timer_id);
@ -224,10 +225,19 @@ bool rlc_am::rlc_am_tx::configure(srslte_rlc_am_config_t cfg_)
cfg = cfg_; cfg = cfg_;
// check timers // check timers
if (not poll_retx_timer or not status_prohibit_timer) { if (poll_retx_timer == NULL or status_prohibit_timer == NULL) {
return false; return false;
} }
// configure timers
if (cfg.t_status_prohibit > 0) {
status_prohibit_timer->set(this, static_cast<uint32_t>(cfg.t_status_prohibit));
}
if (cfg.t_poll_retx > 0) {
poll_retx_timer->set(this, static_cast<uint32_t>(cfg.t_poll_retx));
}
tx_enabled = true; tx_enabled = true;
return true; return true;
@ -239,13 +249,15 @@ void rlc_am::rlc_am_tx::stop()
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (parent->mac_timers && poll_retx_timer) { tx_enabled = false;
if (parent->mac_timers != NULL && poll_retx_timer != NULL) {
poll_retx_timer->stop(); poll_retx_timer->stop();
parent->mac_timers->timer_release_id(poll_retx_timer_id); parent->mac_timers->timer_release_id(poll_retx_timer_id);
poll_retx_timer = NULL; poll_retx_timer = NULL;
} }
if (parent->mac_timers && status_prohibit_timer) { if (parent->mac_timers != NULL && status_prohibit_timer != NULL) {
status_prohibit_timer->stop(); status_prohibit_timer->stop();
parent->mac_timers->timer_release_id(status_prohibit_timer_id); parent->mac_timers->timer_release_id(status_prohibit_timer_id);
status_prohibit_timer = NULL; status_prohibit_timer = NULL;
@ -283,7 +295,7 @@ void rlc_am::rlc_am_tx::empty_queue()
} }
// deallocate SDU that is currently processed // deallocate SDU that is currently processed
if(tx_sdu) { if (tx_sdu != NULL) {
pool->deallocate(tx_sdu); pool->deallocate(tx_sdu);
tx_sdu = NULL; tx_sdu = NULL;
} }
@ -316,7 +328,7 @@ uint32_t rlc_am::rlc_am_tx::get_buffer_state()
} }
// Bytes needed for retx // Bytes needed for retx
if (retx_queue.size() > 0) { if (not retx_queue.empty()) {
rlc_amd_retx_t retx = retx_queue.front(); rlc_amd_retx_t retx = retx_queue.front();
log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end); log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end);
if(tx_window.end() != tx_window.find(retx.sn)) { if(tx_window.end() != tx_window.find(retx.sn)) {
@ -326,7 +338,7 @@ uint32_t rlc_am::rlc_am_tx::get_buffer_state()
retx_queue.pop_front(); retx_queue.pop_front();
goto unlock_and_return; goto unlock_and_return;
} }
n_bytes = (uint32_t) req_bytes; n_bytes = static_cast<uint32_t>(req_bytes);
log->debug("Buffer state - retx: %d bytes\n", n_bytes); log->debug("Buffer state - retx: %d bytes\n", n_bytes);
goto unlock_and_return; goto unlock_and_return;
} }
@ -336,7 +348,7 @@ uint32_t rlc_am::rlc_am_tx::get_buffer_state()
if (tx_window.size() < 1024) { if (tx_window.size() < 1024) {
n_sdus = tx_sdu_queue.size(); n_sdus = tx_sdu_queue.size();
n_bytes = tx_sdu_queue.size_bytes(); n_bytes = tx_sdu_queue.size_bytes();
if (tx_sdu) { if (tx_sdu != NULL) {
n_sdus++; n_sdus++;
n_bytes += tx_sdu->N_bytes; n_bytes += tx_sdu->N_bytes;
} }
@ -371,7 +383,7 @@ uint32_t rlc_am::rlc_am_tx::get_total_buffer_state()
} }
// Bytes needed for retx // Bytes needed for retx
if(retx_queue.size() > 0) { if(not retx_queue.empty()) {
rlc_amd_retx_t retx = retx_queue.front(); rlc_amd_retx_t retx = retx_queue.front();
log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end); log->debug("Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", retx.sn, retx.is_segment ? "true" : "false", retx.so_start, retx.so_end);
if(tx_window.end() != tx_window.find(retx.sn)) { if(tx_window.end() != tx_window.find(retx.sn)) {
@ -390,19 +402,19 @@ uint32_t rlc_am::rlc_am_tx::get_total_buffer_state()
if(tx_window.size() < 1024) { if(tx_window.size() < 1024) {
n_sdus = tx_sdu_queue.size(); n_sdus = tx_sdu_queue.size();
n_bytes += tx_sdu_queue.size_bytes(); n_bytes += tx_sdu_queue.size_bytes();
if(tx_sdu) if (tx_sdu != NULL) {
{
n_sdus++; n_sdus++;
n_bytes += tx_sdu->N_bytes; n_bytes += tx_sdu->N_bytes;
} }
} }
// Room needed for header extensions? (integer rounding) // Room needed for header extensions? (integer rounding)
if(n_sdus > 1) if (n_sdus > 1) {
n_bytes += ((n_sdus-1)*1.5)+0.5; n_bytes += ((n_sdus-1)*1.5)+0.5;
}
// Room needed for fixed header? // Room needed for fixed header?
if(n_bytes > 0) { if (n_bytes > 0) {
n_bytes += 3; n_bytes += 3;
log->debug("Buffer state - tx SDUs: %d bytes\n", n_bytes); log->debug("Buffer state - tx SDUs: %d bytes\n", n_bytes);
} }
@ -417,7 +429,8 @@ void rlc_am::rlc_am_tx::write_sdu(byte_buffer_t *sdu, bool blocking)
byte_buffer_pool::get_instance()->deallocate(sdu); byte_buffer_pool::get_instance()->deallocate(sdu);
return; return;
} }
if (sdu) {
if (sdu != NULL) {
if (blocking) { if (blocking) {
// block on write to queue // block on write to queue
tx_sdu_queue.write(sdu); tx_sdu_queue.write(sdu);
@ -427,7 +440,7 @@ void rlc_am::rlc_am_tx::write_sdu(byte_buffer_t *sdu, bool blocking)
if (tx_sdu_queue.try_write(sdu)) { if (tx_sdu_queue.try_write(sdu)) {
log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", RB_NAME, sdu->N_bytes, tx_sdu_queue.size()); log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", RB_NAME, sdu->N_bytes, tx_sdu_queue.size());
} else { } else {
log->info_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", RB_NAME, sdu->N_bytes, tx_sdu_queue.size()); log->debug_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", RB_NAME, sdu->N_bytes, tx_sdu_queue.size());
pool->deallocate(sdu); pool->deallocate(sdu);
} }
} }
@ -439,11 +452,17 @@ void rlc_am::rlc_am_tx::write_sdu(byte_buffer_t *sdu, bool blocking)
int rlc_am::rlc_am_tx::read_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_am::rlc_am_tx::read_pdu(uint8_t *payload, uint32_t nof_bytes)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
int pdu_size = 0; int pdu_size = 0;
log->debug("MAC opportunity - %d bytes\n", nof_bytes); log->debug("MAC opportunity - %d bytes\n", nof_bytes);
log->debug("tx_window size - %zu PDUs\n", tx_window.size()); log->debug("tx_window size - %zu PDUs\n", tx_window.size());
if (not tx_enabled) {
log->debug("RLC entity not active. Not generating PDU.\n");
goto unlock_and_exit;
}
// Tx STATUS if requested // Tx STATUS if requested
if(do_status() && not status_prohibited) { if(do_status() && not status_prohibited) {
pdu_size = build_status_pdu(payload, nof_bytes); pdu_size = build_status_pdu(payload, nof_bytes);
@ -451,10 +470,10 @@ int rlc_am::rlc_am_tx::read_pdu(uint8_t *payload, uint32_t nof_bytes)
} }
// if tx_window is full and retx_queue empty, retransmit next PDU to be ack'ed // if tx_window is full and retx_queue empty, retransmit next PDU to be ack'ed
if (tx_window.size() >= RLC_AM_WINDOW_SIZE && retx_queue.size() == 0) { if (tx_window.size() >= RLC_AM_WINDOW_SIZE && retx_queue.empty()) {
if (tx_window[vt_a].buf != NULL) { if (tx_window[vt_a].buf != NULL) {
log->warning("Full Tx window, ReTx'ing first outstanding PDU\n"); log->warning("Full Tx window, ReTx'ing first outstanding PDU\n");
rlc_amd_retx_t retx; rlc_amd_retx_t retx = {};
retx.is_segment = false; retx.is_segment = false;
retx.so_start = 0; retx.so_start = 0;
retx.so_end = tx_window[vt_a].buf->N_bytes; retx.so_end = tx_window[vt_a].buf->N_bytes;
@ -466,7 +485,7 @@ int rlc_am::rlc_am_tx::read_pdu(uint8_t *payload, uint32_t nof_bytes)
} }
// RETX if required // RETX if required
if(retx_queue.size() > 0) { if (not retx_queue.empty()) {
pdu_size = build_retx_pdu(payload, nof_bytes); pdu_size = build_retx_pdu(payload, nof_bytes);
if (pdu_size > 0) { if (pdu_size > 0) {
goto unlock_and_exit; goto unlock_and_exit;
@ -485,14 +504,14 @@ unlock_and_exit:
void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id) void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (poll_retx_timer && poll_retx_timer_id == timeout_id) { if (poll_retx_timer != NULL && poll_retx_timer_id == timeout_id) {
// if both tx and retx buffer are empty, retransmit next PDU to be ack'ed (Section 5.2.2.3 in TS 36.322) // if both tx and retx buffer are empty, retransmit next PDU to be ack'ed (Section 5.2.2.3 in TS 36.322)
log->debug("Poll reTx timer expired (lcid=%d)\n", parent->lcid); log->debug("Poll reTx timer expired (lcid=%d)\n", parent->lcid);
if ((tx_window.size() > 0 && retx_queue.size() == 0 && tx_sdu_queue.size() == 0)) { if ((not tx_window.empty() && retx_queue.empty() && tx_sdu_queue.size() == 0)) {
std::map<uint32_t, rlc_amd_tx_pdu_t>::iterator it = tx_window.find(vt_s - 1); std::map<uint32_t, rlc_amd_tx_pdu_t>::iterator it = tx_window.find(vt_s - 1);
if (it != tx_window.end()) { if (it != tx_window.end()) {
log->info("Schedule last PDU (SN=%d) for reTx.\n", vt_s - 1); log->info("Schedule last PDU (SN=%d) for reTx.\n", vt_s - 1);
rlc_amd_retx_t retx; rlc_amd_retx_t retx = {};
retx.is_segment = false; retx.is_segment = false;
retx.so_start = 0; retx.so_start = 0;
retx.so_end = tx_window[vt_s - 1].buf->N_bytes; retx.so_end = tx_window[vt_s - 1].buf->N_bytes;
@ -503,9 +522,8 @@ void rlc_am::rlc_am_tx::timer_expired(uint32_t timeout_id)
} }
} }
} else } else
if (status_prohibit_timer && status_prohibit_timer_id == timeout_id) { if (status_prohibit_timer != NULL && status_prohibit_timer_id == timeout_id) {
status_prohibited = true; status_prohibited = false;
status_prohibit_timer->reset();
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
@ -528,25 +546,28 @@ void rlc_am::rlc_am_tx::reset_metrics()
bool rlc_am::rlc_am_tx::poll_required() bool rlc_am::rlc_am_tx::poll_required()
{ {
if (cfg.poll_pdu > 0 && pdu_without_poll > (uint32_t)cfg.poll_pdu) { if (cfg.poll_pdu > 0 && pdu_without_poll > static_cast<uint32_t>(cfg.poll_pdu)) {
return true; return true;
} }
if (cfg.poll_byte > 0 && byte_without_poll > (uint32_t)cfg.poll_byte) { if (cfg.poll_byte > 0 && byte_without_poll > static_cast<uint32_t>(cfg.poll_byte)) {
return true; return true;
} }
if (poll_retx_timer) { if (poll_retx_timer != NULL) {
if (poll_retx_timer->is_expired()) { if (poll_retx_timer->is_expired()) {
// re-arm timer // re-arm timer
poll_retx_timer->reset(); poll_retx_timer->reset();
poll_retx_timer->set(this, cfg.t_poll_retx);
poll_retx_timer->run(); poll_retx_timer->run();
return true; return true;
} }
} }
if (tx_sdu_queue.size() == 0 && retx_queue.size() == 0) { if (tx_window.size() >= RLC_AM_WINDOW_SIZE) {
return true;
}
if (tx_sdu_queue.size() == 0 && retx_queue.empty()) {
return true; return true;
} }
@ -565,25 +586,28 @@ bool rlc_am::rlc_am_tx::poll_required()
int rlc_am::rlc_am_tx::build_status_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_am::rlc_am_tx::build_status_pdu(uint8_t *payload, uint32_t nof_bytes)
{ {
int pdu_len = parent->rx.get_status(&tx_status); int pdu_len = parent->rx.get_status(&tx_status);
if (pdu_len > 0 && nof_bytes >= (uint32_t)pdu_len) if (pdu_len > 0 && nof_bytes >= static_cast<uint32_t>(pdu_len)) {
{
log->info("%s Tx status PDU - %s\n", log->info("%s Tx status PDU - %s\n",
RB_NAME, rlc_am_to_string(&tx_status).c_str()); RB_NAME, rlc_am_to_string(&tx_status).c_str());
parent->rx.reset_status(); parent->rx.reset_status();
if(cfg.t_status_prohibit > 0 && status_prohibit_timer) { if (cfg.t_status_prohibit > 0 && status_prohibit_timer != NULL) {
status_prohibited = false; status_prohibited = true;
status_prohibit_timer->set(this, cfg.t_status_prohibit);
// re-arm timer
status_prohibit_timer->reset();
status_prohibit_timer->run(); status_prohibit_timer->run();
} }
debug_state(); debug_state();
return rlc_am_write_status_pdu(&tx_status, payload); pdu_len = rlc_am_write_status_pdu(&tx_status, payload);
}else{ } else{
log->warning("%s Cannot tx status PDU - %d bytes available, %d bytes required\n", log->warning("%s Cannot tx status PDU - %d bytes available, %d bytes required\n",
RB_NAME, nof_bytes, pdu_len); RB_NAME, nof_bytes, pdu_len);
return 0; pdu_len = 0;
} }
return pdu_len;
} }
int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
@ -614,7 +638,8 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
retx_queue.pop_front(); retx_queue.pop_front();
return -1; return -1;
} }
if(retx.is_segment || req_size > (int)nof_bytes) {
if (retx.is_segment || req_size > static_cast<int>(nof_bytes)) {
log->debug("%s build_retx_pdu - resegmentation required\n", RB_NAME); log->debug("%s build_retx_pdu - resegmentation required\n", RB_NAME);
return build_segment(payload, nof_bytes, retx); return build_segment(payload, nof_bytes, retx);
} }
@ -633,8 +658,8 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s; poll_sn = vt_s;
pdu_without_poll = 0; pdu_without_poll = 0;
byte_without_poll = 0; byte_without_poll = 0;
if (poll_retx_timer) { if (poll_retx_timer != NULL) {
poll_retx_timer->set(this, cfg.t_poll_retx); poll_retx_timer->reset();
poll_retx_timer->run(); poll_retx_timer->run();
} }
} }
@ -646,6 +671,8 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
retx_queue.pop_front(); retx_queue.pop_front();
tx_window[retx.sn].retx_count++; tx_window[retx.sn].retx_count++;
if (tx_window[retx.sn].retx_count >= cfg.max_retx_thresh) { if (tx_window[retx.sn].retx_count >= cfg.max_retx_thresh) {
log->warning("%s Signaling max number of reTx=%d for for PDU %d\n",
RB_NAME, tx_window[retx.sn].retx_count, retx.sn);
parent->rrc->max_retx_attempted(); parent->rrc->max_retx_attempted();
} }
@ -656,15 +683,14 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
return (ptr-payload) + tx_window[retx.sn].buf->N_bytes; return (ptr-payload) + tx_window[retx.sn].buf->N_bytes;
} }
int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t retx) int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t retx) {
{ if (tx_window[retx.sn].buf == NULL) {
if (!tx_window[retx.sn].buf) {
log->error("In build_segment: retx.sn=%d has null buffer\n", retx.sn); log->error("In build_segment: retx.sn=%d has null buffer\n", retx.sn);
return 0; return 0;
} }
if(!retx.is_segment){ if (!retx.is_segment) {
retx.so_start = 0; retx.so_start = 0;
retx.so_end = tx_window[retx.sn].buf->N_bytes; retx.so_end = tx_window[retx.sn].buf->N_bytes;
} }
// Construct new header // Construct new header
@ -676,28 +702,27 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
log->info("%s pdu_without_poll: %d\n", RB_NAME, pdu_without_poll); log->info("%s pdu_without_poll: %d\n", RB_NAME, pdu_without_poll);
log->info("%s byte_without_poll: %d\n", RB_NAME, byte_without_poll); log->info("%s byte_without_poll: %d\n", RB_NAME, byte_without_poll);
new_header.dc = RLC_DC_FIELD_DATA_PDU; new_header.dc = RLC_DC_FIELD_DATA_PDU;
new_header.rf = 1; new_header.rf = 1;
new_header.fi = RLC_FI_FIELD_NOT_START_OR_END_ALIGNED; new_header.fi = RLC_FI_FIELD_NOT_START_OR_END_ALIGNED;
new_header.sn = old_header.sn; new_header.sn = old_header.sn;
new_header.lsf = 0; new_header.lsf = 0;
new_header.so = retx.so_start; new_header.so = retx.so_start;
new_header.N_li = 0; new_header.N_li = 0;
new_header.p = 0; new_header.p = 0;
if(poll_required()) if (poll_required()) {
{
log->debug("%s setting poll bit to request status\n", RB_NAME); log->debug("%s setting poll bit to request status\n", RB_NAME);
new_header.p = 1; new_header.p = 1;
poll_sn = vt_s; poll_sn = vt_s;
pdu_without_poll = 0; pdu_without_poll = 0;
byte_without_poll = 0; byte_without_poll = 0;
if (poll_retx_timer) { if (poll_retx_timer != NULL) {
poll_retx_timer->set(this, cfg.t_poll_retx); poll_retx_timer->reset();
poll_retx_timer->run(); poll_retx_timer->run();
} }
} }
uint32_t head_len = 0; uint32_t head_len = 0;
uint32_t pdu_space = 0; uint32_t pdu_space = 0;
head_len = rlc_am_packed_length(&new_header); head_len = rlc_am_packed_length(&new_header);
@ -706,48 +731,55 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
head_len += 2; head_len += 2;
} }
if(nof_bytes <= head_len) if (nof_bytes <= head_len) {
{
log->warning("%s Cannot build a PDU segment - %d bytes available, %d bytes required for header\n", log->warning("%s Cannot build a PDU segment - %d bytes available, %d bytes required for header\n",
RB_NAME, nof_bytes, head_len); RB_NAME, nof_bytes, head_len);
return 0; return 0;
} }
pdu_space = nof_bytes-head_len; pdu_space = nof_bytes - head_len;
if(pdu_space < (retx.so_end-retx.so_start)) if (pdu_space < (retx.so_end - retx.so_start)) {
retx.so_end = retx.so_start+pdu_space; retx.so_end = retx.so_start + pdu_space;
}
// Need to rebuild the li table & update fi based on so_start and so_end // Need to rebuild the li table & update fi based on so_start and so_end
if(retx.so_start == 0 && rlc_am_start_aligned(old_header.fi)) if (retx.so_start == 0 && rlc_am_start_aligned(old_header.fi)) {
new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment is start aligned new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment is start aligned
}
uint32_t lower = 0; uint32_t lower = 0;
uint32_t upper = 0; uint32_t upper = 0;
uint32_t li = 0; uint32_t li = 0;
for(uint32_t i=0; i<old_header.N_li; i++) { for(uint32_t i=0; i<old_header.N_li; i++) {
if(lower >= retx.so_end) if (lower >= retx.so_end) {
break; break;
}
if(pdu_space <= 2) if (pdu_space <= 2) {
break; break;
}
upper += old_header.li[i]; upper += old_header.li[i];
head_len = rlc_am_packed_length(&new_header); head_len = rlc_am_packed_length(&new_header);
pdu_space = nof_bytes-head_len; pdu_space = nof_bytes-head_len;
if(pdu_space < (retx.so_end-retx.so_start)) if(pdu_space < (retx.so_end-retx.so_start)) {
retx.so_end = retx.so_start+pdu_space; retx.so_end = retx.so_start + pdu_space;
}
if(upper > retx.so_start && lower < retx.so_end) { // Current SDU is needed if(upper > retx.so_start && lower < retx.so_end) { // Current SDU is needed
li = upper - lower; li = upper - lower;
if(upper > retx.so_end) if (upper > retx.so_end) {
li -= upper - retx.so_end; li -= upper - retx.so_end;
if(lower < retx.so_start) }
if (lower < retx.so_start) {
li -= retx.so_start - lower; li -= retx.so_start - lower;
if(lower > 0 && lower == retx.so_start) }
if (lower > 0 && lower == retx.so_start) {
new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment start is aligned with this SDU new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment start is aligned with this SDU
if(upper == retx.so_end) { }
if (upper == retx.so_end) {
new_header.fi &= RLC_FI_FIELD_NOT_START_ALIGNED; // segment end is aligned with this SDU new_header.fi &= RLC_FI_FIELD_NOT_START_ALIGNED; // segment end is aligned with this SDU
} }
new_header.li[new_header.N_li++] = li; new_header.li[new_header.N_li++] = li;
@ -767,15 +799,17 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
if(tx_window[retx.sn].buf->N_bytes == retx.so_end) { if(tx_window[retx.sn].buf->N_bytes == retx.so_end) {
retx_queue.pop_front(); retx_queue.pop_front();
new_header.lsf = 1; new_header.lsf = 1;
if(rlc_am_end_aligned(old_header.fi)) if(rlc_am_end_aligned(old_header.fi)) {
new_header.fi &= RLC_FI_FIELD_NOT_START_ALIGNED; // segment is end aligned new_header.fi &= RLC_FI_FIELD_NOT_START_ALIGNED; // segment is end aligned
}
} else if(retx_queue.front().so_end == retx.so_end) { } else if(retx_queue.front().so_end == retx.so_end) {
retx_queue.pop_front(); retx_queue.pop_front();
} else { } else {
retx_queue.front().is_segment = true; retx_queue.front().is_segment = true;
retx_queue.front().so_start = retx.so_end; retx_queue.front().so_start = retx.so_end;
if(new_header.N_li > 0) if (new_header.N_li > 0) {
new_header.N_li--; new_header.N_li--;
}
} }
// Write header and pdu // Write header and pdu
@ -790,7 +824,7 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
debug_state(); debug_state();
int pdu_len = (ptr-payload) + len; int pdu_len = (ptr-payload) + len;
if(pdu_len > (int)nof_bytes) { if (pdu_len > static_cast<int>(nof_bytes)) {
log->error("%s Retx PDU segment length error. Available: %d, Used: %d\n", log->error("%s Retx PDU segment length error. Available: %d, Used: %d\n",
RB_NAME, nof_bytes, pdu_len); RB_NAME, nof_bytes, pdu_len);
log->debug("%s Retx PDU segment length error. Header len: %ld, Payload len: %d, N_li: %d\n", log->debug("%s Retx PDU segment length error. Header len: %ld, Payload len: %d, N_li: %d\n",
@ -802,20 +836,20 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
{ {
if(!tx_sdu && tx_sdu_queue.size() == 0) if(tx_sdu == NULL && tx_sdu_queue.size() == 0)
{ {
log->info("No data available to be sent\n"); log->info("No data available to be sent\n");
return 0; return 0;
} }
// do not build any more PDU if window is already full // do not build any more PDU if window is already full
if (!tx_sdu && tx_window.size() >= RLC_AM_WINDOW_SIZE) { if (tx_sdu == NULL && tx_window.size() >= RLC_AM_WINDOW_SIZE) {
log->info("Tx window full.\n"); log->info("Tx window full.\n");
return 0; return 0;
} }
byte_buffer_t *pdu = pool_allocate_blocking; byte_buffer_t *pdu = pool_allocate_blocking;
if (!pdu) { if (pdu == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG
log->console("Fatal Error: Could not allocate PDU in build_data_pdu()\n"); log->console("Fatal Error: Could not allocate PDU in build_data_pdu()\n");
log->console("tx_window size: %d PDUs\n", tx_window.size()); log->console("tx_window size: %d PDUs\n", tx_window.size());
@ -862,8 +896,7 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
RB_NAME, pdu_space, head_len); RB_NAME, pdu_space, head_len);
// Check for SDU segment // Check for SDU segment
if(tx_sdu) if (tx_sdu != NULL) {
{
to_move = ((pdu_space-head_len) >= tx_sdu->N_bytes) ? tx_sdu->N_bytes : pdu_space-head_len; to_move = ((pdu_space-head_len) >= tx_sdu->N_bytes) ? tx_sdu->N_bytes : pdu_space-head_len;
memcpy(pdu_ptr, tx_sdu->msg, to_move); memcpy(pdu_ptr, tx_sdu->msg, to_move);
last_li = to_move; last_li = to_move;
@ -878,10 +911,11 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
pool->deallocate(tx_sdu); pool->deallocate(tx_sdu);
tx_sdu = NULL; tx_sdu = NULL;
} }
if(pdu_space > to_move) if (pdu_space > to_move) {
pdu_space -= to_move; pdu_space -= to_move;
else } else {
pdu_space = 0; pdu_space = 0;
}
header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU
log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n",
@ -889,12 +923,12 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
} }
// Pull SDUs from queue // Pull SDUs from queue
while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) while (pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) {
{ if (last_li > 0) {
if(last_li > 0)
header.li[header.N_li++] = last_li; header.li[header.N_li++] = last_li;
}
head_len = rlc_am_packed_length(&header); head_len = rlc_am_packed_length(&header);
if(head_len >= pdu_space) { if (head_len >= pdu_space) {
header.N_li--; header.N_li--;
break; break;
} }
@ -913,10 +947,11 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
pool->deallocate(tx_sdu); pool->deallocate(tx_sdu);
tx_sdu = NULL; tx_sdu = NULL;
} }
if(pdu_space > to_move) if(pdu_space > to_move) {
pdu_space -= to_move; pdu_space -= to_move;
else } else {
pdu_space = 0; pdu_space = 0;
}
log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n", log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n",
RB_NAME, to_move, pdu_space, head_len); RB_NAME, to_move, pdu_space, head_len);
@ -928,8 +963,9 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
return 0; return 0;
} }
if(tx_sdu) if (tx_sdu != NULL) {
header.fi |= RLC_FI_FIELD_NOT_END_ALIGNED; // Last byte does not correspond to last byte of SDU header.fi |= RLC_FI_FIELD_NOT_END_ALIGNED; // Last byte does not correspond to last byte of SDU
}
// Set Poll bit // Set Poll bit
pdu_without_poll++; pdu_without_poll++;
@ -943,8 +979,8 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s; poll_sn = vt_s;
pdu_without_poll = 0; pdu_without_poll = 0;
byte_without_poll = 0; byte_without_poll = 0;
if (poll_retx_timer) { if (poll_retx_timer != NULL) {
poll_retx_timer->set(this, cfg.t_poll_retx); poll_retx_timer->reset();
poll_retx_timer->run(); poll_retx_timer->run();
} }
} }
@ -979,7 +1015,7 @@ 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_to_string(&status).c_str()); log->info("%s Rx Status PDU: %s\n", RB_NAME, rlc_am_to_string(&status).c_str());
if (poll_retx_timer) { if (poll_retx_timer != NULL) {
poll_retx_timer->reset(); poll_retx_timer->reset();
} }
@ -1005,7 +1041,8 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
if(tx_window.end() != it) if(tx_window.end() != it)
{ {
if(!retx_queue_has_sn(i)) { if(!retx_queue_has_sn(i)) {
rlc_amd_retx_t retx; rlc_amd_retx_t retx = {};
retx.sn = i;
retx.is_segment = false; retx.is_segment = false;
retx.so_start = 0; retx.so_start = 0;
retx.so_end = it->second.buf->N_bytes; retx.so_end = it->second.buf->N_bytes;
@ -1036,8 +1073,6 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
RB_NAME, i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes); RB_NAME, i, status.nacks[j].so_start, status.nacks[j].so_end, it->second.buf->N_bytes);
} }
} }
retx.sn = i;
retx_queue.push_back(retx); retx_queue.push_back(retx);
} }
} }
@ -1050,7 +1085,7 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
it = tx_window.find(i); it = tx_window.find(i);
if (it != tx_window.end()) { if (it != tx_window.end()) {
if(update_vt_a) { if(update_vt_a) {
if(it->second.buf) { if (it->second.buf != NULL) {
pool->deallocate(it->second.buf); pool->deallocate(it->second.buf);
it->second.buf = 0; it->second.buf = 0;
} }
@ -1080,7 +1115,7 @@ void rlc_am::rlc_am_tx::debug_state()
int rlc_am::rlc_am_tx::required_buffer_size(rlc_amd_retx_t retx) int rlc_am::rlc_am_tx::required_buffer_size(rlc_amd_retx_t retx)
{ {
if (!retx.is_segment) { if (!retx.is_segment) {
if (tx_window.count(retx.sn)) { if (tx_window.count(retx.sn) == 1) {
if (tx_window[retx.sn].buf) { if (tx_window[retx.sn].buf) {
return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes; return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes;
} else { } else {
@ -1106,33 +1141,34 @@ int rlc_am::rlc_am_tx::required_buffer_size(rlc_amd_retx_t retx)
new_header.so = retx.so_start; new_header.so = retx.so_start;
new_header.N_li = 0; new_header.N_li = 0;
uint32_t head_len = 0;
// Need to rebuild the li table & update fi based on so_start and so_end // Need to rebuild the li table & update fi based on so_start and so_end
if(retx.so_start != 0 && rlc_am_start_aligned(old_header.fi)) if(retx.so_start != 0 && rlc_am_start_aligned(old_header.fi)) {
new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment is start aligned new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment is start aligned
}
uint32_t lower = 0; uint32_t lower = 0;
uint32_t upper = 0; uint32_t upper = 0;
uint32_t li = 0; uint32_t li = 0;
for(uint32_t i=0; i<old_header.N_li; i++) { for(uint32_t i=0; i<old_header.N_li; i++) {
if(lower >= retx.so_end) if(lower >= retx.so_end) {
break; break;
}
upper += old_header.li[i]; upper += old_header.li[i];
head_len = rlc_am_packed_length(&new_header); if (upper > retx.so_start && lower < retx.so_end) { // Current SDU is needed
if(upper > retx.so_start && lower < retx.so_end) { // Current SDU is needed
li = upper - lower; li = upper - lower;
if(upper > retx.so_end) if (upper > retx.so_end) {
li -= upper - retx.so_end; li -= upper - retx.so_end;
if(lower < retx.so_start) }
if (lower < retx.so_start) {
li -= retx.so_start - lower; li -= retx.so_start - lower;
if(lower > 0 && lower == retx.so_start) }
if (lower > 0 && lower == retx.so_start) {
new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment start is aligned with this SDU new_header.fi &= RLC_FI_FIELD_NOT_END_ALIGNED; // segment start is aligned with this SDU
if(upper == retx.so_end) { }
if (upper == retx.so_end) {
new_header.fi &= RLC_FI_FIELD_NOT_START_ALIGNED; // segment end is aligned with this SDU new_header.fi &= RLC_FI_FIELD_NOT_START_ALIGNED; // segment end is aligned with this SDU
} }
new_header.li[new_header.N_li++] = li; new_header.li[new_header.N_li++] = li;
@ -1152,9 +1188,10 @@ int rlc_am::rlc_am_tx::required_buffer_size(rlc_amd_retx_t retx)
bool rlc_am::rlc_am_tx::retx_queue_has_sn(uint32_t sn) bool rlc_am::rlc_am_tx::retx_queue_has_sn(uint32_t sn)
{ {
std::deque<rlc_amd_retx_t>::iterator q_it; std::deque<rlc_amd_retx_t>::iterator q_it;
for(q_it = retx_queue.begin(); q_it != retx_queue.end(); q_it++) { for (q_it = retx_queue.begin(); q_it != retx_queue.end(); ++q_it) {
if(q_it->sn == sn) if (q_it->sn == sn) {
return true; return true;
}
} }
return false; return false;
} }
@ -1192,8 +1229,8 @@ rlc_am::rlc_am_rx::~rlc_am_rx()
void rlc_am::rlc_am_rx::init() void rlc_am::rlc_am_rx::init()
{ {
log = parent->log; log = parent->log;
if (parent->mac_timers) { if (parent->mac_timers != NULL) {
reordering_timer_id = parent->mac_timers->timer_get_unique_id(); reordering_timer_id = parent->mac_timers->timer_get_unique_id();
reordering_timer = parent->mac_timers->timer_get(reordering_timer_id); reordering_timer = parent->mac_timers->timer_get(reordering_timer_id);
} }
@ -1205,10 +1242,15 @@ bool rlc_am::rlc_am_rx::configure(srslte_rlc_am_config_t cfg_)
cfg = cfg_; cfg = cfg_;
// check timers // check timers
if (not reordering_timer) { if (reordering_timer == NULL) {
return false; return false;
} }
// configure timer
if (cfg.t_reordering > 0) {
reordering_timer->set(this, static_cast<uint32_t>(cfg.t_reordering));
}
return true; return true;
} }
@ -1221,13 +1263,13 @@ void rlc_am::rlc_am_rx::stop()
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (parent->mac_timers && reordering_timer) { if (parent->mac_timers != NULL && reordering_timer != NULL) {
reordering_timer->stop(); reordering_timer->stop();
parent->mac_timers->timer_release_id(reordering_timer_id); parent->mac_timers->timer_release_id(reordering_timer_id);
reordering_timer = NULL; reordering_timer = NULL;
} }
if (rx_sdu) { if (rx_sdu != NULL) {
pool->deallocate(rx_sdu); pool->deallocate(rx_sdu);
rx_sdu = NULL; rx_sdu = NULL;
} }
@ -1269,7 +1311,10 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
std::map<uint32_t, rlc_amd_rx_pdu_t>::iterator it; std::map<uint32_t, rlc_amd_rx_pdu_t>::iterator it;
log->info_hex(payload, nof_bytes, "%s Rx data PDU SN: %d (%d B), %s", log->info_hex(payload, nof_bytes, "%s Rx data PDU SN: %d (%d B), %s",
RB_NAME, header.sn, nof_bytes, rlc_fi_field_text[header.fi]); RB_NAME,
header.sn,
nof_bytes,
rlc_fi_field_text[header.fi]);
if(!inside_rx_window(header.sn)) { if(!inside_rx_window(header.sn)) {
if(header.p) { if(header.p) {
@ -1295,7 +1340,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
// Write to rx window // Write to rx window
rlc_amd_rx_pdu_t pdu; rlc_amd_rx_pdu_t pdu;
pdu.buf = pool_allocate_blocking; pdu.buf = pool_allocate_blocking;
if (!pdu.buf) { if (pdu.buf == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG
log->console("Fatal Error: Couldn't allocate PDU in handle_data_pdu().\n"); log->console("Fatal Error: Couldn't allocate PDU in handle_data_pdu().\n");
exit(-1); exit(-1);
@ -1331,7 +1376,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
} }
// Check poll bit // Check poll bit
if(header.p) { if (header.p) {
log->info("%s Status packet requested through polling bit\n", RB_NAME); log->info("%s Status packet requested through polling bit\n", RB_NAME);
poll_received = true; poll_received = true;
@ -1348,7 +1393,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
reassemble_rx_sdus(); reassemble_rx_sdus();
// Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3) // Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3)
if (reordering_timer) { if (reordering_timer != NULL) {
if (reordering_timer->is_running()) { if (reordering_timer->is_running()) {
if(vr_x == vr_r || (!inside_rx_window(vr_x) && vr_x != vr_mr)) { if(vr_x == vr_r || (!inside_rx_window(vr_x) && vr_x != vr_mr)) {
reordering_timer->reset(); reordering_timer->reset();
@ -1357,7 +1402,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
if (not reordering_timer->is_running()) { if (not reordering_timer->is_running()) {
if(RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) { if(RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) {
reordering_timer->set(this, cfg.t_reordering); reordering_timer->reset();
reordering_timer->run(); reordering_timer->run();
vr_x = vr_h; vr_x = vr_h;
} }
@ -1388,7 +1433,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_b
rlc_amd_rx_pdu_t segment; rlc_amd_rx_pdu_t segment;
segment.buf = pool_allocate_blocking; segment.buf = pool_allocate_blocking;
if (!segment.buf) { if (segment.buf == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG
log->console("Fatal Error: Couldn't allocate PDU in handle_data_pdu_segment().\n"); log->console("Fatal Error: Couldn't allocate PDU in handle_data_pdu_segment().\n");
exit(-1); exit(-1);
@ -1429,14 +1474,13 @@ void rlc_am::rlc_am_rx::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_b
pdu.segments.push_back(segment); pdu.segments.push_back(segment);
rx_segments[header.sn] = pdu; rx_segments[header.sn] = pdu;
// Update vr_h // Update vr_h
if(RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_h)) if (RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_h)) {
vr_h = (header.sn + 1)%MOD; vr_h = (header.sn + 1) % MOD;
}
// Check poll bit // Check poll bit
if(header.p) if (header.p) {
{
log->info("%s Status packet requested through polling bit\n", RB_NAME); log->info("%s Status packet requested through polling bit\n", RB_NAME);
poll_received = true; poll_received = true;
@ -1459,9 +1503,9 @@ void rlc_am::rlc_am_rx::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_b
void rlc_am::rlc_am_rx::reassemble_rx_sdus() void rlc_am::rlc_am_rx::reassemble_rx_sdus()
{ {
uint32_t len = 0; uint32_t len = 0;
if(!rx_sdu) { if (rx_sdu == NULL) {
rx_sdu = pool_allocate_blocking; rx_sdu = pool_allocate_blocking;
if (!rx_sdu) { if (rx_sdu == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG
log->console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (1)\n"); log->console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (1)\n");
exit(-1); exit(-1);
@ -1495,7 +1539,7 @@ void rlc_am::rlc_am_rx::reassemble_rx_sdus()
parent->pdcp->write_pdu(parent->lcid, rx_sdu); parent->pdcp->write_pdu(parent->lcid, rx_sdu);
rx_sdu = pool_allocate_blocking; rx_sdu = pool_allocate_blocking;
if (!rx_sdu) { if (rx_sdu == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG
log->console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (2)\n"); log->console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (2)\n");
exit(-1); exit(-1);
@ -1528,12 +1572,12 @@ void rlc_am::rlc_am_rx::reassemble_rx_sdus()
rx_window.erase(vr_r); rx_window.erase(vr_r);
} }
if(rlc_am_end_aligned(rx_window[vr_r].header.fi)) { if (rlc_am_end_aligned(rx_window[vr_r].header.fi)) {
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes); log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes);
rx_sdu->set_timestamp(); rx_sdu->set_timestamp();
parent->pdcp->write_pdu(parent->lcid, rx_sdu); parent->pdcp->write_pdu(parent->lcid, rx_sdu);
rx_sdu = pool_allocate_blocking; rx_sdu = pool_allocate_blocking;
if (!rx_sdu) { if (rx_sdu == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG
log->console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (3)\n"); log->console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (3)\n");
exit(-1); exit(-1);
@ -1604,7 +1648,7 @@ void rlc_am::rlc_am_rx::write_pdu(uint8_t *payload, uint32_t nof_bytes)
void rlc_am::rlc_am_rx::timer_expired(uint32_t timeout_id) void rlc_am::rlc_am_rx::timer_expired(uint32_t timeout_id)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if (reordering_timer && reordering_timer_id == timeout_id) { if (reordering_timer != NULL && reordering_timer_id == timeout_id) {
reordering_timer->reset(); reordering_timer->reset();
log->debug("%s reordering timeout expiry - updating vr_ms\n", RB_NAME); log->debug("%s reordering timeout expiry - updating vr_ms\n", RB_NAME);
@ -1621,7 +1665,7 @@ void rlc_am::rlc_am_rx::timer_expired(uint32_t timeout_id)
} }
if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_ms)) { if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_ms)) {
reordering_timer->set(this, cfg.t_reordering); reordering_timer->reset();
reordering_timer->run(); reordering_timer->run();
vr_x = vr_h; vr_x = vr_h;
} }
@ -1694,12 +1738,14 @@ bool rlc_am::rlc_am_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rl
uint32_t so = 0; uint32_t so = 0;
std::list<rlc_amd_rx_pdu_t>::iterator it, tmpit; std::list<rlc_amd_rx_pdu_t>::iterator it, tmpit;
for(it = pdu->segments.begin(); it != pdu->segments.end(); it++) { for(it = pdu->segments.begin(); it != pdu->segments.end(); it++) {
if(so != it->header.so) if (so != it->header.so) {
return false; return false;
}
so += it->buf->N_bytes; so += it->buf->N_bytes;
} }
if(!pdu->segments.back().header.lsf) if (!pdu->segments.back().header.lsf) {
return false; return false;
}
// We have all segments of the PDU - reconstruct and handle // We have all segments of the PDU - reconstruct and handle
rlc_amd_pdu_header_t header; rlc_amd_pdu_header_t header;
@ -1745,7 +1791,7 @@ bool rlc_am::rlc_am_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rl
// Copy data // Copy data
byte_buffer_t *full_pdu = pool_allocate_blocking; byte_buffer_t *full_pdu = pool_allocate_blocking;
if (!full_pdu) { if (full_pdu == NULL) {
#ifdef RLC_AM_BUFFER_DEBUG #ifdef RLC_AM_BUFFER_DEBUG
log->console("Fatal Error: Could not allocate PDU in add_segment_and_check()\n"); log->console("Fatal Error: Could not allocate PDU in add_segment_and_check()\n");
exit(-1); exit(-1);
@ -1801,14 +1847,14 @@ void rlc_am_read_data_pdu_header(uint8_t **payload, uint32_t *nof_bytes, rlc_amd
uint8_t ext; uint8_t ext;
uint8_t *ptr = *payload; uint8_t *ptr = *payload;
header->dc = (rlc_dc_field_t)((*ptr >> 7) & 0x01); header->dc = static_cast<rlc_dc_field_t>((*ptr >> 7) & 0x01);
if(RLC_DC_FIELD_DATA_PDU == header->dc) if(RLC_DC_FIELD_DATA_PDU == header->dc)
{ {
// Fixed part // Fixed part
header->rf = ((*ptr >> 6) & 0x01); header->rf = ((*ptr >> 6) & 0x01);
header->p = ((*ptr >> 5) & 0x01); header->p = ((*ptr >> 5) & 0x01);
header->fi = (rlc_fi_field_t)((*ptr >> 3) & 0x03); header->fi = static_cast<rlc_fi_field_t>((*ptr >> 3) & 0x03);
ext = ((*ptr >> 2) & 0x01); ext = ((*ptr >> 2) & 0x01);
header->sn = (*ptr & 0x03) << 8; // 2 bits SN header->sn = (*ptr & 0x03) << 8; // 2 bits SN
ptr++; ptr++;
@ -1848,8 +1894,9 @@ void rlc_am_read_data_pdu_header(uint8_t **payload, uint32_t *nof_bytes, rlc_amd
} }
// Account for padding if N_li is odd // Account for padding if N_li is odd
if(header->N_li%2 == 1) if (header->N_li%2 == 1) {
ptr++; ptr++;
}
*nof_bytes -= ptr-*payload; *nof_bytes -= ptr-*payload;
*payload = ptr; *payload = ptr;
@ -1885,7 +1932,7 @@ void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t *header, uint8_t **payloa
ptr++; ptr++;
// Segment part // Segment part
if(header->rf) if (header->rf)
{ {
*ptr = (header->lsf & 0x01) << 7; *ptr = (header->lsf & 0x01) << 7;
*ptr |= (header->so & 0x7F00) >> 8; // 7 bits of SO *ptr |= (header->so & 0x7F00) >> 8; // 7 bits of SO
@ -1916,8 +1963,9 @@ void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t *header, uint8_t **payloa
} }
} }
// Pad if N_li is odd // Pad if N_li is odd
if(header->N_li%2 == 1) if (header->N_li%2 == 1) {
ptr++; ptr++;
}
*payload = ptr; *payload = ptr;
} }
@ -1937,7 +1985,7 @@ void rlc_am_read_status_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_status_pdu
srslte_bit_unpack_vector(payload, tmp.msg, nof_bytes*8); srslte_bit_unpack_vector(payload, tmp.msg, nof_bytes*8);
tmp.N_bits = nof_bytes*8; tmp.N_bits = nof_bytes*8;
rlc_dc_field_t dc = (rlc_dc_field_t)srslte_bit_pack(&ptr, 1); rlc_dc_field_t dc = static_cast<rlc_dc_field_t>(srslte_bit_pack(&ptr, 1));
if(RLC_DC_FIELD_CONTROL_PDU == dc) if(RLC_DC_FIELD_CONTROL_PDU == dc)
{ {
@ -2009,7 +2057,9 @@ int rlc_am_write_status_pdu(rlc_status_pdu_t *status, uint8_t *payload)
uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t *header) uint32_t rlc_am_packed_length(rlc_amd_pdu_header_t *header)
{ {
uint32_t len = 2; // Fixed part is 2 bytes uint32_t len = 2; // Fixed part is 2 bytes
if(header->rf) len += 2; // Segment header is 2 bytes if (header->rf) {
len += 2; // Segment header is 2 bytes
}
len += header->N_li * 1.5 + 0.5; // Extension part - integer rounding up len += header->N_li * 1.5 + 0.5; // Extension part - integer rounding up
return len; return len;
} }
@ -2086,4 +2136,4 @@ bool rlc_am_not_start_aligned(const uint8_t fi)
return (fi == RLC_FI_FIELD_NOT_START_ALIGNED || fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED); return (fi == RLC_FI_FIELD_NOT_START_ALIGNED || fi == RLC_FI_FIELD_NOT_START_OR_END_ALIGNED);
} }
} // namespace srsue } // namespace srslte

@ -25,7 +25,7 @@
*/ */
#include <iostream> #include <iostream>
#include <stdlib.h> #include <cstdlib>
#include <pthread.h> #include <pthread.h>
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
#include "srslte/common/logger_stdout.h" #include "srslte/common/logger_stdout.h"
@ -34,7 +34,7 @@
#include "srslte/upper/rlc.h" #include "srslte/upper/rlc.h"
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <boost/program_options/parsers.hpp> #include <boost/program_options/parsers.hpp>
#include <assert.h> #include <cassert>
#include <srslte/upper/rlc_interface.h> #include <srslte/upper/rlc_interface.h>
#define SDU_SIZE (1500) #define SDU_SIZE (1500)

Loading…
Cancel
Save