A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-emlsr-enabling-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 Universita' degli Studi di Napoli Federico II
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Stefano Avallone <stavallo@unina.it>
7 */
8
10
11#include "ns3/advanced-emlsr-manager.h"
12#include "ns3/boolean.h"
13#include "ns3/config.h"
14#include "ns3/ctrl-headers.h"
15#include "ns3/default-power-save-manager.h"
16#include "ns3/log.h"
17#include "ns3/mgt-action-headers.h"
18#include "ns3/qos-txop.h"
19#include "ns3/simulator.h"
20#include "ns3/string.h"
21#include "ns3/wifi-net-device.h"
22#include "ns3/wifi-phy.h"
23
24#include <algorithm>
25#include <functional>
26#include <iomanip>
27
28using namespace ns3;
29
30NS_LOG_COMPONENT_DEFINE("WifiEmlsrEnablingTest");
31
34 "Check serialization and deserialization of the EML Operating Mode Notification frame")
35{
36}
37
38void
40{
41 MgtEmlOmn frame;
42
43 // Both EMLSR Mode and EMLMR Mode subfields set to 0 (no link bitmap);
45
46 frame.m_emlControl.emlsrMode = 1;
47 frame.SetLinkIdInBitmap(0);
48 frame.SetLinkIdInBitmap(5);
49 frame.SetLinkIdInBitmap(15);
50
51 // Adding Link Bitmap
53
54 NS_TEST_EXPECT_MSG_EQ((frame.GetLinkBitmap() == std::list<uint8_t>{0, 5, 15}),
55 true,
56 "Unexpected link bitmap");
57
58 auto padding = MicroSeconds(64);
59 auto transition = MicroSeconds(128);
60
64 frame.m_emlsrParamUpdate->transitionDelay =
66
67 // Adding the EMLSR Parameter Update field
69
72 padding,
73 "Unexpected EMLSR Padding Delay");
76 transition,
77 "Unexpected EMLSR Transition Delay");
78}
79
80EmlOmnExchangeTest::EmlOmnExchangeTest(const std::set<uint8_t>& linksToEnableEmlsrOn,
81 Time transitionTimeout)
82 : EmlsrOperationsTestBase("Check EML Notification exchange"),
85{
86 m_linksToEnableEmlsrOn = linksToEnableEmlsrOn;
89 m_transitionTimeout = transitionTimeout;
90 m_duration = Seconds(0.5);
91}
92
93void
95{
97
99 for (std::size_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++)
100 {
101 m_apMac->GetWifiPhy(linkId)->SetPostReceptionErrorModel(m_errorModel);
102 }
103
104 m_staMacs[0]->TraceConnectWithoutContext("AckedMpdu",
106 m_staMacs[0]->TraceConnectWithoutContext("DroppedMpdu",
108
109 // Add a Power Save Manager to the EMLSR client and set all the links, but the link used for ML
110 // setup, to powersave mode, so that they will switch to active mode when EMLSR mode is enabled
111 std::string s;
112 for (uint8_t id = 0; id < m_staMacs[0]->GetNLinks(); ++id)
113 {
114 if (id != m_mainPhyId)
115 {
116 s += std::to_string(id) + " true, ";
117 }
118 }
119 s.pop_back();
120 s.pop_back();
121 m_staMacs[0]->SetPowerSaveManager(
123}
124
125void
127 uint8_t phyId,
128 WifiConstPsduMap psduMap,
129 WifiTxVector txVector,
130 double txPowerW)
131{
132 EmlsrOperationsTestBase::Transmit(mac, phyId, psduMap, txVector, txPowerW);
133 auto linkId = m_txPsdus.back().linkId;
134
135 auto psdu = psduMap.begin()->second;
136 const auto txDuration =
138 txVector,
139 mac->GetDevice()->GetPhy(phyId)->GetPhyBand());
140
141 switch (psdu->GetHeader(0).GetType())
142 {
144 NS_TEST_EXPECT_MSG_EQ(+linkId, +m_mainPhyId, "AssocReq not sent by the main PHY");
145 CheckEmlCapabilitiesInAssocReq(*psdu->begin(), txVector, linkId);
146 break;
147
149 CheckEmlCapabilitiesInAssocResp(*psdu->begin(), txVector, linkId);
150
151 // check the PM mode of links after ML setup
152 Simulator::Schedule(txDuration + mac->GetDevice()->GetPhy(phyId)->GetSifs(), [=, this]() {
153 const auto linkIds = m_staMacs[0]->GetSetupLinkIds();
154 for (const auto id : linkIds)
155 {
156 // only the link used for ML setup must be in active mode
157 const auto isActive = (id == linkId);
158 const auto pmMode = m_staMacs[0]->GetPmMode(id);
159 NS_TEST_EXPECT_MSG_EQ((pmMode == WifiPowerManagementMode::WIFI_PM_ACTIVE),
160 isActive,
161 "Unexpected PM mode (" << +pmMode << ") for link " << +id);
162 }
163 });
164 break;
165
167 if (auto [category, action] = WifiActionHeader::Peek(psdu->GetPayload(0));
169 action.protectedEhtAction ==
171 {
172 CheckEmlNotification(psdu, txVector, linkId);
173
175 m_staMacs[0]->GetLinkIdByAddress(psdu->GetAddr2()) == linkId)
176 {
177 // transmitted by non-AP MLD, we need to corrupt it
178 m_uidList.push_front(psdu->GetPacket()->GetUid());
179 m_errorModel->SetList(m_uidList);
180 }
181 break;
182 }
183
184 default:;
185 }
186}
187
188void
190 const WifiTxVector& txVector,
191 uint8_t linkId)
192{
194 mpdu->GetPacket()->PeekHeader(frame);
195
196 const auto& mle = frame.Get<MultiLinkElement>();
197 NS_TEST_ASSERT_MSG_EQ(mle.has_value(), true, "Multi-Link Element must be present in AssocReq");
198
199 NS_TEST_ASSERT_MSG_EQ(mle->HasEmlCapabilities(),
200 true,
201 "Multi-Link Element in AssocReq must have EML Capabilities");
202 NS_TEST_ASSERT_MSG_EQ(mle->IsEmlsrSupported(),
203 true,
204 "EML Support subfield of EML Capabilities in AssocReq must be set to 1");
205 NS_TEST_ASSERT_MSG_EQ(mle->GetEmlsrPaddingDelay(),
206 m_paddingDelay.at(0),
207 "Unexpected Padding Delay in EML Capabilities included in AssocReq");
208 NS_TEST_ASSERT_MSG_EQ(mle->GetEmlsrTransitionDelay(),
209 m_transitionDelay.at(0),
210 "Unexpected Transition Delay in EML Capabilities included in AssocReq");
211}
212
213void
215 const WifiTxVector& txVector,
216 uint8_t linkId)
217{
218 bool sentToEmlsrClient =
219 (m_staMacs[0]->GetLinkIdByAddress(mpdu->GetHeader().GetAddr1()) == linkId);
220
221 if (!sentToEmlsrClient)
222 {
223 // nothing to check
224 return;
225 }
226
228 mpdu->GetPacket()->PeekHeader(frame);
229
230 const auto& mle = frame.Get<MultiLinkElement>();
231 NS_TEST_ASSERT_MSG_EQ(mle.has_value(), true, "Multi-Link Element must be present in AssocResp");
232
233 NS_TEST_ASSERT_MSG_EQ(mle->HasEmlCapabilities(),
234 true,
235 "Multi-Link Element in AssocResp must have EML Capabilities");
236 NS_TEST_ASSERT_MSG_EQ(mle->IsEmlsrSupported(),
237 true,
238 "EML Support subfield of EML Capabilities in AssocResp must be set to 1");
240 mle->GetTransitionTimeout(),
242 "Unexpected Transition Timeout in EML Capabilities included in AssocResp");
243}
244
245void
247 const WifiTxVector& txVector,
248 uint8_t linkId)
249{
250 MgtEmlOmn frame;
251 auto mpdu = *psdu->begin();
252 auto pkt = mpdu->GetPacket()->Copy();
254 pkt->RemoveHeader(frame);
255 NS_LOG_DEBUG(frame);
256
257 bool sentbyNonApMld = m_staMacs[0]->GetLinkIdByAddress(mpdu->GetHeader().GetAddr2()) == linkId;
258
260 1,
261 "EMLSR Mode subfield should be set to 1 (frame sent by non-AP MLD: "
262 << std::boolalpha << sentbyNonApMld << ")");
263
265 0,
266 "EMLMR Mode subfield should be set to 0 (frame sent by non-AP MLD: "
267 << std::boolalpha << sentbyNonApMld << ")");
268
270 true,
271 "Link Bitmap subfield should be present (frame sent by non-AP MLD: "
272 << std::boolalpha << sentbyNonApMld << ")");
273
274 auto setupLinks = m_staMacs[0]->GetSetupLinkIds();
275 std::list<uint8_t> expectedEmlsrLinks;
276 std::set_intersection(setupLinks.begin(),
277 setupLinks.end(),
280 std::back_inserter(expectedEmlsrLinks));
281
282 NS_TEST_EXPECT_MSG_EQ((expectedEmlsrLinks == frame.GetLinkBitmap()),
283 true,
284 "Unexpected Link Bitmap subfield (frame sent by non-AP MLD: "
285 << std::boolalpha << sentbyNonApMld << ")");
286
287 if (!sentbyNonApMld)
288 {
289 // the frame has been sent by the AP MLD
292 0,
293 "EMLSR Parameter Update Control should be set to 0 in frames sent by the AP MLD");
294
295 // as soon as the non-AP MLD receives this frame, it sets the EMLSR links
296 auto delay = WifiPhy::CalculateTxDuration(psdu,
297 txVector,
298 m_staMacs[0]->GetWifiPhy(linkId)->GetPhyBand()) +
299 MicroSeconds(1); // to account for propagation delay
301 }
302
304 +linkId,
305 "EML Notification received on unexpected link (frame sent by non-AP MLD: "
306 << std::boolalpha << sentbyNonApMld << ")");
307}
308
309void
311{
312 const auto& hdr = mpdu->GetHeader();
313
314 if (hdr.IsMgt() && hdr.IsAction())
315 {
316 if (auto [category, action] = WifiActionHeader::Peek(mpdu->GetPacket());
318 action.protectedEhtAction ==
320 {
321 // the EML Operating Mode Notification frame that the non-AP MLD sent has been
322 // acknowledged; after the transition timeout, the EMLSR links have been set
325 this);
326 }
327 }
328}
329
330void
332{
333 const auto& hdr = mpdu->GetHeader();
334
335 if (hdr.IsMgt() && hdr.IsAction())
336 {
337 if (auto [category, action] = WifiActionHeader::Peek(mpdu->GetPacket());
339 action.protectedEhtAction ==
341 {
342 // the EML Operating Mode Notification frame has been dropped. Don't
343 // corrupt it anymore
345 }
346 }
347}
348
349void
351{
353
354 auto setupLinks = m_staMacs[0]->GetSetupLinkIds();
355 std::set<uint8_t> expectedEmlsrLinks;
356 std::set_intersection(setupLinks.begin(),
357 setupLinks.end(),
360 std::inserter(expectedEmlsrLinks, expectedEmlsrLinks.end()));
361
362 NS_TEST_EXPECT_MSG_EQ((expectedEmlsrLinks == m_staMacs[0]->GetEmlsrManager()->GetEmlsrLinks()),
363 true,
364 "Unexpected set of EMLSR links)");
365
366 // check the PM mode of links after enabling EMLSR mode
367 const auto linkIds = m_staMacs[0]->GetSetupLinkIds();
368 for (const auto id : linkIds)
369 {
370 // the link used for ML setup and the EMLSR links must be in active mode
371 const auto isActive = ((id == m_mainPhyId) || m_linksToEnableEmlsrOn.contains(id));
372 const auto pmMode = m_staMacs[0]->GetPmMode(id);
374 isActive,
375 "Unexpected PM mode (" << +pmMode << ") for link " << +id);
376 }
377}
378
379void
381{
384
386 2,
387 "Unexpected number of times CheckEmlsrLinks() is called");
390 1,
391 "Unexpected number of times the EML Notification frame is dropped due to max retry limit");
392
394}
395
406
Test the exchange of EML Operating Mode Notification frames.
void CheckEmlCapabilitiesInAssocResp(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of the EML Capabilities subfield of the Multi-Link Element included in the Associat...
void TxOk(Ptr< const WifiMpdu > mpdu)
Callback invoked when the non-AP MLD receives the acknowledgment for a transmitted MPDU.
std::list< uint64_t > m_uidList
list of UIDs of packets to corrupt
std::size_t m_checkEmlsrLinksCount
counter for the number of times CheckEmlsrLinks is called (should be two: when the transition timeout...
Ptr< ListErrorModel > m_errorModel
error rate model to corrupt packets at AP MLD
void DoSetup() override
Implementation to do any local setup required for this TestCase.
EmlOmnExchangeTest(const std::set< uint8_t > &linksToEnableEmlsrOn, Time transitionTimeout)
Constructor.
std::size_t m_emlNotificationDroppedCount
counter for the number of times the EML Notification frame sent by the non-AP MLD has been dropped du...
void CheckEmlsrLinks()
Check that the EMLSR mode has been enabled on the expected EMLSR links.
void CheckEmlCapabilitiesInAssocReq(Ptr< const WifiMpdu > mpdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of the EML Capabilities subfield of the Multi-Link Element included in the Associat...
void TxDropped(WifiMacDropReason reason, Ptr< const WifiMpdu > mpdu)
Callback invoked when the non-AP MLD drops the given MPDU for the given reason.
void CheckEmlNotification(Ptr< const WifiPsdu > psdu, const WifiTxVector &txVector, uint8_t linkId)
Check the content of a received EML Operating Mode Notification frame.
void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override
Callback invoked when a FEM passes PSDUs to the PHY.
void DoRun() override
Implementation to actually run this TestCase.
Test EML Operating Mode Notification frame serialization and deserialization.
void DoRun() override
Implementation to actually run this TestCase.
std::size_t m_nNonEmlsrStations
number of stations to create that do not activate EMLSR
std::size_t m_nEmlsrStations
number of stations to create that activate EMLSR
std::vector< Time > m_paddingDelay
Padding Delay advertised by the non-AP MLD.
std::set< uint8_t > m_linksToEnableEmlsrOn
IDs of the links on which EMLSR mode has to be enabled.
Ptr< ApWifiMac > m_apMac
AP wifi MAC.
void DoSetup() override
Implementation to do any local setup required for this TestCase.
uint8_t m_mainPhyId
ID of the main PHY.
Time m_duration
simulation duration
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
virtual void Transmit(Ptr< WifiMac > mac, uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW)
Callback invoked when a FEM passes PSDUs to the PHY.
std::vector< Time > m_transitionDelay
Transition Delay advertised by the non-AP MLD.
Time m_transitionTimeout
Transition Timeout advertised by the AP MLD.
std::vector< Ptr< StaWifiMac > > m_staMacs
MACs of the non-AP MLDs.
EmlsrOperationsTestBase(const std::string &name)
Constructor.
wifi EMLSR suite to test the procedure for enabling EMLSR mode
void TestHeaderSerialization(const T &hdr, Args &&... args)
Serialize the given header in a buffer, then create a new header by deserializing from the buffer and...
HeaderSerializationTestCase(std::string name)
Constructor.
Implement the header for management frames of type association request.
Implement the header for management frames of type association and reassociation response.
Implement the header for Action frames of type EML Operating Mode Notification.
void SetLinkIdInBitmap(uint8_t linkId)
Set the bit position in the link bitmap corresponding to the given link.
EmlControl m_emlControl
EML Control field.
std::optional< EmlsrParamUpdate > m_emlsrParamUpdate
EMLSR Parameter Update field.
std::list< uint8_t > GetLinkBitmap() const
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
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
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
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
static std::pair< CategoryValue, ActionValue > Peek(Ptr< const Packet > pkt)
Peek an Action header from the given packet.
static std::pair< CategoryValue, ActionValue > Remove(Ptr< Packet > pkt)
Remove an Action header from the given packet.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1574
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
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:690
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:260
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
Ptr< T > CreateObjectWithAttributes(Args... args)
Allocate an Object on the heap and initialize with a set of attributes.
#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
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
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
WifiMacDropReason
The reason why an MPDU was dropped.
Definition wifi-mac.h:71
@ WIFI_PM_ACTIVE
Every class exported by the ns3 library is enclosed in the ns3 namespace.
@ WIFI_MAC_MGT_ACTION
@ WIFI_MAC_MGT_ASSOCIATION_RESPONSE
@ WIFI_MAC_MGT_ASSOCIATION_REQUEST
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
static uint8_t EncodeEmlsrTransitionDelay(Time delay)
static Time DecodeEmlsrTransitionDelay(uint8_t value)
static Time DecodeEmlsrPaddingDelay(uint8_t value)
static uint8_t EncodeEmlsrPaddingDelay(Time delay)
uint8_t emlsrParamUpdateCtrl
EMLSR Parameter Update Control.
std::optional< uint16_t > linkBitmap
EMLSR/EMLMR Link Bitmap.
EMLSR Parameter Update field.
static WifiEmlsrEnablingTestSuite g_wifiEmlsrEnablingTestSuite
the test suite