0001
0002
0003 #define _GNU_SOURCE
0004 #include <sched.h>
0005 #include <test_progs.h>
0006 #include "network_helpers.h"
0007 #include "bpf_dctcp.skel.h"
0008 #include "bpf_cubic.skel.h"
0009 #include "bpf_iter_setsockopt.skel.h"
0010
0011 static int create_netns(void)
0012 {
0013 if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns"))
0014 return -1;
0015
0016 if (!ASSERT_OK(system("ip link set dev lo up"), "bring up lo"))
0017 return -1;
0018
0019 return 0;
0020 }
0021
0022 static unsigned int set_bpf_cubic(int *fds, unsigned int nr_fds)
0023 {
0024 unsigned int i;
0025
0026 for (i = 0; i < nr_fds; i++) {
0027 if (setsockopt(fds[i], SOL_TCP, TCP_CONGESTION, "bpf_cubic",
0028 sizeof("bpf_cubic")))
0029 return i;
0030 }
0031
0032 return nr_fds;
0033 }
0034
0035 static unsigned int check_bpf_dctcp(int *fds, unsigned int nr_fds)
0036 {
0037 char tcp_cc[16];
0038 socklen_t optlen = sizeof(tcp_cc);
0039 unsigned int i;
0040
0041 for (i = 0; i < nr_fds; i++) {
0042 if (getsockopt(fds[i], SOL_TCP, TCP_CONGESTION,
0043 tcp_cc, &optlen) ||
0044 strcmp(tcp_cc, "bpf_dctcp"))
0045 return i;
0046 }
0047
0048 return nr_fds;
0049 }
0050
0051 static int *make_established(int listen_fd, unsigned int nr_est,
0052 int **paccepted_fds)
0053 {
0054 int *est_fds, *accepted_fds;
0055 unsigned int i;
0056
0057 est_fds = malloc(sizeof(*est_fds) * nr_est);
0058 if (!est_fds)
0059 return NULL;
0060
0061 accepted_fds = malloc(sizeof(*accepted_fds) * nr_est);
0062 if (!accepted_fds) {
0063 free(est_fds);
0064 return NULL;
0065 }
0066
0067 for (i = 0; i < nr_est; i++) {
0068 est_fds[i] = connect_to_fd(listen_fd, 0);
0069 if (est_fds[i] == -1)
0070 break;
0071 if (set_bpf_cubic(&est_fds[i], 1) != 1) {
0072 close(est_fds[i]);
0073 break;
0074 }
0075
0076 accepted_fds[i] = accept(listen_fd, NULL, 0);
0077 if (accepted_fds[i] == -1) {
0078 close(est_fds[i]);
0079 break;
0080 }
0081 }
0082
0083 if (!ASSERT_EQ(i, nr_est, "create established fds")) {
0084 free_fds(accepted_fds, i);
0085 free_fds(est_fds, i);
0086 return NULL;
0087 }
0088
0089 *paccepted_fds = accepted_fds;
0090 return est_fds;
0091 }
0092
0093 static unsigned short get_local_port(int fd)
0094 {
0095 struct sockaddr_in6 addr;
0096 socklen_t addrlen = sizeof(addr);
0097
0098 if (!getsockname(fd, &addr, &addrlen))
0099 return ntohs(addr.sin6_port);
0100
0101 return 0;
0102 }
0103
0104 static void do_bpf_iter_setsockopt(struct bpf_iter_setsockopt *iter_skel,
0105 bool random_retry)
0106 {
0107 int *reuse_listen_fds = NULL, *accepted_fds = NULL, *est_fds = NULL;
0108 unsigned int nr_reuse_listens = 256, nr_est = 256;
0109 int err, iter_fd = -1, listen_fd = -1;
0110 char buf;
0111
0112
0113 listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0);
0114 if (!ASSERT_GE(listen_fd, 0, "start_server"))
0115 return;
0116 if (!ASSERT_EQ(set_bpf_cubic(&listen_fd, 1), 1,
0117 "set listen_fd to cubic"))
0118 goto done;
0119 iter_skel->bss->listen_hport = get_local_port(listen_fd);
0120 if (!ASSERT_NEQ(iter_skel->bss->listen_hport, 0,
0121 "get_local_port(listen_fd)"))
0122 goto done;
0123
0124
0125 est_fds = make_established(listen_fd, nr_est, &accepted_fds);
0126 if (!ASSERT_OK_PTR(est_fds, "create established"))
0127 goto done;
0128
0129
0130 reuse_listen_fds = start_reuseport_server(AF_INET6, SOCK_STREAM,
0131 "::1", 0, 0,
0132 nr_reuse_listens);
0133 if (!ASSERT_OK_PTR(reuse_listen_fds, "start_reuseport_server"))
0134 goto done;
0135 if (!ASSERT_EQ(set_bpf_cubic(reuse_listen_fds, nr_reuse_listens),
0136 nr_reuse_listens, "set reuse_listen_fds to cubic"))
0137 goto done;
0138 iter_skel->bss->reuse_listen_hport = get_local_port(reuse_listen_fds[0]);
0139 if (!ASSERT_NEQ(iter_skel->bss->reuse_listen_hport, 0,
0140 "get_local_port(reuse_listen_fds[0])"))
0141 goto done;
0142
0143
0144 iter_skel->bss->random_retry = random_retry;
0145 iter_fd = bpf_iter_create(bpf_link__fd(iter_skel->links.change_tcp_cc));
0146 if (!ASSERT_GE(iter_fd, 0, "create iter_fd"))
0147 goto done;
0148
0149 while ((err = read(iter_fd, &buf, sizeof(buf))) == -1 &&
0150 errno == EAGAIN)
0151 ;
0152 if (!ASSERT_OK(err, "read iter error"))
0153 goto done;
0154
0155
0156 ASSERT_EQ(check_bpf_dctcp(reuse_listen_fds, nr_reuse_listens),
0157 nr_reuse_listens,
0158 "check reuse_listen_fds dctcp");
0159
0160
0161 ASSERT_EQ(check_bpf_dctcp(&listen_fd, 1), 1,
0162 "check listen_fd dctcp");
0163
0164
0165 ASSERT_EQ(check_bpf_dctcp(est_fds, nr_est), nr_est,
0166 "check est_fds dctcp");
0167
0168
0169 ASSERT_EQ(check_bpf_dctcp(accepted_fds, nr_est), nr_est,
0170 "check accepted_fds dctcp");
0171
0172 done:
0173 if (iter_fd != -1)
0174 close(iter_fd);
0175 if (listen_fd != -1)
0176 close(listen_fd);
0177 free_fds(reuse_listen_fds, nr_reuse_listens);
0178 free_fds(accepted_fds, nr_est);
0179 free_fds(est_fds, nr_est);
0180 }
0181
0182 void serial_test_bpf_iter_setsockopt(void)
0183 {
0184 struct bpf_iter_setsockopt *iter_skel = NULL;
0185 struct bpf_cubic *cubic_skel = NULL;
0186 struct bpf_dctcp *dctcp_skel = NULL;
0187 struct bpf_link *cubic_link = NULL;
0188 struct bpf_link *dctcp_link = NULL;
0189
0190 if (create_netns())
0191 return;
0192
0193
0194 iter_skel = bpf_iter_setsockopt__open_and_load();
0195 if (!ASSERT_OK_PTR(iter_skel, "iter_skel"))
0196 return;
0197 iter_skel->links.change_tcp_cc = bpf_program__attach_iter(iter_skel->progs.change_tcp_cc, NULL);
0198 if (!ASSERT_OK_PTR(iter_skel->links.change_tcp_cc, "attach iter"))
0199 goto done;
0200
0201
0202 cubic_skel = bpf_cubic__open_and_load();
0203 if (!ASSERT_OK_PTR(cubic_skel, "cubic_skel"))
0204 goto done;
0205 cubic_link = bpf_map__attach_struct_ops(cubic_skel->maps.cubic);
0206 if (!ASSERT_OK_PTR(cubic_link, "cubic_link"))
0207 goto done;
0208
0209
0210 dctcp_skel = bpf_dctcp__open_and_load();
0211 if (!ASSERT_OK_PTR(dctcp_skel, "dctcp_skel"))
0212 goto done;
0213 dctcp_link = bpf_map__attach_struct_ops(dctcp_skel->maps.dctcp);
0214 if (!ASSERT_OK_PTR(dctcp_link, "dctcp_link"))
0215 goto done;
0216
0217 do_bpf_iter_setsockopt(iter_skel, true);
0218 do_bpf_iter_setsockopt(iter_skel, false);
0219
0220 done:
0221 bpf_link__destroy(cubic_link);
0222 bpf_link__destroy(dctcp_link);
0223 bpf_cubic__destroy(cubic_skel);
0224 bpf_dctcp__destroy(dctcp_skel);
0225 bpf_iter_setsockopt__destroy(iter_skel);
0226 }