diff --git a/examples/wireless/80211e-txop.cc b/examples/wireless/80211e-txop.cc index 92fa534a7..f85539ada 100644 --- a/examples/wireless/80211e-txop.cc +++ b/examples/wireless/80211e-txop.cc @@ -65,6 +65,24 @@ using namespace ns3; NS_LOG_COMPONENT_DEFINE ("80211eTxop"); +/** + * Keeps the maximum duration among all TXOPs + */ +struct TxopDurationTracer +{ + void Trace (Time startTime, Time duration); + Time m_max {Seconds (0)}; +}; + +void +TxopDurationTracer::Trace (Time startTime, Time duration) +{ + if (duration > m_max) + { + m_max = duration; + } +} + int main (int argc, char *argv[]) { uint32_t payloadSize = 1472; //bytes @@ -137,6 +155,15 @@ int main (int argc, char *argv[]) edca = ptr.Get (); edca->SetTxopLimit (MicroSeconds (3008)); + // Trace TXOP duration for BE on STA1 + dev = wifiStaNodes.Get (1)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_mac = wifi_dev->GetMac (); + wifi_mac->GetAttribute ("BE_Txop", ptr); + edca = ptr.Get (); + TxopDurationTracer beTxopTracer; + edca->TraceConnectWithoutContext ("TxopTrace", MakeCallback (&TxopDurationTracer::Trace, &beTxopTracer)); + //Network C ssid = Ssid ("network-C"); phy.Set ("ChannelNumber", UintegerValue (44)); @@ -152,6 +179,15 @@ int main (int argc, char *argv[]) "EnableBeaconJitter", BooleanValue (false)); apDeviceC = wifi.Install (phy, mac, wifiApNodes.Get (2)); + // Trace TXOP duration for VI on STA2 + dev = wifiStaNodes.Get (2)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_mac = wifi_dev->GetMac (); + wifi_mac->GetAttribute ("VI_Txop", ptr); + edca = ptr.Get (); + TxopDurationTracer viTxopTracer; + edca->TraceConnectWithoutContext ("TxopTrace", MakeCallback (&TxopDurationTracer::Trace, &viTxopTracer)); + //Network D ssid = Ssid ("network-D"); phy.Set ("ChannelNumber", UintegerValue (48)); @@ -325,7 +361,8 @@ int main (int argc, char *argv[]) Simulator::Destroy (); double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0); - std::cout << "Throughput for AC_BE with default TXOP limit (0ms): " << throughput << " Mbit/s" << '\n'; + std::cout << "AC_BE with default TXOP limit (0ms): " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 28 || throughput > 29)) { NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); @@ -333,23 +370,38 @@ int main (int argc, char *argv[]) } throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0); - std::cout << "Throughput for AC_BE with non-default TXOP limit (3.008ms): " << throughput << " Mbit/s" << '\n'; + std::cout << "AC_BE with non-default TXOP limit (3.008ms): " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 35.5 || throughput > 36.5)) { NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); exit (1); } + std::cout << " Maximum TXOP duration = " << beTxopTracer.m_max.GetMicroSeconds () << " us" << '\n'; + if (verifyResults && (beTxopTracer.m_max < MicroSeconds (2700) || beTxopTracer.m_max > MicroSeconds (3008))) + { + NS_LOG_ERROR ("Maximum TXOP duration " << beTxopTracer.m_max << " is not in the expected boundaries!"); + exit (1); + } throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0); - std::cout << "Throughput for AC_VI with default TXOP limit (3.008ms): " << throughput << " Mbit/s" << '\n'; + std::cout << "AC_VI with default TXOP limit (3.008ms): " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 36 || throughput > 37)) { NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); exit (1); } + std::cout << " Maximum TXOP duration = " << viTxopTracer.m_max.GetMicroSeconds () << " us" << '\n'; + if (verifyResults && (viTxopTracer.m_max < MicroSeconds (2700) || viTxopTracer.m_max > MicroSeconds (3008))) + { + NS_LOG_ERROR ("Maximum TXOP duration " << viTxopTracer.m_max << " is not in the expected boundaries!"); + exit (1); + } throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0); - std::cout << "Throughput for AC_VI with non-default TXOP limit (0ms): " << throughput << " Mbit/s" << '\n'; + std::cout << "AC_VI with non-default TXOP limit (0ms): " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 31.5 || throughput > 32.5)) { NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); diff --git a/examples/wireless/examples-to-run.py b/examples/wireless/examples-to-run.py index 41f72ef0d..ab124ffc5 100755 --- a/examples/wireless/examples-to-run.py +++ b/examples/wireless/examples-to-run.py @@ -52,6 +52,7 @@ cpp_examples = [ ("simple-ht-hidden-stations --simulationTime=1 --enableRts=1 --nMpdus=32 --minExpectedThroughput=57 --maxExpectedThroughput=58", "True", "True"), ("mixed-network --simulationTime=1", "True", "True"), ("wifi-aggregation --simulationTime=1 --verifyResults=1", "True", "True"), + ("wifi-txop-aggregation --simulationTime=1 --verifyResults=1", "True", "True"), ("80211e-txop --simulationTime=1 --verifyResults=1", "True", "True"), ("wifi-multi-tos --simulationTime=1 --nWifi=16 --useRts=1 --useShortGuardInterval=1", "True", "True"), ("wifi-tcp", "True", "True"), diff --git a/examples/wireless/wifi-txop-aggregation.cc b/examples/wireless/wifi-txop-aggregation.cc new file mode 100644 index 000000000..22e08f592 --- /dev/null +++ b/examples/wireless/wifi-txop-aggregation.cc @@ -0,0 +1,470 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2016 Sébastien Deronne + * + * 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: Sébastien Deronne + */ + +#include "ns3/command-line.h" +#include "ns3/config.h" +#include "ns3/uinteger.h" +#include "ns3/boolean.h" +#include "ns3/string.h" +#include "ns3/pointer.h" +#include "ns3/log.h" +#include "ns3/yans-wifi-helper.h" +#include "ns3/ssid.h" +#include "ns3/mobility-helper.h" +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv4-address-helper.h" +#include "ns3/udp-client-server-helper.h" +#include "ns3/packet-sink-helper.h" +#include "ns3/yans-wifi-channel.h" +#include "ns3/wifi-net-device.h" +#include "ns3/wifi-mac.h" +#include "ns3/qos-txop.h" + +// This is an example that illustrates how 802.11n aggregation is configured. +// It defines 4 independent Wi-Fi networks (working on different channels). +// Each network contains one access point and one station. Each station +// continuously transmits data packets to its respective AP. +// +// Network topology (numbers in parentheses are channel numbers): +// +// Network A (36) Network B (40) Network C (44) Network D (48) +// * * * * * * * * +// | | | | | | | | +// AP A STA A AP B STA B AP C STA C AP D STA D +// +// The aggregation parameters are configured differently on the 4 stations: +// - station A uses default aggregation parameter values (A-MSDU disabled, A-MPDU enabled with maximum size of 65 kB); +// - station B doesn't use aggregation (both A-MPDU and A-MSDU are disabled); +// - station C enables A-MSDU (with maximum size of 8 kB) but disables A-MPDU; +// - station D uses two-level aggregation (A-MPDU with maximum size of 32 kB and A-MSDU with maximum size of 4 kB). +// +// The user can select the distance between the stations and the APs, can enable/disable the RTS/CTS mechanism +// and can modify the duration of a TXOP. +// Example: ./waf --run "wifi-aggregation --distance=10 --enableRts=0 --simulationTime=20" +// +// The output prints the throughput and the maximum TXOP duration measured for the 4 cases/networks +// described above. When default aggregation parameters are enabled, the +// maximum A-MPDU size is 65 kB and the throughput is maximal. When aggregation is disabled, the throughput is about the half of the +// physical bitrate as in legacy wifi networks. When only A-MSDU is enabled, the throughput is increased but is not maximal, since the maximum +// A-MSDU size is limited to 7935 bytes (whereas the maximum A-MPDU size is limited to 65535 bytes). When A-MSDU and A-MPDU are both enabled +// (= two-level aggregation), the throughput is slightly smaller than the first scenario since we set a smaller maximum A-MPDU size. +// +// When the distance is increased, the frame error rate gets higher, and the output shows how it affects the throughput for the 4 networks. +// Even through A-MSDU has less overheads than A-MPDU, A-MSDU is less robust against transmission errors than A-MPDU. When the distance is +// augmented, the throughput for the third scenario is more affected than the throughput obtained in other networks. + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("TxopMpduAggregation"); + +/** + * Keeps the maximum duration among all TXOPs + */ +struct TxopDurationTracer +{ + void Trace (Time startTime, Time duration); + Time m_max {Seconds (0)}; +}; + +void +TxopDurationTracer::Trace (Time startTime, Time duration) +{ + if (duration > m_max) + { + m_max = duration; + } +} + +int main (int argc, char *argv[]) +{ + uint32_t payloadSize = 1472; //bytes + double simulationTime = 10; //seconds + double txopLimit = 3520; //microseconds + double distance = 5; //meters + bool enableRts = 0; + bool enablePcap = 0; + bool verifyResults = 0; //used for regression + + CommandLine cmd; + cmd.AddValue ("payloadSize", "Payload size in bytes", payloadSize); + cmd.AddValue ("enableRts", "Enable or disable RTS/CTS", enableRts); + cmd.AddValue ("txopLimit", "TXOP duration in microseconds", txopLimit); + cmd.AddValue ("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue ("distance", "Distance in meters between the station and the access point", distance); + cmd.AddValue ("enablePcap", "Enable/disable pcap file generation", enablePcap); + cmd.AddValue ("verifyResults", "Enable/disable results verification at the end of the simulation", verifyResults); + cmd.Parse (argc, argv); + + Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", enableRts ? StringValue ("0") : StringValue ("999999")); + + NodeContainer wifiStaNodes; + wifiStaNodes.Create (4); + NodeContainer wifiApNodes; + wifiApNodes.Create (4); + + YansWifiChannelHelper channel = YansWifiChannelHelper::Default (); + YansWifiPhyHelper phy = YansWifiPhyHelper::Default (); + phy.SetPcapDataLinkType (WifiPhyHelper::DLT_IEEE802_11_RADIO); + phy.SetChannel (channel.Create ()); + + WifiHelper wifi; + wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ); + wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("HtMcs7"), "ControlMode", StringValue ("HtMcs0")); + WifiMacHelper mac; + + NetDeviceContainer staDeviceA, staDeviceB, staDeviceC, staDeviceD, apDeviceA, apDeviceB, apDeviceC, apDeviceD; + Ssid ssid; + + // Network A + ssid = Ssid ("network-A"); + phy.Set ("ChannelNumber", UintegerValue (36)); + mac.SetType ("ns3::StaWifiMac", + "Ssid", SsidValue (ssid)); + staDeviceA = wifi.Install (phy, mac, wifiStaNodes.Get (0)); + + mac.SetType ("ns3::ApWifiMac", + "Ssid", SsidValue (ssid), + "EnableBeaconJitter", BooleanValue (false)); + apDeviceA = wifi.Install (phy, mac, wifiApNodes.Get (0)); + + // Modify EDCA configuration (TXOP limit) for AC_BE + Ptr dev = wifiApNodes.Get (0)->GetDevice (0); + Ptr wifi_dev = DynamicCast (dev); + PointerValue ptr; + Ptr edca; + wifi_dev->GetMac ()->GetAttribute ("BE_Txop", ptr); + edca = ptr.Get (); + edca->SetTxopLimit (MicroSeconds (txopLimit)); + + // Trace TXOP duration for BE on AP A + TxopDurationTracer netA; + edca->TraceConnectWithoutContext ("TxopTrace", MakeCallback (&TxopDurationTracer::Trace, &netA)); + + // Network B + ssid = Ssid ("network-B"); + phy.Set ("ChannelNumber", UintegerValue (40)); + mac.SetType ("ns3::StaWifiMac", + "Ssid", SsidValue (ssid)); + + staDeviceB = wifi.Install (phy, mac, wifiStaNodes.Get (1)); + + // Disable A-MPDU + dev = wifiStaNodes.Get (1)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0)); + + mac.SetType ("ns3::ApWifiMac", + "Ssid", SsidValue (ssid), + "EnableBeaconJitter", BooleanValue (false)); + apDeviceB = wifi.Install (phy, mac, wifiApNodes.Get (1)); + + // Disable A-MPDU + dev = wifiApNodes.Get (1)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0)); + + // Modify EDCA configuration (TXOP limit) for AC_BE + wifi_dev->GetMac ()->GetAttribute ("BE_Txop", ptr); + edca = ptr.Get (); + edca->SetTxopLimit (MicroSeconds (txopLimit)); + + // Trace TXOP duration for BE on AP B + TxopDurationTracer netB; + edca->TraceConnectWithoutContext ("TxopTrace", MakeCallback (&TxopDurationTracer::Trace, &netB)); + + // Network C + ssid = Ssid ("network-C"); + phy.Set ("ChannelNumber", UintegerValue (44)); + mac.SetType ("ns3::StaWifiMac", + "Ssid", SsidValue (ssid)); + + staDeviceC = wifi.Install (phy, mac, wifiStaNodes.Get (2)); + + // Disable A-MPDU and enable A-MSDU with the highest maximum size allowed by the standard (7935 bytes) + dev = wifiStaNodes.Get (2)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0)); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (7935)); + + mac.SetType ("ns3::ApWifiMac", + "Ssid", SsidValue (ssid), + "EnableBeaconJitter", BooleanValue (false)); + apDeviceC = wifi.Install (phy, mac, wifiApNodes.Get (2)); + + // Disable A-MPDU and enable A-MSDU with the highest maximum size allowed by the standard (7935 bytes) + dev = wifiApNodes.Get (2)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0)); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (7935)); + + // Modify EDCA configuration (TXOP limit) for AC_BE + wifi_dev->GetMac ()->GetAttribute ("BE_Txop", ptr); + edca = ptr.Get (); + edca->SetTxopLimit (MicroSeconds (txopLimit)); + + // Trace TXOP duration for BE on AP C + TxopDurationTracer netC; + edca->TraceConnectWithoutContext ("TxopTrace", MakeCallback (&TxopDurationTracer::Trace, &netC)); + + // Network D + ssid = Ssid ("network-D"); + phy.Set ("ChannelNumber", UintegerValue (48)); + mac.SetType ("ns3::StaWifiMac", + "Ssid", SsidValue (ssid)); + + staDeviceD = wifi.Install (phy, mac, wifiStaNodes.Get (3)); + + // Enable A-MPDU with a smaller size than the default one and + // enable A-MSDU with the smallest maximum size allowed by the standard (3839 bytes) + dev = wifiStaNodes.Get (3)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (32768)); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (3839)); + + mac.SetType ("ns3::ApWifiMac", + "Ssid", SsidValue (ssid), + "EnableBeaconJitter", BooleanValue (false)); + apDeviceD = wifi.Install (phy, mac, wifiApNodes.Get (3)); + + // Enable A-MPDU with a smaller size than the default one and + // enable A-MSDU with the smallest maximum size allowed by the standard (3839 bytes) + dev = wifiApNodes.Get (3)->GetDevice (0); + wifi_dev = DynamicCast (dev); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (32768)); + wifi_dev->GetMac ()->SetAttribute ("BE_MaxAmsduSize", UintegerValue (3839)); + + // Modify EDCA configuration (TXOP limit) for AC_BE + wifi_dev->GetMac ()->GetAttribute ("BE_Txop", ptr); + edca = ptr.Get (); + edca->SetTxopLimit (MicroSeconds (txopLimit)); + + // Trace TXOP duration for BE on AP D + TxopDurationTracer netD; + edca->TraceConnectWithoutContext ("TxopTrace", MakeCallback (&TxopDurationTracer::Trace, &netD)); + + // Setting mobility model + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + + // Set position for APs + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (10.0, 0.0, 0.0)); + positionAlloc->Add (Vector (20.0, 0.0, 0.0)); + positionAlloc->Add (Vector (30.0, 0.0, 0.0)); + // Set position for STAs + positionAlloc->Add (Vector (distance, 0.0, 0.0)); + positionAlloc->Add (Vector (10 + distance, 0.0, 0.0)); + positionAlloc->Add (Vector (20 + distance, 0.0, 0.0)); + positionAlloc->Add (Vector (30 + distance, 0.0, 0.0)); + + mobility.SetPositionAllocator (positionAlloc); + mobility.Install (wifiApNodes); + mobility.Install (wifiStaNodes); + + // Internet stack + InternetStackHelper stack; + stack.Install (wifiApNodes); + stack.Install (wifiStaNodes); + + Ipv4AddressHelper address; + address.SetBase ("192.168.1.0", "255.255.255.0"); + Ipv4InterfaceContainer StaInterfaceA; + StaInterfaceA = address.Assign (staDeviceA); + Ipv4InterfaceContainer ApInterfaceA; + ApInterfaceA = address.Assign (apDeviceA); + + address.SetBase ("192.168.2.0", "255.255.255.0"); + Ipv4InterfaceContainer StaInterfaceB; + StaInterfaceB = address.Assign (staDeviceB); + Ipv4InterfaceContainer ApInterfaceB; + ApInterfaceB = address.Assign (apDeviceB); + + address.SetBase ("192.168.3.0", "255.255.255.0"); + Ipv4InterfaceContainer StaInterfaceC; + StaInterfaceC = address.Assign (staDeviceC); + Ipv4InterfaceContainer ApInterfaceC; + ApInterfaceC = address.Assign (apDeviceC); + + address.SetBase ("192.168.4.0", "255.255.255.0"); + Ipv4InterfaceContainer StaInterfaceD; + StaInterfaceD = address.Assign (staDeviceD); + Ipv4InterfaceContainer ApInterfaceD; + ApInterfaceD = address.Assign (apDeviceD); + + // Setting applications + uint16_t port = 9; + UdpServerHelper serverA (port); + ApplicationContainer serverAppA = serverA.Install (wifiStaNodes.Get (0)); + serverAppA.Start (Seconds (0.0)); + serverAppA.Stop (Seconds (simulationTime + 1)); + + UdpClientHelper clientA (StaInterfaceA.GetAddress (0), port); + clientA.SetAttribute ("MaxPackets", UintegerValue (4294967295u)); + clientA.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s + clientA.SetAttribute ("PacketSize", UintegerValue (payloadSize)); + + ApplicationContainer clientAppA = clientA.Install (wifiApNodes.Get (0)); + clientAppA.Start (Seconds (1.0)); + clientAppA.Stop (Seconds (simulationTime + 1)); + + UdpServerHelper serverB (port); + ApplicationContainer serverAppB = serverB.Install (wifiStaNodes.Get (1)); + serverAppB.Start (Seconds (0.0)); + serverAppB.Stop (Seconds (simulationTime + 1)); + + UdpClientHelper clientB (StaInterfaceB.GetAddress (0), port); + clientB.SetAttribute ("MaxPackets", UintegerValue (4294967295u)); + clientB.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s + clientB.SetAttribute ("PacketSize", UintegerValue (payloadSize)); + + ApplicationContainer clientAppB = clientB.Install (wifiApNodes.Get (1)); + clientAppB.Start (Seconds (1.0)); + clientAppB.Stop (Seconds (simulationTime + 1)); + + UdpServerHelper serverC (port); + ApplicationContainer serverAppC = serverC.Install (wifiStaNodes.Get (2)); + serverAppC.Start (Seconds (0.0)); + serverAppC.Stop (Seconds (simulationTime + 1)); + + UdpClientHelper clientC (StaInterfaceC.GetAddress (0), port); + clientC.SetAttribute ("MaxPackets", UintegerValue (4294967295u)); + clientC.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s + clientC.SetAttribute ("PacketSize", UintegerValue (payloadSize)); + + ApplicationContainer clientAppC = clientC.Install (wifiApNodes.Get (2)); + clientAppC.Start (Seconds (1.0)); + clientAppC.Stop (Seconds (simulationTime + 1)); + + UdpServerHelper serverD (port); + ApplicationContainer serverAppD = serverD.Install (wifiStaNodes.Get (3)); + serverAppD.Start (Seconds (0.0)); + serverAppD.Stop (Seconds (simulationTime + 1)); + + UdpClientHelper clientD (StaInterfaceD.GetAddress (0), port); + clientD.SetAttribute ("MaxPackets", UintegerValue (4294967295u)); + clientD.SetAttribute ("Interval", TimeValue (Time ("0.00002"))); //packets/s + clientD.SetAttribute ("PacketSize", UintegerValue (payloadSize)); + + ApplicationContainer clientAppD = clientD.Install (wifiApNodes.Get (3)); + clientAppD.Start (Seconds (1.0)); + clientAppD.Stop (Seconds (simulationTime + 1)); + + if (enablePcap) + { + phy.EnablePcap ("AP_A", apDeviceA.Get (0)); + phy.EnablePcap ("STA_A", staDeviceA.Get (0)); + phy.EnablePcap ("AP_B", apDeviceB.Get (0)); + phy.EnablePcap ("STA_B", staDeviceB.Get (0)); + phy.EnablePcap ("AP_C", apDeviceC.Get (0)); + phy.EnablePcap ("STA_C", staDeviceC.Get (0)); + phy.EnablePcap ("AP_D", apDeviceD.Get (0)); + phy.EnablePcap ("STA_D", staDeviceD.Get (0)); + } + + Simulator::Stop (Seconds (simulationTime + 1)); + Simulator::Run (); + + // Show results + uint64_t totalPacketsThroughA = DynamicCast (serverAppA.Get (0))->GetReceived (); + uint64_t totalPacketsThroughB = DynamicCast (serverAppB.Get (0))->GetReceived (); + uint64_t totalPacketsThroughC = DynamicCast (serverAppC.Get (0))->GetReceived (); + uint64_t totalPacketsThroughD = DynamicCast (serverAppD.Get (0))->GetReceived (); + + Simulator::Destroy (); + + double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0); + std::cout << "Default configuration (A-MPDU aggregation enabled, 65kB): " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; + if (verifyResults && (throughput < 57 || throughput > 58)) + { + NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); + exit (1); + } + if (txopLimit) + { + std::cout << " Maximum TXOP duration (TXOP limit = " << txopLimit << "us): " + << netA.m_max.GetMicroSeconds () << " us" << '\n'; + if (verifyResults && txopLimit && (netA.m_max < MicroSeconds (3350) || netA.m_max > MicroSeconds (3520))) + { + NS_LOG_ERROR ("Maximum TXOP duration " << netA.m_max << " is not in the expected boundaries!"); + exit (1); + } + } + + throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0); + std::cout << "Aggregation disabled: " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; + if (verifyResults && (throughput < 39 || throughput > 40)) + { + NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); + exit (1); + } + if (txopLimit) + { + std::cout << " Maximum TXOP duration (TXOP limit = " << txopLimit << "us): " + << netB.m_max.GetMicroSeconds () << " us" << '\n'; + if (verifyResults && (netB.m_max < MicroSeconds (3350) || netB.m_max > MicroSeconds (3520))) + { + NS_LOG_ERROR ("Maximum TXOP duration " << netB.m_max << " is not in the expected boundaries!"); + exit (1); + } + } + + throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0); + std::cout << "A-MPDU disabled and A-MSDU enabled (8kB): " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; + if (verifyResults && (throughput < 53 || throughput > 53.5)) + { + NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); + exit (1); + } + if (txopLimit) + { + std::cout << " Maximum TXOP duration (TXOP limit = " << txopLimit << "us): " + << netC.m_max.GetMicroSeconds () << " us" << '\n'; + if (verifyResults && (netC.m_max < MicroSeconds (3350) || netC.m_max > MicroSeconds (3520))) + { + NS_LOG_ERROR ("Maximum TXOP duration " << netC.m_max << " is not in the expected boundaries!"); + exit (1); + } + } + + throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0); + std::cout << "A-MPDU enabled (32kB) and A-MSDU enabled (4kB): " << '\n' + << " Throughput = " << throughput << " Mbit/s" << '\n'; + if (verifyResults && (throughput < 58 || throughput > 59)) + { + NS_LOG_ERROR ("Obtained throughput " << throughput << " is not in the expected boundaries!"); + exit (1); + } + if (txopLimit) + { + std::cout << " Maximum TXOP duration (TXOP limit = " << txopLimit << "us): " + << netD.m_max.GetMicroSeconds () << " us" << '\n'; + if (verifyResults && txopLimit && (netD.m_max < MicroSeconds (3350) || netD.m_max > MicroSeconds (3520))) + { + NS_LOG_ERROR ("Maximum TXOP duration " << netD.m_max << " is not in the expected boundaries!"); + exit (1); + } + } + + return 0; +} diff --git a/examples/wireless/wscript b/examples/wireless/wscript index 3396e9fb3..b8798f7f1 100644 --- a/examples/wireless/wscript +++ b/examples/wireless/wscript @@ -77,6 +77,9 @@ def build(bld): obj = bld.create_ns3_program('wifi-aggregation', ['wifi', 'applications']) obj.source = 'wifi-aggregation.cc' + obj = bld.create_ns3_program('wifi-txop-aggregation', ['wifi', 'applications']) + obj.source = 'wifi-txop-aggregation.cc' + obj = bld.create_ns3_program('simple-ht-hidden-stations', ['wifi', 'applications']) obj.source = 'simple-ht-hidden-stations.cc' diff --git a/src/wifi/model/mac-low.h b/src/wifi/model/mac-low.h index 021dff3fa..c9f9c4cc6 100644 --- a/src/wifi/model/mac-low.h +++ b/src/wifi/model/mac-low.h @@ -35,10 +35,6 @@ #include "block-ack-type.h" #include "wifi-mpdu-type.h" -class TwoLevelAggregationTest; -class AmpduAggregationTest; -class HeAggregationTest; - namespace ns3 { class WifiMac; @@ -63,10 +59,6 @@ class MpduAggregator; class MacLow : public Object { public: - /// Allow test cases to access private members - friend class ::TwoLevelAggregationTest; - friend class ::AmpduAggregationTest; - friend class ::HeAggregationTest; /** * typedef for a callback for MacLowRx diff --git a/src/wifi/model/qos-txop.h b/src/wifi/model/qos-txop.h index 8ba5610b8..f8cb13b68 100644 --- a/src/wifi/model/qos-txop.h +++ b/src/wifi/model/qos-txop.h @@ -29,6 +29,7 @@ #include "qos-utils.h" class AmpduAggregationTest; +class TwoLevelAggregationTest; class HeAggregationTest; namespace ns3 { @@ -92,6 +93,7 @@ class QosTxop : public Txop public: /// Allow test cases to access private members friend class ::AmpduAggregationTest; + friend class ::TwoLevelAggregationTest; friend class ::HeAggregationTest; std::map m_aMpduEnabled; //!< list containing flags whether A-MPDU is enabled for a given destination address diff --git a/src/wifi/test/wifi-aggregation-test.cc b/src/wifi/test/wifi-aggregation-test.cc index 83935b1ff..57d9c577a 100644 --- a/src/wifi/test/wifi-aggregation-test.cc +++ b/src/wifi/test/wifi-aggregation-test.cc @@ -142,14 +142,11 @@ AmpduAggregationTest::DoRun (void) /* * Test behavior when no other packets are in the queue */ - m_mac->GetBEQueue ()->GetLow ()->m_currentPacket = Create (pkt, hdr); - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector - (*m_mac->GetBEQueue ()->GetLow ()->m_currentPacket->begin ()); + WifiTxVector txVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector (Create (pkt, hdr)); - auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu - (Create (pkt, hdr), m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector); + auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create (pkt, hdr), + txVector); NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet should not result in an A-MPDU"); - NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (), 0, "aggregation queue is not flushed"); //----------------------------------------------------------------------------------------------------- @@ -173,30 +170,21 @@ AmpduAggregationTest::DoRun (void) m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt1, hdr1)); m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt2, hdr2)); - mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create (pkt, hdr), - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector); - m_mac->GetBEQueue ()->GetLow ()->m_currentPacket = Create (mpduList); - for (auto& mpdu : mpduList) - { - m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->Enqueue (Create (*mpdu)); - } + mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create (pkt, hdr), + txVector); + Ptr psdu = Create (mpduList); - uint32_t aggregationQueueSize = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (); NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "MPDU aggregation failed"); - NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_currentPacket->GetSize (), 4606, "A-MPDU size is not correct"); - NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 3, "aggregation queue should not be empty"); + NS_TEST_EXPECT_MSG_EQ (psdu->GetSize (), 4606, "A-MPDU size is not correct"); + NS_TEST_EXPECT_MSG_EQ (mpduList.size (), 3, "A-MPDU should contain 3 MPDUs"); NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetWifiMacQueue ()->GetNPackets (), 0, "queue should be empty"); Ptr dequeuedItem; WifiMacHeader dequeuedHdr; - uint32_t i = 0; - for (; aggregationQueueSize > 0; aggregationQueueSize--, i++) + for (uint32_t i = 0; i < psdu->GetNMpdus (); i++) { - dequeuedItem = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->Dequeue (); - dequeuedHdr = dequeuedItem->GetHeader (); - NS_TEST_EXPECT_MSG_EQ (dequeuedHdr.GetSequenceNumber (), i, "wrong sequence number"); + NS_TEST_EXPECT_MSG_EQ (psdu->GetHeader (i).GetSequenceNumber (), i, "wrong sequence number"); } - NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, 0, "aggregation queue should be empty"); //----------------------------------------------------------------------------------------------------- @@ -227,19 +215,17 @@ AmpduAggregationTest::DoRun (void) m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt3, hdr3)); - mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create (pkt1, hdr1), - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector); + mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create (pkt1, hdr1), + txVector); NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "a single packet for this destination should not result in an A-MPDU"); - NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (), 0, "aggregation queue is not flushed"); - m_mac->GetBEQueue ()->m_currentHdr = hdr2; - m_mac->GetBEQueue ()->m_currentPacket = pkt2->Copy (); - mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu - (Create (pkt2, hdr2), m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector); + mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (Create (pkt2, hdr2), + txVector); NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), true, "no MPDU aggregation should be performed if there is no agreement"); - NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (), 0, "aggregation queue is not flushed"); m_manager->SetMaxSsrc (0); //set to 0 in order to fake that the maximum number of retries has been reached + m_mac->GetBEQueue ()->m_currentHdr = hdr2; + m_mac->GetBEQueue ()->m_currentPacket = pkt2->Copy (); m_mac->GetBEQueue ()->MissedAck (); NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->m_currentPacket, 0, "packet should be discarded"); @@ -328,19 +314,18 @@ TwoLevelAggregationTest::DoRun (void) HtCapabilities htCapabilities; htCapabilities.SetMaxAmsduLength (7935); htCapabilities.SetMaxAmpduLength (65535); - m_manager->AddStationHtCapabilities (Mac48Address ("00:00:00:00:00:01"), htCapabilities); + m_manager->AddStationHtCapabilities (Mac48Address ("00:00:00:00:00:02"), htCapabilities); /* * Create dummy packets of 1500 bytes and fill mac header fields that will be used for the tests. */ Ptr pkt = Create (1500); Ptr currentAggregatedPacket = Create (); - WifiMacHeader hdr, peekedHdr; - hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:01")); - hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:02")); + WifiMacHeader hdr; + hdr.SetAddr1 (Mac48Address ("00:00:00:00:00:02")); + hdr.SetAddr2 (Mac48Address ("00:00:00:00:00:01")); hdr.SetType (WIFI_MAC_QOSDATA); hdr.SetQosTid (0); - Time tstamp; //----------------------------------------------------------------------------------------------------- @@ -354,17 +339,10 @@ TwoLevelAggregationTest::DoRun (void) m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt, hdr)); m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt, hdr)); - Ptr peekedItem = m_mac->GetBEQueue ()->GetWifiMacQueue ()->PeekByTidAndAddress (0, hdr.GetAddr1 ()); - Ptr peekedPacket = peekedItem->GetPacket (); - peekedHdr = peekedItem->GetHeader (); - tstamp = peekedItem->GetTimeStamp (); - m_mac->GetBEQueue ()->GetLow ()->m_currentPacket = Create (peekedPacket, peekedHdr); - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector - (*m_mac->GetBEQueue ()->GetLow ()->m_currentPacket->begin ()); + WifiTxVector txVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector (Create (pkt, hdr)); Ptr item; - item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector, + item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, txVector, currentAggregatedPacket->GetSize ()); bool result = (item != 0); NS_TEST_EXPECT_MSG_EQ (result, true, "aggregation failed"); @@ -383,8 +361,7 @@ TwoLevelAggregationTest::DoRun (void) m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt, hdr)); - item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector, + item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, txVector, currentAggregatedPacket->GetSize ()); result = (item != 0); NS_TEST_EXPECT_MSG_EQ (result, false, "maximum aggregated frame size check failed"); @@ -401,13 +378,74 @@ TwoLevelAggregationTest::DoRun (void) m_mac->GetBEQueue ()->GetWifiMacQueue ()->Remove (pkt); m_mac->GetBEQueue ()->GetWifiMacQueue ()->Remove (pkt); - item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector, + item = m_mac->GetBEQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), 0, txVector, currentAggregatedPacket->GetSize ()); result = (item != 0); NS_TEST_EXPECT_MSG_EQ (result, false, "aggregation failed to stop as queue is empty"); + //----------------------------------------------------------------------------------------------------- + + /* + * Aggregation of MPDUs is stopped to prevent that the PPDU duration exceeds the TXOP limit. + * In this test, the VI AC is used, which has a default TXOP limit of 3008 microseconds. + */ + + // Establish agreement. + uint8_t tid = 5; + MgtAddBaRequestHeader reqHdr; + reqHdr.SetImmediateBlockAck (); + reqHdr.SetTid (tid); + reqHdr.SetBufferSize (64); + reqHdr.SetTimeout (0); + reqHdr.SetStartingSequence (0); + m_mac->GetVIQueue ()->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ()); + m_mac->GetVIQueue ()->m_baManager->NotifyAgreementEstablished (hdr.GetAddr1 (), tid, 0); + + m_mac->SetAttribute ("VI_MaxAmsduSize", UintegerValue (3050)); // max 2 MSDUs per A-MSDU + m_mac->SetAttribute ("VI_MaxAmpduSize", UintegerValue (65535)); + m_manager->SetAttribute ("DataMode", StringValue ("HtMcs2")); // 19.5Mbps + + pkt = Create (1400); + hdr.SetQosTid (tid); + + // Add 10 MSDUs to the EDCA queue + for (uint8_t i = 0; i < 10; i++) + { + m_mac->GetVIQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt, hdr)); + } + + txVector = m_mac->GetVIQueue ()->GetLow ()->GetDataTxVector (Create (pkt, hdr)); + Time txopLimit = m_mac->GetVIQueue ()->GetTxopLimit (); // 3.008 ms + + // Compute the first MPDU to be aggregated in an A-MPDU. It must contain an A-MSDU + // aggregating two MSDUs + Ptr mpdu = m_mac->GetVIQueue ()->GetLow ()->GetMsduAggregator ()->GetNextAmsdu (hdr.GetAddr1 (), tid, + txVector, 0, txopLimit); + NS_TEST_EXPECT_MSG_EQ (m_mac->GetVIQueue ()->GetWifiMacQueue ()->GetNPackets (), 8, "There must be 8 MSDUs left in EDCA queue"); + + auto mpduList = m_mac->GetVIQueue ()->GetLow ()->GetMpduAggregator ()->GetNextAmpdu (mpdu, txVector, txopLimit); + + // The maximum number of bytes that can be transmitted in a TXOP is (approximately, as we + // do not consider that the preamble is transmitted at a different rate): + // 19.5 Mbps * 3.008 ms = 7332 bytes + // Given that the max A-MSDU size is set to 3050, an A-MSDU will contain two MSDUs and have + // a size of 2 * 1400 (MSDU size) + 2 * 14 (A-MSDU subframe header size) + 2 (one padding field) = 2830 bytes + // Hence, we expect that the A-MPDU will consist of: + // - 2 MPDUs containing each an A-MSDU. The size of each MPDU is 2830 (A-MSDU) + 30 (header+trailer) = 2860 + // - 1 MPDU containing a single MSDU. The size of such MPDU is 1400 (MSDU) + 30 (header+trailer) = 1430 + // The size of the A-MPDU is 4 + 2860 + 4 + 2860 + 4 + 1430 = 7162 + NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "aggregation failed"); + NS_TEST_EXPECT_MSG_EQ (mpduList.size (), 3, "Unexpected number of MPDUs in the A-MPDU"); + NS_TEST_EXPECT_MSG_EQ (mpduList.at (0)->GetSize (), 2860, "Unexpected size of the first MPDU"); + NS_TEST_EXPECT_MSG_EQ (mpduList.at (1)->GetSize (), 2860, "Unexpected size of the second MPDU"); + NS_TEST_EXPECT_MSG_EQ (mpduList.at (2)->GetSize (), 1430, "Unexpected size of the first MPDU"); + NS_TEST_EXPECT_MSG_EQ (m_mac->GetVIQueue ()->GetWifiMacQueue ()->GetNPackets (), 5, + "Unexpected number of MSDUs left in the EDCA queue"); + + Ptr psdu = Create (mpduList); + NS_TEST_EXPECT_MSG_EQ (psdu->GetSize (), 7162, "Unexpected size of the A-MPDU"); + Simulator::Destroy (); m_device->Dispose (); @@ -518,13 +556,6 @@ HeAggregationTest::DoRunSubTest (uint16_t bufferSize) m_mac->GetBEQueue ()->m_baManager->CreateAgreement (&reqHdr, hdr.GetAddr1 ()); m_mac->GetBEQueue ()->m_baManager->NotifyAgreementEstablished (hdr.GetAddr1 (), 0, 0); - /* - * Prepare MacLow for transmission - */ - m_mac->GetBEQueue ()->GetLow ()->m_currentPacket = Create (pkt, hdr); - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector - (*m_mac->GetBEQueue ()->GetLow ()->m_currentPacket->begin ()); - /* * Test behavior when 300 packets are ready for transmission but negociated buffer size is 64 */ @@ -541,16 +572,12 @@ HeAggregationTest::DoRunSubTest (uint16_t bufferSize) m_mac->GetBEQueue ()->GetWifiMacQueue ()->Enqueue (Create (pkt, hdr)); } - auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create (pkt, hdr), - m_mac->GetBEQueue ()->GetLow ()->m_currentTxVector); - for (auto& mpdu : mpduList) - { - m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->Enqueue (Create (*mpdu)); - } + WifiTxVector txVector = m_mac->GetBEQueue ()->GetLow ()->GetDataTxVector (Create (pkt, hdr)); + auto mpduList = m_mac->GetBEQueue ()->GetLow ()->GetMpduAggregator ()-> GetNextAmpdu (Create (pkt, hdr), + txVector); NS_TEST_EXPECT_MSG_EQ (mpduList.empty (), false, "MPDU aggregation failed"); - uint32_t aggregationQueueSize = m_mac->GetBEQueue ()->GetLow ()->m_aggregateQueue->GetNPackets (); - NS_TEST_EXPECT_MSG_EQ (aggregationQueueSize, bufferSize, "aggregation queue should countain " << bufferSize << " MPDUs"); + NS_TEST_EXPECT_MSG_EQ (mpduList.size (), bufferSize, "A-MPDU should countain " << bufferSize << " MPDUs"); uint16_t expectedRemainingPacketsInQueue = 300 - bufferSize + 1; NS_TEST_EXPECT_MSG_EQ (m_mac->GetBEQueue ()->GetWifiMacQueue ()->GetNPackets (), expectedRemainingPacketsInQueue, "queue should contain 300 - "<< bufferSize - 1 << " = "<< expectedRemainingPacketsInQueue << " packets"); diff --git a/src/wifi/test/wifi-test.cc b/src/wifi/test/wifi-test.cc index 37c02ed20..b7e83f50c 100644 --- a/src/wifi/test/wifi-test.cc +++ b/src/wifi/test/wifi-test.cc @@ -689,6 +689,169 @@ Bug730TestCase::DoRun (void) NS_TEST_ASSERT_MSG_EQ (result, true, "packet reception unexpectedly stopped after adapting fragmentation threshold!"); } +//----------------------------------------------------------------------------- +/** + * Make sure that fragmentation works with QoS stations. + * + * The scenario considers a TCP transmission between an 802.11n station and an 802.11n + * access point. + */ + +class QosFragmentationTestCase : public TestCase +{ +public: + QosFragmentationTestCase (); + virtual ~QosFragmentationTestCase (); + + virtual void DoRun (void); + + +private: + uint32_t m_received; ///< received packets + uint32_t m_fragments; ///< transmitted fragments + + /** + * Receive function + * \param context the context + * \param p the packet + * \param adr the address + */ + void Receive (std::string context, Ptr p, const Address &adr); + + /** + * Callback invoked when PHY transmits a packet + * \param context the context + * \param p the packet + * \param power the tx power + */ + void Transmit (std::string context, Ptr p, double power); +}; + +QosFragmentationTestCase::QosFragmentationTestCase () + : TestCase ("Test case for fragmentation with QoS stations"), + m_received (0), + m_fragments (0) +{ +} + +QosFragmentationTestCase::~QosFragmentationTestCase () +{ +} + +void +QosFragmentationTestCase::Receive (std::string context, Ptr p, const Address &adr) +{ + if (p->GetSize () == 1400) + { + m_received++; + } +} + +void +QosFragmentationTestCase::Transmit (std::string context, Ptr p, double power) +{ + WifiMacHeader hdr; + p->PeekHeader (hdr); + if (hdr.IsQosData ()) + { + NS_TEST_EXPECT_MSG_LT_OR_EQ (p->GetSize (), 400, "Unexpected fragment size"); + m_fragments++; + } +} + +void +QosFragmentationTestCase::DoRun (void) +{ + NodeContainer wifiStaNode; + wifiStaNode.Create (1); + + NodeContainer wifiApNode; + wifiApNode.Create (1); + + YansWifiChannelHelper channel = YansWifiChannelHelper::Default (); + YansWifiPhyHelper phy = YansWifiPhyHelper::Default (); + phy.SetChannel (channel.Create ()); + + WifiHelper wifi; + wifi.SetStandard (WIFI_PHY_STANDARD_80211n_5GHZ); + wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", + "DataMode", StringValue ("HtMcs7")); + + WifiMacHelper mac; + Ssid ssid = Ssid ("ns-3-ssid"); + mac.SetType ("ns3::StaWifiMac", + "Ssid", SsidValue (ssid), + "ActiveProbing", BooleanValue (false)); + + NetDeviceContainer staDevices; + staDevices = wifi.Install (phy, mac, wifiStaNode); + + mac.SetType ("ns3::ApWifiMac", + "Ssid", SsidValue (ssid), + "BeaconGeneration", BooleanValue (true)); + + NetDeviceContainer apDevices; + apDevices = wifi.Install (phy, mac, wifiApNode); + + MobilityHelper mobility; + Ptr positionAlloc = CreateObject (); + + positionAlloc->Add (Vector (0.0, 0.0, 0.0)); + positionAlloc->Add (Vector (1.0, 0.0, 0.0)); + mobility.SetPositionAllocator (positionAlloc); + + mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel"); + mobility.Install (wifiApNode); + mobility.Install (wifiStaNode); + + Ptr ap_device = DynamicCast (apDevices.Get (0)); + Ptr sta_device = DynamicCast (staDevices.Get (0)); + + // set the TXOP limit on BE AC + Ptr sta_mac = DynamicCast (sta_device->GetMac ()); + NS_ASSERT (sta_mac); + PointerValue ptr; + sta_mac->GetAttribute ("BE_Txop", ptr); + ptr.Get ()->SetTxopLimit (MicroSeconds (3008)); + + PacketSocketAddress socket; + socket.SetSingleDevice (sta_device->GetIfIndex ()); + socket.SetPhysicalAddress (ap_device->GetAddress ()); + socket.SetProtocol (1); + + // give packet socket powers to nodes. + PacketSocketHelper packetSocket; + packetSocket.Install (wifiStaNode); + packetSocket.Install (wifiApNode); + + Ptr client = CreateObject (); + client->SetAttribute ("PacketSize", UintegerValue (1400)); + client->SetAttribute ("MaxPackets", UintegerValue (1)); + client->SetRemote (socket); + wifiStaNode.Get (0)->AddApplication (client); + client->SetStartTime (Seconds (1)); + client->SetStopTime (Seconds (3.0)); + + Ptr server = CreateObject (); + server->SetLocal (socket); + wifiApNode.Get (0)->AddApplication (server); + server->SetStartTime (Seconds (0.0)); + server->SetStopTime (Seconds (4.0)); + + Config::Connect ("/NodeList/*/ApplicationList/0/$ns3::PacketSocketServer/Rx", MakeCallback (&QosFragmentationTestCase::Receive, this)); + + Config::Set ("/NodeList/0/DeviceList/0/RemoteStationManager/FragmentationThreshold", StringValue ("400")); + Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyTxBegin", MakeCallback (&QosFragmentationTestCase::Transmit, this)); + + Simulator::Stop (Seconds (5)); + Simulator::Run (); + + Simulator::Destroy (); + + NS_TEST_ASSERT_MSG_EQ (m_received, 1, "Unexpected number of received packets"); + NS_TEST_ASSERT_MSG_EQ (m_fragments, 4, "Unexpected number of transmitted fragments"); +} + /** * \ingroup wifi-test * \ingroup tests @@ -2023,6 +2186,7 @@ WifiTestSuite::WifiTestSuite () AddTestCase (new InterferenceHelperSequenceTest, TestCase::QUICK); //Bug 991 AddTestCase (new DcfImmediateAccessBroadcastTestCase, TestCase::QUICK); AddTestCase (new Bug730TestCase, TestCase::QUICK); //Bug 730 + AddTestCase (new QosFragmentationTestCase, TestCase::QUICK); AddTestCase (new SetChannelFrequencyTest, TestCase::QUICK); AddTestCase (new Bug2222TestCase, TestCase::QUICK); //Bug 2222 AddTestCase (new Bug2843TestCase, TestCase::QUICK); //Bug 2843