/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2015, IMDEA Networks Institute * * 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: Hany Assasa .* * This is a simple example to test TCP over 802.11n (with MPDU aggregation enabled). * * Network topology: * * Ap STA * * * * | | * n1 n2 * * In this example, an HT station sends TCP packets to the access point. * We report the total throughput received during a window of 100ms. * The user can specify the application data rate and choose the variant * of TCP i.e. congestion control algorithm to use. */ #include "ns3/applications-module.h" #include "ns3/core-module.h" #include "ns3/internet-module.h" #include "ns3/mobility-module.h" #include "ns3/wifi-module.h" NS_LOG_COMPONENT_DEFINE ("wifi-tcp"); using namespace ns3; Ptr sink; /* Pointer to the packet sink application */ uint64_t lastTotalRx = 0; /* The value of the last total received bytes */ void CalculateThroughput () { Time now = Simulator::Now (); /* Return the simulator's virtual time. */ double cur = (sink->GetTotalRx () - lastTotalRx) * (double) 8 / 1e5; /* Convert Application RX Packets to MBits. */ std::cout << now.GetSeconds () << "s: \t" << cur << " Mbit/s" << std::endl; lastTotalRx = sink->GetTotalRx (); Simulator::Schedule (MilliSeconds (100), &CalculateThroughput); } int main (int argc, char *argv[]) { uint32_t payloadSize = 1472; /* Transport layer payload size in bytes. */ std::string dataRate = "100Mbps"; /* Application layer datarate. */ std::string tcpVariant = "TcpNewReno"; /* TCP variant type. */ std::string phyRate = "HtMcs7"; /* Physical layer bitrate. */ double simulationTime = 10; /* Simulation time in seconds. */ bool pcapTracing = false; /* PCAP Tracing is enabled or not. */ /* Command line argument parser setup. */ CommandLine cmd; cmd.AddValue ("payloadSize", "Payload size in bytes", payloadSize); cmd.AddValue ("dataRate", "Application data ate", dataRate); cmd.AddValue ("tcpVariant", "Transport protocol to use: TcpNewReno, " "TcpHybla, TcpHighSpeed, TcpHtcp, TcpVegas, TcpScalable, TcpVeno, " "TcpBic, TcpYeah, TcpIllinois, TcpWestwood, TcpWestwoodPlus, TcpLedbat ", tcpVariant); cmd.AddValue ("phyRate", "Physical layer bitrate", phyRate); cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime); cmd.AddValue ("pcap", "Enable/disable PCAP Tracing", pcapTracing); cmd.Parse (argc, argv); tcpVariant = std::string ("ns3::") + tcpVariant; /* No fragmentation and no RTS/CTS */ Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("999999")); Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("999999")); // Select TCP variant if (tcpVariant.compare ("ns3::TcpWestwoodPlus") == 0) { // TcpWestwoodPlus is not an actual TypeId name; we need TcpWestwood here Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TcpWestwood::GetTypeId ())); // the default protocol type in ns3::TcpWestwood is WESTWOOD Config::SetDefault ("ns3::TcpWestwood::ProtocolType", EnumValue (TcpWestwood::WESTWOODPLUS)); } else { TypeId tcpTid; NS_ABORT_MSG_UNLESS (TypeId::LookupByNameFailSafe (tcpVariant, &tcpTid), "TypeId " << tcpVariant << " not found"); Config::SetDefault ("ns3::TcpL4Protocol::SocketType", TypeIdValue (TypeId::LookupByName (tcpVariant))); } /* Configure TCP Options */ Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (payloadSize)); WifiMacHelper wifiMac; WifiHelper wifiHelper; wifiHelper.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ); /* Set up Legacy Channel */ YansWifiChannelHelper wifiChannel; wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel"); wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel", "Frequency", DoubleValue (5e9)); /* Setup Physical Layer */ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default (); wifiPhy.SetChannel (wifiChannel.Create ()); wifiPhy.Set ("TxPowerStart", DoubleValue (10.0)); wifiPhy.Set ("TxPowerEnd", DoubleValue (10.0)); wifiPhy.Set ("TxPowerLevels", UintegerValue (1)); wifiPhy.Set ("TxGain", DoubleValue (0)); wifiPhy.Set ("RxGain", DoubleValue (0)); wifiPhy.Set ("RxNoiseFigure", DoubleValue (10)); wifiPhy.Set ("CcaMode1Threshold", DoubleValue (-79)); wifiPhy.Set ("EnergyDetectionThreshold", DoubleValue (-79 + 3)); wifiPhy.SetErrorRateModel ("ns3::YansErrorRateModel"); wifiHelper.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue (phyRate), "ControlMode", StringValue ("HtMcs0")); NodeContainer networkNodes; networkNodes.Create (2); Ptr apWifiNode = networkNodes.Get (0); Ptr staWifiNode = networkNodes.Get (1); /* Configure AP */ Ssid ssid = Ssid ("network"); wifiMac.SetType ("ns3::ApWifiMac", "Ssid", SsidValue (ssid)); NetDeviceContainer apDevice; apDevice = wifiHelper.Install (wifiPhy, wifiMac, apWifiNode); /* Configure STA */ wifiMac.SetType ("ns3::StaWifiMac", "Ssid", SsidValue (ssid)); NetDeviceContainer staDevices; staDevices = wifiHelper.Install (wifiPhy, wifiMac, staWifiNode); /* Mobility model */ MobilityHelper mobility; Ptr positionAlloc = CreateObject (); positionAlloc->Add (Vector (0.0, 0.0, 0.0)); positionAlloc->Add (Vector (1.0, 1.0, 0.0)); mobility.SetPositionAllocator (positionAlloc); mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); mobility.Install (apWifiNode); mobility.Install (staWifiNode); /* Internet stack */ InternetStackHelper stack; stack.Install (networkNodes); Ipv4AddressHelper address; address.SetBase ("10.0.0.0", "255.255.255.0"); Ipv4InterfaceContainer apInterface; apInterface = address.Assign (apDevice); Ipv4InterfaceContainer staInterface; staInterface = address.Assign (staDevices); /* Populate routing table */ Ipv4GlobalRoutingHelper::PopulateRoutingTables (); /* Install TCP Receiver on the access point */ PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), 9)); ApplicationContainer sinkApp = sinkHelper.Install (apWifiNode); sink = StaticCast (sinkApp.Get (0)); /* Install TCP/UDP Transmitter on the station */ OnOffHelper server ("ns3::TcpSocketFactory", (InetSocketAddress (apInterface.GetAddress (0), 9))); server.SetAttribute ("PacketSize", UintegerValue (payloadSize)); server.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]")); server.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]")); server.SetAttribute ("DataRate", DataRateValue (DataRate (dataRate))); ApplicationContainer serverApp = server.Install (staWifiNode); /* Start Applications */ sinkApp.Start (Seconds (0.0)); serverApp.Start (Seconds (1.0)); Simulator::Schedule (Seconds (1.1), &CalculateThroughput); /* Enable Traces */ if (pcapTracing) { wifiPhy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO); wifiPhy.EnablePcap ("AccessPoint", apDevice); wifiPhy.EnablePcap ("Station", staDevices); } /* Start Simulation */ Simulator::Stop (Seconds (simulationTime + 1)); Simulator::Run (); Simulator::Destroy (); double averageThroughput = ((sink->GetTotalRx () * 8) / (1e6 * simulationTime)); if (averageThroughput < 50) { NS_LOG_ERROR ("Obtained throughput is not in the expected boundaries!"); exit (1); } std::cout << "\nAverage throughput: " << averageThroughput << " Mbit/s" << std::endl; return 0; }