A Discrete-Event Network Simulator
API
inter-bss-test-suite.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2018 University of Washington
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Sébastien Deronne <sebastien.deronne@gmail.com>
19  * Scott Carpenter <scarpenter44@windstream.net>
20  */
21 
22 #include "ns3/log.h"
23 #include "ns3/test.h"
24 #include "ns3/uinteger.h"
25 #include "ns3/double.h"
26 #include "ns3/string.h"
27 #include "ns3/pointer.h"
28 #include "ns3/config.h"
29 #include "ns3/ssid.h"
30 #include "ns3/rng-seed-manager.h"
31 #include "ns3/mobility-helper.h"
32 #include "ns3/wifi-net-device.h"
33 #include "ns3/spectrum-wifi-helper.h"
34 #include "ns3/multi-model-spectrum-channel.h"
35 #include "ns3/constant-obss-pd-algorithm.h"
36 #include "ns3/he-configuration.h"
37 #include "ns3/wifi-utils.h"
38 
39 using namespace ns3;
40 
41 NS_LOG_COMPONENT_DEFINE ("InterBssTestSuite");
42 
43 static uint32_t
44 ConvertContextToNodeId (std::string context)
45 {
46  std::string sub = context.substr (10);
47  uint32_t pos = sub.find ("/Device");
48  uint32_t nodeId = atoi (sub.substr (0, pos).c_str ());
49  return nodeId;
50 }
51 
79 {
80 public:
83 
84  void DoRun (void) override;
85 
86 private:
93  void SendOnePacket (Ptr<WifiNetDevice> tx_dev, Ptr<WifiNetDevice> rx_dev, uint32_t payloadSize);
94 
104  Ptr<ListPositionAllocator> AllocatePositions (double d1, double d2, double d3, double d4, double d5);
105 
110  void SetExpectedTxPower (double txPowerDbm);
111 
115  void SetupSimulation ();
116 
120  void CheckResults ();
121 
125  void ResetResults ();
126 
130  void ClearDropReasons ();
131 
135  void RunOne ();
136 
142  void CheckPhyState (Ptr<WifiNetDevice> device, WifiPhyState expectedState);
143 
149  void CheckPhyDropReasons (Ptr<WifiNetDevice> device, std::vector<WifiPhyRxfailureReason> expectedDropReasons);
150 
157  void NotifyPhyTxBegin (std::string context, Ptr<const Packet> p, double txPowerW);
158 
164  void NotifyPhyRxEnd (std::string context, Ptr<const Packet> p);
165 
172  void NotifyPhyRxDrop (std::string context, Ptr<const Packet> p, WifiPhyRxfailureReason reason);
173 
174  unsigned int m_numSta1PacketsSent;
175  unsigned int m_numSta2PacketsSent;
176  unsigned int m_numAp1PacketsSent;
177  unsigned int m_numAp2PacketsSent;
178 
181  unsigned int m_numAp1PacketsReceived;
182  unsigned int m_numAp2PacketsReceived;
183 
184  std::vector<WifiPhyRxfailureReason> m_dropReasonsSta1;
185  std::vector<WifiPhyRxfailureReason> m_dropReasonsSta2;
186  std::vector<WifiPhyRxfailureReason> m_dropReasonsAp1;
187  std::vector<WifiPhyRxfailureReason> m_dropReasonsAp2;
188 
189  unsigned int m_payloadSize1;
190  unsigned int m_payloadSize2;
191  unsigned int m_payloadSize3;
192 
195 
196  double m_txPowerDbm;
200 
201  uint8_t m_bssColor1;
202  uint8_t m_bssColor2;
203  uint8_t m_bssColor3;
204 };
205 
207  : TestCase ("InterBssConstantObssPd"),
208  m_numSta1PacketsSent (0),
209  m_numSta2PacketsSent (0),
210  m_numAp1PacketsSent (0),
211  m_numAp2PacketsSent (0),
212  m_numSta1PacketsReceived (0),
213  m_numSta2PacketsReceived (0),
214  m_numAp1PacketsReceived (0),
215  m_numAp2PacketsReceived (0),
216  m_payloadSize1 (1000),
217  m_payloadSize2 (1500),
218  m_payloadSize3 (2000),
219  m_txPowerDbm (15),
220  m_obssPdLevelDbm (-72),
221  m_obssRxPowerDbm (-82),
222  m_expectedTxPowerDbm (15),
223  m_bssColor1 (1),
224  m_bssColor2 (2),
225  m_bssColor3 (3)
226 {
227 }
228 
230 {
231  ClearDropReasons ();
232 }
233 
235 TestInterBssConstantObssPdAlgo::AllocatePositions (double d1, double d2, double d3, double d4, double d5)
236 {
237  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
238  positionAlloc->Add (Vector (0.0, 0.0, 0.0)); // AP1
239  positionAlloc->Add (Vector (d1 + d2, 0.0, 0.0)); // AP2
240  positionAlloc->Add (Vector (d1 + d2 + d3 + d4, 0.0, 0.0)); // AP3
241  positionAlloc->Add (Vector (d1, 0.0, 0.0)); // STA1
242  positionAlloc->Add (Vector (d1 + d2 + d3, 0.0, 0.0)); // STA2
243  positionAlloc->Add (Vector (d1 + d2 + d3 + d4 + d5, 0.0, 0.0)); // STA3
244  return positionAlloc;
245 }
246 
247 void
249 {
250  Ptr<WifiNetDevice> ap_device1 = DynamicCast<WifiNetDevice> (m_apDevices.Get (0));
251  Ptr<WifiNetDevice> ap_device2 = DynamicCast<WifiNetDevice> (m_apDevices.Get (1));
252  Ptr<WifiNetDevice> ap_device3 = DynamicCast<WifiNetDevice> (m_apDevices.Get (2));
253  Ptr<WifiNetDevice> sta_device1 = DynamicCast<WifiNetDevice> (m_staDevices.Get (0));
254  Ptr<WifiNetDevice> sta_device2 = DynamicCast<WifiNetDevice> (m_staDevices.Get (1));
255  Ptr<WifiNetDevice> sta_device3 = DynamicCast<WifiNetDevice> (m_staDevices.Get (2));
256 
257  bool expectFilter = (m_bssColor1 != 0) && (m_bssColor2 != 0);
258  bool expectPhyReset = expectFilter && (m_obssPdLevelDbm >= m_obssRxPowerDbm);
259  std::vector<WifiPhyRxfailureReason> dropReasons;
260  WifiPhyState stateDuringPayloadNeighboringBss = expectFilter ? WifiPhyState::CCA_BUSY : WifiPhyState::RX;
261  if (expectFilter)
262  {
263  dropReasons.push_back (FILTERED);
264  }
265  if (expectPhyReset)
266  {
267  dropReasons.push_back (OBSS_PD_CCA_RESET);
268  }
269 
270  // In order to have all ADDBA handshakes established, each AP and STA sends a packet.
271 
272  Simulator::Schedule (Seconds (0.25), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device1, sta_device1, m_payloadSize1);
273  Simulator::Schedule (Seconds (0.5), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, sta_device1, ap_device1, m_payloadSize1);
274  Simulator::Schedule (Seconds (0.75), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device2, sta_device2, m_payloadSize2);
275  Simulator::Schedule (Seconds (1), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, sta_device2, ap_device2, m_payloadSize2);
276  Simulator::Schedule (Seconds (1.25), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device3, sta_device3, m_payloadSize3);
277  Simulator::Schedule (Seconds (1.5), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, sta_device3, ap_device3, m_payloadSize3);
278 
279  // We test PHY state and verify whether a CCA reset did occur.
280 
281  // AP2 sends a packet 0.5s later.
282  Simulator::Schedule (Seconds (2.0), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
283  Simulator::Schedule (Seconds (2.0), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device2, sta_device2, m_payloadSize2);
284  Simulator::Schedule (Seconds (2.0) + MicroSeconds (5), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device2, WifiPhyState::TX);
285  // All other PHYs should have stay idle until 4us (preamble detection time).
286  Simulator::Schedule (Seconds (2.0) + MicroSeconds (6), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, WifiPhyState::IDLE);
287  Simulator::Schedule (Seconds (2.0) + MicroSeconds (6), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device2, WifiPhyState::IDLE);
288  Simulator::Schedule (Seconds (2.0) + MicroSeconds (6), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, WifiPhyState::IDLE);
289  // All PHYs should be receiving the PHY header (i.e. PHY state is CCA_BUSY) if preamble has been detected (always the case in this test).
290  Simulator::Schedule (Seconds (2.0) + MicroSeconds (10), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, WifiPhyState::CCA_BUSY);
291  Simulator::Schedule (Seconds (2.0) + MicroSeconds (10), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device2, WifiPhyState::CCA_BUSY);
292  Simulator::Schedule (Seconds (2.0) + MicroSeconds (10), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, WifiPhyState::CCA_BUSY);
293  // PHYs of AP1 and STA1 should be idle after HE-SIG-A if they were reset by OBSS_PD SR, otherwise they should be CCA_busy until beginning of payload.
294  Simulator::Schedule (Seconds (2.0) + MicroSeconds (35), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, sta_device1, dropReasons);
295  Simulator::Schedule (Seconds (2.0) + MicroSeconds (35), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, expectPhyReset ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
296  Simulator::Schedule (Seconds (2.0) + MicroSeconds (35), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, ap_device1, dropReasons);
297  Simulator::Schedule (Seconds (2.0) + MicroSeconds (35), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, expectPhyReset ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
298  // PHYs of AP1 and STA1 should be idle if they were reset by OBSS_PD SR, otherwise they should be CCA_busy/Rx (since filtered/not filtered, resp.).
299  Simulator::Schedule (Seconds (2.0) + MicroSeconds (50), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
300  Simulator::Schedule (Seconds (2.0) + MicroSeconds (50), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
301  // STA2 should be receiving
302  Simulator::Schedule (Seconds (2.0) + MicroSeconds (50), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device2, WifiPhyState::RX);
303 
304  // We test whether two networks can transmit simultaneously, and whether transmit power restrictions are applied.
305 
306  // AP2 sends another packet 0.1s later.
307  Simulator::Schedule (Seconds (2.1), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
308  Simulator::Schedule (Seconds (2.1), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device2, sta_device2, m_payloadSize2);
309  // STA1 sends a packet 42us later (i.e. right after HE-SIG-A of AP2). Even though AP2 is still transmitting, STA1 can transmit simultaneously if it's PHY was reset by OBSS_PD SR.
310  Simulator::Schedule (Seconds (2.1) + MicroSeconds (42), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, sta_device1, ap_device1, m_payloadSize1);
311  if (expectPhyReset)
312  {
313  // In this case, we check the TX power is restricted (and set the expected value slightly before transmission should occur)
314  double expectedTxPower = std::min (m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
315  Simulator::Schedule (Seconds (2.1) + MicroSeconds (41), &TestInterBssConstantObssPdAlgo::SetExpectedTxPower, this, expectedTxPower);
316  }
317  // Check simultaneous transmissions
318  Simulator::Schedule (Seconds (2.1) + MicroSeconds (100), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device2, WifiPhyState::TX);
319  Simulator::Schedule (Seconds (2.1) + MicroSeconds (100), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, sta_device1, dropReasons);
320  Simulator::Schedule (Seconds (2.1) + MicroSeconds (100), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, expectPhyReset ? WifiPhyState::TX : stateDuringPayloadNeighboringBss);
321  Simulator::Schedule (Seconds (2.1) + MicroSeconds (100), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device2, WifiPhyState::RX);
322  Simulator::Schedule (Seconds (2.1) + MicroSeconds (100), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, ap_device1, dropReasons);
323  Simulator::Schedule (Seconds (2.1) + MicroSeconds (100), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, stateDuringPayloadNeighboringBss);
324  Simulator::Schedule (Seconds (2.1) + MicroSeconds (142), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, expectPhyReset ? WifiPhyState::RX : stateDuringPayloadNeighboringBss);
325 
326  // AP2 sends another packet 0.1s later, and STA1 wanting to send a packet during the payload of the former.
327  Simulator::Schedule (Seconds (2.2), &TestInterBssConstantObssPdAlgo::ClearDropReasons, this);
328  Simulator::Schedule (Seconds (2.2), &TestInterBssConstantObssPdAlgo::SetExpectedTxPower, this, m_txPowerDbm);
329  Simulator::Schedule (Seconds (2.2), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device2, sta_device2, m_payloadSize2);
330  // STA1 sends a packet 90us later (i.e. during payload of AP2). Even though AP2 is still transmitting, STA1 can transmit simultaneously if it's PHY was reset by OBSS_PD SR.
331  Simulator::Schedule (Seconds (2.2) + MicroSeconds (90), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, sta_device1, ap_device1, m_payloadSize1);
332  if (expectPhyReset)
333  {
334  // In this case, we check the TX power is restricted (and set the expected value slightly before transmission should occur)
335  double expectedTxPower = std::min (m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
336  Simulator::Schedule (Seconds (2.2) + MicroSeconds (89), &TestInterBssConstantObssPdAlgo::SetExpectedTxPower, this, expectedTxPower);
337  }
338  // Check simultaneous transmissions
339  Simulator::Schedule (Seconds (2.2) + MicroSeconds (105), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device2, WifiPhyState::TX);
340  Simulator::Schedule (Seconds (2.2) + MicroSeconds (105), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, sta_device1, dropReasons);
341  Simulator::Schedule (Seconds (2.2) + MicroSeconds (105), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, expectPhyReset ? WifiPhyState::TX : stateDuringPayloadNeighboringBss);
342  Simulator::Schedule (Seconds (2.2) + MicroSeconds (105), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device2, WifiPhyState::RX);
343  Simulator::Schedule (Seconds (2.2) + MicroSeconds (105), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, ap_device1, dropReasons);
344  Simulator::Schedule (Seconds (2.2) + MicroSeconds (105), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, stateDuringPayloadNeighboringBss);
345  Simulator::Schedule (Seconds (2.2) + MicroSeconds (195), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, expectPhyReset ? WifiPhyState::RX : stateDuringPayloadNeighboringBss);
346 
347 
348  // Verify transmit power restrictions are not applied if access to the channel is requested after ignored OBSS transmissions.
349 
350  Simulator::Schedule (Seconds (2.3), &TestInterBssConstantObssPdAlgo::SetExpectedTxPower, this, m_txPowerDbm);
351  // AP2 sends another packet 0.1s later. Power restriction should not be applied.
352  Simulator::Schedule (Seconds (2.3), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device2, sta_device2, m_payloadSize2);
353  // STA1 sends a packet 0.1s later. Power restriction should not be applied.
354  Simulator::Schedule (Seconds (2.4), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, sta_device1, ap_device1, m_payloadSize1);
355 
356  // Verify a scenario that involves 3 networks in order to verify corner cases for transmit power restrictions.
357  // First, there is a transmission on network 2 from STA to AP, followed by a response from AP to STA.
358  // During that time, the STA on network 1 has a packet to send and request access to the channel.
359  // If a CCA reset occurred, it starts deferring while transmissions are ongoing from network 2.
360  // Before its backoff expires, a transmission on network 3 occurs, also eventually triggering another CCA reset (depending on the scenario that is being run).
361  // This test checks whether this sequence preserves transmit power restrictions if CCA resets occurred, since STA 1 has been deferring during ignored OBSS transmissions.
362 
363  Simulator::Schedule (Seconds (2.5), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, sta_device2, ap_device2, m_payloadSize2 / 10);
364  Simulator::Schedule (Seconds (2.5) + MicroSeconds (15), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device2, sta_device2, m_payloadSize2 / 10);
365  Simulator::Schedule (Seconds (2.5) + MicroSeconds (270), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device1, sta_device1, m_payloadSize1 / 10);
366  Simulator::Schedule (Seconds (2.5) + MicroSeconds (300), &TestInterBssConstantObssPdAlgo::SendOnePacket, this, ap_device3, sta_device3, m_payloadSize3 / 10);
367  if (expectPhyReset)
368  {
369  // In this case, we check the TX power is restricted (and set the expected value slightly before transmission should occur)
370  double expectedTxPower = std::min (m_txPowerDbm, 21 - (m_obssPdLevelDbm + 82));
371  Simulator::Schedule (Seconds (2.5) + MicroSeconds (338), &TestInterBssConstantObssPdAlgo::SetExpectedTxPower, this, expectedTxPower);
372  }
373 
374  Simulator::Stop (Seconds (2.6));
375 }
376 
377 void
379 {
388  ClearDropReasons ();
390 }
391 
392 void
394 {
395  m_dropReasonsSta1.clear ();
396  m_dropReasonsSta2.clear ();
397  m_dropReasonsAp1.clear ();
398  m_dropReasonsAp2.clear ();
399 }
400 
401 void
403 {
404  NS_TEST_ASSERT_MSG_EQ (m_numSta1PacketsSent, 4, "The number of packets sent by STA1 is not correct!");
405  NS_TEST_ASSERT_MSG_EQ (m_numSta2PacketsSent, 2, "The number of packets sent by STA2 is not correct!");
406  NS_TEST_ASSERT_MSG_EQ (m_numAp1PacketsSent, 2, "The number of packets sent by AP1 is not correct!");
407  NS_TEST_ASSERT_MSG_EQ (m_numAp2PacketsSent, 6, "The number of packets sent by AP2 is not correct!");
408  NS_TEST_ASSERT_MSG_EQ (m_numSta1PacketsReceived, 2, "The number of packets received by STA1 is not correct!");
409  NS_TEST_ASSERT_MSG_EQ (m_numSta2PacketsReceived, 6, "The number of packets received by STA2 is not correct!");
410  NS_TEST_ASSERT_MSG_EQ (m_numAp1PacketsReceived, 4, "The number of packets received by AP1 is not correct!");
411  NS_TEST_ASSERT_MSG_EQ (m_numAp2PacketsReceived, 2, "The number of packets received by AP2 is not correct!");
412 }
413 
414 void
416 {
417  uint32_t idx = ConvertContextToNodeId (context);
418  uint32_t pktSize = p->GetSize () - 38;
419  if ((idx == 0) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
420  {
422  NS_TEST_EXPECT_MSG_EQ (TestDoubleIsEqual (WToDbm (txPowerW), m_expectedTxPowerDbm, 1e-12), true, "Tx power is not correct!");
423  }
424  else if ((idx == 1) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
425  {
427  NS_TEST_EXPECT_MSG_EQ (TestDoubleIsEqual (WToDbm (txPowerW), m_expectedTxPowerDbm, 1e-12), true, "Tx power is not correct!");
428  }
429  else if ((idx == 3) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
430  {
432  NS_TEST_EXPECT_MSG_EQ (TestDoubleIsEqual (WToDbm (txPowerW), m_expectedTxPowerDbm, 1e-12), true, "Tx power is not correct!");
433  }
434  else if ((idx == 4) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
435  {
437  NS_TEST_EXPECT_MSG_EQ (TestDoubleIsEqual (WToDbm (txPowerW), m_expectedTxPowerDbm, 1e-12), true, "Tx power is not correct!");
438  }
439 }
440 
441 void
443 {
444  uint32_t idx = ConvertContextToNodeId (context);
445  uint32_t pktSize = p->GetSize () - 38;
446  if ((idx == 0) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
447  {
449  }
450  else if ((idx == 1) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
451  {
453  }
454  else if ((idx == 3) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
455  {
457  }
458  else if ((idx == 4) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
459  {
461  }
462 }
463 
464 void
466  WifiPhyRxfailureReason reason)
467 {
468  uint32_t idx = ConvertContextToNodeId (context);
469  uint32_t pktSize = p->GetSize () - 38;
470  if ((idx == 0) && ((pktSize != m_payloadSize1) && (pktSize != (m_payloadSize1 / 10))))
471  {
472  m_dropReasonsSta1.push_back (reason);
473  }
474  else if ((idx == 1) && ((pktSize != m_payloadSize2) && (pktSize != (m_payloadSize2 / 10))))
475  {
476  m_dropReasonsSta2.push_back (reason);
477  }
478  else if ((idx == 3) && ((pktSize != m_payloadSize1) && (pktSize != (m_payloadSize1 / 10))))
479  {
480  m_dropReasonsAp1.push_back (reason);
481  }
482  else if ((idx == 4) && ((pktSize != m_payloadSize2) && (pktSize != (m_payloadSize2 / 10))))
483  {
484  m_dropReasonsAp2.push_back (reason);
485  }
486 }
487 
488 void
490 {
491  Ptr<Packet> p = Create<Packet> (payloadSize);
492  tx_dev->Send (p, rx_dev->GetAddress (), 1);
493 }
494 
495 void
497 {
498  m_expectedTxPowerDbm = txPowerDbm;
499 }
500 
501 void
503 {
504  WifiPhyState currentState;
505  PointerValue ptr;
506  Ptr<WifiPhy> phy = DynamicCast<WifiPhy> (device->GetPhy ());
507  phy->GetAttribute ("State", ptr);
508  Ptr <WifiPhyStateHelper> state = DynamicCast <WifiPhyStateHelper> (ptr.Get<WifiPhyStateHelper> ());
509  currentState = state->GetState ();
510  NS_TEST_ASSERT_MSG_EQ (currentState, expectedState, "PHY State " << currentState << " does not match expected state " << expectedState << " at " << Simulator::Now ());
511 }
512 
513 void
515  std::vector<WifiPhyRxfailureReason> expectedDropReasons)
516 {
517  std::vector<WifiPhyRxfailureReason> currentDropReasons;
518  uint32_t nodeId = device->GetNode ()->GetId ();
519  switch (nodeId)
520  {
521  case 0: //STA1
522  currentDropReasons = m_dropReasonsSta1;
523  break;
524  case 1: //STA2
525  currentDropReasons = m_dropReasonsSta2;
526  break;
527  case 3: //AP1
528  currentDropReasons = m_dropReasonsAp1;
529  break;
530  case 4: //AP2
531  currentDropReasons = m_dropReasonsAp2;
532  break;
533  default: //others, no attribute
534  return;
535  }
536  NS_TEST_ASSERT_MSG_EQ (currentDropReasons.size (), expectedDropReasons.size (), "Number of drop reasons " << currentDropReasons.size () << " does not match expected one " << expectedDropReasons.size () << " at " << Simulator::Now ());
537  for (std::size_t i = 0; i < currentDropReasons.size (); ++i)
538  {
539  NS_TEST_ASSERT_MSG_EQ (currentDropReasons[i], expectedDropReasons[i], "Drop reason " << i << ": " << currentDropReasons[i] << " does not match expected reason " << expectedDropReasons[i] << " at " << Simulator::Now ());
540  }
541 }
542 
543 void
545 {
546  RngSeedManager::SetSeed (1);
547  RngSeedManager::SetRun (1);
548  int64_t streamNumber = 2;
549 
550  Config::Set ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize", UintegerValue (0));
551 
552  ResetResults ();
553 
555  wifiStaNodes.Create (3);
556 
557  NodeContainer wifiApNodes;
558  wifiApNodes.Create (3);
559 
560  Ptr<MatrixPropagationLossModel> lossModel = CreateObject<MatrixPropagationLossModel> ();
561  lossModel->SetDefaultLoss (m_txPowerDbm - m_obssRxPowerDbm); //Force received RSSI to be equal to m_obssRxPowerDbm
562 
564  phy.DisablePreambleDetectionModel ();
565  phy.SetFrameCaptureModel ("ns3::SimpleFrameCaptureModel");
566  Ptr<MultiModelSpectrumChannel> channel = CreateObject<MultiModelSpectrumChannel> ();
567  channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
568  channel->AddPropagationLossModel (lossModel);
569  phy.SetChannel (channel);
570  phy.Set ("TxPowerStart", DoubleValue (m_txPowerDbm));
571  phy.Set ("TxPowerEnd", DoubleValue (m_txPowerDbm));
572  phy.Set ("ChannelWidth", UintegerValue (20));
573 
575  wifi.SetStandard (WIFI_STANDARD_80211ax_5GHZ);
576  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
577  "DataMode", StringValue ("HeMcs5"),
578  "ControlMode", StringValue ("HeMcs0"));
579 
580  wifi.SetObssPdAlgorithm ("ns3::ConstantObssPdAlgorithm",
581  "ObssPdLevel", DoubleValue (m_obssPdLevelDbm));
582 
584  Ssid ssid = Ssid ("ns-3-ssid");
585  mac.SetType ("ns3::StaWifiMac",
586  "Ssid", SsidValue (ssid));
587  m_staDevices = wifi.Install (phy, mac, wifiStaNodes);
588 
589  // Assign fixed streams to random variables in use
590  wifi.AssignStreams (m_staDevices, streamNumber);
591 
592  mac.SetType ("ns3::ApWifiMac",
593  "Ssid", SsidValue (ssid));
594  m_apDevices = wifi.Install (phy, mac, wifiApNodes);
595 
596  // Assign fixed streams to random variables in use
597  wifi.AssignStreams (m_apDevices, streamNumber);
598 
599  for (uint32_t i = 0; i < m_apDevices.GetN (); i++)
600  {
601  Ptr<WifiNetDevice> device = DynamicCast<WifiNetDevice> (m_apDevices.Get (i));
602  Ptr<HeConfiguration> heConfiguration = device->GetHeConfiguration ();
603  if (i == 0)
604  {
605  heConfiguration->SetAttribute ("BssColor", UintegerValue (m_bssColor1));
606  }
607  else if (i == 1)
608  {
609  heConfiguration->SetAttribute ("BssColor", UintegerValue (m_bssColor2));
610  }
611  else
612  {
613  heConfiguration->SetAttribute ("BssColor", UintegerValue (m_bssColor3));
614  }
615  }
616 
618  Ptr<ListPositionAllocator> positionAlloc = AllocatePositions (10, 50, 10, 50, 10); //distances do not really matter since we set RSSI per TX-RX pair to have full control
619  mobility.SetPositionAllocator (positionAlloc);
620  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
621  mobility.Install (wifiApNodes);
622  mobility.Install (wifiStaNodes);
623 
624  lossModel->SetLoss (wifiStaNodes.Get (0)->GetObject<MobilityModel> (), wifiApNodes.Get (0)->GetObject<MobilityModel> (), m_txPowerDbm + 30); //Low attenuation for IBSS transmissions
625  lossModel->SetLoss (wifiStaNodes.Get (1)->GetObject<MobilityModel> (), wifiApNodes.Get (1)->GetObject<MobilityModel> (), m_txPowerDbm + 30); //Low attenuation for IBSS transmissions
626  lossModel->SetLoss (wifiStaNodes.Get (2)->GetObject<MobilityModel> (), wifiApNodes.Get (2)->GetObject<MobilityModel> (), m_txPowerDbm + 30); //Low attenuation for IBSS transmissions
627 
628  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyTxBegin", MakeCallback (&TestInterBssConstantObssPdAlgo::NotifyPhyTxBegin, this));
629  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxEnd", MakeCallback (&TestInterBssConstantObssPdAlgo::NotifyPhyRxEnd, this));
630  Config::Connect ("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/PhyRxDrop", MakeCallback (&TestInterBssConstantObssPdAlgo::NotifyPhyRxDrop, this));
631 
632  SetupSimulation ();
633 
634  Simulator::Run ();
635  Simulator::Destroy ();
636 
637  CheckResults ();
638 }
639 
640 void
642 {
643  //Test case 1: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm
644  m_obssPdLevelDbm = -72;
645  m_obssRxPowerDbm = -82;
646  m_bssColor1 = 1;
647  m_bssColor2 = 2;
648  m_bssColor3 = 3;
649  RunOne ();
650 
651  //Test case 2: CCA CS Threshold < m_obssPdLevelDbm < m_obssRxPowerDbm
652  m_obssPdLevelDbm = -72;
653  m_obssRxPowerDbm = -62;
654  m_bssColor1 = 1;
655  m_bssColor2 = 2;
656  m_bssColor3 = 3;
657  RunOne ();
658 
659  //Test case 3: CCA CS Threshold < m_obssPdLevelDbm = m_obssRxPowerDbm
660  m_obssPdLevelDbm = -72;
661  m_obssRxPowerDbm = -72;
662  m_bssColor1 = 1;
663  m_bssColor2 = 2;
664  m_bssColor3 = 3;
665  RunOne ();
666 
667  //Test case 4: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm with BSS color 2 and 3 set to 0
668  m_obssPdLevelDbm = -72;
669  m_obssRxPowerDbm = -82;
670  m_bssColor1 = 1;
671  m_bssColor2 = 0;
672  m_bssColor3 = 0;
673  RunOne ();
674 
675  //Test case 5: CCA CS Threshold = m_obssRxPowerDbm < m_obssPdLevelDbm with BSS color 1 set to 0
676  m_obssPdLevelDbm = -72;
677  m_obssRxPowerDbm = -82;
678  m_bssColor1 = 0;
679  m_bssColor2 = 2;
680  m_bssColor3 = 3;
681  RunOne ();
682 }
683 
692 {
693 public:
695 };
696 
698  : TestSuite ("wifi-inter-bss", UNIT)
699 {
700  AddTestCase (new TestInterBssConstantObssPdAlgo, TestCase::QUICK);
701 }
702 
703 // Do not forget to allocate an instance of this TestSuite
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
static InterBssTestSuite interBssTestSuite
Ptr< Node > GetNode(void) const override
void NotifyPhyRxDrop(std::string context, Ptr< const Packet > p, WifiPhyRxfailureReason reason)
Notify Phy receive drops.
unsigned int m_payloadSize1
size in bytes of packet payload in BSS 1
Ptr< HeConfiguration > GetHeConfiguration(void) const
Ptr< T > Get(void) const
Definition: pointer.h:201
void SetDefaultLoss(double defaultLoss)
Set the default propagation loss (in dB, positive) to be used, infinity if not set.
uint32_t GetId(void) const
Definition: node.cc:109
std::vector< WifiPhyRxfailureReason > m_dropReasonsAp2
drop reasons for AP2
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
void CheckPhyDropReasons(Ptr< WifiNetDevice > device, std::vector< WifiPhyRxfailureReason > expectedDropReasons)
Check if the Phy drop reasons for a device are as expected.
Hold variables of type string.
Definition: string.h:41
#define min(a, b)
Definition: 80211b.c:42
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:839
A suite of tests to run.
Definition: test.h:1343
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#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:283
NetDeviceContainer m_staDevices
STA devices.
encapsulates test code
Definition: test.h:1153
void SetupSimulation()
Setup the simulation.
double m_obssPdLevelDbm
OBSS-PD level in dBm.
helps to create WifiNetDevice objects
Definition: wifi-helper.h:326
unsigned int m_numSta2PacketsReceived
number of received packets from STA2
void SetExpectedTxPower(double txPowerDbm)
Set the expected transmit power in dBm.
unsigned int m_numAp1PacketsSent
number of sent packets from AP1
channel
Definition: third.py:92
mobility
Definition: third.py:108
phy
Definition: third.py:93
static uint32_t ConvertContextToNodeId(std::string context)
Keep track of the current position and velocity of an object.
NetDeviceContainer m_apDevices
AP devices.
unsigned int m_numAp2PacketsReceived
number of received packets from AP2
void ResetResults()
Reset the results.
Ptr< ListPositionAllocator > AllocatePositions(double d1, double d2, double d3, double d4, double d5)
Allocate the node positions.
unsigned int m_numSta1PacketsReceived
number of received packets from STA1
std::vector< WifiPhyRxfailureReason > m_dropReasonsSta2
drop reasons for STA2
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
Hold an unsigned integer type.
Definition: uinteger.h:44
Address GetAddress(void) const override
ssid
Definition: third.py:100
#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:166
holds a vector of ns3::NetDevice pointers
mac
Definition: third.py:99
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:44
The PHY layer has sense the medium busy through the CCA mechanism.
std::vector< WifiPhyRxfailureReason > m_dropReasonsAp1
drop reasons for AP1
void CheckPhyState(Ptr< WifiNetDevice > device, WifiPhyState expectedState)
Check if the Phy State for a device is an expected value.
double m_txPowerDbm
configured transmit power in dBm
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
Ptr< WifiPhy > GetPhy(void) const
Every class exported by the ns3 library is enclosed in the ns3 namespace.
keep track of a set of node pointers.
Hold objects of type Ptr<T>.
Definition: pointer.h:36
The PHY layer is IDLE.
WifiPhyState
The state of the PHY layer.
uint8_t m_bssColor1
color for BSS 1
double m_obssRxPowerDbm
forced RX power in dBm for OBSS
Inter BSS Test Suite.
double WToDbm(double w)
Convert from Watts to dBm.
Definition: wifi-utils.cc:47
create MAC layers for a ns3::WifiNetDevice.
void SendOnePacket(Ptr< LrWpanPhy > sender, Ptr< LrWpanPhy > receiver)
Send one packet.
The IEEE 802.11 SSID Information Element.
Definition: ssid.h:35
unsigned int m_numSta2PacketsSent
number of sent packets from STA2
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
unsigned int m_numAp1PacketsReceived
number of received packets from AP1
wifi
Definition: third.py:96
Helper class used to assign positions and mobility models to nodes.
void ClearDropReasons()
Clear the drop reasons.
This objects implements the PHY state machine of the Wifi device.
WifiPhyState GetState(void) const
Return the current state of WifiPhy.
The PHY layer is sending a packet.
unsigned int m_payloadSize3
size in bytes of packet payload in BSS 3
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
uint32_t GetN(void) const
Get the number of Ptr<NetDevice> stored in this container.
AttributeValue implementation for Ssid.
Definition: ssid.h:105
The PHY layer is receiving a packet.
void NotifyPhyRxEnd(std::string context, Ptr< const Packet > p)
Notify Phy receive ends.
double m_expectedTxPowerDbm
expected transmit power in dBm
void Add(Vector v)
Add a position to the list of positions.
void SetLoss(Ptr< MobilityModel > a, Ptr< MobilityModel > b, double loss, bool symmetric=true)
Set loss (in dB, positive) between pair of ns-3 objects (typically, nodes).
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
void NotifyPhyTxBegin(std::string context, Ptr< const Packet > p, double txPowerW)
Notify Phy transmit begin.
uint8_t m_bssColor3
color for BSS 3
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1305
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
void DoRun(void) override
Implementation to actually run this TestCase.
unsigned int m_numAp2PacketsSent
number of sent packets from AP2
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
std::vector< WifiPhyRxfailureReason > m_dropReasonsSta1
drop reasons for STA1
wifiStaNodes
Definition: third.py:88
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:86
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
unsigned int m_numSta1PacketsSent
number of sent packets from STA1
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
void SendOnePacket(Ptr< WifiNetDevice > tx_dev, Ptr< WifiNetDevice > rx_dev, uint32_t payloadSize)
Send one packet function.
unsigned int m_payloadSize2
size in bytes of packet payload in BSS 2
uint8_t m_bssColor2
color for BSS 2
void CheckResults()
Check the results.
Make it easy to create and manage PHY objects for the spectrum model.