Created TCB: Transmission Control Block
authorNatale Patriciello <natale.patriciello@gmail.com>
Fri, 16 Oct 2015 10:42:14 -0700
changeset 11705 66e6652cc874
parent 11704 1c5aafc4c589
child 11706 89b14419f599
Created TCB: Transmission Control Block The data structure contains information that should be exchanged between congestion control and the socket.
src/internet/model/tcp-newreno.cc
src/internet/model/tcp-socket-base.cc
src/internet/model/tcp-socket-base.h
src/internet/model/tcp-westwood.cc
--- a/src/internet/model/tcp-newreno.cc	Fri Oct 16 10:39:34 2015 -0700
+++ b/src/internet/model/tcp-newreno.cc	Fri Oct 16 10:42:14 2015 -0700
@@ -74,8 +74,8 @@
 {
   NS_LOG_FUNCTION (this << seq);
   NS_LOG_LOGIC ("TcpNewReno received ACK for seq " << seq <<
-                " cwnd " << m_cWnd <<
-                " ssthresh " << m_ssThresh);
+                " cwnd " << m_tcb->m_cWnd <<
+                " ssthresh " << m_tcb->m_ssThresh);
 
   // No cWnd management while recovering
   if (m_ackState == RECOVERY && seq < m_recover)
@@ -85,18 +85,18 @@
     }
 
   // Increase of cwnd based on current phase (slow start or congestion avoidance)
-  if (m_cWnd < m_ssThresh)
-    { // Slow start mode, add one segSize to cWnd. Default m_ssThresh is 65535. (RFC2001, sec.1)
-      m_cWnd += m_segmentSize;
-      NS_LOG_INFO ("In SlowStart, ACK of seq " << seq << "; update cwnd to " << m_cWnd << "; ssthresh " << m_ssThresh);
+  if (m_tcb->m_cWnd < m_tcb->m_ssThresh)
+    { // Slow start mode, add one segSize to cWnd. Default m_tcb->m_ssThresh is 65535. (RFC2001, sec.1)
+      m_tcb->m_cWnd += m_tcb->m_segmentSize;
+      NS_LOG_INFO ("In SlowStart, ACK of seq " << seq << "; update cwnd to " << m_tcb->m_cWnd << "; ssthresh " << m_tcb->m_ssThresh);
     }
   else
     { // Congestion avoidance mode, increase by (segSize*segSize)/cwnd. (RFC2581, sec.3.1)
       // To increase cwnd for one segSize per RTT, it should be (ackBytes*segSize)/cwnd
-      double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get ();
+      double adder = static_cast<double> (m_tcb->m_segmentSize * m_tcb->m_segmentSize) / m_tcb->m_cWnd.Get ();
       adder = std::max (1.0, adder);
-      m_cWnd += static_cast<uint32_t> (adder);
-      NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
+      m_tcb->m_cWnd += static_cast<uint32_t> (adder);
+      NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_tcb->m_cWnd << " ssthresh " << m_tcb->m_ssThresh);
     }
 
   // Complete newAck processing
@@ -106,7 +106,7 @@
 uint32_t
 TcpNewReno::GetSsThresh ()
 {
-  return std::max (2 * m_segmentSize, BytesInFlight () / 2);
+  return std::max (2 * m_tcb->m_segmentSize, BytesInFlight () / 2);
 }
 
 } // namespace ns3
--- a/src/internet/model/tcp-socket-base.cc	Fri Oct 16 10:39:34 2015 -0700
+++ b/src/internet/model/tcp-socket-base.cc	Fri Oct 16 10:42:14 2015 -0700
@@ -164,16 +164,50 @@
                      "ns3::SequenceNumber32TracedValueCallback")
     .AddTraceSource ("CongestionWindow",
                      "The TCP connection's congestion window",
-                     MakeTraceSourceAccessor (&TcpSocketBase::m_cWnd),
+                     MakeTraceSourceAccessor (&TcpSocketBase::m_cWndTrace),
                      "ns3::TracedValueCallback::Uint32")
     .AddTraceSource ("SlowStartThreshold",
                      "TCP slow start threshold (bytes)",
-                     MakeTraceSourceAccessor (&TcpSocketBase::m_ssThresh),
+                     MakeTraceSourceAccessor (&TcpSocketBase::m_ssThTrace),
                      "ns3::TracedValueCallback::Uint32")
   ;
   return tid;
 }
 
