tools/testing/selftests/net/tcp_ao/seq-ext.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/net/tcp_ao/seq-ext.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/net/tcp_ao/seq-ext.c
Extension
.c
Size
7781 bytes
Lines
256
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/* Check that after SEQ number wrap-around:
 * 1. SEQ-extension has upper bytes set
 * 2. TCP connection is alive and no TCPAOBad segments
 * In order to test (2), the test doesn't just adjust seq number for a queue
 * on a connected socket, but migrates it to another sk+port number, so
 * that there won't be any delayed packets that will fail to verify
 * with the new SEQ numbers.
 */
#include <inttypes.h>
#include "aolib.h"

const unsigned int nr_packets = 1000;
const unsigned int msg_len = 1000;
const unsigned int quota = nr_packets * msg_len;
unsigned int client_new_port;

/* Move them closer to roll-over */
static void test_adjust_seqs(struct tcp_sock_state *img,
			     struct tcp_ao_repair *ao_img,
			     bool server)
{
	uint32_t new_seq1, new_seq2;

	/* make them roll-over during quota, but on different segments */
	if (server) {
		new_seq1 = ((uint32_t)-1) - msg_len;
		new_seq2 = ((uint32_t)-1) - (quota - 2 * msg_len);
	} else {
		new_seq1 = ((uint32_t)-1) - (quota - 2 * msg_len);
		new_seq2 = ((uint32_t)-1) - msg_len;
	}

	img->in.seq = new_seq1;
	img->trw.snd_wl1 = img->in.seq - msg_len;
	img->out.seq = new_seq2;
	img->trw.rcv_wup = img->in.seq;
}

static int test_sk_restore(struct tcp_sock_state *img,
			   struct tcp_ao_repair *ao_img, sockaddr_af *saddr,
			   const union tcp_addr daddr, unsigned int dport,
			   struct tcp_counters *cnt)
{
	int sk;

	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);
	if (sk < 0)
		test_error("socket()");

	test_enable_repair(sk);
	test_sock_restore(sk, img, saddr, daddr, dport);
	if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0, daddr, -1, 100, 100))
		test_error("setsockopt(TCP_AO_ADD_KEY)");
	test_ao_restore(sk, ao_img);

	if (test_get_tcp_counters(sk, cnt))
		test_error("test_get_tcp_counters()");

	test_disable_repair(sk);
	test_sock_state_free(img);
	return sk;
}

static void *server_fn(void *arg)
{
	uint64_t before_good, after_good, after_bad;
	struct tcp_counters cnt1, cnt2;
	struct tcp_sock_state img;
	struct tcp_ao_repair ao_img;
	sockaddr_af saddr;
	ssize_t bytes;
	int sk, lsk;

	lsk = test_listen_socket(this_ip_addr, test_server_port, 1);

	if (test_add_key(lsk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))
		test_error("setsockopt(TCP_AO_ADD_KEY)");

	synchronize_threads(); /* 1: MKT added => connect() */

	if (test_wait_fd(lsk, TEST_TIMEOUT_SEC, 0))
		test_error("test_wait_fd()");

	sk = accept(lsk, NULL, NULL);
	if (sk < 0)
		test_error("accept()");

	synchronize_threads(); /* 2: accepted => send data */
	close(lsk);

Annotation

Implementation Notes