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-ns3-constants.h"
31#include "ns3/wifi-ppdu.h"
32#include "ns3/wifi-psdu.h"
33
34using namespace ns3;
35
36NS_LOG_COMPONENT_DEFINE("WifiTxopTest");
37
38/**
39 * @ingroup wifi-test
40 * @ingroup tests
41 *
42 * @brief Test TXOP rules
43 *
44 * A BSS consisting of an AP and 3 non-AP STAs is considered in this test. Both non-HT (802.11a)
45 * and HE devices are tested. Two TXOPs are simulated in this test:
46 * - In the first TXOP, the AP sends a QoS data frame to each of the three STAs. The Ack in
47 * response to the initial frame is corrupted, hence the AP terminates the TXOP and tries again
48 * when a new TXOP is gained. In the new TXOP, the initial frame sent to STA 1 is successfully
49 * received, while the second frame to STA 2 is corrupted. It is checked that the AP performs
50 * PIFS recovery or invokes backoff depending on the value of the PifsRecovery attribute. All
51 * QoS data frames transmitted have a length/duration that does not exceed the length/duration
52 * based RTS/CTS threshold, hence RTS/CTS is never used. After that a QoS data frame has been
53 * sent to every STA, the AP sends another QoS data frame to one of them; the size/duration of
54 * this frame exceeds the threshold, but, given that the STA has already sent a response to the
55 * AP in this TXOP, RTS/CTS is only used if the ProtectedIfResponded is false.
56 * - In the second TXOP, the AP sends a QoS data frame, in case of non-HT devices, or an A-MPDU
57 * consisting of 2 MPDUs, in case of HE devices, to each of the three STAs. All PSDUs transmitted
58 * have a length/duration that exceeds the length/duration based RTS/CTS threshold, hence RTS/CTS
59 * is used to protect every PSDU, unless the SingleRtsPerTxop attribute is set to true, in which
60 * case only the initial frame in the TXOP is protected by RTS/CTS.
61 */
62class WifiTxopTest : public TestCase
63{
64 public:
65 /// Parameters for this test
66 struct Params
67 {
68 bool nonHt; //!< use 802.11a standard if true, 802.11ax standard otherwise
69 bool pifsRecovery; //!< whether PIFS recovery is used after failure of a non-initial frame
70 bool singleRtsPerTxop; //!< whether protection mechanism is used no more than once per TXOP
71 bool lengthBasedRtsCtsThresh; //!< if true, use length based RTS/CTS threshold; if false,
72 //!< use TX duration based RTS/CTS threshold
73 bool protectedIfResponded; //!< whether a station is assumed to be protected if replied to
74 //!< a frame requiring acknowledgment
75 bool protectSingleExchange; //!< whether the Duration/ID field in frames establishing
76 //!< protection only covers the immediate frame exchange instead
77 //!< of rest of the TXOP limit
78 Time singleExchangeProtectionBuffer; //!< whether the NAV duration should be extended by a
79 //!< PIFS after the frame exchange when protection only
80 //!< covers the immediate frame exchange instead of
81 //!< rest of the TXOP limit
82 };
83
84 /**
85 * Constructor
86 * @param params parameters for the Wi-Fi TXOP test
87 */
88 WifiTxopTest(const Params& params);
89
90 /**
91 * Function to trace packets received by the server application
92 * @param context the context
93 * @param p the packet
94 * @param addr the address
95 */
96 void L7Receive(std::string context, Ptr<const Packet> p, const Address& addr);
97
98 /**
99 * Callback invoked when PHY receives a PSDU to transmit
100 * @param context the context
101 * @param psduMap the PSDU map
102 * @param txVector the TX vector
103 * @param txPowerW the tx power in Watts
104 */
105 void Transmit(std::string context,
106 WifiConstPsduMap psduMap,
107 WifiTxVector txVector,
108 double txPowerW);
109
110 /**
111 * Check correctness of transmitted frames
112 */
113 void CheckResults();
114
115 private:
116 void DoRun() override;
117
118 /// Enumeration for traffic directions
119 enum TrafficDirection : uint8_t
120 {
123 };
124
125 /**
126 * @param dir the traffic direction (downlink/uplink)
127 * @param staId the index (starting at 0) of the non-AP STA generating/receiving packets
128 * @param count the number of packets to generate
129 * @param pktSize the size of the packets to generate
130 * @return an application generating the given number packets of the given size from/to the
131 * AP to/from the given non-AP STA
132 */
134 std::size_t staId,
135 std::size_t count,
136 std::size_t pktSize) const;
137
138 /// Information about transmitted frames
140 {
141 Time txStart; ///< Frame start TX time
142 Time txDuration; ///< Frame TX duration
143 uint32_t size; ///< PSDU size in bytes
144 WifiMacHeader header; ///< Frame MAC header
145 WifiTxVector txVector; ///< TX vector used to transmit the frame
146 };
147
148 uint16_t m_nStations; ///< number of stations
149 NetDeviceContainer m_staDevices; ///< container for stations' NetDevices
150 NetDeviceContainer m_apDevices; ///< container for AP's NetDevice
151 std::vector<FrameInfo> m_txPsdus; ///< transmitted PSDUs
152 Time m_apTxopLimit; ///< TXOP limit for AP (AC BE)
153 uint8_t m_staAifsn; ///< AIFSN for STAs (AC BE)
154 uint32_t m_staCwMin; ///< CWmin for STAs (AC BE)
155 uint32_t m_staCwMax; ///< CWmax for STAs (AC BE)
156 Time m_staTxopLimit; ///< TXOP limit for STAs (AC BE)
157 uint16_t m_received; ///< number of packets received by the stations
158 bool m_nonHt; ///< @copydoc Params::nonHt
159 std::size_t m_payloadSizeRtsOn; ///< size in bytes of packets protected by RTS
160 std::size_t m_payloadSizeRtsOff; ///< size in bytes of packets not protected by RTS
161 Time m_startTime; ///< time when data frame exchanges start
162 WifiMode m_mode; ///< wifi mode used to transmit data frames
163 bool m_pifsRecovery; ///< @copydoc Params::pifsRecovery
164 bool m_singleRtsPerTxop; ///< @copydoc Params::singleRtsPerTxop
165 bool m_lengthBasedRtsCtsThresh; ///< @copydoc Params::lengthBasedRtsCtsThresh
166 bool m_protectedIfResponded; ///< @copydoc Params::protectedIfResponded
167 bool m_protectSingleExchange; ///< @copydoc Params::protectSingleExchange
168 Time m_singleExchangeProtectionSurplus; ///< @copydoc Params::singleExchangeProtectionBuffer
169 Ptr<ListErrorModel> m_apErrorModel; ///< error model to install on the AP
170 Ptr<ListErrorModel> m_staErrorModel; ///< error model to install on a STA
171 bool m_apCorrupted; ///< whether the frame to be corrupted by the AP has been corrupted
172 bool m_staCorrupted; ///< whether the frame to be corrupted by the STA has been corrupted
173 std::vector<PacketSocketAddress> m_dlSockets; ///< packet socket address for DL traffic
174 std::vector<PacketSocketAddress> m_ulSockets; ///< packet socket address for UL traffic
175};
176
178 : TestCase("Check correct operation within TXOPs with parameters: nonHt=" +
179 std::to_string(params.nonHt) +
180 " pifsRecovery=" + std::to_string(params.pifsRecovery) +
181 " singleRtsPerTxop=" + std::to_string(params.singleRtsPerTxop) +
182 " lengthBasedRtsCtsThresh=" + std::to_string(params.lengthBasedRtsCtsThresh) +
183 " protectedIfResponded=" + std::to_string(params.protectedIfResponded) +
184 " protectSingleExchange=" + std::to_string(params.protectSingleExchange) +
185 " singleExchangeProtectionBuffer=" +
186 std::to_string(params.singleExchangeProtectionBuffer.GetMicroSeconds()) + "us"),
187 m_nStations(3),
189 m_staAifsn(4),
190 m_staCwMin(63),
191 m_staCwMax(511),
193 m_received(0),
194 m_nonHt(params.nonHt),
195 m_payloadSizeRtsOn(m_nonHt ? 2000 : 540),
197 m_startTime(MilliSeconds(m_nonHt ? 410 : 520)),
198 m_mode(m_nonHt ? OfdmPhy::GetOfdmRate12Mbps() : HePhy::GetHeMcs0()),
199 m_pifsRecovery(params.pifsRecovery),
200 m_singleRtsPerTxop(params.singleRtsPerTxop),
201 m_lengthBasedRtsCtsThresh(params.lengthBasedRtsCtsThresh),
202 m_protectedIfResponded(params.protectedIfResponded),
203 m_protectSingleExchange(params.protectSingleExchange),
204 m_singleExchangeProtectionSurplus(params.singleExchangeProtectionBuffer),
207 m_apCorrupted(false),
208 m_staCorrupted(false)
209{
210}
211
212void
213WifiTxopTest::L7Receive(std::string context, Ptr<const Packet> p, const Address& addr)
214{
215 if (p->GetSize() >= m_payloadSizeRtsOff)
216 {
217 m_received++;
218 }
219}
220
221void
222WifiTxopTest::Transmit(std::string context,
223 WifiConstPsduMap psduMap,
224 WifiTxVector txVector,
225 double txPowerW)
226{
227 bool corrupted{false};
228
229 // The AP does not correctly receive the Ack sent in response to the QoS
230 // data frame sent to the first station
231 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
232 hdr.IsAck() && !m_apCorrupted && !m_txPsdus.empty() &&
233 m_txPsdus.back().header.IsQosData() &&
234 m_txPsdus.back().header.GetAddr1() == m_staDevices.Get(0)->GetAddress())
235 {
236 corrupted = m_apCorrupted = true;
237 m_apErrorModel->SetList({psduMap.begin()->second->GetPacket()->GetUid()});
238 }
239
240 // The second station does not correctly receive the first QoS data frame sent by the AP
241 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
242 !m_txPsdus.empty() && hdr.IsQosData() &&
243 hdr.GetAddr1() == m_staDevices.Get(1)->GetAddress())
244 {
245 if (!m_staCorrupted)
246 {
247 corrupted = m_staCorrupted = true;
248 }
249 if (corrupted)
250 {
251 m_staErrorModel->SetList({psduMap.begin()->second->GetPacket()->GetUid()});
252 }
253 else
254 {
255 m_staErrorModel->SetList({});
256 }
257 }
258
259 // When the AP sends the first frame to the third station (which is not protected by RTS/CTS),
260 // we generate another frame addressed to the second station whose size/duration exceeds the
261 // threshold; however, RTS is not used because the second station has already responded to
262 // another frame in the same TXOP
263 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
264 hdr.IsQosData() && hdr.GetAddr1() == m_staDevices.Get(2)->GetAddress() &&
265 hdr.GetSequenceNumber() == (m_nonHt ? 0 : 1))
266 {
267 m_apDevices.Get(0)->GetNode()->AddApplication(
269 }
270
271 // Log all transmitted frames that are not beacon frames and have been transmitted
272 // after the start time (so as to skip association requests/responses)
273 if (!psduMap.begin()->second->GetHeader(0).IsBeacon() && Simulator::Now() >= m_startTime)
274 {
275 m_txPsdus.push_back({Simulator::Now(),
277 psduMap[SU_STA_ID]->GetSize(),
278 psduMap[SU_STA_ID]->GetHeader(0),
279 txVector});
280 }
281
282 // Print all the transmitted frames if the test is executed through test-runner
283 NS_LOG_INFO(psduMap.begin()->second->GetHeader(0).GetTypeString()
284 << " seq " << psduMap.begin()->second->GetHeader(0).GetSequenceNumber() << " to "
285 << psduMap.begin()->second->GetAddr1() << " TX duration "
287 << " duration/ID " << psduMap.begin()->second->GetHeader(0).GetDuration()
288 << (corrupted ? " CORRUPTED" : "") << std::endl);
289}
290
291void
293{
294 // LogComponentEnable("WifiTxopTest", LOG_LEVEL_ALL);
295 NS_LOG_FUNCTION(this);
296
299 int64_t streamNumber = 100;
300
301 NodeContainer wifiApNode;
302 wifiApNode.Create(1);
303
304 NodeContainer wifiStaNodes;
305 wifiStaNodes.Create(m_nStations);
306
307 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
309 spectrumChannel->AddPropagationLossModel(lossModel);
311 spectrumChannel->SetPropagationDelayModel(delayModel);
312
314 phy.SetChannel(spectrumChannel);
315 // use default 20 MHz channel in 5 GHz band
316 phy.Set("ChannelSettings", StringValue("{0, 20, BAND_5GHZ, 0}"));
317
318 Config::SetDefault("ns3::QosFrameExchangeManager::PifsRecovery", BooleanValue(m_pifsRecovery));
319 Config::SetDefault("ns3::QosFrameExchangeManager::ProtectSingleExchange",
321 Config::SetDefault("ns3::QosFrameExchangeManager::SingleExchangeProtectionSurplus",
323 Config::SetDefault("ns3::WifiDefaultProtectionManager::SingleRtsPerTxop",
326 {
327 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold",
329 }
330 else
331 {
332 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsTxDurationThresh",
333 TimeValue(Seconds(m_payloadSizeRtsOn * (m_nonHt ? 1 : 2) * 8.0 /
334 m_mode.GetDataRate(MHz_u{20}))));
335 }
336 Config::SetDefault("ns3::FrameExchangeManager::ProtectedIfResponded",
338
339 WifiHelper wifi;
341 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
342 "DataMode",
344 "ControlMode",
345 StringValue("OfdmRate6Mbps"));
346
347 WifiMacHelper mac;
348 mac.SetType("ns3::StaWifiMac",
349 "QosSupported",
350 BooleanValue(true),
351 "Ssid",
352 SsidValue(Ssid("non-existent-ssid")));
353
354 m_staDevices = wifi.Install(phy, mac, wifiStaNodes);
355 streamNumber += WifiHelper::AssignStreams(m_staDevices, streamNumber);
356
357 mac.SetType(
358 "ns3::ApWifiMac",
359 "QosSupported",
360 BooleanValue(true),
361 "Ssid",
362 SsidValue(Ssid("wifi-txop-ssid")),
363 "BeaconInterval",
365 "EnableBeaconJitter",
366 BooleanValue(false),
367 "AifsnsForSta",
368 StringValue(std::string("BE ") + std::to_string(m_staAifsn)),
369 "CwMinsForSta",
371 ApWifiMac::UintAccessParamsMap{{AC_BE, std::vector<uint64_t>{m_staCwMin}}}),
372 "CwMaxsForSta",
373 StringValue(std::string("BE ") + std::to_string(m_staCwMax)),
374 "TxopLimitsForSta",
375 StringValue(std::string("BE ") + std::to_string(m_staTxopLimit.GetMicroSeconds()) + "us"));
376
377 mac.SetEdca(AC_BE, "TxopLimits", AttributeContainerValue<TimeValue>(std::list{m_apTxopLimit}));
378
379 m_apDevices = wifi.Install(phy, mac, wifiApNode);
380 streamNumber += WifiHelper::AssignStreams(m_apDevices, streamNumber);
381
382 // schedule association requests at different times. One station's SSID is
383 // set to the correct value before initialization, so that such a station
384 // starts the scanning procedure by looking for the correct SSID
386 dev->GetMac()->SetSsid(Ssid("wifi-txop-ssid"));
387
388 for (uint16_t i = 1; i < m_nStations; i++)
389 {
393 dev->GetMac(),
394 Ssid("wifi-txop-ssid"));
395 }
396
397 MobilityHelper mobility;
399
400 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
401 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
402 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
403 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
404 mobility.SetPositionAllocator(positionAlloc);
405
406 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
407 mobility.Install(wifiApNode);
408 mobility.Install(wifiStaNodes);
409
410 PacketSocketHelper packetSocket;
411 packetSocket.Install(wifiApNode);
412 packetSocket.Install(wifiStaNodes);
413
414 // install a packet socket server on all nodes
415 for (auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); ++nodeIt)
416 {
417 PacketSocketAddress srvAddr;
418 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
419 NS_TEST_ASSERT_MSG_NE(device, nullptr, "Expected a WifiNetDevice");
420 srvAddr.SetSingleDevice(device->GetIfIndex());
421 srvAddr.SetProtocol(1);
422
423 auto server = CreateObject<PacketSocketServer>();
424 server->SetLocal(srvAddr);
425 (*nodeIt)->AddApplication(server);
426 server->SetStartTime(Time{0}); // now
427 server->SetStopTime(Seconds(1));
428 }
429
430 // set DL and UL packet sockets
431 for (uint16_t i = 0; i < m_nStations; ++i)
432 {
433 m_dlSockets.emplace_back();
434 m_dlSockets.back().SetSingleDevice(m_apDevices.Get(0)->GetIfIndex());
435 m_dlSockets.back().SetPhysicalAddress(m_staDevices.Get(i)->GetAddress());
436 m_dlSockets.back().SetProtocol(1);
437
438 m_ulSockets.emplace_back();
439 m_ulSockets.back().SetSingleDevice(m_staDevices.Get(i)->GetIfIndex());
440 m_ulSockets.back().SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
441 m_ulSockets.back().SetProtocol(1);
442 }
443
444 // DL frames
445 for (uint16_t i = 0; i < m_nStations; i++)
446 {
447 if (!m_nonHt)
448 {
449 // Send one QoS data frame to establish Block Ack agreement (packet size is such that
450 // this packet is not counted as a received packet)
453 wifiApNode.Get(0),
455 }
456
457 // Send one QoS data frame (not protected by RTS/CTS) to each station
460 wifiApNode.Get(0),
462
463 // Send one QoS data frame (protected by RTS/CTS) to each station
466 wifiApNode.Get(0),
468 }
469
470 // install the error model on the AP
472 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(m_apErrorModel);
473
474 // install the error model on the second station
476 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(m_staErrorModel);
477
478 // UL Traffic (the first station sends one frame to the AP)
479 {
480 if (!m_nonHt)
481 {
482 // Send one QoS data frame to establish Block Ack agreement (packet size is such that
483 // this packet is not counted as a received packet)
486 wifiStaNodes.Get(0),
488 }
489
492 wifiStaNodes.Get(0),
494 }
495
496 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx",
498 // Trace PSDUs passed to the PHY on all devices
499 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
501
504
505 CheckResults();
506
508}
509
512 std::size_t staId,
513 std::size_t count,
514 std::size_t pktSize) const
515{
516 auto client = CreateObject<PacketSocketClient>();
517 client->SetAttribute("PacketSize", UintegerValue(pktSize));
518 client->SetAttribute("MaxPackets", UintegerValue(count));
519 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
520 client->SetRemote(dir == DOWNLINK ? m_dlSockets.at(staId) : m_ulSockets.at(staId));
521 client->SetStartTime(Time{0}); // now
522 client->SetStopTime(Seconds(1));
523
524 return client;
525}
526
527void
529{
530 // check that STAs used the access parameters advertised by the AP
531 for (uint32_t i = 0; i < m_staDevices.GetN(); ++i)
532 {
533 auto staEdca = DynamicCast<WifiNetDevice>(m_staDevices.Get(i))->GetMac()->GetQosTxop(AC_BE);
534 NS_TEST_EXPECT_MSG_EQ(staEdca->GetAifsn(SINGLE_LINK_OP_ID),
536 "Unexpected AIFSN for STA " << i);
537 NS_TEST_EXPECT_MSG_EQ(staEdca->GetMinCw(SINGLE_LINK_OP_ID),
539 "Unexpected CWmin for STA " << i);
540 NS_TEST_EXPECT_MSG_EQ(staEdca->GetMaxCw(SINGLE_LINK_OP_ID),
542 "Unexpected CWmax for STA " << i);
543 NS_TEST_EXPECT_MSG_EQ(staEdca->GetTxopLimit(SINGLE_LINK_OP_ID),
545 "Unexpected TXOP limit for STA " << i);
546 }
547
548 const auto apDev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
549
550 NS_TEST_EXPECT_MSG_EQ(apDev->GetMac()->GetQosTxop(AC_BE)->GetTxopLimit(SINGLE_LINK_OP_ID),
552 "Unexpected TXOP limit for AP");
553
554 const auto aifsn = apDev->GetMac()->GetQosTxop(AC_BE)->GetAifsn(SINGLE_LINK_OP_ID);
555 const auto cwMin = apDev->GetMac()->GetQosTxop(AC_BE)->GetMinCw(SINGLE_LINK_OP_ID);
556 Time tEnd; // TX end for a frame
557 Time tStart; // TX start for the next frame
558 Time txopStart; // TXOP start time
559 Time tolerance = NanoSeconds(50); // due to propagation delay
560 Time sifs = apDev->GetPhy()->GetSifs();
561 Time slot = apDev->GetPhy()->GetSlot();
562 Time navEnd;
565 const uint32_t rtsCtsThreshold = DynamicCast<const UintegerValue>(info.initialValue)->Get();
566 WifiRemoteStationManager::GetTypeId().LookupAttributeByName("RtsCtsTxDurationThresh", &info);
567 const Time rtsCtsTxDurationThresh = DynamicCast<const TimeValue>(info.initialValue)->Get();
568
569 // lambda to round Duration/ID (in microseconds) up to the next higher integer
570 auto RoundDurationId = [](Time t) {
571 return MicroSeconds(ceil(static_cast<double>(t.GetNanoSeconds()) / 1000));
572 };
573
574 /*
575 * Verify the different behavior followed when an initial/non-initial frame of a TXOP
576 * fails. Also, verify that a CF-end frame is sent if enough time remains in the TXOP.
577 * The destination of failed frames is put in square brackets below.
578 *
579 * |--NAV----till end TXOP-------->|
580 * | |---NAV--till end TXOP--->|
581 * | | |-----------------------------NAV--------------------------------->|
582 * | | | |----------------------------NAV---------------------------->|
583 * | | | | |---------------------------NAV----------------------->|
584 * | | | | | |----------------NAV------------------>|
585 * | | | | | | |-------------NAV--------------->|
586 * | | | | | Ack | | |-----------NAV----------->|
587 * Start| | Start| | | Timeout | | | |--------NAV-------->|
588 * TXOP | | TXOP | | | |-PIFS-> | | | | |-----NAV----->|
589 * | | | back | | | | |- or -> | | | | | |--NAV-->|
590 * ┌───┐ ┌───┐-off->┌───┐ ┌───┐ ┌───┐ |-back->┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌─────┐
591 * │QoS│ │Ack│ │QoS│ │Ack│ │QoS│ |-off ->│QoS│ │Ack│ │QoS│ │Ack│ │QoS│ │Ack│ │CFend│
592 * ───┴───┴─┴───┴──────┴───┴─┴───┴─┴───┴───────────┴───┴─┴───┴─┴───┴─┴───┴─┴───┴─┴───┴─┴─────┴─
593 * TA: AP STA1 AP STA1 AP AP STA2 AP STA3 AP STA2 AP
594 * RA: STA1 [AP] STA1 AP [STA2] STA2 AP STA3 AP STA2 AP all
595 *
596 * NOTE: If ProtectedIfResponded is false, the last QoS data frame is protected by RTS/CTS
597 * NOTE: If ProtectSingleExchange is true, CF-END frames are not transmitted
598 * and NAV ends once DATA+Ack is completed
599 */
600
601 // We expect 25 frames to be transmitted if SingleRtsPerTxop is false and 22 frames (2 RTS
602 // less, 2 CTS less, 1 more CF-End). If ProtectedIfResponded is false, there are 2 frames
603 // (an RTS and a CTS) more. If ProtectSingleExchange is true, there are 2 (if
604 // SingleRtsPerTxop is false) or 3 (if SingleRtsPerTxop is true) less frames (CF-END)
606 m_txPsdus.size(),
608 ? 21U + (m_protectedIfResponded ? 0U : 2U) + (m_protectSingleExchange ? 0U : 3U)
609 : 25U + (m_protectedIfResponded ? 0U : 2U) + (m_protectSingleExchange ? 0U : 2U)),
610 "Unexpected number of transmitted frames");
611
612 // the first frame sent after 400ms is a QoS data frame sent by the AP to STA1 without RTS/CTS
613 txopStart = m_txPsdus[0].txStart;
614
615 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].header.IsQosData(), true, "Expected a QoS data frame");
616 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].header.GetAddr1(),
617 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
618 "Expected a frame sent by the AP to the first station");
620 {
622 rtsCtsThreshold,
623 "PSDU size expected not to exceed length based RTS/CTS threshold");
624 }
625 else
626 {
628 m_txPsdus[0].txDuration,
629 rtsCtsTxDurationThresh,
630 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
631 }
633 m_txPsdus[0].header.GetDuration(),
635 ? RoundDurationId(m_apTxopLimit - m_txPsdus[0].txDuration)
636 : sifs + m_txPsdus[1].txDuration + m_singleExchangeProtectionSurplus),
638 ? "Duration/ID of the first frame must cover the whole TXOP"
639 : "Duration/ID of the first frame must be set to remaining time to "
640 "complete DATA+ACK sequence"));
641
642 // a Normal Ack is sent by STA1
643 tEnd = m_txPsdus[0].txStart + m_txPsdus[0].txDuration;
644 tStart = m_txPsdus[1].txStart;
645
646 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
648 tEnd + sifs + tolerance,
649 "Ack in response to the first frame sent too late");
650 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[1].header.IsAck(), true, "Expected a Normal Ack");
651 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[1].header.GetAddr1(),
652 apDev->GetMac()->GetAddress(),
653 "Expected a Normal Ack sent to the AP");
655 m_txPsdus[1].header.GetDuration(),
656 RoundDurationId(m_txPsdus[0].header.GetDuration() - sifs - m_txPsdus[1].txDuration),
657 "Duration/ID of the Ack must be derived from that of the first frame");
658
659 // the AP receives a corrupted Ack in response to the frame it sent, which is the initial
660 // frame of a TXOP. Hence, the TXOP is terminated and the AP retransmits the frame after
661 // waiting for EIFS - DIFS + AIFS + backoff (see section 10.3.2.3.7 of 802.11-2020)
662 txopStart = m_txPsdus[2].txStart;
663
664 tEnd = m_txPsdus[1].txStart + m_txPsdus[1].txDuration;
665 tStart = m_txPsdus[2].txStart;
666
667 auto apPhy = apDev->GetPhy(SINGLE_LINK_OP_ID);
668 auto eifsNoDifs = apPhy->GetSifs() + GetEstimatedAckTxTime(m_txPsdus[1].txVector);
669
671 tStart - tEnd,
672 eifsNoDifs + sifs + aifsn * slot,
673 "Less than AIFS elapsed between AckTimeout and the next TXOP start");
675 tStart - tEnd,
676 eifsNoDifs + sifs + aifsn * slot + (2 * (cwMin + 1) - 1) * slot,
677 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
678 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].header.IsQosData(),
679 true,
680 "Expected to retransmit a QoS data frame");
681 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].header.GetAddr1(),
682 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
683 "Expected to retransmit a frame to the first station");
685 {
687 rtsCtsThreshold,
688 "PSDU size expected not to exceed length based RTS/CTS threshold");
689 }
690 else
691 {
693 m_txPsdus[2].txDuration,
694 rtsCtsTxDurationThresh,
695 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
696 }
698 m_txPsdus[2].header.GetDuration(),
700 ? RoundDurationId(m_apTxopLimit - m_txPsdus[2].txDuration)
701 : sifs + m_txPsdus[3].txDuration + m_singleExchangeProtectionSurplus),
703 ? "Duration/ID of the retransmitted frame must cover the whole TXOP"
704 : "Duration/ID of the retransmitted frame must be set to remaining time to "
705 "complete DATA+ACK sequence"));
706
707 // a Normal Ack is then sent by STA1
708 tEnd = m_txPsdus[2].txStart + m_txPsdus[2].txDuration;
709 tStart = m_txPsdus[3].txStart;
710
711 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
713 tEnd + sifs + tolerance,
714 "Ack in response to the first frame sent too late");
715 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[3].header.IsAck(), true, "Expected a Normal Ack");
716 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[3].header.GetAddr1(),
717 apDev->GetMac()->GetAddress(),
718 "Expected a Normal Ack sent to the AP");
720 m_txPsdus[3].header.GetDuration(),
721 RoundDurationId(m_txPsdus[2].header.GetDuration() - sifs - m_txPsdus[3].txDuration),
722 "Duration/ID of the Ack must be derived from that of the previous frame");
723
724 // the AP sends a frame to STA2
725 tEnd = m_txPsdus[3].txStart + m_txPsdus[3].txDuration;
726 tStart = m_txPsdus[4].txStart;
727
728 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second frame sent too early");
729 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second frame sent too late");
730 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.IsQosData(), true, "Expected a QoS data frame");
731 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.GetAddr1(),
732 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
733 "Expected a frame sent by the AP to the second station");
735 {
737 rtsCtsThreshold,
738 "PSDU size expected not to exceed length based RTS/CTS threshold");
739 }
740 else
741 {
743 m_txPsdus[4].txDuration,
744 rtsCtsTxDurationThresh,
745 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
746 }
747 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.GetDuration(),
749 ? RoundDurationId(m_apTxopLimit -
750 (m_txPsdus[4].txStart - txopStart) -
751 m_txPsdus[4].txDuration)
752 : sifs +
753 m_txPsdus[6].txDuration + m_singleExchangeProtectionSurplus /* ACK is 2 frames later since this DATA is first corrupted */),
755 ? "Duration/ID of the second frame does not cover the remaining TXOP"
756 : "Duration/ID of the second frame must be set to remaining time to "
757 "complete DATA+ACK sequence"));
758
759 // STA2 receives a corrupted frame and hence it does not send the Ack. When the AckTimeout
760 // expires, the AP performs PIFS recovery or invoke backoff, without terminating the TXOP,
761 // because a non-initial frame of the TXOP failed
762 auto apStationManager = apDev->GetRemoteStationManager(SINGLE_LINK_OP_ID);
763 auto staAddress = DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress();
764 auto ackTxVector = apStationManager->GetAckTxVector(staAddress, m_txPsdus[4].txVector);
765 tEnd = m_txPsdus[4].txStart + m_txPsdus[4].txDuration + sifs + slot +
766 WifiPhy::CalculatePhyPreambleAndHeaderDuration(ackTxVector); // AckTimeout
767 tStart = m_txPsdus[5].txStart;
768
769 if (m_pifsRecovery)
770 {
771 NS_TEST_EXPECT_MSG_EQ(tEnd + sifs + slot,
772 tStart,
773 "Second frame must have been sent after a PIFS");
774 }
775 else
776 {
778 tStart - tEnd,
779 sifs + aifsn * slot,
780 "Less than AIFS elapsed between AckTimeout and the next transmission");
782 tStart - tEnd,
783 sifs + aifsn * slot + (2 * (cwMin + 1) - 1) * slot,
784 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
785 }
786 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[5].header.IsQosData(), true, "Expected a QoS data frame");
787 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[5].header.GetAddr1(),
788 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
789 "Expected a frame sent by the AP to the second station");
791 {
793 rtsCtsThreshold,
794 "PSDU size expected not to exceed length based RTS/CTS threshold");
795 }
796 else
797 {
799 m_txPsdus[5].txDuration,
800 rtsCtsTxDurationThresh,
801 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
802 }
804 m_txPsdus[5].header.GetDuration(),
806 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[5].txStart - txopStart) -
807 m_txPsdus[5].txDuration)
808 : sifs + m_txPsdus[6].txDuration + m_singleExchangeProtectionSurplus),
810 ? "Duration/ID of the second frame does not cover the remaining TXOP"
811 : "Duration/ID of the second frame must be set to remaining time to "
812 "complete DATA+ACK sequence"));
813
814 // a Normal Ack is then sent by STA2
815 tEnd = m_txPsdus[5].txStart + m_txPsdus[5].txDuration;
816 tStart = m_txPsdus[6].txStart;
817
818 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
819 tStart,
820 "Ack in response to the second frame sent too early");
822 tEnd + sifs + tolerance,
823 "Ack in response to the second frame sent too late");
824 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[6].header.IsAck(), true, "Expected a Normal Ack");
825 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[6].header.GetAddr1(),
826 apDev->GetMac()->GetAddress(),
827 "Expected a Normal Ack sent to the AP");
829 m_txPsdus[6].header.GetDuration(),
830 RoundDurationId(m_txPsdus[5].header.GetDuration() - sifs - m_txPsdus[6].txDuration),
831 "Duration/ID of the Ack must be derived from that of the previous frame");
832
833 // the AP sends a frame to STA3
834 tEnd = m_txPsdus[6].txStart + m_txPsdus[6].txDuration;
835 tStart = m_txPsdus[7].txStart;
836
837 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third frame sent too early");
838 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third frame sent too late");
839 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[7].header.IsQosData(), true, "Expected a QoS data frame");
840 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[7].header.GetAddr1(),
841 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
842 "Expected a frame sent by the AP to the third station");
844 {
846 rtsCtsThreshold,
847 "PSDU size expected not to exceed length based RTS/CTS threshold");
848 }
849 else
850 {
852 m_txPsdus[7].txDuration,
853 rtsCtsTxDurationThresh,
854 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
855 }
857 m_txPsdus[7].header.GetDuration(),
859 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[7].txStart - txopStart) -
860 m_txPsdus[7].txDuration)
861 : sifs + m_txPsdus[8].txDuration + m_singleExchangeProtectionSurplus),
863 ? "Duration/ID of the third frame does not cover the remaining TXOP"
864 : "Duration/ID of the third frame must be set to remaining time to "
865 "complete DATA+ACK sequence"));
866
867 // a Normal Ack is then sent by STA3
868 tEnd = m_txPsdus[7].txStart + m_txPsdus[7].txDuration;
869 tStart = m_txPsdus[8].txStart;
870
871 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the third frame sent too early");
873 tEnd + sifs + tolerance,
874 "Ack in response to the third frame sent too late");
875 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[8].header.IsAck(), true, "Expected a Normal Ack");
876 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[8].header.GetAddr1(),
877 apDev->GetMac()->GetAddress(),
878 "Expected a Normal Ack sent to the AP");
880 m_txPsdus[8].header.GetDuration(),
881 RoundDurationId(m_txPsdus[7].header.GetDuration() - sifs - m_txPsdus[8].txDuration),
882 "Duration/ID of the Ack must be derived from that of the previous frame");
883
884 // the AP sends another frame to STA2, which is only protected if ProtectedIfResponded is true,
885 // because its size/duration exceeds the threshold but STA2 has already responded to the AP in
886 // this TXOP
888 {
889 tEnd = m_txPsdus[8].txStart + m_txPsdus[8].txDuration;
890 tStart = m_txPsdus[9].txStart;
891
892 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "RTS before fourth frame sent too early");
894 tEnd + sifs + tolerance,
895 "RTS before fourth frame sent too late");
896 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.IsRts(), true, "Expected an RTS frame");
898 m_txPsdus[9].header.GetAddr1(),
899 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
900 "Expected an RTS frame sent by the AP to the second station");
902 m_txPsdus[9].header.GetDuration(),
904 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[9].txStart - txopStart) -
905 m_txPsdus[9].txDuration)
906 : sifs + m_txPsdus[10].txDuration + sifs + m_txPsdus[11].txDuration + sifs +
909 ? "Duration/ID of the RTS before the fourth frame does not cover the remaining "
910 "TXOP"
911 : "Duration/ID of the RTS before the fourth frame must be set to remaining time "
912 "to complete CTS+DATA+ACK sequence"));
913
914 // a CTS is sent by STA2
915 tEnd = m_txPsdus[9].txStart + m_txPsdus[9].txDuration;
916 tStart = m_txPsdus[10].txStart;
917
918 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
919 tStart,
920 "CTS in response to RTS before the fourth frame sent too early");
922 tEnd + sifs + tolerance,
923 "CTS in response to RTS before the fourth frame sent too late");
924 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.IsCts(), true, "Expected a CTS");
925 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.GetAddr1(),
926 apDev->GetMac()->GetAddress(),
927 "Expected a CTS frame sent to the AP");
929 m_txPsdus[10].header.GetDuration(),
930 RoundDurationId(m_txPsdus[9].header.GetDuration() - sifs - m_txPsdus[10].txDuration),
931 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
932
933 // the AP sends another frame to STA2
934 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
935 tStart = m_txPsdus[11].txStart;
936
937 // remove RTS and CTS so that indices are aligned with the ProtectedIfResponded true case
938 m_txPsdus.erase(std::next(m_txPsdus.cbegin(), 9), std::next(m_txPsdus.cbegin(), 11));
939 }
940 else
941 {
942 // the AP sends another frame to STA2
943 tEnd = m_txPsdus[8].txStart + m_txPsdus[8].txDuration;
944 tStart = m_txPsdus[9].txStart;
945 }
946
947 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Fourth frame sent too early");
948 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Fourth frame sent too late");
949 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.IsQosData(), true, "Expected a QoS data frame");
950 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.GetAddr1(),
951 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
952 "Expected a frame sent by the AP to the second station");
954 {
956 rtsCtsThreshold,
957 "PSDU size expected to exceed length based RTS/CTS threshold");
958 }
959 else
960 {
961 NS_TEST_EXPECT_MSG_GT(m_txPsdus[9].txDuration,
962 rtsCtsTxDurationThresh,
963 "PSDU duration expected to exceed duration based RTS/CTS threshold");
964 }
966 m_txPsdus[9].header.GetDuration(),
968 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[9].txStart - txopStart) -
969 m_txPsdus[9].txDuration)
970 : sifs + m_txPsdus[10].txDuration + m_singleExchangeProtectionSurplus),
972 ? "Duration/ID of the fourth frame does not cover the remaining TXOP"
973 : "Duration/ID of the fourth frame must be set to remaining time to "
974 "complete DATA+(Block)ACK sequence"));
975
976 std::string ack(m_nonHt ? "Normal Ack" : "Block Ack");
977
978 // a Normal/Block Ack is then sent by STA1
979 tEnd = m_txPsdus[9].txStart + m_txPsdus[9].txDuration;
980 tStart = m_txPsdus[10].txStart;
981
982 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
983 tStart,
984 ack << " in response to the fourth QoS data frame sent too early");
986 tEnd + sifs + tolerance,
987 ack << " in response to the fourth QoS data frame sent too late");
989 (m_nonHt ? m_txPsdus[10].header.IsAck() : m_txPsdus[10].header.IsBlockAck()),
990 true,
991 "Expected a " << ack);
992 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.GetAddr1(),
993 apDev->GetMac()->GetAddress(),
994 "Expected a " << ack << " sent to the AP");
996 m_txPsdus[10].header.GetDuration(),
997 RoundDurationId(m_txPsdus[9].header.GetDuration() - sifs - m_txPsdus[10].txDuration),
998 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
999
1001 {
1002 // the TXOP limit is such that enough time for sending a CF-End frame remains
1003 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
1004 tStart = m_txPsdus[11].txStart;
1005
1006 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
1007 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
1008 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.IsCfEnd(), true, "Expected a CF-End frame");
1009 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.GetDuration(),
1010 MicroSeconds(0),
1011 "Duration/ID must be set to 0 for CF-End frames");
1012
1013 // remove CF-END so that indices are aligned with the protectSingleExchange false case
1014 m_txPsdus.erase(std::next(m_txPsdus.cbegin(), 11), std::next(m_txPsdus.cbegin(), 12));
1015 }
1016
1017 // the CF-End frame resets the NAV on STA1, which can now transmit
1018 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
1019 tStart = m_txPsdus[11].txStart;
1020
1021 NS_TEST_EXPECT_MSG_GT_OR_EQ(tStart - tEnd,
1022 sifs + m_staAifsn * slot,
1023 "Less than AIFS elapsed between two TXOPs");
1024 NS_TEST_EXPECT_MSG_LT_OR_EQ(tStart - tEnd,
1025 sifs + m_staAifsn * slot + m_staCwMin * slot + tolerance,
1026 "More than AIFS+BO elapsed between two TXOPs");
1027 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.IsQosData(), true, "Expected a QoS data frame");
1028 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.GetAddr1(),
1029 apDev->GetMac()->GetAddress(),
1030 "Expected a frame sent by the first station to the AP");
1032 {
1034 rtsCtsThreshold,
1035 "PSDU size expected not to exceed length based RTS/CTS threshold");
1036 }
1037 else
1038 {
1040 m_txPsdus[11].txDuration,
1041 rtsCtsTxDurationThresh,
1042 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
1043 }
1045 m_txPsdus[11].header.GetDuration(),
1047 ? RoundDurationId(m_staTxopLimit - m_txPsdus[11].txDuration)
1048 : sifs + m_txPsdus[12].txDuration + m_singleExchangeProtectionSurplus),
1050 ? "Duration/ID of the frame sent by the first station does not "
1051 "cover the remaining TXOP"
1052 : "Duration/ID of the frame sent by the first station must be set "
1053 "to remaining time to "
1054 "complete DATA+ACK sequence"));
1055
1056 // a Normal Ack is then sent by the AP
1057 tEnd = m_txPsdus[11].txStart + m_txPsdus[11].txDuration;
1058 tStart = m_txPsdus[12].txStart;
1059
1060 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack sent too early");
1061 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Ack sent too late");
1062 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[12].header.IsAck(), true, "Expected a Normal Ack");
1063 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[12].header.GetAddr1(),
1064 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1065 "Expected a Normal Ack sent to the first station");
1067 m_txPsdus[12].header.GetDuration(),
1068 RoundDurationId(m_txPsdus[11].header.GetDuration() - sifs - m_txPsdus[12].txDuration),
1069 "Duration/ID of the Ack must be derived from that of the previous frame");
1070
1072 {
1073 // the TXOP limit is such that enough time for sending a CF-End frame remains
1074 tEnd = m_txPsdus[12].txStart + m_txPsdus[12].txDuration;
1075 tStart = m_txPsdus[13].txStart;
1076
1077 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
1078 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
1079 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.IsCfEnd(), true, "Expected a CF-End frame");
1080 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.GetDuration(),
1081 MicroSeconds(0),
1082 "Duration/ID must be set to 0 for CF-End frames");
1083
1084 // remove CF-END so that indices are aligned with the protectSingleExchange false case
1085 m_txPsdus.erase(std::next(m_txPsdus.cbegin(), 13), std::next(m_txPsdus.cbegin(), 14));
1086 }
1087
1088 /*
1089 * Verify that the Duration/ID of RTS/CTS frames is set correctly, that the TXOP holder is
1090 * kept and allows stations to ignore NAV properly and that the CF-End Frame is not sent if
1091 * not enough time remains. If SingleRtsPerTxop is set to true, only one RTS/CTS is sent.
1092 *
1093 * |---------------------------------------------NAV---------------------------------->|
1094 * | |-----------------------------------------NAV------------------------------->| |
1095 * | |-------------------------------------NAV---------------------------->| | | |
1096 * |---------------------------------NAV------------------------->| | | | |
1097 * |-----------------------------NAV---------------------->| | | | | |
1098 * |-------------------------NAV------------------->| | | | | | |
1099 * |---------------------NAV---------------->| | | | | | | |
1100 * |-----------------NAV------------->| | | | | | | | |
1101 * |-------------NAV---------->| | | | | | | | | |
1102 * |---------NAV------->| | | | | | | | | | |
1103 * |-----NAV---->| | | | | | | | | | | |
1104 * |-NAV->|
1105 * |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---|
1106 * |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack|
1107 * ----------------------------------------------------------------------------------------------------
1108 * From: AP STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3
1109 * To: STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3 AP
1110 */
1111
1112 // the first frame is an RTS frame sent by the AP to STA1
1113 txopStart = m_txPsdus[13].txStart;
1114
1115 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.IsRts(), true, "Expected an RTS frame");
1116 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.GetAddr1(),
1117 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1118 "Expected an RTS frame sent by the AP to the first station");
1119 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.GetDuration(),
1121 ? RoundDurationId(m_apTxopLimit - m_txPsdus[13].txDuration)
1122 : sifs + m_txPsdus[14].txDuration + sifs + m_txPsdus[15].txDuration +
1123 sifs + m_txPsdus[16].txDuration +
1126 ? "Duration/ID of the first RTS frame must cover the whole TXOP"
1127 : "Duration/ID of the first RTS frame must be set to remaining time "
1128 "to complete CTS+DATA+(Block)ACK sequence"));
1129
1130 // a CTS is sent by STA1
1131 tEnd = m_txPsdus[13].txStart + m_txPsdus[13].txDuration;
1132 tStart = m_txPsdus[14].txStart;
1133
1134 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1135 tStart,
1136 "CTS in response to the first RTS frame sent too early");
1137 NS_TEST_EXPECT_MSG_LT(tStart,
1138 tEnd + sifs + tolerance,
1139 "CTS in response to the first RTS frame sent too late");
1140 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[14].header.IsCts(), true, "Expected a CTS");
1141 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[14].header.GetAddr1(),
1142 apDev->GetMac()->GetAddress(),
1143 "Expected a CTS frame sent to the AP");
1145 m_txPsdus[14].header.GetDuration(),
1146 RoundDurationId(m_txPsdus[13].header.GetDuration() - sifs - m_txPsdus[14].txDuration),
1147 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1148
1149 // the AP sends a frame to STA1
1150 tEnd = m_txPsdus[14].txStart + m_txPsdus[14].txDuration;
1151 tStart = m_txPsdus[15].txStart;
1152
1153 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "First QoS data frame sent too early");
1154 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "First QoS data frame sent too late");
1155 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[15].header.IsQosData(), true, "Expected a QoS data frame");
1156 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[15].header.GetAddr1(),
1157 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1158 "Expected a frame sent by the AP to the first station");
1160 {
1162 rtsCtsThreshold,
1163 "PSDU size expected to exceed length based RTS/CTS threshold");
1164 }
1165 else
1166 {
1167 NS_TEST_EXPECT_MSG_GT(m_txPsdus[15].txDuration,
1168 rtsCtsTxDurationThresh,
1169 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1170 }
1172 m_txPsdus[15].header.GetDuration(),
1174 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[15].txStart - txopStart) -
1175 m_txPsdus[15].txDuration)
1176 : sifs + m_txPsdus[16].txDuration + m_singleExchangeProtectionSurplus),
1178 ? "Duration/ID of the first QoS data frame does not cover the remaining TXOP"
1179 : "Duration/ID of the first QoS data frame must be set to remaining time to "
1180 "complete DATA+(Block)ACK sequence"));
1181
1182 // a Normal/Block Ack is then sent by STA1
1183 tEnd = m_txPsdus[15].txStart + m_txPsdus[15].txDuration;
1184 tStart = m_txPsdus[16].txStart;
1185
1186 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1187 tStart,
1188 ack << " in response to the first QoS data frame sent too early");
1189 NS_TEST_EXPECT_MSG_LT(tStart,
1190 tEnd + sifs + tolerance,
1191 ack << " in response to the first QoS data frame sent too late");
1193 (m_nonHt ? m_txPsdus[16].header.IsAck() : m_txPsdus[16].header.IsBlockAck()),
1194 true,
1195 "Expected a " << ack);
1196 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[16].header.GetAddr1(),
1197 apDev->GetMac()->GetAddress(),
1198 "Expected a " << ack << " sent to the AP");
1200 m_txPsdus[16].header.GetDuration(),
1201 RoundDurationId(m_txPsdus[15].header.GetDuration() - sifs - m_txPsdus[16].txDuration),
1202 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1203
1204 std::size_t idx = 16;
1205
1206 if (!m_singleRtsPerTxop)
1207 {
1208 // An RTS frame is sent by the AP to STA2
1209 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1210 ++idx;
1211 tStart = m_txPsdus[idx].txStart;
1212
1213 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second RTS frame sent too early");
1214 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second RTS frame sent too late");
1215 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsRts(), true, "Expected an RTS frame");
1217 m_txPsdus[idx].header.GetAddr1(),
1218 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
1219 "Expected an RTS frame sent by the AP to the second station");
1221 m_txPsdus[idx].header.GetDuration(),
1223 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1224 m_txPsdus[idx].txDuration)
1225 : sifs + m_txPsdus[idx + 1].txDuration + sifs + m_txPsdus[idx + 2].txDuration +
1226 sifs + m_txPsdus[idx + 3].txDuration + m_singleExchangeProtectionSurplus),
1228 ? "Duration/ID of the second RTS frame must cover the whole TXOP"
1229 : "Duration/ID of the second RTS frame must be set to remaining time to complete "
1230 "CTS+DATA+(Block)ACK sequence"));
1231
1232 // a CTS is sent by STA2 (which ignores the NAV)
1233 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1234 tStart = m_txPsdus[idx + 1].txStart;
1235
1236 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1237 tStart,
1238 "CTS in response to the second RTS frame sent too early");
1239 NS_TEST_EXPECT_MSG_LT(tStart,
1240 tEnd + sifs + tolerance,
1241 "CTS in response to the second RTS frame sent too late");
1242 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.IsCts(), true, "Expected a CTS");
1243 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1244 apDev->GetMac()->GetAddress(),
1245 "Expected a CTS frame sent to the AP");
1247 m_txPsdus[idx + 1].header.GetDuration(),
1248 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs -
1249 m_txPsdus[idx + 1].txDuration),
1250 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1251
1252 ++idx;
1253 }
1254
1255 // the AP sends a frame to STA2
1256 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1257 ++idx;
1258 tStart = m_txPsdus[idx].txStart;
1259
1260 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second QoS data frame sent too early");
1261 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second QoS data frame sent too late");
1262 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsQosData(), true, "Expected a QoS data frame");
1263 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetAddr1(),
1264 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
1265 "Expected a frame sent by the AP to the second station");
1267 {
1269 rtsCtsThreshold,
1270 "PSDU size expected to exceed length based RTS/CTS threshold");
1271 }
1272 else
1273 {
1274 NS_TEST_EXPECT_MSG_GT(m_txPsdus[idx].txDuration,
1275 rtsCtsTxDurationThresh,
1276 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1277 }
1279 m_txPsdus[idx].header.GetDuration(),
1281 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1282 m_txPsdus[idx].txDuration)
1283 : sifs + m_txPsdus[idx + 1].txDuration + m_singleExchangeProtectionSurplus),
1285 ? "Duration/ID of the second QoS data frame does not cover the remaining TXOP"
1286 : "Duration/ID of the second QoS data frame must be set to remaining time to "
1287 "complete DATA+(Block)ACK sequence"));
1288
1289 // a Normal/Block Ack is then sent by STA2
1290 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1291 tStart = m_txPsdus[idx + 1].txStart;
1292
1293 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1294 tStart,
1295 ack << " in response to the second QoS data frame sent too early");
1296 NS_TEST_EXPECT_MSG_LT(tStart,
1297 tEnd + sifs + tolerance,
1298 ack << " in response to the second QoS data frame sent too late");
1300 (m_nonHt ? m_txPsdus[idx + 1].header.IsAck() : m_txPsdus[idx + 1].header.IsBlockAck()),
1301 true,
1302 "Expected a " << ack);
1303 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1304 apDev->GetMac()->GetAddress(),
1305 "Expected a " << ack << " sent to the AP");
1307 m_txPsdus[idx + 1].header.GetDuration(),
1308 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs - m_txPsdus[idx + 1].txDuration),
1309 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1310 ++idx;
1311
1312 if (!m_singleRtsPerTxop)
1313 {
1314 // An RTS frame is sent by the AP to STA3
1315 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1316 ++idx;
1317 tStart = m_txPsdus[idx].txStart;
1318
1319 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third RTS frame sent too early");
1320 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third RTS frame sent too late");
1321 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsRts(), true, "Expected an RTS frame");
1323 m_txPsdus[idx].header.GetAddr1(),
1324 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
1325 "Expected an RTS frame sent by the AP to the third station");
1327 m_txPsdus[idx].header.GetDuration(),
1329 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1330 m_txPsdus[idx].txDuration)
1331 : sifs + m_txPsdus[idx + 1].txDuration + sifs + m_txPsdus[idx + 2].txDuration +
1332 sifs + m_txPsdus[idx + 3].txDuration + m_singleExchangeProtectionSurplus),
1334 ? "Duration/ID of the third RTS frame must cover the whole TXOP"
1335 : "Duration/ID of the third RTS frame must be set to remaining time to complete "
1336 "CTS+DATA+(Block)ACK sequence"));
1337
1338 // a CTS is sent by STA3 (which ignores the NAV)
1339 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1340 tStart = m_txPsdus[idx + 1].txStart;
1341
1342 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1343 tStart,
1344 "CTS in response to the third RTS frame sent too early");
1345 NS_TEST_EXPECT_MSG_LT(tStart,
1346 tEnd + sifs + tolerance,
1347 "CTS in response to the third RTS frame sent too late");
1348 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.IsCts(), true, "Expected a CTS");
1349 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1350 apDev->GetMac()->GetAddress(),
1351 "Expected a CTS frame sent to the AP");
1353 m_txPsdus[idx + 1].header.GetDuration(),
1354 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs -
1355 m_txPsdus[idx + 1].txDuration),
1356 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1357 ++idx;
1358 }
1359
1360 // the AP sends a frame to STA3
1361 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1362 ++idx;
1363 tStart = m_txPsdus[idx].txStart;
1364
1365 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third QoS data frame sent too early");
1366 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third QoS data frame sent too late");
1367 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsQosData(), true, "Expected a QoS data frame");
1368 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetAddr1(),
1369 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
1370 "Expected a frame sent by the AP to the third station");
1372 {
1374 rtsCtsThreshold,
1375 "PSDU size expected to exceed length based RTS/CTS threshold");
1376 }
1377 else
1378 {
1379 NS_TEST_EXPECT_MSG_GT(m_txPsdus[idx].txDuration,
1380 rtsCtsTxDurationThresh,
1381 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1382 }
1384 m_txPsdus[idx].header.GetDuration(),
1386 ? RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1387 m_txPsdus[idx].txDuration)
1388 : sifs + m_txPsdus[idx + 1].txDuration + m_singleExchangeProtectionSurplus),
1390 ? "Duration/ID of the third QoS data frame does not cover the remaining TXOP"
1391 : "Duration/ID of the third QoS data frame must be set to remaining time to "
1392 "complete DATA+(Block)ACK sequence"));
1393
1394 // a Normal/Block Ack is then sent by STA3
1395 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1396 tStart = m_txPsdus[idx + 1].txStart;
1397
1398 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1399 tStart,
1400 ack << " in response to the third QoS data frame sent too early");
1401 NS_TEST_EXPECT_MSG_LT(tStart,
1402 tEnd + sifs + tolerance,
1403 ack << " in response to the third QoS data frame sent too late");
1405 (m_nonHt ? m_txPsdus[idx + 1].header.IsAck() : m_txPsdus[idx + 1].header.IsBlockAck()),
1406 true,
1407 "Expected a " << ack);
1408 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1409 apDev->GetMac()->GetAddress(),
1410 "Expected a " << ack << " sent to the AP");
1412 m_txPsdus[idx + 1].header.GetDuration(),
1413 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs - m_txPsdus[idx + 1].txDuration),
1414 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1415 ++idx;
1416
1417 // there is no time remaining for sending a CF-End frame if SingleRtsPerTxop is false. This is
1418 // verified by checking that 25 frames are transmitted (done at the beginning of this method)
1420 {
1421 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1422 ++idx;
1423 tStart = m_txPsdus[idx].txStart;
1424
1425 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
1426 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
1427 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsCfEnd(), true, "Expected a CF-End frame");
1428 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetDuration(),
1429 MicroSeconds(0),
1430 "Duration/ID must be set to 0 for CF-End frames");
1431 }
1432
1433 // Expected received packets:
1434 // - 4 DL packets (without RTS/CTS) if non-HT, 5 DL packets (without RTS/CTS) if HE
1435 // - 1 UL packet
1436 // - 3 DL packets (with RTS/CTS) if non-HT, 6 DL packets (with RTS/CTS) if HE
1437 NS_TEST_EXPECT_MSG_EQ(m_received, (m_nonHt ? 8 : 12), "Unexpected number of packets received");
1438}
1439
1440/**
1441 * @ingroup wifi-test
1442 * @ingroup tests
1443 *
1444 * @brief wifi TXOP Test Suite
1445 */
1447{
1448 public:
1450};
1451
1453 : TestSuite("wifi-txop", Type::UNIT)
1454{
1455 for (const auto nonHt : {true, false})
1456 {
1457 for (const auto pifsRecovery : {true, false})
1458 {
1459 for (const auto singleRtsPerTxop : {true, false})
1460 {
1461 for (const auto lengthBasedRtsCtsThresh : {true, false})
1462 {
1463 for (const auto protectedIfResponded : {true, false})
1464 {
1465 for (const auto protectSingleExchange : {false, true})
1466 {
1467 for (const auto& singleExchangeProtectionBuffer :
1468 {Time(), MicroSeconds(25) /* PIFS */})
1469 {
1470 if (!protectSingleExchange &&
1471 singleExchangeProtectionBuffer.IsStrictlyPositive())
1472 {
1473 continue;
1474 }
1476 .nonHt = nonHt,
1477 .pifsRecovery = pifsRecovery,
1478 .singleRtsPerTxop = singleRtsPerTxop,
1479 .lengthBasedRtsCtsThresh = lengthBasedRtsCtsThresh,
1480 .protectedIfResponded = protectedIfResponded,
1481 .protectSingleExchange = protectSingleExchange,
1482 .singleExchangeProtectionBuffer =
1483 singleExchangeProtectionBuffer,
1484 }),
1486 }
1487 }
1488 }
1489 }
1490 }
1491 }
1492 }
1493}
1494
1495static 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:114
AttributeContainerValue< UintAccessParamsPairValue, ';'> UintAccessParamsMapValue
AttributeValue type of an ACI-indexed map of access parameters of type unsigned integer.
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.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
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.
Definition ptr.h:70
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:580
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
static void Run()
Run the simulation.
Definition simulator.cc:161
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:169
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
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
AttributeValue implementation for Time.
Definition nstime.h:1375
bool LookupAttributeByName(std::string name, AttributeInformation *info, bool permissive=false) const
Find an Attribute by name, retrieving the associated AttributeInformation.
Definition type-id.cc:966
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:38
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:1574
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition wifi-phy.cc:1567
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...
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:690
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:194
#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:267
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#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:985
#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:133
#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:819
#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:779
#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:945
#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:240
#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:553
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1307
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1324
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1290
@ WIFI_STANDARD_80211a
@ WIFI_STANDARD_80211ax
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
@ AC_BE
Best Effort.
Definition qos-utils.h:66
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:605
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:295
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).
const Time DEFAULT_BEACON_INTERVAL
Default Beacon interval.
STL namespace.
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:87
Ptr< const AttributeValue > initialValue
Configured initial value.
Definition type-id.h:97
std::string dir
static WifiTxopTestSuite g_wifiTxopTestSuite
the test suite