~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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_connect(int fd, unsigned int timeout_sec)
183 {
184         struct timeval timeout = { .tv_sec = timeout_sec };
185         fd_set wfds;
186         int r, eval;
187         socklen_t esize = sizeof(eval);
188 
189         FD_ZERO(&wfds);
190         FD_SET(fd, &wfds);
191 
192         r = select(fd + 1, NULL, &wfds, NULL, &timeout);
193         if (r == 0)
194                 errno = ETIME;
195         if (r != 1)
196                 return -1;
197 
198         if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &eval, &esize) < 0)
199                 return -1;
200         if (eval != 0) {
201                 errno = eval;
202                 return -1;
203         }
204 
205         return 0;
206 }
207 
208 static inline int poll_read(int fd, unsigned int timeout_sec)
209 {
210         struct timeval timeout = { .tv_sec = timeout_sec };
211         fd_set rfds;
212         int r;
213 
214         FD_ZERO(&rfds);
215         FD_SET(fd, &rfds);
216 
217         r = select(fd + 1, &rfds, NULL, NULL, &timeout);
218         if (r == 0)
219                 errno = ETIME;
220 
221         return r == 1 ? 0 : -1;
222 }
223 
224 static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
225                                  unsigned int timeout_sec)
226 {
227         if (poll_read(fd, timeout_sec))
228                 return -1;
229 
230         return accept(fd, addr, len);
231 }
232 
233 static inline int recv_timeout(int fd, void *buf, size_t len, int flags,
234                                unsigned int timeout_sec)
235 {
236         if (poll_read(fd, timeout_sec))
237                 return -1;
238 
239         return recv(fd, buf, len, flags);
240 }
241 
242 static inline void init_addr_loopback4(struct sockaddr_storage *ss,
243                                        socklen_t *len)
244 {
245         struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
246 
247         addr4->sin_family = AF_INET;
248         addr4->sin_port = 0;
249         addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
250         *len = sizeof(*addr4);
251 }
252 
253 static inline void init_addr_loopback6(struct sockaddr_storage *ss,
254                                        socklen_t *len)
255 {
256         struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
257 
258         addr6->sin6_family = AF_INET6;
259         addr6->sin6_port = 0;
260         addr6->sin6_addr = in6addr_loopback;
261         *len = sizeof(*addr6);
262 }
263 
264 static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss,
265                                             socklen_t *len)
266 {
267         struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
268 
269         addr->svm_family = AF_VSOCK;
270         addr->svm_port = VMADDR_PORT_ANY;
271         addr->svm_cid = VMADDR_CID_LOCAL;
272         *len = sizeof(*addr);
273 }
274 
275 static inline void init_addr_loopback(int family, struct sockaddr_storage *ss,
276                                       socklen_t *len)
277 {
278         switch (family) {
279         case AF_INET:
280                 init_addr_loopback4(ss, len);
281                 return;
282         case AF_INET6:
283                 init_addr_loopback6(ss, len);
284                 return;
285         case AF_VSOCK:
286                 init_addr_loopback_vsock(ss, len);
287                 return;
288         default:
289                 FAIL("unsupported address family %d", family);
290         }
291 }
292 
293 static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
294 {
295         return (struct sockaddr *)ss;
296 }
297 
298 static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
299 {
300         u64 value;
301         u32 key;
302         int err;
303 
304         key = 0;
305         value = fd1;
306         err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
307         if (err)
308                 return err;
309 
310         key = 1;
311         value = fd2;
312         return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
313 }
314 
315 static inline int create_pair(int s, int family, int sotype, int *c, int *p)
316 {
317         struct sockaddr_storage addr;
318         socklen_t len;
319         int err = 0;
320 
321         len = sizeof(addr);
322         err = xgetsockname(s, sockaddr(&addr), &len);
323         if (err)
324                 return err;
325 
326         *c = xsocket(family, sotype, 0);
327         if (*c < 0)
328                 return errno;
329         err = xconnect(*c, sockaddr(&addr), len);
330         if (err) {
331                 err = errno;
332                 goto close_cli0;
333         }
334 
335         *p = xaccept_nonblock(s, NULL, NULL);
336         if (*p < 0) {
337                 err = errno;
338                 goto close_cli0;
339         }
340         return err;
341 close_cli0:
342         close(*c);
343         return err;
344 }
345 
346 static inline int create_socket_pairs(int s, int family, int sotype,
347                                       int *c0, int *c1, int *p0, int *p1)
348 {
349         int err;
350 
351         err = create_pair(s, family, sotype, c0, p0);
352         if (err)
353                 return err;
354 
355         err = create_pair(s, family, sotype, c1, p1);
356         if (err) {
357                 close(*c0);
358                 close(*p0);
359         }
360         return err;
361 }
362 
363 static inline int enable_reuseport(int s, int progfd)
364 {
365         int err, one = 1;
366 
367         err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
368         if (err)
369                 return -1;
370         err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
371                           sizeof(progfd));
372         if (err)
373                 return -1;
374 
375         return 0;
376 }
377 
378 static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
379 {
380         struct sockaddr_storage addr;
381         socklen_t len = 0;
382         int err, s;
383 
384         init_addr_loopback(family, &addr, &len);
385 
386         s = xsocket(family, sotype, 0);
387         if (s == -1)
388                 return -1;
389 
390         if (progfd >= 0)
391                 enable_reuseport(s, progfd);
392 
393         err = xbind(s, sockaddr(&addr), len);
394         if (err)
395                 goto close;
396 
397         if (sotype & SOCK_DGRAM)
398                 return s;
399 
400         err = xlisten(s, SOMAXCONN);
401         if (err)
402                 goto close;
403 
404         return s;
405 close:
406         xclose(s);
407         return -1;
408 }
409 
410 static inline int socket_loopback(int family, int sotype)
411 {
412         return socket_loopback_reuseport(family, sotype, -1);
413 }
414 
415 
416 #endif // __SOCKMAP_HELPERS__
417 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php