Bug 2055 - TxBuffer and RxBuffer traces don't work
authorTommaso Pecorella <tommaso.pecorella@unifi.it>
Sat, 31 Jan 2015 15:45:36 -0800
changeset 11195 0c5e9bfa1b48
parent 11194 46b6e53e8dbc
child 11196 9d8c60f0db81
Bug 2055 - TxBuffer and RxBuffer traces don't work
RELEASE_NOTES
src/internet/model/tcp-newreno.cc
src/internet/model/tcp-reno.cc
src/internet/model/tcp-socket-base.cc
src/internet/model/tcp-socket-base.h
src/internet/model/tcp-tahoe.cc
src/internet/model/tcp-westwood.cc
src/internet/test/tcp-wscaling-test.cc
--- a/RELEASE_NOTES	Sat Jan 31 15:42:19 2015 -0800
+++ b/RELEASE_NOTES	Sat Jan 31 15:45:36 2015 -0800
@@ -76,6 +76,7 @@
 - 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
 ------------
--- a/src/internet/model/tcp-newreno.cc	Sat Jan 31 15:42:19 2015 -0800
+++ b/src/internet/model/tcp-newreno.cc	Sat Jan 31 15:45:36 2015 -0800
@@ -130,9 +130,9 @@
   // 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 @@
       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 @@
   // 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
--- a/src/internet/model/tcp-reno.cc	Sat Jan 31 15:42:19 2015 -0800
+++ b/src/internet/model/tcp-reno.cc	Sat Jan 31 15:45:36 2015 -0800
@@ -178,14 +178,14 @@
   // 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
--- a/src/internet/model/tcp-socket-base.cc	Sat Jan 31 15:42:19 2015 -0800
+++ b/src/internet/model/tcp-socket-base.cc	Sat Jan 31 15:45:36 2015 -0800
@@ -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 @@
                    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 @@
 
 {
   NS_LOG_FUNCTION (this);
+  m_rxBuffer = CreateObject<TcpRxBuffer> ();
+  m_txBuffer = CreateObject<TcpTxBuffer> ();
 }
 
 TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock)
@@ -184,8 +197,6 @@
     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 @@
   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 @@
   /// \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 @@
   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 @@
   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 @@
           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 @@
 {
   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 @@
 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 @@
 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 @@
     }
   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 @@
       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 @@
           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 @@
       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 @@
           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 @@
   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 @@
   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 @@
       // 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 @@
       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 @@
       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 @@
       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 @@
     }
   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 @@
   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 @@
         { // 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 @@
     }
 
   // 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 @@
 
   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 @@
     }
   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 @@
   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 @@
       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 @@
 
   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 @@
   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 @@
   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 @@
   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 @@
 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 @@
       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 @@
                     " 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 @@
 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 @@
 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 @@
                 " 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 @@
         }
     }
   // 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 @@
         }
       // 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 @@
     }
   // 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 @@
     {
       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 @@
       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 @@
 {
   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 @@
 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 @@
       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 @@
       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 @@
 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 @@
 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 @@
     }
 
   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 @@
   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)
--- a/src/internet/model/tcp-socket-base.h	Sat Jan 31 15:42:19 2015 -0800
+++ b/src/internet/model/tcp-socket-base.h	Sat Jan 31 15:45:36 2015 -0800
@@ -154,6 +154,18 @@
    */
   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 @@
   // 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
--- a/src/internet/model/tcp-tahoe.cc	Sat Jan 31 15:42:19 2015 -0800
+++ b/src/internet/model/tcp-tahoe.cc	Sat Jan 31 15:45:36 2015 -0800
@@ -146,7 +146,7 @@
       // (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 @@
   // 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
 }
 
--- a/src/internet/model/tcp-westwood.cc	Sat Jan 31 15:42:19 2015 -0800
+++ b/src/internet/model/tcp-westwood.cc	Sat Jan 31 15:45:36 2015 -0800
@@ -307,7 +307,7 @@
   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 @@
   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);
 
--- a/src/internet/test/tcp-wscaling-test.cc	Sat Jan 31 15:42:19 2015 -0800
+++ b/src/internet/test/tcp-wscaling-test.cc	Sat Jan 31 15:45:36 2015 -0800
@@ -385,8 +385,8 @@
       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);