Isn't This Only the Case Where TCP is Retransmitting? Causes of Bad TCP in Wireshark
*This article is an English translation of the Engineer Notes article as of Oct 24, 2023.
*Please note that the content may have been updated since then.
When capturing my traffic at home with Wireshark while working remotely, I often notice a lot of black packets. These black packets are classified as "Bad TCP" in Wireshark's default coloring settings.
My home uses fiber optic communication up to my place, with a WiFi router set up afterwards, connecting wirelessly to my PC. The connection is very fast and comfortable, and I never experience any slowness or disconnections.
Home network traffic captured with Wireshark (filtering only Bad TCP)
This time, I will explain some of the "Bad TCP" alerts detected by Wireshark, their types, and why they appear.
How to Filter Bad TCP Packets in Wireshark
To filter Bad TCP packets in Wireshark, you need to specify parameters.
- tcp.analysis.flags && !tcp.analysis.window_update && !tcp.analysis.keep_alive && !tcp.analysis.keep_alive_ack
- Bad TCP filter. It is used to detect anomalies in TCP sequence numbers.
In a previous post, Wireshark Display Filters - Basic Operations, I explained how to operate on the information contained in packets.
This time, Bad TCP is not about the information contained in the packet itself. Wireshark has a feature that analyzes packets based on the information contained in the packet and their relationship to preceding and following packets. The results of Wireshark's analysis are displayed in brackets [], and information displayed in brackets is generally not contained in the packet.
Besides Bad TCP, there are other TCP-related filter parameters that do not contain information in the packet, as introduced below.
- tcp.completeness == <value>
- A filter that specifies how far the TCP session message exchange has progressed. The stages are set by summing the TCP flag bits.
- For example, the filter for communication with only the three-way handshake would be 'tcp.completeness==7', where 1 (SYN) + 2 (SYN/ACK) + 4 (ACK).
- tcp.stream == <value>
- Filter by TCP stream. Wireshark automatically generates stream numbers, which can be used to filter packets of the same stream.
In fact, Wireshark has many more TCP-related filters. This can be inferred from the many brackets [] seen in the decode screen compared to other protocols.
How TCP Retransmission Works
It is often said that "TCP is a reliable protocol" because TCP has a mechanism to confirm how much data the receiver has received and retransmit any data that has not been received.
Specifically, TCP sets sequence numbers (Seq#) and acknowledgment numbers (Ack#) in its packets to notify each other of which data has been sent and how much data has been received, thus establishing a conversation. The diagram below shows when retransmissions occur. (For conceptual understanding, Seq#, Ack#, and TCP length are not indicated.)
Assuming Alice is the data sender and Bob is the data receiver, there are two possible cases where a packet is lost in transit: "Alice's packet does not reach Bob" and "Bob's packet does not reach Alice". Additionally, in captured data, "The capture device loses packets even though the communication itself is fine" may also be considered.
Therefore, some Wireshark alerts may not directly relate to the troubleshooting issue, so care is needed.
Note that for simplicity, the diagram shows each piece of data being individually acknowledged, but TCP uses mechanisms like "sliding window," "fast retransmission," and "SACK" to communicate more efficiently. You can see this by capturing packets on your own PC with Wireshark and accessing a web page; you will likely observe batch ACK responses.
Causes of Bad TCP Alerts
Below, I explain common sequence anomalies among Bad TCP alerts. Details of Wireshark's alert determination are available in the Wireshark User's Guide - TCP Analysis.
As in the previous diagram, Alice is the data sender and Bob is the data receiver. Here, I describe alerts marked on the Alice side (sender) and the Bob side (receiver) separately.
Alerts Marked on Alice (Sender) Side
TCP Retransmission
This alert is marked on Alice's data retransmission packets. If the expected next Seq# from Bob does not return by the RTO (retransmission timeout), Alice retransmits the data.
It is set under the following conditions:
- Not a keep-alive packet
- Segment length is greater than zero or SYN or FIN flag is set
- The expected next Seq# is greater than the current Seq#
TCP Out-Of-Order
This alert is marked on Alice's packets. It is marked when a packet with a Seq# smaller than the highest Seq# is received within the iRTT threshold, even though the Seq# is not progressing. This can occur if packets arrive out of order or if a retransmitted packet is received within the iRTT threshold.
It is set under the following conditions:
- Not a keep-alive packet
- Alice's packet with a segment length greater than zero or SYN or FIN flag set
- The expected next Seq# is greater than the current Seq#
- The expected next Seq# and the next Seq# are different
- The last packet from Alice is observed within the Out-Of-Order RTT threshold
The threshold is the value displayed in the "iRTT" (tcp.analysis.initial_rtt) field of "SEQ/ACK Analysis" or the default value of 3msec if not present
TCP Fast Retransmission
This alert is marked on Alice's data retransmission packets. Unlike TCP Retransmission, it is marked due to TCP fast retransmission (retransmission triggered by receiving three or more duplicate ACKs without waiting for RTO). In Wireshark, it is marked if at least two duplicate ACKs are received.
It is set under the following conditions:
- Not a keep-alive packet
- Alice's packet with a segment length greater than zero or SYN or FIN flag set
- The expected next Seq# from Bob is greater than the current Seq#
- At least two duplicate ACKs from Bob
- Alice's current Seq# matches Bob's next expected Ack#
- The last ACK from Bob is observed within 20 msec
If all of these conditions are met, the alert replaces "Out-Of-Order" and "Retransmission".
TCP Spurious Retransmission
This alert is marked on Alice's packets. Although Alice should not need to retransmit due to receiving an ACK from Bob, it retransmits. The most likely cause is that Bob's ACK packet was lost between the capture device and Alice. (Thus, the issue lies between the capture device and Alice, not between Bob and the capture device.)
It is set under the following conditions:
- Not a keep-alive packet
- Segment length is greater than zero
- Alice has already sent data with this Seq#, and an Ack# has been received from Bob
- The expected next Seq# from Bob is less than or equal to the last observed Ack#
If all of these conditions are met, the alert replaces "TCP Fast Retransmission", "Out-Of-Order", and "Retransmission".
According to the Wireshark User's Guide Version 4.3.0, one condition for TCP Spurious Retransmission is "The SYN or FIN flag is set." However, this alert is typically marked on data packets, so this seems incorrect. I confirmed that TCP Spurious Retransmission packets captured at home did not have SYN or FIN flags set. (I am currently inquiring about the detailed specifications with Wireshark.)
Verified TCP Spurious Retransmission packet at home
TCP Previous segment not captured
This alert is marked on Alice's packets. It is set when the current Seq# is greater than the expected next Seq#.
This indicates that some packets from Alice are either lost by the capture device or on the actual network. This alert is also marked if the capture starts in the middle of a session, as previous packets are not visible.
Alerts Marked on Bob (Receiver) Side
TCP Dup ACK <frame>#<acknowledgment number>
This alert is marked on ACK packets from Bob. It is displayed when the same Ack# is observed for previous communications in Wireshark. Bob sends the same Ack# to Alice because it did not receive the data, indicating a high possibility of packet loss on the path from Alice.
It is set under the following conditions:
- Segment length is zero
- Window size is not zero and has not changed
- The expected next Seq# and the last observed Ack# are non-zero (indicating the connection is established)
- SYN, FIN, RST flags are not set
TCP ACKed unseen segment
This alert is marked on ACK packets from Bob. It indicates that Bob is acknowledging data from Alice that Wireshark did not capture. This suggests packet loss by the capture device or that the data from Alice existed before capturing started.
However, since an ACK packet exists for the data, it differs from "TCP Previous segment not captured" in that there is no packet loss on Alice's path. This means the TCP communication is functioning correctly without issues.
Packet Capture Devices without Loss
Our packet capture product, SYNESIS, is designed to ensure performance without packet loss during capture, regardless of packet length. Without reliable packet capture devices, it is impossible to determine whether the missing packet existed on the network or was lost by the capture device. Eliminating the possibility of packet loss in the capture device ensures the captured packet data can be trusted for troubleshooting.
We offer various models for lines from 1G to 100G. If you are interested in SYNESIS, please contact us below.
Afterword
Even if the communication is smooth, various alerts may appear when visualizing packets. Some alerts may result from capturing in the middle of a session, meaning the communication might actually be normal. Not all black displays indicate anomalies. Wireshark judges based on packet content and arrival order.
If you are interested in learning packet capture, why not start by capturing familiar packets? You might discover unexpected things different from your assumptions.
My recent discovery was the higher-than-expected percentage of IPv6 traffic. Wireshark's Protocol Hierarchy Statistics showed 7.5% IPv6 traffic. (I expected less, depending on the task.) I also found a graph on IPv6 adoption from Google's statistics, shown below.
The graph indicates that IPv6 has started to become widely adopted only in the past decade. The first RFC for IPv6, RFC1883, was published in 1995, almost 30 years ago. The current Standard Track, RFC8200, was published in 2017. Although not as long as TCP, IPv6 has a considerable history in RFCs.