Merge branch 'next' into agpl_next

This commit is contained in:
Codebot 2022-06-12 21:12:20 +00:00 committed by SRS codebot
commit ac06cf7453
6 changed files with 238 additions and 14 deletions

View File

@ -188,7 +188,7 @@ struct rlc_status_nack_t {
has_so = false;
nack_sn = 0;
so_start = 0;
so_end = 0;
so_end = so_end_of_sdu;
has_nack_range = false;
nack_range = 0;
}

View File

@ -699,8 +699,8 @@ int rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_bytes)
}
// do not build any more PDU if window is already full
if (tx_sdu == NULL && tx_window.size() >= RLC_AM_WINDOW_SIZE) {
RlcInfo("Tx window full.");
if (tx_window.size() >= RLC_AM_WINDOW_SIZE) {
RlcInfo("Cannot build data PDU - Tx window full.");
return 0;
}

View File

@ -184,6 +184,13 @@ uint32_t rlc_am_nr_tx::build_new_pdu(uint8_t* payload, uint32_t nof_bytes)
RlcInfo("Not enough bytes for payload plus header. nof_bytes=%d", nof_bytes);
return 0;
}
// do not build any more PDU if window is already full
if (tx_window->size() >= RLC_AM_WINDOW_SIZE) {
RlcInfo("Cannot build data PDU - Tx window full.");
return 0;
}
// Read new SDU from TX queue
unique_byte_buffer_t tx_sdu;
RlcDebug("Reading from RLC SDU queue. Queue size %d", tx_sdu_queue.size());
@ -856,17 +863,16 @@ void rlc_am_nr_tx::handle_control_pdu(uint8_t* payload, uint32_t nof_bytes)
rlc_status_nack_t nack = {};
nack.nack_sn = range_sn;
if (status.nacks[nack_idx].has_so) {
// Apply so_start to first range item
if (range_sn == status.nacks[nack_idx].nack_sn) {
// First SN
nack.has_so = true;
nack.so_start = status.nacks[nack_idx].so_start;
nack.so_end = rlc_status_nack_t::so_end_of_sdu;
} else if (range_sn == (status.nacks[nack_idx].nack_sn + status.nacks[nack_idx].nack_range - 1)) {
// Last SN
nack.has_so = true;
// This might be first+last item at the same time, so don't change so_start here
}
// Apply so_end to last range item
if (range_sn == (status.nacks[nack_idx].nack_sn + status.nacks[nack_idx].nack_range - 1)) {
nack.so_end = status.nacks[nack_idx].so_end;
}
// Enable has_so only if the offsets do not span the whole SDU
nack.has_so = (nack.so_start != 0) || (nack.so_end != rlc_status_nack_t::so_end_of_sdu);
}
handle_nack(nack, retx_sn_set);
}

View File

@ -121,7 +121,6 @@ int test_tx_all(srslog::basic_logger& logger)
auto& test_logger = srslog::fetch_basic_logger("TESTER ");
srsran::test_delimit_logger delimiter("TX COUNT 4096, 12 bit SN");
test_tx_helper tx_helper(srsran::PDCP_SN_LEN_12, logger);
n_packets = 2049;
n_packets = 4097;
srsran::unique_byte_buffer_t pdu_exp_count4096_len12 = srsran::make_byte_buffer();
pdu_exp_count4096_len12->append_bytes(pdu1_count4096_snlen12, sizeof(pdu1_count4096_snlen12));

View File

