drm/atomic-helper: document drm_atomic_helper_check() restrictions
[drm/drm-misc.git] / tools / testing / selftests / net / epoll_busy_poll.c
blob16e457c2f8772da99ebd2f22723f7151a60c47ce
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /* Basic per-epoll context busy poll test.
5 * Only tests the ioctls, but should be expanded to test two connected hosts in
6 * the future
7 */
9 #define _GNU_SOURCE
11 #include <error.h>
12 #include <errno.h>
13 #include <inttypes.h>
14 #include <limits.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
20 #include <sys/capability.h>
22 #include <sys/epoll.h>
23 #include <sys/ioctl.h>
24 #include <sys/socket.h>
26 #include "../kselftest_harness.h"
28 /* if the headers haven't been updated, we need to define some things */
29 #if !defined(EPOLL_IOC_TYPE)
30 struct epoll_params {
31 uint32_t busy_poll_usecs;
32 uint16_t busy_poll_budget;
33 uint8_t prefer_busy_poll;
35 /* pad the struct to a multiple of 64bits */
36 uint8_t __pad;
39 #define EPOLL_IOC_TYPE 0x8A
40 #define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)
41 #define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
42 #endif
44 FIXTURE(invalid_fd)
46 int invalid_fd;
47 struct epoll_params params;
50 FIXTURE_SETUP(invalid_fd)
52 int ret;
54 ret = socket(AF_UNIX, SOCK_DGRAM, 0);
55 EXPECT_NE(-1, ret)
56 TH_LOG("error creating unix socket");
58 self->invalid_fd = ret;
61 FIXTURE_TEARDOWN(invalid_fd)
63 int ret;
65 ret = close(self->invalid_fd);
66 EXPECT_EQ(0, ret);
69 TEST_F(invalid_fd, test_invalid_fd)
71 int ret;
73 ret = ioctl(self->invalid_fd, EPIOCGPARAMS, &self->params);
75 EXPECT_EQ(-1, ret)
76 TH_LOG("EPIOCGPARAMS on invalid epoll FD should error");
78 EXPECT_EQ(ENOTTY, errno)
79 TH_LOG("EPIOCGPARAMS on invalid epoll FD should set errno to ENOTTY");
81 memset(&self->params, 0, sizeof(struct epoll_params));
83 ret = ioctl(self->invalid_fd, EPIOCSPARAMS, &self->params);
85 EXPECT_EQ(-1, ret)
86 TH_LOG("EPIOCSPARAMS on invalid epoll FD should error");
88 EXPECT_EQ(ENOTTY, errno)
89 TH_LOG("EPIOCSPARAMS on invalid epoll FD should set errno to ENOTTY");
92 FIXTURE(epoll_busy_poll)
94 int fd;
95 struct epoll_params params;
96 struct epoll_params *invalid_params;
97 cap_t caps;
100 FIXTURE_SETUP(epoll_busy_poll)
102 int ret;
104 ret = epoll_create1(0);
105 EXPECT_NE(-1, ret)
106 TH_LOG("epoll_create1 failed?");
108 self->fd = ret;
110 self->caps = cap_get_proc();
111 EXPECT_NE(NULL, self->caps);
114 FIXTURE_TEARDOWN(epoll_busy_poll)
116 int ret;
118 ret = close(self->fd);
119 EXPECT_EQ(0, ret);
121 ret = cap_free(self->caps);
122 EXPECT_NE(-1, ret)
123 TH_LOG("unable to free capabilities");
126 TEST_F(epoll_busy_poll, test_get_params)
128 /* begin by getting the epoll params from the kernel
130 * the default should be default and all fields should be zero'd by the
131 * kernel, so set params fields to garbage to test this.
133 int ret = 0;
135 self->params.busy_poll_usecs = 0xff;
136 self->params.busy_poll_budget = 0xff;
137 self->params.prefer_busy_poll = 1;
138 self->params.__pad = 0xf;
140 ret = ioctl(self->fd, EPIOCGPARAMS, &self->params);
141 EXPECT_EQ(0, ret)
142 TH_LOG("ioctl EPIOCGPARAMS should succeed");
144 EXPECT_EQ(0, self->params.busy_poll_usecs)
145 TH_LOG("EPIOCGPARAMS busy_poll_usecs should have been 0");
147 EXPECT_EQ(0, self->params.busy_poll_budget)
148 TH_LOG("EPIOCGPARAMS busy_poll_budget should have been 0");
150 EXPECT_EQ(0, self->params.prefer_busy_poll)
151 TH_LOG("EPIOCGPARAMS prefer_busy_poll should have been 0");
153 EXPECT_EQ(0, self->params.__pad)
154 TH_LOG("EPIOCGPARAMS __pad should have been 0");
156 self->invalid_params = (struct epoll_params *)0xdeadbeef;
157 ret = ioctl(self->fd, EPIOCGPARAMS, self->invalid_params);
159 EXPECT_EQ(-1, ret)
160 TH_LOG("EPIOCGPARAMS should error with invalid params");
162 EXPECT_EQ(EFAULT, errno)
163 TH_LOG("EPIOCGPARAMS with invalid params should set errno to EFAULT");
166 TEST_F(epoll_busy_poll, test_set_invalid)
168 int ret;
170 memset(&self->params, 0, sizeof(struct epoll_params));
172 self->params.__pad = 1;
174 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params);
176 EXPECT_EQ(-1, ret)
177 TH_LOG("EPIOCSPARAMS non-zero __pad should error");
179 EXPECT_EQ(EINVAL, errno)
180 TH_LOG("EPIOCSPARAMS non-zero __pad errno should be EINVAL");
182 self->params.__pad = 0;
183 self->params.busy_poll_usecs = (uint32_t)INT_MAX + 1;
185 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params);
187 EXPECT_EQ(-1, ret)
188 TH_LOG("EPIOCSPARAMS should error busy_poll_usecs > S32_MAX");
190 EXPECT_EQ(EINVAL, errno)
191 TH_LOG("EPIOCSPARAMS busy_poll_usecs > S32_MAX errno should be EINVAL");
193 self->params.__pad = 0;
194 self->params.busy_poll_usecs = 32;
195 self->params.prefer_busy_poll = 2;
197 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params);
199 EXPECT_EQ(-1, ret)
200 TH_LOG("EPIOCSPARAMS should error prefer_busy_poll > 1");
202 EXPECT_EQ(EINVAL, errno)
203 TH_LOG("EPIOCSPARAMS prefer_busy_poll > 1 errno should be EINVAL");
205 self->params.__pad = 0;
206 self->params.busy_poll_usecs = 32;
207 self->params.prefer_busy_poll = 1;
209 /* set budget well above kernel's NAPI_POLL_WEIGHT of 64 */
210 self->params.busy_poll_budget = UINT16_MAX;
212 /* test harness should run with CAP_NET_ADMIN, but let's make sure */
213 cap_flag_value_t tmp;
215 ret = cap_get_flag(self->caps, CAP_NET_ADMIN, CAP_EFFECTIVE, &tmp);
216 EXPECT_EQ(0, ret)
217 TH_LOG("unable to get CAP_NET_ADMIN cap flag");
219 EXPECT_EQ(CAP_SET, tmp)
220 TH_LOG("expecting CAP_NET_ADMIN to be set for the test harness");
222 /* at this point we know CAP_NET_ADMIN is available, so setting the
223 * params with a busy_poll_budget > NAPI_POLL_WEIGHT should succeed
225 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params);
227 EXPECT_EQ(0, ret)
228 TH_LOG("EPIOCSPARAMS should allow busy_poll_budget > NAPI_POLL_WEIGHT");
230 /* remove CAP_NET_ADMIN from our effective set */
231 cap_value_t net_admin[] = { CAP_NET_ADMIN };
233 ret = cap_set_flag(self->caps, CAP_EFFECTIVE, 1, net_admin, CAP_CLEAR);
234 EXPECT_EQ(0, ret)
235 TH_LOG("couldn't clear CAP_NET_ADMIN");
237 ret = cap_set_proc(self->caps);
238 EXPECT_EQ(0, ret)
239 TH_LOG("cap_set_proc should drop CAP_NET_ADMIN");
241 /* this is now expected to fail */
242 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params);
244 EXPECT_EQ(-1, ret)
245 TH_LOG("EPIOCSPARAMS should error busy_poll_budget > NAPI_POLL_WEIGHT");
247 EXPECT_EQ(EPERM, errno)
248 TH_LOG("EPIOCSPARAMS errno should be EPERM busy_poll_budget > NAPI_POLL_WEIGHT");
250 /* restore CAP_NET_ADMIN to our effective set */
251 ret = cap_set_flag(self->caps, CAP_EFFECTIVE, 1, net_admin, CAP_SET);
252 EXPECT_EQ(0, ret)
253 TH_LOG("couldn't restore CAP_NET_ADMIN");
255 ret = cap_set_proc(self->caps);
256 EXPECT_EQ(0, ret)
257 TH_LOG("cap_set_proc should set CAP_NET_ADMIN");
259 self->invalid_params = (struct epoll_params *)0xdeadbeef;
260 ret = ioctl(self->fd, EPIOCSPARAMS, self->invalid_params);
262 EXPECT_EQ(-1, ret)
263 TH_LOG("EPIOCSPARAMS should error when epoll_params is invalid");
265 EXPECT_EQ(EFAULT, errno)
266 TH_LOG("EPIOCSPARAMS should set errno to EFAULT when epoll_params is invalid");
269 TEST_F(epoll_busy_poll, test_set_and_get_valid)
271 int ret;
273 memset(&self->params, 0, sizeof(struct epoll_params));
275 self->params.busy_poll_usecs = 25;
276 self->params.busy_poll_budget = 16;
277 self->params.prefer_busy_poll = 1;
279 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params);
281 EXPECT_EQ(0, ret)
282 TH_LOG("EPIOCSPARAMS with valid params should not error");
284 /* check that the kernel returns the same values back */
286 memset(&self->params, 0, sizeof(struct epoll_params));
288 ret = ioctl(self->fd, EPIOCGPARAMS, &self->params);
290 EXPECT_EQ(0, ret)
291 TH_LOG("EPIOCGPARAMS should not error");
293 EXPECT_EQ(25, self->params.busy_poll_usecs)
294 TH_LOG("params.busy_poll_usecs incorrect");
296 EXPECT_EQ(16, self->params.busy_poll_budget)
297 TH_LOG("params.busy_poll_budget incorrect");
299 EXPECT_EQ(1, self->params.prefer_busy_poll)
300 TH_LOG("params.prefer_busy_poll incorrect");
302 EXPECT_EQ(0, self->params.__pad)
303 TH_LOG("params.__pad was not 0");
306 TEST_F(epoll_busy_poll, test_invalid_ioctl)
308 int invalid_ioctl = EPIOCGPARAMS + 10;
309 int ret;
311 ret = ioctl(self->fd, invalid_ioctl, &self->params);
313 EXPECT_EQ(-1, ret)
314 TH_LOG("invalid ioctl should return error");
316 EXPECT_EQ(EINVAL, errno)
317 TH_LOG("invalid ioctl should set errno to EINVAL");
320 TEST_HARNESS_MAIN