linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • Симулятор
  • База знаний
  • Собеседование
Index
Categories
All entries
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
home/linux/kb/Сеть: L2 / L3/ebpf-xdp

kb/network-l2-l3 ── Сеть: L2 / L3 ── advanced

eBPF XDP - kernel data-plane

XDP - eBPF-программа на самом раннем RX-hook (до skb_alloc). Actions: DROP, PASS, TX, REDIRECT. Native-mode в драйвере, generic в стеке. AF_XDP - zero-copy в userspace. Use cases - DDoS-фильтр, L4 load balancer, cilium kube-proxy.

view as markdownaka: xdp, ebpf-xdp, xdp-program, tc-clsact, af-xdp

Что такое XDP

XDP (eXpress Data Path) - наиболее ранний hook для [[ebpf-basics|eBPF]] в receive-pipeline сетевого стека. Программа выполняется до того, как ядро аллоцирует sk_buff (универсальный буфер пакета) - буквально на raw frame в DMA-области от NIC. Это даёт:

  • Минимум CPU/пакет - 5-10x быстрее чем iptables
  • Pre-allocation - можно дропнуть пакет без аллокации
  • Прямой доступ к payload через указатель

Применяется для:

  • DDoS filtering (Cloudflare обрабатывает 10M+ pps на одном CPU)
  • L4 load balancer (Facebook Katran заменил IPVS)
  • kube-proxy replacement в [[cni-plugins|cilium]]
  • Sampling/mirroring для observability

Где XDP в сетевом стеке

NIC → DMA → ┌────────────────┐
            │  XDP program   │ ← здесь, до skb_alloc
            │  return ACTION │
            └─────┬──────────┘
                  │ XDP_PASS
                  ▼
            ┌────────────────┐
            │  skb_alloc     │
            │  netif_receive │
            └─────┬──────────┘
                  │
                  ▼
            ┌────────────────┐
            │  tc-clsact     │ ← вторая точка для eBPF (tc/ingress)
            └─────┬──────────┘
                  │
                  ▼
            ┌────────────────┐
            │  netfilter     │ ← iptables / nftables
            │  (PREROUTING)  │
            └─────┬──────────┘
                  │
                  ▼
            routing → socket → app

Чем раньше - тем быстрее. XDP < tc-clsact < iptables по latency на пакет.

XDP actions

Программа возвращает один из action-кодов:

ActionЧто делает
XDP_DROPдропнуть, без аллокации skb (cheapest)
XDP_PASSпередать в обычный сетевой стек
XDP_TXотправить пакет обратно на тот же интерфейс
XDP_REDIRECTперенаправить на другой интерфейс или socket
XDP_ABORTEDдроп + tracepoint (debugging)

REDIRECT - самое мощное: можно переправить в другой NIC (мост через XDP), в [[veth-pair|veth]] (для container ingress), или в AF_XDP-сокет (kernel bypass).

Три mode driver-поддержки

XDP исполняется быстрее всего, если NIC-драйвер его поддерживает напрямую. Возможные modes:

ModeГде исполняетсяСкорость
Native (driver)в RX hook драйвера, до DMA-completionмаксимум
Offloadedв SmartNICещё быстрее, но редко (Netronome)
Generic (skb)в netif_receive_skb (после skb_alloc)fallback, медленнее

Native-mode driver'ы (на 2025): mlx5, ixgbe, i40e, ice (Intel), bnxt_en (Broadcom), qede (Marvell), virtio-net (с 5.10+).

Если драйвер не поддерживает - грузится в generic mode (xdpgeneric), работает но медленнее (skb уже аллоцирован).

Проверить:

ip -d link show eth0 | grep xdp

Прицепить XDP-программу

Через bpftool (libbpf-style):

bpftool prog loadall drop_all.bpf.o /sys/fs/bpf/drop type xdp
bpftool net attach xdp pinned /sys/fs/bpf/drop dev eth0

Через ip link (старее):

ip link set dev eth0 xdpdrv obj prog.o sec xdp_prog

Снять:

ip link set dev eth0 xdpdrv off
bpftool net detach xdp dev eth0

Опции xdpdrv (driver), xdpgeneric (force generic), xdpoffload (HW offload).

Минимальная программа

