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>
9 #include <linux/hrtimer.h>
13 u64 nsec_to_sleep_before;
14 } expected_results[] __initconst = {
15 [0 ... PACKETS_BURSTABLE - 1] = { true, 0 },
16 [PACKETS_BURSTABLE] = { false, 0 },
17 [PACKETS_BURSTABLE + 1] = { true, NSEC_PER_SEC / PACKETS_PER_SECOND },
18 [PACKETS_BURSTABLE + 2] = { false, 0 },
19 [PACKETS_BURSTABLE + 3] = { true, (NSEC_PER_SEC / PACKETS_PER_SECOND) * 2 },
20 [PACKETS_BURSTABLE + 4] = { true, 0 },
21 [PACKETS_BURSTABLE + 5] = { false, 0 }
24 static __init unsigned int maximum_jiffies_at_index(int index)
26 u64 total_nsecs = 2 * NSEC_PER_SEC / PACKETS_PER_SECOND / 3;
29 for (i = 0; i <= index; ++i)
30 total_nsecs += expected_results[i].nsec_to_sleep_before;
31 return nsecs_to_jiffies(total_nsecs);
34 static __init int timings_test(struct sk_buff *skb4, struct iphdr *hdr4,
35 struct sk_buff *skb6, struct ipv6hdr *hdr6,
38 unsigned long loop_start_time;
41 wg_ratelimiter_gc_entries(NULL);
43 loop_start_time = jiffies;
45 for (i = 0; i < ARRAY_SIZE(expected_results); ++i) {
46 if (expected_results[i].nsec_to_sleep_before) {
47 ktime_t timeout = ktime_add(ktime_add_ns(ktime_get_coarse_boottime(), TICK_NSEC * 4 / 3),
48 ns_to_ktime(expected_results[i].nsec_to_sleep_before));
49 set_current_state(TASK_UNINTERRUPTIBLE);
50 schedule_hrtimeout_range_clock(&timeout, 0, HRTIMER_MODE_ABS, CLOCK_BOOTTIME);
53 if (time_is_before_jiffies(loop_start_time +
54 maximum_jiffies_at_index(i)))
56 if (wg_ratelimiter_allow(skb4, &init_net) !=
57 expected_results[i].result)
61 hdr4->saddr = htonl(ntohl(hdr4->saddr) + i + 1);
62 if (time_is_before_jiffies(loop_start_time +
63 maximum_jiffies_at_index(i)))
65 if (!wg_ratelimiter_allow(skb4, &init_net))
69 hdr4->saddr = htonl(ntohl(hdr4->saddr) - i - 1);
71 #if IS_ENABLED(CONFIG_IPV6)
72 hdr6->saddr.in6_u.u6_addr32[2] = htonl(i);
73 hdr6->saddr.in6_u.u6_addr32[3] = htonl(i);
74 if (time_is_before_jiffies(loop_start_time +
75 maximum_jiffies_at_index(i)))
77 if (wg_ratelimiter_allow(skb6, &init_net) !=
78 expected_results[i].result)
82 hdr6->saddr.in6_u.u6_addr32[0] =
83 htonl(ntohl(hdr6->saddr.in6_u.u6_addr32[0]) + i + 1);
84 if (time_is_before_jiffies(loop_start_time +
85 maximum_jiffies_at_index(i)))
87 if (!wg_ratelimiter_allow(skb6, &init_net))
91 hdr6->saddr.in6_u.u6_addr32[0] =
92 htonl(ntohl(hdr6->saddr.in6_u.u6_addr32[0]) - i - 1);
94 if (time_is_before_jiffies(loop_start_time +
95 maximum_jiffies_at_index(i)))
102 static __init int capacity_test(struct sk_buff *skb4, struct iphdr *hdr4,
107 wg_ratelimiter_gc_entries(NULL);
110 if (atomic_read(&total_entries))
114 for (i = 0; i <= max_entries; ++i) {
115 hdr4->saddr = htonl(i);
116 if (wg_ratelimiter_allow(skb4, &init_net) != (i != max_entries))
123 bool __init wg_ratelimiter_selftest(void)
125 enum { TRIALS_BEFORE_GIVING_UP = 5000 };
126 bool success = false;
127 int test = 0, trials;
128 struct sk_buff *skb4, *skb6 = NULL;
130 struct ipv6hdr *hdr6 = NULL;
132 if (IS_ENABLED(CONFIG_KASAN) || IS_ENABLED(CONFIG_UBSAN))
135 BUILD_BUG_ON(NSEC_PER_SEC % PACKETS_PER_SECOND != 0);
137 if (wg_ratelimiter_init())
140 if (wg_ratelimiter_init()) {
141 wg_ratelimiter_uninit();
145 if (wg_ratelimiter_init()) {
146 wg_ratelimiter_uninit();
147 wg_ratelimiter_uninit();
152 skb4 = alloc_skb(sizeof(struct iphdr), GFP_KERNEL);
155 skb4->protocol = htons(ETH_P_IP);
156 hdr4 = (struct iphdr *)skb_put(skb4, sizeof(*hdr4));
157 hdr4->saddr = htonl(8182);
158 skb_reset_network_header(skb4);
161 #if IS_ENABLED(CONFIG_IPV6)
162 skb6 = alloc_skb(sizeof(struct ipv6hdr), GFP_KERNEL);
163 if (unlikely(!skb6)) {
167 skb6->protocol = htons(ETH_P_IPV6);
168 hdr6 = (struct ipv6hdr *)skb_put(skb6, sizeof(*hdr6));
169 hdr6->saddr.in6_u.u6_addr32[0] = htonl(1212);
170 hdr6->saddr.in6_u.u6_addr32[1] = htonl(289188);
171 skb_reset_network_header(skb6);
175 for (trials = TRIALS_BEFORE_GIVING_UP;;) {
176 int test_count = 0, ret;
178 ret = timings_test(skb4, hdr4, skb6, hdr6, &test_count);
179 if (ret == -ETIMEDOUT) {
185 } else if (ret < 0) {
194 for (trials = TRIALS_BEFORE_GIVING_UP;;) {
197 if (capacity_test(skb4, hdr4, &test_count) < 0) {
212 #if IS_ENABLED(CONFIG_IPV6)
216 wg_ratelimiter_uninit();
217 wg_ratelimiter_uninit();
218 wg_ratelimiter_uninit();
219 /* Uninit one extra time to check underflow detection. */
220 wg_ratelimiter_uninit();
223 pr_info("ratelimiter self-tests: pass\n");
225 pr_err("ratelimiter self-test %d: FAIL\n", test);