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
) {
130 Tcb
->Rto
= TCP_RTO_MIN
;
131 } else if (Tcb
->Rto
> TCP_RTO_MAX
) {
132 Tcb
->Rto
= TCP_RTO_MAX
;
137 Connect timeout handler.
139 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
147 if (!TCP_CONNECTED (Tcb
->State
)) {
150 "TcpConnectTimeout: connection closed because connection timer timeout for TCB %p\n",
154 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
155 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
158 if (TCP_SYN_RCVD
== Tcb
->State
) {
161 "TcpConnectTimeout: send reset because connection timer timeout for TCB %p\n",
165 TcpResetConnection (Tcb
);
173 Timeout handler for TCP retransmission timer.
175 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
187 "TcpRexmitTimeout: transmission timeout for TCB %p\n",
192 // Set the congestion window. FlightSize is the
193 // amount of data that has been sent but not
196 FlightSize
= TCP_SUB_SEQ (Tcb
->SndNxt
, Tcb
->SndUna
);
197 Tcb
->Ssthresh
= MAX ((UINT32
)(2 * Tcb
->SndMss
), FlightSize
/ 2);
199 Tcb
->CWnd
= Tcb
->SndMss
;
200 Tcb
->LossRecover
= Tcb
->SndNxt
;
203 if ((Tcb
->LossTimes
> Tcb
->MaxRexmit
) && !TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_CONNECT
)) {
206 "TcpRexmitTimeout: connection closed because too many timeouts for TCB %p\n",
210 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
211 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
219 TcpRetransmit (Tcb
, Tcb
->SndUna
);
220 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
222 Tcb
->CongestState
= TCP_CONGEST_LOSS
;
224 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
228 Timeout handler for window probe timer.
230 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
239 // This is the timer for sender's SWSA. RFC1122 requires
240 // a timer set for sender's SWSA, and suggest combine it
241 // with window probe timer. If data is sent, don't set
242 // the probe timer, since retransmit timer is on.
244 if ((TcpDataToSend (Tcb
, 1) != 0) && (TcpToSendData (Tcb
, 1) > 0)) {
245 ASSERT (TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
) != 0);
246 Tcb
->ProbeTimerOn
= FALSE
;
250 TcpSendZeroProbe (Tcb
);
251 TcpSetProbeTimer (Tcb
);
255 Timeout handler for keepalive timer.
257 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
261 TcpKeepaliveTimeout (
265 Tcb
->KeepAliveProbes
++;
268 // Too many Keep-alive probes, drop the connection
270 if (Tcb
->KeepAliveProbes
> Tcb
->MaxKeepAlive
) {
271 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
272 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
279 TcpSendZeroProbe (Tcb
);
280 TcpSetKeepaliveTimer (Tcb
);
284 Timeout handler for FIN_WAIT_2 timer.
286 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
296 "TcpFinwait2Timeout: connection closed because FIN_WAIT2 timer timeouts for TCB %p\n",
304 Timeout handler for 2MSL timer.
306 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
316 "Tcp2MSLTimeout: connection closed because TIME_WAIT timer timeouts for TCB %p\n",
324 Update the timer status and the next expire time according to the timers
325 to expire in a specific future time slot.
327 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
338 // Don't use a too large value to init NextExpire
339 // since mTcpTick wraps around as sequence no does.
341 Tcb
->NextExpire
= TCP_EXPIRE_TIME
;
342 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
344 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
345 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
346 TCP_TIME_LT (Tcb
->Timer
[Index
], mTcpTick
+ Tcb
->NextExpire
)
349 Tcb
->NextExpire
= TCP_SUB_TIME (Tcb
->Timer
[Index
], mTcpTick
);
350 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
358 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
359 @param[in] Timer The index of the timer to be enabled.
360 @param[in] TimeOut The timeout value of this timer.
370 TCP_SET_TIMER (Tcb
->EnabledTimer
, Timer
);
371 Tcb
->Timer
[Timer
] = mTcpTick
+ TimeOut
;
373 TcpUpdateTimer (Tcb
);
379 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
380 @param[in] Timer The index of the timer to be cleared.
389 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Timer
);
390 TcpUpdateTimer (Tcb
);
394 Clear all TCP timers.
396 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
404 Tcb
->EnabledTimer
= 0;
405 TcpUpdateTimer (Tcb
);
409 Enable the window prober timer and set the timeout value.
411 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
419 if (!Tcb
->ProbeTimerOn
) {
420 Tcb
->ProbeTime
= Tcb
->Rto
;
421 Tcb
->ProbeTimerOn
= TRUE
;
423 Tcb
->ProbeTime
<<= 1;
426 if (Tcb
->ProbeTime
< TCP_RTO_MIN
) {
427 Tcb
->ProbeTime
= TCP_RTO_MIN
;
428 } else if (Tcb
->ProbeTime
> TCP_RTO_MAX
) {
429 Tcb
->ProbeTime
= TCP_RTO_MAX
;
432 TcpSetTimer (Tcb
, TCP_TIMER_PROBE
, Tcb
->ProbeTime
);
436 Enable the keepalive timer and set the timeout value.
438 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
442 TcpSetKeepaliveTimer (
446 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
)) {
451 // Set the timer to KeepAliveIdle if either
452 // 1. the keepalive timer is off
453 // 2. The keepalive timer is on, but the idle
454 // is less than KeepAliveIdle, that means the
455 // connection is alive since our last probe.
457 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_KEEPALIVE
) ||
458 (Tcb
->Idle
< Tcb
->KeepAliveIdle
)
461 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAliveIdle
);
462 Tcb
->KeepAliveProbes
= 0;
464 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAlivePeriod
);
469 Heart beat timer handler.
471 @param[in] Context Context of the timer event, ignored.
486 mTcpGlobalIss
+= TCP_ISS_INCREMENT_2
;
489 // Don't use LIST_FOR_EACH, which isn't delete safe.
491 for (Entry
= mTcpRunQue
.ForwardLink
; Entry
!= &mTcpRunQue
; Entry
= Next
) {
492 Next
= Entry
->ForwardLink
;
494 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
496 if (Tcb
->State
== TCP_CLOSED
) {
501 // The connection is doing RTT measurement.
503 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
509 if (Tcb
->DelayedAck
!= 0) {
513 if ((Tcb
->IpInfo
->IpVersion
== IP_VERSION_6
) && (Tcb
->Tick
> 0)) {
518 // No timer is active or no timer expired
520 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
) || ((--Tcb
->NextExpire
) > 0)) {
525 // Call the timeout handler for each expired timer.
527 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
528 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) && TCP_TIME_LEQ (Tcb
->Timer
[Index
], mTcpTick
)) {
530 // disable the timer before calling the handler
531 // in case the handler enables it again.
533 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Index
);
534 mTcpTimerHandler
[Index
](Tcb
);
537 // The Tcb may have been deleted by the timer, or
538 // no other timer is set.
540 if ((Next
->BackLink
!= Entry
) || (Tcb
->EnabledTimer
== 0)) {
547 // If the Tcb still exist or some timer is set, update the timer
549 if (Index
== TCP_TIMER_NUMBER
) {
550 TcpUpdateTimer (Tcb
);
556 Heart beat timer handler, queues the DPC at TPL_CALLBACK.
558 @param[in] Event Timer event signaled, ignored.
559 @param[in] Context Context of the timer event, ignored.
569 QueueDpc (TPL_CALLBACK
, TcpTickingDpc
, Context
);