Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.18-rc5 320 lines 8.0 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2 3/* Basic per-epoll context busy poll test. 4 * 5 * Only tests the ioctls, but should be expanded to test two connected hosts in 6 * the future 7 */ 8 9#define _GNU_SOURCE 10 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> 19 20#include <sys/capability.h> 21 22#include <sys/epoll.h> 23#include <sys/ioctl.h> 24#include <sys/socket.h> 25 26#include "../kselftest_harness.h" 27 28/* if the headers haven't been updated, we need to define some things */ 29#if !defined(EPOLL_IOC_TYPE) 30struct epoll_params { 31 uint32_t busy_poll_usecs; 32 uint16_t busy_poll_budget; 33 uint8_t prefer_busy_poll; 34 35 /* pad the struct to a multiple of 64bits */ 36 uint8_t __pad; 37}; 38 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 43 44FIXTURE(invalid_fd) 45{ 46 int invalid_fd; 47 struct epoll_params params; 48}; 49 50FIXTURE_SETUP(invalid_fd) 51{ 52 int ret; 53 54 ret = socket(AF_UNIX, SOCK_DGRAM, 0); 55 EXPECT_NE(-1, ret) 56 TH_LOG("error creating unix socket"); 57 58 self->invalid_fd = ret; 59} 60 61FIXTURE_TEARDOWN(invalid_fd) 62{ 63 int ret; 64 65 ret = close(self->invalid_fd); 66 EXPECT_EQ(0, ret); 67} 68 69TEST_F(invalid_fd, test_invalid_fd) 70{ 71 int ret; 72 73 ret = ioctl(self->invalid_fd, EPIOCGPARAMS, &self->params); 74 75 EXPECT_EQ(-1, ret) 76 TH_LOG("EPIOCGPARAMS on invalid epoll FD should error"); 77 78 EXPECT_EQ(ENOTTY, errno) 79 TH_LOG("EPIOCGPARAMS on invalid epoll FD should set errno to ENOTTY"); 80 81 memset(&self->params, 0, sizeof(struct epoll_params)); 82 83 ret = ioctl(self->invalid_fd, EPIOCSPARAMS, &self->params); 84 85 EXPECT_EQ(-1, ret) 86 TH_LOG("EPIOCSPARAMS on invalid epoll FD should error"); 87 88 EXPECT_EQ(ENOTTY, errno) 89 TH_LOG("EPIOCSPARAMS on invalid epoll FD should set errno to ENOTTY"); 90} 91 92FIXTURE(epoll_busy_poll) 93{ 94 int fd; 95 struct epoll_params params; 96 struct epoll_params *invalid_params; 97 cap_t caps; 98}; 99 100FIXTURE_SETUP(epoll_busy_poll) 101{ 102 int ret; 103 104 ret = epoll_create1(0); 105 EXPECT_NE(-1, ret) 106 TH_LOG("epoll_create1 failed?"); 107 108 self->fd = ret; 109 110 self->caps = cap_get_proc(); 111 EXPECT_NE(NULL, self->caps); 112} 113 114FIXTURE_TEARDOWN(epoll_busy_poll) 115{ 116 int ret; 117 118 ret = close(self->fd); 119 EXPECT_EQ(0, ret); 120 121 ret = cap_free(self->caps); 122 EXPECT_NE(-1, ret) 123 TH_LOG("unable to free capabilities"); 124} 125 126TEST_F(epoll_busy_poll, test_get_params) 127{ 128 /* begin by getting the epoll params from the kernel 129 * 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. 132 */ 133 int ret = 0; 134 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; 139 140 ret = ioctl(self->fd, EPIOCGPARAMS, &self->params); 141 EXPECT_EQ(0, ret) 142 TH_LOG("ioctl EPIOCGPARAMS should succeed"); 143 144 EXPECT_EQ(0, self->params.busy_poll_usecs) 145 TH_LOG("EPIOCGPARAMS busy_poll_usecs should have been 0"); 146 147 EXPECT_EQ(0, self->params.busy_poll_budget) 148 TH_LOG("EPIOCGPARAMS busy_poll_budget should have been 0"); 149 150 EXPECT_EQ(0, self->params.prefer_busy_poll) 151 TH_LOG("EPIOCGPARAMS prefer_busy_poll should have been 0"); 152 153 EXPECT_EQ(0, self->params.__pad) 154 TH_LOG("EPIOCGPARAMS __pad should have been 0"); 155 156 self->invalid_params = (struct epoll_params *)0xdeadbeef; 157 ret = ioctl(self->fd, EPIOCGPARAMS, self->invalid_params); 158 159 EXPECT_EQ(-1, ret) 160 TH_LOG("EPIOCGPARAMS should error with invalid params"); 161 162 EXPECT_EQ(EFAULT, errno) 163 TH_LOG("EPIOCGPARAMS with invalid params should set errno to EFAULT"); 164} 165 166TEST_F(epoll_busy_poll, test_set_invalid) 167{ 168 int ret; 169 170 memset(&self->params, 0, sizeof(struct epoll_params)); 171 172 self->params.__pad = 1; 173 174 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params); 175 176 EXPECT_EQ(-1, ret) 177 TH_LOG("EPIOCSPARAMS non-zero __pad should error"); 178 179 EXPECT_EQ(EINVAL, errno) 180 TH_LOG("EPIOCSPARAMS non-zero __pad errno should be EINVAL"); 181 182 self->params.__pad = 0; 183 self->params.busy_poll_usecs = (uint32_t)INT_MAX + 1; 184 185 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params); 186 187 EXPECT_EQ(-1, ret) 188 TH_LOG("EPIOCSPARAMS should error busy_poll_usecs > S32_MAX"); 189 190 EXPECT_EQ(EINVAL, errno) 191 TH_LOG("EPIOCSPARAMS busy_poll_usecs > S32_MAX errno should be EINVAL"); 192 193 self->params.__pad = 0; 194 self->params.busy_poll_usecs = 32; 195 self->params.prefer_busy_poll = 2; 196 197 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params); 198 199 EXPECT_EQ(-1, ret) 200 TH_LOG("EPIOCSPARAMS should error prefer_busy_poll > 1"); 201 202 EXPECT_EQ(EINVAL, errno) 203 TH_LOG("EPIOCSPARAMS prefer_busy_poll > 1 errno should be EINVAL"); 204 205 self->params.__pad = 0; 206 self->params.busy_poll_usecs = 32; 207 self->params.prefer_busy_poll = 1; 208 209 /* set budget well above kernel's NAPI_POLL_WEIGHT of 64 */ 210 self->params.busy_poll_budget = UINT16_MAX; 211 212 /* test harness should run with CAP_NET_ADMIN, but let's make sure */ 213 cap_flag_value_t tmp; 214 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"); 218 219 EXPECT_EQ(CAP_SET, tmp) 220 TH_LOG("expecting CAP_NET_ADMIN to be set for the test harness"); 221 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 224 */ 225 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params); 226 227 EXPECT_EQ(0, ret) 228 TH_LOG("EPIOCSPARAMS should allow busy_poll_budget > NAPI_POLL_WEIGHT"); 229 230 /* remove CAP_NET_ADMIN from our effective set */ 231 cap_value_t net_admin[] = { CAP_NET_ADMIN }; 232 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"); 236 237 ret = cap_set_proc(self->caps); 238 EXPECT_EQ(0, ret) 239 TH_LOG("cap_set_proc should drop CAP_NET_ADMIN"); 240 241 /* this is now expected to fail */ 242 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params); 243 244 EXPECT_EQ(-1, ret) 245 TH_LOG("EPIOCSPARAMS should error busy_poll_budget > NAPI_POLL_WEIGHT"); 246 247 EXPECT_EQ(EPERM, errno) 248 TH_LOG("EPIOCSPARAMS errno should be EPERM busy_poll_budget > NAPI_POLL_WEIGHT"); 249 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"); 254 255 ret = cap_set_proc(self->caps); 256 EXPECT_EQ(0, ret) 257 TH_LOG("cap_set_proc should set CAP_NET_ADMIN"); 258 259 self->invalid_params = (struct epoll_params *)0xdeadbeef; 260 ret = ioctl(self->fd, EPIOCSPARAMS, self->invalid_params); 261 262 EXPECT_EQ(-1, ret) 263 TH_LOG("EPIOCSPARAMS should error when epoll_params is invalid"); 264 265 EXPECT_EQ(EFAULT, errno) 266 TH_LOG("EPIOCSPARAMS should set errno to EFAULT when epoll_params is invalid"); 267} 268 269TEST_F(epoll_busy_poll, test_set_and_get_valid) 270{ 271 int ret; 272 273 memset(&self->params, 0, sizeof(struct epoll_params)); 274 275 self->params.busy_poll_usecs = 25; 276 self->params.busy_poll_budget = 16; 277 self->params.prefer_busy_poll = 1; 278 279 ret = ioctl(self->fd, EPIOCSPARAMS, &self->params); 280 281 EXPECT_EQ(0, ret) 282 TH_LOG("EPIOCSPARAMS with valid params should not error"); 283 284 /* check that the kernel returns the same values back */ 285 286 memset(&self->params, 0, sizeof(struct epoll_params)); 287 288 ret = ioctl(self->fd, EPIOCGPARAMS, &self->params); 289 290 EXPECT_EQ(0, ret) 291 TH_LOG("EPIOCGPARAMS should not error"); 292 293 EXPECT_EQ(25, self->params.busy_poll_usecs) 294 TH_LOG("params.busy_poll_usecs incorrect"); 295 296 EXPECT_EQ(16, self->params.busy_poll_budget) 297 TH_LOG("params.busy_poll_budget incorrect"); 298 299 EXPECT_EQ(1, self->params.prefer_busy_poll) 300 TH_LOG("params.prefer_busy_poll incorrect"); 301 302 EXPECT_EQ(0, self->params.__pad) 303 TH_LOG("params.__pad was not 0"); 304} 305 306TEST_F(epoll_busy_poll, test_invalid_ioctl) 307{ 308 int invalid_ioctl = EPIOCGPARAMS + 10; 309 int ret; 310 311 ret = ioctl(self->fd, invalid_ioctl, &self->params); 312 313 EXPECT_EQ(-1, ret) 314 TH_LOG("invalid ioctl should return error"); 315 316 EXPECT_EQ(EINVAL, errno) 317 TH_LOG("invalid ioctl should set errno to EINVAL"); 318} 319 320TEST_HARNESS_MAIN