?? tcptime.c
字號:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// TCPTIME.C
//
// TCP Timer Timeout Functions
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "tcp.h"
// tcp_backoff - Exponential backoff applied to Timer Ticks
UINT32 tcp_backoff[TCP_MAXBACKOFF+1] =
{ 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
//--------------------------------------------------------------------
// TcpSetPersist
//
// Set persist time used when client advertised window is Zero
//--------------------------------------------------------------------
void TcpSetPersist( TCPPROT *pt )
{
UINT32 Ticks;
// Calculate
Ticks = ( pt->t_srtt + 2 * pt->t_rttvar ) >> TCP_FIXP_SHIFT;
Ticks *= tcp_backoff[pt->t_rtxindex];
// Start/restart persistance timer.
TCPT_RANGESET( pt->dwTicksPersist, Ticks, TCPTV_PERSMIN, TCPTV_PERSMAX);
// Back off some more next time
if (pt->t_rtxindex < TCP_MAXBACKOFF)
pt->t_rtxindex++;
}
//--------------------------------------------------------------------
// TcpTimeoutWait2
//
// Called when the TCP wait timer (TIME_WAIT or FIN_WAIT_2) has fired
//--------------------------------------------------------------------
void TcpTimeoutWait2( TCPPROT *pt )
{
// If we're in the TIMEWAIT state, close the control block
// Otherwise, we're in FIN_WAIT_2 - if we've been idle for more
// than MAX_IDLE (10min), close the control block. Otherwise,
// time another interval.
if( pt->t_state != TSTATE_TIMEWAIT && pt->t_tidle <= TCPTV_MAX_IDLE )
pt->dwTicksWait2 = TCPTV_KEEP_INTVL;
else
TcpClose( pt );
}
//--------------------------------------------------------------------
// TcpTimeoutPersist
//
// Called when the TCP retransmit timer has expired
//--------------------------------------------------------------------
void TcpTimeoutPersist( TCPPROT *pt )
{
DbgPrintf(DBG_INFO,"TCP: Persist Timeout");
// Bump the timeout stats
tcps.dwPersistTimeout++;
// Set the next persist timeout
TcpSetPersist( pt );
// Force a segment (check for lost window advertisement)
pt->t_flags |= TF_PERSIST;
TcpOutput( pt );
}
//--------------------------------------------------------------------
// TcpTimeoutKeep
//
// Called when the TCP KeepAlive timer has expired
//--------------------------------------------------------------------
void TcpTimeoutKeep( TCPPROT *pt )
{
INT32 KeepAlive;
DbgPrintf(DBG_INFO,"TCP: Keep Timeout");
// Bump the timeout stats
tcps.dwKeepTimeout++;
// Check for timeout on a connection request
if( pt->t_state < TSTATE_ESTAB )
goto KeepDrop;
// Get the socket option KEEPALIVE
KeepAlive = SockGetOptionFlags( pt->hSock ) & SO_KEEPALIVE;
// Once "closed", KeepAlive no longer applies. Otherwise, when
// KeepAlive is set, send a probe.
if( KeepAlive && pt->t_state <= TSTATE_CLOSEWAIT )
{
// If we've been idle too long (2 hours + 10 min), drop connection
if( pt->t_tidle >= TCPTV_KEEP_IDLE + TCPTV_MAX_IDLE )
goto KeepDrop;
// Bump the "probe" stats
tcps.dwKeepProbe++;
// Send a keepalive packet
TcpGenPacket( pt, SockGetFIP(pt->hSock), SockGetFPort(pt->hSock),
SockGetLIP(pt->hSock), SockGetLPort(pt->hSock),
pt->rcv_nxt, pt->snd_una-1, 0 );
// Set to probe again in in 75 seconds
pt->dwTicksKeep = TCPTV_KEEP_INTVL;
}
else
{
// We're not active
// Set to probe again in in 2 hours seconds
pt->dwTicksKeep = TCPTV_KEEP_IDLE;
}
return;
KeepDrop:
// Bump the drop stats
tcps.dwKeepDrops++;
// Set socket error and drop connection
TcpDrop( pt, ETIMEDOUT );
}
//--------------------------------------------------------------------
// TcpTimeoutRexmt
//
// Called when the TCP retransmit timer has expired
//--------------------------------------------------------------------
void TcpTimeoutRexmt( TCPPROT *pt )
{
UINT32 win,Ticks;
DbgPrintf(DBG_INFO,"TCP: Retransmit Timeout");
//
// Message has not been acked within retransmit interval.
// Back off to a longer retransmit interval and retransmit one segment.
//
if( ++pt->t_rtxindex > TCP_MAXBACKOFF )
{
//
// Aleady at max - drop it like a bad habit
//
pt->t_rtxindex = TCP_MAXBACKOFF;
// Bump the drop stats
tcps.dwTimeoutDrops++;
// Set socket error and drop connection
TcpDrop( pt, ETIMEDOUT );
return;
}
// Bump the stats
tcps.dwRexmtTimeout++;
// Calculate
Ticks = ( pt->t_srtt + 4 * pt->t_rttvar ) >> TCP_FIXP_SHIFT;
Ticks *= tcp_backoff[pt->t_rtxindex];
// Start/restart retransmit timer.
TCPT_RANGESET( pt->t_trtx, Ticks, TCPTV_RTXMIN, TCPTV_RTXMAX);
pt->dwTicksRexmt = pt->t_trtx;
DbgPrintf(DBG_INFO,"TCP: Retransmit Ticks %ld",pt->t_trtx);
//
// If we've retransmitted four or more times, notify the
// Socket handler. Also, the round trip time is no longer
// accurate, so we reset it.
//
if (pt->t_rtxindex > TCP_MAXBACKOFF / 4)
{
// Notify socket its losing data
SockValidateRoute( pt->hSock );
// First pre-adjust rttvar so that RTO will be
// the same if we time out again
pt->t_rttvar += pt->t_srtt/4;
// Now clear srtt so that the measured RTT is used
pt->t_srtt = TCPTV_SRTTBASE;
}
// Retransmit earliest unacked sequence
pt->snd_nxt = pt->snd_una;
// Force a segment to be sent.
pt->t_flags |= TF_ACKNOW;
// If timing a segment in this window, stop the timer.
pt->t_trtt = 0;
//
// Close the congestion window down to one segment
// (we'll open it by one segment for each ack we get).
//
// This "slow start" keeps us from dumping all that data
// as back-to-back packets
//
// Take one half the LESSER of the advertised window, or the
// congestion window.
if( pt->snd_wnd < pt->snd_cwnd )
win = pt->snd_wnd / 2 / (UINT32)pt->t_mss;
else
win = pt->snd_cwnd / 2 / (UINT32)pt->t_mss;
if (win < 2)
win = 2;
pt->snd_cwnd = pt->t_mss; // (one segment)
pt->t_dupacks = 0; // Reset fast retransmit
// Retransmit earliest unacked sequence
TcpOutput( pt );
}
//--------------------------------------------------------------------
// TcpXmitTimer
//
// Called when reset xmit timer based on new RTT data
//--------------------------------------------------------------------
void TcpXmitTimer( TCPPROT *pt, UINT32 rtt )
{
INT32 delta;
UINT32 rto;
// Keep this stat for the heck of it.
tcps.dwRttUpdated++;
rtt = rtt << TCP_FIXP_SHIFT;
if( !pt->t_srtt )
{
// We have no data yet, so just initialize
//
// srtt = rtt
// rttvar = srtt / 2
// RTO = srtt + 2 * rttvar (same as 2*rtt)
//
pt->t_srtt = rtt;
pt->t_rttvar = pt->t_srtt / 2;
rto = ( rtt * 2 ) >> TCP_FIXP_SHIFT;
}
else
{
//
// We want to adjust srtt / rttvar by the following formulas:
//
// delta = ticks - srtt
// srtt = srtt + (1/8)delta
// rttvar = rttvar + (1/4)(|delta| - rttvar)
// RTO = srtt + 4 * rttvar
//
delta = rtt - (INT32)pt->t_srtt;
pt->t_srtt += (UINT32)(delta/8);
if( (INT32)pt->t_srtt <= 0 )
pt->t_srtt = 1 << TCP_FIXP_SHIFT;
if( delta < 0 )
delta = -delta;
delta -= (INT32)pt->t_rttvar;
pt->t_rttvar += (UINT32)(delta/4);
if( (INT32)pt->t_rttvar <= 0 )
pt->t_rttvar = 1 << (TCP_FIXP_SHIFT-2);
rto = ( pt->t_srtt + 4 * pt->t_rttvar ) >> TCP_FIXP_SHIFT;
}
// Reset RTT timer
pt->t_trtt = 0;
// Reset RTT backoff
pt->t_rtxindex = 0;
TCPT_RANGESET( pt->t_trtx, rto, TCPTV_RTXMIN, TCPTV_RTXMAX);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -