Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2020 Facebook */
  3
  4#define _GNU_SOURCE
  5#include <netinet/in.h>
  6#include <arpa/inet.h>
  7#include <unistd.h>
  8#include <stdlib.h>
  9#include <string.h>
 10#include <errno.h>
 11#include <sched.h>
 12#include <net/if.h>
 13#include <linux/compiler.h>
 14#include <bpf/libbpf.h>
 15
 16#include "network_helpers.h"
 17#include "test_progs.h"
 18#include "test_btf_skc_cls_ingress.skel.h"
 19
 20#define TEST_NS "skc_cls_ingress"
 
 
 21
 22#define BIT(n)		(1 << (n))
 23#define TEST_MODE_IPV4	BIT(0)
 24#define TEST_MODE_IPV6	BIT(1)
 25#define TEST_MODE_DUAL	(TEST_MODE_IPV4 | TEST_MODE_IPV6)
 26
 27#define SERVER_ADDR_IPV4	"127.0.0.1"
 28#define SERVER_ADDR_IPV6	"::1"
 29#define SERVER_ADDR_DUAL	"::0"
 30/* RFC791, 576 for minimal IPv4 datagram, minus 40 bytes of TCP header */
 31#define MIN_IPV4_MSS		536
 32
 33static struct netns_obj *prepare_netns(struct test_btf_skc_cls_ingress *skel)
 34{
 35	LIBBPF_OPTS(bpf_tc_hook, qdisc_lo, .attach_point = BPF_TC_INGRESS);
 36	LIBBPF_OPTS(bpf_tc_opts, tc_attach,
 37		    .prog_fd = bpf_program__fd(skel->progs.cls_ingress));
 38	struct netns_obj *ns = NULL;
 39
 40	ns = netns_new(TEST_NS, true);
 41	if (!ASSERT_OK_PTR(ns, "create and join netns"))
 42		return ns;
 
 
 
 
 
 43
 44	qdisc_lo.ifindex = if_nametoindex("lo");
 45	if (!ASSERT_OK(bpf_tc_hook_create(&qdisc_lo), "qdisc add dev lo clsact"))
 46		goto free_ns;
 47
 48	if (!ASSERT_OK(bpf_tc_attach(&qdisc_lo, &tc_attach),
 49		       "filter add dev lo ingress"))
 50		goto free_ns;
 51
 52	/* Ensure 20 bytes options (i.e. in total 40 bytes tcp header) for the
 53	 * bpf_tcp_gen_syncookie() helper.
 54	 */
 55	if (write_sysctl("/proc/sys/net/ipv4/tcp_window_scaling", "1") ||
 56	    write_sysctl("/proc/sys/net/ipv4/tcp_timestamps", "1") ||
 57	    write_sysctl("/proc/sys/net/ipv4/tcp_sack", "1"))
 58		goto free_ns;
 59
 60	return ns;
 61
 62free_ns:
 63	netns_free(ns);
 64	return NULL;
 65}
 66
 67static void reset_test(struct test_btf_skc_cls_ingress *skel)
 68{
 69	memset(&skel->bss->srv_sa4, 0, sizeof(skel->bss->srv_sa4));
 70	memset(&skel->bss->srv_sa6, 0, sizeof(skel->bss->srv_sa6));
 71	skel->bss->listen_tp_sport = 0;
 72	skel->bss->req_sk_sport = 0;
 73	skel->bss->recv_cookie = 0;
 74	skel->bss->gen_cookie = 0;
 75	skel->bss->linum = 0;
 76	skel->bss->mss = 0;
 77}
 78
 79static void print_err_line(struct test_btf_skc_cls_ingress *skel)
 80{
 81	if (skel->bss->linum)
 82		printf("bpf prog error at line %u\n", skel->bss->linum);
 83}
 84
 85static int v6only_true(int fd, void *opts)
 86{
 87	int mode = true;
 88
 89	return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode));
 90}
 91
 92static int v6only_false(int fd, void *opts)
 93{
 94	int mode = false;
 95
 96	return setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &mode, sizeof(mode));
 97}
 98
 99static void run_test(struct test_btf_skc_cls_ingress *skel, bool gen_cookies,
100		     int ip_mode)
101{
102	const char *tcp_syncookies = gen_cookies ? "2" : "1";
103	int listen_fd = -1, cli_fd = -1, srv_fd = -1, err;
104	struct network_helper_opts opts = { 0 };
105	struct sockaddr_storage *addr;
106	struct sockaddr_in6 srv_sa6;
107	struct sockaddr_in srv_sa4;
108	socklen_t addr_len;
109	int sock_family;
110	char *srv_addr;
111	int srv_port;
112
113	switch (ip_mode) {
114	case TEST_MODE_IPV4:
115		sock_family = AF_INET;
116		srv_addr = SERVER_ADDR_IPV4;
117		addr = (struct sockaddr_storage *)&srv_sa4;
118		addr_len = sizeof(srv_sa4);
119		break;
120	case TEST_MODE_IPV6:
121		opts.post_socket_cb = v6only_true;
122		sock_family = AF_INET6;
123		srv_addr = SERVER_ADDR_IPV6;
124		addr = (struct sockaddr_storage *)&srv_sa6;
125		addr_len = sizeof(srv_sa6);
126		break;
127	case TEST_MODE_DUAL:
128		opts.post_socket_cb = v6only_false;
129		sock_family = AF_INET6;
130		srv_addr = SERVER_ADDR_DUAL;
131		addr = (struct sockaddr_storage *)&srv_sa6;
132		addr_len = sizeof(srv_sa6);
133		break;
134	default:
135		PRINT_FAIL("Unknown IP mode %d", ip_mode);
136		return;
137	}
138
139	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", tcp_syncookies))
 
140		return;
141
142	listen_fd = start_server_str(sock_family, SOCK_STREAM, srv_addr,  0,
143				     &opts);
144	if (!ASSERT_OK_FD(listen_fd, "start server"))
145		return;
146
147	err = getsockname(listen_fd, (struct sockaddr *)addr, &addr_len);
148	if (!ASSERT_OK(err, "getsockname(listen_fd)"))
149		goto done;
150
151	switch (ip_mode) {
152	case TEST_MODE_IPV4:
153		memcpy(&skel->bss->srv_sa4, &srv_sa4, sizeof(srv_sa4));
154		srv_port = ntohs(srv_sa4.sin_port);
155		break;
156	case TEST_MODE_IPV6:
157	case TEST_MODE_DUAL:
158		memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6));
159		srv_port = ntohs(srv_sa6.sin6_port);
160		break;
161	default:
162		goto done;
163	}
 
164
165	cli_fd = connect_to_fd(listen_fd, 0);
166	if (!ASSERT_OK_FD(cli_fd, "connect client"))
167		goto done;
168
169	srv_fd = accept(listen_fd, NULL, NULL);
170	if (!ASSERT_OK_FD(srv_fd, "accept connection"))
 
 
 
 
 
 
 
 
171		goto done;
172
173	ASSERT_EQ(skel->bss->listen_tp_sport, srv_port, "listen tp src port");
 
 
 
 
174
175	if (!gen_cookies) {
176		ASSERT_EQ(skel->bss->req_sk_sport, srv_port,
177			  "request socket source port with syncookies disabled");
178		ASSERT_EQ(skel->bss->gen_cookie, 0,
179			  "generated syncookie with syncookies disabled");
180		ASSERT_EQ(skel->bss->recv_cookie, 0,
181			  "received syncookie with syncookies disabled");
182	} else {
183		ASSERT_EQ(skel->bss->req_sk_sport, 0,
184			  "request socket source port with syncookies enabled");
185		ASSERT_NEQ(skel->bss->gen_cookie, 0,
186			   "syncookie properly generated");
187		ASSERT_EQ(skel->bss->gen_cookie, skel->bss->recv_cookie,
188			  "matching syncookies on client and server");
189		ASSERT_GT(skel->bss->mss, MIN_IPV4_MSS,
190			  "MSS in cookie min value");
191		ASSERT_LT(skel->bss->mss, USHRT_MAX,
192			  "MSS in cookie max value");
193	}
194
195done:
196	if (listen_fd != -1)
197		close(listen_fd);
198	if (cli_fd != -1)
199		close(cli_fd);
200	if (srv_fd != -1)
201		close(srv_fd);
202}
203
204static void test_conn_ipv4(struct test_btf_skc_cls_ingress *skel)
205{
206	run_test(skel, false, TEST_MODE_IPV4);
207}
 
208
209static void test_conn_ipv6(struct test_btf_skc_cls_ingress *skel)
210{
211	run_test(skel, false, TEST_MODE_IPV6);
212}
213
214static void test_conn_dual(struct test_btf_skc_cls_ingress *skel)
215{
216	run_test(skel, false, TEST_MODE_DUAL);
217}
218
219static void test_syncookie_ipv4(struct test_btf_skc_cls_ingress *skel)
220{
221	run_test(skel, true, TEST_MODE_IPV4);
222}
 
 
223
224static void test_syncookie_ipv6(struct test_btf_skc_cls_ingress *skel)
225{
226	run_test(skel, true, TEST_MODE_IPV6);
227}
228
229static void test_syncookie_dual(struct test_btf_skc_cls_ingress *skel)
230{
231	run_test(skel, true, TEST_MODE_DUAL);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232}
233
234struct test {
235	const char *desc;
236	void (*run)(struct test_btf_skc_cls_ingress *skel);
237};
238
239#define DEF_TEST(name) { #name, test_##name }
240static struct test tests[] = {
241	DEF_TEST(conn_ipv4),
242	DEF_TEST(conn_ipv6),
243	DEF_TEST(conn_dual),
244	DEF_TEST(syncookie_ipv4),
245	DEF_TEST(syncookie_ipv6),
246	DEF_TEST(syncookie_dual),
247};
248
249void test_btf_skc_cls_ingress(void)
250{
251	struct test_btf_skc_cls_ingress *skel;
252	struct netns_obj *ns;
253	int i;
254
255	skel = test_btf_skc_cls_ingress__open_and_load();
256	if (!ASSERT_OK_PTR(skel, "test_btf_skc_cls_ingress__open_and_load"))
257		return;
258
259	for (i = 0; i < ARRAY_SIZE(tests); i++) {
260		if (!test__start_subtest(tests[i].desc))
261			continue;
262
263		ns = prepare_netns(skel);
264		if (!ns)
265			break;
266
267		tests[i].run(skel);
268
269		print_err_line(skel);
270		reset_test(skel);
271		netns_free(ns);
272	}
273
274	test_btf_skc_cls_ingress__destroy(skel);
275}
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2020 Facebook */
  3
  4#define _GNU_SOURCE
  5#include <netinet/in.h>
  6#include <arpa/inet.h>
  7#include <unistd.h>
  8#include <stdlib.h>
  9#include <string.h>
 10#include <errno.h>
 11#include <sched.h>
 12#include <net/if.h>
 13#include <linux/compiler.h>
 14#include <bpf/libbpf.h>
 15
 16#include "network_helpers.h"
 17#include "test_progs.h"
 18#include "test_btf_skc_cls_ingress.skel.h"
 19
 20static struct test_btf_skc_cls_ingress *skel;
 21static struct sockaddr_in6 srv_sa6;
 22static __u32 duration;
 23
 24static int prepare_netns(void)
 
 
 
 
 
 
 
 
 
 
 
 25{
 26	LIBBPF_OPTS(bpf_tc_hook, qdisc_lo, .attach_point = BPF_TC_INGRESS);
 27	LIBBPF_OPTS(bpf_tc_opts, tc_attach,
 28		    .prog_fd = bpf_program__fd(skel->progs.cls_ingress));
 
 29
 30	if (CHECK(unshare(CLONE_NEWNET), "create netns",
 31		  "unshare(CLONE_NEWNET): %s (%d)",
 32		  strerror(errno), errno))
 33		return -1;
 34
 35	if (CHECK(system("ip link set dev lo up"),
 36		  "ip link set dev lo up", "failed\n"))
 37		return -1;
 38
 39	qdisc_lo.ifindex = if_nametoindex("lo");
 40	if (!ASSERT_OK(bpf_tc_hook_create(&qdisc_lo), "qdisc add dev lo clsact"))
 41		return -1;
 42
 43	if (!ASSERT_OK(bpf_tc_attach(&qdisc_lo, &tc_attach),
 44		       "filter add dev lo ingress"))
 45		return -1;
 46
 47	/* Ensure 20 bytes options (i.e. in total 40 bytes tcp header) for the
 48	 * bpf_tcp_gen_syncookie() helper.
 49	 */
 50	if (write_sysctl("/proc/sys/net/ipv4/tcp_window_scaling", "1") ||
 51	    write_sysctl("/proc/sys/net/ipv4/tcp_timestamps", "1") ||
 52	    write_sysctl("/proc/sys/net/ipv4/tcp_sack", "1"))
 53		return -1;
 
 
 54
 55	return 0;
 
 
 56}
 57
 58static void reset_test(void)
 59{
 
 60	memset(&skel->bss->srv_sa6, 0, sizeof(skel->bss->srv_sa6));
 61	skel->bss->listen_tp_sport = 0;
 62	skel->bss->req_sk_sport = 0;
 63	skel->bss->recv_cookie = 0;
 64	skel->bss->gen_cookie = 0;
 65	skel->bss->linum = 0;
 
 66}
 67
 68static void print_err_line(void)
 69{
 70	if (skel->bss->linum)
 71		printf("bpf prog error at line %u\n", skel->bss->linum);
 72}
 73
 74static void test_conn(void)
 75{
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 76	int listen_fd = -1, cli_fd = -1, srv_fd = -1, err;
 77	socklen_t addrlen = sizeof(srv_sa6);
 
 
 
 
 
 
 78	int srv_port;
 79
 80	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "1"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 81		return;
 
 82
 83	listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0);
 84	if (CHECK_FAIL(listen_fd == -1))
 85		return;
 86
 87	err = getsockname(listen_fd, (struct sockaddr *)&srv_sa6, &addrlen);
 88	if (CHECK(err, "getsockname(listen_fd)", "err:%d errno:%d\n", err,
 89		  errno))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 90		goto done;
 91	memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6));
 92	srv_port = ntohs(srv_sa6.sin6_port);
 93
 94	cli_fd = connect_to_fd(listen_fd, 0);
 95	if (CHECK_FAIL(cli_fd == -1))
 96		goto done;
 97
 98	srv_fd = accept(listen_fd, NULL, NULL);
 99	if (CHECK_FAIL(srv_fd == -1))
