A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-mlo-udp-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 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
9#include "wifi-mlo-test.h"
10
11#include "ns3/arp-header.h"
12#include "ns3/arp-l3-protocol.h"
13#include "ns3/config.h"
14#include "ns3/frame-exchange-manager.h"
15#include "ns3/icmpv6-header.h"
16#include "ns3/internet-stack-helper.h"
17#include "ns3/ipv4-address-helper.h"
18#include "ns3/ipv6-address-helper.h"
19#include "ns3/ipv6-header.h"
20#include "ns3/ipv6-l3-protocol.h"
21#include "ns3/llc-snap-header.h"
22#include "ns3/mobility-helper.h"
23#include "ns3/pointer.h"
24#include "ns3/qos-txop.h"
25#include "ns3/rng-seed-manager.h"
26#include "ns3/ssid.h"
27#include "ns3/string.h"
28#include "ns3/test.h"
29#include "ns3/udp-client-server-helper.h"
30#include "ns3/wifi-mac-queue.h"
31#include "ns3/wifi-mac.h"
32#include "ns3/wifi-net-device.h"
33
34#include <array>
35#include <list>
36
37using namespace ns3;
38
39NS_LOG_COMPONENT_DEFINE("WifiMloUdpTest");
40
41/**
42 * @ingroup wifi-test
43 * @ingroup tests
44 *
45 * @brief Test UDP packet transmission between MLDs and SLDs.
46 *
47 * This test sets up an AP MLD and two non-AP MLDs having a variable number of links (possibly one).
48 * The RF channels to set each link to are provided as input parameters. This test aims at verifying
49 * the successful transmission and reception of UDP packets in different traffic scenarios (from
50 * the first station to the AP, from the AP to the first station, from one station to another).
51 * The number of transmitted ARP Request/Reply frames for IPv4 traffic and Neighbor
52 * Solicitation/Advertisement frames for IPv6 traffic is verified, as well as the link-layer
53 * address they carry. Specifically:
54 *
55 * STA to AP
56 * ---------
57 * The source HW address of the ARP Request sent by the STA is:
58 * - the address of the link used to associate, if STA performs legacy association or AP is an SLD
59 * - the non-AP MLD address (or the unique STA address), otherwise
60 * The source HW address of the ARP Reply sent by the AP is the address of the link used by STA to
61 * associate, if the STA performed legacy association, or the AP MLD address, otherwise.
62 *
63 * AP to STA
64 * ---------
65 * The source HW address of the ARP Request sent by the AP is:
66 * - the unique AP address, if the AP is an SLD
67 * - the AP MLD address, if the AP is an MLD
68 * The source HW address of the ARP Reply sent by the STA is the address of the link used by STA to
69 * associate, if the STA performed legacy association, or the non-AP MLD address, otherwise.
70 *
71 * STA 1 to STA 2
72 * --------------
73 * The source HW address of the ARP Request sent by STA 1 is:
74 * - the address of the link used to associate, if STA performs legacy association or AP is an SLD
75 * - the non-AP MLD address (or the unique STA address), otherwise
76 * The source HW address of the ARP Reply sent by STA 2 is the address of the link used by STA 2 to
77 * associate, if STA 2 performed legacy association, or the non-AP MLD address of STA 2, otherwise.
78 */
80{
81 public:
82 /// Input parameters
84 {
85 std::size_t id; ///< input ID
86 std::vector<std::string> apChannels; ///< string specifying channels for AP
87 std::vector<std::string> firstStaChannels; ///< string specifying channels for first STA
88 std::vector<std::string> secondStaChannels; ///< string specifying channels for second STA
89 WifiTrafficPattern trafficPattern; ///< the pattern of traffic to generate
90 WifiAssocType assocType; ///< type of association procedure
91 bool amsduAggr; ///< whether A-MSDU aggregation is enabled
92 uint8_t ipVersion; ///< IP version to use, either 4 or 6
93 };
94
95 /**
96 * Constructor
97 *
98 * @param params the input parameters
99 */
100 WifiMloUdpTest(const InputParams& params);
101
102 protected:
103 void DoSetup() override;
104 void Transmit(Ptr<WifiMac> mac,
105 uint8_t phyId,
106 WifiConstPsduMap psduMap,
107 WifiTxVector txVector,
108 double txPowerW) override;
109 void DoRun() override;
110
111 /**
112 * Check source and destination hardware addresses in ARP request frames.
113 *
114 * @param arp the ARP header
115 * @param sender the MAC address of the sender (Address 2 field)
116 * @param linkId the ID of the link on which the ARP frame is transmitted
117 */
118 void CheckArpRequestHwAddresses(const ArpHeader& arp, Mac48Address sender, uint8_t linkId);
119
120 /**
121 * Check source and destination hardware addresses in ARP reply frames.
122 *
123 * @param arp the ARP header
124 * @param sender the MAC address of the sender (Address 2 field)
125 * @param linkId the ID of the link on which the ARP frame is transmitted
126 */
127 void CheckArpReplyHwAddresses(const ArpHeader& arp, Mac48Address sender, uint8_t linkId);
128
129 /**
130 * Check source link-layer address in Neighbor Solicitation frames.
131 *
132 * @param sourceLinkLayerAddress the source link-layer address option
133 * @param sender the MAC address of the sender (Address 2 field)
134 * @param linkId the ID of the link on which the Neighbor Solicitation frame is transmitted
135 */
136 void CheckNsHwAddress(Address sourceLinkLayerAddress, Mac48Address sender, uint8_t linkId);
137
138 /**
139 * Check target link-layer address in Neighbor Advertisement frames.
140 *
141 * @param targetLinkLayerAddress the target link-layer address option
142 * @param sender the MAC address of the sender (Address 2 field)
143 * @param linkId the ID of the link on which the Neighbor Advertisement frame is transmitted
144 */
145 void CheckNaHwAddress(Address targetLinkLayerAddress, Mac48Address sender, uint8_t linkId);
146
147 private:
148 void StartTraffic() override;
149
150 const std::vector<std::string> m_2ndStaChannels; ///< string specifying channels for second STA
151 WifiTrafficPattern m_trafficPattern; ///< the pattern of traffic to generate
152 WifiAssocType m_assocType; //!< association type
153 bool m_amsduAggr; ///< whether A-MSDU aggregation is enabled
154 uint8_t m_ipVersion; ///< IP version to use, either 4 or 6
155 const std::size_t m_nPackets{3}; ///< number of application packets to generate
156 Ipv4InterfaceContainer m_staInterfaces; ///< IPv4 interfaces for non-AP MLDs
157 Ipv4InterfaceContainer m_apInterface; ///< IPv4 interface for AP MLD
158 Ipv6InterfaceContainer m_staInterfaces6; ///< IPv6 interfaces for non-AP MLDs
159 Ipv6InterfaceContainer m_apInterface6; ///< IPv6 interface for AP MLD
160 const uint16_t m_udpPort{50000}; ///< UDP port for application servers
161 Ptr<UdpServer> m_sink; ///< server app on the receiving node
162 std::size_t m_nArpRequest{0}; ///< counts how many ARP Requests are transmitted
163 std::size_t m_nCheckedArpRequest{0}; ///< counts how many ARP Requests are checked
164 std::size_t m_nArpReply{0}; ///< counts how many ARP Replies are transmitted
165 std::size_t m_nCheckedArpReply{0}; ///< counts how many ARP Replies are checked
166 std::size_t m_nNs{0}; ///< counts how many Neighbor Solicitations are transmitted
167 std::size_t m_nCheckedNs{0}; ///< counts how many Neighbor Solicitations are checked
168 std::size_t m_nNa{0}; ///< counts how many Neighbor Advertisements are sent
169 std::size_t m_nCheckedNa{0}; ///< counts how many Neighbor Advertisements are checked
170};
171
174 std::string("Check UDP packet transmission between MLDs ") +
175 " (ID: " + std::to_string(params.id) +
176 ", #AP_links: " + std::to_string(params.apChannels.size()) +
177 ", #STA_1_links: " + std::to_string(params.firstStaChannels.size()) +
178 ", #STA_2_links: " + std::to_string(params.secondStaChannels.size()) +
179 ", Traffic pattern: " + std::to_string(static_cast<uint8_t>(params.trafficPattern)) +
180 ", Assoc type: " +
181 (params.assocType == WifiAssocType::LEGACY ? "Legacy" : "ML setup") +
182 ", A-MSDU aggregation: " + std::to_string(params.amsduAggr) +
183 ", IP version: " + std::to_string(params.ipVersion) + ")",
184 2,
185 BaseParams{params.firstStaChannels, params.apChannels, {}}),
186 m_2ndStaChannels(params.secondStaChannels),
187 m_trafficPattern(params.trafficPattern),
188 m_assocType(params.assocType),
189 m_amsduAggr(params.amsduAggr),
190 m_ipVersion(params.ipVersion)
191{
192 NS_ABORT_MSG_IF(m_ipVersion != 4 && m_ipVersion != 6,
193 "Unsupported IP version " << +m_ipVersion);
194}
195
196void
198{
199 Config::SetDefault("ns3::WifiMac::BE_MaxAmsduSize", UintegerValue(m_amsduAggr ? 4000 : 0));
200
203 int64_t streamNumber = 30;
204
205 NodeContainer wifiApNode(1);
206 NodeContainer wifiStaNodes(2);
207
208 WifiHelper wifi;
209 // WifiHelper::EnableLogComponents();
210 wifi.SetStandard(WIFI_STANDARD_80211be);
211 wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager",
212 "DataMode",
213 StringValue("EhtMcs0"),
214 "ControlMode",
215 StringValue("HtMcs0"));
216
220
221 SpectrumWifiPhyHelper staPhyHelper1;
222 SpectrumWifiPhyHelper staPhyHelper2;
223 SpectrumWifiPhyHelper apPhyHelper;
224 SetChannels(staPhyHelper1, m_staChannels, channelMap);
225 SetChannels(staPhyHelper2, m_2ndStaChannels, channelMap);
226 SetChannels(apPhyHelper, m_apChannels, channelMap);
227
228 WifiMacHelper mac;
229 mac.SetType("ns3::StaWifiMac", // default SSID
230 "ActiveProbing",
231 BooleanValue(false),
232 "AssocType",
234
235 NetDeviceContainer staDevices = wifi.Install(staPhyHelper1, mac, wifiStaNodes.Get(0));
236
237 mac.SetType("ns3::StaWifiMac", // default SSID
238 "ActiveProbing",
239 BooleanValue(false),
240 "AssocType",
242
243 staDevices.Add(wifi.Install(staPhyHelper2, mac, wifiStaNodes.Get(1)));
244
245 mac.SetType("ns3::ApWifiMac",
246 "Ssid",
247 SsidValue(Ssid("ns-3-ssid")),
248 "BeaconGeneration",
249 BooleanValue(true));
250
251 NetDeviceContainer apDevices = wifi.Install(apPhyHelper, mac, wifiApNode);
252
253 // Uncomment the lines below to write PCAP files
254 // apPhyHelper.EnablePcap("wifi-mlo_AP", apDevices);
255 // staPhyHelper1.EnablePcap("wifi-mlo_STA", staDevices);
256
257 // Assign fixed streams to random variables in use
258 streamNumber += WifiHelper::AssignStreams(apDevices, streamNumber);
259 streamNumber += WifiHelper::AssignStreams(staDevices, streamNumber);
260
261 MobilityHelper mobility;
263
264 positionAlloc->Add(Vector(0.0, 0.0, 0.0));
265 positionAlloc->Add(Vector(1.0, 0.0, 0.0));
266 mobility.SetPositionAllocator(positionAlloc);
267
268 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
269 mobility.Install(wifiApNode);
270 mobility.Install(wifiStaNodes);
271
272 m_apMac = DynamicCast<ApWifiMac>(DynamicCast<WifiNetDevice>(apDevices.Get(0))->GetMac());
273 for (uint8_t i = 0; i < m_nStations; i++)
274 {
275 m_staMacs[i] =
276 DynamicCast<StaWifiMac>(DynamicCast<WifiNetDevice>(staDevices.Get(i))->GetMac());
277 }
278
279 // Trace PSDUs passed to the PHY on all devices
280 for (uint8_t phyId = 0; phyId < m_apMac->GetDevice()->GetNPhys(); phyId++)
281 {
283 "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) +
284 "/PhyTxPsduBegin",
285 MakeCallback(&WifiMloUdpTest::Transmit, this).Bind(m_apMac, phyId));
286 }
287 for (uint8_t i = 0; i < m_nStations; i++)
288 {
289 for (uint8_t phyId = 0; phyId < m_staMacs[i]->GetDevice()->GetNPhys(); phyId++)
290 {
292 "/NodeList/" + std::to_string(i + 1) + "/DeviceList/*/$ns3::WifiNetDevice/Phys/" +
293 std::to_string(phyId) + "/PhyTxPsduBegin",
294 MakeCallback(&WifiMloUdpTest::Transmit, this).Bind(m_staMacs[i], phyId));
295 }
296 }
297
298 // install Internet stack on all nodes
300 auto allNodes = NodeContainer::GetGlobal();
301 stack.Install(allNodes);
302 streamNumber += stack.AssignStreams(allNodes, streamNumber);
303
304 if (m_ipVersion == 4)
305 {
306 Ipv4AddressHelper address;
307 address.SetBase("10.1.0.0", "255.255.255.0");
308 m_apInterface = address.Assign(NetDeviceContainer(m_apMac->GetDevice()));
309 for (std::size_t i = 0; i < m_nStations; i++)
310 {
311 m_staInterfaces.Add(address.Assign(NetDeviceContainer(m_staMacs[i]->GetDevice())));
312 }
313 }
314 else
315 {
316 Ipv6AddressHelper address;
317 address.SetBase(Ipv6Address("2001:1::"), Ipv6Prefix(64));
318 m_apInterface6 = address.Assign(NetDeviceContainer(m_apMac->GetDevice()));
319 for (std::size_t i = 0; i < m_nStations; i++)
320 {
321 m_staInterfaces6.Add(address.Assign(NetDeviceContainer(m_staMacs[i]->GetDevice())));
322 }
323 }
324
325 // install a UDP server on all nodes
326 UdpServerHelper serverHelper(m_udpPort);
327 auto serverApps = serverHelper.Install(allNodes);
328 serverApps.Start(Seconds(0.0));
329 serverApps.Stop(m_duration);
330
331 switch (m_trafficPattern)
332 {
334 m_sink = DynamicCast<UdpServer>(serverApps.Get(0));
335 break;
337 m_sink = DynamicCast<UdpServer>(serverApps.Get(1));
338 break;
340 m_sink = DynamicCast<UdpServer>(serverApps.Get(2));
341 break;
342 default:
343 m_sink = nullptr; // other cases are not supported
344 }
345
346 m_startAid = m_apMac->GetNextAssociationId();
347
348 // schedule association/ML setup for one station at a time
349 m_apMac->TraceConnectWithoutContext("AssociatedSta",
351 m_staMacs[0]->SetSsid(Ssid("ns-3-ssid"));
352}
353
354void
356{
357 Ptr<WifiMac> srcMac;
358 Address destAddr;
359
360 switch (m_trafficPattern)
361 {
363 srcMac = m_staMacs[0];
364 destAddr = (m_ipVersion == 4 ? Address(m_apInterface.GetAddress(0))
365 : Address(m_apInterface6.GetAddress(0, 1)));
366 break;
368 srcMac = m_apMac;
369 destAddr = (m_ipVersion == 4 ? Address(m_staInterfaces.GetAddress(0))
370 : Address(m_staInterfaces6.GetAddress(0, 1)));
371 break;
373 srcMac = m_staMacs[0];
374 destAddr = (m_ipVersion == 4 ? Address(m_staInterfaces.GetAddress(1))
375 : Address(m_staInterfaces6.GetAddress(1, 1)));
376 break;
377 default:
378 NS_ABORT_MSG("Unsupported scenario " << +static_cast<uint8_t>(m_trafficPattern));
379 }
380
381 UdpClientHelper clientHelper(destAddr, m_udpPort);
382 clientHelper.SetAttribute("MaxPackets", UintegerValue(m_nPackets));
383 clientHelper.SetAttribute("Interval", TimeValue(Time{0}));
384 clientHelper.SetAttribute("PacketSize", UintegerValue(100));
385 auto clientApp = clientHelper.Install(srcMac->GetDevice()->GetNode());
386 clientApp.Start(Seconds(0.0));
387 clientApp.Stop(m_duration);
388}
389
390void
392 uint8_t phyId,
393 WifiConstPsduMap psduMap,
394 WifiTxVector txVector,
395 double txPowerW)
396{
397 MultiLinkOperationsTestBase::Transmit(mac, phyId, psduMap, txVector, txPowerW);
398
399 auto psdu = psduMap.begin()->second;
400 auto linkId = m_txPsdus.back().linkId;
401
402 if (!psdu->GetHeader(0).IsQosData() || !psdu->GetHeader(0).HasData())
403 {
404 // we are interested in address resolution frames, which are carried by QoS data frames
405 return;
406 }
407
408 for (const auto& mpdu : *PeekPointer(psdu))
409 {
410 std::list<Ptr<const Packet>> packets;
411
412 if (mpdu->GetHeader().IsQosAmsdu())
413 {
414 for (const auto& msdu : *PeekPointer(mpdu))
415 {
416 packets.push_back(msdu.first);
417 }
418 }
419 else
420 {
421 packets.push_back(mpdu->GetPacket());
422 }
423
424 for (auto pkt : packets)
425 {
426 LlcSnapHeader llc;
427 auto packet = pkt->Copy();
428 packet->RemoveHeader(llc);
429
431 {
432 ArpHeader arp;
433 packet->RemoveHeader(arp);
434
435 if (arp.IsRequest())
436 {
437 CheckArpRequestHwAddresses(arp, psdu->GetAddr2(), linkId);
438 }
439 if (arp.IsReply())
440 {
441 CheckArpReplyHwAddresses(arp, psdu->GetAddr2(), linkId);
442 }
443 continue;
444 }
445
447 {
448 continue;
449 }
450
451 Ipv6Header ipv6;
452 packet->RemoveHeader(ipv6);
453
454 if (ipv6.GetNextHeader() != Ipv6Header::IPV6_ICMPV6 || ipv6.GetSource().IsAny())
455 {
456 continue;
457 }
458
459 Icmpv6Header icmpv6;
460 packet->PeekHeader(icmpv6);
461
463 {
464 Icmpv6NS ns;
465 packet->RemoveHeader(ns);
466
467 NS_TEST_ASSERT_MSG_NE(packet->GetSize(), 0, "Missing Neighbor Solicitation option");
468
469 uint8_t type;
470 packet->CopyData(&type, sizeof(type));
473 "Unexpected Neighbor Solicitation option");
474
476 packet->RemoveHeader(lla);
477 CheckNsHwAddress(lla.GetAddress(), psdu->GetAddr2(), linkId);
478 }
480 {
481 Icmpv6NA na;
482 packet->RemoveHeader(na);
483
484 NS_TEST_ASSERT_MSG_NE(packet->GetSize(),
485 0,
486 "Missing Neighbor Advertisement option");
487
488 uint8_t type;
489 packet->CopyData(&type, sizeof(type));
492 "Unexpected Neighbor Advertisement option");
493
495 packet->RemoveHeader(lla);
496 CheckNaHwAddress(lla.GetAddress(), psdu->GetAddr2(), linkId);
497 }
498 }
499 }
500}
501
502void
504 Mac48Address sender,
505 uint8_t linkId)
506{
508
509 // source and destination HW addresses cannot be checked for forwarded frames because
510 // they can be forwarded on different links
511 if (auto srcMac =
514 !srcMac->GetLinkIdByAddress(sender) && sender != srcMac->GetAddress())
515 {
516 // the sender address is not the MLD address nor a link address of the source device
517 return;
518 }
519
520 Mac48Address expectedSrc;
521
522 switch (m_trafficPattern)
523 {
526 // if the ARP Request is sent by a STA, the source HW address is:
527 // - the address of the link used to associate, if the STA performs legacy association or
528 // the AP is an SLD
529 // - the non-AP MLD address (or the unique STA address), otherwise
530 expectedSrc = (m_assocType == WifiAssocType::LEGACY || m_apMac->GetNLinks() == 1)
531 ? m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress()
532 : m_staMacs[0]->GetAddress();
533 break;
535 // if the ARP Request is sent by an AP, the source HW address is:
536 // - the unique AP address, if the AP is an SLD
537 // - the AP MLD address, if the AP is an MLD
538 expectedSrc = m_apMac->GetAddress();
539 break;
540 default:
541 NS_ABORT_MSG("Unsupported scenario " << +static_cast<uint8_t>(m_trafficPattern));
542 }
543
545
547 expectedSrc,
548 "Unexpected source HW address");
551 "Unexpected destination HW address");
552}
553
554void
556{
557 ++m_nArpReply;
558
559 // source and destination HW addresses cannot be checked for forwarded frames because
560 // they can be forwarded on different links
561 auto srcMac =
565
566 if (!srcMac->GetLinkIdByAddress(sender) && sender != srcMac->GetAddress())
567 {
568 // the sender address is not the MLD address nor a link address of the source device
569 return;
570 }
571
572 // the source HW address of the ARP Reply is the address of the link on which the ARP Reply is
573 // sent, if the sender performed legacy association, or the MLD address, otherwise
574 Mac48Address expectedSrc = (m_assocType == WifiAssocType::LEGACY || m_apMac->GetNLinks() == 1)
575 ? srcMac->GetFrameExchangeManager(linkId)->GetAddress()
576 : srcMac->GetAddress();
577
579
581 expectedSrc,
582 "Unexpected source HW address");
583}
584
585void
587 Mac48Address sender,
588 uint8_t linkId)
589{
590 ++m_nNs;
591
592 // source link-layer address cannot be checked for forwarded frames because
593 // they can be forwarded on different links
594 if (auto srcMac =
597 !srcMac->GetLinkIdByAddress(sender) && sender != srcMac->GetAddress())
598 {
599 // the sender address is not the MLD address nor a link address of the source device
600 return;
601 }
602
603 Mac48Address expectedSrc;
604
605 switch (m_trafficPattern)
606 {
609 // Neighbor Solicitations are forged with the MAC address advertised by the NetDevice to
610 // IPv6.
611 expectedSrc = (m_assocType == WifiAssocType::LEGACY || m_apMac->GetNLinks() == 1)
612 ? m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress()
613 : m_staMacs[0]->GetAddress();
614 break;
616 // Neighbor Solicitations are forged with the MAC address advertised by the NetDevice to
617 // IPv6.
618 expectedSrc = m_apMac->GetAddress();
619 break;
620 default:
621 NS_ABORT_MSG("Unsupported scenario " << +static_cast<uint8_t>(m_trafficPattern));
622 }
623
624 ++m_nCheckedNs;
625
626 NS_TEST_EXPECT_MSG_EQ(Mac48Address::ConvertFrom(sourceLinkLayerAddress),
627 expectedSrc,
628 "Unexpected source link-layer address");
629}
630
631void
633 Mac48Address sender,
634 uint8_t linkId)
635{
636 ++m_nNa;
637
638 // target link-layer address cannot be checked for forwarded frames because
639 // they can be forwarded on different links
640 auto srcMac =
644
645 if (!srcMac->GetLinkIdByAddress(sender) && sender != srcMac->GetAddress())
646 {
647 // the sender address is not the MLD address nor a link address of the source device
648 return;
649 }
650
651 // the target link-layer address of the Neighbor Advertisement is the address of the link on
652 // which the Neighbor Advertisement is sent, if the sender performed legacy association, or the
653 // MLD address, otherwise
654 Mac48Address expectedTarget =
655 (m_assocType == WifiAssocType::LEGACY || m_apMac->GetNLinks() == 1)
656 ? srcMac->GetFrameExchangeManager(linkId)->GetAddress()
657 : srcMac->GetAddress();
658
659 ++m_nCheckedNa;
660
661 NS_TEST_EXPECT_MSG_EQ(Mac48Address::ConvertFrom(targetLinkLayerAddress),
662 expectedTarget,
663 "Unexpected target link-layer address");
664}
665
666void
668{
671
672 NS_TEST_ASSERT_MSG_NE(m_sink, nullptr, "Sink is not set");
673 NS_TEST_EXPECT_MSG_EQ(m_sink->GetReceived(),
675 "Unexpected number of received packets");
676
677 std::size_t expectedNOrigRequest{0};
678 std::size_t expectedNFwdRequest{0};
679
680 switch (m_trafficPattern)
681 {
684 // STA transmits one request, AP retransmits it on all of its links
685 expectedNOrigRequest = 1;
686 expectedNFwdRequest = m_apMac->GetNLinks();
687 break;
689 // AP transmits the request on all of its links
690 expectedNOrigRequest = m_apMac->GetNLinks();
691 expectedNFwdRequest = 0;
692 break;
693 default:
694 NS_ABORT_MSG("Unsupported scenario " << +static_cast<uint8_t>(m_trafficPattern));
695 }
696
697 std::size_t expectedNOrigReply{0};
698 std::size_t expectedNFwdReply{0};
699
700 switch (m_trafficPattern)
701 {
703 // STA transmits only one request, AP replies with one unicast reply
704 expectedNOrigReply = 1;
705 expectedNFwdReply = 0;
706 break;
708 // the request is broadcast/multicast, so it is sent by the AP on all of its links; the STA
709 // sends a reply for each setup link
710 expectedNOrigReply =
711 std::min<std::size_t>(m_apMac->GetNLinks(), m_staMacs[0]->GetSetupLinkIds().size());
712 expectedNFwdReply = 0;
713 break;
715 // AP forwards the request on all of its links; STA 2 sends as many replies as the number
716 // of setup links; each such reply is forwarded by the AP to STA 1
717 expectedNOrigReply = expectedNFwdReply = m_staMacs[1]->GetSetupLinkIds().size();
718 break;
719 default:
720 NS_ABORT_MSG("Unsupported scenario " << +static_cast<uint8_t>(m_trafficPattern));
721 }
722
723 if (m_ipVersion == 4)
724 {
726 expectedNOrigRequest + expectedNFwdRequest,
727 "Unexpected number of transmitted ARP Request frames");
729 expectedNOrigRequest,
730 "Unexpected number of checked ARP Request frames");
732 expectedNOrigReply + expectedNFwdReply,
733 "Unexpected number of transmitted ARP Reply frames");
735 expectedNOrigReply,
736 "Unexpected number of checked ARP Reply frames");
737 }
738 else
739 {
741 expectedNOrigRequest + expectedNFwdRequest,
742 "Unexpected number of transmitted Neighbor Solicitation frames");
744 expectedNOrigRequest,
745 "Unexpected number of checked Neighbor Solicitation frames");
747 expectedNOrigReply + expectedNFwdReply,
748 "Unexpected number of transmitted Neighbor Advertisement frames");
750 expectedNOrigReply,
751 "Unexpected number of checked Neighbor Advertisement frames");
752 }
753
755}
756
757/**
758 * @ingroup wifi-test
759 * @ingroup tests
760 *
761 * @brief Multi-Link Operations with UDP traffic Test Suite
762 */
764{
765 public:
767};
768
770 : TestSuite("wifi-mlo-udp", Type::SYSTEM)
771{
772 std::size_t inputId{};
773 std::vector<WifiMloUdpTest::InputParams> testVectors;
774 using ParamsTuple = std::array<std::vector<std::string>, 3>; // AP, STA 1, STA 2 channels
775
776 for (const auto& channels :
777 {// single link AP, non-AP MLD with 3 links, single link non-AP STA
778 ParamsTuple{
779 {{"{3, 40, BAND_6GHZ, 0}"},
780 {"{46, 40, BAND_5GHZ, 1}", "{5, 40, BAND_2_4GHZ, 0}", "{3, 40, BAND_6GHZ, 0}"},
781 {"{3, 40, BAND_6GHZ, 0}"}}},
782 // single link AP, non-AP MLD with 3 links, non-AP MLD with 2 links
783 ParamsTuple{
784 {{"{3, 40, BAND_6GHZ, 0}"},
785 {"{46, 40, BAND_5GHZ, 1}", "{5, 40, BAND_2_4GHZ, 0}", "{3, 40, BAND_6GHZ, 0}"},
786 {"{46, 40, BAND_5GHZ, 1}", "{3, 40, BAND_6GHZ, 0}"}}},
787 // AP MLD with 3 links, single link non-AP STA, non-AP MLD with 2 links
788 ParamsTuple{
789 {{"{46, 40, BAND_5GHZ, 1}", "{5, 40, BAND_2_4GHZ, 0}", "{3, 40, BAND_6GHZ, 0}"},
790 {"{3, 40, BAND_6GHZ, 0}"},
791 {"{46, 40, BAND_5GHZ, 1}", "{5, 40, BAND_2_4GHZ, 0}"}}},
792 // AP MLD with 3 links, non-AP MLD with 3 links, non-AP MLD with 2 links
793 ParamsTuple{
794 {{"{46, 40, BAND_5GHZ, 1}", "{3, 40, BAND_6GHZ, 0}", "{5, 40, BAND_2_4GHZ, 0}"},
795 {"{46, 40, BAND_5GHZ, 1}", "{3, 40, BAND_6GHZ, 0}", "{5, 40, BAND_2_4GHZ, 0}"},
796 {"{3, 40, BAND_6GHZ, 0}", "{5, 40, BAND_2_4GHZ, 0}"}}}})
797 {
798 for (const auto& trafficPattern : {WifiTrafficPattern::STA_TO_AP,
801 {
802 for (const auto amsduAggr : {false, true})
803 {
804 for (const auto assocType : {WifiAssocType::LEGACY, WifiAssocType::ML_SETUP})
805 {
806 for (const uint8_t ipVersion : {4, 6})
807 {
808 testVectors.emplace_back(
809 WifiMloUdpTest::InputParams{.id = inputId++,
810 .apChannels = channels[0],
811 .firstStaChannels = channels[1],
812 .secondStaChannels = channels[2],
813 .trafficPattern = trafficPattern,
814 .assocType = assocType,
815 .amsduAggr = amsduAggr,
816 .ipVersion = ipVersion});
817 }
818 }
819 }
820 }
821 }
822
823 for (const auto& testVector : testVectors)
824 {
826 }
827}
828
Test UDP packet transmission between MLDs and SLDs.
Ipv6InterfaceContainer m_staInterfaces6
IPv6 interfaces for non-AP MLDs.
uint8_t m_ipVersion
IP version to use, either 4 or 6.
Ipv6InterfaceContainer m_apInterface6
IPv6 interface for AP MLD.
WifiMloUdpTest(const InputParams &params)
Constructor.
const uint16_t m_udpPort
UDP port for application servers.
WifiAssocType m_assocType
association type
std::size_t m_nNa
counts how many Neighbor Advertisements are sent
void CheckArpRequestHwAddresses(const ArpHeader &arp, Mac48Address sender, uint8_t linkId)
Check source and destination hardware addresses in ARP request frames.
std::size_t m_nArpRequest
counts how many ARP Requests are transmitted
WifiTrafficPattern m_trafficPattern
the pattern of traffic to generate
std::size_t m_nCheckedNs
counts how many Neighbor Solicitations are checked
void CheckArpReplyHwAddresses(const ArpHeader &arp, Mac48Address sender, uint8_t linkId)
Check source and destination hardware addresses in ARP reply frames.
std::size_t m_nCheckedNa
counts how many Neighbor Advertisements are checked
void CheckNaHwAddress(Address targetLinkLayerAddress, Mac48Address sender, uint8_t linkId)
Check target link-layer address in Neighbor Advertisement frames.
std::size_t m_nCheckedArpReply
counts how many ARP Replies are checked
void CheckNsHwAddress(Address sourceLinkLayerAddress, Mac48Address sender, uint8_t linkId)
Check source link-layer address in Neighbor Solicitation frames.
const std::vector< std::string > m_2ndStaChannels
string specifying channels for second STA
Ipv4InterfaceContainer m_staInterfaces
IPv4 interfaces for non-AP MLDs.
std::size_t m_nNs
counts how many Neighbor Solicitations are transmitted
void DoSetup() override
Implementation to do any local setup required for this TestCase.
const std::size_t m_nPackets
number of application packets to generate
std::size_t m_nArpReply
counts how many ARP Replies are transmitted
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.
Ptr< UdpServer > m_sink
server app on the receiving node
Ipv4InterfaceContainer m_apInterface
IPv4 interface for AP MLD.
void StartTraffic() override
Start the generation of traffic (needs to be overridden).
bool m_amsduAggr
whether A-MSDU aggregation is enabled
std::size_t m_nCheckedArpRequest
counts how many ARP Requests are checked
Multi-Link Operations with UDP traffic Test Suite.
a polymophic address class
Definition address.h:114
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
ApplicationContainer Install(NodeContainer c)
Install an application on each node of the input container configured with all the attributes set wit...
void SetAttribute(const std::string &name, const AttributeValue &value)
Helper function used to set the underlying application attributes.
The packet header for an ARP packet.
Definition arp-header.h:23
bool IsReply() const
Check if the ARP is a reply.
Definition arp-header.cc:78
bool IsRequest() const
Check if the ARP is a request.
Definition arp-header.cc:71
Address GetDestinationHardwareAddress() const
Returns the destination hardware address.
Definition arp-header.cc:99
Address GetSourceHardwareAddress() const
Returns the source hardware address.
Definition arp-header.cc:92
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806).
Hold variables of type enum.
Definition enum.h:52
ICMPv6 header.
uint8_t GetType() const
Get the type field.
ICMPv6 Neighbor Advertisement header.
ICMPv6 Neighbor Solicitation header.
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Helper class to auto-assign global IPv6 unicast addresses.
Describes an IPv6 address.
bool IsAny() const
If the IPv6 address is the "Any" address.
Packet header for IPv6.
Definition ipv6-header.h:24
uint8_t GetNextHeader() const
Get the next header.
Ipv6Address GetSource() const
Get the "Source address" field.
Keep track of a set of IPv6 interfaces.
static constexpr uint16_t PROT_NUMBER
The protocol number for IPv6 (0x86DD).
Describes an IPv6 prefix.
Header for the LLC/SNAP encapsulation.
uint16_t GetType()
Return the Ethertype.
an EUI-48 address
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address GetBroadcast()
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
static NodeContainer GetGlobal()
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
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.
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
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
Create a client application which sends UDP packets carrying a 32bit sequence number and a 64 bit tim...
Create a server application which waits for input UDP packets and uses the information carried into t...
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
static int64_t AssignStreams(NetDeviceContainer c, int64_t stream)
Assign a fixed random variable stream number to the random variables used by the PHY and MAC aspects ...
create MAC layers for a ns3::WifiNetDevice.
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
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_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#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_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 Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
WifiAssocType
Type of association performed by this device (provided that it is supported by the standard configure...
@ WIFI_STANDARD_80211be
Every class exported by the ns3 library is enclosed in the ns3 namespace.
constexpr FrequencyRange WIFI_SPECTRUM_6_GHZ
Identifier for the frequency range covering the wifi spectrum in the 6 GHz band.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:501
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:643
constexpr FrequencyRange WIFI_SPECTRUM_5_GHZ
Identifier for the frequency range covering the wifi spectrum in the 5 GHz band.
Ptr< T1 > StaticCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:650
std::unordered_map< uint16_t, Ptr< const WifiPsdu > > WifiConstPsduMap
Map of const PSDUs indexed by STA-ID.
Definition wifi-ppdu.h:38
constexpr FrequencyRange WIFI_SPECTRUM_2_4_GHZ
Identifier for the frequency range covering the wifi spectrum in the 2.4 GHz band.
STL namespace.
params
Fit Fluctuating Two Ray model to the 3GPP TR 38.901 using the Anderson-Darling goodness-of-fit ##.
bool amsduAggr
whether A-MSDU aggregation is enabled
WifiTrafficPattern trafficPattern
the pattern of traffic to generate
std::vector< std::string > secondStaChannels
string specifying channels for second STA
std::vector< std::string > apChannels
string specifying channels for AP
std::vector< std::string > firstStaChannels
string specifying channels for first STA
WifiAssocType assocType
type of association procedure
uint8_t ipVersion
IP version to use, either 4 or 6.
static WifiMloUdpTestSuite g_wifiMloUdpTestSuite
the test suite