xref: /linux/tools/testing/selftests/bpf/prog_tests/rhash_timer.c (revision 2beb1b31a12b57e19cd5c82ea6d54e56520605e8)
1*dbf6806dSKumar Kartikeya Dwivedi // SPDX-License-Identifier: GPL-2.0
2*dbf6806dSKumar Kartikeya Dwivedi 
3*dbf6806dSKumar Kartikeya Dwivedi #define _GNU_SOURCE
4*dbf6806dSKumar Kartikeya Dwivedi #include <sched.h>
5*dbf6806dSKumar Kartikeya Dwivedi 
6*dbf6806dSKumar Kartikeya Dwivedi #include <test_progs.h>
7*dbf6806dSKumar Kartikeya Dwivedi #include "rhash_timer.skel.h"
8*dbf6806dSKumar Kartikeya Dwivedi 
9*dbf6806dSKumar Kartikeya Dwivedi #define MAX_ATTEMPTS 256
10*dbf6806dSKumar Kartikeya Dwivedi #define RCU_SYNC_INTERVAL 64
11*dbf6806dSKumar Kartikeya Dwivedi 
pin_to_first_cpu(cpu_set_t * old_mask)12*dbf6806dSKumar Kartikeya Dwivedi static int pin_to_first_cpu(cpu_set_t *old_mask)
13*dbf6806dSKumar Kartikeya Dwivedi {
14*dbf6806dSKumar Kartikeya Dwivedi 	cpu_set_t new_mask;
15*dbf6806dSKumar Kartikeya Dwivedi 	int cpu;
16*dbf6806dSKumar Kartikeya Dwivedi 
17*dbf6806dSKumar Kartikeya Dwivedi 	if (sched_getaffinity(0, sizeof(*old_mask), old_mask))
18*dbf6806dSKumar Kartikeya Dwivedi 		return -errno;
19*dbf6806dSKumar Kartikeya Dwivedi 
20*dbf6806dSKumar Kartikeya Dwivedi 	for (cpu = 0; cpu < CPU_SETSIZE; cpu++)
21*dbf6806dSKumar Kartikeya Dwivedi 		if (CPU_ISSET(cpu, old_mask))
22*dbf6806dSKumar Kartikeya Dwivedi 			break;
23*dbf6806dSKumar Kartikeya Dwivedi 	if (cpu == CPU_SETSIZE)
24*dbf6806dSKumar Kartikeya Dwivedi 		return -EINVAL;
25*dbf6806dSKumar Kartikeya Dwivedi 
26*dbf6806dSKumar Kartikeya Dwivedi 	CPU_ZERO(&new_mask);
27*dbf6806dSKumar Kartikeya Dwivedi 	CPU_SET(cpu, &new_mask);
28*dbf6806dSKumar Kartikeya Dwivedi 	if (sched_setaffinity(0, sizeof(new_mask), &new_mask))
29*dbf6806dSKumar Kartikeya Dwivedi 		return -errno;
30*dbf6806dSKumar Kartikeya Dwivedi 	return 0;
31*dbf6806dSKumar Kartikeya Dwivedi }
32*dbf6806dSKumar Kartikeya Dwivedi 
update_timer_map(int map_fd,__u64 key)33*dbf6806dSKumar Kartikeya Dwivedi static int update_timer_map(int map_fd, __u64 key)
34*dbf6806dSKumar Kartikeya Dwivedi {
35*dbf6806dSKumar Kartikeya Dwivedi 	__u64 value[3] = {};
36*dbf6806dSKumar Kartikeya Dwivedi 
37*dbf6806dSKumar Kartikeya Dwivedi 	return bpf_map_update_elem(map_fd, &key, value, BPF_NOEXIST);
38*dbf6806dSKumar Kartikeya Dwivedi }
39*dbf6806dSKumar Kartikeya Dwivedi 
run_prog(int prog_fd,struct bpf_test_run_opts * opts)40*dbf6806dSKumar Kartikeya Dwivedi static int run_prog(int prog_fd, struct bpf_test_run_opts *opts)
41*dbf6806dSKumar Kartikeya Dwivedi {
42*dbf6806dSKumar Kartikeya Dwivedi 	int err;
43*dbf6806dSKumar Kartikeya Dwivedi 
44*dbf6806dSKumar Kartikeya Dwivedi 	err = bpf_prog_test_run_opts(prog_fd, opts);
45*dbf6806dSKumar Kartikeya Dwivedi 	if (err)
46*dbf6806dSKumar Kartikeya Dwivedi 		return err;
47*dbf6806dSKumar Kartikeya Dwivedi 	return opts->retval;
48*dbf6806dSKumar Kartikeya Dwivedi }
49*dbf6806dSKumar Kartikeya Dwivedi 
test_rhash_timer(void)50*dbf6806dSKumar Kartikeya Dwivedi void test_rhash_timer(void)
51*dbf6806dSKumar Kartikeya Dwivedi {
52*dbf6806dSKumar Kartikeya Dwivedi 	LIBBPF_OPTS(bpf_test_run_opts, opts);
53*dbf6806dSKumar Kartikeya Dwivedi 	struct rhash_timer *skel = NULL;
54*dbf6806dSKumar Kartikeya Dwivedi 	cpu_set_t old_mask;
55*dbf6806dSKumar Kartikeya Dwivedi 	int map_fd = -1, arm_fd, cancel_fd;
56*dbf6806dSKumar Kartikeya Dwivedi 	bool affinity_set = false;
57*dbf6806dSKumar Kartikeya Dwivedi 	__u64 key = 1;
58*dbf6806dSKumar Kartikeya Dwivedi 	int attempt, err;
59*dbf6806dSKumar Kartikeya Dwivedi 
60*dbf6806dSKumar Kartikeya Dwivedi 	err = pin_to_first_cpu(&old_mask);
61*dbf6806dSKumar Kartikeya Dwivedi 	if (!ASSERT_OK(err, "pin_to_first_cpu"))
62*dbf6806dSKumar Kartikeya Dwivedi 		return;
63*dbf6806dSKumar Kartikeya Dwivedi 	affinity_set = true;
64*dbf6806dSKumar Kartikeya Dwivedi 
65*dbf6806dSKumar Kartikeya Dwivedi 	skel = rhash_timer__open_and_load();
66*dbf6806dSKumar Kartikeya Dwivedi 	if (!ASSERT_OK_PTR(skel, "open_and_load"))
67*dbf6806dSKumar Kartikeya Dwivedi 		goto out;
68*dbf6806dSKumar Kartikeya Dwivedi 
69*dbf6806dSKumar Kartikeya Dwivedi 	map_fd = bpf_map__fd(skel->maps.timer_map);
70*dbf6806dSKumar Kartikeya Dwivedi 	if (!ASSERT_GE(map_fd, 0, "timer_map fd"))
71*dbf6806dSKumar Kartikeya Dwivedi 		goto out;
72*dbf6806dSKumar Kartikeya Dwivedi 	arm_fd = bpf_program__fd(skel->progs.arm_deleted_timer);
73*dbf6806dSKumar Kartikeya Dwivedi 	if (!ASSERT_GE(arm_fd, 0, "arm_deleted_timer fd"))
74*dbf6806dSKumar Kartikeya Dwivedi 		goto out;
75*dbf6806dSKumar Kartikeya Dwivedi 	cancel_fd = bpf_program__fd(skel->progs.cancel_recycled_timer);
76*dbf6806dSKumar Kartikeya Dwivedi 	if (!ASSERT_GE(cancel_fd, 0, "cancel_recycled_timer fd"))
77*dbf6806dSKumar Kartikeya Dwivedi 		goto out;
78*dbf6806dSKumar Kartikeya Dwivedi 
79*dbf6806dSKumar Kartikeya Dwivedi 	err = update_timer_map(map_fd, key);
80*dbf6806dSKumar Kartikeya Dwivedi 	if (!ASSERT_OK(err, "seed_timer_map"))
81*dbf6806dSKumar Kartikeya Dwivedi 		goto out;
82*dbf6806dSKumar Kartikeya Dwivedi 
83*dbf6806dSKumar Kartikeya Dwivedi 	for (attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
84*dbf6806dSKumar Kartikeya Dwivedi 		err = run_prog(arm_fd, &opts);
85*dbf6806dSKumar Kartikeya Dwivedi 		if (err) {
86*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_OK(err, "arm_deleted_timer");
87*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
88*dbf6806dSKumar Kartikeya Dwivedi 		}
89*dbf6806dSKumar Kartikeya Dwivedi 		if (skel->bss->armed != attempt + 1) {
90*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_EQ(skel->bss->armed, attempt + 1, "armed");
91*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
92*dbf6806dSKumar Kartikeya Dwivedi 		}
93*dbf6806dSKumar Kartikeya Dwivedi 		if (skel->bss->timer_init_err) {
94*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_OK(skel->bss->timer_init_err, "timer_init_err");
95*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
96*dbf6806dSKumar Kartikeya Dwivedi 		}
97*dbf6806dSKumar Kartikeya Dwivedi 		if (skel->bss->timer_set_callback_err) {
98*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_OK(skel->bss->timer_set_callback_err,
99*dbf6806dSKumar Kartikeya Dwivedi 				  "timer_set_callback_err");
100*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
101*dbf6806dSKumar Kartikeya Dwivedi 		}
102*dbf6806dSKumar Kartikeya Dwivedi 		if (skel->bss->timer_start_err) {
103*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_OK(skel->bss->timer_start_err, "timer_start_err");
104*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
105*dbf6806dSKumar Kartikeya Dwivedi 		}
106*dbf6806dSKumar Kartikeya Dwivedi 
107*dbf6806dSKumar Kartikeya Dwivedi 		if ((attempt + 1) % RCU_SYNC_INTERVAL == 0) {
108*dbf6806dSKumar Kartikeya Dwivedi 			err = kern_sync_rcu();
109*dbf6806dSKumar Kartikeya Dwivedi 			if (err) {
110*dbf6806dSKumar Kartikeya Dwivedi 				ASSERT_OK(err, "kern_sync_rcu");
111*dbf6806dSKumar Kartikeya Dwivedi 				goto out;
112*dbf6806dSKumar Kartikeya Dwivedi 			}
113*dbf6806dSKumar Kartikeya Dwivedi 		}
114*dbf6806dSKumar Kartikeya Dwivedi 
115*dbf6806dSKumar Kartikeya Dwivedi 		err = update_timer_map(map_fd, ++key);
116*dbf6806dSKumar Kartikeya Dwivedi 		if (err) {
117*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_OK(err, "replace_timer_map");
118*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
119*dbf6806dSKumar Kartikeya Dwivedi 		}
120*dbf6806dSKumar Kartikeya Dwivedi 
121*dbf6806dSKumar Kartikeya Dwivedi 		err = run_prog(cancel_fd, &opts);
122*dbf6806dSKumar Kartikeya Dwivedi 		if (err) {
123*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_OK(err, "cancel_recycled_timer");
124*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
125*dbf6806dSKumar Kartikeya Dwivedi 		}
126*dbf6806dSKumar Kartikeya Dwivedi 		if (skel->bss->timer_cancel_err) {
127*dbf6806dSKumar Kartikeya Dwivedi 			ASSERT_OK(skel->bss->timer_cancel_err, "timer_cancel_err");
128*dbf6806dSKumar Kartikeya Dwivedi 			goto out;
129*dbf6806dSKumar Kartikeya Dwivedi 		}
130*dbf6806dSKumar Kartikeya Dwivedi 		if (skel->bss->cancelled)
131*dbf6806dSKumar Kartikeya Dwivedi 			break;
132*dbf6806dSKumar Kartikeya Dwivedi 	}
133*dbf6806dSKumar Kartikeya Dwivedi 
134*dbf6806dSKumar Kartikeya Dwivedi 	ASSERT_GT(skel->bss->cancelled, 0, "preserved timer");
135*dbf6806dSKumar Kartikeya Dwivedi out:
136*dbf6806dSKumar Kartikeya Dwivedi 	if (map_fd >= 0)
137*dbf6806dSKumar Kartikeya Dwivedi 		bpf_map_delete_elem(map_fd, &key);
138*dbf6806dSKumar Kartikeya Dwivedi 	rhash_timer__destroy(skel);
139*dbf6806dSKumar Kartikeya Dwivedi 	if (affinity_set)
140*dbf6806dSKumar Kartikeya Dwivedi 		sched_setaffinity(0, sizeof(old_mask), &old_mask);
141*dbf6806dSKumar Kartikeya Dwivedi }
142