A Discrete-Event Network Simulator
API
inter-bss-test-suite.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 University of Washington
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  * Authors: Sébastien Deronne <sebastien.deronne@gmail.com>
18  * Scott Carpenter <scarpenter44@windstream.net>
19  */
20 
21 #include "ns3/config.h"
22 #include "ns3/constant-obss-pd-algorithm.h"
23 #include "ns3/double.h"
24 #include "ns3/he-configuration.h"
25 #include "ns3/log.h"
26 #include "ns3/mobility-helper.h"
27 #include "ns3/multi-model-spectrum-channel.h"
28 #include "ns3/pointer.h"
29 #include "ns3/rng-seed-manager.h"
30 #include "ns3/spectrum-wifi-helper.h"
31 #include "ns3/ssid.h"
32 #include "ns3/string.h"
33 #include "ns3/test.h"
34 #include "ns3/uinteger.h"
35 #include "ns3/wifi-net-device.h"
36 #include "ns3/wifi-utils.h"
37 
38 using namespace ns3;
39 
40 NS_LOG_COMPONENT_DEFINE("InterBssTestSuite");
41 
42 static uint32_t
43 ConvertContextToNodeId(std::string context)
44 {
45  std::string sub = context.substr(10);
46  uint32_t pos = sub.find("/Device");
47  uint32_t nodeId = std::stoi(sub.substr(0, pos));
48  return nodeId;
49 }
50 
78 {
79  public:
87 
88  void DoRun() override;
89 
90  private:
97  void SendOnePacket(Ptr<WifiNetDevice> tx_dev, Ptr<WifiNetDevice> rx_dev, uint32_t payloadSize);
98 
108  Ptr<ListPositionAllocator> AllocatePositions(double d1,
109  double d2,
110  double d3,
111  double d4,
112  double d5);
113 
118  void SetExpectedTxPower(double txPowerDbm);
119 
123  void SetupSimulation();
124 
128  void CheckResults();
129 
133  void ResetResults();
134 
138  void ClearDropReasons();
139 
143  void RunOne();
144 
150  void CheckPhyState(Ptr<WifiNetDevice> device, WifiPhyState expectedState);
151 
157  void CheckPhyDropReasons(Ptr<WifiNetDevice> device,
158  std::vector<WifiPhyRxfailureReason> expectedDropReasons);
159 
166  void NotifyPhyTxBegin(std::string context, Ptr<const Packet> p, double txPowerW);
167 
173  void NotifyPhyRxEnd(std::string context, Ptr<const Packet> p);
174 
181  void NotifyPhyRxDrop(std::string context, Ptr<const Packet> p, WifiPhyRxfailureReason reason);
182 
183  unsigned int m_numSta1PacketsSent;
184  unsigned int m_numSta2PacketsSent;
185  unsigned int m_numAp1PacketsSent;
186  unsigned int m_numAp2PacketsSent;
187 
190  unsigned int m_numAp1PacketsReceived;
191  unsigned int m_numAp2PacketsReceived;
192 
193  std::vector<WifiPhyRxfailureReason> m_dropReasonsSta1;
194  std::vector<WifiPhyRxfailureReason> m_dropReasonsSta2;
195  std::vector<WifiPhyRxfailureReason> m_dropReasonsAp1;
196  std::vector<WifiPhyRxfailureReason> m_dropReasonsAp2;
197 
198  unsigned int m_payloadSize1;
199  unsigned int m_payloadSize2;
200  unsigned int m_payloadSize3;
201 
204 
205  double m_txPowerDbm;
209 
210  uint8_t m_bssColor1;
211  uint8_t m_bssColor2;
212  uint8_t m_bssColor3;
213 
215 };
216 
218  : TestCase("InterBssConstantObssPd"),
219  m_numSta1PacketsSent(0),
220  m_numSta2PacketsSent(0),
221  m_numAp1PacketsSent(0),
222  m_numAp2PacketsSent(0),
223  m_numSta1PacketsReceived(0),
224  m_numSta2PacketsReceived(0),
225  m_numAp1PacketsReceived(0),
226  m_numAp2PacketsReceived(0),
227  m_payloadSize1(1000),
228  m_payloadSize2(1500),
229  m_payloadSize3(2000),
230  m_txPowerDbm(15),
231  m_obssPdLevelDbm(-72),
232  m_obssRxPowerDbm(-82),
233  m_expectedTxPowerDbm(15),
234  m_bssColor1(1),
235  m_bssColor2(2),
236  m_bssColor3(3),
237  m_standard(standard)
238 {
239 }
240 
242 {
244 }
245 
248  double d2,
249  double d3,
250  double d4,
251  double d5)
252 {
253  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
254  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // AP1
255  positionAlloc->Add(Vector(d1 + d2, 0.0, 0.0)); // AP2
256  positionAlloc->Add(Vector(d1 + d2 + d3 + d4, 0.0, 0.0)); // AP3
257  positionAlloc->Add(Vector(d1, 0.0, 0.0)); // STA1
258  positionAlloc->Add(Vector(d1 + d2 + d3, 0.0, 0.0)); // STA2
259  positionAlloc->Add(Vector(d1 + d2 + d3 + d4 + d5, 0.0, 0.0)); // STA3
260  return positionAlloc;
261 }
262 
263 void
265 {
266  Ptr<WifiNetDevice> ap_device1 = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
267  Ptr<WifiNetDevice> ap_device2 = DynamicCast<WifiNetDevice>(m_apDevices.Get(1));
268  Ptr<WifiNetDevice> ap_device3 = DynamicCast<WifiNetDevice>(m_apDevices.Get(2));
269  Ptr<WifiNetDevice> sta_device1 = DynamicCast<WifiNetDevice>(m_staDevices.Get(0));
270  Ptr<WifiNetDevice> sta_device2 = DynamicCast<WifiNetDevice>(m_staDevices.Get(1));
271  Ptr<WifiNetDevice> sta_device3 = DynamicCast<WifiNetDevice>(m_staDevices.Get(2));
272 
273  bool expectFilter = (m_bssColor1 != 0) && (m_bssColor2 != 0);
274  bool expectPhyReset = expectFilter && (m_obssPdLevelDbm >= m_obssRxPowerDbm);
275  std::vector<WifiPhyRxfailureReason> dropReasons;
276  WifiPhyState stateDuringPayloadNeighboringBss =
277  expectFilter ? WifiPhyState::CCA_BUSY : WifiPhyState::RX;
278  if (expectFilter)
279  {
280  dropReasons.push_back(FILTERED);
281  }
282  if (expectPhyReset)
283  {
284  dropReasons.push_back(OBSS_PD_CCA_RESET);
285  }
286 
287  // In order to have all ADDBA handshakes established, each AP and STA sends a packet.
288 
289  Simulator::Schedule(Seconds(0.25),
291  this,
292  ap_device1,
293  sta_device1,
295  Simulator::Schedule(Seconds(0.5),
297  this,
298  sta_device1,
299  ap_device1,
301  Simulator::Schedule(Seconds(0.75),
303  this,
304  ap_device2,
305  sta_device2,
307  Simulator::Schedule(Seconds(1),
309  this,
310  sta_device2,
311  ap_device2,
313  Simulator::Schedule(Seconds(1.25),
315  this,
316  ap_device3,
317  sta_device3,
319  Simulator::Schedule(Seconds(1.5),
321  this,
322  sta_device3,
323  ap_device3,
325 
326  // We test PHY state and verify whether a CCA reset did occur.
327 
328  // AP2 sends a packet 0.5s later.
329  Simulator::Schedule(Seconds(2.0), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
330  Simulator::Schedule(Seconds(2.0),
332  this,
333  ap_device2,
334  sta_device2,
336  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10),
338  this,
339  ap_device2,
341  // All other PHYs should have stay idle until 4us (preamble detection time).
342  Simulator::Schedule(Seconds(2.0) + MicroSeconds(13),
344  this,
345  sta_device1,
347  Simulator::Schedule(Seconds(2.0) + MicroSeconds(13),
349  this,
350  sta_device2,
352  Simulator::Schedule(Seconds(2.0) + MicroSeconds(13),
354  this,
355  ap_device1,
357  // All PHYs should be receiving the PHY header (i.e. PHY state is CCA_BUSY) if preamble has been
358  // detected (always the case in this test).
359  Simulator::Schedule(Seconds(2.0) + MicroSeconds(14),
361  this,
362  sta_device1,
364  Simulator::Schedule(Seconds(2.0) + MicroSeconds(14),
366  this,
367  sta_device2,
369  Simulator::Schedule(Seconds(2.0) + MicroSeconds(14),
371  this,
372  ap_device1,
374  // PHYs of AP1 and STA1 should be idle after HE-SIG-A if they were reset by OBSS_PD SR,
375  // otherwise they should be CCA_busy until beginning of payload.
376  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
378  this,
379  sta_device1,
380  dropReasons);
381  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
383  this,
384  sta_device1,
385  expectPhyReset ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
386  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
388  this,
389  ap_device1,
390  dropReasons);
391  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
393  this,
394  ap_device1,
395  expectPhyReset ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
396  // PHYs of AP1 and STA1 should be idle if they were reset by OBSS_PD SR, otherwise they should
397  // be CCA_busy/Rx (since filtered/not filtered, resp.).
398  Simulator::Schedule(Seconds(2.0) + MicroSeconds(54),
400  this,
401  sta_device1,
402  expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
403  Simulator::Schedule(Seconds(2.0) + MicroSeconds(54),
405  this,
406  ap_device1,
407  expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
408  // STA2 should be receiving
409  Simulator::Schedule(Seconds(2.0) + MicroSeconds(54),
411  this,
412  sta_device2,
414 
415  // We test whether two networks can transmit simultaneously, and whether transmit power
416  // restrictions are applied.
417 
418  // AP2 sends another packet 0.1s later.
419  Simulator::Schedule(Seconds(2.1), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
420  Simulator::Schedule(Seconds(2.1),
422  this,
423  ap_device2,
424  sta_device2,
426  // STA1 sends a packet 42us later (i.e. right after HE-SIG-A of AP2). Even though AP2 is still
427  // transmitting, STA1 can transmit simultaneously if it's PHY was reset by OBSS_PD SR.
428  Simulator::Schedule(Seconds(2.1) + MicroSeconds(42),
430  this,
431  sta_device1,
432  ap_device1,
434  if (expectPhyReset)
435  {
436  // In this case, we check the TX power is restricted (and set the expected value slightly
437  // before transmission should occur)
438  double expectedTxPower = std::min(m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
439  Simulator::Schedule(Seconds(2.1) + MicroSeconds(41),
441  this,
442  expectedTxPower);
443  }
444  // Check simultaneous transmissions
445  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
447  this,
448  ap_device2,
450  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
452  this,
453  sta_device1,
454  dropReasons);
455  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
457  this,
458  sta_device1,
459  expectPhyReset ? WifiPhyState::TX : stateDuringPayloadNeighboringBss);
460  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
462  this,
463  sta_device2,
465  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
467  this,
468  ap_device1,
469  dropReasons);
470  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
472  this,
473  ap_device1,
474  stateDuringPayloadNeighboringBss);
475  Simulator::Schedule(Seconds(2.1) + MicroSeconds(142),
477  this,
478  ap_device1,
479  expectPhyReset ? WifiPhyState::RX : stateDuringPayloadNeighboringBss);
480 
481  // AP2 sends another packet 0.1s later, and STA1 wanting to send a packet during the payload of
482  // the former.
483  Simulator::Schedule(Seconds(2.2), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
484  Simulator::Schedule(Seconds(2.2),
486  this,
487  m_txPowerDbm);
488  Simulator::Schedule(Seconds(2.2),
490  this,
491  ap_device2,
492  sta_device2,
494  // STA1 sends a packet 90us later (i.e. during payload of AP2). Even though AP2 is still
495  // transmitting, STA1 can transmit simultaneously if it's PHY was reset by OBSS_PD SR.
496  Simulator::Schedule(Seconds(2.2) + MicroSeconds(90),
498  this,
499  sta_device1,
500  ap_device1,
502  if (expectPhyReset)
503  {
504  // In this case, we check the TX power is restricted (and set the expected value slightly
505  // before transmission should occur)
506  double expectedTxPower = std::min(m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
507  Simulator::Schedule(Seconds(2.2) + MicroSeconds(89),
509  this,
510  expectedTxPower);
511  }
512  // Check simultaneous transmissions
513  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
515  this,
516  ap_device2,
518  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
520  this,
521  sta_device1,
522  dropReasons);
523  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
525  this,
526  sta_device1,
527  expectPhyReset ? WifiPhyState::TX : stateDuringPayloadNeighboringBss);
528  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
530  this,
531  sta_device2,
533  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
535  this,
536  ap_device1,
537  dropReasons);
538  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
540  this,
541  ap_device1,
542  stateDuringPayloadNeighboringBss);
543  Simulator::Schedule(Seconds(2.2) + MicroSeconds(195),
545  this,
546  ap_device1,
547  expectPhyReset ? WifiPhyState::RX : stateDuringPayloadNeighboringBss);
548 
549  // Verify transmit power restrictions are not applied if access to the channel is requested
550  // after ignored OBSS transmissions.
551 
552  Simulator::Schedule(Seconds(2.3),
554  this,
555  m_txPowerDbm);
556  // AP2 sends another packet 0.1s later. Power restriction should not be applied.
557  Simulator::Schedule(Seconds(2.3),
559  this,
560  ap_device2,
561  sta_device2,
563  // STA1 sends a packet 0.1s later. Power restriction should not be applied.
564  Simulator::Schedule(Seconds(2.4),
566  this,
567  sta_device1,
568  ap_device1,
570 
571  // Verify a scenario that involves 3 networks in order to verify corner cases for transmit power
572  // restrictions. First, there is a transmission on network 2 from STA to AP, followed by a
573  // response from AP to STA. During that time, the STA on network 1 has a packet to send and
574  // request access to the channel. If a CCA reset occurred, it starts deferring while
575  // transmissions are ongoing from network 2. Before its backoff expires, a transmission on
576  // network 3 occurs, also eventually triggering another CCA reset (depending on the scenario
577  // that is being run). This test checks whether this sequence preserves transmit power
578  // restrictions if CCA resets occurred, since STA 1 has been deferring during ignored OBSS
579  // transmissions.
580 
581  Simulator::Schedule(Seconds(2.5),
583  this,
584  sta_device2,
585  ap_device2,
586  m_payloadSize2 / 10);
587  Simulator::Schedule(Seconds(2.5) + MicroSeconds(15),
589  this,
590  ap_device2,
591  sta_device2,
592  m_payloadSize2 / 10);
593  Simulator::Schedule(Seconds(2.5) + MicroSeconds(270),
595  this,
596  ap_device1,
597  sta_device1,
598  m_payloadSize1 / 10);
599  Simulator::Schedule(Seconds(2.5) + MicroSeconds(300),
601  this,
602  ap_device3,
603  sta_device3,
604  m_payloadSize3 / 10);
605  if (expectPhyReset)
606  {
607  // In this case, we check the TX power is restricted (and set the expected value slightly
608  // before transmission should occur)
609  double expectedTxPower = std::min(m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
610  Simulator::Schedule(Seconds(2.5) + MicroSeconds(338),
612  this,
613  expectedTxPower);
614  }
615 
616  Simulator::Stop(Seconds(2.6));
617 }
618 
619 void
621 {
632 }
633 
634 void
636 {
637  m_dropReasonsSta1.clear();
638  m_dropReasonsSta2.clear();
639  m_dropReasonsAp1.clear();
640  m_dropReasonsAp2.clear();
641 }
642 
643 void
645 {
647  4,
648  "The number of packets sent by STA1 is not correct!");
650  2,
651  "The number of packets sent by STA2 is not correct!");
653  2,
654  "The number of packets sent by AP1 is not correct!");
656  6,
657  "The number of packets sent by AP2 is not correct!");
659  2,
660  "The number of packets received by STA1 is not correct!");
662  6,
663  "The number of packets received by STA2 is not correct!");
665  4,
666  "The number of packets received by AP1 is not correct!");
668  2,
669  "The number of packets received by AP2 is not correct!");
670 }
671 
672 void
675  double txPowerW)
676 {
677  uint32_t idx = ConvertContextToNodeId(context);
678  uint32_t pktSize = p->GetSize() - 38;
679  if ((idx == 0) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
680  {
683  true,
684  "Tx power is not correct!");
685  }
686  else if ((idx == 1) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
687  {
690  true,
691  "Tx power is not correct!");
692  }
693  else if ((idx == 3) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
694  {
697  true,
698  "Tx power is not correct!");
699  }
700  else if ((idx == 4) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
701  {
704  true,
705  "Tx power is not correct!");
706  }
707 }
708 
709 void
711 {
712  uint32_t idx = ConvertContextToNodeId(context);
713  uint32_t pktSize = p->GetSize() - 38;
714  if ((idx == 0) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
715  {
717  }
718  else if ((idx == 1) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
719  {
721  }
722  else if ((idx == 3) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
723  {
725  }
726  else if ((idx == 4) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
727  {
729  }
730 }
731 
732 void
735  WifiPhyRxfailureReason reason)
736 {
737  uint32_t idx = ConvertContextToNodeId(context);
738  uint32_t pktSize = p->GetSize() - 38;
739  if ((idx == 0) && ((pktSize != m_payloadSize1) && (pktSize != (m_payloadSize1 / 10))))
740  {
741  m_dropReasonsSta1.push_back(reason);
742  }
743  else if ((idx == 1) && ((pktSize != m_payloadSize2) && (pktSize != (m_payloadSize2 / 10))))
744  {
745  m_dropReasonsSta2.push_back(reason);
746  }
747  else if ((idx == 3) && ((pktSize != m_payloadSize1) && (pktSize != (m_payloadSize1 / 10))))
748  {
749  m_dropReasonsAp1.push_back(reason);
750  }
751  else if ((idx == 4) && ((pktSize != m_payloadSize2) && (pktSize != (m_payloadSize2 / 10))))
752  {
753  m_dropReasonsAp2.push_back(reason);
754  }
755 }
756 
757 void
759  Ptr<WifiNetDevice> rx_dev,
760  uint32_t payloadSize)
761 {
762  Ptr<Packet> p = Create<Packet>(payloadSize);
763  tx_dev->Send(p, rx_dev->GetAddress(), 1);
764 }
765 
766 void
768 {
769  m_expectedTxPowerDbm = txPowerDbm;
770 }
771 
772 void
774 {
775  WifiPhyState currentState;
776  PointerValue ptr;
777  Ptr<WifiPhy> phy = DynamicCast<WifiPhy>(device->GetPhy());
778  phy->GetAttribute("State", ptr);
779  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
780  currentState = state->GetState();
781  NS_TEST_ASSERT_MSG_EQ(currentState,
782  expectedState,
783  "PHY State " << currentState << " does not match expected state "
784  << expectedState << " at " << Simulator::Now());
785 }
786 
787 void
789  Ptr<WifiNetDevice> device,
790  std::vector<WifiPhyRxfailureReason> expectedDropReasons)
791 {
792  std::vector<WifiPhyRxfailureReason> currentDropReasons;
793  uint32_t nodeId = device->GetNode()->GetId();
794  switch (nodeId)
795  {
796  case 0: // STA1
797  currentDropReasons = m_dropReasonsSta1;
798  break;
799  case 1: // STA2
800  currentDropReasons = m_dropReasonsSta2;
801  break;
802  case 3: // AP1
803  currentDropReasons = m_dropReasonsAp1;
804  break;
805  case 4: // AP2
806  currentDropReasons = m_dropReasonsAp2;
807  break;
808  default: // others, no attribute
809  return;
810  }
811  NS_TEST_ASSERT_MSG_EQ(currentDropReasons.size(),
812  expectedDropReasons.size(),
813  "Number of drop reasons "
814  << currentDropReasons.size() << " does not match expected one "
815  << expectedDropReasons.size() << " at " << Simulator::Now());
816  for (std::size_t i = 0; i < currentDropReasons.size(); ++i)
817  {
818  NS_TEST_ASSERT_MSG_EQ(currentDropReasons[i],
819  expectedDropReasons[i],
820  "Drop reason " << i << ": " << currentDropReasons[i]
821  << " does not match expected reason "
822  << expectedDropReasons[i] << " at "
823  << Simulator::Now());
824  }
825 }
826 
827 void
829 {
830  RngSeedManager::SetSeed(1);
831  RngSeedManager::SetRun(3);
832  int64_t streamNumber = 50;
833 
834  Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
835  UintegerValue(0));
836 
837  ResetResults();
838 
840  wifiStaNodes.Create(3);
841 
842  NodeContainer wifiApNodes;
843  wifiApNodes.Create(3);
844 
845  Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
846  lossModel->SetDefaultLoss(
847  m_txPowerDbm - m_obssRxPowerDbm); // Force received RSSI to be equal to m_obssRxPowerDbm
848 
850  phy.DisablePreambleDetectionModel();
851  phy.SetFrameCaptureModel("ns3::SimpleFrameCaptureModel");
852  Ptr<MultiModelSpectrumChannel> channel = CreateObject<MultiModelSpectrumChannel>();
853  channel->SetPropagationDelayModel(CreateObject<ConstantSpeedPropagationDelayModel>());
854  channel->AddPropagationLossModel(lossModel);
855  phy.SetChannel(channel);
856  phy.Set("TxPowerStart", DoubleValue(m_txPowerDbm));
857  phy.Set("TxPowerEnd", DoubleValue(m_txPowerDbm));
858  phy.Set("ChannelSettings", StringValue("{36, 20, BAND_5GHZ, 0}"));
859 
861  wifi.SetStandard(m_standard);
862  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
863  "DataMode",
864  StringValue("HeMcs5"),
865  "ControlMode",
866  StringValue("HeMcs0"));
867 
868  wifi.SetObssPdAlgorithm("ns3::ConstantObssPdAlgorithm",
869  "ObssPdLevel",
871 
873  Ssid ssid = Ssid("ns-3-ssid");
874  mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
875  m_staDevices = wifi.Install(phy, mac, wifiStaNodes);
876 
877  // Assign fixed streams to random variables in use
878  wifi.AssignStreams(m_staDevices, streamNumber);
879 
880  mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
881  m_apDevices = wifi.Install(phy, mac, wifiApNodes);
882 
883  // Assign fixed streams to random variables in use
884  wifi.AssignStreams(m_apDevices, streamNumber);
885 
886  for (uint32_t i = 0; i < m_apDevices.GetN(); i++)
887  {
888  Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(m_apDevices.Get(i));
889  Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
890  if (i == 0)
891  {
892  heConfiguration->SetAttribute("BssColor", UintegerValue(m_bssColor1));
893  }
894  else if (i == 1)
895  {
896  heConfiguration->SetAttribute("BssColor", UintegerValue(m_bssColor2));
897  }
898  else
899  {
900  heConfiguration->SetAttribute("BssColor", UintegerValue(m_bssColor3));
901  }
902  }
903 
906  10,
907  50,
908  10,
909  50,
910  10); // distances do not really matter since we set RSSI per TX-RX pair to have full control
911  mobility.SetPositionAllocator(positionAlloc);
912  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
913  mobility.Install(wifiApNodes);
914  mobility.Install(wifiStaNodes);
915 
916  lossModel->SetLoss(wifiStaNodes.Get(0)->GetObject<MobilityModel>(),
917  wifiApNodes.Get(0)->GetObject<MobilityModel>(),
918  m_txPowerDbm + 30); // Low attenuation for IBSS transmissions
919  lossModel->SetLoss(wifiStaNodes.Get(1)->GetObject<MobilityModel>(),
920  wifiApNodes.Get(1)->GetObject<MobilityModel>(),
921  m_txPowerDbm + 30); // Low attenuation for IBSS transmissions
922  lossModel->SetLoss(wifiStaNodes.Get(2)->GetObject<MobilityModel>(),
923  wifiApNodes.Get(2)->GetObject<MobilityModel>(),
924  m_txPowerDbm + 30); // Low attenuation for IBSS transmissions
925 
926  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin",
928  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxEnd",
930  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop",
932 
933  SetupSimulation();
934 
935  Simulator::Run();
936  Simulator::Destroy();
937 
938  CheckResults();
939 }
940 
941 void
943 {
944  // Test case 1: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm
945  m_obssPdLevelDbm = -72;
946  m_obssRxPowerDbm = -82;
947  m_bssColor1 = 1;
948  m_bssColor2 = 2;
949  m_bssColor3 = 3;
950  RunOne();
951 
952  // Test case 2: CCA CS Threshold < m_obssPdLevelDbm < m_obssRxPowerDbm
953  m_obssPdLevelDbm = -72;
954  m_obssRxPowerDbm = -62;
955  m_bssColor1 = 1;
956  m_bssColor2 = 2;
957  m_bssColor3 = 3;
958  RunOne();
959 
960  // Test case 3: CCA CS Threshold < m_obssPdLevelDbm = m_obssRxPowerDbm
961  m_obssPdLevelDbm = -72;
962  m_obssRxPowerDbm = -72;
963  m_bssColor1 = 1;
964  m_bssColor2 = 2;
965  m_bssColor3 = 3;
966  RunOne();
967 
968  // Test case 4: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm with BSS color 2 and 3
969  // set to 0
970  m_obssPdLevelDbm = -72;
971  m_obssRxPowerDbm = -82;
972  m_bssColor1 = 1;
973  m_bssColor2 = 0;
974  m_bssColor3 = 0;
975  RunOne();
976 
977  // Test case 5: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm with BSS color 1 set to 0
978  m_obssPdLevelDbm = -72;
979  m_obssRxPowerDbm = -82;
980  m_bssColor1 = 0;
981  m_bssColor2 = 2;
982  m_bssColor3 = 3;
983  RunOne();
984 }
985 
994 {
995  public:
997 };
998 
1000  : TestSuite("wifi-inter-bss", UNIT)
1001 {
1004 }
1005 
1006 // Do not forget to allocate an instance of this TestSuite
#define min(a, b)
Definition: 80211b.c:41
Inter BSS Test Suite.
unsigned int m_numSta2PacketsSent
number of sent packets from STA2
unsigned int m_numAp2PacketsReceived
number of received packets from AP2
unsigned int m_numSta1PacketsSent
number of sent packets from STA1
double m_obssRxPowerDbm
forced RX power in dBm for OBSS
unsigned int m_payloadSize2
size in bytes of packet payload in BSS 2
Ptr< ListPositionAllocator > AllocatePositions(double d1, double d2, double d3, double d4, double d5)
Allocate the node positions.
void ClearDropReasons()
Clear the drop reasons.
std::vector< WifiPhyRxfailureReason > m_dropReasonsAp2
drop reasons for AP2
void SetupSimulation()
Setup the simulation.
void CheckPhyDropReasons(Ptr< WifiNetDevice > device, std::vector< WifiPhyRxfailureReason > expectedDropReasons)
Check if the Phy drop reasons for a device are as expected.
void SetExpectedTxPower(double txPowerDbm)
Set the expected transmit power in dBm.
unsigned int m_payloadSize3
size in bytes of packet payload in BSS 3
void NotifyPhyTxBegin(std::string context, Ptr< const Packet > p, double txPowerW)
Notify Phy transmit begin.
unsigned int m_payloadSize1
size in bytes of packet payload in BSS 1
void ResetResults()
Reset the results.
unsigned int m_numSta2PacketsReceived
number of received packets from STA2
unsigned int m_numAp2PacketsSent
number of sent packets from AP2
void CheckPhyState(Ptr< WifiNetDevice > device, WifiPhyState expectedState)
Check if the Phy State for a device is an expected value.
void CheckResults()
Check the results.
void NotifyPhyRxDrop(std::string context, Ptr< const Packet > p, WifiPhyRxfailureReason reason)
Notify Phy receive drops.
NetDeviceContainer m_staDevices
STA devices.
std::vector< WifiPhyRxfailureReason > m_dropReasonsSta1
drop reasons for STA1
void NotifyPhyRxEnd(std::string context, Ptr< const Packet > p)
Notify Phy receive ends.
void SendOnePacket(Ptr< WifiNetDevice > tx_dev, Ptr< WifiNetDevice > rx_dev, uint32_t payloadSize)
Send one packet function.
void DoRun() override
Implementation to actually run this TestCase.
TestInterBssConstantObssPdAlgo(WifiStandard standard)
Constructor.
std::vector< WifiPhyRxfailureReason > m_dropReasonsSta2
drop reasons for STA2
NetDeviceContainer m_apDevices
AP devices.
unsigned int m_numAp1PacketsSent
number of sent packets from AP1
double m_txPowerDbm
configured transmit power in dBm
std::vector< WifiPhyRxfailureReason > m_dropReasonsAp1
drop reasons for AP1
unsigned int m_numSta1PacketsReceived
number of received packets from STA1
unsigned int m_numAp1PacketsReceived
number of received packets from AP1
WifiStandard m_standard
the standard to use for the test
double m_obssPdLevelDbm
OBSS-PD level in dBm.
double m_expectedTxPowerDbm
expected transmit power in dBm
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:42
Helper class used to assign positions and mobility models to nodes.
Keep track of the current position and velocity of an object.
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t GetId() const
Definition: node.cc:117
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:202
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
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:324
create MAC layers for a ns3::WifiNetDevice.
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Ptr< HeConfiguration > GetHeConfiguration() const
Ptr< WifiPhy > GetPhy() const
Address GetAddress() const override
Ptr< Node > GetNode() const override
This objects implements the PHY state machine of the Wifi device.
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:974
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:876
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
bool TestDoubleIsEqual(const double x1, const double x2, const double epsilon)
Compare two double precision floating point numbers and declare them equal if they are within some ep...
Definition: test.cc:45
#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_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:251
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1350
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211ax
@ OBSS_PD_CCA_RESET
static uint32_t ConvertContextToNodeId(std::string context)
static InterBssTestSuite interBssTestSuite
void SendOnePacket(Ptr< LrWpanPhy > sender, Ptr< LrWpanPhy > receiver)
Send one packet.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
double WToDbm(double w)
Convert from Watts to dBm.
Definition: wifi-utils.cc:46
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
ssid
Definition: third.py:93
channel
Definition: third.py:88
mac
Definition: third.py:92
wifi
Definition: third.py:95
mobility
Definition: third.py:105
wifiStaNodes
Definition: third.py:84
phy
Definition: third.py:89
uint32_t pktSize
packet size used for the simulation (in bytes)
WifiPhyState
The state of the PHY layer.
@ CCA_BUSY
The PHY layer has sense the medium busy through the CCA mechanism.
@ RX
The PHY layer is receiving a packet.
@ TX
The PHY layer is sending a packet.
@ IDLE
The PHY layer is IDLE.