refactoring for IP priority queue sublayer
authorTom Henderson <tomh@tomh.org>
Fri, 16 Jan 2015 15:57:07 -0800
changeset 11046 b6891bd5dedd
parent 11045 4e1543dc9d68
child 11047 0eb710c869eb
refactoring for IP priority queue sublayer
src/bridge/model/bridge-net-device.h
src/csma/model/csma-net-device.cc
src/csma/model/csma-net-device.h
src/fd-net-device/model/fd-net-device.h
src/internet-queues/examples/bench-queue.cc
src/internet-queues/examples/wscript
src/internet-queues/model/pfifo-fast-queue.cc
src/internet-queues/model/pfifo-fast-queue.h
src/internet-queues/test/pfifo-fast-queue-test-suite.cc
src/internet-queues/wscript
src/internet/examples/bench-queue.cc
src/internet/examples/wscript
src/internet/model/codel-queue.cc
src/internet/model/codel-queue.h
src/internet/model/ipv4-interface.cc
src/internet/model/ipv4-interface.h
src/internet/model/loopback-net-device.h
src/internet/model/pfifo-fast-queue.cc
src/internet/model/pfifo-fast-queue.h
src/internet/model/priority-queue.cc
src/internet/model/priority-queue.h
src/internet/test/pfifo-fast-queue-test-suite.cc
src/internet/wscript
src/lr-wpan/model/lr-wpan-net-device.h
src/lte/model/lte-net-device.h
src/mesh/model/mesh-point-device.h
src/network/model/net-device.h
src/network/utils/drop-tail-queue.cc
src/network/utils/drop-tail-queue.h
src/network/utils/queue.h
src/network/utils/red-queue.cc
src/network/utils/red-queue.h
src/network/utils/simple-net-device.h
src/point-to-point/model/point-to-point-net-device.cc
src/point-to-point/model/point-to-point-net-device.h
src/sixlowpan/model/sixlowpan-net-device.h
src/spectrum/model/aloha-noack-net-device.h
src/spectrum/model/non-communicating-net-device.h
src/tap-bridge/model/tap-bridge.h
src/uan/model/uan-net-device.h
src/virtual-net-device/model/virtual-net-device.h
src/wifi/model/wifi-net-device.cc
src/wifi/model/wifi-net-device.h
src/wimax/model/wimax-net-device.cc
src/wimax/model/wimax-net-device.h
--- 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;