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 <john.fastabend@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Link: https://lore.kernel.org/bpf/20230523025618.113937-11-john.fastabend@gmail.com
This commit is contained in:
John Fastabend
2023-05-22 19:56:14 -07:00
committed by Daniel Borkmann
parent 4e02588d9a
commit 298970c8af
2 changed files with 123 additions and 102 deletions

View File

@@ -269,4 +269,122 @@ static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
return (struct sockaddr *)ss;
}
static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
{
u64 value;
u32 key;
int err;
key = 0;
value = fd1;
err = xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
if (err)
return err;
key = 1;
value = fd2;
return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
}
static inline int create_pair(int s, int family, int sotype, int *c, int *p)
{
struct sockaddr_storage addr;
socklen_t len;
int err = 0;
len = sizeof(addr);
err = xgetsockname(s, sockaddr(&addr), &len);
if (err)
return err;
*c = xsocket(family, sotype, 0);
if (*c < 0)
return errno;
err = xconnect(*c, sockaddr(&addr), len);
if (err) {
err = errno;
goto close_cli0;
}
*p = xaccept_nonblock(s, NULL, NULL);
if (*p < 0) {
err = errno;
goto close_cli0;
}
return err;
close_cli0:
close(*c);
return err;
}
static inline int create_socket_pairs(int s, int family, int sotype,
int *c0, int *c1, int *p0, int *p1)
{
int err;
err = create_pair(s, family, sotype, c0, p0);
if (err)
return err;
err = create_pair(s, family, sotype, c1, p1);
if (err) {
close(*c0);
close(*p0);
}
return err;
}
static inline int enable_reuseport(int s, int progfd)
{
int err, one = 1;
err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
if (err)
return -1;
err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
sizeof(progfd));
if (err)
return -1;
return 0;
}
static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
{
struct sockaddr_storage addr;
socklen_t len;
int err, s;
init_addr_loopback(family, &addr, &len);
s = xsocket(family, sotype, 0);
if (s == -1)
return -1;
if (progfd >= 0)
enable_reuseport(s, progfd);
err = xbind(s, sockaddr(&addr), len);
if (err)
goto close;
if (sotype & SOCK_DGRAM)
return s;
err = xlisten(s, SOMAXCONN);
if (err)
goto close;
return s;
close:
xclose(s);
return -1;
}
static inline int socket_loopback(int family, int sotype)
{
return socket_loopback_reuseport(family, sotype, -1);
}
#endif // __SOCKMAP_HELPERS__