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 */
33 extern void __test_msg(const char *buf);
34 extern void __test_ok(const char *buf);
35 extern void __test_fail(const char *buf);
36 extern void __test_xfail(const char *buf);
37 extern void __test_error(const char *buf);
38 extern void __test_skip(const char *buf);
39
test_snprintf(const char * fmt,va_list vargs)40 static 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
test_sprintf(const char * fmt,...)66 static __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
__test_print(void (* fn)(const char *),const char * fmt,...)78 static __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, ...) \
108 do { \
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, ...) \
118 do { \
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
130 enum 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 };
140 typedef enum test_fault fault_t;
141
142 enum 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 };
151 extern bool kernel_config_has(enum test_needs_kconfig k);
152 extern const char *tests_skip_reason[__KCONFIG_LAST__];
should_skip_test(const char * tst_name,enum test_needs_kconfig k)153 static 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
162 union tcp_addr {
163 struct in_addr a4;
164 struct in6_addr a6;
165 };
166
167 typedef void *(*thread_fn)(void *);
168 extern void test_failed(void);
169 extern 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
test_init2(unsigned int ntests,thread_fn peer1,thread_fn peer2,int family,unsigned int prefix,const char * addr1,const char * addr2)173 static 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 }
187 extern void test_add_destructor(void (*d)(void));
188 extern void test_init_ftrace(int nsfd1, int nsfd2);
189 extern 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
196 extern void test_set_optmem(size_t value);
197 extern size_t test_get_optmem(void);
198
199 extern const struct sockaddr_in6 addr_any6;
200 extern 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
gen_tcp_addr(union tcp_addr net,size_t n)224 static 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
tcp_addr_to_sockaddr_in(void * dest,const union tcp_addr * src,unsigned int port)238 static 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
test_init(unsigned int ntests,thread_fn peer1,thread_fn peer2)256 static 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 }
262 extern void synchronize_threads(void);
263 extern void switch_ns(int fd);
264 extern int switch_save_ns(int fd);
265 extern void switch_close_ns(int fd);
266
267 extern __thread union tcp_addr this_ip_addr;
268 extern __thread union tcp_addr this_ip_dest;
269 extern int test_family;
270
271 extern void randomize_buffer(void *buf, size_t buflen);
272 extern __printf(3, 4) int test_echo(const char *fname, bool append,
273 const char *fmt, ...);
274
275 extern int open_netns(void);
276 extern int unshare_open_netns(void);
277 extern const char veth_name[];
278 extern int add_veth(const char *name, int nsfda, int nsfdb);
279 extern int add_vrf(const char *name, uint32_t tabid, int ifindex, int nsfd);
280 extern int ip_addr_add(const char *intf, int family,
281 union tcp_addr addr, uint8_t prefix);
282 extern int ip_route_add(const char *intf, int family,
283 union tcp_addr src, union tcp_addr dst);
284 extern int ip_route_add_vrf(const char *intf, int family,
285 union tcp_addr src, union tcp_addr dst,
286 uint8_t vrf);
287 extern int link_set_up(const char *intf);
288
289 extern const unsigned int test_server_port;
290 extern int test_wait_fd(int sk, time_t sec, bool write);
291 extern int __test_connect_socket(int sk, const char *device,
292 void *addr, size_t addr_sz, bool async);
293 extern int __test_listen_socket(int backlog, void *addr, size_t addr_sz);
294
test_listen_socket(const union tcp_addr taddr,unsigned int port,int backlog)295 static 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
_test_connect_socket(int sk,const union tcp_addr taddr,unsigned int port,bool async)340 static 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
test_connect_socket(int sk,const union tcp_addr taddr,unsigned int port)350 static 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
356 extern int __test_set_md5(int sk, void *addr, size_t addr_sz,
357 uint8_t prefix, int vrf, const char *password);
test_set_md5(int sk,const union tcp_addr in_addr,uint8_t prefix,int vrf,const char * password)358 static 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
371 extern 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
test_prepare_key(struct tcp_ao_add * ao,const char * alg,union tcp_addr taddr,bool set_current,bool set_rnext,uint8_t prefix,uint8_t vrf,uint8_t sndid,uint8_t rcvid,uint8_t maclen,uint8_t keyflags,uint8_t keylen,const char * key)377 static 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
test_prepare_def_key(struct tcp_ao_add * ao,const char * key,uint8_t keyflags,union tcp_addr in_addr,uint8_t prefix,uint8_t vrf,uint8_t sndid,uint8_t rcvid)392 static 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
405 extern 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,
408 uint8_t keyflags, int ifindex);
409 extern int test_get_ao_info(int sk, struct tcp_ao_info_opt *out);
410 extern int test_set_ao_info(int sk, struct tcp_ao_info_opt *in);
411 extern int test_cmp_getsockopt_setsockopt(const struct tcp_ao_add *a,
412 const struct tcp_ao_getsockopt *b);
413 extern int test_cmp_getsockopt_setsockopt_ao(const struct tcp_ao_info_opt *a,
414 const struct tcp_ao_info_opt *b);
415
test_verify_socket_key(int sk,struct tcp_ao_add * key)416 static inline int test_verify_socket_key(int sk, struct tcp_ao_add *key)
417 {
418 struct tcp_ao_getsockopt key2 = {};
419 int err;
420
421 err = test_get_one_ao(sk, &key2, &key->addr, sizeof(key->addr),
422 key->prefix, key->sndid, key->rcvid,
423 key->keyflags, key->ifindex);
424 if (err)
425 return err;
426
427 return test_cmp_getsockopt_setsockopt(key, &key2);
428 }
429
test_add_key_vrf(int sk,const char * key,uint8_t keyflags,union tcp_addr in_addr,uint8_t prefix,uint8_t vrf,uint8_t sndid,uint8_t rcvid)430 static inline int test_add_key_vrf(int sk,
431 const char *key, uint8_t keyflags,
432 union tcp_addr in_addr, uint8_t prefix,
433 uint8_t vrf, uint8_t sndid, uint8_t rcvid)
434 {
435 struct tcp_ao_add tmp = {};
436 int err;
437
438 err = test_prepare_def_key(&tmp, key, keyflags, in_addr, prefix,
439 vrf, sndid, rcvid);
440 if (err)
441 return err;
442
443 err = setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp));
444 if (err < 0)
445 return -errno;
446
447 return test_verify_socket_key(sk, &tmp);
448 }
449
test_add_key(int sk,const char * key,union tcp_addr in_addr,uint8_t prefix,uint8_t sndid,uint8_t rcvid)450 static inline int test_add_key(int sk, const char *key,
451 union tcp_addr in_addr, uint8_t prefix,
452 uint8_t sndid, uint8_t rcvid)
453 {
454 return test_add_key_vrf(sk, key, 0, in_addr, prefix, 0, sndid, rcvid);
455 }
456
test_verify_socket_ao(int sk,struct tcp_ao_info_opt * ao)457 static inline int test_verify_socket_ao(int sk, struct tcp_ao_info_opt *ao)
458 {
459 struct tcp_ao_info_opt ao2 = {};
460 int err;
461
462 err = test_get_ao_info(sk, &ao2);
463 if (err)
464 return err;
465
466 return test_cmp_getsockopt_setsockopt_ao(ao, &ao2);
467 }
468
test_set_ao_flags(int sk,bool ao_required,bool accept_icmps)469 static inline int test_set_ao_flags(int sk, bool ao_required, bool accept_icmps)
470 {
471 struct tcp_ao_info_opt ao = {};
472 int err;
473
474 err = test_get_ao_info(sk, &ao);
475 /* Maybe ao_info wasn't allocated yet */
476 if (err && err != -ENOENT)
477 return err;
478
479 ao.ao_required = !!ao_required;
480 ao.accept_icmps = !!accept_icmps;
481 err = test_set_ao_info(sk, &ao);
482 if (err)
483 return err;
484
485 return test_verify_socket_ao(sk, &ao);
486 }
487
488 extern ssize_t test_server_run(int sk, ssize_t quota, time_t timeout_sec);
489 extern int test_client_verify(int sk, const size_t msg_len, const size_t nr);
490
491 struct tcp_ao_key_counters {
492 uint8_t sndid;
493 uint8_t rcvid;
494 uint64_t pkt_good;
495 uint64_t pkt_bad;
496 };
497
498 struct tcp_ao_counters {
499 /* per-netns */
500 uint64_t netns_ao_good;
501 uint64_t netns_ao_bad;
502 uint64_t netns_ao_key_not_found;
503 uint64_t netns_ao_required;
504 uint64_t netns_ao_dropped_icmp;
505 /* per-socket */
506 uint64_t ao_info_pkt_good;
507 uint64_t ao_info_pkt_bad;
508 uint64_t ao_info_pkt_key_not_found;
509 uint64_t ao_info_pkt_ao_required;
510 uint64_t ao_info_pkt_dropped_icmp;
511 /* per-key */
512 size_t nr_keys;
513 struct tcp_ao_key_counters *key_cnts;
514 };
515
516 struct tcp_counters {
517 struct tcp_ao_counters ao;
518 uint64_t netns_md5_notfound;
519 uint64_t netns_md5_unexpected;
520 uint64_t netns_md5_failure;
521 };
522
523 extern int test_get_tcp_counters(int sk, struct tcp_counters *out);
524
525 #define TEST_CNT_KEY_GOOD BIT(0)
526 #define TEST_CNT_KEY_BAD BIT(1)
527 #define TEST_CNT_SOCK_GOOD BIT(2)
528 #define TEST_CNT_SOCK_BAD BIT(3)
529 #define TEST_CNT_SOCK_KEY_NOT_FOUND BIT(4)
530 #define TEST_CNT_SOCK_AO_REQUIRED BIT(5)
531 #define TEST_CNT_SOCK_DROPPED_ICMP BIT(6)
532 #define TEST_CNT_NS_GOOD BIT(7)
533 #define TEST_CNT_NS_BAD BIT(8)
534 #define TEST_CNT_NS_KEY_NOT_FOUND BIT(9)
535 #define TEST_CNT_NS_AO_REQUIRED BIT(10)
536 #define TEST_CNT_NS_DROPPED_ICMP BIT(11)
537 #define TEST_CNT_NS_MD5_NOT_FOUND BIT(12)
538 #define TEST_CNT_NS_MD5_UNEXPECTED BIT(13)
539 #define TEST_CNT_NS_MD5_FAILURE BIT(14)
540 typedef uint16_t test_cnt;
541
542 #define _for_each_counter(f) \
543 do { \
544 /* per-netns */ \
545 f(ao.netns_ao_good, TEST_CNT_NS_GOOD); \
546 f(ao.netns_ao_bad, TEST_CNT_NS_BAD); \
547 f(ao.netns_ao_key_not_found, TEST_CNT_NS_KEY_NOT_FOUND); \
548 f(ao.netns_ao_required, TEST_CNT_NS_AO_REQUIRED); \
549 f(ao.netns_ao_dropped_icmp, TEST_CNT_NS_DROPPED_ICMP); \
550 /* per-socket */ \
551 f(ao.ao_info_pkt_good, TEST_CNT_SOCK_GOOD); \
552 f(ao.ao_info_pkt_bad, TEST_CNT_SOCK_BAD); \
553 f(ao.ao_info_pkt_key_not_found, TEST_CNT_SOCK_KEY_NOT_FOUND); \
554 f(ao.ao_info_pkt_ao_required, TEST_CNT_SOCK_AO_REQUIRED); \
555 f(ao.ao_info_pkt_dropped_icmp, TEST_CNT_SOCK_DROPPED_ICMP); \
556 /* non-AO */ \
557 f(netns_md5_notfound, TEST_CNT_NS_MD5_NOT_FOUND); \
558 f(netns_md5_unexpected, TEST_CNT_NS_MD5_UNEXPECTED); \
559 f(netns_md5_failure, TEST_CNT_NS_MD5_FAILURE); \
560 } while (0)
561
562 #define TEST_CNT_AO_GOOD (TEST_CNT_SOCK_GOOD | TEST_CNT_NS_GOOD)
563 #define TEST_CNT_AO_BAD (TEST_CNT_SOCK_BAD | TEST_CNT_NS_BAD)
564 #define TEST_CNT_AO_KEY_NOT_FOUND (TEST_CNT_SOCK_KEY_NOT_FOUND | \
565 TEST_CNT_NS_KEY_NOT_FOUND)
566 #define TEST_CNT_AO_REQUIRED (TEST_CNT_SOCK_AO_REQUIRED | \
567 TEST_CNT_NS_AO_REQUIRED)
568 #define TEST_CNT_AO_DROPPED_ICMP (TEST_CNT_SOCK_DROPPED_ICMP | \
569 TEST_CNT_NS_DROPPED_ICMP)
570 #define TEST_CNT_GOOD (TEST_CNT_KEY_GOOD | TEST_CNT_AO_GOOD)
571 #define TEST_CNT_BAD (TEST_CNT_KEY_BAD | TEST_CNT_AO_BAD)
572
573 extern test_cnt test_cmp_counters(struct tcp_counters *before,
574 struct tcp_counters *after);
575 extern int test_assert_counters_sk(const char *tst_name,
576 struct tcp_counters *before, struct tcp_counters *after,
577 test_cnt expected);
578 extern int test_assert_counters_key(const char *tst_name,
579 struct tcp_ao_counters *before, struct tcp_ao_counters *after,
580 test_cnt expected, int sndid, int rcvid);
581 extern void test_tcp_counters_free(struct tcp_counters *cnts);
582
583 /*
584 * Polling for netns and socket counters during select()/connect() and also
585 * client/server messaging. Instead of constant timeout on underlying select(),
586 * check the counters and return early. This allows to pass the tests where
587 * timeout is expected without waiting for that fixing timeout (tests speed-up).
588 * Previously shorter timeouts were used for tests expecting to time out,
589 * but that leaded to sporadic false positives on counter checks failures,
590 * as one second timeouts aren't enough for TCP retransmit.
591 *
592 * Two sides of the socketpair (client/server) should synchronize failures
593 * using a shared variable *err, so that they can detect the other side's
594 * failure.
595 */
596 extern int test_skpair_wait_poll(int sk, bool write, test_cnt cond,
597 volatile int *err);
598 extern int _test_skpair_connect_poll(int sk, const char *device,
599 void *addr, size_t addr_sz,
600 test_cnt cond, volatile int *err);
test_skpair_connect_poll(int sk,const union tcp_addr taddr,unsigned int port,test_cnt cond,volatile int * err)601 static inline int test_skpair_connect_poll(int sk, const union tcp_addr taddr,
602 unsigned int port,
603 test_cnt cond, volatile int *err)
604 {
605 sockaddr_af addr;
606
607 tcp_addr_to_sockaddr_in(&addr, &taddr, htons(port));
608 return _test_skpair_connect_poll(sk, veth_name,
609 (void *)&addr, sizeof(addr), cond, err);
610 }
611
612 extern int test_skpair_client(int sk, const size_t msg_len, const size_t nr,
613 test_cnt cond, volatile int *err);
614 extern int test_skpair_server(int sk, ssize_t quota,
615 test_cnt cond, volatile int *err);
616
617 /*
618 * Frees buffers allocated in test_get_tcp_counters().
619 * The function doesn't expect new keys or keys removed between calls
620 * to test_get_tcp_counters(). Check key counters manually if they
621 * may change.
622 */
test_assert_counters(const char * tst_name,struct tcp_counters * before,struct tcp_counters * after,test_cnt expected)623 static inline int test_assert_counters(const char *tst_name,
624 struct tcp_counters *before,
625 struct tcp_counters *after,
626 test_cnt expected)
627 {
628 int ret;
629
630 ret = test_assert_counters_sk(tst_name, before, after, expected);
631 if (ret)
632 goto out;
633 ret = test_assert_counters_key(tst_name, &before->ao, &after->ao,
634 expected, -1, -1);
635 out:
636 test_tcp_counters_free(before);
637 test_tcp_counters_free(after);
638 return ret;
639 }
640
641 struct netstat;
642 extern struct netstat *netstat_read(void);
643 extern void netstat_free(struct netstat *ns);
644 extern void netstat_print_diff(struct netstat *nsa, struct netstat *nsb);
645 extern uint64_t netstat_get(struct netstat *ns,
646 const char *name, bool *not_found);
647
netstat_get_one(const char * name,bool * not_found)648 static inline uint64_t netstat_get_one(const char *name, bool *not_found)
649 {
650 struct netstat *ns = netstat_read();
651 uint64_t ret;
652
653 ret = netstat_get(ns, name, not_found);
654
655 netstat_free(ns);
656 return ret;
657 }
658
659 struct tcp_sock_queue {
660 uint32_t seq;
661 void *buf;
662 };
663
664 struct tcp_sock_state {
665 struct tcp_info info;
666 struct tcp_repair_window trw;
667 struct tcp_sock_queue out;
668 int outq_len; /* output queue size (not sent + not acked) */
669 int outq_nsd_len; /* output queue size (not sent only) */
670 struct tcp_sock_queue in;
671 int inq_len;
672 int mss;
673 int timestamp;
674 };
675
676 extern void __test_sock_checkpoint(int sk, struct tcp_sock_state *state,
677 void *addr, size_t addr_size);
test_sock_checkpoint(int sk,struct tcp_sock_state * state,sockaddr_af * saddr)678 static inline void test_sock_checkpoint(int sk, struct tcp_sock_state *state,
679 sockaddr_af *saddr)
680 {
681 __test_sock_checkpoint(sk, state, saddr, sizeof(*saddr));
682 }
683 extern void test_ao_checkpoint(int sk, struct tcp_ao_repair *state);
684 extern void __test_sock_restore(int sk, const char *device,
685 struct tcp_sock_state *state,
686 void *saddr, void *daddr, size_t addr_size);
test_sock_restore(int sk,struct tcp_sock_state * state,sockaddr_af * saddr,const union tcp_addr daddr,unsigned int dport)687 static inline void test_sock_restore(int sk, struct tcp_sock_state *state,
688 sockaddr_af *saddr,
689 const union tcp_addr daddr,
690 unsigned int dport)
691 {
692 sockaddr_af addr;
693
694 tcp_addr_to_sockaddr_in(&addr, &daddr, htons(dport));
695 __test_sock_restore(sk, veth_name, state, saddr, &addr, sizeof(addr));
696 }
697 extern void test_ao_restore(int sk, struct tcp_ao_repair *state);
698 extern void test_sock_state_free(struct tcp_sock_state *state);
699 extern void test_enable_repair(int sk);
700 extern void test_disable_repair(int sk);
701 extern void test_kill_sk(int sk);
test_add_repaired_key(int sk,const char * key,uint8_t keyflags,union tcp_addr in_addr,uint8_t prefix,uint8_t sndid,uint8_t rcvid)702 static inline int test_add_repaired_key(int sk,
703 const char *key, uint8_t keyflags,
704 union tcp_addr in_addr, uint8_t prefix,
705 uint8_t sndid, uint8_t rcvid)
706 {
707 struct tcp_ao_add tmp = {};
708 int err;
709
710 err = test_prepare_def_key(&tmp, key, keyflags, in_addr, prefix,
711 0, sndid, rcvid);
712 if (err)
713 return err;
714
715 tmp.set_current = 1;
716 tmp.set_rnext = 1;
717 if (setsockopt(sk, IPPROTO_TCP, TCP_AO_ADD_KEY, &tmp, sizeof(tmp)) < 0)
718 return -errno;
719
720 return test_verify_socket_key(sk, &tmp);
721 }
722
723 #define DEFAULT_FTRACE_BUFFER_KB 10000
724 #define DEFAULT_TRACER_LINES_ARR 200
725 struct test_ftracer;
726 extern uint64_t ns_cookie1, ns_cookie2;
727
728 enum ftracer_op {
729 FTRACER_LINE_DISCARD = 0,
730 FTRACER_LINE_PRESERVE,
731 FTRACER_EXIT,
732 };
733
734 extern struct test_ftracer *create_ftracer(const char *name,
735 enum ftracer_op (*process_line)(const char *line),
736 void (*destructor)(struct test_ftracer *tracer),
737 bool (*expecting_more)(void),
738 size_t lines_buf_sz, size_t buffer_size_kb);
739 extern int setup_trace_event(struct test_ftracer *tracer,
740 const char *event, const char *filter);
741 extern void destroy_ftracer(struct test_ftracer *tracer);
742 extern const size_t tracer_get_savedlines_nr(struct test_ftracer *tracer);
743 extern const char **tracer_get_savedlines(struct test_ftracer *tracer);
744
745 enum trace_events {
746 /* TCP_HASH_EVENT */
747 TCP_HASH_BAD_HEADER = 0,
748 TCP_HASH_MD5_REQUIRED,
749 TCP_HASH_MD5_UNEXPECTED,
750 TCP_HASH_MD5_MISMATCH,
751 TCP_HASH_AO_REQUIRED,
752 /* TCP_AO_EVENT */
753 TCP_AO_HANDSHAKE_FAILURE,
754 TCP_AO_WRONG_MACLEN,
755 TCP_AO_MISMATCH,
756 TCP_AO_KEY_NOT_FOUND,
757 TCP_AO_RNEXT_REQUEST,
758 /* TCP_AO_EVENT_SK */
759 TCP_AO_SYNACK_NO_KEY,
760 /* TCP_AO_EVENT_SNE */
761 TCP_AO_SND_SNE_UPDATE,
762 TCP_AO_RCV_SNE_UPDATE,
763 __MAX_TRACE_EVENTS
764 };
765
766 extern int __trace_event_expect(enum trace_events type, int family,
767 union tcp_addr src, union tcp_addr dst,
768 int src_port, int dst_port, int L3index,
769 int fin, int syn, int rst, int psh, int ack,
770 int keyid, int rnext, int maclen, int sne);
771
trace_hash_event_expect(enum trace_events type,union tcp_addr src,union tcp_addr dst,int src_port,int dst_port,int L3index,int fin,int syn,int rst,int psh,int ack)772 static inline void trace_hash_event_expect(enum trace_events type,
773 union tcp_addr src, union tcp_addr dst,
774 int src_port, int dst_port, int L3index,
775 int fin, int syn, int rst, int psh, int ack)
776 {
777 int err;
778
779 err = __trace_event_expect(type, TEST_FAMILY, src, dst,
780 src_port, dst_port, L3index,
781 fin, syn, rst, psh, ack,
782 -1, -1, -1, -1);
783 if (err)
784 test_error("Couldn't add a trace event: %d", err);
785 }
786
trace_ao_event_expect(enum trace_events type,union tcp_addr src,union tcp_addr dst,int src_port,int dst_port,int L3index,int fin,int syn,int rst,int psh,int ack,int keyid,int rnext,int maclen)787 static inline void trace_ao_event_expect(enum trace_events type,
788 union tcp_addr src, union tcp_addr dst,
789 int src_port, int dst_port, int L3index,
790 int fin, int syn, int rst, int psh, int ack,
791 int keyid, int rnext, int maclen)
792 {
793 int err;
794
795 err = __trace_event_expect(type, TEST_FAMILY, src, dst,
796 src_port, dst_port, L3index,
797 fin, syn, rst, psh, ack,
798 keyid, rnext, maclen, -1);
799 if (err)
800 test_error("Couldn't add a trace event: %d", err);
801 }
802
trace_ao_event_sk_expect(enum trace_events type,union tcp_addr src,union tcp_addr dst,int src_port,int dst_port,int keyid,int rnext)803 static inline void trace_ao_event_sk_expect(enum trace_events type,
804 union tcp_addr src, union tcp_addr dst,
805 int src_port, int dst_port,
806 int keyid, int rnext)
807 {
808 int err;
809
810 err = __trace_event_expect(type, TEST_FAMILY, src, dst,
811 src_port, dst_port, -1,
812 -1, -1, -1, -1, -1,
813 keyid, rnext, -1, -1);
814 if (err)
815 test_error("Couldn't add a trace event: %d", err);
816 }
817
trace_ao_event_sne_expect(enum trace_events type,union tcp_addr src,union tcp_addr dst,int src_port,int dst_port,int sne)818 static inline void trace_ao_event_sne_expect(enum trace_events type,
819 union tcp_addr src, union tcp_addr dst,
820 int src_port, int dst_port, int sne)
821 {
822 int err;
823
824 err = __trace_event_expect(type, TEST_FAMILY, src, dst,
825 src_port, dst_port, -1,
826 -1, -1, -1, -1, -1,
827 -1, -1, -1, sne);
828 if (err)
829 test_error("Couldn't add a trace event: %d", err);
830 }
831
832 extern int setup_aolib_ftracer(void);
833
834 #endif /* _AOLIB_H_ */
835