1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) 2020 Cloudflare 3 /* 4 * Tests for sockmap/sockhash holding kTLS sockets. 5 */ 6 7 #include "test_progs.h" 8 9 #define MAX_TEST_NAME 80 10 #define TCP_ULP 31 11 12 static int tcp_server(int family) 13 { 14 int err, s; 15 16 s = socket(family, SOCK_STREAM, 0); 17 if (CHECK_FAIL(s == -1)) { 18 perror("socket"); 19 return -1; 20 } 21 22 err = listen(s, SOMAXCONN); 23 if (CHECK_FAIL(err)) { 24 perror("listen"); 25 return -1; 26 } 27 28 return s; 29 } 30 31 static int disconnect(int fd) 32 { 33 struct sockaddr unspec = { AF_UNSPEC }; 34 35 return connect(fd, &unspec, sizeof(unspec)); 36 } 37 38 /* Disconnect (unhash) a kTLS socket after removing it from sockmap. */ 39 static void test_sockmap_ktls_disconnect_after_delete(int family, int map) 40 { 41 struct sockaddr_storage addr = {0}; 42 socklen_t len = sizeof(addr); 43 int err, cli, srv, zero = 0; 44 45 srv = tcp_server(family); 46 if (srv == -1) 47 return; 48 49 err = getsockname(srv, (struct sockaddr *)&addr, &len); 50 if (CHECK_FAIL(err)) { 51 perror("getsockopt"); 52 goto close_srv; 53 } 54 55 cli = socket(family, SOCK_STREAM, 0); 56 if (CHECK_FAIL(cli == -1)) { 57 perror("socket"); 58 goto close_srv; 59 } 60 61 err = connect(cli, (struct sockaddr *)&addr, len); 62 if (CHECK_FAIL(err)) { 63 perror("connect"); 64 goto close_cli; 65 } 66 67 err = bpf_map_update_elem(map, &zero, &cli, 0); 68 if (CHECK_FAIL(err)) { 69 perror("bpf_map_update_elem"); 70 goto close_cli; 71 } 72 73 err = setsockopt(cli, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls")); 74 if (CHECK_FAIL(err)) { 75 perror("setsockopt(TCP_ULP)"); 76 goto close_cli; 77 } 78 79 err = bpf_map_delete_elem(map, &zero); 80 if (CHECK_FAIL(err)) { 81 perror("bpf_map_delete_elem"); 82 goto close_cli; 83 } 84 85 err = disconnect(cli); 86 if (CHECK_FAIL(err)) 87 perror("disconnect"); 88 89 close_cli: 90 close(cli); 91 close_srv: 92 close(srv); 93 } 94 95 static void run_tests(int family, enum bpf_map_type map_type) 96 { 97 char test_name[MAX_TEST_NAME]; 98 int map; 99 100 map = bpf_create_map(map_type, sizeof(int), sizeof(int), 1, 0); 101 if (CHECK_FAIL(map == -1)) { 102 perror("bpf_map_create"); 103 return; 104 } 105 106 snprintf(test_name, MAX_TEST_NAME, 107 "sockmap_ktls disconnect_after_delete %s %s", 108 family == AF_INET ? "IPv4" : "IPv6", 109 map_type == BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH"); 110 if (!test__start_subtest(test_name)) 111 return; 112 113 test_sockmap_ktls_disconnect_after_delete(family, map); 114 115 close(map); 116 } 117 118 void test_sockmap_ktls(void) 119 { 120 run_tests(AF_INET, BPF_MAP_TYPE_SOCKMAP); 121 run_tests(AF_INET, BPF_MAP_TYPE_SOCKHASH); 122 run_tests(AF_INET6, BPF_MAP_TYPE_SOCKMAP); 123 run_tests(AF_INET6, BPF_MAP_TYPE_SOCKHASH); 124 } 125