BSD 4_4 release
[unix-history] / usr / src / sys / netiso / tp_driver.c
index 92b9eae..586ef4e 100644 (file)
@@ -14,23 +14,25 @@ static struct act_ent {
 #include "tp_states.init"
 };
 
 #include "tp_states.init"
 };
 
-/*     @(#)tp.trans    7.4 (Berkeley) 1/16/90 */
-#include "param.h"
-#include "socket.h"
-#include "socketvar.h"
-#include "protosw.h"
-#include "mbuf.h"
-#include "time.h"
-#include "errno.h"
-#include "../netiso/tp_param.h"
-#include "../netiso/tp_stat.h"
-#include "../netiso/tp_pcb.h"
-#include "../netiso/tp_tpdu.h"
-#include "../netiso/argo_debug.h"
-#include "../netiso/tp_trace.h"
-#include "../netiso/iso_errno.h"
-#include "../netiso/tp_seq.h"
-#include "../netiso/cons.h"
+/* @(#)tp.trans        8.1 (Berkeley) 6/10/93 */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/protosw.h>
+#include <sys/mbuf.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+
+#include <netiso/tp_param.h>
+#include <netiso/tp_stat.h>
+#include <netiso/tp_pcb.h>
+#include <netiso/tp_tpdu.h>
+#include <netiso/argo_debug.h>
+#include <netiso/tp_trace.h>
+#include <netiso/iso_errno.h>
+#include <netiso/tp_seq.h>
+#include <netiso/cons.h>
 
 #define DRIVERTRACE TPPTdriver
 #define sbwakeup(sb)   sowakeup(p->tp_sock, sb);
 
 #define DRIVERTRACE TPPTdriver
 #define sbwakeup(sb)   sowakeup(p->tp_sock, sb);
@@ -45,9 +47,11 @@ int  tp_emit(),
 void   tp_indicate(),                          tp_getoptions(),        
                tp_soisdisconnecting(),         tp_soisdisconnected(),
                tp_recycle_tsuffix(),           
 void   tp_indicate(),                          tp_getoptions(),        
                tp_soisdisconnecting(),         tp_soisdisconnected(),
                tp_recycle_tsuffix(),           
+#ifdef TP_DEBUG_TIMERS
                tp_etimeout(),                          tp_euntimeout(),
                tp_etimeout(),                          tp_euntimeout(),
-               tp_euntimeout_lss(),            tp_ctimeout(),
-               tp_cuntimeout(),                        tp_ctimeout_MIN(),
+               tp_ctimeout(),                          tp_cuntimeout(),
+               tp_ctimeout_MIN(),
+#endif
                tp_freeref(),                           tp_detach(),
                tp0_stash(),                            tp0_send(),
                tp_netcmd(),                            tp_send()
                tp_freeref(),                           tp_detach(),
                tp0_stash(),                            tp0_send(),
                tp_netcmd(),                            tp_send()
@@ -98,7 +102,7 @@ case 0x4:
                 break;
 case 0x5: 
                {
                 break;
 case 0x5: 
                {
-               p->tp_refp->tpr_state = REF_OPEN; /* has timers ??? */
+               p->tp_refstate = REF_OPEN; /* has timers ??? */
        }
                 break;
 case 0x6: 
        }
                 break;
 case 0x6: 
@@ -109,14 +113,13 @@ case 0x6:
                IFDEBUG(D_CONN)
                        printf("CR datalen 0x%x data 0x%x", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data);
                ENDDEBUG
                IFDEBUG(D_CONN)
                        printf("CR datalen 0x%x data 0x%x", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data);
                ENDDEBUG
