diff --git a/src/wifi/test/block-ack-test-suite.cc b/src/wifi/test/block-ack-test-suite.cc index 9825a8d11..4522bd836 100644 --- a/src/wifi/test/block-ack-test-suite.cc +++ b/src/wifi/test/block-ack-test-suite.cc @@ -19,8 +19,20 @@ */ #include "ns3/test.h" +#include "ns3/string.h" #include "ns3/qos-utils.h" #include "ns3/ctrl-headers.h" +#include "ns3/packet.h" +#include "ns3/wifi-net-device.h" +#include "ns3/ap-wifi-mac.h" +#include "ns3/wifi-mac-header.h" +#include "ns3/mobility-helper.h" +#include "ns3/yans-wifi-helper.h" +#include "ns3/packet-socket-server.h" +#include "ns3/packet-socket-client.h" +#include "ns3/packet-socket-helper.h" +#include "ns3/config.h" +#include "ns3/pointer.h" using namespace ns3; @@ -306,6 +318,225 @@ CtrlBAckResponseHeaderTest::DoRun (void) NS_TEST_EXPECT_MSG_EQ (m_blockAckHdr.IsPacketReceived (80), false, "error in compressed bitmap"); } + +/** + * \ingroup wifi-test + * \ingroup tests + * + * \brief Test for Block Ack Policy with aggregation disabled + * + * This test aims to check the Block Ack policy with "legacy" 802.11, i.e., prior + * to aggregation (802.11n). The block ack threshold is set to 2, hence a block ack + * agreement is established when there are at least two packets in the EDCA queue. + * Consequently, the first packet is sent with Normal Ack policy (because a BA agreement + * has not been established yet), while all other packets are sent with Block Ack + * policy and followed by a Block Ack Request and then a Block Ack. + */ +class BlockAckAggregationDisabledTest : public TestCase +{ + /** + * Keeps the maximum duration among all TXOPs + */ + struct TxopDurationTracer + { + void Trace (Time startTime, Time duration); + Time m_max {Seconds (0)}; + }; + +public: + BlockAckAggregationDisabledTest (); + virtual ~BlockAckAggregationDisabledTest (); + + virtual void DoRun (void); + + +private: + uint32_t m_received; ///< received packets + uint16_t m_txTotal; ///< transmitted data packets + uint16_t m_nBar; ///< transmitted BlockAckReq frames + uint16_t m_nBa; ///< received BlockAck frames + + /** + * Function to trace packets received by the server application + * \param context the context + * \param p the packet + * \param adr the address + */ + void L7Receive (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); + /** + * Callback invoked when PHY receives a packet + * \param context the context + * \param p the packet + */ + void Receive (std::string context, Ptr p); +}; + +void +BlockAckAggregationDisabledTest::TxopDurationTracer::Trace (Time startTime, Time duration) +{ + if (duration > m_max) + { + m_max = duration; + } +} + +BlockAckAggregationDisabledTest::BlockAckAggregationDisabledTest () + : TestCase ("Test case for Block Ack Policy with aggregation disabled"), + m_received (0), + m_txTotal (0), + m_nBar (0), + m_nBa (0) +{ +} + +BlockAckAggregationDisabledTest::~BlockAckAggregationDisabledTest () +{ +} + +void +BlockAckAggregationDisabledTest::L7Receive (std::string context, Ptr p, const Address &adr) +{ + if (p->GetSize () == 1400) + { + m_received++; + } +} + +void +BlockAckAggregationDisabledTest::Transmit (std::string context, Ptr p, double power) +{ + WifiMacHeader hdr; + p->PeekHeader (hdr); + + if (hdr.IsQosData ()) + { + m_txTotal++; + NS_TEST_EXPECT_MSG_EQ ((m_txTotal == 1 || hdr.IsQosBlockAck ()), true, "Unexpected QoS ack policy"); + } + else if (hdr.IsBlockAckReq ()) + { + m_nBar++; + } +} + +void +BlockAckAggregationDisabledTest::Receive (std::string context, Ptr p) +{ + WifiMacHeader hdr; + p->PeekHeader (hdr); + + if (hdr.IsBlockAck ()) + { + m_nBa++; + } +} + +void +BlockAckAggregationDisabledTest::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_80211a); + wifi.SetRemoteStationManager ("ns3::IdealWifiManager"); + + WifiMacHelper mac; + Ssid ssid = Ssid ("ns-3-ssid"); + mac.SetType ("ns3::StaWifiMac", + "QosSupported", BooleanValue (true), + "Ssid", SsidValue (ssid), + /* setting blockack threshold for sta's BE queue */ + "BE_BlockAckThreshold", UintegerValue (2), + "ActiveProbing", BooleanValue (false)); + + NetDeviceContainer staDevices; + staDevices = wifi.Install (phy, mac, wifiStaNode); + + mac.SetType ("ns3::ApWifiMac", + "QosSupported", BooleanValue (true), + "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)); + + // Disable A-MPDU aggregation + sta_device->GetMac ()->SetAttribute ("BE_MaxAmpduSize", UintegerValue (0)); + TxopDurationTracer txopTracer; + + 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 (14)); + client->SetAttribute ("Interval", TimeValue (MicroSeconds (0))); + 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 (&BlockAckAggregationDisabledTest::L7Receive, this)); + Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyTxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Transmit, this)); + Config::Connect ("/NodeList/0/DeviceList/0/Phy/PhyRxBegin", MakeCallback (&BlockAckAggregationDisabledTest::Receive, this)); + + Simulator::Stop (Seconds (5)); + Simulator::Run (); + + Simulator::Destroy (); + + // The client application generates 14 packets, so we expect that the wifi PHY + // layer transmits 14 MPDUs, the server application receives 14 packets, and + // a BAR is transmitted after each MPDU but the first one (because a BA agreement + // is established before transmitting the second MPDU). + NS_TEST_EXPECT_MSG_EQ (m_txTotal, 14, "Unexpected number of transmitted packets"); + NS_TEST_EXPECT_MSG_EQ (m_received, 14, "Unexpected number of received packets"); + NS_TEST_EXPECT_MSG_EQ (m_nBar, 13, "Unexpected number of Block Ack Requests"); + NS_TEST_EXPECT_MSG_EQ (m_nBa, 13, "Unexpected number of Block Ack Responses"); +} + /** * \ingroup wifi-test * \ingroup tests @@ -324,6 +555,7 @@ BlockAckTestSuite::BlockAckTestSuite () AddTestCase (new PacketBufferingCaseA, TestCase::QUICK); AddTestCase (new PacketBufferingCaseB, TestCase::QUICK); AddTestCase (new CtrlBAckResponseHeaderTest, TestCase::QUICK); + AddTestCase (new BlockAckAggregationDisabledTest, TestCase::QUICK); } static BlockAckTestSuite g_blockAckTestSuite; ///< the test suite