3 Copyright (c) 2005 - 2006, 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;
63 TCP_TIMER_HANDLER mTcpTimerHandler
[TCP_TIMER_NUMBER
] = {
74 Close the TCP connection.
76 @param Tcb Pointer to the TCP_CB of this TCP instance.
86 NetbufFreeList (&Tcb
->SndQue
);
87 NetbufFreeList (&Tcb
->RcvQue
);
89 TcpSetState (Tcb
, TCP_CLOSED
);
94 Connect timeout handler.
96 @param Tcb Pointer to the TCP_CB of this TCP instance.
107 if (!TCP_CONNECTED (Tcb
->State
)) {
108 TCP4_DEBUG_ERROR (("TcpConnectTimeout: connection closed "
109 "because conenction timer timeout for TCB %x\n", Tcb
));
111 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
112 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
115 if (TCP_SYN_RCVD
== Tcb
->State
) {
116 TCP4_DEBUG_WARN (("TcpConnectTimeout: send reset because "
117 "connection timer timeout for TCB %x\n", Tcb
));
119 TcpResetConnection (Tcb
);
129 Timeout handler for TCP retransmission timer.
131 @param Tcb Pointer to the TCP_CB of this TCP instance.
144 TCP4_DEBUG_WARN (("TcpRexmitTimeout: transmission "
145 "timeout for TCB %x\n", Tcb
));
148 // Set the congestion window. FlightSize is the
149 // amount of data that has been sent but not
152 FlightSize
= TCP_SUB_SEQ (Tcb
->SndNxt
, Tcb
->SndUna
);
153 Tcb
->Ssthresh
= NET_MAX ((UINT32
) (2 * Tcb
->SndMss
), FlightSize
/ 2);
155 Tcb
->CWnd
= Tcb
->SndMss
;
156 Tcb
->LossRecover
= Tcb
->SndNxt
;
159 if (Tcb
->LossTimes
> Tcb
->MaxRexmit
&&
160 !TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_CONNECT
)) {
162 TCP4_DEBUG_ERROR (("TcpRexmitTimeout: connection closed "
163 "because too many timeouts for TCB %x\n", Tcb
));
165 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
166 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
174 TcpRetransmit (Tcb
, Tcb
->SndUna
);
175 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
177 Tcb
->CongestState
= TCP_CONGEST_LOSS
;
179 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
184 Timeout handler for window probe timer.
186 @param Tcb Pointer to the TCP_CB of this TCP instance.
198 // This is the timer for sender's SWSA. RFC1122 requires
199 // a timer set for sender's SWSA, and suggest combine it
200 // with window probe timer. If data is sent, don't set
201 // the probe timer, since retransmit timer is on.
203 if ((TcpDataToSend (Tcb
, 1) != 0) && (TcpToSendData (Tcb
, 1) > 0)) {
205 ASSERT (TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
));
209 TcpSendZeroProbe (Tcb
);
210 TcpSetProbeTimer (Tcb
);
215 Timeout handler for keepalive timer.
217 @param Tcb Pointer to the TCP_CB of this TCP instance.
224 TcpKeepaliveTimeout (
228 Tcb
->KeepAliveProbes
++;
231 // Too many Keep-alive probes, drop the connection
233 if (Tcb
->KeepAliveProbes
> Tcb
->MaxKeepAlive
) {
235 if (EFI_ABORTED
== Tcb
->Sk
->SockError
) {
236 SOCK_ERROR (Tcb
->Sk
, EFI_TIMEOUT
);
243 TcpSendZeroProbe (Tcb
);
244 TcpSetKeepaliveTimer (Tcb
);
249 Timeout handler for FIN_WAIT_2 timer.
251 @param Tcb Pointer to the TCP_CB of this TCP instance.
262 TCP4_DEBUG_WARN (("TcpFinwait2Timeout: connection closed "
263 "because FIN_WAIT2 timer timeouts for TCB %x\n", Tcb
));
270 Timeout handler for 2MSL timer.
272 @param Tcb Pointer to the TCP_CB of this TCP instance.
283 TCP4_DEBUG_WARN (("Tcp2MSLTimeout: connection closed "
284 "because TIME_WAIT timer timeouts for TCB %x\n", Tcb
));
291 Update the timer status and the next expire time
292 according to the timers to expire in a specific
295 @param Tcb Pointer to the TCP_CB of this TCP instance.
309 // Don't use a too large value to init NextExpire
310 // since mTcpTick wraps around as sequence no does.
312 Tcb
->NextExpire
= 65535;
313 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
315 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
317 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
318 TCP_TIME_LT (Tcb
->Timer
[Index
], mTcpTick
+ Tcb
->NextExpire
)) {
320 Tcb
->NextExpire
= TCP_SUB_TIME (Tcb
->Timer
[Index
], mTcpTick
);
321 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
);
330 @param Tcb Pointer to the TCP_CB of this TCP instance.
331 @param Timer The index of the timer to be enabled.
332 @param TimeOut The timeout value of this timer.
344 TCP_SET_TIMER (Tcb
->EnabledTimer
, Timer
);
345 Tcb
->Timer
[Timer
] = mTcpTick
+ TimeOut
;
347 TcpUpdateTimer (Tcb
);
354 @param Tcb Pointer to the TCP_CB of this TCP instance.
355 @param Timer The index of the timer to be cleared.
366 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Timer
);
367 TcpUpdateTimer (Tcb
);
372 Clear all TCP timers.
374 @param Tcb Pointer to the TCP_CB of this TCP instance.
384 Tcb
->EnabledTimer
= 0;
385 TcpUpdateTimer (Tcb
);
390 Enable the window prober timer and set the timeout value.
392 @param Tcb Pointer to the TCP_CB of this TCP instance.
402 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_PROBE
)) {
403 Tcb
->ProbeTime
= Tcb
->Rto
;
406 Tcb
->ProbeTime
<<= 1;
409 if (Tcb
->ProbeTime
< TCP_RTO_MIN
) {
411 Tcb
->ProbeTime
= TCP_RTO_MIN
;
412 } else if (Tcb
->ProbeTime
> TCP_RTO_MAX
) {
414 Tcb
->ProbeTime
= TCP_RTO_MAX
;
417 TcpSetTimer (Tcb
, TCP_TIMER_PROBE
, Tcb
->ProbeTime
);
422 Enable the keepalive timer and set the timeout value.
424 @param Tcb Pointer to the TCP_CB of this TCP instance.
430 TcpSetKeepaliveTimer (
434 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_KEEPALIVE
)) {
440 // Set the timer to KeepAliveIdle if either
441 // 1. the keepalive timer is off
442 // 2. The keepalive timer is on, but the idle
443 // is less than KeepAliveIdle, that means the
444 // connection is alive since our last probe.
446 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_KEEPALIVE
) ||
447 (Tcb
->Idle
< Tcb
->KeepAliveIdle
)) {
449 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAliveIdle
);
450 Tcb
->KeepAliveProbes
= 0;
454 TcpSetTimer (Tcb
, TCP_TIMER_KEEPALIVE
, Tcb
->KeepAlivePeriod
);
462 @param Tcb Pointer to the TCP_CB of this TCP instance.
473 // Fold the RTT estimate if too many times, the estimate
474 // may be wrong, fold it. So the next time a valid
475 // measurement is sampled, we can start fresh.
477 if ((Tcb
->LossTimes
>= TCP_FOLD_RTT
) && Tcb
->SRtt
) {
478 Tcb
->RttVar
+= Tcb
->SRtt
>> 2;
484 if (Tcb
->Rto
< TCP_RTO_MIN
) {
486 Tcb
->Rto
= TCP_RTO_MIN
;
487 } else if (Tcb
->Rto
> TCP_RTO_MAX
) {
489 Tcb
->Rto
= TCP_RTO_MAX
;
495 Heart beat timer handler.
497 @param Event Timer event signaled, ignored.
498 @param Context Context of the timer event, ignored.
510 NET_LIST_ENTRY
*Entry
;
511 NET_LIST_ENTRY
*Next
;
516 mTcpGlobalIss
+= 100;
519 // Don't use LIST_FOR_EACH, which isn't delete safe.
521 for (Entry
= mTcpRunQue
.ForwardLink
; Entry
!= &mTcpRunQue
; Entry
= Next
) {
523 Next
= Entry
->ForwardLink
;
525 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
527 if (Tcb
->State
== TCP_CLOSED
) {
531 // The connection is doing RTT measurement.
533 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
539 if (Tcb
->DelayedAck
) {
544 // No timer is active or no timer expired
546 if (!TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_TIMER_ON
) ||
547 ((--Tcb
->NextExpire
) > 0)) {
553 // Call the timeout handler for each expired timer.
555 for (Index
= 0; Index
< TCP_TIMER_NUMBER
; Index
++) {
557 if (TCP_TIMER_ON (Tcb
->EnabledTimer
, Index
) &&
558 TCP_TIME_LEQ (Tcb
->Timer
[Index
], mTcpTick
)) {
560 // disable the timer before calling the handler
561 // in case the handler enables it again.
563 TCP_CLEAR_TIMER (Tcb
->EnabledTimer
, Index
);
564 mTcpTimerHandler
[Index
](Tcb
);
567 // The Tcb may have been deleted by the timer, or
568 // no other timer is set.
570 if ((Next
->BackLink
!= Entry
) ||
571 (Tcb
->EnabledTimer
== 0)) {
578 TcpUpdateTimer (Tcb
);