From 8e8fab027bbe475699ba614b4ce6b0781b173766 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 20 Jul 2018 10:19:08 +0200 Subject: [PATCH] refactor RLC base class - add rwlock - put RLC entities into map - general cleanup --- lib/include/srslte/upper/rlc.h | 17 +- lib/include/srslte/upper/rlc_entity.h | 87 ------ lib/src/upper/rlc.cc | 427 +++++++++++++++++--------- lib/src/upper/rlc_entity.cc | 170 ---------- 4 files changed, 300 insertions(+), 401 deletions(-) delete mode 100644 lib/include/srslte/upper/rlc_entity.h delete mode 100644 lib/src/upper/rlc_entity.cc diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 8d6eb2fd5..0d8dcad91 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -50,7 +50,7 @@ class rlc { public: rlc(); - virtual ~rlc() {} + virtual ~rlc(); void init(srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, srsue::ue_interface *ue_, @@ -88,7 +88,7 @@ public: void add_bearer(uint32_t lcid); void add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg); void add_bearer_mrb(uint32_t lcid); - void add_bearer_mrb_enb(uint32_t lcid); + private: void reset_metrics(); @@ -98,14 +98,17 @@ private: srsue::rrc_interface_rlc *rrc; srslte::mac_interface_timers *mac_timers; srsue::ue_interface *ue; - srslte::rlc_entity rlc_array[SRSLTE_N_RADIO_BEARERS]; - srslte::rlc_um rlc_array_mrb[SRSLTE_N_MCH_LCIDS]; + + typedef std::map rlc_map_t; + typedef std::pair rlc_map_pair_t; + + rlc_map_t rlc_array, rlc_array_mrb; + pthread_rwlock_t rwlock; + uint32_t default_lcid; int buffer_size; - long ul_tput_bytes[SRSLTE_N_RADIO_BEARERS]; - long dl_tput_bytes[SRSLTE_N_RADIO_BEARERS]; - long dl_tput_bytes_mrb[SRSLTE_N_MCH_LCIDS]; + // Timer needed for metrics calculation struct timeval metrics_time[3]; bool valid_lcid(uint32_t lcid); diff --git a/lib/include/srslte/upper/rlc_entity.h b/lib/include/srslte/upper/rlc_entity.h deleted file mode 100644 index 894572c14..000000000 --- a/lib/include/srslte/upper/rlc_entity.h +++ /dev/null @@ -1,87 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2015 Software Radio Systems Limited - * - * \section LICENSE - * - * This file is part of the srsUE library. - * - * srsUE is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsUE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#ifndef SRSLTE_RLC_ENTITY_H -#define SRSLTE_RLC_ENTITY_H - -#include "srslte/common/log.h" -#include "srslte/common/common.h" -#include "srslte/interfaces/ue_interfaces.h" -#include "srslte/upper/rlc_common.h" -#include "srslte/upper/rlc_tm.h" -#include "srslte/upper/rlc_um.h" -#include "srslte/upper/rlc_am.h" - -namespace srslte { - - - -/**************************************************************************** - * RLC Entity - * Common container for all RLC entities - ***************************************************************************/ -class rlc_entity -{ -public: - rlc_entity(); - void init(rlc_mode_t mode, - log *rlc_entity_log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc *pdcp_, - srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers_, - int buffer_size = -1); // use -1 for default buffer sizes - - void configure(srslte_rlc_config_t cnfg); - void reestablish(); - void stop(); - void empty_queue(); - bool active(); - - rlc_mode_t get_mode(); - uint32_t get_bearer(); - - // PDCP interface - void write_sdu(byte_buffer_t *sdu); - void write_sdu_nb(byte_buffer_t *sdu); - - // MAC interface - uint32_t get_buffer_state(); - uint32_t get_total_buffer_state(); - int read_pdu(uint8_t *payload, uint32_t nof_bytes); - void write_pdu(uint8_t *payload, uint32_t nof_bytes); - - -private: - rlc_mode_t mode; - uint32_t lcid; - rlc_common *rlc; -}; - -} // namespace srslte - - -#endif // SRSLTE_RLC_ENTITY_H diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index c24f0076b..1a602d7c0 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -25,6 +25,7 @@ */ +#include #include "srslte/upper/rlc.h" #include "srslte/upper/rlc_tm.h" #include "srslte/upper/rlc_um.h" @@ -42,8 +43,25 @@ rlc::rlc() ue = NULL; default_lcid = 0; bzero(metrics_time, sizeof(metrics_time)); - bzero(ul_tput_bytes, sizeof(ul_tput_bytes)); - bzero(dl_tput_bytes, sizeof(dl_tput_bytes)); + pthread_rwlock_init(&rwlock, NULL); +} + +rlc::~rlc() +{ + // destroy all remaining entities + pthread_rwlock_wrlock(&rwlock); + for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) { + delete(it->second); + } + rlc_array.clear(); + + for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { + delete(it->second); + } + rlc_array_mrb.clear(); + + pthread_rwlock_unlock(&rwlock); + pthread_rwlock_destroy(&rwlock); } void rlc::init(srsue::pdcp_interface_rlc *pdcp_, @@ -63,109 +81,170 @@ void rlc::init(srsue::pdcp_interface_rlc *pdcp_, buffer_size = buffer_size_; gettimeofday(&metrics_time[1], NULL); - reset_metrics(); + reset_metrics(); - rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers, buffer_size); // SRB0 + // create default RLC_TM bearer for SRB0 + add_bearer(default_lcid, srslte_rlc_config_t()); } void rlc::reset_metrics() { - bzero(dl_tput_bytes, sizeof(long)*SRSLTE_N_RADIO_BEARERS); - bzero(ul_tput_bytes, sizeof(long)*SRSLTE_N_RADIO_BEARERS); + for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) { + it->second->reset_metrics(); + } + + for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { + it->second->reset_metrics(); + } } void rlc::stop() { - for(uint32_t i=0; isecond->stop(); } + for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { + it->second->stop(); + } + pthread_rwlock_unlock(&rwlock); } void rlc::get_metrics(rlc_metrics_t &m) { - + pthread_rwlock_rdlock(&rwlock); + gettimeofday(&metrics_time[2], NULL); get_time_interval(metrics_time); double secs = (double)metrics_time[0].tv_sec + metrics_time[0].tv_usec*1e-6; m.dl_tput_mbps = 0; - m.ul_tput_mbps = 0; - for (int i=0;iinfo("LCID=%d, RX throughput: %4.6f Mbps. TX throughput: %4.6f Mbps.\n", - i, - (dl_tput_bytes[i]*8/(double)1e6)/secs, - (ul_tput_bytes[i]*8/(double)1e6)/secs); - } + m.ul_tput_mbps = 0; + + for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) { + m.dl_tput_mbps += (it->second->get_num_rx_bytes()*8/(double)1e6)/secs; + m.ul_tput_mbps += (it->second->get_num_tx_bytes()*8/(double)1e6)/secs; + rlc_log->info("LCID=%d, RX throughput: %4.6f Mbps. TX throughput: %4.6f Mbps.\n", + it->first, + (it->second->get_num_rx_bytes()*8/(double)1e6)/secs, + (it->second->get_num_tx_bytes()*8/(double)1e6)/secs); } // Add multicast metrics - for (int i=0;iinfo("MCH_LCID=%d, RX throughput: %4.6f Mbps.\n", - i, - (dl_tput_bytes_mrb[i]*8/(double)1e6)/secs); - } + for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { + m.dl_tput_mbps += (it->second->get_num_rx_bytes()*8/(double)1e6)/secs; + rlc_log->info("MCH_LCID=%d, RX throughput: %4.6f Mbps\n", + it->first, + (it->second->get_num_rx_bytes()*8/(double)1e6)/secs); } memcpy(&metrics_time[1], &metrics_time[2], sizeof(struct timeval)); reset_metrics(); + + pthread_rwlock_unlock(&rwlock); } // A call to reestablish stops all lcids but does not delete the instances. The mapping lcid to rlc mode can not change -void rlc::reestablish() { - for(uint32_t i=0; isecond->reestablish(); + } + + for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { + it->second->reestablish(); } + + pthread_rwlock_unlock(&rwlock); } -// Resetting the RLC layer returns the object to the state after the call to init(): All lcids are stopped and -// defaul lcid=0 is created +// Resetting the RLC layer returns the object to the state after the call to init(): +// All LCIDs are removed, except SRB0 void rlc::reset() { - stop(); - rlc_array[0].init(RLC_MODE_TM, rlc_log, default_lcid, pdcp, rrc, mac_timers, buffer_size); // SRB0 + pthread_rwlock_wrlock(&rwlock); + for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) { + delete(it->second); + } + rlc_array.clear(); + + for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { + delete(it->second); + } + rlc_array_mrb.clear(); + + // Add SRB0 again + add_bearer(default_lcid, srslte_rlc_config_t()); + + pthread_rwlock_unlock(&rwlock); } void rlc::empty_queue() { - for(uint32_t i=0; isecond->empty_queue(); } + pthread_rwlock_unlock(&rwlock); } /******************************************************************************* PDCP interface *******************************************************************************/ + void rlc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { - if(valid_lcid(lcid)) { - rlc_array[lcid].write_sdu(sdu); + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + rlc_array.at(lcid)->write_sdu(sdu); + } else { + rlc_log->warning("Writing SDU: lcid=%d. Deallocating sdu\n", lcid); + byte_buffer_pool::get_instance()->deallocate(sdu); } + pthread_rwlock_unlock(&rwlock); } + + void rlc::write_sdu_nb(uint32_t lcid, byte_buffer_t *sdu) { - if(valid_lcid(lcid)) { - rlc_array[lcid].write_sdu_nb(sdu); + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + rlc_array.at(lcid)->write_sdu_nb(sdu); + } else { + rlc_log->warning("Writing SDU: lcid=%d. Deallocating sdu\n", lcid); + byte_buffer_pool::get_instance()->deallocate(sdu); } + pthread_rwlock_unlock(&rwlock); } + + void rlc::write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu) { - if(valid_lcid_mrb(lcid)) { - rlc_array_mrb[lcid].write_sdu(sdu); + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid_mrb(lcid)) { + rlc_array_mrb.at(lcid)->write_sdu_nb(sdu); + } else { + rlc_log->warning("Writing SDU: lcid=%d. Deallocating sdu\n", lcid); + byte_buffer_pool::get_instance()->deallocate(sdu); } + pthread_rwlock_unlock(&rwlock); } -bool rlc::rb_is_um(uint32_t lcid) { - return rlc_array[lcid].get_mode()==RLC_MODE_UM; + +bool rlc::rb_is_um(uint32_t lcid) +{ + bool ret = false; + + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + ret = rlc_array.at(lcid)->get_mode() == RLC_MODE_UM; + } + pthread_rwlock_unlock(&rwlock); + + return ret; } /******************************************************************************* @@ -173,61 +252,82 @@ bool rlc::rb_is_um(uint32_t lcid) { *******************************************************************************/ uint32_t rlc::get_buffer_state(uint32_t lcid) { - if(valid_lcid(lcid)) { - return rlc_array[lcid].get_buffer_state(); - } else { - return 0; + uint32_t ret = 0; + + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + ret = rlc_array.at(lcid)->get_buffer_state(); } + pthread_rwlock_unlock(&rwlock); + + return ret; } uint32_t rlc::get_total_buffer_state(uint32_t lcid) { - if(valid_lcid(lcid)) { - return rlc_array[lcid].get_total_buffer_state(); - } else { - return 0; + uint32_t ret = 0; + + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + ret = rlc_array.at(lcid)->get_total_buffer_state(); } + pthread_rwlock_unlock(&rwlock); + + return ret; } uint32_t rlc::get_total_mch_buffer_state(uint32_t lcid) { - if(valid_lcid_mrb(lcid)) { - return rlc_array_mrb[lcid].get_total_buffer_state(); - } else { - return 0; + uint32_t ret = 0; + + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + ret = rlc_array_mrb.at(lcid)->get_total_buffer_state(); } + pthread_rwlock_unlock(&rwlock); + + return ret; } int rlc::read_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) { - if(valid_lcid(lcid)) { - ul_tput_bytes[lcid] += nof_bytes; - return rlc_array[lcid].read_pdu(payload, nof_bytes); + uint32_t ret = 0; + + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + ret = rlc_array.at(lcid)->read_pdu(payload, nof_bytes); } - return 0; + pthread_rwlock_unlock(&rwlock); + + return ret; } int rlc::read_pdu_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) { - if(valid_lcid_mrb(lcid)) { - ul_tput_bytes[lcid] += nof_bytes; - return rlc_array_mrb[lcid].read_pdu(payload, nof_bytes); + uint32_t ret = 0; + + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + ret = rlc_array_mrb.at(lcid)->read_pdu(payload, nof_bytes); } - return 0; + pthread_rwlock_unlock(&rwlock); + + return ret; } void rlc::write_pdu(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) { - if(valid_lcid(lcid)) { - dl_tput_bytes[lcid] += nof_bytes; - rlc_array[lcid].write_pdu(payload, nof_bytes); + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid(lcid)) { + rlc_array.at(lcid)->write_pdu(payload, nof_bytes); } + pthread_rwlock_unlock(&rwlock); } +// Pass directly to PDCP, no DL througput counting done void rlc::write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes) { rlc_log->info_hex(payload, nof_bytes, "BCCH BCH message received."); - dl_tput_bytes[0] += nof_bytes; byte_buffer_t *buf = pool_allocate; if (buf) { memcpy(buf->msg, payload, nof_bytes); @@ -239,10 +339,10 @@ void rlc::write_pdu_bcch_bch(uint8_t *payload, uint32_t nof_bytes) } } +// Pass directly to PDCP, no DL througput counting done void rlc::write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes) { rlc_log->info_hex(payload, nof_bytes, "BCCH TXSCH message received."); - dl_tput_bytes[0] += nof_bytes; byte_buffer_t *buf = pool_allocate; if (buf) { memcpy(buf->msg, payload, nof_bytes); @@ -254,10 +354,10 @@ void rlc::write_pdu_bcch_dlsch(uint8_t *payload, uint32_t nof_bytes) } } +// Pass directly to PDCP, no DL througput counting done void rlc::write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes) { rlc_log->info_hex(payload, nof_bytes, "PCCH message received."); - dl_tput_bytes[0] += nof_bytes; byte_buffer_t *buf = pool_allocate; if (buf) { memcpy(buf->msg, payload, nof_bytes); @@ -271,117 +371,170 @@ void rlc::write_pdu_pcch(uint8_t *payload, uint32_t nof_bytes) void rlc::write_pdu_mch(uint32_t lcid, uint8_t *payload, uint32_t nof_bytes) { - if(valid_lcid_mrb(lcid)) { - dl_tput_bytes_mrb[lcid] += nof_bytes; - rlc_array_mrb[lcid].write_pdu(payload, nof_bytes); + pthread_rwlock_rdlock(&rwlock); + if (valid_lcid_mrb(lcid)) { + rlc_array_mrb.at(lcid)->write_pdu(payload, nof_bytes); } + pthread_rwlock_unlock(&rwlock); } /******************************************************************************* RRC interface *******************************************************************************/ + +// FIXME: Remove function to forbid implicit configuration void rlc::add_bearer(uint32_t lcid) { - // No config provided - use defaults for SRB1 and SRB2 - if(lcid < 3) { - if (!rlc_array[lcid].active()) { - LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; - cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; - cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45; - cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY; - cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_INFINITY; - cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; - cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS35; - cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; - add_bearer(lcid, srslte_rlc_config_t(&cnfg)); - } else { - rlc_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rrc->get_rb_name(lcid).c_str()); - } - }else{ + if (lcid > 2) { rlc_log->error("Radio bearer %s does not support default RLC configuration.\n", rrc->get_rb_name(lcid).c_str()); + return; + } + + // No config provided - use defaults for SRB0, SRB1, and SRB2 + if (lcid == 0) { + // SRB0 is TM + add_bearer(lcid, srslte_rlc_config_t()); + } else { + // SRB1 and SRB2 are AM + LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; + cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; + cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS45; + cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_INFINITY; + cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_INFINITY; + cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4; + cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS35; + cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS0; + add_bearer(lcid, srslte_rlc_config_t(&cnfg)); } } + void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) { - if(lcid >= SRSLTE_N_RADIO_BEARERS) { - rlc_log->error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_RADIO_BEARERS, lcid); - return; - } + pthread_rwlock_wrlock(&rwlock); - if (!rlc_array[lcid].active()) { - rlc_log->warning("Adding radio bearer %s with mode %s\n", - rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]); + rlc_common *rlc_entity = NULL; + + if (not valid_lcid(lcid)) { switch(cnfg.rlc_mode) { - case LIBLTE_RRC_RLC_MODE_AM: - rlc_array[lcid].init(RLC_MODE_AM, rlc_log, lcid, pdcp, rrc, mac_timers, buffer_size); - break; - case LIBLTE_RRC_RLC_MODE_UM_BI: - rlc_array[lcid].init(RLC_MODE_UM, rlc_log, lcid, pdcp, rrc, mac_timers, buffer_size); - break; - case LIBLTE_RRC_RLC_MODE_UM_UNI_DL: - rlc_array[lcid].init(RLC_MODE_UM, rlc_log, lcid, pdcp, rrc, mac_timers, buffer_size); - break; - case LIBLTE_RRC_RLC_MODE_UM_UNI_UL: - rlc_array[lcid].init(RLC_MODE_UM, rlc_log, lcid, pdcp, rrc, mac_timers, buffer_size); - break; - default: - rlc_log->error("Cannot add RLC entity - invalid mode\n"); - return; + case SRSLTE_RLC_MODE_TM: + rlc_entity = new rlc_tm(); + break; + case SRSLTE_RLC_MODE_AM: + rlc_entity = new rlc_am(); + break; + case SRSLTE_RLC_MODE_UM: + rlc_entity = new rlc_um(); + break; + default: + rlc_log->error("Cannot add RLC entity - invalid mode\n"); + return; + } + + if (rlc_entity) { + // configure and add to array + rlc_entity->init(rlc_log, lcid, pdcp, rrc, mac_timers); + + if (cnfg.rlc_mode != SRSLTE_RLC_MODE_TM) { + if (rlc_entity->configure(cnfg) == false) { + rlc_log->error("Error configuring RLC entity\n."); + goto delete_and_exit; + } + } + + if (not rlc_array.insert(rlc_map_pair_t(lcid, rlc_entity)).second) { + rlc_log->error("Error inserting RLC entity in to array\n."); + goto delete_and_exit; + } + } else { + rlc_log->error("Error instantiating RLC\n"); + goto delete_and_exit; } + rlc_log->warning("Added radio bearer %s with mode %s\n", rrc->get_rb_name(lcid).c_str(), liblte_rrc_rlc_mode_text[cnfg.rlc_mode]); + goto unlock_and_exit; } else { rlc_log->warning("Bearer %s already created.\n", rrc->get_rb_name(lcid).c_str()); } - rlc_array[lcid].configure(cnfg); +delete_and_exit: + if (rlc_entity) { + delete(rlc_entity); + } + +unlock_and_exit: + pthread_rwlock_unlock(&rwlock); } + void rlc::add_bearer_mrb(uint32_t lcid) { - // 36.321 Table 6.2.1-4 - if(lcid >= SRSLTE_N_MCH_LCIDS) { - rlc_log->error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_MCH_LCIDS, lcid); - return; + pthread_rwlock_wrlock(&rwlock); + rlc_common *rlc_entity = NULL; + + if (not valid_lcid_mrb(lcid)) { + rlc_entity = new rlc_um(); + if (rlc_entity) { + // configure and add to array + rlc_entity->init(rlc_log, lcid, pdcp, rrc, mac_timers); + if (rlc_entity->configure(srslte_rlc_config_t::mch_config()) == false) { + rlc_log->error("Error configuring RLC entity\n."); + goto delete_and_exit; + } + if (not rlc_array_mrb.insert(rlc_map_pair_t(lcid, rlc_entity)).second) { + rlc_log->error("Error inserting RLC entity in to array\n."); + goto delete_and_exit; + } + } else { + rlc_log->error("Error instantiating RLC\n"); + goto delete_and_exit; + } + rlc_log->warning("Added radio bearer %s with mode RLC_UM\n", rrc->get_rb_name(lcid).c_str()); + goto unlock_and_exit; + } else { + rlc_log->warning("Bearer %s already created.\n", rrc->get_rb_name(lcid).c_str()); } - 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) -{ - if(lcid >= SRSLTE_N_MCH_LCIDS) { - rlc_log->error("Radio bearer id must be in [0:%d] - %d\n", SRSLTE_N_MCH_LCIDS, lcid); - return; +delete_and_exit: + if (rlc_entity) { + delete(rlc_entity); } - rlc_array_mrb[lcid].init(rlc_log,lcid,pdcp,rrc,mac_timers); - rlc_array_mrb[lcid].configure(srslte_rlc_config_t::mch_config()); + +unlock_and_exit: + pthread_rwlock_unlock(&rwlock); } + /******************************************************************************* - Helpers + Helpers (Lock must be hold when calling those) *******************************************************************************/ + bool rlc::valid_lcid(uint32_t lcid) { - if(lcid >= SRSLTE_N_RADIO_BEARERS) { - rlc_log->warning("Invalid LCID=%d\n", lcid); + if (lcid >= SRSLTE_N_RADIO_BEARERS) { + rlc_log->error("Radio bearer id must be in [0:%d] - %d", SRSLTE_N_RADIO_BEARERS, lcid); return false; - } else if(!rlc_array[lcid].active()) { + } + + if (rlc_array.find(lcid) == rlc_array.end()) { return false; } + return true; } bool rlc::valid_lcid_mrb(uint32_t lcid) { - if(lcid >= SRSLTE_N_MCH_LCIDS) { + if (lcid >= SRSLTE_N_MCH_LCIDS) { + rlc_log->error("Radio bearer id must be in [0:%d] - %d", SRSLTE_N_RADIO_BEARERS, lcid); return false; } - if(!rlc_array_mrb[lcid].is_mrb()) { + + if (rlc_array_mrb.find(lcid) == rlc_array_mrb.end()) { return false; } + return true; } - } // namespace srsue diff --git a/lib/src/upper/rlc_entity.cc b/lib/src/upper/rlc_entity.cc deleted file mode 100644 index 783a14982..000000000 --- a/lib/src/upper/rlc_entity.cc +++ /dev/null @@ -1,170 +0,0 @@ -/** - * - * \section COPYRIGHT - * - * Copyright 2013-2015 Software Radio Systems Limited - * - * \section LICENSE - * - * This file is part of the srsUE library. - * - * srsUE is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of - * the License, or (at your option) any later version. - * - * srsUE is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * A copy of the GNU Affero General Public License can be found in - * the LICENSE file in the top-level directory of this distribution - * and at http://www.gnu.org/licenses/. - * - */ - -#include "srslte/upper/rlc_entity.h" - -namespace srslte { - -rlc_entity::rlc_entity() - :rlc(NULL) -{ -} - -void rlc_entity::init(rlc_mode_t mode_, - log *rlc_entity_log_, - uint32_t lcid_, - srsue::pdcp_interface_rlc *pdcp_, - srsue::rrc_interface_rlc *rrc_, - mac_interface_timers *mac_timers_, - int buffer_size) -{ - - if (buffer_size <= 0) { - buffer_size = rlc_common::RLC_BUFFER_NOF_PDU; - } - // Create the RLC instance the first time init() is called. - // If called to reestablished, the entity is stopped but not destroyed - // Next call to init() must use same mode - if (rlc == NULL) { - switch(mode_) - { - case RLC_MODE_TM: - rlc = new rlc_tm((uint32_t) buffer_size); - break; - case RLC_MODE_UM: - rlc = new rlc_um((uint32_t) buffer_size); - break; - case RLC_MODE_AM: - rlc = new rlc_am((uint32_t) buffer_size); - break; - default: - rlc_entity_log_->error("Invalid RLC mode - defaulting to TM\n"); - rlc = new rlc_tm((uint32_t) buffer_size); - break; - } - lcid = lcid_; - mode = mode_; - } else { - if (lcid != lcid_) { - rlc_entity_log_->warning("Reestablishing RLC instance. LCID changed from %d to %d\n", lcid, lcid_); - lcid = lcid_; - } - if (mode != mode_) { - rlc_entity_log_->console("Error reestablishing RLC instance. Mode changed from %d to %d. \n", mode, mode_); - } - } - rlc->init(rlc_entity_log_, lcid_, pdcp_, rrc_, mac_timers_); -} - -void rlc_entity::configure(srslte_rlc_config_t cnfg) -{ - if(rlc) - rlc->configure(cnfg); -} - -// Reestablishment stops the entity but does not destroy it. Mode will not change -void rlc_entity::reestablish() { - rlc->reestablish(); -} - -// A call to stop() stops the entity and clears deletes the instance. Next time this entity can be used for other mode. -void rlc_entity::stop() -{ - rlc->stop(); - delete rlc; - rlc = NULL; -} - -void rlc_entity::empty_queue() -{ - rlc->empty_queue(); -} - -bool rlc_entity::active() -{ - return (rlc != NULL); -} - -rlc_mode_t rlc_entity::get_mode() -{ - if(rlc) - return rlc->get_mode(); - else - return RLC_MODE_TM; -} - -uint32_t rlc_entity::get_bearer() -{ - if(rlc) - return rlc->get_bearer(); - else - return 0; -} - -// PDCP interface -void rlc_entity::write_sdu(byte_buffer_t *sdu) -{ - if(rlc) - rlc->write_sdu(sdu); -} - -void rlc_entity::write_sdu_nb(byte_buffer_t *sdu) -{ - if(rlc) - rlc->write_sdu_nb(sdu); -} - -// MAC interface -uint32_t rlc_entity::get_buffer_state() -{ - if(rlc) - return rlc->get_buffer_state(); - else - return 0; -} - -uint32_t rlc_entity::get_total_buffer_state() -{ - if(rlc) - return rlc->get_total_buffer_state(); - else - return 0; -} - -int rlc_entity::read_pdu(uint8_t *payload, uint32_t nof_bytes) -{ - if(rlc) - return rlc->read_pdu(payload, nof_bytes); - else - return 0; -} -void rlc_entity::write_pdu(uint8_t *payload, uint32_t nof_bytes) -{ - if(rlc) - rlc->write_pdu(payload, nof_bytes); -} - -} // namespace srsue