diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index 2d05967f5..3a8c2cc16 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -72,13 +72,11 @@ class rlc_am public: rlc_am(); ~rlc_am(); - - void init(log *rlc_entity_log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc *pdcp_, - srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers, - bool is_mrb_=false); + void init(log *rlc_entity_log_, + uint32_t lcid_, + srsue::pdcp_interface_rlc *pdcp_, + srsue::rrc_interface_rlc *rrc_, + mac_interface_timers *mac_timers); void configure(srslte_rlc_config_t cnfg); void reset(); void reestablish(); diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index 9c304d4f6..9be390d31 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -155,8 +155,7 @@ public: uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - srslte::mac_interface_timers *mac_timers_, - bool is_mrb_=false) = 0; + srslte::mac_interface_timers *mac_timers_) = 0; virtual void configure(srslte_rlc_config_t cnfg) = 0; virtual void reset() = 0; virtual void stop() = 0; diff --git a/lib/include/srslte/upper/rlc_interface.h b/lib/include/srslte/upper/rlc_interface.h index a28d3d9bd..94fd2abcc 100644 --- a/lib/include/srslte/upper/rlc_interface.h +++ b/lib/include/srslte/upper/rlc_interface.h @@ -73,6 +73,7 @@ typedef struct { uint32_t rx_window_size; uint32_t rx_mod; // Rx counter modulus uint32_t tx_mod; // Tx counter modulus + bool is_mrb; // Whether this is a multicast bearer } srslte_rlc_um_config_t; @@ -122,6 +123,21 @@ public: break; } } + + // Factory for MCH + static srslte_rlc_config_t mch_config() + { + srslte_rlc_config_t cfg; + cfg.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_UNI_DL; + cfg.um.t_reordering = 0; + cfg.um.rx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; + cfg.um.rx_window_size = 0; + cfg.um.rx_mod = 32; + cfg.um.tx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; + cfg.um.tx_mod = 32; + cfg.um.is_mrb = true; + return cfg; + } }; } // namespace srslte diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index 8adda8639..ecb79e653 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -45,8 +45,7 @@ public: uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers, - bool is_mrb_=false); + mac_interface_timers *mac_timers); void configure(srslte_rlc_config_t cnfg); void reset(); void stop(); diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index 6a9eaef5c..80def61f8 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -56,8 +56,7 @@ public: uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers_, - bool mrb_=false); + mac_interface_timers *mac_timers_); void configure(srslte_rlc_config_t cnfg); void reset(); void stop(); @@ -88,8 +87,7 @@ private: uint32_t lcid; srsue::pdcp_interface_rlc *pdcp; srsue::rrc_interface_rlc *rrc; - mac_interface_timers *mac_timers; - bool mrb; + mac_interface_timers *mac_timers; // TX SDU buffers rlc_tx_queue tx_sdu_queue; @@ -137,7 +135,6 @@ private: int build_data_pdu(uint8_t *payload, uint32_t nof_bytes); void handle_data_pdu(uint8_t *payload, uint32_t nof_bytes); - int build_mch_data_pdu(uint8_t *payload, uint32_t nof_bytes); void handle_mch_data_pdu(uint8_t *payload, uint32_t nof_bytes); void reassemble_rx_sdus(); bool inside_reordering_window(uint16_t sn); diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 77a71afd4..69f530846 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -315,7 +315,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) } else { rlc_log->warning("Bearer %s already created.\n", rrc->get_rb_name(lcid).c_str()); } - rlc_array[lcid].configure(cnfg); + rlc_array[lcid].configure(cnfg); } @@ -326,8 +326,8 @@ void rlc::add_bearer_mrb(uint32_t lcid) rlc_log->error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_MCH_LCIDS, lcid); return; } - bool is_mrb = true; - rlc_array_mrb[lcid].init(rlc_log, lcid, pdcp, rrc, mac_timers, is_mrb); + rlc_array_mrb[lcid].init(rlc_log, lcid, pdcp, rrc, mac_timers); + rlc_array_mrb[lcid].configure(srslte_rlc_config_t::mch_config()); } void rlc::add_bearer_mrb_enb(uint32_t lcid) @@ -336,8 +336,8 @@ void rlc::add_bearer_mrb_enb(uint32_t lcid) rlc_log->error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_MCH_LCIDS, lcid); return; } - rlc_array_mrb[lcid].init(rlc_log,lcid,pdcp,rrc,mac_timers,true); - + rlc_array_mrb[lcid].init(rlc_log,lcid,pdcp,rrc,mac_timers); + rlc_array_mrb[lcid].configure(srslte_rlc_config_t::mch_config()); } /******************************************************************************* diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index a992e1182..a29f54216 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -85,8 +85,7 @@ void rlc_am::init(srslte::log *log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - srslte::mac_interface_timers *mac_timers, - bool is_mrb) + srslte::mac_interface_timers *mac_timers) { log = log_; lcid = lcid_; diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 21db7b0ac..0dd16bf4d 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -42,8 +42,7 @@ void rlc_tm::init(srslte::log *log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers, - bool is_mrb) + mac_interface_timers *mac_timers) { log = log_; lcid = lcid_; diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index 29ebcb4c7..a4cb116bb 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -27,6 +27,7 @@ #include "srslte/upper/rlc_um.h" #include +#include #define RX_MOD_BASE(x) (x-vr_uh-cfg.rx_window_size)%cfg.rx_mod @@ -56,8 +57,7 @@ rlc_um::rlc_um() : tx_sdu_queue(32) vr_ur_in_rx_sdu = 0; - mac_timers = NULL; - mrb = false; + mac_timers = NULL; pdu_lost = false; } @@ -70,38 +70,19 @@ void rlc_um::init(srslte::log *log_, uint32_t lcid_, srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, - srslte::mac_interface_timers *mac_timers_, - bool mrb_) + srslte::mac_interface_timers *mac_timers_) { log = log_; lcid = lcid_; pdcp = pdcp_; rrc = rrc_; mac_timers = mac_timers_; - mrb = mrb_; reordering_timer_id = mac_timers->timer_get_unique_id(); reordering_timer = mac_timers->timer_get(reordering_timer_id); - - if(mrb) { - cfg.t_reordering = 0; - cfg.rx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; - cfg.rx_window_size = 0; - cfg.rx_mod = 32; - cfg.tx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; - cfg.tx_mod = 32; - log->info("MRB%d configured in %s mode: " - "t_reordering=%d ms, rx_sn_field_length=%u bits\n", - lcid, liblte_rrc_rlc_mode_text[LIBLTE_RRC_RLC_MODE_UM_UNI_DL], - cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length]); - } } void rlc_um::configure(srslte_rlc_config_t cnfg_) -{ - if(mrb) { - return; // Default configured in init() - } - +{ cfg = cnfg_.um; switch(cnfg_.rlc_mode) @@ -140,7 +121,7 @@ void rlc_um::empty_queue() { bool rlc_um::is_mrb() { - return mrb; + return cfg.is_mrb; } void rlc_um::stop() @@ -224,7 +205,7 @@ uint32_t rlc_um::get_buffer_state() // Room needed for fixed header? if(n_bytes > 0) - n_bytes += (mrb)?2:3; + n_bytes += (cfg.is_mrb)?2:3; return n_bytes; } @@ -239,11 +220,7 @@ int rlc_um::read_pdu(uint8_t *payload, uint32_t nof_bytes) int r; log->debug("MAC opportunity - %d bytes\n", nof_bytes); pthread_mutex_lock(&mutex); - if(mrb){ - r = build_mch_data_pdu(payload, nof_bytes); - } else{ - r = build_data_pdu(payload, nof_bytes); - } + r = build_data_pdu(payload, nof_bytes); pthread_mutex_unlock(&mutex); return r; } @@ -251,7 +228,7 @@ int rlc_um::read_pdu(uint8_t *payload, uint32_t nof_bytes) void rlc_um::write_pdu(uint8_t *payload, uint32_t nof_bytes) { pthread_mutex_lock(&mutex); - if(mrb) { + if(cfg.is_mrb) { handle_mch_data_pdu(payload, nof_bytes); } else { handle_data_pdu(payload, nof_bytes); @@ -305,130 +282,6 @@ bool rlc_um::reordering_timeout_running() * Helpers ***************************************************************************/ - -int rlc_um::build_mch_data_pdu(uint8_t *payload, uint32_t nof_bytes) -{ - - if(!tx_sdu && tx_sdu_queue.size() == 0) - { - log->info("No data available to be sent\n"); - return 0; - } - - byte_buffer_t *pdu = pool_allocate; - if(!pdu || pdu->N_bytes != 0) - { - log->error("Failed to allocate PDU buffer\n"); - return 0; - } - - rlc_umd_pdu_header_t header; - header.fi = RLC_FI_FIELD_START_AND_END_ALIGNED; - header.sn = vt_us; - header.N_li = 0; - header.sn_size = RLC_UMD_SN_SIZE_5_BITS; //cfg.tx_sn_field_length; - - - uint32_t to_move = 0; - uint32_t last_li = 0; - uint8_t *pdu_ptr = pdu->msg; - - int head_len = rlc_um_packed_length(&header); - int pdu_space = nof_bytes; - - if(pdu_space <= head_len + 1) - { - pool->deallocate(pdu); - log->warning("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", - rb_name().c_str(), nof_bytes, head_len); - return 0; - } - - // Check for SDU segment - if(tx_sdu) - { - uint32_t space = pdu_space-head_len; - to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; - log->debug("%s adding remainder of SDU segment - %d bytes of %d remaining\n", - rb_name().c_str(), to_move, tx_sdu->N_bytes); - memcpy(pdu_ptr, tx_sdu->msg, to_move); - - last_li = to_move; - pdu_ptr += to_move; - pdu->N_bytes += to_move; - tx_sdu->N_bytes -= to_move; - tx_sdu->msg += to_move; - if(tx_sdu->N_bytes == 0) - { - log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); - - pool->deallocate(tx_sdu); - tx_sdu = NULL; - } - pdu_space -= to_move; - header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU - } - - // Pull SDUs from queue - while(pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) - { - log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len); - if(last_li > 0) - header.li[header.N_li++] = last_li; - head_len = rlc_um_packed_length(&header); - tx_sdu_queue.read(&tx_sdu); - - uint32_t space = pdu_space-head_len; - to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space; - log->debug("%s adding new SDU segment - %d bytes of %d remaining\n", - rb_name().c_str(), to_move, tx_sdu->N_bytes); - memcpy(pdu_ptr, tx_sdu->msg, to_move); - last_li = to_move; - pdu_ptr += to_move; - pdu->N_bytes += to_move; - tx_sdu->N_bytes -= to_move; - tx_sdu->msg += to_move; - if(tx_sdu->N_bytes == 0) - { - log->debug("%s Complete SDU scheduled for tx. Stack latency: %ld us\n", - rrc->get_rb_name(lcid).c_str(), tx_sdu->get_latency_us()); - pool->deallocate(tx_sdu); - tx_sdu = NULL; - } - pdu_space -= to_move; - } - - if(tx_sdu) - header.fi |= RLC_FI_FIELD_NOT_END_ALIGNED; // Last byte does not correspond to last byte of SDU - - // Set SN - header.sn = vt_us; - vt_us = (vt_us + 1)%cfg.tx_mod; - - - // Add header and TX - log->debug("%s packing PDU with length %d\n", rb_name().c_str(), pdu->N_bytes); - - - if(pdu_space > 0 && tx_sdu == NULL){ - //header.li[header.N_li++] = last_li; - header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; - } - rlc_um_write_data_pdu_header(&header, pdu); - memcpy(payload, pdu->msg, pdu->N_bytes); - uint32_t ret = pdu->N_bytes; - - log->debug("%s returning length %d\n", rrc->get_rb_name(lcid).c_str(), pdu->N_bytes); - - pool->deallocate(pdu); - - debug_state(); - return ret; - - -} - int rlc_um::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) { if(!tx_sdu && tx_sdu_queue.size() == 0) @@ -867,7 +720,7 @@ void rlc_um::debug_state() } std::string rlc_um::rb_name() { - if(mrb) { + if(cfg.is_mrb) { std::stringstream ss; ss << "MRB" << lcid; return ss.str(); diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/upper/rlc_um_test.cc index c0ad46e7b..58cc217f1 100644 --- a/lib/test/upper/rlc_um_test.cc +++ b/lib/test/upper/rlc_um_test.cc @@ -260,12 +260,13 @@ void basic_mbsfn_test() log1.set_level(srslte::LOG_LEVEL_DEBUG); log2.set_level(srslte::LOG_LEVEL_DEBUG); - bool is_mrb = true; - rlc1.init(&log1, 3, &tester, &tester, &timers, is_mrb); - rlc2.init(&log2, 3, &tester, &tester, &timers, is_mrb); + rlc1.init(&log1, 3, &tester, &tester, &timers); + rlc2.init(&log2, 3, &tester, &tester, &timers); - //rlc1.configure(&cnfg); //MRB RLC is default configured - //rlc2.configure(&cnfg); //MRB RLC is default configured + rlc1.configure(srslte_rlc_config_t::mch_config()); + rlc2.configure(srslte_rlc_config_t::mch_config()); + + tester.set_expected_sdu_len(1); // Push 5 SDUs into RLC1 byte_buffer_t sdu_bufs[NBUFS*2];