brintos

brintos / linux-shallow public Read only

0
0
Text · 7.8 KiB · 16e457c Raw
321 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2 3/* Basic per-epoll context busy poll test.4 *5 * Only tests the ioctls, but should be expanded to test two connected hosts in6 * the future7 */8 9#define _GNU_SOURCE10 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 0x8A40#define EPIOCSPARAMS _IOW(EPOLL_IOC_TYPE, 0x01, struct epoll_params)41#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)42#endif43 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 kernel129	 *130	 * the default should be default and all fields should be zero'd by the131	 * 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 the223	 * params with a busy_poll_budget > NAPI_POLL_WEIGHT should succeed224	 */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_MAIN321