Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 07 Mar 2001 10:47:06 -0500
From:      "Louis A. Mamakos" <louie@TransSys.COM>
To:        Ruslan Ermilov <ru@FreeBSD.ORG>
Cc:        Jonathan Lemon <jlemon@flugsvamp.com>, Jonathan Lemon <jlemon@FreeBSD.ORG>, net@FreeBSD.ORG
Subject:   Re: Delayed checksums commit broke UDP checksum calculation 
Message-ID:  <200103071547.f27Fl6a00528@whizzo.transsys.com>
In-Reply-To: Your message of "Wed, 07 Mar 2001 17:19:56 %2B0200." <20010307171956.B36537@sunbay.com> 
References:  <20001116120936.A45755@sunbay.com> <20001116091954.A19895@prism.flugsvamp.com> <20010307123156.A19829@sunbay.com> <200103071440.f27EeYa99809@whizzo.transsys.com> <20010307164822.E97252@sunbay.com> <200103071458.f27EwWa99960@whizzo.transsys.com> <20010307171956.B36537@sunbay.com> 

next in thread | previous in thread | raw e-mail | index | archive | help

> In two's complement arithmetics, yes.  What matters here is how the
> the real checkers are implemented.  For BSD-derived implementations,
> this does not matter.  I don't know if others really exist.  RFC 1624
> is pretty clear on this topic.  The usual Internet principle is in place
> (from RFC 791): "In general, an implementation must be conservative in
> its sending behavior, and liberal in its receiving behavior.  That is,
> it must be careful to send well-formed datagrams, but must accept any
> datagram that it can interpret (e.g., not object to technical errors
> where the meaning is still clear)."

> To be CONSERVATIVE, the implementation MUST NOT transmit all-zero
> computed TCP checksum as all-ones; while they are certainly equivalent
> in two's complement arithmetics, but RFC 793 does not grant us to do
> this conversion (as opposed to RFC 768), and there may an implementation
> exist that computes checksums from scratch using the "shift-and-add-carry"
> algorithm to compute the two's complement sum on a non-two's-complement
> hardware, and compare the result with what stored in the checksum field.
> In this case, +0 and -0 will differ.

I disagree on your conservative interpretation of the spec.  Here's
the text from RFC 793, on TCP, and what it has to say about the
checksum computation:

  Checksum:  16 bits

    The checksum field is the 16 bit one's complement of the one's
    complement sum of all 16 bit words in the header and text.  If a
    segment contains an odd number of header and text octets to be
    checksummed, the last octet is padded on the right with zeros to
    form a 16 bit word for checksum purposes.  The pad is not
    transmitted as part of the segment.  While computing the checksum,
    the checksum field itself is replaced with zeros.

    The checksum also covers a 96 bit pseudo header conceptually
    prefixed to the TCP header.  This pseudo header contains the Source
    Address, the Destination Address, the Protocol, and TCP length.
    This gives the TCP protection against misrouted segments.  This
    information is carried in the Internet Protocol and is transferred
    across the TCP/Network interface in the arguments or results of
    calls by the TCP on the IP.

                     +--------+--------+--------+--------+
                     |           Source Address          |
                     +--------+--------+--------+--------+
                     |         Destination Address       |
                     +--------+--------+--------+--------+
                     |  zero  |  PTCL  |    TCP Length   |
                     +--------+--------+--------+--------+

      The TCP Length is the TCP header length plus the data length in
      octets (this is not an explicitly transmitted quantity, but is
      computed), and it does not count the 12 octets of the pseudo
      header.

For the sake of illustration, assume that you're computing a checksum
over segment which contains all zeros.  This will produce a sum with
a value of zero.  When you take the 16 bit one's complement of this
value, you end up with 0xFFFF which is supposed to be put into the
checksum field. 

For other segments which you're computing the checksum over, a
properly implemented 1's complement arithemetic sum will produce
a normalized +0 (0x0000) rather than a negative zero (0xFFFF).  So
when you get to the step of taking the 1's complement (the logical
NOT operation), you'll never start with 0xFFFF to produce a 0x0000
result.  Of course the problem is that all these modern systems
apparently don't have high-fidelity emulation of 1's complement
add operations and are computing a -0 value along the way.

> To be LIBERAL, the implementation SHOULD verify checksums by computing
> the checksum using the value stored in the checksum field, and comparing
> the result with zero, as opposed to computing the checksum from scratch
> and comparing with the value stored in the checksum field.

But computing a checksum with either 0xffff or 0x0000 WILL produce
the same result if you are implementing the Internet 1's complement
checksum algorithm correctly. 

I can assure you that the stack I wrote in 1981, which ran on a
1's complement-based CPU sent TCP checksums with value 0xFFFF in
the packet header, and it works Just Fine.  I don't see how
reading that section of the TCP protocol spec would lead you to
believe otherwise.

louie




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200103071547.f27Fl6a00528>