Moved notification tests from rlc_am_notify_pdcp_test.cc to rlc_am_test.cc.

This added some tests to resegmentation.
master
Pedro Alvarez 4 years ago
parent 389cf4d943
commit 649d642776

@ -1049,8 +1049,8 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
if (tx_window.count(i) > 0) { if (tx_window.count(i) > 0) {
it = tx_window.find(i); it = tx_window.find(i);
if (it != tx_window.end()) { if (it != tx_window.end()) {
if (update_vt_a) {
update_notification_ack_info(it->second, notify_info_vec); update_notification_ack_info(it->second, notify_info_vec);
if (update_vt_a) {
tx_window.erase(it); tx_window.erase(it);
vt_a = (vt_a + 1) % MOD; vt_a = (vt_a + 1) % MOD;
vt_ms = (vt_ms + 1) % MOD; vt_ms = (vt_ms + 1) % MOD;
@ -1079,13 +1079,18 @@ void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pd
std::vector<uint32_t>& notify_info_vec) std::vector<uint32_t>& notify_info_vec)
{ {
// Notify PDCP of the number of bytes succesfully delivered // Notify PDCP of the number of bytes succesfully delivered
uint32_t notified_bytes = 0; uint32_t total_acked_bytes = 0;
uint32_t nof_bytes = 0; uint32_t nof_bytes = 0;
uint32_t pdcp_sn = 0; uint32_t pdcp_sn = 0;
for (uint32_t pdcp_notify_it = 0; pdcp_notify_it < tx_pdu.header.N_li; pdcp_notify_it++) { for (uint32_t pdcp_notify_it = 0; pdcp_notify_it < tx_pdu.header.N_li; pdcp_notify_it++) {
nof_bytes = tx_pdu.header.li[pdcp_notify_it]; nof_bytes = tx_pdu.header.li[pdcp_notify_it];
pdcp_sn = tx_pdu.pdcp_tx_counts[pdcp_notify_it]; pdcp_sn = tx_pdu.pdcp_tx_counts[pdcp_notify_it];
if (undelivered_sdu_info_queue.find(pdcp_sn) == undelivered_sdu_info_queue.end()) {
log->debug("Could not find notification info, perhaps SDU was already ACK'ed.\n");
continue;
}
undelivered_sdu_info_queue[pdcp_sn].acked_bytes += nof_bytes; undelivered_sdu_info_queue[pdcp_sn].acked_bytes += nof_bytes;
total_acked_bytes += nof_bytes;
if (undelivered_sdu_info_queue[pdcp_sn].acked_bytes >= undelivered_sdu_info_queue[pdcp_sn].total_bytes) { if (undelivered_sdu_info_queue[pdcp_sn].acked_bytes >= undelivered_sdu_info_queue[pdcp_sn].total_bytes) {
undelivered_sdu_info_queue.erase(pdcp_sn); undelivered_sdu_info_queue.erase(pdcp_sn);
notify_info_vec.push_back(pdcp_sn); notify_info_vec.push_back(pdcp_sn);
@ -1093,7 +1098,11 @@ void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pd
} }
} }
pdcp_sn = tx_pdu.pdcp_tx_counts[tx_pdu.header.N_li]; pdcp_sn = tx_pdu.pdcp_tx_counts[tx_pdu.header.N_li];
nof_bytes = tx_pdu.buf->N_bytes - notified_bytes; // Notify last SDU nof_bytes = tx_pdu.buf->N_bytes - total_acked_bytes; // Notify last SDU
if (undelivered_sdu_info_queue.find(pdcp_sn) == undelivered_sdu_info_queue.end()) {
log->debug("Could not find notification info, perhaps SDU was already ACK'ed.\n");
return;
}
undelivered_sdu_info_queue[pdcp_sn].acked_bytes += nof_bytes; undelivered_sdu_info_queue[pdcp_sn].acked_bytes += nof_bytes;
if (undelivered_sdu_info_queue[pdcp_sn].acked_bytes >= undelivered_sdu_info_queue[pdcp_sn].total_bytes) { if (undelivered_sdu_info_queue[pdcp_sn].acked_bytes >= undelivered_sdu_info_queue[pdcp_sn].total_bytes) {
undelivered_sdu_info_queue.erase(pdcp_sn); undelivered_sdu_info_queue.erase(pdcp_sn);
@ -1438,7 +1447,6 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa
// Check if we already have a segment from the same PDU // Check if we already have a segment from the same PDU
it = rx_segments.find(header.sn); it = rx_segments.find(header.sn);
if (rx_segments.end() != it) { if (rx_segments.end() != it) {
if (header.p) { if (header.p) {
log->info("%s Status packet requested through polling bit\n", RB_NAME); log->info("%s Status packet requested through polling bit\n", RB_NAME);
do_status = true; do_status = true;
@ -1451,7 +1459,6 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa
} }
} else { } else {
// Create new PDU segment list and write to rx_segments // Create new PDU segment list and write to rx_segments
rlc_amd_rx_pdu_segments_t pdu; rlc_amd_rx_pdu_segments_t pdu;
pdu.segments.push_back(std::move(segment)); pdu.segments.push_back(std::move(segment));

@ -34,8 +34,6 @@ public:
} }
assert(lcid == 1); assert(lcid == 1);
notified_counts[pdcp_sn] += 1; notified_counts[pdcp_sn] += 1;
// std::cout << "Notified " << notified_counts[tx_count] << "Tx count" << tx_count << "nof_bytes" << nof_bytes
// << std::endl;
} }
} }
}; };
@ -141,6 +139,7 @@ int two_pdus_notify_test()
sta_buf->N_bytes = srslte::rlc_am_write_status_pdu(&s1, sta_buf->msg); sta_buf->N_bytes = srslte::rlc_am_write_status_pdu(&s1, sta_buf->msg);
rlc.write_pdu(sta_buf->msg, sta_buf->N_bytes); rlc.write_pdu(sta_buf->msg, sta_buf->N_bytes);
TESTASSERT(pdcp.notified_counts.size() == 0);
// Feed ack of PDU2 to RLC // Feed ack of PDU2 to RLC
srslte::rlc_status_pdu_t s2; srslte::rlc_status_pdu_t s2;
@ -403,10 +402,14 @@ int two_sdus_out_of_order_ack_notify_test()
// Intentionally do not write first ack to RLC // Intentionally do not write first ack to RLC
// Feed ack of PDU2 to RLC // Ack of PDU2 to RLC, with PDU1 with NACK
srslte::rlc_status_nack_t nack = {};
nack.nack_sn = 1;
srslte::rlc_status_pdu_t s2; srslte::rlc_status_pdu_t s2;
s2.ack_sn = 2; s2.ack_sn = 2;
s2.N_nack = 0; s2.N_nack = 1;
s2.nacks[0] = nack;
// Write second ack // Write second ack
sta_buf->N_bytes = srslte::rlc_am_write_status_pdu(&s2, sta_buf->msg); sta_buf->N_bytes = srslte::rlc_am_write_status_pdu(&s2, sta_buf->msg);
@ -472,6 +475,7 @@ int two_pdus_out_of_order_ack_notify_test()
sta_buf->N_bytes = srslte::rlc_am_write_status_pdu(&s1, sta_buf->msg); sta_buf->N_bytes = srslte::rlc_am_write_status_pdu(&s1, sta_buf->msg);
rlc.write_pdu(sta_buf->msg, sta_buf->N_bytes); rlc.write_pdu(sta_buf->msg, sta_buf->N_bytes);
TESTASSERT(pdcp.notified_counts.size() == 0);
// Feed ack of PDU2 to RLC // Feed ack of PDU2 to RLC
srslte::rlc_status_pdu_t s2; srslte::rlc_status_pdu_t s2;

@ -57,7 +57,16 @@ public:
void write_pdu_bcch_dlsch(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_pcch(unique_byte_buffer_t sdu) {}
void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {} void write_pdu_mch(uint32_t lcid, srslte::unique_byte_buffer_t pdu) {}
void notify_delivery(uint32_t lcid, const std::vector<uint32_t>& tx_count) {} void notify_delivery(uint32_t lcid, const std::vector<uint32_t>& pdcp_sn_vec)
{
for (uint32_t pdcp_sn : pdcp_sn_vec) {
if (notified_counts.find(pdcp_sn) == notified_counts.end()) {
notified_counts[pdcp_sn] = 0;
}
assert(lcid == 1);
notified_counts[pdcp_sn] += 1;
}
}
// RRC interface // RRC interface
void max_retx_attempted() {} void max_retx_attempted() {}
@ -66,6 +75,8 @@ public:
unique_byte_buffer_t sdus[10]; unique_byte_buffer_t sdus[10];
int n_sdus; int n_sdus;
rlc_pcap* pcap; rlc_pcap* pcap;
std::map<uint32_t, uint32_t> notified_counts; // Map of PDCP SNs to number of notifications
}; };
class ul_writer : public thread class ul_writer : public thread
@ -114,7 +125,6 @@ private:
int basic_test_tx(rlc_am_lte* rlc, byte_buffer_t pdu_bufs[NBUFS]) int basic_test_tx(rlc_am_lte* rlc, byte_buffer_t pdu_bufs[NBUFS])
{ {
// Push 5 SDUs into RLC1 // Push 5 SDUs into RLC1
byte_buffer_pool* pool = byte_buffer_pool::get_instance(); byte_buffer_pool* pool = byte_buffer_pool::get_instance();
unique_byte_buffer_t sdu_bufs[NBUFS]; unique_byte_buffer_t sdu_bufs[NBUFS];
@ -122,6 +132,7 @@ int basic_test_tx(rlc_am_lte* rlc, byte_buffer_t pdu_bufs[NBUFS])
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true); sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer 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 sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
sdu_bufs[i]->md.pdcp_sn = i; // PDCP SN for notifications
rlc->write_sdu(std::move(sdu_bufs[i])); rlc->write_sdu(std::move(sdu_bufs[i]));
} }
@ -182,9 +193,13 @@ int basic_test()
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
for (int i = 0; i < tester.n_sdus; i++) { // Check PDCP notifications
std::cout << tester.notified_counts.size() << std::endl;
TESTASSERT(tester.notified_counts.size() == 5);
for (uint16_t i = 0; i < tester.n_sdus; i++) {
TESTASSERT(tester.sdus[i]->N_bytes == 1); TESTASSERT(tester.sdus[i]->N_bytes == 1);
TESTASSERT(*(tester.sdus[i]->msg) == i); TESTASSERT(*(tester.sdus[i]->msg) == i);
TESTASSERT(tester.notified_counts[i] == 1);
} }
// Check statistics // Check statistics
@ -216,6 +231,7 @@ int concat_test()
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true); sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer 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 sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
sdu_bufs[i]->md.pdcp_sn = i; // PDCP SN for notifications
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -253,6 +269,14 @@ int concat_test()
TESTASSERT(*(tester.sdus[i]->msg) == i); TESTASSERT(*(tester.sdus[i]->msg) == i);
} }
// Check PDCP notifications
TESTASSERT(tester.notified_counts.size() == 5);
for (uint16_t i = 0; i < tester.n_sdus; i++) {
TESTASSERT(tester.sdus[i]->N_bytes == 1);
TESTASSERT(*(tester.sdus[i]->msg) == i);
TESTASSERT(tester.notified_counts[i] == 1);
}
// Check statistics // Check statistics
TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics())); TESTASSERT(rx_is_tx(rlc1.get_metrics(), rlc2.get_metrics()));
@ -284,6 +308,7 @@ int segment_test(bool in_seq_rx)
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
sdu_bufs[i]->md.pdcp_sn = i; // PDCP SN for notifications
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -329,6 +354,13 @@ int segment_test(bool in_seq_rx)
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check all notification of ack'ed PDUs
TESTASSERT(tester.notified_counts.size() == 5);
for (int i = 0; i < NBUFS; i++) {
auto not_it = tester.notified_counts.find(i);
TESTASSERT(not_it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
} }
TESTASSERT(0 == rlc2.get_buffer_state()); TESTASSERT(0 == rlc2.get_buffer_state());
@ -370,6 +402,7 @@ int retx_test()
sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true); sdu_bufs[i] = srslte::allocate_unique_buffer(*pool, true);
sdu_bufs[i]->msg[0] = i; // Write the index into the buffer 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 sdu_bufs[i]->N_bytes = 1; // Give each buffer a size of 1 byte
sdu_bufs[i]->md.pdcp_sn = i; // PDCP SN for notifications
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -422,6 +455,17 @@ int retx_test()
TESTASSERT(3 == rlc1.get_buffer_state()); // 2 byte header + 1 byte payload TESTASSERT(3 == rlc1.get_buffer_state()); // 2 byte header + 1 byte payload
// Check notifications of ack'ed PDUs
TESTASSERT(tester.notified_counts.size() == 4);
for (int i = 0; i < NBUFS; i++) {
auto not_it = tester.notified_counts.find(i);
if (i != 1) {
TESTASSERT(not_it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
} else {
TESTASSERT(not_it == tester.notified_counts.end());
}
}
// Read the retx PDU from RLC1 // Read the retx PDU from RLC1
byte_buffer_t retx; byte_buffer_t retx;
len = rlc1.read_pdu(retx.msg, 3); // 2 byte header + 1 byte payload len = rlc1.read_pdu(retx.msg, 3); // 2 byte header + 1 byte payload
@ -438,6 +482,33 @@ int retx_test()
return -1; return -1;
} }
// Step timers until poll Retx timeout expires
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Get status report of RETX PDU
buffer_state = rlc2.get_buffer_state();
TESTASSERT(2 == buffer_state);
len = rlc2.read_pdu(status_buf.msg, buffer_state); // provide exactly the reported buffer state
status_buf.N_bytes = len;
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // 1 packet was lost.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 4.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check all notification of ack'ed PDUs
TESTASSERT(tester.notified_counts.size() == 5);
for (int i = 0; i < NBUFS; i++) {
auto not_it = tester.notified_counts.find(i);
TESTASSERT(not_it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
return 0; return 0;
} }
@ -482,8 +553,7 @@ int segment_retx_test()
TESTASSERT(rlc1.get_buffer_state() == 0); TESTASSERT(rlc1.get_buffer_state() == 0);
// Step timers until poll Retx timeout expires // Step timers until poll Retx timeout expires
int cnt = 5; for (int cnt = 0; cnt < 5; cnt++) {
while (cnt--) {
timers.step_all(); timers.step_all();
} }
@ -506,12 +576,20 @@ int segment_retx_test()
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
status_buf.N_bytes = len; status_buf.N_bytes = len;
// 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 == 0); // 1 packet was lost.
TESTASSERT(status_check.ack_sn == 1); // Delivered up to SN 0.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Make sure no notifications yet
TESTASSERT(tester.notified_counts.size() == 0);
// Step timers again until poll Retx timeout expires // Step timers again until poll Retx timeout expires
cnt = 5; for (int cnt = 0; cnt < 5; cnt++) {
while (cnt--) {
timers.step_all(); timers.step_all();
} }
@ -532,6 +610,16 @@ int segment_retx_test()
status_buf.N_bytes = len; status_buf.N_bytes = len;
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // 1 packet was lost.
TESTASSERT(status_check.ack_sn == 2); // Delivered up to SN 0.
// Make sure SDU was notified
TESTASSERT(tester.notified_counts.size() == 1);
TESTASSERT(tester.notified_counts.find(0) != tester.notified_counts.end() && tester.notified_counts[0] == 1);
TESTASSERT(tester.n_sdus == nof_sdus); TESTASSERT(tester.n_sdus == nof_sdus);
for (int i = 0; i < tester.n_sdus; i++) { for (int i = 0; i < tester.n_sdus; i++) {
if (tester.sdus[i]->N_bytes != 10) { if (tester.sdus[i]->N_bytes != 10) {
@ -574,6 +662,7 @@ int resegment_test_1()
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -595,8 +684,7 @@ int resegment_test_1()
} }
// Step timers until reordering timeout expires // Step timers until reordering timeout expires
int cnt = 5; for (int cnt = 0; cnt < 5; cnt++) {
while (cnt--) {
timers.step_all(); timers.step_all();
} }
@ -607,11 +695,29 @@ int resegment_test_1()
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
status_buf.N_bytes = len; status_buf.N_bytes = len;
// 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 5.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
TESTASSERT(12 == rlc1.get_buffer_state()); // 2 byte header + 10 data TESTASSERT(12 == rlc1.get_buffer_state()); // 2 byte header + 10 data
// Check notifications
rrc_log1->debug("%ld\n", tester.notified_counts.size());
TESTASSERT(tester.notified_counts.size() == 4);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
if (i != 1) {
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
} else {
TESTASSERT(it == tester.notified_counts.end());
}
}
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
len = rlc1.read_pdu(retx1.msg, 9); // 4 byte header + 5 data len = rlc1.read_pdu(retx1.msg, 9); // 4 byte header + 5 data
@ -622,6 +728,22 @@ int resegment_test_1()
TESTASSERT(9 == rlc1.get_buffer_state()); TESTASSERT(9 == rlc1.get_buffer_state());
// Step timers to get status report
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Read status PDU from RLC2
status_buf = {};
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
status_buf.N_bytes = len;
// Assert status is correct
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 5.
// Read the remaining segment // Read the remaining segment
byte_buffer_t retx2; byte_buffer_t retx2;
len = rlc1.read_pdu(retx2.msg, 9); // 4 byte header + 5 data len = rlc1.read_pdu(retx2.msg, 9); // 4 byte header + 5 data
@ -639,12 +761,37 @@ int resegment_test_1()
return -1; return -1;
} }
// Step timers to get status report
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Read status PDU from RLC2
status_buf = {};
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
status_buf.N_bytes = len;
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check notifications
TESTASSERT(tester.notified_counts.size() == 5);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
return 0; return 0;
} }
int resegment_test_2() int resegment_test_2()
{ {
// SDUs: | 10 | 10 | 10 | 10 | 10 | // SDUs: | 10 | 10 | 10 | 10 | 10 |
// PDUs: | 5 | 10 | 20 | 10 | 5 | // PDUs: | 5 | 10 | 20 | 10 | 5 |
// Retx PDU segments: | 10 | 10 | // Retx PDU segments: | 10 | 10 |
@ -672,6 +819,7 @@ int resegment_test_2()
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
sdu_bufs[i]->md.pdcp_sn = i; // Give each buffer a size of 10 bytes
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -694,8 +842,7 @@ int resegment_test_2()
} }
// Step timers until reordering timeout expires // Step timers until reordering timeout expires
int cnt = 5; for (int cnt = 0; cnt < 5; cnt++) {
while (cnt--) {
timers.step_all(); timers.step_all();
} }
@ -705,11 +852,28 @@ int resegment_test_2()
byte_buffer_t status_buf; byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// 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); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
TESTASSERT(25 == rlc1.get_buffer_state()); // 4 byte header + 20 data TESTASSERT(25 == rlc1.get_buffer_state()); // 4 byte header + 20 data
// Check notifications
TESTASSERT(tester.notified_counts.size() == 2);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
if (i == 0 || i == 4) {
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
} else {
TESTASSERT(it == tester.notified_counts.end());
}
}
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 6 byte header + 10 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 6 byte header + 10 data
@ -735,12 +899,33 @@ int resegment_test_2()
return -1; return -1;
} }
// Step timers until reordering timeout expires
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Read status PDU from RLC2
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
TESTASSERT(tester.notified_counts.size() == 5);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
return 0; return 0;
} }
int resegment_test_3() int resegment_test_3()
{ {
// SDUs: | 10 | 10 | 10 | 10 | 10 | // SDUs: | 10 | 10 | 10 | 10 | 10 |
// PDUs: | 5 | 5| 20 | 10 | 10 | // PDUs: | 5 | 5| 20 | 10 | 10 |
// Retx PDU segments: | 10 | 10 | // Retx PDU segments: | 10 | 10 |
@ -767,6 +952,7 @@ int resegment_test_3()
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -789,8 +975,7 @@ int resegment_test_3()
} }
// Step timers until reordering timeout expires // Step timers until reordering timeout expires
int cnt = 5; for (int cnt = 0; cnt < 5; cnt++) {
while (cnt--) {
timers.step_all(); timers.step_all();
} }
@ -800,9 +985,26 @@ int resegment_test_3()
byte_buffer_t status_buf; byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// 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); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check notifications
TESTASSERT(tester.notified_counts.size() == 3);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
if (i == 0 || i == 3 || i == 4) {
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
} else {
TESTASSERT(it == tester.notified_counts.end());
}
}
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 6 byte header + 10 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 6 byte header + 10 data
@ -826,6 +1028,29 @@ int resegment_test_3()
return -1; return -1;
} }
// Get status from RLC 2
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Read status PDU from RLC2
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check final notifications
TESTASSERT(tester.notified_counts.size() == 5);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
return 0; return 0;
} }
@ -857,6 +1082,7 @@ int resegment_test_4()
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -890,9 +1116,25 @@ int resegment_test_4()
byte_buffer_t status_buf; byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// 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); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
TESTASSERT(tester.notified_counts.size() == 2);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
if (i == 0 || i == 4) {
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
} else {
TESTASSERT(it == tester.notified_counts.end());
}
}
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 21); // 6 byte header + 15 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 21); // 6 byte header + 15 data
@ -918,6 +1160,29 @@ int resegment_test_4()
return -1; return -1;
} }
// Get status from RLC 2
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Read status PDU from RLC2
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check final notifications
TESTASSERT(tester.notified_counts.size() == 5);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
return 0; return 0;
} }
@ -949,6 +1214,7 @@ int resegment_test_5()
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -982,9 +1248,18 @@ int resegment_test_5()
byte_buffer_t status_buf; byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// 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); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check notifications
TESTASSERT(tester.notified_counts.size() == 0);
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 27); // 7 byte header + 20 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 27); // 7 byte header + 20 data
@ -1010,6 +1285,30 @@ int resegment_test_5()
return -1; return -1;
} }
// Get status from RLC 2
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Read status PDU from RLC2
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check final notifications
TESTASSERT(tester.notified_counts.size() == 5);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
return 0; return 0;
} }
@ -1042,6 +1341,7 @@ int resegment_test_6()
for (int j = 0; j < 10; j++) for (int j = 0; j < 10; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes sdu_bufs[i]->N_bytes = 10; // Give each buffer a size of 10 bytes
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
for (int i = 3; i < 9; i++) { for (int i = 3; i < 9; i++) {
@ -1049,6 +1349,7 @@ int resegment_test_6()
for (int j = 0; j < 54; j++) for (int j = 0; j < 54; j++)
sdu_bufs[i]->msg[j] = j; sdu_bufs[i]->msg[j] = j;
sdu_bufs[i]->N_bytes = 54; sdu_bufs[i]->N_bytes = 54;
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -1086,11 +1387,28 @@ int resegment_test_6()
len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status len = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
status_buf.N_bytes = len; status_buf.N_bytes = len;
// 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);
TESTASSERT(status_check.ack_sn == 5);
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
TESTASSERT(278 == rlc1.get_buffer_state()); TESTASSERT(278 == rlc1.get_buffer_state());
// Check notifications
TESTASSERT(tester.notified_counts.size() == 4);
for (int i = 0; i < 5; i++) {
auto it = tester.notified_counts.find(i);
if (i == 0 || i == 1 || i == 2 || i == 8) {
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
} else {
TESTASSERT(it == tester.notified_counts.end());
}
}
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
len = rlc1.read_pdu(retx1.msg, 129); len = rlc1.read_pdu(retx1.msg, 129);
@ -1126,6 +1444,30 @@ int resegment_test_6()
} }
} }
// Get status from RLC 2
for (int cnt = 0; cnt < 5; cnt++) {
timers.step_all();
}
// Read status PDU from RLC2
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
// Check final notifications
TESTASSERT(tester.notified_counts.size() == 9);
for (int i = 0; i < 9; i++) {
auto it = tester.notified_counts.find(i);
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
return 0; return 0;
} }
@ -1170,6 +1512,7 @@ int resegment_test_7()
sdu_bufs[i]->msg[j] = i; sdu_bufs[i]->msg[j] = i;
} }
sdu_bufs[i]->N_bytes = sdu_size; // Give each buffer a size of 15 bytes sdu_bufs[i]->N_bytes = sdu_size; // Give each buffer a size of 15 bytes
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }
@ -1231,6 +1574,12 @@ int resegment_test_7()
byte_buffer_t status_buf; byte_buffer_t status_buf;
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// 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); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
#if HAVE_PCAP #if HAVE_PCAP
@ -1239,6 +1588,9 @@ int resegment_test_7()
TESTASSERT(15 == rlc1.get_buffer_state()); TESTASSERT(15 == rlc1.get_buffer_state());
// Check notifications
TESTASSERT(tester.notified_counts.size() == 0);
// second round of retx, forcing resegmentation // second round of retx, forcing resegmentation
byte_buffer_t retx2[4]; byte_buffer_t retx2[4];
for (uint32_t i = 0; i < 4; i++) { for (uint32_t i = 0; i < 4; i++) {
@ -1265,6 +1617,12 @@ int resegment_test_7()
TESTASSERT(rlc2.get_buffer_state()); TESTASSERT(rlc2.get_buffer_state());
status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status status_buf.N_bytes = rlc2.read_pdu(status_buf.msg, 10); // 10 bytes is enough to hold the status
// Assert status is correct
status_check = {};
rlc_am_read_status_pdu(status_buf.msg, status_buf.N_bytes, &status_check);
TESTASSERT(status_check.N_nack == 0); // all packets delivered.
TESTASSERT(status_check.ack_sn == 5); // Delivered up to SN 5.
// Write status PDU to RLC1 // Write status PDU to RLC1
rlc1.write_pdu(status_buf.msg, status_buf.N_bytes); rlc1.write_pdu(status_buf.msg, status_buf.N_bytes);
#if HAVE_PCAP #if HAVE_PCAP
@ -1286,6 +1644,13 @@ int resegment_test_7()
} }
} }
// Check final notifications
TESTASSERT(tester.notified_counts.size() == 2);
for (int i = 0; i < 2; i++) {
auto it = tester.notified_counts.find(i);
TESTASSERT(it != tester.notified_counts.end() && tester.notified_counts[i] == 1);
}
#if HAVE_PCAP #if HAVE_PCAP
pcap.close(); pcap.close();
#endif #endif
@ -1333,7 +1698,8 @@ int resegment_test_8()
for (uint32_t j = 0; j < sdu_size; j++) { for (uint32_t j = 0; j < sdu_size; j++) {
sdu_bufs[i]->msg[j] = i; sdu_bufs[i]->msg[j] = i;
} }
sdu_bufs[i]->N_bytes = sdu_size; // Give each buffer a size of 15 bytes sdu_bufs[i]->N_bytes = sdu_size; // Give each buffer a size of 30 bytes
sdu_bufs[i]->md.pdcp_sn = i;
rlc1.write_sdu(std::move(sdu_bufs[i])); rlc1.write_sdu(std::move(sdu_bufs[i]));
} }

Loading…
Cancel
Save