wifi: WifiPhyRxTraceHelper documentation

This commit is contained in:
Tom Henderson
2024-04-12 14:29:52 -04:00
parent 038387315b
commit 8282f5dc83
4 changed files with 239 additions and 1 deletions

View File

@@ -142,6 +142,7 @@ SOURCEFIGS = \
$(SRC)/wifi/doc/source/figures/PhyEntityHierarchy.dia \
$(SRC)/wifi/doc/source/figures/WifiPpduHierarchy.dia \
$(SRC)/wifi/doc/source/figures/FemHierarchy.dia \
$(SRC)/wifi/doc/source/figures/wifi-phy-rx-trace-helper.dia \
$(SRC)/wifi/doc/source/figures/snir.dia \
$(SRC)/wifi/doc/source/figures/ack-su-format.pdf \
$(SRC)/wifi/doc/source/figures/ack-su-format.png \
@@ -389,6 +390,7 @@ IMAGES_EPS = \
$(FIGURES)/PhyEntityHierarchy.eps \
$(FIGURES)/WifiPpduHierarchy.eps \
$(FIGURES)/FemHierarchy.eps \
$(FIGURES)/wifi-phy-rx-trace-helper.eps \
$(FIGURES)/snir.eps \
$(FIGURES)/WimaxArchitecture.eps \
$(FIGURES)/epc-ctrl-arch.eps \

View File

@@ -13,7 +13,8 @@ IMAGES_DIA = \
$(FIGURES)/WifiArchitecture.dia \
$(FIGURES)/PhyEntityHierarchy.dia \
$(FIGURES)/WifiPpduHierarchy.dia \
$(FIGURES)/FemHierarchy.dia
$(FIGURES)/FemHierarchy.dia \
$(FIGURES)/wifi-phy-rx-trace-helper.dia
# specify eps figures from which .png and .pdf figures need to be built
@@ -23,6 +24,7 @@ IMAGES_EPS = \
$(FIGURES)/PhyEntityHierarchy.eps \
$(FIGURES)/WifiPpduHierarchy.eps \
$(FIGURES)/FemHierarchy.eps \
$(FIGURES)/wifi-phy-rx-trace-helper.eps \
$(FIGURES)/assoc-manager.eps \
$(FIGURES)/clear-channel.eps \
$(FIGURES)/emlsr-dl-txop.eps \

View File

