تقوم العتاد الشبكي ونواة نظام التشغيل بنقل البيانات وتوجيهها عبر تحريك هياكل الذاكرة بين المستويات المختلفة للنظام. في بدايات شبكات الإيثرنت، كان كل إطار قياسي بحجم 1500 بايت يولد مقاطعة عتادية مستقلة، ويتطلب حجز مخزن مؤقت للمقبس (sk_buff)، ويمر بشكل منفرد عبر جداول التوجيه وقواعد جدار الحماية. ومع أن هذا النموذج القائم على معالجة كل حزمة بمفردها كان كافياً لسرعات 100 ميغابت في الثانية، إلا أنه يشكل عنق زجاجة حرجاً في الشبكات الحديثة متعددة الغيغابت. وعندما تمر البيانات عبر أنفاق الشبكات الخاصة الافتراضية (VPN) المشفرة، تزيد عمليات التغليف البرمجي من استهلاك المعالج لكل مقطع، مما يعيق الوصول إلى السرعات العالية.

وللتغلب على العوائق الهيكلية في معالجة الحزم الفردية، دمجت نواة لينكس أنظمة فرعية متطورة لتجميع الحزم وتفريغ العبء عن المعالج: تفريغ تجزئة بروتوكول التحكم في الإرسال (TSO)، والتفريغ العام للتجزئة (GSO)، والتفريغ العام للاستقبال (GRO). ويوضح فهم كيفية تفاعل هذه التقنيات مع واجهات TUN الافتراضية، وطبقات التشفير، ومشغلات الشبكة، كيف تبلغ مسارات النقل الحديثة أقصى سعة ممكنة دون استنزاف طاقة المعالجة المركزية.

اختناق المعالج مع كل حزمة: قيود وحدة النقل الكبرى على الواجهات الافتراضية

في شبكات بروتوكول الإنترنت التقليدية، يبلغ الحد الأقصى لوحدة النقل (MTU) في شبكات الإيثرنت 1500 بايت. وعند خصم 20 بايت لترويسة IPv4 و 20 أو 32 بايت لترويسة TCP، يصبح الحجم الأقصى للحمولة المفيدة (MSS) 1460 بايت. ولإشغال رابط إيثرنت بسرعة 10 غيغابت في الثانية بالكامل، يتعين على النظام معالجة وإرسال قرابة 820,000 حزمة في كل ثانية.

المعالجة التقليدية لحزم 1500 بايت المستقلة:
[بيانات التطبيق] -> تجزئة TCP -> [skb_1..skb_45] -> جدار الحماية -> التوجيه -> المشغل -> 45 مقاطعة للمعالج

تجميع GSO (حزمة فائقة بحجم 64 كيلوبايت):
[بيانات التطبيق] -> حزمة فائقة واحدة (64KB) -> [هيكل skb موحد] -> جدار الحماية -> التوجيه -> تجزئة متأخرة

عواصف المقاطعات وتكاليف تبديل السياق في مسارات البيانات البرمجية

تتطلب كل حزمة تدخل إلى نواة نظام التشغيل سلسلة من الخطوات البرمجية المستهلكة للموارد:

  • تخصيص وتهيئة هيكل الذاكرة المؤقتة لمقبس النواة (struct sk_buff).
  • فحص ذاكرة التوجيه ومطابقة قواعد الجدران النارية عبر netfilter أو خطافات eBPF.
  • تنفيذ التحويلات التشفيرية (مثل ChaCha20-Poly1305 أو AES-GCM) بين طرفي النفق.
  • توليد مقاطعات برمجية (NET_RX_SOFTIRQ و NET_TX_SOFTIRQ) وتوزيعها على نوى المعالج.

عندما يتجاوز تدفق البيانات 500,000 إطار في الثانية، تستهلك نوى المعالجة معظم طاقتها في تلبية طلبات المقاطعة ومسح مستويات الذاكرة المخبأة L1/L2 بدلاً من تشغيل برامج المستخدم. وفي أنظمة VPN، تواجه الحزم العابرة لأجهزة TUN أو TAP تأخيراً إضافياً ناتجاً عن تمرير البيانات بين النواة ومساحة المستخدم مع تكرار تبديل سياق المعالجة.

استنزاف الذاكرة ونسخ البيانات عبر الحدود بين مساحة المستخدم والنواة

تقوم برمجيات VPN في مساحة المستخدم بقراءة البيانات من واجهة الشبكة الافتراضية (/dev/net/tun) عبر نداءات النظام مثل read() أو recvmsg(). وإذا كان النفق مقيداً بحجم 1500 بايت لكل عملية قراءة، فإن تدفق البيانات بمعدل 1 غيغابت في الثانية يجبر النظام على إجراء أكثر من 80,000 تبديل سياق في كل ثانية.

