Add callback to RLC to indicate BSR for TX and reTX queues (used in ENB) (#1361)

master
Ismael Gomez 5 years ago committed by GitHub
parent 860174a819
commit a1f0f8de35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -46,6 +46,11 @@ public:
srsue::rrc_interface_rlc* rrc_,
srslte::timer_handler* timers_,
uint32_t lcid_);
void init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srslte::timer_handler* timers_,
uint32_t lcid_,
bsr_callback_t bsr_callback_);
void stop();
void get_metrics(rlc_metrics_t& m);
@ -101,11 +106,16 @@ private:
uint32_t default_lcid = 0;
bsr_callback_t bsr_callback = nullptr;
// Timer needed for metrics calculation
struct timeval metrics_time[3] = {};
bool valid_lcid(uint32_t lcid);
bool valid_lcid_mrb(uint32_t lcid);
void update_bsr(uint32_t lcid);
void update_bsr_mch(uint32_t lcid);
};
} // namespace srslte

@ -91,6 +91,8 @@ public:
rlc_bearer_metrics_t get_metrics();
void reset_metrics();
void set_bsr_callback(bsr_callback_t callback);
private:
// Transmitter sub-class
class rlc_am_lte_tx : public timer_callback
@ -120,6 +122,8 @@ private:
// Interface for Rx subclass
void handle_control_pdu(uint8_t* payload, uint32_t nof_bytes);
void set_bsr_callback(bsr_callback_t callback);
private:
int build_status_pdu(uint8_t* payload, uint32_t nof_bytes);
int build_retx_pdu(uint8_t* payload, uint32_t nof_bytes);
@ -178,6 +182,9 @@ private:
srslte::timer_handler::unique_timer poll_retx_timer;
srslte::timer_handler::unique_timer status_prohibit_timer;
// Callback function for buffer status report
bsr_callback_t bsr_callback;
// Tx windows
std::map<uint32_t, rlc_amd_tx_pdu_t> tx_window;
std::deque<rlc_amd_retx_t> retx_queue;

