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

 

 

Back to NS3 Learning Guide

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