RED
authorJohn Abraham <john.abraham@gatech.edu>
Mon, 05 Dec 2011 09:39:55 -0500
changeset 7613 62d636866e2e
parent 7612 ae2e795bc396
child 7614 4ba41cead1bf
RED
src/network/examples/wscript
src/network/test/examples-to-run.py
src/network/test/red-queue-test-suite.cc
src/network/utils/red-queue.cc
src/network/utils/red-queue.h
src/network/wscript
--- a/src/network/examples/wscript	Mon Dec 05 09:39:28 2011 -0500
+++ b/src/network/examples/wscript	Mon Dec 05 09:39:55 2011 -0500
@@ -10,3 +10,6 @@
     obj = bld.create_ns3_program('main-packet-tag', ['network'])
     obj.source = 'main-packet-tag.cc'
 
+    obj = bld.create_ns3_program('red-tests', ['point-to-point', 'internet', 'applications', 'flow-monitor'])
+    obj.source = 'red-tests.cc'
+
--- a/src/network/test/examples-to-run.py	Mon Dec 05 09:39:28 2011 -0500
+++ b/src/network/test/examples-to-run.py	Mon Dec 05 09:39:55 2011 -0500
@@ -10,6 +10,7 @@
 cpp_examples = [
     ("main-packet-header", "True", "True"),
     ("main-packet-tag", "True", "True"),
+    ("red-tests", "True", "True"),
 ]
 
 # A list of Python examples to run in order to ensure that they remain
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/network/test/red-queue-test-suite.cc	Mon Dec 05 09:39:55 2011 -0500
@@ -0,0 +1,280 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright © 2011 Marcos Talau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marcos Talau (talau@users.sourceforge.net)
+ *
+ */
+
+#include "ns3/test.h"
+#include "ns3/red-queue.h"
+#include "ns3/uinteger.h"
+#include "ns3/string.h"
+#include "ns3/double.h"
+#include "ns3/log.h"
+
+namespace ns3 {
+
+class RedQueueTestCase : public TestCase
+{
+public:
+  RedQueueTestCase ();
+  virtual void DoRun (void);
+private:  
+  void Enqueue(Ptr<RedQueue> queue, uint32_t size, uint32_t nPkt);
+  void RunRedTest(StringValue mode);
+};
+
+RedQueueTestCase::RedQueueTestCase ()
+  : TestCase ("Sanity check on the red queue implementation")
+{
+}
+
+void
+RedQueueTestCase::RunRedTest(StringValue mode)
+{
+  uint32_t pktSize = 0;
+  // 1 for packets; pktSize for bytes
+  uint32_t modeSize = 1;
+  double minTh = 2;
+  double maxTh = 5;
+  uint32_t qSize = 8;
+  Ptr<RedQueue> queue = CreateObject<RedQueue> ();
+
+  // test 1: simple enqueue/dequeue with no drops
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
+                         "Verify that we can actually set the attribute Mode");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
+                         "Verify that we can actually set the attribute MinTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
+                         "Verify that we can actually set the attribute MaxTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
+                         "Verify that we can actually set the attribute QueueLimit");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.002)), true,
+                         "Verify that we can actually set the attribute QW");
+
+  if (queue->GetMode () == RedQueue::BYTES)
+    {
+      pktSize = 1000;
+      modeSize = pktSize;
+      queue->SetTh (minTh * pktSize, maxTh * pktSize);
+      queue->SetQueueLimit (qSize * pktSize);
+    }
+
+  Ptr<Packet> p1, p2, p3, p4, p5, p6, p7, p8;
+  p1 = Create<Packet> (pktSize);
+  p2 = Create<Packet> (pktSize);
+  p3 = Create<Packet> (pktSize);
+  p4 = Create<Packet> (pktSize);
+  p5 = Create<Packet> (pktSize);
+  p6 = Create<Packet> (pktSize);
+  p7 = Create<Packet> (pktSize);
+  p8 = Create<Packet> (pktSize);
+
+  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 0 * modeSize, "There should be no packets in there");
+  queue->Enqueue (p1);
+  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 1 * modeSize, "There should be one packet in there");
+  queue->Enqueue (p2);
+  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 2 * modeSize, "There should be two packets in there");
+  queue->Enqueue (p3);
+  queue->Enqueue (p4);
+  queue->Enqueue (p5);
+  queue->Enqueue (p6);
+  queue->Enqueue (p7);
+  queue->Enqueue (p8);
+  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 8 * modeSize, "There should be eight packets in there");
+
+  Ptr<Packet> p;
+
+  p = queue->Dequeue ();
+  NS_TEST_EXPECT_MSG_EQ ((p != 0), true, "I want to remove the first packet");
+  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 7 * modeSize, "There should be seven packets in there");
+  NS_TEST_EXPECT_MSG_EQ (p->GetUid (), p1->GetUid (), "was this the first packet ?");
+
+  p = queue->Dequeue ();
+  NS_TEST_EXPECT_MSG_EQ ((p != 0), true, "I want to remove the second packet");
+  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 6 * modeSize, "There should be six packet in there");
+  NS_TEST_EXPECT_MSG_EQ (p->GetUid (), p2->GetUid (), "Was this the second packet ?");
+
+  p = queue->Dequeue ();
+  NS_TEST_EXPECT_MSG_EQ ((p != 0), true, "I want to remove the third packet");
+  NS_TEST_EXPECT_MSG_EQ (queue->GetQueueSize (), 5 * modeSize, "There should be five packets in there");
+  NS_TEST_EXPECT_MSG_EQ (p->GetUid (), p3->GetUid (), "Was this the third packet ?");
+
+  p = queue->Dequeue ();
+  p = queue->Dequeue ();
+  p = queue->Dequeue ();
+  p = queue->Dequeue ();
+  p = queue->Dequeue ();
+
+  p = queue->Dequeue ();
+  NS_TEST_EXPECT_MSG_EQ ((p == 0), true, "There are really no packets in there");
+
+
+  // test 2: more data, but with no drops
+  queue = CreateObject<RedQueue> ();
+  minTh = 70 * modeSize;
+  maxTh = 150 * modeSize;
+  qSize = 300 * modeSize;
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
+                         "Verify that we can actually set the attribute Mode");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
+                         "Verify that we can actually set the attribute MinTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
+                         "Verify that we can actually set the attribute MaxTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
+                         "Verify that we can actually set the attribute QueueLimit");
+  Enqueue(queue, pktSize, 300);
+  RedQueue::Stats st = StaticCast<RedQueue> (queue)->GetStats ();
+  NS_TEST_EXPECT_MSG_EQ (st.unforcedDrop, 0, "There should zero dropped packets due probability mark");
+  NS_TEST_EXPECT_MSG_EQ (st.forcedDrop, 0, "There should zero dropped packets due hardmark mark");
+  NS_TEST_EXPECT_MSG_EQ (st.qLimDrop, 0, "There should zero dropped packets due queue full");
+
+  // save number of drops from tests
+  struct d {
+    uint32_t test3;
+    uint32_t test4;
+    uint32_t test5;
+    uint32_t test6;
+    uint32_t test7;
+  } drop;
+
+
+  // test 3: more data, now drops due QW change
+  queue = CreateObject<RedQueue> ();
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
+                         "Verify that we can actually set the attribute Mode");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
+                         "Verify that we can actually set the attribute MinTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
+                         "Verify that we can actually set the attribute MaxTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
+                         "Verify that we can actually set the attribute QueueLimit");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
+                         "Verify that we can actually set the attribute QW");
+  Enqueue(queue, pktSize, 300);
+  st = StaticCast<RedQueue> (queue)->GetStats ();
+  drop.test3 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
+  NS_TEST_EXPECT_MSG_NE (drop.test3, 0, "There should be some dropped packets");
+
+
+  // test 4: reduced maxTh, this causes more drops
+  maxTh = 100 * modeSize;
+  queue = CreateObject<RedQueue> ();
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
+                         "Verify that we can actually set the attribute Mode");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
+                         "Verify that we can actually set the attribute MinTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
+                         "Verify that we can actually set the attribute MaxTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
+                         "Verify that we can actually set the attribute QueueLimit");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
+                         "Verify that we can actually set the attribute QW");
+  Enqueue(queue, pktSize, 300);
+  st = StaticCast<RedQueue> (queue)->GetStats ();
+  drop.test4 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
+  NS_TEST_EXPECT_MSG_GT (drop.test4, drop.test3, "Test 4 should have more drops than test 3");
+
+
+  // test 5: change drop probability to a high value (LInterm)
+  maxTh = 150 * modeSize;
+  queue = CreateObject<RedQueue> ();
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
+                         "Verify that we can actually set the attribute Mode");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
+                         "Verify that we can actually set the attribute MinTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
+                         "Verify that we can actually set the attribute MaxTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
+                         "Verify that we can actually set the attribute QueueLimit");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
+                         "Verify that we can actually set the attribute QW");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("LInterm", DoubleValue (5)), true,
+                         "Verify that we can actually set the attribute LInterm");
+  Enqueue(queue, pktSize, 300);
+  st = StaticCast<RedQueue> (queue)->GetStats ();
+  drop.test5 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
+  NS_TEST_EXPECT_MSG_GT (drop.test5, drop.test3, "Test 5 should have more drops than test 3");
+
+
+  // test 6: disable Gentle param
+  queue = CreateObject<RedQueue> ();
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
+                         "Verify that we can actually set the attribute Mode");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
+                         "Verify that we can actually set the attribute MinTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
+                         "Verify that we can actually set the attribute MaxTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
+                         "Verify that we can actually set the attribute QueueLimit");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
+                         "Verify that we can actually set the attribute QW");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Gentle", BooleanValue (false)), true,
+                         "Verify that we can actually set the attribute Gentle");
+  Enqueue(queue, pktSize, 300);
+  st = StaticCast<RedQueue> (queue)->GetStats ();
+  drop.test6 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
+  NS_TEST_EXPECT_MSG_GT (drop.test6, drop.test3, "Test 6 should have more drops than test 3");
+
+
+  // test 7: disable Wait param
+  queue = CreateObject<RedQueue> ();
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Mode", mode), true,
+                         "Verify that we can actually set the attribute Mode");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MinTh", DoubleValue (minTh)), true,
+                         "Verify that we can actually set the attribute MinTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("MaxTh", DoubleValue (maxTh)), true,
+                         "Verify that we can actually set the attribute MaxTh");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QueueLimit", UintegerValue (qSize)), true,
+                         "Verify that we can actually set the attribute QueueLimit");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("QW", DoubleValue (0.020)), true,
+                         "Verify that we can actually set the attribute QW");
+  NS_TEST_EXPECT_MSG_EQ (queue->SetAttributeFailSafe ("Wait", BooleanValue (false)), true,
+                         "Verify that we can actually set the attribute Wait");
+  Enqueue(queue, pktSize, 300);
+  st = StaticCast<RedQueue> (queue)->GetStats ();
+  drop.test7 = st.unforcedDrop + st.forcedDrop + st.qLimDrop;
+  NS_TEST_EXPECT_MSG_GT (drop.test7, drop.test3, "Test 7 should have more drops than test 3");
+}
+
+void 
+RedQueueTestCase::Enqueue(Ptr<RedQueue> queue, uint32_t size, uint32_t nPkt)
+{
+  for (uint32_t i = 0; i < nPkt; i++)
+    {
+      queue->Enqueue (Create<Packet> (size));
+    }
+}
+
+void
+RedQueueTestCase::DoRun (void)
+{
+  RunRedTest (StringValue("Packets"));
+  RunRedTest (StringValue("Bytes"));
+}
+
+static class RedQueueTestSuite : public TestSuite
+{
+public:
+  RedQueueTestSuite ()
+    : TestSuite ("red-queue", UNIT)
+  {
+    AddTestCase (new RedQueueTestCase ());
+  }
+} g_redQueueTestSuite;
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/network/utils/red-queue.cc	Mon Dec 05 09:39:55 2011 -0500
@@ -0,0 +1,646 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This code was ported from NS-2.34, with licence:
+ *
+ * Copyright (c) 1990-1997 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the Computer Systems
+ *	Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * This port: 
+ *
+ * Copyright © 2011 Marcos Talau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marcos Talau (talau@users.sourceforge.net)
+ *
+ * Thanks to: Duy Nguyen<duy@soe.ucsc.edu> by RED efforts in NS3
+ *
+ */
+
+/*
+ * PORT NOTE: Almost all comments have also been ported from NS-2
+ */
+
+#include "ns3/log.h"
+#include "ns3/enum.h"
+#include "ns3/uinteger.h"
+#include "ns3/double.h"
+#include "ns3/simulator.h"
+#include "ns3/abort.h"
+#include "red-queue.h"
+
+NS_LOG_COMPONENT_DEFINE ("RedQueue");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (RedQueue);
+
+TypeId RedQueue::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::RedQueue")
+    .SetParent<Queue> ()
+    .AddConstructor<RedQueue> ()
+    .AddAttribute ("Mode",
+                   "Bytes or packets",
+                   EnumValue (PACKETS),
+                   MakeEnumAccessor (&RedQueue::SetMode),
+                   MakeEnumChecker (BYTES, "Bytes",
+                                    PACKETS, "Packets"))
+    .AddAttribute ("MeanPktSize",
+                   "Average of packet size",
+                   UintegerValue (500),
+                   MakeUintegerAccessor (&RedQueue::m_meanPktSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("IdlePktSize",
+                   "Average packet size used during idle times. Used when m_cautions = 3",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&RedQueue::m_idlePktSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("Wait",
+                   "True for waiting between dropped packets",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&RedQueue::m_isWait),
+                   MakeBooleanChecker ())
+    .AddAttribute ("Gentle",
+                   "True to increases dropping probability slowly when average queue exceeds maxthresh",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&RedQueue::m_isGentle),
+                   MakeBooleanChecker ())
+    .AddAttribute ("MinTh",
+                   "Minimum average length threshold in packets/bytes",
+                   DoubleValue (5),
+                   MakeDoubleAccessor (&RedQueue::m_minTh),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MaxTh",
+                   "Maximum average length threshold in packets/bytes",
+                   DoubleValue (15),
+                   MakeDoubleAccessor (&RedQueue::m_maxTh),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("QueueLimit",
+                   "Queue limit in bytes/packets",
+                   UintegerValue (25),
+                   MakeUintegerAccessor (&RedQueue::m_queueLimit),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("QW",
+                   "Queue weight related to the exponential weighted moving average (EWMA)",
+                   DoubleValue (0.002),
+                   MakeDoubleAccessor (&RedQueue::m_qW),
+                   MakeDoubleChecker <double> ())
+    .AddAttribute ("LInterm",
+                   "The maximum probability of dropping a packet",
+                   DoubleValue (50),
+                   MakeDoubleAccessor (&RedQueue::m_lInterm),
+                   MakeDoubleChecker <double> ())
+    .AddAttribute ("Ns1Compat",
+                   "NS-1 compatibility",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&RedQueue::m_isNs1Compat),
+                   MakeBooleanChecker ())
+    .AddAttribute ("LinkBandwidth", 
+                   "The RED link bandwidth",
+                   DataRateValue (DataRate ("1.5Mbps")),
+                   MakeDataRateAccessor (&RedQueue::m_linkBandwidth),
+                   MakeDataRateChecker ())
+    .AddAttribute ("LinkDelay", 
+                   "The RED link delay",
+                   TimeValue (MilliSeconds (20)),
+                   MakeTimeAccessor (&RedQueue::m_linkDelay),
+                   MakeTimeChecker ())
+  ;
+
+  return tid;
+}
+
+RedQueue::RedQueue () :
+  Queue (),
+  m_packets (),
+  m_bytesInQueue (0),
+  m_hasRedStarted (false)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+RedQueue::~RedQueue ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+RedQueue::SetMode (enum Mode mode)
+{
+  NS_LOG_FUNCTION (mode);
+  m_mode = mode;
+}
+
+RedQueue::Mode
+RedQueue::GetMode (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_mode;
+}
+
+void
+RedQueue::SetQueueLimit (uint32_t lim)
+{
+  NS_LOG_FUNCTION (lim);
+  m_queueLimit = lim;
+}
+
+void
+RedQueue::SetTh (double minTh, double maxTh)
+{
+  NS_LOG_FUNCTION (this << minTh << maxTh);
+  NS_ASSERT(minTh <= maxTh);
+  m_minTh = minTh;
+  m_maxTh = maxTh;
+}
+
+RedQueue::Stats
+RedQueue::GetStats ()
+{
+  return m_stats;
+}
+
+bool
+RedQueue::DoEnqueue (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << p);
+
+  if (! m_hasRedStarted )
+    {
+      NS_LOG_INFO ("Initializing RED params.");
+      InitializeParams ();
+      m_hasRedStarted = true;
+    }
+
+  uint32_t nQueued;
+
+  if (GetMode () == BYTES)
+    {
+      NS_LOG_DEBUG ("Enqueue in bytes mode");
+      nQueued = m_bytesInQueue;
+    }
+  else if (GetMode () == PACKETS)
+    {
+      NS_LOG_DEBUG ("Enqueue in packets mode");
+      nQueued = m_packets.size ();
+    }
+
+  // simulate number of packets arrival during idle period
+  uint32_t m = 0;
+
+  if (m_idle == 1)
+    {
+      NS_LOG_DEBUG ("RED Queue is idle.");
+      Time now = Simulator::Now ();
+
+      if (m_cautious == 3)
+        {
+          double ptc = m_ptc * m_meanPktSize / m_idlePktSize;
+          m = uint32_t (ptc * (now - m_idleTime).GetSeconds ());
+        }
+      else
+        {
+          m = uint32_t (m_ptc * (now - m_idleTime).GetSeconds ());
+        }
+
+      m_idle = 0;
+    }
+
+  m_qAvg = Estimator (nQueued, m + 1, m_qAvg, m_qW);
+
+  NS_LOG_DEBUG ("\t bytesInQueue  " << m_bytesInQueue << "\tQavg " << m_qAvg);
+  NS_LOG_DEBUG ("\t packetsInQueue  " << m_packets.size () << "\tQavg " << m_qAvg);
+
+  m_count++;
+  m_countBytes += p->GetSize ();
+
+  uint32_t dropType = DTYPE_NONE;
+  if (m_qAvg >= m_minTh && nQueued > 1)
+    {
+      if ((! m_isGentle && m_qAvg >= m_maxTh) ||
+          (m_isGentle && m_qAvg >= 2 * m_maxTh))
+          {
+            NS_LOG_DEBUG ("adding DROP FORCED MARK");
+            dropType = DTYPE_FORCED;
+          }
+      else if (m_old == 0)
+        {
+          /* 
+           * The average queue size has just crossed the
+           * threshold from below to above "minthresh", or
+           * from above "minthresh" with an empty queue to
+           * above "minthresh" with a nonempty queue.
+           */
+          m_count = 1;
+          m_countBytes = p->GetSize();
+          m_old = 1;
+        }
+      else if (DropEarly (p, nQueued))
+        {
+          NS_LOG_LOGIC ("DropEarly returns 1");
+          dropType = DTYPE_UNFORCED;
+        }
+    }
+  else 
+    {
+      // No packets are being dropped
+      m_vProb = 0.0;
+      m_old = 0;
+    }
+
+  if (nQueued >= m_queueLimit)
+    {
+      NS_LOG_DEBUG ("\t Dropping due to Queue Full " << nQueued);
+      dropType = DTYPE_FORCED;
+      m_stats.qLimDrop++;
+    }
+
+  if (dropType == DTYPE_UNFORCED)
+    {
+      NS_LOG_DEBUG ("\t Dropping due to Prob Mark " << m_qAvg);
+      m_stats.unforcedDrop++;
+      Drop (p);
+      return false;
+    }
+  else if (dropType == DTYPE_FORCED)
+    {
+      NS_LOG_DEBUG ("\t Dropping due to Hard Mark " << m_qAvg);
+      m_stats.forcedDrop++;
+      Drop (p);
+      if (m_isNs1Compat)
+        {
+          m_count = 0;
+          m_countBytes = 0;
+        }
+      return false;
+    }
+
+  m_bytesInQueue += p->GetSize ();
+  m_packets.push_back (p);
+
+  NS_LOG_LOGIC ("Number packets " << m_packets.size ());
+  NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue);
+  
+  return true;
+}
+
+/*
+ * Note: if the link bandwidth changes in the course of the
+ * simulation, the bandwidth-dependent RED parameters do not change.
+ * This should be fixed, but it would require some extra parameters,
+ * and didn't seem worth the trouble...
+ */
+void
+RedQueue::InitializeParams (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  m_stats.forcedDrop = 0;
+  m_stats.unforcedDrop = 0;
+  m_stats.qLimDrop = 0;
+
+  m_cautious = 0;
+  m_ptc = m_linkBandwidth.GetBitRate () / (8.0 * m_meanPktSize);
+  
+  m_qAvg = 0.0;
+  m_count = 0;
+  m_countBytes = 0;
+  m_old = 0;
+  m_idle = 1;
+
+  double th_diff = (m_maxTh - m_minTh);
+  if (th_diff == 0)
+    {
+      th_diff = 1.0; 
+    }
+  m_vA = 1.0 / th_diff;
+  m_curMaxP = 1.0 / m_lInterm;
+  m_vB = - m_minTh / th_diff;
+  
+  if (m_isGentle)
+    {
+      m_vC = (1.0 - m_curMaxP) / m_maxTh;
+      m_vD = 2.0 * m_curMaxP - 1.0;
+    }
+  m_idleTime = NanoSeconds (0);
+
+/*
+ * If m_qW=0, set it to a reasonable value of 1-exp(-1/C)
+ * This corresponds to choosing m_qW to be of that value for
+ * which the packet time constant -1/ln(1-m)qW) per default RTT 
+ * of 100ms is an order of magnitude more than the link capacity, C.
+ *
+ * If m_qW=-1, then the queue weight is set to be a function of
+ * the bandwidth and the link propagation delay.  In particular, 
+ * the default RTT is assumed to be three times the link delay and 
+ * transmission delay, if this gives a default RTT greater than 100 ms. 
+ *
+ * If m_qW=-2, set it to a reasonable value of 1-exp(-10/C).
+ */
+  if (m_qW == 0.0)
+    {
+      m_qW = 1.0 - exp(-1.0 / m_ptc);
+    }
+  else if (m_qW == -1.0)
+    {
+      double rtt = 3.0 * (m_linkDelay.GetSeconds () + 1.0 / m_ptc);
+
+      if (rtt < 0.1)
+        {
+          rtt = 0.1;
+        }
+      m_qW = 1.0 - exp(-1.0 / (10 * rtt * m_ptc));
+    }
+  else if (m_qW == -2.0)
+    {
+      m_qW = 1.0 - exp(-10.0 / m_ptc);
+    }
+
+  // TODO: implement adaptive RED
+
+  NS_LOG_DEBUG ("\tm_delay " << m_linkDelay.GetSeconds () << "; m_isWait " << m_isWait << "; m_qW " << m_qW << "; m_ptc " << m_ptc << "; m_minTh " << m_minTh << "; m_maxTh " << m_maxTh << "; m_isGentle " << m_isGentle << "; th_diff " << th_diff << "; lInterm " << m_lInterm << "; va " << m_vA <<  "; cur_max_p " << m_curMaxP << "; v_b " << m_vB <<  "; m_vC " << m_vC << "; m_vD " <<  m_vD);
+}
+
+// Compute the average queue size
+double
+RedQueue::Estimator (uint32_t nQueued, uint32_t m, double qAvg, double qW)
+{
+  NS_LOG_FUNCTION (this << nQueued << m << qAvg << qW);
+  double newAve;
+
+  newAve = qAvg;
+  while (--m >= 1)
+    {
+      newAve *= 1.0 - qW;
+    }
+  newAve *= 1.0 - qW;
+  newAve += qW * nQueued;
+
+  // TODO: implement adaptive RED
+
+  return newAve;
+}
+
+// Check if packet p needs to be dropped due to probability mark
+uint32_t
+RedQueue::DropEarly (Ptr<Packet> p, uint32_t qSize)
+{
+  NS_LOG_FUNCTION (this << p << qSize);
+  m_vProb1 = CalculatePNew(m_qAvg, m_maxTh, m_isGentle, m_vA, m_vB, m_vC, m_vD, m_curMaxP);
+  m_vProb = ModifyP(m_vProb1, m_count, m_countBytes, m_meanPktSize, m_isWait, p->GetSize ());
+
+  // Drop probability is computed, pick random number and act
+  if (m_cautious == 1)
+    {
+      /*
+       * Don't drop/mark if the instantaneous queue is much below the average.
+       * For experimental purposes only.
+       * pkts: the number of packets arriving in 50 ms
+       */
+      double pkts = m_ptc * 0.05;
+      double fraction = pow ((1 - m_qW), pkts);
+
+      if ((double) qSize < fraction * m_qAvg)
+        {
+          // Queue could have been empty for 0.05 seconds
+          return 0;
+        }
+    }
+
+  UniformVariable uV;
+  double u = uV.GetValue ();
+
+  if (m_cautious == 2)
+    {
+      /*
+       * Decrease the drop probability if the instantaneous
+       * queue is much below the average.
+       * For experimental purposes only.
+       * pkts: the number of packets arriving in 50 ms
+       */
+      double pkts = m_ptc * 0.05;
+      double fraction = pow ((1 - m_qW), pkts);
+      double ratio = qSize / (fraction * m_qAvg);
+
+      if (ratio < 1.0)
+        {
+          u *= 1.0 / ratio;
+        }
+    }
+
+  if (u <= m_vProb)
+    {
+      NS_LOG_LOGIC ("u <= m_vProb; u " << u << "; m_vProb " << m_vProb);
+
+      // DROP or MARK
+      m_count = 0;
+      m_countBytes = 0;
+      // TODO: Implement set bit to mark
+
+      return 1; // drop
+    }
+
+  return 0; // no drop/mark
+}
+
+// Returns a probability using these function parameters for the DropEarly funtion
+double
+RedQueue::CalculatePNew (double qAvg, double maxTh, bool isGentle, double vA,
+                         double vB, double vC, double vD, double maxP)
+{
+  NS_LOG_FUNCTION (this << qAvg << maxTh << isGentle << vA << vB << vC << vD << maxP);
+  double p;
+
+  if (isGentle && qAvg >= maxTh)
+    {
+      // p ranges from maxP to 1 as the average queue
+      // Size ranges from maxTh to twice maxTh
+      p = vC * qAvg + vD;
+    }
+  else if (!isGentle && qAvg >= maxTh)
+    {
+      /* 
+       * OLD: p continues to range linearly above max_p as
+       * the average queue size ranges above th_max.
+       * NEW: p is set to 1.0
+       */
+      p = 1.0;
+    }
+  else
+    {
+      /*
+       * p ranges from 0 to max_p as the average queue size ranges from
+       * th_min to th_max
+       */
+      p = vA * qAvg + vB;
+      p *= maxP;
+    }
+
+  if (p > 1.0)
+    {
+      p = 1.0;
+    }
+
+  return p;
+}
+
+// Returns a probability using these function parameters for the DropEarly funtion
+double 
+RedQueue::ModifyP (double p, uint32_t count, uint32_t countBytes,
+                  uint32_t meanPktSize, bool isWait, uint32_t size)
+{
+  NS_LOG_FUNCTION (this << p << count << countBytes << meanPktSize << isWait << size);
+  double count1 = (double) count;
+
+  if (GetMode () == BYTES)
+    {
+      count1 = (double) (countBytes / meanPktSize);
+    }
+
+  if (isWait)
+    {
+      if (count1 * p < 1.0)
+        {
+          p = 0.0;
+        }
+      else if (count1 * p < 2.0)
+        {
+          p /= (2.0 - count1 * p);
+        }
+      else
+        {
+          p = 1.0;
+        }
+    }
+  else
+    {
+      if (count1 * p < 1.0)
+        {
+          p /= (1.0 - count1 * p);
+        }
+      else
+        {
+          p = 1.0;
+        }
+    }
+
+  if ((GetMode () == BYTES) && (p < 1.0))
+    {
+      p = (p * size) / meanPktSize;
+    }
+
+  if (p > 1.0)
+    {
+      p = 1.0;
+    }
+
+  return p;
+}
+
+uint32_t
+RedQueue::GetQueueSize (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  if (GetMode () == BYTES)
+    {
+      return m_bytesInQueue;
+    }
+  else if (GetMode () == PACKETS)
+    {
+      return m_packets.size ();
+    }
+  else
+    {
+      NS_ABORT_MSG ("Unknown RED mode.");
+    }
+}
+
+Ptr<Packet>
+RedQueue::DoDequeue (void)
+{
+  NS_LOG_FUNCTION (this);
+
+  if (m_packets.empty ())
+    {
+      NS_LOG_LOGIC ("Queue empty");
+      m_idle = 1;
+      m_idleTime = Simulator::Now ();
+
+      return 0;
+    }
+  else
+    {
+      m_idle = 0;
+      Ptr<Packet> p = m_packets.front ();
+      m_packets.pop_front ();
+      m_bytesInQueue -= p->GetSize ();
+
+      NS_LOG_LOGIC ("Popped " << p);
+
+      NS_LOG_LOGIC ("Number packets " << m_packets.size ());
+      NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue);
+
+      return p;
+    }
+}
+
+Ptr<const Packet>
+RedQueue::DoPeek (void) const
+{
+  NS_LOG_FUNCTION (this);
+  if (m_packets.empty ())
+    {
+      NS_LOG_LOGIC ("Queue empty");
+      return 0;
+    }
+
+  Ptr<Packet> p = m_packets.front ();
+
+  NS_LOG_LOGIC ("Number packets " << m_packets.size ());
+  NS_LOG_LOGIC ("Number bytes " << m_bytesInQueue);
+
+  return p;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/network/utils/red-queue.h	Mon Dec 05 09:39:55 2011 -0500
@@ -0,0 +1,261 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This code was ported from NS-2.34, with licence:
+ *
+ * Copyright (c) 1990-1997 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *	This product includes software developed by the Computer Systems
+ *	Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ *    to endorse or promote products derived from this software without
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * This port:
+ *
+ * Copyright © 2011 Marcos Talau
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Marcos Talau (talau@users.sourceforge.net)
+ *
+ * Thanks to: Duy Nguyen<duy@soe.ucsc.edu> by RED efforts in NS3
+ *
+ */
+
+/*
+ * PORT NOTE: Almost all comments also been ported from NS-2
+ */
+
+#ifndef RED_QUEUE_H
+#define RED_QUEUE_H
+
+#include <queue>
+#include "ns3/packet.h"
+#include "ns3/queue.h"
+#include "ns3/nstime.h"
+#include "ns3/random-variable.h"
+#include "ns3/boolean.h"
+#include "ns3/data-rate.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+
+class TraceContainer;
+
+/*
+ * \ingroup queue
+ *
+ * \brief A RED packet queue
+ */
+class RedQueue : public Queue
+{
+public:
+  static TypeId GetTypeId (void);
+  /*
+   * \brief RedQueue Constructor
+   *
+   * Create a RED queue
+   */
+  RedQueue ();
+
+  virtual ~RedQueue ();
+
+  typedef struct
+  {
+    // Early probability drops
+    uint32_t unforcedDrop;
+    // Forced drops, qavg > max threshold
+    uint32_t forcedDrop;
+    // Drops due to queue limits
+    uint32_t qLimDrop;
+  } Stats;
+
+  // Drop types
+  enum
+    {
+      DTYPE_NONE,      // Ok, no drop
+      DTYPE_FORCED,    // A "forced" drop
+      DTYPE_UNFORCED,  // An "unforced" (random) drop
+    };
+
+  /*
+   * Enumeration of the modes supported in the class.
+   *
+   */
+  enum Mode
+  {
+    ILLEGAL,     // Mode not set
+    PACKETS,     // Use number of packets for maximum queue size
+    BYTES,       // Use number of bytes for maximum queue size
+  };
+
+  /*
+   * Set the operating mode of this device.
+   *
+   * \param mode The operating mode of this device.
+   */
+  void SetMode (RedQueue::Mode mode);
+
+  /*
+   * Get the encapsulation mode of this device.
+   *
+   * \returns The encapsulation mode of this device.
+   */
+  RedQueue::Mode  GetMode (void);
+
+  /*
+   * Get the current value of the queue in bytes or packets.
+   *
+   * \returns The queue size in bytes or packets.
+   */
+  uint32_t GetQueueSize (void);
+
+  /*
+   * Set the limit of the queue.
+   *
+   * \param lim The limit in bytes or packets.
+   */
+  void SetQueueLimit(uint32_t lim);
+
+  /*
+   * Set the thresh limits of RED.
+   *
+   * \param min Minimum thresh in bytes or packets.
+   * \param max Maximum thresh in bytes or packets.
+   */
+  void SetTh(double minTh, double maxTh);
+
+  /*
+   * Get the RED statistics after running.
+   *
+   * \returns The drop statistics.
+   */
+  Stats GetStats();
+
+private:
+  virtual bool DoEnqueue (Ptr<Packet> p);
+  virtual Ptr<Packet> DoDequeue (void);
+  virtual Ptr<const Packet> DoPeek (void) const;
+
+  // ...
+  void InitializeParams (void);
+  // Compute the average queue size
+  double Estimator (uint32_t nQueued, uint32_t m, double qAvg, double qW);
+  // Check if packet p needs to be dropped due to probability mark
+  uint32_t DropEarly (Ptr<Packet> p, uint32_t qSize);
+  // Returns a probability using these function parameters for the DropEarly funtion
+  double CalculatePNew (double qAvg, double maxTh, bool gentle, double vA,
+                        double vB, double vC, double vD, double maxP);
+  // Returns a probability using these function parameters for the DropEarly funtion
+  double ModifyP(double p, uint32_t count, uint32_t countBytes,
+                 uint32_t meanPktSize, bool wait, uint32_t size);
+
+  std::list<Ptr<Packet> > m_packets;
+
+  uint32_t m_bytesInQueue;
+  bool m_hasRedStarted;
+  Stats m_stats;
+
+  // ** Variables supplied by user
+  // Bytes or packets?
+  Mode m_mode;
+  // Avg pkt size
+  uint32_t m_meanPktSize;
+  // Avg pkt size used during idle times
+  uint32_t m_idlePktSize;
+  // True for waiting between dropped packets
+  bool m_isWait;
+  // True to increases dropping prob. slowly when ave queue exceeds maxthresh
+  bool m_isGentle;
+  // Min avg length threshold (bytes)
+  double m_minTh;
+  // Max avg length threshold (bytes), should be >= 2*minTh
+  double m_maxTh;
+  // Queue limit in bytes / packets
+  uint32_t m_queueLimit;
+  // Queue weight given to cur q size sample
+  double m_qW;
+  // The max probability of dropping a packet
+  double m_lInterm;
+  // Ns-1 compatibility
+  bool m_isNs1Compat;
+  // Link bandwidth
+  DataRate m_linkBandwidth;
+  // Link delay
+  Time m_linkDelay;
+
+  // ** Variables maintained by RED
+  // Prob. of packet drop before "count"
+  double m_vProb1;
+  // v_prob = v_a * v_ave + v_b
+  double m_vA;
+  double m_vB;
+  // Used for "gentle" mode
+  double m_vC;
+  // Used for "gentle" mode
+  double m_vD;
+  // Current max_p
+  double m_curMaxP;
+  // Prob. of packet drop
+  double m_vProb;
+  // # of bytes since last drop
+  uint32_t m_countBytes;
+  // 0 when average queue first exceeds thresh
+  uint32_t m_old;
+  // 0/1 idle status
+  uint32_t m_idle;
+  // packet time constant in packets/second
+  double m_ptc;
+  // Average queue length
+  double m_qAvg;
+  // number of packets since last random number generation
+  uint32_t m_count;
+  /*
+   * 0 for default RED
+   * 1 experimental (see red-queue.cc)
+   * 2 experimental (see red-queue.cc)
+   * 3 use Idle packet size in the ptc
+   */
+  uint32_t m_cautious;
+  // Start of current idle period
+  Time m_idleTime;
+};
+
+}; // namespace ns3
+
+#endif // RED_QUEUE_H
--- a/src/network/wscript	Mon Dec 05 09:39:28 2011 -0500
+++ b/src/network/wscript	Mon Dec 05 09:39:55 2011 -0500
@@ -47,6 +47,7 @@
         'utils/pcap-file-wrapper.cc',
         'utils/queue.cc',
         'utils/radiotap-header.cc',
+        'utils/red-queue.cc',
         'utils/simple-channel.cc',
         'utils/simple-net-device.cc',
         'helper/application-container.cc',
@@ -64,6 +65,7 @@
         'test/packet-test-suite.cc',
         'test/packet-metadata-test.cc',
         'test/pcap-file-test-suite.cc',
+        'test/red-queue-test-suite.cc',
         'test/sequence-number-test-suite.cc',
         ]
 
@@ -115,6 +117,7 @@
         'utils/generic-phy.h',
         'utils/queue.h',
         'utils/radiotap-header.h',
+        'utils/red-queue.h',
         'utils/sequence-number.h',
         'utils/sgi-hashmap.h',
         'utils/simple-channel.h',