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:
82 
83  void DoRun() override;
84 
85  private:
92  void SendOnePacket(Ptr<WifiNetDevice> tx_dev, Ptr<WifiNetDevice> rx_dev, uint32_t payloadSize);
93 
103  Ptr<ListPositionAllocator> AllocatePositions(double d1,
104  double d2,
105  double d3,
106  double d4,
107  double d5);
108 
113  void SetExpectedTxPower(double txPowerDbm);
114 
118  void SetupSimulation();
119 
123  void CheckResults();
124 
128  void ResetResults();
129 
133  void ClearDropReasons();
134 
138  void RunOne();
139 
145  void CheckPhyState(Ptr<WifiNetDevice> device, WifiPhyState expectedState);
146 
152  void CheckPhyDropReasons(Ptr<WifiNetDevice> device,
153  std::vector<WifiPhyRxfailureReason> expectedDropReasons);
154 
161  void NotifyPhyTxBegin(std::string context, Ptr<const Packet> p, double txPowerW);
162 
168  void NotifyPhyRxEnd(std::string context, Ptr<const Packet> p);
169 
176  void NotifyPhyRxDrop(std::string context, Ptr<const Packet> p, WifiPhyRxfailureReason reason);
177 
178  unsigned int m_numSta1PacketsSent;
179  unsigned int m_numSta2PacketsSent;
180  unsigned int m_numAp1PacketsSent;
181  unsigned int m_numAp2PacketsSent;
182 
185  unsigned int m_numAp1PacketsReceived;
186  unsigned int m_numAp2PacketsReceived;
187 
188  std::vector<WifiPhyRxfailureReason> m_dropReasonsSta1;
189  std::vector<WifiPhyRxfailureReason> m_dropReasonsSta2;
190  std::vector<WifiPhyRxfailureReason> m_dropReasonsAp1;
191  std::vector<WifiPhyRxfailureReason> m_dropReasonsAp2;
192 
193  unsigned int m_payloadSize1;
194  unsigned int m_payloadSize2;
195  unsigned int m_payloadSize3;
196 
199 
200  double m_txPowerDbm;
204 
205  uint8_t m_bssColor1;
206  uint8_t m_bssColor2;
207  uint8_t m_bssColor3;
208 };
209 
211  : TestCase("InterBssConstantObssPd"),
212  m_numSta1PacketsSent(0),
213  m_numSta2PacketsSent(0),
214  m_numAp1PacketsSent(0),
215  m_numAp2PacketsSent(0),
216  m_numSta1PacketsReceived(0),
217  m_numSta2PacketsReceived(0),
218  m_numAp1PacketsReceived(0),
219  m_numAp2PacketsReceived(0),
220  m_payloadSize1(1000),
221  m_payloadSize2(1500),
222  m_payloadSize3(2000),
223  m_txPowerDbm(15),
224  m_obssPdLevelDbm(-72),
225  m_obssRxPowerDbm(-82),
226  m_expectedTxPowerDbm(15),
227  m_bssColor1(1),
228  m_bssColor2(2),
229  m_bssColor3(3)
230 {
231 }
232 
234 {
236 }
237 
240  double d2,
241  double d3,
242  double d4,
243  double d5)
244 {
245  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
246  positionAlloc->Add(Vector(0.0, 0.0, 0.0)); // AP1
247  positionAlloc->Add(Vector(d1 + d2, 0.0, 0.0)); // AP2
248  positionAlloc->Add(Vector(d1 + d2 + d3 + d4, 0.0, 0.0)); // AP3
249  positionAlloc->Add(Vector(d1, 0.0, 0.0)); // STA1
250  positionAlloc->Add(Vector(d1 + d2 + d3, 0.0, 0.0)); // STA2
251  positionAlloc->Add(Vector(d1 + d2 + d3 + d4 + d5, 0.0, 0.0)); // STA3
252  return positionAlloc;
253 }
254 
255 void
257 {
258  Ptr<WifiNetDevice> ap_device1 = DynamicCast<WifiNetDevice>(m_apDevices.Get(0));
259  Ptr<WifiNetDevice> ap_device2 = DynamicCast<WifiNetDevice>(m_apDevices.Get(1));
260  Ptr<WifiNetDevice> ap_device3 = DynamicCast<WifiNetDevice>(m_apDevices.Get(2));
261  Ptr<WifiNetDevice> sta_device1 = DynamicCast<WifiNetDevice>(m_staDevices.Get(0));
262  Ptr<WifiNetDevice> sta_device2 = DynamicCast<WifiNetDevice>(m_staDevices.Get(1));
263  Ptr<WifiNetDevice> sta_device3 = DynamicCast<WifiNetDevice>(m_staDevices.Get(2));
264 
265  bool expectFilter = (m_bssColor1 != 0) && (m_bssColor2 != 0);
266  bool expectPhyReset = expectFilter && (m_obssPdLevelDbm >= m_obssRxPowerDbm);
267  std::vector<WifiPhyRxfailureReason> dropReasons;
268  WifiPhyState stateDuringPayloadNeighboringBss =
269  expectFilter ? WifiPhyState::CCA_BUSY : WifiPhyState::RX;
270  if (expectFilter)
271  {
272  dropReasons.push_back(FILTERED);
273  }
274  if (expectPhyReset)
275  {
276  dropReasons.push_back(OBSS_PD_CCA_RESET);
277  }
278 
279  // In order to have all ADDBA handshakes established, each AP and STA sends a packet.
280 
281  Simulator::Schedule(Seconds(0.25),
283  this,
284  ap_device1,
285  sta_device1,
287  Simulator::Schedule(Seconds(0.5),
289  this,
290  sta_device1,
291  ap_device1,
293  Simulator::Schedule(Seconds(0.75),
295  this,
296  ap_device2,
297  sta_device2,
299  Simulator::Schedule(Seconds(1),
301  this,
302  sta_device2,
303  ap_device2,
305  Simulator::Schedule(Seconds(1.25),
307  this,
308  ap_device3,
309  sta_device3,
311  Simulator::Schedule(Seconds(1.5),
313  this,
314  sta_device3,
315  ap_device3,
317 
318  // We test PHY state and verify whether a CCA reset did occur.
319 
320  // AP2 sends a packet 0.5s later.
321  Simulator::Schedule(Seconds(2.0), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
322  Simulator::Schedule(Seconds(2.0),
324  this,
325  ap_device2,
326  sta_device2,
328  Simulator::Schedule(Seconds(2.0) + MicroSeconds(10),
330  this,
331  ap_device2,
333  // All other PHYs should have stay idle until 4us (preamble detection time).
334  Simulator::Schedule(Seconds(2.0) + MicroSeconds(13),
336  this,
337  sta_device1,
339  Simulator::Schedule(Seconds(2.0) + MicroSeconds(13),
341  this,
342  sta_device2,
344  Simulator::Schedule(Seconds(2.0) + MicroSeconds(13),
346  this,
347  ap_device1,
349  // All PHYs should be receiving the PHY header (i.e. PHY state is CCA_BUSY) if preamble has been
350  // detected (always the case in this test).
351  Simulator::Schedule(Seconds(2.0) + MicroSeconds(14),
353  this,
354  sta_device1,
356  Simulator::Schedule(Seconds(2.0) + MicroSeconds(14),
358  this,
359  sta_device2,
361  Simulator::Schedule(Seconds(2.0) + MicroSeconds(14),
363  this,
364  ap_device1,
366  // PHYs of AP1 and STA1 should be idle after HE-SIG-A if they were reset by OBSS_PD SR,
367  // otherwise they should be CCA_busy until beginning of payload.
368  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
370  this,
371  sta_device1,
372  dropReasons);
373  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
375  this,
376  sta_device1,
377  expectPhyReset ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
378  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
380  this,
381  ap_device1,
382  dropReasons);
383  Simulator::Schedule(Seconds(2.0) + MicroSeconds(43),
385  this,
386  ap_device1,
387  expectPhyReset ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
388  // PHYs of AP1 and STA1 should be idle if they were reset by OBSS_PD SR, otherwise they should
389  // be CCA_busy/Rx (since filtered/not filtered, resp.).
390  Simulator::Schedule(Seconds(2.0) + MicroSeconds(54),
392  this,
393  sta_device1,
394  expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
395  Simulator::Schedule(Seconds(2.0) + MicroSeconds(54),
397  this,
398  ap_device1,
399  expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
400  // STA2 should be receiving
401  Simulator::Schedule(Seconds(2.0) + MicroSeconds(54),
403  this,
404  sta_device2,
406 
407  // We test whether two networks can transmit simultaneously, and whether transmit power
408  // restrictions are applied.
409 
410  // AP2 sends another packet 0.1s later.
411  Simulator::Schedule(Seconds(2.1), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
412  Simulator::Schedule(Seconds(2.1),
414  this,
415  ap_device2,
416  sta_device2,
418  // STA1 sends a packet 42us later (i.e. right after HE-SIG-A of AP2). Even though AP2 is still
419  // transmitting, STA1 can transmit simultaneously if it's PHY was reset by OBSS_PD SR.
420  Simulator::Schedule(Seconds(2.1) + MicroSeconds(42),
422  this,
423  sta_device1,
424  ap_device1,
426  if (expectPhyReset)
427  {
428  // In this case, we check the TX power is restricted (and set the expected value slightly
429  // before transmission should occur)
430  double expectedTxPower = std::min(m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
431  Simulator::Schedule(Seconds(2.1) + MicroSeconds(41),
433  this,
434  expectedTxPower);
435  }
436  // Check simultaneous transmissions
437  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
439  this,
440  ap_device2,
442  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
444  this,
445  sta_device1,
446  dropReasons);
447  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
449  this,
450  sta_device1,
451  expectPhyReset ? WifiPhyState::TX : stateDuringPayloadNeighboringBss);
452  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
454  this,
455  sta_device2,
457  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
459  this,
460  ap_device1,
461  dropReasons);
462  Simulator::Schedule(Seconds(2.1) + MicroSeconds(100),
464  this,
465  ap_device1,
466  stateDuringPayloadNeighboringBss);
467  Simulator::Schedule(Seconds(2.1) + MicroSeconds(142),
469  this,
470  ap_device1,
471  expectPhyReset ? WifiPhyState::RX : stateDuringPayloadNeighboringBss);
472 
473  // AP2 sends another packet 0.1s later, and STA1 wanting to send a packet during the payload of
474  // the former.
475  Simulator::Schedule(Seconds(2.2), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
476  Simulator::Schedule(Seconds(2.2),
478  this,
479  m_txPowerDbm);
480  Simulator::Schedule(Seconds(2.2),
482  this,
483  ap_device2,
484  sta_device2,
486  // STA1 sends a packet 90us later (i.e. during payload of AP2). Even though AP2 is still
487  // transmitting, STA1 can transmit simultaneously if it's PHY was reset by OBSS_PD SR.
488  Simulator::Schedule(Seconds(2.2) + MicroSeconds(90),
490  this,
491  sta_device1,
492  ap_device1,
494  if (expectPhyReset)
495  {
496  // In this case, we check the TX power is restricted (and set the expected value slightly
497  // before transmission should occur)
498  double expectedTxPower = std::min(m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
499  Simulator::Schedule(Seconds(2.2) + MicroSeconds(89),
501  this,
502  expectedTxPower);
503  }
504  // Check simultaneous transmissions
505  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
507  this,
508  ap_device2,
510  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
512  this,
513  sta_device1,
514  dropReasons);
515  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
517  this,
518  sta_device1,
519  expectPhyReset ? WifiPhyState::TX : stateDuringPayloadNeighboringBss);
520  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
522  this,
523  sta_device2,
525  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
527  this,
528  ap_device1,
529  dropReasons);
530  Simulator::Schedule(Seconds(2.2) + MicroSeconds(105),
532  this,
533  ap_device1,
534  stateDuringPayloadNeighboringBss);
535  Simulator::Schedule(Seconds(2.2) + MicroSeconds(195),
537  this,
538  ap_device1,
539  expectPhyReset ? WifiPhyState::RX : stateDuringPayloadNeighboringBss);
540 
541  // Verify transmit power restrictions are not applied if access to the channel is requested
542  // after ignored OBSS transmissions.
543 
544  Simulator::Schedule(Seconds(2.3),
546  this,
547  m_txPowerDbm);
548  // AP2 sends another packet 0.1s later. Power restriction should not be applied.
549  Simulator::Schedule(Seconds(2.3),
551  this,
552  ap_device2,
553  sta_device2,
555  // STA1 sends a packet 0.1s later. Power restriction should not be applied.
556  Simulator::Schedule(Seconds(2.4),
558  this,
559  sta_device1,
560  ap_device1,
562 
563  // Verify a scenario that involves 3 networks in order to verify corner cases for transmit power
564  // restrictions. First, there is a transmission on network 2 from STA to AP, followed by a
565  // response from AP to STA. During that time, the STA on network 1 has a packet to send and
566  // request access to the channel. If a CCA reset occurred, it starts deferring while
567  // transmissions are ongoing from network 2. Before its backoff expires, a transmission on
568  // network 3 occurs, also eventually triggering another CCA reset (depending on the scenario
569  // that is being run). This test checks whether this sequence preserves transmit power
570  // restrictions if CCA resets occurred, since STA 1 has been deferring during ignored OBSS
571  // transmissions.
572 
573  Simulator::Schedule(Seconds(2.5),
575  this,
576  sta_device2,
577  ap_device2,
578  m_payloadSize2 / 10);
579  Simulator::Schedule(Seconds(2.5) + MicroSeconds(15),
581  this,
582  ap_device2,
583  sta_device2,
584  m_payloadSize2 / 10);
585  Simulator::Schedule(Seconds(2.5) + MicroSeconds(270),
587  this,
588  ap_device1,
589  sta_device1,
590  m_payloadSize1 / 10);
591  Simulator::Schedule(Seconds(2.5) + MicroSeconds(300),
593  this,
594  ap_device3,
595  sta_device3,
596  m_payloadSize3 / 10);
597  if (expectPhyReset)
598  {
599  // In this case, we check the TX power is restricted (and set the expected value slightly
600  // before transmission should occur)
601  double expectedTxPower = std::min(m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
602  Simulator::Schedule(Seconds(2.5) + MicroSeconds(338),
604  this,
605  expectedTxPower);
606  }
607 
608  Simulator::Stop(Seconds(2.6));
609 }
610 
611 void
613 {
624 }
625 
626 void
628 {
629  m_dropReasonsSta1.clear();
630  m_dropReasonsSta2.clear();
631  m_dropReasonsAp1.clear();
632  m_dropReasonsAp2.clear();
633 }
634 
635 void
637 {
639  4,
640  "The number of packets sent by STA1 is not correct!");
642  2,
643  "The number of packets sent by STA2 is not correct!");
645  2,
646  "The number of packets sent by AP1 is not correct!");
648  6,
649  "The number of packets sent by AP2 is not correct!");
651  2,
652  "The number of packets received by STA1 is not correct!");
654  6,
655  "The number of packets received by STA2 is not correct!");
657  4,
658  "The number of packets received by AP1 is not correct!");
660  2,
661  "The number of packets received by AP2 is not correct!");
662 }
663 
664 void
667  double txPowerW)
668 {
669  uint32_t idx = ConvertContextToNodeId(context);
670  uint32_t pktSize = p->GetSize() - 38;
671  if ((idx == 0) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
672  {
675  true,
676  "Tx power is not correct!");
677  }
678  else if ((idx == 1) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
679  {
682  true,
683  "Tx power is not correct!");
684  }
685  else if ((idx == 3) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
686  {
689  true,
690  "Tx power is not correct!");
691  }
692  else if ((idx == 4) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
693  {
696  true,
697  "Tx power is not correct!");
698  }
699 }
700 
701 void
703 {
704  uint32_t idx = ConvertContextToNodeId(context);
705  uint32_t pktSize = p->GetSize() - 38;
706  if ((idx == 0) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
707  {
709  }
710  else if ((idx == 1) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
711  {
713  }
714  else if ((idx == 3) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
715  {
717  }
718  else if ((idx == 4) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
719  {
721  }
722 }
723 
724 void
727  WifiPhyRxfailureReason reason)
728 {
729  uint32_t idx = ConvertContextToNodeId(context);
730  uint32_t pktSize = p->GetSize() - 38;
731  if ((idx == 0) && ((pktSize != m_payloadSize1) && (pktSize != (m_payloadSize1 / 10))))
732  {
733  m_dropReasonsSta1.push_back(reason);
734  }
735  else if ((idx == 1) && ((pktSize != m_payloadSize2) && (pktSize != (m_payloadSize2 / 10))))
736  {
737  m_dropReasonsSta2.push_back(reason);
738  }
739  else if ((idx == 3) && ((pktSize != m_payloadSize1) && (pktSize != (m_payloadSize1 / 10))))
740  {
741  m_dropReasonsAp1.push_back(reason);
742  }
743  else if ((idx == 4) && ((pktSize != m_payloadSize2) && (pktSize != (m_payloadSize2 / 10))))
744  {
745  m_dropReasonsAp2.push_back(reason);
746  }
747 }
748 
749 void
751  Ptr<WifiNetDevice> rx_dev,
752  uint32_t payloadSize)
753 {
754  Ptr<Packet> p = Create<Packet>(payloadSize);
755  tx_dev->Send(p, rx_dev->GetAddress(), 1);
756 }
757 
758 void
760 {
761  m_expectedTxPowerDbm = txPowerDbm;
762 }
763 
764 void
766 {
767  WifiPhyState currentState;
768  PointerValue ptr;
769  Ptr<WifiPhy> phy = DynamicCast<WifiPhy>(device->GetPhy());
770  phy->GetAttribute("State", ptr);
771  Ptr<WifiPhyStateHelper> state = DynamicCast<WifiPhyStateHelper>(ptr.Get<WifiPhyStateHelper>());
772  currentState = state->GetState();
773  NS_TEST_ASSERT_MSG_EQ(currentState,
774  expectedState,
775  "PHY State " << currentState << " does not match expected state "
776  << expectedState << " at " << Simulator::Now());
777 }
778 
779 void
781  Ptr<WifiNetDevice> device,
782  std::vector<WifiPhyRxfailureReason> expectedDropReasons)
783 {
784  std::vector<WifiPhyRxfailureReason> currentDropReasons;
785  uint32_t nodeId = device->GetNode()->GetId();
786  switch (nodeId)
787  {
788  case 0: // STA1
789  currentDropReasons = m_dropReasonsSta1;
790  break;
791  case 1: // STA2
792  currentDropReasons = m_dropReasonsSta2;
793  break;
794  case 3: // AP1
795  currentDropReasons = m_dropReasonsAp1;
796  break;
797  case 4: // AP2
798  currentDropReasons = m_dropReasonsAp2;
799  break;
800  default: // others, no attribute
801  return;
802  }
803  NS_TEST_ASSERT_MSG_EQ(currentDropReasons.size(),
804  expectedDropReasons.size(),
805  "Number of drop reasons "
806  << currentDropReasons.size() << " does not match expected one "
807  << expectedDropReasons.size() << " at " << Simulator::Now());
808  for (std::size_t i = 0; i < currentDropReasons.size(); ++i)
809  {
810  NS_TEST_ASSERT_MSG_EQ(currentDropReasons[i],
811  expectedDropReasons[i],
812  "Drop reason " << i << ": " << currentDropReasons[i]
813  << " does not match expected reason "
814  << expectedDropReasons[i] << " at "
815  << Simulator::Now());
816  }
817 }
818 
819 void
821 {
822  RngSeedManager::SetSeed(1);
823  RngSeedManager::SetRun(3);
824  int64_t streamNumber = 50;
825 
826  Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize",
827  UintegerValue(0));
828 
829  ResetResults();
830 
832  wifiStaNodes.Create(3);
833 
834  NodeContainer wifiApNodes;
835  wifiApNodes.Create(3);
836 
837  Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel>();
838  lossModel->SetDefaultLoss(
839  m_txPowerDbm - m_obssRxPowerDbm); // Force received RSSI to be equal to m_obssRxPowerDbm
840 
842  phy.DisablePreambleDetectionModel();
843  phy.SetFrameCaptureModel("ns3::SimpleFrameCaptureModel");
844  Ptr<MultiModelSpectrumChannel> channel = CreateObject<MultiModelSpectrumChannel>();
845  channel->SetPropagationDelayModel(CreateObject<ConstantSpeedPropagationDelayModel>());
846  channel->AddPropagationLossModel(lossModel);
847  phy.SetChannel(channel);
848  phy.Set("TxPowerStart", DoubleValue(m_txPowerDbm));
849  phy.Set("TxPowerEnd", DoubleValue(m_txPowerDbm));
850  phy.Set("ChannelSettings", StringValue("{36, 20, BAND_5GHZ, 0}"));
851 
853  wifi.SetStandard(WIFI_STANDARD_80211ax);
854  wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
855  "DataMode",
856  StringValue("HeMcs5"),
857  "ControlMode",
858  StringValue("HeMcs0"));
859 
860  wifi.SetObssPdAlgorithm("ns3::ConstantObssPdAlgorithm",
861  "ObssPdLevel",
863 
865  Ssid ssid = Ssid("ns-3-ssid");
866  mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
867  m_staDevices = wifi.Install(phy, mac, wifiStaNodes);
868 
869  // Assign fixed streams to random variables in use
870  wifi.AssignStreams(m_staDevices, streamNumber);
871 
872  mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
873  m_apDevices = wifi.Install(phy, mac, wifiApNodes);
874 
875  // Assign fixed streams to random variables in use
876  wifi.AssignStreams(m_apDevices, streamNumber);
877 
878  for (uint32_t i = 0; i < m_apDevices.GetN(); i++)
879  {
880  Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice>(m_apDevices.Get(i));
881  Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration();
882  if (i == 0)
883  {
884  heConfiguration->SetAttribute("BssColor", UintegerValue(m_bssColor1));
885  }
886  else if (i == 1)
887  {
888  heConfiguration->SetAttribute("BssColor", UintegerValue(m_bssColor2));
889  }
890  else
891  {
892  heConfiguration->SetAttribute("BssColor", UintegerValue(m_bssColor3));
893  }
894  }
895 
898  10,
899  50,
900  10,
901  50,
902  10); // distances do not really matter since we set RSSI per TX-RX pair to have full control
903  mobility.SetPositionAllocator(positionAlloc);
904  mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
905  mobility.Install(wifiApNodes);
906  mobility.Install(wifiStaNodes);
907 
908  lossModel->SetLoss(wifiStaNodes.Get(0)->GetObject<MobilityModel>(),
909  wifiApNodes.Get(0)->GetObject<MobilityModel>(),
910  m_txPowerDbm + 30); // Low attenuation for IBSS transmissions
911  lossModel->SetLoss(wifiStaNodes.Get(1)->GetObject<MobilityModel>(),
912  wifiApNodes.Get(1)->GetObject<MobilityModel>(),
913  m_txPowerDbm + 30); // Low attenuation for IBSS transmissions
914  lossModel->SetLoss(wifiStaNodes.Get(2)->GetObject<MobilityModel>(),
915  wifiApNodes.Get(2)->GetObject<MobilityModel>(),
916  m_txPowerDbm + 30); // Low attenuation for IBSS transmissions
917 
918  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin",
920  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxEnd",
922  Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop",
924 
925  SetupSimulation();
926 
927  Simulator::Run();
928  Simulator::Destroy();
929 
930  CheckResults();
931 }
932 
933 void
935 {
936  // Test case 1: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm
937  m_obssPdLevelDbm = -72;
938  m_obssRxPowerDbm = -82;
939  m_bssColor1 = 1;
940  m_bssColor2 = 2;
941  m_bssColor3 = 3;
942  RunOne();
943 
944  // Test case 2: CCA CS Threshold < m_obssPdLevelDbm < m_obssRxPowerDbm
945  m_obssPdLevelDbm = -72;
946  m_obssRxPowerDbm = -62;
947  m_bssColor1 = 1;
948  m_bssColor2 = 2;
949  m_bssColor3 = 3;
950  RunOne();
951 
952  // Test case 3: CCA CS Threshold < m_obssPdLevelDbm = m_obssRxPowerDbm
953  m_obssPdLevelDbm = -72;
954  m_obssRxPowerDbm = -72;
955  m_bssColor1 = 1;
956  m_bssColor2 = 2;
957  m_bssColor3 = 3;
958  RunOne();
959 
960  // Test case 4: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm with BSS color 2 and 3
961  // set to 0
962  m_obssPdLevelDbm = -72;
963  m_obssRxPowerDbm = -82;
964  m_bssColor1 = 1;
965  m_bssColor2 = 0;
966  m_bssColor3 = 0;
967  RunOne();
968 
969  // Test case 5: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm with BSS color 1 set to 0
970  m_obssPdLevelDbm = -72;
971  m_obssRxPowerDbm = -82;
972  m_bssColor1 = 0;
973  m_bssColor2 = 2;
974  m_bssColor3 = 3;
975  RunOne();
976 }
977 
986 {
987  public:
989 };
990 
992  : TestSuite("wifi-inter-bss", UNIT)
993 {
994  AddTestCase(new TestInterBssConstantObssPdAlgo, TestCase::QUICK);
995 }
996 
997 // Do not forget to allocate an instance of this TestSuite
#define min(a, b)
Definition: 80211b.c:42
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.
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
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:863
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get() const
Definition: pointer.h:206
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
Hold an unsigned integer type.
Definition: uinteger.h:45
helps to create WifiNetDevice objects
Definition: wifi-helper.h:325
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:975
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:877
#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:296
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:1360
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
@ 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:707
ssid
Definition: third.py:86
channel
Definition: third.py:81
mac
Definition: third.py:85
wifi
Definition: third.py:88
mobility
Definition: third.py:96
wifiStaNodes
Definition: third.py:77
phy
Definition: third.py:82
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.