-
Notifications
You must be signed in to change notification settings - Fork 427
Libbpf 1.0 migration guide
Libbpf is moving towards v1.0 release. This document contains a list of planned breaking changes and API deprecations planned for v1.0 release. This page contains a short guide-lines on making sure applications using libbpf can migrate smoothly with least amount of effort and no unintended breakage. Most API deprecations and other behavior changes should have a corresponding short section on this page listing the recommended new API(s) and conventions, compared to pre-1.0 API.
Whenever libbpf is attempting some breaking change, it doesn't go in effect until the official 1.0 release. Instead, libbpf provides a new API:
int libbpf_set_strict_mode(enum libbpf_strict_mode mode);
This API allows to turn on v1.0 behavior for various aspects of libbpf. It accepts a set of flags, defined in enum libbpf_strict_mode
:
enum libbpf_strict_mode {
/* Turn on all supported strict features of libbpf to simulate libbpf
* v1.0 behavior.
* This will be the default behavior in libbpf v1.0.
*/
LIBBPF_STRICT_ALL = 0xffffffff,
/*
* Disable any libbpf 1.0 behaviors. This is the default before libbpf
* v1.0. It won't be supported anymore in v1.0, please update your
* code so that it handles LIBBPF_STRICT_ALL mode before libbpf v1.0.
*/
LIBBPF_STRICT_NONE = 0x00,
/*
* Return NULL pointers on error, not ERR_PTR(err).
* Additionally, libbpf also always sets errno to corresponding Exx
* (positive) error code.
*/
LIBBPF_STRICT_CLEAN_PTRS = 0x01,
/*
* Return actual error codes from low-level APIs directly, not just -1.
* Additionally, libbpf also always sets errno to corresponding Exx
* (positive) error code.
*/
LIBBPF_STRICT_DIRECT_ERRS = 0x02,
};
So to turn on 1.0 behavior of consistently returning errors directly for int
-returning APIs and also start returning NULL pointers on errors for pointer-returning APIs, application should do this before using any other libbpf APIs:
libbpf_set_strict_mode(LIBBPF_STRICT_CLEAN_PTRS | LIBBPF_STRICT_DIRECT_ERRS);
Such approach allows to opt-in into new behaviors once you are sure application's usage of APIs or reliance of legacy libbpf behaviors were fixed.
For brand new users of libbpf or for those who are confident they follow best practices, it's possible to opt-in into all current and future planned changes by passing LIBBPF_STRICT_ALL
:
libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
Most (but not all) libbpf APIs that construct new "objects" (like bpf_object__open_file()
, btf__parse()
, perf_buffer__new()
, etc) typically return a special non-NULL pointer, encoding a specific error code (e.g., -EINVAL
). This is a convention stemming from libbpf's kernel heritage, but is quite surprising for user-space. Libbpf provides libbpf_get_error()
API to check such pointer for error and extract error code, if any. This is the recommended way to do this, instead of relying on kernel definitions of PTR_ERR()
and IS_ERR()
macros:
struct bpf_object *obj;
int err;
obj = bpf_object__open_file(...);
err = libbpf_get_error(obj);
if (err) {
...
}
When LIBBPF_STRICT_CLEAN_PTRS
mode is enabled, libbpf will no longer return such special pointer. Instead NULL is returned, as one would expect. In cases when user would like to extract underlying error code, errno
thread-local variable is set with the exact error code:
struct bpf_object *obj;
int err;
obj = bpf_object__open_file(...);
if (!obj) {
err = -errno;
...
}
Note, libbpf_get_error()
is able to handle both modes and extract correct error code (assuming libbpf_get_error()
is called right after the API that error out without any other function clobbering errno
), so feel free to keep using it. But libbpf_get_error()
is going to be eventually deprecated and removed in libbpf 1.0 release, so eventually you'd need to turn on LIBBPF_STRICT_CLEAN_PTRS
and switch code to NULL checks and errno
(if necessary).
Pre-v1.0, some low-level libbpf APIs, wrapping bpf()
syscalls, would return -1 on error and set errno
with the actual error code returned by kernel. Some APIs might in some situations return the error code directly. So it's a bit of a mess.
With LIBBPF_STRICT_DIRECT_ERRS
enabled, libbpf always sets errno
and always return the actual error code directly. So if your code relies on -1 checks like below, it will become broken:
int err;
err = bpf_create_map(...);
if (err == -1) {
/* wrong -1 catches only -EPERM error */
...
}
Instead, use < 0
comparison:
int err;
err = bpf_create_map(...);
if (err < 0) {
/* err might be -EPERM, but also -EINVAL or whatever other error code */
...
}
High-level APIs (mostly those that are coming from libbpf.h
and btf.h
headers) have always returned error codes directly, so no changes there. But now they, for uniformity, also set errno
with a positive error code, so when returned code is -EINVAL
, errno
will be set to EINVAL
. So this is possible, but discouraged given how easy it is to mis-use errno
thread-local variable:
int fd, err;
fd = bpf_create_map(...);
if (fd < 0) {
err = -errno;
...
}
Some previously supported BPF program SEC()
annotations are deprecated. See the table below for alternatives.
Old SEC() definition | New SEC() definition |
---|---|
SEC("xdp_cpumap") |
SEC("xdp/cpumap") |
SEC("xdp_devmap") |
SEC("xdp/devmap") |
SEC("classifier") |
SEC("tc") |