Incast fix
authorAdrian S Tam <adrian.sw.tam@gmail.com>
Wed, 07 Dec 2011 21:00:03 -0500
changeset 7621 ab42fd168916
parent 7620 b2579b330f01
child 7622 c46fa31f71ea
Incast fix
src/internet/model/tcp-admctrl.cc
src/internet/model/tcp-rx-buffer.cc
src/internet/model/tcp-socket-base.cc
src/internet/model/tcp-socket-base.h
src/point-to-point/model/point-to-point-net-device.cc
src/point-to-point/model/point-to-point-net-device.h
--- a/src/internet/model/tcp-admctrl.cc	Wed Dec 07 15:43:04 2011 -0500
+++ b/src/internet/model/tcp-admctrl.cc	Wed Dec 07 21:00:03 2011 -0500
@@ -91,14 +91,14 @@
           m_ece = true;
         }
     }
-/*  if (tcpHeader.GetFlags () & TcpHeader::ECE)
+/*  if ((tcpHeader.GetFlags () & TcpHeader::ECE) && ! m_cwr)
     {
       // Peer echoed ECN. Reduce window
       m_ssThresh = std::max (2 * m_segmentSize, BytesInFlight () / 2);
       m_cWnd = m_ssThresh + 3 * m_segmentSize;
       m_cwr = true;
     }
-  else if (m_cwr)
+  else if (!(tcpHeader.GetFlags () & TcpHeader::ECE) && m_cwr)
     { // Peer acknowledged my window reduction. Reset CWR flag
       m_cwr = false;
     };
@@ -132,6 +132,14 @@
   op->SetTimestamp (uint32_t (Now ().GetNanoSeconds () & std::numeric_limits<uint32_t>::max ()));
   op->SetEcho (m_lastTS);
   h.AppendOption (op);
+  // Put flags into headers
+  if (m_ece || m_cwr)
+    {
+      uint8_t flags = h.GetFlags ();
+      if (m_ece) flags |= TcpHeader::ECE;
+      if (m_cwr) flags |= TcpHeader::CWR;
+      h.SetFlags (flags);
+    }
 }
 
 void
--- a/src/internet/model/tcp-rx-buffer.cc	Wed Dec 07 15:43:04 2011 -0500
+++ b/src/internet/model/tcp-rx-buffer.cc	Wed Dec 07 21:00:03 2011 -0500
@@ -102,7 +102,7 @@
   m_nextRxSeq++;
 }
 
-// Return the highest sequence number that this TcpRxBuffer can accept
+// Return the lowest sequence number that this TcpRxBuffer cannot accept
 SequenceNumber32
 TcpRxBuffer::MaxRxSequence (void) const
 {
--- a/src/internet/model/tcp-socket-base.cc	Wed Dec 07 15:43:04 2011 -0500
+++ b/src/internet/model/tcp-socket-base.cc	Wed Dec 07 21:00:03 2011 -0500
@@ -110,7 +110,8 @@
     m_shutdownRecv (false),
     m_connected (false),
     m_segmentSize (0),          // For attribute initialization consistency (quiet valgrind)
-    m_rWnd (0)
+    m_rWnd (0),
+    m_btto (false)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -143,7 +144,8 @@
     m_msl (sock.m_msl),
     m_segmentSize (sock.m_segmentSize),
     m_maxWinSize (sock.m_maxWinSize),
-    m_rWnd (sock.m_rWnd)
+    m_rWnd (sock.m_rWnd),
+    m_btto (sock.m_btto)
 {
   NS_LOG_FUNCTION (this);
   NS_LOG_LOGIC ("Invoked the copy constructor");
@@ -815,7 +817,7 @@
           // Special treatment to prevent BTTO: Resend FIN packet until ACK is received
           if ((m_state == FIN_WAIT_1 || m_state == LAST_ACK) && m_state == oldState)
             {
-               SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
+               if (m_btto) SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
             }
         }
       // otherwise, the ACK is precisely equal to the nextTxSequence
@@ -831,7 +833,7 @@
       if ((m_state == FIN_WAIT_1 || m_state == LAST_ACK) && m_state == oldState &&
           tcpHeader.GetAckNumber () != m_highTxMark + SequenceNumber32 (1))
         {
-          SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
+          if (m_btto) SendEmptyPacket (TcpHeader::FIN | TcpHeader::ACK);
         }
     }
   // If there is any data piggybacked, store it into m_rxBuffer
--- a/src/internet/model/tcp-socket-base.h	Wed Dec 07 15:43:04 2011 -0500
+++ b/src/internet/model/tcp-socket-base.h	Wed Dec 07 21:00:03 2011 -0500
@@ -228,6 +228,8 @@
   uint32_t              m_segmentSize; //< Segment size
   uint16_t              m_maxWinSize;  //< Maximum window size to advertise
   TracedValue<uint32_t> m_rWnd;        //< Flow control window at remote side
+
+  bool m_btto;
 };
 
 } // namespace ns3
--- a/src/point-to-point/model/point-to-point-net-device.cc	Wed Dec 07 15:43:04 2011 -0500
+++ b/src/point-to-point/model/point-to-point-net-device.cc	Wed Dec 07 21:00:03 2011 -0500
@@ -24,6 +24,7 @@
 #include "ns3/error-model.h"
 #include "ns3/trace-source-accessor.h"
 #include "ns3/uinteger.h"
+#include "ns3/double.h"
 #include "ns3/pointer.h"
 #include "ns3/mpi-interface.h"
 #include "point-to-point-net-device.h"
@@ -75,6 +76,21 @@
                    UintegerValue (3000),
                    MakeUintegerAccessor (&PointToPointNetDevice::m_unitSize),
                    MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinThreshold",
+                   "Minimum threshold of RED-like marking",
+                   UintegerValue (8192),
+                   MakeUintegerAccessor (&PointToPointNetDevice::m_minTh),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxThreshold",
+                   "Maximum threshold of RED-like marking",
+                   UintegerValue (16384),
+                   MakeUintegerAccessor (&PointToPointNetDevice::m_maxTh),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MinProbability",
+                   "Minimum probability of RED-like marking",
+                   DoubleValue (0),
+                   MakeDoubleAccessor (&PointToPointNetDevice::m_minProb),
+                   MakeDoubleChecker<double> (0,1))
 
     //
     // Transmit queueing discipline for the device which includes its own set
@@ -154,6 +170,7 @@
 
 PointToPointNetDevice::PointToPointNetDevice () 
   :
+    norandom(false),
     m_virtBytes (0),
     m_unitSize (3000),
     m_txMachineState (READY),
@@ -235,7 +252,13 @@
   m_currentPkt = p;
   m_phyTxBeginTrace (m_currentPkt);
 
-  Time txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ()));
+  static UniformVariable v(0.0,0.33);
+  double multiple = 1.0 + v.GetValue();
+  Time txTime;
+  if (norandom)
+    txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ()));
+  else
+    txTime = Seconds (m_bps.CalculateTxTime (p->GetSize ()) * multiple);
   Time txCompleteTime = txTime + m_tInterframeGap;
 
   NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << txCompleteTime.GetSeconds () << "sec");
@@ -479,7 +502,19 @@
 bool
 PointToPointNetDevice::QFull (void) const
 {
-  return m_virtBytes + m_queue->GetNBytes() >= (m_queue->GetObject<DropTailQueue>()->m_maxBytes)*0.85;
+  return m_virtBytes + m_queue->GetNBytes() >= (m_queue->GetObject<DropTailQueue>()->m_maxBytes);
+}
+
+bool
+PointToPointNetDevice::ShallDrop (void) const
+{
+  return false; // Disable this function: Not mature
+  uint32_t virtQLen = /* m_virtBytes + */ m_queue->GetNBytes();
+  if (virtQLen <= m_minTh) return false;
+  uint32_t offset = m_minTh - virtQLen;
+  double slope = (1 - m_minProb)/(m_maxTh - m_minTh);
+  double prob = offset * slope + m_minProb;
+  return (UniformVariable(0.0,1.0).GetValue() < prob);
 }
 
 bool
