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:
Kuniyuki Iwashima 2022-01-13 09:28:48 +09:00 коммит произвёл Alexei Starovoitov
Родитель eb7d8f1d9e
Коммит 7ff8985cc1
3 изменённых файлов: 162 добавлений и 0 удалений

Просмотреть файл

@ -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