--- 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',