2 TCP timer related functions.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 UINT32 mTcpTick
= 1000;
15 Connect timeout handler.
17 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
26 Timeout handler for TCP retransmission timer.
28 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
37 Timeout handler for window probe timer.
39 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
48 Timeout handler for keepalive timer.
50 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
59 Timeout handler for FIN_WAIT_2 timer.
61 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
70 Timeout handler for 2MSL timer.
72 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
80 TCP_TIMER_HANDLER mTcpTimerHandler
[TCP_TIMER_NUMBER
] = {
90 Close the TCP connection.
92 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
100 NetbufFreeList (&Tcb
->SndQue
);
101 NetbufFreeList (&Tcb
->RcvQue
);
103 TcpSetState (Tcb
, TCP_CLOSED
);
109 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
118 // Fold the RTT estimate if too many times, the estimate
119 // may be wrong, fold it. So the next time a valid
120 // measurement is sampled, we can start fresh.
122 if ((Tcb
->LossTimes
>= TCP_FOLD_RTT
) && (Tcb
->SRtt
!= 0)) {
123 Tcb
->RttVar
+= Tcb
->SRtt
>> 2;
129 if (Tcb
->Rto
< TCP_RTO_MIN
) {
131 Tcb
->Rto
= TCP_RTO_MIN
;
132 } else if (Tcb
->Rto
> TCP_RTO_MAX
) {
134 Tcb
->Rto
= TCP_RTO_MAX
;
139 Connect timeout handler.
141 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
149 if (!TCP_CONNECTED (Tcb
->State
)) {
152 "TcpConnectTimeout: connection closed because conenction timer timeout for TCB %p\n",
156 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
157 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
160 if (TCP_SYN_RCVD
== Tcb
->State
) {
163 "TcpConnectTimeout: send reset because connection timer timeout for TCB %p\n",
167 TcpResetConnection (Tcb
);
177 Timeout handler for TCP retransmission timer.
179 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
191 "TcpRexmitTimeout: transmission timeout for TCB %p\n",
196 // Set the congestion window. FlightSize is the
197 // amount of data that has been sent but not
200 FlightSize
= TCP_SUB_SEQ (Tcb
->SndNxt
, Tcb
->SndUna
);
201 Tcb
->Ssthresh
= MAX ((UINT32
) (2 * Tcb
->SndMss
), FlightSize
/ 2);
203 Tcb
->CWnd
= Tcb
->SndMss
;
204 Tcb
->LossRecover
= Tcb
->SndNxt
;
207 if ((Tcb
->LossTimes
> Tcb
->MaxRexmit
) && !TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_CONNECT
)) {
211 "TcpRexmitTimeout: connection closed because too many timeouts for TCB %p\n",
215 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
216 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
224 TcpRetransmit (Tcb
, Tcb
->SndUna
);
225 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
227 Tcb
->CongestState
= TCP_CONGEST_LOSS
;
229 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
233 Timeout handler for window probe timer.
235 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
244 // This is the timer for sender's SWSA. RFC1122 requires
245 // a timer set for sender's SWSA, and suggest combine it
246 // with window probe timer. If data is sent, don't set
247 // the probe timer, since retransmit timer is on.
249 if ((TcpDataToSend (Tcb
, 1) != 0) && (TcpToSendData (Tcb
, 1) > 0)) {
251 ASSERT (TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
) != 0);
252 Tcb
->ProbeTimerOn
= FALSE
;
256 TcpSendZeroProbe (Tcb
);
257 TcpSetProbeTimer (Tcb
);
261 Timeout handler for keepalive timer.
263 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
267 TcpKeepaliveTimeout (
271 Tcb
->KeepAliveProbes
++;
274 // Too many Keep-alive probes, drop the connection
276 if (Tcb
->KeepAliveProbes
> Tcb
->MaxKeepAlive
) {
278 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
279 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
286 TcpSendZeroProbe (Tcb
);
287 TcpSetKeepaliveTimer (Tcb
);
291 Timeout handler for FIN_WAIT_2 timer.
293 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
303 "TcpFinwait2Timeout: connection closed because FIN_WAIT2 timer timeouts for TCB %p\n",
311 Timeout handler for 2MSL timer.
313 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
323 "Tcp2MSLTimeout: connection closed because TIME_WAIT timer timeouts for TCB %p\n",
331 Update the timer status and the next expire time according to the timers
332 to expire in a specific future time slot.
334 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
345 // Don't use a too large value to init NextExpire
346 // since mTcpTick wraps around as sequence no does.
348 Tcb
->NextExpire
= TCP_EXPIRE_TIME
;
349 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
351 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
353 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
354 TCP_TIME_LT (Tcb
->Timer
[Index
], mTcpTick
+ Tcb
->NextExpire
)
357 Tcb
->NextExpire
= TCP_SUB_TIME (Tcb
->Timer
[Index
], mTcpTick
);
358 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
366 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
367 @param[in] Timer The index of the timer to be enabled.
368 @param[in] TimeOut The timeout value of this timer.
378 TCP_SET_TIMER (Tcb
->EnabledTimer
, Timer
);
379 Tcb
->Timer
[Timer
] = mTcpTick
+ TimeOut
;
381 TcpUpdateTimer (Tcb
);
387 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
388 @param[in] Timer The index of the timer to be cleared.
397 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Timer
);
398 TcpUpdateTimer (Tcb
);
402 Clear all TCP timers.
404 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
412 Tcb
->EnabledTimer
= 0;
413 TcpUpdateTimer (Tcb
);
417 Enable the window prober timer and set the timeout value.
419 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
427 if (!Tcb
->ProbeTimerOn
) {
428 Tcb
->ProbeTime
= Tcb
->Rto
;
429 Tcb
->ProbeTimerOn
= TRUE
;
432 Tcb
->ProbeTime
<<= 1;
435 if (Tcb
->ProbeTime
< TCP_RTO_MIN
) {
437 Tcb
->ProbeTime
= TCP_RTO_MIN
;
438 } else if (Tcb
->ProbeTime
> TCP_RTO_MAX
) {
440 Tcb
->ProbeTime
= TCP_RTO_MAX
;
443 TcpSetTimer (Tcb
, TCP_TIMER_PROBE
, Tcb
->ProbeTime
);
447 Enable the keepalive timer and set the timeout value.
449 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
453 TcpSetKeepaliveTimer (
457 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
)) {
463 // Set the timer to KeepAliveIdle if either
464 // 1. the keepalive timer is off
465 // 2. The keepalive timer is on, but the idle
466 // is less than KeepAliveIdle, that means the
467 // connection is alive since our last probe.
469 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_KEEPALIVE
) ||
470 (Tcb
->Idle
< Tcb
->KeepAliveIdle
)
473 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAliveIdle
);
474 Tcb
->KeepAliveProbes
= 0;
478 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAlivePeriod
);
483 Heart beat timer handler.
485 @param[in] Context Context of the timer event, ignored.
500 mTcpGlobalIss
+= TCP_ISS_INCREMENT_2
;
503 // Don't use LIST_FOR_EACH, which isn't delete safe.
505 for (Entry
= mTcpRunQue
.ForwardLink
; Entry
!= &mTcpRunQue
; Entry
= Next
) {
507 Next
= Entry
->ForwardLink
;
509 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
511 if (Tcb
->State
== TCP_CLOSED
) {
515 // The connection is doing RTT measurement.
517 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
523 if (Tcb
->DelayedAck
!= 0) {
527 if (Tcb
->IpInfo
->IpVersion
== IP_VERSION_6
&& Tcb
->Tick
> 0) {
532 // No timer is active or no timer expired
534 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
) || ((--Tcb
->NextExpire
) > 0)) {
540 // Call the timeout handler for each expired timer.
542 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
544 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) && TCP_TIME_LEQ (Tcb
->Timer
[Index
], mTcpTick
)) {
546 // disable the timer before calling the handler
547 // in case the handler enables it again.
549 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Index
);
550 mTcpTimerHandler
[Index
](Tcb
);
553 // The Tcb may have been deleted by the timer, or
554 // no other timer is set.
556 if ((Next
->BackLink
!= Entry
) || (Tcb
->EnabledTimer
== 0)) {
563 // If the Tcb still exist or some timer is set, update the timer
565 if (Index
== TCP_TIMER_NUMBER
) {
566 TcpUpdateTimer (Tcb
);
572 Heart beat timer handler, queues the DPC at TPL_CALLBACK.
574 @param[in] Event Timer event signaled, ignored.
575 @param[in] Context Context of the timer event, ignored.
585 QueueDpc (TPL_CALLBACK
, TcpTickingDpc
, Context
);