xref: /linux/tools/testing/selftests/bpf/prog_tests/test_tc_edt.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1b0f82e7aSAlexis Lothoré (eBPF Foundation) // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2b0f82e7aSAlexis Lothoré (eBPF Foundation) 
3b0f82e7aSAlexis Lothoré (eBPF Foundation) /*
4b0f82e7aSAlexis Lothoré (eBPF Foundation)  * BPF-based flow shaping
5b0f82e7aSAlexis Lothoré (eBPF Foundation)  *
6b0f82e7aSAlexis Lothoré (eBPF Foundation)  * The test brings up two veth in two isolated namespaces, attach some flow
7b0f82e7aSAlexis Lothoré (eBPF Foundation)  * shaping program onto it, and ensures that a manual speedtest maximum
8b0f82e7aSAlexis Lothoré (eBPF Foundation)  * value matches the rate set in the BPF shapers.
9b0f82e7aSAlexis Lothoré (eBPF Foundation)  */
10b0f82e7aSAlexis Lothoré (eBPF Foundation) 
11b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <asm-generic/socket.h>
12b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <stdio.h>
13b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <unistd.h>
14b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <fcntl.h>
15b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <math.h>
16b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <sys/time.h>
17b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <sys/socket.h>
18b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <bpf/libbpf.h>
19b0f82e7aSAlexis Lothoré (eBPF Foundation) #include <pthread.h>
20b0f82e7aSAlexis Lothoré (eBPF Foundation) #include "test_progs.h"
21b0f82e7aSAlexis Lothoré (eBPF Foundation) #include "network_helpers.h"
22b0f82e7aSAlexis Lothoré (eBPF Foundation) #include "test_tc_edt.skel.h"
23b0f82e7aSAlexis Lothoré (eBPF Foundation) 
24b0f82e7aSAlexis Lothoré (eBPF Foundation) #define SERVER_NS "tc-edt-server-ns"
25b0f82e7aSAlexis Lothoré (eBPF Foundation) #define CLIENT_NS "tc-edt-client-ns"
26b0f82e7aSAlexis Lothoré (eBPF Foundation) #define IP4_ADDR_VETH1 "192.168.1.1"
27b0f82e7aSAlexis Lothoré (eBPF Foundation) #define IP4_ADDR_VETH2 "192.168.1.2"
28b0f82e7aSAlexis Lothoré (eBPF Foundation) #define IP4_ADDR_VETH2_HEX 0xC0A80102
29b0f82e7aSAlexis Lothoré (eBPF Foundation) 
30b0f82e7aSAlexis Lothoré (eBPF Foundation) #define TIMEOUT_MS		2000
31b0f82e7aSAlexis Lothoré (eBPF Foundation) #define TEST_PORT		9000
32b0f82e7aSAlexis Lothoré (eBPF Foundation) #define TARGET_RATE_MBPS	5.0
33b0f82e7aSAlexis Lothoré (eBPF Foundation) #define TX_BYTES_COUNT		(1 * 1000 * 1000)
34b0f82e7aSAlexis Lothoré (eBPF Foundation) #define RATE_ERROR_PERCENT	2.0
35b0f82e7aSAlexis Lothoré (eBPF Foundation) 
36b0f82e7aSAlexis Lothoré (eBPF Foundation) struct connection {
37b0f82e7aSAlexis Lothoré (eBPF Foundation) 	int server_listen_fd;
38b0f82e7aSAlexis Lothoré (eBPF Foundation) 	int server_conn_fd;
39b0f82e7aSAlexis Lothoré (eBPF Foundation) 	int client_conn_fd;
40b0f82e7aSAlexis Lothoré (eBPF Foundation) };
41b0f82e7aSAlexis Lothoré (eBPF Foundation) 
42b0f82e7aSAlexis Lothoré (eBPF Foundation) static int setup(struct test_tc_edt *skel)
43b0f82e7aSAlexis Lothoré (eBPF Foundation) {
44b0f82e7aSAlexis Lothoré (eBPF Foundation) 	struct nstoken *nstoken_client, *nstoken_server;
45b0f82e7aSAlexis Lothoré (eBPF Foundation) 	int ret;
46b0f82e7aSAlexis Lothoré (eBPF Foundation) 
47b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK(make_netns(CLIENT_NS), "create client ns"))
48b0f82e7aSAlexis Lothoré (eBPF Foundation) 		goto fail;
49b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK(make_netns(SERVER_NS), "create server ns"))
50b0f82e7aSAlexis Lothoré (eBPF Foundation) 		goto fail_delete_client_ns;
51b0f82e7aSAlexis Lothoré (eBPF Foundation) 
52b0f82e7aSAlexis Lothoré (eBPF Foundation) 	nstoken_client = open_netns(CLIENT_NS);
53b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK_PTR(nstoken_client, "open client ns"))
54b0f82e7aSAlexis Lothoré (eBPF Foundation) 		goto fail_delete_server_ns;
55b0f82e7aSAlexis Lothoré (eBPF Foundation) 	SYS(fail_close_client_ns, "ip link add veth1 type veth peer name %s",
56b0f82e7aSAlexis Lothoré (eBPF Foundation) 	    "veth2 netns " SERVER_NS);
57b0f82e7aSAlexis Lothoré (eBPF Foundation) 	SYS(fail_close_client_ns, "ip -4 addr add " IP4_ADDR_VETH1 "/24 dev veth1");
58b0f82e7aSAlexis Lothoré (eBPF Foundation) 	SYS(fail_close_client_ns, "ip link set veth1 up");
59b0f82e7aSAlexis Lothoré (eBPF Foundation) 
60b0f82e7aSAlexis Lothoré (eBPF Foundation) 	nstoken_server = open_netns(SERVER_NS);
61b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK_PTR(nstoken_server, "enter server ns"))
62b0f82e7aSAlexis Lothoré (eBPF Foundation) 		goto fail_close_client_ns;
63b0f82e7aSAlexis Lothoré (eBPF Foundation) 	SYS(fail_close_server_ns, "ip -4 addr add " IP4_ADDR_VETH2 "/24 dev veth2");
64b0f82e7aSAlexis Lothoré (eBPF Foundation) 	SYS(fail_close_server_ns, "ip link set veth2 up");
65b0f82e7aSAlexis Lothoré (eBPF Foundation) 	SYS(fail_close_server_ns, "tc qdisc add dev veth2 root fq");
66b0f82e7aSAlexis Lothoré (eBPF Foundation) 	ret = tc_prog_attach("veth2", -1, bpf_program__fd(skel->progs.tc_prog));
67b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK(ret, "attach bpf prog"))
68b0f82e7aSAlexis Lothoré (eBPF Foundation) 		goto fail_close_server_ns;
69*1d17bcceSAlexis Lothoré (eBPF Foundation) 	skel->bss->target_rate = TARGET_RATE_MBPS * 1000 * 1000;
70b0f82e7aSAlexis Lothoré (eBPF Foundation) 	close_netns(nstoken_server);
71b0f82e7aSAlexis Lothoré (eBPF Foundation) 	close_netns(nstoken_client);
72b0f82e7aSAlexis Lothoré (eBPF Foundation) 
73b0f82e7aSAlexis Lothoré (eBPF Foundation) 	return 0;
74b0f82e7aSAlexis Lothoré (eBPF Foundation) 
75b0f82e7aSAlexis Lothoré (eBPF Foundation) fail_close_server_ns:
76b0f82e7aSAlexis Lothoré (eBPF Foundation) 	close_netns(nstoken_server);
77b0f82e7aSAlexis Lothoré (eBPF Foundation) fail_close_client_ns:
78b0f82e7aSAlexis Lothoré (eBPF Foundation) 	close_netns(nstoken_client);
79b0f82e7aSAlexis Lothoré (eBPF Foundation) fail_delete_server_ns:
80b0f82e7aSAlexis Lothoré (eBPF Foundation) 	remove_netns(SERVER_NS);
81b0f82e7aSAlexis Lothoré (eBPF Foundation) fail_delete_client_ns:
82b0f82e7aSAlexis Lothoré (eBPF Foundation) 	remove_netns(CLIENT_NS);
83b0f82e7aSAlexis Lothoré (eBPF Foundation) fail:
84b0f82e7aSAlexis Lothoré (eBPF Foundation) 	return -1;
85b0f82e7aSAlexis Lothoré (eBPF Foundation) }
86b0f82e7aSAlexis Lothoré (eBPF Foundation) 
87b0f82e7aSAlexis Lothoré (eBPF Foundation) static void cleanup(void)
88b0f82e7aSAlexis Lothoré (eBPF Foundation) {
89b0f82e7aSAlexis Lothoré (eBPF Foundation) 	remove_netns(CLIENT_NS);
90b0f82e7aSAlexis Lothoré (eBPF Foundation) 	remove_netns(SERVER_NS);
91b0f82e7aSAlexis Lothoré (eBPF Foundation) }
92b0f82e7aSAlexis Lothoré (eBPF Foundation) 
93b0f82e7aSAlexis Lothoré (eBPF Foundation) static void run_test(void)
94b0f82e7aSAlexis Lothoré (eBPF Foundation) {
95b0f82e7aSAlexis Lothoré (eBPF Foundation) 	int server_fd, client_fd, err;
96b0f82e7aSAlexis Lothoré (eBPF Foundation) 	double rate_mbps, rate_error;
97b0f82e7aSAlexis Lothoré (eBPF Foundation) 	struct nstoken *nstoken;
98b0f82e7aSAlexis Lothoré (eBPF Foundation) 	__u64 ts_start, ts_end;
99b0f82e7aSAlexis Lothoré (eBPF Foundation) 
100b0f82e7aSAlexis Lothoré (eBPF Foundation) 	nstoken = open_netns(SERVER_NS);
101b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK_PTR(nstoken, "open server ns"))
102b0f82e7aSAlexis Lothoré (eBPF Foundation) 		return;
103b0f82e7aSAlexis Lothoré (eBPF Foundation) 	server_fd = start_server(AF_INET, SOCK_STREAM, IP4_ADDR_VETH2,
104b0f82e7aSAlexis Lothoré (eBPF Foundation) 			TEST_PORT, TIMEOUT_MS);
105b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK_FD(server_fd, "start server"))
106b0f82e7aSAlexis Lothoré (eBPF Foundation) 		return;
107b0f82e7aSAlexis Lothoré (eBPF Foundation) 
108b0f82e7aSAlexis Lothoré (eBPF Foundation) 	close_netns(nstoken);
109b0f82e7aSAlexis Lothoré (eBPF Foundation) 	nstoken = open_netns(CLIENT_NS);
110b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK_PTR(nstoken, "open client ns"))
111b0f82e7aSAlexis Lothoré (eBPF Foundation) 		return;
112b0f82e7aSAlexis Lothoré (eBPF Foundation) 	client_fd = connect_to_fd(server_fd, 0);
113b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK_FD(client_fd, "connect client"))
114b0f82e7aSAlexis Lothoré (eBPF Foundation) 		return;
115b0f82e7aSAlexis Lothoré (eBPF Foundation) 
116b0f82e7aSAlexis Lothoré (eBPF Foundation) 	ts_start = get_time_ns();
117b0f82e7aSAlexis Lothoré (eBPF Foundation) 	err = send_recv_data(server_fd, client_fd, TX_BYTES_COUNT);
118b0f82e7aSAlexis Lothoré (eBPF Foundation) 	ts_end = get_time_ns();
119b0f82e7aSAlexis Lothoré (eBPF Foundation) 	close_netns(nstoken);
120b0f82e7aSAlexis Lothoré (eBPF Foundation) 	ASSERT_OK(err, "send_recv_data");
121b0f82e7aSAlexis Lothoré (eBPF Foundation) 
122b0f82e7aSAlexis Lothoré (eBPF Foundation) 	rate_mbps = TX_BYTES_COUNT / ((ts_end - ts_start) / 1000.0);
123b0f82e7aSAlexis Lothoré (eBPF Foundation) 	rate_error =
124b0f82e7aSAlexis Lothoré (eBPF Foundation) 		fabs((rate_mbps - TARGET_RATE_MBPS) * 100.0 / TARGET_RATE_MBPS);
125b0f82e7aSAlexis Lothoré (eBPF Foundation) 
126b0f82e7aSAlexis Lothoré (eBPF Foundation) 	ASSERT_LE(rate_error, RATE_ERROR_PERCENT,
127b0f82e7aSAlexis Lothoré (eBPF Foundation) 		  "rate error is lower than threshold");
128b0f82e7aSAlexis Lothoré (eBPF Foundation) }
129b0f82e7aSAlexis Lothoré (eBPF Foundation) 
130b0f82e7aSAlexis Lothoré (eBPF Foundation) void test_tc_edt(void)
131b0f82e7aSAlexis Lothoré (eBPF Foundation) {
132b0f82e7aSAlexis Lothoré (eBPF Foundation) 	struct test_tc_edt *skel;
133b0f82e7aSAlexis Lothoré (eBPF Foundation) 
134b0f82e7aSAlexis Lothoré (eBPF Foundation) 	skel = test_tc_edt__open_and_load();
135b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK_PTR(skel, "skel open and load"))
136b0f82e7aSAlexis Lothoré (eBPF Foundation) 		return;
137b0f82e7aSAlexis Lothoré (eBPF Foundation) 
138b0f82e7aSAlexis Lothoré (eBPF Foundation) 	if (!ASSERT_OK(setup(skel), "global setup"))
139b0f82e7aSAlexis Lothoré (eBPF Foundation) 		return;
140b0f82e7aSAlexis Lothoré (eBPF Foundation) 
141b0f82e7aSAlexis Lothoré (eBPF Foundation) 	run_test();
142b0f82e7aSAlexis Lothoré (eBPF Foundation) 
143b0f82e7aSAlexis Lothoré (eBPF Foundation) 	cleanup();
144b0f82e7aSAlexis Lothoré (eBPF Foundation) 	test_tc_edt__destroy(skel);
145b0f82e7aSAlexis Lothoré (eBPF Foundation) }
146