Perché le ritrasmissioni TCP bloccano la comunicazione con telecamere industriali, e come isolarle

· Aggiornato il: · · TCP, Networking, Bug Investigation, Sviluppo Windows, Telecamera industriale

Nella comunicazione con telecamere industriali e controllo apparati, il sintomo più fastidioso è un collegamento veloce in media ma che occasionalmente si blocca per diversi secondi. Si riproduce raramente e la maggior parte del tempo nulla accade, quindi l’UI, i thread, il GC, l’SDK della telecamera, la NIC e lo switch iniziano tutti a sembrare leggermente sospetti.

Questo articolo tratta un caso in cui la comunicazione TCP tra un host e un’applicazione che controlla una telecamera industriale si bloccava occasionalmente per qualche secondo. Quando abbiamo investigato, il colpevole non era l’applicazione che si congelava, ma TCP in attesa di una ritrasmissione causata da perdita di pacchetto. Inoltre, abilitare la funzionalità timestamps di famiglia RFC1323 (nello scenario degli standard attuali, RFC 7323) ci ha permesso di mantenere al minimo il tempo di attesa in questo sistema.

Nomi dispositivo, configurazioni e numeri sono stati generalizzati, ma il modo di pensare si applica direttamente in pratica.

1. La conclusione prima di tutto (in una riga)

  • Una comunicazione TCP che occasionalmente si blocca per diversi secondi può essere causata non dal congelamento dell’app, ma da un’attesa di ritrasmissione a seguito di perdita di pacchetto
  • Se una cattura pacchetti mostra Retransmission con un grande gap temporale, e la durata del blocco corrisponde al comportamento delle attese RTO, è abbastanza sospetto
  • L’opzione TCP timestamps è un meccanismo per RTT measurement e PAWS, e rimuove anche l’ambiguità della misura RTT sulla ritrasmissione
  • In questo caso, abilitare la funzionalità timestamps di famiglia RFC1323 ha ridotto il tempo in cui la stima RTO restava obsoleta e conservativa, mantenendo al minimo i blocchi di diversi secondi
  • Tuttavia, questo non è magia che fa sparire la perdita in sé. Bisogna ancora rivedere separatamente layer fisico, NIC, switch, dispositivi intermedi, driver e design dei buffer

In breve, se la vera identità di “si blocca occasionalmente per qualche secondo” è un tempo di attesa dentro TCP, sforzarsi solo su retry a livello applicazione manca il bersaglio. È più veloce guardare prima il wire e confermare se ci troviamo in un’attesa di ritrasmissione.

2. Come appare il sintomo

2.1. L’app è viva, ma solo le risposte si bloccano per secondi

La prima parte confusa è che l’applicazione nel complesso non sembra congelata.

  • L’UI non è completamente morta
  • Il processo non è crashato
  • La CPU non è al 100%
  • Eppure le risposte ai comandi di controllo della telecamera occasionalmente cadono per diversi secondi

Sintomi come questi sono difficili da distinguere da un deadlock in-app o un loop infinito. Inoltre, nel controllo apparati, un singolo blocco di diversi secondi crea direttamente l’impressione di un fermo linea. Anche se le medie appaiono pulite, la percezione sul campo è considerevolmente peggiore.

2.2. La bassa frequenza rende difficile vederlo solo dai log

Quel che rende fastidioso questo tipo di difetto è la bassa frequenza. Si comporta come una volta all’ora, una volta ogni mezza giornata, o solo quando le condizioni si allineano.

Se lo insegui solo attraverso i log, di solito va così.

  • Il log applicativo si ferma su “spedito” e “nessuna risposta tornata”
  • Il log lato ricevitore sembra “nulla è arrivato”
  • Qualche altro evento capita nello stesso intervallo temporale, sparpagliando i sospettati

In situazioni come questa, provare a ricostruire la causalità solo dai log applicativi è un modo piuttosto affidabile per impantanarsi. È più veloce scendere di un livello, al layer comunicazione.

3. Cosa stava succedendo effettivamente (diagrammi)

