wifi: WifiPhyRxTraceHelper documentation
This commit is contained in:
@@ -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 \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
BIN
src/wifi/doc/source/figures/wifi-phy-rx-trace-helper.dia
Normal file
BIN
src/wifi/doc/source/figures/wifi-phy-rx-trace-helper.dia
Normal file
Binary file not shown.
@@ -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
|
||||
================
|
||||
|
||||
|
||||
Reference in New Issue
Block a user