simplify RLC buffer status query procedures

- add a simple and low-overhead has_data() method to check whether
  an RLC entity has data to transmit or not
- use this method for all calls that are actually not interested
  in the amount of data to send
- use the more expensive get_buffer_state() for all cases where
  the actual size of the buffer is of importance
master
Andre Puschmann 6 years ago
parent 946a50adf0
commit c3441046c9

@ -300,11 +300,12 @@ public:
class rlc_interface_mac : public srslte::read_pdu_interface class rlc_interface_mac : public srslte::read_pdu_interface
{ {
public: public:
/* MAC calls RLC to get buffer state for a logical channel. /* MAC calls has_data() to query whether a logical channel has data to transmit (without
* This function should return quickly. */ * knowing how much. This function should return quickly. */
virtual uint32_t get_buffer_state(uint32_t lcid) = 0; virtual bool has_data(const uint32_t lcid) = 0;
virtual uint32_t get_total_buffer_state(uint32_t lcid) = 0;
/* MAC calls RLC to get the buffer state for a logical channel. */
virtual uint32_t get_buffer_state(const uint32_t lcid) = 0;
const static int MAX_PDU_SEGMENTS = 20; const static int MAX_PDU_SEGMENTS = 20;

@ -67,8 +67,8 @@ public:
bool rb_is_um(uint32_t lcid); bool rb_is_um(uint32_t lcid);
// MAC interface // MAC interface
uint32_t get_buffer_state(uint32_t lcid); bool has_data(const uint32_t lcid);
uint32_t get_total_buffer_state(uint32_t lcid); uint32_t get_buffer_state(const uint32_t lcid);
uint32_t get_total_mch_buffer_state(uint32_t lcid); uint32_t get_total_mch_buffer_state(uint32_t lcid);
int read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes); int read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes);
int read_pdu_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes); int read_pdu_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes);

@ -89,8 +89,8 @@ public:
void write_sdu(byte_buffer_t *sdu, bool blocking = true); void write_sdu(byte_buffer_t *sdu, bool blocking = true);
// MAC interface // MAC interface
bool has_data();
uint32_t get_buffer_state(); uint32_t get_buffer_state();
uint32_t get_total_buffer_state();
int read_pdu(uint8_t *payload, uint32_t nof_bytes); int read_pdu(uint8_t *payload, uint32_t nof_bytes);
void write_pdu(uint8_t *payload, uint32_t nof_bytes); void write_pdu(uint8_t *payload, uint32_t nof_bytes);
@ -117,8 +117,8 @@ private:
void write_sdu(byte_buffer_t *sdu, bool blocking); void write_sdu(byte_buffer_t *sdu, bool blocking);
int read_pdu(uint8_t *payload, uint32_t nof_bytes); int read_pdu(uint8_t *payload, uint32_t nof_bytes);
bool has_data();
uint32_t get_buffer_state(); uint32_t get_buffer_state();
uint32_t get_total_buffer_state();
uint32_t get_num_tx_bytes(); uint32_t get_num_tx_bytes();
void reset_metrics(); void reset_metrics();

@ -169,8 +169,8 @@ public:
virtual void write_sdu(byte_buffer_t *sdu, bool blocking) = 0; virtual void write_sdu(byte_buffer_t *sdu, bool blocking) = 0;
// MAC interface // MAC interface
virtual bool has_data() = 0;
virtual uint32_t get_buffer_state() = 0; virtual uint32_t get_buffer_state() = 0;
virtual uint32_t get_total_buffer_state() = 0;
virtual int read_pdu(uint8_t *payload, uint32_t nof_bytes) = 0; virtual int read_pdu(uint8_t *payload, uint32_t nof_bytes) = 0;
virtual void write_pdu(uint8_t *payload, uint32_t nof_bytes) = 0; virtual void write_pdu(uint8_t *payload, uint32_t nof_bytes) = 0;
}; };

@ -62,8 +62,8 @@ public:
void write_sdu(byte_buffer_t *sdu, bool blocking); void write_sdu(byte_buffer_t *sdu, bool blocking);
// MAC interface // MAC interface
bool has_data();
uint32_t get_buffer_state(); uint32_t get_buffer_state();
uint32_t get_total_buffer_state();
int read_pdu(uint8_t *payload, uint32_t nof_bytes); int read_pdu(uint8_t *payload, uint32_t nof_bytes);
void write_pdu(uint8_t *payload, uint32_t nof_bytes); void write_pdu(uint8_t *payload, uint32_t nof_bytes);

@ -110,8 +110,11 @@ public:
unread_bytes = 0; unread_bytes = 0;
} }
bool is_empty() {
return queue.empty();
}
private: private:
bool is_empty() { return queue.empty(); }
block_queue<byte_buffer_t*> queue; block_queue<byte_buffer_t*> queue;
uint32_t unread_bytes; uint32_t unread_bytes;

@ -68,8 +68,8 @@ public:
void write_sdu(byte_buffer_t *sdu, bool blocking = true); void write_sdu(byte_buffer_t *sdu, bool blocking = true);
// MAC interface // MAC interface
bool has_data();
uint32_t get_buffer_state(); uint32_t get_buffer_state();
uint32_t get_total_buffer_state();
int read_pdu(uint8_t *payload, uint32_t nof_bytes); int read_pdu(uint8_t *payload, uint32_t nof_bytes);
void write_pdu(uint8_t *payload, uint32_t nof_bytes); void write_pdu(uint8_t *payload, uint32_t nof_bytes);
int get_increment_sequence_num(); int get_increment_sequence_num();
@ -96,7 +96,8 @@ private:
void try_write_sdu(byte_buffer_t *sdu); void try_write_sdu(byte_buffer_t *sdu);
uint32_t get_num_tx_bytes(); uint32_t get_num_tx_bytes();
void reset_metrics(); void reset_metrics();
uint32_t get_buffer_size_bytes(); bool has_data();
uint32_t get_buffer_state();
private: private:
byte_buffer_pool *pool; byte_buffer_pool *pool;

@ -256,26 +256,26 @@ bool rlc::rb_is_um(uint32_t lcid)
/******************************************************************************* /*******************************************************************************
MAC interface MAC interface
*******************************************************************************/ *******************************************************************************/
uint32_t rlc::get_buffer_state(uint32_t lcid) bool rlc::has_data(uint32_t lcid)
{ {
uint32_t ret = 0; bool has_data = false;
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) { if (valid_lcid(lcid)) {
ret = rlc_array.at(lcid)->get_buffer_state(); has_data = rlc_array.at(lcid)->has_data();
} }
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
return ret; return has_data;
} }
uint32_t rlc::get_total_buffer_state(uint32_t lcid) uint32_t rlc::get_buffer_state(uint32_t lcid)
{ {
uint32_t ret = 0; uint32_t ret = 0;
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) { if (valid_lcid(lcid)) {
ret = rlc_array.at(lcid)->get_total_buffer_state(); ret = rlc_array.at(lcid)->get_buffer_state();
} }
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);
@ -288,7 +288,7 @@ uint32_t rlc::get_total_mch_buffer_state(uint32_t lcid)
pthread_rwlock_rdlock(&rwlock); pthread_rwlock_rdlock(&rwlock);
if (valid_lcid_mrb(lcid)) { if (valid_lcid_mrb(lcid)) {
ret = rlc_array_mrb.at(lcid)->get_total_buffer_state(); ret = rlc_array_mrb.at(lcid)->get_buffer_state();
} }
pthread_rwlock_unlock(&rwlock); pthread_rwlock_unlock(&rwlock);

