مدیریت گیت‌وی‌های شبکه خصوصی مجازی (VPN)، سرورهای بازپخش میانی و پروکسی‌های ترانزیت در شرایط ترافیک سنگین، نیازمند راهکارهای ساختاری کارآمد است. بر روی پورت‌های فیزیکی مدرن 40GbE و 100GbE، نرخ ورود بسته‌ها به سیستم معمولاً از ۲۰ تا ۵۰ میلیون بسته در ثانیه (Mpps) فراتر می‌رود.

در چنین سرعت‌هایی، پشته شبکه سنتی در هسته لینوکس با محدودیت‌های پردازش بسته در ثانیه (PPS) مواجه می‌شود. در مسیر پیش‌فرض سیستم‌عامل، هر فریم دریافتی مستلزم تخصیص بافرهای حلقوی درایور، ایجاد ساختار پرهزینه Socket Buffer (sk_buff)، جستجو در جداول مسیریابی IP، عبور از رهگیری‌های Netfilter (conntrack) و قفل‌های داخلی هسته است.

حتی در صورت بهره‌گیری از تکنیک‌های توزیع سخت‌افزاری دریافت (RSS)، بار پردازشی ناشی از ایجاد و آزادسازی ساختارهای sk_buff ظرفیت پردازش یک هسته CPU را در حدود ۲ تا ۴ میلیون بسته در ثانیه محدود می‌سازد.

برای دستیابی به ظرفیت خطوط فیزیکی انتقال بدون خروج از محیط استاندارد لینوکس، مهندسان سیستم از معماری eXpress Data Path (XDP) همراه با فرمان XDP_REDIRECT و نگاشت‌های اختصاصی BPF موسوم به devmap و cpumap استفاده می‌کنند.

+--------------------------------------------------------------------------+
|          معماری هدایت بسته در هسته لینوکس با EBPF XDP_REDIRECT            |
+--------------------------------------------------------------------------+
|                                                                          |
|       ورودی داده از خطوط فیبر نوری فیزیکی (100GbE SFP28)                 |
|                           │                                              |
|                           v                                              |
|       بافر حلقوی دریافت RX کارت شبکه (دسترسی مستقیم DMA)                 |
|                           │                                              |
|                           v (بافر خام xdp_buff بدون ساختار sk_buff)      |
|      +-------------------------------------------------------------+     |
|      |               قلاب پردازش درایور XDP (eBPF)                 |     |
|      |                                                             |     |
|      |   - تحلیل سرآیندهای لایه ۲ تا ۴ (پروتکل‌های IP, UDP)        |     |
|      |   - جستجو در جدول نگاشت BPF (شامل devmap یا cpumap)         |     |
|      |   - صدور تصمیم هدایت مجدد XDP_REDIRECT                      |     |
|      +-------------------------------------------------------------+     |
|              │                                             │             |
|              v (XDP_REDIRECT به devmap)                    v (cpumap)    |
|      +-------------------------------+             +---------------+     |
|      | BPF_MAP_TYPE_DEVMAP           |             | BPF_CPUMAP    |     |
|      | مقصد: حلقه ارسال TX کارت دوم  |             | مقصد: هسته N  |     |
|      +-------------------------------+             +---------------+     |
|              │                                             │             |
|              v (ارسال مستقیم سخت‌افزاری بدون کپی)           v             |
|      انتقال با حداکثر سرعت خط فیزیکی               پردازش وقفه نرم‌افزاری|
|      (بیش از ۳۰ Mpps در لایه درایور)               (رمزگشایی محاسباتی)   |
|                                                                          |
+--------------------------------------------------------------------------+

سازوکار اساسی فرمان XDP_REDIRECT

فریم‌ورک eXpress Data Path (XDP) بستری برای اجرای کدهای eBPF در سطح درایور کارت شبکه قبل از تخصیص اشیاء sk_buff توسط هسته فراهم می‌سازد. پردازش روی ساختار فشرده xdp_buff صورت می‌پذیرد و می‌تواند پنج تصمیم مختلف صادر کند:

  • XDP_DROP: حذف فوری بسته برای مقابله مؤثر با حملات منع سرویس توزیع‌شده.
  • XDP_TX: ارسال مجدد بسته از همان درگاه شبکه‌ای که بسته را دریافت کرده است.
  • XDP_PASS: ارسال بسته به پشته شبکه استاندارد هسته لینوکس جهت پردازش معمول.
  • XDP_ABORTED: ثبت خطای اجرایی برنامه و دور انداختن بسته ورودی.
  • XDP_REDIRECT: هدایت مستقیم بافر خام بسته به مقصد دیگر بدون درگیر شدن پشته شبکه.

در حالی که در مراحل اولیه توسعه XDP بیشترین تمرکز روی حذف سریع بسته‌ها (XDP_DROP) بود، شبکه‌های ترانزیت و گیت‌وی‌های مدرن VPN از XDP_REDIRECT استفاده می‌کنند. با فراخوانی تابع سیستمی bpf_redirect_map()، برنامه eBPF فریم‌های خام را با تاخیر زیر یک میکروثانیه به کارت شبکه دیگر یا یک هسته پردازشی معین هدایت می‌کند.

مسیریابی خروجی پرسرعت با devmap

ساختار devmap (با شناسه‌های BPF_MAP_TYPE_DEVMAP و BPF_MAP_TYPE_DEVMAP_HASH) جدولی از شناسه‌های کارت‌های شبکه مقصد را در حافظه هسته نگهداری می‌کند.

هنگامی که برنامه XDP بسته را به سوی یک devmap هدایت می‌نماید، هسته لینوکس از لایه‌های بالاتر شبکه صرف‌نظر می‌کند؛ در نتیجه جستجوی جداول مسیریابی، پردازش فیلترهای Netfilter و صف‌های میانی (qdisc) حذف می‌شوند. بافر خام xdp_buff مستقیماً در حلقه ارسال (TX) کارت شبکه مقصد قرار می‌گیرد.

+--------------------------------------------------------------------------+
|            مقایسه مسیر بسته: پشته استاندارد IP در برابر XDP DEVMAP       |
+--------------------------------------------------------------------------+
| مرحله پردازش          | مسیر استاندارد IP در هسته | هدایت مستقیم XDP devmap |
+-----------------------+--------------------------+-----------------------+
| نقطه شروع پردازش      | دریافت وقفه NAPI درایور  | قلاب بومی درایور XDP  |
| ساختار حافظه          | sk_buff سنگین (~256 بایت)| xdp_buff بسیار سبک    |
| تصمیم‌گیری مسیر        | جستجوی درختی FIB         | نگاشت O(1) در جدول BPF|
| فیلترینگ و Conntrack  | پردازش کامل در Netfilter | عدم ورود به پشته هسته |
| سازوکار ارسال نهایی   | فراخوانی dev_queue_xmit  | اجرای مستقیم ndo_xdp_xmit|
| توان عملیاتی هر هسته  | حدود ۲ تا ۴ Mpps         | حدود ۲۵ تا ۳۵ Mpps    |
+--------------------------------------------------------------------------+

پیاده‌سازی نگاشت devmap با زبان C (eBPF)

در نمونه کد زیر، هدایت ترافیک رمزنگاری‌شده بین دو کارت شبکه 100GbE در هسته لینوکس پیاده‌سازی شده است:

#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <bpf/bpf_helpers.h>

/* تعریف جدول نگاشت devmap برای ذخیره شناسه‌های خروجی */
struct {
    __uint(type, BPF_MAP_TYPE_DEVMAP);
    __uint(max_entries, 64);
    __uint(key_size, sizeof(__u32));
    __uint(value_size, sizeof(__u32));
} tx_port_map SEC(".maps");

