Skip to content

Commit 5310cfd

Browse files
authored
Merge pull request #42 from olsajiri/tracing
Add tracing examples from @olsajiri
2 parents 50b9bc5 + d822333 commit 5310cfd

22 files changed

Lines changed: 2665 additions & 4 deletions

common/common.mk

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,13 @@ EXTRA_DEPS +=
3838
# BPF-prog kern and userspace shares struct via header file:
3939
KERN_USER_H ?= $(wildcard common_kern_user.h)
4040

41-
CFLAGS ?= -I$(LIBBPF_DIR)/root/usr/include/ -I/usr/include/x86_64-linux-gnu
41+
CFLAGS ?= -I$(LIBBPF_DIR)/root/usr/include/ -g
42+
# Extra include for Ubuntu issue #44
43+
CFLAGS += -I/usr/include/x86_64-linux-gnu
4244
CFLAGS += -I../headers/
4345
LDFLAGS ?= -L$(LIBBPF_DIR)
4446

45-
LIBS = -l:libbpf.a -lelf
47+
LIBS = -l:libbpf.a -lelf $(USER_LIBS)
4648

4749
all: llvm-check $(USER_TARGETS) $(XDP_OBJ) $(COPY_LOADER) $(COPY_STATS)
4850

common/common_defines.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
#ifndef __COMMON_DEFINES_H
22
#define __COMMON_DEFINES_H
33

4+
#include <net/if.h>
5+
#include <linux/types.h>
6+
#include <stdbool.h>
7+
48
struct config {
59
__u32 xdp_flags;
610
int ifindex;

common/common_user_bpf_xdp.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,9 @@ struct bpf_object *load_bpf_and_xdp_attach(struct config *cfg)
179179
return bpf_obj;
180180
}
181181

182+
#define XDP_UNKNOWN XDP_REDIRECT + 1
182183
#ifndef XDP_ACTION_MAX
183-
#define XDP_ACTION_MAX (XDP_REDIRECT + 1)
184+
#define XDP_ACTION_MAX (XDP_UNKNOWN + 1)
184185
#endif
185186

