From cfd24f6a0ec7b3f54f0420bacaae15de87f7cbf8 Mon Sep 17 00:00:00 2001 From: Francisco Date: Wed, 24 Mar 2021 16:06:34 +0000 Subject: [PATCH] gtpu - leverage byte_buffer_pool to store buffered sdus in gtpu --- lib/include/srsran/adt/bounded_vector.h | 34 +++++++------- lib/include/srsran/adt/pool/fixed_size_pool.h | 2 + lib/include/srsran/common/buffer_pool.h | 44 +++++++++++++++++++ lib/include/srsran/upper/rlc_am_lte.h | 6 +-- srsenb/hdr/stack/upper/gtpu.h | 2 +- srsenb/src/stack/upper/gtpu.cc | 16 ++++--- 6 files changed, 76 insertions(+), 28 deletions(-) diff --git a/lib/include/srsran/adt/bounded_vector.h b/lib/include/srsran/adt/bounded_vector.h index e33a4286d..239c975af 100644 --- a/lib/include/srsran/adt/bounded_vector.h +++ b/lib/include/srsran/adt/bounded_vector.h @@ -13,7 +13,7 @@ #ifndef SRSRAN_BOUNDED_VECTOR_H #define SRSRAN_BOUNDED_VECTOR_H -#include +#include "srsran/common/srsran_assert.h" #include #include #include @@ -87,22 +87,22 @@ public: // Element access T& operator[](std::size_t i) { - assert(i < size_ && "Array index is out of bounds."); + srsran_assert(i < size_, "Array index is out of bounds."); return reinterpret_cast(buffer[i]); } const T& operator[](std::size_t i) const { - assert(i < size_ && "Array index is out of bounds."); + srsran_assert(i < size_, "Array index is out of bounds."); return reinterpret_cast(buffer[i]); } T& back() { - assert(size_ > 0 && "Trying to get back of empty array."); + srsran_assert(size_ > 0, "Trying to get back of empty array."); return *(begin() + size_ - 1); } const T& back() const { - assert(size_ > 0 && "Trying to get back of empty array."); + srsran_assert(size_ > 0, "Trying to get back of empty array."); return *(begin() + size_ - 1); } T& front() { return (*this)[0]; } @@ -130,8 +130,8 @@ public: } iterator erase(iterator pos) { - assert(pos >= this->begin() && "Iterator to erase is out of bounds."); - assert(pos < this->end() && "Erasing at past-the-end iterator."); + srsran_assert(pos >= this->begin(), "Iterator to erase is out of bounds."); + srsran_assert(pos < this->end(), "Erasing at past-the-end iterator."); iterator ret = pos; std::move(pos + 1, end(), pos); pop_back(); @@ -139,9 +139,9 @@ public: } iterator erase(iterator it_start, iterator it_end) { - assert(it_start >= begin() && "Range to erase is out of bounds."); - assert(it_start <= it_end && "Trying to erase invalid range."); - assert(it_end <= end() && "Trying to erase past the end."); + srsran_assert(it_start >= begin(), "Range to erase is out of bounds."); + srsran_assert(it_start <= it_end, "Trying to erase invalid range."); + srsran_assert(it_end <= end(), "Trying to erase past the end."); iterator ret = it_start; // Shift all elts down. @@ -154,14 +154,14 @@ public: { static_assert(std::is_copy_constructible::value, "T must be copy-constructible"); size_++; - assert(size_ <= MAX_N); + srsran_assert(size_ <= MAX_N, "bounded vector maximum size=%zd was exceeded", MAX_N); new (&back()) T(value); } void push_back(T&& value) { static_assert(std::is_move_constructible::value, "T must be move-constructible"); size_++; - assert(size_ <= MAX_N); + srsran_assert(size_ <= MAX_N, "bounded vector maximum size=%zd was exceeded", MAX_N); new (&back()) T(std::move(value)); } template @@ -169,12 +169,12 @@ public: { static_assert(std::is_constructible::value, "Passed arguments to emplace_back are invalid"); size_++; - assert(size_ <= MAX_N); + srsran_assert(size_ <= MAX_N, "bounded vector maximum size=%zd was exceeded", MAX_N); new (&back()) T(std::forward(args)...); } void pop_back() { - assert(size_ > 0 && "Trying to erase element from empty vector."); + srsran_assert(size_ > 0, "Trying to erase element from empty vector."); back().~T(); size_--; } @@ -210,21 +210,21 @@ private: void append(const_iterator it_begin, const_iterator it_end) { size_type N = std::distance(it_begin, it_end); - assert(N + size_ <= MAX_N); + srsran_assert(N + size_ <= MAX_N, "bounded vector maximum size=%zd was exceeded", MAX_N); std::uninitialized_copy(it_begin, it_end, end()); size_ += N; } void append(size_type N, const T& element) { static_assert(std::is_copy_constructible::value, "T must be copy-constructible"); - assert(N + size_ <= MAX_N); + srsran_assert(N + size_ <= MAX_N, "bounded vector maximum size=%zd was exceeded", MAX_N); std::uninitialized_fill_n(end(), N, element); size_ += N; } void append(size_type N) { static_assert(std::is_default_constructible::value, "T must be default-constructible"); - assert(N + size_ <= MAX_N); + srsran_assert(N + size_ <= MAX_N, "bounded vector maximum size=%zd was exceeded", MAX_N); for (size_type i = size_; i < size_ + N; ++i) { new (&buffer[i]) T(); } diff --git a/lib/include/srsran/adt/pool/fixed_size_pool.h b/lib/include/srsran/adt/pool/fixed_size_pool.h index ca707274a..09942a809 100644 --- a/lib/include/srsran/adt/pool/fixed_size_pool.h +++ b/lib/include/srsran/adt/pool/fixed_size_pool.h @@ -62,6 +62,8 @@ class concurrent_fixed_memory_pool } public: + const static size_t BLOCK_SIZE = ObjSize; + concurrent_fixed_memory_pool(const concurrent_fixed_memory_pool&) = delete; concurrent_fixed_memory_pool(concurrent_fixed_memory_pool&&) = delete; concurrent_fixed_memory_pool& operator=(const concurrent_fixed_memory_pool&) = delete; diff --git a/lib/include/srsran/common/buffer_pool.h b/lib/include/srsran/common/buffer_pool.h index 7f0f3c9e8..a05c65665 100644 --- a/lib/include/srsran/common/buffer_pool.h +++ b/lib/include/srsran/common/buffer_pool.h @@ -14,6 +14,7 @@ #define SRSRAN_BUFFER_POOL_H #include "byte_buffer.h" +#include "srsran/adt/bounded_vector.h" #include #include #include @@ -183,6 +184,49 @@ inline unique_byte_buffer_t make_byte_buffer(const char* debug_ctxt) noexcept return buffer; } +namespace detail { +struct byte_buffer_pool_deleter { + void operator()(void* ptr) { byte_buffer_pool::get_instance()->deallocate_node(ptr); } +}; +} // namespace detail + +template +struct byte_buffer_pool_ptr { + static_assert(sizeof(T) <= byte_buffer_pool::BLOCK_SIZE, "pool_bounded_vector does not fit buffer pool block size"); + +public: + byte_buffer_pool_ptr() = default; + void reset() { ptr.reset(); } + + T* operator->() { return ptr.get(); } + const T* operator->() const { return ptr.get(); } + T& operator*() { return *ptr; } + const T& operator*() const { return *ptr; } + + template + void emplace(CtorArgs&&... args) + { + ptr.reset(make(std::forward(args)...).ptr.release()); + } + + template + static byte_buffer_pool_ptr make(CtorArgs&&... args) + { + void* memblock = byte_buffer_pool::get_instance()->allocate_node(sizeof(T)); + if (memblock == nullptr) { + return byte_buffer_pool_ptr(); + } + new (memblock) T(std::forward(args)...); + byte_buffer_pool_ptr ret; + ret.ptr = std::unique_ptr(static_cast(memblock), + detail::byte_buffer_pool_deleter()); + return ret; + }; + +private: + std::unique_ptr ptr; +}; + } // namespace srsran #endif // SRSRAN_BUFFER_POOL_H diff --git a/lib/include/srsran/upper/rlc_am_lte.h b/lib/include/srsran/upper/rlc_am_lte.h index 5f273c64a..50e195511 100644 --- a/lib/include/srsran/upper/rlc_am_lte.h +++ b/lib/include/srsran/upper/rlc_am_lte.h @@ -76,7 +76,7 @@ struct rlc_ringbuffer_t { rlc_ringbuffer_t() { clear(); } T& add_pdu(size_t sn) { - srsran_expect(not has_sn(sn), "The same SN=%d should not be added twice", sn); + srsran_expect(not has_sn(sn), "The same SN=%zd should not be added twice", sn); window[sn].rlc_sn = sn; active_flag[sn] = true; count++; @@ -84,14 +84,14 @@ struct rlc_ringbuffer_t { } void remove_pdu(size_t sn) { - srsran_expect(has_sn(sn), "The removed SN=%d is not in the window", sn); + srsran_expect(has_sn(sn), "The removed SN=%zd is not in the window", sn); window[sn] = {}; active_flag[sn] = false; count--; } T& operator[](size_t sn) { - srsran_expect(has_sn(sn), "The accessed SN=%d is not in the window", sn); + srsran_expect(has_sn(sn), "The accessed SN=%zd is not in the window", sn); return window[sn]; } size_t size() const { return count; } diff --git a/srsenb/hdr/stack/upper/gtpu.h b/srsenb/hdr/stack/upper/gtpu.h index a16e4ca51..53e10be66 100644 --- a/srsenb/hdr/stack/upper/gtpu.h +++ b/srsenb/hdr/stack/upper/gtpu.h @@ -49,7 +49,7 @@ struct gtpu_tunnel { uint32_t fwd_teid_in = 0; ///< forward Rx SDUs to this TEID uint32_t prior_teid_in = 0; ///< buffer bearer SDUs until this TEID receives an End Marker srsran::unique_timer rx_timer; - std::vector > buffer; + srsran::byte_buffer_pool_ptr, 512> > buffer; }; class gtpu_tunnel_manager diff --git a/srsenb/src/stack/upper/gtpu.cc b/srsenb/src/stack/upper/gtpu.cc index ed99d0919..0aa861dfe 100644 --- a/srsenb/src/stack/upper/gtpu.cc +++ b/srsenb/src/stack/upper/gtpu.cc @@ -322,6 +322,7 @@ uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t if (props->flush_before_teidin_present) { // GTPU should wait for the bearer ctxt to arrive before sending SDUs from DL tunnel to PDCP new_tun->dl_enabled = false; + new_tun->buffer.emplace(); // GTPU should not forward SDUs from main tunnel until the SeNB-TeNB tunnel has been flushed gtpu_tunnel* after_tun = tunnels.find_tunnel(props->flush_before_teidin); if (after_tun == nullptr) { @@ -329,7 +330,8 @@ uint32_t gtpu::add_bearer(uint16_t rnti, uint32_t lcid, uint32_t addr, uint32_t tunnels.remove_tunnel(teid_in); return -1; } - after_tun->dl_enabled = false; + after_tun->dl_enabled = false; + after_tun->buffer.emplace(); after_tun->prior_teid_in_present = true; after_tun->prior_teid_in = teid_in; @@ -378,17 +380,17 @@ void gtpu::set_tunnel_status(uint32_t teidin, bool dl_active) tun->dl_enabled = dl_active; if (dl_active and not old_state) { logger.info( - "Activating GTPU tunnel rnti=0x%x,TEID=%d. %d SDUs currently buffered", tun->rnti, teidin, tun->buffer.size()); + "Activating GTPU tunnel rnti=0x%x,TEID=%d. %d SDUs currently buffered", tun->rnti, teidin, tun->buffer->size()); std::stable_sort( - tun->buffer.begin(), - tun->buffer.end(), + tun->buffer->begin(), + tun->buffer->end(), [](const std::pair& lhs, const std::pair& rhs) { return lhs.first < rhs.first; }); - for (auto& sdu_it : tun->buffer) { + for (auto& sdu_it : *tun->buffer) { pdcp->write_sdu( tun->rnti, tun->lcid, std::move(sdu_it.second), sdu_it.first == undefined_pdcp_sn ? -1 : sdu_it.first); } - tun->buffer.clear(); + tun->buffer.reset(); } } @@ -513,7 +515,7 @@ void gtpu::handle_msg_data_pdu(const gtpu_header_t& header, gtpu_tunnel& rx_tunn pdcp_sn = (header.ext_buffer[1] << 8U) + header.ext_buffer[2]; } if (not rx_tunnel.dl_enabled) { - rx_tunnel.buffer.push_back(std::make_pair(pdcp_sn, std::move(pdu))); + rx_tunnel.buffer->push_back(std::make_pair(pdcp_sn, std::move(pdu))); } else { pdcp->write_sdu(rnti, lcid, std::move(pdu), pdcp_sn == undefined_pdcp_sn ? -1 : (int)pdcp_sn); }