2 TCP timer related functions.
4 Copyright (c) 2005 - 2007, 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);
218 TcpSendZeroProbe (Tcb
);
219 TcpSetProbeTimer (Tcb
);
224 Timeout handler for keepalive timer.
226 @param Tcb Pointer to the TCP_CB of this TCP instance.
230 TcpKeepaliveTimeout (
234 Tcb
->KeepAliveProbes
++;
237 // Too many Keep-alive probes, drop the connection
239 if (Tcb
->KeepAliveProbes
> Tcb
->MaxKeepAlive
) {
241 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
242 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
249 TcpSendZeroProbe (Tcb
);
250 TcpSetKeepaliveTimer (Tcb
);
255 Timeout handler for FIN_WAIT_2 timer.
257 @param Tcb Pointer to the TCP_CB of this TCP instance.
265 DEBUG ((EFI_D_WARN
, "TcpFinwait2Timeout: connection closed "
266 "because FIN_WAIT2 timer timeouts for TCB %p\n", Tcb
));
273 Timeout handler for 2MSL timer.
275 @param Tcb Pointer to the TCP_CB of this TCP instance.
283 DEBUG ((EFI_D_WARN
, "Tcp2MSLTimeout: connection closed "
284 "because TIME_WAIT timer timeouts for TCB %p\n", Tcb
));
291 Update the timer status and the next expire time according to the timers
292 to expire in a specific future time slot.
294 @param Tcb Pointer to the TCP_CB of this TCP instance.
305 // Don't use a too large value to init NextExpire
306 // since mTcpTick wraps around as sequence no does.
308 Tcb
->NextExpire
= 65535;
309 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
311 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
313 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
314 TCP_TIME_LT (Tcb
->Timer
[Index
], mTcpTick
+ Tcb
->NextExpire
)) {
316 Tcb
->NextExpire
= TCP_SUB_TIME (Tcb
->Timer
[Index
], mTcpTick
);
317 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
326 @param Tcb Pointer to the TCP_CB of this TCP instance.
327 @param Timer The index of the timer to be enabled.
328 @param TimeOut The timeout value of this timer.
338 TCP_SET_TIMER (Tcb
->EnabledTimer
, Timer
);
339 Tcb
->Timer
[Timer
] = mTcpTick
+ TimeOut
;
341 TcpUpdateTimer (Tcb
);
348 @param Tcb Pointer to the TCP_CB of this TCP instance.
349 @param Timer The index of the timer to be cleared.
358 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Timer
);
359 TcpUpdateTimer (Tcb
);
364 Clear all TCP timers.
366 @param Tcb Pointer to the TCP_CB of this TCP instance.
374 Tcb
->EnabledTimer
= 0;
375 TcpUpdateTimer (Tcb
);
380 Enable the window prober timer and set the timeout value.
382 @param Tcb Pointer to the TCP_CB of this TCP instance.
390 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_PROBE
)) {
391 Tcb
->ProbeTime
= Tcb
->Rto
;
394 Tcb
->ProbeTime
<<= 1;
397 if (Tcb
->ProbeTime
< TCP_RTO_MIN
) {
399 Tcb
->ProbeTime
= TCP_RTO_MIN
;
400 } else if (Tcb
->ProbeTime
> TCP_RTO_MAX
) {
402 Tcb
->ProbeTime
= TCP_RTO_MAX
;
405 TcpSetTimer (Tcb
, TCP_TIMER_PROBE
, Tcb
->ProbeTime
);
410 Enable the keepalive timer and set the timeout value.
412 @param Tcb Pointer to the TCP_CB of this TCP instance.
416 TcpSetKeepaliveTimer (
420 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
)) {
426 // Set the timer to KeepAliveIdle if either
427 // 1. the keepalive timer is off
428 // 2. The keepalive timer is on, but the idle
429 // is less than KeepAliveIdle, that means the
430 // connection is alive since our last probe.
432 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_KEEPALIVE
) ||
433 (Tcb
->Idle
< Tcb
->KeepAliveIdle
)) {
435 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAliveIdle
);
436 Tcb
->KeepAliveProbes
= 0;
440 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAlivePeriod
);
448 @param Tcb Pointer to the TCP_CB of this TCP instance.
457 // Fold the RTT estimate if too many times, the estimate
458 // may be wrong, fold it. So the next time a valid
459 // measurement is sampled, we can start fresh.
461 if ((Tcb
->LossTimes
>= TCP_FOLD_RTT
) && (Tcb
->SRtt
!= 0)) {
462 Tcb
->RttVar
+= Tcb
->SRtt
>> 2;
468 if (Tcb
->Rto
< TCP_RTO_MIN
) {
470 Tcb
->Rto
= TCP_RTO_MIN
;
471 } else if (Tcb
->Rto
> TCP_RTO_MAX
) {
473 Tcb
->Rto
= TCP_RTO_MAX
;
479 Heart beat timer handler.
481 @param Context Context of the timer event, ignored.
496 mTcpGlobalIss
+= 100;
499 // Don't use LIST_FOR_EACH, which isn't delete safe.
501 for (Entry
= mTcpRunQue
.ForwardLink
; Entry
!= &mTcpRunQue
; Entry
= Next
) {
503 Next
= Entry
->ForwardLink
;
505 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
507 if (Tcb
->State
== TCP_CLOSED
) {
511 // The connection is doing RTT measurement.
513 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
519 if (Tcb
->DelayedAck
!= 0) {
524 // No timer is active or no timer expired
526 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
) ||
527 ((--Tcb
->NextExpire
) > 0)) {
533 // Call the timeout handler for each expired timer.
535 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
537 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
538 TCP_TIME_LEQ (Tcb
->Timer
[Index
], mTcpTick
)) {
540 // disable the timer before calling the handler
541 // in case the handler enables it again.
543 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Index
);
544 mTcpTimerHandler
[Index
](Tcb
);
547 // The Tcb may have been deleted by the timer, or
548 // no other timer is set.
550 if ((Next
->BackLink
!= Entry
) ||
551 (Tcb
->EnabledTimer
== 0)) {
558 // If the Tcb still exist or some timer is set, update the timer
560 if (Index
== TCP_TIMER_NUMBER
) {
561 TcpUpdateTimer (Tcb
);
567 Heart beat timer handler, queues the DPC at TPL_CALLBACK.
569 @param Event Timer event signaled, ignored.
570 @param Context Context of the timer event, ignored.
580 QueueDpc (TPL_CALLBACK
, TcpTickingDpc
, Context
);