Adding t_reassembly to RLC AM NR

This commit is contained in:
Pedro Alvarez 2021-10-21 13:39:54 +01:00
parent f09020e57f
commit 3f000f0472
5 changed files with 68 additions and 22 deletions

View File

@ -98,7 +98,7 @@ struct rlc_am_nr_config_t {
// Timers Ref: 3GPP TS 38.322 Section 7.3
int32_t t_poll_retx; // Poll retx timeout (ms)
int32_t t_reassambly; // Timer used by rx to detect PDU loss (ms)
int32_t t_reassembly; // Timer used by rx to detect PDU loss (ms)
int32_t t_status_prohibit; // Timer used by rx to prohibit tx of status PDU (ms)
// Configurable Parameters. Ref: 3GPP TS 38.322 Section 7.4

View File

@ -55,7 +55,7 @@ public:
void empty_queue() final;
bool has_data() final;
uint32_t get_buffer_state() final;
void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue);
void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) final;
bool do_status();
uint32_t build_status_pdu(byte_buffer_t* payload, uint32_t nof_bytes);
@ -103,9 +103,6 @@ public:
void stop();
void reestablish();
uint32_t get_sdu_rx_latency_ms();
uint32_t get_rx_buffered_bytes();
// Status PDU
bool get_do_status();
uint32_t get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t len);
@ -115,6 +112,10 @@ public:
void handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rlc_am_nr_pdu_header_t& header);
bool inside_rx_window(uint32_t sn);
// Metrics
uint32_t get_sdu_rx_latency_ms() final;
uint32_t get_rx_buffered_bytes() final;
// Timers
void timer_expired(uint32_t timeout_id);
@ -132,18 +133,6 @@ private:
// Mutexes
std::mutex mutex;
/****************************************************************************
* Rx timers
* Ref: 3GPP TS 38.322 v10.0.0 Section 7.3
***************************************************************************/
srsran::timer_handler::unique_timer status_prohibit_timer;
/****************************************************************************
* Configurable parameters
* Ref: 3GPP TS 38.322 v10.0.0 Section 7.4
***************************************************************************/
rlc_am_nr_config_t cfg = {};
/****************************************************************************
* State Variables
* Ref: 3GPP TS 38.322 v10.0.0 Section 7.1
@ -166,9 +155,22 @@ private:
uint32_t rx_highest_status = 0;
/*
* RX_Next_Highest: This state variable holds the value of the SN following the SN of the RLC SDU with the
* highest SN among received *RLC SDUs. It is initially set to 0.
* highest SN among received RLC SDUs. It is initially set to 0.
*/
uint32_t rx_next_highest = 0;
/****************************************************************************
* Rx timers
* Ref: 3GPP TS 38.322 v10.0.0 Section 7.3
***************************************************************************/
srsran::timer_handler::unique_timer status_prohibit_timer;
srsran::timer_handler::unique_timer reassembly_timer;
/****************************************************************************
* Configurable parameters
* Ref: 3GPP TS 38.322 v10.0.0 Section 7.4
***************************************************************************/
rlc_am_nr_config_t cfg = {};
};
} // namespace srsran

View File

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

View File

@ -241,12 +241,17 @@ bool rlc_am_nr_rx::configure(const rlc_config_t& cfg_)
{
cfg = cfg_.am_nr;
// configure timers
// Configure status prohibit timer
if (cfg.t_status_prohibit > 0) {
status_prohibit_timer.set(static_cast<uint32_t>(cfg.t_status_prohibit),
[this](uint32_t timerid) { timer_expired(timerid); });
}
// Configure t_reassembly timer
if (cfg.t_reassembly > 0) {
reassembly_timer.set(static_cast<uint32_t>(cfg.t_reassembly), [this](uint32_t timerid) { timer_expired(timerid); });
}
return true;
}
@ -405,11 +410,10 @@ uint32_t rlc_am_nr_rx::get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t m
}
status->N_nack = 0;
status->ack_sn = rx_next; // start with lower edge of the rx window
status->ack_sn = rx_highest_status; // ACK RX_Highest_Status
byte_buffer_t tmp_buf;
uint32_t len;
// We don't use segment NACKs - just NACK the full PDU
uint32_t i = status->ack_sn;
while (RX_MOD_BASE_NR(i) <= RX_MOD_BASE_NR(rx_highest_status)) {
if (rx_window.has_sn(i) || i == rx_highest_status) {
@ -445,8 +449,42 @@ bool rlc_am_nr_rx::get_do_status()
void rlc_am_nr_rx::timer_expired(uint32_t timeout_id)
{
std::unique_lock<std::mutex> lock(mutex);
// Status Prohibit
if (status_prohibit_timer.is_valid() && status_prohibit_timer.id() == timeout_id) {
logger->debug("%s Status prohibit timer expired after %dms", parent->rb_name, status_prohibit_timer.duration());
return;
}
// Reassembly
if (reassembly_timer.is_valid() && reassembly_timer.id() == timeout_id) {
logger->debug("%s Reassembly timer expired after %dms", parent->rb_name, reassembly_timer.duration());
/*
* 5.2.3.2.4 Actions when t-Reassembly expires:
* - update RX_Highest_Status to the SN of the first RLC SDU with SN >= RX_Next_Status_Trigger for which not
* all bytes have been received;
* - if RX_Next_Highest> RX_Highest_Status +1: or
* - if RX_Next_Highest = RX_Highest_Status + 1 and there is at least one missing byte segment of the SDU
* associated with SN = RX_Highest_Status before the last byte of all received segments of this SDU:
* - start t-Reassembly;
* - 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*/) {
rx_highest_status = tmp_sn;
break;
}
}
bool restart_reassembly_timer = false;
if (rx_next_highest > rx_highest_status + 1) {
restart_reassembly_timer = true;
}
if (rx_next_highest == rx_highest_status + 1) {
restart_reassembly_timer = true;
}
if (restart_reassembly_timer) {
}
return;
}
}

View File

@ -88,7 +88,7 @@ int basic_test()
int len = rlc2.read_pdu(status_buf.msg, 3);
status_buf.N_bytes = len;
// TESTASSERT(0 == rlc2.get_buffer_state());
TESTASSERT(0 == rlc2.get_buffer_state());
// Assert status is correct
rlc_am_nr_status_pdu_t status_check = {};