diff --git a/src/network/examples/droptail_vs_red.cc b/src/network/examples/droptail_vs_red.cc new file mode 100644 index 000000000..7eddf4ff3 --- /dev/null +++ b/src/network/examples/droptail_vs_red.cc @@ -0,0 +1,160 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * 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 + * + * Author: John Abraham + * + */ + + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/internet-module.h" +#include "ns3/point-to-point-module.h" +#include "ns3/applications-module.h" +#include "ns3/point-to-point-layout-module.h" + +#include +#include +#include + +using namespace ns3; +using namespace std; + + +int main (int argc, char *argv[]) +{ + uint32_t nLeaf = 5; + uint32_t maxPackets = 100; + uint32_t modeBytes = 0; + double minTh = 50; + double maxTh = 80; + uint32_t pktSize = 512; + std::string appDataRate = "10Mbps"; + std::string queueType = "DropTail"; + uint16_t port = 5001; + std::string bottleNeckLinkBw = "1Mbps"; + std::string bottleNeckLinkDelay = "50ms"; + + CommandLine cmd; + cmd.AddValue ("nLeaf", "Number of left and right side leaf nodes", nLeaf); + cmd.AddValue ("maxPackets","Max Packets allowed in the queue", maxPackets); + cmd.AddValue ("queueType", "Set Queue type to DropTail or RED", queueType); + cmd.AddValue ("appPktSize", "Set OnOff App Packet Size", pktSize); + cmd.AddValue ("appDataRate", "Set OnOff App DataRate", appDataRate); + cmd.AddValue ("modeBytes", "Set Queue mode to Packets <0> or bytes <1>", modeBytes); + + cmd.AddValue ("redMinTh", "RED queue minimum threshold", minTh); + cmd.AddValue ("redMaxTh", "RED queue maximum threshold", maxTh); + + + Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (pktSize)); + Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue (appDataRate)); + + cmd.Parse (argc,argv); + + if (!modeBytes) + { + Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("Packets")); + Config::SetDefault ("ns3::DropTailQueue::MaxPackets", UintegerValue (maxPackets)); + Config::SetDefault ("ns3::RedQueue::Mode", StringValue ("Packets")); + Config::SetDefault ("ns3::RedQueue::QueueLimit", UintegerValue (maxPackets)); + } + else + { + Config::SetDefault ("ns3::DropTailQueue::Mode", StringValue ("Bytes")); + Config::SetDefault ("ns3::DropTailQueue::MaxBytes", UintegerValue (maxPackets * pktSize)); + Config::SetDefault ("ns3::RedQueue::Mode", StringValue ("Bytes")); + Config::SetDefault ("ns3::RedQueue::QueueLimit", UintegerValue (maxPackets * pktSize)); + minTh *= pktSize; + maxTh *= pktSize; + } + + // Create the point-to-point link helpers + PointToPointHelper bottleNeckLink; + bottleNeckLink.SetDeviceAttribute ("DataRate", StringValue (bottleNeckLinkBw)); + bottleNeckLink.SetChannelAttribute ("Delay", StringValue (bottleNeckLinkDelay)); + if (queueType == "RED") + { + bottleNeckLink.SetQueue ("ns3::RedQueue", + "MinTh", DoubleValue (minTh), + "MaxTh", DoubleValue (maxTh), + "LinkBandwidth", StringValue (bottleNeckLinkBw), + "LinkDelay", StringValue (bottleNeckLinkDelay)); + } + PointToPointHelper pointToPointLeaf; + pointToPointLeaf.SetDeviceAttribute ("DataRate", StringValue ("10Mbps")); + pointToPointLeaf.SetChannelAttribute ("Delay", StringValue ("1ms")); + + PointToPointDumbbellHelper d (nLeaf, pointToPointLeaf, + nLeaf, pointToPointLeaf, + bottleNeckLink); + + // Install Stack + InternetStackHelper stack; + d.InstallStack (stack); + + // Assign IP Addresses + d.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.1.0", "255.255.255.0"), + Ipv4AddressHelper ("10.2.1.0", "255.255.255.0"), + Ipv4AddressHelper ("10.3.1.0", "255.255.255.0")); + + // Install on/off app on all right side nodes + OnOffHelper clientHelper ("ns3::TcpSocketFactory", Address ()); + clientHelper.SetAttribute ("OnTime", RandomVariableValue (UniformVariable (0, 1))); + clientHelper.SetAttribute ("OffTime", RandomVariableValue (UniformVariable (0, 1))); + Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port)); + PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress); + ApplicationContainer sinkApps; + for (uint32_t i = 0; i < d.LeftCount (); ++i) + { + sinkApps.Add (packetSinkHelper.Install (d.GetLeft (i))); + } + sinkApps.Start (Seconds (0.0)); + sinkApps.Stop (Seconds (30.0)); + + ApplicationContainer clientApps; + for (uint32_t i = 0; i < d.RightCount (); ++i) + { + // Create an on/off app sending packets to the left side + AddressValue remoteAddress (InetSocketAddress (d.GetLeftIpv4Address (i), port)); + clientHelper.SetAttribute ("Remote", remoteAddress); + clientApps.Add (clientHelper.Install (d.GetRight (i))); + } + clientApps.Start (Seconds (1.0));// Start 1 second after sink + clientApps.Stop (Seconds (15.0));// Stop before the sink + + Ipv4GlobalRoutingHelper::PopulateRoutingTables (); + + std::cout << "Running the simulation" << std::endl; + Simulator::Run (); + + uint32_t totalRxBytesCounter = 0; + for (uint32_t i = 0; i < sinkApps.GetN (); i++) + { + Ptr app = sinkApps.Get (i); + Ptr pktSink = DynamicCast (app); + totalRxBytesCounter += pktSink->GetTotalRx (); + } + NS_LOG_UNCOND ("----------------------------\nQueue Type:" + << queueType + << "\nGoodput Bytes/sec:" + << totalRxBytesCounter/Simulator::Now ().GetSeconds ()); + NS_LOG_UNCOND ("----------------------------"); + + + std::cout << "Destroying the simulation" << std::endl; + Simulator::Destroy (); + return 0; +} diff --git a/src/network/examples/red-tests.cc b/src/network/examples/red-tests.cc index 5ab3b0a1c..f695d31c8 100644 --- a/src/network/examples/red-tests.cc +++ b/src/network/examples/red-tests.cc @@ -21,7 +21,8 @@ /** * These validation tests are detailed in http://icir.org/floyd/papers/redsims.ps * - * In this code the tests 1, 3, 4 and 5 from the document above were written. + * In this code the tests 1, 3, 4 and 5 refer to the tests corresponding to + * Figure 1, 3, 4, and 5 respectively from the document mentioned above. */ /** Network topology @@ -42,12 +43,10 @@ #include "ns3/flow-monitor-helper.h" #include "ns3/point-to-point-module.h" #include "ns3/applications-module.h" -#include "ns3/uinteger.h" -#include "ns3/red-queue.h" using namespace ns3; -NS_LOG_COMPONENT_DEFINE ("RedExamples"); +NS_LOG_COMPONENT_DEFINE ("RedTests"); uint32_t checkTimes; double avgQueueSize; @@ -102,7 +101,7 @@ BuildAppsTest (uint32_t test) { // SINK is in the right side uint16_t port = 50000; - Address sinkLocalAddress(InetSocketAddress (Ipv4Address::GetAny (), port)); + Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port)); PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", sinkLocalAddress); ApplicationContainer sinkApp = sinkHelper.Install (n3n4.Get(1)); sinkApp.Start (Seconds (sink_start_time)); @@ -154,28 +153,28 @@ BuildAppsTest (uint32_t test) // SINKs // #1 uint16_t port1 = 50001; - Address sinkLocalAddress1(InetSocketAddress (Ipv4Address::GetAny (), port1)); + Address sinkLocalAddress1 (InetSocketAddress (Ipv4Address::GetAny (), port1)); PacketSinkHelper sinkHelper1 ("ns3::TcpSocketFactory", sinkLocalAddress1); ApplicationContainer sinkApp1 = sinkHelper1.Install (n3n4.Get(1)); sinkApp1.Start (Seconds (sink_start_time)); sinkApp1.Stop (Seconds (sink_stop_time)); // #2 uint16_t port2 = 50002; - Address sinkLocalAddress2(InetSocketAddress (Ipv4Address::GetAny (), port2)); + Address sinkLocalAddress2 (InetSocketAddress (Ipv4Address::GetAny (), port2)); PacketSinkHelper sinkHelper2 ("ns3::TcpSocketFactory", sinkLocalAddress2); ApplicationContainer sinkApp2 = sinkHelper2.Install (n3n5.Get(1)); sinkApp2.Start (Seconds (sink_start_time)); sinkApp2.Stop (Seconds (sink_stop_time)); // #3 uint16_t port3 = 50003; - Address sinkLocalAddress3(InetSocketAddress (Ipv4Address::GetAny (), port3)); + Address sinkLocalAddress3 (InetSocketAddress (Ipv4Address::GetAny (), port3)); PacketSinkHelper sinkHelper3 ("ns3::TcpSocketFactory", sinkLocalAddress3); ApplicationContainer sinkApp3 = sinkHelper3.Install (n0n2.Get(0)); sinkApp3.Start (Seconds (sink_start_time)); sinkApp3.Stop (Seconds (sink_stop_time)); // #4 uint16_t port4 = 50004; - Address sinkLocalAddress4(InetSocketAddress (Ipv4Address::GetAny (), port4)); + Address sinkLocalAddress4 (InetSocketAddress (Ipv4Address::GetAny (), port4)); PacketSinkHelper sinkHelper4 ("ns3::TcpSocketFactory", sinkLocalAddress4); ApplicationContainer sinkApp4 = sinkHelper4.Install (n1n2.Get(0)); sinkApp4.Start (Seconds (sink_start_time)); @@ -238,7 +237,7 @@ BuildAppsTest (uint32_t test) AddressValue remoteAddress3 (InetSocketAddress (i0i2.GetAddress (0), port3)); clientHelper3.SetAttribute ("Remote", remoteAddress3); - clientApps3.Add(clientHelper3.Install (n3n4.Get(1))); + clientApps3.Add (clientHelper3.Install (n3n4.Get(1))); clientApps3.Start (Seconds (3.5)); clientApps3.Stop (Seconds (client_stop_time)); @@ -257,7 +256,7 @@ BuildAppsTest (uint32_t test) AddressValue remoteAddress4 (InetSocketAddress (i1i2.GetAddress (0), port4)); clientHelper4.SetAttribute ("Remote", remoteAddress4); - clientApps4.Add(clientHelper4.Install (n3n5.Get(1))); + clientApps4.Add (clientHelper4.Install (n3n5.Get(1))); clientApps4.Start (Seconds (1.0)); clientApps4.Stop (Seconds (client_stop_time)); } @@ -292,7 +291,7 @@ main (int argc, char *argv[]) // Configuration and command line parameter parsing redTest = 1; // Will only save in the directory if enable opts below - pathOut = "/tmp"; + pathOut = "."; // Current directory CommandLine cmd; cmd.AddValue ("testNumber", "Run test 1, 3, 4 or 5", redTest); cmd.AddValue ("pathOut", "Path to save results from --writeForPlot/--writePcap/--writeFlowMonitor", pathOut); @@ -339,8 +338,6 @@ main (int argc, char *argv[]) Config::SetDefault ("ns3::RedQueue::MinTh", DoubleValue (5)); Config::SetDefault ("ns3::RedQueue::MaxTh", DoubleValue (15)); Config::SetDefault ("ns3::RedQueue::QueueLimit", UintegerValue (25)); - Config::SetDefault ("ns3::RedQueue::LinkBandwidth", StringValue(redLinkDataRate)); - Config::SetDefault ("ns3::RedQueue::LinkDelay", StringValue(redLinkDelay)); if (redTest == 3) // test like 1, but with bad params { @@ -349,17 +346,13 @@ main (int argc, char *argv[]) } else if (redTest == 5) // test 5, same of test 4, but in byte mode { - Config::SetDefault ("ns3::RedQueue::Mode", StringValue("Bytes")); + Config::SetDefault ("ns3::RedQueue::Mode", StringValue ("Bytes")); Config::SetDefault ("ns3::RedQueue::Ns1Compat", BooleanValue (true)); Config::SetDefault ("ns3::RedQueue::MinTh", DoubleValue (5 * meanPktSize)); Config::SetDefault ("ns3::RedQueue::MaxTh", DoubleValue (15 * meanPktSize)); Config::SetDefault ("ns3::RedQueue::QueueLimit", UintegerValue (25 * meanPktSize)); } - // fix the TCP window size - // uint16_t wnd = 15000; - // GlobalValue::Bind ("GlobalFixedTcpWindowSize", IntegerValue (wnd)); - NS_LOG_INFO ("Install internet stack on all nodes."); InternetStackHelper internet; internet.Install (c); @@ -377,7 +370,9 @@ main (int argc, char *argv[]) p2p.SetChannelAttribute ("Delay", StringValue ("3ms")); NetDeviceContainer devn1n2 = p2p.Install (n1n2); - p2p.SetQueue("ns3::RedQueue"); // yeah, only backbone link have special queue + p2p.SetQueue ("ns3::RedQueue", // only backbone link has RED queue + "LinkBandwidth", StringValue (redLinkDataRate), + "LinkDelay", StringValue (redLinkDelay)); p2p.SetDeviceAttribute ("DataRate", StringValue (redLinkDataRate)); p2p.SetChannelAttribute ("Delay", StringValue (redLinkDelay)); NetDeviceContainer devn2n3 = p2p.Install (n2n3); @@ -413,7 +408,7 @@ main (int argc, char *argv[]) // Set up the routing Ipv4GlobalRoutingHelper::PopulateRoutingTables (); - if (redTest == 5) // byte mode + if (redTest == 5) { // like in ns2 test, r2 -> r1, have a queue in packet mode Ptr nd = StaticCast (devn2n3.Get (1)); @@ -435,7 +430,6 @@ main (int argc, char *argv[]) } Ptr flowmon; - if (flowMonitor) { FlowMonitorHelper flowmonHelper; diff --git a/src/network/examples/wscript b/src/network/examples/wscript index 5cf773381..127b000ea 100644 --- a/src/network/examples/wscript +++ b/src/network/examples/wscript @@ -13,3 +13,5 @@ def build(bld): obj = bld.create_ns3_program('red-tests', ['point-to-point', 'internet', 'applications', 'flow-monitor']) obj.source = 'red-tests.cc' + obj = bld.create_ns3_program('droptail_vs_red', ['point-to-point', 'point-to-point-layout', 'internet', 'applications']) + obj.source = 'droptail_vs_red.cc' diff --git a/src/network/test/red-queue-test-suite.cc b/src/network/test/red-queue-test-suite.cc index 9b71de9f7..e5711327a 100644 --- a/src/network/test/red-queue-test-suite.cc +++ b/src/network/test/red-queue-test-suite.cc @@ -25,6 +25,7 @@ #include "ns3/string.h" #include "ns3/double.h" #include "ns3/log.h" +#include "ns3/simulator.h" namespace ns3 { @@ -265,6 +266,8 @@ RedQueueTestCase::DoRun (void) { RunRedTest (StringValue("Packets")); RunRedTest (StringValue("Bytes")); + Simulator::Destroy (); + } static class RedQueueTestSuite : public TestSuite diff --git a/src/network/utils/red-queue.cc b/src/network/utils/red-queue.cc index 479918fe2..6c67d3904 100644 --- a/src/network/utils/red-queue.cc +++ b/src/network/utils/red-queue.cc @@ -190,7 +190,7 @@ void RedQueue::SetTh (double minTh, double maxTh) { NS_LOG_FUNCTION (this << minTh << maxTh); - NS_ASSERT(minTh <= maxTh); + NS_ASSERT (minTh <= maxTh); m_minTh = minTh; m_maxTh = maxTh; } @@ -273,7 +273,7 @@ RedQueue::DoEnqueue (Ptr p) * above "minthresh" with a nonempty queue. */ m_count = 1; - m_countBytes = p->GetSize(); + m_countBytes = p->GetSize (); m_old = 1; } else if (DropEarly (p, nQueued)) @@ -336,6 +336,7 @@ RedQueue::InitializeParams (void) { NS_LOG_FUNCTION_NOARGS (); + NS_ASSERT (m_minTh <= m_maxTh); m_stats.forcedDrop = 0; m_stats.unforcedDrop = 0; m_stats.qLimDrop = 0; @@ -399,7 +400,13 @@ RedQueue::InitializeParams (void) // 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); + 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 @@ -427,8 +434,8 @@ uint32_t RedQueue::DropEarly (Ptr 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 ()); + 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)