3.1. La perdita di pacchetto porta in un’attesa di ritrasmissione

La trama questa volta è semplice. Un pacchetto era perso da qualche parte lungo il percorso, il mittente attendeva un ACK, nessuno arrivava, quindi aspettava lo scadere dell’RTO e poi ritrasmetteva.

Lato telecameraReteHost appLato telecameraReteHost appPerso quiNon arriva ACK, quindi attendeRecuperare questa richiesta richiede di attendere l'RTOLa comunicazione riprende quiComando di controllo (Seq=N)Ritrasmette il comando di controlloIl pacchetto ritrasmissione arrivaACKACK

Dal punto di vista dell’applicazione sembra “si è bloccato per qualche secondo”, ma dal punto di vista TCP era semplicemente “non è ancora arrivato un ACK, quindi sto aspettando che scada il timer di ritrasmissione”. È poco appariscente, ma questo tipo di blocco accade continuamente.

Il traffico di controllo in questo caso consisteva principalmente in piccoli scambi richiesta/risposta, e un singolo scambio non aveva una grande quantità di dati non riconosciuti in volo. Di conseguenza, questa era una configurazione in cui l’attesa RTO tendeva a emergere prima che accumulassi abbastanza ACK duplicati per innescare la fast retransmit.

3.2. I blocchi di diversi secondi corrispondevano alla forma dell’RTO

L’attesa di ritrasmissione TCP, sebbene vari per implementazione, si comporta in modo conservativo. Sotto RFC 6298, l’RTO iniziale ha una baseline di 1 secondo; se il valore calcolato è inferiore, viene arrotondato a 1 secondo, e quando scade un timeout, l’RTO raddoppia.

SiNoPerdita pacchettoNon arriva ACKAttendi l'RTORitrasmettiACK tornato?Comunicazione riprendeRaddoppia l'RTO

Quindi anche in situazioni in cui vorresti risolvere in qualche centinaio di millisecondo, in condizioni avverse le attese possono apparire come 1 secondo, 2 secondi, 4 secondi. Il “si blocca occasionalmente per qualche secondo” in questo caso si allineava piuttosto naturalmente con quella forma.

4. Cosa abbiamo guardato durante l’indagine

4.1. Per prima cosa escludere cause di stallo interne all’app

Piuttosto che saltare subito a incolpare TCP, abbiamo prima escluso le tipiche cause lato applicazione.

Cosa abbiamo controllato Perché abbiamo guardato Conclusione in questo caso
Thread UI / worker thread Verificare blocchi o attese reciproche Non la causa principale
Uso CPU Verificare ritardi di elaborazione sotto carico Non al 100% anche durante i blocchi
GC / pressione memoria Verificare pause La forma delle durate di blocco non corrispondeva
Chiamate SDK telecamera Verificare attese dentro l’SDK Non corrispondevano ai ritardi sul wire
Cattura pacchetti Verificare ritrasmissioni al layer comunicazione È qui che è emersa la causa

La cosa importante qui è non scegliere il colpevole basandosi solo sui timestamp dei log applicativi. Nelle applicazioni di controllo apparati, un’attesa a livello superiore a volte è solo il riflesso di un’attesa a livello inferiore.

4.2. Confermare le ritrasmissioni con una cattura pacchetti

Quando abbiamo preso una cattura pacchetti, vedemmo TCP Retransmission nella finestra temporale del blocco, e inoltre che nessun ACK era tornato subito prima.

Questi sono i punti da guardare.

  • Stesso Seq viene ritrasmesso?
  • Il gap temporale fino alla ritrasmissione corrisponde alla durata del blocco?
  • Sembra un’attesa per scadenza RTO piuttosto che Dup ACK o Fast Retransmission?
  • La connessione problematica appare sempre come lo stesso tcp.stream?

Quando questi si allineano, “TCP sta aspettando una ritrasmissione” diventa molto più probabile di “l’app è congelata”.

4.3. Guardare le opzioni TCP negoziate

La prossima cosa che abbiamo guardato era il SYN / SYN-ACK all’apertura della connessione. I timestamp vengono negoziati nel three-way handshake TCP, quindi se TSopt non appare lì, non è usato su quella connessione.

