linux/tools/testing/selftests/bpf/progs/bpf_iter_bpf_hash_map.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/* Copyright (c) 2020 Facebook */
   3#include "bpf_iter.h"
   4#include <bpf/bpf_helpers.h>
   5
   6char _license[] SEC("license") = "GPL";
   7
   8struct key_t {
   9        int a;
  10        int b;
  11        int c;
  12};
  13
  14struct {
  15        __uint(type, BPF_MAP_TYPE_HASH);
  16        __uint(max_entries, 3);
  17        __type(key, struct key_t);
  18        __type(value, __u64);
  19} hashmap1 SEC(".maps");
  20
  21struct {
  22        __uint(type, BPF_MAP_TYPE_HASH);
  23        __uint(max_entries, 3);
  24        __type(key, __u64);
  25        __type(value, __u64);
  26} hashmap2 SEC(".maps");
  27
  28struct {
  29        __uint(type, BPF_MAP_TYPE_HASH);
  30        __uint(max_entries, 3);
  31        __type(key, struct key_t);
  32        __type(value, __u32);
  33} hashmap3 SEC(".maps");
  34
  35/* will set before prog run */
  36bool in_test_mode = 0;
  37
  38/* will collect results during prog run */
  39__u32 key_sum_a = 0, key_sum_b = 0, key_sum_c = 0;
  40__u64 val_sum = 0;
  41
  42SEC("iter/bpf_map_elem")
  43int dump_bpf_hash_map(struct bpf_iter__bpf_map_elem *ctx)
  44{
  45        struct seq_file *seq = ctx->meta->seq;
  46        __u32 seq_num = ctx->meta->seq_num;
  47        struct bpf_map *map = ctx->map;
  48        struct key_t *key = ctx->key;
  49        struct key_t tmp_key;
  50        __u64 *val = ctx->value;
  51        __u64 tmp_val = 0;
  52        int ret;
  53
  54        if (in_test_mode) {
  55                /* test mode is used by selftests to
  56                 * test functionality of bpf_hash_map iter.
  57                 *
  58                 * the above hashmap1 will have correct size
  59                 * and will be accepted, hashmap2 and hashmap3
  60                 * should be rejected due to smaller key/value
  61                 * size.
  62                 */
  63                if (key == (void *)0 || val == (void *)0)
  64                        return 0;
  65
  66                /* update the value and then delete the <key, value> pair.
  67                 * it should not impact the existing 'val' which is still
  68                 * accessible under rcu.
  69                 */
  70                __builtin_memcpy(&tmp_key, key, sizeof(struct key_t));
  71                ret = bpf_map_update_elem(&hashmap1, &tmp_key, &tmp_val, 0);
  72                if (ret)
  73                        return 0;
  74                ret = bpf_map_delete_elem(&hashmap1, &tmp_key);
  75                if (ret)
  76                        return 0;
  77
  78                key_sum_a += key->a;
  79                key_sum_b += key->b;
  80                key_sum_c += key->c;
  81                val_sum += *val;
  82                return 0;
  83        }
  84
  85        /* non-test mode, the map is prepared with the
  86         * below bpftool command sequence:
  87         *   bpftool map create /sys/fs/bpf/m1 type hash \
  88         *      key 12 value 8 entries 3 name map1
  89         *   bpftool map update id 77 key 0 0 0 1 0 0 0 0 0 0 0 1 \
  90         *      value 0 0 0 1 0 0 0 1
  91         *   bpftool map update id 77 key 0 0 0 1 0 0 0 0 0 0 0 2 \
  92         *      value 0 0 0 1 0 0 0 2
  93         * The bpftool iter command line:
  94         *   bpftool iter pin ./bpf_iter_bpf_hash_map.o /sys/fs/bpf/p1 \
  95         *      map id 77
  96         * The below output will be:
  97         *   map dump starts
  98         *   77: (1000000 0 2000000) (200000001000000)
  99         *   77: (1000000 0 1000000) (100000001000000)
 100         *   map dump ends
 101         */
 102        if (seq_num == 0)
 103                BPF_SEQ_PRINTF(seq, "map dump starts\n");
 104
 105        if (key == (void *)0 || val == (void *)0) {
 106                BPF_SEQ_PRINTF(seq, "map dump ends\n");
 107                return 0;
 108        }
 109
 110        BPF_SEQ_PRINTF(seq, "%d: (%x %d %x) (%llx)\n", map->id,
 111                       key->a, key->b, key->c, *val);
 112
 113        return 0;
 114}
 115