|
|
| 1196 |
// Initialize cWnd and ssThresh |
1196 |
// Initialize cWnd and ssThresh |
| 1197 |
m_tcb->m_cWnd = GetInitialCwnd () * GetSegSize (); |
1197 |
m_tcb->m_cWnd = GetInitialCwnd () * GetSegSize (); |
| 1198 |
m_tcb->m_ssThresh = GetInitialSSThresh (); |
1198 |
m_tcb->m_ssThresh = GetInitialSSThresh (); |
|
|
1199 |
|
| 1200 |
//Also estimate the RTT for SYN/ACK |
| 1201 |
if(tcpHeader.GetFlags () & TcpHeader::ACK) |
| 1202 |
{ |
| 1203 |
EstimateRtt (tcpHeader); |
| 1204 |
} |
| 1199 |
} |
1205 |
} |
| 1200 |
else if (tcpHeader.GetFlags () & TcpHeader::ACK) |
1206 |
else if (tcpHeader.GetFlags () & TcpHeader::ACK) |
| 1201 |
{ |
1207 |
{ |
|
|
| 1419 |
{ |
1425 |
{ |
| 1420 |
// RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit |
1426 |
// RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit |
| 1421 |
NS_LOG_INFO ("Limited transmit"); |
1427 |
NS_LOG_INFO ("Limited transmit"); |
| 1422 |
uint32_t sz = SendDataPacket (m_nextTxSequence, m_tcb->m_segmentSize, true); |
1428 |
uint32_t sz = SendDataPacket (m_nextTxSequence, m_tcb->m_segmentSize, true, false); |
| 1423 |
m_nextTxSequence += sz; |
1429 |
m_nextTxSequence += sz; |
| 1424 |
} |
1430 |
} |
| 1425 |
|
1431 |
|
|
|
| 1452 |
{ |
1458 |
{ |
| 1453 |
// RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit |
1459 |
// RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit |
| 1454 |
NS_LOG_INFO ("Limited transmit"); |
1460 |
NS_LOG_INFO ("Limited transmit"); |
| 1455 |
uint32_t sz = SendDataPacket (m_nextTxSequence, m_tcb->m_segmentSize, true); |
1461 |
uint32_t sz = SendDataPacket (m_nextTxSequence, m_tcb->m_segmentSize, true, false); |
| 1456 |
m_nextTxSequence += sz; |
1462 |
m_nextTxSequence += sz; |
| 1457 |
} |
1463 |
} |
| 1458 |
} |
1464 |
} |
|
|
| 2056 |
|
2062 |
|
| 2057 |
/* Send an empty packet with specified TCP flags */ |
2063 |
/* Send an empty packet with specified TCP flags */ |
| 2058 |
void |
2064 |
void |
| 2059 |
TcpSocketBase::SendEmptyPacket (uint8_t flags) |
2065 |
TcpSocketBase::SendEmptyPacket (uint8_t flags, bool isRetransmission) |
| 2060 |
{ |
2066 |
{ |
| 2061 |
NS_LOG_FUNCTION (this << (uint32_t)flags); |
2067 |
NS_LOG_FUNCTION (this << (uint32_t)flags); |
| 2062 |
Ptr<Packet> p = Create<Packet> (); |
2068 |
Ptr<Packet> p = Create<Packet> (); |
|
|
| 2161 |
} |
2167 |
} |
| 2162 |
|
2168 |
|
| 2163 |
m_txTrace (p, header, this); |
2169 |
m_txTrace (p, header, this); |
|
|
2170 |
|
| 2171 |
if(hasSyn) |
| 2172 |
{ |
| 2173 |
UpdateRTTHistory(s, 0, isRetransmission); |
| 2174 |
} |
| 2164 |
|
2175 |
|
| 2165 |
if (flags & TcpHeader::ACK) |
2176 |
if (flags & TcpHeader::ACK) |
| 2166 |
{ // If sending an ACK, cancel the delay ACK as well |
2177 |
{ // If sending an ACK, cancel the delay ACK as well |
|
|
| 2176 |
NS_LOG_LOGIC ("Schedule retransmission timeout at time " |
2187 |
NS_LOG_LOGIC ("Schedule retransmission timeout at time " |
| 2177 |
<< Simulator::Now ().GetSeconds () << " to expire at time " |
2188 |
<< Simulator::Now ().GetSeconds () << " to expire at time " |
| 2178 |
<< (Simulator::Now () + m_rto.Get ()).GetSeconds ()); |
2189 |
<< (Simulator::Now () + m_rto.Get ()).GetSeconds ()); |
| 2179 |
m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::SendEmptyPacket, this, flags); |
2190 |
m_retxEvent = Simulator::Schedule (m_rto, &TcpSocketBase::SendEmptyPacket, this, flags, true); |
| 2180 |
} |
2191 |
} |
| 2181 |
} |
2192 |
} |
| 2182 |
|
2193 |
|
|
|
| 2328 |
/* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the |
2339 |
/* Extract at most maxSize bytes from the TxBuffer at sequence seq, add the |
| 2329 |
TCP header, and send to TcpL4Protocol */ |
2340 |
TCP header, and send to TcpL4Protocol */ |
| 2330 |
uint32_t |
2341 |
uint32_t |
| 2331 |
TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck) |
2342 |
TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool withAck, bool isRetransmission) |
| 2332 |
{ |
2343 |
{ |
| 2333 |
NS_LOG_FUNCTION (this << seq << maxSize << withAck); |
2344 |
NS_LOG_FUNCTION (this << seq << maxSize << withAck); |
| 2334 |
|
2345 |
|
| 2335 |
bool isRetransmission = false; |
|
|
| 2336 |
if ( seq == m_txBuffer->HeadSequence () ) |
| 2337 |
{ |
| 2338 |
isRetransmission = true; |
| 2339 |
} |
| 2340 |
|
| 2341 |
Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq); |
2346 |
Ptr<Packet> p = m_txBuffer->CopyFromSequence (maxSize, seq); |
| 2342 |
uint32_t sz = p->GetSize (); // Size of packet |
2347 |
uint32_t sz = p->GetSize (); // Size of packet |
| 2343 |
uint8_t flags = withAck ? TcpHeader::ACK : 0; |
2348 |
uint8_t flags = withAck ? TcpHeader::ACK : 0; |
|
|
| 2458 |
m_txTrace (p, header, this); |
2464 |
m_txTrace (p, header, this); |
| 2459 |
|
2465 |
|
| 2460 |
// update the history of sequence numbers used to calculate the RTT |
2466 |
// update the history of sequence numbers used to calculate the RTT |
| 2461 |
if (isRetransmission == false) |
2467 |
UpdateRTTHistory(seq, sz, isRetransmission); |
| 2462 |
{ // This is the next expected one, just log at end |
|
|
| 2463 |
m_history.push_back (RttHistory (seq, sz, Simulator::Now () )); |
| 2464 |
} |
| 2465 |
else |
| 2466 |
{ // This is a retransmit, find in list and mark as re-tx |
| 2467 |
for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i) |
| 2468 |
{ |
| 2469 |
if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count)))) |
| 2470 |
{ // Found it |
| 2471 |
i->retx = true; |
| 2472 |
i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist |
| 2473 |
break; |
| 2474 |
} |
| 2475 |
} |
| 2476 |
} |
| 2477 |
|
2468 |
|
| 2478 |
// Notify the application of the data being sent unless this is a retransmit |
2469 |
// Notify the application of the data being sent unless this is a retransmit |
| 2479 |
if (seq + sz > m_highTxMark) |
2470 |
if (seq + sz > m_highTxMark) |
|
|
| 2533 |
" unAck: " << UnAckDataCount ()); |
2524 |
" unAck: " << UnAckDataCount ()); |
| 2534 |
|
2525 |
|
| 2535 |
uint32_t s = std::min (w, m_tcb->m_segmentSize); // Send no more than window |
2526 |
uint32_t s = std::min (w, m_tcb->m_segmentSize); // Send no more than window |
| 2536 |
uint32_t sz = SendDataPacket (m_nextTxSequence, s, withAck); |
2527 |
uint32_t sz = SendDataPacket (m_nextTxSequence, s, withAck, false); |
| 2537 |
nPacketsSent++; // Count sent this loop |
2528 |
nPacketsSent++; // Count sent this loop |
| 2538 |
m_nextTxSequence += sz; // Advance next tx sequence |
2529 |
m_nextTxSequence += sz; // Advance next tx sequence |
| 2539 |
} |
2530 |
} |
|
|
| 2650 |
} |
2641 |
} |
| 2651 |
|
2642 |
|
| 2652 |
/** |
2643 |
/** |
|
|
2644 |
* \brief Update the RTT history, when we send TCP segments |
| 2645 |
* \param seq The sequence number of the TCP segment |
| 2646 |
* \param sz The segment's size |
| 2647 |
* \param isRetransmission Whether or not the segment is a retransmission |
| 2648 |
*/ |
| 2649 |
|
| 2650 |
void |
| 2651 |
TcpSocketBase::UpdateRTTHistory (SequenceNumber32 seq, uint32_t sz, bool isRetransmission) |
| 2652 |
{ |
| 2653 |
// update the history of sequence numbers used to calculate the RTT |
| 2654 |
if (isRetransmission == false) |
| 2655 |
{ // This is the next expected one, just log at end |
| 2656 |
m_history.push_back (RttHistory (seq, sz, Simulator::Now () )); |
| 2657 |
} |
| 2658 |
else |
| 2659 |
{ // This is a retransmit, find in list and mark as re-tx |
| 2660 |
for (RttHistory_t::iterator i = m_history.begin (); i != m_history.end (); ++i) |
| 2661 |
{ |
| 2662 |
if ((seq >= i->seq) && (seq < (i->seq + SequenceNumber32 (i->count)))) |
| 2663 |
{ // Found it |
| 2664 |
i->retx = true; |
| 2665 |
i->count = ((seq + SequenceNumber32 (sz)) - i->seq); // And update count in hist |
| 2666 |
break; |
| 2667 |
} |
| 2668 |
} |
| 2669 |
} |
| 2670 |
} |
| 2671 |
|
| 2672 |
/** |
| 2653 |
* \brief Estimate the RTT |
2673 |
* \brief Estimate the RTT |
| 2654 |
* |
2674 |
* |
| 2655 |
* Called by ForwardUp() to estimate RTT. |
2675 |
* Called by ForwardUp() to estimate RTT. |
|
|
| 2907 |
{ |
2927 |
{ |
| 2908 |
if (m_synCount > 0) |
2928 |
if (m_synCount > 0) |
| 2909 |
{ |
2929 |
{ |
| 2910 |
SendEmptyPacket (TcpHeader::SYN); |
2930 |
SendEmptyPacket (TcpHeader::SYN, true); |
| 2911 |
} |
2931 |
} |
| 2912 |
else |
2932 |
else |
| 2913 |
{ |
2933 |
{ |
|
|
| 2933 |
{ |
2953 |
{ |
| 2934 |
if (m_state == FIN_WAIT_1 || m_state == CLOSING) |
2954 |
if (m_state == FIN_WAIT_1 || m_state == CLOSING) |
| 2935 |
{ // Must have lost FIN, re-send |
2955 |
{ // Must have lost FIN, re-send |
| 2936 |
SendEmptyPacket (TcpHeader::FIN); |
2956 |
SendEmptyPacket (TcpHeader::FIN, true); |
| 2937 |
} |
2957 |
} |
| 2938 |
return; |
2958 |
return; |
| 2939 |
} |
2959 |
} |
| 2940 |
|
2960 |
|
| 2941 |
// Retransmit a data packet: Call SendDataPacket |
2961 |
// Retransmit a data packet: Call SendDataPacket |
| 2942 |
uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_tcb->m_segmentSize, true); |
2962 |
uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_tcb->m_segmentSize, true, true); |
| 2943 |
// In case of RTO, advance m_nextTxSequence |
2963 |
// In case of RTO, advance m_nextTxSequence |
| 2944 |
m_nextTxSequence = std::max (m_nextTxSequence.Get (), m_txBuffer->HeadSequence () + sz); |
2964 |
m_nextTxSequence = std::max (m_nextTxSequence.Get (), m_txBuffer->HeadSequence () + sz); |
| 2945 |
|
2965 |
|