ويؤدي كل انتقال بين مساحة النواة ومساحة المستخدم إلى تعطيل مخزن ترجمة العناوين (TLB) ومنافسة حادة على مسار الذاكرة. وبدون تجميع الحزم في دفعات كبرى، تستنفد طاقة المعالجة قبل أن تقترب بطاقة الشبكة من طاقتها القصوى.

تسريع الإرسال: تفريغ التجزئة عبر العتاد TSO وتفريغ التجزئة العام GSO

لمنع استنزاف المعالج في مسار الإرسال، ينقل مهندسو الشبكات مهمة تقطيع البيانات إلى بطاقة الشبكة مباشرة، أو يؤجلون تجزئتها برمجياً حتى آخر نقطة قبل إرسالها إلى المشغل.

بناء الحزم الفائقة: صيانة محددات البروتوكول عبر ضبط وتيرة تدفق TCP

تتيح تقنية تفريغ التجزئة العتادية (TSO) لمكدس بروتوكول TCP تجميع كتلة بيانات متصلة يصل حجمها إلى 64 كيلوبايت (GSO_MAX_SIZE)، والتعامل معها كحزمة إرسال مفردة. وبدلاً من تقطيع البيانات إلى أجزاء بحجم 1460 بايت في طبقة المقابس:

  1. يبني مكدس TCP هيكل sk_buff واحداً يضم حمولة تعادل ما يصل إلى 45 إطاراً قياسياً.
  2. تعبر الحزمة الفائقة قواعد جدار الحماية، وخوارزميات التحكم في الازدحام، وطوابير تنظيم الحركة كوحدة واحدة.
  3. يحافظ محرك ضبط وتيرة التدفق على فترات زمنية دقيقة بين الحزم، متوافقاً مع المبادئ المشروحة في مقالنا حول /news/bufferbloat-active-queue-management-vpn-fq-codel-cake.
  4. يجري تخصيص أرقام التسلسل ومتابعة نافذة الإرسال مرة واحدة للكتلة بأكملها بدلاً من تكرارها عشرات المرات.

ولما كانت بطاقات الشبكة تحتاج إلى دعم عتادي خاص لتجزئة حزم TSO، طورت نواة لينكس آلية التجزئة العامة GSO لتعميم هذه الميزة برمجياً على كافة الواجهات، بما فيها الأنفاق الافتراضية المشفرة.

آلية عمل skb_gso_segment(): التجزئة المتأخرة عند طبقة مشغل العتاد

عندما تصل الحزمة الفائقة إلى طابور الإرسال، تتحقق النواة من خصائص الواجهة (netdev->features). وإذا كان المشغل أو العتاد يدعم رايات NETIF_F_TSO أو NETIF_F_GSO، يُمرر الهيكل المجمع مباشرة إلى الذاكرة الحلقية للبطاقة.

أما إذا كانت الواجهة تفتقر للدعم العتادي — وهو الأمر الشائع في شبكات الأنفاق البرمجية — فتستدعي النواة دالة skb_gso_segment() عبر الدالة dev_hard_start_xmit() لإتمام التجزئة برمجياً في اللحظة الأخيرة:

struct sk_buff *skb_gso_segment(struct sk_buff *skb, netdev_features_t features)
{
    if (skb_needs_check(skb, true))
        return ERR_PTR(-EINVAL);

    /* تجزئة حمولة skb إلى وحدات MTU مع نسخ الترويسات بدقة */
    return skb_mac_gso_segment(skb, features);
}

وبتأجيل التجزئة حتى اللحظة الأخيرة قبل الإرسال الفعلي، يعالج مسار النواة هيكل بيانات واحداً عبر 95% من مراحله بدلاً من 45 هيكلاً، مما يحد بدرجة هائلة من حركة البيانات على ناقل الذاكرة.

دمج البيانات عند الاستقبال: آلية Generic Receive Offload (GRO) في دورة NAPI

بينما تتولى تقنية GSO تسريع إرسال البيانات، تتطلب حركة المرور الواردة آلية عكسية متطابقة. وتستقبل منافذ الشبكة آلاف الحزم المنفصلة بحجم 1500 بايت، والتي ينبغي تجميعها قبل تسليمها إلى طبقات الشبكة العليا.

التحقق الصارم من البروتوكول: دمج المقاطع المتتالية المنتظمة دون أخطاء