SEC("xdp")
int xdp_redirect_forwarder(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;

    /* پردازش بسته‌های IPv4 */
    if (eth->h_proto != __constant_htons(ETH_P_IP))
        return XDP_PASS;

    struct iphdr *iph = (void *)(eth + 1);
    if ((void *)(iph + 1) > data_end)
        return XDP_PASS;

    /* تعیین درگاه شبکه مقصد برای پورت ۲ */
    __u32 target_ifindex = 2;

    /* اجرای هدایت در لایه درایور بدون کپی در حافظه */
    return bpf_redirect_map(&tx_port_map, target_ifindex, 0);
}

char _license[] SEC("license") = "GPL";

توزیع بار رمزنگاری میان هسته‌های پردازنده با cpumap

در حالی که devmap برای ارسال مستقیم داده‌های عبوری مناسب است، پروتکل‌های امن شبکه خصوصی مجازی (نظیر WireGuard و RiceGuard) نیازمند منابع پردازشی CPU برای رمزگشایی الگوریتم‌های ChaCha20-Poly1305 یا AES-GCM هستند.

چالش عمده زمانی رخ می‌دهد که حجم بالایی از بسته‌ها به یک صف دریافت (RX) کارت شبکه هدایت شود. چنانچه یک هسته CPU بخواهد هم‌زمان وقفه‌های سخت‌افزاری درایور و محاسبات ریاضی رمزگشایی را انجام دهد، بار کاری آن به ۱۰۰ درصد می‌رسد در حالی که سایر هسته‌های سرور بلااستفاده مانده‌اند.

نگاشت cpumap (با شناسه BPF_MAP_TYPE_CPUMAP) این ناهمگونی را برطرف می‌کند:

  1. دسته‌بندی اولیه در درایور: برنامه XDP روی هسته دریافت‌کننده با سرعت خط اجرا شده و داده‌های سرآیند را استخراج می‌کند.
  2. محاسبه هش جریان: برنامه با استفاده از ۴ پارامتر اصلی بسته (آدرس‌های مبدا و مقصد، پورت‌ها)، مقدار هش را محاسبه کرده و هسته هدف را تعیین می‌کند.
  3. انتقال به صف هسته مقصد: با فراخوانی bpf_redirect_map(&cpu_map, target_cpu, 0)، فریم خام به حلقه کاری پردازنده منتخب منتقل می‌شود.
  4. تخصیص مستقل و رمزگشایی: هسته هدف فریم را برداشته، ساختار sk_buff را ایجاد کرده و در زمینه وقفه نرم‌افزاری خود (softirq) عملیات رمزگشایی را انجام می‌دهد.
جریان ورودی 100GbE (تک‌صف دریافت RX)
          │
          v
   هسته 0 (تحلیل‌گر سریع XDP)
   [ محاسبه هش ۴-تایی جریان ]
          │
    ┌─────┴─────────────────────────┐
    │ bpf_redirect_map(&cpu_map)    │
    ▼                               ▼
هسته 1 (پردازشگر وقفه SoftIRQ)  هسته 2 (پردازشگر وقفه SoftIRQ)
تخصیص حافظه sk_buff             تخصیص حافظه sk_buff
رمزگشایی ترافیک RiceGuard       رمزگشایی ترافیک RiceGuard

این فرایند، مدیریت صفوف درایور را از پردازش محاسباتی رمزنگاری جدا می‌کند و مانع از مسدود شدن صف‌های کاری در سرورهای مجهز به پردازنده‌های چند‌هسته‌ای می‌گردد.

مراحل پیکربندی و راه‌اندازی در لینوکس

راه‌اندازی ساختار هدایت ترافیک بر پایه XDP در لینوکس از طریق ابزارهای استاندارد BPF صورت می‌گیرد:

مرحله اول: کامپایل برنامه eBPF

کامپایل کد منبع C با استفاده از Clang برای معماری هدف BPF:

clang -O2 -g -target bpf -c xdp_forward.c -o xdp_forward.o

مرحله دوم: اتصال برنامه XDP به رابط شبکه

