linux/tools/testing/selftests/bpf/test_netcnt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <stdio.h>
   3#include <stdlib.h>
   4#include <string.h>
   5#include <errno.h>
   6#include <assert.h>
   7#include <sys/sysinfo.h>
   8#include <sys/time.h>
   9
  10#include <linux/bpf.h>
  11#include <bpf/bpf.h>
  12#include <bpf/libbpf.h>
  13
  14#include "cgroup_helpers.h"
  15#include "bpf_rlimit.h"
  16#include "netcnt_common.h"
  17
  18#define BPF_PROG "./netcnt_prog.o"
  19#define TEST_CGROUP "/test-network-counters/"
  20
  21static int bpf_find_map(const char *test, struct bpf_object *obj,
  22                        const char *name)
  23{
  24        struct bpf_map *map;
  25
  26        map = bpf_object__find_map_by_name(obj, name);
  27        if (!map) {
  28                printf("%s:FAIL:map '%s' not found\n", test, name);
  29                return -1;
  30        }
  31        return bpf_map__fd(map);
  32}
  33
  34int main(int argc, char **argv)
  35{
  36        struct percpu_net_cnt *percpu_netcnt;
  37        struct bpf_cgroup_storage_key key;
  38        int map_fd, percpu_map_fd;
  39        int error = EXIT_FAILURE;
  40        struct net_cnt netcnt;
  41        struct bpf_object *obj;
  42        int prog_fd, cgroup_fd;
  43        unsigned long packets;
  44        unsigned long bytes;
  45        int cpu, nproc;
  46        __u32 prog_cnt;
  47
  48        nproc = get_nprocs_conf();
  49        percpu_netcnt = malloc(sizeof(*percpu_netcnt) * nproc);
  50        if (!percpu_netcnt) {
  51                printf("Not enough memory for per-cpu area (%d cpus)\n", nproc);
  52                goto err;
  53        }
  54
  55        if (bpf_prog_load(BPF_PROG, BPF_PROG_TYPE_CGROUP_SKB,
  56                          &obj, &prog_fd)) {
  57                printf("Failed to load bpf program\n");
  58                goto out;
  59        }
  60
  61        if (setup_cgroup_environment()) {
  62                printf("Failed to load bpf program\n");
  63                goto err;
  64        }
  65
  66        /* Create a cgroup, get fd, and join it */
  67        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
  68        if (cgroup_fd < 0) {
  69                printf("Failed to create test cgroup\n");
  70                goto err;
  71        }
  72
  73        if (join_cgroup(TEST_CGROUP)) {
  74                printf("Failed to join cgroup\n");
  75                goto err;
  76        }
  77
  78        /* Attach bpf program */
  79        if (bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 0)) {
  80                printf("Failed to attach bpf program");
  81                goto err;
  82        }
  83
  84        if (system("which ping6 &>/dev/null") == 0)
  85                assert(!system("ping6 localhost -c 10000 -f -q > /dev/null"));
  86        else
  87                assert(!system("ping -6 localhost -c 10000 -f -q > /dev/null"));
  88
  89        if (bpf_prog_query(cgroup_fd, BPF_CGROUP_INET_EGRESS, 0, NULL, NULL,
  90                           &prog_cnt)) {
  91                printf("Failed to query attached programs");
  92                goto err;
  93        }
  94
  95        map_fd = bpf_find_map(__func__, obj, "netcnt");
  96        if (map_fd < 0) {
  97                printf("Failed to find bpf map with net counters");
  98                goto err;
  99        }
 100
 101        percpu_map_fd = bpf_find_map(__func__, obj, "percpu_netcnt");
 102        if (percpu_map_fd < 0) {
 103                printf("Failed to find bpf map with percpu net counters");
 104                goto err;
 105        }
 106
 107        if (bpf_map_get_next_key(map_fd, NULL, &key)) {
 108                printf("Failed to get key in cgroup storage\n");
 109                goto err;
 110        }
 111
 112        if (bpf_map_lookup_elem(map_fd, &key, &netcnt)) {
 113                printf("Failed to lookup cgroup storage\n");
 114                goto err;
 115        }
 116
 117        if (bpf_map_lookup_elem(percpu_map_fd, &key, &percpu_netcnt[0])) {
 118                printf("Failed to lookup percpu cgroup storage\n");
 119                goto err;
 120        }
 121
 122        /* Some packets can be still in per-cpu cache, but not more than
 123         * MAX_PERCPU_PACKETS.
 124         */
 125        packets = netcnt.packets;
 126        bytes = netcnt.bytes;
 127        for (cpu = 0; cpu < nproc; cpu++) {
 128                if (percpu_netcnt[cpu].packets > MAX_PERCPU_PACKETS) {
 129                        printf("Unexpected percpu value: %llu\n",
 130                               percpu_netcnt[cpu].packets);
 131                        goto err;
 132                }
 133
 134                packets += percpu_netcnt[cpu].packets;
 135                bytes += percpu_netcnt[cpu].bytes;
 136        }
 137
 138        /* No packets should be lost */
 139        if (packets != 10000) {
 140                printf("Unexpected packet count: %lu\n", packets);
 141                goto err;
 142        }
 143
 144        /* Let's check that bytes counter matches the number of packets
 145         * multiplied by the size of ipv6 ICMP packet.
 146         */
 147        if (bytes != packets * 104) {
 148                printf("Unexpected bytes count: %lu\n", bytes);
 149                goto err;
 150        }
 151
 152        error = 0;
 153        printf("test_netcnt:PASS\n");
 154
 155err:
 156        cleanup_cgroup_environment();
 157        free(percpu_netcnt);
 158
 159out:
 160        return error;
 161}
 162