brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · 8901a67 Raw
256 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Check that after SEQ number wrap-around:3 * 1. SEQ-extension has upper bytes set4 * 2. TCP conneciton is alive and no TCPAOBad segments5 * In order to test (2), the test doesn't just adjust seq number for a queue6 * on a connected socket, but migrates it to another sk+port number, so7 * that there won't be any delayed packets that will fail to verify8 * with the new SEQ numbers.9 */10#include <inttypes.h>11#include "aolib.h"12 13const unsigned int nr_packets = 1000;14const unsigned int msg_len = 1000;15const unsigned int quota = nr_packets * msg_len;16unsigned int client_new_port;17 18/* Move them closer to roll-over */19static void test_adjust_seqs(struct tcp_sock_state *img,20			     struct tcp_ao_repair *ao_img,21			     bool server)22{23	uint32_t new_seq1, new_seq2;24 25	/* make them roll-over during quota, but on different segments */26	if (server) {27		new_seq1 = ((uint32_t)-1) - msg_len;28		new_seq2 = ((uint32_t)-1) - (quota - 2 * msg_len);29	} else {30		new_seq1 = ((uint32_t)-1) - (quota - 2 * msg_len);31		new_seq2 = ((uint32_t)-1) - msg_len;32	}33 34	img->in.seq = new_seq1;35	img->trw.snd_wl1 = img->in.seq - msg_len;36	img->out.seq = new_seq2;37	img->trw.rcv_wup = img->in.seq;38}39 40static int test_sk_restore(struct tcp_sock_state *img,41			   struct tcp_ao_repair *ao_img, sockaddr_af *saddr,42			   const union tcp_addr daddr, unsigned int dport,43			   struct tcp_ao_counters *cnt)44{45	int sk;46 47	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);48	if (sk < 0)49		test_error("socket()");50 51	test_enable_repair(sk);52	test_sock_restore(sk, img, saddr, daddr, dport);53	if (test_add_repaired_key(sk, DEFAULT_TEST_PASSWORD, 0, daddr, -1, 100, 100))54		test_error("setsockopt(TCP_AO_ADD_KEY)");55	test_ao_restore(sk, ao_img);56 57	if (test_get_tcp_ao_counters(sk, cnt))58		test_error("test_get_tcp_ao_counters()");59 60	test_disable_repair(sk);61	test_sock_state_free(img);62	return sk;63}64 65static void *server_fn(void *arg)66{67	uint64_t before_good, after_good, after_bad;68	struct tcp_ao_counters ao1, ao2;69	struct tcp_sock_state img;70	struct tcp_ao_repair ao_img;71	sockaddr_af saddr;72	ssize_t bytes;73	int sk, lsk;74 75	lsk = test_listen_socket(this_ip_addr, test_server_port, 1);76 77	if (test_add_key(lsk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))78		test_error("setsockopt(TCP_AO_ADD_KEY)");79 80	synchronize_threads(); /* 1: MKT added => connect() */81 82	if (test_wait_fd(lsk, TEST_TIMEOUT_SEC, 0))83		test_error("test_wait_fd()");84 85	sk = accept(lsk, NULL, NULL);86	if (sk < 0)87		test_error("accept()");88 89	synchronize_threads(); /* 2: accepted => send data */90	close(lsk);91 92	bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);93	if (bytes != quota) {94		if (bytes > 0)95			test_fail("server served: %zd", bytes);96		else97			test_fail("server returned: %zd", bytes);98		goto out;99	}100 101	before_good = netstat_get_one("TCPAOGood", NULL);102 103	synchronize_threads(); /* 3: restore the connection on another port */104 105	test_enable_repair(sk);106	test_sock_checkpoint(sk, &img, &saddr);107	test_ao_checkpoint(sk, &ao_img);108	test_kill_sk(sk);109#ifdef IPV6_TEST110	saddr.sin6_port = htons(ntohs(saddr.sin6_port) + 1);111#else112	saddr.sin_port = htons(ntohs(saddr.sin_port) + 1);113#endif114	test_adjust_seqs(&img, &ao_img, true);115	synchronize_threads(); /* 4: dump finished */116	sk = test_sk_restore(&img, &ao_img, &saddr, this_ip_dest,117			     client_new_port, &ao1);118 119	trace_ao_event_sne_expect(TCP_AO_SND_SNE_UPDATE, this_ip_addr,120			this_ip_dest, test_server_port + 1, client_new_port, 1);121	trace_ao_event_sne_expect(TCP_AO_SND_SNE_UPDATE, this_ip_dest,122			this_ip_addr, client_new_port, test_server_port + 1, 1);123	trace_ao_event_sne_expect(TCP_AO_RCV_SNE_UPDATE, this_ip_addr,124			this_ip_dest, test_server_port + 1, client_new_port, 1);125	trace_ao_event_sne_expect(TCP_AO_RCV_SNE_UPDATE, this_ip_dest,126			this_ip_addr, client_new_port, test_server_port + 1, 1);127	synchronize_threads(); /* 5: verify the connection during SEQ-number rollover */128	bytes = test_server_run(sk, quota, TEST_TIMEOUT_SEC);129	if (bytes != quota) {130		if (bytes > 0)131			test_fail("server served: %zd", bytes);132		else133			test_fail("server returned: %zd", bytes);134	} else {135		test_ok("server alive");136	}137 138	synchronize_threads(); /* 6: verify counters after SEQ-number rollover */139	if (test_get_tcp_ao_counters(sk, &ao2))140		test_error("test_get_tcp_ao_counters()");141	after_good = netstat_get_one("TCPAOGood", NULL);142 143	test_tcp_ao_counters_cmp(NULL, &ao1, &ao2, TEST_CNT_GOOD);144 145	if (after_good <= before_good) {146		test_fail("TCPAOGood counter did not increase: %" PRIu64 " <= %" PRIu64,147			  after_good, before_good);148	} else {149		test_ok("TCPAOGood counter increased %" PRIu64 " => %" PRIu64,150			before_good, after_good);151	}152	after_bad = netstat_get_one("TCPAOBad", NULL);153	if (after_bad)154		test_fail("TCPAOBad counter is non-zero: %" PRIu64, after_bad);155	else156		test_ok("TCPAOBad counter didn't increase");157	test_enable_repair(sk);158	test_ao_checkpoint(sk, &ao_img);159	if (ao_img.snd_sne && ao_img.rcv_sne) {160		test_ok("SEQ extension incremented: %u/%u",161			ao_img.snd_sne, ao_img.rcv_sne);162	} else {163		test_fail("SEQ extension was not incremented: %u/%u",164			  ao_img.snd_sne, ao_img.rcv_sne);165	}166 167	synchronize_threads(); /* 6: verified => closed */168out:169	close(sk);170	return NULL;171}172 173static void *client_fn(void *arg)174{175	uint64_t before_good, after_good, after_bad;176	struct tcp_ao_counters ao1, ao2;177	struct tcp_sock_state img;178	struct tcp_ao_repair ao_img;179	sockaddr_af saddr;180	int sk;181 182	sk = socket(test_family, SOCK_STREAM, IPPROTO_TCP);183	if (sk < 0)184		test_error("socket()");185 186	if (test_add_key(sk, DEFAULT_TEST_PASSWORD, this_ip_dest, -1, 100, 100))187		test_error("setsockopt(TCP_AO_ADD_KEY)");188 189	synchronize_threads(); /* 1: MKT added => connect() */190	if (test_connect_socket(sk, this_ip_dest, test_server_port) <= 0)191		test_error("failed to connect()");192 193	synchronize_threads(); /* 2: accepted => send data */194	if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC)) {195		test_fail("pre-migrate verify failed");196		return NULL;197	}198 199	before_good = netstat_get_one("TCPAOGood", NULL);200 201	synchronize_threads(); /* 3: restore the connection on another port */202	test_enable_repair(sk);203	test_sock_checkpoint(sk, &img, &saddr);204	test_ao_checkpoint(sk, &ao_img);205	test_kill_sk(sk);206#ifdef IPV6_TEST207	client_new_port = ntohs(saddr.sin6_port) + 1;208	saddr.sin6_port = htons(ntohs(saddr.sin6_port) + 1);209#else210	client_new_port = ntohs(saddr.sin_port) + 1;211	saddr.sin_port = htons(ntohs(saddr.sin_port) + 1);212#endif213	test_adjust_seqs(&img, &ao_img, false);214	synchronize_threads(); /* 4: dump finished */215	sk = test_sk_restore(&img, &ao_img, &saddr, this_ip_dest,216			     test_server_port + 1, &ao1);217 218	synchronize_threads(); /* 5: verify the connection during SEQ-number rollover */219	if (test_client_verify(sk, msg_len, nr_packets, TEST_TIMEOUT_SEC))220		test_fail("post-migrate verify failed");221	else222		test_ok("post-migrate connection alive");223 224	synchronize_threads(); /* 5: verify counters after SEQ-number rollover */225	if (test_get_tcp_ao_counters(sk, &ao2))226		test_error("test_get_tcp_ao_counters()");227	after_good = netstat_get_one("TCPAOGood", NULL);228 229	test_tcp_ao_counters_cmp(NULL, &ao1, &ao2, TEST_CNT_GOOD);230 231	if (after_good <= before_good) {232		test_fail("TCPAOGood counter did not increase: %" PRIu64 " <= %" PRIu64,233			  after_good, before_good);234	} else {235		test_ok("TCPAOGood counter increased %" PRIu64 " => %" PRIu64,236			before_good, after_good);237	}238	after_bad = netstat_get_one("TCPAOBad", NULL);239	if (after_bad)240		test_fail("TCPAOBad counter is non-zero: %" PRIu64, after_bad);241	else242		test_ok("TCPAOBad counter didn't increase");243 244	synchronize_threads(); /* 6: verified => closed */245	close(sk);246 247	synchronize_threads(); /* don't race to exit: let server exit() */248	return NULL;249}250 251int main(int argc, char *argv[])252{253	test_init(8, server_fn, client_fn);254	return 0;255}256