Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 18 Mar 2010 16:19:53 -0400
From:      "Chris Harrer" <cjharrer@comcast.net>
To:        <freebsd-net@freebsd.org>
Subject:   Bug in tcp_output?
Message-ID:  <006f01cac6d8$5fc03cb0$1f40b610$@net>

next in thread | raw e-mail | index | archive | help
Hi All,

=20

In the following block of code, running on a x86_64 platform, I believe =
that
cwin should be declared as an int:

        /*

         * If snd_nxt =3D=3D snd_max and we have transmitted a FIN, the

         * offset will be > 0 even if so_snd.sb_cc is 0, resulting in

         * a negative length.  This can also occur when TCP opens up

         * its congestion window while receiving additional duplicate

         * acks after fast-retransmit because TCP will reset snd_nxt

         * to snd_max after the fast-retransmit.

         *

         * In the normal retransmit-FIN-only case, however, snd_nxt will

         * be set to snd_una, the offset will be 0, and the length may

         * wind up 0.

         *

         * If sack_rxmit is true we are retransmitting from the =
scoreboard

         * in which case len is already set.

         */

        if (sack_rxmit =3D=3D 0) {

               if (sack_bytes_rxmt =3D=3D 0)

                       len =3D ((long)ulmin(so->so_snd.sb_cc, sendwin) - =
off);

               else {

                       long cwin;  =DF-- Should be an int

=20

                        /*

                        * We are inside of a SACK recovery episode and =
are

                        * sending new data, having retransmitted all the

                        * data possible in the scoreboard.

                        */

                       len =3D ((long)ulmin(so->so_snd.sb_cc, =
tp->snd_wnd)=20

                              - off);

                       /*

                        * Don't remove this (len > 0) check !

                        * We explicitly check for len > 0 here (although =
it=20

                        * isn't really necessary), to work around a gcc=20

                        * optimization issue - to force gcc to compute

                        * len above. Without this check, the computation

                        * of len is bungled by the optimizer.

                        */

                       if (len > 0) {

                               cwin =3D tp->snd_cwnd -=20

                                      (tp->snd_nxt - tp->sack_newdata) -

                                      sack_bytes_rxmt;

                               if (cwin < 0)

                                      cwin =3D 0;

                               len =3D lmin(len, cwin);

                       }

               }

        }

=20

Consider the case where:

sack_rxmit =3D 0

sack_bytes_rxmt =3D 0x2238

off =3D 0

len =3D0xa19c

tp->snd_cwnd =3D 0x2238

tp->snd_nxt =3D 0xdd6d7974

tp->sack_newdata =3D 0xdd6d6858

In this case cwin evaluates to 0x00000000ffffe37c, which is not <0, but
instead huge.  This causes the remaining data on the socket=92s =
so->so_snd
buffer to be sent to the network causing more problems at the receiver =
which
is already dropping frames.

Thanks,

=20

Chris




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?006f01cac6d8$5fc03cb0$1f40b610$>