Skip to content

Commit fb5cd0c

Browse files
nvmmaxAlexei Starovoitov
authored andcommitted
selftests/bpf: Add selftests for raw syncookie helpers
This commit adds selftests for the new BPF helpers: bpf_tcp_raw_{gen,check}_syncookie_ipv{4,6}. xdp_synproxy_kern.c is a BPF program that generates SYN cookies on allowed TCP ports and sends SYNACKs to clients, accelerating synproxy iptables module. xdp_synproxy.c is a userspace control application that allows to configure the following options in runtime: list of allowed ports, MSS, window scale, TTL. A selftest is added to prog_tests that leverages the above programs to test the functionality of the new helpers. Signed-off-by: Maxim Mikityanskiy <[email protected]> Reviewed-by: Tariq Toukan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 33bf988 commit fb5cd0c

File tree

5 files changed

+1330
-1
lines changed

5 files changed

+1330
-1
lines changed

tools/testing/selftests/bpf/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,4 @@ test_cpp
4343
*.tmp
4444
xdpxceiver
4545
xdp_redirect_multi
46+
xdp_synproxy

tools/testing/selftests/bpf/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ TEST_PROGS_EXTENDED := with_addr.sh \
8282
TEST_GEN_PROGS_EXTENDED = test_sock_addr test_skb_cgroup_id_user \
8383
flow_dissector_load test_flow_dissector test_tcp_check_syncookie_user \
8484
test_lirc_mode2_user xdping test_cpp runqslower bench bpf_testmod.ko \
85-
xdpxceiver xdp_redirect_multi
85+
xdpxceiver xdp_redirect_multi xdp_synproxy
8686

8787
TEST_CUSTOM_PROGS = $(OUTPUT)/urandom_read
8888

