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 (10), &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 (13), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, WifiPhyState::IDLE);
287  Simulator::Schedule (Seconds (2.0) + MicroSeconds (13), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device2, WifiPhyState::IDLE);
288  Simulator::Schedule (Seconds (2.0) + MicroSeconds (13), &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 (14), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, WifiPhyState::CCA_BUSY);
291  Simulator::Schedule (Seconds (2.0) + MicroSeconds (14), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device2, WifiPhyState::CCA_BUSY);
292  Simulator::Schedule (Seconds (2.0) + MicroSeconds (14), &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 (43), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, sta_device1, dropReasons);
295  Simulator::Schedule (Seconds (2.0) + MicroSeconds (43), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, expectPhyReset ? WifiPhyState::IDLE : WifiPhyState::CCA_BUSY);
296  Simulator::Schedule (Seconds (2.0) + MicroSeconds (43), &TestInterBssConstantObssPdAlgo::CheckPhyDropReasons, this, ap_device1, dropReasons);
297  Simulator::Schedule (Seconds (2.0) + MicroSeconds (43), &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 (54), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, sta_device1, expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
300  Simulator::Schedule (Seconds (2.0) + MicroSeconds (54), &TestInterBssConstantObssPdAlgo::CheckPhyState, this, ap_device1, expectPhyReset ? WifiPhyState::IDLE : stateDuringPayloadNeighboringBss);
301  // STA2 should be receiving
302  Simulator::Schedule (Seconds (2.0) + MicroSeconds (54), &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 (3);
548  int64_t streamNumber = 50;
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 ("ChannelSettings", StringValue ("{36, 20, BAND_5GHZ, 0}"));
573 
575  wifi.SetStandard (WIFI_STANDARD_80211ax);
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
#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 DoRun(void) override
Implementation to actually run this TestCase.
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.
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:41
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(void) 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(void) const
Definition: node.cc:109
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
Hold objects of type Ptr<T>.
Definition: pointer.h:37
Ptr< T > Get(void) const
Definition: pointer.h:201
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.
Definition: ssid.h:105
Hold variables of type string.
Definition: string.h:41
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
Hold an unsigned integer type.
Definition: uinteger.h:44
helps to create WifiNetDevice objects
Definition: wifi-helper.h:274
create MAC layers for a ns3::WifiNetDevice.
bool Send(Ptr< Packet > packet, const Address &dest, uint16_t protocolNumber) override
Address GetAddress(void) const override
Ptr< WifiPhy > GetPhy(void) const
Ptr< HeConfiguration > GetHeConfiguration(void) const
Ptr< Node > GetNode(void) const override
This objects implements the PHY state machine of the Wifi device.
void Connect(std::string path, const CallbackBase &cb)
Definition: config.cc:920
void Set(std::string path, const AttributeValue &value)
Definition: config.cc:839
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:287
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
#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:141
#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:240
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1260
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
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:43
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:1648
ssid
Definition: third.py:100
channel
Definition: third.py:92
mac
Definition: third.py:99
wifi
Definition: third.py:96
mobility
Definition: third.py:108
wifiStaNodes
Definition: third.py:88
phy
Definition: third.py:93
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:89
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.