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; byte_buffer_pool* pool = nullptr;
// RX Window // 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 // Mutexes
std::mutex mutex; std::mutex mutex;

@ -56,6 +56,16 @@ struct rlc_amd_rx_sdu_t {
std::list<rlc_amd_rx_pdu_nr> segments; 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) ///< AM NR Status PDU header (perhaps merge with LTE version)
typedef struct { typedef struct {
rlc_am_nr_control_pdu_type_t cpt; 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 // Write to rx window
rlc_amd_rx_pdu_nr& rx_pdu = rx_window.add_pdu(header.sn); if (header.si == rlc_nr_si_field_t::full_sdu) {
rx_pdu.buf = srsran::make_byte_buffer(); // Full SDU received. Add SDU to Rx Window and copy full PDU into SDU buffer.
if (rx_pdu.buf == nullptr) { 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()."); logger->error("Fatal Error: Couldn't allocate PDU in handle_data_pdu().");
rx_window.remove_pdu(header.sn); rx_window.remove_pdu(header.sn);
return; return;
} }
rx_pdu.buf->set_timestamp(); rx_sdu.buf->set_timestamp();
// check available space for payload // check available space for payload
if (nof_bytes > rx_pdu.buf->get_tailroom()) { if (nof_bytes > rx_sdu.buf->get_tailroom()) {
logger->error("%s Discarding SN=%d of size %d B (available space %d B)", logger->error("%s Discarding SN=%d of size %d B (available space %d B)",
parent->rb_name, parent->rb_name,
header.sn, header.sn,
nof_bytes, nof_bytes,
rx_pdu.buf->get_tailroom()); rx_sdu.buf->get_tailroom());
return; return;
} }
memcpy(rx_pdu.buf->msg, payload + hdr_len, nof_bytes - hdr_len); // Don't copy header memcpy(rx_sdu.buf->msg, payload + hdr_len, nof_bytes - hdr_len); // Don't copy header
rx_pdu.buf->N_bytes = nof_bytes - hdr_len; rx_sdu.buf->N_bytes = nof_bytes - hdr_len;
rx_pdu.header = header; 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) {
}
}
// Check poll bit // Check poll bit
if (header.p) { if (header.p) {
@ -324,28 +335,6 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
rx_next_highest = (header.sn + 1) % MOD; 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));
}
} else {
// Missing PDU. Cannot deliver SDUs in order. Break
break;
}
}
}
if (sdu_fully_received) {
// Remove SDU from RX Window
rx_window.remove_pdu(header.sn);
// Update RX_Highest_Status // Update RX_Highest_Status
/* /*
* - if x = RX_Highest_Status, * - if x = RX_Highest_Status,
@ -353,19 +342,20 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
* bytes have been received. * bytes have been received.
*/ */
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) { if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) {
bool has_sn_with_missing_bytes = false; uint32_t sn_upd = 0;
for (uint32_t sn_tmp = rx_highest_status; sn_tmp < rx_highest_status + RLC_AM_WINDOW_SIZE; sn_tmp++) { uint32_t window_top = rx_next + RLC_AM_WINDOW_SIZE;
if (rx_window.has_sn(sn_tmp)) { for (sn_upd = rx_highest_status; sn_upd < window_top; ++sn_upd) {
rx_highest_status = sn_tmp; if (rx_window.has_sn(sn_upd)) {
has_sn_with_missing_bytes = true; if (not rx_window[sn_upd].fully_received) {
break; break; // first SDU not fully received
} }
} else {
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_Highest_Status to RX_Highest_Status + 1
rx_highest_status = header.sn + 1 % MOD;
} }
// 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;
} }
/* /*
@ -374,21 +364,25 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
* have been received. * have been received.
*/ */
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_next)) { if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_next)) {
bool has_sn_with_missing_bytes = false; uint32_t sn_upd = 0;
for (uint32_t sn_tmp = rx_next; sn_tmp < rx_next + RLC_AM_WINDOW_SIZE; sn_tmp++) { uint32_t window_top = rx_next + RLC_AM_WINDOW_SIZE;
if (rx_window.has_sn(sn_tmp)) { for (sn_upd = rx_next; sn_upd < window_top; ++sn_upd) {
rx_next = sn_tmp; if (rx_window.has_sn(sn_upd)) {
has_sn_with_missing_bytes = true; if (not rx_window[sn_upd].fully_received) {
break; break; // first SDU not fully received
} }
} // RX_Next serves as the lower edge of the receiving window
if (not has_sn_with_missing_bytes) { // As such, we remove any SDU from the window if we update this value
// There was no SN with missing bytes on the RX window. rx_window.remove_pdu(sn_upd);
// Updating RX_Next to RX_Next + 1 } else {
rx_next = header.sn + 1 % MOD; 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 running: (TODO)
// if t-Reassembly is not running (includes the case t-Reassembly is stopped due to actions above): (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. * - 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++) { 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; rx_highest_status = tmp_sn;
break; break;
} }
@ -479,10 +473,12 @@ void rlc_am_nr_rx::timer_expired(uint32_t timeout_id)
if (rx_next_highest > rx_highest_status + 1) { if (rx_next_highest > rx_highest_status + 1) {
restart_reassembly_timer = true; 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; restart_reassembly_timer = true;
} }
if (restart_reassembly_timer) { if (restart_reassembly_timer) {
reassembly_timer.run();
rx_next_status_trigger = rx_next_highest;
} }
return; return;
} }

Loading…
Cancel
Save