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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Stefano Avallone <stavallo@unina.it>
18 */
19
20#include "ns3/ap-wifi-mac.h"
21#include "ns3/boolean.h"
22#include "ns3/config.h"
23#include "ns3/mobility-helper.h"
24#include "ns3/packet-socket-client.h"
25#include "ns3/packet-socket-helper.h"
26#include "ns3/packet-socket-server.h"
27#include "ns3/packet.h"
28#include "ns3/pointer.h"
29#include "ns3/qos-txop.h"
30#include "ns3/qos-utils.h"
31#include "ns3/rng-seed-manager.h"
32#include "ns3/single-model-spectrum-channel.h"
33#include "ns3/spectrum-wifi-helper.h"
34#include "ns3/string.h"
35#include "ns3/test.h"
36#include "ns3/wifi-mac-header.h"
37#include "ns3/wifi-net-device.h"
38#include "ns3/wifi-ppdu.h"
39#include "ns3/wifi-psdu.h"
40
41using namespace ns3;
42
43/**
44 * \ingroup wifi-test
45 * \ingroup tests
46 *
47 * \brief Test TXOP rules
48 *
49 *
50 */
51class WifiTxopTest : public TestCase
52{
53 public:
54 /**
55 * Constructor
56 * \param pifsRecovery whether PIFS recovery is used after failure of a non-initial frame
57 */
58 WifiTxopTest(bool pifsRecovery);
59 ~WifiTxopTest() override;
60
61 /**
62 * Function to trace packets received by the server application
63 * \param context the context
64 * \param p the packet
65 * \param addr the address
66 */
67 void L7Receive(std::string context, Ptr<const Packet> p, const Address& addr);
68 /**
69 * Callback invoked when PHY receives a PSDU to transmit
70 * \param context the context
71 * \param psduMap the PSDU map
72 * \param txVector the TX vector
73 * \param txPowerW the tx power in Watts
74 */
75 void Transmit(std::string context,
76 WifiConstPsduMap psduMap,
77 WifiTxVector txVector,
78 double txPowerW);
79 /**
80 * Check correctness of transmitted frames
81 */
82 void CheckResults();
83
84 private:
85 void DoRun() override;
86
87 /// Information about transmitted frames
88 struct FrameInfo
89 {
90 Time txStart; ///< Frame start TX time
91 Time txDuration; ///< Frame TX duration
92 WifiMacHeader header; ///< Frame MAC header
93 WifiTxVector txVector; ///< TX vector used to transmit the frame
94 };
95
96 uint16_t m_nStations; ///< number of stations
97 NetDeviceContainer m_staDevices; ///< container for stations' NetDevices
98 NetDeviceContainer m_apDevices; ///< container for AP's NetDevice
99 std::vector<FrameInfo> m_txPsdus; ///< transmitted PSDUs
100 Time m_txopLimit; ///< TXOP limit
101 uint8_t m_aifsn; ///< AIFSN for BE
102 uint32_t m_cwMin; ///< CWmin for BE
103 uint16_t m_received; ///< number of packets received by the stations
104 bool m_pifsRecovery; ///< whether to use PIFS recovery
105};
106
108 : TestCase("Check correct operation within TXOPs"),
109 m_nStations(3),
110 m_txopLimit(MicroSeconds(4768)),
111 m_received(0),
112 m_pifsRecovery(pifsRecovery)
113{
114}
115
117{
118}
119
120void
121WifiTxopTest::L7Receive(std::string context, Ptr<const Packet> p, const Address& addr)
122{
123 if (p->GetSize() >= 500)
124 {
125 m_received++;
126 }
127}
128
129void
130WifiTxopTest::Transmit(std::string context,
131 WifiConstPsduMap psduMap,
132 WifiTxVector txVector,
133 double txPowerW)
134{
135 // Log all transmitted frames that are not beacon frames and have been transmitted
136 // after 400ms (so as to skip association requests/responses)
137 if (!psduMap.begin()->second->GetHeader(0).IsBeacon() && Simulator::Now() > MilliSeconds(400))
138 {
139 m_txPsdus.push_back({Simulator::Now(),
141 psduMap[SU_STA_ID]->GetHeader(0),
142 txVector});
143 }
144
145 // Print all the transmitted frames if the test is executed through test-runner
146 std::cout << Simulator::Now() << " " << psduMap.begin()->second->GetHeader(0).GetTypeString()
147 << " seq " << psduMap.begin()->second->GetHeader(0).GetSequenceNumber() << " to "
148 << psduMap.begin()->second->GetAddr1() << " TX duration "
150 << " duration/ID " << psduMap.begin()->second->GetHeader(0).GetDuration()
151 << std::endl;
152}
153
154void
156{
159 int64_t streamNumber = 100;
160
161 NodeContainer wifiApNode;
162 wifiApNode.Create(1);
163
164 NodeContainer wifiStaNodes;
165 wifiStaNodes.Create(m_nStations);
166
167 Ptr<SingleModelSpectrumChannel> spectrumChannel = CreateObject<SingleModelSpectrumChannel>();
168 Ptr<FriisPropagationLossModel> lossModel = CreateObject<FriisPropagationLossModel>();
169 spectrumChannel->AddPropagationLossModel(lossModel);
171 CreateObject<ConstantSpeedPropagationDelayModel>();
172 spectrumChannel->SetPropagationDelayModel(delayModel);
173
175 phy.SetChannel(spectrumChannel);
176
177 Config::SetDefault("ns3::QosFrameExchangeManager::PifsRecovery", BooleanValue(m_pifsRecovery));
178 Config::SetDefault("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue(1900));
179
180 WifiHelper wifi;
181 wifi.SetStandard(WIFI_STANDARD_80211a);
182 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
183 "DataMode",
184 StringValue("OfdmRate12Mbps"),
185 "ControlMode",
186 StringValue("OfdmRate6Mbps"));
187
188 WifiMacHelper mac;
189 mac.SetType("ns3::StaWifiMac",
190 "QosSupported",
191 BooleanValue(true),
192 "Ssid",
193 SsidValue(Ssid("non-existent-ssid")));
194
195 m_staDevices = wifi.Install(phy, mac, wifiStaNodes);
196
197 mac.SetType("ns3::ApWifiMac",
198 "QosSupported",
199 BooleanValue(true),
200 "Ssid",
201 SsidValue(Ssid("wifi-txop-ssid")),
202 "BeaconInterval",
203 TimeValue(MicroSeconds(102400)),
204 "EnableBeaconJitter",
205 BooleanValue(false));
206
207 m_apDevices = wifi.Install(phy, mac, wifiApNode);
208
209 // schedule association requests at different times. One station's SSID is
210 // set to the correct value before initialization, so that such a station
211 // starts the scanning procedure by looking for the correct SSID
212 Ptr<WifiNetDevice> dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(0));
213 dev->GetMac()->SetSsid(Ssid("wifi-txop-ssid"));
214
215 for (uint16_t i = 1; i < m_nStations; i++)
216 {
217 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(i));
220 dev->GetMac(),
221 Ssid("wifi-txop-ssid"));
222 }
223
224 // Assign fixed streams to random variables in use
225 wifi.AssignStreams(m_apDevices, streamNumber);
226
227 MobilityHelper mobility;
228 Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
229
230 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
231 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
232 positionAlloc->Add(Vector(0.0, 1.0, 0.0));
233 positionAlloc->Add(Vector(-1.0, 0.0, 0.0));
234 mobility.SetPositionAllocator(positionAlloc);
235
236 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
237 mobility.Install(wifiApNode);
238 mobility.Install(wifiStaNodes);
239
240 // set the TXOP limit on BE AC
241 dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
242 PointerValue ptr;
243 dev->GetMac()->GetAttribute("BE_Txop", ptr);
244 ptr.Get<QosTxop>()->SetTxopLimit(m_txopLimit);
245 m_aifsn = ptr.Get<QosTxop>()->Txop::GetAifsn();
246 m_cwMin = ptr.Get<QosTxop>()->Txop::GetMinCw();
247
248 PacketSocketHelper packetSocket;
249 packetSocket.Install(wifiApNode);
250 packetSocket.Install(wifiStaNodes);
251
252 // DL frames
253 for (uint16_t i = 0; i < m_nStations; i++)
254 {
255 PacketSocketAddress socket;
256 socket.SetSingleDevice(m_apDevices.Get(0)->GetIfIndex());
257 socket.SetPhysicalAddress(m_staDevices.Get(i)->GetAddress());
258 socket.SetProtocol(1);
259
260 // Send one QoS data frame (not protected by RTS/CTS) to each station
261 Ptr<PacketSocketClient> client1 = CreateObject<PacketSocketClient>();
262 client1->SetAttribute("PacketSize", UintegerValue(500));
263 client1->SetAttribute("MaxPackets", UintegerValue(1));
264 client1->SetAttribute("Interval", TimeValue(MicroSeconds(1)));
265 client1->SetRemote(socket);
266 wifiApNode.Get(0)->AddApplication(client1);
267 client1->SetStartTime(MilliSeconds(410));
268 client1->SetStopTime(Seconds(1.0));
269
270 // Send one QoS data frame (protected by RTS/CTS) to each station
271 Ptr<PacketSocketClient> client2 = CreateObject<PacketSocketClient>();
272 client2->SetAttribute("PacketSize", UintegerValue(2000));
273 client2->SetAttribute("MaxPackets", UintegerValue(1));
274 client2->SetAttribute("Interval", TimeValue(MicroSeconds(1)));
275 client2->SetRemote(socket);
276 wifiApNode.Get(0)->AddApplication(client2);
277 client2->SetStartTime(MilliSeconds(520));
278 client2->SetStopTime(Seconds(1.0));
279
280 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
281 server->SetLocal(socket);
282 wifiStaNodes.Get(i)->AddApplication(server);
283 server->SetStartTime(Seconds(0.0));
284 server->SetStopTime(Seconds(1.0));
285 }
286
287 // The AP does not correctly receive the Ack sent in response to the QoS
288 // data frame sent to the first station
289 Ptr<ReceiveListErrorModel> apPem = CreateObject<ReceiveListErrorModel>();
290 apPem->SetList({9});
291 dev = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
292 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(apPem);
293
294 // The second station does not correctly receive the first QoS
295 // data frame sent by the AP
296 Ptr<ReceiveListErrorModel> sta2Pem = CreateObject<ReceiveListErrorModel>();
297 sta2Pem->SetList({24});
298 dev = DynamicCast<WifiNetDevice>(m_staDevices.Get(1));
299 dev->GetMac()->GetWifiPhy()->SetPostReceptionErrorModel(sta2Pem);
300
301 // UL Traffic (the first station sends one frame to the AP)
302 {
303 PacketSocketAddress socket;
304 socket.SetSingleDevice(m_staDevices.Get(0)->GetIfIndex());
305 socket.SetPhysicalAddress(m_apDevices.Get(0)->GetAddress());
306 socket.SetProtocol(1);
307
308 Ptr<PacketSocketClient> client = CreateObject<PacketSocketClient>();
309 client->SetAttribute("PacketSize", UintegerValue(1500));
310 client->SetAttribute("MaxPackets", UintegerValue(1));
311 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
312 client->SetRemote(socket);
313 wifiStaNodes.Get(0)->AddApplication(client);
314 client->SetStartTime(MilliSeconds(412));
315 client->SetStopTime(Seconds(1.0));
316
317 Ptr<PacketSocketServer> server = CreateObject<PacketSocketServer>();
318 server->SetLocal(socket);
319 wifiApNode.Get(0)->AddApplication(server);
320 server->SetStartTime(Seconds(0.0));
321 server->SetStopTime(Seconds(1.0));
322 }
323
324 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx",
326 // Trace PSDUs passed to the PHY on all devices
327 Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxPsduBegin",
329
332
333 CheckResults();
334
336}
337
338void
340{
341 Time tEnd; // TX end for a frame
342 Time tStart; // TX start for the next frame
343 Time txopStart; // TXOP start time
344 Time tolerance = NanoSeconds(50); // due to propagation delay
345 Time sifs = DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetPhy()->GetSifs();
346 Time slot = DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetPhy()->GetSlot();
347 Time navEnd;
348
349 // lambda to round Duration/ID (in microseconds) up to the next higher integer
350 auto RoundDurationId = [](Time t) {
351 return MicroSeconds(ceil(static_cast<double>(t.GetNanoSeconds()) / 1000));
352 };
353
354 /*
355 * Verify the different behavior followed when an initial/non-initial frame of a TXOP
356 * fails. Also, verify that a CF-end frame is sent if enough time remains in the TXOP.
357 * The destination of failed frames is put in square brackets below.
358 *
359 * |---NAV-----till end TXOP--------->|
360 * | |----NAV--till end TXOP---->|
361 * | | |---------------------------NAV---------------------------------->| | | |
362 * |--------------------------NAV---------------------------->| | | | |
363 * |------------------------NAV----------------------->| | | | | |
364 * |-------------NAV--------------->| Start| | Start| | | |
365 * |----------NAV----------->| TXOP | | TXOP | | | Ack | |
366 * |-------NAV------->| | | | | | | | Timeout | | |
367 * |---NAV---->|
368 * |---| |---|-backoff->|---| |---| |---| |-PIFS or->|---| |---| |---| |---|
369 * |-----| |QoS| |Ack| |QoS| |Ack| |QoS| |-backoff->|QoS| |Ack| |QoS| |Ack|
370 * |CFend|
371 * ----------------------------------------------------------------------------------------------------
372 * From: AP STA1 AP STA1 AP AP STA2 AP STA3 AP
373 * To: STA1 [AP] STA1 AP [STA2] STA2 AP STA3 AP all
374 */
375
376 NS_TEST_ASSERT_MSG_EQ(m_txPsdus.size(), 25, "Expected 25 transmitted frames");
377
378 // the first frame sent after 400ms is a QoS data frame sent by the AP to STA1
379 txopStart = m_txPsdus[0].txStart;
380
381 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[0].header.IsQosData(), true, "Expected a QoS data frame");
382 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[0].header.GetAddr1(),
383 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
384 "Expected a frame sent by the AP to the first station");
385 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[0].header.GetDuration(),
386 RoundDurationId(m_txopLimit - m_txPsdus[0].txDuration),
387 "Duration/ID of the first frame must cover the whole TXOP");
388
389 // a Normal Ack is sent by STA1
390 tEnd = m_txPsdus[0].txStart + m_txPsdus[0].txDuration;
391 tStart = m_txPsdus[1].txStart;
392
393 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
395 tEnd + sifs + tolerance,
396 "Ack in response to the first frame sent too late");
397 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[1].header.IsAck(), true, "Expected a Normal Ack");
398 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[1].header.GetAddr1(),
399 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
400 "Expected a Normal Ack sent to the AP");
402 m_txPsdus[1].header.GetDuration(),
403 RoundDurationId(m_txPsdus[0].header.GetDuration() - sifs - m_txPsdus[1].txDuration),
404 "Duration/ID of the Ack must be derived from that of the first frame");
405
406 // the AP receives a corrupted Ack in response to the frame it sent, which is the initial
407 // frame of a TXOP. Hence, the TXOP is terminated and the AP retransmits the frame after
408 // invoking the backoff
409 txopStart = m_txPsdus[2].txStart;
410
411 tEnd = m_txPsdus[1].txStart + m_txPsdus[1].txDuration;
412 tStart = m_txPsdus[2].txStart;
413
415 tStart - tEnd,
416 sifs + m_aifsn * slot,
417 "Less than AIFS elapsed between AckTimeout and the next TXOP start");
419 tStart - tEnd,
420 sifs + m_aifsn * slot + (2 * (m_cwMin + 1) - 1) * slot,
421 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
422 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[2].header.IsQosData(),
423 true,
424 "Expected to retransmit a QoS data frame");
425 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[2].header.GetAddr1(),
426 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
427 "Expected to retransmit a frame to the first station");
428 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[2].header.GetDuration(),
429 RoundDurationId(m_txopLimit - m_txPsdus[2].txDuration),
430 "Duration/ID of the retransmitted frame must cover the whole TXOP");
431
432 // a Normal Ack is then sent by STA1
433 tEnd = m_txPsdus[2].txStart + m_txPsdus[2].txDuration;
434 tStart = m_txPsdus[3].txStart;
435
436 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the first frame sent too early");
438 tEnd + sifs + tolerance,
439 "Ack in response to the first frame sent too late");
440 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[3].header.IsAck(), true, "Expected a Normal Ack");
441 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[3].header.GetAddr1(),
442 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
443 "Expected a Normal Ack sent to the AP");
445 m_txPsdus[3].header.GetDuration(),
446 RoundDurationId(m_txPsdus[2].header.GetDuration() - sifs - m_txPsdus[3].txDuration),
447 "Duration/ID of the Ack must be derived from that of the previous frame");
448
449 // the AP sends a frame to STA2
450 tEnd = m_txPsdus[3].txStart + m_txPsdus[3].txDuration;
451 tStart = m_txPsdus[4].txStart;
452
453 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Second frame sent too early");
454 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second frame sent too late");
455 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[4].header.IsQosData(), true, "Expected a QoS data frame");
456 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[4].header.GetAddr1(),
457 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
458 "Expected a frame sent by the AP to the second station");
460 m_txPsdus[4].header.GetDuration(),
461 RoundDurationId(m_txopLimit - (m_txPsdus[4].txStart - txopStart) - m_txPsdus[4].txDuration),
462 "Duration/ID of the second frame does not cover the remaining TXOP");
463
464 // STA2 receives a corrupted frame and hence it does not send the Ack. When the AckTimeout
465 // expires, the AP performs PIFS recovery or invoke backoff, without terminating the TXOP,
466 // because a non-initial frame of the TXOP failed
467 tEnd = m_txPsdus[4].txStart + m_txPsdus[4].txDuration + sifs + slot +
469 tStart = m_txPsdus[5].txStart;
470
471 if (m_pifsRecovery)
472 {
473 NS_TEST_ASSERT_MSG_EQ(tEnd + sifs + slot,
474 tStart,
475 "Second frame must have been sent after a PIFS");
476 }
477 else
478 {
480 tStart - tEnd,
481 sifs + m_aifsn * slot,
482 "Less than AIFS elapsed between AckTimeout and the next transmission");
484 tStart - tEnd,
485 sifs + m_aifsn * slot + (2 * (m_cwMin + 1) - 1) * slot,
486 "More than AIFS+BO elapsed between AckTimeout and the next TXOP start");
487 }
488 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[5].header.IsQosData(), true, "Expected a QoS data frame");
489 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[5].header.GetAddr1(),
490 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
491 "Expected a frame sent by the AP to the second station");
493 m_txPsdus[5].header.GetDuration(),
494 RoundDurationId(m_txopLimit - (m_txPsdus[5].txStart - txopStart) - m_txPsdus[5].txDuration),
495 "Duration/ID of the second frame does not cover the remaining TXOP");
496
497 // a Normal Ack is then sent by STA2
498 tEnd = m_txPsdus[5].txStart + m_txPsdus[5].txDuration;
499 tStart = m_txPsdus[6].txStart;
500
501 NS_TEST_ASSERT_MSG_LT(tEnd + sifs,
502 tStart,
503 "Ack in response to the second frame sent too early");
505 tEnd + sifs + tolerance,
506 "Ack in response to the second frame sent too late");
507 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[6].header.IsAck(), true, "Expected a Normal Ack");
508 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[6].header.GetAddr1(),
509 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
510 "Expected a Normal Ack sent to the AP");
512 m_txPsdus[6].header.GetDuration(),
513 RoundDurationId(m_txPsdus[5].header.GetDuration() - sifs - m_txPsdus[6].txDuration),
514 "Duration/ID of the Ack must be derived from that of the previous frame");
515
516 // the AP sends a frame to STA3
517 tEnd = m_txPsdus[6].txStart + m_txPsdus[6].txDuration;
518 tStart = m_txPsdus[7].txStart;
519
520 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Third frame sent too early");
521 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third frame sent too late");
522 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[7].header.IsQosData(), true, "Expected a QoS data frame");
523 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[7].header.GetAddr1(),
524 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
525 "Expected a frame sent by the AP to the third station");
527 m_txPsdus[7].header.GetDuration(),
528 RoundDurationId(m_txopLimit - (m_txPsdus[7].txStart - txopStart) - m_txPsdus[7].txDuration),
529 "Duration/ID of the third frame does not cover the remaining TXOP");
530
531 // a Normal Ack is then sent by STA3
532 tEnd = m_txPsdus[7].txStart + m_txPsdus[7].txDuration;
533 tStart = m_txPsdus[8].txStart;
534
535 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Ack in response to the third frame sent too early");
537 tEnd + sifs + tolerance,
538 "Ack in response to the third frame sent too late");
539 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[8].header.IsAck(), true, "Expected a Normal Ack");
540 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[8].header.GetAddr1(),
541 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
542 "Expected a Normal Ack sent to the AP");
544 m_txPsdus[8].header.GetDuration(),
545 RoundDurationId(m_txPsdus[7].header.GetDuration() - sifs - m_txPsdus[8].txDuration),
546 "Duration/ID of the Ack must be derived from that of the previous frame");
547
548 // the TXOP limit is such that enough time for sending a CF-End frame remains
549 tEnd = m_txPsdus[8].txStart + m_txPsdus[8].txDuration;
550 tStart = m_txPsdus[9].txStart;
551
552 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
553 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
554 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[9].header.IsCfEnd(), true, "Expected a CF-End frame");
555 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[9].header.GetDuration(),
556 Seconds(0),
557 "Duration/ID must be set to 0 for CF-End frames");
558
559 // the CF-End frame resets the NAV on STA1, which can now transmit
560 tEnd = m_txPsdus[9].txStart + m_txPsdus[9].txDuration;
561 tStart = m_txPsdus[10].txStart;
562
563 NS_TEST_ASSERT_MSG_GT_OR_EQ(tStart - tEnd,
564 sifs + m_aifsn * slot,
565 "Less than AIFS elapsed between two TXOPs");
566 NS_TEST_ASSERT_MSG_LT_OR_EQ(tStart - tEnd,
567 sifs + m_aifsn * slot + m_cwMin * slot + tolerance,
568 "More than AIFS+BO elapsed between two TXOPs");
569 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[10].header.IsQosData(), true, "Expected a QoS data frame");
570 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[10].header.GetAddr1(),
571 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
572 "Expected a frame sent by the first station to the AP");
574 m_txPsdus[10].header.GetDuration(),
575 RoundDurationId(m_txopLimit - m_txPsdus[10].txDuration),
576 "Duration/ID of the frame sent by the first station does not cover the remaining TXOP");
577
578 // a Normal Ack is then sent by the AP
579 tEnd = m_txPsdus[10].txStart + m_txPsdus[10].txDuration;
580 tStart = m_txPsdus[11].txStart;
581
582 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Ack sent too early");
583 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "Ack sent too late");
584 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[11].header.IsAck(), true, "Expected a Normal Ack");
585 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[11].header.GetAddr1(),
586 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
587 "Expected a Normal Ack sent to the first station");
589 m_txPsdus[11].header.GetDuration(),
590 RoundDurationId(m_txPsdus[10].header.GetDuration() - sifs - m_txPsdus[11].txDuration),
591 "Duration/ID of the Ack must be derived from that of the previous frame");
592
593 // the TXOP limit is such that enough time for sending a CF-End frame remains
594 tEnd = m_txPsdus[11].txStart + m_txPsdus[11].txDuration;
595 tStart = m_txPsdus[12].txStart;
596
597 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "CF-End sent too early");
598 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "CF-End sent too late");
599 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[12].header.IsCfEnd(), true, "Expected a CF-End frame");
600 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[12].header.GetDuration(),
601 Seconds(0),
602 "Duration/ID must be set to 0 for CF-End frames");
603
604 /*
605 * Verify that the Duration/ID of RTS/CTS frames is set correctly, that the TXOP holder is
606 * kept and allows stations to ignore NAV properly and that the CF-End Frame is not sent if
607 * not enough time remains
608 *
609 * |---------------------------------------------NAV---------------------------------->|
610 * | |-----------------------------------------NAV------------------------------->| |
611 * | |-------------------------------------NAV---------------------------->| | | |
612 * |---------------------------------NAV------------------------->| | | | |
613 * |-----------------------------NAV---------------------->| | | | | |
614 * |-------------------------NAV------------------->| | | | | | |
615 * |---------------------NAV---------------->| | | | | | | |
616 * |-----------------NAV------------->| | | | | | | | |
617 * |-------------NAV---------->| | | | | | | | | |
618 * |---------NAV------->| | | | | | | | | | |
619 * |-----NAV---->| | | | | | | | | | | |
620 * |-NAV->|
621 * |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---| |---|
622 * |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack| |RTS| |CTS| |QoS| |Ack|
623 * ----------------------------------------------------------------------------------------------------
624 * From: AP STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3
625 * To: STA1 AP STA1 AP STA2 AP STA2 AP STA3 AP STA3 AP
626 */
627
628 // the first frame is an RTS frame sent by the AP to STA1
629 txopStart = m_txPsdus[13].txStart;
630
631 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[13].header.IsRts(), true, "Expected an RTS frame");
632 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[13].header.GetAddr1(),
633 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
634 "Expected an RTS frame sent by the AP to the first station");
635 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[13].header.GetDuration(),
636 RoundDurationId(m_txopLimit - m_txPsdus[13].txDuration),
637 "Duration/ID of the first RTS frame must cover the whole TXOP");
638
639 // a CTS is sent by STA1
640 tEnd = m_txPsdus[13].txStart + m_txPsdus[13].txDuration;
641 tStart = m_txPsdus[14].txStart;
642
643 NS_TEST_ASSERT_MSG_LT(tEnd + sifs,
644 tStart,
645 "CTS in response to the first RTS frame sent too early");
647 tEnd + sifs + tolerance,
648 "CTS in response to the first RTS frame sent too late");
649 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[14].header.IsCts(), true, "Expected a CTS");
650 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[14].header.GetAddr1(),
651 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
652 "Expected a CTS frame sent to the AP");
654 m_txPsdus[14].header.GetDuration(),
655 RoundDurationId(m_txPsdus[13].header.GetDuration() - sifs - m_txPsdus[14].txDuration),
656 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
657
658 // the AP sends a frame to STA1
659 tEnd = m_txPsdus[14].txStart + m_txPsdus[14].txDuration;
660 tStart = m_txPsdus[15].txStart;
661
662 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "First QoS data frame sent too early");
663 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "First QoS data frame sent too late");
664 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[15].header.IsQosData(), true, "Expected a QoS data frame");
665 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[15].header.GetAddr1(),
666 DynamicCast<WifiNetDevice>(m_staDevices.Get(0))->GetMac()->GetAddress(),
667 "Expected a frame sent by the AP to the first station");
669 m_txPsdus[15].header.GetDuration(),
670 RoundDurationId(m_txopLimit - (m_txPsdus[15].txStart - txopStart) -
671 m_txPsdus[15].txDuration),
672 "Duration/ID of the first QoS data frame does not cover the remaining TXOP");
673
674 // a Normal Ack is then sent by STA1
675 tEnd = m_txPsdus[15].txStart + m_txPsdus[15].txDuration;
676 tStart = m_txPsdus[16].txStart;
677
678 NS_TEST_ASSERT_MSG_LT(tEnd + sifs,
679 tStart,
680 "Ack in response to the first QoS data frame sent too early");
682 tEnd + sifs + tolerance,
683 "Ack in response to the first QoS data frame sent too late");
684 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[16].header.IsAck(), true, "Expected a Normal Ack");
685 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[16].header.GetAddr1(),
686 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
687 "Expected a Normal Ack sent to the AP");
689 m_txPsdus[16].header.GetDuration(),
690 RoundDurationId(m_txPsdus[15].header.GetDuration() - sifs - m_txPsdus[16].txDuration),
691 "Duration/ID of the Ack must be derived from that of the previous frame");
692
693 // An RTS frame is sent by the AP to STA2
694 tEnd = m_txPsdus[16].txStart + m_txPsdus[16].txDuration;
695 tStart = m_txPsdus[17].txStart;
696
697 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Second RTS frame sent too early");
698 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second RTS frame sent too late");
699 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[17].header.IsRts(), true, "Expected an RTS frame");
700 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[17].header.GetAddr1(),
701 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
702 "Expected an RTS frame sent by the AP to the second station");
703 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[17].header.GetDuration(),
704 RoundDurationId(m_txopLimit - (m_txPsdus[17].txStart - txopStart) -
705 m_txPsdus[17].txDuration),
706 "Duration/ID of the second RTS frame must cover the whole TXOP");
707
708 // a CTS is sent by STA2 (which ignores the NAV)
709 tEnd = m_txPsdus[17].txStart + m_txPsdus[17].txDuration;
710 tStart = m_txPsdus[18].txStart;
711
712 NS_TEST_ASSERT_MSG_LT(tEnd + sifs,
713 tStart,
714 "CTS in response to the second RTS frame sent too early");
716 tEnd + sifs + tolerance,
717 "CTS in response to the second RTS frame sent too late");
718 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[18].header.IsCts(), true, "Expected a CTS");
719 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[18].header.GetAddr1(),
720 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
721 "Expected a CTS frame sent to the AP");
723 m_txPsdus[18].header.GetDuration(),
724 RoundDurationId(m_txPsdus[17].header.GetDuration() - sifs - m_txPsdus[18].txDuration),
725 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
726
727 // the AP sends a frame to STA2
728 tEnd = m_txPsdus[18].txStart + m_txPsdus[18].txDuration;
729 tStart = m_txPsdus[19].txStart;
730
731 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Second QoS data frame sent too early");
732 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "Second QoS data frame sent too late");
733 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[19].header.IsQosData(), true, "Expected a QoS data frame");
734 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[19].header.GetAddr1(),
735 DynamicCast<WifiNetDevice>(m_staDevices.Get(1))->GetMac()->GetAddress(),
736 "Expected a frame sent by the AP to the second station");
738 m_txPsdus[19].header.GetDuration(),
739 RoundDurationId(m_txopLimit - (m_txPsdus[19].txStart - txopStart) -
740 m_txPsdus[19].txDuration),
741 "Duration/ID of the second QoS data frame does not cover the remaining TXOP");
742
743 // a Normal Ack is then sent by STA2
744 tEnd = m_txPsdus[19].txStart + m_txPsdus[19].txDuration;
745 tStart = m_txPsdus[20].txStart;
746
747 NS_TEST_ASSERT_MSG_LT(tEnd + sifs,
748 tStart,
749 "Ack in response to the second QoS data frame sent too early");
751 tEnd + sifs + tolerance,
752 "Ack in response to the second QoS data frame sent too late");
753 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[20].header.IsAck(), true, "Expected a Normal Ack");
754 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[20].header.GetAddr1(),
755 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
756 "Expected a Normal Ack sent to the AP");
758 m_txPsdus[20].header.GetDuration(),
759 RoundDurationId(m_txPsdus[19].header.GetDuration() - sifs - m_txPsdus[20].txDuration),
760 "Duration/ID of the Ack must be derived from that of the previous frame");
761
762 // An RTS frame is sent by the AP to STA3
763 tEnd = m_txPsdus[20].txStart + m_txPsdus[20].txDuration;
764 tStart = m_txPsdus[21].txStart;
765
766 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Third RTS frame sent too early");
767 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third RTS frame sent too late");
768 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[21].header.IsRts(), true, "Expected an RTS frame");
769 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[21].header.GetAddr1(),
770 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
771 "Expected an RTS frame sent by the AP to the third station");
772 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[21].header.GetDuration(),
773 RoundDurationId(m_txopLimit - (m_txPsdus[21].txStart - txopStart) -
774 m_txPsdus[21].txDuration),
775 "Duration/ID of the third RTS frame must cover the whole TXOP");
776
777 // a CTS is sent by STA3 (which ignores the NAV)
778 tEnd = m_txPsdus[21].txStart + m_txPsdus[21].txDuration;
779 tStart = m_txPsdus[22].txStart;
780
781 NS_TEST_ASSERT_MSG_LT(tEnd + sifs,
782 tStart,
783 "CTS in response to the third RTS frame sent too early");
785 tEnd + sifs + tolerance,
786 "CTS in response to the third RTS frame sent too late");
787 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[22].header.IsCts(), true, "Expected a CTS");
788 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[22].header.GetAddr1(),
789 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
790 "Expected a CTS frame sent to the AP");
792 m_txPsdus[22].header.GetDuration(),
793 RoundDurationId(m_txPsdus[21].header.GetDuration() - sifs - m_txPsdus[22].txDuration),
794 "Duration/ID of the CTS frame must be derived from that of the RTS frame");
795
796 // the AP sends a frame to STA3
797 tEnd = m_txPsdus[22].txStart + m_txPsdus[22].txDuration;
798 tStart = m_txPsdus[23].txStart;
799
800 NS_TEST_ASSERT_MSG_LT(tEnd + sifs, tStart, "Third QoS data frame sent too early");
801 NS_TEST_ASSERT_MSG_LT(tStart, tEnd + sifs + tolerance, "Third QoS data frame sent too late");
802 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[23].header.IsQosData(), true, "Expected a QoS data frame");
803 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[23].header.GetAddr1(),
804 DynamicCast<WifiNetDevice>(m_staDevices.Get(2))->GetMac()->GetAddress(),
805 "Expected a frame sent by the AP to the third station");
807 m_txPsdus[23].header.GetDuration(),
808 RoundDurationId(m_txopLimit - (m_txPsdus[23].txStart - txopStart) -
809 m_txPsdus[23].txDuration),
810 "Duration/ID of the third QoS data frame does not cover the remaining TXOP");
811
812 // a Normal Ack is then sent by STA3
813 tEnd = m_txPsdus[23].txStart + m_txPsdus[23].txDuration;
814 tStart = m_txPsdus[24].txStart;
815
816 NS_TEST_ASSERT_MSG_LT(tEnd + sifs,
817 tStart,
818 "Ack in response to the third QoS data frame sent too early");
820 tEnd + sifs + tolerance,
821 "Ack in response to the third QoS data frame sent too late");
822 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[24].header.IsAck(), true, "Expected a Normal Ack");
823 NS_TEST_ASSERT_MSG_EQ(m_txPsdus[24].header.GetAddr1(),
824 DynamicCast<WifiNetDevice>(m_apDevices.Get(0))->GetMac()->GetAddress(),
825 "Expected a Normal Ack sent to the AP");
827 m_txPsdus[24].header.GetDuration(),
828 RoundDurationId(m_txPsdus[23].header.GetDuration() - sifs - m_txPsdus[24].txDuration),
829 "Duration/ID of the Ack must be derived from that of the previous frame");
830
831 // there is no time remaining for sending a CF-End frame. This is verified by checking
832 // that 25 frames are transmitted (done at the beginning of this method)
833
834 // 3 DL packets (without RTS/CTS), 1 UL packet and 3 DL packets (with RTS/CTS)
835 NS_TEST_ASSERT_MSG_EQ(m_received, 7, "Unexpected number of packets received");
836}
837
838/**
839 * \ingroup wifi-test
840 * \ingroup tests
841 *
842 * \brief wifi TXOP Test Suite
843 */
845{
846 public:
848};
849
851 : TestSuite("wifi-txop", Type::UNIT)
852{
853 AddTestCase(new WifiTxopTest(true), TestCase::Duration::QUICK);
854 AddTestCase(new WifiTxopTest(false), TestCase::Duration::QUICK);
855}
856
857static 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
NetDeviceContainer m_apDevices
container for AP's NetDevice
void DoRun() override
Implementation to actually run this TestCase.
uint32_t m_cwMin
CWmin for BE.
uint16_t m_received
number of packets received by the stations
uint16_t m_nStations
number of stations
uint8_t m_aifsn
AIFSN for BE.
Time m_txopLimit
TXOP limit.
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
void Transmit(std::string context, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when PHY receives a PSDU to transmit.
~WifiTxopTest() override
NetDeviceContainer m_staDevices
container for stations' NetDevices
WifiTxopTest(bool pifsRecovery)
Constructor.
void CheckResults()
Check correctness of transmitted frames.
wifi TXOP Test Suite
a polymophic address class
Definition: address.h:101
AttributeValue implementation for Boolean.
Definition: boolean.h:37
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
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.
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
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.
AttributeValue implementation for Pointer.
Definition: pointer.h:48
Ptr< T > Get() const
Definition: pointer.h:234
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:74
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:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
AttributeValue implementation for Ssid.
Definition: ssid.h:96
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1061
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1268
Type
Type of test.
Definition: test.h:1275
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1406
uint32_t GetMinCw() const
Return the minimum contention window size.
Definition: txop.cc:417
uint8_t GetAifsn() const
Return the number of slots that make up an AIFS.
Definition: txop.cc:465
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
Implements the IEEE 802.11 MAC header.
create MAC layers for a ns3::WifiNetDevice.
void SetSsid(Ssid ssid)
Definition: wifi-mac.cc:472
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition: wifi-phy.cc:1529
static Time CalculatePhyPreambleAndHeaderDuration(const WifiTxVector &txVector)
Definition: wifi-phy.cc:1522
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:894
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:978
#define NS_TEST_ASSERT_MSG_LT(actual, limit, msg)
Test that an actual value is less than a limit and report and abort if not.
Definition: test.h:710
#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:145
#define NS_TEST_ASSERT_MSG_LT_OR_EQ(actual, limit, msg)
Test that an actual value is less than or equal to a limit and report and abort if not.
Definition: test.h:751
#define NS_TEST_ASSERT_MSG_GT_OR_EQ(actual, limit, msg)
Test that an actual value is greater than or equal to a limit and report and abort if not.
Definition: test.h:916
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1343
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1355
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1319
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1331
@ WIFI_STANDARD_80211a
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
Definition: wifi-phy-band.h:37
Every class exported by the ns3 library is enclosed in the ns3 namespace.
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
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:706
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
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.
static WifiTxopTestSuite g_wifiTxopTestSuite
the test suite