Frontend Labs
⋯

42. Reading a Wireshark trace like a detective

42.1 First moves on any capture

  1. Statistics → Capture File Properties: duration, packet rate, drops.
  2. Statistics → Conversations (TCP tab): sort by bytes / by "Bits/s". Find the flow that matters. "Follow → TCP Stream" to see the app dialogue.
  3. Statistics → Protocol Hierarchy: what's actually on this wire.
  4. Set the time display to "Seconds Since Previous Displayed Packet" (View → Time Display Format) — gaps jump out.
  5. Enable tcp.analysis expert flags (on by default): look at Analyze → Expert Information.

42.2 The display filters that find problems

Filter Finds
tcp.analysis.retransmission retransmitted segments
tcp.analysis.fast_retransmission fast retransmits (3 dup-ACKs)
tcp.analysis.spurious_retransmission retransmit of data already ACKed (RTO too tight / reordering)
tcp.analysis.out_of_order reordering
tcp.analysis.duplicate_ack dup-ACKs (tcp.analysis.duplicate_ack_num >= 3 = triggering)
tcp.analysis.lost_segment a gap Wireshark inferred ("previous segment not captured")
tcp.analysis.zero_window receiver said "stop, buffer full"
tcp.analysis.window_full sender has filled the offered window
tcp.analysis.ack_rtt > 0.2 ACKs that took >200 ms (delayed-ACK or path)
tcp.flags.reset == 1 who reset, and when relative to the last data
tcp.time_delta > 0.2 && tcp.flags.push == 1 app "think time" gaps
tcp.analysis.bytes_in_flight plot it (I/O Graph) to see cwnd behavior
tcp.stream == N isolate one connection

42.3 Signatures → diagnosis

What you see Likely cause
Steady retransmissions + duplicate_ack bursts, throughput sawtooths real packet loss on the path; check both-end captures & link counters
spurious_retransmission + out_of_order, ~no true loss packet reordering (ECMP/LACP hashing), RTO too aggressive
zero_window from the receiver, then window_update seconds later receiver app too slow — not a network problem
Long tcp.time_delta gap before a PSH from the server, no missing packets server-side application latency (slow query, GC pause)
Client SYN, SYN, SYN at 1s/3s, no SYN-ACK SYN or SYN-ACK lost; firewall DROP; accept-queue overflow
Handshake OK, first full-size (~1500) data packet retransmitted forever PMTU black hole (ICMP filtered) — Ch. 8
RST immediately after SYN-ACK backlog overflow w/ abort, or app crashed on accept
RST right after a normal data exchange, from a third pattern/TTL forged RST by a middlebox/IPS
ACKs every ~40 ms, tiny segments, request in 2 parts Nagle × delayed-ACK — Ch. 33
win never grows past ~64 KB on a high-RTT path window scaling stripped/off — Ch. 30
Big bytes_in_flight, RTT climbing steadily with throughput flat bufferbloat at the bottleneck — Ch. 44
Duplicate IP ID / duplicate SYN with different TTL two hosts sharing an IP, or a retransmit vs a spoofed packet

42.4 The I/O Graph (your most powerful view)

Statistics → I/O Graph. Plot on the same time axis:

  • tcp.analysis.bytes_in_flight (AVG) — proxy for cwnd.
  • tcp.analysis.retransmission (COUNT) — loss events.
  • tcp.analysis.ack_rtt (AVG/MAX) — RTT over time.
  • Throughput (bytes, "Bits/s").

Now you can see slow start ramp, the sawtooth of CUBIC on loss, an RTO (everything stops for ~200 ms–1 s then restarts from near zero), or RTT rising with in-flight bytes (bufferbloat).

42.5 tshark for scripted analysis

# Per-connection retransmit counts:
tshark -r cap.pcap -q -z conv,tcp
# List every retransmission with time and stream:
tshark -r cap.pcap -Y tcp.analysis.retransmission \
  -T fields -e frame.time_relative -e tcp.stream -e ip.src -e ip.dst -e tcp.seq
# RTT distribution:
tshark -r cap.pcap -Y tcp.analysis.ack_rtt -T fields -e tcp.analysis.ack_rtt | \
  sort -n | awk '{a[NR]=$1} END{print "p50",a[int(NR*.5)],"p95",a[int(NR*.95)],"max",a[NR]}'
# Time-to-first-byte per HTTP request:
tshark -r cap.pcap -Y http.response -T fields -e http.time -e http.request.uri

42.6 War story

A dashboard showed 2% "network errors" calling an internal API. The capture had zero retransmissions or resets. Filtering http.response.code >= 500 and "Follow TCP Stream" showed the server returned 503 with a JSON body in ~4 ms — the API's own rate limiter. The "network" error was an application status code the client's metrics mislabeled. Lesson: confirm at the packet layer whether a failure is TCP (RST/timeout/retransmit) or application (a clean HTTP 4xx/5xx) before opening a network ticket.

Try it yourself

tshark -r cap.pcap -q -z io,stat,1,'COUNT(tcp.analysis.retransmission)tcp.analysis.retransmission','AVG(tcp.analysis.bytes_in_flight)tcp.analysis.bytes_in_flight'
tshark -r cap.pcap -q -z expert
wireshark cap.pcap   # then: Analyze > Expert Information; Statistics > I/O Graph

Generated from real-life-example.md · 8 Oct 2026 16:36