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
Copy file name to clipboardexpand all lines: src/43-kfuncs/README_en.md
+122-55
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
Have you ever felt constrained by eBPF's capabilities? Maybe you've run into situations where the existing eBPF features just aren't enough to accomplish your goals. Perhaps you need deeper interactions with the kernel, or you're facing performance issues that the standard eBPF runtime can't solve. If you've ever wished for more flexibility and power in your eBPF programs, this tutorial is for you.
4
4
5
-
## Introduction: Breaking Free from eBPF Runtime Limitations with kfuncs
5
+
## Introduction: Adding a `strstr` kfunc to Break Free from eBPF Runtime Limitations
6
6
7
7
**eBPF (extended Berkeley Packet Filter)** has revolutionized Linux system programming by allowing developers to run sandboxed programs inside the kernel. It's a game-changer for networking, security, and observability, enabling powerful functionalities without the need to modify kernel source code or load traditional kernel modules.
8
8
@@ -20,11 +20,13 @@ Enter **kfuncs (BPF Kernel Functions)**. By defining your own kfuncs within kern
20
20
-**Customize Behavior:** Tailor kernel interactions to fit your specific needs.
21
21
-**Boost Performance:** Optimize critical paths by executing custom code directly in the kernel context.
22
22
23
+
**In this tutorial, we'll specifically add a `strstr` kfunc.** While implementing a string search directly in eBPF is challenging due to verifier restrictions, defining it as a kfunc allows us to bypass these limitations and perform more complex operations safely and efficiently.
24
+
23
25
Best of all, you achieve this without modifying the core kernel, keeping your system stable and your code safe.
24
26
25
27
In this tutorial, we'll show you how to define custom kfuncs to fill any gaps in eBPF's capabilities. We'll walk through creating a kernel module that introduces new kfuncs and demonstrate how to use them in your eBPF programs. Whether you're looking to overcome performance bottlenecks or need features the eBPF runtime doesn't offer, custom kfuncs can unlock new possibilities for your projects.
@@ -40,7 +42,7 @@ In this tutorial, we'll show you how to define custom kfuncs to fill any gaps in
40
42
41
43
kfuncs serve as bridges between eBPF programs and deeper kernel functionalities. They allow eBPF programs to perform more intricate operations by either exposing existing kernel functions or introducing new wrappers specifically designed for eBPF interactions. This integration facilitates deeper kernel interactions while ensuring that eBPF programs remain safe and maintainable.
42
44
43
-
It's important to note that the Linux kernel already includes a plethora of kfuncs. These built-in kfuncs cover a wide range of functionalities, allowing most developers to accomplish their tasks without the need to define new ones. However, in cases where the existing kfuncs do not meet specific requirements, defining custom kfuncs becomes necessary. This tutorial demonstrates how to define new kfuncs to fill any gaps, ensuring that your eBPF programs can leverage the exact functionality you need. eBPF can also be extended to userspace. In the userspace eBPF runtime [bpftime](https://github.com/eunomia-bpf/bpftime), we are also implementing ufuncs, which are similar to kfuncs but extending userspace applications.
45
+
It's important to note that the Linux kernel already includes a plethora of kfuncs. These built-in kfuncs cover a wide range of functionalities, allowing most developers to accomplish their tasks without the need to define new ones. However, in cases where the existing kfuncs do not meet specific requirements, defining custom kfuncs becomes necessary. This tutorial demonstrates how to define new kfuncs to fill any gaps, ensuring that your eBPF programs can leverage the exact functionality you need. eBPF can also be extended to userspace. In the userspace eBPF runtime [bpftime](https://github.com/eunomia-bpf/bpftime), we are also implementing ufuncs, which are similar to kfuncs but extend userspace applications.
44
46
45
47
## Overview of kfuncs and Their Evolution
46
48
@@ -62,83 +64,112 @@ To harness the power of kfuncs, you'll need to define them within a kernel modul
62
64
63
65
### Writing the Kernel Module
64
66
65
-
Let's start by creating a simple kernel module that defines a kfunc. This kfunc will perform a basic arithmetic operation, serving as a foundation for understanding the mechanics.
67
+
Let's start by creating a simple kernel module that defines a `strstr`kfunc. This kfunc will perform a substring search operation, serving as a foundation for understanding the mechanics.
66
68
67
69
#### **File: `hello.c`**
68
70
69
71
```c
70
-
#include<linux/init.h>// Macros for module initialization
71
-
#include<linux/module.h>// Core header for loading modules
72
-
#include<linux/kernel.h>// Kernel logging macros
72
+
#include<linux/init.h>// Macros for module initialization
73
+
#include<linux/module.h>// Core header for loading modules
74
+
#include<linux/kernel.h>// Kernel logging macros
73
75
#include<linux/bpf.h>
74
76
#include<linux/btf.h>
75
77
#include<linux/btf_ids.h>
76
78
77
-
// Declare the kfunc
78
-
__bpf_kfunc u64 bpf_kfunc_call_test(u32 a, u64 b, u32 c, u64 d);
- **Declaring the kfunc:** The `__bpf_kfunc` macro declares a function that eBPF programs can invoke. Here, `bpf_kfunc_call_test` takes four parameters (`a`, `b`, `c`, `d`) and returns their sum.
168
+
- **Declaring the kfunc:** The `__bpf_kfunc` macro declares a function that eBPF programs can invoke. Here, `bpf_strstr` performs a substring search within a given string.
138
169
139
170
- **BTF Definitions:** The `__bpf_kfunc_start_defs` and `__bpf_kfunc_end_defs` macros demarcate the beginning and end of kfunc definitions. The `BTF_KFUNCS_START` and related macros assist in registering the kfuncs with the BPF Type Format (BTF).
140
171
141
-
- **Module Initialization:** The `hello_init` function registers the kfunc ID set, making `bpf_kfunc_call_test` available to eBPF programs of type `BPF_PROG_TYPE_KPROBE`.
172
+
- **Module Initialization:** The `hello_init` function registers the kfunc ID set, making `bpf_strstr` available to eBPF programs of type `BPF_PROG_TYPE_KPROBE`.
142
173
143
174
- **Module Cleanup:** The `hello_exit` function ensures that the kfunc ID set is unregistered upon module removal, maintaining system cleanliness.
144
175
@@ -258,15 +289,15 @@ Skipping BTF generation for /root/bpf-developer-tutorial/src/43-kfuncs/module/he
258
289
259
290
This command copies the `vmlinux` file to the appropriate build directory, enabling successful BTF generation.
260
291
261
-
The complete code for this tutorial can be found in the link <https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/43-kfuncs> on GitHub. This is tested on Linux kernel version 6.11, and some modifications may be required for lower versions, referring to `compact.h`.
292
+
The complete code for this tutorial can be found in the [bpf-developer-tutorial repository](https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/43-kfuncs) on GitHub. This is tested on Linux kernel version 6.11, and some modifications may be required for lower versions, referring to `compact.h`.
262
293
263
294
## Utilizing Your Custom kfunc in an eBPF Program
264
295
265
-
With the kernel module defining your custom kfunc in place, the next step is to create an eBPF program that leverages this function. This interaction showcases the enhanced capabilities introduced by kfuncs.
296
+
With the kernel module defining your custom `strstr`kfunc in place, the next step is to create an eBPF program that leverages this function. This interaction showcases the enhanced capabilities introduced by kfuncs.
266
297
267
298
### Writing the eBPF Program
268
299
269
-
Create an eBPF program that attaches to the `do_unlinkat` kernel function and uses the custom `bpf_kfunc_call_test` kfunc.
300
+
Create an eBPF program that attaches to the `do_unlinkat` kernel function and uses the custom `bpf_strstr` kfunc.
270
301
271
302
#### **File: `kfunc.c`**
272
303
@@ -278,33 +309,44 @@ Create an eBPF program that attaches to the `do_unlinkat` kernel function and us
278
309
#include<bpf/bpf_tracing.h>
279
310
280
311
typedefunsignedint u32;
281
-
typedefunsignedlonglong u64;
282
-
typedefintpid_t;
312
+
typedeflonglong s64;
283
313
284
-
// Declare the external kfunc
285
-
externu64 bpf_kfunc_call_test(u32 a, u64 b, u32 c, u64 d) __ksym;
- **External kfunc Declaration:** The `extern` keyword declares the `bpf_kfunc_call_test` function, making it accessible within the eBPF program.
304
-
337
+
- **External kfunc Declaration:** The `extern` keyword declares the `bpf_strstr` function, making it accessible within the eBPF program.
338
+
305
339
- **Kprobe Attachment:** The `SEC("kprobe/do_unlinkat")` macro attaches the eBPF program to the `do_unlinkat` kernel function. Every time `do_unlinkat` is invoked, the `handle_kprobe` function executes.
306
-
307
-
- **Using the kfunc:** Within `handle_kprobe`, the eBPF program calls `bpf_kfunc_call_test` with four arguments (`1, 2, 3, 4`). The result, which should be the sum of these numbers, is then printed using `bpf_printk`, displaying both the PID and the result.
340
+
341
+
- **Using the kfunc:** Within `handle_kprobe`, the eBPF program calls `bpf_strstr` with four arguments:
342
+
- `str`: The main string to search within.
343
+
- `str__sz`: The size of the main string.
344
+
- `substr`: The substring to search for.
345
+
- `substr__sz`: The size of the substring.
346
+
347
+
The result, which is the index of the first occurrence of `substr` in `str` or `-1` if not found, is then printed using `bpf_printk`, displaying both the PID and the result.
348
+
349
+
**Important Note:** Implementing a `strstr`-like function directly in eBPF is challenging due to verifier restrictions that limit loops and complex memory accesses. By implementing `strstr` as a kfunc, we bypass these limitations, allowing for more complex and efficient string operations within eBPF programs.
308
350
309
351
### Compiling the eBPF Program
310
352
@@ -316,39 +358,68 @@ To compile the eBPF program, ensure you have the necessary tools installed, such
This command will generate a file named `kfunc.o`, which is the compiled eBPF object file.
388
+
325
389
### Running the eBPF Program
326
390
327
391
Assuming you have a user-space application or a tool to load and attach the eBPF program, you can execute it to observe the interaction between the eBPF program and the custom kfunc.
328
392
329
393
**Sample Output:**
330
394
331
395
```bash
332
-
$ sudo ./kfunc
396
+
# sudo ./load_kfunc
333
397
BPF program loaded and attached successfully. Press Ctrl-C to exit.
Each time the `do_unlinkat` function is invoked in the kernel, the eBPF program prints a message indicating the PID of the process and the result of the kfunc call. In this example, the sum `1 + 2 + 3 + 4` results in `10`, which is reflected in the output.
415
+
Each time the `do_unlinkat` function is invoked in the kernel, the eBPF program prints a message indicating the PID of the process and the result of the kfunc call. In this example, the substring `"wor"` is found at index `7`in the string `"Hello, world!"`.
345
416
346
417
## Summary and Conclusion
347
418
348
419
In this tutorial, we've delved deep into extending eBPF's capabilities by defining and utilizing custom kernel functions (kfuncs). Here's a recap of what we've covered:
349
420
350
421
-**Understanding kfuncs:** Grasped the concept of kfuncs and their role in enhancing eBPF beyond standard helper functions.
351
-
-**Defining kfuncs:** Created a kernel module that defines a custom kfunc, ensuring it can be safely exposed to eBPF programs without altering the core kernel.
422
+
-**Defining kfuncs:** Created a kernel module that defines a custom `strstr`kfunc, ensuring it can be safely exposed to eBPF programs without altering the core kernel.
352
423
-**Writing eBPF Programs with kfuncs:** Developed an eBPF program that leverages the custom kfunc to perform specific operations, demonstrating the enhanced functionality.
353
424
-**Compilation and Execution:** Provided a step-by-step guide to compile, load, and run both the kernel module and the eBPF program, ensuring you can replicate the setup on your own system.
354
425
-**Error Handling:** Addressed potential compilation issues and offered solutions to ensure a smooth development experience.
@@ -371,8 +442,4 @@ Happy eBPF-ing!
371
442
372
443
## Additional Resources
373
444
374
-
If you'd like to learn more about eBPF knowledge and practices, you can visit our open source tutorial code repository at <https://github.com/eunomia-bpf/bpf-developer-tutorial> or website <https://eunomia.dev/tutorials/> for more examples and complete code.
375
-
376
-
## Conclusion
377
-
378
-
By following this detailed tutorial, you've equipped yourself with the knowledge to extend eBPF's capabilities using custom kfuncs. Whether you're aiming to perform advanced kernel interactions, overcome helper limitations, or enhance your observability tools, kfuncs provide the flexibility and power you need. Continue experimenting, stay curious, and contribute to the ever-evolving landscape of eBPF!
445
+
If you'd like to learn more about eBPF knowledge and practices, you can visit our open-source tutorial code repository at [bpf-developer-tutorial](https://github.com/eunomia-bpf/bpf-developer-tutorial) or our website [eunomia.dev/tutorials](https://eunomia.dev/tutorials/) for more examples and complete code.
0 commit comments