]> Git Repo - J-linux.git/blob - tools/testing/selftests/bpf/prog_tests/xdp_synproxy.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / tools / testing / selftests / bpf / prog_tests / xdp_synproxy.c
1 // SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause
2 /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
3
4 #define _GNU_SOURCE
5 #include <test_progs.h>
6 #include <network_helpers.h>
7 #include <ctype.h>
8
9 #define CMD_OUT_BUF_SIZE 1023
10
11 #define SYS_OUT(cmd, ...) ({ \
12         char buf[1024]; \
13         snprintf(buf, sizeof(buf), (cmd), ##__VA_ARGS__); \
14         FILE *f = popen(buf, "r"); \
15         if (!ASSERT_OK_PTR(f, buf)) \
16                 goto out; \
17         f; \
18 })
19
20 /* out must be at least `size * 4 + 1` bytes long */
21 static void escape_str(char *out, const char *in, size_t size)
22 {
23         static const char *hex = "0123456789ABCDEF";
24         size_t i;
25
26         for (i = 0; i < size; i++) {
27                 if (isprint(in[i]) && in[i] != '\\' && in[i] != '\'') {
28                         *out++ = in[i];
29                 } else {
30                         *out++ = '\\';
31                         *out++ = 'x';
32                         *out++ = hex[(in[i] >> 4) & 0xf];
33                         *out++ = hex[in[i] & 0xf];
34                 }
35         }
36         *out++ = '\0';
37 }
38
39 static bool expect_str(char *buf, size_t size, const char *str, const char *name)
40 {
41         static char escbuf_expected[CMD_OUT_BUF_SIZE * 4];
42         static char escbuf_actual[CMD_OUT_BUF_SIZE * 4];
43         static int duration = 0;
44         bool ok;
45
46         ok = size == strlen(str) && !memcmp(buf, str, size);
47
48         if (!ok) {
49                 escape_str(escbuf_expected, str, strlen(str));
50                 escape_str(escbuf_actual, buf, size);
51         }
52         CHECK(!ok, name, "unexpected %s: actual '%s' != expected '%s'\n",
53               name, escbuf_actual, escbuf_expected);
54
55         return ok;
56 }
57
58 static void test_synproxy(bool xdp)
59 {
60         int server_fd = -1, client_fd = -1, accept_fd = -1;
61         char *prog_id = NULL, *prog_id_end;
62         struct nstoken *ns = NULL;
63         FILE *ctrl_file = NULL;
64         char buf[CMD_OUT_BUF_SIZE];
65         size_t size;
66
67         SYS(out, "ip netns add synproxy");
68
69         SYS(out, "ip link add tmp0 type veth peer name tmp1");
70         SYS(out, "ip link set tmp1 netns synproxy");
71         SYS(out, "ip link set tmp0 up");
72         SYS(out, "ip addr replace 198.18.0.1/24 dev tmp0");
73
74         /* When checksum offload is enabled, the XDP program sees wrong
75          * checksums and drops packets.
76          */
77         SYS(out, "ethtool -K tmp0 tx off");
78         if (xdp)
79                 /* Workaround required for veth. */
80                 SYS(out, "ip link set tmp0 xdp object xdp_dummy.bpf.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(out, "ip link set lo up");
87         SYS(out, "ip link set tmp1 up");
88         SYS(out, "ip addr replace 198.18.0.2/24 dev tmp1");
89         SYS(out, "sysctl -w net.ipv4.tcp_syncookies=2");
90         SYS(out, "sysctl -w net.ipv4.tcp_timestamps=1");
91         SYS(out, "sysctl -w net.netfilter.nf_conntrack_tcp_loose=0");
92         SYS(out, "iptables-legacy -t raw -I PREROUTING \
93             -i tmp1 -p tcp -m tcp --syn --dport 8080 -j CT --notrack");
94         SYS(out, "iptables-legacy -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(out, "iptables-legacy -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 \
101                             --single --mss4 1460 --mss6 1440 \
102                             --wscale 7 --ttl 64%s", xdp ? "" : " --tc");
103         size = fread(buf, 1, sizeof(buf), ctrl_file);
104         pclose(ctrl_file);
105         if (!expect_str(buf, size, "Total SYNACKs generated: 0\n",
106                         "initial SYNACKs"))
107                 goto out;
108
109         if (!xdp) {
110                 ctrl_file = SYS_OUT("tc filter show dev tmp1 ingress");
111                 size = fread(buf, 1, sizeof(buf), ctrl_file);
112                 pclose(ctrl_file);
113                 prog_id = memmem(buf, size, " id ", 4);
114                 if (!ASSERT_OK_PTR(prog_id, "find prog id"))
115                         goto out;
116                 prog_id += 4;
117                 if (!ASSERT_LT(prog_id, buf + size, "find prog id begin"))
118                         goto out;
119                 prog_id_end = prog_id;
120                 while (prog_id_end < buf + size && *prog_id_end >= '0' &&
121                        *prog_id_end <= '9')
122                         prog_id_end++;
123                 if (!ASSERT_LT(prog_id_end, buf + size, "find prog id end"))
124                         goto out;
125                 *prog_id_end = '\0';
126         }
127
128         server_fd = start_server(AF_INET, SOCK_STREAM, "198.18.0.2", 8080, 0);
129         if (!ASSERT_GE(server_fd, 0, "start_server"))
130                 goto out;
131
132         close_netns(ns);
133         ns = NULL;
134
135         client_fd = connect_to_fd(server_fd, 10000);
136         if (!ASSERT_GE(client_fd, 0, "connect_to_fd"))
137                 goto out;
138
139         accept_fd = accept(server_fd, NULL, NULL);
140         if (!ASSERT_GE(accept_fd, 0, "accept"))
141                 goto out;
142
143         ns = open_netns("synproxy");
144         if (!ASSERT_OK_PTR(ns, "setns"))
145                 goto out;
146
147         if (xdp)
148                 ctrl_file = SYS_OUT("./xdp_synproxy --iface tmp1 --single");
149         else
150                 ctrl_file = SYS_OUT("./xdp_synproxy --prog %s --single",
151                                     prog_id);
152         size = fread(buf, 1, sizeof(buf), ctrl_file);
153         pclose(ctrl_file);
154         if (!expect_str(buf, size, "Total SYNACKs generated: 1\n",
155                         "SYNACKs after connection"))
156                 goto out;
157
158 out:
159         if (accept_fd >= 0)
160                 close(accept_fd);
161         if (client_fd >= 0)
162                 close(client_fd);
163         if (server_fd >= 0)
164                 close(server_fd);
165         if (ns)
166                 close_netns(ns);
167
168         SYS_NOFAIL("ip link del tmp0");
169         SYS_NOFAIL("ip netns del synproxy");
170 }
171
172 void test_xdp_synproxy(void)
173 {
174         if (test__start_subtest("xdp"))
175                 test_synproxy(true);
176         if (test__start_subtest("tc"))
177                 test_synproxy(false);
178 }
This page took 0.036842 seconds and 4 git commands to generate.