tools/testing/selftests/net/tcp_ao/restore.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/net/tcp_ao/restore.c
Extension
.c
Size
8410 bytes
Lines
252
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
/* Author: Dmitry Safonov <dima@arista.com> */
/* This is over-simplified TCP_REPAIR for TCP_ESTABLISHED sockets
 * It tests that TCP-AO enabled connection can be restored.
 * For the proper socket repair see:
 * https://github.com/checkpoint-restore/criu/blob/criu-dev/soccr/soccr.h
 */
#include <inttypes.h>
#include "aolib.h"

const size_t nr_packets = 20;
const size_t msg_len = 100;
const size_t quota = nr_packets * msg_len;
#define fault(type)	(inj == FAULT_ ## type)

static void try_server_run(const char *tst_name, unsigned int port,
			   fault_t inj, test_cnt cnt_expected)
{
	test_cnt poll_cnt = (cnt_expected == TEST_CNT_GOOD) ? 0 : cnt_expected;
	const char *cnt_name = "TCPAOGood";
	struct tcp_counters cnt1, cnt2;
	uint64_t before_cnt, after_cnt;
	int sk, lsk, dummy;
	ssize_t bytes;

	if (fault(TIMEOUT))
		cnt_name = "TCPAOBad";
	lsk = test_listen_socket(this_ip_addr, 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);

	bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);
	if (bytes != quota) {
		test_fail("%s: server served: %zd", tst_name, bytes);
		goto out;
	}

	before_cnt = netstat_get_one(cnt_name, NULL);
	if (test_get_tcp_counters(sk, &cnt1))
		test_error("test_get_tcp_counters()");

	bytes = test_skpair_server(sk, quota, poll_cnt, &dummy);
	if (fault(TIMEOUT)) {
		if (bytes > 0)
			test_fail("%s: server served: %zd", tst_name, bytes);
		else
			test_ok("%s: server couldn't serve", tst_name);
	} else {
		if (bytes != quota)
			test_fail("%s: server served: %zd", tst_name, bytes);
		else
			test_ok("%s: server alive", tst_name);
	}
	synchronize_threads(); /* 3: counters checks */
	if (test_get_tcp_counters(sk, &cnt2))
		test_error("test_get_tcp_counters()");
	after_cnt = netstat_get_one(cnt_name, NULL);

	test_assert_counters(tst_name, &cnt1, &cnt2, cnt_expected);

	if (after_cnt <= before_cnt) {
		test_fail("%s(server): %s counter did not increase: %" PRIu64 " <= %" PRIu64,
			  tst_name, cnt_name, after_cnt, before_cnt);
	} else {
		test_ok("%s(server): counter %s increased %" PRIu64 " => %" PRIu64,
			tst_name, cnt_name, before_cnt, after_cnt);
	}

	/*
	 * Before close() as that will send FIN and move the peer in TCP_CLOSE
	 * and that will prevent reading AO counters from the peer's socket.
	 */
	synchronize_threads(); /* 4: verified => closed */
out:
	close(sk);
}

static void *server_fn(void *arg)

Annotation

Implementation Notes