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        cgroup_fd = cgroup_setup_and_join(TEST_CGROUP);
  62        if (cgroup_fd < 0)
  63                goto err;
  64
  65        /* Attach bpf program */
  66        if (bpf_prog_attach(prog_fd, cgroup_fd, BPF_CGROUP_INET_EGRESS, 0)) {
  67                printf("Failed to attach bpf program");
  68                goto err;
  69        }
  70
  71        if (system("which ping6 &>/dev/null") == 0)
  72                assert(!system("ping6 ::1 -c 10000 -f -q > /dev/null"));
  73        else
  74                assert(!system("ping -6 ::1 -c 10000 -f -q > /dev/null"));
  75
  76        if (bpf_prog_query(cgroup_fd, BPF_CGROUP_INET_EGRESS, 0, NULL, NULL,
  77                           &prog_cnt)) {
  78                printf("Failed to query attached programs");
  79                goto err;
  80        }
  81
  82        map_fd = bpf_find_map(__func__, obj, "netcnt");
  83        if (map_fd < 0) {
  84                printf("Failed to find bpf map with net counters");
  85                goto err;
  86        }
  87
  88        percpu_map_fd = bpf_find_map(__func__, obj, "percpu_netcnt");
  89        if (percpu_map_fd < 0) {
  90                printf("Failed to find bpf map with percpu net counters");
  91                goto err;
  92        }
  93
  94        if (bpf_map_get_next_key(map_fd, NULL, &key)) {
  95                printf("Failed to get key in cgroup storage\n");
  96                goto err;
  97        }
  98
  99        if (bpf_map_lookup_elem(map_fd, &key, &netcnt)) {
 100                printf("Failed to lookup cgroup storage\n");
 101                goto err;
 102        }
 103
 104        if (bpf_map_lookup_elem(percpu_map_fd, &key, &percpu_netcnt[0])) {
 105                printf("Failed to lookup percpu cgroup storage\n");
 106                goto err;
 107        }
 108
 109        /* Some packets can be still in per-cpu cache, but not more than
 110         * MAX_PERCPU_PACKETS.
 111         */
 112        packets = netcnt.packets;
 113        bytes = netcnt.bytes;
 114        for (cpu = 0; cpu < nproc; cpu++) {
 115                if (percpu_netcnt[cpu].packets > MAX_PERCPU_PACKETS) {
 116                        printf("Unexpected percpu value: %llu\n",
 117                               percpu_netcnt[cpu].packets);
 118                        goto err;
 119                }
 120
 121                packets += percpu_netcnt[cpu].packets;
 122                bytes += percpu_netcnt[cpu].bytes;
 123        }
 124
 125        /* No packets should be lost */
 126        if (packets != 10000) {
 127                printf("Unexpected packet count: %lu\n", packets);
 128                goto err;
 129        }
 130
 131        /* Let's check that bytes counter matches the number of packets
 132         * multiplied by the size of ipv6 ICMP packet.
 133         */
 134        if (bytes != packets * 104) {
 135                printf("Unexpected bytes count: %lu\n", bytes);
 136                goto err;
 137        }
 138
 139        error = 0;
 140        printf("test_netcnt:PASS\n");
 141
 142err:
 143        cleanup_cgroup_environment();
 144        free(percpu_netcnt);
 145
 146out:
 147        return error;
 148}
 149