A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-channel-settings-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025 DERONNE SOFTWARE ENGINEERING
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "ns3/ap-wifi-mac.h"
10#include "ns3/boolean.h"
11#include "ns3/config.h"
12#include "ns3/double.h"
13#include "ns3/mobility-helper.h"
14#include "ns3/multi-model-spectrum-channel.h"
15#include "ns3/packet-socket-client.h"
16#include "ns3/packet-socket-helper.h"
17#include "ns3/packet-socket-server.h"
18#include "ns3/rng-seed-manager.h"
19#include "ns3/spectrum-wifi-helper.h"
20#include "ns3/sta-wifi-mac.h"
21#include "ns3/string.h"
22#include "ns3/test.h"
23#include "ns3/wifi-net-device.h"
24#include "ns3/wifi-standards.h"
25
26#include <map>
27#include <sstream>
28#include <string>
29#include <vector>
30
31using namespace ns3;
32
33NS_LOG_COMPONENT_DEFINE("WifiChannelSettingsTest");
34
35/**
36 * @ingroup wifi-test
37 * @ingroup tests
38 *
39 * @brief Test initial channel settings for AP and non-AP STAs when those are not necessarily
40 * identical
41 *
42 * This test verifies the channel width used by the non-AP STA is properly advertised to the AP STA,
43 * and that invalid combinations get rejected. It generates DL and UL traffic (limited to 1 packet
44 * for each direction) and checks that the number of received packets matches with the expectation.
45 */
47{
48 public:
49 /**
50 * Parameters for the test
51 */
52 struct Params
53 {
54 WifiStandard apStandard; ///< wifi standard for AP STA
55 WifiStandard staStandard; ///< wifi standard for non-AP STA
56 std::string apChannelSettings; ///< channel setting string for AP STA
57 std::string staChannelSettings; ///< channel setting string for non-AP STA
58 MHz_u staLargestSupportedChWidth; ///< largest supported channel width by the non-AP STA
60 false}; ///< flag to skip association when STA channel width is incompatible with AP
61
62 /**
63 * Print the parameters
64 *
65 * @return a string with the parameters
66 */
67 std::string Print() const
68 {
69 std::ostringstream oss;
70 oss << "AP standard=" << apStandard << ", non-AP STA standard=" << staStandard
71 << ", AP settings="
72 << apChannelSettings + ", non-AP STA settings=" + staChannelSettings
73 << ", staLargestSupportedChWidth=" << staLargestSupportedChWidth
74 << " MHz, skipAssocIncompatibleChannelWidth=" << skipAssocIncompatibleChannelWidth;
75 return oss.str();
76 }
77 };
78
79 /**
80 * Constructor
81 *
82 * @param params parameters for the test
83 */
84 WifiChannelSettingsTest(const Params& params);
85 ~WifiChannelSettingsTest() override = default;
86
87 private:
88 void DoRun() override;
89
90 /**
91 * Callback invoked when a packet is received by the server application
92 * @param p the packet
93 * @param adr the address
94 */
95 void AppRx(Ptr<const Packet> p, const Address& adr);
96
97 /**
98 * Check results
99 */
100 void CheckResults();
101
102 Params m_params; ///< test parameters
103
104 Ptr<ApWifiMac> m_apWifiMac; ///< AP wifi MAC
105 Ptr<StaWifiMac> m_staWifiMac; ///< STA wifi MAC
106
107 const uint32_t m_dlPacketSize{1400}; ///< DL packet size (bytes)
108 const uint32_t m_ulPacketSize{600}; ///< UL packet size (bytes)
109
110 uint32_t m_receivedDl{0}; ///< received DL packets
111 uint32_t m_receivedUl{0}; ///< received UL packets
112};
113
115 : TestCase("Check correct behaviour for scenario: " + params.Print()),
116 m_params{params}
117{
118}
119
120void
122{
123 NS_LOG_INFO("Received " << p->GetSize() << " bytes");
124 if (p->GetSize() == m_dlPacketSize)
125 {
126 m_receivedDl++;
127 }
128 else if (p->GetSize() == m_ulPacketSize)
129 {
130 m_receivedUl++;
131 }
132}
133
134void
136{
139 int64_t streamNumber = 100;
140
141 NodeContainer wifiApNode(1);
142 NodeContainer wifiStaNode(1);
143
144 auto spectrumChannel = CreateObject<MultiModelSpectrumChannel>();
146 spectrumChannel->AddPropagationLossModel(lossModel);
148 spectrumChannel->SetPropagationDelayModel(delayModel);
149
151 phy.SetChannel(spectrumChannel);
152
153 WifiHelper wifi;
154 wifi.SetRemoteStationManager("ns3::IdealWifiManager");
155
156 wifi.SetStandard(m_params.apStandard);
157 phy.Set("ChannelSettings", StringValue(m_params.apChannelSettings));
158
159 WifiMacHelper mac;
160 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(Ssid("ns-3-ssid")));
161 auto apDevice = wifi.Install(phy, mac, wifiApNode);
162
163 wifi.SetStandard(m_params.staStandard);
164 phy.Set("MaxRadioBw", DoubleValue(m_params.staLargestSupportedChWidth));
165 phy.Set("ChannelSettings", StringValue(m_params.staChannelSettings));
166
167 NetDeviceContainer staDevice;
168 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(Ssid("ns-3-ssid")));
169
170 mac.SetAssocManager(
171 "ns3::WifiDefaultAssocManager",
172 "AllowAssocAllChannelWidths",
173 BooleanValue(true), // avoid assert in test, it checks for received DL packets instead
174 "SkipAssocIncompatibleChannelWidth",
176
177 std::istringstream split(m_params.staChannelSettings);
178 std::vector<std::string> tmp;
179 for (std::string val; std::getline(split, val, ',');)
180 {
181 tmp.emplace_back(val);
182 }
183 const auto staBw = std::stold(tmp.at(1));
184 const auto expectInvalidConfig = m_params.staLargestSupportedChWidth < staBw;
185 auto invalidConfig{false};
186 try
187 {
188 staDevice = wifi.Install(phy, mac, wifiStaNode);
189 }
190 catch (const std::runtime_error&)
191 {
192 invalidConfig = true;
193 }
194
195 NS_TEST_ASSERT_MSG_EQ(invalidConfig,
196 expectInvalidConfig,
197 "Configuration should " << (expectInvalidConfig ? "not " : "")
198 << "have been allowed");
199 if (invalidConfig)
200 {
202 return;
203 }
204
207
208 streamNumber += WifiHelper::AssignStreams(apDevice, streamNumber);
209 streamNumber += WifiHelper::AssignStreams(staDevice, streamNumber);
210
211 MobilityHelper mobility;
212 auto positionAlloc = CreateObject<ListPositionAllocator>();
213 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
214 positionAlloc->Add(Vector(10.0, 0.0, 0.0));
215 mobility.SetPositionAllocator(positionAlloc);
216
217 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
218 mobility.Install(wifiApNode);
219 mobility.Install(wifiStaNode);
220
221 PacketSocketHelper packetSocket;
222 packetSocket.Install(wifiStaNode);
223 packetSocket.Install(wifiApNode);
224
225 // generate a single packet in DL direction
226 PacketSocketAddress dlSocket;
227 dlSocket.SetSingleDevice(apDevice.Get(0)->GetIfIndex());
228 dlSocket.SetPhysicalAddress(staDevice.Get(0)->GetAddress());
229 dlSocket.SetProtocol(0);
230
231 auto dlClient = CreateObject<PacketSocketClient>();
232 dlClient->SetAttribute("PacketSize", UintegerValue(m_dlPacketSize));
233 dlClient->SetAttribute("MaxPackets", UintegerValue(1));
234 dlClient->SetRemote(dlSocket);
235 wifiApNode.Get(0)->AddApplication(dlClient);
236 dlClient->SetStartTime(Seconds(0.15));
237 dlClient->SetStopTime(Seconds(0.25));
238
239 auto dlServer = CreateObject<PacketSocketServer>();
240 dlServer->SetLocal(dlSocket);
241 wifiStaNode.Get(0)->AddApplication(dlServer);
242 dlServer->SetStartTime(Seconds(0.0));
243 dlServer->SetStopTime(Seconds(0.25));
244
245 // generate a single packet in UL direction
246 PacketSocketAddress ulSocket;
247 ulSocket.SetSingleDevice(staDevice.Get(0)->GetIfIndex());
248 ulSocket.SetPhysicalAddress(apDevice.Get(0)->GetAddress());
249 ulSocket.SetProtocol(1);
250
251 auto ulClient = CreateObject<PacketSocketClient>();
252 ulClient->SetAttribute("PacketSize", UintegerValue(m_ulPacketSize));
253 ulClient->SetAttribute("MaxPackets", UintegerValue(1));
254 ulClient->SetRemote(ulSocket);
255 wifiStaNode.Get(0)->AddApplication(ulClient);
256 ulClient->SetStartTime(Seconds(0.2));
257 ulClient->SetStopTime(Seconds(0.25));
258
259 auto ulServer = CreateObject<PacketSocketServer>();
260 ulServer->SetLocal(ulSocket);
261 wifiApNode.Get(0)->AddApplication(ulServer);
262 ulServer->SetStartTime(Seconds(0.0));
263 ulServer->SetStopTime(Seconds(0.25));
264
265 Config::ConnectWithoutContext("/NodeList/*/ApplicationList/*/$ns3::PacketSocketServer/Rx",
267
270
271 CheckResults();
272
274}
275
276void
278{
279 const auto staPhy = m_staWifiMac->GetDevice()->GetPhy();
280 const auto staBw = staPhy->GetChannelWidth();
281 const auto compatibleBw =
282 GetSupportedChannelWidthSet(staPhy->GetStandard(), staPhy->GetPhyBand()).contains(staBw) ||
283 (staBw >= m_apWifiMac->GetDevice()->GetPhy()->GetChannelWidth());
284
285 NS_TEST_EXPECT_MSG_EQ(m_staWifiMac->GetWifiRemoteStationManager()->GetChannelWidthSupported(
286 m_apWifiMac->GetAddress()),
287 m_apWifiMac->GetDevice()->GetPhy()->GetChannelWidth(),
288 "Incorrect AP channel width information received by STA");
289
290 // if BW is not compatible, STA should not be able to receive any DL packets (since they will
291 // use a larger BW than the one supported by its PHY)
292 const uint32_t expectedRxDl = compatibleBw ? 1 : 0;
294 expectedRxDl,
295 "Unexpected number of received packets in downlink direction");
296
297 // if BW is not compatible and skipAssocIncompatibleChannelWidth is true, STA should not be
298 // associated to AP and hence no traffic should be received
299 const uint32_t expectedRxUl =
300 (compatibleBw || !m_params.skipAssocIncompatibleChannelWidth) ? 1 : 0;
302 expectedRxUl,
303 "Unexpected number of received packets in uplink direction");
304}
305
306/**
307 * @ingroup wifi-test
308 * @ingroup tests
309 *
310 * @brief wifi channel settings test suite
311 */
313{
314 public:
316};
317
319 : TestSuite("wifi-channel-settings", Type::UNIT)
320{
321 const std::map<std::pair<MHz_u, WifiPhyBand>, std::string> channelSettingsMap{
322 {{MHz_u{20}, WIFI_PHY_BAND_2_4GHZ}, "{1, 20, BAND_2_4GHZ, 0}"},
323 {{MHz_u{40}, WIFI_PHY_BAND_2_4GHZ}, "{3, 40, BAND_2_4GHZ, 0}"},
324 {{MHz_u{20}, WIFI_PHY_BAND_5GHZ}, "{36, 20, BAND_5GHZ, 0}"},
325 {{MHz_u{40}, WIFI_PHY_BAND_5GHZ}, "{38, 40, BAND_5GHZ, 0}"},
326 {{MHz_u{80}, WIFI_PHY_BAND_5GHZ}, "{42, 80, BAND_5GHZ, 0}"},
327 {{MHz_u{160}, WIFI_PHY_BAND_5GHZ}, "{50, 160, BAND_5GHZ, 0}"},
328 {{MHz_u{20}, WIFI_PHY_BAND_6GHZ}, "{1, 20, BAND_6GHZ, 0}"},
329 {{MHz_u{40}, WIFI_PHY_BAND_6GHZ}, "{3, 40, BAND_6GHZ, 0}"},
330 {{MHz_u{80}, WIFI_PHY_BAND_6GHZ}, "{7, 80, BAND_6GHZ, 0}"},
331 {{MHz_u{160}, WIFI_PHY_BAND_6GHZ}, "{15, 160, BAND_6GHZ, 0}"},
332 };
333
334 for (const auto standard : {WIFI_STANDARD_80211n,
338 {
339 for (const auto maxSupportedBw : {MHz_u{20}, MHz_u{40}, MHz_u{80}, MHz_u{160}})
340 {
341 for (const auto& [apWidthBandPair, apChannel] : channelSettingsMap)
342 {
343 for (const auto& [staWidthBandPair, staChannel] : channelSettingsMap)
344 {
345 if (apWidthBandPair.second != staWidthBandPair.second)
346 {
347 continue; // different band
348 }
349 if (const auto& allowedBands = wifiStandards.at(standard);
350 std::find(allowedBands.cbegin(),
351 allowedBands.cend(),
352 apWidthBandPair.second) == allowedBands.cend())
353 {
354 continue; // standard does not operate on this band
355 }
356 if (const auto maxWidth =
357 std::max(apWidthBandPair.first, staWidthBandPair.first);
359 {
360 continue; // channel width(s) not supported by the standard
361 }
362 for (const auto skipAssocIfIncompatible : {false, true})
363 {
366 {.apStandard = standard,
367 .staStandard = standard,
368 .apChannelSettings = apChannel,
369 .staChannelSettings = staChannel,
370 .staLargestSupportedChWidth = maxSupportedBw,
371 .skipAssocIncompatibleChannelWidth = skipAssocIfIncompatible}),
372 TestCase::Duration::QUICK);
373 }
374 }
375 }
376 }
377 }
378}
379
Test initial channel settings for AP and non-AP STAs when those are not necessarily identical.
~WifiChannelSettingsTest() override=default
uint32_t m_receivedDl
received DL packets
uint32_t m_receivedUl
received UL packets
Ptr< StaWifiMac > m_staWifiMac
STA wifi MAC.
WifiChannelSettingsTest(const Params &params)
Constructor.
const uint32_t m_ulPacketSize
UL packet size (bytes)
void DoRun() override
Implementation to actually run this TestCase.
void AppRx(Ptr< const Packet > p, const Address &adr)
Callback invoked when a packet is received by the server application.
Ptr< ApWifiMac > m_apWifiMac
AP wifi MAC.
const uint32_t m_dlPacketSize
DL packet size (bytes)
wifi channel settings test suite
a polymophic address class
Definition address.h:90
AttributeValue implementation for Boolean.
Definition boolean.h:26
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
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.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
uint32_t AddApplication(Ptr< Application > application)
Associate an Application to this Node.
Definition node.cc:153
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Give ns3::PacketSocket powers to ns3::Node.
void Install(Ptr< Node > node) const
Aggregate an instance of a ns3::PacketSocketFactory onto the provided node.
Smart pointer class similar to boost::intrusive_ptr.
static void SetRun(uint64_t run)
Set the run number of simulation.
static void SetSeed(uint32_t seed)
Set the seed.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void Run()
Run the simulation.
Definition simulator.cc:167
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:175
Make it easy to create and manage PHY objects for the spectrum model.
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Hold variables of type string.
Definition string.h:45
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
create MAC layers for a ns3::WifiNetDevice.
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition config.cc:946
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#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:134
#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:241
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
WifiStandard
Identifies the IEEE 802.11 specifications that a Wifi device can be configured to use.
@ WIFI_STANDARD_80211be
@ WIFI_STANDARD_80211n
@ WIFI_STANDARD_80211ax
@ WIFI_STANDARD_80211ac
@ WIFI_PHY_BAND_6GHZ
The 6 GHz band.
@ WIFI_PHY_BAND_2_4GHZ
The 2.4 GHz band.
@ WIFI_PHY_BAND_5GHZ
The 5 GHz band.
void Print(ComponentCarrier cc)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
MHz_u GetMaximumChannelWidth(WifiModulationClass modulation)
Get the maximum channel width allowed for the given modulation class.
WifiModulationClass GetModulationClassForStandard(WifiStandard standard)
Return the modulation class corresponding to a given standard.
const std::map< WifiStandard, std::list< WifiPhyBand > > wifiStandards
map a given standard configured by the user to the allowed PHY bands
std::set< MHz_u > GetSupportedChannelWidthSet(WifiStandard standard, WifiPhyBand band)
Get the supported channel width set that can be advertised in PHY capabilities.
WifiStandard apStandard
wifi standard for AP STA
WifiStandard staStandard
wifi standard for non-AP STA
std::string apChannelSettings
channel setting string for AP STA
std::string staChannelSettings
channel setting string for non-AP STA
MHz_u staLargestSupportedChWidth
largest supported channel width by the non-AP STA
bool skipAssocIncompatibleChannelWidth
flag to skip association when STA channel width is incompatible with AP
std::string Print() const
Print the parameters.
static WifiChannelSettingsTestSuite g_wifiChannelSettingsTestSuite
the test suite