How to add a new queue into NS3 ?
[Steps]
1. go to traffic-control/model folder
2. copy fifo-queue-disc.h to myfifo-queue-disc.h and fifo-queue-disc.cc to myfifo-queue-disc.cc .
3. edit the wscript
4. edit the myfifo-queue-disc.cc (You can use find and replace feature. Change “FifoQueue” to “myFifoQueue”.)
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2017 Universita' degli Studi di Napoli Federico II * * 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 * * Authors: Stefano Avallone <stavallo@unina.it> */ #include "ns3/log.h" #include "myfifo-queue-disc.h" #include "ns3/object-factory.h" #include "ns3/drop-tail-queue.h" namespace ns3 { NS_LOG_COMPONENT_DEFINE ("myFifoQueueDisc"); NS_OBJECT_ENSURE_REGISTERED (myFifoQueueDisc); TypeId myFifoQueueDisc::GetTypeId (void) { static TypeId tid = TypeId ("ns3::myFifoQueueDisc") .SetParent<QueueDisc> () .SetGroupName ("TrafficControl") .AddConstructor<myFifoQueueDisc> () .AddAttribute ("MaxSize", "The max queue size", QueueSizeValue (QueueSize ("1000p")), MakeQueueSizeAccessor (&QueueDisc::SetMaxSize, &QueueDisc::GetMaxSize), MakeQueueSizeChecker ()) ; return tid; } myFifoQueueDisc::myFifoQueueDisc () : QueueDisc (QueueDiscSizePolicy::SINGLE_INTERNAL_QUEUE) { NS_LOG_FUNCTION (this); } myFifoQueueDisc::~myFifoQueueDisc () { NS_LOG_FUNCTION (this); } bool myFifoQueueDisc::DoEnqueue (Ptr<QueueDiscItem> item) { NS_LOG_FUNCTION (this << item); if (GetCurrentSize () + item > GetMaxSize ()) { NS_LOG_LOGIC ("Queue full -- dropping pkt"); DropBeforeEnqueue (item, LIMIT_EXCEEDED_DROP); return false; } bool retval = GetInternalQueue (0)->Enqueue (item); // If Queue::Enqueue fails, QueueDisc::DropBeforeEnqueue is called by the // internal queue because QueueDisc::AddInternalQueue sets the trace callback NS_LOG_LOGIC ("Number packets " << GetInternalQueue (0)->GetNPackets ()); NS_LOG_LOGIC ("Number bytes " << GetInternalQueue (0)->GetNBytes ()); return retval; } Ptr<QueueDiscItem> myFifoQueueDisc::DoDequeue (void) { NS_LOG_FUNCTION (this); Ptr<QueueDiscItem> item = GetInternalQueue (0)->Dequeue (); if (!item) { NS_LOG_LOGIC ("Queue empty"); return 0; } return item; } Ptr<const QueueDiscItem> myFifoQueueDisc::DoPeek (void) { NS_LOG_FUNCTION (this); Ptr<const QueueDiscItem> item = GetInternalQueue (0)->Peek (); if (!item) { NS_LOG_LOGIC ("Queue empty"); return 0; } return item; } bool myFifoQueueDisc::CheckConfig (void) { NS_LOG_FUNCTION (this); if (GetNQueueDiscClasses () > 0) { NS_LOG_ERROR ("myFifoQueueDisc cannot have classes"); return false; } if (GetNPacketFilters () > 0) { NS_LOG_ERROR ("myFifoQueueDisc needs no packet filter"); return false; } if (GetNInternalQueues () == 0) { // add a DropTail queue AddInternalQueue (CreateObjectWithAttributes<DropTailQueue<QueueDiscItem> > ("MaxSize", QueueSizeValue (GetMaxSize ()))); } if (GetNInternalQueues () != 1) { NS_LOG_ERROR ("myFifoQueueDisc needs 1 internal queue"); return false; } return true; } void myFifoQueueDisc::InitializeParams (void) { NS_LOG_FUNCTION (this); } } // namespace ns3 |
5. edit the myfifo-queue-disc.cc
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2017 Universita' degli Studi di Napoli Federico II * * 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 * * Authors: Stefano Avallone <stavallo@unina.it> */ #ifndef myFIFO_QUEUE_DISC_H #define myFIFO_QUEUE_DISC_H #include "ns3/queue-disc.h" namespace ns3 { /** * \ingroup traffic-control * * Simple queue disc implementing the FIFO (First-In First-Out) policy. * */ class myFifoQueueDisc : public QueueDisc { public: /** * \brief Get the type ID. * \return the object TypeId */ static TypeId GetTypeId (void); /** * \brief myFifoQueueDisc constructor * * Creates a queue with a depth of 1000 packets by default */ myFifoQueueDisc (); virtual ~myFifoQueueDisc(); // Reasons for dropping packets static constexpr const char* LIMIT_EXCEEDED_DROP = "Queue disc limit exceeded"; //!< Packet dropped due to queue disc limit exceeded private: virtual bool DoEnqueue (Ptr<QueueDiscItem> item); virtual Ptr<QueueDiscItem> DoDequeue (void); virtual Ptr<const QueueDiscItem> DoPeek (void); virtual bool CheckConfig (void); virtual void InitializeParams (void); }; } // namespace ns3 #endif /* FIFO_QUEUE_DISC_H */ |
6. re-compile
7. Test
Based on http://csie.nqu.edu.tw/smallko/ns3/test-pfifo.htm, I wrote the following test code.
test-myfifo.cc (put this file under scratch)
#include <fstream> #include <string.h> #include "ns3/core-module.h" #include "ns3/internet-module.h" #include "ns3/point-to-point-module.h" #include "ns3/packet-sink.h" #include "ns3/packet-sink-helper.h" #include "ns3/on-off-helper.h" #include "ns3/traffic-control-module.h" using namespace ns3; NS_LOG_COMPONENT_DEFINE ("test-myfifo"); const int no=2; Ptr<PacketSink> sink[no]; /* Pointer to the packet sink application */ uint64_t lastTotalRx[no]; /* The value of the last total received bytes */ double cur[no]; QueueDiscContainer queueDiscs; void PrintCurrentQueueSize() { std::cout << queueDiscs.Get(0)->GetNPackets() << std::endl; Simulator::Schedule (MilliSeconds (1), &PrintCurrentQueueSize); } void CalculateThroughput () { Time now = Simulator::Now (); std::cout << now.GetSeconds (); for(int j=0;j<no;j++){ cur[j] = (sink[j]->GetTotalRx () - lastTotalRx[j]) * (double) 8 / 1e3; std::cout << "\t" << cur[j]; lastTotalRx[j] = sink[j]->GetTotalRx (); } std::cout << std::endl; Simulator::Schedule (MilliSeconds (1000), &CalculateThroughput); }
int main (int argc, char *argv[]) { NodeContainer term_0; term_0.Create (1); NodeContainer term_1; term_1.Create (1); NodeContainer term_2; term_2.Create (1); NodeContainer term_3; term_3.Create (1); TrafficControlHelper tch; tch.SetRootQueueDisc ("ns3::myFifoQueueDisc"); /* Build link. */ PointToPointHelper p2p_p2p_0; p2p_p2p_0.SetDeviceAttribute ("DataRate", StringValue ("10Mbps")); p2p_p2p_0.SetChannelAttribute ("Delay", StringValue ("1ms")); PointToPointHelper p2p_p2p_1; p2p_p2p_1.SetDeviceAttribute ("DataRate", StringValue ("10Mbps")); p2p_p2p_1.SetChannelAttribute ("Delay", StringValue ("1ms")); PointToPointHelper p2p_p2p_2; p2p_p2p_2.SetDeviceAttribute ("DataRate", StringValue ("1Mbps")); p2p_p2p_2.SetChannelAttribute ("Delay", StringValue ("1ms"));
/* Build link net device container. */ NodeContainer all_p2p_0; all_p2p_0.Add (term_0); all_p2p_0.Add (term_2); NetDeviceContainer ndc_p2p_0 = p2p_p2p_0.Install (all_p2p_0); NodeContainer all_p2p_1; all_p2p_1.Add (term_1); all_p2p_1.Add (term_2); NetDeviceContainer ndc_p2p_1 = p2p_p2p_1.Install (all_p2p_1); NodeContainer all_p2p_2; all_p2p_2.Add (term_2); all_p2p_2.Add (term_3); NetDeviceContainer ndc_p2p_2 = p2p_p2p_2.Install (all_p2p_2);
/* Install the IP stack. */ InternetStackHelper internetStackH; internetStackH.Install (term_0); internetStackH.Install (term_1); internetStackH.Install (term_2); internetStackH.Install (term_3);
queueDiscs = tch.Install
(ndc_p2p_2.Get(0)); /* IP assign. */ Ipv4AddressHelper ipv4; ipv4.SetBase ("10.0.0.0", "255.255.255.0"); Ipv4InterfaceContainer iface_ndc_p2p_0 = ipv4.Assign (ndc_p2p_0); ipv4.SetBase ("10.0.1.0", "255.255.255.0"); Ipv4InterfaceContainer iface_ndc_p2p_1 = ipv4.Assign (ndc_p2p_1); ipv4.SetBase ("10.0.2.0", "255.255.255.0"); Ipv4InterfaceContainer iface_ndc_p2p_2 = ipv4.Assign (ndc_p2p_2); /* Generate Route. */ Ipv4GlobalRoutingHelper::PopulateRoutingTables (); NS_LOG_INFO ("Create Applications."); PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 9)); ApplicationContainer sinkApp = sinkHelper.Install (term_3.Get(0)); sink[0] = StaticCast<PacketSink> (sinkApp.Get (0)); InetSocketAddress sinkSocket (InetSocketAddress (iface_ndc_p2p_2.GetAddress (1), 9)); sinkSocket.SetTos (16); //interactive OnOffHelper server ("ns3::UdpSocketFactory", sinkSocket); server.SetAttribute ("PacketSize", UintegerValue (1000)); server.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); server.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); server.SetAttribute ("DataRate", DataRateValue (DataRate ("600Kbps"))); ApplicationContainer serverApp = server.Install (term_0.Get(0)); sinkApp.Start (Seconds (0.0)); serverApp.Start (Seconds (1.0)); serverApp.Stop (Seconds (20.0)); PacketSinkHelper sinkHelper2 ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 10)); ApplicationContainer sinkApp2 = sinkHelper2.Install (term_3.Get(0)); sink[1] = StaticCast<PacketSink> (sinkApp2.Get (0)); InetSocketAddress sinkSocket2 (InetSocketAddress (iface_ndc_p2p_2.GetAddress (1), 10)); sinkSocket2.SetTos (0); //best effort OnOffHelper server2 ("ns3::UdpSocketFactory", sinkSocket2); server2.SetAttribute ("PacketSize", UintegerValue (1000)); server2.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); server2.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); server2.SetAttribute ("DataRate", DataRateValue (DataRate ("900Kbps"))); ApplicationContainer serverApp2 = server2.Install (term_1.Get(0)); sinkApp2.Start (Seconds (0.0)); serverApp2.Start (Seconds (5.0)); serverApp2.Stop (Seconds (15.0)); Simulator::Schedule (Seconds (1.0), &CalculateThroughput); //Simulator::Schedule (MilliSeconds (1), &PrintCurrentQueueSize);
Simulator::Stop (Seconds (25.0)); //pointToPoint.EnablePcapAll("test-pfifo0"); NS_LOG_INFO ("Run Simulation."); Simulator::Run (); Simulator::Destroy (); NS_LOG_INFO ("Done."); } |
8. Execution
Last
Modified: 2022/2/15 done
[Author]
Dr. Chih-Heng Ke
Department of Computer
Science and Information Engineering, National Quemoy University, Kinmen,
Taiwan
Email: smallko@gmail.com