+// TcpSocketState
+TypeId
+TcpSocketState::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TcpSocketState")
+    .SetParent<Object> ()
+    .SetGroupName ("Internet")
+    .AddConstructor <TcpSocketState> ()
+    .AddTraceSource ("CongestionWindow",
+                     "The TCP connection's congestion window",
+                     MakeTraceSourceAccessor (&TcpSocketState::m_cWnd),
+                     "ns3::TracedValue::Uint32Callback")
+    .AddTraceSource ("SlowStartThreshold",
+                     "TCP slow start threshold (bytes)",
+                     MakeTraceSourceAccessor (&TcpSocketState::m_ssThresh),
+                     "ns3::TracedValue::Uint32Callback")
+  ;
+  return tid;
+}
+
+TcpSocketState::TcpSocketState (void)
+  : Object ()
+{
+}
+
+TcpSocketState::TcpSocketState (const TcpSocketState &other)
+  : m_cWnd (other.m_cWnd),
+    m_ssThresh (other.m_ssThresh),
+    m_initialCWnd (other.m_initialCWnd),
+    m_initialSsThresh (other.m_initialSsThresh),
+    m_segmentSize (other.m_segmentSize)
+{
+}
+
 TcpSocketBase::TcpSocketBase (void)
   : m_dupAckCount (0),
     m_delAckCount (0),
@@ -194,7 +228,6 @@
     m_shutdownSend (false),
     m_shutdownRecv (false),
     m_connected (false),
-    m_segmentSize (0),
     // For attribute initialization consistency (quiet valgrind)
     m_rWnd (0),
     m_highRxMark (0),
@@ -211,6 +244,17 @@
   NS_LOG_FUNCTION (this);
   m_rxBuffer = CreateObject<TcpRxBuffer> ();
   m_txBuffer = CreateObject<TcpTxBuffer> ();
+  m_tcb      = CreateObject<TcpSocketState> ();
+
+  bool ok;
+
+  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
+                                          MakeCallback (&TcpSocketBase::UpdateCwnd, this));
+  NS_ASSERT (ok == true);
+
+  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
+                                          MakeCallback (&TcpSocketBase::UpdateSsThresh, this));
+  NS_ASSERT (ok == true);
 }
 
 TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock)
@@ -239,15 +283,10 @@
     m_shutdownRecv (sock.m_shutdownRecv),
     m_connected (sock.m_connected),
     m_msl (sock.m_msl),
-    m_segmentSize (sock.m_segmentSize),
     m_maxWinSize (sock.m_maxWinSize),
     m_rWnd (sock.m_rWnd),
     m_highRxMark (sock.m_highRxMark),
     m_highRxAckMark (sock.m_highRxAckMark),
-    m_cWnd (sock.m_cWnd),
-    m_ssThresh (sock.m_ssThresh),
-    m_initialCWnd (sock.m_initialCWnd),
-    m_initialSsThresh (sock.m_initialSsThresh),
     m_winScalingEnabled (sock.m_winScalingEnabled),
     m_sndScaleFactor (sock.m_sndScaleFactor),
     m_rcvScaleFactor (sock.m_rcvScaleFactor),
@@ -255,8 +294,8 @@
     m_timestampToEcho (sock.m_timestampToEcho),
     m_ackState (sock.m_ackState),
     m_retxThresh (sock.m_retxThresh),
-    m_limitedTx (sock.m_limitedTx)
-
+    m_limitedTx (sock.m_limitedTx),
+    m_tcb (sock.m_tcb)
 {
   NS_LOG_FUNCTION (this);
   NS_LOG_LOGIC ("Invoked the copy constructor");
@@ -275,6 +314,16 @@
   SetRecvCallback (vPS);
   m_txBuffer = CopyObject (sock.m_txBuffer);
   m_rxBuffer = CopyObject (sock.m_rxBuffer);
+
+  bool ok;
+
+  ok = m_tcb->TraceConnectWithoutContext ("CongestionWindow",
+                                          MakeCallback (&TcpSocketBase::UpdateCwnd, this));
+  NS_ASSERT (ok == true);
+
+  ok = m_tcb->TraceConnectWithoutContext ("SlowStartThreshold",
+                                          MakeCallback (&TcpSocketBase::UpdateSsThresh, this));
+  NS_ASSERT (ok == true);
 }
 
 TcpSocketBase::~TcpSocketBase (void)
@@ -457,8 +506,8 @@
 void
 TcpSocketBase::InitializeCwnd (void)
 {
-  m_cWnd = m_initialCWnd * m_segmentSize;
-  m_ssThresh = m_initialSsThresh;
+  m_tcb->m_cWnd = m_tcb->m_initialCWnd * m_tcb->m_segmentSize;
+  m_tcb->m_ssThresh = m_tcb->m_initialSsThresh;
 }
 
 void
@@ -467,13 +516,13 @@
   NS_ABORT_MSG_UNLESS (m_state == CLOSED,
     "TcpSocketBase::SetSSThresh() cannot change initial ssThresh after connection started.");
 
-  m_initialSsThresh = threshold;
+  m_tcb->m_initialSsThresh = threshold;
 }
 
 uint32_t
 TcpSocketBase::GetInitialSSThresh (void) const
 {
-  return m_initialSsThresh;
+  return m_tcb->m_initialSsThresh;
 }
 
 void
@@ -482,19 +531,19 @@
   NS_ABORT_MSG_UNLESS (m_state == CLOSED,
     "TcpSocketBase::SetInitialCwnd() cannot change initial cwnd after connection started.");
 
-  m_initialCWnd = cwnd;
+  m_tcb->m_initialCWnd = cwnd;
 }
 
 uint32_t
 TcpSocketBase::GetInitialCwnd (void) const
 {
-  return m_initialCWnd;
+  return m_tcb->m_initialCWnd;
 }
 
 void
 TcpSocketBase::ScaleSsThresh (uint8_t scaleFactor)
 {
-  m_ssThresh <<= scaleFactor;
+  m_tcb->m_ssThresh <<= scaleFactor;
 }
 
 /* Inherit from Socket class: Initiate connection to a remote address:port */
@@ -1227,7 +1276,7 @@
             {
               // 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);
+              uint32_t sz = SendDataPacket (m_nextTxSequence, m_tcb->m_segmentSize, true);
               m_nextTxSequence += sz;
             }
           else if (m_dupAckCount == m_retxThresh)
@@ -1236,25 +1285,26 @@
               m_recover = m_highTxMark;
               m_ackState = RECOVERY;
 
-              m_ssThresh = GetSsThresh ();
-              m_cWnd = m_ssThresh + m_dupAckCount * m_segmentSize;
+              m_tcb->m_ssThresh = GetSsThresh ();
+              m_tcb->m_cWnd = m_tcb->m_ssThresh + m_dupAckCount * m_tcb->m_segmentSize;
 
               NS_LOG_INFO (m_dupAckCount << " dupack. Enter fast recovery mode." <<
-                           "Reset cwnd to " << m_cWnd << ", ssthresh to " <<
-                           m_ssThresh << " at fast recovery seqnum " << m_recover);
+                           "Reset cwnd to " << m_tcb->m_cWnd << ", ssthresh to " <<
+                           m_tcb->m_ssThresh << " at fast recovery seqnum " << m_recover);
               DoRetransmit ();
 
