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