rlc am - use of circular_map container in RLC AM window

The window elements are not being correctly cleaned up when clear() is called
or when overwritten by newer SN. Furthermore, the window count member is not being
correctly updated when the insertion of a newer SN overwrites the previous one.

I used the circular_map container to avoid this sort of bugs
master
Francisco 4 years ago committed by Francisco Paisana
parent c4069b58af
commit ebbb74e639

@ -170,6 +170,16 @@ public:
return iterator(this, idx); return iterator(this, idx);
} }
template <typename U>
void overwrite(K id, U&& obj)
{
size_t idx = id % N;
if (present[idx]) {
erase(buffer[idx].get().first);
}
insert(id, std::forward<U>(obj));
}
bool erase(K id) bool erase(K id)
{ {
if (not contains(id)) { if (not contains(id)) {

@ -15,6 +15,7 @@
#include "srsran/adt/accumulators.h" #include "srsran/adt/accumulators.h"
#include "srsran/adt/circular_array.h" #include "srsran/adt/circular_array.h"
#include "srsran/adt/circular_map.h"
#include "srsran/common/buffer_pool.h" #include "srsran/common/buffer_pool.h"
#include "srsran/common/common.h" #include "srsran/common/common.h"
#include "srsran/common/srsran_assert.h" #include "srsran/common/srsran_assert.h"
@ -73,53 +74,39 @@ struct pdcp_sdu_info_t {
template <class T> template <class T>
struct rlc_ringbuffer_t { struct rlc_ringbuffer_t {
rlc_ringbuffer_t() { clear(); }
T& add_pdu(size_t sn) T& add_pdu(size_t sn)
{ {
srsran_expect(not has_sn(sn), "The same SN=%zd should not be added twice", sn); srsran_expect(not has_sn(sn), "The same SN=%zd should not be added twice", sn);
window.overwrite(sn, T{});
window[sn].rlc_sn = sn; window[sn].rlc_sn = sn;
active_flag[sn] = true;
count++;
return window[sn]; return window[sn];
} }
void remove_pdu(size_t sn) void remove_pdu(size_t sn)
{ {
srsran_expect(has_sn(sn), "The removed SN=%zd is not in the window", sn); srsran_expect(has_sn(sn), "The removed SN=%zd is not in the window", sn);
window[sn] = {}; window.erase(sn);
active_flag[sn] = false;
count--;
}
T& operator[](size_t 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; }
bool empty() const { return count == 0; }
void clear()
{
std::fill(active_flag.begin(), active_flag.end(), false);
count = 0;
} }
T& operator[](size_t sn) { return window[sn]; }
size_t size() const { return window.size(); }
bool empty() const { return window.empty(); }
void clear() { window.clear(); }
bool has_sn(uint32_t sn) const { return active_flag[sn] and (window[sn].rlc_sn == sn); } bool has_sn(uint32_t sn) const { return window.contains(sn); }
// Return the sum data bytes of all active PDUs (check PDU is non-null) // Return the sum data bytes of all active PDUs (check PDU is non-null)
uint32_t get_buffered_bytes() uint32_t get_buffered_bytes()
{ {
uint32_t buff_size = 0; uint32_t buff_size = 0;
for (const auto& pdu : window) { for (const auto& pdu : window) {
if (pdu.buf != nullptr) { if (pdu.second.buf != nullptr) {
buff_size += pdu.buf->N_bytes; buff_size += pdu.second.buf->N_bytes;
} }
} }
return buff_size; return buff_size;
} }
private: private:
size_t count = 0; srsran::static_circular_map<uint32_t, T, RLC_AM_WINDOW_SIZE> window;
srsran::circular_array<bool, RLC_AM_WINDOW_SIZE> active_flag = {};
srsran::circular_array<T, RLC_AM_WINDOW_SIZE> window;
}; };
struct buffered_pdcp_pdu_list { struct buffered_pdcp_pdu_list {

Loading…
Cancel
Save