1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
8 #include <linux/jiffies.h>
12 unsigned int msec_to_sleep_before
;
13 } expected_results
[] __initconst
= {
14 [0 ... PACKETS_BURSTABLE
- 1] = { true, 0 },
15 [PACKETS_BURSTABLE
] = { false, 0 },
16 [PACKETS_BURSTABLE
+ 1] = { true, MSEC_PER_SEC
/ PACKETS_PER_SECOND
},
17 [PACKETS_BURSTABLE
+ 2] = { false, 0 },
18 [PACKETS_BURSTABLE
+ 3] = { true, (MSEC_PER_SEC
/ PACKETS_PER_SECOND
) * 2 },
19 [PACKETS_BURSTABLE
+ 4] = { true, 0 },
20 [PACKETS_BURSTABLE
+ 5] = { false, 0 }
23 static __init
unsigned int maximum_jiffies_at_index(int index
)
25 unsigned int total_msecs
= 2 * MSEC_PER_SEC
/ PACKETS_PER_SECOND
/ 3;
28 for (i
= 0; i
<= index
; ++i
)
29 total_msecs
+= expected_results
[i
].msec_to_sleep_before
;
30 return msecs_to_jiffies(total_msecs
);
33 static __init
int timings_test(struct sk_buff
*skb4
, struct iphdr
*hdr4
,
34 struct sk_buff
*skb6
, struct ipv6hdr
*hdr6
,
37 unsigned long loop_start_time
;
40 wg_ratelimiter_gc_entries(NULL
);
42 loop_start_time
= jiffies
;
44 for (i
= 0; i
< ARRAY_SIZE(expected_results
); ++i
) {
45 if (expected_results
[i
].msec_to_sleep_before
)
46 msleep(expected_results
[i
].msec_to_sleep_before
);
48 if (time_is_before_jiffies(loop_start_time
+
49 maximum_jiffies_at_index(i
)))
51 if (wg_ratelimiter_allow(skb4
, &init_net
) !=
52 expected_results
[i
].result
)
56 hdr4
->saddr
= htonl(ntohl(hdr4
->saddr
) + i
+ 1);
57 if (time_is_before_jiffies(loop_start_time
+
58 maximum_jiffies_at_index(i
)))
60 if (!wg_ratelimiter_allow(skb4
, &init_net
))
64 hdr4
->saddr
= htonl(ntohl(hdr4
->saddr
) - i
- 1);
66 #if IS_ENABLED(CONFIG_IPV6)
67 hdr6
->saddr
.in6_u
.u6_addr32
[2] = htonl(i
);
68 hdr6
->saddr
.in6_u
.u6_addr32
[3] = htonl(i
);
69 if (time_is_before_jiffies(loop_start_time
+
70 maximum_jiffies_at_index(i
)))
72 if (wg_ratelimiter_allow(skb6
, &init_net
) !=
73 expected_results
[i
].result
)
77 hdr6
->saddr
.in6_u
.u6_addr32
[0] =
78 htonl(ntohl(hdr6
->saddr
.in6_u
.u6_addr32
[0]) + i
+ 1);
79 if (time_is_before_jiffies(loop_start_time
+
80 maximum_jiffies_at_index(i
)))
82 if (!wg_ratelimiter_allow(skb6
, &init_net
))
86 hdr6
->saddr
.in6_u
.u6_addr32
[0] =
87 htonl(ntohl(hdr6
->saddr
.in6_u
.u6_addr32
[0]) - i
- 1);
89 if (time_is_before_jiffies(loop_start_time
+
90 maximum_jiffies_at_index(i
)))
97 static __init
int capacity_test(struct sk_buff
*skb4
, struct iphdr
*hdr4
,
102 wg_ratelimiter_gc_entries(NULL
);
105 if (atomic_read(&total_entries
))
109 for (i
= 0; i
<= max_entries
; ++i
) {
110 hdr4
->saddr
= htonl(i
);
111 if (wg_ratelimiter_allow(skb4
, &init_net
) != (i
!= max_entries
))
118 bool __init
wg_ratelimiter_selftest(void)
120 enum { TRIALS_BEFORE_GIVING_UP
= 5000 };
121 bool success
= false;
122 int test
= 0, trials
;
123 struct sk_buff
*skb4
, *skb6
;
125 struct ipv6hdr
*hdr6
;
127 if (IS_ENABLED(CONFIG_KASAN
) || IS_ENABLED(CONFIG_UBSAN
))
130 BUILD_BUG_ON(MSEC_PER_SEC
% PACKETS_PER_SECOND
!= 0);
132 if (wg_ratelimiter_init())
135 if (wg_ratelimiter_init()) {
136 wg_ratelimiter_uninit();
140 if (wg_ratelimiter_init()) {
141 wg_ratelimiter_uninit();
142 wg_ratelimiter_uninit();
147 skb4
= alloc_skb(sizeof(struct iphdr
), GFP_KERNEL
);
150 skb4
->protocol
= htons(ETH_P_IP
);
151 hdr4
= (struct iphdr
*)skb_put(skb4
, sizeof(*hdr4
));
152 hdr4
->saddr
= htonl(8182);
153 skb_reset_network_header(skb4
);
156 #if IS_ENABLED(CONFIG_IPV6)
157 skb6
= alloc_skb(sizeof(struct ipv6hdr
), GFP_KERNEL
);
158 if (unlikely(!skb6
)) {
162 skb6
->protocol
= htons(ETH_P_IPV6
);
163 hdr6
= (struct ipv6hdr
*)skb_put(skb6
, sizeof(*hdr6
));
164 hdr6
->saddr
.in6_u
.u6_addr32
[0] = htonl(1212);
165 hdr6
->saddr
.in6_u
.u6_addr32
[1] = htonl(289188);
166 skb_reset_network_header(skb6
);
170 for (trials
= TRIALS_BEFORE_GIVING_UP
;;) {
171 int test_count
= 0, ret
;
173 ret
= timings_test(skb4
, hdr4
, skb6
, hdr6
, &test_count
);
174 if (ret
== -ETIMEDOUT
) {
181 } else if (ret
< 0) {
190 for (trials
= TRIALS_BEFORE_GIVING_UP
;;) {
193 if (capacity_test(skb4
, hdr4
, &test_count
) < 0) {
209 #if IS_ENABLED(CONFIG_IPV6)
213 wg_ratelimiter_uninit();
214 wg_ratelimiter_uninit();
215 wg_ratelimiter_uninit();
216 /* Uninit one extra time to check underflow detection. */
217 wg_ratelimiter_uninit();
220 pr_info("ratelimiter self-tests: pass\n");
222 pr_err("ratelimiter self-test %d: FAIL\n", test
);