2 TCP timer related functions.
4 Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 UINT32 mTcpTick
= 1000;
20 Connect timeout handler.
22 @param Tcb Pointer to the TCP_CB of this TCP instance.
31 Timeout handler for TCP retransmission timer.
33 @param Tcb Pointer to the TCP_CB of this TCP instance.
42 Timeout handler for window probe timer.
44 @param Tcb Pointer to the TCP_CB of this TCP instance.
53 Timeout handler for keepalive timer.
55 @param Tcb Pointer to the TCP_CB of this TCP instance.
64 Timeout handler for FIN_WAIT_2 timer.
66 @param Tcb Pointer to the TCP_CB of this TCP instance.
75 Timeout handler for 2MSL timer.
77 @param Tcb Pointer to the TCP_CB of this TCP instance.
85 TCP_TIMER_HANDLER mTcpTimerHandler
[TCP_TIMER_NUMBER
] = {
95 Close the TCP connection.
97 @param Tcb Pointer to the TCP_CB of this TCP instance.
105 NetbufFreeList (&Tcb
->SndQue
);
106 NetbufFreeList (&Tcb
->RcvQue
);
108 TcpSetState (Tcb
, TCP_CLOSED
);
113 Connect timeout handler.
115 @param Tcb Pointer to the TCP_CB of this TCP instance.
123 if (!TCP_CONNECTED (Tcb
->State
)) {
124 DEBUG ((EFI_D_ERROR
, "TcpConnectTimeout: connection closed "
125 "because conenction timer timeout for TCB %p\n", Tcb
));
127 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
128 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
131 if (TCP_SYN_RCVD
== Tcb
->State
) {
132 DEBUG ((EFI_D_WARN
, "TcpConnectTimeout: send reset because "
133 "connection timer timeout for TCB %p\n", Tcb
));
135 TcpResetConnection (Tcb
);
145 Timeout handler for TCP retransmission timer.
147 @param Tcb Pointer to the TCP_CB of this TCP instance.
157 DEBUG ((EFI_D_WARN
, "TcpRexmitTimeout: transmission "
158 "timeout for TCB %p\n", Tcb
));
161 // Set the congestion window. FlightSize is the
162 // amount of data that has been sent but not
165 FlightSize
= TCP_SUB_SEQ (Tcb
->SndNxt
, Tcb
->SndUna
);
166 Tcb
->Ssthresh
= MAX ((UINT32
) (2 * Tcb
->SndMss
), FlightSize
/ 2);
168 Tcb
->CWnd
= Tcb
->SndMss
;
169 Tcb
->LossRecover
= Tcb
->SndNxt
;
172 if ((Tcb
->LossTimes
> Tcb
->MaxRexmit
) &&
173 !TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_CONNECT
)) {
175 DEBUG ((EFI_D_ERROR
, "TcpRexmitTimeout: connection closed "
176 "because too many timeouts for TCB %p\n", Tcb
));
178 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
179 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
187 TcpRetransmit (Tcb
, Tcb
->SndUna
);
188 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
190 Tcb
->CongestState
= TCP_CONGEST_LOSS
;
191 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
196 Timeout handler for window probe timer.
198 @param Tcb Pointer to the TCP_CB of this TCP instance.
207 // This is the timer for sender's SWSA. RFC1122 requires
208 // a timer set for sender's SWSA, and suggest combine it
209 // with window probe timer. If data is sent, don't set
210 // the probe timer, since retransmit timer is on.
212 if ((TcpDataToSend (Tcb
, 1) != 0) && (TcpToSendData (Tcb
, 1) > 0)) {
214 ASSERT (TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
) != 0);
215 Tcb
->ProbeTimerOn
= FALSE
;
219 TcpSendZeroProbe (Tcb
);
220 TcpSetProbeTimer (Tcb
);
225 Timeout handler for keepalive timer.
227 @param Tcb Pointer to the TCP_CB of this TCP instance.
231 TcpKeepaliveTimeout (
235 Tcb
->KeepAliveProbes
++;
238 // Too many Keep-alive probes, drop the connection
240 if (Tcb
->KeepAliveProbes
> Tcb
->MaxKeepAlive
) {
242 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
243 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
250 TcpSendZeroProbe (Tcb
);
251 TcpSetKeepaliveTimer (Tcb
);
256 Timeout handler for FIN_WAIT_2 timer.
258 @param Tcb Pointer to the TCP_CB of this TCP instance.
266 DEBUG ((EFI_D_WARN
, "TcpFinwait2Timeout: connection closed "
267 "because FIN_WAIT2 timer timeouts for TCB %p\n", Tcb
));
274 Timeout handler for 2MSL timer.
276 @param Tcb Pointer to the TCP_CB of this TCP instance.
284 DEBUG ((EFI_D_WARN
, "Tcp2MSLTimeout: connection closed "
285 "because TIME_WAIT timer timeouts for TCB %p\n", Tcb
));
292 Update the timer status and the next expire time according to the timers
293 to expire in a specific future time slot.
295 @param Tcb Pointer to the TCP_CB of this TCP instance.
306 // Don't use a too large value to init NextExpire
307 // since mTcpTick wraps around as sequence no does.
309 Tcb
->NextExpire
= 65535;
310 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
312 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
314 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
315 TCP_TIME_LT (Tcb
->Timer
[Index
], mTcpTick
+ Tcb
->NextExpire
)) {
317 Tcb
->NextExpire
= TCP_SUB_TIME (Tcb
->Timer
[Index
], mTcpTick
);
318 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
327 @param Tcb Pointer to the TCP_CB of this TCP instance.
328 @param Timer The index of the timer to be enabled.
329 @param TimeOut The timeout value of this timer.
339 TCP_SET_TIMER (Tcb
->EnabledTimer
, Timer
);
340 Tcb
->Timer
[Timer
] = mTcpTick
+ TimeOut
;
342 TcpUpdateTimer (Tcb
);
349 @param Tcb Pointer to the TCP_CB of this TCP instance.
350 @param Timer The index of the timer to be cleared.
359 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Timer
);
360 TcpUpdateTimer (Tcb
);
365 Clear all TCP timers.
367 @param Tcb Pointer to the TCP_CB of this TCP instance.
375 Tcb
->EnabledTimer
= 0;
376 TcpUpdateTimer (Tcb
);
381 Enable the window prober timer and set the timeout value.
383 @param Tcb Pointer to the TCP_CB of this TCP instance.
391 if (!Tcb
->ProbeTimerOn
) {
392 Tcb
->ProbeTime
= Tcb
->Rto
;
393 Tcb
->ProbeTimerOn
= TRUE
;
396 Tcb
->ProbeTime
<<= 1;
399 if (Tcb
->ProbeTime
< TCP_RTO_MIN
) {
401 Tcb
->ProbeTime
= TCP_RTO_MIN
;
402 } else if (Tcb
->ProbeTime
> TCP_RTO_MAX
) {
404 Tcb
->ProbeTime
= TCP_RTO_MAX
;
407 TcpSetTimer (Tcb
, TCP_TIMER_PROBE
, Tcb
->ProbeTime
);
412 Enable the keepalive timer and set the timeout value.
414 @param Tcb Pointer to the TCP_CB of this TCP instance.
418 TcpSetKeepaliveTimer (
422 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
)) {
428 // Set the timer to KeepAliveIdle if either
429 // 1. the keepalive timer is off
430 // 2. The keepalive timer is on, but the idle
431 // is less than KeepAliveIdle, that means the
432 // connection is alive since our last probe.
434 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_KEEPALIVE
) ||
435 (Tcb
->Idle
< Tcb
->KeepAliveIdle
)) {
437 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAliveIdle
);
438 Tcb
->KeepAliveProbes
= 0;
442 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAlivePeriod
);
450 @param Tcb Pointer to the TCP_CB of this TCP instance.
459 // Fold the RTT estimate if too many times, the estimate
460 // may be wrong, fold it. So the next time a valid
461 // measurement is sampled, we can start fresh.
463 if ((Tcb
->LossTimes
>= TCP_FOLD_RTT
) && (Tcb
->SRtt
!= 0)) {
464 Tcb
->RttVar
+= Tcb
->SRtt
>> 2;
470 if (Tcb
->Rto
< TCP_RTO_MIN
) {
472 Tcb
->Rto
= TCP_RTO_MIN
;
473 } else if (Tcb
->Rto
> TCP_RTO_MAX
) {
475 Tcb
->Rto
= TCP_RTO_MAX
;
481 Heart beat timer handler.
483 @param Context Context of the timer event, ignored.
498 mTcpGlobalIss
+= 100;
501 // Don't use LIST_FOR_EACH, which isn't delete safe.
503 for (Entry
= mTcpRunQue
.ForwardLink
; Entry
!= &mTcpRunQue
; Entry
= Next
) {
505 Next
= Entry
->ForwardLink
;
507 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
509 if (Tcb
->State
== TCP_CLOSED
) {
513 // The connection is doing RTT measurement.
515 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
521 if (Tcb
->DelayedAck
!= 0) {
526 // No timer is active or no timer expired
528 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
) ||
529 ((--Tcb
->NextExpire
) > 0)) {
535 // Call the timeout handler for each expired timer.
537 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
539 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
540 TCP_TIME_LEQ (Tcb
->Timer
[Index
], mTcpTick
)) {
542 // disable the timer before calling the handler
543 // in case the handler enables it again.
545 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Index
);
546 mTcpTimerHandler
[Index
](Tcb
);
549 // The Tcb may have been deleted by the timer, or
550 // no other timer is set.
552 if ((Next
->BackLink
!= Entry
) ||
553 (Tcb
->EnabledTimer
== 0)) {
560 // If the Tcb still exist or some timer is set, update the timer
562 if (Index
== TCP_TIMER_NUMBER
) {
563 TcpUpdateTimer (Tcb
);
569 Heart beat timer handler, queues the DPC at TPL_CALLBACK.
571 @param Event Timer event signaled, ignored.
572 @param Context Context of the timer event, ignored.
582 QueueDpc (TPL_CALLBACK
, TcpTickingDpc
, Context
);