Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3/*
  4 * Copyright 2020 Google LLC.
  5 */
  6
  7#include <test_progs.h>
  8#include <cgroup_helpers.h>
  9#include <network_helpers.h>
 10
 11#include "progs/cg_storage_multi.h"
 12
 13#include "cg_storage_multi_egress_only.skel.h"
 14#include "cg_storage_multi_isolated.skel.h"
 15#include "cg_storage_multi_shared.skel.h"
 16
 17#define PARENT_CGROUP "/cgroup_storage"
 18#define CHILD_CGROUP "/cgroup_storage/child"
 19
 20static int duration;
 21
 22static bool assert_storage(struct bpf_map *map, const void *key,
 23			   struct cgroup_value *expected)
 24{
 25	struct cgroup_value value;
 26	int map_fd;
 27
 28	map_fd = bpf_map__fd(map);
 29
 30	if (CHECK(bpf_map_lookup_elem(map_fd, key, &value) < 0,
 31		  "map-lookup", "errno %d", errno))
 32		return true;
 33	if (CHECK(memcmp(&value, expected, sizeof(struct cgroup_value)),
 34		  "assert-storage", "storages differ"))
 35		return true;
 36
 37	return false;
 38}
 39
 40static bool assert_storage_noexist(struct bpf_map *map, const void *key)
 41{
 42	struct cgroup_value value;
 43	int map_fd;
 44
 45	map_fd = bpf_map__fd(map);
 46
 47	if (CHECK(bpf_map_lookup_elem(map_fd, key, &value) == 0,
 48		  "map-lookup", "succeeded, expected ENOENT"))
 49		return true;
 50	if (CHECK(errno != ENOENT,
 51		  "map-lookup", "errno %d, expected ENOENT", errno))
 52		return true;
 53
 54	return false;
 55}
 56
 57static bool connect_send(const char *cgroup_path)
 58{
 59	int server_fd = -1, client_fd = -1;
 60	char message[] = "message";
 61	bool res = true;
 
 62
 63	if (join_cgroup(cgroup_path))
 64		goto out_clean;
 65
 66	server_fd = start_server(AF_INET, SOCK_DGRAM, NULL, 0, 0);
 67	if (server_fd < 0)
 68		goto out_clean;
 69
 70	client_fd = connect_to_fd(server_fd, 0);
 71	if (client_fd < 0)
 72		goto out_clean;
 73
 74	if (send(client_fd, &message, sizeof(message), 0) < 0)
 75		goto out_clean;
 76
 77	if (read(server_fd, &message, sizeof(message)) < 0)
 78		goto out_clean;
 79
 80	res = false;
 81
 82out_clean:
 83	close(client_fd);
 84	close(server_fd);
 85	return res;
 86}
 87
 88static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
 89{
 90	struct cg_storage_multi_egress_only *obj;
 91	struct cgroup_value expected_cgroup_value;
 92	struct bpf_cgroup_storage_key key;
 93	struct bpf_link *parent_link = NULL, *child_link = NULL;
 94	bool err;
 95
 96	key.attach_type = BPF_CGROUP_INET_EGRESS;
 97
 98	obj = cg_storage_multi_egress_only__open_and_load();
 99	if (CHECK(!obj, "skel-load", "errno %d", errno))
100		return;
101
102	/* Attach to parent cgroup, trigger packet from child.
103	 * Assert that there is only one run and in that run the storage is
104	 * parent cgroup's storage.
105	 * Also assert that child cgroup's storage does not exist
106	 */
107	parent_link = bpf_program__attach_cgroup(obj->progs.egress,
108						 parent_cgroup_fd);
109	if (!ASSERT_OK_PTR(parent_link, "parent-cg-attach"))
110		goto close_bpf_object;
111	err = connect_send(CHILD_CGROUP);
112	if (CHECK(err, "first-connect-send", "errno %d", errno))
113		goto close_bpf_object;
114	if (CHECK(obj->bss->invocations != 1,
115		  "first-invoke", "invocations=%d", obj->bss->invocations))
116		goto close_bpf_object;
117	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
118	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
119	if (assert_storage(obj->maps.cgroup_storage,
120			   &key, &expected_cgroup_value))
121		goto close_bpf_object;
122	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
123	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
124		goto close_bpf_object;
125
126	/* Attach to parent and child cgroup, trigger packet from child.
127	 * Assert that there are two additional runs, one that run with parent
128	 * cgroup's storage and one with child cgroup's storage.
129	 */
130	child_link = bpf_program__attach_cgroup(obj->progs.egress,
131						child_cgroup_fd);
132	if (!ASSERT_OK_PTR(child_link, "child-cg-attach"))
133		goto close_bpf_object;
134	err = connect_send(CHILD_CGROUP);
135	if (CHECK(err, "second-connect-send", "errno %d", errno))
136		goto close_bpf_object;
137	if (CHECK(obj->bss->invocations != 3,
138		  "second-invoke", "invocations=%d", obj->bss->invocations))
139		goto close_bpf_object;
140	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
141	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
142	if (assert_storage(obj->maps.cgroup_storage,
143			   &key, &expected_cgroup_value))
144		goto close_bpf_object;
145	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
146	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
147	if (assert_storage(obj->maps.cgroup_storage,
148			   &key, &expected_cgroup_value))
149		goto close_bpf_object;
150
151close_bpf_object:
152	bpf_link__destroy(parent_link);
153	bpf_link__destroy(child_link);
154
155	cg_storage_multi_egress_only__destroy(obj);
156}
157
158static void test_isolated(int parent_cgroup_fd, int child_cgroup_fd)
159{
160	struct cg_storage_multi_isolated *obj;
161	struct cgroup_value expected_cgroup_value;
162	struct bpf_cgroup_storage_key key;
163	struct bpf_link *parent_egress1_link = NULL, *parent_egress2_link = NULL;
164	struct bpf_link *child_egress1_link = NULL, *child_egress2_link = NULL;
165	struct bpf_link *parent_ingress_link = NULL, *child_ingress_link = NULL;
166	bool err;
167
168	obj = cg_storage_multi_isolated__open_and_load();
169	if (CHECK(!obj, "skel-load", "errno %d", errno))
170		return;
171
172	/* Attach to parent cgroup, trigger packet from child.
173	 * Assert that there is three runs, two with parent cgroup egress and
174	 * one with parent cgroup ingress, stored in separate parent storages.
175	 * Also assert that child cgroup's storages does not exist
176	 */
177	parent_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
178							 parent_cgroup_fd);
179	if (!ASSERT_OK_PTR(parent_egress1_link, "parent-egress1-cg-attach"))
180		goto close_bpf_object;
181	parent_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
182							 parent_cgroup_fd);
183	if (!ASSERT_OK_PTR(parent_egress2_link, "parent-egress2-cg-attach"))
184		goto close_bpf_object;
185	parent_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
186							 parent_cgroup_fd);
187	if (!ASSERT_OK_PTR(parent_ingress_link, "parent-ingress-cg-attach"))
188		goto close_bpf_object;
189	err = connect_send(CHILD_CGROUP);
190	if (CHECK(err, "first-connect-send", "errno %d", errno))
191		goto close_bpf_object;
192	if (CHECK(obj->bss->invocations != 3,
193		  "first-invoke", "invocations=%d", obj->bss->invocations))
194		goto close_bpf_object;
195	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
196	key.attach_type = BPF_CGROUP_INET_EGRESS;
197	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
198	if (assert_storage(obj->maps.cgroup_storage,
199			   &key, &expected_cgroup_value))
200		goto close_bpf_object;
201	key.attach_type = BPF_CGROUP_INET_INGRESS;
202	expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 1 };
203	if (assert_storage(obj->maps.cgroup_storage,
204			   &key, &expected_cgroup_value))
205		goto close_bpf_object;
206	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
207	key.attach_type = BPF_CGROUP_INET_EGRESS;
208	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
209		goto close_bpf_object;
210	key.attach_type = BPF_CGROUP_INET_INGRESS;
211	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
212		goto close_bpf_object;
213
214	/* Attach to parent and child cgroup, trigger packet from child.
215	 * Assert that there is six additional runs, parent cgroup egresses and
216	 * ingress, child cgroup egresses and ingress.
217	 * Assert that egress and ingress storages are separate.
218	 */
219	child_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
220							child_cgroup_fd);
221	if (!ASSERT_OK_PTR(child_egress1_link, "child-egress1-cg-attach"))
222		goto close_bpf_object;
223	child_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
224							child_cgroup_fd);
225	if (!ASSERT_OK_PTR(child_egress2_link, "child-egress2-cg-attach"))
226		goto close_bpf_object;
227	child_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
228							child_cgroup_fd);
229	if (!ASSERT_OK_PTR(child_ingress_link, "child-ingress-cg-attach"))
230		goto close_bpf_object;
231	err = connect_send(CHILD_CGROUP);
232	if (CHECK(err, "second-connect-send", "errno %d", errno))
233		goto close_bpf_object;
234	if (CHECK(obj->bss->invocations != 9,
235		  "second-invoke", "invocations=%d", obj->bss->invocations))
236		goto close_bpf_object;
237	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
238	key.attach_type = BPF_CGROUP_INET_EGRESS;
239	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 4 };
240	if (assert_storage(obj->maps.cgroup_storage,
241			   &key, &expected_cgroup_value))
242		goto close_bpf_object;
243	key.attach_type = BPF_CGROUP_INET_INGRESS;
244	expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 2 };
245	if (assert_storage(obj->maps.cgroup_storage,
246			   &key, &expected_cgroup_value))
247		goto close_bpf_object;
248	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
249	key.attach_type = BPF_CGROUP_INET_EGRESS;
250	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
251	if (assert_storage(obj->maps.cgroup_storage,
252			   &key, &expected_cgroup_value))
253		goto close_bpf_object;
254	key.attach_type = BPF_CGROUP_INET_INGRESS;
255	expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 1 };
256	if (assert_storage(obj->maps.cgroup_storage,
257			   &key, &expected_cgroup_value))
258		goto close_bpf_object;
259
260close_bpf_object:
261	bpf_link__destroy(parent_egress1_link);
262	bpf_link__destroy(parent_egress2_link);
263	bpf_link__destroy(parent_ingress_link);
264	bpf_link__destroy(child_egress1_link);
265	bpf_link__destroy(child_egress2_link);
266	bpf_link__destroy(child_ingress_link);
267
268	cg_storage_multi_isolated__destroy(obj);
269}
270
271static void test_shared(int parent_cgroup_fd, int child_cgroup_fd)
272{
273	struct cg_storage_multi_shared *obj;
274	struct cgroup_value expected_cgroup_value;
275	__u64 key;
276	struct bpf_link *parent_egress1_link = NULL, *parent_egress2_link = NULL;
277	struct bpf_link *child_egress1_link = NULL, *child_egress2_link = NULL;
278	struct bpf_link *parent_ingress_link = NULL, *child_ingress_link = NULL;
279	bool err;
280
281	obj = cg_storage_multi_shared__open_and_load();
282	if (CHECK(!obj, "skel-load", "errno %d", errno))
283		return;
284
285	/* Attach to parent cgroup, trigger packet from child.
286	 * Assert that there is three runs, two with parent cgroup egress and
287	 * one with parent cgroup ingress.
288	 * Also assert that child cgroup's storage does not exist
289	 */
290	parent_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
291							 parent_cgroup_fd);
292	if (!ASSERT_OK_PTR(parent_egress1_link, "parent-egress1-cg-attach"))
293		goto close_bpf_object;
294	parent_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
295							 parent_cgroup_fd);
296	if (!ASSERT_OK_PTR(parent_egress2_link, "parent-egress2-cg-attach"))
297		goto close_bpf_object;
298	parent_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
299							 parent_cgroup_fd);
300	if (!ASSERT_OK_PTR(parent_ingress_link, "parent-ingress-cg-attach"))
301		goto close_bpf_object;
302	err = connect_send(CHILD_CGROUP);
303	if (CHECK(err, "first-connect-send", "errno %d", errno))
304		goto close_bpf_object;
305	if (CHECK(obj->bss->invocations != 3,
306		  "first-invoke", "invocations=%d", obj->bss->invocations))
307		goto close_bpf_object;
308	key = get_cgroup_id(PARENT_CGROUP);
309	expected_cgroup_value = (struct cgroup_value) {
310		.egress_pkts = 2,
311		.ingress_pkts = 1,
312	};
313	if (assert_storage(obj->maps.cgroup_storage,
314			   &key, &expected_cgroup_value))
315		goto close_bpf_object;
316	key = get_cgroup_id(CHILD_CGROUP);
317	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
318		goto close_bpf_object;
319
320	/* Attach to parent and child cgroup, trigger packet from child.
321	 * Assert that there is six additional runs, parent cgroup egresses and
322	 * ingress, child cgroup egresses and ingress.
323	 */
324	child_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
325							child_cgroup_fd);
326	if (!ASSERT_OK_PTR(child_egress1_link, "child-egress1-cg-attach"))
327		goto close_bpf_object;
328	child_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
329							child_cgroup_fd);
330	if (!ASSERT_OK_PTR(child_egress2_link, "child-egress2-cg-attach"))
331		goto close_bpf_object;
332	child_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
333							child_cgroup_fd);
334	if (!ASSERT_OK_PTR(child_ingress_link, "child-ingress-cg-attach"))
335		goto close_bpf_object;
336	err = connect_send(CHILD_CGROUP);
337	if (CHECK(err, "second-connect-send", "errno %d", errno))
338		goto close_bpf_object;
339	if (CHECK(obj->bss->invocations != 9,
340		  "second-invoke", "invocations=%d", obj->bss->invocations))
341		goto close_bpf_object;
342	key = get_cgroup_id(PARENT_CGROUP);
343	expected_cgroup_value = (struct cgroup_value) {
344		.egress_pkts = 4,
345		.ingress_pkts = 2,
346	};
347	if (assert_storage(obj->maps.cgroup_storage,
348			   &key, &expected_cgroup_value))
349		goto close_bpf_object;
350	key = get_cgroup_id(CHILD_CGROUP);
351	expected_cgroup_value = (struct cgroup_value) {
352		.egress_pkts = 2,
353		.ingress_pkts = 1,
354	};
355	if (assert_storage(obj->maps.cgroup_storage,
356			   &key, &expected_cgroup_value))
357		goto close_bpf_object;
358
359close_bpf_object:
360	bpf_link__destroy(parent_egress1_link);
361	bpf_link__destroy(parent_egress2_link);
362	bpf_link__destroy(parent_ingress_link);
363	bpf_link__destroy(child_egress1_link);
364	bpf_link__destroy(child_egress2_link);
365	bpf_link__destroy(child_ingress_link);
366
367	cg_storage_multi_shared__destroy(obj);
368}
369
370void serial_test_cg_storage_multi(void)
371{
372	int parent_cgroup_fd = -1, child_cgroup_fd = -1;
373
374	parent_cgroup_fd = test__join_cgroup(PARENT_CGROUP);
375	if (CHECK(parent_cgroup_fd < 0, "cg-create-parent", "errno %d", errno))
376		goto close_cgroup_fd;
377	child_cgroup_fd = create_and_get_cgroup(CHILD_CGROUP);
378	if (CHECK(child_cgroup_fd < 0, "cg-create-child", "errno %d", errno))
379		goto close_cgroup_fd;
380
381	if (test__start_subtest("egress_only"))
382		test_egress_only(parent_cgroup_fd, child_cgroup_fd);
383
384	if (test__start_subtest("isolated"))
385		test_isolated(parent_cgroup_fd, child_cgroup_fd);
386
387	if (test__start_subtest("shared"))
388		test_shared(parent_cgroup_fd, child_cgroup_fd);
389
390close_cgroup_fd:
391	close(child_cgroup_fd);
392	close(parent_cgroup_fd);
393}
v6.2
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3/*
  4 * Copyright 2020 Google LLC.
  5 */
  6
  7#include <test_progs.h>
  8#include <cgroup_helpers.h>
  9#include <network_helpers.h>
 10
 11#include "progs/cg_storage_multi.h"
 12
 13#include "cg_storage_multi_egress_only.skel.h"
 14#include "cg_storage_multi_isolated.skel.h"
 15#include "cg_storage_multi_shared.skel.h"
 16
 17#define PARENT_CGROUP "/cgroup_storage"
 18#define CHILD_CGROUP "/cgroup_storage/child"
 19
 20static int duration;
 21
 22static bool assert_storage(struct bpf_map *map, const void *key,
 23			   struct cgroup_value *expected)
 24{
 25	struct cgroup_value value;
 26	int map_fd;
 27
 28	map_fd = bpf_map__fd(map);
 29
 30	if (CHECK(bpf_map_lookup_elem(map_fd, key, &value) < 0,
 31		  "map-lookup", "errno %d", errno))
 32		return true;
 33	if (CHECK(memcmp(&value, expected, sizeof(struct cgroup_value)),
 34		  "assert-storage", "storages differ"))
 35		return true;
 36
 37	return false;
 38}
 39
 40static bool assert_storage_noexist(struct bpf_map *map, const void *key)
 41{
 42	struct cgroup_value value;
 43	int map_fd;
 44
 45	map_fd = bpf_map__fd(map);
 46
 47	if (CHECK(bpf_map_lookup_elem(map_fd, key, &value) == 0,
 48		  "map-lookup", "succeeded, expected ENOENT"))
 49		return true;
 50	if (CHECK(errno != ENOENT,
 51		  "map-lookup", "errno %d, expected ENOENT", errno))
 52		return true;
 53
 54	return false;
 55}
 56
 57static bool connect_send(const char *cgroup_path)
 58{
 
 
 59	bool res = true;
 60	int server_fd = -1, client_fd = -1;
 61
 62	if (join_cgroup(cgroup_path))
 63		goto out_clean;
 64
 65	server_fd = start_server(AF_INET, SOCK_DGRAM, NULL, 0, 0);
 66	if (server_fd < 0)
 67		goto out_clean;
 68
 69	client_fd = connect_to_fd(server_fd, 0);
 70	if (client_fd < 0)
 71		goto out_clean;
 72
 73	if (send(client_fd, "message", strlen("message"), 0) < 0)
 
 
 
 74		goto out_clean;
 75
 76	res = false;
 77
 78out_clean:
 79	close(client_fd);
 80	close(server_fd);
 81	return res;
 82}
 83
 84static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
 85{
 86	struct cg_storage_multi_egress_only *obj;
 87	struct cgroup_value expected_cgroup_value;
 88	struct bpf_cgroup_storage_key key;
 89	struct bpf_link *parent_link = NULL, *child_link = NULL;
 90	bool err;
 91
 92	key.attach_type = BPF_CGROUP_INET_EGRESS;
 93
 94	obj = cg_storage_multi_egress_only__open_and_load();
 95	if (CHECK(!obj, "skel-load", "errno %d", errno))
 96		return;
 97
 98	/* Attach to parent cgroup, trigger packet from child.
 99	 * Assert that there is only one run and in that run the storage is
100	 * parent cgroup's storage.
101	 * Also assert that child cgroup's storage does not exist
102	 */
103	parent_link = bpf_program__attach_cgroup(obj->progs.egress,
104						 parent_cgroup_fd);
105	if (!ASSERT_OK_PTR(parent_link, "parent-cg-attach"))
106		goto close_bpf_object;
107	err = connect_send(CHILD_CGROUP);
108	if (CHECK(err, "first-connect-send", "errno %d", errno))
109		goto close_bpf_object;
110	if (CHECK(obj->bss->invocations != 1,
111		  "first-invoke", "invocations=%d", obj->bss->invocations))
112		goto close_bpf_object;
113	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
114	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
115	if (assert_storage(obj->maps.cgroup_storage,
116			   &key, &expected_cgroup_value))
117		goto close_bpf_object;
118	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
119	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
120		goto close_bpf_object;
121
122	/* Attach to parent and child cgroup, trigger packet from child.
123	 * Assert that there are two additional runs, one that run with parent
124	 * cgroup's storage and one with child cgroup's storage.
125	 */
126	child_link = bpf_program__attach_cgroup(obj->progs.egress,
127						child_cgroup_fd);
128	if (!ASSERT_OK_PTR(child_link, "child-cg-attach"))
129		goto close_bpf_object;
130	err = connect_send(CHILD_CGROUP);
131	if (CHECK(err, "second-connect-send", "errno %d", errno))
132		goto close_bpf_object;
133	if (CHECK(obj->bss->invocations != 3,
134		  "second-invoke", "invocations=%d", obj->bss->invocations))
135		goto close_bpf_object;
136	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
137	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
138	if (assert_storage(obj->maps.cgroup_storage,
139			   &key, &expected_cgroup_value))
140		goto close_bpf_object;
141	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
142	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
143	if (assert_storage(obj->maps.cgroup_storage,
144			   &key, &expected_cgroup_value))
145		goto close_bpf_object;
146
147close_bpf_object:
148	bpf_link__destroy(parent_link);
149	bpf_link__destroy(child_link);
150
151	cg_storage_multi_egress_only__destroy(obj);
152}
153
154static void test_isolated(int parent_cgroup_fd, int child_cgroup_fd)
155{
156	struct cg_storage_multi_isolated *obj;
157	struct cgroup_value expected_cgroup_value;
158	struct bpf_cgroup_storage_key key;
159	struct bpf_link *parent_egress1_link = NULL, *parent_egress2_link = NULL;
160	struct bpf_link *child_egress1_link = NULL, *child_egress2_link = NULL;
161	struct bpf_link *parent_ingress_link = NULL, *child_ingress_link = NULL;
162	bool err;
163
164	obj = cg_storage_multi_isolated__open_and_load();
165	if (CHECK(!obj, "skel-load", "errno %d", errno))
166		return;
167
168	/* Attach to parent cgroup, trigger packet from child.
169	 * Assert that there is three runs, two with parent cgroup egress and
170	 * one with parent cgroup ingress, stored in separate parent storages.
171	 * Also assert that child cgroup's storages does not exist
172	 */
173	parent_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
174							 parent_cgroup_fd);
175	if (!ASSERT_OK_PTR(parent_egress1_link, "parent-egress1-cg-attach"))
176		goto close_bpf_object;
177	parent_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
178							 parent_cgroup_fd);
179	if (!ASSERT_OK_PTR(parent_egress2_link, "parent-egress2-cg-attach"))
180		goto close_bpf_object;
181	parent_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
182							 parent_cgroup_fd);
183	if (!ASSERT_OK_PTR(parent_ingress_link, "parent-ingress-cg-attach"))
184		goto close_bpf_object;
185	err = connect_send(CHILD_CGROUP);
186	if (CHECK(err, "first-connect-send", "errno %d", errno))
187		goto close_bpf_object;
188	if (CHECK(obj->bss->invocations != 3,
189		  "first-invoke", "invocations=%d", obj->bss->invocations))
190		goto close_bpf_object;
191	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
192	key.attach_type = BPF_CGROUP_INET_EGRESS;
193	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
194	if (assert_storage(obj->maps.cgroup_storage,
195			   &key, &expected_cgroup_value))
196		goto close_bpf_object;
197	key.attach_type = BPF_CGROUP_INET_INGRESS;
198	expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 1 };
199	if (assert_storage(obj->maps.cgroup_storage,
200			   &key, &expected_cgroup_value))
201		goto close_bpf_object;
202	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
203	key.attach_type = BPF_CGROUP_INET_EGRESS;
204	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
205		goto close_bpf_object;
206	key.attach_type = BPF_CGROUP_INET_INGRESS;
207	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
208		goto close_bpf_object;
209
210	/* Attach to parent and child cgroup, trigger packet from child.
211	 * Assert that there is six additional runs, parent cgroup egresses and
212	 * ingress, child cgroup egresses and ingress.
213	 * Assert that egree and ingress storages are separate.
214	 */
215	child_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
216							child_cgroup_fd);
217	if (!ASSERT_OK_PTR(child_egress1_link, "child-egress1-cg-attach"))
218		goto close_bpf_object;
219	child_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
220							child_cgroup_fd);
221	if (!ASSERT_OK_PTR(child_egress2_link, "child-egress2-cg-attach"))
222		goto close_bpf_object;
223	child_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
224							child_cgroup_fd);
225	if (!ASSERT_OK_PTR(child_ingress_link, "child-ingress-cg-attach"))
226		goto close_bpf_object;
227	err = connect_send(CHILD_CGROUP);
228	if (CHECK(err, "second-connect-send", "errno %d", errno))
229		goto close_bpf_object;
230	if (CHECK(obj->bss->invocations != 9,
231		  "second-invoke", "invocations=%d", obj->bss->invocations))
232		goto close_bpf_object;
233	key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
234	key.attach_type = BPF_CGROUP_INET_EGRESS;
235	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 4 };
236	if (assert_storage(obj->maps.cgroup_storage,
237			   &key, &expected_cgroup_value))
238		goto close_bpf_object;
239	key.attach_type = BPF_CGROUP_INET_INGRESS;
240	expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 2 };
241	if (assert_storage(obj->maps.cgroup_storage,
242			   &key, &expected_cgroup_value))
243		goto close_bpf_object;
244	key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
245	key.attach_type = BPF_CGROUP_INET_EGRESS;
246	expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
247	if (assert_storage(obj->maps.cgroup_storage,
248			   &key, &expected_cgroup_value))
249		goto close_bpf_object;
250	key.attach_type = BPF_CGROUP_INET_INGRESS;
251	expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 1 };
252	if (assert_storage(obj->maps.cgroup_storage,
253			   &key, &expected_cgroup_value))
254		goto close_bpf_object;
255
256close_bpf_object:
257	bpf_link__destroy(parent_egress1_link);
258	bpf_link__destroy(parent_egress2_link);
259	bpf_link__destroy(parent_ingress_link);
260	bpf_link__destroy(child_egress1_link);
261	bpf_link__destroy(child_egress2_link);
262	bpf_link__destroy(child_ingress_link);
263
264	cg_storage_multi_isolated__destroy(obj);
265}
266
267static void test_shared(int parent_cgroup_fd, int child_cgroup_fd)
268{
269	struct cg_storage_multi_shared *obj;
270	struct cgroup_value expected_cgroup_value;
271	__u64 key;
272	struct bpf_link *parent_egress1_link = NULL, *parent_egress2_link = NULL;
273	struct bpf_link *child_egress1_link = NULL, *child_egress2_link = NULL;
274	struct bpf_link *parent_ingress_link = NULL, *child_ingress_link = NULL;
275	bool err;
276
277	obj = cg_storage_multi_shared__open_and_load();
278	if (CHECK(!obj, "skel-load", "errno %d", errno))
279		return;
280
281	/* Attach to parent cgroup, trigger packet from child.
282	 * Assert that there is three runs, two with parent cgroup egress and
283	 * one with parent cgroup ingress.
284	 * Also assert that child cgroup's storage does not exist
285	 */
286	parent_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
287							 parent_cgroup_fd);
288	if (!ASSERT_OK_PTR(parent_egress1_link, "parent-egress1-cg-attach"))
289		goto close_bpf_object;
290	parent_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
291							 parent_cgroup_fd);
292	if (!ASSERT_OK_PTR(parent_egress2_link, "parent-egress2-cg-attach"))
293		goto close_bpf_object;
294	parent_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
295							 parent_cgroup_fd);
296	if (!ASSERT_OK_PTR(parent_ingress_link, "parent-ingress-cg-attach"))
297		goto close_bpf_object;
298	err = connect_send(CHILD_CGROUP);
299	if (CHECK(err, "first-connect-send", "errno %d", errno))
300		goto close_bpf_object;
301	if (CHECK(obj->bss->invocations != 3,
302		  "first-invoke", "invocations=%d", obj->bss->invocations))
303		goto close_bpf_object;
304	key = get_cgroup_id(PARENT_CGROUP);
305	expected_cgroup_value = (struct cgroup_value) {
306		.egress_pkts = 2,
307		.ingress_pkts = 1,
308	};
309	if (assert_storage(obj->maps.cgroup_storage,
310			   &key, &expected_cgroup_value))
311		goto close_bpf_object;
312	key = get_cgroup_id(CHILD_CGROUP);
313	if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
314		goto close_bpf_object;
315
316	/* Attach to parent and child cgroup, trigger packet from child.
317	 * Assert that there is six additional runs, parent cgroup egresses and
318	 * ingress, child cgroup egresses and ingress.
319	 */
320	child_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
321							child_cgroup_fd);
322	if (!ASSERT_OK_PTR(child_egress1_link, "child-egress1-cg-attach"))
323		goto close_bpf_object;
324	child_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
325							child_cgroup_fd);
326	if (!ASSERT_OK_PTR(child_egress2_link, "child-egress2-cg-attach"))
327		goto close_bpf_object;
328	child_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
329							child_cgroup_fd);
330	if (!ASSERT_OK_PTR(child_ingress_link, "child-ingress-cg-attach"))
331		goto close_bpf_object;
332	err = connect_send(CHILD_CGROUP);
333	if (CHECK(err, "second-connect-send", "errno %d", errno))
334		goto close_bpf_object;
335	if (CHECK(obj->bss->invocations != 9,
336		  "second-invoke", "invocations=%d", obj->bss->invocations))
337		goto close_bpf_object;
338	key = get_cgroup_id(PARENT_CGROUP);
339	expected_cgroup_value = (struct cgroup_value) {
340		.egress_pkts = 4,
341		.ingress_pkts = 2,
342	};
343	if (assert_storage(obj->maps.cgroup_storage,
344			   &key, &expected_cgroup_value))
345		goto close_bpf_object;
346	key = get_cgroup_id(CHILD_CGROUP);
347	expected_cgroup_value = (struct cgroup_value) {
348		.egress_pkts = 2,
349		.ingress_pkts = 1,
350	};
351	if (assert_storage(obj->maps.cgroup_storage,
352			   &key, &expected_cgroup_value))
353		goto close_bpf_object;
354
355close_bpf_object:
356	bpf_link__destroy(parent_egress1_link);
357	bpf_link__destroy(parent_egress2_link);
358	bpf_link__destroy(parent_ingress_link);
359	bpf_link__destroy(child_egress1_link);
360	bpf_link__destroy(child_egress2_link);
361	bpf_link__destroy(child_ingress_link);
362
363	cg_storage_multi_shared__destroy(obj);
364}
365
366void serial_test_cg_storage_multi(void)
367{
368	int parent_cgroup_fd = -1, child_cgroup_fd = -1;
369
370	parent_cgroup_fd = test__join_cgroup(PARENT_CGROUP);
371	if (CHECK(parent_cgroup_fd < 0, "cg-create-parent", "errno %d", errno))
372		goto close_cgroup_fd;
373	child_cgroup_fd = create_and_get_cgroup(CHILD_CGROUP);
374	if (CHECK(child_cgroup_fd < 0, "cg-create-child", "errno %d", errno))
375		goto close_cgroup_fd;
376
377	if (test__start_subtest("egress_only"))
378		test_egress_only(parent_cgroup_fd, child_cgroup_fd);
379
380	if (test__start_subtest("isolated"))
381		test_isolated(parent_cgroup_fd, child_cgroup_fd);
382
383	if (test__start_subtest("shared"))
384		test_shared(parent_cgroup_fd, child_cgroup_fd);
385
386close_cgroup_fd:
387	close(child_cgroup_fd);
388	close(parent_cgroup_fd);
389}