@ -2846,6 +2846,220 @@ int rx_nack_range_with_so_test(rlc_am_nr_sn_size_t sn_size)
return SRSRAN_SUCCESS;
}
int rx_nack_range_with_so_starting_with_full_sdu_test(rlc_am_nr_sn_size_t sn_size)
{
rlc_am_tester tester;
timer_handler timers(8);
auto& test_logger = srslog::fetch_basic_logger("TESTER ");
rlc_am rlc1(srsran_rat_t::nr, srslog::fetch_basic_logger("RLC_AM_1"), 1, &tester, &tester, &timers);
rlc_am rlc2(srsran_rat_t::nr, srslog::fetch_basic_logger("RLC_AM_2"), 1, &tester, &tester, &timers);
std::string str =
"Rx NACK range test with SO starting with full SDU (" + std::to_string(to_number(sn_size)) + " bit SN)";
test_delimit_logger delimiter(str.c_str());
rlc_am_nr_tx* tx1 = dynamic_cast<rlc_am_nr_tx*>(rlc1.get_tx());
rlc_am_nr_rx* rx1 = dynamic_cast<rlc_am_nr_rx*>(rlc1.get_rx());
rlc_am_nr_tx* tx2 = dynamic_cast<rlc_am_nr_tx*>(rlc2.get_tx());
rlc_am_nr_rx* rx2 = dynamic_cast<rlc_am_nr_rx*>(rlc2.get_rx());
auto rlc_cnfg = rlc_config_t::default_rlc_am_nr_config(to_number(sn_size));
rlc_cnfg.am_nr.t_poll_retx = -1;
if (not rlc1.configure(rlc_cnfg)) {
return -1;
}
// after configuring entity
TESTASSERT(0 == rlc1.get_buffer_state());
int n_sdu_bufs = 5;
int n_pdu_bufs = 15;
// Push 5 SDUs into RLC1
std::vector<unique_byte_buffer_t> sdu_bufs(n_sdu_bufs);
constexpr uint32_t payload_size = 3; // Give the SDU the size of 3 bytes
uint32_t header_size = sn_size == rlc_am_nr_sn_size_t::size12bits ? 2 : 3;
for (int i = 0; i < n_sdu_bufs; i++) {
sdu_bufs[i] = srsran::make_byte_buffer();
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = payload_size; // Give each buffer a size of 3 bytes
sdu_bufs[i]->md.pdcp_sn = i; // PDCP SN for notifications
rlc1.write_sdu(std::move(sdu_bufs[i]));
}
uint32_t expected_buffer_state = (header_size + payload_size) * n_sdu_bufs;
TESTASSERT_EQ(expected_buffer_state, rlc1.get_buffer_state());
constexpr uint32_t so_size = 2;
constexpr uint32_t segment_size = 1;
uint32_t pdu_size_whole = header_size + payload_size;
uint32_t pdu_size_first = header_size + segment_size;
uint32_t pdu_size_continued = header_size + so_size + segment_size;
// Read 15 PDUs from RLC1
std::vector<unique_byte_buffer_t> pdu_bufs(n_pdu_bufs);
for (int i = 0; i < n_pdu_bufs; i++) {
// First also test buffer state
uint32_t remaining_total_bytes = (payload_size * n_sdu_bufs) - (i * segment_size);
uint32_t remaining_full_sdus = remaining_total_bytes / payload_size;
uint32_t remaining_seg_bytes = remaining_total_bytes % payload_size;
uint32_t buffer_state_full_sdus = (header_size + payload_size) * remaining_full_sdus;
uint32_t buffer_state_seg_sdu = remaining_seg_bytes == 0 ? 0 : (header_size + so_size + remaining_seg_bytes);
expected_buffer_state = buffer_state_full_sdus + buffer_state_seg_sdu;
TESTASSERT_EQ(expected_buffer_state, rlc1.get_buffer_state());
pdu_bufs[i] = srsran::make_byte_buffer();
if (i == 3) {
// Special handling for SDU SN=1 (i==3): send as a whole, not segmented
uint32_t len = rlc1.read_pdu(pdu_bufs[i]->msg, pdu_size_whole); // 2 bytes for header + 3 byte payload
pdu_bufs[i]->N_bytes = len;
TESTASSERT_EQ(pdu_size_whole, len);
// update i to skip 2 segments
i += 2;
} else {
if (i == 0 || i == 6 || i == 9 || i == 12) {
// First segment, no SO
uint32_t len = rlc1.read_pdu(pdu_bufs[i]->msg, pdu_size_first); // 2 bytes for header + 1 byte payload
pdu_bufs[i]->N_bytes = len;
TESTASSERT_EQ(pdu_size_first, len);
} else {
// Middle or last segment, SO present
uint32_t len = rlc1.read_pdu(pdu_bufs[i]->msg, pdu_size_continued); // 4 bytes for header + 1 byte payload
pdu_bufs[i]->N_bytes = len;
TESTASSERT_EQ(pdu_size_continued, len);
}
}
}
// Deliver dummy status report with nack range betwen PDU 4 and 10.
rlc_am_nr_status_pdu_t status(sn_size);
status.ack_sn = 5;
rlc_status_nack_t nack = {};
nack.nack_sn = 1;
nack.has_nack_range = true;
nack.nack_range = 3;
nack.has_so = true;
nack.so_start = 0;
nack.so_end = 0;
status.push_nack(nack);
byte_buffer_t status_pdu;
rlc_am_nr_write_status_pdu(status, sn_size, &status_pdu);
rlc1.write_pdu(status_pdu.msg, status_pdu.N_bytes);
TESTASSERT_EQ(pdu_size_whole + 2 * pdu_size_first + 2 * pdu_size_continued, rlc1.get_buffer_state());
return SRSRAN_SUCCESS;
}
int rx_nack_range_with_so_ending_with_full_sdu_test(rlc_am_nr_sn_size_t sn_size)
{
rlc_am_tester tester;
timer_handler timers(8);
auto& test_logger = srslog::fetch_basic_logger("TESTER ");
rlc_am rlc1(srsran_rat_t::nr, srslog::fetch_basic_logger("RLC_AM_1"), 1, &tester, &tester, &timers);
rlc_am rlc2(srsran_rat_t::nr, srslog::fetch_basic_logger("RLC_AM_2"), 1, &tester, &tester, &timers);
std::string str =
"Rx NACK range test with SO starting with full SDU (" + std::to_string(to_number(sn_size)) + " bit SN)";
test_delimit_logger delimiter(str.c_str());
rlc_am_nr_tx* tx1 = dynamic_cast<rlc_am_nr_tx*>(rlc1.get_tx());
rlc_am_nr_rx* rx1 = dynamic_cast<rlc_am_nr_rx*>(rlc1.get_rx());
rlc_am_nr_tx* tx2 = dynamic_cast<rlc_am_nr_tx*>(rlc2.get_tx());
rlc_am_nr_rx* rx2 = dynamic_cast<rlc_am_nr_rx*>(rlc2.get_rx());
auto rlc_cnfg = rlc_config_t::default_rlc_am_nr_config(to_number(sn_size));
rlc_cnfg.am_nr.t_poll_retx = -1;
if (not rlc1.configure(rlc_cnfg)) {
return -1;
}
// after configuring entity
TESTASSERT(0 == rlc1.get_buffer_state());
int n_sdu_bufs = 5;
int n_pdu_bufs = 15;
// Push 5 SDUs into RLC1
std::vector<unique_byte_buffer_t> sdu_bufs(n_sdu_bufs);
constexpr uint32_t payload_size = 3; // Give the SDU the size of 3 bytes
uint32_t header_size = sn_size == rlc_am_nr_sn_size_t::size12bits ? 2 : 3;
for (int i = 0; i < n_sdu_bufs; i++) {
sdu_bufs[i] = srsran::make_byte_buffer();
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = payload_size; // Give each buffer a size of 3 bytes
sdu_bufs[i]->md.pdcp_sn = i; // PDCP SN for notifications
rlc1.write_sdu(std::move(sdu_bufs[i]));
}
uint32_t expected_buffer_state = (header_size + payload_size) * n_sdu_bufs;
TESTASSERT_EQ(expected_buffer_state, rlc1.get_buffer_state());
constexpr uint32_t so_size = 2;
constexpr uint32_t segment_size = 1;
uint32_t pdu_size_whole = header_size + payload_size;
uint32_t pdu_size_first = header_size + segment_size;
uint32_t pdu_size_continued = header_size + so_size + segment_size;
// Read 15 PDUs from RLC1
std::vector<unique_byte_buffer_t> pdu_bufs(n_pdu_bufs);
for (int i = 0; i < n_pdu_bufs; i++) {
// First also test buffer state
uint32_t remaining_total_bytes = (payload_size * n_sdu_bufs) - (i * segment_size);
uint32_t remaining_full_sdus = remaining_total_bytes / payload_size;
uint32_t remaining_seg_bytes = remaining_total_bytes % payload_size;
uint32_t buffer_state_full_sdus = (header_size + payload_size) * remaining_full_sdus;
uint32_t buffer_state_seg_sdu = remaining_seg_bytes == 0 ? 0 : (header_size + so_size + remaining_seg_bytes);
expected_buffer_state = buffer_state_full_sdus + buffer_state_seg_sdu;
TESTASSERT_EQ(expected_buffer_state, rlc1.get_buffer_state());
pdu_bufs[i] = srsran::make_byte_buffer();
if (i == 9) {
// Special handling for SDU SN=3 (i==9): send as a whole, not segmented
uint32_t len = rlc1.read_pdu(pdu_bufs[i]->msg, pdu_size_whole); // 2 bytes for header + 3 byte payload
pdu_bufs[i]->N_bytes = len;
TESTASSERT_EQ(pdu_size_whole, len);
// update i to skip 2 segments
i += 2;
} else {
if (i == 0 || i == 3 || i == 6 || i == 12) {
// First segment, no SO
uint32_t len = rlc1.read_pdu(pdu_bufs[i]->msg, pdu_size_first); // 2 bytes for header + 1 byte payload
pdu_bufs[i]->N_bytes = len;
TESTASSERT_EQ(pdu_size_first, len);
} else {
// Middle or last segment, SO present
uint32_t len = rlc1.read_pdu(pdu_bufs[i]->msg, pdu_size_continued); // 4 bytes for header + 1 byte payload
pdu_bufs[i]->N_bytes = len;
TESTASSERT_EQ(pdu_size_continued, len);
}
}
}
// Deliver dummy status report with nack range betwen PDU 6 and 12.
rlc_am_nr_status_pdu_t status(sn_size);
status.ack_sn = 5;
rlc_status_nack_t nack = {};
nack.nack_sn = 1;
nack.has_nack_range = true;
nack.nack_range = 3;
nack.has_so = true;
nack.so_start = 2;
nack.so_end = rlc_status_nack_t::so_end_of_sdu;
status.push_nack(nack);
byte_buffer_t status_pdu;
rlc_am_nr_write_status_pdu(status, sn_size, &status_pdu);
rlc1.write_pdu(status_pdu.msg, status_pdu.N_bytes);
TESTASSERT_EQ(1 * pdu_size_first + 3 * pdu_size_continued + pdu_size_whole, rlc1.get_buffer_state());
return SRSRAN_SUCCESS;
}
int out_of_order_status(rlc_am_nr_sn_size_t sn_size)
{
rlc_am_tester tester;
@ -2963,6 +3177,8 @@ int main()
TESTASSERT(poll_retx_expiry(sn_size) == SRSRAN_SUCCESS);
TESTASSERT(rx_nack_range_no_so_test(sn_size) == SRSRAN_SUCCESS);
TESTASSERT(rx_nack_range_with_so_test(sn_size) == SRSRAN_SUCCESS);
TESTASSERT(rx_nack_range_with_so_starting_with_full_sdu_test(sn_size) == SRSRAN_SUCCESS);
TESTASSERT(rx_nack_range_with_so_ending_with_full_sdu_test(sn_size) == SRSRAN_SUCCESS);
TESTASSERT(out_of_order_status(sn_size) == SRSRAN_SUCCESS);
}
return SRSRAN_SUCCESS;

