@@ -7,6 +7,7 @@
#include <linux/bpf.h>
#include <bpf/libbpf.h>
+#include <bpf/bpf.h>
#include <linux/err.h>
#include "perf.h"
#include "debug.h"
@@ -666,6 +667,69 @@ bpf_map_priv__clear(struct bpf_map *map __maybe_unused,
}
static int
+bpf_map_config_foreach_key(struct bpf_map *map,
+ int (*func)(const char *name,
+ int map_fd,
+ struct bpf_map_def *pdef,
+ struct bpf_map_priv *priv,
+ void *pkey, void *arg),
+ void *arg)
+{
+ unsigned int i;
+ int err, map_fd;
+ const char *name;
+ struct bpf_map_def def;
+ struct bpf_map_priv *priv;
+
+ name = bpf_map__get_name(map);
+
+ err = bpf_map__get_private(map, (void **)&priv);
+ if (err) {
+ pr_debug("ERROR: failed to get private from map %s\n", name);
+ return -EINVAL;
+ }
+ if (!priv) {
+ pr_debug("INFO: nothing to config for map %s\n", name);
+ return 0;
+ }
+
+ err = bpf_map__get_def(map, &def);
+ if (err) {
+ pr_debug("ERROR: failed to get definition from map %s\n", name);
+ return -EINVAL;
+ }
+ map_fd = bpf_map__get_fd(map);
+ if (map_fd < 0) {
+ pr_debug("ERROR: failed to get fd from map %s\n", name);
+ return map_fd;
+ }
+
+ switch (def.type) {
+ case BPF_MAP_TYPE_ARRAY:
+ switch (priv->key.type) {
+ case BPF_MAP_PRIV_KEY_ALL:
+ for (i = 0; i < def.max_entries; i++) {
+ err = (*func)(name, map_fd, &def,
+ priv, &i, arg);
+ if (err) {
+ pr_debug("ERROR: failed to insert value to %s[%u]\n",
+ name, i);
+ return err;
+ }
+ }
+ return 0;
+ default:
+ pr_debug("ERROR: keytype for map '%s' invalid\n", name);
+ return -EINVAL;
+ }
+ default:
+ pr_debug("ERROR: type of '%s' incorrect\n", name);
+ return -EINVAL;
+ }
+}
+
+
+static int
bpf__config_obj_map_array_value(struct bpf_map *map,
struct parse_events_term *term)
{
@@ -799,6 +863,97 @@ int bpf__config_obj(struct bpf_object *obj,
return -ENODEV;
}
+static int
+bpf__apply_config_value_for_key(int map_fd, void *pkey,
+ size_t val_size, u64 val)
+{
+ int err = 0;
+
+ switch (val_size) {
+ case 1: {
+ u8 _val = (u8)(val);
+ err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY);
+ break;
+ }
+ case 2: {
+ u16 _val = (u16)(val);
+ err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY);
+ break;
+ }
+ case 4: {
+ u32 _val = (u32)(val);
+ err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY);
+ break;
+ }
+ case 8: {
+ err = bpf_map_update_elem(map_fd, pkey, &val, BPF_ANY);
+ break;
+ }
+ default:
+ pr_debug("ERROR: internal error: invalid value size\n");
+ return -EINVAL;
+ }
+ if (err && errno)
+ err = -errno;
+ return err;
+}
+
+static int
+bpf__apply_config_map_for_key(const char *name, int map_fd,
+ struct bpf_map_def *pdef __maybe_unused,
+ struct bpf_map_priv *priv,
+ void *pkey, void *arg __maybe_unused)
+{
+ int err;
+
+ switch (priv->value.type) {
+ case BPF_MAP_PRIV_VAL_VALUE:
+ err = bpf__apply_config_value_for_key(map_fd, pkey,
+ pdef->value_size,
+ priv->value.val);
+ break;
+ default:
+ pr_debug("ERROR: unknown value type for '%s'\n", name);
+ err = -EINVAL;
+ }
+ return err;
+}
+
+static int
+bpf__apply_config_map(struct bpf_map *map)
+{
+ return bpf_map_config_foreach_key(map, bpf__apply_config_map_for_key,
+ NULL);
+}
+
+static int
+bpf__apply_config_object(struct bpf_object *obj)
+{
+ struct bpf_map *map;
+ int err;
+
+ bpf_map__for_each(map, obj) {
+ err = bpf__apply_config_map(map);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+int bpf__apply_config(void)
+{
+ struct bpf_object *obj, *tmp;
+ int err;
+
+ bpf_object__for_each_safe(obj, tmp) {
+ err = bpf__apply_config_object(obj);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
#define bpf__strerror_head(err, buf, size) \
char sbuf[STRERR_BUFSIZE], *emsg;\
if (!size)\
@@ -855,3 +1010,11 @@ int bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
bpf__strerror_end(buf, size);
return 0;
}
+
+int bpf__strerror_apply_config(int err, char *buf, size_t size)
+{
+ bpf__strerror_head(err, buf, size);
+ bpf__strerror_entry(EINVAL, "Invalid option for map, add -v to see detail");
+ bpf__strerror_end(buf, size);
+ return 0;
+}
@@ -43,6 +43,8 @@ int bpf__strerror_config_obj(struct bpf_object *obj,
struct parse_events_term *term,
struct perf_evlist *evlist,
int err, char *buf, size_t size);
+int bpf__apply_config(void);
+int bpf__strerror_apply_config(int err, char *buf, size_t size);
#else
static inline struct bpf_object *
bpf__prepare_load(const char *filename __maybe_unused,
@@ -82,6 +84,12 @@ bpf__config_obj(struct bpf_object *obj __maybe_unused,
}
static inline int
+bpf__apply_config(void)
+{
+ return 0;
+}
+
+static inline int
__bpf_strerror(char *buf, size_t size)
{
if (!size)
@@ -117,5 +125,12 @@ bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused,
{
return __bpf_strerror(buf, size);
}
+
+static inline int
+bpf__strerror_apply_config(int err __maybe_unused,
+ char *buf, size_t size)
+{
+ return __bpf_strerror(buf, size);
+}
#endif
#endif