12a7c2fffSYonghong Song // SPDX-License-Identifier: GPL-2.0
22a7c2fffSYonghong Song /* Copyright (c) 2020 Facebook */
32a7c2fffSYonghong Song #include "bpf_iter.h"
42a7c2fffSYonghong Song #include <bpf/bpf_helpers.h>
52a7c2fffSYonghong Song 
62a7c2fffSYonghong Song char _license[] SEC("license") = "GPL";
72a7c2fffSYonghong Song 
82a7c2fffSYonghong Song struct key_t {
92a7c2fffSYonghong Song 	int a;
102a7c2fffSYonghong Song 	int b;
112a7c2fffSYonghong Song 	int c;
122a7c2fffSYonghong Song };
132a7c2fffSYonghong Song 
142a7c2fffSYonghong Song struct {
152a7c2fffSYonghong Song 	__uint(type, BPF_MAP_TYPE_HASH);
162a7c2fffSYonghong Song 	__uint(max_entries, 3);
172a7c2fffSYonghong Song 	__type(key, struct key_t);
182a7c2fffSYonghong Song 	__type(value, __u64);
192a7c2fffSYonghong Song } hashmap1 SEC(".maps");
202a7c2fffSYonghong Song 
212a7c2fffSYonghong Song struct {
222a7c2fffSYonghong Song 	__uint(type, BPF_MAP_TYPE_HASH);
232a7c2fffSYonghong Song 	__uint(max_entries, 3);
242a7c2fffSYonghong Song 	__type(key, __u64);
252a7c2fffSYonghong Song 	__type(value, __u64);
262a7c2fffSYonghong Song } hashmap2 SEC(".maps");
272a7c2fffSYonghong Song 
282a7c2fffSYonghong Song struct {
292a7c2fffSYonghong Song 	__uint(type, BPF_MAP_TYPE_HASH);
302a7c2fffSYonghong Song 	__uint(max_entries, 3);
312a7c2fffSYonghong Song 	__type(key, struct key_t);
322a7c2fffSYonghong Song 	__type(value, __u32);
332a7c2fffSYonghong Song } hashmap3 SEC(".maps");
342a7c2fffSYonghong Song 
352a7c2fffSYonghong Song /* will set before prog run */
362a7c2fffSYonghong Song bool in_test_mode = 0;
372a7c2fffSYonghong Song 
382a7c2fffSYonghong Song /* will collect results during prog run */
392a7c2fffSYonghong Song __u32 key_sum_a = 0, key_sum_b = 0, key_sum_c = 0;
402a7c2fffSYonghong Song __u64 val_sum = 0;
412a7c2fffSYonghong Song 
422a7c2fffSYonghong Song SEC("iter/bpf_map_elem")
dump_bpf_hash_map(struct bpf_iter__bpf_map_elem * ctx)432a7c2fffSYonghong Song int dump_bpf_hash_map(struct bpf_iter__bpf_map_elem *ctx)
442a7c2fffSYonghong Song {
452a7c2fffSYonghong Song 	struct seq_file *seq = ctx->meta->seq;
462a7c2fffSYonghong Song 	__u32 seq_num = ctx->meta->seq_num;
472a7c2fffSYonghong Song 	struct bpf_map *map = ctx->map;
482a7c2fffSYonghong Song 	struct key_t *key = ctx->key;
494daab713SYonghong Song 	struct key_t tmp_key;
502a7c2fffSYonghong Song 	__u64 *val = ctx->value;
514daab713SYonghong Song 	__u64 tmp_val = 0;
524daab713SYonghong Song 	int ret;
532a7c2fffSYonghong Song 
542a7c2fffSYonghong Song 	if (in_test_mode) {
552a7c2fffSYonghong Song 		/* test mode is used by selftests to
562a7c2fffSYonghong Song 		 * test functionality of bpf_hash_map iter.
572a7c2fffSYonghong Song 		 *
582a7c2fffSYonghong Song 		 * the above hashmap1 will have correct size
592a7c2fffSYonghong Song 		 * and will be accepted, hashmap2 and hashmap3
602a7c2fffSYonghong Song 		 * should be rejected due to smaller key/value
612a7c2fffSYonghong Song 		 * size.
622a7c2fffSYonghong Song 		 */
632a7c2fffSYonghong Song 		if (key == (void *)0 || val == (void *)0)
642a7c2fffSYonghong Song 			return 0;
652a7c2fffSYonghong Song 
664daab713SYonghong Song 		/* update the value and then delete the <key, value> pair.
674daab713SYonghong Song 		 * it should not impact the existing 'val' which is still
684daab713SYonghong Song 		 * accessible under rcu.
694daab713SYonghong Song 		 */
704daab713SYonghong Song 		__builtin_memcpy(&tmp_key, key, sizeof(struct key_t));
714daab713SYonghong Song 		ret = bpf_map_update_elem(&hashmap1, &tmp_key, &tmp_val, 0);
724daab713SYonghong Song 		if (ret)
734daab713SYonghong Song 			return 0;
744daab713SYonghong Song 		ret = bpf_map_delete_elem(&hashmap1, &tmp_key);
754daab713SYonghong Song 		if (ret)
764daab713SYonghong Song 			return 0;
774daab713SYonghong Song 
782a7c2fffSYonghong Song 		key_sum_a += key->a;
792a7c2fffSYonghong Song 		key_sum_b += key->b;
802a7c2fffSYonghong Song 		key_sum_c += key->c;
812a7c2fffSYonghong Song 		val_sum += *val;
822a7c2fffSYonghong Song 		return 0;
832a7c2fffSYonghong Song 	}
842a7c2fffSYonghong Song 
852a7c2fffSYonghong Song 	/* non-test mode, the map is prepared with the
862a7c2fffSYonghong Song 	 * below bpftool command sequence:
872a7c2fffSYonghong Song 	 *   bpftool map create /sys/fs/bpf/m1 type hash \
882a7c2fffSYonghong Song 	 *   	key 12 value 8 entries 3 name map1
892a7c2fffSYonghong Song 	 *   bpftool map update id 77 key 0 0 0 1 0 0 0 0 0 0 0 1 \
902a7c2fffSYonghong Song 	 *   	value 0 0 0 1 0 0 0 1
912a7c2fffSYonghong Song 	 *   bpftool map update id 77 key 0 0 0 1 0 0 0 0 0 0 0 2 \
922a7c2fffSYonghong Song 	 *   	value 0 0 0 1 0 0 0 2
932a7c2fffSYonghong Song 	 * The bpftool iter command line:
942a7c2fffSYonghong Song 	 *   bpftool iter pin ./bpf_iter_bpf_hash_map.o /sys/fs/bpf/p1 \
952a7c2fffSYonghong Song 	 *   	map id 77
962a7c2fffSYonghong Song 	 * The below output will be:
972a7c2fffSYonghong Song 	 *   map dump starts
982a7c2fffSYonghong Song 	 *   77: (1000000 0 2000000) (200000001000000)
992a7c2fffSYonghong Song 	 *   77: (1000000 0 1000000) (100000001000000)
1002a7c2fffSYonghong Song 	 *   map dump ends
1012a7c2fffSYonghong Song 	 */
1022a7c2fffSYonghong Song 	if (seq_num == 0)
1032a7c2fffSYonghong Song 		BPF_SEQ_PRINTF(seq, "map dump starts\n");
1042a7c2fffSYonghong Song 
1052a7c2fffSYonghong Song 	if (key == (void *)0 || val == (void *)0) {
1062a7c2fffSYonghong Song 		BPF_SEQ_PRINTF(seq, "map dump ends\n");
1072a7c2fffSYonghong Song 		return 0;
1082a7c2fffSYonghong Song 	}
1092a7c2fffSYonghong Song 
1102a7c2fffSYonghong Song 	BPF_SEQ_PRINTF(seq, "%d: (%x %d %x) (%llx)\n", map->id,
1112a7c2fffSYonghong Song 		       key->a, key->b, key->c, *val);
1122a7c2fffSYonghong Song 
1132a7c2fffSYonghong Song 	return 0;
1142a7c2fffSYonghong Song }
115*c5c0981fSHou Tao 
116*c5c0981fSHou Tao SEC("iter.s/bpf_map_elem")
sleepable_dummy_dump(struct bpf_iter__bpf_map_elem * ctx)117*c5c0981fSHou Tao int sleepable_dummy_dump(struct bpf_iter__bpf_map_elem *ctx)
118*c5c0981fSHou Tao {
119*c5c0981fSHou Tao 	if (ctx->meta->seq_num == 0)
120*c5c0981fSHou Tao 		BPF_SEQ_PRINTF(ctx->meta->seq, "map dump starts\n");
121*c5c0981fSHou Tao 
122*c5c0981fSHou Tao 	return 0;
123*c5c0981fSHou Tao }
124