@@ -504,6 +504,7 @@ TRUNNER_EXTRA_SOURCES := test_progs.c cgroup_helpers.c trace_helpers.c \
504504
cap_helpers.c
505505
TRUNNER_EXTRA_FILES := $(OUTPUT)/urandom_read $(OUTPUT)/bpf_testmod.ko \
506506
$(OUTPUT)/liburandom_read.so \
507+
$(OUTPUT)/xdp_synproxy \
507508
ima_setup.sh \
508509
$(wildcard progs/btf_dump_test_case_*.c)
509510
TRUNNER_BPF_BUILD_RULE := CLANG_BPF_BUILD_RULE
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause
2+
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
3+
4+
#include <test_progs.h>
5+
#include <network_helpers.h>
6+
#include <ctype.h>
7+
8+
#define CMD_OUT_BUF_SIZE 1023
9+
10+
#define SYS(cmd) ({ \
11+
if (!ASSERT_OK(system(cmd), (cmd))) \
12+
goto out; \
13+
})
14+
15+
#define SYS_OUT(cmd) ({ \
16+
FILE *f = popen((cmd), "r"); \
17+
if (!ASSERT_OK_PTR(f, (cmd))) \
18+
goto out; \
19+
f; \
20+
})
21+
22+
/* out must be at least `size * 4 + 1` bytes long */
23+
static void escape_str(char *out, const char *in, size_t size)
24+
{
25+
static const char *hex = "0123456789ABCDEF";
26+
size_t i;
27+
28+
for (i = 0; i < size; i++) {
29+
if (isprint(in[i]) && in[i] != '\\' && in[i] != '\'') {
30+
*out++ = in[i];
31+
} else {
32+
*out++ = '\\';
33+
*out++ = 'x';
34+
*out++ = hex[(in[i] >> 4) & 0xf];
35+
*out++ = hex[in[i] & 0xf];
36+
}
37+
}
38+
*out++ = '\0';
39+
}
40+
41+
static bool expect_str(char *buf, size_t size, const char *str, const char *name)
42+
{
43+
static char escbuf_expected[CMD_OUT_BUF_SIZE * 4];
44+
static char escbuf_actual[CMD_OUT_BUF_SIZE * 4];
45+
static int duration = 0;
46+
bool ok;
47+
48+
ok = size == strlen(str) && !memcmp(buf, str, size);
49+
50+
if (!ok) {
51+
escape_str(escbuf_expected, str, strlen(str));
52+
escape_str(escbuf_actual, buf, size);
53+
}
54+
CHECK(!ok, name, "unexpected %s: actual '%s' != expected '%s'\n",
55+
name, escbuf_actual, escbuf_expected);
56+
57+
return ok;
58+
}
59+
60+
void test_xdp_synproxy(void)
61+
{
62+
int server_fd = -1, client_fd = -1, accept_fd = -1;
63+
struct nstoken *ns = NULL;
64+
FILE *ctrl_file = NULL;
65+
char buf[CMD_OUT_BUF_SIZE];
66+
size_t size;
67+
68+
SYS("ip netns add synproxy");
69+
70+
SYS("ip link add tmp0 type veth peer name tmp1");
71+
SYS("ip link set tmp1 netns synproxy");
72+
SYS("ip link set tmp0 up");
73+
SYS("ip addr replace 198.18.0.1/24 dev tmp0");
74+
75+
/* When checksum offload is enabled, the XDP program sees wrong
76+
* checksums and drops packets.
77+
*/
78+
SYS("ethtool -K tmp0 tx off");
79+
/* Workaround required for veth. */
80+
SYS("ip link set tmp0 xdp object xdp_dummy.o section xdp 2> /dev/null");
81+
82+
ns = open_netns("synproxy");
83+
if (!ASSERT_OK_PTR(ns, "setns"))
84+
goto out;
85+
86+
SYS("ip link set lo up");
87+
SYS("ip link set tmp1 up");
88+
SYS("ip addr replace 198.18.0.2/24 dev tmp1");
89+
SYS("sysctl -w net.ipv4.tcp_syncookies=2");
90+
SYS("sysctl -w net.ipv4.tcp_timestamps=1");
91+
SYS("sysctl -w net.netfilter.nf_conntrack_tcp_loose=0");
92+
SYS("iptables -t raw -I PREROUTING \
93+
-i tmp1 -p tcp -m tcp --syn --dport 8080 -j CT --notrack");
94+
SYS("iptables -t filter -A INPUT \
95+
-i tmp1 -p tcp -m tcp --dport 8080 -m state --state INVALID,UNTRACKED \
96+
-j SYNPROXY --sack-perm --timestamp --wscale 7 --mss 1460");
97+
SYS("iptables -t filter -A INPUT \
98+
-i tmp1 -m state --state INVALID -j DROP");
99+
100+
ctrl_file = SYS_OUT("./xdp_synproxy --iface tmp1 --ports 8080 --single \
101+
--mss4 1460 --mss6 1440 --wscale 7 --ttl 64");
102+
size = fread(buf, 1, sizeof(buf), ctrl_file);
103+
pclose(ctrl_file);
104+
if (!expect_str(buf, size, "Total SYNACKs generated: 0\n",
105+
"initial SYNACKs"))
106+
goto out;
107+
108+
server_fd = start_server(AF_INET, SOCK_STREAM, "198.18.0.2", 8080, 0);
109+
if (!ASSERT_GE(server_fd, 0, "start_server"))
110+
goto out;
111+
112+
close_netns(ns);
113+
ns = NULL;
114+
115+
client_fd = connect_to_fd(server_fd, 10000);
116+
if (!ASSERT_GE(client_fd, 0, "connect_to_fd"))
117+
goto out;
118+
119+
accept_fd = accept(server_fd, NULL, NULL);
120+
if (!ASSERT_GE(accept_fd, 0, "accept"))
121+
goto out;
122+
123+
ns = open_netns("synproxy");
124+
if (!ASSERT_OK_PTR(ns, "setns"))
125+
goto out;
126+
127+
ctrl_file = SYS_OUT("./xdp_synproxy --iface tmp1 --single");
128+
size = fread(buf, 1, sizeof(buf), ctrl_file);
129+
pclose(ctrl_file);
130+
if (!expect_str(buf, size, "Total SYNACKs generated: 1\n",
131+
"SYNACKs after connection"))
132+
goto out;
133+
134+
out:
135+
if (accept_fd >= 0)
136+
close(accept_fd);
137+
if (client_fd >= 0)
138+
close(client_fd);
139+
if (server_fd >= 0)
140+
close(server_fd);
141+
if (ns)
142+
close_netns(ns);
143+
144+
system("ip link del tmp0");
145+
system("ip netns del synproxy");
146+
}

0 commit comments

Comments
 (0)