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