staging: rtl8192u: remove redundant assignment to pointer crypt
[linux/fpc-iii.git] / tools / testing / selftests / bpf / test_tcp_rtt.c
blob90c3862f74a856cc10685130a3313dedcdb1dd34
1 // SPDX-License-Identifier: GPL-2.0
2 #include <error.h>
3 #include <errno.h>
4 #include <stdio.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <netinet/in.h>
9 #include <pthread.h>
11 #include <linux/filter.h>
12 #include <bpf/bpf.h>
13 #include <bpf/libbpf.h>
15 #include "bpf_rlimit.h"
16 #include "bpf_util.h"
17 #include "cgroup_helpers.h"
19 #define CG_PATH "/tcp_rtt"
21 struct tcp_rtt_storage {
22 __u32 invoked;
23 __u32 dsack_dups;
24 __u32 delivered;
25 __u32 delivered_ce;
26 __u32 icsk_retransmits;
29 static void send_byte(int fd)
31 char b = 0x55;
33 if (write(fd, &b, sizeof(b)) != 1)
34 error(1, errno, "Failed to send single byte");
37 static int verify_sk(int map_fd, int client_fd, const char *msg, __u32 invoked,
38 __u32 dsack_dups, __u32 delivered, __u32 delivered_ce,
39 __u32 icsk_retransmits)
41 int err = 0;
42 struct tcp_rtt_storage val;
44 if (bpf_map_lookup_elem(map_fd, &client_fd, &val) < 0)
45 error(1, errno, "Failed to read socket storage");
47 if (val.invoked != invoked) {
48 log_err("%s: unexpected bpf_tcp_sock.invoked %d != %d",
49 msg, val.invoked, invoked);
50 err++;
53 if (val.dsack_dups != dsack_dups) {
54 log_err("%s: unexpected bpf_tcp_sock.dsack_dups %d != %d",
55 msg, val.dsack_dups, dsack_dups);
56 err++;
59 if (val.delivered != delivered) {
60 log_err("%s: unexpected bpf_tcp_sock.delivered %d != %d",
61 msg, val.delivered, delivered);
62 err++;
65 if (val.delivered_ce != delivered_ce) {
66 log_err("%s: unexpected bpf_tcp_sock.delivered_ce %d != %d",
67 msg, val.delivered_ce, delivered_ce);
68 err++;
71 if (val.icsk_retransmits != icsk_retransmits) {
72 log_err("%s: unexpected bpf_tcp_sock.icsk_retransmits %d != %d",
73 msg, val.icsk_retransmits, icsk_retransmits);
74 err++;
77 return err;
80 static int connect_to_server(int server_fd)
82 struct sockaddr_storage addr;
83 socklen_t len = sizeof(addr);
84 int fd;
86 fd = socket(AF_INET, SOCK_STREAM, 0);
87 if (fd < 0) {
88 log_err("Failed to create client socket");
89 return -1;
92 if (getsockname(server_fd, (struct sockaddr *)&addr, &len)) {
93 log_err("Failed to get server addr");
94 goto out;
97 if (connect(fd, (const struct sockaddr *)&addr, len) < 0) {
98 log_err("Fail to connect to server");
99 goto out;
102 return fd;
104 out:
105 close(fd);
106 return -1;
109 static int run_test(int cgroup_fd, int server_fd)
111 struct bpf_prog_load_attr attr = {
112 .prog_type = BPF_PROG_TYPE_SOCK_OPS,
113 .file = "./tcp_rtt.o",
114 .expected_attach_type = BPF_CGROUP_SOCK_OPS,
116 struct bpf_object *obj;
117 struct bpf_map *map;
118 int client_fd;
119 int prog_fd;
120 int map_fd;
121 int err;
123 err = bpf_prog_load_xattr(&attr, &obj, &prog_fd);
124 if (err) {
125 log_err("Failed to load BPF object");
126 return -1;
129 map = bpf_map__next(NULL, obj);
130 map_fd = bpf_map__fd(map);
132 err = bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_SOCK_OPS, 0);
133 if (err) {
134 log_err("Failed to attach BPF program");
135 goto close_bpf_object;
138 client_fd = connect_to_server(server_fd);
139 if (client_fd < 0) {
140 err = -1;
141 goto close_bpf_object;
144 err += verify_sk(map_fd, client_fd, "syn-ack",
145 /*invoked=*/1,
146 /*dsack_dups=*/0,
147 /*delivered=*/1,
148 /*delivered_ce=*/0,
149 /*icsk_retransmits=*/0);
151 send_byte(client_fd);
153 err += verify_sk(map_fd, client_fd, "first payload byte",
154 /*invoked=*/2,
155 /*dsack_dups=*/0,
156 /*delivered=*/2,
157 /*delivered_ce=*/0,
158 /*icsk_retransmits=*/0);
160 close(client_fd);
162 close_bpf_object:
163 bpf_object__close(obj);
164 return err;
167 static int start_server(void)
169 struct sockaddr_in addr = {
170 .sin_family = AF_INET,
171 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
173 int fd;
175 fd = socket(AF_INET, SOCK_STREAM, 0);
176 if (fd < 0) {
177 log_err("Failed to create server socket");
178 return -1;
181 if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr)) < 0) {
182 log_err("Failed to bind socket");
183 close(fd);
184 return -1;
187 return fd;
190 static void *server_thread(void *arg)
192 struct sockaddr_storage addr;
193 socklen_t len = sizeof(addr);
194 int fd = *(int *)arg;
195 int client_fd;
197 if (listen(fd, 1) < 0)
198 error(1, errno, "Failed to listed on socket");
200 client_fd = accept(fd, (struct sockaddr *)&addr, &len);
201 if (client_fd < 0)
202 error(1, errno, "Failed to accept client");
204 /* Wait for the next connection (that never arrives)
205 * to keep this thread alive to prevent calling
206 * close() on client_fd.
208 if (accept(fd, (struct sockaddr *)&addr, &len) >= 0)
209 error(1, errno, "Unexpected success in second accept");
211 close(client_fd);
213 return NULL;
216 int main(int args, char **argv)
218 int server_fd, cgroup_fd;
219 int err = EXIT_SUCCESS;
220 pthread_t tid;
222 if (setup_cgroup_environment())
223 goto cleanup_obj;
225 cgroup_fd = create_and_get_cgroup(CG_PATH);
226 if (cgroup_fd < 0)
227 goto cleanup_cgroup_env;
229 if (join_cgroup(CG_PATH))
230 goto cleanup_cgroup;
232 server_fd = start_server();
233 if (server_fd < 0) {
234 err = EXIT_FAILURE;
235 goto cleanup_cgroup;
238 pthread_create(&tid, NULL, server_thread, (void *)&server_fd);
240 if (run_test(cgroup_fd, server_fd))
241 err = EXIT_FAILURE;
243 close(server_fd);
245 printf("test_sockopt_sk: %s\n",
246 err == EXIT_SUCCESS ? "PASSED" : "FAILED");
248 cleanup_cgroup:
249 close(cgroup_fd);
250 cleanup_cgroup_env:
251 cleanup_cgroup_environment();
252 cleanup_obj:
253 return err;