Subject: Re: kern/34674: Panic in tcp_input() by integer division fault
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Michael van Elst <mlelstv@serpens.de>
List: netbsd-bugs
Date: 10/01/2006 11:25:02
The following reply was made to PR kern/34674; it has been noted by GNATS.
From: Michael van Elst <mlelstv@serpens.de>
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: kern/34674: Panic in tcp_input() by integer division fault
Date: Sun, 1 Oct 2006 13:24:00 +0200
christianbiere@gmx.de (Christian Biere) writes:
> eip points into tcp_input(). I've dumped the assembler code of tcp_input()
> and uploaded it here:
>
> http://ghostwhitecrab.de/trash/gdb.log.bz2
The division by zero occurs here:
* When new data is acked, open the congestion window.
* If the window gives us less than ssthresh packets
* in flight, open exponentially (segsz per packet).
* Otherwise open linearly: segsz per window
* (segsz^2 / cwnd per packet).
*
* If we are still in fast recovery (meaning we are using
* NewReno and we have only received partial acks), do not
* inflate the window yet.
*/
if (tp->t_partialacks < 0) {
u_int cw = tp->snd_cwnd;
u_int incr = tp->t_segsz;
if (cw >= tp->snd_ssthresh)
--------> incr = incr * incr / cw;
tp->snd_cwnd = min(cw + incr,
TCP_MAXWIN << tp->snd_scale);
}
with cw == 0.
> The "culprit" is definitely /sys/netinet/tcp_output.c rev. 1.144.
from tcp_output.c:
[...]
*txsegsizep = min((so->so_snd.sb_hiwat -
so->so_snd.sb_lowat + 1) >> 1, *txsegsizep);
[...]
tp->snd_cwnd = max((tp->snd_cwnd / tp->t_segsz)
* *txsegsizep, *txsegsizep);
tp->snd_ssthresh = max((tp->snd_ssthresh / tp->t_segsz)
* *txsegsizep, *txsegsizep);
With 1.144 txsegsizep can become zero when sb_hiwat and sb_lowat are
identical. Then snd_cwnd and snd_ssthresh both become zero.
With 1.143 the computation of txsegsize is a bit different:
*txsegsizep = min(so->so_snd.sb_hiwat >> 1, *txsegsizep);
--
Michael van Elst
Internet: mlelstv@serpens.de
"A potential Snark may lurk in every tree."