@@ -8,16 +8,19 @@
#include <cgroup_helpers.h>
#include <network_helpers.h>
+#include "progs/cg_storage_multi.h"
+
#include "cg_storage_multi_egress_only.skel.h"
+#include "cg_storage_multi_egress_ingress.skel.h"
#define PARENT_CGROUP "/cgroup_storage"
#define CHILD_CGROUP "/cgroup_storage/child"
static bool assert_storage(struct bpf_map *map, const char *cgroup_path,
- __u32 expected)
+ struct cgroup_value *expected)
{
struct bpf_cgroup_storage_key key = {0};
- __u32 value;
+ struct cgroup_value value;
int map_fd;
map_fd = bpf_map__fd(map);
@@ -26,7 +29,7 @@ static bool assert_storage(struct bpf_map *map, const char *cgroup_path,
key.attach_type = BPF_CGROUP_INET_EGRESS;
if (CHECK_FAIL(bpf_map_lookup_elem(map_fd, &key, &value) < 0))
return true;
- if (CHECK_FAIL(value != expected))
+ if (CHECK_FAIL(memcmp(&value, expected, sizeof(struct cgroup_value))))
return true;
return false;
@@ -35,7 +38,7 @@ static bool assert_storage(struct bpf_map *map, const char *cgroup_path,
static bool assert_storage_noexist(struct bpf_map *map, const char *cgroup_path)
{
struct bpf_cgroup_storage_key key = {0};
- __u32 value;
+ struct cgroup_value value;
int map_fd;
map_fd = bpf_map__fd(map);
@@ -80,6 +83,7 @@ static bool connect_send(const char *cgroup_path)
static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
{
struct cg_storage_multi_egress_only *obj;
+ struct cgroup_value expected_cgroup_value;
int err;
if (!test__start_subtest("egress_only"))
@@ -104,8 +108,9 @@ static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
goto close_bpf_object;
if (CHECK_FAIL(obj->bss->invocations != 1))
goto close_bpf_object;
+ expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
if (CHECK_FAIL(assert_storage(obj->maps.cgroup_storage,
- PARENT_CGROUP, 1)))
+ PARENT_CGROUP, &expected_cgroup_value)))
goto close_bpf_object;
if (CHECK_FAIL(assert_storage_noexist(obj->maps.cgroup_storage,
CHILD_CGROUP)))
@@ -126,17 +131,34 @@ static void test_egress_only(int parent_cgroup_fd, int child_cgroup_fd)
goto close_bpf_object;
if (CHECK_FAIL(obj->bss->invocations != 3))
goto close_bpf_object;
+ expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
if (CHECK_FAIL(assert_storage(obj->maps.cgroup_storage,
- PARENT_CGROUP, 2)))
+ PARENT_CGROUP, &expected_cgroup_value)))
goto close_bpf_object;
+ expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
if (CHECK_FAIL(assert_storage(obj->maps.cgroup_storage,
- CHILD_CGROUP, 1)))
+ CHILD_CGROUP, &expected_cgroup_value)))
goto close_bpf_object;
close_bpf_object:
cg_storage_multi_egress_only__destroy(obj);
}
+static void test_egress_ingress(int parent_cgroup_fd, int child_cgroup_fd)
+{
+ struct cg_storage_multi_egress_ingress *obj;
+
+ if (!test__start_subtest("egress_ingress"))
+ return;
+
+ /* Cannot load both programs due to verifier failure:
+ * "only one cgroup storage of each type is allowed"
+ */
+ obj = cg_storage_multi_egress_ingress__open_and_load();
+ if (CHECK_FAIL(obj || errno != EBUSY))
+ return;
+}
+
void test_cg_storage_multi(void)
{
int parent_cgroup_fd, child_cgroup_fd;
@@ -147,6 +169,7 @@ void test_cg_storage_multi(void)
goto close_cgroup_fd;
test_egress_only(parent_cgroup_fd, child_cgroup_fd);
+ test_egress_ingress(parent_cgroup_fd, child_cgroup_fd);
close_cgroup_fd:
close(child_cgroup_fd);
new file mode 100644
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __PROGS_CG_STORAGE_MULTI_H
+#define __PROGS_CG_STORAGE_MULTI_H
+
+#include <asm/types.h>
+
+struct cgroup_value {
+ __u32 egress_pkts;
+ __u32 ingress_pkts;
+};
+
+#endif
new file mode 100644
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+/*
+ * Copyright 2020 Google LLC.
+ */
+
+#include <errno.h>
+#include <linux/bpf.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <bpf/bpf_helpers.h>
+
+#include "progs/cg_storage_multi.h"
+
+struct {
+ __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
+ __type(key, struct bpf_cgroup_storage_key);
+ __type(value, struct cgroup_value);
+} cgroup_storage SEC(".maps");
+
+__u32 invocations = 0;
+
+SEC("cgroup_skb/egress")
+int egress(struct __sk_buff *skb)
+{
+ struct cgroup_value *ptr_cg_storage =
+ bpf_get_local_storage(&cgroup_storage, 0);
+
+ __sync_fetch_and_add(&ptr_cg_storage->egress_pkts, 1);
+ __sync_fetch_and_add(&invocations, 1);
+
+ return 1;
+}
+
+SEC("cgroup_skb/ingress")
+int ingress(struct __sk_buff *skb)
+{
+ struct cgroup_value *ptr_cg_storage =
+ bpf_get_local_storage(&cgroup_storage, 0);
+
+ __sync_fetch_and_add(&ptr_cg_storage->ingress_pkts, 1);
+ __sync_fetch_and_add(&invocations, 1);
+
+ return 1;
+}
@@ -10,10 +10,12 @@
#include <linux/udp.h>
#include <bpf/bpf_helpers.h>
+#include "progs/cg_storage_multi.h"
+
struct {
__uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
__type(key, struct bpf_cgroup_storage_key);
- __type(value, __u32);
+ __type(value, struct cgroup_value);
} cgroup_storage SEC(".maps");
__u32 invocations = 0;
@@ -21,9 +23,10 @@ __u32 invocations = 0;
SEC("cgroup_skb/egress")
int egress(struct __sk_buff *skb)
{
- __u32 *ptr_cg_storage = bpf_get_local_storage(&cgroup_storage, 0);
+ struct cgroup_value *ptr_cg_storage =
+ bpf_get_local_storage(&cgroup_storage, 0);
- __sync_fetch_and_add(ptr_cg_storage, 1);
+ __sync_fetch_and_add(&ptr_cg_storage->egress_pkts, 1);
__sync_fetch_and_add(&invocations, 1);
return 1;