📄 tp.trans
字号:
/* TP4 only */TP_CLOSING <== [ TP_CLOSING, TP_AKWAIT, TP_CRSENT, TP_CONFIRMING ] T_DETACH DEFAULT { struct socket *so = $P.tp_sock; struct mbuf *data = MNULL; /* detach from parent socket so it can finish closing */ if (so->so_head) { if (!soqremque(so, 0) && !soqremque(so, 1)) panic("tp: T_DETACH"); so->so_head = 0; } if ($P.tp_state != TP_CLOSING) { tp_soisdisconnecting($P.tp_sock); 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, TM_retrans, (int)$P.tp_dr_ticks); } };TP_REFWAIT <== [ TP_OPEN, TP_CRSENT ] T_DISC_req ( $P.tp_class == TP_CLASS_0 ) { tp_soisdisconnecting($P.tp_sock); tp_netcmd( $P, CONN_CLOSE); tp_soisdisconnected($P); };/* TP4 only */TP_CLOSING <== [ TP_AKWAIT, TP_OPEN, TP_CRSENT, TP_CONFIRMING ] T_DISC_req DEFAULT { struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT); if($P.tp_state == TP_OPEN) { 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) printf("T_DISC_req.trans tp_ucddata 0x%x\n", $P.tp_ucddata); dump_mbuf(data, "ucddata @ T_DISC_req"); ENDDEBUG } tp_soisdisconnecting($P.tp_sock); $P.tp_retrans = $P.tp_Nretrans; tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks); if( trick_hc ) return tp_emit(DR_TPDU_type, $P, 0, $$.e_reason, data); };/* TP4 only */SAME <== TP_AKWAIT TM_retrans ( $P.tp_retrans > 0 ) { int error; struct mbuf *data = MCPY($P.tp_ucddata, M_WAIT); IncStat(ts_retrans_cc); $P.tp_retrans --; $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, TM_retrans, (int)$P.tp_cc_ticks); };/* TP4 only */TP_CLOSING <== TP_AKWAIT TM_retrans DEFAULT /* out of time */ { IncStat(ts_conn_gaveup); tp_soisdisconnecting($P.tp_sock); $P.tp_sock->so_error = ETIMEDOUT; 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, TM_retrans, (int)$P.tp_dr_ticks); };/* the retrans timers had better go off BEFORE the inactivity timer does, * if transmissions are going on. * (i.e., TM_inact should be greater than timer for all retrans plus ack * turnaround) *//* TP4 only */TP_CLOSING <== TP_OPEN [ TM_inact, TM_retrans, TM_data_retrans ] DEFAULT { 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); $P.tp_sock->so_error = ETIMEDOUT; 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, TM_retrans, (int)$P.tp_dr_ticks); };/* TP4 only */SAME <== TP_OPEN TM_retrans ( $P.tp_retrans > 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); int shift; IFTRACE(D_XPD) tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndnxt snduna", $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndnxt, $P.tp_snduna); ENDTRACE IFDEBUG(D_XPD) dump_mbuf(m, "XPD retrans emitting M"); 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, TM_retrans, ((int)$P.tp_dt_ticks) << shift); } };/* TP4 only */SAME <== TP_OPEN TM_data_retrans ($P.tp_rxtshift < TP_NRETRANS) { $P.tp_rxtshift++; (void) tp_data_retrans($P); };/* TP4 only */SAME <== TP_CLOSING TM_retrans ( $P.tp_retrans > 0 ) { $P.tp_retrans --; (void) tp_emit(DR_TPDU_type, $P, 0, E_TP_DR_NO_REAS, MNULL); IncStat(ts_retrans_dr); tp_ctimeout($P, TM_retrans, (int)$P.tp_dr_ticks); };/* TP4 only */TP_REFWAIT <== TP_CLOSING TM_retrans DEFAULT /* no more retrans - gave up */ { $P.tp_sock->so_error = ETIMEDOUT; $P.tp_refstate = REF_FROZEN; tp_recycle_tsuffix( $P ); tp_etimeout($P, TM_reference, (int)$P.tp_refer_ticks); };/* * The resources are kept around until the ref timer goes off. * The suffices are wiped out sooner so they can be reused right away. *//* applicable in TP4, TP0 */TP_CLOSED <== TP_REFWAIT TM_reference DEFAULT { tp_freeref($P.tp_lref); tp_detach($P); };/* applicable in TP4, TP0 *//* A duplicate CR from connectionless network layer can't happen */SAME <== TP_OPEN [ CR_TPDU, CC_TPDU ] DEFAULT { if( $P.tp_class != TP_CLASS_0) { 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); } /* ignore it if class 0 - state tables are blank for this */ };/* applicable in TP4, TP0 */SAME <== TP_OPEN T_DATA_req DEFAULT { IFTRACE(D_DATA) tptrace(TPPTmisc, "T_DATA_req sndnxt snduna fcredit, tpcb", $P.tp_sndnxt, $P.tp_snduna, $P.tp_fcredit, $P); ENDTRACE tp_send($P); };/* TP4 only */SAME <== TP_OPEN T_XPD_req DEFAULT /* T_XPD_req was issued by sosend iff xpd socket buf was empty * at time of sosend(), * AND (which means) there were no unacknowledged XPD tpdus outstanding! */ { int error = 0; /* 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 */ IFTRACE(D_XPD) tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndnxt snduna", $P.tp_Xuna, $P.tp_Xsndnxt, $P.tp_sndnxt, $P.tp_snduna); ENDTRACE IFDEBUG(D_XPD) printf("T_XPD_req: sb_cc 0x%x\n", $P.tp_Xsnd.sb_cc); dump_mbuf(m, "XPD req emitting M"); ENDDEBUG error = tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m); $P.tp_retrans = $P.tp_Nretrans; tp_ctimeout($P, TM_retrans, (int)$P.tp_rxtcur); SEQ_INC($P, $P.tp_Xsndnxt); } if(trick_hc) return error; };/* TP4, faked ack in TP0 when cons send completes */SAME <== TP_OPEN AK_TPDU ( tp_goodack($P, $$.e_cdt, $$.e_seq, $$.e_subseq) ) /* tp_goodack == true means * EITHER it actually acked something heretofore unacknowledged * OR no news but the credit should be processed. */ { struct sockbuf *sb = &$P.tp_sock->so_snd; IFDEBUG(D_ACKRECV) 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, TM_inact, (int)$P.tp_inact_ticks); } sbwakeup(sb); IFDEBUG(D_ACKRECV) printf("GOOD ACK new sndnxt 0x%x\n", $P.tp_sndnxt); ENDDEBUG };/* TP4, and TP0 after sending a CC or possibly a CR */SAME <== TP_OPEN AK_TPDU DEFAULT { IFTRACE(D_ACKRECV) tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", $$.e_fcc_present, $P.tp_r_subseq, $$.e_subseq, 0); ENDTRACE if( $P.tp_class != TP_CLASS_0 ) { if ( !$$.e_fcc_present ) { /* send ACK with FCC */ IncStat( ts_ackreason[_ACK_FCC_] ); (void) tp_emit(AK_TPDU_type, $P, $P.tp_rcvnxt, 1, MNULL); } tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks); } };/* NBS(47) */ /* goes in at *** */ /* just so happens that this is never true now, because we allow * only 1 packet in the queue at once (this could be changed) if ( $P.tp_Xsnd.sb_mb ) { struct mbuf *m = m_copy($P.tp_Xsnd.sb_mb, 0, ??); (void) tp_emit(XPD_TPDU_type, $P, $P.tp_Xuna, 1, m); $P.tp_retrans = $P.tp_Nretrans; tp_ctimeout($P, TM_retrans, (int)$P.tp_xpd_ticks); SEQ_INC($P, $P.tp_Xsndnxt); } */ /* end of the above hack *//* TP4 only */SAME <== TP_OPEN XAK_TPDU ( tp_goodXack($P, $$.e_seq) ) /* tp_goodXack checks for good ack, removes the correct * tpdu from the queue and returns 1 if ack was legit, 0 if not. * also updates tp_Xuna */ { tp_ctimeout($P, TM_inact, (int)$P.tp_inact_ticks); tp_cuntimeout($P, TM_retrans); sbwakeup( &$P.tp_sock->so_snd ); /* resume normal data */ tp_send($P); };/* TP4, and TP0 after sending a CC or possibly a CR */SAME <== TP_OPEN XAK_TPDU DEFAULT { 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); } };/* TP4 only */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); 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); };/* TP0 only */SAME <== TP_OPEN T_USR_rcvd ($P.tp_class == TP_CLASS_0) { if (sbspace(&$P.tp_sock->so_rcv) > 0) tp0_openflow($P); };/* TP4 only */ /* If old credit was zero, * we'd better inform other side that we now have space * But this is not enough. Sender might not yet have * seen an ack with cdt 0 but it might still think the * window is closed, so it's going to wait. * Best to send an ack each time. * Strictly speaking, this ought to be a function of the * general ack strategy. */SAME <== TP_OPEN T_USR_rcvd DEFAULT { if( trick_hc ) { 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); } } };/* applicable in TP4, TP0 */SAME <== TP_REFWAIT [ T_USR_rcvd, T_USR_Xrcvd ] DEFAULT /* This happens if other end sent a DR when the user was waiting * on a receive. * Processing the DR includes putting us in REFWAIT state. */ { if(trick_hc) return ECONNABORTED; };/* TP0 only */TP_REFWAIT <== [ TP_OPEN, TP_CRSENT, TP_LISTENING ] T_NETRESET ( $P.tp_class != TP_CLASS_4 ) /* 0 or (4 and 0) */ /* in OPEN class will be 0 or 4 but not both */ /* in CRSENT or LISTENING it could be in negotiation, hence both */ /* Actually, this shouldn't ever happen in LISTENING */ { ASSERT( $P.tp_state != TP_LISTENING ); tp_indicate(T_DISCONNECT, $P, ECONNRESET); tp_soisdisconnected($P); };/* TP4: ignore resets */SAME <== [ TP_OPEN, TP_CRSENT, TP_AKWAIT, TP_CLOSING, TP_LISTENING ] T_NETRESET DEFAULT NULLACTION; /* applicable in TP4, TP0 */SAME <== [ TP_CLOSED, TP_REFWAIT ] T_NETRESET DEFAULT NULLACTION;/* C'EST TOUT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -