61 #include "ns3/uinteger.h"
62 #include "ns3/double.h"
63 #include "ns3/simulator.h"
64 #include "ns3/abort.h"
65 #include "ns3/random-variable-stream.h"
66 #include "red-queue.h"
72 NS_OBJECT_ENSURE_REGISTERED (RedQueue);
74 TypeId RedQueue::GetTypeId (
void)
76 static TypeId tid = TypeId (
"ns3::RedQueue")
78 .AddConstructor<RedQueue> ()
79 .AddAttribute (
"Mode",
80 "Determines unit for QueueLimit",
82 MakeEnumAccessor (&RedQueue::SetMode),
85 .AddAttribute (
"MeanPktSize",
86 "Average of packet size",
88 MakeUintegerAccessor (&RedQueue::m_meanPktSize),
89 MakeUintegerChecker<uint32_t> ())
90 .AddAttribute (
"IdlePktSize",
91 "Average packet size used during idle times. Used when m_cautions = 3",
93 MakeUintegerAccessor (&RedQueue::m_idlePktSize),
94 MakeUintegerChecker<uint32_t> ())
95 .AddAttribute (
"Wait",
96 "True for waiting between dropped packets",
98 MakeBooleanAccessor (&RedQueue::m_isWait),
99 MakeBooleanChecker ())
100 .AddAttribute (
"Gentle",
101 "True to increases dropping probability slowly when average queue exceeds maxthresh",
103 MakeBooleanAccessor (&RedQueue::m_isGentle),
104 MakeBooleanChecker ())
105 .AddAttribute (
"MinTh",
106 "Minimum average length threshold in packets/bytes",
108 MakeDoubleAccessor (&RedQueue::m_minTh),
109 MakeDoubleChecker<double> ())
110 .AddAttribute (
"MaxTh",
111 "Maximum average length threshold in packets/bytes",
113 MakeDoubleAccessor (&RedQueue::m_maxTh),
114 MakeDoubleChecker<double> ())
115 .AddAttribute (
"QueueLimit",
116 "Queue limit in bytes/packets",
118 MakeUintegerAccessor (&RedQueue::m_queueLimit),
119 MakeUintegerChecker<uint32_t> ())
121 "Queue weight related to the exponential weighted moving average (EWMA)",
123 MakeDoubleAccessor (&RedQueue::m_qW),
124 MakeDoubleChecker <double> ())
125 .AddAttribute (
"LInterm",
126 "The maximum probability of dropping a packet",
128 MakeDoubleAccessor (&RedQueue::m_lInterm),
129 MakeDoubleChecker <double> ())
130 .AddAttribute (
"Ns1Compat",
131 "NS-1 compatibility",
132 BooleanValue (
false),
133 MakeBooleanAccessor (&RedQueue::m_isNs1Compat),
134 MakeBooleanChecker ())
135 .AddAttribute (
"LinkBandwidth",
136 "The RED link bandwidth",
137 DataRateValue (DataRate (
"1.5Mbps")),
138 MakeDataRateAccessor (&RedQueue::m_linkBandwidth),
139 MakeDataRateChecker ())
140 .AddAttribute (
"LinkDelay",
141 "The RED link delay",
143 MakeTimeAccessor (&RedQueue::m_linkDelay),
150 RedQueue::RedQueue () :
154 m_hasRedStarted (false)
157 m_uv = CreateObject<UniformRandomVariable> ();
160 RedQueue::~RedQueue ()
173 RedQueue::GetMode (
void)
180 RedQueue::SetQueueLimit (uint32_t lim)
187 RedQueue::SetTh (
double minTh,
double maxTh)
196 RedQueue::GetStats ()
215 if (!m_hasRedStarted )
219 m_hasRedStarted =
true;
222 uint32_t nQueued = 0;
227 nQueued = m_bytesInQueue;
232 nQueued = m_packets.size ();
245 double ptc = m_ptc * m_meanPktSize / m_idlePktSize;
246 m = uint32_t (ptc * (now - m_idleTime).GetSeconds ());
250 m = uint32_t (m_ptc * (now - m_idleTime).GetSeconds ());
256 m_qAvg = Estimator (nQueued, m + 1, m_qAvg, m_qW);
258 NS_LOG_DEBUG (
"\t bytesInQueue " << m_bytesInQueue <<
"\tQavg " << m_qAvg);
259 NS_LOG_DEBUG (
"\t packetsInQueue " << m_packets.size () <<
"\tQavg " << m_qAvg);
264 uint32_t dropType = DTYPE_NONE;
265 if (m_qAvg >= m_minTh && nQueued > 1)
267 if ((!m_isGentle && m_qAvg >= m_maxTh) ||
268 (m_isGentle && m_qAvg >= 2 * m_maxTh))
271 dropType = DTYPE_FORCED;
285 else if (DropEarly (p, nQueued))
288 dropType = DTYPE_UNFORCED;
298 if (nQueued >= m_queueLimit)
300 NS_LOG_DEBUG (
"\t Dropping due to Queue Full " << nQueued);
301 dropType = DTYPE_FORCED;
305 if (dropType == DTYPE_UNFORCED)
307 NS_LOG_DEBUG (
"\t Dropping due to Prob Mark " << m_qAvg);
308 m_stats.unforcedDrop++;
312 else if (dropType == DTYPE_FORCED)
314 NS_LOG_DEBUG (
"\t Dropping due to Hard Mark " << m_qAvg);
315 m_stats.forcedDrop++;
325 m_bytesInQueue += p->
GetSize ();
326 m_packets.push_back (p);
341 RedQueue::InitializeParams (
void)
346 m_stats.forcedDrop = 0;
347 m_stats.unforcedDrop = 0;
348 m_stats.qLimDrop = 0;
351 m_ptc = m_linkBandwidth.
GetBitRate () / (8.0 * m_meanPktSize);
359 double th_diff = (m_maxTh - m_minTh);
364 m_vA = 1.0 / th_diff;
365 m_curMaxP = 1.0 / m_lInterm;
366 m_vB = -m_minTh / th_diff;
370 m_vC = (1.0 - m_curMaxP) / m_maxTh;
371 m_vD = 2.0 * m_curMaxP - 1.0;
390 m_qW = 1.0 - std::exp (-1.0 / m_ptc);
392 else if (m_qW == -1.0)
394 double rtt = 3.0 * (m_linkDelay.
GetSeconds () + 1.0 / m_ptc);
400 m_qW = 1.0 - std::exp (-1.0 / (10 * rtt * m_ptc));
402 else if (m_qW == -2.0)
404 m_qW = 1.0 - std::exp (-10.0 / m_ptc);
410 << m_isWait <<
"; m_qW " << m_qW <<
"; m_ptc " << m_ptc
411 <<
"; m_minTh " << m_minTh <<
"; m_maxTh " << m_maxTh
412 <<
"; m_isGentle " << m_isGentle <<
"; th_diff " << th_diff
413 <<
"; lInterm " << m_lInterm <<
"; va " << m_vA <<
"; cur_max_p "
414 << m_curMaxP <<
"; v_b " << m_vB <<
"; m_vC "
415 << m_vC <<
"; m_vD " << m_vD);
420 RedQueue::Estimator (uint32_t nQueued, uint32_t m,
double qAvg,
double qW)
431 newAve += qW * nQueued;
440 RedQueue::DropEarly (Ptr<Packet> p, uint32_t qSize)
443 m_vProb1 = CalculatePNew (m_qAvg, m_maxTh, m_isGentle, m_vA, m_vB, m_vC, m_vD, m_curMaxP);
444 m_vProb = ModifyP (m_vProb1, m_count, m_countBytes, m_meanPktSize, m_isWait, p->GetSize ());
454 double pkts = m_ptc * 0.05;
455 double fraction = std::pow ((1 - m_qW), pkts);
457 if ((
double) qSize < fraction * m_qAvg)
474 double pkts = m_ptc * 0.05;
475 double fraction = std::pow ((1 - m_qW), pkts);
476 double ratio = qSize / (fraction * m_qAvg);
486 NS_LOG_LOGIC (
"u <= m_vProb; u " << u <<
"; m_vProb " << m_vProb);
501 RedQueue::CalculatePNew (
double qAvg,
double maxTh,
bool isGentle,
double vA,
502 double vB,
double vC,
double vD,
double maxP)
504 NS_LOG_FUNCTION (
this << qAvg << maxTh << isGentle << vA << vB << vC << vD << maxP);
507 if (isGentle && qAvg >= maxTh)
513 else if (!isGentle && qAvg >= maxTh)
542 RedQueue::ModifyP (
double p, uint32_t count, uint32_t countBytes,
543 uint32_t meanPktSize,
bool isWait, uint32_t size)
545 NS_LOG_FUNCTION (
this << p << count << countBytes << meanPktSize << isWait << size);
546 double count1 = (double) count;
550 count1 = (double) (countBytes / meanPktSize);
555 if (count1 * p < 1.0)
559 else if (count1 * p < 2.0)
561 p /= (2.0 - count1 * p);
570 if (count1 * p < 1.0)
572 p /= (1.0 - count1 * p);
582 p = (p * size) / meanPktSize;
594 RedQueue::GetQueueSize (
void)
599 return m_bytesInQueue;
603 return m_packets.size ();
612 RedQueue::DoDequeue (
void)
616 if (m_packets.empty ())
627 Ptr<Packet> p = m_packets.front ();
628 m_packets.pop_front ();
629 m_bytesInQueue -= p->GetSize ();
641 RedQueue::DoPeek (
void)
const
644 if (m_packets.empty ())
650 Ptr<Packet> p = m_packets.front ();
Time NanoSeconds(uint64_t ns)
create ns3::Time instances in units of nanoseconds.
#define NS_LOG_FUNCTION(parameters)
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
#define NS_ASSERT(condition)
#define NS_LOG_COMPONENT_DEFINE(name)
uint32_t GetSize(void) const
double GetSeconds(void) const
int64_t AssignStreams(int64_t stream)
#define NS_LOG_LOGIC(msg)
uint64_t GetBitRate() const
QueueMode
Enumeration of the modes supported in the class.
#define NS_ABORT_MSG(msg)
Abnormal program termination.
#define NS_LOG_DEBUG(msg)
Time MilliSeconds(uint64_t ms)
create ns3::Time instances in units of milliseconds.