Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/bpf/prog_tests/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 13 kB image not shown  

Quelle  cg_storage_multi.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only

/*
 * Copyright 2020 Google LLC.
 */


#include <test_progs.h>
#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_isolated.skel.h"
#include "cg_storage_multi_shared.skel.h"

#define PARENT_CGROUP "/cgroup_storage"
#define CHILD_CGROUP "/cgroup_storage/child"

static int duration;

static bool assert_storage(struct bpf_map *map, const void *key,
      struct cgroup_value *expected)
{
 struct cgroup_value value;
 int map_fd;

 map_fd = bpf_map__fd(map);

 if (CHECK(bpf_map_lookup_elem(map_fd, key, &value) < 0,
    "map-lookup""errno %d", errno))
  return true;
 if (CHECK(memcmp(&value, expected, sizeof(struct cgroup_value)),
    "assert-storage""storages differ"))
  return true;

 return false;
}

static bool assert_storage_noexist(struct bpf_map *map, const void *key)
{
 struct cgroup_value value;
 int map_fd;

 map_fd = bpf_map__fd(map);

 if (CHECK(bpf_map_lookup_elem(map_fd, key, &value) == 0,
    "map-lookup""succeeded, expected ENOENT"))
  return true;
 if (CHECK(errno != ENOENT,
    "map-lookup""errno %d, expected ENOENT", errno))
  return true;

 return false;
}

static bool connect_send(const char *cgroup_path)
{
 int server_fd = -1, client_fd = -1;
 char message[] = "message";
 bool res = true;

 if (join_cgroup(cgroup_path))
  goto out_clean;

 server_fd = start_server(AF_INET, SOCK_DGRAM, NULL, 0, 0);
 if (server_fd < 0)
  goto out_clean;

 client_fd = connect_to_fd(server_fd, 0);
 if (client_fd < 0)
  goto out_clean;

 if (send(client_fd, &message, sizeof(message), 0) < 0)
  goto out_clean;

 if (read(server_fd, &message, sizeof(message)) < 0)
  goto out_clean;

 res = false;

out_clean:
 close(client_fd);
 close(server_fd);
 return res;
}

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;
 struct bpf_cgroup_storage_key key;
 struct bpf_link *parent_link = NULL, *child_link = NULL;
 bool err;

 key.attach_type = BPF_CGROUP_INET_EGRESS;

 obj = cg_storage_multi_egress_only__open_and_load();
 if (CHECK(!obj, "skel-load""errno %d", errno))
  return;

 /* Attach to parent cgroup, trigger packet from child.
 * Assert that there is only one run and in that run the storage is
 * parent cgroup's storage.
 * Also assert that child cgroup's storage does not exist
 */

 parent_link = bpf_program__attach_cgroup(obj->progs.egress,
       parent_cgroup_fd);
 if (!ASSERT_OK_PTR(parent_link, "parent-cg-attach"))
  goto close_bpf_object;
 err = connect_send(CHILD_CGROUP);
 if (CHECK(err, "first-connect-send""errno %d", errno))
  goto close_bpf_object;
 if (CHECK(obj->bss->invocations != 1,
    "first-invoke""invocations=%d", obj->bss->invocations))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
 expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
 if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
  goto close_bpf_object;

 /* Attach to parent and child cgroup, trigger packet from child.
 * Assert that there are two additional runs, one that run with parent
 * cgroup's storage and one with child cgroup's storage.
 */

 child_link = bpf_program__attach_cgroup(obj->progs.egress,
      child_cgroup_fd);
 if (!ASSERT_OK_PTR(child_link, "child-cg-attach"))
  goto close_bpf_object;
 err = connect_send(CHILD_CGROUP);
 if (CHECK(err, "second-connect-send""errno %d", errno))
  goto close_bpf_object;
 if (CHECK(obj->bss->invocations != 3,
    "second-invoke""invocations=%d", obj->bss->invocations))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
 expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
 expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 1 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;

close_bpf_object:
 bpf_link__destroy(parent_link);
 bpf_link__destroy(child_link);

 cg_storage_multi_egress_only__destroy(obj);
}