بارگذاری برنامه کامپایل‌شده در حالت بومی درایور:

# غیرفعال کردن حالت عمومی و بارگذاری در درایور بومی
ip link set dev eth0 xdpgeneric off
ip link set dev eth0 xdpdrv object xdp_forward.o section xdp

مرحله سوم: مقداردهی به جدول devmap

ثبت شناسه رابط شبکه خروجی در نگاشت پین‌شده BPF:

# دریافت شناسه سیستمی برای eth1
IFINDEX_ETH1=$(cat /sys/class/net/eth1/ifindex)

# به‌روزرسانی ورودی جدول devmap با bpftool
bpftool map update pinned /sys/fs/bpf/tx_port_map \
    key 2 0 0 0 \
    value $IFINDEX_ETH1 0 0 0

مرحله چهارم: نظارت بر عملکرد و بررسی شاخص‌ها

مشاهده وضعیت بسته‌های هدایت‌شده و آمار کارت شبکه:

# مشاهده آمار و وضعیت لینک XDP
ip -s link show dev eth0

# مشاهده لاگ‌های تعاملی اجرای برنامه‌های BPF
bpftool prog tracelog

هم‌افزایی فنی با شبکه RiceGuard و VPNRice

در زیرساخت جهانی سرورهای VPNRice، به‌کارگیری هم‌زمان XDP_REDIRECT، devmap و cpumap مزایای فنی گسترده‌ای ایجاد می‌کند:

  1. انتقال داده‌های عبوری با سرعت خط: نودهای میانی شبکه‌های ترانزیت، بسته‌های رمزگذاری‌شده پروتکل‌های WireGuard و RiceGuard را از طریق devmap بازپخش می‌کنند. با حذف تخصیص اشیاء sk_buff، هر سرور می‌تواند بیش از ۳۰ Mpps را در پورت‌های 100GbE انتقال دهد.
  2. توزیع بار هماهنگ با ساختار حافظه NUMA: گیت‌وی‌های تجمیع‌کننده که میزبان هزاران نشست هم‌زمان هستند، از cpumap جهت ارسال ترافیک به هسته‌های متصل به همان نود حافظه NUMA کارت شبکه استفاده می‌کنند تا تاخیر دسترسی به حافظه به کمترین میزان کاهش یابد.
  3. پایداری در برابر ترافیک غیرمجاز: بسته‌های ناهماهنگ و ترافیک غیرعادی در لایه درایور پیش از رسیدن به حافظه اصلی هسته فیلتر و حذف می‌شوند، که پایداری پایدار گیت‌وی‌ها را تحت فشارهای شدید شبکه تضمین می‌نماید.

نکات مهندسی برای محیط‌های عملیاتی

در پیاده‌سازی صنعتی هدایت مبتنی بر XDP رعایت موارد زیر الزامی است:

  • پشتیبانی درایور سخت‌افزاری: اطمینان حاصل کنید که درایور کارت شبکه از متد ndo_xdp_xmit در حالت بومی پشتیبانی کند (از جمله کارت‌های سازگار نظیر Mellanox mlx5، Intel i40e/ice و Broadcom bnxt_en).
  • رزرو فضای سرآیند: بررسی کنید که درایور فضای سرآیند کافی (XDP_PACKET_HEADROOM) را مهیا سازد تا اصلاح فریم‌ها بدون بازتخصیص حافظه صورت پذیرد.
  • تطابق کامل اندازه MTU: اندازه واحد انتقال بیشینه (MTU) در درگاه‌های ورودی و خروجی باید یکنواخت باشد؛ چرا که تفاوت در اندازه منجر به حذف خاموش بسته‌های هدایت‌شده توسط سخت‌افزار خواهد شد.

تلفیق XDP_REDIRECT، devmap و cpumap سرورهای لینوکس را به تجهیزات انتقال داده با عملکرد سازمانی تبدیل کرده و زیرساختی مستحکم برای شبکه‌های امن و مدرن VPN فراهم می‌آورد.