Lato telecameraHostLato telecameraHostSolo dopo avernegoziato qui TSopt può essere usato sui segmenti successiviSYN + TSopt ?SYN/ACK + TSopt ?ACK

Se giochi con le impostazioni OS senza guardare questo, finisci con un altro incidente poco appariscente: “ne sono sicuro di averlo abilitato, ma non ha effetto”. I fatti sul wire sono più forti dei valori configurati.

5. Perché i timestamp RFC1323 aiutano

In pratica la gente ancora chiama questo “i timestamp RFC1323”, ma lo standard corrente è RFC 7323. Questo articolo segue l’uso consueto e scrive RFC1323, intendendo l’opzione TCP timestamps.

5.1. I timestamp esistono per RTTM e PAWS

L’opzione timestamps di TCP viene usata principalmente per due scopi.

  • RTTM (Round-Trip Time Measurement)
  • PAWS (Protect Against Wrapped Sequences)

Quel che ha aiutato in questo caso era il lato RTTM. Facendo eco del TSval di un segmento trasmesso nel TSecr dell’ACK, il peer può misurare RTT in modo più fine e accurato.

5.2. Rimuovono l’ambiguità della misura RTT sulla ritrasmissione

Una volta che avviene una ritrasmissione, senza timestamp diventa ambiguo se “questo ACK è per la trasmissione originale o per la ritrasmissione”. Questo è il punto cui si occupa l’algoritmo di Karn.

RFC 6298 dice che non si deve prendere un campione RTT da un segmento ritrasmesso. Il motivo è che non si riesce a dire a quale trasmissione corrisponda l’ACK. Con l’opzione timestamps, però, questa ambiguità svanisce: guardando il TSecr nell’ACK che arriva, si può identificare quale segmento, con quale TSval, è effettivamente passato.

ReceiverSenderReceiverSenderQuesto segmento è persoNon arriva ACK, quindi attendePuò dire a quale trasmissione corrispondeSeq=N, TSval=1000Ritrasmetti Seq=N, TSval=2000ACK, TSecr=2000

Questo è il nucleo del miglioramento in questo caso.

5.3. Perché potevamo stringere il tempo di attesa in questo caso

In questo caso, la perdita di pacchetto avveniva di tanto in tanto, e ogni occorrenza tendeva a spingere le stime RTT / RTO verso il lato conservativo. Abilitare i timestamp rende più facile aggiornare la stima RTT anche in scenari che coinvolgono ritrasmissioni, il che limita il tempo in cui la stima RTO resta gonfiata e obsoleta.

In altre parole, quello che abbiamo fatto non è magia che rende TCP più veloce, ma ridurre il tempo in cui TCP continua a guardare e aspettare più del necessario.

Ovviamente, RFC 7323 non sostiene che “più campioni RTT risolvono tutto pulitamente”. Il grado in cui aiuta l’ottimizzazione RTO è limitato sotto certi aspetti. Tuttavia, il fatto che rimuova l’ambiguità sulla ritrasmissione può aiutare abbastanza naturalmente in un sistema come questo.

Ci sono cavilli.

  • Parte di questo dipende dall’implementazione dello stack TCP
  • I timestamp da soli non fanno sparire la perdita di pacchetto in sé
  • Se il layer fisico o i dispositivi intermedi sono in colpa, la causa radicale sta altrove
  • SACK, driver NIC, impostazioni offload e problemi lato switch vanno esaminati separatamente

Detto questo, in un sistema come questo — dove “la perdita non è zero” ma “quel che fa veramente male è l’attesa di diversi secondi” — può essere abbastanza efficace.

6. Cosa abbiamo fatto effettivamente

6.1. Abilitare i timestamps

Come contromisura, ci siamo assicurati che l’opzione timestamps potesse essere negoziata su entrambe le estremità della connessione. Sui sistemi Windows questa è a volte trattata come l’opzione RFC 1323, ed è influenzata da impostazioni OS e di rete.

