1 #ifndef __SOCKMAP_HELPERS__
2 #define __SOCKMAP_HELPERS__
4 #include <linux/vm_sockets.h>
6 #define IO_TIMEOUT_SEC 30
7 #define MAX_STRERR_LEN 256
8 #define MAX_TEST_NAME 80
10 /* workaround for older vm_sockets.h */
11 #ifndef VMADDR_CID_LOCAL
12 #define VMADDR_CID_LOCAL 1
15 #define __always_unused __attribute__((__unused__))
17 #define _FAIL(errnum, fmt...) \
19 error_at_line(0, (errnum), __func__, __LINE__, fmt); \
22 #define FAIL(fmt...) _FAIL(0, fmt)
23 #define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
24 #define FAIL_LIBBPF(err, msg) \
26 char __buf[MAX_STRERR_LEN]; \
27 libbpf_strerror((err), __buf, sizeof(__buf)); \
28 FAIL("%s: %s", (msg), __buf); \
31 /* Wrappers that fail the test on error and report it. */
33 #define xaccept_nonblock(fd, addr, len) \
36 accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC); \
38 FAIL_ERRNO("accept"); \
42 #define xbind(fd, addr, len) \
44 int __ret = bind((fd), (addr), (len)); \
52 int __ret = close((fd)); \
54 FAIL_ERRNO("close"); \
58 #define xconnect(fd, addr, len) \
60 int __ret = connect((fd), (addr), (len)); \
62 FAIL_ERRNO("connect"); \
66 #define xgetsockname(fd, addr, len) \
68 int __ret = getsockname((fd), (addr), (len)); \
70 FAIL_ERRNO("getsockname"); \
74 #define xgetsockopt(fd, level, name, val, len) \
76 int __ret = getsockopt((fd), (level), (name), (val), (len)); \
78 FAIL_ERRNO("getsockopt(" #name ")"); \
82 #define xlisten(fd, backlog) \
84 int __ret = listen((fd), (backlog)); \
86 FAIL_ERRNO("listen"); \
90 #define xsetsockopt(fd, level, name, val, len) \
92 int __ret = setsockopt((fd), (level), (name), (val), (len)); \
94 FAIL_ERRNO("setsockopt(" #name ")"); \
98 #define xsend(fd, buf, len, flags) \
100 ssize_t __ret = send((fd), (buf), (len), (flags)); \
102 FAIL_ERRNO("send"); \
106 #define xrecv_nonblock(fd, buf, len, flags) \
108 ssize_t __ret = recv_timeout((fd), (buf), (len), (flags), \
111 FAIL_ERRNO("recv"); \
115 #define xsocket(family, sotype, flags) \
117 int __ret = socket(family, sotype, flags); \
119 FAIL_ERRNO("socket"); \
123 #define xbpf_map_delete_elem(fd, key) \
125 int __ret = bpf_map_delete_elem((fd), (key)); \
127 FAIL_ERRNO("map_delete"); \
131 #define xbpf_map_lookup_elem(fd, key, val) \
133 int __ret = bpf_map_lookup_elem((fd), (key), (val)); \
135 FAIL_ERRNO("map_lookup"); \
139 #define xbpf_map_update_elem(fd, key, val, flags) \
141 int __ret = bpf_map_update_elem((fd), (key), (val), (flags)); \
143 FAIL_ERRNO("map_update"); \
147 #define xbpf_prog_attach(prog, target, type, flags) \
150 bpf_prog_attach((prog), (target), (type), (flags)); \
152 FAIL_ERRNO("prog_attach(" #type ")"); \
156 #define xbpf_prog_detach2(prog, target, type) \
158 int __ret = bpf_prog_detach2((prog), (target), (type)); \
160 FAIL_ERRNO("prog_detach2(" #type ")"); \
164 #define xpthread_create(thread, attr, func, arg) \
166 int __ret = pthread_create((thread), (attr), (func), (arg)); \
169 FAIL_ERRNO("pthread_create"); \
173 #define xpthread_join(thread, retval) \
175 int __ret = pthread_join((thread), (retval)); \
178 FAIL_ERRNO("pthread_join"); \
182 static inline int poll_connect(int fd, unsigned int timeout_sec)
184 struct timeval timeout = { .tv_sec = timeout_sec };
187 socklen_t esize = sizeof(eval);
192 r = select(fd + 1, NULL, &wfds, NULL, &timeout);
198 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &eval, &esize) < 0)
208 static inline int poll_read(int fd, unsigned int timeout_sec)
210 struct timeval timeout = { .tv_sec = timeout_sec };
217 r = select(fd + 1, &rfds, NULL, NULL, &timeout);
221 return r == 1 ? 0 : -1;
224 static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
225 unsigned int timeout_sec)
227 if (poll_read(fd, timeout_sec))
230 return accept(fd, addr, len);
233 static inline int recv_timeout(int fd, void *buf, size_t len, int flags,
234 unsigned int timeout_sec)
236 if (poll_read(fd, timeout_sec))
239 return recv(fd, buf, len, flags);
242 static inline void init_addr_loopback4(struct sockaddr_storage *ss,
245 struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
247 addr4->sin_family = AF_INET;
249 addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
250 *len = sizeof(*addr4);
253 static inline void init_addr_loopback6(struct sockaddr_storage *ss,
256 struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
258 addr6->sin6_family = AF_INET6;
259 addr6->sin6_port = 0;
260 addr6->sin6_addr = in6addr_loopback;
261 *len = sizeof(*addr6);
264 static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss,
267 struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
269 addr->svm_family = AF_VSOCK;
270 addr->svm_port = VMADDR_PORT_ANY;
271 addr->svm_cid = VMADDR_CID_LOCAL;
272 *len = sizeof(*addr);
275 static inline void init_addr_loopback(int family, struct sockaddr_storage *ss,
280 init_addr_loopback4(ss, len);
283 init_addr_loopback6(ss, len);
286 init_addr_loopback_vsock(ss, len);
289 FAIL("unsupported address family %d", family);
293 static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
295 return (struct sockaddr *)ss;
298 static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
306 err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
312 return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
315 static inline int create_pair(int s, int family, int sotype, int *c, int *p)
317 struct sockaddr_storage addr;
322 err = xgetsockname(s, sockaddr(&addr), &len);
326 *c = xsocket(family, sotype, 0);
329 err = xconnect(*c, sockaddr(&addr), len);
335 *p = xaccept_nonblock(s, NULL, NULL);
346 static inline int create_socket_pairs(int s, int family, int sotype,
347 int *c0, int *c1, int *p0, int *p1)
351 err = create_pair(s, family, sotype, c0, p0);
355 err = create_pair(s, family, sotype, c1, p1);
363 static inline int enable_reuseport(int s, int progfd)
367 err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
370 err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
378 static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
380 struct sockaddr_storage addr;
384 init_addr_loopback(family, &addr, &len);
386 s = xsocket(family, sotype, 0);
391 enable_reuseport(s, progfd);
393 err = xbind(s, sockaddr(&addr), len);
397 if (sotype & SOCK_DGRAM)
400 err = xlisten(s, SOMAXCONN);
410 static inline int socket_loopback(int family, int sotype)
412 return socket_loopback_reuseport(family, sotype, -1);
416 #endif // __SOCKMAP_HELPERS__