I can see the "source node" and "destination node", but I can see the "hops node"!
p.s I've used "netanim" and "wireshark", though I need results more clear, it's OK to just see the number of hops without ip
#include "ns3/core-module.h"
#include "ns3/simulator.h"
#include "ns3/node.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/wifi-module.h"
#include "ns3/mesh-module.h"
#include "ns3/mobility-helper.h"
#include "ns3/mesh-helper.h"
#include "ns3/mesh-module.h"
#include "ns3/wifi-phy.h"
#include "ns3/application-container.h"
#include "ns3/inet-socket-address.h"
#include "ns3/packet-sink-helper.h"
#include "ns3/flow-monitor.h"
#include "ns3/flow-monitor-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/ipv4-interface-container.h"
#include "ns3/ipv4-flow-classifier.h"
#include "ns3/random-variable.h"
#include "ns3/on-off-helper.h"
#include "ns3/boolean.h"
#include "ns3/csma-module.h"
#include "ns3/netanim-module.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
using namespace ns3;
class MeshTest
{
public:
// Init test
MeshTest ();
// Configure test from command line arguments
void Configure (int argc, char ** argv);
// Run test
int Run ();
private:
int m_nnodes; // number of nodes
int m_nconn; // number of connections
double m_step;
double m_randomStart;
double m_totalTime;
uint16_t m_packetSize;
uint32_t m_nIfaces;
bool m_chan;
bool m_pcap;
std::string m_stack;
std::string m_txrate;
//to calculate the lenght of the simulation
float m_timeTotal, m_timeStart, m_timeEnd;
// List of network nodes
NodeContainer nodes;
// List of all mesh point devices
NetDeviceContainer meshDevices;
//Addresses of interfaces:
Ipv4InterfaceContainer interfaces;
// MeshHelper. Report is not static methods
MeshHelper mesh;
private:
// Create nodes and setup their mobility
void CreateNodes ();
// Install internet m_stack on nodes
void InstallInternetStack ();
// Install applications randomly
void InstallApplicationRandom ();
// Print mesh devices diagnostics
void Report ();
};
MeshTest::MeshTest () :
m_nnodes (40),
m_nconn (35),
m_step (630),
m_randomStart (0.5),
m_totalTime (240),
m_packetSize (1024),
m_nIfaces (1),
m_chan (false),
m_pcap (false),
m_stack ("ns3::Dot11sStack"),
m_txrate ("340kbps")
{
}
void
MeshTest::Configure (int argc, char *argv[])
{
CommandLine cmd;
cmd.AddValue ("m_step", "Separation", m_step);
cmd.AddValue ("m_nconn", "Number of connections", m_nconn);
cmd.Parse (argc, argv);
}
void MeshTest::CreateNodes ()
{
double m_txpower = 18.0; // dbm
// Calculate nnodes stations random topology
nodes.Create (m_nnodes);
// Setup mobility - static rectangle topology
MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::RandomRectanglePositionAllocator", "X", RandomVariableValue (UniformVariable (0, m_step)),
"Y", RandomVariableValue (UniformVariable (0, m_step/2)));
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (nodes);
// Configure YansWifiChannel
YansWifiPhyHelper WifiPhy = YansWifiPhyHelper::Default ();
WifiPhy.Set("EnergyDetectionThreshold", DoubleValue (-89.0) );
WifiPhy.Set("CcaMode1Threshold", DoubleValue (-62.0) );
WifiPhy.Set("TxGain", DoubleValue (1.0) );
WifiPhy.Set("RxGain", DoubleValue (1.0) );
WifiPhy.Set("TxPowerLevels", UintegerValue (1) );
WifiPhy.Set("TxPowerEnd", DoubleValue (m_txpower) );
WifiPhy.Set("TxPowerStart", DoubleValue (m_txpower) );
WifiPhy.Set("RxNoiseFigure", DoubleValue (7.0) );
YansWifiChannelHelper WifiChannel;
WifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
WifiChannel.AddPropagationLoss ("ns3::LogDistancePropagationLossModel","Exponent", StringValue ("2.7"));
WifiPhy.SetChannel (WifiChannel.Create ());
// Configure the parameters of the Peer Link
Config::SetDefault ("ns3::dot11s::PeerLink::MaxBeaconLoss", UintegerValue (20));
Config::SetDefault ("ns3::dot11s::PeerLink::MaxRetries", UintegerValue (4));
Config::SetDefault ("ns3::dot11s::PeerLink::MaxPacketFailure", UintegerValue (5));
// Configure the parameters of the Peer Management Protocol
//Config::SetDefault ("ns3::dot11s::PeerManagementProtocol::EnableBeaconCollision-Avoidance", BooleanValue (false));
// Configure the parameters of the HWMP
Config::SetDefault ("ns3::dot11s::HwmpProtocol::Dot11MeshHWMPactivePathTimeout", TimeValue (Seconds (100)));
Config::SetDefault ("ns3::dot11s::HwmpProtocol::Dot11MeshHWMPactiveRootTimeout", TimeValue (Seconds (100)));
Config::SetDefault ("ns3::dot11s::HwmpProtocol::Dot11MeshHWMPmaxPREQretries", UintegerValue (5));
Config::SetDefault ("ns3::dot11s::HwmpProtocol::UnicastPreqThreshold", UintegerValue (10));
Config::SetDefault ("ns3::dot11s::HwmpProtocol::UnicastDataThreshold", UintegerValue (5));
Config::SetDefault ("ns3::dot11s::HwmpProtocol::DoFlag", BooleanValue (false));
Config::SetDefault ("ns3::dot11s::HwmpProtocol::RfFlag", BooleanValue (true));
// Create mesh helper and set stack installer to it
// Stack installer creates all needed protocols and install them to device
mesh = MeshHelper::Default ();
mesh.SetStandard (WIFI_PHY_STANDARD_80211a);
mesh.SetMacType ("RandomStart", TimeValue (Seconds(m_randomStart)));
mesh.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("OfdmRate6Mbps"), "RtsCtsThreshold", UintegerValue (2500));
// Set number of interfaces - default is single-interface mesh point
mesh.SetNumberOfInterfaces (m_nIfaces);
mesh.SetStackInstaller (m_stack);
//If multiple channels is activated
if (m_chan)
{
mesh.SetSpreadInterfaceChannels (MeshHelper::SPREAD_CHANNELS);
}
else
{
mesh.SetSpreadInterfaceChannels (MeshHelper::ZERO_CHANNEL);
}
// Install protocols and return container if MeshPointDevices
meshDevices = mesh.Install (WifiPhy, nodes);
if (m_pcap)
WifiPhy.EnablePcapAll (std::string ("mp-"));
}
void MeshTest::InstallInternetStack ()
{
//Install the internet protocol stack on all nodes
InternetStackHelper internetStack;
internetStack.Install (nodes);
//Assign IP addresses to the devices interfaces (m_nIfaces)
Ipv4AddressHelper address;
address.SetBase ("192.168.1.0", "255.255.255.0");
interfaces = address.Assign (meshDevices);
}
void MeshTest::InstallApplicationRandom ()
{
int i=0;
int m_source, m_dest, m_dest_port;
char num [2];
char onoff [7];
char sink [6];
double start_time, stop_time, duration;
// Set the parameters of the onoff application
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (m_packetSize));
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue (m_txrate));
ApplicationContainer apps [m_nconn];
UniformVariable rand_nodes (0,m_nnodes-1);
UniformVariable rand_port (49000,49100);
// 50 seconds for transitori are left at the beginning.
UniformVariable a(50,m_totalTime-15);
for (i = 0; i < m_nconn; i++){
start_time = a.GetValue();
ExponentialVariable b(25);
duration = b.GetValue()+1;
//If the exponential variable gives us a value that added to the start time
//is greater than the maximum permitted, this is changed for the maximum
//10 seconds are left at the end to calculate well the statistics of each flow
if ( (start_time + duration) > (m_totalTime - 10)){
stop_time = m_totalTime-10;
}else{
stop_time = start_time + duration;
}
//create different names for the connections
//(we can not use vectors for OnOffHelper)
strcpy(onoff,"onoff");
strcpy(sink,"sink");
sprintf(num,"%d",i);
strcat(onoff,num);
strcat(sink,num);
//set random variables of the destination (server) and destination port.
m_dest = rand_nodes.GetInteger (0,m_nnodes-1);
m_dest_port = rand_port.GetInteger (49000,49100);
// Set random variables of the source (client).
// Client and server can not be the same node.
m_source = rand_nodes.GetInteger (0,m_nnodes-1);
while (m_source == m_dest){
m_source = rand_nodes.GetInteger (0,m_nnodes-1);
}
// Plot the connection values
std::cout << "\n\t Node "<< m_source << " to " << m_dest;
std::cout << "\n Start_time: " << start_time << "s";
std::cout << "\n Stop_time: " << stop_time << "s";
std::cout << "\n Duration: " << stop_time-start_time << "s\n";
// Define UDP traffic for the onoff application
OnOffHelper onoff ("ns3::UdpSocketFactory", Address (InetSocketAddress (interfaces.GetAddress (m_dest), m_dest_port)));
onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
apps[i] = onoff.Install (nodes.Get(m_source));
apps[i].Start (Seconds (start_time));
apps[i].Stop (Seconds (stop_time));
// Create a packet sink to receive these packets
PacketSinkHelper sink ("ns3::UdpSocketFactory",InetSocketAddress (interfaces.GetAddress (m_dest), 49001));
apps[i] = sink.Install (nodes.Get (m_dest));
apps[i].Start (Seconds (1.0));
}
}
int MeshTest::Run ()
{
CreateNodes ();
InstallInternetStack ();
InstallApplicationRandom ();
// Install FlowMonitor on all nodes
FlowMonitorHelper flowmon;
Ptr<FlowMonitor> monitor = flowmon.InstallAll();
//AnimationInterface anim("hwmp-test-anim.xml");
m_timeStart=clock();
Simulator::Schedule (Seconds(m_totalTime), & MeshTest::Report, this);
Simulator::Stop (Seconds (m_totalTime));
Simulator::Run ();
// Define variables to calculate the metrics
int k=0;
int totaltxPackets = 0;
int totalrxPackets = 0;
double totaltxbytes = 0;
double totalrxbytes = 0;
double totaldelay = 0;
double totalrxbitrate = 0;
double totalpacketloss =0;
double difftx, diffrx;
double pdf_value, rxbitrate_value, txbitrate_value, delay_value;
double pdf_total, rxbitrate_total, delay_total;
//Print per flow statistics
monitor->CheckForLostPackets ();
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier>(flowmon.GetClassifier ());
std::map<FlowId, FlowMonitor::FlowStats> stats = monitor->GetFlowStats ();
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin (); i != stats.end (); ++i)
{
Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow (i->first);
difftx = i->second.timeLastTxPacket.GetSeconds() - i->second.timeFirstTxPacket.GetSeconds();
diffrx = i->second.timeLastRxPacket.GetSeconds() - i->second.timeFirstRxPacket.GetSeconds();
pdf_value = (double) i->second.lostPackets / (double) i->second.txPackets * 100;
txbitrate_value = (double) i->second.txBytes * 8 / 1024 / difftx;
if (i->second.rxPackets != 0){
rxbitrate_value = (double)i->second.rxBytes / diffrx*8/m_packetSize;
delay_value = (double) i->second.delaySum.GetSeconds() / (double) i->second.rxPackets;
}
else{
rxbitrate_value = 0;
delay_value = 0;
}
// We are only interested in the metrics of the data flows
if ((!t.destinationAddress.IsSubnetDirectedBroadcast("255.255.255.0")))
{
k++;
// Plot the statistics for each data flow
std::cout << "\nFlow " << k << " (" << t.sourceAddress << " -> "<< t.destinationAddress << ")\n";
//std::cout << "Tx Packets: " << i->second.txPackets << "\n";
//std::cout << "Rx Packets: " << i->second.rxPackets << "\n";
//std::cout << "Lost Packets: " << i->second.lostPackets << "\n";
//std::cout << "Dropped Packets: " << i->second.packetsDropped.size() << "\n";
std::cout << "Packetloss for flow: " << pdf_value << " %\n";
std::cout << "Average delay x flow: " << delay_value << "s\n";
std::cout << "Throughput x flow: " << rxbitrate_value << " kbps\n";
std::cout << "Tx bitrate x flow: " << txbitrate_value << " kbps\n\n";
// Acumulate for average statistics
totaltxPackets += i->second.txPackets;
totalpacketloss += i->second.lostPackets;
totaltxbytes += i->second.txBytes;
totalrxPackets += i->second.rxPackets;
totaldelay += i->second.delaySum.GetSeconds();
totalrxbitrate += rxbitrate_value;
totalrxbytes += i->second.rxBytes;
}
}
// Average all nodes statistics
if (totaltxPackets != 0){
pdf_total = (double) totalpacketloss / (double) totaltxPackets * 100;
}
else{
pdf_total = 0;
}
if (totalrxPackets != 0){
rxbitrate_total = totalrxbitrate;
delay_total = (double) totaldelay / (double) totalrxPackets;
}
else{
rxbitrate_total = 0;
delay_total = 0;
}
//print all nodes statistics
std::cout << "\nTotal Packetloss: " << pdf_total << " %\n";
std::cout << "Total throughput: " << rxbitrate_total << " kbps\n";
std::cout << "Total Delay: " << delay_total << " s\n";
Simulator::Destroy ();
m_timeEnd=clock();
m_timeTotal=(m_timeEnd - m_timeStart)/(double) CLOCKS_PER_SEC;
std::cout << "\n*** Simulation time: " << m_timeTotal << "s\n\n";
return 0;
}
void MeshTest::Report ()
{
// Using this function we print detailed statistics of each mesh point device
// These statistics are used later with an AWK files to extract routing metrics
unsigned n (0);
for (NetDeviceContainer::Iterator i = meshDevices.Begin (); i != meshDevices.End (); ++i, ++n)
{
std::ostringstream os;
os << "mp-report.xml";
std::cerr << "Printing mesh point device #" << n << " diagnostics to " << os.str () << "\n";
std::ofstream of;
of.open (os.str().c_str(), ios::out | ios::app);
if (! of.is_open ())
{
std::cerr << "Error: Can’t open file " << os.str() << "\n";
return;
}
mesh.Report (*i, of);
of.close ();
}
}
int main (int argc, char *argv[])
{
MeshTest t;
t.Configure (argc, argv);
return t.Run();
}