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:100
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.
void GetAttribute(std::string name, AttributeValue &value) const
Get the value of an attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:240
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:863
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:206
Handle packet fragmentation and retransmissions for QoS data frames as well as MSDU aggregation (A-MS...
Definition: qos-txop.h:73
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.
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:305
A suite of tests to run.
Definition: test.h:1256
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
AttributeValue implementation for Time.
Definition: nstime.h:1423
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:325
Implements the IEEE 802.11 MAC header.
create MAC layers for a ns3::WifiNetDevice.
void SetSsid(Ssid ssid)
Definition: wifi-mac.cc:449
Ptr< WifiPhy > GetWifiPhy(uint8_t linkId=SINGLE_LINK_OP_ID) const
Definition: wifi-mac.cc:954
Ptr< WifiMac > GetMac() const
void SetPostReceptionErrorModel(const Ptr< ErrorModel > em)
Attach a receive ErrorModel to the WifiPhy.
Definition: wifi-phy.cc:639
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:891
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:975
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:296
#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:1360
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
@ 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:707
mac
Definition: third.py:85
wifi
Definition: third.py:88
wifiApNode
Definition: third.py:79
mobility
Definition: third.py:96
wifiStaNodes
Definition: third.py:77
phy
Definition: third.py:82
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.
#define SU_STA_ID
Definition: wifi-mode.h:34
static WifiTxopTestSuite g_wifiTxopTestSuite
the test suite