brintos

brintos / linux-shallow public Read only

0
0
Text · 4.1 KiB · 2d07963 Raw
172 lines · c
1// SPDX-License-Identifier: GPL-2.02// Copyright (c) 2020 Cloudflare3/*4 * Tests for sockmap/sockhash holding kTLS sockets.5 */6 7#include <netinet/tcp.h>8#include "test_progs.h"9 10#define MAX_TEST_NAME 8011#define TCP_ULP 3112 13static int tcp_server(int family)14{15	int err, s;16 17	s = socket(family, SOCK_STREAM, 0);18	if (!ASSERT_GE(s, 0, "socket"))19		return -1;20 21	err = listen(s, SOMAXCONN);22	if (!ASSERT_OK(err, "listen"))23		return -1;24 25	return s;26}27 28static int disconnect(int fd)29{30	struct sockaddr unspec = { AF_UNSPEC };31 32	return connect(fd, &unspec, sizeof(unspec));33}34 35/* Disconnect (unhash) a kTLS socket after removing it from sockmap. */36static void test_sockmap_ktls_disconnect_after_delete(int family, int map)37{38	struct sockaddr_storage addr = {0};39	socklen_t len = sizeof(addr);40	int err, cli, srv, zero = 0;41 42	srv = tcp_server(family);43	if (srv == -1)44		return;45 46	err = getsockname(srv, (struct sockaddr *)&addr, &len);47	if (!ASSERT_OK(err, "getsockopt"))48		goto close_srv;49 50	cli = socket(family, SOCK_STREAM, 0);51	if (!ASSERT_GE(cli, 0, "socket"))52		goto close_srv;53 54	err = connect(cli, (struct sockaddr *)&addr, len);55	if (!ASSERT_OK(err, "connect"))56		goto close_cli;57 58	err = bpf_map_update_elem(map, &zero, &cli, 0);59	if (!ASSERT_OK(err, "bpf_map_update_elem"))60		goto close_cli;61 62	err = setsockopt(cli, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));63	if (!ASSERT_OK(err, "setsockopt(TCP_ULP)"))64		goto close_cli;65 66	err = bpf_map_delete_elem(map, &zero);67	if (!ASSERT_OK(err, "bpf_map_delete_elem"))68		goto close_cli;69 70	err = disconnect(cli);71	ASSERT_OK(err, "disconnect");72 73close_cli:74	close(cli);75close_srv:76	close(srv);77}78 79static void test_sockmap_ktls_update_fails_when_sock_has_ulp(int family, int map)80{81	struct sockaddr_storage addr = {};82	socklen_t len = sizeof(addr);83	struct sockaddr_in6 *v6;84	struct sockaddr_in *v4;85	int err, s, zero = 0;86 87	switch (family) {88	case AF_INET:89		v4 = (struct sockaddr_in *)&addr;90		v4->sin_family = AF_INET;91		break;92	case AF_INET6:93		v6 = (struct sockaddr_in6 *)&addr;94		v6->sin6_family = AF_INET6;95		break;96	default:97		PRINT_FAIL("unsupported socket family %d", family);98		return;99	}100 101	s = socket(family, SOCK_STREAM, 0);102	if (!ASSERT_GE(s, 0, "socket"))103		return;104 105	err = bind(s, (struct sockaddr *)&addr, len);106	if (!ASSERT_OK(err, "bind"))107		goto close;108 109	err = getsockname(s, (struct sockaddr *)&addr, &len);110	if (!ASSERT_OK(err, "getsockname"))111		goto close;112 113	err = connect(s, (struct sockaddr *)&addr, len);114	if (!ASSERT_OK(err, "connect"))115		goto close;116 117	/* save sk->sk_prot and set it to tls_prots */118	err = setsockopt(s, IPPROTO_TCP, TCP_ULP, "tls", strlen("tls"));119	if (!ASSERT_OK(err, "setsockopt(TCP_ULP)"))120		goto close;121 122	/* sockmap update should not affect saved sk_prot */123	err = bpf_map_update_elem(map, &zero, &s, BPF_ANY);124	if (!ASSERT_ERR(err, "sockmap update elem"))125		goto close;126 127	/* call sk->sk_prot->setsockopt to dispatch to saved sk_prot */128	err = setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &zero, sizeof(zero));129	ASSERT_OK(err, "setsockopt(TCP_NODELAY)");130 131close:132	close(s);133}134 135static const char *fmt_test_name(const char *subtest_name, int family,136				 enum bpf_map_type map_type)137{138	const char *map_type_str = BPF_MAP_TYPE_SOCKMAP ? "SOCKMAP" : "SOCKHASH";139	const char *family_str = AF_INET ? "IPv4" : "IPv6";140	static char test_name[MAX_TEST_NAME];141 142	snprintf(test_name, MAX_TEST_NAME,143		 "sockmap_ktls %s %s %s",144		 subtest_name, family_str, map_type_str);145 146	return test_name;147}148 149static void run_tests(int family, enum bpf_map_type map_type)150{151	int map;152 153	map = bpf_map_create(map_type, NULL, sizeof(int), sizeof(int), 1, NULL);154	if (!ASSERT_GE(map, 0, "bpf_map_create"))155		return;156 157	if (test__start_subtest(fmt_test_name("disconnect_after_delete", family, map_type)))158		test_sockmap_ktls_disconnect_after_delete(family, map);159	if (test__start_subtest(fmt_test_name("update_fails_when_sock_has_ulp", family, map_type)))160		test_sockmap_ktls_update_fails_when_sock_has_ulp(family, map);161 162	close(map);163}164 165void test_sockmap_ktls(void)166{167	run_tests(AF_INET, BPF_MAP_TYPE_SOCKMAP);168	run_tests(AF_INET, BPF_MAP_TYPE_SOCKHASH);169	run_tests(AF_INET6, BPF_MAP_TYPE_SOCKMAP);170	run_tests(AF_INET6, BPF_MAP_TYPE_SOCKHASH);171}172