xref: /aosp_15_r20/external/bcc/libbpf-tools/map_helpers.c (revision 387f9dfdfa2baef462e92476d413c7bc2470293e)
1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2 // Copyright (c) 2020 Anton Protopopov
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <errno.h>
6 
7 #include "map_helpers.h"
8 
9 #define warn(...) fprintf(stderr, __VA_ARGS__)
10 
11 static bool batch_map_ops = true; /* hope for the best */
12 
13 static int
dump_hash_iter(int map_fd,void * keys,__u32 key_size,void * values,__u32 value_size,__u32 * count,void * invalid_key)14 dump_hash_iter(int map_fd, void *keys, __u32 key_size,
15 	       void *values, __u32 value_size, __u32 *count,
16 	       void *invalid_key)
17 {
18 	__u8 key[key_size], next_key[key_size];
19 	__u32 n = 0;
20 	int i, err;
21 
22 	/* First get keys */
23 	__builtin_memcpy(key, invalid_key, key_size);
24 	while (n < *count) {
25 		err = bpf_map_get_next_key(map_fd, key, next_key);
26 		if (err && errno != ENOENT) {
27 			return -1;
28 		} else if (err) {
29 			break;
30 		}
31 		__builtin_memcpy(key, next_key, key_size);
32 		__builtin_memcpy(keys + key_size * n, next_key, key_size);
33 		n++;
34 	}
35 
36 	/* Now read values */
37 	for (i = 0; i < n; i++) {
38 		err = bpf_map_lookup_elem(map_fd, keys + key_size * i,
39 					  values + value_size * i);
40 		if (err)
41 			return -1;
42 	}
43 
44 	*count = n;
45 	return 0;
46 }
47 
48 static int
dump_hash_batch(int map_fd,void * keys,__u32 key_size,void * values,__u32 value_size,__u32 * count)49 dump_hash_batch(int map_fd, void *keys, __u32 key_size,
50 		void *values, __u32 value_size, __u32 *count)
51 {
52 	void *in = NULL, *out;
53 	__u32 n, n_read = 0;
54 	int err = 0;
55 
56 	while (n_read < *count && !err) {
57 		n = *count - n_read;
58 		err = bpf_map_lookup_batch(map_fd, &in, &out,
59 					   keys + n_read * key_size,
60 					   values + n_read * value_size,
61 					   &n, NULL);
62 		if (err && errno != ENOENT) {
63 			return -1;
64 		}
65 		n_read += n;
66 		in = out;
67 	}
68 
69 	*count = n_read;
70 	return 0;
71 }
72 
dump_hash(int map_fd,void * keys,__u32 key_size,void * values,__u32 value_size,__u32 * count,void * invalid_key)73 int dump_hash(int map_fd,
74 	      void *keys, __u32 key_size,
75 	      void *values, __u32 value_size,
76 	      __u32 *count, void *invalid_key)
77 {
78 	int err;
79 
80 	if (!keys || !values || !count || !key_size || !value_size) {
81 		errno = EINVAL;
82 		return -1;
83 	}
84 
85 	if (batch_map_ops) {
86 		err = dump_hash_batch(map_fd, keys, key_size,
87 				      values, value_size, count);
88 		if (err) {
89 			if (errno != EINVAL) {
90 				return -1;
91 
92 				/* assume that batch operations are not
93 				 * supported and try non-batch mode */
94 				batch_map_ops = false;
95 			}
96 		}
97 	}
98 
99 	if (!invalid_key) {
100 		errno = EINVAL;
101 		return -1;
102 	}
103 
104 	return dump_hash_iter(map_fd, keys, key_size,
105 			      values, value_size, count, invalid_key);
106 }
107