# What Is eBPF?

URL:: https://containiq.com/post/ebpf
Author:: containiq.com
## Highlights
> In Linux architecture, memory is separated into kernel space and user space. The kernel space is used to run the core kernel code and the device drivers. Processes running in kernel space have unrestricted access to all hardware, including CPU, memory, and disks. All other processes run in the user space, which relies on the kernel to access the hardware. Processes running in the user space use system calls to communicate with the kernel for privileged operations like disk or network I/O. ([View Highlight](https://read.readwise.io/read/01fsy1a1ha9f9t8tgtq5hsh0jp))
> This separation creates a secure distinction between various processes, but in some cases the syscall interface is not sufficient and developers need more flexibility to run custom code directly in the kernel without changing the kernel’s source code. For this purpose, Linux provides Linux Kernel Modules, which can be loaded directly in the kernel on demand during runtime. ([View Highlight](https://read.readwise.io/read/01fsy1aapdwp5nd3kd5qjq2yxp))
> BPF, or the Berkeley Packet Filter, was developed from a need to filter network packets in order to minimize unnecessary packet copies from the kernel space to the user space. User space applications like tcpdump are only interested in a small subset of network packets (for example, TCP/IP packets). If the filtering logic is in the user space application, unnecessary packets are copied from the kernel space to the user space. Placing the filtering logic in the kernel prevents those extra copies. ([View Highlight](https://read.readwise.io/read/01fsy1awyg9tcnysn1c0n28jsz))
> BPF provided a register-based virtual machine with its own instruction set where programs could be safely loaded into the kernel and executed in a secure, sandboxed environment. Since version 3.18, the Linux kernel provides extended BPF, or eBPF, which uses 64-bit registers and increases the number of registers from two to ten. eBPF offers an improved instruction set, which significantly boosts performance. ([View Highlight](https://read.readwise.io/read/01fsy1b12qb5ynx5rskrhv51sg))
> eBPF programs are event-driven, which means they can be hooked to certain events and will be run by the kernel when that particular event occurs. ([View Highlight](https://read.readwise.io/read/01fsy1b8xv0s4e2fwv3xkfcy38))
> eBPF programs follow these steps:
> 1. The bytecode of the eBPF program is sent to the kernel along with a program type that determines where the program needs to be attached, which in-kernel helper functions the verifier will allow to be called, whether network packet data can be accessed directly, and what type of object will pass as the first argument to the program.
> 2. The kernel runs a verifier on the bytecode. The verifier runs several security checks on the bytecode, which make sure that the program terminates and does not contain any loop that could potentially lock up the kernel. It also simulates the execution of the eBPF program and checks the state of the virtual machine at every step to ensure the register and stack states are valid. Finally, it uses the program type to restrict the allowed kernel function calls from the program.
> 3. The bytecode is JIT-compiled into native code and attached to the specified location.
> 4. When the specified event occurs, the program is executed and writes data to the ring buffer or the map.
> 5. The map or ring buffer can be read by the user space to get the program result.
>
> 
> Diagram explaining how eBPF works ([View Highlight](https://read.readwise.io/read/01fsy1c0ddfqnegzadv5x5cghp))
> • eBPF moves the task of packet filtering from the user space to the kernel space, thus preventing unnecessary packet copies, which results in a significant performance increase. Because the program is JIT-compiled, it operates quickly. ([View Highlight](https://read.readwise.io/read/01fsy1crj5vx0f535q8wmfa6yj))
> • eBPF programs are sandboxed and verified, which ensures the kernel doesn’t crash or hang up in a loop. This provides greater security over kernel modules. ([View Highlight](https://read.readwise.io/read/01fsy1cv00zhdgkr8dtjdt9hv4))
> • Using eBPF doesn’t require you to modify kernel source code or write full-fledged kernel modules. It is easy to write and execute an eBPF program. ([View Highlight](https://read.readwise.io/read/01fsy1cwczf6wdzntqzvkv100t))
> When to Use eBPF
> eBPF offers the greatest benefits in some specific use cases:
> • eBPF is superior to other methods of profiling and tracing user space processes. eBPF programs can be attached to any kernel function and access the context and arguments of the function, as well as modify them. eBPF provides advanced statistical data structures that easily and efficiently extract meaningful data.
> • eBPF can implement traffic control, so that packets are directly sent to their destination. This is especially useful in Kubernetes and other container environments in which you have multiple networks, because traffic is usually routed to a container stack. Using eBPF, the complex path between the host and the container stack can be bypassed.
> • eBPF can implement [security policies in container environments](https://www.containiq.com/post/kubernetes-security-best-practices) such as Docker or Kubernetes. eBPF is used in XDP (eXpress Data Path) to provide a high-performance, programmable network data path. ([View Highlight](https://read.readwise.io/read/01fsy1dg058pstyvmc58sw3c8t))
> When Not to Use eBPF
> eBPF offers many advantages, but it does have limitations. Here are a few situations where eBPF should not be used:
> • Since eBPF aims to be secure, it prohibits loops and other high-level constructs, which means the programs are simple and restricted. If you want more control over how the programs are executed, writing a kernel module might be a better choice.
> • Executing eBPF programs consumes CPU cycles, and using eBPF instead of built-in tools like iptables might result in a high CPU usage. This will increase the costs from your cloud provider.
> • eBPF is not suited for a use case in which you need to process every packet, such as in decryption and re-encryption of packets. Per-packet processing will be expensive and relatively slow. ([View Highlight](https://read.readwise.io/read/01fsy1e3pyzv3qpw6p115v8fj7))
> Writing an eBPF program directly in the bytecode is extremely hard. Fortunately, you can write the program in other languages and compile it to the eBPF bytecode. You’ll also need to write a user space program that attaches this bytecode to the kernel and interacts with it. The most straightforward way to write an eBPF program is to use [BCC (BPF Compiler Collection)](https://github.com/iovisor/bcc), which provides frontend for eBPF in C++, Python, and Lua. For this example, you will be using the Python frontend. ([View Highlight](https://read.readwise.io/read/01fsy1ecqe2v0p4y8p0b540vvj))
> eBPF is an excellent advancement for the Linux kernel. The ability to run code in a secured and sandboxed fashion in the kernel is a valuable tool for observability, network traffic control, and containerization. ([View Highlight](https://read.readwise.io/read/01fsy1fa9rw62b7287h7y7526s))
> If you want to learn more about eBPF and access community resources, conferences, and blogs, visit [ebpf.io](https://ebpf.io/). The [BCC docs](https://github.com/iovisor/bcc/tree/master/docs) are great to get started quickly with code samples. However, you may also want to consider using [libbpf as an alternative to BCC](https://www.containiq.com/post/libbpf). Finally, the [Awesome eBPF repo](https://github.com/zoidbergwill/awesome-ebpf) aggregates multiple resources for further research. ([View Highlight](https://read.readwise.io/read/01fsy1ff07ysczw2d3gafx7d07))
---
Title: What Is eBPF?
Author: containiq.com
Tags: readwise, articles
date: 2024-01-30
---
# What Is eBPF?

URL:: https://containiq.com/post/ebpf
Author:: containiq.com
## AI-Generated Summary
This article introduces developers to eBPF and explains how it can be used to add security, networking, and other capabilities in the Linux kernel space.
## Highlights
> In Linux architecture, memory is separated into kernel space and user space. The kernel space is used to run the core kernel code and the device drivers. Processes running in kernel space have unrestricted access to all hardware, including CPU, memory, and disks. All other processes run in the user space, which relies on the kernel to access the hardware. Processes running in the user space use system calls to communicate with the kernel for privileged operations like disk or network I/O. ([View Highlight](https://read.readwise.io/read/01fsy1a1ha9f9t8tgtq5hsh0jp))
> This separation creates a secure distinction between various processes, but in some cases the syscall interface is not sufficient and developers need more flexibility to run custom code directly in the kernel without changing the kernel’s source code. For this purpose, Linux provides Linux Kernel Modules, which can be loaded directly in the kernel on demand during runtime. ([View Highlight](https://read.readwise.io/read/01fsy1aapdwp5nd3kd5qjq2yxp))
> BPF, or the Berkeley Packet Filter, was developed from a need to filter network packets in order to minimize unnecessary packet copies from the kernel space to the user space. User space applications like tcpdump are only interested in a small subset of network packets (for example, TCP/IP packets). If the filtering logic is in the user space application, unnecessary packets are copied from the kernel space to the user space. Placing the filtering logic in the kernel prevents those extra copies. ([View Highlight](https://read.readwise.io/read/01fsy1awyg9tcnysn1c0n28jsz))
> BPF provided a register-based virtual machine with its own instruction set where programs could be safely loaded into the kernel and executed in a secure, sandboxed environment. Since version 3.18, the Linux kernel provides extended BPF, or eBPF, which uses 64-bit registers and increases the number of registers from two to ten. eBPF offers an improved instruction set, which significantly boosts performance. ([View Highlight](https://read.readwise.io/read/01fsy1b12qb5ynx5rskrhv51sg))
> eBPF programs are event-driven, which means they can be hooked to certain events and will be run by the kernel when that particular event occurs. ([View Highlight](https://read.readwise.io/read/01fsy1b8xv0s4e2fwv3xkfcy38))
> eBPF programs follow these steps:
> 1. The bytecode of the eBPF program is sent to the kernel along with a program type that determines where the program needs to be attached, which in-kernel helper functions the verifier will allow to be called, whether network packet data can be accessed directly, and what type of object will pass as the first argument to the program.
> 2. The kernel runs a verifier on the bytecode. The verifier runs several security checks on the bytecode, which make sure that the program terminates and does not contain any loop that could potentially lock up the kernel. It also simulates the execution of the eBPF program and checks the state of the virtual machine at every step to ensure the register and stack states are valid. Finally, it uses the program type to restrict the allowed kernel function calls from the program.
> 3. The bytecode is JIT-compiled into native code and attached to the specified location.
> 4. When the specified event occurs, the program is executed and writes data to the ring buffer or the map.
> 5. The map or ring buffer can be read by the user space to get the program result.
>
> 
> Diagram explaining how eBPF works ([View Highlight](https://read.readwise.io/read/01fsy1c0ddfqnegzadv5x5cghp))
> • eBPF moves the task of packet filtering from the user space to the kernel space, thus preventing unnecessary packet copies, which results in a significant performance increase. Because the program is JIT-compiled, it operates quickly. ([View Highlight](https://read.readwise.io/read/01fsy1crj5vx0f535q8wmfa6yj))
> • eBPF programs are sandboxed and verified, which ensures the kernel doesn’t crash or hang up in a loop. This provides greater security over kernel modules. ([View Highlight](https://read.readwise.io/read/01fsy1cv00zhdgkr8dtjdt9hv4))
> • Using eBPF doesn’t require you to modify kernel source code or write full-fledged kernel modules. It is easy to write and execute an eBPF program. ([View Highlight](https://read.readwise.io/read/01fsy1cwczf6wdzntqzvkv100t))
> When to Use eBPF
> eBPF offers the greatest benefits in some specific use cases:
> • eBPF is superior to other methods of profiling and tracing user space processes. eBPF programs can be attached to any kernel function and access the context and arguments of the function, as well as modify them. eBPF provides advanced statistical data structures that easily and efficiently extract meaningful data.
> • eBPF can implement traffic control, so that packets are directly sent to their destination. This is especially useful in Kubernetes and other container environments in which you have multiple networks, because traffic is usually routed to a container stack. Using eBPF, the complex path between the host and the container stack can be bypassed.
> • eBPF can implement [security policies in container environments](https://www.containiq.com/post/kubernetes-security-best-practices) such as Docker or Kubernetes. eBPF is used in XDP (eXpress Data Path) to provide a high-performance, programmable network data path. ([View Highlight](https://read.readwise.io/read/01fsy1dg058pstyvmc58sw3c8t))
> When Not to Use eBPF
> eBPF offers many advantages, but it does have limitations. Here are a few situations where eBPF should not be used:
> • Since eBPF aims to be secure, it prohibits loops and other high-level constructs, which means the programs are simple and restricted. If you want more control over how the programs are executed, writing a kernel module might be a better choice.
> • Executing eBPF programs consumes CPU cycles, and using eBPF instead of built-in tools like iptables might result in a high CPU usage. This will increase the costs from your cloud provider.
> • eBPF is not suited for a use case in which you need to process every packet, such as in decryption and re-encryption of packets. Per-packet processing will be expensive and relatively slow. ([View Highlight](https://read.readwise.io/read/01fsy1e3pyzv3qpw6p115v8fj7))
> Writing an eBPF program directly in the bytecode is extremely hard. Fortunately, you can write the program in other languages and compile it to the eBPF bytecode. You’ll also need to write a user space program that attaches this bytecode to the kernel and interacts with it. The most straightforward way to write an eBPF program is to use [BCC (BPF Compiler Collection)](https://github.com/iovisor/bcc), which provides frontend for eBPF in C++, Python, and Lua. For this example, you will be using the Python frontend. ([View Highlight](https://read.readwise.io/read/01fsy1ecqe2v0p4y8p0b540vvj))
> eBPF is an excellent advancement for the Linux kernel. The ability to run code in a secured and sandboxed fashion in the kernel is a valuable tool for observability, network traffic control, and containerization. ([View Highlight](https://read.readwise.io/read/01fsy1fa9rw62b7287h7y7526s))
> If you want to learn more about eBPF and access community resources, conferences, and blogs, visit [ebpf.io](https://ebpf.io/). The [BCC docs](https://github.com/iovisor/bcc/tree/master/docs) are great to get started quickly with code samples. However, you may also want to consider using [libbpf as an alternative to BCC](https://www.containiq.com/post/libbpf). Finally, the [Awesome eBPF repo](https://github.com/zoidbergwill/awesome-ebpf) aggregates multiple resources for further research. ([View Highlight](https://read.readwise.io/read/01fsy1ff07ysczw2d3gafx7d07))