You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The assignments in [[file:../basic03-map-counter][basic03]] have been "solved" or implemented in this basic04
34
35
lesson. Thus, this functions as the reference solution for basic03.
35
36
36
-
* Lessons
37
+
* What you will learn in this lesson
37
38
38
-
** Lesson#1: bpf-syscall wrappers
39
+
** bpfsyscall wrappers
39
40
40
-
When splitting up the [[file:../basic03-map-counter/xdp_load_and_stats.c][xdp_load_and_stats.c]] program, into [[file:xdp_loader.c]]
41
-
and [[file:xdp_stats.c]], notice that xdp_stats.c no-longer =#include
42
-
<bpf/libbpf.h>=. This is because xdp_stats doesn't use any of the advanced
43
-
libbpf "object" related functions, it only use the basis bpf-syscall
41
+
When splitting up the [[file:../basic03-map-counter/xdp_load_and_stats.c][xdp_load_and_stats.c]] program into [[file:xdp_loader.c]]
42
+
and [[file:xdp_stats.c]], notice that xdp_stats.c nolonger includes
43
+
=#<bpf/libbpf.h>=. This is because xdp_stats doesn't use any of the advanced
44
+
libbpf "object" related functions, it only uses the basis bpfsyscall
44
45
wrappers, which libbpf also provides.
45
46
46
-
The bpf-syscall wrappers are provided by libbpf via =#include <bpf/bpf.h>=,
47
-
which for this build-setup gets installed in =../libbpf/src/root/usr/include/bpf/bpf.h=
48
-
(link to source [[https://github.com/libbpf/libbpf/blob/master/src/bpf.h][bpf.h]] in libbpf-github repo).
47
+
The bpf syscall wrappers are provided by libbpf via the =#<bpf/bpf.h>=
48
+
include file, which for this tutorial setup lives in
49
+
=../libbpf/src/root/usr/include/bpf/bpf.h= (but see also the [[https://github.com/libbpf/libbpf/blob/master/src/bpf.h][source bpf.h in
50
+
the libbpf github repository]]).
49
51
50
-
The point there is that libbpf keep the low-level bpf-syscall wrappers in
51
-
separate files [[https://github.com/libbpf/libbpf/blob/master/src/bpf.h][bpf.h]] and [[https://github.com/libbpf/libbpf/blob/master/src/bpf.c][bpf.c]]. We could create a smaller binary by not
52
-
linking with libbpf.a, but for ease of use, the proper library is used.
52
+
The point here is that libbpf keeps the low-level bpf-syscall wrappers in
53
+
separate files [[https://github.com/libbpf/libbpf/blob/master/src/bpf.h][bpf.h]] and [[https://github.com/libbpf/libbpf/blob/master/src/bpf.c][bpf.c]]. Thus, we could shrink the size of our binary
54
+
by not linking with libbpf.a. However, for ease of use we just link
55
+
everything with the full library in this tutorial.
53
56
54
-
** Lesson#2: mount BPF file-system
57
+
** Mounting the BPF filesystem
55
58
56
-
Pinning BPF-map means creating files for-each map under a special mount
57
-
point =/sys/fs/bpf/=. This mount point use a "BPF file-system" type. The
58
-
pinning will fail of this is not mounted under =/sys/fs/bpf/=.
59
+
The mechanism used for sharing BPF maps between programs is called
60
+
/pinning/. What this means is that we create a file for each map under a
61
+
special file system mounted at =/sys/fs/bpf/=. If this file system is not
62
+
mounted, our attempts to pin BPF objects will fail, so we need to make sure
63
+
it is mounted.
59
64
60
65
The needed mount command is:
61
66
#+begin_example
@@ -67,33 +72,34 @@ mounted without noticing. As both iproute2 'ip' and our [[file:../testenv][teste
67
72
automatically mount it to the default location under =/sys/fs/bpf/=.
68
73
If not, use the above command to mount it.
69
74
70
-
** Lesson#3: gotchas with pinned maps
75
+
** Gotchas with pinned maps
71
76
72
77
Pinning all maps in a =bpf_object= using libbpf is easily done with:
73
-
=bpf_object__pin_maps(bpf_object, pin_dir)=.
74
-
75
-
To avoid filename collisions, when loading several XDP program on different
76
-
interfaces, the maps are export/pinned under a sub-directory with the
77
-
interface name, that was specified via =--dev=. The libbpf
78
-
=bpf_object__pin_maps()= call even handle creating this sub-directory (via
79
-
mkdir(3)).
80
-
81
-
Open [[file:xdp_loader.c]] and look at our function =pin_maps_in_bpf_object()=,
82
-
and you will see that due to corner-case it is slightly more complicated.
83
-
E.g. need to handle cleanup of previous XDP progs that not have cleaned up
84
-
their maps, which we choose to do via =bpf_object__unpin_maps()=. If this is
85
-
the first usage, then we should not try to "unpin maps" as that will fail.
86
-
87
-
We currently don't handle the corner case, where our BPF-prog get extended
88
-
with a new-map, and then want to replace an existing BPF-prog that doesn't
89
-
contain this new-map, which will result in =bpf_object__unpin_maps()= not
90
-
finding the new-map to unlink, and then fails.
91
-
92
-
** Lesson#4: Deleting maps on XDP-reload
93
-
94
-
When reloading the XDP BPF-prog via our =xdp_loader=, then the existing
95
-
pinned maps are not reused. This differs from iproute2 tool BPF-loader (=ip=
96
-
and =tc= commands), which will reuse the existing pinned maps, rather than
78
+
=bpf_object__pin_maps(bpf_object, pin_dir)=, which we use in =xdp_loader=.
79
+
80
+
To avoid filename collisions, we create a subdirectory named after the
81
+
interface that we are loading the BPF program onto. The libbpf
82
+
=bpf_object__pin_maps()= call even handles creating this subdirectory if it
83
+
doesn't exist.
84
+
85
+
However, if you open [[file:xdp_loader.c]] and look at our function
86
+
=pin_maps_in_bpf_object()=, you will see that due to corner cases things are
87
+
slightly more complicated. E.g., we also need to handle cleanup of previous
88
+
XDP programs that not have cleaned up their maps, which we choose to do via
89
+
=bpf_object__unpin_maps()=. If this is the first usage, then we should not
90
+
try to "unpin maps" as that will fail.
91
+
92
+
There is one corner case that we currently don't handle, namely the case
93
+
where our BPF-prog get extended with a new map, and is loaded as a
94
+
replacement for an existing BPF progam that doesn't contain this new map. In
95
+
this case, =bpf_object__unpin_maps()= won't finding the new map to unlink,
96
+
and therefore fail in its operation.
97
+
98
+
** Deleting maps on XDP reload
99
+
100
+
When reloading the XDP BPF program via our =xdp_loader=, the existing pinned
101
+
maps are not reused. This differs from iproute2 tool BPF-loader (=ip= and
102
+
=tc= commands), which will reuse the existing pinned maps, rather than
97
103
creating new maps.
98
104
99
105
This is a design choice, mostly because libbpf doesn't have easy support for
@@ -103,15 +109,15 @@ applications it could be a problem that the counters reset to zero for the
103
109
different stats tools. Even for our split =xdp_stats= program it is
104
110
annoying, as you must remember to restart the =xdp_stats= tool, after
105
111
reloading via =xdp_loader=, else it will be watching the wrong FD.
106
-
(See [[#assignment1-xdp_statsc-reload-map-file-descriptor][Assignment#1]] for workaround)
112
+
(See [[#assignment1-xdp_statsc-reload-map-file-descriptor][Assignment1]] for workaround)
107
113
108
-
*** Lesson#4.1: libbpf reuse map
114
+
*** Reusing maps with libbpf
109
115
110
-
The libbpf library can *reuse and replace* a map with an existing map
111
-
file-descriptor, via the libbpf API call: =bpf_map__reuse_fd()=. But you
112
-
cannot use =bpf_prog_load()= any-longer, instead you have to open-code it,
113
-
as you need a step in-between =bpf_object__open()= and =bpf_object__load=.
114
-
The basic steps needed looks like:
116
+
The libbpf library can *reuse and replace* a map with an existing map file
117
+
descriptor, via the libbpf API call: =bpf_map__reuse_fd()=. But you cannot
118
+
use =bpf_prog_load()= for this; instead you have to code it yourself, as you
119
+
need a step in-between =bpf_object__open()= and =bpf_object__load=. The
120
+
basic steps needed looks like:
115
121
116
122
#+begin_src C
117
123
int pinned_map_fd = bpf_obj_get("/sys/fs/bpf/veth0/xdp_stats_map");
@@ -121,29 +127,30 @@ The basic steps needed looks like:
121
127
bpf_object__load(obj);
122
128
#+end_src
123
129
124
-
(Hint: see [[#assignment2-xdp_loaderc-reuse-pinned-map][Assignment#2]])
130
+
(Hint: see [[#assignment2-xdp_loaderc-reuse-pinned-map][Assignment2]])
0 commit comments