mirror of https://github.com/PentHertz/srsLTE.git
Add RLC resume procedure
This commit is contained in:
parent
3f613d7183
commit
ade720e032
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue