test_connection: test packet queue and (re)transmission
All checks were successful
/ build-hamnet70 (push) Successful in 38s
/ build-doc (push) Successful in 17s
/ deploy-doc (push) Has been skipped

This commit is contained in:
Thomas Kolb 2025-02-23 13:55:03 +01:00
commit f7a0186f4f

View file

@ -3,6 +3,7 @@
#include "layer2/packet_queue.h"
#include "layer2/packet_structs.h"
#include "results.h"
#include "utils.h"
#include "config.h"
@ -312,5 +313,200 @@ int main(void)
expected_state.next_expected_seq = 3;
ASSERT_STATE(expected_state, conn);
LOG(LVL_INFO, ">>> Checking packet transmission.");
LOG(LVL_INFO, "Enqueueing 8 packets and checking that they are transmitted correctly.");
// prepare 200 static bytes of payload data (starts at index 1).
// the first byte is used as a counter.
for(size_t i = 0; i < 200; i++) {
static_payload[i+1] = i;
}
// enqueue 8 packets
for(size_t i = 0; i < 8; i++) {
payload_len = 201;
static_payload[0] = i;
ASSERT_RESULT(OK, connection_enqueue_data_packet(&conn, L2_PAYLOAD_TYPE_IPV6, static_payload, payload_len));
}
// "transmit" these 8 packets
for(size_t i = 0; i < 8; i++) {
ASSERT_TRUE(connection_can_transmit(&conn));
packet_len = connection_encode_next_packet(&conn, packet_buf, sizeof(packet_buf), &end_burst);
ASSERT_EQUAL_UINT(214, packet_len);
bool header_decoded_ok = layer2_decode_packet_header(packet_buf, packet_len, &header);
ASSERT_TRUE(header_decoded_ok);
LOG(LVL_DUMP, "Header of supposed data packet:");
layer2_dump_packet_header(LVL_DUMP, &header);
// check the header
if(i == 7) {
ASSERT_TRUE(header.tx_request);
} else {
ASSERT_FALSE(header.tx_request);
}
ASSERT_EQUAL_UINT(3, header.rx_seq_nr);
ASSERT_EQUAL_UINT(i, header.tx_seq_nr);
}
ASSERT_FALSE(connection_can_transmit(&conn));
// no packet must be returned
packet_len = connection_encode_next_packet(&conn, packet_buf, sizeof(packet_buf), &end_burst);
ASSERT_EQUAL_UINT(0, packet_len);
expected_state.next_seq_nr = 8;
expected_state.next_packet_index = 8;
ASSERT_STATE(expected_state, conn);
LOG(LVL_INFO, "Acknowledging up to packet #6 -> #7 must be retransmitted");
// build empty ACK packet
header.dst_addr = dut_address;
header.src_addr = peer_address;
header.msg_type = L2_MSG_TYPE_EMPTY;
header.rx_seq_nr = 7;
header.tx_seq_nr = 0;
header.tx_request = 1;
packet_len = layer2_encode_packet(&header, NULL, 0, packet_buf, sizeof(packet_buf));
ASSERT_EQUAL_UINT(12, packet_len);
ASSERT_RESULT(OK, connection_handle_packet(&conn, packet_buf, packet_len, &data_packet, &tx_req_rcvd));
// next packet index must change because packets were removed from the queue
expected_state.next_packet_index = 1;
expected_state.last_acked_seq = 7;
ASSERT_STATE(expected_state, conn);
// reset the transmitter
connection_restart_tx(&conn);
expected_state.next_packet_index = 0;
ASSERT_STATE(expected_state, conn);
// verify that the next encoded packet is indeed the one with sequence number 7
ASSERT_TRUE(connection_can_transmit(&conn));
packet_len = connection_encode_next_packet(&conn, packet_buf, sizeof(packet_buf), &end_burst);
ASSERT_EQUAL_UINT(214, packet_len);
ASSERT_FALSE(connection_can_transmit(&conn));
header_decoded_ok = layer2_decode_packet_header(packet_buf, packet_len, &header);
ASSERT_TRUE(header_decoded_ok);
LOG(LVL_DUMP, "Header of supposed data packet #7:");
layer2_dump_packet_header(LVL_DUMP, &header);
// check the header
ASSERT_TRUE(header.tx_request);
ASSERT_EQUAL_UINT(3, header.rx_seq_nr);
ASSERT_EQUAL_UINT(7, header.tx_seq_nr);
// check the payload
header_size = layer2_get_encoded_header_size(&header);
payload_len = packet_len - header_size - crc_size;
payload = packet_buf + header_size;
ASSERT_EQUAL_UINT(L2_PAYLOAD_TYPE_IPV6, payload[0]);
ASSERT_EQUAL_UINT(7, payload[1]);
// enqueue 10 more packets to test the sequence number overflow.
for(size_t i = 0; i < 10; i++) {
payload_len = 201;
static_payload[0] = i;
ASSERT_RESULT(OK, connection_enqueue_data_packet(&conn, L2_PAYLOAD_TYPE_IPV6, static_payload, payload_len));
}
ASSERT_TRUE(connection_can_transmit(&conn));
expected_state.next_seq_nr = 2;
expected_state.next_packet_index = 1;
ASSERT_STATE(expected_state, conn);
// transmitter was NOT reset, so #7 remains in the queue, but is not transmitted again.
// Only 10 packets should be "transmitted" before the burst ends.
for(size_t i = 0; i < 10; i++) {
ASSERT_TRUE(connection_can_transmit(&conn));
packet_len = connection_encode_next_packet(&conn, packet_buf, sizeof(packet_buf), &end_burst);
ASSERT_EQUAL_UINT(214, packet_len);
bool header_decoded_ok = layer2_decode_packet_header(packet_buf, packet_len, &header);
ASSERT_TRUE(header_decoded_ok);
// check the header
if(i == 9) {
ASSERT_TRUE(header.tx_request);
} else {
ASSERT_FALSE(header.tx_request);
}
ASSERT_EQUAL_UINT(3, header.rx_seq_nr);
ASSERT_EQUAL_UINT((i+8)%16, header.tx_seq_nr);
}
ASSERT_FALSE(connection_can_transmit(&conn));
expected_state.next_packet_index = 11;
ASSERT_STATE(expected_state, conn);
LOG(LVL_INFO, "Queue overflow test:");
// nothing has been acknowledged so far, so we have 11 packets in the queue.
// It must be possible to add 4 more packets, but the 5th must fail.
// enqueue 5 more packets to test queue full checks.
for(size_t i = 0; i < 5; i++) {
payload_len = 201;
static_payload[0] = i;
LOG(LVL_DEBUG, "Trying to add %dth entry (15 max) to queue:", i+12);
result_t result = connection_enqueue_data_packet(&conn, L2_PAYLOAD_TYPE_IPV6, static_payload, payload_len);
if(i < 4) {
ASSERT_RESULT(OK, result);
} else {
ASSERT_RESULT(ERR_NO_MEM, result);
}
}
expected_state.next_seq_nr += 4;
ASSERT_STATE(expected_state, conn);
LOG(LVL_INFO, "Acknowledging all packets");
// build empty ACK packet
header.dst_addr = dut_address;
header.src_addr = peer_address;
header.msg_type = L2_MSG_TYPE_EMPTY;
header.rx_seq_nr = 6;
header.tx_seq_nr = 0;
header.tx_request = 1;
packet_len = layer2_encode_packet(&header, NULL, 0, packet_buf, sizeof(packet_buf));
ASSERT_EQUAL_UINT(12, packet_len);
ASSERT_RESULT(OK, connection_handle_packet(&conn, packet_buf, packet_len, &data_packet, &tx_req_rcvd));
expected_state.next_packet_index = 0;
expected_state.last_acked_seq = 6;
ASSERT_STATE(expected_state, conn);
// TODO: test connection close sequence
LOG(LVL_INFO, ">>> All assertions successful.");
}