@ -152,14 +152,14 @@ void rlc_am::write_sdu(byte_buffer_t *sdu, bool blocking)
* MAC interface * MAC interface
***************************************************************************/ ***************************************************************************/
uint32_t rlc_am::get_buffer_state() bool rlc_am::has_data()
{ {
return tx.get_buffer_state(); return tx.has_data();
} }
uint32_t rlc_am::get_total_buffer_state() uint32_t rlc_am::get_buffer_state()
{ {
return tx.get_total_buffer_state(); return tx.get_buffer_state();
} }
int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes)
@ -314,63 +314,16 @@ bool rlc_am::rlc_am_tx::do_status()
return parent->rx.get_do_status(); return parent->rx.get_do_status();
} }
uint32_t rlc_am::rlc_am_tx::get_buffer_state() // Function is supposed to return as fast as possible
bool rlc_am::rlc_am_tx::has_data()
{ {
pthread_mutex_lock(&mutex); return (((do_status() && not status_prohibited)) || // if we have a status PDU to transmit
uint32_t n_bytes = 0; (not retx_queue.empty()) || // if we have a retransmission
uint32_t n_sdus = 0; (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
// Bytes needed for status report
if (do_status() && not status_prohibited) {
n_bytes = parent->rx.get_status_pdu_length();
log->debug("%s Buffer state - status report: %d bytes\n", RB_NAME, n_bytes);
goto unlock_and_return;
}
// Bytes needed for retx
if (not retx_queue.empty()) {
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);
if(tx_window.end() != tx_window.find(retx.sn)) {
int req_bytes = required_buffer_size(retx);
if (req_bytes < 0) {
log->error("In get_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn);
retx_queue.pop_front();
goto unlock_and_return;
}
n_bytes = static_cast<uint32_t>(req_bytes);
log->debug("Buffer state - retx: %d bytes\n", n_bytes);
goto unlock_and_return;
}
}
// Bytes needed for tx SDUs
if (tx_window.size() < 1024) {
n_sdus = tx_sdu_queue.size();
n_bytes = tx_sdu_queue.size_bytes();
if (tx_sdu != NULL) {
n_sdus++;
n_bytes += tx_sdu->N_bytes;
}
}
// Room needed for header extensions? (integer rounding)
if (n_sdus > 1) {
n_bytes += ((n_sdus-1)*1.5)+0.5;
}
// Room needed for fixed header?
if (n_bytes > 0) {
n_bytes += 3;
log->debug("Buffer state - tx SDUs: %d bytes\n", n_bytes);
}
unlock_and_return:
pthread_mutex_unlock(&mutex);
return n_bytes;
} }
uint32_t rlc_am::rlc_am_tx::get_total_buffer_state() uint32_t rlc_am::rlc_am_tx::get_buffer_state()
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
uint32_t n_bytes = 0; uint32_t n_bytes = 0;
@ -385,11 +338,11 @@ uint32_t rlc_am::rlc_am_tx::get_total_buffer_state()
// Bytes needed for retx // Bytes needed for retx
if(not retx_queue.empty()) { 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("%s Buffer state - retx - SN: %d, Segment: %s, %d:%d\n", RB_NAME, 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)) {
int req_bytes = required_buffer_size(retx); int req_bytes = required_buffer_size(retx);
if (req_bytes < 0) { if (req_bytes < 0) {
log->error("In get_total_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn); log->error("In get_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn);
retx_queue.pop_front(); retx_queue.pop_front();
} else { } else {
n_bytes += req_bytes; n_bytes += req_bytes;
@ -413,10 +366,10 @@ uint32_t rlc_am::rlc_am_tx::get_total_buffer_state()
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 of data PDUs
if (n_bytes > 0) { if (n_bytes > 0 && n_sdus > 0) {
n_bytes += 3; n_bytes += 3;
log->debug("Buffer state - tx SDUs: %d bytes\n", n_bytes); log->debug("%s Total buffer state - %d SDUs (%d B)\n", RB_NAME, n_sdus, n_bytes);
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);

@ -123,14 +123,14 @@ void rlc_tm::write_sdu(byte_buffer_t *sdu, bool blocking)
} }
// MAC interface // MAC interface
uint32_t rlc_tm::get_buffer_state() bool rlc_tm::has_data()
{ {
return ul_queue.size_bytes(); return not ul_queue.is_empty();
} }
uint32_t rlc_tm::get_total_buffer_state() uint32_t rlc_tm::get_buffer_state()
{ {
return get_buffer_state(); return ul_queue.size_bytes();
} }
uint32_t rlc_tm::get_num_tx_bytes() uint32_t rlc_tm::get_num_tx_bytes()

@ -162,14 +162,14 @@ void rlc_um::write_sdu(byte_buffer_t *sdu, bool blocking)
* MAC interface * MAC interface
***************************************************************************/ ***************************************************************************/
uint32_t rlc_um::get_buffer_state() bool rlc_um::has_data()
{ {
return tx.get_buffer_size_bytes(); return tx.has_data();
} }
uint32_t rlc_um::get_total_buffer_state() uint32_t rlc_um::get_buffer_state()
{ {
return get_buffer_state(); return tx.get_buffer_state();
} }
int rlc_um::read_pdu(uint8_t *payload, uint32_t nof_bytes) int rlc_um::read_pdu(uint8_t *payload, uint32_t nof_bytes)
@ -313,7 +313,13 @@ void rlc_um::rlc_um_tx::reset_metrics()
} }
uint32_t rlc_um::rlc_um_tx::get_buffer_size_bytes() bool rlc_um::rlc_um_tx::has_data()
{
return (tx_sdu != NULL || !tx_sdu_queue.is_empty());
}
uint32_t rlc_um::rlc_um_tx::get_buffer_state()
{ {
// Bytes needed for tx SDUs // Bytes needed for tx SDUs
uint32_t n_sdus = tx_sdu_queue.size(); uint32_t n_sdus = tx_sdu_queue.size();

@ -142,7 +142,7 @@ int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_b
if(users.count(rnti)) { if(users.count(rnti)) {
if(rnti != SRSLTE_MRNTI) { if(rnti != SRSLTE_MRNTI) {
ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes); ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes);
tx_queue = users[rnti].rlc->get_total_buffer_state(lcid); tx_queue = users[rnti].rlc->get_buffer_state(lcid);
} else { } else {
ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes); ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes);
tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid); tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid);
@ -168,7 +168,7 @@ void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof
// In the eNodeB, there is no polling for buffer state from the scheduler, thus // In the eNodeB, there is no polling for buffer state from the scheduler, thus
// communicate buffer state every time a new PDU is written // communicate buffer state every time a new PDU is written
uint32_t tx_queue = users[rnti].rlc->get_total_buffer_state(lcid); uint32_t tx_queue = users[rnti].rlc->get_buffer_state(lcid);
uint32_t retx_queue = 0; uint32_t retx_queue = 0;
log_h->debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue); log_h->debug("Buffer state PDCP: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue);
mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue); mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue);
@ -191,7 +191,7 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
if (users.count(rnti)) { if (users.count(rnti)) {
if(rnti != SRSLTE_MRNTI){ if(rnti != SRSLTE_MRNTI){
users[rnti].rlc->write_sdu(lcid, sdu, false); users[rnti].rlc->write_sdu(lcid, sdu, false);
tx_queue = users[rnti].rlc->get_total_buffer_state(lcid); tx_queue = users[rnti].rlc->get_buffer_state(lcid);
}else { }else {
users[rnti].rlc->write_sdu_mch(lcid, sdu); users[rnti].rlc->write_sdu_mch(lcid, sdu);
tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid); tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid);

@ -73,7 +73,7 @@ void mux::reset()
bool mux::is_pending_any_sdu() bool mux::is_pending_any_sdu()
{ {
for (uint32_t i=0;i<lch.size();i++) { for (uint32_t i=0;i<lch.size();i++) {
if (rlc->get_buffer_state(lch[i].id)) { if (rlc->has_data(lch[i].id)) {
return true; return true;
} }
} }
@ -81,7 +81,7 @@ bool mux::is_pending_any_sdu()
} }
bool mux::is_pending_sdu(uint32_t lch_id) { bool mux::is_pending_sdu(uint32_t lch_id) {
return rlc->get_buffer_state(lch_id)>0; return rlc->has_data(lch_id);
} }
int mux::find_lchid(uint32_t lcid) int mux::find_lchid(uint32_t lcid)

@ -104,10 +104,10 @@ bool bsr_proc::check_highest_channel() {
for (int i=0;i<MAX_LCID && pending_data_lcid == -1;i++) { for (int i=0;i<MAX_LCID && pending_data_lcid == -1;i++) {
if (lcg[i] >= 0) { if (lcg[i] >= 0) {
if (rlc->get_buffer_state(i) > 0) { if (rlc->has_data(i)) {
pending_data_lcid = i; pending_data_lcid = i;
for (int j=0;j<MAX_LCID;j++) { for (int j=0;j<MAX_LCID;j++) {
if (rlc->get_buffer_state(j) > 0) { if (rlc->has_data(j)) {
if (priorities[j] > priorities[i]) { if (priorities[j] > priorities[i]) {
pending_data_lcid = -1; pending_data_lcid = -1;
} }
@ -148,7 +148,7 @@ bool bsr_proc::check_single_channel() {
for (int i=0;i<MAX_LCID;i++) { for (int i=0;i<MAX_LCID;i++) {
if (lcg[i] >= 0) { if (lcg[i] >= 0) {
if (rlc->get_buffer_state(i) > 0) { if (rlc->has_data(i)) {
pending_data_lcid = i; pending_data_lcid = i;
nof_nonzero_lcid++; nof_nonzero_lcid++;
} }

@ -312,11 +312,11 @@ bool ue::switch_off() {
// wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2) // wait for max. 5s for it to be sent (according to TS 24.301 Sec 25.5.2.2)
const uint32_t RB_ID_SRB1 = 1; const uint32_t RB_ID_SRB1 = 1;
int cnt = 0, timeout = 5; int cnt = 0, timeout = 5;
while (rlc.get_buffer_state(RB_ID_SRB1) && ++cnt <= timeout) { while (rlc.has_data(RB_ID_SRB1) && ++cnt <= timeout) {
sleep(1); sleep(1);
} }
bool detach_sent = true; bool detach_sent = true;
if (rlc.get_buffer_state(RB_ID_SRB1)) { if (rlc.has_data(RB_ID_SRB1)) {
nas_log.warning("Detach couldn't be sent after %ds.\n", timeout); nas_log.warning("Detach couldn't be sent after %ds.\n", timeout);
detach_sent = false; detach_sent = false;
} }

@ -282,7 +282,7 @@ public:
sib2_period = 0; sib2_period = 0;
send_ack = 0; send_ack = 0;
} }
uint32_t get_total_buffer_state(uint32_t lcid) { bool has_data(uint32_t lcid) {
return get_buffer_state(lcid); return get_buffer_state(lcid);
} }
uint32_t get_buffer_state(uint32_t lcid) { uint32_t get_buffer_state(uint32_t lcid) {

Loading…
Cancel
Save