selftest/bpf: Test batching and bpf_(get|set)sockopt in bpf unix iter.
This patch adds a test for the batching and bpf_(get|set)sockopt in bpf unix iter. It does the following. 1. Creates an abstract UNIX domain socket 2. Call bpf_setsockopt() 3. Call bpf_getsockopt() and save the value 4. Call setsockopt() 5. Call getsockopt() and save the value 6. Compare the saved values Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp> Link: https://lore.kernel.org/r/20220113002849.4384-5-kuniyu@amazon.co.jp Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Родитель
eb7d8f1d9e
Коммит
7ff8985cc1
|
@ -0,0 +1,100 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright Amazon.com Inc. or its affiliates. */
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <test_progs.h>
|
||||
#include "bpf_iter_setsockopt_unix.skel.h"
|
||||
|
||||
#define NR_CASES 5
|
||||
|
||||
static int create_unix_socket(struct bpf_iter_setsockopt_unix *skel)
|
||||
{
|
||||
struct sockaddr_un addr = {
|
||||
.sun_family = AF_UNIX,
|
||||
.sun_path = "",
|
||||
};
|
||||
socklen_t len;
|
||||
int fd, err;
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (!ASSERT_NEQ(fd, -1, "socket"))
|
||||
return -1;
|
||||
|
||||
len = offsetof(struct sockaddr_un, sun_path);
|
||||
err = bind(fd, (struct sockaddr *)&addr, len);
|
||||
if (!ASSERT_OK(err, "bind"))
|
||||
return -1;
|
||||
|
||||
len = sizeof(addr);
|
||||
err = getsockname(fd, (struct sockaddr *)&addr, &len);
|
||||
if (!ASSERT_OK(err, "getsockname"))
|
||||
return -1;
|
||||
|
||||
memcpy(&skel->bss->sun_path, &addr.sun_path,
|
||||
len - offsetof(struct sockaddr_un, sun_path));
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static void test_sndbuf(struct bpf_iter_setsockopt_unix *skel, int fd)
|
||||
{
|
||||
socklen_t optlen;
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < NR_CASES; i++) {
|
||||
if (!ASSERT_NEQ(skel->data->sndbuf_getsockopt[i], -1,
|
||||
"bpf_(get|set)sockopt"))
|
||||
return;
|
||||
|
||||
err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
|
||||
&(skel->data->sndbuf_setsockopt[i]),
|
||||
sizeof(skel->data->sndbuf_setsockopt[i]));
|
||||
if (!ASSERT_OK(err, "setsockopt"))
|
||||
return;
|
||||
|
||||
optlen = sizeof(skel->bss->sndbuf_getsockopt_expected[i]);
|
||||
err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF,
|
||||
&(skel->bss->sndbuf_getsockopt_expected[i]),
|
||||
&optlen);
|
||||
if (!ASSERT_OK(err, "getsockopt"))
|
||||
return;
|
||||
|
||||
if (!ASSERT_EQ(skel->data->sndbuf_getsockopt[i],
|
||||
skel->bss->sndbuf_getsockopt_expected[i],
|
||||
"bpf_(get|set)sockopt"))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void test_bpf_iter_setsockopt_unix(void)
|
||||
{
|
||||
struct bpf_iter_setsockopt_unix *skel;
|
||||
int err, unix_fd, iter_fd;
|
||||
char buf;
|
||||
|
||||
skel = bpf_iter_setsockopt_unix__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "open_and_load"))
|
||||
return;
|
||||
|
||||
unix_fd = create_unix_socket(skel);
|
||||
if (!ASSERT_NEQ(unix_fd, -1, "create_unix_server"))
|
||||
goto destroy;
|
||||
|
||||
skel->links.change_sndbuf = bpf_program__attach_iter(skel->progs.change_sndbuf, NULL);
|
||||
if (!ASSERT_OK_PTR(skel->links.change_sndbuf, "bpf_program__attach_iter"))
|
||||
goto destroy;
|
||||
|
||||
iter_fd = bpf_iter_create(bpf_link__fd(skel->links.change_sndbuf));
|
||||
if (!ASSERT_GE(iter_fd, 0, "bpf_iter_create"))
|
||||
goto destroy;
|
||||
|
||||
while ((err = read(iter_fd, &buf, sizeof(buf))) == -1 &&
|
||||
errno == EAGAIN)
|
||||
;
|
||||
if (!ASSERT_OK(err, "read iter error"))
|
||||
goto destroy;
|
||||
|
||||
test_sndbuf(skel, unix_fd);
|
||||
destroy:
|
||||
bpf_iter_setsockopt_unix__destroy(skel);
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright Amazon.com Inc. or its affiliates. */
|
||||
#include "bpf_iter.h"
|
||||
#include "bpf_tracing_net.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define AUTOBIND_LEN 6
|
||||
char sun_path[AUTOBIND_LEN];
|
||||
|
||||
#define NR_CASES 5
|
||||
int sndbuf_setsockopt[NR_CASES] = {-1, 0, 8192, INT_MAX / 2, INT_MAX};
|
||||
int sndbuf_getsockopt[NR_CASES] = {-1, -1, -1, -1, -1};
|
||||
int sndbuf_getsockopt_expected[NR_CASES];
|
||||
|
||||
static inline int cmpname(struct unix_sock *unix_sk)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AUTOBIND_LEN; i++) {
|
||||
if (unix_sk->addr->name->sun_path[i] != sun_path[i])
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("iter/unix")
|
||||
int change_sndbuf(struct bpf_iter__unix *ctx)
|
||||
{
|
||||
struct unix_sock *unix_sk = ctx->unix_sk;
|
||||
int i, err;
|
||||
|
||||
if (!unix_sk || !unix_sk->addr)
|
||||
return 0;
|
||||
|
||||
if (unix_sk->addr->name->sun_path[0])
|
||||
return 0;
|
||||
|
||||
if (cmpname(unix_sk))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < NR_CASES; i++) {
|
||||
err = bpf_setsockopt(unix_sk, SOL_SOCKET, SO_SNDBUF,
|
||||
&sndbuf_setsockopt[i],
|
||||
sizeof(sndbuf_setsockopt[i]));
|
||||
if (err)
|
||||
break;
|
||||
|
||||
err = bpf_getsockopt(unix_sk, SOL_SOCKET, SO_SNDBUF,
|
||||
&sndbuf_getsockopt[i],
|
||||
sizeof(sndbuf_getsockopt[i]));
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
|
@ -5,6 +5,8 @@
|
|||
#define AF_INET 2
|
||||
#define AF_INET6 10
|
||||
|
||||
#define SOL_SOCKET 1
|
||||
#define SO_SNDBUF 7
|
||||
#define __SO_ACCEPTCON (1 << 16)
|
||||
|
||||
#define SOL_TCP 6
|
||||
|
|
Загрузка…
Ссылка в новой задаче