2 TCP timer related functions.
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 UINT32 mTcpTick
= 1000;
21 Connect timeout handler.
23 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
32 Timeout handler for TCP retransmission timer.
34 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
43 Timeout handler for window probe timer.
45 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
54 Timeout handler for keepalive timer.
56 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
65 Timeout handler for FIN_WAIT_2 timer.
67 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
76 Timeout handler for 2MSL timer.
78 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
86 TCP_TIMER_HANDLER mTcpTimerHandler
[TCP_TIMER_NUMBER
] = {
96 Close the TCP connection.
98 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
106 NetbufFreeList (&Tcb
->SndQue
);
107 NetbufFreeList (&Tcb
->RcvQue
);
109 TcpSetState (Tcb
, TCP_CLOSED
);
115 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
124 // Fold the RTT estimate if too many times, the estimate
125 // may be wrong, fold it. So the next time a valid
126 // measurement is sampled, we can start fresh.
128 if ((Tcb
->LossTimes
>= TCP_FOLD_RTT
) && (Tcb
->SRtt
!= 0)) {
129 Tcb
->RttVar
+= Tcb
->SRtt
>> 2;
135 if (Tcb
->Rto
< TCP_RTO_MIN
) {
137 Tcb
->Rto
= TCP_RTO_MIN
;
138 } else if (Tcb
->Rto
> TCP_RTO_MAX
) {
140 Tcb
->Rto
= TCP_RTO_MAX
;
145 Connect timeout handler.
147 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
155 if (!TCP_CONNECTED (Tcb
->State
)) {
158 "TcpConnectTimeout: connection closed because conenction timer timeout for TCB %p\n",
162 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
163 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
166 if (TCP_SYN_RCVD
== Tcb
->State
) {
169 "TcpConnectTimeout: send reset because connection timer timeout for TCB %p\n",
173 TcpResetConnection (Tcb
);
183 Timeout handler for TCP retransmission timer.
185 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
197 "TcpRexmitTimeout: transmission timeout for TCB %p\n",
202 // Set the congestion window. FlightSize is the
203 // amount of data that has been sent but not
206 FlightSize
= TCP_SUB_SEQ (Tcb
->SndNxt
, Tcb
->SndUna
);
207 Tcb
->Ssthresh
= MAX ((UINT32
) (2 * Tcb
->SndMss
), FlightSize
/ 2);
209 Tcb
->CWnd
= Tcb
->SndMss
;
210 Tcb
->LossRecover
= Tcb
->SndNxt
;
213 if ((Tcb
->LossTimes
> Tcb
->MaxRexmit
) && !TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_CONNECT
)) {
217 "TcpRexmitTimeout: connection closed because too many timeouts for TCB %p\n",
221 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
222 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
230 TcpRetransmit (Tcb
, Tcb
->SndUna
);
231 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
233 Tcb
->CongestState
= TCP_CONGEST_LOSS
;
235 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
239 Timeout handler for window probe timer.
241 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
250 // This is the timer for sender's SWSA. RFC1122 requires
251 // a timer set for sender's SWSA, and suggest combine it
252 // with window probe timer. If data is sent, don't set
253 // the probe timer, since retransmit timer is on.
255 if ((TcpDataToSend (Tcb
, 1) != 0) && (TcpToSendData (Tcb
, 1) > 0)) {
257 ASSERT (TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
) != 0);
258 Tcb
->ProbeTimerOn
= FALSE
;
262 TcpSendZeroProbe (Tcb
);
263 TcpSetProbeTimer (Tcb
);
267 Timeout handler for keepalive timer.
269 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
273 TcpKeepaliveTimeout (
277 Tcb
->KeepAliveProbes
++;
280 // Too many Keep-alive probes, drop the connection
282 if (Tcb
->KeepAliveProbes
> Tcb
->MaxKeepAlive
) {
284 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
285 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
292 TcpSendZeroProbe (Tcb
);
293 TcpSetKeepaliveTimer (Tcb
);
297 Timeout handler for FIN_WAIT_2 timer.
299 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
309 "TcpFinwait2Timeout: connection closed because FIN_WAIT2 timer timeouts for TCB %p\n",
317 Timeout handler for 2MSL timer.
319 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
329 "Tcp2MSLTimeout: connection closed because TIME_WAIT timer timeouts for TCB %p\n",
337 Update the timer status and the next expire time according to the timers
338 to expire in a specific future time slot.
340 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
351 // Don't use a too large value to init NextExpire
352 // since mTcpTick wraps around as sequence no does.
354 Tcb
->NextExpire
= TCP_EXPIRE_TIME
;
355 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
357 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
359 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
360 TCP_TIME_LT (Tcb
->Timer
[Index
], mTcpTick
+ Tcb
->NextExpire
)
363 Tcb
->NextExpire
= TCP_SUB_TIME (Tcb
->Timer
[Index
], mTcpTick
);
364 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
372 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
373 @param[in] Timer The index of the timer to be enabled.
374 @param[in] TimeOut The timeout value of this timer.
384 TCP_SET_TIMER (Tcb
->EnabledTimer
, Timer
);
385 Tcb
->Timer
[Timer
] = mTcpTick
+ TimeOut
;
387 TcpUpdateTimer (Tcb
);
393 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
394 @param[in] Timer The index of the timer to be cleared.
403 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Timer
);
404 TcpUpdateTimer (Tcb
);
408 Clear all TCP timers.
410 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
418 Tcb
->EnabledTimer
= 0;
419 TcpUpdateTimer (Tcb
);
423 Enable the window prober timer and set the timeout value.
425 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
433 if (!Tcb
->ProbeTimerOn
) {
434 Tcb
->ProbeTime
= Tcb
->Rto
;
435 Tcb
->ProbeTimerOn
= TRUE
;
438 Tcb
->ProbeTime
<<= 1;
441 if (Tcb
->ProbeTime
< TCP_RTO_MIN
) {
443 Tcb
->ProbeTime
= TCP_RTO_MIN
;
444 } else if (Tcb
->ProbeTime
> TCP_RTO_MAX
) {
446 Tcb
->ProbeTime
= TCP_RTO_MAX
;
449 TcpSetTimer (Tcb
, TCP_TIMER_PROBE
, Tcb
->ProbeTime
);
453 Enable the keepalive timer and set the timeout value.
455 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
459 TcpSetKeepaliveTimer (
463 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
)) {
469 // Set the timer to KeepAliveIdle if either
470 // 1. the keepalive timer is off
471 // 2. The keepalive timer is on, but the idle
472 // is less than KeepAliveIdle, that means the
473 // connection is alive since our last probe.
475 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_KEEPALIVE
) ||
476 (Tcb
->Idle
< Tcb
->KeepAliveIdle
)
479 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAliveIdle
);
480 Tcb
->KeepAliveProbes
= 0;
484 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAlivePeriod
);
489 Heart beat timer handler.
491 @param[in] Context Context of the timer event, ignored.
506 mTcpGlobalIss
+= TCP_ISS_INCREMENT_2
;
509 // Don't use LIST_FOR_EACH, which isn't delete safe.
511 for (Entry
= mTcpRunQue
.ForwardLink
; Entry
!= &mTcpRunQue
; Entry
= Next
) {
513 Next
= Entry
->ForwardLink
;
515 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
517 if (Tcb
->State
== TCP_CLOSED
) {
521 // The connection is doing RTT measurement.
523 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
529 if (Tcb
->DelayedAck
!= 0) {
533 if (Tcb
->IpInfo
->IpVersion
== IP_VERSION_6
&& Tcb
->Tick
> 0) {
538 // No timer is active or no timer expired
540 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
) || ((--Tcb
->NextExpire
) > 0)) {
546 // Call the timeout handler for each expired timer.
548 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
550 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) && TCP_TIME_LEQ (Tcb
->Timer
[Index
], mTcpTick
)) {
552 // disable the timer before calling the handler
553 // in case the handler enables it again.
555 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Index
);
556 mTcpTimerHandler
[Index
](Tcb
);
559 // The Tcb may have been deleted by the timer, or
560 // no other timer is set.
562 if ((Next
->BackLink
!= Entry
) || (Tcb
->EnabledTimer
== 0)) {
569 // If the Tcb still exist or some timer is set, update the timer
571 if (Index
== TCP_TIMER_NUMBER
) {
572 TcpUpdateTimer (Tcb
);
578 Heart beat timer handler, queues the DPC at TPL_CALLBACK.
580 @param[in] Event Timer event signaled, ignored.
581 @param[in] Context Context of the timer event, ignored.
591 QueueDpc (TPL_CALLBACK
, TcpTickingDpc
, Context
);