1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
5 #include <netinet/in.h>
12 #include <linux/compiler.h>
13 #include <bpf/libbpf.h>
15 #include "network_helpers.h"
16 #include "test_progs.h"
17 #include "test_btf_skc_cls_ingress.skel.h"
19 static struct test_btf_skc_cls_ingress
*skel
;
20 static struct sockaddr_in6 srv_sa6
;
21 static __u32 duration
;
23 #define PROG_PIN_FILE "/sys/fs/bpf/btf_skc_cls_ingress"
25 static int write_sysctl(const char *sysctl
, const char *value
)
29 fd
= open(sysctl
, O_WRONLY
);
30 if (CHECK(fd
== -1, "open sysctl", "open(%s): %s (%d)\n",
31 sysctl
, strerror(errno
), errno
))
35 err
= write(fd
, value
, len
);
37 if (CHECK(err
!= len
, "write sysctl",
38 "write(%s, %s, %d): err:%d %s (%d)\n",
39 sysctl
, value
, len
, err
, strerror(errno
), errno
))
45 static int prepare_netns(void)
47 if (CHECK(unshare(CLONE_NEWNET
), "create netns",
48 "unshare(CLONE_NEWNET): %s (%d)",
49 strerror(errno
), errno
))
52 if (CHECK(system("ip link set dev lo up"),
53 "ip link set dev lo up", "failed\n"))
56 if (CHECK(system("tc qdisc add dev lo clsact"),
57 "tc qdisc add dev lo clsact", "failed\n"))
60 if (CHECK(system("tc filter add dev lo ingress bpf direct-action object-pinned " PROG_PIN_FILE
),
61 "install tc cls-prog at ingress", "failed\n"))
64 /* Ensure 20 bytes options (i.e. in total 40 bytes tcp header) for the
65 * bpf_tcp_gen_syncookie() helper.
67 if (write_sysctl("/proc/sys/net/ipv4/tcp_window_scaling", "1") ||
68 write_sysctl("/proc/sys/net/ipv4/tcp_timestamps", "1") ||
69 write_sysctl("/proc/sys/net/ipv4/tcp_sack", "1"))
75 static void reset_test(void)
77 memset(&skel
->bss
->srv_sa6
, 0, sizeof(skel
->bss
->srv_sa6
));
78 skel
->bss
->listen_tp_sport
= 0;
79 skel
->bss
->req_sk_sport
= 0;
80 skel
->bss
->recv_cookie
= 0;
81 skel
->bss
->gen_cookie
= 0;
85 static void print_err_line(void)
88 printf("bpf prog error at line %u\n", skel
->bss
->linum
);
91 static void test_conn(void)
93 int listen_fd
= -1, cli_fd
= -1, err
;
94 socklen_t addrlen
= sizeof(srv_sa6
);
97 if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "1"))
100 listen_fd
= start_server(AF_INET6
, SOCK_STREAM
, "::1", 0, 0);
101 if (CHECK_FAIL(listen_fd
== -1))
104 err
= getsockname(listen_fd
, (struct sockaddr
*)&srv_sa6
, &addrlen
);
105 if (CHECK(err
, "getsockname(listen_fd)", "err:%d errno:%d\n", err
,
108 memcpy(&skel
->bss
->srv_sa6
, &srv_sa6
, sizeof(srv_sa6
));
109 srv_port
= ntohs(srv_sa6
.sin6_port
);
111 cli_fd
= connect_to_fd(listen_fd
, 0);
112 if (CHECK_FAIL(cli_fd
== -1))
115 if (CHECK(skel
->bss
->listen_tp_sport
!= srv_port
||
116 skel
->bss
->req_sk_sport
!= srv_port
,
117 "Unexpected sk src port",
118 "listen_tp_sport:%u req_sk_sport:%u expected:%u\n",
119 skel
->bss
->listen_tp_sport
, skel
->bss
->req_sk_sport
,
123 if (CHECK(skel
->bss
->gen_cookie
|| skel
->bss
->recv_cookie
,
124 "Unexpected syncookie states",
125 "gen_cookie:%u recv_cookie:%u\n",
126 skel
->bss
->gen_cookie
, skel
->bss
->recv_cookie
))
129 CHECK(skel
->bss
->linum
, "bpf prog detected error", "at line %u\n",
139 static void test_syncookie(void)
141 int listen_fd
= -1, cli_fd
= -1, err
;
142 socklen_t addrlen
= sizeof(srv_sa6
);
145 /* Enforce syncookie mode */
146 if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "2"))
149 listen_fd
= start_server(AF_INET6
, SOCK_STREAM
, "::1", 0, 0);
150 if (CHECK_FAIL(listen_fd
== -1))
153 err
= getsockname(listen_fd
, (struct sockaddr
*)&srv_sa6
, &addrlen
);
154 if (CHECK(err
, "getsockname(listen_fd)", "err:%d errno:%d\n", err
,
157 memcpy(&skel
->bss
->srv_sa6
, &srv_sa6
, sizeof(srv_sa6
));
158 srv_port
= ntohs(srv_sa6
.sin6_port
);
160 cli_fd
= connect_to_fd(listen_fd
, 0);
161 if (CHECK_FAIL(cli_fd
== -1))
164 if (CHECK(skel
->bss
->listen_tp_sport
!= srv_port
,
165 "Unexpected tp src port",
166 "listen_tp_sport:%u expected:%u\n",
167 skel
->bss
->listen_tp_sport
, srv_port
))
170 if (CHECK(skel
->bss
->req_sk_sport
,
171 "Unexpected req_sk src port",
172 "req_sk_sport:%u expected:0\n",
173 skel
->bss
->req_sk_sport
))
176 if (CHECK(!skel
->bss
->gen_cookie
||
177 skel
->bss
->gen_cookie
!= skel
->bss
->recv_cookie
,
178 "Unexpected syncookie states",
179 "gen_cookie:%u recv_cookie:%u\n",
180 skel
->bss
->gen_cookie
, skel
->bss
->recv_cookie
))
183 CHECK(skel
->bss
->linum
, "bpf prog detected error", "at line %u\n",
198 #define DEF_TEST(name) { #name, test_##name }
199 static struct test tests
[] = {
204 void test_btf_skc_cls_ingress(void)
208 skel
= test_btf_skc_cls_ingress__open_and_load();
209 if (CHECK(!skel
, "test_btf_skc_cls_ingress__open_and_load", "failed\n"))
212 err
= bpf_program__pin(skel
->progs
.cls_ingress
, PROG_PIN_FILE
);
213 if (CHECK(err
, "bpf_program__pin",
214 "cannot pin bpf prog to %s. err:%d\n", PROG_PIN_FILE
, err
)) {
215 test_btf_skc_cls_ingress__destroy(skel
);
219 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++) {
220 if (!test__start_subtest(tests
[i
].desc
))
232 bpf_program__unpin(skel
->progs
.cls_ingress
, PROG_PIN_FILE
);
233 test_btf_skc_cls_ingress__destroy(skel
);