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