> ## Content Index
> Fetch the complete content index at: https://www.pinglabz.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# TCP Retransmission, Reordering, or a Capture Artifact?
- URL: https://www.pinglabz.com/tcp-retransmission-reordering-capture-artifact/
- Published: 2026-10-13T06:25:15.000Z
- Updated: 2026-10-13T06:25:15.000Z
- Description: Compare controlled loss, reordering, and one filtered capture frame. Use both endpoint traces and queue evidence before diagnosing TCP loss.
- Author: Jaime
- Tags: Packet Analysis, Troubleshooting, TCP/IP, Linux

A TCP transfer retransmitted 378 segments in the reordering experiment below. The netem queue recorded zero drops. In a separate healthy transfer, removing one frame from a saved capture caused Wireshark to report an unseen segment, even though the original capture contained it.

Those are two reasons to investigate a packet-analysis label before calling it network loss. We'll compare actual loss, deliberate reordering, and an incomplete capture on the same small path, using both endpoint traces and queue evidence.

## Keep the capture points consistent

Use the [Linux namespace lab](https://www.pinglabz.com/linux-namespace-network-lab/): `pl-client` at `192.0.2.10`, `pl-router` between subnets, and `pl-server` at `198.51.100.10`. Any impairment goes on the router's `wan0` egress toward the server. The return path has no netem impairment.

Tested with: kernel `7.0.0-38-generic`, iproute2 `6.19.0`, iPerf3 `3.20`, tcpdump `4.99.6`, TShark/Wireshark `4.6.4`. Install `iperf3`, `tcpdump`, `ethtool`, and `tshark` on the lab VM as needed.

For these traces, segmentation and receive aggregation were disabled on the newly created veth interfaces before testing:

```bash
for ns in pl-client pl-peer pl-server; do
  sudo ip netns exec "$ns" ethtool -k eth0
  sudo ip netns exec "$ns" ethtool -K eth0 tso off gso off gro off
done
for dev in lan1 lan2 wan0; do
  sudo ip netns exec pl-router ethtool -K "$dev" tso off gso off gro off
done
```

The `ethtool -k` output records the original settings. To restore them afterward, rerun `ethtool -K` with those recorded values (veth links usually default to `tso on gso on gro off`), or delete the lab namespaces, which removes these veth links. These are isolated lab veth links; don't apply the loop to production NICs. The [ethtool guide](https://www.pinglabz.com/ethtool-linux/) explains why a host-side capture can otherwise show buffers rather than individual wire-sized segments.

Start a foreground server in its own terminal:

```bash
sudo ip netns exec pl-server iperf3 -s
```

Before each client run, start two captures in separate terminals. Change the filenames for each case so you keep both originals:

```bash
# Client-side capture
sudo ip netns exec pl-client tcpdump --immediate-mode -ni eth0 -s 0 -w /tmp/sender.pcap 'tcp port 5201'

# Server-side capture
sudo ip netns exec pl-server tcpdump --immediate-mode -ni eth0 -s 0 -w /tmp/receiver.pcap 'tcp port 5201'
```

Start captures before the connection opens. Let the client complete, then stop each capture with Ctrl+C and retain the statistics. Immediate mode helps short experiments avoid leaving their final packets waiting in the capture buffer. Zero kernel drops is useful, but it does not prove that every packet you intended to record reached the saved file.

Use the same paced workload for each case:

```bash
sudo ip netns exec pl-client iperf3 -c 198.51.100.10 -t 8 -b 2M -J > result.json
```

Here `-b 2M` also paces the TCP client; it is not limited to UDP mode. The low offered rate keeps this exercise focused on packet behavior rather than saturating the VM. There is no TBF shaper attached during these three TCP runs.

## First establish a clean comparison

Check that `wan0` has no leftover netem or shaping qdisc, then run the workload and captures. The clean transfer reported zero iPerf3 retransmissions. Neither endpoint trace had TShark retransmission, out-of-order, previous-segment-not-captured, or ACKed-unseen-segment flags.

Keep that receiver file as `clean-receiver.pcap`. It is the source for the later capture-gap experiment, so do not overwrite or filter it in place.

The [TCP handshake and teardown article](https://www.pinglabz.com/tcp-handshake-teardown-capture/) helps identify the connection boundaries. iPerf3 creates a control connection as well as its data connection; isolate the data flow by its endpoints and port pair before comparing sequence numbers.

## Actual loss: correlate the resend with the other capture

Add a 15 ms one-way delay and independent two-percent loss with the tested seed:

```bash
sudo ip netns exec pl-router tc qdisc add dev wan0 root handle 10: netem delay 15ms loss random 2% seed 43
```

Start both captures, run the same eight-second client, stop the captures, then save the queue state:

```bash
sudo ip netns exec pl-router tc -s qdisc show dev wan0
```

The client reported 23 retransmissions. The queue recorded drops. More usefully, we can identify one byte range at both endpoints. In this measured example, client source port `34984` sent 1,448 bytes with absolute sequence number `2960746657`:

```text
Sender frame 21: first transmission, Seq(raw)=2960746657 Len=1448
Sender frame 40: same byte range sent again, about 15.7 ms later
Receiver frame 46: that byte range arrives about 15.3 ms after the retry
```

The first transmission appears in the sender trace but not in the receiver trace. The later matching transmission appears at both endpoints. Along with the known netem fault and its drop counter, that is evidence of loss between these capture points. The captures shared the VM's clock, and their capture statistics reported no kernel drops.

To reproduce the comparison, extract absolute sequence numbers, lengths, and ports. Relative sequence numbering can be based on different starting points if a capture is incomplete:

```bash
tshark -r - -Y 'ip.src == 192.0.2.10 && tcp.len > 0' -T fields \
  -e frame.number -e frame.time_epoch -e tcp.srcport -e tcp.dstport \
  -e tcp.seq_raw -e tcp.len < /tmp/sender.pcap
```

Repeat against the receiver file. Match the connection and byte range; a sequence number alone is not unique across connections. Different segment sizes may also cover overlapping ranges, so exact packet equality is not always the right comparison.

Remove this lab qdisc before the next case:

```bash
sudo ip netns exec pl-router tc qdisc del dev wan0 root
```

For a device-policy drop with matching Cisco counters, compare the [Linux-to-Cisco investigation](https://www.pinglabz.com/linux-cisco-packet-drop-lab/).

## Reordering: retransmissions without configured loss

Apply delay and reordering, with no loss parameter:

```bash
sudo ip netns exec pl-router tc qdisc add dev wan0 root handle 10: netem delay 15ms reorder 25% seed 43
```

Repeat the same captures and workload. This run reported 378 iPerf3 retransmissions, while netem reported zero dropped packets. In the receiver trace, TShark marked 229 frames out of order. Later sequence ranges arrived before earlier ones; some earlier data appeared after the gap was visible.

```bash
tshark -r - -Y 'tcp.analysis.out_of_order' -T fields \
  -e frame.number -e tcp.seq -e tcp.len -e _ws.col.Info < /tmp/receiver.pcap
```

Repeated ACKs and gaps in the arrival sequence can make a sender retransmit data that is delayed rather than lost. Reordering was the deliberately changed condition here. The zero netem-drop counter establishes that this qdisc did not discard packets.

The sender and receiver traces also produced different retransmission-label counts. TShark classified 378 sender-side frames as retransmissions and 589 receiver-side frames as retransmissions. Those numbers are analyzer judgments over different observed packet orders, not counters you should add together or equate with iPerf3's kernel-reported count. Fast retransmission is a related classification and can overlap other retransmission labels.

The [Wireshark TCP-analysis documentation](https://www.wireshark.org/docs/wsug%5Fhtml%5Fchunked/ChAdvTCPAnalysis.html?ref=pinglabz.com) explains that analysis depends on packets processed in capture order. Use its labels to find a sequence worth examining, then compare the surrounding data and ACK behavior.

```bash
sudo ip netns exec pl-router tc qdisc del dev wan0 root
```

## A missing capture frame: the network never changed

Take the unmodified clean receiver capture. Find one data frame, then write a separate file with that frame excluded. The source stays intact:

```bash
tshark -r - -Y 'ip.src == 192.0.2.10 && tcp.len > 1000' \
  -T fields -e frame.number -e tcp.seq -e tcp.len < clean-receiver.pcap
```

In the measured capture, frame 30 contained 1,448 bytes starting at relative sequence 7,278\. Remove that particular frame from the derived file:

```bash
tshark -r - -Y 'frame.number != 30' -w - \
  < clean-receiver.pcap > filtered-receiver.pcapng
```

Choose a data frame from your own capture; frame 30 is specific to this run. Read the resulting analysis flags:

```bash
tshark -r - \
  -Y 'tcp.analysis.lost_segment || tcp.analysis.ack_lost_segment' \
  -T fields -e frame.number -e tcp.seq -e tcp.ack -e _ws.col.Info \
  < filtered-receiver.pcapng
```

The derived trace now contained these observations:

```text
Frame 30: [TCP ACKed unseen segment] Ack=8726
Frame 31: [TCP Previous segment not captured] Seq=8726 Len=1448
```

Frame numbers change when a file is filtered. These are the derived file's frame numbers, not the removed original frame followed by its original neighbor.

The receiver ACKed data beyond the absent byte range. The original clean trace contains that range, and its transfer reported zero retransmissions. We changed the evidence file, not the network. Real captures can become incomplete through late starts, filters, overruns, or packet export choices; this synthetic example isolates one such visibility gap.

## Decide what the evidence supports

For a retransmitting transfer, first check capture completeness and offloads, then isolate the connection and compare sequence ranges at both ends. Ask whether the data was absent downstream, merely late, or only missing from the file you opened. Correlate a queue or policy counter if you have one.

These tests distinguish three controlled conditions. The same [netem setup](https://www.pinglabz.com/tc-netem-delay-loss-reordering/) lets you repeat the comparisons, and the [packet-analysis hub](https://www.pinglabz.com/packet-analysis/) links the capture tools needed to investigate a less predictable path. To summarize a saved capture as connection and DNS logs, try [Zeek](https://www.pinglabz.com/pcap-to-zeek-connection-dns-logs/); for rule-driven alerts on the same kind of PCAP, see [Suricata EVE output](https://www.pinglabz.com/suricata-eve-json-controlled-scan/). To join those Zeek and Suricata records for the same flow, see [Community ID: correlate Zeek and Suricata logs from one PCAP](https://www.pinglabz.com/zeek-suricata-community-id-same-pcap/).