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
ConvertContextToNodeId(std::string context)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
52 /**
53 * \ingroup wifi-test
54 * \ingroup tests
55 *
56 * \brief Wifi Test
57 *
58 * This test case tests the transmission of inter-BSS cases
59 * and verify behavior of 11ax OBSS_PD spatial reuse.
60 *
61 * The topology for this test case is made of three networks, each with one AP and one STA:
62 *
63 * AP --d1-- STA1 --d2-- AP2 --d3-- STA2 --d4-- AP3 --d5-- STA3
64 * TX1 RX1 TX2 RX2 TX3 RX3
65 *
66 * Main parameters:
67 * OBSS_PD level = -72dbm
68 * Received Power by TX1 from TX2 = [-62dbm, -82dbm]
69 * Received SINR by RX1 from TX1 > 3dB (enough to pass MCS0 reception)
70 * Received SINR by RX2 from TX2 > 3dB (enough to pass MCS0 reception)
71 * Received SINR by RX3 from TX3 > 3dB (enough to pass MCS0 reception)
72 * TX1/RX1 BSS Color = 1
73 * TX2/RX2 transmission PPDU BSS Color = [2 0]
74 * TX3/RX3 BSS color = 3 (BSS 3 only used to test some corner cases)
75 * PHY = 11ax, MCS 0, 80MHz
76 */
77
78 class TestInterBssConstantObssPdAlgo : public TestCase
79 {
80 public:
81 TestInterBssConstantObssPdAlgo ();
82 ~TestInterBssConstantObssPdAlgo ();
83
84 void DoRun (void) override;
85
86 private:
87 /**
88 * Send one packet function
89 * \param tx_dev the transmitting device
90 * \param rx_dev the receiving device
91 * \param payloadSize the payload size
92 */
93 void SendOnePacket (Ptr<WifiNetDevice> tx_dev, Ptr<WifiNetDevice> rx_dev, uint32_t payloadSize);
94
95 /**
96 * Allocate the node positions
97 * \param d1 distance d1 (in meters)
98 * \param d2 distance d2 (in meters)
99 * \param d3 distance d3 (in meters)
100 * \param d4 distance d4 (in meters)
101 * \param d5 distance d5 (in meters)
102 * \return the node positions
103 */
104 Ptr<ListPositionAllocator> AllocatePositions (double d1, double d2, double d3, double d4, double d5);
105
106 /**
107 * Set the expected transmit power in dBm
108 * \param txPowerDbm the transmit power in dBm
109 */
110 void SetExpectedTxPower (double txPowerDbm);
111
112 /**
113 * Setup the simulation
114 */
115 void SetupSimulation ();
116
117 /**
118 * Check the results
119 */
120 void CheckResults ();
121
122 /**
123 * Reset the results
124 */
125 void ResetResults ();
126
127 /**
128 * Clear the drop reasons
129 */
130 void ClearDropReasons ();
131
132 /**
133 * Run one function
134 */
135 void RunOne ();
136
137 /**
138 * Check if the Phy State for a device is an expected value
139 * \param device the device to check
140 * \param expectedState the expected PHY state
141 */
142 void CheckPhyState (Ptr<WifiNetDevice> device, WifiPhyState expectedState);
143
144 /**
145 * Check if the Phy drop reasons for a device are as expected
146 * \param device the device to check
147 * \param expectedDropReasons the expected PHY drop reasons
148 */
149 void CheckPhyDropReasons (Ptr<WifiNetDevice> device, std::vector<WifiPhyRxfailureReason> expectedDropReasons);
150
151 /**
152 * Notify Phy transmit begin
153 * \param context the context
154 * \param p the packet
155 * \param txPowerW the tx power
156 */
157 void NotifyPhyTxBegin (std::string context, Ptr<const Packet> p, double txPowerW);
158
159 /**
160 * Notify Phy receive ends
161 * \param context the context
162 * \param p the packet
163 */
164 void NotifyPhyRxEnd (std::string context, Ptr<const Packet> p);
165
166 /**
167 * Notify Phy receive drops
168 * \param context the context
169 * \param p the packet
170 * \param reason the reason why it was dropped
171 */
172 void NotifyPhyRxDrop (std::string context, Ptr<const Packet> p, WifiPhyRxfailureReason reason);
173
174 unsigned int m_numSta1PacketsSent; ///< number of sent packets from STA1
175 unsigned int m_numSta2PacketsSent; ///< number of sent packets from STA2
176 unsigned int m_numAp1PacketsSent; ///< number of sent packets from AP1
177 unsigned int m_numAp2PacketsSent; ///< number of sent packets from AP2
178
179 unsigned int m_numSta1PacketsReceived; ///< number of received packets from STA1
180 unsigned int m_numSta2PacketsReceived; ///< number of received packets from STA2
181 unsigned int m_numAp1PacketsReceived; ///< number of received packets from AP1
182 unsigned int m_numAp2PacketsReceived; ///< number of received packets from AP2
183
184 std::vector<WifiPhyRxfailureReason> m_dropReasonsSta1; ///< drop reasons for STA1
185 std::vector<WifiPhyRxfailureReason> m_dropReasonsSta2; ///< drop reasons for STA2
186 std::vector<WifiPhyRxfailureReason> m_dropReasonsAp1; ///< drop reasons for AP1
187 std::vector<WifiPhyRxfailureReason> m_dropReasonsAp2; ///< drop reasons for AP2
188
189 unsigned int m_payloadSize1; ///< size in bytes of packet payload in BSS 1
190 unsigned int m_payloadSize2; ///< size in bytes of packet payload in BSS 2
191 unsigned int m_payloadSize3; ///< size in bytes of packet payload in BSS 3
192
193 NetDeviceContainer m_staDevices; ///< STA devices
194 NetDeviceContainer m_apDevices; ///< AP devices
195
196 double m_txPowerDbm; ///< configured transmit power in dBm
197 double m_obssPdLevelDbm; ///< OBSS-PD level in dBm
198 double m_obssRxPowerDbm; ///< forced RX power in dBm for OBSS
199 double m_expectedTxPowerDbm; ///< expected transmit power in dBm
200
201 uint8_t m_bssColor1; ///< color for BSS 1
202 uint8_t m_bssColor2; ///< color for BSS 2
203 uint8_t m_bssColor3; ///< color for BSS 3
204 };
205
TestInterBssConstantObssPdAlgo()206 TestInterBssConstantObssPdAlgo::TestInterBssConstantObssPdAlgo ()
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
~TestInterBssConstantObssPdAlgo()229 TestInterBssConstantObssPdAlgo::~TestInterBssConstantObssPdAlgo ()
230 {
231 ClearDropReasons ();
232 }
233
234 Ptr<ListPositionAllocator>
AllocatePositions(double d1,double d2,double d3,double d4,double d5)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
SetupSimulation()248 TestInterBssConstantObssPdAlgo::SetupSimulation ()
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
ResetResults()378 TestInterBssConstantObssPdAlgo::ResetResults ()
379 {
380 m_numSta1PacketsSent = 0;
381 m_numSta2PacketsSent = 0;
382 m_numAp1PacketsSent = 0;
383 m_numAp2PacketsSent = 0;
384 m_numSta1PacketsReceived = 0;
385 m_numSta2PacketsReceived = 0;
386 m_numAp1PacketsReceived = 0;
387 m_numAp2PacketsReceived = 0;
388 ClearDropReasons ();
389 m_expectedTxPowerDbm = m_txPowerDbm;
390 }
391
392 void
ClearDropReasons()393 TestInterBssConstantObssPdAlgo::ClearDropReasons ()
394 {
395 m_dropReasonsSta1.clear ();
396 m_dropReasonsSta2.clear ();
397 m_dropReasonsAp1.clear ();
398 m_dropReasonsAp2.clear ();
399 }
400
401 void
CheckResults()402 TestInterBssConstantObssPdAlgo::CheckResults ()
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
NotifyPhyTxBegin(std::string context,Ptr<const Packet> p,double txPowerW)415 TestInterBssConstantObssPdAlgo::NotifyPhyTxBegin (std::string context, Ptr<const Packet> p, double txPowerW)
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 {
421 m_numSta1PacketsSent++;
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 {
426 m_numSta2PacketsSent++;
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 {
431 m_numAp1PacketsSent++;
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 {
436 m_numAp2PacketsSent++;
437 NS_TEST_EXPECT_MSG_EQ (TestDoubleIsEqual (WToDbm (txPowerW), m_expectedTxPowerDbm, 1e-12), true, "Tx power is not correct!");
438 }
439 }
440
441 void
NotifyPhyRxEnd(std::string context,Ptr<const Packet> p)442 TestInterBssConstantObssPdAlgo::NotifyPhyRxEnd (std::string context, Ptr<const Packet> p)
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 {
448 m_numSta1PacketsReceived++;
449 }
450 else if ((idx == 1) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
451 {
452 m_numSta2PacketsReceived++;
453 }
454 else if ((idx == 3) && ((pktSize == m_payloadSize1) || (pktSize == (m_payloadSize1 / 10))))
455 {
456 m_numAp1PacketsReceived++;
457 }
458 else if ((idx == 4) && ((pktSize == m_payloadSize2) || (pktSize == (m_payloadSize2 / 10))))
459 {
460 m_numAp2PacketsReceived++;
461 }
462 }
463
464 void
NotifyPhyRxDrop(std::string context,Ptr<const Packet> p,WifiPhyRxfailureReason reason)465 TestInterBssConstantObssPdAlgo::NotifyPhyRxDrop (std::string context, Ptr<const Packet> p,
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
SendOnePacket(Ptr<WifiNetDevice> tx_dev,Ptr<WifiNetDevice> rx_dev,uint32_t payloadSize)489 TestInterBssConstantObssPdAlgo::SendOnePacket (Ptr<WifiNetDevice> tx_dev, Ptr<WifiNetDevice> rx_dev, uint32_t payloadSize)
490 {
491 Ptr<Packet> p = Create<Packet> (payloadSize);
492 tx_dev->Send (p, rx_dev->GetAddress (), 1);
493 }
494
495 void
SetExpectedTxPower(double txPowerDbm)496 TestInterBssConstantObssPdAlgo::SetExpectedTxPower (double txPowerDbm)
497 {
498 m_expectedTxPowerDbm = txPowerDbm;
499 }
500
501 void
CheckPhyState(Ptr<WifiNetDevice> device,WifiPhyState expectedState)502 TestInterBssConstantObssPdAlgo::CheckPhyState (Ptr<WifiNetDevice> device, WifiPhyState expectedState)
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
CheckPhyDropReasons(Ptr<WifiNetDevice> device,std::vector<WifiPhyRxfailureReason> expectedDropReasons)514 TestInterBssConstantObssPdAlgo::CheckPhyDropReasons (Ptr<WifiNetDevice> device,
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
RunOne(void)544 TestInterBssConstantObssPdAlgo::RunOne (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
554 NodeContainer wifiStaNodes;
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
563 SpectrumWifiPhyHelper phy;
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
574 WifiHelper wifi;
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
583 WifiMacHelper mac;
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
617 MobilityHelper mobility;
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
DoRun(void)641 TestInterBssConstantObssPdAlgo::DoRun (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
684 /**
685 * \ingroup wifi-test
686 * \ingroup tests
687 *
688 * \brief Inter BSS Test Suite
689 */
690
691 class InterBssTestSuite : public TestSuite
692 {
693 public:
694 InterBssTestSuite ();
695 };
696
InterBssTestSuite()697 InterBssTestSuite::InterBssTestSuite ()
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
704 static InterBssTestSuite interBssTestSuite;
705