In pratica, però, quel che conta non è “è abilitata nelle impostazioni” ma “TSopt è effettivamente presente sui pacchetti SYN / SYN-ACK sul wire”. Questo è veramente vero.

6.2. Verificare TSopt in SYN / SYN-ACK

Dopo averla abilitata, abbiamo verificato tre cose.

  • Il SYN della connessione in questione porta TSopt?
  • Anche il SYN/ACK lato ritorna TSopt?
  • I segmenti di dati successivi e gli ACK continuano a portare TSopt?

Solo quando queste sono conferme si può dire “i timestamp sono effettivamente usati su quella connessione”.

6.3. Dove guardare se ancora non aiuta

Anche con i timestamp abilitati, il miglioramento può essere lento in casi come questi.

  • Il tasso di perdita in sé è alto
  • Un dispositivo intermedio rompe, scarta o altera le opzioni TCP
  • C’è un problema separato intorno a NIC / driver / offloading
  • L’applicazione appende tutto a una singola chiamata sincrona, così una sola attesa sembra uno stallo totale
  • La causa primaria non è TCP, ma uno stallo di elaborazione sul lato telecamera o una coda intasata dentro il dispositivo

Quindi è più chiaro procedere con le contromisure in questo ordine.

  1. Conferma prima l’attesa di ritrasmissione sul wire
  2. Controlla se TSopt viene negoziato
  3. Abilita i timestamps e misura il delta di miglioramento
  4. Se i problemi restano, affronta separatamente la sorgente di perdita e il design applicativo

7. Cosa controllare in Wireshark

Ecco display filter utili per l’isolamento.

tcp.stream eq <target stream>
tcp.analysis.retransmission
tcp.analysis.fast_retransmission
tcp.analysis.lost_segment
tcp.options.timestamp.tsval
tcp.options.timestamp.tsecr

Ci sono alcuni trucchi per leggere i risultati.

  • Restringi alla connessione target con tcp.stream
  • Visualizza Time delta from previous displayed packet per vedere direttamente i secondi di stallo
  • Conferma se Retransmission appare nel momento problematico
  • Conferma se TSopt viene negoziato nel SYN / SYN-ACK all’apertura della connessione
  • Controlla se TSecr viene restituito negli ACK

Quando si correlano log con pacchetti, fai attenzione anche all’offset tra orologio applicazione e orologio della cattura. Se sono sfasati, tendi ad attribuire la colpa a un evento non correlato.

8. Una guida decisionale approssimativa

Sintomo Primo sospetto Prima azione
Si blocca occasionalmente per diversi secondi Attesa RTO di TCP Conferma ritrasmissioni e gap temporali nei pacchetti
Si blocca quasi allo stesso istante ogni volta Attese in-app, elaborazione lato dispositivo, timeout fissi Guarda thread, chiamate SDK, log dispositivo
Degrada solo sotto alto carico CPU, GC, code intasate Guarda CPU, interrupt, memoria, lunghezza code
Cattivo su molte connessioni contemporaneamente Layer fisico, switch, dispositivi intermedi Guarda NIC, cavi, statistiche porte, log dispositivi intermedi
Ho cambiato impostazioni ma non è cambiato nulla L’opzione TCP non viene negoziata Ricontrolla SYN / SYN-ACK

Quell’ultima riga è genuinamente comune. La soddisfazione di aver modificato un’impostazione e il fatto che venga usata sul wire sono due cose diverse.

9. Riassunto

Punti chiave questa volta:

  • “Si blocca occasionalmente per diversi secondi” può essere l’attesa di ritrasmissione di TCP, non l’app congelata
  • Se la durata del blocco corrisponde al comportamento delle attese RTO e si vede Retransmission, sei su una buona pista
  • L’opzione TCP timestamps è un meccanismo per RTTM e PAWS, e rimuove l’ambiguità della misura RTT sulla ritrasmissione
  • In questo caso, abilitare la funzionalità timestamps di famiglia RFC1323 ha limitato il tempo in cui l’RTO restava eccessivamente conservativo

