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
This commit is contained in:
Andre Puschmann 2018-11-30 12:26:37 +01:00
parent 946a50adf0
commit c3441046c9
16 changed files with 76 additions and 112 deletions

View File

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

View File

@ -67,8 +67,8 @@ public:
bool rb_is_um(uint32_t lcid);
// MAC interface
uint32_t get_buffer_state(uint32_t lcid);
uint32_t get_total_buffer_state(uint32_t lcid);
bool has_data(const uint32_t lcid);
uint32_t get_buffer_state(const 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_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes);

View File

@ -89,8 +89,8 @@ public:
void write_sdu(byte_buffer_t *sdu, bool blocking = true);
// MAC interface
bool has_data();
uint32_t get_buffer_state();
uint32_t get_total_buffer_state();
int read_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);
int read_pdu(uint8_t *payload, uint32_t nof_bytes);
bool has_data();
uint32_t get_buffer_state();
uint32_t get_total_buffer_state();
uint32_t get_num_tx_bytes();
void reset_metrics();

View File

@ -169,8 +169,8 @@ public:
virtual void write_sdu(byte_buffer_t *sdu, bool blocking) = 0;
// MAC interface
virtual bool has_data() = 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 void write_pdu(uint8_t *payload, uint32_t nof_bytes) = 0;
};

View File

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

View File

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

View File

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

View File

@ -256,6 +256,19 @@ bool rlc::rb_is_um(uint32_t lcid)
/*******************************************************************************
MAC interface
*******************************************************************************/
bool rlc::has_data(uint32_t lcid)
{
bool has_data = false;
pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) {
has_data = rlc_array.at(lcid)->has_data();
}
pthread_rwlock_unlock(&rwlock);
return has_data;
}
uint32_t rlc::get_buffer_state(uint32_t lcid)
{
uint32_t ret = 0;
@ -269,26 +282,13 @@ uint32_t rlc::get_buffer_state(uint32_t lcid)
return ret;
}
uint32_t rlc::get_total_buffer_state(uint32_t lcid)
{
uint32_t ret = 0;
pthread_rwlock_rdlock(&rwlock);
if (valid_lcid(lcid)) {
ret = rlc_array.at(lcid)->get_total_buffer_state();
}
pthread_rwlock_unlock(&rwlock);
return ret;
}
uint32_t rlc::get_total_mch_buffer_state(uint32_t lcid)
{
uint32_t ret = 0;
pthread_rwlock_rdlock(&rwlock);
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);

View File

@ -152,16 +152,16 @@ void rlc_am::write_sdu(byte_buffer_t *sdu, bool blocking)
* MAC interface
***************************************************************************/
bool rlc_am::has_data()
{
return tx.has_data();
}
uint32_t rlc_am::get_buffer_state()
{
return tx.get_buffer_state();
}
uint32_t rlc_am::get_total_buffer_state()
{
return tx.get_total_buffer_state();
}
int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes)
{
return tx.read_pdu(payload, nof_bytes);
@ -314,63 +314,16 @@ bool rlc_am::rlc_am_tx::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);
uint32_t n_bytes = 0;
uint32_t n_sdus = 0;
// 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;
return (((do_status() && not status_prohibited)) || // 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
}
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);
uint32_t n_bytes = 0;
@ -385,11 +338,11 @@ uint32_t rlc_am::rlc_am_tx::get_total_buffer_state()
// 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);
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)) {
int req_bytes = required_buffer_size(retx);
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();
} else {
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;
}
// Room needed for fixed header?
if (n_bytes > 0) {
// Room needed for fixed header of data PDUs
if (n_bytes > 0 && n_sdus > 0) {
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);

View File

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

View File

@ -162,14 +162,14 @@ void rlc_um::write_sdu(byte_buffer_t *sdu, bool blocking)
* 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)
@ -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
uint32_t n_sdus = tx_sdu_queue.size();

View File

@ -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(rnti != SRSLTE_MRNTI) {
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 {
ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes);
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
// 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;
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);
@ -191,7 +191,7 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu)
if (users.count(rnti)) {
if(rnti != SRSLTE_MRNTI){
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 {
users[rnti].rlc->write_sdu_mch(lcid, sdu);
tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid);

View File

@ -73,7 +73,7 @@ void mux::reset()
bool mux::is_pending_any_sdu()
{
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;
}
}
@ -81,7 +81,7 @@ bool mux::is_pending_any_sdu()
}
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)

View File

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

View File

@ -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)
const uint32_t RB_ID_SRB1 = 1;
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);
}
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);
detach_sent = false;
}

View File

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