static void test_isolated(int parent_cgroup_fd, int child_cgroup_fd)
{
 struct cg_storage_multi_isolated *obj;
 struct cgroup_value expected_cgroup_value;
 struct bpf_cgroup_storage_key key;
 struct bpf_link *parent_egress1_link = NULL, *parent_egress2_link = NULL;
 struct bpf_link *child_egress1_link = NULL, *child_egress2_link = NULL;
 struct bpf_link *parent_ingress_link = NULL, *child_ingress_link = NULL;
 bool err;

 obj = cg_storage_multi_isolated__open_and_load();
 if (CHECK(!obj, "skel-load""errno %d", errno))
  return;

 /* Attach to parent cgroup, trigger packet from child.
 * Assert that there is three runs, two with parent cgroup egress and
 * one with parent cgroup ingress, stored in separate parent storages.
 * Also assert that child cgroup's storages does not exist
 */

 parent_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
        parent_cgroup_fd);
 if (!ASSERT_OK_PTR(parent_egress1_link, "parent-egress1-cg-attach"))
  goto close_bpf_object;
 parent_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
        parent_cgroup_fd);
 if (!ASSERT_OK_PTR(parent_egress2_link, "parent-egress2-cg-attach"))
  goto close_bpf_object;
 parent_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
        parent_cgroup_fd);
 if (!ASSERT_OK_PTR(parent_ingress_link, "parent-ingress-cg-attach"))
  goto close_bpf_object;
 err = connect_send(CHILD_CGROUP);
 if (CHECK(err, "first-connect-send""errno %d", errno))
  goto close_bpf_object;
 if (CHECK(obj->bss->invocations != 3,
    "first-invoke""invocations=%d", obj->bss->invocations))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
 key.attach_type = BPF_CGROUP_INET_EGRESS;
 expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key.attach_type = BPF_CGROUP_INET_INGRESS;
 expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 1 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
 key.attach_type = BPF_CGROUP_INET_EGRESS;
 if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
  goto close_bpf_object;
 key.attach_type = BPF_CGROUP_INET_INGRESS;
 if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
  goto close_bpf_object;

 /* Attach to parent and child cgroup, trigger packet from child.
 * Assert that there is six additional runs, parent cgroup egresses and
 * ingress, child cgroup egresses and ingress.
 * Assert that egress and ingress storages are separate.
 */

 child_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
       child_cgroup_fd);
 if (!ASSERT_OK_PTR(child_egress1_link, "child-egress1-cg-attach"))
  goto close_bpf_object;
 child_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
       child_cgroup_fd);
 if (!ASSERT_OK_PTR(child_egress2_link, "child-egress2-cg-attach"))
  goto close_bpf_object;
 child_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
       child_cgroup_fd);
 if (!ASSERT_OK_PTR(child_ingress_link, "child-ingress-cg-attach"))
  goto close_bpf_object;
 err = connect_send(CHILD_CGROUP);
 if (CHECK(err, "second-connect-send""errno %d", errno))
  goto close_bpf_object;
 if (CHECK(obj->bss->invocations != 9,
    "second-invoke""invocations=%d", obj->bss->invocations))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(PARENT_CGROUP);
 key.attach_type = BPF_CGROUP_INET_EGRESS;
 expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 4 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key.attach_type = BPF_CGROUP_INET_INGRESS;
 expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 2 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key.cgroup_inode_id = get_cgroup_id(CHILD_CGROUP);
 key.attach_type = BPF_CGROUP_INET_EGRESS;
 expected_cgroup_value = (struct cgroup_value) { .egress_pkts = 2 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key.attach_type = BPF_CGROUP_INET_INGRESS;
 expected_cgroup_value = (struct cgroup_value) { .ingress_pkts = 1 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;

close_bpf_object:
 bpf_link__destroy(parent_egress1_link);
 bpf_link__destroy(parent_egress2_link);
 bpf_link__destroy(parent_ingress_link);
 bpf_link__destroy(child_egress1_link);
 bpf_link__destroy(child_egress2_link);
 bpf_link__destroy(child_ingress_link);

 cg_storage_multi_isolated__destroy(obj);
}

static void test_shared(int parent_cgroup_fd, int child_cgroup_fd)
{
 struct cg_storage_multi_shared *obj;
 struct cgroup_value expected_cgroup_value;
 __u64 key;
 struct bpf_link *parent_egress1_link = NULL, *parent_egress2_link = NULL;
 struct bpf_link *child_egress1_link = NULL, *child_egress2_link = NULL;
 struct bpf_link *parent_ingress_link = NULL, *child_ingress_link = NULL;
 bool err;

 obj = cg_storage_multi_shared__open_and_load();
 if (CHECK(!obj, "skel-load""errno %d", errno))
  return;

 /* Attach to parent cgroup, trigger packet from child.
 * Assert that there is three runs, two with parent cgroup egress and
 * one with parent cgroup ingress.
 * Also assert that child cgroup's storage does not exist
 */

 parent_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
        parent_cgroup_fd);
 if (!ASSERT_OK_PTR(parent_egress1_link, "parent-egress1-cg-attach"))
  goto close_bpf_object;
 parent_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
        parent_cgroup_fd);
 if (!ASSERT_OK_PTR(parent_egress2_link, "parent-egress2-cg-attach"))
  goto close_bpf_object;
 parent_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
        parent_cgroup_fd);
 if (!ASSERT_OK_PTR(parent_ingress_link, "parent-ingress-cg-attach"))
  goto close_bpf_object;
 err = connect_send(CHILD_CGROUP);
 if (CHECK(err, "first-connect-send""errno %d", errno))
  goto close_bpf_object;
 if (CHECK(obj->bss->invocations != 3,
    "first-invoke""invocations=%d", obj->bss->invocations))
  goto close_bpf_object;
 key = get_cgroup_id(PARENT_CGROUP);
 expected_cgroup_value = (struct cgroup_value) {
  .egress_pkts = 2,
  .ingress_pkts = 1,
 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key = get_cgroup_id(CHILD_CGROUP);
 if (assert_storage_noexist(obj->maps.cgroup_storage, &key))
  goto close_bpf_object;

 /* Attach to parent and child cgroup, trigger packet from child.
 * Assert that there is six additional runs, parent cgroup egresses and
 * ingress, child cgroup egresses and ingress.
 */

 child_egress1_link = bpf_program__attach_cgroup(obj->progs.egress1,
       child_cgroup_fd);
 if (!ASSERT_OK_PTR(child_egress1_link, "child-egress1-cg-attach"))
  goto close_bpf_object;
 child_egress2_link = bpf_program__attach_cgroup(obj->progs.egress2,
       child_cgroup_fd);
 if (!ASSERT_OK_PTR(child_egress2_link, "child-egress2-cg-attach"))
  goto close_bpf_object;
 child_ingress_link = bpf_program__attach_cgroup(obj->progs.ingress,
       child_cgroup_fd);
 if (!ASSERT_OK_PTR(child_ingress_link, "child-ingress-cg-attach"))
  goto close_bpf_object;
 err = connect_send(CHILD_CGROUP);
 if (CHECK(err, "second-connect-send""errno %d", errno))
  goto close_bpf_object;
 if (CHECK(obj->bss->invocations != 9,
    "second-invoke""invocations=%d", obj->bss->invocations))
  goto close_bpf_object;
 key = get_cgroup_id(PARENT_CGROUP);
 expected_cgroup_value = (struct cgroup_value) {
  .egress_pkts = 4,
  .ingress_pkts = 2,
 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;
 key = get_cgroup_id(CHILD_CGROUP);
 expected_cgroup_value = (struct cgroup_value) {
  .egress_pkts = 2,
  .ingress_pkts = 1,
 };
 if (assert_storage(obj->maps.cgroup_storage,
      &key, &expected_cgroup_value))
  goto close_bpf_object;

close_bpf_object:
 bpf_link__destroy(parent_egress1_link);
 bpf_link__destroy(parent_egress2_link);
 bpf_link__destroy(parent_ingress_link);
 bpf_link__destroy(child_egress1_link);
 bpf_link__destroy(child_egress2_link);
 bpf_link__destroy(child_ingress_link);

 cg_storage_multi_shared__destroy(obj);
}

void serial_test_cg_storage_multi(void)
{
 int parent_cgroup_fd = -1, child_cgroup_fd = -1;

 parent_cgroup_fd = test__join_cgroup(PARENT_CGROUP);
 if (CHECK(parent_cgroup_fd < 0, "cg-create-parent""errno %d", errno))
  goto close_cgroup_fd;
 child_cgroup_fd = create_and_get_cgroup(CHILD_CGROUP);
 if (CHECK(child_cgroup_fd < 0, "cg-create-child""errno %d", errno))
  goto close_cgroup_fd;

 if (test__start_subtest("egress_only"))
  test_egress_only(parent_cgroup_fd, child_cgroup_fd);

 if (test__start_subtest("isolated"))
  test_isolated(parent_cgroup_fd, child_cgroup_fd);

 if (test__start_subtest("shared"))
  test_shared(parent_cgroup_fd, child_cgroup_fd);

close_cgroup_fd:
 close(child_cgroup_fd);
 close(parent_cgroup_fd);
}

Messung V0.5
C=91 H=68 G=80

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.