bool CobaltQueueDisc::CobaltShouldDrop()

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;
}