Merge branch 'selftests/bpf: Migrate test_tcpbpf_user to be a part of test_progs'
Alexander Duyck says: ==================== Move the test functionality from test_tcpbpf_user into the test_progs framework so that it will be run any time the test_progs framework is run. This will help to prevent future test escapes as the individual tests, such as test_tcpbpf_user, are less likely to be run by developers and CI tests. As a part of moving it over the series goes through and updates the code to make use of the existing APIs included in the test_progs framework. This is meant to simplify and streamline the test code and avoid duplication of effort. v2: Dropped test_tcpbpf_user from .gitignore Replaced CHECK_FAIL calls with CHECK calls Minimized changes in patch 1 when moving the file Updated stg mail command line to display renames in submission Added shutdown logic to end of run_test function to guarantee close Added patch that replaces the two maps with use of global variables v3: Left err at -1 while we are performing send/recv calls w/ data Drop extra labels from test_tcpbpf_user in favor of keeping err label Dropped redundant zero init for tcpbpf_globals result and key Dropped replacing of "printf(" with "fprintf(stderr, " Fixed error in use of ASSERT_OK_PTR which was skipping of run_test Replaced "{ 0 }" with "{}" in init of global in test_tcpbpf_kern.c Added "Acked-by" from Martin KaiFai Lau and Andrii Nakryiko ==================== Acked-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
d0b3d2d7e5
1
tools/testing/selftests/bpf/.gitignore
vendored
1
tools/testing/selftests/bpf/.gitignore
vendored
@ -8,7 +8,6 @@ FEATURE-DUMP.libbpf
|
||||
fixdep
|
||||
test_dev_cgroup
|
||||
/test_progs*
|
||||
test_tcpbpf_user
|
||||
test_verifier_log
|
||||
feature
|
||||
test_sock
|
||||
|
@ -32,7 +32,7 @@ LDLIBS += -lcap -lelf -lz -lrt -lpthread
|
||||
|
||||
# Order correspond to 'make run_tests' order
|
||||
TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
|
||||
test_verifier_log test_dev_cgroup test_tcpbpf_user \
|
||||
test_verifier_log test_dev_cgroup \
|
||||
test_sock test_sockmap get_cgroup_id_user test_socket_cookie \
|
||||
test_cgroup_storage \
|
||||
test_netcnt test_tcpnotify_user test_sysctl \
|
||||
@ -163,7 +163,6 @@ $(OUTPUT)/test_sock: cgroup_helpers.c
|
||||
$(OUTPUT)/test_sock_addr: cgroup_helpers.c
|
||||
$(OUTPUT)/test_socket_cookie: cgroup_helpers.c
|
||||
$(OUTPUT)/test_sockmap: cgroup_helpers.c
|
||||
$(OUTPUT)/test_tcpbpf_user: cgroup_helpers.c
|
||||
$(OUTPUT)/test_tcpnotify_user: cgroup_helpers.c trace_helpers.c
|
||||
$(OUTPUT)/get_cgroup_id_user: cgroup_helpers.c
|
||||
$(OUTPUT)/test_cgroup_storage: cgroup_helpers.c
|
||||
|
141
tools/testing/selftests/bpf/prog_tests/tcpbpf_user.c
Normal file
141
tools/testing/selftests/bpf/prog_tests/tcpbpf_user.c
Normal file
@ -0,0 +1,141 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <test_progs.h>
|
||||
#include <network_helpers.h>
|
||||
|
||||
#include "test_tcpbpf.h"
|
||||
#include "test_tcpbpf_kern.skel.h"
|
||||
|
||||
#define LO_ADDR6 "::1"
|
||||
#define CG_NAME "/tcpbpf-user-test"
|
||||
|
||||
static __u32 duration;
|
||||
|
||||
static void verify_result(struct tcpbpf_globals *result)
|
||||
{
|
||||
__u32 expected_events = ((1 << BPF_SOCK_OPS_TIMEOUT_INIT) |
|
||||
(1 << BPF_SOCK_OPS_RWND_INIT) |
|
||||
(1 << BPF_SOCK_OPS_TCP_CONNECT_CB) |
|
||||
(1 << BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) |
|
||||
(1 << BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB) |
|
||||
(1 << BPF_SOCK_OPS_NEEDS_ECN) |
|
||||
(1 << BPF_SOCK_OPS_STATE_CB) |
|
||||
(1 << BPF_SOCK_OPS_TCP_LISTEN_CB));
|
||||
|
||||
/* check global map */
|
||||
CHECK(expected_events != result->event_map, "event_map",
|
||||
"unexpected event_map: actual 0x%08x != expected 0x%08x\n",
|
||||
result->event_map, expected_events);
|
||||
|
||||
ASSERT_EQ(result->bytes_received, 501, "bytes_received");
|
||||
ASSERT_EQ(result->bytes_acked, 1002, "bytes_acked");
|
||||
ASSERT_EQ(result->data_segs_in, 1, "data_segs_in");
|
||||
ASSERT_EQ(result->data_segs_out, 1, "data_segs_out");
|
||||
ASSERT_EQ(result->bad_cb_test_rv, 0x80, "bad_cb_test_rv");
|
||||
ASSERT_EQ(result->good_cb_test_rv, 0, "good_cb_test_rv");
|
||||
ASSERT_EQ(result->num_listen, 1, "num_listen");
|
||||
|
||||
/* 3 comes from one listening socket + both ends of the connection */
|
||||
ASSERT_EQ(result->num_close_events, 3, "num_close_events");
|
||||
|
||||
/* check setsockopt for SAVE_SYN */
|
||||
ASSERT_EQ(result->tcp_save_syn, 0, "tcp_save_syn");
|
||||
|
||||
/* check getsockopt for SAVED_SYN */
|
||||
ASSERT_EQ(result->tcp_saved_syn, 1, "tcp_saved_syn");
|
||||
}
|
||||
|
||||
static void run_test(struct tcpbpf_globals *result)
|
||||
{
|
||||
int listen_fd = -1, cli_fd = -1, accept_fd = -1;
|
||||
char buf[1000];
|
||||
int err = -1;
|
||||
int i, rv;
|
||||
|
||||
listen_fd = start_server(AF_INET6, SOCK_STREAM, LO_ADDR6, 0, 0);
|
||||
if (CHECK(listen_fd == -1, "start_server", "listen_fd:%d errno:%d\n",
|
||||
listen_fd, errno))
|
||||
goto done;
|
||||
|
||||
cli_fd = connect_to_fd(listen_fd, 0);
|
||||
if (CHECK(cli_fd == -1, "connect_to_fd(listen_fd)",
|
||||
"cli_fd:%d errno:%d\n", cli_fd, errno))
|
||||
goto done;
|
||||
|
||||
accept_fd = accept(listen_fd, NULL, NULL);
|
||||
if (CHECK(accept_fd == -1, "accept(listen_fd)",
|
||||
"accept_fd:%d errno:%d\n", accept_fd, errno))
|
||||
goto done;
|
||||
|
||||
/* Send 1000B of '+'s from cli_fd -> accept_fd */
|
||||
for (i = 0; i < 1000; i++)
|
||||
buf[i] = '+';
|
||||
|
||||
rv = send(cli_fd, buf, 1000, 0);
|
||||
if (CHECK(rv != 1000, "send(cli_fd)", "rv:%d errno:%d\n", rv, errno))
|
||||
goto done;
|
||||
|
||||
rv = recv(accept_fd, buf, 1000, 0);
|
||||
if (CHECK(rv != 1000, "recv(accept_fd)", "rv:%d errno:%d\n", rv, errno))
|
||||
goto done;
|
||||
|
||||
/* Send 500B of '.'s from accept_fd ->cli_fd */
|
||||
for (i = 0; i < 500; i++)
|
||||
buf[i] = '.';
|
||||
|
||||
rv = send(accept_fd, buf, 500, 0);
|
||||
if (CHECK(rv != 500, "send(accept_fd)", "rv:%d errno:%d\n", rv, errno))
|
||||
goto done;
|
||||
|
||||
rv = recv(cli_fd, buf, 500, 0);
|
||||
if (CHECK(rv != 500, "recv(cli_fd)", "rv:%d errno:%d\n", rv, errno))
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* shutdown accept first to guarantee correct ordering for
|
||||
* bytes_received and bytes_acked when we go to verify the results.
|
||||
*/
|
||||
shutdown(accept_fd, SHUT_WR);
|
||||
err = recv(cli_fd, buf, 1, 0);
|
||||
if (CHECK(err, "recv(cli_fd) for fin", "err:%d errno:%d\n", err, errno))
|
||||
goto done;
|
||||
|
||||
shutdown(cli_fd, SHUT_WR);
|
||||
err = recv(accept_fd, buf, 1, 0);
|
||||
CHECK(err, "recv(accept_fd) for fin", "err:%d errno:%d\n", err, errno);
|
||||
done:
|
||||
if (accept_fd != -1)
|
||||
close(accept_fd);
|
||||
if (cli_fd != -1)
|
||||
close(cli_fd);
|
||||
if (listen_fd != -1)
|
||||
close(listen_fd);
|
||||
|
||||
if (!err)
|
||||
verify_result(result);
|
||||
}
|
||||
|
||||
void test_tcpbpf_user(void)
|
||||
{
|
||||
struct test_tcpbpf_kern *skel;
|
||||
int cg_fd = -1;
|
||||
|
||||
skel = test_tcpbpf_kern__open_and_load();
|
||||
if (CHECK(!skel, "open and load skel", "failed"))
|
||||
return;
|
||||
|
||||
cg_fd = test__join_cgroup(CG_NAME);
|
||||
if (CHECK(cg_fd < 0, "test__join_cgroup(" CG_NAME ")",
|
||||
"cg_fd:%d errno:%d", cg_fd, errno))
|
||||
goto err;
|
||||
|
||||
skel->links.bpf_testcb = bpf_program__attach_cgroup(skel->progs.bpf_testcb, cg_fd);
|
||||
if (!ASSERT_OK_PTR(skel->links.bpf_testcb, "attach_cgroup(bpf_testcb)"))
|
||||
goto err;
|
||||
|
||||
run_test(&skel->bss->global);
|
||||
|
||||
err:
|
||||
if (cg_fd != -1)
|
||||
close(cg_fd);
|
||||
test_tcpbpf_kern__destroy(skel);
|
||||
}
|
@ -14,40 +14,7 @@
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include "test_tcpbpf.h"
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 4);
|
||||
__type(key, __u32);
|
||||
__type(value, struct tcpbpf_globals);
|
||||
} global_map SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(max_entries, 2);
|
||||
__type(key, __u32);
|
||||
__type(value, int);
|
||||
} sockopt_results SEC(".maps");
|
||||
|
||||
static inline void update_event_map(int event)
|
||||
{
|
||||
__u32 key = 0;
|
||||
struct tcpbpf_globals g, *gp;
|
||||
|
||||
gp = bpf_map_lookup_elem(&global_map, &key);
|
||||
if (gp == NULL) {
|
||||
struct tcpbpf_globals g = {0};
|
||||
|
||||
g.event_map |= (1 << event);
|
||||
bpf_map_update_elem(&global_map, &key, &g,
|
||||
BPF_ANY);
|
||||
} else {
|
||||
g = *gp;
|
||||
g.event_map |= (1 << event);
|
||||
bpf_map_update_elem(&global_map, &key, &g,
|
||||
BPF_ANY);
|
||||
}
|
||||
}
|
||||
|
||||
struct tcpbpf_globals global = {};
|
||||
int _version SEC("version") = 1;
|
||||
|
||||
SEC("sockops")
|
||||
@ -105,29 +72,15 @@ int bpf_testcb(struct bpf_sock_ops *skops)
|
||||
|
||||
op = (int) skops->op;
|
||||
|
||||
update_event_map(op);
|
||||
global.event_map |= (1 << op);
|
||||
|
||||
switch (op) {
|
||||
case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
|
||||
/* Test failure to set largest cb flag (assumes not defined) */
|
||||
bad_call_rv = bpf_sock_ops_cb_flags_set(skops, 0x80);
|
||||
global.bad_cb_test_rv = bpf_sock_ops_cb_flags_set(skops, 0x80);
|
||||
/* Set callback */
|
||||
good_call_rv = bpf_sock_ops_cb_flags_set(skops,
|
||||
global.good_cb_test_rv = bpf_sock_ops_cb_flags_set(skops,
|
||||
BPF_SOCK_OPS_STATE_CB_FLAG);
|
||||
/* Update results */
|
||||
{
|
||||
__u32 key = 0;
|
||||
struct tcpbpf_globals g, *gp;
|
||||
|
||||
gp = bpf_map_lookup_elem(&global_map, &key);
|
||||
if (!gp)
|
||||
break;
|
||||
g = *gp;
|
||||
g.bad_cb_test_rv = bad_call_rv;
|
||||
g.good_cb_test_rv = good_call_rv;
|
||||
bpf_map_update_elem(&global_map, &key, &g,
|
||||
BPF_ANY);
|
||||
}
|
||||
break;
|
||||
case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
|
||||
skops->sk_txhash = 0x12345f;
|
||||
@ -143,10 +96,8 @@ int bpf_testcb(struct bpf_sock_ops *skops)
|
||||
|
||||
thdr = (struct tcphdr *)(header + offset);
|
||||
v = thdr->syn;
|
||||
__u32 key = 1;
|
||||
|
||||
bpf_map_update_elem(&sockopt_results, &key, &v,
|
||||
BPF_ANY);
|
||||
global.tcp_saved_syn = v;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -156,25 +107,16 @@ int bpf_testcb(struct bpf_sock_ops *skops)
|
||||
break;
|
||||
case BPF_SOCK_OPS_STATE_CB:
|
||||
if (skops->args[1] == BPF_TCP_CLOSE) {
|
||||
__u32 key = 0;
|
||||
struct tcpbpf_globals g, *gp;
|
||||
|
||||
gp = bpf_map_lookup_elem(&global_map, &key);
|
||||
if (!gp)
|
||||
break;
|
||||
g = *gp;
|
||||
if (skops->args[0] == BPF_TCP_LISTEN) {
|
||||
g.num_listen++;
|
||||
global.num_listen++;
|
||||
} else {
|
||||
g.total_retrans = skops->total_retrans;
|
||||
g.data_segs_in = skops->data_segs_in;
|
||||
g.data_segs_out = skops->data_segs_out;
|
||||
g.bytes_received = skops->bytes_received;
|
||||
g.bytes_acked = skops->bytes_acked;
|
||||
global.total_retrans = skops->total_retrans;
|
||||
global.data_segs_in = skops->data_segs_in;
|
||||
global.data_segs_out = skops->data_segs_out;
|
||||
global.bytes_received = skops->bytes_received;
|
||||
global.bytes_acked = skops->bytes_acked;
|
||||
}
|
||||
g.num_close_events++;
|
||||
bpf_map_update_elem(&global_map, &key, &g,
|
||||
BPF_ANY);
|
||||
global.num_close_events++;
|
||||
}
|
||||
break;
|
||||
case BPF_SOCK_OPS_TCP_LISTEN_CB:
|
||||
@ -182,9 +124,7 @@ int bpf_testcb(struct bpf_sock_ops *skops)
|
||||
v = bpf_setsockopt(skops, IPPROTO_TCP, TCP_SAVE_SYN,
|
||||
&save_syn, sizeof(save_syn));
|
||||
/* Update global map w/ result of setsock opt */
|
||||
__u32 key = 0;
|
||||
|
||||
bpf_map_update_elem(&sockopt_results, &key, &v, BPF_ANY);
|
||||
global.tcp_save_syn = v;
|
||||
break;
|
||||
default:
|
||||
rv = -1;
|
||||
|
@ -1,50 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
|
||||
import sys, os, os.path, getopt
|
||||
import socket, time
|
||||
import subprocess
|
||||
import select
|
||||
|
||||
def read(sock, n):
|
||||
buf = b''
|
||||
while len(buf) < n:
|
||||
rem = n - len(buf)
|
||||
try: s = sock.recv(rem)
|
||||
except (socket.error) as e: return b''
|
||||
buf += s
|
||||
return buf
|
||||
|
||||
def send(sock, s):
|
||||
total = len(s)
|
||||
count = 0
|
||||
while count < total:
|
||||
try: n = sock.send(s)
|
||||
except (socket.error) as e: n = 0
|
||||
if n == 0:
|
||||
return count;
|
||||
count += n
|
||||
return count
|
||||
|
||||
|
||||
serverPort = int(sys.argv[1])
|
||||
|
||||
# create active socket
|
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
try:
|
||||
sock.connect(('::1', serverPort))
|
||||
except socket.error as e:
|
||||
sys.exit(1)
|
||||
|
||||
buf = b''
|
||||
n = 0
|
||||
while n < 1000:
|
||||
buf += b'+'
|
||||
n += 1
|
||||
|
||||
sock.settimeout(1);
|
||||
n = send(sock, buf)
|
||||
n = read(sock, 500)
|
||||
sys.exit(0)
|
@ -1,80 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
|
||||
import sys, os, os.path, getopt
|
||||
import socket, time
|
||||
import subprocess
|
||||
import select
|
||||
|
||||
def read(sock, n):
|
||||
buf = b''
|
||||
while len(buf) < n:
|
||||
rem = n - len(buf)
|
||||
try: s = sock.recv(rem)
|
||||
except (socket.error) as e: return b''
|
||||
buf += s
|
||||
return buf
|
||||
|
||||
def send(sock, s):
|
||||
total = len(s)
|
||||
count = 0
|
||||
while count < total:
|
||||
try: n = sock.send(s)
|
||||
except (socket.error) as e: n = 0
|
||||
if n == 0:
|
||||
return count;
|
||||
count += n
|
||||
return count
|
||||
|
||||
|
||||
SERVER_PORT = 12877
|
||||
MAX_PORTS = 2
|
||||
|
||||
serverPort = SERVER_PORT
|
||||
serverSocket = None
|
||||
|
||||
# create passive socket
|
||||
serverSocket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
||||
|
||||
try: serverSocket.bind(('::1', 0))
|
||||
except socket.error as msg:
|
||||
print('bind fails: ' + str(msg))
|
||||
|
||||
sn = serverSocket.getsockname()
|
||||
serverPort = sn[1]
|
||||
|
||||
cmdStr = ("./tcp_client.py %d &") % (serverPort)
|
||||
os.system(cmdStr)
|
||||
|
||||
buf = b''
|
||||
n = 0
|
||||
while n < 500:
|
||||
buf += b'.'
|
||||
n += 1
|
||||
|
||||
serverSocket.listen(MAX_PORTS)
|
||||
readList = [serverSocket]
|
||||
|
||||
while True:
|
||||
readyRead, readyWrite, inError = \
|
||||
select.select(readList, [], [], 2)
|
||||
|
||||
if len(readyRead) > 0:
|
||||
waitCount = 0
|
||||
for sock in readyRead:
|
||||
if sock == serverSocket:
|
||||
(clientSocket, address) = serverSocket.accept()
|
||||
address = str(address[0])
|
||||
readList.append(clientSocket)
|
||||
else:
|
||||
sock.settimeout(1);
|
||||
s = read(sock, 1000)
|
||||
n = send(sock, buf)
|
||||
sock.close()
|
||||
serverSocket.close()
|
||||
sys.exit(0)
|
||||
else:
|
||||
print('Select timeout!')
|
||||
sys.exit(1)
|
@ -14,5 +14,7 @@ struct tcpbpf_globals {
|
||||
__u64 bytes_acked;
|
||||
__u32 num_listen;
|
||||
__u32 num_close_events;
|
||||
__u32 tcp_save_syn;
|
||||
__u32 tcp_saved_syn;
|
||||
};
|
||||
#endif
|
||||
|
@ -1,165 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <sys/types.h>
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/libbpf.h>
|
||||
|
||||
#include "bpf_rlimit.h"
|
||||
#include "bpf_util.h"
|
||||
#include "cgroup_helpers.h"
|
||||
|
||||
#include "test_tcpbpf.h"
|
||||
|
||||
/* 3 comes from one listening socket + both ends of the connection */
|
||||
#define EXPECTED_CLOSE_EVENTS 3
|
||||
|
||||
#define EXPECT_EQ(expected, actual, fmt) \
|
||||
do { \
|
||||
if ((expected) != (actual)) { \
|
||||
printf(" Value of: " #actual "\n" \
|
||||
" Actual: %" fmt "\n" \
|
||||
" Expected: %" fmt "\n", \
|
||||
(actual), (expected)); \
|
||||
ret--; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int verify_result(const struct tcpbpf_globals *result)
|
||||
{
|
||||
__u32 expected_events;
|
||||
int ret = 0;
|
||||
|
||||
expected_events = ((1 << BPF_SOCK_OPS_TIMEOUT_INIT) |
|
||||
(1 << BPF_SOCK_OPS_RWND_INIT) |
|
||||
(1 << BPF_SOCK_OPS_TCP_CONNECT_CB) |
|
||||
(1 << BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) |
|
||||
(1 << BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB) |
|
||||
(1 << BPF_SOCK_OPS_NEEDS_ECN) |
|
||||
(1 << BPF_SOCK_OPS_STATE_CB) |
|
||||
(1 << BPF_SOCK_OPS_TCP_LISTEN_CB));
|
||||
|
||||
EXPECT_EQ(expected_events, result->event_map, "#" PRIx32);
|
||||
EXPECT_EQ(501ULL, result->bytes_received, "llu");
|
||||
EXPECT_EQ(1002ULL, result->bytes_acked, "llu");
|
||||
EXPECT_EQ(1, result->data_segs_in, PRIu32);
|
||||
EXPECT_EQ(1, result->data_segs_out, PRIu32);
|
||||
EXPECT_EQ(0x80, result->bad_cb_test_rv, PRIu32);
|
||||
EXPECT_EQ(0, result->good_cb_test_rv, PRIu32);
|
||||
EXPECT_EQ(1, result->num_listen, PRIu32);
|
||||
EXPECT_EQ(EXPECTED_CLOSE_EVENTS, result->num_close_events, PRIu32);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int verify_sockopt_result(int sock_map_fd)
|
||||
{
|
||||
__u32 key = 0;
|
||||
int ret = 0;
|
||||
int res;
|
||||
int rv;
|
||||
|
||||
/* check setsockopt for SAVE_SYN */
|
||||
rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
|
||||
EXPECT_EQ(0, rv, "d");
|
||||
EXPECT_EQ(0, res, "d");
|
||||
key = 1;
|
||||
/* check getsockopt for SAVED_SYN */
|
||||
rv = bpf_map_lookup_elem(sock_map_fd, &key, &res);
|
||||
EXPECT_EQ(0, rv, "d");
|
||||
EXPECT_EQ(1, res, "d");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int bpf_find_map(const char *test, struct bpf_object *obj,
|
||||
const char *name)
|
||||
{
|
||||
struct bpf_map *map;
|
||||
|
||||
map = bpf_object__find_map_by_name(obj, name);
|
||||
if (!map) {
|
||||
printf("%s:FAIL:map '%s' not found\n", test, name);
|
||||
return -1;
|
||||
}
|
||||
return bpf_map__fd(map);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *file = "test_tcpbpf_kern.o";
|
||||
int prog_fd, map_fd, sock_map_fd;
|
||||
struct tcpbpf_globals g = {0};
|
||||
const char *cg_path = "/foo";
|
||||
int error = EXIT_FAILURE;
|
||||
struct bpf_object *obj;
|
||||
int cg_fd = -1;
|
||||
int retry = 10;
|
||||
__u32 key = 0;
|
||||
int rv;
|
||||
|
||||
cg_fd = cgroup_setup_and_join(cg_path);
|
||||
if (cg_fd < 0)
|
||||
goto err;
|
||||
|
||||
if (bpf_prog_load(file, BPF_PROG_TYPE_SOCK_OPS, &obj, &prog_fd)) {
|
||||
printf("FAILED: load_bpf_file failed for: %s\n", file);
|
||||
goto err;
|
||||
}
|
||||
|
||||
rv = bpf_prog_attach(prog_fd, cg_fd, BPF_CGROUP_SOCK_OPS, 0);
|
||||
if (rv) {
|
||||
printf("FAILED: bpf_prog_attach: %d (%s)\n",
|
||||
error, strerror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (system("./tcp_server.py")) {
|
||||
printf("FAILED: TCP server\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
map_fd = bpf_find_map(__func__, obj, "global_map");
|
||||
if (map_fd < 0)
|
||||
goto err;
|
||||
|
||||
sock_map_fd = bpf_find_map(__func__, obj, "sockopt_results");
|
||||
if (sock_map_fd < 0)
|
||||
goto err;
|
||||
|
||||
retry_lookup:
|
||||
rv = bpf_map_lookup_elem(map_fd, &key, &g);
|
||||
if (rv != 0) {
|
||||
printf("FAILED: bpf_map_lookup_elem returns %d\n", rv);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (g.num_close_events != EXPECTED_CLOSE_EVENTS && retry--) {
|
||||
printf("Unexpected number of close events (%d), retrying!\n",
|
||||
g.num_close_events);
|
||||
usleep(100);
|
||||
goto retry_lookup;
|
||||
}
|
||||
|
||||
if (verify_result(&g)) {
|
||||
printf("FAILED: Wrong stats\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (verify_sockopt_result(sock_map_fd)) {
|
||||
printf("FAILED: Wrong sockopt stats\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
printf("PASSED!\n");
|
||||
error = 0;
|
||||
err:
|
||||
bpf_prog_detach(cg_fd, BPF_CGROUP_SOCK_OPS);
|
||||
close(cg_fd);
|
||||
cleanup_cgroup_environment();
|
||||
return error;
|
||||
}
|
Loading…
Reference in New Issue
Block a user