lib,rlc_am_nr: added struct to hold state variables. This is consistent

with TX and makes it easier to make getter/setters.
This commit is contained in:
Pedro Alvarez 2021-12-03 16:09:21 +00:00
parent bca9ef2454
commit fea7828d3e
2 changed files with 73 additions and 57 deletions

View File

@ -125,10 +125,39 @@ private:
public:
// Getters/Setters
void set_tx_state(const rlc_am_nr_tx_state_t& st_) { st = st_; } // This should only be used for testing.
rlc_am_nr_tx_state_t get_tx_state() { return st; } // This should only be used for testing.
uint32_t get_tx_window_size() { return tx_window.size(); } // This should only be used for testing.
};
/****************************************************************************
* RX State Variables
* Ref: 3GPP TS 38.322 v16.2.0 Section 7.1
***************************************************************************/
struct rlc_am_nr_rx_state_t {
/*
* RX_Next: This state variable holds the value of the SN following the last in-sequence completely received RLC
* SDU, and it serves as the lower edge of the receiving window. It is initially set to 0, and is updated whenever
* the AM RLC entity receives an RLC SDU with SN = RX_Next.
*/
uint32_t rx_next = 0;
/*
* RX_Next_Status_Trigger: This state variable holds the value of the SN following the SN of the RLC SDU which
* triggered t-Reassembly.
*/
uint32_t rx_next_status_trigger = 0;
/*
* RX_Next_Highest: This state variable holds the highest possible value of the SN which can be indicated by
*"ACK_SN" when a STATUS PDU needs to be constructed. It is initially set to 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
* highest SN among received RLC SDUs. It is initially set to 0.
*/
uint32_t rx_next_highest = 0;
};
// Receiver sub-class
class rlc_am_nr_rx : public rlc_am::rlc_am_base_rx
{
@ -170,7 +199,7 @@ private:
byte_buffer_pool* pool = nullptr;
uint32_t mod_nr = 4096;
inline int32_t rx_mod_base_nr(uint32_t sn) { return ((int32_t)sn - (int32_t)rx_next) % mod_nr; }
inline int32_t rx_mod_base_nr(uint32_t sn) { return ((int32_t)sn - (int32_t)st.rx_next) % mod_nr; }
// RX Window
rlc_ringbuffer_t<rlc_amd_rx_sdu_nr_t, RLC_AM_WINDOW_SIZE> rx_window;
@ -178,32 +207,6 @@ private:
// Mutexes
std::mutex mutex;
/****************************************************************************
* State Variables
* Ref: 3GPP TS 38.322 v16.2.0 Section 7.1
***************************************************************************/
/*
* RX_Next: This state variable holds the value of the SN following the last in-sequence completely received RLC
* SDU, and it serves as the lower edge of the receiving window. It is initially set to 0, and is updated whenever
* the AM RLC entity receives an RLC SDU with SN = RX_Next.
*/
uint32_t rx_next = 0;
/*
* RX_Next_Status_Trigger: This state variable holds the value of the SN following the SN of the RLC SDU which
* triggered t-Reassembly.
*/
uint32_t rx_next_status_trigger = 0;
/*
* RX_Next_Highest: This state variable holds the highest possible value of the SN which can be indicated by
*"ACK_SN" when a STATUS PDU needs to be constructed. It is initially set to 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
* 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 v16.2.0 Section 7.3
@ -216,6 +219,18 @@ private:
* Ref: 3GPP TS 38.322 v16.2.0 Section 7.4
***************************************************************************/
rlc_am_nr_config_t cfg = {};
/****************************************************************************
* Tx state variables
* Ref: 3GPP TS 38.322 v16.2.0 Section 7.1
***************************************************************************/
struct rlc_am_nr_rx_state_t st = {};
public:
// Getters/Setters
void set_rx_state(const rlc_am_nr_rx_state_t& st_) { st = st_; } // This should only be used for testing.
rlc_am_nr_rx_state_t get_rx_state() { return st; } // This should only be used for testing.
uint32_t get_rx_window_size() { return rx_window.size(); } // This should only be used for testing.
};
} // namespace srsran

View File