تعمل آلية التجميع العام عند الاستقبال (GRO) ضمن حلقة فحص المقاطعات البرمجية NAPI. وعندما يستخرج المشغل الحزم من الذاكرة الحلقية، تفحص دالة napi_gro_receive() الترويسات للتأكد مما إذا كانت الحزم المتتابعة تنتمي إلى نفس الاتصال.

وتفرض الآلية شروطاً صارمة قبل دمج الحزم:

  • التطابق التام لعناوين IP المصدر والوجهة، وأرقام المنافذ، ومعرف البروتوكول.
  • تسلسل أرقام حزم TCP بصورة متصلة ومنتظمة دون انقطاع أو تداخل في البيانات.
  • تصاعد وصحة قيم الطوابع الزمنية TCP Timestamps (وفق معيار RFC 7323).
  • تطابق إشارات الإخطار الصريح بالازدحام (ECN) في جميع الحزم المدمجة.

وفي حال حدوث أي اختلاف في الترويسات أو اضطراب في ترتيب وصول الحزم، يتوقف التجميع فوراً وتُسلم الحزم المتوفرة للطبقات العليا. وتضمن هذه الرقابة الدقيقة سلامة حسابات خوارزميات رصد الفقدان مثل /news/tcp-sack-rfc-6675-loss-recovery-pipe-algorithm-vpn و /news/tcp-rack-tlp-rfc-8985-time-based-loss-recovery-vpn.

تقليل اجتياز طبقات الشبكة: تسليم حمولات مجمعة بحجم 64 كيلوبايت إلى المقابس

عقب إتمام الدمج، يُرفع هيكل sk_buff موحد بحمولة تصل إلى 64 كيلوبايت إلى مكدس الشبكة. وبدلاً من تكرار فحص جداول التوجيه وقواعد التصفية 40 مرة لحمولة قدرها 60 كيلوبايت، تنفذ النواة التدقيق لمرة واحدة فقط. ويستقبل التطبيق البيانات بنداء read() واحد، مما يلغي الاستيقاظ المتكرر للعمليات ويوفر حتى 70% من استهلاك المعالج.

تكامل واجهة TUN الافتراضية: راية IFF_VNET_HDR وتفريغ UDP في بروتوكولات VPN

في بيئات الشبكات الافتراضية والمشفرة، يقع عنق الزجاجة الأساسي عند الحد الفاصل بين مكدس شبكة النواة ومحرك تشفير النفق.

تمرير بيانات تعريف Virtio Net عبر حدود الواجهة /dev/net/tun

في السابق، كانت واجهة /dev/net/tun في لينكس تجرد الحزم من بيانات التجميع، مما يلزم المحولات الافتراضية بالتعامل مع حزم مقيدة بحجم MTU فقط. ولتجاوز هذه العقبة، أُضيفت راية IFF_VNET_HDR إلى أجهزة TUN/TAP.

وعند تفعيل IFF_VNET_HDR، تسبق كل حزمة متبادلة مع /dev/net/tun ترويسة تعريفية خاصة struct virtio_net_hdr:

struct virtio_net_hdr {
    uint8_t  flags;       /* حالة صحة المجموع الاختباري أو الحاجة لحسابه */
    uint8_t  gso_type;    /* نمط التجزئة VIRTIO_NET_HDR_GSO_TCPV4, UDP */
    uint16_t hdr_len;     /* الطول الكلي لترويسات الإيثرنت و IP و TCP */
    uint16_t gso_size;    /* حجم شريحة MSS المستهدف عند التجزئة */
    uint16_t csum_start;  /* نقطة بداية حساب المجموع الاختباري */
    uint16_t csum_offset; /* موضع كتابة ناتج المجموع الاختباري */
};

تنقل هذه البنية تعليمات التفريغ عبر حدود النواة. وبذلك يقرأ تطبيق VPN حزمة فائقة بحجم 64 كيلوبايت بنداء واحد مع الحفاظ على خصائص GSO، ثم يشفر الكتلة بالكامل ويرسلها إلى البطاقة الفعلية دون تقطيع مسبق.

تجزئة حزم UDP وتفريغ GRO لأنفاق بروتوكولات WireGuard و IPsec