@ -195,6 +195,8 @@ typedef struct {
rlc_status_nack_t nacks[RLC_AM_WINDOW_SIZE];
} rlc_am_nr_status_pdu_t;
typedef std::function<void(uint32_t, uint32_t, uint32_t)> bsr_callback_t;
/****************************************************************************
* RLC Common interface
* Common interface for all RLC entities
@ -276,6 +278,8 @@ public:
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 set_bsr_callback(bsr_callback_t callback) = 0;
private:
bool suspended = false;

@ -62,6 +62,8 @@ public:
int read_pdu(uint8_t* payload, uint32_t nof_bytes) override;
void write_pdu(uint8_t* payload, uint32_t nof_bytes) override;
void set_bsr_callback(bsr_callback_t callback) override {}
private:
byte_buffer_pool* pool = nullptr;
srslte::log_ref log;

@ -66,6 +66,8 @@ public:
rlc_bearer_metrics_t get_metrics();
void reset_metrics();
void set_bsr_callback(bsr_callback_t callback) {}
protected:
// Transmitter sub-class base
class rlc_um_base_tx

@ -72,6 +72,16 @@ void rlc::init(srsue::pdcp_interface_rlc* pdcp_,
add_bearer(default_lcid, rlc_config_t());
}
void rlc::init(srsue::pdcp_interface_rlc* pdcp_,
srsue::rrc_interface_rlc* rrc_,
srslte::timer_handler* timers_,
uint32_t lcid_,
bsr_callback_t bsr_callback_)
{
init(pdcp_, rrc_, timers_, lcid_);
bsr_callback = bsr_callback_;
}
void rlc::reset_metrics()
{
for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) {
@ -140,7 +150,7 @@ void rlc::reestablish(uint32_t lcid)
rlc_log->info("Reestablishing LCID %d\n", lcid);
rlc_array.at(lcid)->reestablish();
} else {
rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid);
rlc_log->warning("RLC LCID %d doesn't exist.\n", lcid);
}
}
@ -185,6 +195,7 @@ void rlc::write_sdu(uint32_t lcid, unique_byte_buffer_t sdu, bool blocking)
if (valid_lcid(lcid)) {
rlc_array.at(lcid)->write_sdu_s(std::move(sdu), blocking);
update_bsr(lcid);
} else {
rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid);
}
@ -194,6 +205,7 @@ void rlc::write_sdu_mch(uint32_t lcid, unique_byte_buffer_t sdu)
{
if (valid_lcid_mrb(lcid)) {
rlc_array_mrb.at(lcid)->write_sdu(std::move(sdu), false); // write in non-blocking mode by default
update_bsr_mch(lcid);
} else {
rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid);
}
@ -216,6 +228,7 @@ void rlc::discard_sdu(uint32_t lcid, uint32_t discard_sn)
{
if (valid_lcid(lcid)) {
rlc_array.at(lcid)->discard_sdu(discard_sn);
update_bsr(lcid);
} else {
rlc_log->warning("RLC LCID %d doesn't exist. Ignoring discard SDU\n", lcid);
}
@ -281,6 +294,7 @@ int rlc::read_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
rwlock_read_guard lock(rwlock);
if (valid_lcid(lcid)) {
ret = rlc_array.at(lcid)->read_pdu(payload, nof_bytes);
update_bsr(lcid);
} else {
rlc_log->warning("LCID %d doesn't exist.\n", lcid);
}
@ -295,6 +309,7 @@ int rlc::read_pdu_mch(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
rwlock_read_guard lock(rwlock);
if (valid_lcid_mrb(lcid)) {
ret = rlc_array_mrb.at(lcid)->read_pdu(payload, nof_bytes);
update_bsr_mch(lcid);
} else {
rlc_log->warning("LCID %d doesn't exist.\n", lcid);
}
@ -306,6 +321,7 @@ void rlc::write_pdu(uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
{
if (valid_lcid(lcid)) {
rlc_array.at(lcid)->write_pdu_s(payload, nof_bytes);
update_bsr(lcid);
} else {
rlc_log->warning("LCID %d doesn't exist. Dropping PDU.\n", lcid);
}
@ -355,7 +371,7 @@ void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg)
{
rwlock_write_guard lock(rwlock);
rlc_common* rlc_entity = NULL;
rlc_common* rlc_entity = nullptr;
if (not valid_lcid(lcid)) {
if (cnfg.rat == srslte_rat_t::lte) {
@ -373,6 +389,9 @@ void rlc::add_bearer(uint32_t lcid, const rlc_config_t& cnfg)
rlc_log->error("Cannot add RLC entity - invalid mode\n");
return;
}
if (rlc_entity != nullptr) {
rlc_entity->set_bsr_callback(bsr_callback);
}
#ifdef HAVE_5GNR
} else if (cnfg.rat == srslte_rat_t::nr) {
switch (cnfg.rlc_mode) {
@ -570,4 +589,22 @@ bool rlc::valid_lcid_mrb(uint32_t lcid)
return true;
}
void rlc::update_bsr(uint32_t lcid)
{
if (bsr_callback) {
uint32_t tx_queue = get_buffer_state(lcid);
uint32_t retx_queue = 0; // todo: separate tx_queue and retx_queue
bsr_callback(lcid, tx_queue, retx_queue);
}
}
void rlc::update_bsr_mch(uint32_t lcid)
{
if (bsr_callback) {
uint32_t tx_queue = get_total_mch_buffer_state(lcid);
uint32_t retx_queue = 0; // todo: separate tx_queue and retx_queue
bsr_callback(lcid, tx_queue, retx_queue);
}
}
} // namespace srslte

@ -77,6 +77,11 @@ bool rlc_am_lte::configure(const rlc_config_t& cfg_)
return true;
}
void rlc_am_lte::set_bsr_callback(bsr_callback_t callback)
{
tx.set_bsr_callback(callback);
}
void rlc_am_lte::empty_queue()
{
// Drop all messages in TX SDU queue
@ -175,6 +180,11 @@ rlc_am_lte::rlc_am_lte_tx::~rlc_am_lte_tx()
pthread_mutex_destroy(&mutex);
}
void rlc_am_lte::rlc_am_lte_tx::set_bsr_callback(bsr_callback_t callback)
{
bsr_callback = callback;
}
bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
{
// TODO: add config checks
@ -434,6 +444,10 @@ void rlc_am_lte::rlc_am_lte_tx::timer_expired(uint32_t timeout_id)
}
}
pthread_mutex_unlock(&mutex);
if (bsr_callback) {
bsr_callback(parent->lcid, get_buffer_state(), 0);
}
}
void rlc_am_lte::rlc_am_lte_tx::retransmit_random_pdu()

@ -87,6 +87,8 @@ private:
srsenb::rlc* parent;
};
void update_bsr(uint32_t rnti, uint32_t lcid, uint32_t tx_queue, uint32_t retx_queue);
pthread_rwlock_t rwlock;
std::map<uint32_t, user_interface> users;

@ -57,7 +57,13 @@ void rlc::add_user(uint16_t rnti)
pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti) == 0) {
std::unique_ptr<srslte::rlc> obj(new srslte::rlc(log_h->get_service_name().c_str()));
obj->init(&users[rnti], &users[rnti], timers, RB_ID_SRB0);
obj->init(&users[rnti],
&users[rnti],
timers,
RB_ID_SRB0,
[rnti, this](uint32_t lcid, uint32_t tx_queue, uint32_t retx_queue) {
update_bsr(rnti, lcid, tx_queue, retx_queue);
});
users[rnti].rnti = rnti;
users[rnti].pdcp = pdcp;
users[rnti].rrc = rrc;
@ -154,6 +160,14 @@ bool rlc::resume_bearer(uint16_t rnti, uint32_t lcid)
return result;
}
// In the eNodeB, there is no polling for buffer state from the scheduler.
// This function is called by UE RLC instance every time the tx/retx buffers are updated
void rlc::update_bsr(uint32_t rnti, uint32_t lcid, uint32_t tx_queue, uint32_t retx_queue)
{
log_h->debug("Buffer state: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue);
mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue);
}
void rlc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size)
{
rrc->read_pdu_pcch(payload, buffer_size);
@ -162,23 +176,14 @@ void rlc::read_pdu_pcch(uint8_t* payload, uint32_t buffer_size)
int rlc::read_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof_bytes)
{
int ret;
uint32_t tx_queue;
pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti)) {
if (rnti != SRSLTE_MRNTI) {
ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes);
tx_queue = users[rnti].rlc->get_buffer_state(lcid);
ret = users[rnti].rlc->read_pdu(lcid, payload, nof_bytes);
} else {
ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes);
tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid);
ret = users[rnti].rlc->read_pdu_mch(lcid, payload, nof_bytes);
}
// In the eNodeB, there is no polling for buffer state from the scheduler, thus
// communicate buffer state every time a PDU is read
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);
} else {
ret = SRSLTE_ERROR;
}
@ -191,36 +196,19 @@ void rlc::write_pdu(uint16_t rnti, uint32_t lcid, uint8_t* payload, uint32_t nof
pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti)) {
users[rnti].rlc->write_pdu(lcid, payload, nof_bytes);
// 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_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);
}
pthread_rwlock_unlock(&rwlock);
}
void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::unique_byte_buffer_t sdu)
{
uint32_t tx_queue;
pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti)) {
if (rnti != SRSLTE_MRNTI) {
users[rnti].rlc->write_sdu(lcid, std::move(sdu), false);
tx_queue = users[rnti].rlc->get_buffer_state(lcid);
} else {
users[rnti].rlc->write_sdu_mch(lcid, std::move(sdu));
tx_queue = users[rnti].rlc->get_total_mch_buffer_state(lcid);
}
// In the eNodeB, there is no polling for buffer state from the scheduler, thus
// communicate buffer state every time a new SDU is written
uint32_t retx_queue = 0;
mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue);
log_h->info("Buffer state: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue);
}
pthread_rwlock_unlock(&rwlock);
}
@ -230,13 +218,6 @@ void rlc::discard_sdu(uint16_t rnti, uint32_t lcid, uint32_t discard_sn)
pthread_rwlock_rdlock(&rwlock);
if (users.count(rnti)) {
users[rnti].rlc->discard_sdu(lcid, discard_sn);
uint32_t tx_queue = users[rnti].rlc->get_buffer_state(lcid);
// In the eNodeB, there is no polling for buffer state from the scheduler, thus
// communicate buffer state every time a new SDU is discarded
uint32_t retx_queue = 0;
mac->rlc_buffer_state(rnti, lcid, tx_queue, retx_queue);
log_h->info("Buffer state: rnti=0x%x, lcid=%d, tx_queue=%d\n", rnti, lcid, tx_queue);
}
pthread_rwlock_unlock(&rwlock);
}

Loading…
Cancel
Save