Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3e26a68f4 | |||
| 937c3c388c | |||
| a64d062b49 |
@@ -49,4 +49,8 @@ src/ndnSIM
|
||||
configure
|
||||
toggle
|
||||
.ns3rc
|
||||
.cproject
|
||||
.project
|
||||
.settings/
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,8 @@ all:
|
||||
|
||||
# free free to change this part to suit your requirements
|
||||
configure:
|
||||
./waf configure --enable-examples --enable-tests
|
||||
#./waf configure --enable-examples --enable-tests
|
||||
./waf configure -d optimized --enable-examples --disable-python --disable-tests
|
||||
|
||||
build:
|
||||
./waf build
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* \file
|
||||
@@ -752,6 +753,10 @@ TypeId::LookupByName (std::string name)
|
||||
{
|
||||
NS_LOG_FUNCTION (name);
|
||||
uint16_t uid = IidManager::Get ()->GetUid (name);
|
||||
if (uid == 0){
|
||||
std::cout << "Name " << name << " not found!!\n";
|
||||
}
|
||||
assert(uid != 0);
|
||||
NS_ASSERT_MSG (uid != 0, "Assert in TypeId::LookupByName: " << name << " not found");
|
||||
return TypeId (uid);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,503 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew McGregor
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Codel, the COntrolled DELay Queueing discipline
|
||||
* Based on ns2 simulation code presented by Kathie Nichols
|
||||
*
|
||||
* This port based on linux kernel code by
|
||||
* Authors: Dave Täht <d@taht.net>
|
||||
* Eric Dumazet <edumazet@google.com>
|
||||
*
|
||||
* Ported to ns-3 by: Andrew McGregor <andrewmcgr@gmail.com>
|
||||
*/
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/enum.h"
|
||||
#include "ns3/uinteger.h"
|
||||
#include "ns3/abort.h"
|
||||
#include "codel-queue2.h"
|
||||
#include <assert.h>
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("CoDelQueue2");
|
||||
|
||||
/**
|
||||
* Performs a reciprocal divide, similar to the
|
||||
* Linux kernel reciprocal_divide function
|
||||
* \param A numerator
|
||||
* \param R reciprocal of the denominator B
|
||||
* \return the value of A/B
|
||||
*/
|
||||
/* borrowed from the linux kernel */
|
||||
|
||||
static inline uint64_t
|
||||
ReciprocalDivide(uint64_t A, uint64_t R)
|
||||
{
|
||||
return (uint64_t) (((uint64_t) A * R) >> 32);
|
||||
}
|
||||
|
||||
/* end kernel borrowings */
|
||||
|
||||
/**
|
||||
* Returns the current time translated in CoDel time representation
|
||||
* \return the current time
|
||||
*/
|
||||
static uint64_t
|
||||
CoDelGetTime(void)
|
||||
{
|
||||
Time time = Simulator::Now();
|
||||
uint64_t ns = time.GetNanoSeconds();
|
||||
|
||||
return ns >> CODEL2_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* CoDel time stamp, used to carry CoDel time informations.
|
||||
*/
|
||||
class CoDelTimestampTag : public Tag
|
||||
{
|
||||
public:
|
||||
CoDelTimestampTag();
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId
|
||||
GetTypeId(void);
|
||||
virtual TypeId
|
||||
GetInstanceTypeId(void) const;
|
||||
|
||||
virtual uint32_t
|
||||
GetSerializedSize(void) const;
|
||||
virtual void
|
||||
Serialize(TagBuffer i) const;
|
||||
virtual void
|
||||
Deserialize(TagBuffer i);
|
||||
virtual void
|
||||
Print(std::ostream &os) const;
|
||||
|
||||
/**
|
||||
* Gets the Tag creation time
|
||||
* @return the time object stored in the tag
|
||||
*/
|
||||
Time
|
||||
GetTxTime(void) const;
|
||||
private:
|
||||
uint64_t m_creationTime; //!< Tag creation time
|
||||
};
|
||||
|
||||
NS_OBJECT_ENSURE_REGISTERED (CoDelQueue2);
|
||||
|
||||
TypeId
|
||||
CoDelQueue2::GetTypeId(void)
|
||||
{
|
||||
static TypeId tid =
|
||||
TypeId("ns3::CoDelQueue2").SetParent<Queue>().SetGroupName("Internet")
|
||||
.AddConstructor<CoDelQueue2>().AddAttribute("Mode",
|
||||
"Whether to use Bytes (see MaxBytes) or Packets (see MaxPackets) as the maximum queue size metric.",
|
||||
EnumValue(QUEUE_MODE_BYTES), MakeEnumAccessor(&CoDelQueue2::SetMode),
|
||||
MakeEnumChecker(QUEUE_MODE_BYTES, "QUEUE_MODE_BYTES", QUEUE_MODE_PACKETS,
|
||||
"QUEUE_MODE_PACKETS")).AddAttribute("MaxPackets",
|
||||
"The maximum number of packets accepted by this CoDelQueue.",
|
||||
UintegerValue(DEFAULT_CODEL_LIMIT),
|
||||
MakeUintegerAccessor(&CoDelQueue2::m_maxPackets),
|
||||
MakeUintegerChecker<uint32_t>()).AddAttribute("MaxBytes",
|
||||
"The maximum number of bytes accepted by this CoDelQueue.",
|
||||
UintegerValue(1500 * DEFAULT_CODEL_LIMIT),
|
||||
MakeUintegerAccessor(&CoDelQueue2::m_maxBytes), MakeUintegerChecker<uint32_t>())
|
||||
.AddAttribute("Interval", "The CoDel algorithm interval", StringValue("100ms"),
|
||||
MakeTimeAccessor(&CoDelQueue2::m_interval), MakeTimeChecker()).AddAttribute(
|
||||
"Target", "The CoDel algorithm target queue delay", StringValue("5ms"),
|
||||
MakeTimeAccessor(&CoDelQueue2::m_target), MakeTimeChecker()).AddTraceSource(
|
||||
"Count", "CoDel count", MakeTraceSourceAccessor(&CoDelQueue2::m_markedCount),
|
||||
"ns3::TracedValue::Uint32Callback").AddTraceSource("DropCount",
|
||||
"CoDel drop count", MakeTraceSourceAccessor(&CoDelQueue2::m_dropCount),
|
||||
"ns3::TracedValue::Uint32Callback").AddTraceSource("LastCount",
|
||||
"CoDel lastcount", MakeTraceSourceAccessor(&CoDelQueue2::m_lastCount),
|
||||
"ns3::TracedValue::Uint32Callback").AddTraceSource("BytesInQueue",
|
||||
"Number of bytes in the queue",
|
||||
MakeTraceSourceAccessor(&CoDelQueue2::m_bytesInQueue),
|
||||
"ns3::TracedValue::Uint32Callback").AddTraceSource("Sojourn",
|
||||
"Time in the queue", MakeTraceSourceAccessor(&CoDelQueue2::m_sojourn),
|
||||
"ns3::Time::TracedValueCallback").AddTraceSource("DropNext",
|
||||
"Time until next packet drop",
|
||||
MakeTraceSourceAccessor(&CoDelQueue2::m_nextMarkingTime),
|
||||
"ns3::TracedValue::Uint32Callback");
|
||||
|
||||
return tid;
|
||||
}
|
||||
|
||||
CoDelQueue2::CoDelQueue2()
|
||||
: Queue(),
|
||||
m_packets(),
|
||||
m_maxBytes(),
|
||||
m_bytesInQueue(0),
|
||||
m_markedCount(0),
|
||||
m_dropCount(0),
|
||||
m_lastCount(0),
|
||||
m_recInvSqrt(~0U >> REC_INV_SQRT_SHIFT),
|
||||
m_firstAboveTime(0),
|
||||
m_nextMarkingTime(0),
|
||||
m_state1(0),
|
||||
m_state2(0),
|
||||
m_state3(0),
|
||||
m_states(0),
|
||||
m_dropOverLimit(0),
|
||||
m_sojourn(0),
|
||||
m_overTargetForInterval(false),
|
||||
m_markNext(false)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
}
|
||||
|
||||
CoDelQueue2::~CoDelQueue2()
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
}
|
||||
|
||||
void
|
||||
CoDelQueue2::NewtonStep(void)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
uint32_t invsqrt = ((uint32_t) m_recInvSqrt) << REC_INV_SQRT_SHIFT;
|
||||
uint32_t invsqrt2 = ((uint64_t) invsqrt * invsqrt) >> 32;
|
||||
uint64_t val = (3ll << 32) - ((uint64_t) m_markedCount * invsqrt2);
|
||||
|
||||
val >>= 2; /* avoid overflow */
|
||||
val = (val * invsqrt) >> (32 - 2 + 1);
|
||||
m_recInvSqrt = val >> REC_INV_SQRT_SHIFT;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CoDelQueue2::getNextMarkingTime(uint64_t t)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
double rec_inv_sqrt = 1.1 / sqrt(m_markedCount);
|
||||
|
||||
uint64_t addTime = Time2CoDel(m_interval) * rec_inv_sqrt;
|
||||
|
||||
return t + addTime;
|
||||
}
|
||||
|
||||
void
|
||||
CoDelQueue2::SetMode(CoDelQueue2::QueueMode mode)
|
||||
{
|
||||
NS_LOG_FUNCTION(mode);
|
||||
m_mode = mode;
|
||||
}
|
||||
|
||||
CoDelQueue2::QueueMode
|
||||
CoDelQueue2::GetMode(void)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
return m_mode;
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueue2::DoEnqueue(Ptr<Packet> p)
|
||||
{
|
||||
NS_LOG_FUNCTION(this << p);
|
||||
|
||||
if (m_mode == QUEUE_MODE_PACKETS && (m_packets.size() + 1 > m_maxPackets)) {
|
||||
NS_LOG_LOGIC("Queue full (at max packets) -- droppping pkt");
|
||||
// std::cout << "Queue full (at max packets) -- droppping pkt";
|
||||
Drop(p);
|
||||
++m_dropOverLimit;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_mode == QUEUE_MODE_BYTES && (m_bytesInQueue + p->GetSize() > m_maxBytes)) {
|
||||
NS_LOG_LOGIC("Queue full (packet would exceed max bytes) -- droppping pkt");
|
||||
// std::cout << "Queue full (packet would exceed max bytes) -- droppping pkt";
|
||||
Drop(p);
|
||||
++m_dropOverLimit;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tag packet with current time for DoDequeue() to compute sojourn time
|
||||
CoDelTimestampTag tag;
|
||||
p->AddPacketTag(tag);
|
||||
|
||||
m_bytesInQueue += p->GetSize();
|
||||
m_packets.push(p);
|
||||
|
||||
NS_LOG_LOGIC("Number packets " << m_packets.size());
|
||||
NS_LOG_LOGIC("Number bytes " << m_bytesInQueue);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueue2::checkSojournTime(Ptr<Packet> p, uint64_t now)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
CoDelTimestampTag tag;
|
||||
|
||||
bool found = p->RemovePacketTag(tag);
|
||||
NS_ASSERT_MSG(found, "found a packet without an input timestamp tag");
|
||||
NS_UNUSED(found); //silence compiler warning
|
||||
Time delta = Simulator::Now() - tag.GetTxTime();
|
||||
NS_LOG_INFO("Sojourn time " << delta.GetSeconds());
|
||||
uint64_t sojournTime = Time2CoDel(delta);
|
||||
|
||||
assert(m_bytesInQueue >= 0);
|
||||
|
||||
// Sojourn time above target:
|
||||
if (CoDelTimeAfter(sojournTime, Time2CoDel(m_target))) {
|
||||
m_overTargetForInterval = false;
|
||||
|
||||
if (m_firstAboveTime == 0) {
|
||||
/* just went above from below. If we stay above
|
||||
* for at least q->interval we'll say it's ok to drop
|
||||
*/
|
||||
NS_LOG_LOGIC(
|
||||
"Sojourn time has just gone above target from below, need to stay above for "
|
||||
"at least q->interval before packet can be dropped. ");
|
||||
m_overTargetForInterval = false;
|
||||
m_firstAboveTime = now;
|
||||
}
|
||||
else {
|
||||
if (CoDelTimeAfter(now, (m_firstAboveTime + Time2CoDel(m_interval)))) {
|
||||
|
||||
/* Queue has been over limit for longer than interval!
|
||||
* Set class state to mark next packet:
|
||||
*/
|
||||
m_sojourn = delta;
|
||||
m_overTargetForInterval = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Sojourn time below target:
|
||||
else {
|
||||
NS_LOG_LOGIC("Sojourn time is below target");
|
||||
m_firstAboveTime = 0;
|
||||
m_overTargetForInterval = false;
|
||||
}
|
||||
return m_overTargetForInterval;
|
||||
}
|
||||
|
||||
Ptr<Packet>
|
||||
CoDelQueue2::DoDequeue(void)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
assert(m_bytesInQueue >= 0);
|
||||
|
||||
// If queue is empty: leave marking state
|
||||
if (m_packets.empty()) {
|
||||
m_overTargetForInterval = false;
|
||||
m_firstAboveTime = 0;
|
||||
NS_LOG_LOGIC("Queue empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t now = CoDelGetTime();
|
||||
Ptr<Packet> p = m_packets.front();
|
||||
m_packets.pop();
|
||||
m_bytesInQueue -= p->GetSize();
|
||||
|
||||
NS_LOG_LOGIC("Popped " << p);
|
||||
NS_LOG_LOGIC("Number packets remaining " << m_packets.size());
|
||||
NS_LOG_LOGIC("Number bytes remaining " << m_bytesInQueue);
|
||||
|
||||
bool okToMark = checkSojournTime(p, now);
|
||||
|
||||
// If sojourn time over target for at least interval: Mark packets according
|
||||
// to decreasing interval length
|
||||
if (okToMark) {
|
||||
|
||||
if (CoDelTimeAfterEq(now, m_nextMarkingTime)) {
|
||||
++m_markedCount;
|
||||
|
||||
m_markNext = true;
|
||||
m_nextMarkingTime = getNextMarkingTime(now);
|
||||
}
|
||||
}
|
||||
// If sojourn time falls below target: Reset markedCount
|
||||
else {
|
||||
m_markedCount = 0;
|
||||
}
|
||||
++m_states;
|
||||
return p;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CoDelQueue2::GetQueueSize(void)
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
if (GetMode() == QUEUE_MODE_BYTES) {
|
||||
return m_bytesInQueue;
|
||||
}
|
||||
else if (GetMode() == QUEUE_MODE_PACKETS) {
|
||||
return m_packets.size();
|
||||
}
|
||||
else {
|
||||
NS_ABORT_MSG("Unknown mode.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CoDelQueue2::GetDropOverLimit(void)
|
||||
{
|
||||
return m_dropOverLimit;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CoDelQueue2::GetDropCount(void)
|
||||
{
|
||||
return m_dropCount;
|
||||
}
|
||||
|
||||
Time
|
||||
CoDelQueue2::GetTarget(void)
|
||||
{
|
||||
return m_target;
|
||||
}
|
||||
|
||||
Time
|
||||
CoDelQueue2::GetInterval(void)
|
||||
{
|
||||
return m_interval;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
CoDelQueue2::GetDropNext(void)
|
||||
{
|
||||
return m_nextMarkingTime;
|
||||
}
|
||||
|
||||
Ptr<const Packet>
|
||||
CoDelQueue2::DoPeek(void) const
|
||||
{
|
||||
NS_LOG_FUNCTION(this);
|
||||
|
||||
if (m_packets.empty()) {
|
||||
NS_LOG_LOGIC("Queue empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Ptr<Packet> p = m_packets.front();
|
||||
|
||||
NS_LOG_LOGIC("Number packets " << m_packets.size());
|
||||
NS_LOG_LOGIC("Number bytes " << m_bytesInQueue);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueue2::CoDelTimeAfter(uint64_t a, uint64_t b)
|
||||
{
|
||||
return ((int64_t) (a) - (int64_t) (b) > 0);
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueue2::CoDelTimeAfterEq(uint64_t a, uint64_t b)
|
||||
{
|
||||
return ((int64_t) (a) - (int64_t) (b) >= 0);
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueue2::CoDelTimeBefore(uint64_t a, uint64_t b)
|
||||
{
|
||||
return ((int64_t) (a) - (int64_t) (b) < 0);
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueue2::CoDelTimeBeforeEq(uint64_t a, uint64_t b)
|
||||
{
|
||||
return ((int64_t) (a) - (int64_t) (b) <= 0);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CoDelQueue2::Time2CoDel(Time t)
|
||||
{
|
||||
return (t.GetNanoSeconds() >> CODEL2_SHIFT);
|
||||
}
|
||||
|
||||
void
|
||||
CoDelQueue2::Drop(Ptr<Packet> p)
|
||||
{
|
||||
m_nTotalDroppedPackets++;
|
||||
m_nTotalDroppedBytes += p->GetSize();
|
||||
|
||||
NS_LOG_LOGIC("m_traceDrop (p)");
|
||||
|
||||
Queue::Drop(p);
|
||||
}
|
||||
|
||||
//bool CoDelQueue2::isInDroppingState()
|
||||
//{
|
||||
// return m_dropping.Get();
|
||||
//}
|
||||
|
||||
bool
|
||||
CoDelQueue2::traceOkToDrop()
|
||||
{
|
||||
return m_overTargetForInterval;
|
||||
}
|
||||
|
||||
// TODO: Make sure to only call this at one place!
|
||||
bool
|
||||
CoDelQueue2::isOkToMark()
|
||||
{
|
||||
if (m_markNext) {
|
||||
m_markNext = false;
|
||||
if (m_overTargetForInterval == false) {
|
||||
std::cout << "Marking next packet, but sojourn time fell below target value!\n";
|
||||
}
|
||||
return m_overTargetForInterval;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CoDelQueue2::isQueueOverLimit(double limit)
|
||||
{
|
||||
assert(limit >= 0 && limit <= 1);
|
||||
if (m_bytesInQueue > m_maxBytes * limit || m_packets.size() > m_maxPackets * limit) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t
|
||||
CoDelQueue2::getTimeOverLimitInNS()
|
||||
{
|
||||
uint64_t now = CoDelGetTime();
|
||||
|
||||
if (m_firstAboveTime == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
if (((int64_t)now - (int64_t)m_firstAboveTime) < 0){
|
||||
std::cout << "ERROR: firstAboveTime shouldn't be after current time!\n";
|
||||
}
|
||||
return (now - m_firstAboveTime);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -0,0 +1,318 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2012 Andrew McGregor
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Codel, the COntrolled DELay Queueing discipline
|
||||
* Based on ns2 simulation code presented by Kathie Nichols
|
||||
*
|
||||
* This port based on linux kernel code by
|
||||
* Authors: Dave Täht <d@taht.net>
|
||||
* Eric Dumazet <edumazet@google.com>
|
||||
*
|
||||
* Ported to ns-3 by: Andrew McGregor <andrewmcgr@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef CODEL_2_H
|
||||
#define CODEL_2_H
|
||||
|
||||
#include <queue>
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/queue.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/string.h"
|
||||
#include "ns3/traced-value.h"
|
||||
#include "ns3/trace-source-accessor.h"
|
||||
|
||||
namespace ns3 {
|
||||
class TypeId;
|
||||
} /* namespace ns3 */
|
||||
|
||||
class CoDelQueueNewtonStepTest;
|
||||
// Forward declaration for unit test
|
||||
class CoDelQueueControlLawTest;
|
||||
// Forward declaration for unit test
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* Number of bits discarded from the time representation.
|
||||
* The time is assumed to be in nanoseconds.
|
||||
*/
|
||||
static const int CODEL2_SHIFT = 0;
|
||||
|
||||
#define DEFAULT_CODEL_LIMIT 1000
|
||||
#define REC_INV_SQRT_BITS (8 * sizeof(uint16_t))
|
||||
#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS)
|
||||
|
||||
class TraceContainer;
|
||||
|
||||
/**
|
||||
* \ingroup queue
|
||||
*
|
||||
* \brief New Codel Queue class for monitoring queue status and marking packets.
|
||||
*
|
||||
* Increases the timing accuracy to 64 bit.
|
||||
* Also ads some functions to access the queue status from outside this class.
|
||||
*
|
||||
*/
|
||||
|
||||
class CoDelQueue2: public Queue
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Get the type ID.
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId
|
||||
GetTypeId(void);
|
||||
|
||||
/**
|
||||
* \brief CoDelQueue Constructor
|
||||
*
|
||||
* Creates a CoDel queue
|
||||
*/
|
||||
CoDelQueue2();
|
||||
|
||||
virtual
|
||||
~CoDelQueue2();
|
||||
|
||||
/**
|
||||
* \brief Set the operating mode of this device.
|
||||
*
|
||||
* \param mode The operating mode of this device.
|
||||
*/
|
||||
void
|
||||
SetMode(CoDelQueue2::QueueMode mode);
|
||||
|
||||
// bool isInDroppingState();
|
||||
|
||||
/**
|
||||
* \brief Return time over limit in Nanoseconds
|
||||
*/
|
||||
int64_t
|
||||
getTimeOverLimitInNS();
|
||||
|
||||
/**
|
||||
* \brief Returns if queue size is over *limit* percentage of the queue size.
|
||||
* This applies to either maxBytes ore maxPackets
|
||||
*/
|
||||
bool
|
||||
isQueueOverLimit(double limit = 0.9);
|
||||
|
||||
/**
|
||||
* \brief Get the encapsulation mode of this device.
|
||||
*
|
||||
* \returns The encapsulation mode of this device.
|
||||
*/
|
||||
CoDelQueue2::QueueMode
|
||||
GetMode(void);
|
||||
|
||||
/**
|
||||
* \brief Get the current value of the queue in bytes or packets.
|
||||
*
|
||||
* \returns The queue size in bytes or packets.
|
||||
*/
|
||||
uint32_t
|
||||
GetQueueSize(void);
|
||||
|
||||
/**
|
||||
* \brief Get the number of packets dropped when packets
|
||||
* arrive at a full queue and cannot be enqueued.
|
||||
*
|
||||
* \returns The number of dropped packets
|
||||
*/
|
||||
uint32_t
|
||||
GetDropOverLimit(void);
|
||||
|
||||
/**
|
||||
* \brief Get the number of packets dropped according to CoDel algorithm
|
||||
*
|
||||
* \returns The number of dropped packets
|
||||
*/
|
||||
uint32_t
|
||||
GetDropCount(void);
|
||||
|
||||
/**
|
||||
* \brief Get the target queue delay
|
||||
*
|
||||
* \returns The target queue delay
|
||||
*/
|
||||
Time
|
||||
GetTarget(void);
|
||||
|
||||
/**
|
||||
* \brief Get the interval
|
||||
*
|
||||
* \returns The interval
|
||||
*/
|
||||
Time
|
||||
GetInterval(void);
|
||||
|
||||
/**
|
||||
* \brief Get the time for next packet drop while in the dropping state
|
||||
*
|
||||
* \returns The time for next packet drop
|
||||
*/
|
||||
uint32_t
|
||||
GetDropNext(void);
|
||||
|
||||
/**
|
||||
* Returns true if next packet would have been dropped according to Codel logic.
|
||||
* Also resets m_marknext to 0;
|
||||
*/
|
||||
bool
|
||||
isOkToMark();
|
||||
|
||||
private:
|
||||
|
||||
bool
|
||||
traceOkToDrop();
|
||||
|
||||
friend class ::CoDelQueueNewtonStepTest; // Test code
|
||||
friend class ::CoDelQueueControlLawTest; // Test code
|
||||
/**
|
||||
* \brief Add a packet to the queue
|
||||
*
|
||||
* \param p The packet to be added
|
||||
* \returns True if the packet can be added, False if the packet is dropped due to full queue
|
||||
*/
|
||||
virtual bool
|
||||
DoEnqueue(Ptr<Packet> p);
|
||||
|
||||
void
|
||||
Drop(Ptr<Packet> p);
|
||||
|
||||
/**
|
||||
* \brief Remove a packet from queue based on the current state
|
||||
* If we are in dropping state, check if we could leave the dropping state
|
||||
* or if we should perform next drop
|
||||
* If we are not currently in dropping state, check if we need to enter the state
|
||||
* and drop the first packet
|
||||
*
|
||||
* \returns The packet that is examined
|
||||
*/
|
||||
virtual Ptr<Packet>
|
||||
DoDequeue(void);
|
||||
|
||||
virtual Ptr<const Packet>
|
||||
DoPeek(void) const;
|
||||
|
||||
/**
|
||||
* \brief Calculate the reciprocal square root of m_count by using Newton's method
|
||||
* http://en.wikipedia.org/wiki/
|
||||
* Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots
|
||||
* m_recInvSqrt (new) = (m_recInvSqrt (old) / 2) * (3 - m_count * m_recInvSqrt^2)
|
||||
*/
|
||||
void
|
||||
NewtonStep(void);
|
||||
|
||||
/**
|
||||
* \brief Determine the time for next packet mark.
|
||||
* CoDel control law is t + m_interval/sqrt(m_count).
|
||||
* Here, we use m_recInvSqrt calculated by Newton's method in NewtonStep() to avoid
|
||||
* both sqrt() and divide operations
|
||||
*
|
||||
* \param t Current next drop time
|
||||
* \returns The new next drop time:
|
||||
*/
|
||||
uint64_t
|
||||
getNextMarkingTime(uint64_t t);
|
||||
|
||||
/**
|
||||
* \brief Determine whether a packet is OK to be dropped. The packet
|
||||
* may not be actually dropped (depending on the drop state)
|
||||
*
|
||||
* \param p The packet that is considered
|
||||
* \param now The current time represented as 32-bit unsigned integer (us)
|
||||
* \returns True if it is OK to drop the packet (sojourn time above target for at least interval)
|
||||
*/
|
||||
// bool OkToDrop(Ptr<Packet> p, uint64_t now);
|
||||
bool
|
||||
checkSojournTime(Ptr<Packet> p, uint64_t now);
|
||||
|
||||
/**
|
||||
* Check if CoDel time a is successive to b
|
||||
* @param a left operand
|
||||
* @param b right operand
|
||||
* @return true if a is greater than b
|
||||
*/
|
||||
bool
|
||||
CoDelTimeAfter(uint64_t a, uint64_t b);
|
||||
/**
|
||||
* Check if CoDel time a is successive or equal to b
|
||||
* @param a left operand
|
||||
* @param b right operand
|
||||
* @return true if a is greater than or equal to b
|
||||
*/
|
||||
bool
|
||||
CoDelTimeAfterEq(uint64_t a, uint64_t b);
|
||||
/**
|
||||
* Check if CoDel time a is preceding b
|
||||
* @param a left operand
|
||||
* @param b right operand
|
||||
* @return true if a is less than to b
|
||||
*/
|
||||
bool
|
||||
CoDelTimeBefore(uint64_t a, uint64_t b);
|
||||
/**
|
||||
* Check if CoDel time a is preceding or equal to b
|
||||
* @param a left operand
|
||||
* @param b right operand
|
||||
* @return true if a is less than or equal to b
|
||||
*/
|
||||
bool
|
||||
CoDelTimeBeforeEq(uint64_t a, uint64_t b);
|
||||
|
||||
/**
|
||||
* returned unsigned 32-bit integer representation of the input Time object
|
||||
* units are microseconds
|
||||
*/
|
||||
uint64_t
|
||||
Time2CoDel(Time t);
|
||||
|
||||
std::queue<Ptr<Packet> > m_packets; //!< The packet queue
|
||||
uint32_t m_maxPackets; //!< Max # of packets accepted by the queue
|
||||
uint32_t m_maxBytes; //!< Max # of bytes accepted by the queue
|
||||
TracedValue<int64_t> m_bytesInQueue; //!< The total number of bytes in queue
|
||||
// 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
|
||||
TracedValue<uint32_t> m_markedCount; //!< Number of packets marked since entering marking state
|
||||
TracedValue<uint32_t> m_dropCount; //!< Number of dropped packets according CoDel algorithm
|
||||
TracedValue<uint32_t> m_lastCount; //!< Last number of packets dropped since entering drop state
|
||||
uint16_t m_recInvSqrt; //!< Reciprocal inverse square root
|
||||
uint64_t m_firstAboveTime; //!< Time to declare sojourn time above target
|
||||
TracedValue<uint64_t> m_nextMarkingTime; //!< Time to drop next packet
|
||||
uint32_t m_state1; //!< Number of times packet sojourn goes above target for interval
|
||||
uint32_t m_state2; //!< Number of times we perform next drop while in dropping state
|
||||
uint32_t m_state3; //!< Number of times we enter drop state and drop the fist packet
|
||||
uint32_t m_states; //!< Total number of times we are in state 1, state 2, or state 3
|
||||
uint32_t m_dropOverLimit; //!< The number of packets dropped due to full queue
|
||||
QueueMode m_mode; //!< The operating mode (Bytes or packets)
|
||||
TracedValue<Time> m_sojourn; //!< Time in queue
|
||||
|
||||
// True if sojourn time has been higher than m_target for at m_interval
|
||||
bool m_overTargetForInterval;
|
||||
|
||||
// Mark next packet? Spaced out by the Codel ControlLaw logic
|
||||
bool m_markNext;
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
#endif /* CODEL_H */
|
||||
@@ -190,6 +190,7 @@ def build(bld):
|
||||
'model/global-route-manager-impl.cc',
|
||||
'model/candidate-queue.cc',
|
||||
'model/codel-queue.cc',
|
||||
'model/codel-queue2.cc',
|
||||
'model/ipv4-global-routing.cc',
|
||||
'helper/ipv4-global-routing-helper.cc',
|
||||
'helper/internet-stack-helper.cc',
|
||||
|
||||
Reference in New Issue
Block a user