A Discrete-Event Network Simulator
API
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 
41 using namespace ns3;
42 
51 class WifiTxopTest : public TestCase
52 {
53  public:
58  WifiTxopTest(bool pifsRecovery);
59  ~WifiTxopTest() override;
60 
67  void L7Receive(std::string context, Ptr<const Packet> p, const Address& addr);
75  void Transmit(std::string context,
76  WifiConstPsduMap psduMap,
77  WifiTxVector txVector,
78  double txPowerW);
82  void CheckResults();
83 
84  private:
85  void DoRun() override;
86 
88  struct FrameInfo
89  {
94  };
95 
96  uint16_t m_nStations;
99  std::vector<FrameInfo> m_txPsdus;
101  uint8_t m_aifsn;
102  uint32_t m_cwMin;
103  uint16_t m_received;
105 };
106 
107 WifiTxopTest::WifiTxopTest(bool pifsRecovery)
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 
120 void
121 WifiTxopTest::L7Receive(std::string context, Ptr<const Packet> p, const Address& addr)
122 {
123  if (p->GetSize() >= 500)
124  {
125  m_received++;
126  }
127 }
128 
129 void
130 WifiTxopTest::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(),
140  WifiPhy::CalculateTxDuration(psduMap, txVector, WIFI_PHY_BAND_5GHZ),
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 "
149  << WifiPhy::CalculateTxDuration(psduMap, txVector, WIFI_PHY_BAND_5GHZ)
150  << " duration/ID " << psduMap.begin()->second->GetHeader(0).GetDuration()
151  << std::endl;
152 }
153 
154 void
156 {
157  RngSeedManager::SetSeed(1);
158  RngSeedManager::SetRun(40);
159  int64_t streamNumber = 100;
160 
162  wifiApNode.Create(1);
163 
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 
181  wifi.SetStandard(WIFI_STANDARD_80211a);
182  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
183  "DataMode",
184  StringValue("OfdmRate12Mbps"),
185  "ControlMode",
186  StringValue("OfdmRate6Mbps"));
187 
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));
218  Simulator::Schedule(i * MicroSeconds(102400),
219  &WifiMac::SetSsid,
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 
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 
330  Simulator::Stop(Seconds(1));
331  Simulator::Run();
332 
333  CheckResults();
334 
335  Simulator::Destroy();
336 }
337 
338 void
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");
394  NS_TEST_ASSERT_MSG_LT(tStart,
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");
437  NS_TEST_ASSERT_MSG_LT(tStart,
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 +
468  WifiPhy::CalculatePhyPreambleAndHeaderDuration(m_txPsdus[4].txVector); // AckTimeout
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");
504  NS_TEST_ASSERT_MSG_LT(tStart,
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");
536  NS_TEST_ASSERT_MSG_LT(tStart,
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");
646  NS_TEST_ASSERT_MSG_LT(tStart,
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");
681  NS_TEST_ASSERT_MSG_LT(tStart,
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");
715  NS_TEST_ASSERT_MSG_LT(tStart,
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");
750  NS_TEST_ASSERT_MSG_LT(tStart,
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");
784  NS_TEST_ASSERT_MSG_LT(tStart,
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");
819  NS_TEST_ASSERT_MSG_LT(tStart,
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 
845 {
846  public:
848 };
849 
851  : TestSuite("wifi-txop", UNIT)
852 {
853  AddTestCase(new WifiTxopTest(true), TestCase::QUICK);
854  AddTestCase(new WifiTxopTest(false), TestCase::QUICK);
855 }
856 
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
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.
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:244
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
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.
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:202
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:74
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:36
Hold variables of type string.
Definition: string.h:56
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
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:458
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:1171
Ptr< WifiMac > GetMac() const
void SetPostReceptionErrorModel(const Ptr< ErrorModel > em)
Attach a receive ErrorModel to the WifiPhy.
Definition: wifi-phy.cc:646
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:890
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:974
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
#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:709
#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:144
#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:750
#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:915
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1362
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
@ 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:704
static constexpr uint16_t SU_STA_ID
STA_ID to identify a single user (SU)
Definition: wifi-mode.h:35
mac
Definition: third.py:92
wifi
Definition: third.py:95
wifiApNode
Definition: third.py:86
mobility
Definition: third.py:105
wifiStaNodes
Definition: third.py:84
phy
Definition: third.py:89
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