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 };
75
76 /**
77 * Constructor
78 * @param params parameters for the Wi-Fi TXOP test
79 */
80 WifiTxopTest(const Params& params);
81
82 /**
83 * Function to trace packets received by the server application
84 * @param context the context
85 * @param p the packet
86 * @param addr the address
87 */
88 void L7Receive(std::string context, Ptr<const Packet> p, const Address& addr);
89
90 /**
91 * Callback invoked when PHY receives a PSDU to transmit
92 * @param context the context
93 * @param psduMap the PSDU map
94 * @param txVector the TX vector
95 * @param txPowerW the tx power in Watts
96 */
97 void Transmit(std::string context,
98 WifiConstPsduMap psduMap,
99 WifiTxVector txVector,
100 double txPowerW);
101
102 /**
103 * Check correctness of transmitted frames
104 */
105 void CheckResults();
106
107 private:
108 void DoRun() override;
109
110 /// Enumeration for traffic directions
111 enum TrafficDirection : uint8_t
112 {
114 UPLINK
115 };
116
117 /**
118 * @param dir the traffic direction (downlink/uplink)
119 * @param staId the index (starting at 0) of the non-AP STA generating/receiving packets
120 * @param count the number of packets to generate
121 * @param pktSize the size of the packets to generate
122 * @return an application generating the given number packets of the given size from/to the
123 * AP to/from the given non-AP STA
124 */
126 std::size_t staId,
127 std::size_t count,
128 std::size_t pktSize) const;
129
130 /// Information about transmitted frames
132 {
133 Time txStart; ///< Frame start TX time
134 Time txDuration; ///< Frame TX duration
135 uint32_t size; ///< PSDU size in bytes
136 WifiMacHeader header; ///< Frame MAC header
137 WifiTxVector txVector; ///< TX vector used to transmit the frame
138 };
139
140 uint16_t m_nStations; ///< number of stations
141 NetDeviceContainer m_staDevices; ///< container for stations' NetDevices
142 NetDeviceContainer m_apDevices; ///< container for AP's NetDevice
143 std::vector<FrameInfo> m_txPsdus; ///< transmitted PSDUs
144 Time m_apTxopLimit; ///< TXOP limit for AP (AC BE)
145 uint8_t m_staAifsn; ///< AIFSN for STAs (AC BE)
146 uint32_t m_staCwMin; ///< CWmin for STAs (AC BE)
147 uint32_t m_staCwMax; ///< CWmax for STAs (AC BE)
148 Time m_staTxopLimit; ///< TXOP limit for STAs (AC BE)
149 uint16_t m_received; ///< number of packets received by the stations
150 bool m_nonHt; ///< whether to use 802.11a or 802.11ax
151 std::size_t m_payloadSizeRtsOn; ///< size in bytes of packets protected by RTS
152 std::size_t m_payloadSizeRtsOff; ///< size in bytes of packets not protected by RTS
153 Time m_startTime; ///< time when data frame exchanges start
154 WifiMode m_mode; ///< wifi mode used to transmit data frames
155 bool m_pifsRecovery; ///< whether to use PIFS recovery
156 bool m_singleRtsPerTxop; ///< whether to use single RTS per TXOP
157 bool m_lengthBasedRtsCtsThresh; ///< whether to use length based RTS/CTS threshold
158 bool m_protectedIfResponded; ///< whether a STA is protected if it responds to the AP
159 Ptr<ListErrorModel> m_apErrorModel; ///< error model to install on the AP
160 Ptr<ListErrorModel> m_staErrorModel; ///< error model to install on a STA
161 bool m_apCorrupted; ///< whether the frame to be corrupted by the AP has been corrupted
162 bool m_staCorrupted; ///< whether the frame to be corrupted by the STA has been corrupted
163 std::vector<PacketSocketAddress> m_dlSockets; ///< packet socket address for DL traffic
164 std::vector<PacketSocketAddress> m_ulSockets; ///< packet socket address for UL traffic
165};
166
168 : TestCase("Check correct operation within TXOPs"),
169 m_nStations(3),
170 m_apTxopLimit(MicroSeconds(4768)),
171 m_staAifsn(4),
172 m_staCwMin(63),
173 m_staCwMax(511),
174 m_staTxopLimit(MicroSeconds(3232)),
175 m_received(0),
176 m_nonHt(params.nonHt),
177 m_payloadSizeRtsOn(m_nonHt ? 2000 : 540),
178 m_payloadSizeRtsOff(500),
179 m_startTime(MilliSeconds(m_nonHt ? 410 : 520)),
180 m_mode(m_nonHt ? OfdmPhy::GetOfdmRate12Mbps() : HePhy::GetHeMcs0()),
181 m_pifsRecovery(params.pifsRecovery),
182 m_singleRtsPerTxop(params.singleRtsPerTxop),
183 m_lengthBasedRtsCtsThresh(params.lengthBasedRtsCtsThresh),
184 m_protectedIfResponded(params.protectedIfResponded),
185 m_apErrorModel(CreateObject<ListErrorModel>()),
186 m_staErrorModel(CreateObject<ListErrorModel>()),
187 m_apCorrupted(false),
188 m_staCorrupted(false)
189{
190}
191
192void
193WifiTxopTest::L7Receive(std::string context, Ptr<const Packet> p, const Address& addr)
194{
195 if (p->GetSize() >= m_payloadSizeRtsOff)
196 {
197 m_received++;
198 }
199}
200
201void
202WifiTxopTest::Transmit(std::string context,
203 WifiConstPsduMap psduMap,
204 WifiTxVector txVector,
205 double txPowerW)
206{
207 bool corrupted{false};
208
209 // The AP does not correctly receive the Ack sent in response to the QoS
210 // data frame sent to the first station
211 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
212 hdr.IsAck() && !m_apCorrupted && !m_txPsdus.empty() &&
213 m_txPsdus.back().header.IsQosData() &&
214 m_txPsdus.back().header.GetAddr1() == m_staDevices.Get(0)->GetAddress())
215 {
216 corrupted = m_apCorrupted = true;
217 m_apErrorModel->SetList({psduMap.begin()->second->GetPacket()->GetUid()});
218 }
219
220 // The second station does not correctly receive the first QoS data frame sent by the AP
221 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
222 !m_txPsdus.empty() && hdr.IsQosData() &&
223 hdr.GetAddr1() == m_staDevices.Get(1)->GetAddress())
224 {
225 if (!m_staCorrupted)
226 {
227 corrupted = m_staCorrupted = true;
228 }
229 if (corrupted)
230 {
231 m_staErrorModel->SetList({psduMap.begin()->second->GetPacket()->GetUid()});
232 }
233 else
234 {
236 }
237 }
238
239 // When the AP sends the first frame to the third station (which is not protected by RTS/CTS),
240 // we generate another frame addressed to the second station whose size/duration exceeds the
241 // threshold; however, RTS is not used because the second station has already responded to
242 // another frame in the same TXOP
243 if (const auto& hdr = psduMap.begin()->second->GetHeader(0);
244 hdr.IsQosData() && hdr.GetAddr1() == m_staDevices.Get(2)->GetAddress() &&
245 hdr.GetSequenceNumber() == (m_nonHt ? 0 : 1))
246 {
247 m_apDevices.Get(0)->GetNode()->AddApplication(
249 }
250
251 // Log all transmitted frames that are not beacon frames and have been transmitted
252 // after the start time (so as to skip association requests/responses)
253 if (!psduMap.begin()->second->GetHeader(0).IsBeacon() && Simulator::Now() >= m_startTime)
254 {
255 m_txPsdus.push_back({Simulator::Now(),
257 psduMap[SU_STA_ID]->GetSize(),
258 psduMap[SU_STA_ID]->GetHeader(0),
259 txVector});
260 }
261
262 // Print all the transmitted frames if the test is executed through test-runner
263 NS_LOG_INFO(psduMap.begin()->second->GetHeader(0).GetTypeString()
264 << " seq " << psduMap.begin()->second->GetHeader(0).GetSequenceNumber() << " to "
265 << psduMap.begin()->second->GetAddr1() << " TX duration "
267 << " duration/ID " << psduMap.begin()->second->GetHeader(0).GetDuration()
268 << (corrupted ? " CORRUPTED" : "") << std::endl);
269}
270
271void
273{
276 int64_t streamNumber = 100;
277
278 NodeContainer wifiApNode;
279 wifiApNode.Create(1);
280
281 NodeContainer wifiStaNodes;
282 wifiStaNodes.Create(m_nStations);
283
284 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
286 spectrumChannel->AddPropagationLossModel(lossModel);
288 spectrumChannel->SetPropagationDelayModel(delayModel);
289
291 phy.SetChannel(spectrumChannel);
292 // use default 20 MHz channel in 5 GHz band
293 phy.Set("ChannelSettings", StringValue("{0, 20, BAND_5GHZ, 0}"));
294
295 Config::SetDefault("ns3::QosFrameExchangeManager::PifsRecovery", BooleanValue(m_pifsRecovery));
296 Config::SetDefault("ns3::WifiDefaultProtectionManager::SingleRtsPerTxop",
299 {
300 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold",
302 }
303 else
304 {
305 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsTxDurationThresh",
306 TimeValue(Seconds(m_payloadSizeRtsOn * (m_nonHt ? 1 : 2) * 8.0 /
307 m_mode.GetDataRate(MHz_u{20}))));
308 }
309 Config::SetDefault("ns3::FrameExchangeManager::ProtectedIfResponded",
310 BooleanValue(m_protectedIfResponded));
311
312 WifiHelper wifi;
313 wifi.SetStandard(m_nonHt ? WIFI_STANDARD_80211a : WIFI_STANDARD_80211ax);
314 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
315 "DataMode",
316 WifiModeValue(m_mode),
317 "ControlMode",
318 StringValue("OfdmRate6Mbps"));
319
320 WifiMacHelper mac;
321 mac.SetType("ns3::StaWifiMac",
322 "QosSupported",
323 BooleanValue(true),
324 "Ssid",
325 SsidValue(Ssid("non-existent-ssid")));
326
327 m_staDevices = wifi.Install(phy, mac, wifiStaNodes);
328
329 mac.SetType(
330 "ns3::ApWifiMac",
331 "QosSupported",
332 BooleanValue(true),
333 "Ssid",
334 SsidValue(Ssid("wifi-txop-ssid")),
335 "BeaconInterval",
336 TimeValue(MicroSeconds(102400)),
337 "EnableBeaconJitter",
338 BooleanValue(false),
339 "AifsnsForSta",
340 StringValue(std::string("BE ") + std::to_string(m_staAifsn)),
341 "CwMinsForSta",
343 ApWifiMac::UintAccessParamsMap{{AC_BE, std::vector<uint64_t>{m_staCwMin}}}),
344 "CwMaxsForSta",
345 StringValue(std::string("BE ") + std::to_string(m_staCwMax)),
346 "TxopLimitsForSta",
347 StringValue(std::string("BE ") + std::to_string(m_staTxopLimit.GetMicroSeconds()) + "us"));
348
349 mac.SetEdca(AC_BE, "TxopLimits", AttributeContainerValue<TimeValue>(std::list{m_apTxopLimit}));
350
351 m_apDevices = wifi.Install(phy, mac, wifiApNode);
352
353 // schedule association requests at different times. One station's SSID is
354 // set to the correct value before initialization, so that such a station
355 // starts the scanning procedure by looking for the correct SSID
356 Ptr<WifiNetDevice> dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(0));
357 dev->GetMac()->SetSsid(Ssid("wifi-txop-ssid"));
358
359 for (uint16_t i = 1; i < m_nStations; i++)
360 {
361 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
364 dev->GetMac(),
365 Ssid("wifi-txop-ssid"));
366 }
367
368 // Assign fixed streams to random variables in use
369 WifiHelper::AssignStreams(m_apDevices, streamNumber);
370
373
374 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
375 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
376 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
377 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
378 mobility.SetPositionAllocator(positionAlloc);
379
380 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
381 mobility.Install(wifiApNode);
382 mobility.Install(wifiStaNodes);
383
384 PacketSocketHelper packetSocket;
385 packetSocket.Install(wifiApNode);
386 packetSocket.Install(wifiStaNodes);
387
388 // install a packet socket server on all nodes
389 for (auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); ++nodeIt)
390 {
391 PacketSocketAddress srvAddr;
392 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
393 NS_TEST_ASSERT_MSG_NE(device, nullptr, "Expected a WifiNetDevice");
394 srvAddr.SetSingleDevice(device->GetIfIndex());
395 srvAddr.SetProtocol(1);
396
398 server->SetLocal(srvAddr);
399 (*nodeIt)->AddApplication(server);
400 server->SetStartTime(Time{0}); // now
401 server->SetStopTime(Seconds(1));
402 }
403
404 // set DL and UL packet sockets
405 for (uint16_t i = 0; i < m_nStations; ++i)
406 {
407 m_dlSockets.emplace_back();
408 m_dlSockets.back().SetSingleDevice(m_apDevices.Get(0)->GetIfIndex());
409 m_dlSockets.back().SetPhysicalAddress(m_staDevices.Get(i)->GetAddress());
410 m_dlSockets.back().SetProtocol(1);
411
412 m_ulSockets.emplace_back();
413 m_ulSockets.back().SetSingleDevice(m_staDevices.Get(i)->GetIfIndex());
414 m_ulSockets.back().SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
415 m_ulSockets.back().SetProtocol(1);
416 }
417
418 // DL frames
419 for (uint16_t i = 0; i < m_nStations; i++)
420 {
421 if (!m_nonHt)
422 {
423 // Send one QoS data frame to establish Block Ack agreement (packet size is such that
424 // this packet is not counted as a received packet)
425 Simulator::Schedule(m_startTime - MilliSeconds(110 - i * 25),
427 wifiApNode.Get(0),
428 GetApplication(DOWNLINK, i, 1, m_payloadSizeRtsOff - 1));
429 }
430
431 // Send one QoS data frame (not protected by RTS/CTS) to each station
432 Simulator::Schedule(m_startTime,
434 wifiApNode.Get(0),
435 GetApplication(DOWNLINK, i, 1, m_payloadSizeRtsOff));
436
437 // Send one QoS data frame (protected by RTS/CTS) to each station
438 Simulator::Schedule(m_startTime + MilliSeconds(110),
440 wifiApNode.Get(0),
441 GetApplication(DOWNLINK, i, m_nonHt ? 1 : 2, m_payloadSizeRtsOn));
442 }
443
444 // install the error model on the AP
445 dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
446 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(m_apErrorModel);
447
448 // install the error model on the second station
449 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(1));
450 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(m_staErrorModel);
451
452 // UL Traffic (the first station sends one frame to the AP)
453 {
454 if (!m_nonHt)
455 {
456 // Send one QoS data frame to establish Block Ack agreement (packet size is such that
457 // this packet is not counted as a received packet)
458 Simulator::Schedule(m_startTime - MilliSeconds(35),
460 wifiStaNodes.Get(0),
461 GetApplication(UPLINK, 0, 1, m_payloadSizeRtsOff - 1));
462 }
463
464 Simulator::Schedule(m_startTime + MilliSeconds(2),
466 wifiStaNodes.Get(0),
467 GetApplication(UPLINK, 0, 1, m_payloadSizeRtsOff));
468 }
469
470 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx",
472 // Trace PSDUs passed to the PHY on all devices
473 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
475
478
479 CheckResults();
480
482}
483
486 std::size_t staId,
487 std::size_t count,
488 std::size_t pktSize) const
489{
490 auto client = CreateObject<PacketSocketClient>();
491 client->SetAttribute("PacketSize", UintegerValue(pktSize));
492 client->SetAttribute("MaxPackets", UintegerValue(count));
493 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
494 client->SetRemote(dir == DOWNLINK ? m_dlSockets.at(staId) : m_ulSockets.at(staId));
495 client->SetStartTime(Time{0}); // now
496 client->SetStopTime(Seconds(1));
497
498 return client;
499}
500
501void
503{
504 // check that STAs used the access parameters advertised by the AP
505 for (uint32_t i = 0; i < m_staDevices.GetN(); ++i)
506 {
507 auto staEdca = DynamicCast<WifiNetDevice>(m_staDevices.Get(i))->GetMac()->GetQosTxop(AC_BE);
508 NS_TEST_EXPECT_MSG_EQ(staEdca->GetAifsn(SINGLE_LINK_OP_ID),
510 "Unexpected AIFSN for STA " << i);
511 NS_TEST_EXPECT_MSG_EQ(staEdca->GetMinCw(SINGLE_LINK_OP_ID),
513 "Unexpected CWmin for STA " << i);
514 NS_TEST_EXPECT_MSG_EQ(staEdca->GetMaxCw(SINGLE_LINK_OP_ID),
516 "Unexpected CWmax for STA " << i);
517 NS_TEST_EXPECT_MSG_EQ(staEdca->GetTxopLimit(SINGLE_LINK_OP_ID),
519 "Unexpected TXOP limit for STA " << i);
520 }
521
522 const auto apDev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
523
524 NS_TEST_EXPECT_MSG_EQ(apDev->GetMac()->GetQosTxop(AC_BE)->GetTxopLimit(SINGLE_LINK_OP_ID),
526 "Unexpected TXOP limit for AP");
527
528 const auto aifsn = apDev->GetMac()->GetQosTxop(AC_BE)->GetAifsn(SINGLE_LINK_OP_ID);
529 const auto cwMin = apDev->GetMac()->GetQosTxop(AC_BE)->GetMinCw(SINGLE_LINK_OP_ID);
530 Time tEnd; // TX end for a frame
531 Time tStart; // TX start for the next frame
532 Time txopStart; // TXOP start time
533 Time tolerance = NanoSeconds(50); // due to propagation delay
534 Time sifs = apDev->GetPhy()->GetSifs();
535 Time slot = apDev->GetPhy()->GetSlot();
536 Time navEnd;
539 const uint32_t rtsCtsThreshold = DynamicCast<const UintegerValue>(info.initialValue)->Get();
540 WifiRemoteStationManager::GetTypeId().LookupAttributeByName("RtsCtsTxDurationThresh", &info);
541 const Time rtsCtsTxDurationThresh = DynamicCast<const TimeValue>(info.initialValue)->Get();
542
543 // lambda to round Duration/ID (in microseconds) up to the next higher integer
544 auto RoundDurationId = [](Time t) {
545 return MicroSeconds(ceil(static_cast<double>(t.GetNanoSeconds()) / 1000));
546 };
547
548 /*
549 * Verify the different behavior followed when an initial/non-initial frame of a TXOP
550 * fails. Also, verify that a CF-end frame is sent if enough time remains in the TXOP.
551 * The destination of failed frames is put in square brackets below.
552 *
553 * |--NAV----till end TXOP-------->|
554 * | |---NAV--till end TXOP--->|
555 * | | |-----------------------------NAV--------------------------------->|
556 * | | | |----------------------------NAV---------------------------->|
557 * | | | | |---------------------------NAV----------------------->|
558 * | | | | | |----------------NAV------------------>|
559 * | | | | | | |-------------NAV--------------->|
560 * | | | | | Ack | | |-----------NAV----------->|
561 * Start| | Start| | | Timeout | | | |--------NAV-------->|
562 * TXOP | | TXOP | | | |-PIFS-> | | | | |-----NAV----->|
563 * | | | back | | | | |- or -> | | | | | |--NAV-->|
564 * ┌───┐ ┌───┐-off->┌───┐ ┌───┐ ┌───┐ |-back->┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌─────┐
565 * │QoS│ │Ack│ │QoS│ │Ack│ │QoS│ |-off ->│QoS│ │Ack│ │QoS│ │Ack│ │QoS│ │Ack│ │CFend│
566 * ───┴───┴─┴───┴──────┴───┴─┴───┴─┴───┴───────────┴───┴─┴───┴─┴───┴─┴───┴─┴───┴─┴───┴─┴─────┴─
567 * TA: AP STA1 AP STA1 AP AP STA2 AP STA3 AP STA2 AP
568 * RA: STA1 [AP] STA1 AP [STA2] STA2 AP STA3 AP STA2 AP all
569 *
570 * NOTE: If ProtectedIfResponded is false, the last QoS data frame is protected by RTS/CTS
571 */
572
573 // We expect 25 frames to be transmitted if SingleRtsPerTxop is false and 22 frames (2 RTS
574 // less, 2 CTS less, 1 more CF-End). If ProtectedIfResponded is false, there are 2 frames
575 // (an RTS and a CTS) more.
578 : 27 + (m_protectedIfResponded ? 0 : 2)),
579 "Unexpected number of transmitted frames");
580
581 // the first frame sent after 400ms is a QoS data frame sent by the AP to STA1 without RTS/CTS
582 txopStart = m_txPsdus[0].txStart;
583
584 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].header.IsQosData(), true, "Expected a QoS data frame");
585 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].header.GetAddr1(),
586 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
587 "Expected a frame sent by the AP to the first station");
589 {
591 rtsCtsThreshold,
592 "PSDU size expected not to exceed length based RTS/CTS threshold");
593 }
594 else
595 {
597 m_txPsdus[0].txDuration,
598 rtsCtsTxDurationThresh,
599 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
600 }
601 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[0].header.GetDuration(),
602 RoundDurationId(m_apTxopLimit - m_txPsdus[0].txDuration),
603 "Duration/ID of the first frame must cover the whole TXOP");
604
605 // a Normal Ack is sent by STA1
606 tEnd = m_txPsdus[0].txStart + m_txPsdus[0].txDuration;
607 tStart = m_txPsdus[1].txStart;
608
609 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
611 tEnd + sifs + tolerance,
612 "Ack in response to the first frame sent too late");
613 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[1].header.IsAck(), true, "Expected a Normal Ack");
614 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[1].header.GetAddr1(),
615 apDev->GetMac()->GetAddress(),
616 "Expected a Normal Ack sent to the AP");
618 m_txPsdus[1].header.GetDuration(),
619 RoundDurationId(m_txPsdus[0].header.GetDuration() - sifs - m_txPsdus[1].txDuration),
620 "Duration/ID of the Ack must be derived from that of the first frame");
621
622 // the AP receives a corrupted Ack in response to the frame it sent, which is the initial
623 // frame of a TXOP. Hence, the TXOP is terminated and the AP retransmits the frame after
624 // waiting for EIFS - DIFS + AIFS + backoff (see section 10.3.2.3.7 of 802.11-2020)
625 txopStart = m_txPsdus[2].txStart;
626
627 tEnd = m_txPsdus[1].txStart + m_txPsdus[1].txDuration;
628 tStart = m_txPsdus[2].txStart;
629
630 auto apPhy = apDev->GetPhy(SINGLE_LINK_OP_ID);
631 auto eifsNoDifs = apPhy->GetSifs() + apPhy->GetAckTxTime();
632
634 tStart - tEnd,
635 eifsNoDifs + sifs + aifsn * slot,
636 "Less than AIFS elapsed between AckTimeout and the next TXOP start");
638 tStart - tEnd,
639 eifsNoDifs + sifs + aifsn * slot + (2 * (cwMin + 1) - 1) * slot,
640 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
641 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].header.IsQosData(),
642 true,
643 "Expected to retransmit a QoS data frame");
644 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].header.GetAddr1(),
645 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
646 "Expected to retransmit a frame to the first station");
648 {
650 rtsCtsThreshold,
651 "PSDU size expected not to exceed length based RTS/CTS threshold");
652 }
653 else
654 {
656 m_txPsdus[2].txDuration,
657 rtsCtsTxDurationThresh,
658 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
659 }
660 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[2].header.GetDuration(),
661 RoundDurationId(m_apTxopLimit - m_txPsdus[2].txDuration),
662 "Duration/ID of the retransmitted frame must cover the whole TXOP");
663
664 // a Normal Ack is then sent by STA1
665 tEnd = m_txPsdus[2].txStart + m_txPsdus[2].txDuration;
666 tStart = m_txPsdus[3].txStart;
667
668 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
670 tEnd + sifs + tolerance,
671 "Ack in response to the first frame sent too late");
672 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[3].header.IsAck(), true, "Expected a Normal Ack");
673 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[3].header.GetAddr1(),
674 apDev->GetMac()->GetAddress(),
675 "Expected a Normal Ack sent to the AP");
677 m_txPsdus[3].header.GetDuration(),
678 RoundDurationId(m_txPsdus[2].header.GetDuration() - sifs - m_txPsdus[3].txDuration),
679 "Duration/ID of the Ack must be derived from that of the previous frame");
680
681 // the AP sends a frame to STA2
682 tEnd = m_txPsdus[3].txStart + m_txPsdus[3].txDuration;
683 tStart = m_txPsdus[4].txStart;
684
685 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second frame sent too early");
686 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second frame sent too late");
687 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.IsQosData(), true, "Expected a QoS data frame");
688 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.GetAddr1(),
689 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
690 "Expected a frame sent by the AP to the second station");
692 {
694 rtsCtsThreshold,
695 "PSDU size expected not to exceed length based RTS/CTS threshold");
696 }
697 else
698 {
700 m_txPsdus[4].txDuration,
701 rtsCtsTxDurationThresh,
702 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
703 }
704 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[4].header.GetDuration(),
705 RoundDurationId(m_apTxopLimit - (m_txPsdus[4].txStart - txopStart) -
706 m_txPsdus[4].txDuration),
707 "Duration/ID of the second frame does not cover the remaining TXOP");
708
709 // STA2 receives a corrupted frame and hence it does not send the Ack. When the AckTimeout
710 // expires, the AP performs PIFS recovery or invoke backoff, without terminating the TXOP,
711 // because a non-initial frame of the TXOP failed
712 auto apStationManager = apDev->GetRemoteStationManager(SINGLE_LINK_OP_ID);
713 auto staAddress = DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress();
714 auto ackTxVector = apStationManager->GetAckTxVector(staAddress, m_txPsdus[4].txVector);
715 tEnd = m_txPsdus[4].txStart + m_txPsdus[4].txDuration + sifs + slot +
716 WifiPhy::CalculatePhyPreambleAndHeaderDuration(ackTxVector); // AckTimeout
717 tStart = m_txPsdus[5].txStart;
718
719 if (m_pifsRecovery)
720 {
721 NS_TEST_EXPECT_MSG_EQ(tEnd + sifs + slot,
722 tStart,
723 "Second frame must have been sent after a PIFS");
724 }
725 else
726 {
728 tStart - tEnd,
729 sifs + aifsn * slot,
730 "Less than AIFS elapsed between AckTimeout and the next transmission");
732 tStart - tEnd,
733 sifs + aifsn * slot + (2 * (cwMin + 1) - 1) * slot,
734 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
735 }
736 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[5].header.IsQosData(), true, "Expected a QoS data frame");
737 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[5].header.GetAddr1(),
738 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
739 "Expected a frame sent by the AP to the second station");
741 {
743 rtsCtsThreshold,
744 "PSDU size expected not to exceed length based RTS/CTS threshold");
745 }
746 else
747 {
749 m_txPsdus[5].txDuration,
750 rtsCtsTxDurationThresh,
751 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
752 }
753 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[5].header.GetDuration(),
754 RoundDurationId(m_apTxopLimit - (m_txPsdus[5].txStart - txopStart) -
755 m_txPsdus[5].txDuration),
756 "Duration/ID of the second frame does not cover the remaining TXOP");
757
758 // a Normal Ack is then sent by STA2
759 tEnd = m_txPsdus[5].txStart + m_txPsdus[5].txDuration;
760 tStart = m_txPsdus[6].txStart;
761
762 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
763 tStart,
764 "Ack in response to the second frame sent too early");
766 tEnd + sifs + tolerance,
767 "Ack in response to the second frame sent too late");
768 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[6].header.IsAck(), true, "Expected a Normal Ack");
769 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[6].header.GetAddr1(),
770 apDev->GetMac()->GetAddress(),
771 "Expected a Normal Ack sent to the AP");
773 m_txPsdus[6].header.GetDuration(),
774 RoundDurationId(m_txPsdus[5].header.GetDuration() - sifs - m_txPsdus[6].txDuration),
775 "Duration/ID of the Ack must be derived from that of the previous frame");
776
777 // the AP sends a frame to STA3
778 tEnd = m_txPsdus[6].txStart + m_txPsdus[6].txDuration;
779 tStart = m_txPsdus[7].txStart;
780
781 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third frame sent too early");
782 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third frame sent too late");
783 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[7].header.IsQosData(), true, "Expected a QoS data frame");
784 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[7].header.GetAddr1(),
785 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
786 "Expected a frame sent by the AP to the third station");
788 {
790 rtsCtsThreshold,
791 "PSDU size expected not to exceed length based RTS/CTS threshold");
792 }
793 else
794 {
796 m_txPsdus[7].txDuration,
797 rtsCtsTxDurationThresh,
798 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
799 }
800 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[7].header.GetDuration(),
801 RoundDurationId(m_apTxopLimit - (m_txPsdus[7].txStart - txopStart) -
802 m_txPsdus[7].txDuration),
803 "Duration/ID of the third frame does not cover the remaining TXOP");
804
805 // a Normal Ack is then sent by STA3
806 tEnd = m_txPsdus[7].txStart + m_txPsdus[7].txDuration;
807 tStart = m_txPsdus[8].txStart;
808
809 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the third frame sent too early");
811 tEnd + sifs + tolerance,
812 "Ack in response to the third frame sent too late");
813 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[8].header.IsAck(), true, "Expected a Normal Ack");
814 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[8].header.GetAddr1(),
815 apDev->GetMac()->GetAddress(),
816 "Expected a Normal Ack sent to the AP");
818 m_txPsdus[8].header.GetDuration(),
819 RoundDurationId(m_txPsdus[7].header.GetDuration() - sifs - m_txPsdus[8].txDuration),
820 "Duration/ID of the Ack must be derived from that of the previous frame");
821
822 // the AP sends another frame to STA2, which is only protected if ProtectedIfResponded is true,
823 // because its size/duration exceeds the threshold but STA2 has already responded to the AP in
824 // this TXOP
826 {
827 tEnd = m_txPsdus[8].txStart + m_txPsdus[8].txDuration;
828 tStart = m_txPsdus[9].txStart;
829
830 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "RTS before fourth frame sent too early");
832 tEnd + sifs + tolerance,
833 "RTS before fourth frame sent too late");
834 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.IsRts(), true, "Expected an RTS frame");
836 m_txPsdus[9].header.GetAddr1(),
837 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
838 "Expected an RTS frame sent by the AP to the second station");
840 m_txPsdus[9].header.GetDuration(),
841 RoundDurationId(m_apTxopLimit - (m_txPsdus[9].txStart - txopStart) -
842 m_txPsdus[9].txDuration),
843 "Duration/ID of the RTS before the fourth frame does not cover the remaining TXOP");
844
845 // a CTS is sent by STA2
846 tEnd = m_txPsdus[9].txStart + m_txPsdus[9].txDuration;
847 tStart = m_txPsdus[10].txStart;
848
849 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
850 tStart,
851 "CTS in response to RTS before the fourth frame sent too early");
853 tEnd + sifs + tolerance,
854 "CTS in response to RTS before the fourth frame sent too late");
855 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.IsCts(), true, "Expected a CTS");
856 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.GetAddr1(),
857 apDev->GetMac()->GetAddress(),
858 "Expected a CTS frame sent to the AP");
860 m_txPsdus[10].header.GetDuration(),
861 RoundDurationId(m_txPsdus[9].header.GetDuration() - sifs - m_txPsdus[10].txDuration),
862 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
863
864 // the AP sends another frame to STA2
865 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
866 tStart = m_txPsdus[11].txStart;
867
868 // remove RTS and CTS so that indices are aligned with the ProtectedIfResponded true case
869 m_txPsdus.erase(std::next(m_txPsdus.cbegin(), 9), std::next(m_txPsdus.cbegin(), 11));
870 }
871 else
872 {
873 // the AP sends another frame to STA2
874 tEnd = m_txPsdus[8].txStart + m_txPsdus[8].txDuration;
875 tStart = m_txPsdus[9].txStart;
876 }
877
878 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Fourth frame sent too early");
879 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Fourth frame sent too late");
880 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.IsQosData(), true, "Expected a QoS data frame");
881 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.GetAddr1(),
882 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
883 "Expected a frame sent by the AP to the second station");
885 {
887 rtsCtsThreshold,
888 "PSDU size expected to exceed length based RTS/CTS threshold");
889 }
890 else
891 {
892 NS_TEST_EXPECT_MSG_GT(m_txPsdus[9].txDuration,
893 rtsCtsTxDurationThresh,
894 "PSDU duration expected to exceed duration based RTS/CTS threshold");
895 }
896 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[9].header.GetDuration(),
897 RoundDurationId(m_apTxopLimit - (m_txPsdus[9].txStart - txopStart) -
898 m_txPsdus[9].txDuration),
899 "Duration/ID of the fourth frame does not cover the remaining TXOP");
900
901 std::string ack(m_nonHt ? "Normal Ack" : "Block Ack");
902
903 // a Normal/Block Ack is then sent by STA1
904 tEnd = m_txPsdus[9].txStart + m_txPsdus[9].txDuration;
905 tStart = m_txPsdus[10].txStart;
906
907 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
908 tStart,
909 ack << " in response to the fourth QoS data frame sent too early");
911 tEnd + sifs + tolerance,
912 ack << " in response to the fourth QoS data frame sent too late");
914 (m_nonHt ? m_txPsdus[10].header.IsAck() : m_txPsdus[10].header.IsBlockAck()),
915 true,
916 "Expected a " << ack);
917 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[10].header.GetAddr1(),
918 apDev->GetMac()->GetAddress(),
919 "Expected a " << ack << " sent to the AP");
921 m_txPsdus[10].header.GetDuration(),
922 RoundDurationId(m_txPsdus[9].header.GetDuration() - sifs - m_txPsdus[10].txDuration),
923 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
924
925 // the TXOP limit is such that enough time for sending a CF-End frame remains
926 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
927 tStart = m_txPsdus[11].txStart;
928
929 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
930 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
931 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.IsCfEnd(), true, "Expected a CF-End frame");
932 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[11].header.GetDuration(),
933 Seconds(0),
934 "Duration/ID must be set to 0 for CF-End frames");
935
936 // the CF-End frame resets the NAV on STA1, which can now transmit
937 tEnd = m_txPsdus[11].txStart + m_txPsdus[11].txDuration;
938 tStart = m_txPsdus[12].txStart;
939
940 NS_TEST_EXPECT_MSG_GT_OR_EQ(tStart - tEnd,
941 sifs + m_staAifsn * slot,
942 "Less than AIFS elapsed between two TXOPs");
943 NS_TEST_EXPECT_MSG_LT_OR_EQ(tStart - tEnd,
944 sifs + m_staAifsn * slot + m_staCwMin * slot + tolerance,
945 "More than AIFS+BO elapsed between two TXOPs");
946 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[12].header.IsQosData(), true, "Expected a QoS data frame");
947 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[12].header.GetAddr1(),
948 apDev->GetMac()->GetAddress(),
949 "Expected a frame sent by the first station to the AP");
951 {
953 rtsCtsThreshold,
954 "PSDU size expected not to exceed length based RTS/CTS threshold");
955 }
956 else
957 {
959 m_txPsdus[12].txDuration,
960 rtsCtsTxDurationThresh,
961 "PSDU duration expected not to exceed duration based RTS/CTS threshold");
962 }
964 m_txPsdus[12].header.GetDuration(),
965 RoundDurationId(m_staTxopLimit - m_txPsdus[12].txDuration),
966 "Duration/ID of the frame sent by the first station does not cover the remaining TXOP");
967
968 // a Normal Ack is then sent by the AP
969 tEnd = m_txPsdus[12].txStart + m_txPsdus[12].txDuration;
970 tStart = m_txPsdus[13].txStart;
971
972 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Ack sent too early");
973 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Ack sent too late");
974 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.IsAck(), true, "Expected a Normal Ack");
975 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[13].header.GetAddr1(),
976 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
977 "Expected a Normal Ack sent to the first station");
979 m_txPsdus[13].header.GetDuration(),
980 RoundDurationId(m_txPsdus[12].header.GetDuration() - sifs - m_txPsdus[13].txDuration),
981 "Duration/ID of the Ack must be derived from that of the previous frame");
982
983 // the TXOP limit is such that enough time for sending a CF-End frame remains
984 tEnd = m_txPsdus[13].txStart + m_txPsdus[13].txDuration;
985 tStart = m_txPsdus[14].txStart;
986
987 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
988 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
989 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[14].header.IsCfEnd(), true, "Expected a CF-End frame");
990 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[14].header.GetDuration(),
991 Seconds(0),
992 "Duration/ID must be set to 0 for CF-End frames");
993
994 /*
995 * Verify that the Duration/ID of RTS/CTS frames is set correctly, that the TXOP holder is
996 * kept and allows stations to ignore NAV properly and that the CF-End Frame is not sent if
997 * not enough time remains. If SingleRtsPerTxop is set to true, only one RTS/CTS is sent.
998 *
999 * |---------------------------------------------NAV---------------------------------->|
1000 * | |-----------------------------------------NAV------------------------------->| |
1001 * | |-------------------------------------NAV---------------------------->| | | |
1002 * |---------------------------------NAV------------------------->| | | | |
1003 * |-----------------------------NAV---------------------->| | | | | |
1004 * |-------------------------NAV------------------->| | | | | | |
1005 * |---------------------NAV---------------->| | | | | | | |
1006 * |-----------------NAV------------->| | | | | | | | |
1007 * |-------------NAV---------->| | | | | | | | | |
1008 * |---------NAV------->| | | | | | | | | | |
1009 * |-----NAV---->| | | | | | | | | | | |
1010 * |-NAV->|
1011 * |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---|
1012 * |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack|
1013 * ----------------------------------------------------------------------------------------------------
1014 * From: AP STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3
1015 * To: STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3 AP
1016 */
1017
1018 // the first frame is an RTS frame sent by the AP to STA1
1019 txopStart = m_txPsdus[15].txStart;
1020
1021 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[15].header.IsRts(), true, "Expected an RTS frame");
1022 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[15].header.GetAddr1(),
1023 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1024 "Expected an RTS frame sent by the AP to the first station");
1025 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[15].header.GetDuration(),
1026 RoundDurationId(m_apTxopLimit - m_txPsdus[15].txDuration),
1027 "Duration/ID of the first RTS frame must cover the whole TXOP");
1028
1029 // a CTS is sent by STA1
1030 tEnd = m_txPsdus[15].txStart + m_txPsdus[15].txDuration;
1031 tStart = m_txPsdus[16].txStart;
1032
1033 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1034 tStart,
1035 "CTS in response to the first RTS frame sent too early");
1036 NS_TEST_EXPECT_MSG_LT(tStart,
1037 tEnd + sifs + tolerance,
1038 "CTS in response to the first RTS frame sent too late");
1039 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[16].header.IsCts(), true, "Expected a CTS");
1040 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[16].header.GetAddr1(),
1041 apDev->GetMac()->GetAddress(),
1042 "Expected a CTS frame sent to the AP");
1044 m_txPsdus[16].header.GetDuration(),
1045 RoundDurationId(m_txPsdus[15].header.GetDuration() - sifs - m_txPsdus[16].txDuration),
1046 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1047
1048 // the AP sends a frame to STA1
1049 tEnd = m_txPsdus[16].txStart + m_txPsdus[16].txDuration;
1050 tStart = m_txPsdus[17].txStart;
1051
1052 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "First QoS data frame sent too early");
1053 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "First QoS data frame sent too late");
1054 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[17].header.IsQosData(), true, "Expected a QoS data frame");
1055 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[17].header.GetAddr1(),
1056 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
1057 "Expected a frame sent by the AP to the first station");
1059 {
1061 rtsCtsThreshold,
1062 "PSDU size expected to exceed length based RTS/CTS threshold");
1063 }
1064 else
1065 {
1066 NS_TEST_EXPECT_MSG_GT(m_txPsdus[17].txDuration,
1067 rtsCtsTxDurationThresh,
1068 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1069 }
1071 m_txPsdus[17].header.GetDuration(),
1072 RoundDurationId(m_apTxopLimit - (m_txPsdus[17].txStart - txopStart) -
1073 m_txPsdus[17].txDuration),
1074 "Duration/ID of the first QoS data frame does not cover the remaining TXOP");
1075
1076 // a Normal/Block Ack is then sent by STA1
1077 tEnd = m_txPsdus[17].txStart + m_txPsdus[17].txDuration;
1078 tStart = m_txPsdus[18].txStart;
1079
1080 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1081 tStart,
1082 ack << " in response to the first QoS data frame sent too early");
1083 NS_TEST_EXPECT_MSG_LT(tStart,
1084 tEnd + sifs + tolerance,
1085 ack << " in response to the first QoS data frame sent too late");
1087 (m_nonHt ? m_txPsdus[18].header.IsAck() : m_txPsdus[18].header.IsBlockAck()),
1088 true,
1089 "Expected a " << ack);
1090 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[18].header.GetAddr1(),
1091 apDev->GetMac()->GetAddress(),
1092 "Expected a " << ack << " sent to the AP");
1094 m_txPsdus[18].header.GetDuration(),
1095 RoundDurationId(m_txPsdus[17].header.GetDuration() - sifs - m_txPsdus[18].txDuration),
1096 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1097
1098 std::size_t idx = 18;
1099
1100 if (!m_singleRtsPerTxop)
1101 {
1102 // An RTS frame is sent by the AP to STA2
1103 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1104 ++idx;
1105 tStart = m_txPsdus[idx].txStart;
1106
1107 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second RTS frame sent too early");
1108 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second RTS frame sent too late");
1109 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsRts(), true, "Expected an RTS frame");
1111 m_txPsdus[idx].header.GetAddr1(),
1112 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
1113 "Expected an RTS frame sent by the AP to the second station");
1114 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetDuration(),
1115 RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1116 m_txPsdus[idx].txDuration),
1117 "Duration/ID of the second RTS frame must cover the whole TXOP");
1118
1119 // a CTS is sent by STA2 (which ignores the NAV)
1120 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1121 tStart = m_txPsdus[idx + 1].txStart;
1122
1123 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1124 tStart,
1125 "CTS in response to the second RTS frame sent too early");
1126 NS_TEST_EXPECT_MSG_LT(tStart,
1127 tEnd + sifs + tolerance,
1128 "CTS in response to the second RTS frame sent too late");
1129 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.IsCts(), true, "Expected a CTS");
1130 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1131 apDev->GetMac()->GetAddress(),
1132 "Expected a CTS frame sent to the AP");
1134 m_txPsdus[idx + 1].header.GetDuration(),
1135 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs -
1136 m_txPsdus[idx + 1].txDuration),
1137 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1138
1139 ++idx;
1140 }
1141
1142 // the AP sends a frame to STA2
1143 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1144 ++idx;
1145 tStart = m_txPsdus[idx].txStart;
1146
1147 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Second QoS data frame sent too early");
1148 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second QoS data frame sent too late");
1149 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsQosData(), true, "Expected a QoS data frame");
1150 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetAddr1(),
1151 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
1152 "Expected a frame sent by the AP to the second station");
1154 {
1156 rtsCtsThreshold,
1157 "PSDU size expected to exceed length based RTS/CTS threshold");
1158 }
1159 else
1160 {
1161 NS_TEST_EXPECT_MSG_GT(m_txPsdus[idx].txDuration,
1162 rtsCtsTxDurationThresh,
1163 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1164 }
1166 m_txPsdus[idx].header.GetDuration(),
1167 RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1168 m_txPsdus[idx].txDuration),
1169 "Duration/ID of the second QoS data frame does not cover the remaining TXOP");
1170
1171 // a Normal/Block Ack is then sent by STA2
1172 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1173 tStart = m_txPsdus[idx + 1].txStart;
1174
1175 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1176 tStart,
1177 ack << " in response to the second QoS data frame sent too early");
1178 NS_TEST_EXPECT_MSG_LT(tStart,
1179 tEnd + sifs + tolerance,
1180 ack << " in response to the second QoS data frame sent too late");
1182 (m_nonHt ? m_txPsdus[idx + 1].header.IsAck() : m_txPsdus[idx + 1].header.IsBlockAck()),
1183 true,
1184 "Expected a " << ack);
1185 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1186 apDev->GetMac()->GetAddress(),
1187 "Expected a " << ack << " sent to the AP");
1189 m_txPsdus[idx + 1].header.GetDuration(),
1190 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs - m_txPsdus[idx + 1].txDuration),
1191 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1192 ++idx;
1193
1194 if (!m_singleRtsPerTxop)
1195 {
1196 // An RTS frame is sent by the AP to STA3
1197 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1198 ++idx;
1199 tStart = m_txPsdus[idx].txStart;
1200
1201 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third RTS frame sent too early");
1202 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third RTS frame sent too late");
1203 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsRts(), true, "Expected an RTS frame");
1205 m_txPsdus[idx].header.GetAddr1(),
1206 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
1207 "Expected an RTS frame sent by the AP to the third station");
1208 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetDuration(),
1209 RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1210 m_txPsdus[idx].txDuration),
1211 "Duration/ID of the third RTS frame must cover the whole TXOP");
1212
1213 // a CTS is sent by STA3 (which ignores the NAV)
1214 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1215 tStart = m_txPsdus[idx + 1].txStart;
1216
1217 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1218 tStart,
1219 "CTS in response to the third RTS frame sent too early");
1220 NS_TEST_EXPECT_MSG_LT(tStart,
1221 tEnd + sifs + tolerance,
1222 "CTS in response to the third RTS frame sent too late");
1223 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.IsCts(), true, "Expected a CTS");
1224 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1225 apDev->GetMac()->GetAddress(),
1226 "Expected a CTS frame sent to the AP");
1228 m_txPsdus[idx + 1].header.GetDuration(),
1229 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs -
1230 m_txPsdus[idx + 1].txDuration),
1231 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
1232 ++idx;
1233 }
1234
1235 // the AP sends a frame to STA3
1236 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1237 ++idx;
1238 tStart = m_txPsdus[idx].txStart;
1239
1240 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "Third QoS data frame sent too early");
1241 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third QoS data frame sent too late");
1242 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsQosData(), true, "Expected a QoS data frame");
1243 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetAddr1(),
1244 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
1245 "Expected a frame sent by the AP to the third station");
1247 {
1249 rtsCtsThreshold,
1250 "PSDU size expected to exceed length based RTS/CTS threshold");
1251 }
1252 else
1253 {
1254 NS_TEST_EXPECT_MSG_GT(m_txPsdus[idx].txDuration,
1255 rtsCtsTxDurationThresh,
1256 "PSDU duration expected to exceed duration based RTS/CTS threshold");
1257 }
1259 m_txPsdus[idx].header.GetDuration(),
1260 RoundDurationId(m_apTxopLimit - (m_txPsdus[idx].txStart - txopStart) -
1261 m_txPsdus[idx].txDuration),
1262 "Duration/ID of the third QoS data frame does not cover the remaining TXOP");
1263
1264 // a Normal/Block Ack is then sent by STA3
1265 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1266 tStart = m_txPsdus[idx + 1].txStart;
1267
1268 NS_TEST_EXPECT_MSG_LT(tEnd + sifs,
1269 tStart,
1270 ack << " in response to the third QoS data frame sent too early");
1271 NS_TEST_EXPECT_MSG_LT(tStart,
1272 tEnd + sifs + tolerance,
1273 ack << " in response to the third QoS data frame sent too late");
1275 (m_nonHt ? m_txPsdus[idx + 1].header.IsAck() : m_txPsdus[idx + 1].header.IsBlockAck()),
1276 true,
1277 "Expected a " << ack);
1278 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx + 1].header.GetAddr1(),
1279 apDev->GetMac()->GetAddress(),
1280 "Expected a " << ack << " sent to the AP");
1282 m_txPsdus[idx + 1].header.GetDuration(),
1283 RoundDurationId(m_txPsdus[idx].header.GetDuration() - sifs - m_txPsdus[idx + 1].txDuration),
1284 "Duration/ID of the " << ack << " must be derived from that of the previous frame");
1285 ++idx;
1286
1287 // there is no time remaining for sending a CF-End frame if SingleRtsPerTxop is false. This is
1288 // verified by checking that 25 frames are transmitted (done at the beginning of this method)
1290 {
1291 tEnd = m_txPsdus[idx].txStart + m_txPsdus[idx].txDuration;
1292 ++idx;
1293 tStart = m_txPsdus[idx].txStart;
1294
1295 NS_TEST_EXPECT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
1296 NS_TEST_EXPECT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
1297 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.IsCfEnd(), true, "Expected a CF-End frame");
1298 NS_TEST_EXPECT_MSG_EQ(m_txPsdus[idx].header.GetDuration(),
1299 Seconds(0),
1300 "Duration/ID must be set to 0 for CF-End frames");
1301 }
1302
1303 // Expected received packets:
1304 // - 4 DL packets (without RTS/CTS) if non-HT, 5 DL packets (without RTS/CTS) if HE
1305 // - 1 UL packet
1306 // - 3 DL packets (with RTS/CTS) if non-HT, 6 DL packets (with RTS/CTS) if HE
1307 NS_TEST_EXPECT_MSG_EQ(m_received, (m_nonHt ? 8 : 12), "Unexpected number of packets received");
1308}
1309
1310/**
1311 * @ingroup wifi-test
1312 * @ingroup tests
1313 *
1314 * @brief wifi TXOP Test Suite
1315 */
1317{
1318 public:
1320};
1321
1323 : TestSuite("wifi-txop", Type::UNIT)
1324{
1325 for (const auto nonHt : {true, false})
1326 {
1327 AddTestCase(new WifiTxopTest({.nonHt = nonHt,
1328 .pifsRecovery = true,
1329 .singleRtsPerTxop = false,
1330 .lengthBasedRtsCtsThresh = false,
1331 .protectedIfResponded = true}),
1332 TestCase::Duration::QUICK);
1333 AddTestCase(new WifiTxopTest({.nonHt = nonHt,
1334 .pifsRecovery = false,
1335 .singleRtsPerTxop = true,
1336 .lengthBasedRtsCtsThresh = false,
1337 .protectedIfResponded = false}),
1338 TestCase::Duration::QUICK);
1339 AddTestCase(new WifiTxopTest({.nonHt = nonHt,
1340 .pifsRecovery = true,
1341 .singleRtsPerTxop = true,
1342 .lengthBasedRtsCtsThresh = true,
1343 .protectedIfResponded = true}),
1344 TestCase::Duration::QUICK);
1345 }
1346}
1347
1348static 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 to use PIFS recovery
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)
bool m_nonHt
whether to use 802.11a or 802.11ax
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 to use single RTS per TXOP
bool m_protectedIfResponded
whether a STA is protected if it responds to the AP
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
whether to use length based RTS/CTS threshold
Time m_staTxopLimit
TXOP limit for STAs (AC BE)
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:560
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:1431
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:111
AttributeValue implementation for WifiMode.
Definition wifi-mode.h:243
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1587
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition wifi-phy.cc:1580
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:883
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:967
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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:1368
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1380
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1344
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1356
@ 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
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:272
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
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 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
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