diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 904a6175f..517214c91 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -76,6 +76,7 @@ Bugs fixed - Bug 2047 - Ipv6EndPointDemux::Lookup may crash - Bug 2049 - CQI feedback should always use the same calculation method - Bug 2053 - In tcp-socket-base.cc, NotifyDataSent incorrectly called with retransmits +- Bug 2055 - TCP TxBuffer and RxBuffer traces don't work Known issues ------------ diff --git a/src/internet/model/tcp-newreno.cc b/src/internet/model/tcp-newreno.cc index 184dfccb6..a189398b7 100644 --- a/src/internet/model/tcp-newreno.cc +++ b/src/internet/model/tcp-newreno.cc @@ -130,9 +130,9 @@ TcpNewReno::NewAck (const SequenceNumber32& seq) // Check for exit condition of fast recovery if (m_inFastRec && seq < m_recover) { // Partial ACK, partial window deflation (RFC2582 sec.3 bullet #5 paragraph 3) - m_cWnd += m_segmentSize - (seq - m_txBuffer.HeadSequence ()); + m_cWnd += m_segmentSize - (seq - m_txBuffer->HeadSequence ()); NS_LOG_INFO ("Partial ACK for seq " << seq << " in fast recovery: cwnd set to " << m_cWnd); - m_txBuffer.DiscardUpTo(seq); //Bug 1850: retransmit before newack + m_txBuffer->DiscardUpTo(seq); //Bug 1850: retransmit before newack DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet TcpSocketBase::NewAck (seq); // update m_nextTxSequence and send new data if allowed by window return; @@ -184,7 +184,7 @@ TcpNewReno::DupAck (const TcpHeader& t, uint32_t count) NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd); SendPendingData (m_connected); } - else if (!m_inFastRec && m_limitedTx && m_txBuffer.SizeFromSequence (m_nextTxSequence) > 0) + else if (!m_inFastRec && m_limitedTx && m_txBuffer->SizeFromSequence (m_nextTxSequence) > 0) { // RFC3042 Limited transmit: Send a new packet for each duplicated ACK before fast retransmit NS_LOG_INFO ("Limited transmit"); uint32_t sz = SendDataPacket (m_nextTxSequence, m_segmentSize, true); @@ -203,14 +203,14 @@ TcpNewReno::Retransmit (void) // If erroneous timeout in closed/timed-wait state, just return if (m_state == CLOSED || m_state == TIME_WAIT) return; // If all data are received (non-closing socket and nothing to send), just return - if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark) return; + if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark) return; // According to RFC2581 sec.3.1, upon RTO, ssthresh is set to half of flight // size and cwnd is set to 1*MSS, then the lost packet is retransmitted and // TCP back to slow start m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2); m_cWnd = m_segmentSize; - m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack + m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd << ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence); DoRetransmit (); // Retransmit the packet diff --git a/src/internet/model/tcp-reno.cc b/src/internet/model/tcp-reno.cc index 1263a4015..e278e6e83 100644 --- a/src/internet/model/tcp-reno.cc +++ b/src/internet/model/tcp-reno.cc @@ -178,14 +178,14 @@ void TcpReno::Retransmit (void) // If erroneous timeout in closed/timed-wait state, just return if (m_state == CLOSED || m_state == TIME_WAIT) return; // If all data are received (non-closing socket and nothing to send), just return - if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark) return; + if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark) return; // According to RFC2581 sec.3.1, upon RTO, ssthresh is set to half of flight // size and cwnd is set to 1*MSS, then the lost packet is retransmitted and // TCP back to slow start m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2); m_cWnd = m_segmentSize; - m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack + m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd << ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence); DoRetransmit (); // Retransmit the packet diff --git a/src/internet/model/tcp-socket-base.cc b/src/internet/model/tcp-socket-base.cc index afc58053c..f31398cb5 100644 --- a/src/internet/model/tcp-socket-base.cc +++ b/src/internet/model/tcp-socket-base.cc @@ -39,6 +39,7 @@ #include "ns3/packet.h" #include "ns3/uinteger.h" #include "ns3/double.h" +#include "ns3/pointer.h" #include "ns3/trace-source-accessor.h" #include "tcp-socket-base.h" #include "tcp-l4-protocol.h" @@ -106,6 +107,16 @@ TcpSocketBase::GetTypeId (void) MakeTimeAccessor (&TcpSocketBase::SetClockGranularity, &TcpSocketBase::GetClockGranularity), MakeTimeChecker ()) + .AddAttribute ("TxBuffer", + "TCP Tx buffer", + PointerValue (), + MakePointerAccessor (&TcpSocketBase::GetTxBuffer), + MakePointerChecker ()) + .AddAttribute ("RxBuffer", + "TCP Rx buffer", + PointerValue (), + MakePointerAccessor (&TcpSocketBase::GetRxBuffer), + MakePointerChecker ()) .AddTraceSource ("RTO", "Retransmission timeout", MakeTraceSourceAccessor (&TcpSocketBase::m_rto), @@ -164,6 +175,8 @@ TcpSocketBase::TcpSocketBase (void) { NS_LOG_FUNCTION (this); + m_rxBuffer = CreateObject (); + m_txBuffer = CreateObject (); } TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock) @@ -184,8 +197,6 @@ TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock) m_rtt (0), m_nextTxSequence (sock.m_nextTxSequence), m_highTxMark (sock.m_highTxMark), - m_rxBuffer (sock.m_rxBuffer), - m_txBuffer (sock.m_txBuffer), m_state (sock.m_state), m_errno (sock.m_errno), m_closeNotified (sock.m_closeNotified), @@ -219,6 +230,8 @@ TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock) SetDataSentCallback (vPSUI); SetSendCallback (vPSUI); SetRecvCallback (vPS); + m_txBuffer = CopyObject (sock.m_txBuffer); + m_rxBuffer = CopyObject (sock.m_rxBuffer); } TcpSocketBase::~TcpSocketBase (void) @@ -501,14 +514,14 @@ TcpSocketBase::Close (void) /// \internal /// First we check to see if there is any unread rx data. /// \bugid{426} claims we should send reset in this case. - if (m_rxBuffer.Size () != 0) + if (m_rxBuffer->Size () != 0) { NS_LOG_INFO ("Socket " << this << " << unread rx data during close. Sending reset"); SendRST (); return 0; } - if (m_txBuffer.SizeFromSequence (m_nextTxSequence) > 0) + if (m_txBuffer->SizeFromSequence (m_nextTxSequence) > 0) { // App close with pending data must wait until all data transmitted if (m_closeOnEmpty == false) { @@ -531,7 +544,7 @@ TcpSocketBase::ShutdownSend (void) m_closeOnEmpty = true; //if buffer is already empty, send a fin now //otherwise fin will go when buffer empties. - if (m_txBuffer.Size () == 0) + if (m_txBuffer->Size () == 0) { if (m_state == ESTABLISHED || m_state == CLOSE_WAIT) { @@ -573,7 +586,7 @@ TcpSocketBase::Send (Ptr p, uint32_t flags) if (m_state == ESTABLISHED || m_state == SYN_SENT || m_state == CLOSE_WAIT) { // Store the packet into Tx buffer - if (!m_txBuffer.Add (p)) + if (!m_txBuffer->Add (p)) { // TxBuffer overflow, send failed m_errno = ERROR_MSGSIZE; return -1; @@ -584,7 +597,7 @@ TcpSocketBase::Send (Ptr p, uint32_t flags) return -1; } // Submit the data to lower layers - NS_LOG_LOGIC ("txBufSize=" << m_txBuffer.Size () << " state " << TcpStateName[m_state]); + NS_LOG_LOGIC ("txBufSize=" << m_txBuffer->Size () << " state " << TcpStateName[m_state]); if (m_state == ESTABLISHED || m_state == CLOSE_WAIT) { // Try to send the data out SendPendingData (m_connected); @@ -612,11 +625,11 @@ TcpSocketBase::Recv (uint32_t maxSize, uint32_t flags) { NS_LOG_FUNCTION (this); NS_ABORT_MSG_IF (flags, "use of flags is not supported in TcpSocketBase::Recv()"); - if (m_rxBuffer.Size () == 0 && m_state == CLOSE_WAIT) + if (m_rxBuffer->Size () == 0 && m_state == CLOSE_WAIT) { return Create (); // Send EOF on connection close } - Ptr outPacket = m_rxBuffer.Extract (maxSize); + Ptr outPacket = m_rxBuffer->Extract (maxSize); if (outPacket != 0 && outPacket->GetSize () != 0) { SocketAddressTag tag; @@ -663,7 +676,7 @@ uint32_t TcpSocketBase::GetTxAvailable (void) const { NS_LOG_FUNCTION (this); - return m_txBuffer.Available (); + return m_txBuffer->Available (); } /* Inherit from Socket class: Get the max number of bytes an app can read */ @@ -671,7 +684,7 @@ uint32_t TcpSocketBase::GetRxAvailable (void) const { NS_LOG_FUNCTION (this); - return m_rxBuffer.Available (); + return m_rxBuffer->Available (); } /* Inherit from Socket class: Return local address:port */ @@ -847,12 +860,12 @@ TcpSocketBase::OutOfRange (SequenceNumber32 head, SequenceNumber32 tail) const } if (m_state == LAST_ACK || m_state == CLOSING || m_state == CLOSE_WAIT) { // In LAST_ACK and CLOSING states, it only wait for an ACK and the - // sequence number must equals to m_rxBuffer.NextRxSequence () - return (m_rxBuffer.NextRxSequence () != head); + // sequence number must equals to m_rxBuffer->NextRxSequence () + return (m_rxBuffer->NextRxSequence () != head); } // In all other cases, check if the sequence number is in range - return (tail < m_rxBuffer.NextRxSequence () || m_rxBuffer.MaxRxSequence () <= head); + return (tail < m_rxBuffer->NextRxSequence () || m_rxBuffer->MaxRxSequence () <= head); } /* Function called by the L3 protocol when it received a packet to pass on to @@ -944,8 +957,8 @@ TcpSocketBase::DoForwardUp (Ptr packet, Ipv4Header header, uint16_t port NS_LOG_LOGIC ("At state " << TcpStateName[m_state] << " received packet of seq [" << tcpHeader.GetSequenceNumber () << ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () << - ") out of range [" << m_rxBuffer.NextRxSequence () << ":" << - m_rxBuffer.MaxRxSequence () << ")"); + ") out of range [" << m_rxBuffer->NextRxSequence () << ":" << + m_rxBuffer->MaxRxSequence () << ")"); // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69) if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST)) { @@ -974,7 +987,7 @@ TcpSocketBase::DoForwardUp (Ptr packet, Ipv4Header header, uint16_t port TcpHeader h; h.SetFlags (TcpHeader::RST); h.SetSequenceNumber (m_nextTxSequence); - h.SetAckNumber (m_rxBuffer.NextRxSequence ()); + h.SetAckNumber (m_rxBuffer->NextRxSequence ()); h.SetSourcePort (tcpHeader.GetDestinationPort ()); h.SetDestinationPort (tcpHeader.GetSourcePort ()); h.SetWindowSize (AdvertisedWindowSize ()); @@ -1048,8 +1061,8 @@ TcpSocketBase::DoForwardUp (Ptr packet, Ipv6Header header, uint16_t port NS_LOG_LOGIC ("At state " << TcpStateName[m_state] << " received packet of seq [" << tcpHeader.GetSequenceNumber () << ":" << tcpHeader.GetSequenceNumber () + packet->GetSize () << - ") out of range [" << m_rxBuffer.NextRxSequence () << ":" << - m_rxBuffer.MaxRxSequence () << ")"); + ") out of range [" << m_rxBuffer->NextRxSequence () << ":" << + m_rxBuffer->MaxRxSequence () << ")"); // Acknowledgement should be sent for all unacceptable packets (RFC793, p.69) if (m_state == ESTABLISHED && !(tcpHeader.GetFlags () & TcpHeader::RST)) { @@ -1078,7 +1091,7 @@ TcpSocketBase::DoForwardUp (Ptr packet, Ipv6Header header, uint16_t port TcpHeader h; h.SetFlags (TcpHeader::RST); h.SetSequenceNumber (m_nextTxSequence); - h.SetAckNumber (m_rxBuffer.NextRxSequence ()); + h.SetAckNumber (m_rxBuffer->NextRxSequence ()); h.SetSourcePort (tcpHeader.GetDestinationPort ()); h.SetDestinationPort (tcpHeader.GetSourcePort ()); h.SetWindowSize (AdvertisedWindowSize ()); @@ -1138,7 +1151,7 @@ TcpSocketBase::ProcessEstablished (Ptr packet, const TcpHeader& tcpHeade else if (tcpflags == 0) { // No flags means there is only data ReceivedData (packet, tcpHeader); - if (m_rxBuffer.Finished ()) + if (m_rxBuffer->Finished ()) { PeerClose (packet, tcpHeader); } @@ -1164,11 +1177,11 @@ TcpSocketBase::ReceivedAck (Ptr packet, const TcpHeader& tcpHeader) if (0 == (tcpHeader.GetFlags () & TcpHeader::ACK)) { // Ignore if no ACK flag } - else if (tcpHeader.GetAckNumber () < m_txBuffer.HeadSequence ()) + else if (tcpHeader.GetAckNumber () < m_txBuffer->HeadSequence ()) { // Case 1: Old ACK, ignored. NS_LOG_LOGIC ("Ignored ack of " << tcpHeader.GetAckNumber ()); } - else if (tcpHeader.GetAckNumber () == m_txBuffer.HeadSequence ()) + else if (tcpHeader.GetAckNumber () == m_txBuffer->HeadSequence ()) { // Case 2: Potentially a duplicated ACK if (tcpHeader.GetAckNumber () < m_nextTxSequence && packet->GetSize() == 0) { @@ -1178,7 +1191,7 @@ TcpSocketBase::ReceivedAck (Ptr packet, const TcpHeader& tcpHeader) // otherwise, the ACK is precisely equal to the nextTxSequence NS_ASSERT (tcpHeader.GetAckNumber () <= m_nextTxSequence); } - else if (tcpHeader.GetAckNumber () > m_txBuffer.HeadSequence ()) + else if (tcpHeader.GetAckNumber () > m_txBuffer->HeadSequence ()) { // Case 3: New ACK, reset m_dupAckCount and update m_txBuffer NS_LOG_LOGIC ("New ack of " << tcpHeader.GetAckNumber ()); NewAck (tcpHeader.GetAckNumber ()); @@ -1248,7 +1261,7 @@ TcpSocketBase::ProcessSynSent (Ptr packet, const TcpHeader& tcpHeader) NS_LOG_INFO ("SYN_SENT -> SYN_RCVD"); m_state = SYN_RCVD; m_cnCount = m_cnRetries; - m_rxBuffer.SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); + m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); } else if (tcpflags == (TcpHeader::SYN | TcpHeader::ACK) @@ -1258,9 +1271,9 @@ TcpSocketBase::ProcessSynSent (Ptr packet, const TcpHeader& tcpHeader) m_state = ESTABLISHED; m_connected = true; m_retxEvent.Cancel (); - m_rxBuffer.SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); + m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); m_highTxMark = ++m_nextTxSequence; - m_txBuffer.SetHeadSequence (m_nextTxSequence); + m_txBuffer->SetHeadSequence (m_nextTxSequence); SendEmptyPacket (TcpHeader::ACK); SendPendingData (m_connected); Simulator::ScheduleNow (&TcpSocketBase::ConnectionSucceeded, this); @@ -1300,7 +1313,7 @@ TcpSocketBase::ProcessSynRcvd (Ptr packet, const TcpHeader& tcpHeader, m_connected = true; m_retxEvent.Cancel (); m_highTxMark = ++m_nextTxSequence; - m_txBuffer.SetHeadSequence (m_nextTxSequence); + m_txBuffer->SetHeadSequence (m_nextTxSequence); if (m_endPoint) { m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (), @@ -1324,17 +1337,17 @@ TcpSocketBase::ProcessSynRcvd (Ptr packet, const TcpHeader& tcpHeader, } else if (tcpflags == TcpHeader::SYN) { // Probably the peer lost my SYN+ACK - m_rxBuffer.SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); + m_rxBuffer->SetNextRxSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (1)); SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); } else if (tcpflags == (TcpHeader::FIN | TcpHeader::ACK)) { - if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSequence ()) + if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ()) { // In-sequence FIN before connection complete. Set up connection and close. m_connected = true; m_retxEvent.Cancel (); m_highTxMark = ++m_nextTxSequence; - m_txBuffer.SetHeadSequence (m_nextTxSequence); + m_txBuffer->SetHeadSequence (m_nextTxSequence); if (m_endPoint) { m_endPoint->SetPeer (InetSocketAddress::ConvertFrom (fromAddress).GetIpv4 (), @@ -1385,7 +1398,7 @@ TcpSocketBase::ProcessWait (Ptr packet, const TcpHeader& tcpHeader) else if (tcpflags == TcpHeader::ACK) { // Process the ACK, and if in FIN_WAIT_1, conditionally move to FIN_WAIT_2 ReceivedAck (packet, tcpHeader); - if (m_state == FIN_WAIT_1 && m_txBuffer.Size () == 0 + if (m_state == FIN_WAIT_1 && m_txBuffer->Size () == 0 && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1)) { // This ACK corresponds to the FIN sent NS_LOG_INFO ("FIN_WAIT_1 -> FIN_WAIT_2"); @@ -1398,7 +1411,7 @@ TcpSocketBase::ProcessWait (Ptr packet, const TcpHeader& tcpHeader) { // Process the ACK first ReceivedAck (packet, tcpHeader); } - m_rxBuffer.SetFinSequence (tcpHeader.GetSequenceNumber ()); + m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber ()); } else if (tcpflags == TcpHeader::SYN || tcpflags == (TcpHeader::SYN | TcpHeader::ACK)) { // Duplicated SYN or SYN+ACK, possibly due to spurious retransmission @@ -1416,13 +1429,13 @@ TcpSocketBase::ProcessWait (Ptr packet, const TcpHeader& tcpHeader) } // Check if the close responder sent an in-sequence FIN, if so, respond ACK - if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer.Finished ()) + if ((m_state == FIN_WAIT_1 || m_state == FIN_WAIT_2) && m_rxBuffer->Finished ()) { if (m_state == FIN_WAIT_1) { NS_LOG_INFO ("FIN_WAIT_1 -> CLOSING"); m_state = CLOSING; - if (m_txBuffer.Size () == 0 + if (m_txBuffer->Size () == 0 && tcpHeader.GetAckNumber () == m_highTxMark + SequenceNumber32 (1)) { // This ACK corresponds to the FIN sent TimeWait (); @@ -1451,7 +1464,7 @@ TcpSocketBase::ProcessClosing (Ptr packet, const TcpHeader& tcpHeader) if (tcpflags == TcpHeader::ACK) { - if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSequence ()) + if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ()) { // This ACK corresponds to the FIN sent TimeWait (); } @@ -1487,7 +1500,7 @@ TcpSocketBase::ProcessLastAck (Ptr packet, const TcpHeader& tcpHeader) } else if (tcpflags == TcpHeader::ACK) { - if (tcpHeader.GetSequenceNumber () == m_rxBuffer.NextRxSequence ()) + if (tcpHeader.GetSequenceNumber () == m_rxBuffer->NextRxSequence ()) { // This ACK corresponds to the FIN sent. This socket closed peacefully. CloseAndNotify (); } @@ -1515,13 +1528,13 @@ TcpSocketBase::PeerClose (Ptr p, const TcpHeader& tcpHeader) NS_LOG_FUNCTION (this << tcpHeader); // Ignore all out of range packets - if (tcpHeader.GetSequenceNumber () < m_rxBuffer.NextRxSequence () - || tcpHeader.GetSequenceNumber () > m_rxBuffer.MaxRxSequence ()) + if (tcpHeader.GetSequenceNumber () < m_rxBuffer->NextRxSequence () + || tcpHeader.GetSequenceNumber () > m_rxBuffer->MaxRxSequence ()) { return; } // For any case, remember the FIN position in rx buffer first - m_rxBuffer.SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ())); + m_rxBuffer->SetFinSequence (tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ())); NS_LOG_LOGIC ("Accepted FIN at seq " << tcpHeader.GetSequenceNumber () + SequenceNumber32 (p->GetSize ())); // If there is any piggybacked data, process it if (p->GetSize ()) @@ -1529,7 +1542,7 @@ TcpSocketBase::PeerClose (Ptr p, const TcpHeader& tcpHeader) ReceivedData (p, tcpHeader); } // Return if FIN is out of sequence, otherwise move to CLOSE_WAIT state by DoPeerClose - if (!m_rxBuffer.Finished ()) + if (!m_rxBuffer->Finished ()) { return; } @@ -1684,7 +1697,7 @@ TcpSocketBase::SendEmptyPacket (uint8_t flags) header.SetFlags (flags); header.SetSequenceNumber (s); - header.SetAckNumber (m_rxBuffer.NextRxSequence ()); + header.SetAckNumber (m_rxBuffer->NextRxSequence ()); if (m_endPoint != 0) { header.SetSourcePort (m_endPoint->GetLocalPort ()); @@ -1879,7 +1892,7 @@ TcpSocketBase::CompleteFork (Ptr p, const TcpHeader& h, m_cnCount = m_cnRetries; SetupCallback (); // Set the sequence number and send SYN+ACK - m_rxBuffer.SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1)); + m_rxBuffer->SetNextRxSequence (h.GetSequenceNumber () + SequenceNumber32 (1)); SendEmptyPacket (TcpHeader::SYN | TcpHeader::ACK); } @@ -1906,15 +1919,15 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with NS_LOG_FUNCTION (this << seq << maxSize << withAck); bool isRetransmission = false; - if ( seq == m_txBuffer.HeadSequence () ) + if ( seq == m_txBuffer->HeadSequence () ) { isRetransmission = true; } - Ptr p = m_txBuffer.CopyFromSequence (maxSize, seq); + Ptr p = m_txBuffer->CopyFromSequence (maxSize, seq); uint32_t sz = p->GetSize (); // Size of packet uint8_t flags = withAck ? TcpHeader::ACK : 0; - uint32_t remainingData = m_txBuffer.SizeFromSequence (seq + SequenceNumber32 (sz)); + uint32_t remainingData = m_txBuffer->SizeFromSequence (seq + SequenceNumber32 (sz)); /* * Add tags for each socket option. @@ -1967,7 +1980,7 @@ TcpSocketBase::SendDataPacket (SequenceNumber32 seq, uint32_t maxSize, bool with TcpHeader header; header.SetFlags (flags); header.SetSequenceNumber (seq); - header.SetAckNumber (m_rxBuffer.NextRxSequence ()); + header.SetAckNumber (m_rxBuffer->NextRxSequence ()); if (m_endPoint) { header.SetSourcePort (m_endPoint->GetLocalPort ()); @@ -2041,7 +2054,7 @@ bool TcpSocketBase::SendPendingData (bool withAck) { NS_LOG_FUNCTION (this << withAck); - if (m_txBuffer.Size () == 0) + if (m_txBuffer->Size () == 0) { return false; // Nothing to send @@ -2052,7 +2065,7 @@ TcpSocketBase::SendPendingData (bool withAck) return false; // Is this the right way to handle this condition? } uint32_t nPacketsSent = 0; - while (m_txBuffer.SizeFromSequence (m_nextTxSequence)) + while (m_txBuffer->SizeFromSequence (m_nextTxSequence)) { uint32_t w = AvailableWindow (); // Get available window size NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" << @@ -2060,18 +2073,18 @@ TcpSocketBase::SendPendingData (bool withAck) " rxwin " << m_rWnd << " segsize " << m_segmentSize << " nextTxSeq " << m_nextTxSequence << - " highestRxAck " << m_txBuffer.HeadSequence () << - " pd->Size " << m_txBuffer.Size () << - " pd->SFS " << m_txBuffer.SizeFromSequence (m_nextTxSequence)); + " highestRxAck " << m_txBuffer->HeadSequence () << + " pd->Size " << m_txBuffer->Size () << + " pd->SFS " << m_txBuffer->SizeFromSequence (m_nextTxSequence)); // Stop sending if we need to wait for a larger Tx window (prevent silly window syndrome) - if (w < m_segmentSize && m_txBuffer.SizeFromSequence (m_nextTxSequence) > w) + if (w < m_segmentSize && m_txBuffer->SizeFromSequence (m_nextTxSequence) > w) { break; // No more } // Nagle's algorithm (RFC896): Hold off sending if there is unacked data // in the buffer and the amount of data to send is less than one segment if (!m_noDelay && UnAckDataCount () > 0 - && m_txBuffer.SizeFromSequence (m_nextTxSequence) < m_segmentSize) + && m_txBuffer->SizeFromSequence (m_nextTxSequence) < m_segmentSize) { NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send."); break; @@ -2089,14 +2102,14 @@ uint32_t TcpSocketBase::UnAckDataCount () { NS_LOG_FUNCTION (this); - return m_nextTxSequence.Get () - m_txBuffer.HeadSequence (); + return m_nextTxSequence.Get () - m_txBuffer->HeadSequence (); } uint32_t TcpSocketBase::BytesInFlight () { NS_LOG_FUNCTION (this); - return m_highTxMark.Get () - m_txBuffer.HeadSequence (); + return m_highTxMark.Get () - m_txBuffer->HeadSequence (); } uint32_t @@ -2119,7 +2132,7 @@ TcpSocketBase::AvailableWindow () uint16_t TcpSocketBase::AdvertisedWindowSize () { - uint32_t w = m_rxBuffer.MaxBufferSize () - m_rxBuffer.Size (); + uint32_t w = m_rxBuffer->MaxBufferSize () - m_rxBuffer->Size (); w >>= m_sndScaleFactor; @@ -2142,14 +2155,14 @@ TcpSocketBase::ReceivedData (Ptr p, const TcpHeader& tcpHeader) " pkt size " << p->GetSize () ); // Put into Rx buffer - SequenceNumber32 expectedSeq = m_rxBuffer.NextRxSequence (); - if (!m_rxBuffer.Add (p, tcpHeader)) + SequenceNumber32 expectedSeq = m_rxBuffer->NextRxSequence (); + if (!m_rxBuffer->Add (p, tcpHeader)) { // Insert failed: No data or RX buffer full SendEmptyPacket (TcpHeader::ACK); return; } // Now send a new ACK packet acknowledging all received and delivered data - if (m_rxBuffer.Size () > m_rxBuffer.Available () || m_rxBuffer.NextRxSequence () > expectedSeq + p->GetSize ()) + if (m_rxBuffer->Size () > m_rxBuffer->Available () || m_rxBuffer->NextRxSequence () > expectedSeq + p->GetSize ()) { // A gap exists in the buffer, or we filled a gap: Always ACK SendEmptyPacket (TcpHeader::ACK); } @@ -2169,7 +2182,7 @@ TcpSocketBase::ReceivedData (Ptr p, const TcpHeader& tcpHeader) } } // Notify app to receive if necessary - if (expectedSeq < m_rxBuffer.NextRxSequence ()) + if (expectedSeq < m_rxBuffer->NextRxSequence ()) { // NextRxSeq advanced, we have something to send to the app if (!m_shutdownRecv) { @@ -2182,7 +2195,7 @@ TcpSocketBase::ReceivedData (Ptr p, const TcpHeader& tcpHeader) } // If we received FIN before and now completed all "holes" in rx buffer, // invoke peer close procedure - if (m_rxBuffer.Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0) + if (m_rxBuffer->Finished () && (tcpHeader.GetFlags () & TcpHeader::FIN) == 0) { DoPeerClose (); } @@ -2277,8 +2290,8 @@ TcpSocketBase::NewAck (SequenceNumber32 const& ack) } // Note the highest ACK and tell app to send more NS_LOG_LOGIC ("TCP " << this << " NewAck " << ack << - " numberAck " << (ack - m_txBuffer.HeadSequence ())); // Number bytes ack'ed - m_txBuffer.DiscardUpTo (ack); + " numberAck " << (ack - m_txBuffer->HeadSequence ())); // Number bytes ack'ed + m_txBuffer->DiscardUpTo (ack); if (GetTxAvailable () > 0) { NotifySend (GetTxAvailable ()); @@ -2287,7 +2300,7 @@ TcpSocketBase::NewAck (SequenceNumber32 const& ack) { m_nextTxSequence = ack; // If advanced } - if (m_txBuffer.Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING) + if (m_txBuffer->Size () == 0 && m_state != FIN_WAIT_1 && m_state != CLOSING) { // No retransmit timer if no data to retransmit NS_LOG_LOGIC (this << " Cancelled ReTxTimeout event which was set to expire at " << (Simulator::Now () + Simulator::GetDelayLeft (m_retxEvent)).GetSeconds ()); @@ -2309,7 +2322,7 @@ TcpSocketBase::ReTxTimeout () return; } // If all data are received (non-closing socket and nothing to send), just return - if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark) + if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark) { return; } @@ -2348,10 +2361,10 @@ TcpSocketBase::PersistTimeout () { NS_LOG_LOGIC ("PersistTimeout expired at " << Simulator::Now ().GetSeconds ()); m_persistTimeout = std::min (Seconds (60), Time (2 * m_persistTimeout)); // max persist timeout = 60s - Ptr p = m_txBuffer.CopyFromSequence (1, m_nextTxSequence); + Ptr p = m_txBuffer->CopyFromSequence (1, m_nextTxSequence); TcpHeader tcpHeader; tcpHeader.SetSequenceNumber (m_nextTxSequence); - tcpHeader.SetAckNumber (m_rxBuffer.NextRxSequence ()); + tcpHeader.SetAckNumber (m_rxBuffer->NextRxSequence ()); tcpHeader.SetWindowSize (AdvertisedWindowSize ()); if (m_endPoint != 0) { @@ -2384,7 +2397,7 @@ TcpSocketBase::PersistTimeout () void TcpSocketBase::Retransmit () { - m_nextTxSequence = m_txBuffer.HeadSequence (); // Start from highest Ack + m_nextTxSequence = m_txBuffer->HeadSequence (); // Start from highest Ack m_dupAckCount = 0; DoRetransmit (); // Retransmit the packet } @@ -2407,7 +2420,7 @@ TcpSocketBase::DoRetransmit () return; } // Retransmit non-data packet: Only if in FIN_WAIT_1 or CLOSING state - if (m_txBuffer.Size () == 0) + if (m_txBuffer->Size () == 0) { if (m_state == FIN_WAIT_1 || m_state == CLOSING) { // Must have lost FIN, re-send @@ -2416,10 +2429,10 @@ TcpSocketBase::DoRetransmit () return; } // Retransmit a data packet: Call SendDataPacket - NS_LOG_LOGIC ("TcpSocketBase " << this << " retxing seq " << m_txBuffer.HeadSequence ()); - uint32_t sz = SendDataPacket (m_txBuffer.HeadSequence (), m_segmentSize, true); + NS_LOG_LOGIC ("TcpSocketBase " << this << " retxing seq " << m_txBuffer->HeadSequence ()); + uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_segmentSize, true); // In case of RTO, advance m_nextTxSequence - m_nextTxSequence = std::max (m_nextTxSequence.Get (), m_txBuffer.HeadSequence () + sz); + m_nextTxSequence = std::max (m_nextTxSequence.Get (), m_txBuffer->HeadSequence () + sz); } @@ -2451,25 +2464,25 @@ TcpSocketBase::TimeWait () void TcpSocketBase::SetSndBufSize (uint32_t size) { - m_txBuffer.SetMaxBufferSize (size); + m_txBuffer->SetMaxBufferSize (size); } uint32_t TcpSocketBase::GetSndBufSize (void) const { - return m_txBuffer.MaxBufferSize (); + return m_txBuffer->MaxBufferSize (); } void TcpSocketBase::SetRcvBufSize (uint32_t size) { - m_rxBuffer.SetMaxBufferSize (size); + m_rxBuffer->SetMaxBufferSize (size); } uint32_t TcpSocketBase::GetRcvBufSize (void) const { - return m_rxBuffer.MaxBufferSize (); + return m_rxBuffer->MaxBufferSize (); } void @@ -2640,7 +2653,7 @@ uint8_t TcpSocketBase::CalculateWScale () const { NS_LOG_FUNCTION (this); - uint32_t maxSpace = m_rxBuffer.MaxBufferSize (); + uint32_t maxSpace = m_rxBuffer->MaxBufferSize (); uint8_t scale = 0; while (maxSpace > m_maxWinSize) @@ -2656,7 +2669,7 @@ TcpSocketBase::CalculateWScale () const } NS_LOG_INFO ("Node " << m_node->GetId () << " calculated wscale factor of " << - static_cast (scale) << " for buffer size " << m_rxBuffer.MaxBufferSize ()); + static_cast (scale) << " for buffer size " << m_rxBuffer->MaxBufferSize ()); return scale; } @@ -2733,6 +2746,19 @@ TcpSocketBase::GetClockGranularity (void) const return m_clockGranularity; } +Ptr +TcpSocketBase::GetTxBuffer (void) const +{ + return m_txBuffer; +} + +Ptr +TcpSocketBase::GetRxBuffer (void) const +{ + return m_rxBuffer; +} + + //RttHistory methods RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t) : seq (s), count (c), time (t), retx (false) diff --git a/src/internet/model/tcp-socket-base.h b/src/internet/model/tcp-socket-base.h index d2ab1e43b..bcc8c2c09 100644 --- a/src/internet/model/tcp-socket-base.h +++ b/src/internet/model/tcp-socket-base.h @@ -154,6 +154,18 @@ public: */ Time GetClockGranularity (void) const; + /** + * \brief Get a pointer to the Tx buffer + * \return a pointer to the tx buffer + */ + Ptr GetTxBuffer (void) const; + + /** + * \brief Get a pointer to the Rx buffer + * \return a pointer to the rx buffer + */ + Ptr GetRxBuffer (void) const; + // Necessary implementations of null functions from ns3::Socket virtual enum SocketErrno GetErrno (void) const; // returns m_errno @@ -699,8 +711,8 @@ protected: // Rx and Tx buffer management TracedValue m_nextTxSequence; //!< Next seqnum to be sent (SND.NXT), ReTx pushes it back TracedValue m_highTxMark; //!< Highest seqno ever sent, regardless of ReTx - TcpRxBuffer m_rxBuffer; //!< Rx buffer (reordering buffer) - TcpTxBuffer m_txBuffer; //!< Tx buffer + Ptr m_rxBuffer; //!< Rx buffer (reordering buffer) + Ptr m_txBuffer; //!< Tx buffer // State-related attributes TracedValue m_state; //!< TCP state diff --git a/src/internet/model/tcp-tahoe.cc b/src/internet/model/tcp-tahoe.cc index 9144a9dde..4ec83e02e 100644 --- a/src/internet/model/tcp-tahoe.cc +++ b/src/internet/model/tcp-tahoe.cc @@ -146,7 +146,7 @@ TcpTahoe::DupAck (const TcpHeader& t, uint32_t count) // (Fall & Floyd 1996, sec.1) m_ssThresh = std::max (static_cast (m_cWnd / 2), m_segmentSize * 2); // Half ssthresh m_cWnd = m_segmentSize; // Run slow start again - m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack + m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack NS_LOG_INFO ("Triple Dup Ack: new ssthresh " << m_ssThresh << " cwnd " << m_cWnd); NS_LOG_LOGIC ("Triple Dup Ack: retransmit missing segment at " << Simulator::Now ().GetSeconds ()); DoRetransmit (); @@ -161,11 +161,11 @@ void TcpTahoe::Retransmit (void) // If erroneous timeout in closed/timed-wait state, just return if (m_state == CLOSED || m_state == TIME_WAIT) return; // If all data are received (non-closing socket and nothing to send), just return - if (m_state <= ESTABLISHED && m_txBuffer.HeadSequence () >= m_highTxMark) return; + if (m_state <= ESTABLISHED && m_txBuffer->HeadSequence () >= m_highTxMark) return; m_ssThresh = std::max (static_cast (m_cWnd / 2), m_segmentSize * 2); // Half ssthresh m_cWnd = m_segmentSize; // Set cwnd to 1 segSize (RFC2001, sec.2) - m_nextTxSequence = m_txBuffer.HeadSequence (); // Restart from highest Ack + m_nextTxSequence = m_txBuffer->HeadSequence (); // Restart from highest Ack DoRetransmit (); // Retransmit the packet } diff --git a/src/internet/model/tcp-westwood.cc b/src/internet/model/tcp-westwood.cc index 8d6848be1..44090c175 100644 --- a/src/internet/model/tcp-westwood.cc +++ b/src/internet/model/tcp-westwood.cc @@ -307,7 +307,7 @@ TcpWestwood::Retransmit (void) if (m_state == CLOSED || m_state == TIME_WAIT) return; // If all data are received, just return - if (m_txBuffer.HeadSequence () >= m_nextTxSequence) + if (m_txBuffer->HeadSequence () >= m_nextTxSequence) return; // Upon an RTO, adjust cwnd and ssthresh based on the estimated BW @@ -315,7 +315,7 @@ TcpWestwood::Retransmit (void) m_cWnd = m_segmentSize; // Restart from highest ACK - m_nextTxSequence = m_txBuffer.HeadSequence (); + m_nextTxSequence = m_txBuffer->HeadSequence (); NS_LOG_INFO ("RTO. Reset cwnd to " << m_cWnd << ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence); diff --git a/src/internet/test/tcp-wscaling-test.cc b/src/internet/test/tcp-wscaling-test.cc index 3ed99ee82..d4fc38129 100644 --- a/src/internet/test/tcp-wscaling-test.cc +++ b/src/internet/test/tcp-wscaling-test.cc @@ -385,8 +385,8 @@ WScalingTestCase::SetupDefaultSim (void) break; } - m_server->m_rxBuffer.SetMaxBufferSize (m_maxServerBufferSize); - m_source->m_rxBuffer.SetMaxBufferSize (m_maxSourceBufferSize); + m_server->m_rxBuffer->SetMaxBufferSize (m_maxServerBufferSize); + m_source->m_rxBuffer->SetMaxBufferSize (m_maxSourceBufferSize); uint16_t port = 50000; InetSocketAddress serverlocaladdr (Ipv4Address::GetAny (), port);