XDP Packet Processing

XDP Temelleri ve Packet Parsing

XDP (eXpress Data Path) - driver seviyesinde, kernel stack’e girmeden önce packet processing. En hızlı eBPF hook noktası.

XDP Temelleri ve Packet Parsing

Lab: eBPF XDP Fundamentals

Bu lab’da öğrenecekleriniz:

  • XDP mode’ları: Generic (test), Native (production), Offload (NIC)
  • XDP action’ları:
    • XDP_PASS - paketi kernel stack’e ilet
    • XDP_DROP - paketi düşür (en hızlı)
    • XDP_TX - paketi aynı interface’den geri gönder
    • XDP_REDIRECT - başka bir interface’e yönlendir
    • XDP_ABORTED - hata, paketi düşür + trace
  • struct xdp_md context (data, data_end, data_meta)
  • Ethernet header parsing (struct ethhdr)
  • IPv4/IPv6 header parsing
  • TCP/UDP header parsing
  • ICMP parsing
  • Byte order: bpf_ntohs(), bpf_htons()

Packet Parsing Pattern

SEC("xdp")
int xdp_parser(struct xdp_md *ctx) {
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;

    struct ethhdr *eth = data;
    if (data + sizeof(*eth) > data_end)
        return XDP_PASS;

    if (eth->h_proto == bpf_htons(ETH_P_IP)) {
        struct iphdr *ip = data + sizeof(*eth);
        if ((void *)(ip + 1) > data_end)
            return XDP_PASS;
        // IPv4 packet processing...
    }
    return XDP_PASS;
}

Tam parse chain: Ethernet → IP → TCP/UDP

Yukarıdaki temel pattern’i tam bir L3/L4 parser’a genişletme:

SEC("xdp")
int xdp_full_parse(struct xdp_md *ctx) {
    void *data = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;

    // L2: Ethernet
    struct ethhdr *eth = data;
    if (data + sizeof(*eth) > data_end)
        return XDP_PASS;

    if (eth->h_proto != bpf_htons(ETH_P_IP))
        return XDP_PASS;  // IPv4 değil, atla

    // L3: IPv4
    struct iphdr *ip = data + sizeof(*eth);
    if ((void *)(ip + 1) > data_end)
        return XDP_PASS;

    // L4: TCP veya UDP
    void *l4 = (void *)ip + (ip->ihl * 4);  // IP header değişken uzunlukta olabilir

    if (ip->protocol == IPPROTO_TCP) {
        struct tcphdr *tcp = l4;
        if ((void *)(tcp + 1) > data_end)
            return XDP_PASS;
        // tcp->dest hedef portu içerir (network byte order)
        if (tcp->dest == bpf_htons(80))
            return XDP_DROP;  // HTTP trafiğini düşür
    } else if (ip->protocol == IPPROTO_UDP) {
        struct udphdr *udp = l4;
        if ((void *)(udp + 1) > data_end)
            return XDP_PASS;
        // udp->dest hedef portu içerir
        if (udp->dest == bpf_htons(53))
            return XDP_DROP;  // DNS trafiğini düşür
    }

    return XDP_PASS;
}

Pattern’e dikkat edin: her pointer dereference, data_end’e karşı sınır kontrolü gerektirir. Verifier bunu zorlar — herhangi bir kontrolü atlarsanız programınız yüklenmez.

xdp-tutorial: packet01-parsing/ - kendiniz yapın!

xdp-tutorial nasıl çalışılır:

  1. Önce README.org dosyasını okuyun (ödevleri anlayın)
  2. xdp_prog_kern.c dosyasını okuyun, parsing_helpers.h inceleyin
  3. Ödevleri kendiniz yapın
  4. Takılırsanız packet-solutions/ klasörüne bakın

Ön okuma: XDP Paper (~15 sayfa)

xdp-tutorial’da inceleyin: setup_dependencies.org - bağımlılıklar (clang, llvm, libelf, kernel header’ları, bpftool, libxdp, libbpf).