@@ -804,6 +804,240 @@ There are many other |ns3| attributes that can be set on the above helpers to
deviate from the default behavior; the example scripts show how to do some of
this reconfiguration.
WifiPhyRxTraceHelper
====================
The ``WifiPhyRxTraceHelper`` can be used to collect statistics and records of Wi-Fi
reception events at the physical layer, such as whether a PPDU was received or was dropped for
some reason, and whether a PPDU overlapped in time (collided) with one or more other PPDUs on the
channel. Two possible types of studies that may be helped by this feature are:
1) Wi-Fi PPDU and MPDU reception outcomes to assess the performance of spatial reuse mechanisms
2) Calculation of airtime fairness between contending stations on a network
The trace helper works by hooking PHY-level traces on the applicable nodes, devices, and
links and maintaining per-receiver records of all of the Wi-Fi PPDUs that are received,
from each receiver's vantage point. These records include a listing of all other PPDUs
that may have overlapped in time and/or frequency for a given PPDU, and the received
signal power of each PPDU involved, and the outcome of the attempt at reception (whether
the PPDU was dropped entirely, or whether the PPDU was partially or fully decoded).
This trace helper collects records of all Wi-Fi PPDus received on every PHY that is enabled
for the helper. As an example, consider the scenario in Figure :ref:`wifi-phy-rx-trace-helper`,
depicting the arrival of three PPDUs that overlap in time. The trace helper keeps a record
of each PPDU arrival, on each enabled PHY, and also keeps track of the PPDUs that collided
with it, if any. In the figure, the first PPDU overlaps in time with both the second and
third PPDU. Likewise, the second PPDU overlaps in time with the first and third PPDUs, and
the third PPDU overlaps in time with the first and second. All of these relationships (each
frame arrival, the frames that overlapped in time with it), from the perspective of each
PHY, are stored in internal data structures. Additionally, the reception outcome of each
PPDU, and its constituent MPDUs, is tracked. This database of reception events can be
exported by the trace helper for fine-grained tabulation of spatial reuse events of interest,
or can be summarized by some built-in statistics printing methods.
.. _wifi-phy-rx-trace-helper:
.. figure:: figures/wifi-phy-rx-trace-helper.*
*WifiPhyRxTraceHelper scenario of interest*
The output of this trace helper is provided in three formats:
1) Built-in print methods to allow printing of key statistics with a single C++ statement,
2) Export of a trace statistics object allowing the user to post-process or format the
data according to the user's formatting choice, and
3) Export of the complete reception records, allowing the user to perform their own
custom processing of the data.
A sample usage of this trace helper is as follows, as demonstrated in the example program
``src/wifi/examples/wifi-phy-rx-trace-helper-example.cc``. First, declare an instance
of it as one might do with other Wi-Fi helpers:
.. sourcecode:: cpp
WifiPhyRxTraceHelper rxTraceHelper;
You may need to include the trace helper's header if it is not otherwise included by the
wifi module header:
.. sourcecode:: cpp
#include "ns3/wifi-phy-rx-trace-helper.h"
Next, enable the trace helper on some subset of the Wi-Fi nodes in the simulation. This step
will hook traces on all of the nodes enabled. It is important to include all of the nodes
within reception range of the nodes of interest, because PPDUs need to be traced at
both transmission and reception times. If you are only interested in statistics or records
on a given receiver, you can later (as explained below) request for only the statistics
of interest. For example, if you are interested in a particular AP, in a particular BSS,
and there is an interfering BSS nearby, you will want to enable all of the nodes within
interference range of the AP of interest (even if not in the same BSS). So, in general,
you will want to ``Enable()`` the trace helper on all Wi-Fi nodes in the simulation,
unless you want to explore pruning this set for runtime scaling reasons.
In this example, we will enable on all of the Wi-Fi nodes:
.. sourcecode:: cpp
NodeContainer c;
c.Create(2);
...
NetDeviceContainer apDevice = wifi.Install(wifiPhy, wifiMac, c.Get(1));
NetDeviceContainer staDevice = wifi.Install(wifiPhy, wifiMac, c.Get(0));
...
rxTraceHelper.Enable(c);
The important thing to note in the above is that ``Enable()`` must be called after
Wi-Fi devices are installed, because it will hook traces on what has been installed
up to that point.
The next configuration aspect is to establish a start and stop time for PPDU reception
collection. In the example program, application data is not sent before 1 second,
and we want to capture all data PPDUs, so the ``Start()`` and ``Stop()`` times are set
as follows:
.. sourcecode:: cpp
rxTraceHelper.Start(Seconds(1));
// The last packet will be sent at time 1 sec. + (numPackets - 1) * interval
// Configure the stop time to be 1 sec. later than this.
Time stopTime = Seconds(1) + (numPackets - 1) * interval + Seconds(1);
rxTraceHelper.Stop(stopTime);
The start and stop times can be tuned to whatever collection window is desired. Furthermore,
there is a ``Reset()`` method that will clear all of the PPDU records and restart collection;
this can be used if one wants to periodically sample the statistics in different time
intervals.
Next, run the simulation, and either during the run or after the simulation has completed,
harvest the statistics. As noted above, there are three main ways to output data.
Furthermore, there are C++ method overloads that allow users to narrow the scope of
output data.
The first option is to use ``PrintStatistics()``, which will dump some statistics with
built-in formatting, such as follows:
.. sourcecode:: cpp
traceHelper.PrintStatistics();
This will result in a number of statistics being printed out. The statistics will
be aggregated for all nodes that are enabled. The following is some of the default
output of the sample program:
.. sourcecode:: text
*** Print statistics for all nodes using built-in print method:
Total PPDUs Received: 1
Total Non-Overlapping PPDUs Received: 1
Total Overlapping PPDUs Received: 0
Successful PPDUs: 1
Failed PPDUs: 0
Total MPDUs: 1
Total Successful MPDUs: 1
Total Failed MPDUs: 0
In the above simple case, there is one PPDU successfully received, and within this PPDU,
there was one MPDU which was successfully decoded. No other PPDUs overlapped in time
with this PPDU.
Although this is a PHY trace helper, there is one important aspect from the MAC layer
that is used to classify PPDUs. When reporting statistics for a given node, a PPDU
is counted only if there was at least one MPDU intended for the node. If the MPDU
has a MAC address that is either broadcast or belongs to the device (unicast), that
PPDU will be counted. If, instead, a receiver locks onto and overhears a PPDU
that ultimately will be discarded because the receiver was not an intended receiver, that
PPDU reception or failure will be excluded from the statistics.
The sample program next shows how ``PrintStatistics`` can take an argument:
.. sourcecode:: cpp
rxTraceHelper.PrintStatistics(c.Get(0)->GetId());
rxTraceHelper.PrintStatistics(c.Get(1));
In the above, the statistics can be limited to a particular node (either passed in
by Node ID or by Node pointer). Furthermore, although not shown in the example,
the method can be further downscoped to also take a device index argument and
(in the case of multi-link operation (MLO)) a specific link ID. In the above example,
all devices and all MLO links will be included in the output.
Users can write their own printing methods or further process the statistics by
calling ``GetStatistics()`` as the following example demonstrates:
.. sourcecode:: cpp
auto stats = rxTraceHelper.GetStatistics();
std::cout << " numOverlapppingPpdu: " << stats.m_numOverlappingPpdu << std::endl;
std::cout << " numNonOverlapppingPpdu: " << stats.m_numNonOverlappingPpdu << std::endl;
std::cout << " numPpduFailed: " << stats.m_numPpduFailed << std::endl;
std::cout << " numPpduSuccess: " << stats.m_numPpduSuccess << std::endl;
std::cout << " numMpduSuccess: " << stats.m_numMpduSuccess << std::endl;
std::cout << " numMpduFailed: " << stats.m_numMpduFailed << std::endl;
Similar to ``PrintStatistics()``, ``GetStatistics()`` with no arguments will collect
a statistics output structure covering all nodes, while additional arguments of
Node ID, device index, and link ID can be used to constrain the statistics report.
Finally, the output of the internal data structure that tracks PPDU receptions can
be exported, with the ``GetPpduRecords()`` method, which can be called
without any arguments, and with arguments of nodeId, deviceId, and linkId:
.. sourcecode:: cpp
auto optionalRecords = rxTraceHelper.GetPpduRecords(1);
The above statements asks for records from receiving node 1 (the AP). The example
iterates the returned vector, printing out the size of this structure, as well
as some data fields:
.. sourcecode:: text
*** Records vector has size of 3
First record:
first PPDU's RSSI (dBm): -30.6633
first PPDU's receiver ID: 1
first PPDU's sender ID: 0
first PPDU's start time: 1
first PPDU's end time: 1.00008
first PPDU's number of MPDUs: 1
first PPDU's sender device ID: 0
Second record:
second PPDU's RSSI (dBm): -30.6633
second PPDU's receiver ID: 1
second PPDU's sender ID: 0
second PPDU's start time: 1.00027
second PPDU's end time: 1.00032
second PPDU's number of MPDUs: 1
second PPDU's sender device ID: 0
Third record:
third PPDU's RSSI (dBm): -30.6633
third PPDU's receiver ID: 1
third PPDU's sender ID: 0
third PPDU's start time: 1.00039
third PPDU's end time: 1.00072
third PPDU's number of MPDUs: 1
third PPDU's sender device ID: 0
That the size of the vector is 3 may be surprising, considering that we have observed
above in this example that only one PPDU is being counted in the statistics. However,
in this example, there is only one data PPDU but also additional management and control
frames. Specifically, the first PPDU is a Block ACK ADDBA_REQUEST frame, the second PPDU
is an ACK of the AP's ADDBA_RESPONSE frame, and the third PPDU record corresponds to the
actual data PPDU, starting at time 1.00039 and ending at 1.00072.
The management and control frames (which also include beacons) are filtered out above by
the ``GetStatistics()`` methods, but when the raw PPDU records are retrieved, all PPDUs
received are available and the user is responsible for further filtering as they see fit.
HT configuration
================