Skip to content

Commit

Permalink
Merge branch 'libbpf: deprecate legacy BPF map definitions'
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexei Starovoitov committed Jan 21, 2022
2 parents 1058b6a + 96c8530 commit 1713e33
Show file tree
Hide file tree
Showing 15 changed files with 90 additions and 64 deletions.
32 changes: 14 additions & 18 deletions Documentation/bpf/btf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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:
::
Expand Down
9 changes: 8 additions & 1 deletion tools/bpf/bpftool/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion tools/lib/bpf/bpf_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
8 changes: 8 additions & 0 deletions tools/lib/bpf/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions tools/lib/bpf/libbpf_legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down
4 changes: 2 additions & 2 deletions tools/testing/selftests/bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)

Expand Down
4 changes: 4 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/btf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -4684,6 +4686,8 @@ static void do_test_file(unsigned int test_num)
fprintf(stderr, "OK");

done:
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);

btf__free(btf);
free(func_info);
bpf_object__close(obj);
Expand Down
12 changes: 6 additions & 6 deletions tools/testing/selftests/bpf/progs/freplace_cls_redirect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
24 changes: 12 additions & 12 deletions tools/testing/selftests/bpf/progs/sample_map_ret0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions tools/testing/selftests/bpf/progs/test_btf_haskv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions tools/testing/selftests/bpf/progs/test_btf_newkv.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ 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,
.key_size = sizeof(int),
.value_size = sizeof(long long),
.max_entries = 4,
};
#pragma GCC diagnostic pop

BPF_ANNOTATE_KV_PAIR(btf_map_legacy, int, struct ipv_counts);

Expand Down
12 changes: 6 additions & 6 deletions tools/testing/selftests/bpf/progs/test_btf_nokv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 6 additions & 6 deletions tools/testing/selftests/bpf/progs/test_skb_cgroup_id_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
12 changes: 6 additions & 6 deletions tools/testing/selftests/bpf/progs/test_tc_edt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 1713e33

Please sign in to comment.