Merge branch 'libbpf: deprecate legacy BPF map definitions'
Andrii Nakryiko says: ==================== Officially deprecate legacy BPF map definitions in libbpf. They've been slated for deprecation for a while in favor of more powerful BTF-defined map definitions and this patch set adds warnings and a way to enforce this in libbpf through LIBBPF_STRICT_MAP_DEFINITIONS strict mode flag. Selftests are fixed up and updated, BPF documentation is updated, bpftool's strict mode usage is adjusted to avoid breaking users unnecessarily. v1->v2: - replace missed bpf_map_def case in Documentation/bpf/btf.rst (Alexei). ==================== Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
commit
1713e33bfd
|
@ -565,18 +565,15 @@ A map can be created with ``btf_fd`` and specified key/value type id.::
|
|||
In libbpf, the map can be defined with extra annotation like below:
|
||||
::
|
||||
|
||||
struct bpf_map_def SEC("maps") btf_map = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(struct ipv_counts),
|
||||
.max_entries = 4,
|
||||
};
|
||||
BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, int);
|
||||
__type(value, struct ipv_counts);
|
||||
__uint(max_entries, 4);
|
||||
} btf_map SEC(".maps");
|
||||
|
||||
Here, the parameters for macro BPF_ANNOTATE_KV_PAIR are map name, key and
|
||||
value types for the map. During ELF parsing, libbpf is able to extract
|
||||
key/value type_id's and assign them to BPF_MAP_CREATE attributes
|
||||
automatically.
|
||||
During ELF parsing, libbpf is able to extract key/value type_id's and assign
|
||||
them to BPF_MAP_CREATE attributes automatically.
|
||||
|
||||
.. _BPF_Prog_Load:
|
||||
|
||||
|
@ -824,13 +821,12 @@ structure has bitfields. For example, for the following map,::
|
|||
___A b1:4;
|
||||
enum A b2:4;
|
||||
};
|
||||
struct bpf_map_def SEC("maps") tmpmap = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(struct tmp_t),
|
||||
.max_entries = 1,
|
||||
};
|
||||
BPF_ANNOTATE_KV_PAIR(tmpmap, int, struct tmp_t);
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, int);
|
||||
__type(value, struct tmp_t);
|
||||
__uint(max_entries, 1);
|
||||
} tmpmap SEC(".maps");
|
||||
|
||||
bpftool is able to pretty print like below:
|
||||
::
|
||||
|
|
|
@ -478,7 +478,14 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (!legacy_libbpf) {
|
||||
ret = libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
|
||||
enum libbpf_strict_mode mode;
|
||||
|
||||
/* Allow legacy map definitions for skeleton generation.
|
||||
* It will still be rejected if users use LIBBPF_STRICT_ALL
|
||||
* mode for loading generated skeleton.
|
||||
*/
|
||||
mode = (__LIBBPF_STRICT_LAST - 1) & ~LIBBPF_STRICT_MAP_DEFINITIONS;
|
||||
ret = libbpf_set_strict_mode(mode);
|
||||
if (ret)
|
||||
p_err("failed to enable libbpf strict mode: %d", ret);
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ struct bpf_map_def {
|
|||
unsigned int value_size;
|
||||
unsigned int max_entries;
|
||||
unsigned int map_flags;
|
||||
};
|
||||
} __attribute__((deprecated("use BTF-defined maps in .maps section")));
|
||||
|
||||
enum libbpf_pin_type {
|
||||
LIBBPF_PIN_NONE,
|
||||
|
|
|
@ -1937,6 +1937,11 @@ static int bpf_object__init_user_maps(struct bpf_object *obj, bool strict)
|
|||
if (obj->efile.maps_shndx < 0)
|
||||
return 0;
|
||||
|
||||
if (libbpf_mode & LIBBPF_STRICT_MAP_DEFINITIONS) {
|
||||
pr_warn("legacy map definitions in SEC(\"maps\") are not supported\n");
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (!symbols)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1999,6 +2004,8 @@ static int bpf_object__init_user_maps(struct bpf_object *obj, bool strict)
|
|||
return -LIBBPF_ERRNO__FORMAT;
|
||||
}
|
||||
|
||||
pr_warn("map '%s' (legacy): legacy map definitions are deprecated, use BTF-defined maps instead\n", map_name);
|
||||
|
||||
if (ELF64_ST_BIND(sym->st_info) == STB_LOCAL) {
|
||||
pr_warn("map '%s' (legacy): static maps are not supported\n", map_name);
|
||||
return -ENOTSUP;
|
||||
|
@ -4190,6 +4197,7 @@ static int bpf_map_find_btf_info(struct bpf_object *obj, struct bpf_map *map)
|
|||
return 0;
|
||||
|
||||
if (!bpf_map__is_internal(map)) {
|
||||
pr_warn("Use of BPF_ANNOTATE_KV_PAIR is deprecated, use BTF-defined maps in .maps section instead\n");
|
||||
ret = btf__get_map_kv_tids(obj->btf, map->name, def->key_size,
|
||||
def->value_size, &key_type_id,
|
||||
&value_type_id);
|
||||
|
|
|
@ -73,6 +73,11 @@ enum libbpf_strict_mode {
|
|||
* operation.
|
||||
*/
|
||||
LIBBPF_STRICT_AUTO_RLIMIT_MEMLOCK = 0x10,
|
||||
/*
|
||||
* Error out on any SEC("maps") map definition, which are deprecated
|
||||
* in favor of BTF-defined map definitions in SEC(".maps").
|
||||
*/
|
||||
LIBBPF_STRICT_MAP_DEFINITIONS = 0x20,
|
||||
|
||||
__LIBBPF_STRICT_LAST,
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ endif
|
|||
|
||||
BPF_GCC ?= $(shell command -v bpf-gcc;)
|
||||
SAN_CFLAGS ?=
|
||||
CFLAGS += -g -O0 -rdynamic -Wall $(GENFLAGS) $(SAN_CFLAGS) \
|
||||
CFLAGS += -g -O0 -rdynamic -Wall -Werror $(GENFLAGS) $(SAN_CFLAGS) \
|
||||
-I$(CURDIR) -I$(INCLUDE_DIR) -I$(GENDIR) -I$(LIBDIR) \
|
||||
-I$(TOOLSINCDIR) -I$(APIDIR) -I$(OUTPUT)
|
||||
LDFLAGS += $(SAN_CFLAGS)
|
||||
|
@ -292,7 +292,7 @@ IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \
|
|||
MENDIAN=$(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian)
|
||||
|
||||
CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG))
|
||||
BPF_CFLAGS = -g -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
|
||||
BPF_CFLAGS = -g -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN) \
|
||||
-I$(INCLUDE_DIR) -I$(CURDIR) -I$(APIDIR) \
|
||||
-I$(abspath $(OUTPUT)/../usr/include)
|
||||
|
||||
|
|
|
@ -4560,6 +4560,8 @@ static void do_test_file(unsigned int test_num)
|
|||
has_btf_ext = btf_ext != NULL;
|
||||
btf_ext__free(btf_ext);
|
||||
|
||||
/* temporary disable LIBBPF_STRICT_MAP_DEFINITIONS to test legacy maps */
|
||||
libbpf_set_strict_mode((__LIBBPF_STRICT_LAST - 1) & ~LIBBPF_STRICT_MAP_DEFINITIONS);
|
||||
obj = bpf_object__open(test->file);
|
||||
err = libbpf_get_error(obj);
|
||||
if (CHECK(err, "obj: %d", err))
|
||||
|
@ -4684,6 +4686,8 @@ skip:
|
|||
fprintf(stderr, "OK");
|
||||
|
||||
done:
|
||||
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
|
||||
|
||||
btf__free(btf);
|
||||
free(func_info);
|
||||
bpf_object__close(obj);
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
struct bpf_map_def SEC("maps") sock_map = {
|
||||
.type = BPF_MAP_TYPE_SOCKMAP,
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(int),
|
||||
.max_entries = 2,
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_SOCKMAP);
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
__uint(max_entries, 2);
|
||||
} sock_map SEC(".maps");
|
||||
|
||||
SEC("freplace/cls_redirect")
|
||||
int freplace_cls_redirect_test(struct __sk_buff *skb)
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
#include <linux/bpf.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
|
||||
struct bpf_map_def SEC("maps") htab = {
|
||||
.type = BPF_MAP_TYPE_HASH,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(long),
|
||||
.max_entries = 2,
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, __u32);
|
||||
__type(value, long);
|
||||
__uint(max_entries, 2);
|
||||
} htab SEC(".maps");
|
||||
|
||||
struct bpf_map_def SEC("maps") array = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(long),
|
||||
.max_entries = 2,
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, __u32);
|
||||
__type(value, long);
|
||||
__uint(max_entries, 2);
|
||||
} array SEC(".maps");
|
||||
|
||||
/* Sample program which should always load for testing control paths. */
|
||||
SEC(".text") int func()
|
||||
|
|
|
@ -9,12 +9,15 @@ struct ipv_counts {
|
|||
unsigned int v6;
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
struct bpf_map_def SEC("maps") btf_map = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(struct ipv_counts),
|
||||
.max_entries = 4,
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ struct ipv_counts {
|
|||
unsigned int v6;
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
/* just to validate we can handle maps in multiple sections */
|
||||
struct bpf_map_def SEC("maps") btf_map_legacy = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
|
@ -16,6 +18,7 @@ struct bpf_map_def SEC("maps") btf_map_legacy = {
|
|||
.value_size = sizeof(long long),
|
||||
.max_entries = 4,
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
BPF_ANNOTATE_KV_PAIR(btf_map_legacy, int, struct ipv_counts);
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ struct ipv_counts {
|
|||
unsigned int v6;
|
||||
};
|
||||
|
||||
struct bpf_map_def SEC("maps") btf_map = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(int),
|
||||
.value_size = sizeof(struct ipv_counts),
|
||||
.max_entries = 4,
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(struct ipv_counts));
|
||||
__uint(max_entries, 4);
|
||||
} btf_map SEC(".maps");
|
||||
|
||||
__attribute__((noinline))
|
||||
int test_long_fname_2(void)
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
|
||||
#define NUM_CGROUP_LEVELS 4
|
||||
|
||||
struct bpf_map_def SEC("maps") cgroup_ids = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(__u64),
|
||||
.max_entries = NUM_CGROUP_LEVELS,
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, __u32);
|
||||
__type(value, __u64);
|
||||
__uint(max_entries, NUM_CGROUP_LEVELS);
|
||||
} cgroup_ids SEC(".maps");
|
||||
|
||||
static __always_inline void log_nth_level(struct __sk_buff *skb, __u32 level)
|
||||
{
|
||||
|
|
|
@ -17,12 +17,12 @@
|
|||
#define THROTTLE_RATE_BPS (5 * 1000 * 1000)
|
||||
|
||||
/* flow_key => last_tstamp timestamp used */
|
||||
struct bpf_map_def SEC("maps") flow_map = {
|
||||
.type = BPF_MAP_TYPE_HASH,
|
||||
.key_size = sizeof(uint32_t),
|
||||
.value_size = sizeof(uint64_t),
|
||||
.max_entries = 1,
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__type(key, uint32_t);
|
||||
__type(value, uint64_t);
|
||||
__uint(max_entries, 1);
|
||||
} flow_map SEC(".maps");
|
||||
|
||||
static inline int throttle_flow(struct __sk_buff *skb)
|
||||
{
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
|
||||
struct bpf_map_def SEC("maps") results = {
|
||||
.type = BPF_MAP_TYPE_ARRAY,
|
||||
.key_size = sizeof(__u32),
|
||||
.value_size = sizeof(__u32),
|
||||
.max_entries = 3,
|
||||
};
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
__uint(max_entries, 3);
|
||||
} results SEC(".maps");
|
||||
|
||||
static __always_inline __s64 gen_syncookie(void *data_end, struct bpf_sock *sk,
|
||||
void *iph, __u32 ip_size,
|
||||
|
|
Loading…
Reference in New Issue