1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2020 Cloudflare
3 #include <error.h>
4 
5 #include "test_progs.h"
6 #include "test_skmsg_load_helpers.skel.h"
7 
8 #define TCP_REPAIR		19	/* TCP sock is under repair right now */
9 
10 #define TCP_REPAIR_ON		1
11 #define TCP_REPAIR_OFF_NO_WP	-1	/* Turn off without window probes */
12 
13 static int connected_socket_v4(void)
14 {
15 	struct sockaddr_in addr = {
16 		.sin_family = AF_INET,
17 		.sin_port = htons(80),
18 		.sin_addr = { inet_addr("127.0.0.1") },
19 	};
20 	socklen_t len = sizeof(addr);
21 	int s, repair, err;
22 
23 	s = socket(AF_INET, SOCK_STREAM, 0);
24 	if (CHECK_FAIL(s == -1))
25 		goto error;
26 
27 	repair = TCP_REPAIR_ON;
28 	err = setsockopt(s, SOL_TCP, TCP_REPAIR, &repair, sizeof(repair));
29 	if (CHECK_FAIL(err))
30 		goto error;
31 
32 	err = connect(s, (struct sockaddr *)&addr, len);
33 	if (CHECK_FAIL(err))
34 		goto error;
35 
36 	repair = TCP_REPAIR_OFF_NO_WP;
37 	err = setsockopt(s, SOL_TCP, TCP_REPAIR, &repair, sizeof(repair));
38 	if (CHECK_FAIL(err))
39 		goto error;
40 
41 	return s;
42 error:
43 	perror(__func__);
44 	close(s);
45 	return -1;
46 }
47 
48 /* Create a map, populate it with one socket, and free the map. */
49 static void test_sockmap_create_update_free(enum bpf_map_type map_type)
50 {
51 	const int zero = 0;
52 	int s, map, err;
53 
54 	s = connected_socket_v4();
55 	if (CHECK_FAIL(s == -1))
56 		return;
57 
58 	map = bpf_create_map(map_type, sizeof(int), sizeof(int), 1, 0);
59 	if (CHECK_FAIL(map == -1)) {
60 		perror("bpf_create_map");
61 		goto out;
62 	}
63 
64 	err = bpf_map_update_elem(map, &zero, &s, BPF_NOEXIST);
65 	if (CHECK_FAIL(err)) {
66 		perror("bpf_map_update");
67 		goto out;
68 	}
69 
70 out:
71 	close(map);
72 	close(s);
73 }
74 
75 static void test_skmsg_helpers(enum bpf_map_type map_type)
76 {
77 	struct test_skmsg_load_helpers *skel;
78 	int err, map, verdict;
79 
80 	skel = test_skmsg_load_helpers__open_and_load();
81 	if (CHECK_FAIL(!skel)) {
82 		perror("test_skmsg_load_helpers__open_and_load");
83 		return;
84 	}
85 
86 	verdict = bpf_program__fd(skel->progs.prog_msg_verdict);
87 	map = bpf_map__fd(skel->maps.sock_map);
88 
89 	err = bpf_prog_attach(verdict, map, BPF_SK_MSG_VERDICT, 0);
90 	if (CHECK_FAIL(err)) {
91 		perror("bpf_prog_attach");
92 		goto out;
93 	}
94 
95 	err = bpf_prog_detach2(verdict, map, BPF_SK_MSG_VERDICT);
96 	if (CHECK_FAIL(err)) {
97 		perror("bpf_prog_detach2");
98 		goto out;
99 	}
100 out:
101 	test_skmsg_load_helpers__destroy(skel);
102 }
103 
104 void test_sockmap_basic(void)
105 {
106 	if (test__start_subtest("sockmap create_update_free"))
107 		test_sockmap_create_update_free(BPF_MAP_TYPE_SOCKMAP);
108 	if (test__start_subtest("sockhash create_update_free"))
109 		test_sockmap_create_update_free(BPF_MAP_TYPE_SOCKHASH);
110 	if (test__start_subtest("sockmap sk_msg load helpers"))
111 		test_skmsg_helpers(BPF_MAP_TYPE_SOCKMAP);
112 	if (test__start_subtest("sockhash sk_msg load helpers"))
113 		test_skmsg_helpers(BPF_MAP_TYPE_SOCKHASH);
114 }
115