186187
static const char *xdp_action_names[XDP_ACTION_MAX] = {
@@ -189,6 +190,7 @@ static const char *xdp_action_names[XDP_ACTION_MAX] = {
189190
[XDP_PASS] = "XDP_PASS",
190191
[XDP_TX] = "XDP_TX",
191192
[XDP_REDIRECT] = "XDP_REDIRECT",
193+
[XDP_UNKNOWN] = "XDP_UNKNOWN",
192194
};
193195

194196
const char *action2str(__u32 action)

headers/linux/err.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
2+
3+
#ifndef __LINUX_ERR_H
4+
#define __LINUX_ERR_H
5+
6+
#include <linux/types.h>
7+
#include <asm/errno.h>
8+
9+
#define MAX_ERRNO 4095
10+
11+
#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO)
12+
13+
static inline void * ERR_PTR(long error_)
14+
{
15+
return (void *) error_;
16+
}
17+
18+
static inline long PTR_ERR(const void *ptr)
19+
{
20+
return (long) ptr;
21+
}
22+
23+
static inline bool IS_ERR(const void *ptr)
24+
{
25+
return IS_ERR_VALUE((unsigned long)ptr);
26+
}
27+
28+
static inline bool IS_ERR_OR_NULL(const void *ptr)
29+
{
30+
return (!ptr) || IS_ERR_VALUE((unsigned long)ptr);
31+
}
32+
33+
#endif

tracing01-xdp-simple/Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
2+
3+
# Departing from the implicit _user.c scheme
4+
XDP_TARGETS := trace_prog_kern xdp_prog_kern
5+
USER_TARGETS := trace_load_and_stats
6+
7+
LIBBPF_DIR = ../libbpf/src/
8+
COMMON_DIR = ../common/
9+
10+
include $(COMMON_DIR)/common.mk
11+

tracing01-xdp-simple/README.org

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# -*- fill-column: 76; -*-
2+
#+TITLE: Tutorial: Tracing01 - monitor xdp tracepoint
3+
#+OPTIONS: ^:nil
4+
5+
In this lesson we will show how to create and load eBPF program that
6+
hooks on xdp:exception tracepoint and get its values to user space
7+
stats application.
8+
9+
* Table of Contents :TOC:
10+
- [[#using-libbpf][XDP tracepoints]]
11+
- [[#xdp-tracepoints][XDP tracepoints]]
12+
- [[#tracepoint-program-section][Tracepoint program section]]
13+
- [[#tracepoint-arguments][Tracepoint arguments]]
14+
- [[#tracepoint-attaching][Tracepoint attaching]]
15+
- [[#hash-map][HASH map]]
16+
- [[#assignments][Assignments]]
17+
- [[#assignment-1][Assignment 1: Setting up your test lab]]
18+
- [[#assignment-2][Assignment 2: Load tracepoint monitor program]]
19+
20+
21+
* XDP tracepoints
22+
23+
The eBPF programs can be attached also to tracepoints. There are
24+
several tracepoints related to xdp:
25+
26+
#+begin_example sh
27+
ls /sys/kernel/debug/tracing/events/xdp/
28+
xdp_cpumap_enqueue
29+
xdp_cpumap_kthread
30+
xdp_devmap_xmit
31+
xdp_exception
32+
xdp_redirect
33+
xdp_redirect_err
34+
xdp_redirect_map
35+
xdp_redirect_map_err
36+
#+end_example
37+
38+
** Tracepoint program section
39+
40+
The bpf library expects the tracepoint eBPF program to be stored
41+
in a section with following name:
42+
43+
#+begin_example sh
44+
tracepoint/sys/tracepoint
45+
#+end_example
46+
47+
where 'sys' is the tracepoint subsystem and 'tracepoint' is
48+
the tracepoint name.
49+
50+
which can be done with following construct:
51+
52+
#+begin_example sh
53+
SEC("tracepoint/xdp/xdp_exception")
54+
int trace_xdp_exception(struct xdp_exception_ctx *ctx)
55+
#+end_example
56+
57+
** Tracepoint arguments
58+
59+
There's single program pointer argument which points
60+
to the structure, that defines the tracepoint fields.
61+
62+
Like for xdp:xdp_exception tracepoint:
63+
64+
#+begin_example sh
65+
struct xdp_exception_ctx {
66+
__u64 __pad; // First 8 bytes are not accessible by bpf code
67+
__s32 prog_id; // offset:8; size:4; signed:1;
68+
__u32 act; // offset:12; size:4; signed:0;
69+
__s32 ifindex; // offset:16; size:4; signed:1;
70+
};
71+
72+
int trace_xdp_exception(struct xdp_exception_ctx *ctx)
73+
#+end_example
74+
75+
This struct is exported in tracepoint format file:
76+
77+
#+begin_example sh
78+
# cat /sys/kernel/debug/tracing/events/xdp/xdp_exception/format
79+
...
80+
field:unsigned short common_type; offset:0; size:2; signed:0;
81+
field:unsigned char common_flags; offset:2; size:1; signed:0;
82+
field:unsigned char common_preempt_count; offset:3; size:1; signed:0;
83+
field:int common_pid; offset:4; size:4; signed:1;
84+
85+
field:int prog_id; offset:8; size:4; signed:1;
86+
field:u32 act; offset:12; size:4; signed:0;
87+
field:int ifindex; offset:16; size:4; signed:1;
88+
...
89+
#+end_example
90+
91+
** Tracepoint attaching
92+
93+
To load a tracepoint program for this example we use following bpf
94+
library helper function:
95+
96+
#+begin_example sh
97+
bpf_prog_load(cfg->filename, BPF_PROG_TYPE_TRACEPOINT, &obj, &bpf_fd))
98+
#+end_example
99+
100+
It loads all the programs from the object together with maps and
101+
returns file descriptor of the first one.
102+
103+
To attach the program to the tracepoint we need to create a tracepoint
104+
perf event and attach the eBPF program to it, using its file descriptor
105+
via PERF_EVENT_IOC_SET_BPF ioctl call:
106+
107+
#+begin_example sh
108+
err = ioctl(fd, PERF_EVENT_IOC_SET_BPF, bpf_fd);
109+
#+end_example
110+
111+
Please check trace_load_and_stats.c load_bpf_and_trace_attach function
112+
for all the details.
113+
114+
* HASH map
115+
116+
This example is using PERCPU HASH map, that stores number of aborted
117+
packets for interface
118+
#+begin_example sh
119+
struct bpf_map_def SEC("maps") xdp_stats_map = {
120+
.type = BPF_MAP_TYPE_PERCPU_HASH,
121+
.key_size = sizeof(__s32),
122+
.value_size = sizeof(__u64),
123+
.max_entries = 10,
124+
};
125+
#+end_example
126+
127+
The interface is similar to the ARRAY map except that we need to specifically
128+
create new element in the hash if it does not exist:
129+
130+
#+begin_example sh
131+
/* Lookup in kernel BPF-side returns pointer to actual data. */
132+
valp = bpf_map_lookup_elem(&xdp_stats_map, &key);
133+
134+
/* If there's no record for interface, we need to create one,
135+
* with number of packets == 1
136+
*/
137+
if (!valp) {
138+
__u64 one = 1;
139+
return bpf_map_update_elem(&xdp_stats_map, &key, &one, 0) ? 1 : 0;
140+
}
141+
142+
(*valp)++;
143+
#+end_example
144+
145+
Please check trace_prog_kern.c for the full code.
146+
147+
* Assignments
148+
149+
** Assignment 1: Setting up your test lab
150+
151+
In this lesson we will use the setup of the previous lesson:
152+
Basic02 - loading a program by name [[https://github.com/xdp-project/xdp-tutorial/tree/master/basic02-prog-by-name#assignment-2-add-xdp_abort-program]]
153+
154+
and load XDP program from xdp_prog_kern.o that will abort every
155+
incoming packet:
156+
157+
#+begin_example sh
158+
SEC("xdp_abort")
159+
int xdp_drop_func(struct xdp_md *ctx)
160+
{
161+
return XDP_ABORTED;
162+
}
163+
#+end_example
164+
165+
with xdp_loader from previous lessson:
166+
Assignment 2: Add xdp_abort program [[https://github.com/xdp-project/xdp-tutorial/tree/master/basic02-prog-by-name#assignment-2-add-xdp_abort-program]]
167+
168+
Setup the environment:
169+
170+
#+begin_example sh
171+
$ sudo ../testenv/testenv.sh setup --name veth-basic02
172+
#+end_example
173+
174+
Load the XDP program, tak produces aborted packets:
175+
176+
#+begin_example sh
177+
$ sudo ../basic02-prog-by-name/xdp_loader --dev veth-basic02 --force --progsec xdp_abort
178+
#+end_example
179+
180+
and make some packets:
181+
182+
#+begin_example sh
183+
$ sudo ../testenv/testenv.sh enter --name veth-basic02
184+
# ping fc00:dead:cafe:1::1
185+
PING fc00:dead:cafe:1::1(fc00:dead:cafe:1::1) 56 data bytes
186+
#+end_example
187+
188+
** Assignment 2: Load tracepoint monitor program
189+
190+
Now when you run the trace_load_and_stats application it will
191+
load and attach the tracepoint eBPF program and display number
192+
of aborted packets per interface:
193+
194+
#+begin_example
195+
# ./trace_load_and_stats
196+
Success: Loaded BPF-object(trace_prog_kern.o)
197+
198+
Collecting stats from BPF map
199+
- BPF map (bpf_map_type:1) id:46 name:xdp_stats_map key_size:4 value_size:4 max_entries:10
200+
201+
veth-basic02 (2)
202+
veth-basic02 (4)
203+
veth-basic02 (6)
204+
...
205+
#+end_example

0 commit comments

Comments
 (0)