From ade720e032afa5201c047836141409b72070556a Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 4 Jun 2019 17:29:02 +0200 Subject: [PATCH] Add RLC resume procedure --- lib/include/srslte/upper/rlc.h | 1 + lib/include/srslte/upper/rlc_am.h | 4 +- lib/include/srslte/upper/rlc_common.h | 1 + lib/include/srslte/upper/rlc_tm.h | 1 + lib/include/srslte/upper/rlc_um.h | 4 +- lib/src/upper/rlc.cc | 20 +++++ lib/src/upper/rlc_am.cc | 63 ++++++++++---- lib/src/upper/rlc_tm.cc | 5 ++ lib/src/upper/rlc_um.cc | 46 +++++++---- lib/test/upper/rlc_am_test.cc | 115 +++++++++++++++++++++----- 10 files changed, 205 insertions(+), 55 deletions(-) diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 853cb5262..8e5a8e6f8 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -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); diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index 8872279be..da0435d98 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -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 diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index 0398a84c2..56a95a515 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -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; diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index 2d74cc6ee..2f4664ec5 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -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(); diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index 311276fb9..318945037 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -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; diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index a4c487980..6f2354989 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -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) { diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index f27c8c75c..9f43cb9be 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -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(); } diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index a8e3abf7c..9246a4964 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -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 diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index efb53cb71..9eadc1cee 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -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; } diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index 9fddd52c2..62695d3f8 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -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;imsg[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;imsg[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(); }