A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-txop-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
9#include "ns3/ap-wifi-mac.h"
10#include "ns3/boolean.h"
11#include "ns3/config.h"
12#include "ns3/he-phy.h"
13#include "ns3/log.h"
14#include "ns3/mobility-helper.h"
15#include "ns3/multi-model-spectrum-channel.h"
16#include "ns3/node-list.h"
17#include "ns3/packet-socket-client.h"
18#include "ns3/packet-socket-helper.h"
19#include "ns3/packet-socket-server.h"
20#include "ns3/packet.h"
21#include "ns3/pointer.h"
22#include "ns3/qos-txop.h"
23#include "ns3/qos-utils.h"
24#include "ns3/rng-seed-manager.h"
25#include "ns3/spectrum-wifi-helper.h"
26#include "ns3/string.h"
27#include "ns3/test.h"
28#include "ns3/wifi-mac-header.h"
29#include "ns3/wifi-net-device.h"
30#include "ns3/wifi-ppdu.h"
31#include "ns3/wifi-psdu.h"
32
33using namespace ns3;
34
35NS_LOG_COMPONENT_DEFINE("WifiTxopTest");
36
37/**
38 * @ingroup wifi-test
39 * @ingroup tests
40 *
41 * @brief Test TXOP rules
42 *
43 * A BSS consisting of an AP and 3 non-AP STAs is considered in this test. Both non-HT (802.11a)
44 * and HE devices are tested. Two TXOPs are simulated in this test:
45 * - In the first TXOP, the AP sends a QoS data frame to each of the three STAs. The Ack in
46 * response to the initial frame is corrupted, hence the AP terminates the TXOP and tries again
47 * when a new TXOP is gained. In the new TXOP, the initial frame sent to STA 1 is successfully
48 * received, while the second frame to STA 2 is corrupted. It is checked that the AP performs
49 * PIFS recovery or invokes backoff depending on the value of the PifsRecovery attribute. All
50 * QoS data frames transmitted have a length/duration that does not exceed the length/duration
51 * based RTS/CTS threshold, hence RTS/CTS is never used. After that a QoS data frame has been
52 * sent to every STA, the AP sends another QoS data frame to one of them; the size/duration of
53 * this frame exceeds the threshold, but, given that the STA has already sent a response to the
54 * AP in this TXOP, RTS/CTS is only used if the ProtectedIfResponded is false.
55 * - In the second TXOP, the AP sends a QoS data frame, in case of non-HT devices, or an A-MPDU
56 * consisting of 2 MPDUs, in case of HE devices, to each of the three STAs. All PSDUs transmitted
57 * have a length/duration that exceeds the length/duration based RTS/CTS threshold, hence RTS/CTS
58 * is used to protect every PSDU, unless the SingleRtsPerTxop attribute is set to true, in which
59 * case only the initial frame in the TXOP is protected by RTS/CTS.
60 */
61class WifiTxopTest : public TestCase
62{
63 public:
64 /// Parameters for this test
65 struct Params
66 {
67 bool nonHt; //!< use 802.11a standard if true, 802.11ax standard otherwise
68 bool pifsRecovery; //!< whether PIFS recovery is used after failure of a non-initial frame
69 bool singleRtsPerTxop; //!< whether protection mechanism is used no more than once per TXOP
70 bool lengthBasedRtsCtsThresh; //!< if true, use length based RTS/CTS threshold; if false,
71 //!< use TX duration based RTS/CTS threshold
72 bool protectedIfResponded; //!< whether a station is assumed to be protected if replied to
73 //!< a frame requiring acknowledgment
74 bool protectSingleExchange; //!< whether the Duration/ID field in frames establishing
75 //!< protection only covers the immediate frame exchange instead
76 //!< of rest of the TXOP limit
77 Time singleExchangeProtectionBuffer; //!< whether the NAV duration should be extended by a
78 //!< PIFS after the frame exchange when protection only
79 //!< covers the immediate frame exchange instead of
80 //!< rest of the TXOP limit
81 };
82
83 /**
84 * Constructor
85 * @param params parameters for the Wi-Fi TXOP test
86 */
87 WifiTxopTest(const Params& params);
88
89 /**
90 * Function to trace packets received by the server application
91 * @param context the context
92 * @param p the packet
93 * @param addr the address
94 */
95 void L7Receive(std::string context, Ptr<const Packet> p, const Address& addr);
96
97 /**
98 * Callback invoked when PHY receives a PSDU to transmit
99 * @param context the context
100 * @param psduMap the PSDU map
101 * @param txVector the TX vector
102 * @param txPowerW the tx power in Watts
103 */
104 void Transmit(std::string context,
105 WifiConstPsduMap psduMap,
106 WifiTxVector txVector,
107 double txPowerW);
108
109 /**
110 * Check correctness of transmitted frames
111 */
112 void CheckResults();
113
114 private:
115 void DoRun() override;
116
117 /// Enumeration for traffic directions
118 enum TrafficDirection : uint8_t
119 {
121 UPLINK
122 };
123
124 /**
125 * @param dir the traffic direction (downlink/uplink)
126 * @param staId the index (starting at 0) of the non-AP STA generating/receiving packets
127 * @param count the number of packets to generate
128 * @param pktSize the size of the packets to generate
129 * @return an application generating the given number packets of the given size from/to the
130 * AP to/from the given non-AP STA
131 */
133 std::size_t staId,
134 std::size_t count,
135 std::size_t pktSize) const;
136
137 /// Information about transmitted frames
139 {
140 Time txStart; ///< Frame start TX time
141 Time txDuration; ///< Frame TX duration
142 uint32_t size; ///< PSDU size in bytes
143 WifiMacHeader header; ///< Frame MAC header
144 WifiTxVector txVector; ///< TX vector used to transmit the frame
145 };
146
147 uint16_t m_nStations; ///< number of stations
148 NetDeviceContainer m_staDevices; ///< container for stations' NetDevices
149 NetDeviceContainer m_apDevices; ///< container for AP's NetDevice
150 std::vector<FrameInfo> m_txPsdus; ///< transmitted PSDUs
151 Time m_apTxopLimit; ///< TXOP limit for AP (AC BE)
152 uint8_t m_staAifsn; ///< AIFSN for STAs (AC BE)
153 uint32_t m_staCwMin; ///< CWmin for STAs (AC BE)
154 uint32_t m_staCwMax; ///< CWmax for STAs (AC BE)
155 Time m_staTxopLimit; ///< TXOP limit for STAs (AC BE)
156 uint16_t m_received; ///< number of packets received by the stations
157 bool m_nonHt; ///< @copydoc Params::nonHt
158 std::size_t m_payloadSizeRtsOn; ///< size in bytes of packets protected by RTS
159 std::size_t m_payloadSizeRtsOff; ///< size in bytes of packets not protected by RTS
160 Time m_startTime; ///< time when data frame exchanges start
161 WifiMode m_mode; ///< wifi mode used to transmit data frames
162 bool m_pifsRecovery; ///< @copydoc Params::pifsRecovery
163 bool m_singleRtsPerTxop; ///< @copydoc Params::singleRtsPerTxop
164 bool m_lengthBasedRtsCtsThresh; ///< @copydoc Params::lengthBasedRtsCtsThresh
165 bool m_protectedIfResponded; ///< @copydoc Params::protectedIfResponded
166 bool m_protectSingleExchange; ///< @copydoc Params::protectSingleExchange
167 Time m_singleExchangeProtectionSurplus; ///< @copydoc Params::singleExchangeProtectionBuffer
168 Ptr<ListErrorModel> m_apErrorModel; ///< error model to install on the AP
169 Ptr<ListErrorModel> m_staErrorModel; ///< error model to install on a STA
170 bool m_apCorrupted; ///< whether the frame to be corrupted by the AP has been corrupted
171 bool m_staCorrupted; ///< whether the frame to be corrupted by the STA has been corrupted
172 std::vector<PacketSocketAddress> m_dlSockets; ///< packet socket address for DL traffic
173 std::vector<PacketSocketAddress> m_ulSockets; ///< packet socket address for UL traffic
174};
175
177 : TestCase("Check correct operation within TXOPs with parameters: nonHt=" +
178 std::to_string(params.nonHt) +
179 " pifsRecovery=" + std::to_string(params.pifsRecovery) +
180 " singleRtsPerTxop=" + std::to_string(params.singleRtsPerTxop) +
181 " lengthBasedRtsCtsThresh=" + std::to_string(params.lengthBasedRtsCtsThresh) +
182 " protectedIfResponded=" + std::to_string(params.protectedIfResponded) +
183 " protectSingleExchange=" + std::to_string(params.protectSingleExchange) +
184 " singleExchangeProtectionBuffer=" +
185 std::to_string(params.singleExchangeProtectionBuffer.GetMicroSeconds()) + "us"),
186 m_nStations(3),
187 m_apTxopLimit(MicroSeconds(4768)),
188 m_staAifsn(4),
189 m_staCwMin(63),
190 m_staCwMax(511),
191 m_staTxopLimit(MicroSeconds(3232)),
192 m_received(0),
193 m_nonHt(params.nonHt),
194 m_payloadSizeRtsOn(m_nonHt ? 2000 : 540),
195 m_payloadSizeRtsOff(500),
196 m_startTime(MilliSeconds(m_nonHt ? 410 : 520)),
197 m_mode(m_nonHt ? OfdmPhy::GetOfdmRate12Mbps() : HePhy::GetHeMcs0()),
198 m_pifsRecovery(params.pifsRecovery),
199 m_singleRtsPerTxop(params.singleRtsPerTxop),
200 m_lengthBasedRtsCtsThresh(params.lengthBasedRtsCtsThresh),
201 m_protectedIfResponded(params.protectedIfResponded),
202 m_protectSingleExchange(params.protectSingleExchange),
203 m_singleExchangeProtectionSurplus(params.singleExchangeProtectionBuffer),
204 m_apErrorModel(CreateObject<ListErrorModel>()),
205 m_staErrorModel(CreateObject<ListErrorModel>()),
206 m_apCorrupted(false),
207 m_staCorrupted(false)
208{
209}
210
211void
212WifiTxopTest::L7Receive(std::string context, Ptr<const Packet> p, const Address& addr)
213{
214 if (p->GetSize() >= m_payloadSizeRtsOff)
215 {
216 m_received++;
217 }
218}
219
220void
221WifiTxopTest::Transmit(std::string context,
222 WifiConstPsduMap psduMap,
223 WifiTxVector txVector,
224 double txPowerW)
225{
226 bool corrupted{false};
227
228 // The AP does not correctly receive the Ack sent in response to the QoS
229 // data frame sent to the first station
230 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
231 hdr.IsAck() && !m_apCorrupted && !m_txPsdus.empty() &&
232 m_txPsdus.back().header.IsQosData() &&
233 m_txPsdus.back().header.GetAddr1() == m_staDevices.Get(0)->GetAddress())
234 {
235 corrupted = m_apCorrupted = true;
236 m_apErrorModel->SetList({psduMap.begin()->second->GetPacket()->GetUid()});
237 }
238
239 // The second station does not correctly receive the first QoS data frame sent by the AP
240 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
241 !m_txPsdus.empty() && hdr.IsQosData() &&
242 hdr.GetAddr1() == m_staDevices.Get(1)->GetAddress())
243 {
244 if (!m_staCorrupted)
245 {
246 corrupted = m_staCorrupted = true;
247 }
248 if (corrupted)
249 {
250 m_staErrorModel->SetList({psduMap.begin()->second->GetPacket()->GetUid()});
251 }
252 else
253 {
255 }
256 }
257
258 // When the AP sends the first frame to the third station (which is not protected by RTS/CTS),
259 // we generate another frame addressed to the second station whose size/duration exceeds the
260 // threshold; however, RTS is not used because the second station has already responded to
261 // another frame in the same TXOP
262 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
263 hdr.IsQosData() && hdr.GetAddr1() == m_staDevices.Get(2)->GetAddress() &&
264 hdr.GetSequenceNumber() == (m_nonHt ? 0 : 1))
265 {
266 m_apDevices.Get(0)->GetNode()->AddApplication(
268 }
269
270 // Log all transmitted frames that are not beacon frames and have been transmitted
271 // after the start time (so as to skip association requests/responses)
272 if (!psduMap.begin()->second->GetHeader(0).IsBeacon() && Simulator::Now() >= m_startTime)
273 {
274 m_txPsdus.push_back({Simulator::Now(),
276 psduMap[SU_STA_ID]->GetSize(),
277 psduMap[SU_STA_ID]->GetHeader(0),
278 txVector});
279 }
280
281 // Print all the transmitted frames if the test is executed through test-runner
282 NS_LOG_INFO(psduMap.begin()->second->GetHeader(0).GetTypeString()
283 << " seq " << psduMap.begin()->second->GetHeader(0).GetSequenceNumber() << " to "
284 << psduMap.begin()->second->GetAddr1() << " TX duration "
286 << " duration/ID " << psduMap.begin()->second->GetHeader(0).GetDuration()
287 << (corrupted ? " CORRUPTED" : "") << std::endl);
288}
289
290void
292{
293 // LogComponentEnable("WifiTxopTest", LOG_LEVEL_ALL);
294 NS_LOG_FUNCTION(this);
295
298 int64_t streamNumber = 100;
299
300 NodeContainer wifiApNode;
301 wifiApNode.Create(1);
302
303 NodeContainer wifiStaNodes;
304 wifiStaNodes.Create(m_nStations);
305
306 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
308 spectrumChannel->AddPropagationLossModel(lossModel);
310 spectrumChannel->SetPropagationDelayModel(delayModel);
311
313 phy.SetChannel(spectrumChannel);
314 // use default 20 MHz channel in 5 GHz band
315 phy.Set("ChannelSettings", StringValue("{0, 20, BAND_5GHZ, 0}"));
316
317 Config::SetDefault("ns3::QosFrameExchangeManager::PifsRecovery", BooleanValue(m_pifsRecovery));
318 Config::SetDefault("ns3::QosFrameExchangeManager::ProtectSingleExchange",
320 Config::SetDefault("ns3::QosFrameExchangeManager::SingleExchangeProtectionSurplus",
322 Config::SetDefault("ns3::WifiDefaultProtectionManager::SingleRtsPerTxop",
325 {
326 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold",
328 }
329 else
330 {
331 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsTxDurationThresh",
332 TimeValue(Seconds(m_payloadSizeRtsOn * (m_nonHt ? 1 : 2) * 8.0 /
333 m_mode.GetDataRate(MHz_u{20}))));
334 }
335 Config::SetDefault("ns3::FrameExchangeManager::ProtectedIfResponded",
336 BooleanValue(m_protectedIfResponded));
337
338 WifiHelper wifi;
339 wifi.SetStandard(m_nonHt ? WIFI_STANDARD_80211a : WIFI_STANDARD_80211ax);
340 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
341 "DataMode",
342 WifiModeValue(m_mode),
343 "ControlMode",
344 StringValue("OfdmRate6Mbps"));
345
346 WifiMacHelper mac;
347 mac.SetType("ns3::StaWifiMac",
348 "QosSupported",
349 BooleanValue(true),
350 "Ssid",
351 SsidValue(Ssid("non-existent-ssid")));
352
353 m_staDevices = wifi.Install(phy, mac, wifiStaNodes);
354 streamNumber += WifiHelper::AssignStreams(m_staDevices, streamNumber);
355
356 mac.SetType(
357 "ns3::ApWifiMac",
358 "QosSupported",
359 BooleanValue(true),
360 "Ssid",
361 SsidValue(Ssid("wifi-txop-ssid")),
362 "BeaconInterval",
363 TimeValue(MicroSeconds(102400)),
364 "EnableBeaconJitter",
365 BooleanValue(false),
366 "AifsnsForSta",
367 StringValue(std::string("BE ") + std::to_string(m_staAifsn)),
368 "CwMinsForSta",
370 ApWifiMac::UintAccessParamsMap{{AC_BE, std::vector<uint64_t>{m_staCwMin}}}),
371 "CwMaxsForSta",
372 StringValue(std::string("BE ") + std::to_string(m_staCwMax)),
373 "TxopLimitsForSta",
374 StringValue(std::string("BE ") + std::to_string(m_staTxopLimit.GetMicroSeconds()) + "us"));
375
376 mac.SetEdca(AC_BE, "TxopLimits", AttributeContainerValue<TimeValue>(std::list{m_apTxopLimit}));
377
378 m_apDevices = wifi.Install(phy, mac, wifiApNode);
379 streamNumber += WifiHelper::AssignStreams(m_apDevices, streamNumber);
380
381 // schedule association requests at different times. One station's SSID is
382 // set to the correct value before initialization, so that such a station
383 // starts the scanning procedure by looking for the correct SSID
384 Ptr<WifiNetDevice> dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(0));
385 dev->GetMac()->SetSsid(Ssid("wifi-txop-ssid"));
386
387 for (uint16_t i = 1; i < m_nStations; i++)
388 {
389 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
392 dev->GetMac(),
393 Ssid("wifi-txop-ssid"));
394 }
395
398
399 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
400 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
401 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
402 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
403 mobility.SetPositionAllocator(positionAlloc);
404
405 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
406 mobility.Install(wifiApNode);
407 mobility.Install(wifiStaNodes);
408
409 PacketSocketHelper packetSocket;
410 packetSocket.Install(wifiApNode);
411 packetSocket.Install(wifiStaNodes);
412
413 // install a packet socket server on all nodes
414 for (auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); ++nodeIt)
415 {
416 PacketSocketAddress srvAddr;
417 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
418 NS_TEST_ASSERT_MSG_NE(device, nullptr, "Expected a WifiNetDevice");
419 srvAddr.SetSingleDevice(device->GetIfIndex());
420 srvAddr.SetProtocol(1);
421
423 server->SetLocal(srvAddr);
424 (*nodeIt)->AddApplication(server);
425 server->SetStartTime(Time{0}); // now
426 server->SetStopTime(Seconds(1));
427 }
428
429 // set DL and UL packet sockets
430 for (uint16_t i = 0; i < m_nStations; ++i)
431 {
432 m_dlSockets.emplace_back();
433 m_dlSockets.back().SetSingleDevice(m_apDevices.Get(0)->GetIfIndex());
434 m_dlSockets.back().SetPhysicalAddress(m_staDevices.Get(i)->GetAddress());
435 m_dlSockets.back().SetProtocol(1);
436
437 m_ulSockets.emplace_back();
438 m_ulSockets.back().SetSingleDevice(m_staDevices.Get(i)->GetIfIndex());
439 m_ulSockets.back().SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
440 m_ulSockets.back().SetProtocol(1);
441 }
442
443 // DL frames
444 for (uint16_t i = 0; i < m_nStations; i++)
445 {
446 if (!m_nonHt)
447 {
448 // Send one QoS data frame to establish Block Ack agreement (packet size is such that
449 // this packet is not counted as a received packet)
450 Simulator::Schedule(m_startTime - MilliSeconds(110 - i * 25),
452 wifiApNode.Get(0),
453 GetApplication(DOWNLINK, i, 1, m_payloadSizeRtsOff - 1));
454 }
455
456 // Send one QoS data frame (not protected by RTS/CTS) to each station
457 Simulator::Schedule(m_startTime,
459 wifiApNode.Get(0),
460 GetApplication(DOWNLINK, i, 1, m_payloadSizeRtsOff));
461
462 // Send one QoS data frame (protected by RTS/CTS) to each station
463 Simulator::Schedule(m_startTime + MilliSeconds(110),
465 wifiApNode.Get(0),
466 GetApplication(DOWNLINK, i, m_nonHt ? 1 : 2, m_payloadSizeRtsOn));
467 }
468
469 // install the error model on the AP
470 dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
471 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(m_apErrorModel);
472
473 // install the error model on the second station
474 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(1));
475 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(m_staErrorModel);
476
477 // UL Traffic (the first station sends one frame to the AP)
478 {
479 if (!m_nonHt)
480 {
481 // Send one QoS data frame to establish Block Ack agreement (packet size is such that
482 // this packet is not counted as a received packet)
483 Simulator::Schedule(m_startTime - MilliSeconds(35),
485 wifiStaNodes.Get(0),
486 GetApplication(UPLINK, 0, 1, m_payloadSizeRtsOff - 1));
487 }
488
489 Simulator::Schedule(m_startTime + MilliSeconds(2),
491 wifiStaNodes.Get(0),
492 GetApplication(UPLINK, 0, 1, m_payloadSizeRtsOff));
493 }
494
495 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx",
497 // Trace PSDUs passed to the PHY on all devices
498 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
500
503
504 CheckResults();
505
507}
508
511 std::size_t staId,
512 std::size_t count,
513 std::size_t pktSize) const
514{
515 auto client = CreateObject<PacketSocketClient>();
516 client->SetAttribute("PacketSize", UintegerValue(pktSize));
517 client->SetAttribute("MaxPackets", UintegerValue(count));
518 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
519 client->SetRemote(dir == DOWNLINK ? m_dlSockets.at(staId) : m_ulSockets.at(staId));
520 client->SetStartTime(Time{0}); // now
521 client->SetStopTime(Seconds(1));
522
523 return client;
524}
525
526void
528{
529 // check that STAs used the access parameters advertised by the AP
530 for (uint32_t i = 0; i < m_staDevices.GetN(); ++i)
531 {
532 auto staEdca = DynamicCast<WifiNetDevice>(m_staDevices.Get(i))->GetMac()->GetQosTxop(AC_BE);
533 NS_TEST_EXPECT_MSG_EQ(staEdca->GetAifsn(SINGLE_LINK_OP_ID),
535 "Unexpected AIFSN for STA " << i);
536 NS_TEST_EXPECT_MSG_EQ(staEdca->GetMinCw(SINGLE_LINK_OP_ID),
538 "Unexpected CWmin for STA " << i);
539 NS_TEST_EXPECT_MSG_EQ(staEdca->GetMaxCw(SINGLE_LINK_OP_ID),
541 "Unexpected CWmax for STA " << i);
542 NS_TEST_EXPECT_MSG_EQ(staEdca->GetTxopLimit(SINGLE_LINK_OP_ID),
544 "Unexpected TXOP limit for STA " << i);
545 }
546
547 const auto apDev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
548
549 NS_TEST_EXPECT_MSG_EQ(apDev->GetMac()->GetQosTxop(AC_BE)->GetTxopLimit(SINGLE_LINK_OP_ID),
551 "Unexpected TXOP limit for AP");
552
553 const auto aifsn = apDev->GetMac()->GetQosTxop(AC_BE)->GetAifsn(SINGLE_LINK_OP_ID);
554 const auto cwMin = apDev->GetMac()->GetQosTxop(AC_BE)->GetMinCw(SINGLE_LINK_OP_ID);
555 Time tEnd; // TX end for a frame
556 Time tStart; // TX start for the next frame
557 Time txopStart; // TXOP start time
558 Time tolerance = NanoSeconds(50); // due to propagation delay
559 Time sifs = apDev->GetPhy()->GetSifs();
560 Time slot = apDev->GetPhy()->GetSlot();
561 Time navEnd;
564 const uint32_t rtsCtsThreshold = DynamicCast<const UintegerValue>(info.initialValue)->Get();
565 WifiRemoteStationManager::GetTypeId().LookupAttributeByName("RtsCtsTxDurationThresh", &info);
566 const Time rtsCtsTxDurationThresh = DynamicCast<const TimeValue>(info.initialValue)->Get();
567
568 // lambda to round Duration/ID (in microseconds) up to the next higher integer
569 auto RoundDurationId = [](Time t) {
570 return MicroSeconds(ceil(static_cast<double>(t.GetNanoSeconds()) / 1000));
571 };
572
573 /*
574 * Verify the different behavior followed when an initial/non-initial frame of a TXOP
575 * fails. Also, verify that a CF-end frame is sent if enough time remains in the TXOP.
576 * The destination of failed frames is put in square brackets below.
577 *
578 * |--NAV----till end TXOP-------->|
579 * | |---NAV--till end TXOP--->|
580 * | | |-----------------------------NAV--------------------------------->|
581 * | | | |----------------------------NAV---------------------------->|
582 * | | | | |---------------------------NAV----------------------->|
583 * | | | | | |----------------NAV------------------>|
584 * | | | | | | |-------------NAV--------------->|
585 * | | | | | Ack | | |-----------NAV----------->|
586 * Start| | Start| | | Timeout | | | |--------NAV-------->|
587 * TXOP | | TXOP | | | |-PIFS-> | | | | |-----NAV----->|
588 * | | | back | | | | |- or -> | | | | | |--NAV-->|
589 * ┌───┐ ┌───┐-off->┌───┐ ┌───┐ ┌───┐ |-back->┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌─────┐
590 * │QoS│ │Ack│ │QoS│ │Ack│ │QoS│ |-off ->│QoS│ │Ack│ │QoS│ │Ack│ │QoS│ │Ack│ │CFend│
591 * ───┴───┴─┴───┴──────┴───┴─┴───┴─┴───┴───────────┴───┴─┴───┴─┴───┴─┴───┴─┴───┴─┴───┴─┴─────┴─
592 * TA: AP STA1 AP STA1 AP AP STA2 AP STA3 AP STA2 AP
593 * RA: STA1 [AP] STA1 AP [STA2] STA2 AP STA3 AP STA2 AP all
594 *
595 * NOTE: If ProtectedIfResponded is false, the last QoS data frame is protected by RTS/CTS
596 * NOTE: If ProtectSingleExchange is true, CF-END frames are not transmitted
597 * and NAV ends once DATA+Ack is completed
598 */
599
600 // We expect 25 frames to be transmitted if SingleRtsPerTxop is false and 22 frames (2 RTS
601 // less, 2 CTS less, 1 more CF-End). If ProtectedIfResponded is false, there are 2 frames
602 // (an RTS and a CTS) more. If ProtectSingleExchange is true, there are 2 (if
603 // SingleRtsPerTxop is false) or 3 (if SingleRtsPerTxop is true) less frames (CF-END)
605 m_txPsdus.size(),
607 ? 21U + (m_protectedIfResponded ? 0U : 2U) + (m_protectSingleExchange ? 0U : 3U)
608 : 25U + (m_protectedIfResponded ? 0U : 2U) + (m_protectSingleExchange ? 0U : 2U)),
609 "Unexpected number of transmitted frames");
610
611 // the first frame sent after 400ms is a QoS data frame sent by the AP to STA1 without RTS/CTS
612 txopStart = m_txPsdus[0].txStart;
613
614 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].header.IsQosData(), true, "Expected a QoS data frame");
615 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].header.GetAddr1(),
616 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
617 "Expected a frame sent by the AP to the first station");
619 {
621 rtsCtsThreshold,
622 "PSDU size expected not to exceed length based RTS/CTS threshold");
623 }
624 else
625 {
627 m_txPsdus[0].txDuration,
628 rtsCtsTxDurationThresh,
629 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
630 }
632 m_txPsdus[0].header.GetDuration(),
634 ? RoundDurationId(m_apTxopLimit - m_txPsdus[0].txDuration)
635 : sifs + m_txPsdus[1].txDuration + m_singleExchangeProtectionSurplus),
637 ? "Duration/ID of the first frame must cover the whole TXOP"
638 : "Duration/ID of the first frame must be set to remaining time to "
639 "complete DATA+ACK sequence"));
640
641 // a Normal Ack is sent by STA1
642 tEnd = m_txPsdus[0].txStart + m_txPsdus[0].txDuration;
643 tStart = m_txPsdus[1].txStart;
644
645 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
647 tEnd + sifs + tolerance,
648 "Ack in response to the first frame sent too late");
649 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[1].header.IsAck(), true, "Expected a Normal Ack");
650 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[1].header.GetAddr1(),
651 apDev->GetMac()->GetAddress(),
652 "Expected a Normal Ack sent to the AP");
654 m_txPsdus[1].header.GetDuration(),
655 RoundDurationId(m_txPsdus[0].header.GetDuration() - sifs - m_txPsdus[1].txDuration),
656 "Duration/ID of the Ack must be derived from that of the first frame");
657
658 // the AP receives a corrupted Ack in response to the frame it sent, which is the initial
659 // frame of a TXOP. Hence, the TXOP is terminated and the AP retransmits the frame after
660 // waiting for EIFS - DIFS + AIFS + backoff (see section 10.3.2.3.7 of 802.11-2020)
661 txopStart = m_txPsdus[2].txStart;
662
663 tEnd = m_txPsdus[1].txStart + m_txPsdus[1].txDuration;
664 tStart = m_txPsdus[2].txStart;
665
666 auto apPhy = apDev->GetPhy(SINGLE_LINK_OP_ID);
667 auto eifsNoDifs = apPhy->GetSifs() + GetEstimatedAckTxTime(m_txPsdus[1].txVector);
668
670 tStart - tEnd,
671 eifsNoDifs + sifs + aifsn * slot,
672 "Less than AIFS elapsed between AckTimeout and the next TXOP start");
674 tStart - tEnd,
675 eifsNoDifs + sifs + aifsn * slot + (2 * (cwMin + 1) - 1) * slot,
676 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
677 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].header.IsQosData(),
678 true,
679 "Expected to retransmit a QoS data frame");
680 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].header.GetAddr1(),
681 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
682 "Expected to retransmit a frame to the first station");
684 {
686 rtsCtsThreshold,
687 "PSDU size expected not to exceed length based RTS/CTS threshold");
688 }
689 else
690 {
692 m_txPsdus[2].txDuration,
693 rtsCtsTxDurationThresh,
694 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
695 }
697 m_txPsdus[2].header.GetDuration(),
699 ? RoundDurationId(m_apTxopLimit - m_txPsdus[2].txDuration)
700 : sifs + m_txPsdus[3].txDuration + m_singleExchangeProtectionSurplus),
702 ? "Duration/ID of the retransmitted frame must cover the whole TXOP"
703 : "Duration/ID of the retransmitted frame must be set to remaining time to "
704 "complete DATA+ACK sequence"));
705
706 // a Normal Ack is then sent by STA1
707 tEnd = m_txPsdus[2].txStart + m_txPsdus[2].txDuration;
708 tStart = m_txPsdus[3].txStart;
709
710 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
712 tEnd + sifs + tolerance,
713 "Ack in response to the first frame sent too late");
714 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[3].header.IsAck(), true, "Expected a Normal Ack");
715 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[3].header.GetAddr1(),
716 apDev->GetMac()->GetAddress(),
717 "Expected a Normal Ack sent to the AP");
719 m_txPsdus[3].header.GetDuration(),
720 RoundDurationId(m_txPsdus[2].header.GetDuration() - sifs - m_txPsdus[3].txDuration),
721 "Duration/ID of the Ack must be derived from that of the previous frame");
722
723 // the AP sends a frame to STA2
724 tEnd = m_txPsdus[3].txStart + m_txPsdus[3].txDuration;
725 tStart = m_txPsdus[4].txStart;
726
727 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second frame sent too early");
728 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second frame sent too late");
729 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.IsQosData(), true, "Expected a QoS data frame");
730 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.GetAddr1(),
731 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
732 "Expected a frame sent by the AP to the second station");
734 {
736 rtsCtsThreshold,
737 "PSDU size expected not to exceed length based RTS/CTS threshold");
738 }
739 else
740 {
742 m_txPsdus[4].txDuration,
743 rtsCtsTxDurationThresh,
744 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
745 }
746 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.GetDuration(),
748 ? RoundDurationId(m_apTxopLimit -
749 (m_txPsdus[4].txStart - txopStart) -
750 m_txPsdus[4].txDuration)
751 : sifs +
752 m_txPsdus[6].txDuration + m_singleExchangeProtectionSurplus /* ACK is 2 frames later since this DATA is first corrupted */),
754 ? "Duration/ID of the second frame does not cover the remaining TXOP"
755 : "Duration/ID of the second frame must be set to remaining time to "
756 "complete DATA+ACK sequence"));
757
758 // STA2 receives a corrupted frame and hence it does not send the Ack. When the AckTimeout
759 // expires, the AP performs PIFS recovery or invoke backoff, without terminating the TXOP,
760 // because a non-initial frame of the TXOP failed
761 auto apStationManager = apDev->GetRemoteStationManager(SINGLE_LINK_OP_ID);
762 auto staAddress = DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress();
763 auto ackTxVector = apStationManager->GetAckTxVector(staAddress, m_txPsdus[4].txVector);
764 tEnd = m_txPsdus[4].txStart + m_txPsdus[4].txDuration + sifs + slot +
765 WifiPhy::CalculatePhyPreambleAndHeaderDuration(ackTxVector); // AckTimeout
766 tStart = m_txPsdus[5].txStart;
767
768 if (m_pifsRecovery)
769 {
770 NS_TEST_EXPECT_MSG_EQ(tEnd + sifs + slot,
771 tStart,
772 "Second frame must have been sent after a PIFS");
773 }
774 else
775 {
777 tStart - tEnd,
778 sifs + aifsn * slot,
779 "Less than AIFS elapsed between AckTimeout and the next transmission");
781 tStart - tEnd,
782 sifs + aifsn * slot + (2 * (cwMin + 1) - 1) * slot,
783 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
784 }
785 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[5].header.IsQosData(), true, "Expected a QoS data frame");
786 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[5].header.GetAddr1(),
787 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
788 "Expected a frame sent by the AP to the second station");
790 {
792 rtsCtsThreshold,
793 "PSDU size expected not to exceed length based RTS/CTS threshold");
794 }
795 else
796 {
798 m_txPsdus[5].txDuration,
799 rtsCtsTxDurationThresh,
800 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
801 }
803 m_txPsdus[5].header.GetDuration(),
805 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[5].txStart - txopStart) -
806 m_txPsdus[5].txDuration)
807 : sifs + m_txPsdus[6].txDuration + m_singleExchangeProtectionSurplus),
809 ? "Duration/ID of the second frame does not cover the remaining TXOP"
810 : "Duration/ID of the second frame must be set to remaining time to "
811 "complete DATA+ACK sequence"));
812
813 // a Normal Ack is then sent by STA2
814 tEnd = m_txPsdus[5].txStart + m_txPsdus[5].txDuration;
815 tStart = m_txPsdus[6].txStart;
816
817 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
818 tStart,
819 "Ack in response to the second frame sent too early");
821 tEnd + sifs + tolerance,
822 "Ack in response to the second frame sent too late");
823 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[6].header.IsAck(), true, "Expected a Normal Ack");
824 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[6].header.GetAddr1(),
825 apDev->GetMac()->GetAddress(),
826 "Expected a Normal Ack sent to the AP");
828 m_txPsdus[6].header.GetDuration(),
829 RoundDurationId(m_txPsdus[5].header.GetDuration() - sifs - m_txPsdus[6].txDuration),
830 "Duration/ID of the Ack must be derived from that of the previous frame");
831
832 // the AP sends a frame to STA3
833 tEnd = m_txPsdus[6].txStart + m_txPsdus[6].txDuration;
834 tStart = m_txPsdus[7].txStart;
835
836 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third frame sent too early");
837 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third frame sent too late");
838 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[7].header.IsQosData(), true, "Expected a QoS data frame");
839 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[7].header.GetAddr1(),
840 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
841 "Expected a frame sent by the AP to the third station");
843 {
845 rtsCtsThreshold,
846 "PSDU size expected not to exceed length based RTS/CTS threshold");
847 }
848 else
849 {
851 m_txPsdus[7].txDuration,
852 rtsCtsTxDurationThresh,
853 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
854 }
856 m_txPsdus[7].header.GetDuration(),
858 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[7].txStart - txopStart) -
859 m_txPsdus[7].txDuration)
860 : sifs + m_txPsdus[8].txDuration + m_singleExchangeProtectionSurplus),
862 ? "Duration/ID of the third frame does not cover the remaining TXOP"
863 : "Duration/ID of the third frame must be set to remaining time to "
864 "complete DATA+ACK sequence"));
865
866 // a Normal Ack is then sent by STA3
867 tEnd = m_txPsdus[7].txStart + m_txPsdus[7].txDuration;
868 tStart = m_txPsdus[8].txStart;
869
870 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the third frame sent too early");
872 tEnd + sifs + tolerance,
873 "Ack in response to the third frame sent too late");
874 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[8].header.IsAck(), true, "Expected a Normal Ack");
875 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[8].header.GetAddr1(),
876 apDev->GetMac()->GetAddress(),
877 "Expected a Normal Ack sent to the AP");
879 m_txPsdus[8].header.GetDuration(),
880 RoundDurationId(m_txPsdus[7].header.GetDuration() - sifs - m_txPsdus[8].txDuration),
881 "Duration/ID of the Ack must be derived from that of the previous frame");
882
883 // the AP sends another frame to STA2, which is only protected if ProtectedIfResponded is true,
884 // because its size/duration exceeds the threshold but STA2 has already responded to the AP in
885 // this TXOP
887 {
888 tEnd = m_txPsdus[8].txStart + m_txPsdus[8].txDuration;
889 tStart = m_txPsdus[9].txStart;
890
891 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "RTS before fourth frame sent too early");
893 tEnd + sifs + tolerance,
894 "RTS before fourth frame sent too late");
895 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.IsRts(), true, "Expected an RTS frame");
897 m_txPsdus[9].header.GetAddr1(),
898 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
899 "Expected an RTS frame sent by the AP to the second station");
901 m_txPsdus[9].header.GetDuration(),
903 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[9].txStart - txopStart) -
904 m_txPsdus[9].txDuration)
905 : sifs + m_txPsdus[10].txDuration + sifs + m_txPsdus[11].txDuration + sifs +
908 ? "Duration/ID of the RTS before the fourth frame does not cover the remaining "
909 "TXOP"
910 : "Duration/ID of the RTS before the fourth frame must be set to remaining time "
911 "to complete CTS+DATA+ACK sequence"));
912
913 // a CTS is sent by STA2
914 tEnd = m_txPsdus[9].txStart + m_txPsdus[9].txDuration;
915 tStart = m_txPsdus[10].txStart;
916
917 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
918 tStart,
919 "CTS in response to RTS before the fourth frame sent too early");
921 tEnd + sifs + tolerance,
922 "CTS in response to RTS before the fourth frame sent too late");
923 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.IsCts(), true, "Expected a CTS");
924 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.GetAddr1(),
925 apDev->GetMac()->GetAddress(),
926 "Expected a CTS frame sent to the AP");
928 m_txPsdus[10].header.GetDuration(),
929 RoundDurationId(m_txPsdus[9].header.GetDuration() - sifs - m_txPsdus[10].txDuration),
930 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
931
932 // the AP sends another frame to STA2
933 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
934 tStart = m_txPsdus[11].txStart;
935
936 // remove RTS and CTS so that indices are aligned with the ProtectedIfResponded true case
937 m_txPsdus.erase(std::next(m_txPsdus.cbegin(), 9), std::next(m_txPsdus.cbegin(), 11));
938 }
939 else
940 {
941 // the AP sends another frame to STA2
942 tEnd = m_txPsdus[8].txStart + m_txPsdus[8].txDuration;
943 tStart = m_txPsdus[9].txStart;
944 }
945
946 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Fourth frame sent too early");
947 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Fourth frame sent too late");
948 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.IsQosData(), true, "Expected a QoS data frame");
949 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.GetAddr1(),
950 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
951 "Expected a frame sent by the AP to the second station");
953 {
955 rtsCtsThreshold,
956 "PSDU size expected to exceed length based RTS/CTS threshold");
957 }
958 else
959 {
960 NS_TEST_EXPECT_MSG_GT(m_txPsdus[9].txDuration,
961 rtsCtsTxDurationThresh,
962 "PSDU duration expected to exceed duration based RTS/CTS threshold");
963 }
965 m_txPsdus[9].header.GetDuration(),
967 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[9].txStart - txopStart) -
968 m_txPsdus[9].txDuration)
969 : sifs + m_txPsdus[10].txDuration + m_singleExchangeProtectionSurplus),
971 ? "Duration/ID of the fourth frame does not cover the remaining TXOP"
972 : "Duration/ID of the fourth frame must be set to remaining time to "
973 "complete DATA+(Block)ACK sequence"));
974
975 std::string ack(m_nonHt ? "Normal Ack" : "Block Ack");
976
977 // a Normal/Block Ack is then sent by STA1
978 tEnd = m_txPsdus[9].txStart + m_txPsdus[9].txDuration;
979 tStart = m_txPsdus[10].txStart;
980
981 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
982 tStart,
983 ack << " in response to the fourth QoS data frame sent too early");
985 tEnd + sifs + tolerance,
986 ack << " in response to the fourth QoS data frame sent too late");
988 (m_nonHt ? m_txPsdus[10].header.IsAck() : m_txPsdus[10].header.IsBlockAck()),
989 true,
990 "Expected a " << ack);
991 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.GetAddr1(),
992 apDev->GetMac()->GetAddress(),
993 "Expected a " << ack << " sent to the AP");
995 m_txPsdus[10].header.GetDuration(),
996 RoundDurationId(m_txPsdus[9].header.GetDuration() - sifs - m_txPsdus[10].txDuration),
997 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
998
1000 {
1001 // the TXOP limit is such that enough time for sending a CF-End frame remains
1002 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
1003 tStart = m_txPsdus[11].txStart;
1004
1005 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
1006 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
1007 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.IsCfEnd(), true, "Expected a CF-End frame");
1008 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.GetDuration(),
1009 MicroSeconds(0),
1010 "Duration/ID must be set to 0 for CF-End frames");
1011
1012 // remove CF-END so that indices are aligned with the protectSingleExchange false case
1013 m_txPsdus.erase(std::next(m_txPsdus.cbegin(), 11), std::next(m_txPsdus.cbegin(), 12));
1014 }
1015
1016 // the CF-End frame resets the NAV on STA1, which can now transmit
1017 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
1018 tStart = m_txPsdus[11].txStart;
1019
1020 NS_TEST_EXPECT_MSG_GT_OR_EQ(tStart - tEnd,
1021 sifs + m_staAifsn * slot,
1022 "Less than AIFS elapsed between two TXOPs");
1023 NS_TEST_EXPECT_MSG_LT_OR_EQ(tStart - tEnd,
1024 sifs + m_staAifsn * slot + m_staCwMin * slot + tolerance,
1025 "More than AIFS+BO elapsed between two TXOPs");
1026 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.IsQosData(), true, "Expected a QoS data frame");
1027 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.GetAddr1(),
1028 apDev->GetMac()->GetAddress(),
1029 "Expected a frame sent by the first station to the AP");
1031 {
1033 rtsCtsThreshold,
1034 "PSDU size expected not to exceed length based RTS/CTS threshold");
1035 }
1036 else
1037 {
1039 m_txPsdus[11].txDuration,
1040 rtsCtsTxDurationThresh,
1041 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
1042 }
1044 m_txPsdus[11].header.GetDuration(),
1046 ? RoundDurationId(m_staTxopLimit - m_txPsdus[11].txDuration)
1047 : sifs + m_txPsdus[12].txDuration + m_singleExchangeProtectionSurplus),
1049 ? "Duration/ID of the frame sent by the first station does not "
1050 "cover the remaining TXOP"
1051 : "Duration/ID of the frame sent by the first station must be set "
1052 "to remaining time to "
1053 "complete DATA+ACK sequence"));
1054
1055 // a Normal Ack is then sent by the AP
1056 tEnd = m_txPsdus[11].txStart + m_txPsdus[11].txDuration;
1057 tStart = m_txPsdus[12].txStart;
1058
1059 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack sent too early");
1060 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Ack sent too late");
1061 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[12].header.IsAck(), true, "Expected a Normal Ack");
1062 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[12].header.GetAddr1(),
1063 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1064 "Expected a Normal Ack sent to the first station");
1066 m_txPsdus[12].header.GetDuration(),
1067 RoundDurationId(m_txPsdus[11].header.GetDuration() - sifs - m_txPsdus[12].txDuration),
1068 "Duration/ID of the Ack must be derived from that of the previous frame");
1069
1071 {
1072 // the TXOP limit is such that enough time for sending a CF-End frame remains
1073 tEnd = m_txPsdus[12].txStart + m_txPsdus[12].txDuration;
1074 tStart = m_txPsdus[13].txStart;
1075
1076 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
1077 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
1078 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.IsCfEnd(), true, "Expected a CF-End frame");
1079 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.GetDuration(),
1080 MicroSeconds(0),
1081 "Duration/ID must be set to 0 for CF-End frames");
1082
1083 // remove CF-END so that indices are aligned with the protectSingleExchange false case
1084 m_txPsdus.erase(std::next(m_txPsdus.cbegin(), 13), std::next(m_txPsdus.cbegin(), 14));
1085 }
1086
1087 /*
1088 * Verify that the Duration/ID of RTS/CTS frames is set correctly, that the TXOP holder is
1089 * kept and allows stations to ignore NAV properly and that the CF-End Frame is not sent if
1090 * not enough time remains. If SingleRtsPerTxop is set to true, only one RTS/CTS is sent.
1091 *
1092 * |---------------------------------------------NAV---------------------------------->|
1093 * | |-----------------------------------------NAV------------------------------->| |
1094 * | |-------------------------------------NAV---------------------------->| | | |
1095 * |---------------------------------NAV------------------------->| | | | |
1096 * |-----------------------------NAV---------------------->| | | | | |
1097 * |-------------------------NAV------------------->| | | | | | |
1098 * |---------------------NAV---------------->| | | | | | | |
1099 * |-----------------NAV------------->| | | | | | | | |
1100 * |-------------NAV---------->| | | | | | | | | |
1101 * |---------NAV------->| | | | | | | | | | |
1102 * |-----NAV---->| | | | | | | | | | | |
1103 * |-NAV->|
1104 * |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---|
1105 * |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack|
1106 * ----------------------------------------------------------------------------------------------------
1107 * From: AP STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3
1108 * To: STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3 AP
1109 */
1110
1111 // the first frame is an RTS frame sent by the AP to STA1
1112 txopStart = m_txPsdus[13].txStart;
1113
1114 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.IsRts(), true, "Expected an RTS frame");
1115 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.GetAddr1(),
1116 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1117 "Expected an RTS frame sent by the AP to the first station");
1118 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.GetDuration(),
1120 ? RoundDurationId(m_apTxopLimit - m_txPsdus[13].txDuration)
1121 : sifs + m_txPsdus[14].txDuration + sifs + m_txPsdus[15].txDuration +
1122 sifs + m_txPsdus[16].txDuration +
1125 ? "Duration/ID of the first RTS frame must cover the whole TXOP"
1126 : "Duration/ID of the first RTS frame must be set to remaining time "
1127 "to complete CTS+DATA+(Block)ACK sequence"));
1128
1129 // a CTS is sent by STA1
1130 tEnd = m_txPsdus[13].txStart + m_txPsdus[13].txDuration;
1131 tStart = m_txPsdus[14].txStart;
1132
1133 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1134 tStart,
1135 "CTS in response to the first RTS frame sent too early");
1136 NS_TEST_EXPECT_MSG_LT(tStart,
1137 tEnd + sifs + tolerance,
1138 "CTS in response to the first RTS frame sent too late");
1139 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[14].header.IsCts(), true, "Expected a CTS");
1140 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[14].header.GetAddr1(),
1141 apDev->GetMac()->GetAddress(),
1142 "Expected a CTS frame sent to the AP");
1144 m_txPsdus[14].header.GetDuration(),
1145 RoundDurationId(m_txPsdus[13].header.GetDuration() - sifs - m_txPsdus[14].txDuration),
1146 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1147
1148 // the AP sends a frame to STA1
1149 tEnd = m_txPsdus[14].txStart + m_txPsdus[14].txDuration;
1150 tStart = m_txPsdus[15].txStart;
1151
1152 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "First QoS data frame sent too early");
1153 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "First QoS data frame sent too late");
1154 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[15].header.IsQosData(), true, "Expected a QoS data frame");
1155 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[15].header.GetAddr1(),
1156 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1157 "Expected a frame sent by the AP to the first station");
1159 {
1161 rtsCtsThreshold,
1162 "PSDU size expected to exceed length based RTS/CTS threshold");
1163 }
1164 else
1165 {
1166 NS_TEST_EXPECT_MSG_GT(m_txPsdus[15].txDuration,
1167 rtsCtsTxDurationThresh,
1168 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1169 }
1171 m_txPsdus[15].header.GetDuration(),
1173 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[15].txStart - txopStart) -
1174 m_txPsdus[15].txDuration)
1175 : sifs + m_txPsdus[16].txDuration + m_singleExchangeProtectionSurplus),
1177 ? "Duration/ID of the first QoS data frame does not cover the remaining TXOP"
1178 : "Duration/ID of the first QoS data frame must be set to remaining time to "
1179 "complete DATA+(Block)ACK sequence"));
1180
1181 // a Normal/Block Ack is then sent by STA1
1182 tEnd = m_txPsdus[15].txStart + m_txPsdus[15].txDuration;
1183 tStart = m_txPsdus[16].txStart;
1184
1185 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1186 tStart,
1187 ack << " in response to the first QoS data frame sent too early");
1188 NS_TEST_EXPECT_MSG_LT(tStart,
1189 tEnd + sifs + tolerance,
1190 ack << " in response to the first QoS data frame sent too late");
1192 (m_nonHt ? m_txPsdus[16].header.IsAck() : m_txPsdus[16].header.IsBlockAck()),
1193 true,
1194 "Expected a " << ack);
1195 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[16].header.GetAddr1(),
1196 apDev->GetMac()->GetAddress(),
1197 "Expected a " << ack << " sent to the AP");
1199 m_txPsdus[16].header.GetDuration(),
1200 RoundDurationId(m_txPsdus[15].header.GetDuration() - sifs - m_txPsdus[16].txDuration),
1201 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1202
1203 std::size_t idx = 16;
1204
1205 if (!m_singleRtsPerTxop)
1206 {
1207 // An RTS frame is sent by the AP to STA2
1208 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1209 ++idx;
1210 tStart = m_txPsdus[idx].txStart;
1211
1212 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second RTS frame sent too early");
1213 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second RTS frame sent too late");
1214 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsRts(), true, "Expected an RTS frame");
1216 m_txPsdus[idx].header.GetAddr1(),
1217 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
1218 "Expected an RTS frame sent by the AP to the second station");
1220 m_txPsdus[idx].header.GetDuration(),
1222 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1223 m_txPsdus[idx].txDuration)
1224 : sifs + m_txPsdus[idx + 1].txDuration + sifs + m_txPsdus[idx + 2].txDuration +
1225 sifs + m_txPsdus[idx + 3].txDuration + m_singleExchangeProtectionSurplus),
1227 ? "Duration/ID of the second RTS frame must cover the whole TXOP"
1228 : "Duration/ID of the second RTS frame must be set to remaining time to complete "
1229 "CTS+DATA+(Block)ACK sequence"));
1230
1231 // a CTS is sent by STA2 (which ignores the NAV)
1232 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1233 tStart = m_txPsdus[idx + 1].txStart;
1234
1235 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1236 tStart,
1237 "CTS in response to the second RTS frame sent too early");
1238 NS_TEST_EXPECT_MSG_LT(tStart,
1239 tEnd + sifs + tolerance,
1240 "CTS in response to the second RTS frame sent too late");
1241 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.IsCts(), true, "Expected a CTS");
1242 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1243 apDev->GetMac()->GetAddress(),
1244 "Expected a CTS frame sent to the AP");
1246 m_txPsdus[idx + 1].header.GetDuration(),
1247 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs -
1248 m_txPsdus[idx + 1].txDuration),
1249 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1250
1251 ++idx;
1252 }
1253
1254 // the AP sends a frame to STA2
1255 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1256 ++idx;
1257 tStart = m_txPsdus[idx].txStart;
1258
1259 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second QoS data frame sent too early");
1260 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second QoS data frame sent too late");
1261 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsQosData(), true, "Expected a QoS data frame");
1262 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetAddr1(),
1263 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
1264 "Expected a frame sent by the AP to the second station");
1266 {
1268 rtsCtsThreshold,
1269 "PSDU size expected to exceed length based RTS/CTS threshold");
1270 }
1271 else
1272 {
1273 NS_TEST_EXPECT_MSG_GT(m_txPsdus[idx].txDuration,
1274 rtsCtsTxDurationThresh,
1275 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1276 }
1278 m_txPsdus[idx].header.GetDuration(),
1280 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1281 m_txPsdus[idx].txDuration)
1282 : sifs + m_txPsdus[idx + 1].txDuration + m_singleExchangeProtectionSurplus),
1284 ? "Duration/ID of the second QoS data frame does not cover the remaining TXOP"
1285 : "Duration/ID of the second QoS data frame must be set to remaining time to "
1286 "complete DATA+(Block)ACK sequence"));
1287
1288 // a Normal/Block Ack is then sent by STA2
1289 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1290 tStart = m_txPsdus[idx + 1].txStart;
1291
1292 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1293 tStart,
1294 ack << " in response to the second QoS data frame sent too early");
1295 NS_TEST_EXPECT_MSG_LT(tStart,
1296 tEnd + sifs + tolerance,
1297 ack << " in response to the second QoS data frame sent too late");
1299 (m_nonHt ? m_txPsdus[idx + 1].header.IsAck() : m_txPsdus[idx + 1].header.IsBlockAck()),
1300 true,
1301 "Expected a " << ack);
1302 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1303 apDev->GetMac()->GetAddress(),
1304 "Expected a " << ack << " sent to the AP");
1306 m_txPsdus[idx + 1].header.GetDuration(),
1307 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs - m_txPsdus[idx + 1].txDuration),
1308 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1309 ++idx;
1310
1311 if (!m_singleRtsPerTxop)
1312 {
1313 // An RTS frame is sent by the AP to STA3
1314 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1315 ++idx;
1316 tStart = m_txPsdus[idx].txStart;
1317
1318 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third RTS frame sent too early");
1319 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third RTS frame sent too late");
1320 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsRts(), true, "Expected an RTS frame");
1322 m_txPsdus[idx].header.GetAddr1(),
1323 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
1324 "Expected an RTS frame sent by the AP to the third station");
1326 m_txPsdus[idx].header.GetDuration(),
1328 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1329 m_txPsdus[idx].txDuration)
1330 : sifs + m_txPsdus[idx + 1].txDuration + sifs + m_txPsdus[idx + 2].txDuration +
1331 sifs + m_txPsdus[idx + 3].txDuration + m_singleExchangeProtectionSurplus),
1333 ? "Duration/ID of the third RTS frame must cover the whole TXOP"
1334 : "Duration/ID of the third RTS frame must be set to remaining time to complete "
1335 "CTS+DATA+(Block)ACK sequence"));
1336
1337 // a CTS is sent by STA3 (which ignores the NAV)
1338 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1339 tStart = m_txPsdus[idx + 1].txStart;
1340
1341 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1342 tStart,
1343 "CTS in response to the third RTS frame sent too early");
1344 NS_TEST_EXPECT_MSG_LT(tStart,
1345 tEnd + sifs + tolerance,
1346 "CTS in response to the third RTS frame sent too late");
1347 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.IsCts(), true, "Expected a CTS");
1348 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1349 apDev->GetMac()->GetAddress(),
1350 "Expected a CTS frame sent to the AP");
1352 m_txPsdus[idx + 1].header.GetDuration(),
1353 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs -
1354 m_txPsdus[idx + 1].txDuration),
1355 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1356 ++idx;
1357 }
1358
1359 // the AP sends a frame to STA3
1360 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1361 ++idx;
1362 tStart = m_txPsdus[idx].txStart;
1363
1364 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third QoS data frame sent too early");
1365 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third QoS data frame sent too late");
1366 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsQosData(), true, "Expected a QoS data frame");
1367 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetAddr1(),
1368 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
1369 "Expected a frame sent by the AP to the third station");
1371 {
1373 rtsCtsThreshold,
1374 "PSDU size expected to exceed length based RTS/CTS threshold");
1375 }
1376 else
1377 {
1378 NS_TEST_EXPECT_MSG_GT(m_txPsdus[idx].txDuration,
1379 rtsCtsTxDurationThresh,
1380 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1381 }
1383 m_txPsdus[idx].header.GetDuration(),
1385 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1386 m_txPsdus[idx].txDuration)
1387 : sifs + m_txPsdus[idx + 1].txDuration + m_singleExchangeProtectionSurplus),
1389 ? "Duration/ID of the third QoS data frame does not cover the remaining TXOP"
1390 : "Duration/ID of the third QoS data frame must be set to remaining time to "
1391 "complete DATA+(Block)ACK sequence"));
1392
1393 // a Normal/Block Ack is then sent by STA3
1394 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1395 tStart = m_txPsdus[idx + 1].txStart;
1396
1397 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1398 tStart,
1399 ack << " in response to the third QoS data frame sent too early");
1400 NS_TEST_EXPECT_MSG_LT(tStart,
1401 tEnd + sifs + tolerance,
1402 ack << " in response to the third QoS data frame sent too late");
1404 (m_nonHt ? m_txPsdus[idx + 1].header.IsAck() : m_txPsdus[idx + 1].header.IsBlockAck()),
1405 true,
1406 "Expected a " << ack);
1407 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1408 apDev->GetMac()->GetAddress(),
1409 "Expected a " << ack << " sent to the AP");
1411 m_txPsdus[idx + 1].header.GetDuration(),
1412 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs - m_txPsdus[idx + 1].txDuration),
1413 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1414 ++idx;
1415
1416 // there is no time remaining for sending a CF-End frame if SingleRtsPerTxop is false. This is
1417 // verified by checking that 25 frames are transmitted (done at the beginning of this method)
1419 {
1420 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1421 ++idx;
1422 tStart = m_txPsdus[idx].txStart;
1423
1424 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
1425 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
1426 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsCfEnd(), true, "Expected a CF-End frame");
1427 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetDuration(),
1428 MicroSeconds(0),
1429 "Duration/ID must be set to 0 for CF-End frames");
1430 }
1431
1432 // Expected received packets:
1433 // - 4 DL packets (without RTS/CTS) if non-HT, 5 DL packets (without RTS/CTS) if HE
1434 // - 1 UL packet
1435 // - 3 DL packets (with RTS/CTS) if non-HT, 6 DL packets (with RTS/CTS) if HE
1436 NS_TEST_EXPECT_MSG_EQ(m_received, (m_nonHt ? 8 : 12), "Unexpected number of packets received");
1437}
1438
1439/**
1440 * @ingroup wifi-test
1441 * @ingroup tests
1442 *
1443 * @brief wifi TXOP Test Suite
1444 */
1446{
1447 public:
1449};
1450
1452 : TestSuite("wifi-txop", Type::UNIT)
1453{
1454 for (const auto nonHt : {true, false})
1455 {
1456 for (const auto pifsRecovery : {true, false})
1457 {
1458 for (const auto singleRtsPerTxop : {true, false})
1459 {
1460 for (const auto lengthBasedRtsCtsThresh : {true, false})
1461 {
1462 for (const auto protectedIfResponded : {true, false})
1463 {
1464 for (const auto protectSingleExchange : {false, true})
1465 {
1466 for (const auto& singleExchangeProtectionBuffer :
1467 {Time(), MicroSeconds(25) /* PIFS */})
1468 {
1469 if (!protectSingleExchange &&
1470 singleExchangeProtectionBuffer.IsStrictlyPositive())
1471 {
1472 continue;
1473 }
1475 .nonHt = nonHt,
1476 .pifsRecovery = pifsRecovery,
1477 .singleRtsPerTxop = singleRtsPerTxop,
1478 .lengthBasedRtsCtsThresh = lengthBasedRtsCtsThresh,
1479 .protectedIfResponded = protectedIfResponded,
1480 .protectSingleExchange = protectSingleExchange,
1481 .singleExchangeProtectionBuffer =
1482 singleExchangeProtectionBuffer,
1483 }),
1484 TestCase::Duration::QUICK);
1485 }
1486 }
1487 }
1488 }
1489 }
1490 }
1491 }
1492}
1493
1494static WifiTxopTestSuite g_wifiTxopTestSuite; ///< the test suite
Test TXOP rules.
void L7Receive(std::string context, Ptr< const Packet > p, const Address &addr)
Function to trace packets received by the server application.
bool m_pifsRecovery
whether PIFS recovery is used after failure of a non-initial frame
std::vector< PacketSocketAddress > m_dlSockets
packet socket address for DL traffic
NetDeviceContainer m_apDevices
container for AP's NetDevice
WifiTxopTest(const Params &params)
Constructor.
uint8_t m_staAifsn
AIFSN for STAs (AC BE)
void DoRun() override
Implementation to actually run this TestCase.
uint16_t m_received
number of packets received by the stations
TrafficDirection
Enumeration for traffic directions.
uint16_t m_nStations
number of stations
Ptr< ListErrorModel > m_apErrorModel
error model to install on the AP
uint32_t m_staCwMin
CWmin for STAs (AC BE)
Time m_singleExchangeProtectionSurplus
whether the NAV duration should be extended by a PIFS after the frame exchange when protection only c...
bool m_nonHt
use 802.11a standard if true, 802.11ax standard otherwise
std::size_t m_payloadSizeRtsOff
size in bytes of packets not protected by RTS
WifiMode m_mode
wifi mode used to transmit data frames
Time m_apTxopLimit
TXOP limit for AP (AC BE)
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
Time m_startTime
time when data frame exchanges start
std::vector< PacketSocketAddress > m_ulSockets
packet socket address for UL traffic
bool m_staCorrupted
whether the frame to be corrupted by the STA has been corrupted
Ptr< PacketSocketClient > GetApplication(TrafficDirection dir, std::size_t staId, std::size_t count, std::size_t pktSize) const
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when PHY receives a PSDU to transmit.
bool m_singleRtsPerTxop
whether protection mechanism is used no more than once per TXOP
bool m_protectedIfResponded
whether a station is assumed to be protected if replied to a frame requiring acknowledgment
NetDeviceContainer m_staDevices
container for stations' NetDevices
bool m_apCorrupted
whether the frame to be corrupted by the AP has been corrupted
std::size_t m_payloadSizeRtsOn
size in bytes of packets protected by RTS
uint32_t m_staCwMax
CWmax for STAs (AC BE)
bool m_lengthBasedRtsCtsThresh
if true, use length based RTS/CTS threshold; if false, use TX duration based RTS/CTS threshold
Time m_staTxopLimit
TXOP limit for STAs (AC BE)
bool m_protectSingleExchange
whether the Duration/ID field in frames establishing protection only covers the immediate frame excha...
Ptr< ListErrorModel > m_staErrorModel
error model to install on a STA
void CheckResults()
Check correctness of transmitted frames.
wifi TXOP Test Suite
a polymophic address class
Definition address.h:90
std::map< AcIndex, std::vector< uint64_t > > UintAccessParamsMap
ACI-indexed map of access parameters of type unsigned integer (CWmin, CWmax and AIFSN)
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition boolean.h:26
PHY entity for HE (11ax)
Definition he-phy.h:58
Provide a list of Packet uids to corrupt.
void SetList(const std::list< uint64_t > &packetlist)
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition node.cc:153
static Iterator Begin()
Definition node-list.cc:226
static Iterator End()
Definition node-list.cc:233
PHY entity for OFDM (11a)
Definition ofdm-phy.h:50
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
AttributeValue implementation for Time.
Definition nstime.h:1432
bool LookupAttributeByName(std::string name, AttributeInformation *info, bool permissive=false) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition type-id.cc:968
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
Implements the IEEE 802.11 MAC header.
create MAC layers for a ns3::WifiNetDevice.
void SetSsid(Ssid ssid)
Definition wifi-mac.cc:527
represent a single transmission mode
Definition wifi-mode.h:40
uint64_t GetDataRate(MHz_u channelWidth, Time guardInterval, uint8_t nss) const
Definition wifi-mode.cc:110
AttributeValue implementation for WifiMode.
Definition wifi-mode.h:246
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1563
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition wifi-phy.cc:1556
static TypeId GetTypeId()
Get the type ID.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:886
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:970
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#define NS_TEST_EXPECT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to limit and report if not.
Definition test.h:986
#define NS_TEST_ASSERT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report and abort if not.
Definition test.h:134
#define NS_TEST_EXPECT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report if not.
Definition test.h:820
#define NS_TEST_EXPECT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report if not.
Definition test.h:780
#define NS_TEST_EXPECT_MSG_GT(actual, limit, msg)
Test that an actual value is greater than a limit and report if not.
Definition test.h:946
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition test.h:241
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:554
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211ax
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ AC_BE
Best Effort.
Definition qos-utils.h:64
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
Time GetEstimatedAckTxTime(const WifiTxVector &txVector)
static constexpr uint8_t SINGLE_LINK_OP_ID
Link ID for single link operations (helps tracking places where correct link ID is to be used to supp...
Definition wifi-utils.h:280
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition wifi-mode.h:24
STL namespace.
mac
Definition third.py:81
wifi
Definition third.py:84
wifiApNode
Definition third.py:75
mobility
Definition third.py:92
wifiStaNodes
Definition third.py:73
Information about transmitted frames.
WifiMacHeader header
Frame MAC header.
WifiTxVector txVector
TX vector used to transmit the frame.
Time txStart
Frame start TX time.
Time txDuration
Frame TX duration.
uint32_t size
PSDU size in bytes.
Parameters for this test.
bool lengthBasedRtsCtsThresh
if true, use length based RTS/CTS threshold; if false, use TX duration based RTS/CTS threshold
bool protectSingleExchange
whether the Duration/ID field in frames establishing protection only covers the immediate frame excha...
bool protectedIfResponded
whether a station is assumed to be protected if replied to a frame requiring acknowledgment
bool singleRtsPerTxop
whether protection mechanism is used no more than once per TXOP
bool nonHt
use 802.11a standard if true, 802.11ax standard otherwise
Time singleExchangeProtectionBuffer
whether the NAV duration should be extended by a PIFS after the frame exchange when protection only c...
bool pifsRecovery
whether PIFS recovery is used after failure of a non-initial frame
Attribute implementation.
Definition type-id.h:86
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition type-id.h:96
std::string dir
uint32_t pktSize
packet size used for the simulation (in bytes)
static WifiTxopTestSuite g_wifiTxopTestSuite
the test suite