c
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
SEC("xdp")
int drop_icmp(struct xdp_md *ctx) {
    void *data     = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;
    struct ethhdr *eth = data;
    if ((void *)(eth + 1) > data_end) return XDP_PASS;
    if (eth->h_proto != bpf_htons(ETH_P_IP)) return XDP_PASS;
    struct iphdr *ip = (void *)(eth + 1);
    if ((void *)(ip + 1) > data_end) return XDP_PASS;
    if (ip->protocol == IPPROTO_ICMP) return XDP_DROP;
    return XDP_PASS;
}
char LICENSE[] SEC("license") = "GPL";

Каждая проверка > data_end обязательна - verifier требует доказать, что доступ не выйдет за payload (см. ebpf-basics).

tc-clsact - второй hook на уровне TC

XDP - только на ingress. Для egress-фильтрации (или если нужен skb, например для conntrack-info) есть tc-clsact - eBPF на уровне Traffic Control:

tc qdisc add dev eth0 clsact
tc filter add dev eth0 ingress bpf da obj prog.o sec ingress
tc filter add dev eth0 egress  bpf da obj prog.o sec egress

Программа в tc видит уже аллоцированный skb, имеет доступ к conntrack-info, но платит skb_alloc cost. Используется в cilium для pod-egress policy.

Сравнение:

HookКогдаAction
XDPдо skbDROP/PASS/TX/REDIRECT
tc-ingressпосле skb_alloc, до netfilterOK/SHOT/REDIRECT
tc-egressперед отправкойOK/SHOT/REDIRECT
netfilter (iptables/nft)в L3 chainACCEPT/DROP/MARK/...

AF_XDP - zero-copy в userspace

XDP может перенаправить пакет в AF_XDP-сокет - тогда фрейм приходит userspace без копирования через ring-buffer (как DPDK/Netmap, но в kernel-friendly формате).

Архитектура:

  • 4 ring'а: TX, RX, FILL (free buffers), COMPLETION
  • UMEM (User Memory) - shared между app и kernel
  • kernel пишет packet pointer в RX ring
  • app читает RX, обрабатывает, кладёт buffer в FILL для повторного использования

Throughput: 50+ Mpps на одном ядре, latency меньше микросекунды. Применяется в HFT, telco vRAN, DPI системах.

