Bug 2055 - TxBuffer and RxBuffer traces don't work

This commit is contained in:
Tommaso Pecorella
2015-01-31 15:45:36 -08:00
parent f91739ec9a
commit 68c826b445
8 changed files with 134 additions and 95 deletions

View File

@@ -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
------------

View File

@@ -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

View File

@@ -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

View File

@@ -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<TcpTxBuffer> ())
.AddAttribute ("RxBuffer",
"TCP Rx buffer",
PointerValue (),
MakePointerAccessor (&TcpSocketBase::GetRxBuffer),
MakePointerChecker<TcpRxBuffer> ())
.AddTraceSource ("RTO",
"Retransmission timeout",
MakeTraceSourceAccessor (&TcpSocketBase::m_rto),
@@ -164,6 +175,8 @@ TcpSocketBase::TcpSocketBase (void)
{
NS_LOG_FUNCTION (this);
m_rxBuffer = CreateObject<TcpRxBuffer> ();
m_txBuffer = CreateObject<TcpTxBuffer> ();
}
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<Packet> 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<Packet> 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<Packet> (); // Send EOF on connection close
}
Ptr<Packet> outPacket = m_rxBuffer.Extract (maxSize);
Ptr<Packet> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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> 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<Packet> 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<Packet> 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<Packet> 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<Packet> p = m_txBuffer.CopyFromSequence (maxSize, seq);
Ptr<Packet> 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<Packet> 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<Packet> 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<Packet> 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<Packet> p = m_txBuffer.CopyFromSequence (1, m_nextTxSequence);
Ptr<Packet> 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<int> (scale) << " for buffer size " << m_rxBuffer.MaxBufferSize ());
static_cast<int> (scale) << " for buffer size " << m_rxBuffer->MaxBufferSize ());
return scale;
}
@@ -2733,6 +2746,19 @@ TcpSocketBase::GetClockGranularity (void) const
return m_clockGranularity;
}
Ptr<TcpTxBuffer>
TcpSocketBase::GetTxBuffer (void) const
{
return m_txBuffer;
}
Ptr<TcpRxBuffer>
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)

View File

@@ -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<TcpTxBuffer> GetTxBuffer (void) const;
/**
* \brief Get a pointer to the Rx buffer
* \return a pointer to the rx buffer
*/
Ptr<TcpRxBuffer> 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<SequenceNumber32> m_nextTxSequence; //!< Next seqnum to be sent (SND.NXT), ReTx pushes it back
TracedValue<SequenceNumber32> m_highTxMark; //!< Highest seqno ever sent, regardless of ReTx
TcpRxBuffer m_rxBuffer; //!< Rx buffer (reordering buffer)
TcpTxBuffer m_txBuffer; //!< Tx buffer
Ptr<TcpRxBuffer> m_rxBuffer; //!< Rx buffer (reordering buffer)
Ptr<TcpTxBuffer> m_txBuffer; //!< Tx buffer
// State-related attributes
TracedValue<TcpStates_t> m_state; //!< TCP state

View File

@@ -146,7 +146,7 @@ TcpTahoe::DupAck (const TcpHeader& t, uint32_t count)
// (Fall & Floyd 1996, sec.1)
m_ssThresh = std::max (static_cast<unsigned> (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<unsigned> (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
}

View File

@@ -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);

View File

@@ -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);