تعتمد بروتوكولات VPN الحديثة على تغليف البيانات داخل حزم UDP. ومنذ إصدار النواة 4.18، أُضيفت ميزات UDP GSO (UDP_SEGMENT) و UDP GRO (UDP_GRO):

  1. إرسال دفعات UDP GSO: يستطيع التطبيق إنشاء حزمة UDP موحدة بحجم 64 كيلوبايت وتحديد حجم الشريحة المطلوب للنواة عبر خيار المقبس UDP_SEGMENT.
  2. التشفير الشعاعي السريع: تشفر بروتوكولات الأنفاق كتل 64 كيلوبايت في الذاكرة باستخدام تعليمات المعالجة المتوازية (AVX-512 أو ARM NEON)، متفادية إعادة تحميل مفاتيح التشفير مع كل حزمة صغيرة.
  3. التجزئة العتادية على الخط: تتولى بطاقة الشبكة تجزئة البيانات عند إرسالها الفعلي في الكابل، مما يحقق أعلى استفادة من وحدة النقل دون اللجوء لتجزئة حزم IP.

يمنع هذا التكامل تدهور السرعة الناتج عن الامتلاء المفاجئ للمخازن المؤقتة أثناء مرحلة البدء البطيء، وهي الظاهرة المفصلة في دراستنا حول /news/tcp-hystart-plus-rfc-9406-bufferbloat-slow-start-vpn.

التحسين الهيكلي للبنية التحتية: محرك خطوط الأنابيب فائق الإنتاجية RiceGuard

تدمج منصة VPNRice أحدث ميزات تفريغ النواة مباشرة في قلب مكدس الأنفاق الخاص بها من خلال محرك التسريع RiceGuard:

  • بنية TUN متعددة الطوابير: تخصيص طوابير افتراضية مستقلة ترتبط بنوى محددة في المعالج لمنع تنازع الأقفال الدوارة أثناء التوزيع المتوازي للحزم.
  • التكامل المباشر مع ترويسات Vnet: دعم كامل لرايتي IFF_VNET_HDR و TUNSETOFFLOAD لتبادل حزم 64 كيلوبايت مباشرة بين حلقات التشفير ومكدس الشبكة.
  • تجميع UDP GRO التكيفي: الرصد التلقائي لسعة مخازن المقابس وتجميع الحزم المشفرة الواردة في حزم كبرى قبل التحقق من التوقيع الرقمي.
  • حلقات ذاكرة عديمة النسخ: حجز مسبق لمخازن دائرية محاذاة لخطوط ذاكرة المعالج لتفادي إخفاقات TLB أثناء التدفقات التي تبلغ عدة غيغابتات.

تكفل هذه التحسينات لشبكة VPNRice استغلال كامل النطاق الترددي لشبكات الألياف الضوئية والجيل الخامس 5G، مع الحفاظ على برودة العتاد وتوفير طاقة البطارية في الهواتف الذكية.

القياس العملي في بيئة لينكس: إعداد واختبار كفاءة تقنيات GSO و GRO

يستطيع مهندسو الشبكات ومديرو الأنظمة فحص وضبط خصائص تفريغ التجزئة على بوابات لينكس باستخدام أدوات سطر الأوامر القياسية.

فحص قدرات تفريغ العتاد الشبكي باستخدام أداة ethtool

تتيح أداة ethtool استعراض وتعديل ميزات البطاقة الشبكية:

# فحص حالة ميزات تفريغ التجزئة على الواجهة الفعلية eth0
ethtool -k eth0 | grep -E "segmentation|receive-offload"

# مثال للمخرجات:
# tcp-segmentation-offload: on
# generic-segmentation-offload: on
# generic-receive-offload: on
# large-receive-offload: off [fixed]

ولتفعيل هذه الخصائص بصورة دائمة على المنفذ:

# تفعيل تقنيات GSO و GRO و TSO على بطاقة الشبكة الخارجية
sudo ethtool -K eth0 gso on gro on tso on

# متابعة إحصائيات تجميع الحزم في المشغل
ethtool -S eth0 | grep -E "gro|gso|tso"

لتحقيق أقصى استفادة من تقنيتي GSO و GRO، يجب رفع سعة المخازن المؤقتة للمقابس لتستوعب حزم 64 كيلوبايت دون إسقاط للبيانات:

# رفع الحدود القصوى لذاكرة مقابس النواة
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216

# ضبط حدود ذاكرة TCP (الحد الأدنى، الافتراضي، الأقصى مقاساً بالصفحات)
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"

# التحقق من حدود نقل GSO على واجهة النفق الافتراضي
ip -d link show dev tun0

يضمن التنسيق الدقيق بين البطاقات العتادية والواجهات الافتراضية TUN ومخازن النواة التخلص من اختناقات المعالجة التسلسلية، وإطلاق العنان لأداء متين وسريع متعدد الغيغابت عبر الأنفاق المؤسسية الآمنة.

تحميل VPNRice.