586 lines
17 KiB
C++
586 lines
17 KiB
C++
/* -*- 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: Duy Nguyen <duy@soe.ucsc.edu>
|
|
*/
|
|
|
|
/**
|
|
* Scenarios: 100 nodes, multiple simultaneous flows, multi-hop ad hoc, routing,
|
|
* and mobility
|
|
*
|
|
* QUICK INSTRUCTIONS:
|
|
*
|
|
* To optimize build:
|
|
* ./waf -d optimized configure
|
|
* ./waf
|
|
*
|
|
* To compile:
|
|
* ./waf --run multirate
|
|
*
|
|
* To compile with command line(useful for varying parameters):
|
|
* ./waf --run "multirate --totalTime=0.3s --rateManager=ns3::MinstrelWifiManager"
|
|
*
|
|
* To turn on NS_LOG:
|
|
* export NS_LOG=multirate=level_all
|
|
* (can only view log if built with ./waf -d debug configure)
|
|
*
|
|
* To debug:
|
|
* ./waf --shell
|
|
* gdb ./build/debug/examples/wireless/multirate
|
|
*
|
|
* To view pcap files:
|
|
* tcpdump -nn -tt -r filename.pcap
|
|
*
|
|
* To monitor the files:
|
|
* tail -f filename.pcap
|
|
*
|
|
*/
|
|
|
|
#include "ns3/core-module.h"
|
|
#include "ns3/network-module.h"
|
|
#include "ns3/applications-module.h"
|
|
#include "ns3/mobility-module.h"
|
|
#include "ns3/tools-module.h"
|
|
#include "ns3/random-variable.h"
|
|
#include "ns3/wifi-module.h"
|
|
#include "ns3/internet-module.h"
|
|
#include "ns3/flow-monitor-helper.h"
|
|
#include "ns3/olsr-helper.h"
|
|
#include "ns3/ipv4-static-routing-helper.h"
|
|
#include "ns3/ipv4-list-routing-helper.h"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
NS_LOG_COMPONENT_DEFINE ("multirate");
|
|
|
|
using namespace ns3;
|
|
|
|
class Experiment
|
|
{
|
|
public:
|
|
|
|
Experiment ();
|
|
Experiment (std::string name);
|
|
Gnuplot2dDataset Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
|
|
const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, const MobilityHelper &mobility);
|
|
|
|
bool CommandSetup (int argc, char **argv);
|
|
bool IsRouting () { return (enableRouting == 1) ? 1 : 0; }
|
|
bool IsMobility () { return (enableMobility == 1) ? 1 : 0; }
|
|
|
|
uint32_t GetScenario () { return scenario; }
|
|
|
|
std::string GetRtsThreshold () { return rtsThreshold; }
|
|
std::string GetOutputFileName () { return outputFileName; }
|
|
std::string GetRateManager () { return rateManager; }
|
|
|
|
private:
|
|
|
|
Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
|
|
NodeContainer GenerateNeighbors (NodeContainer c, uint32_t senderId);
|
|
|
|
void ApplicationSetup (Ptr<Node> client, Ptr<Node> server, double start, double stop);
|
|
void AssignNeighbors (NodeContainer c);
|
|
void SelectSrcDest (NodeContainer c);
|
|
void ReceivePacket (Ptr<Socket> socket);
|
|
void CheckThroughput ();
|
|
void SendMultiDestinations (Ptr<Node> sender, NodeContainer c);
|
|
|
|
Gnuplot2dDataset m_output;
|
|
|
|
double totalTime;
|
|
double expMean;
|
|
|
|
uint32_t bytesTotal;
|
|
uint32_t packetSize;
|
|
uint32_t gridSize;
|
|
uint32_t nodeDistance;
|
|
uint32_t port;
|
|
uint32_t scenario;
|
|
|
|
bool enablePcap;
|
|
bool enableTracing;
|
|
bool enableFlowMon;
|
|
bool enableRouting;
|
|
bool enableMobility;
|
|
|
|
NodeContainer containerA, containerB, containerC, containerD;
|
|
std::string rtsThreshold, rateManager, outputFileName;
|
|
};
|
|
|
|
Experiment::Experiment ()
|
|
{
|
|
}
|
|
|
|
Experiment::Experiment (std::string name) :
|
|
m_output (name),
|
|
totalTime (0.3),
|
|
expMean (0.1), //flows being exponentially distributed
|
|
bytesTotal (0),
|
|
packetSize (2000),
|
|
gridSize (10), //10x10 grid for a total of 100 nodes
|
|
nodeDistance (30),
|
|
port (5000),
|
|
scenario (4),
|
|
enablePcap (false),
|
|
enableTracing (true),
|
|
enableFlowMon (false),
|
|
enableRouting (false),
|
|
enableMobility (false),
|
|
rtsThreshold ("2200"), //0 for enabling rts/cts
|
|
rateManager ("ns3::MinstrelWifiManager"),
|
|
outputFileName ("minstrel")
|
|
{
|
|
m_output.SetStyle (Gnuplot2dDataset::LINES);
|
|
}
|
|
|
|
Ptr<Socket>
|
|
Experiment::SetupPacketReceive (Ptr<Node> node)
|
|
{
|
|
TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
|
|
Ptr<Socket> sink = Socket::CreateSocket (node, tid);
|
|
InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), port);
|
|
sink->Bind (local);
|
|
sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
|
|
|
|
return sink;
|
|
}
|
|
|
|
void
|
|
Experiment::ReceivePacket (Ptr<Socket> socket)
|
|
{
|
|
Ptr<Packet> packet;
|
|
while (packet = socket->Recv ())
|
|
{
|
|
bytesTotal += packet->GetSize ();
|
|
}
|
|
}
|
|
|
|
void
|
|
Experiment::CheckThroughput ()
|
|
{
|
|
double mbs = ((bytesTotal * 8.0) /1000000);
|
|
bytesTotal = 0;
|
|
m_output.Add ((Simulator::Now ()).GetSeconds (), mbs);
|
|
|
|
//check throughput every 1/10 of a second
|
|
Simulator::Schedule (Seconds (0.1), &Experiment::CheckThroughput, this);
|
|
}
|
|
|
|
/**
|
|
*
|
|
* Take the grid map, divide it into 4 quadrants
|
|
* Assign all nodes from each quadrant to a specific container
|
|
*
|
|
*/
|
|
void
|
|
Experiment::AssignNeighbors (NodeContainer c)
|
|
{
|
|
uint32_t totalNodes = c.GetN ();
|
|
for (uint32_t i=0; i< totalNodes; i++)
|
|
{
|
|
if ( (i % gridSize) <= (gridSize/2 - 1))
|
|
{
|
|
//lower left quadrant
|
|
if ( i < totalNodes/2 )
|
|
{
|
|
containerA.Add (c.Get (i));
|
|
}
|
|
|
|
//upper left quadrant
|
|
if ( i >= (uint32_t)(4*totalNodes)/10 )
|
|
{
|
|
containerC.Add (c.Get (i));
|
|
}
|
|
}
|
|
if ( (i % gridSize) >= (gridSize/2 - 1))
|
|
{
|
|
//lower right quadrant
|
|
if ( i < totalNodes/2 )
|
|
{
|
|
containerB.Add (c.Get (i));
|
|
}
|
|
|
|
//upper right quadrant
|
|
if ( i >= (uint32_t)(4*totalNodes)/10 )
|
|
{
|
|
containerD.Add (c.Get (i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generate 1-hop and 2-hop neighbors of a node in grid topology
|
|
*
|
|
*/
|
|
NodeContainer
|
|
Experiment::GenerateNeighbors (NodeContainer c, uint32_t senderId)
|
|
{
|
|
NodeContainer nc;
|
|
uint32_t limit = senderId + 2;
|
|
for (uint32_t i= senderId - 2; i <= limit; i++)
|
|
{
|
|
//must ensure the boundaries for other topologies
|
|
nc.Add (c.Get (i));
|
|
nc.Add (c.Get (i + 10));
|
|
nc.Add (c.Get (i + 20));
|
|
nc.Add (c.Get (i - 10));
|
|
nc.Add (c.Get (i - 20));
|
|
}
|
|
return nc;
|
|
}
|
|
|
|
/**
|
|
* Sources and destinations are randomly selected such that a node
|
|
* may be the source for multiple destinations and a node maybe a destination
|
|
* for multiple sources.
|
|
*/
|
|
void
|
|
Experiment::SelectSrcDest (NodeContainer c)
|
|
{
|
|
uint32_t totalNodes = c.GetN ();
|
|
UniformVariable uvSrc (0, totalNodes/2 -1);
|
|
UniformVariable uvDest (totalNodes/2, totalNodes);
|
|
|
|
for (uint32_t i=0; i < totalNodes/3; i++)
|
|
{
|
|
ApplicationSetup (c.Get (uvSrc.RandomVariable::GetInteger ()), c.Get (uvDest.RandomVariable::GetInteger ()), 0, totalTime);
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
* A sender node will set up a flow to each of the its neighbors
|
|
* in its quadrant randomly. All the flows are exponentially distributed
|
|
*
|
|
*/
|
|
void
|
|
Experiment::SendMultiDestinations (Ptr<Node> sender, NodeContainer c)
|
|
{
|
|
|
|
// UniformVariable params: (Xrange, Yrange)
|
|
UniformVariable uv (0, c.GetN ());
|
|
|
|
// ExponentialVariable params: (mean, upperbound)
|
|
ExponentialVariable ev (expMean, totalTime);
|
|
|
|
double start=0.0, stop=totalTime;
|
|
uint32_t destIndex;
|
|
|
|
for (uint32_t i=0; i < c.GetN (); i++)
|
|
{
|
|
stop = start + ev.GetValue ();
|
|
NS_LOG_DEBUG ("Start=" << start << " Stop=" << stop);
|
|
|
|
do {
|
|
destIndex = (uint32_t) uv.GetValue ();
|
|
} while ( (c.Get (destIndex))->GetId () == sender->GetId ());
|
|
|
|
ApplicationSetup (sender, c.Get (destIndex), start, stop);
|
|
|
|
start = stop;
|
|
|
|
if(start > totalTime)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Vector
|
|
GetPosition (Ptr<Node> node)
|
|
{
|
|
Ptr<MobilityModel> mobility = node->GetObject<MobilityModel> ();
|
|
return mobility->GetPosition ();
|
|
}
|
|
|
|
std::string
|
|
PrintPosition (Ptr<Node> client, Ptr<Node> server)
|
|
{
|
|
Vector serverPos = GetPosition (server);
|
|
Vector clientPos = GetPosition (client);
|
|
|
|
Ptr<Ipv4> ipv4Server = server->GetObject<Ipv4>();
|
|
Ptr<Ipv4> ipv4Client = client->GetObject<Ipv4>();
|
|
|
|
Ipv4InterfaceAddress iaddrServer = ipv4Server->GetAddress (1,0);
|
|
Ipv4InterfaceAddress iaddrClient = ipv4Client->GetAddress (1,0);
|
|
|
|
Ipv4Address ipv4AddrServer = iaddrServer.GetLocal ();
|
|
Ipv4Address ipv4AddrClient = iaddrClient.GetLocal ();
|
|
|
|
std::ostringstream oss;
|
|
oss << "Set up Server Device " << (server->GetDevice (0))->GetAddress ()
|
|
<< " with ip " << ipv4AddrServer
|
|
<< " position (" << serverPos.x << "," << serverPos.y << "," << serverPos.z << ")";
|
|
|
|
oss << "Set up Client Device " << (client->GetDevice (0))->GetAddress ()
|
|
<< " with ip " << ipv4AddrClient
|
|
<< " position (" << clientPos.x << "," << clientPos.y << "," << clientPos.z << ")"
|
|
<< "\n";
|
|
return oss.str ();
|
|
}
|
|
|
|
void
|
|
Experiment::ApplicationSetup (Ptr<Node> client, Ptr<Node> server, double start, double stop)
|
|
{
|
|
Ptr<Ipv4> ipv4Server = server->GetObject<Ipv4> ();
|
|
|
|
Ipv4InterfaceAddress iaddrServer = ipv4Server->GetAddress (1,0);
|
|
Ipv4Address ipv4AddrServer = iaddrServer.GetLocal ();
|
|
|
|
NS_LOG_DEBUG (PrintPosition (client, server));
|
|
|
|
// Equipping the source node with OnOff Application used for sending
|
|
OnOffHelper onoff ("ns3::UdpSocketFactory", Address (InetSocketAddress (Ipv4Address ("10.0.0.1"), port)));
|
|
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
|
|
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
|
|
onoff.SetAttribute ("DataRate", DataRateValue (DataRate (60000000)));
|
|
onoff.SetAttribute ("PacketSize", UintegerValue (packetSize));
|
|
onoff.SetAttribute ("Remote", AddressValue (InetSocketAddress (ipv4AddrServer, port)));
|
|
|
|
ApplicationContainer apps = onoff.Install (client);
|
|
apps.Start (Seconds (start));
|
|
apps.Stop (Seconds (stop));
|
|
|
|
Ptr<Socket> sink = SetupPacketReceive (server);
|
|
|
|
}
|
|
|
|
Gnuplot2dDataset
|
|
Experiment::Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
|
|
const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, const MobilityHelper &mobility)
|
|
{
|
|
|
|
|
|
uint32_t nodeSize = gridSize*gridSize;
|
|
NodeContainer c;
|
|
c.Create (nodeSize);
|
|
|
|
YansWifiPhyHelper phy = wifiPhy;
|
|
phy.SetChannel (wifiChannel.Create ());
|
|
|
|
NqosWifiMacHelper mac = wifiMac;
|
|
NetDeviceContainer devices = wifi.Install (phy, mac, c);
|
|
|
|
|
|
OlsrHelper olsr;
|
|
Ipv4StaticRoutingHelper staticRouting;
|
|
|
|
Ipv4ListRoutingHelper list;
|
|
|
|
if (enableRouting)
|
|
{
|
|
list.Add (staticRouting, 0);
|
|
list.Add (olsr, 10);
|
|
}
|
|
|
|
InternetStackHelper internet;
|
|
|
|
if (enableRouting)
|
|
{
|
|
internet.SetRoutingHelper (list); // has effect on the next Install ()
|
|
}
|
|
internet.Install (c);
|
|
|
|
|
|
Ipv4AddressHelper address;
|
|
address.SetBase ("10.0.0.0", "255.255.255.0");
|
|
|
|
Ipv4InterfaceContainer ipInterfaces;
|
|
ipInterfaces = address.Assign (devices);
|
|
|
|
MobilityHelper mobil= mobility;
|
|
mobil.SetPositionAllocator ("ns3::GridPositionAllocator",
|
|
"MinX", DoubleValue (0.0),
|
|
"MinY", DoubleValue (0.0),
|
|
"DeltaX", DoubleValue (nodeDistance),
|
|
"DeltaY", DoubleValue (nodeDistance),
|
|
"GridWidth", UintegerValue (gridSize),
|
|
"LayoutType", StringValue ("RowFirst"));
|
|
|
|
mobil.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
|
|
|
|
if (enableMobility && enableRouting)
|
|
{
|
|
//Rectangle (xMin, xMax, yMin, yMax)
|
|
mobil.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
|
|
"Bounds", RectangleValue (Rectangle (0, 500, 0, 500)),
|
|
"Speed", RandomVariableValue (ConstantVariable (10)),
|
|
"Pause", RandomVariableValue (ConstantVariable (0.2)));
|
|
}
|
|
mobil.Install (c);
|
|
|
|
|
|
// NS_LOG_INFO ("Enabling global routing on all nodes");
|
|
// Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
|
|
|
|
if ( scenario == 1 && enableRouting)
|
|
{
|
|
SelectSrcDest (c);
|
|
}
|
|
else if ( scenario == 2)
|
|
{
|
|
//All flows begin at the same time
|
|
for (uint32_t i = 0; i < nodeSize - 1; i = i+2)
|
|
{
|
|
ApplicationSetup (c.Get (i), c.Get (i+1), 0, totalTime);
|
|
}
|
|
}
|
|
else if ( scenario == 3)
|
|
{
|
|
AssignNeighbors (c);
|
|
//Note: these senders are hand-picked in order to ensure good coverage
|
|
//for 10x10 grid, basically one sender for each quadrant
|
|
//you might have to change these values for other grids
|
|
NS_LOG_DEBUG (">>>>>>>>>region A<<<<<<<<<");
|
|
SendMultiDestinations (c.Get (22), containerA);
|
|
|
|
NS_LOG_DEBUG (">>>>>>>>>region B<<<<<<<<<");
|
|
SendMultiDestinations (c.Get (26), containerB);
|
|
|
|
NS_LOG_DEBUG (">>>>>>>>>region C<<<<<<<<<");
|
|
SendMultiDestinations (c.Get (72), containerC);
|
|
|
|
NS_LOG_DEBUG (">>>>>>>>>region D<<<<<<<<<");
|
|
SendMultiDestinations (c.Get (76), containerD);
|
|
}
|
|
else if ( scenario == 4)
|
|
{
|
|
//GenerateNeighbors(NodeContainer, uint32_t sender)
|
|
//Note: these senders are hand-picked in order to ensure good coverage
|
|
//you might have to change these values for other grids
|
|
NodeContainer c1, c2, c3, c4, c5, c6, c7, c8, c9;
|
|
|
|
c1 = GenerateNeighbors (c, 22);
|
|
c2 = GenerateNeighbors (c, 24);;
|
|
c3 = GenerateNeighbors (c, 26);;
|
|
c4 = GenerateNeighbors (c, 42);;
|
|
c5 = GenerateNeighbors (c, 44);;
|
|
c6 = GenerateNeighbors (c, 46);;
|
|
c7 = GenerateNeighbors (c, 62);;
|
|
c8 = GenerateNeighbors (c, 64);;
|
|
c9 = GenerateNeighbors (c, 66);;
|
|
|
|
SendMultiDestinations (c.Get (22), c1);
|
|
SendMultiDestinations (c.Get (24), c2);
|
|
SendMultiDestinations (c.Get (26), c3);
|
|
SendMultiDestinations (c.Get (42), c4);
|
|
SendMultiDestinations (c.Get (44), c5);
|
|
SendMultiDestinations (c.Get (46), c6);
|
|
SendMultiDestinations (c.Get (62), c7);
|
|
SendMultiDestinations (c.Get (64), c8);
|
|
SendMultiDestinations (c.Get (66), c9);
|
|
}
|
|
|
|
CheckThroughput ();
|
|
|
|
if (enablePcap)
|
|
{
|
|
phy.EnablePcapAll (GetOutputFileName ());
|
|
}
|
|
|
|
if (enableTracing)
|
|
{
|
|
AsciiTraceHelper ascii;
|
|
phy.EnableAsciiAll (ascii.CreateFileStream (GetOutputFileName () + ".tr"));
|
|
}
|
|
|
|
Ptr<FlowMonitor> flowmon;
|
|
|
|
if (enableFlowMon)
|
|
{
|
|
FlowMonitorHelper flowmonHelper;
|
|
flowmon = flowmonHelper.InstallAll ();
|
|
}
|
|
|
|
Simulator::Stop (Seconds (totalTime));
|
|
Simulator::Run ();
|
|
|
|
if (enableFlowMon)
|
|
{
|
|
flowmon->SerializeToXmlFile ((GetOutputFileName () + ".flomon"), false, false);
|
|
}
|
|
|
|
Simulator::Destroy ();
|
|
|
|
return m_output;
|
|
}
|
|
|
|
bool
|
|
Experiment::CommandSetup (int argc, char **argv)
|
|
{
|
|
// for commandline input
|
|
CommandLine cmd;
|
|
cmd.AddValue ("packetSize", "packet size", packetSize);
|
|
cmd.AddValue ("totalTime", "simulation time", totalTime);
|
|
cmd.AddValue ("rtsThreshold", "rts threshold", rtsThreshold);
|
|
cmd.AddValue ("rateManager", "type of rate", rateManager);
|
|
cmd.AddValue ("outputFileName", "output filename", outputFileName);
|
|
cmd.AddValue ("enableRouting", "enable Routing", enableRouting);
|
|
cmd.AddValue ("enableMobility", "enable Mobility", enableMobility);
|
|
cmd.AddValue ("scenario", "scenario ", scenario);
|
|
|
|
cmd.Parse (argc, argv);
|
|
return true;
|
|
}
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
|
|
Experiment experiment;
|
|
experiment = Experiment ("multirate");
|
|
|
|
//for commandline input
|
|
experiment.CommandSetup (argc, argv);
|
|
|
|
// set value to 0 for enabling fragmentation
|
|
Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
|
|
Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue (experiment.GetRtsThreshold ()));
|
|
|
|
std::ofstream outfile ((experiment.GetOutputFileName ()+ ".plt").c_str ());
|
|
|
|
MobilityHelper mobility;
|
|
Gnuplot gnuplot;
|
|
Gnuplot2dDataset dataset;
|
|
|
|
WifiHelper wifi = WifiHelper::Default ();
|
|
NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
|
|
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
|
|
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
|
|
Ssid ssid = Ssid ("Testbed");
|
|
|
|
wifiMac.SetType ("ns3::AdhocWifiMac",
|
|
"Ssid", SsidValue (ssid));
|
|
wifi.SetStandard (WIFI_PHY_STANDARD_holland);
|
|
wifi.SetRemoteStationManager (experiment.GetRateManager ());
|
|
|
|
NS_LOG_INFO ("Scenario: " << experiment.GetScenario ());
|
|
NS_LOG_INFO ("Rts Threshold: " << experiment.GetRtsThreshold ());
|
|
NS_LOG_INFO ("Name: " << experiment.GetOutputFileName ());
|
|
NS_LOG_INFO ("Rate: " << experiment.GetRateManager ());
|
|
NS_LOG_INFO ("Routing: " << experiment.IsRouting ());
|
|
NS_LOG_INFO ("Mobility: " << experiment.IsMobility ());
|
|
|
|
dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility);
|
|
|
|
gnuplot.AddDataset (dataset);
|
|
gnuplot.GenerateOutput (outfile);
|
|
|
|
return 0;
|
|
}
|