/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2010 IITP RAS
*
* 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
*
*/
/*
* Topology: .ac [node 0] <-- -50 dB --> [node 1]
*
* .n [node 2] <-- -50 db --> [node 3]
*
*
* This example illustrates the use of
* - Wifi in ad-hoc mode
* - Matrix propagation loss model
* - Use of OnOffApplication to generate CBR stream
* - IP flow monitor
*/
#include "ns3/core-module.h"
#include "ns3/propagation-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/internet-module.h"
#include "ns3/flow-monitor-module.h"
#include "ns3/wifi-module.h"
using namespace ns3;
/// Run single 10 seconds experiment with enabled or disabled RTS/CTS mechanism
void experiment ()
{
// 0. Enable or disable CTS/RTS
//UintegerValue ctsThr = 2200;
//Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", ctsThr);
// 1. Create 2 nodes
NodeContainer acnodes;
acnodes.Create (2);
NodeContainer nnodes;
nnodes.Create (2);
// 2. Place nodes somehow, this is required by every wireless simulation
for (size_t i = 0; i < 2; ++i)
{
acnodes.Get (i)->AggregateObject (CreateObject<ConstantPositionMobilityModel> ());
nnodes.Get (i)->AggregateObject (CreateObject<ConstantPositionMobilityModel> ());
}
// 3. Create propagation loss matrix
Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel> ();
lossModel->SetDefaultLoss (70); // set default loss to 70 dB (no link)
lossModel->SetLoss (acnodes.Get (0)->GetObject<MobilityModel>(), acnodes.Get (1)->GetObject<MobilityModel>(), 50); // set symmetric loss 0 <-> 1 to 50 dB
lossModel->SetLoss (nnodes.Get (0)->GetObject<MobilityModel>(), nnodes.Get (1)->GetObject<MobilityModel>(), 50); // set symmetric loss 2 <-> 3 to 50 db
// 4. Create & setup wifi channel
Ptr<YansWifiChannel> wifiChannel = CreateObject <YansWifiChannel> ();
wifiChannel->SetPropagationLossModel (lossModel);
wifiChannel->SetPropagationDelayModel (CreateObject <ConstantSpeedPropagationDelayModel> ());
// 5. Install wireless devices
WifiHelper acwifi;
//acwifi.SetStandard (WIFI_PHY_STANDARD_80211ac);
acwifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
acwifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
//"DataMode",StringValue ("VhtMcs8"),
//"ControlMode",StringValue ("VhtMcs8"));
"DataMode",StringValue ("HtMcs7"),
"ControlMode",StringValue ("HtMcs7"));
YansWifiPhyHelper acwifiPhy = YansWifiPhyHelper::Default ();
acwifiPhy.SetChannel (wifiChannel);
acwifiPhy.Set ("TxAntennas", UintegerValue (3) );
acwifiPhy.Set ("RxAntennas", UintegerValue (3) );
acwifiPhy.Set ("ShortGuardEnabled", BooleanValue (true) );
WifiMacHelper acwifiMac;
acwifiMac.SetType ("ns3::AdhocWifiMac", // use ad-hoc MAC
"VO_MaxAmsduSize", UintegerValue (0),
"VI_MaxAmsduSize", UintegerValue (0),
"BE_MaxAmsduSize", UintegerValue (0),
"BK_MaxAmsduSize", UintegerValue (0),
"VO_MaxAmpduSize", UintegerValue (0),
"VI_MaxAmpduSize", UintegerValue (0),
"BE_MaxAmpduSize", UintegerValue (0),
"BK_MaxAmpduSize", UintegerValue (0) );
NetDeviceContainer acdevices = acwifi.Install (acwifiPhy, acwifiMac, acnodes);
Config::Set ("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", UintegerValue (80));
Config::Set ("/NodeList/1/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", UintegerValue (80));
// uncomment the following to have pcap output
acwifiPhy.EnablePcap ("pcap-node-ac" , acnodes);
// 5. Install wireless devices
WifiHelper nwifi;
nwifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ);
nwifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode",StringValue ("HtMcs23"),
"ControlMode",StringValue ("HtMcs23"));
YansWifiPhyHelper nwifiPhy = YansWifiPhyHelper::Default ();
nwifiPhy.SetChannel (wifiChannel);
nwifiPhy.Set ("TxAntennas", UintegerValue (3) );
nwifiPhy.Set ("RxAntennas", UintegerValue (3) );
nwifiPhy.Set ("ShortGuardEnabled", BooleanValue (true) );
WifiMacHelper nwifiMac;
nwifiMac.SetType ("ns3::AdhocWifiMac"); // use ad-hoc MAC
NetDeviceContainer ndevices = nwifi.Install (nwifiPhy, nwifiMac, nnodes);
Config::Set ("/NodeList/2/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", UintegerValue (40));
Config::Set ("/NodeList/3/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", UintegerValue (40));
// uncomment the following to have athstats output
// AthstatsHelper athstats;
// athstats.EnableAthstats(enableCtsRts ? "rtscts-athstats-node" : "basic-athstats-node" , nodes);
// uncomment the following to have pcap output
nwifiPhy.EnablePcap ("pcap-node-n" , nnodes);
// 6. Install TCP/IP stack & assign IP addresses
InternetStackHelper acinternet;
acinternet.Install (acnodes);
Ipv4AddressHelper acipv4;
acipv4.SetBase ("10.0.0.0", "255.0.0.0");
acipv4.Assign (acdevices);
// 6. Install TCP/IP stack & assign IP addresses
InternetStackHelper ninternet;
ninternet.Install (nnodes);
Ipv4AddressHelper nipv4;
nipv4.SetBase ("11.0.0.0", "255.0.0.0");
nipv4.Assign (ndevices);
// 7. Install applications: two CBR streams each saturating the channel
ApplicationContainer accbrApps;
//uint16_t accbrPort = 12345;
InetSocketAddress destAddress ("10.0.0.2", 12345);
destAddress.SetTos (110);
OnOffHelper aconOffHelper ("ns3::UdpSocketFactory", destAddress);
//OnOfHelper aconOffHelper ("ns3::UdpSocketFactory", destAddress);
aconOffHelper.SetConstantRate (64000, 160);
aconOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ExponentialRandomVariable[Mean=1]"));
aconOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ExponentialRandomVariable[Mean=1.3]]"));
//aconOffHelper.SetAttribute ("Jitter", DoubleValue (0.0) );
//aconOffHelper.SetAttribute ("MaxBytes", UintegerValue (0) );
//aconOffHelper.SetAttribute ("UserPriority", UintegerValue (userPriority) );
//aconOffHelper.SetAttribute ("StartTime", TimeValue (start) );
//aconOffHelper.SetAttribute ("StopTime", TimeValue (stop) );
//aconOffHelper.Install (srcNode);
// flow 1: node 0 -> node 1
aconOffHelper.SetAttribute ("DataRate", StringValue ("13000000bps"));
aconOffHelper.SetAttribute ("StartTime", TimeValue (Seconds (1.000000)));
accbrApps.Add (aconOffHelper.Install (acnodes.Get (0)));
PacketSinkHelper acsink ("ns3::UdpSocketFactory", destAddress);
acsink.Install (acnodes.Get (1));
// flow 2: node 2 -> node 3
ApplicationContainer ncbrApps;
uint16_t ncbrPort = 12345;
OnOffHelper nonOffHelper ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("11.0.0.2"), ncbrPort));
nonOffHelper.SetAttribute ("PacketSize", UintegerValue (1400));
nonOffHelper.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=10]"));
nonOffHelper.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
/** \internal
* The slightly different start times and data rates are a workaround
* for \bugid{388} and \bugid{912}
*/
nonOffHelper.SetAttribute ("DataRate", StringValue ("451100bps"));
nonOffHelper.SetAttribute ("StartTime", TimeValue (Seconds (1.001)));
ncbrApps.Add (nonOffHelper.Install (nnodes.Get (0)));
PacketSinkHelper nsink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address ("11.0.0.2"), ncbrPort));
nsink.Install (nnodes.Get (1));
// 8. Install FlowMonitor on all nodes
FlowMonitorHelper flowmon;
Ptr<FlowMonitor> monitor = flowmon.InstallAll ();
// 9. Run simulation for 10 seconds
Simulator::Stop (Seconds (11));
Simulator::Run ();
// 10. Print per flow statistics
monitor->CheckForLostPackets ();
Ptr<Ipv4FlowClassifier> classifier = DynamicCast<Ipv4FlowClassifier> (flowmon.GetClassifier ());
FlowMonitor::FlowStatsContainer stats = monitor->GetFlowStats ();
for (std::map<FlowId, FlowMonitor::FlowStats>::const_iterator i = stats.begin (); i != stats.end (); ++i)
{
// first 2 FlowIds are for ECHO apps, we don't want to display them
//
// Duration for throughput measurement is 9.0 seconds, since
// StartTime of the OnOffApplication is at about "second 1"
// and
// Simulator::Stops at "second 10".
if (i->first > 0)
{
Ipv4FlowClassifier::FiveTuple t = classifier->FindFlow (i->first);
std::cout << "Flow " << i->first - 0 << " (" << t.sourceAddress << " -> " << t.destinationAddress << ")\n";
std::cout << " Tx Packets: " << i->second.txPackets << "\n";
std::cout << " Tx Bytes: " << i->second.txBytes << "\n";
std::cout << " TxOffered: " << i->second.txBytes * 8.0 / 10.0 / 1000 / 1000 << " Mbps\n";
std::cout << " Rx Packets: " << i->second.rxPackets << "\n";
std::cout << " Rx Bytes: " << i->second.rxBytes << "\n";
std::cout << " Throughput: " << i->second.rxBytes * 8.0 / 10.0 / 1000 / 1000 << " Mbps\n";
std::cout << " Mean delay: " << i->second.delaySum / (i->second.rxPackets) << "\n";
std::cout << " Mean jitter: " << i->second.jitterSum / (i->second.rxPackets - 1 ) << " Mbs\n";
}
}
// 11. Cleanup
Simulator::Destroy ();
}
int main (int argc, char **argv)
{
CommandLine cmd;
cmd.Parse (argc, argv);
std::cout << "Hidden station experiment with RTS/CTS enabled:\n";
experiment();
return 0;
}