TianoCore EDK2 master
Loading...
Searching...
No Matches
TcpTimer.c
Go to the documentation of this file.
1
10#include "TcpMain.h"
11
12UINT32 mTcpTick = 1000;
13
20VOID
22 IN OUT TCP_CB *Tcb
23 );
24
31VOID
33 IN OUT TCP_CB *Tcb
34 );
35
42VOID
44 IN OUT TCP_CB *Tcb
45 );
46
53VOID
55 IN OUT TCP_CB *Tcb
56 );
57
64VOID
66 IN OUT TCP_CB *Tcb
67 );
68
75VOID
77 IN OUT TCP_CB *Tcb
78 );
79
80TCP_TIMER_HANDLER mTcpTimerHandler[TCP_TIMER_NUMBER] = {
87};
88
95VOID
97 IN OUT TCP_CB *Tcb
98 )
99{
100 NetbufFreeList (&Tcb->SndQue);
101 NetbufFreeList (&Tcb->RcvQue);
102
103 TcpSetState (Tcb, TCP_CLOSED);
104}
105
112VOID
114 IN OUT TCP_CB *Tcb
115 )
116{
117 //
118 // Fold the RTT estimate if too many times, the estimate
119 // may be wrong, fold it. So the next time a valid
120 // measurement is sampled, we can start fresh.
121 //
122 if ((Tcb->LossTimes >= TCP_FOLD_RTT) && (Tcb->SRtt != 0)) {
123 Tcb->RttVar += Tcb->SRtt >> 2;
124 Tcb->SRtt = 0;
125 }
126
127 Tcb->Rto <<= 1;
128
129 if (Tcb->Rto < TCP_RTO_MIN) {
130 Tcb->Rto = TCP_RTO_MIN;
131 } else if (Tcb->Rto > TCP_RTO_MAX) {
132 Tcb->Rto = TCP_RTO_MAX;
133 }
134}
135
142VOID
144 IN OUT TCP_CB *Tcb
145 )
146{
147 if (!TCP_CONNECTED (Tcb->State)) {
148 DEBUG (
149 (DEBUG_ERROR,
150 "TcpConnectTimeout: connection closed because connection timer timeout for TCB %p\n",
151 Tcb)
152 );
153
154 if (EFI_ABORTED == Tcb->Sk->SockError) {
155 SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
156 }
157
158 if (TCP_SYN_RCVD == Tcb->State) {
159 DEBUG (
160 (DEBUG_WARN,
161 "TcpConnectTimeout: send reset because connection timer timeout for TCB %p\n",
162 Tcb)
163 );
164
165 TcpResetConnection (Tcb);
166 }
167
168 TcpClose (Tcb);
169 }
170}
171
178VOID
180 IN OUT TCP_CB *Tcb
181 )
182{
183 UINT32 FlightSize;
184
185 DEBUG (
186 (DEBUG_WARN,
187 "TcpRexmitTimeout: transmission timeout for TCB %p\n",
188 Tcb)
189 );
190
191 //
192 // Set the congestion window. FlightSize is the
193 // amount of data that has been sent but not
194 // yet ACKed.
195 //
196 FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
197 Tcb->Ssthresh = MAX ((UINT32)(2 * Tcb->SndMss), FlightSize / 2);
198
199 Tcb->CWnd = Tcb->SndMss;
200 Tcb->LossRecover = Tcb->SndNxt;
201
202 Tcb->LossTimes++;
203 if ((Tcb->LossTimes > Tcb->MaxRexmit) && !TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_CONNECT)) {
204 DEBUG (
205 (DEBUG_ERROR,
206 "TcpRexmitTimeout: connection closed because too many timeouts for TCB %p\n",
207 Tcb)
208 );
209
210 if (EFI_ABORTED == Tcb->Sk->SockError) {
211 SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
212 }
213
214 TcpClose (Tcb);
215 return;
216 }
217
218 TcpBackoffRto (Tcb);
219 TcpRetransmit (Tcb, Tcb->SndUna);
220 TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
221
222 Tcb->CongestState = TCP_CONGEST_LOSS;
223
224 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
225}
226
233VOID
235 IN OUT TCP_CB *Tcb
236 )
237{
238 //
239 // This is the timer for sender's SWSA. RFC1122 requires
240 // a timer set for sender's SWSA, and suggest combine it
241 // with window probe timer. If data is sent, don't set
242 // the probe timer, since retransmit timer is on.
243 //
244 if ((TcpDataToSend (Tcb, 1) != 0) && (TcpToSendData (Tcb, 1) > 0)) {
245 ASSERT (TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT) != 0);
246 Tcb->ProbeTimerOn = FALSE;
247 return;
248 }
249
250 TcpSendZeroProbe (Tcb);
251 TcpSetProbeTimer (Tcb);
252}
253
260VOID
262 IN OUT TCP_CB *Tcb
263 )
264{
265 Tcb->KeepAliveProbes++;
266
267 //
268 // Too many Keep-alive probes, drop the connection
269 //
270 if (Tcb->KeepAliveProbes > Tcb->MaxKeepAlive) {
271 if (EFI_ABORTED == Tcb->Sk->SockError) {
272 SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
273 }
274
275 TcpClose (Tcb);
276 return;
277 }
278
279 TcpSendZeroProbe (Tcb);
281}
282
289VOID
291 IN OUT TCP_CB *Tcb
292 )
293{
294 DEBUG (
295 (DEBUG_WARN,
296 "TcpFinwait2Timeout: connection closed because FIN_WAIT2 timer timeouts for TCB %p\n",
297 Tcb)
298 );
299
300 TcpClose (Tcb);
301}
302
309VOID
311 IN OUT TCP_CB *Tcb
312 )
313{
314 DEBUG (
315 (DEBUG_WARN,
316 "Tcp2MSLTimeout: connection closed because TIME_WAIT timer timeouts for TCB %p\n",
317 Tcb)
318 );
319
320 TcpClose (Tcb);
321}
322
330VOID
332 IN OUT TCP_CB *Tcb
333 )
334{
335 UINT16 Index;
336
337 //
338 // Don't use a too large value to init NextExpire
339 // since mTcpTick wraps around as sequence no does.
340 //
341 Tcb->NextExpire = TCP_EXPIRE_TIME;
342 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
343
344 for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
345 if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
346 TCP_TIME_LT (Tcb->Timer[Index], mTcpTick + Tcb->NextExpire)
347 )
348 {
349 Tcb->NextExpire = TCP_SUB_TIME (Tcb->Timer[Index], mTcpTick);
350 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
351 }
352 }
353}
354
363VOID
365 IN OUT TCP_CB *Tcb,
366 IN UINT16 Timer,
367 IN UINT32 TimeOut
368 )
369{
370 TCP_SET_TIMER (Tcb->EnabledTimer, Timer);
371 Tcb->Timer[Timer] = mTcpTick + TimeOut;
372
373 TcpUpdateTimer (Tcb);
374}
375
383VOID
385 IN OUT TCP_CB *Tcb,
386 IN UINT16 Timer
387 )
388{
389 TCP_CLEAR_TIMER (Tcb->EnabledTimer, Timer);
390 TcpUpdateTimer (Tcb);
391}
392
399VOID
401 IN OUT TCP_CB *Tcb
402 )
403{
404 Tcb->EnabledTimer = 0;
405 TcpUpdateTimer (Tcb);
406}
407
414VOID
416 IN OUT TCP_CB *Tcb
417 )
418{
419 if (!Tcb->ProbeTimerOn) {
420 Tcb->ProbeTime = Tcb->Rto;
421 Tcb->ProbeTimerOn = TRUE;
422 } else {
423 Tcb->ProbeTime <<= 1;
424 }
425
426 if (Tcb->ProbeTime < TCP_RTO_MIN) {
427 Tcb->ProbeTime = TCP_RTO_MIN;
428 } else if (Tcb->ProbeTime > TCP_RTO_MAX) {
429 Tcb->ProbeTime = TCP_RTO_MAX;
430 }
431
432 TcpSetTimer (Tcb, TCP_TIMER_PROBE, Tcb->ProbeTime);
433}
434
441VOID
443 IN OUT TCP_CB *Tcb
444 )
445{
446 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE)) {
447 return;
448 }
449
450 //
451 // Set the timer to KeepAliveIdle if either
452 // 1. the keepalive timer is off
453 // 2. The keepalive timer is on, but the idle
454 // is less than KeepAliveIdle, that means the
455 // connection is alive since our last probe.
456 //
457 if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_KEEPALIVE) ||
458 (Tcb->Idle < Tcb->KeepAliveIdle)
459 )
460 {
461 TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAliveIdle);
462 Tcb->KeepAliveProbes = 0;
463 } else {
464 TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAlivePeriod);
465 }
466}
467
474VOID
475EFIAPI
477 IN VOID *Context
478 )
479{
480 LIST_ENTRY *Entry;
481 LIST_ENTRY *Next;
482 TCP_CB *Tcb;
483 INT16 Index;
484
485 mTcpTick++;
486
487 //
488 // Don't use LIST_FOR_EACH, which isn't delete safe.
489 //
490 for (Entry = mTcpRunQue.ForwardLink; Entry != &mTcpRunQue; Entry = Next) {
491 Next = Entry->ForwardLink;
492
493 Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
494
495 if (Tcb->State == TCP_CLOSED) {
496 continue;
497 }
498
499 //
500 // The connection is doing RTT measurement.
501 //
502 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
503 Tcb->RttMeasure++;
504 }
505
506 Tcb->Idle++;
507
508 if (Tcb->DelayedAck != 0) {
509 TcpSendAck (Tcb);
510 }
511
512 if ((Tcb->IpInfo->IpVersion == IP_VERSION_6) && (Tcb->Tick > 0)) {
513 Tcb->Tick--;
514 }
515
516 //
517 // No timer is active or no timer expired
518 //
519 if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON) || ((--Tcb->NextExpire) > 0)) {
520 continue;
521 }
522
523 //
524 // Call the timeout handler for each expired timer.
525 //
526 for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
527 if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) && TCP_TIME_LEQ (Tcb->Timer[Index], mTcpTick)) {
528 //
529 // disable the timer before calling the handler
530 // in case the handler enables it again.
531 //
532 TCP_CLEAR_TIMER (Tcb->EnabledTimer, Index);
533 mTcpTimerHandler[Index](Tcb);
534
535 //
536 // The Tcb may have been deleted by the timer, or
537 // no other timer is set.
538 //
539 if ((Next->BackLink != Entry) || (Tcb->EnabledTimer == 0)) {
540 break;
541 }
542 }
543 }
544
545 //
546 // If the Tcb still exist or some timer is set, update the timer
547 //
548 if (Index == TCP_TIMER_NUMBER) {
549 TcpUpdateTimer (Tcb);
550 }
551 }
552}
553
561VOID
562EFIAPI
564 IN EFI_EVENT Event,
565 IN VOID *Context
566 )
567{
568 QueueDpc (TPL_CALLBACK, TcpTickingDpc, Context);
569}
EFI_STATUS EFIAPI QueueDpc(IN EFI_TPL DpcTpl, IN EFI_DPC_PROCEDURE DpcProcedure, IN VOID *DpcContext OPTIONAL)
Definition: DpcLib.c:62
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define MAX(a, b)
Definition: Base.h:992
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID EFIAPI NetbufFreeList(IN OUT LIST_ENTRY *Head)
Definition: NetBuffer.c:319
#define SOCK_ERROR(Sock, Error)
Definition: Socket.h:312
INTN TcpRetransmit(IN TCP_CB *Tcb, IN TCP_SEQNO Seq)
Definition: TcpOutput.c:632
INTN TcpToSendData(IN OUT TCP_CB *Tcb, IN INTN Force)
Definition: TcpOutput.c:776
VOID TcpSetState(IN TCP_CB *Tcb, IN UINT8 State)
Definition: TcpMisc.c:801
VOID(* TCP_TIMER_HANDLER)(IN OUT TCP_CB *Tcb)
Definition: TcpFunc.h:26
VOID TcpResetConnection(IN TCP_CB *Tcb)
Definition: TcpMisc.c:1130
INTN TcpSendZeroProbe(IN OUT TCP_CB *Tcb)
Definition: TcpOutput.c:1005
VOID TcpSendAck(IN OUT TCP_CB *Tcb)
Definition: TcpOutput.c:967
UINT32 TcpDataToSend(IN TCP_CB *Tcb, IN INTN Force)
Definition: TcpOutput.c:166
#define TCP_CTRL_NO_KEEPALIVE
Disable keepalive timer.
Definition: TcpProto.h:59
#define TCP_TIMER_PROBE
Window probe timer.
Definition: TcpProto.h:79
#define TCP_CTRL_TIMER_ON
At least one of the timer is on.
Definition: TcpProto.h:70
#define TCP_TIMER_CONNECT
Connection establishment timer.
Definition: TcpProto.h:77
#define TCP_CONNECTED(state)
Definition: TcpProto.h:129
#define TCP_RTO_MIN
The minimum value of RTO.
Definition: TcpProto.h:87
#define TCP_TIMER_KEEPALIVE
Keepalive timer.
Definition: TcpProto.h:80
#define TCP_RTO_MAX
The maximum value of RTO.
Definition: TcpProto.h:88
#define TCP_TIMER_REXMIT
Retransmit timer.
Definition: TcpProto.h:78
#define TCP_TIMER_NUMBER
The total number of the TCP timer.
Definition: TcpProto.h:83
#define TCP_CLOSED
Definition: TcpProto.h:17
#define TCP_CTRL_RTT_ON
The RTT measurement is on.
Definition: TcpProto.h:71
#define TCP_FOLD_RTT
Timeout threshold to fold RTT.
Definition: TcpProto.h:89
#define TCP_CONGEST_LOSS
Retxmit because of retxmit time out.
Definition: TcpProto.h:52
VOID EFIAPI TcpTickingDpc(IN VOID *Context)
Definition: TcpTimer.c:476
VOID EFIAPI TcpTicking(IN EFI_EVENT Event, IN VOID *Context)
Definition: TcpTimer.c:563
VOID TcpClose(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:96
VOID TcpProbeTimeout(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:234
VOID TcpBackoffRto(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:113
VOID TcpClearTimer(IN OUT TCP_CB *Tcb, IN UINT16 Timer)
Definition: TcpTimer.c:384
VOID TcpSetProbeTimer(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:415
VOID TcpSetTimer(IN OUT TCP_CB *Tcb, IN UINT16 Timer, IN UINT32 TimeOut)
Definition: TcpTimer.c:364
VOID TcpRexmitTimeout(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:179
VOID Tcp2MSLTimeout(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:310
VOID TcpConnectTimeout(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:143
VOID TcpUpdateTimer(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:331
VOID TcpKeepaliveTimeout(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:261
VOID TcpClearAllTimer(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:400
VOID TcpFinwait2Timeout(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:290
VOID TcpSetKeepaliveTimer(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:442
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINT32 Tick
1 tick = 200ms
Definition: TcpProto.h:337
UINT32 RttMeasure
Currently measured RTT in heartbeats.
Definition: TcpProto.h:292
UINT8 DelayedAck
Number of delayed ACKs.
Definition: TcpProto.h:249
INT32 NextExpire
Countdown offset for the nearest timer.
Definition: TcpProto.h:274
UINT32 Timer[TCP_TIMER_NUMBER]
When the timer will expire.
Definition: TcpProto.h:273
UINT16 EnabledTimer
Which timer is currently enabled.
Definition: TcpProto.h:272
UINT32 Idle
How long the connection is in idle.
Definition: TcpProto.h:275
UINT8 State
TCP state, such as SYN_SENT, LISTEN.
Definition: TcpProto.h:248
IP_IO_IP_INFO * IpInfo
Pointer reference to Ip used to send pkt.
Definition: TcpProto.h:336
UINT32 CtrlFlag
Control flags, such as NO_NAGLE.
Definition: TcpProto.h:242