123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- /** @file
- TCP timer related functions.
- Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "TcpMain.h"
- UINT32 mTcpTick = 1000;
- /**
- Connect timeout handler.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpConnectTimeout (
- IN OUT TCP_CB *Tcb
- );
- /**
- Timeout handler for TCP retransmission timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpRexmitTimeout (
- IN OUT TCP_CB *Tcb
- );
- /**
- Timeout handler for window probe timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpProbeTimeout (
- IN OUT TCP_CB *Tcb
- );
- /**
- Timeout handler for keepalive timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpKeepaliveTimeout (
- IN OUT TCP_CB *Tcb
- );
- /**
- Timeout handler for FIN_WAIT_2 timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpFinwait2Timeout (
- IN OUT TCP_CB *Tcb
- );
- /**
- Timeout handler for 2MSL timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- Tcp2MSLTimeout (
- IN OUT TCP_CB *Tcb
- );
- TCP_TIMER_HANDLER mTcpTimerHandler[TCP_TIMER_NUMBER] = {
- TcpConnectTimeout,
- TcpRexmitTimeout,
- TcpProbeTimeout,
- TcpKeepaliveTimeout,
- TcpFinwait2Timeout,
- Tcp2MSLTimeout,
- };
- /**
- Close the TCP connection.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpClose (
- IN OUT TCP_CB *Tcb
- )
- {
- NetbufFreeList (&Tcb->SndQue);
- NetbufFreeList (&Tcb->RcvQue);
- TcpSetState (Tcb, TCP_CLOSED);
- }
- /**
- Backoff the RTO.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpBackoffRto (
- IN OUT TCP_CB *Tcb
- )
- {
- //
- // Fold the RTT estimate if too many times, the estimate
- // may be wrong, fold it. So the next time a valid
- // measurement is sampled, we can start fresh.
- //
- if ((Tcb->LossTimes >= TCP_FOLD_RTT) && (Tcb->SRtt != 0)) {
- Tcb->RttVar += Tcb->SRtt >> 2;
- Tcb->SRtt = 0;
- }
- Tcb->Rto <<= 1;
- if (Tcb->Rto < TCP_RTO_MIN) {
- Tcb->Rto = TCP_RTO_MIN;
- } else if (Tcb->Rto > TCP_RTO_MAX) {
- Tcb->Rto = TCP_RTO_MAX;
- }
- }
- /**
- Connect timeout handler.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpConnectTimeout (
- IN OUT TCP_CB *Tcb
- )
- {
- if (!TCP_CONNECTED (Tcb->State)) {
- DEBUG (
- (DEBUG_ERROR,
- "TcpConnectTimeout: connection closed because connection timer timeout for TCB %p\n",
- Tcb)
- );
- if (EFI_ABORTED == Tcb->Sk->SockError) {
- SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
- }
- if (TCP_SYN_RCVD == Tcb->State) {
- DEBUG (
- (DEBUG_WARN,
- "TcpConnectTimeout: send reset because connection timer timeout for TCB %p\n",
- Tcb)
- );
- TcpResetConnection (Tcb);
- }
- TcpClose (Tcb);
- }
- }
- /**
- Timeout handler for TCP retransmission timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpRexmitTimeout (
- IN OUT TCP_CB *Tcb
- )
- {
- UINT32 FlightSize;
- DEBUG (
- (DEBUG_WARN,
- "TcpRexmitTimeout: transmission timeout for TCB %p\n",
- Tcb)
- );
- //
- // Set the congestion window. FlightSize is the
- // amount of data that has been sent but not
- // yet ACKed.
- //
- FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
- Tcb->Ssthresh = MAX ((UINT32)(2 * Tcb->SndMss), FlightSize / 2);
- Tcb->CWnd = Tcb->SndMss;
- Tcb->LossRecover = Tcb->SndNxt;
- Tcb->LossTimes++;
- if ((Tcb->LossTimes > Tcb->MaxRexmit) && !TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_CONNECT)) {
- DEBUG (
- (DEBUG_ERROR,
- "TcpRexmitTimeout: connection closed because too many timeouts for TCB %p\n",
- Tcb)
- );
- if (EFI_ABORTED == Tcb->Sk->SockError) {
- SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
- }
- TcpClose (Tcb);
- return;
- }
- TcpBackoffRto (Tcb);
- TcpRetransmit (Tcb, Tcb->SndUna);
- TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
- Tcb->CongestState = TCP_CONGEST_LOSS;
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
- }
- /**
- Timeout handler for window probe timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpProbeTimeout (
- IN OUT TCP_CB *Tcb
- )
- {
- //
- // This is the timer for sender's SWSA. RFC1122 requires
- // a timer set for sender's SWSA, and suggest combine it
- // with window probe timer. If data is sent, don't set
- // the probe timer, since retransmit timer is on.
- //
- if ((TcpDataToSend (Tcb, 1) != 0) && (TcpToSendData (Tcb, 1) > 0)) {
- ASSERT (TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT) != 0);
- Tcb->ProbeTimerOn = FALSE;
- return;
- }
- TcpSendZeroProbe (Tcb);
- TcpSetProbeTimer (Tcb);
- }
- /**
- Timeout handler for keepalive timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpKeepaliveTimeout (
- IN OUT TCP_CB *Tcb
- )
- {
- Tcb->KeepAliveProbes++;
- //
- // Too many Keep-alive probes, drop the connection
- //
- if (Tcb->KeepAliveProbes > Tcb->MaxKeepAlive) {
- if (EFI_ABORTED == Tcb->Sk->SockError) {
- SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
- }
- TcpClose (Tcb);
- return;
- }
- TcpSendZeroProbe (Tcb);
- TcpSetKeepaliveTimer (Tcb);
- }
- /**
- Timeout handler for FIN_WAIT_2 timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpFinwait2Timeout (
- IN OUT TCP_CB *Tcb
- )
- {
- DEBUG (
- (DEBUG_WARN,
- "TcpFinwait2Timeout: connection closed because FIN_WAIT2 timer timeouts for TCB %p\n",
- Tcb)
- );
- TcpClose (Tcb);
- }
- /**
- Timeout handler for 2MSL timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- Tcp2MSLTimeout (
- IN OUT TCP_CB *Tcb
- )
- {
- DEBUG (
- (DEBUG_WARN,
- "Tcp2MSLTimeout: connection closed because TIME_WAIT timer timeouts for TCB %p\n",
- Tcb)
- );
- TcpClose (Tcb);
- }
- /**
- Update the timer status and the next expire time according to the timers
- to expire in a specific future time slot.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpUpdateTimer (
- IN OUT TCP_CB *Tcb
- )
- {
- UINT16 Index;
- //
- // Don't use a too large value to init NextExpire
- // since mTcpTick wraps around as sequence no does.
- //
- Tcb->NextExpire = TCP_EXPIRE_TIME;
- TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
- for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
- if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
- TCP_TIME_LT (Tcb->Timer[Index], mTcpTick + Tcb->NextExpire)
- )
- {
- Tcb->NextExpire = TCP_SUB_TIME (Tcb->Timer[Index], mTcpTick);
- TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
- }
- }
- }
- /**
- Enable a TCP timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- @param[in] Timer The index of the timer to be enabled.
- @param[in] TimeOut The timeout value of this timer.
- **/
- VOID
- TcpSetTimer (
- IN OUT TCP_CB *Tcb,
- IN UINT16 Timer,
- IN UINT32 TimeOut
- )
- {
- TCP_SET_TIMER (Tcb->EnabledTimer, Timer);
- Tcb->Timer[Timer] = mTcpTick + TimeOut;
- TcpUpdateTimer (Tcb);
- }
- /**
- Clear one TCP timer.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- @param[in] Timer The index of the timer to be cleared.
- **/
- VOID
- TcpClearTimer (
- IN OUT TCP_CB *Tcb,
- IN UINT16 Timer
- )
- {
- TCP_CLEAR_TIMER (Tcb->EnabledTimer, Timer);
- TcpUpdateTimer (Tcb);
- }
- /**
- Clear all TCP timers.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpClearAllTimer (
- IN OUT TCP_CB *Tcb
- )
- {
- Tcb->EnabledTimer = 0;
- TcpUpdateTimer (Tcb);
- }
- /**
- Enable the window prober timer and set the timeout value.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpSetProbeTimer (
- IN OUT TCP_CB *Tcb
- )
- {
- if (!Tcb->ProbeTimerOn) {
- Tcb->ProbeTime = Tcb->Rto;
- Tcb->ProbeTimerOn = TRUE;
- } else {
- Tcb->ProbeTime <<= 1;
- }
- if (Tcb->ProbeTime < TCP_RTO_MIN) {
- Tcb->ProbeTime = TCP_RTO_MIN;
- } else if (Tcb->ProbeTime > TCP_RTO_MAX) {
- Tcb->ProbeTime = TCP_RTO_MAX;
- }
- TcpSetTimer (Tcb, TCP_TIMER_PROBE, Tcb->ProbeTime);
- }
- /**
- Enable the keepalive timer and set the timeout value.
- @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
- **/
- VOID
- TcpSetKeepaliveTimer (
- IN OUT TCP_CB *Tcb
- )
- {
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE)) {
- return;
- }
- //
- // Set the timer to KeepAliveIdle if either
- // 1. the keepalive timer is off
- // 2. The keepalive timer is on, but the idle
- // is less than KeepAliveIdle, that means the
- // connection is alive since our last probe.
- //
- if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_KEEPALIVE) ||
- (Tcb->Idle < Tcb->KeepAliveIdle)
- )
- {
- TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAliveIdle);
- Tcb->KeepAliveProbes = 0;
- } else {
- TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAlivePeriod);
- }
- }
- /**
- Heart beat timer handler.
- @param[in] Context Context of the timer event, ignored.
- **/
- VOID
- EFIAPI
- TcpTickingDpc (
- IN VOID *Context
- )
- {
- LIST_ENTRY *Entry;
- LIST_ENTRY *Next;
- TCP_CB *Tcb;
- INT16 Index;
- mTcpTick++;
- mTcpGlobalIss += TCP_ISS_INCREMENT_2;
- //
- // Don't use LIST_FOR_EACH, which isn't delete safe.
- //
- for (Entry = mTcpRunQue.ForwardLink; Entry != &mTcpRunQue; Entry = Next) {
- Next = Entry->ForwardLink;
- Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
- if (Tcb->State == TCP_CLOSED) {
- continue;
- }
- //
- // The connection is doing RTT measurement.
- //
- if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
- Tcb->RttMeasure++;
- }
- Tcb->Idle++;
- if (Tcb->DelayedAck != 0) {
- TcpSendAck (Tcb);
- }
- if ((Tcb->IpInfo->IpVersion == IP_VERSION_6) && (Tcb->Tick > 0)) {
- Tcb->Tick--;
- }
- //
- // No timer is active or no timer expired
- //
- if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON) || ((--Tcb->NextExpire) > 0)) {
- continue;
- }
- //
- // Call the timeout handler for each expired timer.
- //
- for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
- if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) && TCP_TIME_LEQ (Tcb->Timer[Index], mTcpTick)) {
- //
- // disable the timer before calling the handler
- // in case the handler enables it again.
- //
- TCP_CLEAR_TIMER (Tcb->EnabledTimer, Index);
- mTcpTimerHandler[Index](Tcb);
- //
- // The Tcb may have been deleted by the timer, or
- // no other timer is set.
- //
- if ((Next->BackLink != Entry) || (Tcb->EnabledTimer == 0)) {
- break;
- }
- }
- }
- //
- // If the Tcb still exist or some timer is set, update the timer
- //
- if (Index == TCP_TIMER_NUMBER) {
- TcpUpdateTimer (Tcb);
- }
- }
- }
- /**
- Heart beat timer handler, queues the DPC at TPL_CALLBACK.
- @param[in] Event Timer event signaled, ignored.
- @param[in] Context Context of the timer event, ignored.
- **/
- VOID
- EFIAPI
- TcpTicking (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
- {
- QueueDpc (TPL_CALLBACK, TcpTickingDpc, Context);
- }
|