100		goto done;
101
102	if (CHECK(skel->bss->listen_tp_sport != srv_port ||
103		  skel->bss->req_sk_sport != srv_port,
104		  "Unexpected sk src port",
105		  "listen_tp_sport:%u req_sk_sport:%u expected:%u\n",
106		  skel->bss->listen_tp_sport, skel->bss->req_sk_sport,
107		  srv_port))
108		goto done;
109
110	if (CHECK(skel->bss->gen_cookie || skel->bss->recv_cookie,
111		  "Unexpected syncookie states",
112		  "gen_cookie:%u recv_cookie:%u\n",
113		  skel->bss->gen_cookie, skel->bss->recv_cookie))
114		goto done;
115
116	CHECK(skel->bss->linum, "bpf prog detected error", "at line %u\n",
117	      skel->bss->linum);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
119done:
120	if (listen_fd != -1)
121		close(listen_fd);
122	if (cli_fd != -1)
123		close(cli_fd);
124	if (srv_fd != -1)
125		close(srv_fd);
126}
127
128static void test_syncookie(void)
129{
130	int listen_fd = -1, cli_fd = -1, srv_fd = -1, err;
131	socklen_t addrlen = sizeof(srv_sa6);
132	int srv_port;
133
134	/* Enforce syncookie mode */
135	if (write_sysctl("/proc/sys/net/ipv4/tcp_syncookies", "2"))
136		return;
 
137
138	listen_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0);
139	if (CHECK_FAIL(listen_fd == -1))
140		return;
 
141
142	err = getsockname(listen_fd, (struct sockaddr *)&srv_sa6, &addrlen);
143	if (CHECK(err, "getsockname(listen_fd)", "err:%d errno:%d\n", err,
144		  errno))
145		goto done;
146	memcpy(&skel->bss->srv_sa6, &srv_sa6, sizeof(srv_sa6));
147	srv_port = ntohs(srv_sa6.sin6_port);
148
149	cli_fd = connect_to_fd(listen_fd, 0);
150	if (CHECK_FAIL(cli_fd == -1))
151		goto done;
 
152
153	srv_fd = accept(listen_fd, NULL, NULL);
154	if (CHECK_FAIL(srv_fd == -1))
155		goto done;
156
157	if (CHECK(skel->bss->listen_tp_sport != srv_port,
158		  "Unexpected tp src port",
159		  "listen_tp_sport:%u expected:%u\n",
160		  skel->bss->listen_tp_sport, srv_port))
161		goto done;
162
163	if (CHECK(skel->bss->req_sk_sport,
164		  "Unexpected req_sk src port",
165		  "req_sk_sport:%u expected:0\n",
166		   skel->bss->req_sk_sport))
167		goto done;
168
169	if (CHECK(!skel->bss->gen_cookie ||
170		  skel->bss->gen_cookie != skel->bss->recv_cookie,
171		  "Unexpected syncookie states",
172		  "gen_cookie:%u recv_cookie:%u\n",
173		  skel->bss->gen_cookie, skel->bss->recv_cookie))
174		goto done;
175
176	CHECK(skel->bss->linum, "bpf prog detected error", "at line %u\n",
177	      skel->bss->linum);
178
179done:
180	if (listen_fd != -1)
181		close(listen_fd);
182	if (cli_fd != -1)
183		close(cli_fd);
184	if (srv_fd != -1)
185		close(srv_fd);
186}
187
188struct test {
189	const char *desc;
190	void (*run)(void);
191};
192
193#define DEF_TEST(name) { #name, test_##name }
194static struct test tests[] = {
195	DEF_TEST(conn),
196	DEF_TEST(syncookie),
 
 
 
 
197};
198
199void test_btf_skc_cls_ingress(void)
200{
 
 
201	int i;
202
203	skel = test_btf_skc_cls_ingress__open_and_load();
204	if (CHECK(!skel, "test_btf_skc_cls_ingress__open_and_load", "failed\n"))
205		return;
206
207	for (i = 0; i < ARRAY_SIZE(tests); i++) {
208		if (!test__start_subtest(tests[i].desc))
209			continue;
210
211		if (prepare_netns())
 
212			break;
213
214		tests[i].run();
215
216		print_err_line();
217		reset_test();
 
218	}
219
220	test_btf_skc_cls_ingress__destroy(skel);
221}