3 Copyright (c) 2005 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 TCP timer related functions.
25 UINT32 mTcpTick
= 1000;
57 TCP_TIMER_HANDLER mTcpTimerHandler
[TCP_TIMER_NUMBER
] = {
68 Close the TCP connection.
70 @param Tcb Pointer to the TCP_CB of this TCP instance.
80 NetbufFreeList (&Tcb
->SndQue
);
81 NetbufFreeList (&Tcb
->RcvQue
);
83 TcpSetState (Tcb
, TCP_CLOSED
);
88 Connect timeout handler.
90 @param Tcb Pointer to the TCP_CB of this TCP instance.
100 if (!TCP_CONNECTED (Tcb
->State
)) {
101 DEBUG ((EFI_D_ERROR
, "TcpConnectTimeout: connection closed "
102 "because conenction timer timeout for TCB %p\n", Tcb
));
104 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
105 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
108 if (TCP_SYN_RCVD
== Tcb
->State
) {
109 DEBUG ((EFI_D_WARN
, "TcpConnectTimeout: send reset because "
110 "connection timer timeout for TCB %p\n", Tcb
));
112 TcpResetConnection (Tcb
);
122 Timeout handler for TCP retransmission timer.
124 @param Tcb Pointer to the TCP_CB of this TCP instance.
136 DEBUG ((EFI_D_WARN
, "TcpRexmitTimeout: transmission "
137 "timeout for TCB %p\n", Tcb
));
140 // Set the congestion window. FlightSize is the
141 // amount of data that has been sent but not
144 FlightSize
= TCP_SUB_SEQ (Tcb
->SndNxt
, Tcb
->SndUna
);
145 Tcb
->Ssthresh
= MAX ((UINT32
) (2 * Tcb
->SndMss
), FlightSize
/ 2);
147 Tcb
->CWnd
= Tcb
->SndMss
;
148 Tcb
->LossRecover
= Tcb
->SndNxt
;
151 if (Tcb
->LossTimes
> Tcb
->MaxRexmit
&&
152 !TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_CONNECT
)) {
154 DEBUG ((EFI_D_ERROR
, "TcpRexmitTimeout: connection closed "
155 "because too many timeouts for TCB %p\n", Tcb
));
157 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
158 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
166 TcpRetransmit (Tcb
, Tcb
->SndUna
);
167 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
169 Tcb
->CongestState
= TCP_CONGEST_LOSS
;
171 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
176 Timeout handler for window probe timer.
178 @param Tcb Pointer to the TCP_CB of this TCP instance.
189 // This is the timer for sender's SWSA. RFC1122 requires
190 // a timer set for sender's SWSA, and suggest combine it
191 // with window probe timer. If data is sent, don't set
192 // the probe timer, since retransmit timer is on.
194 if ((TcpDataToSend (Tcb
, 1) != 0) && (TcpToSendData (Tcb
, 1) > 0)) {
196 ASSERT (TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
));
200 TcpSendZeroProbe (Tcb
);
201 TcpSetProbeTimer (Tcb
);
206 Timeout handler for keepalive timer.
208 @param Tcb Pointer to the TCP_CB of this TCP instance.
214 TcpKeepaliveTimeout (
218 Tcb
->KeepAliveProbes
++;
221 // Too many Keep-alive probes, drop the connection
223 if (Tcb
->KeepAliveProbes
> Tcb
->MaxKeepAlive
) {
225 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
226 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
233 TcpSendZeroProbe (Tcb
);
234 TcpSetKeepaliveTimer (Tcb
);
239 Timeout handler for FIN_WAIT_2 timer.
241 @param Tcb Pointer to the TCP_CB of this TCP instance.
251 DEBUG ((EFI_D_WARN
, "TcpFinwait2Timeout: connection closed "
252 "because FIN_WAIT2 timer timeouts for TCB %p\n", Tcb
));
259 Timeout handler for 2MSL timer.
261 @param Tcb Pointer to the TCP_CB of this TCP instance.
271 DEBUG ((EFI_D_WARN
, "Tcp2MSLTimeout: connection closed "
272 "because TIME_WAIT timer timeouts for TCB %p\n", Tcb
));
279 Update the timer status and the next expire time
280 according to the timers to expire in a specific
283 @param Tcb Pointer to the TCP_CB of this TCP instance.
296 // Don't use a too large value to init NextExpire
297 // since mTcpTick wraps around as sequence no does.
299 Tcb
->NextExpire
= 65535;
300 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
302 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
304 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
305 TCP_TIME_LT (Tcb
->Timer
[Index
], mTcpTick
+ Tcb
->NextExpire
)) {
307 Tcb
->NextExpire
= TCP_SUB_TIME (Tcb
->Timer
[Index
], mTcpTick
);
308 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
317 @param Tcb Pointer to the TCP_CB of this TCP instance.
318 @param Timer The index of the timer to be enabled.
319 @param TimeOut The timeout value of this timer.
331 TCP_SET_TIMER (Tcb
->EnabledTimer
, Timer
);
332 Tcb
->Timer
[Timer
] = mTcpTick
+ TimeOut
;
334 TcpUpdateTimer (Tcb
);
341 @param Tcb Pointer to the TCP_CB of this TCP instance.
342 @param Timer The index of the timer to be cleared.
353 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Timer
);
354 TcpUpdateTimer (Tcb
);
359 Clear all TCP timers.
361 @param Tcb Pointer to the TCP_CB of this TCP instance.
371 Tcb
->EnabledTimer
= 0;
372 TcpUpdateTimer (Tcb
);
377 Enable the window prober timer and set the timeout value.
379 @param Tcb Pointer to the TCP_CB of this TCP instance.
389 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_PROBE
)) {
390 Tcb
->ProbeTime
= Tcb
->Rto
;
393 Tcb
->ProbeTime
<<= 1;
396 if (Tcb
->ProbeTime
< TCP_RTO_MIN
) {
398 Tcb
->ProbeTime
= TCP_RTO_MIN
;
399 } else if (Tcb
->ProbeTime
> TCP_RTO_MAX
) {
401 Tcb
->ProbeTime
= TCP_RTO_MAX
;
404 TcpSetTimer (Tcb
, TCP_TIMER_PROBE
, Tcb
->ProbeTime
);
409 Enable the keepalive timer and set the timeout value.
411 @param Tcb Pointer to the TCP_CB of this TCP instance.
417 TcpSetKeepaliveTimer (
421 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
)) {
427 // Set the timer to KeepAliveIdle if either
428 // 1. the keepalive timer is off
429 // 2. The keepalive timer is on, but the idle
430 // is less than KeepAliveIdle, that means the
431 // connection is alive since our last probe.
433 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_KEEPALIVE
) ||
434 (Tcb
->Idle
< Tcb
->KeepAliveIdle
)) {
436 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAliveIdle
);
437 Tcb
->KeepAliveProbes
= 0;
441 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAlivePeriod
);
449 @param Tcb Pointer to the TCP_CB of this TCP instance.
460 // Fold the RTT estimate if too many times, the estimate
461 // may be wrong, fold it. So the next time a valid
462 // measurement is sampled, we can start fresh.
464 if ((Tcb
->LossTimes
>= TCP_FOLD_RTT
) && Tcb
->SRtt
) {
465 Tcb
->RttVar
+= Tcb
->SRtt
>> 2;
471 if (Tcb
->Rto
< TCP_RTO_MIN
) {
473 Tcb
->Rto
= TCP_RTO_MIN
;
474 } else if (Tcb
->Rto
> TCP_RTO_MAX
) {
476 Tcb
->Rto
= TCP_RTO_MAX
;
482 Heart beat timer handler.
484 @param Context Context of the timer event, ignored.
501 mTcpGlobalIss
+= 100;
504 // Don't use LIST_FOR_EACH, which isn't delete safe.
506 for (Entry
= mTcpRunQue
.ForwardLink
; Entry
!= &mTcpRunQue
; Entry
= Next
) {
508 Next
= Entry
->ForwardLink
;
510 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
512 if (Tcb
->State
== TCP_CLOSED
) {
516 // The connection is doing RTT measurement.
518 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
524 if (Tcb
->DelayedAck
) {
529 // No timer is active or no timer expired
531 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
) ||
532 ((--Tcb
->NextExpire
) > 0)) {
538 // Call the timeout handler for each expired timer.
540 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
542 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
543 TCP_TIME_LEQ (Tcb
->Timer
[Index
], mTcpTick
)) {
545 // disable the timer before calling the handler
546 // in case the handler enables it again.
548 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Index
);
549 mTcpTimerHandler
[Index
](Tcb
);
552 // The Tcb may have been deleted by the timer, or
553 // no other timer is set.
555 if ((Next
->BackLink
!= Entry
) ||
556 (Tcb
->EnabledTimer
== 0)) {
563 TcpUpdateTimer (Tcb
);
570 Heart beat timer handler, queues the DPC at TPL_CALLBACK.
572 @param Event Timer event signaled, ignored.
573 @param Context Context of the timer event, ignored.
585 NetLibQueueDpc (TPL_CALLBACK
, TcpTickingDpc
, Context
);