-              NS_LOG_DEBUG ("DISORDER -> RECOVERY");
+              NS_LOG_DEBUG (TcpAckStateName[m_ackState] << " -> RECOVERY");
             }
           else
             {
-              NS_FATAL_ERROR ("m_dupAckCount > m_retxThresh and we still are in DISORDER state");
+              NS_FATAL_ERROR ("m_dupAckCount > m_retxThresh and we still are "
+                              "in DISORDER state");
             }
         }
       else if (m_ackState == RECOVERY)
         { // Increase cwnd for every additional dupack (RFC2582, sec.3 bullet #3)
-          m_cWnd += m_segmentSize;
-          NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_cWnd);
+          m_tcb->m_cWnd +=  m_tcb->m_segmentSize;
+          NS_LOG_INFO ("Dupack in fast recovery mode. Increase cwnd to " << m_tcb->m_cWnd);
           if (!m_sendPendingDataEvent.IsRunning ())
             {
               m_sendPendingDataEvent = Simulator::Schedule (TimeStep (1), &TcpSocketBase::SendPendingData, this, m_connected);
@@ -1279,17 +1329,19 @@
         {
           if (tcpHeader.GetAckNumber () < m_recover)
             { // Partial ACK, partial window deflation (RFC2582 sec.3 bullet #5 paragraph 3)
-              m_cWnd += m_segmentSize - (tcpHeader.GetAckNumber () - m_txBuffer->HeadSequence ());
-              NS_LOG_INFO ("Partial ACK for seq " << tcpHeader.GetAckNumber () << " in fast recovery: cwnd set to " << m_cWnd);
+              m_tcb->m_cWnd +=  m_tcb->m_segmentSize -
+                                (tcpHeader.GetAckNumber () - m_txBuffer->HeadSequence ());
+              NS_LOG_INFO ("Partial ACK for seq " << tcpHeader.GetAckNumber () <<
+                           " in fast recovery: cwnd set to " << m_tcb->m_cWnd);
               m_txBuffer->DiscardUpTo(tcpHeader.GetAckNumber ());  //Bug 1850:  retransmit before newack
               DoRetransmit (); // Assume the next seq is lost. Retransmit lost packet
             }
           else if (tcpHeader.GetAckNumber () >= m_recover)
             {// Full ACK (RFC2582 sec.3 bullet #5 paragraph 2, option 1)
-              m_cWnd = std::min (m_ssThresh.Get (), BytesInFlight () + m_segmentSize);
+               m_tcb->m_cWnd = std::min ( m_tcb->m_ssThresh.Get (), BytesInFlight () +  m_tcb->m_segmentSize);
               m_ackState = OPEN;
               NS_LOG_INFO ("Received full ACK for seq " << tcpHeader.GetAckNumber () <<
-                           ". Leaving fast recovery with cwnd set to " << m_cWnd);
+                           ". Leaving fast recovery with cwnd set to " << m_tcb->m_cWnd);
               NS_LOG_DEBUG ("RECOVERY -> OPEN");
             }
         }
@@ -2170,7 +2222,7 @@
     {
       uint32_t w = AvailableWindow (); // Get available window size
       // 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_tcb->m_segmentSize && m_txBuffer->SizeFromSequence (m_nextTxSequence) > w)
         {
           NS_LOG_LOGIC ("Preventing Silly Window Syndrome. Wait to send.");
           break; // No more
@@ -2178,7 +2230,7 @@
       // 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_tcb->m_segmentSize)
         {
           NS_LOG_LOGIC ("Invoking Nagle's algorithm. Wait to send.");
           break;
@@ -2186,12 +2238,12 @@
       NS_LOG_LOGIC ("TcpSocketBase " << this << " SendPendingData" <<
                     " w " << w <<
                     " rxwin " << m_rWnd <<
-                    " segsize " << m_segmentSize <<
+                    " segsize " << m_tcb->m_segmentSize <<
                     " nextTxSeq " << m_nextTxSequence <<
                     " highestRxAck " << m_txBuffer->HeadSequence () <<
                     " pd->Size " << m_txBuffer->Size () <<
                     " pd->SFS " << m_txBuffer->SizeFromSequence (m_nextTxSequence));
-      uint32_t s = std::min (w, m_segmentSize);  // Send no more than window
+      uint32_t s = std::min (w, m_tcb->m_segmentSize);  // Send no more than window
       uint32_t sz = SendDataPacket (m_nextTxSequence, s, withAck);
       nPacketsSent++;                             // Count sent this loop
       m_nextTxSequence += sz;                     // Advance next tx sequence
@@ -2221,7 +2273,7 @@
 TcpSocketBase::Window (void)
 {
   NS_LOG_FUNCTION (this);
-  return std::min (m_rWnd.Get (), m_cWnd.Get ());
+  return std::min (m_rWnd.Get (), m_tcb->m_cWnd.Get ());
 }
 
 uint32_t
@@ -2532,12 +2584,12 @@
   if (m_ackState != LOSS)
     {
       m_ackState = LOSS;
-      m_cWnd = m_segmentSize;
-      m_ssThresh = GetSsThresh ();
+      m_tcb->m_ssThresh = GetSsThresh ();
+      m_tcb->m_cWnd = m_tcb->m_segmentSize;
     }
 
-  NS_LOG_DEBUG ("RTO. Reset cwnd to " << m_cWnd <<
-               ", ssthresh to " << m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
+  NS_LOG_DEBUG ("RTO. Reset cwnd to " <<  m_tcb->m_cWnd << ", ssthresh to " <<
+                m_tcb->m_ssThresh << ", restart from seqnum " << m_nextTxSequence);
   DoRetransmit ();                          // Retransmit the packet
 }
 
@@ -2569,7 +2621,7 @@
     }
   // 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);
+  uint32_t sz = SendDataPacket (m_txBuffer->HeadSequence (), m_tcb->m_segmentSize, true);
   // In case of RTO, advance m_nextTxSequence
   m_nextTxSequence = std::max (m_nextTxSequence.Get (), m_txBuffer->HeadSequence () + sz);
 
@@ -2631,7 +2683,7 @@
 TcpSocketBase::SetSegSize (uint32_t size)
 {
   NS_LOG_FUNCTION (this << size);
-  m_segmentSize = size;
+  m_tcb->m_segmentSize = size;
 
   NS_ABORT_MSG_UNLESS (m_state == CLOSED, "Cannot change segment size dynamically.");
 }
@@ -2639,7 +2691,7 @@
 uint32_t
 TcpSocketBase::GetSegSize (void) const
 {
-  return m_segmentSize;
+  return m_tcb->m_segmentSize;
 }
 
 void
@@ -2957,10 +3009,21 @@
 const char* const
 TcpSocketBase::TcpAckStateName[TcpSocketBase::LAST_ACKSTATE] =
 {
-  "OPEN", "DISORDER", "CWR", "RECOVERY",
-  "LOSS"
+  "OPEN", "DISORDER", "CWR", "RECOVERY", "LOSS"
 };
 
+void
+TcpSocketBase::UpdateCwnd (uint32_t oldValue, uint32_t newValue)
+{
+  m_cWndTrace (oldValue, newValue);
+}
+
+void
+TcpSocketBase::UpdateSsThresh (uint32_t oldValue, uint32_t newValue)
+{
+  m_ssThTrace (oldValue, newValue);
+}
+
 
 //RttHistory methods
 RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t)
--- a/src/internet/model/tcp-socket-base.h	Fri Oct 16 10:39:34 2015 -0700
+++ b/src/internet/model/tcp-socket-base.h	Fri Oct 16 10:42:14 2015 -0700
@@ -45,6 +45,7 @@
 class Packet;
 class TcpL4Protocol;
 class TcpHeader;
+class TcpSocketState;
 
 /**
  * \ingroup tcp
@@ -104,6 +105,13 @@
  * the TcpAckState_t documentation.
  *
  *
+ * Congestion control interface
+ * ---------------------------
+ *
+ * The variables needed to congestion control subclasses have been moved inside
+ * the TcpSocketState class. It contains information on the congestion window,
+ * slow start threshold, segment size and the state of the Ack state machine.
+ *
  * Fast retransmit
  * ---------------------------
  *
@@ -244,6 +252,30 @@
    */
   static const char* const TcpAckStateName[TcpSocketBase::LAST_ACKSTATE];
 
+  /**
+   * \brief Callback pointer for cWnd trace chaining
+   */
+  TracedCallback<uint32_t, uint32_t> m_cWndTrace;
+
+  /**
+   * \brief Callback pointer for ssTh trace chaining
+   */
+  TracedCallback<uint32_t, uint32_t> m_ssThTrace;
+
+  /**
+   * \brief Callback function to hook to TcpSocketState congestion window
+   * \param oldValue old cWnd value
+   * \param newValue new cWnd value
+   */
+  void UpdateCwnd (uint32_t oldValue, uint32_t newValue);
+
+  /**
+   * \brief Callback function to hook to TcpSocketState slow start threshold
+   * \param oldValue old ssTh value
+   * \param newValue new ssTh value
+   */
+  void UpdateSsThresh (uint32_t oldValue, uint32_t newValue);
+
   // Necessary implementations of null functions from ns3::Socket
   virtual enum SocketErrno GetErrno (void) const;    // returns m_errno
   virtual enum SocketType GetSocketType (void) const; // returns socket type
@@ -828,18 +860,11 @@
   double                   m_msl;           //!< Max segment lifetime
 
   // Window management
-  uint32_t              m_segmentSize; //!< Segment size
   uint16_t              m_maxWinSize;  //!< Maximum window size to advertise
   TracedValue<uint32_t> m_rWnd;        //!< Receiver window (RCV.WND in RFC793)
   TracedValue<SequenceNumber32> m_highRxMark;     //!< Highest seqno received
   TracedValue<SequenceNumber32> m_highRxAckMark;  //!< Highest ack received
 
-  // Congestion control
-  TracedValue<uint32_t> m_cWnd;     //!< Congestion window
-  TracedValue<uint32_t> m_ssThresh; //!< Slow start threshold
-  uint32_t               m_initialCWnd;      //!< Initial cWnd value
-  uint32_t               m_initialSsThresh;  //!< Initial Slow Start Threshold value
-
   // Options
   bool    m_winScalingEnabled;    //!< Window Scale option enabled
   uint8_t m_sndScaleFactor;       //!< Sent Window Scale (i.e., the one of the node)
@@ -857,6 +882,44 @@
   SequenceNumber32       m_recover;      //!< Previous highest Tx seqnum for fast recovery
   uint32_t               m_retxThresh;   //!< Fast Retransmit threshold
   bool                   m_limitedTx;    //!< perform limited transmit
+
+  // Transmission Control Block
+  Ptr<TcpSocketState> m_tcb;             //!< Congestion control informations
+};
+
+/**
+ * \brief Data structure that records the congestion state of a connection
+ *
+ * In this data structure, basic informations that should be passed between
+ * socket and the congestion control algorithm are saved. Through the code,
+ * it will be referred as Transmission Control Block (TCB), but there are some
+ * differencies. In the RFCs, the TCB contains all the variables that defines
+ * a connection, while we preferred to maintain in this class only the values
+ * that should be exchanged between socket and other parts, like congestion
+ * control algorithms.
+ *
+ */
+class TcpSocketState : public Object
+{
+public:
+  /**
+   * Get the type ID.
+   * \brief Get the type ID.
+   * \return the object TypeId
+   */
+  static TypeId GetTypeId (void);
+
+  TcpSocketState ();
+  TcpSocketState (const TcpSocketState &other);
+
+  // Congestion control
+  TracedValue<uint32_t>  m_cWnd;             //!< Congestion window
+  TracedValue<uint32_t>  m_ssThresh;         //!< Slow start threshold
+  uint32_t               m_initialCWnd;      //!< Initial cWnd value
+  uint32_t               m_initialSsThresh;  //!< Initial Slow Start Threshold value
+
+  // Segment
+  uint32_t               m_segmentSize;      //!< Segment size
 };
 
 /**
--- a/src/internet/model/tcp-westwood.cc	Fri Oct 16 10:39:34 2015 -0700
+++ b/src/internet/model/tcp-westwood.cc	Fri Oct 16 10:42:14 2015 -0700
@@ -117,21 +117,21 @@
 { // Same as Reno
   NS_LOG_FUNCTION (this << seq);
   NS_LOG_LOGIC ("TcpWestwood receieved ACK for seq " << seq <<
-                " cwnd " << m_cWnd <<
-                " ssthresh " << m_ssThresh);
+                " cwnd " << m_tcb->m_cWnd <<
+                " ssthresh " << m_tcb->m_ssThresh);
 
   // Increase of cwnd based on current phase (slow start or congestion avoidance)
-  if (m_cWnd < m_ssThresh)
+  if (m_tcb->m_cWnd < m_tcb->m_ssThresh)
     { // Slow start mode, add one segSize to cWnd as in Reno
-      m_cWnd += m_segmentSize;
-      NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
+      m_tcb->m_cWnd += m_tcb->m_segmentSize;
+      NS_LOG_INFO ("In SlowStart, updated to cwnd " << m_tcb->m_cWnd << " ssthresh " << m_tcb->m_ssThresh);
     }
   else
     { // Congestion avoidance mode, increase by (segSize*segSize)/cwnd as in Reno
-      double adder = static_cast<double> (m_segmentSize * m_segmentSize) / m_cWnd.Get();
+      double adder = static_cast<double> (m_tcb->m_segmentSize * m_tcb->m_segmentSize) / m_tcb->m_cWnd.Get();
       adder = std::max(1.0, adder);
-      m_cWnd += static_cast<uint32_t>(adder);
-      NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_cWnd << " ssthresh " << m_ssThresh);
+      m_tcb->m_cWnd += static_cast<uint32_t>(adder);
+      NS_LOG_INFO ("In CongAvoid, updated to cwnd " << m_tcb->m_cWnd << " ssthresh " << m_tcb->m_ssThresh);
     }
 
   // Complete newAck processing
@@ -172,14 +172,14 @@
       // Get the time when the current ACK is received
       double currentAck = static_cast<double> (Simulator::Now().GetSeconds());
       // Calculate the BW
-      m_currentBW = acked * m_segmentSize / (currentAck - m_lastAck);
+      m_currentBW = acked * m_tcb->m_segmentSize / (currentAck - m_lastAck);
       // Update the last ACK time
       m_lastAck = currentAck;
     }
   else if (m_pType == TcpWestwood::WESTWOODPLUS)
     {
       // Calculate the BW
-      m_currentBW = m_ackedSegments * m_segmentSize / rtt.GetSeconds();
+      m_currentBW = m_ackedSegments * m_tcb->m_segmentSize / rtt.GetSeconds();
       // Reset m_ackedSegments and m_IsCount for the next sampling
       m_ackedSegments = 0;
       m_IsCount = false;
@@ -195,7 +195,7 @@
   NS_LOG_FUNCTION (this);
 
   // Calculate the number of acknowledged segments based on the received ACK number
-  int cumul_ack = (tcpHeader.GetAckNumber() - m_prevAckNo) / m_segmentSize;
+  int cumul_ack = (tcpHeader.GetAckNumber() - m_prevAckNo) / m_tcb->m_segmentSize;
 
   if (cumul_ack == 0)
     {// A DUPACK counts for 1 segment delivered successfully