--- a/src/bridge/model/bridge-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/bridge/model/bridge-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -112,6 +112,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
virtual bool SupportsSendFrom () const;
+ virtual bool IsReady (void) const { return true; }
virtual Address GetMulticast (Ipv6Address addr) const;
protected:
--- a/src/csma/model/csma-net-device.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/csma/model/csma-net-device.cc Fri Jan 16 15:57:07 2015 -0800
@@ -153,7 +153,8 @@
}
CsmaNetDevice::CsmaNetDevice ()
- : m_linkUp (false)
+ : m_linkUp (false),
+ m_isReady (true)
{
NS_LOG_FUNCTION (this);
m_txMachineState = READY;
@@ -1019,4 +1020,11 @@
return m_backoff.AssignStreams (stream);
}
+bool
+CsmaNetDevice::IsReady (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_isReady;
+}
+
} // namespace ns3
--- a/src/csma/model/csma-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/csma/model/csma-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -350,6 +350,11 @@
*/
void AddHeader (Ptr<Packet> p, Mac48Address source, Mac48Address dest, uint16_t protocolNumber);
+ /**
+ * \return true if this interface is ready for a packet from the higher layer
+ */
+ virtual bool IsReady (void) const;
+
private:
/**
@@ -704,6 +709,12 @@
bool m_linkUp;
/**
+ * Flag indicating whether or not the device will accept packets from
+ * the higher layer.
+ */
+ bool m_isReady;
+
+ /**
* List of callbacks to fire if the link changes state (up or down).
*/
TracedCallback<> m_linkChangeCallbacks;
--- a/src/fd-net-device/model/fd-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/fd-net-device/model/fd-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -168,6 +168,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
virtual bool SupportsSendFrom () const;
+ virtual bool IsReady (void) const { return true; }
virtual Address GetMulticast (Ipv6Address addr) const;
virtual void SetIsBroadcast (bool broadcast);
--- a/src/internet-queues/examples/bench-queue.cc Thu Nov 06 15:18:11 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright 2013-14 University of Washington
- *
- * 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
- *
- */
-
-// This program is intended to benchmark packet enqueuing/dequeuing for
-// different internet-aware packet queues, for which the operations of
-// the queue may require modifying/deserializing packet headers (which
-// may incur a performance hit).
-//
-// It is recommended when testing to build this as optimized code.
-//
-// By default, it will generate, enqueue, and dequeue packets according
-// to a poisson process. IPv4 headers with random valid field values
-// will be added to the test packets. It will run for 10000 seconds by
-// default, with DropTailQueue, and generate about 10000 packets.
-//
-// The key arguments are:
-// "--queueType=" (possible values DropTailQueue and PfifoFastQueue)
-// "--stopTime=" (use this to extend the simulation time; simulation will
-// stop at this time)
-// "--maxPackets=" (use this to send a specified number of packets; if set,
-// then the stop time will be ignored)
-
-#include <fstream>
-#include <sstream>
-#include <iostream>
-#include <string>
-#include <vector>
-#include <algorithm>
-
-#include "ns3/packet.h"
-#include "ns3/drop-tail-queue.h"
-#include "ns3/pfifo-fast-queue.h"
-#include "ns3/uinteger.h"
-#include "ns3/simulator.h"
-#include "ns3/nstime.h"
-#include "ns3/double.h"
-#include "ns3/enum.h"
-#include "ns3/log.h"
-#include "ns3/ipv4-header.h"
-#include "ns3/abort.h"
-#include "ns3/command-line.h"
-#include "ns3/random-variable-stream.h"
-
-using namespace ns3;
-
-NS_LOG_COMPONENT_DEFINE ("BenchQueue");
-
-class Enqueuer
-{
-public:
- Enqueuer () : m_num (0), m_maxPackets (0) {}
- Enqueuer (uint32_t maxPackets) : m_num (0), m_maxPackets (maxPackets) {}
- void SetQueue (Ptr<Queue> queue) { m_queue = queue; }
- void SetGenerator (Ptr<RandomVariableStream> var) { m_intervalDist = var; }
- void SetSize (Ptr<RandomVariableStream> var) { m_sizeDist = var; }
- void SetProto (Ptr<RandomVariableStream> var) { m_protoDist = var; }
- void SetSrc (Ptr<RandomVariableStream> var) { m_srcDist = var; }
- void SetDst (Ptr<RandomVariableStream> var) { m_dstDist = var; }
- void SetSrcPort (Ptr<RandomVariableStream> var) { m_srcPortDist = var; }
- void SetDstPort (Ptr<RandomVariableStream> var) { m_dstPortDist = var; }
- void SetTos (Ptr<RandomVariableStream> var) { m_tosDist = var; }
- void Start (void) { Simulator::Schedule (Seconds (m_intervalDist->GetValue ()), &Enqueuer::Generate, this); }
- uint32_t GetNum () const { return m_num; }
-
-private:
- void Generate (void);
- Ptr<Queue> m_queue;
- Ptr<RandomVariableStream> m_intervalDist;
- Ptr<RandomVariableStream> m_sizeDist;
- Ptr<RandomVariableStream> m_protoDist;
- Ptr<RandomVariableStream> m_srcDist;
- Ptr<RandomVariableStream> m_dstDist;
- Ptr<RandomVariableStream> m_tosDist;
- Ptr<RandomVariableStream> m_srcPortDist;
- Ptr<RandomVariableStream> m_dstPortDist;
- uint32_t m_num;
- uint32_t m_maxPackets;
-};
-
-void
-Enqueuer::Generate (void)
-{
- NS_LOG_DEBUG ("Generating a packet at time " << Simulator::Now ().GetSeconds ());
- uint32_t size = m_sizeDist->GetInteger ();
- size -= size % 8;
- Ptr<Packet> p = Create<Packet> (size);
- Ipv4Header ipHeader;
- ipHeader.SetPayloadSize (size);
- uint8_t tos = m_tosDist->GetInteger () * 2;
- uint32_t dstAddrVal = (m_dstDist->GetInteger () << 24) + (m_dstDist->GetInteger () << 16) + (m_dstDist->GetInteger () << 8) + m_dstDist->GetInteger ();
- uint32_t srcAddrVal = (m_srcDist->GetInteger () << 24) + (m_srcDist->GetInteger () << 16) + (m_srcDist->GetInteger () << 8) + m_srcDist->GetInteger ();
- ipHeader.SetDestination (Ipv4Address (dstAddrVal));
- ipHeader.SetSource (Ipv4Address (srcAddrVal));
- ipHeader.SetTos (tos);
- uint16_t protocol = (m_protoDist->GetValue () > 1 ) ? 6 : 17;
- ipHeader.SetProtocol (protocol);
- p->AddHeader (ipHeader);
- m_queue->Enqueue (p);
- m_num++;
- if (m_num == m_maxPackets)
- {
- Simulator::Stop ();
- }
- else
- {
- Simulator::Schedule (Seconds (m_intervalDist->GetValue ()), &Enqueuer::Generate, this);
- }
-}
-
-class Dequeuer
-{
-public:
- void SetQueue (Ptr<Queue> queue) { m_queue = queue; }
- void SetGenerator (Ptr<RandomVariableStream> var) { m_var = var; }
- void Start (void) { Simulator::Schedule (Seconds (m_var->GetValue ()), &Dequeuer::Consume, this); }
-
-private:
- void Consume (void);
- Ptr<Queue> m_queue;
- Ptr<RandomVariableStream> m_var;
-};
-
-void
-Dequeuer::Consume (void)
-{
- Ptr<Packet> p = m_queue->Dequeue ();
- if (p)
- {
- NS_LOG_DEBUG ("Consuming a packet at time " << Simulator::Now ().GetSeconds ());
- }
- else
- {
- NS_LOG_DEBUG ("Tried to consume, but queue empty, at time " << Simulator::Now ().GetSeconds ());
- }
- p = 0;
- Simulator::Schedule (Seconds (m_var->GetValue ()), &Dequeuer::Consume, this);
-}
-
-void FutureEvent (void)
-{
-}
-
-int main (int argc, char *argv[])
-{
- double lambda = 1;
- double mu = 1.1;
- double stopTimeInput = 10000.0;
- uint32_t maxPackets = 0;
- std::string queueType = "DropTailQueue";
-
- CommandLine cmd;
- cmd.AddValue ("lambda", "arrival rate", lambda);
- cmd.AddValue ("mu", "departure rate", mu);
- cmd.AddValue ("queueType", "class name of queue", queueType);
- cmd.AddValue ("stopTime", "time to stop simulation (s)", stopTimeInput);
- cmd.AddValue ("maxPackets", "number of packets to stop simulation", maxPackets);
-
- cmd.Parse (argc, argv);
-
- NS_ASSERT_MSG (lambda < mu, "Stability only if lamdba < mu");
- NS_ASSERT (lambda > 0);
- NS_ASSERT (mu > 0);
- NS_ASSERT (queueType == "DropTailQueue" || queueType == "PfifoFastQueue");
- Time stopTime = Seconds (stopTimeInput);
-
-
- Ptr<Queue> queue = 0;
- if (queueType == "DropTailQueue")
- {
- queue = CreateObject<DropTailQueue> ();
- bool ok = queue->SetAttributeFailSafe ("MaxPackets", UintegerValue (1000));
- NS_ABORT_MSG_UNLESS (ok == true, "Could not set MaxPackets");
- }
- else if (queueType == "PfifoFastQueue")
- {
- queue = CreateObject<PfifoFastQueue> ();
- bool ok = queue->SetAttributeFailSafe ("MaxPackets", UintegerValue (1000));
- NS_ABORT_MSG_UNLESS (ok == true, "Could not set MaxPackets");
- // It is easier to generate TOS values (contiguous) than DSCP
- ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_TOS));
- NS_ABORT_MSG_UNLESS (ok == true, "unable to set attribute");
- }
- NS_ASSERT (queue != 0);
-
- Enqueuer enq (maxPackets);
- enq.SetQueue (queue);
-
- Ptr<UniformRandomVariable> rv_sizeDist = CreateObject<UniformRandomVariable> ();
- rv_sizeDist->SetAttribute ("Min", DoubleValue (40));
- rv_sizeDist->SetAttribute ("Max", DoubleValue (1400));
- enq.SetSize (rv_sizeDist);
- Ptr<UniformRandomVariable> rv_protoDist = CreateObject<UniformRandomVariable> ();
- rv_protoDist->SetAttribute ("Min", DoubleValue (0));
- rv_protoDist->SetAttribute ("Max", DoubleValue (2));
- enq.SetProto (rv_protoDist);
- Ptr<UniformRandomVariable> rv_srcDist = CreateObject<UniformRandomVariable> ();
- rv_srcDist->SetAttribute ("Min", DoubleValue (1));
- rv_srcDist->SetAttribute ("Max", DoubleValue (254));
- enq.SetSrc (rv_srcDist);
- Ptr<UniformRandomVariable> rv_dstDist = CreateObject<UniformRandomVariable> ();
- rv_dstDist->SetAttribute ("Min", DoubleValue (1));
- rv_dstDist->SetAttribute ("Max", DoubleValue (254));
- enq.SetDst (rv_dstDist);
- Ptr<UniformRandomVariable> rv_tosDist = CreateObject<UniformRandomVariable> ();
- rv_tosDist->SetAttribute ("Min", DoubleValue (0));
- rv_tosDist->SetAttribute ("Max", DoubleValue (15));
- enq.SetTos (rv_tosDist);
- Ptr<UniformRandomVariable> rv_srcPortDist = CreateObject<UniformRandomVariable> ();
- rv_srcPortDist->SetAttribute ("Min", DoubleValue (4000));
- rv_srcPortDist->SetAttribute ("Max", DoubleValue (5000));
- enq.SetSrcPort (rv_srcPortDist);
- Ptr<UniformRandomVariable> rv_dstPortDist = CreateObject<UniformRandomVariable> ();
- rv_dstPortDist->SetAttribute ("Min", DoubleValue (10));
- rv_dstPortDist->SetAttribute ("Max", DoubleValue (100));
- enq.SetDstPort (rv_dstPortDist);
-
- Ptr<ExponentialRandomVariable> rv_enq = CreateObject<ExponentialRandomVariable> ();
- rv_enq->SetAttribute ("Mean", DoubleValue (1/lambda));
- enq.SetGenerator (rv_enq);
- enq.Start ();
-
- Dequeuer deq;
- deq.SetQueue (queue);
- Ptr<ExponentialRandomVariable> rv_deq = CreateObject<ExponentialRandomVariable> ();
- rv_deq->SetAttribute ("Mean", DoubleValue (1/mu));
- deq.SetGenerator (rv_deq);
- deq.Start ();
-
- if (maxPackets == 0)
- {
- // Stop at stop time
- Simulator::Stop (stopTime);
- }
- else
- {
- // Schedule event way out in the future, to keep simulator alive
- // The enqueuer will eventually stop it when maxPackets reached
- Simulator::Schedule (Years (100), &FutureEvent);
- }
-
- Simulator::Run ();
- std::cout << "Sent " << enq.GetNum () << " packets to queue type " << queueType << std::endl;
-
- NS_LOG_DEBUG ("Final queue depth = " << queue->GetNPackets ());
-
- Simulator::Destroy ();
-
- return 0;
-}
--- a/src/internet-queues/examples/wscript Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet-queues/examples/wscript Fri Jan 16 15:57:07 2015 -0800
@@ -1,6 +1,2 @@
# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-def build(bld):
- obj = bld.create_ns3_program('bench-queue',
- ['network', 'internet', 'internet-queues'])
- obj.source = 'bench-queue.cc'
--- a/src/internet-queues/model/pfifo-fast-queue.cc Thu Nov 06 15:18:11 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,307 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007, 2014 University of Washington
- *
- * 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
- */
-
-#include "ns3/log.h"
-#include "ns3/enum.h"
-#include "ns3/uinteger.h"
-#include "ns3/ipv4-header.h"
-#include "pfifo-fast-queue.h"
-
-namespace ns3 {
-
-NS_LOG_COMPONENT_DEFINE ("PfifoFastQueue");
-
-NS_OBJECT_ENSURE_REGISTERED (PfifoFastQueue);
-
-TypeId PfifoFastQueue::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::PfifoFastQueue")
- .SetParent<Queue> ()
- .AddConstructor<PfifoFastQueue> ()
- .AddAttribute ("Mode",
- "Whether to interpret the TOS byte as legacy TOS or DSCP",
- EnumValue (QUEUE_MODE_DSCP),
- MakeEnumAccessor (&PfifoFastQueue::m_trafficClassMode),
- MakeEnumChecker (QUEUE_MODE_TOS, "TOS semantics",
- QUEUE_MODE_DSCP, "DSCP semantics"))
- .AddAttribute ("MaxPackets",
- "The maximum number of packets per band",
- UintegerValue (1000),
- MakeUintegerAccessor (&PfifoFastQueue::m_maxPackets),
- MakeUintegerChecker<uint32_t> ())
- ;
-
- return tid;
-}
-
-PfifoFastQueue::PfifoFastQueue () :
- Queue ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-PfifoFastQueue::~PfifoFastQueue ()
-{
- NS_LOG_FUNCTION (this);
-}
-
-bool
-PfifoFastQueue::DoEnqueue (Ptr<Packet> p)
-{
- NS_LOG_FUNCTION (this << p);
-
- uint32_t band = Classify (p);
-
- if (band == 0)
- {
- if (m_packets0.size () >= m_maxPackets)
- {
- NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt");
- Drop (p);
- return false;
- }
- m_packets0.push (p);
- NS_LOG_LOGIC ("Number packets band 0: " << m_packets0.size ());
- }
- else if (band == 1)
- {
- if (m_packets1.size () >= m_maxPackets)
- {
- NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt");
- Drop (p);
- return false;
- }
- m_packets1.push (p);
- NS_LOG_LOGIC ("Number packets band 1: " << m_packets1.size ());
- }
- else
- {
- if (m_packets2.size () >= m_maxPackets)
- {
- NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt");
- Drop (p);
- return false;
- }
- m_packets2.push (p);
- NS_LOG_LOGIC ("Number packets band 2: " << m_packets2.size ());
- }
- return true;
-}
-
-Ptr<Packet>
-PfifoFastQueue::DoDequeue (void)
-{
- NS_LOG_FUNCTION (this);
-
- Ptr<Packet> p;
- if (m_packets0.size ())
- {
- p = m_packets0.front ();
- m_packets0.pop ();
- NS_LOG_LOGIC ("Popped from band 0: " << p);
- NS_LOG_LOGIC ("Number packets band 0: " << m_packets0.size ());
- }
- else if (m_packets1.size ())
- {
- p = m_packets1.front ();
- m_packets1.pop ();
- NS_LOG_LOGIC ("Popped from band 1: " << p);
- NS_LOG_LOGIC ("Number packets band 1: " << m_packets1.size ());
- }
- else if (m_packets2.size ())
- {
- p = m_packets2.front ();
- m_packets2.pop ();
- NS_LOG_LOGIC ("Popped from band 2: " << p);
- NS_LOG_LOGIC ("Number packets band 2: " << m_packets2.size ());
- }
-
- if (p == 0)
- {
- NS_LOG_LOGIC ("Queue empty");
- }
- return p;
-}
-
-Ptr<const Packet>
-PfifoFastQueue::DoPeek (void) const
-{
- NS_LOG_FUNCTION (this);
-
- Ptr<Packet> p = 0;
- if (m_packets0.size ())
- {
- p = m_packets0.front ();
- }
- else if (m_packets1.size ())
- {
- p = m_packets1.front ();
- }
- else if (m_packets2.size ())
- {
- p = m_packets2.front ();
- }
- if (p == 0)
- {
- NS_LOG_LOGIC ("Queue empty");
- }
- return p;
-}
-
-uint32_t
-PfifoFastQueue::GetNPackets (uint32_t band) const
-{
- NS_LOG_FUNCTION (this << band);
- if (band == 0)
- {
- return m_packets0.size ();
- }
- else if (band == 1)
- {
- return m_packets1.size ();
- }
- else if (band == 2)
- {
- return m_packets2.size ();
- }
- else
- {
- NS_LOG_ERROR ("Invalid band " << band);
- return 0;
- }
-}
-
-uint32_t
-PfifoFastQueue::Classify (Ptr<const Packet> p) const
-{
- NS_LOG_FUNCTION (this << p);
- bool found = false;
- uint32_t band = 1;
-
- Ipv4Header hdr4;
- if (p->GetSize () >= hdr4.GetSerializedSize ())
- {
- p->PeekHeader (hdr4);
- if (hdr4.GetVersion () == 4 && hdr4.GetSerializedSize () >= 20 &&
- hdr4.GetSerializedSize () <= 60 && hdr4.GetProtocol () < 160 &&
- hdr4.GetPayloadSize () == (p->GetSize () - hdr4.GetSerializedSize ()))
- {
- // Likely an IPv4 packet
- if (m_trafficClassMode == QUEUE_MODE_TOS)
- {
- band = TosToBand (hdr4.GetTos ());
- found = true;
- NS_LOG_DEBUG ("Found Ipv4 packet; TOS " << (uint16_t) hdr4.GetTos () << " band " << band);
- }
- else
- {
- band = DscpToBand (hdr4.GetDscp ());
- found = true;
- NS_LOG_DEBUG ("Found Ipv4 packet; DSCP " << Ipv4Header::DscpTypeToString (hdr4.GetDscp ()) << " band " << band);
- }
- }
- else
- {
- NS_LOG_DEBUG ("Unable to classify but large enough packet for IPv4");
- }
- }
- if (!found)
- {
- NS_LOG_DEBUG ("Unable to classify; returning default band of " << band);
- }
- return band;
-}
-
-uint32_t
-PfifoFastQueue::TosToBand (uint8_t tos) const
-{
- NS_LOG_FUNCTION (this << (uint16_t) tos);
-
- uint32_t band = 1;
- switch (tos) {
- case 0x10 :
- case 0x12 :
- case 0x14 :
- case 0x16 :
- band = 0;
- break;
- case 0x0 :
- case 0x4 :
- case 0x6 :
- case 0x18 :
- case 0x1a :
- case 0x1c :
- case 0x1e :
- band = 1;
- break;
- case 0x2 :
- case 0x8 :
- case 0xa :
- case 0xc :
- case 0xe :
- band = 2;
- break;
- default :
- NS_LOG_ERROR ("Invalid TOS " << (uint16_t) tos);
- }
- return band;
-}
-
-uint32_t
-PfifoFastQueue::DscpToBand (Ipv4Header::DscpType dscpType) const
-{
- NS_LOG_FUNCTION (this << Ipv4Header::DscpTypeToString (dscpType));
-
- uint32_t band = 1;
- switch (dscpType) {
- case Ipv4Header::DSCP_EF :
- case Ipv4Header::DSCP_AF13 :
- case Ipv4Header::DSCP_AF23 :
- case Ipv4Header::DSCP_AF33 :
- case Ipv4Header::DSCP_AF43 :
- case Ipv4Header::DscpDefault :
- case Ipv4Header::DSCP_CS2 :
- case Ipv4Header::DSCP_CS3 :
- band = 1;
- break;
- case Ipv4Header::DSCP_AF11 :
- case Ipv4Header::DSCP_AF21 :
- case Ipv4Header::DSCP_AF31 :
- case Ipv4Header::DSCP_AF41 :
- case Ipv4Header::DSCP_CS1 :
- band = 2;
- break;
- case Ipv4Header::DSCP_AF12 :
- case Ipv4Header::DSCP_AF22 :
- case Ipv4Header::DSCP_AF32 :
- case Ipv4Header::DSCP_AF42 :
- case Ipv4Header::DSCP_CS4 :
- case Ipv4Header::DSCP_CS5 :
- case Ipv4Header::DSCP_CS6 :
- case Ipv4Header::DSCP_CS7 :
- band = 0;
- break;
- default :
- band = 1;
- }
- NS_LOG_DEBUG ("Band returned: " << band);
- return band;
-}
-
-} // namespace ns3
-
--- a/src/internet-queues/model/pfifo-fast-queue.h Thu Nov 06 15:18:11 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007, 2014 University of Washington
- *
- * 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
- */
-
-#ifndef PFIFO_FAST_H
-#define PFIFO_FAST_H
-
-#include <queue>
-#include "ns3/packet.h"
-#include "ns3/queue.h"
-#include "ns3/ipv4-header.h"
-
-namespace ns3 {
-
-/**
- * \ingroup internet-queues
- *
- * Linux pfifo_fast is the default priority queue enabled on Linux
- * systems. Packets are enqueued in three FIFO droptail queues according
- * to three priority bands based on their Type of Service bits or DSCP bits.
- *
- * The system behaves similar to three ns3::DropTail queues operating
- * together, in which packets from higher priority bands are always
- * dequeued before a packet from a lower priority band is dequeued.
- *
- * The queue depth set by the attributes is applicable to all three
- * queue bands, similar to Linux behavior that each band is txqueuelen
- * packets long.
- *
- * Packets are grouped into bands according to the IP TOS or DSCP. Packets
- * without such a marking or without an IP header are grouped into band 1
- * (normal service).
- *
- * Two modes of operation are provided. pfifo_fast is originally based
- * on RFC 1349 TOS byte definition:
- * http://www.ietf.org/rfc/rfc1349.txt
- *
- * 0 1 2 3 4 5 6 7
- * +-----+-----+-----+-----+-----+-----+-----+-----+
- * | PRECEDENCE | TOS | MBZ |
- * +-----+-----+-----+-----+-----+-----+-----+-----+
- *
- * where MBZ stands for 'must be zero'.
- *
- * In the eight-bit legacy TOS byte, there were five lower bits for TOS
- * and three upper bits for Precedence. Bit 7 was never used. Bits 6-7
- * are now repurposed for ECN. The below TOS values correspond to
- * bits 3-7 in the TOS byte (i.e. including MBZ), omitting the precedence
- * bits 0-2.
- *
- * TOS | Bits | Means | Linux Priority | Band
- * -----|------|-------------------------|----------------|-----
- * 0x0 | 0 | Normal Service | 0 Best Effort | 1
- * 0x2 | 1 | Minimize Monetary Cost | 1 Filler | 2
- * 0x4 | 2 | Maximize Reliability | 0 Best Effort | 1
- * 0x6 | 3 | mmc+mr | 0 Best Effort | 1
- * 0x8 | 4 | Maximize Throughput | 2 Bulk | 2
- * 0xa | 5 | mmc+mt | 2 Bulk | 2
- * 0xc | 6 | mr+mt | 2 Bulk | 2
- * 0xe | 7 | mmc+mr+mt | 2 Bulk | 2
- * 0x10 | 8 | Minimize Delay | 6 Interactive | 0
- * 0x12 | 9 | mmc+md | 6 Interactive | 0
- * 0x14 | 10 | mr+md | 6 Interactive | 0
- * 0x16 | 11 | mmc+mr+md | 6 Interactive | 0
- * 0x18 | 12 | mt+md | 4 Int. Bulk | 1
- * 0x1a | 13 | mmc+mt+md | 4 Int. Bulk | 1
- * 0x1c | 14 | mr+mt+md | 4 Int. Bulk | 1
- * 0x1e | 15 | mmc+mr+mt+md | 4 Int. Bulk | 1
- *
- * When the queue is set to mode PfifoFastQueue::QUEUE_MODE_TOS, the
- * above values are used to map packets into bands, and IP precedence
- * bits are disregarded.
- *
- * When the queue is set to mode PfifoFastQueue::QUEUE_MODE_DSCP
- * (the default), the following mappings are used.
- *
- * For DSCP, the following values are recommended for Linux in a patch
- * to the netdev mailing list from Jesper Dangaard Brouer <brouer@redhat.com>
- * on 15 Sept 2014. CS* values I made up myself.
- *
- * DSCP | Hex | Means | Linux Priority | Band
- * -----|------|----------------------------|----------------|-----
- * EF | 0x2E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
- * AF11 | 0x0A | TC_PRIO_BULK=2 | 2 Bulk | 2
- * AF21 | 0x12 | TC_PRIO_BULK=2 | 2 Bulk | 2
- * AF31 | 0x1A | TC_PRIO_BULK=2 | 2 Bulk | 2
- * AF41 | 0x22 | TC_PRIO_BULK=2 | 2 Bulk | 2
- * AF12 | 0x0C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
- * AF22 | 0x14 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
- * AF32 | 0x1C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
- * AF42 | 0x34 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
- * AF13 | 0x0E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
- * AF23 | 0x16 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
- * AF33 | 0x1E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
- * AF43 | 0x26 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
- * CS0 | 0x00 | TC_PRIO_BESTEFFORT | 0 Best Effort | 1
- * CS1 | 0x20 | TC_PRIO_FILLER | 1 Filler | 2
- * CS2 | 0x40 | TC_PRIO_BULK | 2 Bulk | 1
- * CS3 | 0x60 | TC_PRIO_INTERACTIVE_BULK | 4 Int. Bulk | 1
- * CS4 | 0x80 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
- * CS5 | 0xA0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
- * CS6 | 0xC0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
- * CS7 | 0xE0 | TC_PRIO_CONTROL | 8 Control | 0
- *
- */
-class PfifoFastQueue : public Queue {
-public:
- /**
- * \brief Get the type ID.
- * \return the object TypeId
- */
- static TypeId GetTypeId (void);
- /**
- * \brief PfifoFastQueue constructor
- *
- * Creates a queue with a depth of 1000 packets per band by default
- */
- PfifoFastQueue ();
-
- virtual ~PfifoFastQueue();
-
- /**
- * \brief Enumeration of modes of Ipv4 header traffic class semantics
- */
- enum Ipv4TrafficClassMode
- {
- QUEUE_MODE_TOS, //!< use legacy TOS semantics to interpret TOS byte
- QUEUE_MODE_DSCP, //!< use DSCP semantics to interpret TOS byte
- };
-
- /**
- * \return The number of packets currently stored in one band of the queue
- * \param band the band to check (0, 1, or 2)
- */
- uint32_t GetNPackets (uint32_t band) const;
-
-private:
- virtual bool DoEnqueue (Ptr<Packet> p);
- virtual Ptr<Packet> DoDequeue (void);
- virtual Ptr<const Packet> DoPeek (void) const;
- uint32_t Classify (Ptr<const Packet> p) const;
- uint32_t TosToBand (uint8_t tos) const;
- uint32_t DscpToBand (Ipv4Header::DscpType dscpType) const;
-
- std::queue<Ptr<Packet> > m_packets0; //!< the packets in band 0
- std::queue<Ptr<Packet> > m_packets1; //!< the packets in band 1
- std::queue<Ptr<Packet> > m_packets2; //!< the packets in band 2
- uint32_t m_maxPackets; //!< max packets in the queue
- Ipv4TrafficClassMode m_trafficClassMode; //!< traffic class mode
-};
-
-} // namespace ns3
-
-#endif /* PFIFO_FAST_H */
--- a/src/internet-queues/test/pfifo-fast-queue-test-suite.cc Thu Nov 06 15:18:11 2014 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2014 University of Washington
- *
- * 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
- *
- */
-
-#include "ns3/test.h"
-#include "ns3/pfifo-fast-queue.h"
-#include "ns3/ipv4-header.h"
-#include "ns3/enum.h"
-#include "ns3/uinteger.h"
-
-using namespace ns3;
-
-/**
- * This class tests that each possible TOS is enqueued in the right band
- */
-class PfifoFastQueueTosPrioritization : public TestCase
-{
-public:
- PfifoFastQueueTosPrioritization ();
- virtual ~PfifoFastQueueTosPrioritization ();
-
-private:
- virtual void DoRun (void);
- Ptr<Packet> CreatePacketWithTos (uint8_t tos);
- void TestTosValue (Ptr<PfifoFastQueue> queue, uint8_t tos, uint32_t band);
-};
-
-PfifoFastQueueTosPrioritization::PfifoFastQueueTosPrioritization ()
- : TestCase ("Test TOS-based prioritization")
-{
-}
-
-PfifoFastQueueTosPrioritization::~PfifoFastQueueTosPrioritization ()
-{
-}
-
-Ptr<Packet>
-PfifoFastQueueTosPrioritization::CreatePacketWithTos (uint8_t tos)
-{
- Ptr<Packet> p = Create<Packet> (100);
- Ipv4Header ipHeader;
- ipHeader.SetPayloadSize (100);
- ipHeader.SetTos (tos);
- ipHeader.SetProtocol (6);
- p->AddHeader (ipHeader);
- return p;
-}
-
-void
-PfifoFastQueueTosPrioritization::TestTosValue (Ptr<PfifoFastQueue> queue, uint8_t tos, uint32_t band)
-{
- Ptr<Packet> p = CreatePacketWithTos (tos);
- queue->Enqueue (p);
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 1, "enqueued to unexpected band");
- p = queue->Dequeue ();
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 0, "unable to dequeue");
-}
-
-void
-PfifoFastQueueTosPrioritization::DoRun (void)
-{
- Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
- bool ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_TOS));
- NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 0, "initialized non-zero");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 0, "initialized non-zero");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 0, "initialized non-zero");
-
- TestTosValue (queue, 0x0, 1);
- TestTosValue (queue, 0x2, 2);
- TestTosValue (queue, 0x4, 1);
- TestTosValue (queue, 0x6, 1);
- TestTosValue (queue, 0x8, 2);
- TestTosValue (queue, 0xa, 2);
- TestTosValue (queue, 0xc, 2);
- TestTosValue (queue, 0xe, 2);
- TestTosValue (queue, 0x10, 0);
- TestTosValue (queue, 0x12, 0);
- TestTosValue (queue, 0x14, 0);
- TestTosValue (queue, 0x16, 0);
- TestTosValue (queue, 0x18, 1);
- TestTosValue (queue, 0x1a, 1);
- TestTosValue (queue, 0x1c, 1);
- TestTosValue (queue, 0x1e, 1);
-}
-
-/**
- * This class tests that each possible DSCP is enqueued in the right band
- */
-class PfifoFastQueueDscpPrioritization : public TestCase
-{
-public:
- PfifoFastQueueDscpPrioritization ();
- virtual ~PfifoFastQueueDscpPrioritization ();
-
-private:
- virtual void DoRun (void);
- Ptr<Packet> CreatePacketWithDscp (Ipv4Header::DscpType dscp);
- void TestDscpValue (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp, uint32_t band);
-};
-
-PfifoFastQueueDscpPrioritization::PfifoFastQueueDscpPrioritization ()
- : TestCase ("Test DSCP-based prioritization")
-{
-}
-
-PfifoFastQueueDscpPrioritization::~PfifoFastQueueDscpPrioritization ()
-{
-}
-
-Ptr<Packet>
-PfifoFastQueueDscpPrioritization::CreatePacketWithDscp (Ipv4Header::DscpType dscp)
-{
- Ptr<Packet> p = Create<Packet> (100);
- Ipv4Header ipHeader;
- ipHeader.SetPayloadSize (100);
- ipHeader.SetProtocol (6);
- ipHeader.SetDscp (dscp);
- p->AddHeader (ipHeader);
- return p;
-}
-
-void
-PfifoFastQueueDscpPrioritization::TestDscpValue (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp, uint32_t band)
-{
- Ptr<Packet> p = CreatePacketWithDscp (dscp);
- queue->Enqueue (p);
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 1, "enqueued to unexpected band");
- p = queue->Dequeue ();
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 0, "unable to dequeue");
-}
-
-void
-PfifoFastQueueDscpPrioritization::DoRun (void)
-{
- Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
- bool ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_DSCP));
- NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 0, "initialized non-zero");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 0, "initialized non-zero");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 0, "initialized non-zero");
-
- TestDscpValue (queue, Ipv4Header::DscpDefault, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_EF, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_AF11, 2);
- TestDscpValue (queue, Ipv4Header::DSCP_AF21, 2);
- TestDscpValue (queue, Ipv4Header::DSCP_AF31, 2);
- TestDscpValue (queue, Ipv4Header::DSCP_AF41, 2);
- TestDscpValue (queue, Ipv4Header::DSCP_AF12, 0);
- TestDscpValue (queue, Ipv4Header::DSCP_AF22, 0);
- TestDscpValue (queue, Ipv4Header::DSCP_AF32, 0);
- TestDscpValue (queue, Ipv4Header::DSCP_AF42, 0);
- TestDscpValue (queue, Ipv4Header::DSCP_AF13, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_AF23, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_AF33, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_AF43, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_CS1, 2);
- TestDscpValue (queue, Ipv4Header::DSCP_CS2, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_CS3, 1);
- TestDscpValue (queue, Ipv4Header::DSCP_CS4, 0);
- TestDscpValue (queue, Ipv4Header::DSCP_CS5, 0);
- TestDscpValue (queue, Ipv4Header::DSCP_CS6, 0);
- TestDscpValue (queue, Ipv4Header::DSCP_CS7, 0);
-}
-
-/**
- * This class tests that each band is txqueuelen deep
- */
-class PfifoFastQueueOverflow : public TestCase
-{
-public:
- PfifoFastQueueOverflow ();
- virtual ~PfifoFastQueueOverflow ();
-
-private:
- virtual void DoRun (void);
- void AddPacket (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp);
-};
-
-PfifoFastQueueOverflow::PfifoFastQueueOverflow ()
- : TestCase ("Test queue overflow")
-{
-}
-
-PfifoFastQueueOverflow::~PfifoFastQueueOverflow ()
-{
-}
-
-void
-PfifoFastQueueOverflow::AddPacket (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp)
-{
- Ptr<Packet> p = Create<Packet> (100);
- Ipv4Header ipHeader;
- ipHeader.SetPayloadSize (100);
- ipHeader.SetProtocol (6);
- ipHeader.SetDscp (dscp);
- p->AddHeader (ipHeader);
- queue->Enqueue (p);
-}
-
-void
-PfifoFastQueueOverflow::DoRun (void)
-{
- Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
- bool ok = queue->SetAttributeFailSafe ("MaxPackets", UintegerValue (2));
- NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
- ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_DSCP));
- NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
-
- // Add two packets per each band
- AddPacket (queue, Ipv4Header::DSCP_AF42); // 0
- AddPacket (queue, Ipv4Header::DSCP_AF42); // 0
- AddPacket (queue, Ipv4Header::DSCP_AF13); // 1
- AddPacket (queue, Ipv4Header::DSCP_AF13); // 1
- AddPacket (queue, Ipv4Header::DSCP_AF11); // 2
- AddPacket (queue, Ipv4Header::DSCP_AF11); // 2
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 2, "unexpected queue depth");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 2, "unexpected queue depth");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 2, "unexpected queue depth");
- NS_TEST_ASSERT_MSG_EQ (queue->Queue::GetNPackets (), 6, "unexpected queue depth");
- // Add a third packet to each band
- AddPacket (queue, Ipv4Header::DSCP_AF42); // 0
- AddPacket (queue, Ipv4Header::DSCP_AF13); // 1
- AddPacket (queue, Ipv4Header::DSCP_AF11); // 2
- // Bands should still have two packets each
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 2, "unexpected queue depth");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 2, "unexpected queue depth");
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 2, "unexpected queue depth");
- NS_TEST_ASSERT_MSG_EQ (queue->Queue::GetNPackets (), 6, "unexpected queue depth");
-}
-
-/**
- * This class tests that non-IP packets are handled by placing them into
- * band 1
- */
-class PfifoFastQueueNonIpHeader : public TestCase
-{
-public:
- PfifoFastQueueNonIpHeader ();
- virtual ~PfifoFastQueueNonIpHeader ();
-
-private:
- virtual void DoRun (void);
-};
-
-PfifoFastQueueNonIpHeader::PfifoFastQueueNonIpHeader ()
- : TestCase ("Test queue with non IP header")
-{
-}
-
-PfifoFastQueueNonIpHeader::~PfifoFastQueueNonIpHeader ()
-{
-}
-
-void
-PfifoFastQueueNonIpHeader::DoRun (void)
-{
- // all packets with non-IP headers should enqueue in band 1
- Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 0, "unexpected queue depth");
- Ptr<Packet> p;
- p = Create<Packet> ();
- queue->Enqueue (p);
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 1, "unexpected queue depth");
- p = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello, world"), 12);
- queue->Enqueue (p);
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 2, "unexpected queue depth");
- p = Create<Packet> (100);
- uint8_t *buf = new uint8_t[100];
- uint8_t counter = 0;
- for (uint32_t i = 0; i < 100; i++)
- {
- buf[i] = counter++;
- }
- p->CopyData (buf, 100);
- queue->Enqueue (p);
- NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 3, "unexpected queue depth");
- delete[] buf;
-}
-
-class PfifoFastQueueTestSuite : public TestSuite
-{
-public:
- PfifoFastQueueTestSuite ();
-};
-
-PfifoFastQueueTestSuite::PfifoFastQueueTestSuite ()
- : TestSuite ("internet-queues-pfifo-fast", UNIT)
-{
- AddTestCase (new PfifoFastQueueTosPrioritization, TestCase::QUICK);
- AddTestCase (new PfifoFastQueueDscpPrioritization, TestCase::QUICK);
- AddTestCase (new PfifoFastQueueOverflow, TestCase::QUICK);
- AddTestCase (new PfifoFastQueueNonIpHeader, TestCase::QUICK);
-}
-
-static PfifoFastQueueTestSuite pfifoFastQueueTestSuite;
-
--- a/src/internet-queues/wscript Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet-queues/wscript Fri Jan 16 15:57:07 2015 -0800
@@ -9,22 +9,16 @@
def build(bld):
module = bld.create_ns3_module('internet-queues', ['core', 'network', 'internet'])
module.source = [
- 'model/pfifo-fast-queue.cc',
]
module_test = bld.create_ns3_module_test_library('internet-queues')
module_test.source = [
- 'test/pfifo-fast-queue-test-suite.cc',
]
headers = bld(features='ns3header')
headers.module = 'internet-queues'
headers.source = [
- 'model/pfifo-fast-queue.h',
]
- if bld.env.ENABLE_EXAMPLES:
- bld.recurse('examples')
-
# bld.ns3_python_bindings()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/examples/bench-queue.cc Fri Jan 16 15:57:07 2015 -0800
@@ -0,0 +1,267 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright 2013-14 University of Washington
+ *
+ * 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
+ *
+ */
+
+// This program is intended to benchmark packet enqueuing/dequeuing for
+// different internet-aware packet queues, for which the operations of
+// the queue may require modifying/deserializing packet headers (which
+// may incur a performance hit).
+//
+// It is recommended when testing to build this as optimized code.
+//
+// By default, it will generate, enqueue, and dequeue packets according
+// to a poisson process. IPv4 headers with random valid field values
+// will be added to the test packets. It will run for 10000 seconds by
+// default, with DropTailQueue, and generate about 10000 packets.
+//
+// The key arguments are:
+// "--queueType=" (possible values DropTailQueue and PfifoFastQueue)
+// "--stopTime=" (use this to extend the simulation time; simulation will
+// stop at this time)
+// "--maxPackets=" (use this to send a specified number of packets; if set,
+// then the stop time will be ignored)
+
+#include <fstream>
+#include <sstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <algorithm>
+
+#include "ns3/packet.h"
+#include "ns3/drop-tail-queue.h"
+#include "ns3/pfifo-fast-queue.h"
+#include "ns3/uinteger.h"
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/double.h"
+#include "ns3/enum.h"
+#include "ns3/log.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/abort.h"
+#include "ns3/command-line.h"
+#include "ns3/random-variable-stream.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("BenchQueue");
+
+class Enqueuer
+{
+public:
+ Enqueuer () : m_num (0), m_maxPackets (0) {}
+ Enqueuer (uint32_t maxPackets) : m_num (0), m_maxPackets (maxPackets) {}
+ void SetQueue (Ptr<Queue> queue) { m_queue = queue; }
+ void SetGenerator (Ptr<RandomVariableStream> var) { m_intervalDist = var; }
+ void SetSize (Ptr<RandomVariableStream> var) { m_sizeDist = var; }
+ void SetProto (Ptr<RandomVariableStream> var) { m_protoDist = var; }
+ void SetSrc (Ptr<RandomVariableStream> var) { m_srcDist = var; }
+ void SetDst (Ptr<RandomVariableStream> var) { m_dstDist = var; }
+ void SetSrcPort (Ptr<RandomVariableStream> var) { m_srcPortDist = var; }
+ void SetDstPort (Ptr<RandomVariableStream> var) { m_dstPortDist = var; }
+ void SetTos (Ptr<RandomVariableStream> var) { m_tosDist = var; }
+ void Start (void) { Simulator::Schedule (Seconds (m_intervalDist->GetValue ()), &Enqueuer::Generate, this); }
+ uint32_t GetNum () const { return m_num; }
+
+private:
+ void Generate (void);
+ Ptr<Queue> m_queue;
+ Ptr<RandomVariableStream> m_intervalDist;
+ Ptr<RandomVariableStream> m_sizeDist;
+ Ptr<RandomVariableStream> m_protoDist;
+ Ptr<RandomVariableStream> m_srcDist;
+ Ptr<RandomVariableStream> m_dstDist;
+ Ptr<RandomVariableStream> m_tosDist;
+ Ptr<RandomVariableStream> m_srcPortDist;
+ Ptr<RandomVariableStream> m_dstPortDist;
+ uint32_t m_num;
+ uint32_t m_maxPackets;
+};
+
+void
+Enqueuer::Generate (void)
+{
+ NS_LOG_DEBUG ("Generating a packet at time " << Simulator::Now ().GetSeconds ());
+ uint32_t size = m_sizeDist->GetInteger ();
+ size -= size % 8;
+ Ptr<Packet> p = Create<Packet> (size);
+ Ipv4Header ipHeader;
+ ipHeader.SetPayloadSize (size);
+ uint8_t tos = m_tosDist->GetInteger () * 2;
+ uint32_t dstAddrVal = (m_dstDist->GetInteger () << 24) + (m_dstDist->GetInteger () << 16) + (m_dstDist->GetInteger () << 8) + m_dstDist->GetInteger ();
+ uint32_t srcAddrVal = (m_srcDist->GetInteger () << 24) + (m_srcDist->GetInteger () << 16) + (m_srcDist->GetInteger () << 8) + m_srcDist->GetInteger ();
+ ipHeader.SetDestination (Ipv4Address (dstAddrVal));
+ ipHeader.SetSource (Ipv4Address (srcAddrVal));
+ ipHeader.SetTos (tos);
+ uint16_t protocol = (m_protoDist->GetValue () > 1 ) ? 6 : 17;
+ ipHeader.SetProtocol (protocol);
+ p->AddHeader (ipHeader);
+ m_queue->Enqueue (p);
+ m_num++;
+ if (m_num == m_maxPackets)
+ {
+ Simulator::Stop ();
+ }
+ else
+ {
+ Simulator::Schedule (Seconds (m_intervalDist->GetValue ()), &Enqueuer::Generate, this);
+ }
+}
+
+class Dequeuer
+{
+public:
+ void SetQueue (Ptr<Queue> queue) { m_queue = queue; }
+ void SetGenerator (Ptr<RandomVariableStream> var) { m_var = var; }
+ void Start (void) { Simulator::Schedule (Seconds (m_var->GetValue ()), &Dequeuer::Consume, this); }
+
+private:
+ void Consume (void);
+ Ptr<Queue> m_queue;
+ Ptr<RandomVariableStream> m_var;
+};
+
+void
+Dequeuer::Consume (void)
+{
+ Ptr<Packet> p = m_queue->Dequeue ();
+ if (p)
+ {
+ NS_LOG_DEBUG ("Consuming a packet at time " << Simulator::Now ().GetSeconds ());
+ }
+ else
+ {
+ NS_LOG_DEBUG ("Tried to consume, but queue empty, at time " << Simulator::Now ().GetSeconds ());
+ }
+ p = 0;
+ Simulator::Schedule (Seconds (m_var->GetValue ()), &Dequeuer::Consume, this);
+}
+
+void FutureEvent (void)
+{
+}
+
+int main (int argc, char *argv[])
+{
+ double lambda = 1;
+ double mu = 1.1;
+ double stopTimeInput = 10000.0;
+ uint32_t maxPackets = 0;
+ std::string queueType = "DropTailQueue";
+
+ CommandLine cmd;
+ cmd.AddValue ("lambda", "arrival rate", lambda);
+ cmd.AddValue ("mu", "departure rate", mu);
+ cmd.AddValue ("queueType", "class name of queue", queueType);
+ cmd.AddValue ("stopTime", "time to stop simulation (s)", stopTimeInput);
+ cmd.AddValue ("maxPackets", "number of packets to stop simulation", maxPackets);
+
+ cmd.Parse (argc, argv);
+
+ NS_ASSERT_MSG (lambda < mu, "Stability only if lamdba < mu");
+ NS_ASSERT (lambda > 0);
+ NS_ASSERT (mu > 0);
+ NS_ASSERT (queueType == "DropTailQueue" || queueType == "PfifoFastQueue");
+ Time stopTime = Seconds (stopTimeInput);
+
+
+ Ptr<Queue> queue = 0;
+ if (queueType == "DropTailQueue")
+ {
+ queue = CreateObject<DropTailQueue> ();
+ bool ok = queue->SetAttributeFailSafe ("MaxPackets", UintegerValue (1000));
+ NS_ABORT_MSG_UNLESS (ok == true, "Could not set MaxPackets");
+ }
+/*
+ else if (queueType == "PfifoFastQueue")
+ {
+ queue = CreateObject<PfifoFastQueue> ();
+ bool ok = queue->SetAttributeFailSafe ("MaxPackets", UintegerValue (1000));
+ NS_ABORT_MSG_UNLESS (ok == true, "Could not set MaxPackets");
+ // It is easier to generate TOS values (contiguous) than DSCP
+ ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_TOS));
+ NS_ABORT_MSG_UNLESS (ok == true, "unable to set attribute");
+ }
+*/
+ NS_ASSERT (queue != 0);
+
+ Enqueuer enq (maxPackets);
+ enq.SetQueue (queue);
+
+ Ptr<UniformRandomVariable> rv_sizeDist = CreateObject<UniformRandomVariable> ();
+ rv_sizeDist->SetAttribute ("Min", DoubleValue (40));
+ rv_sizeDist->SetAttribute ("Max", DoubleValue (1400));
+ enq.SetSize (rv_sizeDist);
+ Ptr<UniformRandomVariable> rv_protoDist = CreateObject<UniformRandomVariable> ();
+ rv_protoDist->SetAttribute ("Min", DoubleValue (0));
+ rv_protoDist->SetAttribute ("Max", DoubleValue (2));
+ enq.SetProto (rv_protoDist);
+ Ptr<UniformRandomVariable> rv_srcDist = CreateObject<UniformRandomVariable> ();
+ rv_srcDist->SetAttribute ("Min", DoubleValue (1));
+ rv_srcDist->SetAttribute ("Max", DoubleValue (254));
+ enq.SetSrc (rv_srcDist);
+ Ptr<UniformRandomVariable> rv_dstDist = CreateObject<UniformRandomVariable> ();
+ rv_dstDist->SetAttribute ("Min", DoubleValue (1));
+ rv_dstDist->SetAttribute ("Max", DoubleValue (254));
+ enq.SetDst (rv_dstDist);
+ Ptr<UniformRandomVariable> rv_tosDist = CreateObject<UniformRandomVariable> ();
+ rv_tosDist->SetAttribute ("Min", DoubleValue (0));
+ rv_tosDist->SetAttribute ("Max", DoubleValue (15));
+ enq.SetTos (rv_tosDist);
+ Ptr<UniformRandomVariable> rv_srcPortDist = CreateObject<UniformRandomVariable> ();
+ rv_srcPortDist->SetAttribute ("Min", DoubleValue (4000));
+ rv_srcPortDist->SetAttribute ("Max", DoubleValue (5000));
+ enq.SetSrcPort (rv_srcPortDist);
+ Ptr<UniformRandomVariable> rv_dstPortDist = CreateObject<UniformRandomVariable> ();
+ rv_dstPortDist->SetAttribute ("Min", DoubleValue (10));
+ rv_dstPortDist->SetAttribute ("Max", DoubleValue (100));
+ enq.SetDstPort (rv_dstPortDist);
+
+ Ptr<ExponentialRandomVariable> rv_enq = CreateObject<ExponentialRandomVariable> ();
+ rv_enq->SetAttribute ("Mean", DoubleValue (1/lambda));
+ enq.SetGenerator (rv_enq);
+ enq.Start ();
+
+ Dequeuer deq;
+ deq.SetQueue (queue);
+ Ptr<ExponentialRandomVariable> rv_deq = CreateObject<ExponentialRandomVariable> ();
+ rv_deq->SetAttribute ("Mean", DoubleValue (1/mu));
+ deq.SetGenerator (rv_deq);
+ deq.Start ();
+
+ if (maxPackets == 0)
+ {
+ // Stop at stop time
+ Simulator::Stop (stopTime);
+ }
+ else
+ {
+ // Schedule event way out in the future, to keep simulator alive
+ // The enqueuer will eventually stop it when maxPackets reached
+ Simulator::Schedule (Years (100), &FutureEvent);
+ }
+
+ Simulator::Run ();
+ std::cout << "Sent " << enq.GetNum () << " packets to queue type " << queueType << std::endl;
+
+ NS_LOG_DEBUG ("Final queue depth = " << queue->GetNPackets ());
+
+ Simulator::Destroy ();
+
+ return 0;
+}
--- a/src/internet/examples/wscript Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet/examples/wscript Fri Jan 16 15:57:07 2015 -0800
@@ -15,3 +15,7 @@
obj = bld.create_ns3_program('codel-vs-droptail-asymmetric',
['point-to-point','network', 'internet', 'applications'])
obj.source = 'codel-vs-droptail-asymmetric.cc'
+ obj = bld.create_ns3_program('bench-queue',
+ ['network', 'internet'])
+ obj.source = 'bench-queue.cc'
+
--- a/src/internet/model/codel-queue.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet/model/codel-queue.cc Fri Jan 16 15:57:07 2015 -0800
@@ -240,6 +240,13 @@
NS_LOG_FUNCTION (this);
}
+bool
+CoDelQueue::IsFull (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return false;
+}
+
void
CoDelQueue::NewtonStep (void)
{
--- a/src/internet/model/codel-queue.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet/model/codel-queue.h Fri Jan 16 15:57:07 2015 -0800
@@ -100,6 +100,7 @@
*/
uint32_t GetQueueSize (void);
+ virtual bool IsFull (void) const;
/**
* \brief Get the number of packets dropped when packets
* arrive at a full queue and cannot be enqueued.
--- a/src/internet/model/ipv4-interface.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet/model/ipv4-interface.cc Fri Jan 16 15:57:07 2015 -0800
@@ -29,6 +29,7 @@
#include "ns3/packet.h"
#include "ns3/node.h"
#include "ns3/pointer.h"
+#include "priority-queue.h"
namespace ns3 {
@@ -63,7 +64,9 @@
m_metric (1),
m_node (0),
m_device (0),
- m_cache (0)
+ m_cache (0),
+ m_prioQueue (0),
+ m_prioQueueTid ("")
{
NS_LOG_FUNCTION (this);
}
@@ -95,10 +98,38 @@
{
NS_LOG_FUNCTION (this << device);
m_device = device;
+ m_device->SetDeviceReadyCallback (MakeCallback (&Ipv4Interface::DeviceReady, this));
DoSetup ();
}
void
+Ipv4Interface::DeviceReady (Ptr<NetDevice> nd)
+{
+ NS_LOG_FUNCTION (this << nd);
+ NS_LOG_UNCOND ("Device is ready");
+ struct PriorityQueue::QueueElement q;
+ q = m_prioQueue->Dequeue ();
+ if (!q.p)
+ {
+ NS_LOG_LOGIC ("No packet to send");
+ return;
+ }
+ do
+ {
+ m_device->Send (q.p, q.dest, Ipv4L3Protocol::PROT_NUMBER);
+ if (m_device->IsReady ())
+ {
+ q = m_prioQueue->Dequeue ();
+ }
+ else
+ {
+ break;
+ }
+ }
+ while (q.p);
+}
+
+void
Ipv4Interface::DoSetup (void)
{
NS_LOG_FUNCTION (this);
@@ -106,6 +137,10 @@
{
return;
}
+ ObjectFactory objectFactory;
+ m_prioQueueTid = "ns3::PfifoFastQueue";
+ objectFactory.SetTypeId (m_prioQueueTid);
+ m_prioQueue = DynamicCast<PriorityQueue> (objectFactory.Create ());
if (!m_device->NeedsArp ())
{
return;
@@ -114,6 +149,24 @@
m_cache = arp->CreateCache (m_device, this);
}
+void
+Ipv4Interface::DeviceQueueTransmit (Ptr<Packet> packet, const Address& dest)
+{
+ NS_LOG_FUNCTION (this << packet << dest);
+ NS_ASSERT_MSG (m_prioQueue, "This method being called before DoSetup; shouldn't happen");
+ struct PriorityQueue::QueueElement q;
+ q.p = packet;
+ q.dest = dest;
+ m_prioQueue->Enqueue (q);
+ if (m_device->IsReady ())
+ {
+ // We enqueue and dequeue immediately rather than bypass the queue in
+ // case the queue needs to know about such packets for future scheduling
+ q = m_prioQueue->Dequeue ();
+ m_device->Send (q.p, q.dest, Ipv4L3Protocol::PROT_NUMBER);
+ }
+}
+
Ptr<NetDevice>
Ipv4Interface::GetDevice (void) const
{
@@ -209,6 +262,8 @@
{
/// \todo additional checks needed here (such as whether multicast
/// goes to loopback)?
+ //
+ // Skip priority queueing (DeviceQueueTransmit); send directly to device
m_device->Send (p, m_device->GetBroadcast (),
Ipv4L3Protocol::PROT_NUMBER);
return;
@@ -272,15 +327,13 @@
if (found)
{
NS_LOG_LOGIC ("Address Resolved. Send.");
- m_device->Send (p, hardwareDestination,
- Ipv4L3Protocol::PROT_NUMBER);
+ DeviceQueueTransmit (p, hardwareDestination);
}
}
else
{
NS_LOG_LOGIC ("Doesn't need ARP");
- m_device->Send (p, m_device->GetBroadcast (),
- Ipv4L3Protocol::PROT_NUMBER);
+ DeviceQueueTransmit (p, m_device->GetBroadcast ());
}
}
--- a/src/internet/model/ipv4-interface.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet/model/ipv4-interface.h Fri Jan 16 15:57:07 2015 -0800
@@ -34,6 +34,7 @@
class Packet;
class Node;
class ArpCache;
+class PriorityQueue;
/**
* \brief The IPv4 representation of a network interface
@@ -186,6 +187,14 @@
*/
void DoSetup (void);
+ /**
+ */
+ void DeviceQueueTransmit (Ptr<Packet> packet, const Address& dest);
+
+ /**
+ * method to register in NetDevice DeviceReady callback
+ */
+ void DeviceReady (Ptr<NetDevice> nd);
/**
* \brief Container for the Ipv4InterfaceAddresses.
@@ -211,6 +220,8 @@
Ptr<Node> m_node; //!< The associated node
Ptr<NetDevice> m_device; //!< The associated NetDevice
Ptr<ArpCache> m_cache; //!< ARP cache
+ Ptr<PriorityQueue> m_prioQueue; //!< Priority queue
+ std::string m_prioQueueTid; //!< Type ID for queue to create
};
} // namespace ns3
--- a/src/internet/model/loopback-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet/model/loopback-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -72,6 +72,7 @@
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const { return true; }
protected:
virtual void DoDispose (void);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/pfifo-fast-queue.cc Fri Jan 16 15:57:07 2015 -0800
@@ -0,0 +1,281 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2014 University of Washington
+ *
+ * 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
+ */
+
+#include "ns3/log.h"
+#include "ns3/enum.h"
+#include "ns3/uinteger.h"
+#include "ns3/ipv4-header.h"
+#include "pfifo-fast-queue.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("PfifoFastQueue");
+
+NS_OBJECT_ENSURE_REGISTERED (PfifoFastQueue);
+
+TypeId PfifoFastQueue::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::PfifoFastQueue")
+ .SetParent<PriorityQueue> ()
+ .AddConstructor<PfifoFastQueue> ()
+ .AddAttribute ("Mode",
+ "Whether to interpret the TOS byte as legacy TOS or DSCP",
+ EnumValue (QUEUE_MODE_DSCP),
+ MakeEnumAccessor (&PfifoFastQueue::m_trafficClassMode),
+ MakeEnumChecker (QUEUE_MODE_TOS, "TOS semantics",
+ QUEUE_MODE_DSCP, "DSCP semantics"))
+ .AddAttribute ("MaxPackets",
+ "The maximum number of packets per band",
+ UintegerValue (1000),
+ MakeUintegerAccessor (&PfifoFastQueue::m_maxPackets),
+ MakeUintegerChecker<uint32_t> ())
+ ;
+
+ return tid;
+}
+
+PfifoFastQueue::PfifoFastQueue ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+PfifoFastQueue::~PfifoFastQueue ()
+{
+ NS_LOG_FUNCTION (this);
+}
+
+bool
+PfifoFastQueue::DoEnqueue (struct PriorityQueue::QueueElement q)
+{
+ NS_LOG_FUNCTION (this << q.p << q.dest);
+
+ uint32_t band = Classify (q.p);
+
+ if (band == 0)
+ {
+ if (m_packets0.size () >= m_maxPackets)
+ {
+ NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt");
+ Drop (q.p);
+ return false;
+ }
+ m_packets0.push (q);
+ NS_LOG_LOGIC ("Number packets band 0: " << m_packets0.size ());
+ }
+ else if (band == 1)
+ {
+ if (m_packets1.size () >= m_maxPackets)
+ {
+ NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt");
+ Drop (q.p);
+ return false;
+ }
+ m_packets1.push (q);
+ NS_LOG_LOGIC ("Number packets band 1: " << m_packets1.size ());
+ }
+ else
+ {
+ if (m_packets2.size () >= m_maxPackets)
+ {
+ NS_LOG_LOGIC ("Queue full (at max packets) -- droppping pkt");
+ Drop (q.p);
+ return false;
+ }
+ m_packets2.push (q);
+ NS_LOG_LOGIC ("Number packets band 2: " << m_packets2.size ());
+ }
+ return true;
+}
+
+struct PriorityQueue::QueueElement
+PfifoFastQueue::DoDequeue (void)
+{
+ NS_LOG_FUNCTION (this);
+
+ struct PriorityQueue::QueueElement q;
+ if (m_packets0.size ())
+ {
+ q = m_packets0.front ();
+ m_packets0.pop ();
+ NS_LOG_LOGIC ("Popped from band 0: " << q.p);
+ NS_LOG_LOGIC ("Number packets band 0: " << m_packets0.size ());
+ }
+ else if (m_packets1.size ())
+ {
+ q = m_packets1.front ();
+ m_packets1.pop ();
+ NS_LOG_LOGIC ("Popped from band 1: " << q.p);
+ NS_LOG_LOGIC ("Number packets band 1: " << m_packets1.size ());
+ }
+ else if (m_packets2.size ())
+ {
+ q = m_packets2.front ();
+ m_packets2.pop ();
+ NS_LOG_LOGIC ("Popped from band 2: " << q.p);
+ NS_LOG_LOGIC ("Number packets band 2: " << m_packets2.size ());
+ }
+
+ if (q.p == 0)
+ {
+ NS_LOG_LOGIC ("Queue empty");
+ }
+ return q;
+}
+
+uint32_t
+PfifoFastQueue::GetNPackets (uint32_t band) const
+{
+ NS_LOG_FUNCTION (this << band);
+ if (band == 0)
+ {
+ return m_packets0.size ();
+ }
+ else if (band == 1)
+ {
+ return m_packets1.size ();
+ }
+ else if (band == 2)
+ {
+ return m_packets2.size ();
+ }
+ else
+ {
+ NS_LOG_ERROR ("Invalid band " << band);
+ return 0;
+ }
+}
+
+uint32_t
+PfifoFastQueue::Classify (Ptr<const Packet> p) const
+{
+ NS_LOG_FUNCTION (this << p);
+ bool found = false;
+ uint32_t band = 1;
+
+ Ipv4Header hdr4;
+ if (p->GetSize () >= hdr4.GetSerializedSize ())
+ {
+ p->PeekHeader (hdr4);
+ if (hdr4.GetVersion () == 4 && hdr4.GetSerializedSize () >= 20 &&
+ hdr4.GetSerializedSize () <= 60 && hdr4.GetProtocol () < 160 &&
+ hdr4.GetPayloadSize () == (p->GetSize () - hdr4.GetSerializedSize ()))
+ {
+ // Likely an IPv4 packet
+ if (m_trafficClassMode == QUEUE_MODE_TOS)
+ {
+ band = TosToBand (hdr4.GetTos ());
+ found = true;
+ NS_LOG_DEBUG ("Found Ipv4 packet; TOS " << (uint16_t) hdr4.GetTos () << " band " << band);
+ }
+ else
+ {
+ band = DscpToBand (hdr4.GetDscp ());
+ found = true;
+ NS_LOG_DEBUG ("Found Ipv4 packet; DSCP " << Ipv4Header::DscpTypeToString (hdr4.GetDscp ()) << " band " << band);
+ }
+ }
+ else
+ {
+ NS_LOG_DEBUG ("Unable to classify but large enough packet for IPv4");
+ }
+ }
+ if (!found)
+ {
+ NS_LOG_DEBUG ("Unable to classify; returning default band of " << band);
+ }
+ return band;
+}
+
+uint32_t
+PfifoFastQueue::TosToBand (uint8_t tos) const
+{
+ NS_LOG_FUNCTION (this << (uint16_t) tos);
+
+ uint32_t band = 1;
+ switch (tos) {
+ case 0x10 :
+ case 0x12 :
+ case 0x14 :
+ case 0x16 :
+ band = 0;
+ break;
+ case 0x0 :
+ case 0x4 :
+ case 0x6 :
+ case 0x18 :
+ case 0x1a :
+ case 0x1c :
+ case 0x1e :
+ band = 1;
+ break;
+ case 0x2 :
+ case 0x8 :
+ case 0xa :
+ case 0xc :
+ case 0xe :
+ band = 2;
+ break;
+ default :
+ NS_LOG_ERROR ("Invalid TOS " << (uint16_t) tos);
+ }
+ return band;
+}
+
+uint32_t
+PfifoFastQueue::DscpToBand (Ipv4Header::DscpType dscpType) const
+{
+ NS_LOG_FUNCTION (this << Ipv4Header::DscpTypeToString (dscpType));
+
+ uint32_t band = 1;
+ switch (dscpType) {
+ case Ipv4Header::DSCP_EF :
+ case Ipv4Header::DSCP_AF13 :
+ case Ipv4Header::DSCP_AF23 :
+ case Ipv4Header::DSCP_AF33 :
+ case Ipv4Header::DSCP_AF43 :
+ case Ipv4Header::DscpDefault :
+ case Ipv4Header::DSCP_CS2 :
+ case Ipv4Header::DSCP_CS3 :
+ band = 1;
+ break;
+ case Ipv4Header::DSCP_AF11 :
+ case Ipv4Header::DSCP_AF21 :
+ case Ipv4Header::DSCP_AF31 :
+ case Ipv4Header::DSCP_AF41 :
+ case Ipv4Header::DSCP_CS1 :
+ band = 2;
+ break;
+ case Ipv4Header::DSCP_AF12 :
+ case Ipv4Header::DSCP_AF22 :
+ case Ipv4Header::DSCP_AF32 :
+ case Ipv4Header::DSCP_AF42 :
+ case Ipv4Header::DSCP_CS4 :
+ case Ipv4Header::DSCP_CS5 :
+ case Ipv4Header::DSCP_CS6 :
+ case Ipv4Header::DSCP_CS7 :
+ band = 0;
+ break;
+ default :
+ band = 1;
+ }
+ NS_LOG_DEBUG ("Band returned: " << band);
+ return band;
+}
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/pfifo-fast-queue.h Fri Jan 16 15:57:07 2015 -0800
@@ -0,0 +1,167 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2014 University of Washington
+ *
+ * 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
+ */
+
+#ifndef PFIFO_FAST_H
+#define PFIFO_FAST_H
+
+#include <queue>
+#include "ns3/packet.h"
+#include "ns3/priority-queue.h"
+#include "ns3/ipv4-header.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup internet-queues
+ *
+ * Linux pfifo_fast is the default priority queue enabled on Linux
+ * systems. Packets are enqueued in three FIFO droptail queues according
+ * to three priority bands based on their Type of Service bits or DSCP bits.
+ *
+ * The system behaves similar to three ns3::DropTail queues operating
+ * together, in which packets from higher priority bands are always
+ * dequeued before a packet from a lower priority band is dequeued.
+ *
+ * The queue depth set by the attributes is applicable to all three
+ * queue bands, similar to Linux behavior that each band is txqueuelen
+ * packets long.
+ *
+ * Packets are grouped into bands according to the IP TOS or DSCP. Packets
+ * without such a marking or without an IP header are grouped into band 1
+ * (normal service).
+ *
+ * Two modes of operation are provided. pfifo_fast is originally based
+ * on RFC 1349 TOS byte definition:
+ * http://www.ietf.org/rfc/rfc1349.txt
+ *
+ * 0 1 2 3 4 5 6 7
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ * | PRECEDENCE | TOS | MBZ |
+ * +-----+-----+-----+-----+-----+-----+-----+-----+
+ *
+ * where MBZ stands for 'must be zero'.
+ *
+ * In the eight-bit legacy TOS byte, there were five lower bits for TOS
+ * and three upper bits for Precedence. Bit 7 was never used. Bits 6-7
+ * are now repurposed for ECN. The below TOS values correspond to
+ * bits 3-7 in the TOS byte (i.e. including MBZ), omitting the precedence
+ * bits 0-2.
+ *
+ * TOS | Bits | Means | Linux Priority | Band
+ * -----|------|-------------------------|----------------|-----
+ * 0x0 | 0 | Normal Service | 0 Best Effort | 1
+ * 0x2 | 1 | Minimize Monetary Cost | 1 Filler | 2
+ * 0x4 | 2 | Maximize Reliability | 0 Best Effort | 1
+ * 0x6 | 3 | mmc+mr | 0 Best Effort | 1
+ * 0x8 | 4 | Maximize Throughput | 2 Bulk | 2
+ * 0xa | 5 | mmc+mt | 2 Bulk | 2
+ * 0xc | 6 | mr+mt | 2 Bulk | 2
+ * 0xe | 7 | mmc+mr+mt | 2 Bulk | 2
+ * 0x10 | 8 | Minimize Delay | 6 Interactive | 0
+ * 0x12 | 9 | mmc+md | 6 Interactive | 0
+ * 0x14 | 10 | mr+md | 6 Interactive | 0
+ * 0x16 | 11 | mmc+mr+md | 6 Interactive | 0
+ * 0x18 | 12 | mt+md | 4 Int. Bulk | 1
+ * 0x1a | 13 | mmc+mt+md | 4 Int. Bulk | 1
+ * 0x1c | 14 | mr+mt+md | 4 Int. Bulk | 1
+ * 0x1e | 15 | mmc+mr+mt+md | 4 Int. Bulk | 1
+ *
+ * When the queue is set to mode PfifoFastQueue::QUEUE_MODE_TOS, the
+ * above values are used to map packets into bands, and IP precedence
+ * bits are disregarded.
+ *
+ * When the queue is set to mode PfifoFastQueue::QUEUE_MODE_DSCP
+ * (the default), the following mappings are used.
+ *
+ * For DSCP, the following values are recommended for Linux in a patch
+ * to the netdev mailing list from Jesper Dangaard Brouer <brouer@redhat.com>
+ * on 15 Sept 2014. CS* values I made up myself.
+ *
+ * DSCP | Hex | Means | Linux Priority | Band
+ * -----|------|----------------------------|----------------|-----
+ * EF | 0x2E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
+ * AF11 | 0x0A | TC_PRIO_BULK=2 | 2 Bulk | 2
+ * AF21 | 0x12 | TC_PRIO_BULK=2 | 2 Bulk | 2
+ * AF31 | 0x1A | TC_PRIO_BULK=2 | 2 Bulk | 2
+ * AF41 | 0x22 | TC_PRIO_BULK=2 | 2 Bulk | 2
+ * AF12 | 0x0C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
+ * AF22 | 0x14 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
+ * AF32 | 0x1C | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
+ * AF42 | 0x34 | TC_PRIO_INTERACTIVE=6 | 6 Interactive | 0
+ * AF13 | 0x0E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
+ * AF23 | 0x16 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
+ * AF33 | 0x1E | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
+ * AF43 | 0x26 | TC_PRIO_INTERACTIVE_BULK=4 | 4 Int. Bulk | 1
+ * CS0 | 0x00 | TC_PRIO_BESTEFFORT | 0 Best Effort | 1
+ * CS1 | 0x20 | TC_PRIO_FILLER | 1 Filler | 2
+ * CS2 | 0x40 | TC_PRIO_BULK | 2 Bulk | 1
+ * CS3 | 0x60 | TC_PRIO_INTERACTIVE_BULK | 4 Int. Bulk | 1
+ * CS4 | 0x80 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
+ * CS5 | 0xA0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
+ * CS6 | 0xC0 | TC_PRIO_INTERACTIVE | 6 Interactive | 0
+ * CS7 | 0xE0 | TC_PRIO_CONTROL | 8 Control | 0
+ *
+ */
+class PfifoFastQueue : public PriorityQueue {
+public:
+ /**
+ * \brief Get the type ID.
+ * \return the object TypeId
+ */
+ static TypeId GetTypeId (void);
+ /**
+ * \brief PfifoFastQueue constructor
+ *
+ * Creates a queue with a depth of 1000 packets per band by default
+ */
+ PfifoFastQueue ();
+
+ virtual ~PfifoFastQueue();
+
+ /**
+ * \brief Enumeration of modes of Ipv4 header traffic class semantics
+ */
+ enum Ipv4TrafficClassMode
+ {
+ QUEUE_MODE_TOS, //!< use legacy TOS semantics to interpret TOS byte
+ QUEUE_MODE_DSCP, //!< use DSCP semantics to interpret TOS byte
+ };
+
+ /**
+ * \return The number of packets currently stored in one band of the queue
+ * \param band the band to check (0, 1, or 2)
+ */
+ uint32_t GetNPackets (uint32_t band) const;
+
+private:
+ virtual bool DoEnqueue (struct PriorityQueue::QueueElement);
+ virtual struct PriorityQueue::QueueElement DoDequeue (void);
+ uint32_t Classify (Ptr<const Packet> p) const;
+ uint32_t TosToBand (uint8_t tos) const;
+ uint32_t DscpToBand (Ipv4Header::DscpType dscpType) const;
+
+ std::queue<struct PriorityQueue::QueueElement> m_packets0; //!< the packets in band 0
+ std::queue<struct PriorityQueue::QueueElement> m_packets1; //!< the packets in band 1
+ std::queue<struct PriorityQueue::QueueElement> m_packets2; //!< the packets in band 2
+ uint32_t m_maxPackets; //!< max packets in the queue
+ Ipv4TrafficClassMode m_trafficClassMode; //!< traffic class mode
+};
+
+} // namespace ns3
+
+#endif /* PFIFO_FAST_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/priority-queue.cc Fri Jan 16 15:57:07 2015 -0800
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2014 University of Washington
+ *
+ * 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
+ */
+
+#include "ns3/log.h"
+#include "priority-queue.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("PriorityQueue");
+
+NS_OBJECT_ENSURE_REGISTERED (PriorityQueue);
+
+TypeId PriorityQueue::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::PriorityQueue")
+ .SetParent<Object> ();
+ return tid;
+}
+
+PriorityQueue::PriorityQueue ()
+ : m_nPackets (0)
+{
+ NS_LOG_FUNCTION (this);
+}
+
+bool
+PriorityQueue::Enqueue (struct QueueElement q)
+{
+ NS_LOG_FUNCTION (this << q.p << q.dest);
+ bool ret = DoEnqueue (q);
+ if (ret)
+ {
+ m_nPackets++;
+ }
+ return ret;
+}
+
+struct PriorityQueue::QueueElement
+PriorityQueue::Dequeue ()
+{
+ NS_LOG_FUNCTION (this);
+ struct QueueElement q = DoDequeue ();
+ if (q.p)
+ {
+ m_nPackets--;
+ }
+ return q;
+}
+
+uint32_t
+PriorityQueue::GetNPackets () const
+{
+ return m_nPackets;
+}
+
+void
+PriorityQueue::Drop (Ptr<Packet> p)
+{
+ NS_LOG_FUNCTION (this << p);
+}
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/model/priority-queue.h Fri Jan 16 15:57:07 2015 -0800
@@ -0,0 +1,91 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2014 University of Washington
+ *
+ * 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
+ */
+
+#ifndef PRIORITY_QUEUE_H
+#define PRIORITY_QUEUE_H
+
+#include <queue>
+#include "ns3/packet.h"
+#include "ns3/object.h"
+#include "ns3/ipv4-header.h"
+
+namespace ns3 {
+
+/**
+ * \ingroup internet-queues
+ *
+ */
+class PriorityQueue : public Object {
+public:
+ /**
+ * \brief Get the type ID.
+ * \return the object TypeId
+ */
+ static TypeId GetTypeId (void);
+
+ struct QueueElement
+ {
+ Ptr<Packet> p;
+ Address dest;
+ };
+
+ PriorityQueue ();
+
+ /**
+ * Place a packet into the rear of the Queue
+ * \param q packet to enqueue
+ * \param addr address to enqueue
+ * \return True if the operation was successful; false otherwise
+ */
+ bool Enqueue (struct QueueElement q);
+ /**
+ * Remove a packet from the front of the Queue
+ * \return 0 if the operation was not successful; the packet otherwise.
+ */
+ struct QueueElement Dequeue (void);
+
+ uint32_t GetNPackets (void) const;
+
+protected:
+ /**
+ * \brief Drop a packet
+ * \param packet packet that was dropped
+ * This method is called by subclasses to notify parent (this class) of packet drops.
+ */
+ void Drop (Ptr<Packet> packet);
+private:
+
+ /**
+ * Push a packet in the queue
+ * \param p the packet to enqueue
+ * \return true if success, false if the packet has been dropped.
+ */
+ virtual bool DoEnqueue (struct QueueElement) = 0;
+ /**
+ * Pull a packet from the queue
+ * \return the packet.
+ */
+ virtual struct QueueElement DoDequeue (void) = 0;
+
+ uint32_t m_nPackets; //!< Number of packets in the queue
+
+};
+
+} // namespace ns3
+
+#endif /* PriorityQueue */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet/test/pfifo-fast-queue-test-suite.cc Fri Jan 16 15:57:07 2015 -0800
@@ -0,0 +1,322 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2014 University of Washington
+ *
+ * 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
+ *
+ */
+
+#include "ns3/test.h"
+#include "ns3/pfifo-fast-queue.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/enum.h"
+#include "ns3/uinteger.h"
+
+using namespace ns3;
+
+/**
+ * This class tests that each possible TOS is enqueued in the right band
+ */
+class PfifoFastQueueTosPrioritization : public TestCase
+{
+public:
+ PfifoFastQueueTosPrioritization ();
+ virtual ~PfifoFastQueueTosPrioritization ();
+
+private:
+ virtual void DoRun (void);
+ Ptr<Packet> CreatePacketWithTos (uint8_t tos);
+ void TestTosValue (Ptr<PfifoFastQueue> queue, uint8_t tos, uint32_t band);
+};
+
+PfifoFastQueueTosPrioritization::PfifoFastQueueTosPrioritization ()
+ : TestCase ("Test TOS-based prioritization")
+{
+}
+
+PfifoFastQueueTosPrioritization::~PfifoFastQueueTosPrioritization ()
+{
+}
+
+Ptr<Packet>
+PfifoFastQueueTosPrioritization::CreatePacketWithTos (uint8_t tos)
+{
+ Ptr<Packet> p = Create<Packet> (100);
+ Ipv4Header ipHeader;
+ ipHeader.SetPayloadSize (100);
+ ipHeader.SetTos (tos);
+ ipHeader.SetProtocol (6);
+ p->AddHeader (ipHeader);
+ return p;
+}
+
+void
+PfifoFastQueueTosPrioritization::TestTosValue (Ptr<PfifoFastQueue> queue, uint8_t tos, uint32_t band)
+{
+ Ptr<Packet> p = CreatePacketWithTos (tos);
+ struct PriorityQueue::QueueElement q;
+ q.p = p;
+ queue->Enqueue (q);
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 1, "enqueued to unexpected band");
+ q = queue->Dequeue ();
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 0, "unable to dequeue");
+}
+
+void
+PfifoFastQueueTosPrioritization::DoRun (void)
+{
+ Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
+ bool ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_TOS));
+ NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 0, "initialized non-zero");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 0, "initialized non-zero");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 0, "initialized non-zero");
+
+ TestTosValue (queue, 0x0, 1);
+ TestTosValue (queue, 0x2, 2);
+ TestTosValue (queue, 0x4, 1);
+ TestTosValue (queue, 0x6, 1);
+ TestTosValue (queue, 0x8, 2);
+ TestTosValue (queue, 0xa, 2);
+ TestTosValue (queue, 0xc, 2);
+ TestTosValue (queue, 0xe, 2);
+ TestTosValue (queue, 0x10, 0);
+ TestTosValue (queue, 0x12, 0);
+ TestTosValue (queue, 0x14, 0);
+ TestTosValue (queue, 0x16, 0);
+ TestTosValue (queue, 0x18, 1);
+ TestTosValue (queue, 0x1a, 1);
+ TestTosValue (queue, 0x1c, 1);
+ TestTosValue (queue, 0x1e, 1);
+}
+
+/**
+ * This class tests that each possible DSCP is enqueued in the right band
+ */
+class PfifoFastQueueDscpPrioritization : public TestCase
+{
+public:
+ PfifoFastQueueDscpPrioritization ();
+ virtual ~PfifoFastQueueDscpPrioritization ();
+
+private:
+ virtual void DoRun (void);
+ Ptr<Packet> CreatePacketWithDscp (Ipv4Header::DscpType dscp);
+ void TestDscpValue (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp, uint32_t band);
+};
+
+PfifoFastQueueDscpPrioritization::PfifoFastQueueDscpPrioritization ()
+ : TestCase ("Test DSCP-based prioritization")
+{
+}
+
+PfifoFastQueueDscpPrioritization::~PfifoFastQueueDscpPrioritization ()
+{
+}
+
+Ptr<Packet>
+PfifoFastQueueDscpPrioritization::CreatePacketWithDscp (Ipv4Header::DscpType dscp)
+{
+ Ptr<Packet> p = Create<Packet> (100);
+ Ipv4Header ipHeader;
+ ipHeader.SetPayloadSize (100);
+ ipHeader.SetProtocol (6);
+ ipHeader.SetDscp (dscp);
+ p->AddHeader (ipHeader);
+ return p;
+}
+
+void
+PfifoFastQueueDscpPrioritization::TestDscpValue (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp, uint32_t band)
+{
+ Ptr<Packet> p = CreatePacketWithDscp (dscp);
+ struct PriorityQueue::QueueElement q;
+ q.p = p;
+ queue->Enqueue (q);
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 1, "enqueued to unexpected band");
+ q = queue->Dequeue ();
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (band), 0, "unable to dequeue");
+}
+
+void
+PfifoFastQueueDscpPrioritization::DoRun (void)
+{
+ Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
+ bool ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_DSCP));
+ NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 0, "initialized non-zero");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 0, "initialized non-zero");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 0, "initialized non-zero");
+
+ TestDscpValue (queue, Ipv4Header::DscpDefault, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_EF, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF11, 2);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF21, 2);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF31, 2);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF41, 2);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF12, 0);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF22, 0);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF32, 0);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF42, 0);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF13, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF23, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF33, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_AF43, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_CS1, 2);
+ TestDscpValue (queue, Ipv4Header::DSCP_CS2, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_CS3, 1);
+ TestDscpValue (queue, Ipv4Header::DSCP_CS4, 0);
+ TestDscpValue (queue, Ipv4Header::DSCP_CS5, 0);
+ TestDscpValue (queue, Ipv4Header::DSCP_CS6, 0);
+ TestDscpValue (queue, Ipv4Header::DSCP_CS7, 0);
+}
+
+/**
+ * This class tests that each band is txqueuelen deep
+ */
+class PfifoFastQueueOverflow : public TestCase
+{
+public:
+ PfifoFastQueueOverflow ();
+ virtual ~PfifoFastQueueOverflow ();
+
+private:
+ virtual void DoRun (void);
+ void AddPacket (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp);
+};
+
+PfifoFastQueueOverflow::PfifoFastQueueOverflow ()
+ : TestCase ("Test queue overflow")
+{
+}
+
+PfifoFastQueueOverflow::~PfifoFastQueueOverflow ()
+{
+}
+
+void
+PfifoFastQueueOverflow::AddPacket (Ptr<PfifoFastQueue> queue, Ipv4Header::DscpType dscp)
+{
+ Ptr<Packet> p = Create<Packet> (100);
+ Ipv4Header ipHeader;
+ ipHeader.SetPayloadSize (100);
+ ipHeader.SetProtocol (6);
+ ipHeader.SetDscp (dscp);
+ p->AddHeader (ipHeader);
+ struct PriorityQueue::QueueElement q;
+ q.p = p;
+ queue->Enqueue (q);
+}
+
+void
+PfifoFastQueueOverflow::DoRun (void)
+{
+ Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
+ bool ok = queue->SetAttributeFailSafe ("MaxPackets", UintegerValue (2));
+ NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
+ ok = queue->SetAttributeFailSafe ("Mode", EnumValue (PfifoFastQueue::QUEUE_MODE_DSCP));
+ NS_TEST_ASSERT_MSG_EQ (ok, true, "unable to set attribute");
+
+ // Add two packets per each band
+ AddPacket (queue, Ipv4Header::DSCP_AF42); // 0
+ AddPacket (queue, Ipv4Header::DSCP_AF42); // 0
+ AddPacket (queue, Ipv4Header::DSCP_AF13); // 1
+ AddPacket (queue, Ipv4Header::DSCP_AF13); // 1
+ AddPacket (queue, Ipv4Header::DSCP_AF11); // 2
+ AddPacket (queue, Ipv4Header::DSCP_AF11); // 2
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 2, "unexpected queue depth");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 2, "unexpected queue depth");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 2, "unexpected queue depth");
+ NS_TEST_ASSERT_MSG_EQ (queue->PriorityQueue::GetNPackets (), 6, "unexpected queue depth");
+ // Add a third packet to each band
+ AddPacket (queue, Ipv4Header::DSCP_AF42); // 0
+ AddPacket (queue, Ipv4Header::DSCP_AF13); // 1
+ AddPacket (queue, Ipv4Header::DSCP_AF11); // 2
+ // Bands should still have two packets each
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (0), 2, "unexpected queue depth");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 2, "unexpected queue depth");
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (2), 2, "unexpected queue depth");
+ NS_TEST_ASSERT_MSG_EQ (queue->PriorityQueue::GetNPackets (), 6, "unexpected queue depth");
+}
+
+/**
+ * This class tests that non-IP packets are handled by placing them into
+ * band 1
+ */
+class PfifoFastQueueNonIpHeader : public TestCase
+{
+public:
+ PfifoFastQueueNonIpHeader ();
+ virtual ~PfifoFastQueueNonIpHeader ();
+
+private:
+ virtual void DoRun (void);
+};
+
+PfifoFastQueueNonIpHeader::PfifoFastQueueNonIpHeader ()
+ : TestCase ("Test queue with non IP header")
+{
+}
+
+PfifoFastQueueNonIpHeader::~PfifoFastQueueNonIpHeader ()
+{
+}
+
+void
+PfifoFastQueueNonIpHeader::DoRun (void)
+{
+ // all packets with non-IP headers should enqueue in band 1
+ Ptr<PfifoFastQueue> queue = CreateObject<PfifoFastQueue> ();
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 0, "unexpected queue depth");
+ Ptr<Packet> p;
+ p = Create<Packet> ();
+ struct PriorityQueue::QueueElement q;
+ q.p = p;
+ queue->Enqueue (q);
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 1, "unexpected queue depth");
+ p = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello, world"), 12);
+ q.p = p;
+ queue->Enqueue (q);
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 2, "unexpected queue depth");
+ p = Create<Packet> (100);
+ uint8_t *buf = new uint8_t[100];
+ uint8_t counter = 0;
+ for (uint32_t i = 0; i < 100; i++)
+ {
+ buf[i] = counter++;
+ }
+ p->CopyData (buf, 100);
+ q.p = p;
+ queue->Enqueue (q);
+ NS_TEST_ASSERT_MSG_EQ (queue->GetNPackets (1), 3, "unexpected queue depth");
+ delete[] buf;
+}
+
+class PfifoFastQueueTestSuite : public TestSuite
+{
+public:
+ PfifoFastQueueTestSuite ();
+};
+
+PfifoFastQueueTestSuite::PfifoFastQueueTestSuite ()
+ : TestSuite ("internet-queues-pfifo-fast", UNIT)
+{
+ AddTestCase (new PfifoFastQueueTosPrioritization, TestCase::QUICK);
+ AddTestCase (new PfifoFastQueueDscpPrioritization, TestCase::QUICK);
+ AddTestCase (new PfifoFastQueueOverflow, TestCase::QUICK);
+ AddTestCase (new PfifoFastQueueNonIpHeader, TestCase::QUICK);
+}
+
+static PfifoFastQueueTestSuite pfifoFastQueueTestSuite;
+
--- a/src/internet/wscript Thu Nov 06 15:18:11 2014 -0800
+++ b/src/internet/wscript Fri Jan 16 15:57:07 2015 -0800
@@ -206,6 +206,8 @@
'model/ipv6-pmtu-cache.cc',
'model/ripng.cc',
'model/ripng-header.cc',
+ 'model/priority-queue.cc',
+ 'model/pfifo-fast-queue.cc',
'helper/ripng-helper.cc',
]
@@ -241,6 +243,7 @@
'test/ipv6-forwarding-test.cc',
'test/ipv6-ripng-test.cc',
'test/ipv6-address-helper-test-suite.cc',
+ 'test/pfifo-fast-queue-test-suite.cc',
'test/rtt-test.cc',
'test/codel-queue-test-suite.cc',
]
@@ -332,6 +335,8 @@
'model/ipv6-pmtu-cache.h',
'model/ripng.h',
'model/ripng-header.h',
+ 'model/priority-queue.h',
+ 'model/pfifo-fast-queue.h',
'helper/ripng-helper.h',
]
--- a/src/lr-wpan/model/lr-wpan-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/lr-wpan/model/lr-wpan-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -141,6 +141,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const { return true; }
/**
* The callback used by the MAC to hand over incoming packets to the
--- a/src/lte/model/lte-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/lte/model/lte-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -79,6 +79,7 @@
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const { return true; }
/**
* receive a packet from the lower layers in order to forward it to the upper layers
--- a/src/mesh/model/mesh-point-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/mesh/model/mesh-point-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -111,6 +111,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
virtual bool SupportsSendFrom () const;
+ virtual bool IsReady (void) const { return true; }
virtual Address GetMulticast (Ipv6Address addr) const;
virtual void DoDispose ();
--- a/src/network/model/net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/network/model/net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -335,6 +335,22 @@
*/
virtual bool SupportsSendFrom (void) const = 0;
+
+ /**
+ * Callback invoked when device wants to tell the higher layer that it
+ * may send a packet
+ */
+ typedef Callback < void, Ptr<NetDevice> > DeviceReadyCallback;
+
+ virtual void SetDeviceReadyCallback (DeviceReadyCallback cb) { m_deviceReadyCallback = cb; }
+
+ /**
+ * \return true if this interface is ready for a packet from the higher layer
+ */
+ virtual bool IsReady (void) const = 0;
+
+private:
+ DeviceReadyCallback m_deviceReadyCallback;
};
} // namespace ns3
--- a/src/network/utils/drop-tail-queue.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/network/utils/drop-tail-queue.cc Fri Jan 16 15:57:07 2015 -0800
@@ -79,6 +79,27 @@
NS_LOG_FUNCTION (this);
return m_mode;
}
+bool
+DropTailQueue::IsFull (void) const
+{
+ NS_LOG_FUNCTION (this);
+ if (m_mode == QUEUE_MODE_PACKETS && (m_packets.size () == m_maxPackets))
+ {
+ NS_LOG_LOGIC ("Queue full (at max packets)");
+ return true;
+ }
+ // XXX remove 1500 magic number
+ else if (m_mode == QUEUE_MODE_BYTES && (m_bytesInQueue + 1500 >= m_maxBytes))
+ {
+ NS_LOG_LOGIC ("Queue full (at max bytes)");
+ return true;
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Queue not full");
+ return false;
+ }
+}
bool
DropTailQueue::DoEnqueue (Ptr<Packet> p)
--- a/src/network/utils/drop-tail-queue.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/network/utils/drop-tail-queue.h Fri Jan 16 15:57:07 2015 -0800
@@ -49,6 +49,14 @@
virtual ~DropTailQueue();
/**
+ * \return true if queue is full
+ *
+ * XXX need to generalize this for byte and packet modes; presently
+ * assumes packet mode
+ */
+ virtual bool IsFull (void) const;
+
+ /**
* Set the operating mode of this device.
*
* \param mode The operating mode of this device.
--- a/src/network/utils/queue.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/network/utils/queue.h Fri Jan 16 15:57:07 2015 -0800
@@ -59,6 +59,10 @@
*/
bool IsEmpty (void) const;
/**
+ * \return true if the queue is full; false otherwise
+ */
+ virtual bool IsFull (void) const = 0;
+ /**
* Place a packet into the rear of the Queue
* \param p packet to enqueue
* \return True if the operation was successful; false otherwise
--- a/src/network/utils/red-queue.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/network/utils/red-queue.cc Fri Jan 16 15:57:07 2015 -0800
@@ -183,6 +183,17 @@
m_queueLimit = lim;
}
+bool
+RedQueue::IsFull (void) const
+{
+ NS_LOG_FUNCTION (this);
+ if (m_packets.size () > m_queueLimit)
+ {
+ return true;
+ }
+ return false;
+}
+
void
RedQueue::SetTh (double minTh, double maxTh)
{
--- a/src/network/utils/red-queue.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/network/utils/red-queue.h Fri Jan 16 15:57:07 2015 -0800
@@ -144,6 +144,7 @@
*/
uint32_t GetQueueSize (void);
+ virtual bool IsFull (void) const;
/**
* \brief Set the limit of the queue.
*
--- a/src/network/utils/simple-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/network/utils/simple-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -135,6 +135,7 @@
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const { return true; }
protected:
virtual void DoDispose (void);
--- a/src/point-to-point/model/point-to-point-net-device.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/point-to-point/model/point-to-point-net-device.cc Fri Jan 16 15:57:07 2015 -0800
@@ -148,6 +148,7 @@
m_txMachineState (READY),
m_channel (0),
m_linkUp (false),
+ m_isReady (true),
m_currentPkt (0)
{
NS_LOG_FUNCTION (this);
@@ -251,12 +252,15 @@
m_phyTxEndTrace (m_currentPkt);
m_currentPkt = 0;
+ bool blocked = m_queue->IsFull ();
Ptr<Packet> p = m_queue->Dequeue ();
if (p == 0)
{
- //
- // No packet was on the queue, so we just exit.
- //
+ NS_LOG_LOGIC ("No pending packets in device queue after tx complete");
+ if (blocked && !m_deviceReadyCallback.IsNull())
+ {
+ m_deviceReadyCallback (this);
+ }
return;
}
@@ -266,6 +270,11 @@
m_snifferTrace (p);
m_promiscSnifferTrace (p);
TransmitStart (p);
+ if (blocked && !m_deviceReadyCallback.IsNull())
+ {
+ NS_LOG_LOGIC ("Dequeue event frees space, notifying higher layer");
+ m_deviceReadyCallback (this);
+ }
}
bool
@@ -641,5 +650,20 @@
return 0;
}
+bool
+PointToPointNetDevice::IsReady (void) const
+{
+ NS_LOG_FUNCTION (this);
+/*
+ return (m_txMachineState == READY);
+*/
+ return !(m_queue->IsFull ());
+}
+
+void
+PointToPointNetDevice::SetDeviceReadyCallback (DeviceReadyCallback cb)
+{
+ m_deviceReadyCallback = cb;
+}
} // namespace ns3
--- a/src/point-to-point/model/point-to-point-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/point-to-point/model/point-to-point-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -190,6 +190,8 @@
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ void SetDeviceReadyCallback (DeviceReadyCallback cb);
+
protected:
/**
* \brief Handler for MPI receive event
@@ -224,6 +226,11 @@
*/
virtual void DoDispose (void);
+ /**
+ * \return true if this interface is ready for a packet from the higher layer
+ */
+ virtual bool IsReady (void) const;
+
private:
/**
@@ -441,7 +448,9 @@
// (promisc data)
uint32_t m_ifIndex; //!< Index of the interface
bool m_linkUp; //!< Identify if the link is up or not
+ bool m_isReady; //!< Indicate whether can accept packet from higher layer
TracedCallback<> m_linkChangeCallbacks; //!< Callback for the link change event
+ DeviceReadyCallback m_deviceReadyCallback;
static const uint16_t DEFAULT_MTU = 1500; //!< Default MTU
--- a/src/sixlowpan/model/sixlowpan-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/sixlowpan/model/sixlowpan-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -117,6 +117,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
virtual bool SupportsSendFrom () const;
+ virtual bool IsReady (void) const { return true; }
virtual Address GetMulticast (Ipv6Address addr) const;
/**
--- a/src/spectrum/model/aloha-noack-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/spectrum/model/aloha-noack-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -173,6 +173,7 @@
virtual Address GetMulticast (Ipv6Address addr) const;
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const { return true; }
--- a/src/spectrum/model/non-communicating-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/spectrum/model/non-communicating-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -115,6 +115,7 @@
virtual Address GetMulticast (Ipv6Address addr) const;
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const { return true; }
--- a/src/tap-bridge/model/tap-bridge.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/tap-bridge/model/tap-bridge.h Fri Jan 16 15:57:07 2015 -0800
@@ -206,6 +206,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
virtual bool SupportsSendFrom () const;
+ virtual bool IsReady () const { return true; }
virtual Address GetMulticast (Ipv6Address addr) const;
protected:
--- a/src/uan/model/uan-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/uan/model/uan-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -144,6 +144,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const { return true; }
virtual void AddLinkChangeCallback (Callback<void> callback);
virtual void SetAddress (Address address);
--- a/src/virtual-net-device/model/virtual-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/virtual-net-device/model/virtual-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -144,6 +144,7 @@
virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
virtual void SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb);
virtual bool SupportsSendFrom () const;
+ virtual bool IsReady (void) const { return true; }
virtual bool IsBridge (void) const;
protected:
--- a/src/wifi/model/wifi-net-device.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/wifi/model/wifi-net-device.cc Fri Jan 16 15:57:07 2015 -0800
@@ -71,7 +71,8 @@
}
WifiNetDevice::WifiNetDevice ()
- : m_configComplete (false)
+ : m_isReady (true),
+ m_configComplete (false)
{
NS_LOG_FUNCTION_NOARGS ();
}
@@ -365,5 +366,12 @@
return m_mac->SupportsSendFrom ();
}
+bool
+WifiNetDevice::IsReady (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return m_linkUp;
+}
+
} // namespace ns3
--- a/src/wifi/model/wifi-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/wifi/model/wifi-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -109,6 +109,7 @@
virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const;
protected:
virtual void DoDispose (void);
virtual void DoInitialize (void);
@@ -158,6 +159,7 @@
uint32_t m_ifIndex;
bool m_linkUp;
+ bool m_isReady;
TracedCallback<> m_linkChanges;
mutable uint16_t m_mtu;
bool m_configComplete;
--- a/src/wimax/model/wimax-net-device.cc Thu Nov 06 15:18:11 2014 -0800
+++ b/src/wimax/model/wimax-net-device.cc Fri Jan 16 15:57:07 2015 -0800
@@ -640,4 +640,12 @@
*/
NS_FATAL_ERROR ("Not implemented-- please implement and contribute a patch");
}
+
+bool
+WimaxNetDevice::IsReady (void) const
+{
+ NS_LOG_FUNCTION (this);
+ return true;
+}
+
} // namespace ns3
--- a/src/wimax/model/wimax-net-device.h Thu Nov 06 15:18:11 2014 -0800
+++ b/src/wimax/model/wimax-net-device.h Fri Jan 16 15:57:07 2015 -0800
@@ -218,6 +218,7 @@
virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
NetDevice::PromiscReceiveCallback GetPromiscReceiveCallback (void);
virtual bool SupportsSendFrom (void) const;
+ virtual bool IsReady (void) const;
TracedCallback<Ptr<const Packet>, const Mac48Address&> m_traceRx;
TracedCallback<Ptr<const Packet>, const Mac48Address&> m_traceTx;