عندما يقوم مهندسو الشبكات بتشخيص أسباب ارتفاع زمن الاستجابة (Latency) عبر الأنفاق الافتراضية عالية الإنتاجية، غالباً ما يتجه التركيز إلى نقاط التوجيه الوسيطة في مسار الإنترنت، أو تذبذب الترددات اللاسلكية، أو امتلاء طوابير أجهزة التوجيه الخارجية. ومع ذلك، في العديد من أنظمة لينكس، ينشأ جزء معتبر من تأخير الطوابير مباشرة داخل نواة نظام التشغيل المحلي قبل أن تصل الحزم إلى بطاقة الشبكة الفيزيائية أو الواجهات الافتراضية. عُرفت هذه الظاهرة باسم تضخم الذاكرة المؤقتة للمضيف (Host Bufferbloat)، وكانت تؤدي تاريخياً إلى شلل استجابة التطبيقات التفاعلية كلما بدأت عمليات نقل ملفات ضخمة بالتوازي.
للقضاء على تراكم البيانات الضخم في مشغلات الشبكة مع الحفاظ على معدل النقل الأقصى للخط، قدم مطور نواة لينكس إريك دومازيه (Eric Dumazet) بنية طوابير TCP الصغيرة (TCP Small Queues - TSQ). من خلال وضع حدود ديناميكية لحجم البيانات المسموح بها لكل مقبس بين طبقة النقل وقواعد تنظيم الطوابير (qdisc)، غيّرت هذه التقنية جوهرياً آلية إدارة تدفق البيانات داخل النواة. ويعد استيعاب هندسة TSQ أمراً بالغ الأهمية لبناء شبكات مشفرة وأنفاق VPN عالية الكفاءة.
آليات تضخم الذاكرة المؤقتة (Host Bufferbloat) قبل ظهور TSQ
قبل الإصدار 3.6 من نواة لينكس، كانت بنية مكدس TCP تدفع بالبيانات نحو أجهزة الشبكة بأقصى سرعة تسمح بها نافذة الازدحام (snd_cwnd). وطالما توفرت مساحة في ذاكرة التخزين المؤقت للمقبس، كانت النواة تغلف البيانات في هياكل sk_buff وتسلمها مباشرة إلى طبقة التحكم في حركة البيانات (Traffic Control).
وفي سيناريوهات نقل الملفات الضخمة، سمحت هذه الهندسة بتراكم مئات أو آلاف الحزم غير المرسلة داخل حلقات واصفات المشغل (Driver Rings) وطوابير بطاقة الشبكة. وكان بإمكان اتصال TCP سريع واحد أن يراكم من 2 إلى 8 ميغابايت من البيانات المحتجزة في طوابير البرمجيات بانتظار الخروج عبر كابل الشبكة.
[ كتابة التطبيق Application Write ]
│
▼
[ ذاكرة مقبس TCP Socket Buffer ] ──► نافذة cwnd تسمح بالإرسال
│
▼
[ طابور مشغل الشبكة Driver TX Ring ] ──► (تراكم غير مقيد لعدة ميغابايت)
│
▼
[ الواجهة المادية PHY / واجهة TUN الافتراضية ]
أدى هذا التخزين المؤقت غير المقيد إلى ثلاثة اختلالات تقنية جسيمة:
- تضخم زمن الذهاب والإياب (RTT): عندما تقضي الحزم عشرات أو مئات الأجزاء من الثانية خاملة في الطوابير المحلية، تتضخم قيم RTT المحسوبة، مما يشوش على خوارزميات التحكم في الازدحام ويقلل دقة ردود فعلها.
- احتجاز البيانات عند فقدان الحزم: إذا طرأ فقدان للحزم على المسار الخارجي، تظل كميات ضخمة من البيانات القديمة عالقة في طوابير المشغل ويجب إرسالها بالكامل قبل أن تتمكن حزم إعادة الإرسال العاجلة من مغادرة الجهاز.
- تعطيل تدفق البيانات الحساسة للتأخير: تصبح جلسات SSH وأوامر خوادم DNS ومحادثات الصوت الرقمي التفاعلية عالقة خلف موجات البيانات الضخمة المنبثقة من التنزيلات.
ورغم ظهور خوارزميات إدارة الطوابير النشطة (AQM) مثل CoDel وFQ-CoDel لمعالجة التأخير في أجهزة التوجيه، إلا أن هذه الخوارزميات تعجز عن العمل بكفاءة إذا كان مكدس النقل يغمر الطابور بحزم متراكمة دفعة واحدة. ولذا، دعت الحاجة إلى وضع صمام كبح مباشر عند حدود طبقة النقل.
كيف تفرض طوابير TCP الصغيرة (TSQ) تنظيماً ديناميكياً لكل مقبس
تعتمد تقنية TCP Small Queues على آلية تغذية راجعة محكمة بين اكتمال إرسال الحزم من عتاد الشبكة وإنتاج حزم جديدة من المقابس. وبدلاً من التعامل مع طابور بطاقة الشبكة كمستودع تخزين مفتوح، تتتبع TSQ الحجم الفعلي للبيانات المحتجزة وغير المرسلة لكل مقبس على حدة.
تتبع عداد الذاكرة sk_wmem_alloc
ترتبط كل بنية sk_buff يولدها المقبس بزيادة العداد المحاسبي لذاكرة الكتابة (sk->sk_wmem_alloc). يتضمن هذا العداد حجم الحمولة المفيدة وبيانات النواة الهيكلية. وعندما تكمل بطاقة الشبكة أو واجهة TUN الافتراضية إرسال الإطار، يؤدي مقاطعة العتاد إلى تحرير الذاكرة (kfree_skb)، مما يخفض عداد sk_wmem_alloc.
وقبل بناء حزم إرسال جديدة، يتحقق مكدس TCP مما إذا كان حجم البيانات قيد التداول يتجاوز حد TSQ المسموح به:
static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb, unsigned int factor)
{
unsigned int limit = max(2 * skb->truesize, sk->sk_pacing_shift);
limit = min_t(unsigned int, limit, sysctl_tcp_limit_output_bytes);
if (atomic_read(&sk->sk_wmem_alloc) > limit) {
set_bit(TSQ_THROTTLED, &tcp_sk(sk)->tsq_flags);
return true; /* كبح الإرسال مؤقتاً */
}
return false;
}
إذا تجاوزت الذاكرة المسجلة هذا السقف، يضع النظام راية TSQ_THROTTLED على المقبس ويوقف دفع الحزم الإضافية إلى الأسفل، مما يمنع أي اتصال منفرد من ملء طوابير بطاقة الشبكة بمفرده.
استدعاء الإيقاظ عند اكتمال الإرسال
عندما ينتهي مشغل العتاد من إرسال الإطار ويحرر الذاكرة عبر skb_destroy()، تفحص النواة ما إذا كان المقبس يحمل شارة TSQ_THROTTLED. وفي حال وجودها، يجدول النظام مهمة سريعة في طابور مهام المعالج (tsq_tasklet)، والتي تستدعي مباشرة دالة tcp_tsq_handler().
تعمل هذه الدالة على إزالة شارة التقييد وتستأنف عملية tcp_write_xmit() لإرسال الدفعة التالية من الحزم المقننة. ونظراً لأن هذه الدورة تكتمل في أجزاء من الميلي ثانية بالتزامن مع نبضات العتاد، تحافظ الاتصالات على الأداء الكامل لخط النقل مع إبقاء طوابير الانتظار في أدنى مستوياتها.
التكامل بين TSQ وتنظيم التدفق وخوارزمية Sch_FQ
تبلغ بنية TSQ أقصى فاعليتها التشغيلية عند ربطها بخاصية تنظيم التدفق (Packet Pacing) وجدولة الطوابير العادلة (sch_fq). يعمل تنظيم التدفق على توزيع إرسال الحزم بالتساوي على امتداد زمن الذهاب والإياب المقدر بدلاً من تفريغها في دفعات متتالية عند وصول إشعارات التأكيد ACK.
وتقوم نواة لينكس تلقائياً بحساب الحد الأقصى لـ TSQ بناءً على معدل تدفق الحزم المنظم للمقبس:
$$\text{TSQ Limit} = \max\left(2 \times \text{MSS}, \text{Pacing Rate} \times 1\text{ ms}\right)$$
على وصلة بسرعة 1 غيغابت في الثانية، تعادل حركة مرور مدتها 1 ميلي ثانية حوالي 125 كيلوبايت فقط من البيانات في الطابور. وعلى وصلة بسرعة 100 ميغابت في الثانية، يتقلص هذا الحد إلى نحو 12.5 كيلوبايت. وهكذا تتكيف طوابير TSQ تلقائياً مع السعة اللحظية لمسار الشبكة.
┌─────────────────────────┐
│ مقبس النقل TCP │
└────────────┬────────────┘
│ فحص sk_wmem_alloc
┌─────────────────────┴─────────────────────┐
│ │
sk_wmem_alloc <= Limit sk_wmem_alloc > Limit
│ │
▼ ▼
التمرير إلى sch_fq / Pacing تفعيل راية TSQ_THROTTLED
│ (إيقاف المقبس مؤقتاً)
▼ │
[ طابور جهاز مصغر للغاية ] │
│ │
▼ │
إرسال عتادي / واجهة TUN ───────── اكتمال الإرسال ────────────┘
kfree_skb()
عند تفعيل sch_fq، يمتلك كل مقبس طابوراً افتراضياً خاصاً به، وتضمن TSQ ألا يحتوي كل طابور إلا على القدر الضئيل الضروري لملء أنبوب الإرسال، مما يزيل تفاوت زمن الوصول (Jitter) بين التدفقات المتزامنة.
الأثر المباشر على شبكات VPN وواجهات TUN المشفرة
يمثل تضخم الذاكرة المؤقتة خطراً مضاعفاً في بنيات الشبكات الافتراضية الخاصة VPN. ففي الأنفاق المشفرة المعتادة، تعبر الحزم من واجهة افتراضية (tun0 أو wg0) قبل أن تصل إلى بطاقة الشبكة الفعلية.
معضلة التخزين المؤقت المزدوج
بدون TSQ، تعاني الأنفاق الافتراضية من مشكلة تكدس مضاعفة:
- تضخم الواجهة الافتراضية: يغمر تدفق TCP الداخلي طابور واجهة
tunأوwgبحزم ضخمة بانتظار التشفير والتغليف. - تضخم الواجهة المادية: يغمر مقبس UDP الخارجي حلقات إرسال بطاقة الشبكة الفعلية بحزم النفق المشفرة.
تتسبب هذه الطبقات المتراكمة في قفز زمن الاستجابة من 20 ميلي ثانية إلى أكثر من 350 ميلي ثانية أثناء التنزيل المكثف. كما أن فقدان أي حزمة في النفق الخارجي يجبر مكدس النقل الداخلي على إعادة الإرسال، فتظل الحزم الجديدة محتجزة خلف ميغابايتات من البيانات القديمة في الطابور الداخلي.
كيف توظف بنية RiceGuard هندسة TSQ
في البروتوكولات الحديثة مثل RiceGuard، تتكامل عمليات تغليف وتشفير الحزم بدقة مع نظام محاسبة الذاكرة في نواة لينكس. ومن خلال مواءمة حجم وحدات الإرسال القصوى (MTU) الافتراضية مع حدود التجزئة العتادية، وضبط سقف طوابير TSQ، تضمن منظومة RiceGuard ألا تحتجز واصفات النفق الافتراضي أكثر من وحدتي إرسال لكل تدفق نشط.
وعند دمج هذا التنسيق مع بنية التوجيه Core L3 VPN وتقنيات التمرير دون نسخ الذاكرة (zero-copy)، تتيح TSQ لحزم المكالمات الصوتية والبيانات التفاعلية تجاوز تدفقات التنزيل الكبيرة في غضون ميكروثوانٍ معدودة. فبدلاً من الانتظار لتفريغ طابور مشغل ضخم بسعة 4 ميغابايت، تجد الحزم الآنية طوابير شبه فارغة في كل مراحل المعالجة.
التحقق العملي وضبط إعدادات Sysctl في نظام لينكس
يمكن لمديري الأنظمة فحص وضبط متغيرات TSQ بسهولة من خلال سطر أوامر لينكس.
فحص وتعديل الحد الأقصى لطوابير TSQ
يتم التحكم في سقف حجم البيانات التي يسمح لـ TSQ بتجميعها لكل مقبس عبر واجهة sysctl:
# عرض القيمة الحالية للحد الأقصى (القيمة الافتراضية عادة 262144 بايت / 256 كيلوبايت)
sysctl net.ipv4.tcp_limit_output_bytes
ولتحسين خوادم بوابات VPN التي تخدم آلاف الاتصالات المتزامنة ذات التأخير المنخفض، يمكن ضبط هذه القيمة لتقليل استهلاك الذاكرة وتفادي أي تكدس:
# تعيين الحد الأقصى عند 128 كيلوبايت لبوابات الأنفاق الحساسة للتأخير
sudo sysctl -w "net.ipv4.tcp_limit_output_bytes = 131072"
مراقبة حالات كبح TSQ النشطة
توفر أداة الإحصاءات ss (Socket Statistics) مراقبة فورية لبيانات مقابس TCP لمعرفة ما إذا كانت خاصية كبح TSQ مفعلة حالياً:
# فحص المقاييس الداخلية لمقابس TCP النشطة على المنفذ 443
ss -tin '( dport = :443 or sport = :443 )'
وفي مخرجات الأمر، تمثل الحقول التالية مؤشرات هامة لأداء الطوابير:
wmem_alloc: إجمالي حجم ذاكرة الكتابة المحجوزة للحزم بانتظار إرسال العتاد.tsq: تظهر الإشارة إذا كان المقبس يخضع حالياً لتنظيم طوابير TCP الصغيرة.pacing_rate: معدل التدفق المنظم المحسوب بواسطة خوارزمية التحكم بالازدحام (مثل BBR).bytes_acked: إجمالي البيانات المستلمة والمؤكدة بنجاح دون الحاجة لإعادة الإرسال.
وعندما يبقى مقياس wmem_alloc ثابتاً دون 150 كيلوبايت مع بقاء سرعة الاتصال عند أعلى كفاءة، فإن ذلك يؤكد نجاح TSQ في منع تضخم الطوابير تماماً.
الخلاصة: ركيزة أساسية لشبكات الاتصال منخفضة التأخير
تعد طوابير TCP الصغيرة نقلة نوعية حاسمة في معمارية شبكات أنظمة التشغيل الحديثة. ومن خلال فرض قيود دقيقة مرتبطة بمعدل التدفق مباشرة عند طبقة النقل، استطاعت TSQ القضاء نهائياً على معضلة تضخم الذاكرة المؤقتة التي عانت منها أنظمة لينكس طويلاً.
وبالنسبة لشبكات VPN المشفرة فائقة الأداء، تحول TSQ المحولات الافتراضية من نقاط اختناق ترفع زمن الاستجابة إلى مسارات مرنة وسريعة. ومن خلال تكاملها مع جدولة الطوابير العادلة والبروتوكولات الحديثة، تضمن TSQ تدفقاً سلساً وتعايشاً متناغماً بين حركة البيانات الكثيفة والاتصالات التفاعلية عبر مختلف شبكات الاتصالات المعاصرة.