View File

@ -55,10 +55,11 @@ bool phy_common::init(const phy_cell_cfg_list_t& cell_list_,
// Instantiate DL channel emulator
if (params.dl_channel_args.enable) {
int channel_prbs = (cell_list_lte.empty()) ? cell_list_nr[0].carrier.nof_prb : cell_list_lte[0].cell.nof_prb;
dl_channel = srsran::channel_ptr(
new srsran::channel(params.dl_channel_args, get_nof_rf_channels(), srslog::fetch_basic_logger("PHY")));
dl_channel->set_srate((uint32_t)srsran_sampling_freq_hz(cell_list_lte[0].cell.nof_prb));
dl_channel->set_signal_power_dBfs(srsran_enb_dl_get_maximum_signal_power_dBfs(cell_list_lte[0].cell.nof_prb));
dl_channel->set_srate((uint32_t)srsran_sampling_freq_hz(channel_prbs));
dl_channel->set_signal_power_dBfs(srsran_enb_dl_get_maximum_signal_power_dBfs(channel_prbs));
}
// Create grants
@ -67,7 +68,9 @@ bool phy_common::init(const phy_cell_cfg_list_t& cell_list_,
}
// Set UE PHY data-base stack and configuration
ue_db.init(stack, params, cell_list_lte);
if (!cell_list_lte.empty()) {
ue_db.init(stack, params, cell_list_lte);
}
if (mcch_configured) {
build_mch_table();
build_mcch_table();