Disturber
Disturber تونلی آزمایشی برای شبیهسازی شرایط نامطلوب شبکه در یک chain از WaterWall است. بدون نیاز به ابزار خارجی میتواند قطع اتصال، از دست رفتن payload، خرابی داده، تکرار، جابهجایی ترتیب، تأخیر و dead-hang ایجاد کند.
از این نود برای stress test تونلهایی استفاده کنید که باید روی مسیرهای ناپایدار تاب بیاورند؛ مانند mux، TCP-over-UDP، HTTP، TLS، packet transport، منطق اتصال مجدد و تونلهای سفارشی.
Disturber عمداً ترافیک را مختل میکند. برای تست، debug و سنجش پایداری مناسب است، نه عبور عادی ترافیک در محیط production.
جایگاه رایج
حالت ساده عبوری:
TesterClient -> Disturber -> TesterServer
در کنار transport مورد آزمایش:
TesterClient -> TunnelUnderTest -> Disturber -> PeerUnderTest -> TesterServer
یک تونل در هر دو جهت مسیر:
TesterClient -> Disturber -> TunnelClient -> ... -> TunnelServer -> Disturber -> TesterServer
Disturber socket جداگانهای ندارد. به next نیاز دارد و معمولاً در میانه یک chain از نوع stream یا packet قرار میگیرد.
این نود چه میکند؟
- تا زمانی که اختلالی از نوع بستن اتصال فعال نشود، callbackهای lifecycle را در همان جهت عبور میدهد.
- میتواند lineهای عادی را هنگام init فوراً ببندد.
- میتواند lineهای عادی را هنگام payload forwarding ببندد.
- میتواند payload را دور بیندازد یا یک نسخه اضافه از آن بسازد.
- میتواند بایتهای payload را خراب کند.
- میتواند یک payload را نگه دارد و بعداً آزاد کند تا رسیدن داده خارج از ترتیب شبیهسازی شود.
- میتواند payload را برای مدتی تصادفی در بازه تعیینشده به تأخیر بیندازد.
- میتواند یک جهت را وارد حالت dead-hang کند تا payloadها در سکوت دور ریخته شوند.
- در packet lineها، بهجای آزاد کردن packet line مربوط به worker از dead-hang استفاده میکند و قواعد lifetime آن را حفظ میکند.
مقدار پیشفرض همه فیلدهای chance برابر 0 است. بنابراین، بهجز تنظیم پیشفرض جهت، Disturber بدون تنظیم خاص مانند نودی شفاف و عبوری رفتار میکند.
نمونه تنظیم
تنظیم کامل:
{
"name": "disturber",
"type": "Disturber",
"settings": {
"disturb-upstream": true,
"disturb-downstream": true,
"chance_instant_close": 5,
"chance_middle_close": 2,
"chance_payload_corruption": 3,
"chance_payload_loss": 10,
"chance_payload_duplication": 2,
"chance_payload_out_of_order": 4,
"chance_payload_delay": 15,
"chance_connection_deadhang": 1,
"delay_min_ms": 50,
"delay_max_ms": 300
},
"next": "next-node"
}
فقط از دست رفتن packet:
{
"name": "loss",
"type": "Disturber",
"settings": {
"disturb-upstream": true,
"disturb-downstream": false,
"chance_payload_loss": 100
},
"next": "receiver"
}
فیلدهای لازم
فیلدهای سطح اصلی:
| فیلد | نوع | توضیح |
|---|---|---|
name | string | نام دلخواه نود که باید در فایل پیکربندی یکتا باشد. |
type | string | باید دقیقاً "Disturber" باشد. |
next | string | برای استفاده عملی لازم است. نود بعدی ترافیک upstream را میگیرد. |
settings اختیاری است. اگر آن را ننویسید، همه chanceها مقدار پیشفرض خواهند داشت.
تنظیمات اختیاری
کنترل جهتها:
| گزینه | نوع | پیشفرض | توضیح |
|---|---|---|---|
disturb-upstream | boolean | true | اعمال اختلال روی init و payload در جهت upstream. |
disturb-downstream | boolean | false | اعمال اختلال روی init و payload در جهت downstream. |
فیلدهای chance:
| گزینه | نوع | پیشفرض | توضیح |
|---|---|---|---|
chance_instant_close | درصد integer | 0 | احتمال بستن مسیر هنگام رسیدن init در جهت فعال. |
chance_middle_close | درصد integer | 0 | احتمال بستن هنگام مدیریت payload جهت فعال. |
chance_payload_corruption | درصد integer | 0 | احتمال تغییر دادن بایتهای payload پیش از ارسال. |
chance_payload_loss | درصد integer | 0 | احتمال دور انداختن payload فعلی. |
chance_payload_duplication | درصد integer | 0 | احتمال ساخت یک کپی اضافه از payload. |
chance_payload_out_of_order | درصد integer | 0 | احتمال نگه داشتن payload فعلی و آزاد کردن آن در حوالی payload بعدی. |
chance_payload_delay | درصد integer | 0 | احتمال به تأخیر انداختن payload فعلی. |
chance_connection_deadhang | درصد integer | 0 | احتمال قرار دادن جهت در dead-hang mode. |
فیلدهای delay:
| گزینه | نوع | پیشفرض | توضیح |
|---|---|---|---|
delay_min_ms | integer | 0 | کمترین تأخیر هنگام فعال شدن delay برای payload. مقادیر منفی به 0 محدود میشوند. |
delay_max_ms | integer | 0 | بیشترین تأخیر هنگام فعال شدن delay برای payload. مقادیر کمتر از delay_min_ms به همان مقدار محدود میشوند. |
احتمالها با roll100 تفسیر میشوند: مقادیر <= 0 هرگز رخ نمیدهند، مقادیر >= 100 همیشه رخ میدهند و مقادیر 1 تا 99 درصد احتمال را نشان میدهند.
رفتار جهتها
بهطور پیشفرض فقط مسیر upstream مختل میشود:
{
"disturb-upstream": true,
"disturb-downstream": false
}
اگر میخواهید مسیر پاسخ نیز مختل شود، disturb-downstream را true کنید. برای ایجاد اختلال فقط در downstream، مقدار disturb-upstream را false بگذارید.
اگر اختلال در یک جهت غیرفعال باشد، payload همان جهت بیواسطه عبور میکند:
| جهت | callback forwarding |
|---|---|
| upstream payload | tunnelNextUpStreamPayload |
| downstream payload | tunnelPrevDownStreamPayload |
Est، Pause و Resume در هر دو جهت بهصورت عادی عبور داده میشوند.
پردازش Payload
برای هر payload در جهتی که اختلال روی آن فعال است، Disturber موارد زیر را به ترتیب بررسی میکند:
- اگر جهت از قبل وارد dead-hang شده باشد، payload دور ریخته میشود.
chance_middle_closechance_payload_losschance_payload_duplicationchance_payload_corruption- آزاد کردن payload نگهداشتهشده برای ایجاد ترتیب نادرست
chance_payload_out_of_orderchance_payload_delaychance_connection_deadhang- ارسال عادی
بعضی بررسیها pipeline را همانجا متوقف میکنند. برای مثال، در payload loss بافر دور ریخته میشود و callback برمیگردد. Duplication میتواند با بررسیهای بعدی ترکیب شود، زیرا پیش از ادامه pipeline یک بافر اضافه میسازد.
جزئیات Disturbance
Instant Close
وقتی init از upstream برسد و disturb-upstream فعال باشد، chance_instant_close ممکن است بهجای فرستادن init به next، سمت قبلی را ببندد.
وقتی init از downstream برسد و disturb-downstream فعال باشد، chance_instant_close ممکن است بهجای فرستادن init به نود قبلی، سمت next را ببندد.
Middle Close
وقتی chance_middle_close روی یک line عادی رخ دهد، payload فعلی دور ریخته میشود، state محلی Disturber برای line از بین میرود و هر دو جهت finish میشوند.
Payload Loss
وقتی chance_payload_loss رخ دهد، بافر payload فعلی برای استفاده مجدد برگردانده میشود و داده عبور نمیکند.
Duplication
وقتی chance_payload_duplication رخ دهد، Disturber یک کپی از بافر میسازد و ارسال آن را در همان جهت زمانبندی میکند. بررسیهای بعدی همچنان میتوانند payload اصلی را تغییر دهند.
Corruption
وقتی chance_payload_corruption رخ دهد، چند بایت تصادفی از payload فعلی با XOR تغییر میکنند. برای payloadهای غیرخالی، پیادهسازی حدود ده درصد داده را خراب میکند و دستکم یک بایت تغییر مییابد.
Out-of-Order Delivery
Disturber برای هر line برای هر جهت حداکثر یک payload نگه میدارد.
وقتی out-of-order رخ دهد و payload نگهداشتهشدهای وجود نداشته باشد، payload فعلی ذخیره میشود و فوراً عبور نمیکند. با رسیدن payload بعدی، داده نگهداشتهشده در حوالی آن آزاد میشود تا یک جابهجایی ساده در ترتیب ایجاد شود.
اگر state مربوط به line در حالی از بین برود که payloadی هنوز نگه داشته شده است، بافر آن برای استفاده مجدد برگردانده میشود.
Delay
وقتی chance_payload_delay رخ دهد، تأخیری تصادفی میان delay_min_ms و delay_max_ms انتخاب میشود. سپس ارسال payload روی همان line برای زمان بعد برنامهریزی میشود.
Dead-Hang
وقتی chance_connection_deadhang رخ دهد، جهت مورد نظر dead-hung علامت میخورد. Payload فعلی دور ریخته میشود، ساختار line باقی میماند و payloadهای بعدی در همان جهت بیسروصدا حذف میشوند.
این حالت یک اتصال را شبیهسازی میکند که هنوز زنده به نظر میرسد اما پیشرفتی نمیکند.
رفتار packet-line
Disturber قواعد packet line را در نظر میگیرد.
برای lineهای اتصال عادی، اختلالهایی که اتصال را میبندند میتوانند Finish بفرستند و state مخصوص آن line را در تونل از بین ببرند. اما Disturber در runtime، packet line مربوط به worker را آزاد نمیکند. در عوض، instant-close و middle-close جهت آسیبدیده را dead-hung میکنند و بدون فراخوانی lineDestroy() ادامه میدهند.
به این ترتیب هم قواعد lifetime مربوط به packet line در WaterWall حفظ میشود و هم میتوان سناریوهای packet loss و blackhole را آزمایش کرد.
نکتهها
- ترکیب چند chance با مقدار بالا میتواند ترافیک بسیار آشفتهای بسازد.
- مقدار
chance_payload_duplication = 100برای تست پروتکلهای مقاوم در برابر داده تکراری مفید است، اما میتواند حجم ترافیک را بهسرعت چند برابر کند. - رفتارهای delay و out-of-order از callbackهای زمانبندیشده استفاده میکنند و میتوانند باگهای re-entrancy و lifetime را در تونلهای اطراف آشکار کنند.
- این نود framing اضافه نمیکند و
required_padding_left = 0دارد. - در حال حاضر callback مربوط به API فقط پیام API را میگیرد و بافرش را برای استفاده مجدد برمیگرداند؛ امکان تنظیم در runtime وجود ندارد.