- cb->s_flags |= SF_DELACK;
- if (SSEQ_GT(si->si_ack,cb->s_rack)) {
- cb->s_rack = si->si_ack;
- cb->s_timer[TCPT_REXMT] = 0;
-
- /*
- * If transmit timer is running and timed sequence
- * number was acked, update smoothed round trip time.
- */
- if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) {
- if (cb->s_srtt == 0)
- cb->s_srtt = cb->s_rtt;
- else
- cb->s_srtt =
- tcp_alpha * cb->s_srtt +
- (1 - tcp_alpha) * cb->s_rtt;
- cb->s_rtt = 0;
+ cb->s_flags |= (spp_use_delack ? SF_DELACK : SF_ACKNOW);
+ if (SSEQ_GT(si->si_alo, cb->s_ralo))
+ cb->s_flags |= SF_WIN;
+ if (SSEQ_LEQ(si->si_ack, cb->s_rack)) {
+ if ((si->si_cc & SP_SP) && cb->s_rack != (cb->s_smax + 1)) {
+ sppstat.spps_rcvdupack++;
+ /*
+ * If this is a completely duplicate ack
+ * and other conditions hold, we assume
+ * a packet has been dropped and retransmit
+ * it exactly as in tcp_input().
+ */
+ if (si->si_ack != cb->s_rack ||
+ si->si_alo != cb->s_ralo)
+ cb->s_dupacks = 0;
+ else if (++cb->s_dupacks == spprexmtthresh) {
+ u_short onxt = cb->s_snxt;
+ int cwnd = cb->s_cwnd;
+
+ cb->s_snxt = si->si_ack;
+ cb->s_cwnd = CUNIT;
+ cb->s_force = 1 + SPPT_REXMT;
+ (void) spp_output(cb, (struct mbuf *)0);
+ cb->s_timer[SPPT_REXMT] = cb->s_rxtcur;
+ cb->s_rtt = 0;
+ if (cwnd >= 4 * CUNIT)
+ cb->s_cwnd = cwnd / 2;
+ if (SSEQ_GT(onxt, cb->s_snxt))
+ cb->s_snxt = onxt;
+ return (1);
+ }
+ } else
+ cb->s_dupacks = 0;
+ goto update_window;
+ }
+ cb->s_dupacks = 0;
+ /*
+ * If our correspondent acknowledges data we haven't sent
+ * TCP would drop the packet after acking. We'll be a little
+ * more permissive
+ */
+ if (SSEQ_GT(si->si_ack, (cb->s_smax + 1))) {
+ sppstat.spps_rcvacktoomuch++;
+ si->si_ack = cb->s_smax + 1;
+ }
+ sppstat.spps_rcvackpack++;
+ /*
+ * If transmit timer is running and timed sequence
+ * number was acked, update smoothed round trip time.
+ * See discussion of algorithm in tcp_input.c
+ */
+ if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) {
+ sppstat.spps_rttupdated++;
+ if (cb->s_srtt != 0) {
+ register short delta;
+ delta = cb->s_rtt - (cb->s_srtt >> 3);
+ if ((cb->s_srtt += delta) <= 0)
+ cb->s_srtt = 1;
+ if (delta < 0)
+ delta = -delta;
+ delta -= (cb->s_rttvar >> 2);
+ if ((cb->s_rttvar += delta) <= 0)
+ cb->s_rttvar = 1;
+ } else {
+ /*
+ * No rtt measurement yet
+ */
+ cb->s_srtt = cb->s_rtt << 3;
+ cb->s_rttvar = cb->s_rtt << 1;