in simulation/src/traffic-control/model/cobalt-queue-disc.cc [432:545]
bool CobaltQueueDisc::CobaltShouldDrop (Ptr<QueueDiscItem> item, int64_t now)
{
NS_LOG_FUNCTION (this);
bool drop = false;
/* Simplified Codel implementation */
Time delta = Simulator::Now () - item->GetTimeStamp ();
NS_LOG_INFO ("Sojourn time " << delta.As (Time::S));
int64_t sojournTime = Time2CoDel (delta);
int64_t schedule = now - m_dropNext;
bool over_target = CoDelTimeAfter (sojournTime, Time2CoDel (m_target));
bool next_due = m_count && schedule >= 0;
bool isMarked = false;
// If L4S mode is enabled then check if the packet is ECT1 or CE and
// if sojourn time is greater than CE threshold then the packet is marked.
// If packet is marked succesfully then the CoDel steps can be skipped.
if (item && m_useL4s)
{
uint8_t tosByte = 0;
if (item->GetUint8Value (QueueItem::IP_DSFIELD, tosByte) && (((tosByte & 0x3) == 1) || (tosByte & 0x3) == 3))
{
if ((tosByte & 0x3) == 1)
{
NS_LOG_DEBUG ("ECT1 packet " << static_cast<uint16_t> (tosByte & 0x3));
}
else
{
NS_LOG_DEBUG ("CE packet " << static_cast<uint16_t> (tosByte & 0x3));
}
if (CoDelTimeAfter (sojournTime, Time2CoDel (m_ceThreshold)) && Mark (item, CE_THRESHOLD_EXCEEDED_MARK))
{
NS_LOG_LOGIC ("Marking due to CeThreshold " << m_ceThreshold.GetSeconds ());
}
return false;
}
}
if (over_target)
{
if (!m_dropping)
{
m_dropping = true;
m_dropNext = ControlLaw (now);
}
if (!m_count)
{
m_count = 1;
}
}
else if (m_dropping)
{
m_dropping = false;
}
if (next_due && m_dropping)
{
/* Check for marking possibility only if BLUE decides NOT to drop. */
/* Check if router and packet, both have ECN enabled. Only if this is true, mark the packet. */
isMarked = (m_useEcn && Mark (item, FORCED_MARK));
drop = !isMarked;
m_count = std::max (m_count, m_count + 1);
InvSqrt ();
m_dropNext = ControlLaw (m_dropNext);
schedule = now - m_dropNext;
}
else
{
while (next_due)
{
m_count--;
InvSqrt ();
m_dropNext = ControlLaw (m_dropNext);
schedule = now - m_dropNext;
next_due = m_count && schedule >= 0;
}
}
// If CE threshold is enabled then isMarked flag is used to determine whether
// packet is marked and if the packet is marked then a second attempt at marking should be suppressed.
// If UseL4S attribute is enabled then ECT0 packets should not be marked.
if (!isMarked && !m_useL4s && m_useEcn && CoDelTimeAfter (sojournTime, Time2CoDel (m_ceThreshold)) && Mark (item, CE_THRESHOLD_EXCEEDED_MARK))
{
NS_LOG_LOGIC ("Marking due to CeThreshold " << m_ceThreshold.GetSeconds ());
}
// Enable Blue Enhancement if sojourn time is greater than blueThreshold and its been m_target time until the last time blue was updated
if (CoDelTimeAfter (sojournTime, Time2CoDel (m_blueThreshold)) && CoDelTimeAfter ((now - m_lastUpdateTimeBlue), Time2CoDel (m_target)))
{
m_pDrop = std::min (m_pDrop + m_increment, (double)1.0);
m_lastUpdateTimeBlue = now;
}
/* Simple BLUE implementation. Lack of ECN is deliberate. */
if (m_pDrop)
{
double u = m_uv->GetValue ();
drop = drop | (u < m_pDrop);
}
/* Overload the drop_next field as an activity timeout */
if (!m_count)
{
m_dropNext = now + Time2CoDel (m_interval);
}
else if (schedule > 0 && !drop)
{
m_dropNext = now;
}
return drop;
}