Skip to content

Commit 4e02588

Browse files
jrfastabborkmann
authored andcommitted
bpf, sockmap: Pull socket helpers out of listen test for general use
No functional change here we merely pull the helpers in sockmap_listen.c into a header file so we can use these in other programs. The tests we are about to add aren't really _listen tests so doesn't make sense to add them here. Signed-off-by: John Fastabend <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]> Reviewed-by: Jakub Sitnicki <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent e5c6de5 commit 4e02588

File tree

2 files changed

+273
-262
lines changed

2 files changed

+273
-262
lines changed
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
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+
#endif // __SOCKMAP_HELPERS__

0 commit comments

Comments
 (0)