#include <fstream>
#include <iostream>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/internet-module.h"
#include "ns3/mobility-module.h"
#include "ns3/aodv-module.h"
#include "ns3/olsr-module.h"
#include "ns3/dsdv-module.h"
#include "ns3/dsr-module.h"
#include "ns3/applications-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/ipv4-flow-classifier.h"
#include "ns3/gnuplot.h"
#include "ns3/netanim-module.h"
using namespace ns3;
using namespace dsr;
using namespace std;
NS_LOG_COMPONENT_DEFINE("manet-routing-compare");
class RoutingExperiment
{
public:
RoutingExperiment();
void Run(int nSinks, double txp, std::string CSVfileName);
// static void SetMACParam (ns3::NetDeviceContainer & devices,
// int slotDistance);
std::string CommandSetup(int argc, char **argv);
private:
Ptr<Socket> SetupPacketReceive(Ipv4Address addr, Ptr<Node> node);
void ReceivePacket(Ptr<Socket> socket);
void CheckThroughput();
void countTime();
uint32_t port;
uint32_t bytesTotal;
uint32_t packetsReceived;
std::string m_CSVfileName;
int m_nSinks;
std::string m_protocolName;
double m_txp;
bool m_traceMobility;
uint32_t m_protocol;
};
RoutingExperiment::RoutingExperiment()
: port(9),
bytesTotal(0),
packetsReceived(0),
m_CSVfileName("manet-routing.output.csv"),
m_traceMobility(false),
m_protocol(1), // olsr
{
}
static inline std::string
PrintReceivedPacket(Ptr<Socket> socket, Ptr<Packet> packet, Address senderAddress)
{
std::ostringstream oss;
oss << Simulator::Now().GetSeconds() << " " << socket->GetNode()->GetId();
if (InetSocketAddress::IsMatchingType(senderAddress))
{
InetSocketAddress addr = InetSocketAddress::ConvertFrom(senderAddress);
oss << " received one packet from " << addr.GetIpv4();
}
else
{
oss << " received one packet!";
}
return oss.str();
}
void RoutingExperiment::ReceivePacket(Ptr<Socket> socket)
{
Ptr<Packet> packet;
Address senderAddress;
while ((packet = socket->RecvFrom(senderAddress)))
{
bytesTotal += packet->GetSize();
packetsReceived += 1;
// NS_LOG_UNCOND(PrintReceivedPacket(socket, packet, senderAddress));
}
}
void RoutingExperiment::CheckThroughput()
{
double kbs = (bytesTotal * 8.0) / 1000;
bytesTotal = 0;
std::ofstream out(m_CSVfileName.c_str(), std::ios::app);
out << (Simulator::Now()).GetSeconds() << ","
<< kbs << ","
<< packetsReceived << ","
<< m_nSinks << ","
<< m_protocolName << ","
<< m_txp << ""
<< std::endl;
out.close();
packetsReceived = 0;
Simulator::Schedule(Seconds(1.0), &RoutingExperiment::CheckThroughput, this);
}
void RoutingExperiment::countTime(){
cout<<"进行到:"<< Simulator::Now().GetSeconds()<<"s"<<endl;
Simulator::Schedule(Seconds(5.0), &RoutingExperiment::countTime, this);
}
Ptr<Socket>
RoutingExperiment::SetupPacketReceive(Ipv4Address addr, Ptr<Node> node)
{
TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
Ptr<Socket> sink = Socket::CreateSocket(node, tid);
InetSocketAddress local = InetSocketAddress(addr, port);
sink->Bind(local);
sink->SetRecvCallback(MakeCallback(&RoutingExperiment::ReceivePacket, this));
return sink;
}
std::string
RoutingExperiment::CommandSetup(int argc, char **argv)
{
CommandLine cmd(__FILE__);
cmd.AddValue("CSVfileName", "The name of the CSV output file name", m_CSVfileName);
cmd.AddValue("traceMobility", "Enable mobility tracing", m_traceMobility);
cmd.AddValue("protocol", "1=OLSR;2=AODV;3=DSDV;4=DSR;5=lpolsr", m_protocol);
cmd.Parse(argc, argv);
return m_CSVfileName;
}
int main(int argc, char *argv[])
{
RoutingExperiment experiment;
std::string CSVfileName = experiment.CommandSetup(argc, argv);
// blank out the last output file and write the column headers
std::ofstream out(CSVfileName.c_str());
out << "SimulationSecond,"
<< "ReceiveRate,"
<< "PacketsReceived,"
<< "NumberOfSinks,"
<< "RoutingProtocol,"
<< "TransmissionPower" << std::endl;
out.close();
int nSinks = 10;
double txp = 15;
experiment.Run(nSinks, txp, CSVfileName);
}
void RoutingExperiment::Run(int nSinks, double txp, std::string CSVfileName)
{
Packet::EnablePrinting();
m_nSinks = nSinks;
m_txp = txp;
m_CSVfileName = CSVfileName;
int nWifis = 50;
double TotalTime = 100.0;
std::string rate("10kb/s");
std::string phyMode("DsssRate11Mbps");
std::string tr_name("manet-routing-compare");
int nodeSpeed = 20; // in m/s
int nodePause = 0; // in s
m_protocolName = "protocol";
Config::SetDefault("ns3::OnOffApplication::PacketSize", StringValue("1024"));
Config::SetDefault("ns3::OnOffApplication::DataRate", StringValue(rate));
// Set Non-unicastMode rate to unicast mode
Config::SetDefault("ns3::WifiRemoteStationManager::NonUnicastMode", StringValue(phyMode));
NodeContainer adhocNodes;
adhocNodes.Create(nWifis);
// setting up wifi phy and channel using helpers
WifiHelper wifi;
wifi.SetStandard(WIFI_STANDARD_80211b);
YansWifiPhyHelper wifiPhy;
YansWifiChannelHelper wifiChannel;
wifiChannel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel");
wifiChannel.AddPropagationLoss("ns3::FriisPropagationLossModel");
wifiPhy.SetChannel(wifiChannel.Create());
// Add a mac and disable rate control
WifiMacHelper wifiMac;
wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
"DataMode", StringValue(phyMode),
"ControlMode", StringValue(phyMode));
wifiPhy.Set("TxPowerStart", DoubleValue(txp));
wifiPhy.Set("TxPowerEnd", DoubleValue(txp));
wifiMac.SetType("ns3::AdhocWifiMac");
NetDeviceContainer adhocDevices = wifi.Install(wifiPhy, wifiMac, adhocNodes);
MobilityHelper mobilityAdhoc;
int64_t streamIndex = 0; // used to get consistent mobility across scenarios
ObjectFactory pos;
pos.SetTypeId ("ns3::RandomRectanglePositionAllocator");
pos.Set ("X", StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=300.0]"));
pos.Set ("Y", StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1500.0]"));
Ptr<PositionAllocator> taPositionAlloc = pos.Create ()->GetObject<PositionAllocator> ();
streamIndex += taPositionAlloc->AssignStreams (streamIndex);
std::stringstream ssSpeed;
ssSpeed << "ns3::UniformRandomVariable[Min=0.0|Max=" << nodeSpeed << "]";
std::stringstream ssPause;
ssPause << "ns3::ConstantRandomVariable[Constant=" << nodePause << "]";
mobilityAdhoc.SetMobilityModel ("ns3::RandomWaypointMobilityModel",
"Speed", StringValue (ssSpeed.str ()),
"Pause", StringValue (ssPause.str ()),
"PositionAllocator", PointerValue (taPositionAlloc));
mobilityAdhoc.SetPositionAllocator (taPositionAlloc);
mobilityAdhoc.Install (adhocNodes);
streamIndex += mobilityAdhoc.AssignStreams (adhocNodes, streamIndex);
NS_UNUSED (streamIndex); // From this point, streamIndex is unused
AodvHelper aodv;
OlsrHelper olsr;
DsdvHelper dsdv;
DsrHelper dsr;
DsrMainHelper dsrMain;
Ipv4ListRoutingHelper list;
InternetStackHelper internet;
switch (m_protocol)
{
case 1:
list.Add(olsr, 100);
m_protocolName = "OLSR";
break;
case 2:
list.Add(aodv, 100);
m_protocolName = "AODV";
break;
case 3:
list.Add(dsdv, 100);
m_protocolName = "DSDV";
break;
// case 4:
// list.Add (lpolsr, 100);
// m_protocolName = "lpolsr";
// break;
case 5:
m_protocolName = "DSR";
break;
default:
NS_FATAL_ERROR("No such protocol:" << m_protocol);
}
if (m_protocol < 5)
{
internet.SetRoutingHelper(list);
internet.Install(adhocNodes);
}
else if (m_protocol == 5)
{
internet.Install(adhocNodes);
dsrMain.Install(dsr, adhocNodes);
}
NS_LOG_INFO("assigning ip address");
Ipv4AddressHelper addressAdhoc;
addressAdhoc.SetBase("10.1.1.0", "255.255.255.0");
Ipv4InterfaceContainer adhocInterfaces;
adhocInterfaces = addressAdhoc.Assign(adhocDevices);
OnOffHelper onoff1("ns3::UdpSocketFactory", Address());
onoff1.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1.0]"));
onoff1.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0.0]"));
for (int i = 0; i < nSinks; i++)
{
Ptr<Socket> sink = SetupPacketReceive(adhocInterfaces.GetAddress(i), adhocNodes.Get(i));
AddressValue remoteAddress(InetSocketAddress(adhocInterfaces.GetAddress(i), port));
onoff1.SetAttribute("Remote", remoteAddress);
Ptr<UniformRandomVariable> var = CreateObject<UniformRandomVariable>();
ApplicationContainer temp = onoff1.Install(adhocNodes.Get(i + nSinks));
temp.Start(Seconds(var->GetValue(20.0, 21.0)));
temp.Stop(Seconds(TotalTime));
}
// std::stringstream ss;
// ss << nWifis;
// std::string nodes = ss.str();
// std::stringstream ss2;
// ss2 << nodeSpeed;
// std::string sNodeSpeed = ss2.str();
// std::stringstream ss3;
// ss3 << nodePause;
// std::string sNodePause = ss3.str();
// std::stringstream ss4;
// ss4 << rate;
// std::string sRate = ss4.str();
// NS_LOG_INFO ("Configure Tracing.");
// tr_name = tr_name + "_" + m_protocolName +"_" + nodes + "nodes_" + sNodeSpeed + "speed_" + sNodePause + "pause_" + sRate + "rate";
// AsciiTraceHelper ascii;
// Ptr<OutputStreamWrapper> osw = ascii.CreateFileStream ( (tr_name + ".tr").c_str());
// wifiPhy.EnableAsciiAll (osw);
AsciiTraceHelper ascii;
MobilityHelper::EnableAsciiAll(ascii.CreateFileStream(tr_name + ".mob"));
uint32_t SentPackets = 0;
uint32_t ReceivedPackets = 0;
uint32_t LostPackets = 0;
// Gnuplot parameters
string fileNameWithNoExtension = "FlowVSThroughput";
string graphicsFileName = fileNameWithNoExtension + ".png";
string plotFileName = fileNameWithNoExtension + ".plt";
string plotTitle = "Flow vs Throughput";
string dataTitle = "Throughput";
// Instantiate the plot and set its title.
Gnuplot gnuplot(graphicsFileName);
gnuplot.SetTitle(plotTitle);
// Make the graphics file, which the plot file will be when it
// is used with Gnuplot, be a PNG file.
gnuplot.SetTerminal("png");
// Set the labels for each axis.
gnuplot.SetLegend("Flow", "Throughput");
Gnuplot2dDataset dataset;
dataset.SetTitle(dataTitle);
dataset.SetStyle(Gnuplot2dDataset::LINES_POINTS);
FlowMonitorHelper flowmon;
Ptr<FlowMonitor> monitor = flowmon.InstallAll();
NS_LOG_INFO("Run Simulationdsada");
CheckThroughput();
countTime();
Simulator::Stop(Seconds(TotalTime));
Simulator::Run();
int j = 0;
float Throughput = 0;
float AvgThroughput = 0;
Time Jitter;
Time Delay;
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier());
std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats();
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator iter = stats.begin(); iter != stats.end(); ++iter)
{
Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow(iter->first);
NS_LOG_UNCOND("----Flow ID:" << iter->first);
NS_LOG_UNCOND("Src Addr" << t.sourceAddress << "Dst Addr " << t.destinationAddress);
NS_LOG_UNCOND("Sent Packets=" << iter->second.txPackets);
NS_LOG_UNCOND("Received Packets =" << iter->second.rxPackets);
NS_LOG_UNCOND("Lost Packets =" << iter->second.txPackets - iter->second.rxPackets);
NS_LOG_UNCOND("Packet delivery ratio =" << iter->second.rxPackets * 100 / iter->second.txPackets << "%");
NS_LOG_UNCOND("Packet loss ratio =" << (iter->second.txPackets - iter->second.rxPackets) * 100 / iter->second.txPackets << "%");
NS_LOG_UNCOND("Delay =" << iter->second.delaySum);
NS_LOG_UNCOND("Jitter =" << iter->second.jitterSum);
Throughput = iter->second.rxBytes * 8.0 / (iter->second.timeLastRxPacket.GetSeconds() - iter->second.timeFirstTxPacket.GetSeconds()) / 1024;
NS_LOG_UNCOND("Throughput =" << Throughput << "Kbps");
dataset.Add((double)iter->first, (double)Throughput);
SentPackets = SentPackets + (iter->second.txPackets);
ReceivedPackets = ReceivedPackets + (iter->second.rxPackets);
LostPackets = LostPackets + (iter->second.txPackets - iter->second.rxPackets);
AvgThroughput = AvgThroughput + Throughput;
Delay = Delay + (iter->second.delaySum);
Jitter = Jitter + (iter->second.jitterSum);
j = j + 1;
}
AvgThroughput = AvgThroughput / j;
NS_LOG_UNCOND("--------Total Results of the simulation----------" << std::endl);
NS_LOG_UNCOND("Total sent packets = " << SentPackets);
NS_LOG_UNCOND("Total Received Packets = " << ReceivedPackets);
NS_LOG_UNCOND("Total Lost Packets = " << LostPackets);
NS_LOG_UNCOND("Packet Loss ratio = " << ((LostPackets * 100) / SentPackets) << "%");
NS_LOG_UNCOND("Packet delivery ratio = " << ((ReceivedPackets * 100) / SentPackets) << "%");
NS_LOG_UNCOND("Average Throughput = " << AvgThroughput << "Kbps");
NS_LOG_UNCOND("End to End Delay = " << Delay.GetMilliSeconds() << "ms");
NS_LOG_UNCOND("End to End Jitter delay = " << Jitter.GetMilliSeconds() << "ms");
NS_LOG_UNCOND("Total Flod id " << j);
monitor->SerializeToXmlFile("manet-routing.xml", true, true);
// flowmon->SerializeToXmlFile ((tr_name + ".flowmon").c_str(), false, false);
NS_LOG_UNCOND("Done");
// Gnuplot ...continued
gnuplot.AddDataset(dataset);
// Open the plot file.
ofstream plotFile(plotFileName.c_str());
// Write the plot file.
gnuplot.GenerateOutput(plotFile);
// Close the plot file.
plotFile.close();
Simulator::Destroy();
}