A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-emlsr-test-base.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-ap-emlsr-manager.h"
12#include "ns3/advanced-emlsr-manager.h"
13#include "ns3/attribute-container.h"
14#include "ns3/boolean.h"
15#include "ns3/config.h"
16#include "ns3/ctrl-headers.h"
17#include "ns3/eht-configuration.h"
18#include "ns3/eht-frame-exchange-manager.h"
19#include "ns3/interference-helper.h"
20#include "ns3/log.h"
21#include "ns3/mgt-action-headers.h"
22#include "ns3/mobility-helper.h"
23#include "ns3/multi-model-spectrum-channel.h"
24#include "ns3/node-list.h"
25#include "ns3/packet-socket-helper.h"
26#include "ns3/packet-socket-server.h"
27#include "ns3/pointer.h"
28#include "ns3/qos-txop.h"
29#include "ns3/rng-seed-manager.h"
30#include "ns3/rr-multi-user-scheduler.h"
31#include "ns3/simulator.h"
32#include "ns3/spectrum-wifi-helper.h"
33#include "ns3/spectrum-wifi-phy.h"
34#include "ns3/string.h"
35#include "ns3/wifi-net-device.h"
36#include "ns3/wifi-spectrum-phy-interface.h"
37
38#include <algorithm>
39#include <functional>
40#include <iomanip>
41
42using namespace ns3;
43
44NS_LOG_COMPONENT_DEFINE("WifiEmlsrTest");
45
47 : TestCase(name)
48{
49}
50
51void
53 uint8_t phyId,
54 WifiConstPsduMap psduMap,
55 WifiTxVector txVector,
56 double txPowerW)
57{
58 auto linkId = mac->GetLinkForPhy(phyId);
59 NS_TEST_ASSERT_MSG_EQ(linkId.has_value(), true, "No link found for PHY ID " << +phyId);
60 m_txPsdus.push_back({Simulator::Now(), psduMap, txVector, *linkId, phyId});
61
62 auto txDuration =
63 WifiPhy::CalculateTxDuration(psduMap, txVector, mac->GetWifiPhy(*linkId)->GetPhyBand());
64
65 for (const auto& [aid, psdu] : psduMap)
66 {
67 std::stringstream ss;
68 ss << std::setprecision(10) << "PSDU #" << m_txPsdus.size() << " Link ID "
69 << +linkId.value() << " Phy ID " << +phyId << " " << psdu->GetHeader(0).GetTypeString();
70 if (psdu->GetHeader(0).IsAction())
71 {
72 ss << " ";
73 WifiActionHeader actionHdr;
74 psdu->GetPayload(0)->PeekHeader(actionHdr);
75 actionHdr.Print(ss);
76 }
77 ss << " #MPDUs " << psdu->GetNMpdus() << " duration/ID " << psdu->GetHeader(0).GetDuration()
78 << " RA = " << psdu->GetAddr1() << " TA = " << psdu->GetAddr2()
79 << " ADDR3 = " << psdu->GetHeader(0).GetAddr3()
80 << " ToDS = " << psdu->GetHeader(0).IsToDs()
81 << " FromDS = " << psdu->GetHeader(0).IsFromDs();
82 if (psdu->GetHeader(0).IsQosData())
83 {
84 ss << " seqNo = {";
85 for (auto& mpdu : *PeekPointer(psdu))
86 {
87 ss << mpdu->GetHeader().GetSequenceNumber() << ",";
88 }
89 ss << "} TID = " << +psdu->GetHeader(0).GetQosTid();
90 }
91 NS_LOG_INFO(ss.str());
92
93 // if this frame is transmitted by an EMLSR client on an EMLSR links, in-device interference
94 // is configured and the TX duration exceeds the threshold (72us), MediumSyncDelay timer is
95 // (re)started at the end of the transmission
96 if (auto staMac = DynamicCast<StaWifiMac>(mac);
97 staMac && staMac->IsEmlsrLink(*linkId) &&
98 staMac->GetEmlsrManager()->GetMediumSyncDuration().IsStrictlyPositive())
99 {
100 const auto mustStartMsd =
101 staMac->GetEmlsrManager()->GetInDeviceInterference() &&
103
104 for (auto id : staMac->GetLinkIds())
105 {
106 // timer started on EMLSR links other than the link on which TX is starting,
107 // provided that a PHY is operating on the link and MediumSyncDuration is not null
108 if (!staMac->IsEmlsrLink(id) || id == *linkId || staMac->GetWifiPhy(id) == nullptr)
109 {
110 continue;
111 }
113 txDuration - TimeStep(1),
114 [=, hdrType = psdu->GetHeader(0).GetTypeString(), this]() {
115 // check if MSD timer was running on the link before completing transmission
116 // and is expected to be running when check is performed (in 2 timesteps)
117 const auto msdTimer =
118 staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(id);
119 const auto msdDuration =
120 staMac->GetEhtConfiguration()->m_mediumSyncDuration;
121 const auto msdWasRunning =
122 (msdTimer.has_value() && (msdDuration - *msdTimer > TimeStep(2)));
123 if (auto phy = staMac->GetWifiPhy(id);
124 !msdWasRunning && !mustStartMsd && phy && phy->IsStateSleep())
125 {
126 // if the MSD timer was not running before the end of the TX, it is not
127 // expected to be started and the PHY operating on this link is
128 // sleeping, do not check that the MSD timer is not started after the
129 // end of the TX, because it may be started because of the sleep period
130 // of the aux PHY
131 return;
132 }
133 Simulator::Schedule(TimeStep(2), [=, this]() {
135 id,
136 (msdWasRunning || mustStartMsd),
137 std::string("after transmitting ") + hdrType +
138 " on link " + std::to_string(*linkId));
139 });
140 });
141 }
142 }
143 }
144 NS_LOG_INFO("TX duration = " << txDuration.As(Time::MS) << " TXVECTOR = " << txVector << "\n");
145}
146
147void
149 uint8_t linkId,
150 bool isRunning,
151 const std::string& msg)
152{
153 auto time = staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(linkId);
154 NS_TEST_ASSERT_MSG_EQ(time.has_value(),
155 isRunning,
157 << " Unexpected status for MediumSyncDelay timer on link " << +linkId
158 << " " << msg);
159 if (auto phy = staMac->GetWifiPhy(linkId))
160 {
161 auto currThreshold = phy->GetCcaEdThreshold();
162 NS_TEST_EXPECT_MSG_EQ((static_cast<int8_t>(currThreshold) ==
163 staMac->GetEmlsrManager()->GetMediumSyncOfdmEdThreshold()),
164 isRunning,
166 << " Unexpected value (" << currThreshold
167 << ") for CCA ED threshold on link " << +linkId << " " << msg);
168 }
169}
170
171void
173{
175 {
176 // if m_putAuxPhyToSleep is false, aux PHYs must not be put to sleep
177 sleep = false;
178 }
179
180 for (const auto& phy : staMac->GetDevice()->GetPhys())
181 {
182 if (phy->GetPhyId() == m_mainPhyId)
183 {
184 continue; // do not check the main PHY
185 }
186
187 auto linkId = staMac->GetLinkForPhy(phy);
188
189 if (linkId.has_value() && !staMac->IsEmlsrLink(*linkId))
190 {
191 continue; // this PHY is not operating on an EMLSR link
192 }
193
194 if (!sleep)
195 {
196 NS_TEST_EXPECT_MSG_EQ(phy->IsStateSleep(),
197 false,
199 << " PHY " << +phy->GetPhyId() << " is in unexpected state "
200 << phy->GetState()->GetState());
201 continue;
202 }
203
204 // if the PHY is in state TX or switching, sleep is postponed until their end
205 const auto delay =
206 (phy->IsStateTx() || phy->IsStateSwitching()) ? phy->GetDelayUntilIdle() : Time{0};
207
208 Simulator::Schedule(delay, [=, this]() {
209 NS_TEST_EXPECT_MSG_EQ(phy->IsStateSleep(),
210 true,
211 "PHY " << +phy->GetPhyId() << " is in unexpected state "
212 << phy->GetState()->GetState());
213 });
214 }
215}
216
217void
219 const EmlsrMainPhySwitchTrace& info)
220{
221 m_traceInfo[index] = info.Clone();
222}
223
224void
226 std::string_view reason,
227 const std::optional<uint8_t>& fromLinkId,
228 uint8_t toLinkId,
229 bool checkFromLinkId,
230 bool checkToLinkId)
231{
232 const auto traceInfoIt = m_traceInfo.find(index);
233 NS_TEST_ASSERT_MSG_EQ((traceInfoIt != m_traceInfo.cend()),
234 true,
235 "Expected stored trace info: " << reason);
236 const auto& traceInfo = traceInfoIt->second;
237
238 NS_TEST_EXPECT_MSG_EQ(traceInfo->GetName(), reason, "Unexpected reason");
239
240 if (checkFromLinkId)
241 {
242 NS_TEST_ASSERT_MSG_EQ(traceInfo->fromLinkId.has_value(),
243 fromLinkId.has_value(),
244 "Unexpected stored from_link ID");
245 if (fromLinkId.has_value())
246 {
247 NS_TEST_EXPECT_MSG_EQ(+traceInfo->fromLinkId.value(),
248 +fromLinkId.value(),
249 "Unexpected from_link ID");
250 }
251 }
252
253 if (checkToLinkId)
254 {
255 NS_TEST_EXPECT_MSG_EQ(+traceInfo->toLinkId, +toLinkId, "Unexpected to_link ID");
256 }
257
258 m_traceInfo.erase(traceInfoIt);
259}
260
261void
263{
266 int64_t streamNumber = m_streamNo;
267
268 Config::SetDefault("ns3::WifiMac::MpduBufferSize", UintegerValue(64));
269 Config::SetDefault("ns3::EmlsrManager::InDeviceInterference", BooleanValue(true));
270 Config::SetDefault("ns3::EmlsrManager::PutAuxPhyToSleep", BooleanValue(m_putAuxPhyToSleep));
271
272 NodeContainer wifiApNode(1);
273 NodeContainer wifiStaNodes(m_nEmlsrStations);
274
275 WifiHelper wifi;
276 // wifi.EnableLogComponents ();
277 wifi.SetStandard(WIFI_STANDARD_80211be);
278 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
279 "DataMode",
280 StringValue("EhtMcs0"),
281 "ControlMode",
282 StringValue("HtMcs0"));
283 wifi.ConfigEhtOptions("EmlsrActivated",
284 BooleanValue(true),
285 "TransitionTimeout",
287
288 // MLDs are configured with three links
289 SpectrumWifiPhyHelper phyHelper(3);
291 phyHelper.SetPcapCaptureType(WifiPhyHelper::PcapCaptureType::PCAP_PER_LINK);
292
293 for (std::size_t id = 0; id < m_channelsStr.size(); ++id)
294 {
295 phyHelper.Set(id, "ChannelSettings", StringValue(m_channelsStr[id]));
297 }
298
299 WifiMacHelper mac;
300 mac.SetType("ns3::ApWifiMac",
301 "Ssid",
302 SsidValue(Ssid("ns-3-ssid")),
303 "BeaconGeneration",
304 BooleanValue(true));
305 mac.SetApEmlsrManager("ns3::AdvancedApEmlsrManager",
306 "WaitTransDelayOnPsduRxError",
307 BooleanValue(true));
308
309 NetDeviceContainer apDevice = wifi.Install(phyHelper, mac, wifiApNode);
311
312 mac.SetType("ns3::StaWifiMac",
313 "Ssid",
314 SsidValue(Ssid("wrong-ssid")),
315 "MaxMissedBeacons",
316 UintegerValue(1e6), // do not deassociate
317 "ActiveProbing",
318 BooleanValue(false));
319 mac.SetEmlsrManager("ns3::AdvancedEmlsrManager",
320 "EmlsrLinkSet",
322 "MainPhyId",
324
325 if (m_nPhysPerEmlsrDevice < 3)
326 {
329 phyHelper.SetPcapCaptureType(WifiPhyHelper::PcapCaptureType::PCAP_PER_LINK);
330
331 for (std::size_t id = 0; id < m_nPhysPerEmlsrDevice; ++id)
332 {
333 phyHelper.Set(id, "ChannelSettings", StringValue(m_channelsStr[id]));
334 auto channel =
335 DynamicCast<MultiModelSpectrumChannel>(m_apMac->GetWifiPhy(id)->GetChannel());
336 NS_TEST_ASSERT_MSG_NE(channel,
337 nullptr,
338 "Channel " << +id << " is not a spectrum channel");
339 phyHelper.AddChannel(channel, m_freqRanges[id]);
340 }
341 }
342
343 NetDeviceContainer staDevices = wifi.Install(phyHelper, mac, wifiStaNodes);
344
345 for (uint32_t i = 0; i < staDevices.GetN(); i++)
346 {
347 auto device = DynamicCast<WifiNetDevice>(staDevices.Get(i));
348 auto staMac = DynamicCast<StaWifiMac>(device->GetMac());
349 auto emlsrManager = staMac->GetEmlsrManager();
350 NS_ASSERT_MSG(i < m_paddingDelay.size(), "Not enough padding delay values provided");
351 emlsrManager->SetAttribute("EmlsrPaddingDelay", TimeValue(m_paddingDelay.at(i)));
352 NS_ASSERT_MSG(i < m_transitionDelay.size(), "Not enough transition delay values provided");
353 emlsrManager->SetAttribute("EmlsrTransitionDelay", TimeValue(m_transitionDelay.at(i)));
354 emlsrManager->TraceConnectWithoutContext(
355 "MainPhySwitch",
357 }
358
359 if (m_nNonEmlsrStations > 0)
360 {
361 // create the other non-AP MLDs for which EMLSR is not activated
362 wifi.ConfigEhtOptions("EmlsrActivated", BooleanValue(false));
363 NodeContainer otherStaNodes(m_nNonEmlsrStations);
364 staDevices.Add(wifi.Install(phyHelper, mac, otherStaNodes));
365 wifiStaNodes.Add(otherStaNodes);
366 }
367
368 for (uint32_t i = 0; i < staDevices.GetN(); i++)
369 {
370 auto device = DynamicCast<WifiNetDevice>(staDevices.Get(i));
371 m_staMacs.push_back(DynamicCast<StaWifiMac>(device->GetMac()));
372 }
373
374 // Trace PSDUs passed to the PHY on AP MLD and non-AP MLDs
375 for (uint8_t phyId = 0; phyId < m_apMac->GetDevice()->GetNPhys(); phyId++)
376 {
378 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
379 "/PhyTxPsduBegin",
381 }
382 for (std::size_t i = 0; i < m_nEmlsrStations + m_nNonEmlsrStations; i++)
383 {
384 for (uint8_t phyId = 0; phyId < m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
385 {
387 "/NodeList/" + std::to_string(i + 1) + "/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
388 std::to_string(phyId) + "/PhyTxPsduBegin",
390 }
391 }
392
393 // Uncomment the lines below to write PCAP files
394 // phyHelper.EnablePcap("wifi-emlsr_AP", apDevice);
395 // phyHelper.EnablePcap("wifi-emlsr_STA", staDevices);
396
397 // Assign fixed streams to random variables in use
398 streamNumber += WifiHelper::AssignStreams(apDevice, streamNumber);
399 streamNumber += WifiHelper::AssignStreams(staDevices, streamNumber);
400
401 MobilityHelper mobility;
403
404 for (std::size_t id = 0; id <= m_nEmlsrStations + m_nNonEmlsrStations; id++)
405 {
406 // all non-AP MLDs are co-located
407 positionAlloc->Add(Vector(std::min<double>(id, 1), 0.0, 0.0));
408 }
409 mobility.SetPositionAllocator(positionAlloc);
410
411 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
412 mobility.Install(wifiApNode);
413 mobility.Install(wifiStaNodes);
414
415 // install packet socket on all nodes
416 PacketSocketHelper packetSocket;
417 packetSocket.Install(wifiApNode);
418 packetSocket.Install(wifiStaNodes);
419
420 // install a packet socket server on all nodes
421 for (auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); nodeIt++)
422 {
423 PacketSocketAddress srvAddr;
424 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
425 NS_TEST_ASSERT_MSG_NE(device, nullptr, "Expected a WifiNetDevice");
426 srvAddr.SetSingleDevice(device->GetIfIndex());
427 srvAddr.SetProtocol(1);
428
429 auto server = CreateObject<PacketSocketServer>();
430 server->SetLocal(srvAddr);
431 (*nodeIt)->AddApplication(server);
432 server->SetStartTime(Seconds(0)); // now
433 server->SetStopTime(m_duration);
434 }
435
436 // set DL and UL packet sockets
437 for (const auto& staMac : m_staMacs)
438 {
439 m_dlSockets.emplace_back();
440 m_dlSockets.back().SetSingleDevice(m_apMac->GetDevice()->GetIfIndex());
441 m_dlSockets.back().SetPhysicalAddress(staMac->GetDevice()->GetAddress());
442 m_dlSockets.back().SetProtocol(1);
443
444 m_ulSockets.emplace_back();
445 m_ulSockets.back().SetSingleDevice(staMac->GetDevice()->GetIfIndex());
446 m_ulSockets.back().SetPhysicalAddress(m_apMac->GetDevice()->GetAddress());
447 m_ulSockets.back().SetProtocol(1);
448 }
449
450 m_startAid = m_apMac->GetNextAssociationId();
451
452 // schedule ML setup for one station at a time
453 m_apMac->TraceConnectWithoutContext(
454 "AssociatedSta",
456 for (const auto& [aci, ac] : wifiAcList)
457 {
458 m_apMac->GetQosTxop(aci)->TraceConnectWithoutContext(
459 "BaEstablished",
461 for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
462 {
463 m_staMacs[id]->GetQosTxop(aci)->TraceConnectWithoutContext(
464 "BaEstablished",
466 }
467 }
468 Simulator::Schedule(Seconds(0), [&]() { m_staMacs[0]->SetSsid(Ssid("ns-3-ssid")); });
469}
470
473 std::size_t staId,
474 std::size_t count,
475 std::size_t pktSize,
476 uint8_t priority) const
477{
478 auto client = CreateObject<PacketSocketClient>();
479 client->SetAttribute("PacketSize", UintegerValue(pktSize));
480 client->SetAttribute("MaxPackets", UintegerValue(count));
481 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
482 client->SetAttribute("Priority", UintegerValue(priority));
483 client->SetRemote(dir == DOWNLINK ? m_dlSockets.at(staId) : m_ulSockets.at(staId));
484 client->SetStartTime(Seconds(0)); // now
485 client->SetStopTime(m_duration - Simulator::Now());
486
487 return client;
488}
489
490void
492{
493 if (m_lastAid == aid)
494 {
495 // another STA of this non-AP MLD has already fired this callback
496 return;
497 }
498 m_lastAid = aid;
499
500 // wait some time (10ms) to allow the completion of association
501 const auto delay = MilliSeconds(10);
502
503 if (!m_establishBaDl.empty())
504 {
505 // trigger establishment of BA agreement with AP as originator
506 Simulator::Schedule(delay, [=, this]() {
507 m_apMac->GetDevice()->GetNode()->AddApplication(
508 GetApplication(DOWNLINK, aid - m_startAid, 4, 1000, m_establishBaDl.front()));
509 });
510 }
511 else if (!m_establishBaUl.empty())
512 {
513 // trigger establishment of BA agreement with AP as recipient
514 Simulator::Schedule(delay, [=, this]() {
515 m_staMacs[aid - m_startAid]->GetDevice()->GetNode()->AddApplication(
516 GetApplication(UPLINK, aid - m_startAid, 4, 1000, m_establishBaUl.front()));
517 });
518 }
519 else
520 {
521 Simulator::Schedule(delay, [=, this]() { SetSsid(aid - m_startAid + 1); });
522 }
523}
524
525void
527 uint8_t tid,
528 std::optional<Mac48Address> /* gcrGroup */)
529{
530 // wait some time (10ms) to allow the exchange of the data frame that triggered the Block Ack
531 const auto delay = MilliSeconds(10);
532
533 auto linkId = m_apMac->IsAssociated(recipient);
534 NS_TEST_ASSERT_MSG_EQ(linkId.has_value(), true, "No link for association of " << recipient);
535 auto aid = m_apMac->GetWifiRemoteStationManager(*linkId)->GetAssociationId(recipient);
536
537 if (auto it = std::find(m_establishBaDl.cbegin(), m_establishBaDl.cend(), tid);
538 it != m_establishBaDl.cend() && std::next(it) != m_establishBaDl.cend())
539 {
540 // trigger establishment of BA agreement with AP as originator
541 Simulator::Schedule(delay, [=, this]() {
542 m_apMac->GetDevice()->GetNode()->AddApplication(
543 GetApplication(DOWNLINK, aid - m_startAid, 4, 1000, *std::next(it)));
544 });
545 }
546 else if (!m_establishBaUl.empty())
547 {
548 // trigger establishment of BA agreement with AP as recipient
549 Simulator::Schedule(delay, [=, this]() {
550 m_staMacs[aid - m_startAid]->GetDevice()->GetNode()->AddApplication(
551 GetApplication(UPLINK, aid - m_startAid, 4, 1000, m_establishBaUl.front()));
552 });
553 }
554 else
555 {
556 Simulator::Schedule(delay, [=, this]() { SetSsid(aid - m_startAid + 1); });
557 }
558}
559
560void
562 Mac48Address recipient,
563 uint8_t tid,
564 std::optional<Mac48Address> /* gcrGroup */)
565{
566 // wait some time (10ms) to allow the exchange of the data frame that triggered the Block Ack
567 const auto delay = MilliSeconds(10);
568
569 if (auto it = std::find(m_establishBaUl.cbegin(), m_establishBaUl.cend(), tid);
570 it != m_establishBaUl.cend() && std::next(it) != m_establishBaUl.cend())
571 {
572 // trigger establishment of BA agreement with AP as recipient
573 Simulator::Schedule(delay, [=, this]() {
574 m_staMacs[index]->GetDevice()->GetNode()->AddApplication(
575 GetApplication(UPLINK, index, 4, 1000, *std::next(it)));
576 });
577 }
578 else
579 {
580 Simulator::Schedule(delay, [=, this]() { SetSsid(index + 1); });
581 }
582}
583
584void
586{
588 {
589 // make the next STA start ML discovery & setup
590 m_staMacs[count]->SetSsid(Ssid("ns-3-ssid"));
591 return;
592 }
593 // all stations associated; start traffic if needed
594 StartTraffic();
595 // stop generation of beacon frames in order to avoid interference
596 m_apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
597 // Set the short slot time on the 2.4 GHz link because it is not updated automatically given
598 // that no more Beacon frames are sent
599 for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
600 {
601 m_staMacs[id]->GetDevice()->GetPhy(0)->SetSlot(MicroSeconds(9));
602 }
603 // disconnect callbacks
604 m_apMac->TraceDisconnectWithoutContext(
605 "AssociatedSta",
607 for (const auto& [aci, ac] : wifiAcList)
608 {
609 m_apMac->GetQosTxop(aci)->TraceDisconnectWithoutContext(
610 "BaEstablished",
612 for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
613 {
614 m_staMacs[id]->GetQosTxop(aci)->TraceDisconnectWithoutContext(
615 "BaEstablished",
617 }
618 }
619}
620
621void
623 Mac48Address dest,
624 uint8_t linkId,
626 bool blocked,
627 std::string description,
628 bool testUnblockedForOtherReasons)
629{
631 auto mask = mac->GetMacQueueScheduler()->GetQueueLinkMask(AC_BE, queueId, linkId);
632 NS_TEST_EXPECT_MSG_EQ(mask.has_value(),
633 true,
634 description << ": Expected to find a mask for EMLSR link " << +linkId);
635 if (blocked)
636 {
637 NS_TEST_EXPECT_MSG_EQ(mask->test(static_cast<std::size_t>(reason)),
638 true,
639 description << ": Expected EMLSR link " << +linkId
640 << " to be blocked for reason " << reason);
641 if (testUnblockedForOtherReasons)
642 {
643 NS_TEST_EXPECT_MSG_EQ(mask->count(),
644 1,
645 description << ": Expected EMLSR link " << +linkId
646 << " to be blocked for one reason only");
647 }
648 }
649 else if (testUnblockedForOtherReasons)
650 {
651 NS_TEST_EXPECT_MSG_EQ(mask->none(),
652 true,
653 description << ": Expected EMLSR link " << +linkId
654 << " to be unblocked");
655 }
656 else
657 {
658 NS_TEST_EXPECT_MSG_EQ(mask->test(static_cast<std::size_t>(reason)),
659 false,
660 description << ": Expected EMLSR link " << +linkId
661 << " to be unblocked for reason " << reason);
662 }
663}
void BaEstablishedDl(Mac48Address recipient, uint8_t tid, std::optional< Mac48Address >)
Callback connected to the QosTxop's BaEstablished trace source of the AP's BE AC.
virtual void MainPhySwitchInfoCallback(std::size_t index, const EmlsrMainPhySwitchTrace &info)
Callback connected to the EMLSR Manager MainPhySwitch trace source.
std::size_t m_nNonEmlsrStations
number of stations to create that do not activate EMLSR
std::vector< uint8_t > m_establishBaDl
the TIDs for which BA needs to be established with the AP as originator
void CheckBlockedLink(Ptr< WifiMac > mac, Mac48Address dest, uint8_t linkId, WifiQueueBlockedReason reason, bool blocked, std::string description, bool testUnblockedForOtherReasons=true)
Check whether QoS data unicast transmissions addressed to the given destination on the given link are...
std::size_t m_nEmlsrStations
number of stations to create that activate EMLSR
std::vector< PacketSocketAddress > m_dlSockets
packet socket address for DL traffic
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.
bool m_putAuxPhyToSleep
whether aux PHYs are put to sleep during DL/UL TXOPs
void BaEstablishedUl(std::size_t index, Mac48Address recipient, uint8_t tid, std::optional< Mac48Address >)
Callback connected to the QosTxop's BaEstablished trace source of a STA's BE AC.
TrafficDirection
Enumeration for traffic directions.
void CheckMsdTimerRunning(Ptr< StaWifiMac > staMac, uint8_t linkId, bool isRunning, const std::string &msg)
Check whether the MediumSyncDelay timer is running on the given link of the given device.
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
Ptr< PacketSocketClient > GetApplication(TrafficDirection dir, std::size_t staId, std::size_t count, std::size_t pktSize, uint8_t priority=0) const
std::vector< FrameInfo > m_txPsdus
transmitted PSDUs
uint32_t m_rngSeed
RNG seed value.
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.
uint16_t m_lastAid
AID of last associated station.
std::vector< Time > m_transitionDelay
Transition Delay advertised by the non-AP MLD.
void CheckMainPhyTraceInfo(std::size_t index, std::string_view reason, const std::optional< uint8_t > &fromLinkId, uint8_t toLinkId, bool checkFromLinkId=true, bool checkToLinkId=true)
Check information provided by the EMLSR Manager MainPhySwitch trace.
uint16_t m_startAid
first AID to allocate to stations
std::array< std::string, 3 > m_channelsStr
array of strings defining the channels for the MLD links
std::map< std::size_t, std::shared_ptr< EmlsrMainPhySwitchTrace > > m_traceInfo
EMLSR client ID-indexed map of trace info from last main PHY switch.
Time m_transitionTimeout
Transition Timeout advertised by the AP MLD.
const std::array< FrequencyRange, 3 > m_freqRanges
array of frequency ranges for MLD links
void SetSsid(std::size_t count)
Set the SSID on the next station that needs to start the association procedure, or start traffic if n...
std::vector< PacketSocketAddress > m_ulSockets
packet socket address for UL traffic
void StaAssociated(uint16_t aid, Mac48Address)
Callback connected to the ApWifiMac's AssociatedSta trace source.
void CheckAuxPhysSleepMode(Ptr< StaWifiMac > staMac, bool sleep)
Check whether aux PHYs of the given device are in sleep mode/awake.
std::vector< Ptr< StaWifiMac > > m_staMacs
MACs of the non-AP MLDs.
std::size_t m_nPhysPerEmlsrDevice
number of PHYs per EMLSR client
virtual void StartTraffic()
Start the generation of traffic (needs to be overridden)
int64_t m_streamNo
RNG stream number.
uint64_t m_rngRun
RNG run value.
std::vector< uint8_t > m_establishBaUl
the TIDs for which BA needs to be established with the AP as recipient
EmlsrOperationsTestBase(const std::string &name)
Constructor.
A container for one type of attribute.
AttributeValue implementation for Boolean.
Definition boolean.h:26
static constexpr uint16_t MEDIUM_SYNC_THRESHOLD_USEC
The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0.
an EUI-48 address
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.
static Iterator Begin()
Definition node-list.cc:226
static Iterator End()
Definition node-list.cc:233
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
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 EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
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)
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
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:403
@ MS
millisecond
Definition nstime.h:106
int64_t GetTimeStep() const
Get the raw time value, in the current resolution unit.
Definition nstime.h:434
AttributeValue implementation for Time.
Definition nstime.h:1432
Hold an unsigned integer type.
Definition uinteger.h:34
See IEEE 802.11 chapter 7.3.1.11 Header format: | category: 1 | action value: 1 |.
void Print(std::ostream &os) const override
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 SetPcapCaptureType(PcapCaptureType type)
Set the PCAP capture type to be used.
void SetPcapDataLinkType(SupportedPcapDataLinkTypes dlt)
Set the data link type of PCAP traces to be used.
void Set(std::string name, const AttributeValue &v)
@ DLT_IEEE802_11_RADIO
Include Radiotap link layer information.
static Time CalculateTxDuration(uint32_t size, const WifiTxVector &txVector, WifiPhyBand band, uint16_t staId=SU_STA_ID)
Definition wifi-phy.cc:1563
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
#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
void SetDefault(std::string name, const AttributeValue &value)
Definition config.cc:886
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
#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:554
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1345
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1357
WifiQueueBlockedReason
Enumeration of the reasons to block container queues.
@ WIFI_STANDARD_80211be
@ AC_BE
Best Effort.
Definition qos-utils.h:64
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:443
std:: tuple< WifiContainerQueueType, WifiReceiverAddressType, Mac48Address, std::optional< uint8_t > > WifiContainerQueueId
Tuple (queue type, receiver address type, Address, TID) identifying a container queue.
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
const std::map< AcIndex, WifiAc > wifiAcList
Map containing the four ACs in increasing order of priority (according to Table 10-1 "UP-to-AC Mappin...
Definition qos-utils.cc:115
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
Base struct for EMLSR Main PHY switch traces.
virtual std::shared_ptr< EmlsrMainPhySwitchTrace > Clone() const =0
std::string dir
uint32_t pktSize
packet size used for the simulation (in bytes)