Linux Audio

Check our new training course

Loading...
  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
116SEC("iter.s/bpf_map_elem")
117int sleepable_dummy_dump(struct bpf_iter__bpf_map_elem *ctx)
118{
119	if (ctx->meta->seq_num == 0)
120		BPF_SEQ_PRINTF(ctx->meta->seq, "map dump starts\n");
121
122	return 0;
123}