Add RLC resume procedure

This commit is contained in:
Ismael Gomez 2019-06-04 17:29:02 +02:00 committed by Xavier Arteaga
parent 3f613d7183
commit ade720e032
10 changed files with 205 additions and 55 deletions

View File

@ -83,6 +83,7 @@ public:
void add_bearer_mrb(uint32_t lcid);
void del_bearer(uint32_t lcid);
void del_bearer_mrb(uint32_t lcid);
void resume_bearer(uint32_t lcid);
void change_lcid(uint32_t old_lcid, uint32_t new_lcid);
bool has_bearer(uint32_t lcid);

View File

@ -71,6 +71,7 @@ public:
srsue::pdcp_interface_rlc *pdcp_,
srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers_);
bool resume();
bool configure(srslte_rlc_config_t cfg_);
void reestablish();
void stop();
@ -292,7 +293,8 @@ private:
srsue::pdcp_interface_rlc *pdcp;
mac_interface_timers *mac_timers;
uint32_t lcid;
srslte_rlc_am_config_t cfg;
srslte_rlc_config_t cfg;
bool has_configuration;
std::string rb_name;
static const int poll_periodicity = 8; // After how many data PDUs a status PDU shall be requested

View File

@ -149,6 +149,7 @@ public:
srsue::rrc_interface_rlc *rrc_,
srslte::mac_interface_timers *mac_timers_) = 0;
virtual bool configure(srslte_rlc_config_t cnfg) = 0;
virtual bool resume() = 0;
virtual void stop() = 0;
virtual void reestablish() = 0;
virtual void empty_queue() = 0;

View File

@ -42,6 +42,7 @@ public:
srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers);
bool configure(srslte_rlc_config_t cnfg);
bool resume();
void stop();
void reestablish();
void empty_queue();

View File

@ -51,6 +51,7 @@ public:
srsue::rrc_interface_rlc *rrc_,
mac_interface_timers *mac_timers_);
bool configure(srslte_rlc_config_t cnfg);
bool resume();
void reestablish();
void stop();
void empty_queue();
@ -209,7 +210,8 @@ private:
srsue::rrc_interface_rlc *rrc;
srslte::log *log;
uint32_t lcid;
srslte_rlc_um_config_t cfg;
srslte_rlc_config_t cfg;
bool has_configuration;
std::string rb_name;
byte_buffer_pool *pool;

View File

