|
2 | 2 | # BPF Compiler Collection (BCC) |
3 | 3 |
|
4 | 4 | BCC is a toolkit for creating efficient kernel tracing and manipulation |
5 | | -programs, and includes several useful tools and examples. It makes use of eBPF |
6 | | -(Extended Berkeley Packet Filters), a new feature that was first added to |
7 | | -Linux 3.15. Much of what BCC uses requires Linux 4.1 and above. |
| 5 | +programs, and includes several useful tools and examples. It makes use of |
| 6 | +extended BPF (Berkeley Packet Filters), formally known as eBPF, a new feature |
| 7 | +that was first added to Linux 3.15. Much of what BCC uses requires Linux 4.1 |
| 8 | +and above. |
8 | 9 |
|
9 | 10 | eBPF was [described by](https://lkml.org/lkml/2015/4/14/232) Ingo Molnár as: |
10 | 11 |
|
11 | 12 | > One of the more interesting features in this cycle is the ability to attach eBPF programs (user-defined, sandboxed bytecode executed by the kernel) to kprobes. This allows user-defined instrumentation on a live kernel image that can never crash, hang or interfere with the kernel negatively. |
12 | 13 |
|
13 | | -BCC makes eBPF programs easier to write, with kernel instrumentation in C |
14 | | -and a front-end in Python. It is suited for many tasks, including performance |
15 | | -analysis and network traffic control. |
| 14 | +BCC makes BPF programs easier to write, with kernel instrumentation in C |
| 15 | +(and includes a C wrapper around LLVM), and front-ends in Python and lua. |
| 16 | +It is suited for many tasks, including performance analysis and network |
| 17 | +traffic control. |
16 | 18 |
|
17 | 19 | ## Screenshot |
18 | 20 |
|
@@ -170,46 +172,10 @@ The features of this toolkit include: |
170 | 172 | In the future, more bindings besides python will likely be supported. Feel free |
171 | 173 | to add support for the language of your choice and send a pull request! |
172 | 174 |
|
173 | | -## Tutorial |
| 175 | +## Tutorials |
174 | 176 |
|
175 | | -The BCC toolchain is currently composed of two parts: a C wrapper around LLVM, |
176 | | -and a Python API to interact with the running program. Later, we will go into |
177 | | -more detail of how this all works. |
178 | | - |
179 | | -### Hello, World |
180 | | - |
181 | | -First, we should include the BPF class from the bpf module: |
182 | | -```python |
183 | | -from bcc import BPF |
184 | | -``` |
185 | | - |
186 | | -Since the C code is so short, we will embed it inside the python script. |
187 | | - |
188 | | -The BPF program always takes at least one argument, which is a pointer to the |
189 | | -context for this type of program. Different program types have different calling |
190 | | -conventions, but for this one we don't care so `void *` is fine. |
191 | | -```python |
192 | | -BPF(text='int kprobe__sys_clone(void *ctx) { bpf_trace_printk("Hello, World!\\n"); return 0; }').trace_print() |
193 | | -``` |
194 | | - |
195 | | -For this example, we will call the program every time `fork()` is called by a |
196 | | -userspace process. Underneath the hood, fork translates to the `clone` syscall. |
197 | | -BCC recognizes prefix `kprobe__`, and will auto attach our program to the kernel symbol `sys_clone`. |
198 | | - |
199 | | -The python process will then print the trace printk circular buffer until ctrl-c |
200 | | -is pressed. The BPF program is removed from the kernel when the userspace |
201 | | -process that loaded it closes the fd (or exits). |
202 | | - |
203 | | -Output: |
204 | | -``` |
205 | | -bcc/examples$ sudo python hello_world.py |
206 | | - python-7282 [002] d... 3757.488508: : Hello, World! |
207 | | -``` |
208 | | - |
209 | | -For an explanation of the meaning of the printed fields, see the trace_pipe |
210 | | -section of the [kernel ftrace doc](https://www.kernel.org/doc/Documentation/trace/ftrace.txt). |
211 | | - |
212 | | -[Source code listing](examples/hello_world.py) |
| 177 | +- [docs/tutorial.md](docs/tutorial.md): Using bcc tools to solve performance, troubleshooting, and networking issues. |
| 178 | +- [docs/tutorial_bcc_python_developer.md](docs/tutorial_bcc_python_developer.md): Developing new bcc programs using the Python interface. |
213 | 179 |
|
214 | 180 | ### Networking |
215 | 181 |
|
@@ -222,75 +188,6 @@ multiple granularities. See the code [here](examples/networking/tunnel_monitor). |
222 | 188 |
|
223 | 189 | [](https://youtu.be/yYy3Cwce02k) |
224 | 190 |
|
225 | | -### Tracing |
226 | | - |
227 | | -Here is a slightly more complex tracing example than Hello World. This program |
228 | | -will be invoked for every task change in the kernel, and record in a BPF map |
229 | | -the new and old pids. |
230 | | - |
231 | | -The C program below introduces two new concepts. |
232 | | -The first is the macro `BPF_TABLE`. This defines a table (type="hash"), with key |
233 | | -type `key_t` and leaf type `u64` (a single counter). The table name is `stats`, |
234 | | -containing 1024 entries maximum. One can `lookup`, `lookup_or_init`, `update`, |
235 | | -and `delete` entries from the table. |
236 | | -The second concept is the prev argument. This argument is treated specially by |
237 | | -the BCC frontend, such that accesses to this variable are read from the saved |
238 | | -context that is passed by the kprobe infrastructure. The prototype of the args |
239 | | -starting from position 1 should match the prototype of the kernel function being |
240 | | -kprobed. If done so, the program will have seamless access to the function |
241 | | -parameters. |
242 | | -```c |
243 | | -#include <uapi/linux/ptrace.h> |
244 | | -#include <linux/sched.h> |
245 | | - |
246 | | -struct key_t { |
247 | | - u32 prev_pid; |
248 | | - u32 curr_pid; |
249 | | -}; |
250 | | -// map_type, key_type, leaf_type, table_name, num_entry |
251 | | -BPF_TABLE("hash", struct key_t, u64, stats, 1024); |
252 | | -// attach to finish_task_switch in kernel/sched/core.c, which has the following |
253 | | -// prototype: |
254 | | -// struct rq *finish_task_switch(struct task_struct *prev) |
255 | | -int count_sched(struct pt_regs *ctx, struct task_struct *prev) { |
256 | | - struct key_t key = {}; |
257 | | - u64 zero = 0, *val; |
258 | | - |
259 | | - key.curr_pid = bpf_get_current_pid_tgid(); |
260 | | - key.prev_pid = prev->pid; |
261 | | - |
262 | | - val = stats.lookup_or_init(&key, &zero); |
263 | | - (*val)++; |
264 | | - return 0; |
265 | | -} |
266 | | -``` |
267 | | -[Source code listing](examples/tracing/task_switch.c) |
268 | | -
|
269 | | -The userspace component loads the file shown above, and attaches it to the |
270 | | -`finish_task_switch` kernel function. |
271 | | -The [] operator of the BPF object gives access to each BPF_TABLE in the |
272 | | -program, allowing pass-through access to the values residing in the kernel. Use |
273 | | -the object as you would any other python dict object: read, update, and deletes |
274 | | -are all allowed. |
275 | | -```python |
276 | | -from bcc import BPF |
277 | | -from time import sleep |
278 | | -
|
279 | | -b = BPF(src_file="task_switch.c") |
280 | | -b.attach_kprobe(event="finish_task_switch", fn_name="count_sched") |
281 | | -
|
282 | | -# generate many schedule events |
283 | | -for i in range(0, 100): sleep(0.01) |
284 | | -
|
285 | | -for k, v in b["stats"].items(): |
286 | | - print("task_switch[%5d->%5d]=%u" % (k.prev_pid, k.curr_pid, v.value)) |
287 | | -``` |
288 | | -[Source code listing](examples/tracing/task_switch.py) |
289 | | - |
290 | | -## Getting started |
291 | | - |
292 | | -See [INSTALL.md](INSTALL.md) for installation steps on your platform. |
293 | | - |
294 | 191 | ## Contributing |
295 | 192 |
|
296 | 193 | Already pumped up to commit some code? Here are some resources to join the |
|