lib,rlc_am_nr: status PDU creation supports NACK range

This commit is contained in:
Robert Falkenberg 2022-04-29 16:23:09 +02:00
parent 283199d54f
commit e9156d4ba2
3 changed files with 81 additions and 5 deletions

View File

@ -165,6 +165,8 @@ public:
// NACK helper (for LTE and NR)
struct rlc_status_nack_t {
const static uint16_t so_end_of_sdu = 0xFFFF;
uint32_t nack_sn; // Sequence Number (SN) of first missing SDU
bool has_so; // NACKs continuous sequence of bytes [so_start..so_end]
uint16_t so_start; // First missing byte in SDU with SN=nack_sn

View File

@ -23,7 +23,6 @@
namespace srsran {
const static uint32_t max_tx_queue_size = 256;
const static uint32_t so_end_of_sdu = 0xFFFF;
/****************************************************************************
* RLC AM NR entity
@ -838,7 +837,7 @@ void rlc_am_nr_tx::handle_control_pdu(uint8_t* payload, uint32_t nof_bytes)
// First SN
nack.has_so = true;
nack.so_start = status.nacks[nack_idx].so_start;
nack.so_end = so_end_of_sdu;
nack.so_end = rlc_status_nack_t::so_end_of_sdu;
} else if (range_sn == (status.nacks[nack_idx].nack_sn + status.nacks[nack_idx].nack_range - 1)) {
// Last SN
nack.has_so = true;
@ -1743,7 +1742,7 @@ uint32_t rlc_am_nr_rx::get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t m
nack.nack_sn = i;
nack.has_so = true;
nack.so_start = last_so;
nack.so_end = so_end_of_sdu;
nack.so_end = rlc_status_nack_t::so_end_of_sdu;
status->push_nack(nack);
RlcDebug(
"Final segment missing. NACK_SN=%d. SO_start=%d, SO_end=%d", nack.nack_sn, nack.so_start, nack.so_end);

View File

@ -32,10 +32,85 @@ void rlc_am_nr_status_pdu_t::reset()
packed_size_ = rlc_am_nr_status_pdu_sizeof_header_ack_sn;
}
static bool is_continuous_sequence(const rlc_status_nack_t& left, const rlc_status_nack_t& right)
{
// SN must be continuous
if (right.nack_sn != left.has_nack_range ? left.nack_sn + left.nack_range : left.nack_sn + 1) {
return false;
}
// Segments on left side (if present) must reach the end of sdu
if (left.has_so && left.so_end != rlc_status_nack_t::so_end_of_sdu) {
return false;
}
// Segments on right side (if present) must start from the beginning
if (right.has_so && right.so_start != 0) {
return false;
}
return true;
}
void rlc_am_nr_status_pdu_t::push_nack(const rlc_status_nack_t& nack)
{
nacks_.push_back(nack);
packed_size_ += nack_size(nack);
if (nacks_.size() == 0) {
nacks_.push_back(nack);
packed_size_ += nack_size(nack);
return;
}
rlc_status_nack_t& prev = nacks_.back();
if (is_continuous_sequence(prev, nack) == false) {
nacks_.push_back(nack);
packed_size_ += nack_size(nack);
return;
}
// expand previous NACK
// subtract size of previous NACK (add updated size later)
packed_size_ -= nack_size(prev);
// enable and update NACK range
if (nack.has_nack_range == true) {
if (prev.has_nack_range == true) {
// [NACK range][NACK range]
prev.nack_range += nack.nack_range;
} else {
// [NACK SDU][NACK range]
prev.nack_range = nack.nack_range + 1;
prev.has_nack_range = true;
}
} else {
if (prev.has_nack_range == true) {
// [NACK range][NACK SDU]
prev.nack_range++;
} else {
// [NACK SDU][NACK SDU]
prev.nack_range = 2;
prev.has_nack_range = true;
}
}
// enable and update segment offsets (if required)
if (nack.has_so == true) {
if (prev.has_so == false) {
// [NACK SDU][NACK segm]
prev.has_so = true;
prev.so_start = 0;
}
// [NACK SDU][NACK segm] or [NACK segm][NACK segm]
prev.so_end = nack.so_end;
} else {
if (prev.has_so == true) {
// [NACK segm][NACK SDU]
prev.so_end = rlc_status_nack_t::so_end_of_sdu;
}
// [NACK segm][NACK SDU] or [NACK SDU][NACK SDU]
}
// add updated size
packed_size_ += nack_size(prev);
}
bool rlc_am_nr_status_pdu_t::trim(uint32_t max_packed_size)