@ -454,8 +454,8 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
logger->info("%s SN=%d outside rx window [%d:%d] - discarding",
parent->rb_name,
header.sn,
rx_next,
rx_next + RLC_AM_NR_WINDOW_SIZE);
st.rx_next,
st.rx_next + RLC_AM_NR_WINDOW_SIZE);
return;
}
@ -510,8 +510,8 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
// 5.2.3.2.3 Actions when an AMD PDU is placed in the reception buffer
// Update Rx_Next_Highest
if (rx_mod_base_nr(header.sn) >= rx_mod_base_nr(rx_next_highest)) {
rx_next_highest = (header.sn + 1) % MOD;
if (rx_mod_base_nr(header.sn) >= rx_mod_base_nr(st.rx_next_highest)) {
st.rx_next_highest = (header.sn + 1) % MOD;
}
// Update RX_Highest_Status
@ -520,10 +520,10 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
* - 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)) {
if (rx_mod_base_nr(header.sn) == rx_mod_base_nr(st.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) {
uint32_t window_top = st.rx_next + RLC_AM_WINDOW_SIZE;
for (sn_upd = st.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
@ -534,7 +534,7 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
}
// 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;
st.rx_highest_status = sn_upd;
}
/*
@ -542,10 +542,10 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
* - 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)) {
if (rx_mod_base_nr(header.sn) == rx_mod_base_nr(st.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) {
uint32_t window_top = st.rx_next + RLC_AM_WINDOW_SIZE;
for (sn_upd = st.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
@ -559,7 +559,7 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
}
// 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;
st.rx_next = sn_upd;
}
if (reassembly_timer.is_running()) {
@ -581,24 +581,24 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
* - set RX_Next_Status_Trigger to RX_Next_Highest.
*/
bool restart_reassembly_timer = false;
if (rx_next_highest > rx_next + 1) {
if (st.rx_next_highest > st.rx_next + 1) {
restart_reassembly_timer = true;
}
if (rx_next_highest == rx_next + 1 &&
rx_window[rx_next + 1].fully_received == false) { // TODO: does the last by need to be received?
if (st.rx_next_highest == st.rx_next + 1 &&
rx_window[st.rx_next + 1].fully_received == false) { // TODO: does the last by need to be received?
restart_reassembly_timer = true;
}
if (restart_reassembly_timer) {
reassembly_timer.run();
rx_next_status_trigger = rx_next_highest;
st.rx_next_status_trigger = st.rx_next_highest;
}
}
}
bool rlc_am_nr_rx::inside_rx_window(uint32_t sn)
{
return (rx_mod_base_nr(sn) >= rx_mod_base_nr(rx_next)) &&
(rx_mod_base_nr(sn) < rx_mod_base_nr(rx_next + RLC_AM_NR_WINDOW_SIZE));
return (rx_mod_base_nr(sn) >= rx_mod_base_nr(st.rx_next)) &&
(rx_mod_base_nr(sn) < rx_mod_base_nr(st.rx_next + RLC_AM_NR_WINDOW_SIZE));
}
/*
@ -612,12 +612,12 @@ 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 the lower end of the window
status->ack_sn = st.rx_next; // Start with the lower end of the window
byte_buffer_t tmp_buf;
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) {
while (rx_mod_base_nr(i) <= rx_mod_base_nr(st.rx_highest_status)) {
if (rx_window.has_sn(i) || i == st.rx_highest_status) {
// only update ACK_SN if this SN has been received, or if we reached the maximum possible SN
status->ack_sn = i;
} else {
@ -674,22 +674,23 @@ void rlc_am_nr_rx::timer_expired(uint32_t timeout_id)
* - 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++) {
for (uint32_t tmp_sn = st.rx_next_status_trigger; tmp_sn < st.rx_next_status_trigger + RLC_AM_WINDOW_SIZE;
tmp_sn++) {
if (not rx_window.has_sn(tmp_sn) || not rx_window[tmp_sn].fully_received) {
rx_highest_status = tmp_sn;
st.rx_highest_status = tmp_sn;
break;
}
}
bool restart_reassembly_timer = false;
if (rx_next_highest > rx_highest_status + 1) {
if (st.rx_next_highest > st.rx_highest_status + 1) {
restart_reassembly_timer = true;
}
if (rx_next_highest == rx_highest_status + 1 && not rx_window[rx_next_highest].fully_received) {
if (st.rx_next_highest == st.rx_highest_status + 1 && not rx_window[st.rx_next_highest].fully_received) {
restart_reassembly_timer = true;
}
if (restart_reassembly_timer) {
reassembly_timer.run();
rx_next_status_trigger = rx_next_highest;
st.rx_next_status_trigger = st.rx_next_highest;
}
/* 5.3.4 Status reporting:
@ -730,9 +731,9 @@ uint32_t rlc_am_nr_rx::get_rx_buffered_bytes()
void rlc_am_nr_rx::debug_state()
{
logger->debug("RX entity state: Rx_Next %d, Rx_Next_Status_Trigger %d, Rx_Highest_Status %d, Rx_Next_Highest",
rx_next,
rx_next_status_trigger,
rx_highest_status,
rx_next_highest);
st.rx_next,
st.rx_next_status_trigger,
st.rx_highest_status,
st.rx_next_highest);
}
} // namespace srsran