+ /*
+ * If we have outstanding data (not a
+ * window probe), this is a completely
+ * duplicate ack (ie, window info didn't
+ * change), the ack is the biggest we've
+ * seen and we've seen exactly our rexmt
+ * threshhold of them, assume a packet
+ * has been dropped and retransmit it.
+ * Kludge snd_nxt & the congestion
+ * window so we send only this one
+ * packet. If this packet fills the
+ * only hole in the receiver's seq.
+ * space, the next real ack will fully
+ * open our window. This means we
+ * have to do the usual slow-start to
+ * not overwhelm an intermediate gateway
+ * with a burst of packets. Leave
+ * here with the congestion window set
+ * to allow 2 packets on the next real
+ * ack and the exp-to-linear thresh
+ * set for half the current window
+ * size (since we know we're losing at
+ * the current window size).
+ */
+ if (tp->t_timer[TCPT_REXMT] == 0 ||
+ ti->ti_ack != tp->snd_una)
+ tp->t_dupacks = 0;
+ else if (++tp->t_dupacks == tcprexmtthresh) {
+ tcp_seq onxt = tp->snd_nxt;
+ u_int win =
+ MIN(tp->snd_wnd, tp->snd_cwnd) / 2 /
+ tp->t_maxseg;
+
+ if (win < 2)
+ win = 2;
+ tp->snd_ssthresh = win * tp->t_maxseg;
+
+ tp->t_timer[TCPT_REXMT] = 0;
+ tp->t_rtt = 0;
+ tp->snd_nxt = ti->ti_ack;
+ tp->snd_cwnd = tp->t_maxseg;
+ (void) tcp_output(tp);
+
+ if (SEQ_GT(onxt, tp->snd_nxt))
+ tp->snd_nxt = onxt;
+ goto drop;
+ }
+ } else
+ tp->t_dupacks = 0;