These changes represent a rewrite of retransmission policies to
authorKeith Sklower <sklower@ucbvax.Berkeley.EDU>
Fri, 27 Sep 1991 08:02:46 +0000 (00:02 -0800)
committerKeith Sklower <sklower@ucbvax.Berkeley.EDU>
Fri, 27 Sep 1991 08:02:46 +0000 (00:02 -0800)
imitate the TCP algorithms more closely.  More tuning and testing need to
be done, but the code runs at least somewhat, and these represent a checkpoint

SCCS-vsn: sys/netiso/tp_subr.c 7.15
SCCS-vsn: sys/netiso/tp_pcb.c 7.18
SCCS-vsn: sys/netiso/tp_pcb.h 7.17
SCCS-vsn: sys/netiso/tp.trans 7.14
SCCS-vsn: sys/netiso/tp_subr2.c 7.14
SCCS-vsn: sys/netiso/tp_emit.c 7.12
SCCS-vsn: sys/netiso/tp_input.c 7.23
SCCS-vsn: sys/netiso/tp_param.h 7.10
SCCS-vsn: sys/netiso/tp_timer.c 7.10

usr/src/sys/netiso/tp.trans
usr/src/sys/netiso/tp_emit.c
usr/src/sys/netiso/tp_input.c
usr/src/sys/netiso/tp_param.h
usr/src/sys/netiso/tp_pcb.c
usr/src/sys/netiso/tp_pcb.h
usr/src/sys/netiso/tp_subr.c
usr/src/sys/netiso/tp_subr2.c
usr/src/sys/netiso/tp_timer.c

index dae91ad..882e6d2 100644 (file)
@@ -5,7 +5,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp.trans    7.13 (Berkeley) %G%
+ *     @(#)tp.trans    7.14 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -59,7 +59,7 @@ SOFTWARE.
 
 *INCLUDE
 {
 
 *INCLUDE
 {
-/* @(#)tp.trans        7.13 (Berkeley) %G% */
+/* @(#)tp.trans        7.14 (Berkeley) %G% */
 #include "param.h"
 #include "socket.h"
 #include "socketvar.h"
 #include "param.h"
 #include "socket.h"
 #include "socketvar.h"
@@ -91,7 +91,7 @@ void  tp_indicate(),                          tp_getoptions(),
                tp_soisdisconnecting(),         tp_soisdisconnected(),
                tp_recycle_tsuffix(),           
                tp_etimeout(),                          tp_euntimeout(),
                tp_soisdisconnecting(),         tp_soisdisconnected(),
                tp_recycle_tsuffix(),           
                tp_etimeout(),                          tp_euntimeout(),
-               tp_euntimeout_lss(),            tp_ctimeout(),
+               tp_ctimeout(),
                tp_cuntimeout(),                        tp_ctimeout_MIN(),
                tp_freeref(),                           tp_detach(),
                tp0_stash(),                            tp0_send(),
                tp_cuntimeout(),                        tp_ctimeout_MIN(),
                tp_freeref(),                           tp_detach(),
                tp0_stash(),                            tp0_send(),
@@ -132,14 +132,12 @@ TP_CONFIRMING     /* Local to this implementation */
                                 */
 
  TM_sendack            
                                 */
 
  TM_sendack            
-                               /* TM_sendack does dual duty - keepalive AND sendack.
+                               /* TM_sendack does dual duty - keepalive AND closed-window
+                                * Probes.
                                 * It's set w/ keepalive-ticks every time an ack is sent.
                                 * (this is done in (void) tp_emit() ).
                                 * It's set w/ keepalive-ticks every time an ack is sent.
                                 * (this is done in (void) tp_emit() ).
-                                * It's cancelled and reset whenever a DT
-                                * arrives and it doesn't require immediate acking.
-                                * Note that in this case it's set w/ the minimum of
-                                * its prev value and the sendack-ticks value so the 
-                                * purpose of the keepalive is preserved.
+                                * Whenever a DT arrives which doesn't require immediate acking,
+                                * a separate fast-timeout flag is set ensuring 200ms response.
                                 */
  TM_notused    
 
                                 */
  TM_notused    
 
@@ -304,7 +302,7 @@ TP_CLOSED           <==             [ TP_LISTENING, TP_CLOSED ]                     T_DETACH
 TP_CONFIRMING  <==              TP_LISTENING                                                           CR_TPDU 
        ( $P.tp_class == TP_CLASS_0)
        {
 TP_CONFIRMING  <==              TP_LISTENING                                                           CR_TPDU 
        ( $P.tp_class == TP_CLASS_0)
        {
-               $P.tp_refp->tpr_state = REF_OPEN; /* has timers ??? */
+               $P.tp_refstate = REF_OPEN; /* has timers ??? */
        }
 ;
 
        }
 ;
 
@@ -317,7 +315,7 @@ TP_CONFIRMING               <==              TP_LISTENING                                                   CR_TPDU
                IFDEBUG(D_CONN)
                        printf("CR datalen 0x%x data 0x%x", $$.e_datalen, $$.e_data);
                ENDDEBUG
                IFDEBUG(D_CONN)
                        printf("CR datalen 0x%x data 0x%x", $$.e_datalen, $$.e_data);
                ENDDEBUG
-               $P.tp_refp->tpr_state = REF_OPEN; /* has timers */
+               $P.tp_refstate = REF_OPEN; /* has timers */
                $P.tp_fcredit = $$.e_cdt;
 
                if ($$.e_datalen > 0) {
                $P.tp_fcredit = $$.e_cdt;
 
                if ($$.e_datalen > 0) {
@@ -358,9 +356,9 @@ TP_AKWAIT           <==              TP_CONFIRMING                                                          T_ACPT_req
                tp_getoptions($P);
                soisconnecting($P.tp_sock);
                if (($P.tp_rx_strat & TPRX_FASTSTART) && ($P.tp_fcredit > 0))
                tp_getoptions($P);
                soisconnecting($P.tp_sock);
                if (($P.tp_rx_strat & TPRX_FASTSTART) && ($P.tp_fcredit > 0))
-                       $P.tp_cong_win = $P.tp_fcredit;
+                       $P.tp_cong_win = $P.tp_fcredit * $P.tp_l_tpdusize;
                $P.tp_retrans = $P.tp_Nretrans;
                $P.tp_retrans = $P.tp_Nretrans;
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cc_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_cc_ticks);
        }
 ;
 
        }
 ;
 
@@ -403,10 +401,10 @@ TP_CRSENT         <==             TP_CLOSED                                                               T_CONN_req
                if (error = tp_emit(CR_TPDU_type, $P, 0, 0, data) )
                        return error; /* driver WON'T change state; will return error */
                
                if (error = tp_emit(CR_TPDU_type, $P, 0, 0, data) )
                        return error; /* driver WON'T change state; will return error */
                
-               $P.tp_refp->tpr_state = REF_OPEN; /* has timers */
+               $P.tp_refstate = REF_OPEN; /* has timers */
                if($P.tp_class != TP_CLASS_0) {
                        $P.tp_retrans = $P.tp_Nretrans;
                if($P.tp_class != TP_CLASS_0) {
                        $P.tp_retrans = $P.tp_Nretrans;
-                       tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cr_ticks);
+                       tp_ctimeout($P, TM_retrans, (int)$P.tp_cr_ticks);
                }
        }
 ;
                }
        }
 ;
@@ -424,12 +422,12 @@ TP_REFWAIT                <==             [ TP_CRSENT, TP_AKWAIT, TP_OPEN ]                       DR_TPDU
                tp_soisdisconnected($P);
                if ($P.tp_class != TP_CLASS_0) {
                        if ($P.tp_state == TP_OPEN ) {
                tp_soisdisconnected($P);
                if ($P.tp_class != TP_CLASS_0) {
                        if ($P.tp_state == TP_OPEN ) {
-                               tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
-                               tp_cuntimeout($P.tp_refp, TM_retrans);
-                               tp_cuntimeout($P.tp_refp, TM_inact);
-                               tp_cuntimeout($P.tp_refp, TM_sendack);
+                               tp_euntimeout($P, TM_data_retrans); /* all */
+                               tp_cuntimeout($P, TM_retrans);
+                               tp_cuntimeout($P, TM_inact);
+                               tp_cuntimeout($P, TM_sendack);
                        }
                        }
-                       tp_cuntimeout($P.tp_refp, TM_retrans);
+                       tp_cuntimeout($P, TM_retrans);
                        if( $$.e_sref !=  0 ) 
                                (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL);
                }
                        if( $$.e_sref !=  0 ) 
                                (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL);
                }
@@ -442,8 +440,8 @@ SAME                        <==             TP_CLOSED                                                                       DR_TPDU
                if( $$.e_sref != 0 )
                        (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL); 
                /* reference timer already set - reset it to be safe (???) */
                if( $$.e_sref != 0 )
                        (void) tp_emit(DC_TPDU_type, $P, 0, 0, MNULL); 
                /* reference timer already set - reset it to be safe (???) */
-               tp_euntimeout($P.tp_refp, TM_reference); /* all */
-               tp_etimeout($P.tp_refp, TM_reference, 0, 0, 0, (int)$P.tp_refer_ticks);
+               tp_euntimeout($P, TM_reference); /* all */
+               tp_etimeout($P, TM_reference, (int)$P.tp_refer_ticks);
        }
 ;
 
        }
 ;
 
@@ -451,7 +449,7 @@ SAME                        <==             TP_CLOSED                                                                       DR_TPDU
 TP_REFWAIT             <==     TP_CRSENT                                                                       ER_TPDU
        DEFAULT
        {       
 TP_REFWAIT             <==     TP_CRSENT                                                                       ER_TPDU
        DEFAULT
        {       
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_cuntimeout($P, TM_retrans);
                tp_indicate(ER_TPDU, $P, $$.e_reason);
                tp_soisdisconnected($P);
        }
                tp_indicate(ER_TPDU, $P, $$.e_reason);
                tp_soisdisconnected($P);
        }
@@ -461,7 +459,7 @@ TP_REFWAIT          <==     TP_CRSENT                                                                       ER_TPDU
 TP_REFWAIT             <==             TP_CLOSING                                                                      DR_TPDU
        DEFAULT
        {        
 TP_REFWAIT             <==             TP_CLOSING                                                                      DR_TPDU
        DEFAULT
        {        
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_cuntimeout($P, TM_retrans);
                tp_soisdisconnected($P);
        }
 ;
                tp_soisdisconnected($P);
        }
 ;
@@ -473,7 +471,7 @@ TP_REFWAIT          <==             TP_CLOSING                                                                      ER_TPDU
        DEFAULT
        {        
                tp_indicate(ER_TPDU, $P, $$.e_reason);
        DEFAULT
        {        
                tp_indicate(ER_TPDU, $P, $$.e_reason);
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_cuntimeout($P, TM_retrans);
                tp_soisdisconnected($P);
        }
 ;
                tp_soisdisconnected($P);
        }
 ;
@@ -481,7 +479,7 @@ TP_REFWAIT          <==             TP_CLOSING                                                                      ER_TPDU
 TP_REFWAIT             <==             TP_CLOSING                                                                      DC_TPDU 
        DEFAULT
        {        
 TP_REFWAIT             <==             TP_CLOSING                                                                      DC_TPDU 
        DEFAULT
        {        
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_cuntimeout($P, TM_retrans);
                tp_soisdisconnected($P);
        }
 ;
                tp_soisdisconnected($P);
        }
 ;
@@ -510,14 +508,14 @@ TP_CLOSING                <==     [ TP_AKWAIT, TP_OPEN ]                                          ER_TPDU
        DEFAULT
        {
                if ($P.tp_state == TP_OPEN) {
        DEFAULT
        {
                if ($P.tp_state == TP_OPEN) {
-                       tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
-                       tp_cuntimeout($P.tp_refp, TM_inact);
-                       tp_cuntimeout($P.tp_refp, TM_sendack);
+                       tp_euntimeout($P, TM_data_retrans); /* all */
+                       tp_cuntimeout($P, TM_inact);
+                       tp_cuntimeout($P, TM_sendack);
                }
                tp_soisdisconnecting($P.tp_sock);
                tp_indicate(ER_TPDU, $P, $$.e_reason);
                $P.tp_retrans = $P.tp_Nretrans;
                }
                tp_soisdisconnecting($P.tp_sock);
                tp_indicate(ER_TPDU, $P, $$.e_reason);
                $P.tp_retrans = $P.tp_Nretrans;
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_PROTO_ERR, MNULL);
        }
 ;
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_PROTO_ERR, MNULL);
        }
 ;
@@ -525,7 +523,7 @@ TP_CLOSING          <==     [ TP_AKWAIT, TP_OPEN ]                                          ER_TPDU
 TP_OPEN                        <==             TP_CRSENT                                                                       CC_TPDU 
        ($P.tp_class == TP_CLASS_0) 
        {       
 TP_OPEN                        <==             TP_CRSENT                                                                       CC_TPDU 
        ($P.tp_class == TP_CLASS_0) 
        {       
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_cuntimeout($P, TM_retrans);
                IncStat(ts_tp0_conn);
                $P.tp_fcredit = 1;
                soisconnected($P.tp_sock);
                IncStat(ts_tp0_conn);
                $P.tp_fcredit = 1;
                soisconnected($P.tp_sock);
@@ -542,11 +540,10 @@ TP_OPEN                   <==             TP_CRSENT                                                                       CC_TPDU
                IncStat(ts_tp4_conn);
                $P.tp_fref = $$.e_sref;
                $P.tp_fcredit = $$.e_cdt;
                IncStat(ts_tp4_conn);
                $P.tp_fref = $$.e_sref;
                $P.tp_fcredit = $$.e_cdt;
-               $P.tp_ackrcvd = 0;
                if (($P.tp_rx_strat & TPRX_FASTSTART) && ($$.e_cdt > 0))
                if (($P.tp_rx_strat & TPRX_FASTSTART) && ($$.e_cdt > 0))
-                       $P.tp_cong_win = $$.e_cdt;
+                       $P.tp_cong_win = $$.e_cdt * $P.tp_l_tpdusize;
                tp_getoptions($P);
                tp_getoptions($P);
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_cuntimeout($P, TM_retrans);
                if ($P.tp_ucddata) {
                        IFDEBUG(D_CONN)
                                printf("dropping user connect data cc 0x%x\n",
                if ($P.tp_ucddata) {
                        IFDEBUG(D_CONN)
                                printf("dropping user connect data cc 0x%x\n",
@@ -563,7 +560,7 @@ TP_OPEN                     <==             TP_CRSENT                                                                       CC_TPDU
                }
 
                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL);
                }
 
                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL);
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
        }
 ;
 
        }
 ;
 
@@ -575,8 +572,7 @@ SAME                        <==             TP_CRSENT                                                                       TM_retrans
                int error;
 
                IncStat(ts_retrans_cr);
                int error;
 
                IncStat(ts_retrans_cr);
-               $P.tp_cong_win = 1;
-               $P.tp_ackrcvd = 0;
+               $P.tp_cong_win = 1 * $P.tp_l_tpdusize;
                data = MCPY($P.tp_ucddata, M_NOWAIT);
                if($P.tp_ucddata) {
                        IFDEBUG(D_CONN)
                data = MCPY($P.tp_ucddata, M_NOWAIT);
                if($P.tp_ucddata) {
                        IFDEBUG(D_CONN)
@@ -591,7 +587,7 @@ SAME                        <==             TP_CRSENT                                                                       TM_retrans
                if( error = tp_emit(CR_TPDU_type, $P, 0, 0, data) ) {
                        $P.tp_sock->so_error = error;
                }
                if( error = tp_emit(CR_TPDU_type, $P, 0, 0, data) ) {
                        $P.tp_sock->so_error = error;
                }
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cr_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_cr_ticks);
        }
 ;
 
        }
 ;
 
@@ -621,7 +617,7 @@ SAME                        <==      TP_AKWAIT                                                                                      CR_TPDU
                        $P.tp_sock->so_error = error;
                }
                $P.tp_retrans = $P.tp_Nretrans;
                        $P.tp_sock->so_error = error;
                }
                $P.tp_retrans = $P.tp_Nretrans;
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cc_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_cc_ticks);
        }
 ;
 
        }
 ;
 
@@ -640,10 +636,10 @@ TP_OPEN                   <==             TP_AKWAIT                                                                               DT_TPDU
                        m_freem($P.tp_ucddata);
                        $P.tp_ucddata = 0;
                }
                        m_freem($P.tp_ucddata);
                        $P.tp_ucddata = 0;
                }
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
+               tp_cuntimeout($P, TM_retrans);
                soisconnected($P.tp_sock);
                soisconnected($P.tp_sock);
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
 
                /* see also next 2 transitions, if you make any changes */
 
 
                /* see also next 2 transitions, if you make any changes */
 
@@ -652,11 +648,11 @@ TP_OPEN                   <==             TP_AKWAIT                                                                               DT_TPDU
                        printf("tp_stash returns %d\n",doack);
                ENDDEBUG
 
                        printf("tp_stash returns %d\n",doack);
                ENDDEBUG
 
-               if(doack) {
+               if (doack) {
                        (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
                        (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
-                       tp_ctimeout($P.tp_refp, TM_sendack, (int)$P.tp_keepalive_ticks);
+                       tp_ctimeout($P, TM_sendack, (int)$P.tp_keepalive_ticks);
                } else
                } else
-                       tp_ctimeout( $P.tp_refp, TM_sendack, (int)$P.tp_sendack_ticks);
+                       tp_ctimeout( $P, TM_sendack, (int)$P.tp_sendack_ticks);
                
                IFDEBUG(D_DATA)
                        printf("after stash calling sbwakeup\n");
                
                IFDEBUG(D_DATA)
                        printf("after stash calling sbwakeup\n");
@@ -683,7 +679,7 @@ SAME                        <==             TP_OPEN                                                                         DT_TPDU
        {
                int doack; /* tells if we must ack immediately */
 
        {
                int doack; /* tells if we must ack immediately */
 
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                sbwakeup( &$P.tp_sock->so_rcv );
 
                doack = tp_stash($P, $E);
                sbwakeup( &$P.tp_sock->so_rcv );
 
                doack = tp_stash($P, $E);
@@ -694,7 +690,7 @@ SAME                        <==             TP_OPEN                                                                         DT_TPDU
                if(doack)
                        (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
                else
                if(doack)
                        (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
                else
-                       tp_ctimeout_MIN( $P.tp_refp, TM_sendack, (int)$P.tp_sendack_ticks);
+                       tp_ctimeout_MIN( $P, TM_sendack, (int)$P.tp_sendack_ticks);
                
                IFDEBUG(D_DATA)
                        printf("after stash calling sbwakeup\n");
                
                IFDEBUG(D_DATA)
                        printf("after stash calling sbwakeup\n");
@@ -721,7 +717,7 @@ SAME                        <==     [ TP_OPEN, TP_AKWAIT ]                                                  DT_TPDU
                ENDTRACE
                IncStat(ts_dt_niw);
                m_freem($$.e_data);
                ENDTRACE
                IncStat(ts_dt_niw);
                m_freem($$.e_data);
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
        }
 ;
                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL ); 
        }
 ;
@@ -735,7 +731,7 @@ TP_OPEN                     <==             TP_AKWAIT                                                                               AK_TPDU
                        $P.tp_ucddata = 0;
                }
                (void) tp_goodack($P, $$.e_cdt, $$.e_seq, $$.e_subseq);
                        $P.tp_ucddata = 0;
                }
                (void) tp_goodack($P, $$.e_cdt, $$.e_seq, $$.e_subseq);
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_cuntimeout($P, TM_retrans);
 
                soisconnected($P.tp_sock);
                IFTRACE(D_CONN)
 
                soisconnected($P.tp_sock);
                IFTRACE(D_CONN)
@@ -748,8 +744,8 @@ TP_OPEN                     <==             TP_AKWAIT                                                                               AK_TPDU
                                so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head);
                ENDTRACE
 
                                so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head);
                ENDTRACE
 
-               tp_ctimeout($P.tp_refp, TM_sendack, (int)$P.tp_keepalive_ticks);
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+               tp_ctimeout($P, TM_sendack, (int)$P.tp_keepalive_ticks);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
        }
 ;
 
        }
 ;
 
@@ -762,10 +758,10 @@ TP_OPEN           <==     [ TP_OPEN, TP_AKWAIT ]                                          XPD_TPDU
                                m_freem($P.tp_ucddata);
                                $P.tp_ucddata = 0;
                        }
                                m_freem($P.tp_ucddata);
                                $P.tp_ucddata = 0;
                        }
-                       tp_cuntimeout($P.tp_refp, TM_retrans);
+                       tp_cuntimeout($P, TM_retrans);
                        soisconnected($P.tp_sock);
                        soisconnected($P.tp_sock);
-                       tp_ctimeout($P.tp_refp, TM_sendack, (int)$P.tp_keepalive_ticks);
-                       tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+                       tp_ctimeout($P, TM_sendack, (int)$P.tp_keepalive_ticks);
+                       tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                } 
                IFTRACE(D_XPD)
                tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n",
                } 
                IFTRACE(D_XPD)
                tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n",
@@ -833,7 +829,7 @@ SAME                        <==     [ TP_AKWAIT, TP_OPEN ]                                                  XPD_TPDU
                        IncStat(ts_xpd_dup);
                }
                m_freem($$.e_data);
                        IncStat(ts_xpd_dup);
                }
                m_freem($$.e_data);
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                /* don't send an xack because the xak gives "last one received", not
                 * "next one i expect" (dumb)
                 */
                /* don't send an xack because the xak gives "last one received", not
                 * "next one i expect" (dumb)
                 */
@@ -879,7 +875,7 @@ TP_CLOSING          <== [ TP_CLOSING, TP_AKWAIT, TP_CRSENT, TP_CONFIRMING ] T_DETACH
                        data = MCPY($P.tp_ucddata, M_NOWAIT);
                        (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_NORMAL_DISC, data);
                        $P.tp_retrans = $P.tp_Nretrans;
                        data = MCPY($P.tp_ucddata, M_NOWAIT);
                        (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_NORMAL_DISC, data);
                        $P.tp_retrans = $P.tp_Nretrans;
-                       tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
+                       tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
                }
        }
 ;
                }
        }
 ;
@@ -900,9 +896,9 @@ TP_CLOSING          <==     [ TP_AKWAIT, TP_OPEN, TP_CRSENT, TP_CONFIRMING ]  T_DISC_req
                struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
 
                if($P.tp_state == TP_OPEN) {
                struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT);
 
                if($P.tp_state == TP_OPEN) {
-                       tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
-                       tp_cuntimeout($P.tp_refp, TM_inact);
-                       tp_cuntimeout($P.tp_refp, TM_sendack);
+                       tp_euntimeout($P, TM_data_retrans); /* all */
+                       tp_cuntimeout($P, TM_inact);
+                       tp_cuntimeout($P, TM_sendack);
                }
                if (data) {
                        IFDEBUG(D_CONN)
                }
                if (data) {
                        IFDEBUG(D_CONN)
@@ -913,7 +909,7 @@ TP_CLOSING          <==     [ TP_AKWAIT, TP_OPEN, TP_CRSENT, TP_CONFIRMING ]  T_DISC_req
                }
                tp_soisdisconnecting($P.tp_sock);
                $P.tp_retrans = $P.tp_Nretrans;
                }
                tp_soisdisconnecting($P.tp_sock);
                $P.tp_retrans = $P.tp_Nretrans;
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
 
                if( trick_hc )
                        return tp_emit(DR_TPDU_type, $P, 0, $$.e_reason, data);
 
                if( trick_hc )
                        return tp_emit(DR_TPDU_type, $P, 0, $$.e_reason, data);
@@ -929,12 +925,11 @@ SAME                      <==             TP_AKWAIT                                                                       TM_retrans
 
                IncStat(ts_retrans_cc);
                $P.tp_retrans --;
 
                IncStat(ts_retrans_cc);
                $P.tp_retrans --;
-               $P.tp_cong_win = 1;
-               $P.tp_ackrcvd = 0;
+               $P.tp_cong_win = 1 * $P.tp_l_tpdusize;
 
                if( error = tp_emit(CC_TPDU_type, $P, 0, 0, data) ) 
                        $P.tp_sock->so_error = error;
 
                if( error = tp_emit(CC_TPDU_type, $P, 0, 0, data) ) 
                        $P.tp_sock->so_error = error;
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_cc_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_cc_ticks);
        }
 ;
 
        }
 ;
 
@@ -948,7 +943,7 @@ TP_CLOSING          <==             TP_AKWAIT                                                                       TM_retrans
                tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST, MNULL);
                $P.tp_retrans = $P.tp_Nretrans;
                tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST, MNULL);
                $P.tp_retrans = $P.tp_Nretrans;
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
        }
 ;
 
        }
 ;
 
@@ -961,9 +956,9 @@ TP_CLOSING          <==             TP_AKWAIT                                                                       TM_retrans
 TP_CLOSING             <==             TP_OPEN            [ TM_inact, TM_retrans, TM_data_retrans ]
        DEFAULT
        {
 TP_CLOSING             <==             TP_OPEN            [ TM_inact, TM_retrans, TM_data_retrans ]
        DEFAULT
        {
-               tp_euntimeout($P.tp_refp, TM_data_retrans); /* all */
-               tp_cuntimeout($P.tp_refp, TM_inact); 
-               tp_cuntimeout($P.tp_refp, TM_sendack);
+               tp_euntimeout($P, TM_data_retrans); /* all */
+               tp_cuntimeout($P, TM_inact); 
+               tp_cuntimeout($P, TM_sendack);
 
                IncStat(ts_conn_gaveup);
                tp_soisdisconnecting($P.tp_sock);
 
                IncStat(ts_conn_gaveup);
                tp_soisdisconnecting($P.tp_sock);
@@ -971,7 +966,7 @@ TP_CLOSING          <==             TP_OPEN            [ TM_inact, TM_retrans, TM_data_retrans ]
                tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST_2, MNULL);
                $P.tp_retrans = $P.tp_Nretrans;
                tp_indicate(T_DISCONNECT, $P, ETIMEDOUT);
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_CONGEST_2, MNULL);
                $P.tp_retrans = $P.tp_Nretrans;
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
        }
 ;
 
        }
 ;
 
@@ -979,18 +974,15 @@ TP_CLOSING                <==             TP_OPEN            [ TM_inact, TM_retrans, TM_data_retrans ]
 SAME                   <==             TP_OPEN                                                                         TM_retrans
        ( $P.tp_retrans > 0 )
        {
 SAME                   <==             TP_OPEN                                                                         TM_retrans
        ( $P.tp_retrans > 0 )
        {
-               $P.tp_cong_win = 1;
-               $P.tp_ackrcvd = 0;
+               $P.tp_cong_win = 1 * $P.tp_l_tpdusize;
                /* resume XPD */
                if      ( $P.tp_Xsnd.sb_mb )  {
                        struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, (int)$P.tp_Xsnd.sb_cc);
                /* resume XPD */
                if      ( $P.tp_Xsnd.sb_mb )  {
                        struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, (int)$P.tp_Xsnd.sb_cc);
-                       /* m_copy doesn't preserve the m_xlink field, but at this pt.
-                        * that doesn't matter
-                        */
+                       int shift;
 
                        IFTRACE(D_XPD)
 
                        IFTRACE(D_XPD)
-                               tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndhiwat snduna",
-                                       $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndhiwat, 
+                               tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndnxt snduna",
+                                       $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndnxt, 
                                        $P.tp_snduna); 
                        ENDTRACE
                        IFDEBUG(D_XPD)
                                        $P.tp_snduna); 
                        ENDTRACE
                        IFDEBUG(D_XPD)
@@ -998,62 +990,19 @@ SAME                      <==             TP_OPEN                                                                         TM_retrans
                        ENDDEBUG
                        IncStat(ts_retrans_xpd);
                        $P.tp_retrans --;
                        ENDDEBUG
                        IncStat(ts_retrans_xpd);
                        $P.tp_retrans --;
+                       shift = max($P.tp_Nretrans - $P.tp_retrans, 6);
                        (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                        (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
-                       tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_xpd_ticks);
+                       tp_ctimeout($P, TM_retrans, ((int)$P.tp_dt_ticks) << shift);
                }
        }
 ;
 
 /* TP4 only */
 SAME                   <==             TP_OPEN                                                                 TM_data_retrans
                }
        }
 ;
 
 /* TP4 only */
 SAME                   <==             TP_OPEN                                                                 TM_data_retrans
-       ( $$.e_retrans > 0 )
+       ($P.tp_rxtshift < TP_NRETRANS)
        {       
        {       
-               register        SeqNum                  low, lowsave = 0;
-               register        struct mbuf     *m, *n = $P.tp_sock->so_snd.sb_mb;
-               register        SeqNum                  high = $$.e_high;
-
-               low = $P.tp_snduna;
-               lowsave = high = low;
-
-               tp_euntimeout_lss($P.tp_refp, TM_data_retrans,
-                       SEQ_ADD($P, $P.tp_sndhiwat, 1));
-               $P.tp_retrans_hiwat = $P.tp_sndhiwat;
-
-               if (($P.tp_rx_strat & TPRX_EACH) == 0)
-                       high = (high>low)?low:high;
-
-               if( $P.tp_rx_strat & TPRX_USE_CW ) {
-                       register int i;
-
-                       $P.tp_cong_win = 1;
-                       $P.tp_ackrcvd = 0;
-                       i = SEQ_ADD($P, low, $P.tp_cong_win);
-
-                       high = SEQ_MIN($P, high, $P.tp_sndhiwat);
-
-               }
-
-               while (SEQ_LEQ($P, low, high)) {
-                       if (n) {
-                               if ((m = m_copy(n, 0, M_COPYALL))== MNULL)
-                                       break;
-                               (void) tp_emit(DT_TPDU_type, $P,
-                                       low, (m->m_flags & M_EOR) != 0, m);
-                               IncStat(ts_retrans_dt);
-                               SEQ_INC($P, low );
-                       }
-                       n = n->m_nextpkt;
-               }
-/* CE_BIT
-               if ( SEQ_LEQ($P, lowsave, high) ){
-*/
-                       $$.e_retrans --;
-                       tp_etimeout($P.tp_refp, TM_data_retrans, (caddr_t)lowsave,
-                                       (caddr_t)high, $$.e_retrans,
-                                       ($P.tp_Nretrans - $$.e_retrans) * (int)$P.tp_dt_ticks);
-/* CE_BIT
-               }
-*/
+               $P.tp_rxtshift++;
+               (void) tp_data_retrans($P);
        }
 ;
 
        }
 ;
 
@@ -1064,7 +1013,7 @@ SAME                      <==             TP_CLOSING                                                                      TM_retrans
                $P.tp_retrans --;
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_DR_NO_REAS, MNULL);
                IncStat(ts_retrans_dr);
                $P.tp_retrans --;
                (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_DR_NO_REAS, MNULL);
                IncStat(ts_retrans_dr);
-               tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_dr_ticks);
+               tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks);
        }
 ;
 
        }
 ;
 
@@ -1073,9 +1022,9 @@ TP_REFWAIT                <==             TP_CLOSING                                                                      TM_retrans
        DEFAULT /* no more retrans - gave up */
        {       
                $P.tp_sock->so_error = ETIMEDOUT;
        DEFAULT /* no more retrans - gave up */
        {       
                $P.tp_sock->so_error = ETIMEDOUT;
-               $P.tp_refp->tpr_state = REF_FROZEN;
+               $P.tp_refstate = REF_FROZEN;
                tp_recycle_tsuffix( $P );
                tp_recycle_tsuffix( $P );
-               tp_etimeout($P.tp_refp, TM_reference, 0,0,0, (int)$P.tp_refer_ticks);
+               tp_etimeout($P, TM_reference, (int)$P.tp_refer_ticks);
        }
 ;
 
        }
 ;
 
@@ -1098,7 +1047,7 @@ SAME                      <==     TP_OPEN                                                         [ CR_TPDU, CC_TPDU ]
        DEFAULT
        {       
                if( $P.tp_class != TP_CLASS_0) {
        DEFAULT
        {       
                if( $P.tp_class != TP_CLASS_0) {
-                       tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+                       tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                        if ( $E.ev_number == CC_TPDU )
                                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL); 
                }
                        if ( $E.ev_number == CC_TPDU )
                                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 0, MNULL); 
                }
@@ -1111,8 +1060,8 @@ SAME                      <==     TP_OPEN                                                                 T_DATA_req
        DEFAULT
        {
                IFTRACE(D_DATA)
        DEFAULT
        {
                IFTRACE(D_DATA)
-                       tptrace(TPPTmisc, "T_DATA_req sndhiwat snduna fcredit, tpcb",
-                               $P.tp_sndhiwat, $P.tp_snduna, $P.tp_fcredit, $P);
+                       tptrace(TPPTmisc, "T_DATA_req sndnxt snduna fcredit, tpcb",
+                               $P.tp_sndnxt, $P.tp_snduna, $P.tp_fcredit, $P);
                ENDTRACE
 
                tp_send($P);
                ENDTRACE
 
                tp_send($P);
@@ -1137,8 +1086,8 @@ SAME                      <==             TP_OPEN                                                                         T_XPD_req
                         */
 
                        IFTRACE(D_XPD)
                         */
 
                        IFTRACE(D_XPD)
-                               tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndhiwat snduna",
-                                       $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndhiwat, 
+                               tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndnxt snduna",
+                                       $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndnxt, 
                                        $P.tp_snduna); 
                        ENDTRACE
                        IFDEBUG(D_XPD)
                                        $P.tp_snduna); 
                        ENDTRACE
                        IFDEBUG(D_XPD)
@@ -1148,7 +1097,8 @@ SAME                      <==             TP_OPEN                                                                         T_XPD_req
                        error = 
                                tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                        $P.tp_retrans = $P.tp_Nretrans;
                        error = 
                                tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                        $P.tp_retrans = $P.tp_Nretrans;
-                       tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_xpd_ticks);
+
+                       tp_ctimeout($P, TM_retrans, (int)$P.tp_rxtcur);
                        SEQ_INC($P, $P.tp_Xsndnxt);
                } 
                if(trick_hc)
                        SEQ_INC($P, $P.tp_Xsndnxt);
                } 
                if(trick_hc)
@@ -1171,48 +1121,11 @@ SAME                    <==             TP_OPEN                                                                         AK_TPDU
                        printf("GOOD ACK seq 0x%x cdt 0x%x\n", $$.e_seq, $$.e_cdt);
                ENDDEBUG
                if( $P.tp_class != TP_CLASS_0) {
                        printf("GOOD ACK seq 0x%x cdt 0x%x\n", $$.e_seq, $$.e_cdt);
                ENDDEBUG
                if( $P.tp_class != TP_CLASS_0) {
-                       tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
-                       tp_euntimeout_lss($P.tp_refp, TM_data_retrans, $$.e_seq);
+                       tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                }
                sbwakeup(sb);
                }
                sbwakeup(sb);
-               if ($P.tp_sndhiwat <= $P.tp_retrans_hiwat &&
-                       $P.tp_snduna <= $P.tp_retrans_hiwat) {
-
-                       register struct mbuf     *m, *n = sb->sb_mb;
-                       SeqNum          high, retrans, lowsave;
-
-                       high = SEQ_MIN($P, SEQ_ADD($P, $P.tp_snduna,
-                                       MIN($P.tp_cong_win, $P.tp_fcredit)) - 1,
-                                       $P.tp_sndhiwat);
-                       retrans = SEQ_MAX($P, SEQ_ADD($P, $P.tp_last_retrans, 1),
-                                       $P.tp_snduna);
-                       for (lowsave = $P.tp_snduna;
-                                       SEQ_LT($P, lowsave, retrans); SEQ_INC($P, lowsave))
-                               n = n->m_nextpkt;
-                       for (; SEQ_LEQ($P, retrans, high); SEQ_INC($P, retrans)) {
-                               if (n == 0) {
-                                       IFDEBUG(D_RTC)
-                                               printf("tp: retrans list is GONE!\n");
-                                       ENDDEBUG
-                                       break;
-                               } else if (m = m_copy(n, 0, M_COPYALL)) {
-                                       (void) tp_emit(DT_TPDU_type, $P, retrans,
-                                               (m->m_flags & M_EOR) != 0, m);
-                                       $P.tp_last_retrans = retrans;
-                                       IncStat(ts_retrans_dt);
-                               }
-                               n = n->m_nextpkt;
-                       }
-                       tp_etimeout($P.tp_refp, TM_data_retrans, (caddr_t)lowsave,
-                                       (caddr_t)high, $P.tp_retrans, (int)$P.tp_dt_ticks);
-                       if (SEQ_DEC($P, retrans) == $P.tp_retrans_hiwat)
-                               tp_send($P);
-               }
-               else {
-                       tp_send($P);
-               }
                IFDEBUG(D_ACKRECV)
                IFDEBUG(D_ACKRECV)
-                       printf("GOOD ACK new sndhiwat 0x%x\n", $P.tp_sndhiwat);
+                       printf("GOOD ACK new sndnxt 0x%x\n", $P.tp_sndnxt);
                ENDDEBUG
        }
 ;
                ENDDEBUG
        }
 ;
@@ -1232,7 +1145,7 @@ SAME                      <==             TP_OPEN                                                                          AK_TPDU
                                IncStat( ts_ackreason[_ACK_FCC_] );
                                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 1, MNULL);
                        }
                                IncStat( ts_ackreason[_ACK_FCC_] );
                                (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 1, MNULL);
                        }
-                       tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+                       tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                } 
        }
 ;
                } 
        }
 ;
@@ -1246,7 +1159,7 @@ SAME                      <==             TP_OPEN                                                                          AK_TPDU
 
                        (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                        $P.tp_retrans = $P.tp_Nretrans;
 
                        (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m);
                        $P.tp_retrans = $P.tp_Nretrans;
-                       tp_ctimeout($P.tp_refp, TM_retrans, (int)$P.tp_xpd_ticks);
+                       tp_ctimeout($P, TM_retrans, (int)$P.tp_xpd_ticks);
                        SEQ_INC($P, $P.tp_Xsndnxt);
                }
                 */
                        SEQ_INC($P, $P.tp_Xsndnxt);
                }
                 */
@@ -1260,8 +1173,8 @@ SAME                      <==     TP_OPEN                                                                         XAK_TPDU
         * also updates tp_Xuna
         */
        {       
         * also updates tp_Xuna
         */
        {       
-               tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
-               tp_cuntimeout($P.tp_refp, TM_retrans);
+               tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
+               tp_cuntimeout($P, TM_retrans);
 
                sbwakeup( &$P.tp_sock->so_snd );
 
 
                sbwakeup( &$P.tp_sock->so_snd );
 
@@ -1278,7 +1191,7 @@ SAME                      <==             TP_OPEN                                                                         XAK_TPDU
                        tptrace(TPPTmisc, "BOGUS XACK eventtype ", $E.ev_number, 0, 0,0);
                ENDTRACE
                if( $P.tp_class != TP_CLASS_0 ) {
                        tptrace(TPPTmisc, "BOGUS XACK eventtype ", $E.ev_number, 0, 0,0);
                ENDTRACE
                if( $P.tp_class != TP_CLASS_0 ) {
-                       tp_ctimeout($P.tp_refp, TM_inact, (int)$P.tp_inact_ticks);
+                       tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks);
                } 
        }
 ;
                } 
        }
 ;
@@ -1287,6 +1200,7 @@ SAME                      <==             TP_OPEN                                                                         XAK_TPDU
 SAME                   <==             TP_OPEN                                                                 TM_sendack 
        DEFAULT
        {       
 SAME                   <==             TP_OPEN                                                                 TM_sendack 
        DEFAULT
        {       
+               int timo;
                IFTRACE(D_TIMER)
                        tptrace(TPPTsendack, -1, $P.tp_lcredit, $P.tp_sent_uwe, 
                        $P.tp_sent_lcdt, 0);
                IFTRACE(D_TIMER)
                        tptrace(TPPTsendack, -1, $P.tp_lcredit, $P.tp_sent_uwe, 
                        $P.tp_sent_lcdt, 0);
index 0ae9e50..8bee83e 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_emit.c   7.11 (Berkeley) %G%
+ *     @(#)tp_emit.c   7.12 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -148,6 +148,8 @@ tp_emit(dutype,     tpcb, seq, eot, data)
        int csum_offset=0;
        int datalen = 0;
        int error = 0;
        int csum_offset=0;
        int datalen = 0;
        int error = 0;
+       SeqNum olduwe;
+       int acking_ooo;
 
        /* NOTE:
         * here we treat tpdu_li as if it DID include the li field, up until
 
        /* NOTE:
         * here we treat tpdu_li as if it DID include the li field, up until
@@ -218,9 +220,7 @@ tp_emit(dutype,     tpcb, seq, eot, data)
                                tpcb->tp_win_recv = tp_start_win << 8;
                                LOCAL_CREDIT(tpcb);
                                CONG_INIT_SAMPLE(tpcb);
                                tpcb->tp_win_recv = tp_start_win << 8;
                                LOCAL_CREDIT(tpcb);
                                CONG_INIT_SAMPLE(tpcb);
-                               tpcb->tp_ackrcvd = 0;
-                       }
-                       else
+                       } else
                                LOCAL_CREDIT(tpcb);
 
 
                                LOCAL_CREDIT(tpcb);
 
 
@@ -431,68 +431,71 @@ tp_emit(dutype,   tpcb, seq, eot, data)
                case AK_TPDU_type:/* ak not used in class 0 */
                        ASSERT( tpcb->tp_class != TP_CLASS_0); 
                        data = (struct mbuf *)0;
                case AK_TPDU_type:/* ak not used in class 0 */
                        ASSERT( tpcb->tp_class != TP_CLASS_0); 
                        data = (struct mbuf *)0;
-                       {       SeqNum olduwe = tpcb->tp_sent_uwe;
+                       olduwe = tpcb->tp_sent_uwe;
 
 
+                       if (seq != tpcb->tp_sent_rcvnxt || tpcb->tp_rsycnt == 0) {
+                               LOCAL_CREDIT( tpcb ); 
                                tpcb->tp_sent_uwe = 
                                        SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1);
                                tpcb->tp_sent_uwe = 
                                        SEQ(tpcb,tpcb->tp_rcvnxt + tpcb->tp_lcredit -1);
-                               LOCAL_CREDIT( tpcb ); 
                                tpcb->tp_sent_lcdt = tpcb->tp_lcredit;
                                tpcb->tp_sent_lcdt = tpcb->tp_lcredit;
+                               acking_ooo = 0;
+                       } else
+                               acking_ooo = 1;
 
 
-                               IFDEBUG(D_RENEG)
-                                       /* occasionally fake a reneging so 
-                                               you can test subsequencing */
-                                       if( olduwe & 0x1 ) {
-                                               tpcb->tp_reneged = 1;
-                                               IncStat(ts_ldebug);
-                                       }
-                               ENDDEBUG
-                               /* Are we about to reneg on credit? 
-                                * When might we do so?
-                                *      a) when using optimistic credit (which we no longer do).
-                                *  b) when drain() gets implemented (not in the plans).
-                                *  c) when D_RENEG is on.
-                                *  d) when DEC BIT response is implemented.
-                                *      (not- when we do this, we'll need to implement flow control
-                                *      confirmation)
-                                */
-                               if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) {
+                       IFDEBUG(D_RENEG)
+                               /* occasionally fake a reneging so 
+                                       you can test subsequencing */
+                               if( olduwe & 0x1 ) {
                                        tpcb->tp_reneged = 1;
                                        tpcb->tp_reneged = 1;
-                                       IncStat(ts_lcdt_reduced);
-                                       IFTRACE(D_CREDIT)
-                                               tptraceTPCB(TPPTmisc, 
-                                                       "RENEG: olduwe newuwe lcredit rcvnxt",
-                                                       olduwe,
-                                                       tpcb->tp_sent_uwe, tpcb->tp_lcredit,
-                                                       tpcb->tp_rcvnxt);
-                                       ENDTRACE
+                                       IncStat(ts_ldebug);
                                }
                                }
+                       ENDDEBUG
+                       /* Are we about to reneg on credit? 
+                        * When might we do so?
+                        *      a) when using optimistic credit (which we no longer do).
+                        *  b) when drain() gets implemented (not in the plans).
+                        *  c) when D_RENEG is on.
+                        *  d) when DEC BIT response is implemented.
+                        *      (not- when we do this, we'll need to implement flow control
+                        *      confirmation)
+                        */
+                       if( SEQ_LT(tpcb, tpcb->tp_sent_uwe, olduwe) ) {
+                               tpcb->tp_reneged = 1;
+                               IncStat(ts_lcdt_reduced);
+                               IFTRACE(D_CREDIT)
+                                       tptraceTPCB(TPPTmisc, 
+                                               "RENEG: olduwe newuwe lcredit rcvnxt",
+                                               olduwe,
+                                               tpcb->tp_sent_uwe, tpcb->tp_lcredit,
+                                               tpcb->tp_rcvnxt);
+                               ENDTRACE
+                       }
+                       IFPERF(tpcb)
+                               /* new lwe is less than old uwe means we're
+                                * acking before we received a whole window full
+                                */
+                               if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) {
+                                       /* tmp1 = number of pkts fewer than the full window */
+                                       register int tmp1 = 
+                                               (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt);
 
 
-                               IFPERF(tpcb)
-                                       /* new lwe is less than old uwe means we're
-                                        * acking before we received a whole window full
-                                        */
-                                       if( SEQ_LT( tpcb, tpcb->tp_rcvnxt, olduwe) ) {
-                                               /* tmp1 = number of pkts fewer than the full window */
-                                               register int tmp1 = 
-                                                       (int) SEQ_SUB( tpcb, olduwe, tpcb->tp_rcvnxt);
+                                       if(tmp1 > TP_PM_MAX)
+                                               tmp1 = TP_PM_MAX;
+                                       IncPStat( tpcb,  tps_ack_early[tmp1] );
 
 
-                                               if(tmp1 > TP_PM_MAX)
-                                                       tmp1 = TP_PM_MAX;
-                                               IncPStat( tpcb,  tps_ack_early[tmp1] );
+                                       /* tmp1 = amt of new cdt we're advertising */
+                                       tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt);
+                                       if(tmp1 > TP_PM_MAX )
+                                               tmp1 = TP_PM_MAX;
 
 
-                                               /* tmp1 = amt of new cdt we're advertising */
-                                               tmp1 = SEQ_SUB( tpcb, seq, tpcb->tp_sent_rcvnxt);
-                                               if(tmp1 > TP_PM_MAX )
-                                                       tmp1 = TP_PM_MAX;
+                                       IncPStat( tpcb, 
+                                                       tps_cdt_acked [ tmp1 ]
+                                                       [ ((tpcb->tp_lcredit > TP_PM_MAX)?
+                                                               TP_PM_MAX:tpcb->tp_lcredit) ] );
 
 
-                                               IncPStat( tpcb, 
-                                                               tps_cdt_acked [ tmp1 ]
-                                                               [ ((tpcb->tp_lcredit > TP_PM_MAX)?
-                                                                       TP_PM_MAX:tpcb->tp_lcredit) ] );
+                               }
+                       ENDPERF
 
 
-                                       }
-                               ENDPERF
-                       }
                        IFTRACE(D_ACKSEND)
                                tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 
                                        tpcb->tp_r_subseq, 0);
                        IFTRACE(D_ACKSEND)
                                tptraceTPCB(TPPTack, seq, tpcb->tp_lcredit, tpcb->tp_sent_uwe, 
                                        tpcb->tp_r_subseq, 0);
@@ -514,7 +517,8 @@ tp_emit(dutype,     tpcb, seq, eot, data)
                                hdr->tpdu_AKseq = seq;
                                hdr->tpdu_AKcdt = tpcb->tp_lcredit;
                        }
                                hdr->tpdu_AKseq = seq;
                                hdr->tpdu_AKcdt = tpcb->tp_lcredit;
                        }
-                       if ((tpcb->tp_class == TP_CLASS_4) && tpcb->tp_reneged ) {
+                       if ((tpcb->tp_class == TP_CLASS_4) &&
+                               (tpcb->tp_reneged || acking_ooo)) {
                                /* 
                                 * Ack subsequence parameter req'd if WE reneged on 
                                 * credit offered.  (ISO 8073, 12.2.3.8.2, p. 74)
                                /* 
                                 * Ack subsequence parameter req'd if WE reneged on 
                                 * credit offered.  (ISO 8073, 12.2.3.8.2, p. 74)
@@ -594,8 +598,14 @@ tp_emit(dutype,    tpcb, seq, eot, data)
                        }
                        tpcb->tp_reneged = 0;
                        tpcb->tp_sent_rcvnxt = seq;
                        }
                        tpcb->tp_reneged = 0;
                        tpcb->tp_sent_rcvnxt = seq;
-                       tp_ctimeout(tpcb->tp_refp, TM_sendack, 
-                               (int)tpcb->tp_keepalive_ticks);
+                       if (tpcb->tp_fcredit == 0) {
+                               int timo = tpcb->tp_keepalive_ticks;
+                               if (tpcb->tp_rxtshift < TP_MAXRXTSHIFT)
+                                       tpcb->tp_rxtshift++;
+                               timo = min(timo, ((int)tpcb->tp_dt_ticks) << tpcb->tp_rxtshift);
+                               tp_ctimeout(tpcb, TM_sendack, timo);
+                       } else
+                               tp_ctimeout(tpcb, TM_sendack, tpcb->tp_keepalive_ticks);
                        IncStat(ts_AK_sent);
                        IncPStat(tpcb, tps_AK_sent);
                        IFDEBUG(D_ACKSEND)
                        IncStat(ts_AK_sent);
                        IncPStat(tpcb, tps_AK_sent);
                        IFDEBUG(D_ACKSEND)
@@ -691,9 +701,13 @@ tp_emit(dutype,    tpcb, seq, eot, data)
                        tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 
        ENDTRACE
 done:
                        tpcb->tp_nlproto->nlp_output, tpcb->tp_netservice, error, datalen); 
        ENDTRACE
 done:
-       if( error == E_CO_QFULL ) {
-               tp_quench(tpcb, PRC_QUENCH);
-               return 0;
+       if (error) {
+               if (dutype == AK_TPDU_type)
+                       tp_ctimeout(tpcb, TM_sendack, 1);
+               if (error == E_CO_QFULL) {
+                       tp_quench(tpcb, PRC_QUENCH);
+                       return 0;
+               }
        }
        return error;
 }
        }
        return error;
 }
index 0210eaf..9881d64 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_input.c  7.22 (Berkeley) %G%
+ *     @(#)tp_input.c  7.23 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -846,7 +846,6 @@ again:
                        CONG_INIT_SAMPLE(tpcb);
                        CONG_UPDATE_SAMPLE(tpcb, ce_bit);
                }
                        CONG_INIT_SAMPLE(tpcb);
                        CONG_UPDATE_SAMPLE(tpcb, ce_bit);
                }
-               tpcb->tp_ackrcvd = 0;
        } else if ( dutype == ER_TPDU_type ) {
                /* 
                 * ER TPDUs have to be recognized separately
        } else if ( dutype == ER_TPDU_type ) {
                /* 
                 * ER TPDUs have to be recognized separately
@@ -863,8 +862,8 @@ again:
                e.ATTR(ER_TPDU).e_reason =  (u_char)hdr->tpdu_ERreason;
                CHECK (((int)dref <= 0 || dref >= tp_refinfo.tpr_size || 
                        (tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 ||
                e.ATTR(ER_TPDU).e_reason =  (u_char)hdr->tpdu_ERreason;
                CHECK (((int)dref <= 0 || dref >= tp_refinfo.tpr_size || 
                        (tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 ||
-                       tpcb->tp_refp->tpr_state == REF_FREE ||
-                       tpcb->tp_refp->tpr_state == REF_FROZEN),
+                       tpcb->tp_refstate == REF_FREE ||
+                       tpcb->tp_refstate == REF_FROZEN),
                       E_TP_MISM_REFS, ts_inv_dref, discard, 0)
 
        } else {
                       E_TP_MISM_REFS, ts_inv_dref, discard, 0)
 
        } else {
@@ -886,7 +885,7 @@ again:
                                ENDDEBUG
                                dref = tpcb->tp_lref;
                                sref = tpcb->tp_fref;
                                ENDDEBUG
                                dref = tpcb->tp_lref;
                                sref = tpcb->tp_fref;
-                               CHECK( (tpcb->tp_refp->tpr_state == REF_FREE), 
+                               CHECK( (tpcb->tp_refstate == REF_FREE), 
                                        E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
                                        (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
                                goto tp0_data;
                                        E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
                                        (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
                                goto tp0_data;
@@ -902,7 +901,7 @@ again:
                        CHECK( ((tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 ), 
                                E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
                                (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
                        CHECK( ((tpcb = tp_ref[dref].tpr_pcb ) == (struct tp_pcb *) 0 ), 
                                E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
                                (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
-                       CHECK( (tpcb->tp_refp->tpr_state == REF_FREE), 
+                       CHECK( (tpcb->tp_refstate == REF_FREE), 
                                E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
                                (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
                }
                                E_TP_MISM_REFS,ts_inv_dref, nonx_dref,
                                (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
                }
@@ -912,7 +911,7 @@ again:
                ENDDEBUG
 
                /* causes a DR to be sent for CC; ER for all else */
                ENDDEBUG
 
                /* causes a DR to be sent for CC; ER for all else */
-               CHECK( (tpcb->tp_refp->tpr_state == REF_FROZEN),
+               CHECK( (tpcb->tp_refstate == REF_FROZEN),
                        (dutype == CC_TPDU_type?E_TP_NO_SESSION:E_TP_MISM_REFS),
                        ts_inv_dref, respond,
                        (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
                        (dutype == CC_TPDU_type?E_TP_NO_SESSION:E_TP_MISM_REFS),
                        ts_inv_dref, respond,
                        (1 + 2 + (caddr_t)&hdr->_tpduf - (caddr_t)hdr))
@@ -1016,7 +1015,7 @@ again:
                                vb_getval(P, u_short, subseq);
                                subseq = ntohs(subseq);
                                IFDEBUG(D_ACKRECV)
                                vb_getval(P, u_short, subseq);
                                subseq = ntohs(subseq);
                                IFDEBUG(D_ACKRECV)
-                                       printf("AK Subsequence # 0x%x\n", subseq);
+                                       printf("AK dref 0x%x Subseq 0x%x\n", dref, subseq);
                                ENDDEBUG
                                break;
 
                                ENDDEBUG
                                break;
 
@@ -1033,8 +1032,8 @@ again:
                                        ysubseq = ntohs(ysubseq);
                                        ycredit = ntohs(ycredit);
                                        IFDEBUG(D_ACKRECV)
                                        ysubseq = ntohs(ysubseq);
                                        ycredit = ntohs(ycredit);
                                        IFDEBUG(D_ACKRECV)
-                                               printf("AK FCC lwe 0x%x, subseq 0x%x, cdt 0x%x\n", 
-                                                       ylwe, ysubseq, ycredit);
+                                               printf("%s%x, subseq 0x%x, cdt 0x%x dref 0x%x\n", 
+                                                       "AK FCC lwe 0x", ylwe, ysubseq, ycredit, dref);
                                        ENDDEBUG
                                }
                                break;
                                        ENDDEBUG
                                }
                                break;
index 7242382..6915146 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_param.h  7.9 (Berkeley) %G%
+ *     @(#)tp_param.h  7.10 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -70,10 +70,10 @@ extern int N_TPREF;
         * wraparound in checksumming
         * (No mtu is likely to be larger than 4K anyway...)
         */
         * wraparound in checksumming
         * (No mtu is likely to be larger than 4K anyway...)
         */
-#define                TP_NRETRANS                     5 /* was 1; cray uses 6 */
+#define                TP_NRETRANS                     12              /* TCP_MAXRXTSHIFT + 1 */
+#define                TP_MAXRXTSHIFT          6               /* factor of 64 */
 #define                TP_MAXPORT                      0xefff
 
 #define                TP_MAXPORT                      0xefff
 
-#define                TP_RTT_NUM                      0x7
 /* ALPHA: to be used in the context: gain= 1/(2**alpha), or 
  * put another way, gaintimes(x) (x)>>alpha (forgetting the case alpha==0) 
  */
 /* ALPHA: to be used in the context: gain= 1/(2**alpha), or 
  * put another way, gaintimes(x) (x)>>alpha (forgetting the case alpha==0) 
  */
@@ -308,7 +308,7 @@ bcopy((caddr_t)&(((struct tp_vbp *)(src))->tpv_val),(caddr_t)&(dst),sizeof(type)
 #if defined(ARGO_DEBUG)&&!defined(LOCAL_CREDIT_EXPAND)
 #define LOCAL_CREDIT(tpcb) tp_local_credit(tpcb)
 #else
 #if defined(ARGO_DEBUG)&&!defined(LOCAL_CREDIT_EXPAND)
 #define LOCAL_CREDIT(tpcb) tp_local_credit(tpcb)
 #else
-#define LOCAL_CREDIT(tpcb) {\
+#define LOCAL_CREDIT(tpcb) { if (tpcb->tp_rsycnt == 0) {\
     register struct sockbuf *xxsb = &((tpcb)->tp_sock->so_rcv);\
     register int xxi = sbspace(xxsb);\
     xxi = (xxi<0) ? 0 : ((xxi) / (tpcb)->tp_l_tpdusize);\
     register struct sockbuf *xxsb = &((tpcb)->tp_sock->so_rcv);\
     register int xxi = sbspace(xxsb);\
     xxi = (xxi<0) ? 0 : ((xxi) / (tpcb)->tp_l_tpdusize);\
@@ -318,18 +318,14 @@ bcopy((caddr_t)&(((struct tp_vbp *)(src))->tpv_val),(caddr_t)&(dst),sizeof(type)
         if (xxi < (tpcb)->tp_lcredit) { \
             (tpcb)->tp_lcredit = xxi; \
         } \
         if (xxi < (tpcb)->tp_lcredit) { \
             (tpcb)->tp_lcredit = xxi; \
         } \
-    } \
-    else { \
+    } else \
         (tpcb)->tp_lcredit = xxi; \
         (tpcb)->tp_lcredit = xxi; \
-    } \
-}
+} }
 #endif ARGO_DEBUG
 
 #ifdef KERNEL
 #endif ARGO_DEBUG
 
 #ifdef KERNEL
-#ifdef ARGO_DEBUG
 #include "syslog.h"
 #define printf logpri(LOG_DEBUG),addlog
 #include "syslog.h"
 #define printf logpri(LOG_DEBUG),addlog
-#endif
 
 #ifndef  tp_NSTATES 
 
 
 #ifndef  tp_NSTATES 
 
index 7d9a69e..f637d32 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_pcb.c    7.17 (Berkeley) %G%
+ *     @(#)tp_pcb.c    7.18 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -450,7 +450,7 @@ tp_soisdisconnected(tpcb)
 
        tpcb->tp_refstate = REF_FROZEN;
        tp_recycle_tsuffix(tpcb);
 
        tpcb->tp_refstate = REF_FROZEN;
        tp_recycle_tsuffix(tpcb);
-       tp_etimeout(tpcb->tp_refp, TM_reference, 0,0,0, (int)tpcb->tp_refer_ticks);
+       tp_etimeout(tpcb, TM_reference, (int)tpcb->tp_refer_ticks);
 }
 
 /*
 }
 
 /*
@@ -521,7 +521,7 @@ tp_freeref(r)
  *
  * NOTES:
  */
  *
  * NOTES:
  */
-RefNum
+u_long
 tp_getref(tpcb) 
        register struct tp_pcb *tpcb;
 {
 tp_getref(tpcb) 
        register struct tp_pcb *tpcb;
 {
@@ -620,6 +620,7 @@ tp_attach(so, protocol)
        register struct tp_pcb  *tpcb;
        int                                     error;
        int                                     dom = so->so_proto->pr_domain->dom_family;
        register struct tp_pcb  *tpcb;
        int                                     error;
        int                                     dom = so->so_proto->pr_domain->dom_family;
+       u_long                                  lref;
        extern struct tp_conn_param tp_conn_param[];
 
        IFDEBUG(D_CONN)
        extern struct tp_conn_param tp_conn_param[];
 
        IFDEBUG(D_CONN)
@@ -650,10 +651,11 @@ tp_attach(so, protocol)
        }
        bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) );
 
        }
        bzero( (caddr_t)tpcb, sizeof (struct tp_pcb) );
 
-       if ( ((tpcb->tp_lref = tp_getref(tpcb)) &  TP_ENOREF) != 0 ) { 
+       if ( ((lref = tp_getref(tpcb)) &  TP_ENOREF) != 0 ) { 
                error = ETOOMANYREFS; 
                goto bad3;
        }
                error = ETOOMANYREFS; 
                goto bad3;
        }
+       tpcb->tp_lref = lref;
        tpcb->tp_sock =  so;
        tpcb->tp_domain = dom;
        /* tpcb->tp_proto = protocol; someday maybe? */
        tpcb->tp_sock =  so;
        tpcb->tp_domain = dom;
        /* tpcb->tp_proto = protocol; someday maybe? */
@@ -668,7 +670,6 @@ tp_attach(so, protocol)
        }
        tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
 
        }
        tpcb->_tp_param = tp_conn_param[tpcb->tp_netservice];
 
-       tpcb->tp_cong_win = 1;  
        tpcb->tp_state = TP_CLOSED;
        tpcb->tp_vers  = TP_VERSION;
        tpcb->tp_notdetached = 1;
        tpcb->tp_state = TP_CLOSED;
        tpcb->tp_vers  = TP_VERSION;
        tpcb->tp_notdetached = 1;
@@ -682,13 +683,12 @@ tp_attach(so, protocol)
                        * we'll respond w/ this.
                        * Our maximum is 4096.  See tp_chksum.c comments.
                        */
                        * we'll respond w/ this.
                        * Our maximum is 4096.  See tp_chksum.c comments.
                        */
-       tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
+       tpcb->tp_cong_win = 
+               tpcb->tp_l_tpdusize = 1 << tpcb->tp_tpdusize;
 
        tpcb->tp_seqmask  = TP_NML_FMT_MASK;
        tpcb->tp_seqbit  =  TP_NML_FMT_BIT;
        tpcb->tp_seqhalf  =  tpcb->tp_seqbit >> 1;
 
        tpcb->tp_seqmask  = TP_NML_FMT_MASK;
        tpcb->tp_seqbit  =  TP_NML_FMT_BIT;
        tpcb->tp_seqhalf  =  tpcb->tp_seqbit >> 1;
-       tpcb->tp_sndhiwat = (SeqNum) - 1; /* a kludge but it works */
-       tpcb->tp_s_subseq = 0;
 
        /* attach to a network-layer protoswitch */
        if ( error =  tp_set_npcb(tpcb))
 
        /* attach to a network-layer protoswitch */
        if ( error =  tp_set_npcb(tpcb))
index f999f4a..0efdfe5 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_pcb.h    7.16 (Berkeley) %G%
+ *     @(#)tp_pcb.h    7.17 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -83,15 +83,11 @@ SOFTWARE.
 #define REF_OPENING 1  /* in use (has a pcb) but no timers */
 #define REF_FREE 0             /* free to reallocate */
 
 #define REF_OPENING 1  /* in use (has a pcb) but no timers */
 #define REF_FREE 0             /* free to reallocate */
 
-#define N_CTIMERS              6
+#define TM_NTIMERS             6
 
 struct tp_ref {
 /*     u_char                          tpr_state; /* values REF_FROZEN, etc. above */
 
 struct tp_ref {
 /*     u_char                          tpr_state; /* values REF_FROZEN, etc. above */
-/*     struct Ccallout         tpr_callout[N_CTIMERS]; /* C timers */
-/*     struct Ecallout         tpr_calltodo;                   /* list of active E timers */
 #define        tpr_state               tpr_pcb->tp_refstate
 #define        tpr_state               tpr_pcb->tp_refstate
-#define        tpr_callout             tpr_pcb->tp_refcallout
-#define        tpr_calltodo    tpr_pcb->tp_refcalltodo
        struct tp_pcb           *tpr_pcb;       /* back ptr to PCB */
 };
 
        struct tp_pcb           *tpr_pcb;       /* back ptr to PCB */
 };
 
@@ -152,38 +148,32 @@ struct tp_pcb {
 
        /* credit & sequencing info for SENDING */
        u_short                         tp_fcredit;             /* current remote credit in # packets */
 
        /* credit & sequencing info for SENDING */
        u_short                         tp_fcredit;             /* current remote credit in # packets */
-       u_short                         tp_ssthresh;    /* cong_win threshold for slow start
-                                                                                * exponential to linear switch
+       u_short                         tp_maxfcredit;  /* max remote credit in # packets */
+       u_short                         tp_dupacks;             /* intuit packet loss before rxt timo */
+       u_long                          tp_cong_win;    /* congestion window in bytes.
+                                                                                * see profuse comments in TCP code
                                                                                 */
                                                                                 */
-       u_short                         tp_cong_win;    /* congestion window : set to 1 on
-                                                                                * source quench
-                                                                                * Minimizes the amount of retrans-
-                                                                                * missions (independently of the
-                                                                                * retrans strategy).  Increased
-                                                                                * by one for each good ack received.
-                                                                                * Minimizes the amount sent in a
-                                                                                * regular tp_send() also.
+       u_long                          tp_ssthresh;    /* cong_win threshold for slow start
+                                                                                * exponential to linear switch
                                                                                 */
                                                                                 */
-       u_int   tp_ackrcvd; /* ACKs received since the send window was updated */
-       SeqNum              tp_last_retrans;
-       SeqNum              tp_retrans_hiwat;
        SeqNum                          tp_snduna;              /* seq # of lowest unacked DT */
        SeqNum                          tp_snduna;              /* seq # of lowest unacked DT */
-       SeqNum                          tp_sndhiwat;    /* highest seq # sent so far */
+       SeqNum                          tp_sndnew;              /* seq # of lowest unsent DT  */
        SeqNum                          tp_sndnum;              /* next seq # to be assigned */
        SeqNum                          tp_sndnum;              /* next seq # to be assigned */
-       struct mbuf                     *tp_sndhiwat_m; /* packet corres. to sndhiwat*/
+       SeqNum                          tp_sndnxt;              /* what to do next; poss. rxt */
+       struct mbuf                     *tp_sndnxt_m;   /* packet corres. to sndnxt*/
        int                                     tp_Nwindow;             /* for perf. measurement */
 
        /* credit & sequencing info for RECEIVING */
        int                                     tp_Nwindow;             /* for perf. measurement */
 
        /* credit & sequencing info for RECEIVING */
+       SeqNum                          tp_rcvnxt;              /* next DT seq # expect to recv */
        SeqNum                          tp_sent_lcdt;   /* cdt according to last ack sent */
        SeqNum                          tp_sent_uwe;    /* uwe according to last ack sent */
        SeqNum                          tp_sent_lcdt;   /* cdt according to last ack sent */
        SeqNum                          tp_sent_uwe;    /* uwe according to last ack sent */
-       SeqNum                          tp_rcvnxt;              /* next DT seq # expect to recv */
        SeqNum                          tp_sent_rcvnxt; /* rcvnxt according to last ack sent 
                                                                                 * needed for perf measurements only
                                                                                 */
        u_short                         tp_lcredit;             /* current local credit in # packets */
        u_short                         tp_maxlcredit;  /* needed for reassembly queue */
        struct mbuf                     **tp_rsyq;              /* unacked stuff recvd out of order */
        SeqNum                          tp_sent_rcvnxt; /* rcvnxt according to last ack sent 
                                                                                 * needed for perf measurements only
                                                                                 */
        u_short                         tp_lcredit;             /* current local credit in # packets */
        u_short                         tp_maxlcredit;  /* needed for reassembly queue */
        struct mbuf                     **tp_rsyq;              /* unacked stuff recvd out of order */
-       int                                     tp_rsycnt;              /* number of packets */
+       int                                     tp_rsycnt;              /* number of packets "" "" "" ""    */
 
        /* receiver congestion state stuff ...  */
        u_int               tp_win_recv;
 
        /* receiver congestion state stuff ...  */
        u_int               tp_win_recv;
@@ -284,7 +274,7 @@ struct tp_pcb {
        u_char                          tp_peer_acktime;        /* used for DT retrans time */
        u_char                          tp_refstate;            /* values REF_FROZEN, etc. above */
        struct tp_pcb           *tp_fasttimeo;          /* limit pcbs to examine */
        u_char                          tp_peer_acktime;        /* used for DT retrans time */
        u_char                          tp_refstate;            /* values REF_FROZEN, etc. above */
        struct tp_pcb           *tp_fasttimeo;          /* limit pcbs to examine */
-       struct Ccallout         tp_refcallout[N_CTIMERS]; /* C timers */
+       u_int                           tp_timer[TM_NTIMERS]; /* C timers */
        struct Ecallarg         tp_retransargs;         /* dunt ask ... */
 
        struct sockbuf          tp_Xsnd;                /* for expedited data */
        struct Ecallarg         tp_retransargs;         /* dunt ask ... */
 
        struct sockbuf          tp_Xsnd;                /* for expedited data */
@@ -329,17 +319,6 @@ u_int      tp_start_win;
         CONG_INIT_SAMPLE(pcb); \
     }
 
         CONG_INIT_SAMPLE(pcb); \
     }
 
-#define CONG_ACK(pcb, seq) \
-{ int   newacks = SEQ_SUB(pcb, seq, pcb->tp_snduna); \
-       if (newacks > 0) { \
-               pcb->tp_ackrcvd += newacks; \
-               if (pcb->tp_ackrcvd >= MIN(pcb->tp_fcredit, pcb->tp_cong_win)) { \
-                       ++pcb->tp_cong_win; \
-                       pcb->tp_ackrcvd = 0; \
-               } \
-       } \
-}
-
 #ifdef KERNEL
 extern struct tp_refinfo       tp_refinfo;
 extern struct timeval  time;
 #ifdef KERNEL
 extern struct tp_refinfo       tp_refinfo;
 extern struct timeval  time;
index 84c649e..f61a9ad 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_subr.c   7.14 (Berkeley) %G%
+ *     @(#)tp_subr.c   7.15 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -70,7 +70,9 @@ SOFTWARE.
 #include "tp_meas.h"
 #include "tp_seq.h"
 
 #include "tp_meas.h"
 #include "tp_seq.h"
 
-int            tp_emit(), tp_sbdrop();
+int            tp_emit(), tp_sbdrop();
+int            tprexmtthresh = 3;
+void   tp_send();
 
 /*
  * CALLED FROM:
 
 /*
  * CALLED FROM:
@@ -90,7 +92,7 @@ tp_goodXack(tpcb, seq)
 
        IFTRACE(D_XPD)
                tptraceTPCB(TPPTgotXack, 
 
        IFTRACE(D_XPD)
                tptraceTPCB(TPPTgotXack, 
-                       seq, tpcb->tp_Xuna, tpcb->tp_Xsndnxt, tpcb->tp_sndhiwat
+                       seq, tpcb->tp_Xuna, tpcb->tp_Xsndnxt, tpcb->tp_sndnew
                        tpcb->tp_snduna); 
        ENDTRACE
 
                        tpcb->tp_snduna); 
        ENDTRACE
 
@@ -115,8 +117,7 @@ tp_goodXack(tpcb, seq)
                                        (int)(tpcb->tp_Xsnd.sb_cc),
                                        0,0,0);
                        ENDTRACE
                                        (int)(tpcb->tp_Xsnd.sb_cc),
                                        0,0,0);
                        ENDTRACE
-                       sbdrop( &tpcb->tp_Xsnd, (int)(tpcb->tp_Xsnd.sb_cc));
-                       CONG_ACK(tpcb, seq);
+                       sbdroprecord(&tpcb->tp_Xsnd);
                        return 1;
        } 
        return 0;
                        return 1;
        } 
        return 0;
@@ -135,18 +136,64 @@ tp_goodXack(tpcb, seq)
  */
 
 void
  */
 
 void
-tp_rtt_rtv( rtt, rtv, newmeas )
-       register int     *rtt, *rtv;
-       int newmeas;
+tp_rtt_rtv(tpcb)
+register struct tp_pcb *tpcb;
 {
 {
-       int delta = newmeas - *rtt;
-
-       if ((*rtt += (delta >> TP_RTT_ALPHA)) <= 0)
-               *rtt = 1;
-       if (delta < 0)
-               delta = -delta;
-       if (*rtv = ((delta - *rtv) >> TP_RTV_ALPHA) <= 0)
-               *rtv = 1;
+       int new, old = tpcb->tp_dt_ticks;
+       int delta, elapsed = tick - tpcb->tp_rttemit;
+
+       if (tpcb->tp_rtt != 0) {
+               /*
+                * rtt is the smoothed round trip time in machine clock ticks (hz).
+                * it is stored as a fixed point number, unscaled (unlike the tcp
+                * srtt.  The rationale here is that it is only significant to the
+                * nearest unit of slowtimo, which is at least 8 machine clock ticks
+                * so there is no need to scale.  The smoothing is done according
+                * to the same formula as TCP (rtt = rtt*7/8 + measured_rtt/8).
+                */
+               delta = elapsed - tpcb->tp_rtt;
+               if ((tpcb->tp_rtt += (delta >> TP_RTT_ALPHA)) <= 0)
+                       tpcb->tp_rtt = 1;
+               /*
+                * rtv is a smoothed accumulated mean difference, unscaled
+                * for reasons expressed above.
+                * It is smoothed with an alpha of .75, and the round trip timer
+                * will be set to rtt + 4*rtv, also as TCP does.
+                */
+               if (delta < 0)
+                       delta = -delta;
+               if ((tpcb->tp_rtv += ((delta - tpcb->tp_rtv) >> TP_RTV_ALPHA)) <= 0)
+                       tpcb->tp_rtv = 1;
+       } else {
+               /* 
+                * No rtt measurement yet - use the unsmoothed rtt.
+                * Set the variance to half the rtt (so our first
+                * retransmit happens at 3*rtt)
+                */
+               tpcb->tp_rtt = elapsed;
+               tpcb->tp_rtv = elapsed >> 1;
+       }
+       tpcb->tp_rttemit = 0;
+       tpcb->tp_rxtshift = 0;
+       /*
+        * Quoting TCP: "the retransmit should happen at rtt + 4 * rttvar.
+        * Because of the way we do the smoothing, srtt and rttvar
+        * will each average +1/2 tick of bias.  When we compute
+        * the retransmit timer, we want 1/2 tick of rounding and
+        * 1 extra tick because of +-1/2 tick uncertainty in the
+        * firing of the timer.  The bias will give us exactly the
+        * 1.5 tick we need.  But, because the bias is
+        * statistical, we have to test that we don't drop below
+        * the minimum feasible timer (which is 2 ticks)."
+        */
+       new = (((tpcb->tp_rtt + (tpcb->tp_rtv << 2)) * PR_SLOWHZ) + hz) / hz;
+       new = MAX(new + 1, tpcb->tp_peer_acktime);
+       new = MAX(new, 2);
+       IFTRACE(D_RTT)
+               tptraceTPCB(TPPTmisc, "oldticks ,rtv, rtt, newticks",
+                       old, rtv, rtt, new);
+       ENDTRACE
+       tpcb->tp_rxtcur = tpcb->tp_dt_ticks = new;
 }
 
 /*
 }
 
 /*
@@ -172,117 +219,132 @@ int
 tp_goodack(tpcb, cdt, seq, subseq)
        register struct tp_pcb  *tpcb;
        u_int                                   cdt;
 tp_goodack(tpcb, cdt, seq, subseq)
        register struct tp_pcb  *tpcb;
        u_int                                   cdt;
-       register SeqNum                 seq, subseq;
+       register SeqNum                 seq;
+       u_int                                   subseq;
 {
 {
-       int     old_fcredit = tpcb->tp_fcredit
+       int     old_fcredit; 
        int     bang = 0;       /* bang --> ack for something heretofore unacked */
        int     bang = 0;       /* bang --> ack for something heretofore unacked */
+       u_int   bytes_acked;
 
        IFDEBUG(D_ACKRECV)
 
        IFDEBUG(D_ACKRECV)
-               printf("goodack seq 0x%x cdt 0x%x snduna 0x%x sndhiwat 0x%x\n",
-                       seq, cdt, tpcb->tp_snduna, tpcb->tp_sndhiwat);
+               printf("goodack tpcb 0x%x seq 0x%x cdt %d una 0x%x new 0x%x nxt 0x%x\n",
+                       tpcb, seq, cdt, tpcb->tp_snduna, tpcb->tp_sndnew, tpcb->tp_sndnxt);
        ENDDEBUG
        IFTRACE(D_ACKRECV)
                tptraceTPCB(TPPTgotack, 
        ENDDEBUG
        IFTRACE(D_ACKRECV)
                tptraceTPCB(TPPTgotack, 
-                       seq,cdt, tpcb->tp_snduna,tpcb->tp_sndhiwat,subseq); 
+                       seq,cdt, tpcb->tp_snduna,tpcb->tp_sndnew,subseq); 
        ENDTRACE
 
        IFPERF(tpcb)
                tpmeas(tpcb->tp_lref, TPtime_ack_rcvd, (struct timeval *)0, seq, 0, 0);
        ENDPERF
 
        ENDTRACE
 
        IFPERF(tpcb)
                tpmeas(tpcb->tp_lref, TPtime_ack_rcvd, (struct timeval *)0, seq, 0, 0);
        ENDPERF
 
-       if ( subseq != 0 && (subseq <= tpcb->tp_r_subseq) ) {
-               /* discard the ack */
-               IFTRACE(D_ACKRECV)
-                       tptraceTPCB(TPPTmisc, "goodack discard : subseq tp_r_subseq",
-                               subseq, tpcb->tp_r_subseq, 0, 0);
-               ENDTRACE
-               return 0;
-       } else {
-               tpcb->tp_r_subseq = subseq;
-       }
-
-       if ( IN_SWINDOW(tpcb, seq, 
-                       tpcb->tp_snduna, SEQ(tpcb, tpcb->tp_sndhiwat+1)) ) {
-
-               IFDEBUG(D_XPD)
-                       dump_mbuf(tpcb->tp_sock->so_snd.sb_mb, 
-                               "tp_goodack snd before sbdrop");
-               ENDDEBUG
-               tpsbcheck(tpcb, 0);
-               (void)tp_sbdrop(tpcb, seq);
-               tpsbcheck(tpcb, 1);
-
-               /* increase congestion window but don't let it get too big */
-               {
-                       register int maxcdt = tpcb->tp_xtd_format?0xffff:0xf;
-                       CONG_ACK(tpcb, seq);
+       if (seq == tpcb->tp_snduna) {
+               if (subseq < tpcb->tp_r_subseq ||
+                       (subseq == tpcb->tp_r_subseq && cdt <= tpcb->tp_fcredit)) {
+               discard_the_ack:
+                       IFDEBUG(D_ACKRECV)
+                               printf("goodack discard : tpcb 0x%x subseq %d r_subseq %d\n",
+                                       tpcb, subseq, tpcb->tp_r_subseq);
+                       ENDDEBUG
+                       goto done;
                }
                }
+               if (cdt == tpcb->tp_fcredit /*&& thus subseq > tpcb->tp_r_subseq */) {
+                       tpcb->tp_r_subseq = subseq;
+                       if (tpcb->tp_timer[TM_data_retrans] == 0)
+                               tpcb->tp_dupacks = 0;
+                       else if (++tpcb->tp_dupacks == tprexmtthresh) {
+                               /* partner went out of his way to signal with different
+                                  subsequences that he has the same lack of an expected
+                                  packet.  This may be an early indiciation of a loss */
+
+                               SeqNum onxt = tpcb->tp_sndnxt;
+                               struct mbuf *onxt_m = tpcb->tp_sndnxt_m;
+                               u_int win = min(tpcb->tp_fcredit,
+                                                       tpcb->tp_cong_win / tpcb->tp_l_tpdusize) / 2;
+                               if (win < 2)
+                                       win = 2;
+                               tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize;
+                               tpcb->tp_timer[TM_data_retrans] = 0;
+                               tpcb->tp_rttemit = 0;
+                               tpcb->tp_sndnxt = tpcb->tp_snduna;
+                               tpcb->tp_sndnxt_m = 0;
+                               tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
+                               tp_send(tpcb);
+                               tpcb->tp_cong_win = tpcb->tp_ssthresh +
+                                       tpcb->tp_dupacks * tpcb->tp_l_tpdusize;
+                               if (SEQ_GT(tpcb, onxt, tpcb->tp_sndnxt)) {
+                                       tpcb->tp_sndnxt = onxt;
+                                       tpcb->tp_sndnxt_m = onxt_m;
+                               }
 
 
-               /* Compute smoothed round trip time.
-                * Only measure rtt for tp_snduna if acked and the data
-                * were not retransmitted.
-                */
-               if (tpcb->tp_rttemit && SEQ_GT(tpcb, seq, tpcb->tp_rttseq)) {
-                       int x = tick - tpcb->tp_rttemit;
-
-                       if (tpcb->tp_rtt)
-                               tp_rtt_rtv(&(tpcb->tp_rtt), &(tpcb->tp_rtv), x);
-                       else {
-                               tpcb->tp_rtt = x;
-                               tpcb->tp_rtv = x >> 1;
-                       }
-
-                       {       /* update the global rtt, rtv stats */
-                               int i = tpcb->tp_flags & (TPF_PEER_ON_SAMENET | TPF_NLQOS_PDN);
-                               tp_rtt_rtv(tp_stat.ts_rtt + i, tp_stat.ts_rtv + i, x);
-
-                               IFTRACE(D_RTT)
-                                       tptraceTPCB(TPPTmisc, "Global rtt, rtv: i", i, 0, 0, 0);
-                               ENDTRACE
+                       } else if (tpcb->tp_dupacks > tprexmtthresh) {
+                               tpcb->tp_cong_win += tpcb->tp_l_tpdusize;
                        }
                        }
+                       goto done;
+               }
+       } else if (SEQ_LT(tpcb, seq, tpcb->tp_snduna))
+               goto discard_the_ack;
+       /*
+        * If the congestion window was inflated to account
+        * for the other side's cached packets, retract it.
+        */
+       if (tpcb->tp_dupacks > tprexmtthresh &&
+               tpcb->tp_cong_win > tpcb->tp_ssthresh)
+                       tpcb->tp_cong_win = tpcb->tp_ssthresh;
+       tpcb->tp_r_subseq = subseq;
+       old_fcredit = tpcb->tp_fcredit;
+       tpcb->tp_fcredit = cdt;
+       if (cdt > tpcb->tp_maxfcredit)
+               tpcb->tp_maxfcredit = cdt;
+       tpcb->tp_dupacks = 0;
 
 
-                       IFTRACE(D_RTT)
-                               tptraceTPCB(TPPTmisc, 
-                               "Smoothed rtt: tp_snduna, (time.sec, time.usec), peer_acktime",
-                               tpcb->tp_snduna, time.tv_sec, time.tv_usec,
-                                       tpcb->tp_peer_acktime);
-
-                               tptraceTPCB(TPPTmisc, 
-                                       "(secs): emittime diff(x) rtt, rtv",
-                                               tpcb->tp_rttemit, x, tpcb->tp_rtt, tpcb->tp_rtv);
-                       ENDTRACE
+       if (IN_SWINDOW(tpcb, seq, tpcb->tp_snduna, tpcb->tp_sndnew)) {
 
 
-                       {
-                               /* Update data retransmission timer based on the smoothed
-                                * round trip time, peer ack time, and the pseudo-arbitrary
-                                * number 2.
-                                * new ticks: (avg rtt + 4*dev)
-                                * rtt, rtv are in hz-ticks,
-                                * and slowtimo-ticks are hz / 2;
-                                * We want no less than peer ack time and no less than 2
-                                */
-
-
-                               int rtt = tpcb->tp_rtt, rtv = tpcb->tp_rtv,
-                                       old = tpcb->tp_dt_ticks, new;
-
-                               new = (((rtt + (rtv << 2)) << 1) + hz) / hz;
-                               new = MAX(new + 1, old);
-                               new = MAX(new, tpcb->tp_peer_acktime);
-                               new = MAX(new, 2);
-                               IFTRACE(D_RTT)
-                                       tptraceTPCB(TPPTmisc, "oldticks ,rtv, rtt, newticks",
-                                               old, rtv, rtt, new);
-                               ENDTRACE
-                               tpcb->tp_dt_ticks = new;
-                       }
-                       tpcb->tp_rxtcur = tpcb->tp_dt_ticks;
-                       tpcb->tp_rxtshift = 0;
+               tpsbcheck(tpcb, 0);
+               bytes_acked = tp_sbdrop(tpcb, seq);
+               tpsbcheck(tpcb, 1);
+               /*
+                * If transmit timer is running and timed sequence
+                * number was acked, update smoothed round trip time.
+                * Since we now have an rtt measurement, cancel the
+                * timer backoff (cf., Phil Karn's retransmit alg.).
+                * Recompute the initial retransmit timer.
+                */
+               if (tpcb->tp_rttemit && SEQ_GT(tpcb, seq, tpcb->tp_rttseq))
+                       tp_rtt_rtv(tpcb);
+               /*
+                * If all outstanding data is acked, stop retransmit timer.
+                * If there is more data to be acked, restart retransmit
+                * timer, using current (possibly backed-off) value.
+                * OSI combines the keepalive and persistance functions.
+                * So, there is no persistance timer per se, to restart.
+                */
+               tpcb->tp_timer[TM_data_retrans] =
+                       (seq == tpcb->tp_sndnew) ? 0 : tpcb->tp_rxtcur;
+               /*
+                * When new data is acked, open the congestion window.
+                * If the window gives us less than ssthresh packets
+                * in flight, open exponentially (maxseg per packet).
+                * Otherwise open linearly: maxseg per window
+                * (maxseg^2 / cwnd per packet), plus a constant
+                * fraction of a packet (maxseg/8) to help larger windows
+                * open quickly enough.
+                */
+               {
+                       u_int cw = tpcb->tp_cong_win, incr = tpcb->tp_l_tpdusize;
 
 
+                       incr = min(incr, bytes_acked);
+                       if (cw > tpcb->tp_ssthresh)
+                               incr = incr * incr / cw + incr / 8;
+                       tpcb->tp_cong_win =
+                               min(cw + incr, tpcb->tp_sock->so_snd.sb_hiwat);
                }
                tpcb->tp_snduna = seq;
                }
                tpcb->tp_snduna = seq;
-               tpcb->tp_retrans = tpcb->tp_Nretrans; /* CE_BIT */
-
+               if (SEQ_LT(tpcb, tpcb->tp_sndnxt, seq)) {
+                               tpcb->tp_sndnxt = seq;
+                               tpcb->tp_sndnxt_m = 0;
+               }
                bang++;
        } 
 
                bang++;
        } 
 
@@ -293,13 +355,16 @@ tp_goodack(tpcb, cdt, seq, subseq)
                IncStat(ts_zfcdt);
        }
        tpcb->tp_fcredit = cdt;
                IncStat(ts_zfcdt);
        }
        tpcb->tp_fcredit = cdt;
+       bang |= (old_fcredit < cdt);
 
 
+done:
        IFDEBUG(D_ACKRECV)
        IFDEBUG(D_ACKRECV)
-               printf("goodack returning 0x%x, bang 0x%x cdt 0x%x old_fcredit 0x%x\n",
-                       (bang || (old_fcredit < cdt) ), bang, cdt, old_fcredit );
+               printf("goodack returns 0x%x, cdt 0x%x ocdt 0x%x cwin 0x%x\n",
+                       bang, cdt, old_fcredit, tpcb->tp_cong_win);
        ENDDEBUG
        ENDDEBUG
-
-       return (bang || (old_fcredit < cdt)) ;
+       /* if (bang) XXXXX Very bad to remove this test, but somethings broken */
+               tp_send(tpcb);
+       return (bang);
 }
 
 /*
 }
 
 /*
@@ -314,17 +379,19 @@ tp_sbdrop(tpcb, seq)
        SeqNum                                  seq;
 {
        struct sockbuf *sb = &tpcb->tp_sock->so_snd;
        SeqNum                                  seq;
 {
        struct sockbuf *sb = &tpcb->tp_sock->so_snd;
-       register int i = ((int)seq)-((int)tpcb->tp_snduna);
-       int     oldcc = sb->sb_cc;
+       register int i = SEQ_SUB(tpcb, seq, tpcb->tp_snduna);
+       int     oldcc = sb->sb_cc, oldi = i;
 
 
-       if (i < 0) i += tpcb->tp_seqhalf;
-       IFDEBUG(D_ACKRECV)
-               printf("tp_sbdroping %d up through seq 0x%x\n", i, seq);
-       ENDDEBUG
+       if (i >= tpcb->tp_seqhalf)
+               printf("tp_spdropping too much -- should panic");
        while (i-- > 0)
                sbdroprecord(sb);
        while (i-- > 0)
                sbdroprecord(sb);
-       if (SEQ_LT(tpcb, tpcb->tp_sndhiwat, seq))
-               tpcb->tp_sndhiwat_m = 0;
+       IFDEBUG(D_ACKRECV)
+               printf("tp_sbdroping %d pkts %d bytes on %x at 0x%x\n",
+                       oldi, oldcc - sb->sb_cc, tpcb, seq);
+       ENDDEBUG
+       if (sb->sb_flags & SB_NOTIFY)
+               sowwakeup(tpcb->tp_sock);
        return (oldcc - sb->sb_cc);
 }
 
        return (oldcc - sb->sb_cc);
 }
 
@@ -332,9 +399,9 @@ tp_sbdrop(tpcb, seq)
  * CALLED FROM:
  *     tp.trans on user send request, arrival of AK and arrival of XAK
  * FUNCTION and ARGUMENTS:
  * CALLED FROM:
  *     tp.trans on user send request, arrival of AK and arrival of XAK
  * FUNCTION and ARGUMENTS:
- *     Emits tpdus starting at sequence number (lowseq).
+ *     Emits tpdus starting at sequence number (tpcb->tp_sndnxt).
  *     Emits until a) runs out of data, or  b) runs into an XPD mark, or
  *     Emits until a) runs out of data, or  b) runs into an XPD mark, or
- *                     c) it hits seq number (highseq)
+ *                     c) it hits seq number (highseq) limited by cong or credit.
  *
  *     If you want XPD to buffer > 1 du per socket buffer, you can
  *     modifiy this to issue XPD tpdus also, but then it'll have
  *
  *     If you want XPD to buffer > 1 du per socket buffer, you can
  *     modifiy this to issue XPD tpdus also, but then it'll have
@@ -342,133 +409,135 @@ tp_sbdrop(tpcb, seq)
  *     hand tp_emit.
  *
  *     When something is sent for the first time, its time-of-send
  *     hand tp_emit.
  *
  *     When something is sent for the first time, its time-of-send
- *     is stashed (the last RTT_NUM of them are stashed).  When the
- *     ack arrives, the smoothed round-trip time is figured using this value.
- * RETURN VALUE:
- *     the highest seq # sent successfully.
+ *     is stashed (in system clock ticks rather than pf_slowtimo ticks).
+ *  When the ack arrives, the smoothed round-trip time is figured
+ *  using this value.
  */
  */
+void
 tp_send(tpcb)
        register struct tp_pcb  *tpcb;
 {
        register int                    len;
 tp_send(tpcb)
        register struct tp_pcb  *tpcb;
 {
        register int                    len;
-       register struct mbuf    *m; /* the one we're inspecting now */
-       struct mbuf                             *mb;/* beginning of this tpdu */
-       struct mbuf                     *nextrecord; /* NOT next tpdu but next sb record */
+       register struct mbuf    *m;
+       struct mbuf                             *mb = 0;
        struct  sockbuf                 *sb = &tpcb->tp_sock->so_snd;
        struct  sockbuf                 *sb = &tpcb->tp_sock->so_snd;
-       unsigned int                    eotsdu_reached=0;
-       SeqNum                                  lowseq, highseq ;
-       SeqNum                                  lowsave; 
+       unsigned int                    eotsdu = 0;
+       SeqNum                                  highseq, checkseq;
+       int                                             idle, idleticks, off, cong_win;
 #ifdef TP_PERF_MEAS
 #ifdef TP_PERF_MEAS
-
        int                                             send_start_time = tick;
        int                                             send_start_time = tick;
+       SeqNum                                  oldnxt = tpcb->tp_sndnxt; 
 #endif TP_PERF_MEAS
 
 #endif TP_PERF_MEAS
 
-       lowsave =  lowseq = SEQ(tpcb, tpcb->tp_sndhiwat + 1);
-
-       ASSERT( tpcb->tp_cong_win > 0 && tpcb->tp_cong_win < 0xffff);
-
-       if( tpcb->tp_rx_strat & TPRX_USE_CW ) {
-                       /*first hiseq is temp vbl*/
-               highseq = MIN(tpcb->tp_fcredit, tpcb->tp_cong_win); 
-       } else {
-               highseq = tpcb->tp_fcredit;
+       idle = (tpcb->tp_snduna == tpcb->tp_sndnew);
+       if (idle) {
+               idleticks = tpcb->tp_inact_ticks - tpcb->tp_timer[TM_inact];
+               if (idleticks > tpcb->tp_dt_ticks)
+                       /*
+                        * We have been idle for "a while" and no acks are
+                        * expected to clock out any data we send --
+                        * slow start to get ack "clock" running again.
+                        */
+                       tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
        }
        }
-       highseq = SEQ(tpcb, tpcb->tp_snduna + highseq);
-               
-       SEQ_DEC(tpcb, highseq);
 
 
+       cong_win = tpcb->tp_cong_win;
+       highseq = SEQ(tpcb, tpcb->tp_fcredit + tpcb->tp_snduna);
+       if (tpcb->tp_Xsnd.sb_mb)
+               highseq = SEQ_MIN(tpcb, highseq, tpcb->tp_sndnew);
+               
        IFDEBUG(D_DATA)
        IFDEBUG(D_DATA)
-               printf( 
-                       "tp_send enter tpcb 0x%x l %d -> h %d\ndump of sb_mb:\n",
-                       tpcb, lowseq, highseq);
-               dump_mbuf(sb->sb_mb, "sb_mb:");
+               printf("tp_send enter tpcb 0x%x nxt 0x%x win %d high 0x%x\n",
+                               tpcb, tpcb->tp_sndnxt, cong_win, highseq);
        ENDDEBUG
        IFTRACE(D_DATA)
        ENDDEBUG
        IFTRACE(D_DATA)
-               tptraceTPCB( TPPTmisc, "tp_send lowsave sndhiwat snduna", 
-                       lowsave, tpcb->tp_sndhiwat,  tpcb->tp_snduna, 0);
-               tptraceTPCB( TPPTmisc, "tp_send low high fcredit congwin", 
-                       lowseq, highseq, tpcb->tp_fcredit,  tpcb->tp_cong_win);
+               tptraceTPCB( TPPTmisc, "tp_send sndnew snduna", 
+                       tpcb->tp_sndnew,  tpcb->tp_snduna, 0, 0);
+               tptraceTPCB( TPPTmisc, "tp_send tpcb->tp_sndnxt win fcredit congwin", 
+                       tpcb->tp_sndnxt, cong_win, tpcb->tp_fcredit, tpcb->tp_cong_win);
        ENDTRACE
        ENDTRACE
-
-
-       if      ( SEQ_GT(tpcb, lowseq, highseq) )
-                       return ; /* don't send, don't change hiwat, don't set timers */
-
-       ASSERT( SEQ_LEQ(tpcb, lowseq, highseq) );
-       SEQ_DEC(tpcb, lowseq);
-
-       if (tpcb->tp_Xsnd.sb_mb) {
-               IFTRACE(D_XPD)
-                       tptraceTPCB( TPPTmisc,
-                               "tp_send XPD mark low high tpcb.Xuna", 
-                               lowseq, highseq, tpcb->tp_Xsnd.sb_mb, 0);
-               ENDTRACE
-               /* stop sending here because there are unacked XPD present
-                */
-               IncStat(ts_xpd_intheway);
-               goto done;
-       }
        IFTRACE(D_DATA)
        IFTRACE(D_DATA)
-               tptraceTPCB( TPPTmisc, "tp_send 2 low high fcredit congwin", 
-                       lowseq, highseq, tpcb->tp_fcredit,  tpcb->tp_cong_win);
+               tptraceTPCB( TPPTmisc, "tp_send 2 nxt high fcredit congwin", 
+                       tpcb->tp_sndnxt, highseq, tpcb->tp_fcredit, cong_win);
        ENDTRACE
 
        ENDTRACE
 
-       if (m = tpcb->tp_sndhiwat_m)
-               mb  = m->m_nextpkt;
-       else
-               mb = sb->sb_mb;
-       while ((SEQ_LT(tpcb, lowseq, highseq)) && mb ) {
-
-               /* 
-                * In all cases, m points to mbuf containing first octet to be
-                * sent in the tpdu AFTER the one we're going to send now,
-                * or else m is null.
-                *
-                * The chain we're working on now begins at mb and has length <len>.
-                */
-
-               eotsdu_reached = (mb->m_flags & M_EOR) != 0;
-               len = mb->m_pkthdr.len;
-               IFTRACE(D_STASH)
-                       tptraceTPCB( TPPTmisc, 
-                               "tp_send mcopy low high eotsdu_reached len", 
-                               lowseq, highseq, eotsdu_reached, len);
-               ENDTRACE
-
+       if (tpcb->tp_sndnxt_m)
+               m = tpcb->tp_sndnxt_m;
+       else {
+               off = SEQ_SUB(tpcb, tpcb->tp_sndnxt, tpcb->tp_snduna);
+               for (m = sb->sb_mb; m && off > 0; m = m->m_next)
+                       off--;
+       }
+send:
+       /*
+        * Avoid silly window syndrome here . . . figure out how!
+        */
+       checkseq = tpcb->tp_sndnum;
+       if (idle && SEQ_LT(tpcb, tpcb->tp_sndnum, highseq))
+               checkseq = highseq;
+
+       while ((SEQ_LT(tpcb, tpcb->tp_sndnxt, highseq)) && m && cong_win > 0) {
+
+               eotsdu = (m->m_flags & M_EOR) != 0;
+               len = m->m_pkthdr.len;
+               if (tpcb->tp_sndnxt == checkseq && eotsdu == 0 &&
+                       len < (tpcb->tp_l_tpdusize / 2))
+                               break;  /* Nagle . . . . . */
+               cong_win -= len;
                /* make a copy - mb goes into the retransmission list 
                 * while m gets emitted.  m_copy won't copy a zero-length mbuf.
                 */
                /* make a copy - mb goes into the retransmission list 
                 * while m gets emitted.  m_copy won't copy a zero-length mbuf.
                 */
+               mb = m;
                m = m_copy(mb, 0, M_COPYALL);
                if (m == MNULL)
                m = m_copy(mb, 0, M_COPYALL);
                if (m == MNULL)
-                               goto done;
-               SEQ_INC(tpcb,lowseq);   /* it was decremented at the beginning */
-               IFTRACE(D_DATA)
+                               break;
+               IFTRACE(D_STASH)
                        tptraceTPCB( TPPTmisc, 
                        tptraceTPCB( TPPTmisc, 
-                               "tp_send emitting DT lowseq eotsdu_reached len",
-                               lowseq, eotsdu_reached, len, 0);
+                               "tp_send mcopy nxt high eotsdu len", 
+                               tpcb->tp_sndnxt, highseq, eotsdu, len);
                ENDTRACE
                ENDTRACE
-               if (mb->m_nextpkt == 0 && tpcb->tp_oktonagle) {
-                       SEQ_INC(tpcb, tpcb->tp_sndnum);
-                       tpcb->tp_oktonagle = 0;
-                       /* when headers are precomputed, may need to fill
+
+               IFDEBUG(D_DATA)
+                       printf("tp_sending tpcb 0x%x nxt 0x%x\n",
+                               tpcb, tpcb->tp_sndnxt);
+               ENDDEBUG
+               /* when headers are precomputed, may need to fill
                           in checksum here */
                           in checksum here */
-               }
                if (tpcb->tp_sock->so_error =
                if (tpcb->tp_sock->so_error =
-                       tp_emit(DT_TPDU_type, tpcb, lowseq, eotsdu_reached, m)) {
+                       tp_emit(DT_TPDU_type, tpcb, tpcb->tp_sndnxt, eotsdu, m)) {
                        /* error */
                        /* error */
-                       SEQ_DEC(tpcb, lowseq); 
-                       goto done;
+                       break;
                }
                }
-               /* set the transmit-time for computation of round-trip times */
-               if (tpcb->tp_rttemit == 0) {
-                       tpcb->tp_rttemit = tick;
-                       tpcb->tp_rttseq = lowseq;
+               m = mb->m_nextpkt;
+               tpcb->tp_sndnxt_m = m;
+               if (tpcb->tp_sndnxt == tpcb->tp_sndnew) {
+                       SEQ_INC(tpcb, tpcb->tp_sndnew);
+                       /*
+                        * Time this transmission if not a retransmission and
+                        * not currently timing anything.
+                        */
+                       if (tpcb->tp_rttemit == 0) {
+                               tpcb->tp_rttemit = tick;
+                               tpcb->tp_rttseq = tpcb->tp_sndnxt;
+                       }
+                       tpcb->tp_sndnxt = tpcb->tp_sndnew;
+               } else
+                       SEQ_INC(tpcb, tpcb->tp_sndnxt);
+               /*
+                * Set retransmit timer if not currently set.
+                * Initial value for retransmit timer is smoothed
+                * round-trip time + 2 * round-trip time variance.
+                * Initialize shift counter which is used for backoff
+                * of retransmit time.
+                */
+               if (tpcb->tp_timer[TM_data_retrans] == 0) {
+                       tpcb->tp_timer[TM_data_retrans] = tpcb->tp_dt_ticks;
+                       tpcb->tp_timer[TM_sendack] = tpcb->tp_keepalive_ticks;
+                       tpcb->tp_rxtshift = 0;
                }
                }
-               tpcb->tp_sndhiwat_m = mb;
-               mb = mb->m_nextpkt;
        }
        }
-
-done:
+       if (SEQ_GT(tpcb, tpcb->tp_sndnew, tpcb->tp_sndnum))
+               tpcb->tp_oktonagle = 0;
 #ifdef TP_PERF_MEAS
        IFPERF(tpcb)
                {
 #ifdef TP_PERF_MEAS
        IFPERF(tpcb)
                {
@@ -476,11 +545,9 @@ done:
                        int      elapsed = tick - send_start_time, *t;
                        struct timeval now;
 
                        int      elapsed = tick - send_start_time, *t;
                        struct timeval now;
 
-                       npkts = lowseq;
-                       SEQ_INC(tpcb, npkts);
-                       npkts = SEQ_SUB(tpcb, npkts, lowsave);
+                       npkts = SEQ_SUB(tpcb, tpcb->tp_sndnxt, oldnxt);
 
 
-                       if(npkts > 0) 
+                       if (npkts > 0) 
                                tpcb->tp_Nwindow++;
 
                        if (npkts > TP_PM_MAX) 
                                tpcb->tp_Nwindow++;
 
                        if (npkts > TP_PM_MAX) 
@@ -489,7 +556,7 @@ done:
                        t = &(tpcb->tp_p_meas->tps_sendtime[npkts]);
                        *t += (t - elapsed) >> TP_RTT_ALPHA;
 
                        t = &(tpcb->tp_p_meas->tps_sendtime[npkts]);
                        *t += (t - elapsed) >> TP_RTT_ALPHA;
 
-                       if ( SEQ_LT(tpcb, lowseq, highseq) ) {
+                       if (mb == 0) {
                                IncPStat(tpcb, tps_win_lim_by_data[npkts] );
                        } else {
                                IncPStat(tpcb, tps_win_lim_by_cdt[npkts] );
                                IncPStat(tpcb, tps_win_lim_by_data[npkts] );
                        } else {
                                IncPStat(tpcb, tps_win_lim_by_cdt[npkts] );
@@ -498,22 +565,16 @@ done:
                        now.tv_sec = elapsed / hz;
                        now.tv_usec = (elapsed - (hz * now.tv_sec)) * 1000000 / hz;
                        tpmeas( tpcb->tp_lref, 
                        now.tv_sec = elapsed / hz;
                        now.tv_usec = (elapsed - (hz * now.tv_sec)) * 1000000 / hz;
                        tpmeas( tpcb->tp_lref, 
-                                       TPsbsend, &elapsed, lowsave, tpcb->tp_Nwindow, npkts);
+                                       TPsbsend, &elapsed, newseq, tpcb->tp_Nwindow, npkts);
                }
        ENDPERF
 #endif TP_PERF_MEAS
 
                }
        ENDPERF
 #endif TP_PERF_MEAS
 
-       tpcb->tp_sndhiwat = lowseq;
 
 
-       if ( SEQ_LEQ(tpcb, lowsave, tpcb->tp_sndhiwat)  && 
-                       (tpcb->tp_class != TP_CLASS_0) ) 
-                       tp_etimeout(tpcb->tp_refp, TM_data_retrans, lowsave, 
-                               tpcb->tp_sndhiwat,
-                               (u_int)tpcb->tp_Nretrans, (int)tpcb->tp_dt_ticks);
        IFTRACE(D_DATA)
                tptraceTPCB( TPPTmisc, 
        IFTRACE(D_DATA)
                tptraceTPCB( TPPTmisc, 
-                       "tp_send at end: sndhiwat lowseq eotsdu_reached error",
-                       tpcb->tp_sndhiwat, lowseq, eotsdu_reached, tpcb->tp_sock->so_error);
+                       "tp_send at end: new nxt eotsdu error",
+                       tpcb->tp_sndnew, tpcb->tp_sndnxt, eotsdu, tpcb->tp_sock->so_error);
                
        ENDTRACE
 }
                
        ENDTRACE
 }
@@ -541,10 +602,9 @@ int eotsdu;
         * This presumes knowledge of sockbuf conventions.
         * TODO: allocate space for header and fill it in (once!).
         */
         * This presumes knowledge of sockbuf conventions.
         * TODO: allocate space for header and fill it in (once!).
         */
-       IFTRACE(D_DATA)
-               tptraceTPCB(TPPTmisc,
-               "SEND BF: maxsize totlen eotsdu",
-                       maxsize, totlen, eotsdu, 0);
+       IFDEBUG(D_DATA)
+               printf("SEND BF: maxsize %d totlen %d eotsdu %d sndnum 0x%x\n",
+                       maxsize, totlen, eotsdu, tpcb->tp_sndnum);
        ENDTRACE
        if (tpcb->tp_oktonagle) {
                if ((n = sb->sb_mb) == 0)
        ENDTRACE
        if (tpcb->tp_oktonagle) {
                if ((n = sb->sb_mb) == 0)
@@ -590,6 +650,10 @@ out:
                tpcb->tp_oktonagle = 1;
                TPNagleok++;
        }
                tpcb->tp_oktonagle = 1;
                TPNagleok++;
        }
+       IFDEBUG(D_DATA)
+               printf("SEND out: oktonagle %d sndnum 0x%x\n",
+                       tpcb->tp_oktonagle, tpcb->tp_sndnum);
+       ENDTRACE
        return 0;
 }
 
        return 0;
 }
 
@@ -614,7 +678,7 @@ out:
  * being in a reneged portion of the window.
  */
 
  * being in a reneged portion of the window.
  */
 
-tp_stash( tpcb, e )
+tp_stash(tpcb, e)
        register struct tp_pcb          *tpcb;
        register struct tp_event        *e;
 {
        register struct tp_pcb          *tpcb;
        register struct tp_event        *e;
 {
index 52b393e..5c7bde9 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_subr2.c  7.13 (Berkeley) %G%
+ *     @(#)tp_subr2.c  7.14 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -343,11 +343,11 @@ tp_quench( tpcb, cmd )
        ENDDEBUG
        switch(cmd) {
                case PRC_QUENCH:
        ENDDEBUG
        switch(cmd) {
                case PRC_QUENCH:
-                       tpcb->tp_cong_win = 1;
+                       tpcb->tp_cong_win = tpcb->tp_l_tpdusize;
                        IncStat(ts_quench);
                        break;
                case PRC_QUENCH2:
                        IncStat(ts_quench);
                        break;
                case PRC_QUENCH2:
-                       tpcb->tp_cong_win = 1; /* might as well quench source also */
+                       tpcb->tp_cong_win = tpcb->tp_l_tpdusize; /* might as well quench source also */
                        tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
                        IncStat(ts_rcvdecbit);
                        break;
                        tpcb->tp_decbit = TP_DECBIT_CLEAR_COUNT;
                        IncStat(ts_rcvdecbit);
                        break;
index 712b368..4198ad2 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)tp_timer.c  7.9 (Berkeley) %G%
+ *     @(#)tp_timer.c  7.10 (Berkeley) %G%
  */
 
 /***********************************************************
  */
 
 /***********************************************************
@@ -71,8 +71,6 @@ SOFTWARE.
 #include "tp_trace.h"
 #include "tp_seq.h"
 
 #include "tp_trace.h"
 #include "tp_seq.h"
 
-struct Ecallout *TP_callfree;
-struct Ecallout *TP_callout; 
 struct tp_ref *tp_ref;
 int            N_TPREF = 127;
 struct tp_refinfo tp_refinfo;
 struct tp_ref *tp_ref;
 int            N_TPREF = 127;
 struct tp_refinfo tp_refinfo;
@@ -88,63 +86,49 @@ struct      tp_pcb *tp_ftimeolist = (struct tp_pcb *)&tp_ftimeolist;
 void
 tp_timerinit()
 {
 void
 tp_timerinit()
 {
-       register struct Ecallout *e;
        register int s;
 #define GETME(x, t, n) {s = (n)*sizeof(*x); x = (t) malloc(s, M_PCB, M_NOWAIT);\
 if (x == 0) panic("tp_timerinit"); bzero((caddr_t)x, s);}
        /*
         * Initialize storage
         */
        register int s;
 #define GETME(x, t, n) {s = (n)*sizeof(*x); x = (t) malloc(s, M_PCB, M_NOWAIT);\
 if (x == 0) panic("tp_timerinit"); bzero((caddr_t)x, s);}
        /*
         * Initialize storage
         */
-       GETME(tp_ref, struct tp_ref *, 1 +  N_TPREF);
-       tp_refinfo.tpr_base = tp_ref;
        tp_refinfo.tpr_size = N_TPREF + 1;  /* Need to start somewhere */
        tp_refinfo.tpr_size = N_TPREF + 1;  /* Need to start somewhere */
+       GETME(tp_ref, struct tp_ref *, tp_refinfo.tpr_size);
+       tp_refinfo.tpr_base = tp_ref;
 #undef GETME
 }
 
 /**********************  e timers *************************/
 
 #undef GETME
 }
 
 /**********************  e timers *************************/
 
-int Enoisy = 1;
 /*
  * CALLED FROM:
  *  tp.trans all over
  * FUNCTION and ARGUMENTS:
 /*
  * CALLED FROM:
  *  tp.trans all over
  * FUNCTION and ARGUMENTS:
- * Set an E type timer.  (refp) is the ref structure.
- * Causes  fun(arg1,arg2,arg3) to be called after time t.
+ * Set an E type timer.
  */
 void
  */
 void
-tp_etimeout(refp, fun, arg1, arg2, arg3, ticks)
-       struct tp_ref   *refp;          
-       int                     fun;    /* function to be called */
-       u_int                   arg1, arg2; 
-       int                             arg3;
-       register int    ticks;
+tp_etimeout(tpcb, fun, ticks)
+       register struct tp_pcb  *tpcb;
+       int                                     fun;    /* function to be called */
+       int                                             ticks;
 {
 
 {
 
-       register struct tp_pcb *tpcb = refp->tpr_pcb;
-       register struct Ccallout *callp;
+       register u_int *callp;
        IFDEBUG(D_TIMER)
        IFDEBUG(D_TIMER)
-               printf("etimeout pcb 0x%x state 0x%x\n", refp->tpr_pcb,
-               refp->tpr_pcb->tp_state);
+               printf("etimeout pcb 0x%x state 0x%x\n", tpcb, tpcb->tp_state);
        ENDDEBUG
        IFTRACE(D_TIMER)
        ENDDEBUG
        IFTRACE(D_TIMER)
-               tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", refp-tp_ref,
-               refp->tpr_state, ticks, tp_stat.ts_Eticks);
+               tptrace(TPPTmisc, "tp_etimeout ref refstate tks Etick", tpcb->tp_lref,
+               tpcb->tp_state, ticks, tp_stat.ts_Eticks);
        ENDTRACE
        if (tpcb == 0)
                return;
        IncStat(ts_Eset);
        if (ticks == 0)
                ticks = 1;
        ENDTRACE
        if (tpcb == 0)
                return;
        IncStat(ts_Eset);
        if (ticks == 0)
                ticks = 1;
-       if (fun == TM_data_retrans) {
-               tpcb->tp_retransargs.c_arg1 = arg1;
-               tpcb->tp_retransargs.c_arg2 = arg2;
-               tpcb->tp_retransargs.c_arg3 = arg3;
-       }
-       callp = tpcb->tp_refcallout + fun;
-       if (Enoisy && callp->c_time)
-               printf("E timer allready set: %d of ref %d\n", fun, tpcb->tp_lref);
-       if (callp->c_time == 0 || callp->c_time > ticks)
-               callp->c_time = ticks;
+       callp = tpcb->tp_timer + fun;
+       if (*callp == 0 || *callp > ticks)
+               *callp = ticks;
 }
 
 /*
 }
 
 /*
@@ -154,47 +138,16 @@ tp_etimeout(refp, fun, arg1, arg2, arg3, ticks)
  *  Cancel all occurrences of E-timer function (fun) for reference (refp)
  */
 void
  *  Cancel all occurrences of E-timer function (fun) for reference (refp)
  */
 void
-tp_euntimeout(refp, fun)
-       struct tp_ref *refp;
+tp_euntimeout(tpcb, fun)
+       register struct tp_pcb  *tpcb;
        int                       fun;
 {
        int                       fun;
 {
-       register struct tp_pcb *tpcb = refp->tpr_pcb;
-
        IFTRACE(D_TIMER)
        IFTRACE(D_TIMER)
-               tptrace(TPPTmisc, "tp_euntimeout ref", refp-tp_ref, 0, 0, 0);
+               tptrace(TPPTmisc, "tp_euntimeout ref", tpcb->tp_lref, 0, 0, 0);
        ENDTRACE
 
        if (tpcb)
        ENDTRACE
 
        if (tpcb)
-               tpcb->tp_refcallout[fun].c_time = 0;
-}
-
-/*
- * CALLED FROM:
- *  tp.trans, when an incoming ACK causes things to be dropped
- *  from the retransmission queue, and we want their associated
- *  timers to be cancelled.
- *  NOTE: (by sklower) only called with TM_data_retrans.
- * FUNCTION and ARGUMENTS:
- *  cancel all occurrences of function (fun) where (arg2) < (seq)
- */
-void
-tp_euntimeout_lss(refp, fun, seq)
-       struct tp_ref *refp;
-       int                       fun;
-       SeqNum            seq;
-{
-       register struct tp_pcb *tpcb = refp->tpr_pcb;
-
-       IFTRACE(D_TIMER)
-               tptrace(TPPTmisc, "tp_euntimeoutLSS ref", refp-tp_ref, seq, 0, 0);
-       ENDTRACE
-
-       if (tpcb == 0 || tpcb->tp_refcallout[fun].c_time == 0)
-               return;
-       if (SEQ_LT(tpcb, tpcb->tp_retransargs.c_arg2, seq))  {
-                       IncStat(ts_Ecan_act);
-                       tpcb->tp_refcallout[fun].c_time = 0;
-       }
+               tpcb->tp_timer[fun] = 0;
 }
 
 /****************  c timers **********************
 }
 
 /****************  c timers **********************
@@ -218,7 +171,7 @@ tp_euntimeout_lss(refp, fun, seq)
 ProtoHook
 tp_slowtimo()
 {
 ProtoHook
 tp_slowtimo()
 {
-       register struct Ccallout        *cp, *cpbase;
+       register u_int  *cp, *cpbase;
        register struct tp_ref          *rp;
        struct tp_pcb           *tpcb;
        struct tp_event         E;
        register struct tp_ref          *rp;
        struct tp_pcb           *tpcb;
        struct tp_event         E;
@@ -230,19 +183,13 @@ tp_slowtimo()
        for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) {
                if ((tpcb = rp->tpr_pcb) == 0 || rp->tpr_state < REF_OPEN) 
                        continue;
        for (rp = tp_ref + tp_refinfo.tpr_maxopen; rp > tp_ref; rp--) {
                if ((tpcb = rp->tpr_pcb) == 0 || rp->tpr_state < REF_OPEN) 
                        continue;
-               cpbase = tpcb->tp_refcallout;
-               t = N_CTIMERS;
-               /* check the C-type timers */
+               cpbase = tpcb->tp_timer;
+               t = TM_NTIMERS;
+               /* check the timers */
                for (cp = cpbase + t; (--t, --cp) >= cpbase; ) {
                for (cp = cpbase + t; (--t, --cp) >= cpbase; ) {
-                       if (cp->c_time && --(cp->c_time) <= 0 ) {
-                               cp->c_time = 0;
+                       if (*cp && --(*cp) <= 0 ) {
+                               *cp = 0;
                                E.ev_number = t;
                                E.ev_number = t;
-                               if (t == TM_data_retrans) {
-                                       register struct Ecallarg *p1 = &tpcb->tp_retransargs;
-                                       E.ATTR(TM_data_retrans).e_low = (SeqNum) p1->c_arg1;
-                                       E.ATTR(TM_data_retrans).e_high = (SeqNum) p1->c_arg2;
-                                       E.ATTR(TM_data_retrans).e_retrans =  p1->c_arg3;
-                               }
                                IFDEBUG(D_TIMER)
                                        printf("C expired! type 0x%x\n", t);
                                ENDDEBUG
                                IFDEBUG(D_TIMER)
                                        printf("C expired! type 0x%x\n", t);
                                ENDDEBUG
@@ -265,6 +212,47 @@ tp_slowtimo()
        return 0;
 }
 
        return 0;
 }
 
+/*
+ * Called From: tp.trans from tp_slowtimo() -- retransmission timer went off.
+ */
+tp_data_retrans(tpcb)
+register struct tp_pcb *tpcb;
+{
+       int rexmt, win;
+       tpcb->tp_rttemit = 0;   /* cancel current round trip time */
+       tpcb->tp_dupacks = 0;
+       tpcb->tp_sndnxt = tpcb->tp_snduna;
+       if (tpcb->tp_fcredit == 0) {
+               /*
+                * We transmitted new data, started timing it and the window
+                * got shrunk under us.  This can only happen if all data
+                * that they wanted us to send got acked, so don't
+                * bother shrinking the congestion windows, et. al.
+                * The retransmission timer should have been reset in goodack()
+                */
+               tpcb->tp_rxtshift = 0;
+               tpcb->tp_timer[TM_data_retrans] = 0;
+               tpcb->tp_timer[TM_sendack] = tpcb->tp_dt_ticks;
+       }
+       rexmt = tpcb->tp_dt_ticks << min(tpcb->tp_rxtshift, TP_MAXRXTSHIFT);
+       win = min(tpcb->tp_fcredit, (tpcb->tp_cong_win / tpcb->tp_l_tpdusize / 2));
+       win = max(win, 2);
+       tpcb->tp_cong_win = tpcb->tp_l_tpdusize;        /* slow start again. */
+       tpcb->tp_ssthresh = win * tpcb->tp_l_tpdusize;
+       /* We're losing; our srtt estimate is probably bogus.
+        * Clobber it so we'll take the next rtt measurement as our srtt;
+        * Maintain current rxt times until then.
+        */
+       if (++tpcb->tp_rxtshift > TP_NRETRANS / 4) {
+               /* tpcb->tp_nlprotosw->nlp_losing(tpcb->tp_npcb) someday */
+               tpcb->tp_rtt = 0;
+       }
+       if (rexmt > 128)
+               rexmt = 128; /* XXXX value from tcp_timer.h */
+       tpcb->tp_timer[TM_data_retrans] = tpcb->tp_rxtcur = rexmt;
+       tp_send(tpcb);
+}
+
 int
 tp_fasttimo()
 {
 int
 tp_fasttimo()
 {
@@ -282,7 +270,7 @@ tp_fasttimo()
                                t->tp_flags &= ~TPF_DELACK;
                                IncStat(ts_Fdelack);
                                tp_driver(t, &E);
                                t->tp_flags &= ~TPF_DELACK;
                                IncStat(ts_Fdelack);
                                tp_driver(t, &E);
-                               t->tp_refcallout[TM_sendack].c_time = t->tp_keepalive_ticks;
+                               t->tp_timer[TM_sendack] = t->tp_keepalive_ticks;
                        } else
                                IncStat(ts_Fpruned);
                        tp_ftimeolist = t->tp_fasttimeo;
                        } else
                                IncStat(ts_Fpruned);
                        tp_ftimeolist = t->tp_fasttimeo;
@@ -299,22 +287,21 @@ tp_fasttimo()
  *     Set a C type timer of type (which) to go off after (ticks) time.
  */
 void
  *     Set a C type timer of type (which) to go off after (ticks) time.
  */
 void
-tp_ctimeout(refp, which, ticks)
-       register struct tp_ref  *refp;
+tp_ctimeout(tpcb, which, ticks)
+       register struct tp_pcb  *tpcb;
        int                                     which, ticks; 
 {
        int                                     which, ticks; 
 {
-       register struct Ccallout *cp = &(refp->tpr_callout[which]);
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", 
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout ref which tpcb active", 
-                       (int)(refp - tp_ref), which, refp->tpr_pcb, cp->c_time);
+                       tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
        ENDTRACE
        ENDTRACE
-       if(cp->c_time)
+       if(tpcb->tp_timer[which])
                IncStat(ts_Ccan_act);
        IncStat(ts_Cset);
        if (ticks <= 0)
                ticks = 1;
                IncStat(ts_Ccan_act);
        IncStat(ts_Cset);
        if (ticks <= 0)
                ticks = 1;
-       cp->c_time = ticks;
+       tpcb->tp_timer[which] = ticks;
 }
 
 /*
 }
 
 /*
@@ -325,22 +312,20 @@ tp_ctimeout(refp, which, ticks)
  *     parameter (ticks) is > the current value of the timer.
  */
 void
  *     parameter (ticks) is > the current value of the timer.
  */
 void
-tp_ctimeout_MIN(refp, which, ticks)
-       register struct tp_ref  *refp;
+tp_ctimeout_MIN(tpcb, which, ticks)
+       register struct tp_pcb  *tpcb;
        int                                             which, ticks; 
 {
        int                                             which, ticks; 
 {
-       register struct Ccallout *cp = &(refp->tpr_callout[which]);
-
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_ctimeout_MIN ref which tpcb active", 
-                       (int)(refp - tp_ref), which, refp->tpr_pcb, cp->c_time);
+                       tpcb->tp_lref, which, tpcb, tpcb->tp_timer[which]);
        ENDTRACE
        IncStat(ts_Cset);
        ENDTRACE
        IncStat(ts_Cset);
-       if (cp->c_time)  {
-               cp->c_time = MIN(ticks, cp->c_time);
+       if (tpcb->tp_timer[which])  {
+               tpcb->tp_timer[which] = MIN(ticks, tpcb->tp_timer[which]);
                IncStat(ts_Ccan_act);
        } else
                IncStat(ts_Ccan_act);
        } else
-               cp->c_time = ticks;
+               tpcb->tp_timer[which] = ticks;
 }
 
 /*
 }
 
 /*
@@ -350,26 +335,23 @@ tp_ctimeout_MIN(refp, which, ticks)
  *  Cancel the (which) timer in the ref structure indicated by (refp).
  */
 void
  *  Cancel the (which) timer in the ref structure indicated by (refp).
  */
 void
-tp_cuntimeout(refp, which)
+tp_cuntimeout(tpcb, which)
+       register struct tp_pcb  *tpcb;
        int                                             which;
        int                                             which;
-       register struct tp_ref  *refp;
 {
 {
-       register struct Ccallout *cp;
-
-       cp = &(refp->tpr_callout[which]);
-
        IFDEBUG(D_TIMER)
        IFDEBUG(D_TIMER)
-               printf("tp_cuntimeout(0x%x, %d) active %d\n", refp, which, cp->c_time);
+               printf("tp_cuntimeout(0x%x, %d) active %d\n",
+                               tpcb, which, tpcb->tp_timer[which]);
        ENDDEBUG
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, 
        ENDDEBUG
 
        IFTRACE(D_TIMER)
                tptrace(TPPTmisc, "tp_cuntimeout ref which, active", refp-tp_ref, 
-                       which, cp->c_time, 0);
+                       which, tpcb->tp_timer[which], 0);
        ENDTRACE
 
        ENDTRACE
 
-       if (cp->c_time)
+       if (tpcb->tp_timer[which])
                IncStat(ts_Ccan_act);
        else
                IncStat(ts_Ccan_inact);
                IncStat(ts_Ccan_act);
        else
                IncStat(ts_Ccan_inact);
-       cp->c_time = 0;
+       tpcb->tp_timer[which] = 0;
 }
 }