eBPF for Linux Admins: Part IV
Table of Contents
eBPF - This article is part of a series.
In the previous articles, we were using skb
to get details of a packet.
This skb
object is the kernel representation of a packet.
Dropping a packet after skb gets created is waste of CPU and memory. This can even have an impact during DDoS attempt.
So how can we drop a packet even before it reaches the stage of skb
creation.
Here we will use another hook point called XDP
or eXpressDataPath
.
XDP
is a high-performance, programmable packet processing framework within the Linux kernel that enables early packet handling before reaching the network stack.
XDP Packet flow#
- The packets comes to the NIC.
- NIC places those packets to the
RX_RING
which is a circular ring buffer via DMA. - When the buffer gets full, an interrupt is fired to CPU.
- Once the CPU get’s interrupted, the loaded NIC driver code gets executed.
- The driver code reads the packets from the queue.
- The initial path of packet after
RX_RING
is where we use XDP.
Instead of writing our own module, we will write an eBPF program this time and then attach that to the the interface.
There are different ways to us XDP.
Generic XDP#
XDP program loaded into the kernel as part of the network path.
Native XDP#
XDP program loaded by the driver in it’s initial receive path
Offloaded XDP#
XDP program loads directly to the NIC and handled by the NIC controller.
In this article we will use Generic XDP since it doesn’t need support from NIC or it’s driver.
Once the packet is received by the XDP program, it can do one of below;
XDP_DROP
: No processing, just drop the packet.XDP_PASS
: Pass the packet to the next network stack component.XDP_TX
: Forward the packet to the same network interface.XDP_REDIRECT
: Froward the packet to another NIC and bypass all kernel network stack paths.
As I mentioned earlier, this is our gateway to eBPF so pay attention to this chapter.
Our experiments will happen from an Ubuntu 23.10 VM running in VirtualBox.
The eBPF program we write will block all network in an interface.
To compile eBPF programs, we need to install few tools.
sudo apt install clang llvm libelf-dev libpcap-dev build-essential libbpf-dev linux-headers-$(uname -r) gcc-multilib
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
SEC("xdp_drop")
int xdp_drop_prog(struct xdp_md *ctx)
{
return XDP_DROP;
}
char _license[] SEC("license") = "GPL";
Compile the program to bpf format.
Use
man bpf-helpers
command to get more details.clang -O2 -g -Wall -target bpf -c xdp_drop.c -o xdp_drop.o
After compilation, we will get an eBPF file named xdp_drop.o
.
We will be using the xdp-loader
tool to load the xdp_drop.o
program, so we need install xdp tools first.
sudo apt-get install xdp-tools
After installing the tool, check the loaded programs on the interfaces. As of now no programs were loaded!
sudo xdp-loader status
CURRENT XDP PROGRAM STATUS:
Interface Prio Program name Mode ID Tag Chain actions
--------------------------------------------------------------------------------------
lo <No XDP program loaded!>
enp0s3 <No XDP program loaded!>
enp0s8 <No XDP program loaded!>
enp0s9 <No XDP program loaded!>
Now load the program to one of the interface.
sudo xdp-loader load -m skb -s xdp_drop enp0s8 xdp_drop.o
Check the loaded program on all interfaces.
sudo xdp-loader status
CURRENT XDP PROGRAM STATUS:
Interface Prio Program name Mode ID Tag Chain actions
--------------------------------------------------------------------------------------
lo <No XDP program loaded!>
enp0s3 <No XDP program loaded!>
enp0s8 xdp_dispatcher skb 117 90f686eb86991928
=> 50 xdp_drop_prog 126 57cd311f2e27366b XDP_PASS
enp0s9 <No XDP program loaded!>
That concludes part 4 of this eBPF series. In next one we will see how to block a port using eBPF in XDP.