1 #ifndef __SOCKMAP_HELPERS__ 2 #define __SOCKMAP_HELPERS__ 3 4 #include <linux/vm_sockets.h> 5 6 #define IO_TIMEOUT_SEC 30 7 #define MAX_STRERR_LEN 256 8 #define MAX_TEST_NAME 80 9 10 /* workaround for older vm_sockets.h */ 11 #ifndef VMADDR_CID_LOCAL 12 #define VMADDR_CID_LOCAL 1 13 #endif 14 15 #define __always_unused __attribute__((__unused__)) 16 17 #define _FAIL(errnum, fmt...) \ 18 ({ \ 19 error_at_line(0, (errnum), __func__, __LINE__, fmt); \ 20 CHECK_FAIL(true); \ 21 }) 22 #define FAIL(fmt...) _FAIL(0, fmt) 23 #define FAIL_ERRNO(fmt...) _FAIL(errno, fmt) 24 #define FAIL_LIBBPF(err, msg) \ 25 ({ \ 26 char __buf[MAX_STRERR_LEN]; \ 27 libbpf_strerror((err), __buf, sizeof(__buf)); \ 28 FAIL("%s: %s", (msg), __buf); \ 29 }) 30 31 /* Wrappers that fail the test on error and report it. */ 32 33 #define xaccept_nonblock(fd, addr, len) \ 34 ({ \ 35 int __ret = \ 36 accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC); \ 37 if (__ret == -1) \ 38 FAIL_ERRNO("accept"); \ 39 __ret; \ 40 }) 41 42 #define xbind(fd, addr, len) \ 43 ({ \ 44 int __ret = bind((fd), (addr), (len)); \ 45 if (__ret == -1) \ 46 FAIL_ERRNO("bind"); \ 47 __ret; \ 48 }) 49 50 #define xclose(fd) \ 51 ({ \ 52 int __ret = close((fd)); \ 53 if (__ret == -1) \ 54 FAIL_ERRNO("close"); \ 55 __ret; \ 56 }) 57 58 #define xconnect(fd, addr, len) \ 59 ({ \ 60 int __ret = connect((fd), (addr), (len)); \ 61 if (__ret == -1) \ 62 FAIL_ERRNO("connect"); \ 63 __ret; \ 64 }) 65 66 #define xgetsockname(fd, addr, len) \ 67 ({ \ 68 int __ret = getsockname((fd), (addr), (len)); \ 69 if (__ret == -1) \ 70 FAIL_ERRNO("getsockname"); \ 71 __ret; \ 72 }) 73 74 #define xgetsockopt(fd, level, name, val, len) \ 75 ({ \ 76 int __ret = getsockopt((fd), (level), (name), (val), (len)); \ 77 if (__ret == -1) \ 78 FAIL_ERRNO("getsockopt(" #name ")"); \ 79 __ret; \ 80 }) 81 82 #define xlisten(fd, backlog) \ 83 ({ \ 84 int __ret = listen((fd), (backlog)); \ 85 if (__ret == -1) \ 86 FAIL_ERRNO("listen"); \ 87 __ret; \ 88 }) 89 90 #define xsetsockopt(fd, level, name, val, len) \ 91 ({ \ 92 int __ret = setsockopt((fd), (level), (name), (val), (len)); \ 93 if (__ret == -1) \ 94 FAIL_ERRNO("setsockopt(" #name ")"); \ 95 __ret; \ 96 }) 97 98 #define xsend(fd, buf, len, flags) \ 99 ({ \ 100 ssize_t __ret = send((fd), (buf), (len), (flags)); \ 101 if (__ret == -1) \ 102 FAIL_ERRNO("send"); \ 103 __ret; \ 104 }) 105 106 #define xrecv_nonblock(fd, buf, len, flags) \ 107 ({ \ 108 ssize_t __ret = recv_timeout((fd), (buf), (len), (flags), \ 109 IO_TIMEOUT_SEC); \ 110 if (__ret == -1) \ 111 FAIL_ERRNO("recv"); \ 112 __ret; \ 113 }) 114 115 #define xsocket(family, sotype, flags) \ 116 ({ \ 117 int __ret = socket(family, sotype, flags); \ 118 if (__ret == -1) \ 119 FAIL_ERRNO("socket"); \ 120 __ret; \ 121 }) 122 123 #define xbpf_map_delete_elem(fd, key) \ 124 ({ \ 125 int __ret = bpf_map_delete_elem((fd), (key)); \ 126 if (__ret < 0) \ 127 FAIL_ERRNO("map_delete"); \ 128 __ret; \ 129 }) 130 131 #define xbpf_map_lookup_elem(fd, key, val) \ 132 ({ \ 133 int __ret = bpf_map_lookup_elem((fd), (key), (val)); \ 134 if (__ret < 0) \ 135 FAIL_ERRNO("map_lookup"); \ 136 __ret; \ 137 }) 138 139 #define xbpf_map_update_elem(fd, key, val, flags) \ 140 ({ \ 141 int __ret = bpf_map_update_elem((fd), (key), (val), (flags)); \ 142 if (__ret < 0) \ 143 FAIL_ERRNO("map_update"); \ 144 __ret; \ 145 }) 146 147 #define xbpf_prog_attach(prog, target, type, flags) \ 148 ({ \ 149 int __ret = \ 150 bpf_prog_attach((prog), (target), (type), (flags)); \ 151 if (__ret < 0) \ 152 FAIL_ERRNO("prog_attach(" #type ")"); \ 153 __ret; \ 154 }) 155 156 #define xbpf_prog_detach2(prog, target, type) \ 157 ({ \ 158 int __ret = bpf_prog_detach2((prog), (target), (type)); \ 159 if (__ret < 0) \ 160 FAIL_ERRNO("prog_detach2(" #type ")"); \ 161 __ret; \ 162 }) 163 164 #define xpthread_create(thread, attr, func, arg) \ 165 ({ \ 166 int __ret = pthread_create((thread), (attr), (func), (arg)); \ 167 errno = __ret; \ 168 if (__ret) \ 169 FAIL_ERRNO("pthread_create"); \ 170 __ret; \ 171 }) 172 173 #define xpthread_join(thread, retval) \ 174 ({ \ 175 int __ret = pthread_join((thread), (retval)); \ 176 errno = __ret; \ 177 if (__ret) \ 178 FAIL_ERRNO("pthread_join"); \ 179 __ret; \ 180 }) 181 182 static inline int poll_read(int fd, unsigned int timeout_sec) 183 { 184 struct timeval timeout = { .tv_sec = timeout_sec }; 185 fd_set rfds; 186 int r; 187 188 FD_ZERO(&rfds); 189 FD_SET(fd, &rfds); 190 191 r = select(fd + 1, &rfds, NULL, NULL, &timeout); 192 if (r == 0) 193 errno = ETIME; 194 195 return r == 1 ? 0 : -1; 196 } 197 198 static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len, 199 unsigned int timeout_sec) 200 { 201 if (poll_read(fd, timeout_sec)) 202 return -1; 203 204 return accept(fd, addr, len); 205 } 206 207 static inline int recv_timeout(int fd, void *buf, size_t len, int flags, 208 unsigned int timeout_sec) 209 { 210 if (poll_read(fd, timeout_sec)) 211 return -1; 212 213 return recv(fd, buf, len, flags); 214 } 215 216 static inline void init_addr_loopback4(struct sockaddr_storage *ss, 217 socklen_t *len) 218 { 219 struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss)); 220 221 addr4->sin_family = AF_INET; 222 addr4->sin_port = 0; 223 addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK); 224 *len = sizeof(*addr4); 225 } 226 227 static inline void init_addr_loopback6(struct sockaddr_storage *ss, 228 socklen_t *len) 229 { 230 struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss)); 231 232 addr6->sin6_family = AF_INET6; 233 addr6->sin6_port = 0; 234 addr6->sin6_addr = in6addr_loopback; 235 *len = sizeof(*addr6); 236 } 237 238 static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss, 239 socklen_t *len) 240 { 241 struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss)); 242 243 addr->svm_family = AF_VSOCK; 244 addr->svm_port = VMADDR_PORT_ANY; 245 addr->svm_cid = VMADDR_CID_LOCAL; 246 *len = sizeof(*addr); 247 } 248 249 static inline void init_addr_loopback(int family, struct sockaddr_storage *ss, 250 socklen_t *len) 251 { 252 switch (family) { 253 case AF_INET: 254 init_addr_loopback4(ss, len); 255 return; 256 case AF_INET6: 257 init_addr_loopback6(ss, len); 258 return; 259 case AF_VSOCK: 260 init_addr_loopback_vsock(ss, len); 261 return; 262 default: 263 FAIL("unsupported address family %d", family); 264 } 265 } 266 267 static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss) 268 { 269 return (struct sockaddr *)ss; 270 } 271 272 static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2) 273 { 274 u64 value; 275 u32 key; 276 int err; 277 278 key = 0; 279 value = fd1; 280 err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST); 281 if (err) 282 return err; 283 284 key = 1; 285 value = fd2; 286 return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST); 287 } 288 289 static inline int create_pair(int s, int family, int sotype, int *c, int *p) 290 { 291 struct sockaddr_storage addr; 292 socklen_t len; 293 int err = 0; 294 295 len = sizeof(addr); 296 err = xgetsockname(s, sockaddr(&addr), &len); 297 if (err) 298 return err; 299 300 *c = xsocket(family, sotype, 0); 301 if (*c < 0) 302 return errno; 303 err = xconnect(*c, sockaddr(&addr), len); 304 if (err) { 305 err = errno; 306 goto close_cli0; 307 } 308 309 *p = xaccept_nonblock(s, NULL, NULL); 310 if (*p < 0) { 311 err = errno; 312 goto close_cli0; 313 } 314 return err; 315 close_cli0: 316 close(*c); 317 return err; 318 } 319 320 static inline int create_socket_pairs(int s, int family, int sotype, 321 int *c0, int *c1, int *p0, int *p1) 322 { 323 int err; 324 325 err = create_pair(s, family, sotype, c0, p0); 326 if (err) 327 return err; 328 329 err = create_pair(s, family, sotype, c1, p1); 330 if (err) { 331 close(*c0); 332 close(*p0); 333 } 334 return err; 335 } 336 337 static inline int enable_reuseport(int s, int progfd) 338 { 339 int err, one = 1; 340 341 err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)); 342 if (err) 343 return -1; 344 err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd, 345 sizeof(progfd)); 346 if (err) 347 return -1; 348 349 return 0; 350 } 351 352 static inline int socket_loopback_reuseport(int family, int sotype, int progfd) 353 { 354 struct sockaddr_storage addr; 355 socklen_t len; 356 int err, s; 357 358 init_addr_loopback(family, &addr, &len); 359 360 s = xsocket(family, sotype, 0); 361 if (s == -1) 362 return -1; 363 364 if (progfd >= 0) 365 enable_reuseport(s, progfd); 366 367 err = xbind(s, sockaddr(&addr), len); 368 if (err) 369 goto close; 370 371 if (sotype & SOCK_DGRAM) 372 return s; 373 374 err = xlisten(s, SOMAXCONN); 375 if (err) 376 goto close; 377 378 return s; 379 close: 380 xclose(s); 381 return -1; 382 } 383 384 static inline int socket_loopback(int family, int sotype) 385 { 386 return socket_loopback_reuseport(family, sotype, -1); 387 } 388 389 390 #endif // __SOCKMAP_HELPERS__ 391