mirror of https://github.com/PentHertz/srsLTE.git
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:
parent
946a50adf0
commit
c3441046c9
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue