הסיבה לכך ששידור חוזר ב-TCP עוצר תקשורת עם מצלמה תעשייתית, ואיך מבודדים אותה

· עודכן בתאריך: · · TCP, רשתות, חקירת תקלות, פיתוח Windows, מצלמה תעשייתית

בתקשורת עם מצלמות תעשייתיות ובבקרת התקנים, התופעה הכי מטרידה היא כשבממוצע הכול מהיר, אבל לפעמים יש עצירה של כמה שניות. שיעור השחזור נמוך, ורוב הזמן שום דבר לא קורה, כך שה-UI, התהליכונים, ה-GC, ה-SDK של המצלמה, ה-NIC והמתג — כולם מתחילים להיראות קצת חשודים.

במקרה הזה מדובר בתקשורת TCP בין אפליקציה ששולטת במצלמה תעשייתית לבין ה-host, שבה לעיתים נדירות התקשורת נעצרת לכמה שניות בלבד. כשבדקנו, התברר שהאשם אינו עצירה של האפליקציה, אלא המתנה לשידור חוזר ב-TCP שנובעת מאובדן מנות. יתרה מכך, הפעלה של פונקציית חותמות הזמן מסדרת RFC1323 (בסיווג הנוכחי — RFC 7323) אפשרה לצמצם את זמן ההמתנה למינימום במערכת הזו.

שמות ההתקנים, התצורה והמספרים הוכללו, אבל אופן החשיבה ישים ישירות בעבודה בפועל.

תוכן עניינים

  1. קודם כול, המסקנה (במשפט אחד)
  2. איך התסמין נראה
    • 2.1. האפליקציה חיה, אבל התגובה נעצרת לכמה שניות
    • 2.2. בתדירות נמוכה, קשה לראות רק מהלוגים
  3. מה קרה בפועל (בתרשימים)
    • 3.1. מאובדן מנות להמתנה לשידור חוזר
    • 3.2. העצירה בסדר גודל של שניות תאמה לצורת ה-RTO
  4. נקודות שנבדקו בחקירה
    • 4.1. קודם כול, לשלול גורמי עצירה בתוך האפליקציה
    • 4.2. אימות שידור חוזר בלכידת מנות
    • 4.3. בדיקת אפשרויות ה-TCP שסוכמו
  5. הסיבה לכך שחותמות הזמן של RFC1323 עוזרות
    • 5.1. חותמות הזמן נועדו ל-RTTM ול-PAWS
    • 5.2. אפשר להסיר את העמימות במדידת RTT בעת שידור חוזר
    • 5.3. הסיבה לכך שבמקרה הזה הצטמצם זמן ההמתנה
  6. הפעולות שבוצעו בפועל
    • 6.1. הפעלת חותמות הזמן
    • 6.2. בדיקת TSopt ב-SYN /‏ SYN-ACK
    • 6.3. איפה לבדוק כשזה עדיין לא עוזר
  7. נקודות בדיקה ב-Wireshark
  8. חלוקה גסה בין המצבים
  9. סיכום
  10. מקורות

מפת הידע של המאמר

מאמר שמפרק את הסיבה לכך שבאפליקציית בקרה למצלמה תעשייתית, לעיתים רחוקות התקשורת נעצרת לכמה שניות בלבד. הסיבה לא הייתה עצירה של האפליקציה, אלא המתנה לשידור חוזר — אובדן חבילה מנע חזרת ACK, ו-TCP המתין לפקיעת טיימר השידור החוזר (RTO). מכיוון ש-RTO מוכפל בכל כישלון החל מערך התחלתי של שנייה אחת, בתנאים גרועים זה נראה כעצירה בסדר גודל של כמה שניות. הפעלת אופציית חותמת הזמן של TCP (‏RFC1323/‏RFC7323) מסירה את המגבלה שאלגוריתם Karn אוסר — מדידת RTT מתוך מקטע ששודר מחדש — וכך מקטינה את משך הזמן שבו ה-RTO נשאר שמרני יתר על המידה, אבל זה לא מנגנון שמבטל את אובדן החבילה עצמו. בדיקת השידור החוזר וזמן ההמתנה ב-Wireshark, ואימות משא ומתן ה-TSopt ב-SYN/‏SYN-ACK, הם הבסיס לפירוק הבעיה.

מפת הידע של שידור חוזר ב-TCP ואופציית חותמת הזמן של RFC1323תרשים שמראה איך אובדן חבילה גורם לשידור חוזר ב-TCP ולהמתנה ל-RTO, שנראית כעצירת תקשורת של כמה שניות; איך אופציית חותמת הזמן של TCP מסירה את המגבלה של אלגוריתם Karn ומקטינה את חוסר הוודאות במדידת ה-RTT בזמן שידור חוזר; והקשר לשלבי הבדיקה ב-Wireshark.עלול לגרום למחייבמשתמש בעלול לגרום לנבדק באמצעותנבדק באמצעותנבדק באמצעותמשתמש במשתמש במצמצםמצמצםמצמצםמונעמחייבעלול לגרום למחייבמוגדר באמצעותנבדק באמצעותמשתמש בשידור חוזר ב-TCP‏ (TCP Retransmission)‏RTO (טיימר השידור החוזר)אפשרות חותמות הזמן של TCPאובדן מנות‏RTT (זמן הלוך-ושוב)עצירות תקשורת לסירוגין של שניות בודדותWireshark‏RTTM (מדידת זמן הלוך-ושוב)‏PAWS (הגנה מפני מחזור מספרי הרצף)האלגוריתם של Karnעמימות מדידת ה-RTT בעת שידור חוזר‏fast retransmit (שידור חוזר מהיר)‏Duplicate ACK (אישור כפול)לחיצת היד המשולשת של TCPהגדרת חותמות הזמן של TCP ב-Windows

בתרשים, קו מלא מציין קשר שמתקיים תמיד וקו מקווקו מציין קשר מותנה (תנאי ההתקיימות מפורטים בהסבר של כל קשר בעמוד המפורט). רשימת כל הקשרים (סך הכול 19, עם אסמכתה ורמת ודאות) והגדרות המושגים המרכזיים מרוכזות בעמוד המפורט של מפת הידע (ביפנית). נתונים: JSON-LD / Turtle

1. קודם כול, המסקנה (במשפט אחד)

  • תקשורת TCP שנעצרת לעיתים נדירות לכמה שניות עשויה להיות לא עצירה של האפליקציה, אלא המתנה לשידור חוזר לאחר אובדן מנות
  • אם בלכידת המנות רואים Retransmission ופער זמן גדול, ומשך העצירה תואם את אופן ההמתנה של ה-RTO, זה חשוד מאוד
  • אפשרות חותמות הזמן של TCP קיימת למדידת RTT ול-PAWS, והיא גם מאפשרת להסיר את העמימות במדידת RTT בעת שידור חוזר
  • במקרה הזה, הפעלת פונקציית חותמות הזמן מסדרת RFC1323 צמצמה את הזמן שבו הערכת ה-RTO נשארת ישנה ושמרנית מדי, וכך צומצמה העצירה בסדר גודל של שניות למינימום
  • עם זאת, זו אינה קסם שמסלק את האובדן עצמו. יש לבחון בנפרד את השכבה הפיזית, ה-NIC, המתג, ציוד הביניים, הדרייברים ותכנון ה-buffer

בקיצור, אם הזהות האמיתית של “עצירה של כמה שניות מדי פעם” היא זמן המתנה בתוך ה-TCP, אז מאמץ שמושקע רק בניסיונות חוזרים (retry) באפליקציה מפספס את הליבה. מהיר יותר להסתכל קודם על ה-wire ולקבוע אם מדובר בהמתנה לשידור חוזר.

זרימת המסקנה של המאמרתרשים המראה שבתקשורת TCP שנעצרת לעיתים נדירות לכמה שניות יש להסתכל קודם על ה-wire ולקבוע אם מדובר בהמתנה לשידור חוזר, שאז לעיתים אפשר לצמצם את ההמתנה בעזרת timestamps, אבל חקירת מקור האובדן עצמו נדרשת בנפרד.תקשורת TCP שנעצרת מדי פעםקודם כול, הסתכלות על wireקביעה אם זו המתנה לשידור חוזרtimestamps עשויות לצמצם המתנהחקירת מקור האובדן נדרשת בנפרד

איור 1: לפני שמתאמצים על ניסיונות חוזרים באפליקציה, קודם קובעים ב-wire “איפה ממתינים”.

בהמשך יופיעו רצף של קיצורים מעולם ה-TCP. עבור מפתחי Windows שלא מתמחים ברשתות, הנה סיכום מראש. אם תשלטו רק בזה, לא תיתקעו בהמשך.

מונח שם מלא משמעות
ACK Acknowledgment אישור קבלה. מנגנון שמודיע לצד השני “קיבלתי עד כאן”
RTT Round-Trip Time זמן הלוך-ושוב. הזמן משליחה ועד שחוזר ה-ACK
RTO Retransmission Timeout טיימר השידור החוזר. אם ה-ACK לא חוזר בתוך הזמן הזה, מתבצע שידור חוזר. הוא מחושב מהערכת ה-RTT
RTTM Round-Trip Time Measurement מדידת ה-RTT. אחת ממטרות פונקציית חותמות הזמן
PAWS Protect Against Wrapped Sequences הגנה מפני מצב שבו מספר הרצף עושה סיבוב שלם (wrap). המטרה השנייה של פונקציית חותמות הזמן
TSopt TCP Timestamps Option אחת האפשרויות שמצורפות לכותרת ה-TCP. סוג 8, אורך 10 בייטים, ונושאת שני ערכים
TSval Timestamp Value הערך שהצד השולח מכניס — הזמן לפי השעון שלו
TSecr Timestamp Echo Reply השדה שמחזיר בדיוק את ה-TSval שהתקבל. כך אפשר לדעת “לאיזו שליחה שייך האישור הזה”
SACK Selective Acknowledgment מנגנון שמאפשר לצד המקבל להודיע באופן פרטני “אילו טווחים התקבלו”
Dup ACK Duplicate ACK מצב שבו מתקבלים כמה ACK החוזרים על אותו מספר רצף. זה סימן לפער באמצע
fast retransmit מנגנון שמבצע שידור חוזר בלי להמתין לתפוגת ה-RTO, ברגע שמצטבר מספר מסוים של Dup ACK. ברירת המחדל ב-Windows היא “לאחר קבלת שלושה ACK לאותו מספר רצף (הראשון ועוד שניים כפולים)”
האלגוריתם של Karn הכלל שאומר שאסור לקחת מדגם RTT מקטע שעבר שידור חוזר, כי לא ידוע לאיזו שליחה שייך ה-ACK

2. איך התסמין נראה

2.1. האפליקציה חיה, אבל התגובה נעצרת לכמה שניות

מה שמבלבל בהתחלה הוא שהאפליקציה כולה לא נראית תקועה.

  • ה-UI לא מת לגמרי
  • התהליך (process) לא קרס
  • ה-CPU גם לא תקוע
  • אבל רק התגובה לפקודות בקרת המצלמה נעלמת מדי פעם לכמה שניות

קשה להבחין בין תסמינים כאלה לבין קיפאון (deadlock) או לולאה אינסופית בתוך האפליקציה. יתרה מכך, בבקרת התקנים עצירה בודדת של כמה שניות מתקבלת מיד כרושם של עצירת קו הייצור. גם אם הממוצע נראה נקי, החוויה בשטח גרועה למדי.

2.2. בתדירות נמוכה, קשה לראות רק מהלוגים

מה שמטריד בסוג הזה של תקלה הוא שהתדירות נמוכה. ההתנהגות היא בערך פעם בשעה, פעם בחצי יום, או רק כשכמה תנאים מתלכדים יחד.

אם עוקבים אחר זה רק דרך הלוגים, בדרך כלל קורה כך:

  • אצל האפליקציה, הלוג נעצר במצב “נשלח” ואז “לא חוזר”
  • בצד המקבל, הלוג נראה כאילו “שום דבר לא הגיע”
  • באותו פרק זמן קורים במקרה גם אירועים אחרים, והחשוד מתפזר

במצב כזה, ניסיון לשחזר את הקשר הסיבתי רק מלוגי האפליקציה נוטה להיתקע בבוץ. מהיר יותר לרדת שלב אחד עד שכבת התקשורת.

המבנה שבו הלוגים לבדם לא קובעים את החשודתרשים המראה שלוג האפליקציה נעצר במצב שנשלח ולא חוזר, לוג הצד המקבל נראה כאילו לא הגיע דבר, ואירועים אחרים באותו פרק זמן מפזרים את החשוד, ולכן עדיף לרדת עד שכבת התקשורת ולא לנסות לשחזר את הסיבתיות רק מלוגי האפליקציה.לוג האפליקציה: נשלח ולא חוזרהחשוד מתפזר ונתקעים בבוץלוג הצד המקבל: לא הגיע דבראירוע אחר באותו פרק זמןירידה שלב אחד עד שכבת התקשורת

איור 2: עצירה בתדירות נמוכה שעוקבים אחריה רק בלוגים נתקעת בבוץ. מהיר יותר להסתכל דרך המנות.

3. מה קרה בפועל (בתרשימים)

3.1. מאובדן מנות להמתנה לשידור חוזר

התרחיש הפעם פשוט. מנה אבדה איפשהו בדרך, הצד השולח המתין ל-ACK, וכשזה לא הגיע, הוא המתין לתפוגת ה-RTO ואז ביצע שידור חוזר.

מעבר מאובדן מנה להמתנה לשידור חוזרתרשים רצף המראה שפקודת בקרה נשלחת מהמארח, המנה אובדת ברשת, המארח ממתין לתפוגת ה-RTO, מבצע שידור חוזר, והמנה המשודרת מחדש מגיעה למצלמה ומקבלת ACK שמסמן חידוש התקשורת.צד המצלמההרשתאפליקציית ה-Hostצד המצלמההרשתאפליקציית ה-Hostכאן מתרחש האובדןה-ACK לא מגיע, ולכן ממתיניםהשחזור של הבקשה הזו כולל המתנה ל-RTOכאן התקשורת מתחדשתפקודת בקרה (Seq=N)שידור חוזר של פקודת הבקרההמנה המשודרת מחדש מגיעהACKACK

איור 3: כשמנה אובדת, ה-ACK לא חוזר וממתינים לתפוגת ה-RTO לפני שידור חוזר. מבחינת האפליקציה, פרק הזמן הזה נראה כ”עצירה של כמה שניות”.

מבחינת האפליקציה זה נראה כ”עצירה של כמה שניות”, אבל מבחינת TCP זה פשוט “ה-ACK עדיין לא הגיע, ולכן ממתינים לתפוגת טיימר השידור החוזר”. זה לא מרשים, אבל עצירה מהסוג הזה שכיחה למדי.

תקשורת הבקרה במקרה הזה כללה בעיקר בקשות/תגובות (request/response) קטנות, ובכל חילופין לא נשלחה כמות גדולה של נתונים ללא ACK. לכן במקום שיצטברו מספיק Duplicate ACK כדי להפעיל fast retransmit, המבנה נטה לחשוף קודם המתנה ל-RTO.

הסיבה לכך שבתקשורת בקרה נחשפת בקלות המתנה ל-RTOתרשים המראה שבתקשורת בקרה המבוססת בעיקר על request/response קטנים יש מעט נתונים ללא ACK, לכן Duplicate ACK לא מצטברים מספיק, קשה להפעיל fast retransmit, ולכן נחשפת המתנה ל-RTO.בעיקר request/response קטניםמעט נתונים ללא ACKDup ACK לא מצטברים מספיקקשה להפעיל fast retransmitנחשפת המתנה ל-RTO

איור 4: בשונה מתקשורת שזורמים בה נתונים רבים, אובדן בתקשורת בקרה נוטה להסתיים בהמתנה לתפוגת RTO.

3.2. העצירה בסדר גודל של שניות תאמה לצורת ה-RTO

ההמתנה לשידור חוזר ב-TCP שמרנית באופייה, גם אם יש הבדלים בין מימושים. לפי RFC 6298, ה-RTO ההתחלתי מבוסס על שנייה אחת: אם תוצאת החישוב קטנה מכך, מעגלים כלפי מעלה ל-1 שנייה, ועם כל תפוגה (timeout) מכפילים אותו.

מחזור ההכפלה של RTO עד לחידוש התקשורתתרשים המראה שאובדן מנה גורם להיעדר ACK, שמוביל להמתנה ל-RTO ואז לשידור חוזר; אם ה-ACK חוזר התקשורת מתחדשת, ואם לא, ה-RTO מוכפל והמחזור חוזר על עצמו.כןלאאובדן מנהה-ACK לא מגיעהמתנה ל-RTOשידור חוזרה-ACK חוזר?התקשורת מתחדשתהכפלת ה-RTO

איור 5: ה-RTO מוכפל בכל פעם שה-ACK לא חוזר. צורת ההמתנה של שנייה, שתי שניות, ארבע שניות נובעת מהמנגנון הזה.

לכן, גם ברגעים שבהם היינו רוצים שהעניין ייגמר תוך מאות מילישניות, בתנאים גרועים אפשר לראות דפוס המתנה כמו שנייה, שתי שניות, ארבע שניות. ה”עצירה הנדירה של כמה שניות” במקרה הזה תאמה את הצורה הזו בצורה די ישירה.

4. נקודות שנבדקו בחקירה

4.1. קודם כול, לשלול גורמי עצירה בתוך האפליקציה

בלי לקבוע מראש ש-TCP הוא האשם, קודם שללנו את הגורמים האופייניים בצד האפליקציה.

מה נבדק הסיבה לבדיקה המסקנה במקרה הזה
ת’רד ה-UI /‏ ת’רדי עבודה בדיקת תקיעה (hang) או המתנה הדדית לא היה הגורם העיקרי
ניצול CPU בדיקת עיכוב עיבוד עקב עומס גבוה גם בזמן העצירה ה-CPU לא היה תקוע
GC / לחץ זיכרון בדיקת השהיה זמנית צורת זמן ההשהיה לא תאמה
קריאות ל-SDK של המצלמה בדיקת המתנה בתוך ה-SDK לא תאם לעיכוב שנצפה ב-wire
לכידת מנות בדיקת שידור חוזר בשכבת התקשורת כאן נראה חוט הסיבה האמיתי

החשוב כאן הוא לא לקבוע את החשוד רק לפי זמני לוג האפליקציה. באפליקציות בקרת התקנים, המתנה בשכבה עליונה לפעמים רק משקפת המתנה בשכבה נמוכה יותר.

סדר הבידוד ששולל קודם גורמים בתוך האפליקציהתרשים המראה שבמקום לקבוע מראש ש-TCP הוא האשם, קודם שוללים גורמי עצירה אופייניים בתוך האפליקציה כמו תהליכונים, CPU, GC ו-SDK של המצלמה, ורק אז בודקים שידור חוזר בשכבת התקשורת באמצעות לכידת מנות.שלילת תהליכונים, CPU, GC ו-SDK תחילהבדיקת שכבת התקשורת בלכידת מנותחוט הסיבה של השידור החוזר מתגלהלא לקבוע חשוד רק לפי זמני הלוג

איור 6: לא לקבוע מראש. קודם שוללים גורמים אופייניים בתוך האפליקציה, ורק אז יורדים אל ה-wire.

4.2. אימות שידור חוזר בלכידת מנות

כשלכדנו את המנות, ראינו TCP Retransmission בדיוק בפרק הזמן של העצירה, ומצאנו שממש לפני כן ה-ACK לא חזר.

אלה הנקודות שכדאי לבדוק:

  • האם מופיע שידור חוזר לאותו Seq
  • האם פער הזמן עד השידור החוזר תואם את משך העצירה
  • האם זה נראה כהמתנה לתפוגת RTO ולא כ-Dup ACK או Fast Retransmission
  • האם החיבור הבעייתי מופיע תמיד באותו tcp.stream

כשהנקודות האלה מתיישרות, ההשערה ש”ה-TCP ממתין לשידור חוזר” — ולא ש”האפליקציה נעצרת” — מתחזקת מאוד.

נקודות הבדיקה שקובעות המתנה לשידור חוזרתרשים המראה ששלוש נקודות בדיקה — שידור חוזר לאותו Seq, פער זמן שתואם את משך העצירה, והופעה שנראית כהמתנה לתפוגת RTO ולא כ-fast retransmission — כשמתיישרות מחזקות את ההשערה שה-TCP ממתין לשידור חוזר ולא שהאפליקציה נעצרת.שידור חוזר לאותו Seqה-TCP ממתין לשידור חוזרפער זמן שתואם את משך העצירהנראה כהמתנה לתפוגת RTOהאפליקציה לא נעצרת

איור 7: אם שלוש הנקודות האלה מתיישרות, ההשערה עוברת מ”האפליקציה נעצרת” ל”ה-TCP ממתין לשידור חוזר”.

4.3. בדיקת אפשרויות ה-TCP שסוכמו

הדבר הבא שבדקנו היה ה-SYN /‏ SYN-ACK בתחילת החיבור. חותמות הזמן מסוכמות (negotiated) בלחיצת היד המשולשת (3-way handshake) של חיבור ה-TCP, ואם ה-TSopt לא מופיע שם, הוא לא ישמש באותו חיבור.

סיכום TSopt בלחיצת היד המשולשתתרשים רצף המראה שהמארח שולח SYN עם TSopt אפשרי, המצלמה מחזירה SYN/ACK עם TSopt אפשרי, ורק אחרי שהסיכום הצליח ניתן להשתמש ב-TSopt בקטעים הבאים.צד המצלמההמארחצד המצלמההמארחרק אחרי שהסיכום הזה מצליח, אפשר להשתמש ב-TSopt בקטעים הבאיםSYN + TSopt?SYN/ACK + TSopt?ACK

איור 8: חותמות הזמן מסוכמות בלחיצת היד המשולשת. אם אין TSopt ב-SYN /‏ SYN-ACK, הן לא ישמשו באותו חיבור.

אם משנים רק את הגדרות מערכת ההפעלה בלי לבדוק את זה, קורה תקלה שקטה נוספת: “הפעלתי, אבל זה לא עובד”. העובדה שנראית ב-wire חזקה יותר מערך ההגדרה.

5. הסיבה לכך שחותמות הזמן של RFC1323 עוזרות

בפועל השם “חותמות הזמן של RFC1323” עדיין נפוץ, אבל הסיווג העדכני הוא RFC 7323. במאמר הזה אנחנו כותבים RFC1323 בהתאם למקובל, אך הכוונה היא לאפשרות חותמות הזמן של TCP.

5.1. חותמות הזמן נועדו ל-RTTM ול-PAWS

אפשרות ה-timestamps של TCP משמשת בעיקר לשתי מטרות:

  • RTTM (מדידת זמן הלוך-ושוב)
  • PAWS (הגנה מפני מחזור מספרי הרצף)

מה שעזר במקרה הזה הוא הצד של RTTM. הצד השני מחזיר את TSval של הקטע שנשלח בתוך TSecr של ה-ACK, וכך הצד השולח יכול למדוד את ה-RTT בפירוט ובדיוק רבים יותר.

שתי המטרות של אפשרות ה-timestampsתרשים המראה שאפשרות ה-timestamps של TCP משמשת לשתי מטרות, RTTM שהיא מדידת זמן הלוך-ושוב ו-PAWS שהיא הגנה מפני מחזור מספרי הרצף, ושבמקרה הזה מה שעזר היה הצד של RTTM.timestamps optionRTTM (מדידת זמן הלוך-ושוב)PAWS (הגנה מפני מחזור מספרי רצף)זה מה שעזר במקרה הזהמדידה בהחזרת TSval בתוך TSecr

איור 9: למטרת חותמות הזמן שני צדדים — RTTM ו-PAWS. במקרה הזה מה שעזר היה צד מדידת ה-RTT.

5.2. אפשר להסיר את העמימות במדידת RTT בעת שידור חוזר

כשמתרחש שידור חוזר, בלי חותמות זמן נוצרת עמימות: “האם ה-ACK הזה שייך לשליחה הראשונה או לשידור החוזר?” זו בדיוק הנקודה שהאלגוריתם של Karn מתייחס אליה.

לפי RFC 6298, אסור לקחת מדגם RTT מקטע שעבר שידור חוזר, מכיוון שלא ידוע לאיזו שליחה שייך ה-ACK. אבל כשקיימת אפשרות ה-timestamps, אפשר להסיר את העמימות הזו: הסתכלות על TSecr שמגיע בתוך ה-ACK מאפשרת לזהות איזה קטע, עם איזה TSval, הגיע.

זיהוי השליחה שאליה שייך ה-ACK באמצעות TSecrתרשים רצף המראה שקטע עם TSval=1000 אובד, השולח ממתין ל-ACK, מבצע שידור חוזר עם TSval=2000, ומקבל ACK עם TSecr=2000 שמאפשר לזהות בוודאות לאיזו שליחה הוא שייך.הצד המקבלהצד השולחהצד המקבלהצד השולחהקטע הזה אובדה-ACK לא מגיע, ולכן ממתיניםאפשר לזהות לאיזו שליחה זו התגובהSeq=N, TSval=1000שידור חוזר עם Seq=N, TSval=2000ACK, TSecr=2000

איור 10: הסתכלות על TSecr מאפשרת לזהות אם ה-ACK הוא תגובה לשליחה הראשונה או לשידור החוזר.

זה הליבה של השיפור במקרה הזה.

5.3. הסיבה לכך שבמקרה הזה הצטמצם זמן ההמתנה

במקרה הזה אובדן מנות התרחש מדי פעם, ובכל פעם ההערכות של RTT/RTO נטו להיות שמרניות. הפעלת חותמות הזמן מקלה על עדכון הערכת ה-RTT גם ברגעים שכוללים שידור חוזר, וכך מצטמצם הזמן שבו הערכת ה-RTO ממשיכה להתנפח בלי עדכון.

זו נקודה שקל לדלג עליה בקפיצה, אז נפרק אותה בזהירות רבה יותר.

קודם כול, הגבול התחתון של ה-RTO עצמו לא משתנה בהתאם לקיום או היעדר חותמות זמן. RFC 6298 קובע שאם ה-RTO המחושב קטן משנייה, יש לעגל אותו כלפי מעלה לשנייה. יש מימושים עם גבול תחתון משלהם — ב-Windows זהו MinRtoMs שמופיע ב-Get-NetTCPSetting (בטווח של 20 עד 300 מילישניות, בקפיצות של 10 מילישניות). כלומר, זה לא ש”הגבול התחתון ירד כי הוספנו חותמות זמן”.

מה שבאמת עוזר קורה שלב לפני כן. RFC 6298 קובע שלושה דברים:

  1. בכל פעם שטיימר השידור החוזר פוקע, ה-RTO מוכפל (נסיגה מעריכית / exponential backoff)
  2. ה-RTO שהוכפל חוזר לערכו כשמתקבלת מדידת RTT חדשה
  3. אותה “מדידת RTT חדשה” מתקבלת רק כשנתונים שלא עברו שידור חוזר נשלחו וקיבלו ACK

יתרה מכך, לפי האלגוריתם של Karn, אסור לקחת מדגם RTT מקטע שעבר שידור חוזר. אבל כשמשתמשים באפשרות ה-timestamps, המגבלה הזו מוסרת, מכיוון שכפי שהוסבר בסעיף 5.2, הסתכלות על TSecr מאפשרת לזהות לאיזו שליחה שייך ה-ACK.

כשמסדרים את זה ברצף, החוט מתגלה. במערכת שבה אובדן מתרחש מדי פעם, בלי חותמות זמן קשה שהתנאים 2 ו-3 יתקיימו יחד, ולכן נשאר זמן ארוך שבו ה-RTO המוכפל לא חוזר לערכו על בסיס מדידה בפועל. אם באותו מצב מגיע אובדן נוסף, ההמתנה מתחילה לא משנייה אלא משתי שניות או ארבע שניות. כשיש חותמות זמן, אפשר למדוד מחדש גם בקטעים הכוללים שידור חוזר, כך שה”זמן שבו לא חוזרים לערך” מתקצר — וזה בדיוק המסלול שעבד במקרה הזה.

התנאים לחזרת ה-RTO המוכפל ואופן הפעולה של חותמות הזמןתרשים המראה שבכל תפוגה ה-RTO מוכפל וחוזר לערכו כשמתקבלת מדידת RTT חדשה, אך המדידה מתקבלת רק מ-ACK על נתונים שלא עברו שידור חוזר, ולכן כשחותמות הזמן מסירות את המגבלה הזו וניתן למדוד גם בקטעי שידור חוזר, מתקצר הזמן שבו ה-RTO המוכפל לא חוזר לערכו.הכפלת ה-RTO בכל תפוגהחזרה לערך עם מדידת RTT חדשההמדידה רק מ-ACK על נתונים שלא שוגרו מחדשtimestamps מאפשרות מדידה גם בשידור חוזריותר הזדמנויות למדידה מחדשמתקצר הזמן שבו ה-RTO המוכפל לא חוזר

איור 11: הליבה של אופן הפעולה היא לא ירידה של הגבול התחתון, אלא חזרה מהירה יותר של ה-RTO המוכפל על סמך מדידה בפועל.

נכתוב את זה בכנות: במאמר הזה לא נאספו ערכי RTO בפועל אחרי השיפור. מה שידוע הוא שהעצירות בסדר גודל של שניות ירדו לרמה שלא מהווה בעיה בשטח. אם רוצים להראות את האפקט במספרים, הדרך הקצרה ביותר היא להשתמש במסנני התצוגה מפרק 7 ובעמודה Time delta from previous displayed packet כדי לרכז את התפלגות פערי הזמן עד לשידור חוזר, לפני ואחרי.

במילים אחרות, מה שנעשה כאן אינו קסם שמאיץ את ה-TCP, אלא צמצום הזמן שבו ה-TCP ממשיך “לחכות ולראות” יותר מהנדרש.

כמובן, גם RFC 7323 לא טוען ש”יותר מדגמי RTT פותרים הכול בצורה נקייה”. יש היבטים שבהם התרומה לאופטימיזציה של ה-RTO מוגבלת. אבל היכולת להסיר את העמימות בעת שידור חוזר היא נקודה שיכולה לעבוד טוב במערכות כמו זו שתוארה כאן.

יש גם נקודות לתשומת לב:

  • זה תלוי בחלקו במימוש ה-TCP stack
  • חותמות זמן בלבד לא מסלקות את אובדן המנות עצמו
  • אם השכבה הפיזית או ציוד הביניים לקויים, הסיבה השורשית נמצאת במקום אחר
  • כדאי לבדוק בנפרד גם SACK, דרייבר ה-NIC, הגדרות offload ובעיות בצד המתג

עם זאת, במערכות שבהן “האובדן לא אפס” אך “מה שכואב באמת זו ההמתנה בסדר גודל של שניות” — כמו במקרה הזה — זה יכול לעזור באופן משמעותי.

6. הפעולות שבוצעו בפועל

6.1. הפעלת חותמות הזמן

כפתרון, וידאנו ששני קצות החיבור יכולים לסכם את אפשרות ה-timestamps. במערכות Windows זה לפעמים מטופל כאפשרות RFC 1323, והוא מושפע מהגדרות מערכת ההפעלה והרשת.

נכתוב את השלבים המדויקים. קודם כול, בודקים מה המצב הנוכחי:

netsh interface tcp show global

בפלט מופיע פריט של חותמות זמן RFC 1323, ובודקים אם הוא מופעל. כדי להפעיל, בשורת פקודה עם הרשאות מנהל:

netsh interface tcp set global timestamps=enabled

עבור timestamps אפשר לציין שלושה ערכים: disabled / enabled / default, כאשר default מחזיר לברירת המחדל של המערכת.

כדי לבדוק ולהגדיר דרך PowerShell:

Get-NetTCPSetting | Select-Object SettingName, Timestamps, MinRtoMs, InitialRtoMs
Set-NetTCPSetting -SettingName InternetCustom -Timestamps Enabled

עבור Timestamps אפשר לציין Enabled / Disabled. ה-SettingName שניתן לשנות משתנה לפי גרסת Windows, ולכן לא כדאי להריץ Set- ישר — קודם יש לבדוק עם Get-NetTCPSetting אילו שמות קיימים בפועל. העברת שם שלא קיים תעצור את הפעולה שם.

בסביבות ישנות, אם בודקים ישירות דרך הרישום (registry), מדובר בערך Tcp1323Opts (מסוג REG_DWORD) תחת המפתח הבא:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

המשמעות של הערכים: 0 — אפשרויות RFC 1323 מבוטלות, 1 — window scaling בלבד, 2 — timestamps בלבד, 3 — שניהם מופעלים. כדי לא להתבלבל, כדאי לזכור שביט 0 מתאים ל-window scaling וביט 1 מתאים ל-timestamps.

יש שלוש נקודות לתשומת לב בעת ההגדרה:

  • זה עובד רק על חיבורים חדשים. חותמות הזמן מסוכמות בלחיצת היד המשולשת, כך שזה לא משפיע על חיבורים שכבר קיימים. צריך לפתוח מחדש את החיבור בצד ההתקן
  • זה לא יעבוד אם שני הצדדים לא תומכים. גם אם מפעילים רק בצד ה-host, אם המצלמה לא מחזירה TSopt ב-SYN/ACK, זה לא ישמש באותו חיבור
  • ההגדרה גם משנה את אופי החיבור. חותמות הזמן מגדילות את כותרת ה-TCP, כך שכמות הנתונים שנכנסת לקטע אחד קטנה מעט

עם זאת, בפועל “TSopt מופיע בפועל במנת ה-SYN /‏ SYN-ACK” חשוב יותר מ”מוצג כמופעל במסך ההגדרות”. זה באמת המצב.

שלוש נקודות לתשומת לב בהגדרת חותמות הזמןתרשים המראה ששלוש נקודות לתשומת לב בהגדרת חותמות הזמן הן שההגדרה עובדת רק על חיבורים חדשים כי היא מסוכמת בלחיצת היד המשולשת, ששני הצדדים חייבים לתמוך בה, ושהכותרת גדלה וכמות הנתונים בקטע קטנה מעט.שלוש נקודות לתשומת לבעובד רק מחיבורים חדשיםנדרשת תמיכה בשני הצדדיםהכותרת גדלה והנתונים קטנים מעטיש לפתוח מחדש את חיבור ההתקן

איור 12: ההגדרה לבדה לא מספיקה. צריך גם לפתוח מחדש את החיבור וגם לוודא תמיכה בצד השני.

6.2. בדיקת TSopt ב-SYN /‏ SYN-ACK

אחרי ההפעלה בדקנו שלוש נקודות:

  • האם יש TSopt ב-SYN של החיבור הבעייתי
  • האם גם צד ה-SYN/ACK מחזיר TSopt
  • האם TSopt ממשיך להופיע גם בקטעי הנתונים וב-ACK שבאים אחר כך

רק אחרי אימות הנקודות האלה אפשר לומר ש”חותמות הזמן באמת בשימוש בחיבור הזה”.

6.3. איפה לבדוק כשזה עדיין לא עוזר

גם אחרי הפעלת חותמות הזמן, במקרים הבאים השיפור עשוי להיות חלש:

  • שיעור האובדן עצמו גבוה
  • ציוד ביניים שובר, מפיל או משנה את אפשרויות ה-TCP
  • יש בעיה אחרת סביב ה-NIC / הדרייבר / הגדרות ה-offload
  • האפליקציה תולה את כל התהליך בקריאה סינכרונית בודדת, כך שהמתנה אחת נראית כעצירה כוללת
  • בפועל הגורם העיקרי אינו TCP, אלא עצירת עיבוד בצד המצלמה או גודש בתור הפנימי של ההתקן

לכן, קל יותר להתקדם עם הטיפול לפי הסדר הבא:

  1. קודם כול, לוודא ב-wire שיש המתנה לשידור חוזר
  2. לבדוק אם התבצע סיכום של TSopt
  3. להפעיל timestamps ולבדוק את הפער בשיפור
  4. אם עדיין נשאר, לטפל בנפרד במקור האובדן ובתכנון האפליקציה
הסדר לביצוע הטיפולתרשים המראה שהסדר לביצוע הטיפול הוא קודם לבדוק ב-wire המתנה לשידור חוזר, לבדוק אם בוצע סיכום של TSopt, להפעיל timestamps ולבדוק את פער השיפור, ואם עדיין נשאר בעיה לטפל בנפרד במקור האובדן ובתכנון האפליקציה.בדיקת המתנה לשידור חוזר ב-wireבדיקת סיכום TSoptהפעלת timestamps ובדיקת השיפוראם נשאר, טיפול נפרד במקור האובדן ובתכנון

איור 13: סדר של בדיקה, סיכום, הפעלה ובדיקת מה שנשאר מקל על בידוד הגורם כשההפעלה לא עוזרת.

7. נקודות בדיקה ב-Wireshark

הנה מסנני תצוגה שנוחים לשימוש בבידוד:

tcp.stream eq <תזרים היעד>
tcp.analysis.retransmission
tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.options.timestamp.tsval
tcp.options.timestamp.tsecr

יש כמה טיפים לאופן ההסתכלות:

  • מצמצמים ל-tcp.stream של החיבור היעד בלבד
  • מציגים את Time delta from previous displayed packet ורואים ישירות כמה שניות העצירה נמשכה
  • בודקים אם Retransmission מופיע ברגע הבעייתי
  • בודקים אם TSopt סוכם ב-SYN /‏ SYN-ACK בתחילת החיבור
  • בודקים אם TSecr חוזר ב-ACK

נכתוב גם איך זה נראה על המסך, במילים. אחרי שמתרגלים, אפשר לזהות את המקרה הזה במבט אחד.

היכן מסתכלים איך זה נראה
עמודת ה-Info ברשימת המנות על מנות של שידור חוזר מופיע [TCP Retransmission]
צבע השורה זה תואם לכלל צביעת ברירת המחדל של Wireshark “Bad TCP”, כך שהשורה מקבלת רקע שחור וטקסט אדום. אפשר לתפוס את זה גם במבט חטוף
חלונית הפרטים בוחרים את השורה, פותחים את Transmission Control Protocol, ובתוכו את SEQ/ACK analysis — שם מופיע ציון שהמנה זוהתה כשידור חוזר
פער הזמן הצגת Time delta from previous displayed packet כעמודה מראה כמה שניות עברו מהמנה המוצגת הקודמת. כאן רואים רצף של שנייה, שתי שניות
ה-Options של ה-SYN בוחרים את שורת ה-SYN, פותחים את Options, ובודקים אם יש פריט Timestamps — כך יודעים אם יש TSopt

הרצף האופייני נראה כך: תחילה שורה עם אותו Seq מופיעה שוב אחרי שנייה, ואז שוב אחרי שתי שניות נוספות, ומיד אחרי השורה האחרונה חוזר ה-ACK, ומשם מתחדשים חילופי הדברים הרגילים. אם “פער השניות הריק” הזה תואם את הזמן שבו התגובה נעצרה בלוג האפליקציה, כמעט אפשר לקבוע את החשוד.

כשמצליבים בין הלוג לבין המנות, יש לשים לב גם להפרש בין בסיס הזמן של האפליקציה לבין בסיס הזמן של הלכידה. אם יש הסטה כאן, קל להאשים אירוע לא קשור.

התהליך לקביעת החשוד ב-Wiresharkתרשים המראה שמצמצמים ל-tcp.stream של החיבור היעד, מסתכלים על עמודת פער הזמן כדי לראות ישירות את משך העצירה, מוודאים שורות שידור חוזר לאותו Seq, ואם הפער תואם את זמן העצירה בלוג האפליקציה החשוד כמעט מוכרע.כןלאצמצום ל-tcp.stream של החיבורהסתכלות על עמודת פער הזמןוידוא שורות שידור חוזר לאותו Seqתואם את זמן העצירה באפליקציה?החשוד כמעט מוכרעלחשוד בהפרש זמן או בגורם אחר

איור 14: לצמצם, להסתכל על פער הזמן, ולהצליב. בשלושה צעדים אלה קובעים את זהות “פער השניות הריק”.

8. חלוקה גסה בין המצבים

תסמין הגורם החשוד הראשון מה לבדוק תחילה
עצירה מדי פעם בסדר גודל של שניות המתנה ל-RTO ב-TCP לבדוק שידור חוזר ופער זמן במנות
עצירה כמעט באותו תזמון בכל פעם המתנה בתוך האפליקציה, עיבוד בצד ההתקן, timeout קבוע לבדוק תהליכונים, קריאות SDK ולוגי התקן
מחמיר רק בעומס גבוה CPU,‏ GC, גודש בתור לבדוק CPU, הפרעות (interrupts), זיכרון ואורך תור
גרוע בבת אחת על פני חיבורים רבים השכבה הפיזית, מתג, ציוד ביניים לבדוק NIC, כבלים, סטטיסטיקת פורטים ולוגי ציוד ביניים
שינוי הגדרה לא שינה כלום אפשרות ה-TCP לא סוכמה בפועל לבדוק שוב את SYN /‏ SYN-ACK

