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