A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-phy-rx-trace-helper.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2023 University of Washington
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 */
17
19
20#include "ns3/boolean.h"
21#include "ns3/config.h"
22#include "ns3/fatal-error.h"
23#include "ns3/frame-exchange-manager.h"
24#include "ns3/log.h"
25#include "ns3/multi-model-spectrum-channel.h"
26#include "ns3/net-device-container.h"
27#include "ns3/node-container.h"
28#include "ns3/node-list.h"
29#include "ns3/pointer.h"
30#include "ns3/simulator.h"
31#include "ns3/spectrum-wifi-phy.h"
32#include "ns3/wifi-mac-header.h"
33#include "ns3/wifi-mac-queue.h"
34#include "ns3/wifi-mac.h"
35#include "ns3/wifi-mode.h"
36#include "ns3/wifi-net-device.h"
37#include "ns3/wifi-psdu.h"
38#include "ns3/wifi-spectrum-signal-parameters.h"
39#include "ns3/yans-wifi-phy.h"
40
41#include <algorithm>
42#include <iostream>
43#include <set>
44#include <string>
45#include <utility>
46
47namespace ns3
48{
49
50NS_LOG_COMPONENT_DEFINE("WifiPhyRxTraceHelper");
51
52/**
53 * Number of places to shift WifiPpdu UID values, when generating unique IDs
54 */
55const uint32_t SHIFT = 16;
56
58{
59 NS_LOG_FUNCTION(this);
60}
61
62void
64{
65 NS_LOG_FUNCTION(this << nodes.GetN());
67}
68
69void
71{
72 NS_LOG_FUNCTION(this << netDevices.GetN());
74 // filter netDevice entries through a set to prevent duplicate entries in the NodeContainer
75 std::set<Ptr<Node>> nodesSeen;
76 for (uint32_t i = 0; i < netDevices.GetN(); i++)
77 {
78 auto nodePtr = netDevices.Get(i)->GetNode();
79 if (nodesSeen.count(nodePtr) == 0)
80 {
81 nodesSeen.insert(nodePtr);
82 nodes.Add(nodePtr);
83 }
84 }
86}
87
88void
90 const std::map<Mac48Address, uint32_t>& macToNodeMap)
91{
92 NS_LOG_FUNCTION(this << nodes.GetN() << macToNodeMap.size());
93 NS_ABORT_MSG_IF(m_traceSink, "A trace sink is already configured for this helper");
94 m_traceSink = CreateObject<WifiPhyRxTraceSink>();
95 m_traceSink->SetMapMacAddressToNodeId(macToNodeMap);
96 for (uint32_t nodeId = 0; nodeId < nodes.GetN(); nodeId++)
97 {
98 for (uint32_t deviceId = 0; deviceId < nodes.Get(nodeId)->GetNDevices(); deviceId++)
99 {
100 auto wifiDevice = DynamicCast<WifiNetDevice>(nodes.Get(nodeId)->GetDevice(deviceId));
101 if (wifiDevice)
102 {
103 for (uint8_t i = 0; i < wifiDevice->GetNPhys(); i++)
104 {
105 auto phy = wifiDevice->GetPhy(i);
106 auto yansPhy = DynamicCast<YansWifiPhy>(phy);
107 auto spectrumPhy = DynamicCast<SpectrumWifiPhy>(phy);
108 NS_ASSERT_MSG(yansPhy || spectrumPhy, "Phy type not found");
109 const std::string context =
110 "/NodeList/" + std::to_string(wifiDevice->GetNode()->GetId()) +
111 "/DeviceList/" + std::to_string(wifiDevice->GetIfIndex()) + "/Phys/" +
112 std::to_string(i);
113 auto connected = false;
114 if (yansPhy)
115 {
116 connected = yansPhy->TraceConnect(
117 "SignalArrival",
118 context,
120 }
121 else if (spectrumPhy)
122 {
123 connected = spectrumPhy->TraceConnect(
124 "SignalArrival",
125 context,
127 m_traceSink));
128 }
129 else
130 {
131 NS_FATAL_ERROR("Phy type not found");
132 }
133 NS_ASSERT_MSG(connected, "Trace source not connected");
134 connected = phy->TraceConnect(
135 "SignalTransmission",
136 context,
138 NS_ASSERT_MSG(connected, "Trace source not connected");
139 // Log packet drops
140 connected = phy->TraceConnect(
141 "PhyRxPpduDrop",
142 context,
144 NS_ASSERT_MSG(connected, "Trace source not connected");
145 // Trace PHY Outcome events
146 connected = phy->GetState()->TraceConnect(
147 "RxOutcome",
148 context,
150 NS_ASSERT_MSG(connected, "Trace source not connected");
151 }
152 }
153 }
154 }
155
156 // If a map is provided use map if not populate it yourself
157 if (!macToNodeMap.empty())
158 {
159 m_traceSink->SetMapMacAddressToNodeId(macToNodeMap);
160 }
161 // A linkID in one device might not be the same link on another device, need to create a mapping
162 // from node to link
163 m_traceSink->MapNodeToLinkToChannel(nodes);
164
165 if (!m_traceSink->IsCollectionPeriodActive())
166 {
167 NS_LOG_DEBUG("Connected traces but collection period is not active");
168 }
169}
170
171void
173{
174 m_traceSink->PrintStatistics();
175}
176
177void
178WifiPhyRxTraceHelper::PrintStatistics(Ptr<Node> node, uint32_t deviceId, uint8_t linkId) const
179{
180 m_traceSink->PrintStatistics(node->GetId(), deviceId, linkId);
181}
182
183void
184WifiPhyRxTraceHelper::PrintStatistics(uint32_t nodeId, uint32_t deviceId, uint8_t linkId) const
185{
186 m_traceSink->PrintStatistics(nodeId, deviceId, linkId);
187}
188
189void
191{
192 NS_LOG_FUNCTION(this << startTime.As(Time::S));
194}
195
196void
198{
199 NS_LOG_FUNCTION(this << stopTime.As(Time::S));
201}
202
203const std::vector<WifiPpduRxRecord>&
205{
206 m_traceSink->CreateVectorFromRecords();
207 return m_traceSink->GetPpduRecords();
208}
209
210std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>
211WifiPhyRxTraceHelper::GetPpduRecords(uint32_t nodeId, uint32_t deviceId, uint8_t linkId) const
212{
213 return m_traceSink->GetPpduRecords(nodeId, deviceId, linkId);
214}
215
216void
218{
219 NS_LOG_FUNCTION(this);
220 NS_LOG_INFO("Reset WifiPhyRxTraceHelper");
221 m_traceSink->Reset();
222}
223
226{
227 return m_traceSink->GetStatistics();
228}
229
231WifiPhyRxTraceHelper::GetStatistics(Ptr<Node> node, uint32_t deviceId, uint8_t linkId) const
232{
233 return m_traceSink->GetStatistics(node->GetId(), deviceId, linkId);
234}
235
237WifiPhyRxTraceHelper::GetStatistics(uint32_t nodeId, uint32_t deviceId, uint8_t linkId) const
238{
239 return m_traceSink->GetStatistics(nodeId, deviceId, linkId);
240}
241
242std::map<Mac48Address, uint32_t>
244{
245 std::map<Mac48Address, uint32_t> macAddressToNodeId;
246 for (uint32_t i = 0; i < nodes.GetN(); i++)
247 {
248 for (uint32_t device = 0; device < nodes.Get(i)->GetNDevices(); device++)
249 {
250 if (auto wdev = DynamicCast<WifiNetDevice>(nodes.Get(i)->GetDevice(device)))
251 {
252 for (uint32_t link = 0; link < wdev->GetNPhys(); link++)
253 {
254 macAddressToNodeId[Mac48Address::ConvertFrom(
255 wdev->GetMac()->GetFrameExchangeManager(link)->GetAddress())] =
256 nodes.Get(i)->GetId();
257 NS_LOG_DEBUG("NodeID: "
258 << nodes.Get(i)->GetId() << " DeviceID: " << device
259 << " LinkId: " << link << " MAC: "
260 << wdev->GetMac()->GetFrameExchangeManager(link)->GetAddress());
261 }
262 }
263 }
264 }
265 return macAddressToNodeId;
266}
267
269
270TypeId
272{
273 static TypeId tid = TypeId("ns3::WifiPhyRxTraceSink")
274 .SetParent<Object>()
275 .SetGroupName("Wifi")
276 .AddConstructor<WifiPhyRxTraceSink>();
277 return tid;
278}
279
281{
282 NS_LOG_FUNCTION(this);
283}
284
285void
287 const std::map<Mac48Address, uint32_t>& MacAddressToNodeIdMap)
288{
289 m_macAddressToNodeId = MacAddressToNodeIdMap;
290}
291
293WifiPhyRxTraceSink::ContextToNodeId(std::string context) const
294{
295 const auto sub = context.substr(10);
296 const auto pos = sub.find("/Device");
297 return std::stoi(sub.substr(0, pos));
298}
299
300int
301WifiPhyRxTraceSink::ContextToLinkId(std::string context) const
302{
303 const auto pos = context.find("/Phys/");
304 const auto sub = context.substr(pos + 6);
305 const auto nextSlashPos = sub.find('/');
306 if (nextSlashPos == std::string::npos)
307 {
308 return std::stoi(sub);
309 }
310 const auto physNumberStr = sub.substr(0, nextSlashPos);
311 return std::stoi(physNumberStr);
312}
313
314int
316{
317 auto pos = context.find("/DeviceList/");
318 pos += 12;
319 const auto sub = context.substr(pos);
320 const auto nextSlashPos = sub.find('/');
321 const auto deviceIdStr = sub.substr(0, nextSlashPos);
322 return std::stoi(deviceIdStr);
323}
324
325std::string
326WifiPhyRxTraceSink::ContextToTuple(std::string context) const
327{
328 const auto str = std::to_string(ContextToNodeId(context)) + ":" +
329 std::to_string(ContextToDeviceId(context)) + ":" +
330 std::to_string(ContextToLinkId(context));
331 return str;
332}
333
334// Each WifiPpdu has a UID, but more than one trace record can exist for a unique WifiPpdu
335// This generator shifts the WifiPpdu UID leftward and combines it with a member variable
336// counter to generate more than one unique ID for each WifiPpdu UID
337uint64_t
339{
340 uint64_t tag;
341 do
342 {
343 tag = (ppduUid << SHIFT) | counter++;
344 } while (usedTags.find(tag) != usedTags.end());
345 usedTags.insert(tag);
346 NS_LOG_DEBUG("Generating tag " << tag << " from ppdu UID " << ppduUid);
347 return tag;
348}
349
350bool
352{
353 return lhs.m_rxTag == rhs.m_rxTag;
354}
355
356bool
358{
359 return !(lhs == rhs);
360}
361
362bool
363operator<(const WifiPpduRxRecord& lhs, const WifiPpduRxRecord& rhs)
364{
365 return lhs.m_rxTag < rhs.m_rxTag;
366}
367
368WifiPhyTraceStatistics
370{
374 result.m_failedPpdus = lhs.m_failedPpdus + rhs.m_failedPpdus;
377 result.m_failedMpdus = lhs.m_failedMpdus + rhs.m_failedMpdus;
378
379 // Merge map fields
380 for (const auto& pair : lhs.m_ppduDropReasons)
381 {
382 result.m_ppduDropReasons[pair.first] += pair.second;
383 }
384 for (const auto& pair : rhs.m_ppduDropReasons)
385 {
386 result.m_ppduDropReasons[pair.first] += pair.second;
387 }
388 return result;
389}
390
391bool
393{
394 return lhs.m_overlappingPpdus == rhs.m_overlappingPpdus &&
399}
400
401bool
403{
404 return !(lhs == rhs);
405}
406
407void
409{
410 for (uint32_t i = 0; i < nodes.GetN(); i++)
411 {
412 for (uint32_t device = 0; device < nodes.Get(i)->GetNDevices(); device++)
413 {
414 auto wdev = DynamicCast<WifiNetDevice>(nodes.Get(i)->GetDevice(device));
415 if (wdev)
416 {
417 for (uint32_t link = 0; link < wdev->GetNPhys(); link++)
418 {
419 m_nodeToDeviceToLinkToChannelInfo[nodes.Get(i)->GetId()][wdev->GetIfIndex()]
420 [link] = std::make_pair(
421 wdev->GetPhy(link)->GetChannelNumber(),
422 wdev->GetPhy(link)->GetFrequency());
423
424 NS_LOG_DEBUG("NodeId: "
425 << nodes.Get(i)->GetId() << " DeviceID: " << wdev->GetIfIndex()
426 << " LinkId: " << link
427 << " freq: " << wdev->GetPhy(link)->GetFrequency()
428 << " ch#: " << int(wdev->GetPhy(link)->GetChannelNumber()));
429 }
430 }
431 }
432 }
433}
434
435// channel number, frequency
436std::optional<std::pair<uint8_t, uint16_t>>
437WifiPhyRxTraceSink::GetChannelInfo(uint32_t nodeId, uint32_t deviceId, int link) const
438{
439 auto nodeIter = m_nodeToDeviceToLinkToChannelInfo.find(nodeId);
440 if (nodeIter != m_nodeToDeviceToLinkToChannelInfo.end())
441 {
442 auto& deviceMap = nodeIter->second;
443 auto deviceIter = deviceMap.find(deviceId);
444 if (deviceIter != deviceMap.end())
445 {
446 auto& linkMap = deviceIter->second;
447 auto linkIter = linkMap.find(link);
448 if (linkIter != linkMap.end())
449 {
450 return std::optional<std::pair<uint8_t, uint16_t>>(linkIter->second);
451 }
452 }
453 }
454 return std::nullopt;
455}
456
457// TODO: Profile this and possibly refactor to avoid duplicates
458void
460 uint32_t deviceId,
461 uint8_t linkId)
462{
463 NS_LOG_FUNCTION(this << nodeId << deviceId << linkId);
464 // Add all overlapping packets to the list of overlapping packets for this frame arrival
465 for (const auto& it : m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(linkId))
466 {
467 for (const auto& iter : m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(linkId))
468 {
469 if (it != iter)
470 {
471 m_rxTagToListOfOverlappingPpduRecords[it.m_rxTag].emplace_back(iter);
472 }
473 }
474 }
475
476 // Remove duplicates
477 for (const auto& it : m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(linkId))
478 {
479 // First, sort the vector to bring duplicates together
480 std::sort(m_rxTagToListOfOverlappingPpduRecords[it.m_rxTag].begin(),
481 m_rxTagToListOfOverlappingPpduRecords[it.m_rxTag].end());
482 // Use std::unique to remove duplicates (adjacent identical elements)
484 std::unique(m_rxTagToListOfOverlappingPpduRecords[it.m_rxTag].begin(),
485 m_rxTagToListOfOverlappingPpduRecords[it.m_rxTag].end()),
486 m_rxTagToListOfOverlappingPpduRecords[it.m_rxTag].end());
487 }
489 "Map of overlapping PPDU records size: " << m_rxTagToListOfOverlappingPpduRecords.size());
490}
491
492void
494{
495 NS_LOG_FUNCTION(this << nodeId << deviceId);
496 // remove from currently received (in this case transmitted) packets
497 NS_LOG_INFO("Remove transmit record at " << nodeId << ":" << deviceId << ":"
498 << +ppduRecord.m_linkId << " UID "
499 << ppduRecord.m_rxTag);
501 .at(deviceId)
502 .at(ppduRecord.m_linkId)
503 .erase(
504 std::remove(
505 m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(ppduRecord.m_linkId).begin(),
506 m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(ppduRecord.m_linkId).end(),
507 ppduRecord),
508 m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(ppduRecord.m_linkId).end());
509 NS_LOG_INFO("Size of m_nodeDeviceLinkRxRecords: " << m_nodeDeviceLinkRxRecords.size());
510
511 // Erase the item from rxTagToPpduRecord
512 m_rxTagToPpduRecord.erase(ppduRecord.m_rxTag);
513 NS_LOG_INFO("Size of m_rxTagToPpduRecord: " << m_rxTagToPpduRecord.size());
514}
515
516void
517WifiPhyRxTraceSink::PhyRxEnd(uint32_t nodeId, uint32_t deviceId, uint64_t rxTag, uint64_t ppduUid)
518{
519 NS_LOG_FUNCTION(this << nodeId << deviceId << rxTag << ppduUid);
520 NS_ASSERT_MSG(m_rxTagToPpduRecord.contains(rxTag), "Missing PPDU at PhyRxEnd");
521 // Update the end time on the record, and reinsert to the map
522 auto ppduRecord = m_rxTagToPpduRecord[rxTag];
523 ppduRecord.m_endTime = Simulator::Now();
524 auto [it, inserted] = m_rxTagToPpduRecord.insert_or_assign(rxTag, ppduRecord);
525 NS_ASSERT_MSG(!inserted, "Did not assign successfully");
526
527 // Update the lists of overlapping PPDUs
528 UpdateCurrentlyReceivedSignal(nodeId, deviceId, ppduRecord.m_linkId);
529 for (const auto& it : m_rxTagToListOfOverlappingPpduRecords[rxTag])
530 {
531 ppduRecord.m_overlappingPpdu.emplace_back(it);
532 }
533
534 NS_LOG_INFO("Remove reception record at " << nodeId << ":" << deviceId << ":"
535 << +ppduRecord.m_linkId << " UID " << rxTag);
536 // Remove from map of active records
538 .at(deviceId)
539 .at(ppduRecord.m_linkId)
540 .erase(
541 std::remove(
542 m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(ppduRecord.m_linkId).begin(),
543 m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(ppduRecord.m_linkId).end(),
544 ppduRecord),
545 m_nodeDeviceLinkRxRecords.at(nodeId).at(deviceId).at(ppduRecord.m_linkId).end());
546 NS_LOG_INFO("Size of m_nodeDeviceLinkRxRecords: " << m_nodeDeviceLinkRxRecords.size());
547
548 // Erase the item from rxTagToPpduRecord
549 m_rxTagToPpduRecord.erase(rxTag);
550 NS_LOG_INFO("Size of m_rxTagToPpduRecord: " << m_rxTagToPpduRecord.size());
551
552 // checks if statistics period has been started before adding to the list of completed records
554 {
555 NS_LOG_INFO("Adding PPDU record for " << ppduRecord.m_receiverId << " " << deviceId << " "
556 << +ppduRecord.m_linkId);
557 m_completedRecords[ppduRecord.m_receiverId][deviceId][ppduRecord.m_linkId].emplace_back(
558 ppduRecord);
559 }
560 else
561 {
562 NS_LOG_DEBUG("Not adding PPDU record (statistics not started) for "
563 << ppduRecord.m_receiverId << " " << deviceId << " " << ppduRecord.m_linkId);
564 }
565}
566
567bool
569{
571}
572
573void
575{
577}
578
579void
581{
583}
584
585void
588 const WifiTxVector& txVector)
589{
590 NS_LOG_FUNCTION(context << ppdu << txVector);
591 uint32_t nodeId = ContextToNodeId(context);
592 uint32_t deviceId = ContextToDeviceId(context);
593 uint8_t linkId = ContextToLinkId(context);
594
595 WifiPpduRxRecord ppduRecord;
596 ppduRecord.m_startTime = Simulator::Now();
597 ppduRecord.m_endTime = Simulator::Now() + ppdu->GetTxDuration();
598 ppduRecord.m_ppdu = ppdu;
599 ppduRecord.m_senderId = nodeId;
600 ppduRecord.m_linkId = linkId;
601 ppduRecord.m_senderDeviceId = deviceId;
602
603 // Tag used to determine which packet needs to be removed from currently received packets
604 ppduRecord.m_rxTag = m_tagGenerator.GenerateUniqueTag(ppdu->GetUid());
605
606 NS_LOG_INFO("Transmit at " << ContextToTuple(context) << " insert to tagToRecord map for UID "
607 << ppduRecord.m_rxTag);
608 auto [it, inserted] = m_rxTagToPpduRecord.insert_or_assign(ppduRecord.m_rxTag, ppduRecord);
609 NS_ASSERT_MSG(inserted, "Did not insert successfully");
610 NS_LOG_INFO("Size of m_rxTagToPpduRecord: " << m_rxTagToPpduRecord.size());
611
612 /*
613 m_rxTagToPpduRecord[ppduRecord.m_rxTag] = ppduRecord;
614 */
615
616 // Use this to find who is the sender in the reception side
617 m_ppduUidToTxTag[ppduRecord.m_ppdu->GetUid()] = ppduRecord.m_rxTag;
618
619 // store record in a map, indexed by nodeId, deviceId, linkId
620 NS_LOG_INFO("Transmit at " << ContextToTuple(context)
621 << " insert to active records map for UID " << ppduRecord.m_rxTag);
622 m_nodeDeviceLinkRxRecords[nodeId][deviceId][linkId].emplace_back(ppduRecord);
623 NS_LOG_INFO("Size of active records: " << m_nodeDeviceLinkRxRecords.size());
624
625 Simulator::Schedule(ppduRecord.m_endTime - ppduRecord.m_startTime,
627 this,
628 nodeId,
629 deviceId,
630 ppduRecord);
631}
632
633void
636 uint32_t senderNodeId,
637 double rxPower,
638 Time duration)
639{
640 NS_LOG_FUNCTION(context << signal << senderNodeId << rxPower << duration);
641 const auto wifiSignal = DynamicCast<const WifiSpectrumSignalParameters>(signal);
642 const auto ppdu = wifiSignal->ppdu;
643
644 if (!wifiSignal)
645 {
646 NS_LOG_DEBUG("Non-WiFi Signal Received");
647 return;
648 }
649 PhySignalArrival(context, ppdu, rxPower, duration);
650}
651
652void
655 double rxPower,
656 Time duration)
657{
658 NS_LOG_FUNCTION(context << ppdu << rxPower << duration);
659 uint32_t nodeId = ContextToNodeId(context);
660 uint32_t deviceId = ContextToDeviceId(context);
661 uint8_t linkId = ContextToLinkId(context);
662
663 // Associate this received PPDU with a record previously stored on the transmit side, if present
664 bool hasTxTag = false;
665 WifiPpduRxRecord txPpduRecord;
666 if (m_ppduUidToTxTag.contains(ppdu->GetUid()))
667 {
668 hasTxTag = true;
669 txPpduRecord = m_rxTagToPpduRecord[m_ppduUidToTxTag[ppdu->GetUid()]];
670 NS_LOG_DEBUG("Arrival RxNodeID: " << nodeId << " SenderID: " << txPpduRecord.m_senderId
671 << " Received on LinkID: " << +linkId
672 << " Frame Sent on LinkId: " << +txPpduRecord.m_linkId);
673 }
674 else
675 {
676 NS_LOG_DEBUG("Arrival RxNodeID: " << nodeId << " Received on LinkID: " << +linkId
677 << "; no sender info");
678 }
679 if (hasTxTag)
680 {
681 auto rxInfo = GetChannelInfo(nodeId, deviceId, linkId);
682 auto txInfo = GetChannelInfo(txPpduRecord.m_senderId,
683 txPpduRecord.m_senderDeviceId,
684 txPpduRecord.m_linkId);
685 if (!txInfo.has_value())
686 {
688 "Didn't find TX record for transmission; possibly from an untraced sender");
689 }
690 else
691 {
692 if ((int(txInfo->second) != int(rxInfo->second)) ||
693 (int(txInfo->first) != int(rxInfo->first)))
694 {
696 "Received Signal on a different frequency or channel number than what was "
697 "configured for this PHY or link");
698 return;
699 }
700 }
701 }
702
703 WifiPpduRxRecord ppduRecord;
704 ppduRecord.m_startTime = Simulator::Now();
705 ppduRecord.m_endTime = Simulator::Now() + duration;
706 ppduRecord.m_ppdu = ppdu;
707 ppduRecord.m_rssi = rxPower;
708 ppduRecord.m_rxTag = m_tagGenerator.GenerateUniqueTag(ppdu->GetUid());
709 ppduRecord.m_receiverId = nodeId;
710 ppduRecord.m_linkId = linkId;
711 if (hasTxTag)
712 {
713 ppduRecord.m_senderId = txPpduRecord.m_senderId;
714 ppduRecord.m_senderDeviceId = txPpduRecord.m_senderDeviceId;
716 "Receive at " << ContextToTuple(context) << " from node " << txPpduRecord.m_senderId
717 << "; insert to active records map for UID " << ppduRecord.m_rxTag);
718 }
719 else
720 {
721 NS_LOG_INFO("Receive at " << ContextToTuple(context)
722 << "; insert to active records map for UID "
723 << ppduRecord.m_rxTag);
724 }
725
726 // Add to list of currently received frames on this node, device and specific link
727 m_nodeDeviceLinkRxRecords[nodeId][deviceId][linkId].emplace_back(ppduRecord);
728 NS_LOG_INFO("Size of active records " << m_nodeDeviceLinkRxRecords.size());
729
730 UpdateCurrentlyReceivedSignal(nodeId, deviceId, linkId);
731
732 NS_LOG_INFO("Receive at " << ContextToTuple(context) << " insert to tagToRecord map for UID "
733 << ppduRecord.m_rxTag);
734 auto [it, inserted] = m_rxTagToPpduRecord.insert_or_assign(ppduRecord.m_rxTag, ppduRecord);
735 NS_ASSERT_MSG(inserted, "Did not insert successfully");
736 NS_LOG_INFO("Size of m_rxTagToPpduRecord " << m_rxTagToPpduRecord.size());
737
738 NS_LOG_INFO("Receive at " << ContextToTuple(context) << " insert to highly nested map for UID "
739 << ppduRecord.m_rxTag);
740 m_nodeDeviceLinkPidToRxId[nodeId][deviceId][linkId][ppduRecord.m_ppdu->GetUid()] =
741 ppduRecord.m_rxTag;
742 NS_LOG_INFO("Size of highly nested map " << m_nodeDeviceLinkPidToRxId.size());
743}
744
745void
749{
750 NS_LOG_FUNCTION(this << context << ppdu << reason);
751 uint32_t nodeId = ContextToNodeId(context);
752 uint32_t deviceId = ContextToDeviceId(context);
753 uint8_t linkId = ContextToLinkId(context);
754 WifiPpduRxRecord ppduRecord =
755 m_rxTagToPpduRecord[m_nodeDeviceLinkPidToRxId[nodeId][deviceId][linkId][ppdu->GetUid()]];
756
757 if (ppduRecord.m_ppdu == nullptr)
758 {
759 NS_LOG_DEBUG("Frame being dropped was not observed on SignalArrival trace. Means it was "
760 "received on a wrong link configuration");
761 return;
762 }
763 ppduRecord.m_reason = reason;
764
765 std::vector<bool> outcome;
766 for (const auto& mpdu : *PeekPointer(ppdu->GetPsdu()))
767 {
768 mpdu->GetPacket();
769 outcome.emplace_back(false);
770 }
771 ppduRecord.m_statusPerMpdu = outcome;
772 m_rxTagToPpduRecord[ppduRecord.m_rxTag] = ppduRecord;
773
776 this,
777 nodeId,
778 deviceId,
779 ppduRecord.m_rxTag,
780 ppdu->GetUid());
781}
782
783void
786 RxSignalInfo signal,
787 const WifiTxVector& txVector,
788 const std::vector<bool>& statusMpdu)
789{
790 NS_LOG_FUNCTION(context << ppdu << signal << txVector);
791 uint32_t nodeId = ContextToNodeId(context);
792 uint32_t deviceId = ContextToDeviceId(context);
793 uint8_t linkId = ContextToLinkId(context);
794
795 WifiPpduRxRecord ppduRecord =
796 m_rxTagToPpduRecord[m_nodeDeviceLinkPidToRxId[nodeId][deviceId][linkId][ppdu->GetUid()]];
797
798 if (ppduRecord.m_ppdu)
799 {
800 NS_LOG_DEBUG("Found an expected frame in the outcome");
801 }
802 else
803 {
804 NS_LOG_DEBUG("Frame to be processed was not observed on SignalArrival trace");
805 return;
806 }
807 // Save the reception status per MPDU in the PPDU record
808 ppduRecord.m_statusPerMpdu = statusMpdu;
809
810 auto [it, inserted] = m_rxTagToPpduRecord.insert_or_assign(ppduRecord.m_rxTag, ppduRecord);
811 NS_ASSERT_MSG(!inserted, "Did not assign successfully");
812 PhyRxEnd(nodeId, deviceId, ppduRecord.m_rxTag, ppdu->GetUid());
813}
814
815void
817 const WifiPpduRxRecord& record) const
818{
819 // Check if PPDU was dropped and if any MPDU was addressed to the receiver
820 if (record.m_reason)
821 {
822 bool mpduToReceiver = false;
823 bool shouldCount = true;
825 auto it = record.m_statusPerMpdu.begin();
826 for (const auto& mpdu : *PeekPointer(record.m_ppdu->GetPsdu()))
827 {
828 p = mpdu->GetProtocolDataUnit();
829 WifiMacHeader hdr;
830 p->PeekHeader(hdr);
831 if (!(hdr.IsData() &&
832 (hdr.GetType() == WIFI_MAC_DATA || hdr.GetType() == WIFI_MAC_QOSDATA)))
833 {
834 shouldCount = false;
835 break;
836 }
837 if (!(*it) && (record.m_receiverId == m_macAddressToNodeId.at(hdr.GetAddr1())))
838 {
839 // Failed MPDU
840 statistics.m_failedMpdus++;
841 mpduToReceiver = true;
842 }
843 ++it;
844 }
845 // At least one MPDU addressed to the receiver was dropped, mark PPDU as
846 // failed
847 if (mpduToReceiver && shouldCount)
848 {
849 statistics.m_failedPpdus++;
850 // Check if PPDU Overlap
851 if (!record.m_overlappingPpdu.empty())
852 {
853 // Yes Overlap
854 statistics.m_overlappingPpdus++;
855 }
856 else
857 {
858 // No Overlap
859 statistics.m_nonOverlappingPpdus++;
860 }
861 // It is due to a drop, clarify and count the reason
862 statistics.m_ppduDropReasons[record.m_reason]++;
863 }
864 }
865 else
866 {
867 // Payload Decode Attempt (No Drop but still not certain of MPDU outcome)
868 // MPDU Level
869
871 auto it = record.m_statusPerMpdu.begin();
872 bool mpduFail = false;
873 bool shouldCount = true;
874 bool mpduToReceiver = false;
875 for (const auto& mpdu : *PeekPointer(record.m_ppdu->GetPsdu()))
876 {
877 p = mpdu->GetProtocolDataUnit();
878 WifiMacHeader hdr;
879 p->PeekHeader(hdr);
880 if (!(hdr.IsData() &&
881 (hdr.GetType() == WIFI_MAC_DATA || hdr.GetType() == WIFI_MAC_QOSDATA)))
882 {
883 shouldCount = false;
884 break;
885 }
886 if (*it && (m_macAddressToNodeId.contains(hdr.GetAddr1())) &&
887 (record.m_receiverId == m_macAddressToNodeId.at(hdr.GetAddr1())))
888 {
889 // Successful MPDU
890 statistics.m_receivedMpdus++;
891 mpduToReceiver = true;
892 }
893 else if (!(*it) && (m_macAddressToNodeId.contains(hdr.GetAddr1())) &&
894 (record.m_receiverId == m_macAddressToNodeId.at(hdr.GetAddr1())))
895 {
896 // Failed MPDU
897 statistics.m_failedMpdus++;
898 mpduFail = true;
899 mpduToReceiver = true;
900 }
901 ++it;
902 }
903 if (!mpduFail && shouldCount && mpduToReceiver)
904 {
905 // No drops or payload decode errors for all MPDUs addressed to the
906 // receiver
907 statistics.m_receivedPpdus++;
908
909 // Check if PPDU Overlap
910 if (!record.m_overlappingPpdu.empty())
911 {
912 // Yes Overlap
913 statistics.m_overlappingPpdus++;
914 }
915 else
916 {
917 // No Overlap
918 statistics.m_nonOverlappingPpdus++;
919 }
920 }
921 else if (shouldCount && mpduToReceiver)
922 {
923 // At least one MPDU addressed to the receiver failed.
924 statistics.m_failedPpdus++;
925 // Check if PPDU Overlap
926 if (!record.m_overlappingPpdu.empty())
927 {
928 // Yes Overlap
929 statistics.m_overlappingPpdus++;
930 }
931 else
932 {
933 // No Overlap
934 statistics.m_nonOverlappingPpdus++;
935 }
936 }
937 }
938}
939
942{
943 NS_LOG_FUNCTION(this);
944 WifiPhyTraceStatistics statistics;
945 for (const auto& nodeMap : m_completedRecords)
946 {
947 for (const auto& deviceMap : nodeMap.second)
948 {
949 for (const auto& linkMap : deviceMap.second)
950 {
951 for (const auto& record : linkMap.second)
952 {
953 CountStatisticsForRecord(statistics, record);
954 }
955 }
956 }
957 }
958 return statistics;
959}
960
962WifiPhyRxTraceSink::CountStatistics(uint32_t nodeId, uint32_t deviceId, uint8_t linkId) const
963{
964 NS_LOG_FUNCTION(this << nodeId << deviceId << linkId);
965 WifiPhyTraceStatistics statistics;
966 if (m_completedRecords.contains(nodeId))
967 {
968 auto mapOfDevices = m_completedRecords.at(nodeId);
969 if (mapOfDevices.contains(deviceId))
970 {
971 auto mapOfLinks = mapOfDevices.at(deviceId);
972 if (mapOfLinks.contains(linkId))
973 {
974 auto vectorOfRecords = mapOfLinks.at(linkId);
975 for (const auto& record : vectorOfRecords)
976 {
977 CountStatisticsForRecord(statistics, record);
978 }
979 }
980 }
981 }
982 return statistics;
983}
984
987{
989 return stats;
990}
991
993WifiPhyRxTraceSink::GetStatistics(uint32_t nodeId, uint32_t deviceId, uint8_t linkId) const
994{
995 WifiPhyTraceStatistics stats = CountStatistics(nodeId, deviceId, linkId);
996 return stats;
997}
998
999void
1001{
1003
1004 std::cout << "Total PPDUs Received: " << statistics.m_receivedPpdus + statistics.m_failedPpdus
1005 << std::endl;
1006 std::cout << "Total Non-Overlapping PPDUs Received: " << statistics.m_nonOverlappingPpdus
1007 << std::endl;
1008 std::cout << "Total Overlapping PPDUs Received: " << statistics.m_overlappingPpdus << std::endl;
1009
1010 std::cout << "\nSuccessful PPDUs: " << statistics.m_receivedPpdus << std::endl;
1011 std::cout << "Failed PPDUs: " << statistics.m_failedPpdus << std::endl;
1012 for (auto reason : statistics.m_ppduDropReasons)
1013 {
1014 std::cout << "PPDU Dropped due to " << reason.first << ": " << reason.second << std::endl;
1015 }
1016 std::cout << "\nTotal MPDUs: " << statistics.m_failedMpdus + statistics.m_receivedMpdus
1017 << std::endl;
1018 std::cout << "Total Successful MPDUs: " << statistics.m_receivedMpdus << std::endl;
1019 std::cout << "Total Failed MPDUs: " << statistics.m_failedMpdus << std::endl;
1020}
1021
1022void
1023WifiPhyRxTraceSink::PrintStatistics(uint32_t nodeId, uint32_t deviceId, uint8_t linkId) const
1024{
1025 WifiPhyTraceStatistics statistics = CountStatistics(nodeId, deviceId, linkId);
1026 std::cout << "Total PPDUs Received: " << statistics.m_receivedPpdus + statistics.m_failedPpdus
1027 << std::endl;
1028 std::cout << "Total Non-Overlapping PPDUs Received: " << statistics.m_nonOverlappingPpdus
1029 << std::endl;
1030 std::cout << "Total Overlapping PPDUs Received: " << statistics.m_overlappingPpdus << std::endl;
1031
1032 std::cout << "\nSuccessful PPDUs: " << statistics.m_receivedPpdus << std::endl;
1033 std::cout << "Failed PPDUs: " << statistics.m_failedPpdus << std::endl;
1034 for (auto reason : statistics.m_ppduDropReasons)
1035 {
1036 std::cout << "PPDU Dropped due to " << reason.first << ": " << reason.second << std::endl;
1037 }
1038 std::cout << "\nTotal MPDUs: " << statistics.m_failedMpdus + statistics.m_receivedMpdus
1039 << std::endl;
1040 std::cout << "Total Successful MPDUs: " << statistics.m_receivedMpdus << std::endl;
1041 std::cout << "Total Failed MPDUs: " << statistics.m_failedMpdus << std::endl;
1042}
1043
1044void
1046{
1047 m_completedRecords.clear();
1048 m_records.clear();
1049}
1050
1051// Return a single vector with all completed records
1052void
1054{
1055 m_records.clear();
1056 for (const auto& nodeMap : m_completedRecords)
1057 {
1058 for (const auto& deviceMap : nodeMap.second)
1059 {
1060 for (const auto& linkMap : deviceMap.second)
1061 {
1062 for (const auto& wifiRecord : linkMap.second)
1063 {
1064 m_records.emplace_back(wifiRecord);
1065 }
1066 }
1067 }
1068 }
1069}
1070
1071const std::vector<WifiPpduRxRecord>&
1073{
1074 return m_records;
1075}
1076
1077std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>
1078WifiPhyRxTraceSink::GetPpduRecords(uint32_t nodeId, uint32_t deviceId, uint8_t linkId) const
1079{
1080 if (m_completedRecords.contains(nodeId))
1081 {
1082 if (m_completedRecords.at(nodeId).contains(deviceId))
1083 {
1084 if (m_completedRecords.at(nodeId).at(deviceId).contains(linkId))
1085 {
1086 return std::optional<std::reference_wrapper<const std::vector<WifiPpduRxRecord>>>(
1087 m_completedRecords.at(nodeId).at(deviceId).at(linkId));
1088 }
1089 }
1090 }
1091 return std::nullopt;
1092}
1093
1094} // namespace ns3
static Mac48Address ConvertFrom(const Address &address)
holds a vector of ns3::NetDevice pointers
uint32_t GetN() const
Get the number of Ptr<NetDevice> stored in this container.
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.
A base class which provides memory management and object aggregation.
Definition: object.h:89
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
@ S
second
Definition: nstime.h:116
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:932
Implements the IEEE 802.11 MAC header.
Mac48Address GetAddr1() const
Return the address in the Address 1 field.
virtual WifiMacType GetType() const
Return the type (WifiMacType)
bool IsData() const
Return true if the Type is DATA.
const std::vector< WifiPpduRxRecord > & GetPpduRecords() const
Accesses a vector of saved and completed PPDU reception records.
void PrintStatistics() const
Print statistics for all nodes, devices, and links during the collection period.
void Reset()
Resets the current statistics, clearing all counts and PPDU records.
Ptr< WifiPhyRxTraceSink > m_traceSink
Pointer to the current trace sink object.
void Stop(Time stopTime)
Stops the collection of statistics at a specified time.
WifiPhyTraceStatistics GetStatistics() const
Retrieves current statistics of successful and failed data PPDUs and MPDUs receptions,...
void Enable(NodeContainer nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
std::map< Mac48Address, uint32_t > MapMacAddressesToNodeIds(NodeContainer nodes) const
Populates the mapping of MAC addresses to node IDs for a given set of nodes.
void Start(Time startTime)
Starts the collection of statistics from a specified start time.
std::set< uint64_t > usedTags
Set of already used tags.
uint64_t GenerateUniqueTag(uint64_t ppduUid)
Generates a unique tag for a WifiPpdu.
uint64_t counter
Counter to help generate unique tags.
Sink class for capturing and analyzing PHY layer reception events in Wi-Fi networks.
std::map< uint64_t, std::map< uint64_t, std::map< uint64_t, std::map< uint64_t, uint64_t > > > > m_nodeDeviceLinkPidToRxId
Aids in correlating PHY reception drops and outcomes with specific reception tags.
void Reset()
Resets the statistics collection, clearing all counts and discarding all fully completed PPDU records...
std::map< uint32_t, std::map< uint32_t, std::map< uint8_t, std::vector< WifiPpduRxRecord > > > > m_completedRecords
Stores records of PPDUs that have completed reception, organized by node, device, and link.
void CreateVectorFromRecords()
Creates a vector with all completed WiFi reception records to be returned by the GetPpduRecords().
void SpectrumPhySignalArrival(std::string context, Ptr< const SpectrumSignalParameters > signal, uint32_t senderNodeId, double rxPower, Time duration)
Handles the event of a PHY signal arrival from a SpectrumChannel.
const std::vector< WifiPpduRxRecord > & GetPpduRecords() const
Provides access to all saved and completed PPDU reception records across all nodes,...
bool m_statisticsCollectionPeriodStarted
Flag indicating whether to keep a record of certain statistics or events for analysis.
void Stop()
Stops the statistics collection period at a specified time.
WifiPhyTraceStatistics CountStatistics() const
Counts and aggregates PHY layer statistics including receptions, transmissions, and performance metri...
void PhyRxEnd(uint32_t nodeId, uint32_t deviceId, uint64_t rxTag, uint64_t ppduUid)
Handles the end of a PHY reception event, logging the conclusion of a reception and its associated de...
bool IsCollectionPeriodActive() const
Returns whether the collection period is active.
std::map< uint64_t, WifiPpduRxRecord > m_rxTagToPpduRecord
Maps a reception tag to the corresponding WifiPpduRxRecord.
std::map< Mac48Address, uint32_t > m_macAddressToNodeId
Maps MAC addresses to node IDs.
void PhyPpduDrop(std::string context, Ptr< const WifiPpdu > ppdu, WifiPhyRxfailureReason reason)
Logs the drop of a PPDU at the PHY layer, detailing the context and reason for the drop.
std::optional< std::pair< uint8_t, uint16_t > > GetChannelInfo(uint32_t node, uint32_t deviceId, int link) const
Retrieves the frequency and channel number used by a specific link.
std::vector< WifiPpduRxRecord > m_records
Stores a flat vector of all records of PPDUs that have completed reception.
void PhySignalTransmission(std::string context, Ptr< const WifiPpdu > ppdu, const WifiTxVector &txVector)
Handles the event of a PHY signal transmission.
void PrintStatistics() const
Prints a summary of the statistics collected, offering a concise overview of PHY layer performance an...
WifiPhyTraceStatistics GetStatistics() const
Returns statistics on the count of successful and failed PPDUs with unicast data, and their MPDUs,...
std::map< uint64_t, std::vector< WifiPpduRxRecord > > m_rxTagToListOfOverlappingPpduRecords
Maps each reception tag to a list of overlapping WifiPpduRxRecords.
std::string ContextToTuple(std::string context) const
Translate a context string to a colon-delimited tuple "0:0:0" where the first element is a node ID,...
void Start()
Starts the statistics collection period from a specified start time.
void PpduOutcome(std::string context, Ptr< const WifiPpdu > ppdu, RxSignalInfo signal, const WifiTxVector &txVector, const std::vector< bool > &statusPerMpdu)
Records the outcome of a PPDU transmission, including the signal info, and the success or failure sta...
std::map< uint32_t, std::map< uint32_t, std::map< uint32_t, std::vector< WifiPpduRxRecord > > > > m_nodeDeviceLinkRxRecords
Tracks ongoing frames being transmitted or received per node, device, and link.
void EndTx(uint32_t nodeId, uint32_t deviceId, WifiPpduRxRecord ppduRecord)
Handles the conclusion of a transmission event, facilitating the logging of transmission outcomes.
int ContextToDeviceId(std::string context) const
Translates a context string to a device ID, enabling the identification of devices involved in recept...
void CountStatisticsForRecord(WifiPhyTraceStatistics &statistics, const WifiPpduRxRecord &record) const
Update the passed-in statistics object with statistics from the passed-in record.
void PhySignalArrival(std::string context, Ptr< const WifiPpdu > ppdu, double rxPower, Time duration)
Handles the event of a Wi-Fi PPDU arrival.
UniqueTagGenerator m_tagGenerator
Instance of UniqueTagGenerator used for generating unique reception tags.
void SetMapMacAddressToNodeId(const std::map< Mac48Address, uint32_t > &MacAddressToNodeIdMap)
Provides a custom mapping of MAC addresses to intended receiver node IDs.
void UpdateCurrentlyReceivedSignal(uint32_t nodeId, uint32_t deviceId, uint8_t linkId)
Updates the information for signals currently being received by a node.
uint32_t ContextToNodeId(std::string context) const
Translates a context string to a node ID.
int ContextToLinkId(std::string context) const
Translates a context string to a link ID, facilitating the association of events with specific links ...
void MapNodeToLinkToChannel(NodeContainer nodes)
Maps nodes to links and channels, creating a structured association between network elements and thei...
std::map< uint32_t, std::map< uint32_t, std::map< int, std::pair< uint8_t, uint16_t > > > > m_nodeToDeviceToLinkToChannelInfo
Maps node IDs to device IDs and further to link IDs, associating each with a pair consisting of the c...
std::map< uint64_t, uint64_t > m_ppduUidToTxTag
Maps WifiPpdu UIDs to WifiPpduRxRecord tags stored by transmitter.
static TypeId GetTypeId()
Retrieves the TypeId of the class.
This class mimics the TXVECTOR which is to be passed to the PHY in order to define the parameters whi...
Time stopTime
#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:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
int64x64_t operator+(const int64x64_t &lhs, const int64x64_t &rhs)
Addition operator.
Definition: int64x64.h:88
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
WifiPhyRxfailureReason
Enumeration of the possible reception failure reasons.
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:454
bool operator!=(Callback< R, Args... > a, Callback< R, Args... > b)
Inequality test.
Definition: callback.h:674
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:700
bool operator==(const EventId &a, const EventId &b)
Definition: event-id.h:166
bool operator<(const EventId &a, const EventId &b)
Definition: event-id.h:179
@ WIFI_MAC_DATA
@ WIFI_MAC_QOSDATA
const uint32_t SHIFT
Number of places to shift WifiPpdu UID values, when generating unique IDs.
RxSignalInfo structure containing info on the received signal.
Definition: phy-entity.h:69
Keeps track of PHY layer trace statistics.
std::map< WifiPhyRxfailureReason, uint64_t > m_ppduDropReasons
Counts of the drop reasons.
uint64_t m_failedMpdus
Number of failed unicast data MPDU receptions.
uint64_t m_failedPpdus
Number of failed PPDU receptions (with unicast data).
uint64_t m_receivedPpdus
Number of successfully received PPDUs (with unicast data).
uint64_t m_receivedMpdus
Number of successfully received unicast data MPDUs.
uint64_t m_overlappingPpdus
Number of PPDUs that overlapped in time with at least one other PPDU.
uint64_t m_nonOverlappingPpdus
Number of PPDUs that did not overlap in time with any other PPDU.
Structure recording a received PPDU (Physical Protocol Data Unit) in a Wi-Fi network.
Ptr< const WifiPpdu > m_ppdu
Pointer to the received PPDU.
double m_rssi
Received Signal Strength Indicator (RSSI) in dBm.
Time m_endTime
End time of the PPDU reception.
Time m_startTime
Start time of the PPDU reception.
uint8_t m_linkId
The link ID belonging to this record.
WifiPhyRxfailureReason m_reason
Reason for reception failure, if any.
uint32_t m_senderDeviceId
Device ID of Sender.
uint32_t m_senderId
Node ID of the sender.
std::vector< bool > m_statusPerMpdu
Reception status for each MPDU within the PPDU.
std::vector< WifiPpduRxRecord > m_overlappingPpdu
List of PPDUs that overlapped in time with this reception.
uint32_t m_receiverId
Node ID of the receiver.
uint64_t m_rxTag
Unique tag for the reception of this PPDU.