mirror of https://github.com/PentHertz/srsLTE.git
Adding t_reassembly to RLC AM NR
This commit is contained in:
parent
f09020e57f
commit
3f000f0472
|
@ -98,7 +98,7 @@ struct rlc_am_nr_config_t {
|
||||||
|
|
||||||
// Timers Ref: 3GPP TS 38.322 Section 7.3
|
// Timers Ref: 3GPP TS 38.322 Section 7.3
|
||||||
int32_t t_poll_retx; // Poll retx timeout (ms)
|
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)
|
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
|
// Configurable Parameters. Ref: 3GPP TS 38.322 Section 7.4
|
||||||
|
|
|
@ -55,7 +55,7 @@ public:
|
||||||
void empty_queue() final;
|
void empty_queue() final;
|
||||||
bool has_data() final;
|
bool has_data() final;
|
||||||
uint32_t get_buffer_state() 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();
|
bool do_status();
|
||||||
uint32_t build_status_pdu(byte_buffer_t* payload, uint32_t nof_bytes);
|
uint32_t build_status_pdu(byte_buffer_t* payload, uint32_t nof_bytes);
|
||||||
|
@ -103,9 +103,6 @@ public:
|
||||||
void stop();
|
void stop();
|
||||||
void reestablish();
|
void reestablish();
|
||||||
|
|
||||||
uint32_t get_sdu_rx_latency_ms();
|
|
||||||
uint32_t get_rx_buffered_bytes();
|
|
||||||
|
|
||||||
// Status PDU
|
// Status PDU
|
||||||
bool get_do_status();
|
bool get_do_status();
|
||||||
uint32_t get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t len);
|
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);
|
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);
|
bool inside_rx_window(uint32_t sn);
|
||||||
|
|
||||||
|
// Metrics
|
||||||
|
uint32_t get_sdu_rx_latency_ms() final;
|
||||||
|
uint32_t get_rx_buffered_bytes() final;
|
||||||
|
|
||||||
// Timers
|
// Timers
|
||||||
void timer_expired(uint32_t timeout_id);
|
void timer_expired(uint32_t timeout_id);
|
||||||
|
|
||||||
|
@ -132,18 +133,6 @@ private:
|
||||||
// Mutexes
|
// Mutexes
|
||||||
std::mutex mutex;
|
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
|
* State Variables
|
||||||
* Ref: 3GPP TS 38.322 v10.0.0 Section 7.1
|
* Ref: 3GPP TS 38.322 v10.0.0 Section 7.1
|
||||||
|
@ -166,9 +155,22 @@ private:
|
||||||
uint32_t rx_highest_status = 0;
|
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
|
* 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;
|
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
|
} // namespace srsran
|
||||||
|
|
|
@ -50,6 +50,12 @@ struct rlc_amd_rx_pdu_nr {
|
||||||
explicit rlc_amd_rx_pdu_nr(uint32_t rlc_sn_) : rlc_sn(rlc_sn_) {}
|
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)
|
///< 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;
|
||||||
|
|
|
@ -241,12 +241,17 @@ bool rlc_am_nr_rx::configure(const rlc_config_t& cfg_)
|
||||||
{
|
{
|
||||||
cfg = cfg_.am_nr;
|
cfg = cfg_.am_nr;
|
||||||
|
|
||||||
// configure timers
|
// Configure status prohibit timer
|
||||||
if (cfg.t_status_prohibit > 0) {
|
if (cfg.t_status_prohibit > 0) {
|
||||||
status_prohibit_timer.set(static_cast<uint32_t>(cfg.t_status_prohibit),
|
status_prohibit_timer.set(static_cast<uint32_t>(cfg.t_status_prohibit),
|
||||||
[this](uint32_t timerid) { timer_expired(timerid); });
|
[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;
|
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->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;
|
byte_buffer_t tmp_buf;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
|
||||||
// We don't use segment NACKs - just NACK the full PDU
|
|
||||||
uint32_t i = status->ack_sn;
|
uint32_t i = status->ack_sn;
|
||||||
while (RX_MOD_BASE_NR(i) <= RX_MOD_BASE_NR(rx_highest_status)) {
|
while (RX_MOD_BASE_NR(i) <= RX_MOD_BASE_NR(rx_highest_status)) {
|
||||||
if (rx_window.has_sn(i) || i == 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)
|
void rlc_am_nr_rx::timer_expired(uint32_t timeout_id)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
// Status Prohibit
|
||||||
if (status_prohibit_timer.is_valid() && status_prohibit_timer.id() == timeout_id) {
|
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());
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ int basic_test()
|
||||||
int len = rlc2.read_pdu(status_buf.msg, 3);
|
int len = rlc2.read_pdu(status_buf.msg, 3);
|
||||||
status_buf.N_bytes = len;
|
status_buf.N_bytes = len;
|
||||||
|
|
||||||
// TESTASSERT(0 == rlc2.get_buffer_state());
|
TESTASSERT(0 == rlc2.get_buffer_state());
|
||||||
|
|
||||||
// Assert status is correct
|
// Assert status is correct
|
||||||
rlc_am_nr_status_pdu_t status_check = {};
|
rlc_am_nr_status_pdu_t status_check = {};
|
||||||
|
|
Loading…
Reference in New Issue