Approcci da evitare:

  • Scegliere il colpevole per un blocco di comunicazione solo dai log applicativi
  • Guardare solo le impostazioni OS senza guardare i pacchetti effettivi
  • Assumere che abilitare i timestamps eliminerà anche la causa della perdita

Approcci che funzionano in pratica:

  • Guarda prima il wire
  • Conferma la forma delle ritrasmissioni e dei tempi di attesa
  • Conferma la negoziazione TSopt
  • Anche dopo il miglioramento, affronta separatamente la sorgente di perdita e il design applicativo

In altre parole, con questa classe di difetti, “individuare dove sta aspettando” viene prima di “renderlo più veloce”. Solo non perdere questo accorcia considerevolmente l’indagine.

10. Riferimenti

Articoli recenti con gli stessi tag per approfondire argomenti vicini.

Queste pagine collocano l’argomento in un contesto più ampio di servizi e decisioni.

Questi casi mostrano un approccio simile all’analisi, alla definizione delle priorità o alla riprogettazione.

L’articolo è direttamente collegato ai servizi seguenti.

Domande frequenti

Domande che ricorrono nelle consulenze sull’argomento dell’articolo.

Perché la mia connessione TCP si blocca occasionalmente per diversi secondi?
Una causa comune è l'attesa di ritrasmissione a seguito di perdita di pacchetto, non un congelamento dell'applicazione. Quando un pacchetto viene perso, il mittente attende un ACK che non arriva e deve aspettare il retransmission timeout (RTO) prima di rispedire. Sotto RFC 6298, l'RTO iniziale ha una baseline di 1 secondo e raddoppia a ogni timeout, quindi in condizioni avverse le attese appaiono come 1, 2, poi 4 secondi — esattamente lo schema di "blocchi occasionali di qualche secondo".
Come confermo in Wireshark che le ritrasmissioni TCP causano i blocchi?
Restringi alla connessione con il filtro tcp.stream, poi cerca tcp.analysis.retransmission nella finestra temporale del blocco. Cerca lo stesso sequence number ritrasmesso, un gap temporale prima della ritrasmissione che corrisponde alla durata del blocco, e la forma di attesa per scadenza RTO piuttosto che fast retransmission. Controlla anche SYN/SYN-ACK per vedere se l'opzione timestamps (TSopt) è stata negoziata, e visualizza il time delta dal pacchetto precedente per vedere direttamente i secondi di stallo.
Cosa fa effettivamente l'opzione TCP timestamps (RFC 1323)?
L'opzione timestamps serve a due scopi: RTTM (Round-Trip Time Measurement) e PAWS (Protect Against Wrapped Sequences). Per gli stalli di ritrasmissione, conta il lato RTTM: il peer fa eco del TSval del mittente nel TSecr dell'ACK, rimuovendo l'ambiguità se l'ACK risponde alla trasmissione originale o alla ritrasmissione. Questo permette a TCP di continuare ad aggiornare la stima RTT anche in scenari con ritrasmissioni, limitando il tempo in cui l'RTO resta gonfiato eccessivamente conservatore. Lo standard corrente è RFC 7323, anche se si usa abitualmente il nome RFC 1323.
Abilitare i timestamp TCP risolve la perdita di pacchetto?
No. Abilitare i timestamp non è magia che fa sparire la perdita in sé — riduce solo il tempo in cui TCP continua ad attendere più del necessario. Se il tasso di perdita è alto, o la causa radicale risiede nel layer fisico, driver NIC, impostazioni offload, switch o dispositivi intermedi che alterano le opzioni TCP, quelle vanno affrontate separatamente. Verifica anche sul wire che TSopt appaia effettivamente in SYN e SYN-ACK, perché un'impostazione abilitata ma mai negoziata non ha effetto.

Profilo dell’autore

Pagina di presentazione dell’autore dell’articolo.

Go Komura

Rappresentante di KomuraSoft LLC

Specializzato nello sviluppo di software Windows, nella consulenza tecnica e nell’analisi dei malfunzionamenti, soprattutto nei progetti con sistemi esistenti e guasti difficili da riprodurre.

Torna al blog