-               p->tp_refp->tpr_state = REF_OPEN; /* has timers */
+               p->tp_refstate = REF_OPEN; /* has timers */
                p->tp_fcredit = e->ev_union.EV_CR_TPDU.e_cdt;
 
                if (e->ev_union.EV_CR_TPDU.e_datalen > 0) {
                        /* n/a for class 0 */
                        ASSERT(p->tp_Xrcv.sb_cc == 0); 
                        sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CR_TPDU.e_data);
                p->tp_fcredit = e->ev_union.EV_CR_TPDU.e_cdt;
 
                if (e->ev_union.EV_CR_TPDU.e_datalen > 0) {
                        /* n/a for class 0 */
                        ASSERT(p->tp_Xrcv.sb_cc == 0); 
                        sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CR_TPDU.e_data);
-                       /*p->tp_flags |= TPF_CONN_DATA_IN;*/
                        e->ev_union.EV_CR_TPDU.e_data = MNULL; 
                } 
        }
                        e->ev_union.EV_CR_TPDU.e_data = MNULL; 
                } 
        }
@@ -144,23 +147,22 @@ case 0x8:
                IFDEBUG(D_CONN)
                        printf("Confirming connection: p" );
                ENDDEBUG
                IFDEBUG(D_CONN)
                        printf("Confirming connection: p" );
                ENDDEBUG
+               tp_getoptions(p);
                soisconnecting(p->tp_sock);
                soisconnecting(p->tp_sock);
-               if(p->tp_rx_strat & TPRX_FASTSTART)
-                       p->tp_cong_win = p->tp_fcredit;
+               if ((p->tp_rx_strat & TPRX_FASTSTART) && (p->tp_fcredit > 0))
+                       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);
        }
                 break;
 case 0x9: 
                {
        }
                 break;
 case 0x9: 
                {
-               register struct tp_ref *r = p->tp_refp;
-
                IFDEBUG(D_CONN)
                        printf("event: CR_TPDU emit CC failed done " );
                ENDDEBUG
                soisdisconnected(p->tp_sock);
                IFDEBUG(D_CONN)
                        printf("event: CR_TPDU emit CC failed done " );
                ENDDEBUG
                soisdisconnected(p->tp_sock);
-               tp_recycle_tsuffix( p );
-               tp_freeref(r);
+               tp_recycle_tsuffix(p);
+               tp_freeref(p->tp_lref);
                tp_detach(p);
        }
                 break;
                tp_detach(p);
        }
                 break;
@@ -185,32 +187,40 @@ case 0xa:
                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);
                }
        }
                 break;
 case 0xb: 
                {
                }
        }
                 break;
 case 0xb: 
                {
-               if (e->ev_union.EV_DR_TPDU.e_datalen > 0 && p->tp_class != TP_CLASS_0) {
-                       /*sbdrop(&p->tp_Xrcv, p->tp_Xrcv.sb_cc); /* purge expedited data */
-                       sbflush(&p->tp_Xrcv);
-                       p->tp_flags |= TPF_DISC_DATA_IN;
+               sbflush(&p->tp_Xrcv); /* purge non-delivered data data */
+               if (e->ev_union.EV_DR_TPDU.e_datalen > 0) {
                        sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_DR_TPDU.e_data);
                        e->ev_union.EV_DR_TPDU.e_data = MNULL;
                } 
                        sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_DR_TPDU.e_data);
                        e->ev_union.EV_DR_TPDU.e_data = MNULL;
                } 
-               tp_indicate(T_DISCONNECT, p, TP_ERROR_MASK | (u_short)e->ev_union.EV_DR_TPDU.e_reason);
+               if (p->tp_state == TP_OPEN)
+                       tp_indicate(T_DISCONNECT, p, 0);
+               else {
+                       int so_error = ECONNREFUSED;
+                       if (e->ev_union.EV_DR_TPDU.e_reason != (E_TP_NO_SESSION ^ TP_ERROR_MASK) &&
+                           e->ev_union.EV_DR_TPDU.e_reason != (E_TP_NO_CR_ON_NC ^ TP_ERROR_MASK) &&
+                           e->ev_union.EV_DR_TPDU.e_reason != (E_TP_REF_OVERFLOW ^ TP_ERROR_MASK))
+                               so_error = ECONNABORTED;
+                       tp_indicate(T_DISCONNECT, p, so_error);
+               }
                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);
+                               p->tp_flags &= ~TPF_DELACK;
                        }
                        }
-                       tp_cuntimeout(p->tp_refp, TM_retrans);
+                       tp_cuntimeout(p, TM_retrans);
                        if( e->ev_union.EV_DR_TPDU.e_sref !=  0 ) 
                                (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL);
                }
                        if( e->ev_union.EV_DR_TPDU.e_sref !=  0 ) 
                                (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL);
                }
@@ -221,35 +231,33 @@ case 0xc:
                if( e->ev_union.EV_DR_TPDU.e_sref != 0 )
                        (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); 
                /* reference timer already set - reset it to be safe (???) */
                if( e->ev_union.EV_DR_TPDU.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);
        }
                 break;
 case 0xd: 
                {       
        }
                 break;
 case 0xd: 
                {       
-               tp_cuntimeout(p->tp_refp, TM_retrans);
-               tp_indicate(T_DISCONNECT, p, 
-                       TP_ERROR_MASK |(u_short)(e->ev_union.EV_ER_TPDU.e_reason | 0x40));
+               tp_cuntimeout(p, TM_retrans);
+               tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
                tp_soisdisconnected(p);
        }
                 break;
 case 0xe: 
                {        
                tp_soisdisconnected(p);
        }
                 break;
 case 0xe: 
                {        
-               p->tp_sock->so_error = (u_short)e->ev_union.EV_DR_TPDU.e_reason;
-               tp_cuntimeout(p->tp_refp, TM_retrans);
+               tp_cuntimeout(p, TM_retrans);
                tp_soisdisconnected(p);
        }
                 break;
 case 0xf: 
                {        
                tp_soisdisconnected(p);
        }
                 break;
 case 0xf: 
                {        
-               p->tp_sock->so_error = (u_short)e->ev_union.EV_ER_TPDU.e_reason;
-               tp_cuntimeout(p->tp_refp, TM_retrans);
+               tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
+               tp_cuntimeout(p, TM_retrans);
                tp_soisdisconnected(p);
        }
                 break;
 case 0x10: 
                {        
                tp_soisdisconnected(p);
        }
                 break;
 case 0x10: 
                {        
-               tp_cuntimeout(p->tp_refp, TM_retrans);
+               tp_cuntimeout(p, TM_retrans);
                tp_soisdisconnected(p);
        }
                 break;
                tp_soisdisconnected(p);
        }
                 break;
@@ -262,9 +270,7 @@ case 0x11:
 case 0x12: 
                {
                tp_soisdisconnecting(p->tp_sock);
 case 0x12: 
                {
                tp_soisdisconnecting(p->tp_sock);
-               tp_indicate(T_DISCONNECT, p, 
-                       TP_ERROR_MASK |(u_short)(e->ev_union.EV_ER_TPDU.e_reason | 0x40));
-
+               tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
                tp_soisdisconnected(p);
                tp_netcmd( p, CONN_CLOSE );
        }
                tp_soisdisconnected(p);
                tp_netcmd( p, CONN_CLOSE );
        }
@@ -272,21 +278,20 @@ case 0x12:
 case 0x13: 
                {
                if (p->tp_state == TP_OPEN) {
 case 0x13: 
                {
                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_soisdisconnecting(p->tp_sock);
-               tp_indicate(T_DISCONNECT, p, 
-                       TP_ERROR_MASK |(u_short)(e->ev_union.EV_ER_TPDU.e_reason | 0x40));
+               tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason);
                p->tp_retrans = p->tp_Nretrans;
                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);
        }
                 break;
 case 0x14: 
                {       
                (void) tp_emit(DR_TPDU_type, p, 0, E_TP_PROTO_ERR, MNULL);
        }
                 break;
 case 0x14: 
                {       
-               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);
@@ -301,11 +306,10 @@ case 0x15:
                IncStat(ts_tp4_conn);
                p->tp_fref = e->ev_union.EV_CC_TPDU.e_sref;
                p->tp_fcredit = e->ev_union.EV_CC_TPDU.e_cdt;
                IncStat(ts_tp4_conn);
                p->tp_fref = e->ev_union.EV_CC_TPDU.e_sref;
                p->tp_fcredit = e->ev_union.EV_CC_TPDU.e_cdt;
-               p->tp_ackrcvd = 0;
-               if(p->tp_rx_strat & TPRX_FASTSTART)
-                       p->tp_cong_win = e->ev_union.EV_CC_TPDU.e_cdt;
+               if ((p->tp_rx_strat & TPRX_FASTSTART) && (e->ev_union.EV_CC_TPDU.e_cdt > 0))
+                       p->tp_cong_win = e->ev_union.EV_CC_TPDU.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",
@@ -318,12 +322,11 @@ case 0x15:
                if (e->ev_union.EV_CC_TPDU.e_datalen > 0) {
                        ASSERT(p->tp_Xrcv.sb_cc == 0); /* should be empty */
                        sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CC_TPDU.e_data);
                if (e->ev_union.EV_CC_TPDU.e_datalen > 0) {
                        ASSERT(p->tp_Xrcv.sb_cc == 0); /* should be empty */
                        sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CC_TPDU.e_data);
-                       p->tp_flags |= TPF_CONN_DATA_IN;
                        e->ev_union.EV_CC_TPDU.e_data = MNULL;
                }
 
                (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL);
                        e->ev_union.EV_CC_TPDU.e_data = 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);
        }
                 break;
 case 0x16: 
        }
                 break;
 case 0x16: 
@@ -332,8 +335,7 @@ case 0x16:
                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)
@@ -348,7 +350,7 @@ case 0x16:
                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);
        }
                 break;
 case 0x17: 
        }
                 break;
 case 0x17: 
@@ -368,7 +370,7 @@ case 0x18:
                        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);
        }
                 break;
 case 0x19: 
        }
                 break;
 case 0x19: 
@@ -383,11 +385,10 @@ case 0x19:
                        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_getoptions(p);
-               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 */
 
@@ -396,11 +397,11 @@ case 0x19:
                        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");
@@ -421,7 +422,7 @@ case 0x1b:
                {
                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);
@@ -432,7 +433,7 @@ case 0x1b:
                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");
@@ -447,7 +448,7 @@ case 0x1c:
                ENDTRACE
                IncStat(ts_dt_niw);
                m_freem(e->ev_union.EV_DT_TPDU.e_data);
                ENDTRACE
                IncStat(ts_dt_niw);
                m_freem(e->ev_union.EV_DT_TPDU.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 ); 
        }
                 break;
                (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); 
        }
                 break;
@@ -458,9 +459,8 @@ case 0x1d:
                        p->tp_ucddata = 0;
                }
                (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq);
                        p->tp_ucddata = 0;
                }
                (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq);
-               tp_cuntimeout(p->tp_refp, TM_retrans);
+               tp_cuntimeout(p, TM_retrans);
 
 
-               tp_getoptions(p);
                soisconnected(p->tp_sock);
                IFTRACE(D_CONN)
                        struct socket *so = p->tp_sock;
                soisconnected(p->tp_sock);
                IFTRACE(D_CONN)
                        struct socket *so = p->tp_sock;
@@ -472,8 +472,8 @@ case 0x1d:
                                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);
        }
                 break;
 case 0x1e: 
        }
                 break;
 case 0x1e: 
@@ -483,11 +483,10 @@ case 0x1e:
                                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_getoptions(p);
+                       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",
@@ -495,6 +494,7 @@ case 0x1e:
                ENDTRACE
 
                p->tp_sock->so_state |= SS_RCVATMARK;
                ENDTRACE
 
                p->tp_sock->so_state |= SS_RCVATMARK;
+               e->ev_union.EV_XPD_TPDU.e_data->m_flags |= M_EOR;
                sbinsertoob(&p->tp_Xrcv, e->ev_union.EV_XPD_TPDU.e_data);
                IFDEBUG(D_XPD)
                        dump_mbuf(e->ev_union.EV_XPD_TPDU.e_data, "XPD TPDU: tp_Xrcv");
                sbinsertoob(&p->tp_Xrcv, e->ev_union.EV_XPD_TPDU.e_data);
                IFDEBUG(D_XPD)
                        dump_mbuf(e->ev_union.EV_XPD_TPDU.e_data, "XPD TPDU: tp_Xrcv");
@@ -509,7 +509,6 @@ case 0x1e:
 case 0x1f: 
                {
                if( p->tp_Xrcv.sb_cc == 0 ) {
 case 0x1f: 
                {
                if( p->tp_Xrcv.sb_cc == 0 ) {
-                       /*p->tp_flags &= ~TPF_XPD_PRESENT;*/
                        /* kludge for select(): */ 
                        /* p->tp_sock->so_state &= ~SS_OOBAVAIL; */
                }
                        /* kludge for select(): */ 
                        /* p->tp_sock->so_state &= ~SS_OOBAVAIL; */
                }
@@ -524,19 +523,12 @@ case 0x20:
                if( p->tp_Xrcvnxt != e->ev_union.EV_XPD_TPDU.e_seq )
                        IncStat(ts_xpd_niw);
                if( p->tp_Xrcv.sb_cc ) {
                if( p->tp_Xrcvnxt != e->ev_union.EV_XPD_TPDU.e_seq )
                        IncStat(ts_xpd_niw);
                if( p->tp_Xrcv.sb_cc ) {
-#ifdef notdef
-                       if( p->tp_flags & TPF_CONN_DATA_IN ) {
-                               /* user isn't reading the connection data; see note above */
-                               sbdrop(&p->tp_Xrcv, p->tp_Xrcv.sb_cc);
-                               p->tp_flags &= ~TPF_CONN_DATA_IN;
-                       }
-#endif notdef
                        /* might as well kick 'em again */
                        tp_indicate(T_XDATA, p, 0);
                        IncStat(ts_xpd_dup);
                }
                m_freem(e->ev_union.EV_XPD_TPDU.e_data);
                        /* might as well kick 'em again */
                        tp_indicate(T_XDATA, p, 0);
                        IncStat(ts_xpd_dup);
                }
                m_freem(e->ev_union.EV_XPD_TPDU.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)
                 */
@@ -573,7 +565,7 @@ case 0x22:
                        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);
                }
        }
                 break;
                }
        }
                 break;
@@ -589,9 +581,10 @@ case 0x24:
                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);
+                       p->tp_flags &= ~TPF_DELACK;
                }
                if (data) {
                        IFDEBUG(D_CONN)
                }
                if (data) {
                        IFDEBUG(D_CONN)
@@ -602,7 +595,7 @@ case 0x24:
                }
                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->ev_union.EV_T_DISC_req.e_reason, data);
 
                if( trick_hc )
                        return tp_emit(DR_TPDU_type, p, 0, e->ev_union.EV_T_DISC_req.e_reason, data);
@@ -615,12 +608,11 @@ case 0x25:
 
                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);
        }
                 break;
 case 0x26: 
        }
                 break;
 case 0x26: 
@@ -631,14 +623,14 @@ case 0x26:
                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);
        }
                 break;
 case 0x27: 
                {
        }
                 break;
 case 0x27: 
                {
-               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);
@@ -646,23 +638,20 @@ case 0x27:
                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);
        }
                 break;
 case 0x28: 
                {
        }
                 break;
 case 0x28: 
                {
-               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)
@@ -670,65 +659,16 @@ case 0x28:
                        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);
                }
        }
                 break;
 case 0x29: 
                {       
                }
        }
                 break;
 case 0x29: 
                {       
-               register        SeqNum                  low, lowsave = 0;
-               register        struct tp_rtc   *r = p->tp_snduna_rtc;
-               register        struct mbuf     *m;
-               register        SeqNum                  high = e->ev_union.EV_TM_data_retrans.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 ( r == (struct tp_rtc *)0 ){
-                               IFDEBUG(D_RTC)
-                                       printf( "tp: retrans rtc list is GONE!\n");
-                               ENDDEBUG
-                               break;
-                       }
-                       if ( r->tprt_seq == low ){
-                               if(( m = m_copy(r->tprt_data, 0, r->tprt_octets ))== MNULL)
-                                       break;
-                               (void) tp_emit(DT_TPDU_type, p, low, r->tprt_eot, m);
-                               IncStat(ts_retrans_dt);
-                               SEQ_INC(p, low );
-                       }
-                       r = r->tprt_next;
-               }
-/* CE_BIT
-               if ( SEQ_LEQ(p, lowsave, high) ){
-*/
-                       e->ev_union.EV_TM_data_retrans.e_retrans --;
-                       tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)lowsave,
-                                       (caddr_t)high, e->ev_union.EV_TM_data_retrans.e_retrans,
-                                       (p->tp_Nretrans - e->ev_union.EV_TM_data_retrans.e_retrans) * (int)p->tp_dt_ticks);
-/* CE_BIT
-               }
-*/
+               p->tp_rxtshift++;
+               (void) tp_data_retrans(p);
        }
                 break;
 case 0x2a: 
        }
                 break;
 case 0x2a: 
@@ -736,27 +676,27 @@ case 0x2a:
                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);
        }
                 break;
 case 0x2b: 
                {       
                p->tp_sock->so_error = ETIMEDOUT;
        }
                 break;
 case 0x2b: 
                {       
                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);
        }
                 break;
 case 0x2c: 
                {
        }
                 break;
 case 0x2c: 
                {
-               tp_freeref(p->tp_refp);
+               tp_freeref(p->tp_lref);
                tp_detach(p);
        }
                 break;
 case 0x2d: 
                {       
                if( p->tp_class != TP_CLASS_0) {
                tp_detach(p);
        }
                 break;
 case 0x2d: 
                {       
                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); 
                }
@@ -766,8 +706,8 @@ case 0x2d:
 case 0x2e: 
                {
                IFTRACE(D_DATA)
 case 0x2e: 
                {
                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);
@@ -785,8 +725,8 @@ case 0x2f:
                         */
 
                        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)
@@ -796,7 +736,8 @@ case 0x2f:
                        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)
@@ -805,73 +746,21 @@ case 0x2f:
                 break;
 case 0x30: 
                {
                 break;
 case 0x30: 
                {
+               struct sockbuf *sb = &p->tp_sock->so_snd;
+
                IFDEBUG(D_ACKRECV)
                        printf("GOOD ACK seq 0x%x cdt 0x%x\n", e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_cdt);
                ENDDEBUG
                if( p->tp_class != TP_CLASS_0) {
                IFDEBUG(D_ACKRECV)
                        printf("GOOD ACK seq 0x%x cdt 0x%x\n", e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.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->ev_union.EV_AK_TPDU.e_seq);
-               }
-               sbwakeup( &p->tp_sock->so_snd );
-
-               if (p->tp_sndhiwat <= p->tp_retrans_hiwat &&
-                       p->tp_snduna <= p->tp_retrans_hiwat) {
-
-                       register    struct mbuf     *m;
-                       /* extern      struct mbuf     *m_copy(); */
-                       register    struct tp_rtc   *r;
-                       SeqNum      high, retrans, low_save;
-
-                       high = SEQ_MIN(p, SEQ_ADD(p, p->tp_snduna,
-                                       MIN(p->tp_cong_win, p->tp_fcredit)) - 1,
-                                       p->tp_sndhiwat);
-                       low_save = retrans = SEQ_MAX(p, SEQ_ADD(p, p->tp_last_retrans, 1),
-                                       p->tp_snduna);
-                       for (; SEQ_LEQ(p, retrans, high); SEQ_INC(p, retrans)) {
-
-                               for (r = p->tp_snduna_rtc; r; r = r->tprt_next){
-                                       if ( r->tprt_seq == retrans ){
-                                               if(( m = m_copy(r->tprt_data, 0, r->tprt_octets ))
-                                                               == MNULL)
-                                                       break;
-                                               (void) tp_emit(DT_TPDU_type, p, retrans,
-                                                       r->tprt_eot, m);
-                                               p->tp_last_retrans = retrans;
-                                               IncStat(ts_retrans_dt);
-                                               break;
-                                       }
-                               }
-                               if ( r == (struct tp_rtc *)0 ){
-                                       IFDEBUG(D_RTC)
-                                               printf( "tp: retrans rtc list is GONE!\n");
-                                       ENDDEBUG
-                                       break;
-                               }
-                       }
-                       tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)low_save,
-                                       (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);
+                       tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);
                }
                }
+               sbwakeup(sb);
                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
        }
                 break;
 case 0x31: 
                ENDDEBUG
        }
                 break;
 case 0x31: 
-               {
-               IFTRACE(D_ACKRECV)
-                       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);
-               } 
-       }
-                break;
-case 0x32: 
                {
                IFTRACE(D_ACKRECV)
                        tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", 
                {
                IFTRACE(D_ACKRECV)
                        tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", 
@@ -884,14 +773,14 @@ case 0x32:
                                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);
                } 
        }
                 break;
                } 
        }
                 break;
-case 0x33
+case 0x32
                {       
                {       
-               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 );
 
@@ -899,37 +788,69 @@ case 0x33:
                tp_send(p);
        }
                 break;
                tp_send(p);
        }
                 break;
+case 0x33: 
+               {
+               IFTRACE(D_ACKRECV)
+                       tptrace(TPPTmisc, "BOGUS XACK eventtype ", e->ev_number, 0, 0,0);
+               ENDTRACE
+               if( p->tp_class != TP_CLASS_0 ) {
+                       tp_ctimeout(p, TM_inact, (int)p->tp_inact_ticks);
+               } 
+       }
+                break;
 case 0x34: 
                {       
 case 0x34: 
                {       
+               int timo;
                IFTRACE(D_TIMER)
                        tptrace(TPPTsendack, -1, p->tp_lcredit, p->tp_sent_uwe, 
                        p->tp_sent_lcdt, 0);
                ENDTRACE
                IncPStat(p, tps_n_TMsendack);
                (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL);
                IFTRACE(D_TIMER)
                        tptrace(TPPTsendack, -1, p->tp_lcredit, p->tp_sent_uwe, 
                        p->tp_sent_lcdt, 0);
                ENDTRACE
                IncPStat(p, tps_n_TMsendack);
                (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL);
+               if (p->tp_fcredit == 0) {
+                       if (p->tp_rxtshift < TP_MAXRXTSHIFT)
+                               p->tp_rxtshift++;
+                       timo = (p->tp_dt_ticks) << p->tp_rxtshift;
+               } else
+                       timo = p->tp_sendack_ticks;
+               tp_ctimeout(p, TM_sendack, timo);
        }
                 break;
 case 0x35: 
        }
                 break;
 case 0x35: 
+               {
+               if (sbspace(&p->tp_sock->so_rcv) > 0)
+                       tp0_openflow(p);
+       }
+                break;
+case 0x36: 
                {       
                if( trick_hc ) {
                {       
                if( trick_hc ) {
-                       IncStat(ts_ackreason[_ACK_USRRCV_]);
-
-                       /* send an ACK only if there's new information */
-                       LOCAL_CREDIT( p );
-                       if ((p->tp_rcvnxt != p->tp_sent_rcvnxt) ||
-                               (p->tp_lcredit != p->tp_sent_lcdt))
-
+                       SeqNum ack_thresh;
+                       /*
+                        * If the upper window edge has advanced a reasonable
+                        * amount beyond what was known, send an ACK.
+                        * A reasonable amount is 2 packets, unless the max window
+                        * is only 1 or 2 packets, in which case we
+                        * should send an ack for any advance in the upper window edge.
+                        */
+                       LOCAL_CREDIT(p);
+                       ack_thresh = SEQ_SUB(p, p->tp_lcredit + p->tp_rcvnxt,
+                                                                        (p->tp_maxlcredit > 2 ? 2 : 1));
+                       if (SEQ_GT(p, ack_thresh, p->tp_sent_uwe)) {
+                               IncStat(ts_ackreason[_ACK_USRRCV_]);
+                               p->tp_flags &= ~TPF_DELACK;
                                return tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL);
                                return tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL);
+                       }
                }
        }
                 break;
                }
        }
                 break;
-case 0x36
+case 0x37
                {
                if(trick_hc)
                return ECONNABORTED;
        }
                 break;
                {
                if(trick_hc)
                return ECONNABORTED;
        }
                 break;
-case 0x37
+case 0x38
                {
                ASSERT( p->tp_state != TP_LISTENING );
                tp_indicate(T_DISCONNECT, p, ECONNRESET);
                {
                ASSERT( p->tp_state != TP_LISTENING );
                tp_indicate(T_DISCONNECT, p, ECONNRESET);
@@ -959,7 +880,7 @@ case 0x15:
        if (    p->tp_retrans > 0 ) return 0x34;
         else return 0x35;
 case 0x54:
        if (    p->tp_retrans > 0 ) return 0x34;
         else return 0x35;
 case 0x54:
-       if ( e->ev_union.EV_TM_data_retrans.e_retrans > 0 ) return 0x33;
+       if (p->tp_rxtshift < TP_NRETRANS) return 0x33;
         else return 0x31;
 case 0x64:
        if (p->tp_class == TP_CLASS_0) return 0x1a;
         else return 0x31;
 case 0x64:
        if (p->tp_class == TP_CLASS_0) return 0x1a;
@@ -978,7 +899,7 @@ case 0xb2:
         else return 0x0;
 case 0xb4:
        if ( tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq)  ) return 0x3a;
         else return 0x0;
 case 0xb4:
        if ( tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq)  ) return 0x3a;
-        else return 0x3c;
+        else return 0x3b;
 case 0xc3:
        if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq,
                                        p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x21;
 case 0xc3:
        if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq,
                                        p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x21;
@@ -989,14 +910,14 @@ case 0xc4:
                                        p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x23;
         else return 0x25;
 case 0xd3:
                                        p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x23;
         else return 0x25;
 case 0xd3:
-       if ( p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq  /* && p->tp_Xrcv.sb_cc == 0*/) return 0x27;
+       if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27;
         else return 0x2a;
 case 0xd4:
         else return 0x2a;
 case 0xd4:
-       if ( p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq  /* && p->tp_Xrcv.sb_cc == 0*/) return 0x27;
+       if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27;
         else return 0x29;
 case 0xe4:
         else return 0x29;
 case 0xe4:
-       if ( tp_goodXack(p, e->ev_union.EV_XAK_TPDU.e_seq) ) return 0x3d;
-        else return 0x3b;
+       if ( tp_goodXack(p, e->ev_union.EV_XAK_TPDU.e_seq) ) return 0x3c;
+        else return 0x3d;
 case 0x102:
        if ( p->tp_class == TP_CLASS_0 ) return 0x2d;
         else return 0x2e;
 case 0x102:
        if ( p->tp_class == TP_CLASS_0 ) return 0x2d;
         else return 0x2e;
@@ -1071,7 +992,6 @@ register struct tp_event *e;
                error = _Xebec_action( a->a_action, e, p );
        IFTRACE(D_DRIVER)
        tptrace(DRIVERTRACE,            a->a_newstate, p->tp_state, e->ev_number, a->a_action, 0);
                error = _Xebec_action( a->a_action, e, p );
        IFTRACE(D_DRIVER)
        tptrace(DRIVERTRACE,            a->a_newstate, p->tp_state, e->ev_number, a->a_action, 0);
-
        ENDTRACE
        if(error==0)
        p->tp_state = a->a_newstate;
        ENDTRACE
        if(error==0)
        p->tp_state = a->a_newstate;