From 8d25ef3c21ce5b6a3084e23159505ef667aef821 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Wed, 5 Jul 2023 18:49:04 -0700 Subject: [PATCH 001/262] Start RELEASE_NOTES.md and CHANGES.md sections for new release --- CHANGES.md | 11 +++++++++++ RELEASE_NOTES.md | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index a56da96e1..c938c6944 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,17 @@ Note that users who upgrade the simulator across versions, or who work directly This file is a best-effort approach to solving this issue; we will do our best but can guarantee that there will be things that fall through the cracks, unfortunately. If you, as a user, can suggest improvements to this file based on your experience, please contribute a patch or drop us a note on ns-developers mailing list. +Changes from ns-3.39 to ns-3-dev +-------------------------------- + +### New API + +### Changes to existing API + +### Changes to build system + +### Changed behavior + Changes from ns-3.38 to ns-3.39 ------------------------------- diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index e046153aa..70b18f584 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -13,6 +13,15 @@ a [GitLab.com issue tracker](https://gitlab.com/nsnam/ns-3-dev/-/issues) number, and references prefixed by '!' refer to a [GitLab.com merge request](https://gitlab.com/nsnam/ns-3-dev/-/merge_requests) number. +Release 3-dev +------------- + +### Supported platforms + +### New user-visible features + +### Bugs fixed + Release 3.39 ------------ From d4010dce20826eef2e6bf1c67bd303d3b653265c Mon Sep 17 00:00:00 2001 From: Gabriel Ferreira Date: Fri, 7 Jul 2023 11:35:17 -0300 Subject: [PATCH 002/262] ci: fix pip packaging issue --- utils/tests/gitlab-ci-cppyy.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/utils/tests/gitlab-ci-cppyy.yml b/utils/tests/gitlab-ci-cppyy.yml index 63d0d63bb..b138b876c 100644 --- a/utils/tests/gitlab-ci-cppyy.yml +++ b/utils/tests/gitlab-ci-cppyy.yml @@ -104,16 +104,16 @@ cppyy-18.04: - $PYTHON -m venv ./venv - . ./venv/bin/activate # Upgrade the pip version to reuse the pre-build cppyy - - $PYTHON -m pip install pip --upgrade - - $PYTHON -m pip install setuptools setuptools_scm wheel --upgrade - - $PYTHON -m pip install wheel auditwheel cmake-build-extension cppyy==2.4.2 + - python -m pip install pip --upgrade + - python -m pip install setuptools setuptools_scm wheel --upgrade + - python -m pip install auditwheel cmake-build-extension cppyy==2.4.2 # Configure and build wheel - - $PYTHON setup.py bdist_wheel build_ext - - export EXCLUDE_INTERNAL_LIBRARIES=`$PYTHON ./build-support/pip-wheel/auditwheel-exclude-list.py` + - python setup.py bdist_wheel build_ext + - export EXCLUDE_INTERNAL_LIBRARIES=`python ./build-support/pip-wheel/auditwheel-exclude-list.py` # Bundle in shared libraries that were not explicitly packaged or depended upon - - $PYTHON -m auditwheel repair ./dist/*whl -L /lib64 $EXCLUDE_INTERNAL_LIBRARIES + - python -m auditwheel repair ./dist/*whl -L /lib64 $EXCLUDE_INTERNAL_LIBRARIES # Clean the build directory - - $PYTHON ./ns3 clean + - python ./ns3 clean # Clean up the environment - deactivate - rm -R ./venv From 45d7be2cd62e5f29174fdcee2b1eb05bd09367a0 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Thu, 6 Jul 2023 10:37:42 -0700 Subject: [PATCH 003/262] core: Add deprecated for ns-3.40 --- src/core/model/deprecated.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/model/deprecated.h b/src/core/model/deprecated.h index 7401151ef..36a787d6e 100644 --- a/src/core/model/deprecated.h +++ b/src/core/model/deprecated.h @@ -74,6 +74,13 @@ */ #define NS_DEPRECATED(msg) [[deprecated(msg)]] +/** + * \ingroup core + * \def NS_DEPRECATED_3_40 + * Tag for things deprecated in version ns-3.40. + */ +#define NS_DEPRECATED_3_40(msg) NS_DEPRECATED(msg) + /** * \ingroup core * \def NS_DEPRECATED_3_39 From fd5c76a0cb96fc4ccb8c6574c8637476f49db657 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Thu, 6 Jul 2023 11:19:13 -0700 Subject: [PATCH 004/262] doc: (fixes #923) Instructions on installation to privileged directories --- doc/installation/source/quick-start.rst | 29 ++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/doc/installation/source/quick-start.rst b/doc/installation/source/quick-start.rst index bb7813883..1cae262e2 100644 --- a/doc/installation/source/quick-start.rst +++ b/doc/installation/source/quick-start.rst @@ -42,7 +42,7 @@ source archive download (via a web browser, ``wget``, or ``curl``). | | or ``tar`` and ``bunzip2`` | No minimum version | | | (for Web download) | | +--------------------+--------------------------------------+------------------------------+ - | **Compiler** | ``g++`` | >= 8 | + | **Compiler** | ``g++`` | >= 9 | + + + + | | or ``clang++`` | >= 10 | +--------------------+--------------------------------------+------------------------------+ @@ -177,3 +177,30 @@ since CMake enables |ns3| integration with a variety of code editors, including: * Apple's XCode * CodeBlocks * Eclipse CDT4 + +Installing ns-3 +*************** + +Most users do not install |ns3| libraries to typical system library directories; they instead +just leave the libraries in the ``build`` directory, and the ``ns3`` Python program will +find these libraries. However, it is possible to perform an installation step-- ``ns3 install``-- +with the following caveats. + +The location of the installed libraries is set by the ``--prefix`` option specified at the +configure step. The prefix defaults to ``/usr/local``. For a given ``--prefix=$PREFIX``, +the installation step will install headers to a ``$PREFIX/include`` directory, libraries +and pkgconfig files to a ``$PREFIX/lib`` directory, and a few binaries to a +``$PREFIX/libexec`` directory. For example, ``./ns3 configure --prefix=/tmp``, followed +by ``./ns3 build`` and ``./ns3 install``, will lead to files being installed in +``/tmp/include``, ``/tmp/lib``, and ``/tmp/libexec``. + +Note that the ``ns3`` script prevents running the script as root (or as a sudo user). As a +result, with the default prefix of ``/usr/local``, the installation will fail unless the +user has write privileges in that directory. Attempts to force this with +``sudo ./ns3 install`` will fail due to a check in the ``ns3`` program that prevents running +as root. This check was installed by |ns3| maintainers for the safety of novice users who may +run ``./ns3`` in a root shell and later in a normal shell, and become confused about errors +resulting in lack of privileges to modify files. For users who know what they are doing and +who want to install to a privileged directory, users can comment out the statement +``refuse_run_as_root()`` in the ``ns3`` program (around line 1400), and then run +``sudo ./ns3 install``. From 0d00070a732765294e888e5dd7d241a74567821f Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Thu, 6 Jul 2023 12:21:08 -0700 Subject: [PATCH 005/262] doc: Apply consistent sourcecode formatting directive --- src/wifi/doc/source/wifi-user.rst | 132 +++++++++++++++++++++--------- 1 file changed, 93 insertions(+), 39 deletions(-) diff --git a/src/wifi/doc/source/wifi-user.rst b/src/wifi/doc/source/wifi-user.rst index 0f4a47455..d900f07a3 100644 --- a/src/wifi/doc/source/wifi-user.rst +++ b/src/wifi/doc/source/wifi-user.rst @@ -55,7 +55,9 @@ To create a WifiNetDevice, users need to follow these steps: are needed for propagation loss calculations. The following sample code illustrates a typical configuration using mostly -default values in the simulator, and infrastructure mode:: +default values in the simulator, and infrastructure mode: + +.. sourcecode:: cpp NodeContainer wifiStaNode; wifiStaNode.Create(10); // Create 10 station node objects @@ -98,7 +100,9 @@ named this way. The reference is to the `yans simulator helper can be used to create a YansWifiChannel with a default PropagationLoss and PropagationDelay model. -Users will typically type code such as:: +Users will typically type code such as: + +.. sourcecode:: cpp YansWifiChannelHelper wifiChannelHelper = YansWifiChannelHelper::Default(); Ptr wifiChannel = wifiChannelHelper.Create(); @@ -133,7 +137,9 @@ the ``YansWifiPhyHelper`` will do the work. The YansWifiPhyHelper class configures an object factory to create instances of a ``YansWifiPhy`` and adds some other objects to it, including possibly a supplemental ErrorRateModel and a pointer to a MobilityModel. The user code is -typically:: +typically: + +.. sourcecode:: cpp YansWifiPhyHelper wifiPhyHelper; wifiPhyHelper.SetChannel(wifiChannel); @@ -143,7 +149,9 @@ The default YansWifiPhyHelper is configured with TableBasedErrorRateModel calling the ``YansWifiPhyHelper::SetErrorRateModel`` method. Optionally, if pcap tracing is needed, a user may use the following -command to enable pcap tracing:: +command to enable pcap tracing: + +.. sourcecode:: cpp YansWifiPhyHelper::SetPcapDataLinkType(enum SupportedPcapDataLinkTypes dlt) @@ -154,14 +162,18 @@ prepared the YansWifiPhyHelper by telling it which channel it is connected to. The Phy objects are created in the next step. In order to enable 802.11n/ac/ax MIMO, the number of antennas as well as the number of supported spatial streams need to be configured. -For example, this code enables MIMO with 2 antennas and 2 spatial streams:: +For example, this code enables MIMO with 2 antennas and 2 spatial streams: + +.. sourcecode:: cpp wifiPhyHelper.Set("Antennas", UintegerValue(2)); wifiPhyHelper.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); wifiPhyHelper.Set("MaxSupportedRxSpatialStreams", UintegerValue(2)); It is also possible to configure less streams than the number of antennas in order to benefit from diversity gain, and to define different MIMO capabilities for downlink and uplink. -For example, this code configures a node with 3 antennas that supports 2 spatial streams in downstream and 1 spatial stream in upstream:: +For example, this code configures a node with 3 antennas that supports 2 spatial streams in downstream and 1 spatial stream in upstream: + +.. sourcecode:: cpp wifiPhyHelper.Set("Antennas", UintegerValue(3)); wifiPhyHelper.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); @@ -169,7 +181,7 @@ For example, this code configures a node with 3 antennas that supports 2 spatial 802.11n PHY layer can support both 20 (default) or 40 MHz channel width, and 802.11ac/ax PHY layer can use either 20, 40, 80 (default) or 160 MHz channel width. See below for further documentation on setting the frequency, channel width, and channel number. -:: +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211ac); @@ -207,13 +219,13 @@ providing either a StringValue object or a TupleValue object: * Defining a StringValue object to set the ``ChannelSettings`` attribute -:: +.. sourcecode:: cpp StringValue value("{38, 40, BAND_5GHZ, 0}")); * Defining a TupleValue object to set the ``ChannelSettings`` attribute -:: +.. sourcecode:: cpp TupleValue value; value.Set(WifiPhy::ChannelTuple {38, 40, WIFI_PHY_BAND_5GHZ, 0}); @@ -226,13 +238,13 @@ The operating channel settings can then be configured in a number of ways: * by setting global configuration default; e.g. -:: +.. sourcecode:: cpp Config::SetDefault("ns3::WifiPhy::ChannelSettings", StringValue("{38, 40, BAND_5GHZ, 0}")); * by setting an attribute value in the helper; e.g. -:: +.. sourcecode:: cpp TupleValue value; value.Set(WifiPhy::ChannelTuple {38, 40, WIFI_PHY_BAND_5GHZ, 0}); @@ -244,7 +256,7 @@ The operating channel settings can then be configured in a number of ways: * by performing post-installation configuration of the option, either via a Ptr to the WifiPhy object, or through the Config namespace; e.g.: -:: +.. sourcecode:: cpp Config::Set("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phy/$ns3::WifiPhy/ChannelSettings", StringValue("{38, 40, BAND_5GHZ, 0}")); @@ -263,7 +275,7 @@ band can only be configured if the standard is 802.11ax (or beyond). The following values for WifiStandard are defined in ``src/wifi/model/wifi-standards.h``: -:: +.. sourcecode:: cpp WIFI_STANDARD_80211a, WIFI_STANDARD_80211b, @@ -308,7 +320,7 @@ as soon as the WifiStandard is set. Here are the rules (applied in the given ord Following are a few examples to clarify these rules: -:: +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211ac); @@ -317,7 +329,7 @@ Following are a few examples to clarify these rules: // channel width unspecified // -> it is set to 80 MHz (width of channel 58) -:: +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211n); @@ -326,7 +338,7 @@ Following are a few examples to clarify these rules: // channel number unspecified // -> it is set to channel 38 (first 40 MHz channel in the 5GHz band) -:: +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211ax); @@ -336,7 +348,7 @@ Following are a few examples to clarify these rules: // -> width set to 20 MHz (default width for 802.11ax in the 2.4 GHZ band) // -> channel number set to 1 (first 20 MHz channel in the 2.4 GHz band) -:: +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211a); @@ -455,7 +467,7 @@ WifiPhy object. If an unknown channel number (other than zero) is configured, the simulator will exit with an error; for instance, such as: -:: +.. sourcecode:: cpp Ptr wifiPhy = ...; wifiPhy->SetAttribute("ChannelSettings", StringValue("{1321, 20, BAND_5GHZ, 0}")); @@ -468,7 +480,7 @@ If a known channel number is configured against an incorrect value of the WifiPhyStandard, the simulator will exit with an error; for instance, such as: -:: +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211n); @@ -508,7 +520,9 @@ of type ``ns3::YansWifiChannel`` must be used with it. Its API has been extended for 802.11be multi-link and EMLSR in order to attach multiple spectrum channels to a same PHY. For that purpose, a user may use the following command to attach a spectrum channel to the PHY objects -that will be created upon a call to ``ns3::WifiHelper::Install``:: +that will be created upon a call to ``ns3::WifiHelper::Install``: + +.. sourcecode:: cpp SpectrumWifiPhyHelper::SetPcapDataLinkType(const Ptr channel, const FrequencyRange& freqRange) @@ -528,7 +542,9 @@ By default, it creates an ad-hoc MAC instance that does not have 802.11e/WMM-sty nor 802.11ac-style Very High Throughput (VHT) nor 802.11ax-style High Efficiency (HE) support enabled. For example the following user code configures a non-QoS and non-HT/non-VHT/non-HE MAC that -will be a non-AP STA in an infrastructure network where the AP has SSID ``ns-3-ssid``:: +will be a non-AP STA in an infrastructure network where the AP has SSID ``ns-3-ssid``: + +.. sourcecode:: cpp WifiMacHelper wifiMacHelper; Ssid ssid = Ssid("ns-3-ssid"); @@ -536,7 +552,9 @@ will be a non-AP STA in an infrastructure network where the AP has SSID ``ns-3-s "Ssid", SsidValue(ssid), "ActiveProbing", BooleanValue(false)); -The following code shows how to create an AP with QoS enabled:: +The following code shows how to create an AP with QoS enabled: + +.. sourcecode:: cpp WifiMacHelper wifiMacHelper; wifiMacHelper.SetType("ns3::ApWifiMac", @@ -563,7 +581,9 @@ For MAC instances that have QoS support enabled, the ``ns3::WifiMacHelper`` can * block ack inactivity timeout. For example the following user code configures a MAC that will be a non-AP STA with QoS enabled and a block ack threshold for AC_BE set to 2 packets, -in an infrastructure network where the AP has SSID ``ns-3-ssid``:: +in an infrastructure network where the AP has SSID ``ns-3-ssid``: + +.. sourcecode:: cpp WifiMacHelper wifiMacHelper; Ssid ssid = Ssid("ns-3-ssid"); @@ -582,7 +602,9 @@ the ``ns3::WifiMacHelper`` can be also used to set: By default, MSDU aggregation feature is disabled for all ACs and MPDU aggregation is enabled for AC_VI and AC_BE, with a maximum aggregation size of 65535 bytes. For example the following user code configures a MAC that will be a non-AP STA with HT and QoS enabled, MPDU aggregation enabled for AC_VO with a maximum aggregation size of 65535 bytes, and MSDU aggregation enabled for AC_BE with a maximum aggregation size of 7935 bytes, -in an infrastructure network where the AP has SSID ``ns-3-ssid``:: +in an infrastructure network where the AP has SSID ``ns-3-ssid``: + +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211n); @@ -597,7 +619,9 @@ in an infrastructure network where the AP has SSID ``ns-3-ssid``:: 802.11ax APs support sending multi-user frames via DL OFDMA and UL OFDMA if a Multi-User Scheduler is aggregated to the wifi MAC(by default no scheduler is aggregated). WifiMacHelper enables to aggregate -a Multi-User Scheduler to an AP and set its parameters:: +a Multi-User Scheduler to an AP and set its parameters: + +.. sourcecode:: cpp WifiMacHelper wifiMacHelper; wifiMacHelper.SetMultiUserScheduler("ns3::RrMultiUserScheduler", @@ -606,7 +630,9 @@ a Multi-User Scheduler to an AP and set its parameters:: The Ack Manager is in charge of selecting the acknowledgment method among the three available methods(see section :ref:`wifi-mu-ack-sequences` ). The default ack manager -enables to select the acknowledgment method, e.g.:: +enables to select the acknowledgment method, e.g.: + +.. sourcecode:: cpp Config::SetDefault("ns3::WifiDefaultAckManager::DlMuAckSequenceType", EnumValue(WifiAcknowledgment::DL_MU_AGGREGATE_TF)); @@ -620,7 +646,9 @@ value of the DS field in the IP header of the packet (ToS field in case of IPv4, Traffic Class field in case of IPv6). Details on how to set the ToS field of IPv4 packets are given in the :ref:`Type-of-service` section of the documentation. In summary, users can create an address of type :cpp:class:`ns3::InetSocketAddress` -with the desired type of service value and pass it to the application helpers:: +with the desired type of service value and pass it to the application helpers: + +.. sourcecode:: cpp InetSocketAddress destAddress(ipv4Address, udpPort); destAddress.SetTos(tos); @@ -674,7 +702,9 @@ CS6 110000xx 6 AC_VO CS7 111000xx 7 AC_VO ============ ============ == =============== -So, for example,:: +So, for example, + +.. sourcecode:: cpp destAddress.SetTos(0xc0); @@ -696,7 +726,9 @@ WifiHelper ========== We're now ready to create WifiNetDevices. First, let's create -a WifiHelper with default settings:: +a WifiHelper with default settings: + +.. sourcecode:: cpp WifiHelper wifiHelper; @@ -706,7 +738,9 @@ What does this do? It sets the default wifi standard to **802.11a** and sets th ``WifiHelper::SetStandard`` method with the desired standard. Now, let's use the wifiPhyHelper and wifiMacHelper created above to install WifiNetDevices -on a set of nodes in a NodeContainer "c":: +on a set of nodes in a NodeContainer "c": + +.. sourcecode:: cpp NetDeviceContainer wifiContainer = WifiHelper::Install(wifiPhyHelper, wifiMacHelper, c); @@ -714,7 +748,9 @@ This creates the WifiNetDevice which includes also a WifiRemoteStationManager, a WifiMac, and a WifiPhy (connected to the matching Channel). The ``WifiHelper::SetStandard`` method sets various default timing parameters as defined in the selected standard version, overwriting values that may exist or have been previously configured. -In order to change parameters that are overwritten by ``WifiHelper::SetStandard``, this should be done post-install using ``Config::Set``:: +In order to change parameters that are overwritten by ``WifiHelper::SetStandard``, this should be done post-install using ``Config::Set``: + +.. sourcecode:: cpp WifiHelper wifi; wifi.SetStandard(WIFI_STANDARD_80211n); @@ -746,7 +782,9 @@ The WifiHelper can be used to set the attributes of the default ack policy selec (``ConstantWifiAckPolicySelector``) or to select a different (user provided) ack policy selector, for each of the available Access Categories. As an example, the following code can be used to set the BaThreshold attribute of the default ack -policy selector associated with BE AC to 0.5:: +policy selector associated with BE AC to 0.5: + +.. sourcecode:: cpp WifiHelper wifi; wifi.SetAckPolicySelectorForAc(AC_BE, "ns3::ConstantWifiAckPolicySelector", @@ -754,7 +792,9 @@ policy selector associated with BE AC to 0.5:: The WifiHelper is also used to configure OBSS PD spatial reuse for 802.11ax. The following lines configure a WifiHelper to support OBSS PD spatial reuse -using the ``ConstantObssPdAlgorithm`` with a threshold set to -72 dBm:: +using the ``ConstantObssPdAlgorithm`` with a threshold set to -72 dBm: + +.. sourcecode:: cpp WifiHelper wifi; wifi.SetObssPdAlgorithm("ns3::ConstantObssPdAlgorithm", @@ -774,7 +814,9 @@ user sets the standard to a variant that supports HT capabilities (802.11n, created for the device. The configuration object is used to store and manage HT-specific attributes. -802.11n/ac PHY layer can use either long (800 ns) or short (400 ns) OFDM guard intervals. To configure this parameter for a given device, the following lines of code could be used (in this example, it enables the support of a short guard interval for the first station):: +802.11n/ac PHY layer can use either long (800 ns) or short (400 ns) OFDM guard intervals. To configure this parameter for a given device, the following lines of code could be used (in this example, it enables the support of a short guard interval for the first station): + +.. sourcecode:: cpp Ptr nd = wifiStaDevices.Get(0); Ptr wnd = nd->GetObject(); @@ -782,7 +824,9 @@ manage HT-specific attributes. htConfiguration->SetShortGuardIntervalSupported(true); It is also possible to configure HT-specific attributes using ``Config::Set``. -The following line of code enables the support of a short guard interval for all stations:: +The following line of code enables the support of a short guard interval for all stations: + +.. sourcecode:: cpp Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/ShortGuardIntervalSupported", BooleanValue(true)); @@ -803,7 +847,9 @@ IEEE 802.11ax is also known as High Efficiency (HE). Once the ``ns3::WifiHelper HE configuration object will automatically be created to manage HE-specific attributes for 802.11ax devices. -802.11ax PHY layer can use either 3200 ns, 1600 ns or 800 ns OFDM guard intervals. To configure this parameter, the following lines of code could be used (in this example, it enables the support of 1600 ns guard interval), such as in this example code snippet:: +802.11ax PHY layer can use either 3200 ns, 1600 ns or 800 ns OFDM guard intervals. To configure this parameter, the following lines of code could be used (in this example, it enables the support of 1600 ns guard interval), such as in this example code snippet: + +.. sourcecode:: cpp Ptr nd = wifiStaDevices.Get(0); Ptr wnd = nd->GetObject(); @@ -813,7 +859,9 @@ attributes for 802.11ax devices. 802.11ax allows extended compressed Block ACKs containing a 256-bits bitmap, making possible transmissions of A-MPDUs containing up to 256 MPDUs, depending on the negotiated buffer size. In order to configure the buffer size of an 802.11ax device, -the following line of code could be used:: +the following line of code could be used: + +.. sourcecode:: cpp heConfiguration->SetMpduBufferSize(256); @@ -853,7 +901,9 @@ In this example, we create two ad-hoc nodes equipped with 802.11a Wi-Fi devices. We use the ``ns3::ConstantSpeedPropagationDelayModel`` as the propagation delay model and ``ns3::LogDistancePropagationLossModel`` with the exponent of 3.0 as the propagation loss model. Both devices are configured with ``ConstantRateWifiManager`` at the fixed rate of 12Mbps. -Finally, we manually place them by using the ``ns3::ListPositionAllocator``:: +Finally, we manually place them by using the ``ns3::ListPositionAllocator``: + +.. sourcecode:: cpp std::string phyMode("OfdmRate12Mbps"); @@ -898,7 +948,9 @@ Infrastructure (access point and clients) WifiNetDevice configuration This is a typical example of how a user might configure an access point and a set of clients. In this example, we create one access point and two clients. -Each node is equipped with 802.11b Wi-Fi device:: +Each node is equipped with 802.11b Wi-Fi device: + +.. sourcecode:: cpp std::string phyMode("DsssRate1Mbps"); @@ -960,6 +1012,8 @@ Each node is equipped with 802.11b Wi-Fi device:: Multiple RF interfaces configuration ++++++++++++++++++++++++++++++++++++ +.. sourcecode:: cpp + NodeContainer ap; ap.Create(1); NodeContainer sta; From 79e3e8453b1f8ddd6c31748be61b1c05a341a43e Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Thu, 6 Jul 2023 12:21:53 -0700 Subject: [PATCH 006/262] doc: Fix various documentation formatting warnings --- doc/installation/source/windows.rst | 2 +- doc/manual/Makefile | 1 - doc/manual/source/utilities.rst | 8 ++++---- doc/tutorial/source/tracing.rst | 8 ++++---- src/antenna/doc/source/antenna-design.rst | 1 + src/internet/doc/tcp.rst | 13 ++++++------- src/lr-wpan/doc/lr-wpan.rst | 5 ++++- src/propagation/doc/propagation.rst | 6 +++--- src/spectrum/doc/spectrum.rst | 5 ++--- 9 files changed, 25 insertions(+), 24 deletions(-) diff --git a/doc/installation/source/windows.rst b/doc/installation/source/windows.rst index 0bb0db686..7badcb82a 100644 --- a/doc/installation/source/windows.rst +++ b/doc/installation/source/windows.rst @@ -19,7 +19,7 @@ either WSL or the Msys2/MinGW64 toolchain (installing both is not required). .. note:: |ns3| is not fully compatible with Visual Studio IDE / MSVC compiler; only Visual Studio Code -editor, the Msys2/MinGW64 toolchain, and WSL, as explained below. + editor, the Msys2/MinGW64 toolchain, and WSL, as explained below. .. _WSL2: diff --git a/doc/manual/Makefile b/doc/manual/Makefile index 3fb0b88e5..893ba5ba8 100644 --- a/doc/manual/Makefile +++ b/doc/manual/Makefile @@ -78,7 +78,6 @@ SOURCEFIGS = \ figures/hotspot-top-down.png \ figures/perfetto-trace-cmake.png \ figures/uprof-collect-callstack.png \ - figures/uprof-collect-callstack.png \ figures/uprof-profile-application.png \ figures/uprof-select-events.png \ figures/uprof-start.png \ diff --git a/doc/manual/source/utilities.rst b/doc/manual/source/utilities.rst index 9c6421580..491e58da1 100644 --- a/doc/manual/source/utilities.rst +++ b/doc/manual/source/utilities.rst @@ -33,7 +33,7 @@ search for specific information. To run it, simply open terminal and type -.. sourcecode:: +.. sourcecode:: bash $ ./ns3 run print-introspected-doxygen @@ -78,7 +78,7 @@ This tool is used to benchmark the scheduler algorithms used in |ns3|. Command-line Arguments ++++++++++++++++++++++ -.. sourcecode:: +.. sourcecode:: bash $ ./ns3 run "bench-scheduler --help" bench-scheduler [Program Options] [General Arguments] @@ -129,7 +129,7 @@ Invocation To run it, simply open the terminal and type -.. sourcecode:: +.. sourcecode:: bash $ ./ns3 run bench-scheduler -- --runs=5 @@ -156,7 +156,7 @@ It will show something like this depending upon the scheduler being benchmarked: Suppose we had to benchmark `CalendarScheduler` instead, we would have written -.. sourcecode:: +.. sourcecode:: bash $ ./ns3 run bench-scheduler -- --runs=5 --cal" diff --git a/doc/tutorial/source/tracing.rst b/doc/tutorial/source/tracing.rst index 6f979cf8c..d55f12f5d 100644 --- a/doc/tutorial/source/tracing.rst +++ b/doc/tutorial/source/tracing.rst @@ -1463,8 +1463,8 @@ This should also be self-explanatory. Previous versions of |ns3| declared a custom application called ``MyApp`` for use in this program. Current versions of |ns3| have moved this to -a separate header file (``tutorial-app.h'') and implementation file -(``tutorial-app.cc''). This simple application allows the ``Socket'' +a separate header file (``tutorial-app.h``) and implementation file +(``tutorial-app.cc``). This simple application allows the ``Socket`` to be created at configuration time. :: @@ -1887,11 +1887,11 @@ Main Program ~~~~~~~~~~~~ The main function starts off by configuring the TCP type to use a legacy -``NewReno`` congestion control variant, with what is called the ``classic'' +``NewReno`` congestion control variant, with what is called the ``classic`` TCP loss recovery mechanism. When this tutorial program was originally written, these were the default TCP configurations, but over time, |ns3| TCP has evolved to use the current Linux TCP defaults of ``Cubic`` -and ``Prr'' loss recovery. The first statements also configure the +and ``Prr`` loss recovery. The first statements also configure the command-line argument processing. :: diff --git a/src/antenna/doc/source/antenna-design.rst b/src/antenna/doc/source/antenna-design.rst index d5d71ecc9..0caeb6c6f 100644 --- a/src/antenna/doc/source/antenna-design.rst +++ b/src/antenna/doc/source/antenna-design.rst @@ -153,6 +153,7 @@ Derived classes must implement the following functions: The class PhasedArrayModel also assumes that all antenna elements are equal, a typical key assumption which allows to model the PAA field pattern as the sum of the array factor, given by the geometry of the location of the antenna elements, and the element field pattern. Any class derived from AntennaModel is a valid antenna element for the PhasedArrayModel, allowing for a great flexibility of the framework. +.. _3gpp-antenna-model: UniformPlanarArray ++++++++++++++++++ diff --git a/src/internet/doc/tcp.rst b/src/internet/doc/tcp.rst index 445dea31e..bb4a1ca52 100644 --- a/src/internet/doc/tcp.rst +++ b/src/internet/doc/tcp.rst @@ -456,7 +456,7 @@ cwnd, 'bytes_acked' is reduced by the value of cwnd. Next, cwnd is incremented by a full-sized segment (SMSS). In contrast, in ns-3 NewReno, cwnd is increased by (1/cwnd) with a rounding off due to type casting into int. -.. code-block:: +.. code-block:: c++ :caption: Linux Reno `cwnd` update if (m_cWndCnt >= w) @@ -469,7 +469,7 @@ by (1/cwnd) with a rounding off due to type casting into int. } -.. code-block:: +.. code-block:: c++ :caption: New Reno `cwnd` update if (segmentsAcked > 0) @@ -1840,7 +1840,7 @@ advertises a zero window. This can be accomplished by implementing the method CreateReceiverSocket, setting an Rx buffer value of 0 bytes (at line 6 of the following code): -.. code-block:: +.. code-block:: c++ :linenos: :emphasize-lines: 6,7,8 @@ -1987,7 +1987,7 @@ we expect the persistent timer to fire before any rWnd changes. When it fires, the SENDER should send a window probe, and the receiver should reply reporting again a zero window situation. At first, we investigates on what the sender sends: -.. code-block:: +.. code-block:: c++ :linenos: :emphasize-lines: 1,6,7,11 @@ -2020,7 +2020,7 @@ reader: edit the test, getting this value from the Attribute system), we need to check (line 6) between 6.0 and 7.0 simulated seconds that the probe is sent. Only one probe is allowed, and this is the reason for the check at line 11. -.. code-block:: +.. code-block:: c++ :linenos: :emphasize-lines: 6,7 @@ -2072,7 +2072,7 @@ the window should be greater than zero (and precisely, set to 2500): To be sure that the sender receives the window update, we can use the Rx method: -.. code-block:: +.. code-block:: c++ :linenos: :emphasize-lines: 5 @@ -2137,7 +2137,6 @@ To see INFO messages, use a combination of ./ns3 shell and gdb (really useful): .. code-block:: bash - ./ns3 shell && gdb --args ./build/utils/ns3-dev-test-runner-debug --test-name=tcp-zero-window-test --stop-on-failure --fullness=QUICK --assert-on-failure --verbose and then, hit "Run". diff --git a/src/lr-wpan/doc/lr-wpan.rst b/src/lr-wpan/doc/lr-wpan.rst index 25d2bee6b..192a15f2d 100644 --- a/src/lr-wpan/doc/lr-wpan.rst +++ b/src/lr-wpan/doc/lr-wpan.rst @@ -220,7 +220,10 @@ reference packets (11 bytes MAC header + 7 bytes payload (MSDU) + FCS 2 bytes). have the effect to receive more packets (and at a greater distance) but it raises the probability to have dropped packets at the MAC layer or the probability of corrupted packets. By default, the receiver sensitivity is set to the maximum theoretical possible value of -106.58 dBm for the supported IEEE 802.15.4 O-QPSK 250kps. This rx sensitivity is set for the "perfect radio" which only considers the floor noise, in essence, this do not include the noise factor (noise introduced by imperfections in the demodulator chip or external factors). -The receiver sensitivity can be changed to different values using ``SetRxSensitivity`` function in the PHY to simulate the hearing capabilities of different compliant radio transceivers (the standard minimum compliant Rx sensitivity is -85 dBm).::: +The receiver sensitivity can be changed to different values using ``SetRxSensitivity`` function in the PHY to simulate the hearing capabilities of different compliant radio transceivers (the standard minimum compliant Rx sensitivity is -85 dBm).: + +:: + (defined by the standard) NoiseFloor Max Sensitivity Min Sensitivity -106.987dBm -106.58dBm -85dBm diff --git a/src/propagation/doc/propagation.rst b/src/propagation/doc/propagation.rst index a57b35a29..1e45fa0e7 100644 --- a/src/propagation/doc/propagation.rst +++ b/src/propagation/doc/propagation.rst @@ -946,7 +946,7 @@ Vehicular fast fading model The fast fading model described in Sec. 6.2.3 of TR 37.885 is based on the one specified in TR 38.901, whose implementation is provided in the ``spectrum`` module -(see the :ref:`spectrum module documentation `). +(see the :ref:`spectrum module documentation <3gpp-fast-fading-model>`). This model is general and includes different parameters which can be tuned to simulate multiple propagation environments. To better model the channel dynamics in vehicular environments, TR 37.885 @@ -956,7 +956,7 @@ To select the parameters for vehicular scenarios, it is necessary to set the attribute "Scenario" of the class :cpp:class:`ThreeGppChannelModel` using the value "V2V-Urban" or "V2V-Highway". -Additionally, TR 37.885 specifies a new equation to compute the Doppler component, +edditionally, TR 37.885 specifies a new equation to compute the Doppler component, which accounts for the mobility of both nodes, as well as scattering from the environment. In particular, the scattering effect is considered by deviating the Doppler @@ -978,7 +978,7 @@ We considered two communicating vehicles moving within the scenario, and computed the SNR experienced during the entire simulation, with a time resolution of 10 ms. The vehicles are equipped with 2x2 antenna arrays modeled using the -:ref:`3GPP antenna model `. +:ref:`3GPP antenna model <3gpp-antenna-model>`. The bearing and the downtilt angles are properly configured and the optimal beamforming vectors are computed at the beginning of the simulation. diff --git a/src/spectrum/doc/spectrum.rst b/src/spectrum/doc/spectrum.rst index be7118cc0..d971b589f 100644 --- a/src/spectrum/doc/spectrum.rst +++ b/src/spectrum/doc/spectrum.rst @@ -594,6 +594,8 @@ the given geographic origin point, and is tested in the ``rand-cart-around-geo`` test suite by verifying that the generated points do not exceed the given maximum distance radius from the origin point. +.. _3gpp-fast-fading-model: + 3GPP TR 38.901 fast fading model ================================ The framework described by TR 38.901 [TR38901]_ is a 3D statistical Spatial @@ -1042,6 +1044,3 @@ References Mattias Frenne, Farshid Ghasemzadeh, Måns Hagström et al. Advanced Antenna Systems for 5G Network Deployments: Bridging the Gap Between Theory and Practice. Academic Press, 2020. - -.. [TR38901] 3GPP. 2018. TR 38.901. Study on channel for frequencies from 0.5 to - 100 GHz. V.15.0.0. (2018-06). From d5f9654227b9acb01efab3d02e190cde5dfd1c63 Mon Sep 17 00:00:00 2001 From: Tom Henderson Date: Wed, 5 Jul 2023 18:58:25 -0700 Subject: [PATCH 007/262] doc: Number the sections in HTML output --- doc/contributing/source/index.rst | 1 + doc/installation/source/index.rst | 1 + doc/manual/source/index.rst | 1 + doc/models/source/index.rst | 1 + doc/tutorial/source/index.rst | 1 + 5 files changed, 5 insertions(+) diff --git a/doc/contributing/source/index.rst b/doc/contributing/source/index.rst index 7604e4194..798857449 100644 --- a/doc/contributing/source/index.rst +++ b/doc/contributing/source/index.rst @@ -24,6 +24,7 @@ This document is written in `reStructuredText `_ and is maintained in the ``doc/installa .. toctree:: :maxdepth: 2 + :numbered: overview quick-start diff --git a/doc/manual/source/index.rst b/doc/manual/source/index.rst index 534153633..f2bf761da 100644 --- a/doc/manual/source/index.rst +++ b/doc/manual/source/index.rst @@ -24,6 +24,7 @@ This document is written in `reStructuredText Date: Fri, 9 Jun 2023 08:33:44 +0100 Subject: [PATCH 008/262] click: Fix internet stack helper operator=() --- src/click/helper/click-internet-stack-helper.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/click/helper/click-internet-stack-helper.cc b/src/click/helper/click-internet-stack-helper.cc index 1f6f225b8..714bfa0db 100644 --- a/src/click/helper/click-internet-stack-helper.cc +++ b/src/click/helper/click-internet-stack-helper.cc @@ -84,9 +84,9 @@ ClickInternetStackHelper::ClickInternetStackHelper(const ClickInternetStackHelpe ClickInternetStackHelper& ClickInternetStackHelper::operator=(const ClickInternetStackHelper& o) { - if (this == &o) + if (this != &o) { - return *this; + m_ipv4Enabled = o.m_ipv4Enabled; } return *this; } From 3de318090ac1d4068573d0334470a310a02a1a6a Mon Sep 17 00:00:00 2001 From: Eduardo Almeida Date: Fri, 9 Jun 2023 08:48:05 +0100 Subject: [PATCH 009/262] click: Remove non-implemented functions --- src/click/helper/click-internet-stack-helper.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/click/helper/click-internet-stack-helper.h b/src/click/helper/click-internet-stack-helper.h index fea68e954..1f1ec2c3c 100644 --- a/src/click/helper/click-internet-stack-helper.h +++ b/src/click/helper/click-internet-stack-helper.h @@ -175,8 +175,6 @@ class ClickInternetStackHelper : public PcapHelperForIpv4, public AsciiTraceHelp static void CreateAndAggregateObjectFromTypeId(Ptr node, const std::string typeId); - static void Cleanup(); - bool PcapHooked(Ptr ipv4); bool AsciiHooked(Ptr ipv4); From 6a71f98430e3f8097cad7567b60b333abe89dd01 Mon Sep 17 00:00:00 2001 From: Gabriel Ferreira Date: Fri, 14 Jul 2023 15:30:06 -0300 Subject: [PATCH 010/262] core: Remove unnecessary linking statements to threads libraries --- src/core/CMakeLists.txt | 4 +--- src/core/examples/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ad693e31b..db51d1b9f 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,7 +1,5 @@ # Set lib core link dependencies -set(libraries_to_link - ${CMAKE_THREAD_LIBS_INIT} -) +set(libraries_to_link) set(gsl_test_sources) if(${GSL_FOUND}) diff --git a/src/core/examples/CMakeLists.txt b/src/core/examples/CMakeLists.txt index 9befa2b39..0f0d7eeff 100644 --- a/src/core/examples/CMakeLists.txt +++ b/src/core/examples/CMakeLists.txt @@ -47,7 +47,6 @@ build_lib_example( NAME main-test-sync SOURCE_FILES main-test-sync.cc LIBRARIES_TO_LINK ${libnetwork} - ${CMAKE_THREAD_LIBS_INIT} ) build_lib_example( From 2d69a053710d2acdcc5911c8cebabc3361b275ed Mon Sep 17 00:00:00 2001 From: Gabriel Ferreira Date: Fri, 14 Jul 2023 15:30:31 -0300 Subject: [PATCH 011/262] build: (fixes #928) Fix pkgconfig generation --- build-support/custom-modules/ns3-cmake-package.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build-support/custom-modules/ns3-cmake-package.cmake b/build-support/custom-modules/ns3-cmake-package.cmake index ecc2e045f..e441281d7 100644 --- a/build-support/custom-modules/ns3-cmake-package.cmake +++ b/build-support/custom-modules/ns3-cmake-package.cmake @@ -29,7 +29,7 @@ function(build_required_and_libs_lists module_name visibility libraries ) set(lib_real_name "-l${lib_real_name}") else() - if(IS_ABSOLUTE ${lib}) + if((IS_ABSOLUTE "${lib}") OR ("${lib}" MATCHES "^-l")) set(lib_real_name ${lib}) else() set(lib_real_name "-l${lib}") @@ -88,6 +88,9 @@ function(pkgconfig_module libname) string(REPLACE ";-I" " -I" pkgconfig_interface_include_directories "${pkgconfig_interface_include_directories}" ) + string(REPLACE ";" "" pkgconfig_interface_include_directories + "${pkgconfig_interface_include_directories}" + ) endif() # Configure pkgconfig file for the module using pkgconfig variables From 82f43ec5e1c51502f27c505074669b5a626a01bf Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Fri, 12 May 2023 16:29:42 +0200 Subject: [PATCH 012/262] wifi: Add MultiLinkElement methods to return a reference to Common Info --- src/wifi/model/eht/multi-link-element.cc | 12 ++++++++++++ src/wifi/model/eht/multi-link-element.h | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/src/wifi/model/eht/multi-link-element.cc b/src/wifi/model/eht/multi-link-element.cc index 39d79b697..9f69744c6 100644 --- a/src/wifi/model/eht/multi-link-element.cc +++ b/src/wifi/model/eht/multi-link-element.cc @@ -269,6 +269,18 @@ MultiLinkElement::SetVariant(Variant variant) } } +CommonInfoBasicMle& +MultiLinkElement::GetCommonInfoBasic() +{ + return std::get(m_commonInfo); +} + +const CommonInfoBasicMle& +MultiLinkElement::GetCommonInfoBasic() const +{ + return std::get(m_commonInfo); +} + void MultiLinkElement::SetMldMacAddress(Mac48Address address) { diff --git a/src/wifi/model/eht/multi-link-element.h b/src/wifi/model/eht/multi-link-element.h index d81e67419..2d1b1a2ca 100644 --- a/src/wifi/model/eht/multi-link-element.h +++ b/src/wifi/model/eht/multi-link-element.h @@ -217,6 +217,12 @@ class MultiLinkElement : public WifiInformationElement */ Variant GetVariant() const; + /// \return a reference to the Common Info field (the MLE variant must be Basic) + CommonInfoBasicMle& GetCommonInfoBasic(); + + /// \return a const reference to the Common Info field (the MLE variant must be Basic) + const CommonInfoBasicMle& GetCommonInfoBasic() const; + /** * Set the MLD MAC Address subfield in the Common Info field. Make sure that * this is a Basic Multi-Link Element. From c0ce2ea2b752d532a774efc425ad5d6d52fe98db Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Sun, 14 May 2023 18:29:03 +0200 Subject: [PATCH 013/262] wifi: Do not rely on AssocManager subclass to store BSSIDs in remote station manager --- src/wifi/model/sta-wifi-mac.cc | 19 +++++--------- src/wifi/model/sta-wifi-mac.h | 14 ++++++++-- src/wifi/model/wifi-assoc-manager.cc | 4 +-- src/wifi/model/wifi-assoc-manager.h | 2 +- src/wifi/model/wifi-default-assoc-manager.cc | 27 +++++--------------- 5 files changed, 29 insertions(+), 37 deletions(-) diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 667b0c0ba..dc98dd722 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -617,22 +617,17 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) GetLink(bestAp->m_linkId).sendAssocReq = true; GetLink(bestAp->m_linkId).bssid = bestAp->m_bssid; // update info on links to setup (11be MLDs only) - for (const auto& [localLinkId, apLinkId] : bestAp->m_setupLinks) + const auto& mle = + std::visit([](auto&& frame) { return frame.template Get(); }, + bestAp->m_frame); + for (const auto& [localLinkId, apLinkId, bssid] : bestAp->m_setupLinks) { + NS_ASSERT_MSG(mle, "We get here only for ML setup"); NS_LOG_DEBUG("Setting up link (local ID=" << +localLinkId << ", AP ID=" << +apLinkId << ")"); GetLink(localLinkId).apLinkId = apLinkId; - if (localLinkId == bestAp->m_linkId) - { - continue; - } - auto mldAddress = - GetWifiRemoteStationManager(bestAp->m_linkId)->GetMldAddress(bestAp->m_bssid); - NS_ABORT_MSG_IF(!mldAddress.has_value(), "AP MLD address not set"); - auto bssid = GetWifiRemoteStationManager(localLinkId)->GetAffiliatedStaAddress(*mldAddress); - NS_ABORT_MSG_IF(!mldAddress.has_value(), - "AP link address not set for local link " << +localLinkId); - GetLink(localLinkId).bssid = *bssid; + GetLink(localLinkId).bssid = bssid; + GetWifiRemoteStationManager(localLinkId)->SetMldAddress(bssid, mle->GetMldMacAddress()); } // lambda to get beacon interval from Beacon or Probe Response auto getBeaconInterval = [](auto&& frame) { diff --git a/src/wifi/model/sta-wifi-mac.h b/src/wifi/model/sta-wifi-mac.h index 731e9a6e8..9c185c480 100644 --- a/src/wifi/model/sta-wifi-mac.h +++ b/src/wifi/model/sta-wifi-mac.h @@ -162,14 +162,24 @@ class StaWifiMac : public WifiMac */ struct ApInfo { + /** + * Information about links to setup + */ + struct SetupLinksInfo + { + uint8_t localLinkId; ///< local link ID + uint8_t apLinkId; ///< AP link ID + Mac48Address bssid; ///< BSSID + }; + Mac48Address m_bssid; ///< BSSID Mac48Address m_apAddr; ///< AP MAC address double m_snr; ///< SNR in linear scale MgtFrameType m_frame; ///< The body of the management frame used to update AP info WifiScanParams::Channel m_channel; ///< The channel the management frame was received on uint8_t m_linkId; ///< ID of the link used to communicate with the AP - /// list of (local link ID, AP link ID) pairs identifying the links to setup between MLDs - std::list> m_setupLinks; + std::list + m_setupLinks; ///< information about the links to setup between MLDs }; /** diff --git a/src/wifi/model/wifi-assoc-manager.cc b/src/wifi/model/wifi-assoc-manager.cc index dd253d5d0..83c869b73 100644 --- a/src/wifi/model/wifi-assoc-manager.cc +++ b/src/wifi/model/wifi-assoc-manager.cc @@ -234,10 +234,10 @@ WifiAssocManager::ScanningTimeout() m_mac->ScanningTimeout(std::move(bestAp)); } -std::list>& +std::list& WifiAssocManager::GetSetupLinks(const StaWifiMac::ApInfo& apInfo) { - return const_cast>&>(apInfo.m_setupLinks); + return const_cast&>(apInfo.m_setupLinks); } bool diff --git a/src/wifi/model/wifi-assoc-manager.h b/src/wifi/model/wifi-assoc-manager.h index 6e1827276..66cb42009 100644 --- a/src/wifi/model/wifi-assoc-manager.h +++ b/src/wifi/model/wifi-assoc-manager.h @@ -178,7 +178,7 @@ class WifiAssocManager : public Object * \param apInfo the info about the given AP * \return a reference to the list of the links to setup with the given AP */ - std::list>& GetSetupLinks(const StaWifiMac::ApInfo& apInfo); + std::list& GetSetupLinks(const StaWifiMac::ApInfo& apInfo); /** * \return the scanning parameters. diff --git a/src/wifi/model/wifi-default-assoc-manager.cc b/src/wifi/model/wifi-default-assoc-manager.cc index 79e6e81a7..ba6d8bb3a 100644 --- a/src/wifi/model/wifi-default-assoc-manager.cc +++ b/src/wifi/model/wifi-default-assoc-manager.cc @@ -133,15 +133,12 @@ WifiDefaultAssocManager::EndScanning() } auto& bestAp = *GetSortedList().begin(); - - // store AP MLD MAC address in the WifiRemoteStationManager associated with - // the link on which the Beacon/Probe Response was received - m_mac->GetWifiRemoteStationManager(bestAp.m_linkId) - ->SetMldAddress(bestAp.m_apAddr, mle->get().GetMldMacAddress()); auto& setupLinks = GetSetupLinks(bestAp); setupLinks.clear(); - setupLinks.emplace_back(bestAp.m_linkId, mle->get().GetLinkIdInfo()); + setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{bestAp.m_linkId, + mle->get().GetLinkIdInfo(), + bestAp.m_bssid}); // sort local PHY objects so that radios with constrained PHY band comes first, // then radios with no constraint @@ -203,14 +200,10 @@ WifiDefaultAssocManager::EndScanning() // if we get here, it means we can setup a link with this affiliated AP // set the BSSID for this link Mac48Address bssid = rnr->get().GetBssid(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId); - // store AP MLD MAC address in the WifiRemoteStationManager associated with - // the link requested to setup - m_mac->GetWifiRemoteStationManager(linkId)->SetMldAddress( - bssid, - mle->get().GetMldMacAddress()); - setupLinks.emplace_back( + setupLinks.emplace_back(StaWifiMac::ApInfo::SetupLinksInfo{ linkId, - rnr->get().GetLinkId(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId)); + rnr->get().GetLinkId(apIt->m_nbrApInfoId, apIt->m_tbttInfoFieldId), + bssid}); if (needChannelSwitch) { @@ -264,12 +257,6 @@ WifiDefaultAssocManager::NotifyChannelSwitched(uint8_t linkId) // we were waiting for this notification m_channelSwitchInfo[linkId].timer.Cancel(); - // the remote station manager has been reset after switching, hence store - // information about AP link address and AP MLD address - m_mac->GetWifiRemoteStationManager(linkId)->SetMldAddress( - m_channelSwitchInfo[linkId].apLinkAddress, - m_channelSwitchInfo[linkId].apMldAddress); - if (std::none_of(m_channelSwitchInfo.begin(), m_channelSwitchInfo.end(), [](auto&& info) { return info.timer.IsRunning(); })) @@ -289,7 +276,7 @@ WifiDefaultAssocManager::ChannelSwitchTimeout(uint8_t linkId) auto& bestAp = *GetSortedList().begin(); auto& setupLinks = GetSetupLinks(bestAp); auto it = std::find_if(setupLinks.begin(), setupLinks.end(), [&linkId](auto&& linkIds) { - return linkIds.first == linkId; + return linkIds.localLinkId == linkId; }); NS_ASSERT(it != setupLinks.end()); setupLinks.erase(it); From 8601e3a0ef5c5db3a34e66435652604f6717f316 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Sun, 14 May 2023 19:27:12 +0200 Subject: [PATCH 014/262] wifi: Store the whole MLE Common Info field in remote station manager --- src/wifi/model/ap-wifi-mac.cc | 21 +++++---------- .../model/eht/eht-frame-exchange-manager.cc | 4 +-- src/wifi/model/sta-wifi-mac.cc | 6 +++++ src/wifi/model/wifi-remote-station-manager.cc | 27 ++++++++++++------- src/wifi/model/wifi-remote-station-manager.h | 18 ++++++------- 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index 1e30707b1..5a33d266f 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -1995,18 +1995,9 @@ ApWifiMac::ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address fr return; } - auto emlCapabilities = std::make_shared(); - if (mle->HasEmlCapabilities()) - { - emlCapabilities->emlsrSupport = mle->IsEmlsrSupported() ? 1 : 0; - emlCapabilities->emlsrPaddingDelay = - CommonInfoBasicMle::EncodeEmlsrPaddingDelay(mle->GetEmlsrPaddingDelay()); - emlCapabilities->emlsrTransitionDelay = - CommonInfoBasicMle::EncodeEmlsrTransitionDelay(mle->GetEmlsrTransitionDelay()); - } - GetWifiRemoteStationManager(linkId)->SetMldAddress(from, mle->GetMldMacAddress()); - GetWifiRemoteStationManager(linkId)->AddStationEmlCapabilities(from, emlCapabilities); + auto mleCommonInfo = std::make_shared(mle->GetCommonInfoBasic()); + GetWifiRemoteStationManager(linkId)->AddStationMleCommonInfo(from, mleCommonInfo); for (std::size_t i = 0; i < mle->GetNPerStaProfileSubelements(); i++) { @@ -2034,9 +2025,9 @@ ApWifiMac::ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address fr newLinkId); GetWifiRemoteStationManager(newLinkId)->SetMldAddress(perStaProfile.GetStaMacAddress(), mle->GetMldMacAddress()); - GetWifiRemoteStationManager(newLinkId)->AddStationEmlCapabilities( + GetWifiRemoteStationManager(newLinkId)->AddStationMleCommonInfo( perStaProfile.GetStaMacAddress(), - emlCapabilities); + mleCommonInfo); } }; @@ -2070,8 +2061,8 @@ ApWifiMac::ReceiveEmlNotification(MgtEmlOperatingModeNotification& frame, NS_ASSERT_MSG(emlCapabilities, "EML Capabilities not stored for STA " << sender); // update values stored in remote station manager - emlCapabilities->emlsrPaddingDelay = frame.m_emlsrParamUpdate->paddingDelay; - emlCapabilities->emlsrTransitionDelay = frame.m_emlsrParamUpdate->transitionDelay; + emlCapabilities->get().emlsrPaddingDelay = frame.m_emlsrParamUpdate->paddingDelay; + emlCapabilities->get().emlsrTransitionDelay = frame.m_emlsrParamUpdate->transitionDelay; } auto mldAddress = GetWifiRemoteStationManager(linkId)->GetMldAddress(sender); diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index e36c5696e..97ab816b2 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -218,7 +218,7 @@ EhtFrameExchangeManager::EmlsrSwitchToListening(const Mac48Address& address, con // unblock all EMLSR links when the transition delay elapses Simulator::Schedule(delay + CommonInfoBasicMle::DecodeEmlsrTransitionDelay( - emlCapabilities->emlsrTransitionDelay), + emlCapabilities->get().emlsrTransitionDelay), [=]() { m_mac->UnblockUnicastTxOnLinks( WifiQueueBlockedReason::WAITING_EMLSR_TRANSITION_DELAY, @@ -311,7 +311,7 @@ EhtFrameExchangeManager::SendMuRts(const WifiTxParameters& txParams) auto emlCapabilities = GetWifiRemoteStationManager()->GetStationEmlCapabilities(address); NS_ASSERT(emlCapabilities); - maxPaddingDelay = std::max(maxPaddingDelay, emlCapabilities->emlsrPaddingDelay); + maxPaddingDelay = std::max(maxPaddingDelay, emlCapabilities->get().emlsrPaddingDelay); auto mldAddress = GetWifiRemoteStationManager()->GetMldAddress(address); NS_ASSERT(mldAddress); diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index dc98dd722..030a0fb89 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -616,6 +616,7 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) // send Association Request on the link where the Beacon/Probe Response was received GetLink(bestAp->m_linkId).sendAssocReq = true; GetLink(bestAp->m_linkId).bssid = bestAp->m_bssid; + std::shared_ptr mleCommonInfo; // update info on links to setup (11be MLDs only) const auto& mle = std::visit([](auto&& frame) { return frame.template Get(); }, @@ -628,6 +629,11 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) GetLink(localLinkId).apLinkId = apLinkId; GetLink(localLinkId).bssid = bssid; GetWifiRemoteStationManager(localLinkId)->SetMldAddress(bssid, mle->GetMldMacAddress()); + if (!mleCommonInfo) + { + mleCommonInfo = std::make_shared(mle->GetCommonInfoBasic()); + } + GetWifiRemoteStationManager(localLinkId)->AddStationMleCommonInfo(bssid, mleCommonInfo); } // lambda to get beacon interval from Beacon or Probe Response auto getBeaconInterval = [](auto&& frame) { diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 5d315b9e7..2db677d97 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -1422,7 +1422,7 @@ WifiRemoteStationManager::LookupState(Mac48Address address) const state->m_vhtCapabilities = nullptr; state->m_heCapabilities = nullptr; state->m_ehtCapabilities = nullptr; - state->m_emlCapabilities = nullptr; + state->m_mleCommonInfo = nullptr; state->m_emlsrEnabled = false; state->m_channelWidth = m_wifiPhy->GetChannelWidth(); state->m_guardInterval = GetGuardInterval(); @@ -1600,12 +1600,12 @@ WifiRemoteStationManager::AddStationEhtCapabilities(Mac48Address from, } void -WifiRemoteStationManager::AddStationEmlCapabilities( +WifiRemoteStationManager::AddStationMleCommonInfo( Mac48Address from, - const std::shared_ptr& emlCapabilities) + const std::shared_ptr& mleCommonInfo) { NS_LOG_FUNCTION(this << from); - LookupState(from)->m_emlCapabilities = emlCapabilities; + LookupState(from)->m_mleCommonInfo = mleCommonInfo; } Ptr @@ -1632,10 +1632,15 @@ WifiRemoteStationManager::GetStationEhtCapabilities(Mac48Address from) return LookupState(from)->m_ehtCapabilities; } -std::shared_ptr +std::optional> WifiRemoteStationManager::GetStationEmlCapabilities(const Mac48Address& from) { - return LookupState(from)->m_emlCapabilities; + if (auto state = LookupState(from); + state->m_mleCommonInfo && state->m_mleCommonInfo->m_emlCapabilities) + { + return state->m_mleCommonInfo->m_emlCapabilities.value(); + } + return std::nullopt; } bool @@ -2014,8 +2019,9 @@ WifiRemoteStationManager::GetEhtSupported(const WifiRemoteStation* station) cons bool WifiRemoteStationManager::GetEmlsrSupported(const WifiRemoteStation* station) const { - auto emlCapabilities = station->m_state->m_emlCapabilities; - return emlCapabilities && emlCapabilities->emlsrSupport == 1; + auto mleCommonInfo = station->m_state->m_mleCommonInfo; + return mleCommonInfo && mleCommonInfo->m_emlCapabilities && + mleCommonInfo->m_emlCapabilities->emlsrSupport == 1; } bool @@ -2128,8 +2134,9 @@ WifiRemoteStationManager::GetEhtSupported(Mac48Address address) const bool WifiRemoteStationManager::GetEmlsrSupported(const Mac48Address& address) const { - auto emlCapabilities = LookupState(address)->m_emlCapabilities; - return emlCapabilities && emlCapabilities->emlsrSupport == 1; + auto mleCommonInfo = LookupState(address)->m_mleCommonInfo; + return mleCommonInfo && mleCommonInfo->m_emlCapabilities && + mleCommonInfo->m_emlCapabilities->emlsrSupport == 1; } bool diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h index c60403562..59976c4f5 100644 --- a/src/wifi/model/wifi-remote-station-manager.h +++ b/src/wifi/model/wifi-remote-station-manager.h @@ -114,8 +114,8 @@ struct WifiRemoteStationState Ptr m_vhtCapabilities; //!< remote station VHT capabilities Ptr m_heCapabilities; //!< remote station HE capabilities Ptr m_ehtCapabilities; //!< remote station EHT capabilities - /// remote station EML capabilities - std::shared_ptr m_emlCapabilities; + /// remote station Multi-Link Element Common Info + std::shared_ptr m_mleCommonInfo; bool m_emlsrEnabled; //!< whether EMLSR mode is enabled on this link uint16_t m_channelWidth; //!< Channel width (in MHz) supported by the remote station @@ -270,14 +270,14 @@ class WifiRemoteStationManager : public Object */ void AddStationEhtCapabilities(Mac48Address from, EhtCapabilities ehtCapabilities); /** - * Records EML capabilities of the remote station. + * Records the Common Info field advertised by the given remote station in a Multi-Link + * Element. It includes the MLD address of the remote station. * * \param from the address of the station being recorded - * \param emlCapabilities the EML capabilities of the station + * \param mleCommonInfo the MLE Common Info advertised by the station */ - void AddStationEmlCapabilities( - Mac48Address from, - const std::shared_ptr& emlCapabilities); + void AddStationMleCommonInfo(Mac48Address from, + const std::shared_ptr& mleCommonInfo); /** * Return the HT capabilities sent by the remote station. * @@ -310,8 +310,8 @@ class WifiRemoteStationManager : public Object * \param from the (MLD or link) address of the remote non-AP MLD * \return the EML Capabilities advertised by the remote non-AP MLD */ - std::shared_ptr GetStationEmlCapabilities( - const Mac48Address& from); + std::optional> + GetStationEmlCapabilities(const Mac48Address& from); /** * Return whether the device has HT capability support enabled. * From 106c617c98059db0d45476c9c4f7a738c6a6be75 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Sun, 14 May 2023 21:22:22 +0200 Subject: [PATCH 015/262] wifi: MLD address in remote station manager is included in MLE Common Info --- src/wifi/model/ap-wifi-mac.cc | 3 -- src/wifi/model/sta-wifi-mac.cc | 1 - src/wifi/model/wifi-remote-station-manager.cc | 29 +++++++++---------- src/wifi/model/wifi-remote-station-manager.h | 28 ++++++------------ 4 files changed, 23 insertions(+), 38 deletions(-) diff --git a/src/wifi/model/ap-wifi-mac.cc b/src/wifi/model/ap-wifi-mac.cc index 5a33d266f..1caf73adf 100644 --- a/src/wifi/model/ap-wifi-mac.cc +++ b/src/wifi/model/ap-wifi-mac.cc @@ -1995,7 +1995,6 @@ ApWifiMac::ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address fr return; } - GetWifiRemoteStationManager(linkId)->SetMldAddress(from, mle->GetMldMacAddress()); auto mleCommonInfo = std::make_shared(mle->GetCommonInfoBasic()); GetWifiRemoteStationManager(linkId)->AddStationMleCommonInfo(from, mleCommonInfo); @@ -2023,8 +2022,6 @@ ApWifiMac::ParseReportedStaInfo(const AssocReqRefVariant& assoc, Mac48Address fr ReceiveAssocRequest(perStaProfile.GetAssocRequest(), perStaProfile.GetStaMacAddress(), newLinkId); - GetWifiRemoteStationManager(newLinkId)->SetMldAddress(perStaProfile.GetStaMacAddress(), - mle->GetMldMacAddress()); GetWifiRemoteStationManager(newLinkId)->AddStationMleCommonInfo( perStaProfile.GetStaMacAddress(), mleCommonInfo); diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 030a0fb89..2d71afb77 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -628,7 +628,6 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) << ")"); GetLink(localLinkId).apLinkId = apLinkId; GetLink(localLinkId).bssid = bssid; - GetWifiRemoteStationManager(localLinkId)->SetMldAddress(bssid, mle->GetMldMacAddress()); if (!mleCommonInfo) { mleCommonInfo = std::make_shared(mle->GetCommonInfoBasic()); diff --git a/src/wifi/model/wifi-remote-station-manager.cc b/src/wifi/model/wifi-remote-station-manager.cc index 2db677d97..a32048e01 100644 --- a/src/wifi/model/wifi-remote-station-manager.cc +++ b/src/wifi/model/wifi-remote-station-manager.cc @@ -565,21 +565,16 @@ WifiRemoteStationManager::SetPsMode(const Mac48Address& address, bool isInPsMode LookupState(address)->m_isInPsMode = isInPsMode; } -void -WifiRemoteStationManager::SetMldAddress(const Mac48Address& address, const Mac48Address& mldAddress) -{ - NS_LOG_FUNCTION(this << address << mldAddress); - - auto state = LookupState(address); - state->m_mldAddress = mldAddress; - // insert another entry in m_states indexed by the MLD address and pointing to the same state - const_cast(this)->m_states.insert({mldAddress, state}); -} - std::optional WifiRemoteStationManager::GetMldAddress(const Mac48Address& address) const { - return LookupState(address)->m_mldAddress; + if (auto stateIt = m_states.find(address); + stateIt != m_states.end() && stateIt->second->m_mleCommonInfo) + { + return stateIt->second->m_mleCommonInfo->m_mldMacAddress; + } + + return std::nullopt; } std::optional @@ -587,13 +582,13 @@ WifiRemoteStationManager::GetAffiliatedStaAddress(const Mac48Address& mldAddress { auto stateIt = m_states.find(mldAddress); - if (stateIt == m_states.end() || !stateIt->second->m_mldAddress) + if (stateIt == m_states.end() || !stateIt->second->m_mleCommonInfo) { // MLD address not found return std::nullopt; } - NS_ASSERT(*stateIt->second->m_mldAddress == mldAddress); + NS_ASSERT(stateIt->second->m_mleCommonInfo->m_mldMacAddress == mldAddress); return stateIt->second->m_address; } @@ -1605,7 +1600,11 @@ WifiRemoteStationManager::AddStationMleCommonInfo( const std::shared_ptr& mleCommonInfo) { NS_LOG_FUNCTION(this << from); - LookupState(from)->m_mleCommonInfo = mleCommonInfo; + auto state = LookupState(from); + state->m_mleCommonInfo = mleCommonInfo; + // insert another entry in m_states indexed by the MLD address and pointing to the same state + const_cast(this)->m_states.insert( + {mleCommonInfo->m_mldMacAddress, state}); } Ptr diff --git a/src/wifi/model/wifi-remote-station-manager.h b/src/wifi/model/wifi-remote-station-manager.h index 59976c4f5..5e29b8a5f 100644 --- a/src/wifi/model/wifi-remote-station-manager.h +++ b/src/wifi/model/wifi-remote-station-manager.h @@ -99,17 +99,15 @@ struct WifiRemoteStationState * WifiRemoteStationManager::GetNSupported() and * WifiRemoteStationManager::GetSupported(). */ - WifiModeList m_operationalRateSet; //!< operational rate set - WifiModeList m_operationalMcsSet; //!< operational MCS set - Mac48Address m_address; //!< Mac48Address of the remote station - uint16_t m_aid; /**< AID of the remote station (unused if this object - is installed on a non-AP station) */ - std::optional m_mldAddress; /**< MLD MAC address if the remote station is - affiliated with an MLD */ - WifiRemoteStationInfo m_info; //!< remote station info - bool m_dsssSupported; //!< Flag if DSSS is supported by the remote station - bool m_erpOfdmSupported; //!< Flag if ERP OFDM is supported by the remote station - bool m_ofdmSupported; //!< Flag if OFDM is supported by the remote station + WifiModeList m_operationalRateSet; //!< operational rate set + WifiModeList m_operationalMcsSet; //!< operational MCS set + Mac48Address m_address; //!< Mac48Address of the remote station + uint16_t m_aid; /**< AID of the remote station (unused if this object + is installed on a non-AP station) */ + WifiRemoteStationInfo m_info; //!< remote station info + bool m_dsssSupported; //!< Flag if DSSS is supported by the remote station + bool m_erpOfdmSupported; //!< Flag if ERP OFDM is supported by the remote station + bool m_ofdmSupported; //!< Flag if OFDM is supported by the remote station Ptr m_htCapabilities; //!< remote station HT capabilities Ptr m_vhtCapabilities; //!< remote station VHT capabilities Ptr m_heCapabilities; //!< remote station HE capabilities @@ -784,14 +782,6 @@ class WifiRemoteStationManager : public Object */ void SetPsMode(const Mac48Address& address, bool isInPsMode); - /** - * Set the address of the MLD the given station is affiliated with. - * - * \param address the MAC address of the remote station - * \param mldAddress the MAC address of the MLD the remote station is - * affiliated with - */ - void SetMldAddress(const Mac48Address& address, const Mac48Address& mldAddress); /** * Get the address of the MLD the given station is affiliated with, if any. * Note that an MLD address is only present if an ML discovery/setup was performed From 0bc3834adcad2bc3e89f46c53497ce2427468476 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Tue, 16 May 2023 15:28:46 +0200 Subject: [PATCH 016/262] wifi: WifiMac holds link entities in a map rather than a vector The ID does not always match the position in the vector. --- src/wifi/model/wifi-mac.cc | 63 ++++++++++++++++---------------------- src/wifi/model/wifi-mac.h | 6 ++-- 2 files changed, 30 insertions(+), 39 deletions(-) diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index 1a38549f6..74b4aba99 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -363,7 +363,7 @@ WifiMac::DoInitialize() it->second->Initialize(); } - for (auto& link : m_links) + for (const auto& [id, link] : m_links) { if (auto cam = link->channelAccessManager) { @@ -481,7 +481,7 @@ WifiMac::GetBssid(uint8_t linkId) const void WifiMac::SetPromisc() { - for (auto& link : m_links) + for (auto& [id, link] : m_links) { link->feManager->SetPromisc(); } @@ -646,7 +646,7 @@ void WifiMac::ConfigureContentionWindow(uint32_t cwMin, uint32_t cwMax) { std::list isDsssOnly; - for (const auto& link : m_links) + for (const auto& [id, link] : m_links) { isDsssOnly.push_back(link->dsssSupported && !link->erpSupported); } @@ -751,11 +751,11 @@ WifiMac::ConfigureStandard(WifiStandard standard) NS_ABORT_IF(standard >= WIFI_STANDARD_80211n && !m_qosSupported); NS_ABORT_MSG_IF(m_links.empty(), "No PHY configured yet"); - for (auto& link : m_links) + for (auto& [id, link] : m_links) { NS_ABORT_MSG_IF( !link->phy || !link->phy->GetOperatingChannel().IsSet(), - "[LinkID " << link->id + "[LinkID " << +id << "] PHY must have been set and an operating channel must have been set"); // do not create a ChannelAccessManager and a FrameExchangeManager if they @@ -772,8 +772,8 @@ WifiMac::ConfigureStandard(WifiStandard standard) } link->feManager->SetWifiPhy(link->phy); link->feManager->SetWifiMac(this); - link->feManager->SetLinkId(link->id); - link->channelAccessManager->SetLinkId(link->id); + link->feManager->SetLinkId(id); + link->channelAccessManager->SetLinkId(id); link->channelAccessManager->SetupFrameExchangeManager(link->feManager); if (m_txop) @@ -787,7 +787,7 @@ WifiMac::ConfigureStandard(WifiStandard standard) link->channelAccessManager->Add(it->second); } - ConfigurePhyDependentParameters(link->id); + ConfigurePhyDependentParameters(id); } } @@ -896,13 +896,8 @@ WifiMac::SetWifiRemoteStationManagers( for (std::size_t i = 0; i < stationManagers.size(); i++) { // the link may already exist in case PHY objects were configured first - if (i == m_links.size()) - { - m_links.push_back(CreateLinkEntity()); - m_links.back()->id = i; - } - NS_ABORT_IF(i != m_links[i]->id); - m_links[i]->stationManager = stationManagers[i]; + auto [it, inserted] = m_links.emplace(i, CreateLinkEntity()); + it->second->stationManager = stationManagers[i]; } } @@ -921,9 +916,10 @@ WifiMac::CreateLinkEntity() const WifiMac::LinkEntity& WifiMac::GetLink(uint8_t linkId) const { - NS_ASSERT(linkId < m_links.size()); - NS_ASSERT(m_links.at(linkId)); // check that the pointer owns an object - return *m_links.at(linkId); + auto it = m_links.find(linkId); + NS_ASSERT(it != m_links.cend()); + NS_ASSERT(it->second); // check that the pointer owns an object + return *it->second; } uint8_t @@ -935,11 +931,11 @@ WifiMac::GetNLinks() const std::optional WifiMac::GetLinkIdByAddress(const Mac48Address& address) const { - for (std::size_t ret = 0; ret < m_links.size(); ++ret) + for (const auto& [id, link] : m_links) { - if (m_links[ret]->feManager->GetAddress() == address) + if (link->feManager->GetAddress() == address) { - return ret; + return id; } } return std::nullopt; @@ -964,13 +960,8 @@ WifiMac::SetWifiPhys(const std::vector>& phys) // the link may already exist in case we are setting new PHY objects // (ResetWifiPhys just nullified the PHY(s) but left the links) // or the remote station managers were configured first - if (i == m_links.size()) - { - m_links.push_back(CreateLinkEntity()); - m_links.back()->id = i; - } - NS_ABORT_IF(i != m_links[i]->id); - m_links[i]->phy = phys[i]; + auto [it, inserted] = m_links.emplace(i, CreateLinkEntity()); + it->second->phy = phys[i]; } } @@ -985,7 +976,7 @@ void WifiMac::ResetWifiPhys() { NS_LOG_FUNCTION(this); - for (auto& link : m_links) + for (auto& [id, link] : m_links) { if (link->feManager) { @@ -1357,9 +1348,9 @@ WifiMac::DeaggregateAmsduAndForward(Ptr mpdu) std::optional WifiMac::GetMldAddress(const Mac48Address& remoteAddr) const { - for (std::size_t linkId = 0; linkId < m_links.size(); linkId++) + for (const auto& [id, link] : m_links) { - if (auto mldAddress = m_links[linkId]->stationManager->GetMldAddress(remoteAddr)) + if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr)) { return *mldAddress; } @@ -1370,7 +1361,7 @@ WifiMac::GetMldAddress(const Mac48Address& remoteAddr) const Mac48Address WifiMac::GetLocalAddress(const Mac48Address& remoteAddr) const { - for (const auto& link : m_links) + for (const auto& [id, link] : m_links) { if (auto mldAddress = link->stationManager->GetMldAddress(remoteAddr)) { @@ -1511,7 +1502,7 @@ WifiMac::GetEhtSupported() const bool WifiMac::GetHtSupported(const Mac48Address& address) const { - for (const auto& link : m_links) + for (const auto& [id, link] : m_links) { if (link->stationManager->GetHtSupported(address)) { @@ -1524,7 +1515,7 @@ WifiMac::GetHtSupported(const Mac48Address& address) const bool WifiMac::GetVhtSupported(const Mac48Address& address) const { - for (const auto& link : m_links) + for (const auto& [id, link] : m_links) { if (link->stationManager->GetVhtSupported(address)) { @@ -1537,7 +1528,7 @@ WifiMac::GetVhtSupported(const Mac48Address& address) const bool WifiMac::GetHeSupported(const Mac48Address& address) const { - for (const auto& link : m_links) + for (const auto& [id, link] : m_links) { if (link->stationManager->GetHeSupported(address)) { @@ -1550,7 +1541,7 @@ WifiMac::GetHeSupported(const Mac48Address& address) const bool WifiMac::GetEhtSupported(const Mac48Address& address) const { - for (const auto& link : m_links) + for (const auto& [id, link] : m_links) { if (link->stationManager->GetEhtSupported(address)) { diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index 100dbc50b..ea009a4e1 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -27,6 +27,7 @@ #include "wifi-standards.h" #include +#include #include #include #include @@ -763,7 +764,6 @@ class WifiMac : public Object /// Destructor (a virtual method is needed to make this struct polymorphic) virtual ~LinkEntity(); - uint8_t id; //!< Link ID (starting at 0) Ptr phy; //!< Wifi PHY object Ptr channelAccessManager; //!< channel access manager object Ptr feManager; //!< Frame Exchange Manager object @@ -932,8 +932,8 @@ class WifiMac : public Object TypeOfStation m_typeOfStation; //!< the type of station - Ptr m_device; //!< Pointer to the device - std::vector> m_links; //!< vector of Link objects + Ptr m_device; //!< Pointer to the device + std::map> m_links; //!< ID-indexed map of Link objects Mac48Address m_address; //!< MAC address of this station Ssid m_ssid; //!< Service Set ID (SSID) From f8d9a43ad3692e7d2389b890091b463b1927ee85 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Tue, 16 May 2023 23:33:13 +0200 Subject: [PATCH 017/262] wifi: StaWifiMac correctly iterates over all of its links No longer assumes that link IDs are in range 0 to N-1 (where N is the number of links) --- src/wifi/model/sta-wifi-mac.cc | 90 +++++++++++++++++++--------------- src/wifi/model/sta-wifi-mac.h | 8 +++ src/wifi/model/wifi-mac.cc | 6 +++ src/wifi/model/wifi-mac.h | 5 ++ 4 files changed, 70 insertions(+), 39 deletions(-) diff --git a/src/wifi/model/sta-wifi-mac.cc b/src/wifi/model/sta-wifi-mac.cc index 2d71afb77..1f56540c5 100644 --- a/src/wifi/model/sta-wifi-mac.cc +++ b/src/wifi/model/sta-wifi-mac.cc @@ -206,6 +206,12 @@ StaWifiMac::GetLink(uint8_t linkId) const return static_cast(WifiMac::GetLink(linkId)); } +StaWifiMac::StaLinkEntity& +StaWifiMac::GetStaLink(const std::unique_ptr& link) const +{ + return static_cast(*link); +} + int64_t StaWifiMac::AssignStreams(int64_t stream) { @@ -415,10 +421,11 @@ StaWifiMac::GetMultiLinkElement(bool isReassoc, uint8_t linkId) const // frame is transmitted, the Link Info field of the Basic Multi-Link element carried // in the (Re)Association Request frame shall contain the corresponding Per-STA Profile // subelement(s). - for (uint8_t index = 0; index < GetNLinks(); index++) + for (const auto& [index, link] : GetLinks()) { - auto& link = GetLink(index); - if (index != linkId && link.apLinkId.has_value()) + const auto& staLink = GetStaLink(link); + + if (index != linkId && staLink.apLinkId.has_value()) { multiLinkElement.AddPerStaProfileSubelement(); auto& perStaProfile = multiLinkElement.GetPerStaProfile( @@ -427,7 +434,7 @@ StaWifiMac::GetMultiLinkElement(bool isReassoc, uint8_t linkId) const // for the corresponding non-AP STA that requests a link for multi-link (re)setup // with the AP MLD is set to the link ID of the AP affiliated with the AP MLD that // is operating on that link. The link ID is obtained during multi-link discovery - perStaProfile.SetLinkId(link.apLinkId.value()); + perStaProfile.SetLinkId(staLink.apLinkId.value()); // For each Per-STA Profile subelement included in the Link Info field, the // Complete Profile subfield of the STA Control field shall be set to 1 perStaProfile.SetCompleteProfile(); @@ -435,7 +442,7 @@ StaWifiMac::GetMultiLinkElement(bool isReassoc, uint8_t linkId) const // subfield in the STA Info field and is set to 1 if the STA MAC Address subfield // is present in the STA Info field; otherwise set to 0. An STA sets this subfield // to 1 when the element carries complete profile. - perStaProfile.SetStaMacAddress(link.feManager->GetAddress()); + perStaProfile.SetStaMacAddress(staLink.feManager->GetAddress()); perStaProfile.SetAssocRequest(GetAssociationRequest(isReassoc, index)); } } @@ -447,16 +454,18 @@ void StaWifiMac::SendAssociationRequest(bool isReassoc) { // find the link where the (Re)Association Request has to be sent - uint8_t linkId = 0; - while (linkId < GetNLinks()) + auto it = GetLinks().cbegin(); + while (it != GetLinks().cend()) { - if (GetLink(linkId).sendAssocReq) + if (GetStaLink(it->second).sendAssocReq) { break; } - linkId++; + it++; } - NS_ABORT_MSG_IF(linkId == GetNLinks(), "No link selected to send the (Re)Association Request"); + NS_ABORT_MSG_IF(it == GetLinks().cend(), + "No link selected to send the (Re)Association Request"); + uint8_t linkId = it->first; auto& link = GetLink(linkId); NS_ABORT_MSG_IF(!link.bssid.has_value(), "No BSSID set for the link on which the (Re)Association Request is to be sent"); @@ -567,12 +576,11 @@ StaWifiMac::StartScanning() WifiScanParams scanParams; scanParams.ssid = GetSsid(); - for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++) + for (const auto& [id, link] : GetLinks()) { WifiScanParams::ChannelList channel{ - (GetWifiPhy(linkId)->HasFixedPhyBand()) - ? WifiScanParams::Channel{0, GetWifiPhy(linkId)->GetPhyBand()} - : WifiScanParams::Channel{0, WIFI_PHY_BAND_UNSPECIFIED}}; + (link->phy->HasFixedPhyBand()) ? WifiScanParams::Channel{0, link->phy->GetPhyBand()} + : WifiScanParams::Channel{0, WIFI_PHY_BAND_UNSPECIFIED}}; scanParams.channelList.push_back(channel); } @@ -606,12 +614,12 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) NS_LOG_DEBUG("Attempting to associate with AP: " << *bestAp); UpdateApInfo(bestAp->m_frame, bestAp->m_apAddr, bestAp->m_bssid, bestAp->m_linkId); // reset info on links to setup - for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++) + for (auto& [id, link] : GetLinks()) { - auto& link = GetLink(linkId); - link.sendAssocReq = false; - link.apLinkId = std::nullopt; - link.bssid = std::nullopt; + auto& staLink = GetStaLink(link); + staLink.sendAssocReq = false; + staLink.apLinkId = std::nullopt; + staLink.bssid = std::nullopt; } // send Association Request on the link where the Beacon/Probe Response was received GetLink(bestAp->m_linkId).sendAssocReq = true; @@ -651,11 +659,11 @@ StaWifiMac::ScanningTimeout(const std::optional& bestAp) Time beaconInterval = std::visit(getBeaconInterval, bestAp->m_frame); Time delay = beaconInterval * m_maxMissedBeacons; // restart beacon watchdog for all links to setup - for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++) + for (const auto& [id, link] : GetLinks()) { - if (GetLink(linkId).apLinkId.has_value() || GetNLinks() == 1) + if (GetStaLink(link).apLinkId.has_value() || GetNLinks() == 1) { - RestartBeaconWatchdog(delay, linkId); + RestartBeaconWatchdog(delay, id); } } SetState(WAIT_ASSOC_RESP); @@ -716,9 +724,9 @@ StaWifiMac::Disassociated(uint8_t linkId) link.bssid = std::nullopt; link.phy->SetOffMode(); - for (uint8_t id = 0; id < GetNLinks(); id++) + for (const auto& [id, lnk] : GetLinks()) { - if (GetLink(id).apLinkId.has_value()) + if (GetStaLink(lnk).apLinkId.has_value()) { // found an enabled link return; @@ -741,9 +749,9 @@ StaWifiMac::Disassociated(uint8_t linkId) } m_aid = 0; // reset AID // ensure all links are on - for (uint8_t id = 0; id < GetNLinks(); id++) + for (const auto& [id, lnk] : GetLinks()) { - GetLink(id).phy->ResumeFromOff(); + lnk->phy->ResumeFromOff(); } TryToEnsureAssociated(); } @@ -782,11 +790,11 @@ StaWifiMac::GetSetupLinkIds() const } std::set linkIds; - for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++) + for (const auto& [id, link] : GetLinks()) { - if (GetLink(linkId).bssid) + if (GetStaLink(link).bssid) { - linkIds.insert(linkId); + linkIds.insert(id); } } return linkIds; @@ -1151,8 +1159,11 @@ StaWifiMac::ReceiveAssocResp(Ptr mpdu, uint8_t linkId) // create a list of all local Link IDs. IDs are removed as we find a corresponding // Per-STA Profile Subelements indicating successful association. Links with // remaining IDs are not setup - std::list setupLinks(GetNLinks()); - std::iota(setupLinks.begin(), setupLinks.end(), 0); + std::list setupLinks; + for (const auto& [id, link] : GetLinks()) + { + setupLinks.push_back(id); + } if (assocResp.GetStatusCode().IsSuccess()) { setupLinks.remove(linkId); @@ -1177,18 +1188,19 @@ StaWifiMac::ReceiveAssocResp(Ptr mpdu, uint8_t linkId) { auto& perStaProfile = mle->GetPerStaProfile(elem); uint8_t apLinkId = perStaProfile.GetLinkId(); - uint8_t staLinkid = 0; - while (staLinkid < GetNLinks()) + auto it = GetLinks().cbegin(); + while (it != GetLinks().cend()) { - if (GetLink(staLinkid).apLinkId == apLinkId) + if (GetStaLink(it->second).apLinkId == apLinkId) { break; } - staLinkid++; + it++; } + uint8_t staLinkid = 0; std::optional bssid; - NS_ABORT_MSG_IF(staLinkid == GetNLinks() || - !(bssid = GetLink(staLinkid).bssid).has_value(), + NS_ABORT_MSG_IF(it == GetLinks().cend() || + !(bssid = GetLink((staLinkid = it->first)).bssid).has_value(), "Setup for AP link ID " << apLinkId << " was not requested"); NS_ABORT_MSG_IF(*bssid != perStaProfile.GetStaMacAddress(), "The BSSID in the Per-STA Profile for link ID " @@ -1268,9 +1280,9 @@ StaWifiMac::SetPmModeAfterAssociation(uint8_t linkId) auto ackDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, GetLink(linkId).phy->GetPhyBand()); - for (uint8_t id = 0; id < GetNLinks(); id++) + for (const auto& [id, lnk] : GetLinks()) { - auto& link = GetLink(id); + auto& link = GetStaLink(lnk); if (!link.bssid) { diff --git a/src/wifi/model/sta-wifi-mac.h b/src/wifi/model/sta-wifi-mac.h index 9c185c480..1a1171cff 100644 --- a/src/wifi/model/sta-wifi-mac.h +++ b/src/wifi/model/sta-wifi-mac.h @@ -342,6 +342,14 @@ class StaWifiMac : public WifiMac */ StaLinkEntity& GetLink(uint8_t linkId) const; + /** + * Cast the given LinkEntity object to StaLinkEntity. + * + * \param link the given LinkEntity object + * \return a reference to the object casted to StaLinkEntity + */ + StaLinkEntity& GetStaLink(const std::unique_ptr& link) const; + private: /** * The current MAC state of the STA. diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index 74b4aba99..82c8f789f 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -913,6 +913,12 @@ WifiMac::CreateLinkEntity() const return std::make_unique(); } +const std::map>& +WifiMac::GetLinks() const +{ + return m_links; +} + WifiMac::LinkEntity& WifiMac::GetLink(uint8_t linkId) const { diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index ea009a4e1..da62abf65 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -773,6 +773,11 @@ class WifiMac : public Object bool dsssSupported{false}; //!< set to \c true iff this WifiMac is to model 802.11b }; + /** + * \return a const reference to the map of link entities + */ + const std::map>& GetLinks() const; + /** * Get a reference to the link associated with the given ID. * From 990fcc72f0f7cf01fbf41ba951876b209269d1f4 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 15 May 2023 17:31:56 +0200 Subject: [PATCH 018/262] wifi: Add support to WifiMac for swapping links --- .../model/eht/eht-frame-exchange-manager.cc | 8 ++ src/wifi/model/wifi-mac.cc | 68 ++++++++++ src/wifi/model/wifi-mac.h | 19 +++ src/wifi/test/wifi-mlo-test.cc | 116 ++++++++++++++++++ 4 files changed, 211 insertions(+) diff --git a/src/wifi/model/eht/eht-frame-exchange-manager.cc b/src/wifi/model/eht/eht-frame-exchange-manager.cc index 97ab816b2..00c61cbbc 100644 --- a/src/wifi/model/eht/eht-frame-exchange-manager.cc +++ b/src/wifi/model/eht/eht-frame-exchange-manager.cc @@ -59,6 +59,14 @@ EhtFrameExchangeManager::~EhtFrameExchangeManager() void EhtFrameExchangeManager::SetLinkId(uint8_t linkId) { + if (auto protectionManager = GetProtectionManager()) + { + protectionManager->SetLinkId(linkId); + } + if (auto ackManager = GetAckManager()) + { + ackManager->SetLinkId(linkId); + } m_msduAggregator->SetLinkId(linkId); m_mpduAggregator->SetLinkId(linkId); HeFrameExchangeManager::SetLinkId(linkId); diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index 82c8f789f..830360723 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -934,6 +934,22 @@ WifiMac::GetNLinks() const return m_links.size(); } +void +WifiMac::UpdateLinkId(uint8_t id) +{ + NS_LOG_FUNCTION(this << id); + + auto& link = GetLink(id); + if (link.feManager) + { + link.feManager->SetLinkId(id); + } + if (link.channelAccessManager) + { + link.channelAccessManager->SetLinkId(id); + } +} + std::optional WifiMac::GetLinkIdByAddress(const Mac48Address& address) const { @@ -947,6 +963,58 @@ WifiMac::GetLinkIdByAddress(const Mac48Address& address) const return std::nullopt; } +void +WifiMac::SwapLinks(std::map links) +{ + NS_LOG_FUNCTION(this); + + while (!links.empty()) + { + auto from = links.cbegin()->first; + auto to = links.cbegin()->second; + + if (from == to) + { + // nothing to do + links.erase(links.cbegin()); + continue; + } + + std::unique_ptr linkToMove; + NS_ASSERT(m_links.find(from) != m_links.cend()); + linkToMove.swap(m_links.at(from)); // from is now out of m_links + auto empty = from; // track empty cell in m_links + + do + { + auto [it, inserted] = + m_links.emplace(to, nullptr); // insert an element with key to if not present + m_links[to].swap(linkToMove); // to is the link to move now + UpdateLinkId(to); + links.erase(from); + if (!linkToMove) + { + if (inserted) + { + m_links.erase(empty); + } + break; + } + + auto nextTo = links.find(to); + if (nextTo == links.cend()) + { + // no new position specified for 'to', use the current empty cell + m_links[empty].swap(linkToMove); + break; + } + + from = to; + to = nextTo->second; + } while (true); + } +} + void WifiMac::SetWifiPhys(const std::vector>& phys) { diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index da62abf65..1f167669b 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -752,6 +752,16 @@ class WifiMac : public Object */ virtual void DeaggregateAmsduAndForward(Ptr mpdu); + /** + * Swap the links based on the information included in the given map. This method + * is normally called by a non-AP MLD upon completing ML setup to have its link IDs + * match AP MLD's link IDs. + * + * \param links a set of pairs (from, to) each mapping a current link ID to the + * link ID it has to become (i.e., link 'from' becomes link 'to') + */ + void SwapLinks(std::map links); + /** * Structure holding information specific to a single link. Here, the meaning of * "link" is that of the 11be amendment which introduced multi-link devices. For @@ -841,6 +851,15 @@ class WifiMac : public Object */ virtual std::unique_ptr CreateLinkEntity() const; + /** + * This method is intended to be called when a link changes ID in order to update the + * link ID stored by the Frame Exchange Manager and the Channel Access Manager operating + * on that link. + * + * \param id the (new) ID of the link that has changed ID + */ + void UpdateLinkId(uint8_t id); + /** * This method is called if this device is an MLD to determine the MAC address of * the affiliated STA used to communicate with the single link device having the diff --git a/src/wifi/test/wifi-mlo-test.cc b/src/wifi/test/wifi-mlo-test.cc index 702c9a17c..c051097f7 100644 --- a/src/wifi/test/wifi-mlo-test.cc +++ b/src/wifi/test/wifi-mlo-test.cc @@ -189,6 +189,121 @@ GetRnrLinkInfoTest::DoRun() "Unexpected tbtt ID of the second reported AP"); } +/** + * \ingroup wifi-test + * \ingroup tests + * + * Test the WifiMac::SwapLinks() method. + */ +class MldSwapLinksTest : public TestCase +{ + /** + * Test WifiMac subclass used to access the SwapLinks method. + */ + class TestWifiMac : public WifiMac + { + public: + ~TestWifiMac() override = default; + + using WifiMac::GetLinks; + using WifiMac::SwapLinks; + + bool CanForwardPacketsTo(Mac48Address to) const override + { + return true; + } + + void Enqueue(Ptr packet, Mac48Address to) override + { + } + }; + + public: + MldSwapLinksTest(); + ~MldSwapLinksTest() override = default; + + protected: + void DoRun() override; + + private: + /** + * Run a single test case. + * + * \param text string identifying the test case + * \param nLinks the number of links of the MLD + * \param links a set of pairs (from, to) each mapping a current link ID to the + * link ID it has to become (i.e., link 'from' becomes link 'to') + * \param expected maps each link ID to the id of the PHY that is expected + * to operate on that link after the swap + */ + void RunOne(std::string text, + std::size_t nLinks, + const std::map& links, + const std::map& expected); +}; + +MldSwapLinksTest::MldSwapLinksTest() + : TestCase("Test the WifiMac::SwapLinks() method") +{ +} + +void +MldSwapLinksTest::RunOne(std::string text, + std::size_t nLinks, + const std::map& links, + const std::map& expected) +{ + TestWifiMac mac; + + std::vector> phys; + for (std::size_t i = 0; i < nLinks; i++) + { + phys.emplace_back(CreateObject()); + } + mac.SetWifiPhys(phys); // create links containing the given PHYs + + mac.SwapLinks(links); + + NS_TEST_EXPECT_MSG_EQ(mac.GetNLinks(), nLinks, "Number of links changed after swapping"); + + for (const auto& [linkId, phyId] : expected) + { + NS_TEST_ASSERT_MSG_EQ(mac.GetLinks().count(linkId), + 1, + "Link ID " << +linkId << " does not exist"); + + NS_TEST_ASSERT_MSG_LT(+phyId, nLinks, "Invalid PHY ID"); + + // the id of the PHY operating on a link is the original ID of the link + NS_TEST_EXPECT_MSG_EQ(mac.GetWifiPhy(linkId), + phys.at(phyId), + text << ": Link " << +phyId << " has not been moved to link " + << +linkId); + } +} + +void +MldSwapLinksTest::DoRun() +{ + RunOne("No change needed", 3, {{0, 0}, {1, 1}, {2, 2}}, {{0, 0}, {1, 1}, {2, 2}}); + RunOne("Circular swapping", 3, {{0, 2}, {1, 0}, {2, 1}}, {{0, 1}, {1, 2}, {2, 0}}); + RunOne("Swapping two links, one unchanged", 3, {{0, 2}, {2, 0}}, {{0, 2}, {1, 1}, {2, 0}}); + RunOne("Non-circular swapping, autodetect how to close the loop", + 3, + {{0, 2}, {2, 1}}, + {{0, 1}, {1, 2}, {2, 0}}); + RunOne("One move only, autodetect how to complete the swapping", + 3, + {{2, 0}}, + {{0, 2}, {1, 1}, {2, 0}}); + RunOne("Create a new link ID (2), remove the unused one (0)", + 2, + {{0, 1}, {1, 2}}, + {{1, 0}, {2, 1}}); + RunOne("One move only that creates a new link ID (2)", 2, {{0, 2}}, {{1, 1}, {2, 0}}); + RunOne("Move all links to a new set of IDs", 2, {{0, 2}, {1, 3}}, {{2, 0}, {3, 1}}); +} + /** * \ingroup wifi-test * \ingroup tests @@ -2632,6 +2747,7 @@ WifiMultiLinkOperationsTestSuite::WifiMultiLinkOperationsTestSuite() std::vector>; // IDs of link that cannot change PHY band AddTestCase(new GetRnrLinkInfoTest(), TestCase::QUICK); + AddTestCase(new MldSwapLinksTest(), TestCase::QUICK); for (const auto& [staChannels, apChannels, setupLinks, fixedPhyBands] : {// matching channels: setup all links From 1ab959a5121a044481eacfc1fe6c4df36de4a209 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Mon, 1 May 2023 13:07:07 +0200 Subject: [PATCH 019/262] wifi: Add a method to get the link on which a PHY is operating --- src/wifi/model/wifi-mac.cc | 21 +++++++++++++++++++++ src/wifi/model/wifi-mac.h | 16 ++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index 830360723..abfe6e69c 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -963,6 +963,27 @@ WifiMac::GetLinkIdByAddress(const Mac48Address& address) const return std::nullopt; } +std::optional +WifiMac::GetLinkForPhy(Ptr phy) const +{ + for (const auto& [id, link] : m_links) + { + if (link->phy == phy) + { + return id; + } + } + return std::nullopt; +} + +std::optional +WifiMac::GetLinkForPhy(std::size_t phyId) const +{ + NS_ABORT_UNLESS(phyId < m_device->GetNPhys()); + auto phy = m_device->GetPhy(phyId); + return GetLinkForPhy(phy); +} + void WifiMac::SwapLinks(std::map links) { diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index 1f167669b..a95521ac0 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -150,6 +150,22 @@ class WifiMac : public Object */ virtual std::optional GetLinkIdByAddress(const Mac48Address& address) const; + /** + * Get the ID of the link (if any) on which the given PHY is operating. + * + * \param phy the given PHY + * \return the ID of the link (if any) on which the given PHY is operating + */ + std::optional GetLinkForPhy(Ptr phy) const; + + /** + * Get the ID of the link (if any) on which the given PHY is operating. + * + * \param phyId the index of the given PHY in the vector of PHYs held by WifiNetDevice + * \return the ID of the link (if any) on which the given PHY is operating + */ + std::optional GetLinkForPhy(std::size_t phyId) const; + /** * \param remoteAddr the (MLD or link) address of a remote device * \return the MLD address of the remote device having the given (MLD or link) address, if From f32636714382b2fcedb252c66ba486bac31f75c2 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Thu, 18 May 2023 12:14:04 +0200 Subject: [PATCH 020/262] wifi: Add a WifiMac method to get the set of link IDs --- src/wifi/model/wifi-mac.cc | 14 ++++++++++++++ src/wifi/model/wifi-mac.h | 7 +++++++ 2 files changed, 21 insertions(+) diff --git a/src/wifi/model/wifi-mac.cc b/src/wifi/model/wifi-mac.cc index abfe6e69c..5b76b159f 100644 --- a/src/wifi/model/wifi-mac.cc +++ b/src/wifi/model/wifi-mac.cc @@ -897,6 +897,7 @@ WifiMac::SetWifiRemoteStationManagers( { // the link may already exist in case PHY objects were configured first auto [it, inserted] = m_links.emplace(i, CreateLinkEntity()); + m_linkIds.insert(i); it->second->stationManager = stationManagers[i]; } } @@ -934,6 +935,12 @@ WifiMac::GetNLinks() const return m_links.size(); } +const std::set& +WifiMac::GetLinkIds() const +{ + return m_linkIds; +} + void WifiMac::UpdateLinkId(uint8_t id) { @@ -1034,6 +1041,12 @@ WifiMac::SwapLinks(std::map links) to = nextTo->second; } while (true); } + + m_linkIds.clear(); + for (const auto& [id, link] : m_links) + { + m_linkIds.insert(id); + } } void @@ -1056,6 +1069,7 @@ WifiMac::SetWifiPhys(const std::vector>& phys) // (ResetWifiPhys just nullified the PHY(s) but left the links) // or the remote station managers were configured first auto [it, inserted] = m_links.emplace(i, CreateLinkEntity()); + m_linkIds.insert(i); it->second->phy = phys[i]; } } diff --git a/src/wifi/model/wifi-mac.h b/src/wifi/model/wifi-mac.h index a95521ac0..2c745d6aa 100644 --- a/src/wifi/model/wifi-mac.h +++ b/src/wifi/model/wifi-mac.h @@ -142,6 +142,12 @@ class WifiMac : public Object * \return the number of links used by this MAC */ uint8_t GetNLinks() const; + + /** + * \return the set of link IDs in use by this device + */ + const std::set& GetLinkIds() const; + /** * Get the ID of the link having the given MAC address, if any. * @@ -974,6 +980,7 @@ class WifiMac : public Object Ptr m_device; //!< Pointer to the device std::map> m_links; //!< ID-indexed map of Link objects + std::set m_linkIds; //!< IDs of the links in use Mac48Address m_address; //!< MAC address of this station Ssid m_ssid; //!< Service Set ID (SSID) From 44e62a838bbc72bae98d35012f8176a75879e6d7 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Thu, 18 May 2023 12:15:02 +0200 Subject: [PATCH 021/262] wifi: Fix MLO and EMLSR test not to assume that link ID equals PHY ID --- src/wifi/test/wifi-emlsr-test.cc | 82 +++++++++++--------- src/wifi/test/wifi-mlo-test.cc | 124 ++++++++++++++++--------------- 2 files changed, 109 insertions(+), 97 deletions(-) diff --git a/src/wifi/test/wifi-emlsr-test.cc b/src/wifi/test/wifi-emlsr-test.cc index 46e1e1707..058dd52bc 100644 --- a/src/wifi/test/wifi-emlsr-test.cc +++ b/src/wifi/test/wifi-emlsr-test.cc @@ -55,15 +55,6 @@ using namespace ns3; NS_LOG_COMPONENT_DEFINE("WifiEmlsrTest"); -static uint32_t -ContextToNodeId(std::string context) -{ - std::string sub = context.substr(10); - uint32_t pos = sub.find("/Device"); - uint32_t nodeId = std::stoi(sub.substr(0, pos)); - return nodeId; -} - /** * \ingroup wifi-test * \ingroup tests @@ -168,14 +159,14 @@ class EmlsrOperationsTestBase : public TestCase /** * Callback invoked when a FEM passes PSDUs to the PHY. * - * \param linkId the ID of the link transmitting the PSDUs - * \param context the context + * \param mac the MAC transmitting the PSDUs + * \param phyId the ID of the PHY transmitting the PSDUs * \param psduMap the PSDU map * \param txVector the TX vector * \param txPowerW the tx power in Watts */ - virtual void Transmit(uint8_t linkId, - std::string context, + virtual void Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW); @@ -202,6 +193,7 @@ class EmlsrOperationsTestBase : public TestCase WifiConstPsduMap psduMap; ///< transmitted PSDU map WifiTxVector txVector; ///< TXVECTOR uint8_t linkId; ///< link ID + uint8_t phyId; ///< ID of the transmitting PHY }; std::set m_linksToEnableEmlsrOn; /**< IDs of the links on which EMLSR mode has to @@ -250,21 +242,24 @@ EmlsrOperationsTestBase::EmlsrOperationsTestBase(const std::string& name) } void -EmlsrOperationsTestBase::Transmit(uint8_t linkId, - std::string context, +EmlsrOperationsTestBase::Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) { - m_txPsdus.push_back({Simulator::Now(), psduMap, txVector, linkId}); + auto linkId = mac->GetLinkForPhy(phyId); + NS_TEST_ASSERT_MSG_EQ(linkId.has_value(), true, "No link found for PHY ID " << +phyId); + m_txPsdus.push_back({Simulator::Now(), psduMap, txVector, *linkId, phyId}); + auto txDuration = - WifiPhy::CalculateTxDuration(psduMap, txVector, m_apMac->GetWifiPhy(linkId)->GetPhyBand()); + WifiPhy::CalculateTxDuration(psduMap, txVector, mac->GetWifiPhy(*linkId)->GetPhyBand()); for (const auto& [aid, psdu] : psduMap) { std::stringstream ss; - ss << std::setprecision(10) << "PSDU #" << m_txPsdus.size() << " Link ID " << +linkId << " " - << psdu->GetHeader(0).GetTypeString(); + ss << std::setprecision(10) << "PSDU #" << m_txPsdus.size() << " Link ID " + << +linkId.value() << " Phy ID " << +phyId << " " << psdu->GetHeader(0).GetTypeString(); if (psdu->GetHeader(0).IsAction()) { ss << " "; @@ -375,11 +370,22 @@ EmlsrOperationsTestBase::DoSetup() } // Trace PSDUs passed to the PHY on AP MLD and non-AP MLDs - for (uint8_t linkId = 0; linkId < m_apMac->GetNLinks(); linkId++) + for (uint8_t phyId = 0; phyId < m_apMac->GetDevice()->GetNPhys(); phyId++) { - Config::Connect("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phys/" + - std::to_string(linkId) + "/PhyTxPsduBegin", - MakeCallback(&EmlsrOperationsTestBase::Transmit, this).Bind(linkId)); + Config::ConnectWithoutContext( + "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) + + "/PhyTxPsduBegin", + MakeCallback(&EmlsrOperationsTestBase::Transmit, this).Bind(m_apMac, phyId)); + } + for (std::size_t i = 0; i < m_nEmlsrStations + m_nNonEmlsrStations; i++) + { + for (uint8_t phyId = 0; phyId < m_staMacs[i]->GetDevice()->GetNPhys(); phyId++) + { + Config::ConnectWithoutContext( + "/NodeList/" + std::to_string(i + 1) + "/DeviceList/*/$ns3::WifiNetDevice/Phys/" + + std::to_string(phyId) + "/PhyTxPsduBegin", + MakeCallback(&EmlsrOperationsTestBase::Transmit, this).Bind(m_staMacs[i], phyId)); + } } // Uncomment the lines below to write PCAP files @@ -547,8 +553,8 @@ class EmlNotificationExchangeTest : public EmlsrOperationsTestBase protected: void DoSetup() override; void DoRun() override; - void Transmit(uint8_t linkId, - std::string context, + void Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override; @@ -651,12 +657,15 @@ EmlNotificationExchangeTest::DoSetup() } void -EmlNotificationExchangeTest::Transmit(uint8_t linkId, - std::string context, +EmlNotificationExchangeTest::Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) { + EmlsrOperationsTestBase::Transmit(mac, phyId, psduMap, txVector, txPowerW); + auto linkId = m_txPsdus.back().linkId; + auto psdu = psduMap.begin()->second; switch (psdu->GetHeader(0).GetType()) @@ -690,8 +699,6 @@ EmlNotificationExchangeTest::Transmit(uint8_t linkId, default:; } - - EmlsrOperationsTestBase::Transmit(linkId, context, psduMap, txVector, txPowerW); } void @@ -970,8 +977,8 @@ class EmlsrDlTxopTest : public EmlsrOperationsTestBase protected: void DoSetup() override; void DoRun() override; - void Transmit(uint8_t linkId, - std::string context, + void Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override; @@ -1086,14 +1093,17 @@ EmlsrDlTxopTest::EmlsrDlTxopTest(std::size_t nEmlsrStations, } void -EmlsrDlTxopTest::Transmit(uint8_t linkId, - std::string context, +EmlsrDlTxopTest::Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) { + EmlsrOperationsTestBase::Transmit(mac, phyId, psduMap, txVector, txPowerW); + auto linkId = m_txPsdus.back().linkId; + auto psdu = psduMap.begin()->second; - auto nodeId = ContextToNodeId(context); + auto nodeId = mac->GetDevice()->GetNode()->GetId(); switch (psdu->GetHeader(0).GetType()) { @@ -1105,7 +1115,7 @@ EmlsrDlTxopTest::Transmit(uint8_t linkId, // this AssocReq is being sent by an EMLSR client. The other EMLSR links should be // in powersave mode after association; we let the non-EMLSR links transition to // active mode (by sending data null frames) after association - for (uint8_t id = 0; id < m_staMacs.at(nodeId - 1)->GetNLinks(); id++) + for (const auto id : m_staMacs.at(nodeId - 1)->GetLinkIds()) { if (id != linkId && m_emlsrLinks.count(id) == 1) { @@ -1146,8 +1156,6 @@ EmlsrDlTxopTest::Transmit(uint8_t linkId, default:; } - - EmlsrOperationsTestBase::Transmit(linkId, context, psduMap, txVector, txPowerW); } void diff --git a/src/wifi/test/wifi-mlo-test.cc b/src/wifi/test/wifi-mlo-test.cc index c051097f7..9eb20a309 100644 --- a/src/wifi/test/wifi-mlo-test.cc +++ b/src/wifi/test/wifi-mlo-test.cc @@ -337,14 +337,14 @@ class MultiLinkOperationsTestBase : public TestCase /** * Callback invoked when a FEM passes PSDUs to the PHY. * - * \param linkId the ID of the link transmitting the PSDUs - * \param context the context + * \param mac the MAC transmitting the PSDUs + * \param phyId the ID of the PHY transmitting the PSDUs * \param psduMap the PSDU map * \param txVector the TX vector * \param txPowerW the tx power in Watts */ - virtual void Transmit(uint8_t linkId, - std::string context, + virtual void Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW); @@ -379,6 +379,7 @@ class MultiLinkOperationsTestBase : public TestCase WifiConstPsduMap psduMap; ///< transmitted PSDU map WifiTxVector txVector; ///< TXVECTOR uint8_t linkId; ///< link ID + uint8_t phyId; ///< ID of the transmitting PHY }; std::vector m_txPsdus; ///< transmitted PSDUs @@ -489,7 +490,7 @@ MultiLinkOperationsTestBase::CheckAddresses(Ptr psdu, bool found = false; for (uint8_t i = 0; i < m_nStations; i++) { - for (uint8_t linkId = 0; linkId < m_staMacs[i]->GetNLinks(); linkId++) + for (const auto& linkId : m_staMacs[i]->GetLinkIds()) { if (m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress() == *staAddr) { @@ -510,21 +511,24 @@ MultiLinkOperationsTestBase::CheckAddresses(Ptr psdu, } void -MultiLinkOperationsTestBase::Transmit(uint8_t linkId, - std::string context, +MultiLinkOperationsTestBase::Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) { - m_txPsdus.push_back({Simulator::Now(), psduMap, txVector, linkId}); + auto linkId = mac->GetLinkForPhy(phyId); + NS_TEST_ASSERT_MSG_EQ(linkId.has_value(), true, "No link found for PHY ID " << +phyId); + m_txPsdus.push_back({Simulator::Now(), psduMap, txVector, *linkId, phyId}); for (const auto& [aid, psdu] : psduMap) { std::stringstream ss; - ss << std::setprecision(10) << "PSDU #" << m_txPsdus.size() << " Link ID " << +linkId << " " - << psdu->GetHeader(0).GetTypeString() << " #MPDUs " << psdu->GetNMpdus() - << " duration/ID " << psdu->GetHeader(0).GetDuration() << " RA = " << psdu->GetAddr1() - << " TA = " << psdu->GetAddr2() << " ADDR3 = " << psdu->GetHeader(0).GetAddr3() + ss << std::setprecision(10) << "PSDU #" << m_txPsdus.size() << " Link ID " + << +linkId.value() << " Phy ID " << +phyId << " " << psdu->GetHeader(0).GetTypeString() + << " #MPDUs " << psdu->GetNMpdus() << " duration/ID " << psdu->GetHeader(0).GetDuration() + << " RA = " << psdu->GetAddr1() << " TA = " << psdu->GetAddr2() + << " ADDR3 = " << psdu->GetHeader(0).GetAddr3() << " ToDS = " << psdu->GetHeader(0).IsToDs() << " FromDS = " << psdu->GetHeader(0).IsFromDs(); if (psdu->GetHeader(0).IsQosData()) @@ -641,22 +645,22 @@ MultiLinkOperationsTestBase::DoSetup() } // Trace PSDUs passed to the PHY on all devices - for (uint8_t linkId = 0; linkId < StaticCast(apDevices.Get(0))->GetNPhys(); - linkId++) + for (uint8_t phyId = 0; phyId < m_apMac->GetDevice()->GetNPhys(); phyId++) { - Config::Connect("/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + - std::to_string(linkId) + "/PhyTxPsduBegin", - MakeCallback(&MultiLinkOperationsTestBase::Transmit, this).Bind(linkId)); + Config::ConnectWithoutContext( + "/NodeList/0/DeviceList/*/$ns3::WifiNetDevice/Phys/" + std::to_string(phyId) + + "/PhyTxPsduBegin", + MakeCallback(&MultiLinkOperationsTestBase::Transmit, this).Bind(m_apMac, phyId)); } for (uint8_t i = 0; i < m_nStations; i++) { - for (uint8_t linkId = 0; linkId < StaticCast(staDevices.Get(i))->GetNPhys(); - linkId++) + for (uint8_t phyId = 0; phyId < m_staMacs[i]->GetDevice()->GetNPhys(); phyId++) { - Config::Connect( - "/NodeList/" + std::to_string(i + 1) + "/DeviceList/*/$ns3::WifiNetDevice/Phys/" + - std::to_string(linkId) + "/PhyTxPsduBegin", - MakeCallback(&MultiLinkOperationsTestBase::Transmit, this).Bind(linkId)); + Config::ConnectWithoutContext("/NodeList/" + std::to_string(i + 1) + + "/DeviceList/*/$ns3::WifiNetDevice/Phys/" + + std::to_string(phyId) + "/PhyTxPsduBegin", + MakeCallback(&MultiLinkOperationsTestBase::Transmit, this) + .Bind(m_staMacs[i], phyId)); } } @@ -1302,8 +1306,8 @@ class MultiLinkTxTest : public MultiLinkOperationsTestBase */ void CheckBlockAck(Ptr psdu, const WifiTxVector& txVector, uint8_t linkId); - void Transmit(uint8_t linkId, - std::string context, + void Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override; @@ -1367,12 +1371,15 @@ MultiLinkTxTest::MultiLinkTxTest(WifiTrafficPattern trafficPattern, } void -MultiLinkTxTest::Transmit(uint8_t linkId, - std::string context, +MultiLinkTxTest::Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) { + MultiLinkOperationsTestBase::Transmit(mac, phyId, psduMap, txVector, txPowerW); + auto linkId = m_txPsdus.back().linkId; + auto psdu = psduMap.begin()->second; switch (psdu->GetHeader(0).GetType()) @@ -1397,7 +1404,7 @@ MultiLinkTxTest::Transmit(uint8_t linkId, { // determine the max number of simultaneous transmissions for this MPDU // (only if sent by the traffic source and this is not a broadcast frame) - if (m_baEnabled && linkId < m_sourceMac->GetNLinks() && + if (m_baEnabled && m_sourceMac->GetLinkIds().count(linkId) == 1 && m_sourceMac->GetFrameExchangeManager(linkId)->GetAddress() == mpdu->GetHeader().GetAddr2() && !mpdu->GetHeader().GetAddr1().IsGroup()) @@ -1476,8 +1483,6 @@ MultiLinkTxTest::Transmit(uint8_t linkId, } default:; } - - MultiLinkOperationsTestBase::Transmit(linkId, context, psduMap, txVector, txPowerW); } void @@ -1645,15 +1650,14 @@ MultiLinkTxTest::DoSetup() m_errorModels[m_apMac->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; m_apMac->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); } - for (std::size_t linkId = 0; linkId < m_staMacs[0]->GetNLinks(); linkId++) + for (std::size_t i : {0, 1}) { - auto errorModel = CreateObject(); - m_errorModels[m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; - m_staMacs[0]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); - - errorModel = CreateObject(); - m_errorModels[m_staMacs[1]->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; - m_staMacs[1]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); + for (const auto linkId : m_staMacs[i]->GetLinkIds()) + { + auto errorModel = CreateObject(); + m_errorModels[m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; + m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); + } } } @@ -1921,8 +1925,8 @@ class MultiLinkMuTxTest : public MultiLinkOperationsTestBase */ void CheckBlockAck(Ptr psdu, const WifiTxVector& txVector, uint8_t linkId); - void Transmit(uint8_t linkId, - std::string context, + void Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override; @@ -1984,12 +1988,15 @@ MultiLinkMuTxTest::MultiLinkMuTxTest(WifiMuTrafficPattern muTrafficPattern, } void -MultiLinkMuTxTest::Transmit(uint8_t linkId, - std::string context, +MultiLinkMuTxTest::Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) { + MultiLinkOperationsTestBase::Transmit(mac, phyId, psduMap, txVector, txPowerW); + auto linkId = m_txPsdus.back().linkId; + CtrlTriggerHeader trigger; for (const auto& [staId, psdu] : psduMap) @@ -2092,7 +2099,7 @@ MultiLinkMuTxTest::Transmit(uint8_t linkId, m_waitFirstTf = false; // the AP is starting the transmission of the Basic Trigger frame, so generate // the configured number of packets at STAs, which are sent in TB PPDUs - auto band = m_apMac->GetWifiPhy(linkId)->GetPhyBand(); + auto band = mac->GetWifiPhy(linkId)->GetPhyBand(); Time txDuration = WifiPhy::CalculateTxDuration(psduMap, txVector, band); for (uint8_t i = 0; i < m_nStations; i++) { @@ -2112,8 +2119,6 @@ MultiLinkMuTxTest::Transmit(uint8_t linkId, default:; } } - - MultiLinkOperationsTestBase::Transmit(linkId, context, psduMap, txVector, txPowerW); } void @@ -2341,15 +2346,14 @@ MultiLinkMuTxTest::DoSetup() m_errorModels[m_apMac->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; m_apMac->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); } - for (std::size_t linkId = 0; linkId < m_staMacs[0]->GetNLinks(); linkId++) + for (std::size_t i : {0, 1}) { - auto errorModel = CreateObject(); - m_errorModels[m_staMacs[0]->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; - m_staMacs[0]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); - - errorModel = CreateObject(); - m_errorModels[m_staMacs[1]->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; - m_staMacs[1]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); + for (const auto linkId : m_staMacs[i]->GetLinkIds()) + { + auto errorModel = CreateObject(); + m_errorModels[m_staMacs[i]->GetFrameExchangeManager(linkId)->GetAddress()] = errorModel; + m_staMacs[i]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(errorModel); + } } } @@ -2556,8 +2560,8 @@ class ReleaseSeqNoAfterCtsTimeoutTest : public MultiLinkOperationsTestBase protected: void DoSetup() override; void DoRun() override; - void Transmit(uint8_t linkId, - std::string context, + void Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) override; @@ -2597,7 +2601,7 @@ ReleaseSeqNoAfterCtsTimeoutTest::DoSetup() MultiLinkOperationsTestBase::DoSetup(); // install post reception error model on all STAs affiliated with non-AP MLD - for (std::size_t linkId = 0; linkId < m_staMacs[0]->GetNLinks(); linkId++) + for (const auto linkId : m_staMacs[0]->GetLinkIds()) { m_staMacs[0]->GetWifiPhy(linkId)->SetPostReceptionErrorModel(m_errorModel); } @@ -2647,12 +2651,14 @@ ReleaseSeqNoAfterCtsTimeoutTest::StartTraffic() } void -ReleaseSeqNoAfterCtsTimeoutTest::Transmit(uint8_t linkId, - std::string context, +ReleaseSeqNoAfterCtsTimeoutTest::Transmit(Ptr mac, + uint8_t phyId, WifiConstPsduMap psduMap, WifiTxVector txVector, double txPowerW) { + MultiLinkOperationsTestBase::Transmit(mac, phyId, psduMap, txVector, txPowerW); + auto psdu = psduMap.begin()->second; if (psdu->GetHeader(0).IsRts() && !m_rtsCorrupted) @@ -2672,8 +2678,6 @@ ReleaseSeqNoAfterCtsTimeoutTest::Transmit(uint8_t linkId, m_apMac->GetDevice()->GetNode()->AddApplication(GetApplication()); } } - - MultiLinkOperationsTestBase::Transmit(linkId, context, psduMap, txVector, txPowerW); } void From 0901e95ce479eefd7e2600f699f614410f735864 Mon Sep 17 00:00:00 2001 From: Stefano Avallone Date: Thu, 18 May 2023 19:57:08 +0200 Subject: [PATCH 022/262] wifi: Add Txop support for link swapping --- src/wifi/model/qos-txop.cc | 8 ++-- src/wifi/model/txop.cc | 87 ++++++++++++++++++++++++-------------- src/wifi/model/txop.h | 22 +++++++--- src/wifi/model/wifi-mac.cc | 13 ++++++ 4 files changed, 88 insertions(+), 42 deletions(-) diff --git a/src/wifi/model/qos-txop.cc b/src/wifi/model/qos-txop.cc index fb5233e93..8d02ea937 100644 --- a/src/wifi/model/qos-txop.cc +++ b/src/wifi/model/qos-txop.cc @@ -640,9 +640,9 @@ QosTxop::GotAddBaResponse(const MgtAddBaResponseHeader& respHdr, Mac48Address re m_baManager->NotifyOriginatorAgreementRejected(recipient, tid); } - for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++) + for (const auto& [id, link] : GetLinks()) { - StartAccessIfNeeded(linkId); + StartAccessIfNeeded(id); } } @@ -662,9 +662,9 @@ QosTxop::NotifyOriginatorAgreementNoReply(const Mac48Address& recipient, uint8_t m_baManager->NotifyOriginatorAgreementNoReply(recipient, tid); // the recipient has been "unblocked" and transmissions can resume using normal // acknowledgment, hence start access (if needed) on all the links - for (uint8_t linkId = 0; linkId < GetNLinks(); linkId++) + for (const auto& [id, link] : GetLinks()) { - StartAccessIfNeeded(linkId); + StartAccessIfNeeded(id); } } diff --git a/src/wifi/model/txop.cc b/src/wifi/model/txop.cc index 011b97deb..1a645db79 100644 --- a/src/wifi/model/txop.cc +++ b/src/wifi/model/txop.cc @@ -169,15 +169,33 @@ Txop::CreateLinkEntity() const Txop::LinkEntity& Txop::GetLink(uint8_t linkId) const { - NS_ASSERT(linkId < m_links.size()); - NS_ASSERT(m_links.at(linkId)); // check that the pointer owns an object - return *m_links.at(linkId); + auto it = m_links.find(linkId); + NS_ASSERT(it != m_links.cend()); + NS_ASSERT(it->second); // check that the pointer owns an object + return *it->second; } -uint8_t -Txop::GetNLinks() const +const std::map>& +Txop::GetLinks() const { - return m_links.size(); + return m_links; +} + +void +Txop::SwapLinks(std::map links) +{ + NS_LOG_FUNCTION(this); + + decltype(m_links) tmp; + tmp.swap(m_links); // move all links to temporary map + for (const auto& [from, to] : links) + { + auto nh = tmp.extract(from); + nh.key() = to; + m_links.insert(std::move(nh)); + } + // move links remaining in tmp to m_links + m_links.merge(tmp); } void @@ -192,12 +210,9 @@ Txop::SetWifiMac(const Ptr mac) { NS_LOG_FUNCTION(this << mac); m_mac = mac; - m_links.resize(m_mac->GetNLinks()); - uint8_t linkId = 0; - for (auto& link : m_links) + for (const auto linkId : m_mac->GetLinkIds()) { - link = CreateLinkEntity(); - link->id = linkId++; + m_links.emplace(linkId, CreateLinkEntity()); } } @@ -229,9 +244,10 @@ void Txop::SetMinCws(std::vector minCws) { NS_ABORT_IF(minCws.size() != m_links.size()); - for (std::size_t linkId = 0; linkId < minCws.size(); linkId++) + std::size_t i = 0; + for (const auto& [id, link] : m_links) { - SetMinCw(minCws[linkId], linkId); + SetMinCw(minCws[i++], id); } } @@ -258,9 +274,10 @@ void Txop::SetMaxCws(std::vector maxCws) { NS_ABORT_IF(maxCws.size() != m_links.size()); - for (std::size_t linkId = 0; linkId < maxCws.size(); linkId++) + std::size_t i = 0; + for (const auto& [id, link] : m_links) { - SetMaxCw(maxCws[linkId], linkId); + SetMaxCw(maxCws[i++], id); } } @@ -355,9 +372,10 @@ void Txop::SetAifsns(std::vector aifsns) { NS_ABORT_IF(aifsns.size() != m_links.size()); - for (std::size_t linkId = 0; linkId < aifsns.size(); linkId++) + std::size_t i = 0; + for (const auto& [id, link] : m_links) { - SetAifsn(aifsns[linkId], linkId); + SetAifsn(aifsns[i++], id); } } @@ -381,9 +399,10 @@ Txop::SetTxopLimits(const std::vector