Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / tools / testing / selftests / net / tcp_ao / lib / setup.c
bloba27cc03c9fbdcb8e68fdfc6edc3dc0cfd464b292
1 // SPDX-License-Identifier: GPL-2.0
2 #include <fcntl.h>
3 #include <pthread.h>
4 #include <sched.h>
5 #include <signal.h>
6 #include "aolib.h"
8 /*
9 * Can't be included in the header: it defines static variables which
10 * will be unique to every object. Let's include it only once here.
12 #include "../../../kselftest.h"
14 /* Prevent overriding of one thread's output by another */
15 static pthread_mutex_t ksft_print_lock = PTHREAD_MUTEX_INITIALIZER;
17 void __test_msg(const char *buf)
19 pthread_mutex_lock(&ksft_print_lock);
20 ksft_print_msg("%s", buf);
21 pthread_mutex_unlock(&ksft_print_lock);
23 void __test_ok(const char *buf)
25 pthread_mutex_lock(&ksft_print_lock);
26 ksft_test_result_pass("%s", buf);
27 pthread_mutex_unlock(&ksft_print_lock);
29 void __test_fail(const char *buf)
31 pthread_mutex_lock(&ksft_print_lock);
32 ksft_test_result_fail("%s", buf);
33 pthread_mutex_unlock(&ksft_print_lock);
35 void __test_xfail(const char *buf)
37 pthread_mutex_lock(&ksft_print_lock);
38 ksft_test_result_xfail("%s", buf);
39 pthread_mutex_unlock(&ksft_print_lock);
41 void __test_error(const char *buf)
43 pthread_mutex_lock(&ksft_print_lock);
44 ksft_test_result_error("%s", buf);
45 pthread_mutex_unlock(&ksft_print_lock);
47 void __test_skip(const char *buf)
49 pthread_mutex_lock(&ksft_print_lock);
50 ksft_test_result_skip("%s", buf);
51 pthread_mutex_unlock(&ksft_print_lock);
54 static volatile int failed;
55 static volatile int skipped;
57 void test_failed(void)
59 failed = 1;
62 static void test_exit(void)
64 if (failed) {
65 ksft_exit_fail();
66 } else if (skipped) {
67 /* ksft_exit_skip() is different from ksft_exit_*() */
68 ksft_print_cnts();
69 exit(KSFT_SKIP);
70 } else {
71 ksft_exit_pass();
75 struct dlist_t {
76 void (*destruct)(void);
77 struct dlist_t *next;
79 static struct dlist_t *destructors_list;
81 void test_add_destructor(void (*d)(void))
83 struct dlist_t *p;
85 p = malloc(sizeof(struct dlist_t));
86 if (p == NULL)
87 test_error("malloc() failed");
89 p->next = destructors_list;
90 p->destruct = d;
91 destructors_list = p;
94 static void test_destructor(void) __attribute__((destructor));
95 static void test_destructor(void)
97 while (destructors_list) {
98 struct dlist_t *p = destructors_list->next;
100 destructors_list->destruct();
101 free(destructors_list);
102 destructors_list = p;
104 test_exit();
107 static void sig_int(int signo)
109 test_error("Caught SIGINT - exiting");
112 int open_netns(void)
114 const char *netns_path = "/proc/thread-self/ns/net";
115 int fd;
117 fd = open(netns_path, O_RDONLY);
118 if (fd < 0)
119 test_error("open(%s)", netns_path);
120 return fd;
123 int unshare_open_netns(void)
125 if (unshare(CLONE_NEWNET) != 0)
126 test_error("unshare()");
128 return open_netns();
131 void switch_ns(int fd)
133 if (setns(fd, CLONE_NEWNET))
134 test_error("setns()");
137 int switch_save_ns(int new_ns)
139 int ret = open_netns();
141 switch_ns(new_ns);
142 return ret;
145 void switch_close_ns(int fd)
147 if (setns(fd, CLONE_NEWNET))
148 test_error("setns()");
149 close(fd);
152 static int nsfd_outside = -1;
153 static int nsfd_parent = -1;
154 static int nsfd_child = -1;
155 const char veth_name[] = "ktst-veth";
157 static void init_namespaces(void)
159 nsfd_outside = open_netns();
160 nsfd_parent = unshare_open_netns();
161 nsfd_child = unshare_open_netns();
164 static void link_init(const char *veth, int family, uint8_t prefix,
165 union tcp_addr addr, union tcp_addr dest)
167 if (link_set_up(veth))
168 test_error("Failed to set link up");
169 if (ip_addr_add(veth, family, addr, prefix))
170 test_error("Failed to add ip address");
171 if (ip_route_add(veth, family, addr, dest))
172 test_error("Failed to add route");
175 static unsigned int nr_threads = 1;
177 static pthread_mutex_t sync_lock = PTHREAD_MUTEX_INITIALIZER;
178 static pthread_cond_t sync_cond = PTHREAD_COND_INITIALIZER;
179 static volatile unsigned int stage_threads[2];
180 static volatile unsigned int stage_nr;
182 /* synchronize all threads in the same stage */
183 void synchronize_threads(void)
185 unsigned int q = stage_nr;
187 pthread_mutex_lock(&sync_lock);
188 stage_threads[q]++;
189 if (stage_threads[q] == nr_threads) {
190 stage_nr ^= 1;
191 stage_threads[stage_nr] = 0;
192 pthread_cond_signal(&sync_cond);
194 while (stage_threads[q] < nr_threads)
195 pthread_cond_wait(&sync_cond, &sync_lock);
196 pthread_mutex_unlock(&sync_lock);
199 __thread union tcp_addr this_ip_addr;
200 __thread union tcp_addr this_ip_dest;
201 int test_family;
203 struct new_pthread_arg {
204 thread_fn func;
205 union tcp_addr my_ip;
206 union tcp_addr dest_ip;
208 static void *new_pthread_entry(void *arg)
210 struct new_pthread_arg *p = arg;
212 this_ip_addr = p->my_ip;
213 this_ip_dest = p->dest_ip;
214 p->func(NULL); /* shouldn't return */
215 exit(KSFT_FAIL);
218 static void __test_skip_all(const char *msg)
220 ksft_set_plan(1);
221 ksft_print_header();
222 skipped = 1;
223 test_skip("%s", msg);
224 exit(KSFT_SKIP);
227 void __test_init(unsigned int ntests, int family, unsigned int prefix,
228 union tcp_addr addr1, union tcp_addr addr2,
229 thread_fn peer1, thread_fn peer2)
231 struct sigaction sa = {
232 .sa_handler = sig_int,
233 .sa_flags = SA_RESTART,
235 time_t seed = time(NULL);
237 sigemptyset(&sa.sa_mask);
238 if (sigaction(SIGINT, &sa, NULL))
239 test_error("Can't set SIGINT handler");
241 test_family = family;
242 if (!kernel_config_has(KCONFIG_NET_NS))
243 __test_skip_all(tests_skip_reason[KCONFIG_NET_NS]);
244 if (!kernel_config_has(KCONFIG_VETH))
245 __test_skip_all(tests_skip_reason[KCONFIG_VETH]);
246 if (!kernel_config_has(KCONFIG_TCP_AO))
247 __test_skip_all(tests_skip_reason[KCONFIG_TCP_AO]);
249 ksft_set_plan(ntests);
250 test_print("rand seed %u", (unsigned int)seed);
251 srand(seed);
253 ksft_print_header();
254 init_namespaces();
255 test_init_ftrace(nsfd_parent, nsfd_child);
257 if (add_veth(veth_name, nsfd_parent, nsfd_child))
258 test_error("Failed to add veth");
260 switch_ns(nsfd_child);
261 link_init(veth_name, family, prefix, addr2, addr1);
262 if (peer2) {
263 struct new_pthread_arg targ;
264 pthread_t t;
266 targ.my_ip = addr2;
267 targ.dest_ip = addr1;
268 targ.func = peer2;
269 nr_threads++;
270 if (pthread_create(&t, NULL, new_pthread_entry, &targ))
271 test_error("Failed to create pthread");
273 switch_ns(nsfd_parent);
274 link_init(veth_name, family, prefix, addr1, addr2);
276 this_ip_addr = addr1;
277 this_ip_dest = addr2;
278 peer1(NULL);
279 if (failed)
280 exit(KSFT_FAIL);
281 else
282 exit(KSFT_PASS);
285 /* /proc/sys/net/core/optmem_max artifically limits the amount of memory
286 * that can be allocated with sock_kmalloc() on each socket in the system.
287 * It is not virtualized in v6.7, so it has to written outside test
288 * namespaces. To be nice a test will revert optmem back to the old value.
289 * Keeping it simple without any file lock, which means the tests that
290 * need to set/increase optmem value shouldn't run in parallel.
291 * Also, not re-entrant.
292 * Since commit f5769faeec36 ("net: Namespace-ify sysctl_optmem_max")
293 * it is per-namespace, keeping logic for non-virtualized optmem_max
294 * for v6.7, which supports TCP-AO.
296 static const char *optmem_file = "/proc/sys/net/core/optmem_max";
297 static size_t saved_optmem;
298 static int optmem_ns = -1;
300 static bool is_optmem_namespaced(void)
302 if (optmem_ns == -1) {
303 int old_ns = switch_save_ns(nsfd_child);
305 optmem_ns = !access(optmem_file, F_OK);
306 switch_close_ns(old_ns);
308 return !!optmem_ns;
311 size_t test_get_optmem(void)
313 int old_ns = 0;
314 FILE *foptmem;
315 size_t ret;
317 if (!is_optmem_namespaced())
318 old_ns = switch_save_ns(nsfd_outside);
319 foptmem = fopen(optmem_file, "r");
320 if (!foptmem)
321 test_error("failed to open %s", optmem_file);
323 if (fscanf(foptmem, "%zu", &ret) != 1)
324 test_error("can't read from %s", optmem_file);
325 fclose(foptmem);
326 if (!is_optmem_namespaced())
327 switch_close_ns(old_ns);
328 return ret;
331 static void __test_set_optmem(size_t new, size_t *old)
333 int old_ns = 0;
334 FILE *foptmem;
336 if (old != NULL)
337 *old = test_get_optmem();
339 if (!is_optmem_namespaced())
340 old_ns = switch_save_ns(nsfd_outside);
341 foptmem = fopen(optmem_file, "w");
342 if (!foptmem)
343 test_error("failed to open %s", optmem_file);
345 if (fprintf(foptmem, "%zu", new) <= 0)
346 test_error("can't write %zu to %s", new, optmem_file);
347 fclose(foptmem);
348 if (!is_optmem_namespaced())
349 switch_close_ns(old_ns);
352 static void test_revert_optmem(void)
354 if (saved_optmem == 0)
355 return;
357 __test_set_optmem(saved_optmem, NULL);
360 void test_set_optmem(size_t value)
362 if (saved_optmem == 0) {
363 __test_set_optmem(value, &saved_optmem);
364 test_add_destructor(test_revert_optmem);
365 } else {
366 __test_set_optmem(value, NULL);