Минусы:

  • Сложно (нужно управлять UMEM, ring'ами, busy-polling)
  • Эксклюзивный pinning интерфейса (один app - один queue)
  • Требует современный driver с zero-copy (mlx5, ice, i40e)

Real-world use cases

1. Cloudflare DDoS-фильтр

Cloudflare пишет XDP-программу, которая дропает SYN-flood, UDP amp, malformed-пакеты до netfilter'а. На каждом edge-сервере 10M+ pps фильтруется одним CPU. iptables на этом железе = 100% CPU.

2. Facebook/Meta Katran - L4 load balancer

Katran (open source) принимает все incoming пакеты, делает consistent hash по 5-tuple, выбирает backend, перенаправляет через XDP_TX или XDP_REDIRECT с IP-encapsulation. Заменил IPVS, обрабатывает 10x больше трафика на том же железе.

3. Cilium kube-proxy replacement

В [[cni-plugins|Cilium]] XDP+tc-eBPF реализуют:

  • Service ClusterIP → backend resolution (заменяет IPVS/iptables)
  • NodePort load balancing
  • NetworkPolicy в eBPF
  • Hubble observability

Latency пакета меньше, scale до 10K+ services без iptables-degradation.

XDP и MTU

XDP-программа может расширить пакет (bpf_xdp_adjust_head, bpf_xdp_adjust_tail) - типично для encapsulation (IP-in-IP, VXLAN через XDP). Если расширить за linkmtu + headroom - драйвер дропнет.

Headroom: 256 байт по умолчанию (можно bpf_xdp_adjust_head(-N) чтобы добавить N байт перед пакетом).

Связь с [[mtu-and-pmtud|MTU и PMTUD]]: XDP-encap должен учитывать MTU underlay'я, иначе blackhole.

Pinned maps - shared state между программами

XDP-программа держит state в [[ebpf-basics|BPF maps]]. Чтобы карта пережила unload программы и shared'илась между несколькими progs - её pin в /sys/fs/bpf/:

bpftool map pin name allow_list /sys/fs/bpf/allow_list

Userspace process читает/обновляет:

bpftool map update pinned /sys/fs/bpf/allow_list key 0x01 0x02 0x03 0x04 \
                                                value 0x01

Типичный паттерн: control-plane process поддерживает allow/block list, XDP-программа читает map на каждый пакет.

Когда что-то пошло не так

  • Программа не загружается, "verifier rejected" - access за data_end, или unbounded loop. Запусти с bpftool prog load ... -L для verifier-log.
  • Native mode не включается - ip -d link show показывает xdpgeneric вместо xdpdrv. Драйвер не поддерживает - или обновлять kernel + driver, или жить в generic.
  • XDP_TX шлёт пакет в never-never - twin-port NIC иногда маршрутизирует TX на тот же физический интерфейс непредсказуемо. Проверь ethtool -S eth0.
  • Падает throughput при включении XDP - generic-mode + сложная программа. Профилируй через perf top -p $(pidof <prog>).
  • AF_XDP socket не получает пакеты - забыл наполнить FILL ring, или неправильный queue-id (ethtool -L для multi-queue).
  • Conflict между XDP-программами - один интерфейс - одна XDP программа. Используй xdp_dispatcher (libxdp) для chaining.

§ команды

bash
ip -d link show eth0 | grep -i xdp

Показать XDP-режим интерфейса (driver/generic/none)

bash
bpftool net show

Все XDP/tc программы прицепленные к интерфейсам

bash
bpftool prog loadall drop.bpf.o /sys/fs/bpf/drop type xdp

Загрузить XDP-программу из ELF, pin в /sys/fs/bpf/

bash
bpftool net attach xdp pinned /sys/fs/bpf/drop dev eth0

Прикрепить загруженную программу к eth0

bash
ip link set dev eth0 xdpdrv off

Снять XDP-программу со всех режимов

bash
tc qdisc add dev eth0 clsact && tc filter add dev eth0 egress bpf da obj e.o sec egress

tc-eBPF на egress - альтернативный hook когда XDP мало

bash
perf record -e bpf -p <pid> -- sleep 5

Профилировать BPF-программы (cycles, инструкции)

bash
ethtool -G eth0 rx 4096

Увеличить RX-ring - помогает если XDP_DROP не успевает на high-pps

§ см. также

  • ebpf-basicseBPF - программируемый kerneleBPF - запуск sandboxed-программ в kernel без kernel-modules. Прицепляются к hooks (kprobe, uprobe, tracepoint, perf, socket, XDP). Verifier гарантирует завершение и safety. JIT компилирует в native. bpftool/libbpf/BCC - userspace tooling.
  • cni-pluginsCNI plugins - сеть Kubernetes (calico, cilium, flannel)CNI - спека плагина: дай pod IP и сеть. Реализации: flannel (VXLAN L2-overlay), calico (BGP routing), cilium (eBPF в kernel). Каждая даёт NetworkPolicy для firewall'а между подами. IPAM - часть CNI, выделяет адреса.
  • linux-bridgeLinux bridge - программный свитчBridge - программный L2-свитч в ядре Linux. Учит MAC в FDB, форвардит фреймы между интерфейсами. Основа Docker default network, KVM bridge, libvirt. С vlan_filtering эмулирует управляемый свитч.
  • veth-pairveth pairveth-pair - два связанных виртуальных Ethernet-интерфейса. Что заходит в один конец - выходит из другого. Базовый кирпич всех Linux-контейнерных сетей.
  • mtu-and-pmtudMTU и Path MTU Discovery (PMTUD)MTU - максимум байт IP-пакета на интерфейсе. PMTUD ищет минимум на пути через ICMP "Fragmentation Needed". Если ICMP режут - blackhole больших пакетов. MSS clamping в iptables/nftables - стандартный фикс на туннелях VXLAN/IPsec.
  • conntrackConntrack - память Linux о всех сетевых соединенияхПодсистема ядра Linux, которая помнит каждое активное соединение. Без неё NAT не развернёт ответ на нужный приватный IP, а фаервол не отличит «новый коннект» от «уже установленного». Видна в `/proc/net/nf_conntrack`.
Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки