/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2009 MIRKO BANCHI * Copyright (c) 2015 University of Washington * * 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: Mirko Banchi * Sebastien Deronne * Tom Henderson * * Adapted from ht-wifi-network.cc example */ #include #include #include "ns3/core-module.h" #include "ns3/config-store-module.h" #include "ns3/network-module.h" #include "ns3/applications-module.h" #include "ns3/wifi-module.h" #include "ns3/mobility-module.h" #include "ns3/spectrum-module.h" #include "ns3/internet-module.h" // This is a simple example of an IEEE 802.11n Wi-Fi network. // // The main use case is to enable and test SpectrumWifiPhy vs YansWifiPhy // for packet error ratio // // Network topology: // // Wi-Fi 192.168.1.0 // // STA AP // * <-- distance --> * // | | // n1 n2 // // Adapted version of wifi-spectrum-per-example.cc to show the // channel switching bug with WifiSpectrumPhy // // // using namespace ns3; // Global variables for use in callbacks. double g_signalDbmAvg; double g_noiseDbmAvg; uint32_t g_samples; uint16_t g_channelNumber; uint32_t g_rate; void MonitorSniffRx (Ptr packet, uint16_t channelFreqMhz, WifiTxVector txVector, MpduInfo aMpdu, SignalNoiseDbm signalNoise) { g_samples++; g_signalDbmAvg += ((signalNoise.signal - g_signalDbmAvg) / g_samples); g_noiseDbmAvg += ((signalNoise.noise - g_noiseDbmAvg) / g_samples); } NS_LOG_COMPONENT_DEFINE ("WifiSpectrumPerExample"); // Bug-Related function void ChangeFrequencyLocal (NetDeviceContainer deviceslink, uint8_t channel){ for (uint32_t i = 0; i < deviceslink.GetN (); i++) { Ptr wifidevice = DynamicCast (deviceslink.Get(i)); Ptr phy0 = wifidevice->GetPhy(); phy0->SetChannelNumber (channel); //phy0->SetFrequency (5190); Makes no difference //phy0->SetChannelWidth (40); Makes no difference std::cout << "Changed channel on " << deviceslink.Get (i)->GetAddress () << " to: " << channel << std::endl; } } int main (int argc, char *argv[]) { bool udp = true; double distance = 50; double simulationTime = 10; //seconds std::string wifiType = "ns3::SpectrumWifiPhy"; std::string errorModelType = "ns3::NistErrorRateModel"; bool enablePcap = true; const uint32_t tcpPacketSize = 1448; CommandLine cmd; cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime); cmd.AddValue ("udp", "UDP if set to 1, TCP otherwise", udp); cmd.AddValue ("distance", "meters separation between nodes", distance); cmd.AddValue ("wifiType", "select ns3::SpectrumWifiPhy or ns3::YansWifiPhy", wifiType); cmd.AddValue ("errorModelType", "select ns3::NistErrorRateModel or ns3::YansErrorRateModel", errorModelType); cmd.AddValue ("enablePcap", "enable pcap output", enablePcap); cmd.Parse (argc,argv); // Configure Debug Function LogLevel logLevel = (LogLevel) (LOG_PREFIX_FUNC | LOG_PREFIX_NODE | LOG_PREFIX_TIME | LOG_LEVEL_DEBUG); //std::cout << logLevel << std::endl; LogComponentEnable ("WifiPhy", logLevel); std::cout << "wifiType: " << wifiType << " distance: " << distance << "m; sent: 1000 TxPower: 1 dBm (1.3 mW)" << std::endl; std::cout << std::setw (5) << "index" << std::setw (6) << "MCS" << std::setw (12) << "Rate (Mb/s)" << std::setw (12) << "Tput (Mb/s)" << std::setw (10) << "Received " << std::setw (12) << "Signal (dBm)" << std::setw (12) << "Noise (dBm)" << std::setw (10) << "SNR (dB)" << std::endl; uint16_t i=0; //stripped down version uint32_t payloadSize; if (udp) { payloadSize = 972; // 1000 bytes IPv4 } else { payloadSize = 1448; // 1500 bytes IPv6 Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (payloadSize)); } NodeContainer wifiStaNode; wifiStaNode.Create (1); NodeContainer wifiApNode; wifiApNode.Create (1); YansWifiPhyHelper phy = YansWifiPhyHelper::Default (); SpectrumWifiPhyHelper spectrumPhy = SpectrumWifiPhyHelper::Default (); if (wifiType == "ns3::YansWifiPhy") { YansWifiChannelHelper channel; channel.AddPropagationLoss ("ns3::FriisPropagationLossModel"); channel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel"); phy.SetChannel (channel.Create ()); phy.Set ("TxPowerStart", DoubleValue (1)); // dBm (1.26 mW) phy.Set ("TxPowerEnd", DoubleValue (1)); phy.Set ("ShortGuardEnabled", BooleanValue (false)); phy.Set ("ChannelWidth", UintegerValue (20)); } else if (wifiType == "ns3::SpectrumWifiPhy") { //Bug 2460: CcaMode1Threshold default should be set to -62 dBm when using Spectrum Config::SetDefault ("ns3::WifiPhy::CcaMode1Threshold", DoubleValue (-62.0)); Ptr spectrumChannel = CreateObject (); Ptr lossModel = CreateObject (); spectrumChannel->AddPropagationLossModel (lossModel); Ptr delayModel = CreateObject (); spectrumChannel->SetPropagationDelayModel (delayModel); spectrumPhy.SetChannel (spectrumChannel); spectrumPhy.SetErrorRateModel (errorModelType); spectrumPhy.Set ("Frequency", UintegerValue (5180)); spectrumPhy.Set ("TxPowerStart", DoubleValue (1)); // dBm (1.26 mW) spectrumPhy.Set ("TxPowerEnd", DoubleValue (1)); spectrumPhy.Set ("ShortGuardEnabled", BooleanValue (false)); spectrumPhy.Set ("ChannelWidth", UintegerValue (20)); } else { NS_FATAL_ERROR ("Unsupported WiFi type " << wifiType); } WifiHelper wifi; wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ); WifiMacHelper mac; Ssid ssid = Ssid ("ns380211n"); double datarate = 0; StringValue DataRate; DataRate = StringValue ("HtMcs0"); datarate = 6.5; wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager","DataMode", DataRate, "ControlMode", DataRate); NetDeviceContainer staDevice; NetDeviceContainer apDevice; if (wifiType == "ns3::YansWifiPhy") { mac.SetType ("ns3::StaWifiMac", "Ssid", SsidValue (ssid), "ActiveProbing", BooleanValue (false)); staDevice = wifi.Install (phy, mac, wifiStaNode); mac.SetType ("ns3::ApWifiMac", "Ssid", SsidValue (ssid)); apDevice = wifi.Install (phy, mac, wifiApNode); } else if (wifiType == "ns3::SpectrumWifiPhy") { mac.SetType ("ns3::StaWifiMac", "Ssid", SsidValue (ssid), "ActiveProbing", BooleanValue (false)); staDevice = wifi.Install (spectrumPhy, mac, wifiStaNode); mac.SetType ("ns3::ApWifiMac", "Ssid", SsidValue (ssid)); apDevice = wifi.Install (spectrumPhy, mac, wifiApNode); } // mobility. MobilityHelper mobility; Ptr positionAlloc = CreateObject (); positionAlloc->Add (Vector (0.0, 0.0, 0.0)); positionAlloc->Add (Vector (distance, 0.0, 0.0)); mobility.SetPositionAllocator (positionAlloc); mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); mobility.Install (wifiApNode); mobility.Install (wifiStaNode); /* Internet stack*/ InternetStackHelper stack; stack.Install (wifiApNode); stack.Install (wifiStaNode); Ipv4AddressHelper address; address.SetBase ("192.168.1.0", "255.255.255.0"); Ipv4InterfaceContainer staNodeInterface; Ipv4InterfaceContainer apNodeInterface; staNodeInterface = address.Assign (staDevice); apNodeInterface = address.Assign (apDevice); /* Setting applications */ ApplicationContainer serverApp, sinkApp; if (udp) { //UDP flow UdpServerHelper myServer (9); serverApp = myServer.Install (wifiStaNode.Get (0)); serverApp.Start (Seconds (0.0)); serverApp.Stop (Seconds (simulationTime + 1)); UdpClientHelper myClient (staNodeInterface.GetAddress (0), 9); myClient.SetAttribute ("MaxPackets", UintegerValue (1000)); myClient.SetAttribute ("Interval", TimeValue (MilliSeconds (5))); myClient.SetAttribute ("PacketSize", UintegerValue (payloadSize)); ApplicationContainer clientApp = myClient.Install (wifiApNode.Get (0)); clientApp.Start (Seconds (1.0)); clientApp.Stop (Seconds (simulationTime + 1)); } else { //TCP flow uint16_t port = 50000; Address apLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port)); PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", apLocalAddress); sinkApp = packetSinkHelper.Install (wifiStaNode.Get (0)); sinkApp.Start (Seconds (0.0)); sinkApp.Stop (Seconds (simulationTime + 1)); OnOffHelper onoff ("ns3::TcpSocketFactory",Ipv4Address::GetAny ()); onoff.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); onoff.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute ("PacketSize", UintegerValue (payloadSize)); onoff.SetAttribute ("DataRate", DataRateValue (1000000000)); //bit/s ApplicationContainer apps; AddressValue remoteAddress (InetSocketAddress (staNodeInterface.GetAddress (0), port)); onoff.SetAttribute ("Remote", remoteAddress); apps.Add (onoff.Install (wifiApNode.Get (0))); apps.Start (Seconds (1.0)); apps.Stop (Seconds (simulationTime + 1)); } Config::ConnectWithoutContext ("/NodeList/0/DeviceList/*/Phy/MonitorSnifferRx", MakeCallback (&MonitorSniffRx)); g_signalDbmAvg = 0; g_noiseDbmAvg = 0; g_samples = 0; g_channelNumber = 0; g_rate = 0; NetDeviceContainer devices; devices.Add (apDevice); devices.Add (staDevice); if (enablePcap) { spectrumPhy.SetPcapDataLinkType (SpectrumWifiPhyHelper::DLT_IEEE802_11_RADIO); phy.SetPcapDataLinkType (YansWifiPhyHelper::DLT_IEEE802_11_RADIO); std::stringstream ss; ss << "channel-switch-minimal"; spectrumPhy.EnablePcap (ss.str(), devices); //enable pcap output for all devices use tcpdump -r exam1-0-1.pcap -nn -tt } // Bug-Related function call here. //ChangeFrequencyLocal (devices, 44); // This works since it is executed before the simulation starts. Simulator::Stop (Seconds (simulationTime + 1)); Simulator::Schedule(Seconds(simulationTime-5), &ChangeFrequencyLocal, devices, 38); // This does not work with SpectrumWifiPhy Simulator::Run (); double throughput = 0; uint32_t totalPacketsThrough = 0; if (udp) { //UDP totalPacketsThrough = DynamicCast (serverApp.Get (0))->GetReceived (); throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); //Mbit/s } else { //TCP uint32_t totalBytesRx = DynamicCast (sinkApp.Get (0))->GetTotalRx (); totalPacketsThrough = totalBytesRx / tcpPacketSize; throughput = totalBytesRx * 8 / (simulationTime * 1000000.0); //Mbit/s } std::cout << std::setw (5) << i << std::setw (6) << (i % 8) << std::setw (10) << datarate << std::setw (12) << throughput << std::setw (8) << totalPacketsThrough; if (totalPacketsThrough > 0) { std::cout << std::setw (12) << g_signalDbmAvg << std::setw (12) << g_noiseDbmAvg << std::setw (12) << (g_signalDbmAvg - g_noiseDbmAvg) << std::endl; } else { std::cout << std::setw (12) << "N/A" << std::setw (12) << "N/A" << std::setw (12) << "N/A" << std::endl; } Simulator::Destroy (); return 0; }