1. eBPF nedir?
eBPF (genişletilmiş Berkeley Paket Filtresi), çekirdek kaynak kodunu değiştirmeden veya çekirdek modüllerini yüklemeden, çekirdeğin içinde korumalı alana alınmış programları çalıştırmanıza olanak tanıyan bir Linux çekirdek alt sistemidir. Programlar, yürütülmeden önce bir çekirdek bayt kodu doğrulayıcı tarafından doğrulanarak güvenlik sağlanır.
Ağ oluşturmak için eBPF programları aşağıdakilere eklenir:kanca noktalarıçekirdeğin ağ yığınında bulunur ve paketleri inceleyebilir, değiştirebilir, yönlendirebilir veya bırakabilir. Üzerindeki en önemli avantajiptablesveya çekirdek modülleri performans ve programlanabilirliktir: eBPF programları JIT ile yerel koda derlenmiştir ve durumuharitalar(çekirdek ve kullanıcı alanı arasında paylaşılan anahtar/değer depoları).
| Kanca | Konum | Gecikme | Kullanım Örneği |
|---|---|---|---|
| XDP | NIC sürücüsü, sk_buff tahsisinden önce | En düşük | DDoS düşüşü, yük dengeleme |
| TC giriş/çıkış | Sk_buff tahsisinden sonra | Düşük | Trafik şekillendirme, işaretleme, yönlendirme |
| soket filtresi | Soket alma yolu | Orta | tcpdump tarzı filtreleme |
| kprobe/izleme noktası | Çekirdek işlevi girişi/çıkışı | Değişir | Gözlemlenebilirlik, izleme |
2. XDP Kanca Noktaları
XDP (eXpress Veri Yolu) programları, çekirdek bir veri yolu ayırmadan önce ağ yığınında mümkün olan en erken noktada (NIC sürücüsünün içinde) çalışır.sk_buff. Bu şu anlama gelir:
- Yerel XDP: Sürücü XDP'yi yerel olarak destekler (Intel i40e, Mellanox mlx5, vb.). En hızlı — sürücü bağlamında çalışır.
- Genel XDP: Yerel desteği olmayan sürücüler için geri dönüş. Sonra çalışır
sk_bufftahsis - hala iptables'tan daha hızlı, ancak yerel kadar hızlı değil. - Yüklenen XDP: Program NIC ASIC'in kendisinde çalışır. SmartNIC donanımı gerektirir (örn. Netronome). Sıfır CPU maliyeti.
Bir XDP programı beş karardan birini döndürür:
| İade Kodu | Aksiyon |
|---|---|
XDP_DROP | Paketi hemen bırakın — en düşük gecikme süresiyle atma |
XDP_PASS | Normal ağ yığınına geçin |
XDP_TX | Aynı arayüzü geri gönder (geri dön) |
XDP_REDIRECT | Başka bir arayüze veya AF_XDP soketine yönlendir |
XDP_ABORTED | Hata yolu — izleme olayıyla birlikte bırakın |
3. XDP Paket Bırakma Örneği
Aşağıdaki program, bir eBPF haritasında depolanan bir kaynak IP'den tüm UDP paketlerini bırakarak kullanıcı alanı kontrol düzleminin çalışma zamanında engellenenler listesini güncellemesine olanak tanır.
// xdp_drop_udp.c — Drop UDP from IPs in a BPF map
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <bpf/bpf_helpers.h>
// BPF map: src IP → drop flag (1 = drop)
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(max_entries, 1024);
__type(key, __u32); // source IPv4 address
__type(value, __u32); // 1 = block
} blocklist SEC(".maps");
SEC("xdp")
int xdp_drop_udp(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
// Parse Ethernet header
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end) return XDP_PASS;
if (eth->h_proto != __constant_htons(ETH_P_IP)) return XDP_PASS;
// Parse IPv4 header
struct iphdr *ip = (void *)(eth + 1);
if ((void *)(ip + 1) > data_end) return XDP_PASS;
if (ip->protocol != IPPROTO_UDP) return XDP_PASS;
// Check blocklist map
__u32 src = ip->saddr;
__u32 *val = bpf_map_lookup_elem(&blocklist, &src);
if (val && *val == 1) return XDP_DROP;
return XDP_PASS;
}
char _license[] SEC("license") = "GPL";
data_end. Her işaretçi aritmetik işleminin ardından bir sınır kontrolü yapılmalıdır, aksi takdirde program yüklenmeyecektir.Şununla yükleyin ve ekleyin:ip:
# Compile
clang -O2 -target bpf -c xdp_drop_udp.c -o xdp_drop_udp.o
# Attach to interface (native XDP)
ip link set eth0 xdp obj xdp_drop_udp.o sec xdp
# Add an IP to the blocklist via bpftool
bpftool map update name blocklist key 0x01 0x02 0x03 0x04 value 0x01 0x00 0x00 0x00
# Remove XDP program
ip link set eth0 xdp off
4. AF_XDP: Çekirdek Atlaması
AF_XDPXDP'lerle birleştirilmiş bir soket ailesidirXDP_REDIRECTKarar, paket başına çekirdek katılımı olmadan paketleri doğrudan bir kullanıcı alanı bellek bölgesine (UMEM) iletir. Bu, eBPF ekosisteminin DPDK'nın çekirdek atlama modeline cevabıdır.
Anahtar bileşenler:
- UMEM: Çerçevelere bölünmüş, kullanıcı alanı kayıtlı bir bellek bölgesi. Paylaşılan bellek aracılığıyla çekirdek ve kullanıcı alanı arasında paylaşılır.
- Yüzükler: Soket başına dört kilitsiz halka: Doldurma (kullanıcı alanı → serbest çerçeveli çekirdek), Tamamlama (çekirdek → TX yapılan çerçevelerle kullanıcı alanı), RX halkası (çekirdek → alınan çerçevelerle kullanıcı alanı), TX halkası (kullanıcı alanı → gönderilecek çerçevelerle çekirdek).
- Sıfır kopyalama modu: Sürücü destekliyorsa, çerçeveler herhangi bir kopya olmadan aktarılır; yalnızca bir işaretçi aktarımı.
AF_XDP, DPDK'nın operasyonel karmaşıklığı olmadan hat hızında özel paket işleme için idealdir (büyük sayfalar yoktur, temel kullanım için CPU sabitlemesi gerekmez).
5. tc BPF: Trafik Şekillendirme ve Filtreleme
tc(trafik kontrolü) BPF programlarıclsactqdisc ve giriş veya çıkışta çalışabilir. XDP'den farklı olarak, görüntünün tamamını görüyorlarsk_buffve soket meta verilerine, VLAN'lara ve tünel başlıklarına erişebilir.
// tc_mark.c — Mark packets with DSCP EF (46) for VoIP traffic on port 5060
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/udp.h>
#include <bpf/bpf_helpers.h>
SEC("classifier")
int tc_mark_voip(struct __sk_buff *skb) {
void *data = (void *)(long)skb->data;
void *data_end = (void *)(long)skb->data_end;
struct ethhdr *eth = data;
if ((void *)(eth + 1) > data_end) return TC_ACT_OK;
if (eth->h_proto != __constant_htons(ETH_P_IP)) return TC_ACT_OK;
struct iphdr *ip = (void *)(eth + 1);
if ((void *)(ip + 1) > data_end) return TC_ACT_OK;
if (ip->protocol != IPPROTO_UDP) return TC_ACT_OK;
struct udphdr *udp = (void *)(ip + 1);
if ((void *)(udp + 1) > data_end) return TC_ACT_OK;
// Mark SIP traffic (port 5060) with DSCP EF (46 = 0xB8 in TOS byte)
if (udp->dest == __constant_htons(5060) || udp->source == __constant_htons(5060)) {
// DSCP EF = 46, shifted left 2 bits in TOS field = 184 (0xB8)
bpf_skb_store_bytes(skb, offsetof(struct iphdr, tos) + sizeof(struct ethhdr),
&((__u8){184}), 1, BPF_F_RECOMPUTE_CSUM);
}
return TC_ACT_OK;
}
char _license[] SEC("license") = "GPL";
# Attach tc BPF program
tc qdisc add dev eth0 clsact
tc filter add dev eth0 egress bpf da obj tc_mark.o sec classifier
6. eBPF Haritalarıyla Hız Sınırlaması
eBPF haritaları durum bilgisi olan işlemeyi mümkün kılar. Aşağıdaki model, bir sunucuda depolanan bir belirteç kümesini kullanarak kaynak başına IP hızı sınırlamasını uygular.BPF_MAP_TYPE_LRU_HASH:
// Conceptual token bucket per source IP — checks tokens, drops if exceeded
struct ratelimit_entry {
__u64 tokens; // current token count
__u64 last_update; // nanoseconds timestamp
};
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 65536);
__type(key, __u32); // source IP
__type(value, struct ratelimit_entry);
} rate_map SEC(".maps");
// In XDP program:
// 1. bpf_ktime_get_ns() — get current time
// 2. Lookup entry for src IP
// 3. Refill tokens: tokens += (elapsed_ns / 1e9) * rate_pps
// 4. If tokens >= 1: decrement and XDP_PASS
// 5. Else: XDP_DROP
7. bpftool ve bpftrace İç Gözlemi
Canlı eBPF programlarıyla çalışmak için iki temel araç:
# bpftool — inspect loaded programs and maps
bpftool prog list # list all loaded eBPF programs
bpftool prog show id 42 # details for program ID 42
bpftool prog dump xlated id 42 # disassemble to eBPF bytecode
bpftool prog dump jited id 42 # dump JIT-compiled native code
bpftool map list # list all BPF maps
bpftool map dump name blocklist # dump all entries in map "blocklist"
bpftool map update name blocklist \
key 192 168 1 100 value 1 0 0 0 # add entry (network byte order)
# bpftrace — DTrace-style one-liners for kernel tracing
# Count XDP drops per second
bpftrace -e 'tracepoint:xdp:xdp_exception { @drops[args->action] = count(); } interval:s:1 { print(@drops); clear(@drops); }'
# Trace tcp_retransmit_skb — show retransmit events with comm name
bpftrace -e 'kprobe:tcp_retransmit_skb { printf("%s retransmit\n", comm); }'
# Histogram of packet sizes on eth0
bpftrace -e 'tracepoint:net:netif_receive_skb /args->name == "eth0"/ { @size = hist(args->len); }'
8. Karşılaştırma: eBPF/XDP, DPDK ve RDMA
| Özellik | eBPF/XDP | DPDK | RDMA |
|---|---|---|---|
| Çekirdek katılımı | Minimum (sürücüde XDP) | Yok (tam bypass) | Yok (RDMA NIC) |
| Bellek modeli | Standart + AF_XDP UMEM | Çok büyük sayfalar gerekli | Kayıtlı hafıza bölgeleri |
| Maksimum verim | ~100 Gbps yerel XDP | >100 Gbps | 200+ Gb/sn (InfiniBand) |
| CPU kullanımı | Düşük (olay odaklı) | Yüksek (meşgul yoklama çekirdekleri) | Sıfıra yakın (yüksüz) |
| Operasyon karmaşıklığı | Düşük — standart araçlar | Yüksek - özel çekirdekler, devasa sayfalar | Yüksek — yapı yönetimi |
| Kullanım örneği | DDoS azaltma, LB, gözlemlenebilirlik | Sanal yönlendiriciler, NFV, paket oluşturma | Depolama (NVMe-oF), HPC MPI |
| Dil | Kısıtlı C / Pas | C / Pas | Fiiller API'si (C) |