A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-static-emlsr-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2025
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sharan Naribole <sharan.naribole@gmail.com>
7 */
8
9#include "ns3/ap-wifi-mac.h"
10#include "ns3/assert.h"
11#include "ns3/attribute-container.h"
12#include "ns3/boolean.h"
13#include "ns3/emlsr-manager.h"
14#include "ns3/frame-exchange-manager.h"
15#include "ns3/log.h"
16#include "ns3/mac48-address.h"
17#include "ns3/multi-model-spectrum-channel.h"
18#include "ns3/node-container.h"
19#include "ns3/rng-seed-manager.h"
20#include "ns3/simulator.h"
21#include "ns3/spectrum-wifi-helper.h"
22#include "ns3/sta-wifi-mac.h"
23#include "ns3/string.h"
24#include "ns3/test.h"
25#include "ns3/wifi-mac-header.h"
26#include "ns3/wifi-mac-helper.h"
27#include "ns3/wifi-mac.h"
28#include "ns3/wifi-net-device.h"
29#include "ns3/wifi-static-setup-helper.h"
30#include "ns3/wifi-utils.h"
31
32#include <algorithm>
33#include <iterator>
34#include <set>
35#include <unordered_map>
36
37/// @ingroup wifi-test
38/// @ingroup tests
39/// @brief WifiStaticSetupHelper EMLSR setup test suite
40/// Test suite intended to test static EMLSR setup between AP MLD and client MLD.
41/// The test prepares AP WifiNetDevice and client WifiNetDevice based on test vector input and
42/// performs static EMLSR setup using WifiStaticSetupHelper. The test verifies if EMLSR state
43/// machine at ApWifiMac and StaWifiMac has been updated correctly.
44
45using namespace ns3;
46NS_LOG_COMPONENT_DEFINE("WifiStaticEmlsrTestSuite");
47
49{
50const auto DEFAULT_RNG_SEED = 3;
51const auto DEFAULT_RNG_RUN = 7;
52const auto DEFAULT_STREAM_INDEX = 100;
54const auto DEFAULT_BEACON_GEN = false;
55const auto DEFAULT_DATA_MODE = "HeMcs3";
56const auto DEFAULT_CONTROL_MODE = "OfdmRate24Mbps";
59const auto DEFAULT_SWITCH_AUX_PHY = false;
61const auto DEFAULT_SSID = Ssid("static-assoc-test");
62const std::string CHANNEL_0 = "{42, 80, BAND_5GHZ, 0}";
63const std::string CHANNEL_1 = "{23, 80, BAND_6GHZ, 0}";
64const std::string CHANNEL_2 = "{2, 0, BAND_2_4GHZ, 0}";
65const std::vector<std::string> DEFAULT_AP_CHS = {CHANNEL_0, CHANNEL_1, CHANNEL_2};
66using ChannelMap = std::unordered_map<WifiPhyBand, Ptr<MultiModelSpectrumChannel>>;
67} // namespace WifiStaticEmlsrTestConstants
68
69/// @brief test case information
71{
72 std::string name; ///< Test case name
73 std::vector<std::string> clientChs{}; ///< Channel settings for client device
74 std::set<uint8_t> emlsrLinks{}; ///< EMLSR mode links
79 std::vector<WifiPowerManagementMode> pmModes; ///< if non-empty, PM mode for each STA affiliated
80 ///< with the client in increasing order of client
81 ///< link ID (as assigned before association); if
82 ///< empty, no PowerSave manager is installed
83};
84
85/**
86 * Test static setup of the EMLSR mode.
87 *
88 * It is checked that:
89 * - EMLSR mode is enabled on the expected set of links, both at client side and AP MLD side
90 * - the channel switch delay is configured on the client links as expected
91 */
93{
94 public:
95 /**
96 * Constructor.
97 *
98 * @param testVec the test vector
99 */
101
102 private:
103 /// Construct WifiNetDevice
104 /// @param isAp true if AP, false otherwise
105 /// @param channelMap created spectrum channels
106 /// @return constructed WifiNetDevice
109
110 /// Construct PHY helper based on input operating channels
111 /// @param settings vector of strings specifying the operating channels to configure
112 /// @param channelMap created spectrum channels
113 /// @return PHY helper
115 const std::vector<std::string>& settings,
116 const WifiStaticEmlsrTestConstants::ChannelMap& channelMap) const;
117
118 /// @return the WifiHelper
120 /// @return the AP MAC helper
122 /// @return the Client MAC helper
124 void ValidateEmlsr(); ///< Validate EMLSR setup
125 void DoRun() override;
126 void DoSetup() override;
127
128 /// Validate the configured PM mode for the STA(s) affiliated with the client device
129 /// @param apMac AP MAC
130 /// @param clientMac Client MAC
131 void ValidatePmMode(Ptr<ApWifiMac> apMac, Ptr<StaWifiMac> clientMac);
132
134 Ptr<WifiNetDevice> m_apDev{nullptr}; ///< AP WiFi device
135 Ptr<WifiNetDevice> m_clientDev{nullptr}; ///< client WiFi device
136 std::map<linkId_t, linkId_t> m_linkIdMap; ///< non-AP MLD link ID to AP MLD link ID mapping
137};
138
140 : TestCase(testVec.name),
141 m_testVec(testVec)
142{
143}
144
147{
148 WifiHelper wifiHelper;
150 wifiHelper.SetRemoteStationManager(
151 "ns3::ConstantRateWifiManager",
152 "DataMode",
154 "ControlMode",
156 wifiHelper.ConfigEhtOptions("EmlsrActivated", BooleanValue(true));
157 return wifiHelper;
158}
159
161WifiStaticEmlsrTest::GetPhyHelper(const std::vector<std::string>& settings,
162 const WifiStaticEmlsrTestConstants::ChannelMap& channelMap) const
163{
164 NS_ASSERT(not settings.empty());
165 SpectrumWifiPhyHelper helper(settings.size());
166
167 uint8_t linkId = 0;
168 for (const auto& str : settings)
169 {
170 helper.Set(linkId, "ChannelSettings", StringValue(str));
171 helper.Set(linkId, "ChannelSwitchDelay", TimeValue(m_testVec.switchDelay));
172 auto channelConfig = WifiChannelConfig::FromString(str);
173 auto phyBand = channelConfig.front().band;
174 auto freqRange = GetFrequencyRange(phyBand);
175 helper.AddPhyToFreqRangeMapping(linkId, freqRange);
176 helper.AddChannel(channelMap.at(phyBand), freqRange);
177
178 ++linkId;
179 }
180 return helper;
181}
182
185{
186 WifiMacHelper macHelper;
188
189 macHelper.SetType("ns3::ApWifiMac",
190 "Ssid",
191 SsidValue(ssid),
192 "BeaconGeneration",
194 return macHelper;
195}
196
199{
200 WifiMacHelper macHelper;
202 macHelper.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
203 macHelper.SetEmlsrManager("ns3::DefaultEmlsrManager",
204 "EmlsrLinkSet",
206 "AuxPhyChannelWidth",
207 UintegerValue(m_testVec.auxPhyWidth),
208 "SwitchAuxPhy",
209 BooleanValue(m_testVec.switchAuxPhy));
210 // install and configure a PowerSave manager if PM modes are provided
211 if (!m_testVec.pmModes.empty())
212 {
213 std::string s;
214 for (std::size_t id = 0; const auto pmMode : m_testVec.pmModes)
215 {
216 s += std::to_string(id++) + (pmMode == WIFI_PM_POWERSAVE ? " true, " : " false, ");
217 }
218 s.pop_back();
219 s.pop_back();
220 macHelper.SetPowerSaveManager("ns3::DefaultPowerSaveManager",
221 "PowerSaveMode",
222 StringValue(s));
223 }
224 return macHelper;
225}
226
230{
231 NodeContainer node(1);
232 auto wifiHelper = GetWifiHelper();
233 auto settings = isAp ? WifiStaticEmlsrTestConstants::DEFAULT_AP_CHS : m_testVec.clientChs;
234 auto phyHelper = GetPhyHelper(settings, channelMap);
235 auto macHelper = isAp ? GetApMacHelper() : GetClientMacHelper();
236 auto netDev = wifiHelper.Install(phyHelper, macHelper, node);
238 return DynamicCast<WifiNetDevice>(netDev.Get(0));
239}
240
241void
268
269void
271{
272 auto clientMac = DynamicCast<StaWifiMac>(m_clientDev->GetMac());
273 NS_ASSERT_MSG(clientMac, "Expected StaWifiMac");
274 NS_TEST_ASSERT_MSG_EQ(clientMac->IsAssociated(), true, "Expected non-AP MLD to be associated");
275 auto setupLinks = clientMac->GetSetupLinkIds();
276 auto isMldAssoc = (setupLinks.size() > 1);
277 NS_TEST_ASSERT_MSG_EQ(isMldAssoc, true, "EMLSR mode requires association on multiple links");
278 auto emlsrManager = clientMac->GetEmlsrManager();
279 NS_ASSERT_MSG(emlsrManager, "EMLSR Manager not set");
280 auto clientEmlsrLinks = emlsrManager->GetEmlsrLinks();
281 auto match = (clientEmlsrLinks == m_testVec.emlsrLinks);
282 NS_TEST_ASSERT_MSG_EQ(match, true, "Unexpected set of EMLSR links enabled");
283 auto apMac = DynamicCast<ApWifiMac>(m_apDev->GetMac());
284 NS_TEST_ASSERT_MSG_NE(apMac, nullptr, "Expected ApWifiMac");
285 for (auto linkId : setupLinks)
286 {
287 auto expectedState = clientEmlsrLinks.contains(linkId);
288 auto clientLinkAddr = clientMac->GetFrameExchangeManager(linkId)->GetAddress();
289 auto apManager = m_apDev->GetRemoteStationManager(linkId);
290 auto actualState = apManager->GetEmlsrEnabled(clientLinkAddr);
291 NS_TEST_ASSERT_MSG_EQ(actualState,
292 expectedState,
293 "EMLSR state mismatch on client link ID " << +linkId);
294
295 // Validate Channel switch delay
296 auto actualDelay = clientMac->GetWifiPhy(linkId)->GetChannelSwitchDelay();
297 NS_TEST_ASSERT_MSG_EQ(actualDelay,
298 m_testVec.switchDelay,
299 "Channel switch delay mismatch on client link ID " << +linkId);
300 }
301
302 ValidatePmMode(apMac, clientMac);
303}
304
305void
307{
308 const auto& clientLinkIds = clientMac->GetLinkIds();
309 // if PM modes are not provided (hence, no PowerSave manager is installed), we expect all
310 // STAs affiliated with the client to be in active mode
311 auto pmModes = !m_testVec.pmModes.empty()
312 ? m_testVec.pmModes
313 : std::vector<WifiPowerManagementMode>(clientLinkIds.size(), WIFI_PM_ACTIVE);
314
315 NS_TEST_ASSERT_MSG_EQ(pmModes.size(), clientLinkIds.size(), "Number of PM modes mismatch");
316 for (std::size_t id = 0; const auto pmMode : pmModes)
317 {
319 true,
320 "Non-AP MLD did not have link " << id << " before association");
321 const auto linkId = m_linkIdMap.at(id);
323 clientMac->GetPmMode(linkId),
324 pmMode,
325 "Unexpected PM mode for STA affiliated with the non-AP MLD and operating on link "
326 << +linkId << "(non-AP MLD side)");
327
329 apMac->GetWifiRemoteStationManager(linkId)->IsInPsMode(clientMac->GetAddress()),
330 (pmMode == WIFI_PM_POWERSAVE),
331 "Unexpected PM mode for STA affiliated with the non-AP MLD and operating on link "
332 << +linkId << "(AP MLD side)");
333
334 NS_TEST_EXPECT_MSG_EQ(apMac->GetNStationsInPsMode(linkId),
335 (pmMode == WIFI_PM_POWERSAVE ? 1 : 0),
336 "AP is tracking an unexpected number of STAs in PS mode on link "
337 << +linkId);
338 ++id;
339 }
340}
341
342void
350
351/**
352 * @ingroup wifi-test
353 * @ingroup tests
354 *
355 * @brief EMLSR static setup test suite
356 */
358{
359 public:
361};
362
364 : TestSuite("wifi-static-emlsr-test", Type::UNIT)
365{
366 auto CHANNELS_2_LINKS = {WifiStaticEmlsrTestConstants::CHANNEL_0,
368 auto CHANNELS_3_LINKS = {WifiStaticEmlsrTestConstants::CHANNEL_0,
371 auto CHANNELS_2_LINKS_ALT = {WifiStaticEmlsrTestConstants::CHANNEL_0,
373
374 for (const std::vector<WifiStaticEmlsrTestVector> inputs{
375 {"Setup-2-link-EMLSR-2-link",
376 CHANNELS_2_LINKS,
377 {0, 1},
381 {}},
382 {"Setup-3-link-EMLSR-2-link",
383 CHANNELS_3_LINKS,
384 {0, 1},
388 {}},
389 {"Setup-3-link-EMLSR-2-link-Diff",
390 CHANNELS_3_LINKS,
391 {1, 2},
396 {"Setup-3-link-EMLSR-2-link-Diff-2",
397 CHANNELS_3_LINKS,
398 {0, 2},
403 {"Setup-3-link-EMLSR-3-link",
404 CHANNELS_3_LINKS,
405 {0, 1, 2},
410 {"Setup-2-link-EMLSR-2-link-Diff-Set",
411 CHANNELS_2_LINKS_ALT,
412 {0, 2},
417 {"EMLSR-2-link-16us-delay",
418 CHANNELS_2_LINKS,
419 {0, 1},
420 MicroSeconds(16),
424 {"EMLSR-2-link-32us-delay",
425 CHANNELS_2_LINKS,
426 {0, 1},
427 MicroSeconds(32),
431 {"EMLSR-2-link-80MHz-AuxPhy",
432 CHANNELS_2_LINKS,
433 {0, 1},
434 MicroSeconds(32),
435 MHz_u{80},
438 {"EMLSR-2-link-Switch-Aux-PHY",
439 CHANNELS_2_LINKS,
440 {0, 1},
443 true,
445 {"EMLSR-2-link-80MHz-AuxPhy-Switch",
446 CHANNELS_2_LINKS,
447 {0, 1},
449 MHz_u{80},
450 true,
451 {}}};
452 const auto& input : inputs)
453 {
455 }
456}
457
Test static setup of the EMLSR mode.
WifiStaticEmlsrTestVector m_testVec
Test vector.
WifiMacHelper GetApMacHelper() const
SpectrumWifiPhyHelper GetPhyHelper(const std::vector< std::string > &settings, const WifiStaticEmlsrTestConstants::ChannelMap &channelMap) const
Construct PHY helper based on input operating channels.
Ptr< WifiNetDevice > m_apDev
AP WiFi device.
Ptr< WifiNetDevice > GetWifiNetDevice(bool isAp, const WifiStaticEmlsrTestConstants::ChannelMap &channelMap)
Construct WifiNetDevice.
std::map< linkId_t, linkId_t > m_linkIdMap
non-AP MLD link ID to AP MLD link ID mapping
void ValidatePmMode(Ptr< ApWifiMac > apMac, Ptr< StaWifiMac > clientMac)
Validate the configured PM mode for the STA(s) affiliated with the client device.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
void DoRun() override
Implementation to actually run this TestCase.
WifiMacHelper GetClientMacHelper() const
WifiStaticEmlsrTest(const WifiStaticEmlsrTestVector &testVec)
Constructor.
WifiHelper GetWifiHelper() const
void ValidateEmlsr()
Validate EMLSR setup.
Ptr< WifiNetDevice > m_clientDev
client WiFi device
EMLSR static setup test suite.
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition boolean.h:26
keep track of a set of node pointers.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
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:125
static void Run()
Run the simulation.
Definition simulator.cc:161
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:169
Make it easy to create and manage PHY objects for the spectrum model.
void AddChannel(const Ptr< SpectrumChannel > channel, const FrequencyRange &freqRange=WHOLE_WIFI_SPECTRUM)
void AddPhyToFreqRangeMapping(uint8_t linkId, const FrequencyRange &freqRange)
Add a given spectrum PHY interface to the PHY instance corresponding of a given link.
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
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:296
@ QUICK
Fast test.
Definition test.h:1057
TestCase(const TestCase &)=delete
Caller graph was not generated because of its size.
Type
Type of test.
Definition test.h:1271
TestSuite(std::string name, Type type=Type::UNIT)
Construct a new test suite.
Definition test.cc:494
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
AttributeValue implementation for Time.
Definition nstime.h:1375
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
void SetRemoteStationManager(std::string type, Args &&... args)
Helper function used to set the station manager.
void ConfigEhtOptions(Args &&... args)
Helper function used to configure the EHT options listed as attributes of the EhtConfiguration class.
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 ...
virtual void SetStandard(WifiStandard standard)
create MAC layers for a ns3::WifiNetDevice.
void SetPowerSaveManager(std::string type, Args &&... args)
Helper function used to set the Power Save Manager.
void SetEmlsrManager(std::string type, Args &&... args)
Helper function used to set the EMLSR Manager that can be installed on an EHT non-AP MLD.
void SetType(std::string type, Args &&... args)
void Set(std::string name, const AttributeValue &v)
static void SetStaticAssociation(Ptr< WifiNetDevice > bssDev, const NetDeviceContainer &clientDevs)
Bypass static capabilities exchange for input devices.
static std::map< linkId_t, linkId_t > GetLinkIdMap(Ptr< WifiNetDevice > apDev, Ptr< WifiNetDevice > clientDev)
Construct non-AP MLD link ID to AP MLD link ID mapping based on PHY channel settings.
static void SetStaticEmlsr(Ptr< WifiNetDevice > apDev, const NetDeviceContainer &clientDevs)
Bypass EML Operating Mode Notification exchange sequence between AP MLD and input non-AP devices.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#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:133
#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
#define NS_TEST_ASSERT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report and abort if not.
Definition test.h:553
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1307
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1324
@ WIFI_STANDARD_80211be
@ WIFI_PM_POWERSAVE
@ WIFI_PM_ACTIVE
@ 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.
const std::vector< std::string > DEFAULT_AP_CHS
std::unordered_map< WifiPhyBand, Ptr< MultiModelSpectrumChannel > > ChannelMap
Every class exported by the ns3 library is enclosed in the ns3 namespace.
FrequencyRange GetFrequencyRange(WifiPhyBand band)
Get the frequency range corresponding to the given PHY band.
double MHz_u
MHz weak type.
Definition wifi-units.h:31
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:605
MHz_u auxPhyWidth
Aux PHY channel width.
std::vector< WifiPowerManagementMode > pmModes
if non-empty, PM mode for each STA affiliated with the client in increasing order of client link ID (...
std::vector< std::string > clientChs
Channel settings for client device.
std::set< uint8_t > emlsrLinks
EMLSR mode links.
std::string name
Test case name.
Time switchDelay
Radio Switch Delay.
static WifiChannelConfig FromString(const std::string &settings, WifiStandard standard=WIFI_STANDARD_UNSPECIFIED)
Get the wifi channel config from a WifiPhy::ChannelSettings string.
Definition wifi-types.cc:24
static WifiStaticEmlsrTestSuite g_wifiStaticEmlsrTestSuite