srsLTE/lib/test/upper/rlc_am_test.cc

1799 lines
50 KiB
C++
Raw Normal View History

/**
2017-05-18 03:52:29 -07:00
*
* \section COPYRIGHT
2017-05-18 03:52:29 -07:00
*
* Copyright 2013-2020 Software Radio Systems Limited
2017-05-18 03:52:29 -07:00
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
2017-05-18 03:52:29 -07:00
*
*/
2017-06-23 07:29:46 -07:00
#include "srslte/common/log_filter.h"
2018-03-28 07:06:28 -07:00
#include "srslte/common/rlc_pcap.h"
#include "srslte/common/test_common.h"
2019-11-12 08:04:09 -08:00
#include "srslte/common/threads.h"
#include "srslte/upper/rlc_am_lte.h"
2017-05-18 03:52:29 -07:00
#include <assert.h>
2019-11-12 08:04:09 -08:00
#include <iostream>
2017-05-18 03:52:29 -07:00
#define NBUFS 5
2018-03-28 07:06:28 -07:00
#define HAVE_PCAP 0
#define SDU_SIZE 500
2017-05-18 03:52:29 -07:00
using namespace srsue;
using namespace srslte;
2020-03-25 07:57:29 -07:00
srslte::log_ref rrc_log1("RLC_AM_1");
srslte::log_ref rrc_log2("RLC_AM_2");
bool rx_is_tx(const rlc_bearer_metrics_t& rlc1_metrics, const rlc_bearer_metrics_t& rlc2_metrics)
{
if (rlc1_metrics.num_tx_pdu_bytes != rlc2_metrics.num_rx_pdu_bytes) {
return false;
}
if (rlc2_metrics.num_tx_pdu_bytes != rlc1_metrics.num_rx_pdu_bytes) {
return false;
}
return true;
}
class rlc_am_tester : public pdcp_interface_rlc, public rrc_interface_rlc
2017-05-18 03:52:29 -07:00
{
public:
rlc_am_tester(rlc_pcap* pcap_ = NULL)
2018-03-28 07:06:28 -07:00
{
2018-01-31 07:48:50 -08:00
n_sdus = 0;
pcap = pcap_;
2018-01-31 07:48:50 -08:00
}
2017-05-18 03:52:29 -07:00
// PDCP interface
2019-05-13 07:34:15 -07:00
void write_pdu(uint32_t lcid, unique_byte_buffer_t sdu)
2017-05-18 03:52:29 -07:00
{
assert(lcid == 1);
sdus[n_sdus++] = std::move(sdu);
2017-05-18 03:52:29 -07:00
}
2019-05-13 07:34:15 -07:00
void write_pdu_bcch_bch(unique_byte_buffer_t sdu) {}
void write_pdu_bcch_dlsch(unique_byte_buffer_t sdu) {}
void write_pdu_pcch(unique_byte_buffer_t sdu) {}
void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {}
2017-05-18 03:52:29 -07:00
// RRC interface
void max_retx_attempted() {}
std::string get_rb_name(uint32_t lcid) { return std::string(""); }
2017-05-18 03:52:29 -07:00
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdus[10];
int n_sdus;
rlc_pcap* pcap;
2017-05-18 03:52:29 -07:00
};
class ul_writer : public thread
{
public:
2019-11-12 08:04:09 -08:00
ul_writer(rlc_am_lte* rlc_) : rlc(rlc_), running(false), thread("UL_WRITER") {}
~ul_writer() { stop(); }
void stop()
{
running = false;
int cnt = 0;
while (running && cnt < 100) {
usleep(10000);
cnt++;
}
wait_thread_finish();
}
private:
void run_thread()
{
int sn = 0;
running = true;
while (running) {
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t pdu = srslte::allocate_unique_buffer(*pool, "rlc_tester::run_thread", true);
if (!pdu) {
printf("Error: Could not allocate PDU in rlc_tester::run_thread\n\n\n");
// backoff for a bit
usleep(1000);
continue;
}
for (uint32_t i = 0; i < SDU_SIZE; i++) {
pdu->msg[i] = sn;
}
sn++;
pdu->N_bytes = SDU_SIZE;
rlc->write_sdu(std::move(pdu));
}
running = false;
}
2019-11-12 08:04:09 -08:00
rlc_am_lte* rlc;
bool running;
};
2019-11-12 08:04:09 -08:00
void basic_test_tx(rlc_am_lte* rlc, byte_buffer_t pdu_bufs[NBUFS])
2019-06-04 08:29:02 -07:00
{
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
rlc->write_sdu(std::move(sdu_bufs[i]));
}
assert(13 == rlc->get_buffer_state()); // 2 Bytes for fixed header + 6 for LIs + 5 for payload
2019-06-04 08:29:02 -07:00
// Read 5 PDUs from RLC1 (1 byte each)
for (int i = 0; i < NBUFS; i++) {
uint32_t len = rlc->read_pdu(pdu_bufs[i].msg, 3); // 2 bytes for header + 1 byte payload
2019-06-04 08:29:02 -07:00
pdu_bufs[i].N_bytes = len;
assert(3 == len);
2019-06-04 08:29:02 -07:00
}
assert(0 == rlc->get_buffer_state());
}
bool basic_test()
2017-05-18 03:52:29 -07:00
{
rlc_am_tester tester;
timer_handler timers(8);
byte_buffer_t pdu_bufs[NBUFS];
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
2019-10-23 02:53:00 -07:00
// before configuring entity
assert(0 == rlc1.get_buffer_state());
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
2019-06-04 08:29:02 -07:00
basic_test_tx(&rlc1, pdu_bufs);
2017-05-18 03:52:29 -07:00
// Write 5 PDUs into RLC2
for (int i = 0; i < NBUFS; i++) {
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
assert(2 == rlc2.get_buffer_state());
// Read status PDU from RLC2
byte_buffer_t status_buf;
int len = rlc2.read_pdu(status_buf.msg, 2);
2017-05-18 03:52:29 -07:00
status_buf.N_bytes = len;
assert(0 == rlc2.get_buffer_state());
// Assert status is correct
rlc_status_pdu_t status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.ack_sn == 5); // 5 is the last SN that was not received.
2017-05-18 03:52:29 -07:00
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
for (int i = 0; i < tester.n_sdus; i++) {
2017-05-18 03:52:29 -07:00
assert(tester.sdus[i]->N_bytes == 1);
assert(*(tester.sdus[i]->msg) == i);
2017-05-18 03:52:29 -07:00
}
// Check statistics
TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics()));
2018-08-13 03:44:28 -07:00
return SRSLTE_SUCCESS;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
bool concat_test()
2017-05-18 03:52:29 -07:00
{
rlc_am_tester tester;
srslte::timer_handler timers(8);
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(13 == rlc1.get_buffer_state()); // 2 Bytes for fixed header + 6 for LIs + 5 for payload
2017-05-18 03:52:29 -07:00
// Read 1 PDUs from RLC1 containing all 5 SDUs
byte_buffer_t pdu_buf;
int len = rlc1.read_pdu(pdu_buf.msg, 13); // 8 bytes for header + payload
pdu_buf.N_bytes = len;
2017-05-18 03:52:29 -07:00
assert(0 == rlc1.get_buffer_state());
// Write PDU into RLC2
rlc2.write_pdu(pdu_buf.msg, pdu_buf.N_bytes);
// Check status report
TESTASSERT(2 == rlc2.get_buffer_state());
byte_buffer_t status_buf;
len = rlc2.read_pdu(status_buf.msg, 2);
status_buf.N_bytes = len;
TESTASSERT(0 == rlc2.get_buffer_state());
// Assert status is correct
rlc_status_pdu_t status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.ack_sn == 1); // 1 is the last SN that was not received.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
2017-05-18 03:52:29 -07:00
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
2017-05-18 03:52:29 -07:00
assert(tester.sdus[i]->N_bytes == 1);
assert(*(tester.sdus[i]->msg) == i);
2017-05-18 03:52:29 -07:00
}
2019-10-23 02:53:00 -07:00
// Check statistics
TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics()));
2019-10-23 02:53:00 -07:00
return SRSLTE_SUCCESS;
2017-05-18 03:52:29 -07:00
}
2018-11-22 04:18:53 -08:00
bool segment_test(bool in_seq_rx)
2017-05-18 03:52:29 -07:00
{
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(58 == rlc1.get_buffer_state()); // 2 bytes for header + 6 bytes for LI + 50 bytes for payload
2017-05-18 03:52:29 -07:00
// Read PDUs from RLC1 (force segmentation)
byte_buffer_t pdu_bufs[20];
int n_pdus = 0;
while (rlc1.get_buffer_state() > 0) {
len = rlc1.read_pdu(pdu_bufs[n_pdus].msg, 10); // 2 header + payload
2017-05-18 03:52:29 -07:00
pdu_bufs[n_pdus++].N_bytes = len;
}
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2
2018-11-22 04:18:53 -08:00
if (in_seq_rx) {
// deliver PDUs in order
for (int i = 0; i < n_pdus; ++i) {
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
} else {
// deliver PDUs in reverse order
for (int i = n_pdus - 1; i >= 0; --i) {
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
2017-05-18 03:52:29 -07:00
}
2018-11-22 04:18:53 -08:00
// Receiver will only generate status PDU if they arrive in order
// If SN=7 arrives first, but the Rx expects SN=0, status reporting will be delayed, see TS 36.322 v10 Section 5.2.3
if (in_seq_rx) {
assert(2 == rlc2.get_buffer_state());
2017-05-18 03:52:29 -07:00
2018-11-22 04:18:53 -08:00
// Read status PDU from RLC2
byte_buffer_t status_buf;
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
2018-11-22 04:18:53 -08:00
status_buf.N_bytes = len;
2017-05-18 03:52:29 -07:00
// Assert status is correct
rlc_status_pdu_t status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.ack_sn == n_pdus); // n_pdus (8) is the last SN that was not received.
2018-11-22 04:18:53 -08:00
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
}
2017-05-18 03:52:29 -07:00
2018-11-22 04:18:53 -08:00
assert(0 == rlc2.get_buffer_state());
2017-05-18 03:52:29 -07:00
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
2017-05-18 03:52:29 -07:00
assert(tester.sdus[i]->N_bytes == 10);
for (int j = 0; j < 10; j++)
assert(tester.sdus[i]->msg[j] == j);
2017-05-18 03:52:29 -07:00
}
2019-10-23 02:53:00 -07:00
// Check statistics
TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics()));
2018-08-13 03:44:28 -07:00
return SRSLTE_SUCCESS;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
bool retx_test()
2017-05-18 03:52:29 -07:00
{
rlc_am_tester tester;
timer_handler timers(8);
int len = 0;
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(13 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read 5 PDUs from RLC1 (1 byte each)
byte_buffer_t pdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
len = rlc1.read_pdu(pdu_bufs[i].msg, 3); // 2 byte header + 1 byte payload
2017-05-18 03:52:29 -07:00
pdu_bufs[i].N_bytes = len;
}
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2 (skip SN 1)
for (int i = 0; i < NBUFS; i++) {
if (i != 1)
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
// check buffered bytes at receiver, 3 PDUs with one 1 B each (SN=0 has been delivered already)
rlc_bearer_metrics_t metrics = rlc2.get_metrics();
assert(metrics.rx_buffered_bytes == 3);
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
for (int cnt = 0; cnt < 5; cnt++) {
2018-08-10 06:50:08 -07:00
timers.step_all();
}
2017-05-18 03:52:29 -07:00
uint32_t buffer_state = rlc2.get_buffer_state();
assert(4 == buffer_state);
2017-05-18 03:52:29 -07:00
// Read status PDU from RLC2
byte_buffer_t status_buf;
len = rlc2.read_pdu(status_buf.msg, buffer_state); // provide exactly the reported buffer state
2017-05-18 03:52:29 -07:00
status_buf.N_bytes = len;
// Assert all bytes for status PDU were read
buffer_state = rlc2.get_buffer_state();
TESTASSERT(0 == buffer_state);
// Assert status is correct
rlc_status_pdu_t status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 1); // 1 packet was lost.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 4.
2017-05-18 03:52:29 -07:00
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
assert(3 == rlc1.get_buffer_state()); // 2 byte header + 1 byte payload
// Read the retx PDU from RLC1
byte_buffer_t retx;
len = rlc1.read_pdu(retx.msg, 3); // 2 byte header + 1 byte payload
2017-05-18 03:52:29 -07:00
retx.N_bytes = len;
// Write the retx PDU to RLC2
rlc2.write_pdu(retx.msg, retx.N_bytes);
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 1)
return -1;
if (*(tester.sdus[i]->msg) != i)
return -1;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
return 0;
2017-05-18 03:52:29 -07:00
}
// Purpose: test correct retx of lost segment and pollRetx timer expiration
bool segment_retx_test()
{
rlc_am_tester tester;
timer_handler timers(8);
int len = 0;
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
return -1;
}
// Push SDU(s) into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
const uint32_t nof_sdus = 1; // just one SDU to make sure the transmitter sets polling bit
unique_byte_buffer_t sdu_bufs[nof_sdus];
for (uint32_t i = 0; i < nof_sdus; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
}
// Read 2 PDUs from RLC1
const uint32_t nof_pdus = 2;
byte_buffer_t pdu_bufs[nof_pdus];
for (uint32_t i = 0; i < nof_pdus; i++) {
len = rlc1.read_pdu(pdu_bufs[i].msg, 7); // 2 byte header
pdu_bufs[i].N_bytes = len;
}
TESTASSERT(rlc1.get_buffer_state() == 0);
// Step timers until poll Retx timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
uint32_t buffer_state = rlc1.get_buffer_state();
TESTASSERT(buffer_state == 7);
// Read retx PDU from RLC1
byte_buffer_t retx_pdu;
len = rlc1.read_pdu(retx_pdu.msg, buffer_state); // provide exactly the reported buffer state
retx_pdu.N_bytes = len;
// Write retx segment to RLC2
rlc2.write_pdu(retx_pdu.msg, retx_pdu.N_bytes);
buffer_state = rlc2.get_buffer_state(); // Status PDU
TESTASSERT(buffer_state == 2);
// Read status PDU from RLC2
byte_buffer_t status_buf;
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
status_buf.N_bytes = len;
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Step timers again until poll Retx timeout expires
cnt = 5;
while (cnt--) {
timers.step_all();
}
// read buffer state from RLC1 again to see if it has rescheduled SN=1 for retx
buffer_state = rlc1.get_buffer_state(); // Status PDU
TESTASSERT(buffer_state == 7);
// Read 2nd retx PDU from RLC1
byte_buffer_t retx_pdu2;
len = rlc1.read_pdu(retx_pdu2.msg, buffer_state); // provide exactly the reported buffer state
retx_pdu2.N_bytes = len;
// Write retx segment to RLC2
rlc2.write_pdu(retx_pdu2.msg, retx_pdu2.N_bytes);
// read Status PDU from RLC2 again
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
status_buf.N_bytes = len;
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
TESTASSERT(tester.n_sdus == nof_sdus);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 10) {
return SRSLTE_ERROR;
}
if (*(tester.sdus[i]->msg) != i) {
return SRSLTE_ERROR;
}
}
return SRSLTE_SUCCESS;
}
2018-08-13 03:44:28 -07:00
bool resegment_test_1()
2017-05-18 03:52:29 -07:00
{
// SDUs: | 10 | 10 | 10 | 10 | 10 |
// PDUs: | 10 | 10 | 10 | 10 | 10 |
// Retx PDU segments: | 5 | 5|
rlc_am_tester tester;
timer_handler timers(8);
int len = 0;
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(58 == rlc1.get_buffer_state()); // 2 bytes for fixed header, 6 bytes for LIs, 50 bytes for data
2017-05-18 03:52:29 -07:00
// Read 5 PDUs from RLC1 (10 bytes each)
byte_buffer_t pdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
len = rlc1.read_pdu(pdu_bufs[i].msg, 12); // 12 bytes for header + payload
2017-05-18 03:52:29 -07:00
pdu_bufs[i].N_bytes = len;
}
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2 (skip SN 1)
for (int i = 0; i < NBUFS; i++) {
if (i != 1)
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
2017-05-18 03:52:29 -07:00
assert(4 == rlc2.get_buffer_state());
// Read status PDU from RLC2
byte_buffer_t status_buf;
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
2017-05-18 03:52:29 -07:00
status_buf.N_bytes = len;
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
assert(12 == rlc1.get_buffer_state()); // 2 byte header + 10 data
// Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1;
len = rlc1.read_pdu(retx1.msg, 9); // 4 byte header + 5 data
2017-05-18 03:52:29 -07:00
retx1.N_bytes = len;
// Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
assert(9 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read the remaining segment
byte_buffer_t retx2;
len = rlc1.read_pdu(retx2.msg, 9); // 4 byte header + 5 data
2017-05-18 03:52:29 -07:00
retx2.N_bytes = len;
// Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 10)
return -1;
for (int j = 0; j < 10; j++)
if (tester.sdus[i]->msg[j] != j)
return -1;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
return 0;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
bool resegment_test_2()
2017-05-18 03:52:29 -07:00
{
// SDUs: | 10 | 10 | 10 | 10 | 10 |
// PDUs: | 5 | 10 | 20 | 10 | 5 |
// Retx PDU segments: | 10 | 10 |
rlc_am_tester tester;
timer_handler timers(8);
int len = 0;
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(58 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read 5 PDUs from RLC1 (5 bytes, 10 bytes, 20 bytes, 10 bytes, 5 bytes)
byte_buffer_t pdu_bufs[NBUFS];
pdu_bufs[0].N_bytes = rlc1.read_pdu(pdu_bufs[0].msg, 7); // 2 byte header + 5 byte payload
pdu_bufs[1].N_bytes = rlc1.read_pdu(pdu_bufs[1].msg, 14); // 4 byte header + 10 byte payload
pdu_bufs[2].N_bytes = rlc1.read_pdu(pdu_bufs[2].msg, 25); // 5 byte header + 20 byte payload
pdu_bufs[3].N_bytes = rlc1.read_pdu(pdu_bufs[3].msg, 14); // 4 byte header + 10 byte payload
pdu_bufs[4].N_bytes = rlc1.read_pdu(pdu_bufs[4].msg, 7); // 2 byte header + 5 byte payload
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2 (skip SN 2)
for (int i = 0; i < NBUFS; i++) {
if (i != 2)
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
2017-05-18 03:52:29 -07:00
assert(4 == rlc2.get_buffer_state());
// Read status PDU from RLC2
byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
assert(25 == rlc1.get_buffer_state()); // 4 byte header + 20 data
// Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 6 byte header + 10 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
2018-10-02 08:02:45 -07:00
assert(18 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read the remaining segment
byte_buffer_t retx2;
2018-10-02 08:02:45 -07:00
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 18); // 6 byte header + 12 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 10)
return -1;
for (int j = 0; j < 10; j++)
if (tester.sdus[i]->msg[j] != j)
return -1;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
return 0;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
bool resegment_test_3()
2017-05-18 03:52:29 -07:00
{
// SDUs: | 10 | 10 | 10 | 10 | 10 |
// PDUs: | 5 | 5| 20 | 10 | 10 |
// Retx PDU segments: | 10 | 10 |
rlc_am_tester tester;
srslte::timer_handler timers(8);
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(58 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read 5 PDUs from RLC1 (5 bytes, 5 bytes, 20 bytes, 10 bytes, 10 bytes)
byte_buffer_t pdu_bufs[NBUFS];
pdu_bufs[0].N_bytes = rlc1.read_pdu(pdu_bufs[0].msg, 7); // 2 byte header + 5 byte payload
pdu_bufs[1].N_bytes = rlc1.read_pdu(pdu_bufs[1].msg, 7); // 2 byte header + 5 byte payload
pdu_bufs[2].N_bytes = rlc1.read_pdu(pdu_bufs[2].msg, 24); // 4 byte header + 20 byte payload
pdu_bufs[3].N_bytes = rlc1.read_pdu(pdu_bufs[3].msg, 12); // 2 byte header + 10 byte payload
pdu_bufs[4].N_bytes = rlc1.read_pdu(pdu_bufs[4].msg, 12); // 2 byte header + 10 byte payload
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2 (skip SN 2)
for (int i = 0; i < NBUFS; i++) {
if (i != 2)
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
2017-05-18 03:52:29 -07:00
assert(4 == rlc2.get_buffer_state());
// Read status PDU from RLC2
byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 6 byte header + 10 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
// Read the remaining segment
byte_buffer_t retx2;
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 16); // 6 byte header + 10 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 10)
return -1;
for (int j = 0; j < 10; j++)
if (tester.sdus[i]->msg[j] != j)
return -1;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
return 0;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
bool resegment_test_4()
2017-05-18 03:52:29 -07:00
{
// SDUs: | 10 | 10 | 10 | 10 | 10 |
// PDUs: | 5 | 5| 30 | 5 | 5|
// Retx PDU segments: | 15 | 15 |
rlc_am_tester tester;
srslte::timer_handler timers(8);
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(58 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read 5 PDUs from RLC1 (5 bytes, 5 bytes, 30 bytes, 5 bytes, 5 bytes)
byte_buffer_t pdu_bufs[NBUFS];
pdu_bufs[0].N_bytes = rlc1.read_pdu(pdu_bufs[0].msg, 7); // 2 byte header + 5 byte payload
pdu_bufs[1].N_bytes = rlc1.read_pdu(pdu_bufs[1].msg, 7); // 2 byte header + 5 byte payload
pdu_bufs[2].N_bytes = rlc1.read_pdu(pdu_bufs[2].msg, 35); // 5 byte header + 30 byte payload
pdu_bufs[3].N_bytes = rlc1.read_pdu(pdu_bufs[3].msg, 7); // 2 byte header + 5 byte payload
pdu_bufs[4].N_bytes = rlc1.read_pdu(pdu_bufs[4].msg, 7); // 2 byte header + 5 byte payload
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2 (skip SN 2)
for (int i = 0; i < NBUFS; i++) {
if (i != 2)
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
2017-05-18 03:52:29 -07:00
assert(4 == rlc2.get_buffer_state());
// Read status PDU from RLC2
byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 21); // 6 byte header + 15 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
2018-10-02 08:02:45 -07:00
assert(23 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read the remaining segment
byte_buffer_t retx2;
2018-10-02 08:02:45 -07:00
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 23); // 6 byte header + 18 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 10)
return -1;
for (int j = 0; j < 10; j++)
if (tester.sdus[i]->msg[j] != j)
return -1;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
return 0;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
bool resegment_test_5()
2017-05-18 03:52:29 -07:00
{
// SDUs: | 10 | 10 | 10 | 10 | 10 |
// PDUs: |2|3| 40 |3|2|
// Retx PDU segments: | 20 | 20 |
rlc_am_tester tester;
srslte::timer_handler timers(8);
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(58 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read 5 PDUs from RLC1 (2 bytes, 3 bytes, 40 bytes, 3 bytes, 2 bytes)
byte_buffer_t pdu_bufs[NBUFS];
pdu_bufs[0].N_bytes = rlc1.read_pdu(pdu_bufs[0].msg, 4); // 2 byte header + 2 byte payload
pdu_bufs[1].N_bytes = rlc1.read_pdu(pdu_bufs[1].msg, 5); // 2 byte header + 3 byte payload
pdu_bufs[2].N_bytes = rlc1.read_pdu(pdu_bufs[2].msg, 48); // 8 byte header + 40 byte payload
pdu_bufs[3].N_bytes = rlc1.read_pdu(pdu_bufs[3].msg, 5); // 2 byte header + 3 byte payload
pdu_bufs[4].N_bytes = rlc1.read_pdu(pdu_bufs[4].msg, 4); // 2 byte header + 2 byte payload
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2 (skip SN 2)
for (int i = 0; i < NBUFS; i++) {
if (i != 2)
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
2017-05-18 03:52:29 -07:00
assert(4 == rlc2.get_buffer_state());
// Read status PDU from RLC2
byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 27); // 7 byte header + 20 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
2018-10-02 08:02:45 -07:00
assert(31 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read the remaining segment
byte_buffer_t retx2;
2018-10-02 08:02:45 -07:00
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 34); // 7 byte header + 24 data
2017-05-18 03:52:29 -07:00
// Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
assert(tester.n_sdus == 5);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 10)
return -1;
for (int j = 0; j < 10; j++)
if (tester.sdus[i]->msg[j] != j)
return -1;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
return 0;
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
bool resegment_test_6()
2017-05-18 03:52:29 -07:00
{
// SDUs: |10|10|10| 54 | 54 | 54 | 54 | 54 | 54 |
// PDUs: |10|10|10| 270 | 54 |
// Retx PDU segments: | 120 | 150 |
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
2017-05-18 03:52:29 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2017-05-18 03:52:29 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2017-05-18 03:52:29 -07:00
// Push SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[9];
for (int i = 0; i < 3; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
for (int i = 3; i < 9; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (int j = 0; j < 54; j++)
sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 54;
rlc1.write_sdu(std::move(sdu_bufs[i]));
2017-05-18 03:52:29 -07:00
}
assert(368 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read PDUs from RLC1 (10, 10, 10, 270, 54)
byte_buffer_t pdu_bufs[5];
for (int i = 0; i < 3; i++) {
len = rlc1.read_pdu(pdu_bufs[i].msg, 12);
2017-05-18 03:52:29 -07:00
pdu_bufs[i].N_bytes = len;
}
len = rlc1.read_pdu(pdu_bufs[3].msg, 278);
2017-05-18 03:52:29 -07:00
pdu_bufs[3].N_bytes = len;
len = rlc1.read_pdu(pdu_bufs[4].msg, 56);
2017-05-18 03:52:29 -07:00
pdu_bufs[4].N_bytes = len;
assert(0 == rlc1.get_buffer_state());
// Write PDUs into RLC2 (skip SN 3)
for (int i = 0; i < 5; i++) {
if (i != 3)
2017-05-18 03:52:29 -07:00
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
2017-05-18 03:52:29 -07:00
assert(4 == rlc2.get_buffer_state());
// Read status PDU from RLC2
byte_buffer_t status_buf;
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
2017-05-18 03:52:29 -07:00
status_buf.N_bytes = len;
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
assert(278 == rlc1.get_buffer_state());
// Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1;
len = rlc1.read_pdu(retx1.msg, 129);
2017-05-18 03:52:29 -07:00
retx1.N_bytes = len;
// Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes);
2018-10-02 08:02:45 -07:00
assert(159 == rlc1.get_buffer_state());
2017-05-18 03:52:29 -07:00
// Read the remaining segment
byte_buffer_t retx2;
len = rlc1.read_pdu(retx2.msg, 162);
2017-05-18 03:52:29 -07:00
retx2.N_bytes = len;
// Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes);
assert(tester.n_sdus == 9);
for (int i = 0; i < 3; i++) {
2017-05-18 03:52:29 -07:00
assert(tester.sdus[i]->N_bytes == 10);
for (int j = 0; j < 10; j++)
assert(tester.sdus[i]->msg[j] == j);
2017-05-18 03:52:29 -07:00
}
for (int i = 3; i < 9; i++) {
if (i >= tester.n_sdus)
return -1;
if (tester.sdus[i]->N_bytes != 54)
return -1;
for (int j = 0; j < 54; j++) {
if (tester.sdus[i]->msg[j] != j)
return -1;
2018-08-13 03:44:28 -07:00
}
2017-05-18 03:52:29 -07:00
}
2018-08-13 03:44:28 -07:00
return 0;
2017-05-18 03:52:29 -07:00
}
2018-03-28 07:06:28 -07:00
// Retransmission of PDU segments of the same size
2018-08-13 03:44:28 -07:00
bool resegment_test_7()
{
// SDUs: | 30 | 30 |
2018-04-04 08:02:45 -07:00
// PDUs: | 13 | 13 | 11 | 13 | 10 |
// Rxed PDUs | 13 | 13 | | 13 | 10 |
// Retx PDU segments: | 4 | 7 |
// Retx PDU segments: |3|3]3|2|
const uint32_t N_SDU_BUFS = 2;
const uint32_t N_PDU_BUFS = 5;
const uint32_t sdu_size = 30;
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
rlc_pcap pcap;
pcap.open("rlc_am_test7.pcap", 0);
rlc_am_tester tester(&pcap);
2018-03-28 07:06:28 -07:00
#else
rlc_am_tester tester(NULL);
2018-03-28 07:06:28 -07:00
#endif
srslte::timer_handler timers(8);
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
// Push 2 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[N_SDU_BUFS];
for (uint32_t i = 0; i < N_SDU_BUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (uint32_t j = 0; j < sdu_size; j++) {
sdu_bufs[i]->msg[j] = i;
}
sdu_bufs[i]->N_bytes = sdu_size; // Give each buffer a size of 15 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
}
assert(64 == rlc1.get_buffer_state());
// Read PDUs from RLC1 (15 bytes each)
byte_buffer_t pdu_bufs[N_PDU_BUFS];
for (uint32_t i = 0; i < N_PDU_BUFS; i++) {
2018-04-04 08:02:45 -07:00
pdu_bufs[i].N_bytes = rlc1.read_pdu(pdu_bufs[i].msg, 15); // 2 bytes for header + 12 B payload
assert(pdu_bufs[i].N_bytes);
}
2018-09-26 07:55:46 -07:00
// Step timers until poll_retx timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
// RLC should try to retx a random PDU because it needs to request a status from the receiver
assert(0 != rlc1.get_buffer_state());
2018-04-04 08:02:45 -07:00
// Skip PDU with SN 2
for (uint32_t i = 0; i < N_PDU_BUFS; i++) {
if (i != 2) {
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
pcap.write_dl_am_ccch(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
#endif
}
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
2018-09-26 07:55:46 -07:00
cnt = 5;
2018-08-10 06:50:08 -07:00
while (cnt--) {
timers.step_all();
}
2018-09-26 07:55:46 -07:00
// RLC should try to retransmit a random PDU because it needs to re-request a status PDU from the receiver
assert(0 != rlc1.get_buffer_state());
2018-03-28 07:06:28 -07:00
// first round of retx, forcing resegmentation
byte_buffer_t retx[4];
for (uint32_t i = 0; i < 4; i++) {
2018-09-26 07:55:46 -07:00
assert(0 != rlc1.get_buffer_state());
2018-03-28 07:06:28 -07:00
retx[i].N_bytes = rlc1.read_pdu(retx[i].msg, 7);
assert(retx[i].N_bytes);
// Write the last two segments to RLC2
if (i > 1) {
rlc2.write_pdu(retx[i].msg, retx[i].N_bytes);
#if HAVE_PCAP
pcap.write_dl_am_ccch(retx[i].msg, retx[i].N_bytes);
#endif
}
}
// Read status PDU from RLC2
2018-03-28 07:06:28 -07:00
assert(rlc2.get_buffer_state());
byte_buffer_t status_buf;
2018-03-28 07:06:28 -07:00
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
pcap.write_ul_am_ccch(status_buf.msg, status_buf.N_bytes);
#endif
assert(15 == rlc1.get_buffer_state());
// second round of retx, forcing resegmentation
2018-04-04 08:02:45 -07:00
byte_buffer_t retx2[4];
for (uint32_t i = 0; i < 4; i++) {
2018-03-28 07:06:28 -07:00
assert(rlc1.get_buffer_state() != 0);
retx2[i].N_bytes = rlc1.read_pdu(retx2[i].msg, 9);
2018-03-28 07:06:28 -07:00
assert(retx2[i].N_bytes != 0);
rlc2.write_pdu(retx2[i].msg, retx2[i].N_bytes);
#if HAVE_PCAP
pcap.write_dl_am_ccch(retx[i].msg, retx[i].N_bytes);
#endif
}
// check buffer states
assert(0 == rlc1.get_buffer_state());
2018-08-10 06:50:08 -07:00
// Step timers until poll_retx timeout expires
cnt = 5;
while (cnt--) {
timers.step_all();
}
2018-08-10 06:50:08 -07:00
// Read status PDU from RLC2
assert(rlc2.get_buffer_state());
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
#if HAVE_PCAP
pcap.write_ul_am_ccch(status_buf.msg, status_buf.N_bytes);
#endif
// check status again
assert(0 == rlc1.get_buffer_state());
2018-03-28 07:06:28 -07:00
assert(0 == rlc2.get_buffer_state());
// Check number of SDUs and their content
assert(tester.n_sdus == N_SDU_BUFS);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != sdu_size)
return -1;
for (uint32_t j = 0; j < N_SDU_BUFS; j++) {
if (tester.sdus[i]->msg[j] != i)
return -1;
2018-03-28 07:06:28 -07:00
}
}
#if HAVE_PCAP
pcap.close();
#endif
2018-08-13 03:44:28 -07:00
return 0;
2018-03-28 07:06:28 -07:00
}
// Retransmission of PDU segments with different size
2018-08-13 03:44:28 -07:00
bool resegment_test_8()
2018-03-28 07:06:28 -07:00
{
// SDUs: | 30 | 30 |
// PDUs: | 15 | 15 | 15 | 15 | 15 |
// Rxed PDUs | 15 | | 15 | 15 |
// Retx PDU segments: | 7 | 7 | 7 | 7 |
// Retx PDU segments: | 6 | 6 ] 6 | 6 | 6 | 6 | 6 | 6 |
const uint32_t N_SDU_BUFS = 2;
const uint32_t N_PDU_BUFS = 5;
const uint32_t sdu_size = 30;
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
rlc_pcap pcap;
pcap.open("rlc_am_test8.pcap", 0);
rlc_am_tester tester(&pcap);
2018-03-28 07:06:28 -07:00
#else
rlc_am_tester tester(NULL);
2018-03-28 07:06:28 -07:00
#endif
srslte::timer_handler timers(8);
2018-03-28 07:06:28 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
2018-03-28 07:06:28 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-10 06:50:08 -07:00
return -1;
2018-08-13 03:44:28 -07:00
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-10 06:50:08 -07:00
return -1;
2018-08-13 03:44:28 -07:00
}
2018-03-28 07:06:28 -07:00
// Push 2 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_bufs[N_SDU_BUFS];
for (uint32_t i = 0; i < N_SDU_BUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
for (uint32_t j = 0; j < sdu_size; j++) {
sdu_bufs[i]->msg[j] = i;
2018-03-28 07:06:28 -07:00
}
sdu_bufs[i]->N_bytes = sdu_size; // Give each buffer a size of 15 bytes
rlc1.write_sdu(std::move(sdu_bufs[i]));
2018-03-28 07:06:28 -07:00
}
assert(64 == rlc1.get_buffer_state());
2018-03-28 07:06:28 -07:00
// Read PDUs from RLC1 (15 bytes each)
byte_buffer_t pdu_bufs[N_PDU_BUFS];
for (uint32_t i = 0; i < N_PDU_BUFS; i++) {
2018-03-28 07:06:28 -07:00
pdu_bufs[i].N_bytes = rlc1.read_pdu(pdu_bufs[i].msg, 15); // 12 bytes for header + payload
assert(pdu_bufs[i].N_bytes);
}
assert(0 == rlc1.get_buffer_state());
// Skip PDU one and two
for (uint32_t i = 0; i < N_PDU_BUFS; i++) {
2018-03-28 07:06:28 -07:00
if (i < 1 || i > 2) {
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
#if HAVE_PCAP
pcap.write_dl_am_ccch(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
#endif
}
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
2018-09-26 07:55:46 -07:00
// what PDU to retransmit is random but it must not be zero
assert(0 != rlc1.get_buffer_state());
// first round of retx, forcing resegmentation
byte_buffer_t retx[4];
2018-04-04 08:02:45 -07:00
for (uint32_t i = 0; i < 3; i++) {
assert(rlc1.get_buffer_state());
2018-04-04 08:02:45 -07:00
retx[i].N_bytes = rlc1.read_pdu(retx[i].msg, 8);
assert(retx[i].N_bytes);
// Write the last two segments to RLC2
if (i > 1) {
rlc2.write_pdu(retx[i].msg, retx[i].N_bytes);
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
pcap.write_dl_am_ccch(retx[i].msg, retx[i].N_bytes);
#endif
}
}
2018-08-10 06:50:08 -07:00
// Step timers until reordering timeout expires
cnt = 7;
while (cnt--) {
timers.step_all();
}
// Read status PDU from RLC2
assert(rlc2.get_buffer_state());
2018-03-28 07:06:28 -07:00
byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
pcap.write_ul_am_ccch(status_buf.msg, status_buf.N_bytes);
#endif
assert(15 == rlc1.get_buffer_state());
2018-03-28 07:06:28 -07:00
// second round of retx, reduce grant size to force different segment sizes
byte_buffer_t retx2[20];
for (uint32_t i = 0; i < 7; i++) {
assert(rlc1.get_buffer_state() != 0);
retx2[i].N_bytes = rlc1.read_pdu(retx2[i].msg, 9);
assert(retx2[i].N_bytes != 0);
rlc2.write_pdu(retx2[i].msg, retx2[i].N_bytes);
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
pcap.write_dl_am_ccch(retx[i].msg, retx[i].N_bytes);
#endif
}
2018-08-13 03:44:28 -07:00
// get BSR from RLC2
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
#if HAVE_PCAP
pcap.write_ul_am_ccch(status_buf.msg, status_buf.N_bytes);
#endif
// check buffer states
2018-08-13 03:44:28 -07:00
if (rlc1.get_buffer_state() != 0) {
return -1;
};
if (rlc2.get_buffer_state() != 0) {
return -1;
};
// Check number of SDUs and their content
assert(tester.n_sdus == N_SDU_BUFS);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != sdu_size)
return -1;
for (uint32_t j = 0; j < N_SDU_BUFS; j++) {
if (tester.sdus[i]->msg[j] != i)
return -1;
}
}
2018-03-28 07:06:28 -07:00
#if HAVE_PCAP
pcap.close();
#endif
2018-08-13 03:44:28 -07:00
return 0;
}
2018-08-13 03:44:28 -07:00
bool reset_test()
2018-02-20 03:27:02 -08:00
{
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
2018-02-20 03:27:02 -08:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
2018-02-20 03:27:02 -08:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
2018-02-20 03:27:02 -08:00
// Push 1 SDU of size 10 into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
2019-05-13 07:34:15 -07:00
unique_byte_buffer_t sdu_buf = srslte::allocate_unique_buffer(*pool, true);
sdu_buf->msg[0] = 1; // Write the index into the buffer
sdu_buf->N_bytes = 100;
rlc1.write_sdu(std::move(sdu_buf));
2018-02-20 03:27:02 -08:00
// read 1 PDU from RLC1 and force segmentation
byte_buffer_t pdu_bufs;
len = rlc1.read_pdu(pdu_bufs.msg, 4);
2018-02-20 03:27:02 -08:00
pdu_bufs.N_bytes = len;
// reset RLC1
rlc1.stop();
2018-02-20 03:27:02 -08:00
// read another PDU segment from RLC1
len = rlc1.read_pdu(pdu_bufs.msg, 4);
2018-02-20 03:27:02 -08:00
pdu_bufs.N_bytes = len;
// now empty RLC buffer
len = rlc1.read_pdu(pdu_bufs.msg, 100);
2018-02-20 03:27:02 -08:00
pdu_bufs.N_bytes = len;
2018-08-13 03:44:28 -07:00
if (0 != rlc1.get_buffer_state()) {
return -1;
}
return 0;
2018-02-20 03:27:02 -08:00
}
2019-06-04 08:29:02 -07:00
bool resume_test()
{
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
2019-06-04 08:29:02 -07:00
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
2019-06-04 08:29:02 -07:00
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2019-06-04 08:29:02 -07:00
return -1;
}
// Push 1 SDU of size 10 into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
unique_byte_buffer_t sdu_buf = srslte::allocate_unique_buffer(*pool, true);
sdu_buf->msg[0] = 1; // Write the index into the buffer
sdu_buf->N_bytes = 100;
rlc1.write_sdu(std::move(sdu_buf));
// read 1 PDU from RLC1 and force segmentation
byte_buffer_t pdu_bufs;
len = rlc1.read_pdu(pdu_bufs.msg, 4);
pdu_bufs.N_bytes = len;
// reestablish RLC1
rlc1.reestablish();
// resume RLC1
rlc1.resume();
// Buffer should be zero
if (0 != rlc1.get_buffer_state()) {
return -1;
}
// Do basic test
byte_buffer_t pdu_bufs_tx[NBUFS];
basic_test_tx(&rlc1, pdu_bufs_tx);
return 0;
}
2018-08-13 03:44:28 -07:00
bool stop_test()
{
rlc_am_tester tester;
srslte::timer_handler timers(8);
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
2018-08-13 03:44:28 -07:00
return -1;
}
// start thread reading
ul_writer writer(&rlc1);
writer.start(-2);
// let writer thread block on tx_queue
usleep(1e6);
// stop RLC1
rlc1.stop();
2018-08-13 03:44:28 -07:00
return 0;
}
// This test checks if status PDUs are generated even though the grant size may not
// be enough to fit all SNs that would need to be NACKed
bool status_pdu_test()
{
rlc_am_tester tester;
srslte::timer_handler timers(8);
int len = 0;
2020-03-25 07:57:29 -07:00
rlc_am_lte rlc1(rrc_log1, 1, &tester, &tester, &timers);
rlc_am_lte rlc2(rrc_log2, 1, &tester, &tester, &timers);
if (not rlc1.configure(rlc_config_t::default_rlc_am_config())) {
return -1;
}
if (not rlc2.configure(rlc_config_t::default_rlc_am_config())) {
return -1;
}
// Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance();
unique_byte_buffer_t sdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer
sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
rlc1.write_sdu(std::move(sdu_bufs[i]));
}
assert(13 == rlc1.get_buffer_state());
// Read 5 PDUs from RLC1 (1 byte each)
byte_buffer_t pdu_bufs[NBUFS];
for (int i = 0; i < NBUFS; i++) {
len = rlc1.read_pdu(pdu_bufs[i].msg, 4); // 2 byte header + 1 byte payload
pdu_bufs[i].N_bytes = len;
}
assert(0 == rlc1.get_buffer_state());
// Only pass last PDUs to RLC2
for (int i = 0; i < NBUFS; i++) {
if (i == 4) {
rlc2.write_pdu(pdu_bufs[i].msg, pdu_bufs[i].N_bytes);
}
}
// Step timers until reordering timeout expires
int cnt = 5;
while (cnt--) {
timers.step_all();
}
uint32_t buffer_state = rlc2.get_buffer_state();
assert(8 == buffer_state);
// Read status PDU from RLC2
byte_buffer_t status_buf;
len = rlc2.read_pdu(status_buf.msg, 5); // provide only small grant
status_buf.N_bytes = len;
assert(status_buf.N_bytes != 0);
// check status PDU doesn't contain ACK_SN in NACK list
rlc_status_pdu_t status_pdu = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_pdu);
if (rlc_am_is_valid_status_pdu(status_pdu) == false) {
return -1;
}
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
assert(3 == rlc1.get_buffer_state()); // 2 byte header + 1 byte payload
// Read the retx PDU from RLC1
byte_buffer_t retx;
len = rlc1.read_pdu(retx.msg, 10);
retx.N_bytes = len;
// Write the retx PDU to RLC2
rlc2.write_pdu(retx.msg, retx.N_bytes);
// Step timers until reordering timeout expires
cnt = 5;
while (cnt--) {
timers.step_all();
}
// get buffer state and status PDU again
status_buf.clear();
len = rlc2.read_pdu(status_buf.msg, 10); // big enough grant to fit full status PDU
status_buf.N_bytes = len;
assert(status_buf.N_bytes != 0);
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// retransmission of remaining PDUs
for (int i = 0; i < 3; i++) {
retx.clear();
len = rlc1.read_pdu(retx.msg, 3);
retx.N_bytes = len;
// Write the retx PDU to RLC2
rlc2.write_pdu(retx.msg, retx.N_bytes);
}
assert(tester.n_sdus == NBUFS);
for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 1)
return -1;
if (*(tester.sdus[i]->msg) != i)
return -1;
}
return 0;
}
int main(int argc, char** argv)
2018-08-13 03:44:28 -07:00
{
2020-03-25 07:57:29 -07:00
rrc_log1->set_level(srslte::LOG_LEVEL_DEBUG);
rrc_log2->set_level(srslte::LOG_LEVEL_DEBUG);
rrc_log1->set_hex_limit(-1);
rrc_log2->set_hex_limit(-1);
if (basic_test()) {
2018-08-13 03:44:28 -07:00
printf("basic_test failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-08-13 03:44:28 -07:00
if (concat_test()) {
printf("concat_test failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-11-22 04:18:53 -08:00
if (segment_test(true)) {
printf("segment_test with in-order PDU reception failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
if (segment_test(false)) {
printf("segment_test with out-of-order PDU reception failed\n");
2018-08-13 03:44:28 -07:00
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-08-13 03:44:28 -07:00
if (retx_test()) {
printf("retx_test failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
if (segment_retx_test()) {
printf("segment_retx_test failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
2018-08-13 03:44:28 -07:00
if (resegment_test_1()) {
printf("resegment_test_1 failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-08-13 03:44:28 -07:00
if (resegment_test_2()) {
printf("resegment_test_2 failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-08-13 03:44:28 -07:00
if (resegment_test_3()) {
printf("resegment_test_3 failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-08-13 03:44:28 -07:00
if (resegment_test_4()) {
printf("resegment_test_4 failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-08-13 03:44:28 -07:00
if (resegment_test_5()) {
printf("resegment_test_5 failed\n");
exit(-1);
};
2017-05-18 03:52:29 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-02-16 03:41:13 -08:00
2018-08-13 03:44:28 -07:00
if (resegment_test_6()) {
printf("resegment_test_6 failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
2020-03-25 07:57:29 -07:00
rrc_log1->set_hex_limit(100);
rrc_log2->set_hex_limit(100);
2018-08-13 03:44:28 -07:00
if (resegment_test_7()) {
printf("resegment_test_7 failed\n");
exit(-1);
2020-03-25 07:57:29 -07:00
}
2018-03-28 07:06:28 -07:00
byte_buffer_pool::get_instance()->cleanup();
2018-08-13 03:44:28 -07:00
if (resegment_test_8()) {
printf("resegment_test_8 failed\n");
exit(-1);
};
2018-02-20 03:27:02 -08:00
byte_buffer_pool::get_instance()->cleanup();
2020-03-25 07:57:29 -07:00
rrc_log1->set_hex_limit(-1);
rrc_log2->set_hex_limit(-1);
2018-08-13 03:44:28 -07:00
if (reset_test()) {
printf("reset_test failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
2018-08-13 03:44:28 -07:00
if (stop_test()) {
printf("stop_test failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
2019-06-04 08:29:02 -07:00
if (resume_test()) {
printf("resume_test failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
if (status_pdu_test()) {
printf("status_pdu_test failed\n");
exit(-1);
};
byte_buffer_pool::get_instance()->cleanup();
return 0;
2017-05-18 03:52:29 -07:00
}