diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..b75e1ba38 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# Makefile wrapper for waf + +all: + ./waf + +# free free to change this part to suit your requirements +configure: + ./waf configure --enable-examples --enable-tests + +build: + ./waf build + +install: + ./waf install + +clean: + ./waf clean + +distclean: + ./waf distclean diff --git a/doc/doxygen.warnings.report.sh b/doc/doxygen.warnings.report.sh index 45dd116bc..7865fd5c8 100755 --- a/doc/doxygen.warnings.report.sh +++ b/doc/doxygen.warnings.report.sh @@ -2,7 +2,7 @@ # Process doxygen.warnings.log to generate sorted list of top offenders -# Flag to skip running doxygen +# Flag to skip the build and running doxygen, and just analyze the log skipdoxy=${1:-""} DIR=`dirname $0` diff --git a/doc/manual/source/attributes.rst b/doc/manual/source/attributes.rst index 3c3472280..ee2e65557 100644 --- a/doc/manual/source/attributes.rst +++ b/doc/manual/source/attributes.rst @@ -1,4 +1,6 @@ .. include:: replace.txt +.. highlight:: cpp + .. _Attributes: @@ -405,7 +407,9 @@ Object Name Service-based access Another way to get at the attribute is to use the object name service facility. Here, this attribute is found using a name string. This approach is useful if one doesn't have access to the underlying pointers and it is difficult to -determine the required concrete configuration namespaced path.:: +determine the required concrete configuration namespaced path. + +:: Names::Add ("server", serverNode); Names::Add ("server/eth0", serverDevice); @@ -414,7 +418,7 @@ determine the required concrete configuration namespaced path.:: Config::Set ("/Names/server/eth0/TxQueue/MaxPackets", UintegerValue (25)); -:ref:`Object-names` for a fuller treatment of the |ns3| configuration namespace. +See :ref:`Object-names` for a fuller treatment of the |ns3| configuration namespace. Setting through constructors helper classes +++++++++++++++++++++++++++++++++++++++++++ @@ -737,7 +741,9 @@ The example shows::: Simulator::Destroy (); -After running, you can open the output-attributes.txt file and see::: +After running, you can open the output-attributes.txt file and see: + +.. sourcecode:: text default ns3::RealtimeSimulatorImpl::SynchronizationMode "BestEffort" default ns3::RealtimeSimulatorImpl::HardLimit "+100000000.0ns" @@ -769,7 +775,9 @@ are recorded. Finally, the value of the instance of A that was rooted in the configuration namespace is shown. In a real ns-3 program, many more models, attributes, and defaults would be shown. -An XML version also exists in ``output-attributes.xml``::: +An XML version also exists in ``output-attributes.xml``: + +.. sourcecode:: xml @@ -858,13 +866,17 @@ in the `|ns3| Overview `_ presentation. To use this feature, one must install libgtk and libgtk-dev; an example -Ubuntu installation command is::: +Ubuntu installation command is: - sudo apt-get install libgtk2.0-0 libgtk2.0-dev +.. sourcecode:: bash -To check whether it is configured or not, check the output of the step::: + $ sudo apt-get install libgtk2.0-0 libgtk2.0-dev - ./waf configure --enable-examples --enable-tests +To check whether it is configured or not, check the output of the step: + +.. sourcecode:: bash + + $ ./waf configure --enable-examples --enable-tests ---- Summary of optional NS-3 features: Python Bindings : enabled @@ -873,10 +885,12 @@ To check whether it is configured or not, check the output of the step::: GtkConfigStore : not enabled (library 'gtk+-2.0 >= 2.12' not found) In the above example, it was not enabled, so it cannot be used until a suitable -version is installed and:: +version is installed and: - ./waf configure --enable-examples --enable-tests - ./waf +.. sourcecode:: bash + + $ ./waf configure --enable-examples --enable-tests + $ ./waf is rerun. @@ -895,6 +909,7 @@ when you are done. Future work +++++++++++ There are a couple of possible improvements: + * save a unique version number with date and time at start of file * save rng initial seed somewhere. * make each RandomVariable serialize its own initial seed and re-read it later diff --git a/doc/manual/source/callbacks.rst b/doc/manual/source/callbacks.rst index 6436fcf21..30b4e4de6 100644 --- a/doc/manual/source/callbacks.rst +++ b/doc/manual/source/callbacks.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Callbacks --------- @@ -364,11 +365,11 @@ Now, we need to tie together this callback instance and the actual target functi callback-- this is important. We can pass in any such properly-typed function to this callback. Let's look at this more closely:: - static double CbOne (double a, double b) {} - ^ ^ ^ - | ---| ------| - | | | - Callback one; + static double CbOne (double a, double b) {} + ^ ^ ^ + | | | + | | | + Callback one; You can only bind a function to a callback if they have the matching signature. The first template argument is the return type, and the additional template diff --git a/doc/manual/source/conf.py b/doc/manual/source/conf.py index 884b84716..065e8edef 100644 --- a/doc/manual/source/conf.py +++ b/doc/manual/source/conf.py @@ -197,7 +197,7 @@ latex_logo = '../../ns3_html_theme/static/ns-3.png' #latex_show_urls = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +latex_preamble = '\usepackage{amssymb}' # Documents to append as an appendix to all manuals. #latex_appendices = [] diff --git a/doc/manual/source/enable-modules.rst b/doc/manual/source/enable-modules.rst index d7fd025e2..e395acb97 100644 --- a/doc/manual/source/enable-modules.rst +++ b/doc/manual/source/enable-modules.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: bash Enabling Subsets of |ns3| Modules --------------------------------- @@ -10,11 +11,15 @@ This chapter discusses how to enable only the |ns3| modules that you are interst How to enable a subset of |ns3|'s modules ***************************************** -If shared libraries are being built, then enabling a module will cause at least one library to be built: :: +If shared libraries are being built, then enabling a module will cause at least one library to be built: + +.. sourcecode:: text libns3-modulename.so -If the module has a test library and test libraries are being built, then :: +If the module has a test library and test libraries are being built, then + +.. sourcecode:: text libns3-modulename-test.so @@ -31,29 +36,37 @@ Enable modules using waf's --enable-modules option To enable only the core module with example and tests, for example, try these commands: :: - ./waf clean - ./waf configure --enable-examples --enable-tests --enable-modules=core - ./waf build - cd build/debug/ - ls + $ ./waf clean + $ ./waf configure --enable-examples --enable-tests --enable-modules=core + $ ./waf build + $ cd build/debug/ + $ ls -and the following libraries should be present: :: +and the following libraries should be present: + +.. sourcecode:: text bindings libns3-core.so ns3 scratch utils examples libns3-core-test.so samples src Note the ``./waf clean`` step is done here only to make it more obvious which module libraries were built. You don't have to do ``./waf clean`` in order to enable subsets of modules. -Running test.py will cause only those tests that depend on module core to be run: :: +Running test.py will cause only those tests that depend on module core to be run: +.. sourcecode:: text + 24 of 24 tests passed (24 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) -Repeat the above steps for the "network" module instead of the "core" module, and the following will be built, since network depends on core: :: +Repeat the above steps for the "network" module instead of the "core" module, and the following will be built, since network depends on core: + +.. sourcecode:: text bindings libns3-core.so libns3-network.so ns3 scratch utils examples libns3-core-test.so libns3-network-test.so samples src -Running test.py will cause those tests that depend on only the core and network modules to be run: :: +Running test.py will cause those tests that depend on only the core and network modules to be run: + +.. sourcecode:: text 31 of 31 tests passed (31 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) @@ -74,9 +87,11 @@ The maintained version of the .ns3rc file in the |ns3| source code repository re Assuming that you are in the top level |ns3| directory, you can get a copy of the .ns3rc file that is in the ``utils`` directory as follows: :: - cp utils/.ns3rc . + $ cp utils/.ns3rc . -The .ns3rc file should now be in your top level |ns3| directory, and it contains the following: :: +The .ns3rc file should now be in your top level |ns3| directory, and it contains the following: + +.. sourcecode:: python #! /usr/bin/env python @@ -92,7 +107,9 @@ The .ns3rc file should now be in your top level |ns3| directory, and it contains # Set this equal to true if you want tests to be run. tests_enabled = False -Use your favorite editor to modify the .ns3rc file to only enable the core module with examples and tests like this: :: +Use your favorite editor to modify the .ns3rc file to only enable the core module with examples and tests like this: + +.. sourcecode:: python #! /usr/bin/env python @@ -110,28 +127,36 @@ Use your favorite editor to modify the .ns3rc file to only enable the core modul Only the core module will be enabled now if you try these commands: :: - ./waf clean - ./waf configure - ./waf build - cd build/debug/ - ls + $ ./waf clean + $ ./waf configure + $ ./waf build + $ cd build/debug/ + $ ls -and the following libraries should be present: :: +and the following libraries should be present: + +.. sourcecode:: text bindings libns3-core.so ns3 scratch utils examples libns3-core-test.so samples src Note the ``./waf clean`` step is done here only to make it more obvious which module libraries were built. You don't have to do ``./waf clean`` in order to enable subsets of modules. -Running test.py will cause only those tests that depend on module core to be run: :: +Running test.py will cause only those tests that depend on module core to be run: +.. sourcecode:: text + 24 of 24 tests passed (24 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) -Repeat the above steps for the "network" module instead of the "core" module, and the following will be built, since network depends on core: :: +Repeat the above steps for the "network" module instead of the "core" module, and the following will be built, since network depends on core: + +.. sourcecode:: text bindings libns3-core.so libns3-network.so ns3 scratch utils examples libns3-core-test.so libns3-network-test.so samples src -Running test.py will cause those tests that depend on only the core and network modules to be run: :: +Running test.py will cause those tests that depend on only the core and network modules to be run: + +.. sourcecode:: text 31 of 31 tests passed (31 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) diff --git a/doc/manual/source/enable-tests.rst b/doc/manual/source/enable-tests.rst index ba44dde55..3325836a9 100644 --- a/doc/manual/source/enable-tests.rst +++ b/doc/manual/source/enable-tests.rst @@ -1,4 +1,6 @@ .. include:: replace.txt +.. highlight:: bash + Enabling/disabling |ns3| Tests and Examples ------------------------------------------- @@ -26,18 +28,22 @@ By default, examples and tests are not built in |ns3|. From the ns-3-allinone directory, you can build |ns3| without any examples or tests simply by doing: :: - ./build.py + $ ./build.py -Running test.py in the top level |ns3| directory now will cause no examples or tests to be run: :: +Running test.py in the top level |ns3| directory now will cause no examples or tests to be run: +.. sourcecode:: text + 0 of 0 tests passed (0 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) If you would like build |ns3| with examples and tests, then do the following from the ns-3-allinone directory: :: - ./build.py --enable-examples --enable-tests + $ ./build.py --enable-examples --enable-tests -Running test.py in the top level |ns3| directory will cause all of the examples and tests to be run: :: +Running test.py in the top level |ns3| directory will cause all of the examples and tests to be run: +.. sourcecode:: text + 170 of 170 tests passed (170 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) Enable/disable examples and tests using waf @@ -50,20 +56,24 @@ By default, examples and tests are not built in |ns3|. From the top level |ns3| directory, you can build |ns3| without any examples or tests simply by doing: :: - ./waf configure - ./waf build + $ ./waf configure + $ ./waf build -Running test.py now will cause no examples or tests to be run: :: +Running test.py now will cause no examples or tests to be run: +.. sourcecode:: text + 0 of 0 tests passed (0 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) If you would like build |ns3| with examples and tests, then do the following from the top level |ns3| directory: :: - ./waf configure --enable-examples --enable-tests - ./waf build + $ ./waf configure --enable-examples --enable-tests + $ ./waf build -Running test.py will cause all of the examples and tests to be run: :: +Running test.py will cause all of the examples and tests to be run: +.. sourcecode:: text + 170 of 170 tests passed (170 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) Enable/disable examples and tests using the |ns3| configuration file @@ -84,9 +94,11 @@ The maintained version of the .ns3rc file in the |ns3| source code repository re Assuming that you are in the top level |ns3| directory, you can get a copy of the .ns3rc file that is in the ``utils`` directory as follows: :: - cp utils/.ns3rc . + $ cp utils/.ns3rc . -The .ns3rc file should now be in your top level |ns3| directory, and it contains the following: :: +The .ns3rc file should now be in your top level |ns3| directory, and it contains the following: + +.. sourcecode:: python #! /usr/bin/env python @@ -105,16 +117,20 @@ The .ns3rc file should now be in your top level |ns3| directory, and it contains From the top level |ns3| directory, you can build |ns3| without any examples or tests simply by doing: :: - ./waf configure - ./waf build + $ ./waf configure + $ ./waf build -Running test.py now will cause no examples or tests to be run: :: +Running test.py now will cause no examples or tests to be run: +.. sourcecode:: text + 0 of 0 tests passed (0 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) If you would like build |ns3| with examples and tests, use your favorite editor to change the values in the .ns3rc file for -examples_enabled and tests_enabled file to be True: :: +examples_enabled and tests_enabled file to be True: + +.. sourcecode:: python #! /usr/bin/env python @@ -133,9 +149,11 @@ examples_enabled and tests_enabled file to be True: :: From the top level |ns3| directory, you can build |ns3| with examples and tests simply by doing: :: - ./waf configure - ./waf build + $ ./waf configure + $ ./waf build -Running test.py will cause all of the examples and tests to be run: :: +Running test.py will cause all of the examples and tests to be run: +.. sourcecode:: text + 170 of 170 tests passed (170 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) diff --git a/doc/manual/source/events.rst b/doc/manual/source/events.rst index bfd3d5983..763713f82 100644 --- a/doc/manual/source/events.rst +++ b/doc/manual/source/events.rst @@ -1,4 +1,6 @@ .. include:: replace.txt +.. highlight:: cpp + .. heading hierarchy: ------------- Chapter @@ -42,7 +44,7 @@ Simulator The Simulator class is the public entry point to access event scheduling facilities. Once a couple of events have been scheduled to start the simulation, the user can start to execute them by entering the simulator -main loop (call Simulator::Run). Once the main loop starts running, it +main loop (call ``Simulator::Run``). Once the main loop starts running, it will sequentially execute all scheduled events in order from oldest to most recent until there are either no more events left in the event queue or Simulator::Stop has been called. @@ -70,7 +72,7 @@ might write this: Which will output: -:: +.. sourcecode:: text handler called with argument arg0=10 and arg1=5 diff --git a/doc/manual/source/gnuplot.rst b/doc/manual/source/gnuplot.rst index ca4ec33be..3ba1f714c 100644 --- a/doc/manual/source/gnuplot.rst +++ b/doc/manual/source/gnuplot.rst @@ -1,5 +1,6 @@ .. include:: replace.txt - +.. highlight:: cpp + Making Plots using the Gnuplot Class ------------------------------------ @@ -25,39 +26,51 @@ See the code from the example plots that are discussed below for details on step An Example Program that Uses the Gnuplot Class ********************************************** -An example program that uses |ns3|'s Gnuplot class can be found here: :: +An example program that uses |ns3|'s Gnuplot class can be found here: + +.. sourcecode:: bash src/stats/examples/gnuplot-example.cc -In order to run this example, do the following: :: +In order to run this example, do the following: - ./waf shell - cd build/debug/src/stats/examples - ./gnuplot-example +.. sourcecode:: bash -This should produce the following gnuplot control files in the directory where the example is located: :: + $ ./waf shell + $ cd build/debug/src/stats/examples + $ ./gnuplot-example + +This should produce the following gnuplot control files in the directory where the example is located: + +.. sourcecode:: text plot-2d.plt plot-2d-with-error-bars.plt plot-3d.plt -In order to process these gnuplot control files, do the following: :: +In order to process these gnuplot control files, do the following: - gnuplot plot-2d.plt - gnuplot plot-2d-with-error-bars.plt - gnuplot plot-3d.plt +.. sourcecode:: bash -This should produce the following graphics files in the directory where the example is located: :: + $ gnuplot plot-2d.plt + $ gnuplot plot-2d-with-error-bars.plt + $ gnuplot plot-3d.plt + +This should produce the following graphics files in the directory where the example is located: + +.. sourcecode:: text plot-2d.png plot-2d-with-error-bars.png plot-3d.png -You can view these graphics files in your favorite graphics viewer. If you have gimp installed on your machine, for example, you can do this: :: +You can view these graphics files in your favorite graphics viewer. If you have gimp installed on your machine, for example, you can do this: - gimp plot-2d.png - gimp plot-2d-with-error-bars.png - gimp plot-3d.png +.. sourcecode:: bash + + $ gimp plot-2d.png + $ gimp plot-2d-with-error-bars.png + $ gimp plot-3d.png An Example 2-Dimensional Plot ***************************** diff --git a/doc/manual/source/hash-functions.rst b/doc/manual/source/hash-functions.rst index 7977ad403..88bea60f2 100644 --- a/doc/manual/source/hash-functions.rst +++ b/doc/manual/source/hash-functions.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Hash Functions ---------------- diff --git a/doc/manual/source/helpers.rst b/doc/manual/source/helpers.rst index c8c5a98fa..ca6980eec 100644 --- a/doc/manual/source/helpers.rst +++ b/doc/manual/source/helpers.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Helpers ------- diff --git a/doc/manual/source/how-to-write-tests.rst b/doc/manual/source/how-to-write-tests.rst index afc4355dd..3becadbcb 100644 --- a/doc/manual/source/how-to-write-tests.rst +++ b/doc/manual/source/how-to-write-tests.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp How to write tests ------------------ @@ -46,7 +47,7 @@ more descriptive test case name. You also need to add a block into your wscript to get this test to compile: -:: +.. sourcecode:: python module_test.source = [ 'test/router-test-suite.cc', @@ -64,13 +65,13 @@ is called "router" such as here: Try this command: -:: +.. sourcecode:: bash - ./test.py -s router + $ ./test.py -s router Output such as below should be produced: -:: +.. sourcecode:: text PASS: TestSuite router 1 of 1 tests passed (1 passed, 0 skipped, 0 failed, 0 crashed, 0 valgrind errors) diff --git a/doc/manual/source/logging.rst b/doc/manual/source/logging.rst index eaea17f65..014e46ecf 100644 --- a/doc/manual/source/logging.rst +++ b/doc/manual/source/logging.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp .. heading hierarchy: ------------- Chapter @@ -71,7 +72,7 @@ Logging prefixes This section still needs documentation; bug 1496 is open on this: -:: +.. sourcecode:: bash $ NS_LOG="*=all|prefix_all" ./waf --run scratch-simulator Scratch Simulator @@ -88,16 +89,16 @@ Enabling logging output There are two ways that users typically control logging output. The first is by setting an ``NS_LOG`` environment variable; e.g.: -:: +.. sourcecode:: bash - NS_LOG="*" ./waf --run first + $ NS_LOG="*" ./waf --run first will run the first tutorial program with all logging output. This can be made more granular by selecting individual components: -:: +.. sourcecode:: bash - NS_LOG="Ipv4L3Protocol" ./waf --run first + $ NS_LOG="Ipv4L3Protocol" ./waf --run first The second way to enable this is to use explicit statements in your program, such as in the first tutorial program: diff --git a/doc/manual/source/new-models.rst b/doc/manual/source/new-models.rst index 00b83cc70..b875d0dfe 100644 --- a/doc/manual/source/new-models.rst +++ b/doc/manual/source/new-models.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Creating a new ns-3 model ------------------------- @@ -408,7 +409,7 @@ Add basic support in the class :: - point-to-point-net-device.h + /* point-to-point-net-device.h */ class ErrorModel; /** @@ -473,7 +474,7 @@ Create null functional script :: - simple-error-model.cc + /* simple-error-model.cc */ // Error model // We want to add an error model to node 3's NetDevice diff --git a/doc/manual/source/new-modules.rst b/doc/manual/source/new-modules.rst index 2018d32dd..dd2cd79e6 100644 --- a/doc/manual/source/new-modules.rst +++ b/doc/manual/source/new-modules.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Adding a New Module to |ns3| ---------------------------- @@ -20,7 +21,9 @@ example, the spectrum module can be found here: :: src/spectrum A prototypical module has the following directory structure and -required files: :: +required files: + +.. sourcecode:: text src/ module-name/ @@ -39,29 +42,39 @@ Not all directories will be present in each module. Step 2 - Create your new module based on the template module ************************************************************ -A python program is provided in the source directory that will create a skeleton for a new module :: +A python program is provided in the source directory that will create a skeleton for a new module - src/create-module.py +.. sourcecode:: bash -For the purposes of this discussion we will assume that your new module is called "new-module". From the ``src`` directory, do the following to create the new module: :: + $ src/create-module.py - ./create-module.py new-module +For the purposes of this discussion we will assume that your new module is called "new-module". From the ``src`` directory, do the following to create the new module: -Next, cd into ``new-module``; you will find this directory layout: :: +.. sourcecode:: bash - examples helper model test wscript + $ ./create-module.py new-module + +Next, cd into ``new-module``; you will find this directory layout: + +.. sourcecode:: text + + $ examples helper model test wscript We next walk through how to customize this module. All |ns3| modules depend on the 'core' module and usually on other modules. This dependency is specified in the wscript file. Let's assume that 'new-module' depends on the internet, mobility, and aodv modules. Then the call to the function that will -create this module should look like this before editing: :: +create this module should look like this before editing: + +.. sourcecode:: python def build(bld): module = bld.create_ns3_module('new-module', ['core']) -and after editing: :: +and after editing: + +.. sourcecode:: python def build(bld): module = bld.create_ns3_module('new-module', ['internet', 'mobility', 'aodv']) @@ -82,18 +95,24 @@ Step 3 - Adding to your module's source files ********************************************* If your new module has model and/or helper source files, then they -must be specified in your :: +must be specified in your + +.. sourcecode:: text src/new-module/wscript file by modifying it with your text editor. As an example, the source files for the spectrum module are specified -in :: +in + +.. sourcecode:: text src/spectrum/wscript -with the following list of source files: :: +with the following list of source files: + +.. sourcecode:: python module.source = [ 'model/spectrum-model.cc', @@ -112,20 +131,26 @@ Step 4 - Specify your module's header files ******************************************* If your new module has model and/or helper header files, then they -must be specified in your :: +must be specified in your + +.. sourcecode:: text src/new-module/wscript file by modifying it with your text editor. As an example, the header files for the spectrum module are specified -in :: +in + +.. sourcecode:: text src/spectrum/wscript with the following function call, module name, and list of header files. Note that the argument for the function new_task_gen() tells -waf to install this module's headers with the other |ns3| headers: :: +waf to install this module's headers with the other |ns3| headers: + +.. sourcecode:: python headers = bld.new_task_gen(features=['ns3header']) @@ -147,17 +172,23 @@ waf to install this module's headers with the other |ns3| headers: :: Step 5 - Specify your module's tests ************************************ -If your new module has tests, then they must be specified in your :: +If your new module has tests, then they must be specified in your + +.. sourcecode:: text src/new-module/wscript file by modifying it with your text editor. -As an example, the tests for the spectrum module are specified in :: +As an example, the tests for the spectrum module are specified in + +.. sourcecode:: text src/spectrum/wscript -with the following function call and list of test suites: :: +with the following function call and list of test suites: + +.. sourcecode:: python module_test = bld.create_ns3_module_test_library('spectrum') @@ -170,20 +201,26 @@ with the following function call and list of test suites: :: Step 6 - Specify your module's examples *************************************** -If your new module has examples, then they must be specified in your :: +If your new module has examples, then they must be specified in your + +.. sourcecode:: text src/new-module/examples/wscript file by modifying it with your text editor. -As an example, the examples for the core module are specified in :: +As an example, the examples for the core module are specified in + +.. sourcecode:: text src/core/examples/wscript The core module's C++ examples are specified using the following function calls and source file names. Note that the second argument for the function ``create_ns3_program()`` is the list of modules that the -program being created depends on: :: +program being created depends on: + +.. sourcecode:: python obj = bld.create_ns3_program('main-callback', ['core']) obj.source = 'main-callback.cc' @@ -194,7 +231,9 @@ program being created depends on: :: The core module's Python examples are specified using the following function call. Note that the second argument for the function register_ns3_script() is the list of modules that the Python example -depends on: :: +depends on: + +.. sourcecode:: python bld.register_ns3_script('sample-simulator.py', ['core']) @@ -207,11 +246,15 @@ are suitable for regression tests. A file called ``examples-to-run.py`` that exists in each module's test directory can control the invocation of the examples when the test framework runs. -As an example, the examples that are run by ``test.py`` for the core module are specified in :: +As an example, the examples that are run by ``test.py`` for the core module are specified in + +.. sourcecode:: text src/core/test/examples-to-run.py -using the following two lists of C++ and Python examples: :: +using the following two lists of C++ and Python examples: + +.. sourcecode:: python # 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 @@ -238,7 +281,9 @@ using the following two lists of C++ and Python examples: :: ("sample-simulator.py", "True"), ] -Each tuple in the C++ list of examples to run contains :: +Each tuple in the C++ list of examples to run contains + +.. sourcecode:: python (example_name, do_run, do_valgrind_run) @@ -249,11 +294,15 @@ is needed because NSC causes illegal instruction crashes with some tests when they are run under valgrind. Note that the two conditions are Python statements that -can depend on waf configuration variables. For example, :: +can depend on waf configuration variables. For example, + +.. sourcecode:: python ("tcp-nsc-lfn", "NSC_ENABLED == True", "NSC_ENABLED == False"), -Each tuple in the Python list of examples to run contains :: +Each tuple in the Python list of examples to run contains + +.. sourcecode:: python (example_name, do_run) @@ -261,12 +310,16 @@ where example_name is the Python script to be run and do_run is a condition under which to run the example. Note that the condition is a Python statement that can -depend on waf configuration variables. For example, :: +depend on waf configuration variables. For example, + +.. sourcecode:: python ("realtime-udp-echo.py", "ENABLE_REAL_TIME == False"), If your new module has examples, then you must specify which of them -should be run in your :: +should be run in your + +.. sourcecode:: text src/new-module/test/examples-to-run.py @@ -276,10 +329,12 @@ test.py. Step 8 - Build and test your new module *************************************** -You can now build and test your module as normal: :: +You can now build and test your module as normal: - ./waf configure --enable-examples --enable-tests - ./waf build - ./test.py +.. sourcecode:: bash + + $ ./waf configure --enable-examples --enable-tests + $ ./waf build + $ ./test.py and look for your new module's test suite (and example programs, if enabled) in the test output. diff --git a/doc/manual/source/object-model.rst b/doc/manual/source/object-model.rst index 41b2ea335..c5879385d 100644 --- a/doc/manual/source/object-model.rst +++ b/doc/manual/source/object-model.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp .. _Object-model: diff --git a/doc/manual/source/object-names.rst b/doc/manual/source/object-names.rst index 932485368..d1b287e84 100644 --- a/doc/manual/source/object-names.rst +++ b/doc/manual/source/object-names.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp .. _Object-names: diff --git a/doc/manual/source/organization.rst b/doc/manual/source/organization.rst index 9648c0197..01c650a67 100644 --- a/doc/manual/source/organization.rst +++ b/doc/manual/source/organization.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Organization diff --git a/doc/manual/source/python.rst b/doc/manual/source/python.rst index 3732dfbe8..c8a983ff0 100644 --- a/doc/manual/source/python.rst +++ b/doc/manual/source/python.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: python Using Python to Run |ns3| ------------------------- @@ -74,30 +75,30 @@ Running Python Scripts waf contains some options that automatically update the python path to find the ns3 module. To run example programs, there are two ways to use waf to take care of this. One is to run a waf shell; e.g.: -:: +.. sourcecode:: bash - ./waf --shell - python examples/wireless/mixed-wireless.py + $ ./waf --shell + $ python examples/wireless/mixed-wireless.py and the other is to use the --pyrun option to waf: -:: +.. sourcecode:: bash - ./waf --pyrun examples/wireless/mixed-wireless.py + $ ./waf --pyrun examples/wireless/mixed-wireless.py To run a python script under the C debugger: -:: +.. sourcecode:: bash - ./waf --shell - gdb --args python examples/wireless/mixed-wireless.py + $ ./waf --shell + $ gdb --args python examples/wireless/mixed-wireless.py To run your own Python script that calls |ns3| and that has this path, ``/path/to/your/example/my-script.py``, do the following: -:: +.. sourcecode:: bash - ./waf --shell - python /path/to/your/example/my-script.py + $ ./waf --shell + $ python /path/to/your/example/my-script.py Caveats ******* @@ -118,9 +119,9 @@ Most of the missing APIs can be wrapped, given enough time, patience, and expert Conversion Constructors +++++++++++++++++++++++ -Conversion constructors (http://publib.boulder.ibm.com/infocenter/compbgpl/v9v111/topic/com.ibm.xlcpp9.bg.doc/language_ref/cplr384.htm) are not fully supported yet by PyBindGen, and they always act as explicit constructors when translating an API into Python. For example, in C++ you can do this: +`Conversion constructors `_ are not fully supported yet by PyBindGen, and they always act as explicit constructors when translating an API into Python. For example, in C++ you can do this: -:: +.. sourcecode:: cpp Ipv4AddressHelper ipAddrs; ipAddrs.SetBase ("192.168.0.0", "255.255.255.0"); @@ -188,9 +189,9 @@ will probably have to be that we disable python bindings in CygWin. If you really care about Python bindings on Windows, try building with mingw and native python instead. Or else, to build without python bindings, disable python bindings in the configuration stage: -:: +.. sourcecode:: bash - ./waf configure --disable-python + $ ./waf configure --disable-python Working with Python Bindings **************************** @@ -211,9 +212,9 @@ The process by which Python bindings are handled is the following: If something goes wrong with compiling Python bindings and you just want to ignore them and move on with C++, you can disable Python with: -:: +.. sourcecode:: bash - ./waf --disable-python + $ ./waf --disable-python Instructions for Handling New Files or Changed API's **************************************************** @@ -230,9 +231,9 @@ Scanning the Monolithic Python Bindings To scan the monolithic Python bindings do the following: -:: +.. sourcecode:: bash - ./waf --python-scan + $ ./waf --python-scan Organization of the Monolithic Python Bindings ++++++++++++++++++++++++++++++++++++++++++++++ @@ -269,15 +270,15 @@ Scanning the Modular Python Bindings To scan the modular Python bindings for the core module, for example, do the following: -:: +.. sourcecode:: bash - ./waf --apiscan=core + $ ./waf --apiscan=core To scan the modular Python bindings for all of the modules, do the following: -:: +.. sourcecode:: bash - ./waf --apiscan=all + $ ./waf --apiscan=all Creating a New Module +++++++++++++++++++++ @@ -311,5 +312,4 @@ The ``src//bindings`` directory may contain the following files, some of More Information for Developers ******************************* -If you are a developer and need more information on |ns3|'s Python bindings, please see the Python Bindings wiki page at -``_. +If you are a developer and need more information on |ns3|'s Python bindings, please see the `Python Bindings wiki page `_. diff --git a/doc/manual/source/random-variables.rst b/doc/manual/source/random-variables.rst index ae36fe7cf..3d6d8d37a 100644 --- a/doc/manual/source/random-variables.rst +++ b/doc/manual/source/random-variables.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Random Variables ---------------- @@ -125,7 +126,7 @@ run number behavior. This seeding and substream state setting must be called before any random variables are created; e.g:: RngSeedManager::SetSeed (3); // Changes seed from default of 1 to 3 - RngSeedManager::SetRun (7); // Changes run number from default of 1 to 7 + RngSeedManager::SetRun (7); // Changes run number from default of 1 to 7 // Now, create random variables Ptr x = CreateObject (); Ptr y = CreateObject (); @@ -143,18 +144,24 @@ independent replications using the substreams. For ease of use, it is not necessary to control the seed and run number from within the program; the user can set the ``NS_GLOBAL_VALUE`` environment -variable as follows:: +variable as follows: - NS_GLOBAL_VALUE="RngRun=3" ./waf --run program-name +.. sourcecode:: bash + + $ NS_GLOBAL_VALUE="RngRun=3" ./waf --run program-name Another way to control this is by passing a command-line argument; since this is -an |ns3| GlobalValue instance, it is equivalently done such as follows:: +an |ns3| GlobalValue instance, it is equivalently done such as follows: - ./waf --command-template="%s --RngRun=3" --run program-name +.. sourcecode:: bash -or, if you are running programs directly outside of waf:: + $ ./waf --command-template="%s --RngRun=3" --run program-name - ./build/optimized/scratch/program-name --RngRun=3 +or, if you are running programs directly outside of waf: + +.. sourcecode:: bash + + $ ./build/optimized/scratch/program-name --RngRun=3 The above command-line variants make it easy to run lots of different runs from a shell script by just passing a different RngRun index. @@ -177,7 +184,9 @@ Base class public API ********************* Below are excerpted a few public methods of class :cpp:class:`RandomVariableStream` -that access the next value in the substream.:: +that access the next value in the substream. + +:: /** * \brief Returns a random double from the underlying distribution @@ -226,7 +235,7 @@ handled by smart pointers. RandomVariableStream instances can also be used in |ns3| attributes, which means that values can be set for them through the |ns3| attribute system. -An example is in the propagation models for WifiNetDevice::: +An example is in the propagation models for WifiNetDevice:: TypeId RandomPropagationDelayModel::GetTypeId (void) @@ -278,20 +287,20 @@ of the base class RandomVariableStream. By partitioning the existing sequence of streams from before: -:: +.. sourcecode:: text <--------------------------------------------------------------------------> - stream 0 stream (2^64 - 1) + stream 0 stream (2^64 - 1) into two equal-sized sets: -:: +.. sourcecode:: text - <---------------------------------------------------------------------------> - ^ ^^ ^ - | || | - stream 0 stream (2^63 - 1) stream 2^63 stream (2^64 - 1) - <- automatically assigned -----><-------- assigned by user-----------> + <--------------------------------------------------------------------------> + ^ ^^ ^ + | || | + stream 0 stream (2^63 - 1) stream 2^63 stream (2^64 - 1) + <- automatically assigned -----------><- assigned by user -----------------> The first 2^63 streams continue to be automatically assigned, while the last 2^63 are given stream indices starting with zero up to diff --git a/doc/manual/source/realtime.rst b/doc/manual/source/realtime.rst index 47d6be20e..0d22982e0 100644 --- a/doc/manual/source/realtime.rst +++ b/doc/manual/source/realtime.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp RealTime -------- @@ -61,9 +62,11 @@ perspective. Users just need to set the attribute StringValue ("ns3::RealtimeSimulatorImpl")); There is a script in ``examples/realtime/realtime-udp-echo.cc`` that -has an example of how to configure the realtime behavior. Try: :: +has an example of how to configure the realtime behavior. Try: - ./waf --run realtime-udp-echo +.. sourcecode:: bash + + $ ./waf --run realtime-udp-echo Whether the simulator will work in a best effort or hard limit policy fashion is governed by the attributes explained in the previous section. diff --git a/doc/manual/source/replace.txt b/doc/manual/source/replace.txt index 4cb2f2303..d3c0a4273 100644 --- a/doc/manual/source/replace.txt +++ b/doc/manual/source/replace.txt @@ -1,3 +1,5 @@ .. |ns3| replace:: *ns-3* .. |ns2| replace:: *ns-2* + +.. |check| replace:: :math:`\checkmark` diff --git a/doc/manual/source/test-framework.rst b/doc/manual/source/test-framework.rst index 6ec109d23..0fa404693 100644 --- a/doc/manual/source/test-framework.rst +++ b/doc/manual/source/test-framework.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: bash Testing framework ----------------- @@ -27,7 +28,9 @@ properly on all of its supported systems. Users (and developers) typically will not interact with the buildbot system other than to read its messages regarding test results. If a failure is detected in one of the automated build and test jobs, the buildbot will send an email to the -*ns-developers* mailing list. This email will look something like:: +*ns-developers* mailing list. This email will look something like + +.. sourcecode: text The Buildbot has detected a new failure of osx-ppc-g++-4.2 on NsNam. Full details are available at: @@ -69,20 +72,20 @@ have been built by doing the following :: - ./waf configure --enable-examples --enable-tests - ./waf + $ ./waf configure --enable-examples --enable-tests + $ ./waf By default, ``test.py`` will run all available tests and report status back in a very concise form. Running the command :: - ./test.py + $ ./test.py will result in a number of ``PASS``, ``FAIL``, ``CRASH`` or ``SKIP`` indications followed by the kind of test that was run and its display name. -:: +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' @@ -103,7 +106,7 @@ in determining if changes they have made have caused any regressions. There are a number of options available to control the behavior of ``test.py``. if you run ``test.py --help`` you should see a command summary like: -:: +.. sourcecode:: text Usage: test.py [options] @@ -145,7 +148,7 @@ nightly builds using :: - ./test.py --html=nightly.html + $ ./test.py --html=nightly.html In this case, an HTML file named ''nightly.html'' would be created with a pretty summary of the testing done. A ''human readable'' format is available for users @@ -153,7 +156,7 @@ interested in the details. :: - ./test.py --text=results.txt + $ ./test.py --text=results.txt In the example above, the test suite checking the |ns3| wireless device propagation loss models failed. By default no further information is @@ -164,17 +167,17 @@ to be specified. Running the command :: - ./test.py --suite=ns3-wifi-propagation-loss-models + $ ./test.py --suite=ns3-wifi-propagation-loss-models or equivalently :: - ./test.py -s ns3-wifi-propagation-loss-models + $ ./test.py -s ns3-wifi-propagation-loss-models results in that single test suite being run. -:: +.. sourcecode:: text FAIL: TestSuite ns3-wifi-propagation-loss-models @@ -182,13 +185,14 @@ To find detailed information regarding the failure, one must specify the kind of output desired. For example, most people will probably be interested in a text file:: - ./test.py --suite=ns3-wifi-propagation-loss-models --text=results.txt + $ ./test.py --suite=ns3-wifi-propagation-loss-models --text=results.txt This will result in that single test suite being run with the test status written to the file ''results.txt''. -You should find something similar to the following in that file:: +You should find something similar to the following in that file +.. sourcecode:: text FAIL: Test Suite ''ns3-wifi-propagation-loss-models'' (real 0.02 user 0.01 system 0.00) PASS: Test Case "Check ... Friis ... model ..." (real 0.01 user 0.00 system 0.00) @@ -222,21 +226,23 @@ changes to a repository. In this case, ``test.py`` can be told to constrain the types of tests being run to a particular class of tests. The following command will result in only the unit tests being run:: - ./test.py --constrain=unit + $ ./test.py --constrain=unit Similarly, the following command will result in only the example smoke tests being run:: - ./test.py --constrain=unit + $ ./test.py --constrain=unit To see a quick list of the legal kinds of constraints, you can ask for them to be listed. The following command :: - ./test.py --kinds + $ ./test.py --kinds -will result in the following list being displayed:: +will result in the following list being displayed: + +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' @@ -256,9 +262,11 @@ to be listed. The following command, :: - ./test.py --list + $ ./test.py --list -will result in a list of the test suite being displayed, similar to:: +will result in a list of the test suite being displayed, similar to + +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' @@ -291,11 +299,11 @@ for C++ examples do not have extensions. Entering :: - ./test.py --example=udp-echo + $ ./test.py --example=udp-echo results in that single example being run. -:: +.. sourcecode:: text PASS: Example examples/udp/udp-echo @@ -304,7 +312,7 @@ You can specify the directory where ns-3 was built using the :: - ./test.py --buildpath=/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build/debug --example=wifi-simple-adhoc + $ ./test.py --buildpath=/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build/debug --example=wifi-simple-adhoc One can run a single Python example program using the ``--pyexample`` option. Note that the relative path for the example must be included @@ -312,11 +320,11 @@ and that Python examples do need their extensions. Entering :: - ./test.py --pyexample=examples/tutorial/first.py + $ ./test.py --pyexample=examples/tutorial/first.py results in that single example being run. -:: +.. sourcecode:: text PASS: Example examples/tutorial/first.py @@ -344,9 +352,11 @@ option. :: - ./test.py --list --nowaf + $ ./test.py --list --nowaf -will result in a list of the currently built test suites being displayed, similar to:: +will result in a list of the currently built test suites being displayed, similar to: + +.. sourcecode:: text ns3-wifi-propagation-loss-models ns3-tcp-cwnd @@ -366,7 +376,7 @@ leaks. This can be selected by using the ``--grind`` option. :: - ./test.py --grind + $ ./test.py --grind As it runs, ``test.py`` and the programs that it runs indirectly, generate large numbers of temporary files. Usually, the content of these files is not interesting, @@ -378,7 +388,7 @@ Universal Time (also known as Greenwich Mean Time). :: - ./test.py --retain + $ ./test.py --retain Finally, ``test.py`` provides a ``--verbose`` option which will print large amounts of information about its progress. It is not expected that this @@ -386,13 +396,13 @@ will be terribly useful unless there is an error. In this case, you can get access to the standard output and standard error reported by running test suites and examples. Select verbose in the following way:: - ./test.py --verbose + $ ./test.py --verbose All of these options can be mixed and matched. For example, to run all of the ns-3 core test suites under valgrind, in verbose mode, while generating an HTML output file, one would do:: - ./test.py --verbose --grind --constrain=core --html=results.html + $ ./test.py --verbose --grind --constrain=core --html=results.html TestTaxonomy ************ @@ -480,7 +490,7 @@ stage, and also (optionally) examples if examples are to be checked: :: - ./waf --configure --enable-examples --enable-tests + $ ./waf --configure --enable-examples --enable-tests Then, build ns-3, and after it is built, just run ``test.py``. ``test.py -h`` will show a number of configuration options that modify the behavior @@ -501,9 +511,11 @@ The main reason why ``test.py`` is not suitable for debugging is that it is not In order to execute the test-runner, you run it like any other ns-3 executable -- using ``waf``. To get a list of available options, you can type:: - ./waf --run "test-runner --help" + $ ./waf --run "test-runner --help" -You should see something like the following:: +You should see something like the following + +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-test/ns-3-dev/build' @@ -537,10 +549,10 @@ option something like, :: - ./waf shell - cd build/debug/utils - gdb test-runner - run --suite=global-value --assert + $ ./waf shell + $ cd build/debug/utils + $ gdb test-runner + $ run --suite=global-value --assert If an error is then found in the global-value test suite, a segfault would be generated and the (source level) debugger would stop at the ``NS_TEST_ASSERT_MSG`` @@ -556,7 +568,7 @@ option for you. To run one of the tests directly from the test-runner using ``waf``, you will need to specify the test suite to run along with the base directory. So you could use the shell and do:: - ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object" + $ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object" Note the ''backward'' quotation marks on the ``pwd`` command. @@ -601,7 +613,7 @@ output, run ``test.py`` with the "retain" option: :: - ./test.py -r + $ ./test.py -r and test output can be found in the ``testpy-output/`` directory. @@ -619,11 +631,11 @@ Try, :: - ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object --out=myfile.xml" + $ ./waf --run "test-runner --basedir=`pwd` --suite=pcap-file-object --out=myfile.xml" If you look at the file ``myfile.xml`` you should see something like, -:: +.. sourcecode:: xml pcap-file-object @@ -669,7 +681,9 @@ section. Debugging test suite failures +++++++++++++++++++++++++++++ -To debug test crashes, such as:: +To debug test crashes, such as + +.. sourcecode:: text CRASH: TestSuite ns3-wifi-interference @@ -677,7 +691,7 @@ You can access the underlying test-runner program via gdb as follows, and then pass the "--basedir=`pwd`" argument to run (you can also pass other arguments as needed, but basedir is the minimum needed):: - ./waf --command-template="gdb %s" --run "test-runner" + $ ./waf --command-template="gdb %s" --run "test-runner" Waf: Entering directory `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build' Waf: Leaving directory `/home/tomh/hg/sep09/ns-3-allinone/ns-3-dev-678/build' 'build' finished successfully (0.380s) @@ -699,7 +713,7 @@ such as:: VALGR: TestSuite devices-mesh-dot11s-regression - ./waf --command-template="valgrind %s --basedir=`pwd` --suite=devices-mesh-dot11s-regression" --run test-runner + $ ./waf --command-template="valgrind %s --basedir=`pwd` --suite=devices-mesh-dot11s-regression" --run test-runner Class TestRunner **************** @@ -736,7 +750,7 @@ and perform these two duties. The following code will define a new class that can be run by ``test.py`` as a ''unit'' test with the display name, ``my-test-suite-name``. -:: +.. sourcecode:: cpp class MySuite : public TestSuite { @@ -766,7 +780,7 @@ In order to create a new test case in the system, all one has to do is to inheri from the ``TestCase`` base class, override the constructor to give the test case a name and override the ``DoRun`` method to run the test. -:: +.. sourcecode:: cpp class MyTestCase : public TestCase { diff --git a/doc/manual/source/tracing.rst b/doc/manual/source/tracing.rst index 3e65834c2..24aa2ac50 100644 --- a/doc/manual/source/tracing.rst +++ b/doc/manual/source/tracing.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Tracing ------- @@ -269,7 +270,7 @@ aggregation model. The next path segment begins with the "$" character which indicates a ``GetObject`` call should be made looking for the type that follows. When a node is initialized by an ``InternetStackHelper`` a number of interfaces are aggregated to the node. One of these is the TCP level four protocol. The -runtime type of this protocol object is "ns3::TcpL4Protocol". When the +runtime type of this protocol object is ``ns3::TcpL4Protocol''. When the ``GetObject`` is executed, it returns a pointer to the object of this type. The ``TcpL4Protocol`` class defines an Attribute called "SocketList" which is a @@ -342,14 +343,15 @@ stack helpers. Naturally, the trace files should follow a The trace helpers therefore fall naturally into a two-dimensional taxonomy. There are subtleties that prevent all four classes from behaving identically, but we do strive to make them all work as similarly as possible; and whenever -possible there are analogs for all methods in all classes.:: +possible there are analogs for all methods in all classes. - | pcap | ascii | - -----------------+------+-------| - Device Helper | | | - -----------------+------+-------| - Protocol Helper | | | - -----------------+------+-------| + +-----------------+---------+---------+ + | | pcap | ascii | + +=================+=========+=========+ + | Device Helper | |check| | |check| | + +-----------------+---------+---------+ + | Protocol Helper | |check| | |check| | + +-----------------+---------+---------+ We use an approach called a ``mixin`` to add tracing functionality to our helper classes. A ``mixin`` is a class that provides functionality to that is @@ -393,11 +395,16 @@ Pcap Tracing Device Helper Methods :: - void EnablePcap (std::string prefix, Ptr nd, bool promiscuous = false, bool explicitFilename = false); - void EnablePcap (std::string prefix, std::string ndName, bool promiscuous = false, bool explicitFilename = false); - void EnablePcap (std::string prefix, NetDeviceContainer d, bool promiscuous = false); - void EnablePcap (std::string prefix, NodeContainer n, bool promiscuous = false); - void EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous = false); + void EnablePcap (std::string prefix, Ptr nd, + bool promiscuous = false, bool explicitFilename = false); + void EnablePcap (std::string prefix, std::string ndName, + bool promiscuous = false, bool explicitFilename = false); + void EnablePcap (std::string prefix, NetDeviceContainer d, + bool promiscuous = false); + void EnablePcap (std::string prefix, NodeContainer n, + bool promiscuous = false); + void EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, + bool promiscuous = false); void EnablePcapAll (std::string prefix, bool promiscuous = false); In each of the methods shown above, there is a default parameter called diff --git a/doc/manual/source/troubleshoot.rst b/doc/manual/source/troubleshoot.rst index e59c83923..45809f7c0 100644 --- a/doc/manual/source/troubleshoot.rst +++ b/doc/manual/source/troubleshoot.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: bash Troubleshooting --------------- @@ -22,18 +23,20 @@ values are unexpectedly null. Here is an example of what might occur::: - ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point - Entering directory `/home/tomh/ns-3-nsc/build' + $ ./waf --run tcp-point-to-point + Entering directory '/home/tomh/ns-3-nsc/build' Compilation finished successfully Command ['/home/tomh/ns-3-nsc/build/debug/examples/tcp-point-to-point'] exited with code -11 The error message says that the program terminated unsuccessfully, but it is not clear from this information what might be wrong. To examine more closely, try running it under the `gdb debugger -`_::: +`_: - ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="gdb %s" - Entering directory `/home/tomh/ns-3-nsc/build' +.. sourcecode:: bash + + $ ./waf --run tcp-point-to-point --command-template="gdb %s" + Entering directory '/home/tomh/ns-3-nsc/build' Compilation finished successfully GNU gdb Red Hat Linux (6.3.0.0-1.134.fc5rh) Copyright 2004 Free Software Foundation, Inc. @@ -66,7 +69,9 @@ argument to the command template "gdb %s". This tells us that there was an attempt to dereference a null pointer socketFactory. -Let's look around line 136 of tcp-point-to-point, as gdb suggests::: +Let's look around line 136 of tcp-point-to-point, as gdb suggests: + +.. sourcecode:: cpp Ptr socketFactory = n2->GetObject (Tcp::iid); Ptr localSocket = socketFactory->CreateSocket (); @@ -77,6 +82,6 @@ may be null. Sometimes you may need to use the `valgrind memory checker `_ for more subtle errors. Again, you invoke the use of -valgrind similarly::: +valgrind similarly:: - ns-old:~/ns-3-nsc$ ./waf --run tcp-point-to-point --command-template="valgrind %s" + $ ./waf --run tcp-point-to-point --command-template="valgrind %s" diff --git a/doc/modules b/doc/modules index 62974397e..11d7e1eb8 100644 --- a/doc/modules +++ b/doc/modules @@ -1,8 +1,8 @@ /** * @anchor modules_anchor * - * @defgroup constructs C++ Constructs Used by All Modules - * \brief These are C++ constructs defined by the modules. + * @defgroup constructs Introspected Lists + * \brief These are lists of useful items found by examining the type system. * * @defgroup constants Constants * @brief Constants you can change diff --git a/doc/ns3_html_theme/static/ns3_stylesheet.css b/doc/ns3_html_theme/static/ns3_stylesheet.css index 5b99b5cc6..1c9a10be3 100644 --- a/doc/ns3_html_theme/static/ns3_stylesheet.css +++ b/doc/ns3_html_theme/static/ns3_stylesheet.css @@ -25,6 +25,11 @@ div.body h6 { background-image: url('nav_f.png'); } +/* Sphinx figure captions */ +p.caption { + font-weight: bold; +} + /* Doxygen side bar */ #nav-tree { font-size: 12px; diff --git a/doc/tutorial/source/building-topologies.rst b/doc/tutorial/source/building-topologies.rst index 69d713458..44d36fbf7 100644 --- a/doc/tutorial/source/building-topologies.rst +++ b/doc/tutorial/source/building-topologies.rst @@ -1,5 +1,5 @@ .. include:: replace.txt - +.. highlight:: cpp Building Topologies ------------------- @@ -337,10 +337,10 @@ the scratch directory and use waf to build just as you did with the ``first.cc`` example. If you are in the top-level directory of the repository you just type, -:: +.. sourcecode:: bash - cp examples/tutorial/second.cc scratch/mysecond.cc - ./waf + $ cp examples/tutorial/second.cc scratch/mysecond.cc + $ ./waf Warning: We use the file ``second.cc`` as one of our regression tests to verify that it works exactly as we think it should in order to make your @@ -353,15 +353,15 @@ If you are following the tutorial religiously (you are, aren't you) you will still have the NS_LOG variable set, so go ahead and clear that variable and run the program. -:: +.. sourcecode:: bash - export NS_LOG= - ./waf --run scratch/mysecond + $ export NS_LOG= + $ ./waf --run scratch/mysecond Since we have set up the UDP echo applications to log just as we did in ``first.cc``, you will see similar output when you run the script. -:: +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -381,7 +381,7 @@ the server. If you now go and look in the top level directory, you will find three trace files: -:: +.. sourcecode:: text second-0-0.pcap second-1-0.pcap second-2-0.pcap @@ -403,13 +403,13 @@ promiscuous-mode trace. Now, let's follow the echo packet through the internetwork. First, do a tcpdump of the trace file for the leftmost point-to-point node --- node zero. -:: +.. sourcecode:: bash - tcpdump -nn -tt -r second-0-0.pcap + $ tcpdump -nn -tt -r second-0-0.pcap You should see the contents of the pcap file displayed: -:: +.. sourcecode:: text reading from file second-0-0.pcap, link-type PPP (PPP) 2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 @@ -422,14 +422,14 @@ device associated with IP address 10.1.1.1 headed for IP address point-to-point link and be received by the point-to-point net device on node one. Let's take a look: -:: +.. sourcecode:: bash - tcpdump -nn -tt -r second-1-0.pcap + $ tcpdump -nn -tt -r second-1-0.pcap You should now see the pcap trace output of the other side of the point-to-point link: -:: +.. sourcecode:: text reading from file second-1-0.pcap, link-type PPP (PPP) 2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 @@ -444,13 +444,13 @@ pop out on that device headed for its ultimate destination. Remember that we selected node 2 as the promiscuous sniffer node for the CSMA network so let's then look at second-2-0.pcap and see if its there. -:: +.. sourcecode:: bash - tcpdump -nn -tt -r second-2-0.pcap + $ tcpdump -nn -tt -r second-2-0.pcap You should now see the promiscuous dump of node two, device zero: -:: +.. sourcecode:: text reading from file second-2-0.pcap, link-type EN10MB (Ethernet) 2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1 @@ -471,7 +471,7 @@ exchange, but is sniffing the network and reporting all of the traffic it sees. This exchange is seen in the following lines, -:: +.. sourcecode:: text 2.003696 arp who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1 2.003707 arp reply 10.1.2.4 is-at 00:00:00:00:00:06 @@ -479,7 +479,7 @@ This exchange is seen in the following lines, Then node one, device one goes ahead and sends the echo packet to the UDP echo server at IP address 10.1.2.4. -:: +.. sourcecode:: text 2.003801 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 @@ -490,40 +490,41 @@ routing and it has figured all of this out for us. But, the echo server node doesn't know the MAC address of the first CSMA node, so it has to ARP for it just like the first CSMA node had to do. -:: +.. sourcecode:: text 2.003811 arp who-has 10.1.2.1 (ff:ff:ff:ff:ff:ff) tell 10.1.2.4 2.003822 arp reply 10.1.2.1 is-at 00:00:00:00:00:03 The server then sends the echo back to the forwarding node. -:: +.. sourcecode:: text 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024 Looking back at the rightmost node of the point-to-point link, -:: +.. sourcecode:: bash - tcpdump -nn -tt -r second-1-0.pcap + $ tcpdump -nn -tt -r second-1-0.pcap You can now see the echoed packet coming back onto the point-to-point link as the last line of the trace dump. -:: +.. sourcecode:: text reading from file second-1-0.pcap, link-type PPP (PPP) 2.003686 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 2.003915 IP 10.1.2.4.9 > 10.1.1.1.49153: UDP, length 1024 Lastly, you can look back at the node that originated the echo -:: - tcpdump -nn -tt -r second-0-0.pcap +.. sourcecode:: bash + + $ tcpdump -nn -tt -r second-0-0.pcap and see that the echoed packet arrives back at the source at 2.007602 seconds, -:: +.. sourcecode:: text reading from file second-0-0.pcap, link-type PPP (PPP) 2.000000 IP 10.1.1.1.49153 > 10.1.2.4.9: UDP, length 1024 @@ -535,13 +536,13 @@ the same way as when we looked at changing the number of packets echoed in the ``first.cc`` example. Try running the program with the number of "extra" devices set to four: -:: +.. sourcecode:: bash - ./waf --run "scratch/mysecond --nCsma=4" + $ ./waf --run "scratch/mysecond --nCsma=4" You should now see, -:: +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -602,20 +603,20 @@ determining node numbers much easier in complex topologies. Let's clear the old trace files out of the top-level directory to avoid confusion about what is going on, -:: +.. sourcecode:: bash - rm *.pcap - rm *.tr + $ rm *.pcap + $ rm *.tr If you build the new script and run the simulation setting ``nCsma`` to 100, -:: +.. sourcecode:: bash - ./waf --run "scratch/mysecond --nCsma=100" + $ ./waf --run "scratch/mysecond --nCsma=100" you will see the following output: -:: +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -628,7 +629,7 @@ Note that the echo server is now located at 10.1.2.101 which corresponds to having 100 "extra" CSMA nodes with the echo server on the last one. If you list the pcap files in the top level directory you will see, -:: +.. sourcecode:: text second-0-0.pcap second-100-0.pcap second-101-0.pcap @@ -643,15 +644,15 @@ To illustrate the difference between promiscuous and non-promiscuous traces, we also requested a non-promiscuous trace for the next-to-last node. Go ahead and take a look at the ``tcpdump`` for ``second-100-0.pcap``. -:: +.. sourcecode:: bash - tcpdump -nn -tt -r second-100-0.pcap + $ tcpdump -nn -tt -r second-100-0.pcap You can now see that node 100 is really a bystander in the echo exchange. The only packets that it receives are the ARP requests which are broadcast to the entire CSMA network. -:: +.. sourcecode:: text reading from file second-100-0.pcap, link-type EN10MB (Ethernet) 2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1 @@ -659,13 +660,13 @@ entire CSMA network. Now take a look at the ``tcpdump`` for ``second-101-0.pcap``. -:: +.. sourcecode:: bash - tcpdump -nn -tt -r second-101-0.pcap + $ tcpdump -nn -tt -r second-101-0.pcap You can now see that node 101 is really the participant in the echo exchange. -:: +.. sourcecode:: text reading from file second-101-0.pcap, link-type EN10MB (Ethernet) 2.003696 arp who-has 10.1.2.101 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1 @@ -1180,16 +1181,16 @@ script into the scratch directory and use Waf to build just as you did with the ``second.cc`` example. If you are in the top-level directory of the repository you would type, -:: +.. sourcecode:: bash - cp examples/third.cc scratch/mythird.cc - ./waf - ./waf --run scratch/mythird + $ cp examples/third.cc scratch/mythird.cc + $ ./waf + $ ./waf --run scratch/mythird Again, since we have set up the UDP echo applications just as we did in the ``second.cc`` script, you will see similar output. -:: +.. sourcecode:: text Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -1209,7 +1210,7 @@ that it has received its echo back from the server. If you now go and look in the top level directory, you will find four trace files from this simulation, two from node zero and two from node one: -:: +.. sourcecode:: text third-0-0.pcap third-0-1.pcap third-1-0.pcap third-1-1.pcap @@ -1224,13 +1225,13 @@ the code? Since the echo client is on the Wifi network, let's start there. Let's take a look at the promiscuous (monitor mode) trace we captured on that network. -:: +.. sourcecode:: bash - tcpdump -nn -tt -r third-0-1.pcap + $ tcpdump -nn -tt -r third-0-1.pcap You should see some wifi-looking contents you haven't seen here before: -:: +.. sourcecode:: text reading from file third-0-1.pcap, link-type IEEE802_11 (802.11) 0.000025 Beacon (ns-3-ssid) [6.0* 9.0 12.0 18.0 24.0 36.0 48.0 54.0 Mbit] IBSS @@ -1258,13 +1259,13 @@ trace dump. Now, look at the pcap file of the right side of the point-to-point link, -:: +.. sourcecode:: bash - tcpdump -nn -tt -r third-0-0.pcap + $ tcpdump -nn -tt -r third-0-0.pcap Again, you should see some familiar looking contents: -:: +.. sourcecode:: text reading from file third-0-0.pcap, link-type PPP (PPP) 2.002160 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024 @@ -1275,13 +1276,13 @@ again across the point-to-point link. Now, look at the pcap file of the right side of the point-to-point link, -:: +.. sourcecode:: bash - tcpdump -nn -tt -r third-1-0.pcap + $ tcpdump -nn -tt -r third-1-0.pcap Again, you should see some familiar looking contents: -:: +.. sourcecode:: text reading from file third-1-0.pcap, link-type PPP (PPP) 2.005846 IP 10.1.3.3.49153 > 10.1.2.4.9: UDP, length 1024 @@ -1294,13 +1295,13 @@ as you might expect. The echo server is on the CSMA network, let's look at the promiscuous trace there: -:: +.. sourcecode:: bash - tcpdump -nn -tt -r third-1-1.pcap + $ tcpdump -nn -tt -r third-1-1.pcap You should see some familiar looking contents: -:: +.. sourcecode:: text reading from file third-1-1.pcap, link-type EN10MB (Ethernet) 2.005846 ARP, Request who-has 10.1.2.4 (ff:ff:ff:ff:ff:ff) tell 10.1.2.1, length 50 @@ -1382,7 +1383,7 @@ trace sink, which will in turn print out the new position. If you now run the simulation, you will see the course changes displayed as they happen. -:: +.. sourcecode:: text Build finished successfully (00:00:01) /NodeList/7/$ns3::MobilityModel/CourseChange x = 10, y = 0 diff --git a/doc/tutorial/source/conceptual-overview.rst b/doc/tutorial/source/conceptual-overview.rst index d0538a33b..b75feced9 100644 --- a/doc/tutorial/source/conceptual-overview.rst +++ b/doc/tutorial/source/conceptual-overview.rst @@ -1,5 +1,5 @@ .. include:: replace.txt - +.. highlight:: cpp Conceptual Overview ------------------- @@ -153,7 +153,7 @@ of |ns3| in a directory called ``repos`` under your home directory. Change into that release directory, and you should find a directory structure something like the following: -:: +.. sourcecode:: bash AUTHORS examples scratch utils waf.bat* bindings LICENSE src utils.py waf-tools @@ -250,16 +250,16 @@ load all of the public header files. Since you are, of course, following this tutorial religiously, you will already have done a -:: +.. sourcecode:: bash - ./waf -d debug --enable-examples --enable-tests configure + $ ./waf -d debug --enable-examples --enable-tests configure in order to configure the project to perform debug builds that include examples and tests. You will also have done a -:: +.. sourcecode:: bash - ./waf + $ ./waf to build the project. So now if you look in the directory ``../../build/debug/ns3`` you will find the four module include files shown @@ -735,21 +735,21 @@ to drop your script into the scratch directory and it will automatically be built if you run Waf. Let's try it. Copy ``examples/tutorial/first.cc`` into the ``scratch`` directory after changing back into the top level directory. -:: +.. sourcecode:: bash - cd ../.. - cp examples/tutorial/first.cc scratch/myfirst.cc + $ cd ../.. + $ cp examples/tutorial/first.cc scratch/myfirst.cc Now build your first example script using waf: -:: +.. sourcecode:: bash - ./waf + $ ./waf You should see messages reporting that your ``myfirst`` example was built successfully. -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' [614/708] cxx: scratch/myfirst.cc -> build/debug/scratch/myfirst_3.o @@ -760,13 +760,13 @@ successfully. You can now run the example (note that if you build your program in the scratch directory you must run it out of the scratch directory): -:: +.. sourcecode:: bash - ./waf --run scratch/myfirst + $ ./waf --run scratch/myfirst You should see some output: -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -794,14 +794,14 @@ summary page for our |ns3| development tree. At the top of the page, you will see a number of links, -:: +.. sourcecode:: text summary | shortlog | changelog | graph | tags | files Go ahead and select the ``files`` link. This is what the top-level of most of our *repositories* will look: -:: +.. sourcecode:: text drwxr-xr-x [up] drwxr-xr-x bindings python files diff --git a/doc/tutorial/source/getting-started.rst b/doc/tutorial/source/getting-started.rst index 9d4f88b94..e04ac169e 100644 --- a/doc/tutorial/source/getting-started.rst +++ b/doc/tutorial/source/getting-started.rst @@ -1,5 +1,5 @@ - .. include:: replace.txt - +.. include:: replace.txt +.. highlight:: bash Getting Started --------------- @@ -89,11 +89,11 @@ get a copy of a release by typing the following into your Linux shell :: - cd - mkdir workspace - cd workspace - wget http://www.nsnam.org/releases/ns-allinone-3.17.tar.bz2 - tar xjf ns-allinone-3.17.tar.bz2 + $ cd + $ mkdir workspace + $ cd workspace + $ wget http://www.nsnam.org/releases/ns-allinone-3.17.tar.bz2 + $ tar xjf ns-allinone-3.17.tar.bz2 If you change into the directory ``ns-allinone-3.17`` you should see a number of files: @@ -123,10 +123,10 @@ following into your Linux shell (assuming you have installed Mercurial): :: - cd - mkdir workspace - cd workspace - hg clone http://code.nsnam.org/bake + $ cd + $ mkdir workspace + $ cd workspace + $ hg clone http://code.nsnam.org/bake As the hg (Mercurial) command executes, you should see something like the following displayed, @@ -191,9 +191,9 @@ to put bake into your path, such as follows (Linux bash shell example): :: - export BAKE_HOME=`pwd`/bake - export PATH=$PATH:$BAKE_HOME - export PYTHONPATH=$PYTHONPATH:$BAKE_HOME + $ export BAKE_HOME=`pwd`/bake + $ export PATH=$PATH:$BAKE_HOME + $ export PYTHONPATH=$PYTHONPATH:$BAKE_HOME However, setting environment variables is not strictly necessary to complete this tutorial, so we'll call bake directly by specifying the path @@ -203,14 +203,14 @@ Step into the workspace directory and type the following into your shell: :: - ./bake.py configure -e ns-3-dev + $ ./bake.py configure -e ns-3.17 Next, we'l ask bake to check whether we have enough tools to download various components. Type: :: - ./bake.py check + $ ./bake.py check You should see something like the following, @@ -232,7 +232,9 @@ You should see something like the following, > patch tool - OK > autoreconf tool - OK - > Path searched for tools: /usr/lib64/qt-3.3/bin /usr/lib64/ccache /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin /home/tomh/bin bin + > Path searched for tools: /usr/lib64/qt-3.3/bin /usr/lib64/ccache + /usr/local/bin /bin /usr/bin /usr/local/sbin /usr/sbin /sbin + /home/tomh/bin bin In particular, download tools such as Mercurial, CVS, GIT, and Bazaar are our principal concerns at this point, since they allow us to fetch @@ -286,7 +288,7 @@ Type the following: :: - ./build.py --enable-examples --enable-tests + $ ./build.py --enable-examples --enable-tests Because we are working with examples and tests in this tutorial, and because they are not built by default in |ns3|, the arguments for @@ -323,7 +325,7 @@ following magic words: brite click openflow visualizer - Leaving directory `./ns-3.17` + Leaving directory `./ns-3.17' Regarding the portion about modules not built: @@ -347,7 +349,7 @@ may continue to use it to build |ns3|. Type :: - ./bake.py build + $ ./bake.py build and you should see something like: @@ -364,7 +366,7 @@ command tells you; it may give a hint as to a missing dependency: :: - ./bake.py show + $ ./bake.py show This will list out the various dependencies of the packages you are trying to build. @@ -392,8 +394,8 @@ following commands, :: - ./waf clean - ./waf -d optimized --enable-examples --enable-tests configure + $ ./waf clean + $ ./waf -d optimized --enable-examples --enable-tests configure This runs Waf out of the local directory (which is provided as a convenience for you). The first command to clean out the previous build is not @@ -476,15 +478,15 @@ Now go ahead and switch back to the debug build that includes the examples and t :: - ./waf clean - ./waf -d debug --enable-examples --enable-tests configure + $ ./waf clean + $ ./waf -d debug --enable-examples --enable-tests configure The build system is now configured and you can build the debug versions of the |ns3| programs by simply typing :: - ./waf + $ ./waf Okay, sorry, I made you build the |ns3| part of the system twice, but now you know how to change the configuration and build optimized code. @@ -498,7 +500,7 @@ you could reconfigure using the following command that also includes the example :: - ./waf configure -d debug --enable-sudo --enable-examples --enable-tests + $ ./waf configure -d debug --enable-sudo --enable-examples --enable-tests If you do this, waf will have run sudo to change the socket creator programs of the emulation code to run as root. There are many other configure- and build-time options @@ -506,7 +508,7 @@ available in waf. To explore these options, type: :: - ./waf --help + $ ./waf --help We'll use some of the testing-related commands in the next section. @@ -517,7 +519,7 @@ the ``-o`` option to configure; e.g. :: - ./waf configure -d debug -o build/debug --enable-examples --enable-tests + $ ./waf configure -d debug -o build/debug --enable-examples --enable-tests This allows users to work with multiple builds rather than always overwriting the last build. @@ -528,16 +530,16 @@ Say one wants to use Clang C++ compiler, command ``clang++``; it's done by :: - CXX="clang++" ./waf configure - ./waf build + $ CXX="clang++" ./waf configure + $ ./waf build One can also set up waf to do distributed compilation with ``distcc`` in a similar way: :: - CXX="distcc g++" ./waf configure - ./waf build + $ CXX="distcc g++" ./waf configure + $ ./waf build More info on distcc and distributed compilation can be found on it's `project page @@ -552,7 +554,7 @@ You can run the unit tests of the |ns3| distribution by running the :: - ./test.py -c core + $ ./test.py -c core These tests are run in parallel by waf. You should eventually see a report saying that, @@ -617,7 +619,7 @@ ubiquitous hello world program by typing the following: :: - ./waf --run hello-simulator + $ ./waf --run hello-simulator Waf first checks to make sure that the program is built correctly and executes a build if required. Waf then executes the program, which @@ -644,7 +646,7 @@ type the following, :: - ./waf configure -d debug --enable-examples --enable-tests + $ ./waf configure -d debug --enable-examples --enable-tests to tell ``waf`` to build the debug versions of the |ns3| programs that includes the examples and tests. You must still build @@ -652,7 +654,7 @@ the actual debug version of the code by typing, :: - ./waf + $ ./waf Now, if you run the ``hello-simulator`` program, you should see the expected output. diff --git a/doc/tutorial/source/tracing.rst b/doc/tutorial/source/tracing.rst index c80600796..a8cf87db8 100644 --- a/doc/tutorial/source/tracing.rst +++ b/doc/tutorial/source/tracing.rst @@ -1,5 +1,7 @@ .. include:: replace.txt - +.. highlight:: cpp +.. role:: raw-role(raw) + :format: html latex Tracing ------- @@ -426,14 +428,14 @@ called with the parameters provided by the source. If you now build and run this example, -:: +.. sourcecode:: bash - ./waf --run fourth + $ ./waf --run fourth you will see the output from the ``IntTrace`` function execute as soon as the trace source is hit: -:: +.. sourcecode:: bash Traced 0 to 1234 @@ -679,9 +681,9 @@ The easiest way to do this is to grep around in the |ns3| codebase for someone who has already figured it out, You should always try to copy someone else's working code before you start to write your own. Try something like: -:: +.. sourcecode:: bash - find . -name '*.cc' | xargs grep CourseChange | grep Connect + $ find . -name '*.cc' | xargs grep CourseChange | grep Connect and you may find your answer along with working code. For example, in this case, ``./ns-3-dev/examples/wireless/mixed-wireless.cc`` has something @@ -732,7 +734,7 @@ connect. You are looking at the same information for the RandomWalk2dMobilityModel; and the information you want is now right there in front of you in the Doxygen: -:: +.. sourcecode:: bash This object is accessible through the following paths with Config::Set and Config::Connect: @@ -756,7 +758,7 @@ going to be looking for is found in the base class as we have seen. Look further down in the ``GetTypeId`` doxygen. You will find, -:: +.. sourcecode:: bash No TraceSources defined for this type. TraceSources defined in parent class ns3::MobilityModel: @@ -788,9 +790,9 @@ The easiest way to do this is to grep around in the |ns3| codebase for someone who has already figured it out, You should always try to copy someone else's working code. Try something like: -:: +.. sourcecode:: bash - find . -name '*.cc' | xargs grep CourseChange | grep Connect + $ find . -name '*.cc' | xargs grep CourseChange | grep Connect and you may find your answer along with working code. For example, in this case, ``./ns-3-dev/examples/wireless/mixed-wireless.cc`` has something @@ -812,7 +814,7 @@ there is a callback function there which you can use. Sure enough, there is: ... } -Take my Word for It +Take My Word for It ~~~~~~~~~~~~~~~~~~~ If there are no examples to work from, this can be, well, challenging to @@ -899,9 +901,9 @@ We are probably going to be interested in some kind of declaration in the we know this declaration is going to have to be in some kind of header file, so just grep for it using: -:: +.. sourcecode:: bash - find . -name '*.h' | xargs grep TracedCallback + $ find . -name '*.h' | xargs grep TracedCallback You'll see 124 lines fly by (I piped this through wc to see how bad it was). Although that may seem like it, that's not really a lot. Just pipe the output @@ -943,7 +945,7 @@ in your favorite editor to see what is happening. You will see a comment at the top of the file that should be comforting: -:: +.. sourcecode:: text An ns3::TracedCallback has almost exactly the same API as a normal ns3::Callback but instead of forwarding calls to a single function (as an ns3::Callback normally does), @@ -1019,7 +1021,7 @@ If you look down through the file, you will see a lot of probably almost incomprehensible template code. You will eventually come to some Doxygen for the Callback template class, though. Fortunately, there is some English: -:: +.. sourcecode:: text This class template implements the Functor Design Pattern. It is used to declare the type of a Callback: @@ -1179,7 +1181,7 @@ trace sources" to see what we have to work with. Recall that this is found in the |ns3| Doxygen in the "C++ Constructs Used by All Modules" Module section. If you scroll through the list, you will eventually find: -:: +.. sourcecode:: bash ns3::TcpNewReno CongestionWindow: The TCP connection's congestion window @@ -1189,9 +1191,9 @@ file ``src/internet/model/tcp-socket-base.cc`` while congestion control variants are in files such as ``src/internet/model/tcp-newreno.cc``. If you don't know this a priori, you can use the recursive grep trick: -:: +.. sourcecode:: bash - find . -name '*.cc' | xargs grep -i tcp + $ find . -name '*.cc' | xargs grep -i tcp You will find page after page of instances of tcp pointing you to that file. @@ -1247,9 +1249,9 @@ modify, rather than starting from scratch. So the first order of business now is to find some code that already hooks the "CongestionWindow" trace source and see if we can modify it. As usual, grep is your friend: -:: +.. sourcecode:: bash - find . -name '*.cc' | xargs grep CongestionWindow + $ find . -name '*.cc' | xargs grep CongestionWindow This will point out a couple of promising candidates: ``examples/tcp/tcp-large-transfer.cc`` and @@ -1954,10 +1956,10 @@ Since we have provided the file ``fifth.cc`` for you, if you have built your distribution (in debug mode since it uses NS_LOG -- recall that optimized builds optimize out NS_LOGs) it will be waiting for you to run. -:: +.. sourcecode:: bash - ./waf --run fifth - Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-dev/ns-3-dev/build + $ ./waf --run fifth + Waf: Entering directory `/home/craigdo/repos/ns-3-allinone-dev/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone-dev/ns-3-dev/build' 'build' finished successfully (0.684s) 1.20919 1072 @@ -1976,9 +1978,9 @@ information along with those RxDrop messages. We will remedy that soon, but I'm sure you can't wait to see the results of all of this work. Let's redirect that output to a file called ``cwnd.dat``: -:: +.. sourcecode:: bash - ./waf --run fifth > cwnd.dat 2>&1 + $ ./waf --run fifth > cwnd.dat 2>&1 Now edit up "cwnd.dat" in your favorite editor and remove the waf build status and drop lines, leaving only the traced data (you could also comment out the @@ -1988,8 +1990,9 @@ script to get rid of the drop prints just as easily. You can now run gnuplot (if you have it installed) and tell it to generate some pretty pictures: -:: +.. sourcecode:: bash + $ gnuplot gnuplot> set terminal png size 640,480 gnuplot> set output "cwnd.png" gnuplot> plot "cwnd.dat" using 1:2 title 'Congestion Window' with linespoints @@ -2187,21 +2190,21 @@ mean that "something" is an |ns3| Object on which you can hang |ns3| Now, back to the example. If you now build and run this example, -:: +.. sourcecode:: bash - ./waf --run sixth + $ ./waf --run sixth you will see the same messages appear as when you ran "fifth", but two new files will appear in the top-level directory of your |ns3| distribution. -:: +.. sourcecode:: bash sixth.cwnd sixth.pcap Since "sixth.cwnd" is an ASCII text file, you can view it with ``cat`` or your favorite file viewer. -:: +.. sourcecode:: bash 1.20919 536 1072 1.21511 1072 1608 @@ -2215,7 +2218,7 @@ There are no extraneous prints in the file, no parsing or editing is required. Since "sixth.pcap" is a pcap file, you can fiew it with ``tcpdump``. -:: +.. sourcecode:: bash reading from file ../../sixth.pcap, link-type PPP (PPP) 1.251507 IP 10.1.1.1.49153 > 10.1.1.2.8080: . 17689:18225(536) ack 1 win 65535 @@ -2305,14 +2308,13 @@ There are subtleties that prevent all four classes from behaving identically, but we do strive to make them all work as similarly as possible; and whenever possible there are analogs for all methods in all classes. -:: - - | pcap | ascii | - -----------------+------+-------| - Device Helper | | | - -----------------+------+-------| - Protocol Helper | | | - -----------------+------+-------| + +-----------------+----------------------+----------------------+ + | \ | pcap | ascii | + +=================+======================+======================+ + | Device Helper | :raw-role:`✓` | :raw-role:`✓` | + +-----------------+----------------------+----------------------+ + | Protocol Helper | :raw-role:`✓` | :raw-role:`✓` | + +-----------------+----------------------+----------------------+ We use an approach called a ``mixin`` to add tracing functionality to our helper classes. A ``mixin`` is a class that provides functionality to that diff --git a/doc/tutorial/source/tweaking.rst b/doc/tutorial/source/tweaking.rst index bb4d200a3..fd98b68b7 100644 --- a/doc/tutorial/source/tweaking.rst +++ b/doc/tutorial/source/tweaking.rst @@ -1,4 +1,5 @@ .. include:: replace.txt +.. highlight:: cpp Tweaking @@ -80,16 +81,16 @@ Let's use the NS_LOG environment variable to turn on some more logging, but first, just to get our bearings, go ahead and run the last script just as you did previously, -:: +.. sourcecode:: bash - ./waf --run scratch/myfirst + $ ./waf --run scratch/myfirst You should see the now familiar output of the first |ns3| example program -:: +.. sourcecode:: bash - Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' + $ Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' 'build' finished successfully (0.413s) Sent 1024 bytes to 10.1.1.2 @@ -121,13 +122,13 @@ all lower levels. In this case, we have enabled ``NS_LOG_INFO``, increase the logging level and get more information without changing the script and recompiling by setting the NS_LOG environment variable like this: -:: +.. sourcecode:: bash - export NS_LOG=UdpEchoClientApplication=level_all + $ export NS_LOG=UdpEchoClientApplication=level_all This sets the shell environment variable ``NS_LOG`` to the string, -:: +.. sourcecode:: bash UdpEchoClientApplication=level_all @@ -137,9 +138,9 @@ we are going to turn on all of the debugging levels for the application. If you run the script with NS_LOG set this way, the |ns3| logging system will pick up the change and you should see the following output: -:: +.. sourcecode:: bash - Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build + Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' 'build' finished successfully (0.404s) UdpEchoClientApplication:UdpEchoClient() @@ -183,9 +184,9 @@ wonder where the string "``Received 1024 bytes from 10.1.1.2``" comes from. You can resolve this by OR'ing the ``prefix_func`` level into the ``NS_LOG`` environment variable. Try doing the following, -:: +.. sourcecode:: bash - export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func' + $ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func' Note that the quotes are required since the vertical bar we use to indicate an OR operation is also a Unix pipe connector. @@ -194,7 +195,7 @@ Now, if you run the script you will see that the logging system makes sure that every message from the given log component is prefixed with the component name. -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -219,9 +220,9 @@ remaining message must be coming from the UDP echo server application. We can enable that component by entering a colon separated list of components in the NS_LOG environment variable. -:: +.. sourcecode:: bash - export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func: + $ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func: UdpEchoServerApplication=level_all|prefix_func' Warning: You will need to remove the newline after the ``:`` in the @@ -231,7 +232,7 @@ Now, if you run the script you will see all of the log messages from both the echo client and server applications. You may see that this can be very useful in debugging problems. -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -258,15 +259,15 @@ in debugging problems. It is also sometimes useful to be able to see the simulation time at which a log message is generated. You can do this by ORing in the prefix_time bit. -:: +.. sourcecode:: bash - export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time: + $ export 'NS_LOG=UdpEchoClientApplication=level_all|prefix_func|prefix_time: UdpEchoServerApplication=level_all|prefix_func|prefix_time' Again, you will have to remove the newline above. If you run the script now, you should see the following output: -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -314,9 +315,9 @@ are not seeing as well. You can very easily follow the entire process by turning on all of the logging components in the system. Try setting the ``NS_LOG`` variable to the following, -:: +.. sourcecode:: bash - export 'NS_LOG=*=level_all|prefix_func|prefix_time' + $ export 'NS_LOG=*=level_all|prefix_func|prefix_time' The asterisk above is the logging component wildcard. This will turn on all of the logging in all of the components used in the simulation. I won't @@ -324,9 +325,9 @@ reproduce the output here (as of this writing it produces 1265 lines of output for the single packet echo) but you can redirect this information into a file and look through it with your favorite editor if you like, -:: +.. sourcecode:: bash - ./waf --run scratch/myfirst > log.out 2>&1 + $ ./waf --run scratch/myfirst > log.out 2>&1 I personally use this extremely verbose version of logging when I am presented with a problem and I have no idea where things are going wrong. I can follow the @@ -374,16 +375,16 @@ right before the lines, Now build the script using waf and clear the ``NS_LOG`` variable to turn off the torrent of logging we previously enabled: -:: +.. sourcecode:: bash - ./waf - export NS_LOG= + $ ./waf + $ export NS_LOG= Now, if you run the script, -:: +.. sourcecode:: bash - ./waf --run scratch/myfirst + $ ./waf --run scratch/myfirst you will ``not`` see your new message since its associated logging component (``FirstScriptExample``) has not been enabled. In order to see your @@ -391,14 +392,14 @@ message you will have to enable the ``FirstScriptExample`` logging component with a level greater than or equal to ``NS_LOG_INFO``. If you just want to see this particular level of logging, you can enable it by, -:: +.. sourcecode:: bash - export NS_LOG=FirstScriptExample=info + $ export NS_LOG=FirstScriptExample=info If you now run the script you will see your new "Creating Topology" log message, -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -441,16 +442,16 @@ ahead and add that two lines of code to the ``scratch/myfirst.cc`` script at the start of ``main``. Go ahead and build the script and run it, but ask the script for help in the following way, -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst --PrintHelp" + $ ./waf --run "scratch/myfirst --PrintHelp" This will ask Waf to run the ``scratch/myfirst`` script and pass the command line argument ``--PrintHelp`` to the script. The quotes are required to sort out which program gets which argument. The command line parser will now see the ``--PrintHelp`` argument and respond with, -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -481,14 +482,14 @@ listing says that we should provide a ``TypeId``. This corresponds to the class name of the class to which the ``Attributes`` belong. In this case it will be ``ns3::PointToPointNetDevice``. Let's go ahead and type in, -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice" + $ ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointNetDevice" The system will print out all of the ``Attributes`` of this kind of net device. Among the ``Attributes`` you will see listed is, -:: +.. sourcecode:: bash --ns3::PointToPointNetDevice::DataRate=[32768bps]: The default data rate for point to point links @@ -521,13 +522,13 @@ Go ahead and build the new script with Waf (``./waf``) and let's go back and enable some logging from the UDP echo server application and turn on the time prefix. -:: +.. sourcecode:: bash - export 'NS_LOG=UdpEchoServerApplication=level_all|prefix_time' + $ export 'NS_LOG=UdpEchoServerApplication=level_all|prefix_time' If you run the script, you should now see the following output, -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -545,7 +546,7 @@ If you run the script, you should now see the following output, Recall that the last time we looked at the simulation time at which the packet was received by the echo server, it was at 2.00369 seconds. -:: +.. sourcecode:: bash 2.00369s UdpEchoServerApplication:HandleRead(): Received 1024 bytes from 10.1.1.1 @@ -557,9 +558,9 @@ If we were to provide a new ``DataRate`` using the command line, we could speed our simulation up again. We do this in the following way, according to the formula implied by the help item: -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps" + $ ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps" This will set the default value of the ``DataRate`` ``Attribute`` back to five megabits per second. Are you surprised by the result? It turns out that @@ -568,30 +569,30 @@ the speed-of-light delay of the channel as well. We can ask the command line system to print out the ``Attributes`` of the channel just like we did for the net device: -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel" + $ ./waf --run "scratch/myfirst --PrintAttributes=ns3::PointToPointChannel" We discover the ``Delay`` ``Attribute`` of the channel is set in the following way: -:: +.. sourcecode:: bash --ns3::PointToPointChannel::Delay=[0ns]: Transmission delay through the channel We can then set both of these default values through the command line system, -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst + $ ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps --ns3::PointToPointChannel::Delay=2ms" in which case we recover the timing we had when we explicitly set the ``DataRate`` and ``Delay`` in the script: -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -620,9 +621,9 @@ you should be able to control the number of packets echoed from the command line. Since we're nice folks, we'll tell you that your command line should end up looking something like, -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst + $ ./waf --run "scratch/myfirst --ns3::PointToPointNetDevice::DataRate=5Mbps --ns3::PointToPointChannel::Delay=2ms --ns3::UdpEchoClient::MaxPackets=2" @@ -666,11 +667,11 @@ should see your new ``User Argument`` listed in the help display. Try, -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst --PrintHelp" + $ ./waf --run "scratch/myfirst --PrintHelp" -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -687,13 +688,13 @@ Try, If you want to specify the number of packets to echo, you can now do so by setting the ``--nPackets`` argument in the command line, -:: +.. sourcecode:: bash - ./waf --run "scratch/myfirst --nPackets=2" + $ ./waf --run "scratch/myfirst --nPackets=2" You should now see -:: +.. sourcecode:: bash Waf: Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build' @@ -821,9 +822,9 @@ the popular trace points that log "+", "-", "d", and "r" events. You can now build the script and run it from the command line: -:: +.. sourcecode:: bash - ./waf --run scratch/myfirst + $ ./waf --run scratch/myfirst Just as you have seen many times before, you will see some messages from Waf and then "'build' finished successfully" with some number of messages from @@ -856,31 +857,32 @@ space after it). This character will have the following meaning: * ``r``: A packet was received by the net device. Let's take a more detailed view of the first line in the trace file. I'll -break it down into sections (indented for clarity) with a two digit reference +break it down into sections (indented for clarity) with a reference number on the left side: -:: +.. sourcecode:: text + :linenos: - 00 + - 01 2 - 02 /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue - 03 ns3::PppHeader ( - 04 Point-to-Point Protocol: IP (0x0021)) - 05 ns3::Ipv4Header ( - 06 tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none] - 07 length: 1052 10.1.1.1 > 10.1.1.2) - 08 ns3::UdpHeader ( - 09 length: 1032 49153 > 9) - 10 Payload (size=1024) + + + 2 + /NodeList/0/DeviceList/0/$ns3::PointToPointNetDevice/TxQueue/Enqueue + ns3::PppHeader ( + Point-to-Point Protocol: IP (0x0021)) + ns3::Ipv4Header ( + tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none] + length: 1052 10.1.1.1 > 10.1.1.2) + ns3::UdpHeader ( + length: 1032 49153 > 9) + Payload (size=1024) -The first line of this expanded trace event (reference number 00) is the +The first section of this expanded trace event (reference number 0) is the operation. We have a ``+`` character, so this corresponds to an -*enqueue* operation on the transmit queue. The second line (reference 01) +*enqueue* operation on the transmit queue. The second section (reference 1) is the simulation time expressed in seconds. You may recall that we asked the ``UdpEchoClientApplication`` to start sending packets at two seconds. Here we see confirmation that this is, indeed, happening. -The next line of the example trace (reference 02) tell us which trace source +The next section of the example trace (reference 2) tell us which trace source originated this event (expressed in the tracing namespace). You can think of the tracing namespace somewhat like you would a filesystem namespace. The root of the namespace is the ``NodeList``. This corresponds to a container @@ -899,11 +901,11 @@ Recall that the operation ``+`` found at reference 00 meant that an enqueue operation happened on the transmit queue of the device. This is reflected in the final segments of the "trace path" which are ``TxQueue/Enqueue``. -The remaining lines in the trace should be fairly intuitive. References 03-04 +The remaining sections in the trace should be fairly intuitive. References 3-4 indicate that the packet is encapsulated in the point-to-point protocol. -References 05-07 show that the packet has an IP version four header and has +References 5-7 show that the packet has an IP version four header and has originated from IP address 10.1.1.1 and is destined for 10.1.1.2. References -08-09 show that this packet has a UDP header and, finally, reference 10 shows +8-9 show that this packet has a UDP header and, finally, reference 10 shows that the payload is the expected 1024 bytes. The next line in the trace file shows the same packet being dequeued from the @@ -912,17 +914,18 @@ transmit queue on the same node. The Third line in the trace file shows the packet being received by the net device on the node with the echo server. I have reproduced that event below. -:: +.. sourcecode:: text + :linenos: - 00 r - 01 2.25732 - 02 /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx - 03 ns3::Ipv4Header ( - 04 tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none] - 05 length: 1052 10.1.1.1 > 10.1.1.2) - 06 ns3::UdpHeader ( - 07 length: 1032 49153 > 9) - 08 Payload (size=1024) + r + 2.25732 + /NodeList/1/DeviceList/0/$ns3::PointToPointNetDevice/MacRx + ns3::Ipv4Header ( + tos 0x0 ttl 64 id 0 protocol 17 offset 0 flags [none] + length: 1052 10.1.1.1 > 10.1.1.2) + ns3::UdpHeader ( + length: 1032 49153 > 9) + Payload (size=1024) Notice that the trace operation is now ``r`` and the simulation time has increased to 2.25732 seconds. If you have been following the tutorial steps @@ -968,9 +971,9 @@ node 1-device 0, respectively. Once you have added the line of code to enable pcap tracing, you can run the script in the usual way: -:: +.. sourcecode:: bash - ./waf --run scratch/myfirst + $ ./waf --run scratch/myfirst If you look at the top level directory of your distribution, you should now see three log files: ``myfirst.tr`` is the ASCII trace file we have @@ -982,9 +985,9 @@ Reading output with tcpdump The easiest thing to do at this point will be to use ``tcpdump`` to look at the ``pcap`` files. -:: +.. sourcecode:: bash - tcpdump -nn -tt -r myfirst-0-0.pcap + $ tcpdump -nn -tt -r myfirst-0-0.pcap reading from file myfirst-0-0.pcap, link-type PPP (PPP) 2.000000 IP 10.1.1.1.49153 > 10.1.1.2.9: UDP, length 1024 2.514648 IP 10.1.1.2.9 > 10.1.1.1.49153: UDP, length 1024 diff --git a/src/aodv/helper/aodv-helper.h b/src/aodv/helper/aodv-helper.h index 919f5c9d6..d39fed424 100644 --- a/src/aodv/helper/aodv-helper.h +++ b/src/aodv/helper/aodv-helper.h @@ -38,9 +38,9 @@ public: AodvHelper(); /** - * \internal * \returns pointer to clone of this OlsrHelper * + * \internal * This method is mainly for internal use by the other helpers; * clients are expected to free the dynamic memory allocated by this method */ @@ -76,6 +76,7 @@ public: int64_t AssignStreams (NodeContainer c, int64_t stream); private: + /** the factory to create AODV routing object */ ObjectFactory m_agentFactory; }; diff --git a/src/click/model/ipv4-l3-click-protocol.cc b/src/click/model/ipv4-l3-click-protocol.cc index 8761bd0cd..4b721d5e2 100644 --- a/src/click/model/ipv4-l3-click-protocol.cc +++ b/src/click/model/ipv4-l3-click-protocol.cc @@ -434,6 +434,29 @@ Ipv4L3ClickProtocol::RemoveAddress (uint32_t i, uint32_t addressIndex) return false; } +bool +Ipv4L3ClickProtocol::RemoveAddress (uint32_t i, Ipv4Address address) +{ + NS_LOG_FUNCTION (this << i << address); + + if (address == Ipv4Address::GetLoopback()) + { + NS_LOG_WARN ("Cannot remove loopback address."); + return false; + } + Ptr interface = GetInterface (i); + Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address); + if (ifAddr != Ipv4InterfaceAddress ()) + { + if (m_routingProtocol != 0) + { + m_routingProtocol->NotifyRemoveAddress (i, ifAddr); + } + return true; + } + return false; +} + Ipv4Address Ipv4L3ClickProtocol::SelectSourceAddress (Ptr device, Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope) diff --git a/src/click/model/ipv4-l3-click-protocol.h b/src/click/model/ipv4-l3-click-protocol.h index 3f0bece9c..0c35738e3 100644 --- a/src/click/model/ipv4-l3-click-protocol.h +++ b/src/click/model/ipv4-l3-click-protocol.h @@ -215,6 +215,7 @@ public: Ipv4InterfaceAddress GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const; uint32_t GetNAddresses (uint32_t interface) const; bool RemoveAddress (uint32_t interfaceIndex, uint32_t addressIndex); + bool RemoveAddress (uint32_t interfaceIndex, Ipv4Address address); Ipv4Address SelectSourceAddress (Ptr device, Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope); diff --git a/src/core/examples/command-line-example.cc b/src/core/examples/command-line-example.cc index 196945075..e7da99c60 100644 --- a/src/core/examples/command-line-example.cc +++ b/src/core/examples/command-line-example.cc @@ -47,13 +47,13 @@ int main (int argc, char *argv[]) cmd.Usage ("CommandLine example program.\n" "\n" "This little program demonstrates how to use CommandLine."); - cmd.AddValue ("val1", "an int argument", val1); - cmd.AddValue ("val2", "a bool argument", val2); - cmd.AddValue ("val3", "a string argument", val3); + cmd.AddValue ("val1", "an int argument", val1); + cmd.AddValue ("val2", "a bool argument", val2); + cmd.AddValue ("val3", "a string argument", val3); cmd.AddValue ("val4", "a string via callback", MakeCallback (SetVal4)); cmd.Parse (argc, argv); - std::cout << "val1:\t" << val1 << std::endl; + std::cout << "val1:\t" << val1 << std::endl; std::cout << "val2:\t" << std::boolalpha << val2 << std::noboolalpha << std::endl; std::cout << "val3:\t\"" << val3 << "\"" << std::endl; diff --git a/src/core/model/assert.h b/src/core/model/assert.h index 9ecde44ed..8b2f4652c 100644 --- a/src/core/model/assert.h +++ b/src/core/model/assert.h @@ -28,7 +28,7 @@ #include "fatal-error.h" /** - * \ingroup constructs + * \ingroup core * \defgroup debugging Debugging */ /** diff --git a/src/core/model/attribute-helper.h b/src/core/model/attribute-helper.h index ffc25a1f7..e94fc5dc7 100644 --- a/src/core/model/attribute-helper.h +++ b/src/core/model/attribute-helper.h @@ -27,6 +27,34 @@ namespace ns3 { +/** + * \ingroup attribute + * \defgroup attributehelper Attribute Helper + * + * All these macros can be used to generate automatically the code + * for subclasses of AttributeValue, AttributeAccessor, and, AttributeChecker, + * which can be used to give attribute powers to a normal class. i.e., + * the user class can then effectively be made an attribute. + * + * There are two kinds of helper macros: + * 1) The simple macros. + * - ATTRIBUTE_HELPER_HEADER(type) + * - ATTRIBUTE_HELPER_CPP + * 2) The more complex macros. + * + * The simple macros are implemented in terms of the complex + * macros and should generally be preferred over the complex macros. + */ + +/** + * \ingroup attributehelper + * + * A simple string-based attribute checker + * + * \param name value type of the attribute + * \param underlying underlying type name + * \return Ptr to AttributeChecker + */ template Ptr MakeSimpleAttributeChecker (std::string name, std::string underlying) @@ -69,26 +97,7 @@ MakeSimpleAttributeChecker (std::string name, std::string underlying) } /** - * \ingroup core - * \defgroup AttributeHelper Attribute Helper - * - * All these macros can be used to generate automatically the code - * for subclasses of AttributeValue, AttributeAccessor, and, AttributeChecker, - * which can be used to give attribute powers to a normal class. i.e., - * the user class can then effectively be made an attribute. - * - * There are two kinds of helper macros: - * 1) The simple macros. - * 2) The more complex macros. - * - * The simple macros are implemented in terms of the complex - * macros and should generally be preferred over the complex macros: - * - \ref ATTRIBUTE_HELPER_HEADER, and, - * - \ref ATTRIBUTE_HELPER_CPP, - */ - -/** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class * * This macro defines and generates the code for the implementation @@ -109,6 +118,10 @@ MakeSimpleAttributeChecker (std::string name, std::string underlying) return MakeAccessorHelper (a1, a2); \ } +/** + * \ingroup attributehelper + * \internal + */ #define ATTRIBUTE_VALUE_DEFINE_WITH_NAME(type,name) \ class name ## Value : public AttributeValue \ { \ @@ -131,7 +144,7 @@ private: \ /** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class. * * This macro defines the class \c typeValue associated to class \c type. @@ -142,7 +155,7 @@ private: \ /** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class * * This macro defines the conversion operators for class \c type to and @@ -152,7 +165,7 @@ private: \ #define ATTRIBUTE_CONVERTER_DEFINE(type) /** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class * * This macro defines the \c typeChecker class and the associated @@ -164,6 +177,10 @@ private: \ Ptr Make ## type ## Checker (void); \ +/** + * \ingroup attributehelper + * \internal + */ #define ATTRIBUTE_VALUE_IMPLEMENT_WITH_NAME(type,name) \ name ## Value::name ## Value () \ : m_value () {} \ @@ -194,7 +211,7 @@ private: \ } /** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class. * * This macro implements the \c typeValue class (including the @@ -207,7 +224,7 @@ private: \ /** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class * * This macro implements the \c MakeChecker function. @@ -219,6 +236,10 @@ private: \ return MakeSimpleAttributeChecker (# type "Value", # type); \ } \ +/** + * \ingroup attributehelper + * \internal + */ #define ATTRIBUTE_CHECKER_IMPLEMENT_WITH_NAME(type,name) \ Ptr Make ## type ## Checker (void) \ { \ @@ -226,7 +247,7 @@ private: \ } \ /** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class * * This macro should be invoked outside of the class @@ -238,7 +259,7 @@ private: \ ATTRIBUTE_CHECKER_DEFINE (type); /** - * \ingroup AttributeHelper + * \ingroup attributehelper * \param type the name of the class * * This macro should be invoked from the class implementation file. diff --git a/src/core/model/attribute.h b/src/core/model/attribute.h index 4f35ce359..3f336e50d 100644 --- a/src/core/model/attribute.h +++ b/src/core/model/attribute.h @@ -35,7 +35,12 @@ class ObjectBase; /** * * \ingroup core - * \defgroup attribute Attribute + * \defgroup attribute Attributes + * + * The \c ns-3 attribute system is the mechanism used in \c ns-3 to + * organize, document, and modify the *values* used by the various + * component models. Attributes also enable the tracing and statistics + * gathering in the simulator. */ /** @@ -152,6 +157,13 @@ public: AttributeChecker (); virtual ~AttributeChecker (); + /** + * Create a valid value from the argument value, + * or reinterpret the argument as a string. + * + * \param value the AttributeValue to check + * \return Ptr to a valid value + */ Ptr CreateValidValue (const AttributeValue &value) const; /** * \param value a pointer to the value to check @@ -190,7 +202,13 @@ public: * to calling Attribute::DeserializeFromString. */ virtual Ptr Create (void) const = 0; + /** + * Copy the source to the destination + * \param source source AttributeValue + * \param destination destination AttributeValue + * \return true if copy was successful + */ virtual bool Copy (const AttributeValue &source, AttributeValue &destination) const = 0; diff --git a/src/core/model/breakpoint.h b/src/core/model/breakpoint.h index 0f06349e2..56e146027 100644 --- a/src/core/model/breakpoint.h +++ b/src/core/model/breakpoint.h @@ -57,6 +57,8 @@ namespace ns3 { #endif /** + * \ingroup debugging + * * \brief fallback breakpoint function * * This function is used by the NS_BREAKPOINT() macro as a fallback diff --git a/src/core/model/callback.h b/src/core/model/callback.h index 027d79fe6..44fb575df 100644 --- a/src/core/model/callback.h +++ b/src/core/model/callback.h @@ -883,7 +883,7 @@ protected: * as well as the function templates \ref MakeCallback : * \include src/core/examples/main-callback.cc * - * \intern + * \internal * This code was originally written based on the techniques * described in http://www.codeproject.com/cpp/TTLFunction.asp * It was subsequently rewritten to follow the architecture @@ -926,7 +926,7 @@ public: * * \param functor the functor to run on this callback * - * \intern + * \internal * There are two dummy args below to ensure that this constructor is * always properly disambiguated by the c++ compiler. */ @@ -1445,7 +1445,7 @@ Callback MakeNullCallback (void) { * Build bound Callbacks which take varying numbers of arguments, * and potentially returning a value. * - * \intern + * \internal * * The following is experimental code. It works but we have * not yet determined whether or not it is really useful and whether diff --git a/src/core/model/command-line.h b/src/core/model/command-line.h index 6fee0f900..ba13248ad 100644 --- a/src/core/model/command-line.h +++ b/src/core/model/command-line.h @@ -47,36 +47,49 @@ namespace ns3 { * arguments: programs can register new arguments with * CommandLine::AddValue. * + * In use, arguments are given in the form + * \code + * --arg=value --toggle + * \endcode + * Most arguments expect a value, as in the first form, \c --arg=value. + * Toggles, corresponding to boolean arguments, can be given in any of + * the forms + * \code + * --toggle-1 --toggle-2=1 --toggle-3=t --toggle-4=true + * \endcode + * all of which set the corresponding boolean variable to true. + * * In addition, this class can be used to set the - * 'initial value' of every attribute in the system with the + * initial value of every attribute in the system with the + * \c --TypeIdName::AttributeName=value syntax, for example * \code - * --TypeIdName::AttributeName=value + * --Application::StartTime=3s * \endcode - * syntax, and it can be used to set the value of every GlobalValue - * in the system with the + * + * This class can also be used to set the value of every GlobalValue + * in the system with the \c --GlobalValueName=value syntax, for example * \code - * --GlobalValueName=value + * --SchedulerType=HeapScheduler * \endcode - * syntax. * * A simple example is in \c src/core/example/command-line-example.cc * The heart of that example is this code: * * \code - * int val1 = 1; - * bool val2 = false; - * std::string val3 = ""; + * int var1 = 1; + * bool var2 = false; + * std::string var3 = ""; * * CommandLine cmd; * cmd.Usage ("CommandLine example program.\n" * "\n" * "This little program demonstrates how to use CommandLine."); - * cmd.AddValue ("val1", "an int argument", val1); - * cmd.AddValue ("val2", "a bool argument", val2); - * cmd.AddValue ("val3", "a string argument", val3); - * cmd.AddValue ("val4", "a string via callback", MakeCallback (SetVal4)); + * cmd.AddValue ("val1", "an int argument", val1); + * cmd.AddValue ("val2", "a bool argument", val2); + * cmd.AddValue ("val3", "a string argument", val3); * cmd.Parse (argc, argv); * \endcode + * after which it prints the values of each variable. * * Here is the output from a few runs of that program: * @@ -84,14 +97,12 @@ namespace ns3 { * $ ./waf --run="command-line-example" * val1: 1 * val2: 0 - * val3: "val3 default" - * val4: "val4 default" + * val3: "" * - * $ ./waf --run="command-line-example --val1=2 --val2 --val3=Hello --val4=World" + * $ ./waf --run="command-line-example --val1=2 --val2 --val3=Hello" * val1: 2 * val2: 1 * val3: "Hello" - * val4: "World" * * $ ./waf --run="command-line-example --help" * ns3-dev-command-line-example-debug [Program Arguments] [General Arguments] @@ -101,10 +112,9 @@ namespace ns3 { * This little program demonstrates how to use CommandLine. * * Program Arguments: - * --val1: an int argument - * --val2: a bool argument - * --val3: a string argument - * --val4: a string via callback + * --val1: an int argument + * --val2: a bool argument + * --val3: a string argument * * General Arguments: * --PrintGlobals: Print the list of globals. diff --git a/src/core/model/event-id.h b/src/core/model/event-id.h index c9cf4c396..5bad1e19e 100644 --- a/src/core/model/event-id.h +++ b/src/core/model/event-id.h @@ -29,7 +29,7 @@ namespace ns3 { class EventImpl; /** - * \ingroup core + * \ingroup events * \brief an identifier for simulation events. * * Each EventId identifies a unique event scheduled with one diff --git a/src/core/model/event-impl.h b/src/core/model/event-impl.h index 9eef400f2..8949894a8 100644 --- a/src/core/model/event-impl.h +++ b/src/core/model/event-impl.h @@ -26,7 +26,7 @@ namespace ns3 { /** - * \ingroup core + * \ingroup events * \brief a simulation event * * Each subclass of this base class represents a simulation event. The diff --git a/src/core/model/hash-murmur3.cc b/src/core/model/hash-murmur3.cc index 02bb64ae6..103ac8862 100644 --- a/src/core/model/hash-murmur3.cc +++ b/src/core/model/hash-murmur3.cc @@ -44,6 +44,9 @@ namespace Function { namespace Murmur3Implementation { +// Changes from Murmur3 distribution are marked with `//PDB' +// + /************************************************* ** class Murmur3HashImplementation ************************************************/ @@ -177,7 +180,8 @@ void MurmurHash3_x86_32_incr ( const void * key, int len, k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1; }; - *(uint32_t*)out = h1; + uint32_t * res = (uint32_t *)out; //PDB: strict aliasing + *res = h1; } //PDB - incremental hashing - finalization @@ -193,7 +197,8 @@ void MurmurHash3_x86_32_fin ( int len, h1 = fmix(h1); - *(uint32_t*)out = h1; + uint32_t * res = (uint32_t *)out; //PDB: strict aliasing + *res = h1; } //----------------------------------------------------------------------------- @@ -296,10 +301,11 @@ void MurmurHash3_x86_128_incr ( const void * key, const int len, k1 *= c1; k1 = rotl32(k1,15); k1 *= c2; h1 ^= k1; }; - ((uint32_t*)out)[0] = h1; - ((uint32_t*)out)[1] = h2; - ((uint32_t*)out)[2] = h3; - ((uint32_t*)out)[3] = h4; + uint32_t * res = (uint32_t *)out; //PDB: strict aliasing + res[0] = h1; + res[1] = h2; + res[2] = h3; + res[3] = h4; } //PDB - incremental hashing - finalization @@ -327,10 +333,11 @@ void MurmurHash3_x86_128_fin ( const int len, h1 += h2; h1 += h3; h1 += h4; h2 += h1; h3 += h1; h4 += h1; - ((uint32_t*)out)[0] = h1; - ((uint32_t*)out)[1] = h2; - ((uint32_t*)out)[2] = h3; - ((uint32_t*)out)[3] = h4; + uint32_t * res = (uint32_t *)out; //PDB: strict aliasing + res[0] = h1; + res[1] = h2; + res[2] = h3; + res[3] = h4; } //----------------------------------------------------------------------------- @@ -410,8 +417,9 @@ void MurmurHash3_x64_128 ( const void * key, const int len, h1 += h2; h2 += h1; - ((uint64_t*)out)[0] = h1; - ((uint64_t*)out)[1] = h2; + uint32_t * res = (uint32_t *)out; //PDB: strict aliasing + res[0] = h1; + res[1] = h2; } @@ -419,13 +427,14 @@ void MurmurHash3_x64_128 ( const void * key, const int len, #undef BIG_CONSTANT + //----------------------------------------------------------------------------- } // namespace Murmur3Implementation -Murmur3:: Murmur3 () +Murmur3::Murmur3 () { clear (); } diff --git a/src/core/model/int64x64.cc b/src/core/model/int64x64.cc index b97250668..abb6ee403 100644 --- a/src/core/model/int64x64.cc +++ b/src/core/model/int64x64.cc @@ -1,6 +1,7 @@ #include "int64x64.h" #include #include +#include // showpos #include #include "assert.h" #include "log.h" @@ -38,7 +39,7 @@ static uint64_t PowerOfTen (uint8_t n) std::ostream &operator << (std::ostream &os, const int64x64_t &value) { int64_t hi = value.GetHigh (); - os << ((hi<0) ? "-" : "+") << ((hi<0) ? -hi : hi) << "."; + os << std::showpos << hi << std::noshowpos << "."; uint64_t low = value.GetLow (); uint8_t msd = MostSignificantDigit (~((uint64_t)0)); do diff --git a/src/core/model/nstime.h b/src/core/model/nstime.h index 4a5a672ba..7bb07b472 100644 --- a/src/core/model/nstime.h +++ b/src/core/model/nstime.h @@ -414,7 +414,7 @@ private: { bool toMul; bool fromMul; - uint64_t factor; + int64_t factor; int64x64_t timeTo; int64x64_t timeFrom; }; @@ -687,7 +687,7 @@ Ptr MakeTimeChecker (void) } /** - * \brief Helper to make a Time checker with an upper bound + * \brief Helper to make a Time checker with a lower bound. * * \return the AttributeChecker */ diff --git a/src/core/model/object-base.h b/src/core/model/object-base.h index f93cd9b4c..a3cc4ac68 100644 --- a/src/core/model/object-base.h +++ b/src/core/model/object-base.h @@ -55,8 +55,14 @@ class AttributeConstructionList; class ObjectBase { public: + /** + * Get the type ID. + */ static TypeId GetTypeId (void); + /** + * Virtual destructor + */ virtual ~ObjectBase (); /** diff --git a/src/core/model/object.h b/src/core/model/object.h index 35311d79c..87e1edbd7 100644 --- a/src/core/model/object.h +++ b/src/core/model/object.h @@ -63,6 +63,9 @@ struct ObjectDeleter class Object : public SimpleRefCount { public: + /** + * Get the type ID. + */ static TypeId GetTypeId (void); /** @@ -90,9 +93,9 @@ public: Ptr Next (void); private: friend class Object; - AggregateIterator (Ptr object); - Ptr m_object; - uint32_t m_current; + AggregateIterator (Ptr object); //!< Constructor + Ptr m_object; //!< Parent Object + uint32_t m_current; //!< Current position in parent's aggegrates }; Object (); @@ -241,8 +244,27 @@ private: Object *buffer[1]; }; + /** + * Find an object of TypeId tid in the aggregates of this Object. + * + * \param tid the TypeId we're looking for + * \return the matching Object, if it is found + */ Ptr DoGetObject (TypeId tid) const; + /** + * \return is reference count non zero + */ bool Check (void) const; + /** + * \return Do any of our aggregates have non zero reference count? + * + * In some cases, when an event is scheduled against a subclass of + * Object, and if no one owns a reference directly to this object, the + * object is alive, has a refcount of zero and the method ran when the + * event expires runs against the raw pointer which means that we are + * manipulating an object with a refcount of zero. So, instead we + * check the aggregate reference count. + */ bool CheckLoose (void) const; /** * \param tid an TypeId @@ -262,6 +284,12 @@ private: */ void Construct (const AttributeConstructionList &attributes); + /** + * Keep the list of aggregates in most-recently-used order + * + * \param aggregates the list of aggregated objects + * \param i the most recently used entry in the list + */ void UpdateSortedArray (struct Aggregates *aggregates, uint32_t i) const; /** * Attempt to delete this object. This method iterates diff --git a/src/core/model/random-variable-stream.h b/src/core/model/random-variable-stream.h index de178bcee..5b5f855f5 100644 --- a/src/core/model/random-variable-stream.h +++ b/src/core/model/random-variable-stream.h @@ -33,6 +33,36 @@ namespace ns3 { +/** + * \ingroup core + * \defgroup randomvariable Random Variables + * + * \brief ns-3 random numbers are provided via instances of + * ns3::RandomVariableStream. + * + * - By default, ns-3 simulations use a fixed seed; if there is any + * randomness in the simulation, each run of the program will yield + * identical results unless the seed and/or run number is changed. + * - In ns-3.3 and earlier, ns-3 simulations used a random seed by default; + * this marks a change in policy starting with ns-3.4. + * - In ns-3.14 and earlier, ns-3 simulations used a different wrapper + * class called ns3::RandomVariable. This implementation is documented + * above under Legacy Random Variables. As of ns-3.15, this class has + * been replaced by ns3::RandomVariableStream; the underlying + * pseudo-random number generator has not changed. + * - To obtain randomness across multiple simulation runs, you must + * either set the seed differently or set the run number differently. + * To set a seed, call ns3::RngSeedManager::SetSeed() at the beginning + * of the program; to set a run number with the same seed, call + * ns3::RngSeedManager::SetRun() at the beginning of the program. + * - Each RandomVariableStream used in ns-3 has a virtual random number + * generator associated with it; all random variables use either + * a fixed or random seed based on the use of the global seed. + * - If you intend to perform multiple runs of the same scenario, + * with different random numbers, please be sure to read the manual + * section on how to perform independent replications. + */ + class RngStream; /** @@ -1982,6 +2012,10 @@ private: /// The upper bound on values that can be returned by this RNG stream. double m_max; + + /// It's easier to work with the mode internally instead of the + /// mean. They are related by the simple: mean = (min+max+mode)/3. + double m_mode; }; /** diff --git a/src/core/model/random-variable.cc b/src/core/model/random-variable.cc index 709cbc5a8..5c6dbfbad 100644 --- a/src/core/model/random-variable.cc +++ b/src/core/model/random-variable.cc @@ -46,6 +46,7 @@ namespace ns3 { NS_LOG_COMPONENT_DEFINE ("RandomVariable"); +/** \ingroup legacyrandom */ class RandomVariableBase { public: @@ -163,6 +164,7 @@ ATTRIBUTE_CHECKER_IMPLEMENT (RandomVariable); // ----------------------------------------------------------------------------- // UniformVariableImpl +/** \ingroup legacyrandom */ class UniformVariableImpl : public RandomVariableBase { public: @@ -291,6 +293,7 @@ uint32_t UniformVariable::GetInteger (uint32_t s, uint32_t l) // ----------------------------------------------------------------------------- // ConstantVariableImpl methods +/** \ingroup legacyrandom */ class ConstantVariableImpl : public RandomVariableBase { @@ -391,6 +394,7 @@ ConstantVariable::SetConstant (double c) // SequentialVariableImpl methods +/** \ingroup legacyrandom */ class SequentialVariableImpl : public RandomVariableBase { @@ -513,6 +517,7 @@ SequentialVariable::SequentialVariable (double f, double l, const RandomVariable // ----------------------------------------------------------------------------- // ExponentialVariableImpl methods +/** \ingroup legacyrandom */ class ExponentialVariableImpl : public RandomVariableBase { public: @@ -624,6 +629,7 @@ ExponentialVariable::ExponentialVariable (double m, double b) // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // ParetoVariableImpl methods +/** \ingroup legacyrandom */ class ParetoVariableImpl : public RandomVariableBase { public: @@ -813,6 +819,7 @@ ParetoVariable::ParetoVariable (std::pair params, double b) // ----------------------------------------------------------------------------- // WeibullVariableImpl methods +/** \ingroup legacyrandom */ class WeibullVariableImpl : public RandomVariableBase { public: @@ -948,6 +955,7 @@ WeibullVariable::WeibullVariable (double m, double s, double b) // ----------------------------------------------------------------------------- // NormalVariableImpl methods +/** \ingroup legacyrandom */ class NormalVariableImpl : public RandomVariableBase // Normally Distributed random var { @@ -1103,6 +1111,7 @@ NormalVariable::NormalVariable (double m, double v, double b) // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- +/** \ingroup legacyrandom */ class EmpiricalVariableImpl : public RandomVariableBase { public: @@ -1294,6 +1303,7 @@ EmpiricalVariable::CDF (double v, double c) // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // IntegerValue EmpiricalVariableImpl methods +/** \ingroup legacyrandom */ class IntEmpiricalVariableImpl : public EmpiricalVariableImpl { public: @@ -1342,6 +1352,7 @@ IntEmpiricalVariable::IntEmpiricalVariable () // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // DeterministicVariableImpl +/** \ingroup legacyrandom */ class DeterministicVariableImpl : public RandomVariableBase { @@ -1409,6 +1420,7 @@ DeterministicVariable::DeterministicVariable (double* d, uint32_t c) // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // LogNormalVariableImpl +/** \ingroup legacyrandom */ class LogNormalVariableImpl : public RandomVariableBase { public: @@ -1504,6 +1516,7 @@ LogNormalVariable::LogNormalVariable (double mu, double sigma) // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // GammaVariableImpl +/** \ingroup legacyrandom */ class GammaVariableImpl : public RandomVariableBase { public: @@ -1637,6 +1650,7 @@ double GammaVariable::GetValue (double alpha, double beta) const // ----------------------------------------------------------------------------- // ErlangVariableImpl +/** \ingroup legacyrandom */ class ErlangVariableImpl : public RandomVariableBase { public: @@ -1741,6 +1755,7 @@ double ErlangVariable::GetValue (unsigned int k, double lambda) const // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // TriangularVariableImpl methods +/** \ingroup legacyrandom */ class TriangularVariableImpl : public RandomVariableBase { public: @@ -1834,6 +1849,7 @@ TriangularVariable::TriangularVariable (double s, double l, double mean) // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // ZipfVariableImpl +/** \ingroup legacyrandom */ class ZipfVariableImpl : public RandomVariableBase { public: @@ -1926,6 +1942,7 @@ ZipfVariable::ZipfVariable (long n, double alpha) // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // ZetaVariableImpl +/** \ingroup legacyrandom */ class ZetaVariableImpl : public RandomVariableBase { public: diff --git a/src/core/model/random-variable.h b/src/core/model/random-variable.h index 76bb03f08..a2859f1b2 100644 --- a/src/core/model/random-variable.h +++ b/src/core/model/random-variable.h @@ -32,18 +32,20 @@ #include "rng-seed-manager.h" /** - * \ingroup core - * \defgroup randomvariable Random Variable Distributions - * + * \ingroup randomvariable + * \defgroup legacyrandom Legacy Random Variables */ namespace ns3 { +/** + * \ingroup legacyrandom + */ class RandomVariableBase; /** * \brief The basic RNG for NS-3. - * \ingroup randomvariable + * \ingroup legacyrandom * * Note: The underlying random number generation method used * by NS-3 is the RngStream code by Pierre L'Ecuyer at @@ -87,7 +89,7 @@ protected: /** * \brief The uniform distribution RNG for NS-3. - * \ingroup randomvariable + * \ingroup legacyrandom * * This class supports the creation of objects that return random numbers * from a fixed uniform distribution. It also supports the generation of @@ -146,7 +148,7 @@ public: /** * \brief A random variable that returns a constant - * \ingroup randomvariable + * \ingroup legacyrandom * * Class ConstantVariable defines a random number generator that * returns the same value every sample. @@ -177,7 +179,7 @@ public: /** * \brief Return a sequential list of values - * \ingroup randomvariable + * \ingroup legacyrandom * * Class SequentialVariable defines a random number generator that * returns a sequential sequence. The sequence monotonically @@ -216,7 +218,7 @@ public: /** * \brief Exponentially Distributed random var - * \ingroup randomvariable + * \ingroup legacyrandom * * This class supports the creation of objects that return random numbers * from a fixed exponential distribution. It also supports the generation of @@ -269,7 +271,7 @@ public: /** * \brief ParetoVariable distributed random var - * \ingroup randomvariable + * \ingroup legacyrandom * * This class supports the creation of objects that return random numbers * from a fixed pareto distribution. It also supports the generation of @@ -353,7 +355,7 @@ public: /** * \brief WeibullVariable distributed random var - * \ingroup randomvariable + * \ingroup legacyrandom * * This class supports the creation of objects that return random numbers * from a fixed weibull distribution. It also supports the generation of @@ -408,7 +410,7 @@ public: /** * \brief Class NormalVariable defines a random variable with a * normal (Gaussian) distribution. - * \ingroup randomvariable + * \ingroup legacyrandom * * This class supports the creation of objects that return random numbers * from a fixed normal distribution. It also supports the generation of @@ -447,7 +449,7 @@ public: /** * \brief EmpiricalVariable distribution random var - * \ingroup randomvariable + * \ingroup legacyrandom * * Defines a random variable that has a specified, empirical * distribution. The distribution is specified by a @@ -480,7 +482,7 @@ protected: /** * \brief Integer-based empirical distribution - * \ingroup randomvariable + * \ingroup legacyrandom * * Defines an empirical distribution where all values are integers. * Indentical to EmpiricalVariable, except that the inverse transform @@ -495,7 +497,7 @@ public: /** * \brief a non-random variable - * \ingroup randomvariable + * \ingroup legacyrandom * * Defines a random variable that has a specified, predetermined * sequence. This would be useful when trying to force @@ -521,7 +523,7 @@ public: /** * \brief Log-normal Distributed random var - * \ingroup randomvariable + * \ingroup legacyrandom * * LogNormalVariable defines a random variable with log-normal * distribution. If one takes the natural logarithm of random @@ -553,7 +555,7 @@ public: /** * \brief Gamma Distributed Random Variable - * \ingroup randomvariable + * \ingroup legacyrandom * * GammaVariable defines a random variable with gamma distribution. * @@ -602,7 +604,7 @@ public: /** * \brief Erlang Distributed Random Variable - * \ingroup randomvariable + * \ingroup legacyrandom * * ErlangVariable defines a random variable with Erlang distribution. * @@ -655,7 +657,7 @@ public: /** * \brief Zipf Distributed Random Variable - * \ingroup randomvariable + * \ingroup legacyrandom * * ZipfVariable defines a discrete random variable with Zipf distribution. * @@ -685,7 +687,7 @@ public: /** * \brief Zeta Distributed Distributed Random Variable - * \ingroup randomvariable + * \ingroup legacyrandom * * ZetaVariable defines a discrete random variable with Zeta distribution. * @@ -711,7 +713,7 @@ public: /** * \brief Triangularly Distributed random var - * \ingroup randomvariable + * \ingroup legacyrandom * * This distribution is a triangular distribution. The probability density * is in the shape of a triangle. diff --git a/src/core/model/rng-stream.h b/src/core/model/rng-stream.h index d7791d28c..167e7c5de 100644 --- a/src/core/model/rng-stream.h +++ b/src/core/model/rng-stream.h @@ -25,7 +25,6 @@ namespace ns3 { /** - * \ingroup core * \ingroup randomvariable * * \brief Combined Multiple-Recursive Generator MRG32k3a diff --git a/src/core/model/scheduler.h b/src/core/model/scheduler.h index c7ac05485..a66fa341f 100644 --- a/src/core/model/scheduler.h +++ b/src/core/model/scheduler.h @@ -30,7 +30,11 @@ class EventImpl; /** * \ingroup core - * \defgroup scheduler Scheduler + * \defgroup scheduler Scheduler and Events + */ +/** + * \ingroup scheduler + * \defgroup events Events */ /** * \ingroup scheduler @@ -55,12 +59,14 @@ class Scheduler : public Object public: static TypeId GetTypeId (void); + /** \ingroup events */ struct EventKey { uint64_t m_ts; uint32_t m_uid; uint32_t m_context; }; + /** \ingroup events */ struct Event { EventImpl *impl; diff --git a/src/core/model/simple-ref-count.h b/src/core/model/simple-ref-count.h index fa0b15146..55e54628b 100644 --- a/src/core/model/simple-ref-count.h +++ b/src/core/model/simple-ref-count.h @@ -31,6 +31,7 @@ namespace ns3 { /** + * \ingroup ptr * \brief A template-based reference counting class * * This template can be used to give reference-counting powers @@ -63,12 +64,21 @@ template m_children; - std::string m_dataDir; - TestRunnerImpl *m_runner; - struct Result *m_result; - std::string m_name; - enum TestDuration m_duration; + TestCase *m_parent; //!< Pointer to my parent TestCase + std::vector m_children; //!< Vector of my children + std::string m_dataDir; //!< My data directory + TestRunnerImpl *m_runner; //!< Pointer to the TestRunner + struct Result *m_result; //!< Results data + std::string m_name; //!< TestCase name + enum TestDuration m_duration; //!< TestCase duration }; /** @@ -968,12 +1030,12 @@ public: * \brief Type of test. */ enum Type { - ALL = 0, - BVT = 1, /**< This test suite implements a Build Verification Test */ - UNIT, /**< This test suite implements a Unit Test */ - SYSTEM, /**< This test suite implements a System Test */ - EXAMPLE, /**< This test suite implements an Example Test */ - PERFORMANCE /**< This test suite implements a Performance Test */ + ALL = 0, //!< + BVT = 1, //!< This test suite implements a Build Verification Test + UNIT, //!< This test suite implements a Unit Test + SYSTEM, //!< This test suite implements a System Test + EXAMPLE, //!< This test suite implements an Example Test + PERFORMANCE //!< This test suite implements a Performance Test }; /** @@ -995,7 +1057,7 @@ private: virtual void DoRun (void); - TestSuite::Type m_type; + TestSuite::Type m_type; //!< Type of this TestSuite }; /** @@ -1004,6 +1066,13 @@ private: class TestRunner { public: + /** + * Run the requested suite of tests. + * + * \param list of command line arguments + * \param argc number of elements in argv + * \returns success status + */ static int Run (int argc, char *argv[]); }; @@ -1014,23 +1083,53 @@ template class TestVectors { public: + /** + * Constructor + */ TestVectors (); + /** + * Virtual desctructor + */ virtual ~TestVectors (); + /** + * \param reserve the number of entries to reserve + */ void Reserve (uint32_t reserve); + /** + * \param vector the test vector to add + * \returns the new test vector index + */ uint32_t Add (T vector); + /** + * \return the number of test vectors + */ uint32_t GetN (void) const; + /** + * Get the i'th test vector + * \param i the requested vector index + * \return the requested vector + */ T Get (uint32_t i) const; private: + /** + * Copy constructor, private to block copying + */ TestVectors (const TestVectors& tv); + /** + * Assignment, private to prevent copying + */ TestVectors& operator= (const TestVectors& tv); + /** + * Comparison (unimplemented?) + */ bool operator== (const TestVectors& tv) const; - typedef std::vector TestVector; - TestVector m_vectors; + typedef std::vector TestVector; //!< Container type + TestVector m_vectors; //!< The list of test vectors }; template diff --git a/src/core/model/time.cc b/src/core/model/time.cc index 46cc78d77..9a2420552 100644 --- a/src/core/model/time.cc +++ b/src/core/model/time.cc @@ -108,7 +108,7 @@ Time::SetResolution (enum Unit unit, struct Resolution *resolution) for (int i = 0; i < Time::LAST; i++) { int shift = power[i] - power[(int)unit]; - uint64_t factor = (uint64_t) std::pow (10, std::fabs (shift)); + int64_t factor = (int64_t) std::pow (10, std::fabs (shift)); struct Information *info = &resolution->info[i]; info->factor = factor; if (shift == 0) diff --git a/src/core/model/type-id.cc b/src/core/model/type-id.cc index 165a0103f..079cf6c7a 100644 --- a/src/core/model/type-id.cc +++ b/src/core/model/type-id.cc @@ -17,21 +17,56 @@ * * Author: Mathieu Lacage */ +#include "log.h" // NS_ASSERT and NS_LOG +#include "hash.h" #include "type-id.h" #include "singleton.h" #include "trace-source-accessor.h" -#include "log.h" + +#include #include #include +#include /********************************************************************* * Helper code *********************************************************************/ -NS_LOG_COMPONENT_DEFINE ("TypeID"); +namespace ns3 { -namespace { +NS_LOG_COMPONENT_DEFINE ("TypeId"); +// IidManager needs to be in ns3 namespace for NS_ASSERT and NS_LOG +// to find g_log + +/** + * \brief TypeId information manager + * + * Information records are stored in a vector. Name and hash lookup + * are performed by maps to the vector index. + * + * \internal + * Hash Chaining + * + * We require all types to produce distinct hashes. What if we encounter + * two types that produce the same hash value? As we move to a + * federated distribution model (the App store), it becomes increasingly + * likely that the core ns3 team *won't* discover this in test builds. + * Therefore, we need to handle this case explicitly. + * + * Note, we expect this to be *extremely* rare. As of this writing we + * have ~400 < 2^9 types, so the probability of getting a collision + * when we introduce a new type is ~2^9/2^31 = 2^-22, assuming we + * reserve 31 bits for the hash, and one bit for chaining. Even with + * double the number of types the probability of having a collision + * is only 2 x 10^-4. The probability for a three-fold collision is + * 1 x 10^-10. + * + * Therefore, we'll handle one collision explicitly by reserving + * the high order bit of the hash value, and assert on higher level + * collisions. The three-fold collision probability should be an + * acceptablly small error rate. + */ class IidManager { public: @@ -39,13 +74,15 @@ public: uint16_t AllocateUid (std::string name); void SetParent (uint16_t uid, uint16_t parent); void SetGroupName (uint16_t uid, std::string groupName); - void AddConstructor (uint16_t uid, ns3::Callback callback); + void AddConstructor (uint16_t uid, Callback callback); void HideFromDocumentation (uint16_t uid); uint16_t GetUid (std::string name) const; + uint16_t GetUid (TypeId::hash_t hash) const; std::string GetName (uint16_t uid) const; + TypeId::hash_t GetHash (uint16_t uid) const; uint16_t GetParent (uint16_t uid) const; std::string GetGroupName (uint16_t uid) const; - ns3::Callback GetConstructor (uint16_t uid) const; + Callback GetConstructor (uint16_t uid) const; bool HasConstructor (uint16_t uid) const; uint32_t GetRegisteredN (void) const; uint16_t GetRegistered (uint32_t i) const; @@ -53,41 +90,54 @@ public: std::string name, std::string help, uint32_t flags, - ns3::Ptr initialValue, - ns3::Ptr spec, - ns3::Ptr checker); + Ptr initialValue, + Ptr spec, + Ptr checker); void SetAttributeInitialValue(uint16_t uid, uint32_t i, - ns3::Ptr initialValue); + Ptr initialValue); uint32_t GetAttributeN (uint16_t uid) const; - struct ns3::TypeId::AttributeInformation GetAttribute(uint16_t uid, uint32_t i) const; + struct TypeId::AttributeInformation GetAttribute(uint16_t uid, uint32_t i) const; void AddTraceSource (uint16_t uid, std::string name, std::string help, - ns3::Ptr accessor); + Ptr accessor); uint32_t GetTraceSourceN (uint16_t uid) const; - struct ns3::TypeId::TraceSourceInformation GetTraceSource(uint16_t uid, uint32_t i) const; + struct TypeId::TraceSourceInformation GetTraceSource(uint16_t uid, uint32_t i) const; bool MustHideFromDocumentation (uint16_t uid) const; private: bool HasTraceSource (uint16_t uid, std::string name); bool HasAttribute (uint16_t uid, std::string name); + static TypeId::hash_t Hasher (const std::string name); struct IidInformation { std::string name; + TypeId::hash_t hash; uint16_t parent; std::string groupName; bool hasConstructor; - ns3::Callback constructor; + Callback constructor; bool mustHideFromDocumentation; - std::vector attributes; - std::vector traceSources; + std::vector attributes; + std::vector traceSources; }; typedef std::vector::const_iterator Iterator; struct IidManager::IidInformation *LookupInformation (uint16_t uid) const; std::vector m_information; + + typedef std::map namemap_t; + namemap_t m_namemap; + + typedef std::map hashmap_t; + hashmap_t m_hashmap; + + + // To handle the first collision, we reserve the high bit as a + // chain flag: + enum { HashChainFlag = 0x80000000}; }; IidManager::IidManager () @@ -95,22 +145,70 @@ IidManager::IidManager () NS_LOG_FUNCTION (this); } + //static +TypeId::hash_t +IidManager::Hasher (const std::string name) +{ + static ns3::Hasher hasher ( Create () ); + return hasher.clear ().GetHash32 (name); +} + uint16_t IidManager::AllocateUid (std::string name) { NS_LOG_FUNCTION (this << name); - uint16_t j = 1; - for (Iterator i = m_information.begin (); i != m_information.end (); i++) - { - if (i->name == name) - { - NS_FATAL_ERROR ("Trying to allocate twice the same uid: " << name); - return 0; - } - j++; - } - struct IidInformation information; + // Type names are definitive: equal names are equal types + NS_ASSERT_MSG (m_namemap.count (name) == 0, + "Trying to allocate twice the same uid: " << name); + + TypeId::hash_t hash = Hasher (name) & (~HashChainFlag); + if (m_hashmap.count (hash) == 1) { + NS_LOG_ERROR ("Hash chaining TypeId for '" << name << "'. " + << "This is not a bug, but is extremely unlikely. " + << "Please contact the ns3 developers."); + // ns3 developer contacted about this message: + // You have four options (in order of difficulty): + // 1. Let it ride, and play the odds that a third collision + // never appears. + // 2. Change the name of the new (or old) tag, even trivially, to + // remove the collision. + // 3. Switch to 64-bit hashes. + // 4. Implement 2-bit (or higher) chaining. + // + // Oh, by the way, I owe you a beer, since I bet Mathieu that + // this would never happen.. -- Peter Barnes, LLNL + + NS_ASSERT_MSG (m_hashmap.count (hash | HashChainFlag) == 0, + "Triplicate hash detected while chaining TypeId for '" + << name + << "'. Please contact the ns3 developers for assistance."); + // ns3 developer contacted about this message: + // You have three options: #2-4 above. + // + // Oh, by the way, I have no idea how this crazy hashing idea got + // into ns3. -- Peter Barnes, LLNL + + // Alphabetize the two types, so it's deterministic + struct IidInformation * hinfo = LookupInformation (GetUid (hash)); + if (name > hinfo->name) + { // new type gets chained + NS_LOG_LOGIC ("New TypeId '" << name << "' getting chained."); + hash = hash | HashChainFlag; + } + else + { // chain old type + NS_LOG_LOGIC ("Old TypeId '" << hinfo->name << "' getting chained."); + uint32_t oldUid = GetUid (hinfo->hash); + m_hashmap.erase (m_hashmap.find (hinfo->hash)); + hinfo->hash = hash | HashChainFlag; + m_hashmap.insert (std::make_pair (hinfo->hash, oldUid)); + // leave new hash unchained + } + } + + struct IidInformation information; information.name = name; + information.hash = hash; information.parent = 0; information.groupName = ""; information.hasConstructor = false; @@ -118,6 +216,10 @@ IidManager::AllocateUid (std::string name) m_information.push_back (information); uint32_t uid = m_information.size (); NS_ASSERT (uid <= 0xffff); + + // Add to both maps: + m_namemap.insert (std::make_pair (name, uid)); + m_hashmap.insert (std::make_pair (hash, uid)); return uid; } @@ -153,7 +255,7 @@ IidManager::HideFromDocumentation (uint16_t uid) } void -IidManager::AddConstructor (uint16_t uid, ns3::Callback callback) +IidManager::AddConstructor (uint16_t uid, Callback callback) { NS_LOG_FUNCTION (this << uid << &callback); struct IidInformation *information = LookupInformation (uid); @@ -169,17 +271,28 @@ uint16_t IidManager::GetUid (std::string name) const { NS_LOG_FUNCTION (this << name); - uint32_t j = 1; - for (Iterator i = m_information.begin (); i != m_information.end (); i++) + namemap_t::const_iterator it = m_namemap.find (name); + if (it != m_namemap.end ()) { - if (i->name == name) - { - NS_ASSERT (j <= 0xffff); - return j; - } - j++; + return it->second; + } + else + { + return 0; + } +} +uint16_t +IidManager::GetUid (TypeId::hash_t hash) const +{ + hashmap_t::const_iterator it = m_hashmap.find (hash); + if (it != m_hashmap.end ()) + { + return it->second; + } + else + { // hash not found + return 0; } - return 0; } std::string IidManager::GetName (uint16_t uid) const @@ -188,6 +301,13 @@ IidManager::GetName (uint16_t uid) const struct IidInformation *information = LookupInformation (uid); return information->name; } +TypeId::hash_t +IidManager::GetHash (uint16_t uid) const +{ + NS_LOG_FUNCTION (this << uid); + struct IidInformation *information = LookupInformation (uid); + return information->hash; +} uint16_t IidManager::GetParent (uint16_t uid) const { @@ -203,7 +323,7 @@ IidManager::GetGroupName (uint16_t uid) const return information->groupName; } -ns3::Callback +Callback IidManager::GetConstructor (uint16_t uid) const { NS_LOG_FUNCTION (this << uid); @@ -244,7 +364,7 @@ IidManager::HasAttribute (uint16_t uid, struct IidInformation *information = LookupInformation (uid); while (true) { - for (std::vector::const_iterator i = information->attributes.begin (); + for (std::vector::const_iterator i = information->attributes.begin (); i != information->attributes.end (); ++i) { if (i->name == name) @@ -269,9 +389,9 @@ IidManager::AddAttribute (uint16_t uid, std::string name, std::string help, uint32_t flags, - ns3::Ptr initialValue, - ns3::Ptr accessor, - ns3::Ptr checker) + Ptr initialValue, + Ptr accessor, + Ptr checker) { NS_LOG_FUNCTION (this << uid << name << help << flags << initialValue << accessor << checker); struct IidInformation *information = LookupInformation (uid); @@ -280,7 +400,7 @@ IidManager::AddAttribute (uint16_t uid, NS_FATAL_ERROR ("Attribute \"" << name << "\" already registered on tid=\"" << information->name << "\""); } - struct ns3::TypeId::AttributeInformation info; + struct TypeId::AttributeInformation info; info.name = name; info.help = help; info.flags = flags; @@ -293,7 +413,7 @@ IidManager::AddAttribute (uint16_t uid, void IidManager::SetAttributeInitialValue(uint16_t uid, uint32_t i, - ns3::Ptr initialValue) + Ptr initialValue) { NS_LOG_FUNCTION (this << uid << i << initialValue); struct IidInformation *information = LookupInformation (uid); @@ -310,7 +430,7 @@ IidManager::GetAttributeN (uint16_t uid) const struct IidInformation *information = LookupInformation (uid); return information->attributes.size (); } -struct ns3::TypeId::AttributeInformation +struct TypeId::AttributeInformation IidManager::GetAttribute(uint16_t uid, uint32_t i) const { NS_LOG_FUNCTION (this << uid << i); @@ -327,7 +447,7 @@ IidManager::HasTraceSource (uint16_t uid, struct IidInformation *information = LookupInformation (uid); while (true) { - for (std::vector::const_iterator i = information->traceSources.begin (); + for (std::vector::const_iterator i = information->traceSources.begin (); i != information->traceSources.end (); ++i) { if (i->name == name) @@ -351,7 +471,7 @@ void IidManager::AddTraceSource (uint16_t uid, std::string name, std::string help, - ns3::Ptr accessor) + Ptr accessor) { NS_LOG_FUNCTION (this << uid << name << help << accessor); struct IidInformation *information = LookupInformation (uid); @@ -360,7 +480,7 @@ IidManager::AddTraceSource (uint16_t uid, NS_FATAL_ERROR ("Trace source \"" << name << "\" already registered on tid=\"" << information->name << "\""); } - struct ns3::TypeId::TraceSourceInformation source; + struct TypeId::TraceSourceInformation source; source.name = name; source.help = help; source.accessor = accessor; @@ -373,7 +493,7 @@ IidManager::GetTraceSourceN (uint16_t uid) const struct IidInformation *information = LookupInformation (uid); return information->traceSources.size (); } -struct ns3::TypeId::TraceSourceInformation +struct TypeId::TraceSourceInformation IidManager::GetTraceSource(uint16_t uid, uint32_t i) const { NS_LOG_FUNCTION (this << uid << i); @@ -389,7 +509,7 @@ IidManager::MustHideFromDocumentation (uint16_t uid) const return information->mustHideFromDocumentation; } -} // anonymous namespace +} // namespace ns3 namespace ns3 { @@ -431,6 +551,25 @@ TypeId::LookupByNameFailSafe (std::string name, TypeId *tid) *tid = TypeId (uid); return true; } +TypeId +TypeId::LookupByHash (hash_t hash) +{ + uint16_t uid = Singleton::Get ()->GetUid (hash); + NS_ASSERT_MSG (uid != 0, "Assert in TypeId::LookupByHash: 0x" + << std::hex << hash << std::dec << " not found"); + return TypeId (uid); +} +bool +TypeId::LookupByHashFailSafe (hash_t hash, TypeId *tid) +{ + uint16_t uid = Singleton::Get ()->GetUid (hash); + if (uid == 0) + { + return false; + } + *tid = TypeId (uid); + return true; +} uint32_t TypeId::GetRegisteredN (void) @@ -522,6 +661,13 @@ TypeId::GetName (void) const return name; } +TypeId::hash_t +TypeId::GetHash (void) const +{ + hash_t hash = Singleton::Get ()->GetHash (m_tid); + return hash; +} + bool TypeId::HasConstructor (void) const { diff --git a/src/core/model/type-id.h b/src/core/model/type-id.h index 32f129f09..1f5bb6820 100644 --- a/src/core/model/type-id.h +++ b/src/core/model/type-id.h @@ -25,6 +25,7 @@ #include "trace-source-accessor.h" #include "attribute-helper.h" #include "callback.h" +#include "hash.h" #include #include @@ -40,6 +41,10 @@ class ObjectBase; * - the base class of the subclass * - the set of accessible constructors in the subclass * - the set of 'attributes' accessible in the subclass + * + * \internal + * See the discussion in IidManager about hash chaining of TypeId's. + * */ class TypeId { @@ -57,17 +62,22 @@ public: std::string name; std::string help; uint32_t flags; - ns3::Ptr originalInitialValue; - ns3::Ptr initialValue; - ns3::Ptr accessor; - ns3::Ptr checker; + Ptr originalInitialValue; + Ptr initialValue; + Ptr accessor; + Ptr checker; }; struct TraceSourceInformation { std::string name; std::string help; - ns3::Ptr accessor; + Ptr accessor; }; + /** + * Type of hash values + */ + typedef uint32_t hash_t; + /** * \param name the name of the requested TypeId * \returns the unique id associated with the requested @@ -84,6 +94,21 @@ public: * \returns true if the requested name was found, false otherwise. */ static bool LookupByNameFailSafe (std::string name, TypeId *tid); + /** + * \param hash the hash to lookup + * \returns the unique id associated with the requested hash. + * + * This method cannot fail: it will crash if the input + * hash does not match an existing TypeId. + */ + static TypeId LookupByHash (hash_t hash); + /** + * \param hash the hash of the requested TypeId + * \param tid a pointer to the TypeId instance where the + * result of this function should be stored. + * \returns true if the requested hash was found, false otherwise. + */ + static bool LookupByHashFailSafe (hash_t hash, TypeId *tid); /** * \returns the number of TypeId instances registered. @@ -137,6 +162,11 @@ public: */ std::string GetName (void) const; + /** + * \returns the hash of this interface. + */ + hash_t GetHash (void) const; + /** * \returns true if this TypeId has a constructor */ diff --git a/src/core/test/type-id-test-suite.cc b/src/core/test/type-id-test-suite.cc new file mode 100644 index 000000000..e05206b13 --- /dev/null +++ b/src/core/test/type-id-test-suite.cc @@ -0,0 +1,321 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2012 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 + * + * Author: Peter D. Barnes, Jr. + */ + +#include +#include +#include + +#include "ns3/type-id.h" +#include "ns3/test.h" +#include "ns3/log.h" + +using namespace std; + +namespace ns3 { + + +const std::string suite("type-id: "); + +//---------------------------- +// +// Test for uniqueness of all TypeIds + +class UniqueTypeIdTestCase : public TestCase +{ +public: + UniqueTypeIdTestCase (); + virtual ~UniqueTypeIdTestCase (); +private: + virtual void DoRun (void); + enum { HashChainFlag = 0x80000000}; +}; + +UniqueTypeIdTestCase::UniqueTypeIdTestCase () + : TestCase ("Check uniqueness of all TypeIds") +{ +} + +UniqueTypeIdTestCase::~UniqueTypeIdTestCase () +{ +} + +void +UniqueTypeIdTestCase::DoRun (void) +{ + cout << suite << endl; + cout << suite << GetName () << endl; + + // Use same custom hasher as TypeId + ns3::Hasher hasher = ns3::Hasher ( Create () ); + + uint32_t nids = TypeId::GetRegisteredN (); + + cout << suite << "UniqueTypeIdTestCase: nids: " << nids << endl; + cout << suite << "TypeId list:" << endl; + cout << suite << "TypeId Chain hash Name" << endl; + + for (uint32_t i = 0; i < nids; ++i) + { + const TypeId tid = TypeId::GetRegistered (i); + cout << suite << "" << std::setw(6) << tid.GetUid (); + if (tid.GetHash () & HashChainFlag) + { + cout << " chain"; + } + else + { + cout << " "; + } + cout << " 0x" << std::setfill ('0') << std::hex << std::setw (8) + << tid.GetHash () << std::dec << std::setfill (' ') + << " " << tid.GetName () + << endl; + + NS_TEST_ASSERT_MSG_EQ (tid.GetUid (), + TypeId::LookupByName (tid.GetName ()).GetUid (), + "LookupByName returned different TypeId for " + << tid.GetName ()); + + // Mask off HashChainFlag in this test, since tid might have been chained + NS_TEST_ASSERT_MSG_EQ ((tid.GetHash () & (~HashChainFlag)), + (hasher.clear ().GetHash32 (tid.GetName ()) & (~HashChainFlag)), + "TypeId .hash and Hash32 (.name) unequal for " + << tid.GetName ()); + + NS_TEST_ASSERT_MSG_EQ (tid.GetUid (), + TypeId::LookupByHash (tid.GetHash ()).GetUid (), + "LookupByHash returned different TypeId for " + << tid.GetName ()); + + } + + cout << suite << "<-- end TypeId list -->" << endl; +} + + +//---------------------------- +// +// Collision test + +class CollisionTestCase : public TestCase +{ +public: + CollisionTestCase (); + virtual ~CollisionTestCase (); +private: + virtual void DoRun (void); + enum { HashChainFlag = 0x80000000}; +}; + +CollisionTestCase::CollisionTestCase () + : TestCase ("Check behavour when type names collide") +{ +} + +CollisionTestCase::~CollisionTestCase () +{ +} + +void +CollisionTestCase::DoRun (void) +{ + cout << suite << endl; + cout << suite << GetName () << endl; + + // Register two types whose hashes collide, in alphabetical order + // Murmur3 collision from /usr/share/dict/web2 + string t1Name = "daemon"; + string t2Name = "unerring"; + cout << suite << "creating colliding types " + << "'" << t1Name << "', '" << t2Name << "'" + << " in alphabetical order:" + << endl; + TypeId t1 (t1Name.c_str ()); + TypeId t2 (t2Name.c_str ()); + + // Check that they are alphabetical: t1 name < t2 name + NS_TEST_ASSERT_MSG_EQ ( (t1.GetHash () & HashChainFlag), 0, + "First and lesser TypeId has HashChainFlag set"); + cout << suite << "collision: first,lesser not chained: OK" << endl; + + NS_TEST_ASSERT_MSG_NE ( (t2.GetHash () & HashChainFlag), 0, + "Second and greater TypeId does not have HashChainFlag set"); + cout << suite << "collision: second,greater chained: OK" << endl; + + + // Register colliding types in reverse alphabetical order + // Murmur3 collision from /usr/share/dict/web2 + string t3Name = "trigonon"; + string t4Name = "seriation"; + cout << suite << "creating colliding types " + << "'" << t3Name << "', '" << t4Name << "'" + << " in reverse alphabetical order:" + << endl; + TypeId t3 (t3Name.c_str ()); + TypeId t4 (t4Name.c_str ()); + + // Check that they are alphabetical: t3 name > t4 name + NS_TEST_ASSERT_MSG_NE ( (t3.GetHash () & HashChainFlag), 0, + "First and greater TypeId does not have HashChainFlag set"); + cout << suite << "collision: first,greater chained: OK" << endl; + + NS_TEST_ASSERT_MSG_EQ ( (t4.GetHash () & HashChainFlag), 0, + "Second and lesser TypeId has HashChainFlag set"); + cout << suite << "collision: second,lesser not chained: OK" << endl; + + /** TODO Extra credit: register three types whose hashes collide + * + * None found in /usr/share/dict/web2 + */ + +} + + +//---------------------------- +// +// Performance test + +class LookupTimeTestCase : public TestCase +{ +public: + LookupTimeTestCase (); + virtual ~LookupTimeTestCase (); +private: + void DoRun (void); + void DoSetup (void); + void Report (const std::string how, const uint32_t delta) const ; + + enum { REPETITIONS = 100000 }; +}; + +LookupTimeTestCase::LookupTimeTestCase () + : TestCase ("Measure average lookup time") +{ +} + +LookupTimeTestCase::~LookupTimeTestCase () +{ +} + +void +LookupTimeTestCase::DoRun (void) +{ + cout << suite << endl; + cout << suite << GetName () << endl; + + uint32_t nids = TypeId::GetRegisteredN (); + + int start = clock (); + for (uint32_t j = 0; j < REPETITIONS; ++j) + { + for (uint32_t i = 0; i < nids; ++i) + { + const TypeId tid = TypeId::GetRegistered (i); + const TypeId sid = TypeId::LookupByName (tid.GetName ()); + } + } + int stop = clock (); + Report ("name", stop - start); + + start = clock (); + for (uint32_t j = 0; j < REPETITIONS; ++j) + { + for (uint32_t i = 0; i < nids; ++i) + { + const TypeId tid = TypeId::GetRegistered (i); + const TypeId sid = TypeId::LookupByHash (tid.GetHash ()); + } + } + stop = clock (); + Report ("hash", stop - start); + +} + +void +LookupTimeTestCase::DoSetup (void) +{ + uint32_t nids = TypeId::GetRegisteredN (); + + cout << suite << "Lookup time: reps: " << REPETITIONS + << ", num TypeId's: " << nids + << endl; + +} + +void +LookupTimeTestCase::Report (const std::string how, + const uint32_t delta) const +{ + double nids = TypeId::GetRegisteredN (); + double reps = nids * REPETITIONS; + + double per = 1E6 * double(delta) / (reps * double(CLOCKS_PER_SEC)); + + cout << suite << "Lookup time: by " << how << ": " + << "ticks: " << delta + << "\tper: " << per + << " microsec/lookup" + << endl; +} + + +//---------------------------- +// +// TypeId test suites + +class TypeIdTestSuite : public TestSuite +{ +public: + TypeIdTestSuite (); +}; + +TypeIdTestSuite::TypeIdTestSuite () + : TestSuite ("type-id", UNIT) +{ + // Turn on logging, so we see the result of collisions + LogComponentEnable ("TypeId", ns3::LogLevel(LOG_ERROR|LOG_PREFIX_FUNC)); + + // If the CollisionTestCase is performed before the + // 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); +} + +static TypeIdTestSuite g_TypeIdTestSuite; + + +class TypeIdPerformanceSuite : public TestSuite +{ +public: + TypeIdPerformanceSuite (); +}; + +TypeIdPerformanceSuite::TypeIdPerformanceSuite () + : TestSuite ("type-id-perf", PERFORMANCE) +{ + AddTestCase (new LookupTimeTestCase, QUICK); +} + +static TypeIdPerformanceSuite g_TypeIdPerformanceSuite; + + +} // namespace ns3 diff --git a/src/core/wscript b/src/core/wscript index 64ba9d123..d82252165 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -178,6 +178,7 @@ def build(bld): 'test/type-traits-test-suite.cc', 'test/watchdog-test-suite.cc', 'test/hash-test-suite.cc', + 'test/type-id-test-suite.cc', ] headers = bld(features='ns3header') diff --git a/src/internet/helper/ipv4-routing-helper.cc b/src/internet/helper/ipv4-routing-helper.cc index b4c6537df..deaa64202 100644 --- a/src/internet/helper/ipv4-routing-helper.cc +++ b/src/internet/helper/ipv4-routing-helper.cc @@ -82,27 +82,4 @@ Ipv4RoutingHelper::PrintEvery (Time printInterval, Ptr node, Ptr -Ptr Ipv4RoutingHelper::GetRouting (Ptr protocol) -{ - Ptr ret = DynamicCast (protocol); - if (ret == 0) - { - // trying to check if protocol is a list routing - Ptr lrp = DynamicCast (protocol); - if (lrp != 0) - { - for (uint32_t i = 0; i < lrp->GetNRoutingProtocols (); i++) - { - int16_t priority; - ret = GetRouting (lrp->GetRoutingProtocol (i, priority)); // potential recursion, if inside ListRouting is ListRouting - if (ret != 0) - break; - } - } - } - - return ret; -} - } // namespace ns3 diff --git a/src/internet/helper/ipv4-routing-helper.h b/src/internet/helper/ipv4-routing-helper.h index 06b069195..f777f17a0 100644 --- a/src/internet/helper/ipv4-routing-helper.h +++ b/src/internet/helper/ipv4-routing-helper.h @@ -24,6 +24,7 @@ #include "ns3/ptr.h" #include "ns3/nstime.h" #include "ns3/output-stream-wrapper.h" +#include "ns3/ipv4-list-routing.h" namespace ns3 { @@ -125,6 +126,30 @@ private: void PrintEvery (Time printInterval, Ptr node, Ptr stream) const; }; + +template +Ptr Ipv4RoutingHelper::GetRouting (Ptr protocol) +{ + Ptr ret = DynamicCast (protocol); + if (ret == 0) + { + // trying to check if protocol is a list routing + Ptr lrp = DynamicCast (protocol); + if (lrp != 0) + { + for (uint32_t i = 0; i < lrp->GetNRoutingProtocols (); i++) + { + int16_t priority; + ret = GetRouting (lrp->GetRoutingProtocol (i, priority)); // potential recursion, if inside ListRouting is ListRouting + if (ret != 0) + break; + } + } + } + + return ret; +} + } // namespace ns3 diff --git a/src/internet/helper/ipv6-address-helper.cc b/src/internet/helper/ipv6-address-helper.cc index 3da8864a5..3bb104da0 100644 --- a/src/internet/helper/ipv6-address-helper.cc +++ b/src/internet/helper/ipv6-address-helper.cc @@ -62,10 +62,10 @@ void Ipv6AddressHelper::SetBase (Ipv6Address network, Ipv6Prefix prefix, Ipv6Address Ipv6AddressHelper::NewAddress (Address addr) { NS_LOG_FUNCTION (this << addr); - if (Mac16Address::IsMatchingType (addr)) + if (Mac64Address::IsMatchingType (addr)) { Ipv6Address network = Ipv6AddressGenerator::GetNetwork (Ipv6Prefix (64)); - Ipv6Address address = Ipv6Address::MakeAutoconfiguredAddress (Mac16Address::ConvertFrom (addr), network); + Ipv6Address address = Ipv6Address::MakeAutoconfiguredAddress (Mac64Address::ConvertFrom (addr), network); Ipv6AddressGenerator::AddAllocated (address); return address; } @@ -76,10 +76,10 @@ Ipv6Address Ipv6AddressHelper::NewAddress (Address addr) Ipv6AddressGenerator::AddAllocated (address); return address; } - else if (Mac64Address::IsMatchingType (addr)) + else if (Mac16Address::IsMatchingType (addr)) { Ipv6Address network = Ipv6AddressGenerator::GetNetwork (Ipv6Prefix (64)); - Ipv6Address address = Ipv6Address::MakeAutoconfiguredAddress (Mac64Address::ConvertFrom (addr), network); + Ipv6Address address = Ipv6Address::MakeAutoconfiguredAddress (Mac16Address::ConvertFrom (addr), network); Ipv6AddressGenerator::AddAllocated (address); return address; } diff --git a/src/internet/helper/ipv6-routing-helper.cc b/src/internet/helper/ipv6-routing-helper.cc index 8c7d6a89d..6ab299d69 100644 --- a/src/internet/helper/ipv6-routing-helper.cc +++ b/src/internet/helper/ipv6-routing-helper.cc @@ -82,27 +82,4 @@ Ipv6RoutingHelper::PrintEvery (Time printInterval, Ptr node, Ptr -Ptr Ipv6RoutingHelper::GetRouting (Ptr protocol) -{ - Ptr ret = DynamicCast (protocol); - if (ret == 0) - { - // trying to check if protocol is a list routing - Ptr lrp = DynamicCast (protocol); - if (lrp != 0) - { - for (uint32_t i = 0; i < lrp->GetNRoutingProtocols (); i++) - { - int16_t priority; - ret = GetRouting (lrp->GetRoutingProtocol (i, priority)); // potential recursion, if inside ListRouting is ListRouting - if (ret != 0) - break; - } - } - } - - return ret; -} - } // namespace ns3 diff --git a/src/internet/helper/ipv6-routing-helper.h b/src/internet/helper/ipv6-routing-helper.h index d066a2428..8c08d617a 100644 --- a/src/internet/helper/ipv6-routing-helper.h +++ b/src/internet/helper/ipv6-routing-helper.h @@ -24,6 +24,7 @@ #include "ns3/ptr.h" #include "ns3/nstime.h" #include "ns3/output-stream-wrapper.h" +#include "ns3/ipv6-list-routing.h" namespace ns3 { @@ -127,6 +128,29 @@ private: void PrintEvery (Time printInterval, Ptr node, Ptr stream) const; }; +template +Ptr Ipv6RoutingHelper::GetRouting (Ptr protocol) +{ + Ptr ret = DynamicCast (protocol); + if (ret == 0) + { + // trying to check if protocol is a list routing + Ptr lrp = DynamicCast (protocol); + if (lrp != 0) + { + for (uint32_t i = 0; i < lrp->GetNRoutingProtocols (); i++) + { + int16_t priority; + ret = GetRouting (lrp->GetRoutingProtocol (i, priority)); // potential recursion, if inside ListRouting is ListRouting + if (ret != 0) + break; + } + } + } + + return ret; +} + } // namespace ns3 diff --git a/src/internet/model/ipv6-interface.cc b/src/internet/model/ipv6-interface.cc index 5db0d5a63..5469b01a7 100644 --- a/src/internet/model/ipv6-interface.cc +++ b/src/internet/model/ipv6-interface.cc @@ -89,9 +89,9 @@ void Ipv6Interface::DoSetup () { Address addr = GetDevice ()->GetAddress (); - if (Mac16Address::IsMatchingType (addr)) + if (Mac64Address::IsMatchingType (addr)) { - Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac16Address::ConvertFrom (addr)), Ipv6Prefix (64)); + Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac64Address::ConvertFrom (addr)), Ipv6Prefix (64)); AddAddress (ifaddr); } else if (Mac48Address::IsMatchingType (addr)) @@ -99,9 +99,9 @@ void Ipv6Interface::DoSetup () Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac48Address::ConvertFrom (addr)), Ipv6Prefix (64)); AddAddress (ifaddr); } - else if (Mac64Address::IsMatchingType (addr)) + else if (Mac16Address::IsMatchingType (addr)) { - Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac64Address::ConvertFrom (addr)), Ipv6Prefix (64)); + Ipv6InterfaceAddress ifaddr = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredLinkLocalAddress (Mac16Address::ConvertFrom (addr)), Ipv6Prefix (64)); AddAddress (ifaddr); } else diff --git a/src/internet/model/ipv6-l3-protocol.cc b/src/internet/model/ipv6-l3-protocol.cc index 58a89a263..0ef79e0ac 100644 --- a/src/internet/model/ipv6-l3-protocol.cc +++ b/src/internet/model/ipv6-l3-protocol.cc @@ -266,17 +266,17 @@ void Ipv6L3Protocol::AddAutoconfiguredAddress (uint32_t interface, Ipv6Address n if (flags & (1 << 6)) /* auto flag */ { // In case of new MacAddress types, remember to change Ipv6L3Protocol::RemoveAutoconfiguredAddress as well - if (Mac16Address::IsMatchingType (addr)) + if (Mac64Address::IsMatchingType (addr)) { - address = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredAddress (Mac16Address::ConvertFrom (addr), network)); + address = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredAddress (Mac64Address::ConvertFrom (addr), network)); } else if (Mac48Address::IsMatchingType (addr)) { address = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredAddress (Mac48Address::ConvertFrom (addr), network)); } - else if (Mac64Address::IsMatchingType (addr)) + else if (Mac16Address::IsMatchingType (addr)) { - address = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredAddress (Mac64Address::ConvertFrom (addr), network)); + address = Ipv6InterfaceAddress (Ipv6Address::MakeAutoconfiguredAddress (Mac16Address::ConvertFrom (addr), network)); } else { @@ -324,17 +324,17 @@ void Ipv6L3Protocol::RemoveAutoconfiguredAddress (uint32_t interface, Ipv6Addres uint32_t i = 0; Ipv6Address toFound; - if (Mac16Address::IsMatchingType (addr)) + if (Mac64Address::IsMatchingType (addr)) { - toFound = Ipv6Address::MakeAutoconfiguredAddress (Mac16Address::ConvertFrom (addr), network); + toFound = Ipv6Address::MakeAutoconfiguredAddress (Mac64Address::ConvertFrom (addr), network); } else if (Mac48Address::IsMatchingType (addr)) { toFound = Ipv6Address::MakeAutoconfiguredAddress (Mac48Address::ConvertFrom (addr), network); } - else if (Mac64Address::IsMatchingType (addr)) + else if (Mac16Address::IsMatchingType (addr)) { - toFound = Ipv6Address::MakeAutoconfiguredAddress (Mac64Address::ConvertFrom (addr), network); + toFound = Ipv6Address::MakeAutoconfiguredAddress (Mac16Address::ConvertFrom (addr), network); } else { diff --git a/src/netanim/model/animation-interface.cc b/src/netanim/model/animation-interface.cc index 8b53d9177..bce3d6859 100644 --- a/src/netanim/model/animation-interface.cc +++ b/src/netanim/model/animation-interface.cc @@ -162,7 +162,7 @@ void AnimationInterface::RecursiveIpv4RoutePathSearch (std::string from, std::st { return; } - NS_LOG_UNCOND ("Node: " << fromNode->GetId () << " G:" << rt->GetGateway ()); + NS_LOG_DEBUG ("Node: " << fromNode->GetId () << " G:" << rt->GetGateway ()); std::ostringstream oss; oss << rt->GetGateway (); if (oss.str () == "0.0.0.0" && (sockerr != Socket::ERROR_NOROUTETOHOST)) @@ -219,14 +219,18 @@ void AnimationInterface::TrackIpv4RoutePaths () header.SetDestination (Ipv4Address (trackElement.destination.c_str ())); Socket::SocketErrno sockerr; Ptr rt = rp->RouteOutput (pkt, header, 0, sockerr); + Ipv4RoutePathElements rpElements; if (!rt) { NS_LOG_INFO ("No route to :" << trackElement.destination.c_str ()); + Ipv4RoutePathElement elem = { trackElement.fromNodeId, "-1" }; + rpElements.push_back (elem); + WriteRoutePath (trackElement.fromNodeId, trackElement.destination, rpElements); + continue; } std::ostringstream oss; oss << rt->GetGateway (); NS_LOG_INFO ("Node:" << trackElement.fromNodeId << "-->" << rt->GetGateway ()); - Ipv4RoutePathElements rpElements; if (rt->GetGateway () == "0.0.0.0") { Ipv4RoutePathElement elem = { trackElement.fromNodeId, "C" }; @@ -1995,7 +1999,7 @@ std::string AnimationInterface::GetXMLOpenClose_rp (uint32_t nodeId, std::string Ipv4RoutePathElement rpElement = *i; oss << "" << std::endl; } - oss << "" << std::endl; + oss << "" << std::endl; return oss.str (); } diff --git a/src/network/model/packet-tag-list.h b/src/network/model/packet-tag-list.h index 11f742523..92f3e3a55 100644 --- a/src/network/model/packet-tag-list.h +++ b/src/network/model/packet-tag-list.h @@ -41,7 +41,7 @@ class Tag; * This class is mostly private to the Packet implementation and users * should never have to access it directly. * - * \intern + * \internal * * The implementation of this class is a bit tricky. Refer to this * diagram in the discussion that follows. @@ -145,7 +145,7 @@ public: * The maximum size (in bytes) of a Tag is stored * in this constant. * - * \intern + * \internal * Ideally, TagData would be 32 bytes in size, so they require * no padding on 64-bit architectures. (The architecture * affects the size because of the \c #next pointer.) diff --git a/wscript b/wscript index bdc0cd582..36584fe27 100644 --- a/wscript +++ b/wscript @@ -288,6 +288,8 @@ def configure(conf): conf.env['NS3_OPTIONAL_FEATURES'] = [] conf.load('compiler_c') + cc_string='.'.join(conf.env['CC_VERSION']) + conf.msg('Checking for cc version',cc_string,'GREEN') conf.load('compiler_cxx') conf.load('cflags', tooldir=['waf-tools']) conf.load('command', tooldir=['waf-tools'])