X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/1c15e88899094343f75aeba04122cd96a96b428e..ad7871609881e73855d0b04da49b486cd93efca7:/usr/src/sys/netiso/tp_driver.c diff --git a/usr/src/sys/netiso/tp_driver.c b/usr/src/sys/netiso/tp_driver.c index 92b9eae7f1..586ef4e2ad 100644 --- a/usr/src/sys/netiso/tp_driver.c +++ b/usr/src/sys/netiso/tp_driver.c @@ -14,23 +14,25 @@ static struct act_ent { #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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include #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(), +#ifdef TP_DEBUG_TIMERS 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() @@ -98,7 +102,7 @@ case 0x4: break; case 0x5: { - p->tp_refp->tpr_state = REF_OPEN; /* has timers ??? */ + p->tp_refstate = REF_OPEN; /* has timers ??? */ } 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 - 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_flags |= TPF_CONN_DATA_IN;*/ e->ev_union.EV_CR_TPDU.e_data = MNULL; } } @@ -144,23 +147,22 @@ case 0x8: IFDEBUG(D_CONN) printf("Confirming connection: p" ); ENDDEBUG + tp_getoptions(p); 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; - 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: { - register struct tp_ref *r = p->tp_refp; - 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; @@ -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 */ - 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; - 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: { - 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; } - 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_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); } @@ -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 (???) */ - 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: { - 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: { - 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: { - 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_cuntimeout(p->tp_refp, TM_retrans); + tp_cuntimeout(p, TM_retrans); tp_soisdisconnected(p); } break; @@ -262,9 +270,7 @@ case 0x11: 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 ); } @@ -272,21 +278,20 @@ case 0x12: 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_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; - 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: { - tp_cuntimeout(p->tp_refp, TM_retrans); + tp_cuntimeout(p, TM_retrans); 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; - 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_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", @@ -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); - 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); - 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: @@ -332,8 +335,7 @@ case 0x16: 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) @@ -348,7 +350,7 @@ case 0x16: 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: @@ -368,7 +370,7 @@ case 0x18: 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: @@ -383,11 +385,10 @@ case 0x19: 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); - 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 */ @@ -396,11 +397,11 @@ case 0x19: printf("tp_stash returns %d\n",doack); ENDDEBUG - if(doack) { + if (doack) { (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 - 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"); @@ -421,7 +422,7 @@ case 0x1b: { 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); @@ -432,7 +433,7 @@ case 0x1b: 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"); @@ -447,7 +448,7 @@ case 0x1c: 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; @@ -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); - 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; @@ -472,8 +472,8 @@ case 0x1d: 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: @@ -483,11 +483,10 @@ case 0x1e: 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); - 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", @@ -495,6 +494,7 @@ case 0x1e: 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"); @@ -509,7 +509,6 @@ case 0x1e: 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; */ } @@ -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 ) { -#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); - 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) */ @@ -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; - tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); + tp_ctimeout(p, TM_retrans, (int)p->tp_dr_ticks); } } break; @@ -589,9 +581,10 @@ case 0x24: 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) @@ -602,7 +595,7 @@ case 0x24: } 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); @@ -615,12 +608,11 @@ case 0x25: 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; - 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: @@ -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_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); + tp_ctimeout(p, TM_retrans, (int)p->tp_dr_ticks); } 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); @@ -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_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); + tp_ctimeout(p, TM_retrans, (int)p->tp_dr_ticks); } 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); - /* m_copy doesn't preserve the m_xlink field, but at this pt. - * that doesn't matter - */ + int shift; 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) @@ -670,65 +659,16 @@ case 0x28: 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); - 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: { - 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: @@ -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); - 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; - p->tp_refp->tpr_state = REF_FROZEN; + p->tp_refstate = REF_FROZEN; 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: { - tp_freeref(p->tp_refp); + tp_freeref(p->tp_lref); 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); } @@ -766,8 +706,8 @@ case 0x2d: 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); @@ -785,8 +725,8 @@ case 0x2f: */ 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) @@ -796,7 +736,8 @@ case 0x2f: 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) @@ -805,73 +746,21 @@ case 0x2f: 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) { - 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) - 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: - { - 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", @@ -884,14 +773,14 @@ case 0x32: 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; -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 ); @@ -899,37 +788,69 @@ case 0x33: 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: { + 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); + 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: + { + if (sbspace(&p->tp_sock->so_rcv) > 0) + tp0_openflow(p); + } + break; +case 0x36: { 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); + } } } break; -case 0x36: +case 0x37: { if(trick_hc) return ECONNABORTED; } break; -case 0x37: +case 0x38: { 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 ( 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; @@ -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 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; @@ -989,14 +910,14 @@ case 0xc4: 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: - 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: - 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; @@ -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); - ENDTRACE if(error==0) p->tp_state = a->a_newstate;