diff --git a/.clang-tidy b/.clang-tidy index eebfa02f0a..66224e8324 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -2,6 +2,7 @@ Checks: > -*, bugprone-argument-comment, bugprone-bool-pointer-implicit-conversion, + bugprone-branch-clone, bugprone-inaccurate-erase, bugprone-move-forwarding-reference, bugprone-redundant-branch-condition, diff --git a/.github/workflows/per_commit.yml b/.github/workflows/per_commit.yml index 1f298afd24..941a3d9d4b 100644 --- a/.github/workflows/per_commit.yml +++ b/.github/workflows/per_commit.yml @@ -142,7 +142,8 @@ jobs: ./ns3 build coverage_gcc cd ./build/coverage bash <(curl -s https://codecov.io/bash) -f ns3.info || echo "Codecov did not collect coverage reports" - + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} Windows_MinGW: runs-on: windows-latest defaults: diff --git a/.gitignore b/.gitignore index 46a4022ed0..6201d9a315 100644 --- a/.gitignore +++ b/.gitignore @@ -43,11 +43,7 @@ version.cache .gitlab-ci-local/ .idea/ -cmake-cache/ -cmake-build-debug/ -cmake-build-relwithdebinfo/ -cmake-build-minsizerel/ -cmake-build-release/ +cmake-*/ vcpkg/ .vs/ diff --git a/.ns3.supp b/.ns3.supp new file mode 100644 index 0000000000..63af0bbeb4 --- /dev/null +++ b/.ns3.supp @@ -0,0 +1,10 @@ +# This is the valgrind suppression file for ns-3. + +# libucs is included by openMPI. Added Feb 2024. +# Errors generated by openucx 1.15.0-2 +{ + ignore_libucs_init_memory_leak + Memcheck:Leak + ... + obj:*/libucs.so.* +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index e8f1593262..fe82acc854 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -22,4 +22,4 @@ } } ] -} \ No newline at end of file +} diff --git a/AUTHORS b/AUTHORS index 9214478b32..573414e17d 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,3 +1,4 @@ +Rami Abdallah Eduardo Abinader (eduardo.abinader@gmail.com) John Abraham (john.abraham.in@gmail.com) Danilo Abrignani (dabrignani@gmail.com) @@ -43,6 +44,7 @@ Matthew Bradbury (matt-bradbury@live.co.uk) Dan Broyles (muxman@sbcglobal.net) Jonathan Brugge (j.d.brugge@student.utwente.nl) Junling Bu (linlinjavaer@gmail.com) +Alessio Bugetti (alessiobugetti98@gmail.com) Elena Buchatskaia (borovkovaes@iitp.ru) Alessio Bugetti (alessiobugetti98@gmail.com) Nuno Cardoso (nunopcardoso@gmail.com) @@ -56,6 +58,7 @@ Aditya Chaudhary (adityach2002@gmail.com) Shobhit Chaurasia (000shobhitchaurasia@gmail.com) Luciano Jerez Chaves (ljerezchaves@gmail.com) Eugene Chemeritskiy (echemeritskiy@arccn.ru) +Rui Chen (rui@chenrui.dev) Yufei Cheng (yfcheng@ittc.ku.edu) Aditya Chirania (adityachirania97@gmail.com) Zhao Wen Chow (shu@mos.ics.keio.ac.jp) @@ -136,6 +139,7 @@ Atishay Jain (atishayjain25@gmail.com) Sourabh Jain (jainsourabh679@gmail.com) Vivek Jain (jain.vivek.anand@gmail.com) Sam Jansen (sam.jansen@gmail.com) +Jacob Janzen (jacob.a.s.janzen@gmail.com) Chandrakant Jena (chandrakant.barcelona@gmail.com) Liu Jian (liujatp@gmail.com) Sascha Alexander Jopen (jopen@informatik.uni-bonn.de) @@ -151,6 +155,7 @@ Nils Kattenbeck (nils.kattenbeck@rwth-aachen.de) Morteza Kheirkhah (m.kheirkhah@sussex.ac.uk) Jörg Christian Kirchhof (christian.kirchhof@rwth-aachen.de) Ohad Klausner +Wojtek Kosior (koszko@koszko.org) Katarina Koutlia (katerina.koutlia@cttc.es) Shravya Ks (shravya.ks0@gmail.com) Flavio Kubota (flaviokubota@gmail.com) @@ -193,6 +198,7 @@ Andrey Mazo (mazo@iitp.ru) Jonathan McCrohan (jmccroha@tcd.ie) Andrew McGregor (andrewmcgr@gmail.com) Miralem Mehic (miralemmehic@gmail.com) +Zili Meng (zilim@ieee.org) Levente Mészáros (levy@omnetpp.org) Vedran Miletić (rivanvx@gmail.com) Saswat Mishra (clicksaswat@gmail.com) @@ -270,11 +276,13 @@ Karsten Roscher (sfx@rocktale.de) Ali Rostami (a.rostami@rutgers.edu) Bill Roome (wdr@bell-labs.com) David Rua (david.rua@gmail.com) +Chan Ruihua (chenrh20@mails.tsinghua.edu.cn) Andrea Sacco (andrea.sacco85@gmail.com) Richard Sailer (richard_sailer@systemli.org) Lynne Salameh (l.salameh@cs.ucl.ac.uk) Providence Salumu Munga (Providence.Salumu@gmail.com, Providence.Salumu_Munga@it-sudparis.eu) Francisco Javier Sánchez-Roselly (fnavarro@ujaen.es) +Mattia Sandri (sandrimatt@dei.unipd.it) Charitha Sangaraju (charitha29193@gmail.com) Siddharth Santurkar (siddharth.santurkar@ieee.org) Gaurav Sathe (gaurav.sathe@tcs.com) @@ -288,6 +296,7 @@ Ioannis Selinis (selinis.g@gmail.com) Tomasz Seweryn (tomasz.seweryn7@gmail.com) Dmitrii Shakshin (d.shakshin@gmail.com) Kulin Shah (m.kulin@gmail.com) +Muyuan Shen (shmy315@gmail.com) Guowang Shi (shiguowang2007@gmail.com) Phillip Sitbon (phillip.sitbon@gmail.com) Pedro Silva (pmms@inesctec.pt) diff --git a/CHANGES.md b/CHANGES.md index dd6572e6eb..eced4b4b2e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,50 @@ 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.41 to ns-3.42 +------------------------------- + +### New API +* (antenna) Added `CircularApertureAntennaModel` class which characterizes the antenna gain pattern of the reflector antenna with circular aperture described in 3GPP TR 38.811 v15.4.0, Section 6.4.1 +* (core) Objects now can be aggregated to multiple objects though the `Object::UnidirectionalAggregateObject` function. Objects aggregated in such a way can not use `GetObject` to access the objects they are aggregated to. +* (core) Added `TestVector` iterators and dot product operator for `Vector2D` and `Vector3D` types +* (mobility) Added a new mobility model `GeocentricConstantPositionMobilityModel` for orbital and/or aerial nodes, and coordinate conversion methods between geocentric and topocentric coordinate systems +* (propagation, spectrum) Added 3GPP 38.811 Non-Terrestrial Networks (NTNs) channel model. Specifically, the large-scale phenomena have been implemented by extending `ThreeGppPropagationLossModel` with classes representing the various NTN propagation scenarios (Dense Urban, Urban, Rural and Suburban), while the frequency-dependent phenomena have been implemented by defining the corresponding scenarios in `ThreeGppChannelModel`. +* (network) Added `ApplicationHelper` helper class to create and install applications, removing redundant code in existing helpers and reducing the burden to add yet another helper when a new application model is added. +* (wifi) Added a new **SingleRtsPerTxop** attribute to `WifiDefaultProtectionManager`, which, if set to true, prevents to use protection mechanisms (RTS or MU-RTS) more than once in a TXOP (unless required for specific purposes, such as transmitting an Initial Control Frame to an EMLSR client). +* (wifi) Added a new **RtsCtsTxDurationThresh** to `WifiRemoteStationManager` to enable RTS/CTS protection based on the TX duration of the data frame. Both the value of this attribute and the value of the existing **RtsCtsThreshold** attribute are evaluated: if either of the thresholds (or both) is exceeded, RTS/CTS is used. +* (wifi) New trace helper `WifiPhyRxTraceHelper` for detailed tracing of Wi-Fi Phy reception events +* (wifi) New trace sources `WifiPhy::SignalTransmission`, `SpectrumWifiPhy::SignalArrival`, and `YansWifiPhy::SignalArrival` +* (wifi) New trace sources `WifiPhyStateHelper::RxOutcome` and`WifiPhy::PhyRxPpduDrop`, to support additional tracing. + +### Changes to existing API + +* (applications) Applications have a new Attribute to set the IPv4 ToS field. +* (core) Deprecated enum `TestDuration` in `TestCase` class. It has been replaced by enum class `Duration`. +* (core) In `TestSuite` class, deprecated `ALL`, `UNIT`, `SYSTEM`, `EXAMPLE` and `PERFORMANCE`. They have been replaced by `Type::ALL`, `Type::UNIT`, `Type::SYSTEM`, `Type::EXAMPLE` and `Type::PERFORMANCE`, respectively. +* (core) Deprecated `EventId::IsRunning()`. It has been replaced with `EventId::IsPending()`. +* (energy) The model library code of the energy module now uses the nested namespace `energy`. +* (lr-wpan) `MacPibAttributeIdentifier` attribute ids are now standard compliant. +* (lr-wpan) Multiple new identifiers added to `MacPibAttributeIdentifier`. +* (lr-wpan) Adds standard version comments to `MLME-GET.request` function. +* (lr-wpan) In the MAC layer, renamed `m_selfExt` to the variable `m_macExtendedAddress` to make it consistent with the standard specification. +* (lr-wpan) The Lr-wpan module now uses the namespace `lrwpan`. +* (lr-wpan) The model library code of the lr-wpan module now uses the nested namespace `lrwpan`. +* (lr-wpan) The `LrWpan` prefix of variables, structs and enumerations in the PHY and MAC was shorten to reflect the recent namespace change. +* (wifi) Deprecated `WIFI_TID_TO_LINK_MAPPING_{NOT_SUPPORTED,SAME_LINK_SET,ANY_LINK_SET}`. They have been replaced by `WifiTidToLinkMappingNegSupport::{NOT_SUPPORTED,SAME_LINK_SET,ANY_LINK_SET}`, respectively. +* (wifi) Deprecated `{IDLE, CCA_BUSY, TX, RX, SWITCHING, SLEEP, OFF}`. They have been replaced by `WifiPhyState::{IDLE, CCA_BUSY, TX, RX, SWITCHING, SLEEP, OFF}`, respectively. +* (wifi) Obsoleted **Txop** attributes `MinCw`, `MaxCw`, `Aifsn` and `TxopLimit`. The corresponding attributes for multi-link devices (`MinCws`, `MaxCws`, `Aifsns` and `TxopLimits`) can be used instead. + +### Changes to build system + +* Removed support of the `experimental/filesystem` library, in favor of the official `filesystem` library. +* Fixed static and monolib builds when linking to a non ns-3 module library. + +### Changed behavior + +* (mobility) Fixed the corner rebound direction in `RandomWalk2d[Outdoor]MobilityModel` and the initial direction in case of node starting from a border or corner. +* (tcp) TcpCubic and TcpLinuxReno will no longer grow their congestion window when application-limited, now matching Linux behavior + Changes from ns-3.40 to ns-3.41 ------------------------------- @@ -41,6 +85,7 @@ Changes from ns-3.40 to ns-3.41 ```cpp MakeEnumAccessor(&AttributeObjectTest::m_enum), ``` + * (internet) Deprecated `Ipv4::WeakEsModel` and `Ipv4::GetWeakEsModel()`, `Ipv4::SetWeakEsModel(bool)` methods. Moved `Ipv6L3Protocol::StrongEndSystemModel` to `Ipv6::StrongEndSystemModel` and added `Ipv4::StrongEndSystemModel` with corresponding `GetStrongEndSystemModel()` and `SetStrongEndSystemModel(bool)` methods to improve end system model configuration options. * (lr-wpan) Change the CapabilityField parameter in `LrWpanMac::MlmeAssociateRequest` and `LrWpanMac::MlmeAssociateIndication` to a standard bitmap. * (lr-wpan) Change the MAC SuperframeField usage to a standard bitmap, this change impact parameters in the `BeaconPayloadHeader`. @@ -68,6 +113,7 @@ Changes from ns-3.40 to ns-3.41 * Added guard rails for scratch targets missing or containing more than one `main` function. ### Changed behavior + * (sixlowpan) Now uses RFC 7973 Ethertype by default * (spectrum) SpectrumChannel objects and the loss/delay models attached are now automatically initialized (Object::Initialize) at time zero * (tcp) TCP Cubic (the default congestion control in ns-3) now supports TCP-friendliness by default (see RFC 9438 Section 4.3), making the congestion window growth somewhat more aggressive. This follows the default Linux behavior. diff --git a/CMakeLists.txt b/CMakeLists.txt index 97656e0e82..0fd9b01147 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,7 +13,7 @@ file(STRINGS VERSION NS3_VER) # minimum compiler versions set(AppleClang_MinVersion 11.0.0) set(Clang_MinVersion 10.0.0) -set(GNU_MinVersion 9.0.0) +set(GNU_MinVersion 9.1.0) # common options option(NS3_ASSERT "Enable assert on failure" OFF) @@ -108,21 +108,6 @@ set(NS3_FILTER_MODULE_EXAMPLES_AND_TESTS "List of modules that should have their examples and tests built (e.g. lte;wifi)" ) -if(${NS3_CCACHE}) - # Use ccache if available - mark_as_advanced(CCACHE) - find_program(CCACHE ccache) - if(NOT ("${CCACHE}" STREQUAL "CCACHE-NOTFOUND")) - message(STATUS "CCache is enabled.") - set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) - execute_process( - COMMAND - ${CCACHE} --set-config - sloppiness=pch_defines,time_macros,include_file_mtime,include_file_ctime - ) - endif() -endif() - # Include macros used below include(build-support/macros-and-definitions.cmake) @@ -144,6 +129,21 @@ filter_enabled_and_disabled_modules( ns3rc_enabled_modules ns3rc_disabled_modules ) +if(${NS3_CCACHE}) + # Use ccache if available + mark_as_advanced(CCACHE) + find_program(CCACHE ccache) + if(NOT ("${CCACHE}" STREQUAL "CCACHE-NOTFOUND")) + message(STATUS "CCache is enabled.") + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE}) + execute_process( + COMMAND + ${CCACHE} --set-config + sloppiness=pch_defines,time_macros,include_file_mtime,include_file_ctime + ) + endif() +endif() + # ############################################################################## # Process options # # ############################################################################## diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0dd5528ace..a28d6d4829 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -13,6 +13,67 @@ 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.42 +------------ + +In this release, we have introduced pedantic compiler warnings to enhance C++ standard conformance and improve portability. Also, model library code in the lr-wpan and energy modules has been moved into a nested C++ namespace. + +### Availability + +This release is available from: + + +### Supported platforms + +This release is intended to work on systems with the following minimal +requirements (Note: not all ns-3 features are available on all systems): + +- g++-9 or later, or LLVM/clang++-10 or later +- Python 3.6 or later +- CMake 3.13 or later +- (macOS only) Xcode 11 or later +- (Windows only) Msys2/MinGW64 toolchain or WSL2 + +Python API requires [Cppyy](https://cppyy.readthedocs.io/en/latest/installation.html) and has only +been tested on Linux. As of this release, the latest known version to work with ns-3 is cppyy==3.1.2. + +### New user-visible features + +- (antenna) !1517 - Added `CircularApertureAntennaModel`, which mimics the reflector antenna with circular aperture described in 3GPP TR 38.811 v15.4.0, Section 6.4.1 +- (core) !1517 - Added `TestVector` iterators and dot product operator for `Vector2D` and `Vector3D` types +- (energy) !1948 - Adds C++ namespace 'energy' +- (lr-wpan) !1915 - Use MAC and PHY standard attribute ids +- (lr-wpan) !1924 - Adds MAC attribute identifiers +- (lr-wpan) !1927 - Adds standard version comments to MLME-GET.request function +- (lr-wpan) !1926 - Adds C++ namespace 'lrwpan' and prefix shortening +- (mobility) !1986 - Adds simple constant-mobility-example +- (mobility) !1517 - Added the `GeocentricConstantPositionMobilityModel` mobility model and coordinate conversion methods between geocentric and topocentric coordinate systems +- (propagation, spectrum) !1517 - Added 3GPP 38.811 Non-Terrestrial Networks channel model +- (network) !1828 - Added a common helper to create and install applications +- (wifi) - The `WifiMacHelper` provides a `SetDcf` and a `SetEdca` methods to configure attributes of `Txop` and `QosTxop` objects, respectively +- (wifi) - The `ApWifiMac` provides new attributes (`CwMinsForSta`, `CwMaxsForSta`, `AifsnsForSta` and `TxopLimitsForSta`) to define the EDCA access parameters to include in the EDCA Parameter Set advertised to associated stations +- (wifi) - The `WifiMacHelper` provides a `SetChannelAccessManager` and a `SetFrameExchangeManager` methods to configure attributes of `ChannelAccessManager` and `FrameExchangeManager` objects, respectively +- (wifi) - Simulation duration and data rate parameters of existing wifi examples changed to use Time and DataRate types +- (wifi) 1901! - Added WifiPhyRxTraceHelper for Wi-Fi Phy tracing + +### Bugs fixed + +- (bindings) - Preventing module namespace collision by checking if namespace exists before injecting it. +- (bindings, core) #1059 - Resolved potential initialization issues in TimerImpl and ensured compatibility with Cppyy3. +- (bindings, core) - Introduced a helper class to manage static initialization of Time as a workaround for Cppyy3 static initialization problems. +- (bindings, lte, wifi) - Relocated statically initialized variables from header files to source files for Cppyy3 compatibility. +- (build) #1048 - Resolved an issue with static and monolithic builds incorrectly linking to non-ns-3 libraries. +- (build) #1058 - Corrected the behavior of the ./ns3 clean command in symlinked directories. +- (build) #1065 - Rolled back the -Os optimization setting as the default on MacOS to address lld compatibility issues. +- (core) #1060 - Addressed a stack overflow problem in MakeEvent. +- (tests) - Enhanced error handling in test.py to avoid attempts to open non-existent XML files following early test termination by sanitizers. +- (tcp) #735 - BBR fails to discard invalid samples +- (tcp) #966 - Tcp Cubic (and LinuxReno) cwnd should not grow during application-limited phase +- (tcp) #1085 - Do not reset Cubic W_max upon timeout +- (wifi) #1072 - Support configuration of custom EDCA parameters via Txop attributes before device installation +- (wifi) - Fix operation in 6 GHz band (added support for FILS Discovery frames and HE 6GHz Band Capabilities information element, fixed HE Operation information element, fixed NSS selection, fixed HT and VHT not supported on 6GHz links). +- (wifi, spectrum) - Fix negative power when channel is switched during the propagation delay period (after TX started but before the signal reached RX). + Release 3.41 ------------ diff --git a/VERSION b/VERSION index 91bf8e4134..761e16c131 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.41 +3.42 diff --git a/bindings/python/ns__init__.py b/bindings/python/ns__init__.py index fbd8179afa..c886650ab4 100644 --- a/bindings/python/ns__init__.py +++ b/bindings/python/ns__init__.py @@ -82,11 +82,18 @@ def _search_libraries() -> dict: filter(lambda x: x not in SYSTEM_LIBRARY_DIRECTORIES, set(library_search_paths)) ) + # Exclude injected windows paths in case of WSL + # BTW, why Microsoft? Who had this brilliant idea? + library_search_paths = list(filter(lambda x: "/mnt/c/" not in x, library_search_paths)) + # Search for the core library in the search paths libraries = [] for search_path in library_search_paths: if os.path.exists(search_path): - libraries += glob.glob("%s/**/*.%s*" % (search_path, LIBRARY_EXTENSION), recursive=True) + libraries += glob.glob( + "%s/**/*.%s*" % (search_path, LIBRARY_EXTENSION), + recursive=not os.path.exists(os.path.join(search_path, "ns3")), + ) # Search system library directories (too slow for recursive search) for search_path in SYSTEM_LIBRARY_DIRECTORIES: @@ -238,7 +245,12 @@ def find_ns3_from_lock_file(lock_file: str) -> (str, list, str): # Should be the case when running from the source directory exec(open(lock_file).read(), {}, values) suffix = "-" + values["BUILD_PROFILE"] if values["BUILD_PROFILE"] != "release" else "" - modules = [module.replace("ns3-", "") for module in values["NS3_ENABLED_MODULES"]] + modules = list( + map( + lambda x: x.replace("ns3-", ""), + values["NS3_ENABLED_MODULES"] + values["NS3_ENABLED_CONTRIBUTED_MODULES"], + ) + ) prefix = values["out_dir"] libraries = { os.path.splitext(os.path.basename(x))[0]: x for x in os.listdir(os.path.join(prefix, "lib")) @@ -508,11 +520,6 @@ def dependency_order( # We expose cppyy to consumers of this module as ns.cppyy setattr(cppyy.gbl.ns3, "cppyy", cppyy) - # To maintain compatibility with pybindgen scripts, - # we set an attribute per module that just redirects to the upper object - for module in modules: - setattr(cppyy.gbl.ns3, module.replace("-", "_"), cppyy.gbl.ns3) - # Set up a few tricks cppyy.cppdef( """ @@ -558,81 +565,6 @@ def Node_del(self: cppyy.gbl.ns3.Node) -> None: ) setattr(cppyy.gbl.ns3, "LookupByNameFailSafe", cppyy.gbl.LookupByNameFailSafe) - def CreateObject(className): - try: - try: - func = "CreateObject%s" % re.sub("[<|>]", "_", className) - return getattr(cppyy.gbl, func)() - except AttributeError: - pass - try: - func = "Create%s" % re.sub("[<|>]", "_", className) - return getattr(cppyy.gbl, func)() - except AttributeError: - pass - raise AttributeError - except AttributeError: - try: - func = "CreateObject%s" % re.sub("[<|>]", "_", className) - cppyy.cppdef( - """ - using namespace ns3; - Ptr<%s> %s(){ - Ptr<%s> object = CreateObject<%s>(); - return object; - } - """ - % (className, func, className, className) - ) - except Exception as e: - try: - func = "Create%s" % re.sub("[<|>]", "_", className) - cppyy.cppdef( - """ - using namespace ns3; - %s %s(){ - %s object = %s(); - return object; - } - """ - % (className, func, className, className) - ) - except Exception as e: - exit(-1) - return getattr(cppyy.gbl, func)() - - setattr(cppyy.gbl.ns3, "CreateObject", CreateObject) - - def GetObject(parentObject, aggregatedObject): - # Objects have __cpp_name__ attributes, so parentObject - # should not have it while aggregatedObject can - if hasattr(parentObject, "__cpp_name__"): - raise Exception("Class was passed instead of an instance in parentObject") - - aggregatedIsClass = hasattr(aggregatedObject, "__cpp_name__") - aggregatedIsString = type(aggregatedObject) == str - aggregatedIsInstance = not aggregatedIsClass and not aggregatedIsString - - if aggregatedIsClass: - aggregatedType = aggregatedObject.__cpp_name__ - if aggregatedIsInstance: - aggregatedType = aggregatedObject.__class__.__cpp_name__ - if aggregatedIsString: - aggregatedType = aggregatedObject - - cppyy.cppdef( - """using namespace ns3; template <> Ptr<%s> getAggregatedObject<%s>(Ptr parentPtr, %s param) - { - return parentPtr->GetObject<%s>(); - } - """ - % (aggregatedType, aggregatedType, aggregatedType, aggregatedType) - ) - return cppyy.gbl.getAggregatedObject( - parentObject, aggregatedObject if aggregatedIsClass else aggregatedObject.__class__ - ) - - setattr(cppyy.gbl.ns3, "GetObject", GetObject) return cppyy.gbl.ns3 diff --git a/build-support/custom-modules/ns3-compiler-and-linker-support.cmake b/build-support/custom-modules/ns3-compiler-and-linker-support.cmake index 6861371b88..44426b2d31 100644 --- a/build-support/custom-modules/ns3-compiler-and-linker-support.cmake +++ b/build-support/custom-modules/ns3-compiler-and-linker-support.cmake @@ -47,6 +47,7 @@ if(CLANG) endif() set(GCC FALSE) +set(GCC_WORKING_PEDANTIC_SEMICOLON 1) if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${GNU_MinVersion}) message( @@ -54,6 +55,26 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") "GNU ${CMAKE_CXX_COMPILER_VERSION} ${below_minimum_msg} ${GNU_MinVersion}" ) endif() + + # Check if pedantic throws warning in trailing semicolon after {} scope + # (frequently used to make macros look like functions) + unset(GCC_WORKING_PEDANTIC_SEMICOLON) + include(CheckCXXSourceCompiles) + set(CMAKE_REQUIRED_FLAGS "-Wall -Wpedantic -Werror") + check_cxx_source_compiles( + " + int test(){ return 0; }; + int main(){ + return test(); + } + " + GCC_WORKING_PEDANTIC_SEMICOLON + ) + unset(CMAKE_REQUIRED_FLAGS) + if("${GCC_WORKING_PEDANTIC_SEMICOLON}" STREQUAL "") + set(GCC_WORKING_PEDANTIC_SEMICOLON 0) + endif() + if((CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.2.0")) # PCH causes weird errors on certain versions of GCC when C++20 is enabled # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106799 diff --git a/build-support/custom-modules/ns3-compiler-workarounds.cmake b/build-support/custom-modules/ns3-compiler-workarounds.cmake index f544ddff2d..4386dafd52 100644 --- a/build-support/custom-modules/ns3-compiler-workarounds.cmake +++ b/build-support/custom-modules/ns3-compiler-workarounds.cmake @@ -14,31 +14,3 @@ # Place, Suite 330, Boston, MA 02111-1307 USA # # Author: Gabriel Ferreira - -include(CheckCXXSourceCompiles) - -# Some compilers (e.g. GCC < 9.1) do not link -# std::filesystem/std::experimental::filesystem by default. If the sample -# program can be linked, it means it is indeed linked by default. Otherwise, we -# link it manually. https://en.cppreference.com/w/cpp/filesystem -check_cxx_source_compiles( - " - #ifdef __has_include - #if __has_include() - #include - namespace fs = std::filesystem; - #elif __has_include() - #include - namespace fs = std::experimental::filesystem; - #else - #error \"No support for filesystem library\" - #endif - #endif - int main() - { - std::string path = \"/\"; - return !fs::exists(path); - } - " - FILESYSTEM_LIBRARY_IS_LINKED -) diff --git a/build-support/custom-modules/ns3-executables.cmake b/build-support/custom-modules/ns3-executables.cmake index 92ccea1a84..ab4f3ac0e0 100644 --- a/build-support/custom-modules/ns3-executables.cmake +++ b/build-support/custom-modules/ns3-executables.cmake @@ -102,15 +102,33 @@ function(build_exec) ) endif() + # Check if library is not a ns-3 module library, and if it is, link when + # building static or monolib builds + set(libraries_to_always_link) + set(modules "${libs_to_build};${contrib_libs_to_build}") + foreach(lib ${BEXEC_LIBRARIES_TO_LINK}) + # Remove the lib prefix if one exists + set(libless ${lib}) + string(SUBSTRING "${libless}" 0 3 prefix) + if(prefix STREQUAL "lib") + string(SUBSTRING "${libless}" 3 -1 libless) + endif() + # Check if the library is not a ns-3 module + if(libless IN_LIST modules) + continue() + endif() + list(APPEND libraries_to_always_link ${lib}) + endforeach() + if(${NS3_STATIC} AND (NOT BEXEC_STANDALONE)) target_link_libraries( - ${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} ${LIB_AS_NEEDED_PRE_STATIC} - ${lib-ns3-static} + ${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} ${libraries_to_always_link} + ${LIB_AS_NEEDED_PRE_STATIC} ${lib-ns3-static} ) elseif(${NS3_MONOLIB} AND (NOT BEXEC_STANDALONE)) target_link_libraries( - ${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} ${LIB_AS_NEEDED_PRE} - ${lib-ns3-monolib} ${LIB_AS_NEEDED_POST} + ${BEXEC_EXECNAME_PREFIX}${BEXEC_EXECNAME} ${libraries_to_always_link} + ${LIB_AS_NEEDED_PRE} ${lib-ns3-monolib} ${LIB_AS_NEEDED_POST} ) else() target_link_libraries( diff --git a/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake b/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake index 6f5702cfc6..5834309951 100644 --- a/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake +++ b/build-support/custom-modules/ns3-fetch-optional-modules-dependencies.cmake @@ -3,7 +3,7 @@ include(ExternalProject) ExternalProject_Add( brite_dep GIT_REPOSITORY https://gitlab.com/nsnam/BRITE.git - GIT_TAG 29c301e828d2a4f303b3d0c69360c987b02d0745 + GIT_TAG 2a665ae11740a11afec1b068c2a45f21d901cf55 PREFIX brite_dep BUILD_IN_SOURCE TRUE CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_OUTPUT_DIRECTORY} diff --git a/build-support/custom-modules/ns3-module-macros.cmake b/build-support/custom-modules/ns3-module-macros.cmake index e0b3e41e59..a64790840b 100644 --- a/build-support/custom-modules/ns3-module-macros.cmake +++ b/build-support/custom-modules/ns3-module-macros.cmake @@ -179,10 +179,6 @@ function(build_lib) ) endif() - if(NOT FILESYSTEM_LIBRARY_IS_LINKED) - list(APPEND BLIB_LIBRARIES_TO_LINK -lstdc++fs) - endif() - # Enable examples as tests suites if(${ENABLE_EXAMPLES} AND ${ENABLE_TESTS}) if(NOT ${XCODE}) diff --git a/build-support/macros-and-definitions.cmake b/build-support/macros-and-definitions.cmake index 0147392e43..3808c799cf 100644 --- a/build-support/macros-and-definitions.cmake +++ b/build-support/macros-and-definitions.cmake @@ -159,6 +159,21 @@ macro(process_options) STREQUAL "default" ) set(cmakeBuildType relwithdebinfo) + # Do not use optimized for size builds on MacOS See issue #1065: + # https://gitlab.com/nsnam/ns-3-dev/-/issues/1065 + if(NOT (DEFINED APPLE)) + string(REPLACE "-O2" "-Os" CMAKE_CXX_FLAGS_RELWITHDEBINFO + "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" + ) + endif() + # Do not use -Os for gcc 9 default builds due to a bug in gcc that can + # result in extreme memory usage. See MR !1955 + # https://gitlab.com/nsnam/ns-3-dev/-/merge_requests/1955 + if(GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "10.0.0") + string(REPLACE "-Os" "-O2" CMAKE_CXX_FLAGS_RELWITHDEBINFO + "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}" + ) + endif() set(CMAKE_CXX_FLAGS_DEFAULT ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}) add_definitions(-DNS3_BUILD_PROFILE_DEBUG) elseif(${cmakeBuildType} STREQUAL "release") @@ -214,6 +229,9 @@ macro(process_options) endif() else() add_compile_options(-Wall) # -Wextra + if(${GCC_WORKING_PEDANTIC_SEMICOLON}) + add_compile_options(-Wpedantic) + endif() if(${NS3_WARNINGS_AS_ERRORS}) add_compile_options(-Werror -Wno-error=deprecated-declarations) endif() @@ -371,7 +389,9 @@ macro(process_options) endif() if(${NS3_SANITIZE}) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address,leak,undefined") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fsanitize=address,leak,undefined -fno-sanitize-recover=all" + ) endif() if(${NS3_SANITIZE_MEMORY}) @@ -572,6 +592,7 @@ macro(process_options) endif() endif() + set(LIBXML2_FOUND FALSE) if(${NS3_STATIC}) # Warn users that they may be using shared libraries, which won't produce a # standalone static library @@ -971,7 +992,7 @@ macro(process_options) # return variable check_deps( sphinx_docs_missing_deps CMAKE_PACKAGES Sphinx - EXECUTABLES epstopdf pdflatex latexmk convert dvipng + EXECUTABLES epstopdf pdflatex latexmk convert dvipng dia ) if(sphinx_docs_missing_deps) message( @@ -1256,19 +1277,26 @@ macro(process_options) + + + + + + + ) add_library( @@ -1279,7 +1307,11 @@ macro(process_options) stdlib_pch${build_profile_suffix} PUBLIC "${precompiled_header_libraries}" ) - add_library(stdlib_pch ALIAS stdlib_pch${build_profile_suffix}) + + # Alias may collide with actual pch in builds without suffix (e.g. release) + if(NOT TARGET stdlib_pch) + add_library(stdlib_pch ALIAS stdlib_pch${build_profile_suffix}) + endif() add_executable( stdlib_pch_exec ${PROJECT_SOURCE_DIR}/build-support/empty-main.cc diff --git a/doc/contributing/Makefile b/doc/contributing/Makefile index 811ccb57d5..7c010f98a5 100644 --- a/doc/contributing/Makefile +++ b/doc/contributing/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build diff --git a/doc/contributing/source/coding-style.rst b/doc/contributing/source/coding-style.rst index c9e01d3ad1..6bed1d3d4d 100644 --- a/doc/contributing/source/coding-style.rst +++ b/doc/contributing/source/coding-style.rst @@ -1550,6 +1550,68 @@ explained here. // Avoid repeating the type name "MyClass" in std::less<> std::map> myMap; +- In conditional control blocks (i.e., if-else and switch-case), avoid declaring multiple + branch conditions with the same content to avoid duplicating code. + + In if-else blocks, prefer grouping the identical bodies in a single if condition with a + disjunction of the multiple conditions. + + .. sourcecode:: cpp + + if (condition1) + { + Foo(); + } + else if (condition2) + { + // Same body as condition 1 + Foo(); + } + else + { + Bar(); + } + + // Prefer grouping the two conditions + if (condition1 || condition2) + { + Foo(); + } + else + { + Bar(); + } + + In switch-case blocks, prefer grouping identical ``case`` labels by removing the duplicate + bodies of the former ``case`` labels. + + .. sourcecode:: cpp + + switch (condition) + { + case 1: + Foo(); + break; + case 2: // case 2 has the same body as case 1 + Foo(); + break; + case 3: + Bar(); + break; + } + + switch (condition) + { + // Group identical cases by removing the content of case 1 and letting it fallthrough to case 2 + case 1: + case 2: + Foo(); + break; + case 3: + Bar(); + break; + } + CMake file formatting ********************* diff --git a/doc/contributing/source/conf.py b/doc/contributing/source/conf.py index 133a29fba9..aa5090d31f 100644 --- a/doc/contributing/source/conf.py +++ b/doc/contributing/source/conf.py @@ -49,9 +49,9 @@ # built documents. # # The short X.Y version. -version = "ns-3.41" +version = "ns-3.42" # The full version, including alpha/beta/rc tags. -release = "ns-3.41" +release = "ns-3.42" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/doxygen.conf b/doc/doxygen.conf index 9306cf4aaf..4d604f4e9c 100644 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -461,7 +461,7 @@ TYPEDEF_HIDES_STRUCT = YES # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. -LOOKUP_CACHE_SIZE = 2 +LOOKUP_CACHE_SIZE = 4 # The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use # during processing. When set to 0 doxygen will based this on the number of @@ -1086,7 +1086,7 @@ INLINE_SOURCES = NO # Fortran comments will always remain visible. # The default value is: YES. -STRIP_CODE_COMMENTS = YES +STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # entity all documented functions referencing it will be listed. @@ -2232,7 +2232,7 @@ SEARCH_INCLUDES = YES ## Allow doxygen to find generated include files, such as ns3/core-config.h -INCLUDE_PATH = build +INCLUDE_PATH = build/include # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -2297,7 +2297,11 @@ EXPAND_AS_DEFINED = ATTRIBUTE_ACCESSOR_DEFINE \ ATTRIBUTE_VALUE_DEFINE_WITH_NAME \ ATTRIBUTE_VALUE_IMPLEMENT \ ATTRIBUTE_VALUE_IMPLEMENT_WITH_NAME \ - NS_UNUSED_GLOBAL + NS_UNUSED_GLOBAL \ + NS_DEPRECATED \ + NS_DEPRECATED_3_42 \ + NS_DEPRECATED_3_41 \ + NS_DEPRECATED_3_40 # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have @@ -2571,7 +2575,7 @@ DIR_GRAPH_MAX_DEPTH = 1 # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_IMAGE_FORMAT = png +DOT_IMAGE_FORMAT = SVG # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. @@ -2583,7 +2587,7 @@ DOT_IMAGE_FORMAT = png # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. -INTERACTIVE_SVG = NO +INTERACTIVE_SVG = YES # The DOT_PATH tag can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. @@ -2694,4 +2698,3 @@ DOT_CLEANUP = YES # Disable dark mode in the generated HTML in Doxygen 1.9.6 or greater. # HTML_COLORSTYLE = LIGHT - diff --git a/doc/doxygen.warnings.report.sh b/doc/doxygen.warnings.report.sh index b64a3f3b2e..c24b837be0 100755 --- a/doc/doxygen.warnings.report.sh +++ b/doc/doxygen.warnings.report.sh @@ -248,10 +248,10 @@ REappend filter_blacklistRE "cairo-wideint" # Functions with varying numbers of arguments # Explicit template instantiation declaration -REappend filter_blacklistRE "MakeCallback< ObjectBase \\* >(ObjectBase \\*" +# REappend filter_blacklistRE "MakeCallback< ObjectBase \\* >(ObjectBase \\*" # ATTRIBUTE_HELPER_CPP( and _HEADER( -REappend filter_blacklistRE "ATTRIBUTE_HELPER_\\(CPP\\|HEADER\\)" +# REappend filter_blacklistRE "ATTRIBUTE_HELPER_\\(CPP\\|HEADER\\)" # Filter out regular expression for black list, -e, -t and -F filter_outRE="" diff --git a/doc/installation/Makefile b/doc/installation/Makefile index ea2ecc46f5..fb92c7e7c6 100644 --- a/doc/installation/Makefile +++ b/doc/installation/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build diff --git a/doc/installation/source/conf.py b/doc/installation/source/conf.py index 9ea2578354..57986336aa 100644 --- a/doc/installation/source/conf.py +++ b/doc/installation/source/conf.py @@ -49,9 +49,9 @@ # built documents. # # The short X.Y version. -version = "ns-3.41" +version = "ns-3.42" # The full version, including alpha/beta/rc tags. -release = "ns-3.41" +release = "ns-3.42" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/installation/source/linux.rst b/doc/installation/source/linux.rst index 663eb66b81..3d728101fd 100644 --- a/doc/installation/source/linux.rst +++ b/doc/installation/source/linux.rst @@ -103,9 +103,14 @@ Please see below subsections for Python-related package requirements. Python bindings =============== -Python requires `Cppyy, ` and specifically, version 2.4.2 is the latest version known to work with ns-3 at this time. +Python requires `Cppyy, ` and specifically, +version 3.1.2 is the latest version known to work with ns-3 at this time. -ns-3.37 and newer:: +ns-3.42 and newer:: + + python3 -m pip install --user cppyy==3.1.2 + +ns-3.37-3.41:: python3 -m pip install --user cppyy==2.4.2 diff --git a/doc/installation/source/macos.rst b/doc/installation/source/macos.rst index 76d5be5289..77732307ec 100644 --- a/doc/installation/source/macos.rst +++ b/doc/installation/source/macos.rst @@ -64,7 +64,7 @@ Recommended +=============================+========================+===================================+ | Compiler cache optimization | ``ccache`` | ``ccache`` | +-----------------------------+------------------------+-----------------------------------+ - | Code linting | ``clang-format llvm`` | clang-format included with | + | Code linting | ``clang-format llvm`` | clang-format included with | | | | ``clang``, need to select | | | | ``clang-XX llvm-XX`` versions | +-----------------------------+------------------------+-----------------------------------+ @@ -123,7 +123,8 @@ For MacPorts packages we show the most recent package version available as of ea | Emulation with virtual | | | | machines | Not available for macOS | Not available for macOS | +-----------------------------+----------------------------------+--------------------------+ - | Support for openflow | ``boost`` | ``boost`` | + | Support for openflow, | ``boost`` | ``boost`` | + | CircularApertureAntennaModel| | | +-----------------------------+----------------------------------+--------------------------+ Caveats and troubleshooting diff --git a/doc/installation/source/quick-start.rst b/doc/installation/source/quick-start.rst index bb0b604542..9445b752f2 100644 --- a/doc/installation/source/quick-start.rst +++ b/doc/installation/source/quick-start.rst @@ -80,13 +80,13 @@ Download There are two main options: -1. Download a release tarball. This will unpack to a directory such as ``ns-allinone-3.41`` +1. Download a release tarball. This will unpack to a directory such as ``ns-allinone-3.42`` containing |ns3| and some other programs. Below is a command-line download using ``wget``, but a browser download will also work:: - $ wget https://www.nsnam.org/releases/ns-allinone-3.41.tar.bz2 - $ tar xfj ns-allinone-3.41.tar.bz2 - $ cd ns-allinone-3.41/ns-3.41 + $ wget https://www.nsnam.org/releases/ns-allinone-3.42.tar.bz2 + $ tar xfj ns-allinone-3.42.tar.bz2 + $ cd ns-allinone-3.42/ns-3.42 2. Clone |ns3| from the Git repository. The ``ns-3-allinone`` can be cloned, as well as ``ns-3-dev`` by itself. Below, we illustrate the latter:: @@ -99,7 +99,7 @@ you clone |ns3|, your directory will be named ``ns-3-dev``. By default, Git wil the |ns3| ``master`` branch, which is a development branch. All |ns3| releases are tagged in Git, so if you would then like to check out a past release, you can do so as follows:: - $ git checkout -b ns-3.41-release ns-3.41 + $ git checkout -b ns-3.42-release ns-3.42 In this quick-start, we are omitting download and build instructions for optional |ns3| modules, the ``NetAnim`` animator, Python bindings, and ``NetSimulyzer``. The diff --git a/doc/installation/source/system.rst b/doc/installation/source/system.rst index 1641022ac6..eac22f7788 100644 --- a/doc/installation/source/system.rst +++ b/doc/installation/source/system.rst @@ -140,8 +140,10 @@ if you are running LTE or NR simulations (which make use of SQLite databases): Python bindings (ns-3.37 and newer) =================================== -|ns3| Python support now uses `cppyy `_. Version 2.4.2 -is the most recent supported cppyy release; version 3.0.0 is not currently supported. +|ns3| Python support now uses `cppyy `_. Version 3.1.2 +is the most recent supported cppyy release since ns-3.42. + +Cppyy version 2.4.2 should be used from ns-3.37 up to 3.41. Due to an `upstream limitation with cppyy `_, Python bindings do not work on macOS machines with Apple silicon (M1 and M2 processors). diff --git a/doc/installation/source/windows.rst b/doc/installation/source/windows.rst index 7badcb82a0..03500f1590 100644 --- a/doc/installation/source/windows.rst +++ b/doc/installation/source/windows.rst @@ -175,7 +175,7 @@ To install it with the network installer, start by creating a texlive folder and texlive configuration profile below. You can change the installation directory (starting with ``C:/texlive/2022``). -.. sourcecode:: raw +.. sourcecode:: text selected_scheme scheme-custom TEXDIR C:/texlive/2022 diff --git a/doc/manual/Makefile b/doc/manual/Makefile index a14737fca4..b0a413e618 100644 --- a/doc/manual/Makefile +++ b/doc/manual/Makefile @@ -46,6 +46,7 @@ SOURCES = \ source/troubleshoot.rst \ source/utilities.rst \ source/working-with-cmake.rst \ + source/working-with-docker.rst \ source/working-with-git.rst \ source/working-with-gitlab-ci-local.rst \ ${SRC}/stats/doc/data-collection.rst \ @@ -135,7 +136,7 @@ RESCALE = ../../utils/rescale-pdf.sh @if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build diff --git a/doc/manual/source/conf.py b/doc/manual/source/conf.py index 6396e19408..6249c0dcd9 100644 --- a/doc/manual/source/conf.py +++ b/doc/manual/source/conf.py @@ -74,16 +74,16 @@ # built documents. # # The short X.Y version. -version = "ns-3.41" +version = "ns-3.42" # The full version, including alpha/beta/rc tags. -release = "ns-3.41" +release = "ns-3.42" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff --git a/doc/manual/source/develop.rst b/doc/manual/source/develop.rst index b5ead5678b..cc4e815c40 100644 --- a/doc/manual/source/develop.rst +++ b/doc/manual/source/develop.rst @@ -17,3 +17,4 @@ This chapter describes the development ecosystem generally used to create new mo documentation profiling working-with-gitlab-ci-local + working-with-docker diff --git a/doc/manual/source/enable-tests.rst b/doc/manual/source/enable-tests.rst index 829a17756d..5dbb4a0631 100644 --- a/doc/manual/source/enable-tests.rst +++ b/doc/manual/source/enable-tests.rst @@ -181,14 +181,14 @@ Enable examples and tests that depend on a set of modules using |ns3| As seen above, the following command only builds the requested modules (core and wifi), plus any modules that are implicitly needed (e.g., network), and the resulting compatible examples and tests: -.. sourcecode:: terminal +.. sourcecode:: console ./ns3 configure --enable-modules="wifi;core" --enable-examples --enable-tests However, when developing a new module, you may prefer to use the following alternative, which builds all module libraries, but will filter out any examples and tests from modules that are not explicitly listed. -.. sourcecode:: terminal +.. sourcecode:: console ./ns3 configure --filter-module-examples-and-tests="wifi;core" --enable-examples --enable-tests diff --git a/doc/manual/source/events.rst b/doc/manual/source/events.rst index 9d14da6772..04951fedc2 100644 --- a/doc/manual/source/events.rst +++ b/doc/manual/source/events.rst @@ -81,7 +81,7 @@ monotonically increasing counter) will be handled first. In other words tied events are handled in FIFO order. Note that concurrent events (events that happen at the very same time) -are unlikely in a real system - not to say impossible. In |ns-3| +are unlikely in a real system - not to say impossible. In |ns3| concurrent events are common for a number of reasons, one of them being the time representation. While developing a model this must be carefully taken into account. @@ -289,14 +289,14 @@ for example:: or by using a command line argument -.. sourcecode:: terminal +.. sourcecode:: console $ ./ns3 run "... --SimulatorImplementationType=ns3::DistributedSimulatorImpl" In addition to the basic simulator engines there is a general facility used to build "adapters" which provide small behavior modifications to one of the core `SimulatorImpl` engines. The adapter base class is -`SimulatorAdapter`, itself derived from `SimulatorImpl`. `SimluatorAdapter` +`SimulatorAdapter`, itself derived from `SimulatorImpl`. `SimulatorAdapter` uses the `PIMPL (pointer to implementation) `_ idiom to forward all calls to the configured base simulator engine. This makes it easy to provide small customizations @@ -305,7 +305,7 @@ just by overriding the specific Simulator calls needed, and allowing There are few places where adapters are used currently: -* `ReadltimeSimulatorImpl` This adapter attempts to execute in real time +* `RealtimeSimulatorImpl` This adapter attempts to execute in real time by pacing the wall clock evolution. This pacing is "best effort", meaning actual event execution may not occur exactly in sync, but close to it. This engine is normally only used with the @@ -413,5 +413,5 @@ complexity of the other API calls. +------------------------+-------------------------------------+-------------+--------------+----------+--------------+ | MapScheduler | `st::map` | Logarithmic | Constant | 40 bytes | 32 bytes | +------------------------+-------------------------------------+-------------+--------------+----------+--------------+ -| PriorityQueueScheduler | `std::priority_queue<,std::vector>` | Logarithimc | Logarithims | 24 bytes | 0 | +| PriorityQueueScheduler | `std::priority_queue<,std::vector>` | Logarithmic | Logarithms | 24 bytes | 0 | +------------------------+-------------------------------------+-------------+--------------+----------+--------------+ diff --git a/doc/manual/source/how-to-write-tests.rst b/doc/manual/source/how-to-write-tests.rst index 5a560cedfa..848e7894ce 100644 --- a/doc/manual/source/how-to-write-tests.rst +++ b/doc/manual/source/how-to-write-tests.rst @@ -30,7 +30,7 @@ TestSuite), these things need to be decided up front: * What type of test it will be (Build Verification Test, Unit Test, System Test, or Performance Test) * Where the test code will live (either in an existing ns-3 module or - separately in src/test/ directory). You will have to edit the wscript + separately in src/test/ directory). You will have to edit the CMakeLists.txt file in that directory to compile your new code, if it is a new file. A program called ``utils/create-module.py`` is a good starting point. @@ -44,14 +44,14 @@ substitution of "Router" in that file for something pertaining to the model that you want to test. You can also edit things such as a more descriptive test case name. -You also need to add a block into your wscript to get this test to +You also need to add a block into your CMakeLists.txt to get this test to compile: -.. sourcecode:: python +.. sourcecode:: cmake - module_test.source = [ - 'test/router-test-suite.cc', - ] + set(test_sources + test/router-test-suite.cc + ) Before you actually start making this do useful things, it may help to try to run the skeleton. Make sure that ns-3 has been configured with @@ -61,7 +61,7 @@ is called "router" such as here: :: RouterTestSuite::RouterTestSuite() - : TestSuite("router", UNIT) + : TestSuite("router", Type::UNIT) Try this command: @@ -137,7 +137,7 @@ framework with a specialized ``TestSuite`` or ``TestCase`` class designed to run an example and compare the output with a specified known "good" reference file. To use an example program as a test you need to create a test suite file and add it to the appropriate list in -your module wscript file. The "good" output reference file needs to be +your module CMakeLists.txt file. The "good" output reference file needs to be generated for detecting regressions. If you are thinking about using this class, strongly consider using a @@ -164,16 +164,25 @@ and command line arguments for the example. In the preceding code the same example is run twice with different arguments. You then need to add that newly created test suite file to the list of -test sources in ``mymodule/wscript``. Building of examples +test sources in ``mymodule/CMakeLists.txt``. Building of examples is an option so you need to guard the inclusion of the test suite: -.. sourcecode:: python +.. sourcecode:: cmake - if (bld.env['ENABLE_EXAMPLES']): - module.source.append('model/mymodule-examples-test-suite.cc') + set(example_as_test_suite) + if(${ENABLE_EXAMPLES}) + set(example_as_test_suite + test/mymodule-examples-test-suite.cc + ) + endif() + +and then later + +.. sourcecode:: cmake + + set(test_sources + ${example_as_test_suite} -Since you modified a wscript file you need to reconfigure and rebuild -everything. You just added new tests so you will need to generate the "good" output reference files that will be used to verify the example: diff --git a/doc/manual/source/new-modules.rst b/doc/manual/source/new-modules.rst index a700bc7c95..b3f3fd9518 100644 --- a/doc/manual/source/new-modules.rst +++ b/doc/manual/source/new-modules.rst @@ -162,7 +162,7 @@ which declares a new unit test named ``new-module``, with a single test case consisting of the class ``NewModuleTestCase1``:: NewModuleTestSuite::NewModuleTestSuite() - : TestSuite("new-module", UNIT) + : TestSuite("new-module", Type::UNIT) { AddTestCase(new NewModuleTestCase1); } @@ -372,33 +372,38 @@ two lists of C++ and Python examples: # A list of C++ examples to run in order to ensure that they remain # buildable and runnable over time. Each tuple in the list contains # - # (example_name, do_run, do_valgrind_run). + # (example_name, do_run, do_valgrind_run, fullness). # # See test.py for more information. cpp_examples = [ - ("adhoc-aloha-ideal-phy", "True", "True"), - ("adhoc-aloha-ideal-phy-with-microwave-oven", "True", "True"), - ("adhoc-aloha-ideal-phy-matrix-propagation-loss-model", "True", "True"), + ("adhoc-aloha-ideal-phy", "True", "True", "QUICK"), + ("adhoc-aloha-ideal-phy-with-microwave-oven", "True", "True", "QUICK"), + ("adhoc-aloha-ideal-phy-matrix-propagation-loss-model", "True", "True", "QUICK"), ] # A list of Python examples to run in order to ensure that they remain # runnable over time. Each tuple in the list contains # - # (example_name, do_run). + # (example_name, do_run, fullness). # # See test.py for more information. python_examples = [ - ("sample-simulator.py", "True"), + ("sample-simulator.py", "True", "QUICK"), ] As indicated in the comment, each entry in the C++ list of examples to run -contains the tuple ``(example_name, do_run, do_valgrind_run)``, where +contains the tuple ``(example_name, do_run, do_valgrind_run, fullness)``, where * ``example_name`` is the executable to be run, * ``do_run`` is a condition under which to run the example, and * ``do_valgrind_run`` is a condition under which to run the example under valgrind. (This is needed because NSC causes illegal instruction crashes with some tests when they are run under valgrind.) +* ``fullness`` is the optional classification of how long the example takes to + run, like the :doc:`Tests ` fullness specifier. from + fastest to slowest the possible options are: ``"QUICK"``, + ``"EXTENSIVE"``, and ``"TAKES_FOREVER"``. If no value is + provided, ``"QUICK"`` is used. Note that the two conditions are Python statements that can depend on ``ns3`` configuration variables. For example, using the @@ -406,20 +411,22 @@ NSC_ENABLED variable that was defined up until ns-3.35: .. sourcecode:: python - ("tcp-nsc-lfn", "NSC_ENABLED == True", "NSC_ENABLED == False"), + ("tcp-nsc-lfn", "NSC_ENABLED == True", "NSC_ENABLED == False", "QUICK"), Each entry in the Python list of examples to run contains the tuple -``(example_name, do_run)``, where, as for the C++ examples, +``(example_name, do_run, fullness)``, where, as for the C++ examples, * ``example_name`` is the Python script to be run, and * ``do_run`` is a condition under which to run the example. +* ``fullness`` is the same as ``fullness`` for C++ examples. + If no value is provided, ``"QUICK"`` is used Again, the condition is a Python statement that can depend on ``ns3`` configuration variables. For example, .. sourcecode:: python - ("brite-generic-example", "ENABLE_BRITE == True", "False"), + ("brite-generic-example.py", "ENABLE_BRITE == True", "QUICK"), Step 8 - Configure and Build diff --git a/doc/manual/source/profiling.rst b/doc/manual/source/profiling.rst index e338cb53c2..de7142eb22 100644 --- a/doc/manual/source/profiling.rst +++ b/doc/manual/source/profiling.rst @@ -636,6 +636,24 @@ Hotspot was used to identify performance bottlenecks in multiple occasions: and inlining TtlExceeded. This resulted in a ~1.02x speedup with the test suite (``./test.py -d``). More details on: merge requests `MR681`_ and `MR685`_. +Perf on WSL +~~~~~~~~~~~ + +WSLv1 cannot use perf due to the lack of the linux kernel and its performance counters. + +WSLv2 users need to manually build perf to profile their programs, +which can be accomplished with the following commands: + +.. sourcecode:: console + + apt install flex bison + git clone https://github.com/microsoft/WSL2-Linux-Kernel --depth 1 + cd WSL2-Linux-Kernel/tools/perf + make -j8 + sudo cp perf /usr/local/bin + +Note that hardware `performance counters `_ +are only available in Windows 11. AMD uProf +++++++++ diff --git a/doc/manual/source/python.rst b/doc/manual/source/python.rst index 5b1a13173a..158005dfaf 100644 --- a/doc/manual/source/python.rst +++ b/doc/manual/source/python.rst @@ -52,45 +52,45 @@ Here is some example code that is written in Python and that runs |ns3|, which i from ns import ns - ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO) - ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO) + ns.LogComponentEnable("UdpEchoClientApplication", ns.LOG_LEVEL_INFO) + ns.LogComponentEnable("UdpEchoServerApplication", ns.LOG_LEVEL_INFO) - nodes = ns.network.NodeContainer() + nodes = ns.NodeContainer() nodes.Create(2) - pointToPoint = ns.point_to_point.PointToPointHelper() - pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps")) - pointToPoint.SetChannelAttribute("Delay", ns.core.StringValue("2ms")) + pointToPoint = ns.PointToPointHelper() + pointToPoint.SetDeviceAttribute("DataRate", ns.StringValue("5Mbps")) + pointToPoint.SetChannelAttribute("Delay", ns.StringValue("2ms")) devices = pointToPoint.Install(nodes) - stack = ns.internet.InternetStackHelper() + stack = ns.InternetStackHelper() stack.Install(nodes) - address = ns.internet.Ipv4AddressHelper() - address.SetBase(ns.network.Ipv4Address("10.1.1.0"), - ns.network.Ipv4Mask("255.255.255.0")) + address = ns.Ipv4AddressHelper() + address.SetBase(ns.Ipv4Address("10.1.1.0"), + ns.Ipv4Mask("255.255.255.0")) interfaces = address.Assign(devices) - echoServer = ns.applications.UdpEchoServerHelper(9) + echoServer = ns.UdpEchoServerHelper(9) serverApps = echoServer.Install(nodes.Get(1)) - serverApps.Start(ns.core.Seconds(1.0)) - serverApps.Stop(ns.core.Seconds(10.0)) + serverApps.Start(ns.Seconds(1.0)) + serverApps.Stop(ns.Seconds(10.0)) address = interfaces.GetAddress(1).ConvertTo() - echoClient = ns.applications.UdpEchoClientHelper(address, 9) - echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(1)) - echoClient.SetAttribute("Interval", ns.core.TimeValue(ns.core.Seconds(1.0))) - echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(1024)) + echoClient = ns.UdpEchoClientHelper(address, 9) + echoClient.SetAttribute("MaxPackets", ns.UintegerValue(1)) + echoClient.SetAttribute("Interval", ns.TimeValue(ns.Seconds(1.0))) + echoClient.SetAttribute("PacketSize", ns.UintegerValue(1024)) clientApps = echoClient.Install(nodes.Get(0)) - clientApps.Start(ns.core.Seconds(2.0)) - clientApps.Stop(ns.core.Seconds(10.0)) + clientApps.Start(ns.Seconds(2.0)) + clientApps.Stop(ns.Seconds(10.0)) - ns.core.Simulator.Run() - ns.core.Simulator.Destroy() + ns.Simulator.Run() + ns.Simulator.Destroy() @@ -111,11 +111,11 @@ simple modules in python, jump to the `Using the pip wheel`_ section. Using the bindings from the ns-3 source ======================================= -The main prerequisite is to install `cppyy`, with version no later than 2.4.2. +The main prerequisite is to install `cppyy`, with version 3.1.2. Depending on how you may manage Python extensions, the installation instructions may vary, but you can first check if it installed by seeing if the `cppyy` module can be -successfully imported and the version is no later than 2.4.2: +successfully imported and the version 3.1.2: .. sourcecode:: bash @@ -125,7 +125,7 @@ successfully imported and the version is no later than 2.4.2: Type "help", "copyright", "credits" or "license" for more information. >>> import cppyy >>> print("%s" % cppyy.__version) - 2.4.2 + 3.1.2 >>> If not, you may try to install via `pip` or whatever other manager you are @@ -133,7 +133,7 @@ using; e.g.: .. sourcecode:: bash - $ python3 -m pip install --user cppyy==2.4.2 + $ python3 -m pip install --user cppyy==3.1.2 First, we need to enable the build of Python bindings: @@ -226,71 +226,71 @@ After installing it, you can start using ns-3 right away. For example, using the :: - from ns import ns + from ns import ns - ns.cppyy.cppdef(""" - using namespace ns3; + ns.cppyy.cppdef(""" + using namespace ns3; - Callback,const Address&,const Address&> - make_sinktrace_callback(void(*func)(Ptr,Address,Address)) - { - return MakeCallback(func); - } - """) + Callback,const Address&,const Address&> + make_sinktrace_callback(void(*func)(Ptr, const Address&,const Address&)) + { + return MakeCallback(func); + } + """) - # Define the trace callback - def SinkTracer(packet: ns.Packet, src_address: ns.Address, dst_address: ns.Address) -> None: - print(f"At {ns.Simulator.Now().GetSeconds():.0f}s, '{dst_address}' received packet" - f" with {packet.__deref__().GetSerializedSize()} bytes from '{src_address}'") + # Define the trace callback + def SinkTracer(packet: ns.Packet, src_address: ns.Address, dst_address: ns.Address) -> None: + print(f"At {ns.Simulator.Now().GetSeconds():.0f}s, '{dst_address}' received packet" + f" with {packet.__deref__().GetSerializedSize()} bytes from '{src_address}'") - # Create two nodes - csmaNodes = ns.network.NodeContainer() - csmaNodes.Create(2) + # Create two nodes + csmaNodes = ns.NodeContainer() + csmaNodes.Create(2) - # Connect the two nodes - csma = ns.csma.CsmaHelper() - csma.SetChannelAttribute("DataRate", ns.core.StringValue("100Mbps")) - csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.NanoSeconds(6560))) - csmaDevices = csma.Install(csmaNodes) + # Connect the two nodes + csma = ns.CsmaHelper() + csma.SetChannelAttribute("DataRate", ns.StringValue("100Mbps")) + csma.SetChannelAttribute("Delay", ns.TimeValue(ns.NanoSeconds(6560))) + csmaDevices = csma.Install(csmaNodes) - # Install the internet stack - stack = ns.internet.InternetStackHelper() - stack.Install(csmaNodes) + # Install the internet stack + stack = ns.InternetStackHelper() + stack.Install(csmaNodes) - # Assign Ipv4 addresses - address = ns.internet.Ipv4AddressHelper() - address.SetBase(ns.network.Ipv4Address("10.1.2.0"), ns.network.Ipv4Mask("255.255.255.0")) - csmaInterfaces = address.Assign(csmaDevices) + # Assign Ipv4 addresses + address = ns.Ipv4AddressHelper() + address.SetBase(ns.Ipv4Address("10.1.2.0"), ns.Ipv4Mask("255.255.255.0")) + csmaInterfaces = address.Assign(csmaDevices) - # Setup applications - echoServer = ns.applications.UdpEchoServerHelper(9) + # Setup applications + echoServer = ns.UdpEchoServerHelper(9) - serverApps = echoServer.Install(csmaNodes.Get(0)) - serverApps.Start(ns.core.Seconds(1.0)) - serverApps.Stop(ns.core.Seconds(10.0)) + serverApps = echoServer.Install(csmaNodes.Get(0)) + serverApps.Start(ns.Seconds(1.0)) + serverApps.Stop(ns.Seconds(10.0)) - echoClient = ns.applications.UdpEchoClientHelper(csmaInterfaces.GetAddress(0).ConvertTo(), 9) - echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(10)) - echoClient.SetAttribute("Interval", ns.core.TimeValue(ns.core.Seconds(1.0))) - echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(1024)) + echoClient = ns.UdpEchoClientHelper(csmaInterfaces.GetAddress(0).ConvertTo(), 9) + echoClient.SetAttribute("MaxPackets", ns.UintegerValue(10)) + echoClient.SetAttribute("Interval", ns.TimeValue(ns.Seconds(1.0))) + echoClient.SetAttribute("PacketSize", ns.UintegerValue(1024)) - clientApps = echoClient.Install(csmaNodes.Get(1)) - clientApps.Start(ns.core.Seconds(2.0)) - clientApps.Stop(ns.core.Seconds(10.0)) + clientApps = echoClient.Install(csmaNodes.Get(1)) + clientApps.Start(ns.Seconds(2.0)) + clientApps.Stop(ns.Seconds(10.0)) - # Populate routing tables - ns.internet.Ipv4GlobalRoutingHelper.PopulateRoutingTables() + # Populate routing tables + ns.Ipv4GlobalRoutingHelper.PopulateRoutingTables() - # Setup the trace callback - sinkTraceCallback = ns.cppyy.gbl.make_sinktrace_callback(SinkTracer) - serverApps.Get(0).__deref__().TraceConnectWithoutContext("RxWithAddresses", sinkTraceCallback); + # Setup the trace callback + sinkTraceCallback = ns.cppyy.gbl.make_sinktrace_callback(SinkTracer) + serverApps.Get(0).__deref__().TraceConnectWithoutContext("RxWithAddresses", sinkTraceCallback); - # Set the simulation duration to 11 seconds - ns.Simulator.Stop(ns.Seconds(11)) + # Set the simulation duration to 11 seconds + ns.Simulator.Stop(ns.Seconds(11)) - # Run the simulator - ns.Simulator.Run() - ns.Simulator.Destroy() + # Run the simulator + ns.Simulator.Run() + ns.Simulator.Destroy() Which should print: @@ -326,31 +326,32 @@ For example, when handling command-line arguments, we could set additional param .. sourcecode:: python - # Import the ns-3 C++ modules with Cppyy - from ns import ns - - # To pass the addresses of the Python variables to c++, we need to use ctypes - from ctypes import c_bool, c_int, c_double, c_char_p, create_string_buffer - verbose = c_bool(True) - nCsma = c_int(3) - throughputKbps = c_double(3.1415) - BUFFLEN = 4096 - outputFileBuffer = create_string_buffer(b"default_output_file.xml", BUFFLEN) - outputFile = c_char_p(outputFileBuffer.raw) - - # Cppyy will transform the ctype types into the appropriate reference or raw pointers - cmd = ns.CommandLine(__file__) - cmd.AddValue("verbose", "Tell echo applications to log if true", verbose) - cmd.AddValue("nCsma", "Number of extra CSMA nodes/devices", nCsma) - cmd.AddValue("throughputKbps", "Throughput of nodes", throughputKbps) - cmd.AddValue("outputFile", "Output file name", outputFile, BUFFLEN) - cmd.Parse(sys.argv) - - # Printing values of the different ctypes passed as arguments post parsing - print("Verbose:", verbose.value) - print("nCsma:", nCsma.value) - print("throughputKbps:", throughputKbps.value) - print("outputFile:", outputFile.value) + # Import the ns-3 C++ modules with Cppyy + from ns import ns + import sys + + # To pass the addresses of the Python variables to c++, we need to use ctypes + from ctypes import c_bool, c_int, c_double, c_char_p, create_string_buffer + verbose = c_bool(True) + nCsma = c_int(3) + throughputKbps = c_double(3.1415) + BUFFLEN = 4096 + outputFileBuffer = create_string_buffer(b"default_output_file.xml", BUFFLEN) + outputFile = c_char_p(outputFileBuffer.raw) + + # Cppyy will transform the ctype types into the appropriate reference or raw pointers + cmd = ns.CommandLine(__file__) + cmd.AddValue("verbose", "Tell echo applications to log if true", verbose) + cmd.AddValue("nCsma", "Number of extra CSMA nodes/devices", nCsma) + cmd.AddValue("throughputKbps", "Throughput of nodes", throughputKbps) + cmd.AddValue("outputFile", "Output file name", outputFile, BUFFLEN) + cmd.Parse(sys.argv) + + # Printing values of the different ctypes passed as arguments post parsing + print("Verbose:", verbose.value) + print("nCsma:", nCsma.value) + print("throughputKbps:", throughputKbps.value) + print("outputFile:", outputFile.value) Note that the variables are passed as references or raw pointers. Reassigning them on the Python side (e.g. ``verbose = verbose.value``) can result in the Python garbage collector destroying the object @@ -371,62 +372,63 @@ no bounds checking in CommandLine::AddValue variant for ``char*``. .. sourcecode:: python - from ns import ns - from ctypes import c_char_p, c_char, create_string_buffer, byref, cast - - # The following buffer represent the memory contents - # of a program containing two adjacent C strings - # This could be the result of two subsequent variables - # on the stack or dynamically allocated - memoryContents = create_string_buffer(b"SHORT_STRING_CONTENTS\0"+b"DoNotWriteHere_"*5+b"\0") - lenShortString = len(b"SHORT_STRING_CONTENTS\0") - - # In the next lines, we pick pointers to these two C strings - shortStringBuffer = cast(byref(memoryContents, 0), c_char_p) - victimBuffer = cast(byref(memoryContents, lenShortString), c_char_p) - - cmd = ns.core.CommandLine(__file__) - # in the real implementation, the buffer size of 21+1 bytes containing SHORT_STRING_CONTENTS\0 is passed - cmd.AddValue("shortString", "", shortStringBuffer) - - print("Memory contents before the memory corruption") - print("Full Memory contents", memoryContents.raw) - print("shortStringBuffer contents: ", shortStringBuffer.value) - print("victimBuffer contents: ", victimBuffer.value) - - # The following block should print to the terminal. - # Note that the strings are correctly - # identified due to the null terminator (\x00) - # - # Memory contents before the memory corruption - # Full Memory contents b'SHORT_STRING_CONTENTS\x00DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_\x00\x00' - # shortStringBuffer size=21, contents: b'SHORT_STRING_CONTENTS' - # victimBuffer size=75, contents: b'DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_' - - # Write a very long string to a small buffer of size lenShortString = 22 - cmd.Parse(["python", "--shortString="+("OkToWrite"*lenShortString)[:lenShortString]+"CORRUPTED_"*3]) - - print("\n\nMemory contents after the memory corruption") - print("Full Memory contents", memoryContents.raw) - print("shortStringBuffer contents: ", shortStringBuffer.value) - print("victimBuffer contents: ", victimBuffer.value) - - # The following block should print to the terminal. - # - # Memory contents after the memory corruption - # Full Memory contents b'OkToWriteOkToWriteOkToCORRUPTED_CORRUPTED_CORRUPTED_\x00oNotWriteHere_DoNotWriteHere_DoNotWriteHere_\x00\x00' - # shortStringBuffer size=52, contents: b'OkToWriteOkToWriteOkToCORRUPTED_CORRUPTED_CORRUPTED_' - # victimBuffer size=30, contents: b'CORRUPTED_CORRUPTED_CORRUPTED_' - # - # Note that shortStringBuffer invaded the victimBuffer since the - # string being written was bigger than the shortStringBuffer. - # - # Since no bounds checks were performed, the adjacent memory got - # overwritten and both buffers are now corrupted. - # - # We also have a memory leak of the final block in the memory - # 'oNotWriteHere_DoNotWriteHere_DoNotWriteHere_\x00\x00', caused - # by the null terminator written at the middle of the victimBuffer. + from ns import ns + from ctypes import c_char_p, c_char, create_string_buffer, byref, cast + + # The following buffer represent the memory contents + # of a program containing two adjacent C strings + # This could be the result of two subsequent variables + # on the stack or dynamically allocated + memoryContents = create_string_buffer(b"SHORT_STRING_CONTENTS\0"+b"DoNotWriteHere_"*5+b"\0") + lenShortString = len(b"SHORT_STRING_CONTENTS\0") + + # In the next lines, we pick pointers to these two C strings + shortStringBuffer = cast(byref(memoryContents, 0), c_char_p) + victimBuffer = cast(byref(memoryContents, lenShortString), c_char_p) + + cmd = ns.CommandLine(__file__) + # in the real implementation, the buffer size of 21+1 bytes containing SHORT_STRING_CONTENTS\0 is passed + # we use the entire size of the memory contents for demonstration purposses + cmd.AddValue("shortString", "", shortStringBuffer, 75) + + print("Memory contents before the memory corruption") + print("Full Memory contents", memoryContents.raw) + print("shortStringBuffer contents: ", shortStringBuffer.value) + print("victimBuffer contents: ", victimBuffer.value) + + # The following block should print to the terminal. + # Note that the strings are correctly + # identified due to the null terminator (\x00) + # + # Memory contents before the memory corruption + # Full Memory contents b'SHORT_STRING_CONTENTS\x00DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_\x00\x00' + # shortStringBuffer size=21, contents: b'SHORT_STRING_CONTENTS' + # victimBuffer size=75, contents: b'DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_DoNotWriteHere_' + + # Write a very long string to a small buffer of size lenShortString = 22 + cmd.Parse(["python", "--shortString="+("OkToWrite"*lenShortString)[:lenShortString]+"CORRUPTED_"*3]) + + print("\n\nMemory contents after the memory corruption") + print("Full Memory contents", memoryContents.raw) + print("shortStringBuffer contents: ", shortStringBuffer.value) + print("victimBuffer contents: ", victimBuffer.value) + + # The following block should print to the terminal. + # + # Memory contents after the memory corruption + # Full Memory contents b'OkToWriteOkToWriteOkToCORRUPTED_CORRUPTED_CORRUPTED_\x00oNotWriteHere_DoNotWriteHere_DoNotWriteHere_\x00\x00' + # shortStringBuffer size=52, contents: b'OkToWriteOkToWriteOkToCORRUPTED_CORRUPTED_CORRUPTED_' + # victimBuffer size=30, contents: b'CORRUPTED_CORRUPTED_CORRUPTED_' + # + # Note that shortStringBuffer invaded the victimBuffer since the + # string being written was bigger than the shortStringBuffer. + # + # Since no bounds checks were performed, the adjacent memory got + # overwritten and both buffers are now corrupted. + # + # We also have a memory leak of the final block in the memory + # 'oNotWriteHere_DoNotWriteHere_DoNotWriteHere_\x00\x00', caused + # by the null terminator written at the middle of the victimBuffer. If you find a segmentation violation, be sure to wait for the stacktrace provided by Cppyy and try to find the root cause of the issue. If you have multiple cores, the number of @@ -443,22 +445,22 @@ module (`ns-3-dev/bindings/python/ns__init__.py`). .. sourcecode:: python - # Redefine Time operators - cppyy.cppdef(""" - using namespace ns3; - bool Time_ge(Time& a, Time& b){ return a >= b;} - bool Time_eq(Time& a, Time& b){ return a == b;} - bool Time_ne(Time& a, Time& b){ return a != b;} - bool Time_le(Time& a, Time& b){ return a <= b;} - bool Time_gt(Time& a, Time& b){ return a > b;} - bool Time_lt(Time& a, Time& b){ return a < b;} - """) - cppyy.gbl.ns3.Time.__ge__ = cppyy.gbl.Time_ge - cppyy.gbl.ns3.Time.__eq__ = cppyy.gbl.Time_eq - cppyy.gbl.ns3.Time.__ne__ = cppyy.gbl.Time_ne - cppyy.gbl.ns3.Time.__le__ = cppyy.gbl.Time_le - cppyy.gbl.ns3.Time.__gt__ = cppyy.gbl.Time_gt - cppyy.gbl.ns3.Time.__lt__ = cppyy.gbl.Time_lt + # Redefine Time operators + cppyy.cppdef(""" + using namespace ns3; + bool Time_ge(Time& a, Time& b){ return a >= b;} + bool Time_eq(Time& a, Time& b){ return a == b;} + bool Time_ne(Time& a, Time& b){ return a != b;} + bool Time_le(Time& a, Time& b){ return a <= b;} + bool Time_gt(Time& a, Time& b){ return a > b;} + bool Time_lt(Time& a, Time& b){ return a < b;} + """) + cppyy.gbl.ns3.Time.__ge__ = cppyy.gbl.Time_ge + cppyy.gbl.ns3.Time.__eq__ = cppyy.gbl.Time_eq + cppyy.gbl.ns3.Time.__ne__ = cppyy.gbl.Time_ne + cppyy.gbl.ns3.Time.__le__ = cppyy.gbl.Time_le + cppyy.gbl.ns3.Time.__gt__ = cppyy.gbl.Time_gt + cppyy.gbl.ns3.Time.__lt__ = cppyy.gbl.Time_lt A different operator used by |ns3| is `operator Address()`, used to @@ -467,8 +469,8 @@ This is not supported by Cppyy and requires explicit conversion. .. sourcecode:: python - # Explicitly convert the InetSocketAddress to Address using InetSocketAddress.ConvertTo() - sink.Bind(ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), 80).ConvertTo()) + # Explicitly convert the InetSocketAddress to Address using InetSocketAddress.ConvertTo() + sink.Bind(ns.InetSocketAddress(ns.Ipv4Address.GetAny(), 80).ConvertTo()) Most of the missing APIs can be wrapped, given enough time, patience, and expertise, and will likely be wrapped if bug reports are submitted. However, don't file a bug report saying "bindings are incomplete", because the project does not have maintainers to maintain every API. @@ -487,11 +489,11 @@ In Python, the C++ std::ofstream has been minimally wrapped to allow this. For :: - ascii = ns.ofstream("wifi-ap.tr") # create the file - ns.YansWifiPhyHelper.EnableAsciiAll(ascii) - ns.Simulator.Run() - ns.Simulator.Destroy() - ascii.close() # close the file + ascii = ns.ofstream("wifi-ap.tr") # create the file + ns.YansWifiPhyHelper.EnableAsciiAll(ascii) + ns.Simulator.Run() + ns.Simulator.Destroy() + ascii.close() # close the file There is one caveat: you must not allow the file object to be garbage collected while |ns3| is still using it. That means that the 'ascii' variable above must not be allowed to go out of scope or else the program will crash. @@ -507,14 +509,14 @@ The python bindings are generated into an 'ns' namespace. Examples: :: from ns import ns - n1 = ns.network.Node() + n1 = ns.Node() or :: from ns import* - n1 = ns.network.Node() + n1 = ns.Node() The best way to explore the bindings is to look at the various example programs provided in |ns3|; some C++ examples have a corresponding Python @@ -616,23 +618,23 @@ ns-3 (e.g. libxml2, gsl, sqlite, gtk, etc) and for the bindings and packaging .. sourcecode:: yaml - # Install minimal toolchain - - yum install -y libxml2-devel gsl-devel sqlite-devel gtk3-devel boost-devel - # Create Python venv - - $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 --upgrade - - $PYTHON -m pip install wheel auditwheel cmake-build-extension cppyy + # Install minimal toolchain + - yum install -y libxml2-devel gsl-devel sqlite-devel gtk3-devel boost-devel + # Create Python venv + - $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 --upgrade + - $PYTHON -m pip install wheel auditwheel cmake-build-extension cppyy The project is then configured loading the configuration settings defined in the ``ns-3-dev/setup.py`` file. .. sourcecode:: yaml - # Configure and build wheel - - $PYTHON setup.py bdist_wheel build_ext + # Configure and build wheel + - $PYTHON setup.py bdist_wheel build_ext At this point, we have a wheel that only works in the current system, since external libraries are not shipped. @@ -645,9 +647,9 @@ by the script ``ns-3-dev/build-support/pip-wheel/auditwheel-exclude-list.py``. .. sourcecode:: yaml - - 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 + - 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 At this point, we should have our final wheel ready, but we need to check if it works @@ -657,48 +659,48 @@ We first clean the environment and uninstall the packages previously installed. .. sourcecode:: yaml - # Clean the build directory - - $PYTHON ./ns3 clean - # Clean up the environment - - deactivate - - rm -R ./venv - # Delete toolchain to check if required headers/libraries were really packaged - - yum remove -y libxml2-devel gsl-devel sqlite-devel gtk3-devel boost-devel + # Clean the build directory + - $PYTHON ./ns3 clean + # Clean up the environment + - deactivate + - rm -R ./venv + # Delete toolchain to check if required headers/libraries were really packaged + - yum remove -y libxml2-devel gsl-devel sqlite-devel gtk3-devel boost-devel Then we can install our newly built wheel and test it. .. sourcecode:: yaml - # Install wheel - - $PYTHON -m pip install ./wheelhouse/*whl - - $PYTHON -m pip install matplotlib numpy - # Test the bindings - - $PYTHON ./utils/python-unit-tests.py - - $PYTHON ./examples/realtime/realtime-udp-echo.py - - $PYTHON ./examples/routing/simple-routing-ping6.py - - $PYTHON ./examples/tutorial/first.py - - $PYTHON ./examples/tutorial/second.py - - $PYTHON ./examples/tutorial/third.py - - $PYTHON ./examples/wireless/wifi-ap.py - - $PYTHON ./examples/wireless/mixed-wired-wireless.py - - $PYTHON ./src/bridge/examples/csma-bridge.py - - $PYTHON ./src/brite/examples/brite-generic-example.py - - $PYTHON ./src/core/examples/sample-simulator.py - - $PYTHON ./src/core/examples/sample-rng-plot.py --not-blocking - - $PYTHON ./src/click/examples/nsclick-simple-lan.py - - $PYTHON ./src/flow-monitor/examples/wifi-olsr-flowmon.py - - $PYTHON ./src/flow-monitor/examples/flowmon-parse-results.py output.xml - - $PYTHON ./src/openflow/examples/openflow-switch.py + # Install wheel + - $PYTHON -m pip install ./wheelhouse/*whl + - $PYTHON -m pip install matplotlib numpy + # Test the bindings + - $PYTHON ./utils/python-unit-tests.py + - $PYTHON ./examples/realtime/realtime-udp-echo.py + - $PYTHON ./examples/routing/simple-routing-ping6.py + - $PYTHON ./examples/tutorial/first.py + - $PYTHON ./examples/tutorial/second.py + - $PYTHON ./examples/tutorial/third.py + - $PYTHON ./examples/wireless/wifi-ap.py + - $PYTHON ./examples/wireless/mixed-wired-wireless.py + - $PYTHON ./src/bridge/examples/csma-bridge.py + - $PYTHON ./src/brite/examples/brite-generic-example.py + - $PYTHON ./src/core/examples/sample-simulator.py + - $PYTHON ./src/core/examples/sample-rng-plot.py --not-blocking + - $PYTHON ./src/click/examples/nsclick-simple-lan.py + - $PYTHON ./src/flow-monitor/examples/wifi-olsr-flowmon.py + - $PYTHON ./src/flow-monitor/examples/flowmon-parse-results.py output.xml + - $PYTHON ./src/openflow/examples/openflow-switch.py If all programs finish normally, the bindings are working as expected, and will be saved as an artifact. .. sourcecode:: yaml - artifacts: - paths: - - wheelhouse/*.whl + artifacts: + paths: + - wheelhouse/*.whl One can use ``gitlab-ci-local`` to build the pip wheels locally. After that, the wheels will be stored in ``.gitlab-ci-local/artifacts/manylinux-pip-wheel-py3Lg10/wheelhouse`` @@ -730,7 +732,7 @@ Then install the wheel and its dependencies running the following command: .. sourcecode:: bash - $ pip install *.whl + $ pip install *.whl Publishing the pip wheel via Pypi ********************************* diff --git a/doc/manual/source/test-framework.rst b/doc/manual/source/test-framework.rst index 79bac86c57..5d435bda35 100644 --- a/doc/manual/source/test-framework.rst +++ b/doc/manual/source/test-framework.rst @@ -761,9 +761,9 @@ as a ''unit'' test with the display name, ``my-test-suite-name``. }; MyTestSuite::MyTestSuite() - : TestSuite("my-test-suite-name", UNIT) + : TestSuite("my-test-suite-name", Type::UNIT) { - AddTestCase(new MyTestCase, TestCase::QUICK); + AddTestCase(new MyTestCase, TestCase::Duration::QUICK); } static MyTestSuite myTestSuite; diff --git a/doc/manual/source/working-with-cmake.rst b/doc/manual/source/working-with-cmake.rst index 9527c0ca4c..2d7dc31728 100644 --- a/doc/manual/source/working-with-cmake.rst +++ b/doc/manual/source/working-with-cmake.rst @@ -173,7 +173,7 @@ The mapping of the ``ns3`` build profiles into the CMake build types is the foll +=========================+========================+===============================+=================================+ | debug | debug | | -g | +-------------------------+------------------------+-------------------------------+---------------------------------+ -| default | default | | -O2 -g | +| default | default | | -Os -g | +-------------------------+------------------------+-------------------------------+---------------------------------+ | release | release | | -O3 | +-------------------------+------------------------+-------------------------------+---------------------------------+ @@ -235,9 +235,9 @@ build types and output executable and libraries names, which will receive a suff +==================+===================+ | DEBUG | -g | +------------------+-------------------+ -| DEFAULT | -O2 -g -DNDEBUG | +| DEFAULT | -Os -g -DNDEBUG | +------------------+-------------------+ -| RELWITHDEBINFO | -O2 -g -DNDEBUG | +| RELWITHDEBINFO | -Os -g -DNDEBUG | +------------------+-------------------+ | RELEASE | -O3 -DNDEBUG | +------------------+-------------------+ @@ -1965,7 +1965,7 @@ Installing the packages can take a while, and it can look like it hanged. -- -- Copying /ns-3-dev/cmake-build-release/_deps/armadillo-src/include/ to /ns-3-dev/cmake-build-release/_deps/armadillo-build/tmp/include/ -- Generating /ns-3-dev/cmake-build-release/_deps/armadillo-build/tmp/include/config.hpp - -- CMAKE_CXX_FLAGS = -fsanitize=address,leak,undefined -O2 + -- CMAKE_CXX_FLAGS = -fsanitize=address,leak,undefined -Os -- CMAKE_SHARED_LINKER_FLAGS = -Wl,--no-as-needed -- CMAKE_REQUIRED_INCLUDES = /usr/include;/usr/include/superlu -- diff --git a/doc/manual/source/working-with-docker.rst b/doc/manual/source/working-with-docker.rst new file mode 100644 index 0000000000..f773e2d393 --- /dev/null +++ b/doc/manual/source/working-with-docker.rst @@ -0,0 +1,585 @@ +.. include:: replace.txt +.. highlight:: bash + + +.. _Docker : https://docs.docker.com/desktop/ +.. _rootless mode : https://docs.docker.com/engine/security/rootless/ +.. _Podman : https://podman.io/ +.. _Apptainer : https://apptainer.org/docs/user/latest/ +.. _continuous integration (CI) : https://docs.gitlab.com/ee/ci/ + +.. _Working with Docker: + +Working with Docker +------------------- + +The ns-3 project repository is currently hosted in GitLab, which includes +`continuous integration (CI)`_ tools to automate build, tests, packaging and +distribution of software. The CI works based on jobs, that are defined +in YAML files, which specify a container the job will run on. + +See :ref:`Working with gitlab-ci-local` for how +to use containers for running our CI checks locally. + +A container is a lightweight virtualization tool that allows one to use user space +tools from different OSes on top of the same kernel. This drastically cuts the +overhead of alternatives such as full virtualization, where a complete operating +system and the hardware it runs on needs to be emulated, or the hardware switched +between a host and a guest OS via a hypervisor. + +The most common type of containers are applications containers, where +:ref:`Docker ` is the most popular solution. + +.. _Docker pricing: https://www.docker.com/pricing/ + +Note on pricing: notice that commercial and governmental use of Docker +may require a subscription. See `Docker pricing`_ for more information. +:ref:`Podman ` is an open-source drop-in replacement. + +Note on security: Docker is installed by default with root privileges. +This is a security hazard if you are running untrusted software, +especially in shared environments. Docker can be installed in +`rootless mode`_ for better isolation, however, the alternatives such +as `Podman`_ and `Apptainer`_ (previously Singularity) provide safer +default settings. You can read more on `Docker security`_. + +.. _Docker containers: + +Docker containers +***************** + +`Docker`_ popularized containers and made them ubiquitous in continuous integration +due to its ease of use. This section will consolidate the basics of how to work +with Docker or its compatible alternatives. + +.. _Docker security: https://docs.docker.com/engine/security/ + +Docker workflow typically consists of 10 steps: + +#. `Install Docker`_ +#. `Write a Dockerfile`_ +#. `Build a Docker container image`_ +#. `Create a container based on the image`_ +#. `Start the container`_ +#. `Access the container`_ +#. `Stop the container`_ +#. `Deleting the container`_ +#. `Publishing the container image`_ +#. `Deleting the container image`_ + +.. _Install Docker: + +Install Docker +============== + +Docker is usually set up (*e.g.* via system package managers or their official +installers) in root mode, requiring frequent use of administrative +permissions/sudo, which is necessary for some services, but not for most. +For proper isolation, install Docker in `rootless mode`_, or use one of +its compatible alternatives. + +.. _Write a Dockerfile: + +Write a Dockerfile +================== + +.. _special keywords: https://docs.docker.com/engine/reference/builder/ + +A Dockerfile is a file that contains instructions of how to build an image of the +container that will host the application / service. These files are composed of +one-line commands using `special keywords`_. The most common keywords are: + +* ``FROM``: used to specify a parent image +* ``COPY``: used to copy files from the external build directory into the container +* ``RUN``: run shell commands to install dependencies and set up the service +* ``ENTRYPOINT``: program to be started when the container is launched + +Here is one example of a ``Dockerfile`` that can be used to debug a ns-3 +program on Fedora 37: + +.. sourcecode:: docker + + FROM fedora:37 + + RUN dnf update --assumeyes && dnf install --assumeyes gcc-c++ cmake ccache ninja-build python gdb + + ENTRYPOINT ["bash"] + +When Docker is called to build the container image for this Dockerfile, it will +pull the image for fedora:37 from a ``Docker Registry``. Common registries +include docker.io (which hosts images shown in the DockerHub webpage), quay.io, +GitHub, GitLab, or you can have your own self-hosted option. + +Note: For security reasons, it is not recommended to run third-party images +in production. Dockerfiles are embedded into docker images and can be checked. +One example of how this can be done is shown below: + +.. sourcecode:: console + + $ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + fedoradebugging 37 d96491e23a80 10 days ago 829 MB + + $ docker history fedoradebugging + ID CREATED CREATED BY SIZE COMMENT + 0b56b184852b 10 days ago /bin/sh -c #(nop) ENTRYPOINT ["bash"] 0 B + 10 days ago /bin/sh -c dnf update --assumeyes && dnf i... 648 MB FROM registry.fedoraproject.org/fedora:37 + 4105b568d464 2 months ago 182 MB Created by Image Factory + +We can see different ``layers`` (commands) that compose the final docker image. +When compared to the Dockerfile, they show up in reverse order from the latest +to the earliest event. + +.. _Build a Docker container image: + +Build a Docker container image +============================== + +When building toolchain containers to work on projects, we typically don't +want to copy the projects themselves into the container. So we need to pass +an empty directory to Docker. + +We also need to specify a tag for our image, otherwise it will have a randomly +assigned name which we will have to refer to later. + +.. sourcecode:: console + + $ mkdir empty-dir + + $ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + + $ docker build -t fedoradebugging:37 -f Dockerfile ./empty-dir + STEP 1/3: FROM fedora:37 + Resolved "fedora" as an alias (/etc/containers/registries.conf.d/shortnames.conf) + Trying to pull registry.fedoraproject.org/fedora:37... + Getting image source signatures + Copying blob 80b613d8f1ff done + Copying config 4105b568d4 done + Writing manifest to image destination + Storing signatures + STEP 2/3: RUN dnf update --assumeyes && dnf install --assumeyes gcc-c++ cmake ccache ninja-build python gdb + Fedora 37 - x86_64 4.0 MB/s | 82 MB 00:20 + Fedora 37 openh264 (From Cisco) - x86_64 2.1 kB/s | 2.5 kB 00:01 + Fedora Modular 37 - x86_64 1.6 MB/s | 3.8 MB 00:02 + Fedora 37 - x86_64 - Updates 5.0 MB/s | 41 MB 00:08 + Fedora Modular 37 - x86_64 - Updates 1.3 MB/s | 2.9 MB 00:02 + Last metadata expiration check: 0:00:01 ago on Fri Feb 2 13:41:30 2024. + Dependencies resolved. + ================================================================================ + Package Arch Version Repository Size + ================================================================================ + Upgrading: + elfutils-default-yama-scope noarch 0.190-2.fc37 updates 12 k + ... + (38/56): cmake-3.27.7-1.fc37.x86_64.rpm 1.8 MB/s | 7.8 MB 00:04 + (39/56): cpp-12.3.1-1.fc37.x86_64.rpm 1.8 MB/s | 11 MB 00:05 + ... + Complete! + --> c33f842f2fc + STEP 3/3: ENTRYPOINT ["bash"] + COMMIT fedoradebugging:37 + --> 2412e124d12 + Successfully tagged localhost/fedoradebugging:37 + 2412e124d1257914a70fde70289948f7880fdbd1d3b213c206ff691995ecc03e + + $ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + localhost/fedoradebugging 37 2412e124d125 About a minute ago 829 MB + registry.fedoraproject.org/fedora 37 4105b568d464 2 months ago 182 MB + +Notice that our image got the repository name prepended (``localhost``). +This is a Podman thing, with the objective people specify the repositories +their images come from, instead of risking pulling an image from different +registries and risk pulling an infected image. + +.. _Create a container based on the image: + +Create a container based on the image +===================================== + +Note: For toolchain containers, which is the typical use case +for ns-3 testing, we use the ``run`` command instead. It creates +and starts the container in a single command. You can jump directly +to the `intended way to use toolchain containers`_, or continue +reading in case you want to learn a bit more about Docker. + +Now that we have our container image, we can create a container +based on it. It is like booting a brand-new computer with a freshly +installed operating system and commonly used programs. + +Docker containers can be created with the following: + +.. sourcecode:: console + + $ docker container ls -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + + $ docker container create --name fedoradeb fedoradebugging:37 + 8cb9edea0dcfe4a2335dd5b73766a6985275f9ee3e0b6fd5ea5b03eedbd4bbb1 + + $ docker container ls -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + 8cb9edea0dcf localhost/fedoradebugging:37 13 seconds ago Created fedoradeb + +.. _Start the container: + +Start the container +=================== + +Containers can be started with the following commands: + +.. sourcecode:: console + + $ docker start fedoradeb + fedoradeb + + $ docker container ls -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + 8cb9edea0dcf localhost/fedoradebugging:37 About a minute ago Exited (0) 13 seconds ago fedoradeb + +As it can be seen, our container was started, then executed bash, but it +was in a non-interactive session, so it doesn't wait for the user. The +process created by the entrypoint then exited, and the container +manager stopped the container. + +This is useful for containers running services, like web servers, +but not useful at all to use it as a toolchain container. In the +next section, we see the preferred way to start a container toolchain. + +.. _Access the container: + +Access the container +==================== + +For service containers, after starting the container with +``start``, we can execute commands on the running container +using ``exec``. We are going to use a different container for +demonstration purposes. + +.. sourcecode:: console + + $ docker pull nginx:latest + Resolving "nginx" using unqualified-search registries (/etc/containers/registries.conf) + Trying to pull docker.io/library/nginx:latest... + Getting image source signatures + Copying blob 398157bc5c51 done + Copying blob f0bd99a47d4a done + Copying blob f24a6f652778 done + Copying blob c57ee5000d61 done + Copying blob 9f3589a5fc50 done + Copying blob 9b0163235c08 done + Copying blob 1ef1c1a36ec2 done + Copying config b690f5f0a2 done + Writing manifest to image destination + Storing signatures + b690f5f0a2d535cee5e08631aa508fef339c43bb91d5b1f7d77a1a05cea021a8 + + $ docker container create --name nginx nginx:latest + b6fb5a96bed7552a8164ee20e20cb2dd39ac98f6a7c7c076d0e22b93bc85b988 + + $ docker container ls -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + b6fb5a96bed7 docker.io/library/nginx:latest nginx -g daemon o... 16 seconds ago Created nginx + + $ docker start nginx + nginx + + $ docker exec nginx whereis nginx + nginx: /usr/sbin/nginx /usr/lib/nginx /etc/nginx /usr/share/nginx + + $ docker exec -it nginx bash + + root@b6fb5a96bed7:/# echo "Printing a message in the container" + Printing a message in the container + + root@b6fb5a96bed7:/# exit + exit + + $ docker container stop nginx + nginx + + $ docker container ls -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + b6fb5a96bed7 docker.io/library/nginx:latest nginx -g daemon o... 5 minutes ago Exited (0) 7 seconds ago nginx + + $ docker container rm nginx + b6fb5a96bed7552a8164ee20e20cb2dd39ac98f6a7c7c076d0e22b93bc85b988 + + $ docker container ls -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + + $ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + docker.io/library/nginx latest b690f5f0a2d5 3 months ago 191 MB + + $ docker image rm nginx:latest + Untagged: docker.io/library/nginx:latest + Deleted: b690f5f0a2d535cee5e08631aa508fef339c43bb91d5b1f7d77a1a05cea021a8 + +.. _intended way to use toolchain containers: + +The intended way to access toolchain containers +############################################### + +Other than ``start/stop/exec``, Docker also has a ``run`` option, that builds a +brand-new container from the container image for each time it is executed. +This is the intended way to use toolchain containers. + +.. sourcecode:: console + + $ docker run -it fedoradebugging:37 + + [root@6fa29fa742c5 /]# echo "Printing a message in the container" + Printing a message in the container + + [root@6fa29fa742c5 /]# exit + exit + + $ + +Now we need to access files that are not inside the container volume. To do +this, we can mount an external volume as a local directory. + +.. sourcecode:: console + + $ mkdir -p ./external/ns-3-dev + + $ echo "hello" > ./external/ns-3-dev/msg.txt + + $ docker run -it -v ./external/ns-3-dev:/internal/ns-3-dev fedoradebugging:37 + + [root@6fa29fa742c5 /]# cat /internal/ns-3-dev/msg.txt + hello + + [root@8f0fd2eded04 /]# exit + exit + + $ + +With this, we can point to the real ns-3-dev directory and work as usual. + +.. sourcecode:: console + + $ docker run -it -v ./ns-3-dev:/ns-3-dev fedoradebugging:37 + + [root@067a8b748816 /]# cd ns-3-dev/ + + [root@067a8b748816 ns-3-dev]# ./ns3 configure + Warn about uninitialized values. + -- The CXX compiler identification is GNU 12.3.1 + ... + -- ---- Summary of ns-3 settings: + Build profile : default + Build directory : /ns-3-dev/build + Build with runtime asserts : ON + Build with runtime logging : ON + Build version embedding : OFF (not requested) + ... + -- Configuring done (26.5s) + -- Generating done (11.6s) + -- Build files have been written to: /ns-3-dev/cmake-cache + Finished executing the following commands: + /usr/bin/cmake3 -S /ns-3-dev -B /ns-3-dev/cmake-cache -DCMAKE_BUILD_TYPE=default -DNS3_ASSERT=ON -DNS3_LOG=ON -DNS3_WARNINGS_AS_ERRORS=OFF -DNS3_NATIVE_OPTIMIZATIONS=OFF -G Ninja - + -warn-uninitialized + +The container will be automatically stopped after exiting. + +.. sourcecode:: console + + [root@067a8b748816 ns-3-dev]# exit + exit + + $ docker container ls + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + + +.. _Stop the container: + +Stop the container +================== + +For long-running, non-interactive containers, use: + +.. sourcecode:: console + + $ docker container stop containername + + +.. _Deleting the container: + +Deleting the container +====================== + +To delete a container, it must be stopped first. +If it isn't listed in ``docker container ls``, that +is already the case. + +.. sourcecode:: console + + $ docker container ls -a + CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES + 067a8b748816 localhost/fedoradebugging:37 3 minutes ago Exited (0) 5 seconds ago relaxed_carver + + $ docker container rm relaxed_carver + 067a8b748816715d93ede9099132d943c04b13fcc23b3b8a7e21d23c1096cc2a + +.. _Publishing the container image: + +Publishing the container image +============================== + +To publish an image, you need to tag it prepending the +Docker registry you are submitting your image. + +For example, to submit our ``localhost/fedoradebugging:37`` +to the Docker.io registry, we would add the +``docker.io/username/fedoradebugging:37``. + +.. sourcecode:: console + + $ docker tag localhost/fedoradebugging:37 docker.io/username/fedoradebugging:37 + + $ docker push docker.io/username/fedoradebugging:37 + +If you don't want to push your image to a public registry, you can +run your own registry inside a container. The following command +will set up a registry container, and expose it to port 5000 of +the host device. This allows third parties to access the service +hosted inside the container, as long as the host firewall allows it. + +.. sourcecode:: console + + $ docker run -d -p 5000:5000 --restart always --name registry registry:2 + Resolved "registry" as an alias (/etc/containers/registries.conf.d/shortnames.conf) + Trying to pull docker.io/library/registry:2... + Getting image source signatures + Copying blob 619be1103602 done + Copying blob d1a4f6454cb2 done + Copying blob 0da701e3b4d6 done + Copying blob 2ba4b87859f5 done + Copying blob 14a4d5d702c7 done + Copying config a8781fe3b7 done + Writing manifest to image destination + Storing signatures + fa61d0ba582bc4953d81163abdb174dea937c15f5882a5395a857dfa8b8fc4fc + + $ docker tag fedoradebugging:37 localhost:5000/fedoradebugging:37 + + $ docker push localhost:5000/fedoradebugging:37 + + +Note: you can also publish your container images to GitLab and GitHub +container registries. You first need to login into the registries, +then set the appropriate tag for the registry and push the image. + +Here is an example for GitLab: + +.. sourcecode:: console + + $ docker login -u user_name registry_url + + $ docker tag fedoradebugging:37 registry.gitlab.com/user_name/project_name/fedoradebugging:37 + + $ docker push registry.gitlab.com/user_name/project_name/fedoradebugging:37 + Getting image source signatures + Copying blob cb6b836430b4 [================================>-----] 152.0MiB / 173.3MiB + Copying blob cb6b836430b4 [================================>-----] 152.0MiB / 173.3MiB + Copying blob cb6b836430b4 [================================>-----] 152.0MiB / 173.3MiB + Copying blob cb6b836430b4 [================================>-----] 152.0MiB / 173.3MiB + Copying blob cb6b836430b4 [================================>-----] 152.0MiB / 173.3MiB + Getting image source signatures + Copying blob cb6b836430b4 done + Copying config 4105b568d4 done + Writing manifest to image destination + Storing signatures + + $ docker image prune -a + WARNING! This command removes all images without at least one container associated with them. + Are you sure you want to continue? [y/N] y + 4105b568d464732d3ea6a3ce9a0095f334fa7aa86fdd1129f288d2687801d87d + + $ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + + $ docker pull registry.gitlab.com/user_name/project_name/fedoradebugging:37 + Trying to pull registry.gitlab.com/user_name/project_name/fedoradebugging:37... + Getting image source signatures + Copying blob 6eb8dda2c1ca done + Copying config 4105b568d4 done + Writing manifest to image destination + Storing signatures + 4105b568d464732d3ea6a3ce9a0095f334fa7aa86fdd1129f288d2687801d87d + + +We can also build our docker images directly from the GitLab CI and publish them +with the following jobs: + +.. sourcecode:: yaml + + .build-and-register-docker-image: + image: docker + services: + - docker:dind + before_script: + - mkdir -p $HOME/.docker + - docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY + script: + - docker build --pull -f $DOCKERFILE -t $CI_REGISTRY_IMAGE/$DOCKERTAG . + - docker push $CI_REGISTRY_IMAGE/$DOCKERTAG + + fedoradebugging37: + extends: + - .build-and-register-docker-image + variables: + DOCKERFILE: "Dockerfile.fedoradebugging37.txt" + DOCKERTAG: "fedoradebugging:37" + +.. _Deleting the container image: + +Deleting the container image +============================ + +Same command we have shown a few times in the previous command. + +.. sourcecode:: console + + $ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + localhost/fedoradebugging 37 2412e124d125 About an hour ago 829 MB + localhost:5000/fedoradebugging 37 2412e124d125 About an hour ago 829 MB + + $ docker image rm localhost:5000/fedoradebugging:37 + + $ docker image ls + REPOSITORY TAG IMAGE ID CREATED SIZE + localhost/fedoradebugging 37 2412e124d125 About an hour ago 829 MB + + $ docker image rm localhost/fedoradebugging:37 + Untagged: localhost/fedoradebugging:37 + Deleted: 2412e124d1257914a70fde70289948f7880fdbd1d3b213c206ff691995ecc03e + Deleted: c33f842f2fc0181b3b5f1d71456b0ffb8a2ec94e8d093f4873c61c492dd7e3dd + +.. _Podman containers: + +Podman containers +***************** + +`Podman`_ is the drop-in replacement for Docker made by RedHat. +You can install it and set up an alias using the following command. + +.. sourcecode:: console + + echo alias docker=podman >> ~/.bashrc + +To get a docker-like experience, you might want to +also change a few settings, such as search repositories for unqualified +image names (without the prepended repository/registry). + +This can be done by adding the following line in ``/etc/containers/registries.conf`` + +.. sourcecode:: text + + unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "docker.io"] + + diff --git a/doc/manual/source/working-with-gitlab-ci-local.rst b/doc/manual/source/working-with-gitlab-ci-local.rst index 7a4b30b2af..951b0e0fb0 100644 --- a/doc/manual/source/working-with-gitlab-ci-local.rst +++ b/doc/manual/source/working-with-gitlab-ci-local.rst @@ -1,6 +1,7 @@ .. include:: replace.txt .. highlight:: bash +.. _Working with gitlab-ci-local: Working with gitlab-ci-local ---------------------------- @@ -11,13 +12,13 @@ Working with gitlab-ci-local .. _crypto miners abuse : https://about.gitlab.com/blog/2021/05/17/prevent-crypto-mining-abuse/ .. _GitLab-CI-local : https://github.com/firecow/gitlab-ci-local .. _GitLab CI : https://docs.gitlab.com/ee/ci/ -.. _Docker : https://docs.docker.com/desktop/ -.. _rootless mode : https://docs.docker.com/engine/security/rootless/ The ns-3 project repository is currently hosted in GitLab, which includes `continuous integration (CI)`_ tools to automate build, tests, packaging and distribution of software. The CI works based on jobs, that are defined -on YAML files. +in YAML files and run inside containers. + +See :ref:`Working with Docker` for more information about containers in general. The ns-3 GitLab CI files are located in ``ns-3-dev/utils/tests/``. The main GitLab CI file is ``gitlab-ci.yml``. The different jobs @@ -44,16 +45,16 @@ and pipelines without requiring pushes to test repositories or main repositories that fill up the CI job queues with failed jobs due to script errors. -GitLab-CI-local relies on `Docker`_ to setup the environment to execute -the jobs. +GitLab-CI-local relies on :ref:`Docker containers` +to setup the environment to execute the jobs. Note: Docker is usually setup in root mode, requiring frequent use of administrative permissions/sudo. However, this is highly discouraged. You can configure Docker to run -in `rootless mode`_. From this point onwards, we assume Docker is configured -in `rootless mode`_. +in :ref:`Docker rootless mode `. From this point onwards, we assume Docker is configured +in :ref:`Docker rootless mode `. -After installing both `Docker`_ in `rootless mode`_ and `GitLab-CI-local`_, +After installing both :ref:`Docker ` and `GitLab-CI-local`_, the ns-3 jobs can be listed using the following command: .. sourcecode:: bash diff --git a/doc/models/Makefile b/doc/models/Makefile index d36619895e..e3a8a2dbe1 100644 --- a/doc/models/Makefile +++ b/doc/models/Makefile @@ -111,6 +111,7 @@ SOURCEFIGS = \ figures/testbed.dia \ figures/emulated-channel.dia \ $(SRC)/antenna/doc/source/figures/antenna-coordinate-system.dia \ + $(SRC)/antenna/doc/source/figures/circular-antenna-pattern.png \ $(SRC)/applications/doc/http-embedded-object-size.png \ $(SRC)/applications/doc/http-main-object-size.png \ $(SRC)/applications/doc/http-num-of-embedded-objects.png \ @@ -141,6 +142,7 @@ SOURCEFIGS = \ $(SRC)/wifi/doc/source/figures/PhyEntityHierarchy.dia \ $(SRC)/wifi/doc/source/figures/WifiPpduHierarchy.dia \ $(SRC)/wifi/doc/source/figures/FemHierarchy.dia \ + $(SRC)/wifi/doc/source/figures/wifi-phy-rx-trace-helper.dia \ $(SRC)/wifi/doc/source/figures/snir.dia \ $(SRC)/wifi/doc/source/figures/ack-su-format.pdf \ $(SRC)/wifi/doc/source/figures/ack-su-format.png \ @@ -388,6 +390,7 @@ IMAGES_EPS = \ $(FIGURES)/PhyEntityHierarchy.eps \ $(FIGURES)/WifiPpduHierarchy.eps \ $(FIGURES)/FemHierarchy.eps \ + $(FIGURES)/wifi-phy-rx-trace-helper.eps \ $(FIGURES)/snir.eps \ $(FIGURES)/WimaxArchitecture.eps \ $(FIGURES)/epc-ctrl-arch.eps \ @@ -577,7 +580,7 @@ RESCALE = ../../utils/rescale-pdf.sh @if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build diff --git a/doc/models/source/conf.py b/doc/models/source/conf.py index 665266b9bb..2fbed33d8b 100644 --- a/doc/models/source/conf.py +++ b/doc/models/source/conf.py @@ -74,16 +74,16 @@ # built documents. # # The short X.Y version. -version = "ns-3.41" +version = "ns-3.42" # The full version, including alpha/beta/rc tags. -release = "ns-3.41" +release = "ns-3.42" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff --git a/doc/ns3_html_theme/ns3_doxy_footer.html b/doc/ns3_html_theme/ns3_doxy_footer.html index 1e57ea8c2d..e2fa618a75 100644 --- a/doc/ns3_html_theme/ns3_doxy_footer.html +++ b/doc/ns3_html_theme/ns3_doxy_footer.html @@ -1,6 +1,5 @@ @@ -8,15 +7,15 @@
    $navpath + + doxygen $doxygenversion
diff --git a/doc/ns3_html_theme/ns3_doxy_header.html b/doc/ns3_html_theme/ns3_doxy_header.html index 8617f677d7..cce6448b0e 100644 --- a/doc/ns3_html_theme/ns3_doxy_header.html +++ b/doc/ns3_html_theme/ns3_doxy_header.html @@ -1,28 +1,34 @@ - + - + + $projectname: $title $title + + + + + + $treeview $search $mathjax +$darkmode $extrastylesheet - - +
@@ -30,12 +36,12 @@
- +
@@ -48,19 +54,19 @@
  •   Home + href="https://www.nsnam.org/" + >  Home
  • Tutorials  ▼
    + onmouseover="mcancelclosetime()" + onmouseout="mclosetime()"> English
    + >English
  • Documentation  ▼
    + onmouseover="mcancelclosetime()" + onmouseout="mclosetime()"> Installation
    @@ -92,16 +98,16 @@ onmouseout="mclosetime()" >Development  ▼
    + onmouseover="mcancelclosetime()" + onmouseout="mclosetime()"> API Docs
    Issue Tracker
    Merge Requests
  • @@ -115,7 +121,7 @@
- +
diff --git a/doc/ns3_html_theme/static/drop-down-menu.js b/doc/ns3_html_theme/static/drop-down-menu.js index a0ca0a6e5d..09dcdeaf43 100644 --- a/doc/ns3_html_theme/static/drop-down-menu.js +++ b/doc/ns3_html_theme/static/drop-down-menu.js @@ -30,9 +30,9 @@ // POSSIBILITY OF SUCH DAMAGE. // -var timeout = 250; -var closetimer = 0; -var ddmenuitem = 0; +var timeout = 250; +var closetimer = 0; +var ddmenuitem = 0; // open hidden layer function mopen(id) diff --git a/doc/ns3_html_theme/static/ns3_stylesheet.css b/doc/ns3_html_theme/static/ns3_stylesheet.css index dd32d1aab4..4131072e8c 100644 --- a/doc/ns3_html_theme/static/ns3_stylesheet.css +++ b/doc/ns3_html_theme/static/ns3_stylesheet.css @@ -94,6 +94,11 @@ div.sphinxsidebar a { z-index: 10000; } +#projectrow +{ + height: 56px; +} + #projectlogo { color: white; margin: 10px; diff --git a/doc/ns3_html_theme/static/sidebar.js b/doc/ns3_html_theme/static/sidebar.js index a45e1926ad..8994f91183 100644 --- a/doc/ns3_html_theme/static/sidebar.js +++ b/doc/ns3_html_theme/static/sidebar.js @@ -98,9 +98,9 @@ $(function() { // find the height of the viewport to center the '<<' in the page var viewport_height; if (window.innerHeight) - viewport_height = window.innerHeight; + viewport_height = window.innerHeight; else - viewport_height = $(window).height(); + viewport_height = $(window).height(); sidebarbutton.find('span').css({ 'display': 'block', 'margin-top': (viewport_height - sidebar.position().top - 20) / 2 diff --git a/doc/ns3_html_theme/theme.conf b/doc/ns3_html_theme/theme.conf index 16dd1b00e1..f112f8e844 100644 --- a/doc/ns3_html_theme/theme.conf +++ b/doc/ns3_html_theme/theme.conf @@ -22,29 +22,28 @@ collapsiblesidebar = false externalrefs = false bgcolor = white -textcolor = black +textcolor = black linkcolor = #91A501 visitedlinkcolor = #91A501 headbgcolor = #E3E3E3 -headtextcolor = #373737 -headlinkcolor = #91A501 +headtextcolor = #373737 +headlinkcolor = #91A501 -relbarbgcolor = #D5D5D5 +relbarbgcolor = #D5D5D5 relbarlinkcolor = #373737 relbartextcolor = #373737 -sidebarbgcolor = #FAFAFA +sidebarbgcolor = #FAFAFA sidebartextcolor = #373737 sidebarlinkcolor = #91A501 sidebarbtncolor = #D5D5D5 footerbgcolor = #D5D5D5 -footertextcolor = #364D7C +footertextcolor = #364D7C codebgcolor = #FBFCFD codetextcolor = black bodyfont = 'Lucida Grande', Verdana, Geneva, Arial, sans-serif headfont = 'Lucida Grande', Verdana, Geneva, Arial, sans-serif - diff --git a/doc/tutorial/Makefile b/doc/tutorial/Makefile index ea2ecc46f5..fb92c7e7c6 100644 --- a/doc/tutorial/Makefile +++ b/doc/tutorial/Makefile @@ -2,7 +2,7 @@ # # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build diff --git a/doc/tutorial/source/conf.py b/doc/tutorial/source/conf.py index c1a46d4c20..6f1dee1bc3 100644 --- a/doc/tutorial/source/conf.py +++ b/doc/tutorial/source/conf.py @@ -71,16 +71,16 @@ # built documents. # # The short X.Y version. -version = "ns-3.41" +version = "ns-3.42" # The full version, including alpha/beta/rc tags. -release = "ns-3.41" +release = "ns-3.42" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: diff --git a/doc/tutorial/source/getting-started.rst b/doc/tutorial/source/getting-started.rst index 512102b0d1..de32de1956 100644 --- a/doc/tutorial/source/getting-started.rst +++ b/doc/tutorial/source/getting-started.rst @@ -61,7 +61,7 @@ the project provides an installation guide for various systems, available at https://www.nsnam.org/docs/installation/html/index.html. -As of the most recent |ns3| release (ns-3.41), the following tools +As of the most recent |ns3| release (ns-3.42), the following tools are needed to get started with |ns3|: ============ =========================================================== @@ -116,21 +116,21 @@ get a copy of a release by typing the following into your Linux shell $ cd $ mkdir workspace $ cd workspace - $ wget https://www.nsnam.org/release/ns-allinone-3.41.tar.bz2 - $ tar xjf ns-allinone-3.41.tar.bz2 + $ wget https://www.nsnam.org/release/ns-allinone-3.42.tar.bz2 + $ tar xjf ns-allinone-3.42.tar.bz2 Notice the use above of the ``wget`` utility, which is a command-line tool to fetch objects from the web; if you do not have this installed, you can use a browser for this step. Following these steps, if you change into the directory -``ns-allinone-3.41``, you should see a number of files and directories +``ns-allinone-3.42``, you should see a number of files and directories .. sourcecode:: text - $ cd ns-allinone-3.41 + $ cd ns-allinone-3.42 $ ls - bake build.py constants.py netanim-3.109 ns-3.41 README.md util.py + bake build.py constants.py netanim-3.109 ns-3.42 README.md util.py You are now ready to build the base |ns3| distribution and may skip ahead to the section on building |ns3|. @@ -180,7 +180,7 @@ release number: .. sourcecode:: console - $ python3 download.py -n ns-3.41 + $ python3 download.py -n ns-3.42 After this step, the additional repositories of |ns3|, bake, pybindgen, and netanim will be downloaded to the ``ns-3-allinone`` directory. @@ -249,9 +249,9 @@ distribution of your choice. There are a few configuration targets available: -1. ``ns-3.41``: the code corresponding to the release +1. ``ns-3.42``: the code corresponding to the release 2. ``ns-3-dev``: a similar module but using the development code tree -3. ``ns-allinone-3.41``: the module that includes other optional features +3. ``ns-allinone-3.42``: the module that includes other optional features such as bake build system, netanim animator, and pybindgen 4. ``ns-3-allinone``: similar to the released version of the allinone module, but for development code. @@ -268,7 +268,7 @@ code either by inspection of the repository list or by going to the `"ns-3 Releases" `_ web page and clicking on the latest release link. We'll proceed in -this tutorial example with ``ns-3.41``. +this tutorial example with ``ns-3.42``. We are now going to use the bake tool to pull down the various pieces of |ns3| you will be using. First, we'll say a word about running bake. @@ -297,7 +297,7 @@ Step into the workspace directory and type the following into your shell: .. sourcecode:: console - $ ./bake.py configure -e ns-allinone-3.41 + $ ./bake.py configure -e ns-allinone-3.42 Next, we'll ask bake to check whether we have enough tools to download various components. Type: @@ -347,7 +347,7 @@ should yield something like: >> Downloading click-ns-3.37 - OK >> Downloading BRITE - OK >> Downloading openflow-dev - OK - >> Downloading ns-3.41 (target directory:ns-3.41) - OK + >> Downloading ns-3.42 (target directory:ns-3.42) - OK The above suggests that three sources have been downloaded. Check the ``source`` directory now and type ``ls``; one should see: @@ -356,7 +356,7 @@ The above suggests that three sources have been downloaded. Check the $ cd source $ ls - BRITE click-ns-3.37 netanim-3.109 ns-3.41 openflow-dev + BRITE click-ns-3.37 netanim-3.109 ns-3.42 openflow-dev You are now ready to build the |ns3| distribution. @@ -386,7 +386,7 @@ native |ns3| build system, CMake, to be introduced later in this tutorial. If you downloaded using a tarball you should have a directory called something like -``ns-allinone-3.41`` under your ``~/workspace`` directory. +``ns-allinone-3.42`` under your ``~/workspace`` directory. Type the following: .. sourcecode:: console @@ -419,7 +419,7 @@ and you should see something like: .. sourcecode:: text >> Building netanim-3.109 - OK - >> Building ns-3.41 - OK + >> Building ns-3.42 - OK There may be failures to build all components, but the build will proceed anyway if the component is optional. @@ -795,7 +795,7 @@ The build profile controls the use of logging, assertions, and compiler optimiza | Wrapper | | | | | | Macro | | | | | +----------+---------------------------------+-----------------------------+-------------------------------+---------------------------------+ - | Compiler | ``-Og -g`` | ``-O2 -g`` | ``-O3`` | ``-O3`` | + | Compiler | ``-Og -g`` | ``-Os -g`` | ``-O3`` | ``-O3`` | | Flags | | | | ``-march=native`` | | | | | | ``-mtune=native`` | +----------+---------------------------------+-----------------------------+-------------------------------+---------------------------------+ @@ -1159,7 +1159,7 @@ The first, is to set VSCode's ``settings.json`` file to include the following: The second, a more permanent solution, with the following command: -.. sourcecode:: terminal +.. sourcecode:: console > echo %PATH% C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem; diff --git a/doc/tutorial/source/quick-start.rst b/doc/tutorial/source/quick-start.rst index 9c3f22329a..b2a76e5c6f 100644 --- a/doc/tutorial/source/quick-start.rst +++ b/doc/tutorial/source/quick-start.rst @@ -64,13 +64,13 @@ Downloading the Latest Release :: - $ tar xjf ns-allinone-3.41.tar.bz2 + $ tar xjf ns-allinone-3.42.tar.bz2 3) Change into the |ns3| directory directly; e.g. :: - $ cd ns-allinone-3.41/ns-3.41 + $ cd ns-allinone-3.42/ns-3.42 The ns-allinone directory has some additional components but we are skipping over them here; one can work directly from the |ns3| source code directory. @@ -92,12 +92,12 @@ only to `cd` into ns-3-dev; the `master` branch is checked out by default. $ cd ns-3-dev -If instead you want to try the most recent release (version 3.41 as of this +If instead you want to try the most recent release (version 3.42 as of this writing), you can checkout a branch corresponding to that git tag: :: - $ git checkout -b ns-3.41-branch ns-3.41 + $ git checkout -b ns-3.42-branch ns-3.42 Building and testing ns-3 ************************* diff --git a/doc/tutorial/source/tracing.rst b/doc/tutorial/source/tracing.rst index dfd397eca0..8ba188d480 100644 --- a/doc/tutorial/source/tracing.rst +++ b/doc/tutorial/source/tracing.rst @@ -589,7 +589,7 @@ One of the predefined namespaces in the config system is "NodeList" which is a list of all of the nodes in the simulation. Items in the list are referred to by indices into the list, so "/NodeList/7" refers to the eighth Node in the list of nodes created during the simulation -(recall indices start at `0'). This reference is actually a +(recall indices start at '0'). This reference is actually a ``Ptr`` and so is a subclass of an ``ns3::Object``. As described in the Object Model section of the |ns3| Manual, we make @@ -1763,7 +1763,7 @@ creating simulation events. { m_running = false; - if (m_sendEvent.IsRunning()) + if (m_sendEvent.IsPending()) { Simulator::Cancel(m_sendEvent); } @@ -1776,7 +1776,7 @@ creating simulation events. Every time a simulation event is scheduled, an ``Event`` is created. If the ``Event`` is pending execution or executing, its method -``IsRunning`` will return ``true``. In this code, if ``IsRunning()`` +``IsPending`` will return ``true``. In this code, if ``IsPending()`` returns true, we ``Cancel`` the event which removes it from the simulator event queue. By doing this, we break the chain of events that the ``Application`` is using to keep sending its ``Packets`` and diff --git a/examples/energy/energy-model-example.cc b/examples/energy/energy-model-example.cc index 97e656687d..89e352b500 100644 --- a/examples/energy/energy-model-example.cc +++ b/examples/energy/energy-model-example.cc @@ -31,6 +31,7 @@ #include using namespace ns3; +using namespace ns3::energy; NS_LOG_COMPONENT_DEFINE("EnergyExample"); diff --git a/examples/energy/energy-model-with-harvesting-example.cc b/examples/energy/energy-model-with-harvesting-example.cc index 93dfa393f2..6c1ae96c92 100644 --- a/examples/energy/energy-model-with-harvesting-example.cc +++ b/examples/energy/energy-model-with-harvesting-example.cc @@ -60,6 +60,7 @@ #include using namespace ns3; +using namespace ns3::energy; NS_LOG_COMPONENT_DEFINE("EnergyWithHarvestingExample"); diff --git a/examples/realtime/realtime-udp-echo.py b/examples/realtime/realtime-udp-echo.py index 494d616ede..17fd2088af 100644 --- a/examples/realtime/realtime-udp-echo.py +++ b/examples/realtime/realtime-udp-echo.py @@ -38,43 +38,41 @@ def main(argv): # Allow the user to override any of the defaults and the above Bind() at # run-time, via command-line arguments # - cmd = ns.core.CommandLine() + cmd = ns.CommandLine() cmd.Parse(argv) # # But since this is a realtime script, don't allow the user to mess with # that. # - ns.core.GlobalValue.Bind( - "SimulatorImplementationType", ns.core.StringValue("ns3::RealtimeSimulatorImpl") - ) + ns.GlobalValue.Bind("SimulatorImplementationType", ns.StringValue("ns3::RealtimeSimulatorImpl")) # # Explicitly create the nodes required by the topology (shown above). # print("Create nodes.") - n = ns.network.NodeContainer() + n = ns.NodeContainer() n.Create(4) - internet = ns.internet.InternetStackHelper() + internet = ns.InternetStackHelper() internet.Install(n) # # Explicitly create the channels required by the topology (shown above). # print("Create channels.") - csma = ns.csma.CsmaHelper() - csma.SetChannelAttribute("DataRate", ns.network.DataRateValue(ns.network.DataRate(5000000))) - csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.MilliSeconds(2))) - csma.SetDeviceAttribute("Mtu", ns.core.UintegerValue(1400)) + csma = ns.CsmaHelper() + csma.SetChannelAttribute("DataRate", ns.DataRateValue(ns.DataRate(5000000))) + csma.SetChannelAttribute("Delay", ns.TimeValue(ns.MilliSeconds(2))) + csma.SetDeviceAttribute("Mtu", ns.UintegerValue(1400)) d = csma.Install(n) # # We've got the "hardware" in place. Now we need to add IP addresses. # print("Assign IP Addresses.") - ipv4 = ns.internet.Ipv4AddressHelper() - ipv4.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0")) + ipv4 = ns.Ipv4AddressHelper() + ipv4.SetBase(ns.Ipv4Address("10.1.1.0"), ns.Ipv4Mask("255.255.255.0")) i = ipv4.Assign(d) print("Create Applications.") @@ -83,10 +81,10 @@ def main(argv): # Create a UdpEchoServer application on node one. # port = 9 # well-known echo port number - server = ns.applications.UdpEchoServerHelper(port) + server = ns.UdpEchoServerHelper(port) apps = server.Install(n.Get(1)) - apps.Start(ns.core.Seconds(1.0)) - apps.Stop(ns.core.Seconds(10.0)) + apps.Start(ns.Seconds(1.0)) + apps.Stop(ns.Seconds(10.0)) # # Create a UdpEchoClient application to send UDP datagrams from node zero to @@ -94,16 +92,16 @@ def main(argv): # packetSize = 1024 maxPacketCount = 500 - interPacketInterval = ns.core.Seconds(0.01) - client = ns.applications.UdpEchoClientHelper(i.GetAddress(1).ConvertTo(), port) - client.SetAttribute("MaxPackets", ns.core.UintegerValue(maxPacketCount)) - client.SetAttribute("Interval", ns.core.TimeValue(interPacketInterval)) - client.SetAttribute("PacketSize", ns.core.UintegerValue(packetSize)) + interPacketInterval = ns.Seconds(0.01) + client = ns.UdpEchoClientHelper(i.GetAddress(1).ConvertTo(), port) + client.SetAttribute("MaxPackets", ns.UintegerValue(maxPacketCount)) + client.SetAttribute("Interval", ns.TimeValue(interPacketInterval)) + client.SetAttribute("PacketSize", ns.UintegerValue(packetSize)) apps = client.Install(n.Get(0)) - apps.Start(ns.core.Seconds(2.0)) - apps.Stop(ns.core.Seconds(10.0)) + apps.Start(ns.Seconds(2.0)) + apps.Stop(ns.Seconds(10.0)) - ascii = ns.network.AsciiTraceHelper() + ascii = ns.AsciiTraceHelper() csma.EnableAsciiAll(ascii.CreateFileStream("realtime-udp-echo.tr")) csma.EnablePcapAll("realtime-udp-echo", False) @@ -111,9 +109,9 @@ def main(argv): # Now, do the actual simulation. # print("Run Simulation.") - ns.core.Simulator.Stop(ns.Seconds(10)) - ns.core.Simulator.Run() - ns.core.Simulator.Destroy() + ns.Simulator.Stop(ns.Seconds(10)) + ns.Simulator.Run() + ns.Simulator.Destroy() print("Done.") diff --git a/examples/routing/rip-simple-network.cc b/examples/routing/rip-simple-network.cc index 5c4c52786f..aa2efa011b 100644 --- a/examples/routing/rip-simple-network.cc +++ b/examples/routing/rip-simple-network.cc @@ -82,7 +82,7 @@ main(int argc, char** argv) cmd.AddValue("printRoutingTables", "Print routing tables at 30, 60 and 90 seconds", printRoutingTables); - cmd.AddValue("showPings", "Show Ping6 reception", showPings); + cmd.AddValue("showPings", "Show Ping reception", showPings); cmd.AddValue("splitHorizonStrategy", "Split Horizon strategy to use (NoSplitHorizon, SplitHorizon, PoisonReverse)", SplitHorizon); @@ -102,15 +102,15 @@ main(int argc, char** argv) if (SplitHorizon == "NoSplitHorizon") { - Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(RipNg::NO_SPLIT_HORIZON)); + Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(Rip::NO_SPLIT_HORIZON)); } else if (SplitHorizon == "SplitHorizon") { - Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(RipNg::SPLIT_HORIZON)); + Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(Rip::SPLIT_HORIZON)); } else { - Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(RipNg::POISON_REVERSE)); + Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(Rip::POISON_REVERSE)); } NS_LOG_INFO("Create nodes."); diff --git a/examples/routing/ripng-simple-network.cc b/examples/routing/ripng-simple-network.cc index b336af7afd..744b80f580 100644 --- a/examples/routing/ripng-simple-network.cc +++ b/examples/routing/ripng-simple-network.cc @@ -82,7 +82,7 @@ main(int argc, char** argv) cmd.AddValue("printRoutingTables", "Print routing tables at 30, 60 and 90 seconds", printRoutingTables); - cmd.AddValue("showPings", "Show Ping6 reception", showPings); + cmd.AddValue("showPings", "Show Ping reception", showPings); cmd.AddValue("splitHorizonStrategy", "Split Horizon strategy to use (NoSplitHorizon, SplitHorizon, PoisonReverse)", SplitHorizon); diff --git a/examples/routing/simple-routing-ping6.py b/examples/routing/simple-routing-ping6.py index 501cfb13e1..b8a0f0b4e8 100644 --- a/examples/routing/simple-routing-ping6.py +++ b/examples/routing/simple-routing-ping6.py @@ -58,7 +58,7 @@ def main(argv): internetv6.Install(all) # Create channels - csma = ns.csma.CsmaHelper() + csma = ns.CsmaHelper() csma.SetChannelAttribute("DataRate", ns.DataRateValue(ns.DataRate(5000000))) csma.SetChannelAttribute("Delay", ns.TimeValue(ns.MilliSeconds(2))) d1 = csma.Install(net1) diff --git a/examples/traffic-control/tbf-example.cc b/examples/traffic-control/tbf-example.cc index 1344ae7399..096e543a13 100644 --- a/examples/traffic-control/tbf-example.cc +++ b/examples/traffic-control/tbf-example.cc @@ -133,9 +133,9 @@ main(int argc, char* argv[]) ApplicationContainer apps; InetSocketAddress rmt(interfaces.GetAddress(0), port); - rmt.SetTos(0xb8); - AddressValue remoteAddress(rmt); - onoff.SetAttribute("Remote", remoteAddress); + onoff.SetAttribute("Remote", AddressValue(rmt)); + onoff.SetAttribute("Tos", UintegerValue(0xb8)); + apps.Add(onoff.Install(nodes.Get(1))); apps.Start(Seconds(1.0)); apps.Stop(Seconds(simulationTime + 0.1)); diff --git a/examples/traffic-control/traffic-control.cc b/examples/traffic-control/traffic-control.cc index 85fe47b14f..ee1a1cf848 100644 --- a/examples/traffic-control/traffic-control.cc +++ b/examples/traffic-control/traffic-control.cc @@ -174,9 +174,8 @@ main(int argc, char* argv[]) ApplicationContainer apps; InetSocketAddress rmt(interfaces.GetAddress(0), port); - rmt.SetTos(0xb8); - AddressValue remoteAddress(rmt); - onoff.SetAttribute("Remote", remoteAddress); + onoff.SetAttribute("Remote", AddressValue(rmt)); + onoff.SetAttribute("Tos", UintegerValue(0xb8)); apps.Add(onoff.Install(nodes.Get(1))); apps.Start(Seconds(1.0)); apps.Stop(Seconds(simulationTime + 0.1)); diff --git a/examples/tutorial/first.py b/examples/tutorial/first.py index 42311ad2fd..8a10ae7e30 100644 --- a/examples/tutorial/first.py +++ b/examples/tutorial/first.py @@ -29,41 +29,41 @@ # // point-to-point # // -ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO) -ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO) +ns.LogComponentEnable("UdpEchoClientApplication", ns.LOG_LEVEL_INFO) +ns.LogComponentEnable("UdpEchoServerApplication", ns.LOG_LEVEL_INFO) -nodes = ns.network.NodeContainer() +nodes = ns.NodeContainer() nodes.Create(2) -pointToPoint = ns.point_to_point.PointToPointHelper() -pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps")) -pointToPoint.SetChannelAttribute("Delay", ns.core.StringValue("2ms")) +pointToPoint = ns.PointToPointHelper() +pointToPoint.SetDeviceAttribute("DataRate", ns.StringValue("5Mbps")) +pointToPoint.SetChannelAttribute("Delay", ns.StringValue("2ms")) devices = pointToPoint.Install(nodes) -stack = ns.internet.InternetStackHelper() +stack = ns.InternetStackHelper() stack.Install(nodes) -address = ns.internet.Ipv4AddressHelper() -address.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0")) +address = ns.Ipv4AddressHelper() +address.SetBase(ns.Ipv4Address("10.1.1.0"), ns.Ipv4Mask("255.255.255.0")) interfaces = address.Assign(devices) -echoServer = ns.applications.UdpEchoServerHelper(9) +echoServer = ns.UdpEchoServerHelper(9) serverApps = echoServer.Install(nodes.Get(1)) -serverApps.Start(ns.core.Seconds(1.0)) -serverApps.Stop(ns.core.Seconds(10.0)) +serverApps.Start(ns.Seconds(1.0)) +serverApps.Stop(ns.Seconds(10.0)) address = interfaces.GetAddress(1).ConvertTo() -echoClient = ns.applications.UdpEchoClientHelper(address, 9) -echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(1)) -echoClient.SetAttribute("Interval", ns.core.TimeValue(ns.core.Seconds(1.0))) -echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(1024)) +echoClient = ns.UdpEchoClientHelper(address, 9) +echoClient.SetAttribute("MaxPackets", ns.UintegerValue(1)) +echoClient.SetAttribute("Interval", ns.TimeValue(ns.Seconds(1.0))) +echoClient.SetAttribute("PacketSize", ns.UintegerValue(1024)) clientApps = echoClient.Install(nodes.Get(0)) -clientApps.Start(ns.core.Seconds(2.0)) -clientApps.Stop(ns.core.Seconds(10.0)) +clientApps.Start(ns.Seconds(2.0)) +clientApps.Stop(ns.Seconds(10.0)) -ns.core.Simulator.Run() -ns.core.Simulator.Destroy() +ns.Simulator.Run() +ns.Simulator.Destroy() diff --git a/examples/tutorial/second.py b/examples/tutorial/second.py index 0d01b93672..e5621fe285 100644 --- a/examples/tutorial/second.py +++ b/examples/tutorial/second.py @@ -43,61 +43,59 @@ cmd.Parse(sys.argv) if verbose.value: - ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO) - ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO) + ns.LogComponentEnable("UdpEchoClientApplication", ns.LOG_LEVEL_INFO) + ns.LogComponentEnable("UdpEchoServerApplication", ns.LOG_LEVEL_INFO) nCsma.value = 1 if nCsma.value == 0 else nCsma.value -p2pNodes = ns.network.NodeContainer() +p2pNodes = ns.NodeContainer() p2pNodes.Create(2) -csmaNodes = ns.network.NodeContainer() +csmaNodes = ns.NodeContainer() csmaNodes.Add(p2pNodes.Get(1)) csmaNodes.Create(nCsma.value) -pointToPoint = ns.point_to_point.PointToPointHelper() -pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps")) -pointToPoint.SetChannelAttribute("Delay", ns.core.StringValue("2ms")) +pointToPoint = ns.PointToPointHelper() +pointToPoint.SetDeviceAttribute("DataRate", ns.StringValue("5Mbps")) +pointToPoint.SetChannelAttribute("Delay", ns.StringValue("2ms")) p2pDevices = pointToPoint.Install(p2pNodes) -csma = ns.csma.CsmaHelper() -csma.SetChannelAttribute("DataRate", ns.core.StringValue("100Mbps")) -csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.NanoSeconds(6560))) +csma = ns.CsmaHelper() +csma.SetChannelAttribute("DataRate", ns.StringValue("100Mbps")) +csma.SetChannelAttribute("Delay", ns.TimeValue(ns.NanoSeconds(6560))) csmaDevices = csma.Install(csmaNodes) -stack = ns.internet.InternetStackHelper() +stack = ns.InternetStackHelper() stack.Install(p2pNodes.Get(0)) stack.Install(csmaNodes) -address = ns.internet.Ipv4AddressHelper() -address.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0")) +address = ns.Ipv4AddressHelper() +address.SetBase(ns.Ipv4Address("10.1.1.0"), ns.Ipv4Mask("255.255.255.0")) p2pInterfaces = address.Assign(p2pDevices) -address.SetBase(ns.network.Ipv4Address("10.1.2.0"), ns.network.Ipv4Mask("255.255.255.0")) +address.SetBase(ns.Ipv4Address("10.1.2.0"), ns.Ipv4Mask("255.255.255.0")) csmaInterfaces = address.Assign(csmaDevices) -echoServer = ns.applications.UdpEchoServerHelper(9) +echoServer = ns.UdpEchoServerHelper(9) serverApps = echoServer.Install(csmaNodes.Get(nCsma.value)) -serverApps.Start(ns.core.Seconds(1.0)) -serverApps.Stop(ns.core.Seconds(10.0)) +serverApps.Start(ns.Seconds(1.0)) +serverApps.Stop(ns.Seconds(10.0)) -echoClient = ns.applications.UdpEchoClientHelper( - csmaInterfaces.GetAddress(nCsma.value).ConvertTo(), 9 -) -echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(1)) -echoClient.SetAttribute("Interval", ns.core.TimeValue(ns.core.Seconds(1.0))) -echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(1024)) +echoClient = ns.UdpEchoClientHelper(csmaInterfaces.GetAddress(nCsma.value).ConvertTo(), 9) +echoClient.SetAttribute("MaxPackets", ns.UintegerValue(1)) +echoClient.SetAttribute("Interval", ns.TimeValue(ns.Seconds(1.0))) +echoClient.SetAttribute("PacketSize", ns.UintegerValue(1024)) clientApps = echoClient.Install(p2pNodes.Get(0)) -clientApps.Start(ns.core.Seconds(2.0)) -clientApps.Stop(ns.core.Seconds(10.0)) +clientApps.Start(ns.Seconds(2.0)) +clientApps.Stop(ns.Seconds(10.0)) -ns.internet.Ipv4GlobalRoutingHelper.PopulateRoutingTables() +ns.Ipv4GlobalRoutingHelper.PopulateRoutingTables() pointToPoint.EnablePcapAll("second") csma.EnablePcap("second", csmaDevices.Get(1), True) -ns.core.Simulator.Run() -ns.core.Simulator.Destroy() +ns.Simulator.Run() +ns.Simulator.Destroy() diff --git a/examples/tutorial/third.py b/examples/tutorial/third.py index fdc6b2133d..0bd70e0685 100644 --- a/examples/tutorial/third.py +++ b/examples/tutorial/third.py @@ -59,112 +59,108 @@ sys.exit(1) if verbose.value: - ns.core.LogComponentEnable("UdpEchoClientApplication", ns.core.LOG_LEVEL_INFO) - ns.core.LogComponentEnable("UdpEchoServerApplication", ns.core.LOG_LEVEL_INFO) + ns.LogComponentEnable("UdpEchoClientApplication", ns.LOG_LEVEL_INFO) + ns.LogComponentEnable("UdpEchoServerApplication", ns.LOG_LEVEL_INFO) -p2pNodes = ns.network.NodeContainer() +p2pNodes = ns.NodeContainer() p2pNodes.Create(2) -pointToPoint = ns.point_to_point.PointToPointHelper() -pointToPoint.SetDeviceAttribute("DataRate", ns.core.StringValue("5Mbps")) -pointToPoint.SetChannelAttribute("Delay", ns.core.StringValue("2ms")) +pointToPoint = ns.PointToPointHelper() +pointToPoint.SetDeviceAttribute("DataRate", ns.StringValue("5Mbps")) +pointToPoint.SetChannelAttribute("Delay", ns.StringValue("2ms")) p2pDevices = pointToPoint.Install(p2pNodes) -csmaNodes = ns.network.NodeContainer() +csmaNodes = ns.NodeContainer() csmaNodes.Add(p2pNodes.Get(1)) csmaNodes.Create(nCsma.value) -csma = ns.csma.CsmaHelper() -csma.SetChannelAttribute("DataRate", ns.core.StringValue("100Mbps")) -csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.NanoSeconds(6560))) +csma = ns.CsmaHelper() +csma.SetChannelAttribute("DataRate", ns.StringValue("100Mbps")) +csma.SetChannelAttribute("Delay", ns.TimeValue(ns.NanoSeconds(6560))) csmaDevices = csma.Install(csmaNodes) -wifiStaNodes = ns.network.NodeContainer() +wifiStaNodes = ns.NodeContainer() wifiStaNodes.Create(nWifi.value) wifiApNode = p2pNodes.Get(0) -channel = ns.wifi.YansWifiChannelHelper.Default() -phy = ns.wifi.YansWifiPhyHelper() +channel = ns.YansWifiChannelHelper.Default() +phy = ns.YansWifiPhyHelper() phy.SetChannel(channel.Create()) -mac = ns.wifi.WifiMacHelper() -ssid = ns.wifi.Ssid("ns-3-ssid") +mac = ns.WifiMacHelper() +ssid = ns.Ssid("ns-3-ssid") -wifi = ns.wifi.WifiHelper() +wifi = ns.WifiHelper() -mac.SetType( - "ns3::StaWifiMac", "Ssid", ns.wifi.SsidValue(ssid), "ActiveProbing", ns.core.BooleanValue(False) -) +mac.SetType("ns3::StaWifiMac", "Ssid", ns.SsidValue(ssid), "ActiveProbing", ns.BooleanValue(False)) staDevices = wifi.Install(phy, mac, wifiStaNodes) -mac.SetType("ns3::ApWifiMac", "Ssid", ns.wifi.SsidValue(ssid)) +mac.SetType("ns3::ApWifiMac", "Ssid", ns.SsidValue(ssid)) apDevices = wifi.Install(phy, mac, wifiApNode) -mobility = ns.mobility.MobilityHelper() +mobility = ns.MobilityHelper() mobility.SetPositionAllocator( "ns3::GridPositionAllocator", "MinX", - ns.core.DoubleValue(0.0), + ns.DoubleValue(0.0), "MinY", - ns.core.DoubleValue(0.0), + ns.DoubleValue(0.0), "DeltaX", - ns.core.DoubleValue(5.0), + ns.DoubleValue(5.0), "DeltaY", - ns.core.DoubleValue(10.0), + ns.DoubleValue(10.0), "GridWidth", - ns.core.UintegerValue(3), + ns.UintegerValue(3), "LayoutType", - ns.core.StringValue("RowFirst"), + ns.StringValue("RowFirst"), ) mobility.SetMobilityModel( "ns3::RandomWalk2dMobilityModel", "Bounds", - ns.mobility.RectangleValue(ns.mobility.Rectangle(-50, 50, -50, 50)), + ns.RectangleValue(ns.Rectangle(-50, 50, -50, 50)), ) mobility.Install(wifiStaNodes) mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel") mobility.Install(wifiApNode) -stack = ns.internet.InternetStackHelper() +stack = ns.InternetStackHelper() stack.Install(csmaNodes) stack.Install(wifiApNode) stack.Install(wifiStaNodes) -address = ns.internet.Ipv4AddressHelper() -address.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0")) +address = ns.Ipv4AddressHelper() +address.SetBase(ns.Ipv4Address("10.1.1.0"), ns.Ipv4Mask("255.255.255.0")) p2pInterfaces = address.Assign(p2pDevices) -address.SetBase(ns.network.Ipv4Address("10.1.2.0"), ns.network.Ipv4Mask("255.255.255.0")) +address.SetBase(ns.Ipv4Address("10.1.2.0"), ns.Ipv4Mask("255.255.255.0")) csmaInterfaces = address.Assign(csmaDevices) -address.SetBase(ns.network.Ipv4Address("10.1.3.0"), ns.network.Ipv4Mask("255.255.255.0")) +address.SetBase(ns.Ipv4Address("10.1.3.0"), ns.Ipv4Mask("255.255.255.0")) address.Assign(staDevices) address.Assign(apDevices) -echoServer = ns.applications.UdpEchoServerHelper(9) +echoServer = ns.UdpEchoServerHelper(9) serverApps = echoServer.Install(csmaNodes.Get(nCsma.value)) -serverApps.Start(ns.core.Seconds(1.0)) -serverApps.Stop(ns.core.Seconds(10.0)) +serverApps.Start(ns.Seconds(1.0)) +serverApps.Stop(ns.Seconds(10.0)) -echoClient = ns.applications.UdpEchoClientHelper( - csmaInterfaces.GetAddress(nCsma.value).ConvertTo(), 9 -) -echoClient.SetAttribute("MaxPackets", ns.core.UintegerValue(1)) -echoClient.SetAttribute("Interval", ns.core.TimeValue(ns.core.Seconds(1.0))) -echoClient.SetAttribute("PacketSize", ns.core.UintegerValue(1024)) +echoClient = ns.UdpEchoClientHelper(csmaInterfaces.GetAddress(nCsma.value).ConvertTo(), 9) +echoClient.SetAttribute("MaxPackets", ns.UintegerValue(1)) +echoClient.SetAttribute("Interval", ns.TimeValue(ns.Seconds(1.0))) +echoClient.SetAttribute("PacketSize", ns.UintegerValue(1024)) clientApps = echoClient.Install(wifiStaNodes.Get(nWifi.value - 1)) -clientApps.Start(ns.core.Seconds(2.0)) -clientApps.Stop(ns.core.Seconds(10.0)) +clientApps.Start(ns.Seconds(2.0)) +clientApps.Stop(ns.Seconds(10.0)) -ns.internet.Ipv4GlobalRoutingHelper.PopulateRoutingTables() +ns.Ipv4GlobalRoutingHelper.PopulateRoutingTables() -ns.core.Simulator.Stop(ns.core.Seconds(10.0)) +ns.Simulator.Stop(ns.Seconds(10.0)) if tracing.value: phy.SetPcapDataLinkType(phy.DLT_IEEE802_11_RADIO) @@ -172,5 +168,5 @@ phy.EnablePcap("third", apDevices.Get(0)) csma.EnablePcap("third", csmaDevices.Get(0), True) -ns.core.Simulator.Run() -ns.core.Simulator.Destroy() +ns.Simulator.Run() +ns.Simulator.Destroy() diff --git a/examples/tutorial/tutorial-app.cc b/examples/tutorial/tutorial-app.cc index 821cc0e9c1..70568dec78 100644 --- a/examples/tutorial/tutorial-app.cc +++ b/examples/tutorial/tutorial-app.cc @@ -76,7 +76,7 @@ TutorialApp::StopApplication() { m_running = false; - if (m_sendEvent.IsRunning()) + if (m_sendEvent.IsPending()) { Simulator::Cancel(m_sendEvent); } diff --git a/examples/wireless/examples-to-run.py b/examples/wireless/examples-to-run.py index dc9b766cca..1926ac4801 100755 --- a/examples/wireless/examples-to-run.py +++ b/examples/wireless/examples-to-run.py @@ -25,7 +25,7 @@ ("wifi-wired-bridging", "True", "True"), ("wifi-sleep", "True", "True"), ("wifi-blockack", "True", "True"), - ("wifi-timing-attributes --simulationTime=1", "True", "True"), + ("wifi-timing-attributes --simulationTime=1s", "True", "True"), ( "wifi-power-adaptation-distance --manager=ns3::ParfWifiManager --outputFileName=parf --steps=5 --stepsSize=10", "True", @@ -63,143 +63,143 @@ ("wifi-ofdm-vht-validation", "True", "True"), ("wifi-ofdm-he-validation", "True", "True"), ("wifi-error-models-comparison", "True", "True"), - ("wifi-80211n-mimo --simulationTime=0.1 --step=10", "True", "True"), + ("wifi-80211n-mimo --simulationTime=0.1s --step=10", "True", "True"), ( - "wifi-ht-network --simulationTime=0.2 --frequency=5 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=135", + "wifi-ht-network --simulationTime=0.2s --frequency=5 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=135", "True", "True", ), ( - "wifi-ht-network --simulationTime=0.2 --frequency=5 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=132", + "wifi-ht-network --simulationTime=0.2s --frequency=5 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=132", "True", "True", ), ( - "wifi-ht-network --simulationTime=0.2 --frequency=2.4 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=132", + "wifi-ht-network --simulationTime=0.2s --frequency=2.4 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=132", "True", "True", ), ( - "wifi-ht-network --simulationTime=0.2 --frequency=2.4 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=129", + "wifi-ht-network --simulationTime=0.2s --frequency=2.4 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=129", "True", "True", ), ( - "wifi-vht-network --simulationTime=0.2 --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=583", + "wifi-vht-network --simulationTime=0.2s --useRts=0 --minExpectedThroughput=5 --maxExpectedThroughput=620", "True", "True", ), ( - "wifi-vht-network --simulationTime=0.2 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=557", + "wifi-vht-network --simulationTime=0.2s --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=557", "True", "True", ), ( - "wifi-he-network --simulationTime=0.25 --frequency=5 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=844", + "wifi-he-network --simulationTime=0.25s --frequency=5 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=844", "True", "True", ), ( - "wifi-he-network --simulationTime=0.3 --frequency=5 --useRts=0 --useExtendedBlockAck=1 --minExpectedThroughput=6 --maxExpectedThroughput=1033", + "wifi-he-network --simulationTime=0.3s --frequency=5 --useRts=0 --useExtendedBlockAck=1 --minExpectedThroughput=6 --maxExpectedThroughput=1033", "True", "True", ), ( - "wifi-he-network --simulationTime=0.3 --frequency=5 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=745", + "wifi-he-network --simulationTime=0.3s --frequency=5 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=745", "True", "True", ), ( - "wifi-he-network --simulationTime=0.25 --frequency=2.4 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=238", + "wifi-he-network --simulationTime=0.25s --frequency=2.4 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=238", "True", "True", ), ( - "wifi-he-network --simulationTime=0.3 --frequency=2.4 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=223", + "wifi-he-network --simulationTime=0.3s --frequency=2.4 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=223", "True", "True", ), ( - "wifi-he-network --simulationTime=0.3 --udp=0 --downlink=1 --useRts=0 --nStations=4 --dlAckType=ACK-SU-FORMAT --enableUlOfdma=1 --enableBsrp=0 --mcs=4 --minExpectedThroughput=20 --maxExpectedThroughput=212", + "wifi-he-network --simulationTime=0.3s --udp=0 --downlink=1 --useRts=0 --nStations=4 --dlAckType=ACK-SU-FORMAT --enableUlOfdma=1 --enableBsrp=0 --mcs=4 --minExpectedThroughput=20 --maxExpectedThroughput=212", "True", "True", ), ( - "wifi-he-network --simulationTime=0.3 --frequency=2.4 --udp=0 --downlink=1 --useRts=1 --nStations=5 --dlAckType=MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mcs=5 --minExpectedThroughput=27 --maxExpectedThroughput=50", + "wifi-he-network --simulationTime=0.3s --frequency=2.4 --udp=0 --downlink=1 --useRts=1 --nStations=5 --dlAckType=MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mcs=5 --minExpectedThroughput=21 --maxExpectedThroughput=56", "True", "True", ), ( - "wifi-he-network --simulationTime=0.3 --udp=0 --downlink=1 --useRts=0 --nStations=5 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=0 --mcs=6 --muSchedAccessReqInterval=50ms --minExpectedThroughput=31 --maxExpectedThroughput=290", + "wifi-he-network --simulationTime=0.3s --udp=0 --downlink=1 --useRts=0 --nStations=5 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=0 --mcs=6 --muSchedAccessReqInterval=50ms --minExpectedThroughput=31 --maxExpectedThroughput=290", "True", "True", ), ( - "wifi-he-network --simulationTime=0.3 --udp=1 --downlink=0 --useRts=1 --nStations=5 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mcs=5 --muSchedAccessReqInterval=50ms --minExpectedThroughput=46 --maxExpectedThroughput=327", + "wifi-he-network --simulationTime=0.3s --udp=1 --downlink=0 --useRts=1 --nStations=5 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mcs=5 --muSchedAccessReqInterval=50ms --minExpectedThroughput=46 --maxExpectedThroughput=327", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.1 --frequency=5 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=550", + "wifi-eht-network --simulationTime=0.1s --frequency=5 --useRts=0 --minExpectedThroughput=6 --maxExpectedThroughput=760", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.1 --frequency=5 --useRts=0 --mpduBufferSize=1024 --frequency2=6 --minExpectedThroughput=12 --maxExpectedThroughput=550", + "wifi-eht-network --simulationTime=0.1s --frequency=5 --useRts=0 --mpduBufferSize=1024 --frequency2=6 --minExpectedThroughput=7 --maxExpectedThroughput=1444", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.1 --frequency=5 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=547", + "wifi-eht-network --simulationTime=0.1s --frequency=5 --useRts=1 --minExpectedThroughput=6 --maxExpectedThroughput=660", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.1 --frequency=2.4 --useRts=0 --mpduBufferSize=512 --frequency2=5 --minExpectedThroughput=12 --maxExpectedThroughput=500", + "wifi-eht-network --simulationTime=0.1s --frequency=2.4 --useRts=0 --mpduBufferSize=512 --frequency2=5 --minExpectedThroughput=7 --maxExpectedThroughput=512", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.1 --frequency=2.4 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=240", + "wifi-eht-network --simulationTime=0.1s --frequency=2.4 --useRts=1 --minExpectedThroughput=5 --maxExpectedThroughput=240", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.23 --udp=0 --downlink=1 --useRts=0 --nStations=4 --dlAckType=ACK-SU-FORMAT --enableUlOfdma=1 --enableBsrp=0 --mcs=5 --frequency2=6 --minExpectedThroughput=35 --maxExpectedThroughput=280", + "wifi-eht-network --simulationTime=0.23s --udp=0 --downlink=1 --useRts=0 --nStations=4 --dlAckType=ACK-SU-FORMAT --enableUlOfdma=1 --enableBsrp=0 --mcs=5 --frequency2=6 --minExpectedThroughput=35 --maxExpectedThroughput=404", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.25 --frequency=2.4 --udp=0 --downlink=1 --useRts=0 --nStations=5 --dlAckType=MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mcs=5 --frequency2=5 --mpduBufferSize=1024 --minExpectedThroughput=50 --maxExpectedThroughput=120", + "wifi-eht-network --simulationTime=0.25s --frequency=2.4 --udp=0 --downlink=1 --useRts=0 --nStations=5 --dlAckType=MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mcs=5 --frequency2=5 --mpduBufferSize=1024 --minExpectedThroughput=50 --maxExpectedThroughput=120", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.3 --udp=0 --downlink=1 --useRts=1 --nStations=5 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=0 --mcs=6 --muSchedAccessReqInterval=50ms --frequency2=2.4 --minExpectedThroughput=50 --maxExpectedThroughput=140", + "wifi-eht-network --simulationTime=0.3s --udp=0 --downlink=1 --useRts=1 --nStations=5 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=0 --mcs=6 --muSchedAccessReqInterval=50ms --frequency2=2.4 --minExpectedThroughput=50 --maxExpectedThroughput=140", "True", "True", ), ( - "wifi-eht-network --simulationTime=0.2 --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=4 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=50 --maxExpectedThroughput=415", + "wifi-eht-network --simulationTime=0.25s --udp=0 --downlink=0 --useRts=0 --nStations=4 --dlAckType=AGGR-MU-BAR --enableUlOfdma=1 --enableBsrp=1 --mpduBufferSize=1024 --mcs=7 --muSchedAccessReqInterval=45ms --frequency2=6 --minExpectedThroughput=70 --maxExpectedThroughput=550", "True", "True", ), ( - "wifi-simple-ht-hidden-stations --simulationTime=1 --enableRts=0 --nMpdus=32 --minExpectedThroughput=59 --maxExpectedThroughput=60", + "wifi-simple-ht-hidden-stations --simulationTime=1s --enableRts=0 --nMpdus=32 --minExpectedThroughput=59 --maxExpectedThroughput=60", "True", "True", ), ( - "wifi-simple-ht-hidden-stations --simulationTime=1 --enableRts=1 --nMpdus=32 --minExpectedThroughput=57 --maxExpectedThroughput=58", + "wifi-simple-ht-hidden-stations --simulationTime=1s --enableRts=1 --nMpdus=32 --minExpectedThroughput=57 --maxExpectedThroughput=58", "True", "True", ), - ("wifi-mixed-network --simulationTime=1", "True", "True"), - ("wifi-aggregation --simulationTime=1 --verifyResults=1", "True", "True"), - ("wifi-txop-aggregation --simulationTime=1 --verifyResults=1", "True", "True"), - ("wifi-80211e-txop --simulationTime=1 --verifyResults=1", "True", "True"), + ("wifi-mixed-network --simulationTime=1s", "True", "True"), + ("wifi-aggregation --simulationTime=1s --verifyResults=1", "True", "True"), + ("wifi-txop-aggregation --simulationTime=1s --verifyResults=1", "True", "True"), + ("wifi-80211e-txop --simulationTime=1s --verifyResults=1", "True", "True"), ( - "wifi-multi-tos --simulationTime=1 --nWifi=16 --useRts=1 --useShortGuardInterval=1", + "wifi-multi-tos --simulationTime=1s --nWifi=16 --useRts=1 --useShortGuardInterval=1", "True", "True", ), @@ -214,38 +214,38 @@ ("wifi-hidden-terminal --wifiManager=Rraa", "True", "True"), ("wifi-hidden-terminal --wifiManager=Rrpaa", "True", "True"), ( - "wifi-spectrum-per-example --distance=52 --index=3 --wifiType=ns3::SpectrumWifiPhy --simulationTime=1", + "wifi-spectrum-per-example --distance=52 --index=3 --wifiType=ns3::SpectrumWifiPhy --simulationTime=1s", "True", "True", ), ( - "wifi-spectrum-per-example --distance=24 --index=31 --wifiType=ns3::YansWifiPhy --simulationTime=1", + "wifi-spectrum-per-example --distance=24 --index=31 --wifiType=ns3::YansWifiPhy --simulationTime=1s", "True", "False", ), ( - "wifi-spectrum-per-interference --distance=24 --index=31 --simulationTime=1 --waveformPower=0.1", + "wifi-spectrum-per-interference --distance=24 --index=31 --simulationTime=1s --waveformPower=0.1", "True", "True", ), - ("wifi-spectrum-saturation-example --simulationTime=1 --index=63", "True", "True"), + ("wifi-spectrum-saturation-example --simulationTime=1s --index=63", "True", "True"), ( - "wifi-backward-compatibility --apVersion=80211a --staVersion=80211n_5GHZ --simulationTime=1", + "wifi-backward-compatibility --apVersion=80211a --staVersion=80211n_5GHZ --simulationTime=1s", "True", "True", ), ( - "wifi-backward-compatibility --apVersion=80211a --staVersion=80211n_5GHZ --apRaa=Ideal --staRaa=Ideal --simulationTime=1", + "wifi-backward-compatibility --apVersion=80211a --staVersion=80211n_5GHZ --apRaa=Ideal --staRaa=Ideal --simulationTime=1s", "True", "False", ), ( - "wifi-backward-compatibility --apVersion=80211a --staVersion=80211ac --simulationTime=1", + "wifi-backward-compatibility --apVersion=80211a --staVersion=80211ac --simulationTime=1s", "True", "False", ), ( - "wifi-backward-compatibility --apVersion=80211a --staVersion=80211ac --apRaa=Ideal --staRaa=Ideal --simulationTime=1", + "wifi-backward-compatibility --apVersion=80211a --staVersion=80211ac --apRaa=Ideal --staRaa=Ideal --simulationTime=1s", "True", "False", ), diff --git a/examples/wireless/mixed-wired-wireless.py b/examples/wireless/mixed-wired-wireless.py index d34f099c47..2132135b75 100644 --- a/examples/wireless/mixed-wired-wireless.py +++ b/examples/wireless/mixed-wired-wireless.py @@ -88,8 +88,8 @@ def main(argv): # Simulation defaults are typically set next, before command line # arguments are parsed. # - ns.core.Config.SetDefault("ns3::OnOffApplication::PacketSize", ns.core.StringValue("1472")) - ns.core.Config.SetDefault("ns3::OnOffApplication::DataRate", ns.core.StringValue("100kb/s")) + ns.Config.SetDefault("ns3::OnOffApplication::PacketSize", ns.StringValue("1472")) + ns.Config.SetDefault("ns3::OnOffApplication::DataRate", ns.StringValue("100kb/s")) # # For convenience, we add the local variables to the command line argument @@ -121,29 +121,29 @@ def main(argv): # Create a container to manage the nodes of the adhoc(backbone) network. # Later we'll create the rest of the nodes we'll need. # - backbone = ns.network.NodeContainer() + backbone = ns.NodeContainer() backbone.Create(backboneNodes.value) # # Create the backbone wifi net devices and install them into the nodes in # our container # - wifi = ns.wifi.WifiHelper() - mac = ns.wifi.WifiMacHelper() + wifi = ns.WifiHelper() + mac = ns.WifiMacHelper() mac.SetType("ns3::AdhocWifiMac") wifi.SetRemoteStationManager( - "ns3::ConstantRateWifiManager", "DataMode", ns.core.StringValue("OfdmRate54Mbps") + "ns3::ConstantRateWifiManager", "DataMode", ns.StringValue("OfdmRate54Mbps") ) - wifiPhy = ns.wifi.YansWifiPhyHelper() + wifiPhy = ns.YansWifiPhyHelper() wifiPhy.SetPcapDataLinkType(wifiPhy.DLT_IEEE802_11_RADIO) - wifiChannel = ns.wifi.YansWifiChannelHelper.Default() + wifiChannel = ns.YansWifiChannelHelper.Default() wifiPhy.SetChannel(wifiChannel.Create()) backboneDevices = wifi.Install(wifiPhy, mac, backbone) # # Add the IPv4 protocol stack to the nodes in our container # print("Enabling OLSR routing on all backbone nodes") - internet = ns.internet.InternetStackHelper() - olsr = ns.olsr.OlsrHelper() + internet = ns.InternetStackHelper() + olsr = ns.OlsrHelper() internet.SetRoutingHelper(olsr) # has effect on the next Install () internet.Install(backbone) @@ -153,38 +153,38 @@ def main(argv): # Assign IPv4 addresses to the device drivers(actually to the associated # IPv4 interfaces) we just created. # - ipAddrs = ns.internet.Ipv4AddressHelper() - ipAddrs.SetBase(ns.network.Ipv4Address("192.168.0.0"), ns.network.Ipv4Mask("255.255.255.0")) + ipAddrs = ns.Ipv4AddressHelper() + ipAddrs.SetBase(ns.Ipv4Address("192.168.0.0"), ns.Ipv4Mask("255.255.255.0")) ipAddrs.Assign(backboneDevices) # # The ad-hoc network nodes need a mobility model so we aggregate one to # each of the nodes we just finished building. # - mobility = ns.mobility.MobilityHelper() + mobility = ns.MobilityHelper() mobility.SetPositionAllocator( "ns3::GridPositionAllocator", "MinX", - ns.core.DoubleValue(20.0), + ns.DoubleValue(20.0), "MinY", - ns.core.DoubleValue(20.0), + ns.DoubleValue(20.0), "DeltaX", - ns.core.DoubleValue(20.0), + ns.DoubleValue(20.0), "DeltaY", - ns.core.DoubleValue(20.0), + ns.DoubleValue(20.0), "GridWidth", - ns.core.UintegerValue(5), + ns.UintegerValue(5), "LayoutType", - ns.core.StringValue("RowFirst"), + ns.StringValue("RowFirst"), ) mobility.SetMobilityModel( "ns3::RandomDirection2dMobilityModel", "Bounds", - ns.mobility.RectangleValue(ns.mobility.Rectangle(-500, 500, -500, 500)), + ns.RectangleValue(ns.Rectangle(-500, 500, -500, 500)), "Speed", - ns.core.StringValue("ns3::ConstantRandomVariable[Constant=2]"), + ns.StringValue("ns3::ConstantRandomVariable[Constant=2]"), "Pause", - ns.core.StringValue("ns3::ConstantRandomVariable[Constant=0.2]"), + ns.StringValue("ns3::ConstantRandomVariable[Constant=0.2]"), ) mobility.Install(backbone) @@ -196,7 +196,7 @@ def main(argv): # Reset the address base-- all of the CSMA networks will be in # the "172.16 address space - ipAddrs.SetBase(ns.network.Ipv4Address("172.16.0.0"), ns.network.Ipv4Mask("255.255.255.0")) + ipAddrs.SetBase(ns.Ipv4Address("172.16.0.0"), ns.Ipv4Mask("255.255.255.0")) for i in range(backboneNodes.value): print("Configuring local area network for backbone node ", i) @@ -205,17 +205,17 @@ def main(argv): # two containers here; one with all of the new nodes, and one # with all of the nodes including new and existing nodes # - newLanNodes = ns.network.NodeContainer() + newLanNodes = ns.NodeContainer() newLanNodes.Create(lanNodes.value - 1) # Now, create the container with all nodes on this link - lan = ns.network.NodeContainer(ns.network.NodeContainer(backbone.Get(i)), newLanNodes) + lan = ns.NodeContainer(ns.NodeContainer(backbone.Get(i)), newLanNodes) # # Create the CSMA net devices and install them into the nodes in our # collection. # - csma = ns.csma.CsmaHelper() - csma.SetChannelAttribute("DataRate", ns.network.DataRateValue(ns.network.DataRate(5000000))) - csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.MilliSeconds(2))) + csma = ns.CsmaHelper() + csma.SetChannelAttribute("DataRate", ns.DataRateValue(ns.DataRate(5000000))) + csma.SetChannelAttribute("Delay", ns.TimeValue(ns.MilliSeconds(2))) lanDevices = csma.Install(lan) # # Add the IPv4 protocol stack to the new LAN nodes @@ -235,10 +235,10 @@ def main(argv): # The new LAN nodes need a mobility model so we aggregate one # to each of the nodes we just finished building. # - mobilityLan = ns.mobility.MobilityHelper() - positionAlloc = ns.mobility.ListPositionAllocator() + mobilityLan = ns.MobilityHelper() + positionAlloc = ns.ListPositionAllocator() for j in range(newLanNodes.GetN()): - positionAlloc.Add(ns.core.Vector(0.0, (j * 10 + 10), 0.0)) + positionAlloc.Add(ns.Vector(0.0, (j * 10 + 10), 0.0)) mobilityLan.SetPositionAllocator(positionAlloc) mobilityLan.PushReferenceMobilityModel(backbone.Get(i)) @@ -253,7 +253,7 @@ def main(argv): # Reset the address base-- all of the 802.11 networks will be in # the "10.0" address space - ipAddrs.SetBase(ns.network.Ipv4Address("10.0.0.0"), ns.network.Ipv4Mask("255.255.255.0")) + ipAddrs.SetBase(ns.Ipv4Address("10.0.0.0"), ns.Ipv4Mask("255.255.255.0")) tempRef = [] # list of references to be held to prevent garbage collection for i in range(backboneNodes.value): print("Configuring wireless network for backbone node ", i) @@ -262,26 +262,26 @@ def main(argv): # two containers here; one with all of the new nodes, and one # with all of the nodes including new and existing nodes # - stas = ns.network.NodeContainer() + stas = ns.NodeContainer() stas.Create(infraNodes.value - 1) # Now, create the container with all nodes on this link - infra = ns.network.NodeContainer(ns.network.NodeContainer(backbone.Get(i)), stas) + infra = ns.NodeContainer(ns.NodeContainer(backbone.Get(i)), stas) # # Create another ad hoc network and devices # - ssid = ns.wifi.Ssid("wifi-infra" + str(i)) - wifiInfra = ns.wifi.WifiHelper() + ssid = ns.Ssid("wifi-infra" + str(i)) + wifiInfra = ns.WifiHelper() wifiPhy.SetChannel(wifiChannel.Create()) - macInfra = ns.wifi.WifiMacHelper() - macInfra.SetType("ns3::StaWifiMac", "Ssid", ns.wifi.SsidValue(ssid)) + macInfra = ns.WifiMacHelper() + macInfra.SetType("ns3::StaWifiMac", "Ssid", ns.SsidValue(ssid)) # setup stas staDevices = wifiInfra.Install(wifiPhy, macInfra, stas) # setup ap. - macInfra.SetType("ns3::ApWifiMac", "Ssid", ns.wifi.SsidValue(ssid)) + macInfra.SetType("ns3::ApWifiMac", "Ssid", ns.SsidValue(ssid)) apDevices = wifiInfra.Install(wifiPhy, macInfra, backbone.Get(i)) # Collect all of these new devices - infraDevices = ns.network.NetDeviceContainer(apDevices, staDevices) + infraDevices = ns.NetDeviceContainer(apDevices, staDevices) # Add the IPv4 protocol stack to the nodes in our container # @@ -299,7 +299,7 @@ def main(argv): # This call returns an instance that needs to be stored in the outer scope # not to be garbage collected when overwritten in the next iteration - subnetAlloc = ns.mobility.ListPositionAllocator() + subnetAlloc = ns.ListPositionAllocator() # Appending the object to a list is enough to prevent the garbage collection tempRef.append(subnetAlloc) @@ -309,18 +309,18 @@ def main(argv): # to each of the nodes we just finished building. # for j in range(infra.GetN()): - subnetAlloc.Add(ns.core.Vector(0.0, j, 0.0)) + subnetAlloc.Add(ns.Vector(0.0, j, 0.0)) mobility.PushReferenceMobilityModel(backbone.Get(i)) mobility.SetPositionAllocator(subnetAlloc) mobility.SetMobilityModel( "ns3::RandomDirection2dMobilityModel", "Bounds", - ns.mobility.RectangleValue(ns.mobility.Rectangle(-10, 10, -10, 10)), + ns.RectangleValue(ns.Rectangle(-10, 10, -10, 10)), "Speed", - ns.core.StringValue("ns3::ConstantRandomVariable[Constant=3]"), + ns.StringValue("ns3::ConstantRandomVariable[Constant=3]"), "Pause", - ns.core.StringValue("ns3::ConstantRandomVariable[Constant=0.4]"), + ns.StringValue("ns3::ConstantRandomVariable[Constant=0.4]"), ) mobility.Install(stas) @@ -335,14 +335,14 @@ def main(argv): print("Create Applications.") port = 9 # Discard port(RFC 863) - appSource = ns.network.NodeList.GetNode(backboneNodes.value) + appSource = ns.NodeList.GetNode(backboneNodes.value) lastNodeIndex = ( backboneNodes.value + backboneNodes.value * (lanNodes.value - 1) + backboneNodes.value * (infraNodes.value - 1) - 1 ) - appSink = ns.network.NodeList.GetNode(lastNodeIndex) + appSink = ns.NodeList.GetNode(lastNodeIndex) ns.cppyy.cppdef( """ @@ -353,22 +353,20 @@ def main(argv): ) # Let's fetch the IP address of the last node, which is on Ipv4Interface 1 remoteAddr = ns.cppyy.gbl.getIpv4AddressFromNode(appSink) - socketAddr = ns.network.InetSocketAddress(remoteAddr, port) - onoff = ns.applications.OnOffHelper("ns3::UdpSocketFactory", socketAddr.ConvertTo()) - apps = onoff.Install(ns.network.NodeContainer(appSource)) - apps.Start(ns.core.Seconds(3)) - apps.Stop(ns.core.Seconds(stopTime.value - 1)) + socketAddr = ns.InetSocketAddress(remoteAddr, port) + onoff = ns.OnOffHelper("ns3::UdpSocketFactory", socketAddr.ConvertTo()) + apps = onoff.Install(ns.NodeContainer(appSource)) + apps.Start(ns.Seconds(3)) + apps.Stop(ns.Seconds(stopTime.value - 1)) # Create a packet sink to receive these packets - sink = ns.applications.PacketSinkHelper( + sink = ns.PacketSinkHelper( "ns3::UdpSocketFactory", - ns.network.InetSocketAddress( - ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), port) - ).ConvertTo(), + ns.InetSocketAddress(ns.InetSocketAddress(ns.Ipv4Address.GetAny(), port)).ConvertTo(), ) - sinkContainer = ns.network.NodeContainer(appSink) + sinkContainer = ns.NodeContainer(appSink) apps = sink.Install(sinkContainer) - apps.Start(ns.core.Seconds(3)) + apps.Start(ns.Seconds(3)) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # / # # @@ -377,11 +375,11 @@ def main(argv): # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # / print("Configure Tracing.") - csma = ns.csma.CsmaHelper() + csma = ns.CsmaHelper() # # Let's set up some ns-2-like ascii traces, using another helper class # - ascii = ns.network.AsciiTraceHelper() + ascii = ns.AsciiTraceHelper() stream = ascii.CreateFileStream("mixed-wireless.tr") wifiPhy.EnableAsciiAll(stream) csma.EnableAsciiAll(stream) @@ -405,9 +403,9 @@ def main(argv): # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # print("Run Simulation.") - ns.core.Simulator.Stop(ns.core.Seconds(stopTime.value)) - ns.core.Simulator.Run() - ns.core.Simulator.Destroy() + ns.Simulator.Stop(ns.Seconds(stopTime.value)) + ns.Simulator.Run() + ns.Simulator.Destroy() if __name__ == "__main__": diff --git a/examples/wireless/wifi-80211e-txop.cc b/examples/wireless/wifi-80211e-txop.cc index 9ebbd7486a..67d8dee65a 100644 --- a/examples/wireless/wifi-80211e-txop.cc +++ b/examples/wireless/wifi-80211e-txop.cc @@ -55,7 +55,7 @@ // // The user can select the distance between the stations and the APs, can enable/disable the RTS/CTS // mechanism and can choose the payload size and the simulation duration. Example: ./ns3 run -// "wifi-80211e-txop --distance=10 --simulationTime=20 --payloadSize=1000" +// "wifi-80211e-txop --distance=10 --simulationTime=20s --payloadSize=1000" // // The output prints the throughput measured for the 4 cases/networks described above. When TXOP is // enabled, results show increased throughput since the channel is granted for a longer duration. @@ -94,16 +94,16 @@ TxopDurationTracer::Trace(Time startTime, Time duration, uint8_t linkId) int main(int argc, char* argv[]) { - uint32_t payloadSize = 1472; // bytes - double simulationTime = 10; // seconds - double distance = 5; // meters - bool enablePcap = false; - bool verifyResults = false; // used for regression - Time txopLimit = MicroSeconds(4096); + uint32_t payloadSize{1472}; // bytes + Time simulationTime{"10s"}; + double distance{5}; // meters + bool enablePcap{false}; + bool verifyResults{false}; // used for regression + Time txopLimit{"4096us"}; CommandLine cmd(__FILE__); cmd.AddValue("payloadSize", "Payload size in bytes", payloadSize); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("distance", "Distance in meters between the station and the access point", distance); @@ -296,74 +296,74 @@ main(int argc, char* argv[]) UdpServerHelper serverA(port); ApplicationContainer serverAppA = serverA.Install(wifiApNodes.Get(0)); serverAppA.Start(Seconds(0.0)); - serverAppA.Stop(Seconds(simulationTime + 1)); + serverAppA.Stop(simulationTime + Seconds(1.0)); InetSocketAddress destA(ApInterfaceA.GetAddress(0), port); - destA.SetTos(0x70); // AC_BE OnOffHelper clientA("ns3::UdpSocketFactory", destA); clientA.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); clientA.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); clientA.SetAttribute("DataRate", StringValue("100000kb/s")); clientA.SetAttribute("PacketSize", UintegerValue(payloadSize)); + clientA.SetAttribute("Tos", UintegerValue(0x70)); // AC_BE ApplicationContainer clientAppA = clientA.Install(wifiStaNodes.Get(0)); clientAppA.Start(Seconds(1.0)); - clientAppA.Stop(Seconds(simulationTime + 1)); + clientAppA.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverB(port); ApplicationContainer serverAppB = serverB.Install(wifiApNodes.Get(1)); serverAppB.Start(Seconds(0.0)); - serverAppB.Stop(Seconds(simulationTime + 1)); + serverAppB.Stop(simulationTime + Seconds(1.0)); InetSocketAddress destB(ApInterfaceB.GetAddress(0), port); - destB.SetTos(0x70); // AC_BE OnOffHelper clientB("ns3::UdpSocketFactory", destB); clientB.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); clientB.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); clientB.SetAttribute("DataRate", StringValue("100000kb/s")); clientB.SetAttribute("PacketSize", UintegerValue(payloadSize)); + clientB.SetAttribute("Tos", UintegerValue(0x70)); // AC_BE ApplicationContainer clientAppB = clientB.Install(wifiStaNodes.Get(1)); clientAppB.Start(Seconds(1.0)); - clientAppB.Stop(Seconds(simulationTime + 1)); + clientAppB.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverC(port); ApplicationContainer serverAppC = serverC.Install(wifiApNodes.Get(2)); serverAppC.Start(Seconds(0.0)); - serverAppC.Stop(Seconds(simulationTime + 1)); + serverAppC.Stop(simulationTime + Seconds(1.0)); InetSocketAddress destC(ApInterfaceC.GetAddress(0), port); - destC.SetTos(0xb8); // AC_VI OnOffHelper clientC("ns3::UdpSocketFactory", destC); clientC.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); clientC.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); clientC.SetAttribute("DataRate", StringValue("100000kb/s")); clientC.SetAttribute("PacketSize", UintegerValue(payloadSize)); + clientC.SetAttribute("Tos", UintegerValue(0xb8)); // AC_VI ApplicationContainer clientAppC = clientC.Install(wifiStaNodes.Get(2)); clientAppC.Start(Seconds(1.0)); - clientAppC.Stop(Seconds(simulationTime + 1)); + clientAppC.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverD(port); ApplicationContainer serverAppD = serverD.Install(wifiApNodes.Get(3)); serverAppD.Start(Seconds(0.0)); - serverAppD.Stop(Seconds(simulationTime + 1)); + serverAppD.Stop(simulationTime + Seconds(1.0)); InetSocketAddress destD(ApInterfaceD.GetAddress(0), port); - destD.SetTos(0xb8); // AC_VI OnOffHelper clientD("ns3::UdpSocketFactory", destD); clientD.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); clientD.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); clientD.SetAttribute("DataRate", StringValue("100000kb/s")); clientD.SetAttribute("PacketSize", UintegerValue(payloadSize)); + clientD.SetAttribute("Tos", UintegerValue(0xb8)); // AC_VI ApplicationContainer clientAppD = clientD.Install(wifiStaNodes.Get(3)); clientAppD.Start(Seconds(1.0)); - clientAppD.Stop(Seconds(simulationTime + 1)); + clientAppD.Stop(simulationTime + Seconds(1.0)); if (enablePcap) { @@ -377,18 +377,18 @@ main(int argc, char* argv[]) phy.EnablePcap("STA_D", staDeviceD.Get(0)); } - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); /* Show results */ - uint64_t totalPacketsThroughA = DynamicCast(serverAppA.Get(0))->GetReceived(); - uint64_t totalPacketsThroughB = DynamicCast(serverAppB.Get(0))->GetReceived(); - uint64_t totalPacketsThroughC = DynamicCast(serverAppC.Get(0))->GetReceived(); - uint64_t totalPacketsThroughD = DynamicCast(serverAppD.Get(0))->GetReceived(); + double totalPacketsThroughA = DynamicCast(serverAppA.Get(0))->GetReceived(); + double totalPacketsThroughB = DynamicCast(serverAppB.Get(0))->GetReceived(); + double totalPacketsThroughC = DynamicCast(serverAppC.Get(0))->GetReceived(); + double totalPacketsThroughD = DynamicCast(serverAppD.Get(0))->GetReceived(); Simulator::Destroy(); - double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0); + auto throughput = totalPacketsThroughA * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "AC_BE with default TXOP limit (0ms): " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 28 || throughput > 29)) @@ -397,7 +397,7 @@ main(int argc, char* argv[]) exit(1); } - throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughB * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "AC_BE with non-default TXOP limit (4.096ms): " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 36.5 || throughput > 37)) @@ -415,7 +415,7 @@ main(int argc, char* argv[]) exit(1); } - throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughC * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "AC_VI with default TXOP limit (4.096ms): " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 36.5 || throughput > 37.5)) @@ -433,7 +433,7 @@ main(int argc, char* argv[]) exit(1); } - throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughD * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "AC_VI with non-default TXOP limit (0ms): " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 31.5 || throughput > 32.5)) diff --git a/examples/wireless/wifi-80211n-mimo.cc b/examples/wireless/wifi-80211n-mimo.cc index b6e7f1ef34..549f696e7a 100644 --- a/examples/wireless/wifi-80211n-mimo.cc +++ b/examples/wireless/wifi-80211n-mimo.cc @@ -41,6 +41,7 @@ #include "ns3/config.h" #include "ns3/double.h" #include "ns3/gnuplot.h" +#include "ns3/ht-phy.h" #include "ns3/internet-stack-helper.h" #include "ns3/ipv4-address-helper.h" #include "ns3/ipv4-global-routing-helper.h" @@ -70,17 +71,17 @@ main(int argc, char* argv[]) "HtMcs24", "HtMcs25", "HtMcs26", "HtMcs27", "HtMcs28", "HtMcs29", "HtMcs30", "HtMcs31", }; - bool udp = true; - double simulationTime = 5; // seconds - double frequency = 5.0; // whether 2.4 or 5.0 GHz - double step = 5; // meters - bool shortGuardInterval = false; - bool channelBonding = false; - bool preambleDetection = true; + bool udp{true}; + Time simulationTime{"5s"}; + double frequency{5.0}; // whether 2.4 or 5.0 GHz + double step{5}; // meters + bool shortGuardInterval{false}; + bool channelBonding{false}; + bool preambleDetection{true}; CommandLine cmd(__FILE__); cmd.AddValue("step", "Granularity of the results to be plotted in meters", step); - cmd.AddValue("simulationTime", "Simulation time per step (in seconds)", simulationTime); + cmd.AddValue("simulationTime", "Simulation time per step", simulationTime); cmd.AddValue("channelBonding", "Enable/disable channel bonding (channel width = 20 MHz if false, channel width = " "40 MHz if true)", @@ -213,6 +214,10 @@ main(int argc, char* argv[]) apNodeInterface = address.Assign(apDevice); /* Setting applications */ + const auto maxLoad = HtPhy::GetDataRate(i, + channelBonding ? 40 : 20, + shortGuardInterval ? 400 : 800, + nStreams); ApplicationContainer serverApp; if (udp) { @@ -221,15 +226,16 @@ main(int argc, char* argv[]) UdpServerHelper server(port); serverApp = server.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / maxLoad; UdpClientHelper client(staNodeInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.00001"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } else { @@ -239,7 +245,7 @@ main(int argc, char* argv[]) PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress); serverApp = packetSinkHelper.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny()); onoff.SetAttribute("OnTime", @@ -247,34 +253,34 @@ main(int argc, char* argv[]) onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("PacketSize", UintegerValue(payloadSize)); - onoff.SetAttribute("DataRate", DataRateValue(1000000000)); // bit/s + onoff.SetAttribute("DataRate", DataRateValue(maxLoad)); AddressValue remoteAddress(InetSocketAddress(staNodeInterface.GetAddress(0), port)); onoff.SetAttribute("Remote", remoteAddress); ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); double throughput = 0; if (udp) { // UDP - uint64_t totalPacketsThrough = + double totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); - throughput = - totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); // Mbit/s + throughput = totalPacketsThrough * payloadSize * 8 / + simulationTime.GetMicroSeconds(); // Mbit/s } else { // TCP - uint64_t totalPacketsThrough = + double totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetTotalRx(); - throughput = totalPacketsThrough * 8 / (simulationTime * 1000000.0); // Mbit/s + throughput = totalPacketsThrough * 8 / simulationTime.GetMicroSeconds(); // Mbit/s } dataset.Add(d, throughput); std::cout << throughput << " Mbit/s" << std::endl; diff --git a/examples/wireless/wifi-aggregation.cc b/examples/wireless/wifi-aggregation.cc index 9189051ff6..69ad3b452e 100644 --- a/examples/wireless/wifi-aggregation.cc +++ b/examples/wireless/wifi-aggregation.cc @@ -59,7 +59,7 @@ // // The user can select the distance between the stations and the APs and can enable/disable the // RTS/CTS mechanism. Example: ./ns3 run "wifi-aggregation --distance=10 --enableRts=0 -// --simulationTime=20" +// --simulationTime=20s" // // The output prints the throughput measured for the 4 cases/networks described above. When default // aggregation parameters are enabled, the maximum A-MPDU size is 65 kB and the throughput is @@ -82,17 +82,17 @@ NS_LOG_COMPONENT_DEFINE("SimpleMpduAggregation"); int main(int argc, char* argv[]) { - uint32_t payloadSize = 1472; // bytes - double simulationTime = 10; // seconds - double distance = 5; // meters - bool enableRts = false; - bool enablePcap = false; - bool verifyResults = false; // used for regression + uint32_t payloadSize{1472}; // bytes + Time simulationTime{"10s"}; + double distance{5}; // meters + bool enableRts{false}; + bool enablePcap{false}; + bool verifyResults{false}; // used for regression CommandLine cmd(__FILE__); cmd.AddValue("payloadSize", "Payload size in bytes", payloadSize); cmd.AddValue("enableRts", "Enable or disable RTS/CTS", enableRts); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("distance", "Distance in meters between the station and the access point", distance); @@ -282,7 +282,7 @@ main(int argc, char* argv[]) UdpServerHelper serverA(port); ApplicationContainer serverAppA = serverA.Install(wifiStaNodes.Get(0)); serverAppA.Start(Seconds(0.0)); - serverAppA.Stop(Seconds(simulationTime + 1)); + serverAppA.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientA(StaInterfaceA.GetAddress(0), port); clientA.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -291,12 +291,12 @@ main(int argc, char* argv[]) ApplicationContainer clientAppA = clientA.Install(wifiApNodes.Get(0)); clientAppA.Start(Seconds(1.0)); - clientAppA.Stop(Seconds(simulationTime + 1)); + clientAppA.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverB(port); ApplicationContainer serverAppB = serverB.Install(wifiStaNodes.Get(1)); serverAppB.Start(Seconds(0.0)); - serverAppB.Stop(Seconds(simulationTime + 1)); + serverAppB.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientB(StaInterfaceB.GetAddress(0), port); clientB.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -305,12 +305,12 @@ main(int argc, char* argv[]) ApplicationContainer clientAppB = clientB.Install(wifiApNodes.Get(1)); clientAppB.Start(Seconds(1.0)); - clientAppB.Stop(Seconds(simulationTime + 1)); + clientAppB.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverC(port); ApplicationContainer serverAppC = serverC.Install(wifiStaNodes.Get(2)); serverAppC.Start(Seconds(0.0)); - serverAppC.Stop(Seconds(simulationTime + 1)); + serverAppC.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientC(StaInterfaceC.GetAddress(0), port); clientC.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -319,12 +319,12 @@ main(int argc, char* argv[]) ApplicationContainer clientAppC = clientC.Install(wifiApNodes.Get(2)); clientAppC.Start(Seconds(1.0)); - clientAppC.Stop(Seconds(simulationTime + 1)); + clientAppC.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverD(port); ApplicationContainer serverAppD = serverD.Install(wifiStaNodes.Get(3)); serverAppD.Start(Seconds(0.0)); - serverAppD.Stop(Seconds(simulationTime + 1)); + serverAppD.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientD(StaInterfaceD.GetAddress(0), port); clientD.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -333,7 +333,7 @@ main(int argc, char* argv[]) ApplicationContainer clientAppD = clientD.Install(wifiApNodes.Get(3)); clientAppD.Start(Seconds(1.0)); - clientAppD.Stop(Seconds(simulationTime + 1)); + clientAppD.Stop(simulationTime + Seconds(1.0)); if (enablePcap) { @@ -347,18 +347,18 @@ main(int argc, char* argv[]) phy.EnablePcap("STA_D", staDeviceD.Get(0)); } - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); // Show results - uint64_t totalPacketsThroughA = DynamicCast(serverAppA.Get(0))->GetReceived(); - uint64_t totalPacketsThroughB = DynamicCast(serverAppB.Get(0))->GetReceived(); - uint64_t totalPacketsThroughC = DynamicCast(serverAppC.Get(0))->GetReceived(); - uint64_t totalPacketsThroughD = DynamicCast(serverAppD.Get(0))->GetReceived(); + double totalPacketsThroughA = DynamicCast(serverAppA.Get(0))->GetReceived(); + double totalPacketsThroughB = DynamicCast(serverAppB.Get(0))->GetReceived(); + double totalPacketsThroughC = DynamicCast(serverAppC.Get(0))->GetReceived(); + double totalPacketsThroughD = DynamicCast(serverAppD.Get(0))->GetReceived(); Simulator::Destroy(); - double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0); + auto throughput = totalPacketsThroughA * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "Throughput with default configuration (A-MPDU aggregation enabled, 65kB): " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 59.0 || throughput > 60.0)) @@ -367,7 +367,7 @@ main(int argc, char* argv[]) exit(1); } - throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughB * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "Throughput with aggregation disabled: " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 30 || throughput > 31)) { @@ -375,7 +375,7 @@ main(int argc, char* argv[]) exit(1); } - throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughC * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "Throughput with A-MPDU disabled and A-MSDU enabled (8kB): " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 51 || throughput > 52)) @@ -384,7 +384,7 @@ main(int argc, char* argv[]) exit(1); } - throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughD * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "Throughput with A-MPDU enabled (32kB) and A-MSDU enabled (4kB): " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 58 || throughput > 59)) diff --git a/examples/wireless/wifi-ap.py b/examples/wireless/wifi-ap.py index 464d9dfe52..e97f0ff9a7 100644 --- a/examples/wireless/wifi-ap.py +++ b/examples/wireless/wifi-ap.py @@ -93,16 +93,16 @@ def main(argv): - ns.core.CommandLine().Parse(argv) + ns.CommandLine().Parse(argv) - ns.network.Packet.EnablePrinting() + ns.Packet.EnablePrinting() - wifi = ns.wifi.WifiHelper() - mobility = ns.mobility.MobilityHelper() - stas = ns.network.NodeContainer() - ap = ns.network.NodeContainer() + wifi = ns.WifiHelper() + mobility = ns.MobilityHelper() + stas = ns.NodeContainer() + ap = ns.NodeContainer() # NetDeviceContainer staDevs; - packetSocket = ns.network.PacketSocketHelper() + packetSocket = ns.PacketSocketHelper() stas.Create(2) ap.Create(1) @@ -111,45 +111,45 @@ def main(argv): packetSocket.Install(stas) packetSocket.Install(ap) - wifiPhy = ns.wifi.YansWifiPhyHelper() - wifiChannel = ns.wifi.YansWifiChannelHelper.Default() + wifiPhy = ns.YansWifiPhyHelper() + wifiChannel = ns.YansWifiChannelHelper.Default() wifiPhy.SetChannel(wifiChannel.Create()) - ssid = ns.wifi.Ssid("wifi-default") - wifiMac = ns.wifi.WifiMacHelper() + ssid = ns.Ssid("wifi-default") + wifiMac = ns.WifiMacHelper() # setup stas. wifiMac.SetType( "ns3::StaWifiMac", "ActiveProbing", - ns.core.BooleanValue(True), + ns.BooleanValue(True), "Ssid", - ns.wifi.SsidValue(ssid), + ns.SsidValue(ssid), ) staDevs = wifi.Install(wifiPhy, wifiMac, stas) # setup ap. - wifiMac.SetType("ns3::ApWifiMac", "Ssid", ns.wifi.SsidValue(ssid)) + wifiMac.SetType("ns3::ApWifiMac", "Ssid", ns.SsidValue(ssid)) wifi.Install(wifiPhy, wifiMac, ap) # mobility. mobility.Install(stas) mobility.Install(ap) - ns.core.Simulator.Schedule(ns.core.Seconds(1.0), ns.cppyy.gbl.AdvancePosition, ap.Get(0)) + ns.Simulator.Schedule(ns.Seconds(1.0), ns.cppyy.gbl.AdvancePosition, ap.Get(0)) - socket = ns.network.PacketSocketAddress() + socket = ns.PacketSocketAddress() socket.SetSingleDevice(staDevs.Get(0).GetIfIndex()) socket.SetPhysicalAddress(staDevs.Get(1).GetAddress()) socket.SetProtocol(1) - onoff = ns.applications.OnOffHelper("ns3::PacketSocketFactory", socket.ConvertTo()) - onoff.SetConstantRate(ns.network.DataRate("500kb/s")) + onoff = ns.OnOffHelper("ns3::PacketSocketFactory", socket.ConvertTo()) + onoff.SetConstantRate(ns.DataRate("500kb/s")) - apps = onoff.Install(ns.network.NodeContainer(stas.Get(0))) - apps.Start(ns.core.Seconds(0.5)) - apps.Stop(ns.core.Seconds(43.0)) + apps = onoff.Install(ns.NodeContainer(stas.Get(0))) + apps.Start(ns.Seconds(0.5)) + apps.Stop(ns.Seconds(43.0)) - ns.core.Simulator.Stop(ns.core.Seconds(44.0)) + ns.Simulator.Stop(ns.Seconds(44.0)) # Config::Connect("/NodeList/*/DeviceList/*/Tx", MakeCallback(&DevTxTrace)); # Config::Connect("/NodeList/*/DeviceList/*/Rx", MakeCallback(&DevRxTrace)); @@ -158,8 +158,8 @@ def main(argv): # Config::Connect("/NodeList/*/DeviceList/*/Phy/Tx", MakeCallback(&PhyTxTrace)); # Config::Connect("/NodeList/*/DeviceList/*/Phy/State", MakeCallback(&PhyStateTrace)); - ns.core.Simulator.Run() - ns.core.Simulator.Destroy() + ns.Simulator.Run() + ns.Simulator.Destroy() return 0 diff --git a/examples/wireless/wifi-backward-compatibility.cc b/examples/wireless/wifi-backward-compatibility.cc index 07db57e235..e90e55cead 100644 --- a/examples/wireless/wifi-backward-compatibility.cc +++ b/examples/wireless/wifi-backward-compatibility.cc @@ -113,17 +113,17 @@ ConvertStringToStandardAndBand(std::string version) int main(int argc, char* argv[]) { - uint32_t payloadSize = 1472; // bytes - double simulationTime = 10; // seconds - std::string apVersion = "80211a"; - std::string staVersion = "80211n_5GHZ"; - std::string apRaa = "Minstrel"; - std::string staRaa = "MinstrelHt"; - bool apHasTraffic = false; - bool staHasTraffic = true; + uint32_t payloadSize{1472}; // bytes + Time simulationTime{"10s"}; + std::string apVersion{"80211a"}; + std::string staVersion{"80211n_5GHZ"}; + std::string apRaa{"Minstrel"}; + std::string staRaa{"MinstrelHt"}; + bool apHasTraffic{false}; + bool staHasTraffic{true}; CommandLine cmd(__FILE__); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("apVersion", "The standard version used by the AP: 80211a, 80211b, 80211g, 80211p, " "80211n_2_4GHZ, 80211n_5GHZ, 80211ac, 80211ax_2_4GHZ or 80211ax_5GHZ", @@ -204,12 +204,12 @@ main(int argc, char* argv[]) UdpServerHelper apServer(9); ApplicationContainer apServerApp = apServer.Install(wifiApNode.Get(0)); apServerApp.Start(Seconds(0.0)); - apServerApp.Stop(Seconds(simulationTime + 1)); + apServerApp.Stop(simulationTime + Seconds(1.0)); UdpServerHelper staServer(5001); ApplicationContainer staServerApp = staServer.Install(wifiStaNode.Get(0)); staServerApp.Start(Seconds(0.0)); - staServerApp.Stop(Seconds(simulationTime + 1)); + staServerApp.Stop(simulationTime + Seconds(1.0)); if (apHasTraffic) { @@ -219,7 +219,7 @@ main(int argc, char* argv[]) apClient.SetAttribute("PacketSize", UintegerValue(payloadSize)); // bytes ApplicationContainer apClientApp = apClient.Install(wifiApNode.Get(0)); apClientApp.Start(Seconds(1.0)); - apClientApp.Stop(Seconds(simulationTime + 1)); + apClientApp.Stop(simulationTime + Seconds(1.0)); } if (staHasTraffic) @@ -230,21 +230,21 @@ main(int argc, char* argv[]) staClient.SetAttribute("PacketSize", UintegerValue(payloadSize)); // bytes ApplicationContainer staClientApp = staClient.Install(wifiStaNode.Get(0)); staClientApp.Start(Seconds(1.0)); - staClientApp.Stop(Seconds(simulationTime + 1)); + staClientApp.Stop(simulationTime + Seconds(1.0)); } Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - uint64_t rxBytes; + double rxBytes; double throughput; bool error = false; if (apHasTraffic) { rxBytes = payloadSize * DynamicCast(staServerApp.Get(0))->GetReceived(); - throughput = (rxBytes * 8) / (simulationTime * 1000000.0); // Mbit/s + throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s std::cout << "AP Throughput: " << throughput << " Mbit/s" << std::endl; if (throughput == 0) { @@ -254,7 +254,7 @@ main(int argc, char* argv[]) if (staHasTraffic) { rxBytes = payloadSize * DynamicCast(apServerApp.Get(0))->GetReceived(); - throughput = (rxBytes * 8) / (simulationTime * 1000000.0); // Mbit/s + throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s std::cout << "STA Throughput: " << throughput << " Mbit/s" << std::endl; if (throughput == 0) { diff --git a/examples/wireless/wifi-eht-network.cc b/examples/wireless/wifi-eht-network.cc index a2b2b5e7d6..d14fa202a0 100644 --- a/examples/wireless/wifi-eht-network.cc +++ b/examples/wireless/wifi-eht-network.cc @@ -31,7 +31,6 @@ #include "ns3/on-off-helper.h" #include "ns3/packet-sink-helper.h" #include "ns3/packet-sink.h" -#include "ns3/rng-seed-manager.h" #include "ns3/spectrum-wifi-helper.h" #include "ns3/ssid.h" #include "ns3/string.h" @@ -110,7 +109,7 @@ PrintIntermediateTput(std::vector& rxBytes, const ApplicationContainer& serverApp, uint32_t payloadSize, Time tputInterval, - double simulationTime) + Time simulationTime) { auto newRxBytes = GetRxBytes(udp, serverApp, payloadSize); Time now = Simulator::Now(); @@ -127,9 +126,9 @@ PrintIntermediateTput(std::vector& rxBytes, rxBytes.swap(newRxBytes); - if (now < Seconds(simulationTime) - NanoSeconds(1)) + if (now < (simulationTime - NanoSeconds(1))) { - Simulator::Schedule(Min(tputInterval, Seconds(simulationTime) - now - NanoSeconds(1)), + Simulator::Schedule(Min(tputInterval, simulationTime - now - NanoSeconds(1)), &PrintIntermediateTput, rxBytes, udp, @@ -152,9 +151,11 @@ main(int argc, char* argv[]) uint16_t transitionDelayUsec{128}; uint16_t channelSwitchDelayUsec{100}; bool switchAuxPhy{true}; - double simulationTime{10}; // seconds - double distance{1.0}; // meters - double frequency{5}; // whether the first link operates in the 2.4, 5 or 6 GHz + uint16_t auxPhyChWidth{20}; + bool auxPhyTxCapable{true}; + Time simulationTime{"10s"}; + double distance{1.0}; // meters + double frequency{5}; // whether the first link operates in the 2.4, 5 or 6 GHz double frequency2{0}; // whether the second link operates in the 2.4, 5 or 6 GHz (0 means no // second link exists) double frequency3{ @@ -199,13 +200,19 @@ main(int argc, char* argv[]) "Whether Aux PHY should switch channel to operate on the link on which " "the Main PHY was operating before moving to the link of the Aux PHY. ", switchAuxPhy); + cmd.AddValue("emlsrAuxChWidth", + "The maximum channel width (MHz) supported by Aux PHYs.", + auxPhyChWidth); + cmd.AddValue("emlsrAuxTxCapable", + "Whether Aux PHYs are capable of transmitting.", + auxPhyTxCapable); cmd.AddValue("channelSwitchDelay", "The PHY channel switch delay in microseconds", channelSwitchDelayUsec); cmd.AddValue("distance", "Distance in meters between the station and the access point", distance); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp); cmd.AddValue("downlink", "Generate downlink flows if set to 1, uplink flows otherwise", @@ -214,7 +221,7 @@ main(int argc, char* argv[]) cmd.AddValue("mpduBufferSize", "Size (in number of MPDUs) of the BlockAck buffer", mpduBufferSize); - cmd.AddValue("nStations", "Number of non-AP HE stations", nStations); + cmd.AddValue("nStations", "Number of non-AP EHT stations", nStations); cmd.AddValue("dlAckType", "Ack sequence type for DL OFDMA (NO-OFDMA, ACK-SU-FORMAT, MU-BAR, AGGR-MU-BAR)", dlAckSeqType); @@ -288,9 +295,10 @@ main(int argc, char* argv[]) double previous = 0; uint16_t maxChannelWidth = (frequency != 2.4 && frequency2 != 2.4 && frequency3 != 2.4) ? 160 : 40; + int minGi = enableUlOfdma ? 1600 : 800; for (int channelWidth = 20; channelWidth <= maxChannelWidth;) // MHz { - for (int gi = 3200; gi >= 800;) // Nanoseconds + for (int gi = 3200; gi >= minGi;) // Nanoseconds { if (!udp) { @@ -318,8 +326,7 @@ main(int argc, char* argv[]) if (frequency2 == frequency || frequency3 == frequency || (frequency3 != 0 && frequency3 == frequency2)) { - std::cout << "Frequency values must be unique!" << std::endl; - return 0; + NS_FATAL_ERROR("Frequency values must be unique!"); } for (auto freq : {frequency, frequency2, frequency3}) @@ -370,8 +377,7 @@ main(int argc, char* argv[]) } else { - std::cout << "Wrong frequency value!" << std::endl; - return 0; + NS_FATAL_ERROR("Wrong frequency value!"); } nLinks++; } @@ -402,7 +408,11 @@ main(int argc, char* argv[]) "EmlsrTransitionDelay", TimeValue(MicroSeconds(transitionDelayUsec)), "SwitchAuxPhy", - BooleanValue(switchAuxPhy)); + BooleanValue(switchAuxPhy), + "AuxPhyTxCapable", + BooleanValue(auxPhyTxCapable), + "AuxPhyChannelWidth", + UintegerValue(auxPhyChWidth)); for (uint8_t linkId = 0; linkId < nLinks; linkId++) { phy.Set(linkId, "ChannelSettings", StringValue(channelStr[linkId])); @@ -431,8 +441,6 @@ main(int argc, char* argv[]) SsidValue(ssid)); apDevice = wifi.Install(phy, mac, wifiApNode); - RngSeedManager::SetSeed(1); - RngSeedManager::SetRun(1); int64_t streamNumber = 100; streamNumber += wifi.AssignStreams(apDevice, streamNumber); streamNumber += wifi.AssignStreams(staDevices, streamNumber); @@ -461,6 +469,8 @@ main(int argc, char* argv[]) InternetStackHelper stack; stack.Install(wifiApNode); stack.Install(wifiStaNodes); + streamNumber += stack.AssignStreams(wifiApNode, streamNumber); + streamNumber += stack.AssignStreams(wifiStaNodes, streamNumber); Ipv4AddressHelper address; address.SetBase("192.168.1.0", "255.255.255.0"); @@ -482,24 +492,31 @@ main(int argc, char* argv[]) clientNodes.Add(downlink ? wifiApNode.Get(0) : wifiStaNodes.Get(i)); } + const auto maxLoad = + nLinks * EhtPhy::GetDataRate(mcs, channelWidth, gi, 1) / nStations; if (udp) { // UDP flow uint16_t port = 9; UdpServerHelper server(port); serverApp = server.Install(serverNodes.get()); + streamNumber += server.AssignStreams(serverNodes.get(), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / maxLoad; for (std::size_t i = 0; i < nStations; i++) { UdpClientHelper client(serverInterfaces.GetAddress(i), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.00001"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(clientNodes.Get(i)); + streamNumber += client.AssignStreams(clientNodes.Get(i), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } } else @@ -509,8 +526,10 @@ main(int argc, char* argv[]) Address localAddress(InetSocketAddress(Ipv4Address::GetAny(), port)); PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress); serverApp = packetSinkHelper.Install(serverNodes.get()); + streamNumber += packetSinkHelper.AssignStreams(serverNodes.get(), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); for (std::size_t i = 0; i < nStations; i++) { @@ -520,13 +539,15 @@ main(int argc, char* argv[]) onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("PacketSize", UintegerValue(payloadSize)); - onoff.SetAttribute("DataRate", DataRateValue(1000000000)); // bit/s + onoff.SetAttribute("DataRate", DataRateValue(maxLoad)); AddressValue remoteAddress( InetSocketAddress(serverInterfaces.GetAddress(i), port)); onoff.SetAttribute("Remote", remoteAddress); ApplicationContainer clientApp = onoff.Install(clientNodes.Get(i)); + streamNumber += onoff.AssignStreams(clientNodes.Get(i), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } } @@ -542,20 +563,20 @@ main(int argc, char* argv[]) serverApp, payloadSize, tputInterval, - simulationTime + 1); + simulationTime + Seconds(1.0)); } - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); // When multiple stations are used, there are chances that association requests // collide and hence the throughput may be lower than expected. Therefore, we relax // the check that the throughput cannot decrease by introducing a scaling factor (or // tolerance) - double tolerance = 0.10; + auto tolerance = 0.10; cumulRxBytes = GetRxBytes(udp, serverApp, payloadSize); - uint64_t rxBytes = std::accumulate(cumulRxBytes.cbegin(), cumulRxBytes.cend(), 0); - double throughput = (rxBytes * 8) / (simulationTime * 1000000.0); // Mbit/s + auto rxBytes = std::accumulate(cumulRxBytes.cbegin(), cumulRxBytes.cend(), 0.0); + auto throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s Simulator::Destroy(); @@ -563,7 +584,7 @@ main(int argc, char* argv[]) << throughput << " Mbit/s" << std::endl; // test first element - if (mcs == 0 && channelWidth == 20 && gi == 3200) + if (mcs == minMcs && channelWidth == 20 && gi == 3200) { if (throughput * (1 + tolerance) < minExpectedThroughput) { @@ -572,7 +593,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == 11 && channelWidth == 160 && gi == 800) + if (mcs == maxMcs && channelWidth == maxChannelWidth && gi == 800) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput * (1 + tolerance)) diff --git a/examples/wireless/wifi-he-network.cc b/examples/wireless/wifi-he-network.cc index a13a9d5d87..17b88cc5cb 100644 --- a/examples/wireless/wifi-he-network.cc +++ b/examples/wireless/wifi-he-network.cc @@ -32,7 +32,6 @@ #include "ns3/on-off-helper.h" #include "ns3/packet-sink-helper.h" #include "ns3/packet-sink.h" -#include "ns3/rng-seed-manager.h" #include "ns3/spectrum-wifi-helper.h" #include "ns3/ssid.h" #include "ns3/string.h" @@ -74,9 +73,9 @@ main(int argc, char* argv[]) bool downlink{true}; bool useRts{false}; bool useExtendedBlockAck{false}; - double simulationTime{10}; // seconds - double distance{1.0}; // meters - double frequency{5}; // whether 2.4, 5 or 6 GHz + Time simulationTime{"10s"}; + double distance{1.0}; // meters + double frequency{5}; // whether 2.4, 5 or 6 GHz std::size_t nStations{1}; std::string dlAckSeqType{"NO-OFDMA"}; bool enableUlOfdma{false}; @@ -96,7 +95,7 @@ main(int argc, char* argv[]) cmd.AddValue("distance", "Distance in meters between the station and the access point", distance); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp); cmd.AddValue("downlink", "Generate downlink flows if set to 1, uplink flows otherwise", @@ -189,9 +188,10 @@ main(int argc, char* argv[]) uint8_t index = 0; double previous = 0; uint8_t maxChannelWidth = frequency == 2.4 ? 40 : 160; + int minGi = enableUlOfdma ? 1600 : 800; for (int channelWidth = 20; channelWidth <= maxChannelWidth;) // MHz { - for (int gi = 3200; gi >= 800;) // Nanoseconds + for (int gi = 3200; gi >= minGi;) // Nanoseconds { if (!udp) { @@ -242,8 +242,7 @@ main(int argc, char* argv[]) } else { - std::cout << "Wrong frequency value!" << std::endl; - return 0; + NS_FATAL_ERROR("Wrong frequency value!"); } wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", @@ -323,8 +322,6 @@ main(int argc, char* argv[]) apDevice = wifi.Install(phy, mac, wifiApNode); } - RngSeedManager::SetSeed(1); - RngSeedManager::SetRun(1); int64_t streamNumber = 150; streamNumber += wifi.AssignStreams(apDevice, streamNumber); streamNumber += wifi.AssignStreams(staDevices, streamNumber); @@ -346,6 +343,8 @@ main(int argc, char* argv[]) InternetStackHelper stack; stack.Install(wifiApNode); stack.Install(wifiStaNodes); + streamNumber += stack.AssignStreams(wifiApNode, streamNumber); + streamNumber += stack.AssignStreams(wifiStaNodes, streamNumber); Ipv4AddressHelper address; address.SetBase("192.168.1.0", "255.255.255.0"); @@ -367,24 +366,30 @@ main(int argc, char* argv[]) clientNodes.Add(downlink ? wifiApNode.Get(0) : wifiStaNodes.Get(i)); } + const auto maxLoad = HePhy::GetDataRate(mcs, channelWidth, gi, 1) / nStations; if (udp) { // UDP flow uint16_t port = 9; UdpServerHelper server(port); serverApp = server.Install(serverNodes.get()); + streamNumber += server.AssignStreams(serverNodes.get(), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / maxLoad; for (std::size_t i = 0; i < nStations; i++) { UdpClientHelper client(serverInterfaces.GetAddress(i), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.00001"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(clientNodes.Get(i)); + streamNumber += client.AssignStreams(clientNodes.Get(i), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } } else @@ -394,8 +399,10 @@ main(int argc, char* argv[]) Address localAddress(InetSocketAddress(Ipv4Address::GetAny(), port)); PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress); serverApp = packetSinkHelper.Install(serverNodes.get()); + streamNumber += packetSinkHelper.AssignStreams(serverNodes.get(), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); for (std::size_t i = 0; i < nStations; i++) { @@ -405,27 +412,29 @@ main(int argc, char* argv[]) onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("PacketSize", UintegerValue(payloadSize)); - onoff.SetAttribute("DataRate", DataRateValue(1000000000)); // bit/s + onoff.SetAttribute("DataRate", DataRateValue(maxLoad)); AddressValue remoteAddress( InetSocketAddress(serverInterfaces.GetAddress(i), port)); onoff.SetAttribute("Remote", remoteAddress); ApplicationContainer clientApp = onoff.Install(clientNodes.Get(i)); + streamNumber += onoff.AssignStreams(clientNodes.Get(i), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } } Simulator::Schedule(Seconds(0), &Ipv4GlobalRoutingHelper::PopulateRoutingTables); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); // When multiple stations are used, there are chances that association requests // collide and hence the throughput may be lower than expected. Therefore, we relax // the check that the throughput cannot decrease by introducing a scaling factor (or // tolerance) - double tolerance = 0.10; - uint64_t rxBytes = 0; + auto tolerance = 0.10; + auto rxBytes = 0.0; if (udp) { for (uint32_t i = 0; i < serverApp.GetN(); i++) @@ -441,7 +450,7 @@ main(int argc, char* argv[]) rxBytes += DynamicCast(serverApp.Get(i))->GetTotalRx(); } } - double throughput = (rxBytes * 8) / (simulationTime * 1000000.0); // Mbit/s + auto throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s Simulator::Destroy(); @@ -449,7 +458,7 @@ main(int argc, char* argv[]) << throughput << " Mbit/s" << std::endl; // test first element - if (mcs == 0 && channelWidth == 20 && gi == 3200) + if (mcs == minMcs && channelWidth == 20 && gi == 3200) { if (throughput * (1 + tolerance) < minExpectedThroughput) { @@ -458,7 +467,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == 11 && channelWidth == 160 && gi == 800) + if (mcs == maxMcs && channelWidth == maxChannelWidth && gi == 800) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput * (1 + tolerance)) diff --git a/examples/wireless/wifi-ht-network.cc b/examples/wireless/wifi-ht-network.cc index 64f135ddc5..5b2f545e24 100644 --- a/examples/wireless/wifi-ht-network.cc +++ b/examples/wireless/wifi-ht-network.cc @@ -64,14 +64,14 @@ NS_LOG_COMPONENT_DEFINE("ht-wifi-network"); int main(int argc, char* argv[]) { - bool udp = true; - bool useRts = false; - double simulationTime = 10; // seconds - double distance = 1.0; // meters - double frequency = 5.0; // whether 2.4 or 5.0 GHz - int mcs = -1; // -1 indicates an unset value - double minExpectedThroughput = 0; - double maxExpectedThroughput = 0; + bool udp{true}; + bool useRts{false}; + Time simulationTime{"10s"}; + double distance{1.0}; // meters + double frequency{5}; // whether 2.4 or 5 GHz + int mcs{-1}; // -1 indicates an unset value + double minExpectedThroughput{0.0}; + double maxExpectedThroughput{0.0}; CommandLine cmd(__FILE__); cmd.AddValue("frequency", @@ -80,7 +80,7 @@ main(int argc, char* argv[]) cmd.AddValue("distance", "Distance in meters between the station and the access point", distance); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp); cmd.AddValue("useRts", "Enable/disable RTS/CTS", useRts); cmd.AddValue("mcs", "if set, limit testing to a specific MCS (0-7)", mcs); @@ -159,8 +159,7 @@ main(int argc, char* argv[]) } else { - std::cout << "Wrong frequency value!" << std::endl; - return 0; + NS_FATAL_ERROR("Wrong frequency value!"); } auto nonHtRefRateMbps = HtPhy::GetNonHtReferenceRate(mcs) / 1e6; @@ -197,6 +196,10 @@ main(int argc, char* argv[]) NetDeviceContainer apDevice; apDevice = wifi.Install(phy, mac, wifiApNode); + int64_t streamNumber = 150; + streamNumber += wifi.AssignStreams(apDevice, streamNumber); + streamNumber += wifi.AssignStreams(staDevice, streamNumber); + // mobility. MobilityHelper mobility; Ptr positionAlloc = CreateObject(); @@ -214,6 +217,8 @@ main(int argc, char* argv[]) InternetStackHelper stack; stack.Install(wifiApNode); stack.Install(wifiStaNode); + streamNumber += stack.AssignStreams(wifiApNode, streamNumber); + streamNumber += stack.AssignStreams(wifiStaNode, streamNumber); Ipv4AddressHelper address; address.SetBase("192.168.1.0", "255.255.255.0"); @@ -224,6 +229,7 @@ main(int argc, char* argv[]) apNodeInterface = address.Assign(apDevice); /* Setting applications */ + const auto maxLoad = HtPhy::GetDataRate(mcs, channelWidth, sgi ? 400 : 800, 1); ApplicationContainer serverApp; if (udp) { @@ -231,16 +237,21 @@ main(int argc, char* argv[]) uint16_t port = 9; UdpServerHelper server(port); serverApp = server.Install(wifiStaNode.Get(0)); + streamNumber += server.AssignStreams(wifiStaNode.Get(0), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / maxLoad; UdpClientHelper client(staNodeInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.00001"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(wifiApNode.Get(0)); + streamNumber += client.AssignStreams(wifiApNode.Get(0), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } else { @@ -249,8 +260,11 @@ main(int argc, char* argv[]) Address localAddress(InetSocketAddress(Ipv4Address::GetAny(), port)); PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress); serverApp = packetSinkHelper.Install(wifiStaNode.Get(0)); + streamNumber += + packetSinkHelper.AssignStreams(wifiStaNode.Get(0), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny()); onoff.SetAttribute("OnTime", @@ -258,21 +272,23 @@ main(int argc, char* argv[]) onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("PacketSize", UintegerValue(payloadSize)); - onoff.SetAttribute("DataRate", DataRateValue(200000000)); // bit/s + onoff.SetAttribute("DataRate", DataRateValue(maxLoad)); AddressValue remoteAddress( InetSocketAddress(staNodeInterface.GetAddress(0), port)); onoff.SetAttribute("Remote", remoteAddress); ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0)); + streamNumber += onoff.AssignStreams(wifiApNode.Get(0), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - uint64_t rxBytes = 0; + auto rxBytes = 0.0; if (udp) { rxBytes = payloadSize * DynamicCast(serverApp.Get(0))->GetReceived(); @@ -281,7 +297,7 @@ main(int argc, char* argv[]) { rxBytes = DynamicCast(serverApp.Get(0))->GetTotalRx(); } - double throughput = (rxBytes * 8) / (simulationTime * 1000000.0); // Mbit/s + auto throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s Simulator::Destroy(); @@ -289,7 +305,7 @@ main(int argc, char* argv[]) << sgi << "\t\t\t" << throughput << " Mbit/s" << std::endl; // test first element - if (mcs == 0 && channelWidth == 20 && !sgi) + if (mcs == minMcs && channelWidth == 20 && !sgi) { if (throughput < minExpectedThroughput) { @@ -297,7 +313,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == 7 && channelWidth == 40 && sgi) + if (mcs == maxMcs && channelWidth == 40 && sgi) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput) { diff --git a/examples/wireless/wifi-mixed-network.cc b/examples/wireless/wifi-mixed-network.cc index 695a824523..0613b95f5a 100644 --- a/examples/wireless/wifi-mixed-network.cc +++ b/examples/wireless/wifi-mixed-network.cc @@ -81,7 +81,7 @@ struct Parameters bool nHasTraffic; //!< True if 802.11n stations generate traffic bool isUdp; //!< True to generate UDP traffic uint32_t payloadSize; //!< Payload size in bytes - double simulationTime; //!< Simulation time in seconds + Time simulationTime; //!< Simulation time }; class Experiment @@ -130,7 +130,7 @@ Experiment::Run(Parameters params) uint32_t nWifiB = params.nWifiB; uint32_t nWifiG = params.nWifiG; uint32_t nWifiN = params.nWifiN; - double simulationTime = params.simulationTime; + auto simulationTime = params.simulationTime; uint32_t payloadSize = params.payloadSize; NodeContainer wifiBStaNodes; @@ -277,7 +277,7 @@ Experiment::Run(Parameters params) UdpServerHelper server(port); ApplicationContainer serverApp = server.Install(wifiApNode); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); UdpClientHelper client(ApInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -298,13 +298,13 @@ Experiment::Run(Parameters params) clientApps.Add(client.Install(wifiNStaNodes)); } clientApps.Start(Seconds(1.0)); - clientApps.Stop(Seconds(simulationTime + 1)); + clientApps.Stop(simulationTime + Seconds(1.0)); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - uint64_t totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); - throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); + double totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); + throughput = totalPacketsThrough * payloadSize * 8 / simulationTime.GetMicroSeconds(); } else { @@ -314,7 +314,7 @@ Experiment::Run(Parameters params) ApplicationContainer serverApp = packetSinkHelper.Install(wifiApNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny()); onoff.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); @@ -339,13 +339,13 @@ Experiment::Run(Parameters params) clientApps.Add(onoff.Install(wifiNStaNodes)); } clientApps.Start(Seconds(1.0)); - clientApps.Stop(Seconds(simulationTime + 1)); + clientApps.Stop(simulationTime + Seconds(1.0)); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - uint64_t totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetTotalRx(); - throughput += totalPacketsThrough * 8 / (simulationTime * 1000000.0); + double totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetTotalRx(); + throughput += totalPacketsThrough * 8 / simulationTime.GetMicroSeconds(); } Simulator::Destroy(); return throughput; @@ -368,14 +368,14 @@ main(int argc, char* argv[]) params.nWifiN = 0; params.nHasTraffic = false; params.isUdp = true; - params.payloadSize = 1472; // bytes - params.simulationTime = 10; // seconds + params.payloadSize = 1472; // bytes + params.simulationTime = Seconds(10); bool verifyResults = false; // used for regression CommandLine cmd(__FILE__); cmd.AddValue("payloadSize", "Payload size in bytes", params.payloadSize); - cmd.AddValue("simulationTime", "Simulation time in seconds", params.simulationTime); + cmd.AddValue("simulationTime", "Simulation time", params.simulationTime); cmd.AddValue("isUdp", "UDP if set to 1, TCP otherwise", params.isUdp); cmd.AddValue("verifyResults", "Enable/disable results verification at the end of the simulation", diff --git a/examples/wireless/wifi-multi-tos.cc b/examples/wireless/wifi-multi-tos.cc index 17147bc635..3a10682380 100644 --- a/examples/wireless/wifi-multi-tos.cc +++ b/examples/wireless/wifi-multi-tos.cc @@ -47,20 +47,20 @@ NS_LOG_COMPONENT_DEFINE("WifiMultiTos"); int main(int argc, char* argv[]) { - uint32_t nWifi = 4; - double simulationTime = 10; // seconds - double distance = 1.0; // meters - uint16_t mcs = 7; - uint8_t channelWidth = 20; // MHz - bool useShortGuardInterval = false; - bool useRts = false; + uint32_t nWifi{4}; + Time simulationTime{"10s"}; + double distance{1.0}; // meters + uint16_t mcs{7}; + uint8_t channelWidth{20}; // MHz + bool useShortGuardInterval{false}; + bool useRts{false}; CommandLine cmd(__FILE__); cmd.AddValue("nWifi", "Number of stations", nWifi); cmd.AddValue("distance", "Distance in meters between the stations and the access point", distance); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("useRts", "Enable/disable RTS/CTS", useRts); cmd.AddValue("mcs", "MCS value (0 - 7)", mcs); cmd.AddValue("channelWidth", "Channel width in MHz", channelWidth); @@ -151,7 +151,6 @@ main(int argc, char* argv[]) auto ipv4 = wifiApNode.Get(0)->GetObject(); const auto address = ipv4->GetAddress(1, 0).GetLocal(); InetSocketAddress sinkSocket(address, portNumber++); - sinkSocket.SetTos(tosValue); OnOffHelper onOffHelper("ns3::UdpSocketFactory", sinkSocket); onOffHelper.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); @@ -159,6 +158,7 @@ main(int argc, char* argv[]) StringValue("ns3::ConstantRandomVariable[Constant=0]")); onOffHelper.SetAttribute("DataRate", DataRateValue(50000000 / nWifi)); onOffHelper.SetAttribute("PacketSize", UintegerValue(1472)); // bytes + onOffHelper.SetAttribute("Tos", UintegerValue(tosValue)); sourceApplications.Add(onOffHelper.Install(wifiStaNodes.Get(index))); PacketSinkHelper packetSinkHelper("ns3::UdpSocketFactory", sinkSocket); sinkApplications.Add(packetSinkHelper.Install(wifiApNode.Get(0))); @@ -166,21 +166,21 @@ main(int argc, char* argv[]) } sinkApplications.Start(Seconds(0.0)); - sinkApplications.Stop(Seconds(simulationTime + 1)); + sinkApplications.Stop(simulationTime + Seconds(1.0)); sourceApplications.Start(Seconds(1.0)); - sourceApplications.Stop(Seconds(simulationTime + 1)); + sourceApplications.Stop(simulationTime + Seconds(1.0)); Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); double throughput = 0; for (uint32_t index = 0; index < sinkApplications.GetN(); ++index) { - uint64_t totalPacketsThrough = + double totalPacketsThrough = DynamicCast(sinkApplications.Get(index))->GetTotalRx(); - throughput += ((totalPacketsThrough * 8) / (simulationTime * 1000000.0)); // Mbit/s + throughput += ((totalPacketsThrough * 8) / simulationTime.GetMicroSeconds()); // Mbit/s } Simulator::Destroy(); diff --git a/examples/wireless/wifi-multirate.cc b/examples/wireless/wifi-multirate.cc index 409c1cea2b..0a06712297 100644 --- a/examples/wireless/wifi-multirate.cc +++ b/examples/wireless/wifi-multirate.cc @@ -480,7 +480,7 @@ Experiment::ApplicationSetup(Ptr client, Ptr server, double start, d // Equipping the source node with OnOff Application used for sending OnOffHelper onoff("ns3::UdpSocketFactory", Address(InetSocketAddress(Ipv4Address("10.0.0.1"), m_port))); - onoff.SetConstantRate(DataRate(60000000)); + onoff.SetConstantRate(DataRate(54000000)); onoff.SetAttribute("PacketSize", UintegerValue(m_packetSize)); onoff.SetAttribute("Remote", AddressValue(InetSocketAddress(ipv4AddrServer, m_port))); diff --git a/examples/wireless/wifi-power-adaptation-distance.cc b/examples/wireless/wifi-power-adaptation-distance.cc index 651a1dad8d..1557a127c3 100644 --- a/examples/wireless/wifi-power-adaptation-distance.cc +++ b/examples/wireless/wifi-power-adaptation-distance.cc @@ -171,7 +171,7 @@ class NodeStatistics * \param stepsSize The step size. * \param stepsTime Time on each step. */ - void AdvancePosition(Ptr node, int stepsSize, int stepsTime); + void AdvancePosition(Ptr node, int stepsSize, Time stepsTime); /** * \brief Get the Position of a node. * @@ -325,12 +325,12 @@ NodeStatistics::GetPosition(Ptr node) } void -NodeStatistics::AdvancePosition(Ptr node, int stepsSize, int stepsTime) +NodeStatistics::AdvancePosition(Ptr node, int stepsSize, Time stepsTime) { Vector pos = GetPosition(node); - double mbs = ((m_bytesTotal * 8.0) / (1000000 * stepsTime)); + double mbs = ((m_bytesTotal * 8.0) / stepsTime.GetMicroSeconds()); m_bytesTotal = 0; - double atp = m_totalEnergy / stepsTime; + double atp = m_totalEnergy / stepsTime.GetSeconds(); m_totalEnergy = 0; m_totalTime = 0; m_output_power.Add(pos.x, atp); @@ -339,7 +339,7 @@ NodeStatistics::AdvancePosition(Ptr node, int stepsSize, int stepsTime) SetPosition(node, pos); NS_LOG_INFO("At time " << Simulator::Now().GetSeconds() << " sec; setting new position to " << pos); - Simulator::Schedule(Seconds(stepsTime), + Simulator::Schedule(stepsTime, &NodeStatistics::AdvancePosition, this, node, @@ -392,20 +392,20 @@ RateCallback(std::string path, DataRate oldRate, DataRate newRate, Mac48Address int main(int argc, char* argv[]) { - double maxPower = 17; - double minPower = 0; - uint32_t powerLevels = 18; - - uint32_t rtsThreshold = 2346; - std::string manager = "ns3::ParfWifiManager"; - std::string outputFileName = "parf"; - int ap1_x = 0; - int ap1_y = 0; - int sta1_x = 5; - int sta1_y = 0; - uint32_t steps = 200; - uint32_t stepsSize = 1; - uint32_t stepsTime = 1; + double maxPower{17}; + double minPower{0}; + uint32_t powerLevels{18}; + + uint32_t rtsThreshold{2346}; + std::string manager{"ns3::ParfWifiManager"}; + std::string outputFileName{"parf"}; + int ap1_x{0}; + int ap1_y{0}; + int sta1_x{5}; + int sta1_y{0}; + uint32_t steps{200}; + uint32_t stepsSize{1}; + Time stepsTime{"1s"}; CommandLine cmd(__FILE__); cmd.AddValue("manager", "PRC Manager", manager); @@ -431,7 +431,7 @@ main(int argc, char* argv[]) std::cout << "Exiting without running simulation; steps value of 0" << std::endl; } - uint32_t simuTime = (steps + 1) * stepsTime; + Time simuTime = (steps + 1) * stepsTime; // Define the APs NodeContainer wifiApNodes; @@ -498,7 +498,7 @@ main(int argc, char* argv[]) NodeStatistics statistics = NodeStatistics(wifiApDevices, wifiStaDevices); // Move the STA by stepsSize meters every stepsTime seconds - Simulator::Schedule(Seconds(0.5 + stepsTime), + Simulator::Schedule(Seconds(0.5) + stepsTime, &NodeStatistics::AdvancePosition, &statistics, wifiStaNodes.Get(0), @@ -522,11 +522,11 @@ main(int argc, char* argv[]) OnOffHelper onoff("ns3::UdpSocketFactory", InetSocketAddress(sinkAddress, port)); onoff.SetConstantRate(DataRate("54Mb/s"), packetSize); onoff.SetAttribute("StartTime", TimeValue(Seconds(0.5))); - onoff.SetAttribute("StopTime", TimeValue(Seconds(simuTime))); + onoff.SetAttribute("StopTime", TimeValue(simuTime)); ApplicationContainer apps_source = onoff.Install(wifiApNodes.Get(0)); apps_sink.Start(Seconds(0.5)); - apps_sink.Stop(Seconds(simuTime)); + apps_sink.Stop(simuTime); //------------------------------------------------------------ //-- Setup stats and data collection @@ -555,7 +555,7 @@ main(int argc, char* argv[]) manager + "/RateChange", MakeCallback(RateCallback)); - Simulator::Stop(Seconds(simuTime)); + Simulator::Stop(simuTime); Simulator::Run(); std::ofstream outfile("throughput-" + outputFileName + ".plt"); diff --git a/examples/wireless/wifi-power-adaptation-interference.cc b/examples/wireless/wifi-power-adaptation-interference.cc index 7932a1f0b8..a0b2b4d50d 100644 --- a/examples/wireless/wifi-power-adaptation-interference.cc +++ b/examples/wireless/wifi-power-adaptation-interference.cc @@ -456,22 +456,22 @@ main(int argc, char* argv[]) { // LogComponentEnable("ConstantRateWifiManager", LOG_LEVEL_FUNCTION); - double maxPower = 17; - double minPower = 0; - uint32_t powerLevels = 18; - - uint32_t rtsThreshold = 2346; - std::string manager = "ns3::ParfWifiManager"; - std::string outputFileName = "parf"; - int ap1_x = 0; - int ap1_y = 0; - int sta1_x = 10; - int sta1_y = 0; - int ap2_x = 200; - int ap2_y = 0; - int sta2_x = 180; - int sta2_y = 0; - uint32_t simuTime = 100; + double maxPower{17}; + double minPower{0}; + uint32_t powerLevels{18}; + + uint32_t rtsThreshold{2346}; + std::string manager{"ns3::ParfWifiManager"}; + std::string outputFileName{"parf"}; + int ap1_x{0}; + int ap1_y{0}; + int sta1_x{10}; + int sta1_y{0}; + int ap2_x{200}; + int ap2_y{0}; + int sta2_x{180}; + int sta2_y{0}; + Time simuTime{"100s"}; CommandLine cmd(__FILE__); cmd.AddValue("manager", "PRC Manager", manager); @@ -603,7 +603,7 @@ main(int argc, char* argv[]) apps_source.Add(onoff1.Install(wifiApNodes.Get(1))); apps_sink.Start(Seconds(0.5)); - apps_sink.Stop(Seconds(simuTime)); + apps_sink.Stop(simuTime); //------------------------------------------------------------ //-- Setup stats and data collection @@ -662,7 +662,7 @@ main(int argc, char* argv[]) FlowMonitorHelper flowmon; Ptr monitor = flowmon.InstallAll(); - Simulator::Stop(Seconds(simuTime)); + Simulator::Stop(simuTime); Simulator::Run(); Ptr classifier = DynamicCast(flowmon.GetClassifier()); @@ -686,7 +686,7 @@ main(int argc, char* argv[]) << "\n"); NS_LOG_INFO(" Mean jitter: " << i->second.jitterSum.GetSeconds() / (i->second.rxPackets - 1) << "\n"); - NS_LOG_INFO(" Tx Opp: " << 1 - (statisticsAp0.GetBusyTime() / simuTime)); + NS_LOG_INFO(" Tx Opp: " << 1 - (statisticsAp0.GetBusyTime() / simuTime.GetSeconds())); } if (t.sourceAddress == "10.1.1.4" && t.destinationAddress == "10.1.1.2") { @@ -704,7 +704,7 @@ main(int argc, char* argv[]) << "\n"); NS_LOG_INFO(" Mean jitter: " << i->second.jitterSum.GetSeconds() / (i->second.rxPackets - 1) << "\n"); - NS_LOG_INFO(" Tx Opp: " << 1 - (statisticsAp1.GetBusyTime() / simuTime)); + NS_LOG_INFO(" Tx Opp: " << 1 - (statisticsAp1.GetBusyTime() / simuTime.GetSeconds())); } } diff --git a/examples/wireless/wifi-rate-adaptation-distance.cc b/examples/wireless/wifi-rate-adaptation-distance.cc index 4dc7f6617d..dd59fb9f6d 100644 --- a/examples/wireless/wifi-rate-adaptation-distance.cc +++ b/examples/wireless/wifi-rate-adaptation-distance.cc @@ -24,7 +24,7 @@ * highlighting the power adaptation. * * This simulation consist of 2 nodes, one AP and one STA. - * The AP generates UDP traffic with a CBR of 54 Mbps to the STA. + * The AP generates UDP traffic with a CBR of 400 Mbps to the STA. * The AP can use any power and rate control mechanism and the STA uses * only Minstrel rate control. * The STA can be configured to move away from (or towards to) the AP. @@ -185,21 +185,21 @@ RateCallback(uint64_t oldRate, uint64_t newRate) int main(int argc, char* argv[]) { - uint32_t rtsThreshold = 65535; - std::string staManager = "ns3::MinstrelHtWifiManager"; - std::string apManager = "ns3::MinstrelHtWifiManager"; - std::string standard = "802.11n-5GHz"; - std::string outputFileName = "minstrelHT"; - uint32_t BeMaxAmpduSize = 65535; - bool shortGuardInterval = false; - uint32_t chWidth = 20; - int ap1_x = 0; - int ap1_y = 0; - int sta1_x = 5; - int sta1_y = 0; - int steps = 100; - int stepsSize = 1; - int stepsTime = 1; + uint32_t rtsThreshold{65535}; + std::string staManager{"ns3::MinstrelHtWifiManager"}; + std::string apManager{"ns3::MinstrelHtWifiManager"}; + std::string standard{"802.11n-5GHz"}; + std::string outputFileName{"minstrelHT"}; + uint32_t BeMaxAmpduSize{65535}; + bool shortGuardInterval{false}; + uint32_t chWidth{20}; + int ap1_x{0}; + int ap1_y{0}; + int sta1_x{5}; + int sta1_y{0}; + int steps{100}; + int stepsSize{1}; + int stepsTime{1}; CommandLine cmd(__FILE__); cmd.AddValue("staManager", "Rate adaptation manager of the STA", staManager); @@ -224,7 +224,7 @@ main(int argc, char* argv[]) int simuTime = steps * stepsTime; if (standard != "802.11a" && standard != "802.11b" && standard != "802.11g" && - standard == "802.11n-2.4GHz" && standard != "802.11n-5GHz" && standard != "802.11ac") + standard != "802.11n-2.4GHz" && standard != "802.11n-5GHz" && standard != "802.11ac") { NS_FATAL_ERROR("Standard " << standard << " is not supported by this program"); } diff --git a/examples/wireless/wifi-simple-adhoc-grid.cc b/examples/wireless/wifi-simple-adhoc-grid.cc index 8de6b70f95..b46ccf8921 100644 --- a/examples/wireless/wifi-simple-adhoc-grid.cc +++ b/examples/wireless/wifi-simple-adhoc-grid.cc @@ -149,31 +149,29 @@ GenerateTraffic(Ptr socket, uint32_t pktSize, uint32_t pktCount, Time pk int main(int argc, char* argv[]) { - std::string phyMode("DsssRate1Mbps"); - double distance = 100; // m - uint32_t packetSize = 1000; // bytes - uint32_t numPackets = 1; - uint32_t numNodes = 25; // by default, 5x5 - uint32_t sinkNode = 0; - uint32_t sourceNode = 24; - double interval = 1.0; // seconds - bool verbose = false; - bool tracing = false; + std::string phyMode{"DsssRate1Mbps"}; + double distance{100}; // m + uint32_t packetSize{1000}; // bytes + uint32_t numPackets{1}; + uint32_t numNodes{25}; // by default, 5x5 + uint32_t sinkNode{0}; + uint32_t sourceNode{24}; + Time interPacketInterval{"1s"}; + bool verbose{false}; + bool tracing{false}; CommandLine cmd(__FILE__); cmd.AddValue("phyMode", "Wifi Phy mode", phyMode); cmd.AddValue("distance", "distance (m)", distance); cmd.AddValue("packetSize", "size of application packet sent", packetSize); cmd.AddValue("numPackets", "number of packets generated", numPackets); - cmd.AddValue("interval", "interval (seconds) between packets", interval); + cmd.AddValue("interval", "interval (seconds) between packets", interPacketInterval); cmd.AddValue("verbose", "turn on all WifiNetDevice log components", verbose); cmd.AddValue("tracing", "turn on ascii and pcap tracing", tracing); cmd.AddValue("numNodes", "number of nodes", numNodes); cmd.AddValue("sinkNode", "Receiver node number", sinkNode); cmd.AddValue("sourceNode", "Sender node number", sourceNode); cmd.Parse(argc, argv); - // Convert to time object - Time interPacketInterval = Seconds(interval); // Fix non-unicast data rate to be the same as that of unicast Config::SetDefault("ns3::WifiRemoteStationManager::NonUnicastMode", StringValue(phyMode)); diff --git a/examples/wireless/wifi-simple-adhoc.cc b/examples/wireless/wifi-simple-adhoc.cc index b24b7d7c49..3f85ac58fa 100644 --- a/examples/wireless/wifi-simple-adhoc.cc +++ b/examples/wireless/wifi-simple-adhoc.cc @@ -110,22 +110,20 @@ int main(int argc, char* argv[]) { std::string phyMode("DsssRate1Mbps"); - double rss = -80; // -dBm - uint32_t packetSize = 1000; // bytes - uint32_t numPackets = 1; - double interval = 1.0; // seconds - bool verbose = false; + double rss{-80}; // -dBm + uint32_t packetSize{1000}; // bytes + uint32_t numPackets{1}; + Time interPacketInterval{"1s"}; + bool verbose{false}; CommandLine cmd(__FILE__); cmd.AddValue("phyMode", "Wifi Phy mode", phyMode); cmd.AddValue("rss", "received signal strength", rss); cmd.AddValue("packetSize", "size of application packet sent", packetSize); cmd.AddValue("numPackets", "number of packets generated", numPackets); - cmd.AddValue("interval", "interval (seconds) between packets", interval); + cmd.AddValue("interval", "interval between packets", interPacketInterval); cmd.AddValue("verbose", "turn on all WifiNetDevice log components", verbose); cmd.Parse(argc, argv); - // Convert to time object - Time interPacketInterval = Seconds(interval); // Fix non-unicast data rate to be the same as that of unicast Config::SetDefault("ns3::WifiRemoteStationManager::NonUnicastMode", StringValue(phyMode)); diff --git a/examples/wireless/wifi-simple-ht-hidden-stations.cc b/examples/wireless/wifi-simple-ht-hidden-stations.cc index 7e177c463b..fd779b3beb 100644 --- a/examples/wireless/wifi-simple-ht-hidden-stations.cc +++ b/examples/wireless/wifi-simple-ht-hidden-stations.cc @@ -57,22 +57,22 @@ NS_LOG_COMPONENT_DEFINE("SimplesHtHiddenStations"); int main(int argc, char* argv[]) { - uint32_t payloadSize = 1472; // bytes - double simulationTime = 10; // seconds - uint32_t nMpdus = 1; - uint32_t maxAmpduSize = 0; - bool enableRts = false; - double minExpectedThroughput = 0; - double maxExpectedThroughput = 0; + uint32_t payloadSize{1472}; // bytes + Time simulationTime{"10s"}; + uint32_t nMpdus{1}; + uint32_t maxAmpduSize{0}; + bool enableRts{false}; + double minExpectedThroughput{0}; + double maxExpectedThroughput{0}; RngSeedManager::SetSeed(1); - RngSeedManager::SetRun(5); + RngSeedManager::SetRun(7); CommandLine cmd(__FILE__); cmd.AddValue("nMpdus", "Number of aggregated MPDUs", nMpdus); cmd.AddValue("payloadSize", "Payload size in bytes", payloadSize); cmd.AddValue("enableRts", "Enable RTS/CTS", enableRts); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("minExpectedThroughput", "if set, simulation fails if the lowest throughput is below this value", minExpectedThroughput); @@ -138,6 +138,10 @@ main(int argc, char* argv[]) Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Mac/BE_MaxAmpduSize", UintegerValue(maxAmpduSize)); + int64_t streamNumber = 20; + streamNumber += wifi.AssignStreams(apDevice, streamNumber); + streamNumber += wifi.AssignStreams(staDevices, streamNumber); + // Setting mobility model MobilityHelper mobility; Ptr positionAlloc = CreateObject(); @@ -159,6 +163,8 @@ main(int argc, char* argv[]) InternetStackHelper stack; stack.Install(wifiApNode); stack.Install(wifiStaNodes); + streamNumber += stack.AssignStreams(wifiApNode, streamNumber); + streamNumber += stack.AssignStreams(wifiStaNodes, streamNumber); Ipv4AddressHelper address; address.SetBase("192.168.1.0", "255.255.255.0"); @@ -172,7 +178,8 @@ main(int argc, char* argv[]) UdpServerHelper server(port); ApplicationContainer serverApp = server.Install(wifiApNode); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + streamNumber += server.AssignStreams(wifiApNode, streamNumber); UdpClientHelper client(ApInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -182,7 +189,8 @@ main(int argc, char* argv[]) // Saturated UDP traffic from stations to AP ApplicationContainer clientApp1 = client.Install(wifiStaNodes); clientApp1.Start(Seconds(1.0)); - clientApp1.Stop(Seconds(simulationTime + 1)); + clientApp1.Stop(simulationTime + Seconds(1.0)); + streamNumber += client.AssignStreams(wifiStaNodes, streamNumber); phy.EnablePcap("SimpleHtHiddenStations_Ap", apDevice.Get(0)); phy.EnablePcap("SimpleHtHiddenStations_Sta1", staDevices.Get(0)); @@ -191,15 +199,15 @@ main(int argc, char* argv[]) AsciiTraceHelper ascii; phy.EnableAsciiAll(ascii.CreateFileStream("SimpleHtHiddenStations.tr")); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - uint64_t totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); + double totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); Simulator::Destroy(); - double throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); + auto throughput = totalPacketsThrough * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "Throughput: " << throughput << " Mbit/s" << '\n'; if (throughput < minExpectedThroughput || (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput)) diff --git a/examples/wireless/wifi-simple-infra.cc b/examples/wireless/wifi-simple-infra.cc index 208203bf9b..8e9936738f 100644 --- a/examples/wireless/wifi-simple-infra.cc +++ b/examples/wireless/wifi-simple-infra.cc @@ -142,12 +142,12 @@ GenerateTraffic(Ptr socket, uint32_t pktSize, uint32_t pktCount, Time pk int main(int argc, char* argv[]) { - std::string phyMode("DsssRate1Mbps"); - double rss = -80; // -dBm - uint32_t packetSize = 1000; // bytes - uint32_t numPackets = 1; - Time interval = Seconds(1.0); - bool verbose = false; + std::string phyMode{"DsssRate1Mbps"}; + double rss{-80}; // -dBm + uint32_t packetSize{1000}; // bytes + uint32_t numPackets{1}; + Time interval{"1s"}; + bool verbose{false}; CommandLine cmd(__FILE__); cmd.AddValue("phyMode", "Wifi Phy mode", phyMode); diff --git a/examples/wireless/wifi-simple-interference.cc b/examples/wireless/wifi-simple-interference.cc index cdc0542985..5c6f69faae 100644 --- a/examples/wireless/wifi-simple-interference.cc +++ b/examples/wireless/wifi-simple-interference.cc @@ -160,22 +160,22 @@ GenerateTraffic(Ptr socket, uint32_t pktSize, uint32_t pktCount, Time pk int main(int argc, char* argv[]) { - std::string phyMode("DsssRate1Mbps"); - double Prss = -80; // -dBm - double Irss = -95; // -dBm - double delta = 0; // microseconds - uint32_t PpacketSize = 1000; // bytes - uint32_t IpacketSize = 1000; // bytes - bool verbose = false; + std::string phyMode{"DsssRate1Mbps"}; + double Prss{-80}; // -dBm + double Irss{-95}; // -dBm + double delta{0}; // microseconds + uint32_t PpacketSize{1000}; // bytes + uint32_t IpacketSize{1000}; // bytes + bool verbose{false}; // these are not command line arguments for this version - uint32_t numPackets = 1; - double interval = 1.0; // seconds - double startTime = 10.0; // seconds - double distanceToRx = 100.0; // meters + uint32_t numPackets{1}; + Time interPacketInterval{"1s"}; + Time startTime{"10s"}; + double distanceToRx{100.0}; // meters - double offset = 91; // This is a magic number used to set the - // transmit power, based on other configuration + double offset{91}; // This is a magic number used to set the + // transmit power, based on other configuration CommandLine cmd(__FILE__); cmd.AddValue("phyMode", "Wifi Phy mode", phyMode); cmd.AddValue("Prss", "Intended primary received signal strength (dBm)", Prss); @@ -185,8 +185,6 @@ main(int argc, char* argv[]) cmd.AddValue("IpacketSize", "size of interfering packet sent", IpacketSize); cmd.AddValue("verbose", "turn on all WifiNetDevice log components", verbose); cmd.Parse(argc, argv); - // Convert to time object - Time interPacketInterval = Seconds(interval); // Fix non-unicast data rate to be the same as that of unicast Config::SetDefault("ns3::WifiRemoteStationManager::NonUnicastMode", StringValue(phyMode)); @@ -269,7 +267,7 @@ main(int argc, char* argv[]) << " dBm at time offset=" << delta << " ms"); Simulator::ScheduleWithContext(source->GetNode()->GetId(), - Seconds(startTime), + startTime, &GenerateTraffic, source, PpacketSize, @@ -277,7 +275,7 @@ main(int argc, char* argv[]) interPacketInterval); Simulator::ScheduleWithContext(interferer->GetNode()->GetId(), - Seconds(startTime + delta / 1000000.0), + startTime + Seconds(delta / 1000000.0), &GenerateTraffic, interferer, IpacketSize, diff --git a/examples/wireless/wifi-sleep.cc b/examples/wireless/wifi-sleep.cc index 2bc04743a0..68e2c37a6f 100644 --- a/examples/wireless/wifi-sleep.cc +++ b/examples/wireless/wifi-sleep.cc @@ -62,6 +62,7 @@ #include "ns3/yans-wifi-helper.h" using namespace ns3; +using namespace ns3::energy; NS_LOG_COMPONENT_DEFINE("WifiSleep"); @@ -109,23 +110,23 @@ PhyStateTrace(std::string context, Time start, Time duration, WifiPhyState state int main(int argc, char* argv[]) { - std::string dataRate = "1Mbps"; - uint32_t packetSize = 1000; // bytes - double duration = 10.0; // seconds - double initialEnergy = 7.5; // joule - double voltage = 3.0; // volts - double txPowerStart = 0.0; // dbm - double txPowerEnd = 15.0; // dbm - uint32_t nTxPowerLevels = 16; - uint32_t txPowerLevel = 0; - double idleCurrent = 0.273; // Ampere - double txCurrent = 0.380; // Ampere - bool verbose = false; + DataRate dataRate{"1Mb/s"}; + uint32_t packetSize{1000}; // bytes + Time duration{"10s"}; + double initialEnergy{7.5}; // joule + double voltage{3.0}; // volts + double txPowerStart{0.0}; // dbm + double txPowerEnd{15.0}; // dbm + uint32_t nTxPowerLevels{16}; + uint32_t txPowerLevel{0}; + double idleCurrent{0.273}; // Ampere + double txCurrent{0.380}; // Ampere + bool verbose{false}; CommandLine cmd(__FILE__); cmd.AddValue("dataRate", "Data rate", dataRate); cmd.AddValue("packetSize", "size of application packet sent", packetSize); - cmd.AddValue("duration", "duration (seconds) of the experiment", duration); + cmd.AddValue("duration", "duration of the experiment", duration); cmd.AddValue("initialEnergy", "Initial Energy (Joule) of each node", initialEnergy); cmd.AddValue("voltage", "Supply voltage (Joule)", voltage); cmd.AddValue("txPowerStart", "Minimum available transmission level (dbm)", txPowerStart); @@ -196,13 +197,13 @@ main(int argc, char* argv[]) apps = onOff.Install(c.Get(0)); apps.Start(Seconds(0.01)); - apps.Stop(Seconds(duration)); + apps.Stop(duration); // Create a packet sink to receive these packets PacketSinkHelper sink(transportProto, InetSocketAddress(Ipv4Address::GetAny(), 9001)); apps = sink.Install(c.Get(1)); apps.Start(Seconds(0.01)); - apps.Stop(Seconds(duration)); + apps.Stop(duration); // Energy sources EnergySourceContainer eSources; @@ -255,7 +256,7 @@ main(int argc, char* argv[]) Config::Connect("/NodeList/0/DeviceList/*/Phy/State/State", MakeCallback(&PhyStateTrace<0>)); Config::Connect("/NodeList/1/DeviceList/*/Phy/State/State", MakeCallback(&PhyStateTrace<1>)); - Simulator::Stop(Seconds(duration + 1)); + Simulator::Stop(duration + Seconds(1.0)); Simulator::Run(); Simulator::Destroy(); diff --git a/examples/wireless/wifi-spatial-reuse.cc b/examples/wireless/wifi-spatial-reuse.cc index 1b898f0bd1..a1905a7008 100644 --- a/examples/wireless/wifi-spatial-reuse.cc +++ b/examples/wireless/wifi-spatial-reuse.cc @@ -79,7 +79,7 @@ // thus increasing the amount of generated traffic by setting the // interval argument to a lower value is necessary to see the // benefits of spatial reuse in this scenario. This can, for -// instance, be accomplished by setting --interval=0.0001. +// instance, be accomplished by setting --interval=100us. // // Spatial reuse reset events are traced in two text files: // - wifi-spatial-reuse-resets-bss-1.txt (for STA 1) @@ -156,29 +156,29 @@ ResetTrace(std::string context, int main(int argc, char* argv[]) { - double duration = 10.0; // seconds - double d1 = 30.0; // meters - double d2 = 30.0; // meters - double d3 = 150.0; // meters - double powSta1 = 10.0; // dBm - double powSta2 = 10.0; // dBm - double powAp1 = 21.0; // dBm - double powAp2 = 21.0; // dBm - double ccaEdTrSta1 = -62; // dBm - double ccaEdTrSta2 = -62; // dBm - double ccaEdTrAp1 = -62; // dBm - double ccaEdTrAp2 = -62; // dBm - double minimumRssi = -82; // dBm - int channelWidth = 20; // MHz - uint32_t payloadSize = 1500; // bytes - uint32_t mcs = 0; // MCS value - double interval = 0.001; // seconds - bool enableObssPd = true; - double obssPdThreshold = -72.0; // dBm + Time duration{"10s"}; + double d1{30.0}; // meters + double d2{30.0}; // meters + double d3{150.0}; // meters + double powSta1{10.0}; // dBm + double powSta2{10.0}; // dBm + double powAp1{21.0}; // dBm + double powAp2{21.0}; // dBm + double ccaEdTrSta1{-62}; // dBm + double ccaEdTrSta2{-62}; // dBm + double ccaEdTrAp1{-62}; // dBm + double ccaEdTrAp2{-62}; // dBm + double minimumRssi{-82}; // dBm + int channelWidth{20}; // MHz + uint32_t payloadSize{1500}; // bytes + uint32_t mcs{0}; // MCS value + Time interval{"1ms"}; + bool enableObssPd{true}; + double obssPdThreshold{-72.0}; // dBm CommandLine cmd(__FILE__); - cmd.AddValue("duration", "Duration of simulation (s)", duration); - cmd.AddValue("interval", "Inter packet interval (s)", interval); + cmd.AddValue("duration", "Duration of simulation", duration); + cmd.AddValue("interval", "Inter packet interval", interval); cmd.AddValue("enableObssPd", "Enable/disable OBSS_PD", enableObssPd); cmd.AddValue("d1", "Distance between STA1 and AP1 (m)", d1); cmd.AddValue("d2", "Distance between STA2 and AP2 (m)", d2); @@ -330,7 +330,7 @@ main(int argc, char* argv[]) wifiStaNodes.Get(0)->AddApplication(client); client->SetAttribute("PacketSize", UintegerValue(payloadSize)); client->SetAttribute("MaxPackets", UintegerValue(0)); - client->SetAttribute("Interval", TimeValue(Seconds(interval))); + client->SetAttribute("Interval", TimeValue(interval)); Ptr server = CreateObject(); server->SetLocal(socketAddr); wifiApNodes.Get(0)->AddApplication(server); @@ -347,7 +347,7 @@ main(int argc, char* argv[]) wifiStaNodes.Get(1)->AddApplication(client); client->SetAttribute("PacketSize", UintegerValue(payloadSize)); client->SetAttribute("MaxPackets", UintegerValue(0)); - client->SetAttribute("Interval", TimeValue(Seconds(interval))); + client->SetAttribute("Interval", TimeValue(interval)); Ptr server = CreateObject(); server->SetLocal(socketAddr); wifiApNodes.Get(1)->AddApplication(server); @@ -368,14 +368,14 @@ main(int argc, char* argv[]) // Pass in the context string "2" to allow the trace to distinguish objects hePhyB->GetObssPdAlgorithm()->TraceConnect("Reset", "2", MakeCallback(&ResetTrace)); - Simulator::Stop(Seconds(duration)); + Simulator::Stop(duration); Simulator::Run(); Simulator::Destroy(); for (uint32_t i = 0; i < 2; i++) { - double throughput = static_cast(bytesReceived[2 + i]) * 8 / 1000 / 1000 / duration; + const auto throughput = bytesReceived[2 + i] * 8.0 / duration.GetMicroSeconds(); std::cout << "Throughput for BSS " << i + 1 << ": " << throughput << " Mbit/s" << std::endl; } diff --git a/examples/wireless/wifi-spectrum-per-example.cc b/examples/wireless/wifi-spectrum-per-example.cc index 931e66d4e3..fd30b6262a 100644 --- a/examples/wireless/wifi-spectrum-per-example.cc +++ b/examples/wireless/wifi-spectrum-per-example.cc @@ -64,7 +64,7 @@ // Users may vary the following command-line arguments in addition to the // attributes, global values, and default values typically available: // -// --simulationTime: Simulation time in seconds [10] +// --simulationTime: Simulation time [10s] // --udp: UDP if set to 1, TCP otherwise [true] // --distance: meters separation between nodes [50] // --index: restrict index to single value between 0 and 31 [256] @@ -128,17 +128,17 @@ NS_LOG_COMPONENT_DEFINE("WifiSpectrumPerExample"); int main(int argc, char* argv[]) { - bool udp = true; - double distance = 50; - double simulationTime = 10; // seconds - uint16_t index = 256; - std::string wifiType = "ns3::SpectrumWifiPhy"; - std::string errorModelType = "ns3::NistErrorRateModel"; - bool enablePcap = false; - const uint32_t tcpPacketSize = 1448; + bool udp{true}; + double distance{50}; + Time simulationTime{"10s"}; + uint16_t index{256}; + std::string wifiType{"ns3::SpectrumWifiPhy"}; + std::string errorModelType{"ns3::NistErrorRateModel"}; + bool enablePcap{false}; + const uint32_t tcpPacketSize{1448}; CommandLine cmd(__FILE__); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp); cmd.AddValue("distance", "meters separation between nodes", distance); cmd.AddValue("index", "restrict index to single value between 0 and 31", index); @@ -413,30 +413,10 @@ main(int argc, char* argv[]) apDevice = wifi.Install(spectrumPhy, mac, wifiApNode); } - if (i <= 7) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(false)); - } - else if (i > 7 && i <= 15) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(true)); - } - else if (i > 15 && i <= 23) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(false)); - } - else - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(true)); - } + bool shortGuardIntervalSupported = (i > 7 && i <= 15) || (i > 23); + Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" + "ShortGuardIntervalSupported", + BooleanValue(shortGuardIntervalSupported)); // mobility. MobilityHelper mobility; @@ -473,15 +453,16 @@ main(int argc, char* argv[]) UdpServerHelper server(port); serverApp = server.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / (datarate * 1e6); UdpClientHelper client(staNodeInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.0001"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } else { @@ -491,18 +472,18 @@ main(int argc, char* argv[]) PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress); serverApp = packetSinkHelper.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny()); onoff.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("PacketSize", UintegerValue(payloadSize)); - onoff.SetAttribute("DataRate", DataRateValue(1000000000)); // bit/s + onoff.SetAttribute("DataRate", DataRateValue(datarate * 1e6)); AddressValue remoteAddress(InetSocketAddress(staNodeInterface.GetAddress(0), port)); onoff.SetAttribute("Remote", remoteAddress); ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } Config::ConnectWithoutContext("/NodeList/0/DeviceList/*/Phy/MonitorSnifferRx", @@ -519,24 +500,24 @@ main(int argc, char* argv[]) g_noiseDbmAvg = 0; g_samples = 0; - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - double throughput = 0; - uint64_t totalPacketsThrough = 0; + auto throughput = 0.0; + auto totalPacketsThrough = 0.0; if (udp) { // UDP totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); throughput = - totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); // Mbit/s + totalPacketsThrough * payloadSize * 8 / simulationTime.GetMicroSeconds(); // Mbit/s } else { // TCP - uint64_t totalBytesRx = DynamicCast(serverApp.Get(0))->GetTotalRx(); + auto totalBytesRx = DynamicCast(serverApp.Get(0))->GetTotalRx(); totalPacketsThrough = totalBytesRx / tcpPacketSize; - throughput = totalBytesRx * 8 / (simulationTime * 1000000.0); // Mbit/s + throughput = totalBytesRx * 8 / simulationTime.GetMicroSeconds(); // Mbit/s } std::cout << std::setw(5) << i << std::setw(6) << (i % 8) << std::setprecision(2) << std::fixed << std::setw(10) << datarate << std::setw(12) << throughput diff --git a/examples/wireless/wifi-spectrum-per-interference.cc b/examples/wireless/wifi-spectrum-per-interference.cc index 4cc273cfd2..6e2ae44d76 100644 --- a/examples/wireless/wifi-spectrum-per-interference.cc +++ b/examples/wireless/wifi-spectrum-per-interference.cc @@ -69,7 +69,7 @@ // Users may vary the following command-line arguments in addition to the // attributes, global values, and default values typically available: // -// --simulationTime: Simulation time in seconds [10] +// --simulationTime: Simulation time [10s] // --udp: UDP if set to 1, TCP otherwise [true] // --distance: meters separation between nodes [50] // --index: restrict index to single value between 0 and 31 [256] @@ -179,18 +179,18 @@ static_SpectrumModelWifi5190MHz_initializer static_SpectrumModelWifi5190MHz_init int main(int argc, char* argv[]) { - bool udp = true; - double distance = 50; - double simulationTime = 10; // seconds - uint16_t index = 256; - std::string wifiType = "ns3::SpectrumWifiPhy"; - std::string errorModelType = "ns3::NistErrorRateModel"; - bool enablePcap = false; - const uint32_t tcpPacketSize = 1448; - double waveformPower = 0; + bool udp{true}; + double distance{50}; + Time simulationTime{"10s"}; + uint16_t index{256}; + std::string wifiType{"ns3::SpectrumWifiPhy"}; + std::string errorModelType{"ns3::NistErrorRateModel"}; + bool enablePcap{false}; + const uint32_t tcpPacketSize{1448}; + double waveformPower{0}; CommandLine cmd(__FILE__); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp); cmd.AddValue("distance", "meters separation between nodes", distance); cmd.AddValue("index", "restrict index to single value between 0 and 31", index); @@ -468,30 +468,10 @@ main(int argc, char* argv[]) apDevice = wifi.Install(spectrumPhy, mac, wifiApNode); } - if (i <= 7) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(false)); - } - else if (i > 7 && i <= 15) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(true)); - } - else if (i > 15 && i <= 23) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(false)); - } - else - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(true)); - } + bool shortGuardIntervalSupported = (i > 7 && i <= 15) || (i > 23); + Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" + "ShortGuardIntervalSupported", + BooleanValue(shortGuardIntervalSupported)); // mobility. MobilityHelper mobility; @@ -530,15 +510,16 @@ main(int argc, char* argv[]) UdpServerHelper server(port); serverApp = server.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / (datarate * 1e6); UdpClientHelper client(staNodeInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.0001"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } else { @@ -548,18 +529,18 @@ main(int argc, char* argv[]) PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress); serverApp = packetSinkHelper.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny()); onoff.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]")); onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("PacketSize", UintegerValue(payloadSize)); - onoff.SetAttribute("DataRate", DataRateValue(1000000000)); // bit/s + onoff.SetAttribute("DataRate", DataRateValue(datarate * 1e6)); AddressValue remoteAddress(InetSocketAddress(staNodeInterface.GetAddress(0), port)); onoff.SetAttribute("Remote", remoteAddress); ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } // Configure waveform generator @@ -623,24 +604,24 @@ main(int argc, char* argv[]) "Error: Wi-Fi nodes must be tuned to 5190 MHz to match the waveform generator"); } - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - double throughput = 0; - uint64_t totalPacketsThrough = 0; + auto throughput = 0.0; + auto totalPacketsThrough = 0.0; if (udp) { // UDP totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); throughput = - totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); // Mbit/s + totalPacketsThrough * payloadSize * 8 / simulationTime.GetMicroSeconds(); // Mbit/s } else { // TCP - uint64_t totalBytesRx = DynamicCast(serverApp.Get(0))->GetTotalRx(); + auto totalBytesRx = DynamicCast(serverApp.Get(0))->GetTotalRx(); totalPacketsThrough = totalBytesRx / tcpPacketSize; - throughput = totalBytesRx * 8 / (simulationTime * 1000000.0); // Mbit/s + throughput = totalBytesRx * 8 / simulationTime.GetMicroSeconds(); // Mbit/s } std::cout << std::setw(5) << i << std::setw(6) << (i % 8) << std::setprecision(2) << std::fixed << std::setw(10) << datarate << std::setw(12) << throughput diff --git a/examples/wireless/wifi-spectrum-saturation-example.cc b/examples/wireless/wifi-spectrum-saturation-example.cc index c329c8c093..11dd672632 100644 --- a/examples/wireless/wifi-spectrum-saturation-example.cc +++ b/examples/wireless/wifi-spectrum-saturation-example.cc @@ -60,7 +60,7 @@ // Users may vary the following command-line arguments in addition to the // attributes, global values, and default values typically available: // -// --simulationTime: Simulation time in seconds [10] +// --simulationTime: Simulation time [10s] // --distance: meters separation between nodes [1] // --index: restrict index to single value between 0 and 31 [256] // --wifiType: select ns3::SpectrumWifiPhy or ns3::YansWifiPhy [ns3::SpectrumWifiPhy] @@ -100,16 +100,16 @@ NS_LOG_COMPONENT_DEFINE("WifiSpectrumSaturationExample"); int main(int argc, char* argv[]) { - double distance = 1; - double simulationTime = 10; // seconds - uint16_t index = 256; - uint32_t channelWidth = 0; - std::string wifiType = "ns3::SpectrumWifiPhy"; - std::string errorModelType = "ns3::NistErrorRateModel"; - bool enablePcap = false; + double distance{1}; + Time simulationTime{"10s"}; + uint16_t index{256}; + uint32_t channelWidth{0}; + std::string wifiType{"ns3::SpectrumWifiPhy"}; + std::string errorModelType{"ns3::NistErrorRateModel"}; + bool enablePcap{false}; CommandLine cmd(__FILE__); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("distance", "meters separation between nodes", distance); cmd.AddValue("index", "restrict index to single value between 0 and 63", index); cmd.AddValue("wifiType", "select ns3::SpectrumWifiPhy or ns3::YansWifiPhy", wifiType); @@ -152,25 +152,7 @@ main(int argc, char* argv[]) phy.Set("TxPowerStart", DoubleValue(1)); phy.Set("TxPowerEnd", DoubleValue(1)); - if (i > 31 && i <= 39) - { - phy.Set("Antennas", UintegerValue(2)); - phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); - phy.Set("MaxSupportedRxSpatialStreams", UintegerValue(2)); - } - else if (i > 39 && i <= 47) - { - phy.Set("Antennas", UintegerValue(2)); - phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); - phy.Set("MaxSupportedRxSpatialStreams", UintegerValue(2)); - } - else if (i > 47 && i <= 55) - { - phy.Set("Antennas", UintegerValue(2)); - phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); - phy.Set("MaxSupportedRxSpatialStreams", UintegerValue(2)); - } - else if (i > 55 && i <= 63) + if (i > 31 && i <= 63) { phy.Set("Antennas", UintegerValue(2)); phy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); @@ -193,25 +175,7 @@ main(int argc, char* argv[]) spectrumPhy.Set("TxPowerStart", DoubleValue(1)); spectrumPhy.Set("TxPowerEnd", DoubleValue(1)); - if (i > 31 && i <= 39) - { - spectrumPhy.Set("Antennas", UintegerValue(2)); - spectrumPhy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); - spectrumPhy.Set("MaxSupportedRxSpatialStreams", UintegerValue(2)); - } - else if (i > 39 && i <= 47) - { - spectrumPhy.Set("Antennas", UintegerValue(2)); - spectrumPhy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); - spectrumPhy.Set("MaxSupportedRxSpatialStreams", UintegerValue(2)); - } - else if (i > 47 && i <= 55) - { - spectrumPhy.Set("Antennas", UintegerValue(2)); - spectrumPhy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); - spectrumPhy.Set("MaxSupportedRxSpatialStreams", UintegerValue(2)); - } - else if (i > 55 && i <= 63) + if (i > 31 && i <= 63) { spectrumPhy.Set("Antennas", UintegerValue(2)); spectrumPhy.Set("MaxSupportedTxSpatialStreams", UintegerValue(2)); @@ -588,30 +552,11 @@ main(int argc, char* argv[]) apDevice = wifi.Install(spectrumPhy, mac, wifiApNode); } - if ((i <= 7) || (i > 31 && i <= 39)) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(false)); - } - else if ((i > 7 && i <= 15) || (i > 39 && i <= 47)) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(true)); - } - else if ((i > 15 && i <= 23) || (i > 47 && i <= 55)) - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(false)); - } - else - { - Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" - "ShortGuardIntervalSupported", - BooleanValue(true)); - } + bool shortGuardIntervalSupported = + (i > 7 && i <= 15) || (i > 23 && i <= 31) || (i > 39 && i <= 47) || (i > 55); + Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/HtConfiguration/" + "ShortGuardIntervalSupported", + BooleanValue(shortGuardIntervalSupported)); // mobility. MobilityHelper mobility; @@ -644,15 +589,16 @@ main(int argc, char* argv[]) UdpServerHelper server(port); ApplicationContainer serverApp = server.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / (datarate * 1e6); UdpClientHelper client(staNodeInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.0001"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); if (enablePcap) { @@ -662,13 +608,12 @@ main(int argc, char* argv[]) phy.EnablePcap(ss.str(), apDevice); } - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - double throughput; - uint64_t totalPacketsThrough; - totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); - throughput = totalPacketsThrough * payloadSize * 8 / (simulationTime * 1000000.0); // Mbit/s + double totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); + auto throughput = + totalPacketsThrough * payloadSize * 8 / simulationTime.GetMicroSeconds(); // Mbit/s std::cout << std::setw(5) << i << std::setw(6) << (i % 8) + 8 * (i / 32) << std::setw(8) << channelWidth << std::setw(10) << datarate << std::setw(12) << throughput << std::setw(8) << totalPacketsThrough << std::endl; diff --git a/examples/wireless/wifi-tcp.cc b/examples/wireless/wifi-tcp.cc index 2cd2c08519..ca2c6b64b6 100644 --- a/examples/wireless/wifi-tcp.cc +++ b/examples/wireless/wifi-tcp.cc @@ -72,12 +72,12 @@ CalculateThroughput() int main(int argc, char* argv[]) { - uint32_t payloadSize = 1472; /* Transport layer payload size in bytes. */ - std::string dataRate = "100Mbps"; /* Application layer datarate. */ - std::string tcpVariant = "TcpNewReno"; /* TCP variant type. */ - std::string phyRate = "HtMcs7"; /* Physical layer bitrate. */ - double simulationTime = 10; /* Simulation time in seconds. */ - bool pcapTracing = false; /* PCAP Tracing is enabled or not. */ + uint32_t payloadSize{1472}; /* Transport layer payload size in bytes. */ + DataRate dataRate{"100Mb/s"}; /* Application layer datarate. */ + std::string tcpVariant{"TcpNewReno"}; /* TCP variant type. */ + std::string phyRate{"HtMcs7"}; /* Physical layer bitrate. */ + Time simulationTime{"10s"}; /* Simulation time. */ + bool pcapTracing{false}; /* PCAP Tracing is enabled or not. */ /* Command line argument parser setup. */ CommandLine cmd(__FILE__); @@ -194,10 +194,11 @@ main(int argc, char* argv[]) } /* Start Simulation */ - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - double averageThroughput = ((sink->GetTotalRx() * 8) / (1e6 * simulationTime)); + auto averageThroughput = + (static_cast(sink->GetTotalRx() * 8) / simulationTime.GetMicroSeconds()); Simulator::Destroy(); diff --git a/examples/wireless/wifi-timing-attributes.cc b/examples/wireless/wifi-timing-attributes.cc index bd55cbe7d3..bfc8948468 100644 --- a/examples/wireless/wifi-timing-attributes.cc +++ b/examples/wireless/wifi-timing-attributes.cc @@ -57,16 +57,16 @@ NS_LOG_COMPONENT_DEFINE("wifi-timing-attributes"); int main(int argc, char* argv[]) { - uint32_t slot = 9; // slot time in microseconds - uint32_t sifs = 10; // SIFS duration in microseconds - uint32_t pifs = 19; // PIFS duration in microseconds - double simulationTime = 10; // simulation time in seconds + uint32_t slot{9}; // slot time in microseconds + uint32_t sifs{10}; // SIFS duration in microseconds + uint32_t pifs{19}; // PIFS duration in microseconds + Time simulationTime{"10s"}; // Simulation time CommandLine cmd(__FILE__); cmd.AddValue("slot", "Slot time in microseconds", slot); cmd.AddValue("sifs", "SIFS duration in microseconds", sifs); cmd.AddValue("pifs", "PIFS duration in microseconds", pifs); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.Parse(argc, argv); // Since default reference loss is defined for 5 GHz, it needs to be changed when operating @@ -146,7 +146,7 @@ main(int argc, char* argv[]) UdpServerHelper server(port); ApplicationContainer serverApp = server.Install(wifiStaNode.Get(0)); serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); UdpClientHelper client(staNodeInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -155,18 +155,18 @@ main(int argc, char* argv[]) ApplicationContainer clientApp = client.Install(wifiApNode.Get(0)); clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); // Populate routing table Ipv4GlobalRoutingHelper::PopulateRoutingTables(); // Set simulation time and launch simulation - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); // Get and print results - uint64_t totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); - double throughput = totalPacketsThrough * 1472 * 8 / (simulationTime * 1000000.0); // Mbit/s + double totalPacketsThrough = DynamicCast(serverApp.Get(0))->GetReceived(); + auto throughput = totalPacketsThrough * 1472 * 8 / simulationTime.GetMicroSeconds(); // Mbit/s std::cout << "Throughput: " << throughput << " Mbit/s" << std::endl; Simulator::Destroy(); diff --git a/examples/wireless/wifi-txop-aggregation.cc b/examples/wireless/wifi-txop-aggregation.cc index beb15628bd..0b63ac4e4b 100644 --- a/examples/wireless/wifi-txop-aggregation.cc +++ b/examples/wireless/wifi-txop-aggregation.cc @@ -59,7 +59,7 @@ // // The user can select the distance between the stations and the APs, can enable/disable the RTS/CTS // mechanism and can modify the duration of a TXOP. Example: ./ns3 run "wifi-txop-aggregation -// --distance=10 --enableRts=0 --simulationTime=20" +// --distance=10 --enableRts=0 --simulationTime=20s" // // The output prints the throughput and the maximum TXOP duration measured for the 4 cases/networks // described above. When default aggregation parameters are enabled, the @@ -108,19 +108,19 @@ TxopDurationTracer::Trace(Time startTime, Time duration, uint8_t linkId) int main(int argc, char* argv[]) { - uint32_t payloadSize = 1472; // bytes - double simulationTime = 10; // seconds - double txopLimit = 3520; // microseconds - double distance = 5; // meters - bool enableRts = false; - bool enablePcap = false; - bool verifyResults = false; // used for regression + uint32_t payloadSize{1472}; // bytes + Time simulationTime{"10s"}; + double txopLimit{3520}; // microseconds + double distance{5}; // meters + bool enableRts{false}; + bool enablePcap{false}; + bool verifyResults{false}; // used for regression CommandLine cmd(__FILE__); cmd.AddValue("payloadSize", "Payload size in bytes", payloadSize); cmd.AddValue("enableRts", "Enable or disable RTS/CTS", enableRts); cmd.AddValue("txopLimit", "TXOP duration in microseconds", txopLimit); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("distance", "Distance in meters between the station and the access point", distance); @@ -173,6 +173,8 @@ main(int argc, char* argv[]) SsidValue(ssid), "EnableBeaconJitter", BooleanValue(false)); + // Modify EDCA configuration (TXOP limit) for AC_BE + mac.SetEdca(AC_BE, "TxopLimits", StringValue(std::to_string(txopLimit) + "us")); apDeviceA = wifi.Install(phy, mac, wifiApNodes.Get(0)); // Modify EDCA configuration (TXOP limit) for AC_BE @@ -182,7 +184,6 @@ main(int argc, char* argv[]) Ptr edca; wifi_dev->GetMac()->GetAttribute("BE_Txop", ptr); edca = ptr.Get(); - edca->SetTxopLimit(MicroSeconds(txopLimit)); // Trace TXOP duration for BE on AP A TxopDurationTracer netA; @@ -205,6 +206,8 @@ main(int argc, char* argv[]) SsidValue(ssid), "EnableBeaconJitter", BooleanValue(false)); + // Modify EDCA configuration (TXOP limit) for AC_BE + mac.SetEdca(AC_BE, "TxopLimits", StringValue(std::to_string(txopLimit) + "us")); apDeviceB = wifi.Install(phy, mac, wifiApNodes.Get(1)); // Disable A-MPDU @@ -212,10 +215,8 @@ main(int argc, char* argv[]) wifi_dev = DynamicCast(dev); wifi_dev->GetMac()->SetAttribute("BE_MaxAmpduSize", UintegerValue(0)); - // Modify EDCA configuration (TXOP limit) for AC_BE wifi_dev->GetMac()->GetAttribute("BE_Txop", ptr); edca = ptr.Get(); - edca->SetTxopLimit(MicroSeconds(txopLimit)); // Trace TXOP duration for BE on AP B TxopDurationTracer netB; @@ -240,6 +241,8 @@ main(int argc, char* argv[]) SsidValue(ssid), "EnableBeaconJitter", BooleanValue(false)); + // Modify EDCA configuration (TXOP limit) for AC_BE + mac.SetEdca(AC_BE, "TxopLimits", StringValue(std::to_string(txopLimit) + "us")); apDeviceC = wifi.Install(phy, mac, wifiApNodes.Get(2)); // Disable A-MPDU and enable A-MSDU with the highest maximum size allowed by the standard (7935 @@ -249,10 +252,8 @@ main(int argc, char* argv[]) wifi_dev->GetMac()->SetAttribute("BE_MaxAmpduSize", UintegerValue(0)); wifi_dev->GetMac()->SetAttribute("BE_MaxAmsduSize", UintegerValue(7935)); - // Modify EDCA configuration (TXOP limit) for AC_BE wifi_dev->GetMac()->GetAttribute("BE_Txop", ptr); edca = ptr.Get(); - edca->SetTxopLimit(MicroSeconds(txopLimit)); // Trace TXOP duration for BE on AP C TxopDurationTracer netC; @@ -277,6 +278,8 @@ main(int argc, char* argv[]) SsidValue(ssid), "EnableBeaconJitter", BooleanValue(false)); + // Modify EDCA configuration (TXOP limit) for AC_BE + mac.SetEdca(AC_BE, "TxopLimits", StringValue(std::to_string(txopLimit) + "us")); apDeviceD = wifi.Install(phy, mac, wifiApNodes.Get(3)); // Enable A-MPDU with a smaller size than the default one and @@ -286,10 +289,8 @@ main(int argc, char* argv[]) wifi_dev->GetMac()->SetAttribute("BE_MaxAmpduSize", UintegerValue(32768)); wifi_dev->GetMac()->SetAttribute("BE_MaxAmsduSize", UintegerValue(3839)); - // Modify EDCA configuration (TXOP limit) for AC_BE wifi_dev->GetMac()->GetAttribute("BE_Txop", ptr); edca = ptr.Get(); - edca->SetTxopLimit(MicroSeconds(txopLimit)); // Trace TXOP duration for BE on AP D TxopDurationTracer netD; @@ -350,7 +351,7 @@ main(int argc, char* argv[]) UdpServerHelper serverA(port); ApplicationContainer serverAppA = serverA.Install(wifiStaNodes.Get(0)); serverAppA.Start(Seconds(0.0)); - serverAppA.Stop(Seconds(simulationTime + 1)); + serverAppA.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientA(StaInterfaceA.GetAddress(0), port); clientA.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -359,12 +360,12 @@ main(int argc, char* argv[]) ApplicationContainer clientAppA = clientA.Install(wifiApNodes.Get(0)); clientAppA.Start(Seconds(1.0)); - clientAppA.Stop(Seconds(simulationTime + 1)); + clientAppA.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverB(port); ApplicationContainer serverAppB = serverB.Install(wifiStaNodes.Get(1)); serverAppB.Start(Seconds(0.0)); - serverAppB.Stop(Seconds(simulationTime + 1)); + serverAppB.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientB(StaInterfaceB.GetAddress(0), port); clientB.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -373,12 +374,12 @@ main(int argc, char* argv[]) ApplicationContainer clientAppB = clientB.Install(wifiApNodes.Get(1)); clientAppB.Start(Seconds(1.0)); - clientAppB.Stop(Seconds(simulationTime + 1)); + clientAppB.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverC(port); ApplicationContainer serverAppC = serverC.Install(wifiStaNodes.Get(2)); serverAppC.Start(Seconds(0.0)); - serverAppC.Stop(Seconds(simulationTime + 1)); + serverAppC.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientC(StaInterfaceC.GetAddress(0), port); clientC.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -387,12 +388,12 @@ main(int argc, char* argv[]) ApplicationContainer clientAppC = clientC.Install(wifiApNodes.Get(2)); clientAppC.Start(Seconds(1.0)); - clientAppC.Stop(Seconds(simulationTime + 1)); + clientAppC.Stop(simulationTime + Seconds(1.0)); UdpServerHelper serverD(port); ApplicationContainer serverAppD = serverD.Install(wifiStaNodes.Get(3)); serverAppD.Start(Seconds(0.0)); - serverAppD.Stop(Seconds(simulationTime + 1)); + serverAppD.Stop(simulationTime + Seconds(1.0)); UdpClientHelper clientD(StaInterfaceD.GetAddress(0), port); clientD.SetAttribute("MaxPackets", UintegerValue(4294967295U)); @@ -401,7 +402,7 @@ main(int argc, char* argv[]) ApplicationContainer clientAppD = clientD.Install(wifiApNodes.Get(3)); clientAppD.Start(Seconds(1.0)); - clientAppD.Stop(Seconds(simulationTime + 1)); + clientAppD.Stop(simulationTime + Seconds(1.0)); if (enablePcap) { @@ -415,18 +416,18 @@ main(int argc, char* argv[]) phy.EnablePcap("STA_D", staDeviceD.Get(0)); } - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); // Show results - uint64_t totalPacketsThroughA = DynamicCast(serverAppA.Get(0))->GetReceived(); - uint64_t totalPacketsThroughB = DynamicCast(serverAppB.Get(0))->GetReceived(); - uint64_t totalPacketsThroughC = DynamicCast(serverAppC.Get(0))->GetReceived(); - uint64_t totalPacketsThroughD = DynamicCast(serverAppD.Get(0))->GetReceived(); + double totalPacketsThroughA = DynamicCast(serverAppA.Get(0))->GetReceived(); + double totalPacketsThroughB = DynamicCast(serverAppB.Get(0))->GetReceived(); + double totalPacketsThroughC = DynamicCast(serverAppC.Get(0))->GetReceived(); + double totalPacketsThroughD = DynamicCast(serverAppD.Get(0))->GetReceived(); Simulator::Destroy(); - double throughput = totalPacketsThroughA * payloadSize * 8 / (simulationTime * 1000000.0); + auto throughput = totalPacketsThroughA * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "Default configuration (A-MPDU aggregation enabled, 65kB): " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 57.5 || throughput > 58.5)) @@ -447,7 +448,7 @@ main(int argc, char* argv[]) } } - throughput = totalPacketsThroughB * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughB * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "Aggregation disabled: " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 38 || throughput > 39)) @@ -467,7 +468,7 @@ main(int argc, char* argv[]) } } - throughput = totalPacketsThroughC * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughC * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "A-MPDU disabled and A-MSDU enabled (8kB): " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 52 || throughput > 53)) @@ -487,7 +488,7 @@ main(int argc, char* argv[]) } } - throughput = totalPacketsThroughD * payloadSize * 8 / (simulationTime * 1000000.0); + throughput = totalPacketsThroughD * payloadSize * 8 / simulationTime.GetMicroSeconds(); std::cout << "A-MPDU enabled (32kB) and A-MSDU enabled (4kB): " << '\n' << " Throughput = " << throughput << " Mbit/s" << '\n'; if (verifyResults && (throughput < 58 || throughput > 59)) diff --git a/examples/wireless/wifi-vht-network.cc b/examples/wireless/wifi-vht-network.cc index 34837f73b0..df9b854735 100644 --- a/examples/wireless/wifi-vht-network.cc +++ b/examples/wireless/wifi-vht-network.cc @@ -62,19 +62,19 @@ NS_LOG_COMPONENT_DEFINE("vht-wifi-network"); int main(int argc, char* argv[]) { - bool udp = true; - bool useRts = false; - double simulationTime = 10; // seconds - double distance = 1.0; // meters - int mcs = -1; // -1 indicates an unset value - double minExpectedThroughput = 0; - double maxExpectedThroughput = 0; + bool udp{true}; + bool useRts{false}; + Time simulationTime{"10s"}; + double distance{1.0}; // meters + int mcs{-1}; // -1 indicates an unset value + double minExpectedThroughput{0.0}; + double maxExpectedThroughput{0.0}; CommandLine cmd(__FILE__); cmd.AddValue("distance", "Distance in meters between the station and the access point", distance); - cmd.AddValue("simulationTime", "Simulation time in seconds", simulationTime); + cmd.AddValue("simulationTime", "Simulation time", simulationTime); cmd.AddValue("udp", "UDP if set to 1, TCP otherwise", udp); cmd.AddValue("useRts", "Enable/disable RTS/CTS", useRts); cmd.AddValue("mcs", "if set, limit testing to a specific MCS (0-9)", mcs); @@ -178,6 +178,10 @@ main(int argc, char* argv[]) NetDeviceContainer apDevice; apDevice = wifi.Install(phy, mac, wifiApNode); + int64_t streamNumber = 150; + streamNumber += wifi.AssignStreams(apDevice, streamNumber); + streamNumber += wifi.AssignStreams(staDevice, streamNumber); + // mobility. MobilityHelper mobility; Ptr positionAlloc = CreateObject(); @@ -195,6 +199,8 @@ main(int argc, char* argv[]) InternetStackHelper stack; stack.Install(wifiApNode); stack.Install(wifiStaNode); + streamNumber += stack.AssignStreams(wifiApNode, streamNumber); + streamNumber += stack.AssignStreams(wifiStaNode, streamNumber); Ipv4AddressHelper address; address.SetBase("192.168.1.0", "255.255.255.0"); @@ -205,6 +211,7 @@ main(int argc, char* argv[]) apNodeInterface = address.Assign(apDevice); /* Setting applications */ + const auto maxLoad = VhtPhy::GetDataRate(mcs, channelWidth, sgi ? 400 : 800, 1); ApplicationContainer serverApp; if (udp) { @@ -212,16 +219,21 @@ main(int argc, char* argv[]) uint16_t port = 9; UdpServerHelper server(port); serverApp = server.Install(wifiStaNode.Get(0)); + streamNumber += server.AssignStreams(wifiStaNode.Get(0), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); + const auto packetInterval = payloadSize * 8.0 / maxLoad; UdpClientHelper client(staNodeInterface.GetAddress(0), port); client.SetAttribute("MaxPackets", UintegerValue(4294967295U)); - client.SetAttribute("Interval", TimeValue(Time("0.00002"))); // packets/s + client.SetAttribute("Interval", TimeValue(Seconds(packetInterval))); client.SetAttribute("PacketSize", UintegerValue(payloadSize)); ApplicationContainer clientApp = client.Install(wifiApNode.Get(0)); + streamNumber += client.AssignStreams(wifiApNode.Get(0), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } else { @@ -230,8 +242,11 @@ main(int argc, char* argv[]) Address localAddress(InetSocketAddress(Ipv4Address::GetAny(), port)); PacketSinkHelper packetSinkHelper("ns3::TcpSocketFactory", localAddress); serverApp = packetSinkHelper.Install(wifiStaNode.Get(0)); + streamNumber += + packetSinkHelper.AssignStreams(wifiStaNode.Get(0), streamNumber); + serverApp.Start(Seconds(0.0)); - serverApp.Stop(Seconds(simulationTime + 1)); + serverApp.Stop(simulationTime + Seconds(1.0)); OnOffHelper onoff("ns3::TcpSocketFactory", Ipv4Address::GetAny()); onoff.SetAttribute("OnTime", @@ -239,21 +254,23 @@ main(int argc, char* argv[]) onoff.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]")); onoff.SetAttribute("PacketSize", UintegerValue(payloadSize)); - onoff.SetAttribute("DataRate", DataRateValue(1000000000)); // bit/s + onoff.SetAttribute("DataRate", DataRateValue(maxLoad)); AddressValue remoteAddress( InetSocketAddress(staNodeInterface.GetAddress(0), port)); onoff.SetAttribute("Remote", remoteAddress); ApplicationContainer clientApp = onoff.Install(wifiApNode.Get(0)); + streamNumber += onoff.AssignStreams(wifiApNode.Get(0), streamNumber); + clientApp.Start(Seconds(1.0)); - clientApp.Stop(Seconds(simulationTime + 1)); + clientApp.Stop(simulationTime + Seconds(1.0)); } Ipv4GlobalRoutingHelper::PopulateRoutingTables(); - Simulator::Stop(Seconds(simulationTime + 1)); + Simulator::Stop(simulationTime + Seconds(1.0)); Simulator::Run(); - uint64_t rxBytes = 0; + auto rxBytes = 0.0; if (udp) { rxBytes = payloadSize * DynamicCast(serverApp.Get(0))->GetReceived(); @@ -262,7 +279,7 @@ main(int argc, char* argv[]) { rxBytes = DynamicCast(serverApp.Get(0))->GetTotalRx(); } - double throughput = (rxBytes * 8) / (simulationTime * 1000000.0); // Mbit/s + auto throughput = (rxBytes * 8) / simulationTime.GetMicroSeconds(); // Mbit/s Simulator::Destroy(); @@ -270,7 +287,7 @@ main(int argc, char* argv[]) << sgi << "\t\t\t" << throughput << " Mbit/s" << std::endl; // test first element - if (mcs == 0 && channelWidth == 20 && !sgi) + if (mcs == minMcs && channelWidth == 20 && !sgi) { if (throughput < minExpectedThroughput) { @@ -279,7 +296,7 @@ main(int argc, char* argv[]) } } // test last element - if (mcs == 9 && channelWidth == 160 && sgi) + if (mcs == maxMcs && channelWidth == 160 && sgi) { if (maxExpectedThroughput > 0 && throughput > maxExpectedThroughput) { diff --git a/ns3 b/ns3 index e332457093..fcdca5f46f 100755 --- a/ns3 +++ b/ns3 @@ -10,7 +10,7 @@ import shutil import subprocess import sys -ns3_path = os.path.dirname(os.path.abspath(__file__)) +ns3_path = os.path.dirname(os.path.realpath(os.path.abspath(__file__))) append_to_ns3_path = functools.partial(os.path.join, ns3_path) out_dir = os.sep.join([ns3_path, "build"]) lock_file = os.sep.join([ns3_path, ".lock-ns3_%s_build" % sys.platform]) @@ -619,7 +619,7 @@ def print_and_buffer(message): def remove_dir(dir_to_remove, dry_run, directory_qualifier=""): - dir_to_remove = os.path.abspath(dir_to_remove) + dir_to_remove = os.path.realpath(os.path.abspath(dir_to_remove)) if os.path.exists(dir_to_remove): if ".." in os.path.relpath(dir_to_remove, ns3_path) or os.path.abspath( dir_to_remove @@ -646,6 +646,7 @@ def remove_dir(dir_to_remove, dry_run, directory_qualifier=""): def remove_file(file_to_remove, dry_run): + file_to_remove = os.path.realpath(file_to_remove) if os.path.exists(file_to_remove): print_and_buffer("rm -R %s" % os.path.relpath(file_to_remove, ns3_path)) if not dry_run: @@ -1227,7 +1228,7 @@ def get_target_to_build(program_path, ns3_version, build_profile): print("Target to build does not exist: %s" % program_path) exit(1) - if "scratch" in program_path: + if "scratch" in os.path.relpath(program_path, ns3_path): # Get the path to the program and replace slashes with underlines # to get unique targets for CMake, preventing collisions with modules examples return program_name.replace(out_dir, "").replace("/", "_")[1:] @@ -1414,6 +1415,9 @@ def run_step(args, target_to_run, target_args): debugging_software.extend( [check_program_installed("valgrind"), "--leak-check=full", "--show-leak-kinds=all"] ) + suppressions_file = os.path.join(ns3_path, ".ns3.supp") + if os.path.exists(suppressions_file): + debugging_software.append(f"--suppressions={suppressions_file}") # running gdb? if args.gdb: diff --git a/pyproject.toml b/pyproject.toml index 18b1293c1b..7547794108 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = [ "setuptools>=45", "setuptools_scm[toml]>=6.0", "cmake-build-extension>=0.4", - "cppyy==2.4.2", + "cppyy==3.1.2", ] [tool.setuptools_scm] diff --git a/setup.cfg b/setup.cfg index 679a7d3d95..342e29711b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -40,5 +40,5 @@ classifiers = zip_safe = False python_requires = >=3.6 install_requires = - cppyy==2.4.2 + cppyy==3.1.2 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d72e049a32..52f65e9f80 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,6 +21,38 @@ foreach(libname ${libs}) endif() endforeach() +# Scan for disabled modules that define settings prefixed with NS3_ or ENABLE_ +# so that we can initialize them as turned off (setting as temporary variables +# not to affect the cached variables that are set when normally processed) +subdirlist(modules ${CMAKE_CURRENT_SOURCE_DIR}) +foreach(libname ${modules}) + if(NOT (${libname} IN_LIST libs)) + # Skip module directories without CMakeLists.txt files + if(NOT (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${libname}/CMakeLists.txt)) + continue() + endif() + + file(READ ${CMAKE_CURRENT_SOURCE_DIR}/${libname}/CMakeLists.txt + lib_cmakelists_contents + ) + string(REGEX MATCHALL "(NS3_[a-zA-Z0-9_]*)|(ENABLE_[a-zA-Z0-9_]*)" flags + "${lib_cmakelists_contents}" + ) + foreach(flag ${flags}) + # Skip reason flags + if(${flag} MATCHES "REASON") + continue() + endif() + # Skip flags already defined + if(DEFINED ${flag}) + continue() + endif() + # Set flag to off + set(${flag} OFF PARENT_SCOPE) + endforeach() + endif() +endforeach() + # Prevents link errors due to symbol collisions if the same library is linked # multiple times list(REMOVE_DUPLICATES ns3-external-libs) diff --git a/src/antenna/CMakeLists.txt b/src/antenna/CMakeLists.txt index 5c38a8cf4b..86c442b4ea 100644 --- a/src/antenna/CMakeLists.txt +++ b/src/antenna/CMakeLists.txt @@ -1,6 +1,61 @@ +# Check for dependencies and add sources accordingly +check_cxx_source_compiles( + "#include + int main() + { + return std::cyl_bessel_j(1, 1); + }" + HAVE_STD_BESSEL_FUNC +) + +set(circular_aperture_antenna_sources) +set(circular_aperture_antenna_headers) +set(circular_aperture_antenna_test_sources) + +if(${HAVE_STD_BESSEL_FUNC}) + set(circular_aperture_antenna_sources + model/circular-aperture-antenna-model.cc + ) + set(circular_aperture_antenna_headers + model/circular-aperture-antenna-model.h + ) + set(circular_aperture_antenna_test_sources + test/test-circular-aperture-antenna.cc + ) + message(STATUS "Standard library Bessel function has been found") +else() + check_include_files( + "boost/math/special_functions/bessel.hpp" + HAVE_BOOST_BESSEL_FUNC + LANGUAGE + CXX + ) + if(${HAVE_BOOST_BESSEL_FUNC}) + set(circular_aperture_antenna_sources + model/circular-aperture-antenna-model.cc + ) + set(circular_aperture_antenna_headers + model/circular-aperture-antenna-model.h + ) + set(circular_aperture_antenna_test_sources + test/test-circular-aperture-antenna.cc + ) + add_definitions(-DNEED_AND_HAVE_BOOST_BESSEL_FUNC) + message(STATUS "Boost Bessel function has been found.") + else() + message( + STATUS + "Boost Bessel function is required for CircularApertureAntennaModel" + " on platforms using Clang libc++ such as macOS." + " You may need to clean up the CMake cache after installing it to pass this check." + ) + endif() +endif() + build_lib( LIBNAME antenna SOURCE_FILES + ${circular_aperture_antenna_sources} model/angles.cc model/antenna-model.cc model/cosine-antenna-model.cc @@ -10,6 +65,7 @@ build_lib( model/three-gpp-antenna-model.cc model/uniform-planar-array.cc HEADER_FILES + ${circular_aperture_antenna_headers} model/angles.h model/antenna-model.h model/cosine-antenna-model.h @@ -20,10 +76,11 @@ build_lib( model/uniform-planar-array.h LIBRARIES_TO_LINK ${libcore} TEST_SOURCES + ${circular_aperture_antenna_test_sources} test/test-angles.cc + test/test-cosine-antenna.cc test/test-degrees-radians.cc test/test-isotropic-antenna.cc - test/test-cosine-antenna.cc test/test-parabolic-antenna.cc test/test-uniform-planar-array.cc ) diff --git a/src/antenna/doc/Makefile b/src/antenna/doc/Makefile index 5584732f99..5de021d3a5 100644 --- a/src/antenna/doc/Makefile +++ b/src/antenna/doc/Makefile @@ -40,7 +40,7 @@ GRAPHS = $(GRAPHS_EPS) $(GRAPHS_PNG) $(GRAPHS_PDF) @if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build diff --git a/src/antenna/doc/source/antenna-design.rst b/src/antenna/doc/source/antenna-design.rst index 3d30873875..1581d9296e 100644 --- a/src/antenna/doc/source/antenna-design.rst +++ b/src/antenna/doc/source/antenna-design.rst @@ -113,7 +113,9 @@ pattern. ParabolicAntennaModel +++++++++++++++++++++ -This model is based on the parabolic approximation of the main lobe radiation pattern. It is often used in the context of cellular system to model the radiation pattern of a cell sector, see for instance [R4-092042a]_ and [Calcev]_. The antenna gain in dB is determined as: +This model is based on the parabolic approximation of the main lobe radiation pattern. It is often +used in the context of cellular system to model the radiation pattern of a cell sector, see for +instance [R4-092042a]_ and [Calcev]_. The antenna gain in dB is determined as: .. math:: @@ -174,7 +176,7 @@ and vertical elements can be configured through the attributes "AntennaHorizonta and "AntennaVerticalSpacing". UniformPlannarArray supports the concept of antenna ports following the sub-array partition -model for TXRU virtualization, as described in Section 5.2.2 of 3GPP TR 36.897 [36897]_. +model for TXRU virtualization, as described in Section 5.2.2 of 3GPP TR 36.897 [3GPP_TR36897]_. The number of antenna ports in vertical and horizontal directions can be configured through the attributes "NumVerticalPorts" and "NumHorizontalPorts", respectively. For example, if "NumRows" and "NumColumns" are configured to 2 and 4, and the number of @@ -192,6 +194,40 @@ are configured through the attribute "PolSlantAngle"; while the antenna elements the second polarization have the polarization slant angle minus 90 degrees, as described in [38901]_ (i.e., :math:`{\zeta}`). +CircularApertureAntennaModel +++++++++++++++++++++++++++++ + +The class CircularApertureAntennaModel implements the radiation pattern described in [38811]_. +Specifically, the latter represents parabolic antennas, i.e., antennas which are typically used +for achieving long range communications such as earth-to-satellite links. +The default boresight orientation is parallel to the positive z-axis, and it can be tuned by +using the AntennaInclination and AntennaAzimuth parameters. +This implementation provides an exact characterization of the antenna field pattern, by leveraging +the standard library Bessel functions implementation introduced with C++17. +Accordingly, the antenna gain :math:`G` at an angle :math:`\theta` from the boresight main beam +is evaluated as: + +.. math:: + G \cdot 4\left | \frac{J_{1}\left ( k\cdot a\cdot sin\theta \right )}{k\cdot a\cdot sin\theta} \right + |^{2}\;\;\;\;\; for\; 0<\left | \theta \right |\leq 90^{\circ} \\ + G \cdot 1\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\;\; for\; \theta=0 + +where :math:`J_{1}()` is the Bessel function of the first kind and first order, and :math:`a` is +the radius of the antenna's circular aperture. +The parameter :math:`k` is equal to :math:`k=\frac{2\pi f}{x}`, where :math:`f` is the carrier +frequency, and :math:`c` is the speed of light in vacuum. +The parameters :math:`G` (in logarithmic scale), :math:`a` and :math:`f` can be configured by using +the attributes "AntennaMaxGainDb", "AntennaCircularApertureRadius" and "OperatingFrequency", respectively. +This type of antennas features a symmetric radiation pattern, meaning that a single angle, measured +from the boresight direction, is sufficient to characterize the radiation strength along a given direction. + +.. _fig-circular-antenna-pattern: + +.. figure:: figures/circular-antenna-pattern.png + :align: center + + Circular aperture antenna radiation pattern with :math:`G =` 38.5 dB and :math:`a =` 10 :math:`\frac{c}{f}.` + .. [Balanis] C.A. Balanis, "Antenna Theory - Analysis and Design", Wiley, 2nd Ed. @@ -208,7 +244,9 @@ as described in [38901]_ (i.e., :math:`{\zeta}`). .. [38901] 3GPP. 2018. TR 38.901, Study on channel model for frequencies from 0.5 to 100 GHz, V15.0.0. (2018-06). +.. [38811] 3GPP. 2018. TR 38.811, Study on New Radio (NR) to support non-terrestrial networks, V15.4.0. (2020-09). + .. [Mailloux] Robert J. Mailloux, "Phased Array Antenna Handbook", Artech House, 2nd Ed. -.. [TR36897] 3GPP. 2015. TR 36.897. Study on elevation beamforming / Full-Dimension (FD) +.. [3GPP_TR36897] 3GPP. 2015. TR 36.897. Study on elevation beamforming / Full-Dimension (FD) Multiple Input Multiple Output (MIMO) for LTE. V13.0.0. (2015-06) diff --git a/src/antenna/doc/source/figures/circular-antenna-pattern.png b/src/antenna/doc/source/figures/circular-antenna-pattern.png new file mode 100644 index 0000000000..2a41bf361d Binary files /dev/null and b/src/antenna/doc/source/figures/circular-antenna-pattern.png differ diff --git a/src/antenna/model/angles.cc b/src/antenna/model/angles.cc index ef86c95111..83c94f5257 100644 --- a/src/antenna/model/angles.cc +++ b/src/antenna/model/angles.cc @@ -210,8 +210,9 @@ Angles::Angles(Vector v) // azimuth and inclination angles for zero-length vectors are not defined if (v.x == 0.0 && v.y == 0.0 && v.z == 0.0) { - m_azimuth = NAN; - m_inclination = NAN; + // assume x and length equals to 1 mm to avoid nans + m_azimuth = std::atan2(v.y, 0.001); + m_inclination = std::acos(v.z / 0.001); } NormalizeAngles(); diff --git a/src/antenna/model/circular-aperture-antenna-model.cc b/src/antenna/model/circular-aperture-antenna-model.cc new file mode 100644 index 0000000000..e409a613ab --- /dev/null +++ b/src/antenna/model/circular-aperture-antenna-model.cc @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2022 University of Padova, Dep. of Information Engineering, SIGNET lab. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mattia Sandri + */ + +#include "circular-aperture-antenna-model.h" + +// The host system uses Clang libc++, which does not support the Mathematical special functions +// (P0226R1) and Boost's implementation of cyl_bessel_j has been found. +#ifdef NEED_AND_HAVE_BOOST_BESSEL_FUNC +#include +#endif + +#include "antenna-model.h" + +#include +#include + +#include + +/** + * \file + * \ingroup antenna + * Class CircularApertureAntennaModel implementation. + */ + +namespace +{ +constexpr double C = 299792458.0; ///< speed of light in vacuum, in m/s +} // namespace + +namespace ns3 +{ +NS_LOG_COMPONENT_DEFINE("CircularApertureAntennaModel"); + +NS_OBJECT_ENSURE_REGISTERED(CircularApertureAntennaModel); + +TypeId +CircularApertureAntennaModel::GetTypeId() +{ + static TypeId tid = + TypeId("ns3::CircularApertureAntennaModel") + .SetParent() + .SetGroupName("Antenna") + .AddConstructor() + .AddAttribute("AntennaCircularApertureRadius", + "The radius of the aperture of the antenna, in meters", + DoubleValue(0.5), + MakeDoubleAccessor(&CircularApertureAntennaModel::SetApertureRadius), + MakeDoubleChecker(0.0)) + .AddAttribute("OperatingFrequency", + "The operating frequency in Hz of the antenna", + DoubleValue(2e9), + MakeDoubleAccessor(&CircularApertureAntennaModel::SetOperatingFrequency), + MakeDoubleChecker(0.0)) + .AddAttribute("AntennaMinGainDb", + "The minimum gain value in dB of the antenna", + DoubleValue(-100.0), + MakeDoubleAccessor(&CircularApertureAntennaModel::SetMinGain), + MakeDoubleChecker()) + .AddAttribute("AntennaMaxGainDb", + "The maximum gain value in dB of the antenna", + DoubleValue(1), + MakeDoubleAccessor(&CircularApertureAntennaModel::SetMaxGain), + MakeDoubleChecker(0.0)); + return tid; +} + +void +CircularApertureAntennaModel::SetApertureRadius(double aMeter) +{ + NS_LOG_FUNCTION(this << aMeter); + NS_ASSERT_MSG(aMeter > 0, "Setting invalid aperture radius: " << aMeter); + m_apertureRadiusMeter = aMeter; +} + +double +CircularApertureAntennaModel::GetApertureRadius() const +{ + return m_apertureRadiusMeter; +} + +void +CircularApertureAntennaModel::SetOperatingFrequency(double freqHz) +{ + NS_LOG_FUNCTION(this << freqHz); + NS_ASSERT_MSG(freqHz > 0, "Setting invalid operating frequency: " << freqHz); + m_operatingFrequencyHz = freqHz; +} + +double +CircularApertureAntennaModel::GetOperatingFrequency() const +{ + return m_operatingFrequencyHz; +} + +void +CircularApertureAntennaModel::SetMaxGain(double gainDb) +{ + NS_LOG_FUNCTION(this << gainDb); + m_maxGain = gainDb; +} + +double +CircularApertureAntennaModel::GetMaxGain() const +{ + return m_maxGain; +} + +void +CircularApertureAntennaModel::SetMinGain(double gainDb) +{ + NS_LOG_FUNCTION(this << gainDb); + m_minGain = gainDb; +} + +double +CircularApertureAntennaModel::GetMinGain() const +{ + return m_minGain; +} + +double +CircularApertureAntennaModel::GetGainDb(Angles a) +{ + NS_LOG_FUNCTION(this << a); + + // In 3GPP TR 38.811 v15.4.0, Section 6.4.1, the gain depends on a single angle only. + // We assume that this angle represents the angle between the vectors corresponding + // to the cartesian coordinates of the provided spherical coordinates, and the spherical + // coordinates (r = 1, azimuth = 0, elevation = PI/2) + double theta1 = a.GetInclination(); + double theta2 = M_PI_2; // reference direction + + // Convert to ISO range: the input azimuth angle phi is in [-pi,pi], + // while the ISO convention for spherical to cartesian coordinates + // assumes phi in [0,2*pi]. + double phi1 = M_PI + a.GetAzimuth(); + double phi2 = M_PI; // reference direction + + // Convert the spherical coordinates of the boresight and the incoming ray + // to Cartesian coordinates + Vector p1(sin(theta1) * cos(phi1), sin(theta1) * sin(phi1), cos(theta1)); + Vector p2(sin(theta2) * cos(phi2), sin(theta2) * sin(phi2), cos(theta2)); + + // Calculate the angle between the antenna boresight and the incoming ray + double theta = acos(p1 * p2); + + double gain = 0; + if (theta == 0) + { + gain = m_maxGain; + } + // return value of std::arccos is in [0, PI] deg + else if (theta >= M_PI_2) + { + // This is an approximation. 3GPP TR 38.811 does not provide indications + // on the antenna field pattern outside its PI degrees FOV. + gain = m_minGain; + } + else // 0 < theta < |PI/2| + { + // 3GPP TR 38.811 v15.4.0, Section 6.4.1 + double k = (2 * M_PI * m_operatingFrequencyHz) / C; + double kasintheta = k * m_apertureRadiusMeter * sin(theta); +// If needed, fall back to Boost cyl_bessel_j +#ifdef NEED_AND_HAVE_BOOST_BESSEL_FUNC + gain = boost::math::cyl_bessel_j(1, kasintheta) / kasintheta; +// Otherwise, use the std implementation +#else + gain = std::cyl_bessel_j(1, kasintheta) / kasintheta; +#endif + gain = 10 * log10(4 * gain * gain) + m_maxGain; + } + + return gain; +} + +} // namespace ns3 diff --git a/src/antenna/model/circular-aperture-antenna-model.h b/src/antenna/model/circular-aperture-antenna-model.h new file mode 100644 index 0000000000..84b8feb1a6 --- /dev/null +++ b/src/antenna/model/circular-aperture-antenna-model.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2022 University of Padova, Dep. of Information Engineering, SIGNET lab. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Mattia Sandri + */ + +#ifndef CIRCULAR_APERTURE_ANTENNA_MODEL_H +#define CIRCULAR_APERTURE_ANTENNA_MODEL_H + +#include "antenna-model.h" + +#include + +/** + * \file + * \ingroup antenna + * Class CircularApertureAntennaModel declaration + */ + +namespace ns3 +{ +/** + * \brief Circular Aperture Antenna Model + * + * This class implements the circular aperture antenna as described in 3GPP 38.811 6.4.1 + * https://www.3gpp.org/ftp/Specs/archive/38_series/38.811 without the cosine approximation, thanks + * to the Bessel functions introduced in C++17. Spherical coordinates are used, in particular of the + * azimuth and inclination angles. All working parameters can be set, namely: operating frequency, + * aperture radius, maximum and minimum gain. + * Since Clang libc++ does not support the Mathematical special functions (P0226R1) yet, this class + * falls back to Boost's implementation of cyl_bessel_j whenever the above standard library is in + * use. If neither is available in the host system, this class is not compiled. + */ +class CircularApertureAntennaModel : public AntennaModel +{ + public: + CircularApertureAntennaModel() = default; + ~CircularApertureAntennaModel() override = default; + + /** + * Register this type. + * \return The object TypeId. + */ + static TypeId GetTypeId(); + + /** + * \brief Set the antenna aperture radius + * + * Sets the antenna operating frequency, asserting that + * the provided value is within the acceptable range [0, +inf[. + * + * \param aMeter the strictly positive antenna radius in meters + */ + void SetApertureRadius(double aMeter); + + /** + * \brief Return the antenna aperture radius + * + * \return the antenna radius in meters + */ + double GetApertureRadius() const; + + /** + * \brief Set the antenna operating frequency. + * + * Sets the antenna operating frequency, asserting that + * the provided value is within the acceptable range [0, +inf[. + * + * \param freqHz the strictly positive antenna operating frequency, in Hz + */ + void SetOperatingFrequency(double freqHz); + + /** + * \brief Return the antenna operating frequency + * + * \return the antenna operating frequency, in Hz + */ + double GetOperatingFrequency() const; + + /** + * \brief Set the antenna max gain + * + * \param gainDb the antenna max gain in dB + */ + void SetMaxGain(double gainDb); + + /** + * \brief Return the antenna max gain + * + * \return the antenna max gain in dB + */ + double GetMaxGain() const; + + /** + * \brief Set the antenna min gain + * + * \param gainDb the antenna min gain in dB + */ + void SetMinGain(double gainDb); + + /** + * \brief Return the antenna min gain + * + * \return the antenna min gain in dB + */ + double GetMinGain() const; + + /** + * \brief Get the gain in dB, using Bessel equation of first kind and first order. + * + * \param a the angle at which the gain need to be calculated with respect to the antenna + * bore sight + * + * \return the antenna gain at the specified Angles a + */ + double GetGainDb(Angles a) override; + + private: + double m_apertureRadiusMeter; //!< antenna aperture radius in meters + double m_operatingFrequencyHz; //!< antenna operating frequency in Hz + double m_maxGain; //!< antenna gain in dB towards the main orientation + double m_minGain; //!< antenna min gain in dB +}; + +} // namespace ns3 + +#endif // CIRCULAR_APERTURE_ANTENNA_MODEL_H diff --git a/src/antenna/model/uniform-planar-array.cc b/src/antenna/model/uniform-planar-array.cc index 5debed34a3..a92af41ab9 100644 --- a/src/antenna/model/uniform-planar-array.cc +++ b/src/antenna/model/uniform-planar-array.cc @@ -212,10 +212,12 @@ UniformPlanarArray::GetElementFieldPattern(Angles a, uint8_t polIndex) const // convert the theta and phi angles from GCS to LCS using eq. 7.1-7 and 7.1-8 in 3GPP TR 38.901 // NOTE we assume a fixed slant angle of 0 degrees - double cosIncl = cos(a.GetInclination()); - double sinIncl = sin(a.GetInclination()); - double cosAzim = cos(a.GetAzimuth() - m_alpha); - double sinAzim = sin(a.GetAzimuth() - m_alpha); + double inclination = a.GetInclination(); + double azimuth = a.GetAzimuth(); + double cosIncl = cos(inclination); + double sinIncl = sin(inclination); + double cosAzim = cos(azimuth - m_alpha); + double sinAzim = sin(azimuth - m_alpha); double thetaPrime = std::acos(m_cosBeta * cosIncl + m_sinBeta * cosAzim * sinIncl); double phiPrime = std::arg(std::complex(m_cosBeta * sinIncl * cosAzim - m_sinBeta * cosIncl, diff --git a/src/antenna/test/gen-test-circular-aperture-antenna-reference-points.m b/src/antenna/test/gen-test-circular-aperture-antenna-reference-points.m new file mode 100644 index 0000000000..51db047be1 --- /dev/null +++ b/src/antenna/test/gen-test-circular-aperture-antenna-reference-points.m @@ -0,0 +1,105 @@ +%{ + Compute the antenna gain pattern of the reflector antenna with circular aperture + specified in the Sec. 6.4.1, 3GPP 38.811 v.15.4.0 and generate reference gain values + for the CircularApertureAntennaModelTest. +%} +clc; clearvars; + +%{ + Consider two testing vectors, one with elevation fixed to 90 degrees and + varying azimuth, the other with azimuth fixed to 180 degrees and varying elevation. + The boresight direction, is (az, el) = (180 degrees, 90 degrees) +%} +az_test_fixed_el = 90:10:180; +eL_test_fixed_az = 0:9:90; +% Uncomment line below and comment line below for the fixed elevation test +[theta_vec, az_vec, el_vec] = theta_vec_from_sph_coord_vecs(az_test_fixed_el, 90); +% Uncomment line above and comment line below for the fixed azimuth test +%[theta_vec, az_vec, el_vec] = theta_vec_from_sph_coord_vecs(180, eL_test_fixed_az); + +%{ + The theta angle which represents the input of the pattern formula is + computed as theta = arccos(), where p_i = sin(theta_i) * + cos(phi_i), sin(theta_i) * sin(phi_i), cos(theta_i). The default + boresight is (phi1 (az), theta1(el)) = (180deg, 90deg) +%} + +%{ + 3GPP specifies the antenna gain only for |theta| < 90 degrees. + The gain outside of this region is approximated as min_gain_dB +%} +min_gain_dB = -50; + +max_gain_dB = 0; +c=physconst('LightSpeed'); +f=28e9; % operating frequency +k=2*pi*f/c; % wave number +a=10*c/f; % radius antenna aperture +arg_vec=k*a*sind(theta_vec); +pattern=besselj(1, arg_vec)./arg_vec; +pattern= 4*(abs(pattern).^2); + +% Manually set gain for theta = 0 +where_arg_zero=find(~theta_vec); +pattern(where_arg_zero)=1; +gain_dB=10*log10(pattern) + max_gain_dB; + +% Manually set gain to minimum gain for |theta| >= 90 degrees +where_arg_outside_pattern_domain = find(abs(theta_vec) >= 90); +gain_dB(where_arg_outside_pattern_domain)=min_gain_dB; + +%{ + Plot and output the C++ code which defines the reference vector of data points. + Test points are assumed to be encoded as C++ structs +%} +scatter(theta_vec, gain_dB); +out_str = ns3_output_from_vecs(az_vec, el_vec, gain_dB, max_gain_dB, min_gain_dB, a, f); + + +function theta = theta_from_sph_coord(phi1, theta1) +% theta_from_sph_coord Computes theta (the input of the radiation pattern formula) +% from the azimuth and elevation angles with resepct to boresight. +% phi1 the azimuth with respect to boresight +% theta1 the elevation angle with respect to boresight + + p1 = [sind(theta1)*cosd(phi1), sind(theta1)*sind(phi1), cosd(theta1)]; + % p2, i.e., the boresight direction, is phi1 (az), theta1(el)) = + % (180deg, 90deg) + theta2 = 90; phi2 = 180; + p2 = [sind(theta2)*cosd(phi2), sind(theta2)*sind(phi2), cosd(theta2)]; + theta = acosd(dot(p1,p2)); +end + +function [theta_vec, az_vec, el_vec] = theta_vec_from_sph_coord_vecs(az_vec, el_vec) +% theta_vec_from_sph_coord_vecs Computes the vectors of thetas +% (the inputs of the radiation pattern formula) +% from vectors of azimuth and elevation angles with resepct to boresight. +% phi1 the vector of azimuths with respect to boresight +% theta1 the vector of elevation angles with respect to boresight + if size(az_vec, 2) > 1 + el_vec = repelem(el_vec, size(az_vec, 2)); + elseif size(el_vec, 2) > 1 + az_vec = repelem(az_vec, size(el_vec, 2)); + end + theta_vec = arrayfun(@theta_from_sph_coord, az_vec, el_vec); +end + +function out_str = ns3_output_from_vecs(az_vec, el_vec, gain_dB_vec, max_gain, min_gain, a, f) +% ns3_output_from_vecs Outputs the reference gain values +% as a vector of vectors. +% The entries of the inner vectors, representing a single test point, +% represent: (gain at boresight (dB), gain outside the 3GPP pattern region (dB), +% aperture (meters), carrier frequency (Hz), test azimuth (degrees), +% test elevation angle (degrees), reference antenna gain (dB)) + out_str = ''; + for i=1:size(el_vec, 2) + out_str = [out_str, '{', ... + num2str(max_gain), ',', ... + num2str(min_gain), ',', ... + num2str(a), ',', ... + num2str(f), ',', ... + num2str(az_vec(i) - 180), ',', ... + num2str(el_vec(i)), ',', ... + num2str(gain_dB_vec(i)), '},']; + end +end diff --git a/src/antenna/test/test-angles.cc b/src/antenna/test/test-angles.cc index d84aa441d5..f1af5d5dcc 100644 --- a/src/antenna/test/test-angles.cc +++ b/src/antenna/test/test-angles.cc @@ -296,227 +296,234 @@ class AnglesTestSuite : public TestSuite }; AnglesTestSuite::AnglesTestSuite() - : TestSuite("angles", UNIT) + : TestSuite("angles", Type::UNIT) { AddTestCase(new OneVectorConstructorTestCase(Vector(1, 0, 0), Angles(0, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(-1, 0, 0), Angles(M_PI, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, 1, 0), Angles(M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, -1, 0), Angles(-M_PI_2, M_PI_2)), - TestCase::QUICK); - AddTestCase(new OneVectorConstructorTestCase(Vector(0, 0, 1), Angles(0, 0)), TestCase::QUICK); + TestCase::Duration::QUICK); + AddTestCase(new OneVectorConstructorTestCase(Vector(0, 0, 1), Angles(0, 0)), + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, 0, -1), Angles(0, M_PI)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(2, 0, 0), Angles(0, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(-2, 0, 0), Angles(M_PI, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, 2, 0), Angles(M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, -2, 0), Angles(-M_PI_2, M_PI_2)), - TestCase::QUICK); - AddTestCase(new OneVectorConstructorTestCase(Vector(0, 0, 2), Angles(0, 0)), TestCase::QUICK); + TestCase::Duration::QUICK); + AddTestCase(new OneVectorConstructorTestCase(Vector(0, 0, 2), Angles(0, 0)), + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, 0, -2), Angles(0, M_PI)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(1, 0, 1), Angles(0, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(1, 0, -1), Angles(0, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(1, 1, 0), Angles(M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(1, -1, 0), Angles(-M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(-1, 0, 1), Angles(M_PI, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(-1, 0, -1), Angles(M_PI, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(-1, 1, 0), Angles(3 * M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(-1, -1, 0), Angles(-3 * M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, 1, 1), Angles(M_PI_2, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, 1, -1), Angles(M_PI_2, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, -1, 1), Angles(-M_PI_2, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new OneVectorConstructorTestCase(Vector(0, -1, -1), Angles(-M_PI_2, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new OneVectorConstructorTestCase(Vector(1, 1, std::sqrt(2)), Angles(M_PI_4, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new OneVectorConstructorTestCase(Vector(1, 1, -std::sqrt(2)), Angles(M_PI_4, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new OneVectorConstructorTestCase(Vector(1, -1, std::sqrt(2)), Angles(-M_PI_4, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new OneVectorConstructorTestCase(Vector(-1, 1, std::sqrt(2)), Angles(3 * M_PI_4, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(1, 0, 0), Vector(0, 0, 0), Angles(0, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(-1, 0, 0), Vector(0, 0, 0), Angles(M_PI, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(0, 1, 0), Vector(0, 0, 0), Angles(M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, -1, 0), Vector(0, 0, 0), Angles(-M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, 0, 1), Vector(0, 0, 0), Angles(0, 0)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(0, 0, -1), Vector(0, 0, 0), Angles(0, M_PI)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(2, 0, 0), Vector(0, 0, 0), Angles(0, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(-2, 0, 0), Vector(0, 0, 0), Angles(M_PI, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(0, 2, 0), Vector(0, 0, 0), Angles(M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, -2, 0), Vector(0, 0, 0), Angles(-M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, 0, 2), Vector(0, 0, 0), Angles(0, 0)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(0, 0, -2), Vector(0, 0, 0), Angles(0, M_PI)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(1, 0, 1), Vector(0, 0, 0), Angles(0, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(1, 0, -1), Vector(0, 0, 0), Angles(0, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(1, 1, 0), Vector(0, 0, 0), Angles(M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(1, -1, 0), Vector(0, 0, 0), Angles(-M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(-1, 0, 1), Vector(0, 0, 0), Angles(M_PI, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(-1, 0, -1), Vector(0, 0, 0), Angles(M_PI, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(-1, 1, 0), Vector(0, 0, 0), Angles(3 * M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(-1, -1, 0), Vector(0, 0, 0), Angles(-3 * M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(0, 1, 1), Vector(0, 0, 0), Angles(M_PI_2, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, 1, -1), Vector(0, 0, 0), Angles(M_PI_2, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, -1, 1), Vector(0, 0, 0), Angles(-M_PI_2, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, -1, -1), Vector(0, 0, 0), Angles(-M_PI_2, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(1, 1, std::sqrt(2)), Vector(0, 0, 0), Angles(M_PI_4, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(1, 1, -std::sqrt(2)), Vector(0, 0, 0), Angles(M_PI_4, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(1, -1, std::sqrt(2)), Vector(0, 0, 0), Angles(-M_PI_4, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(-1, 1, std::sqrt(2)), Vector(0, 0, 0), Angles(3 * M_PI_4, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(3, 2, 2), Vector(2, 2, 2), Angles(0, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(1, 2, 2), Vector(2, 2, 2), Angles(M_PI, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(2, 3, 2), Vector(2, 2, 2), Angles(M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(-1, 2, 2), Vector(-1, 3, 2), Angles(-M_PI_2, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(4, -2, 7), Vector(4, -2, 6), Angles(0, 0)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(0, -5, -1), Vector(0, -5, 0), Angles(0, M_PI)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(-2, 2, -1), Vector(-4, 2, -1), Angles(0, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(2, 2, 0), Vector(4, 2, 0), Angles(M_PI, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new TwoVectorsConstructorTestCase(Vector(-1, 4, 4), Vector(-2, 4, 3), Angles(0, M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0, -2, -6), Vector(-1, -2, -5), Angles(0, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(77, 3, 43), Vector(78, 2, 43), Angles(3 * M_PI_4, M_PI_2)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(24, -2, -6 - std::sqrt(2)), Vector(23, -3, -6), Angles(M_PI_4, 3 * M_PI_4)), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TwoVectorsConstructorTestCase(Vector(0.5, 11.45, std::sqrt(2) - 1), Vector(-0.5, 12.45, -1), Angles(-M_PI_4, M_PI_4)), - TestCase::QUICK); - AddTestCase(new WrapToRangeTestCase(WrapTo180, -180, 180), TestCase::QUICK); - AddTestCase(new WrapToRangeTestCase(WrapToPi, -M_PI, M_PI), TestCase::QUICK); - AddTestCase(new WrapToRangeTestCase(WrapTo360, 0, 360), TestCase::QUICK); - AddTestCase(new WrapToRangeTestCase(WrapTo2Pi, 0, 2 * M_PI), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, -182.2, 177.8), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, -179, -179), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, 181, -179), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, 360.6, 0.6), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, -182.8, 177.2), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, -179, 181), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, 181, 181), TestCase::QUICK); - AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, 360.2, 0.2), TestCase::QUICK); + TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeTestCase(WrapTo180, -180, 180), TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeTestCase(WrapToPi, -M_PI, M_PI), TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeTestCase(WrapTo360, 0, 360), TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeTestCase(WrapTo2Pi, 0, 2 * M_PI), TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, -182.2, 177.8), + TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, -179, -179), + TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, 181, -179), TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo180, 360.6, 0.6), + TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, -182.8, 177.2), + TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, -179, 181), TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, 181, 181), TestCase::Duration::QUICK); + AddTestCase(new WrapToRangeFunctionalTestCase(WrapTo360, 360.2, 0.2), + TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/antenna/test/test-circular-aperture-antenna.cc b/src/antenna/test/test-circular-aperture-antenna.cc new file mode 100644 index 0000000000..e6cfa9377e --- /dev/null +++ b/src/antenna/test/test-circular-aperture-antenna.cc @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2023 University of Padova, Dep. of Information Engineering, SIGNET lab. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ns3/circular-aperture-antenna-model.h" +#include "ns3/double.h" +#include "ns3/log.h" +#include "ns3/pointer.h" +#include "ns3/simulator.h" +#include "ns3/test.h" +#include "ns3/uinteger.h" +#include "ns3/uniform-planar-array.h" + +#include +#include +#include +#include + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE("TestCircularApertureAntennaModel"); + +/** + * \ingroup antenna-tests + * + * \brief CircularApertureAntennaModel Test Case + * + * Note: Since Clang libc++ does not support the Mathematical special functions (P0226R1) yet, this + * class falls back to Boost's implementation of cyl_bessel_j whenever the above standard library is + * in use. If neither is available in the host system, this class is not compiled. + */ +class CircularApertureAntennaModelTestCase : public TestCase +{ + public: + CircularApertureAntennaModelTestCase(); + + /** + * \brief Description of a single test point + * + * Description of a test point, which is characterized + * by the CircularApertureAntennaModel parameters, + * the directions towards which the antenna gain + * is to be tested, and the expected gain value. + */ + struct TestPoint + { + /** + * @brief Constructor + * + * @param antennaMaxGainDb the antenna maximum possible gain [dB] + * @param antennaMinGainDb the antenna minimum possible gain [dB] + * @param antennaCircularApertureRadius the radius of the parabolic aperture [m] + * @param operatingFrequency operating frequency [Hz] + * @param testAzimuth test azimuth [rad] + * @param testInclination test inclination [rad] + * @param expectedGain the expected gain value [dB] + */ + TestPoint(double antennaMaxGainDb, + double antennaMinGainDb, + double antennaCircularApertureRadius, + double operatingFrequency, + double testAzimuth, + double testInclination, + double expectedGain) + : m_antennaMaxGainDb(antennaMaxGainDb), + m_antennaMinGainDb(antennaMinGainDb), + m_antennaCircularApertureRadius(antennaCircularApertureRadius), + m_operatingFrequency(operatingFrequency), + m_testAzimuth(DegreesToRadians(testAzimuth)), + m_testInclination(DegreesToRadians(testInclination)), + m_expectedGain(expectedGain) + { + } + + double m_antennaMaxGainDb; ///< the antenna maximum possible gain [dB] + double m_antennaMinGainDb; ///< the antenna minimum possible gain [dB] + double m_antennaCircularApertureRadius; ///< the radius of the parabolic aperture [m] + double m_operatingFrequency; ///< operating frequency [Hz] + double m_testAzimuth; ///< test azimuth [rad] + double m_testInclination; ///< test inclination [rad] + double m_expectedGain; ///< the expected gain value [dB] + }; + + /** + * Generate a string containing all relevant parameters + * \param testPoint the parameter configuration to be tested + * \return the string containing all relevant parameters + */ + static std::string BuildNameString(TestPoint testPoint); + + /** + * Test the antenna gain for a specific parameter configuration, + * by comparing the antenna gain obtained using CircularApertureAntennaModel::GetGainDb + * and the one obtained using MATLAB. + * + * \param testPoint the parameter configuration to be tested + */ + void TestAntennaGain(TestPoint testPoint); + + private: + /** + * Run the test + */ + void DoRun() override; +}; + +CircularApertureAntennaModelTestCase::CircularApertureAntennaModelTestCase() + : TestCase("Creating CircularApertureAntennaModelTestCase") +{ +} + +std::string +CircularApertureAntennaModelTestCase::BuildNameString(TestPoint testPoint) +{ + std::ostringstream oss; + oss << " Maximum gain=" << testPoint.m_antennaMaxGainDb << "dB" + << " minimum gain=" << testPoint.m_antennaMinGainDb << "dB" + << ", antenna aperture radius=" << testPoint.m_antennaCircularApertureRadius << "m" + << ", frequency" << testPoint.m_operatingFrequency << "Hz" + << ", test inclination=" << RadiansToDegrees(testPoint.m_testInclination) << " deg" + << ", test azimuth=" << RadiansToDegrees(testPoint.m_testAzimuth) << " deg"; + return oss.str(); +} + +void +CircularApertureAntennaModelTestCase::TestAntennaGain(TestPoint testPoint) +{ + Ptr antenna = + CreateObjectWithAttributes( + "AntennaMaxGainDb", + DoubleValue(testPoint.m_antennaMaxGainDb), + "AntennaMinGainDb", + DoubleValue(testPoint.m_antennaMinGainDb), + "AntennaCircularApertureRadius", + DoubleValue(testPoint.m_antennaCircularApertureRadius), + "OperatingFrequency", + DoubleValue(testPoint.m_operatingFrequency)); + + Ptr upa = + CreateObjectWithAttributes("AntennaElement", + PointerValue(antenna), + "NumColumns", + UintegerValue(1), + "NumRows", + UintegerValue(1)); + + auto [fieldPhi, fieldTheta] = + upa->GetElementFieldPattern(Angles(testPoint.m_testAzimuth, testPoint.m_testInclination), + 0); + // Compute the antenna gain as the squared sum of the field pattern components + double gainDb = 10 * log10(fieldPhi * fieldPhi + fieldTheta * fieldTheta); + auto log = BuildNameString(testPoint); + NS_LOG_INFO(log); + NS_TEST_EXPECT_MSG_EQ_TOL(gainDb, testPoint.m_expectedGain, 0.1, log); +} + +void +CircularApertureAntennaModelTestCase::DoRun() +{ + // Vector of test points + std::vector testPoints = { + // MaxGainDb MinGainDb Radius (m) Freq (Hz) Azimuth (deg) Incl (deg) ExpGain (dB) + // Test invariant: gain always equal to max gain at boresight (inclination 90, azimuth = 0) + // for different frequency + {30, -30, 0.5, 2e9, 0, 90, 30}, + {30, -30, 2, 20e9, 0, 90, 30}, + // Test invariant: gain always equal to max gain at boresight (inclination 90, azimuth = 0) + // for different max gain + {20, -30, 0.5, 2e9, 0, 90, 20}, + {10, -30, 2, 20e9, 0, 90, 10}, + // Test invariant: gain always equal to min gain outside of |theta| < 90 deg + // for different frequency + {30, -100, 0.5, 2e9, 0, 0, -100}, + {30, -100, 2, 20e9, 0, 0, -100}, + // Test invariant: gain always equal to min gain outside of |theta| < 90 deg + // for different orientations + {30, -100, 0.5, 2e9, 180, 90, -100}, + {30, -100, 2, 20e9, -180, 90, -100}, + // Fixed elevation to boresight (90deg) and azimuth varying in [-90, 0] deg with steps of 10 + // degrees + {0, -50, 0.10707, 28000000000, -90, 90, -50}, + {0, -50, 0.10707, 28000000000, -80, 90, -49.8022}, + {0, -50, 0.10707, 28000000000, -70, 90, -49.1656}, + {0, -50, 0.10707, 28000000000, -60, 90, -60.9132}, + {0, -50, 0.10707, 28000000000, -50, 90, -59.2368}, + {0, -50, 0.10707, 28000000000, -40, 90, -44.6437}, + {0, -50, 0.10707, 28000000000, -30, 90, -43.9686}, + {0, -50, 0.10707, 28000000000, -20, 90, -36.3048}, + {0, -50, 0.10707, 28000000000, -10, 90, -30.5363}, + {0, -50, 0.10707, 28000000000, 0, 90, 0}, + // Fixed azimuth to boresight (0 deg) and azimuth varying in [0, 90] deg with steps of 9 + // degrees + {0, -50, 0.10707, 28e9, 0, 0, -50}, + {0, -50, 0.10707, 28e9, 0, 9, -49.7256}, + {0, -50, 0.10707, 28e9, 0, 18, -52.9214}, + {0, -50, 0.10707, 28e9, 0, 27, -48.6077}, + {0, -50, 0.10707, 28e9, 0, 36, -60.684}, + {0, -50, 0.10707, 28e9, 0, 45, -55.1468}, + {0, -50, 0.10707, 28e9, 0, 54, -42.9648}, + {0, -50, 0.10707, 28e9, 0, 63, -45.6472}, + {0, -50, 0.10707, 28e9, 0, 72, -48.6378}, + {0, -50, 0.10707, 28e9, 0, 81, -35.1613}, + {0, -50, 0.10707, 28e9, 0, 90, 0}}; + + // Call TestAntennaGain on each test point + for (auto& point : testPoints) + { + TestAntennaGain(point); + } +} + +/** + * \ingroup antenna-tests + * + * \brief UniformPlanarArray Test Suite + */ +class CircularApertureAntennaModelTestSuite : public TestSuite +{ + public: + CircularApertureAntennaModelTestSuite(); +}; + +CircularApertureAntennaModelTestSuite::CircularApertureAntennaModelTestSuite() + : TestSuite("circular-aperture-antenna-test", Type::UNIT) +{ + AddTestCase(new CircularApertureAntennaModelTestCase()); +} + +static CircularApertureAntennaModelTestSuite staticCircularApertureAntennaModelTestSuiteInstance; diff --git a/src/antenna/test/test-cosine-antenna.cc b/src/antenna/test/test-cosine-antenna.cc index 014662aff4..efd0a51dd4 100644 --- a/src/antenna/test/test-cosine-antenna.cc +++ b/src/antenna/test/test-cosine-antenna.cc @@ -151,7 +151,7 @@ class CosineAntennaModelTestSuite : public TestSuite }; CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() - : TestSuite("cosine-antenna-model", UNIT) + : TestSuite("cosine-antenna-model", Type::UNIT) { // to calculate the azimut angle offset for a given gain in db: // phideg = (2*acos(10^(targetgaindb/(20*n))))*180/pi @@ -166,77 +166,77 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 60, 0, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(90)), 60, 0, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(100), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(150), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(180), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-180), DegreesToRadians(90)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); // test positive orientation AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(60), DegreesToRadians(90)), @@ -245,77 +245,77 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(90)), 60, 60, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 60, 60, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(150), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(160), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(210), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(240), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-40), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-120), DegreesToRadians(90)), 60, 60, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); // test negative orientation and different beamwidths // with a 100 deg beamwidth, gain is -20dB at +- 117.47 degrees from boresight @@ -325,21 +325,21 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(90)), 100, -150, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-200), DegreesToRadians(90)), 100, -150, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(-32.531), DegreesToRadians(90)), 100, @@ -347,7 +347,7 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(92.531), DegreesToRadians(90)), 100, @@ -355,42 +355,42 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(90)), 100, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(90)), 100, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(60), DegreesToRadians(90)), 100, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(90)), 100, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 100, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); // with a 150 deg beamwidth, gain is -10dB at +- 124.93 degrees from boresight, and -20dB at +- // 155.32 degrees from boresight AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(90)), @@ -399,21 +399,21 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(135), DegreesToRadians(90)), 150, -150, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-75), DegreesToRadians(90)), 150, -150, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(85.070), DegreesToRadians(90)), 150, @@ -421,7 +421,7 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(-25.070), DegreesToRadians(90)), 150, @@ -429,7 +429,7 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(5.3230), DegreesToRadians(90)), 150, @@ -437,7 +437,7 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(54.677), DegreesToRadians(90)), 150, @@ -445,21 +445,21 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 150, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(20), DegreesToRadians(90)), 150, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); // test flat beam, with beamwidth=360 deg AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(90)), 360, @@ -467,35 +467,35 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(180), DegreesToRadians(90)), 360, 0, 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-180), DegreesToRadians(90)), 360, 0, 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(0)), 360, 0, 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(180)), 360, 0, 0, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); // test maxGain AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(90)), @@ -504,63 +504,63 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 10, 10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 60, 0, 22, 19, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(90)), 60, 0, -4, -7, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(90)), 60, 0, 10, -10, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(90)), 60, 0, -20, -40, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(100), DegreesToRadians(90)), 60, 0, 40, 20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(90)), 100, -150, 2, 2, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(90)), 100, -150, 4, 1, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-200), DegreesToRadians(90)), 100, -150, -1, -4, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); // test elevation angle AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(60)), @@ -569,56 +569,56 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(60)), 60, 0, 0, -6, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(60)), 60, 0, 0, -6, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(60)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-180), DegreesToRadians(60)), 60, 0, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(60), DegreesToRadians(120)), 60, 60, 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(120)), 60, 60, 0, -6, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(120)), 60, 60, 0, -6, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(-120), DegreesToRadians(120)), 60, @@ -626,7 +626,7 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(140)), 100, @@ -634,7 +634,7 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(140)), 100, @@ -642,7 +642,7 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -6, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new CosineAntennaModelTestCase(Angles(DegreesToRadians(-200), DegreesToRadians(140)), 100, @@ -650,77 +650,77 @@ CosineAntennaModelTestSuite::CosineAntennaModelTestSuite() 0, -6, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(140)), 100, -150, 0, -20, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(60)), 60, 0, 10, 7, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(60)), 60, 0, 22, 16, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(60)), 60, 0, -4, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(60)), 60, 0, 10, -13, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(60)), 60, 0, -20, -43, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(100), DegreesToRadians(60)), 60, 0, 40, 17, LESSTHAN), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(40)), 100, -150, 2, -1, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(40)), 100, -150, 4, -2, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CosineAntennaModelTestCase(Angles(DegreesToRadians(-200), DegreesToRadians(40)), 100, -150, -1, -7, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/antenna/test/test-degrees-radians.cc b/src/antenna/test/test-degrees-radians.cc index 6643f3ffe4..035199bbcb 100644 --- a/src/antenna/test/test-degrees-radians.cc +++ b/src/antenna/test/test-degrees-radians.cc @@ -138,23 +138,23 @@ class DegreesRadiansTestSuite : public TestSuite }; DegreesRadiansTestSuite::DegreesRadiansTestSuite() - : TestSuite("degrees-radians", UNIT) + : TestSuite("degrees-radians", Type::UNIT) { - AddTestCase(new DegreesToRadiansTestCase(0, 0), TestCase::QUICK); - AddTestCase(new DegreesToRadiansTestCase(90, M_PI_2), TestCase::QUICK); - AddTestCase(new DegreesToRadiansTestCase(180, M_PI), TestCase::QUICK); - AddTestCase(new DegreesToRadiansTestCase(270, M_PI + M_PI_2), TestCase::QUICK); - AddTestCase(new DegreesToRadiansTestCase(360, M_PI + M_PI), TestCase::QUICK); - AddTestCase(new DegreesToRadiansTestCase(-90, -M_PI_2), TestCase::QUICK); - AddTestCase(new DegreesToRadiansTestCase(810, 4.5 * M_PI), TestCase::QUICK); - - AddTestCase(new RadiansToDegreesTestCase(0, 0), TestCase::QUICK); - AddTestCase(new RadiansToDegreesTestCase(M_PI_2, 90), TestCase::QUICK); - AddTestCase(new RadiansToDegreesTestCase(M_PI, 180), TestCase::QUICK); - AddTestCase(new RadiansToDegreesTestCase(M_PI + M_PI_2, 270), TestCase::QUICK); - AddTestCase(new RadiansToDegreesTestCase(M_PI + M_PI, 360), TestCase::QUICK); - AddTestCase(new RadiansToDegreesTestCase(-M_PI_2, -90), TestCase::QUICK); - AddTestCase(new RadiansToDegreesTestCase(4.5 * M_PI, 810), TestCase::QUICK); + AddTestCase(new DegreesToRadiansTestCase(0, 0), TestCase::Duration::QUICK); + AddTestCase(new DegreesToRadiansTestCase(90, M_PI_2), TestCase::Duration::QUICK); + AddTestCase(new DegreesToRadiansTestCase(180, M_PI), TestCase::Duration::QUICK); + AddTestCase(new DegreesToRadiansTestCase(270, M_PI + M_PI_2), TestCase::Duration::QUICK); + AddTestCase(new DegreesToRadiansTestCase(360, M_PI + M_PI), TestCase::Duration::QUICK); + AddTestCase(new DegreesToRadiansTestCase(-90, -M_PI_2), TestCase::Duration::QUICK); + AddTestCase(new DegreesToRadiansTestCase(810, 4.5 * M_PI), TestCase::Duration::QUICK); + + AddTestCase(new RadiansToDegreesTestCase(0, 0), TestCase::Duration::QUICK); + AddTestCase(new RadiansToDegreesTestCase(M_PI_2, 90), TestCase::Duration::QUICK); + AddTestCase(new RadiansToDegreesTestCase(M_PI, 180), TestCase::Duration::QUICK); + AddTestCase(new RadiansToDegreesTestCase(M_PI + M_PI_2, 270), TestCase::Duration::QUICK); + AddTestCase(new RadiansToDegreesTestCase(M_PI + M_PI, 360), TestCase::Duration::QUICK); + AddTestCase(new RadiansToDegreesTestCase(-M_PI_2, -90), TestCase::Duration::QUICK); + AddTestCase(new RadiansToDegreesTestCase(4.5 * M_PI, 810), TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/antenna/test/test-isotropic-antenna.cc b/src/antenna/test/test-isotropic-antenna.cc index 1c4ba29fc2..7d756930cf 100644 --- a/src/antenna/test/test-isotropic-antenna.cc +++ b/src/antenna/test/test-isotropic-antenna.cc @@ -94,17 +94,23 @@ class IsotropicAntennaModelTestSuite : public TestSuite }; IsotropicAntennaModelTestSuite::IsotropicAntennaModelTestSuite() - : TestSuite("isotropic-antenna-model", UNIT) + : TestSuite("isotropic-antenna-model", Type::UNIT) { - AddTestCase(new IsotropicAntennaModelTestCase(Angles(0, 0), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(0, M_PI), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(0, M_PI_2), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI, 0), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI, M_PI), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI, M_PI_2), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI_2, 0), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI_2, M_PI), 0.0), TestCase::QUICK); - AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI_2, M_PI_2), 0.0), TestCase::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(0, 0), 0.0), TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(0, M_PI), 0.0), TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(0, M_PI_2), 0.0), + TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI, 0), 0.0), TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI, M_PI), 0.0), + TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI, M_PI_2), 0.0), + TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI_2, 0), 0.0), + TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI_2, M_PI), 0.0), + TestCase::Duration::QUICK); + AddTestCase(new IsotropicAntennaModelTestCase(Angles(M_PI_2, M_PI_2), 0.0), + TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/antenna/test/test-parabolic-antenna.cc b/src/antenna/test/test-parabolic-antenna.cc index b043471880..795dd9baf4 100644 --- a/src/antenna/test/test-parabolic-antenna.cc +++ b/src/antenna/test/test-parabolic-antenna.cc @@ -152,7 +152,7 @@ class ParabolicAntennaModelTestSuite : public TestSuite }; ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() - : TestSuite("parabolic-antenna-model", UNIT) + : TestSuite("parabolic-antenna-model", Type::UNIT) { // with a 60 deg beamwidth, gain is -20dB at +-77.460 degrees from boresight // phi, theta, @@ -166,7 +166,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 60, @@ -174,7 +174,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(90)), 60, @@ -182,7 +182,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(90)), 60, @@ -190,7 +190,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(90)), 60, @@ -198,7 +198,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(100), DegreesToRadians(90)), 60, @@ -206,7 +206,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(150), DegreesToRadians(90)), 60, @@ -214,7 +214,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(180), DegreesToRadians(90)), 60, @@ -222,7 +222,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(90)), 60, @@ -230,7 +230,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(90)), 60, @@ -238,7 +238,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-180), DegreesToRadians(90)), 60, @@ -246,7 +246,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); // with a 60 deg beamwidth, gain is -10dB at +-54.772 degrees from boresight // test positive orientation @@ -257,7 +257,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(90)), 60, @@ -265,7 +265,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 60, @@ -273,7 +273,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(90)), 60, @@ -281,7 +281,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(150), DegreesToRadians(90)), 60, @@ -289,7 +289,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(160), DegreesToRadians(90)), 60, @@ -297,7 +297,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(210), DegreesToRadians(90)), 60, @@ -305,7 +305,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(240), DegreesToRadians(90)), 60, @@ -313,7 +313,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-40), DegreesToRadians(90)), 60, @@ -321,7 +321,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(90)), 60, @@ -329,7 +329,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-120), DegreesToRadians(90)), 60, @@ -337,7 +337,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); // test negative orientation and different beamwidths // with a 80 deg beamwidth, gain is -20dB at +- 73.030 degrees from boresight @@ -348,7 +348,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-110), DegreesToRadians(90)), 80, @@ -356,7 +356,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-190), DegreesToRadians(90)), 80, @@ -364,7 +364,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-70), DegreesToRadians(90)), 80, @@ -372,7 +372,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(92), DegreesToRadians(90)), 80, @@ -380,7 +380,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(90)), 80, @@ -388,14 +388,14 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(90)), 80, -150, 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(60), DegreesToRadians(90)), 80, @@ -403,7 +403,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(90)), 80, @@ -411,7 +411,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(90)), 80, @@ -419,7 +419,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); // test elevation angle AddTestCase(new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(88)), @@ -428,7 +428,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(88)), 60, @@ -436,7 +436,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(88)), 60, @@ -444,7 +444,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-90), DegreesToRadians(88)), 60, @@ -452,7 +452,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-180), DegreesToRadians(88)), 60, @@ -460,7 +460,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(60), DegreesToRadians(93)), 60, @@ -468,7 +468,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(93)), 60, @@ -476,7 +476,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(93)), 60, @@ -484,7 +484,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-120), DegreesToRadians(93)), 60, @@ -492,7 +492,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(93)), 100, @@ -500,7 +500,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(93)), 100, @@ -508,7 +508,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-200), DegreesToRadians(93)), 100, @@ -516,7 +516,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(93)), 100, @@ -524,7 +524,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(90), DegreesToRadians(80.5)), 100, @@ -532,7 +532,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 10, -10, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(0), DegreesToRadians(80.5)), 60, @@ -540,7 +540,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(30), DegreesToRadians(80.5)), 60, @@ -548,7 +548,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-30), DegreesToRadians(80.5)), 60, @@ -556,7 +556,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(100), DegreesToRadians(80.5)), 60, @@ -564,7 +564,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 20, -20, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-150), DegreesToRadians(80.5)), 100, @@ -572,7 +572,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 30, 0, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-100), DegreesToRadians(80.5)), 100, @@ -580,7 +580,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 30, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new ParabolicAntennaModelTestCase(Angles(DegreesToRadians(-200), DegreesToRadians(80.5)), 100, @@ -588,7 +588,7 @@ ParabolicAntennaModelTestSuite::ParabolicAntennaModelTestSuite() 30, -3, EQUAL), - TestCase::QUICK); + TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/antenna/test/test-uniform-planar-array.cc b/src/antenna/test/test-uniform-planar-array.cc index a471350615..5c95c6c1e5 100644 --- a/src/antenna/test/test-uniform-planar-array.cc +++ b/src/antenna/test/test-uniform-planar-array.cc @@ -215,7 +215,7 @@ class UniformPlanarArrayTestSuite : public TestSuite }; UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() - : TestSuite("uniform-planar-array-test", UNIT) + : TestSuite("uniform-planar-array-test", Type::UNIT) { Ptr isotropic = CreateObject(); Ptr tgpp = CreateObject(); @@ -233,7 +233,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(0), DegreesToRadians(90)), 0.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -243,7 +243,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(0), DegreesToRadians(90)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -253,7 +253,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(90), DegreesToRadians(90)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -263,7 +263,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(-90), DegreesToRadians(90)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -273,7 +273,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(180), DegreesToRadians(90)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -283,7 +283,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(-180), DegreesToRadians(90)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -293,7 +293,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(45), Angles(DegreesToRadians(0), DegreesToRadians(135)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -303,7 +303,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(-45), Angles(DegreesToRadians(0), DegreesToRadians(45)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -313,7 +313,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(90), Angles(DegreesToRadians(0), DegreesToRadians(180)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 1, 1, @@ -323,7 +323,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(-90), Angles(DegreesToRadians(0), DegreesToRadians(0)), 8.0), - TestCase::QUICK); + TestCase::Duration::QUICK); // linear array AddTestCase(new UniformPlanarArrayTestCase(tgpp, @@ -335,7 +335,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(0), DegreesToRadians(90)), 18.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 10, 1, @@ -345,7 +345,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(90), DegreesToRadians(90)), 18.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 10, 1, @@ -355,7 +355,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(45), Angles(DegreesToRadians(0), DegreesToRadians(135)), 18.0), - TestCase::QUICK); + TestCase::Duration::QUICK); // planar array AddTestCase(new UniformPlanarArrayTestCase(tgpp, @@ -367,7 +367,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(0), DegreesToRadians(90)), 28.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 10, 10, @@ -377,7 +377,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(0), Angles(DegreesToRadians(90), DegreesToRadians(90)), 28.0), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new UniformPlanarArrayTestCase(tgpp, 10, 10, @@ -387,7 +387,7 @@ UniformPlanarArrayTestSuite::UniformPlanarArrayTestSuite() DegreesToRadians(45), Angles(DegreesToRadians(0), DegreesToRadians(135)), 28.0), - TestCase::QUICK); + TestCase::Duration::QUICK); } static UniformPlanarArrayTestSuite staticUniformPlanarArrayTestSuiteInstance; diff --git a/src/aodv/examples/aodv.cc b/src/aodv/examples/aodv.cc index 0d32222d4b..79e2e378be 100644 --- a/src/aodv/examples/aodv.cc +++ b/src/aodv/examples/aodv.cc @@ -33,6 +33,12 @@ using namespace ns3; +/** + * \defgroup aodv-examples AODV Examples + * \ingroup aodv + * \ingroup examples + */ + /** * \ingroup aodv-examples * \ingroup examples diff --git a/src/aodv/model/aodv-routing-protocol.cc b/src/aodv/model/aodv-routing-protocol.cc index 158dccde11..4d46b8027b 100644 --- a/src/aodv/model/aodv-routing-protocol.cc +++ b/src/aodv/model/aodv-routing-protocol.cc @@ -1685,33 +1685,24 @@ RoutingProtocol::RecvReply(Ptr p, Ipv4Address receiver, Ipv4Address send RoutingTableEntry toDst; if (m_routingTable.LookupRoute(dst, toDst)) { - /* - * The existing entry is updated only in the following circumstances: - * (i) the sequence number in the routing table is marked as invalid in route table entry. - */ - if (!toDst.GetValidSeqNo()) - { - m_routingTable.Update(newEntry); - } - // (ii)the Destination Sequence Number in the RREP is greater than the node's copy of the - // destination sequence number and the known value is valid, - else if ((int32_t(rrepHeader.GetDstSeqno()) - int32_t(toDst.GetSeqNo())) > 0) - { - m_routingTable.Update(newEntry); - } - else - { + // The existing entry is updated only in the following circumstances: + if ( + // (i) the sequence number in the routing table is marked as invalid in route table + // entry. + (!toDst.GetValidSeqNo()) || + + // (ii) the Destination Sequence Number in the RREP is greater than the node's copy of + // the destination sequence number and the known value is valid, + ((int32_t(rrepHeader.GetDstSeqno()) - int32_t(toDst.GetSeqNo())) > 0) || + // (iii) the sequence numbers are the same, but the route is marked as inactive. - if ((rrepHeader.GetDstSeqno() == toDst.GetSeqNo()) && (toDst.GetFlag() != VALID)) - { - m_routingTable.Update(newEntry); - } - // (iv) the sequence numbers are the same, and the New Hop Count is smaller than the + (rrepHeader.GetDstSeqno() == toDst.GetSeqNo() && toDst.GetFlag() != VALID) || + + // (iv) the sequence numbers are the same, and the New Hop Count is smaller than the // hop count in route table entry. - else if ((rrepHeader.GetDstSeqno() == toDst.GetSeqNo()) && (hop < toDst.GetHop())) - { - m_routingTable.Update(newEntry); - } + (rrepHeader.GetDstSeqno() == toDst.GetSeqNo() && hop < toDst.GetHop())) + { + m_routingTable.Update(newEntry); } } else diff --git a/src/aodv/test/aodv-id-cache-test-suite.cc b/src/aodv/test/aodv-id-cache-test-suite.cc index 780f23fe15..b3325d6c74 100644 --- a/src/aodv/test/aodv-id-cache-test-suite.cc +++ b/src/aodv/test/aodv-id-cache-test-suite.cc @@ -118,9 +118,9 @@ class IdCacheTestSuite : public TestSuite { public: IdCacheTestSuite() - : TestSuite("aodv-routing-id-cache", UNIT) + : TestSuite("aodv-routing-id-cache", Type::UNIT) { - AddTestCase(new IdCacheTest, TestCase::QUICK); + AddTestCase(new IdCacheTest, TestCase::Duration::QUICK); } } g_idCacheTestSuite; ///< the test suite diff --git a/src/aodv/test/aodv-regression.cc b/src/aodv/test/aodv-regression.cc index bad3baa27e..d79384a80a 100644 --- a/src/aodv/test/aodv-regression.cc +++ b/src/aodv/test/aodv-regression.cc @@ -52,17 +52,18 @@ class AodvRegressionTestSuite : public TestSuite { public: AodvRegressionTestSuite() - : TestSuite("routing-aodv-regression", SYSTEM) + : TestSuite("routing-aodv-regression", Type::SYSTEM) { SetDataDir(NS_TEST_SOURCEDIR); // General RREQ-RREP-RRER test case - AddTestCase(new ChainRegressionTest("aodv-chain-regression-test"), TestCase::QUICK); + AddTestCase(new ChainRegressionTest("aodv-chain-regression-test"), + TestCase::Duration::QUICK); // \bugid{606} test case, should crash if bug is not fixed AddTestCase(new ChainRegressionTest("bug-606-test", Seconds(10), 3, Seconds(1)), - TestCase::QUICK); + TestCase::Duration::QUICK); // \bugid{772} UDP test case AddTestCase(new Bug772ChainTest("udp-chain-test", "ns3::UdpSocketFactory", Seconds(3), 10), - TestCase::QUICK); + TestCase::Duration::QUICK); } } g_aodvRegressionTestSuite; ///< the test suite diff --git a/src/aodv/test/aodv-test-suite.cc b/src/aodv/test/aodv-test-suite.cc index 35e8cc9ff3..deb6fffb3f 100644 --- a/src/aodv/test/aodv-test-suite.cc +++ b/src/aodv/test/aodv-test-suite.cc @@ -739,18 +739,18 @@ class AodvTestSuite : public TestSuite { public: AodvTestSuite() - : TestSuite("routing-aodv", UNIT) + : TestSuite("routing-aodv", Type::UNIT) { - AddTestCase(new NeighborTest, TestCase::QUICK); - AddTestCase(new TypeHeaderTest, TestCase::QUICK); - AddTestCase(new RreqHeaderTest, TestCase::QUICK); - AddTestCase(new RrepHeaderTest, TestCase::QUICK); - AddTestCase(new RrepAckHeaderTest, TestCase::QUICK); - AddTestCase(new RerrHeaderTest, TestCase::QUICK); - AddTestCase(new QueueEntryTest, TestCase::QUICK); - AddTestCase(new AodvRqueueTest, TestCase::QUICK); - AddTestCase(new AodvRtableEntryTest, TestCase::QUICK); - AddTestCase(new AodvRtableTest, TestCase::QUICK); + AddTestCase(new NeighborTest, TestCase::Duration::QUICK); + AddTestCase(new TypeHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new RreqHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new RrepHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new RrepAckHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new RerrHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new QueueEntryTest, TestCase::Duration::QUICK); + AddTestCase(new AodvRqueueTest, TestCase::Duration::QUICK); + AddTestCase(new AodvRtableEntryTest, TestCase::Duration::QUICK); + AddTestCase(new AodvRtableTest, TestCase::Duration::QUICK); } } g_aodvTestSuite; ///< the test suite diff --git a/src/aodv/test/loopback.cc b/src/aodv/test/loopback.cc index b4beff5973..3550c1fabb 100644 --- a/src/aodv/test/loopback.cc +++ b/src/aodv/test/loopback.cc @@ -197,11 +197,11 @@ class AodvLoopbackTestSuite : public TestSuite { public: AodvLoopbackTestSuite() - : TestSuite("routing-aodv-loopback", SYSTEM) + : TestSuite("routing-aodv-loopback", Type::SYSTEM) { SetDataDir(NS_TEST_SOURCEDIR); // UDP Echo loopback test case - AddTestCase(new LoopbackTestCase(), TestCase::QUICK); + AddTestCase(new LoopbackTestCase(), TestCase::Duration::QUICK); } } g_aodvLoopbackTestSuite; ///< the test suite diff --git a/src/applications/helper/bulk-send-helper.cc b/src/applications/helper/bulk-send-helper.cc index 6e53e06d4a..594ba90efa 100644 --- a/src/applications/helper/bulk-send-helper.cc +++ b/src/applications/helper/bulk-send-helper.cc @@ -21,59 +21,16 @@ #include "bulk-send-helper.h" -#include "ns3/inet-socket-address.h" -#include "ns3/names.h" -#include "ns3/packet-socket-address.h" -#include "ns3/string.h" +#include namespace ns3 { -BulkSendHelper::BulkSendHelper(std::string protocol, Address address) +BulkSendHelper::BulkSendHelper(const std::string& protocol, const Address& address) + : ApplicationHelper("ns3::BulkSendApplication") { - m_factory.SetTypeId("ns3::BulkSendApplication"); m_factory.Set("Protocol", StringValue(protocol)); m_factory.Set("Remote", AddressValue(address)); } -void -BulkSendHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -BulkSendHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -BulkSendHelper::Install(std::string nodeName) const -{ - Ptr node = Names::Find(nodeName); - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -BulkSendHelper::Install(NodeContainer c) const -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - apps.Add(InstallPriv(*i)); - } - - return apps; -} - -Ptr -BulkSendHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - } // namespace ns3 diff --git a/src/applications/helper/bulk-send-helper.h b/src/applications/helper/bulk-send-helper.h index 803b11d91f..5cb6a7137e 100644 --- a/src/applications/helper/bulk-send-helper.h +++ b/src/applications/helper/bulk-send-helper.h @@ -22,15 +22,7 @@ #ifndef BULK_SEND_HELPER_H #define BULK_SEND_HELPER_H -#include "ns3/address.h" -#include "ns3/application-container.h" -#include "ns3/attribute.h" -#include "ns3/net-device.h" -#include "ns3/node-container.h" -#include "ns3/object-factory.h" - -#include -#include +#include namespace ns3 { @@ -40,7 +32,7 @@ namespace ns3 * \brief A helper to make it easier to instantiate an ns3::BulkSendApplication * on a set of nodes. */ -class BulkSendHelper +class BulkSendHelper : public ApplicationHelper { public: /** @@ -53,58 +45,9 @@ class BulkSendHelper * \param address the address of the remote node to send traffic * to. */ - BulkSendHelper(std::string protocol, Address address); - - /** - * Helper function used to set the underlying application attributes, - * _not_ the socket attributes. - * - * \param name the name of the application attribute to set - * \param value the value of the application attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); - - /** - * Install an ns3::BulkSendApplication on each node of the input container - * configured with all the attributes set with SetAttribute. - * - * \param c NodeContainer of the set of nodes on which an BulkSendApplication - * will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(NodeContainer c) const; - - /** - * Install an ns3::BulkSendApplication on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an BulkSendApplication will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(Ptr node) const; - - /** - * Install an ns3::BulkSendApplication on the node configured with all the - * attributes set with SetAttribute. - * - * \param nodeName The node on which an BulkSendApplication will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(std::string nodeName) const; - - private: - /** - * Install an ns3::BulkSendApplication on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an BulkSendApplication will be installed. - * \returns Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - - ObjectFactory m_factory; //!< Object factory. + BulkSendHelper(const std::string& protocol, const Address& address); }; } // namespace ns3 -#endif /* ON_OFF_HELPER_H */ +#endif /* BULK_SEND_HELPER_H */ diff --git a/src/applications/helper/on-off-helper.cc b/src/applications/helper/on-off-helper.cc index 5dfcdbc134..31b3272679 100644 --- a/src/applications/helper/on-off-helper.cc +++ b/src/applications/helper/on-off-helper.cc @@ -16,87 +16,23 @@ * * Author: Mathieu Lacage */ + #include "on-off-helper.h" -#include "ns3/data-rate.h" -#include "ns3/inet-socket-address.h" -#include "ns3/names.h" -#include "ns3/onoff-application.h" -#include "ns3/packet-socket-address.h" -#include "ns3/random-variable-stream.h" -#include "ns3/string.h" -#include "ns3/uinteger.h" +#include +#include +#include namespace ns3 { -OnOffHelper::OnOffHelper(std::string protocol, Address address) +OnOffHelper::OnOffHelper(const std::string& protocol, const Address& address) + : ApplicationHelper("ns3::OnOffApplication") { - m_factory.SetTypeId("ns3::OnOffApplication"); m_factory.Set("Protocol", StringValue(protocol)); m_factory.Set("Remote", AddressValue(address)); } -void -OnOffHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -OnOffHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -OnOffHelper::Install(std::string nodeName) const -{ - Ptr node = Names::Find(nodeName); - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -OnOffHelper::Install(NodeContainer c) const -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - apps.Add(InstallPriv(*i)); - } - - return apps; -} - -Ptr -OnOffHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - -int64_t -OnOffHelper::AssignStreams(NodeContainer c, int64_t stream) -{ - int64_t currentStream = stream; - Ptr node; - for (auto i = c.Begin(); i != c.End(); ++i) - { - node = (*i); - for (uint32_t j = 0; j < node->GetNApplications(); j++) - { - Ptr onoff = DynamicCast(node->GetApplication(j)); - if (onoff) - { - currentStream += onoff->AssignStreams(currentStream); - } - } - } - return (currentStream - stream); -} - void OnOffHelper::SetConstantRate(DataRate dataRate, uint32_t packetSize) { diff --git a/src/applications/helper/on-off-helper.h b/src/applications/helper/on-off-helper.h index d0bf8e77fb..b0f1ebb799 100644 --- a/src/applications/helper/on-off-helper.h +++ b/src/applications/helper/on-off-helper.h @@ -16,31 +16,24 @@ * * Author: Mathieu Lacage */ + #ifndef ON_OFF_HELPER_H #define ON_OFF_HELPER_H -#include "ns3/address.h" -#include "ns3/application-container.h" -#include "ns3/attribute.h" -#include "ns3/net-device.h" -#include "ns3/node-container.h" -#include "ns3/object-factory.h" -#include "ns3/onoff-application.h" +#include +#include #include -#include namespace ns3 { -class DataRate; - /** * \ingroup onoff * \brief A helper to make it easier to instantiate an ns3::OnOffApplication * on a set of nodes. */ -class OnOffHelper +class OnOffHelper : public ApplicationHelper { public: /** @@ -53,15 +46,7 @@ class OnOffHelper * \param address the address of the remote node to send traffic * to. */ - OnOffHelper(std::string protocol, Address address); - - /** - * Helper function used to set the underlying application attributes. - * - * \param name the name of the application attribute to set - * \param value the value of the application attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); + OnOffHelper(const std::string& protocol, const Address& address); /** * Helper function to set a constant rate source. Equivalent to @@ -72,59 +57,6 @@ class OnOffHelper * \param packetSize size in bytes of the packet payloads generated */ void SetConstantRate(DataRate dataRate, uint32_t packetSize = 512); - - /** - * Install an ns3::OnOffApplication on each node of the input container - * configured with all the attributes set with SetAttribute. - * - * \param c NodeContainer of the set of nodes on which an OnOffApplication - * will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(NodeContainer c) const; - - /** - * Install an ns3::OnOffApplication on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an OnOffApplication will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(Ptr node) const; - - /** - * Install an ns3::OnOffApplication on the node configured with all the - * attributes set with SetAttribute. - * - * \param nodeName The node on which an OnOffApplication will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(std::string nodeName) const; - - /** - * Assign a fixed random variable stream number to the random variables - * used by this model. Return the number of streams (possibly zero) that - * have been assigned. The Install() method should have previously been - * called by the user. - * - * \param stream first stream index to use - * \param c NodeContainer of the set of nodes for which the OnOffApplication - * should be modified to use a fixed stream - * \return the number of stream indices assigned by this helper - */ - int64_t AssignStreams(NodeContainer c, int64_t stream); - - private: - /** - * Install an ns3::OnOffApplication on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an OnOffApplication will be installed. - * \returns Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - - ObjectFactory m_factory; //!< Object factory. }; } // namespace ns3 diff --git a/src/applications/helper/packet-sink-helper.cc b/src/applications/helper/packet-sink-helper.cc index 72f8af81a4..3c61cfb37c 100644 --- a/src/applications/helper/packet-sink-helper.cc +++ b/src/applications/helper/packet-sink-helper.cc @@ -19,58 +19,16 @@ #include "packet-sink-helper.h" -#include "ns3/inet-socket-address.h" -#include "ns3/names.h" -#include "ns3/string.h" +#include namespace ns3 { -PacketSinkHelper::PacketSinkHelper(std::string protocol, Address address) +PacketSinkHelper::PacketSinkHelper(const std::string& protocol, const Address& address) + : ApplicationHelper("ns3::PacketSink") { - m_factory.SetTypeId("ns3::PacketSink"); m_factory.Set("Protocol", StringValue(protocol)); m_factory.Set("Local", AddressValue(address)); } -void -PacketSinkHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -PacketSinkHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -PacketSinkHelper::Install(std::string nodeName) const -{ - Ptr node = Names::Find(nodeName); - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -PacketSinkHelper::Install(NodeContainer c) const -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - apps.Add(InstallPriv(*i)); - } - - return apps; -} - -Ptr -PacketSinkHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - } // namespace ns3 diff --git a/src/applications/helper/packet-sink-helper.h b/src/applications/helper/packet-sink-helper.h index c1c17225cf..b1d43e8d9f 100644 --- a/src/applications/helper/packet-sink-helper.h +++ b/src/applications/helper/packet-sink-helper.h @@ -16,13 +16,11 @@ * * Author: Mathieu Lacage */ + #ifndef PACKET_SINK_HELPER_H #define PACKET_SINK_HELPER_H -#include "ns3/application-container.h" -#include "ns3/ipv4-address.h" -#include "ns3/node-container.h" -#include "ns3/object-factory.h" +#include namespace ns3 { @@ -32,7 +30,7 @@ namespace ns3 * \brief A helper to make it easier to instantiate an ns3::PacketSinkApplication * on a set of nodes. */ -class PacketSinkHelper +class PacketSinkHelper : public ApplicationHelper { public: /** @@ -45,54 +43,7 @@ class PacketSinkHelper * \param address the address of the sink, * */ - PacketSinkHelper(std::string protocol, Address address); - - /** - * Helper function used to set the underlying application attributes. - * - * \param name the name of the application attribute to set - * \param value the value of the application attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); - - /** - * Install an ns3::PacketSinkApplication on each node of the input container - * configured with all the attributes set with SetAttribute. - * - * \param c NodeContainer of the set of nodes on which a PacketSinkApplication - * will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(NodeContainer c) const; - - /** - * Install an ns3::PacketSinkApplication on each node of the input container - * configured with all the attributes set with SetAttribute. - * - * \param node The node on which a PacketSinkApplication will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(Ptr node) const; - - /** - * Install an ns3::PacketSinkApplication on each node of the input container - * configured with all the attributes set with SetAttribute. - * - * \param nodeName The name of the node on which a PacketSinkApplication will be installed. - * \returns Container of Ptr to the applications installed. - */ - ApplicationContainer Install(std::string nodeName) const; - - private: - /** - * Install an ns3::PacketSink on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an PacketSink will be installed. - * \returns Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - ObjectFactory m_factory; //!< Object factory. + PacketSinkHelper(const std::string& protocol, const Address& address); }; } // namespace ns3 diff --git a/src/applications/helper/three-gpp-http-helper.cc b/src/applications/helper/three-gpp-http-helper.cc index 4cc25643aa..c00c19702d 100644 --- a/src/applications/helper/three-gpp-http-helper.cc +++ b/src/applications/helper/three-gpp-http-helper.cc @@ -25,105 +25,23 @@ #include "three-gpp-http-helper.h" -#include - namespace ns3 { // 3GPP HTTP CLIENT HELPER ///////////////////////////////////////////////////////// ThreeGppHttpClientHelper::ThreeGppHttpClientHelper(const Address& address) + : ApplicationHelper("ns3::ThreeGppHttpClient") { - m_factory.SetTypeId("ns3::ThreeGppHttpClient"); m_factory.Set("RemoteServerAddress", AddressValue(address)); } -void -ThreeGppHttpClientHelper::SetAttribute(const std::string& name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -ThreeGppHttpClientHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -ThreeGppHttpClientHelper::Install(const std::string& nodeName) const -{ - Ptr node = Names::Find(nodeName); - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -ThreeGppHttpClientHelper::Install(NodeContainer c) const -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - apps.Add(InstallPriv(*i)); - } - - return apps; -} - -Ptr -ThreeGppHttpClientHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - // HTTP SERVER HELPER ///////////////////////////////////////////////////////// ThreeGppHttpServerHelper::ThreeGppHttpServerHelper(const Address& address) + : ApplicationHelper("ns3::ThreeGppHttpServer") { - m_factory.SetTypeId("ns3::ThreeGppHttpServer"); m_factory.Set("LocalAddress", AddressValue(address)); } -void -ThreeGppHttpServerHelper::SetAttribute(const std::string& name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -ThreeGppHttpServerHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -ThreeGppHttpServerHelper::Install(const std::string& nodeName) const -{ - Ptr node = Names::Find(nodeName); - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -ThreeGppHttpServerHelper::Install(NodeContainer c) const -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - apps.Add(InstallPriv(*i)); - } - - return apps; -} - -Ptr -ThreeGppHttpServerHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - } // namespace ns3 diff --git a/src/applications/helper/three-gpp-http-helper.h b/src/applications/helper/three-gpp-http-helper.h index f4f131812e..5d2363a173 100644 --- a/src/applications/helper/three-gpp-http-helper.h +++ b/src/applications/helper/three-gpp-http-helper.h @@ -26,9 +26,7 @@ #ifndef THREE_GPP_HTTP_HELPER_H #define THREE_GPP_HTTP_HELPER_H -#include -#include -#include +#include namespace ns3 { @@ -37,7 +35,7 @@ namespace ns3 * \ingroup applications * Helper to make it easier to instantiate an ThreeGppHttpClient on a set of nodes. */ -class ThreeGppHttpClientHelper +class ThreeGppHttpClientHelper : public ApplicationHelper { public: /** @@ -46,61 +44,13 @@ class ThreeGppHttpClientHelper * \param address The address of the remote server node to send traffic to. */ ThreeGppHttpClientHelper(const Address& address); - - /** - * Helper function used to set the underlying application attributes, but - * *not* the socket attributes. - * \param name The name of the application attribute to set. - * \param value The value of the application attribute to set. - */ - void SetAttribute(const std::string& name, const AttributeValue& value); - - /** - * Install a ThreeGppHttpClient on each node of the input container configured with - * all the attributes set with SetAttribute(). - * \param c NodeContainer of the set of nodes on which an ThreeGppHttpClient - * will be installed. - * \return Container of Ptr to the applications installed. - */ - ApplicationContainer Install(NodeContainer c) const; - - /** - * Install a ThreeGppHttpClient on each node of the input container - * configured with all the attributes set with SetAttribute(). - * \param node The node on which an ThreeGppHttpClient will be installed. - * \return Container of Ptr to the applications installed. - */ - ApplicationContainer Install(Ptr node) const; - - /** - * Install a ThreeGppHttpClient on each node of the input container - * configured with all the attributes set with SetAttribute(). - * \param nodeName The name of the node on which an ThreeGppHttpClient - * will be installed. - * \return Container of Ptr to the applications installed. - */ - ApplicationContainer Install(const std::string& nodeName) const; - - private: - /** - * \internal - * Install a ThreeGppHttpClient on the node configured with all the - * attributes set with SetAttribute(). - * \param node The node on which an ThreeGppHttpClient will be installed. - * \return Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - - /// Used to instantiate an ThreeGppHttpClient instance. - ObjectFactory m_factory; - }; // end of `class ThreeGppHttpClientHelper` /** * \ingroup http * Helper to make it easier to instantiate an ThreeGppHttpServer on a set of nodes. */ -class ThreeGppHttpServerHelper +class ThreeGppHttpServerHelper : public ApplicationHelper { public: /** @@ -109,54 +59,6 @@ class ThreeGppHttpServerHelper * \param address The address of the server. */ ThreeGppHttpServerHelper(const Address& address); - - /** - * Helper function used to set the underlying application attributes, but - * *not* the socket attributes. - * \param name The name of the application attribute to set. - * \param value The value of the application attribute to set. - */ - void SetAttribute(const std::string& name, const AttributeValue& value); - - /** - * Install an ThreeGppHttpServer on each node of the input container - * configured with all the attributes set with SetAttribute(). - * \param c NodeContainer of the set of nodes on which an ThreeGppHttpServer - * will be installed. - * \return Container of Ptr to the applications installed. - */ - ApplicationContainer Install(NodeContainer c) const; - - /** - * Install an ThreeGppHttpServer on each node of the input container - * configured with all the attributes set with SetAttribute(). - * \param node The node on which an ThreeGppHttpServer will be installed. - * \return Container of Ptr to the applications installed. - */ - ApplicationContainer Install(Ptr node) const; - - /** - * Install an ThreeGppHttpServer on each node of the input container - * configured with all the attributes set with SetAttribute(). - * \param nodeName The name of the node on which an ThreeGppHttpServer - * will be installed. - * \return Container of Ptr to the applications installed. - */ - ApplicationContainer Install(const std::string& nodeName) const; - - private: - /** - * \internal - * Install an ThreeGppHttpServer on the node configured with all the - * attributes set with SetAttribute(). - * \param node The node on which an ThreeGppHttpServer will be installed. - * \return Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - - /// Used to instantiate a ThreeGppHttpServer instance. - ObjectFactory m_factory; - }; // end of `class ThreeGppHttpServerHelper` } // namespace ns3 diff --git a/src/applications/helper/udp-client-server-helper.cc b/src/applications/helper/udp-client-server-helper.cc index 99fd4b7105..8d7bbe4f77 100644 --- a/src/applications/helper/udp-client-server-helper.cc +++ b/src/applications/helper/udp-client-server-helper.cc @@ -16,131 +16,61 @@ * * Author: Mohamed Amine Ismail */ + #include "udp-client-server-helper.h" -#include "ns3/string.h" -#include "ns3/udp-client.h" -#include "ns3/udp-server.h" -#include "ns3/udp-trace-client.h" -#include "ns3/uinteger.h" +#include +#include namespace ns3 { UdpServerHelper::UdpServerHelper() + : ApplicationHelper(UdpServer::GetTypeId()) { - m_factory.SetTypeId(UdpServer::GetTypeId()); } UdpServerHelper::UdpServerHelper(uint16_t port) + : UdpServerHelper() { - m_factory.SetTypeId(UdpServer::GetTypeId()); SetAttribute("Port", UintegerValue(port)); } -void -UdpServerHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -UdpServerHelper::Install(NodeContainer c) -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - Ptr node = *i; - - m_server = m_factory.Create(); - node->AddApplication(m_server); - apps.Add(m_server); - } - return apps; -} - -Ptr -UdpServerHelper::GetServer() -{ - return m_server; -} - UdpClientHelper::UdpClientHelper() + : ApplicationHelper(UdpClient::GetTypeId()) { - m_factory.SetTypeId(UdpClient::GetTypeId()); -} - -UdpClientHelper::UdpClientHelper(Address address, uint16_t port) -{ - m_factory.SetTypeId(UdpClient::GetTypeId()); - SetAttribute("RemoteAddress", AddressValue(address)); - SetAttribute("RemotePort", UintegerValue(port)); } -UdpClientHelper::UdpClientHelper(Address address) +UdpClientHelper::UdpClientHelper(const Address& address) + : UdpClientHelper() { - m_factory.SetTypeId(UdpClient::GetTypeId()); SetAttribute("RemoteAddress", AddressValue(address)); } -void -UdpClientHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -UdpClientHelper::Install(NodeContainer c) +UdpClientHelper::UdpClientHelper(const Address& address, uint16_t port) + : UdpClientHelper(address) { - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - Ptr node = *i; - Ptr client = m_factory.Create(); - node->AddApplication(client); - apps.Add(client); - } - return apps; + SetAttribute("RemotePort", UintegerValue(port)); } UdpTraceClientHelper::UdpTraceClientHelper() + : ApplicationHelper(UdpTraceClient::GetTypeId()) { - m_factory.SetTypeId(UdpTraceClient::GetTypeId()); } -UdpTraceClientHelper::UdpTraceClientHelper(Address address, uint16_t port, std::string filename) +UdpTraceClientHelper::UdpTraceClientHelper(const Address& address, const std::string& filename) + : UdpTraceClientHelper() { - m_factory.SetTypeId(UdpTraceClient::GetTypeId()); SetAttribute("RemoteAddress", AddressValue(address)); - SetAttribute("RemotePort", UintegerValue(port)); SetAttribute("TraceFilename", StringValue(filename)); } -UdpTraceClientHelper::UdpTraceClientHelper(Address address, std::string filename) +UdpTraceClientHelper::UdpTraceClientHelper(const Address& address, + uint16_t port, + const std::string& filename) + : UdpTraceClientHelper(address, filename) { - m_factory.SetTypeId(UdpTraceClient::GetTypeId()); - SetAttribute("RemoteAddress", AddressValue(address)); - SetAttribute("TraceFilename", StringValue(filename)); -} - -void -UdpTraceClientHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -UdpTraceClientHelper::Install(NodeContainer c) -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - Ptr node = *i; - Ptr client = m_factory.Create(); - node->AddApplication(client); - apps.Add(client); - } - return apps; + SetAttribute("RemotePort", UintegerValue(port)); } } // namespace ns3 diff --git a/src/applications/helper/udp-client-server-helper.h b/src/applications/helper/udp-client-server-helper.h index 41bf51cf10..2f09aae3f7 100644 --- a/src/applications/helper/udp-client-server-helper.h +++ b/src/applications/helper/udp-client-server-helper.h @@ -16,15 +16,14 @@ * * Author: Mohamed Amine Ismail */ + #ifndef UDP_CLIENT_SERVER_HELPER_H #define UDP_CLIENT_SERVER_HELPER_H -#include "ns3/application-container.h" -#include "ns3/ipv4-address.h" -#include "ns3/node-container.h" -#include "ns3/object-factory.h" -#include "ns3/udp-client.h" -#include "ns3/udp-server.h" +#include +#include +#include +#include #include @@ -36,7 +35,7 @@ namespace ns3 * and uses the information carried into their payload to compute * delay and to determine if some packets are lost. */ -class UdpServerHelper +class UdpServerHelper : public ApplicationHelper { public: /** @@ -53,38 +52,6 @@ class UdpServerHelper * \param port The port the server will wait on for incoming packets */ UdpServerHelper(uint16_t port); - - /** - * Record an attribute to be set in each Application after it is is created. - * - * \param name the name of the attribute to set - * \param value the value of the attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); - - /** - * Create one UDP server application on each of the Nodes in the - * NodeContainer. - * - * \param c The nodes on which to create the Applications. The nodes - * are specified by a NodeContainer. - * \returns The applications created, one Application per Node in the - * NodeContainer. - */ - ApplicationContainer Install(NodeContainer c); - - /** - * \brief Return the last created server. - * - * This function is mainly used for testing. - * - * \returns a Ptr to the last created server application - */ - Ptr GetServer(); - - private: - ObjectFactory m_factory; //!< Object factory. - Ptr m_server; //!< The last created server application }; /** @@ -93,7 +60,7 @@ class UdpServerHelper * a 32bit sequence number and a 64 bit time stamp. * */ -class UdpClientHelper +class UdpClientHelper : public ApplicationHelper { public: /** @@ -113,7 +80,7 @@ class UdpClientHelper * \param port The port number of the remote UDP server */ - UdpClientHelper(Address ip, uint16_t port); + UdpClientHelper(const Address& ip, uint16_t port); /** * Create UdpClientHelper which will make life easier for people trying * to set up simulations with udp-client-server. Use this variant with @@ -123,27 +90,7 @@ class UdpClientHelper * \param addr The address of the remote UDP server */ - UdpClientHelper(Address addr); - - /** - * Record an attribute to be set in each Application after it is is created. - * - * \param name the name of the attribute to set - * \param value the value of the attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); - - /** - * \param c the nodes - * - * Create one UDP client application on each of the input nodes - * - * \returns the applications created, one application per input node. - */ - ApplicationContainer Install(NodeContainer c); - - private: - ObjectFactory m_factory; //!< Object factory. + UdpClientHelper(const Address& addr); }; /** @@ -158,7 +105,7 @@ class UdpClientHelper * \li -3- the third one indicates the time on which the frame was generated by the encoder * \li -4- the fourth one indicates the frame size in byte */ -class UdpTraceClientHelper +class UdpTraceClientHelper : public ApplicationHelper { public: /** @@ -178,7 +125,8 @@ class UdpTraceClientHelper * \param port The port number of the remote UDP server * \param filename the file from which packet traces will be loaded */ - UdpTraceClientHelper(Address ip, uint16_t port, std::string filename); + UdpTraceClientHelper(const Address& ip, uint16_t port, const std::string& filename = ""); + /** * Create UdpTraceClientHelper which will make life easier for people trying * to set up simulations with udp-client-server. Use this variant with @@ -188,27 +136,7 @@ class UdpTraceClientHelper * \param addr The address of the remote UDP server * \param filename the file from which packet traces will be loaded */ - UdpTraceClientHelper(Address addr, std::string filename); - - /** - * Record an attribute to be set in each Application after it is is created. - * - * \param name the name of the attribute to set - * \param value the value of the attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); - - /** - * \param c the nodes - * - * Create one UDP trace client application on each of the input nodes - * - * \returns the applications created, one application per input node. - */ - ApplicationContainer Install(NodeContainer c); - - private: - ObjectFactory m_factory; //!< Object factory. + UdpTraceClientHelper(const Address& addr, const std::string& filename = ""); }; } // namespace ns3 diff --git a/src/applications/helper/udp-echo-helper.cc b/src/applications/helper/udp-echo-helper.cc index ce57602233..e85e4d93a9 100644 --- a/src/applications/helper/udp-echo-helper.cc +++ b/src/applications/helper/udp-echo-helper.cc @@ -16,9 +16,9 @@ * * Author: Mathieu Lacage */ + #include "udp-echo-helper.h" -#include "ns3/names.h" #include "ns3/udp-echo-client.h" #include "ns3/udp-echo-server.h" #include "ns3/uinteger.h" @@ -27,72 +27,26 @@ namespace ns3 { UdpEchoServerHelper::UdpEchoServerHelper(uint16_t port) + : ApplicationHelper(UdpEchoServer::GetTypeId()) { - m_factory.SetTypeId(UdpEchoServer::GetTypeId()); SetAttribute("Port", UintegerValue(port)); } -void -UdpEchoServerHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -ApplicationContainer -UdpEchoServerHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -UdpEchoServerHelper::Install(std::string nodeName) const -{ - Ptr node = Names::Find(nodeName); - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -UdpEchoServerHelper::Install(NodeContainer c) const -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - apps.Add(InstallPriv(*i)); - } - - return apps; -} - -Ptr -UdpEchoServerHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - -UdpEchoClientHelper::UdpEchoClientHelper(Address address, uint16_t port) +UdpEchoClientHelper::UdpEchoClientHelper(const Address& address, uint16_t port) + : ApplicationHelper(UdpEchoClient::GetTypeId()) { - m_factory.SetTypeId(UdpEchoClient::GetTypeId()); SetAttribute("RemoteAddress", AddressValue(address)); SetAttribute("RemotePort", UintegerValue(port)); } -UdpEchoClientHelper::UdpEchoClientHelper(Address address) +UdpEchoClientHelper::UdpEchoClientHelper(const Address& address) + : ApplicationHelper(UdpEchoClient::GetTypeId()) { - m_factory.SetTypeId(UdpEchoClient::GetTypeId()); SetAttribute("RemoteAddress", AddressValue(address)); } void -UdpEchoClientHelper::SetAttribute(std::string name, const AttributeValue& value) -{ - m_factory.Set(name, value); -} - -void -UdpEchoClientHelper::SetFill(Ptr app, std::string fill) +UdpEchoClientHelper::SetFill(Ptr app, const std::string& fill) { app->GetObject()->SetFill(fill); } @@ -112,38 +66,4 @@ UdpEchoClientHelper::SetFill(Ptr app, app->GetObject()->SetFill(fill, fillLength, dataLength); } -ApplicationContainer -UdpEchoClientHelper::Install(Ptr node) const -{ - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -UdpEchoClientHelper::Install(std::string nodeName) const -{ - Ptr node = Names::Find(nodeName); - return ApplicationContainer(InstallPriv(node)); -} - -ApplicationContainer -UdpEchoClientHelper::Install(NodeContainer c) const -{ - ApplicationContainer apps; - for (auto i = c.Begin(); i != c.End(); ++i) - { - apps.Add(InstallPriv(*i)); - } - - return apps; -} - -Ptr -UdpEchoClientHelper::InstallPriv(Ptr node) const -{ - Ptr app = m_factory.Create(); - node->AddApplication(app); - - return app; -} - } // namespace ns3 diff --git a/src/applications/helper/udp-echo-helper.h b/src/applications/helper/udp-echo-helper.h index 6b904baf0e..dfa6587d11 100644 --- a/src/applications/helper/udp-echo-helper.h +++ b/src/applications/helper/udp-echo-helper.h @@ -16,14 +16,11 @@ * * Author: Mathieu Lacage */ + #ifndef UDP_ECHO_HELPER_H #define UDP_ECHO_HELPER_H -#include "ns3/application-container.h" -#include "ns3/ipv4-address.h" -#include "ns3/ipv6-address.h" -#include "ns3/node-container.h" -#include "ns3/object-factory.h" +#include #include @@ -35,7 +32,7 @@ namespace ns3 * \brief Create a server application which waits for input UDP packets * and sends them back to the original sender. */ -class UdpEchoServerHelper +class UdpEchoServerHelper : public ApplicationHelper { public: /** @@ -45,66 +42,13 @@ class UdpEchoServerHelper * \param port The port the server will wait on for incoming packets */ UdpEchoServerHelper(uint16_t port); - - /** - * Record an attribute to be set in each Application after it is is created. - * - * \param name the name of the attribute to set - * \param value the value of the attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); - - /** - * Create a UdpEchoServerApplication on the specified Node. - * - * \param node The node on which to create the Application. The node is - * specified by a Ptr. - * - * \returns An ApplicationContainer holding the Application created, - */ - ApplicationContainer Install(Ptr node) const; - - /** - * Create a UdpEchoServerApplication on specified node - * - * \param nodeName The node on which to create the application. The node - * is specified by a node name previously registered with - * the Object Name Service. - * - * \returns An ApplicationContainer holding the Application created. - */ - ApplicationContainer Install(std::string nodeName) const; - - /** - * \param c The nodes on which to create the Applications. The nodes - * are specified by a NodeContainer. - * - * Create one udp echo server application on each of the Nodes in the - * NodeContainer. - * - * \returns The applications created, one Application per Node in the - * NodeContainer. - */ - ApplicationContainer Install(NodeContainer c) const; - - private: - /** - * Install an ns3::UdpEchoServer on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an UdpEchoServer will be installed. - * \returns Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - - ObjectFactory m_factory; //!< Object factory. }; /** * \ingroup udpecho * \brief Create an application which sends a UDP packet and waits for an echo of this packet */ -class UdpEchoClientHelper +class UdpEchoClientHelper : public ApplicationHelper { public: /** @@ -115,7 +59,7 @@ class UdpEchoClientHelper * \param ip The IP address of the remote udp echo server * \param port The port number of the remote udp echo server */ - UdpEchoClientHelper(Address ip, uint16_t port); + UdpEchoClientHelper(const Address& ip, uint16_t port); /** * Create UdpEchoClientHelper which will make life easier for people trying * to set up simulations with echos. Use this variant with addresses that do @@ -123,15 +67,7 @@ class UdpEchoClientHelper * * \param addr The address of the remote udp echo server */ - UdpEchoClientHelper(Address addr); - - /** - * Record an attribute to be set in each Application after it is is created. - * - * \param name the name of the attribute to set - * \param value the value of the attribute to set - */ - void SetAttribute(std::string name, const AttributeValue& value); + UdpEchoClientHelper(const Address& addr); /** * Given a pointer to a UdpEchoClient application, set the data fill of the @@ -145,7 +81,7 @@ class UdpEchoClientHelper * \param app Smart pointer to the application (real type must be UdpEchoClient). * \param fill The string to use as the actual echo data bytes. */ - void SetFill(Ptr app, std::string fill); + void SetFill(Ptr app, const std::string& fill); /** * Given a pointer to a UdpEchoClient application, set the data fill of the @@ -183,49 +119,6 @@ class UdpEchoClientHelper * \param dataLength The desired length of the final echo data. */ void SetFill(Ptr app, uint8_t* fill, uint32_t fillLength, uint32_t dataLength); - - /** - * Create a udp echo client application on the specified node. The Node - * is provided as a Ptr. - * - * \param node The Ptr on which to create the UdpEchoClientApplication. - * - * \returns An ApplicationContainer that holds a Ptr to the - * application created - */ - ApplicationContainer Install(Ptr node) const; - - /** - * Create a udp echo client application on the specified node. The Node - * is provided as a string name of a Node that has been previously - * associated using the Object Name Service. - * - * \param nodeName The name of the node on which to create the UdpEchoClientApplication - * - * \returns An ApplicationContainer that holds a Ptr to the - * application created - */ - ApplicationContainer Install(std::string nodeName) const; - - /** - * \param c the nodes - * - * Create one udp echo client application on each of the input nodes - * - * \returns the applications created, one application per input node. - */ - ApplicationContainer Install(NodeContainer c) const; - - private: - /** - * Install an ns3::UdpEchoClient on the node configured with all the - * attributes set with SetAttribute. - * - * \param node The node on which an UdpEchoClient will be installed. - * \returns Ptr to the application installed. - */ - Ptr InstallPriv(Ptr node) const; - ObjectFactory m_factory; //!< Object factory. }; } // namespace ns3 diff --git a/src/applications/model/bulk-send-application.cc b/src/applications/model/bulk-send-application.cc index 9b2100a0b1..5e4ffe4032 100644 --- a/src/applications/model/bulk-send-application.cc +++ b/src/applications/model/bulk-send-application.cc @@ -63,6 +63,12 @@ BulkSendApplication::GetTypeId() AddressValue(), MakeAddressAccessor(&BulkSendApplication::m_local), MakeAddressChecker()) + .AddAttribute("Tos", + "The Type of Service used to send IPv4 packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&BulkSendApplication::m_tos), + MakeUintegerChecker()) .AddAttribute("MaxBytes", "The total number of bytes to send. " "Once these bytes are sent, " @@ -153,6 +159,8 @@ BulkSendApplication::StartApplication() // Called at time specified by Start "In other words, use TCP instead of UDP."); } + NS_ABORT_MSG_IF(m_peer.IsInvalid(), "'Remote' attribute not properly set"); + if (!m_local.IsInvalid()) { NS_ABORT_MSG_IF((Inet6SocketAddress::IsMatchingType(m_peer) && @@ -179,6 +187,10 @@ BulkSendApplication::StartApplication() // Called at time specified by Start NS_FATAL_ERROR("Failed to bind socket"); } + if (InetSocketAddress::IsMatchingType(m_peer)) + { + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. + } m_socket->Connect(m_peer); m_socket->ShutdownRecv(); m_socket->SetConnectCallback(MakeCallback(&BulkSendApplication::ConnectionSucceeded, this), diff --git a/src/applications/model/bulk-send-application.h b/src/applications/model/bulk-send-application.h index 1e8a835d9a..6f4865908d 100644 --- a/src/applications/model/bulk-send-application.h +++ b/src/applications/model/bulk-send-application.h @@ -111,9 +111,8 @@ class BulkSendApplication : public Application void DoDispose() override; private: - // inherited from Application base class. - void StartApplication() override; // Called at time specified by Start - void StopApplication() override; // Called at time specified by Stop + void StartApplication() override; + void StopApplication() override; /** * \brief Send data until the L4 transmission buffer is full. @@ -126,6 +125,7 @@ class BulkSendApplication : public Application Address m_peer; //!< Peer address Address m_local; //!< Local address to bind to bool m_connected; //!< True if connected + uint8_t m_tos; //!< The packets Type of Service uint32_t m_sendSize; //!< Size of data to send each time uint64_t m_maxBytes; //!< Limit total number of bytes sent uint64_t m_totBytes; //!< Total bytes sent so far diff --git a/src/applications/model/onoff-application.cc b/src/applications/model/onoff-application.cc index c250e9c7c3..a5f32c37fb 100644 --- a/src/applications/model/onoff-application.cc +++ b/src/applications/model/onoff-application.cc @@ -79,6 +79,12 @@ OnOffApplication::GetTypeId() AddressValue(), MakeAddressAccessor(&OnOffApplication::m_local), MakeAddressChecker()) + .AddAttribute("Tos", + "The Type of Service used to send IPv4 packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&OnOffApplication::m_tos), + MakeUintegerChecker()) .AddAttribute("OnTime", "A RandomVariableStream used to pick the duration of the 'On' state.", StringValue("ns3::ConstantRandomVariable[Constant=1.0]"), @@ -186,6 +192,8 @@ OnOffApplication::StartApplication() // Called at time specified by Start m_socket = Socket::CreateSocket(GetNode(), m_tid); int ret = -1; + NS_ABORT_MSG_IF(m_peer.IsInvalid(), "'Remote' attribute not properly set"); + if (!m_local.IsInvalid()) { NS_ABORT_MSG_IF((Inet6SocketAddress::IsMatchingType(m_peer) && @@ -216,6 +224,10 @@ OnOffApplication::StartApplication() // Called at time specified by Start m_socket->SetConnectCallback(MakeCallback(&OnOffApplication::ConnectionSucceeded, this), MakeCallback(&OnOffApplication::ConnectionFailed, this)); + if (InetSocketAddress::IsMatchingType(m_peer)) + { + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. + } m_socket->Connect(m_peer); m_socket->SetAllowBroadcast(true); m_socket->ShutdownRecv(); @@ -256,7 +268,7 @@ OnOffApplication::CancelEvents() { NS_LOG_FUNCTION(this); - if (m_sendEvent.IsRunning() && m_cbrRateFailSafe == m_cbrRate) + if (m_sendEvent.IsPending() && m_cbrRateFailSafe == m_cbrRate) { // Cancel the pending send packet event // Calculate residual bits since last packet sent Time delta(Simulator::Now() - m_lastStartTime); diff --git a/src/applications/model/onoff-application.h b/src/applications/model/onoff-application.h index eb69943c89..a994abcece 100644 --- a/src/applications/model/onoff-application.h +++ b/src/applications/model/onoff-application.h @@ -122,22 +122,14 @@ class OnOffApplication : public Application */ Ptr GetSocket() const; - /** - * \brief Assign a fixed random variable stream number to the random variables - * used by this model. - * - * \param stream first stream index to use - * \return the number of stream indices assigned by this model - */ - int64_t AssignStreams(int64_t stream); + int64_t AssignStreams(int64_t stream) override; protected: void DoDispose() override; private: - // inherited from Application base class. - void StartApplication() override; // Called at time specified by Start - void StopApplication() override; // Called at time specified by Stop + void StartApplication() override; + void StopApplication() override; // helpers /** @@ -163,6 +155,7 @@ class OnOffApplication : public Application Address m_peer; //!< Peer address Address m_local; //!< Local address to bind to bool m_connected; //!< True if connected + uint8_t m_tos; //!< The packets Type of Service Ptr m_onTime; //!< rng for On Time Ptr m_offTime; //!< rng for Off Time DataRate m_cbrRate; //!< Rate that data is generated diff --git a/src/applications/model/packet-sink.cc b/src/applications/model/packet-sink.cc index 681c884c97..f1525fb923 100644 --- a/src/applications/model/packet-sink.cc +++ b/src/applications/model/packet-sink.cc @@ -133,6 +133,7 @@ PacketSink::StartApplication() // Called at time specified by Start if (!m_socket) { m_socket = Socket::CreateSocket(GetNode(), m_tid); + NS_ABORT_MSG_IF(m_local.IsInvalid(), "'Local' attribute not properly set"); if (m_socket->Bind(m_local) == -1) { NS_FATAL_ERROR("Failed to bind socket"); diff --git a/src/applications/model/packet-sink.h b/src/applications/model/packet-sink.h index bd66f6e567..6159997d61 100644 --- a/src/applications/model/packet-sink.h +++ b/src/applications/model/packet-sink.h @@ -115,9 +115,8 @@ class PacketSink : public Application void DoDispose() override; private: - // inherited from Application base class. - void StartApplication() override; // Called at time specified by Start - void StopApplication() override; // Called at time specified by Stop + void StartApplication() override; + void StopApplication() override; /** * \brief Handle a packet received by the application diff --git a/src/applications/model/three-gpp-http-client.cc b/src/applications/model/three-gpp-http-client.cc index 2fde0d5df3..dae0b99656 100644 --- a/src/applications/model/three-gpp-http-client.cc +++ b/src/applications/model/three-gpp-http-client.cc @@ -80,6 +80,12 @@ ThreeGppHttpClient::GetTypeId() UintegerValue(80), // the default HTTP port MakeUintegerAccessor(&ThreeGppHttpClient::m_remoteServerPort), MakeUintegerChecker()) + .AddAttribute("Tos", + "The Type of Service used to send packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&ThreeGppHttpClient::m_tos), + MakeUintegerChecker()) .AddTraceSource("RxPage", "A page has been received.", MakeTraceSourceAccessor(&ThreeGppHttpClient::m_rxPageTrace), @@ -362,7 +368,8 @@ ThreeGppHttpClient::OpenConnection() m_state == PARSING_MAIN_OBJECT || m_state == READING) { m_socket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId()); - + NS_ABORT_MSG_IF(m_remoteServerAddress.IsInvalid(), + "'RemoteServerAddress' attribute not properly set"); if (Ipv4Address::IsMatchingType(m_remoteServerAddress)) { int ret [[maybe_unused]]; @@ -375,6 +382,7 @@ ThreeGppHttpClient::OpenConnection() InetSocketAddress inetSocket = InetSocketAddress(ipv4, m_remoteServerPort); NS_LOG_INFO(this << " Connecting to " << ipv4 << " port " << m_remoteServerPort << " / " << inetSocket << "."); + m_socket->SetIpTos(m_tos); ret = m_socket->Connect(inetSocket); NS_LOG_DEBUG(this << " Connect() return value= " << ret << " GetErrNo= " << m_socket->GetErrno() << "."); diff --git a/src/applications/model/three-gpp-http-client.h b/src/applications/model/three-gpp-http-client.h index 344f9ec710..3e09bbe848 100644 --- a/src/applications/model/three-gpp-http-client.h +++ b/src/applications/model/three-gpp-http-client.h @@ -188,14 +188,12 @@ class ThreeGppHttpClient : public Application uint32_t numBytes); protected: - // Inherited from Object base class. void DoDispose() override; - // Inherited from Application base class. + private: void StartApplication() override; void StopApplication() override; - private: // SOCKET CALLBACK METHODS /** @@ -393,6 +391,8 @@ class ThreeGppHttpClient : public Application Address m_remoteServerAddress; /// The `RemoteServerPort` attribute. uint16_t m_remoteServerPort; + /// The `Tos` attribute. + uint8_t m_tos; // TRACE SOURCES diff --git a/src/applications/model/three-gpp-http-server.cc b/src/applications/model/three-gpp-http-server.cc index 3f7caa76d3..0acd43d6be 100644 --- a/src/applications/model/three-gpp-http-server.cc +++ b/src/applications/model/three-gpp-http-server.cc @@ -81,6 +81,12 @@ ThreeGppHttpServer::GetTypeId() UintegerValue(80), // the default HTTP port MakeUintegerAccessor(&ThreeGppHttpServer::m_localPort), MakeUintegerChecker()) + .AddAttribute("Tos", + "The Type of Service used to send packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&ThreeGppHttpServer::m_tos), + MakeUintegerChecker()) .AddAttribute("Mtu", "Maximum transmission unit (in bytes) of the TCP sockets " "used in this application, excluding the compulsory 40 " @@ -205,6 +211,9 @@ ThreeGppHttpServer::StartApplication() m_initialSocket = Socket::CreateSocket(GetNode(), TcpSocketFactory::GetTypeId()); m_initialSocket->SetAttribute("SegmentSize", UintegerValue(m_mtuSize)); + NS_ABORT_MSG_IF(m_localAddress.IsInvalid(), + "'LocalAddress' attribute not properly set"); + if (Ipv4Address::IsMatchingType(m_localAddress)) { const Ipv4Address ipv4 = Ipv4Address::ConvertFrom(m_localAddress); @@ -214,6 +223,8 @@ ThreeGppHttpServer::StartApplication() int ret [[maybe_unused]] = m_initialSocket->Bind(inetSocket); NS_LOG_DEBUG(this << " Bind() return value= " << ret << " GetErrNo= " << m_initialSocket->GetErrno() << "."); + + m_initialSocket->SetIpTos(m_tos); // Affects only IPv4 sockets. } else if (Ipv6Address::IsMatchingType(m_localAddress)) { @@ -225,6 +236,10 @@ ThreeGppHttpServer::StartApplication() NS_LOG_DEBUG(this << " Bind() return value= " << ret << " GetErrNo= " << m_initialSocket->GetErrno() << "."); } + else + { + NS_ABORT_MSG("Incompatible local address"); + } int ret [[maybe_unused]] = m_initialSocket->Listen(); NS_LOG_DEBUG(this << " Listen () return value= " << ret diff --git a/src/applications/model/three-gpp-http-server.h b/src/applications/model/three-gpp-http-server.h index e2781ad9d7..700936ff0b 100644 --- a/src/applications/model/three-gpp-http-server.h +++ b/src/applications/model/three-gpp-http-server.h @@ -148,14 +148,12 @@ class ThreeGppHttpServer : public Application Ptr socket); protected: - // Inherited from Object base class void DoDispose() override; - // Inherited from Application base class + private: void StartApplication() override; void StopApplication() override; - private: // SOCKET CALLBACK METHODS /** @@ -272,6 +270,8 @@ class ThreeGppHttpServer : public Application Address m_localAddress; /// The `LocalPort` attribute. uint16_t m_localPort; + /// The `Tos` attribute. + uint8_t m_tos; /// The `Mtu` attribute. uint32_t m_mtuSize; diff --git a/src/applications/model/udp-client.cc b/src/applications/model/udp-client.cc index 1d374d9f4a..470e360ef5 100644 --- a/src/applications/model/udp-client.cc +++ b/src/applications/model/udp-client.cc @@ -71,6 +71,12 @@ UdpClient::GetTypeId() UintegerValue(100), MakeUintegerAccessor(&UdpClient::m_peerPort), MakeUintegerChecker()) + .AddAttribute("Tos", + "The Type of Service used to send IPv4 packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&UdpClient::m_tos), + MakeUintegerChecker()) .AddAttribute("PacketSize", "Size of packets generated. The minimum packet size is 12 bytes which is " "the size of the header carrying the sequence number and the time stamp.", @@ -117,13 +123,6 @@ UdpClient::SetRemote(Address addr) m_peerAddress = addr; } -void -UdpClient::DoDispose() -{ - NS_LOG_FUNCTION(this); - Application::DoDispose(); -} - void UdpClient::StartApplication() { @@ -139,6 +138,7 @@ UdpClient::StartApplication() { NS_FATAL_ERROR("Failed to bind socket"); } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->Connect( InetSocketAddress(Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort)); } @@ -157,6 +157,7 @@ UdpClient::StartApplication() { NS_FATAL_ERROR("Failed to bind socket"); } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->Connect(m_peerAddress); } else if (Inet6SocketAddress::IsMatchingType(m_peerAddress)) diff --git a/src/applications/model/udp-client.h b/src/applications/model/udp-client.h index d5a14d93a1..89e4c1d668 100644 --- a/src/applications/model/udp-client.h +++ b/src/applications/model/udp-client.h @@ -71,9 +71,6 @@ class UdpClient : public Application */ uint64_t GetTotalTx() const; - protected: - void DoDispose() override; - private: void StartApplication() override; void StopApplication() override; @@ -98,6 +95,7 @@ class UdpClient : public Application Ptr m_socket; //!< Socket Address m_peerAddress; //!< Remote peer address uint16_t m_peerPort; //!< Remote peer port + uint8_t m_tos; //!< The packets Type of Service EventId m_sendEvent; //!< Event to send the next packet #ifdef NS3_LOG_ENABLE diff --git a/src/applications/model/udp-echo-client.cc b/src/applications/model/udp-echo-client.cc index abf302002d..00739372cc 100644 --- a/src/applications/model/udp-echo-client.cc +++ b/src/applications/model/udp-echo-client.cc @@ -65,6 +65,12 @@ UdpEchoClient::GetTypeId() UintegerValue(0), MakeUintegerAccessor(&UdpEchoClient::m_peerPort), MakeUintegerChecker()) + .AddAttribute("Tos", + "The Type of Service used to send IPv4 packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&UdpEchoClient::m_tos), + MakeUintegerChecker()) .AddAttribute( "PacketSize", "Size of echo data in outbound packets", @@ -125,13 +131,6 @@ UdpEchoClient::SetRemote(Address addr) m_peerAddress = addr; } -void -UdpEchoClient::DoDispose() -{ - NS_LOG_FUNCTION(this); - Application::DoDispose(); -} - void UdpEchoClient::StartApplication() { @@ -141,12 +140,14 @@ UdpEchoClient::StartApplication() { TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory"); m_socket = Socket::CreateSocket(GetNode(), tid); + NS_ABORT_MSG_IF(m_peerAddress.IsInvalid(), "'RemoteAddress' attribute not properly set"); if (Ipv4Address::IsMatchingType(m_peerAddress)) { if (m_socket->Bind() == -1) { NS_FATAL_ERROR("Failed to bind socket"); } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->Connect( InetSocketAddress(Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort)); } @@ -165,6 +166,7 @@ UdpEchoClient::StartApplication() { NS_FATAL_ERROR("Failed to bind socket"); } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->Connect(m_peerAddress); } else if (Inet6SocketAddress::IsMatchingType(m_peerAddress)) diff --git a/src/applications/model/udp-echo-client.h b/src/applications/model/udp-echo-client.h index ed7bed03d0..6a8804deba 100644 --- a/src/applications/model/udp-echo-client.h +++ b/src/applications/model/udp-echo-client.h @@ -130,9 +130,6 @@ class UdpEchoClient : public Application */ void SetFill(uint8_t* fill, uint32_t fillSize, uint32_t dataSize); - protected: - void DoDispose() override; - private: void StartApplication() override; void StopApplication() override; @@ -167,6 +164,7 @@ class UdpEchoClient : public Application Ptr m_socket; //!< Socket Address m_peerAddress; //!< Remote peer address uint16_t m_peerPort; //!< Remote peer port + uint8_t m_tos; //!< The packets Type of Service EventId m_sendEvent; //!< Event to send the next packet /// Callbacks for tracing the packet Tx events diff --git a/src/applications/model/udp-echo-server.cc b/src/applications/model/udp-echo-server.cc index f00eed7b42..ab77bddb9d 100644 --- a/src/applications/model/udp-echo-server.cc +++ b/src/applications/model/udp-echo-server.cc @@ -51,6 +51,12 @@ UdpEchoServer::GetTypeId() UintegerValue(9), MakeUintegerAccessor(&UdpEchoServer::m_port), MakeUintegerChecker()) + .AddAttribute("Tos", + "The Type of Service used to send IPv4 packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&UdpEchoServer::m_tos), + MakeUintegerChecker()) .AddTraceSource("Rx", "A packet has been received", MakeTraceSourceAccessor(&UdpEchoServer::m_rxTrace), @@ -74,13 +80,6 @@ UdpEchoServer::~UdpEchoServer() m_socket6 = nullptr; } -void -UdpEchoServer::DoDispose() -{ - NS_LOG_FUNCTION(this); - Application::DoDispose(); -} - void UdpEchoServer::StartApplication() { @@ -134,6 +133,7 @@ UdpEchoServer::StartApplication() } } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this)); m_socket6->SetRecvCallback(MakeCallback(&UdpEchoServer::HandleRead, this)); } diff --git a/src/applications/model/udp-echo-server.h b/src/applications/model/udp-echo-server.h index d71963a920..bc71f06506 100644 --- a/src/applications/model/udp-echo-server.h +++ b/src/applications/model/udp-echo-server.h @@ -52,9 +52,6 @@ class UdpEchoServer : public Application UdpEchoServer(); ~UdpEchoServer() override; - protected: - void DoDispose() override; - private: void StartApplication() override; void StopApplication() override; @@ -69,6 +66,7 @@ class UdpEchoServer : public Application void HandleRead(Ptr socket); uint16_t m_port; //!< Port on which we listen for incoming packets. + uint8_t m_tos; //!< The packets Type of Service Ptr m_socket; //!< IPv4 Socket Ptr m_socket6; //!< IPv6 Socket Address m_local; //!< local multicast address diff --git a/src/applications/model/udp-server.cc b/src/applications/model/udp-server.cc index 940d94ca54..f1a74e0941 100644 --- a/src/applications/model/udp-server.cc +++ b/src/applications/model/udp-server.cc @@ -54,6 +54,12 @@ UdpServer::GetTypeId() UintegerValue(100), MakeUintegerAccessor(&UdpServer::m_port), MakeUintegerChecker()) + .AddAttribute("Tos", + "The Type of Service used to send IPv4 packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&UdpServer::m_tos), + MakeUintegerChecker()) .AddAttribute("PacketWindowSize", "The size of the window used to compute the packet loss. This value " "should be a multiple of 8.", @@ -73,10 +79,10 @@ UdpServer::GetTypeId() } UdpServer::UdpServer() - : m_lossCounter(0) + : m_received(0), + m_lossCounter(0) { NS_LOG_FUNCTION(this); - m_received = 0; } UdpServer::~UdpServer() @@ -112,13 +118,6 @@ UdpServer::GetReceived() const return m_received; } -void -UdpServer::DoDispose() -{ - NS_LOG_FUNCTION(this); - Application::DoDispose(); -} - void UdpServer::StartApplication() { @@ -135,6 +134,7 @@ UdpServer::StartApplication() } } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->SetRecvCallback(MakeCallback(&UdpServer::HandleRead, this)); if (!m_socket6) diff --git a/src/applications/model/udp-server.h b/src/applications/model/udp-server.h index a824b5d96e..e730cc4b16 100644 --- a/src/applications/model/udp-server.h +++ b/src/applications/model/udp-server.h @@ -82,9 +82,6 @@ class UdpServer : public Application */ void SetPacketWindowSize(uint16_t size); - protected: - void DoDispose() override; - private: void StartApplication() override; void StopApplication() override; @@ -99,6 +96,7 @@ class UdpServer : public Application void HandleRead(Ptr socket); uint16_t m_port; //!< Port on which we listen for incoming packets. + uint8_t m_tos; //!< The packets Type of Service Ptr m_socket; //!< IPv4 Socket Ptr m_socket6; //!< IPv6 Socket uint64_t m_received; //!< Number of received packets diff --git a/src/applications/model/udp-trace-client.cc b/src/applications/model/udp-trace-client.cc index aa0e2deed0..b48c74750c 100644 --- a/src/applications/model/udp-trace-client.cc +++ b/src/applications/model/udp-trace-client.cc @@ -79,6 +79,12 @@ UdpTraceClient::GetTypeId() UintegerValue(100), MakeUintegerAccessor(&UdpTraceClient::m_peerPort), MakeUintegerChecker()) + .AddAttribute("Tos", + "The Type of Service used to send IPv4 packets. " + "All 8 bits of the TOS byte are set (including ECN bits).", + UintegerValue(0), + MakeUintegerAccessor(&UdpTraceClient::m_tos), + MakeUintegerChecker()) .AddAttribute("MaxPacketSize", "The maximum size of a packet (including the SeqTsHeader, 12 bytes).", UintegerValue(1024), @@ -175,13 +181,6 @@ UdpTraceClient::GetMaxPacketSize() return m_maxPacketSize; } -void -UdpTraceClient::DoDispose() -{ - NS_LOG_FUNCTION(this); - Application::DoDispose(); -} - void UdpTraceClient::LoadTrace(std::string filename) { @@ -258,12 +257,14 @@ UdpTraceClient::StartApplication() { TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory"); m_socket = Socket::CreateSocket(GetNode(), tid); + NS_ABORT_MSG_IF(m_peerAddress.IsInvalid(), "'RemoteAddress' attribute not properly set"); if (Ipv4Address::IsMatchingType(m_peerAddress)) { if (m_socket->Bind() == -1) { NS_FATAL_ERROR("Failed to bind socket"); } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->Connect( InetSocketAddress(Ipv4Address::ConvertFrom(m_peerAddress), m_peerPort)); } @@ -282,6 +283,7 @@ UdpTraceClient::StartApplication() { NS_FATAL_ERROR("Failed to bind socket"); } + m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets. m_socket->Connect(m_peerAddress); } else if (Inet6SocketAddress::IsMatchingType(m_peerAddress)) diff --git a/src/applications/model/udp-trace-client.h b/src/applications/model/udp-trace-client.h index c04f13828c..be93d1b80d 100644 --- a/src/applications/model/udp-trace-client.h +++ b/src/applications/model/udp-trace-client.h @@ -124,10 +124,10 @@ class UdpTraceClient : public Application */ void SetTraceLoop(bool traceLoop); - protected: - void DoDispose() override; - private: + void StartApplication() override; + void StopApplication() override; + /** * \brief Load a trace file * \param filename the trace file path @@ -137,8 +137,6 @@ class UdpTraceClient : public Application * \brief Load the default trace */ void LoadDefaultTrace(); - void StartApplication() override; - void StopApplication() override; /** * \brief Send a packet @@ -166,6 +164,7 @@ class UdpTraceClient : public Application Ptr m_socket; //!< Socket Address m_peerAddress; //!< Remote peer address uint16_t m_peerPort; //!< Remote peer port + uint8_t m_tos; //!< The packets Type of Service EventId m_sendEvent; //!< Event to send the next packet std::vector m_entries; //!< Entries in the trace to send diff --git a/src/applications/test/bulk-send-application-test-suite.cc b/src/applications/test/bulk-send-application-test-suite.cc index 769742a739..131d8fc032 100644 --- a/src/applications/test/bulk-send-application-test-suite.cc +++ b/src/applications/test/bulk-send-application-test-suite.cc @@ -274,10 +274,10 @@ class BulkSendTestSuite : public TestSuite }; BulkSendTestSuite::BulkSendTestSuite() - : TestSuite("bulk-send-application", UNIT) + : TestSuite("applications-bulk-send", Type::UNIT) { - AddTestCase(new BulkSendBasicTestCase, TestCase::QUICK); - AddTestCase(new BulkSendSeqTsSizeTestCase, TestCase::QUICK); + AddTestCase(new BulkSendBasicTestCase, TestCase::Duration::QUICK); + AddTestCase(new BulkSendSeqTsSizeTestCase, TestCase::Duration::QUICK); } static BulkSendTestSuite g_bulkSendTestSuite; //!< Static variable for test initialization diff --git a/src/applications/test/three-gpp-http-client-server-test.cc b/src/applications/test/three-gpp-http-client-server-test.cc index 7337e23e8d..77bbb5c675 100644 --- a/src/applications/test/three-gpp-http-client-server-test.cc +++ b/src/applications/test/three-gpp-http-client-server-test.cc @@ -799,7 +799,7 @@ class ThreeGppHttpClientServerTestSuite : public TestSuite public: /// Instantiate the test suite. ThreeGppHttpClientServerTestSuite() - : TestSuite("three-gpp-http-client-server-test", SYSTEM) + : TestSuite("applications-three-gpp-http-client-server", Type::SYSTEM) { // LogComponentEnable ("ThreeGppHttpClientServerTest", LOG_INFO); // LogComponentEnable ("ThreeGppHttpClient", LOG_INFO); @@ -873,14 +873,14 @@ class ThreeGppHttpClientServerTestSuite : public TestSuite } // Assign higher fullness for tests with higher RngRun. - TestCase::TestDuration testDuration = TestCase::QUICK; + TestCase::Duration testDuration = TestCase::Duration::QUICK; if (rngRun > 20) { - testDuration = TestCase::EXTENSIVE; + testDuration = TestCase::Duration::EXTENSIVE; } if (rngRun > 50) { - testDuration = TestCase::TAKES_FOREVER; + testDuration = TestCase::Duration::TAKES_FOREVER; } AddTestCase(new ThreeGppHttpObjectTestCase(name.str(), diff --git a/src/applications/test/udp-client-server-test.cc b/src/applications/test/udp-client-server-test.cc index 36fecb721f..55a09ee404 100644 --- a/src/applications/test/udp-client-server-test.cc +++ b/src/applications/test/udp-client-server-test.cc @@ -97,29 +97,28 @@ UdpClientServerTestCase::DoRun() Ipv4InterfaceContainer i = ipv4.Assign(d); uint16_t port = 4000; - UdpServerHelper server(port); - ApplicationContainer apps = server.Install(n.Get(1)); - apps.Start(Seconds(1.0)); - apps.Stop(Seconds(10.0)); + UdpServerHelper serverHelper(port); + auto serverApp = serverHelper.Install(n.Get(1)); + serverApp.Start(Seconds(1.0)); + serverApp.Stop(Seconds(10.0)); uint32_t MaxPacketSize = 1024; Time interPacketInterval = Seconds(1.); uint32_t maxPacketCount = 10; - UdpClientHelper client(i.GetAddress(1), port); - client.SetAttribute("MaxPackets", UintegerValue(maxPacketCount)); - client.SetAttribute("Interval", TimeValue(interPacketInterval)); - client.SetAttribute("PacketSize", UintegerValue(MaxPacketSize)); - apps = client.Install(n.Get(0)); - apps.Start(Seconds(2.0)); - apps.Stop(Seconds(10.0)); + UdpClientHelper clientHelper(i.GetAddress(1), port); + clientHelper.SetAttribute("MaxPackets", UintegerValue(maxPacketCount)); + clientHelper.SetAttribute("Interval", TimeValue(interPacketInterval)); + clientHelper.SetAttribute("PacketSize", UintegerValue(MaxPacketSize)); + auto clientApp = clientHelper.Install(n.Get(0)); + clientApp.Start(Seconds(2.0)); + clientApp.Stop(Seconds(10.0)); Simulator::Run(); Simulator::Destroy(); - NS_TEST_ASSERT_MSG_EQ(server.GetServer()->GetLost(), 0, "Packets were lost !"); - NS_TEST_ASSERT_MSG_EQ(server.GetServer()->GetReceived(), - 8, - "Did not receive expected number of packets !"); + auto server = DynamicCast(serverApp.Get(0)); + NS_TEST_ASSERT_MSG_EQ(server->GetLost(), 0, "Packets were lost !"); + NS_TEST_ASSERT_MSG_EQ(server->GetReceived(), 8, "Did not receive expected number of packets !"); } /** @@ -173,23 +172,24 @@ UdpTraceClientServerTestCase::DoRun() Ipv4InterfaceContainer i = ipv4.Assign(d); uint16_t port = 4000; - UdpServerHelper server(port); - ApplicationContainer apps = server.Install(n.Get(1)); - apps.Start(Seconds(1.0)); - apps.Stop(Seconds(10.0)); + UdpServerHelper serverHelper(port); + auto serverApp = serverHelper.Install(n.Get(1)); + serverApp.Start(Seconds(1.0)); + serverApp.Stop(Seconds(10.0)); uint32_t MaxPacketSize = 1400 - 28; // ip/udp header - UdpTraceClientHelper client(i.GetAddress(1), port, ""); - client.SetAttribute("MaxPacketSize", UintegerValue(MaxPacketSize)); - apps = client.Install(n.Get(0)); - apps.Start(Seconds(2.0)); - apps.Stop(Seconds(10.0)); + UdpTraceClientHelper clientHelper(i.GetAddress(1), port); + clientHelper.SetAttribute("MaxPacketSize", UintegerValue(MaxPacketSize)); + auto clientApp = clientHelper.Install(n.Get(0)); + clientApp.Start(Seconds(2.0)); + clientApp.Stop(Seconds(10.0)); Simulator::Run(); Simulator::Destroy(); - NS_TEST_ASSERT_MSG_EQ(server.GetServer()->GetLost(), 0, "Packets were lost !"); - NS_TEST_ASSERT_MSG_EQ(server.GetServer()->GetReceived(), + auto server = DynamicCast(serverApp.Get(0)); + NS_TEST_ASSERT_MSG_EQ(server->GetLost(), 0, "Packets were lost !"); + NS_TEST_ASSERT_MSG_EQ(server->GetReceived(), 247, "Did not receive expected number of packets !"); } @@ -359,12 +359,12 @@ class UdpClientServerTestSuite : public TestSuite }; UdpClientServerTestSuite::UdpClientServerTestSuite() - : TestSuite("udp-client-server", UNIT) + : TestSuite("applications-udp-client-server", Type::UNIT) { - AddTestCase(new UdpTraceClientServerTestCase, TestCase::QUICK); - AddTestCase(new UdpClientServerTestCase, TestCase::QUICK); - AddTestCase(new PacketLossCounterTestCase, TestCase::QUICK); - AddTestCase(new UdpEchoClientSetFillTestCase, TestCase::QUICK); + AddTestCase(new UdpTraceClientServerTestCase, TestCase::Duration::QUICK); + AddTestCase(new UdpClientServerTestCase, TestCase::Duration::QUICK); + AddTestCase(new PacketLossCounterTestCase, TestCase::Duration::QUICK); + AddTestCase(new UdpEchoClientSetFillTestCase, TestCase::Duration::QUICK); } static UdpClientServerTestSuite diff --git a/src/bridge/examples/csma-bridge.py b/src/bridge/examples/csma-bridge.py index 73294e6726..1d152429a6 100644 --- a/src/bridge/examples/csma-bridge.py +++ b/src/bridge/examples/csma-bridge.py @@ -48,53 +48,51 @@ def main(argv): # Allow the user to override any of the defaults and the above Bind() at # run-time, via command-line arguments # - cmd = ns.core.CommandLine() + cmd = ns.CommandLine() cmd.Parse(argv) # # Explicitly create the nodes required by the topology(shown above). # # print "Create nodes." - terminals = ns.network.NodeContainer() + terminals = ns.NodeContainer() terminals.Create(4) - csmaSwitch = ns.network.NodeContainer() + csmaSwitch = ns.NodeContainer() csmaSwitch.Create(1) # print "Build Topology" - csma = ns.csma.CsmaHelper() - csma.SetChannelAttribute("DataRate", ns.network.DataRateValue(ns.network.DataRate(5000000))) - csma.SetChannelAttribute("Delay", ns.core.TimeValue(ns.core.MilliSeconds(2))) + csma = ns.CsmaHelper() + csma.SetChannelAttribute("DataRate", ns.DataRateValue(ns.DataRate(5000000))) + csma.SetChannelAttribute("Delay", ns.TimeValue(ns.MilliSeconds(2))) # Create the csma links, from each terminal to the switch - terminalDevices = ns.network.NetDeviceContainer() - switchDevices = ns.network.NetDeviceContainer() + terminalDevices = ns.NetDeviceContainer() + switchDevices = ns.NetDeviceContainer() for i in range(4): - link = csma.Install( - ns.network.NodeContainer(ns.network.NodeContainer(terminals.Get(i)), csmaSwitch) - ) + link = csma.Install(ns.NodeContainer(ns.NodeContainer(terminals.Get(i)), csmaSwitch)) terminalDevices.Add(link.Get(0)) switchDevices.Add(link.Get(1)) # Create the bridge netdevice, which will do the packet switching switchNode = csmaSwitch.Get(0) - bridgeDevice = ns.bridge.BridgeNetDevice() + bridgeDevice = ns.BridgeNetDevice() switchNode.AddDevice(bridgeDevice) for portIter in range(switchDevices.GetN()): bridgeDevice.AddBridgePort(switchDevices.Get(portIter)) # Add internet stack to the terminals - internet = ns.internet.InternetStackHelper() + internet = ns.InternetStackHelper() internet.Install(terminals) # We've got the "hardware" in place. Now we need to add IP addresses. # # print "Assign IP Addresses." - ipv4 = ns.internet.Ipv4AddressHelper() - ipv4.SetBase(ns.network.Ipv4Address("10.1.1.0"), ns.network.Ipv4Mask("255.255.255.0")) + ipv4 = ns.Ipv4AddressHelper() + ipv4.SetBase(ns.Ipv4Address("10.1.1.0"), ns.Ipv4Mask("255.255.255.0")) ipv4.Assign(terminalDevices) # @@ -103,39 +101,39 @@ def main(argv): # print "Create Applications." port = 9 # Discard port(RFC 863) - inet_sock_address = ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.2"), port) - onoff = ns.applications.OnOffHelper("ns3::UdpSocketFactory", inet_sock_address.ConvertTo()) - onoff.SetConstantRate(ns.network.DataRate("500kb/s")) + inet_sock_address = ns.InetSocketAddress(ns.Ipv4Address("10.1.1.2"), port) + onoff = ns.OnOffHelper("ns3::UdpSocketFactory", inet_sock_address.ConvertTo()) + onoff.SetConstantRate(ns.DataRate("500kb/s")) - app = onoff.Install(ns.network.NodeContainer(terminals.Get(0))) + app = onoff.Install(ns.NodeContainer(terminals.Get(0))) # Start the application - app.Start(ns.core.Seconds(1.0)) - app.Stop(ns.core.Seconds(10.0)) + app.Start(ns.Seconds(1.0)) + app.Stop(ns.Seconds(10.0)) # Create an optional packet sink to receive these packets - inet_address = ns.network.InetSocketAddress(ns.network.Ipv4Address.GetAny(), port) - sink = ns.applications.PacketSinkHelper("ns3::UdpSocketFactory", inet_address.ConvertTo()) - app = sink.Install(ns.network.NodeContainer(terminals.Get(1))) - app.Start(ns.core.Seconds(0.0)) + inet_address = ns.InetSocketAddress(ns.Ipv4Address.GetAny(), port) + sink = ns.PacketSinkHelper("ns3::UdpSocketFactory", inet_address.ConvertTo()) + app = sink.Install(ns.NodeContainer(terminals.Get(1))) + app.Start(ns.Seconds(0.0)) # # Create a similar flow from n3 to n0, starting at time 1.1 seconds # - inet_address = ns.network.InetSocketAddress(ns.network.Ipv4Address("10.1.1.1"), port) - onoff.SetAttribute("Remote", ns.network.AddressValue(inet_address.ConvertTo())) - app = onoff.Install(ns.network.NodeContainer(terminals.Get(3))) - app.Start(ns.core.Seconds(1.1)) - app.Stop(ns.core.Seconds(10.0)) + inet_address = ns.InetSocketAddress(ns.Ipv4Address("10.1.1.1"), port) + onoff.SetAttribute("Remote", ns.AddressValue(inet_address.ConvertTo())) + app = onoff.Install(ns.NodeContainer(terminals.Get(3))) + app.Start(ns.Seconds(1.1)) + app.Stop(ns.Seconds(10.0)) - app = sink.Install(ns.network.NodeContainer(terminals.Get(0))) - app.Start(ns.core.Seconds(0.0)) + app = sink.Install(ns.NodeContainer(terminals.Get(0))) + app.Start(ns.Seconds(0.0)) # # Configure tracing of all enqueue, dequeue, and NetDevice receive events. # Trace output will be sent to the file "csma-bridge.tr" # # print "Configure Tracing." - # ascii = ns.network.AsciiTraceHelper(); + # ascii = ns.AsciiTraceHelper(); # csma.EnableAsciiAll(ascii.CreateFileStream ("csma-bridge.tr")); # @@ -151,8 +149,8 @@ def main(argv): # Now, do the actual simulation. # # print "Run Simulation." - ns.core.Simulator.Run() - ns.core.Simulator.Destroy() + ns.Simulator.Run() + ns.Simulator.Destroy() # print "Done." diff --git a/src/bridge/model/bridge-net-device.cc b/src/bridge/model/bridge-net-device.cc index 6b0fd11061..adab855aac 100644 --- a/src/bridge/model/bridge-net-device.cc +++ b/src/bridge/model/bridge-net-device.cc @@ -355,7 +355,7 @@ Address BridgeNetDevice::GetBroadcast() const { NS_LOG_FUNCTION_NOARGS(); - return Mac48Address("ff:ff:ff:ff:ff:ff"); + return Mac48Address::GetBroadcast(); } bool diff --git a/src/brite/test/brite-test-topology.cc b/src/brite/test/brite-test-topology.cc index 022d61912a..81f6b2f781 100644 --- a/src/brite/test/brite-test-topology.cc +++ b/src/brite/test/brite-test-topology.cc @@ -215,10 +215,10 @@ class BriteTestSuite : public TestSuite { public: BriteTestSuite() - : TestSuite("brite-testing", UNIT) + : TestSuite("brite-testing", Type::UNIT) { - AddTestCase(new BriteTopologyStructureTestCase, TestCase::QUICK); - AddTestCase(new BriteTopologyFunctionTestCase, TestCase::QUICK); + AddTestCase(new BriteTopologyStructureTestCase, TestCase::Duration::QUICK); + AddTestCase(new BriteTopologyFunctionTestCase, TestCase::Duration::QUICK); } }; diff --git a/src/buildings/doc/Makefile b/src/buildings/doc/Makefile index 5505395cbf..06744f2ce0 100644 --- a/src/buildings/doc/Makefile +++ b/src/buildings/doc/Makefile @@ -40,7 +40,7 @@ GRAPHS = $(GRAPHS_EPS) $(GRAPHS_PNG) $(GRAPHS_PDF) @if test x$($@_width) != x; then $(RESCALE) $($@_width) $@ ; fi # You can set these variables from the command line. -SPHINXOPTS = +SPHINXOPTS = -W --keep-going SPHINXBUILD = sphinx-build PAPER = BUILDDIR = build diff --git a/src/buildings/helper/building-container.h b/src/buildings/helper/building-container.h index 0f2f6fbd2c..51faceecd3 100644 --- a/src/buildings/helper/building-container.h +++ b/src/buildings/helper/building-container.h @@ -30,6 +30,8 @@ namespace ns3 { /** + * \ingroup buildings + * * \brief keep track of a set of building pointers. * * Some ns-3 helpers operate on more than one building at a time. For example diff --git a/src/buildings/helper/building-position-allocator.h b/src/buildings/helper/building-position-allocator.h index 35d861f083..9a64703c16 100644 --- a/src/buildings/helper/building-position-allocator.h +++ b/src/buildings/helper/building-position-allocator.h @@ -32,6 +32,8 @@ class Building; class UniformRandomVariable; /** + * \ingroup buildings + * * Allocate each position by randomly choosing a building from the list * of all buildings, and then randomly choosing a position inside the building. */ diff --git a/src/buildings/helper/buildings-helper.h b/src/buildings/helper/buildings-helper.h index 1a557ba863..25e00766e5 100644 --- a/src/buildings/helper/buildings-helper.h +++ b/src/buildings/helper/buildings-helper.h @@ -34,6 +34,8 @@ class MobilityModel; class Building; /** + * \ingroup buildings + * * Helper used to install a MobilityBuildingInfo into a set of nodes. */ class BuildingsHelper diff --git a/src/buildings/model/building-list.h b/src/buildings/model/building-list.h index c2286b0653..55591abc82 100644 --- a/src/buildings/model/building-list.h +++ b/src/buildings/model/building-list.h @@ -32,6 +32,8 @@ namespace ns3 class Building; /** + * \ingroup buildings + * * Container for Building class */ class BuildingList diff --git a/src/buildings/model/building.h b/src/buildings/model/building.h index 74b072763e..eef5b635cf 100644 --- a/src/buildings/model/building.h +++ b/src/buildings/model/building.h @@ -31,7 +31,13 @@ namespace ns3 { /** - * \ingroup mobility + * \defgroup buildings Buildings + * + * The models to define 3d buildings, associated channel models, and mobility. + */ + +/** + * \ingroup buildings * \brief a 3d building block */ class Building : public Object diff --git a/src/buildings/model/buildings-channel-condition-model.h b/src/buildings/model/buildings-channel-condition-model.h index 518c9a0847..5b532325a5 100644 --- a/src/buildings/model/buildings-channel-condition-model.h +++ b/src/buildings/model/buildings-channel-condition-model.h @@ -30,6 +30,7 @@ class MobilityModel; /** * \ingroup buildings + * \ingroup propagation * * \brief Determines the channel condition based on the buildings deployed in the * scenario diff --git a/src/buildings/model/buildings-propagation-loss-model.h b/src/buildings/model/buildings-propagation-loss-model.h index 6ba3d9a749..6c2f4eafc3 100644 --- a/src/buildings/model/buildings-propagation-loss-model.h +++ b/src/buildings/model/buildings-propagation-loss-model.h @@ -36,6 +36,7 @@ class ShadowingLossModel; class JakesFadingLossModel; /** + * \ingroup buildings * \ingroup propagation * * This model provides means for simulating the following propagation diff --git a/src/buildings/model/hybrid-buildings-propagation-loss-model.h b/src/buildings/model/hybrid-buildings-propagation-loss-model.h index edaf6e69a4..99b2025443 100644 --- a/src/buildings/model/hybrid-buildings-propagation-loss-model.h +++ b/src/buildings/model/hybrid-buildings-propagation-loss-model.h @@ -36,6 +36,7 @@ class ItuR1238PropagationLossModel; class Kun2600MhzPropagationLossModel; /** + * \ingroup buildings * \ingroup propagation * * \brief The HybridBuildingsPropagationModel is a compound of different models able to evaluate diff --git a/src/buildings/model/itu-r-1238-propagation-loss-model.h b/src/buildings/model/itu-r-1238-propagation-loss-model.h index b6ded5bb93..017a362e77 100644 --- a/src/buildings/model/itu-r-1238-propagation-loss-model.h +++ b/src/buildings/model/itu-r-1238-propagation-loss-model.h @@ -29,6 +29,9 @@ namespace ns3 { /** + * \ingroup buildings + * \ingroup propagation + * * This class implements the ITU-R 1238 propagation loss model. * */ diff --git a/src/buildings/model/mobility-building-info.h b/src/buildings/model/mobility-building-info.h index ab9489b8b4..49a9a93a6c 100644 --- a/src/buildings/model/mobility-building-info.h +++ b/src/buildings/model/mobility-building-info.h @@ -36,6 +36,8 @@ namespace ns3 /** * \ingroup buildings + * \ingroup mobility + * \brief mobility buildings information (to be used by mobility models) * * This model implements the management of scenarios where users might be diff --git a/src/buildings/model/oh-buildings-propagation-loss-model.h b/src/buildings/model/oh-buildings-propagation-loss-model.h index a7dd895bc9..8b2a301168 100644 --- a/src/buildings/model/oh-buildings-propagation-loss-model.h +++ b/src/buildings/model/oh-buildings-propagation-loss-model.h @@ -29,6 +29,7 @@ namespace ns3 class OkumuraHataPropagationLossModel; /** + * \ingroup buildings * \ingroup propagation * * this model combines the OkumuraHata model with the BuildingsPropagationLossModel diff --git a/src/buildings/model/random-walk-2d-outdoor-mobility-model.cc b/src/buildings/model/random-walk-2d-outdoor-mobility-model.cc index 23e13b8325..9950231789 100644 --- a/src/buildings/model/random-walk-2d-outdoor-mobility-model.cc +++ b/src/buildings/model/random-walk-2d-outdoor-mobility-model.cc @@ -115,8 +115,8 @@ RandomWalk2dOutdoorMobilityModel::DoInitializePrivate() m_helper.Update(); double speed = m_speed->GetValue(); double direction = m_direction->GetValue(); - Vector vector(std::cos(direction) * speed, std::sin(direction) * speed, 0.0); - m_helper.SetVelocity(vector); + Vector velocity(std::cos(direction) * speed, std::sin(direction) * speed, 0.0); + m_helper.SetVelocity(velocity); m_helper.Unpause(); Time delayLeft; @@ -142,10 +142,10 @@ RandomWalk2dOutdoorMobilityModel::DoWalk(Time delayLeft) NS_LOG_FUNCTION(this << delayLeft.GetSeconds()); Vector position = m_helper.GetCurrentPosition(); - Vector speed = m_helper.GetVelocity(); + Vector velocity = m_helper.GetVelocity(); Vector nextPosition = position; - nextPosition.x += speed.x * delayLeft.GetSeconds(); - nextPosition.y += speed.y * delayLeft.GetSeconds(); + nextPosition.x += velocity.x * delayLeft.GetSeconds(); + nextPosition.y += velocity.y * delayLeft.GetSeconds(); m_event.Cancel(); // check if the nextPosition is inside a building, or if the line @@ -170,13 +170,13 @@ RandomWalk2dOutdoorMobilityModel::DoWalk(Time delayLeft) double delaySecondsX = std::numeric_limits::max(); double delaySecondsY = std::numeric_limits::max(); - if (speed.x != 0) + if (velocity.x != 0) { - delaySecondsX = std::abs((nextPosition.x - position.x) / speed.x); + delaySecondsX = std::abs((nextPosition.x - position.x) / velocity.x); } - if (speed.y != 0) + if (velocity.y != 0) { - delaySecondsY = std::abs((nextPosition.y - position.y) / speed.y); + delaySecondsY = std::abs((nextPosition.y - position.y) / velocity.y); } Time delay = Seconds(std::min(delaySecondsX, delaySecondsY)); m_event = Simulator::Schedule(delay, @@ -189,7 +189,7 @@ RandomWalk2dOutdoorMobilityModel::DoWalk(Time delayLeft) else { NS_LOG_LOGIC("Out of bounding box"); - nextPosition = m_bounds.CalculateIntersection(position, speed); + nextPosition = m_bounds.CalculateIntersection(position, velocity); // check that this nextPosition is outdoor auto outdoorBuilding = IsLineClearOfBuildings(position, nextPosition); bool outdoor = std::get<0>(outdoorBuilding); @@ -198,15 +198,15 @@ RandomWalk2dOutdoorMobilityModel::DoWalk(Time delayLeft) if (outdoor) { double delaySeconds = std::numeric_limits::max(); - if (speed.x != 0) + if (velocity.x != 0) { delaySeconds = - std::min(delaySeconds, std::abs((nextPosition.x - position.x) / speed.x)); + std::min(delaySeconds, std::abs((nextPosition.x - position.x) / velocity.x)); } - else if (speed.y != 0) + else if (velocity.y != 0) { delaySeconds = - std::min(delaySeconds, std::abs((nextPosition.y - position.y) / speed.y)); + std::min(delaySeconds, std::abs((nextPosition.y - position.y) / velocity.y)); } else { @@ -228,15 +228,15 @@ RandomWalk2dOutdoorMobilityModel::DoWalk(Time delayLeft) double delaySecondsX = std::numeric_limits::max(); double delaySecondsY = std::numeric_limits::max(); - if (speed.x != 0) + if (velocity.x != 0) { delaySecondsX = - std::min(delaySecondsX, std::abs((nextPosition.x - position.x) / speed.x)); + std::min(delaySecondsX, std::abs((nextPosition.x - position.x) / velocity.x)); } - if (speed.y != 0) + if (velocity.y != 0) { delaySecondsY = - std::min(delaySecondsY, std::abs((nextPosition.y - position.y) / speed.y)); + std::min(delaySecondsY, std::abs((nextPosition.y - position.y) / velocity.y)); } if (delaySecondsX == std::numeric_limits::max() && delaySecondsY == std::numeric_limits::max()) @@ -381,30 +381,29 @@ RandomWalk2dOutdoorMobilityModel::Rebound(Time delayLeft) NS_LOG_FUNCTION(this << delayLeft.GetSeconds()); m_helper.UpdateWithBounds(m_bounds); Vector position = m_helper.GetCurrentPosition(); - Vector speed = m_helper.GetVelocity(); + Vector velocity = m_helper.GetVelocity(); switch (m_bounds.GetClosestSideOrCorner(position)) { case Rectangle::RIGHTSIDE: case Rectangle::LEFTSIDE: NS_LOG_DEBUG("The closest side is RIGHT or LEFT"); - speed.x = -speed.x; + velocity.x = -velocity.x; break; case Rectangle::TOPSIDE: case Rectangle::BOTTOMSIDE: NS_LOG_DEBUG("The closest side is TOP or BOTTOM"); - speed.y = -speed.y; + velocity.y = -velocity.y; break; case Rectangle::TOPRIGHTCORNER: case Rectangle::BOTTOMRIGHTCORNER: case Rectangle::TOPLEFTCORNER: case Rectangle::BOTTOMLEFTCORNER: NS_LOG_DEBUG("The closest side is a corner"); - auto temp = speed.x; - speed.x = -speed.y; - speed.y = -temp; + velocity.x = -velocity.x; + velocity.y = -velocity.y; break; } - m_helper.SetVelocity(speed); + m_helper.SetVelocity(velocity); m_helper.Unpause(); DoWalk(delayLeft); } diff --git a/src/buildings/model/random-walk-2d-outdoor-mobility-model.h b/src/buildings/model/random-walk-2d-outdoor-mobility-model.h index 1da68f8e60..d570b592ff 100644 --- a/src/buildings/model/random-walk-2d-outdoor-mobility-model.h +++ b/src/buildings/model/random-walk-2d-outdoor-mobility-model.h @@ -36,7 +36,9 @@ namespace ns3 { /** + * \ingroup buildings * \ingroup mobility + * * \brief 2D random walk mobility model which avoids buildings. * * This class reuses most of the code of RandomWalk2dMobilityModel, diff --git a/src/buildings/model/three-gpp-v2v-channel-condition-model.h b/src/buildings/model/three-gpp-v2v-channel-condition-model.h index 0d50c409f3..d5023da690 100644 --- a/src/buildings/model/three-gpp-v2v-channel-condition-model.h +++ b/src/buildings/model/three-gpp-v2v-channel-condition-model.h @@ -33,6 +33,7 @@ class MobilityModel; /** * \ingroup buildings + * \ingroup propagation * * \brief Computes the channel condition for the V2V Urban scenario * diff --git a/src/buildings/test/building-position-allocator-test.cc b/src/buildings/test/building-position-allocator-test.cc index 980a921a77..7fc96c72aa 100644 --- a/src/buildings/test/building-position-allocator-test.cc +++ b/src/buildings/test/building-position-allocator-test.cc @@ -35,13 +35,13 @@ using namespace ns3; NS_LOG_COMPONENT_DEFINE("BuildingPositionAllocatorTest"); /** - * \ingroup propagation + * \ingroup buildings + * \ingroup tests * \defgroup building-test Buildings module tests */ /** * \ingroup building-test - * \ingroup tests * * Room coordinates */ @@ -75,7 +75,6 @@ operator<(const Room& a, const Room& b) /** * \ingroup building-test - * \ingroup tests * * RandomRoomPositionAllocator test */ @@ -153,7 +152,6 @@ RandomRoomPositionAllocatorTestCase::DoRun() /** * \ingroup building-test - * \ingroup tests * * SameRoomPositionAllocator test */ @@ -227,7 +225,6 @@ SameRoomPositionAllocatorTestCase::DoRun() /** * \ingroup building-test - * \ingroup tests * * \brief RandomRoomPositionAllocator TestSuite */ @@ -238,12 +235,12 @@ class BuildingPositionAllocatorTestSuite : public TestSuite }; BuildingPositionAllocatorTestSuite::BuildingPositionAllocatorTestSuite() - : TestSuite("building-position-allocator", UNIT) + : TestSuite("building-position-allocator", Type::UNIT) { NS_LOG_FUNCTION(this); - AddTestCase(new RandomRoomPositionAllocatorTestCase, TestCase::QUICK); - AddTestCase(new SameRoomPositionAllocatorTestCase, TestCase::QUICK); + AddTestCase(new RandomRoomPositionAllocatorTestCase, TestCase::Duration::QUICK); + AddTestCase(new SameRoomPositionAllocatorTestCase, TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/buildings/test/buildings-channel-condition-model-test.cc b/src/buildings/test/buildings-channel-condition-model-test.cc index 15024a8864..ea75acc84f 100644 --- a/src/buildings/test/buildings-channel-condition-model-test.cc +++ b/src/buildings/test/buildings-channel-condition-model-test.cc @@ -31,7 +31,6 @@ NS_LOG_COMPONENT_DEFINE("BuildingsChannelConditionModelsTest"); /** * \ingroup building-test - * \ingroup tests * * Test case for the class BuildingsChannelConditionModel. It checks if the * channel condition is correctly determined when a building is deployed in the @@ -148,7 +147,6 @@ BuildingsChannelConditionModelTestCase::DoRun() /** * \ingroup building-test - * \ingroup tests * Test suite for the buildings channel condition model */ class BuildingsChannelConditionModelsTestSuite : public TestSuite @@ -158,9 +156,9 @@ class BuildingsChannelConditionModelsTestSuite : public TestSuite }; BuildingsChannelConditionModelsTestSuite::BuildingsChannelConditionModelsTestSuite() - : TestSuite("buildings-channel-condition-model", UNIT) + : TestSuite("buildings-channel-condition-model", Type::UNIT) { - AddTestCase(new BuildingsChannelConditionModelTestCase, TestCase::QUICK); + AddTestCase(new BuildingsChannelConditionModelTestCase, TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/buildings/test/buildings-helper-test.cc b/src/buildings/test/buildings-helper-test.cc index 16489f85ba..9dde3fc7d9 100644 --- a/src/buildings/test/buildings-helper-test.cc +++ b/src/buildings/test/buildings-helper-test.cc @@ -32,7 +32,6 @@ NS_LOG_COMPONENT_DEFINE("BuildingsHelperTest"); /** * \ingroup building-test - * \ingroup tests * * \brief Struct representing a position in a building */ @@ -59,7 +58,6 @@ PositionInBuilding::PositionInBuilding() /** * \ingroup building-test - * \ingroup tests * Data to construct a Building object. We don't want to pass Building * objects to the TestCase constructor because otherwise BuildingList @@ -96,7 +94,6 @@ BuildingData::BuildingData() /** * \ingroup building-test - * \ingroup tests * * \brief BuildingsHelper test */ @@ -197,7 +194,6 @@ BuildingsHelperOneTestCase::DoRun() /** * \ingroup building-test - * \ingroup tests * * \brief BuildingsHelper TestSuite */ @@ -208,7 +204,7 @@ class BuildingsHelperTestSuite : public TestSuite }; BuildingsHelperTestSuite::BuildingsHelperTestSuite() - : TestSuite("buildings-helper", UNIT) + : TestSuite("buildings-helper", Type::UNIT) { NS_LOG_FUNCTION(this); @@ -231,25 +227,25 @@ BuildingsHelperTestSuite::BuildingsHelperTestSuite() p1.rx = 1; p1.ry = 1; p1.fn = 1; - AddTestCase(new BuildingsHelperOneTestCase(p1, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p1, b1), TestCase::Duration::QUICK); Vector vp2(1.5, 0.5, 0.5); PositionInBuilding p2; p2.pos = vp2; p2.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(p2, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p2, b1), TestCase::Duration::QUICK); Vector vp3(1.5, 2.5, 0.5); PositionInBuilding p3; p3.pos = vp3; p3.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(p3, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p3, b1), TestCase::Duration::QUICK); Vector vp4(1.5, 1.5, 5); PositionInBuilding p4; p4.pos = vp4; p4.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(p4, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p4, b1), TestCase::Duration::QUICK); Vector vp5(2.5, 1.6, 3.5); PositionInBuilding p5; @@ -259,31 +255,31 @@ BuildingsHelperTestSuite::BuildingsHelperTestSuite() p5.rx = 1; p5.ry = 1; p5.fn = 1; - AddTestCase(new BuildingsHelperOneTestCase(p5, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p5, b1), TestCase::Duration::QUICK); Vector vp6(0.9999, 1.5, 1.5); PositionInBuilding p6; p6.pos = vp6; p6.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(p6, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p6, b1), TestCase::Duration::QUICK); Vector vp7(3.0001, 1.5, 2.5); PositionInBuilding p7; p7.pos = vp7; p7.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(p7, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p7, b1), TestCase::Duration::QUICK); Vector vp8(1.001, 1.001, -0.01); PositionInBuilding p8; p8.pos = vp8; p8.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(p8, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p8, b1), TestCase::Duration::QUICK); Vector vp9(1.5, 1.5, 4.001); PositionInBuilding p9; p9.pos = vp9; p9.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(p9, b1), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(p9, b1), TestCase::Duration::QUICK); BuildingData b2; b2.xmin = -1; @@ -304,7 +300,7 @@ BuildingsHelperTestSuite::BuildingsHelperTestSuite() q1.rx = 1; q1.ry = 2; q1.fn = 3; - AddTestCase(new BuildingsHelperOneTestCase(q1, b2), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(q1, b2), TestCase::Duration::QUICK); Vector vq2(0.2, 0.3, 0.2); PositionInBuilding q2; @@ -314,37 +310,37 @@ BuildingsHelperTestSuite::BuildingsHelperTestSuite() q2.rx = 3; q2.ry = 5; q2.fn = 1; - AddTestCase(new BuildingsHelperOneTestCase(q2, b2), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(q2, b2), TestCase::Duration::QUICK); Vector vq3(0.6, -1.75, 1.5); PositionInBuilding q3; q3.pos = vq3; q3.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(q3, b2), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(q3, b2), TestCase::Duration::QUICK); Vector vq4(-1.01, 0.3, 1.99); PositionInBuilding q4; q4.pos = vq4; q4.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(q4, b2), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(q4, b2), TestCase::Duration::QUICK); Vector vq5(-0.8, 0.7, 0.01); PositionInBuilding q5; q5.pos = vq5; q5.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(q5, b2), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(q5, b2), TestCase::Duration::QUICK); Vector vq6(0.2, 0.3, -0.2); PositionInBuilding q6; q6.pos = vq6; q6.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(q6, b2), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(q6, b2), TestCase::Duration::QUICK); Vector vq7(0.2, 0.3, 2.001); PositionInBuilding q7; q7.pos = vq7; q7.indoor = false; - AddTestCase(new BuildingsHelperOneTestCase(q7, b2), TestCase::QUICK); + AddTestCase(new BuildingsHelperOneTestCase(q7, b2), TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/buildings/test/buildings-pathloss-test.cc b/src/buildings/test/buildings-pathloss-test.cc index 7e9a39f11e..2b2e617199 100644 --- a/src/buildings/test/buildings-pathloss-test.cc +++ b/src/buildings/test/buildings-pathloss-test.cc @@ -41,7 +41,7 @@ NS_LOG_COMPONENT_DEFINE("BuildingsPathlossTest"); * several communication scenarios */ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() - : TestSuite("buildings-pathloss-test", SYSTEM) + : TestSuite("buildings-pathloss-test", Type::SYSTEM) { LogComponentEnable("BuildingsPathlossTest", LOG_LEVEL_ALL); @@ -54,7 +54,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 137.93, "OH Urban Large city"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new BuildingsPathlossTestCase(freq, 1, @@ -63,7 +63,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() SmallCity, 137.88, "OH Urban small city"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new BuildingsPathlossTestCase(freq, 1, @@ -72,7 +72,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 128.03, "loss OH SubUrban"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new BuildingsPathlossTestCase(freq, 1, @@ -81,7 +81,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 110.21, "loss OH OpenAreas"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #2 COST231 Model (1500 < freq < 2000~2170 MHz) (Macro<->UE) @@ -94,7 +94,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 148.55, "COST231 Urban Large city"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new BuildingsPathlossTestCase(freq, 1, @@ -103,7 +103,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() SmallCity, 150.64, "COST231 Urban small city and suburban"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #3 2.6 GHz model (Macro<->UE) @@ -116,7 +116,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() SmallCity, 121.83, "2.6GHz model"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #4 ITU1411 LOS model (Macro<->UE) @@ -128,7 +128,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 81.00, "ITU1411 LOS"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #5 ITU1411 NLOS model (Macro<->UE) @@ -141,14 +141,14 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 143.69, "ITU1411 NLOS"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #6 ITUP1238 (HeNB <-> UE) freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 AddTestCase( new BuildingsPathlossTestCase(freq, 5, 6, UrbanEnvironment, LargeCity, 88.3855, "ITUP1238"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #7 Outdoor -> Indoor OkumuraHata (Macro<->UE) @@ -162,7 +162,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 155.55, "Okumura Hata Outdoor -> Indoor"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #8 Outdoor -> Indoor ITU1411 (Macro<->UE) freq = 2.1140e9; // E_UTRA BAND #1 see table 5.5-1 of 36.101 @@ -175,7 +175,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 88.000, "ITU1411 LOS Outdoor -> Indoor"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #9 Indoor -> Outdoor LOS (HeNB <-> UE) @@ -190,7 +190,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 84.838, "ITU1411 LOS Indoor -> Outdoor"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #10 Indoor -> Outdoor NLOS (HeNB <-> UE) @@ -205,7 +205,7 @@ BuildingsPathlossTestSuite::BuildingsPathlossTestSuite() LargeCity, 183.90, "ITU1411 NLOS Indoor -> Outdoor"), - TestCase::QUICK); + TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/buildings/test/buildings-pathloss-test.h b/src/buildings/test/buildings-pathloss-test.h index 7700d0c163..39c75ca612 100644 --- a/src/buildings/test/buildings-pathloss-test.h +++ b/src/buildings/test/buildings-pathloss-test.h @@ -27,7 +27,6 @@ using namespace ns3; /** * \ingroup building-test - * \ingroup tests * * Test 1.1 BuildingsPathlossModel Pathloss compound test * @@ -42,7 +41,6 @@ class BuildingsPathlossTestSuite : public TestSuite /** * \ingroup building-test - * \ingroup tests * * Test 1.1 BuildingsPathlossModel Pathloss test * diff --git a/src/buildings/test/buildings-penetration-loss-pathloss-test.cc b/src/buildings/test/buildings-penetration-loss-pathloss-test.cc index 0bcf90d527..653fb13780 100644 --- a/src/buildings/test/buildings-penetration-loss-pathloss-test.cc +++ b/src/buildings/test/buildings-penetration-loss-pathloss-test.cc @@ -79,7 +79,6 @@ class BuildingsPenetrationLossesTestCase : public TestCase Vector m_positionA; //!< the position of the first node Vector m_positionB; //!< the position of the second node double m_frequency; //!< carrier frequency in Hz - bool m_isLos; //!< LOS probability TypeId m_condModel; //!< the type ID of the channel condition model to be used TypeId m_propModel; //!< the type ID of the propagation loss model to be used double m_pt; //!< transmitted power in dBm @@ -271,9 +270,9 @@ class BuildingsPenetrationLossesTestSuite : public TestSuite }; BuildingsPenetrationLossesTestSuite::BuildingsPenetrationLossesTestSuite() - : TestSuite("buildings-penetration-losses", UNIT) + : TestSuite("buildings-penetration-losses", Type::UNIT) { - AddTestCase(new BuildingsPenetrationLossesTestCase, TestCase::QUICK); + AddTestCase(new BuildingsPenetrationLossesTestCase, TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/buildings/test/buildings-shadowing-test.cc b/src/buildings/test/buildings-shadowing-test.cc index 5adc16b653..c553cc5096 100644 --- a/src/buildings/test/buildings-shadowing-test.cc +++ b/src/buildings/test/buildings-shadowing-test.cc @@ -45,21 +45,21 @@ NS_LOG_COMPONENT_DEFINE("BuildingsShadowingTest"); */ BuildingsShadowingTestSuite::BuildingsShadowingTestSuite() - : TestSuite("buildings-shadowing-test", SYSTEM) + : TestSuite("buildings-shadowing-test", Type::SYSTEM) { LogComponentEnable("BuildingsShadowingTest", LOG_LEVEL_ALL); // Test #1 Outdoor Model AddTestCase(new BuildingsShadowingTestCase(1, 2, 148.86, 7.0, "Outdoor Shadowing"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #2 Indoor model AddTestCase(new BuildingsShadowingTestCase(5, 6, 88.5724, 8.0, "Indoor Shadowing"), - TestCase::QUICK); + TestCase::Duration::QUICK); // Test #3 Indoor -> Outdoor AddTestCase(new BuildingsShadowingTestCase(9, 10, 85.0012, 8.6, "Indoor -> Outdoor Shadowing"), - TestCase::QUICK); + TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/buildings/test/buildings-shadowing-test.h b/src/buildings/test/buildings-shadowing-test.h index 68a2af7f55..bd8091b8a8 100644 --- a/src/buildings/test/buildings-shadowing-test.h +++ b/src/buildings/test/buildings-shadowing-test.h @@ -32,7 +32,6 @@ using namespace ns3; /** * \ingroup building-test - * \ingroup tests * * Shadowing compound test * @@ -47,7 +46,6 @@ class BuildingsShadowingTestSuite : public TestSuite /** * \ingroup building-test - * \ingroup tests * * Shadowing test */ diff --git a/src/buildings/test/outdoor-random-walk-test.cc b/src/buildings/test/outdoor-random-walk-test.cc index ebb3f32405..3329ef016e 100644 --- a/src/buildings/test/outdoor-random-walk-test.cc +++ b/src/buildings/test/outdoor-random-walk-test.cc @@ -35,7 +35,6 @@ NS_LOG_COMPONENT_DEFINE("OutdoorRandomWalkTest"); /** * \ingroup building-test - * \ingroup tests * * Test case for the class OutdoorRandomWalkTestCase. It checks if the * positions visited by the user are outside buildings @@ -164,7 +163,6 @@ OutdoorRandomWalkTestCase::DoRun() /** * \ingroup building-test - * \ingroup tests * * Test suite for the buildings channel condition model */ @@ -175,9 +173,9 @@ class OutdoorRandomWalkTestSuite : public TestSuite }; OutdoorRandomWalkTestSuite::OutdoorRandomWalkTestSuite() - : TestSuite("outdoor-random-walk-model", UNIT) + : TestSuite("outdoor-random-walk-model", Type::UNIT) { - AddTestCase(new OutdoorRandomWalkTestCase, TestCase::QUICK); + AddTestCase(new OutdoorRandomWalkTestCase, TestCase::Duration::QUICK); } /// Static variable for test initialization diff --git a/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc b/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc index bd3e041c50..428e6d035b 100644 --- a/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc +++ b/src/buildings/test/three-gpp-v2v-channel-condition-model-test.cc @@ -38,7 +38,6 @@ NS_LOG_COMPONENT_DEFINE("ThreeGppV2vChannelConditionModelsTest"); /** * \ingroup building-test - * \ingroup tests * * Test case for the classes ThreeGppV2vUrbanChannelConditionModel, * and ThreeGppV2vHighwayChannelConditionModel to test their code to @@ -511,7 +510,6 @@ ThreeGppV2vHighwayLosNlosvChCondModelTestCase::DoRun() /** * \ingroup building-test - * \ingroup tests * * Test suite for the 3GPP V2V channel condition model * @@ -539,17 +537,17 @@ class ThreeGppV2vChCondModelsTestSuite : public TestSuite }; ThreeGppV2vChCondModelsTestSuite::ThreeGppV2vChCondModelsTestSuite() - : TestSuite("three-gpp-v2v-channel-condition-model", SYSTEM) + : TestSuite("three-gpp-v2v-channel-condition-model", Type::SYSTEM) { AddTestCase(new ThreeGppV2vBuildingsChCondModelTestCase, - TestCase::QUICK); // test for the deterministic procedure (NLOS vs LOS/NLOSv), based - // on buildings + TestCase::Duration::QUICK); // test for the deterministic procedure (NLOS vs + // LOS/NLOSv), based on buildings AddTestCase(new ThreeGppV2vUrbanLosNlosvChCondModelTestCase, - TestCase::QUICK); // test for the probabilistic procedure (LOS vs NLOSv), in V2V - // urban scenario + TestCase::Duration::QUICK); // test for the probabilistic procedure (LOS vs + // NLOSv), in V2V urban scenario AddTestCase(new ThreeGppV2vHighwayLosNlosvChCondModelTestCase, - TestCase::QUICK); // test for the probabilistic procedure (LOS vs NLOSv), in V2V - // highway scenario + TestCase::Duration::QUICK); // test for the probabilistic procedure (LOS vs + // NLOSv), in V2V highway scenario } /// Static variable for test initialization diff --git a/src/click/test/ipv4-click-routing-test.cc b/src/click/test/ipv4-click-routing-test.cc index 93c915af3f..086ba9dc0e 100644 --- a/src/click/test/ipv4-click-routing-test.cc +++ b/src/click/test/ipv4-click-routing-test.cc @@ -30,6 +30,11 @@ using namespace ns3; +/** + * \ingroup click + * \defgroup click-tests click module tests + */ + /** * \file * \ingroup click-tests @@ -37,6 +42,7 @@ using namespace ns3; */ /** + * \ingroup click-tests * Add Click Internet stack. * * \param node Node. @@ -50,6 +56,7 @@ AddClickInternetStack(Ptr node) } /** + * \ingroup click-tests * Add network device. * * \param node Node. @@ -243,11 +250,11 @@ class ClickIfidFromNameTestSuite : public TestSuite { public: ClickIfidFromNameTestSuite() - : TestSuite("routing-click", UNIT) + : TestSuite("routing-click", Type::UNIT) { - AddTestCase(new ClickTrivialTest, TestCase::QUICK); - AddTestCase(new ClickIfidFromNameTest, TestCase::QUICK); - AddTestCase(new ClickIpMacAddressFromNameTest, TestCase::QUICK); + AddTestCase(new ClickTrivialTest, TestCase::Duration::QUICK); + AddTestCase(new ClickIfidFromNameTest, TestCase::Duration::QUICK); + AddTestCase(new ClickIpMacAddressFromNameTest, TestCase::Duration::QUICK); } }; diff --git a/src/config-store/examples/config-store-save.cc b/src/config-store/examples/config-store-save.cc index b72c615c98..65ef5791be 100644 --- a/src/config-store/examples/config-store-save.cc +++ b/src/config-store/examples/config-store-save.cc @@ -6,8 +6,13 @@ using namespace ns3; /** - * \ingroup configstore-examples + * \defgroup configstore-examples Config Store examples + * \ingroup configstore * \ingroup examples + */ + +/** + * \ingroup configstore-examples * * \brief Example class to demonstrate use of the ns-3 Config Store */ diff --git a/src/config-store/model/display-functions.cc b/src/config-store/model/display-functions.cc index ac3ed00551..a8b0abb070 100644 --- a/src/config-store/model/display-functions.cc +++ b/src/config-store/model/display-functions.cc @@ -84,20 +84,15 @@ cell_data_function_col_0(GtkTreeViewColumn* col, node->object->GetInstanceTypeId().GetName().c_str(), nullptr); break; + case ModelNode::NODE_ATTRIBUTE: case ModelNode::NODE_POINTER: - g_object_set(renderer, "text", node->name.c_str(), nullptr); - break; case ModelNode::NODE_VECTOR: g_object_set(renderer, "text", node->name.c_str(), nullptr); break; - case ModelNode::NODE_VECTOR_ITEM: { + case ModelNode::NODE_VECTOR_ITEM: std::stringstream oss; oss << node->index; g_object_set(renderer, "text", oss.str().c_str(), nullptr); - } - break; - case ModelNode::NODE_ATTRIBUTE: - g_object_set(renderer, "text", node->name.c_str(), nullptr); break; } } diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2c6e7aff24..41ed6b21e3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -137,7 +137,6 @@ set(source_files model/timer.cc model/watchdog.cc model/synchronizer.cc - model/make-event.cc model/environment-variable.cc model/log.cc model/breakpoint.cc @@ -229,7 +228,6 @@ set(header_files model/hash-murmur3.h model/hash.h model/heap-scheduler.h - model/int-to-type.h model/int64x64-double.h model/int64x64.h model/integer.h @@ -259,6 +257,7 @@ set(header_files model/rng-stream.h model/scheduler.h model/show-progress.h + model/shuffle.h model/simple-ref-count.h model/simulation-singleton.h model/simulator-impl.h diff --git a/src/core/doc/deprecated-example.h b/src/core/doc/deprecated-example.h deleted file mode 100644 index b4becf2bfb..0000000000 --- a/src/core/doc/deprecated-example.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2015 Lawrence Livermore National Laboratory - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Authors: Peter D. Barnes, Jr. - */ - -/* - * This is an example included in the doxygen-generated documentation - * for NS_DEPRECATED. - */ - -// [doxygen snippet] -/* - * Do something useful. - * - * \deprecated This method will go away in future versions of ns-3. - * See instead TheNewWay() - */ -NS_DEPRECATED_3_XX("see TheNewWay") -void SomethingUseful(); -/* - * Do something more useful. - */ -void TheNewWay(); -// [doxygen snippet] diff --git a/src/core/examples/empirical-random-variable-example.cc b/src/core/examples/empirical-random-variable-example.cc index ce78a348d6..a44ee95510 100644 --- a/src/core/examples/empirical-random-variable-example.cc +++ b/src/core/examples/empirical-random-variable-example.cc @@ -29,9 +29,13 @@ #include /** - * \file - * \ingroup core-examples randomvariable * \defgroup empirical-rng-example Core example: Empirical random variables use. + * \ingroup core-examples randomvariable + */ + +/** + * \file + * \ingroup empirical-rng-example * * Example program illustrating use of ns3::EmpiricalRandomVariable * diff --git a/src/core/examples/sample-rng-plot.py b/src/core/examples/sample-rng-plot.py index 32304b9c34..6b3e0907d8 100644 --- a/src/core/examples/sample-rng-plot.py +++ b/src/core/examples/sample-rng-plot.py @@ -47,7 +47,7 @@ def main(): # mu, var = 100, 225 ## Random number generator. - rng = ns.CreateObject("NormalRandomVariable") + rng = ns.CreateObject[ns.NormalRandomVariable]() rng.SetAttribute("Mean", ns.DoubleValue(100.0)) rng.SetAttribute("Variance", ns.DoubleValue(225.0)) diff --git a/src/core/examples/sample-simulator.py b/src/core/examples/sample-simulator.py index b52330f91b..7f8084a4b1 100755 --- a/src/core/examples/sample-simulator.py +++ b/src/core/examples/sample-simulator.py @@ -38,7 +38,7 @@ ## Example function - triggered at a random time. ## \return None. def RandomFunction(): - print("RandomFunction received event at", ns.core.Simulator.Now().GetSeconds(), "s") + print("RandomFunction received event at", ns.Simulator.Now().GetSeconds(), "s") ## Example function - triggered if an event is canceled (should not be called). @@ -119,23 +119,23 @@ def main(argv): cmd.Parse(argv) model = ns.cppyy.gbl.MyModel() - v = ns.CreateObject("UniformRandomVariable") - v.SetAttribute("Min", ns.core.DoubleValue(10)) - v.SetAttribute("Max", ns.core.DoubleValue(20)) + v = ns.CreateObject[ns.UniformRandomVariable]() + v.SetAttribute("Min", ns.DoubleValue(10)) + v.SetAttribute("Max", ns.DoubleValue(20)) ev = ns.cppyy.gbl.ExampleFunctionEvent(model) - ns.core.Simulator.Schedule(ns.core.Seconds(10.0), ev) + ns.Simulator.Schedule(ns.Seconds(10.0), ev) ev2 = ns.cppyy.gbl.RandomFunctionEvent(model) - ns.core.Simulator.Schedule(ns.core.Seconds(v.GetValue()), ev2) + ns.Simulator.Schedule(ns.Seconds(v.GetValue()), ev2) ev3 = ns.cppyy.gbl.CancelledFunctionEvent() - id = ns.core.Simulator.Schedule(ns.core.Seconds(30.0), ev3) - ns.core.Simulator.Cancel(id) + id = ns.Simulator.Schedule(ns.Seconds(30.0), ev3) + ns.Simulator.Cancel(id) - ns.core.Simulator.Run() + ns.Simulator.Run() - ns.core.Simulator.Destroy() + ns.Simulator.Destroy() if __name__ == "__main__": diff --git a/src/core/helper/csv-reader.cc b/src/core/helper/csv-reader.cc index 0bb5342944..a44e42e5e5 100644 --- a/src/core/helper/csv-reader.cc +++ b/src/core/helper/csv-reader.cc @@ -31,7 +31,6 @@ /** * \file - * \ingroup core * \ingroup csvreader * * ns3::CsvReader implementation @@ -460,7 +459,6 @@ CsvReader::ParseColumn(std::string::const_iterator begin, std::string::const_ite } break; case State::FIND_DELIMITER: - break; case State::END: break; } diff --git a/src/core/helper/csv-reader.h b/src/core/helper/csv-reader.h index bb8ecef740..49c9e9f8b3 100644 --- a/src/core/helper/csv-reader.h +++ b/src/core/helper/csv-reader.h @@ -29,7 +29,6 @@ /** * \file - * \ingroup core * \ingroup csvreader * * ns3::CsvReader declaration diff --git a/src/core/model/attribute-container.h b/src/core/model/attribute-container.h index 547d6fa28c..70f5eb3869 100644 --- a/src/core/model/attribute-container.h +++ b/src/core/model/attribute-container.h @@ -34,10 +34,18 @@ namespace ns3 { +/*! + * \ingroup attributes + * \addtogroup attribute_AttributeContainer AttributeContainer Attribute + * AttributeValue implementation for AttributeContainer + */ + class AttributeChecker; // A = attribute value type, C = container type to return /** + * \ingroup attribute_AttributeContainer + * * A container for one type of attribute. * * The container uses \p A to parse items into elements. @@ -186,11 +194,18 @@ class AttributeContainerValue : public AttributeValue * \return This object with items copied. */ template - Ptr> CopyFrom(const ITER begin, const ITER end); + inline Ptr> CopyFrom(const ITER begin, const ITER end); container_type m_container; //!< Internal container }; +/*! + * \ingroup attribute_AttributeContainer + * + * \class ns3::AttributeContainerChecker "attribute-container.h" + * AttributeChecker implementation for AttributeContainerValue. + * \see AttributeChecker + */ class AttributeContainerChecker : public AttributeChecker { public: @@ -207,6 +222,8 @@ class AttributeContainerChecker : public AttributeChecker }; /** + * \ingroup attribute_AttributeContainer + * * Make AttributeContainerChecker from AttributeContainerValue. * @tparam A \deduced AttributeValue type in container. * @tparam Sep \deduced Character separator between elements for parsing. @@ -219,6 +236,8 @@ Ptr MakeAttributeContainerChecker( const AttributeContainerValue& value); /** + * \ingroup attribute_AttributeContainer + * * Make AttributeContainerChecker using explicit types, initialize item checker. * @tparam A AttributeValue type in container. * @tparam Sep Character separator between elements for parsing. @@ -230,6 +249,8 @@ template class C = std::list> Ptr MakeAttributeContainerChecker(Ptr itemchecker); /** + * \ingroup attribute_AttributeContainer + * * Make uninitialized AttributeContainerChecker using explicit types. * @tparam A AttributeValue type in container. * @tparam Sep Character separator between elements for parsing. @@ -240,6 +261,8 @@ template class C = std::list> Ptr MakeAttributeContainerChecker(); /** + * \ingroup attribute_AttributeContainer + * * Make AttributeContainerAccessor using explicit types. * @tparam A AttributeValue type in container. * @tparam Sep Character separator between elements for parsing. @@ -254,6 +277,8 @@ template class C = std::list Ptr MakeAttributeContainerAccessor(T1 a1); /** + * \ingroup attribute_AttributeContainer + * * Make AttributeContainerAccessor using explicit types. * @tparam A AttributeValue type in container. * @tparam Sep Character separator between elements for parsing. @@ -287,7 +312,10 @@ namespace internal { /** + * \ingroup attribute_AttributeContainer + * * \internal + * * Templated AttributeContainerChecker class that is instantiated * in MakeAttributeContainerChecker. The non-templated base ns3::AttributeContainerChecker * is returned from that function. This is the same pattern as ObjectPtrContainer. diff --git a/src/core/model/attribute.h b/src/core/model/attribute.h index f94f22a1c0..944fe8306c 100644 --- a/src/core/model/attribute.h +++ b/src/core/model/attribute.h @@ -225,10 +225,18 @@ class AttributeChecker : public SimpleRefCount virtual bool Copy(const AttributeValue& source, AttributeValue& destination) const = 0; }; +/** + * \ingroup attributes + * \defgroup attribute_EmptyAttribute EmptyAttribute Attribute + * AttributeValue implementation for EmptyAttribute + */ + /** * \brief A class for an empty attribute value. * - * \ingroup attributes + * \ingroup attribute_EmptyAttribute + * + * \see AttributeValue */ class EmptyAttributeValue : public AttributeValue { @@ -262,6 +270,8 @@ class EmptyAttributeValue : public AttributeValue /** * \brief An accessor for EmptyAttributeValue * + * \ingroup attribute_EmptyAttribute + * * Does nothing, since every EmptyAttributeValue is the same. */ class EmptyAttributeAccessor : public AttributeAccessor @@ -276,7 +286,7 @@ class EmptyAttributeAccessor : public AttributeAccessor }; /** - * \ingroup attributes + * \ingroup attribute_EmptyAttribute * * \brief Create an empty AttributeAccessor. * @@ -291,6 +301,8 @@ MakeEmptyAttributeAccessor() /** * \brief A checker for EmptyAttributeValue * + * \ingroup attribute_EmptyAttribute + * * Does nothing, since every EmptyAttributeValue does not contain anything and * is, of course, valid. */ @@ -308,7 +320,7 @@ class EmptyAttributeChecker : public AttributeChecker }; /** - * \ingroup attributes + * \ingroup attribute_EmptyAttribute * * \brief Create an empty AttributeChecker. * diff --git a/src/core/model/boolean.cc b/src/core/model/boolean.cc index f7c2a0697b..e7706a5faa 100644 --- a/src/core/model/boolean.cc +++ b/src/core/model/boolean.cc @@ -24,7 +24,7 @@ /** * \file * \ingroup attribute_Boolean - * ns3::BooleanValue attribute value implementaation. + * ns3::BooleanValue attribute value implementation. */ namespace ns3 @@ -38,7 +38,7 @@ BooleanValue::BooleanValue() NS_LOG_FUNCTION(this); } -BooleanValue::BooleanValue(bool value) +BooleanValue::BooleanValue(const bool& value) : m_value(value) { NS_LOG_FUNCTION(this << value); diff --git a/src/core/model/boolean.h b/src/core/model/boolean.h index 8e010b0090..4b19f31f86 100644 --- a/src/core/model/boolean.h +++ b/src/core/model/boolean.h @@ -37,12 +37,7 @@ class BooleanValue : public AttributeValue { public: BooleanValue(); - /** - * Construct from an explicit value. - * - * \param [in] value The boolean value to begin with. - */ - BooleanValue(bool value); + BooleanValue(const bool& value); void Set(bool value); bool Get() const; template diff --git a/src/core/model/callback.cc b/src/core/model/callback.cc index 909bb30b92..3971a53582 100644 --- a/src/core/model/callback.cc +++ b/src/core/model/callback.cc @@ -38,8 +38,8 @@ CallbackValue::CallbackValue() NS_LOG_FUNCTION(this); } -CallbackValue::CallbackValue(const CallbackBase& base) - : m_value(base) +CallbackValue::CallbackValue(const CallbackBase& value) + : m_value(value) { } @@ -49,11 +49,17 @@ CallbackValue::~CallbackValue() } void -CallbackValue::Set(CallbackBase base) +CallbackValue::Set(const CallbackBase& value) { - NS_LOG_FUNCTION(&base); + NS_LOG_FUNCTION(&value); + m_value = value; +} - m_value = base; +CallbackBase +CallbackValue::Get() +{ + NS_LOG_FUNCTION(this); + return m_value; } Ptr diff --git a/src/core/model/callback.h b/src/core/model/callback.h index 573aa29e65..df4a2dfb80 100644 --- a/src/core/model/callback.h +++ b/src/core/model/callback.h @@ -490,8 +490,10 @@ class Callback : public CallbackBase * of the first argument is a class derived from CallbackBase (i.e., a Callback). */ template , int> = 0, - typename... BArgs> + typename... BArgs, + std::enable_if_t && + std::is_invocable_r_v, + int> = 0> Callback(T func, BArgs... bargs) { // store the function in a std::function object @@ -648,18 +650,12 @@ class Callback : public CallbackBase */ bool DoCheckType(Ptr other) const { - if (other && dynamic_cast*>(PeekPointer(other)) != nullptr) + if (!other) { return true; } - else if (!other) - { - return true; - } - else - { - return false; - } + + return (dynamic_cast*>(PeekPointer(other)) != nullptr); } }; @@ -805,18 +801,12 @@ namespace ns3 class CallbackValue : public AttributeValue { public: - /** Constructor */ CallbackValue(); - /** - * Copy constructor - * \param [in] base Callback to copy - */ - CallbackValue(const CallbackBase& base); - /** Destructor */ + CallbackValue(const CallbackBase& value); ~CallbackValue() override; - /** \param [in] base The CallbackBase to use */ - void Set(CallbackBase base); - /* Documented by print-introspected-doxygen.cc */ + // Documented by print-introspected-doxygen.cc + void Set(const CallbackBase& value); + CallbackBase Get(); template bool GetAccessor(T& value) const; /** \return A copy of this CallBack */ diff --git a/src/core/model/config.cc b/src/core/model/config.cc index 5f6c51aa8a..578d4c7be7 100644 --- a/src/core/model/config.cc +++ b/src/core/model/config.cc @@ -30,10 +30,14 @@ /** * \file - * \ingroup config + * \ingroup config-impl * ns3::Config implementations. */ +/** + * \defgroup config-impl Config implementations + * \ingroup config + */ namespace ns3 { diff --git a/src/core/model/deprecated.h b/src/core/model/deprecated.h index eb6035e5bf..4166d84e79 100644 --- a/src/core/model/deprecated.h +++ b/src/core/model/deprecated.h @@ -22,12 +22,17 @@ /** * \file - * \ingroup core + * \ingroup deprecation * NS_DEPRECATED macro definition. */ /** + * \defgroup deprecation Deprecation * \ingroup core + */ + +/** + * \ingroup deprecation * \def NS_DEPRECATED * Mark a function as deprecated. * @@ -36,8 +41,22 @@ * When deprecating a feature, please update the documentation * with information for users on how to update their code. * - * For example, - * \snippet src/core/doc/deprecated-example.h doxygen snippet + * The following snippet shows an example of how to deprecate the function SomethingUseful() + * in favor of the new function TheNewWay(). + * Note: in the following snippet, the Doxygen blocks are not following the ns-3 style. + * This allows the code to be safely embedded in the documentation. + * + * \code + * /// Do something useful. + * /// + * /// \deprecated This method will go away in future versions of ns-3. + * /// See instead TheNewWay(). + * NS_DEPRECATED_3_XX("see TheNewWay") + * void SomethingUseful(); + * + * /// Do something more useful. + * void TheNewWay(); + * \endcode * * Please follow these two guidelines to ease future maintenance * (primarily the eventual removal of the deprecated code): @@ -48,7 +67,8 @@ * 2. Typically only the declaration needs to be deprecated, * * \code - * NS_DEPRECATED_3_XX ("see TheNewWay") void SomethingUseful (); + * NS_DEPRECATED_3_XX("see TheNewWay") + * void SomethingUseful(); * \endcode * * but it's helpful to put the same macro as a comment @@ -56,9 +76,9 @@ * all the bits which eventually have to be removed: * * \code - * \/\* NS_DEPRECATED_3_XX ("see TheNewWay") *\\/ - * void SomethingUseful () { ... } - * \endcode. + * // NS_DEPRECATED_3_XX("see TheNewWay") + * void SomethingUseful() { ... } + * \endcode * * \note Sometimes it is necessary to silence a deprecation warning. * Even though this is highly discouraged, if necessary it is possible to use: @@ -75,17 +95,24 @@ #define NS_DEPRECATED(msg) [[deprecated(msg)]] /** - * \ingroup core + * \ingroup deprecation + * \def NS_DEPRECATED_3_42 + * Tag for things deprecated in version ns-3.42. + */ +#define NS_DEPRECATED_3_42(msg) NS_DEPRECATED("Deprecated in ns-3.42: " msg) + +/** + * \ingroup deprecation * \def NS_DEPRECATED_3_41 * Tag for things deprecated in version ns-3.41. */ -#define NS_DEPRECATED_3_41(msg) NS_DEPRECATED(msg) +#define NS_DEPRECATED_3_41(msg) NS_DEPRECATED("Deprecated in ns-3.41: " msg) /** - * \ingroup core + * \ingroup deprecation * \def NS_DEPRECATED_3_40 * Tag for things deprecated in version ns-3.40. */ -#define NS_DEPRECATED_3_40(msg) NS_DEPRECATED(msg) +#define NS_DEPRECATED_3_40(msg) NS_DEPRECATED("Deprecated in ns-3.40: " msg) #endif /* NS3_DEPRECATED_H */ diff --git a/src/core/model/enum.h b/src/core/model/enum.h index 3849abd798..464a7c039a 100644 --- a/src/core/model/enum.h +++ b/src/core/model/enum.h @@ -62,12 +62,7 @@ class EnumValue : public AttributeValue { public: EnumValue(); - /** - * Construct from an explicit value. - * - * \param [in] value The value to begin with. - */ - EnumValue(T value); + EnumValue(const T& value); void Set(T value); T Get() const; @@ -78,14 +73,14 @@ class EnumValue : public AttributeValue bool DeserializeFromString(std::string value, Ptr checker) override; private: - T m_value; //!< The stored value. + T m_value{}; //!< The stored value. }; template EnumValue::EnumValue() = default; template -EnumValue::EnumValue(T value) +EnumValue::EnumValue(const T& value) : m_value(value) { } diff --git a/src/core/model/event-id.cc b/src/core/model/event-id.cc index ef2dd46cd7..174e014291 100644 --- a/src/core/model/event-id.cc +++ b/src/core/model/event-id.cc @@ -73,12 +73,18 @@ EventId::IsExpired() const } bool -EventId::IsRunning() const +EventId::IsPending() const { NS_LOG_FUNCTION(this); return !IsExpired(); } +bool +EventId::IsRunning() const +{ + return IsPending(); +} + EventImpl* EventId::PeekEventImpl() const { diff --git a/src/core/model/event-id.h b/src/core/model/event-id.h index 8361c6ec1b..5f042d4d8f 100644 --- a/src/core/model/event-id.h +++ b/src/core/model/event-id.h @@ -19,6 +19,7 @@ #ifndef EVENT_ID_H #define EVENT_ID_H +#include "deprecated.h" #include "event-impl.h" #include "ptr.h" @@ -47,7 +48,7 @@ class EventImpl; * The important thing to remember about this class is that * every variable of this type is _always_ in a valid state, * even when it has not been assigned an EventId coming from a - * Simulator::Schedule() method: calling Simulator::Cancel(), IsRunning(), + * Simulator::Schedule() method: calling Simulator::Cancel(), IsPending(), * IsExpired() or passing around instances of this object * will not result in crashes or memory leaks. */ @@ -101,6 +102,14 @@ class EventId * * \returns \c true if the event has not expired, \c false otherwise. */ + bool IsPending() const; + + /** + * This method is syntactic sugar for !IsExpired(). + * + * \returns \c true if the event has not expired, \c false otherwise. + */ + NS_DEPRECATED_3_42("Use IsPending instead") bool IsRunning() const; public: diff --git a/src/core/model/example-as-test.cc b/src/core/model/example-as-test.cc index 3ff6e203bc..a53353a94e 100644 --- a/src/core/model/example-as-test.cc +++ b/src/core/model/example-as-test.cc @@ -153,9 +153,9 @@ ExampleAsTestSuite::ExampleAsTestSuite(const std::string name, const std::string program, const std::string dataDir, const std::string args /* = "" */, - const TestDuration duration /* =QUICK */, + const Duration duration /* =QUICK */, const bool shouldNotErr /* = true */) - : TestSuite(name, EXAMPLE) + : TestSuite(name, Type::EXAMPLE) { NS_LOG_FUNCTION(this << name << program << dataDir << args << duration << shouldNotErr); AddTestCase(new ExampleAsTestCase(name, program, dataDir, args, shouldNotErr), duration); diff --git a/src/core/model/example-as-test.h b/src/core/model/example-as-test.h index a13c482c19..c730ec39ec 100644 --- a/src/core/model/example-as-test.h +++ b/src/core/model/example-as-test.h @@ -218,7 +218,7 @@ class ExampleAsTestSuite : public TestSuite const std::string program, const std::string dataDir, const std::string args = "", - const TestDuration duration = QUICK, + const Duration duration = Duration::QUICK, const bool shouldNotErr = true); }; // class ExampleAsTestSuite diff --git a/src/core/model/global-value.h b/src/core/model/global-value.h index d1e1327d16..179191c017 100644 --- a/src/core/model/global-value.h +++ b/src/core/model/global-value.h @@ -41,7 +41,7 @@ class GlobalValueTestCase; } /** - * \ingroup Core + * \ingroup core * * \brief Hold a so-called 'global value'. * diff --git a/src/core/model/int64x64-128.cc b/src/core/model/int64x64-128.cc index daf1057414..c5fc432552 100644 --- a/src/core/model/int64x64-128.cc +++ b/src/core/model/int64x64-128.cc @@ -52,8 +52,8 @@ output_sign(const int128_t sa, const int128_t sb, uint128_t& ua, uint128_t& ub) { bool negA = sa < 0; bool negB = sb < 0; - ua = negA ? -sa : sa; - ub = negB ? -sb : sb; + ua = negA ? -static_cast(sa) : sa; + ub = negB ? -static_cast(sb) : sb; return negA != negB; } @@ -64,50 +64,64 @@ int64x64_t::Mul(const int64x64_t& o) uint128_t b; bool negative = output_sign(_v, o._v, a, b); uint128_t result = Umul(a, b); - _v = negative ? -result : result; + if (negative) + { + NS_ASSERT_MSG(result <= HP128_MASK_HI_BIT, "overflow detected"); + _v = -result; + } + else + { + NS_ASSERT_MSG(result < HP128_MASK_HI_BIT, "overflow detected"); + _v = result; + } } uint128_t int64x64_t::Umul(const uint128_t a, const uint128_t b) { - uint128_t aL = a & HP_MASK_LO; - uint128_t bL = b & HP_MASK_LO; - uint128_t aH = (a >> 64) & HP_MASK_LO; - uint128_t bH = (b >> 64) & HP_MASK_LO; - - uint128_t result; - uint128_t hiPart; - uint128_t loPart; - uint128_t midPart; - uint128_t res1; - uint128_t res2; - - // Multiplying (a.h 2^64 + a.l) x (b.h 2^64 + b.l) = - // 2^128 a.h b.h + 2^64*(a.h b.l+b.h a.l) + a.l b.l - // get the low part a.l b.l - // multiply the fractional part - loPart = aL * bL; - // compute the middle part 2^64*(a.h b.l+b.h a.l) - midPart = aL * bH + aH * bL; - // compute the high part 2^128 a.h b.h - hiPart = aH * bH; - // if the high part is not zero, put a warning - NS_ABORT_MSG_IF((hiPart & HP_MASK_HI) != 0, - "High precision 128 bits multiplication error: multiplication overflow."); - - // Adding 64-bit terms to get 128-bit results, with carries - res1 = loPart >> 64; - res2 = midPart & HP_MASK_LO; - result = res1 + res2; - - res1 = midPart >> 64; - res2 = hiPart & HP_MASK_LO; - res1 += res2; - res1 <<= 64; - - result += res1; + uint128_t al = a & HP_MASK_LO; + uint128_t bl = b & HP_MASK_LO; + uint128_t ah = a >> 64; + uint128_t bh = b >> 64; + + // Let Q(x) be the unsigned Q64.64 fixed point value represented by the uint128_t x: + // Q(x) * 2^64 = x = xh * 2^64 + xl. + // (Defining x this way avoids ambiguity about the meaning of the division operators in + // Q(x) = x / 2^64 = xh + xl / 2^64.) + // Then + // Q(a) = ah + al / 2^64 + // and + // Q(b) = bh + bl / 2^64. + // We need to find uint128_t c such that + // Q(c) = Q(a) * Q(b). + // Then + // c = Q(c) * 2^64 + // = (ah + al / 2^64) * (bh + bl / 2^64) * 2^64 + // = (ah * 2^64 + al) * (bh * 2^64 + bl) / 2^64 + // = ah * bh * 2^64 + (ah * bl + al * bh) + al * bl / 2^64. + // We compute the last part of c by (al * bl) >> 64 which truncates (instead of rounds) + // the LSB. If c exceeds 2^127, we might assert. This is because our caller + // (Mul function) will not be able to represent the result. + + uint128_t res = (al * bl) >> 64; + { + // ah, bh <= 2^63 and al, bl <= 2^64 - 1, so mid < 2^128 - 2^64 and there is no + // integer overflow. + uint128_t mid = ah * bl + al * bh; + // res < 2^64, so there is no integer overflow. + res += mid; + } + { + uint128_t high = ah * bh; + // If high > 2^63, then the result will overflow. + NS_ASSERT_MSG(high <= (static_cast(1) << 63), "overflow detected"); + high <<= 64; + NS_ASSERT_MSG(res + high >= res, "overflow detected"); + // No overflow since res, high <= 2^127 and one of res, high is < 2^127. + res += high; + } - return result; + return res; } void @@ -189,7 +203,7 @@ void int64x64_t::MulByInvert(const int64x64_t& o) { bool negResult = _v < 0; - uint128_t a = negResult ? -_v : _v; + uint128_t a = negResult ? -static_cast(_v) : _v; uint128_t result = UmulByInvert(a, o._v); _v = negResult ? -result : result; @@ -198,21 +212,25 @@ int64x64_t::MulByInvert(const int64x64_t& o) uint128_t int64x64_t::UmulByInvert(const uint128_t a, const uint128_t b) { - uint128_t result; - uint128_t ah; - uint128_t bh; - uint128_t al; - uint128_t bl; - uint128_t hi; - uint128_t mid; - ah = a >> 64; - bh = b >> 64; - al = a & HP_MASK_LO; - bl = b & HP_MASK_LO; - hi = ah * bh; - mid = ah * bl + al * bh; + // Since b is assumed to be the output of Invert(), b <= 2^127. + NS_ASSERT(b <= HP128_MASK_HI_BIT); + + uint128_t al = a & HP_MASK_LO; + uint128_t bl = b & HP_MASK_LO; + uint128_t ah = a >> 64; + uint128_t bh = b >> 64; + + // Since ah, bh <= 2^63, high <= 2^126 and there is no overflow. + uint128_t high = ah * bh; + + // Since ah, bh <= 2^63 and al, bl < 2^64, mid < 2^128 and there is + // no overflow. + uint128_t mid = ah * bl + al * bh; mid >>= 64; - result = hi + mid; + + // Since high <= 2^126 and mid < 2^64, result < 2^127 and there is no overflow. + uint128_t result = high + mid; + return result; } diff --git a/src/core/model/int64x64-128.h b/src/core/model/int64x64-128.h index 3f50efc7d7..0c2a068b31 100644 --- a/src/core/model/int64x64-128.h +++ b/src/core/model/int64x64-128.h @@ -58,8 +58,6 @@ class int64x64_t static const uint128_t HP128_MASK_HI_BIT = (((int128_t)1) << 127); /// Mask for fraction part. static const uint64_t HP_MASK_LO = 0xffffffffffffffffULL; - /// Mask for sign + integer part. - static const uint64_t HP_MASK_HI = ~HP_MASK_LO; /** * Floating point value of HP_MASK_LO + 1. * We really want: @@ -190,11 +188,6 @@ class int64x64_t _v <<= 64; } - inline int64x64_t(const int128_t v) - : _v(v) - { - } - /**@}*/ /** @@ -403,7 +396,9 @@ class int64x64_t friend inline int64x64_t operator-(const int64x64_t& lhs) { - return int64x64_t(-lhs._v); + int64x64_t res; + res._v = -lhs._v; + return res; } friend inline int64x64_t operator!(const int64x64_t& lhs) @@ -415,6 +410,7 @@ class int64x64_t /** * Implement `*=`. + * We assert if the product cannot be encoded in int64x64_t. * * \param [in] o The other factor. */ @@ -430,7 +426,7 @@ class int64x64_t * * Mathematically this should produce a Q128.128 value; * we keep the central 128 bits, representing the Q64.64 result. - * We assert on integer overflow beyond the 64-bit integer portion. + * We might assert if the result, in uint128_t format, exceeds 2^127. * * \param [in] a First factor. * \param [in] b Second factor. diff --git a/src/core/model/int64x64.cc b/src/core/model/int64x64.cc index a4155328d7..2c390b0502 100644 --- a/src/core/model/int64x64.cc +++ b/src/core/model/int64x64.cc @@ -23,6 +23,7 @@ #include // showpos #include +#include #include #include @@ -69,9 +70,19 @@ std::ostream& operator<<(std::ostream& os, const int64x64_t& value) { const bool negative = (value < 0); - const int64x64_t absVal = (negative ? -value : value); - int64_t hi = absVal.GetHigh(); + uint64_t hi; + int64x64_t low; + if (value != int64x64_t(std::numeric_limits::min(), 0)) + { + const int64x64_t absVal = (negative ? -value : value); + hi = absVal.GetHigh(); + low = int64x64_t(0, absVal.GetLow()); + } + else + { + hi = static_cast(1) << 63; + } // Save stream format flags auto precision = static_cast(os.precision()); @@ -84,7 +95,6 @@ operator<<(std::ostream& os, const int64x64_t& value) std::ostringstream oss; oss << hi << "."; // collect the digits here so we can round properly - int64x64_t low(0, absVal.GetLow()); std::size_t places = 0; // Number of decimal places printed so far bool more = true; // Should we print more digits? diff --git a/src/core/model/make-event.cc b/src/core/model/make-event.cc deleted file mode 100644 index 8c32592a5d..0000000000 --- a/src/core/model/make-event.cc +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2008 INRIA - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include "make-event.h" - -#include "log.h" - -/** - * \file - * \ingroup events - * ns3::MakeEvent(void(*f)()) implementation. - */ - -namespace ns3 -{ - -NS_LOG_COMPONENT_DEFINE("MakeEvent"); - -// This is the only non-templated version of MakeEvent. -EventImpl* -MakeEvent(void (*f)()) -{ - NS_LOG_FUNCTION(f); - - // zero arg version - class EventFunctionImpl0 : public EventImpl - { - public: - typedef void (*F)(); - - EventFunctionImpl0(F function) - : m_function(function) - { - } - - ~EventFunctionImpl0() override - { - } - - protected: - void Notify() override - { - (*m_function)(); - } - - private: - F m_function; - }* ev = new EventFunctionImpl0(f); - - return ev; -} - -} // namespace ns3 diff --git a/src/core/model/make-event.h b/src/core/model/make-event.h index c08357d2b9..8cb09164c6 100644 --- a/src/core/model/make-event.h +++ b/src/core/model/make-event.h @@ -19,6 +19,12 @@ #ifndef MAKE_EVENT_H #define MAKE_EVENT_H +#include "warnings.h" + +#include +#include +#include + /** * \file * \ingroup events @@ -32,150 +38,21 @@ class EventImpl; /** * \ingroup events - * \defgroup makeeventmemptr MakeEvent from Member Function Pointer. - * - * Create EventImpl instances from class member functions which take - * varying numbers of arguments. - */ -/** - * \ingroup makeeventmemptr - * @{ - */ -/** * Make an EventImpl from class method members which take * varying numbers of arguments. * * \tparam MEM \deduced The class method function signature. * \tparam OBJ \deduced The class type holding the method. + * \tparam Ts \deduced Type template parameter pack. * \param [in] mem_ptr Class method member function pointer * \param [in] obj Class instance. + * \param [in] args Arguments to be bound to the underlying function. * \returns The constructed EventImpl. */ -template -EventImpl* MakeEvent(MEM mem_ptr, OBJ obj); - -/** - * \copybrief MakeEvent(MEM,OBJ) - * \tparam MEM \deduced The class method function signature. - * \tparam OBJ \deduced The class type holding the method. - * \tparam T1 \deduced Type of the argument to the underlying function. - * \param [in] mem_ptr Class method member function pointer - * \param [in] obj Class instance. - * \param [in] a1 Argument value to be bound to the underlying function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(MEM mem_ptr, OBJ obj, T1 a1); - -/** - * \copybrief MakeEvent(MEM,OBJ) - * \tparam MEM \deduced The class method function signature. - * \tparam OBJ \deduced The class type holding the method. - * \tparam T1 \deduced Type of the first argument to the underlying function. - * \tparam T2 \deduced Type of the second argument to the underlying function. - * \param [in] mem_ptr Class method member function pointer - * \param [in] obj Class instance. - * \param [in] a1 First argument value to be bound to the underlying function. - * \param [in] a2 Second argument value to be bound to the underlying function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2); - -/** - * \copybrief MakeEvent(MEM,OBJ) - * \tparam MEM \deduced The class method function signature. - * \tparam OBJ \deduced The class type holding the method. - * \tparam T1 \deduced Type of the first argument to the underlying function. - * \tparam T2 \deduced Type of the second argument to the underlying function. - * \tparam T3 \deduced Type of the third argument to the underlying function. - * \param [in] mem_ptr Class method member function pointer - * \param [in] obj Class instance. - * \param [in] a1 First argument value to be bound to the underlying function. - * \param [in] a2 Second argument value to be bound to the underlying function. - * \param [in] a3 Third argument value to be bound to the underlying function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3); - -/** - * \copybrief MakeEvent(MEM,OBJ) - * \tparam MEM \deduced The class method function signature. - * \tparam OBJ \deduced The class type holding the method. - * \tparam T1 \deduced Type of the first argument to the underlying function. - * \tparam T2 \deduced Type of the second argument to the underlying function. - * \tparam T3 \deduced Type of the third argument to the underlying function. - * \tparam T4 \deduced Type of the fourth argument to the underlying function. - * \param [in] mem_ptr Class method member function pointer - * \param [in] obj Class instance. - * \param [in] a1 First argument value to be bound to the underlying function. - * \param [in] a2 Second argument value to be bound to the underlying function. - * \param [in] a3 Third argument value to be bound to the underlying function. - * \param [in] a4 Fourth argument value to be bound to the underlying function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4); - -/** - * \copybrief MakeEvent(MEM,OBJ) - * \tparam MEM \deduced The class method function signature. - * \tparam OBJ \deduced The class type holding the method. - * \tparam T1 \deduced Type of the first argument to the underlying function. - * \tparam T2 \deduced Type of the second argument to the underlying function. - * \tparam T3 \deduced Type of the third argument to the underlying function. - * \tparam T4 \deduced Type of the fourth argument to the underlying function. - * \tparam T5 \deduced Type of the fifth argument to the underlying function. - * \param [in] mem_ptr Class method member function pointer - * \param [in] obj Class instance. - * \param [in] a1 First argument value to be bound to the underlying function. - * \param [in] a2 Second argument value to be bound to the underlying function. - * \param [in] a3 Third argument value to be bound to the underlying function. - * \param [in] a4 Fourth argument value to be bound to the underlying function. - * \param [in] a5 Fifh argument value to be bound to the underlying function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); - -/** - * \copybrief MakeEvent(MEM,OBJ) - * \tparam MEM The class method function signature. - * \tparam OBJ The class type holding the method. - * \tparam T1 Type of the first argument to the underlying function. - * \tparam T2 Type of the second argument to the underlying function. - * \tparam T3 Type of the third argument to the underlying function. - * \tparam T4 Type of the fourth argument to the underlying function. - * \tparam T5 Type of the fifth argument to the underlying function. - * \tparam T6 Type of the sixth argument to the underlying function. - * \param mem_ptr Class method member function pointer - * \param obj Class instance. - * \param a1 First argument value to be bound to the underlying function. - * \param a2 Second argument value to be bound to the underlying function. - * \param a3 Third argument value to be bound to the underlying function. - * \param a4 Fourth argument value to be bound to the underlying function. - * \param a5 Fifth argument value to be bound to the underlying function. - * \param a6 Sixth argument value to be bound to the underlying function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6); - -/**@}*/ +template +std::enable_if_t, EventImpl*> MakeEvent(MEM mem_ptr, + OBJ obj, + Ts... args); /** * \ingroup events @@ -190,148 +67,14 @@ EventImpl* MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 * Make an EventImpl from a function pointer taking varying numbers * of arguments. * + * \tparam Us \deduced Formal types of the arguments to the function. + * \tparam Ts \deduced Actual types of the arguments to the function. * \param [in] f The function pointer. + * \param [in] args Arguments to be bound to the function. * \returns The constructed EventImpl. */ -EventImpl* MakeEvent(void (*f)()); - -/** - * \copybrief MakeEvent(void(*f)()) - * \tparam U1 \deduced Formal type of the argument to the function. - * \tparam T1 \deduced Actual type of the argument to the function. - * \param [in] f The function pointer. - * \param [in] a1 Argument to be bound to the function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(void (*f)(U1), T1 a1); - -/** - * \copybrief MakeEvent(void(*f)()) - * \tparam U1 \deduced Formal type of the first argument to the function. - * \tparam U2 \deduced Formal type of the second argument to the function. - * \tparam T1 \deduced Actual type of the first argument to the function. - * \tparam T2 \deduced Actual type of the second argument to the function. - * \param [in] f The function pointer. - * \param [in] a1 First argument to be bound to the function. - * \param [in] a2 Second argument to be bound to the function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(void (*f)(U1, U2), T1 a1, T2 a2); - -/** - * \copybrief MakeEvent(void(*f)()) - * \tparam U1 \deduced Formal type of the first argument to the function. - * \tparam U2 \deduced Formal type of the second argument to the function. - * \tparam U3 \deduced Formal type of the third argument to the function. - * \tparam T1 \deduced Actual type of the first argument to the function. - * \tparam T2 \deduced Actual type of the second argument to the function. - * \tparam T3 \deduced Actual type of the third argument to the function. - * \param [in] f The function pointer. - * \param [in] a1 First argument to be bound to the function. - * \param [in] a2 Second argument to be bound to the function. - * \param [in] a3 Third argument to be bound to the function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(void (*f)(U1, U2, U3), T1 a1, T2 a2, T3 a3); - -/** - * \copybrief MakeEvent(void(*f)()) - * \tparam U1 \deduced Formal type of the first argument to the function. - * \tparam U2 \deduced Formal type of the second argument to the function. - * \tparam U3 \deduced Formal type of the third argument to the function. - * \tparam U4 \deduced Formal type of the fourth argument to the function. - * \tparam T1 \deduced Actual type of the first argument to the function. - * \tparam T2 \deduced Actual type of the second argument to the function. - * \tparam T3 \deduced Actual type of the third argument to the function. - * \tparam T4 \deduced Actual type of the fourth argument to the function. - * \param [in] f The function pointer. - * \param [in] a1 First argument to be bound to the function. - * \param [in] a2 Second argument to be bound to the function. - * \param [in] a3 Third argument to be bound to the function. - * \param [in] a4 Fourth argument to be bound to the function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(void (*f)(U1, U2, U3, U4), T1 a1, T2 a2, T3 a3, T4 a4); - -/** - * \copybrief MakeEvent(void(*f)()) - * \tparam U1 \deduced Formal type of the first argument to the function. - * \tparam U2 \deduced Formal type of the second argument to the function. - * \tparam U3 \deduced Formal type of the third argument to the function. - * \tparam U4 \deduced Formal type of the fourth argument to the function. - * \tparam U5 \deduced Formal type of the fifth argument to the function. - * \tparam T1 \deduced Actual type of the first argument to the function. - * \tparam T2 \deduced Actual type of the second argument to the function. - * \tparam T3 \deduced Actual type of the third argument to the function. - * \tparam T4 \deduced Actual type of the fourth argument to the function. - * \tparam T5 \deduced Actual type of the fifth argument to the function. - * \param [in] f The function pointer. - * \param [in] a1 First argument to be bound to the function. - * \param [in] a2 Second argument to be bound to the function. - * \param [in] a3 Third argument to be bound to the function. - * \param [in] a4 Fourth argument to be bound to the function. - * \param [in] a5 Fifth argument to be bound to the function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(void (*f)(U1, U2, U3, U4, U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); - -/** - * \copybrief MakeEvent(void(*f)()) - * \tparam U1 Formal type of the first argument to the function. - * \tparam U2 Formal type of the second argument to the function. - * \tparam U3 Formal type of the third argument to the function. - * \tparam U4 Formal type of the fourth argument to the function. - * \tparam U5 Formal type of the fifth argument to the function. - * \tparam U6 Formal type of the sixth argument to the function. - * \tparam T1 Actual type of the first argument to the function. - * \tparam T2 Actual type of the second argument to the function. - * \tparam T3 Actual type of the third argument to the function. - * \tparam T4 Actual type of the fourth argument to the function. - * \tparam T5 Actual type of the fifth argument to the function. - * \tparam T6 Actual type of the sixth argument to the function. - * \param f The function pointer. - * \param a1 First argument to be bound to the function. - * \param a2 Second argument to be bound to the function. - * \param a3 Third argument to be bound to the function. - * \param a4 Fourth argument to be bound to the function. - * \param a5 Fifth argument to be bound to the function. - * \param a6 Sixth argument to be bound to the function. - * \returns The constructed EventImpl. - */ -template -EventImpl* MakeEvent(void (*f)(U1, U2, U3, U4, U5, U6), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6); +template +EventImpl* MakeEvent(void (*f)(Us...), Ts... args); /** * Make an EventImpl from a lambda. @@ -351,13 +94,15 @@ EventImpl* MakeEvent(T function); ********************************************************************/ #include "event-impl.h" -#include "type-traits.h" namespace ns3 { +namespace internal +{ + /** - * \ingroup makeeventmemptr + * \ingroup events * Helper for the MakeEvent functions which take a class method. * * This helper converts a pointer to a reference. @@ -370,7 +115,7 @@ template struct EventMemberImplObjTraits; /** - * \ingroup makeeventmemptr + * \ingroup events * Helper for the MakeEvent functions which take a class method. * * This helper converts a pointer to a reference. @@ -392,544 +137,66 @@ struct EventMemberImplObjTraits } }; -template -EventImpl* -MakeEvent(MEM mem_ptr, OBJ obj) -{ - // zero argument version - class EventMemberImpl0 : public EventImpl - { - public: - EventMemberImpl0(OBJ obj, MEM function) - : m_obj(obj), - m_function(function) - { - } - - ~EventMemberImpl0() override - { - } - - private: - void Notify() override - { - (EventMemberImplObjTraits::GetReference(m_obj).*m_function)(); - } - - OBJ m_obj; - MEM m_function; - }* ev = new EventMemberImpl0(obj, mem_ptr); - - return ev; -} - -template -EventImpl* -MakeEvent(MEM mem_ptr, OBJ obj, T1 a1) -{ - // one argument version - class EventMemberImpl1 : public EventImpl - { - public: - EventMemberImpl1(OBJ obj, MEM function, T1 a1) - : m_obj(obj), - m_function(function), - m_a1(a1) - { - } - - protected: - ~EventMemberImpl1() override - { - } - - private: - void Notify() override - { - (EventMemberImplObjTraits::GetReference(m_obj).*m_function)(m_a1); - } - - OBJ m_obj; - MEM m_function; - typename TypeTraits::ReferencedType m_a1; - }* ev = new EventMemberImpl1(obj, mem_ptr, a1); - - return ev; -} - -template -EventImpl* -MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2) -{ - // two argument version - class EventMemberImpl2 : public EventImpl - { - public: - EventMemberImpl2(OBJ obj, MEM function, T1 a1, T2 a2) - : m_obj(obj), - m_function(function), - m_a1(a1), - m_a2(a2) - { - } - - protected: - ~EventMemberImpl2() override - { - } - - private: - void Notify() override - { - (EventMemberImplObjTraits::GetReference(m_obj).*m_function)(m_a1, m_a2); - } - - OBJ m_obj; - MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - }* ev = new EventMemberImpl2(obj, mem_ptr, a1, a2); - - return ev; -} - -template -EventImpl* -MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3) -{ - // three argument version - class EventMemberImpl3 : public EventImpl - { - public: - EventMemberImpl3(OBJ obj, MEM function, T1 a1, T2 a2, T3 a3) - : m_obj(obj), - m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3) - { - } - - protected: - ~EventMemberImpl3() override - { - } - - private: - void Notify() override - { - (EventMemberImplObjTraits::GetReference(m_obj).*m_function)(m_a1, m_a2, m_a3); - } - - OBJ m_obj; - MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - }* ev = new EventMemberImpl3(obj, mem_ptr, a1, a2, a3); - - return ev; -} - -template -EventImpl* -MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4) -{ - // four argument version - class EventMemberImpl4 : public EventImpl - { - public: - EventMemberImpl4(OBJ obj, MEM function, T1 a1, T2 a2, T3 a3, T4 a4) - : m_obj(obj), - m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3), - m_a4(a4) - { - } - - protected: - ~EventMemberImpl4() override - { - } - - private: - void Notify() override - { - (EventMemberImplObjTraits::GetReference(m_obj).* - m_function)(m_a1, m_a2, m_a3, m_a4); - } - - OBJ m_obj; - MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - typename TypeTraits::ReferencedType m_a4; - }* ev = new EventMemberImpl4(obj, mem_ptr, a1, a2, a3, a4); - - return ev; -} - -template -EventImpl* -MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) -{ - // five argument version - class EventMemberImpl5 : public EventImpl - { - public: - EventMemberImpl5(OBJ obj, MEM function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - : m_obj(obj), - m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3), - m_a4(a4), - m_a5(a5) - { - } - - protected: - ~EventMemberImpl5() override - { - } - - private: - void Notify() override - { - (EventMemberImplObjTraits::GetReference(m_obj).* - m_function)(m_a1, m_a2, m_a3, m_a4, m_a5); - } - - OBJ m_obj; - MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - typename TypeTraits::ReferencedType m_a4; - typename TypeTraits::ReferencedType m_a5; - }* ev = new EventMemberImpl5(obj, mem_ptr, a1, a2, a3, a4, a5); - - return ev; -} - -template -EventImpl* -MakeEvent(MEM mem_ptr, OBJ obj, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) -{ - // six argument version - class EventMemberImpl6 : public EventImpl - { - public: - EventMemberImpl6(OBJ obj, MEM function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) - : m_obj(obj), - m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3), - m_a4(a4), - m_a5(a5), - m_a6(a6) - { - } - - protected: - ~EventMemberImpl6() override - { - } - - private: - void Notify() override - { - (EventMemberImplObjTraits::GetReference(m_obj).* - m_function)(m_a1, m_a2, m_a3, m_a4, m_a5, m_a6); - } - - OBJ m_obj; - MEM m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - typename TypeTraits::ReferencedType m_a4; - typename TypeTraits::ReferencedType m_a5; - typename TypeTraits::ReferencedType m_a6; - }* ev = new EventMemberImpl6(obj, mem_ptr, a1, a2, a3, a4, a5, a6); - - return ev; -} +} // namespace internal -template -EventImpl* -MakeEvent(void (*f)(U1), T1 a1) +template +std::enable_if_t, EventImpl*> +MakeEvent(MEM mem_ptr, OBJ obj, Ts... args) { - // one arg version - class EventFunctionImpl1 : public EventImpl + class EventMemberImpl : public EventImpl { public: - [[maybe_unused]] typedef void (*F)(U1); + EventMemberImpl() = delete; - EventFunctionImpl1(F function, T1 a1) - : m_function(function), - m_a1(a1) + EventMemberImpl(OBJ obj, MEM function, Ts... args) + : m_function(std::bind(function, obj, args...)) { } protected: - ~EventFunctionImpl1() override + ~EventMemberImpl() override { } private: void Notify() override { - (*m_function)(m_a1); - } - - F m_function; - typename TypeTraits::ReferencedType m_a1; - }* ev = new EventFunctionImpl1(f, a1); - - return ev; -} - -template -EventImpl* -MakeEvent(void (*f)(U1, U2), T1 a1, T2 a2) -{ - // two arg version - class EventFunctionImpl2 : public EventImpl - { - public: - [[maybe_unused]] typedef void (*F)(U1, U2); - - EventFunctionImpl2(F function, T1 a1, T2 a2) - : m_function(function), - m_a1(a1), - m_a2(a2) - { - } - - protected: - ~EventFunctionImpl2() override - { - } - - private: - void Notify() override - { - (*m_function)(m_a1, m_a2); - } - - F m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - }* ev = new EventFunctionImpl2(f, a1, a2); - - return ev; -} - -template -EventImpl* -MakeEvent(void (*f)(U1, U2, U3), T1 a1, T2 a2, T3 a3) -{ - // three arg version - class EventFunctionImpl3 : public EventImpl - { - public: - [[maybe_unused]] typedef void (*F)(U1, U2, U3); - - EventFunctionImpl3(F function, T1 a1, T2 a2, T3 a3) - : m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3) - { - } - - protected: - ~EventFunctionImpl3() override - { - } - - private: - void Notify() override - { - (*m_function)(m_a1, m_a2, m_a3); - } - - F m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - }* ev = new EventFunctionImpl3(f, a1, a2, a3); - - return ev; -} - -template -EventImpl* -MakeEvent(void (*f)(U1, U2, U3, U4), T1 a1, T2 a2, T3 a3, T4 a4) -{ - // four arg version - class EventFunctionImpl4 : public EventImpl - { - public: - [[maybe_unused]] typedef void (*F)(U1, U2, U3, U4); - - EventFunctionImpl4(F function, T1 a1, T2 a2, T3 a3, T4 a4) - : m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3), - m_a4(a4) - { - } - - protected: - ~EventFunctionImpl4() override - { - } - - private: - void Notify() override - { - (*m_function)(m_a1, m_a2, m_a3, m_a4); - } - - F m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - typename TypeTraits::ReferencedType m_a4; - }* ev = new EventFunctionImpl4(f, a1, a2, a3, a4); - - return ev; -} - -template -EventImpl* -MakeEvent(void (*f)(U1, U2, U3, U4, U5), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) -{ - // five arg version - class EventFunctionImpl5 : public EventImpl - { - public: - [[maybe_unused]] typedef void (*F)(U1, U2, U3, U4, U5); - - EventFunctionImpl5(F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - : m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3), - m_a4(a4), - m_a5(a5) - { - } - - protected: - ~EventFunctionImpl5() override - { - } - - private: - void Notify() override - { - (*m_function)(m_a1, m_a2, m_a3, m_a4, m_a5); + m_function(); } - F m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - typename TypeTraits::ReferencedType m_a4; - typename TypeTraits::ReferencedType m_a5; - }* ev = new EventFunctionImpl5(f, a1, a2, a3, a4, a5); + std::function m_function; + }* ev = new EventMemberImpl(obj, mem_ptr, args...); return ev; } -template +template EventImpl* -MakeEvent(void (*f)(U1, U2, U3, U4, U5, U6), T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) +MakeEvent(void (*f)(Us...), Ts... args) { - // six arg version - class EventFunctionImpl6 : public EventImpl + class EventFunctionImpl : public EventImpl { public: - [[maybe_unused]] typedef void (*F)(U1, U2, U3, U4, U5, U6); - - EventFunctionImpl6(F function, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) + EventFunctionImpl(void (*function)(Us...), Ts... args) : m_function(function), - m_a1(a1), - m_a2(a2), - m_a3(a3), - m_a4(a4), - m_a5(a5), - m_a6(a6) + m_arguments(args...) { } protected: - ~EventFunctionImpl6() override + ~EventFunctionImpl() override { } private: void Notify() override { - (*m_function)(m_a1, m_a2, m_a3, m_a4, m_a5, m_a6); + std::apply([this](Ts... args) { (*m_function)(args...); }, m_arguments); } - F m_function; - typename TypeTraits::ReferencedType m_a1; - typename TypeTraits::ReferencedType m_a2; - typename TypeTraits::ReferencedType m_a3; - typename TypeTraits::ReferencedType m_a4; - typename TypeTraits::ReferencedType m_a5; - typename TypeTraits::ReferencedType m_a6; - }* ev = new EventFunctionImpl6(f, a1, a2, a3, a4, a5, a6); + void (*m_function)(Us...); + std::tuple...> m_arguments; + }* ev = new EventFunctionImpl(f, args...); return ev; } diff --git a/src/core/model/matrix-array.cc b/src/core/model/matrix-array.cc index 72ec3f99a2..854266dee9 100644 --- a/src/core/model/matrix-array.cc +++ b/src/core/model/matrix-array.cc @@ -156,6 +156,70 @@ MatrixArray::Transpose() const return res; } +template +MatrixArray +MatrixArray::Determinant() const +{ + MatrixArray res{1, 1, m_numPages}; + NS_ASSERT_MSG(m_numRows == m_numCols, "Matrix is not square"); + // In case of small matrices, we use a fast path + if (m_numRows == 1) + { + return *this; + } + // Calculate determinant for each matrix + for (size_t page = 0; page < m_numPages; ++page) + { + res(0, 0, page) = 0; + auto pageValues = GetPagePtr(page); + + // Fast path for 2x2 matrices + if (m_numRows == 2) + { + res(0, 0, page) = pageValues[0] * pageValues[3] - pageValues[1] * pageValues[2]; + continue; + } + for (size_t detN = 0; detN < m_numRows; detN++) + { + auto partDetP = T{0} + 1.0; + auto partDetN = T{0} + 1.0; + for (size_t row = 0; row < m_numRows; row++) + { + // Wraparound not to have to extend the matrix + // Positive determinant + size_t col = (row + detN) % m_numCols; + partDetP *= pageValues[row * m_numCols + col]; + + // Negative determinant + col = m_numCols - 1 - (row + detN) % m_numCols; + partDetN *= pageValues[row * m_numCols + col]; + } + res(0, 0, page) += partDetP - partDetN; + } + } + return res; +} + +template +MatrixArray +MatrixArray::FrobeniusNorm() const +{ + MatrixArray res{1, 1, m_numPages}; + for (size_t page = 0; page < m_numPages; ++page) + { + // Calculate the sum of squared absolute values of each matrix page + res[page] = 0; + auto pagePtr = this->GetPagePtr(page); + for (size_t i = 0; i < m_numRows * m_numCols; i++) + { + auto absVal = std::abs(pagePtr[i]); + res[page] += absVal * absVal; + } + res[page] = sqrt(res[page]); + } + return res; +} + template MatrixArray MatrixArray::MultiplyByLeftAndRightMatrix(const MatrixArray& lMatrix, @@ -229,6 +293,84 @@ MatrixArray::HermitianTranspose() const return retMatrix; } +template +MatrixArray +MatrixArray::MakeNCopies(size_t nCopies) const +{ + NS_ASSERT_MSG(m_numPages == 1, "The MatrixArray should have only one page to be copied."); + auto copiedMatrix = MatrixArray{m_numRows, m_numCols, nCopies}; + for (size_t copy = 0; copy < nCopies; copy++) + { + for (size_t i = 0; i < m_numRows * m_numCols; i++) + { + copiedMatrix.GetPagePtr(copy)[i] = m_values[i]; + } + } + return copiedMatrix; +} + +template +MatrixArray +MatrixArray::ExtractPage(size_t page) const +{ + NS_ASSERT_MSG(page < m_numPages, "The page to extract from the MatrixArray is out of bounds."); + auto extractedPage = MatrixArray{m_numRows, m_numCols, 1}; + + for (size_t i = 0; i < m_numRows * m_numCols; ++i) + { + extractedPage.m_values[i] = GetPagePtr(page)[i]; + } + return extractedPage; +} + +template +MatrixArray +MatrixArray::JoinPages(const std::vector>& pages) +{ + auto jointMatrix = + MatrixArray{pages.front().GetNumRows(), pages.front().GetNumCols(), pages.size()}; + for (size_t page = 0; page < jointMatrix.GetNumPages(); page++) + { + NS_ASSERT_MSG(pages[page].GetNumRows() == jointMatrix.GetNumRows(), + "All page matrices should have the same number of rows"); + NS_ASSERT_MSG(pages[page].GetNumCols() == jointMatrix.GetNumCols(), + "All page matrices should have the same number of columns"); + NS_ASSERT_MSG(pages[page].GetNumPages() == 1, + "All page matrices should have a single page"); + + size_t i = 0; + for (auto a : pages[page].GetValues()) + { + jointMatrix.GetPagePtr(page)[i] = a; + i++; + } + } + return jointMatrix; +} + +template +MatrixArray +MatrixArray::IdentityMatrix(const size_t size, const size_t pages) +{ + auto identityMatrix = MatrixArray{size, size, pages}; + for (std::size_t page = 0; page < pages; page++) + { + for (std::size_t i = 0; i < size; i++) + { + identityMatrix(i, i, page) = 1.0; + } + } + return identityMatrix; +} + +template +MatrixArray +MatrixArray::IdentityMatrix(const MatrixArray& likeme) +{ + NS_ASSERT_MSG(likeme.GetNumRows() == likeme.GetNumCols(), "Template array is not square."); + return IdentityMatrix(likeme.GetNumRows(), likeme.GetNumPages()); +} + template MatrixArray> MatrixArray>::HermitianTranspose() const; template class MatrixArray>; diff --git a/src/core/model/matrix-array.h b/src/core/model/matrix-array.h index 34305e214d..3e3bf6ca0a 100644 --- a/src/core/model/matrix-array.h +++ b/src/core/model/matrix-array.h @@ -189,6 +189,16 @@ class MatrixArray : public ValArray * \return The resulting MatrixArray composed of the array of transposed matrices. */ MatrixArray Transpose() const; + /** + * \brief This operator calculates a vector o determinants, one for each page + * \return The resulting MatrixArray with the determinants for each page. + */ + MatrixArray Determinant() const; + /** + * \brief This operator calculates a vector of Frobenius norm, one for each page + * \return The resulting MatrixArray with the Frobenius norm for each page. + */ + MatrixArray FrobeniusNorm() const; /** *\brief Multiply each matrix in the array by the left and the right matrix. * For each page of this MatrixArray the operation performed is @@ -229,6 +239,40 @@ class MatrixArray : public ValArray typename = std::enable_if_t<(std::is_same_v> && EnableBool)>> MatrixArray HermitianTranspose() const; + /** + * \brief Function that copies the current 1-page matrix into a new matrix with n copies of the + * original matrix + * \param nCopies Number of copies to make of the input 1-page MatrixArray + * \return Returns a new matrix with n page copies + */ + MatrixArray MakeNCopies(size_t nCopies) const; + /** + * \brief Function extracts a page from a MatrixArray + * \param page Index of the page to be extracted from the n-page MatrixArray + * \return Returns an extracted page of the original MatrixArray + */ + MatrixArray ExtractPage(size_t page) const; + /** + * \brief Function joins multiple pages into a single MatrixArray + * \param pages Vector containing n 1-page MatrixArrays to be merged into a n-page MatrixArray + * \return Returns a joint MatrixArray + */ + static MatrixArray JoinPages(const std::vector>& pages); + /** + * \brief Function produces an identity MatrixArray with the specified size + * \param size Size of the output identity matrix + * \param pages Number of copies of the identity matrix + * \return Returns an identity MatrixArray + */ + static MatrixArray IdentityMatrix(const size_t size, const size_t pages = 1); + /** + * \brief Function produces an identity MatrixArray with the same size + * as the input MatrixArray + * \param likeme Input matrix used to determine the size of the identity matrix + * \return Returns an identity MatrixArray + */ + static MatrixArray IdentityMatrix(const MatrixArray& likeme); + protected: // To simplify functions in MatrixArray that are using members from the template base class using ValArray::m_numRows; diff --git a/src/core/model/nstime.h b/src/core/model/nstime.h index 85cb00259c..f73c471907 100644 --- a/src/core/model/nstime.h +++ b/src/core/model/nstime.h @@ -840,13 +840,6 @@ typedef void (*Time)(Time oldValue, Time newValue); } // namespace TracedValueCallback -/** - * Force static initialization order of Time in each compilation unit. - * This is internal to the Time implementation. - * \relates Time - */ -static bool g_TimeStaticInit [[maybe_unused]] = Time::StaticInit(); - /** * Equality operator for Time. * \param [in] lhs The first value @@ -1414,9 +1407,9 @@ ATTRIBUTE_VALUE_DEFINE(Time); ATTRIBUTE_ACCESSOR_DEFINE(Time); /** - * \ingroup attribute_time - * Helper to make a Time checker with bounded range. - * Both limits are inclusive + * \ingroup attribute_Time + * Helper to make a Time checker with bounded range. + * Both limits are inclusive * * \param [in] min Minimum allowed value. * \param [in] max Maximum allowed value. @@ -1425,7 +1418,7 @@ ATTRIBUTE_ACCESSOR_DEFINE(Time); Ptr MakeTimeChecker(const Time min, const Time max); /** - * \ingroup attribute_time + * \ingroup attribute_Time * Helper to make an unbounded Time checker. * * \return The AttributeChecker @@ -1437,7 +1430,7 @@ MakeTimeChecker() } /** - * \ingroup attribute_time + * \ingroup attribute_Time * Helper to make a Time checker with a lower bound. * * \param [in] min Minimum allowed value. @@ -1490,6 +1483,27 @@ class TimeWithUnit */ TYPENAMEGET_DEFINE(Time); +/** + * \ingroup time + * + * \brief Helper class to force static initialization + * of Time in each compilation unit, ensuring it is + * initialized before usage. + * This is internal to the Time implementation. + * \relates Time + */ +class TimeInitializationHelper +{ + public: + /** Default constructor calls Time::StaticInit */ + TimeInitializationHelper() + { + Time::StaticInit(); + } +}; + +static TimeInitializationHelper g_timeInitHelper; ///< Instance of Time static initialization helper + } // namespace ns3 #endif /* TIME_H */ diff --git a/src/core/model/object-base.cc b/src/core/model/object-base.cc index 6a9b78df7b..4c2e9a0eb3 100644 --- a/src/core/model/object-base.cc +++ b/src/core/model/object-base.cc @@ -36,6 +36,13 @@ namespace ns3 { // Explicit instantiation declaration + +/** + * \ingroup callback + * Explicit instantiation for ObjectBase + * \return A wrapper Callback + * \sa ns3::MakeCallback + */ template Callback MakeCallback(ObjectBase* (*)()); template Callback::Callback(); template class CallbackImpl; @@ -319,6 +326,7 @@ ObjectBase::TraceConnectWithoutContext(std::string name, const CallbackBase& cb) Ptr accessor = tid.LookupTraceSourceByName(name); if (!accessor) { + NS_LOG_DEBUG("Cannot connect trace " << name << " on object of type " << tid.GetName()); return false; } bool ok = accessor->ConnectWithoutContext(this, cb); @@ -333,6 +341,7 @@ ObjectBase::TraceConnect(std::string name, std::string context, const CallbackBa Ptr accessor = tid.LookupTraceSourceByName(name); if (!accessor) { + NS_LOG_DEBUG("Cannot connect trace " << name << " on object of type " << tid.GetName()); return false; } bool ok = accessor->Connect(this, context, cb); diff --git a/src/core/model/object-factory.cc b/src/core/model/object-factory.cc index 7f13067d9a..1646fb4a92 100644 --- a/src/core/model/object-factory.cc +++ b/src/core/model/object-factory.cc @@ -93,6 +93,9 @@ Ptr ObjectFactory::Create() const { NS_LOG_FUNCTION(this); + NS_ASSERT_MSG( + m_tid.GetUid(), + "ObjectFactory::Create - can't use an ObjectFactory without setting a TypeId first."); Callback cb = m_tid.GetConstructor(); ObjectBase* base = cb(); auto derived = dynamic_cast(base); diff --git a/src/core/model/object-factory.h b/src/core/model/object-factory.h index 272f6ee067..109e1af8b6 100644 --- a/src/core/model/object-factory.h +++ b/src/core/model/object-factory.h @@ -205,7 +205,11 @@ Ptr ObjectFactory::Create() const { Ptr object = Create(); - return object->GetObject(); + auto obj = object->GetObject(); + NS_ASSERT_MSG(obj != nullptr, + "ObjectFactory::Create error: incompatible types (" + << T::GetTypeId().GetName() << " and " << object->GetInstanceTypeId() << ")"); + return obj; } template diff --git a/src/core/model/object-ptr-container.h b/src/core/model/object-ptr-container.h index 931ad9f320..b77cfc339f 100644 --- a/src/core/model/object-ptr-container.h +++ b/src/core/model/object-ptr-container.h @@ -31,6 +31,11 @@ * ns3::ObjectPtrContainerValue attribute value declarations and template implementations. */ +/** + * \ingroup attributes + * \defgroup attribute_ObjectPtrContainer ObjectPtrContainer Attribute + * AttributeValue implementation for ObjectPtrContainer + */ namespace ns3 { @@ -41,6 +46,12 @@ namespace ns3 * * This class it used to get attribute access to an array of * ns3::Object pointers. + * + * \see AttributeValue + * + * Call graph was not generated because of its size. + * \hidecallergraph + * \hidecallgraph */ class ObjectPtrContainerValue : public AttributeValue { @@ -146,6 +157,12 @@ template Ptr MakeObjectPtrContainerAccessor(INDEX (T::*getN)() const, Ptr (T::*get)(INDEX) const); +/** + * \ingroup attribute_ObjectPtrContainer + * + * AttributeChecker implementation for ObjectPtrContainerValue. + * \see AttributeChecker + */ class ObjectPtrContainerChecker : public AttributeChecker { public: @@ -156,22 +173,28 @@ class ObjectPtrContainerChecker : public AttributeChecker virtual TypeId GetItemTypeId() const = 0; }; +/** + * \ingroup attribute_ObjectPtrContainer + * \returns The AttributeChecker. + * \see AttributeChecker + */ template Ptr MakeObjectPtrContainerChecker(); } // namespace ns3 -/*************************************************************** - * The implementation of the above functions. - ***************************************************************/ +// +// The implementation of the above functions. +// namespace ns3 { namespace internal { - -/** ObjectPtrContainerChecker implementation class. */ +/** + * ObjectPtrContainerChecker implementation class. + */ template class ObjectPtrContainerChecker : public ns3::ObjectPtrContainerChecker { diff --git a/src/core/model/object.cc b/src/core/model/object.cc index 92b485d008..f97b2a1abe 100644 --- a/src/core/model/object.cc +++ b/src/core/model/object.cc @@ -59,16 +59,27 @@ bool Object::AggregateIterator::HasNext() const { NS_LOG_FUNCTION(this); - return m_current < m_object->m_aggregates->n; + return (m_current < m_object->m_aggregates->n) || + (m_uniAggrIter != m_object->m_unidirectionalAggregates.end()); } Ptr Object::AggregateIterator::Next() { NS_LOG_FUNCTION(this); - Object* object = m_object->m_aggregates->buffer[m_current]; - m_current++; - return object; + if (m_current < m_object->m_aggregates->n) + { + Object* object = m_object->m_aggregates->buffer[m_current]; + m_current++; + return object; + } + else if (m_uniAggrIter != m_object->m_unidirectionalAggregates.end()) + { + auto object = *m_uniAggrIter; + m_uniAggrIter++; + return object; + } + return nullptr; } Object::AggregateIterator::AggregateIterator(Ptr object) @@ -76,6 +87,7 @@ Object::AggregateIterator::AggregateIterator(Ptr object) m_current(0) { NS_LOG_FUNCTION(this << object); + m_uniAggrIter = object->m_unidirectionalAggregates.begin(); } TypeId @@ -127,6 +139,7 @@ Object::~Object() std::free(m_aggregates); } m_aggregates = nullptr; + m_unidirectionalAggregates.clear(); } Object::Object(const Object& o) @@ -153,6 +166,7 @@ Object::DoGetObject(TypeId tid) const NS_LOG_FUNCTION(this << tid); NS_ASSERT(CheckLoose()); + // First check if the object is in the normal aggregates. uint32_t n = m_aggregates->n; TypeId objectTid = Object::GetTypeId(); for (uint32_t i = 0; i < n; i++) @@ -181,6 +195,20 @@ Object::DoGetObject(TypeId tid) const return const_cast(current); } } + + // Next check if it's a unidirectional aggregate + for (auto& uniItem : m_unidirectionalAggregates) + { + TypeId cur = uniItem->GetInstanceTypeId(); + while (cur != tid && cur != objectTid) + { + cur = cur.GetParent(); + } + if (cur == tid) + { + return uniItem; + } + } return nullptr; } @@ -208,6 +236,17 @@ Object::Initialize() goto restart; } } + + // note: no need to restart because unidirectionally aggregated objects + // can not change the status of the actual object. + for (auto& uniItem : m_unidirectionalAggregates) + { + if (!uniItem->m_initialized) + { + uniItem->DoInitialize(); + uniItem->m_initialized = true; + } + } } bool @@ -241,6 +280,17 @@ Object::Dispose() goto restart; } } + + // note: no need to restart because unidirectionally aggregated objects + // can not change the status of the actual object. + for (auto& uniItem : m_unidirectionalAggregates) + { + if (!uniItem->m_disposed && uniItem->GetReferenceCount() == 1) + { + uniItem->DoDispose(); + uniItem->m_disposed = true; + } + } } void @@ -282,11 +332,13 @@ Object::AggregateObject(Ptr o) { aggregates->buffer[m_aggregates->n + i] = other->m_aggregates->buffer[i]; const TypeId typeId = other->m_aggregates->buffer[i]->GetInstanceTypeId(); + // note: DoGetObject scans also the unidirectional aggregates if (DoGetObject(typeId)) { NS_FATAL_ERROR("Object::AggregateObject(): " "Multiple aggregation of objects of type " - << other->GetInstanceTypeId() << " on objects of type " << typeId); + << other->GetInstanceTypeId() << " on objects of type " + << GetInstanceTypeId()); } UpdateSortedArray(aggregates, m_aggregates->n + i); } @@ -325,7 +377,47 @@ Object::AggregateObject(Ptr o) std::free(b); } -/** +void +Object::UnidirectionalAggregateObject(Ptr o) +{ + NS_LOG_FUNCTION(this << o); + NS_ASSERT(!m_disposed); + NS_ASSERT(!o->m_disposed); + NS_ASSERT(CheckLoose()); + NS_ASSERT(o->CheckLoose()); + + Object* other = PeekPointer(o); + + const TypeId typeId = other->GetInstanceTypeId(); + // note: DoGetObject scans also the unidirectional aggregates + if (DoGetObject(typeId)) + { + NS_FATAL_ERROR("Object::UnidirectionalAggregateObject(): " + "Multiple aggregation of objects of type " + << other->GetInstanceTypeId() << " on objects of type " + << GetInstanceTypeId()); + } + + m_unidirectionalAggregates.emplace_back(other); + + // Finally, call NotifyNewAggregate on all the objects aggregates by this object. + // We skip the aggregated Object and its aggregates because they are not + // mutually aggregated to the others. + // Unfortunately, we have to make a copy of the aggregated objects, because + // NotifyNewAggregate might change it... + + std::list aggregates; + for (uint32_t i = 0; i < m_aggregates->n; i++) + { + aggregates.emplace_back(m_aggregates->buffer[i]); + } + for (auto& item : aggregates) + { + item->NotifyNewAggregate(); + } +} + +/* * This function must be implemented in the stack that needs to notify * other stacks connected to the node of their presence in the node. */ diff --git a/src/core/model/object.h b/src/core/model/object.h index 09bf093573..b5f46a01c2 100644 --- a/src/core/model/object.h +++ b/src/core/model/object.h @@ -137,6 +137,8 @@ class Object : public SimpleRefCount AggregateIterator(Ptr object); Ptr m_object; //!< Parent Object. uint32_t m_current; //!< Current position in parent's aggregates. + /// Iterator to the unidirectional aggregates. + std::vector>::const_iterator m_uniAggrIter; }; /** Constructor. */ @@ -199,6 +201,44 @@ class Object : public SimpleRefCount */ void AggregateObject(Ptr other); + /** + * Aggregate an Object to another Object. + * + * \param [in] other The other Object pointer + * + * This method aggregates the an object to another Object: + * after this method returns, it becomes possible to call GetObject() + * on the aggregating Object to get the other, but not vice-versa. + * + * This method calls the virtual method NotifyNewAggregates() to + * notify all aggregated Objects that they have been aggregated + * together. + * + * This method is useful only if there is the need to aggregate an + * object to more than one object at the same time, and should be avoided + * if not strictly necessary. + * In particular, objects aggregated with this method should be destroyed + * only after making sure that the objects they are aggregated to are + * destroyed as well. However, the destruction of the aggregating objects + * will take care of the unidirectional aggregated objects gracefully. + * + * Beware that an object aggregated to another with this function + * behaves differently than other aggregates in the following ways. + * Suppose that Object B is aggregated unidirectionally: + * - It can be aggregated unidirectionally to more than one objects + * (e.g., A1 and A2). + * - It is not possible to call GetObject on B to find an aggregate of + * object A1 or A2. + * - When A1 or A2 are initialized, B is initialized, whichever happens first. + * - When A1 or A2 are destroyed, B is destroyed, whichever happens last. + * - If B is initialized, A1 and A2 are unaffected. + * - If B is forcefully destroyed, A1 and A2 are unaffected. + * + * + * \sa AggregateObject() + */ + void UnidirectionalAggregateObject(Ptr other); + /** * Get an iterator to the Objects aggregated to this one. * @@ -436,6 +476,17 @@ class Object : public SimpleRefCount * so the size of the array is indirectly a reference count. */ Aggregates* m_aggregates; + + /** + * An array of unidirectional aggregates, i.e., objects that are + * aggregated to the current object, but not vice-versa. + * + * This is useful (and suggested) only for Objects that should + * be aggregated to multiple other Objects, where the normal + * Aggregation would create an issue. + */ + std::vector> m_unidirectionalAggregates; + /** * The number of times the Object was accessed with a * call to GetObject(). diff --git a/src/core/model/pair.h b/src/core/model/pair.h index 460706a581..44c5952f2b 100644 --- a/src/core/model/pair.h +++ b/src/core/model/pair.h @@ -47,10 +47,19 @@ operator<<(std::ostream& os, const std::pair& p) return os; } -// Doxygen for this class is auto-generated by -// utils/print-introspected-doxygen.h +/** + * \ingroup attributes + * \defgroup attribute_Pair Pair Attribute + * AttributeValue implementation for Pair + */ -/** Hold objects of type std::pair. */ +/** + * \ingroup attribute_Pair + * AttributeValue implementation for Pair. + * Hold objects of type std::pair. + * + * \see AttributeValue + */ template class PairValue : public AttributeValue { @@ -64,14 +73,18 @@ class PairValue : public AttributeValue /** Type returned by Get or passed in Set. */ typedef typename std::pair result_type; - PairValue(); + PairValue() + : m_value(std::make_pair(Create(), Create())){}; /** * Construct this PairValue from a std::pair * * \param [in] value Value with which to construct. */ - PairValue(const result_type& value); // "import" constructor + PairValue(const result_type& value) + { + Set(value); + }; // "import" constructor // Inherited Ptr Copy() const override; @@ -86,16 +99,30 @@ class PairValue : public AttributeValue * \return stored value as std::pair. */ result_type Get() const; - /* Documented by print-introspected-doxygen.cc */ + /** + * Set the value. + * \param [in] value The value to adopt. + */ void Set(const result_type& value); + /** + * Access the Pair value as type \p T. + * \tparam T \explicit The type to cast to. + * \param [out] value The Pair value, as type \p T. + * \returns true. + */ template bool GetAccessor(T& value) const; private: - value_type m_value; + value_type m_value; //!< The stored Pair instance. }; +/** + * \ingroup attribute_Pair + * AttributeChecker implementation for PairValue. + * \see AttributeChecker + */ class PairChecker : public AttributeChecker { public: @@ -120,6 +147,8 @@ class PairChecker : public AttributeChecker }; /** + * \ingroup attribute_Pair + * * Make a PairChecker from a PairValue. * * This function returns a Pointer to a non-const instance to @@ -131,6 +160,8 @@ template Ptr MakePairChecker(const PairValue& value); /** + * \ingroup attribute_Pair + * * Make a PairChecker from abscissa and ordinate AttributeCheckers. * * This function returns a Pointer to a const instance since both @@ -145,6 +176,8 @@ Ptr MakePairChecker(Ptr firstche Ptr secondchecker); /** + * \ingroup attribute_Pair + * * Make a PairChecker without abscissa and ordinate AttributeCheckers. * * \return Pointer to PairChecker instance. @@ -152,6 +185,16 @@ Ptr MakePairChecker(Ptr firstche template Ptr MakePairChecker(); +/** + * \ingroup attribute_Pair + * + * Create an AttributeAccessor for std::pair<>. + * \tparam A \explicit The type of pair.first. + * \tparam B \explicit The type of pair.second. + * \tparam T1 \deduced The argument pair type. + * \param [in] a1 The std::pair to be accessed. + * \returns The AttributeAccessor. + */ template Ptr MakePairAccessor(T1 a1); @@ -171,6 +214,8 @@ namespace internal { /** + * \ingroup attribute_Pair + * * Internal checker class templated to each AttributeChecker * for each entry in the pair. */ @@ -272,18 +317,6 @@ MakePairChecker() return MakeSimpleAttributeChecker>(pairName, underlyingType); } -template -PairValue::PairValue() - : m_value(std::make_pair(Create(), Create())) -{ -} - -template -PairValue::PairValue(const typename PairValue::result_type& value) -{ - Set(value); -} - template Ptr PairValue::Copy() const @@ -374,14 +407,6 @@ PairValue::GetAccessor(T& value) const return true; } -/** - * Create an AttributeAccessor for std::pair<>. - * \tparam A \explicit The type of pair.first. - * \tparam B \explicit The type of pair.second. - * \tparam T1 \deduced The argument pair type. - * \param [in] a1 The std::pair to be accessed. - * \returns The AttributeAccessor. - */ template Ptr MakePairAccessor(T1 a1) diff --git a/src/core/model/pointer.cc b/src/core/model/pointer.cc index dbb232f909..3ed2227b0e 100644 --- a/src/core/model/pointer.cc +++ b/src/core/model/pointer.cc @@ -40,7 +40,7 @@ PointerValue::PointerValue() NS_LOG_FUNCTION(this); } -PointerValue::PointerValue(Ptr object) +PointerValue::PointerValue(const Ptr& object) : m_value(object) { NS_LOG_FUNCTION(object); diff --git a/src/core/model/pointer.h b/src/core/model/pointer.h index 228226defb..437198b794 100644 --- a/src/core/model/pointer.h +++ b/src/core/model/pointer.h @@ -31,8 +31,19 @@ namespace ns3 { -// Additional docs for class PointerValue: -/** Hold objects of type Ptr. */ +/** + * \ingroup attributes + * \defgroup attribute_Pointer Pointer Attribute + * AttributeValue implementation for Pointer. + * Hold objects of type Ptr. + */ + +/** + * \ingroup attribute_Pointer + * \class ns3::PointerValue "pointer.h" + * AttributeValue implementation for Pointer. Hold objects of type Ptr. + * \see AttributeValue + */ class PointerValue : public AttributeValue { public: @@ -43,7 +54,7 @@ class PointerValue : public AttributeValue * * \param [in] object The object to begin with. */ - PointerValue(Ptr object); + PointerValue(const Ptr& object); /** * Set the value from by reference an Object. @@ -74,14 +85,26 @@ class PointerValue : public AttributeValue template operator Ptr() const; - // Documentation generated by print-introspected-doxygen.cc + /** + * Set the value. + * \param [in] value The value to adopt. + */ template void Set(const Ptr& value); - /** \tparam T \explicit The type to cast to. */ + /** + * \returns The Pointer value. + * \tparam T \explicit The type to cast to. + */ template Ptr Get() const; + /** + * Access the Pointer value as type \p T. + * \tparam T \explicit The type to cast to. + * \param [out] value The Pointer value, as type \p T. + * \returns true. + */ template bool GetAccessor(Ptr& value) const; @@ -90,9 +113,14 @@ class PointerValue : public AttributeValue bool DeserializeFromString(std::string value, Ptr checker) override; private: - Ptr m_value; + Ptr m_value; //!< The stored Pointer instance. }; +/** + * \ingroup attribute_Pointer + * AttributeChecker implementation for PointerValue. + * \see AttributeChecker + */ class PointerChecker : public AttributeChecker { public: @@ -104,6 +132,7 @@ class PointerChecker : public AttributeChecker }; /** + * \ingroup attribute_Pointer * Create a PointerChecker for a type. * \tparam T \explicit The underlying type. * \returns The PointerChecker. @@ -123,7 +152,10 @@ namespace ns3 namespace internal { -/** PointerChecker implementation. */ +/** + * \ingroup attribute_Pointer + * PointerChecker implementation. + */ template class PointerChecker : public ns3::PointerChecker { @@ -226,6 +258,23 @@ PointerValue::GetAccessor(Ptr& v) const ATTRIBUTE_ACCESSOR_DEFINE(Pointer); +// Documentation of the functions defined by the macro. +// not documented by print-introspected-doxygen because +// Pointer has custom functions. + +/** + * \ingroup attribute_Pointer + * \fn ns3::Ptr ns3::MakePointerAccessor (T1 a1) + * \copydoc ns3::MakeAccessorHelper(T1) + * \see AttributeAccessor + */ +/** + * \ingroup attribute_Pointer + * \fn ns3::Ptr ns3::MakePointerAccessor (T1 a1, T2 a2) + * \copydoc ns3::MakeAccessorHelper(T1,T2) + * \see AttributeAccessor + */ + template Ptr MakePointerChecker() diff --git a/src/core/model/ptr.h b/src/core/model/ptr.h index 06a988b01b..7f0cf3039e 100644 --- a/src/core/model/ptr.h +++ b/src/core/model/ptr.h @@ -401,6 +401,9 @@ struct CallbackTraits> } }; +namespace internal +{ + // Duplicate of struct EventMemberImplObjTraits as defined in make-event.h // We repeat it here to declare a specialization on Ptr // without making this header dependent on make-event.h @@ -428,6 +431,8 @@ struct EventMemberImplObjTraits> } }; +} // namespace internal + } // namespace ns3 namespace ns3 diff --git a/src/core/model/scheduler.h b/src/core/model/scheduler.h index f69ba333b2..7635953efe 100644 --- a/src/core/model/scheduler.h +++ b/src/core/model/scheduler.h @@ -229,7 +229,7 @@ class Scheduler : public Object }; /** - * \ingroup Events + * \ingroup events * Compare (equal) two events by EventKey. * * \param [in] a The first event. @@ -243,7 +243,7 @@ operator==(const Scheduler::EventKey& a, const Scheduler::EventKey& b) } /** - * \ingroup Events + * \ingroup events * Compare (not equal) two events by EventKey. * * \param [in] a The first event. @@ -257,7 +257,7 @@ operator!=(const Scheduler::EventKey& a, const Scheduler::EventKey& b) } /** - * \ingroup Events + * \ingroup events * Compare (less than) two events by EventKey. * * Note the invariants which this function must provide: @@ -272,18 +272,7 @@ operator!=(const Scheduler::EventKey& a, const Scheduler::EventKey& b) inline bool operator<(const Scheduler::EventKey& a, const Scheduler::EventKey& b) { - if (a.m_ts < b.m_ts) - { - return true; - } - else if (a.m_ts == b.m_ts && a.m_uid < b.m_uid) - { - return true; - } - else - { - return false; - } + return (a.m_ts < b.m_ts || (a.m_ts == b.m_ts && a.m_uid < b.m_uid)); } /** @@ -296,18 +285,7 @@ operator<(const Scheduler::EventKey& a, const Scheduler::EventKey& b) inline bool operator>(const Scheduler::EventKey& a, const Scheduler::EventKey& b) { - if (a.m_ts > b.m_ts) - { - return true; - } - else if (a.m_ts == b.m_ts && a.m_uid > b.m_uid) - { - return true; - } - else - { - return false; - } + return (a.m_ts > b.m_ts || (a.m_ts == b.m_ts && a.m_uid > b.m_uid)); } /** diff --git a/src/core/model/shuffle.h b/src/core/model/shuffle.h new file mode 100644 index 0000000000..5b63f98d90 --- /dev/null +++ b/src/core/model/shuffle.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 Universita' degli Studi di Napoli Federico II + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Stefano Avallone + */ + +#ifndef SHUFFLE_H +#define SHUFFLE_H + +/** + * \file + * \ingroup randomvariable + * Function to shuffle elements in a given range. + */ + +#include "random-variable-stream.h" + +#include +#include + +namespace ns3 +{ + +/** + * Shuffle the elements in the range first to last. Given that the implementation + * of std::shuffle is not dictated by the standard + * [CppReference](https://en.cppreference.com/w/cpp/algorithm/random_shuffle), it is not guaranteed + * that std::shuffle returns the same permutation of the given range using different compilers/OSes. + * Therefore, this function provides a specific implementation of the shuffling algorithm reported + * in "The Art of Computer Programming" of Donald Knuth and on + * [Wikipedia](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm), + * which basically matches the implementation in libstdc++. + * + * The complexity of the implemented algorithm is linear with the distance between first + * and last. For containers that do not provide random access iterators (e.g., lists, sets) + * we can still achieve a linear complexity by copying the elements in a vector and shuffling the + * elements of the vector. + * + * \tparam RND_ACCESS_ITER \deduced the iterator type (must be a random access iterator) + * \param first an iterator pointing to the first element in the range to shuffle + * \param last an iterator pointing to past-the-last element in the range to shuffle + * \param rv pointer to a uniform random variable + */ +template +void +Shuffle(RND_ACCESS_ITER first, RND_ACCESS_ITER last, Ptr rv) +{ + if (auto dist = std::distance(first, last); dist > 1) + { + for (--last; first < last; ++first, --dist) + { + if (auto i = rv->GetInteger(0, dist - 1); i != 0) + { + std::iter_swap(first, std::next(first, i)); + } + } + } +} + +} // namespace ns3 + +#endif /* SHUFFLE_H */ diff --git a/src/core/model/simulation-singleton.h b/src/core/model/simulation-singleton.h index 9f18b79e6f..b4ea33c177 100644 --- a/src/core/model/simulation-singleton.h +++ b/src/core/model/simulation-singleton.h @@ -21,7 +21,7 @@ /** * \file - * \ingroup core + * \ingroup singleton * ns3::SimulationSingleton declaration and template implementation. */ @@ -29,7 +29,7 @@ namespace ns3 { /** - * \ingroup core + * \ingroup singleton * This singleton class template ensures that the type * for which we want a singleton has a lifetime bounded * by the simulation run lifetime. That it, the underlying diff --git a/src/core/model/simulator.h b/src/core/model/simulator.h index 1e31d605a1..326678304b 100644 --- a/src/core/model/simulator.h +++ b/src/core/model/simulator.h @@ -426,7 +426,7 @@ class Simulator * Note that it is not possible to test for the expiration of * events which were scheduled for the "destroy" time. Doing so * will result in a program error (crash). - * An event is said to "expire" when it starts being scheduled + * An event is said to "expire" when it starts being executed, * which means that if the code executed by the event calls * this function, it will get true. * diff --git a/src/core/model/singleton.h b/src/core/model/singleton.h index a50e604ec3..9ee0361f0e 100644 --- a/src/core/model/singleton.h +++ b/src/core/model/singleton.h @@ -21,7 +21,7 @@ /** * \file - * \ingroup access + * \ingroup singleton * ns3::Singleton declaration and template implementation. */ @@ -29,7 +29,14 @@ namespace ns3 { /** - * \ingroup access + * \ingroup core + * \defgroup singleton Singleton + * + * Template class implementing the Singleton design pattern. + */ + +/** + * \ingroup singleton * \brief A template singleton * * This template class can be used to implement the singleton pattern. diff --git a/src/core/model/system-path.cc b/src/core/model/system-path.cc index 6ab4927e92..0a16f5bd65 100644 --- a/src/core/model/system-path.cc +++ b/src/core/model/system-path.cc @@ -26,31 +26,11 @@ #include #include +#include #include #include #include -// Some compilers such as GCC < 8 (Ubuntu 18.04 -// ships with GCC 7) do not ship with the -// std::filesystem header, but with the -// std::experimental::filesystem header. -// Since Clang reuses these headers and the libstdc++ -// from GCC, we need to either use the experimental -// version or require a more up-to-date GCC. -// we use the "fs" namespace to prevent collisions -// with musl libc. -#ifdef __has_include -#if __has_include() -#include -namespace fs = std::filesystem; -#elif __has_include() -#include -namespace fs = std::experimental::filesystem; -#else -#error "No support for filesystem library" -#endif -#endif - #ifdef __APPLE__ #include #endif /* __APPLE__ */ @@ -107,13 +87,13 @@ ReadFilesNoThrow(std::string path) { NS_LOG_FUNCTION(path); std::list files; - if (!fs::exists(path)) + if (!std::filesystem::exists(path)) { return std::make_tuple(files, true); } - for (auto& it : fs::directory_iterator(path)) + for (auto& it : std::filesystem::directory_iterator(path)) { - if (!fs::is_directory(it.path())) + if (!std::filesystem::is_directory(it.path())) { files.push_back(it.path().filename().string()); } @@ -189,7 +169,7 @@ FindSelfDirectory() { // LPTSTR = char * DWORD size = 1024; - LPTSTR lpFilename = (LPTSTR)malloc(sizeof(TCHAR) * size); + auto lpFilename = (LPTSTR)malloc(sizeof(TCHAR) * size); DWORD status = GetModuleFileName(nullptr, lpFilename, size); while (status == size) { @@ -352,9 +332,9 @@ MakeDirectories(std::string path) NS_LOG_FUNCTION(path); std::error_code ec; - if (!fs::exists(path)) + if (!std::filesystem::exists(path)) { - fs::create_directories(path, ec); + std::filesystem::create_directories(path, ec); } if (ec.value()) diff --git a/src/core/model/test.cc b/src/core/model/test.cc index 1b319c9d45..af80631185 100644 --- a/src/core/model/test.cc +++ b/src/core/model/test.cc @@ -19,6 +19,7 @@ #include "abort.h" #include "assert.h" +#include "config.h" #include "des-metrics.h" #include "log.h" #include "singleton.h" @@ -238,7 +239,7 @@ class TestRunnerImpl : public Singleton */ std::list FilterTests(std::string testName, TestSuite::Type testType, - TestCase::TestDuration maximumTestDuration); + TestCase::Duration maximumTestDuration); /** Container type for the test. */ typedef std::vector TestSuiteVector; @@ -279,7 +280,7 @@ TestCase::TestCase(std::string name) m_runner(nullptr), m_result(nullptr), m_name(name), - m_duration(TestCase::QUICK) + m_duration(TestCase::Duration::QUICK) { NS_LOG_FUNCTION(this << name); } @@ -298,7 +299,7 @@ TestCase::~TestCase() } void -TestCase::AddTestCase(TestCase* testCase, TestCase::TestDuration duration) +TestCase::AddTestCase(TestCase* testCase, TestCase::Duration duration) { NS_LOG_FUNCTION(&testCase << duration); @@ -351,6 +352,7 @@ TestCase::Run(TestRunnerImpl* runner) NS_LOG_FUNCTION(this << runner); m_result = new Result(); m_runner = runner; + Config::Reset(); DoSetup(); m_result->clock.Start(); for (auto i = m_children.begin(); i != m_children.end(); ++i) @@ -366,6 +368,7 @@ TestCase::Run(TestRunnerImpl* runner) out: m_result->clock.End(); DoTeardown(); + Config::Reset(); m_runner = nullptr; } @@ -796,11 +799,11 @@ TestRunnerImpl::PrintTestNameList(std::list::const_iterator begin, NS_LOG_FUNCTION(this << &begin << &end << printTestType); std::map label; - label[TestSuite::ALL] = "all "; - label[TestSuite::UNIT] = "unit "; - label[TestSuite::SYSTEM] = "system "; - label[TestSuite::EXAMPLE] = "example "; - label[TestSuite::PERFORMANCE] = "performance "; + label[TestSuite::Type::ALL] = "all "; + label[TestSuite::Type::UNIT] = "unit "; + label[TestSuite::Type::SYSTEM] = "system "; + label[TestSuite::Type::EXAMPLE] = "example "; + label[TestSuite::Type::PERFORMANCE] = "performance "; for (auto i = begin; i != end; ++i) { @@ -833,14 +836,14 @@ TestRunnerImpl::PrintTestTypeList() const std::list TestRunnerImpl::FilterTests(std::string testName, TestSuite::Type testType, - TestCase::TestDuration maximumTestDuration) + TestCase::Duration maximumTestDuration) { NS_LOG_FUNCTION(this << testName << testType); std::list tests; for (uint32_t i = 0; i < m_suites.size(); ++i) { TestSuite* test = m_suites[i]; - if (testType != TestSuite::ALL && test->GetTestType() != testType) + if (testType != TestSuite::Type::ALL && test->GetTestType() != testType) { // skip test continue; @@ -894,7 +897,7 @@ TestRunnerImpl::Run(int argc, char* argv[]) bool printTestTypeList = false; bool printTestNameList = false; bool printTestTypeAndName = false; - TestCase::TestDuration maximumTestDuration = TestCase::QUICK; + TestCase::Duration maximumTestDuration = TestCase::Duration::QUICK; char* progname = argv[0]; char** argi = argv; @@ -924,11 +927,6 @@ TestRunnerImpl::Run(int argc, char* argv[]) { m_updateData = true; } - else if (arg == "--help") - { - PrintHelp(progname); - return 0; - } else if (arg == "--print-test-name-list" || arg == "--list") { printTestNameList = true; @@ -953,11 +951,8 @@ TestRunnerImpl::Run(int argc, char* argv[]) { testTypeString = arg.substr(arg.find_first_of('=') + 1); } - else if (arg.find("--test-name=") != std::string::npos) - { - testName = arg.substr(arg.find_first_of('=') + 1); - } - else if (arg.find("--suite=") != std::string::npos) + else if (arg.find("--test-name=") != std::string::npos || + arg.find("--suite=") != std::string::npos) { testName = arg.substr(arg.find_first_of('=') + 1); } @@ -976,15 +971,15 @@ TestRunnerImpl::Run(int argc, char* argv[]) // Set the maximum test length allowed. if (fullness == "QUICK") { - maximumTestDuration = TestCase::QUICK; + maximumTestDuration = TestCase::Duration::QUICK; } else if (fullness == "EXTENSIVE") { - maximumTestDuration = TestCase::EXTENSIVE; + maximumTestDuration = TestCase::Duration::EXTENSIVE; } else if (fullness == "TAKES_FOREVER") { - maximumTestDuration = TestCase::TAKES_FOREVER; + maximumTestDuration = TestCase::Duration::TAKES_FOREVER; } else { @@ -995,36 +990,32 @@ TestRunnerImpl::Run(int argc, char* argv[]) } else { - // un-recognized command-line argument + // Print the help if arg == "--help" or arg is an un-recognized command-line argument PrintHelp(progname); return 0; } argi++; } TestSuite::Type testType; - if (testTypeString.empty()) + if (testTypeString.empty() || testTypeString == "core") { - testType = TestSuite::ALL; - } - else if (testTypeString == "core") - { - testType = TestSuite::ALL; + testType = TestSuite::Type::ALL; } else if (testTypeString == "example") { - testType = TestSuite::EXAMPLE; + testType = TestSuite::Type::EXAMPLE; } else if (testTypeString == "unit") { - testType = TestSuite::UNIT; + testType = TestSuite::Type::UNIT; } else if (testTypeString == "system") { - testType = TestSuite::SYSTEM; + testType = TestSuite::Type::SYSTEM; } else if (testTypeString == "performance") { - testType = TestSuite::PERFORMANCE; + testType = TestSuite::Type::PERFORMANCE; } else { @@ -1144,4 +1135,38 @@ TestRunner::Run(int argc, char* argv[]) return TestRunnerImpl::Get()->Run(argc, argv); } +std::ostream& +operator<<(std::ostream& os, TestSuite::Type type) +{ + switch (type) + { + case TestSuite::Type::ALL: + return os << "ALL"; + case TestSuite::Type::UNIT: + return os << "UNIT"; + case TestSuite::Type::SYSTEM: + return os << "SYSTEM"; + case TestSuite::Type::EXAMPLE: + return os << "EXAMPLE"; + case TestSuite::Type::PERFORMANCE: + return os << "PERFORMANCE"; + }; + return os << "UNKNOWN(" << static_cast(type) << ")"; +} + +std::ostream& +operator<<(std::ostream& os, TestCase::Duration duration) +{ + switch (duration) + { + case TestCase::Duration::QUICK: + return os << "QUICK"; + case TestCase::Duration::EXTENSIVE: + return os << "EXTENSIVE"; + case TestCase::Duration::TAKES_FOREVER: + return os << "TAKES_FOREVER"; + }; + return os << "UNKNOWN(" << static_cast(duration) << ")"; +} + } // namespace ns3 diff --git a/src/core/model/test.h b/src/core/model/test.h index 4e07b8b232..243102b981 100644 --- a/src/core/model/test.h +++ b/src/core/model/test.h @@ -18,6 +18,7 @@ #ifndef NS3_TEST_H #define NS3_TEST_H +#include "deprecated.h" #include "system-wall-clock-ms.h" #include @@ -1060,13 +1061,24 @@ class TestCase { public: /** \brief How long the test takes to execute. */ - enum TestDuration + enum class Duration { QUICK = 1, //!< Fast test. EXTENSIVE = 2, //!< Medium length test. TAKES_FOREVER = 3 //!< Very long running test. }; + NS_DEPRECATED_3_42("Use Duration::QUICK instead") + static constexpr auto QUICK = Duration::QUICK; //!< @deprecated See Duration::QUICK. + NS_DEPRECATED_3_42("Use Duration::EXTENSIVE instead") + static constexpr auto EXTENSIVE = Duration::EXTENSIVE; //!< @deprecated See Duration::EXTENSIVE. + NS_DEPRECATED_3_42("Use Duration::TAKES_FOREVER instead") + static constexpr auto TAKES_FOREVER = + Duration::TAKES_FOREVER; //!< @deprecated See Duration::TAKES_FOREVER. + + using TestDuration NS_DEPRECATED_3_42("Use Duration instead") = + Duration; //!< @deprecated See Duration. + /** * Destructor */ @@ -1096,7 +1108,7 @@ class TestCase * \param [in] duration Amount of time this test takes to execute * (defaults to QUICK). */ - void AddTestCase(TestCase* testCase, TestDuration duration = QUICK); + void AddTestCase(TestCase* testCase, Duration duration = Duration::QUICK); /** * \brief Set the data directory where reference trace files can be @@ -1222,7 +1234,12 @@ class TestCase // methods called by TestRunnerImpl /** - * \brief Actually run this TestCase + * \brief Executes DoSetup(), DoRun(), and DoTeardown() for the TestCase + * + * Config::Reset() is called at both the beginning and end of this method + * so that any changes to attribute default values (Config::SetDefault(...)) + * or global values (e.g., RngRun) that are made within the test case's + * DoRun() method do not propagate beyond the scope of running the TestCase. * * \param [in] runner The test runner implementation. */ @@ -1242,7 +1259,7 @@ class TestCase TestRunnerImpl* m_runner; //!< Pointer to the TestRunner Result* m_result; //!< Results data std::string m_name; //!< TestCase name - TestDuration m_duration; //!< TestCase duration + Duration m_duration; //!< TestCase duration }; /** @@ -1259,7 +1276,7 @@ class TestSuite : public TestCase * \enum Type * \brief Type of test. */ - enum Type + enum class Type { ALL = 0, //!< UNIT, //!< This test suite implements a Unit Test @@ -1268,13 +1285,24 @@ class TestSuite : public TestCase PERFORMANCE //!< This test suite implements a Performance Test }; + NS_DEPRECATED_3_42("Use Type::ALL instead") + static constexpr auto ALL = Type::ALL; //!< @deprecated See Type::ALL. + NS_DEPRECATED_3_42("Use Type::UNIT instead") + static constexpr auto UNIT = Type::UNIT; //!< @deprecated See Type::UNIT. + NS_DEPRECATED_3_42("Use Type::SYSTEM instead") + static constexpr auto SYSTEM = Type::SYSTEM; //!< @deprecated See Type::SYSTEM. + NS_DEPRECATED_3_42("Use Type::EXAMPLE instead") + static constexpr auto EXAMPLE = Type::EXAMPLE; //!< @deprecated See Type::EXAMPLE. + NS_DEPRECATED_3_42("Use Type::PERFORMANCE instead") + static constexpr auto PERFORMANCE = Type::PERFORMANCE; //!< @deprecated See Type::PERFORMANCE. + /** * \brief Construct a new test suite. * * \param [in] name The name of the test suite. * \param [in] type The TestType of the test suite (defaults to UNIT test). */ - TestSuite(std::string name, Type type = UNIT); + TestSuite(std::string name, Type type = Type::UNIT); /** * \brief get the kind of test this test suite implements @@ -1357,6 +1385,38 @@ class TestVectors */ T Get(std::size_t i) const; + /** + * \return The underlying data structure begin iterator + */ + typename std::vector::iterator begin() + { + return m_vectors.begin(); + } + + /** + * \return The underlying data structure end iterator + */ + typename std::vector::iterator end() + { + return m_vectors.end(); + } + + /** + * \return The underlying data structure const begin iterator + */ + typename std::vector::const_iterator begin() const + { + return m_vectors.begin(); + } + + /** + * \return The underlying data structure const end iterator + */ + typename std::vector::const_iterator end() const + { + return m_vectors.end(); + } + private: typedef std::vector TestVector; //!< Container type TestVector m_vectors; //!< The list of test vectors @@ -1404,6 +1464,22 @@ TestVectors::Get(std::size_t i) const return m_vectors[i]; } +/** + * @brief Stream insertion operator. + * @param [in] os The reference to the output stream. + * @param [in] type The TestSuite::Type. + * @return The reference to the output stream. + */ +std::ostream& operator<<(std::ostream& os, TestSuite::Type type); + +/** + * @brief Stream insertion operator. + * @param [in] os The reference to the output stream. + * @param [in] duration The TestCase::Duration. + * @return The reference to the output stream. + */ +std::ostream& operator<<(std::ostream& os, TestCase::Duration duration); + } // namespace ns3 #endif /* NS3_TEST_H */ diff --git a/src/core/model/timer-impl.h b/src/core/model/timer-impl.h index 88996f2270..746ef3b74d 100644 --- a/src/core/model/timer-impl.h +++ b/src/core/model/timer-impl.h @@ -21,9 +21,9 @@ #define TIMER_IMPL_H #include "fatal-error.h" -#include "int-to-type.h" #include "simulator.h" -#include "type-traits.h" + +#include /** * \file @@ -35,6 +35,9 @@ namespace ns3 { +namespace internal +{ + /** * \ingroup timer * The timer implementation underlying Timer and Watchdog. @@ -49,75 +52,12 @@ class TimerImpl /** * Set the arguments to be used when invoking the expire function. + * + * \tparam Args \deduced Type template parameter pack + * \param [in] args The arguments to pass to the invoked method */ - /**@{*/ - /** - * \tparam T1 \deduced Type of the first argument. - * \param [in] a1 The first argument - */ - template - void SetArgs(T1 a1); - /** - * \tparam T1 \deduced Type of the first argument. - * \tparam T2 \deduced Type of the second argument. - * \param [in] a1 the first argument - * \param [in] a2 the second argument - */ - template - void SetArgs(T1 a1, T2 a2); - /** - * \tparam T1 \deduced Type of the first argument. - * \tparam T2 \deduced Type of the second argument. - * \tparam T3 \deduced Type of the third argument. - * \param [in] a1 the first argument - * \param [in] a2 the second argument - * \param [in] a3 the third argument - */ - template - void SetArgs(T1 a1, T2 a2, T3 a3); - /** - * \tparam T1 \deduced Type of the first argument. - * \tparam T2 \deduced Type of the second argument. - * \tparam T3 \deduced Type of the third argument. - * \tparam T4 \deduced Type of the fourth argument. - * \param [in] a1 the first argument - * \param [in] a2 the second argument - * \param [in] a3 the third argument - * \param [in] a4 the fourth argument - */ - template - void SetArgs(T1 a1, T2 a2, T3 a3, T4 a4); - /** - * \tparam T1 \deduced Type of the first argument. - * \tparam T2 \deduced Type of the second argument. - * \tparam T3 \deduced Type of the third argument. - * \tparam T4 \deduced Type of the fourth argument. - * \tparam T5 \deduced Type of the fifth argument. - * \param [in] a1 the first argument - * \param [in] a2 the second argument - * \param [in] a3 the third argument - * \param [in] a4 the fourth argument - * \param [in] a5 the fifth argument - */ - template - void SetArgs(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); - /** - * \tparam T1 \deduced Type of the first argument. - * \tparam T2 \deduced Type of the second argument. - * \tparam T3 \deduced Type of the third argument. - * \tparam T4 \deduced Type of the fourth argument. - * \tparam T5 \deduced Type of the fifth argument. - * \tparam T6 \deduced Type of the sixth argument. - * \param [in] a1 the first argument - * \param [in] a2 the second argument - * \param [in] a3 the third argument - * \param [in] a4 the fourth argument - * \param [in] a5 the fifth argument - * \param [in] a6 the sixth argument - */ - template - void SetArgs(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6); - /**@}*/ + template + void SetArgs(Args... args); /** * Schedule the callback for a future time. @@ -130,946 +70,114 @@ class TimerImpl virtual void Invoke() = 0; }; -} // namespace ns3 - /******************************************************************** * Implementation of TimerImpl implementation functions. ********************************************************************/ -namespace ns3 -{ - /** * \ingroup timer * \defgroup timerimpl TimerImpl Implementation * @{ */ - -/** TimerImpl specialization class for varying numbers of arguments. */ -template -struct TimerImplOne : public TimerImpl -{ - /** - * Bind the arguments to be used when the callback function is invoked. - * - * \param [in] a1 The first argument. - */ - virtual void SetArguments(T1 a1) = 0; -}; - -/** TimerImpl specialization class for varying numbers of arguments. */ -template -struct TimerImplTwo : public TimerImpl -{ - /** - * Bind the arguments to be used when the callback function is invoked. - * - * \param [in] a1 The first argument. - * \param [in] a2 The second argument. - */ - virtual void SetArguments(T1 a1, T2 a2) = 0; -}; - -/** TimerImpl specialization class for varying numbers of arguments. */ -template -struct TimerImplThree : public TimerImpl -{ - /** - * Bind the arguments to be used when the callback function is invoked. - * - * \param [in] a1 The first argument. - * \param [in] a2 The second argument. - * \param [in] a3 The third argument. - */ - virtual void SetArguments(T1 a1, T2 a2, T3 a3) = 0; -}; - -/** TimerImpl specialization class for varying numbers of arguments. */ -template -struct TimerImplFour : public TimerImpl -{ - /** - * Bind the arguments to be used when the callback function is invoked. - * - * \param [in] a1 The first argument. - * \param [in] a2 The second argument. - * \param [in] a3 The third argument. - * \param [in] a4 The fourth argument. - */ - virtual void SetArguments(T1 a1, T2 a2, T3 a3, T4 a4) = 0; -}; - /** TimerImpl specialization class for varying numbers of arguments. */ -template -struct TimerImplFive : public TimerImpl +template +struct TimerImplX : public TimerImpl { /** * Bind the arguments to be used when the callback function is invoked. * - * \param [in] a1 The first argument. - * \param [in] a2 The second argument. - * \param [in] a3 The third argument. - * \param [in] a4 The fourth argument. - * \param [in] a5 The fifth argument. + * \param [in] args The arguments to pass to the invoked method. */ - virtual void SetArguments(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) = 0; -}; - -/** TimerImpl specialization class for varying numbers of arguments. */ -template -struct TimerImplSix : public TimerImpl -{ - /** - * Bind the arguments to be used when the callback function is invoked. - * - * \param [in] a1 The first argument. - * \param [in] a2 The second argument. - * \param [in] a3 The third argument. - * \param [in] a4 The fourth argument. - * \param [in] a5 The fifth argument. - * \param [in] a6 The sixth argument. - */ - virtual void SetArguments(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) = 0; -}; - -/** Type and reference traits for TimerImpl arguments. */ -template -struct TimerTraits -{ - /** Storage type for an argument. */ - typedef typename TypeTraits::ReferencedType>::NonConstType StoredType; - /** Parameter type for an argument. */ - typedef const StoredType& ParameterType; + virtual void SetArguments(Args... args) = 0; }; /** * Make a TimerImpl from a function pointer taking varying numbers of arguments. * - * \tparam FN \deduced Function signature type of the callback function. - * \param [in] fn The function pointer to invoke when the timer expires. + * \tparam U \deduced Return type of the callback function. + * \tparam Ts \deduced Argument types of the callback function. * \returns The TimerImpl. */ -template -TimerImpl* -MakeTimerImpl(FN fn) -{ - NS_ASSERT(TypeTraits::IsFunctionPointer); - return MakeTimerImpl(IntToType::FunctionPointerTraits::nArgs>(), fn); -} - -/** - * Make a TimerImpl from a function pointer taking zero arguments. - * \copydetails MakeTimerImpl(FN) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<0>, FN fn) -{ - struct FnTimerImplZero : public TimerImpl - { - FnTimerImplZero(FN fn) - : m_fn(fn) - { - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_fn); - } - - void Invoke() override - { - m_fn(); - } - - FN m_fn; - }* function = new FnTimerImplZero(fn); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking one argument. - * \copydetails MakeTimerImpl(FN) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<1>, FN fn) -{ - typedef typename TypeTraits::FunctionPointerTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - - struct FnTimerImplOne : public TimerImplOne - { - FnTimerImplOne(FN fn) - : m_fn(fn) - { - } - - void SetArguments(T1Parameter a1) override - { - m_a1 = a1; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_fn, m_a1); - } - - void Invoke() override - { - m_fn(m_a1); - } - - FN m_fn; - T1Stored m_a1; - }* function = new FnTimerImplOne(fn); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking two arguments. - * \copydetails MakeTimerImpl(FN) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<2>, FN fn) -{ - typedef typename TypeTraits::FunctionPointerTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - - struct FnTimerImplTwo : public TimerImplTwo - { - FnTimerImplTwo(FN fn) - : m_fn(fn) - { - } - - void SetArguments(T1Parameter a1, T2Parameter a2) override - { - m_a1 = a1; - m_a2 = a2; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_fn, m_a1, m_a2); - } - - void Invoke() override - { - m_fn(m_a1, m_a2); - } - - FN m_fn; - T1Stored m_a1; - T2Stored m_a2; - }* function = new FnTimerImplTwo(fn); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking three arguments. - * \copydetails MakeTimerImpl(FN) - */ -template +template TimerImpl* -MakeTimerImpl(IntToType<3>, FN fn) +MakeTimerImpl(U(fn)(Ts...)) { - typedef typename TypeTraits::FunctionPointerTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - - struct FnTimerImplThree : public TimerImplThree + struct FnTimerImpl : public TimerImplX&...> { - FnTimerImplThree(FN fn) + FnTimerImpl(void (*fn)(Ts...)) : m_fn(fn) { } - void SetArguments(T1Parameter a1, T2Parameter a2, T3Parameter a3) override + void SetArguments(const std::remove_cvref_t&... args) override { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; + m_arguments = std::tuple(args...); } EventId Schedule(const Time& delay) override { - return Simulator::Schedule(delay, m_fn, m_a1, m_a2, m_a3); + return std::apply( + [&, this](Ts... args) { return Simulator::Schedule(delay, m_fn, args...); }, + m_arguments); } void Invoke() override { - m_fn(m_a1, m_a2, m_a3); - } - - FN m_fn; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - }* function = new FnTimerImplThree(fn); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking four arguments. - * \copydetails MakeTimerImpl(FN) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<4>, FN fn) -{ - typedef typename TypeTraits::FunctionPointerTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg4Type T4; - typedef typename TimerTraits::ParameterType T4Parameter; - typedef typename TimerTraits::StoredType T4Stored; - - struct FnTimerImplFour - : public TimerImplFour - { - FnTimerImplFour(FN fn) - : m_fn(fn) - { - } - - void SetArguments(T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4) override - { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; - m_a4 = a4; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_fn, m_a1, m_a2, m_a3, m_a4); - } - - void Invoke() override - { - m_fn(m_a1, m_a2, m_a3, m_a4); - } - - FN m_fn; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - T4Stored m_a4; - }* function = new FnTimerImplFour(fn); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking five arguments. - * \copydetails MakeTimerImpl(FN) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<5>, FN fn) -{ - typedef typename TypeTraits::FunctionPointerTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg4Type T4; - typedef typename TimerTraits::ParameterType T4Parameter; - typedef typename TimerTraits::StoredType T4Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg5Type T5; - typedef typename TimerTraits::ParameterType T5Parameter; - typedef typename TimerTraits::StoredType T5Stored; - - struct FnTimerImplFive - : public TimerImplFive - { - FnTimerImplFive(FN fn) - : m_fn(fn) - { - } - - void SetArguments(T1Parameter a1, - T2Parameter a2, - T3Parameter a3, - T4Parameter a4, - T5Parameter a5) override - { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; - m_a4 = a4; - m_a5 = a5; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_fn, m_a1, m_a2, m_a3, m_a4, m_a5); - } - - void Invoke() override - { - m_fn(m_a1, m_a2, m_a3, m_a4, m_a5); - } - - FN m_fn; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - T4Stored m_a4; - T5Stored m_a5; - }* function = new FnTimerImplFive(fn); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking six arguments. - * \copydetails MakeTimerImpl(FN) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<6>, FN fn) -{ - typedef typename TypeTraits::FunctionPointerTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg4Type T4; - typedef typename TimerTraits::ParameterType T4Parameter; - typedef typename TimerTraits::StoredType T4Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg5Type T5; - typedef typename TimerTraits::ParameterType T5Parameter; - typedef typename TimerTraits::StoredType T5Stored; - typedef typename TypeTraits::FunctionPointerTraits::Arg6Type T6; - typedef typename TimerTraits::ParameterType T6Parameter; - typedef typename TimerTraits::StoredType T6Stored; - - struct FnTimerImplSix : public TimerImplSix - { - FnTimerImplSix(FN fn) - : m_fn(fn) - { - } - - virtual void SetArguments(T1Parameter a1, - T2Parameter a2, - T3Parameter a3, - T4Parameter a4, - T5Parameter a5, - T6Parameter a6) - { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; - m_a4 = a4; - m_a5 = a5; - m_a6 = a6; - } - - virtual EventId Schedule(const Time& delay) - { - return Simulator::Schedule(delay, m_fn, m_a1, m_a2, m_a3, m_a4, m_a5, m_a6); - } - - virtual void Invoke() - { - m_fn(m_a1, m_a2, m_a3, m_a4, m_a5, m_a6); + std::apply([this](Ts... args) { (m_fn)(args...); }, m_arguments); } - FN m_fn; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - T4Stored m_a4; - T5Stored m_a5; - T6Stored m_a6; - }* function = new FnTimerImplSix(fn); + decltype(fn) m_fn; + std::tuple...> m_arguments; + }* function = new FnTimerImpl(fn); return function; } -/** - * Helper for the MakeTimerImpl functions which take a class method. - * - * This helper converts a pointer to a reference. - * - * This is the generic template declaration (with empty body). - * - * \tparam T \explicit The object type. - */ -template -struct TimerImplMemberTraits; - -/** - * Helper for the MakeTimerImpl functions which take a class method. - * - * This helper converts a pointer to a reference. - * - * This is the specialization for pointer to \c T. - * - * \tparam T \explicit The object type. - */ -template -struct TimerImplMemberTraits -{ - /** - * Convert a pointer type to a reference. - * - * \param [in] p The pointer. - * \returns A reference to the object pointed to by \c p. - */ - static T& GetReference(T* p) - { - return *p; - } -}; - /** * Make a TimerImpl from a class method pointer taking * a varying number of arguments. * - * \tparam MEM_PTR \deduced Class method function signature type. * \tparam OBJ_PTR \deduced Class type. + * \tparam U \deduced Class method function return type. + * \tparam V \deduced Class method function class type. + * \tparam Ts \deduced Class method function argument types. * \param [in] memPtr Class method to invoke when the timer expires. * \param [in] objPtr Object instance pointer. * \returns The TimerImpl. */ -template -TimerImpl* -MakeTimerImpl(MEM_PTR memPtr, OBJ_PTR objPtr) -{ - NS_ASSERT(TypeTraits::IsPointerToMember); - return MakeTimerImpl(IntToType::PointerToMemberTraits::nArgs>(), - memPtr, - objPtr); -} - -/** - * Make a TimerImpl from a function pointer taking zero arguments. - * \copydetails MakeTimerImpl(MEM_PTR,OBJ_PTR) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<0>, MEM_PTR memPtr, OBJ_PTR objPtr) -{ - struct MemFnTimerImplZero : public TimerImpl - { - MemFnTimerImplZero(MEM_PTR memPtr, OBJ_PTR objPtr) - : m_memPtr(memPtr), - m_objPtr(objPtr) - { - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_memPtr, m_objPtr); - } - - void Invoke() override - { - (TimerImplMemberTraits::GetReference(m_objPtr).*m_memPtr)(); - } - - MEM_PTR m_memPtr; - OBJ_PTR m_objPtr; - }* function = new MemFnTimerImplZero(memPtr, objPtr); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking one argument. - * \copydetails MakeTimerImpl(MEM_PTR,OBJ_PTR) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<1>, MEM_PTR memPtr, OBJ_PTR objPtr) -{ - typedef typename TypeTraits::PointerToMemberTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - - struct MemFnTimerImplOne : public TimerImplOne - { - MemFnTimerImplOne(MEM_PTR memPtr, OBJ_PTR objPtr) - : m_memPtr(memPtr), - m_objPtr(objPtr) - { - } - - void SetArguments(T1Parameter a1) override - { - m_a1 = a1; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_memPtr, m_objPtr, m_a1); - } - - void Invoke() override - { - (TimerImplMemberTraits::GetReference(m_objPtr).*m_memPtr)(m_a1); - } - - MEM_PTR m_memPtr; - OBJ_PTR m_objPtr; - T1Stored m_a1; - }* function = new MemFnTimerImplOne(memPtr, objPtr); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking two arguments. - * \copydetails MakeTimerImpl(MEM_PTR,OBJ_PTR) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<2>, MEM_PTR memPtr, OBJ_PTR objPtr) -{ - typedef typename TypeTraits::PointerToMemberTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - - struct MemFnTimerImplTwo : public TimerImplTwo - { - MemFnTimerImplTwo(MEM_PTR memPtr, OBJ_PTR objPtr) - : m_memPtr(memPtr), - m_objPtr(objPtr) - { - } - - void SetArguments(T1Parameter a1, T2Parameter a2) override - { - m_a1 = a1; - m_a2 = a2; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_memPtr, m_objPtr, m_a1, m_a2); - } - - void Invoke() override - { - (TimerImplMemberTraits::GetReference(m_objPtr).*m_memPtr)(m_a1, m_a2); - } - - MEM_PTR m_memPtr; - OBJ_PTR m_objPtr; - T1Stored m_a1; - T2Stored m_a2; - }* function = new MemFnTimerImplTwo(memPtr, objPtr); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking three arguments. - * \copydetails MakeTimerImpl(MEM_PTR,OBJ_PTR) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<3>, MEM_PTR memPtr, OBJ_PTR objPtr) -{ - typedef typename TypeTraits::PointerToMemberTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - - struct MemFnTimerImplThree : public TimerImplThree - { - MemFnTimerImplThree(MEM_PTR memPtr, OBJ_PTR objPtr) - : m_memPtr(memPtr), - m_objPtr(objPtr) - { - } - - void SetArguments(T1Parameter a1, T2Parameter a2, T3Parameter a3) override - { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3); - } - - void Invoke() override - { - (TimerImplMemberTraits::GetReference(m_objPtr).*m_memPtr)(m_a1, m_a2, m_a3); - } - - MEM_PTR m_memPtr; - OBJ_PTR m_objPtr; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - }* function = new MemFnTimerImplThree(memPtr, objPtr); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking four arguments. - * \copydetails MakeTimerImpl(MEM_PTR,OBJ_PTR) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<4>, MEM_PTR memPtr, OBJ_PTR objPtr) -{ - typedef typename TypeTraits::PointerToMemberTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg4Type T4; - typedef typename TimerTraits::ParameterType T4Parameter; - typedef typename TimerTraits::StoredType T4Stored; - - struct MemFnTimerImplFour - : public TimerImplFour - { - MemFnTimerImplFour(MEM_PTR memPtr, OBJ_PTR objPtr) - : m_memPtr(memPtr), - m_objPtr(objPtr) - { - } - - void SetArguments(T1Parameter a1, T2Parameter a2, T3Parameter a3, T4Parameter a4) override - { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; - m_a4 = a4; - } - - EventId Schedule(const Time& delay) override - { - return Simulator::Schedule(delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4); - } - - void Invoke() override - { - (TimerImplMemberTraits::GetReference(m_objPtr).* - m_memPtr)(m_a1, m_a2, m_a3, m_a4); - } - - MEM_PTR m_memPtr; - OBJ_PTR m_objPtr; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - T4Stored m_a4; - }* function = new MemFnTimerImplFour(memPtr, objPtr); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking five arguments. - * \copydetails MakeTimerImpl(MEM_PTR,OBJ_PTR) - */ -template +template TimerImpl* -MakeTimerImpl(IntToType<5>, MEM_PTR memPtr, OBJ_PTR objPtr) +MakeTimerImpl(U (V::*memPtr)(Ts...), OBJ_PTR objPtr) { - typedef typename TypeTraits::PointerToMemberTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg4Type T4; - typedef typename TimerTraits::ParameterType T4Parameter; - typedef typename TimerTraits::StoredType T4Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg5Type T5; - typedef typename TimerTraits::ParameterType T5Parameter; - typedef typename TimerTraits::StoredType T5Stored; - - struct MemFnTimerImplFive - : public TimerImplFive + struct MemFnTimerImpl : public TimerImplX&...> { - MemFnTimerImplFive(MEM_PTR memPtr, OBJ_PTR objPtr) - : m_memPtr(memPtr), - m_objPtr(objPtr) + MemFnTimerImpl(decltype(memPtr) memPtr, OBJ_PTR objPtr) + : m_memPtr(std::bind_front(memPtr, objPtr)) { } - void SetArguments(T1Parameter a1, - T2Parameter a2, - T3Parameter a3, - T4Parameter a4, - T5Parameter a5) override + void SetArguments(const std::remove_cvref_t&... args) override { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; - m_a4 = a4; - m_a5 = a5; + m_arguments = std::tuple(args...); } EventId Schedule(const Time& delay) override { - return Simulator::Schedule(delay, m_memPtr, m_objPtr, m_a1, m_a2, m_a3, m_a4, m_a5); + return std::apply( + [&, this](Ts... args) { + return Simulator::Schedule(delay, std::bind(m_memPtr, args...)); + }, + m_arguments); } void Invoke() override { - (TimerImplMemberTraits::GetReference(m_objPtr).* - m_memPtr)(m_a1, m_a2, m_a3, m_a4, m_a5); + std::apply(m_memPtr, m_arguments); } - MEM_PTR m_memPtr; - OBJ_PTR m_objPtr; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - T4Stored m_a4; - T5Stored m_a5; - }* function = new MemFnTimerImplFive(memPtr, objPtr); - - return function; -} - -/** - * Make a TimerImpl from a function pointer taking six arguments. - * \copydetails MakeTimerImpl(MEM_PTR,OBJ_PTR) - */ -template -TimerImpl* -MakeTimerImpl(IntToType<6>, MEM_PTR memPtr, OBJ_PTR objPtr) -{ - typedef typename TypeTraits::PointerToMemberTraits::Arg1Type T1; - typedef typename TimerTraits::ParameterType T1Parameter; - typedef typename TimerTraits::StoredType T1Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg2Type T2; - typedef typename TimerTraits::ParameterType T2Parameter; - typedef typename TimerTraits::StoredType T2Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg3Type T3; - typedef typename TimerTraits::ParameterType T3Parameter; - typedef typename TimerTraits::StoredType T3Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg4Type T4; - typedef typename TimerTraits::ParameterType T4Parameter; - typedef typename TimerTraits::StoredType T4Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg5Type T5; - typedef typename TimerTraits::ParameterType T5Parameter; - typedef typename TimerTraits::StoredType T5Stored; - typedef typename TypeTraits::PointerToMemberTraits::Arg6Type T6; - typedef typename TimerTraits::ParameterType T6Parameter; - typedef typename TimerTraits::StoredType T6Stored; - - struct MemFnTimerImplSix : public TimerImplSix - { - MemFnTimerImplSix(MEM_PTR memPtr, OBJ_PTR objPtr) - : m_memPtr(memPtr), - m_objPtr(objPtr) - { - } - - virtual void SetArguments(T1Parameter a1, - T2Parameter a2, - T3Parameter a3, - T4Parameter a4, - T5Parameter a5, - T6Parameter a6) - { - m_a1 = a1; - m_a2 = a2; - m_a3 = a3; - m_a4 = a4; - m_a5 = a5; - m_a6 = a6; - } - - virtual EventId Schedule(const Time& delay) - { - return Simulator::Schedule(delay, - m_memPtr, - m_objPtr, - m_a1, - m_a2, - m_a3, - m_a4, - m_a5, - m_a6); - } - - virtual void Invoke() - { - (TimerImplMemberTraits::GetReference(m_objPtr).* - m_memPtr)(m_a1, m_a2, m_a3, m_a4, m_a5, m_a6); - } - - MEM_PTR m_memPtr; - OBJ_PTR m_objPtr; - T1Stored m_a1; - T2Stored m_a2; - T3Stored m_a3; - T4Stored m_a4; - T5Stored m_a5; - T6Stored m_a6; - }* function = new MemFnTimerImplSix(memPtr, objPtr); + std::function m_memPtr; + std::tuple...> m_arguments; + }* function = new MemFnTimerImpl(memPtr, objPtr); return function; } @@ -1080,109 +188,21 @@ MakeTimerImpl(IntToType<6>, MEM_PTR memPtr, OBJ_PTR objPtr) * Implementation of TimerImpl itself. ********************************************************************/ -template +template void -TimerImpl::SetArgs(T1 a1) +TimerImpl::SetArgs(Args... args) { - typedef TimerImplOne::ParameterType> TimerImplBase; + using TimerImplBase = TimerImplX&...>; auto impl = dynamic_cast(this); if (impl == nullptr) { NS_FATAL_ERROR("You tried to set Timer arguments incompatible with its function."); return; } - impl->SetArguments(a1); + impl->SetArguments(args...); } -template -void -TimerImpl::SetArgs(T1 a1, T2 a2) -{ - typedef TimerImplTwo::ParameterType, - typename TimerTraits::ParameterType> - TimerImplBase; - auto impl = dynamic_cast(this); - if (impl == nullptr) - { - NS_FATAL_ERROR("You tried to set Timer arguments incompatible with its function."); - return; - } - impl->SetArguments(a1, a2); -} - -template -void -TimerImpl::SetArgs(T1 a1, T2 a2, T3 a3) -{ - typedef TimerImplThree::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType> - TimerImplBase; - auto impl = dynamic_cast(this); - if (impl == nullptr) - { - NS_FATAL_ERROR("You tried to set Timer arguments incompatible with its function."); - return; - } - impl->SetArguments(a1, a2, a3); -} - -template -void -TimerImpl::SetArgs(T1 a1, T2 a2, T3 a3, T4 a4) -{ - typedef TimerImplFour::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType> - TimerImplBase; - auto impl = dynamic_cast(this); - if (impl == nullptr) - { - NS_FATAL_ERROR("You tried to set Timer arguments incompatible with its function."); - return; - } - impl->SetArguments(a1, a2, a3, a4); -} - -template -void -TimerImpl::SetArgs(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) -{ - typedef TimerImplFive::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType> - TimerImplBase; - auto impl = dynamic_cast(this); - if (impl == nullptr) - { - NS_FATAL_ERROR("You tried to set Timer arguments incompatible with its function."); - return; - } - impl->SetArguments(a1, a2, a3, a4, a5); -} - -template -void -TimerImpl::SetArgs(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) -{ - typedef TimerImplSix::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType, - typename TimerTraits::ParameterType> - TimerImplBase; - auto impl = dynamic_cast(this); - if (impl == 0) - { - NS_FATAL_ERROR("You tried to set Timer arguments incompatible with its function."); - return; - } - impl->SetArguments(a1, a2, a3, a4, a5, a6); -} +} // namespace internal } // namespace ns3 diff --git a/src/core/model/timer.cc b/src/core/model/timer.cc index 1fcba54c39..214125469c 100644 --- a/src/core/model/timer.cc +++ b/src/core/model/timer.cc @@ -56,7 +56,7 @@ Timer::~Timer() NS_LOG_FUNCTION(this); if (m_flags & CHECK_ON_DESTROY) { - if (m_event.IsRunning()) + if (m_event.IsPending()) { NS_FATAL_ERROR("Event is still running while destroying."); } @@ -129,7 +129,7 @@ bool Timer::IsRunning() const { NS_LOG_FUNCTION(this); - return !IsSuspended() && m_event.IsRunning(); + return !IsSuspended() && m_event.IsPending(); } bool @@ -170,7 +170,7 @@ Timer::Schedule(Time delay) { NS_LOG_FUNCTION(this << delay); NS_ASSERT(m_impl != nullptr); - if (m_event.IsRunning()) + if (m_event.IsPending()) { NS_FATAL_ERROR("Event is still running while re-scheduling."); } diff --git a/src/core/model/timer.h b/src/core/model/timer.h index 6cc78b513d..eae0b0e583 100644 --- a/src/core/model/timer.h +++ b/src/core/model/timer.h @@ -21,7 +21,6 @@ #include "event-id.h" #include "fatal-error.h" -#include "int-to-type.h" #include "nstime.h" /** @@ -50,8 +49,13 @@ namespace ns3 * Timer is destroyed. */ +namespace internal +{ + class TimerImpl; +} // namespace internal + /** * \ingroup timer * \brief A simple virtual Timer class @@ -254,7 +258,7 @@ class Timer * The timer implementation, which contains the bound callback * function and arguments. */ - TimerImpl* m_impl; + internal::TimerImpl* m_impl; /** The amount of time left on the Timer while it is suspended. */ Time m_delayLeft; }; @@ -275,7 +279,7 @@ void Timer::SetFunction(FN fn) { delete m_impl; - m_impl = MakeTimerImpl(fn); + m_impl = internal::MakeTimerImpl(fn); } template @@ -283,7 +287,7 @@ void Timer::SetFunction(MEM_PTR memPtr, OBJ_PTR objPtr) { delete m_impl; - m_impl = MakeTimerImpl(memPtr, objPtr); + m_impl = internal::MakeTimerImpl(memPtr, objPtr); } template diff --git a/src/core/model/trickle-timer.cc b/src/core/model/trickle-timer.cc index e97c990251..524d1ac3c2 100644 --- a/src/core/model/trickle-timer.cc +++ b/src/core/model/trickle-timer.cc @@ -21,6 +21,7 @@ #include "log.h" +#include #include namespace ns3 @@ -116,20 +117,7 @@ TrickleTimer::GetDoublings() const return 0; } - // Here we assume that m_ticks is a power of 2. - // This could have been way more elegant by using - // std::countl_zero() defined in the header - // which is c++20 - so not yet widely available. - - uint64_t ticks = m_ticks; - uint8_t doublings = 0; - while (ticks != 1) - { - ticks >>= 1; - doublings++; - } - - return doublings; + return std::countr_zero(m_ticks); } uint16_t @@ -144,7 +132,7 @@ TrickleTimer::GetDelayLeft() const { NS_LOG_FUNCTION(this); - if (m_timerExpiration.IsRunning()) + if (m_timerExpiration.IsPending()) { return Simulator::GetDelayLeft(m_timerExpiration); } @@ -157,7 +145,7 @@ TrickleTimer::GetIntervalLeft() const { NS_LOG_FUNCTION(this); - if (m_intervalExpiration.IsRunning()) + if (m_intervalExpiration.IsPending()) { return Simulator::GetDelayLeft(m_intervalExpiration); } diff --git a/src/core/model/trickle-timer.h b/src/core/model/trickle-timer.h index 301e200746..d50d867867 100644 --- a/src/core/model/trickle-timer.h +++ b/src/core/model/trickle-timer.h @@ -33,8 +33,13 @@ namespace ns3 { +namespace internal +{ + class TimerImpl; +} // namespace internal + /** * \ingroup timer * \brief A Trickle Timer following \RFC{6206}. @@ -230,7 +235,7 @@ class TrickleTimer * The timer implementation, which contains the bound callback * function and arguments. */ - TimerImpl* m_impl; + internal::TimerImpl* m_impl; /** The future event scheduled to expire the timer. */ EventId m_timerExpiration; @@ -265,7 +270,7 @@ void TrickleTimer::SetFunction(FN fn) { delete m_impl; - m_impl = MakeTimerImpl(fn); + m_impl = internal::MakeTimerImpl(fn); } template @@ -273,7 +278,7 @@ void TrickleTimer::SetFunction(MEM_PTR memPtr, OBJ_PTR objPtr) { delete m_impl; - m_impl = MakeTimerImpl(memPtr, objPtr); + m_impl = internal::MakeTimerImpl(memPtr, objPtr); } template diff --git a/src/core/model/tuple.h b/src/core/model/tuple.h index 570c2726bc..422bbab045 100644 --- a/src/core/model/tuple.h +++ b/src/core/model/tuple.h @@ -57,12 +57,21 @@ operator<<(std::ostream& os, const std::tuple& t) return os; } -// Doxygen for this class is auto-generated by -// utils/print-introspected-doxygen.h +/** + * \ingroup attributes + * \defgroup attribute_Tuple Tuple Attribute + * AttributeValue implementation for Tuple + */ /** + * \ingroup attribute_Tuple + * + * AttributeValue implementation for Tuple. + * * Hold objects of type std::tuple. * \tparam Args \explicit The list of AttributeValues to be held by this TupleValue + * + * \see AttributeValue */ template class TupleValue : public AttributeValue @@ -96,6 +105,8 @@ class TupleValue : public AttributeValue result_type Get() const; /** * Set the stored values. + * + * \param value The stored value */ void Set(const result_type& value); @@ -110,6 +121,7 @@ class TupleValue : public AttributeValue * * \tparam T \deduced the type of the given variable (normally, the argument type * of a set method or the type of a data member) + * \param [out] value The stored value * \return true if the given variable was set */ template @@ -131,6 +143,8 @@ class TupleValue : public AttributeValue }; /** + * \ingroup attribute_Tuple + * * Create a TupleValue object. Enable to write code like this snippet: * * \code @@ -149,6 +163,8 @@ template auto MakeTupleValue(T2 t); /** + * \ingroup attribute_Tuple + * * Checker for attribute values storing tuples. */ class TupleChecker : public AttributeChecker @@ -163,6 +179,8 @@ class TupleChecker : public AttributeChecker }; /** + * \ingroup attribute_Tuple + * * Create a TupleChecker from AttributeCheckers associated with TupleValue elements. * * \tparam Args \explicit Attribute value types @@ -174,6 +192,8 @@ template Ptr MakeTupleChecker(Ts... checkers); /** + * \ingroup attribute_Tuple + * * Create an AttributeAccessor for a class data member of type tuple, * or a lone class get functor or set method. * @@ -188,6 +208,8 @@ template Ptr MakeTupleAccessor(T1 a1); /** + * \ingroup attribute_Tuple + * * Create an AttributeAccessor using a pair of get functor * and set methods from a class. * @@ -343,6 +365,8 @@ namespace internal { /** + * \ingroup attribute_Tuple + * * Internal checker class templated to each AttributeChecker * for each entry in the tuple. */ @@ -418,6 +442,8 @@ class TupleChecker : public ns3::TupleChecker }; /** + * \ingroup attribute_Tuple + * * Helper class defining static methods for MakeTupleChecker and MakeTupleAccessor * that are called when user specifies the list of AttributeValue types included * in a TupleValue type. @@ -454,6 +480,8 @@ struct TupleHelper }; /** + * \ingroup attribute_Tuple + * * Helper class defining static methods for MakeTupleValue, MakeTupleChecker and * MakeTupleAccessor that are called when user provides a std::tuple of the * AttributeValue types included in a TupleValue type. diff --git a/src/core/model/type-id.cc b/src/core/model/type-id.cc index 6ebe233802..91241b4c7f 100644 --- a/src/core/model/type-id.cc +++ b/src/core/model/type-id.cc @@ -457,7 +457,8 @@ IidManager::IidInformation* IidManager::LookupInformation(uint16_t uid) const { NS_LOG_FUNCTION(IID << uid); - NS_ASSERT(uid <= m_information.size() && uid != 0); + NS_ASSERT_MSG(uid <= m_information.size() && uid != 0, + "The uid " << uid << " for this TypeId is invalid"); NS_LOG_LOGIC(IIDL << m_information[uid - 1].name); return const_cast(&m_information[uid - 1]); } diff --git a/src/core/model/unix-fd-reader.cc b/src/core/model/unix-fd-reader.cc index 89dd3801c7..f73dc356bf 100644 --- a/src/core/model/unix-fd-reader.cc +++ b/src/core/model/unix-fd-reader.cc @@ -93,7 +93,7 @@ FdReader::Start(int fd, Callback readCallback) // scheduling a "destroy time" method to make sure the thread exits before // proceeding. // - if (!m_destroyEvent.IsRunning()) + if (!m_destroyEvent.IsPending()) { // hold a reference to ensure that this object is not // deallocated before the destroy-time event fires diff --git a/src/core/model/val-array.h b/src/core/model/val-array.h index 9bd2ad968d..d90050be30 100644 --- a/src/core/model/val-array.h +++ b/src/core/model/val-array.h @@ -29,6 +29,11 @@ namespace ns3 { +/** + * \defgroup Matrices Classes to do efficient math operations on arrays + * \ingroup core + */ + /** * \ingroup Matrices * diff --git a/src/core/model/vector.cc b/src/core/model/vector.cc index 26a765da15..d3db45630a 100644 --- a/src/core/model/vector.cc +++ b/src/core/model/vector.cc @@ -27,7 +27,7 @@ /** * \file - * \ingroup attribute_Vector + * \ingroup geometry * ns3::Vector, ns3::Vector2D and ns3::Vector3D attribute value implementations. */ @@ -201,6 +201,24 @@ operator-(const Vector3D& a, const Vector3D& b) return Vector3D(a.x - b.x, a.y - b.y, a.z - b.z); } +Vector3D +operator*(const Vector3D& a, double b) +{ + return Vector3D(a.x * b, a.y * b, a.z * b); +} + +Vector3D +operator*(double a, const Vector3D& b) +{ + return Vector3D(b.x * a, b.y * a, b.z * a); +} + +double +operator*(const Vector3D& a, const Vector3D& b) +{ + return a.x * b.x + a.y * b.y + a.z * b.z; +} + std::ostream& operator<<(std::ostream& os, const Vector2D& vector) { @@ -268,4 +286,22 @@ operator-(const Vector2D& a, const Vector2D& b) return Vector2D(a.x - b.x, a.y - b.y); } +Vector2D +operator*(const Vector2D& a, double b) +{ + return Vector2D(a.x * b, a.y * b); +} + +Vector2D +operator*(double a, const Vector2D& b) +{ + return Vector2D(b.x * a, b.y * a); +} + +double +operator*(const Vector2D& a, const Vector2D& b) +{ + return a.x * b.x + a.y * b.y; +} + } // namespace ns3 diff --git a/src/core/model/vector.h b/src/core/model/vector.h index 90c65874af..ff4483cdc4 100644 --- a/src/core/model/vector.h +++ b/src/core/model/vector.h @@ -172,6 +172,30 @@ class Vector3D * \returns The vector difference of \pname{a} and \pname{b}. */ friend Vector3D operator-(const Vector3D& a, const Vector3D& b); + + /** + * Scalar multiplication operator. + * \param [in] a lhs vector. + * \param [in] b rhs scalar. + * \returns The vector \pname{a} scaled by \pname{b}. + */ + friend Vector3D operator*(const Vector3D& a, double b); + + /** + * Scalar multiplication operator. + * \param [in] a lhs scalar. + * \param [in] b rhs vector. + * \returns The vector \pname{b} scaled by \pname{a}. + */ + friend Vector3D operator*(double a, const Vector3D& b); + + /** + * Dot product operator. + * \param [in] a lhs vector. + * \param [in] b rhs vector. + * \returns The dot product of \pname{a} and \pname{b}. + */ + friend double operator*(const Vector3D& a, const Vector3D& b); }; /** @@ -301,6 +325,30 @@ class Vector2D * \returns The vector difference of \pname{a} and \pname{b}. */ friend Vector2D operator-(const Vector2D& a, const Vector2D& b); + + /** + * Scalar multiplication operator. + * \param [in] a lhs vector. + * \param [in] b rhs scalar. + * \returns The vector \pname{a} scaled by \pname{b}. + */ + friend Vector2D operator*(const Vector2D& a, double b); + + /** + * Scalar multiplication operator. + * \param [in] a lhs scalar. + * \param [in] b rhs vector. + * \returns The vector \pname{b} scaled by \pname{a}. + */ + friend Vector2D operator*(double a, const Vector2D& b); + + /** + * Dot product operator. + * \param [in] a lhs vector. + * \param [in] b rhs vector. + * \returns The dot product of \pname{a} and \pname{b}. + */ + friend double operator*(const Vector2D& a, const Vector2D& b); }; double CalculateDistance(const Vector3D& a, const Vector3D& b); @@ -318,47 +366,53 @@ ATTRIBUTE_HELPER_HEADER(Vector3D); ATTRIBUTE_HELPER_HEADER(Vector2D); /** + * \ingroup attribute_Vector3D * \relates Vector3D * Vector alias typedef for compatibility with mobility models */ typedef Vector3D Vector; /** + * \ingroup attribute_Vector3D * \relates Vector3D * Vector alias typedef for compatibility with mobility models */ typedef Vector3DValue VectorValue; /** + * \ingroup attribute_Vector3D * \relates Vector3D * Vector alias typedef for compatibility with mobility models */ typedef Vector3DChecker VectorChecker; -// Document these by hand so they go in group attribute_Vector3D -/** - * \relates Vector3D - * \fn ns3::Ptr ns3::MakeVectorAccessor (T1 a1) - * \copydoc ns3::MakeAccessorHelper(T1) - * \see AttributeAccessor - */ - -/** - * \relates Vector3D - * \fn ns3::Ptr ns3::MakeVectorAccessor (T1 a1, T2 a2) - * \copydoc ns3::MakeAccessorHelper(T1,T2) - * \see AttributeAccessor - */ - ATTRIBUTE_ACCESSOR_DEFINE(Vector); -/** - * \relates Vector3D - * \returns The AttributeChecker. - * \see AttributeChecker - */ Ptr MakeVectorChecker(); } // namespace ns3 +// Document these by hand so they go in group attribute_Vector3D + +/*! +\ingroup attribute_Vector3D +\fn ns3::Ptr ns3::MakeVectorAccessor (T1 a1) +\copydoc ns3::MakeAccessorHelper(T1) +\see AttributeAccessor +*/ + +/*! +\ingroup attribute_Vector3D +\fn ns3::Ptr ns3::MakeVectorAccessor (T1 a1, T2 a2) +\copydoc ns3::MakeAccessorHelper(T1,T2) +\see AttributeAccessor +*/ + +/*! +\ingroup attribute_Vector3D +\fn ns3::Ptr ns3::MakeVectorChecker () +\returns The AttributeChecker. +\see AttributeChecker +*/ + #endif /* NS3_VECTOR_H */ diff --git a/src/core/model/warnings.h b/src/core/model/warnings.h index 5e38d0134d..c9bd2e8ad7 100644 --- a/src/core/model/warnings.h +++ b/src/core/model/warnings.h @@ -21,28 +21,42 @@ #define NS3_WARNINGS_H /** + * \defgroup warnings Compiler warnings * \ingroup core + * + * Macros useful to silence compiler warnings on selected code parts. + */ + +/** + * \ingroup warnings * \def NS_WARNING_POP * Pops the diagnostic warning list from the stack, restoring it to the previous state. * \sa NS_WARNING_PUSH */ /** - * \ingroup core + * \ingroup warnings * \def NS_WARNING_PUSH * Push the diagnostic warning list to the stack, allowing it to be restored later. * \sa NS_WARNING_POP */ /** - * \ingroup core + * \ingroup warnings * \def NS_WARNING_SILENCE_DEPRECATED * Silences the "-Wdeprecated-declarations" warnings. * \sa NS_WARNING_POP */ /** - * \ingroup core + * \ingroup warnings + * \def NS_WARNING_SILENCE_MAYBE_UNINITIALIZED + * Silences GCC "-Wmaybe-uninitialized" warnings. + * \sa NS_WARNING_POP + */ + +/** + * \ingroup warnings * \def NS_WARNING_PUSH_DEPRECATED * Save the current warning list and disables the ones about deprecated functions and classes. * @@ -55,9 +69,30 @@ * NS_WARNING_POP; * \endcode * + * This macro is equivalent to + * \code + * NS_WARNING_PUSH; + * NS_WARNING_SILENCE_DEPRECATED; + * \endcode + * * Its use is, of course, not suggested unless strictly necessary. */ +/** + * \ingroup warnings + * \def NS_WARNING_PUSH_MAYBE_UNINITIALIZED + * Save the current warning list and disables the ones about possible uninitialized variables. + * + * + * This macro is equivalent to + * \code + * NS_WARNING_PUSH; + * NS_WARNING_SILENCE_MAYBE_UNINITIALIZED; + * \endcode + * + * \sa NS_WARNING_PUSH_DEPRECATED + */ + #if defined(_MSC_VER) // You can find the MSC warning codes at // https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warnings-c4000-c5999 @@ -79,8 +114,20 @@ #endif +// GCC-specific - Apple's clang pretends to be both... +#if defined(__GNUC__) && !defined(__clang__) +#define NS_WARNING_SILENCE_MAYBE_UNINITIALIZED \ + _Pragma("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +#else +#define NS_WARNING_SILENCE_MAYBE_UNINITIALIZED +#endif + #define NS_WARNING_PUSH_DEPRECATED \ NS_WARNING_PUSH; \ NS_WARNING_SILENCE_DEPRECATED +#define NS_WARNING_PUSH_MAYBE_UNINITIALIZED \ + NS_WARNING_PUSH; \ + NS_WARNING_SILENCE_MAYBE_UNINITIALIZED + #endif /* NS3_WARNINGS_H */ diff --git a/src/core/model/watchdog.cc b/src/core/model/watchdog.cc index 18255e9298..d98f101e06 100644 --- a/src/core/model/watchdog.cc +++ b/src/core/model/watchdog.cc @@ -52,7 +52,7 @@ Watchdog::Ping(Time delay) NS_LOG_FUNCTION(this << delay); Time end = Simulator::Now() + delay; m_end = std::max(m_end, end); - if (m_event.IsRunning()) + if (m_event.IsPending()) { return; } diff --git a/src/core/model/watchdog.h b/src/core/model/watchdog.h index 5ac1e259bd..e3fe5eee26 100644 --- a/src/core/model/watchdog.h +++ b/src/core/model/watchdog.h @@ -31,8 +31,13 @@ namespace ns3 { +namespace internal +{ + class TimerImpl; +} // namespace internal + /** * \ingroup timer * \brief A very simple watchdog operating in virtual time. @@ -115,7 +120,7 @@ class Watchdog * The timer implementation, which contains the bound callback * function and arguments. */ - TimerImpl* m_impl; + internal::TimerImpl* m_impl; /** The future event scheduled to expire the timer. */ EventId m_event; /** The absolute time when the timer will expire. */ @@ -138,7 +143,7 @@ void Watchdog::SetFunction(FN fn) { delete m_impl; - m_impl = MakeTimerImpl(fn); + m_impl = internal::MakeTimerImpl(fn); } template @@ -146,7 +151,7 @@ void Watchdog::SetFunction(MEM_PTR memPtr, OBJ_PTR objPtr) { delete m_impl; - m_impl = MakeTimerImpl(memPtr, objPtr); + m_impl = internal::MakeTimerImpl(memPtr, objPtr); } template diff --git a/src/core/model/win32-fd-reader.cc b/src/core/model/win32-fd-reader.cc index 457dd669fb..06ab1f2e2c 100644 --- a/src/core/model/win32-fd-reader.cc +++ b/src/core/model/win32-fd-reader.cc @@ -41,7 +41,10 @@ namespace ns3 NS_LOG_COMPONENT_DEFINE("FdReader"); +// conditional compilation to avoid Doxygen errors +#ifdef __WIN32__ bool FdReader::winsock_initialized = false; +#endif FdReader::FdReader() : m_fd(-1), @@ -101,7 +104,7 @@ FdReader::Start(int fd, Callback readCallback) // scheduling a "destroy time" method to make sure the thread exits before // proceeding. // - if (!m_destroyEvent.IsRunning()) + if (!m_destroyEvent.IsPending()) { // hold a reference to ensure that this object is not // deallocated before the destroy-time event fires diff --git a/src/core/test/attribute-container-test-suite.cc b/src/core/test/attribute-container-test-suite.cc index d8a191ac78..f5e35efef5 100644 --- a/src/core/test/attribute-container-test-suite.cc +++ b/src/core/test/attribute-container-test-suite.cc @@ -193,22 +193,6 @@ AttributeContainerObject::GetIntVec() const return m_intvec; } -/** - * \ingroup attribute-tests - * - * This function handles mixed constness and compatible, yet - * distinct numerical classes (like int and long) - * \param x The left operand. - * \param y The right operand. - * \return true if the pairs have the same numerical values. - */ -template -bool -operator==(const std::pair& x, const std::pair& y) -{ - return x.first == y.first && x.second == y.second; -} - /** * \ingroup attribute-tests * @@ -307,7 +291,9 @@ AttributeContainerTestCase::DoRun() for (const auto& v : ref) { NS_TEST_ASSERT_MSG_NE(true, (aciter == ac.End()), "AC iterator reached end"); - NS_TEST_ASSERT_MSG_EQ(v, (*aciter)->Get(), "Incorrect value"); + bool valCheck = + v.first == (*aciter)->Get().first && v.second == (*aciter)->Get().second; + NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value"); ++aciter; } NS_TEST_ASSERT_MSG_EQ(true, (aciter == ac.End()), "AC iterator did not reach end"); @@ -542,7 +528,8 @@ AttributeContainerSetGetTestCase::DoRun() auto iter = map.begin(); for (const auto& v : mapstrint) { - NS_TEST_ASSERT_MSG_EQ(v, *iter, "Incorrect value in mapstrint"); + bool valCheck = v.first == (*iter).first && v.second == (*iter).second; + NS_TEST_ASSERT_MSG_EQ(valCheck, true, "Incorrect value in mapstrint"); ++iter; } } @@ -560,11 +547,11 @@ class AttributeContainerTestSuite : public TestSuite }; AttributeContainerTestSuite::AttributeContainerTestSuite() - : TestSuite("attribute-container-test-suite", UNIT) + : TestSuite("attribute-container-test-suite", Type::UNIT) { - AddTestCase(new AttributeContainerTestCase(), TestCase::QUICK); - AddTestCase(new AttributeContainerSerializationTestCase(), TestCase::QUICK); - AddTestCase(new AttributeContainerSetGetTestCase(), TestCase::QUICK); + AddTestCase(new AttributeContainerTestCase(), TestCase::Duration::QUICK); + AddTestCase(new AttributeContainerSerializationTestCase(), TestCase::Duration::QUICK); + AddTestCase(new AttributeContainerSetGetTestCase(), TestCase::Duration::QUICK); } static AttributeContainerTestSuite diff --git a/src/core/test/attribute-test-suite.cc b/src/core/test/attribute-test-suite.cc index 9dac00d326..acdec4e4a6 100644 --- a/src/core/test/attribute-test-suite.cc +++ b/src/core/test/attribute-test-suite.cc @@ -2084,44 +2084,44 @@ class AttributesTestSuite : public TestSuite }; AttributesTestSuite::AttributesTestSuite() - : TestSuite("attributes", UNIT) + : TestSuite("attributes", Type::UNIT) { AddTestCase(new AttributeTestCase("Check Attributes of type BooleanValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new AttributeTestCase("Check Attributes of type IntegerValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new AttributeTestCase("Check Attributes of type UintegerValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new AttributeTestCase("Check Attributes of type DoubleValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new AttributeTestCase>( "Check Attributes of type EnumValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new AttributeTestCase>( "Check Attributes of type EnumValue (wrapping an enum class)"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new AttributeTestCase("Check Attributes of type TimeValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new RandomVariableStreamAttributeTestCase("Check Attributes of type RandomVariableStream"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new ObjectVectorAttributeTestCase("Check Attributes of type ObjectVectorValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new ObjectMapAttributeTestCase("Check Attributes of type ObjectMapValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new PointerAttributeTestCase("Check Attributes of type PointerValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new CallbackValueTestCase("Check Attributes of type CallbackValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new IntegerTraceSourceAttributeTestCase( "Ensure TracedValue can be set like IntegerValue"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase( new IntegerTraceSourceTestCase("Ensure TracedValue also works as trace source"), - TestCase::QUICK); + TestCase::Duration::QUICK); AddTestCase(new TracedCallbackTestCase( "Ensure TracedCallback works as trace source"), - TestCase::QUICK); + TestCase::Duration::QUICK); } static AttributesTestSuite g_attributesTestSuite; //!< Static variable for test initialization diff --git a/src/core/test/callback-test-suite.cc b/src/core/test/callback-test-suite.cc index 0e4ef6121d..7ffda9d432 100644 --- a/src/core/test/callback-test-suite.cc +++ b/src/core/test/callback-test-suite.cc @@ -1190,14 +1190,14 @@ class CallbackTestSuite : public TestSuite }; CallbackTestSuite::CallbackTestSuite() - : TestSuite("callback", UNIT) + : TestSuite("callback", Type::UNIT) { - AddTestCase(new BasicCallbackTestCase, TestCase::QUICK); - AddTestCase(new MakeCallbackTestCase, TestCase::QUICK); - AddTestCase(new MakeBoundCallbackTestCase, TestCase::QUICK); - AddTestCase(new CallbackEqualityTestCase, TestCase::QUICK); - AddTestCase(new NullifyCallbackTestCase, TestCase::QUICK); - AddTestCase(new MakeCallbackTemplatesTestCase, TestCase::QUICK); + AddTestCase(new BasicCallbackTestCase, TestCase::Duration::QUICK); + AddTestCase(new MakeCallbackTestCase, TestCase::Duration::QUICK); + AddTestCase(new MakeBoundCallbackTestCase, TestCase::Duration::QUICK); + AddTestCase(new CallbackEqualityTestCase, TestCase::Duration::QUICK); + AddTestCase(new NullifyCallbackTestCase, TestCase::Duration::QUICK); + AddTestCase(new MakeCallbackTemplatesTestCase, TestCase::Duration::QUICK); } static CallbackTestSuite g_gallbackTestSuite; //!< Static variable for test initialization diff --git a/src/core/test/event-garbage-collector-test-suite.cc b/src/core/test/event-garbage-collector-test-suite.cc index 9ee43a5704..b0602d341c 100644 --- a/src/core/test/event-garbage-collector-test-suite.cc +++ b/src/core/test/event-garbage-collector-test-suite.cc @@ -24,7 +24,7 @@ * \file * \ingroup core-tests * \ingroup events - * \ingroup events-garbage-tests + * \ingroup event-garbage-tests * EventGarbageCollector test suite. */ diff --git a/src/core/test/examples-as-tests-test-suite.cc b/src/core/test/examples-as-tests-test-suite.cc index 8a7c67815d..e1540b5a9c 100644 --- a/src/core/test/examples-as-tests-test-suite.cc +++ b/src/core/test/examples-as-tests-test-suite.cc @@ -32,6 +32,7 @@ using namespace ns3; /** * \ingroup core-tests + * \ingroup testing * \defgroup examples-as-tests Examples as tests test suite * * Runs several examples as tests in order to test ExampleAsTestSuite and ExampleAsTestCase. @@ -101,7 +102,7 @@ class ExamplesAsTestsTestSuite : public TestSuite }; ExamplesAsTestsTestSuite::ExamplesAsTestsTestSuite() - : TestSuite("examples-as-tests-test-suite", UNIT) + : TestSuite("examples-as-tests-test-suite", Type::UNIT) { AddTestCase( new ExampleAsTestCase("core-example-simulator", "sample-simulator", NS_TEST_SOURCEDIR)); @@ -114,14 +115,14 @@ ExamplesAsTestsTestSuite::ExamplesAsTestsTestSuite() } /** - * \ingroup examples-tests + * \ingroup examples-as-tests * ExampleAsTestsTestSuite instance variable. * Tests multiple examples in a single TestSuite using AddTestCase to add the examples to the suite. */ static ExamplesAsTestsTestSuite g_examplesAsTestsTestSuite; /** - * \ingroup examples-tests + * \ingroup examples-as-tests * ExampleTestSuite instance variables. * * Tests ExampleTestSuite which runs a single example as test suite as specified in constructor diff --git a/src/core/test/int64x64-test-suite.cc b/src/core/test/int64x64-test-suite.cc index dd691477e5..877a965e8e 100644 --- a/src/core/test/int64x64-test-suite.cc +++ b/src/core/test/int64x64-test-suite.cc @@ -575,6 +575,35 @@ Int64x64ArithmeticTestCase::DoRun() // Check special values Check(51, int64x64_t(0, 0x159fa87f8aeaad21ULL) * 10, int64x64_t(0, 0xd83c94fb6d2ac34aULL)); + { + auto x = int64x64_t(std::numeric_limits::min(), 0); + Check(52, x * 1, x); + Check(53, 1 * x, x); + } + { + int64x64_t x(1 << 30, (static_cast(1) << 63) + 1); + auto ret = x * x; + int64x64_t expected(1152921505680588800, 4611686020574871553); + // The real difference between ret and expected is 2^-128. + int64x64_t tolerance = 0; + if (int64x64_t::implementation == int64x64_t::ld_impl) + { + tolerance = tol1; + } + Check(54, ret, expected, tolerance); + } + + // The following triggers an assert in int64x64-128.cc:Umul():117 + /* + { + auto x = int64x64_t(1LL << 31); // 2^31 + auto y = 2 * x; // 2^32 + Check(55, x, x); + Check(56, y, y); + auto z [[maybe_unused]] = x * y; // 2^63 < 0, triggers assert + Check(57, z, z); + } + */ } /** @@ -1557,20 +1586,20 @@ class Int64x64TestSuite : public TestSuite { public: Int64x64TestSuite() - : TestSuite("int64x64", UNIT) + : TestSuite("int64x64", Type::UNIT) { - AddTestCase(new Int64x64ImplTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64HiLoTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64IntRoundTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64ArithmeticTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64CompareTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64InputTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64InputOutputTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64Bug455TestCase(), TestCase::QUICK); - AddTestCase(new Int64x64Bug863TestCase(), TestCase::QUICK); - AddTestCase(new Int64x64Bug1786TestCase(), TestCase::QUICK); - AddTestCase(new Int64x64InvertTestCase(), TestCase::QUICK); - AddTestCase(new Int64x64DoubleTestCase(), TestCase::QUICK); + AddTestCase(new Int64x64ImplTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64HiLoTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64IntRoundTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64ArithmeticTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64CompareTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64InputTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64InputOutputTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64Bug455TestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64Bug863TestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64Bug1786TestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64InvertTestCase(), TestCase::Duration::QUICK); + AddTestCase(new Int64x64DoubleTestCase(), TestCase::Duration::QUICK); } }; diff --git a/src/core/test/length-test-suite.cc b/src/core/test/length-test-suite.cc index 1d2003fa55..748720a125 100644 --- a/src/core/test/length-test-suite.cc +++ b/src/core/test/length-test-suite.cc @@ -1605,8 +1605,8 @@ class LengthTestSuite : public TestSuite LengthTestSuite::LengthTestSuite() : TestSuite("length") { - AddTestCase(new LengthTestCase(), TestCase::QUICK); - AddTestCase(new LengthValueTestCase(), TestCase::QUICK); + AddTestCase(new LengthTestCase(), TestCase::Duration::QUICK); + AddTestCase(new LengthValueTestCase(), TestCase::Duration::QUICK); } /** diff --git a/src/core/test/many-uniform-random-variables-one-get-value-call-test-suite.cc b/src/core/test/many-uniform-random-variables-one-get-value-call-test-suite.cc index 583c98eba2..09a364d62f 100644 --- a/src/core/test/many-uniform-random-variables-one-get-value-call-test-suite.cc +++ b/src/core/test/many-uniform-random-variables-one-get-value-call-test-suite.cc @@ -28,7 +28,7 @@ * \file * \ingroup core-tests * \ingroup randomvariable - * \ingroup randomvariable-tests + * \ingroup rng-tests * Test for many uniform random variable streams. */ @@ -39,15 +39,13 @@ namespace tests { /** - * \ingroup randomvariable-tests + * \ingroup rng-tests * Test case for many uniform distribution random variable stream generators */ class ManyUniformRandomVariablesOneGetValueCallTestCase : public TestCase { public: - /** Constructor. */ ManyUniformRandomVariablesOneGetValueCallTestCase(); - /** Destructor. */ ~ManyUniformRandomVariablesOneGetValueCallTestCase() override; private: @@ -89,25 +87,24 @@ ManyUniformRandomVariablesOneGetValueCallTestCase::DoRun() } /** - * \ingroup randomvariable-tests + * \ingroup rng-tests * Test suite for many uniform distribution random variable stream generators */ class ManyUniformRandomVariablesOneGetValueCallTestSuite : public TestSuite { public: - /** Constructor. */ ManyUniformRandomVariablesOneGetValueCallTestSuite(); }; ManyUniformRandomVariablesOneGetValueCallTestSuite:: ManyUniformRandomVariablesOneGetValueCallTestSuite() - : TestSuite("many-uniform-random-variables-one-get-value-call", PERFORMANCE) + : TestSuite("many-uniform-random-variables-one-get-value-call", Type::PERFORMANCE) { AddTestCase(new ManyUniformRandomVariablesOneGetValueCallTestCase); } /** - * \ingroup randomvariable-tests + * \ingroup rng-tests * ManuUniformRandomVariablesOneGetValueCallTestSuite instance variable. */ static ManyUniformRandomVariablesOneGetValueCallTestSuite diff --git a/src/core/test/matrix-array-test-suite.cc b/src/core/test/matrix-array-test-suite.cc index 574fe4dd73..3dc0e1ee0d 100644 --- a/src/core/test/matrix-array-test-suite.cc +++ b/src/core/test/matrix-array-test-suite.cc @@ -22,9 +22,13 @@ #include "ns3/test.h" /** - * \file + * \defgroup matrixArray-tests MatrixArray tests * \ingroup core-tests - * \ingroup matrixArray + * \ingroup Matrices + */ + +/** + * \file * \ingroup matrixArray-tests * MatrixArray test suite */ @@ -36,6 +40,27 @@ namespace tests NS_LOG_COMPONENT_DEFINE("MatrixArrayTest"); +/** + * \brief Function casts an input valArray "in" (type IN) to an output valArray "out" (type T) + * \param in Input valarray to be casted + * \param out Output valarray to receive casted values + */ +template +void +CastStdValarray(const std::valarray& in, std::valarray& out) +{ + // Ensure output valarray is the right size + if (out.size() != in.size()) + { + out.resize(in.size()); + } + + // Perform the cast operation + std::transform(std::begin(in), std::end(in), std::begin(out), [](IN i) { + return static_cast(i); + }); +} + /** * \ingroup matrixArray-tests * MatrixArray test case for testing constructors, operators and other functions @@ -439,6 +464,154 @@ MatrixArrayTestCase::DoRun() MatrixArray m27 = MatrixArray(std::move(jCasted)); NS_LOG_INFO("m27.GetSize ()" << m27.GetSize()); NS_TEST_ASSERT_MSG_EQ(jCastedSize, m27.GetSize(), "The number of elements are not equal."); + + // test determinant + { + std::vector, T>> detTestCases{ + // right-wraparound + {{1, 0, 7, 4, 2, 0, 6, 5, 3}, 62}, + // left-wraparound + {{1, 4, 6, 0, 2, 5, 7, 0, 3}, 62}, + // identity rank 3 + {{1, 0, 0, 0, 1, 0, 0, 0, 1}, 1}, + // identity rank 4 + {{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, 1}, + // permutation matrix rank 4 + {{0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0}, -1}, + // positive det matrix rank 2 + {{36, -5, -5, 43}, 1523}, + // single value matrix rank 1 + {{1}, 1}, + }; + for (const auto& [detVal, detRef] : detTestCases) + { + std::valarray detCast(detVal.size()); + CastStdValarray(detVal, detCast); + auto side = sqrt(detVal.size()); + MatrixArray detMat = MatrixArray(side, side, std::move(detCast)); + NS_TEST_ASSERT_MSG_EQ(detMat.Determinant()(0), + static_cast(detRef), + "The determinants are not equal."); + } + } + // clang-format off + std::valarray multiPageMatrixValues{ + // page 0: identity matrix + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + // page 1: permutation matrix + 0, 0, 1, + 0, 1, 0, + 1, 0, 0, + // page 2: random matrix + 1, 4, 6, + 0, 2, 5, + 7, 0, 3, + // page 3: upper triangular + 5, -9, 2, + 0, -4, -10, + 0, 0, -3, + // page 4: lower triangular + -7, 0, 0, + -1, -9, 0, + -5, 6, -5, + // page 5: zero diagonal + 0, 1, 2, + 1, 0, 1, + 2, 1, 0, + // page 6: zero bidiagonal + 0, 1, 0, + 1, 0, 1, + 0, 1, 0 + }; + // clang-format on + std::valarray castMultiPageMatrixValues(multiPageMatrixValues.size()); + CastStdValarray(multiPageMatrixValues, castMultiPageMatrixValues); + MatrixArray multiPageMatrix = MatrixArray(3, + 3, + multiPageMatrixValues.size() / 9, + std::move(castMultiPageMatrixValues)); + // test the determinant in a multi-page MatrixArray + std::vector determinants = {1, -1, 62, 60, -315, 4, 0}; + auto det = multiPageMatrix.Determinant(); + for (size_t page = 0; page < multiPageMatrix.GetNumPages(); page++) + { + NS_TEST_ASSERT_MSG_EQ(det(page), + static_cast(determinants[page]), + "The determinants from the page " << std::to_string(page) + << " are not equal."); + } + + // test Frobenius norm in a multi-page MatrixArray + std::vector fnorms = {sqrt(3), sqrt(3), 11.8322, 15.3297, 14.7309, 3.4641, 2}; + auto frob = multiPageMatrix.FrobeniusNorm(); + for (size_t page = 0; page < multiPageMatrix.GetNumPages(); page++) + { + NS_TEST_ASSERT_MSG_EQ_TOL(std::abs(frob(page)), + std::abs(static_cast(fnorms[page])), + 0.0001, + "The Frobenius norm from the page " << std::to_string(page) + << " are not equal."); + } + + // test page copying + for (size_t noOfCopies = 1; noOfCopies < 4; noOfCopies++) + { + auto copies = m27.MakeNCopies(noOfCopies); + NS_TEST_ASSERT_MSG_EQ(copies.GetNumPages(), + noOfCopies, + "Creating " << std::to_string(noOfCopies) << " copies failed."); + NS_TEST_ASSERT_MSG_EQ(copies.GetNumRows(), + m27.GetNumRows(), + "The copy doesn't have the same number of rows as the original."); + NS_TEST_ASSERT_MSG_EQ(copies.GetNumCols(), + m27.GetNumCols(), + "The copy doesn't have the same number of columns as the original."); + for (size_t page = 0; page < copies.GetNumPages(); page++) + { + T diff{}; + for (size_t row = 0; row < copies.GetNumRows(); row++) + { + for (size_t col = 0; col < copies.GetNumCols(); col++) + { + diff += m27(row, col, 0) - copies(row, col, page); + } + } + NS_TEST_ASSERT_MSG_EQ(diff, T{}, "Mismatch in copied values."); + } + } + + // test page 1 and 0 extraction + std::vector> pages{multiPageMatrix.ExtractPage(1), + multiPageMatrix.ExtractPage(0)}; + + // test page 1 and 0 joining + auto jointPagesMatrix = MatrixArray::JoinPages(pages); + NS_TEST_ASSERT_MSG_EQ(jointPagesMatrix.GetNumPages(), 2, "Mismatch in number of join pages."); + for (size_t page = 0; page < jointPagesMatrix.GetNumPages(); page++) + { + T diff{}; + for (size_t row = 0; row < jointPagesMatrix.GetNumRows(); row++) + { + for (size_t col = 0; col < jointPagesMatrix.GetNumCols(); col++) + { + diff += multiPageMatrix(row, col, 1 - page) - jointPagesMatrix(row, col, page); + } + } + NS_TEST_ASSERT_MSG_EQ(diff, T{}, "Mismatching pages."); + } + + // test identity matrix + auto identityRank3Reference = multiPageMatrix.ExtractPage(0); + auto identityRank3 = MatrixArray::IdentityMatrix(3); + NS_TEST_ASSERT_MSG_EQ(identityRank3, identityRank3Reference, "Mismatch in identity matrices."); + + identityRank3 = MatrixArray::IdentityMatrix(3, 10).ExtractPage(9); + NS_TEST_ASSERT_MSG_EQ(identityRank3, identityRank3Reference, "Mismatch in identity matrices."); + + identityRank3 = MatrixArray::IdentityMatrix(identityRank3Reference); + NS_TEST_ASSERT_MSG_EQ(identityRank3, identityRank3Reference, "Mismatch in identity matrices."); } /** diff --git a/src/core/test/object-test-suite.cc b/src/core/test/object-test-suite.cc index 76032ab68a..f8bfe0cc08 100644 --- a/src/core/test/object-test-suite.cc +++ b/src/core/test/object-test-suite.cc @@ -464,6 +464,74 @@ AggregateObjectTestCase::DoRun() NS_TEST_ASSERT_MSG_NE(baseA, nullptr, "Unable to GetObject on released object"); } +/** + * \ingroup object-tests + * Test we can aggregate Objects. + */ +class UnidirectionalAggregateObjectTestCase : public TestCase +{ + public: + /** Constructor. */ + UnidirectionalAggregateObjectTestCase(); + /** Destructor. */ + ~UnidirectionalAggregateObjectTestCase() override; + + private: + void DoRun() override; +}; + +UnidirectionalAggregateObjectTestCase::UnidirectionalAggregateObjectTestCase() + : TestCase("Check Object unidirectional aggregation functionality") +{ +} + +UnidirectionalAggregateObjectTestCase::~UnidirectionalAggregateObjectTestCase() +{ +} + +void +UnidirectionalAggregateObjectTestCase::DoRun() +{ + Ptr baseAOne = CreateObject(); + NS_TEST_ASSERT_MSG_NE(baseAOne, nullptr, "Unable to CreateObject"); + Ptr baseATwo = CreateObject(); + NS_TEST_ASSERT_MSG_NE(baseATwo, nullptr, "Unable to CreateObject"); + + Ptr baseB = CreateObject(); + NS_TEST_ASSERT_MSG_NE(baseB, nullptr, "Unable to CreateObject"); + + // + // Make an unidirectional aggregation of a BaseA object and a BaseB object. + // + baseAOne->UnidirectionalAggregateObject(baseB); + baseATwo->UnidirectionalAggregateObject(baseB); + + // + // We should be able to ask the aggregation (through baseA) for the BaseB part + // on either BaseA objects + // + NS_TEST_ASSERT_MSG_NE(baseAOne->GetObject(), + nullptr, + "Cannot GetObject (through baseAOne) for BaseB Object"); + + NS_TEST_ASSERT_MSG_NE(baseATwo->GetObject(), + nullptr, + "Cannot GetObject (through baseATwo) for BaseB Object"); + + NS_TEST_ASSERT_MSG_EQ( + baseAOne->GetObject(), + baseATwo->GetObject(), + "GetObject (through baseAOne and baseATwo) for BaseB Object are not equal"); + + // + // We should not be able to ask the aggregation (through baseB) for the BaseA part + // of the aggregation. + // + NS_TEST_ASSERT_MSG_NE(!baseB->GetObject(), + 0, + "Can GetObject (through baseB) for BaseA Object"); +} + /** * \ingroup object-tests * Test an Object factory can create Objects @@ -565,6 +633,7 @@ ObjectTestSuite::ObjectTestSuite() { AddTestCase(new CreateObjectTestCase); AddTestCase(new AggregateObjectTestCase); + AddTestCase(new UnidirectionalAggregateObjectTestCase); AddTestCase(new ObjectFactoryTestCase); } diff --git a/src/core/test/one-uniform-random-variable-many-get-value-calls-test-suite.cc b/src/core/test/one-uniform-random-variable-many-get-value-calls-test-suite.cc index 18f24b9782..8c05056870 100644 --- a/src/core/test/one-uniform-random-variable-many-get-value-calls-test-suite.cc +++ b/src/core/test/one-uniform-random-variable-many-get-value-calls-test-suite.cc @@ -28,7 +28,7 @@ * \file * \ingroup core-tests * \ingroup randomvariable - * \ingroup randomvariable-tests + * \ingroup rng-tests * Test for one uniform random variable stream. */ @@ -39,15 +39,13 @@ namespace tests { /** - * \ingroup randomvariable-tests + * \ingroup rng-tests * Test case for one uniform distribution random variable stream generator */ class OneUniformRandomVariableManyGetValueCallsTestCase : public TestCase { public: - /** Constructor. */ OneUniformRandomVariableManyGetValueCallsTestCase(); - /** Destructor. */ ~OneUniformRandomVariableManyGetValueCallsTestCase() override; private: @@ -89,25 +87,24 @@ OneUniformRandomVariableManyGetValueCallsTestCase::DoRun() } /** - * \ingroup randomvariable-tests + * \ingroup rng-tests * Test suite for one uniform distribution random variable stream generator */ class OneUniformRandomVariableManyGetValueCallsTestSuite : public TestSuite { public: - /** Constructor. */ OneUniformRandomVariableManyGetValueCallsTestSuite(); }; OneUniformRandomVariableManyGetValueCallsTestSuite:: OneUniformRandomVariableManyGetValueCallsTestSuite() - : TestSuite("one-uniform-random-variable-many-get-value-calls", PERFORMANCE) + : TestSuite("one-uniform-random-variable-many-get-value-calls", Type::PERFORMANCE) { AddTestCase(new OneUniformRandomVariableManyGetValueCallsTestCase); } /** - * \ingroup randomvariable-tests + * \ingroup rng-tests * OneUniformRandomVariableManyGetValueCallsTestSuite instance variable. */ static OneUniformRandomVariableManyGetValueCallsTestSuite diff --git a/src/core/test/pair-value-test-suite.cc b/src/core/test/pair-value-test-suite.cc index 595252436d..b62ae3aa7c 100644 --- a/src/core/test/pair-value-test-suite.cc +++ b/src/core/test/pair-value-test-suite.cc @@ -211,10 +211,10 @@ class PairValueTestSuite : public TestSuite }; PairValueTestSuite::PairValueTestSuite() - : TestSuite("pair-value-test-suite", UNIT) + : TestSuite("pair-value-test-suite", Type::UNIT) { - AddTestCase(new PairValueTestCase(), TestCase::QUICK); - AddTestCase(new PairValueSettingsTestCase(), TestCase::QUICK); + AddTestCase(new PairValueTestCase(), TestCase::Duration::QUICK); + AddTestCase(new PairValueSettingsTestCase(), TestCase::Duration::QUICK); } static PairValueTestSuite g_pairValueTestSuite; //!< Static variable for test initialization diff --git a/src/core/test/random-variable-stream-test-suite.cc b/src/core/test/random-variable-stream-test-suite.cc index f91e50a6d5..145bd49bd6 100644 --- a/src/core/test/random-variable-stream-test-suite.cc +++ b/src/core/test/random-variable-stream-test-suite.cc @@ -26,6 +26,7 @@ #include "ns3/log.h" #include "ns3/random-variable-stream.h" #include "ns3/rng-seed-manager.h" +#include "ns3/shuffle.h" #include "ns3/string.h" #include "ns3/test.h" @@ -2872,6 +2873,71 @@ BinomialAntitheticTestCase::DoRun() "Wrong mean value."); } +/** + * \ingroup rng-test + * \ingroup tests + * + * \brief Test the Shuffle function + * + * Check that the Shuffle function actually shuffles the elements and does so in a portable way. + */ +class ShuffleElementsTest : public TestCase +{ + public: + ShuffleElementsTest(); + + private: + void DoRun() override; +}; + +ShuffleElementsTest::ShuffleElementsTest() + : TestCase("Check correct operation of the Shuffle function") +{ +} + +void +ShuffleElementsTest::DoRun() +{ + RngSeedManager::SetSeed(1); + RngSeedManager::SetRun(1); + + auto rv = CreateObject(); + rv->SetStream(1); + + // test empty vector + std::vector vec{}; + + Shuffle(vec.begin(), vec.end(), rv); + + NS_TEST_EXPECT_MSG_EQ(vec.empty(), true, "Expected an empty vector"); + + // test vector with one value + vec.push_back(3); + + Shuffle(vec.begin(), vec.end(), rv); + + NS_TEST_EXPECT_MSG_EQ((vec == std::vector{3}), true, "Expected vector {3}"); + + // test vector with two values + vec.push_back(1); + + Shuffle(vec.begin(), vec.end(), rv); + + NS_TEST_EXPECT_MSG_EQ((vec == std::vector{1, 3}), true, "Expected vector {1, 3}"); + + // test vector with multiple values + vec.push_back(7); + vec.push_back(2); + vec.push_back(4); + vec.push_back(9); + + Shuffle(vec.begin(), vec.end(), rv); + + NS_TEST_EXPECT_MSG_EQ((vec == std::vector{4, 1, 9, 3, 2, 7}), + true, + "Expected vector {4, 1, 9, 3, 2, 7}"); +} + /** * \ingroup rng-tests * RandomVariableStream test suite, covering all random number variable @@ -2885,7 +2951,7 @@ class RandomVariableSuite : public TestSuite }; RandomVariableSuite::RandomVariableSuite() - : TestSuite("random-variable-stream-generators", UNIT) + : TestSuite("random-variable-stream-generators", Type::UNIT) { AddTestCase(new UniformTestCase); AddTestCase(new UniformAntitheticTestCase); @@ -2928,6 +2994,7 @@ RandomVariableSuite::RandomVariableSuite() AddTestCase(new BernoulliAntitheticTestCase); AddTestCase(new BinomialTestCase); AddTestCase(new BinomialAntitheticTestCase); + AddTestCase(new ShuffleElementsTest); } static RandomVariableSuite randomVariableSuite; //!< Static variable for test initialization diff --git a/src/core/test/rng-test-suite.cc b/src/core/test/rng-test-suite.cc index 586b08a481..4cad7d7dee 100644 --- a/src/core/test/rng-test-suite.cc +++ b/src/core/test/rng-test-suite.cc @@ -488,12 +488,12 @@ class RngTestSuite : public TestSuite }; RngTestSuite::RngTestSuite() - : TestSuite("random-number-generators", UNIT) + : TestSuite("random-number-generators", Type::UNIT) { - AddTestCase(new RngUniformTestCase, TestCase::QUICK); - AddTestCase(new RngNormalTestCase, TestCase::QUICK); - AddTestCase(new RngExponentialTestCase, TestCase::QUICK); - AddTestCase(new RngParetoTestCase, TestCase::QUICK); + AddTestCase(new RngUniformTestCase, TestCase::Duration::QUICK); + AddTestCase(new RngNormalTestCase, TestCase::Duration::QUICK); + AddTestCase(new RngExponentialTestCase, TestCase::Duration::QUICK); + AddTestCase(new RngParetoTestCase, TestCase::Duration::QUICK); } static RngTestSuite g_rngTestSuite; //!< Static variable for test initialization diff --git a/src/core/test/simulator-test-suite.cc b/src/core/test/simulator-test-suite.cc index e2ff559693..0f56d30300 100644 --- a/src/core/test/simulator-test-suite.cc +++ b/src/core/test/simulator-test-suite.cc @@ -721,15 +721,15 @@ class SimulatorTestSuite : public TestSuite ObjectFactory factory; factory.SetTypeId(ListScheduler::GetTypeId()); - AddTestCase(new SimulatorEventsTestCase(factory), TestCase::QUICK); + AddTestCase(new SimulatorEventsTestCase(factory), TestCase::Duration::QUICK); factory.SetTypeId(MapScheduler::GetTypeId()); - AddTestCase(new SimulatorEventsTestCase(factory), TestCase::QUICK); + AddTestCase(new SimulatorEventsTestCase(factory), TestCase::Duration::QUICK); factory.SetTypeId(HeapScheduler::GetTypeId()); - AddTestCase(new SimulatorEventsTestCase(factory), TestCase::QUICK); + AddTestCase(new SimulatorEventsTestCase(factory), TestCase::Duration::QUICK); factory.SetTypeId(CalendarScheduler::GetTypeId()); - AddTestCase(new SimulatorEventsTestCase(factory), TestCase::QUICK); + AddTestCase(new SimulatorEventsTestCase(factory), TestCase::Duration::QUICK); factory.SetTypeId(PriorityQueueScheduler::GetTypeId()); - AddTestCase(new SimulatorEventsTestCase(factory), TestCase::QUICK); + AddTestCase(new SimulatorEventsTestCase(factory), TestCase::Duration::QUICK); } }; diff --git a/src/core/test/threaded-test-suite.cc b/src/core/test/threaded-test-suite.cc index da75f31ce8..3490822acf 100644 --- a/src/core/test/threaded-test-suite.cc +++ b/src/core/test/threaded-test-suite.cc @@ -311,7 +311,7 @@ class ThreadedSimulatorTestSuite : public TestSuite factory.SetTypeId(schedulerType); AddTestCase( new ThreadedSimulatorEventsTestCase(factory, simulatorType, threadCount), - TestCase::QUICK); + TestCase::Duration::QUICK); } } } diff --git a/src/core/test/time-test-suite.cc b/src/core/test/time-test-suite.cc index 1b522a3c2e..0e644b96d6 100644 --- a/src/core/test/time-test-suite.cc +++ b/src/core/test/time-test-suite.cc @@ -542,12 +542,12 @@ static class TimeTestSuite : public TestSuite { public: TimeTestSuite() - : TestSuite("time", UNIT) + : TestSuite("time", Type::UNIT) { - AddTestCase(new TimeWithSignTestCase(), TestCase::QUICK); - AddTestCase(new TimeInputOutputTestCase(), TestCase::QUICK); + AddTestCase(new TimeWithSignTestCase(), TestCase::Duration::QUICK); + AddTestCase(new TimeInputOutputTestCase(), TestCase::Duration::QUICK); // This should be last, since it changes the resolution - AddTestCase(new TimeSimpleTestCase(), TestCase::QUICK); + AddTestCase(new TimeSimpleTestCase(), TestCase::Duration::QUICK); } } /** \brief Member variable for time test suite */ diff --git a/src/core/test/timer-test-suite.cc b/src/core/test/timer-test-suite.cc index dd797478d6..3c2df83c1f 100644 --- a/src/core/test/timer-test-suite.cc +++ b/src/core/test/timer-test-suite.cc @@ -229,10 +229,10 @@ class TimerTestSuite : public TestSuite { public: TimerTestSuite() - : TestSuite("timer", UNIT) + : TestSuite("timer", Type::UNIT) { - AddTestCase(new TimerStateTestCase(), TestCase::QUICK); - AddTestCase(new TimerTemplateTestCase(), TestCase::QUICK); + AddTestCase(new TimerStateTestCase(), TestCase::Duration::QUICK); + AddTestCase(new TimerTemplateTestCase(), TestCase::Duration::QUICK); } }; diff --git a/src/core/test/traced-callback-test-suite.cc b/src/core/test/traced-callback-test-suite.cc index ded8f8e063..441225ca2c 100644 --- a/src/core/test/traced-callback-test-suite.cc +++ b/src/core/test/traced-callback-test-suite.cc @@ -145,9 +145,9 @@ class TracedCallbackTestSuite : public TestSuite }; TracedCallbackTestSuite::TracedCallbackTestSuite() - : TestSuite("traced-callback", UNIT) + : TestSuite("traced-callback", Type::UNIT) { - AddTestCase(new BasicTracedCallbackTestCase, TestCase::QUICK); + AddTestCase(new BasicTracedCallbackTestCase, TestCase::Duration::QUICK); } static TracedCallbackTestSuite diff --git a/src/core/test/trickle-timer-test-suite.cc b/src/core/test/trickle-timer-test-suite.cc index b27b8a1901..c3c0b9c532 100644 --- a/src/core/test/trickle-timer-test-suite.cc +++ b/src/core/test/trickle-timer-test-suite.cc @@ -142,6 +142,8 @@ TrickleTimerTestCase::TestSteadyState(Time unit) expirationFrequency.begin()); expirationFrequency.erase(expirationFrequency.begin()); + NS_TEST_ASSERT_MSG_EQ(expirationFrequency.empty(), false, "No expiration frequency"); + int64x64_t min = (*std::min_element(expirationFrequency.begin(), expirationFrequency.end())) / unit; int64x64_t max = diff --git a/src/core/test/tuple-value-test-suite.cc b/src/core/test/tuple-value-test-suite.cc index 2db327dbaf..932444ccbd 100644 --- a/src/core/test/tuple-value-test-suite.cc +++ b/src/core/test/tuple-value-test-suite.cc @@ -321,9 +321,9 @@ class TupleValueTestSuite : public TestSuite }; TupleValueTestSuite::TupleValueTestSuite() - : TestSuite("tuple-value-test-suite", UNIT) + : TestSuite("tuple-value-test-suite", Type::UNIT) { - AddTestCase(new TupleValueTestCase(), TestCase::QUICK); + AddTestCase(new TupleValueTestCase(), TestCase::Duration::QUICK); } static TupleValueTestSuite g_tupleValueTestSuite; //!< Static variable for test initialization diff --git a/src/core/test/type-id-test-suite.cc b/src/core/test/type-id-test-suite.cc index 3f50ffcc3f..265845726b 100644 --- a/src/core/test/type-id-test-suite.cc +++ b/src/core/test/type-id-test-suite.cc @@ -443,7 +443,7 @@ class TypeIdTestSuite : public TestSuite }; TypeIdTestSuite::TypeIdTestSuite() - : TestSuite("type-id", UNIT) + : TestSuite("type-id", Type::UNIT) { // Turn on logging, so we see the result of collisions LogComponentEnable("TypeId", ns3::LogLevel(LOG_ERROR | LOG_PREFIX_FUNC)); @@ -452,9 +452,9 @@ TypeIdTestSuite::TypeIdTestSuite() // UniqueIdTestCase, the artificial collisions added by // CollisionTestCase will show up in the list of TypeIds // as chained. - AddTestCase(new UniqueTypeIdTestCase, QUICK); - AddTestCase(new CollisionTestCase, QUICK); - AddTestCase(new DeprecatedAttributeTestCase, QUICK); + AddTestCase(new UniqueTypeIdTestCase, Duration::QUICK); + AddTestCase(new CollisionTestCase, Duration::QUICK); + AddTestCase(new DeprecatedAttributeTestCase, Duration::QUICK); } /// Static variable for test initialization. @@ -472,9 +472,9 @@ class TypeIdPerformanceSuite : public TestSuite }; TypeIdPerformanceSuite::TypeIdPerformanceSuite() - : TestSuite("type-id-perf", PERFORMANCE) + : TestSuite("type-id-perf", Type::PERFORMANCE) { - AddTestCase(new LookupTimeTestCase, QUICK); + AddTestCase(new LookupTimeTestCase, Duration::QUICK); } /// Static variable for test initialization. diff --git a/src/core/test/val-array-test-suite.cc b/src/core/test/val-array-test-suite.cc index 4c06e34cd5..609217302d 100644 --- a/src/core/test/val-array-test-suite.cc +++ b/src/core/test/val-array-test-suite.cc @@ -22,6 +22,19 @@ #include "ns3/val-array.h" /** + * \defgroup valArray-tests ValArray tests + * \ingroup core-tests + * \ingroup Matrices + */ + +/** + * \file + * \ingroup valArray-tests + * ValArray test suite + */ + +/** + * \file * \ingroup core-tests */ @@ -33,6 +46,8 @@ namespace tests NS_LOG_COMPONENT_DEFINE("ValArrayTest"); /** + * @ingroup valArray-tests + * * @brief ValArray test case for testing ValArray class * * @tparam T the template parameter that can be a complex number, double or int diff --git a/src/csma/model/csma-net-device.cc b/src/csma/model/csma-net-device.cc index 1ce663ab53..a28164089a 100644 --- a/src/csma/model/csma-net-device.cc +++ b/src/csma/model/csma-net-device.cc @@ -912,7 +912,7 @@ Address CsmaNetDevice::GetBroadcast() const { NS_LOG_FUNCTION_NOARGS(); - return Mac48Address("ff:ff:ff:ff:ff:ff"); + return Mac48Address::GetBroadcast(); } bool diff --git a/src/dsdv/examples/dsdv-manet.cc b/src/dsdv/examples/dsdv-manet.cc index 63b6bcca55..0606322c96 100644 --- a/src/dsdv/examples/dsdv-manet.cc +++ b/src/dsdv/examples/dsdv-manet.cc @@ -46,9 +46,13 @@ uint16_t port = 9; NS_LOG_COMPONENT_DEFINE("DsdvManetExample"); /** + * \defgroup dsdv-examples DSDV Examples * \ingroup dsdv - * \ingroup dsdv-examples * \ingroup examples + */ + +/** + * \ingroup dsdv-examples * * \brief DSDV Manet example */ diff --git a/src/dsdv/model/dsdv-rtable.cc b/src/dsdv/model/dsdv-rtable.cc index 7f1f392a71..5e1a58e64a 100644 --- a/src/dsdv/model/dsdv-rtable.cc +++ b/src/dsdv/model/dsdv-rtable.cc @@ -312,7 +312,7 @@ RoutingTable::AnyRunningEvent(Ipv4Address address) return false; } event = i->second; - return event.IsRunning(); + return event.IsPending(); } bool @@ -340,7 +340,7 @@ RoutingTable::DeleteIpv4Event(Ipv4Address address) return false; } event = i->second; - if (event.IsRunning()) + if (event.IsPending()) { return false; } diff --git a/src/dsdv/test/dsdv-testcase.cc b/src/dsdv/test/dsdv-testcase.cc index 508bb82b7d..22a8d457a0 100644 --- a/src/dsdv/test/dsdv-testcase.cc +++ b/src/dsdv/test/dsdv-testcase.cc @@ -218,9 +218,9 @@ class DsdvTestSuite : public TestSuite { public: DsdvTestSuite() - : TestSuite("routing-dsdv", UNIT) + : TestSuite("routing-dsdv", Type::UNIT) { - AddTestCase(new DsdvHeaderTestCase(), TestCase::QUICK); - AddTestCase(new DsdvTableTestCase(), TestCase::QUICK); + AddTestCase(new DsdvHeaderTestCase(), TestCase::Duration::QUICK); + AddTestCase(new DsdvTableTestCase(), TestCase::Duration::QUICK); } } g_dsdvTestSuite; ///< the test suite diff --git a/src/dsr/model/dsr-fs-header.cc b/src/dsr/model/dsr-fs-header.cc index f96ada4a5a..c049216765 100644 --- a/src/dsr/model/dsr-fs-header.cc +++ b/src/dsr/model/dsr-fs-header.cc @@ -34,6 +34,8 @@ #include "ns3/header.h" #include "ns3/log.h" +#include + namespace ns3 { @@ -174,9 +176,9 @@ DsrFsHeader::Deserialize(Buffer::Iterator start) m_destId = i.ReadU16(); m_payloadLen = i.ReadU16(); - uint32_t dataLength = GetPayloadLength(); - uint8_t data[dataLength]; - i.Read(data, dataLength); + const uint32_t dataLength = GetPayloadLength(); + std::vector data(dataLength); + i.Read(data.data(), dataLength); if (dataLength > m_data.GetSize()) { @@ -188,7 +190,7 @@ DsrFsHeader::Deserialize(Buffer::Iterator start) } i = m_data.Begin(); - i.Write(data, dataLength); + i.Write(data.data(), data.size()); return GetSerializedSize(); } @@ -233,11 +235,11 @@ DsrOptionField::Serialize(Buffer::Iterator start) const uint32_t DsrOptionField::Deserialize(Buffer::Iterator start, uint32_t length) { - uint8_t buf[length]; - start.Read(buf, length); + std::vector buf(length); + start.Read(buf.data(), length); m_optionData = Buffer(); m_optionData.AddAtEnd(length); - m_optionData.Begin().Write(buf, length); + m_optionData.Begin().Write(buf.data(), buf.size()); return length; } diff --git a/src/dsr/model/dsr-maintain-buff.h b/src/dsr/model/dsr-maintain-buff.h index af60b049ee..2229c2de10 100644 --- a/src/dsr/model/dsr-maintain-buff.h +++ b/src/dsr/model/dsr-maintain-buff.h @@ -477,7 +477,7 @@ class DsrMaintainBuffer /** * Set maintain buffer timeout - * \param t the maintain buffer timeoout + * \param t the maintain buffer timeout */ void SetMaintainBufferTimeout(Time t) { diff --git a/src/dsr/model/dsr-option-header.h b/src/dsr/model/dsr-option-header.h index 19d8fb4748..0e49503d03 100644 --- a/src/dsr/model/dsr-option-header.h +++ b/src/dsr/model/dsr-option-header.h @@ -384,7 +384,7 @@ class DsrOptionRreqHeader : public DsrOptionHeader */ Ipv4Address m_target; /** - * Ipv4 address to write when desearizing the packet + * Ipv4 address to write when deserializing the packet */ Ipv4Address m_address; /** @@ -673,7 +673,7 @@ class DsrOptionSRHeader : public DsrOptionHeader private: /** - * \brief The ip address header deserilize to + * \brief The ip address header deserialize to */ Ipv4Address m_address; /** @@ -681,7 +681,7 @@ class DsrOptionSRHeader : public DsrOptionHeader */ uint8_t m_segmentsLeft; /** - * \brief Number of savlage times for a packet. + * \brief Number of salvage times for a packet. */ uint8_t m_salvage; /** @@ -821,7 +821,7 @@ class DsrOptionRerrHeader : public DsrOptionHeader */ uint8_t m_errorType; /** - * \brief The salavage field + * \brief The salvage field */ uint8_t m_salvage; /** @@ -976,7 +976,7 @@ class DsrOptionRerrUnreachHeader : public DsrOptionRerrHeader */ uint8_t m_errorType; /** - * \brief The salavage field + * \brief The salvage field */ uint8_t m_salvage; /** @@ -1122,7 +1122,7 @@ class DsrOptionRerrUnsupportedHeader : public DsrOptionRerrHeader */ uint8_t m_errorType; /** - * \brief The salavage field + * \brief The salvage field */ uint8_t m_salvage; /** diff --git a/src/dsr/model/dsr-rcache.cc b/src/dsr/model/dsr-rcache.cc index b4971be601..774721aa6d 100644 --- a/src/dsr/model/dsr-rcache.cc +++ b/src/dsr/model/dsr-rcache.cc @@ -799,7 +799,7 @@ DsrRouteCache::DeleteAllRoutesIncludeLink(Ipv4Address errorSrc, auto i = m_nodeCache.find(errorSrc); if (i == m_nodeCache.end()) { - NS_LOG_LOGIC("Update the node stability unsuccessfuly"); + NS_LOG_LOGIC("Update the node stability unsuccessfully"); } else { @@ -808,7 +808,7 @@ DsrRouteCache::DeleteAllRoutesIncludeLink(Ipv4Address errorSrc, i = m_nodeCache.find(unreachNode); if (i == m_nodeCache.end()) { - NS_LOG_LOGIC("Update the node stability unsuccessfuly"); + NS_LOG_LOGIC("Update the node stability unsuccessfully"); } else { diff --git a/src/dsr/model/dsr-routing.cc b/src/dsr/model/dsr-routing.cc index 38c0d6d08c..a0b230c6f1 100644 --- a/src/dsr/model/dsr-routing.cc +++ b/src/dsr/model/dsr-routing.cc @@ -136,7 +136,7 @@ DsrRouting::GetTypeId() .AddAttribute( "PassiveBuffer", "The passive buffer to manage " - "promisucously received passive ack.", + "promiscuously received passive ack.", PointerValue(nullptr), MakePointerAccessor(&DsrRouting::SetPassiveBuffer, &DsrRouting::GetPassiveBuffer), MakePointerChecker()) @@ -1122,7 +1122,7 @@ DsrRouting::PromiscReceive(Ptr device, /* * Message type 2 means the data packet, we will further process the data * packet for delivery notification, safely ignore control packet - * Another check here is our own address, if this is the data destinated for us, + * Another check here is our own address, if this is the data destined for us, * process it further, otherwise, just ignore it */ Ipv4Address ourAddress = m_ipv4->GetAddress(1, 0).GetLocal(); diff --git a/src/dsr/model/dsr-rreq-table.h b/src/dsr/model/dsr-rreq-table.h index 15b702d853..e4fe2ed0a3 100644 --- a/src/dsr/model/dsr-rreq-table.h +++ b/src/dsr/model/dsr-rreq-table.h @@ -373,7 +373,7 @@ class DsrRreqTable : public Object Time MaxRequestPeriod; /// The original request period Time RequestPeriod; - /// The non-propagaton request timeout + /// The non-propagation request timeout Time NonpropRequestTimeout; /// The source route entry expire time Time m_rreqEntryExpire; diff --git a/src/dsr/test/dsr-test-suite.cc b/src/dsr/test/dsr-test-suite.cc index c77877f471..f469372eb4 100644 --- a/src/dsr/test/dsr-test-suite.cc +++ b/src/dsr/test/dsr-test-suite.cc @@ -630,16 +630,16 @@ class DsrTestSuite : public TestSuite { public: DsrTestSuite() - : TestSuite("routing-dsr", UNIT) + : TestSuite("routing-dsr", Type::UNIT) { - AddTestCase(new DsrFsHeaderTest, TestCase::QUICK); - AddTestCase(new DsrRreqHeaderTest, TestCase::QUICK); - AddTestCase(new DsrRrepHeaderTest, TestCase::QUICK); - AddTestCase(new DsrSRHeaderTest, TestCase::QUICK); - AddTestCase(new DsrRerrHeaderTest, TestCase::QUICK); - AddTestCase(new DsrAckReqHeaderTest, TestCase::QUICK); - AddTestCase(new DsrAckHeaderTest, TestCase::QUICK); - AddTestCase(new DsrCacheEntryTest, TestCase::QUICK); - AddTestCase(new DsrSendBuffTest, TestCase::QUICK); + AddTestCase(new DsrFsHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new DsrRreqHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new DsrRrepHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new DsrSRHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new DsrRerrHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new DsrAckReqHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new DsrAckHeaderTest, TestCase::Duration::QUICK); + AddTestCase(new DsrCacheEntryTest, TestCase::Duration::QUICK); + AddTestCase(new DsrSendBuffTest, TestCase::Duration::QUICK); } } g_dsrTestSuite; diff --git a/src/energy/doc/energy.rst b/src/energy/doc/energy.rst index 74cb35adae..ea2daf1401 100644 --- a/src/energy/doc/energy.rst +++ b/src/energy/doc/energy.rst @@ -41,7 +41,7 @@ Energy Source Models An energy source represents a power supply. In |ns3|, nodes can have one or more energy sources. Likewise, energy sources can be -connected to multiple energy consuption models (Device energy models). +connected to multiple energy consumption models (Device energy models). Connecting an energy source to a device energy model implies that the corresponding device draws power from the source. When energy is completely drained from the energy source, it notifies to the device energy models on @@ -67,11 +67,11 @@ Harvester update triggers an update to the connected Energy Source. The ``EnergySource`` base class keeps a list of devices (``DeviceEnergyModel`` objects) and energy harvesters (``EnergyHarvester`` objects) that are using the particular Energy Source as power supply. When energy is completely drained, the Energy Source will notify all devices on this list. Each device can then handle this event independently, based on the desired behavior that should be followed in case of power outage. -Generic Batttery Model -###################### +Generic Battery Model +##################### The Generic battery model is able to represent 4 basic types of batteries -chemestries: Lithium-Ion (LiIon) or Lithium Polymer (LiPo), Nickel Cadmium (NiCd), +chemistries: Lithium-Ion (LiIon) or Lithium Polymer (LiPo), Nickel Cadmium (NiCd), Lead Acid, and Nickel-metal hydride (NiMH). The main difference between these batteries is the shape of the discharge curves when using constant discharge current and that NiCd and NiMh batteries hysteresis phenomenon is also modeled. Peurket effect, aging, @@ -81,10 +81,10 @@ arqueotipes must be chosen. The Generic Battery Model is directly based by the works of Trembley et al. Tremblay's model on itself is based on a popular battery model created by Shepherd. -Tremblay's model consist in visually identify a set of points from batteries manufacters' +Tremblay's model consist in visually identify a set of points from batteries manufacturers' discharge curves datasheets. -.. _fig-energyFramework: +.. _fig-dischargeCurve: .. figure:: figures/dischargeCurve.* @@ -108,7 +108,7 @@ Additionally, it is also necessary to set the values of: * :math:`cutoffVoltage:` Required if we desired to inform connected energy consumption models that the battery has reached its discharged point. * :math:`i:` The discharge current used to discharge the battery. This value is provided by the energy consumption model attached to the battery. -The value of :math:`R` is typically included in the datatsheets, however, because :math:`R` variability is not modeled in |ns3| (The resistance is fixed), it is necessary +The value of :math:`R` is typically included in the datasheets, however, because :math:`R` variability is not modeled in |ns3| (The resistance is fixed), it is necessary to discretely adjust its value to obtain the desired discharge curves. The value :math:`i_{typical}` can be obtained by inferring its value from the discharged curves shown in datasheets. When modeling the behavior of a new battery, it is important to chose values that satisfies more than one curve, @@ -285,7 +285,7 @@ object. **Generic Battery Model Helper:** The ``GenericBatteryModelHelper`` can be used to easily install an energy source into a -node or node container of one of four types of chemestries (Li-Ion,Lead Acid, NiCd,NiMH). +node or node container of one of four types of chemistries (Li-Ion,Lead Acid, NiCd,NiMH). Users must use one of the available presets that represent an specific battery. .. sourcecode:: cpp @@ -395,7 +395,7 @@ The following tests have been written, which can be found in ``src/energy/tests/ Validation ********** -The RV battery model is validated by comparing results with what was presented in the original RV battery model paper. The generic battery model is validated by superimposing the obtained discharge curves with manufacters's datasheets plots. The following shows the results of the ``generic-battery-discharge-example.cc`` superimposed to manufacter's datasheets charts: +The RV battery model is validated by comparing results with what was presented in the original RV battery model paper. The generic battery model is validated by superimposing the obtained discharge curves with manufacturer's datasheets plots. The following shows the results of the ``generic-battery-discharge-example.cc`` superimposed to manufacturer's datasheets charts: .. _fig-leadacid: @@ -436,7 +436,7 @@ Future Work =========== * Support of device energy models for PHY layers (lr-wpan, WiMax, etc) and other pieces of hardware (UAV, sensors, CPU). -* Support for realistical charging batteries in the ``GenericBatteryModule``. +* Support for realistic charging batteries in the ``GenericBatteryModule``. * Support for device capable of charging batteries (e.g. chargers with CCCV capabilities). * Implement an energy harvester that recharges the energy sources according to the power levels defined in a user customizable dataset of real measurements. diff --git a/src/energy/examples/basic-energy-model-test.cc b/src/energy/examples/basic-energy-model-test.cc index 163a2225bb..c19186f1d5 100644 --- a/src/energy/examples/basic-energy-model-test.cc +++ b/src/energy/examples/basic-energy-model-test.cc @@ -34,6 +34,7 @@ #include using namespace ns3; +using namespace ns3::energy; NS_LOG_COMPONENT_DEFINE("BasicEnergyModelTestSuite"); @@ -165,7 +166,10 @@ BasicEnergyUpdateTest::StateSwitchTest(WifiPhyState state) */ // schedule change of state - Simulator::Schedule(Seconds(m_timeS), &WifiRadioEnergyModel::ChangeState, devModel, state); + Simulator::Schedule(Seconds(m_timeS), + &WifiRadioEnergyModel::ChangeState, + devModel, + static_cast(state)); // Calculate remaining energy at simulation stop time Simulator::Schedule(Seconds(m_timeS * 2), &BasicEnergySource::UpdateEnergySource, source); diff --git a/src/energy/examples/generic-battery-discharge-example.cc b/src/energy/examples/generic-battery-discharge-example.cc index a5a3702a91..43473a8d86 100644 --- a/src/energy/examples/generic-battery-discharge-example.cc +++ b/src/energy/examples/generic-battery-discharge-example.cc @@ -26,6 +26,7 @@ #include using namespace ns3; +using namespace ns3::energy; /** * This example shows the use of batteries in ns-3. @@ -44,8 +45,10 @@ using namespace ns3; * * Plot files are produced as a result of this example. * Graphs can be obtained from the plot using: + * \code{.sh} + $> gnuplot .plt + \endcode * - * $> gnuplot .plt */ Gnuplot battDischPlot1 = Gnuplot("BattDisch1.eps"); diff --git a/src/energy/examples/generic-battery-discharge-example.py b/src/energy/examples/generic-battery-discharge-example.py index 379c564d9b..27aaf39688 100644 --- a/src/energy/examples/generic-battery-discharge-example.py +++ b/src/energy/examples/generic-battery-discharge-example.py @@ -37,27 +37,29 @@ def main(argv): argv: System parameters to use if necessary """ - ns.core.LogComponentEnable("GenericBatteryModel", ns.core.LOG_LEVEL_DEBUG) + ns.LogComponentEnable("GenericBatteryModel", ns.LOG_LEVEL_DEBUG) - node = ns.network.Node() - batteryHelper = ns.energy.GenericBatteryModelHelper() - batteryModel = ns.CreateObject("GenericBatteryModel") + node = ns.Node() + batteryHelper = ns.GenericBatteryModelHelper() + batteryModel = ns.CreateObject[ns.energy.GenericBatteryModel]() devicesEnergyModel = ns.energy.SimpleDeviceEnergyModel() - batteryModel.SetAttribute("FullVoltage", ns.core.DoubleValue(1.39)) # Vfull - batteryModel.SetAttribute("MaxCapacity", ns.core.DoubleValue(7.0)) # Q + batteryModel.SetAttribute("FullVoltage", ns.DoubleValue(1.39)) # Vfull + batteryModel.SetAttribute("MaxCapacity", ns.DoubleValue(7.0)) # Q - batteryModel.SetAttribute("NominalVoltage", ns.core.DoubleValue(1.18)) # Vnom - batteryModel.SetAttribute("NominalCapacity", ns.core.DoubleValue(6.25)) # QNom + batteryModel.SetAttribute("NominalVoltage", ns.DoubleValue(1.18)) # Vnom + batteryModel.SetAttribute("NominalCapacity", ns.DoubleValue(6.25)) # QNom - batteryModel.SetAttribute("ExponentialVoltage", ns.core.DoubleValue(1.28)) # Vexp - batteryModel.SetAttribute("ExponentialCapacity", ns.core.DoubleValue(1.3)) # Qexp + batteryModel.SetAttribute("ExponentialVoltage", ns.DoubleValue(1.28)) # Vexp + batteryModel.SetAttribute("ExponentialCapacity", ns.DoubleValue(1.3)) # Qexp - batteryModel.SetAttribute("InternalResistance", ns.core.DoubleValue(0.0046)) # R - batteryModel.SetAttribute("TypicalDischargeCurrent", ns.core.DoubleValue(1.3)) # i typical - batteryModel.SetAttribute("CutoffVoltage", ns.core.DoubleValue(1.0)) # End of charge. + batteryModel.SetAttribute("InternalResistance", ns.DoubleValue(0.0046)) # R + batteryModel.SetAttribute("TypicalDischargeCurrent", ns.DoubleValue(1.3)) # i typical + batteryModel.SetAttribute("CutoffVoltage", ns.DoubleValue(1.0)) # End of charge. - batteryModel.SetAttribute("BatteryType", ns.core.EnumValue(ns.NIMH_NICD)) # Battery type + batteryModel.SetAttribute( + "BatteryType", ns.EnumValue[ns.energy.GenericBatteryType](ns.energy.NIMH_NICD) + ) # Battery type devicesEnergyModel.SetEnergySource(batteryModel) batteryModel.AppendDeviceEnergyModel(devicesEnergyModel) @@ -65,9 +67,9 @@ def main(argv): devicesEnergyModel.SetCurrentA(6.5) - ns.core.Simulator.Stop(ns.core.Seconds(3600)) - ns.core.Simulator.Run() - ns.core.Simulator.Destroy() + ns.Simulator.Stop(ns.Seconds(3600)) + ns.Simulator.Run() + ns.Simulator.Destroy() if __name__ == "__main__": diff --git a/src/energy/examples/generic-battery-wifiradio-example.cc b/src/energy/examples/generic-battery-wifiradio-example.cc index 2075676f2f..f4985c465e 100644 --- a/src/energy/examples/generic-battery-wifiradio-example.cc +++ b/src/energy/examples/generic-battery-wifiradio-example.cc @@ -48,6 +48,7 @@ #include using namespace ns3; +using namespace ns3::energy; NS_LOG_COMPONENT_DEFINE("GenericBatteryWifiRadioExample"); diff --git a/src/energy/examples/li-ion-energy-source-example.cc b/src/energy/examples/li-ion-energy-source-example.cc index f3c02f01e0..d2d01b0d10 100644 --- a/src/energy/examples/li-ion-energy-source-example.cc +++ b/src/energy/examples/li-ion-energy-source-example.cc @@ -25,6 +25,7 @@ #include "ns3/simulator.h" using namespace ns3; +using namespace ns3::energy; /** * In this simple example, we show how to create and drain energy from a diff --git a/src/energy/examples/rv-battery-model-test.cc b/src/energy/examples/rv-battery-model-test.cc index 051bc00491..fee226d5fa 100644 --- a/src/energy/examples/rv-battery-model-test.cc +++ b/src/energy/examples/rv-battery-model-test.cc @@ -35,6 +35,7 @@ #include using namespace ns3; +using namespace ns3::energy; NS_LOG_COMPONENT_DEFINE("RvBatteryModelTestSuite"); diff --git a/src/energy/helper/basic-energy-harvester-helper.cc b/src/energy/helper/basic-energy-harvester-helper.cc index 7b8c18122c..d311b2d5a3 100644 --- a/src/energy/helper/basic-energy-harvester-helper.cc +++ b/src/energy/helper/basic-energy-harvester-helper.cc @@ -40,14 +40,15 @@ BasicEnergyHarvesterHelper::Set(std::string name, const AttributeValue& v) m_basicEnergyHarvester.Set(name, v); } -Ptr -BasicEnergyHarvesterHelper::DoInstall(Ptr source) const +Ptr +BasicEnergyHarvesterHelper::DoInstall(Ptr source) const { NS_ASSERT(source); Ptr node = source->GetNode(); // Create a new Basic Energy Harvester - Ptr harvester = m_basicEnergyHarvester.Create(); + Ptr harvester = + m_basicEnergyHarvester.Create(); NS_ASSERT(harvester); // Connect the Basic Energy Harvester to the Energy Source diff --git a/src/energy/helper/basic-energy-harvester-helper.h b/src/energy/helper/basic-energy-harvester-helper.h index 9cdae54901..da044a1ebd 100644 --- a/src/energy/helper/basic-energy-harvester-helper.h +++ b/src/energy/helper/basic-energy-harvester-helper.h @@ -42,7 +42,7 @@ class BasicEnergyHarvesterHelper : public EnergyHarvesterHelper void Set(std::string name, const AttributeValue& v) override; private: - Ptr DoInstall(Ptr source) const override; + Ptr DoInstall(Ptr source) const override; private: ObjectFactory m_basicEnergyHarvester; //!< Energy source factory diff --git a/src/energy/helper/basic-energy-source-helper.cc b/src/energy/helper/basic-energy-source-helper.cc index 831e3c048d..e2efaf91c7 100644 --- a/src/energy/helper/basic-energy-source-helper.cc +++ b/src/energy/helper/basic-energy-source-helper.cc @@ -39,11 +39,11 @@ BasicEnergySourceHelper::Set(std::string name, const AttributeValue& v) m_basicEnergySource.Set(name, v); } -Ptr +Ptr BasicEnergySourceHelper::DoInstall(Ptr node) const { NS_ASSERT(node); - Ptr source = m_basicEnergySource.Create(); + Ptr source = m_basicEnergySource.Create(); NS_ASSERT(source); source->SetNode(node); return source; diff --git a/src/energy/helper/basic-energy-source-helper.h b/src/energy/helper/basic-energy-source-helper.h index d998bff859..e9fa8d04af 100644 --- a/src/energy/helper/basic-energy-source-helper.h +++ b/src/energy/helper/basic-energy-source-helper.h @@ -41,7 +41,7 @@ class BasicEnergySourceHelper : public EnergySourceHelper void Set(std::string name, const AttributeValue& v) override; private: - Ptr DoInstall(Ptr node) const override; + Ptr DoInstall(Ptr node) const override; private: ObjectFactory m_basicEnergySource; //!< Energy source factory diff --git a/src/energy/helper/energy-harvester-container.cc b/src/energy/helper/energy-harvester-container.cc index b7bce1ae9e..4eb57cbd49 100644 --- a/src/energy/helper/energy-harvester-container.cc +++ b/src/energy/helper/energy-harvester-container.cc @@ -25,9 +25,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("EnergyHarvesterContainer"); - NS_OBJECT_ENSURE_REGISTERED(EnergyHarvesterContainer); TypeId @@ -160,4 +161,5 @@ EnergyHarvesterContainer::DoInitialize() } } +} // namespace energy } // namespace ns3 diff --git a/src/energy/helper/energy-harvester-container.h b/src/energy/helper/energy-harvester-container.h index 3e4aa72a1e..3b40b05342 100644 --- a/src/energy/helper/energy-harvester-container.h +++ b/src/energy/helper/energy-harvester-container.h @@ -29,6 +29,8 @@ namespace ns3 { +namespace energy +{ class EnergyHarvester; @@ -188,6 +190,7 @@ class EnergyHarvesterContainer : public Object std::vector> m_harvesters; //!< Harvester container }; +} // namespace energy } // namespace ns3 #endif /* defined(ENERGY_HARVESTER_CONTAINER_H) */ diff --git a/src/energy/helper/energy-harvester-helper.cc b/src/energy/helper/energy-harvester-helper.cc index 35c269e161..a8514746df 100644 --- a/src/energy/helper/energy-harvester-helper.cc +++ b/src/energy/helper/energy-harvester-helper.cc @@ -33,32 +33,32 @@ EnergyHarvesterHelper::~EnergyHarvesterHelper() { } -EnergyHarvesterContainer -EnergyHarvesterHelper::Install(Ptr source) const +energy::EnergyHarvesterContainer +EnergyHarvesterHelper::Install(Ptr source) const { - return Install(EnergySourceContainer(source)); + return Install(energy::EnergySourceContainer(source)); } -EnergyHarvesterContainer -EnergyHarvesterHelper::Install(EnergySourceContainer sourceContainer) const +energy::EnergyHarvesterContainer +EnergyHarvesterHelper::Install(energy::EnergySourceContainer sourceContainer) const { - EnergyHarvesterContainer container; + energy::EnergyHarvesterContainer container; for (auto i = sourceContainer.Begin(); i != sourceContainer.End(); ++i) { - Ptr harvester = DoInstall(*i); + Ptr harvester = DoInstall(*i); container.Add(harvester); Ptr node = (*i)->GetNode(); /* * Check if EnergyHarvesterContainer is already aggregated to target node. If * not, create a new EnergyHarvesterContainer and aggregate it to the node. */ - Ptr EnergyHarvesterContainerOnNode = - node->GetObject(); + Ptr EnergyHarvesterContainerOnNode = + node->GetObject(); if (!EnergyHarvesterContainerOnNode) { ObjectFactory fac; fac.SetTypeId("ns3::EnergyHarvesterContainer"); - EnergyHarvesterContainerOnNode = fac.Create(); + EnergyHarvesterContainerOnNode = fac.Create(); EnergyHarvesterContainerOnNode->Add(harvester); node->AggregateObject(EnergyHarvesterContainerOnNode); } @@ -70,10 +70,10 @@ EnergyHarvesterHelper::Install(EnergySourceContainer sourceContainer) const return container; } -EnergyHarvesterContainer +energy::EnergyHarvesterContainer EnergyHarvesterHelper::Install(std::string sourceName) const { - Ptr source = Names::Find(sourceName); + Ptr source = Names::Find(sourceName); return Install(source); } diff --git a/src/energy/helper/energy-harvester-helper.h b/src/energy/helper/energy-harvester-helper.h index 3f2c57698e..dbee2faf8c 100644 --- a/src/energy/helper/energy-harvester-helper.h +++ b/src/energy/helper/energy-harvester-helper.h @@ -60,7 +60,7 @@ class EnergyHarvesterHelper * * This function installs an EnergyHarvester onto an energy source. */ - EnergyHarvesterContainer Install(Ptr source) const; + energy::EnergyHarvesterContainer Install(Ptr source) const; /** * \param sourceContainer List of nodes where EnergyHarvester will be installed. @@ -68,7 +68,7 @@ class EnergyHarvesterHelper * * This function installs an EnergyHarvester onto a list of energy sources. */ - EnergyHarvesterContainer Install(EnergySourceContainer sourceContainer) const; + energy::EnergyHarvesterContainer Install(energy::EnergySourceContainer sourceContainer) const; /** * \param sourceName Name of node where EnergyHarvester will be installed. @@ -76,7 +76,7 @@ class EnergyHarvesterHelper * * This function installs an EnergyHarvester onto a node. */ - EnergyHarvesterContainer Install(std::string sourceName) const; + energy::EnergyHarvesterContainer Install(std::string sourceName) const; private: /** @@ -88,7 +88,7 @@ class EnergyHarvesterHelper * the installation process (eg. installing EnergyHarvester on set of nodes) is * implemented in the EnergyHarvesterHelper base class. */ - virtual Ptr DoInstall(Ptr source) const = 0; + virtual Ptr DoInstall(Ptr source) const = 0; }; } // namespace ns3 diff --git a/src/energy/helper/energy-model-helper.cc b/src/energy/helper/energy-model-helper.cc index 3803db71b4..48ae9bf63b 100644 --- a/src/energy/helper/energy-model-helper.cc +++ b/src/energy/helper/energy-model-helper.cc @@ -32,31 +32,31 @@ EnergySourceHelper::~EnergySourceHelper() { } -EnergySourceContainer +energy::EnergySourceContainer EnergySourceHelper::Install(Ptr node) const { return Install(NodeContainer(node)); } -EnergySourceContainer +energy::EnergySourceContainer EnergySourceHelper::Install(NodeContainer c) const { - EnergySourceContainer container; + energy::EnergySourceContainer container; for (auto i = c.Begin(); i != c.End(); ++i) { - Ptr src = DoInstall(*i); + Ptr src = DoInstall(*i); container.Add(src); /* * Check if EnergySourceContainer is already aggregated to target node. If * not, create a new EnergySourceContainer and aggregate it to node. */ - Ptr EnergySourceContainerOnNode = - (*i)->GetObject(); + Ptr EnergySourceContainerOnNode = + (*i)->GetObject(); if (!EnergySourceContainerOnNode) { ObjectFactory fac; fac.SetTypeId("ns3::EnergySourceContainer"); - EnergySourceContainerOnNode = fac.Create(); + EnergySourceContainerOnNode = fac.Create(); EnergySourceContainerOnNode->Add(src); (*i)->AggregateObject(EnergySourceContainerOnNode); } @@ -68,14 +68,14 @@ EnergySourceHelper::Install(NodeContainer c) const return container; } -EnergySourceContainer +energy::EnergySourceContainer EnergySourceHelper::Install(std::string nodeName) const { Ptr node = Names::Find(nodeName); return Install(node); } -EnergySourceContainer +energy::EnergySourceContainer EnergySourceHelper::InstallAll() const { return Install(NodeContainer::GetGlobal()); @@ -88,30 +88,30 @@ DeviceEnergyModelHelper::~DeviceEnergyModelHelper() { } -DeviceEnergyModelContainer -DeviceEnergyModelHelper::Install(Ptr device, Ptr source) const +energy::DeviceEnergyModelContainer +DeviceEnergyModelHelper::Install(Ptr device, Ptr source) const { NS_ASSERT(device); NS_ASSERT(source); // check to make sure source and net device are on the same node NS_ASSERT(device->GetNode() == source->GetNode()); - DeviceEnergyModelContainer container(DoInstall(device, source)); + energy::DeviceEnergyModelContainer container(DoInstall(device, source)); return container; } -DeviceEnergyModelContainer +energy::DeviceEnergyModelContainer DeviceEnergyModelHelper::Install(NetDeviceContainer deviceContainer, - EnergySourceContainer sourceContainer) const + energy::EnergySourceContainer sourceContainer) const { NS_ASSERT(deviceContainer.GetN() <= sourceContainer.GetN()); - DeviceEnergyModelContainer container; + energy::DeviceEnergyModelContainer container; auto dev = deviceContainer.Begin(); auto src = sourceContainer.Begin(); while (dev != deviceContainer.End()) { // check to make sure source and net device are on the same node NS_ASSERT((*dev)->GetNode() == (*src)->GetNode()); - Ptr model = DoInstall(*dev, *src); + Ptr model = DoInstall(*dev, *src); container.Add(model); dev++; src++; diff --git a/src/energy/helper/energy-model-helper.h b/src/energy/helper/energy-model-helper.h index 9eec9ab7b9..6442d83a20 100644 --- a/src/energy/helper/energy-model-helper.h +++ b/src/energy/helper/energy-model-helper.h @@ -62,7 +62,7 @@ class EnergySourceHelper * * This function installs an EnergySource onto a node. */ - EnergySourceContainer Install(Ptr node) const; + energy::EnergySourceContainer Install(Ptr node) const; /** * \param c List of nodes where EnergySource will be installed. @@ -70,7 +70,7 @@ class EnergySourceHelper * * This function installs an EnergySource onto a list of nodes. */ - EnergySourceContainer Install(NodeContainer c) const; + energy::EnergySourceContainer Install(NodeContainer c) const; /** * \param nodeName Name of node where EnergySource will be installed. @@ -78,14 +78,14 @@ class EnergySourceHelper * * This function installs an EnergySource onto a node. */ - EnergySourceContainer Install(std::string nodeName) const; + energy::EnergySourceContainer Install(std::string nodeName) const; /** * \brief This function installs an EnergySource on all nodes in simulation. * * \returns An EnergySourceContainer which contains all the EnergySources. */ - EnergySourceContainer InstallAll() const; + energy::EnergySourceContainer InstallAll() const; private: /** @@ -97,7 +97,7 @@ class EnergySourceHelper * the installation process (eg. installing EnergySource on set of nodes) is * implemented in the EnergySourceHelper base class. */ - virtual Ptr DoInstall(Ptr node) const = 0; + virtual Ptr DoInstall(Ptr node) const = 0; }; /** @@ -132,7 +132,8 @@ class DeviceEnergyModelHelper * Installs an DeviceEnergyModel with a specified EnergySource onto a * xNetDevice. */ - DeviceEnergyModelContainer Install(Ptr device, Ptr source) const; + energy::DeviceEnergyModelContainer Install(Ptr device, + Ptr source) const; /** * \param deviceContainer List of NetDevices to be install DeviceEnergyModel @@ -144,8 +145,8 @@ class DeviceEnergyModelHelper * Installs DeviceEnergyModels with specified EnergySources onto a list of * NetDevices. */ - DeviceEnergyModelContainer Install(NetDeviceContainer deviceContainer, - EnergySourceContainer sourceContainer) const; + energy::DeviceEnergyModelContainer Install(NetDeviceContainer deviceContainer, + energy::EnergySourceContainer sourceContainer) const; private: /** @@ -158,8 +159,8 @@ class DeviceEnergyModelHelper * node. The rest of the installation process (eg. installing EnergySource on * set of nodes) is implemented in the DeviceEnergyModelHelper base class. */ - virtual Ptr DoInstall(Ptr device, - Ptr source) const = 0; + virtual Ptr DoInstall(Ptr device, + Ptr source) const = 0; }; } // namespace ns3 diff --git a/src/energy/helper/energy-source-container.cc b/src/energy/helper/energy-source-container.cc index 9794b146e1..d22e83eddb 100644 --- a/src/energy/helper/energy-source-container.cc +++ b/src/energy/helper/energy-source-container.cc @@ -25,6 +25,8 @@ namespace ns3 { +namespace energy +{ NS_OBJECT_ENSURE_REGISTERED(EnergySourceContainer); @@ -141,4 +143,5 @@ EnergySourceContainer::DoInitialize() } } +} // namespace energy } // namespace ns3 diff --git a/src/energy/helper/energy-source-container.h b/src/energy/helper/energy-source-container.h index d955f57c87..928e932aad 100644 --- a/src/energy/helper/energy-source-container.h +++ b/src/energy/helper/energy-source-container.h @@ -30,6 +30,8 @@ namespace ns3 { +namespace energy +{ /** * \ingroup energy @@ -181,6 +183,7 @@ class EnergySourceContainer : public Object std::vector> m_sources; //!< Energy source container }; +} // namespace energy } // namespace ns3 #endif /* ENERGY_SOURCE_CONTAINER_H */ diff --git a/src/energy/helper/generic-battery-model-helper.cc b/src/energy/helper/generic-battery-model-helper.cc index 285b66d2f0..186cfbd0c5 100644 --- a/src/energy/helper/generic-battery-model-helper.cc +++ b/src/energy/helper/generic-battery-model-helper.cc @@ -37,20 +37,21 @@ GenericBatteryModelHelper::Set(std::string name, const AttributeValue& v) m_batteryModel.Set(name, v); } -Ptr +Ptr GenericBatteryModelHelper::DoInstall(Ptr node) const { NS_ASSERT(node != nullptr); - Ptr energySource = m_batteryModel.Create(); + Ptr energySource = m_batteryModel.Create(); NS_ASSERT(energySource != nullptr); energySource->SetNode(node); return energySource; } -Ptr +Ptr GenericBatteryModelHelper::Install(NodeContainer c) const { - Ptr batteryContainer = CreateObject(); + Ptr batteryContainer = + CreateObject(); for (auto i = c.Begin(); i != c.End(); i++) { batteryContainer->Add(DoInstall(*i)); @@ -58,48 +59,50 @@ GenericBatteryModelHelper::Install(NodeContainer c) const return batteryContainer; } -Ptr -GenericBatteryModelHelper::Install(Ptr node, BatteryModel bm) const +Ptr +GenericBatteryModelHelper::Install(Ptr node, energy::BatteryModel bm) const { NS_ASSERT(node != nullptr); - Ptr energySource = m_batteryModel.Create(); + Ptr energySource = m_batteryModel.Create(); NS_ASSERT(energySource != nullptr); - energySource->SetAttribute("FullVoltage", DoubleValue(g_batteryPreset[bm].vFull)); - energySource->SetAttribute("MaxCapacity", DoubleValue(g_batteryPreset[bm].qMax)); + energySource->SetAttribute("FullVoltage", DoubleValue(energy::g_batteryPreset[bm].vFull)); + energySource->SetAttribute("MaxCapacity", DoubleValue(energy::g_batteryPreset[bm].qMax)); - energySource->SetAttribute("NominalVoltage", DoubleValue(g_batteryPreset[bm].vNom)); - energySource->SetAttribute("NominalCapacity", DoubleValue(g_batteryPreset[bm].qNom)); + energySource->SetAttribute("NominalVoltage", DoubleValue(energy::g_batteryPreset[bm].vNom)); + energySource->SetAttribute("NominalCapacity", DoubleValue(energy::g_batteryPreset[bm].qNom)); - energySource->SetAttribute("ExponentialVoltage", DoubleValue(g_batteryPreset[bm].vExp)); - energySource->SetAttribute("ExponentialCapacity", DoubleValue(g_batteryPreset[bm].qExp)); + energySource->SetAttribute("ExponentialVoltage", DoubleValue(energy::g_batteryPreset[bm].vExp)); + energySource->SetAttribute("ExponentialCapacity", + DoubleValue(energy::g_batteryPreset[bm].qExp)); energySource->SetAttribute("InternalResistance", - DoubleValue(g_batteryPreset[bm].internalResistance)); + DoubleValue(energy::g_batteryPreset[bm].internalResistance)); energySource->SetAttribute("TypicalDischargeCurrent", - DoubleValue(g_batteryPreset[bm].typicalCurrent)); - energySource->SetAttribute("CutoffVoltage", DoubleValue(g_batteryPreset[bm].cuttoffVoltage)); + DoubleValue(energy::g_batteryPreset[bm].typicalCurrent)); + energySource->SetAttribute("CutoffVoltage", + DoubleValue(energy::g_batteryPreset[bm].cuttoffVoltage)); - energySource->SetAttribute("BatteryType", EnumValue(g_batteryPreset[bm].batteryType)); + energySource->SetAttribute("BatteryType", EnumValue(energy::g_batteryPreset[bm].batteryType)); energySource->SetNode(node); return energySource; } -EnergySourceContainer -GenericBatteryModelHelper::Install(NodeContainer c, BatteryModel bm) const +energy::EnergySourceContainer +GenericBatteryModelHelper::Install(NodeContainer c, energy::BatteryModel bm) const { - EnergySourceContainer batteryContainer; + energy::EnergySourceContainer batteryContainer; for (auto i = c.Begin(); i != c.End(); i++) { - Ptr energySource = Install(*i, bm); + Ptr energySource = Install(*i, bm); batteryContainer.Add(energySource); } return batteryContainer; } void -GenericBatteryModelHelper::SetCellPack(Ptr energySource, +GenericBatteryModelHelper::SetCellPack(Ptr energySource, uint8_t series, uint8_t parallel) const { @@ -141,7 +144,7 @@ GenericBatteryModelHelper::SetCellPack(Ptr energySource, } void -GenericBatteryModelHelper::SetCellPack(EnergySourceContainer energySourceContainer, +GenericBatteryModelHelper::SetCellPack(energy::EnergySourceContainer energySourceContainer, uint8_t series, uint8_t parallel) const { diff --git a/src/energy/helper/generic-battery-model-helper.h b/src/energy/helper/generic-battery-model-helper.h index fe6440d3cb..5370724e69 100644 --- a/src/energy/helper/generic-battery-model-helper.h +++ b/src/energy/helper/generic-battery-model-helper.h @@ -55,7 +55,7 @@ class GenericBatteryModelHelper : public EnergySourceHelper * \param c The node container * \returns An EnergySourceContainer which contains all the EnergySources. */ - Ptr Install(NodeContainer c) const; + Ptr Install(NodeContainer c) const; /** * This function installs an energy source (battery) into a node. @@ -64,7 +64,7 @@ class GenericBatteryModelHelper : public EnergySourceHelper * \param bm The battery model that will be install to the node. * \returns A pointer to the energy source object used. */ - Ptr Install(Ptr node, BatteryModel bm) const; + Ptr Install(Ptr node, energy::BatteryModel bm) const; /** * This function installs energy sources in a group of nodes in a @@ -74,7 +74,7 @@ class GenericBatteryModelHelper : public EnergySourceHelper * \param bm The battery model that will be install to the nodes in the node container. * \returns An EnergySourceContainer which contains all the EnergySources. */ - EnergySourceContainer Install(NodeContainer c, BatteryModel bm) const; + energy::EnergySourceContainer Install(NodeContainer c, energy::BatteryModel bm) const; /** * This function takes an existing energy source and transform its values to form @@ -86,7 +86,9 @@ class GenericBatteryModelHelper : public EnergySourceHelper * \param series The number of cells connected in series. * \param parallel The number of cells connected in parallel. */ - void SetCellPack(Ptr energySource, uint8_t series, uint8_t parallel) const; + void SetCellPack(Ptr energySource, + uint8_t series, + uint8_t parallel) const; /** * This function takes an existing energy source container and transform the values @@ -99,7 +101,7 @@ class GenericBatteryModelHelper : public EnergySourceHelper * \param series The number of cells connected in series. * \param parallel The number of cells connected in parallel. */ - void SetCellPack(EnergySourceContainer energySourceContainer, + void SetCellPack(energy::EnergySourceContainer energySourceContainer, uint8_t series, uint8_t parallel) const; @@ -113,7 +115,7 @@ class GenericBatteryModelHelper : public EnergySourceHelper * \param node Pointer to node where the energy source is to be installed. * \returns Pointer to the created EnergySource. */ - Ptr DoInstall(Ptr node) const override; + Ptr DoInstall(Ptr node) const override; private: ObjectFactory m_batteryModel; //!< The energy source (battery) used by this helper. diff --git a/src/energy/helper/li-ion-energy-source-helper.cc b/src/energy/helper/li-ion-energy-source-helper.cc index bd17ca5b98..ddad6caa12 100644 --- a/src/energy/helper/li-ion-energy-source-helper.cc +++ b/src/energy/helper/li-ion-energy-source-helper.cc @@ -41,11 +41,11 @@ LiIonEnergySourceHelper::Set(std::string name, const AttributeValue& v) m_liIonEnergySource.Set(name, v); } -Ptr +Ptr LiIonEnergySourceHelper::DoInstall(Ptr node) const { NS_ASSERT(node); - Ptr source = m_liIonEnergySource.Create(); + Ptr source = m_liIonEnergySource.Create(); NS_ASSERT(source); source->SetNode(node); return source; diff --git a/src/energy/helper/li-ion-energy-source-helper.h b/src/energy/helper/li-ion-energy-source-helper.h index be51676567..31af7dc3fa 100644 --- a/src/energy/helper/li-ion-energy-source-helper.h +++ b/src/energy/helper/li-ion-energy-source-helper.h @@ -43,7 +43,7 @@ class LiIonEnergySourceHelper : public EnergySourceHelper void Set(std::string name, const AttributeValue& v) override; private: - Ptr DoInstall(Ptr node) const override; + Ptr DoInstall(Ptr node) const override; private: ObjectFactory m_liIonEnergySource; //!< LiIon Battery factory diff --git a/src/energy/helper/rv-battery-model-helper.cc b/src/energy/helper/rv-battery-model-helper.cc index 7de2617348..b1ce17841e 100644 --- a/src/energy/helper/rv-battery-model-helper.cc +++ b/src/energy/helper/rv-battery-model-helper.cc @@ -39,11 +39,11 @@ RvBatteryModelHelper::Set(std::string name, const AttributeValue& v) m_rvBatteryModel.Set(name, v); } -Ptr +Ptr RvBatteryModelHelper::DoInstall(Ptr node) const { NS_ASSERT(node); - Ptr source = m_rvBatteryModel.Create(); + Ptr source = m_rvBatteryModel.Create(); NS_ASSERT(source); source->SetNode(node); return source; diff --git a/src/energy/helper/rv-battery-model-helper.h b/src/energy/helper/rv-battery-model-helper.h index 0f09c7120c..d7ac398eda 100644 --- a/src/energy/helper/rv-battery-model-helper.h +++ b/src/energy/helper/rv-battery-model-helper.h @@ -41,7 +41,7 @@ class RvBatteryModelHelper : public EnergySourceHelper void Set(std::string name, const AttributeValue& v) override; private: - Ptr DoInstall(Ptr node) const override; + Ptr DoInstall(Ptr node) const override; private: ObjectFactory m_rvBatteryModel; //!< RV Battery factory diff --git a/src/energy/model/basic-energy-harvester.cc b/src/energy/model/basic-energy-harvester.cc index 89673cebf2..f49f9d5639 100644 --- a/src/energy/model/basic-energy-harvester.cc +++ b/src/energy/model/basic-energy-harvester.cc @@ -29,9 +29,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("BasicEnergyHarvester"); - NS_OBJECT_ENSURE_REGISTERED(BasicEnergyHarvester); TypeId @@ -183,4 +184,5 @@ BasicEnergyHarvester::DoGetPower() const return m_harvestedPower; } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/basic-energy-harvester.h b/src/energy/model/basic-energy-harvester.h index 02267c0583..a5d1e41eef 100644 --- a/src/energy/model/basic-energy-harvester.h +++ b/src/energy/model/basic-energy-harvester.h @@ -33,6 +33,8 @@ namespace ns3 { +namespace energy +{ /** * \ingroup energy @@ -128,6 +130,7 @@ class BasicEnergyHarvester : public EnergyHarvester Time m_harvestedPowerUpdateInterval; //!< harvestable energy update interval }; +} // namespace energy } // namespace ns3 #endif /* defined(BASIC_ENERGY_HARVESTER) */ diff --git a/src/energy/model/basic-energy-source.cc b/src/energy/model/basic-energy-source.cc index fe59345f6e..51f2330363 100644 --- a/src/energy/model/basic-energy-source.cc +++ b/src/energy/model/basic-energy-source.cc @@ -27,9 +27,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("BasicEnergySource"); - NS_OBJECT_ENSURE_REGISTERED(BasicEnergySource); TypeId @@ -231,4 +232,5 @@ BasicEnergySource::CalculateRemainingEnergy() NS_LOG_DEBUG("BasicEnergySource:Remaining energy = " << m_remainingEnergyJ); } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/basic-energy-source.h b/src/energy/model/basic-energy-source.h index de7be94e66..0d59d39ffd 100644 --- a/src/energy/model/basic-energy-source.h +++ b/src/energy/model/basic-energy-source.h @@ -28,6 +28,8 @@ namespace ns3 { +namespace energy +{ /** * \ingroup energy @@ -155,6 +157,7 @@ class BasicEnergySource : public EnergySource Time m_energyUpdateInterval; //!< energy update interval }; +} // namespace energy } // namespace ns3 #endif /* BASIC_ENERGY_SOURCE_H */ diff --git a/src/energy/model/device-energy-model-container.cc b/src/energy/model/device-energy-model-container.cc index a1a5579b6b..e79085f4bf 100644 --- a/src/energy/model/device-energy-model-container.cc +++ b/src/energy/model/device-energy-model-container.cc @@ -26,6 +26,8 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("DeviceEnergyModelContainer"); @@ -119,4 +121,5 @@ DeviceEnergyModelContainer::Clear() m_models.clear(); } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/device-energy-model-container.h b/src/energy/model/device-energy-model-container.h index 3804b4fe1c..0a8f7f8d61 100644 --- a/src/energy/model/device-energy-model-container.h +++ b/src/energy/model/device-energy-model-container.h @@ -29,6 +29,8 @@ namespace ns3 { +namespace energy +{ /** * \ingroup energy @@ -173,6 +175,7 @@ class DeviceEnergyModelContainer std::vector> m_models; //!< Container of Energy models }; +} // namespace energy } // namespace ns3 #endif /* DEVICE_ENERGY_MODEL_CONTAINER_H */ diff --git a/src/energy/model/device-energy-model.cc b/src/energy/model/device-energy-model.cc index 5f083ebcb7..abdf71f26c 100644 --- a/src/energy/model/device-energy-model.cc +++ b/src/energy/model/device-energy-model.cc @@ -23,9 +23,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("DeviceEnergyModel"); - NS_OBJECT_ENSURE_REGISTERED(DeviceEnergyModel); TypeId @@ -63,4 +64,5 @@ DeviceEnergyModel::DoGetCurrentA() const return 0.0; } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/device-energy-model.h b/src/energy/model/device-energy-model.h index 5312205cca..4bb625cb3c 100644 --- a/src/energy/model/device-energy-model.h +++ b/src/energy/model/device-energy-model.h @@ -27,6 +27,8 @@ namespace ns3 { +namespace energy +{ class EnergySource; @@ -121,6 +123,7 @@ class DeviceEnergyModel : public Object virtual double DoGetCurrentA() const; }; +} // namespace energy } // namespace ns3 #endif /* DEVICE_ENERGY_MODEL_H */ diff --git a/src/energy/model/energy-harvester.cc b/src/energy/model/energy-harvester.cc index 1a050aad1b..b93f713c01 100644 --- a/src/energy/model/energy-harvester.cc +++ b/src/energy/model/energy-harvester.cc @@ -24,9 +24,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("EnergyHarvester"); - NS_OBJECT_ENSURE_REGISTERED(EnergyHarvester); TypeId @@ -100,4 +101,5 @@ EnergyHarvester::DoGetPower() const return 0.0; } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/energy-harvester.h b/src/energy/model/energy-harvester.h index 0bb0e22af7..2c8ae416a7 100644 --- a/src/energy/model/energy-harvester.h +++ b/src/energy/model/energy-harvester.h @@ -32,6 +32,8 @@ namespace ns3 { +namespace energy +{ class EnergySource; @@ -130,6 +132,7 @@ class EnergyHarvester : public Object protected: }; +} // namespace energy } // namespace ns3 #endif /* defined(ENERGY_HARVESTER_H) */ diff --git a/src/energy/model/energy-source.cc b/src/energy/model/energy-source.cc index ba517a9e36..e64d60e110 100644 --- a/src/energy/model/energy-source.cc +++ b/src/energy/model/energy-source.cc @@ -28,9 +28,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("EnergySource"); - NS_OBJECT_ENSURE_REGISTERED(EnergySource); TypeId @@ -237,4 +238,5 @@ EnergySource::BreakDeviceEnergyModelRefCycle() m_node = nullptr; } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/energy-source.h b/src/energy/model/energy-source.h index 3f0c2ea9c2..316ced0952 100644 --- a/src/energy/model/energy-source.h +++ b/src/energy/model/energy-source.h @@ -35,6 +35,10 @@ namespace ns3 { +namespace energy +{ + +class EnergyHarvester; /** * \defgroup energy Energy Models @@ -80,9 +84,6 @@ namespace ns3 * energy in different units (eg. kWh), a simple converter function should * suffice. */ - -class EnergyHarvester; - class EnergySource : public Object { public: @@ -253,6 +254,7 @@ class EnergySource : public Object void BreakDeviceEnergyModelRefCycle(); }; +} // namespace energy } // namespace ns3 #endif /* ENERGY_SOURCE_H */ diff --git a/src/energy/model/generic-battery-model.cc b/src/energy/model/generic-battery-model.cc index cbf5236080..628181ed79 100644 --- a/src/energy/model/generic-battery-model.cc +++ b/src/energy/model/generic-battery-model.cc @@ -32,9 +32,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("GenericBatteryModel"); - NS_OBJECT_ENSURE_REGISTERED(GenericBatteryModel); TypeId @@ -86,7 +87,7 @@ GenericBatteryModel::GetTypeId() MakeDoubleAccessor(&GenericBatteryModel::m_internalResistance), MakeDoubleChecker()) .AddAttribute("TypicalDischargeCurrent", - "Typical discharge current used in manufacters datasheets (A)", + "Typical discharge current used in manufacturers datasheets (A)", DoubleValue(2.33), MakeDoubleAccessor(&GenericBatteryModel::m_typicalCurrent), MakeDoubleChecker()) @@ -435,4 +436,5 @@ GenericBatteryModel::GetVoltage(double i) return V; } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/generic-battery-model.h b/src/energy/model/generic-battery-model.h index 61731f52ca..6b922a554f 100644 --- a/src/energy/model/generic-battery-model.h +++ b/src/energy/model/generic-battery-model.h @@ -31,6 +31,8 @@ namespace ns3 { +namespace energy +{ /** * \ingroup energy @@ -309,6 +311,7 @@ class GenericBatteryModel : public EnergySource GenericBatteryType m_batteryType; //!< Indicates the battery type used by the model }; +} // namespace energy } // namespace ns3 #endif /* GENERIC_BATTERY_MODEL_H */ diff --git a/src/energy/model/li-ion-energy-source.cc b/src/energy/model/li-ion-energy-source.cc index 7fadef39a8..2d201a5c61 100644 --- a/src/energy/model/li-ion-energy-source.cc +++ b/src/energy/model/li-ion-energy-source.cc @@ -29,9 +29,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("LiIonEnergySource"); - NS_OBJECT_ENSURE_REGISTERED(LiIonEnergySource); TypeId @@ -317,4 +318,5 @@ LiIonEnergySource::GetVoltage(double i) const return V; } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/li-ion-energy-source.h b/src/energy/model/li-ion-energy-source.h index 4dd01bcc23..d54b2a0154 100644 --- a/src/energy/model/li-ion-energy-source.h +++ b/src/energy/model/li-ion-energy-source.h @@ -29,6 +29,8 @@ namespace ns3 { +namespace energy +{ /** * \ingroup energy @@ -215,6 +217,7 @@ class LiIonEnergySource : public EnergySource double m_minVoltTh; //!< minimum threshold voltage to consider the battery depleted }; +} // namespace energy } // namespace ns3 #endif /* LI_ION_ENERGY_SOURCE_H */ diff --git a/src/energy/model/rv-battery-model.cc b/src/energy/model/rv-battery-model.cc index 444bff66b3..7ece151298 100644 --- a/src/energy/model/rv-battery-model.cc +++ b/src/energy/model/rv-battery-model.cc @@ -29,9 +29,10 @@ namespace ns3 { +namespace energy +{ NS_LOG_COMPONENT_DEFINE("RvBatteryModel"); - NS_OBJECT_ENSURE_REGISTERED(RvBatteryModel); TypeId @@ -379,4 +380,5 @@ RvBatteryModel::RvModelAFunction(Time t, Time sk, Time sk_1, double beta) return delta + 2 * sum; } +} // namespace energy } // namespace ns3 diff --git a/src/energy/model/rv-battery-model.h b/src/energy/model/rv-battery-model.h index f06b33afa8..7eb8bc946e 100644 --- a/src/energy/model/rv-battery-model.h +++ b/src/energy/model/rv-battery-model.h @@ -28,6 +28,8 @@ namespace ns3 { +namespace energy +{ /** * \ingroup energy @@ -263,6 +265,7 @@ class RvBatteryModel : public EnergySource TracedValue