A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
wifi-tx-stats-helper.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 Huazhong University of Science and Technology
3 * Copyright (c) 2024 University of Washington
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 * Authors: Muyuan Shen <muyuan@uw.edu>
8 * Hao Yin <haoyin@uw.edu>
9 */
10
11#ifndef WIFI_TX_STATS_HELPER_H
12#define WIFI_TX_STATS_HELPER_H
13
14#include "ns3/nstime.h"
15#include "ns3/object.h"
16#include "ns3/qos-utils.h"
17#include "ns3/type-id.h"
18#include "ns3/wifi-mac.h"
19#include "ns3/wifi-types.h"
20#include "ns3/wifi-utils.h"
21
22#include <cstdint>
23#include <functional>
24#include <map>
25#include <string>
26#include <tuple>
27#include <vector>
28
29namespace ns3
30{
31
32class NetDeviceContainer;
33class NodeContainer;
34class Time;
35class Packet;
36class WifiMpdu;
37
38/**
39 * @brief Statistics helper for tracking outcomes of data MPDU transmissions.
40 *
41 * This helper may be used to track statistics of all data MPDU transmissions on a given Node,
42 * WifiNetDevice, or even link granularity (for MLO operation), including counts of the
43 * number of successfully acknowledged MPDUs, the number of retransmissions (if any) of
44 * those successfully acknowledged MPDUs, and the number of failed MPDUs (by drop reason).
45 * The helper can also be used to access timestamped data about how long the MPDU was enqueued
46 * and how long it took to complete acknowledgement (or failure) once the first transmission
47 * of it was attempted. For failed MPDUs, their WifiMacDropReason can be accessed.
48 */
50{
51 public:
52 /**
53 * When Multi-Link Operation (MLO) is used, it is possible for MPDUs to be sent on
54 * multiple links concurrently. When such an MPDU is acked, a question arises as to how
55 * to count the number of successes (only one success, or success on each link). The
56 * ACK does not convey which transmission on which link triggered the event. Therefore,
57 * two policies are defined for how to count a successful event.
58 * 1) FIRST_LINK_IN_SET: Count the success on the first link of the set of in-flight links
59 * 2) ALL_LINKS: Count the success on all links in the in-flight link set
60 */
66
67 /**
68 * Structure for recording information about an individual data MPDU transmission.
69 */
71 {
72 uint32_t m_nodeId{std::numeric_limits<uint32_t>::max()}; //!< The sending node ID
73 uint32_t m_deviceId{std::numeric_limits<uint32_t>::max()}; //!< The sending device ID
74 Time m_enqueueTime; //!< The enqueue time (time that the packet was added to a WifiMacQueue)
75 Time m_txStartTime; //!< The time at which the MPDU was first transmitted
76 std::optional<Time> m_dropTime; //!< The time of removal from the WifiMacQueue, if failed
77 Time m_ackTime; //!< The time at which the MPDU was acknowledged
78 uint64_t m_mpduSeqNum{0}; //!< The MPDU sequence number
79 uint32_t m_retransmissions{0}; //!< A count of the number of retransmissions of the MPDU
80 uint8_t m_tid{WIFI_TID_UNDEFINED}; //!< The TID for the MPDU
81 std::set<uint8_t> m_successLinkIdSet; //!< If acked, the set of in-flight link ID(s)
82 std::optional<WifiMacDropReason> m_dropReason; //!< If failed, the drop reason
83 };
84
85 /**
86 * Default constructor; start time initialized to zero and stop time to Time::Max()
87 */
89 /**
90 * Construct a helper with start and stop times. Only those MPDUs
91 * enqueued between the start and stop times will be counted.
92 *
93 * @param startTime The measurement start time
94 * @param stopTime The measurement stop time
95 */
97
98 /**
99 * Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
100 * @param nodes The NodeContainer to which traces are to be connected.
101 */
102 void Enable(const NodeContainer& nodes);
103 /**
104 * Enables trace collection for all WifiNetDevices in the specified NetDeviceContainer.
105 * @param devices The NetDeviceContainer to which traces are to be connected.
106 */
107 void Enable(const NetDeviceContainer& devices);
108 /**
109 * @brief Set the start time for statistics collection
110 *
111 * No MPDUs enqueued before startTime will be included
112 * in the statistics.
113 *
114 * @param startTime The measurement start time
115 */
116 void Start(Time startTime);
117 /**
118 * @brief Set the stop time for statistics collection
119 *
120 * No MPDUs enqueued after stopTime elapses will be included in
121 * statistics. However, MPDUs that were enqueued before stopTime
122 * (and after startTime) will be included in the statistics if
123 * they are dequeued before the statistics are queried by the user.
124 *
125 * @param stopTime The measurement stop time
126 */
127 void Stop(Time stopTime);
128 /**
129 * @brief Clear the data structures for all completed successful and failed MpduRecords
130 */
131 void Reset();
132
133 //
134 // Hash function and unordered maps
135 //
136
137 /**
138 * Hash function for the tuples used in unordered_maps
139 */
141 {
142 /**
143 * Combines two hash values into one (similar to boost::hash_combine)
144 * @param seed the starting hash point
145 * @param value the value to combine to the hash
146 */
147 template <typename T>
148 void hash_combine(size_t& seed, const T& value) const
149 {
150 seed ^= std::hash<T>{}(value) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
151 }
152
153 /**
154 * Hash function for tuples of arbitrary size
155 * @param tuple the input Tuple
156 * @return the hash of the tuple elements
157 */
158 template <typename Tuple, size_t Index = 0>
159 size_t tuple_hash(const Tuple& tuple) const
160 {
161 if constexpr (Index < std::tuple_size<Tuple>::value)
162 {
163 size_t seed = tuple_hash<Tuple, Index + 1>(tuple);
164 hash_combine(seed, std::get<Index>(tuple));
165 return seed;
166 }
167 else
168 {
169 return 0; // Base case
170 }
171 }
172
173 /**
174 * Operator overload for calculating hash of tuple
175 * @param tuple the input Tuple
176 * @return the hash of the tuple elements
177 */
178 template <typename... Args>
179 size_t operator()(const std::tuple<Args...>& tuple) const
180 {
181 return tuple_hash(tuple);
182 }
183 };
184
186 std::unordered_map<std::tuple<uint32_t, uint32_t, uint8_t>,
187 uint64_t,
188 TupleHash>; //!< std::unordered_map of {nodeId, deviceId, linkId} tuple
189 //!< to counter value
191 std::unordered_map<std::tuple<uint32_t, uint32_t>,
192 uint64_t,
193 TupleHash>; //!< std::unordered_map of {nodeId, deviceId} tuple to
194 //!< counter value
196 std::unordered_map<std::tuple<uint32_t, uint32_t, uint8_t>,
197 std::list<MpduRecord>,
198 TupleHash>; //!< std::unordered_map of {nodeId, deviceId, linkId} tuple
199 //!< to a list of MPDU records
201 std::unordered_map<std::tuple<uint32_t, uint32_t>,
202 std::list<MpduRecord>,
203 TupleHash>; //!< std::unordered_map of {nodeId, deviceId} tuple to a list
204 //!< of MPDU records
205
206 //
207 // Methods to retrieve the counts tabulated by this helper
208 //
209
210 /**
211 * @brief Return the counts of successful MPDU transmissions in a hash map
212 *
213 * The return type is an std::unordered_map, and the keys are tuples of {node ID,
214 * device ID}. The value returned by indexing the tuple is the count of
215 * successful MPDU transmissions.
216 *
217 * If Multi-Link Operation (MLO) is configured, a variant of this method is available
218 * that returns an unordered_map indexed by a tuple that includes the Link ID, for
219 * more granular statistics reporting.
220 * @see GetSuccessesByNodeDeviceLink
221 *
222 * If Multi-Link Operation (MLO) is configured, and MPDUs are sent on multiple
223 * links in parallel, this method will count one success for any such acknowledged
224 * MPDU (even if it was successfully received on more than one link).
225 *
226 * @return A hash map with counts of MPDU successful transmissions
227 */
229 /**
230 * @brief Return the counts of successful MPDU transmissions in a hash map
231 * @param type how the statistics handle a successful MPDU transmitted on multiple links
232 *
233 * The return type is an std::unordered_map, and the keys are tuples of {node ID,
234 * device ID, link ID}. The value returned by indexing the tuple is the count of
235 * successful MPDU transmissions.
236 *
237 * The link ID corresponds to the link for which the MPDU was successfully
238 * acknowledged, regardless of the links that may have been used in
239 * earlier transmissions of the MPDU.
240 *
241 * For a similar method that does not use Link IDs in the key,
242 * @see GetSuccessesByNodeDevice
243 *
244 * @return A hash map with counts of MPDU successful transmissions
245 */
248 /**
249 * @brief Return the counts of failed MPDU transmissions in a hash map
250 *
251 * The return type is an std::unordered_map, and the keys are tuples of {node ID,
252 * device ID}. The value returned by indexing the tuple is the count of
253 * failed MPDU transmissions.
254 *
255 * The number of failures are only stored with the granularity
256 * of per-device, since in a multi-link scenario, some retransmissions
257 * (that lead to eventual failure) may occur on different links.
258 *
259 * @return A hash map with counts of MPDU failed transmissions
260 */
262 /**
263 * @brief Return the counts of failed MPDU transmissions due to given drop reason in a hash map
264 * @param reason Reason for dropping the MPDU
265 *
266 * The return type is an std::unordered_map, and the keys are tuples of {node ID,
267 * device ID}. The value returned by indexing the tuple is the count of
268 * failed MPDU transmissions due to the reason given.
269 *
270 * The number of failures are only stored with the granularity
271 * of per-device, since in a multi-link scenario, some retransmissions
272 * (that lead to eventual failure) may occur on different links.
273 *
274 * @return A hash map with counts of MPDU failed transmissions
275 */
277 /**
278 * @brief Return the counts of MPDU retransmissions in a hash map
279 *
280 * The return type is an std::unordered_map, and the keys are tuples of {node ID,
281 * device ID}. The value returned by indexing the tuple is the count of
282 * MPDU retransmissions of those MPDUs that were successfully acked.
283 *
284 * The number of retransmissions are only stored with the granularity
285 * of per-device, since in a multi-link scenario, some retransmissions
286 * may be sent on different links.
287 *
288 * @return A hash map with counts of MPDU retransmissions for successful MPDUs
289 */
291 /**
292 * @brief Return the count of successful MPDU transmissions across all enabled devices
293 *
294 * @return The count of all successful MPDU transmissions
295 */
296 uint64_t GetSuccesses() const;
297 /**
298 * @brief Return the count of failed MPDU transmissions across all enabled devices
299 *
300 * @return The count of all failed MPDU transmissions
301 */
302 uint64_t GetFailures() const;
303 /**
304 * @brief Return the count of failed MPDU transmissions due to given drop reason across
305 * all enabled devices
306 * @param reason Reason for dropping the MPDU
307 *
308 * @return The count of all failed MPDU transmissions for the specified reason
309 */
310 uint64_t GetFailures(WifiMacDropReason reason) const;
311 /**
312 * @brief Return the count of MPDU retransmissions across all enabled devices
313 *
314 * @return The count of all MPDU retransmissions for acked MPDUs
315 */
316 uint64_t GetRetransmissions() const;
317 /**
318 * @brief Return the duration since the helper was started or reset
319 *
320 * @return The duration since the helper was started or reset
321 */
322 Time GetDuration() const;
323 /**
324 * @brief Return a hash map of successful MPDU records
325 * @param type how the statistics handle a successful MPDU transmitted on multiple links
326 *
327 * The return type is an std::unordered_map, and the keys are tuples of {node ID,
328 * device ID, link ID}. The value returned by indexing the tuple is the list of MPDU
329 * records of the MPDUs that were successfully acked.
330 *
331 * @return A const reference to the hash map of successful MPDU records
332 */
335 /**
336 * @brief Return a hash map of MPDU records for failed transmissions
337 *
338 * The return type is an std::unordered_map, and the keys are tuples of {node ID,
339 * device ID}. The value returned by indexing the tuple is the list of MPDU
340 * records of the MPDUs that failed.
341 *
342 * @return A const reference to the hash map of MPDU records corresponding to failure
343 */
345
346 private:
347 /**
348 * @brief Callback for the WifiMacQueue::Enqueue trace
349 * @param nodeId the Node ID triggering the trace
350 * @param deviceId the Node ID triggering the trace
351 * @param mpdu The MPDU enqueued
352 */
353 void NotifyMacEnqueue(uint32_t nodeId, uint32_t deviceId, Ptr<const WifiMpdu> mpdu);
354 /**
355 * @brief Callback for the WifiPhy::PhyTxBegin trace
356 * @param nodeId the Node ID triggering the trace
357 * @param deviceId the Node ID triggering the trace
358 * @param pkt The frame being sent
359 */
360 void NotifyTxStart(uint32_t nodeId, uint32_t deviceId, Ptr<const Packet> pkt, Watt_u);
361 /**
362 * @brief Callback for the WifiMac::AckedMpdu trace
363 * @param nodeId the Node ID triggering the trace
364 * @param deviceId the Node ID triggering the trace
365 * @param mpdu The MPDU acked
366 */
367 void NotifyAcked(uint32_t nodeId, uint32_t deviceId, Ptr<const WifiMpdu> mpdu);
368 /**
369 * @brief Callback for the WifiMac::DroppedMpdu trace
370 * @param nodeId the Node ID triggering the trace
371 * @param deviceId the Node ID triggering the trace
372 * @param reason Reason for dropping the MPDU
373 * @param mpdu The MPDU dropped
374 */
375 void NotifyMacDropped(uint32_t nodeId,
376 uint32_t deviceId,
377 WifiMacDropReason reason,
379
380 MpduRecordsPerNodeDevice_t m_successMap; //!< The nested map of successful MPDUs
381 MpduRecordsPerNodeDevice_t m_failureMap; //!< The nested map of failed MPDUs
382 std::map<uint64_t, MpduRecord> m_inflightMap; //!< In-flight MPDUs; key is a Packet UID
383 Time m_startTime; //!< The start time for recording statistics
384 Time m_stopTime{Time::Max()}; //!< The stop time for recording statistics
385};
386
387} // namespace ns3
388
389#endif // WIFI_TX_STATS_HELPER_H
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
Smart pointer class similar to boost::intrusive_ptr.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
static Time Max()
Maximum representable Time Not to be confused with Max(Time,Time).
Definition nstime.h:286
Statistics helper for tracking outcomes of data MPDU transmissions.
Time m_stopTime
The stop time for recording statistics.
MpduRecordsPerNodeDevice_t m_successMap
The nested map of successful MPDUs.
void Reset()
Clear the data structures for all completed successful and failed MpduRecords.
std::unordered_map< std::tuple< uint32_t, uint32_t >, std::list< MpduRecord >, TupleHash > MpduRecordsPerNodeDevice_t
std::unordered_map of {nodeId, deviceId} tuple to a list of MPDU records
std::map< uint64_t, MpduRecord > m_inflightMap
In-flight MPDUs; key is a Packet UID.
void NotifyAcked(uint32_t nodeId, uint32_t deviceId, Ptr< const WifiMpdu > mpdu)
Callback for the WifiMac::AckedMpdu trace.
CountPerNodeDeviceLink_t GetSuccessesByNodeDeviceLink(WifiTxStatsHelper::MultiLinkSuccessType type=FIRST_LINK_IN_SET) const
Return the counts of successful MPDU transmissions in a hash map.
MultiLinkSuccessType
When Multi-Link Operation (MLO) is used, it is possible for MPDUs to be sent on multiple links concur...
void Stop(Time stopTime)
Set the stop time for statistics collection.
void NotifyTxStart(uint32_t nodeId, uint32_t deviceId, Ptr< const Packet > pkt, Watt_u)
Callback for the WifiPhy::PhyTxBegin trace.
uint64_t GetFailures() const
Return the count of failed MPDU transmissions across all enabled devices.
WifiTxStatsHelper()
Default constructor; start time initialized to zero and stop time to Time::Max()
Time m_startTime
The start time for recording statistics.
void NotifyMacEnqueue(uint32_t nodeId, uint32_t deviceId, Ptr< const WifiMpdu > mpdu)
Callback for the WifiMacQueue::Enqueue trace.
std::unordered_map< std::tuple< uint32_t, uint32_t, uint8_t >, uint64_t, TupleHash > CountPerNodeDeviceLink_t
std::unordered_map of {nodeId, deviceId, linkId} tuple to counter value
CountPerNodeDevice_t GetFailuresByNodeDevice() const
Return the counts of failed MPDU transmissions in a hash map.
std::unordered_map< std::tuple< uint32_t, uint32_t >, uint64_t, TupleHash > CountPerNodeDevice_t
std::unordered_map of {nodeId, deviceId} tuple to counter value
const MpduRecordsPerNodeDeviceLink_t GetSuccessRecords(WifiTxStatsHelper::MultiLinkSuccessType type=FIRST_LINK_IN_SET) const
Return a hash map of successful MPDU records.
const MpduRecordsPerNodeDevice_t & GetFailureRecords() const
Return a hash map of MPDU records for failed transmissions.
CountPerNodeDevice_t GetSuccessesByNodeDevice() const
Return the counts of successful MPDU transmissions in a hash map.
MpduRecordsPerNodeDevice_t m_failureMap
The nested map of failed MPDUs.
uint64_t GetSuccesses() const
Return the count of successful MPDU transmissions across all enabled devices.
void NotifyMacDropped(uint32_t nodeId, uint32_t deviceId, WifiMacDropReason reason, Ptr< const WifiMpdu > mpdu)
Callback for the WifiMac::DroppedMpdu trace.
void Enable(const NodeContainer &nodes)
Enables trace collection for all nodes and WifiNetDevices in the specified NodeContainer.
CountPerNodeDevice_t GetRetransmissionsByNodeDevice() const
Return the counts of MPDU retransmissions in a hash map.
uint64_t GetRetransmissions() const
Return the count of MPDU retransmissions across all enabled devices.
void Start(Time startTime)
Set the start time for statistics collection.
std::unordered_map< std::tuple< uint32_t, uint32_t, uint8_t >, std::list< MpduRecord >, TupleHash > MpduRecordsPerNodeDeviceLink_t
std::unordered_map of {nodeId, deviceId, linkId} tuple to a list of MPDU records
Time GetDuration() const
Return the duration since the helper was started or reset.
Time stopTime
WifiMacDropReason
The reason why an MPDU was dropped.
Definition wifi-mac.h:71
NodeContainer nodes
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition nstime.h:864
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static constexpr uint8_t WIFI_TID_UNDEFINED
Invalid TID identifier.
Definition wifi-utils.h:278
Structure for recording information about an individual data MPDU transmission.
uint32_t m_deviceId
The sending device ID.
uint32_t m_nodeId
The sending node ID.
uint64_t m_mpduSeqNum
The MPDU sequence number.
Time m_ackTime
The time at which the MPDU was acknowledged.
uint32_t m_retransmissions
A count of the number of retransmissions of the MPDU.
Time m_enqueueTime
The enqueue time (time that the packet was added to a WifiMacQueue)
std::set< uint8_t > m_successLinkIdSet
If acked, the set of in-flight link ID(s)
std::optional< WifiMacDropReason > m_dropReason
If failed, the drop reason.
std::optional< Time > m_dropTime
The time of removal from the WifiMacQueue, if failed.
Time m_txStartTime
The time at which the MPDU was first transmitted.
uint8_t m_tid
The TID for the MPDU.
Hash function for the tuples used in unordered_maps.
size_t operator()(const std::tuple< Args... > &tuple) const
Operator overload for calculating hash of tuple.
size_t tuple_hash(const Tuple &tuple) const
Hash function for tuples of arbitrary size.
void hash_combine(size_t &seed, const T &value) const
Combines two hash values into one (similar to boost::hash_combine)