Wireshark-bugs: [Wireshark-bugs] [Bug 7703] TCP "Bytes in flight" Calculation incorrect

Date: Fri, 14 Sep 2012 12:25:14 -0700 (PDT)
https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=7703

--- Comment #3 from Paul Munford <munford@xxxxxxxxxx> 2012-09-14 12:25:13 PDT ---
(In reply to comment #2)
> Hmm.  It seems that Wireshark is being smarter than just subtracting the
> current sequence number from the last ACK.  In particular what it is doing is
> adding up the sequence numbers of the unacknowledged messages that *Wireshark
> has seen*.  The last bit is important because, as you can see from TCP's
> warning on frame 47, a bunch of packets weren't captured/seen (352920 bytes
> worth).  The "last ack" (frame 58) is acking a TCP segment that's not even in
> the capture file (it's prior to the first frame).
> 
> IOW Wireshark is calculating the bytes in flight (in this direction) by adding
> up the size of these segments:
> 
> Frame:54 Seq:3592761289 Nextseq:3592762001
> Frame:53 Seq:3592759829 Nextseq:3592761289
> Frame:52 Seq:3592758369 Nextseq:3592759829
> Frame:51 Seq:3592756909 Nextseq:3592758369
> Frame:50 Seq:3592755449 Nextseq:3592756909
> Frame:49 Seq:3592753989 Nextseq:3592755449
> Frame:48 Seq:3592752529 Nextseq:3592753989
> Frame:47 Seq:3592751069 Nextseq:3592752529
> Frame:6 Seq:3592406689 Nextseq:3592408149
> Frame:5 Seq:3592405229 Nextseq:3592406689
> Frame:4 Seq:3592403769 Nextseq:3592405229
> Frame:3 Seq:3592402309 Nextseq:3592403769
> Frame:2 Seq:3592400849 Nextseq:3592402309
> 
> (since they are all the segments Wireshark has seen and they are all
> unacknowledged.)
> 
> It's not immediately obvious to me why Wireshark does it this way, but it does
> look fairly intentional (well, at least this method certainly seems harder than
> looking at the last ACK and subtracting!), so I'll leave this bug as-is for now
> in case someone with more TCP knowledge comes along.

In my opinion, the absolute "smartest" that Wireshark should be expected to be
would be to take into account:
   - the ACK value in the TCP header
   - Bytes acknowledged by the LeftEdge/RightEdge pairs in the SACK fields of
the TCP options portion of the TCP header.

This also would be questionable, however, or at least strategically
"interesting" to make this assumption in the math.  I say this because RFC793
clearly indicates that the Sender cannot send a sequence number that is larger
than "rcv.nxt + rcv.wnd - 1"  (where "rcv.nxt" = the next expected seqnum = the
ACK field in the TCP header, "rcv.wnd" = the receive window size of the
recipient).

If the Sender transmits any sequence number higher than this, it is a violation
of basic TCP premise.  therefore, the actual bytes in flight (unacknowledged
bytes, including taking into account bytes acknowledge by SACK) is, to some
extent, interesting... but most "sane" TCP Transmitters will stop transmitting
at "seg.ack + rcv.wnd" (where seg.ack = the value of the ACK field in the TCP
header, as received by the sender, and "rcv.wnd" would be the value of the
Recipients TCP Receive Window as seen in the most recent ACK from the
recipient).

in other words, knowing the true number of "unacked bytes" is of value, but if
SACK is enabled, this will not drive the behavior of the transmitter in most
TCP clients. (HPUX, sadly and notably, has a user-configurable option allowing
it to ignore this TCP RFC requirement) (Solaris used to have a bug where this
was not enforced, as well, and it caused problems).

Given the explanation of how this calculation is being done, the current method
is highly questionable.  If there are any packets missing from the capture flow
(previous segment lost, acking lost segment, etc), it is not reasonable to
assume anything about the data wireshark has available related to those missing
segments, and coagulate that questionable knowledge into some more
sophisticated awareness.  Missing packets in the capture negates the ability to
mathematically track bytes in flight by accounting for each packet
individually.

Unless someone knows better, most modern network stacks should only be
considering:
   "what I have sent"
   "what the recipient has acknowledged in the most recent ACK"  

Perhaps the real answer is to have two tcp.analysis fields (choose what names
you want, just making a point):

1) tcp.analysis.highest_expected_sequence = tcp.nxtseq - [most recent] tcp.ack
2) tcp.analysis.bytes_in_flight = 
   [from most recent data packet]  tcp.nxtseq - 
           [from most recent ack]  tcp.ack -
                                   tcp.options.sack_re1 - tcp.options.sack_le1
                                   tcp.options.sack_re2 - tcp.options.sack_le2
                                   tcp.options.sack_re3 - tcp.options.sack_le3
                                   tcp.options.sack_re4 - tcp.options.sack_le4
   where sack_re1, sack_re2, sack_re3, sack_re4 indicate the right edge of each
of the four allowed ranges in the SACK field of the Options section of the TCP
header.

In this manner, the "true" bytes in flight will only ever require knowledge of
the most recent data packet from the sender and the most recent prior ACK from
the recipient.

-- 
Configure bugmail: https://bugs.wireshark.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are watching all bug changes.