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 = staMac->GetEmlsrManager()->GetInDeviceInterference() &&
101 txDuration > MEDIUM_SYNC_THRESHOLD;
102
103 for (auto id : staMac->GetLinkIds())
104 {
105 // timer started on EMLSR links other than the link on which TX is starting,
106 // provided that a PHY is operating on the link and MediumSyncDuration is not null
107 if (!staMac->IsEmlsrLink(id) || id == *linkId || staMac->GetWifiPhy(id) == nullptr)
108 {
109 continue;
110 }
112 txDuration - TimeStep(1),
113 [=, hdrType = psdu->GetHeader(0).GetTypeString(), this]() {
114 // check if MSD timer was running on the link before completing transmission
115 // and is expected to be running when check is performed (in 2 timesteps)
116 const auto msdTimer =
117 staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(id);
118 const auto msdDuration =
119 staMac->GetEhtConfiguration()->m_mediumSyncDuration;
120 const auto msdWasRunning =
121 (msdTimer.has_value() && (msdDuration - *msdTimer > TimeStep(2)));
122 if (auto phy = staMac->GetWifiPhy(id);
123 !msdWasRunning && !mustStartMsd && phy && phy->IsStateSleep())
124 {
125 // if the MSD timer was not running before the end of the TX, it is not
126 // expected to be started and the PHY operating on this link is
127 // sleeping, do not check that the MSD timer is not started after the
128 // end of the TX, because it may be started because of the sleep period
129 // of the aux PHY
130 return;
131 }
132 Simulator::Schedule(TimeStep(2), [=, this]() {
134 id,
135 (msdWasRunning || mustStartMsd),
136 std::string("after transmitting ") + hdrType +
137 " on link " + std::to_string(*linkId));
138 });
139 });
140 }
141 }
142 }
143 NS_LOG_INFO("TX duration = " << txDuration.As(Time::MS) << " TXVECTOR = " << txVector << "\n");
144}
145
146void
148 uint8_t linkId,
149 bool isRunning,
150 const std::string& msg)
151{
152 auto time = staMac->GetEmlsrManager()->GetElapsedMediumSyncDelayTimer(linkId);
153 NS_TEST_ASSERT_MSG_EQ(time.has_value(),
154 isRunning,
156 << " Unexpected status for MediumSyncDelay timer on link " << +linkId
157 << " " << msg);
158 if (auto phy = staMac->GetWifiPhy(linkId))
159 {
160 auto currThreshold = phy->GetCcaEdThreshold();
161 NS_TEST_EXPECT_MSG_EQ((static_cast<int8_t>(currThreshold) ==
162 staMac->GetEmlsrManager()->GetMediumSyncOfdmEdThreshold()),
163 isRunning,
165 << " Unexpected value (" << currThreshold
166 << ") for CCA ED threshold on link " << +linkId << " " << msg);
167 }
168}
169
170void
172{
174 {
175 // if m_putAuxPhyToSleep is false, aux PHYs must not be put to sleep
176 sleep = false;
177 }
178
179 for (const auto& phy : staMac->GetDevice()->GetPhys())
180 {
181 if (phy->GetPhyId() == m_mainPhyId)
182 {
183 continue; // do not check the main PHY
184 }
185
186 auto linkId = staMac->GetLinkForPhy(phy);
187
188 if (linkId.has_value() && !staMac->IsEmlsrLink(*linkId))
189 {
190 continue; // this PHY is not operating on an EMLSR link
191 }
192
193 if (!sleep)
194 {
195 NS_TEST_EXPECT_MSG_EQ(phy->IsStateSleep(),
196 false,
198 << " PHY " << +phy->GetPhyId() << " is in unexpected state "
199 << phy->GetState()->GetState());
200 continue;
201 }
202
203 // if the PHY is in state TX or switching, sleep is postponed until their end
204 const auto delay =
205 (phy->IsStateTx() || phy->IsStateSwitching()) ? phy->GetDelayUntilIdle() : Time{0};
206
207 Simulator::Schedule(delay, [=, this]() {
208 NS_TEST_EXPECT_MSG_EQ(phy->IsStateSleep(),
209 true,
210 "PHY " << +phy->GetPhyId() << " is in unexpected state "
211 << phy->GetState()->GetState());
212 });
213 }
214}
215
216void
218 const EmlsrMainPhySwitchTrace& info)
219{
220 m_traceInfo[index] = info.Clone();
221}
222
223void
225 std::string_view reason,
226 const std::optional<uint8_t>& fromLinkId,
227 uint8_t toLinkId,
228 bool checkFromLinkId,
229 bool checkToLinkId)
230{
231 const auto traceInfoIt = m_traceInfo.find(index);
232 NS_TEST_ASSERT_MSG_EQ((traceInfoIt != m_traceInfo.cend()),
233 true,
234 "Expected stored trace info: " << reason);
235 const auto& traceInfo = traceInfoIt->second;
236
237 NS_TEST_EXPECT_MSG_EQ(traceInfo->GetName(), reason, "Unexpected reason");
238
239 if (checkFromLinkId)
240 {
241 NS_TEST_ASSERT_MSG_EQ(traceInfo->fromLinkId.has_value(),
242 fromLinkId.has_value(),
243 "Unexpected stored from_link ID");
244 if (fromLinkId.has_value())
245 {
246 NS_TEST_EXPECT_MSG_EQ(+traceInfo->fromLinkId.value(),
247 +fromLinkId.value(),
248 "Unexpected from_link ID");
249 }
250 }
251
252 if (checkToLinkId)
253 {
254 NS_TEST_EXPECT_MSG_EQ(+traceInfo->toLinkId, +toLinkId, "Unexpected to_link ID");
255 }
256
257 m_traceInfo.erase(traceInfoIt);
258}
259
260void
262{
265 int64_t streamNumber = m_streamNo;
266
267 Config::SetDefault("ns3::WifiMac::MpduBufferSize", UintegerValue(64));
268 Config::SetDefault("ns3::EmlsrManager::InDeviceInterference", BooleanValue(true));
269 Config::SetDefault("ns3::EmlsrManager::PutAuxPhyToSleep", BooleanValue(m_putAuxPhyToSleep));
270
271 NodeContainer wifiApNode(1);
272 NodeContainer wifiStaNodes(m_nEmlsrStations);
273
274 WifiHelper wifi;
275 // wifi.EnableLogComponents ();
276 wifi.SetStandard(WIFI_STANDARD_80211be);
277 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
278 "DataMode",
279 StringValue("EhtMcs0"),
280 "ControlMode",
281 StringValue("HtMcs0"));
282 wifi.ConfigEhtOptions("EmlsrActivated",
283 BooleanValue(true),
284 "TransitionTimeout",
286
287 // MLDs are configured with three links
288 SpectrumWifiPhyHelper phyHelper(3);
290 phyHelper.SetPcapCaptureType(WifiPhyHelper::PcapCaptureType::PCAP_PER_LINK);
291
292 for (std::size_t id = 0; id < m_channelsStr.size(); ++id)
293 {
294 phyHelper.Set(id, "ChannelSettings", StringValue(m_channelsStr[id]));
296 }
297
298 WifiMacHelper mac;
299 mac.SetType("ns3::ApWifiMac",
300 "Ssid",
301 SsidValue(Ssid("ns-3-ssid")),
302 "BeaconGeneration",
303 BooleanValue(true));
304 mac.SetApEmlsrManager("ns3::AdvancedApEmlsrManager",
305 "WaitTransDelayOnPsduRxError",
306 BooleanValue(true));
307
308 NetDeviceContainer apDevice = wifi.Install(phyHelper, mac, wifiApNode);
310
311 mac.SetType("ns3::StaWifiMac",
312 "Ssid",
313 SsidValue(Ssid("wrong-ssid")),
314 "MaxMissedBeacons",
315 UintegerValue(1e6), // do not deassociate
316 "ActiveProbing",
317 BooleanValue(false));
318 mac.SetEmlsrManager("ns3::AdvancedEmlsrManager",
319 "EmlsrLinkSet",
321 "MainPhyId",
323
324 if (m_nPhysPerEmlsrDevice < 3)
325 {
328 phyHelper.SetPcapCaptureType(WifiPhyHelper::PcapCaptureType::PCAP_PER_LINK);
329
330 for (std::size_t id = 0; id < m_nPhysPerEmlsrDevice; ++id)
331 {
332 phyHelper.Set(id, "ChannelSettings", StringValue(m_channelsStr[id]));
333 auto channel =
334 DynamicCast<MultiModelSpectrumChannel>(m_apMac->GetWifiPhy(id)->GetChannel());
335 NS_TEST_ASSERT_MSG_NE(channel,
336 nullptr,
337 "Channel " << +id << " is not a spectrum channel");
338 phyHelper.AddChannel(channel, m_freqRanges[id]);
339 }
340 }
341
342 NetDeviceContainer staDevices = wifi.Install(phyHelper, mac, wifiStaNodes);
343
344 for (uint32_t i = 0; i < staDevices.GetN(); i++)
345 {
346 auto device = DynamicCast<WifiNetDevice>(staDevices.Get(i));
347 auto staMac = DynamicCast<StaWifiMac>(device->GetMac());
348 auto emlsrManager = staMac->GetEmlsrManager();
349 NS_ASSERT_MSG(i < m_paddingDelay.size(), "Not enough padding delay values provided");
350 emlsrManager->SetAttribute("EmlsrPaddingDelay", TimeValue(m_paddingDelay.at(i)));
351 NS_ASSERT_MSG(i < m_transitionDelay.size(), "Not enough transition delay values provided");
352 emlsrManager->SetAttribute("EmlsrTransitionDelay", TimeValue(m_transitionDelay.at(i)));
353 emlsrManager->TraceConnectWithoutContext(
354 "MainPhySwitch",
356 }
357
358 if (m_nNonEmlsrStations > 0)
359 {
360 // create the other non-AP MLDs for which EMLSR is not activated
361 wifi.ConfigEhtOptions("EmlsrActivated", BooleanValue(false));
362 NodeContainer otherStaNodes(m_nNonEmlsrStations);
363 staDevices.Add(wifi.Install(phyHelper, mac, otherStaNodes));
364 wifiStaNodes.Add(otherStaNodes);
365 }
366
367 for (uint32_t i = 0; i < staDevices.GetN(); i++)
368 {
369 auto device = DynamicCast<WifiNetDevice>(staDevices.Get(i));
370 m_staMacs.push_back(DynamicCast<StaWifiMac>(device->GetMac()));
371 }
372
373 // Trace PSDUs passed to the PHY on AP MLD and non-AP MLDs
374 for (uint8_t phyId = 0; phyId < m_apMac->GetDevice()->GetNPhys(); phyId++)
375 {
377 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
378 "/PhyTxPsduBegin",
380 }
381 for (std::size_t i = 0; i < m_nEmlsrStations + m_nNonEmlsrStations; i++)
382 {
383 for (uint8_t phyId = 0; phyId < m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
384 {
386 "/NodeList/" + std::to_string(i + 1) + "/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
387 std::to_string(phyId) + "/PhyTxPsduBegin",
389 }
390 }
391
392 // Uncomment the lines below to write PCAP files
393 // phyHelper.EnablePcap("wifi-emlsr_AP", apDevice);
394 // phyHelper.EnablePcap("wifi-emlsr_STA", staDevices);
395
396 // Assign fixed streams to random variables in use
397 streamNumber += WifiHelper::AssignStreams(apDevice, streamNumber);
398 streamNumber += WifiHelper::AssignStreams(staDevices, streamNumber);
399
400 MobilityHelper mobility;
402
403 for (std::size_t id = 0; id <= m_nEmlsrStations + m_nNonEmlsrStations; id++)
404 {
405 // all non-AP MLDs are co-located
406 positionAlloc->Add(Vector(std::min<double>(id, 1), 0.0, 0.0));
407 }
408 mobility.SetPositionAllocator(positionAlloc);
409
410 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
411 mobility.Install(wifiApNode);
412 mobility.Install(wifiStaNodes);
413
414 // install packet socket on all nodes
415 PacketSocketHelper packetSocket;
416 packetSocket.Install(wifiApNode);
417 packetSocket.Install(wifiStaNodes);
418
419 // install a packet socket server on all nodes
420 for (auto nodeIt = NodeList::Begin(); nodeIt != NodeList::End(); nodeIt++)
421 {
422 PacketSocketAddress srvAddr;
423 auto device = DynamicCast<WifiNetDevice>((*nodeIt)->GetDevice(0));
424 NS_TEST_ASSERT_MSG_NE(device, nullptr, "Expected a WifiNetDevice");
425 srvAddr.SetSingleDevice(device->GetIfIndex());
426 srvAddr.SetProtocol(1);
427
428 auto server = CreateObject<PacketSocketServer>();
429 server->SetLocal(srvAddr);
430 (*nodeIt)->AddApplication(server);
431 server->SetStartTime(Seconds(0)); // now
432 server->SetStopTime(m_duration);
433 }
434
435 // set DL and UL packet sockets
436 for (const auto& staMac : m_staMacs)
437 {
438 m_dlSockets.emplace_back();
439 m_dlSockets.back().SetSingleDevice(m_apMac->GetDevice()->GetIfIndex());
440 m_dlSockets.back().SetPhysicalAddress(staMac->GetDevice()->GetAddress());
441 m_dlSockets.back().SetProtocol(1);
442
443 m_ulSockets.emplace_back();
444 m_ulSockets.back().SetSingleDevice(staMac->GetDevice()->GetIfIndex());
445 m_ulSockets.back().SetPhysicalAddress(m_apMac->GetDevice()->GetAddress());
446 m_ulSockets.back().SetProtocol(1);
447 }
448
449 m_startAid = m_apMac->GetNextAssociationId();
450
451 // schedule ML setup for one station at a time
452 m_apMac->TraceConnectWithoutContext(
453 "AssociatedSta",
455 for (const auto& [aci, ac] : wifiAcList)
456 {
457 m_apMac->GetQosTxop(aci)->TraceConnectWithoutContext(
458 "BaEstablished",
460 for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
461 {
462 m_staMacs[id]->GetQosTxop(aci)->TraceConnectWithoutContext(
463 "BaEstablished",
465 }
466 }
467 Simulator::Schedule(Seconds(0), [&]() { m_staMacs[0]->SetSsid(Ssid("ns-3-ssid")); });
468}
469
472 std::size_t staId,
473 std::size_t count,
474 std::size_t pktSize,
475 uint8_t priority) const
476{
477 auto client = CreateObject<PacketSocketClient>();
478 client->SetAttribute("PacketSize", UintegerValue(pktSize));
479 client->SetAttribute("MaxPackets", UintegerValue(count));
480 client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
481 client->SetAttribute("Priority", UintegerValue(priority));
482 client->SetRemote(dir == DOWNLINK ? m_dlSockets.at(staId) : m_ulSockets.at(staId));
483 client->SetStartTime(Seconds(0)); // now
484 client->SetStopTime(m_duration - Simulator::Now());
485
486 return client;
487}
488
489void
491{
492 if (m_lastAid == aid)
493 {
494 // another STA of this non-AP MLD has already fired this callback
495 return;
496 }
497 m_lastAid = aid;
498
499 // wait some time (10ms) to allow the completion of association
500 const auto delay = MilliSeconds(10);
501
502 if (!m_establishBaDl.empty())
503 {
504 // trigger establishment of BA agreement with AP as originator
505 Simulator::Schedule(delay, [=, this]() {
506 m_apMac->GetDevice()->GetNode()->AddApplication(
507 GetApplication(DOWNLINK, aid - m_startAid, 4, 1000, m_establishBaDl.front()));
508 });
509 }
510 else if (!m_establishBaUl.empty())
511 {
512 // trigger establishment of BA agreement with AP as recipient
513 Simulator::Schedule(delay, [=, this]() {
514 m_staMacs[aid - m_startAid]->GetDevice()->GetNode()->AddApplication(
515 GetApplication(UPLINK, aid - m_startAid, 4, 1000, m_establishBaUl.front()));
516 });
517 }
518 else
519 {
520 Simulator::Schedule(delay, [=, this]() { SetSsid(aid - m_startAid + 1); });
521 }
522}
523
524void
526 uint8_t tid,
527 std::optional<Mac48Address> /* gcrGroup */)
528{
529 // wait some time (10ms) to allow the exchange of the data frame that triggered the Block Ack
530 const auto delay = MilliSeconds(10);
531
532 auto linkId = m_apMac->IsAssociated(recipient);
533 NS_TEST_ASSERT_MSG_EQ(linkId.has_value(), true, "No link for association of " << recipient);
534 auto aid = m_apMac->GetWifiRemoteStationManager(*linkId)->GetAssociationId(recipient);
535
536 if (auto it = std::find(m_establishBaDl.cbegin(), m_establishBaDl.cend(), tid);
537 it != m_establishBaDl.cend() && std::next(it) != m_establishBaDl.cend())
538 {
539 // trigger establishment of BA agreement with AP as originator
540 Simulator::Schedule(delay, [=, this]() {
541 m_apMac->GetDevice()->GetNode()->AddApplication(
542 GetApplication(DOWNLINK, aid - m_startAid, 4, 1000, *std::next(it)));
543 });
544 }
545 else if (!m_establishBaUl.empty())
546 {
547 // trigger establishment of BA agreement with AP as recipient
548 Simulator::Schedule(delay, [=, this]() {
549 m_staMacs[aid - m_startAid]->GetDevice()->GetNode()->AddApplication(
550 GetApplication(UPLINK, aid - m_startAid, 4, 1000, m_establishBaUl.front()));
551 });
552 }
553 else
554 {
555 Simulator::Schedule(delay, [=, this]() { SetSsid(aid - m_startAid + 1); });
556 }
557}
558
559void
561 Mac48Address recipient,
562 uint8_t tid,
563 std::optional<Mac48Address> /* gcrGroup */)
564{
565 // wait some time (10ms) to allow the exchange of the data frame that triggered the Block Ack
566 const auto delay = MilliSeconds(10);
567
568 if (auto it = std::find(m_establishBaUl.cbegin(), m_establishBaUl.cend(), tid);
569 it != m_establishBaUl.cend() && std::next(it) != m_establishBaUl.cend())
570 {
571 // trigger establishment of BA agreement with AP as recipient
572 Simulator::Schedule(delay, [=, this]() {
573 m_staMacs[index]->GetDevice()->GetNode()->AddApplication(
574 GetApplication(UPLINK, index, 4, 1000, *std::next(it)));
575 });
576 }
577 else
578 {
579 Simulator::Schedule(delay, [=, this]() { SetSsid(index + 1); });
580 }
581}
582
583void
585{
587 {
588 // make the next STA start ML discovery & setup
589 m_staMacs[count]->SetSsid(Ssid("ns-3-ssid"));
590 return;
591 }
592 // all stations associated; start traffic if needed
593 StartTraffic();
594 // stop generation of beacon frames in order to avoid interference
595 m_apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
596 // Set the short slot time on the 2.4 GHz link because it is not updated automatically given
597 // that no more Beacon frames are sent
598 for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
599 {
600 m_staMacs[id]->GetDevice()->GetPhy(0)->SetSlot(MicroSeconds(9));
601 }
602 // disconnect callbacks
603 m_apMac->TraceDisconnectWithoutContext(
604 "AssociatedSta",
606 for (const auto& [aci, ac] : wifiAcList)
607 {
608 m_apMac->GetQosTxop(aci)->TraceDisconnectWithoutContext(
609 "BaEstablished",
611 for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
612 {
613 m_staMacs[id]->GetQosTxop(aci)->TraceDisconnectWithoutContext(
614 "BaEstablished",
616 }
617 }
618}
619
620void
622 Mac48Address dest,
623 uint8_t linkId,
625 bool blocked,
626 std::string description,
627 bool testUnblockedForOtherReasons)
628{
630 auto mask = mac->GetMacQueueScheduler()->GetQueueLinkMask(AC_BE, queueId, linkId);
631 NS_TEST_EXPECT_MSG_EQ(mask.has_value(),
632 true,
633 description << ": Expected to find a mask for EMLSR link " << +linkId);
634 if (blocked)
635 {
636 NS_TEST_EXPECT_MSG_EQ(mask->test(static_cast<std::size_t>(reason)),
637 true,
638 description << ": Expected EMLSR link " << +linkId
639 << " to be blocked for reason " << reason);
640 if (testUnblockedForOtherReasons)
641 {
642 NS_TEST_EXPECT_MSG_EQ(mask->count(),
643 1,
644 description << ": Expected EMLSR link " << +linkId
645 << " to be blocked for one reason only");
646 }
647 }
648 else if (testUnblockedForOtherReasons)
649 {
650 NS_TEST_EXPECT_MSG_EQ(mask->none(),
651 true,
652 description << ": Expected EMLSR link " << +linkId
653 << " to be unblocked");
654 }
655 else
656 {
657 NS_TEST_EXPECT_MSG_EQ(mask->test(static_cast<std::size_t>(reason)),
658 false,
659 description << ": Expected EMLSR link " << +linkId
660 << " to be unblocked for reason " << reason);
661 }
662}
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
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
const Time MEDIUM_SYNC_THRESHOLD
The aMediumSyncThreshold defined by Sec. 35.3.16.18.1 of 802.11be D4.0.
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)