From 8e8fab027bbe475699ba614b4ce6b0781b173766 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Fri, 20 Jul 2018 10:19:08 +0200 Subject: [PATCH 01/13] 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 From 27d3d697df8b5306b2267dc46e231da2df2298d5 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 23 Jul 2018 15:44:50 +0200 Subject: [PATCH 02/13] refactor RLC part#2 - move metrics into entities - make configure interface return true/false on success/failure - add own srslte mode type --- lib/include/srslte/upper/rlc_am.h | 13 ++- lib/include/srslte/upper/rlc_common.h | 6 +- lib/include/srslte/upper/rlc_interface.h | 35 ++++--- lib/include/srslte/upper/rlc_tm.h | 12 ++- lib/include/srslte/upper/rlc_um.h | 23 +++- lib/src/upper/rlc_am.cc | 48 +++++++-- lib/src/upper/rlc_tm.cc | 29 +++++- lib/src/upper/rlc_um.cc | 127 +++++++++++++++++------ lib/test/upper/rlc_am_test.cc | 11 ++ lib/test/upper/rlc_stress_test.cc | 20 ++-- lib/test/upper/rlc_um_test.cc | 4 +- srsenb/src/upper/rlc.cc | 2 +- 12 files changed, 250 insertions(+), 80 deletions(-) diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index cfaee6c5c..f57a65b0b 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -66,8 +66,7 @@ struct rlc_amd_retx_t{ }; -class rlc_am - :public rlc_common +class rlc_am : public rlc_common { public: rlc_am(uint32_t queue_len = 16); @@ -77,7 +76,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers); - void configure(srslte_rlc_config_t cnfg); + bool configure(srslte_rlc_config_t cnfg); void reestablish(); void stop(); @@ -96,6 +95,10 @@ public: int read_pdu(uint8_t *payload, uint32_t nof_bytes); void write_pdu(uint8_t *payload, uint32_t nof_bytes); + uint32_t get_num_tx_bytes(); + uint32_t get_num_rx_bytes(); + void reset_metrics(); + private: byte_buffer_pool *pool; @@ -128,6 +131,10 @@ private: bool do_status; rlc_status_pdu_t status; + // Metrics + uint32_t num_tx_bytes; + uint32_t num_rx_bytes; + /**************************************************************************** * Configurable parameters * Ref: 3GPP TS 36.322 v10.0.0 Section 7 diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index c9655efae..f3fcec12d 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -161,7 +161,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, srslte::mac_interface_timers *mac_timers_) = 0; - virtual void configure(srslte_rlc_config_t cnfg) = 0; + virtual bool configure(srslte_rlc_config_t cnfg) = 0; virtual void stop() = 0; virtual void reestablish() = 0; virtual void empty_queue() = 0; @@ -169,6 +169,10 @@ public: virtual rlc_mode_t get_mode() = 0; virtual uint32_t get_bearer() = 0; + virtual uint32_t get_num_tx_bytes() = 0; + virtual uint32_t get_num_rx_bytes() = 0; + virtual void reset_metrics() = 0; + // PDCP interface virtual void write_sdu(byte_buffer_t *sdu) = 0; virtual void write_sdu_nb(byte_buffer_t *sdu) = 0; diff --git a/lib/include/srslte/upper/rlc_interface.h b/lib/include/srslte/upper/rlc_interface.h index b1d211527..0b2460101 100644 --- a/lib/include/srslte/upper/rlc_interface.h +++ b/lib/include/srslte/upper/rlc_interface.h @@ -28,11 +28,19 @@ #define SRSLTE_RLC_INTERFACE_H // for custom constructors -#include "srslte/asn1/liblte_rrc.h" +#include namespace srslte { +typedef enum{ + SRSLTE_RLC_MODE_TM = 0, + SRSLTE_RLC_MODE_UM, + SRSLTE_RLC_MODE_AM, + SRSLTE_RLC_MODE_N_ITEMS +} srslte_rlc_mode_t; +static const char srslte_rlc_mode_text[SRSLTE_RLC_MODE_N_ITEMS][20] = { "TM", "UM", "AM"}; + typedef enum{ RLC_UMD_SN_SIZE_5_BITS = 0, RLC_UMD_SN_SIZE_10_BITS, @@ -80,19 +88,22 @@ typedef struct { class srslte_rlc_config_t { public: - LIBLTE_RRC_RLC_MODE_ENUM rlc_mode; + srslte_rlc_mode_t rlc_mode; srslte_rlc_am_config_t am; srslte_rlc_um_config_t um; // Default ctor - srslte_rlc_config_t(): rlc_mode(LIBLTE_RRC_RLC_MODE_AM), am(), um() {}; + srslte_rlc_config_t(): rlc_mode(SRSLTE_RLC_MODE_TM), am(), um() {}; // Constructor based on liblte's RLC config - srslte_rlc_config_t(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) : rlc_mode(cnfg->rlc_mode), am(), um() + srslte_rlc_config_t(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) : rlc_mode(SRSLTE_RLC_MODE_AM), am(), um() { + // update RLC mode to internal mode struct + rlc_mode = (cnfg->rlc_mode == LIBLTE_RRC_RLC_MODE_AM) ? SRSLTE_RLC_MODE_AM : SRSLTE_RLC_MODE_UM; + switch(rlc_mode) { - case LIBLTE_RRC_RLC_MODE_AM: + case SRSLTE_RLC_MODE_AM: am.t_poll_retx = liblte_rrc_t_poll_retransmit_num[cnfg->ul_am_rlc.t_poll_retx]; am.poll_pdu = liblte_rrc_poll_pdu_num[cnfg->ul_am_rlc.poll_pdu]; am.poll_byte = liblte_rrc_poll_byte_num[cnfg->ul_am_rlc.poll_byte]*1000; // KB @@ -100,7 +111,7 @@ public: am.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_am_rlc.t_reordering]; am.t_status_prohibit = liblte_rrc_t_status_prohibit_num[cnfg->dl_am_rlc.t_status_prohibit]; break; - case LIBLTE_RRC_RLC_MODE_UM_BI: + case SRSLTE_RLC_MODE_UM: um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_bi_rlc.t_reordering]; um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_bi_rlc.sn_field_len; um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512; @@ -108,16 +119,6 @@ public: um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_bi_rlc.sn_field_len; um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024; break; - case LIBLTE_RRC_RLC_MODE_UM_UNI_UL: - um.tx_sn_field_length = (rlc_umd_sn_size_t)cnfg->ul_um_uni_rlc.sn_field_len; - um.tx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.tx_sn_field_length) ? 32 : 1024; - break; - case LIBLTE_RRC_RLC_MODE_UM_UNI_DL: - um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_uni_rlc.t_reordering]; - um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_uni_rlc.sn_field_len; - um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512; - um.rx_mod = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 32 : 1024; - break; default: // Handle default case break; @@ -128,7 +129,7 @@ public: static srslte_rlc_config_t mch_config() { srslte_rlc_config_t cfg; - cfg.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_UNI_DL; + cfg.rlc_mode = SRSLTE_RLC_MODE_UM; cfg.um.t_reordering = 0; cfg.um.rx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; cfg.um.rx_window_size = 0; diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index d78ab59c4..5db629231 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -36,8 +36,7 @@ namespace srslte { -class rlc_tm - :public rlc_common +class rlc_tm : public rlc_common { public: rlc_tm(uint32_t queue_len = 16); @@ -47,7 +46,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers); - void configure(srslte_rlc_config_t cnfg); + bool configure(srslte_rlc_config_t cnfg); void stop(); void reestablish(); void empty_queue(); @@ -55,6 +54,10 @@ public: rlc_mode_t get_mode(); uint32_t get_bearer(); + uint32_t get_num_tx_bytes(); + uint32_t get_num_rx_bytes(); + void reset_metrics(); + // PDCP interface void write_sdu(byte_buffer_t *sdu); void write_sdu_nb(byte_buffer_t *sdu); @@ -75,6 +78,9 @@ private: bool tx_enabled; + uint32_t num_tx_bytes; + uint32_t num_rx_bytes; + // Thread-safe queues for MAC messages rlc_tx_queue ul_queue; }; diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index aae8877bb..a880b2238 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -55,7 +55,7 @@ public: srsue::pdcp_interface_rlc *pdcp_, srsue::rrc_interface_rlc *rrc_, mac_interface_timers *mac_timers_); - void configure(srslte_rlc_config_t cnfg); + bool configure(srslte_rlc_config_t cnfg); void reestablish(); void stop(); void empty_queue(); @@ -75,6 +75,10 @@ public: void write_pdu(uint8_t *payload, uint32_t nof_bytes); int get_increment_sequence_num(); + uint32_t get_num_tx_bytes(); + uint32_t get_num_rx_bytes(); + void reset_metrics(); + private: // Transmitter sub-class @@ -84,13 +88,15 @@ private: rlc_um_tx(uint32_t queue_len); ~rlc_um_tx(); void init(srslte::log *log_); - void configure(srslte_rlc_config_t cfg, std::string rb_name); + bool configure(srslte_rlc_config_t cfg, std::string rb_name); int build_data_pdu(uint8_t *payload, uint32_t nof_bytes); void stop(); void reestablish(); void empty_queue(); void write_sdu(byte_buffer_t *sdu); void try_write_sdu(byte_buffer_t *sdu); + uint32_t get_num_tx_bytes(); + void reset_metrics(); uint32_t get_buffer_size_bytes(); private: @@ -119,6 +125,8 @@ private: bool tx_enabled; + uint32_t num_tx_bytes; + // helper functions void debug_state(); const char* get_rb_name(); @@ -136,10 +144,12 @@ private: srslte::mac_interface_timers *mac_timers_); void stop(); void reestablish(); - void configure(srslte_rlc_config_t cfg, std::string rb_name); + bool configure(srslte_rlc_config_t cfg, std::string rb_name); void handle_data_pdu(uint8_t *payload, uint32_t nof_bytes); void reassemble_rx_sdus(); bool inside_reordering_window(uint16_t sn); + uint32_t get_num_rx_bytes(); + void reset_metrics(); // Timeout callback interface void timer_expired(uint32_t timeout_id); @@ -163,12 +173,14 @@ private: byte_buffer_t *rx_sdu; uint32_t vr_ur_in_rx_sdu; - // Rx state variables + // Rx state variables and counter uint32_t vr_ur; // Receive state. SN of earliest PDU still considered for reordering. uint32_t vr_ux; // t_reordering state. SN following PDU which triggered t_reordering. uint32_t vr_uh; // Highest rx state. SN following PDU with highest SN among rxed PDUs. bool pdu_lost; + uint32_t num_rx_bytes; + // Upper layer handles and variables srsue::pdcp_interface_rlc *pdcp; srsue::rrc_interface_rlc *rrc; @@ -177,6 +189,8 @@ private: // Mutexes pthread_mutex_t mutex; + bool rx_enabled; + /**************************************************************************** * Timers * Ref: 3GPP TS 36.322 v10.0.0 Section 7 @@ -196,6 +210,7 @@ private: // Common variables needed by parent class srsue::rrc_interface_rlc *rrc; + srslte::log *log; uint32_t lcid; srslte_rlc_um_config_t cfg; std::string rb_name; diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 768f50089..25fc6d770 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -61,6 +61,9 @@ rlc_am::rlc_am(uint32_t queue_len) : tx_sdu_queue(queue_len) vr_ms = 0; vr_h = 0; + num_tx_bytes = 0; + num_rx_bytes = 0; + pdu_without_poll = 0; byte_without_poll = 0; @@ -88,13 +91,15 @@ void rlc_am::init(srslte::log *log_, tx_enabled = true; } -void rlc_am::configure(srslte_rlc_config_t cfg_) +bool rlc_am::configure(srslte_rlc_config_t cfg_) { cfg = cfg_.am; 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", rrc->get_rb_name(lcid).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; } @@ -363,6 +368,7 @@ unlock_and_return: int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes) { pthread_mutex_lock(&mutex); + int pdu_size = 0; log->debug("MAC opportunity - %d bytes\n", nof_bytes); log->debug("tx_window size - %zu PDUs\n", tx_window.size()); @@ -370,7 +376,8 @@ int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes) // Tx STATUS if requested if(do_status && !status_prohibited()) { pthread_mutex_unlock(&mutex); - return build_status_pdu(payload, nof_bytes); + pdu_size = build_status_pdu(payload, nof_bytes); + goto unlock_and_exit; } // if tx_window is full and retx_queue empty, retransmit next PDU to be ack'ed @@ -390,25 +397,27 @@ int rlc_am::read_pdu(uint8_t *payload, uint32_t nof_bytes) // RETX if required if(retx_queue.size() > 0) { - int ret = build_retx_pdu(payload, nof_bytes); - if (ret > 0) { - pthread_mutex_unlock(&mutex); - return ret; + pdu_size = build_retx_pdu(payload, nof_bytes); + if (pdu_size > 0) { + goto unlock_and_exit; } } // Build a PDU from SDUs - int ret = build_data_pdu(payload, nof_bytes); + pdu_size = build_data_pdu(payload, nof_bytes); +unlock_and_exit: + num_tx_bytes += pdu_size; pthread_mutex_unlock(&mutex); - return ret; + return pdu_size; } void rlc_am::write_pdu(uint8_t *payload, uint32_t nof_bytes) { - if(nof_bytes < 1) - return; + if (nof_bytes < 1) return; + pthread_mutex_lock(&mutex); + num_rx_bytes += nof_bytes; if(rlc_am_is_control_pdu(payload)) { handle_control_pdu(payload, nof_bytes); @@ -424,6 +433,25 @@ void rlc_am::write_pdu(uint8_t *payload, uint32_t nof_bytes) pthread_mutex_unlock(&mutex); } +uint32_t rlc_am::get_num_tx_bytes() +{ + return num_tx_bytes; +} + +uint32_t rlc_am::get_num_rx_bytes() +{ + return num_rx_bytes; +} + +void rlc_am::reset_metrics() +{ + pthread_mutex_lock(&mutex); + num_rx_bytes = 0; + num_tx_bytes = 0; + pthread_mutex_unlock(&mutex); +} + + /**************************************************************************** * Timer checks ***************************************************************************/ diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 988acf2af..9b132b39b 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -35,6 +35,8 @@ rlc_tm::rlc_tm(uint32_t queue_len) : ul_queue(queue_len) pdcp = NULL; rrc = NULL; lcid = 0; + num_tx_bytes = 0; + num_rx_bytes = 0; pool = byte_buffer_pool::get_instance(); } @@ -56,16 +58,17 @@ void rlc_tm::init(srslte::log *log_, tx_enabled = true; } -void rlc_tm::configure(srslte_rlc_config_t cnfg) +bool rlc_tm::configure(srslte_rlc_config_t cnfg) { log->error("Attempted to configure TM RLC entity\n"); + return true; } void rlc_tm::empty_queue() { // Drop all messages in TX queue byte_buffer_t *buf; - while(ul_queue.try_read(&buf)) { + while (ul_queue.try_read(&buf)) { pool->deallocate(buf); } ul_queue.reset(); @@ -139,11 +142,26 @@ uint32_t rlc_tm::get_total_buffer_state() return get_buffer_state(); } +uint32_t rlc_tm::get_num_tx_bytes() +{ + return num_tx_bytes; +} + +uint32_t rlc_tm::get_num_rx_bytes() +{ + return num_rx_bytes; +} + +void rlc_tm::reset_metrics() +{ + num_tx_bytes = 0; + num_rx_bytes = 0; +} + int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) { uint32_t pdu_size = ul_queue.size_tail_bytes(); - if(pdu_size > nof_bytes) - { + if (pdu_size > nof_bytes) { log->error("TX %s PDU size larger than MAC opportunity\n", rrc->get_rb_name(lcid).c_str()); return -1; } @@ -156,6 +174,8 @@ int rlc_tm::read_pdu(uint8_t *payload, uint32_t nof_bytes) pool->deallocate(buf); log->info_hex(payload, pdu_size, "TX %s, %s PDU, queue size=%d, bytes=%d", rrc->get_rb_name(lcid).c_str(), rlc_mode_text[RLC_MODE_TM], ul_queue.size(), ul_queue.size_bytes()); + + num_tx_bytes += pdu_size; return pdu_size; } else { log->warning("Queue empty while trying to read\n"); @@ -174,6 +194,7 @@ void rlc_tm::write_pdu(uint8_t *payload, uint32_t nof_bytes) memcpy(buf->msg, payload, nof_bytes); buf->N_bytes = nof_bytes; buf->set_timestamp(); + num_rx_bytes += nof_bytes; pdcp->write_pdu(lcid, buf); } else { log->error("Fatal Error: Couldn't allocate buffer in rlc_tm::write_pdu().\n"); diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index f2f6d65ef..bf127900b 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -37,6 +37,7 @@ rlc_um::rlc_um(uint32_t queue_len) :lcid(0) ,tx(queue_len) ,rrc(NULL) + ,log(NULL) { bzero(&cfg, sizeof(srslte_rlc_um_config_t)); } @@ -57,48 +58,48 @@ void rlc_um::init(srslte::log *log_, rx.init(log_, lcid_, pdcp_, rrc_, mac_timers_); lcid = lcid_; rrc = rrc_; // needed to determine bearer name during configuration + log = log_; } -void rlc_um::configure(srslte_rlc_config_t cnfg_) +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); - rx.configure(cnfg_, rb_name); - tx.configure(cnfg_, rb_name); + if (not rx.configure(cnfg_, rb_name)) { + return false; + } + + if (not tx.configure(cnfg_, rb_name)) { + return false; + } + + log->warning("%s configured in %s mode: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", + rb_name.c_str(), srslte_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]); // store config cfg = cnfg_.um; + + return true; } -void rlc_um::rlc_um_rx::configure(srslte_rlc_config_t cnfg_, std::string rb_name_) +bool rlc_um::rlc_um_rx::configure(srslte_rlc_config_t cnfg_, std::string rb_name_) { cfg = cnfg_.um; - rb_name = rb_name_; - switch(cnfg_.rlc_mode) { - case LIBLTE_RRC_RLC_MODE_UM_BI: - log->warning("%s configured in %s mode: " - "t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", - get_rb_name(), liblte_rrc_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]); - break; - case LIBLTE_RRC_RLC_MODE_UM_UNI_UL: - log->warning("%s configured in %s mode: tx_sn_field_length=%u bits\n", - get_rb_name(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], - - rlc_umd_sn_size_num[cfg.rx_sn_field_length]); - break; - case LIBLTE_RRC_RLC_MODE_UM_UNI_DL: - log->warning("%s configured in %s mode: " - "t_reordering=%d ms, rx_sn_field_length=%u bits\n", - get_rb_name(), liblte_rrc_rlc_mode_text[cnfg_.rlc_mode], - cfg.t_reordering, rlc_umd_sn_size_num[cfg.rx_sn_field_length]); - break; - default: - log->error("RLC configuration mode not recognized\n"); + + if (cfg.rx_mod == 0) { + log->error("Error configuring %s RLC UM: rx_mod==0\n", get_rb_name()); + return false; } + + rb_name = rb_name_; + + rx_enabled = true; + + return true; } @@ -175,6 +176,22 @@ void rlc_um::write_pdu(uint8_t *payload, uint32_t nof_bytes) rx.handle_data_pdu(payload, nof_bytes); } +uint32_t rlc_um::get_num_tx_bytes() +{ + return tx.get_num_tx_bytes(); +} + +uint32_t rlc_um::get_num_rx_bytes() +{ + return rx.get_num_rx_bytes(); +} + +void rlc_um::reset_metrics() +{ + tx.reset_metrics(); + rx.reset_metrics(); +} + /**************************************************************************** * Helper functions @@ -203,6 +220,7 @@ rlc_um::rlc_um_tx::rlc_um_tx(uint32_t queue_len) ,tx_sdu(NULL) ,vt_us(0) ,tx_enabled(false) + ,num_tx_bytes(0) { pthread_mutex_init(&mutex, NULL); } @@ -217,17 +235,26 @@ rlc_um::rlc_um_tx::~rlc_um_tx() void rlc_um::rlc_um_tx::init(srslte::log *log_) { log = log_; - tx_enabled = true; } -void rlc_um::rlc_um_tx::configure(srslte_rlc_config_t cnfg_, std::string rb_name_) +bool rlc_um::rlc_um_tx::configure(srslte_rlc_config_t cnfg_, std::string rb_name_) { cfg = cnfg_.um; + + if (cfg.tx_mod == 0) { + log->error("Error configuring %s RLC UM: tx_mod==0\n", get_rb_name()); + return false; + } + if(cfg.is_mrb){ tx_sdu_queue.resize(512); } + rb_name = rb_name_; + tx_enabled = true; + + return true; } @@ -266,6 +293,20 @@ void rlc_um::rlc_um_tx::empty_queue() } +uint32_t rlc_um::rlc_um_tx::get_num_tx_bytes() +{ + return num_tx_bytes; +} + + +void rlc_um::rlc_um_tx::reset_metrics() +{ + pthread_mutex_lock(&mutex); + num_tx_bytes = 0; + pthread_mutex_unlock(&mutex); +} + + uint32_t rlc_um::rlc_um_tx::get_buffer_size_bytes() { // Bytes needed for tx SDUs @@ -434,6 +475,8 @@ int rlc_um::rlc_um_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes) debug_state(); + num_tx_bytes += ret; + pthread_mutex_unlock(&mutex); return ret; } @@ -469,6 +512,8 @@ rlc_um::rlc_um_rx::rlc_um_rx() ,pdu_lost(false) ,mac_timers(NULL) ,lcid(0) + ,num_rx_bytes(0) + ,rx_enabled(false) { pthread_mutex_init(&mutex, NULL); } @@ -508,6 +553,8 @@ void rlc_um::rlc_um_rx::stop() vr_ux = 0; vr_uh = 0; pdu_lost = false; + rx_enabled = false; + if(rx_sdu) { pool->deallocate(rx_sdu); rx_sdu = NULL; @@ -531,10 +578,18 @@ void rlc_um::rlc_um_rx::stop() void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) { pthread_mutex_lock(&mutex); + rlc_umd_pdu_t pdu; int header_len = 0; std::map::iterator it; rlc_umd_pdu_header_t header; + + if (!rx_enabled) { + goto unlock_and_exit; + } + + num_rx_bytes += nof_bytes; + rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.rx_sn_field_length, &header); log->info_hex(payload, nof_bytes, "RX %s Rx data PDU SN: %d", get_rb_name(), header.sn); @@ -596,7 +651,7 @@ void rlc_um::rlc_um_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes) debug_state(); - unlock_and_exit: +unlock_and_exit: pthread_mutex_unlock(&mutex); } @@ -814,6 +869,20 @@ bool rlc_um::rlc_um_rx::inside_reordering_window(uint16_t sn) } +uint32_t rlc_um::rlc_um_rx::get_num_rx_bytes() +{ + return num_rx_bytes; +} + + +void rlc_um::rlc_um_rx::reset_metrics() +{ + pthread_mutex_lock(&mutex); + num_rx_bytes = 0; + pthread_mutex_unlock(&mutex); +} + + /**************************************************************************** * Timeout callback interface ***************************************************************************/ diff --git a/lib/test/upper/rlc_am_test.cc b/lib/test/upper/rlc_am_test.cc index ef04062cc..b2d68d3fa 100644 --- a/lib/test/upper/rlc_am_test.cc +++ b/lib/test/upper/rlc_am_test.cc @@ -169,6 +169,10 @@ void basic_test() assert(tester.sdus[i]->N_bytes == 1); assert(*(tester.sdus[i]->msg) == i); } + + // Check statistics + assert(rlc1.get_num_tx_bytes() == rlc2.get_num_rx_bytes()); + assert(rlc2.get_num_tx_bytes() == rlc1.get_num_rx_bytes()); } void concat_test() @@ -234,6 +238,10 @@ void concat_test() assert(tester.sdus[i]->N_bytes == 1); assert(*(tester.sdus[i]->msg) == i); } + + // check statistics + assert(rlc1.get_num_tx_bytes() == rlc2.get_num_rx_bytes()); + assert(rlc2.get_num_tx_bytes() == rlc1.get_num_rx_bytes()); } void segment_test() @@ -317,6 +325,9 @@ void segment_test() for(int j=0;j<10;j++) assert(tester.sdus[i]->msg[j] == j); } + + assert(rlc1.get_num_tx_bytes() == rlc2.get_num_rx_bytes()); + assert(rlc2.get_num_tx_bytes() == rlc1.get_num_rx_bytes()); } void retx_test() diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index 3a6f40a99..57624fc7c 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -325,7 +325,7 @@ void stress_test(stress_test_args_t args) srslte_rlc_config_t cnfg_; if (args.mode == "AM") { // config RLC AM bearer - cnfg_.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; + cnfg_.rlc_mode = SRSLTE_RLC_MODE_AM; cnfg_.am.max_retx_thresh = 4; cnfg_.am.poll_byte = 25*1000; cnfg_.am.poll_pdu = 4; @@ -334,7 +334,7 @@ void stress_test(stress_test_args_t args) cnfg_.am.t_status_prohibit = 5; } else if (args.mode == "UM") { // config UM bearer - cnfg_.rlc_mode = LIBLTE_RRC_RLC_MODE_UM_BI; + cnfg_.rlc_mode = SRSLTE_RLC_MODE_UM; cnfg_.um.t_reordering = 5; cnfg_.um.rx_mod = 32; cnfg_.um.rx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; @@ -388,15 +388,23 @@ void stress_test(stress_test_args_t args) pcap.close(); } - printf("RLC1 received %d SDUs in %ds (%.2f PDU/s)\n", + rlc_metrics_t metrics; + rlc1.get_metrics(metrics); + + printf("RLC1 received %d SDUs in %ds (%.2f PDU/s), Throughput: DL=%4.2f Mbps, UL=%4.2f Mbps\n", tester1.get_nof_rx_pdus(), args.test_duration_sec, - (float)tester1.get_nof_rx_pdus()/args.test_duration_sec); + (float)tester1.get_nof_rx_pdus()/args.test_duration_sec, + metrics.dl_tput_mbps, + metrics.ul_tput_mbps); - printf("RLC2 received %d SDUs in %ds (%.2f PDU/s)\n", + rlc2.get_metrics(metrics); + printf("RLC2 received %d SDUs in %ds (%.2f PDU/s), Throughput: DL=%4.2f Mbps, UL=%4.2f Mbps\n", tester2.get_nof_rx_pdus(), args.test_duration_sec, - (float)tester2.get_nof_rx_pdus()/args.test_duration_sec); + (float)tester2.get_nof_rx_pdus()/args.test_duration_sec, + metrics.dl_tput_mbps, + metrics.ul_tput_mbps); } diff --git a/lib/test/upper/rlc_um_test.cc b/lib/test/upper/rlc_um_test.cc index 58cc217f1..cbeb2d3f6 100644 --- a/lib/test/upper/rlc_um_test.cc +++ b/lib/test/upper/rlc_um_test.cc @@ -130,8 +130,8 @@ void basic_test() cnfg.dl_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10; cnfg.ul_um_bi_rlc.sn_field_len = LIBLTE_RRC_SN_FIELD_LENGTH_SIZE10; - rlc1.configure(&cnfg); - rlc2.configure(&cnfg); + assert(rlc1.configure(&cnfg) == true); + assert(rlc2.configure(&cnfg) == true); tester.set_expected_sdu_len(1); diff --git a/srsenb/src/upper/rlc.cc b/srsenb/src/upper/rlc.cc index 6c97391d7..293b1c634 100644 --- a/srsenb/src/upper/rlc.cc +++ b/srsenb/src/upper/rlc.cc @@ -123,7 +123,7 @@ void rlc::add_bearer_mrb(uint16_t rnti, uint32_t lcid) { pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { - users[rnti].rlc->add_bearer_mrb_enb(lcid); + users[rnti].rlc->add_bearer_mrb(lcid); } pthread_rwlock_unlock(&rwlock); } From eb30d86d44b157182facea6051532d009fe4c5bf Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 23 Jul 2018 17:49:26 +0200 Subject: [PATCH 03/13] process RRC PDUs in RRC thread --- srsue/hdr/upper/rrc.h | 3 +++ srsue/src/upper/rrc.cc | 19 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/srsue/hdr/upper/rrc.h b/srsue/hdr/upper/rrc.h index e56db9e9e..e4d06eb1f 100644 --- a/srsue/hdr/upper/rrc.h +++ b/srsue/hdr/upper/rrc.h @@ -326,10 +326,12 @@ private: typedef struct { enum { + PDU, PCCH, STOP } command; byte_buffer_t *pdu; + uint16_t lcid; } cmd_msg_t; bool running; @@ -606,6 +608,7 @@ private: void send_rrc_ue_cap_info(); // Parsers + void process_pdu(uint32_t lcid, byte_buffer_t *pdu); void parse_dl_ccch(byte_buffer_t *pdu); void parse_dl_dcch(uint32_t lcid, byte_buffer_t *pdu); void parse_dl_info_transfer(uint32_t lcid, byte_buffer_t *pdu); diff --git a/srsue/src/upper/rrc.cc b/srsue/src/upper/rrc.cc index 856aeedf9..1b2d2607d 100644 --- a/srsue/src/upper/rrc.cc +++ b/srsue/src/upper/rrc.cc @@ -32,7 +32,7 @@ #include #include // for printing uint64_t #include -#include "srsue/hdr/upper/rrc.h" +#include #include "srslte/asn1/liblte_rrc.h" #include "srslte/common/security.h" #include "srslte/common/bcd_helpers.h" @@ -248,11 +248,14 @@ void rrc::run_thread() { while(running) { cmd_msg_t msg = cmd_q.wait_pop(); switch(msg.command) { - case cmd_msg_t::STOP: - return; + case cmd_msg_t::PDU: + process_pdu(msg.lcid, msg.pdu); + break; case cmd_msg_t::PCCH: process_pcch(msg.pdu); break; + case cmd_msg_t::STOP: + return; } } } @@ -1939,6 +1942,16 @@ void rrc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) { void rrc::write_pdu(uint32_t lcid, byte_buffer_t *pdu) { rrc_log->info_hex(pdu->msg, pdu->N_bytes, "RX %s PDU", get_rb_name(lcid).c_str()); + // add PDU to command queue + cmd_msg_t msg; + msg.pdu = pdu; + msg.command = cmd_msg_t::PDU; + msg.lcid = lcid; + cmd_q.push(msg); +} + +void rrc::process_pdu(uint32_t lcid, byte_buffer_t *pdu) +{ switch (lcid) { case RB_ID_SRB0: parse_dl_ccch(pdu); From 2b86272c5e56a8a65c4dbcddba611aa49be73324 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 24 Jul 2018 09:43:33 +0200 Subject: [PATCH 04/13] protect PCAP bearer additions with write lock --- lib/src/upper/pdcp.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index e073aeb27..e0a000c93 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -137,7 +137,7 @@ void pdcp::write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu) } void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg) { - pthread_rwlock_rdlock(&rwlock); + pthread_rwlock_wrlock(&rwlock); if (not valid_lcid(lcid)) { if (not pdcp_array.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { pdcp_log->error("Error inserting PDCP entity in to array\n."); @@ -154,7 +154,7 @@ void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg) void pdcp::add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cfg) { - pthread_rwlock_rdlock(&rwlock); + pthread_rwlock_wrlock(&rwlock); if (not valid_mch_lcid(lcid)) { if (not pdcp_array_mrb.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { pdcp_log->error("Error inserting PDCP entity in to array\n."); From b8438e9cc3953d8c10e2dad2c73f37269390c840 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 24 Jul 2018 15:49:09 +0200 Subject: [PATCH 05/13] extend PDCP interface to allow non-blocking write of SDUs --- lib/include/srslte/interfaces/ue_interfaces.h | 6 ++--- lib/include/srslte/upper/pdcp.h | 2 +- lib/include/srslte/upper/pdcp_entity.h | 2 +- lib/include/srslte/upper/pdcp_interface.h | 2 +- lib/include/srslte/upper/rlc.h | 3 +-- lib/src/upper/pdcp.cc | 12 +++++---- lib/src/upper/pdcp_entity.cc | 6 ++--- lib/src/upper/rlc.cc | 27 +++++++------------ lib/src/upper/rlc_am.cc | 2 ++ 9 files changed, 29 insertions(+), 33 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index a4fb2b2cb..1cfcc56e0 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -228,7 +228,7 @@ public: class pdcp_interface_gw { public: - virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; + virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu, bool blocking) = 0; virtual bool is_drb_enabled(uint32_t lcid) = 0; }; @@ -238,7 +238,7 @@ class pdcp_interface_rrc public: virtual void reestablish() = 0; virtual void reset() = 0; - virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; + virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu, bool blocking = true) = 0; virtual void add_bearer(uint32_t lcid, srslte::srslte_pdcp_config_t cnfg = srslte::srslte_pdcp_config_t()) = 0; virtual void config_security(uint32_t lcid, uint8_t *k_enc_, @@ -282,7 +282,7 @@ class rlc_interface_pdcp public: /* PDCP calls RLC to push an RLC SDU. SDU gets placed into the RLC buffer and MAC pulls * RLC PDUs according to TB size. */ - virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu) = 0; + virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu, bool blocking = true) = 0; virtual bool rb_is_um(uint32_t lcid) = 0; }; diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index cd284619f..53149154a 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -56,7 +56,7 @@ public: // RRC interface void reestablish(); void reset(); - void write_sdu(uint32_t lcid, byte_buffer_t *sdu); + void write_sdu(uint32_t lcid, byte_buffer_t *sdu, bool blocking = true); void write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu); void add_bearer(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); void add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cnfg = srslte_pdcp_config_t()); diff --git a/lib/include/srslte/upper/pdcp_entity.h b/lib/include/srslte/upper/pdcp_entity.h index 6586becc0..fd69c92e9 100644 --- a/lib/include/srslte/upper/pdcp_entity.h +++ b/lib/include/srslte/upper/pdcp_entity.h @@ -76,7 +76,7 @@ public: bool is_active(); // RRC interface - void write_sdu(byte_buffer_t *sdu); + void write_sdu(byte_buffer_t *sdu, bool blocking); void config_security(uint8_t *k_enc_, uint8_t *k_int_, CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, diff --git a/lib/include/srslte/upper/pdcp_interface.h b/lib/include/srslte/upper/pdcp_interface.h index 915fbe420..0c2cb2428 100644 --- a/lib/include/srslte/upper/pdcp_interface.h +++ b/lib/include/srslte/upper/pdcp_interface.h @@ -55,7 +55,7 @@ public: virtual bool is_active() = 0; // RRC interface - virtual void write_sdu(byte_buffer_t *sdu) = 0; + virtual void write_sdu(byte_buffer_t *sdu, bool blocking) = 0; virtual void config_security(uint8_t *k_enc_, uint8_t *k_int_, CIPHERING_ALGORITHM_ID_ENUM cipher_algo_, diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 0d8dcad91..4a414f3fe 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -63,8 +63,7 @@ public: void get_metrics(rlc_metrics_t &m); // PDCP interface - void write_sdu(uint32_t lcid, byte_buffer_t *sdu); - void write_sdu_nb(uint32_t lcid, byte_buffer_t *sdu); + void write_sdu(uint32_t lcid, byte_buffer_t *sdu, bool blocking = true); void write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu); bool rb_is_um(uint32_t lcid); diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index e0a000c93..24dbd27d3 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -115,11 +115,11 @@ bool pdcp::is_drb_enabled(uint32_t lcid) return ret; } -void pdcp::write_sdu(uint32_t lcid, byte_buffer_t *sdu) +void pdcp::write_sdu(uint32_t lcid, byte_buffer_t *sdu, bool blocking) { pthread_rwlock_rdlock(&rwlock); if (valid_lcid(lcid)) { - pdcp_array.at(lcid)->write_sdu(sdu); + pdcp_array.at(lcid)->write_sdu(sdu, blocking); } else { pdcp_log->warning("Writing sdu: lcid=%d. Deallocating sdu\n", lcid); byte_buffer_pool::get_instance()->deallocate(sdu); @@ -131,7 +131,7 @@ void pdcp::write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu) { pthread_rwlock_rdlock(&rwlock); if (valid_mch_lcid(lcid)){ - pdcp_array_mrb.at(lcid)->write_sdu(sdu); + pdcp_array_mrb.at(lcid)->write_sdu(sdu, true); } pthread_rwlock_unlock(&rwlock); } @@ -141,13 +141,14 @@ void pdcp::add_bearer(uint32_t lcid, srslte_pdcp_config_t cfg) if (not valid_lcid(lcid)) { if (not pdcp_array.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { pdcp_log->error("Error inserting PDCP entity in to array\n."); - return; + goto unlock_and_exit; } pdcp_array.at(lcid)->init(rlc, rrc, gw, pdcp_log, lcid, cfg); pdcp_log->info("Added bearer %s\n", rrc->get_rb_name(lcid).c_str()); } else { pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rrc->get_rb_name(lcid).c_str()); } +unlock_and_exit: pthread_rwlock_unlock(&rwlock); } @@ -158,13 +159,14 @@ void pdcp::add_bearer_mrb(uint32_t lcid, srslte_pdcp_config_t cfg) if (not valid_mch_lcid(lcid)) { if (not pdcp_array_mrb.insert(pdcp_map_pair_t(lcid, new pdcp_entity())).second) { pdcp_log->error("Error inserting PDCP entity in to array\n."); - return; + goto unlock_and_exit; } pdcp_array_mrb.at(lcid)->init(rlc, rrc, gw, pdcp_log, lcid, cfg); pdcp_log->info("Added bearer %s\n", rrc->get_rb_name(lcid).c_str()); } else { pdcp_log->warning("Bearer %s already configured. Reconfiguration not supported\n", rrc->get_rb_name(lcid).c_str()); } +unlock_and_exit: pthread_rwlock_unlock(&rwlock); } diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index c2c829549..b77a760b9 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -108,8 +108,8 @@ bool pdcp_entity::is_active() return active; } -// RRC interface -void pdcp_entity::write_sdu(byte_buffer_t *sdu) +// GW/RRC interface +void pdcp_entity::write_sdu(byte_buffer_t *sdu, bool blocking) { log->info_hex(sdu->msg, sdu->N_bytes, "TX %s SDU, SN: %d, do_integrity = %s, do_encryption = %s", @@ -141,7 +141,7 @@ void pdcp_entity::write_sdu(byte_buffer_t *sdu) } tx_count++; - rlc->write_sdu(lcid, sdu); + rlc->write_sdu(lcid, sdu, blocking); } void pdcp_entity::config_security(uint8_t *k_enc_, diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 1a602d7c0..2f0e20313 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -165,12 +165,15 @@ void rlc::reestablish() void rlc::reset() { pthread_rwlock_wrlock(&rwlock); + for (rlc_map_t::iterator it = rlc_array.begin(); it != rlc_array.end(); ++it) { + it->second->stop(); delete(it->second); } rlc_array.clear(); for (rlc_map_t::iterator it = rlc_array_mrb.begin(); it != rlc_array_mrb.end(); ++it) { + it->second->stop(); delete(it->second); } rlc_array_mrb.clear(); @@ -195,24 +198,15 @@ void rlc::empty_queue() PDCP interface *******************************************************************************/ -void rlc::write_sdu(uint32_t lcid, byte_buffer_t *sdu) +void rlc::write_sdu(uint32_t lcid, byte_buffer_t *sdu, bool blocking) { 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) -{ - pthread_rwlock_rdlock(&rwlock); - if (valid_lcid(lcid)) { - rlc_array.at(lcid)->write_sdu_nb(sdu); + if (blocking) { + rlc_array.at(lcid)->write_sdu(sdu); + } else { + 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); @@ -220,7 +214,6 @@ void rlc::write_sdu_nb(uint32_t lcid, byte_buffer_t *sdu) pthread_rwlock_unlock(&rwlock); } - void rlc::write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu) { pthread_rwlock_rdlock(&rwlock); @@ -429,7 +422,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) break; default: rlc_log->error("Cannot add RLC entity - invalid mode\n"); - return; + goto unlock_and_exit; } if (rlc_entity) { diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index 25fc6d770..c2ce16dcc 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -105,11 +105,13 @@ bool rlc_am::configure(srslte_rlc_config_t cfg_) void rlc_am::empty_queue() { // Drop all messages in TX SDU queue + pthread_mutex_lock(&mutex); byte_buffer_t *buf; while(tx_sdu_queue.try_read(&buf)) { pool->deallocate(buf); } tx_sdu_queue.reset(); + pthread_mutex_unlock(&mutex); } void rlc_am::reestablish() { From 4da8bf26f876e32a28b8e5063366d80ffb43043f Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 24 Jul 2018 15:50:14 +0200 Subject: [PATCH 06/13] use non-blocking PDCP write in GW --- srsenb/hdr/upper/pdcp.h | 2 +- srsenb/src/upper/pdcp.cc | 3 +-- srsenb/src/upper/rlc.cc | 2 +- srsue/src/upper/gw.cc | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/srsenb/hdr/upper/pdcp.h b/srsenb/hdr/upper/pdcp.h index ce6b01ca6..1dc555fee 100644 --- a/srsenb/hdr/upper/pdcp.h +++ b/srsenb/hdr/upper/pdcp.h @@ -68,7 +68,7 @@ private: uint16_t rnti; srsenb::rlc_interface_pdcp *rlc; // rlc_interface_pdcp - void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu); + void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu, bool blocking); bool rb_is_um(uint32_t lcid); }; diff --git a/srsenb/src/upper/pdcp.cc b/srsenb/src/upper/pdcp.cc index 7f62477f9..4d242bdc1 100644 --- a/srsenb/src/upper/pdcp.cc +++ b/srsenb/src/upper/pdcp.cc @@ -154,9 +154,8 @@ void pdcp::user_interface_gtpu::write_pdu(uint32_t lcid, srslte::byte_buffer_t * gtpu->write_pdu(rnti, lcid, pdu); } -void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::byte_buffer_t* sdu) +void pdcp::user_interface_rlc::write_sdu(uint32_t lcid, srslte::byte_buffer_t* sdu, bool blocking) { - rlc->write_sdu(rnti, lcid, sdu); } diff --git a/srsenb/src/upper/rlc.cc b/srsenb/src/upper/rlc.cc index 293b1c634..aa62ac1e1 100644 --- a/srsenb/src/upper/rlc.cc +++ b/srsenb/src/upper/rlc.cc @@ -190,7 +190,7 @@ void rlc::write_sdu(uint16_t rnti, uint32_t lcid, srslte::byte_buffer_t* sdu) pthread_rwlock_rdlock(&rwlock); if (users.count(rnti)) { if(rnti != SRSLTE_MRNTI){ - users[rnti].rlc->write_sdu_nb(lcid, sdu); + users[rnti].rlc->write_sdu(lcid, sdu, false); tx_queue = users[rnti].rlc->get_total_buffer_state(lcid); }else { users[rnti].rlc->write_sdu_mch(lcid, sdu); diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index 3d91791b2..acf2bb07e 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -364,8 +364,7 @@ void gw::run_thread() if (pdcp->is_drb_enabled(cfg.lcid)) { pdu->set_timestamp(); ul_tput_bytes += pdu->N_bytes; - pdcp->write_sdu(cfg.lcid, pdu); - + pdcp->write_sdu(cfg.lcid, pdu, false); do { pdu = pool_allocate; if (!pdu) { From 6a2dc8677b8e21df3bfec795c26250b4c53e852a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Tue, 24 Jul 2018 16:44:40 +0200 Subject: [PATCH 07/13] remove obsolete header --- lib/include/srslte/upper/rlc.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/include/srslte/upper/rlc.h b/lib/include/srslte/upper/rlc.h index 4a414f3fe..20123da0e 100644 --- a/lib/include/srslte/upper/rlc.h +++ b/lib/include/srslte/upper/rlc.h @@ -31,7 +31,6 @@ #include "srslte/common/log.h" #include "srslte/common/common.h" #include "srslte/interfaces/ue_interfaces.h" -#include "srslte/upper/rlc_entity.h" #include "srslte/upper/rlc_metrics.h" #include "srslte/upper/rlc_common.h" From 260fbff6ab5b9a2f13343e2adf019eaec9cdd6f2 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 25 Jul 2018 09:20:45 +0200 Subject: [PATCH 08/13] unlock before adding SRB0 again during RLC reset --- lib/src/upper/rlc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 2f0e20313..9b4323e53 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -178,10 +178,10 @@ void rlc::reset() } rlc_array_mrb.clear(); + pthread_rwlock_unlock(&rwlock); + // Add SRB0 again add_bearer(default_lcid, srslte_rlc_config_t()); - - pthread_rwlock_unlock(&rwlock); } void rlc::empty_queue() From 40d19e2d32df59edd6bebdc306be4e0813b88bb1 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 25 Jul 2018 15:08:35 +0200 Subject: [PATCH 09/13] fix PDCP reset --- lib/src/upper/pdcp.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index 24dbd27d3..acf0d6988 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -91,14 +91,16 @@ void pdcp::reestablish() { void pdcp::reset() { - pthread_rwlock_rdlock(&rwlock); + // destroy all bearers + pthread_rwlock_wrlock(&rwlock); for (pdcp_map_t::iterator it = pdcp_array.begin(); it != pdcp_array.end(); ++it) { - it->second->reset(); - } - if (valid_lcid(0)) { - pdcp_array.at(0)->init(rlc, rrc, gw, pdcp_log, default_lcid, default_cnfg); + delete(it->second); + pdcp_array.erase(it); } pthread_rwlock_unlock(&rwlock); + + // add default SRB0 again + add_bearer(0, default_cnfg); } /******************************************************************************* From ee5b055829e3844e63439b91fc41b574edfe3886 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 25 Jul 2018 15:09:19 +0200 Subject: [PATCH 10/13] rename pdcp function for GW to is_lcid_enabled() --- lib/include/srslte/interfaces/ue_interfaces.h | 2 +- lib/include/srslte/upper/pdcp.h | 2 +- lib/src/upper/pdcp.cc | 2 +- srsue/src/upper/gw.cc | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 1cfcc56e0..dc8128041 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -229,7 +229,7 @@ class pdcp_interface_gw { public: virtual void write_sdu(uint32_t lcid, srslte::byte_buffer_t *sdu, bool blocking) = 0; - virtual bool is_drb_enabled(uint32_t lcid) = 0; + virtual bool is_lcid_enabled(uint32_t lcid) = 0; }; // PDCP interface for RRC diff --git a/lib/include/srslte/upper/pdcp.h b/lib/include/srslte/upper/pdcp.h index 53149154a..2376bd020 100644 --- a/lib/include/srslte/upper/pdcp.h +++ b/lib/include/srslte/upper/pdcp.h @@ -51,7 +51,7 @@ public: void stop(); // GW interface - bool is_drb_enabled(uint32_t lcid); + bool is_lcid_enabled(uint32_t lcid); // RRC interface void reestablish(); diff --git a/lib/src/upper/pdcp.cc b/lib/src/upper/pdcp.cc index acf0d6988..c15fe6106 100644 --- a/lib/src/upper/pdcp.cc +++ b/lib/src/upper/pdcp.cc @@ -106,7 +106,7 @@ void pdcp::reset() /******************************************************************************* RRC/GW interface *******************************************************************************/ -bool pdcp::is_drb_enabled(uint32_t lcid) +bool pdcp::is_lcid_enabled(uint32_t lcid) { pthread_rwlock_rdlock(&rwlock); bool ret = false; diff --git a/srsue/src/upper/gw.cc b/srsue/src/upper/gw.cc index acf2bb07e..e78bd70bb 100644 --- a/srsue/src/upper/gw.cc +++ b/srsue/src/upper/gw.cc @@ -343,7 +343,7 @@ void gw::run_thread() { gw_log->info_hex(pdu->msg, pdu->N_bytes, "TX PDU"); - while(run_enable && !pdcp->is_drb_enabled(cfg.lcid) && attach_wait < ATTACH_WAIT_TOUT) { + while(run_enable && !pdcp->is_lcid_enabled(cfg.lcid) && attach_wait < ATTACH_WAIT_TOUT) { if (!attach_wait) { gw_log->info("LCID=%d not active, requesting NAS attach (%d/%d)\n", cfg.lcid, attach_wait, ATTACH_WAIT_TOUT); if (!nas->attach_request()) { @@ -361,7 +361,7 @@ void gw::run_thread() } // Send PDU directly to PDCP - if (pdcp->is_drb_enabled(cfg.lcid)) { + if (pdcp->is_lcid_enabled(cfg.lcid)) { pdu->set_timestamp(); ul_tput_bytes += pdu->N_bytes; pdcp->write_sdu(cfg.lcid, pdu, false); From 5444b2a0b79a8c06837a514862b87a54fc0df949 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 25 Jul 2018 15:09:54 +0200 Subject: [PATCH 11/13] tiny cosmetic changes --- lib/src/upper/pdcp_entity.cc | 11 +++++++---- lib/src/upper/rlc.cc | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/src/upper/pdcp_entity.cc b/lib/src/upper/pdcp_entity.cc index b77a760b9..3efdf4786 100644 --- a/lib/src/upper/pdcp_entity.cc +++ b/lib/src/upper/pdcp_entity.cc @@ -70,11 +70,11 @@ void pdcp_entity::init(srsue::rlc_interface_pdcp *rlc_, cfg.sn_len = 0; sn_len_bytes = 0; - if(cfg.is_control) { + if (cfg.is_control) { cfg.sn_len = 5; sn_len_bytes = 1; } - if(cfg.is_data) { + if (cfg.is_data) { cfg.sn_len = 12; sn_len_bytes = 2; } @@ -89,6 +89,7 @@ void pdcp_entity::reestablish() { tx_count = 0; rx_count = 0; } else { + // Only reset counter in RLC-UM if (rlc->rb_is_um(lcid)) { tx_count = 0; rx_count = 0; @@ -96,11 +97,13 @@ void pdcp_entity::reestablish() { } } +// Used to stop/pause the entity (called on RRC conn release) void pdcp_entity::reset() { - active = false; - if(log) + active = false; + if (log) { log->debug("Reset %s\n", rrc->get_rb_name(lcid).c_str()); + } } bool pdcp_entity::is_active() diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index 9b4323e53..d256abbe3 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -208,7 +208,7 @@ void rlc::write_sdu(uint32_t lcid, byte_buffer_t *sdu, bool blocking) rlc_array.at(lcid)->write_sdu_nb(sdu); } } else { - rlc_log->warning("Writing SDU: lcid=%d. Deallocating sdu\n", lcid); + rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid); byte_buffer_pool::get_instance()->deallocate(sdu); } pthread_rwlock_unlock(&rwlock); @@ -220,7 +220,7 @@ void rlc::write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu) 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); + rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid); byte_buffer_pool::get_instance()->deallocate(sdu); } pthread_rwlock_unlock(&rwlock); From 3950629a75f330e318a27dfd4be9ac0152976e5a Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 25 Jul 2018 16:06:42 +0200 Subject: [PATCH 12/13] remove obsolete RLC_MODE struct and move existing one to rlc_interface.h --- lib/include/srslte/upper/rlc_common.h | 10 +------- lib/include/srslte/upper/rlc_interface.h | 29 ++++++++++++------------ lib/src/upper/rlc.cc | 8 +++---- lib/src/upper/rlc_um.cc | 2 +- lib/test/upper/rlc_stress_test.cc | 4 ++-- 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index f3fcec12d..540298217 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -38,15 +38,7 @@ namespace srslte { #define RLC_AM_WINDOW_SIZE 512 -typedef enum{ - RLC_MODE_TM = 0, - RLC_MODE_UM, - RLC_MODE_AM, - RLC_MODE_N_ITEMS, -}rlc_mode_t; -static const char rlc_mode_text[RLC_MODE_N_ITEMS][20] = {"Transparent Mode", - "Unacknowledged Mode", - "Acknowledged Mode"}; + typedef enum{ RLC_FI_FIELD_START_AND_END_ALIGNED = 0, diff --git a/lib/include/srslte/upper/rlc_interface.h b/lib/include/srslte/upper/rlc_interface.h index 0b2460101..4201717dd 100644 --- a/lib/include/srslte/upper/rlc_interface.h +++ b/lib/include/srslte/upper/rlc_interface.h @@ -32,14 +32,15 @@ namespace srslte { - typedef enum{ - SRSLTE_RLC_MODE_TM = 0, - SRSLTE_RLC_MODE_UM, - SRSLTE_RLC_MODE_AM, - SRSLTE_RLC_MODE_N_ITEMS -} srslte_rlc_mode_t; -static const char srslte_rlc_mode_text[SRSLTE_RLC_MODE_N_ITEMS][20] = { "TM", "UM", "AM"}; + RLC_MODE_TM = 0, + RLC_MODE_UM, + RLC_MODE_AM, + RLC_MODE_N_ITEMS, +}rlc_mode_t; +static const char rlc_mode_text[RLC_MODE_N_ITEMS][20] = {"Transparent Mode", + "Unacknowledged Mode", + "Acknowledged Mode"}; typedef enum{ RLC_UMD_SN_SIZE_5_BITS = 0, @@ -88,22 +89,22 @@ typedef struct { class srslte_rlc_config_t { public: - srslte_rlc_mode_t rlc_mode; + rlc_mode_t rlc_mode; srslte_rlc_am_config_t am; srslte_rlc_um_config_t um; // Default ctor - srslte_rlc_config_t(): rlc_mode(SRSLTE_RLC_MODE_TM), am(), um() {}; + srslte_rlc_config_t(): rlc_mode(RLC_MODE_TM), am(), um() {}; // Constructor based on liblte's RLC config - srslte_rlc_config_t(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) : rlc_mode(SRSLTE_RLC_MODE_AM), am(), um() + srslte_rlc_config_t(LIBLTE_RRC_RLC_CONFIG_STRUCT *cnfg) : rlc_mode(RLC_MODE_AM), am(), um() { // update RLC mode to internal mode struct - rlc_mode = (cnfg->rlc_mode == LIBLTE_RRC_RLC_MODE_AM) ? SRSLTE_RLC_MODE_AM : SRSLTE_RLC_MODE_UM; + rlc_mode = (cnfg->rlc_mode == LIBLTE_RRC_RLC_MODE_AM) ? RLC_MODE_AM : RLC_MODE_UM; switch(rlc_mode) { - case SRSLTE_RLC_MODE_AM: + case RLC_MODE_AM: am.t_poll_retx = liblte_rrc_t_poll_retransmit_num[cnfg->ul_am_rlc.t_poll_retx]; am.poll_pdu = liblte_rrc_poll_pdu_num[cnfg->ul_am_rlc.poll_pdu]; am.poll_byte = liblte_rrc_poll_byte_num[cnfg->ul_am_rlc.poll_byte]*1000; // KB @@ -111,7 +112,7 @@ public: am.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_am_rlc.t_reordering]; am.t_status_prohibit = liblte_rrc_t_status_prohibit_num[cnfg->dl_am_rlc.t_status_prohibit]; break; - case SRSLTE_RLC_MODE_UM: + case RLC_MODE_UM: um.t_reordering = liblte_rrc_t_reordering_num[cnfg->dl_um_bi_rlc.t_reordering]; um.rx_sn_field_length = (rlc_umd_sn_size_t)cnfg->dl_um_bi_rlc.sn_field_len; um.rx_window_size = (RLC_UMD_SN_SIZE_5_BITS == um.rx_sn_field_length) ? 16 : 512; @@ -129,7 +130,7 @@ public: static srslte_rlc_config_t mch_config() { srslte_rlc_config_t cfg; - cfg.rlc_mode = SRSLTE_RLC_MODE_UM; + cfg.rlc_mode = RLC_MODE_UM; cfg.um.t_reordering = 0; cfg.um.rx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; cfg.um.rx_window_size = 0; diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index d256abbe3..b461a5740 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -411,13 +411,13 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) if (not valid_lcid(lcid)) { switch(cnfg.rlc_mode) { - case SRSLTE_RLC_MODE_TM: + case RLC_MODE_TM: rlc_entity = new rlc_tm(); break; - case SRSLTE_RLC_MODE_AM: + case RLC_MODE_AM: rlc_entity = new rlc_am(); break; - case SRSLTE_RLC_MODE_UM: + case RLC_MODE_UM: rlc_entity = new rlc_um(); break; default: @@ -429,7 +429,7 @@ void rlc::add_bearer(uint32_t lcid, srslte_rlc_config_t cnfg) // configure and add to array rlc_entity->init(rlc_log, lcid, pdcp, rrc, mac_timers); - if (cnfg.rlc_mode != SRSLTE_RLC_MODE_TM) { + if (cnfg.rlc_mode != RLC_MODE_TM) { if (rlc_entity->configure(cnfg) == false) { rlc_log->error("Error configuring RLC entity\n."); goto delete_and_exit; diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index bf127900b..ac80e6940 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -76,7 +76,7 @@ bool rlc_um::configure(srslte_rlc_config_t cnfg_) } log->warning("%s configured in %s mode: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n", - rb_name.c_str(), srslte_rlc_mode_text[cnfg_.rlc_mode], + 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]); // store config diff --git a/lib/test/upper/rlc_stress_test.cc b/lib/test/upper/rlc_stress_test.cc index 57624fc7c..d48011667 100644 --- a/lib/test/upper/rlc_stress_test.cc +++ b/lib/test/upper/rlc_stress_test.cc @@ -325,7 +325,7 @@ void stress_test(stress_test_args_t args) srslte_rlc_config_t cnfg_; if (args.mode == "AM") { // config RLC AM bearer - cnfg_.rlc_mode = SRSLTE_RLC_MODE_AM; + cnfg_.rlc_mode = RLC_MODE_AM; cnfg_.am.max_retx_thresh = 4; cnfg_.am.poll_byte = 25*1000; cnfg_.am.poll_pdu = 4; @@ -334,7 +334,7 @@ void stress_test(stress_test_args_t args) cnfg_.am.t_status_prohibit = 5; } else if (args.mode == "UM") { // config UM bearer - cnfg_.rlc_mode = SRSLTE_RLC_MODE_UM; + cnfg_.rlc_mode = RLC_MODE_UM; cnfg_.um.t_reordering = 5; cnfg_.um.rx_mod = 32; cnfg_.um.rx_sn_field_length = RLC_UMD_SN_SIZE_5_BITS; From 89df8f1582711b9805889178826e13cdb511967d Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Wed, 25 Jul 2018 16:08:07 +0200 Subject: [PATCH 13/13] unify RLC interface for writing SDUs w/ and w/o blocking --- lib/include/srslte/upper/rlc_am.h | 3 +-- lib/include/srslte/upper/rlc_common.h | 3 +-- lib/include/srslte/upper/rlc_tm.h | 3 +-- lib/include/srslte/upper/rlc_um.h | 3 +-- lib/src/upper/rlc.cc | 8 ++------ lib/src/upper/rlc_am.cc | 29 ++++++++++----------------- lib/src/upper/rlc_tm.cc | 29 +++++++++------------------ lib/src/upper/rlc_um.cc | 12 +++++------ 8 files changed, 33 insertions(+), 57 deletions(-) diff --git a/lib/include/srslte/upper/rlc_am.h b/lib/include/srslte/upper/rlc_am.h index f57a65b0b..ab2c6cd63 100644 --- a/lib/include/srslte/upper/rlc_am.h +++ b/lib/include/srslte/upper/rlc_am.h @@ -86,8 +86,7 @@ public: uint32_t get_bearer(); // PDCP interface - void write_sdu(byte_buffer_t *sdu); - void write_sdu_nb(byte_buffer_t *sdu); + void write_sdu(byte_buffer_t *sdu, bool blocking = true); // MAC interface uint32_t get_buffer_state(); diff --git a/lib/include/srslte/upper/rlc_common.h b/lib/include/srslte/upper/rlc_common.h index 540298217..71fe934df 100644 --- a/lib/include/srslte/upper/rlc_common.h +++ b/lib/include/srslte/upper/rlc_common.h @@ -166,8 +166,7 @@ public: virtual void reset_metrics() = 0; // PDCP interface - virtual void write_sdu(byte_buffer_t *sdu) = 0; - virtual void write_sdu_nb(byte_buffer_t *sdu) = 0; + virtual void write_sdu(byte_buffer_t *sdu, bool blocking) = 0; // MAC interface virtual uint32_t get_buffer_state() = 0; diff --git a/lib/include/srslte/upper/rlc_tm.h b/lib/include/srslte/upper/rlc_tm.h index 5db629231..b1fa03ac6 100644 --- a/lib/include/srslte/upper/rlc_tm.h +++ b/lib/include/srslte/upper/rlc_tm.h @@ -59,8 +59,7 @@ public: void reset_metrics(); // PDCP interface - void write_sdu(byte_buffer_t *sdu); - void write_sdu_nb(byte_buffer_t *sdu); + void write_sdu(byte_buffer_t *sdu, bool blocking); // MAC interface uint32_t get_buffer_state(); diff --git a/lib/include/srslte/upper/rlc_um.h b/lib/include/srslte/upper/rlc_um.h index a880b2238..f866417d2 100644 --- a/lib/include/srslte/upper/rlc_um.h +++ b/lib/include/srslte/upper/rlc_um.h @@ -65,8 +65,7 @@ public: uint32_t get_bearer(); // PDCP interface - void write_sdu(byte_buffer_t *sdu); - void write_sdu_nb(byte_buffer_t *sdu); + void write_sdu(byte_buffer_t *sdu, bool blocking = true); // MAC interface uint32_t get_buffer_state(); diff --git a/lib/src/upper/rlc.cc b/lib/src/upper/rlc.cc index b461a5740..31b740df4 100644 --- a/lib/src/upper/rlc.cc +++ b/lib/src/upper/rlc.cc @@ -202,11 +202,7 @@ void rlc::write_sdu(uint32_t lcid, byte_buffer_t *sdu, bool blocking) { pthread_rwlock_rdlock(&rwlock); if (valid_lcid(lcid)) { - if (blocking) { - rlc_array.at(lcid)->write_sdu(sdu); - } else { - rlc_array.at(lcid)->write_sdu_nb(sdu); - } + rlc_array.at(lcid)->write_sdu(sdu, blocking); } else { rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid); byte_buffer_pool::get_instance()->deallocate(sdu); @@ -218,7 +214,7 @@ void rlc::write_sdu_mch(uint32_t lcid, byte_buffer_t *sdu) { pthread_rwlock_rdlock(&rwlock); if (valid_lcid_mrb(lcid)) { - rlc_array_mrb.at(lcid)->write_sdu_nb(sdu); + rlc_array_mrb.at(lcid)->write_sdu(sdu, false); // write in non-blocking mode by default } else { rlc_log->warning("RLC LCID %d doesn't exist. Deallocating SDU\n", lcid); byte_buffer_pool::get_instance()->deallocate(sdu); diff --git a/lib/src/upper/rlc_am.cc b/lib/src/upper/rlc_am.cc index c2ce16dcc..92c32410d 100644 --- a/lib/src/upper/rlc_am.cc +++ b/lib/src/upper/rlc_am.cc @@ -199,32 +199,25 @@ uint32_t rlc_am::get_bearer() * PDCP interface ***************************************************************************/ -void rlc_am::write_sdu(byte_buffer_t *sdu) +void rlc_am::write_sdu(byte_buffer_t *sdu, bool blocking) { if (!tx_enabled) { byte_buffer_pool::get_instance()->deallocate(sdu); return; } if (sdu) { - tx_sdu_queue.write(sdu); - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); - } else { - log->warning("NULL SDU pointer in write_sdu()\n"); - } -} - -void rlc_am::write_sdu_nb(byte_buffer_t *sdu) -{ - if (!tx_enabled) { - byte_buffer_pool::get_instance()->deallocate(sdu); - return; - } - if (sdu) { - if (tx_sdu_queue.try_write(sdu)) { + if (blocking) { + // block on write to queue + tx_sdu_queue.write(sdu); log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); } else { - log->debug_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); - pool->deallocate(sdu); + // non-blocking write + if (tx_sdu_queue.try_write(sdu)) { + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + } else { + log->debug_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)", rrc->get_rb_name(lcid).c_str(), sdu->N_bytes, tx_sdu_queue.size()); + pool->deallocate(sdu); + } } } else { log->warning("NULL SDU pointer in write_sdu()\n"); diff --git a/lib/src/upper/rlc_tm.cc b/lib/src/upper/rlc_tm.cc index 9b132b39b..96e075cb6 100644 --- a/lib/src/upper/rlc_tm.cc +++ b/lib/src/upper/rlc_tm.cc @@ -96,35 +96,26 @@ uint32_t rlc_tm::get_bearer() } // PDCP interface -void rlc_tm::write_sdu(byte_buffer_t *sdu) +void rlc_tm::write_sdu(byte_buffer_t *sdu, bool blocking) { if (!tx_enabled) { byte_buffer_pool::get_instance()->deallocate(sdu); return; } if (sdu) { - ul_queue.write(sdu); - log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, queue size=%d, bytes=%d", - rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); - } else { - log->warning("NULL SDU pointer in write_sdu()\n"); - } -} - -void rlc_tm::write_sdu_nb(byte_buffer_t *sdu) -{ - if (!tx_enabled) { - byte_buffer_pool::get_instance()->deallocate(sdu); - return; - } - if (sdu) { - if (ul_queue.try_write(sdu)) { + if (blocking) { + ul_queue.write(sdu); log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, queue size=%d, bytes=%d", rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); } else { - log->debug_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU, queue size=%d, bytes=%d", + if (ul_queue.try_write(sdu)) { + log->info_hex(sdu->msg, sdu->N_bytes, "%s Tx SDU, queue size=%d, bytes=%d", + rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); + } else { + log->debug_hex(sdu->msg, sdu->N_bytes, "[Dropped SDU] %s Tx SDU, queue size=%d, bytes=%d", rrc->get_rb_name(lcid).c_str(), ul_queue.size(), ul_queue.size_bytes()); - pool->deallocate(sdu); + pool->deallocate(sdu); + } } } else { log->warning("NULL SDU pointer in write_sdu()\n"); diff --git a/lib/src/upper/rlc_um.cc b/lib/src/upper/rlc_um.cc index ac80e6940..9ea96f6ee 100644 --- a/lib/src/upper/rlc_um.cc +++ b/lib/src/upper/rlc_um.cc @@ -142,14 +142,14 @@ uint32_t rlc_um::get_bearer() /**************************************************************************** * PDCP interface ***************************************************************************/ -void rlc_um::write_sdu(byte_buffer_t *sdu) +void rlc_um::write_sdu(byte_buffer_t *sdu, bool blocking) { - tx.write_sdu(sdu); -} + if (blocking) { + tx.write_sdu(sdu); + } else { + tx.try_write_sdu(sdu); + } -void rlc_um::write_sdu_nb(byte_buffer_t *sdu) -{ - tx.try_write_sdu(sdu); } /****************************************************************************