Change the update of rx_next and rx_highest_status.

master
Pedro Alvarez 3 years ago
parent 3f000f0472
commit 4c02407d3e

@ -128,7 +128,7 @@ private:
byte_buffer_pool* pool = nullptr;
// RX Window
rlc_ringbuffer_t<rlc_amd_rx_pdu_nr, RLC_AM_WINDOW_SIZE> rx_window;
rlc_ringbuffer_t<rlc_amd_rx_sdu_nr_t, RLC_AM_WINDOW_SIZE> rx_window;
// Mutexes
std::mutex mutex;

@ -56,6 +56,16 @@ struct rlc_amd_rx_sdu_t {
std::list<rlc_amd_rx_pdu_nr> segments;
};
struct rlc_amd_rx_sdu_nr_t {
uint32_t rlc_sn = 0;
bool fully_received = false;
unique_byte_buffer_t buf;
std::list<rlc_amd_rx_pdu_nr> segments;
rlc_amd_rx_sdu_nr_t() = default;
explicit rlc_amd_rx_sdu_nr_t(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {}
};
///< AM NR Status PDU header (perhaps merge with LTE version)
typedef struct {
rlc_am_nr_control_pdu_type_t cpt;

@ -288,27 +288,38 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
}
// Write to rx window
rlc_amd_rx_pdu_nr& rx_pdu = rx_window.add_pdu(header.sn);
rx_pdu.buf = srsran::make_byte_buffer();
if (rx_pdu.buf == nullptr) {
logger->error("Fatal Error: Couldn't allocate PDU in handle_data_pdu().");
rx_window.remove_pdu(header.sn);
return;
}
rx_pdu.buf->set_timestamp();
// check available space for payload
if (nof_bytes > rx_pdu.buf->get_tailroom()) {
logger->error("%s Discarding SN=%d of size %d B (available space %d B)",
parent->rb_name,
header.sn,
nof_bytes,
rx_pdu.buf->get_tailroom());
return;
if (header.si == rlc_nr_si_field_t::full_sdu) {
// Full SDU received. Add SDU to Rx Window and copy full PDU into SDU buffer.
rlc_amd_rx_sdu_nr_t& rx_sdu = rx_window.add_pdu(header.sn);
rx_sdu.buf = srsran::make_byte_buffer();
if (rx_sdu.buf == nullptr) {
logger->error("Fatal Error: Couldn't allocate PDU in handle_data_pdu().");
rx_window.remove_pdu(header.sn);
return;
}
rx_sdu.buf->set_timestamp();
// check available space for payload
if (nof_bytes > rx_sdu.buf->get_tailroom()) {
logger->error("%s Discarding SN=%d of size %d B (available space %d B)",
parent->rb_name,
header.sn,
nof_bytes,
rx_sdu.buf->get_tailroom());
return;
}
memcpy(rx_sdu.buf->msg, payload + hdr_len, nof_bytes - hdr_len); // Don't copy header
rx_sdu.buf->N_bytes = nof_bytes - hdr_len;
rx_sdu.fully_received = true;
parent->pdcp->write_pdu(parent->lcid, std::move(rx_window[header.sn].buf));
} else {
// Check if all bytes of the RLC SDU with SN = x are received:
// TODO
if (header.si == rlc_nr_si_field_t::first_segment) { // Check whether it's a full SDU
} else if (header.si == rlc_nr_si_field_t::last_segment) {
} else if (header.si == rlc_nr_si_field_t::neither_first_nor_last_segment) {
}
}
memcpy(rx_pdu.buf->msg, payload + hdr_len, nof_bytes - hdr_len); // Don't copy header
rx_pdu.buf->N_bytes = nof_bytes - hdr_len;
rx_pdu.header = header;
// Check poll bit
if (header.p) {
@ -324,71 +335,54 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
rx_next_highest = (header.sn + 1) % MOD;
}
// Check if all bytes of the RLC SDU with SN = x are received:
bool sdu_fully_received = false;
if (header.si == rlc_nr_si_field_t::full_sdu) { // Check whether it's a full SDU
parent->pdcp->write_pdu(parent->lcid, std::move(rx_window[header.sn].buf));
sdu_fully_received = true;
} else {
for (uint32_t i = rx_next; i < rx_next + RLC_AM_WINDOW_SIZE; i++) {
if (rx_window.has_sn(i)) {
if (rx_window[i].header.si == rlc_nr_si_field_t::full_sdu) {
parent->pdcp->write_pdu(parent->lcid, std::move(rx_window[i].buf));
// Update RX_Highest_Status
/*
* - if x = RX_Highest_Status,
* - update RX_Highest_Status to the SN of the first RLC SDU with SN > current RX_Highest_Status for which not all
* bytes have been received.
*/
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) {
uint32_t sn_upd = 0;
uint32_t window_top = rx_next + RLC_AM_WINDOW_SIZE;
for (sn_upd = rx_highest_status; sn_upd < window_top; ++sn_upd) {
if (rx_window.has_sn(sn_upd)) {
if (not rx_window[sn_upd].fully_received) {
break; // first SDU not fully received
}
} else {
// Missing PDU. Cannot deliver SDUs in order. Break
break;
break; // first SDU not fully received
}
}
// Update to the SN of the first SDU with missing bytes.
// If it not exists, update to the end of the rx_window.
rx_highest_status = sn_upd;
}
if (sdu_fully_received) {
// Remove SDU from RX Window
rx_window.remove_pdu(header.sn);
// Update RX_Highest_Status
/*
* - if x = RX_Highest_Status,
* - update RX_Highest_Status to the SN of the first RLC SDU with SN > current RX_Highest_Status for which not all
* bytes have been received.
*/
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) {
bool has_sn_with_missing_bytes = false;
for (uint32_t sn_tmp = rx_highest_status; sn_tmp < rx_highest_status + RLC_AM_WINDOW_SIZE; sn_tmp++) {
if (rx_window.has_sn(sn_tmp)) {
rx_highest_status = sn_tmp;
has_sn_with_missing_bytes = true;
break;
}
}
if (not has_sn_with_missing_bytes) {
// There was no SN with missing bytes on the RX window.
// Updating RX_Highest_Status to RX_Highest_Status + 1
rx_highest_status = header.sn + 1 % MOD;
}
}
/*
* - if x = RX_Next:
* - update RX_Next to the SN of the first RLC SDU with SN > current RX_Next for which not all bytes
* have been received.
*/
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_next)) {
bool has_sn_with_missing_bytes = false;
for (uint32_t sn_tmp = rx_next; sn_tmp < rx_next + RLC_AM_WINDOW_SIZE; sn_tmp++) {
if (rx_window.has_sn(sn_tmp)) {
rx_next = sn_tmp;
has_sn_with_missing_bytes = true;
break;
/*
* - if x = RX_Next:
* - update RX_Next to the SN of the first RLC SDU with SN > current RX_Next for which not all bytes
* have been received.
*/
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_next)) {
uint32_t sn_upd = 0;
uint32_t window_top = rx_next + RLC_AM_WINDOW_SIZE;
for (sn_upd = rx_next; sn_upd < window_top; ++sn_upd) {
if (rx_window.has_sn(sn_upd)) {
if (not rx_window[sn_upd].fully_received) {
break; // first SDU not fully received
}
}
if (not has_sn_with_missing_bytes) {
// There was no SN with missing bytes on the RX window.
// Updating RX_Next to RX_Next + 1
rx_next = header.sn + 1 % MOD;
// RX_Next serves as the lower edge of the receiving window
// As such, we remove any SDU from the window if we update this value
rx_window.remove_pdu(sn_upd);
} else {
break; // first SDU not fully received
}
}
// Update to the SN of the first SDU with missing bytes.
// If it not exists, update to the end of the rx_window.
rx_next = sn_upd;
}
// if t-Reassembly is running: (TODO)
// if t-Reassembly is not running (includes the case t-Reassembly is stopped due to actions above): (TODO)
}
@ -470,7 +464,7 @@ void rlc_am_nr_rx::timer_expired(uint32_t timeout_id)
* - set RX_Next_Status_Trigger to RX_Next_Highest.
*/
for (uint32_t tmp_sn = rx_next_status_trigger; tmp_sn < rx_next_status_trigger + RLC_AM_WINDOW_SIZE; tmp_sn++) {
if (not rx_window.has_sn(tmp_sn) /*|| rx_window[tmp_sn].fully_received*/) {
if (not rx_window.has_sn(tmp_sn) || not rx_window[tmp_sn].fully_received) {
rx_highest_status = tmp_sn;
break;
}
@ -479,10 +473,12 @@ void rlc_am_nr_rx::timer_expired(uint32_t timeout_id)
if (rx_next_highest > rx_highest_status + 1) {
restart_reassembly_timer = true;
}
if (rx_next_highest == rx_highest_status + 1) {
if (rx_next_highest == rx_highest_status + 1 && not rx_window[rx_next_highest].fully_received) {
restart_reassembly_timer = true;
}
if (restart_reassembly_timer) {
reassembly_timer.run();
rx_next_status_trigger = rx_next_highest;
}
return;
}

Loading…
Cancel
Save