in bpf/xdp_sample_user.c [381:447]
static int map_collect_percpu_devmap(int map_fd, struct stats_record *rec)
{
unsigned int nr_cpus = bpf_num_possible_cpus();
__u32 batch, count = 32;
struct datarec *values;
bool init = false;
__u64 *keys;
int i, ret;
keys = calloc(count, sizeof(__u64));
if (!keys)
return -ENOMEM;
values = calloc(count * nr_cpus, sizeof(struct datarec));
if (!values) {
free(keys);
return -ENOMEM;
}
for (;;) {
bool exit = false;
ret = bpf_map_lookup_batch(map_fd, init ? &batch : NULL, &batch,
keys, values, &count, NULL);
if (ret < 0 && errno != ENOENT)
break;
if (errno == ENOENT)
exit = true;
init = true;
for (i = 0; i < count; i++) {
struct map_entry *e, *x = NULL;
__u64 pair = keys[i];
struct datarec *arr;
arr = &values[i * nr_cpus];
hash_for_each_possible(rec->xmit_map, e, node, pair) {
if (e->pair == pair) {
x = e;
break;
}
}
if (!x) {
x = calloc(1, sizeof(*x));
if (!x)
goto cleanup;
if (map_entry_init(x, pair) < 0) {
free(x);
goto cleanup;
}
hash_add(rec->xmit_map, &x->node, pair);
}
map_collect_percpu(arr, &x->val);
}
if (exit)
break;
count = 32;
}
free(values);
free(keys);
return 0;
cleanup:
free(values);
free(keys);
return -ENOMEM;
}