1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2020 Facebook
3 
4 #include <test_progs.h>
5 
6 #include "network_helpers.h"
7 #include "cgroup_skb_sk_lookup_kern.skel.h"
8 
9 static void run_lookup_test(__u16 *g_serv_port, int out_sk)
10 {
11 	int serv_sk = -1, in_sk = -1, serv_in_sk = -1, err;
12 	struct sockaddr_in6 addr = {};
13 	socklen_t addr_len = sizeof(addr);
14 	__u32 duration = 0;
15 
16 	serv_sk = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
17 	if (CHECK(serv_sk < 0, "start_server", "failed to start server\n"))
18 		return;
19 
20 	err = getsockname(serv_sk, (struct sockaddr *)&addr, &addr_len);
21 	if (CHECK(err, "getsockname", "errno %d\n", errno))
22 		goto cleanup;
23 
24 	*g_serv_port = addr.sin6_port;
25 
26 	/* Client outside of test cgroup should fail to connect by timeout. */
27 	err = connect_fd_to_fd(out_sk, serv_sk, 1000);
28 	if (CHECK(!err || errno != EINPROGRESS, "connect_fd_to_fd",
29 		  "unexpected result err %d errno %d\n", err, errno))
30 		goto cleanup;
31 
32 	/* Client inside test cgroup should connect just fine. */
33 	in_sk = connect_to_fd(serv_sk, 0);
34 	if (CHECK(in_sk < 0, "connect_to_fd", "errno %d\n", errno))
35 		goto cleanup;
36 
37 	serv_in_sk = accept(serv_sk, NULL, NULL);
38 	if (CHECK(serv_in_sk < 0, "accept", "errno %d\n", errno))
39 		goto cleanup;
40 
41 cleanup:
42 	close(serv_in_sk);
43 	close(in_sk);
44 	close(serv_sk);
45 }
46 
47 static void run_cgroup_bpf_test(const char *cg_path, int out_sk)
48 {
49 	struct cgroup_skb_sk_lookup_kern *skel;
50 	struct bpf_link *link;
51 	__u32 duration = 0;
52 	int cgfd = -1;
53 
54 	skel = cgroup_skb_sk_lookup_kern__open_and_load();
55 	if (CHECK(!skel, "skel_open_load", "open_load failed\n"))
56 		return;
57 
58 	cgfd = test__join_cgroup(cg_path);
59 	if (CHECK(cgfd < 0, "cgroup_join", "cgroup setup failed\n"))
60 		goto cleanup;
61 
62 	link = bpf_program__attach_cgroup(skel->progs.ingress_lookup, cgfd);
63 	if (!ASSERT_OK_PTR(link, "cgroup_attach"))
64 		goto cleanup;
65 
66 	run_lookup_test(&skel->bss->g_serv_port, out_sk);
67 
68 	bpf_link__destroy(link);
69 
70 cleanup:
71 	close(cgfd);
72 	cgroup_skb_sk_lookup_kern__destroy(skel);
73 }
74 
75 void test_cgroup_skb_sk_lookup(void)
76 {
77 	const char *cg_path = "/foo";
78 	int out_sk;
79 
80 	/* Create a socket before joining testing cgroup so that its cgroup id
81 	 * differs from that of testing cgroup. Moving selftests process to
82 	 * testing cgroup won't change cgroup id of an already created socket.
83 	 */
84 	out_sk = socket(AF_INET6, SOCK_STREAM, 0);
85 	if (CHECK_FAIL(out_sk < 0))
86 		return;
87 
88 	run_cgroup_bpf_test(cg_path, out_sk);
89 
90 	close(out_sk);
91 }
92