File Index
Files and directories
Sign in
FILE

aolib.h

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/net/tcp_ao/lib/aolib.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2/*
  3 * TCP-AO selftest library. Provides helpers to unshare network
  4 * namespaces, create veth, assign ip addresses, set routes,
  5 * manipulate socket options, read network counter and etc.
  6 * Author: Dmitry Safonov <dima@arista.com>
  7 */
  8#ifndef _AOLIB_H_
  9#define _AOLIB_H_
 10
 11#include <arpa/inet.h>
 12#include <errno.h>
 13#include <linux/snmp.h>
 14#include <linux/tcp.h>
 15#include <netinet/in.h>
 16#include <stdarg.h>
 17#include <stdbool.h>
 18#include <stdlib.h>
 19#include <stdio.h>
 20#include <string.h>
 21#include <sys/syscall.h>
 22#include <unistd.h>
 23
 24#include "../../../../../include/linux/stringify.h"
 25#include "../../../../../include/linux/bits.h"
 26
 27#ifndef SOL_TCP
 28/* can't include <netinet/tcp.h> as including <linux/tcp.h> */
 29# define SOL_TCP		6	/* TCP level */
 30#endif
 31
 32/* Working around ksft, see the comment in lib/setup.c */
 33extern void __test_msg(const char *buf);
 34extern void __test_ok(const char *buf);
 35extern void __test_fail(const char *buf);
 36extern void __test_xfail(const char *buf);
 37extern void __test_error(const char *buf);
 38extern void __test_skip(const char *buf);
 39
 40static inline char *test_snprintf(const char *fmt, va_list vargs)
 41{
 42	char *ret = NULL;
 43	size_t size = 0;
 44	va_list tmp;
 45	int n = 0;
 46
 47	va_copy(tmp, vargs);
 48	n = vsnprintf(ret, size, fmt, tmp);
 49	va_end(tmp);
 50	if (n < 0)
 51		return NULL;
 52
 53	size = n + 1;
 54	ret = malloc(size);
 55	if (!ret)
 56		return NULL;
 57
 58	n = vsnprintf(ret, size, fmt, vargs);
 59	if (n < 0 || n > size - 1) {
 60		free(ret);
 61		return NULL;
 62	}
 63	return ret;
 64}
 65
 66static __printf(1, 2) inline char *test_sprintf(const char *fmt, ...)
 67{
 68	va_list vargs;
 69	char *ret;
 70
 71	va_start(vargs, fmt);
 72	ret = test_snprintf(fmt, vargs);
 73	va_end(vargs);
 74
 75	return ret;
 76}
 77
 78static __printf(2, 3) inline void __test_print(void (*fn)(const char *),
 79					       const char *fmt, ...)
 80{
 81	va_list vargs;
 82	char *msg;
 83
 84	va_start(vargs, fmt);
 85	msg = test_snprintf(fmt, vargs);
 86	va_end(vargs);
 87
 88	if (!msg)
 89		return;
 90
 91	fn(msg);
 92	free(msg);
 93}
 94
 95#define test_print(fmt, ...)						\
 96	__test_print(__test_msg, "%ld[%s:%u] " fmt "\n",		\
 97		     syscall(SYS_gettid),				\
 98		     __FILE__, __LINE__, ##__VA_ARGS__)
 99
100#define test_ok(fmt, ...)						\
101	__test_print(__test_ok, fmt "\n", ##__VA_ARGS__)
102#define test_skip(fmt, ...)						\
103	__test_print(__test_skip, fmt "\n", ##__VA_ARGS__)
104#define test_xfail(fmt, ...)						\
105	__test_print(__test_xfail, fmt "\n", ##__VA_ARGS__)
106
107#define test_fail(fmt, ...)						\
108do {									\
109	if (errno)							\
110		__test_print(__test_fail, fmt ": %m\n", ##__VA_ARGS__);	\
111	else								\
112		__test_print(__test_fail, fmt "\n", ##__VA_ARGS__);	\
113	test_failed();							\
114} while (0)
115
116#define KSFT_FAIL  1
117#define test_error(fmt, ...)						\
118do {									\
119	if (errno)							\
120		__test_print(__test_error, "%ld[%s:%u] " fmt ": %m\n",	\
121			     syscall(SYS_gettid), __FILE__, __LINE__,	\
122			     ##__VA_ARGS__);				\
123	else								\
124		__test_print(__test_error, "%ld[%s:%u] " fmt "\n",	\
125			     syscall(SYS_gettid), __FILE__, __LINE__,	\
126			     ##__VA_ARGS__);				\
127	exit(KSFT_FAIL);						\
128} while (0)
129
130enum test_fault {
131	FAULT_TIMEOUT = 1,
132	FAULT_KEYREJECT,
133	FAULT_PREINSTALL_AO,
134	FAULT_PREINSTALL_MD5,
135	FAULT_POSTINSTALL,
136	FAULT_BUSY,
137	FAULT_CURRNEXT,
138	FAULT_FIXME,
139};
140typedef enum test_fault fault_t;
141
142enum test_needs_kconfig {
143	KCONFIG_NET_NS = 0,		/* required */
144	KCONFIG_VETH,			/* required */
145	KCONFIG_TCP_AO,			/* required */
146	KCONFIG_TCP_MD5,		/* optional, for TCP-MD5 features */
147	KCONFIG_NET_VRF,		/* optional, for L3/VRF testing */
148	KCONFIG_FTRACE,			/* optional, for tracepoints checks */
149	__KCONFIG_LAST__
150};
151extern bool kernel_config_has(enum test_needs_kconfig k);
152extern const char *tests_skip_reason[__KCONFIG_LAST__];
153static inline bool should_skip_test(const char *tst_name,
154				    enum test_needs_kconfig k)
155{
156	if (kernel_config_has(k))
157		return false;
158	test_skip("%s: %s", tst_name, tests_skip_reason[k]);
159	return true;
160}
161
162union tcp_addr {
163	struct in_addr a4;
164	struct in6_addr a6;
165};
166
167typedef void *(*thread_fn)(void *);
168extern void test_failed(void);
169extern void __test_init(unsigned int ntests, int family, unsigned int prefix,
170			union tcp_addr addr1, union tcp_addr addr2,
171			thread_fn peer1, thread_fn peer2);
172
173static inline void test_init2(unsigned int ntests,
174			      thread_fn peer1, thread_fn peer2,
175			      int family, unsigned int prefix,
176			      const char *addr1, const char *addr2)
177{
178	union tcp_addr taddr1, taddr2;
179
180	if (inet_pton(family, addr1, &taddr1) != 1)
181		test_error("Can't convert ip address %s", addr1);
182	if (inet_pton(family, addr2, &taddr2) != 1)
183		test_error("Can't convert ip address %s", addr2);
184
185	__test_init(ntests, family, prefix, taddr1, taddr2, peer1, peer2);
186}
187extern void test_add_destructor(void (*d)(void));
188extern void test_init_ftrace(int nsfd1, int nsfd2);
189extern int test_setup_tracing(void);
190
191/* To adjust optmem socket limit, approximately estimate a number,
192 * that is bigger than sizeof(struct tcp_ao_key).
193 */
194#define KERNEL_TCP_AO_KEY_SZ_ROUND_UP	300
195
196extern void test_set_optmem(size_t value);
197extern size_t test_get_optmem(void);
198
199extern const struct sockaddr_in6 addr_any6;
200extern const struct sockaddr_in addr_any4;
201
202#ifdef IPV6_TEST
203# define __TEST_CLIENT_IP(n)	("2001:db8:" __stringify(n) "::1")
204# define TEST_CLIENT_IP	__TEST_CLIENT_IP(1)
205# define TEST_WRONG_IP	"2001:db8:253::1"
206# define TEST_SERVER_IP	"2001:db8:254::1"
207# define TEST_NETWORK	"2001::"
208# define TEST_PREFIX	128
209# define TEST_FAMILY	AF_INET6
210# define SOCKADDR_ANY	addr_any6
211# define sockaddr_af	struct sockaddr_in6
212#else
213# define __TEST_CLIENT_IP(n)	("10.0." __stringify(n) ".1")
214# define TEST_CLIENT_IP	__TEST_CLIENT_IP(1)
215# define TEST_WRONG_IP	"10.0.253.1"
216# define TEST_SERVER_IP	"10.0.254.1"
217# define TEST_NETWORK	"10.0.0.0"
218# define TEST_PREFIX	32
219# define TEST_FAMILY	AF_INET
220# define SOCKADDR_ANY	addr_any4
221# define sockaddr_af	struct sockaddr_in
222#endif
223
224static inline union tcp_addr gen_tcp_addr(union tcp_addr net, size_t n)
225{
226	union tcp_addr ret = net;
227
228#ifdef IPV6_TEST
229	ret.a6.s6_addr32[3] = htonl(n & (BIT(32) - 1));
230	ret.a6.s6_addr32[2] = htonl((n >> 32) & (BIT(32) - 1));
231#else
232	ret.a4.s_addr = htonl(ntohl(net.a4.s_addr) + n);
233#endif
234
235	return ret;
236}
237
238static inline void tcp_addr_to_sockaddr_in(void *dest,
239					   const union tcp_addr *src,
240					   unsigned int port)
241{
242	sockaddr_af *out = dest;
243
244	memset(out, 0, sizeof(*out));
245#ifdef IPV6_TEST
246	out->sin6_family = AF_INET6;
247	out->sin6_port   = port;
248	out->sin6_addr   = src->a6;
249#else
250	out->sin_family  = AF_INET;
251	out->sin_port    = port;
252	out->sin_addr    = src->a4;
253#endif
254}
255
256static inline void test_init(unsigned int ntests,
257			     thread_fn peer1, thread_fn peer2)
258{
259	test_init2(ntests, peer1, peer2, TEST_FAMILY, TEST_PREFIX,
260			TEST_SERVER_IP, TEST_CLIENT_IP);
261}
262extern void synchronize_threads(void);
263extern void switch_ns(int fd);
264extern int switch_save_ns(int fd);
265extern void switch_close_ns(int fd);
266
267extern __thread union tcp_addr this_ip_addr;
268extern __thread union tcp_addr this_ip_dest;
269extern int test_family;
270
271extern void randomize_buffer(void *buf, size_t buflen);
272extern __printf(3, 4) int test_echo(const char *fname, bool append,
273				    const char *fmt, ...);
274
275extern int open_netns(void);
276extern int unshare_open_netns(void);
277extern const char veth_name[];
278extern int add_veth(const char *name, int nsfda, int nsfdb);
279extern int add_vrf(const char *name, uint32_t tabid, int ifindex, int nsfd);
280extern int ip_addr_add(const char *intf, int family,
281		       union tcp_addr addr, uint8_t prefix);
282extern int ip_route_add(const char *intf, int family,
283			union tcp_addr src, union tcp_addr dst);
284extern int ip_route_add_vrf(const char *intf, int family,
285			    union tcp_addr src, union tcp_addr dst,
286			    uint8_t vrf);
287extern int link_set_up(const char *intf);
288
289extern const unsigned int test_server_port;
290extern int test_wait_fd(int sk, time_t sec, bool write);
291extern int __test_connect_socket(int sk, const char *device,
292				 void *addr, size_t addr_sz, bool async);
293extern int __test_listen_socket(int backlog, void *addr, size_t addr_sz);
294
295static inline int test_listen_socket(const union tcp_addr taddr,
296				     unsigned int port, int backlog)
297{
298	sockaddr_af addr;
299
300	tcp_addr_to_sockaddr_in(&addr, &taddr, htons(port));
301	return __test_listen_socket(backlog, (void *)&addr, sizeof(addr));
302}
303
304/*
305 * In order for selftests to work under CONFIG_CRYPTO_FIPS=y,
306 * the password should be loger than 14 bytes, see hmac_setkey()
307 */
308#define TEST_TCP_AO_MINKEYLEN	14
309#define DEFAULT_TEST_PASSWORD	"In this hour, I do not believe that any darkness will endure."
310
311#ifndef DEFAULT_TEST_ALGO
312#define DEFAULT_TEST_ALGO	"cmac(aes128)"
313#endif
314
315#ifdef IPV6_TEST
316#define DEFAULT_TEST_PREFIX	128
317#else
318#define DEFAULT_TEST_PREFIX	32
319#endif
320
321/*
322 * Timeout on syscalls where failure is not expected.
323 * You may want to rise it if the test machine is very busy.
324 */
325#ifndef TEST_TIMEOUT_SEC
326#define TEST_TIMEOUT_SEC	5
327#endif
328
329/*
330 * Timeout on connect() where a failure is expected.
331 * If set to 0 - kernel will try to retransmit SYN number of times, set in
332 * /proc/sys/net/ipv4/tcp_syn_retries
333 * By default set to 1 to make tests pass faster on non-busy machine.
334 * [in process of removal, don't use in new tests]
335 */
336#ifndef TEST_RETRANSMIT_SEC
337#define TEST_RETRANSMIT_SEC	1
338#endif
339
340static inline int _test_connect_socket(int sk, const union tcp_addr taddr,
341				       unsigned int port, bool async)
342{
343	sockaddr_af addr;
344
345	tcp_addr_to_sockaddr_in(&addr, &taddr, htons(port));
346	return __test_connect_socket(sk, veth_name,
347				     (void *)&addr, sizeof(addr), async);
348}
349
350static inline int test_connect_socket(int sk, const union tcp_addr taddr,
351				      unsigned int port)
352{
353	return _test_connect_socket(sk, taddr, port, false);
354}
355
356extern int __test_set_md5(int sk, void *addr, size_t addr_sz,
357			  uint8_t prefix, int vrf, const char *password);
358static inline int test_set_md5(int sk, const union tcp_addr in_addr,
359			       uint8_t prefix, int vrf, const char *password)
360{
361	sockaddr_af addr;
362
363	if (prefix > DEFAULT_TEST_PREFIX)
364		prefix = DEFAULT_TEST_PREFIX;
365
366	tcp_addr_to_sockaddr_in(&addr, &in_addr, 0);
367	return __test_set_md5(sk, (void *)&addr, sizeof(addr),
368			prefix, vrf, password);
369}
370
371extern int test_prepare_key_sockaddr(struct tcp_ao_add *ao, const char *alg,
372		void *addr, size_t addr_sz, bool set_current, bool set_rnext,
373		uint8_t prefix, uint8_t vrf,
374		uint8_t sndid, uint8_t rcvid, uint8_t maclen,
375		uint8_t keyflags, uint8_t keylen, const char *key);
376
377static inline int test_prepare_key(struct tcp_ao_add *ao,
378		const char *alg, union tcp_addr taddr,
379		bool set_current, bool set_rnext,
380		uint8_t prefix, uint8_t vrf,
381		uint8_t sndid, uint8_t rcvid, uint8_t maclen,
382		uint8_t keyflags, uint8_t keylen, const char *key)
383{
384	sockaddr_af addr;
385
386	tcp_addr_to_sockaddr_in(&addr, &taddr, 0);
387	return test_prepare_key_sockaddr(ao, alg, (void *)&addr, sizeof(addr),
388			set_current, set_rnext, prefix, vrf, sndid, rcvid,
389			maclen, keyflags, keylen, key);
390}
391
392static inline int test_prepare_def_key(struct tcp_ao_add *ao,
393		const char *key, uint8_t keyflags,
394		union tcp_addr in_addr, uint8_t prefix, uint8_t vrf,
395		uint8_t sndid, uint8_t rcvid)
396{
397	if (prefix > DEFAULT_TEST_PREFIX)
398		prefix = DEFAULT_TEST_PREFIX;
399
400	return test_prepare_key(ao, DEFAULT_TEST_ALGO, in_addr, false, false,
401				prefix, vrf, sndid, rcvid, 0, keyflags,
402				strlen(key), key);
403}
404
405extern int test_get_one_ao(int sk, struct tcp_ao_getsockopt *out,
406			   void *addr, size_t addr_sz,
407			   uint8_t prefix, uint8_t sndid, uint8_t rcvid);
408extern int test_get_ao_info(int sk, struct tcp_ao_info_opt *out);
409extern int test_set_ao_info(int sk, struct tcp_ao_info_opt *in);
410extern int test_cmp_getsockopt_setsockopt(const struct tcp_ao_add *a,
411					  const struct tcp_ao_getsockopt *b);
412extern int test_cmp_getsockopt_setsockopt_ao(const struct tcp_ao_info_opt *a,
413					     const struct tcp_ao_info_opt *b);
414
415static inline int test_verify_socket_key(int sk, struct tcp_ao_add *key)
416{
417	struct tcp_ao_getsockopt key2 = {};
418	int err;
419
420	err = test_get_one_ao(sk, &key2, &key->addr, sizeof(key->addr),
421			      key->prefix, key->sndid, key->rcvid);
422	if (err)
423		return err;
424
425	return test_cmp_getsockopt_setsockopt(key, &key2);
426}
427
428static inline int test_add_key_vrf(int sk,
429				   const char *key, uint8_t keyflags,
430				   union tcp_addr in_addr, uint8_t prefix,
431				   uint8_t vrf, uint8_t sndid, uint8_t rcvid)
432{
433	struct tcp_ao_add tmp = {};
434	int err;
435
436	err = test_prepare_def_key(&tmp, key, keyflags, in_addr, prefix,
437				   vrf, sndid, rcvid);
438	if (err)
439		return err;
440
441	err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp));
442	if (err < 0)
443		return -errno;
444
445	return test_verify_socket_key(sk, &tmp);
446}
447
448static inline int test_add_key(int sk, const char *key,
449			      union tcp_addr in_addr, uint8_t prefix,
450			      uint8_t sndid, uint8_t rcvid)
451{
452	return test_add_key_vrf(sk, key, 0, in_addr, prefix, 0, sndid, rcvid);
453}
454
455static inline int test_verify_socket_ao(int sk, struct tcp_ao_info_opt *ao)
456{
457	struct tcp_ao_info_opt ao2 = {};
458	int err;
459
460	err = test_get_ao_info(sk, &ao2);
461	if (err)
462		return err;
463
464	return test_cmp_getsockopt_setsockopt_ao(ao, &ao2);
465}
466
467static inline int test_set_ao_flags(int sk, bool ao_required, bool accept_icmps)
468{
469	struct tcp_ao_info_opt ao = {};
470	int err;
471
472	err = test_get_ao_info(sk, &ao);
473	/* Maybe ao_info wasn't allocated yet */
474	if (err && err != -ENOENT)
475		return err;
476
477	ao.ao_required = !!ao_required;
478	ao.accept_icmps = !!accept_icmps;
479	err = test_set_ao_info(sk, &ao);
480	if (err)
481		return err;
482
483	return test_verify_socket_ao(sk, &ao);
484}
485
486extern ssize_t test_server_run(int sk, ssize_t quota, time_t timeout_sec);
487extern int test_client_verify(int sk, const size_t msg_len, const size_t nr);
488
489struct tcp_ao_key_counters {
490	uint8_t sndid;
491	uint8_t rcvid;
492	uint64_t pkt_good;
493	uint64_t pkt_bad;
494};
495
496struct tcp_ao_counters {
497	/* per-netns */
498	uint64_t netns_ao_good;
499	uint64_t netns_ao_bad;
500	uint64_t netns_ao_key_not_found;
501	uint64_t netns_ao_required;
502	uint64_t netns_ao_dropped_icmp;
503	/* per-socket */
504	uint64_t ao_info_pkt_good;
505	uint64_t ao_info_pkt_bad;
506	uint64_t ao_info_pkt_key_not_found;
507	uint64_t ao_info_pkt_ao_required;
508	uint64_t ao_info_pkt_dropped_icmp;
509	/* per-key */
510	size_t nr_keys;
511	struct tcp_ao_key_counters *key_cnts;
512};
513
514struct tcp_counters {
515	struct tcp_ao_counters ao;
516	uint64_t netns_md5_notfound;
517	uint64_t netns_md5_unexpected;
518	uint64_t netns_md5_failure;
519};
520
521extern int test_get_tcp_counters(int sk, struct tcp_counters *out);
522
523#define TEST_CNT_KEY_GOOD		BIT(0)
524#define TEST_CNT_KEY_BAD		BIT(1)
525#define TEST_CNT_SOCK_GOOD		BIT(2)
526#define TEST_CNT_SOCK_BAD		BIT(3)
527#define TEST_CNT_SOCK_KEY_NOT_FOUND	BIT(4)
528#define TEST_CNT_SOCK_AO_REQUIRED	BIT(5)
529#define TEST_CNT_SOCK_DROPPED_ICMP	BIT(6)
530#define TEST_CNT_NS_GOOD		BIT(7)
531#define TEST_CNT_NS_BAD			BIT(8)
532#define TEST_CNT_NS_KEY_NOT_FOUND	BIT(9)
533#define TEST_CNT_NS_AO_REQUIRED		BIT(10)
534#define TEST_CNT_NS_DROPPED_ICMP	BIT(11)
535#define TEST_CNT_NS_MD5_NOT_FOUND	BIT(12)
536#define TEST_CNT_NS_MD5_UNEXPECTED	BIT(13)
537#define TEST_CNT_NS_MD5_FAILURE		BIT(14)
538typedef uint16_t test_cnt;
539
540#define _for_each_counter(f)						\
541do {									\
542	/* per-netns */							\
543	f(ao.netns_ao_good,		TEST_CNT_NS_GOOD);		\
544	f(ao.netns_ao_bad,		TEST_CNT_NS_BAD);		\
545	f(ao.netns_ao_key_not_found,	TEST_CNT_NS_KEY_NOT_FOUND);	\
546	f(ao.netns_ao_required,		TEST_CNT_NS_AO_REQUIRED);	\
547	f(ao.netns_ao_dropped_icmp,	TEST_CNT_NS_DROPPED_ICMP);	\
548	/* per-socket */						\
549	f(ao.ao_info_pkt_good,		TEST_CNT_SOCK_GOOD);		\
550	f(ao.ao_info_pkt_bad,		TEST_CNT_SOCK_BAD);		\
551	f(ao.ao_info_pkt_key_not_found,	TEST_CNT_SOCK_KEY_NOT_FOUND);	\
552	f(ao.ao_info_pkt_ao_required,	TEST_CNT_SOCK_AO_REQUIRED);	\
553	f(ao.ao_info_pkt_dropped_icmp,	TEST_CNT_SOCK_DROPPED_ICMP);	\
554	/* non-AO */							\
555	f(netns_md5_notfound,		TEST_CNT_NS_MD5_NOT_FOUND);	\
556	f(netns_md5_unexpected,		TEST_CNT_NS_MD5_UNEXPECTED);	\
557	f(netns_md5_failure,		TEST_CNT_NS_MD5_FAILURE);	\
558} while (0)
559
560#define TEST_CNT_AO_GOOD		(TEST_CNT_SOCK_GOOD | TEST_CNT_NS_GOOD)
561#define TEST_CNT_AO_BAD			(TEST_CNT_SOCK_BAD | TEST_CNT_NS_BAD)
562#define TEST_CNT_AO_KEY_NOT_FOUND	(TEST_CNT_SOCK_KEY_NOT_FOUND | \
563					 TEST_CNT_NS_KEY_NOT_FOUND)
564#define TEST_CNT_AO_REQUIRED		(TEST_CNT_SOCK_AO_REQUIRED | \
565					 TEST_CNT_NS_AO_REQUIRED)
566#define TEST_CNT_AO_DROPPED_ICMP	(TEST_CNT_SOCK_DROPPED_ICMP | \
567					 TEST_CNT_NS_DROPPED_ICMP)
568#define TEST_CNT_GOOD			(TEST_CNT_KEY_GOOD | TEST_CNT_AO_GOOD)
569#define TEST_CNT_BAD			(TEST_CNT_KEY_BAD | TEST_CNT_AO_BAD)
570
571extern test_cnt test_cmp_counters(struct tcp_counters *before,
572				  struct tcp_counters *after);
573extern int test_assert_counters_sk(const char *tst_name,
574		struct tcp_counters *before, struct tcp_counters *after,
575		test_cnt expected);
576extern int test_assert_counters_key(const char *tst_name,
577		struct tcp_ao_counters *before, struct tcp_ao_counters *after,
578		test_cnt expected, int sndid, int rcvid);
579extern void test_tcp_counters_free(struct tcp_counters *cnts);
580
581/*
582 * Polling for netns and socket counters during select()/connect() and also
583 * client/server messaging. Instead of constant timeout on underlying select(),
584 * check the counters and return early. This allows to pass the tests where
585 * timeout is expected without waiting for that fixing timeout (tests speed-up).
586 * Previously shorter timeouts were used for tests expecting to time out,
587 * but that leaded to sporadic false positives on counter checks failures,
588 * as one second timeouts aren't enough for TCP retransmit.
589 *
590 * Two sides of the socketpair (client/server) should synchronize failures
591 * using a shared variable *err, so that they can detect the other side's
592 * failure.
593 */
594extern int test_skpair_wait_poll(int sk, bool write, test_cnt cond,
595				 volatile int *err);
596extern int _test_skpair_connect_poll(int sk, const char *device,
597				     void *addr, size_t addr_sz,
598				     test_cnt cond, volatile int *err);
599static inline int test_skpair_connect_poll(int sk, const union tcp_addr taddr,
600					   unsigned int port,
601					   test_cnt cond, volatile int *err)
602{
603	sockaddr_af addr;
604
605	tcp_addr_to_sockaddr_in(&addr, &taddr, htons(port));
606	return _test_skpair_connect_poll(sk, veth_name,
607					 (void *)&addr, sizeof(addr), cond, err);
608}
609
610extern int test_skpair_client(int sk, const size_t msg_len, const size_t nr,
611			      test_cnt cond, volatile int *err);
612extern int test_skpair_server(int sk, ssize_t quota,
613			      test_cnt cond, volatile int *err);
614
615/*
616 * Frees buffers allocated in test_get_tcp_counters().
617 * The function doesn't expect new keys or keys removed between calls
618 * to test_get_tcp_counters(). Check key counters manually if they
619 * may change.
620 */
621static inline int test_assert_counters(const char *tst_name,
622				       struct tcp_counters *before,
623				       struct tcp_counters *after,
624				       test_cnt expected)
625{
626	int ret;
627
628	ret = test_assert_counters_sk(tst_name, before, after, expected);
629	if (ret)
630		goto out;
631	ret = test_assert_counters_key(tst_name, &before->ao, &after->ao,
632				       expected, -1, -1);
633out:
634	test_tcp_counters_free(before);
635	test_tcp_counters_free(after);
636	return ret;
637}
638
639struct netstat;
640extern struct netstat *netstat_read(void);
641extern void netstat_free(struct netstat *ns);
642extern void netstat_print_diff(struct netstat *nsa, struct netstat *nsb);
643extern uint64_t netstat_get(struct netstat *ns,
644			    const char *name, bool *not_found);
645
646static inline uint64_t netstat_get_one(const char *name, bool *not_found)
647{
648	struct netstat *ns = netstat_read();
649	uint64_t ret;
650
651	ret = netstat_get(ns, name, not_found);
652
653	netstat_free(ns);
654	return ret;
655}
656
657struct tcp_sock_queue {
658	uint32_t seq;
659	void *buf;
660};
661
662struct tcp_sock_state {
663	struct tcp_info info;
664	struct tcp_repair_window trw;
665	struct tcp_sock_queue out;
666	int outq_len;		/* output queue size (not sent + not acked) */
667	int outq_nsd_len;	/* output queue size (not sent only) */
668	struct tcp_sock_queue in;
669	int inq_len;
670	int mss;
671	int timestamp;
672};
673
674extern void __test_sock_checkpoint(int sk, struct tcp_sock_state *state,
675				   void *addr, size_t addr_size);
676static inline void test_sock_checkpoint(int sk, struct tcp_sock_state *state,
677					sockaddr_af *saddr)
678{
679	__test_sock_checkpoint(sk, state, saddr, sizeof(*saddr));
680}
681extern void test_ao_checkpoint(int sk, struct tcp_ao_repair *state);
682extern void __test_sock_restore(int sk, const char *device,
683				struct tcp_sock_state *state,
684				void *saddr, void *daddr, size_t addr_size);
685static inline void test_sock_restore(int sk, struct tcp_sock_state *state,
686				     sockaddr_af *saddr,
687				     const union tcp_addr daddr,
688				     unsigned int dport)
689{
690	sockaddr_af addr;
691
692	tcp_addr_to_sockaddr_in(&addr, &daddr, htons(dport));
693	__test_sock_restore(sk, veth_name, state, saddr, &addr, sizeof(addr));
694}
695extern void test_ao_restore(int sk, struct tcp_ao_repair *state);
696extern void test_sock_state_free(struct tcp_sock_state *state);
697extern void test_enable_repair(int sk);
698extern void test_disable_repair(int sk);
699extern void test_kill_sk(int sk);
700static inline int test_add_repaired_key(int sk,
701					const char *key, uint8_t keyflags,
702					union tcp_addr in_addr, uint8_t prefix,
703					uint8_t sndid, uint8_t rcvid)
704{
705	struct tcp_ao_add tmp = {};
706	int err;
707
708	err = test_prepare_def_key(&tmp, key, keyflags, in_addr, prefix,
709				   0, sndid, rcvid);
710	if (err)
711		return err;
712
713	tmp.set_current = 1;
714	tmp.set_rnext = 1;
715	if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp)) < 0)
716		return -errno;
717
718	return test_verify_socket_key(sk, &tmp);
719}
720
721#define DEFAULT_FTRACE_BUFFER_KB	10000
722#define DEFAULT_TRACER_LINES_ARR	200
723struct test_ftracer;
724extern uint64_t ns_cookie1, ns_cookie2;
725
726enum ftracer_op {
727	FTRACER_LINE_DISCARD = 0,
728	FTRACER_LINE_PRESERVE,
729	FTRACER_EXIT,
730};
731
732extern struct test_ftracer *create_ftracer(const char *name,
733		enum ftracer_op (*process_line)(const char *line),
734		void (*destructor)(struct test_ftracer *tracer),
735		bool (*expecting_more)(void),
736		size_t lines_buf_sz, size_t buffer_size_kb);
737extern int setup_trace_event(struct test_ftracer *tracer,
738			     const char *event, const char *filter);
739extern void destroy_ftracer(struct test_ftracer *tracer);
740extern const size_t tracer_get_savedlines_nr(struct test_ftracer *tracer);
741extern const char **tracer_get_savedlines(struct test_ftracer *tracer);
742
743enum trace_events {
744	/* TCP_HASH_EVENT */
745	TCP_HASH_BAD_HEADER = 0,
746	TCP_HASH_MD5_REQUIRED,
747	TCP_HASH_MD5_UNEXPECTED,
748	TCP_HASH_MD5_MISMATCH,
749	TCP_HASH_AO_REQUIRED,
750	/* TCP_AO_EVENT */
751	TCP_AO_HANDSHAKE_FAILURE,
752	TCP_AO_WRONG_MACLEN,
753	TCP_AO_MISMATCH,
754	TCP_AO_KEY_NOT_FOUND,
755	TCP_AO_RNEXT_REQUEST,
756	/* TCP_AO_EVENT_SK */
757	TCP_AO_SYNACK_NO_KEY,
758	/* TCP_AO_EVENT_SNE */
759	TCP_AO_SND_SNE_UPDATE,
760	TCP_AO_RCV_SNE_UPDATE,
761	__MAX_TRACE_EVENTS
762};
763
764extern int __trace_event_expect(enum trace_events type, int family,
765				union tcp_addr src, union tcp_addr dst,
766				int src_port, int dst_port, int L3index,
767				int fin, int syn, int rst, int psh, int ack,
768				int keyid, int rnext, int maclen, int sne);
769
770static inline void trace_hash_event_expect(enum trace_events type,
771				union tcp_addr src, union tcp_addr dst,
772				int src_port, int dst_port, int L3index,
773				int fin, int syn, int rst, int psh, int ack)
774{
775	int err;
776
777	err = __trace_event_expect(type, TEST_FAMILY, src, dst,
778				   src_port, dst_port, L3index,
779				   fin, syn, rst, psh, ack,
780				   -1, -1, -1, -1);
781	if (err)
782		test_error("Couldn't add a trace event: %d", err);
783}
784
785static inline void trace_ao_event_expect(enum trace_events type,
786				union tcp_addr src, union tcp_addr dst,
787				int src_port, int dst_port, int L3index,
788				int fin, int syn, int rst, int psh, int ack,
789				int keyid, int rnext, int maclen)
790{
791	int err;
792
793	err = __trace_event_expect(type, TEST_FAMILY, src, dst,
794				   src_port, dst_port, L3index,
795				   fin, syn, rst, psh, ack,
796				   keyid, rnext, maclen, -1);
797	if (err)
798		test_error("Couldn't add a trace event: %d", err);
799}
800
801static inline void trace_ao_event_sk_expect(enum trace_events type,
802				union tcp_addr src, union tcp_addr dst,
803				int src_port, int dst_port,
804				int keyid, int rnext)
805{
806	int err;
807
808	err = __trace_event_expect(type, TEST_FAMILY, src, dst,
809				   src_port, dst_port, -1,
810				   -1, -1, -1, -1, -1,
811				   keyid, rnext, -1, -1);
812	if (err)
813		test_error("Couldn't add a trace event: %d", err);
814}
815
816static inline void trace_ao_event_sne_expect(enum trace_events type,
817				union tcp_addr src, union tcp_addr dst,
818				int src_port, int dst_port, int sne)
819{
820	int err;
821
822	err = __trace_event_expect(type, TEST_FAMILY, src, dst,
823				   src_port, dst_port, -1,
824				   -1, -1, -1, -1, -1,
825				   -1, -1, -1, sne);
826	if (err)
827		test_error("Couldn't add a trace event: %d", err);
828}
829
830extern int setup_aolib_ftracer(void);
831
832#endif /* _AOLIB_H_ */
~/ Read-only file preview.