// SPDX-License-Identifier: GPL-2.0
/* Check that after SEQ number wrap-around:
 * 1. SEQ-extension has upper bytes set
 * 2. TCP conneciton 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_ao_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_ao_counters(sk, cnt))
		test_error("test_get_tcp_ao_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_ao_counters ao1, ao2;
	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);

	bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);
	if (bytes != quota) {
		if (bytes > 0)
			test_fail("server served: %zd", bytes);
		else
			test_fail("server returned: %zd", bytes);
		goto out;
	}

	before_good = netstat_get_one("TCPAOGood", NULL);

	synchronize_threads(); /* 3: restore the connection on another port */

	test_enable_repair(sk);
	test_sock_checkpoint(sk, &img, &saddr);
	test_ao_checkpoint(sk, &ao_img);
	test_kill_sk(sk);
#ifdef IPV6_TEST
	saddr.sin6_port = htons(ntohs(saddr.sin6_port) + 1);
#else
	saddr.sin_port = htons(ntohs(saddr.sin_port) + 1);
#endif
	test_adjust_seqs(&img, &ao_img, true);
	synchronize_threads(); /* 4: dump finished */
	sk = test_sk_restore(&img, &ao_img, &saddr, this_ip_dest,
			     client_new_port, &ao1);

	synchronize_threads(); /* 5: verify counters during SEQ-number rollover */
	bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);
	if (bytes != quota) {
		if (bytes > 0)
			test_fail("server served: %zd", bytes);
		else
			test_fail("server returned: %zd", bytes);
	} else {
		test_ok("server alive");
	}

	if (test_get_tcp_ao_counters(sk, &ao2))
		test_error("test_get_tcp_ao_counters()");
	after_good = netstat_get_one("TCPAOGood", NULL);

	test_tcp_ao_counters_cmp(NULL, &ao1, &ao2, TEST_CNT_GOOD);

	if (after_good <= before_good) {
		test_fail("TCPAOGood counter did not increase: %zu <= %zu",
			  after_good, before_good);
	} else {
		test_ok("TCPAOGood counter increased %zu => %zu",
			before_good, after_good);
	}
	after_bad = netstat_get_one("TCPAOBad", NULL);
	if (after_bad)
		test_fail("TCPAOBad counter is non-zero: %zu", after_bad);
	else
		test_ok("TCPAOBad counter didn't increase");
	test_enable_repair(sk);
	test_ao_checkpoint(sk, &ao_img);
	if (ao_img.snd_sne && ao_img.rcv_sne) {
		test_ok("SEQ extension incremented: %u/%u",
			ao_img.snd_sne, ao_img.rcv_sne);
	} else {
		test_fail("SEQ extension was not incremented: %u/%u",
			  ao_img.snd_sne, ao_img.rcv_sne);
	}

	synchronize_threads(); /* 6: verified => closed */
out:
	close(sk);
	return NULL;
}

static void *client_fn(void *arg)
{
	uint64_t before_good, after_good, after_bad;
	struct tcp_ao_counters ao1, ao2;
	struct tcp_sock_state img;
	struct tcp_ao_repair ao_img;
	sockaddr_af saddr;
	int sk;

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

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

	synchronize_threads(); /* 1: MKT added => connect() */
	if (test_connect_socket(sk, this_ip_dest, test_server_port) <= 0)
		test_error("failed to connect()");

	synchronize_threads(); /* 2: accepted => send data */
	if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC)) {
		test_fail("pre-migrate verify failed");
		return NULL;
	}

	before_good = netstat_get_one("TCPAOGood", NULL);

	synchronize_threads(); /* 3: restore the connection on another port */
	test_enable_repair(sk);
	test_sock_checkpoint(sk, &img, &saddr);
	test_ao_checkpoint(sk, &ao_img);
	test_kill_sk(sk);
#ifdef IPV6_TEST
	client_new_port = ntohs(saddr.sin6_port) + 1;
	saddr.sin6_port = htons(ntohs(saddr.sin6_port) + 1);
#else
	client_new_port = ntohs(saddr.sin_port) + 1;
	saddr.sin_port = htons(ntohs(saddr.sin_port) + 1);
#endif
	test_adjust_seqs(&img, &ao_img, false);
	synchronize_threads(); /* 4: dump finished */
	sk = test_sk_restore(&img, &ao_img, &saddr, this_ip_dest,
			     test_server_port + 1, &ao1);

	synchronize_threads(); /* 5: verify counters during SEQ-number rollover */
	if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC))
		test_fail("post-migrate verify failed");
	else
		test_ok("post-migrate connection alive");

	if (test_get_tcp_ao_counters(sk, &ao2))
		test_error("test_get_tcp_ao_counters()");
	after_good = netstat_get_one("TCPAOGood", NULL);

	test_tcp_ao_counters_cmp(NULL, &ao1, &ao2, TEST_CNT_GOOD);

	if (after_good <= before_good) {
		test_fail("TCPAOGood counter did not increase: %zu <= %zu",
			  after_good, before_good);
	} else {
		test_ok("TCPAOGood counter increased %zu => %zu",
			before_good, after_good);
	}
	after_bad = netstat_get_one("TCPAOBad", NULL);
	if (after_bad)
		test_fail("TCPAOBad counter is non-zero: %zu", after_bad);
	else
		test_ok("TCPAOBad counter didn't increase");

	synchronize_threads(); /* 6: verified => closed */
	close(sk);

	synchronize_threads(); /* don't race to exit: let server exit() */
	return NULL;
}

int main(int argc, char *argv[])
{
	test_init(7, server_fn, client_fn);
	return 0;
}
