18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci#include "util/bpf_map.h"
48c2ecf20Sopenharmony_ci#include <bpf/bpf.h>
58c2ecf20Sopenharmony_ci#include <bpf/libbpf.h>
68c2ecf20Sopenharmony_ci#include <linux/err.h>
78c2ecf20Sopenharmony_ci#include <linux/kernel.h>
88c2ecf20Sopenharmony_ci#include <stdbool.h>
98c2ecf20Sopenharmony_ci#include <stdlib.h>
108c2ecf20Sopenharmony_ci#include <unistd.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_cistatic bool bpf_map_def__is_per_cpu(const struct bpf_map_def *def)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	return def->type == BPF_MAP_TYPE_PERCPU_HASH ||
158c2ecf20Sopenharmony_ci	       def->type == BPF_MAP_TYPE_PERCPU_ARRAY ||
168c2ecf20Sopenharmony_ci	       def->type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
178c2ecf20Sopenharmony_ci	       def->type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE;
188c2ecf20Sopenharmony_ci}
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic void *bpf_map_def__alloc_value(const struct bpf_map_def *def)
218c2ecf20Sopenharmony_ci{
228c2ecf20Sopenharmony_ci	if (bpf_map_def__is_per_cpu(def))
238c2ecf20Sopenharmony_ci		return malloc(round_up(def->value_size, 8) * sysconf(_SC_NPROCESSORS_CONF));
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	return malloc(def->value_size);
268c2ecf20Sopenharmony_ci}
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciint bpf_map__fprintf(struct bpf_map *map, FILE *fp)
298c2ecf20Sopenharmony_ci{
308c2ecf20Sopenharmony_ci	const struct bpf_map_def *def = bpf_map__def(map);
318c2ecf20Sopenharmony_ci	void *prev_key = NULL, *key, *value;
328c2ecf20Sopenharmony_ci	int fd = bpf_map__fd(map), err;
338c2ecf20Sopenharmony_ci	int printed = 0;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	if (fd < 0)
368c2ecf20Sopenharmony_ci		return fd;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	if (IS_ERR(def))
398c2ecf20Sopenharmony_ci		return PTR_ERR(def);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	err = -ENOMEM;
428c2ecf20Sopenharmony_ci	key = malloc(def->key_size);
438c2ecf20Sopenharmony_ci	if (key == NULL)
448c2ecf20Sopenharmony_ci		goto out;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	value = bpf_map_def__alloc_value(def);
478c2ecf20Sopenharmony_ci	if (value == NULL)
488c2ecf20Sopenharmony_ci		goto out_free_key;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	while ((err = bpf_map_get_next_key(fd, prev_key, key) == 0)) {
518c2ecf20Sopenharmony_ci		int intkey = *(int *)key;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci		if (!bpf_map_lookup_elem(fd, key, value)) {
548c2ecf20Sopenharmony_ci			bool boolval = *(bool *)value;
558c2ecf20Sopenharmony_ci			if (boolval)
568c2ecf20Sopenharmony_ci				printed += fprintf(fp, "[%d] = %d,\n", intkey, boolval);
578c2ecf20Sopenharmony_ci		} else {
588c2ecf20Sopenharmony_ci			printed += fprintf(fp, "[%d] = ERROR,\n", intkey);
598c2ecf20Sopenharmony_ci		}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci		prev_key = key;
628c2ecf20Sopenharmony_ci	}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	if (err == ENOENT)
658c2ecf20Sopenharmony_ci		err = printed;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	free(value);
688c2ecf20Sopenharmony_ciout_free_key:
698c2ecf20Sopenharmony_ci	free(key);
708c2ecf20Sopenharmony_ciout:
718c2ecf20Sopenharmony_ci	return err;
728c2ecf20Sopenharmony_ci}
73