Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // Copyright (c) 2020 Cloudflare
0003 /*
0004  * Tests for sockmap/sockhash holding kTLS sockets.
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 /* Disconnect (unhash) a kTLS socket after removing it from sockmap. */
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     /* save sk->sk_prot and set it to tls_prots */
0135     err = setsockopt(s, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));
0136     if (!ASSERT_OK(err, "setsockopt(TCP_ULP)"))
0137         goto close;
0138 
0139     /* sockmap update should not affect saved sk_prot */
0140     err = bpf_map_update_elem(map, &zero, &s, BPF_ANY);
0141     if (!ASSERT_ERR(err, "sockmap update elem"))
0142         goto close;
0143 
0144     /* call sk->sk_prot->setsockopt to dispatch to saved sk_prot */
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 }