@ -563,6 +563,26 @@ exit:
pthread_rwlock_unlock(&rwlock);
}
void rlc::resume_bearer(uint32_t lcid)
{
pthread_rwlock_wrlock(&rwlock);
if (not valid_lcid(lcid)) {
// Need to call init again because timers have been destroyed
rlc_array.at(lcid)->init(rlc_log, lcid, pdcp, rrc, mac_timers);
if (rlc_array.at(lcid)->resume()) {
rlc_log->info("Resumed radio bearer %s\n", rrc->get_rb_name(lcid).c_str());
} else {
rlc_log->error("Error resuming RLC entity\n.");
}
} else {
rlc_log->error("Resuming bearer: bearer %s not configured.\n", rrc->get_rb_name(lcid).c_str());
}
pthread_rwlock_unlock(&rwlock);
}
bool rlc::has_bearer(uint32_t lcid)
{

View File

@ -32,7 +32,17 @@
namespace srslte {
rlc_am::rlc_am() : tx(this), rx(this), log(NULL), rrc(NULL), pdcp(NULL), mac_timers(NULL), lcid(0), rb_name(""), cfg()
rlc_am::rlc_am() :
tx(this),
rx(this),
log(NULL),
rrc(NULL),
pdcp(NULL),
mac_timers(NULL),
lcid(0),
rb_name(""),
cfg(),
has_configuration(false)
{
}
@ -56,28 +66,47 @@ void rlc_am::init(srslte::log *log_,
tx.init();
}
bool rlc_am::resume()
{
if (not has_configuration) {
log->error("Error resuming bearer: no previous configuration found\n");
return false;
}
if (not rx.configure(cfg.am)) {
return false;
}
if (not tx.configure(cfg)) {
return false;
}
return true;
}
bool rlc_am::configure(srslte_rlc_config_t cfg_)
{
// determine bearer name and configure Rx/Tx objects
rb_name = rrc->get_rb_name(lcid);
if (not rx.configure(cfg_.am)) {
return false;
}
if (not tx.configure(cfg_)) {
return false;
}
// store config
cfg = cfg_.am;
cfg = cfg_;
has_configuration = true;
log->warning("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, "
"t_reordering=%d, t_status_prohibit=%d\n",
rb_name.c_str(), cfg.t_poll_retx, cfg.poll_pdu, cfg.poll_byte, cfg.max_retx_thresh,
cfg.t_reordering, cfg.t_status_prohibit);
return true;
if (resume()) {
log->info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, "
"t_reordering=%d, t_status_prohibit=%d\n",
rb_name.c_str(),
cfg.am.t_poll_retx,
cfg.am.poll_pdu,
cfg.am.poll_byte,
cfg.am.max_retx_thresh,
cfg.am.t_reordering,
cfg.am.t_status_prohibit);
return true;
} else {
return false;
}
}
void rlc_am::empty_queue()
@ -88,12 +117,14 @@ void rlc_am::empty_queue()
void rlc_am::reestablish()
{
log->debug("Reestablished bearer %s\n", rb_name.c_str());
tx.reestablish(); // calls stop and enables tx again
rx.reestablish(); // calls only stop
}
void rlc_am::stop()
{
log->debug("Stopped bearer %s\n", rb_name.c_str());
tx.stop();
rx.stop();
}

View File

@ -60,6 +60,11 @@ bool rlc_tm::configure(srslte_rlc_config_t cnfg)
return true;
}
bool rlc_tm::resume()
{
return true;
}
void rlc_tm::empty_queue()
{
// Drop all messages in TX queue

View File

@ -54,28 +54,44 @@ void rlc_um::init(srslte::log *log_,
log = log_;
}
bool rlc_um::resume()
{
if (not has_configuration) {
log->error("Error resuming bearer: no previous configuration found\n");
return false;
}
if (not rx.configure(cfg, rb_name)) {
return false;
}
if (not tx.configure(cfg, rb_name)) {
return false;
}
return true;
}
bool rlc_um::configure(srslte_rlc_config_t cnfg_)
{
// determine bearer name and configure Rx/Tx objects
rb_name = get_rb_name(rrc, lcid, cnfg_.um.is_mrb);
if (not rx.configure(cnfg_, rb_name)) {
return false;
}
if (not tx.configure(cnfg_, rb_name)) {
return false;
}
// store config
cfg = cnfg_.um;
cfg = cnfg_;
has_configuration = true;
log->warning("%s configured in %s: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n",
rb_name.c_str(), rlc_mode_text[cnfg_.rlc_mode], cfg.t_reordering,
rlc_umd_sn_size_num[cfg.rx_sn_field_length], rlc_umd_sn_size_num[cfg.rx_sn_field_length]);
return true;
if (resume()) {
log->info("%s configured in %s: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n",
rb_name.c_str(),
rlc_mode_text[cnfg_.rlc_mode],
cfg.um.t_reordering,
rlc_umd_sn_size_num[cfg.um.rx_sn_field_length],
rlc_umd_sn_size_num[cfg.um.rx_sn_field_length]);
return true;
} else {
return false;
}
}
@ -109,7 +125,7 @@ void rlc_um::empty_queue() {
bool rlc_um::is_mrb()
{
return cfg.is_mrb;
return cfg.um.is_mrb;
}

View File

@ -129,6 +129,30 @@ private:
bool running;
};
void basic_test_tx(rlc_am* rlc, byte_buffer_t pdu_bufs[NBUFS])
{
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
rlc->write_sdu(std::move(sdu_bufs[i]));
}
assert(14 == rlc->get_buffer_state());
// Read 5 PDUs from RLC1 (1 byte each)
for (int i = 0; i < NBUFS; i++) {
uint32_t len = rlc->read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len;
}
assert(0 == rlc->get_buffer_state());
}
bool basic_test()
{
srslte::log_filter log1("RLC_AM_1");
@ -139,6 +163,7 @@ bool basic_test()
log2.set_hex_limit(-1);
rlc_am_tester tester;
mac_dummy_timers timers;
byte_buffer_t pdu_bufs[NBUFS];
rlc_am rlc1;
rlc_am rlc2;
@ -168,28 +193,7 @@ bool basic_test()
return -1;
}
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
unique_byte_buffer_t sdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++)
{
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
rlc1.write_sdu(std::move(sdu_bufs[i]));
}
assert(14 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (1 byte each)
byte_buffer_t pdu_bufs[NBUFS];
for(int i=0;i<NBUFS;i++)
{
len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 3 bytes for header + payload
pdu_bufs[i].N_bytes = len;
}
assert(0 == rlc1.get_buffer_state());
basic_test_tx(&rlc1, pdu_bufs);
// Write 5 PDUs into RLC2
for(int i=0;i<NBUFS;i++)
@ -1677,6 +1681,67 @@ bool reset_test()
return 0;
}
bool resume_test()
{
srslte::log_filter log1("RLC_AM_1");
srslte::log_filter log2("RLC_AM_2");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
mac_dummy_timers timers;
rlc_am rlc1;
int len;
log1.set_level(srslte::LOG_LEVEL_DEBUG);
rlc1.init(&log1, 1, &tester, &tester, &timers);
rlc_cfg_c cnfg;
cnfg.set(rlc_cfg_c::types::am);
cnfg.am().dl_am_rlc.t_reordering = t_reordering_e::ms5;
cnfg.am().dl_am_rlc.t_status_prohibit = t_status_prohibit_e::ms5;
cnfg.am().ul_am_rlc.max_retx_thres = ul_am_rlc_s::max_retx_thres_e_::t4;
cnfg.am().ul_am_rlc.poll_byte = poll_byte_e::kb25;
cnfg.am().ul_am_rlc.poll_pdu = poll_pdu_e::p4;
cnfg.am().ul_am_rlc.t_poll_retx = t_poll_retx_e::ms5;
if (not rlc1.configure(&cnfg)) {
return -1;
}
// Push 1 SDU of size 10 into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
unique_byte_buffer_t sdu_buf = srslte::allocate_unique_buffer(*pool, true);
sdu_buf->msg[0] = 1; // Write the index into the buffer
sdu_buf->N_bytes = 100;
rlc1.write_sdu(std::move(sdu_buf));
// read 1 PDU from RLC1 and force segmentation
byte_buffer_t pdu_bufs;
len = rlc1.read_pdu(pdu_bufs.msg, 4);
pdu_bufs.N_bytes = len;
// reestablish RLC1
rlc1.reestablish();
// resume RLC1
rlc1.resume();
// Buffer should be zero
if (0 != rlc1.get_buffer_state()) {
return -1;
}
// Do basic test
byte_buffer_t pdu_bufs_tx[NBUFS];
basic_test_tx(&rlc1, pdu_bufs_tx);
return 0;
}
bool stop_test()
{
srslte::log_filter log1("RLC_AM_1");
@ -1808,4 +1873,10 @@ int main(int argc, char **argv)
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
if (resume_test()) {
printf("resume_test failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
}