1698 |
1698 |
1699 if (CanTriggerKeepAlive()) |
1699 if (CanTriggerKeepAlive()) |
1700 { |
1700 { |
1701 // The heaviest time check only if we are otherwise allowed to send the keepalive. |
1701 // The heaviest time check only if we are otherwise allowed to send the keepalive. |
1702 TUint32 time_now = TimeStamp(); |
1702 TUint32 time_now = TimeStamp(); |
1703 if (time_now - iLastTriggeredKeepAlive > KTcpKeepAliveTH * KOneSecondUs) |
1703 if (time_now - iLastTriggeredKeepAlive > KTcpKeepAliveTH * KOneSecondInMs) |
1704 { |
1704 { |
1705 iLastTriggeredKeepAlive = time_now; |
1705 iLastTriggeredKeepAlive = time_now; |
1706 LOG(Log::Printf(_L("\ttcp SAP[%u] CanSend(): Sending a Keep-Alive probe"), (TInt)this)); |
1706 LOG(Log::Printf(_L("\ttcp SAP[%u] CanSend(): Sending a Keep-Alive probe"), (TInt)this)); |
1707 SendSegment(KTcpCtlACK, iSND.UNA - 1, 0); |
1707 SendSegment(KTcpCtlACK, iSND.UNA - 1, 0); |
1708 } |
1708 } |
2352 TUint32 usec = TimeStamp(); |
2352 TUint32 usec = TimeStamp(); |
2353 |
2353 |
2354 if (!iLastTimeout) |
2354 if (!iLastTimeout) |
2355 iLastTimeout = usec; |
2355 iLastTimeout = usec; |
2356 |
2356 |
2357 TUint32 distance = (usec - iLastTimeout) / KOneSecondUs; // seconds |
2357 TUint32 distance = (usec - iLastTimeout) / KOneSecondInMs; // seconds |
2358 TUint32 interval = iBackoff ? Protocol()->KeepAliveRxmt() : Protocol()->KeepAliveIntv(); |
2358 TUint32 interval = iBackoff ? Protocol()->KeepAliveRxmt() : Protocol()->KeepAliveIntv(); |
2359 |
2359 |
2360 if (distance > interval) |
2360 if (distance > interval) |
2361 { |
2361 { |
2362 // Send a keepalive probe. If no ack arrives, next one is sent after a shorter time (75 s) |
2362 // Send a keepalive probe. If no ack arrives, next one is sent after a shorter time (75 s) |
2363 LOG(Log::Printf(_L("\ttcp SAP[%u] KeepAliveTimeout(): Sending a Keep-Alive probe"), (TInt)this)); |
2363 LOG(Log::Printf(_L("\ttcp SAP[%u] KeepAliveTimeout(): Sending a Keep-Alive probe"), (TInt)this)); |
2364 SendSegment(KTcpCtlACK, iSND.UNA - 1, 0); |
2364 SendSegment(KTcpCtlACK, iSND.UNA - 1, 0); |
2365 iBackoff++; |
2365 iBackoff++; |
2366 iRetransTimer->Restart(Protocol()->KeepAliveRxmt() * KOneSecondUs); |
2366 iRetransTimer->Restart(Protocol()->KeepAliveRxmt() * KOneSecondInUs); |
2367 } |
2367 } |
2368 else |
2368 else |
2369 { |
2369 { |
2370 // This branch is entered when the first keepalive has to be issued after an idle period. |
2370 // This branch is entered when the first keepalive has to be issued after an idle period. |
2371 distance = Protocol()->KeepAliveIntv() - distance; |
2371 distance = Protocol()->KeepAliveIntv() - distance; |
2372 iRetransTimer->Restart((distance > 1800) ? |
2372 iRetransTimer->Restart((distance > 1800) ? |
2373 1800 * KOneSecondUs : (distance * KOneSecondUs)); |
2373 1800 * KOneSecondInUs : (distance * KOneSecondInUs)); |
2374 } |
2374 } |
2375 } |
2375 } |
2376 |
2376 |
2377 |
2377 |
2378 void CProviderTCP6::ResetKeepAlives() |
2378 void CProviderTCP6::ResetKeepAlives() |
2379 { |
2379 { |
2380 ASSERT(iRetransTimer); |
2380 ASSERT(iRetransTimer); |
2381 iRetransTimer->Restart((Protocol()->KeepAliveIntv() > 1800) ? |
2381 iRetransTimer->Restart((Protocol()->KeepAliveIntv() > 1800) ? |
2382 1800 * KOneSecondUs : (Protocol()->KeepAliveIntv() * KOneSecondUs)); |
2382 1800 * KOneSecondInUs : (Protocol()->KeepAliveIntv() * KOneSecondInUs)); |
2383 // Backoff is used for counting unacknowledged keepalive retransmissions during idle periods |
2383 // Backoff is used for counting unacknowledged keepalive retransmissions during idle periods |
2384 iBackoff = 0; |
2384 iBackoff = 0; |
2385 iLastTimeout = TimeStamp(); |
2385 iLastTimeout = TimeStamp(); |
2386 } |
2386 } |
2387 |
2387 |
3589 } |
3589 } |
3590 else if (!iFlags.iSackOk) |
3590 else if (!iFlags.iSackOk) |
3591 { |
3591 { |
3592 // NewReno partial ACK processing. |
3592 // NewReno partial ACK processing. |
3593 |
3593 |
3594 /* From RFC2582: |
3594 /* From RFC2582: |
3595 If this ACK does *not* acknowledge all of the data up to and |
3595 If this ACK does *not* acknowledge all of the data up to and |
3596 including "recover", then this is a partial ACK. In this case, |
3596 including "recover", then this is a partial ACK. In this case, |
3597 retransmit the first unacknowledged segment. Deflate the |
3597 retransmit the first unacknowledged segment. Deflate the |
3598 congestion window by the amount of new data acknowledged, then |
3598 congestion window by the amount of new data acknowledged, then |
3599 add back one MSS and send a new segment if permitted by the new |
3599 add back one MSS and send a new segment if permitted by the new |
3600 value of cwnd. This "partial window deflation" attempts to |
3600 value of cwnd. This "partial window deflation" attempts to |
3601 ensure that, when Fast Recovery eventually ends, approximately |
3601 ensure that, when Fast Recovery eventually ends, approximately |
3602 ssthresh amount of data will be outstanding in the network. Do |
3602 ssthresh amount of data will be outstanding in the network. Do |
3603 not exit the Fast Recovery procedure (i.e., if any duplicate ACKs |
3603 not exit the Fast Recovery procedure (i.e., if any duplicate ACKs |
3604 subsequently arrive, execute Steps 3 and 4 above). |
3604 subsequently arrive, execute Steps 3 and 4 above). |
3605 |
3605 |
3606 For the first partial ACK that arrives during Fast Recovery, also |
3606 For the first partial ACK that arrives during Fast Recovery, also |
3607 reset the retransmit timer. |
3607 reset the retransmit timer. |
3608 */ |
3608 */ |
3609 |
3609 |
3610 iCwnd -= acked; |
3610 iCwnd -= acked; |
3611 iCwnd += iSMSS; |
3611 iCwnd += iSMSS; |
3612 LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): FAST RETRANSMIT on PARTIAL ACK"), (TInt)this)); |
3612 LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): FAST RETRANSMIT on PARTIAL ACK"), (TInt)this)); |
3619 // |
3619 // |
3620 ASSERT(iSMSS); |
3620 ASSERT(iSMSS); |
3621 iDupAcks = Max(iDupAcks - acked / (TInt)iSMSS, 0); |
3621 iDupAcks = Max(iDupAcks - acked / (TInt)iSMSS, 0); |
3622 } |
3622 } |
3623 } |
3623 } |
|
3624 else if ( iDupAcks ) |
|
3625 { |
|
3626 // New data acknowledged, and not ongoing any recovery action |
|
3627 // Reset duplicate ack count |
|
3628 LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): Reset iDupAcks to 0"), (TInt)this)); |
|
3629 iDupAcks = 0; |
|
3630 } |
3624 |
3631 |
3625 // Reset limited transmit window |
3632 // Reset limited transmit window |
3626 iLwnd = 0; |
3633 iLwnd = 0; |
3627 |
3634 |
3628 // Everything acked? |
3635 // Everything acked? |
3794 if (SourceQuench() || iQuenchSeq.Outside(iSND.NXT, iSND.NXT + iSND.WND)) |
3801 if (SourceQuench() || iQuenchSeq.Outside(iSND.NXT, iSND.NXT + iSND.WND)) |
3795 { |
3802 { |
3796 iFlags.iEcnSendCWR = ETrue; |
3803 iFlags.iEcnSendCWR = ETrue; |
3797 } |
3804 } |
3798 } |
3805 } |
3799 if((iSND.NXT - ack) >0 && InState(ETcpEstablished) && (acked ==0)) |
3806 // This section used to hold the RetryACK concept, a reference can be checked |
3800 { |
3807 // from older versions(9.2/9.3). Its being removed as not required. |
3801 iRetryAck++; |
|
3802 if(iRetryAck >=4) // 4 an arbitary number; as this count does not refer to dup_ack, this will not interfere with Fast retransmission |
|
3803 { |
|
3804 LOG(Log::Printf(_L("\ttcp SAP[%u] ProcessSegments(): retransmitting the segment"), (TInt)this)); |
|
3805 SendSegments(ETrue); |
|
3806 iRetryAck = 0; // reset the retry count |
|
3807 } |
|
3808 } |
|
3809 |
3808 |
3810 } |
3809 } |
3811 } |
3810 } |
3812 |
3811 |
3813 // |
3812 // |