xref: /linux/tools/testing/selftests/bpf/prog_tests/tc_change_tail_pmtu.c (revision 5fc5768c7ca92895ccd1de94dc521e5a55ae7896)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <netinet/tcp.h>
4 
5 #include "test_progs.h"
6 #include "network_helpers.h"
7 #include "test_tc_change_tail_pmtu.skel.h"
8 
9 #define CLIENT_NS	"tc-change-tail-cli-ns"
10 #define SERVER_NS	"tc-change-tail-srv-ns"
11 #define CLIENT_IP	"192.168.1.1"
12 #define SERVER_IP	"192.168.1.2"
13 
14 #define TEST_PMTU	1000
15 #define TEST_MSS_MAX	(TEST_PMTU - 20 - 20)
16 #define TIMEOUT_MS	3000
17 #define XFER_BYTES	8192
18 
test_tc_change_tail_pmtu(void)19 void test_tc_change_tail_pmtu(void)
20 {
21 	LIBBPF_OPTS(bpf_tcx_opts, tcx_opts);
22 	int mss_before = 0, mss_after = 0, ifindex, port;
23 	int srv_fd = -1, srv_conn_fd = -1, cli_fd = -1;
24 	struct test_tc_change_tail_pmtu *skel = NULL;
25 	struct nstoken *nstoken = NULL;
26 	static char buf[XFER_BYTES];
27 	socklen_t optlen;
28 	ssize_t bytes;
29 	size_t total;
30 
31 	if (!ASSERT_OK(make_netns(CLIENT_NS), "make client ns"))
32 		return;
33 	if (!ASSERT_OK(make_netns(SERVER_NS), "make server ns"))
34 		goto out_client_ns;
35 
36 	nstoken = open_netns(CLIENT_NS);
37 	if (!ASSERT_OK_PTR(nstoken, "open client ns"))
38 		goto out;
39 	SYS(out, "ip link add veth1 type veth peer name veth2 netns " SERVER_NS);
40 	SYS(out, "ip -4 addr add " CLIENT_IP "/24 dev veth1");
41 	SYS(out, "ip link set veth1 up");
42 	ifindex = if_nametoindex("veth1");
43 	if (!ASSERT_NEQ(ifindex, 0, "if_nametoindex"))
44 		goto out;
45 	close_netns(nstoken);
46 	nstoken = NULL;
47 
48 	nstoken = open_netns(SERVER_NS);
49 	if (!ASSERT_OK_PTR(nstoken, "open server ns"))
50 		goto out;
51 	SYS(out, "ip -4 addr add " SERVER_IP "/24 dev veth2");
52 	SYS(out, "ip link set veth2 up");
53 	srv_fd = start_server(AF_INET, SOCK_STREAM, SERVER_IP, 0, TIMEOUT_MS);
54 	if (!ASSERT_OK_FD(srv_fd, "start server"))
55 		goto out;
56 	close_netns(nstoken);
57 	nstoken = NULL;
58 
59 	skel = test_tc_change_tail_pmtu__open_and_load();
60 	if (!ASSERT_OK_PTR(skel, "open and load skeleton"))
61 		goto out;
62 
63 	port = get_socket_local_port(srv_fd);
64 	if (!ASSERT_GE(port, 0, "get server port"))
65 		goto out;
66 
67 	skel->bss->server_port = port;
68 	skel->bss->pmtu = TEST_PMTU;
69 
70 	nstoken = open_netns(CLIENT_NS);
71 	if (!ASSERT_OK_PTR(nstoken, "open client ns"))
72 		goto out;
73 
74 	skel->links.change_tail_icmp =
75 		bpf_program__attach_tcx(skel->progs.change_tail_icmp, ifindex,
76 					&tcx_opts);
77 	if (!ASSERT_OK_PTR(skel->links.change_tail_icmp, "attach tcx"))
78 		goto out;
79 
80 	cli_fd = connect_to_fd(srv_fd, TIMEOUT_MS);
81 	if (!ASSERT_OK_FD(cli_fd, "connect to server"))
82 		goto out;
83 	srv_conn_fd = accept(srv_fd, NULL, NULL);
84 	if (!ASSERT_OK_FD(srv_conn_fd, "accept connection"))
85 		goto out;
86 	if (!ASSERT_OK(settimeo(srv_conn_fd, TIMEOUT_MS), "set server timeout"))
87 		goto out;
88 
89 	optlen = sizeof(mss_before);
90 	if (!ASSERT_OK(getsockopt(cli_fd, IPPROTO_TCP, TCP_MAXSEG, &mss_before,
91 				  &optlen), "get mss before"))
92 		goto out;
93 
94 	bytes = send(cli_fd, buf, sizeof(buf), 0);
95 	if (!ASSERT_EQ(bytes, (ssize_t)sizeof(buf), "send data"))
96 		goto out;
97 
98 	for (total = 0; total < sizeof(buf); total += bytes) {
99 		bytes = recv(srv_conn_fd, buf, sizeof(buf), 0);
100 		if (bytes <= 0)
101 			break;
102 	}
103 
104 	ASSERT_EQ(total, sizeof(buf), "receive data");
105 	ASSERT_OK(skel->data->change_tail_ret, "change tail");
106 	ASSERT_OK(skel->bss->adjust_room_ret, "adjust room");
107 	ASSERT_TRUE(skel->bss->icmp_sent, "icmp sent");
108 
109 	optlen = sizeof(mss_after);
110 	if (!ASSERT_OK(getsockopt(cli_fd, IPPROTO_TCP, TCP_MAXSEG, &mss_after,
111 				  &optlen), "get mss after"))
112 		goto out;
113 
114 	ASSERT_LT(mss_after, mss_before, "mss reduced");
115 	ASSERT_LE(mss_after, TEST_MSS_MAX, "mss below pmtu");
116 out:
117 	close(srv_conn_fd);
118 	close(cli_fd);
119 	close(srv_fd);
120 	test_tc_change_tail_pmtu__destroy(skel);
121 	close_netns(nstoken);
122 	remove_netns(SERVER_NS);
123 out_client_ns:
124 	remove_netns(CLIENT_NS);
125 }
126