0001
0002
0003
0004
0005
0006
0007 #include <netinet/tcp.h>
0008 #include "test_progs.h"
0009
0010 #define MAX_TEST_NAME 80
0011 #define TCP_ULP 31
0012
0013 static int tcp_server(int family)
0014 {
0015 int err, s;
0016
0017 s = socket(family, SOCK_STREAM, 0);
0018 if (CHECK_FAIL(s == -1)) {
0019 perror("socket");
0020 return -1;
0021 }
0022
0023 err = listen(s, SOMAXCONN);
0024 if (CHECK_FAIL(err)) {
0025 perror("listen");
0026 return -1;
0027 }
0028
0029 return s;
0030 }
0031
0032 static int disconnect(int fd)
0033 {
0034 struct sockaddr unspec = { AF_UNSPEC };
0035
0036 return connect(fd, &unspec, sizeof(unspec));
0037 }
0038
0039
0040 static void test_sockmap_ktls_disconnect_after_delete(int family, int map)
0041 {
0042 struct sockaddr_storage addr = {0};
0043 socklen_t len = sizeof(addr);
0044 int err, cli, srv, zero = 0;
0045
0046 srv = tcp_server(family);
0047 if (srv == -1)
0048 return;
0049
0050 err = getsockname(srv, (struct sockaddr *)&addr, &len);
0051 if (CHECK_FAIL(err)) {
0052 perror("getsockopt");
0053 goto close_srv;
0054 }
0055
0056 cli = socket(family, SOCK_STREAM, 0);
0057 if (CHECK_FAIL(cli == -1)) {
0058 perror("socket");
0059 goto close_srv;
0060 }
0061
0062 err = connect(cli, (struct sockaddr *)&addr, len);
0063 if (CHECK_FAIL(err)) {
0064 perror("connect");
0065 goto close_cli;
0066 }
0067
0068 err = bpf_map_update_elem(map, &zero, &cli, 0);
0069 if (CHECK_FAIL(err)) {
0070 perror("bpf_map_update_elem");
0071 goto close_cli;
0072 }
0073
0074 err = setsockopt(cli, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
0075 if (CHECK_FAIL(err)) {
0076 perror("setsockopt(TCP_ULP)");
0077 goto close_cli;
0078 }
0079
0080 err = bpf_map_delete_elem(map, &zero);
0081 if (CHECK_FAIL(err)) {
0082 perror("bpf_map_delete_elem");
0083 goto close_cli;
0084 }
0085
0086 err = disconnect(cli);
0087 if (CHECK_FAIL(err))
0088 perror("disconnect");
0089
0090 close_cli:
0091 close(cli);
0092 close_srv:
0093 close(srv);
0094 }
0095
0096 static void test_sockmap_ktls_update_fails_when_sock_has_ulp(int family, int map)
0097 {
0098 struct sockaddr_storage addr = {};
0099 socklen_t len = sizeof(addr);
0100 struct sockaddr_in6 *v6;
0101 struct sockaddr_in *v4;
0102 int err, s, zero = 0;
0103
0104 switch (family) {
0105 case AF_INET:
0106 v4 = (struct sockaddr_in *)&addr;
0107 v4->sin_family = AF_INET;
0108 break;
0109 case AF_INET6:
0110 v6 = (struct sockaddr_in6 *)&addr;
0111 v6->sin6_family = AF_INET6;
0112 break;
0113 default:
0114 PRINT_FAIL("unsupported socket family %d", family);
0115 return;
0116 }
0117
0118 s = socket(family, SOCK_STREAM, 0);
0119 if (!ASSERT_GE(s, 0, "socket"))
0120 return;
0121
0122 err = bind(s, (struct sockaddr *)&addr, len);
0123 if (!ASSERT_OK(err, "bind"))
0124 goto close;
0125
0126 err = getsockname(s, (struct sockaddr *)&addr, &len);
0127 if (!ASSERT_OK(err, "getsockname"))
0128 goto close;
0129
0130 err = connect(s, (struct sockaddr *)&addr, len);
0131 if (!ASSERT_OK(err, "connect"))
0132 goto close;
0133
0134
0135 err = setsockopt(s, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
0136 if (!ASSERT_OK(err, "setsockopt(TCP_ULP)"))
0137 goto close;
0138
0139
0140 err = bpf_map_update_elem(map, &zero, &s, BPF_ANY);
0141 if (!ASSERT_ERR(err, "sockmap update elem"))
0142 goto close;
0143
0144
0145 err = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &zero, sizeof(zero));
0146 ASSERT_OK(err, "setsockopt(TCP_NODELAY)");
0147
0148 close:
0149 close(s);
0150 }
0151
0152 static const char *fmt_test_name(const char *subtest_name, int family,
0153 enum bpf_map_type map_type)
0154 {
0155 const char *map_type_str = BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH";
0156 const char *family_str = AF_INET ? "IPv4" : "IPv6";
0157 static char test_name[MAX_TEST_NAME];
0158
0159 snprintf(test_name, MAX_TEST_NAME,
0160 "sockmap_ktls %s %s %s",
0161 subtest_name, family_str, map_type_str);
0162
0163 return test_name;
0164 }
0165
0166 static void run_tests(int family, enum bpf_map_type map_type)
0167 {
0168 int map;
0169
0170 map = bpf_map_create(map_type, NULL, sizeof(int), sizeof(int), 1, NULL);
0171 if (CHECK_FAIL(map < 0)) {
0172 perror("bpf_map_create");
0173 return;
0174 }
0175
0176 if (test__start_subtest(fmt_test_name("disconnect_after_delete", family, map_type)))
0177 test_sockmap_ktls_disconnect_after_delete(family, map);
0178 if (test__start_subtest(fmt_test_name("update_fails_when_sock_has_ulp", family, map_type)))
0179 test_sockmap_ktls_update_fails_when_sock_has_ulp(family, map);
0180
0181 close(map);
0182 }
0183
0184 void test_sockmap_ktls(void)
0185 {
0186 run_tests(AF_INET, BPF_MAP_TYPE_SOCKMAP);
0187 run_tests(AF_INET, BPF_MAP_TYPE_SOCKHASH);
0188 run_tests(AF_INET6, BPF_MAP_TYPE_SOCKMAP);
0189 run_tests(AF_INET6, BPF_MAP_TYPE_SOCKHASH);
0190 }