השורה האחרונה קורית ממש הרבה. תחושת הסיפוק מכך ששיחקתם עם ההגדרות, והעובדה שהיא באמת בשימוש ב-wire — הם שני דברים שונים.

9. סיכום

הנקודות העיקריות הפעם:

  • “עצירה מדי פעם לכמה שניות” יכולה להיות המתנה לשידור חוזר ב-TCP, ולא עצירה של האפליקציה
  • אם משך העצירה תואם את אופן ההמתנה של ה-RTO ומופיע Retransmission, זו השערה חזקה למדי
  • אפשרות ה-timestamps של TCP היא מנגנון של RTTM ו-PAWS, שגם מסירה את העמימות במדידת RTT בעת שידור חוזר
  • במקרה הזה, הפעלת חותמות זמן מסדרת RFC1323 צמצמה את הזמן שבו ה-RTO נשאר שמרני מדי

דרכי פעולה שכדאי להימנע מהן:

  • לקבוע את החשוד לעצירת התקשורת רק לפי לוגי האפליקציה
  • להסתכל רק על הגדרות מערכת ההפעלה בלי לבדוק את המנות עצמן
  • לחשוב שהפעלת חותמות זמן מסלקת גם את מקור האובדן

דרכי פעולה שעובדות בפועל:

  • קודם כול, להסתכל על ה-wire
  • לבדוק את הצורה של השידור החוזר וזמן ההמתנה
  • לוודא סיכום של TSopt
  • גם אחרי השיפור, לטפל בנפרד במקור האובדן ובתכנון האפליקציה

במילים אחרות, בסוג הזה של תקלות עדיף קודם “לזהות איפה ממתינים” ולא “להאיץ”. רק אם לא מפספסים את הנקודה הזו, החקירה מתקצרת משמעותית.

10. מקורות

מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.

העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.

חקרי המקרה האלה מציגים גישה דומה לניתוח, לתעדוף או לעיצוב מחדש.

המאמר קשור ישירות לשירותים הבאים.

שאלות נפוצות

שאלות נפוצות בפניות בנושא המאמר.

מהו TCP Retransmission (שידור חוזר ב-TCP)?
מנגנון שבו TCP שולח מחדש את אותם הנתונים כשה-ACK (אישור קבלה) על מנה שנשלחה לא חוזר. אם מנה כלשהי אובדת בדרך, הצד השולח ממתין ל-ACK, ואם הוא לא מגיע, ממתינים לתפוגת טיימר השידור החוזר (RTO) ורק אז משדרים מחדש. מבחינת האפליקציה זה נראה כ"עצירה של כמה שניות", אבל מבחינת TCP זו פשוט המתנה לתפוגת הטיימר עד שה-ACK יגיע — סוג עצירה שקורה באופן שגרתי. בלכידת מנות אפשר לצפות בזה כ-TCP Retransmission.
מה גורם ל-TCP Retransmission?
הגורם הישיר הוא אובדן מנות: כשה-ACK לא חוזר, מתרחש שידור חוזר. את מקור האובדן צריך לבדוק בנפרד — השכבה הפיזית (כבלים ופורטים), ה-NIC והדרייבר או הגדרות ה-offload שלו, ובעיות במתג או בציוד ביניים. הפעלת TCP timestamps יכולה לצמצם את זמן ההמתנה אחרי שידור חוזר, אך אינה קסם שמסלק את האובדן עצמו, ולכן חקירת מקור האובדן נדרשת בנפרד. יש גם מקרים שבהם ציוד ביניים שובר או מפיל אפשרויות TCP, וכן מקרים שבהם הגורם העיקרי בפועל הוא עצירת עיבוד בצד ההתקן ולא TCP כלל.
למה שידור חוזר ב-TCP עוצר תקשורת לכמה שניות?
מכיוון שטיימר השידור החוזר (RTO) של TCP ממתין בצורה שמרנית. לפי RFC 6298, ה-RTO ההתחלתי מבוסס על שנייה אחת, ואם תוצאת החישוב קטנה מכך היא מעוגלת כלפי מעלה לשנייה, ומוכפלת בכל תפוגה. לכן בתנאים גרועים אפשר לראות המתנה כמו שנייה, שתי שניות, ארבע שניות. בתקשורת בקרה המבוססת בעיקר על request/response קטנים, לפני שמצטברים מספיק Duplicate ACK כדי להפעיל fast retransmit, נוטה להיחשף קודם המתנה ל-RTO, שמופיעה כעצירה נדירה של כמה שניות. הפעלת אפשרות ה-TCP timestamps יכולה, במקרים מסוימים, להסיר את העמימות במדידת RTT בעת שידור חוזר ולצמצם את הזמן שבו הערכת ה-RTO נשארת שמרנית מדי.
איך בודקים TCP Retransmission ב-Wireshark?
אפשר להשתמש במסנני התצוגה tcp.analysis.retransmission,‏ tcp.analysis.fast_retransmission ו-tcp.analysis.lost_segment. מצמצמים ל-tcp.stream של החיבור היעד, מציגים את Time delta from previous displayed packet כדי לראות ישירות את משך העצירה, ובודקים אם Retransmission מופיע ברגע הבעייתי ואם פער הזמן עד השידור החוזר תואם את משך העצירה. את השאלה אם משתמשים ב-TCP timestamps בודקים לפי סיכום TSopt ב-SYN /‏ SYN-ACK בתחילת החיבור. העובדה שה-TSopt נמצא בפועל במנות עצמן חשובה יותר מכך שההגדרה מוצגת כמופעלת במסך ההגדרות.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג