Skip to content

Commit 298970c

Browse files
jrfastabborkmann
authored andcommitted
bpf, sockmap: Build helper to create connected socket pair
A common operation for testing is to spin up a pair of sockets that are connected. Then we can use these to run specific tests that need to send data, check BPF programs and so on. The sockmap_listen programs already have this logic lets move it into the new sockmap_helpers header file for general use. 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 4e02588 commit 298970c

File tree

2 files changed

+123
-102
lines changed

2 files changed

+123
-102
lines changed

tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,4 +269,122 @@ static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
269269
return (struct sockaddr *)ss;
270270
}
271271

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+
272390
#endif // __SOCKMAP_HELPERS__

tools/testing/selftests/bpf/prog_tests/sockmap_listen.c

Lines changed: 5 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -29,58 +29,6 @@
2929

3030
#include "sockmap_helpers.h"
3131

32-
static int enable_reuseport(int s, int progfd)
33-
{
34-
int err, one = 1;
35-
36-
err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
37-
if (err)
38-
return -1;
39-
err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
40-
sizeof(progfd));
41-
if (err)
42-
return -1;
43-
44-
return 0;
45-
}
46-
47-
static int socket_loopback_reuseport(int family, int sotype, int progfd)
48-
{
49-
struct sockaddr_storage addr;
50-
socklen_t len;
51-
int err, s;
52-
53-
init_addr_loopback(family, &addr, &len);
54-
55-
s = xsocket(family, sotype, 0);
56-
if (s == -1)
57-
return -1;
58-
59-
if (progfd >= 0)
60-
enable_reuseport(s, progfd);
61-
62-
err = xbind(s, sockaddr(&addr), len);
63-
if (err)
64-
goto close;
65-
66-
if (sotype & SOCK_DGRAM)
67-
return s;
68-
69-
err = xlisten(s, SOMAXCONN);
70-
if (err)
71-
goto close;
72-
73-
return s;
74-
close:
75-
xclose(s);
76-
return -1;
77-
}
78-
79-
static int socket_loopback(int family, int sotype)
80-
{
81-
return socket_loopback_reuseport(family, sotype, -1);
82-
}
83-
8432
static void test_insert_invalid(struct test_sockmap_listen *skel __always_unused,
8533
int family, int sotype, int mapfd)
8634
{
@@ -723,31 +671,12 @@ static const char *redir_mode_str(enum redir_mode mode)
723671
}
724672
}
725673

726-
static int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
727-
{
728-
u64 value;
729-
u32 key;
730-
int err;
731-
732-
key = 0;
733-
value = fd1;
734-
err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
735-
if (err)
736-
return err;
737-
738-
key = 1;
739-
value = fd2;
740-
return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
741-
}
742-
743674
static void redir_to_connected(int family, int sotype, int sock_mapfd,
744675
int verd_mapfd, enum redir_mode mode)
745676
{
746677
const char *log_prefix = redir_mode_str(mode);
747-
struct sockaddr_storage addr;
748678
int s, c0, c1, p0, p1;
749679
unsigned int pass;
750-
socklen_t len;
751680
int err, n;
752681
u32 key;
753682
char b;
@@ -758,49 +687,26 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
758687
if (s < 0)
759688
return;
760689

761-
len = sizeof(addr);
762-
err = xgetsockname(s, sockaddr(&addr), &len);
690+
err = create_socket_pairs(s, family, sotype, &c0, &c1, &p0, &p1);
763691
if (err)
764692
goto close_srv;
765693

766-
c0 = xsocket(family, sotype, 0);
767-
if (c0 < 0)
768-
goto close_srv;
769-
err = xconnect(c0, sockaddr(&addr), len);
770-
if (err)
771-
goto close_cli0;
772-
773-
p0 = xaccept_nonblock(s, NULL, NULL);
774-
if (p0 < 0)
775-
goto close_cli0;
776-
777-
c1 = xsocket(family, sotype, 0);
778-
if (c1 < 0)
779-
goto close_peer0;
780-
err = xconnect(c1, sockaddr(&addr), len);
781-
if (err)
782-
goto close_cli1;
783-
784-
p1 = xaccept_nonblock(s, NULL, NULL);
785-
if (p1 < 0)
786-
goto close_cli1;
787-
788694
err = add_to_sockmap(sock_mapfd, p0, p1);
789695
if (err)
790-
goto close_peer1;
696+
goto close;
791697

792698
n = write(mode == REDIR_INGRESS ? c1 : p1, "a", 1);
793699
if (n < 0)
794700
FAIL_ERRNO("%s: write", log_prefix);
795701
if (n == 0)
796702
FAIL("%s: incomplete write", log_prefix);
797703
if (n < 1)
798-
goto close_peer1;
704+
goto close;
799705

800706
key = SK_PASS;
801707
err = xbpf_map_lookup_elem(verd_mapfd, &key, &pass);
802708
if (err)
803-
goto close_peer1;
709+
goto close;
804710
if (pass != 1)
805711
FAIL("%s: want pass count 1, have %d", log_prefix, pass);
806712
n = recv_timeout(c0, &b, 1, 0, IO_TIMEOUT_SEC);
@@ -809,13 +715,10 @@ static void redir_to_connected(int family, int sotype, int sock_mapfd,
809715
if (n == 0)
810716
FAIL("%s: incomplete recv", log_prefix);
811717

812-
close_peer1:
718+
close:
813719
xclose(p1);
814-
close_cli1:
815720
xclose(c1);
816-
close_peer0:
817721
xclose(p0);
818-
close_cli0:
819722
xclose(c0);
820723
close_srv:
821724
xclose(s);

0 commit comments

Comments
 (0)