traffic-control: Add ECN marking to CoDel queue disc
This commit is contained in:
committed by
Stefano Avallone
parent
d7a144bcf8
commit
4aade6e7ef
@@ -73,6 +73,11 @@ TypeId CoDelQueueDisc::GetTypeId (void)
|
||||
.SetParent<QueueDisc> ()
|
||||
.SetGroupName ("TrafficControl")
|
||||
.AddConstructor<CoDelQueueDisc> ()
|
||||
.AddAttribute ("UseEcn",
|
||||
"True to use ECN (packets are marked instead of being dropped)",
|
||||
BooleanValue (false),
|
||||
MakeBooleanAccessor (&CoDelQueueDisc::m_useEcn),
|
||||
MakeBooleanChecker ())
|
||||
.AddAttribute ("MaxSize",
|
||||
"The maximum number of packets/bytes accepted by this queue disc.",
|
||||
QueueSizeValue (QueueSize (QueueSizeUnit::BYTES, 1500 * DEFAULT_CODEL_LIMIT)),
|
||||
@@ -94,6 +99,11 @@ TypeId CoDelQueueDisc::GetTypeId (void)
|
||||
StringValue ("5ms"),
|
||||
MakeTimeAccessor (&CoDelQueueDisc::m_target),
|
||||
MakeTimeChecker ())
|
||||
.AddAttribute ("CeThreshold",
|
||||
"The CoDel CE threshold for marking packets",
|
||||
TimeValue (Time::Max ()),
|
||||
MakeTimeAccessor (&CoDelQueueDisc::m_ceThreshold),
|
||||
MakeTimeChecker ())
|
||||
.AddTraceSource ("Count",
|
||||
"CoDel count",
|
||||
MakeTraceSourceAccessor (&CoDelQueueDisc::m_count),
|
||||
@@ -258,17 +268,25 @@ CoDelQueueDisc::DoDequeue (void)
|
||||
m_state2++;
|
||||
while (m_dropping && CoDelTimeAfterEq (now, m_dropNext))
|
||||
{
|
||||
++m_count;
|
||||
m_recInvSqrt = NewtonStep (m_recInvSqrt, m_count);
|
||||
// It's time for the next drop. Drop the current packet and
|
||||
// dequeue the next. The dequeue might take us out of dropping
|
||||
// state. If not, schedule the next drop.
|
||||
// A large amount of packets in queue might result in drop
|
||||
// rates so high that the next drop should happen now,
|
||||
// hence the while loop.
|
||||
if (m_useEcn && Mark (item, TARGET_EXCEEDED_MARK))
|
||||
{
|
||||
NS_LOG_LOGIC ("Sojourn time is still above target and it's time for next drop or mark; marking " << item);
|
||||
NS_LOG_LOGIC ("Running ControlLaw for input m_dropNext: " << (double)m_dropNext / 1000000);
|
||||
m_dropNext = ControlLaw (now, Time2CoDel (m_interval), m_recInvSqrt);
|
||||
NS_LOG_LOGIC ("Scheduled next drop at " << (double) m_dropNext / 1000000);
|
||||
goto end;
|
||||
}
|
||||
NS_LOG_LOGIC ("Sojourn time is still above target and it's time for next drop; dropping " << item);
|
||||
DropAfterDequeue (item, TARGET_EXCEEDED_DROP);
|
||||
|
||||
++m_count;
|
||||
m_recInvSqrt = NewtonStep (m_recInvSqrt, m_count);
|
||||
item = GetInternalQueue (0)->Dequeue ();
|
||||
|
||||
if (item)
|
||||
@@ -301,20 +319,24 @@ CoDelQueueDisc::DoDequeue (void)
|
||||
NS_LOG_LOGIC ("Not in dropping state; decide if we have to enter the state and drop the first packet");
|
||||
if (okToDrop)
|
||||
{
|
||||
// Drop the first packet and enter dropping state unless the queue is empty
|
||||
NS_LOG_LOGIC ("Sojourn time goes above target, dropping the first packet " << item << " and entering the dropping state");
|
||||
DropAfterDequeue (item, TARGET_EXCEEDED_DROP);
|
||||
|
||||
item = GetInternalQueue (0)->Dequeue ();
|
||||
|
||||
if (item)
|
||||
if (m_useEcn && Mark (item, TARGET_EXCEEDED_MARK))
|
||||
{
|
||||
NS_LOG_LOGIC ("Popped " << item);
|
||||
NS_LOG_LOGIC ("Number packets remaining " << GetInternalQueue (0)->GetNPackets ());
|
||||
NS_LOG_LOGIC ("Number bytes remaining " << GetInternalQueue (0)->GetNBytes ());
|
||||
NS_LOG_LOGIC ("Sojourn time goes above target, marking the first packet " << item << " and entering the dropping state");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Drop the first packet and enter dropping state unless the queue is empty
|
||||
NS_LOG_LOGIC ("Sojourn time goes above target, dropping the first packet " << item << " and entering the dropping state");
|
||||
DropAfterDequeue (item, TARGET_EXCEEDED_DROP);
|
||||
item = GetInternalQueue (0)->Dequeue ();
|
||||
if (item)
|
||||
{
|
||||
NS_LOG_LOGIC ("Popped " << item);
|
||||
NS_LOG_LOGIC ("Number packets remaining " << GetInternalQueue (0)->GetNPackets ());
|
||||
NS_LOG_LOGIC ("Number bytes remaining " << GetInternalQueue (0)->GetNBytes ());
|
||||
}
|
||||
OkToDrop (item, now);
|
||||
}
|
||||
|
||||
OkToDrop (item, now);
|
||||
m_dropping = true;
|
||||
++m_state3;
|
||||
/*
|
||||
@@ -339,6 +361,12 @@ CoDelQueueDisc::DoDequeue (void)
|
||||
NS_LOG_LOGIC ("Scheduled next drop at " << (double)m_dropNext / 1000000 << " now " << (double)now / 1000000);
|
||||
}
|
||||
}
|
||||
end:
|
||||
uint32_t ldelay = Time2CoDel (Simulator::Now () - item->GetTimeStamp ());
|
||||
if (item && m_useEcn && CoDelTimeAfter (ldelay, Time2CoDel (m_ceThreshold)) && Mark (item, CE_THRESHOLD_EXCEEDED_MARK))
|
||||
{
|
||||
NS_LOG_LOGIC ("Marking due to CeThreshold " << m_ceThreshold.GetSeconds ());
|
||||
}
|
||||
++m_states;
|
||||
return item;
|
||||
}
|
||||
@@ -364,25 +392,25 @@ CoDelQueueDisc::GetDropNext (void)
|
||||
bool
|
||||
CoDelQueueDisc::CoDelTimeAfter (uint32_t a, uint32_t b)
|
||||
{
|
||||
return ((int)(a) - (int)(b) > 0);
|
||||
return ((int64_t)(a) - (int64_t)(b) > 0);
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueueDisc::CoDelTimeAfterEq (uint32_t a, uint32_t b)
|
||||
{
|
||||
return ((int)(a) - (int)(b) >= 0);
|
||||
return ((int64_t)(a) - (int64_t)(b) >= 0);
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueueDisc::CoDelTimeBefore (uint32_t a, uint32_t b)
|
||||
{
|
||||
return ((int)(a) - (int)(b) < 0);
|
||||
return ((int64_t)(a) - (int64_t)(b) < 0);
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueueDisc::CoDelTimeBeforeEq (uint32_t a, uint32_t b)
|
||||
{
|
||||
return ((int)(a) - (int)(b) <= 0);
|
||||
return ((int64_t)(a) - (int64_t)(b) <= 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
||||
@@ -101,6 +101,9 @@ public:
|
||||
// Reasons for dropping packets
|
||||
static constexpr const char* TARGET_EXCEEDED_DROP = "Target exceeded drop"; //!< Sojourn time above target
|
||||
static constexpr const char* OVERLIMIT_DROP = "Overlimit drop"; //!< Overlimit dropped packet
|
||||
// Reasons for marking packets
|
||||
static constexpr const char* TARGET_EXCEEDED_MARK = "Target exceeded mark"; //!< Sojourn time above target
|
||||
static constexpr const char* CE_THRESHOLD_EXCEEDED_MARK = "CE threshold exceeded mark"; //!< Sojourn time above CE threshold
|
||||
|
||||
private:
|
||||
friend class::CoDelQueueDiscNewtonStepTest; // Test code
|
||||
@@ -198,9 +201,11 @@ private:
|
||||
|
||||
virtual void InitializeParams (void);
|
||||
|
||||
bool m_useEcn; //!< True if ECN is used (packets are marked instead of being dropped)
|
||||
uint32_t m_minBytes; //!< Minimum bytes in queue to allow a packet drop
|
||||
Time m_interval; //!< 100 ms sliding minimum time window width
|
||||
Time m_target; //!< 5 ms target queue delay
|
||||
Time m_ceThreshold; //!< Threshold above which to CE mark
|
||||
TracedValue<uint32_t> m_count; //!< Number of packets dropped since entering drop state
|
||||
TracedValue<uint32_t> m_lastCount; //!< Last number of packets dropped since entering drop state
|
||||
TracedValue<bool> m_dropping; //!< True if in dropping state
|
||||
|
||||
Reference in New Issue
Block a user