@@ -510,21 +545,31 @@
     {
       Ipv4Header h;
       packet->PeekHeader(h);
-      if (h.GetProtocol() == 6) {
-              Ptr<Packet> q = packet->Copy();
-              q->RemoveHeader(h);
-              TcpHeader tcph;
-              q->RemoveHeader(tcph);
-              if (tcph.GetFlags() & TcpHeader::SYN) {
-                      m_virtBytes += m_unitSize;
-              };
-      }
-      if (QFull())
+      bool isSyn = false;
+      if (h.GetProtocol() == 6)
+        {
+          Ptr<Packet> q = packet->Copy();
+          q->RemoveHeader(h);
+          TcpHeader tcph;
+          q->RemoveHeader(tcph);
+          if (tcph.GetFlags() & TcpHeader::SYN)
+            {
+              m_virtBytes += m_unitSize;
+              isSyn = true;
+            };
+        }
+      if (isSyn && QFull())
         {
           packet->RemoveHeader(h);
           h.SetEcn(Ipv4Header::CE);
           packet->AddHeader(h);
         }
+      else if (!isSyn && ShallDrop())
+        {
+          // Drop packets
+          m_macTxDropTrace (packet);
+          return false;
+        }
     }
 
   //
--- a/src/point-to-point/model/point-to-point-net-device.h	Wed Dec 07 15:43:04 2011 -0500
+++ b/src/point-to-point/model/point-to-point-net-device.h	Wed Dec 07 21:00:03 2011 -0500
@@ -185,12 +185,17 @@
   virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
   virtual bool SupportsSendFrom (void) const;
 
+  bool norandom;
 protected:
   void DoMpiReceive (Ptr<Packet> p);
 
   bool QFull (void) const;
+  bool ShallDrop (void) const;
   uint32_t m_virtBytes;
   uint32_t m_unitSize;
+  uint32_t m_minTh; // min threshold for RED-like marking
+  uint32_t m_maxTh; // max threshold for RED-like marking
+  double m_minProb; // Marking probability at m_minTh
   Time m_idleBeginTime;
 
 private: