From a3cb21d378f96148bc6aaaff502769e88c6b6cda Mon Sep 17 00:00:00 2001 From: Francisco Date: Mon, 1 Mar 2021 16:25:29 +0000 Subject: [PATCH] move undelivered_pdcp_sdus class methods to .cc file. Fixed the forwarding of pending PDCP SNs during S1 handover --- lib/include/srslte/upper/pdcp_entity_lte.h | 130 ++--------------- lib/src/upper/pdcp_entity_lte.cc | 155 +++++++++++++++++++-- 2 files changed, 152 insertions(+), 133 deletions(-) diff --git a/lib/include/srslte/upper/pdcp_entity_lte.h b/lib/include/srslte/upper/pdcp_entity_lte.h index b3942bc22..4bf62f016 100644 --- a/lib/include/srslte/upper/pdcp_entity_lte.h +++ b/lib/include/srslte/upper/pdcp_entity_lte.h @@ -34,12 +34,7 @@ namespace srslte { class undelivered_sdus_queue { public: - explicit undelivered_sdus_queue(srslte::task_sched_handle task_sched) - { - for (auto& e : sdus) { - e.discard_timer = task_sched.get_unique_timer(); - } - } + explicit undelivered_sdus_queue(srslte::task_sched_handle task_sched); bool empty() const { return count == 0; } bool is_full() const { return count >= capacity; } @@ -51,136 +46,31 @@ public: return sdus[sn].sdu != nullptr and sdus[sn].sdu->md.pdcp_sn == sn; } // Getter for the number of discard timers. Used for debugging. - size_t nof_discard_timers() const - { - return std::count_if(sdus.begin(), sdus.end(), [](const sdu_data& s) { - return s.sdu != nullptr and s.discard_timer.is_valid() and s.discard_timer.is_running(); - }); - } + size_t nof_discard_timers() const; bool add_sdu(uint32_t sn, const srslte::unique_byte_buffer_t& sdu, uint32_t discard_timeout, - const std::function& callback) - { - assert(discard_timeout < capacity and "Invalid discard timeout value"); - assert(not has_sdu(sn) && "Cannot add repeated SNs"); - - if (is_full()) { - return false; - } - - // Make sure we don't associate more than half of the PDCP SN space of contiguous PDCP SDUs - if (not empty()) { - int32_t diff = sn - fms; - if (diff > (int32_t)(capacity / 2)) { - return false; - } - if (diff <= 0 && diff > -((int32_t)(capacity / 2))) { - return false; - } - } - - // Allocate buffer and exit on error - srslte::unique_byte_buffer_t tmp = make_byte_buffer(); - if (tmp == nullptr) { - return false; - } - - // Update FMS and LMS if necessary - if (empty()) { - fms = sn; - lms = sn; - } else { - update_lms(sn); - } - // Add SDU - count++; - sdus[sn].sdu = std::move(tmp); - sdus[sn].sdu->md.pdcp_sn = sn; - sdus[sn].sdu->N_bytes = sdu->N_bytes; - memcpy(sdus[sn].sdu->msg, sdu->msg, sdu->N_bytes); - if (discard_timeout > 0) { - sdus[sn].discard_timer.set(discard_timeout, callback); - sdus[sn].discard_timer.run(); - } - sdus[sn].sdu->set_timestamp(); // Metrics - bytes += sdu->N_bytes; - return true; - } + const std::function& callback); unique_byte_buffer_t& operator[](uint32_t sn) { assert(has_sdu(sn)); return sdus[sn].sdu; } - - bool clear_sdu(uint32_t sn) - { - if (not has_sdu(sn)) { - return false; - } - count--; - bytes -= sdus[sn].sdu->N_bytes; - sdus[sn].discard_timer.clear(); - sdus[sn].sdu.reset(); - // Find next FMS, - update_fms(); - return true; - } - - void clear() - { - count = 0; - bytes = 0; - fms = 0; - for (uint32_t sn = 0; sn < capacity; sn++) { - sdus[sn].discard_timer.clear(); - sdus[sn].sdu.reset(); - } - } + bool clear_sdu(uint32_t sn); + void clear(); uint32_t get_bytes() const { return bytes; } - uint32_t get_fms() const { return fms; } - - void set_fms(uint32_t fms_) { fms = fms_; } - - void update_fms() - { - if (empty()) { - fms = increment_sn(fms); - return; - } - - for (uint32_t i = 0; i < capacity; ++i) { - uint32_t sn = increment_sn(fms + i); - if (has_sdu(sn)) { - fms = sn; - return; - } - } - - fms = increment_sn(fms); - } - - void update_lms(uint32_t sn) - { - if (empty()) { - lms = fms; - return; - } - - int32_t diff = sn - lms; - if (diff > 0 && sn > lms) { - lms = sn; - } else if (diff < 0 && sn < lms) { - lms = sn; - } - } + void set_fms(uint32_t fms_) { fms = fms_; } + void update_fms(); + void update_lms(uint32_t sn); uint32_t get_lms() const { return lms; } + std::map get_buffered_sdus(); + private: const static uint32_t capacity = 4096; const static uint32_t invalid_sn = -1; diff --git a/lib/src/upper/pdcp_entity_lte.cc b/lib/src/upper/pdcp_entity_lte.cc index 8217b4b4a..8015921b2 100644 --- a/lib/src/upper/pdcp_entity_lte.cc +++ b/lib/src/upper/pdcp_entity_lte.cc @@ -19,6 +19,147 @@ namespace srslte { +undelivered_sdus_queue::undelivered_sdus_queue(srslte::task_sched_handle task_sched) +{ + for (auto& e : sdus) { + e.discard_timer = task_sched.get_unique_timer(); + } +} + +bool undelivered_sdus_queue::add_sdu(uint32_t sn, + const srslte::unique_byte_buffer_t& sdu, + uint32_t discard_timeout, + const std::function& callback) +{ + assert(discard_timeout < capacity and "Invalid discard timeout value"); + assert(not has_sdu(sn) && "Cannot add repeated SNs"); + + if (is_full()) { + return false; + } + + // Make sure we don't associate more than half of the PDCP SN space of contiguous PDCP SDUs + if (not empty()) { + int32_t diff = sn - fms; + if (diff > (int32_t)(capacity / 2)) { + return false; + } + if (diff <= 0 && diff > -((int32_t)(capacity / 2))) { + return false; + } + } + + // Allocate buffer and exit on error + srslte::unique_byte_buffer_t tmp = make_byte_buffer(); + if (tmp == nullptr) { + return false; + } + + // Update FMS and LMS if necessary + if (empty()) { + fms = sn; + lms = sn; + } else { + update_lms(sn); + } + // Add SDU + count++; + sdus[sn].sdu = std::move(tmp); + sdus[sn].sdu->md.pdcp_sn = sn; + sdus[sn].sdu->N_bytes = sdu->N_bytes; + memcpy(sdus[sn].sdu->msg, sdu->msg, sdu->N_bytes); + if (discard_timeout > 0) { + sdus[sn].discard_timer.set(discard_timeout, callback); + sdus[sn].discard_timer.run(); + } + sdus[sn].sdu->set_timestamp(); // Metrics + bytes += sdu->N_bytes; + return true; +} + +bool undelivered_sdus_queue::clear_sdu(uint32_t sn) +{ + if (not has_sdu(sn)) { + return false; + } + count--; + bytes -= sdus[sn].sdu->N_bytes; + sdus[sn].discard_timer.clear(); + sdus[sn].sdu.reset(); + // Find next FMS, + update_fms(); + return true; +} + +void undelivered_sdus_queue::clear() +{ + count = 0; + bytes = 0; + fms = 0; + for (uint32_t sn = 0; sn < capacity; sn++) { + sdus[sn].discard_timer.clear(); + sdus[sn].sdu.reset(); + } +} + +size_t undelivered_sdus_queue::nof_discard_timers() const +{ + return std::count_if(sdus.begin(), sdus.end(), [](const sdu_data& s) { + return s.sdu != nullptr and s.discard_timer.is_valid() and s.discard_timer.is_running(); + }); +} + +void undelivered_sdus_queue::update_fms() +{ + if (empty()) { + fms = increment_sn(fms); + return; + } + + for (uint32_t i = 0; i < capacity; ++i) { + uint32_t sn = increment_sn(fms + i); + if (has_sdu(sn)) { + fms = sn; + return; + } + } + + fms = increment_sn(fms); +} + +void undelivered_sdus_queue::update_lms(uint32_t sn) +{ + if (empty()) { + lms = fms; + return; + } + + int32_t diff = sn - lms; + if (diff > 0 && sn > lms) { + lms = sn; + } else if (diff < 0 && sn < lms) { + lms = sn; + } +} + +std::map undelivered_sdus_queue::get_buffered_sdus() +{ + std::map fwd_sdus; + for (auto& sdu : sdus) { + if (sdu.sdu != nullptr) { + // TODO: Find ways to avoid deep copy + srslte::unique_byte_buffer_t fwd_sdu = make_byte_buffer(); + *fwd_sdu = *sdu.sdu; + fwd_sdus.emplace(sdu.sdu->md.pdcp_sn, std::move(fwd_sdu)); + } + } + return fwd_sdus; +} + +/**************************************************************************** + * PDCP Entity LTE class + ***************************************************************************/ + pdcp_entity_lte::pdcp_entity_lte(srsue::rlc_interface_pdcp* rlc_, srsue::rrc_interface_pdcp* rrc_, srsue::gw_interface_pdcp* gw_, @@ -701,19 +842,7 @@ void pdcp_entity_lte::set_bearer_state(const pdcp_lte_state_t& state) std::map pdcp_entity_lte::get_buffered_pdus() { logger.info("Buffered PDUs requested, buffer_size=%d", undelivered_sdus.size()); - - std::map cpy{}; - // Deep copy undelivered SDUs - // TODO: investigate wheter the deep copy can be avoided by moving the undelivered SDU queue. - // That can only be done just before the PDCP is disabled though. - for (uint32_t sn = 0; sn < undelivered_sdus.get_capacity(); sn++) { - if (undelivered_sdus.has_sdu(sn)) { - logger.debug(undelivered_sdus[sn]->msg, undelivered_sdus[sn]->N_bytes, "Forwarding buffered PDU with SN=%d", sn); - cpy[sn] = make_byte_buffer(); - (*cpy[sn]) = *(undelivered_sdus[sn]); - } - } - return cpy; + return undelivered_sdus.get_buffered_sdus(); } /****************************************************************************