Consider this code in tcp_output.c and tcp_input.c

Randall Stewart rrs at
Thu May 12 09:50:26 UTC 2016


Here are a couple blocks of code from input/output

         * Segment received on connection.
         * Reset idle time and keep-alive timer.
         * XXX: This should be done after segment
         * validation to ignore broken/spoofed segs.
        tp->t_rcvtime = ticks;


         * Determine length of data that should be transmitted,
         * and flags that will be used.
         * If there is some data or critical controls (SYN, RST)
         * to send, then transmit; otherwise, investigate further.
        idle = (tp->t_flags & TF_LASTIDLE) || (tp->snd_max == tp->snd_una);
        if (idle && ticks - tp->t_rcvtime >= tp->t_rxtcur)


Now this works just fine if you are the sender of the data.. i.e. we go idle, and then 
you call send(…) to the peer.

However what happens if say you are a CDN?

Your client goes idle, its gotten everything.. for some period of time, maybe its playing out
its play-buffer or what ever..

Then it sends in a request, "please send me a large block of data”?

You then start to stream out your 2Meg block of data….

Since you received a request at tp->t_rcvtime to send you a big block of data
the timestamp is current.

So you blast out 2Meg using your old cwnd/ssthresh and send a nice line-rate
burst… which of course hits tail drops and other fun :-)

I believe we need to have something like:
if ((tp->snd_max == tp->and_una) && ((ticks - tp->t_rcvtime) >= tp->t_rxtcur))) {
tp->t_rcvtime = ticks;
added so we catch both sides of the equation..


Randall Stewart
rrs at

More information about the freebsd-transport mailing list