1 // SPDX-License-Identifier: GPL-2.0
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)
62 static void test_exit(void)
67 /* ksft_exit_skip() is different from ksft_exit_*() */
76 void (*destruct
)(void);
79 static struct dlist_t
*destructors_list
;
81 void test_add_destructor(void (*d
)(void))
85 p
= malloc(sizeof(struct dlist_t
));
87 test_error("malloc() failed");
89 p
->next
= destructors_list
;
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
;
107 static void sig_int(int signo
)
109 test_error("Caught SIGINT - exiting");
114 const char *netns_path
= "/proc/thread-self/ns/net";
117 fd
= open(netns_path
, O_RDONLY
);
119 test_error("open(%s)", netns_path
);
123 int unshare_open_netns(void)
125 if (unshare(CLONE_NEWNET
) != 0)
126 test_error("unshare()");
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();
145 void switch_close_ns(int fd
)
147 if (setns(fd
, CLONE_NEWNET
))
148 test_error("setns()");
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
);
189 if (stage_threads
[q
] == nr_threads
) {
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
;
203 struct new_pthread_arg
{
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 */
218 static void __test_skip_all(const char *msg
)
223 test_skip("%s", msg
);
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
);
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
);
263 struct new_pthread_arg targ
;
267 targ
.dest_ip
= addr1
;
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
;
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
);
311 size_t test_get_optmem(void)
317 if (!is_optmem_namespaced())
318 old_ns
= switch_save_ns(nsfd_outside
);
319 foptmem
= fopen(optmem_file
, "r");
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
);
326 if (!is_optmem_namespaced())
327 switch_close_ns(old_ns
);
331 static void __test_set_optmem(size_t new, size_t *old
)
337 *old
= test_get_optmem();
339 if (!is_optmem_namespaced())
340 old_ns
= switch_save_ns(nsfd_outside
);
341 foptmem
= fopen(optmem_file
, "w");
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
);
348 if (!is_optmem_namespaced())
349 switch_close_ns(old_ns
);
352 static void test_revert_optmem(void)
354 if (saved_optmem
== 0)
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
);
366 __test_set_optmem(value
, NULL
);