branch merge
authorCraig Dowell <craigdo@ee.washington.edu>
Thu, 08 Nov 2007 16:58:24 -0800
changeset 1847 94126d5bfa1d
parent 1846 b0a2f5612f4e (current diff)
parent 1819 c21093326f8d (diff)
child 1848 5dfaf1619279
branch merge
samples/main-debug-other.cc
samples/main-debug.cc
src/core/debug.cc
src/core/debug.h
src/mobility/position.cc
src/mobility/position.h
src/mobility/speed.cc
src/mobility/speed.h
src/simulator/event-garbage-collector.cc
src/simulator/event-garbage-collector.h
--- a/.hgtags	Wed Oct 10 12:25:52 2007 -0700
+++ b/.hgtags	Thu Nov 08 16:58:24 2007 -0800
@@ -6,3 +6,4 @@
 08046b6aef37932507696a2f2f427b42d693781e release ns-3.0.5
 267e2ebc28e4e4ae2f579e1cfc29902acade0c34 buffer-working-before-breaking
 606df29888e7573b825fc891a002f0757166b616 release ns-3.0.6
+36472385a1cc7c44d34fb7a5951b930010f4e8d2 release ns-3.0.7
--- a/README	Wed Oct 10 12:25:52 2007 -0700
+++ b/README	Thu Nov 08 16:58:24 2007 -0800
@@ -84,12 +84,12 @@
   - linux x86 gcc 4.2, 4.1, and, 3.4.
   - linux x86_64 gcc 4.0
   - MacOS X ppc and x86
+  - cygwin
 
 The current codebase is expected to fail to build on
 the following platforms:
   - gcc 3.3 and earlier
   - optimized builds on linux x86 gcc 4.0 
-  - cygwin
 
 Other platforms may or may not work: we welcome 
 patches to improve the portability of the code to these
@@ -102,17 +102,17 @@
 should be easy to run the sample programs with the
 following command:
 
-./waf --run simple-p2p
+./waf --run simple-point-to-point
 
-That program should generate a simple-p2p.tr text 
-trace file and a set of simple-p2p-xx-xx.pcap binary
+That program should generate a simple-point-to-point.tr text 
+trace file and a set of simple-point-to-point-xx-xx.pcap binary
 pcap trace files, which can be read by tcpdump.
 
 5) Getting access to the ns-3 documentation
 -------------------------------------------
 
 Once you have verified that your build of ns-3 works by running
-the simple-p2p example as outlined in 4) above, it is
+the simple-point-to-point example as outlined in 4) above, it is
 quite likely that you will want to get started on reading
 some ns-3 documentation. 
 
--- a/RELEASE_NOTES	Wed Oct 10 12:25:52 2007 -0700
+++ b/RELEASE_NOTES	Thu Nov 08 16:58:24 2007 -0800
@@ -3,6 +3,13 @@
 
 This file contains ns-3 release notes (most recent releases first).
 
+Release 3.0.7 (2007/10/15)
+========================
+  - OLSR routing protocol
+  - A timer class
+  - Additional mobility models (random waypoint, random 2D walk)
+  - A mobility visualization tool 
+
 Release 3.0.6 (2007/09/15)
 ========================
   - Static multicast IPv4 routing
--- a/VERSION	Wed Oct 10 12:25:52 2007 -0700
+++ b/VERSION	Thu Nov 08 16:58:24 2007 -0800
@@ -1,1 +1,1 @@
-3.0.6
+3.0.7
--- a/doc/build.txt	Wed Oct 10 12:25:52 2007 -0700
+++ b/doc/build.txt	Thu Nov 08 16:58:24 2007 -0800
@@ -3,79 +3,62 @@
 
 === Installing Waf ===
 
-If this file is part of a development release tarball, the top-level 
-ns-3 directory should contain a current waf script.
-
-However, the ns-3 Mercurial code repository does not contain the waf 
-script.  Instead, developers should check it out from a subversion 
-repository:
-
-  svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf
-
-[ note: 'tags/ns3' is a tag that represents the last svn version
-tested to work correctly with ns3, although 'trunk' will likely work
- as well ]
-
-Then it can be installed system-wide with 'sudo waf-light install'.
-When preparing a distribution, the resulting 'waf' script, which is
-self contained (no external files needed), can be easily included in
-the tarball so that users downloading ns-3 can easily build it without
-having Waf installed (although Python >= 2.3 is still needed).
+The top-level ns-3 directory should contain a current waf script.
 
 === Building with Waf ===
 
-To build ns-3 with waf type the commands:
- 1. waf configure [options]
- 2. waf
+To build ns-3 with waf type the commands from the top-level directory:
+ 1. ./waf configure [options]
+ 2. ./waf
 
-To see valid configure options, type waf --help.  The most important
+To see valid configure options, type ./waf --help.  The most important
 option is -d <debug level>.  Valid debug levels (which are listed in
-waf --help) are: ultradebug, debug, release, and optimized.  It is
+waf --help) are: "debug" or "optimized".  It is
 also possible to change the flags used for compilation with (e.g.):
-CXXFLAGS="-O3" waf configure.
+CXXFLAGS="-O3" ./waf configure.
 
 [ Note:  Unlike some other build tools, to change the build target,
 the option must be supplied during the configure stage rather than
-the build stage (i.e., "waf -d optimized" will not work; instead, do
-"waf -d optimized configure; waf" ]
+the build stage (i.e., "./waf -d optimized" will not work; instead, do
+"./waf -d optimized configure; ./waf" ]
 
 The resulting binaries are placed in build/<debuglevel>/srcpath.
 
 Other waf usages include:
 
- 1. waf check
+ 1. ./waf check
     Runs the unit tests
 
- 2. waf --doxygen
+ 2. ./waf --doxygen
     Run doxygen to generate documentation
 
- 3. waf --lcov-report
+ 3. ./waf --lcov-report
     Run code coverage analysis (assuming the project was configured
 with --enable-gcov)
 
- 4. waf --run "program [args]"
+ 4. ./waf --run "program [args]"
     Run a ns3 program, given its target name, with the given
     arguments.  This takes care of automatically modifying the the
     path for finding the ns3 dynamic libraries in the environment
     before running the program.  Note: the "program [args]" string is
     parsed using POSIX shell rules.
 
- 4.1 waf --run programname --command-template "... %s ..."
+ 4.1 ./waf --run programname --command-template "... %s ..."
 
     Same as --run, but uses a command template with %s replaced by the
     actual program (whose name is given by --run).  This can be use to
     run ns-3 programs with helper tools.  For example, to run unit
     tests with valgrind, use the command:
 
-         waf --run run-tests --command-template "valgrind %s"
+         ./waf --run run-tests --command-template "valgrind %s"
 
- 5. waf --shell
+ 5. ./waf --shell
     Starts a nested system shell with modified environment to run ns3 programs.
 
- 6. waf distclean
+ 6. ./waf distclean
     Cleans out the entire build/ directory
 
- 7. waf dist
+ 7. ./waf dist
     The command 'waf dist' can be used to create a distribution tarball.
     It includes all files in the source directory, except some particular
     extensions that are blacklisted, such as back files (ending in ~).
--- a/doc/doxygen.conf	Wed Oct 10 12:25:52 2007 -0700
+++ b/doc/doxygen.conf	Thu Nov 08 16:58:24 2007 -0800
@@ -1,4 +1,4 @@
-# Doxyfile 1.4.4
+# Doxyfile 1.5.4
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project
@@ -14,10 +14,18 @@
 # Project related configuration options
 #---------------------------------------------------------------------------
 
+# This tag specifies the encoding used for all characters in the config file that 
+# follow. The default is UTF-8 which is also the encoding used for all text before 
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into 
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of 
+# possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
 # by quotes) that should identify the project.
 
-PROJECT_NAME           = "NS-3"
+PROJECT_NAME           = "NS-3 "
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number. 
 # This could be handy for archiving the generated documentation or 
@@ -45,24 +53,14 @@
 # documentation generated by doxygen is written. Doxygen will use this 
 # information to generate all constant output in the proper language. 
 # The default language is English, other supported languages are: 
-# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, 
-# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, 
-# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, 
-# Swedish, and Ukrainian.
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian, 
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean, 
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian, 
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
 
 OUTPUT_LANGUAGE        = English
 
-# This tag can be used to specify the encoding used in the generated output. 
-# The encoding is not always determined by the language that is chosen, 
-# but also whether or not the output is meant for Windows or non-Windows users. 
-# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES 
-# forces the Windows encoding (this is the default for the Windows binary), 
-# whereas setting the tag to NO uses a Unix-style encoding (the default for 
-# all platforms other than Windows).
-
-USE_WINDOWS_ENCODING   = NO
-
 # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
 # include brief member descriptions after the members that are listed in 
 # the file and class documentation (similar to JavaDoc). 
@@ -135,11 +133,19 @@
 # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
 # will interpret the first line (until the first dot) of a JavaDoc-style 
 # comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like the Qt-style comments (thus requiring an 
-# explicit @brief command for a brief description.
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
 
 JAVADOC_AUTOBRIEF      = NO
 
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
 # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
 # treat a multi-line C++ special comment block (i.e. a block of //! or /// 
 # comments) as a brief description. This used to be the default behaviour. 
@@ -161,13 +167,6 @@
 
 INHERIT_DOCS           = YES
 
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
 # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
 # a new page for each member. If set to NO, the documentation of a member will 
 # be part of the file/class/namespace that contains it.
@@ -195,13 +194,40 @@
 
 OPTIMIZE_OUTPUT_FOR_C  = NO
 
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources 
-# only. Doxygen will then generate output that is more tailored for Java. 
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for Java. 
 # For instance, namespaces will be presented as packages, qualified scopes 
 # will look different, etc.
 
 OPTIMIZE_OUTPUT_JAVA   = NO
 
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to 
+# include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
 # Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
 # the same type (for instance a group of public functions) to be put as a 
 # subgroup of that type (e.g. under the Public Functions section). Set it to 
@@ -210,6 +236,16 @@
 
 SUBGROUPING            = YES
 
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is 
+# documented as struct with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code where the coding convention is that all structs are 
+# typedef'ed and only the typedef is referenced never the struct's name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
 #---------------------------------------------------------------------------
 # Build related configuration options
 #---------------------------------------------------------------------------
@@ -244,6 +280,13 @@
 
 EXTRACT_LOCAL_METHODS  = NO
 
+# If this flag is set to YES, the members of anonymous namespaces will be extracted 
+# and appear in the documentation as a namespace called 'anonymous_namespace{file}', 
+# where file will be replaced with the base name of the file that contains the anonymous 
+# namespace. By default anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
 # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
 # undocumented members of documented classes, files or namespaces. 
 # If set to NO (the default) these members will be included in the 
@@ -376,7 +419,7 @@
 
 # If the sources in your project are distributed over multiple directories 
 # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
-# in the documentation. The default is YES.
+# in the documentation. The default is NO.
 
 SHOW_DIRECTORIES       = NO
 
@@ -385,7 +428,7 @@
 # version control system). Doxygen will invoke the program by executing (via 
 # popen()) the command <command> <input-file>, where <command> is the value of 
 # the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
-# provided by doxygen. Whatever the progam writes to standard output 
+# provided by doxygen. Whatever the program writes to standard output 
 # is used as the file version. See the manual for examples.
 
 FILE_VERSION_FILTER    = 
@@ -433,7 +476,7 @@
 # $version, which will be replaced by the version of the file (if it could 
 # be obtained via FILE_VERSION_FILTER)
 
-WARN_FORMAT            = "$file:$line: $text"
+WARN_FORMAT            = "$file:$line: $text "
 
 # The WARN_LOGFILE tag can be used to specify a file to which warning 
 # and error messages should be written. If left blank the output is written 
@@ -450,16 +493,27 @@
 # directories like "/usr/src/myproject". Separate the files or directories 
 # with spaces.
 
-INPUT                  = src doc/main.txt doc/trace-source-list.h doc/tracing.h
+INPUT                  = src \
+                         doc/main.txt \
+                         doc/trace-source-list.h \
+                         doc/tracing.h
+
+# This tag can be used to specify the character encoding of the source files that 
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default 
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding. 
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
 
 # If the value of the INPUT tag contains directories, you can use the 
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
 # and *.h) to filter out the source-files in the directories. If left 
 # blank the following patterns are tested: 
 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
 
-FILE_PATTERNS          = *.h *.tcc
+FILE_PATTERNS          = *.h \
+                         *.tcc
 
 # The RECURSIVE tag can be used to turn specify whether or not subdirectories 
 # should be searched for input files as well. Possible values are YES and NO. 
@@ -471,10 +525,12 @@
 # excluded from the INPUT source files. This way you can easily exclude a 
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
 
-EXCLUDE                = \
- src/simulator/high-precision.h \
- src/simulator/high-precision-128.h \
- src/simulator/high-precision-double.h
+EXCLUDE                = src/routing/olsr/olsr-state.h \
+                         src/routing/olsr/repositories.h \
+                         src/routing/olsr/routing-table.h \
+                         src/simulator/high-precision.h \
+                         src/simulator/high-precision-128.h \
+                         src/simulator/high-precision-double.h
 
 # The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
 # directories that are symbolic links (a Unix filesystem feature) are excluded 
@@ -490,6 +546,13 @@
 
 EXCLUDE_PATTERNS       = 
 
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the output. 
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used, 
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
 # The EXAMPLE_PATH tag can be used to specify one or more files or 
 # directories that contain example code fragments that are included (see 
 # the \include command).
@@ -548,7 +611,9 @@
 # If the SOURCE_BROWSER tag is set to YES then a list of source files will 
 # be generated. Documented entities will be cross-referenced with these sources. 
 # Note: To get rid of all source code in the generated output, make sure also 
-# VERBATIM_HEADERS is set to NO.
+# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH 
+# then you must also enable this option. If you don't then doxygen will produce 
+# a warning and turn it on anyway
 
 SOURCE_BROWSER         = NO
 
@@ -575,6 +640,13 @@
 
 REFERENCES_RELATION    = YES
 
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
 # If the USE_HTAGS tag is set to YES then the references to source code 
 # will point to the HTML generated by the htags(1) tool instead of doxygen 
 # built-in source browser. The htags tool is part of GNU's global source 
@@ -667,6 +739,14 @@
 
 GENERATE_HTMLHELP      = NO
 
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
 # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
 # be used to specify the file name of the resulting .chm file. You 
 # can add a path in front of the file if the result should not be 
@@ -969,7 +1049,7 @@
 
 # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
 # then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+# PREDEFINED and EXPAND_AS_DEFINED tags.
 
 EXPAND_ONLY_PREDEF     = NO
 
@@ -999,7 +1079,9 @@
 # undefined via #undef or recursively expanded use the := operator 
 # instead of the = operator.
 
-PREDEFINED             = RUN_SELF_TESTS NS3_DEBUG_ENABLE NS3_ASSERT_ENABLE
+PREDEFINED             = RUN_SELF_TESTS \
+                         NS3_ASSERT_ENABLE \
+                         NS3_LOG_ENABLE
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
@@ -1072,6 +1154,14 @@
 
 CLASS_DIAGRAMS         = YES
 
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to 
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to 
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to 
+# be found in the default search path.
+
+MSCGEN_PATH            = 
+
 # If set to YES, the inheritance and collaboration graphs will hide 
 # inheritance and usage relations if the target is undocumented 
 # or is not a class.
@@ -1129,7 +1219,7 @@
 
 INCLUDED_BY_GRAPH      = YES
 
-# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will 
+# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will 
 # generate a call dependency graph for every global function or class method. 
 # Note that enabling this option will significantly increase the time of a run. 
 # So in most cases it will be better to enable call graphs for selected 
@@ -1137,6 +1227,14 @@
 
 CALL_GRAPH             = NO
 
+# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will 
+# generate a caller dependency graph for every global function or class method. 
+# Note that enabling this option will significantly increase the time of a run. 
+# So in most cases it will be better to enable caller graphs for selected 
+# functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
 # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
 # will graphical hierarchy of all classes instead of a textual one.
 
@@ -1166,31 +1264,23 @@
 
 DOTFILE_DIRS           = 
 
-# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_WIDTH    = 1024
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the number 
+# of direct children of the root node in a graph is already larger than 
+# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
 
-# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height 
-# (in pixels) of the graphs generated by dot. If a graph becomes larger than 
-# this value, doxygen will try to truncate the graph, so that it fits within 
-# the specified constraint. Beware that most browsers cannot cope with very 
-# large images.
-
-MAX_DOT_GRAPH_HEIGHT   = 1024
+DOT_GRAPH_MAX_NODES    = 50
 
 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
 # graphs generated by dot. A depth value of 3 means that only nodes reachable 
 # from the root by following a path via at most 3 edges will be shown. Nodes 
 # that lay further from the root node will be omitted. Note that setting this 
 # option to 1 or 2 may greatly reduce the computation time needed for large 
-# code bases. Also note that a graph may be further truncated if the graph's 
-# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH 
-# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), 
-# the graph is not depth-constrained.
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
--- a/doc/main.txt	Wed Oct 10 12:25:52 2007 -0700
+++ b/doc/main.txt	Thu Nov 08 16:58:24 2007 -0800
@@ -18,7 +18,7 @@
  *    - a Functor class: ns3::Callback
  *    - an os-independent interface to get access to the elapsed wall clock time: ns3::SystemWallClockMs
  *    - a class to register regression tests with the test manager: ns3::Test and ns3::TestManager
- *    - debugging facilities: \ref debugging, \ref assert, \ref error
+ *    - debugging facilities: \ref logging, \ref assert, \ref error
  *    - \ref randomvariable
  *    - \ref config
  *    - a base class for objects which need to support reference counting 
@@ -65,4 +65,4 @@
 /**
  * \defgroup constants Constants
  * \brief Constants you can change
- */
\ No newline at end of file
+ */
--- a/doc/release_steps.txt	Wed Oct 10 12:25:52 2007 -0700
+++ b/doc/release_steps.txt	Thu Nov 08 16:58:24 2007 -0800
@@ -1,24 +1,34 @@
 Steps in doing an ns-3 release
 
+0. check out a clean ns-3-dev somewhere
 1. prepare the source files
    - revise and check in AUTHORS, if needed
    - revise and check in RELEASE_NOTES
    - update and check in VERSION to the latest release number
+   - confirm that Doxygen builds cleanly and without warnings
+     (./waf --doxygen), and check in any necessary changes 
 2. make a new "architecture.pdf" document and place it in the doc/ directory
-3. cd ns-3-dev; ./waf configure; ./waf dist
+   of the ns-3-dev working directory
+3. ./waf configure; ./waf dist
+   - this will create a ns-3.0.x.tar.bz2 tarball
 4. test tarball on release platforms (waf check and maybe some other scripts)
-5. tag ns-3-dev with "release ns-3.0.X"
-  - hg tag "release ns-3.0.x"
-  - hg push 
+5. once you are happy with the tarball, tag ns-3-dev with "release ns-3.0.X"
+   - hg tag "release ns-3.0.x"
+   - hg push 
 6. clone the tagged ns-3-dev and place it on the repository
-  - ssh code.nsnam.org; sudo; su code;
-  - cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x
-  - cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately
-7. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server
+   - ssh code.nsnam.org; sudo; su code;
+   - cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x
+   - cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately
+7. upload "ns-3.0.x.tar.bz2" to the /var/www/html/releases/ directory on 
+   the www.nsnam.org server
 8. update web page
    - add link to news.html
-   - update download.html
-   - update roadmap.html
+   - update getting_started.html
+   - update documents.html
+   - update roadmap on wiki
    - build and update Doxygen directory on the server
+     -- ssh www.nsnam.org; sudo tcsh; su nsnam;
+     -- ~/bin/update-doxygen-release
    - update and upload software architecture document (PDF, HTML)
+     -- note:  HTML image generation is not currently automatic
 9. announce to ns-developers, with summary of release notes
--- a/doc/tracing.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/doc/tracing.h	Thu Nov 08 16:58:24 2007 -0800
@@ -497,6 +497,8 @@
  *   };
  *   // called from MyModel::GetTraceResolver
  *   MyModelTraceType (enum Type type);
+ *   // needed for by the tracing subsystem.
+ *   MyModelTraceType ();
  *   // called from trace sink
  *   enum Type Get (void) const;
  *   // needed by the tracing subsystem
@@ -513,10 +515,14 @@
  * \endcode
  * The implementation does not require much thinking:
  * \code
+ * MyModelTraceType::MyModelTraceType ()
+ *  : m_type (RX)
+ * {// an arbitrary default value.
+ * }
  * MyModelTraceType::MyModelTraceType (enum Type type)
  *  : m_type (type)
  * {}
- * enum Type 
+ * enum MyModelTraceType::Type 
  * MyModelTraceType::Get (void) const
  * {
  *   return m_type;
@@ -531,14 +537,14 @@
  * }
  * void 
  * MyModelTraceType::Print (std::ostream &os) const
- * (
+ * {
  *   // this method is invoked by the print function of a TraceContext
  *   // if it contains an instance of this TraceContextElement.
  *   switch (m_type) {
  *     case RX: os << "rx"; break;
  *     // ...
  *   }
- * )
+ * }
  * std::string 
  * MyModelTraceType::GetTypeName (void) const
  * {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-alternate-routing.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,224 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+//
+// Network topology
+//
+//  n0
+//     \ 5 Mb/s, 2ms
+//      \          1.5Mb/s, 10ms
+//       n2 ------------------------n3
+//      /                          /
+//     / 5 Mb/s, 2ms              /
+//   n1--------------------------
+//          1.5 Mb/s, 100ms
+//
+// this is a modification of simple-global-routing to allow for
+// a single hop but higher-cost path between n1 and n3
+// 
+// - Tracing of queues and packet receptions to file "simple-rerouting.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/log.h"
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/global-route-manager.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("SimpleAlternateRoutingExample");
+
+int 
+main (int argc, char *argv[])
+{
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 0 
+  LogComponentEnable("GlobalRouteManager", LOG_LOGIC);
+  LogComponentEnable("GlobalRouter", LOG_LOGIC);
+  LogComponentEnable("Object", LOG_LEVEL_ALL);
+  LogComponentEnable("Queue", LOG_LEVEL_ALL);
+  LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL);
+  LogComponentEnable("Channel", LOG_LEVEL_ALL);
+  LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL);
+  LogComponentEnable("NetDevice", LOG_LEVEL_ALL);
+  LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("PacketSocket", LOG_LEVEL_ALL);
+  LogComponentEnable("Socket", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpSocket", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpL4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4StaticRouting", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL);
+  LogComponentEnable("ArpIpv4Interface", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4LoopbackInterface", LOG_LEVEL_ALL);
+  LogComponentEnable("OnOffApplication", LOG_LEVEL_ALL);
+  LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
+#endif
+  // Set up some default values for the simulation.  Use the 
+  // DefaultValue::Bind () technique to tell the system what subclass of 
+  // Queue to use, and what the queue limit is
+
+  // The below Bind command tells the queue factory which class to
+  // instantiate, when the queue factory is invoked in the topology code
+  DefaultValue::Bind ("Queue", "DropTailQueue");
+
+  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
+  DefaultValue::Bind ("OnOffApplicationDataRate", "300b/s");
+
+  // The below metric, if set to 3 or higher, will cause packets between
+  // n1 and n3 to take the 2-hop route through n2
+  // 
+  // Additionally, we plumb this metric into the default value / command 
+  // line argument system as well, for exemplary purposes.  This means 
+  // that it can be resettable at the command-line to the program, 
+  // rather than recompiling
+  // e.g. waf --run "simple-alternate-routing --AlternateCost=5"
+  uint16_t sampleMetric = 1;
+  CommandLine::AddArgValue ("AlternateCost",
+    "This metric is used in the example script between n3 and n1 ", 
+    sampleMetric);
+
+  // Allow the user to override any of the defaults and the above
+  // DefaultValue::Bind ()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  NS_LOG_INFO ("Create nodes.");
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  NS_LOG_INFO ("Create channels.");
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+      n0, n2, DataRate (5000000), MilliSeconds (2));
+
+  Ptr<PointToPointChannel> channel1 = 
+    PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate (5000000), MilliSeconds (2));
+  
+  Ptr<PointToPointChannel> channel2 = 
+    PointToPointTopology::AddPointToPointLink (
+      n2, n3, DataRate (1500000), MilliSeconds (10));
+  
+  Ptr<PointToPointChannel> channel3 = 
+    PointToPointTopology::AddPointToPointLink (
+      n1, n3, DataRate (1500000), MilliSeconds (100));
+  
+  // Later, we add IP addresses.  The middle two octets correspond to 
+ // the channel number.  
+  NS_LOG_INFO ("Assign IP Addresses.");
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address ("10.0.0.1"),
+      n2, Ipv4Address ("10.0.0.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address ("10.1.1.1"),
+      n2, Ipv4Address ("10.1.1.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel2, n2, Ipv4Address ("10.2.2.1"),
+      n3, Ipv4Address ("10.2.2.2"));
+
+  PointToPointTopology::AddIpv4Addresses (
+      channel3, n1, Ipv4Address ("10.3.3.1"),
+      n3, Ipv4Address ("10.3.3.2"));
+
+  PointToPointTopology::SetIpv4Metric (
+      channel3, n1, n3, sampleMetric);
+
+  // Create router nodes, initialize routing database and set up the routing
+  // tables in the nodes.
+  GlobalRouteManager::PopulateRoutingTables ();
+
+  // Create the OnOff application to send UDP datagrams 
+  NS_LOG_INFO ("Create Application.");
+  uint16_t port = 9;   // Discard port (RFC 863)
+
+  // Create a flow from n3 to n1, starting at time 1.1 seconds
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n3, 
+    InetSocketAddress ("10.1.1.1", port),
+    "Udp",
+    ConstantVariable (1), 
+    ConstantVariable (0));
+  // Start the application
+  ooff->Start (Seconds (1.1));
+  ooff->Stop (Seconds (10.0));
+
+  // Create a packet sink to receive these packets
+  Ptr<PacketSink> sink = Create<PacketSink> (
+    n1, 
+    InetSocketAddress (Ipv4Address::GetAny (), port), 
+    "Udp");
+  // Start the sink
+  sink->Start (Seconds (1.1));
+  sink->Stop (Seconds (10.0));
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-alternate-routing.tr file
+  NS_LOG_INFO ("Configure Tracing.");
+  AsciiTrace asciitrace ("simple-alternate-routing.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("simple-alternate-routing.pcap");
+  pcaptrace.TraceAllIp ();
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-point-to-point-olsr.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,233 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ * ns-2 simple.tcl script (ported from ns-2)
+ * Originally authored by Steve McCanne, 12/19/1996
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//  n0
+//     \ 5 Mb/s, 2ms
+//      \          1.5Mb/s, 10ms
+//       n2 -------------------------n3
+//      /
+//     / 5 Mb/s, 2ms
+//   n1
+//
+// - all links are point-to-point links with indicated one-way BW/delay
+// - CBR/UDP flows from n0 to n3, and from n3 to n1
+// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+//   (i.e., DataRate of 448,000 bps)
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file 
+//   "simple-point-to-point.tr"
+
+#include "ns3/log.h"
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/packet-sink.h"
+#include "ns3/olsr.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("SimplePointToPointExample");
+
+int 
+main (int argc, char *argv[])
+{
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 0 
+  LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_INFO);
+
+  LogComponentEnable("Object", LOG_LEVEL_ALL);
+  LogComponentEnable("Queue", LOG_LEVEL_ALL);
+  LogComponentEnable("DropTailQueue", LOG_LEVEL_ALL);
+  LogComponentEnable("Channel", LOG_LEVEL_ALL);
+  LogComponentEnable("CsmaChannel", LOG_LEVEL_ALL);
+  LogComponentEnable("NetDevice", LOG_LEVEL_ALL);
+  LogComponentEnable("CsmaNetDevice", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("PacketSocket", LOG_LEVEL_ALL);
+  LogComponentEnable("Socket", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpSocket", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpL4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4StaticRouting", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL);
+  LogComponentEnable("ArpIpv4Interface", LOG_LEVEL_ALL);
+  LogComponentEnable("Ipv4LoopbackInterface", LOG_LEVEL_ALL);
+  LogComponentEnable("OnOffApplication", LOG_LEVEL_ALL);
+  LogComponentEnable("PacketSinkApplication", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_ALL);
+  LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
+#endif
+
+  // Set up some default values for the simulation.  Use the Bind()
+  // technique to tell the system what subclass of Queue to use,
+  // and what the queue limit is
+
+  // The below Bind command tells the queue factory which class to
+  // instantiate, when the queue factory is invoked in the topology code
+  DefaultValue::Bind ("Queue", "DropTailQueue");
+
+  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
+  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+
+  //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  NS_LOG_INFO ("Create nodes.");
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  NS_LOG_INFO ("Create channels.");
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+      n0, n2, DataRate(5000000), MilliSeconds(2));
+
+  Ptr<PointToPointChannel> channel1 = 
+    PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate(5000000), MilliSeconds(2));
+  
+  Ptr<PointToPointChannel> channel2 = 
+    PointToPointTopology::AddPointToPointLink (
+      n2, n3, DataRate(1500000), MilliSeconds(10));
+  
+  // Later, we add IP addresses.  
+  NS_LOG_INFO ("Assign IP Addresses.");
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address("10.1.1.1"),
+      n2, Ipv4Address("10.1.1.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address("10.1.2.1"),
+      n2, Ipv4Address("10.1.2.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel2, n2, Ipv4Address("10.1.3.1"),
+      n3, Ipv4Address("10.1.3.2"));
+
+  // Finally, we add static routes.  These three steps (Channel and
+  // NetDevice creation, IP Address assignment, and routing) are 
+  // separated because there may be a need to postpone IP Address
+  // assignment (emulation) or modify to use dynamic routing
+  NS_LOG_INFO ("Enabling OLSR Routing.");
+  olsr::EnableAllNodes ();
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  NS_LOG_INFO ("Create Applications.");
+  uint16_t port = 9;   // Discard port (RFC 863)
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    InetSocketAddress ("10.1.3.2", port), 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Create an optional packet sink to receive these packets
+  Ptr<PacketSink> sink = Create<PacketSink> (
+    n3,
+    InetSocketAddress (Ipv4Address::GetAny (), port),
+    "Udp");
+  // Start the sink
+  sink->Start (Seconds (1.0));
+  sink->Stop (Seconds (10.0));
+
+  // Create a similar flow from n3 to n1, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    InetSocketAddress ("10.1.2.1", port), 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.1));
+  ooff->Stop (Seconds(10.0));
+
+  // Create a packet sink to receive these packets
+  sink = Create<PacketSink> (
+    n1,
+    InetSocketAddress (Ipv4Address::GetAny (), port),
+    "Udp");
+  // Start the sink
+  sink->Start (Seconds (1.1));
+  sink->Stop (Seconds (10.0));
+
+  // Here, finish off packet routing configuration
+  // This will likely set by some global StaticRouting object in the future
+  NS_LOG_INFO ("Set Default Routes.");
+  Ptr<Ipv4> ipv4;
+  ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
+  ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
+  ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
+  
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-point-to-point.tr file
+  NS_LOG_INFO ("Configure Tracing.");
+  AsciiTrace asciitrace ("simple-point-to-point-olsr.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-point-to-point.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("simple-point-to-point-olsr.pcap");
+  pcaptrace.TraceAllIp ();
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::StopAt (Seconds (10));
+  Simulator::Run ();    
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+}
--- a/examples/simple-point-to-point.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/examples/simple-point-to-point.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -227,6 +227,7 @@
   pcaptrace.TraceAllIp ();
 
   NS_LOG_INFO ("Run Simulation.");
+  Simulator::StopAt (Seconds (10));
   Simulator::Run ();    
   Simulator::Destroy ();
   NS_LOG_INFO ("Done.");
--- a/examples/wscript	Wed Oct 10 12:25:52 2007 -0700
+++ b/examples/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -6,6 +6,10 @@
         ['point-to-point', 'internet-node', 'global-routing'])
     obj.source = 'simple-global-routing.cc'
 
+    obj = bld.create_ns3_program('simple-alternate-routing',
+        ['point-to-point', 'internet-node', 'global-routing'])
+    obj.source = 'simple-alternate-routing.cc'
+
     obj = bld.create_ns3_program('simple-point-to-point',
         ['point-to-point', 'internet-node'])
     obj.source = 'simple-point-to-point.cc'
@@ -33,3 +37,7 @@
     obj = bld.create_ns3_program( 'mixed-global-routing',
         ['point-to-point', 'internet-node', 'global-routing' , 'csma-cd'])
     obj.source = 'mixed-global-routing.cc'
+
+    obj = bld.create_ns3_program('simple-point-to-point-olsr',
+        ['point-to-point', 'internet-node', 'olsr'])
+    obj.source = 'simple-point-to-point-olsr.cc'
--- a/samples/main-debug-other.cc	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-#include "ns3/debug.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("MyComponentB");
-
-namespace foo {
-
-void OneFunction (void)
-{
-  NS_DEBUG ("OneFunction debug");
-}
-
-}; // namespace foo
--- a/samples/main-debug.cc	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-#include "ns3/debug.h"
-#include "ns3/assert.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("MyComponentA");
-
-// declare other function
-namespace foo {
-void OneFunction (void);
-}
-
-int main (int argc, int argv)
-{
-  NS_DEBUG ("nargc="<<argc);
-
-  foo::OneFunction ();
-
-  NS_DEBUG ("other debug output");
-
-  int a;
-  a = 0;
-
-  NS_ASSERT (a == 0);
-  NS_ASSERT_MSG (a == 0, "my msg");
-  NS_ASSERT (a != 0);
-  NS_ASSERT_MSG (a != 0, "my 2 msg");
-}
--- a/samples/main-default-value.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/samples/main-default-value.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -62,7 +62,7 @@
   //utilize the loops variable to show that it can be read from the command line
   if(loops>0)
   {
-    cout<<"You requested "<<loops<<" iterations of a loop";
+    std::cerr<<"You requested "<<loops<<" iterations of a loop";
     for(uint32_t i=0;i<loops;++i)
       cout<<"iteration "<<i;
   }
--- a/samples/main-grid-topology.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/samples/main-grid-topology.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -41,7 +41,7 @@
       Ptr<Object> object = *j;
       Ptr<MobilityModel> position = object->QueryInterface<MobilityModel> (MobilityModel::iid);
       NS_ASSERT (position != 0);
-      Position pos = position->Get ();
+      Vector pos = position->GetPosition ();
       std::cout << "x=" << pos.x << ", y=" << pos.y << ", z=" << pos.z << std::endl;
     }
 
--- a/samples/main-random-topology.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/samples/main-random-topology.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -17,7 +17,7 @@
 static void 
 CourseChange (const TraceContext &context, Ptr<const MobilityModel> position)
 {
-  Position pos = position->Get ();
+  Vector pos = position->GetPosition ();
   std::cout << Simulator::Now () << ", pos=" << position << ", x=" << pos.x << ", y=" << pos.y
             << ", z=" << pos.z << std::endl;
 }
--- a/samples/main-random-walk.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/samples/main-random-walk.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -18,11 +18,11 @@
 static void 
 CourseChange (ns3::TraceContext const&, Ptr<const MobilityModel> mobility)
 {
-  Position pos = mobility->Get ();
-  Speed vel = mobility->GetSpeed ();
+  Vector pos = mobility->GetPosition ();
+  Vector vel = mobility->GetVelocity ();
   std::cout << Simulator::Now () << ", model=" << mobility << ", POS: x=" << pos.x << ", y=" << pos.y
-            << ", z=" << pos.z << "; VEL:" << vel.dx << ", y=" << vel.dy
-            << ", z=" << vel.dz << std::endl;
+            << ", z=" << pos.z << "; VEL:" << vel.x << ", y=" << vel.y
+            << ", z=" << vel.z << std::endl;
 }
 
 int main (int argc, char *argv[])
--- a/samples/wscript	Wed Oct 10 12:25:52 2007 -0700
+++ b/samples/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -1,9 +1,6 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 def build(bld):
-    obj = bld.create_ns3_program('main-debug')
-    obj.source = ['main-debug.cc', 'main-debug-other.cc']
-
     obj = bld.create_ns3_program('main-callback')
     obj.source = 'main-callback.cc'
 
--- a/src/common/packet-printer.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/common/packet-printer.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -71,7 +71,7 @@
   // if the over did not override this type of chunk,
   // we print something by default.
   std::string name = ChunkRegistry::GetName (chunkUid, instance);
-  os << name;
+  os << name << " ";
   ChunkRegistry::Print (chunkUid, instance, os);
 }
 void 
--- a/src/common/packet.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/common/packet.h	Thu Nov 08 16:58:24 2007 -0800
@@ -244,6 +244,16 @@
    * A packet is allocated a new uid when it is created
    * empty or with zero-filled payload.
    *
+   * Note: This uid is an internal uid and cannot be counted on to
+   * provide an accurate counter of how many "simulated packets" of a
+   * particular protocol are in the system. It is not trivial to make
+   * this uid into such a counter, because of questions such as what
+   * should the uid be when the packet is sent over broadcast media, or
+   * when fragmentation occurs. If a user wants to trace actual packet
+   * counts, he or she should look at e.g. the IP ID field or transport
+   * sequence numbers, or other packet or frame counters at other
+   * protocol layers.
+   *
    * \returns an integer identifier which uniquely
    *          identifies this packet.
    */
--- a/src/core/command-line.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/command-line.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -24,6 +24,15 @@
 
 namespace ns3 {
 
+CommandLine::List::~List ()
+{
+  for (iterator iter = begin (); iter != end (); iter++)
+    {
+      delete *iter;
+    }
+}
+
+
 CommandDefaultValue CommandLine::g_help ("help",
                                          "Print Help text for all commands",
                                          MakeCallback (&CommandLine::PrintHelp));
@@ -109,8 +118,15 @@
       std::string name, value;
       if (cur == std::string::npos)
         {
+          if (argc == 1)
+            {
+              // invalid argument. ignore it.
+              continue;
+            }
+          argv++;
+          argc--;
           name = param;
-          value = "";
+          value = *argv;
         }
       else
         {
@@ -124,7 +140,12 @@
           DefaultValueBase *item = *i;
           if (item->GetName () == name)
             {
-              item->ParseValue (value);
+              if (!item->ParseValue (value))
+                {
+                  std::cerr << "Warning: failed to parse command line argument `"
+                            << name << "' of type '" << item->GetType ()
+                            << "' with value `" << value << "'." << std::endl;
+                }
               continue;
             }
         }
@@ -144,3 +165,83 @@
 }
 
 }//namespace ns3
+
+
+
+#ifdef RUN_SELF_TESTS
+#include "test.h"
+#include <iostream>
+#include <sstream>
+
+namespace ns3 {
+
+
+class CommandLineTest : public Test
+{
+public:
+  CommandLineTest () : Test ("CommandLine") {}
+  virtual bool RunTests (void)
+  {
+    bool result = true;
+
+    // redirect stderr temporarily (else warnings appear during unit testing, which is not nice)
+    std::ostringstream nullout;
+    std::streambuf *origcerr = std::cerr.rdbuf (nullout.rdbuf ());
+    {
+      char *argv[] = {"run-tests", "--loops", "bad-value", NULL};
+      int argc = sizeof (argv) / sizeof (argv[0]) - 1;
+      
+      uint32_t loops = 123;
+      CommandLine::AddArgValue ("loops","a test of the command line", loops);
+      CommandLine::Parse (argc, argv);
+      
+      NS_TEST_ASSERT_EQUAL (loops, 123);
+    }
+
+    {
+      char *argv[] = {"run-tests", "--loops=bad-value", NULL};
+      int argc = sizeof (argv) / sizeof (argv[0]) - 1;
+      
+      uint32_t loops = 123;
+      CommandLine::AddArgValue ("loops","a test of the command line", loops);
+      CommandLine::Parse (argc, argv);
+      
+      NS_TEST_ASSERT_EQUAL (loops, 123);
+    }
+
+    {
+      char *argv[] = {"run-tests", "--loops", "456", NULL};
+      int argc = sizeof (argv) / sizeof (argv[0]) - 1;
+      
+      uint32_t loops = 123;
+      CommandLine::AddArgValue ("loops","a test of the command line", loops);
+      CommandLine::Parse (argc, argv);
+      
+      NS_TEST_ASSERT_EQUAL (loops, 456);
+    }
+
+    {
+      char *argv[] = {"run-tests", "--loops=456", NULL};
+      int argc = sizeof (argv) / sizeof (argv[0]) - 1;
+      
+      uint32_t loops = 123;
+      CommandLine::AddArgValue ("loops","a test of the command line", loops);
+      CommandLine::Parse (argc, argv);
+      
+      NS_TEST_ASSERT_EQUAL (loops, 456);
+    }
+
+    // unredirect cerr
+    std::cerr.rdbuf (origcerr);
+
+
+    return result;
+  }
+};
+
+
+static CommandLineTest g_commandLineTests;
+
+}//namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- a/src/core/command-line.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/command-line.h	Thu Nov 08 16:58:24 2007 -0800
@@ -85,7 +85,12 @@
     T *m_valuePtr;
   };
   static void PrintHelp (void);
-  typedef std::list<DefaultValueBase *> List;
+
+  class List : public std::list<DefaultValueBase *>
+  {
+  public:
+    ~List ();
+  };
   static List *GetUserList (void);
   static CommandDefaultValue g_help;
 };
@@ -123,14 +128,18 @@
   iss.str (value);
   T v;
   iss >> v;
-  *m_valuePtr = v;
-  return !iss.bad () && !iss.fail ();
+  bool ok = (!iss.bad () && !iss.fail ());
+  if (ok)
+    {
+      *m_valuePtr = v;
+    }
+  return ok;
 }
 template <typename T>
 std::string
 CommandLine::UserDefaultValue<T>::DoGetType (void) const
 {
-  return "";
+  return TypeNameGet<T> ();
 }
 template <typename T>
 std::string
--- a/src/core/debug.cc	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,192 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 INRIA
- * All rights reserved.
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include <list>
-#include <utility>
-#include <iostream>
-#include "debug.h"
-#include "assert.h"
-#include "ns3/core-config.h"
-#include "fatal-error.h"
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-namespace ns3 {
-
-typedef std::list<std::pair <std::string, DebugComponent *> > ComponentList;
-typedef std::list<std::pair <std::string, DebugComponent *> >::iterator ComponentListI;
-
-static 
-ComponentList *GetComponentList (void)
-{
-  static ComponentList components;
-  return &components;
-}
-
-
-static bool g_firstDebug = true;
-
-void
-DebugComponentEnableEnvVar (void)
-{
-#ifdef HAVE_GETENV
-  char *envVar = getenv("NS_DEBUG");
-  if (envVar == 0)
-    {
-      return;
-    }
-  bool allFound = true;
-  std::string env = envVar;
-  std::string::size_type cur = 0;
-  std::string::size_type next = 0;
-  while (true)
-    {
-      next = env.find_first_of (";", cur);
-      std::string tmp = std::string (env, cur, next);
-      {
-        /* The following code is a workaround for a bug in the g++
-         * c++ string library. Its goal is to remove any trailing ';'
-         * from the string even though there should not be any in
-         * it. This code should be safe even if the bug is not there.
-         */
-        std::string::size_type trailing = tmp.find_first_of (";");
-        tmp = tmp.substr (0, trailing);
-      }
-      if (tmp.size () == 0)
-        {
-          break;
-        }
-      bool found = false;
-      ComponentList *components = GetComponentList ();
-      for (ComponentListI i = components->begin ();
-           i != components->end ();
-           i++)
-        {
-          if (i->first.compare (tmp) == 0)
-            {
-              found = true;
-              i->second->Enable ();
-              break;
-            }
-        }
-      if (!found)
-        {
-          allFound = false;
-        }
-      if (next == std::string::npos)
-        {
-          break;
-        }
-      cur = next + 1;
-      if (cur >= env.size ()) 
-        {
-          break;
-        }
-    }
-  if (allFound)
-    {
-      g_firstDebug = true;
-    }
-  
-#endif
-}
-
-
-DebugComponent::DebugComponent (char const * name)
-  : m_isEnabled (false)
-{
-  ComponentList *components = GetComponentList ();
-  for (ComponentListI i = components->begin ();
-       i != components->end ();
-       i++)
-    {
-      NS_ASSERT (i->first != name);
-    }
-  components->push_back (std::make_pair (name, this));
-}
-bool 
-DebugComponent::IsEnabled (void)
-{
-  if (g_firstDebug) 
-    {
-      DebugComponentEnableEnvVar ();
-    }
-  return m_isEnabled;
-}
-void 
-DebugComponent::Enable (void)
-{
-  m_isEnabled = true;
-}
-void 
-DebugComponent::Disable (void)
-{
-  m_isEnabled = false;
-}
-
-void 
-DebugComponentEnable (char const *name)
-{
-  ComponentList *components = GetComponentList ();
-  for (ComponentListI i = components->begin ();
-       i != components->end ();
-       i++)
-    {
-      if (i->first.compare (name) == 0) 
-	{
-	  i->second->Enable ();
-	  break;
-	}
-    }  
-}
-void 
-DebugComponentDisable (char const *name)
-{
-  ComponentList *components = GetComponentList ();
-  for (ComponentListI i = components->begin ();
-       i != components->end ();
-       i++)
-    {
-      if (i->first.compare (name) == 0) 
-	{
-	  i->second->Disable ();
-	  break;
-	}
-    }  
-}
-
-
-void 
-DebugComponentPrintList (void)
-{
-  ComponentList *components = GetComponentList ();
-  for (ComponentListI i = components->begin ();
-       i != components->end ();
-       i++)
-    {
-      std::cout << i->first << "=" << (i->second->IsEnabled ()?"enabled":"disabled") << std::endl;
-    }
-}
-
-}; // namespace ns3
-
-
--- a/src/core/debug.h	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 INRIA
- * All rights reserved.
- *
- * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef DEBUG_H
-#define DEBUG_H
-
-/**
- * \defgroup debugging Debugging
- * \brief Debugging functions and macros
- *
- *   - DEBUG functionality: macros which allow developers to
- *     send information out on screen only in debugging builds.
- *     All debug messages are disabled by default. To enable 
- *     selected debug messages, use the ns3::DebugComponentEnable
- *     function. Alternatively, you can use the NS_DEBUG 
- *     environment variable to define a ';'-separated list of
- *     messages to enable. For example, NS_DEBUG=a;b;c;DAFD;GH
- *     would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
- */
-
-namespace ns3 {
-
-/**
- * \param name a debug component name
- * \ingroup debugging
- *
- * Enable the debugging output associated with that debug component.
- * The debugging output can be later disabled with a call
- * to ns3::DebugComponentDisable.
- */
-void DebugComponentEnable (char const *name);
-/**
- * \param name a debug component name
- * \ingroup debugging
- *
- * Disable the debugging output associated with that debug component.
- * The debugging output can be later re-enabled with a call
- * to ns3::DebugComponentEnable.
- */
-void DebugComponentDisable (char const *name);
-/**
- * \ingroup debugging
- * Print the list of debugging messages available.
- */
-void DebugComponentPrintList (void);
-
-class DebugComponent {
-public:
-  DebugComponent (char const *name);
-  bool IsEnabled (void);
-  void Enable (void);
-  void Disable (void);
-private:
-  bool m_isEnabled;
-};
-
-}; // namespace ns3
-
-
-#ifdef NS3_DEBUG_ENABLE
-
-#include <string>
-#include <iostream>
-
-
-/**
- * \ingroup debugging
- * \param name a string
- *
- * Define a Debug component with a specific name. This macro
- * should be used at the top of every file in which you want 
- * to use the NS_DEBUG macro. This macro defines a new
- * "debug component" which can be later selectively enabled
- * or disabled with the ns3::DebugComponentEnable and 
- * ns3::DebugComponentDisable functions or with the NS_DEBUG
- * environment variable.
- */
-#define NS_DEBUG_COMPONENT_DEFINE(name)                                \
-  static ns3::DebugComponent g_debug = ns3::DebugComponent (name)
-
-/**
- * \ingroup debugging
- * \param msg message to output
- *
- * Generate debugging output in the "debug component" of the 
- * current file. i.e., every call to NS_DEBUG from within
- * a file implicitely generates out within the component
- * defined with the NS_DEBUG_COMPONENT_DEFINE macro in the
- * same file.
- */
-#define NS_DEBUG(msg)				\
-  do                                            \
-    {                                           \
-      if (g_debug.IsEnabled ())			\
-        {                                       \
-          std::cerr << msg << std::endl;        \
-        }                                       \
-    }                                           \
-  while (false)
-
-/**
- * \ingroup debugging
- * \param msg message to output
- *
- * Generate debugging output unconditionally in all
- * debug builds.
- */
-#define NS_DEBUG_UNCOND(msg)         \
-  do                                 \
-    {                                \
-      std::cerr << msg << std::endl; \
-    }                                \
-  while (false)
-
-#else /* NS3_DEBUG_ENABLE */
-
-#define NS_DEBUG_COMPONENT_DEFINE(name)
-#define NS_DEBUG(x)
-#define NS_DEBUG_UNCOND(msg)
-
-#endif /* NS3_DEBUG_ENABLE */
-
-#endif /* DEBUG_H */
--- a/src/core/default-value.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/default-value.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -416,6 +416,8 @@
   DefaultValueList::Remove ("bool-a");
   DefaultValueList::Remove ("test-i");
   DefaultValueList::Remove ("test-c");
+  DefaultValueList::Remove ("test-x");
+  DefaultValueList::Remove ("test-y");
   DefaultValueList::Remove ("test-ui32");
   
   return result;
--- a/src/core/log.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/log.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -18,6 +18,8 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
+// What about print-list!!!!!!???????
+
 #ifdef NS3_LOG_ENABLE
 
 #include <list>
@@ -44,29 +46,33 @@
   return &components;
 }
 
-void
-LogComponentEnableEnvVar (void)
+LogComponent::LogComponent (char const * name)
+  : m_levels (0), m_name (name)
 {
-  static bool isFirstLog = true;
-  if (!isFirstLog)
+  EnvVarCheck (name);
+
+  ComponentList *components = GetComponentList ();
+  for (ComponentListI i = components->begin ();
+       i != components->end ();
+       i++)
     {
-      return;
+      NS_ASSERT (i->first != name);
     }
+  components->push_back (std::make_pair (name, this));
+}
+
+void
+LogComponent::EnvVarCheck (char const * name)
+{
 #ifdef HAVE_GETENV
   char *envVar = getenv("NS_LOG");
   if (envVar == 0)
     {
-      isFirstLog = false;
       return;
     }
   std::string env = envVar;
-  if (env == "print-list")
-    {
-      LogComponentPrintList ();
-      isFirstLog = false;
-      return;
-    }
-  bool allFound = true;
+  std::string myName = name;
+
   std::string::size_type cur = 0;
   std::string::size_type next = 0;
   while (true)
@@ -88,106 +94,101 @@
         }
       std::string::size_type equal = tmp.find ("=");
       std::string component;
-      int level;
       if (equal == std::string::npos)
         {
           component = tmp;
-          level = LOG_DEBUG;
+          if (component == myName || component == "*")
+            {
+              Enable (LOG_DEBUG);
+              return;
+            }
         }
       else
         {
           component = tmp.substr (0, equal);
-          std::string::size_type cur_lev;
-          std::string::size_type next_lev = equal;
-          do
+          if (component == myName || component == "*")
             {
-              cur_lev = next_lev + 1;
-              next_lev = tmp.find ("|", cur_lev);
-              std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
-              if (lev == "error")
-                {
-                  level |= LOG_ERROR;
-                }
-              else if (lev == "warn")
-                {
-                  level |= LOG_WARN;
-                }
-              else if (lev == "debug")
-                {
-                  level |= LOG_DEBUG;
-                }
-              else if (lev == "info")
-                {
-                  level |= LOG_INFO;
-                }
-              else if (lev == "function")
-                {
-                  level |= LOG_FUNCTION;
-                }
-              else if (lev == "param")
-                {
-                  level |= LOG_PARAM;
-                }
-              else if (lev == "logic")
-                {
-                  level |= LOG_LOGIC;
-                }
-              else if (lev == "all")
-                {
-                  level |= LOG_ALL;
-                }
-              else if (lev == "errorlevel")
-                {
-                  level |= LOG_LEVEL_ERROR;
-                }
-              else if (lev == "warnlevel")
+              int level = 0;
+              std::string::size_type cur_lev;
+              std::string::size_type next_lev = equal;
+              do
                 {
-                  level |= LOG_LEVEL_WARN;
-                }
-              else if (lev == "debuglevel")
-                {
-                  level |= LOG_LEVEL_DEBUG;
-                }
-              else if (lev == "infolevel")
-                {
-                  level |= LOG_LEVEL_INFO;
-                }
-              else if (lev == "functionlevel")
-                {
-                  level |= LOG_LEVEL_FUNCTION;
-                }
-              else if (lev == "paramlevel")
-                {
-                  level |= LOG_LEVEL_PARAM;
-                }
-              else if (lev == "logiclevel")
-                {
-                  level |= LOG_LEVEL_LOGIC;
-                }
-              else if (lev == "alllevel")
-                {
-                  level |= LOG_LEVEL_ALL;
-                }
-            } while (next_lev != std::string::npos);
-        }
-      bool found = false;
-      ComponentList *components = GetComponentList ();
-      for (ComponentListI i = components->begin ();
-           i != components->end ();
-           i++)
-        {
-          if (i->first.compare (component) == 0)
-            {
-              found = true;
-              
-              i->second->Enable ((enum LogLevel)level);
-              break;
+                  cur_lev = next_lev + 1;
+                  next_lev = tmp.find ("|", cur_lev);
+                  std::string lev = tmp.substr (cur_lev, next_lev - cur_lev);
+                  if (lev == "error")
+                    {
+                      level |= LOG_ERROR;
+                    }
+                  else if (lev == "warn")
+                    {
+                      level |= LOG_WARN;
+                    }
+                  else if (lev == "debug")
+                    {
+                      level |= LOG_DEBUG;
+                    }
+                  else if (lev == "info")
+                    {
+                      level |= LOG_INFO;
+                    }
+                  else if (lev == "function")
+                    {
+                      level |= LOG_FUNCTION;
+                    }
+                  else if (lev == "param")
+                    {
+                      level |= LOG_PARAM;
+                    }
+                  else if (lev == "logic")
+                    {
+                      level |= LOG_LOGIC;
+                    }
+                  else if (lev == "all")
+                    {
+                      level |= LOG_ALL;
+                    }
+                  else if (lev == "prefix")
+                    {
+                      level |= LOG_PREFIX_ALL;
+                    }
+                  else if (lev == "level_error")
+                    {
+                      level |= LOG_LEVEL_ERROR;
+                    }
+                  else if (lev == "level_warn")
+                    {
+                      level |= LOG_LEVEL_WARN;
+                    }
+                  else if (lev == "level_debug")
+                    {
+                      level |= LOG_LEVEL_DEBUG;
+                    }
+                  else if (lev == "level_info")
+                    {
+                      level |= LOG_LEVEL_INFO;
+                    }
+                  else if (lev == "level_function")
+                    {
+                      level |= LOG_LEVEL_FUNCTION;
+                    }
+                  else if (lev == "level_param")
+                    {
+                      level |= LOG_LEVEL_PARAM;
+                    }
+                  else if (lev == "level_logic")
+                    {
+                      level |= LOG_LEVEL_LOGIC;
+                    }
+                  else if (lev == "level_all")
+                    {
+                      level |= LOG_LEVEL_ALL;
+                    }
+                } while (next_lev != std::string::npos);
+
+              Enable ((enum LogLevel)level);
             }
         }
-      if (!found)
-        {
-          allFound = false;
-        }
       if (next == std::string::npos)
         {
           break;
@@ -198,31 +199,14 @@
           break;
         }
     }
-  if (allFound)
-    {
-      isFirstLog = false;
-    }
-  
 #endif
 }
 
-LogComponent::LogComponent (char const * name)
-  : m_levels (0), m_name (name)
-{
-  ComponentList *components = GetComponentList ();
-  for (ComponentListI i = components->begin ();
-       i != components->end ();
-       i++)
-    {
-      NS_ASSERT (i->first != name);
-    }
-  components->push_back (std::make_pair (name, this));
-}
 
 bool 
 LogComponent::IsEnabled (enum LogLevel level) const
 {
-  LogComponentEnableEnvVar ();
+  //  LogComponentEnableEnvVar ();
   return (level & m_levels) ? 1 : 0;
 }
 
--- a/src/core/log.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/log.h	Thu Nov 08 16:58:24 2007 -0800
@@ -32,22 +32,23 @@
  *     send information out on screen. All logging messages 
  *     are disabled by default. To enable selected logging 
  *     messages, use the ns3::LogComponentEnable
- *     function. 
- * 
- * Alternatively, you can use the NS_LOG
- * environment variable to define a ';'-separated list of
+ *     function or use the NS_LOG environment variable and 
+ *     ns3::LogComponentEnableEnvVar
+ *
+ * Use the environment variable NS_LOG to define a ';'-separated list of
  * logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
  * would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
+ * NS_LOG=* will enable all available log components.
  *
  * For each component, the "debug" log level is enabled by default
  * but more components can be enabled selectively with the following
  * syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
  * This example would enable the 'func', 'param', and 'warn' log
  * levels for 'Component1' and the 'error' and 'debug' log levels
- * for 'Component2'.
+ * for 'Component2'.  The wildcard can be used here as well.  For example
+ * NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
+ * prints with the component and function names.
  *
- * The list of available log components can be printed on stdout
- * with the NS_LOG=print-list syntax.
  */
 
 /**
@@ -87,6 +88,19 @@
 
 #ifdef NS3_LOG_ENABLE
 
+/**
+ * \param level the log level
+ * \param msg the message to log
+ *
+ * This macro allows you to log an arbitrary message at a specific
+ * log level. The log message is expected to be a C++ ostream
+ * message such as "my string" << aNumber << "my oth stream".
+ *
+ * Typical usage looks like:
+ * \code
+ * NS_LOG (LOG_DEBUG, "a number="<<aNumber<<", anotherNumber="<<anotherNumber);
+ * \endcode
+ */
 #define NS_LOG(level, msg)                                      \
   do                                                            \
     {                                                           \
@@ -108,7 +122,7 @@
       if (g_log.IsEnabled (level))                              \
         {                                                       \
           std::clog << g_log.Name () << ":" << __FUNCTION__ <<  \
-            "(): " << std::endl;                                \
+            "()" << std::endl;                                \
         }                                                       \
     }                                                           \
   while (false)
@@ -187,7 +201,7 @@
   LOG_ALL            = 0x7fffffff, // print everything
   LOG_LEVEL_ALL      = LOG_ALL,
 
-  LOG_PREFIX_ALL     = 0x80000000
+  LOG_PREFIX_ALL     = 0x80000000  // prefix all trace prints with function
 };
 
 #endif
@@ -196,7 +210,6 @@
 /**
  * \param name a log component name
  * \param level a logging level
- * \param decorate whether or not to add function names to all logs
  * \ingroup logging
  *
  * Enable the logging output associated with that log component.
@@ -204,9 +217,9 @@
  * to ns3::LogComponentDisable.
  */
   void LogComponentEnable (char const *name, enum LogLevel level);
+
 /**
  * \param level a logging level
- * \param decorate whether or not to add function names to all logs
  * \ingroup logging
  *
  * Enable the logging output for all registered log components.
@@ -230,13 +243,10 @@
 void LogComponentDisable (char const *name, enum LogLevel level);
 
 /**
- * \param name a log component name
  * \param level a logging level
  * \ingroup logging
  *
- * Disable the logging output associated with that log component.
- * The logging output can be later re-enabled with a call
- * to ns3::LogComponentEnable.
+ * Disable all logging for all components.
  */
 void LogComponentDisableAll (enum LogLevel level);
 
@@ -249,11 +259,6 @@
  * \ingroup logging
  *
  * Print the list of logging messages available.
- * The output of this function can be obtained by setting
- * the NS_LOG environment variable to the special value 
- * 'print-list'.
- * 
- * For example: NS_LOG=print-list
  */
 #ifdef NS3_LOG_ENABLE
 void LogComponentPrintList (void);
@@ -266,6 +271,7 @@
 class LogComponent {
 public:
   LogComponent (char const *name);
+  void EnvVarCheck (char const *name);
   bool IsEnabled (enum LogLevel level) const;
   bool IsNoneEnabled (void) const;
   void Enable (enum LogLevel level);
--- a/src/core/random-variable.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/random-variable.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -42,7 +42,6 @@
 //-----------------------------------------------------------------------------
 // RandomVariable methods
 
-uint32_t      RandomVariable::runNumber = 0;
 bool          RandomVariable::initialized = false;   // True if RngStream seed set 
 bool          RandomVariable::useDevRandom = false;  // True if use /dev/random
 bool          RandomVariable::globalSeedSet = false; // True if GlobalSeed called
@@ -50,6 +49,7 @@
 uint32_t      RandomVariable::globalSeed[6];
 unsigned long RandomVariable::heuristic_sequence;
 RngStream*    RandomVariable::m_static_generator = 0;
+uint32_t      RandomVariable::runNumber = 0;
 
 //the static object random_variable_initializer initializes the static members
 //of RandomVariable
@@ -58,9 +58,9 @@
   public:
   RandomVariableInitializer()
   {
-    RandomVariable::Initialize(); // sets the static package seed
-    RandomVariable::m_static_generator = new RngStream();
-    RandomVariable::m_static_generator->InitializeStream();
+//     RandomVariable::Initialize(); // sets the static package seed
+//     RandomVariable::m_static_generator = new RngStream();
+//     RandomVariable::m_static_generator->InitializeStream();
   }
   ~RandomVariableInitializer()
   {
@@ -69,15 +69,20 @@
 } random_variable_initializer;
 
 RandomVariable::RandomVariable() 
+  : m_generator(NULL)
 {
-  m_generator = new RngStream();
-  m_generator->InitializeStream();
-  m_generator->ResetNthSubstream(RandomVariable::runNumber);
+//   m_generator = new RngStream();
+//   m_generator->InitializeStream();
+//   m_generator->ResetNthSubstream(RandomVariable::runNumber);
 }
 
 RandomVariable::RandomVariable(const RandomVariable& r)
+  :m_generator(0)
 {
-  m_generator = new RngStream(*r.m_generator);
+  if(r.m_generator)
+  {
+    m_generator = new RngStream(*r.m_generator);
+  }
 }
 
 RandomVariable::~RandomVariable()
@@ -97,6 +102,12 @@
 
 void RandomVariable::GetSeed(uint32_t seed[6])
 {
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   m_generator->GetState(seed);
 }
 
@@ -202,6 +213,16 @@
 
 double UniformVariable::GetValue()
 {
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   return m_min + m_generator->RandU01() * (m_max - m_min);
 }
 
@@ -212,6 +233,12 @@
 
 double UniformVariable::GetSingleValue(double s, double l)
 {
+  if(!RandomVariable::m_static_generator)
+  {
+    RandomVariable::Initialize(); // sets the static package seed
+    RandomVariable::m_static_generator = new RngStream();
+    RandomVariable::m_static_generator->InitializeStream();
+  }
   return s + m_static_generator->RandU01() * (l - s);;
 }
 
@@ -305,6 +332,16 @@
 
 double ExponentialVariable::GetValue()
 {
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   double r = -m_mean*log(m_generator->RandU01());
   if (m_bound != 0 && r > m_bound) return m_bound;
   return r;
@@ -316,6 +353,12 @@
 }
 double ExponentialVariable::GetSingleValue(double m, double b/*=0*/)
 {
+  if(!RandomVariable::m_static_generator)
+  {
+    RandomVariable::Initialize(); // sets the static package seed
+    RandomVariable::m_static_generator = new RngStream();
+    RandomVariable::m_static_generator->InitializeStream();
+  }
   double r = -m*log(m_static_generator->RandU01());
   if (b != 0 && r > b) return b;
   return r;
@@ -341,6 +384,16 @@
 
 double ParetoVariable::GetValue()
 {
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   double scale = m_mean * ( m_shape - 1.0) / m_shape;
   double r = (scale * ( 1.0 / pow(m_generator->RandU01(), 1.0 / m_shape)));
   if (m_bound != 0 && r > m_bound) return m_bound;
@@ -354,6 +407,12 @@
 
 double ParetoVariable::GetSingleValue(double m, double s, double b/*=0*/)
 {
+  if(!RandomVariable::m_static_generator)
+  {
+    RandomVariable::Initialize(); // sets the static package seed
+    RandomVariable::m_static_generator = new RngStream();
+    RandomVariable::m_static_generator->InitializeStream();
+  }
   double scale = m * ( s - 1.0) / s;
   double r = (scale * ( 1.0 / pow(m_static_generator->RandU01(), 1.0 / s)));
   if (b != 0 && r > b) return b;
@@ -375,6 +434,16 @@
 
 double WeibullVariable::GetValue()
 {
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   double exponent = 1.0 / m_alpha;
   double r = m_mean * pow( -log(m_generator->RandU01()), exponent);
   if (m_bound != 0 && r > m_bound) return m_bound;
@@ -388,6 +457,12 @@
 
 double WeibullVariable::GetSingleValue(double m, double s, double b/*=0*/)
 {
+  if(!RandomVariable::m_static_generator)
+  {
+    RandomVariable::Initialize(); // sets the static package seed
+    RandomVariable::m_static_generator = new RngStream();
+    RandomVariable::m_static_generator->InitializeStream();
+  }
   double exponent = 1.0 / s;
   double r = m * pow( -log(m_static_generator->RandU01()), exponent);
   if (b != 0 && r > b) return b;
@@ -412,6 +487,16 @@
 
 double NormalVariable::GetValue()
 {
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   if (m_nextValid)
     { // use previously generated
       m_nextValid = false;
@@ -445,6 +530,12 @@
 
 double NormalVariable::GetSingleValue(double m, double v, double b)
 {
+  if(!RandomVariable::m_static_generator)
+  {
+    RandomVariable::Initialize(); // sets the static package seed
+    RandomVariable::m_static_generator = new RngStream();
+    RandomVariable::m_static_generator->InitializeStream();
+  }
   if (m_static_nextValid)
     { // use previously generated
       m_static_nextValid = false;
@@ -495,6 +586,16 @@
 double EmpiricalVariable::GetValue()
 { // Return a value from the empirical distribution
   // This code based (loosely) on code by Bruce Mah (Thanks Bruce!)
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   if (emp.size() == 0) return 0.0; // HuH? No empirical data
   if (!validated) Validate();      // Insure in non-decreasing
   double r = m_generator->RandU01();
@@ -642,6 +743,16 @@
 double
 LogNormalVariable::GetValue ()
 {
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   double u, v, r2, normal, z;
 
   do
@@ -665,6 +776,12 @@
 
 double LogNormalVariable::GetSingleValue (double mu, double sigma)
 {
+  if(!RandomVariable::m_static_generator)
+  {
+    RandomVariable::Initialize(); // sets the static package seed
+    RandomVariable::m_static_generator = new RngStream();
+    RandomVariable::m_static_generator->InitializeStream();
+  }
   double u, v, r2, normal, z;
   do
     {
@@ -698,6 +815,16 @@
 
 double TriangularVariable::GetValue()
 {
+  if(!RandomVariable::initialized)
+  {
+    RandomVariable::Initialize();
+  }
+  if(!m_generator)
+  {
+    m_generator = new RngStream();
+    m_generator->InitializeStream();
+    m_generator->ResetNthSubstream(RandomVariable::runNumber);
+  }
   double u = m_generator->RandU01();
   if(u <= (m_mode - m_min) / (m_max - m_min) )
     return m_min + sqrt(u * (m_max - m_min) * (m_mode - m_min) );
@@ -712,6 +839,12 @@
 
 double TriangularVariable::GetSingleValue(double s, double l, double mean)
 {
+  if(!RandomVariable::m_static_generator)
+  {
+    RandomVariable::Initialize(); // sets the static package seed
+    RandomVariable::m_static_generator = new RngStream();
+    RandomVariable::m_static_generator->InitializeStream();
+  }
   double mode = 3.0*mean-s-l;
   double u = m_static_generator->RandU01();
   if(u <= (mode - s) / (l - s) )
--- a/src/core/random-variable.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/random-variable.h	Thu Nov 08 16:58:24 2007 -0800
@@ -71,7 +71,7 @@
    * \brief Returns a random double from the underlying distribution
    * \return A floating point random value
    */
-  virtual double  GetValue() = 0;     
+  virtual double  GetValue() = 0;
 
   /**
    * \brief Returns a random integer integer from the underlying distribution
@@ -173,19 +173,19 @@
    */
   static void SetRunNumber(uint32_t n);
 private:
-  static void Initialize();    // Initialize  the RNG system
   static void GetRandomSeeds(uint32_t seeds[6]);
 private:
-  static bool initialized;     // True if package seed is set 
   static bool useDevRandom;    // True if using /dev/random desired
   static bool globalSeedSet;   // True if global seed has been specified
   static int  devRandom;       // File handle for /dev/random
   static uint32_t globalSeed[6]; // The global seed to use
-  static uint32_t runNumber;
   friend class RandomVariableInitializer;
 protected:
   static unsigned long heuristic_sequence;
   static RngStream* m_static_generator;
+  static uint32_t runNumber;
+  static void Initialize();    // Initialize  the RNG system
+  static bool initialized;     // True if package seed is set 
   RngStream* m_generator;  //underlying generator being wrapped
 };
 
--- a/src/core/wscript	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/core/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -29,7 +29,6 @@
     core = bld.create_ns3_module('core')
     core.source = [
         'callback-test.cc',
-        'debug.cc',
         'log.cc',
         'breakpoint.cc',
         'ptr.cc',
@@ -70,7 +69,6 @@
         'callback.h',
         'ptr.h',
         'object.h',
-        'debug.h',
         'log.h',
         'assert.h',
         'breakpoint.h',
--- a/src/devices/csma/csma-channel.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/csma/csma-channel.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -308,7 +308,7 @@
   return (m_deviceList.size());
 }
 
-Ptr<NetDevice>
+Ptr<CsmaNetDevice>
 CsmaChannel::GetDevice (uint32_t i) const
 {
   Ptr< CsmaNetDevice > netDevice;
@@ -371,4 +371,10 @@
   return m_state;
 }
 
+Ptr<NetDevice>
+CsmaChannel::DoGetDevice (uint32_t i) const
+{
+  return GetDevice (i);
+}
+
 } // namespace ns3
--- a/src/devices/csma/csma-channel.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/csma/csma-channel.h	Thu Nov 08 16:58:24 2007 -0800
@@ -258,12 +258,14 @@
    * \return Returns the pointer to the net device that is associated
    * with deviceId i.
    */
-  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+  Ptr<CsmaNetDevice> GetDevice (uint32_t i) const;
 
   virtual DataRate GetDataRate (void);
   virtual Time GetDelay (void);
 
 private:
+  virtual Ptr<NetDevice> DoGetDevice (uint32_t i) const;
+
   DataRate      m_bps;    /// Data rate of the channel
   Time          m_delay;  /// Delay of the channel.
 
--- a/src/devices/csma/csma-ipv4-topology.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/csma/csma-ipv4-topology.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -96,7 +96,8 @@
   Ptr<Node>             node,
   uint32_t              netDeviceNumber,
   const Ipv4Address     address,
-  const Ipv4Mask        mask)
+  const Ipv4Mask        mask,
+  uint16_t              metric)
 {
   Ptr<NetDevice> nd = node->GetDevice(netDeviceNumber);
 
@@ -105,6 +106,7 @@
 
   ipv4->SetAddress (ifIndex, address);
   ipv4->SetNetworkMask (ifIndex, mask);
+  ipv4->SetMetric (ifIndex, metric);
   ipv4->SetUp (ifIndex);
   return ifIndex;
 }
--- a/src/devices/csma/csma-ipv4-topology.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/csma/csma-ipv4-topology.h	Thu Nov 08 16:58:24 2007 -0800
@@ -49,8 +49,8 @@
 public:
 
   /**
-   * \param n1 Node to be attached to the Csma channel
-   * \param ch CsmaChannel to which node n1 should be attached
+   * \param node Node to be attached to the Csma channel
+   * \param channel CsmaChannel to which node n1 should be attached
    * \param addr Mac address of the node
    *
    * Add a Csma node to a Csma channel. This function adds
@@ -102,7 +102,8 @@
    * \param netDeviceNumber The NetDevice index number with which to associate
    *        the address.
    * \param address The Ipv4 Address for the interface.
-   * \param network The network mask for the interface
+   * \param mask The network mask for the interface
+   * \param metric (optional) metric (cost) to assign for routing calculations
    * 
    * Add an Ipv4Address to the Ipv4 interface associated with the
    * ndNum CsmaIpv4NetDevices on the provided CsmaIpv4Channel
@@ -110,7 +111,8 @@
   static uint32_t AddIpv4Address(Ptr<Node> node,
                                  uint32_t netDeviceNumber, 
                                  const Ipv4Address address,
-                                 const Ipv4Mask mask);
+                                 const Ipv4Mask mask,
+                                 uint16_t metric = 1);
 
   /**
    * \param nd1 Node
--- a/src/devices/point-to-point/point-to-point-channel.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/point-to-point/point-to-point-channel.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -123,7 +123,7 @@
   return m_nDevices;
 }
 
-Ptr<NetDevice>
+Ptr<PointToPointNetDevice>
 PointToPointChannel::GetDevice (uint32_t i) const
 {
   NS_LOG_FUNCTION;
@@ -145,5 +145,12 @@
   return m_delay;
 }
 
+Ptr<NetDevice>
+PointToPointChannel::DoGetDevice (uint32_t i) const
+{
+  NS_LOG_FUNCTION;
+  return GetDevice (i);
+}
+
 
 } // namespace ns3
--- a/src/devices/point-to-point/point-to-point-channel.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/point-to-point/point-to-point-channel.h	Thu Nov 08 16:58:24 2007 -0800
@@ -51,8 +51,6 @@
  */
 class PointToPointChannel : public Channel {
 public:
-// Each point to point link has exactly two net devices
-  static const int N_DEVICES = 2;
   /**
    * \brief Create a PointToPointChannel
    *
@@ -84,20 +82,44 @@
    * \param device pointer to the netdevice to attach to the channel
    */
   void Attach (Ptr<PointToPointNetDevice> device);
+
+  /**
+   * \brief Attach a given netdevice to this channel
+   * \param p Packet to transmit
+   * \param src Source PointToPointNetDevice
+   * \param txTime Transmit time to apply
+   */
   bool TransmitStart (Packet& p, Ptr<PointToPointNetDevice> src,
                       const Time& txTime);
-  // Below two not needed
-  //bool TransmitEnd (Packet &p, Ptr<PointToPointNetDevice> src);
-  //void PropagationCompleteEvent(Packet p, Ptr<PointToPointNetDevice> src);
-
-
+  /**
+   * \brief Get number of devices on this channel
+   * \returns number of devices on this channel
+   */
   virtual uint32_t GetNDevices (void) const;
-  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
-
-  virtual const DataRate& GetDataRate (void);
-  virtual const Time&     GetDelay (void);
+  /*
+   * \brief Get PointToPointNetDevice corresponding to index i on this channel
+   * \param i Index number of the device requested
+   * \returns Ptr to PointToPointNetDevice requested
+   */
+  Ptr<PointToPointNetDevice> GetDevice (uint32_t i) const;
+  /*
+   * \brief Get reference to DataRate for this channel
+   * \returns const reference to underlying DataRate object
+   */
+  const DataRate& GetDataRate (void);
+  /*
+   * \brief Get reference to Time object storing the delay on this channel
+   * \returns const reference to underlying Time object
+   */
+  const Time&     GetDelay (void);
 
 private:
+
+  // Each point to point link has exactly two net devices
+  static const int N_DEVICES = 2;
+
+  virtual Ptr<NetDevice> DoGetDevice (uint32_t i) const;
+
   DataRate      m_bps;
   Time          m_delay;
   int32_t       m_nDevices;
--- a/src/devices/point-to-point/point-to-point-net-device.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Thu Nov 08 16:58:24 2007 -0800
@@ -54,24 +54,13 @@
  * \class PointToPointNetDevice
  * \brief A Device for a Point to Point Network Link.
  *
- * Ns-3 takes a four-layer view of a protocol stack.  This is the same model
- * that TCP uses.  In this view, layers 5-7 of the OSI reference model are
- * grouped together into an application layer; layer four (transport / TCP) is
- * broken out; layer three (network / IP) is broken out; and layers 1-2 are
- * grouped together.  We call this grouping of layers one and two a NetDevice
- * and represent it as a class in the system.
- *
- * The NetDevice class is specialized according to the needs of the specific
- * kind of network link.  In this case, the link is a PointToPoint link.  The
- * PointToPoint link is a family of classes that includes this class, the
- * PointToPointNetDevice, a PointToPointChannel class that represents the 
- * actual medium across which bits are sent, a PointToPointIpv4Interface class
- * that provides the hook to tie a general purpose node to this specific
- * link, and finally, a PointToPointTopology object that is responsible for
- * putting all of the pieces together.
- *
- * This is the PointToPointNetDevice class that represents, essentially, the
- * PC card that is used to connect to the PointToPoint network.
+ * This PointToPointNetDevice class specializes the NetDevice abstract
+ * base class.  Together with a PointToPointChannel (and a peer 
+ * PointToPointNetDevice), the class models, with some level of 
+ * abstraction, a generic point-to-point or serial link.  
+ * Key parameters or objects that can be specified for this device 
+ * include a queue, data rate, and interframe transmission gap (the 
+ * propagation delay is set in the PointToPointChannel).
  */
 class PointToPointNetDevice : public NetDevice {
 public:
@@ -79,20 +68,21 @@
    * Construct a PointToPointNetDevice
    *
    * This is the constructor for the PointToPointNetDevice.  It takes as a
-   * parameter the Node to which this device is connected.  Ownership of the
-   * Node pointer is not implied and the node must not be deleded.
+   * parameter a pointer to the Node to which this device is connected, 
+   * as well as an optional DataRate object.
    *
    * @see PointToPointTopology::AddPointToPointLink ()
    * @param node the Node to which this device is connected.
+   * @param rate (optional) DataRate object
    */
   PointToPointNetDevice (Ptr<Node> node,
-                         const DataRate& = g_defaultRate.GetValue());
+                         const DataRate& rate = g_defaultRate.GetValue());
   /**
    * Destroy a PointToPointNetDevice
    *
    * This is the destructor for the PointToPointNetDevice.
    */
-  virtual ~PointToPointNetDevice();
+  virtual ~PointToPointNetDevice ();
   /**
    * Set the Data Rate used for transmission of packets.  The data rate is
    * set in the Attach () method from the corresponding field in the channel
@@ -101,7 +91,7 @@
    * @see Attach ()
    * @param bps the data rate at which this object operates
    */
-  void SetDataRate(const DataRate& bps);
+  void SetDataRate (const DataRate& bps);
   /**
    * Set the inteframe gap used to separate packets.  The interframe gap
    * defines the minimum space required between packets sent by this device.
@@ -112,7 +102,7 @@
    * @see Attach ()
    * @param t the interframe gap time
    */
-  void SetInterframeGap(const Time& t);
+  void SetInterframeGap (const Time& t);
   /**
    * Attach the device to a channel.
    *
@@ -127,7 +117,7 @@
    * @see SetInterframeGap ()
    * @param ch a pointer to the channel to which this object is being attached.
    */
-  bool Attach(Ptr<PointToPointChannel> ch);
+  bool Attach (Ptr<PointToPointChannel> ch);
   /**
    * Attach a queue to the PointToPointNetDevice.
    *
@@ -142,7 +132,7 @@
    * @param queue a pointer to the queue for which object is assuming
    *        ownership.
    */
-  void AddQueue(Ptr<Queue> queue);
+  void AddQueue (Ptr<Queue> queue);
   /**
    * Receive a packet from a connected PointToPointChannel.
    *
@@ -155,13 +145,15 @@
    * @param p a reference to the received packet
    */
   void Receive (Packet& p);
-protected:
+
+private:
   /**
    * Create a Trace Resolver for events in the net device.
    *
    * @see class TraceResolver
    */
   virtual Ptr<TraceResolver> GetTraceResolver (void) const;
+
   virtual void DoDispose (void);
   /**
    * Get a copy of the attached Queue.
@@ -173,6 +165,7 @@
    * @returns a pointer to the queue.
    */
   Ptr<Queue> GetQueue(void) const; 
+
   /**
    * Get a copy of the attached Channel
    *
@@ -183,6 +176,7 @@
    * @returns a pointer to the channel
    */
   virtual Ptr<Channel> DoGetChannel(void) const;
+
   /**
    * Set a new default data rate
    */
@@ -192,7 +186,6 @@
    * Get the current default rate.
    * @returns a const reference to current default
    */
-
   static const DataRate& GetDefaultRate();
 
 private:
--- a/src/devices/point-to-point/point-to-point-topology.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/point-to-point/point-to-point-topology.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -104,6 +104,59 @@
 }
 
 void
+PointToPointTopology::SetIpv4Metric(
+  Ptr<const PointToPointChannel> chan,
+  Ptr<Node> n1, Ptr<Node> n2, const uint16_t metric)
+{
+
+  // The PointToPoint channel is used to find the relevant NetDevices
+  NS_ASSERT (chan->GetNDevices () == 2);
+  Ptr<NetDevice> nd1 = chan->GetDevice (0);
+  Ptr<NetDevice> nd2 = chan->GetDevice (1);
+  // Make sure that nd1 belongs to n1 and nd2 to n2
+  if ( (nd1->GetNode ()->GetId () == n2->GetId () ) && 
+       (nd2->GetNode ()->GetId () == n1->GetId () ) )
+    {
+      std::swap(nd1, nd2);
+    }
+  NS_ASSERT (nd1->GetNode ()->GetId () == n1->GetId ());
+  NS_ASSERT (nd2->GetNode ()->GetId () == n2->GetId ());
+  
+  // The NetDevice ifIndex does not correspond to the
+  // ifIndex used by Ipv4.  Therefore, we have to iterate
+  // through the NetDevices until we find the Ipv4 ifIndex
+  // that corresponds to NetDevice nd1
+  // Get interface indexes for both nodes corresponding to the right channel
+  uint32_t index = 0;
+  bool found = false;
+  Ptr<Ipv4> ip1 = n1->QueryInterface<Ipv4> (Ipv4::iid);
+  for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++)
+    {
+      if (ip1 ->GetNetDevice (i) == nd1)
+        {
+          index = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+  ip1->SetMetric (index, metric);
+
+  index = 0;
+  found = false;
+  Ptr<Ipv4> ip2 = n2->QueryInterface<Ipv4> (Ipv4::iid);
+  for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++)
+    {
+      if (ip2 ->GetNetDevice (i) == nd2)
+        {
+          index = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+  ip2->SetMetric (index, metric);
+}
+
+void
 PointToPointTopology::AddIpv4Routes (
   Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> chan)
 { 
--- a/src/devices/point-to-point/point-to-point-topology.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/devices/point-to-point/point-to-point-topology.h	Thu Nov 08 16:58:24 2007 -0800
@@ -70,6 +70,20 @@
     Ptr<Node> n1, const Ipv4Address& addr1,
     Ptr<Node> n2, const Ipv4Address& addr2);
 
+  /** 
+   * \param chan PointToPointChannel to use
+   * \param n1 Node
+   * \param n2 Node
+   * \param metric link metric to assign on Ipv4Link on chan between n1 and n2
+   * 
+   * Add a non-unit-cost link metric (bidirectionally) to the Ipv4 
+   * interfaces associated with the two PointToPointNetDevices on the 
+   * provided PointToPointChannel
+   */
+  static void SetIpv4Metric(
+    Ptr<const PointToPointChannel> chan,
+    Ptr<Node> n1, Ptr<Node> n2, const uint16_t metric);
+
   /**
    * \param channel PointToPointChannel to use
    * \param n1 Node
--- a/src/internet-node/ipv4-impl.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/ipv4-impl.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -201,6 +201,18 @@
   return m_ipv4->GetAddress (i);
 }
 
+void
+Ipv4Impl::SetMetric (uint32_t i, uint16_t metric) 
+{
+  m_ipv4->SetMetric (i, metric);
+}
+
+uint16_t
+Ipv4Impl::GetMetric (uint32_t i) const
+{
+  return m_ipv4->GetMetric (i);
+}
+
 bool
 Ipv4Impl::GetIfIndexForDestination (Ipv4Address dest, uint32_t &ifIndex) const
 {
--- a/src/internet-node/ipv4-impl.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/ipv4-impl.h	Thu Nov 08 16:58:24 2007 -0800
@@ -88,6 +88,8 @@
   virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask);
   virtual Ipv4Mask GetNetworkMask (uint32_t t) const;
   virtual Ipv4Address GetAddress (uint32_t i) const;
+  virtual void SetMetric (uint32_t i, uint16_t metric);
+  virtual uint16_t GetMetric (uint32_t i) const;
   virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const;
   virtual bool GetIfIndexForDestination (Ipv4Address dest, 
     uint32_t &ifIndex) const;
--- a/src/internet-node/ipv4-interface.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/ipv4-interface.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -37,7 +37,8 @@
    */
 Ipv4Interface::Ipv4Interface (Ptr<NetDevice> nd) 
   : m_netdevice (nd), 
-    m_ifup(false)
+    m_ifup(false),
+    m_metric(1)
 {
   NS_LOG_FUNCTION;
   NS_LOG_PARAM ("(" << &nd << ")");
@@ -96,6 +97,21 @@
   return m_netmask;
 }
 
+void
+Ipv4Interface::SetMetric (uint16_t metric)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAM ("(" << metric << ")");
+  m_metric = metric;
+}
+
+uint16_t
+Ipv4Interface::GetMetric (void) const
+{
+  NS_LOG_FUNCTION;
+  return m_metric;
+}
+
 Ipv4Address 
 Ipv4Interface::GetAddress (void) const
 {
--- a/src/internet-node/ipv4-interface.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/ipv4-interface.h	Thu Nov 08 16:58:24 2007 -0800
@@ -97,6 +97,14 @@
    */
   Ipv4Mask GetNetworkMask (void) const;
   /**
+   * \param metric configured routing metric (cost) of this interface
+   */
+  void SetMetric (uint16_t metric);
+  /**
+   * \returns configured routing metric (cost) of this interface
+   */
+  uint16_t GetMetric (void) const;
+  /**
    * \returns the ipv4 address of this interface
    */
   Ipv4Address GetAddress (void) const;
@@ -147,6 +155,7 @@
   bool m_ifup;
   Ipv4Address m_address;
   Ipv4Mask m_netmask;
+  uint16_t m_metric;
 };
 
 }; // namespace ns3
--- a/src/internet-node/ipv4-l3-protocol.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -821,6 +821,24 @@
   return interface->GetAddress ();
 }
 
+void 
+Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAM ("(" << i << ", " << metric << ")");
+  Ptr<Ipv4Interface> interface = GetInterface (i);
+  interface->SetMetric (metric);
+}
+
+uint16_t
+Ipv4L3Protocol::GetMetric (uint32_t i) const
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_PARAM ("(" << i << ")");
+  Ptr<Ipv4Interface> interface = GetInterface (i);
+  return interface->GetMetric ();
+}
+
 bool
 Ipv4L3Protocol::GetIfIndexForDestination (
   Ipv4Address destination, uint32_t& ifIndex) const
--- a/src/internet-node/ipv4-l3-protocol.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/ipv4-l3-protocol.h	Thu Nov 08 16:58:24 2007 -0800
@@ -198,6 +198,8 @@
   void SetNetworkMask (uint32_t i, Ipv4Mask mask);
   Ipv4Mask GetNetworkMask (uint32_t t) const;
   Ipv4Address GetAddress (uint32_t i) const;
+  void SetMetric (uint32_t i, uint16_t metric);
+  uint16_t GetMetric (uint32_t i) const;
   bool GetIfIndexForDestination (Ipv4Address destination, 
                                  uint32_t& ifIndex) const;
   uint16_t GetMtu (uint32_t i) const;
--- a/src/internet-node/ipv4-static-routing.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/ipv4-static-routing.h	Thu Nov 08 16:58:24 2007 -0800
@@ -209,7 +209,7 @@
  * @brief Add a network route to the static routing table.
  *
  * @param network The Ipv4Address network for this route.
- * @param networkmask The Ipv4Mask to extract the network.
+ * @param networkMask The Ipv4Mask to extract the network.
  * @param nextHop The next hop in the route to the destination network.
  * @param interface The network interface index used to send packets to the
  * destination.
@@ -225,7 +225,7 @@
  * @brief Add a network route to the static routing table.
  *
  * @param network The Ipv4Address network for this route.
- * @param networkmask The Ipv4Mask to extract the network.
+ * @param networkMask The Ipv4Mask to extract the network.
  * @param interface The network interface index used to send packets to the
  * destination.
  *
@@ -352,7 +352,7 @@
  * @param inputInterface The input network interface index over which to 
  * expect packets destined for this route.  May be
  * Ipv4RoutingProtocol::IF_INDEX_ANY for packets of local origin.
- * @param outputInterface A vector of network interface indices used to specify
+ * @param outputInterfaces A vector of network interface indices used to specify
  * how to send packets to the destination(s).
  *
  * @see Ipv4Address
@@ -411,7 +411,7 @@
  *
  * @param i The index (into the routing table) of the multicast route to
  * retrieve.  If the default route has been set, it will occupy index zero.
- * @return If route <i> is set, a pointer to that Ipv4MulticastRoute is
+ * @return If route \e i is set, a pointer to that Ipv4MulticastRoute is
  * returned, otherwise a zero pointer is returned.
  *
  * @see Ipv4MulticastRoute
@@ -449,11 +449,11 @@
  *
  * @param origin The IP address specified as the origin of packets for the
  * route.
- * @param origin The IP address specified as the multicast group addres of
+ * @param group The IP address specified as the multicast group addres of
  * the route.
- * @param inputInterfade The network interface index specified as the expected
+ * @param inputInterface The network interface index specified as the expected
  * input interface for the route.
- * @returns True if a route was found and removed, false otherwise.
+ * @returns true if a route was found and removed, false otherwise.
  *
  * @see Ipv4MulticastRoute
  * @see Ipv4StaticRouting::AddMulticastRoute
--- a/src/internet-node/udp-l4-protocol.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/udp-l4-protocol.h	Thu Nov 08 16:58:24 2007 -0800
@@ -77,10 +77,11 @@
              Ipv4Address saddr, Ipv4Address daddr, 
              uint16_t sport, uint16_t dport);
   /**
-   * \brief Recieve a packet up the protocol stack
+   * \brief Receive a packet up the protocol stack
    * \param p The Packet to dump the contents into
    * \param source The source's Ipv4Address
    * \param destination The destinations Ipv4Address
+   * \param interface the interface from which the packet is coming.
    */
   // inherited from Ipv4L4Protocol
   virtual void Receive(Packet& p, 
--- a/src/internet-node/udp-socket.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/internet-node/udp-socket.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -452,6 +452,8 @@
   NS_TEST_ASSERT_EQUAL (m_receivedPacket.GetSize (), 123);
   NS_TEST_ASSERT_EQUAL (m_receivedPacket2.GetSize (), 123);
 
+  Simulator::Destroy ();
+
   return result;
 }
 
--- a/src/mobility/grid-topology.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/grid-topology.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -46,7 +46,7 @@
   Ptr<MobilityModel> mobility = ComponentManager::Create<MobilityModel> (m_positionClassId,
                                                                          MobilityModel::iid);
   object->AddInterface (mobility);
-  mobility->Set (Position (x, y, 0.0));
+  mobility->SetPosition (Vector (x, y, 0.0));
 }
 
 void 
@@ -58,7 +58,7 @@
   Ptr<MobilityModel> mobility = ComponentManager::Create<MobilityModel> (m_positionClassId, 
                                                                          MobilityModel::iid);
   object->AddInterface (mobility);
-  mobility->Set (Position (x, y, 0.0));
+  mobility->SetPosition (Vector (x, y, 0.0));
 }
 
 
--- a/src/mobility/grid-topology.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/grid-topology.h	Thu Nov 08 16:58:24 2007 -0800
@@ -97,8 +97,8 @@
   uint32_t j = 0;
   for (T i = begin; i != end; i++)
     {
+      LayoutOneRowFirst (*i, j);
       j++;
-      LayoutOneRowFirst (*i, j);
     }  
 }
 
@@ -109,8 +109,8 @@
   uint32_t j = 0;
   for (T i = begin; i != end; i++)
     {
+      LayoutOneColumnFirst (*i, j);
       j++;
-      LayoutOneColumnFirst (*i, j);
     }
 }
 
--- a/src/mobility/hierarchical-mobility-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/hierarchical-mobility-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -56,34 +56,34 @@
   return m_parent;
 }
 
-Position 
-HierarchicalMobilityModel::DoGet (void) const
+Vector
+HierarchicalMobilityModel::DoGetPosition (void) const
 {
-  Position parentPosition = m_parent->Get ();
-  Position childPosition = m_child->Get ();
-  return Position (parentPosition.x + childPosition.x,
+  Vector parentPosition = m_parent->GetPosition ();
+  Vector childPosition = m_child->GetPosition ();
+  return Vector (parentPosition.x + childPosition.x,
 		   parentPosition.y + childPosition.y,
 		   parentPosition.z + childPosition.z);
 }
 void 
-HierarchicalMobilityModel::DoSet (const Position &position)
+HierarchicalMobilityModel::DoSetPosition (const Vector &position)
 {
-  // This implementation of DoSet is really an arbitraty choice.
+  // This implementation of DoSetPosition is really an arbitraty choice.
   // anything else would have been ok.
-  Position parentPosition = m_parent->Get ();
-  Position childPosition (position.x - parentPosition.x,
+  Vector parentPosition = m_parent->GetPosition ();
+  Vector childPosition (position.x - parentPosition.x,
 			  position.y - parentPosition.y,
 			  position.z - parentPosition.z);
-  m_child->Set (childPosition);
+  m_child->SetPosition (childPosition);
 }
-Speed 
-HierarchicalMobilityModel::DoGetSpeed (void) const
+Vector
+HierarchicalMobilityModel::DoGetVelocity (void) const
 {
-  Speed parentSpeed = m_parent->GetSpeed ();
-  Speed childSpeed = m_child->GetSpeed ();
-  Speed speed (parentSpeed.dx + childSpeed.dx,
-               parentSpeed.dy + childSpeed.dy,
-               parentSpeed.dz + childSpeed.dz);
+  Vector parentSpeed = m_parent->GetVelocity ();
+  Vector childSpeed = m_child->GetVelocity ();
+  Vector speed (parentSpeed.x + childSpeed.x,
+               parentSpeed.y + childSpeed.y,
+               parentSpeed.z + childSpeed.z);
   return speed;
 }
 
--- a/src/mobility/hierarchical-mobility-model.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/hierarchical-mobility-model.h	Thu Nov 08 16:58:24 2007 -0800
@@ -58,9 +58,9 @@
   Ptr<MobilityModel> GetParent (void) const;
   
 private:
-  virtual Position DoGet (void) const;
-  virtual void DoSet (const Position &position);
-  virtual Speed DoGetSpeed (void) const;
+  virtual Vector DoGetPosition (void) const;
+  virtual void DoSetPosition (const Vector &position);
+  virtual Vector DoGetVelocity (void) const;
 
   void ParentChanged (const TraceContext &context, Ptr<const MobilityModel> model);
   void ChildChanged (const TraceContext &context, Ptr<const MobilityModel> model);
--- a/src/mobility/mobility-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/mobility-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -33,28 +33,28 @@
 MobilityModel::~MobilityModel ()
 {}
 
-Position
-MobilityModel::Get (void) const
+Vector
+MobilityModel::GetPosition (void) const
 {
-  return DoGet ();
+  return DoGetPosition ();
 }
-Speed 
-MobilityModel::GetSpeed (void) const
+Vector
+MobilityModel::GetVelocity (void) const
 {
-  return DoGetSpeed ();
+  return DoGetVelocity ();
 }
 
 void 
-MobilityModel::Set (const Position &position)
+MobilityModel::SetPosition (const Vector &position)
 {
-  DoSet (position);
+  DoSetPosition (position);
 }
 
 double 
 MobilityModel::GetDistanceFrom (Ptr<const MobilityModel> other) const
 {
-  Position oPosition = other->DoGet ();
-  Position position = DoGet ();
+  Vector oPosition = other->DoGetPosition ();
+  Vector position = DoGetPosition ();
   return CalculateDistance (position, oPosition);
 }
 
--- a/src/mobility/mobility-model.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/mobility-model.h	Thu Nov 08 16:58:24 2007 -0800
@@ -21,8 +21,7 @@
 #define MOBILITY_MODEL_H
 
 #include "ns3/object.h"
-#include "position.h"
-#include "speed.h"
+#include "vector.h"
 
 namespace ns3 {
 
@@ -43,15 +42,15 @@
   /**
    * \returns the current position
    */
-  Position Get (void) const;
+  Vector GetPosition (void) const;
   /**
    * \param position the position to set.
    */
-  void Set (const Position &position);
+  void SetPosition (const Vector &position);
   /**
-   * \returns the current position.
+   * \returns the current velocity.
    */
-  Speed GetSpeed (void) const;
+  Vector GetVelocity (void) const;
   /**
    * \param position a reference to another mobility model
    * \returns the distance between the two objects. Unit is meters.
@@ -70,21 +69,21 @@
    * Concrete subclasses of this base class must 
    * implement this method.
    */
-  virtual Position DoGet (void) const = 0;
+  virtual Vector DoGetPosition (void) const = 0;
   /**
    * \param position the position to set.
    *
    * Concrete subclasses of this base class must 
    * implement this method.
    */
-  virtual void DoSet (const Position &position) = 0;
+  virtual void DoSetPosition (const Vector &position) = 0;
   /**
-   * \returns the current speed.
+   * \returns the current velocity.
    *
    * Concrete subclasses of this base class must 
    * implement this method.
    */
-  virtual Speed DoGetSpeed (void) const = 0;
+  virtual Vector DoGetVelocity (void) const = 0;
 };
 
 }; // namespace ns3
--- a/src/mobility/ns2-mobility-file-topology.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/ns2-mobility-file-topology.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -20,14 +20,14 @@
  */
 #include <fstream>
 #include <sstream>
-#include "ns3/debug.h"
+#include "ns3/log.h"
 #include "ns3/simulator.h"
 #include "ns3/node-list.h"
 #include "ns3/node.h"
 #include "ns2-mobility-file-topology.h"
 #include "static-speed-mobility-model.h"
 
-NS_DEBUG_COMPONENT_DEFINE ("Ns2MobilityFileTopology");
+NS_LOG_COMPONENT_DEFINE ("Ns2MobilityFileTopology");
 
 namespace ns3 {
 
@@ -97,27 +97,27 @@
 	    {
 	      double value = ReadDouble (line.substr (endNodeId + 9, std::string::npos));
 	      std::string coordinate = line.substr (endNodeId + 6, 1);
-              Position position = model->Get ();
+              Vector position = model->GetPosition ();
 	      if (coordinate == "X")
 		{
                   position.x = value;
-		  NS_DEBUG ("X=" << value);
+		  NS_LOG_DEBUG ("X=" << value);
 		}
 	      else if (coordinate == "Y")
 		{
                   position.y = value;
-		  NS_DEBUG ("Y=" << value);
+		  NS_LOG_DEBUG ("Y=" << value);
 		}
 	      else if (coordinate == "Z")
 		{
                   position.z = value;
-		  NS_DEBUG ("Z=" << value);
+		  NS_LOG_DEBUG ("Z=" << value);
 		}
               else
                 {
                   continue;
                 }
-              model->Set (position);
+              model->SetPosition (position);
 	    }
 	  else 
 	    {
@@ -127,9 +127,9 @@
 	      double xSpeed = ReadDouble (line.substr (endNodeId + 10, xSpeedEnd - endNodeId - 10));
 	      double ySpeed = ReadDouble (line.substr (xSpeedEnd + 1, ySpeedEnd - xSpeedEnd - 1));
 	      double zSpeed = ReadDouble (line.substr (ySpeedEnd + 1, std::string::npos));
-	      NS_DEBUG ("at=" << at << "xSpeed=" << xSpeed << ", ySpeed=" << ySpeed << ", zSpeed=" << zSpeed);
+	      NS_LOG_DEBUG ("at=" << at << "xSpeed=" << xSpeed << ", ySpeed=" << ySpeed << ", zSpeed=" << zSpeed);
 	      Simulator::Schedule (Seconds (at), &StaticSpeedMobilityModel::SetSpeed, model,
-				   Speed (xSpeed, ySpeed, zSpeed));
+				   Vector (xSpeed, ySpeed, zSpeed));
 	    }
 	}
       file.close();
--- a/src/mobility/position.cc	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "position.h"
-#include <cmath>
-
-namespace ns3 {
-
-
-Position::Position (double _x, double _y, double _z)
-  : x (_x),
-    y (_y),
-    z (_z)
-{}
-
-Position::Position ()
-  : x (0.0),
-    y (0.0),
-    z (0.0)
-{}
-
-double 
-CalculateDistance (const Position &a, const Position &b)
-{
-  double dx = b.x - a.x;
-  double dy = b.y - a.y;
-  double dz = b.z - a.z;
-  double distance = std::sqrt (dx * dx + dy * dy + dz * dz);
-  return distance;
-}
-
-} // namespace ns3
--- a/src/mobility/position.h	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef POSITION_H
-#define POSITION_H
-
-namespace ns3 {
-
-/**
- * \brief a 3d cartesian position vector
- *
- * Unit is meters.
- */
-class Position
-{
-public:
-  /**
-   * \param _x x coordinate of position vector
-   * \param _y y coordinate of position vector
-   * \param _z z coordinate of position vector
-   *
-   * Create position vector (_x, _y, _z)
-   */
-  Position (double _x, double _y, double _z);
-  /**
-   * Create position vector (0.0, 0.0, 0.0)
-   */
-  Position ();
-  /**
-   * x coordinate of position vector
-   */
-  double x;
-  /**
-   * y coordinate of position vector
-   */
-  double y;
-  /**
-   * z coordinate of position vector
-   */
-  double z;
-};
-
-double CalculateDistance (const Position &a, const Position &b);
-
-} // namespace ns3
-
-#endif /* POSITION_H */
--- a/src/mobility/random-direction-2d-mobility-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-direction-2d-mobility-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -153,12 +153,12 @@
 {
   NS_LOG_FUNCTION;
   double speed = m_parameters->m_speedVariable->GetValue ();
-  const Speed vector (std::cos (direction) * speed,
-                      std::sin (direction) * speed,
-                      0.0);
-  Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+  const Vector vector (std::cos (direction) * speed,
+                       std::sin (direction) * speed,
+                       0.0);
+  Vector position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
   m_helper.Reset (vector);
-  Position next = m_parameters->m_bounds.CalculateIntersection (position, vector);
+  Vector next = m_parameters->m_bounds.CalculateIntersection (position, vector);
   Time delay = Seconds (CalculateDistance (position, next) / speed);
   m_event = Simulator::Schedule (delay,
 				 &RandomDirection2dMobilityModel::BeginPause, this);
@@ -169,7 +169,7 @@
 {
   double direction = UniformVariable::GetSingleValue (0, PI);
   
-  Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+  Vector position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
   switch (m_parameters->m_bounds.GetClosestSide (position))
     {
     case Rectangle::RIGHT:
@@ -187,22 +187,22 @@
     }
   SetDirectionAndSpeed (direction);
 }
-Position
-RandomDirection2dMobilityModel::DoGet (void) const
+Vector
+RandomDirection2dMobilityModel::DoGetPosition (void) const
 {
   return m_helper.GetCurrentPosition (m_parameters->m_bounds);
 }
 void
-RandomDirection2dMobilityModel::DoSet (const Position &position)
+RandomDirection2dMobilityModel::DoSetPosition (const Vector &position)
 {
   m_helper.InitializePosition (position);
   Simulator::Remove (m_event);
   m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
 }
-Speed 
-RandomDirection2dMobilityModel::DoGetSpeed (void) const
+Vector
+RandomDirection2dMobilityModel::DoGetVelocity (void) const
 {
-  return m_helper.GetSpeed ();
+  return m_helper.GetVelocity ();
 }
 
 
--- a/src/mobility/random-direction-2d-mobility-model.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-direction-2d-mobility-model.h	Thu Nov 08 16:58:24 2007 -0800
@@ -106,9 +106,9 @@
   void SetDirectionAndSpeed (double direction);
   void InitializeDirectionAndSpeed (void);
   virtual void DoDispose (void);
-  virtual Position DoGet (void) const;
-  virtual void DoSet (const Position &position);
-  virtual Speed DoGetSpeed (void) const;
+  virtual Vector DoGetPosition (void) const;
+  virtual void DoSetPosition (const Vector &position);
+  virtual Vector DoGetVelocity (void) const;
 
   static const double PI;
   Ptr<RandomDirection2dMobilityModelParameters> m_parameters;
--- a/src/mobility/random-position.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-position.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -91,12 +91,12 @@
   m_x = 0;
   m_y = 0;
 }
-Position
+Vector
 RandomRectanglePosition::Get (void) const
 {
   double x = m_x->GetValue ();
   double y = m_y->GetValue ();
-  return Position (x, y, 0.0);
+  return Vector (x, y, 0.0);
 }
 
 RandomDiscPosition::RandomDiscPosition ()
@@ -120,7 +120,7 @@
   m_theta = 0;
   m_rho = 0;
 }
-Position
+Vector
 RandomDiscPosition::Get (void) const
 {
   double theta = m_theta->GetValue ();
@@ -128,7 +128,7 @@
   double x = m_x + std::cos (theta) * rho;
   double y = m_y + std::sin (theta) * rho;
   NS_LOG_DEBUG ("Disc position x=" << x << ", y=" << y);
-  return Position (x, y, 0.0);
+  return Vector (x, y, 0.0);
 }
 
 
--- a/src/mobility/random-position.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-position.h	Thu Nov 08 16:58:24 2007 -0800
@@ -22,7 +22,7 @@
 
 #include "ns3/object.h"
 #include "ns3/component-manager.h"
-#include "position.h"
+#include "vector.h"
 
 namespace ns3 {
 
@@ -42,7 +42,7 @@
   /**
    * \returns the next randomly-choosen position.
    */
-  virtual Position Get (void) const = 0;
+  virtual Vector Get (void) const = 0;
 };
 
 /**
@@ -67,7 +67,7 @@
   RandomRectanglePosition (const RandomVariable &x,
 			   const RandomVariable &y);
   virtual ~RandomRectanglePosition ();
-  virtual Position Get (void) const;
+  virtual Vector Get (void) const;
 private:
   RandomVariable *m_x;
   RandomVariable *m_y;
@@ -102,7 +102,7 @@
 		      const RandomVariable &rho,
 		      double x, double y);
   virtual ~RandomDiscPosition ();
-  virtual Position Get (void) const;
+  virtual Vector Get (void) const;
 private:
   RandomVariable *m_theta;
   RandomVariable *m_rho;
--- a/src/mobility/random-topology.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-topology.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -70,8 +70,8 @@
   Ptr<MobilityModel> mobility = ComponentManager::Create<MobilityModel> (m_mobilityModel, 
                                                                          MobilityModel::iid);
   object->AddInterface (mobility);
-  Position position = m_positionModel->Get ();
-  mobility->Set (position);
+  Vector position = m_positionModel->Get ();
+  mobility->SetPosition (position);
 }
 
 
--- a/src/mobility/random-walk-2d-mobility-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-walk-2d-mobility-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -24,10 +24,10 @@
 #include "ns3/rectangle-default-value.h"
 #include "ns3/random-variable-default-value.h"
 #include "ns3/simulator.h"
-#include "ns3/debug.h"
+#include "ns3/log.h"
 #include <cmath>
 
-NS_DEBUG_COMPONENT_DEFINE ("RandomWalk2d");
+NS_LOG_COMPONENT_DEFINE ("RandomWalk2d");
 
 namespace ns3 {
 
@@ -143,9 +143,9 @@
 {
   double speed = m_parameters->m_speed->GetValue ();
   double direction = m_parameters->m_direction->GetValue ();
-  Speed vector (std::cos (direction) * speed,
-                std::sin (direction) * speed,
-                0.0);
+  Vector vector (std::cos (direction) * speed,
+                 std::sin (direction) * speed,
+                 0.0);
   m_helper.Reset (vector);
 
   Time delayLeft;
@@ -163,11 +163,11 @@
 void
 RandomWalk2dMobilityModel::DoWalk (Time delayLeft)
 {
-  Position position = m_helper.GetCurrentPosition ();
-  Speed speed = m_helper.GetSpeed ();
-  Position nextPosition = position;
-  nextPosition.x += speed.dx * delayLeft.GetSeconds ();
-  nextPosition.y += speed.dy * delayLeft.GetSeconds ();
+  Vector position = m_helper.GetCurrentPosition ();
+  Vector speed = m_helper.GetVelocity ();
+  Vector nextPosition = position;
+  nextPosition.x += speed.x * delayLeft.GetSeconds ();
+  nextPosition.y += speed.y * delayLeft.GetSeconds ();
   if (m_parameters->m_bounds.IsInside (nextPosition))
     {
       m_event = Simulator::Schedule (delayLeft, &RandomWalk2dMobilityModel::Start, this);
@@ -175,7 +175,7 @@
   else
     {
       nextPosition = m_parameters->m_bounds.CalculateIntersection (position, speed);
-      Time delay = Seconds ((nextPosition.x - position.x) / speed.dx);
+      Time delay = Seconds ((nextPosition.x - position.x) / speed.x);
       m_event = Simulator::Schedule (delay, &RandomWalk2dMobilityModel::Rebound, this,
                                      delayLeft - delay);      
     }  
@@ -185,17 +185,17 @@
 void
 RandomWalk2dMobilityModel::Rebound (Time delayLeft)
 {
-  Position position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
-  Speed speed = m_helper.GetSpeed ();
+  Vector position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+  Vector speed = m_helper.GetVelocity ();
   switch (m_parameters->m_bounds.GetClosestSide (position))
     {
     case Rectangle::RIGHT:
     case Rectangle::LEFT:
-      speed.dx = - speed.dx;
+      speed.x = - speed.x;
       break;
     case Rectangle::TOP:
     case Rectangle::BOTTOM:
-      speed.dy = - speed.dy;
+      speed.y = - speed.y;
       break;
     }
   m_helper.Reset (speed);
@@ -209,23 +209,23 @@
   // chain up
   MobilityModel::DoDispose ();
 }
-Position
-RandomWalk2dMobilityModel::DoGet (void) const
+Vector
+RandomWalk2dMobilityModel::DoGetPosition (void) const
 {
   return m_helper.GetCurrentPosition (m_parameters->m_bounds);
 }
 void
-RandomWalk2dMobilityModel::DoSet (const Position &position)
+RandomWalk2dMobilityModel::DoSetPosition (const Vector &position)
 {
   NS_ASSERT (m_parameters->m_bounds.IsInside (position));
   m_helper.InitializePosition (position);
   Simulator::Remove (m_event);
   m_event = Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this);
 }
-Speed 
-RandomWalk2dMobilityModel::DoGetSpeed (void) const
+Vector
+RandomWalk2dMobilityModel::DoGetVelocity (void) const
 {
-  return m_helper.GetSpeed ();
+  return m_helper.GetVelocity ();
 }
 
 
--- a/src/mobility/random-walk-2d-mobility-model.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-walk-2d-mobility-model.h	Thu Nov 08 16:58:24 2007 -0800
@@ -132,9 +132,9 @@
   void Rebound (Time timeLeft);
   void DoWalk (Time timeLeft);
   virtual void DoDispose (void);
-  virtual Position DoGet (void) const;
-  virtual void DoSet (const Position &position);
-  virtual Speed DoGetSpeed (void) const;
+  virtual Vector DoGetPosition (void) const;
+  virtual void DoSetPosition (const Vector &position);
+  virtual Vector DoGetVelocity (void) const;
 
   StaticSpeedHelper m_helper;
   EventId m_event;
--- a/src/mobility/random-waypoint-mobility-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-waypoint-mobility-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -117,15 +117,15 @@
 void
 RandomWaypointMobilityModel::BeginWalk (void)
 {
-  Position m_current = m_helper.GetCurrentPosition ();
-  Position destination = m_parameters->m_position->Get ();
+  Vector m_current = m_helper.GetCurrentPosition ();
+  Vector destination = m_parameters->m_position->Get ();
   double speed = m_parameters->m_speed->GetValue ();
   double dx = (destination.x - m_current.x);
   double dy = (destination.y - m_current.y);
   double dz = (destination.z - m_current.z);
   double k = speed / std::sqrt (dx*dx + dy*dy + dz*dz);
 
-  m_helper.Reset (Speed (k*dx, k*dy, k*dz));
+  m_helper.Reset (Vector (k*dx, k*dy, k*dz));
   Time travelDelay = Seconds (CalculateDistance (destination, m_current) / speed);
   m_event = Simulator::Schedule (travelDelay,
 				 &RandomWaypointMobilityModel::Start, this);
@@ -141,22 +141,22 @@
   m_event = Simulator::Schedule (pause, &RandomWaypointMobilityModel::BeginWalk, this);
 }
 
-Position 
-RandomWaypointMobilityModel::DoGet (void) const
+Vector
+RandomWaypointMobilityModel::DoGetPosition (void) const
 {
   return m_helper.GetCurrentPosition ();
 }
 void 
-RandomWaypointMobilityModel::DoSet (const Position &position)
+RandomWaypointMobilityModel::DoSetPosition (const Vector &position)
 {
   m_helper.InitializePosition (position);
   Simulator::Remove (m_event);
   Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
 }
-Speed 
-RandomWaypointMobilityModel::DoGetSpeed (void) const
+Vector
+RandomWaypointMobilityModel::DoGetVelocity (void) const
 {
-  return m_helper.GetSpeed ();
+  return m_helper.GetVelocity ();
 }
 
 
--- a/src/mobility/random-waypoint-mobility-model.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/random-waypoint-mobility-model.h	Thu Nov 08 16:58:24 2007 -0800
@@ -98,9 +98,9 @@
 private:
   void Start (void);
   void BeginWalk (void);
-  virtual Position DoGet (void) const;
-  virtual void DoSet (const Position &position);
-  virtual Speed DoGetSpeed (void) const;
+  virtual Vector DoGetPosition (void) const;
+  virtual void DoSetPosition (const Vector &position);
+  virtual Vector DoGetVelocity (void) const;
 
   StaticSpeedHelper m_helper;
   Ptr<RandomWaypointMobilityModelParameters> m_parameters;
--- a/src/mobility/rectangle.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/rectangle.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -18,8 +18,7 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "rectangle.h"
-#include "position.h"
-#include "speed.h"
+#include "vector.h"
 #include "ns3/assert.h"
 #include <cmath>
 #include <algorithm>
@@ -42,7 +41,7 @@
 {}
 
 bool 
-Rectangle::IsInside (const Position &position) const
+Rectangle::IsInside (const Vector &position) const
 {
   return 
     position.x <= this->xMax && position.x >= this->xMin &&
@@ -50,7 +49,7 @@
 }
 
 Rectangle::Side 
-Rectangle::GetClosestSide (const Position &position) const
+Rectangle::GetClosestSide (const Vector &position) const
 {
   double xMinDist = std::abs (position.x - this->xMin);
   double xMaxDist = std::abs (this->xMax - position.x);
@@ -82,38 +81,38 @@
     }
 }
 
-Position
-Rectangle::CalculateIntersection (const Position &current, const Speed &speed) const
+Vector
+Rectangle::CalculateIntersection (const Vector &current, const Vector &speed) const
 {
-  double xMaxY = current.y + (this->xMax - current.x) / speed.dx * speed.dy;
-  double xMinY = current.y + (this->xMin - current.x) / speed.dx * speed.dy;
-  double yMaxX = current.x + (this->yMax - current.y) / speed.dy * speed.dx;
-  double yMinX = current.x + (this->yMin - current.y) / speed.dy * speed.dx;
+  double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
+  double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
+  double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
+  double yMinX = current.x + (this->yMin - current.y) / speed.y * speed.x;
   bool xMaxYOk = (xMaxY <= this->yMax && xMaxY >= this->yMin);
   bool xMinYOk = (xMinY <= this->yMax && xMinY >= this->yMin);
   bool yMaxXOk = (yMaxX <= this->xMax && yMaxX >= this->xMin);
   bool yMinXOk = (yMinX <= this->xMax && yMinX >= this->xMin);
-  if (xMaxYOk && speed.dx >= 0)
+  if (xMaxYOk && speed.x >= 0)
     {
-      return Position (this->xMax, xMaxY, 0.0);
+      return Vector (this->xMax, xMaxY, 0.0);
     }
-  else if (xMinYOk && speed.dx <= 0)
+  else if (xMinYOk && speed.x <= 0)
     {
-      return Position (this->xMin, xMinY, 0.0);
+      return Vector (this->xMin, xMinY, 0.0);
     }
-  else if (yMaxXOk && speed.dy >= 0)
+  else if (yMaxXOk && speed.y >= 0)
     {
-      return Position (yMaxX, this->yMax, 0.0);
+      return Vector (yMaxX, this->yMax, 0.0);
     }
-  else if (yMinXOk && speed.dy <= 0)
+  else if (yMinXOk && speed.y <= 0)
     {
-      return Position (yMinX, this->yMin, 0.0);
+      return Vector (yMinX, this->yMin, 0.0);
     }
   else
     {
       NS_ASSERT (false);
       // quiet compiler
-      return Position (0.0, 0.0, 0.0);
+      return Vector (0.0, 0.0, 0.0);
     }
 
 }
--- a/src/mobility/rectangle.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/rectangle.h	Thu Nov 08 16:58:24 2007 -0800
@@ -22,8 +22,7 @@
 
 namespace ns3 {
 
-class Position;
-class Speed;
+class Vector;
 
 /**
  * \brief a 2d rectangle
@@ -51,9 +50,9 @@
    * Create a zero-sized rectangle located at coordinates (0.0,0.0)
    */
   Rectangle ();
-  bool IsInside (const Position &position) const;
-  Side GetClosestSide (const Position &position) const;
-  Position CalculateIntersection (const Position &current, const Speed &speed) const;
+  bool IsInside (const Vector &position) const;
+  Side GetClosestSide (const Vector &position) const;
+  Vector CalculateIntersection (const Vector &current, const Vector &speed) const;
 
   double xMin;
   double xMax;
--- a/src/mobility/speed.cc	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "speed.h"
-
-namespace ns3 {
-
-Speed::Speed (double _dx, double _dy, double _dz)
-  : dx (_dx),
-    dy (_dy),
-    dz (_dz)
-{}
-
-Speed::Speed ()
-  : dx (0.0),
-    dy (0.0),
-    dz (0.0)
-{}
-
-} // namespace ns3
--- a/src/mobility/speed.h	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef SPEED_H
-#define SPEED_H
-
-namespace ns3 {
-
-/**
- * \brief keep track of 3d cartesian speed vectors
- *
- * Unit is meters/s.
- */
-class Speed 
-{
-public:
-  /**
-   * \param _dx x coordinate of speed vector
-   * \param _dy y coordinate of speed vector
-   * \param _dz z coordinate of speed vector
-   *
-   * Create speed vector (_dx, _dy, _dz)
-   */
-  Speed (double _dx, double _dy, double _dz);
-  /**
-   * Create speed vector (0.0, 0.0, 0.0)
-   */
-  Speed ();
-  /**
-   * x coordinate of speed vector
-   */
-  double dx;
-  /**
-   * y coordinate of speed vector
-   */
-  double dy;
-  /**
-   * z coordinate of speed vector
-   */
-  double dz;
-};
-
-} // namespace ns3
-
-#endif /* SPEED_H */
--- a/src/mobility/static-mobility-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/static-mobility-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -28,7 +28,7 @@
 {
   SetInterfaceId (StaticMobilityModel::iid);
 }
-StaticMobilityModel::StaticMobilityModel (const Position &position)
+StaticMobilityModel::StaticMobilityModel (const Vector &position)
   : m_position (position)
 {
   SetInterfaceId (StaticMobilityModel::iid);
@@ -36,21 +36,21 @@
 StaticMobilityModel::~StaticMobilityModel ()
 {}
 
-Position
-StaticMobilityModel::DoGet (void) const
+Vector
+StaticMobilityModel::DoGetPosition (void) const
 {
   return m_position;
 }
 void 
-StaticMobilityModel::DoSet (const Position &position)
+StaticMobilityModel::DoSetPosition (const Vector &position)
 {
   m_position = position;
   NotifyCourseChange ();
 }
-Speed 
-StaticMobilityModel::DoGetSpeed (void) const
+Vector
+StaticMobilityModel::DoGetVelocity (void) const
 {
-  return Speed ();
+  return Vector (0.0, 0.0, 0.0);
 }
 
 }; // namespace ns3
--- a/src/mobility/static-mobility-model.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/static-mobility-model.h	Thu Nov 08 16:58:24 2007 -0800
@@ -44,15 +44,15 @@
    * Create a position located at coordinates (x,y,z).
    * Unit is meters
    */
-  StaticMobilityModel (const Position &position);
+  StaticMobilityModel (const Vector &position);
   virtual ~StaticMobilityModel ();
 
 private:
-  virtual Position DoGet (void) const;
-  virtual void DoSet (const Position &position);
-  virtual Speed DoGetSpeed (void) const;
+  virtual Vector DoGetPosition (void) const;
+  virtual void DoSetPosition (const Vector &position);
+  virtual Vector DoGetVelocity (void) const;
 
-  Position m_position;
+  Vector m_position;
 };
 
 }; // namespace ns3
--- a/src/mobility/static-speed-helper.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/static-speed-helper.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -25,40 +25,40 @@
 
 StaticSpeedHelper::StaticSpeedHelper ()
 {}
-StaticSpeedHelper::StaticSpeedHelper (const Position &position)
+StaticSpeedHelper::StaticSpeedHelper (const Vector &position)
   : m_position (position)
 {}
-StaticSpeedHelper::StaticSpeedHelper (const Position &position,
-				      const Speed &speed)
+StaticSpeedHelper::StaticSpeedHelper (const Vector &position,
+				      const Vector &speed)
   : m_position (position),
     m_speed (speed),
     m_paused (true)
 {}
 void 
-StaticSpeedHelper::InitializePosition (const Position &position)
+StaticSpeedHelper::InitializePosition (const Vector &position)
 {
   m_position = position;
-  m_speed.dx = 0.0;
-  m_speed.dy = 0.0;
-  m_speed.dz = 0.0;
+  m_speed.x = 0.0;
+  m_speed.y = 0.0;
+  m_speed.z = 0.0;
   m_lastUpdate = Simulator::Now ();
   m_paused = true;
 }
 
-Position 
+Vector
 StaticSpeedHelper::GetCurrentPosition (void) const
 {
   Update ();
   return m_position;
 }
 
-Speed 
-StaticSpeedHelper::GetSpeed (void) const
+Vector 
+StaticSpeedHelper::GetVelocity (void) const
 {
-  return m_paused? Speed (0, 0, 0) : m_speed;
+  return m_paused? Vector (0.0, 0.0, 0.0) : m_speed;
 }
 void 
-StaticSpeedHelper::SetSpeed (const Speed &speed)
+StaticSpeedHelper::SetSpeed (const Vector &speed)
 {
   Update ();
   m_speed = speed;
@@ -76,13 +76,13 @@
   Time deltaTime = now - m_lastUpdate;
   m_lastUpdate = now;
   double deltaS = deltaTime.GetSeconds ();
-  m_position.x += m_speed.dx * deltaS;
-  m_position.y += m_speed.dy * deltaS;
-  m_position.z += m_speed.dz * deltaS;
+  m_position.x += m_speed.x * deltaS;
+  m_position.y += m_speed.y * deltaS;
+  m_position.z += m_speed.z * deltaS;
 }
 
 void 
-StaticSpeedHelper::Reset (const Speed &speed)
+StaticSpeedHelper::Reset (const Vector &speed)
 {
   Update ();
   m_speed = speed;
@@ -98,7 +98,7 @@
   m_position.y = std::max (bounds.yMin, m_position.y);
 }
 
-Position 
+Vector 
 StaticSpeedHelper::GetCurrentPosition (const Rectangle &bounds) const
 {
   UpdateFull (bounds);
--- a/src/mobility/static-speed-helper.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/static-speed-helper.h	Thu Nov 08 16:58:24 2007 -0800
@@ -21,8 +21,7 @@
 #define STATIC_SPEED_HELPER_H
 
 #include "ns3/nstime.h"
-#include "position.h"
-#include "speed.h"
+#include "vector.h"
 
 namespace ns3 {
 
@@ -32,16 +31,16 @@
 {
  public:
   StaticSpeedHelper ();
-  StaticSpeedHelper (const Position &position);
-  StaticSpeedHelper (const Position &position,
-		     const Speed &speed);
-  void InitializePosition (const Position &position);
+  StaticSpeedHelper (const Vector &position);
+  StaticSpeedHelper (const Vector &position,
+		     const Vector &speed);
+  void InitializePosition (const Vector &position);
 
-  void Reset (const Speed &speed);
-  Position GetCurrentPosition (const Rectangle &bounds) const;
-  Position GetCurrentPosition (void) const;
-  Speed GetSpeed (void) const;
-  void SetSpeed (const Speed &speed);
+  void Reset (const Vector &speed);
+  Vector GetCurrentPosition (const Rectangle &bounds) const;
+  Vector GetCurrentPosition (void) const;
+  Vector GetVelocity (void) const;
+  void SetSpeed (const Vector &speed);
   void Pause (void);
   void Unpause (void);
 
@@ -49,8 +48,8 @@
   void Update (void) const;
   void UpdateFull (const Rectangle &rectangle) const;
   mutable Time m_lastUpdate;
-  mutable Position m_position;
-  Speed m_speed;
+  mutable Vector m_position;
+  Vector m_speed;
   bool m_paused;
 };
 
--- a/src/mobility/static-speed-mobility-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/static-speed-mobility-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -33,13 +33,13 @@
 {
   SetInterfaceId (StaticSpeedMobilityModel::iid);
 }
-StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Position &position)
+StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Vector &position)
   : m_helper (position)
 {
   SetInterfaceId (StaticSpeedMobilityModel::iid);
 }
-StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Position &position,
-                                                    const Speed &speed)
+StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Vector &position,
+                                                    const Vector &speed)
   : m_helper (position, speed)
 {
   SetInterfaceId (StaticSpeedMobilityModel::iid);
@@ -49,28 +49,28 @@
 {}
 
 void 
-StaticSpeedMobilityModel::SetSpeed (const Speed speed)
+StaticSpeedMobilityModel::SetSpeed (const Vector &speed)
 {
   m_helper.SetSpeed (speed);
   NotifyCourseChange ();
 }
 
 
-Position
-StaticSpeedMobilityModel::DoGet (void) const
+Vector
+StaticSpeedMobilityModel::DoGetPosition (void) const
 {
   return m_helper.GetCurrentPosition ();
 }
 void 
-StaticSpeedMobilityModel::DoSet (const Position &position)
+StaticSpeedMobilityModel::DoSetPosition (const Vector &position)
 {
   m_helper.InitializePosition (position);
   NotifyCourseChange ();
 }
-Speed 
-StaticSpeedMobilityModel::DoGetSpeed (void) const
+Vector
+StaticSpeedMobilityModel::DoGetVelocity (void) const
 {
-  return m_helper.GetSpeed ();
+  return m_helper.GetVelocity ();
 }
 
 }; // namespace ns3
--- a/src/mobility/static-speed-mobility-model.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/static-speed-mobility-model.h	Thu Nov 08 16:58:24 2007 -0800
@@ -25,7 +25,6 @@
 #include "ns3/nstime.h"
 #include "ns3/component-manager.h"
 #include "static-speed-helper.h"
-#include "speed.h"
 
 namespace ns3 {
 
@@ -48,15 +47,15 @@
    * Create a position located at coordinates (x,y,z) with
    * speed (0,0,0).
    */
-  StaticSpeedMobilityModel (const Position &position);
+  StaticSpeedMobilityModel (const Vector &position);
   /**
    *
    * Create a position located at coordinates (x,y,z) with
    * speed (dx,dy,dz).
    * Unit is meters and meters/s
    */
-  StaticSpeedMobilityModel (const Position &position,
-                            const Speed &speed);
+  StaticSpeedMobilityModel (const Vector &position,
+                            const Vector &speed);
   virtual ~StaticSpeedMobilityModel ();
 
   /**
@@ -65,11 +64,11 @@
    * Set the current speed now to (dx,dy,dz)
    * Unit is meters/s
    */
-  void SetSpeed (const Speed speed);
+  void SetSpeed (const Vector &speed);
 private:
-  virtual Position DoGet (void) const;
-  virtual void DoSet (const Position &position);
-  virtual Speed DoGetSpeed (void) const;
+  virtual Vector DoGetPosition (void) const;
+  virtual void DoSetPosition (const Vector &position);
+  virtual Vector DoGetVelocity (void) const;
   void Update (void) const;
   StaticSpeedHelper m_helper;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/vector.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,48 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "vector.h"
+#include <cmath>
+
+namespace ns3 {
+
+
+Vector::Vector (double _x, double _y, double _z)
+  : x (_x),
+    y (_y),
+    z (_z)
+{}
+
+Vector::Vector ()
+  : x (0.0),
+    y (0.0),
+    z (0.0)
+{}
+
+double 
+CalculateDistance (const Vector &a, const Vector &b)
+{
+  double dx = b.x - a.x;
+  double dy = b.y - a.y;
+  double dz = b.z - a.z;
+  double distance = std::sqrt (dx * dx + dy * dy + dz * dz);
+  return distance;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/vector.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,63 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef VECTOR_H
+#define VECTOR_H
+
+namespace ns3 {
+
+/**
+ * \brief a 3d cartesian position vector
+ *
+ * Unit is meters.
+ */
+class Vector
+{
+public:
+  /**
+   * \param _x x coordinate of vector vector
+   * \param _y y coordinate of vector vector
+   * \param _z z coordinate of vector vector
+   *
+   * Create vector vector (_x, _y, _z)
+   */
+  Vector (double _x, double _y, double _z);
+  /**
+   * Create vector vector (0.0, 0.0, 0.0)
+   */
+  Vector ();
+  /**
+   * x coordinate of vector vector
+   */
+  double x;
+  /**
+   * y coordinate of vector vector
+   */
+  double y;
+  /**
+   * z coordinate of vector vector
+   */
+  double z;
+};
+
+double CalculateDistance (const Vector &a, const Vector &b);
+
+} // namespace ns3
+
+#endif /* VECTOR_H */
--- a/src/mobility/wscript	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/mobility/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -3,16 +3,15 @@
 def build(bld):
     mobility = bld.create_ns3_module('mobility', ['core', 'simulator'])
     mobility.source = [
+        'vector.cc',
         'grid-topology.cc',
         'hierarchical-mobility-model.cc',
         'mobility-model.cc',
         'mobility-model-notifier.cc',
-        'position.cc',
         'random-position.cc',
         'random-topology.cc',
         'rectangle.cc',
         'rectangle-default-value.cc',
-        'speed.cc',
         'static-mobility-model.cc',
         'static-speed-helper.cc',
         'static-speed-mobility-model.cc',
@@ -24,16 +23,15 @@
 
     headers = bld.create_obj('ns3header')
     headers.source = [
+        'vector.h',
         'grid-topology.h',
         'hierarchical-mobility-model.h',
         'mobility-model.h',
         'mobility-model-notifier.h',
-        'position.h',
         'random-position.h',
         'random-topology.h',
         'rectangle.h',
         'rectangle-default-value.h',
-        'speed.h',
         'static-mobility-model.h',
         'static-speed-helper.h',
         'static-speed-mobility-model.h',
--- a/src/node/channel.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/channel.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -18,6 +18,7 @@
 
 #include "ns3/log.h"
 #include "channel.h"
+#include "net-device.h"
 
 NS_LOG_COMPONENT_DEFINE ("Channel");
 
@@ -60,4 +61,10 @@
   return m_name;
 }
 
+  Ptr<NetDevice>
+Channel::GetDevice (uint32_t i) const
+{
+  return DoGetDevice (i);
+}
+
 } // namespace ns3
--- a/src/node/channel.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/channel.h	Thu Nov 08 16:58:24 2007 -0800
@@ -52,16 +52,18 @@
   /**
    * \param i index of NetDevice to retrieve
    * \returns one of the NetDevices connected to this channel.
-   *
-   * This method must be implemented by subclasses.
    */
-  virtual Ptr<NetDevice> GetDevice (uint32_t i) const = 0;
+  Ptr<NetDevice> GetDevice (uint32_t i) const;
 
 protected:
   virtual      ~Channel ();
   std::string   m_name;
 
 private:
+   /*
+   * This method must be implemented by subclasses.
+   */
+  virtual Ptr<NetDevice> DoGetDevice (uint32_t i) const = 0;
 };
 
 }; // namespace ns3
--- a/src/node/ipv4-address.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/ipv4-address.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -151,16 +151,6 @@
   m_address = AsciiToIpv4Host (address);
 }
 
-bool 
-Ipv4Address::IsEqual (Ipv4Address other) const
-{
-  if (other.m_address == m_address) {
-    return true;
-  } else {
-    return false;
-  }
-}
-
 Ipv4Address
 Ipv4Address::CombineMask (Ipv4Mask const &mask) const
 {
@@ -242,7 +232,7 @@
 {
   return address.CheckCompatible (GetType (), 4);
 }
-Ipv4Address::operator Address ()
+Ipv4Address::operator Address () const
 {
   return ConvertTo ();
 }
@@ -296,19 +286,6 @@
   return loopback;
 }
 
-bool operator == (Ipv4Address const &a, Ipv4Address const &b)
-{
-  return a.IsEqual (b);
-}
-bool operator != (Ipv4Address const &a, Ipv4Address const &b)
-{
-  return !a.IsEqual (b);
-}
-bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB)
-{
-  return (addrA.GetHostOrder () < addrB.GetHostOrder ());
-}
-
 size_t Ipv4AddressHash::operator()(Ipv4Address const &x) const 
 { 
   return x.GetHostOrder ();
--- a/src/node/ipv4-address.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/ipv4-address.h	Thu Nov 08 16:58:24 2007 -0800
@@ -73,7 +73,10 @@
    * \param other address to which to compare this address
    * \return True if the addresses are equal. False otherwise.
    */
-  bool IsEqual (Ipv4Address other) const;
+  bool IsEqual (const Ipv4Address &other) const
+  {
+    return m_address == other.m_address;
+  }
 
   /** 
    * \brief Get the host-order 32-bit IP address
@@ -131,7 +134,7 @@
   bool IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const;
 
   static bool IsMatchingType (const Address &address);
-  operator Address ();
+  operator Address () const;
   static Ipv4Address ConvertFrom (const Address &address);
 
   static Ipv4Address GetZero (void);
@@ -142,6 +145,10 @@
   Address ConvertTo (void) const;
   static uint8_t GetType (void);
   uint32_t m_address;
+
+  friend bool operator == (Ipv4Address const &a, Ipv4Address const &b);
+  friend bool operator != (Ipv4Address const &a, Ipv4Address const &b);
+  friend bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB);
 };
 
 
@@ -177,9 +184,19 @@
 std::ostream& operator<< (std::ostream& os, Ipv4Address const& address);
 std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
 
-bool operator == (Ipv4Address const &a, Ipv4Address const &b);
-bool operator != (Ipv4Address const &a, Ipv4Address const &b);
-bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB);
+inline bool operator == (const Ipv4Address &a, const Ipv4Address &b)
+{
+  return (a.m_address == b.m_address);
+}
+inline bool operator != (const Ipv4Address &a, const Ipv4Address &b)
+{
+  return (a.m_address != b.m_address);
+}
+inline bool operator < (const Ipv4Address &a, const Ipv4Address &b)
+{
+  return (a.m_address < b.m_address);
+}
+
 
 class Ipv4AddressHash : public std::unary_function<Ipv4Address, size_t> {
 public:
--- a/src/node/ipv4.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/ipv4.h	Thu Nov 08 16:58:24 2007 -0800
@@ -385,6 +385,20 @@
 
   /**
    * \param i index of ipv4 interface
+   * \param metric routing metric (cost) associated to the underlying 
+   *          ipv4 interface
+   */
+  virtual void SetMetric (uint32_t i, uint16_t metric) = 0;
+
+  /**
+   * \param i index of ipv4 interface
+   * \returns routing metric (cost) associated to the underlying 
+   *          ipv4 interface
+   */
+  virtual uint16_t GetMetric (uint32_t i) const = 0;
+
+  /**
+   * \param i index of ipv4 interface
    * \returns the address associated to the underlying ipv4 interface
    */
   virtual Ipv4Address GetAddress (uint32_t i) const = 0;
@@ -397,13 +411,13 @@
   virtual Ipv4Address GetSourceAddress (Ipv4Address destination) const = 0;
 
   /**
-   * \param destination The IP address of a hypothetical destination.
+   * \param dest The IP address of a hypothetical destination.
    * \param ifIndex filled in with the interface index that will be used to
    *        send a packet to the hypothetical destination.
-   * \returns True if a single interface can be identified, false otherwise.
+   * \returns true if a single interface can be identified, false otherwise.
    */
   virtual bool GetIfIndexForDestination (Ipv4Address dest,
-    uint32_t &ifIndex) const = 0;
+                                         uint32_t &ifIndex) const = 0;
 
   /**
    * \param i index of ipv4 interface
--- a/src/node/mac48-address.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/mac48-address.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -95,7 +95,7 @@
 {
   return address.CheckCompatible (GetType (), 6);
 }
-Mac48Address::operator Address ()
+Mac48Address::operator Address () const
 {
   return ConvertTo ();
 }
@@ -133,19 +133,48 @@
   return type;
 }
 
+bool
+Mac48Address::IsBroadcast (void) const
+{
+  return *this == GetBroadcast ();
+}
+bool 
+Mac48Address::IsMulticast (void) const
+{
+  return (m_address[0] & 0x01) == 0x01;
+}
+Mac48Address
+Mac48Address::GetBroadcast (void)
+{
+  static Mac48Address broadcast = Mac48Address ("ff:ff:ff:ff:ff:ff");
+  return broadcast;
+}
 bool operator == (const Mac48Address &a, const Mac48Address &b)
 {
-  uint8_t ada[6];
-  uint8_t adb[6];
-  a.CopyTo (ada);
-  b.CopyTo (adb);
-  return memcmp (ada, adb, 6) == 0;
+  return memcmp (a.m_address, b.m_address, 6) == 0;
 }
 bool operator != (const Mac48Address &a, const Mac48Address &b)
 {
   return ! (a == b);
 }
 
+bool operator < (const Mac48Address &a, const Mac48Address &b)
+{
+  for (uint8_t i = 0; i < 6; i++) 
+    {
+      if (a.m_address[i] < b.m_address[i]) 
+        {
+          return true;
+        } 
+      else if (a.m_address[i] > b.m_address[i]) 
+        {
+          return false;
+        }
+    }
+  return false;
+}
+
+
 std::ostream& operator<< (std::ostream& os, const Mac48Address & address)
 {
   uint8_t ad[6];
--- a/src/node/mac48-address.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/mac48-address.h	Thu Nov 08 16:58:24 2007 -0800
@@ -61,7 +61,7 @@
    *
    * Convert an instance of this class to a polymorphic Address instance.
    */
-  operator Address ();
+  operator Address () const;
   /**
    * \param address a polymorphic address
    * \returns a new Mac48Address from the polymorphic address
@@ -79,6 +79,20 @@
    * Allocate a new Mac48Address.
    */
   static Mac48Address Allocate (void);
+
+  /**
+   * \returns true if this is a broadcast address, false otherwise.
+   */
+  bool IsBroadcast (void) const;
+  /**
+   * \returns true if this is a multicast address, false otherwise.
+   */
+  bool IsMulticast (void) const;
+
+  /**
+   * \returns the broadcast address
+   */
+  static Mac48Address GetBroadcast (void);
 private:
   /**
    * \returns a new Address instance
@@ -87,11 +101,15 @@
    */
   Address ConvertTo (void) const;
   static uint8_t GetType (void);
+  friend bool operator < (const Mac48Address &a, const Mac48Address &b);
+  friend bool operator == (const Mac48Address &a, const Mac48Address &b);
+
   uint8_t m_address[6];
 };
 
 bool operator == (const Mac48Address &a, const Mac48Address &b);
 bool operator != (const Mac48Address &a, const Mac48Address &b);
+bool operator < (const Mac48Address &a, const Mac48Address &b);
 std::ostream& operator<< (std::ostream& os, const Mac48Address & address);
 
 } // namespace ns3
--- a/src/node/mac64-address.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/mac64-address.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -95,7 +95,7 @@
 {
   return address.CheckCompatible (GetType (), 8);
 }
-Mac64Address::operator Address ()
+Mac64Address::operator Address () const
 {
   return ConvertTo ();
 }
--- a/src/node/mac64-address.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/node/mac64-address.h	Thu Nov 08 16:58:24 2007 -0800
@@ -60,7 +60,7 @@
    *
    * Convert an instance of this class to a polymorphic Address instance.
    */
-  operator Address ();
+  operator Address () const;
   /**
    * \param address a polymorphic address
    * \returns a new Mac64Address from the polymorphic address
--- a/src/routing/global-routing/global-route-manager-impl.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/routing/global-routing/global-route-manager-impl.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -529,7 +529,8 @@
 // Get w_lsa:  In case of V is Router-LSA
       if (v->GetVertexType () == SPFVertex::VertexRouter) 
         {
-          NS_LOG_LOGIC ("Examining " << v->GetVertexId () << "'s " <<
+          NS_LOG_LOGIC ("Examining link " << i << " of " << 
+            v->GetVertexId () << "'s " <<
             v->GetLSA ()->GetNLinkRecords () << " link records");
 //
 // (a) If this is a link to a stub network, examine the next link in V's LSA.
@@ -637,7 +638,8 @@
               candidate.Push (w);
               NS_LOG_LOGIC ("Pushing " << 
                 w->GetVertexId () << ", parent vertexId: " << 
-                v->GetVertexId ());
+                v->GetVertexId () << ", distance: " <<
+                w->GetDistanceFromRoot ());
             }
         }
       else if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_CANDIDATE)
@@ -688,7 +690,7 @@
 }
 
 //
-// This method is derived from quagga ospf_next_hop_calculation() 16.1.1.  
+// This method is derived from quagga ospf_nexthop_calculation() 16.1.1.  
 //
 // Calculate nexthop from root through V (parent) to vertex W (destination)
 // with given distance from root->W.
@@ -784,11 +786,13 @@
 //
           w->SetOutgoingInterfaceId (
             FindOutgoingInterfaceId (l->GetLinkData ()));
-
+          w->SetDistanceFromRoot (distance);
+          w->SetParent (v);
           NS_LOG_LOGIC ("Next hop from " << 
             v->GetVertexId () << " to " << w->GetVertexId () << 
             " goes through next hop " << w->GetNextHop () <<
-            " via outgoing interface " << w->GetOutgoingInterfaceId ());
+            " via outgoing interface " << w->GetOutgoingInterfaceId () <<
+            " with distance " << distance);
         }  // end W is a router vertes
       else 
         {
@@ -804,7 +808,8 @@
           w->SetParent (v);
           NS_LOG_LOGIC ("Next hop from " << 
             v->GetVertexId () << " to network " << w->GetVertexId () << 
-            " via outgoing interface " << w->GetOutgoingInterfaceId ());
+            " via outgoing interface " << w->GetOutgoingInterfaceId () <<
+            " with distance " << distance);
           return 1;
         }
     } // end v is the root
@@ -997,6 +1002,7 @@
   m_spfroot= v;
   v->SetDistanceFromRoot (0);
   v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE);
+  NS_LOG_LOGIC ("Starting SPFCalculate for node " << root);
 
   for (;;)
     {
--- a/src/routing/global-routing/global-router-interface.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/routing/global-routing/global-router-interface.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -50,7 +50,7 @@
   LinkType    linkType, 
   Ipv4Address linkId, 
   Ipv4Address linkData, 
-  uint32_t    metric)
+  uint16_t    metric)
 :
   m_linkId (linkId),
   m_linkData (linkData),
@@ -110,7 +110,7 @@
   m_linkType = linkType;
 }
 
-  uint32_t
+  uint16_t
 GlobalRoutingLinkRecord::GetMetric (void) const
 {
   NS_LOG_FUNCTION;
@@ -118,7 +118,7 @@
 }
 
   void
-GlobalRoutingLinkRecord::SetMetric (uint32_t metric)
+GlobalRoutingLinkRecord::SetMetric (uint16_t metric)
 {
   NS_LOG_FUNCTION;
   m_metric = metric;
@@ -202,6 +202,7 @@
       pDst->SetLinkType (pSrc->GetLinkType ());
       pDst->SetLinkId (pSrc->GetLinkId ());
       pDst->SetLinkData (pSrc->GetLinkData ());
+      pDst->SetMetric (pSrc->GetMetric ());
 
       m_linkRecords.push_back(pDst);
       pDst = 0;
@@ -397,6 +398,7 @@
           os << "----------" << std::endl;
           os << "m_linkId = " << p->GetLinkId () << std::endl;
           os << "m_linkData = " << p->GetLinkData () << std::endl;
+          os << "m_metric = " << p->GetMetric () << std::endl;
         }
     }
   else if (m_lsType == GlobalRoutingLSA::NetworkLSA) 
@@ -547,6 +549,7 @@
           Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
           Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
           NS_LOG_LOGIC ("Working with local address " << addrLocal);
+          uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
 //
 // Now, we're going to walk over to the remote net device on the other end of 
 // the point-to-point channel we now know we have.  This is where our adjacent 
@@ -566,8 +569,7 @@
               Ipv4Address maskLocalAddr;
               maskLocalAddr.Set(maskLocal.GetHostOrder ());
               plr->SetLinkData (maskLocalAddr);
-              // Cost is interface's configured output cost (NOTYET)
-              plr->SetMetric (1);
+              plr->SetMetric (metricLocal);
               pLSA->AddLinkRecord(plr);
               plr = 0;
               continue;
@@ -589,8 +591,7 @@
               plr->SetLinkId (desigRtr);
               // Link Data is router's own IP address
               plr->SetLinkData (addrLocal);
-              // Cost is interface's configured output cost (NOTYET)
-              plr->SetMetric (1);
+              plr->SetMetric (metricLocal);
               pLSA->AddLinkRecord (plr);
               plr = 0;
               continue;
@@ -613,6 +614,7 @@
           Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
           Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
           NS_LOG_LOGIC ("Working with local address " << addrLocal);
+          uint16_t metricLocal = ipv4Local->GetMetric (ifIndexLocal);
 //
 // Now, we're going to walk over to the remote net device on the other end of 
 // the point-to-point channel we now know we have.  This is where our adjacent 
@@ -659,6 +661,7 @@
           plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
           plr->SetLinkId (rtrIdRemote);
           plr->SetLinkData (addrLocal);
+          plr->SetMetric (metricLocal);
           pLSA->AddLinkRecord (plr);
           plr = 0;
 
@@ -666,6 +669,7 @@
           plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
           plr->SetLinkId (addrRemote);
           plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder()));  // Frown
+          plr->SetMetric (metricLocal);
           pLSA->AddLinkRecord (plr);
           plr = 0;
         }
--- a/src/routing/global-routing/global-router-interface.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/routing/global-routing/global-router-interface.h	Thu Nov 08 16:58:24 2007 -0800
@@ -82,7 +82,7 @@
     LinkType    linkType, 
     Ipv4Address linkId, 
     Ipv4Address linkData, 
-    uint32_t    metric);
+    uint16_t    metric);
 
 /**
  * @brief Destroy a Global Routing Link Record.
@@ -176,7 +176,7 @@
  *
  * @returns The metric field of the Global Routing Link Record.
  */
-  uint32_t GetMetric(void) const;
+  uint16_t GetMetric(void) const;
 
 /**
  * @brief Set the Metric Data field of the Global Routing Link Record.
@@ -189,7 +189,7 @@
  *
  * @param metric The new metric for the current Global Routing Link Record.
  */
-  void SetMetric(uint32_t metric);
+  void SetMetric(uint16_t metric);
 
 private:
 /**
@@ -230,7 +230,7 @@
  * of two hops relate to the cost of sending a packet); rather you should
  * use something like delay.
  */
-  uint32_t m_metric;  
+  uint16_t m_metric;  
 };
 
 /**  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/event-garbage-collector.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,153 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+#include "event-garbage-collector.h"
+
+#define CLEANUP_CHUNK_MIN_SIZE 8
+#define CLEANUP_CHUNK_MAX_SIZE 128
+
+
+namespace ns3 {
+
+
+EventGarbageCollector::EventGarbageCollector () :
+  m_nextCleanupSize (CLEANUP_CHUNK_MIN_SIZE)
+{}
+
+void
+EventGarbageCollector::Track (EventId event)
+{
+  m_events.insert (event);
+  if (m_events.size () >= m_nextCleanupSize)
+    Cleanup ();
+}
+
+void
+EventGarbageCollector::Grow ()
+{
+  m_nextCleanupSize += (m_nextCleanupSize < CLEANUP_CHUNK_MAX_SIZE?
+                        m_nextCleanupSize : CLEANUP_CHUNK_MAX_SIZE);
+}
+
+void
+EventGarbageCollector::Shrink ()
+{
+  while (m_nextCleanupSize > m_events.size ())
+    m_nextCleanupSize >>= 1;
+  Grow ();
+}
+
+// Called when a new event was added and the cleanup limit was exceeded in consequence.
+void
+EventGarbageCollector::Cleanup ()
+{
+  for (EventList::iterator iter = m_events.begin (); iter != m_events.end ();)
+    {
+      if ((*iter).IsExpired ())
+        {
+          m_events.erase (iter++);
+        }
+      else
+        break; // EventIds are sorted by timestamp => further events are not expired for sure
+    }
+
+  // If after cleanup we are still over the limit, increase the limit.
+  if (m_events.size () >= m_nextCleanupSize)
+    Grow ();
+  else
+    Shrink ();
+}
+
+
+EventGarbageCollector::~EventGarbageCollector ()
+{
+  for (EventList::iterator event = m_events.begin ();
+       event != m_events.end (); event++)
+    {
+      Simulator::Cancel (*event);
+    }
+}
+
+}; // namespace ns3
+
+
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+
+namespace ns3 {
+
+class EventGarbageCollectorTests : public Test
+{
+  int m_counter;
+  EventGarbageCollector *m_events;
+
+  void EventGarbageCollectorCallback ();
+
+public:
+
+  EventGarbageCollectorTests ();
+  virtual ~EventGarbageCollectorTests ();
+  virtual bool RunTests (void);
+};
+
+EventGarbageCollectorTests::EventGarbageCollectorTests ()
+  : Test ("EventGarbageCollector"), m_counter (0), m_events (0)
+{}
+
+EventGarbageCollectorTests::~EventGarbageCollectorTests ()
+{}
+
+void
+EventGarbageCollectorTests::EventGarbageCollectorCallback ()
+{
+  m_counter++;
+  if (m_counter == 50)
+    {
+      // this should cause the remaining (50) events to be cancelled
+      delete m_events;
+      m_events = 0;
+    }
+}
+
+bool EventGarbageCollectorTests::RunTests (void)
+{
+  bool result = true;
+
+  m_events = new EventGarbageCollector ();
+
+  for (int n = 0; n < 100; n++)
+    {
+      m_events->Track (Simulator::Schedule
+                       (Simulator::Now (),
+                        &EventGarbageCollectorTests::EventGarbageCollectorCallback,
+                        this));
+    }
+  Simulator::Run ();
+  NS_TEST_ASSERT_EQUAL (m_events, 0);
+  NS_TEST_ASSERT_EQUAL (m_counter, 50);
+  return result;
+}
+
+static EventGarbageCollectorTests g_eventCollectorTests;
+    
+};
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/event-garbage-collector.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,71 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+#ifndef EVENT_GARBAGE_COLLECTOR_H
+#define EVENT_GARBAGE_COLLECTOR_H
+
+#include <set>
+#include "ns3/event-id.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+/**
+ * \brief An object that tracks scheduled events and automatically
+ * cancels them when it is destroyed.  It is useful in situations
+ * where multiple instances of the same type of event can
+ * simultaneously be scheduled, and when the events should be limited
+ * to the lifetime of a container object.
+ */
+class EventGarbageCollector
+{
+public:
+
+  EventGarbageCollector ();
+
+  /**
+   * \brief Tracks a new event
+   */
+  void Track (EventId event);
+
+  ~EventGarbageCollector ();
+
+private:
+
+  struct EventIdLessThanTs
+  {
+    bool operator () (const EventId &a, const EventId &b) const
+    {
+      return (a.GetTs () < b.GetTs ());
+    }
+  };
+
+  typedef std::multiset<EventId, EventIdLessThanTs> EventList;
+
+  EventList::size_type m_nextCleanupSize;
+  EventList m_events;
+
+  void Cleanup ();
+  void Grow ();
+  void Shrink ();
+};
+
+}; // namespace ns3
+
+#endif /* EVENT_GARBAGE_COLLECTOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-agent-impl.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,2114 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+
+///
+/// \file	OLSR.cc
+/// \brief	Implementation of OLSR agent and related classes.
+///
+/// This is the main file of this software because %OLSR's behaviour is
+/// implemented here.
+///
+
+#include "olsr-agent-impl.h"
+#include "ns3/socket-factory.h"
+#include "ns3/udp.h"
+#include "ns3/internet-node.h"
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/composite-trace-resolver.h"
+
+
+/********** Useful macros **********/
+
+///
+/// \brief Gets the delay between a given time and the current time.
+///
+/// If given time is previous to the current one, then this macro returns
+/// a number close to 0. This is used for scheduling events at a certain moment.
+///
+#define DELAY(time) (((time) < (Simulator::Now ())) ? Seconds (0.000001) : \
+                     (time - Simulator::Now () + Seconds (0.000001)))
+
+
+
+/********** Intervals **********/
+
+/// HELLO messages emission interval.
+#define OLSR_HELLO_INTERVAL	Seconds (2)
+
+/// TC messages emission interval.
+#define OLSR_TC_INTERVAL	Seconds (5)
+
+/// MID messages emission interval.
+#define OLSR_MID_INTERVAL	OLSR_TC_INTERVAL
+
+///
+/// \brief Period at which a node must cite every link and every neighbor.
+///
+/// We only use this value in order to define OLSR_NEIGHB_HOLD_TIME.
+///
+#define OLSR_REFRESH_INTERVAL	Seconds (2)
+
+
+/********** Holding times **********/
+
+/// Neighbor holding time.
+#define OLSR_NEIGHB_HOLD_TIME	(Scalar (3) * OLSR_REFRESH_INTERVAL)
+/// Top holding time.
+#define OLSR_TOP_HOLD_TIME	(Scalar (3) * OLSR_TC_INTERVAL)
+/// Dup holding time.
+#define OLSR_DUP_HOLD_TIME	Seconds (30)
+/// MID holding time.
+#define OLSR_MID_HOLD_TIME	(Scalar (3) * OLSR_MID_INTERVAL)
+
+
+/********** Link types **********/
+
+/// Unspecified link type.
+#define OLSR_UNSPEC_LINK	0
+/// Asymmetric link type.
+#define OLSR_ASYM_LINK		1
+/// Symmetric link type.
+#define OLSR_SYM_LINK		2
+/// Lost link type.
+#define OLSR_LOST_LINK		3
+
+/********** Neighbor types **********/
+
+/// Not neighbor type.
+#define OLSR_NOT_NEIGH		0
+/// Symmetric neighbor type.
+#define OLSR_SYM_NEIGH		1
+/// Asymmetric neighbor type.
+#define OLSR_MPR_NEIGH		2
+
+
+/********** Willingness **********/
+
+/// Willingness for forwarding packets from other nodes: never.
+#define OLSR_WILL_NEVER		0
+/// Willingness for forwarding packets from other nodes: low.
+#define OLSR_WILL_LOW		1
+/// Willingness for forwarding packets from other nodes: medium.
+#define OLSR_WILL_DEFAULT	3
+/// Willingness for forwarding packets from other nodes: high.
+#define OLSR_WILL_HIGH		6
+/// Willingness for forwarding packets from other nodes: always.
+#define OLSR_WILL_ALWAYS	7
+
+
+/********** Miscellaneous constants **********/
+
+/// Maximum allowed jitter.
+#define OLSR_MAXJITTER		(OLSR_HELLO_INTERVAL.GetSeconds () / 4)
+/// Maximum allowed sequence number.
+#define OLSR_MAX_SEQ_NUM	65535
+/// Random number between [0-OLSR_MAXJITTER] used to jitter OLSR packet transmission.
+#define JITTER (Seconds (UniformVariable::GetSingleValue (0, OLSR_MAXJITTER)))
+
+
+#define OLSR_PORT_NUMBER 698
+/// Maximum number of messages per packet.
+#define OLSR_MAX_MSGS		64
+
+/// Maximum number of hellos per message (4 possible link types * 3 possible nb types).
+#define OLSR_MAX_HELLOS		12
+
+/// Maximum number of addresses advertised on a message.
+#define OLSR_MAX_ADDRS		64
+
+
+namespace ns3 {
+namespace olsr {
+
+NS_LOG_COMPONENT_DEFINE ("OlsrAgent");
+
+
+/********** OLSR class **********/
+
+
+AgentImpl::AgentImpl (Ptr<Node> node)
+  :
+  m_useL2Notifications (false),
+  m_helloTimer (Timer::CANCEL_ON_DESTROY),
+  m_tcTimer (Timer::CANCEL_ON_DESTROY),
+  m_midTimer (Timer::CANCEL_ON_DESTROY)
+{
+  m_helloTimer.SetFunction (&AgentImpl::HelloTimerExpire, this);
+  m_tcTimer.SetFunction (&AgentImpl::TcTimerExpire, this);
+  m_midTimer.SetFunction (&AgentImpl::MidTimerExpire, this);
+  m_queuedMessagesTimer.SetFunction (&AgentImpl::SendQueuedMessages, this);
+
+
+  SetInterfaceId (AgentImpl::iid);
+
+  // Aggregate with the Node, so that OLSR dies when the node is destroyed.
+  node->AddInterface (this);
+
+  m_packetSequenceNumber = OLSR_MAX_SEQ_NUM;
+  m_messageSequenceNumber = OLSR_MAX_SEQ_NUM;
+  m_ansn = OLSR_MAX_SEQ_NUM;
+
+  m_helloInterval = OLSR_HELLO_INTERVAL;
+  m_tcInterval = OLSR_TC_INTERVAL;
+  m_midInterval = OLSR_MID_INTERVAL;
+  m_willingness = OLSR_WILL_ALWAYS;
+
+  m_linkTupleTimerFirstTime = true;
+
+  m_ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
+  NS_ASSERT (m_ipv4);
+
+  Ptr<SocketFactory> socketFactory = node->QueryInterface<SocketFactory> (Udp::iid);
+
+  m_receiveSocket = socketFactory->CreateSocket ();
+  if (m_receiveSocket->Bind (InetSocketAddress (OLSR_PORT_NUMBER)))
+    NS_ASSERT_MSG (false, "Failed to bind() OLSR receive socket");
+
+  m_sendSocket = socketFactory->CreateSocket ();
+  m_sendSocket->Connect (InetSocketAddress (Ipv4Address (0xffffffff), OLSR_PORT_NUMBER));
+
+}
+
+void AgentImpl::DoDispose ()
+{
+  m_ipv4 = 0;
+  if (m_receiveSocket)
+    {
+      m_receiveSocket->Dispose ();
+      m_receiveSocket = 0;
+    }
+  if (m_sendSocket)
+    {
+      m_sendSocket->Dispose ();
+      m_sendSocket = 0;  
+    }
+  if (m_routingTable)
+    {
+      m_routingTable->Dispose ();
+      m_routingTable = 0;
+    }
+
+  Object::DoDispose ();
+}
+
+void AgentImpl::Start ()
+{
+  if (m_mainAddress == Ipv4Address ())
+    {
+      Ipv4Address loopback ("127.0.0.1");
+      for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+        {
+          Ipv4Address addr = m_ipv4->GetAddress (i);
+          if (addr != loopback)
+            {
+              m_mainAddress = addr;
+              break;
+            }
+        }
+
+      NS_ASSERT (m_mainAddress != Ipv4Address ());
+    }
+
+  NS_LOG_DEBUG ("Starting OLSR on node " << m_mainAddress);
+
+  m_routingTable = Create<RoutingTable> (m_ipv4, m_mainAddress);
+  // Add OLSR as routing protocol, with slightly lower priority than
+  // static routing.
+  m_ipv4->AddRoutingProtocol (m_routingTable, -10);
+
+  if (m_sendSocket->Bind (InetSocketAddress (m_mainAddress, OLSR_PORT_NUMBER)))
+    NS_ASSERT_MSG (false, "Failed to bind() OLSR send socket");
+  m_receiveSocket->SetRecvCallback (MakeCallback (&AgentImpl::RecvOlsr,  this));
+
+  HelloTimerExpire ();
+  TcTimerExpire ();
+  MidTimerExpire ();
+
+  NS_LOG_DEBUG ("OLSR on node " << m_mainAddress << " started");
+}
+
+void AgentImpl::SetMainInterface (uint32_t interface)
+{
+  m_mainAddress = m_ipv4->GetAddress (interface);
+}
+
+
+Ptr<TraceResolver> 
+AgentImpl::GetTraceResolver (void) const
+{
+  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
+  resolver->AddSource ("rx",
+                       TraceDoc ("receive OLSR packet",
+                                 "const olsr::PacketHeader &", "header of OLSR packet received",
+                                 "const olsr::MessageList &", "list of OLSR messages contained in the packet"
+                                 ),
+                       m_rxPacketTrace);
+  resolver->AddSource ("tx",
+                       TraceDoc ("send OLSR packet",
+                                 "const olsr::PacketHeader &", "header of OLSR packet sent",
+                                 "const olsr::MessageList &", "list of OLSR messages contained in the packet"
+                                 ),
+                       m_txPacketTrace);
+  resolver->SetParentResolver (Object::GetTraceResolver ());
+  return resolver;
+}
+
+
+//
+// \brief Processes an incoming %OLSR packet following RFC 3626 specification.
+void
+AgentImpl::RecvOlsr (Ptr<Socket> socket,
+                         const Packet &receivedPacket,
+                         const Address &sourceAddress)
+{
+  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " received a OLSR packet");
+  InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
+  
+  // All routing messages are sent from and to port RT_PORT,
+  // so we check it.
+  NS_ASSERT (inetSourceAddr.GetPort () == OLSR_PORT_NUMBER);
+  
+  Packet packet = receivedPacket;
+
+  olsr::PacketHeader olsrPacketHeader;
+  packet.RemoveHeader (olsrPacketHeader);
+  NS_ASSERT (olsrPacketHeader.GetPacketLength () >= olsrPacketHeader.GetSerializedSize ());
+  uint32_t sizeLeft = olsrPacketHeader.GetPacketLength () - olsrPacketHeader.GetSerializedSize ();
+
+  MessageList messages;
+  
+  while (sizeLeft)
+    {
+      MessageHeader messageHeader;
+      if (packet.RemoveHeader (messageHeader) == 0)
+        NS_ASSERT (false);
+      
+      sizeLeft -= messageHeader.GetSerializedSize ();
+
+      NS_LOG_DEBUG ("Olsr Msg received with type "
+                << std::dec << int (messageHeader.GetMessageType ())
+                << " TTL=" << int (messageHeader.GetTimeToLive ())
+                << " origAddr=" << messageHeader.GetOriginatorAddress ());
+      messages.push_back (messageHeader);
+    }
+
+  m_rxPacketTrace (olsrPacketHeader, messages);
+
+  for (MessageList::const_iterator messageIter = messages.begin ();
+       messageIter != messages.end (); messageIter++)
+    {
+      const MessageHeader &messageHeader = *messageIter;
+      // If ttl is less than or equal to zero, or
+      // the receiver is the same as the originator,
+      // the message must be silently dropped
+      if (messageHeader.GetTimeToLive () == 0
+          || messageHeader.GetOriginatorAddress () == m_mainAddress)
+        {
+          packet.RemoveAtStart (messageHeader.GetSerializedSize ()
+                                - messageHeader.GetSerializedSize ());
+          continue;
+        }
+
+      // If the message has been processed it must not be processed again
+      bool do_forwarding = true;
+      DuplicateTuple *duplicated = m_state.FindDuplicateTuple
+        (messageHeader.GetOriginatorAddress (),
+         messageHeader.GetMessageSequenceNumber ());
+      
+      if (duplicated == NULL)
+        {
+          switch (messageHeader.GetMessageType ())
+            {
+            case olsr::MessageHeader::HELLO_MESSAGE:
+              NS_LOG_DEBUG ("OLSR node received HELLO message of size " << messageHeader.GetSerializedSize ());
+              ProcessHello (messageHeader, m_mainAddress, inetSourceAddr.GetIpv4 ());
+              break;
+
+            case olsr::MessageHeader::TC_MESSAGE:
+              NS_LOG_DEBUG ("OLSR node received TC message of size " << messageHeader.GetSerializedSize ());
+              ProcessTc (messageHeader, inetSourceAddr.GetIpv4 ());
+              break;
+
+            case olsr::MessageHeader::MID_MESSAGE:
+              NS_LOG_DEBUG ("OLSR node received MID message of size " << messageHeader.GetSerializedSize ());
+              ProcessMid (messageHeader, inetSourceAddr.GetIpv4 ());
+              break;
+
+            default:
+              NS_LOG_DEBUG ("OLSR message type " <<
+                        int (messageHeader.GetMessageType ()) <<
+                        " not implemented");
+            }
+        }
+      else
+        {
+          NS_LOG_DEBUG ("OLSR message is duplicated, not reading it.");
+      
+          // If the message has been considered for forwarding, it should
+          // not be retransmitted again
+          for (std::vector<Ipv4Address>::const_iterator it = duplicated->ifaceList.begin ();
+               it != duplicated->ifaceList.end(); it++)
+            {
+              if (*it == m_mainAddress)
+                {
+                  do_forwarding = false;
+                  break;
+                }
+            }
+        }
+      
+      if (do_forwarding)
+        {
+          // HELLO messages are never forwarded.
+          // TC and MID messages are forwarded using the default algorithm.
+          // Remaining messages are also forwarded using the default algorithm.
+          if (messageHeader.GetMessageType ()  != olsr::MessageHeader::HELLO_MESSAGE)
+            ForwardDefault (messageHeader, duplicated,
+                            m_mainAddress, inetSourceAddr.GetIpv4 ());
+        }
+	
+    }
+
+  // After processing all OLSR messages, we must recompute the routing table
+  RoutingTableComputation ();
+}
+
+///
+/// \brief This auxiliary function (defined in RFC 3626) is used for calculating the MPR Set.
+///
+/// \param tuple the neighbor tuple which has the main address of the node we are going to calculate its degree to.
+/// \return the degree of the node.
+///
+int
+AgentImpl::Degree (NeighborTuple const &tuple)
+{
+  int degree = 0;
+  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
+       it != m_state.GetTwoHopNeighbors ().end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple = *it;
+      if (nb2hop_tuple.neighborMainAddr == tuple.neighborMainAddr)
+        {
+          NeighborTuple *nb_tuple =
+            m_state.FindNeighborTuple (nb2hop_tuple.neighborMainAddr);
+          if (nb_tuple == NULL)
+            degree++;
+        }
+    }
+  return degree;
+}
+
+///
+/// \brief Computates MPR set of a node following RFC 3626 hints.
+///
+void
+AgentImpl::MprComputation()
+{
+  // MPR computation should be done for each interface. See section 8.3.1
+  // (RFC 3626) for details.
+	
+  m_state.ClearMprSet ();
+  
+  // N is the subset of neighbors of the node, which are
+  // neighbor "of the interface I"
+  NeighborSet N;
+  for (NeighborSet::const_iterator it = m_state.GetNeighbors ().begin();
+       it != m_state.GetNeighbors ().end (); it++)
+    {
+      if ((*it).status == NeighborTuple::STATUS_SYM) // I think that we need this check
+        N.push_back (*it);
+    }
+	
+  // N2 is the set of 2-hop neighbors reachable from "the interface
+  // I", excluding:
+  // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
+  // (ii)  the node performing the computation
+  // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+  //       link to this node on some interface.
+  TwoHopNeighborSet N2;
+  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
+       it != m_state.GetTwoHopNeighbors ().end (); it++)
+    {
+      TwoHopNeighborTuple const &twoHopNeigh = *it;
+      bool ok = true;
+      const NeighborTuple *nb_tuple = m_state.FindSymNeighborTuple (twoHopNeigh.neighborMainAddr);
+      if (nb_tuple == NULL)
+        {
+          ok = false;
+        }
+      else
+        {
+          nb_tuple = m_state.FindNeighborTuple (twoHopNeigh.neighborMainAddr, OLSR_WILL_NEVER);
+          if (nb_tuple != NULL)
+            {
+              ok = false;
+            }
+          else
+            {
+              nb_tuple = m_state.FindSymNeighborTuple (twoHopNeigh.neighborMainAddr);
+              if (nb_tuple != NULL)
+                ok = false;
+            }
+        }
+
+      if (ok)
+        N2.push_back (twoHopNeigh);
+    }
+	
+  // 1. Start with an MPR set made of all members of N with
+  // N_willingness equal to WILL_ALWAYS
+  for (NeighborSet::const_iterator it = N.begin (); it != N.end (); it++)
+    {
+      NeighborTuple const &nb_tuple = *it;
+      if (nb_tuple.willingness == OLSR_WILL_ALWAYS)
+        m_state.InsertMprAddress (nb_tuple.neighborMainAddr);
+    }
+  
+  // 2. Calculate D(y), where y is a member of N, for all nodes in N.
+  // We will do this later.
+  // FIXME
+	
+  // 3. Add to the MPR set those nodes in N, which are the *only*
+  // nodes to provide reachability to a node in N2. Remove the
+  // nodes from N2 which are now covered by a node in the MPR set.
+  MprSet foundset;
+  std::set<Ipv4Address> deleted_addrs;
+  for (TwoHopNeighborSet::iterator it = N2.begin (); it != N2.end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple1 = *it;
+		
+      MprSet::const_iterator pos = foundset.find (nb2hop_tuple1.twoHopNeighborAddr);
+      if (pos != foundset.end ())
+        continue;
+		
+      bool found = false;
+      for (NeighborSet::const_iterator it2 = N.begin ();
+           it2 != N.end (); it2++)
+        {
+          if ((*it2).neighborMainAddr == nb2hop_tuple1.neighborMainAddr) {
+            found = true;
+            break;
+          }
+        }
+      if (!found)
+        continue;
+		
+      found = false;
+      for (TwoHopNeighborSet::const_iterator it2 = it + 1;
+           it2 != N2.end (); it2++)
+        {
+          TwoHopNeighborTuple const &nb2hop_tuple2 = *it2;
+          if (nb2hop_tuple1.twoHopNeighborAddr == nb2hop_tuple2.twoHopNeighborAddr)
+            {
+              foundset.insert (nb2hop_tuple1.twoHopNeighborAddr);
+              found = true;
+              break;
+            }
+        }
+      if (!found)
+        {
+          m_state.InsertMprAddress (nb2hop_tuple1.neighborMainAddr);
+          
+          for (TwoHopNeighborSet::iterator it2 = it + 1; it2 != N2.end (); it2++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple2 = *it2;
+              if (nb2hop_tuple1.neighborMainAddr == nb2hop_tuple2.neighborMainAddr)
+                {
+                  deleted_addrs.insert (nb2hop_tuple2.twoHopNeighborAddr);
+                  it2 = N2.erase (it2);
+                  it2--;
+                }
+            }
+          it = N2.erase (it);
+          it--;
+        }
+		
+      for (std::set<Ipv4Address>::iterator it2 = deleted_addrs.begin ();
+           it2 != deleted_addrs.end ();
+           it2++)
+        {
+          for (TwoHopNeighborSet::iterator it3 = N2.begin ();
+               it3 != N2.end ();
+               it3++)
+            {
+              if ((*it3).twoHopNeighborAddr == *it2)
+                {
+                  it3 = N2.erase (it3);
+                  it3--;
+                  // I have to reset the external iterator because it
+                  // may have been invalidated by the latter deletion
+                  it = N2.begin ();
+                  it--;
+                }
+            }
+        }
+      deleted_addrs.clear ();
+    }
+	
+  // 4. While there exist nodes in N2 which are not covered by at
+  // least one node in the MPR set:
+  while (N2.begin () != N2.end ())
+    {
+      // 4.1. For each node in N, calculate the reachability, i.e., the
+      // number of nodes in N2 which are not yet covered by at
+      // least one node in the MPR set, and which are reachable
+      // through this 1-hop neighbor
+      std::map<int, std::vector<const NeighborTuple *> > reachability;
+      std::set<int> rs;
+      for (NeighborSet::iterator it = N.begin(); it != N.end(); it++)
+        {
+          NeighborTuple const &nb_tuple = *it;
+          int r = 0;
+          for (TwoHopNeighborSet::iterator it2 = N2.begin (); it2 != N2.end (); it2++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple = *it2;
+              if (nb_tuple.neighborMainAddr == nb2hop_tuple.neighborMainAddr)
+                r++;
+            }
+          rs.insert (r);
+          reachability[r].push_back (&nb_tuple);
+        }
+      
+      // 4.2. Select as a MPR the node with highest N_willingness among
+      // the nodes in N with non-zero reachability. In case of
+      // multiple choice select the node which provides
+      // reachability to the maximum number of nodes in N2. In
+      // case of multiple nodes providing the same amount of
+      // reachability, select the node as MPR whose D(y) is
+      // greater. Remove the nodes from N2 which are now covered
+      // by a node in the MPR set.
+      NeighborTuple const *max = NULL;
+      int max_r = 0;
+      for (std::set<int>::iterator it = rs.begin (); it != rs.end (); it++)
+        {
+          int r = *it;
+          if (r > 0)
+            {
+              for (std::vector<const NeighborTuple *>::iterator it2 = reachability[r].begin ();
+                   it2 != reachability[r].end ();
+                   it2++)
+                {
+                  const NeighborTuple *nb_tuple = *it2;
+                  if (max == NULL || nb_tuple->willingness > max->willingness)
+                    {
+                      max = nb_tuple;
+                      max_r = r;
+                    }
+                  else if (nb_tuple->willingness == max->willingness)
+                    {
+                      if (r > max_r)
+                        {
+                          max = nb_tuple;
+                          max_r = r;
+                        }
+                      else if (r == max_r)
+                        {
+                          if (Degree (*nb_tuple) > Degree (*max))
+                            {
+                              max = nb_tuple;
+                              max_r = r;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+      if (max != NULL)
+        {
+          m_state.InsertMprAddress (max->neighborMainAddr);
+          std::set<Ipv4Address> nb2hop_addrs;
+          for (TwoHopNeighborSet::iterator it = N2.begin ();
+               it != N2.end (); it++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple = *it;
+              if (nb2hop_tuple.neighborMainAddr == max->neighborMainAddr)
+                {
+                  nb2hop_addrs.insert (nb2hop_tuple.twoHopNeighborAddr);
+                  it = N2.erase (it);
+                  it--;
+                }
+            }
+          for (TwoHopNeighborSet::iterator it = N2.begin ();
+               it != N2.end (); it++)
+            {
+              TwoHopNeighborTuple const &nb2hop_tuple = *it;
+              std::set<Ipv4Address>::iterator it2 =
+                nb2hop_addrs.find (nb2hop_tuple.twoHopNeighborAddr);
+              if (it2 != nb2hop_addrs.end ())
+                {
+                  it = N2.erase (it);
+                  it--;
+                }
+            }
+        }
+    }
+}
+
+///
+/// \brief Gets the main address associated with a given interface address.
+///
+/// \param iface_addr the interface address.
+/// \return the corresponding main address.
+///
+Ipv4Address
+AgentImpl::GetMainAddress (Ipv4Address iface_addr) const
+{
+  const IfaceAssocTuple *tuple =
+    m_state.FindIfaceAssocTuple (iface_addr);
+  
+  if (tuple != NULL)
+    return tuple->mainAddr;
+  else
+    return iface_addr;
+}
+
+///
+/// \brief Creates the routing table of the node following RFC 3626 hints.
+///
+void
+AgentImpl::RoutingTableComputation ()
+{
+  // 1. All the entries from the routing table are removed.
+  m_routingTable->Clear ();
+	
+  // 2. The new routing entries are added starting with the
+  // symmetric neighbors (h=1) as the destination nodes.
+  for (NeighborSet::const_iterator it = m_state.GetNeighbors ().begin ();
+       it != m_state.GetNeighbors ().end(); it++)
+    {
+      NeighborTuple const &nb_tuple = *it;
+      if (nb_tuple.status == NeighborTuple::STATUS_SYM)
+        {
+          bool nb_main_addr = false;
+          const LinkTuple *lt = NULL;
+          for (LinkSet::const_iterator it2 = m_state.GetLinks ().begin();
+               it2 != m_state.GetLinks ().end(); it2++)
+            {
+              LinkTuple const &link_tuple = *it2;
+              if ((GetMainAddress (link_tuple.neighborIfaceAddr)
+                   == nb_tuple.neighborMainAddr)
+                  && link_tuple.time >= Simulator::Now ())
+                {
+                  lt = &link_tuple;
+                  m_routingTable->AddEntry (link_tuple.neighborIfaceAddr,
+                                            link_tuple.neighborIfaceAddr,
+                                            link_tuple.localIfaceAddr,
+                                            1);
+                  if (link_tuple.neighborIfaceAddr
+                      == nb_tuple.neighborMainAddr)
+                    nb_main_addr = true;
+                }
+            }
+          if (!nb_main_addr && lt != NULL)
+            {
+              m_routingTable->AddEntry(nb_tuple.neighborMainAddr,
+                                       lt->neighborIfaceAddr,
+                                       lt->localIfaceAddr,
+                                       1);
+            }
+        }
+    }
+  
+  // N2 is the set of 2-hop neighbors reachable from this node, excluding:
+  // (i)   the nodes only reachable by members of N with willingness WILL_NEVER
+  // (ii)  the node performing the computation
+  // (iii) all the symmetric neighbors: the nodes for which there exists a symmetric
+  //       link to this node on some interface.
+  for (TwoHopNeighborSet::const_iterator it = m_state.GetTwoHopNeighbors ().begin ();
+       it != m_state.GetTwoHopNeighbors ().end (); it++)
+    {
+      TwoHopNeighborTuple const &nb2hop_tuple = *it;
+      bool ok = true;
+      const NeighborTuple *nb_tuple = m_state.FindSymNeighborTuple
+        (nb2hop_tuple.neighborMainAddr);
+      if (nb_tuple == NULL)
+        ok = false;
+      else
+        {
+          nb_tuple = m_state.FindNeighborTuple (nb2hop_tuple.neighborMainAddr,
+                                                OLSR_WILL_NEVER);
+          if (nb_tuple != NULL)
+            ok = false;
+          else
+            {
+              nb_tuple = m_state.FindSymNeighborTuple (nb2hop_tuple.twoHopNeighborAddr);
+
+              if (nb_tuple != NULL)
+                ok = false;
+            }
+        }
+
+      // 3. For each node in N2 create a new entry in the routing table
+      if (ok)
+        {
+          RoutingTableEntry entry;
+          bool foundEntry = m_routingTable->Lookup (nb2hop_tuple.neighborMainAddr, entry);
+          if (!foundEntry)
+            NS_FATAL_ERROR ("m_routingTable->Lookup failure");
+
+          m_routingTable->AddEntry (nb2hop_tuple.twoHopNeighborAddr,
+                                    entry.nextAddr,
+                                    entry.interface,
+                                    2);
+        }
+    }
+  
+  for (uint32_t h = 2; ; h++)
+    {
+      bool added = false;
+		
+      // 4.1. For each topology entry in the topology table, if its
+      // T_dest_addr does not correspond to R_dest_addr of any
+      // route entry in the routing table AND its T_last_addr
+      // corresponds to R_dest_addr of a route entry whose R_dist
+      // is equal to h, then a new route entry MUST be recorded in
+      // the routing table (if it does not already exist)
+      for (TopologySet::const_iterator it = m_state.GetTopologySet ().begin ();
+           it != m_state.GetTopologySet ().end ();
+           it++)
+        {
+          TopologyTuple const &topology_tuple = *it;
+          RoutingTableEntry entry1, entry2;
+          bool have_entry1 = m_routingTable->Lookup (topology_tuple.destAddr, entry1);
+          bool have_entry2 = m_routingTable->Lookup (topology_tuple.lastAddr, entry2);
+          if (!have_entry1 && have_entry2 && entry2.distance == h)
+            {
+              m_routingTable->AddEntry (topology_tuple.destAddr,
+                                        entry2.nextAddr,
+                                        entry2.interface,
+                                        h + 1);
+              added = true;
+            }
+        }
+		
+      // 5. For each entry in the multiple interface association base
+      // where there exists a routing entry such that:
+      //	R_dest_addr  == I_main_addr  (of the multiple interface association entry)
+      // AND there is no routing entry such that:
+      //	R_dest_addr  == I_iface_addr
+      // then a route entry is created in the routing table
+      for (IfaceAssocSet::const_iterator it = m_state.GetIfaceAssocSet ().begin ();
+           it != m_state.GetIfaceAssocSet ().end ();
+           it++)
+        {
+          IfaceAssocTuple const &tuple = *it;
+          RoutingTableEntry entry1, entry2;
+          bool have_entry1 = m_routingTable->Lookup (tuple.mainAddr, entry1);
+          bool have_entry2 = m_routingTable->Lookup (tuple.ifaceAddr, entry2);
+          if (have_entry1 && !have_entry2)
+            {
+              m_routingTable->AddEntry (tuple.ifaceAddr,
+                                        entry1.nextAddr,
+                                        entry1.interface,
+                                        entry1.distance);
+              added = true;
+            }
+        }
+
+      if (!added)
+        break;
+    }
+}
+
+
+///
+/// \brief Processes a HELLO message following RFC 3626 specification.
+///
+/// Link sensing and population of the Neighbor Set, 2-hop Neighbor Set and MPR
+/// Selector Set are performed.
+///
+/// \param msg the %OLSR message which contains the HELLO message.
+/// \param receiver_iface the address of the interface where the message was received from.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+AgentImpl::ProcessHello (const olsr::MessageHeader &msg,
+                             const Ipv4Address &receiverIface,
+                             const Ipv4Address &senderIface)
+{
+  const olsr::MessageHeader::Hello &hello = msg.GetHello ();
+  LinkSensing (msg, hello, receiverIface, senderIface);
+  PopulateNeighborSet (msg, hello);
+  PopulateTwoHopNeighborSet (msg, hello);
+  MprComputation ();
+  PopulateMprSelectorSet (msg, hello);
+}
+
+///
+/// \brief Processes a TC message following RFC 3626 specification.
+///
+/// The Topology Set is updated (if needed) with the information of
+/// the received TC message.
+///
+/// \param msg the %OLSR message which contains the TC message.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+AgentImpl::ProcessTc (const olsr::MessageHeader &msg,
+                          const Ipv4Address &senderIface)
+{
+  const olsr::MessageHeader::Tc &tc = msg.GetTc ();
+  Time now = Simulator::Now ();
+	
+  // 1. If the sender interface of this message is not in the symmetric
+  // 1-hop neighborhood of this node, the message MUST be discarded.
+  LinkTuple *link_tuple = m_state.FindSymLinkTuple (senderIface, now);
+  if (link_tuple == NULL)
+    return;
+	
+  // 2. If there exist some tuple in the topology set where:
+  // 	T_last_addr == originator address AND
+  // 	T_seq       >  ANSN,
+  // then further processing of this TC message MUST NOT be
+  // performed.
+  TopologyTuple *topologyTuple =
+    m_state.FindNewerTopologyTuple (msg.GetOriginatorAddress (), tc.ansn);
+  if (topologyTuple != NULL)
+    return;
+	
+  // 3. All tuples in the topology set where:
+  //	T_last_addr == originator address AND
+  //	T_seq       <  ANSN
+  // MUST be removed from the topology set.
+  m_state.EraseOlderTopologyTuples (msg.GetOriginatorAddress (), tc.ansn);
+
+  // 4. For each of the advertised neighbor main address received in
+  // the TC message:
+  for (std::vector<Ipv4Address>::const_iterator i = tc.neighborAddresses.begin ();
+       i != tc.neighborAddresses.end (); i++)
+    {
+      const Ipv4Address &addr = *i;
+      // 4.1. If there exist some tuple in the topology set where:
+      // 	T_dest_addr == advertised neighbor main address, AND
+      // 	T_last_addr == originator address,
+      // then the holding time of that tuple MUST be set to:
+      // 	T_time      =  current time + validity time.
+      TopologyTuple *topologyTuple =
+        m_state.FindTopologyTuple (addr, msg.GetOriginatorAddress ());
+
+      if (topologyTuple != NULL)
+        {
+          topologyTuple->expirationTime = now + msg.GetVTime ();
+        }
+      else
+        {
+          // 4.2. Otherwise, a new tuple MUST be recorded in the topology
+          // set where:
+          //	T_dest_addr = advertised neighbor main address,
+          //	T_last_addr = originator address,
+          //	T_seq       = ANSN,
+          //	T_time      = current time + validity time.
+          TopologyTuple topologyTuple;;
+          topologyTuple.destAddr = addr;
+          topologyTuple.lastAddr = msg.GetOriginatorAddress ();
+          topologyTuple.sequenceNumber = tc.ansn;
+          topologyTuple.expirationTime = now + msg.GetVTime ();
+          AddTopologyTuple (topologyTuple);
+
+          // Schedules topology tuple deletion
+          m_events.Track (Simulator::Schedule (DELAY (topologyTuple.expirationTime),
+                                               &AgentImpl::TopologyTupleTimerExpire,
+                                               this, topologyTuple));
+        }
+    }
+}
+
+///
+/// \brief Processes a MID message following RFC 3626 specification.
+///
+/// The Interface Association Set is updated (if needed) with the information
+/// of the received MID message.
+///
+/// \param msg the %OLSR message which contains the MID message.
+/// \param sender_iface the address of the interface where the message was sent from.
+///
+void
+AgentImpl::ProcessMid (const olsr::MessageHeader &msg,
+                           const Ipv4Address &senderIface)
+{
+  const olsr::MessageHeader::Mid &mid = msg.GetMid ();
+  Time now = Simulator::Now ();
+	
+  // 1. If the sender interface of this message is not in the symmetric
+  // 1-hop neighborhood of this node, the message MUST be discarded.
+  LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderIface, now);
+  if (linkTuple == NULL)
+    return;
+	
+  // 2. For each interface address listed in the MID message
+  for (std::vector<Ipv4Address>::const_iterator i = mid.interfaceAddresses.begin ();
+       i != mid.interfaceAddresses.end (); i++)
+    {
+      bool updated = false;
+      IfaceAssocSet &ifaceAssoc = m_state.GetIfaceAssocSetMutable ();
+      for (IfaceAssocSet::iterator tuple = ifaceAssoc.begin();
+           tuple != ifaceAssoc.end(); tuple++)
+        {
+          if (tuple->ifaceAddr == *i
+              && tuple->mainAddr == msg.GetOriginatorAddress ())
+            {
+              tuple->time = now + msg.GetVTime ();
+              updated = true;
+            }
+        }
+      if (!updated)
+        {
+          IfaceAssocTuple tuple;
+          tuple.ifaceAddr = *i;
+          tuple.mainAddr = msg.GetOriginatorAddress ();
+          tuple.time = now + msg.GetVTime ();
+          AddIfaceAssocTuple (tuple);
+          // Schedules iface association tuple deletion
+          Simulator::Schedule (DELAY (tuple.time),
+                               &AgentImpl::IfaceAssocTupleTimerExpire, this, tuple);
+        }
+    }
+}
+
+
+///
+/// \brief OLSR's default forwarding algorithm.
+///
+/// See RFC 3626 for details.
+///
+/// \param p the %OLSR packet which has been received.
+/// \param msg the %OLSR message which must be forwarded.
+/// \param dup_tuple NULL if the message has never been considered for forwarding,
+/// or a duplicate tuple in other case.
+/// \param local_iface the address of the interface where the message was received from.
+///
+void
+AgentImpl::ForwardDefault (olsr::MessageHeader olsrMessage,
+                               DuplicateTuple *duplicated,
+                               const Ipv4Address &localIface,
+                               const Ipv4Address &senderAddress)
+{
+  Time now = Simulator::Now ();
+  
+  // If the sender interface address is not in the symmetric
+  // 1-hop neighborhood the message must not be forwarded
+  LinkTuple *linkTuple = m_state.FindSymLinkTuple (senderAddress, now);
+  if (linkTuple == NULL)
+    return;
+
+  // If the message has already been considered for forwarding,
+  // it must not be retransmitted again
+  if (duplicated != NULL && duplicated->retransmitted)
+    {
+//       debug("%f: Node %d does not forward a message received"
+//             " from %d because it is duplicated\n",
+//             Simulator::Now (),
+//             OLSR::node_id(ra_addr()),
+//             OLSR::node_id(dup_tuple->addr()));
+      return;
+    }
+	
+  // If the sender interface address is an interface address
+  // of a MPR selector of this node and ttl is greater than 1,
+  // the message must be retransmitted
+  bool retransmitted = false;
+  if (olsrMessage.GetTimeToLive () > 1)
+    {
+      MprSelectorTuple *mprselTuple =
+        m_state.FindMprSelectorTuple (GetMainAddress (senderAddress));
+      if (mprselTuple != NULL)
+        {
+          olsrMessage.SetTimeToLive (olsrMessage.GetTimeToLive () - 1);
+          olsrMessage.SetHopCount (olsrMessage.GetHopCount () + 1);
+          // We have to introduce a random delay to avoid
+          // synchronization with neighbors.
+          QueueMessage (olsrMessage, JITTER);
+          retransmitted = true;
+        }
+    }
+	
+  // Update duplicate tuple...
+  if (duplicated != NULL)
+    {
+      duplicated->expirationTime = now + OLSR_DUP_HOLD_TIME;
+      duplicated->retransmitted = retransmitted;
+      duplicated->ifaceList.push_back (localIface);
+    }
+  // ...or create a new one
+  else
+    {
+      DuplicateTuple newDup;
+      newDup.address = olsrMessage.GetOriginatorAddress ();
+      newDup.sequenceNumber = olsrMessage.GetMessageSequenceNumber ();
+      newDup.expirationTime = now + OLSR_DUP_HOLD_TIME;
+      newDup.retransmitted = retransmitted;
+      newDup.ifaceList.push_back (localIface);
+      AddDuplicateTuple (newDup);
+      // Schedule dup tuple deletion
+      Simulator::Schedule (OLSR_DUP_HOLD_TIME,
+                           &AgentImpl::DupTupleTimerExpire, this, newDup);
+    }
+}
+
+///
+/// \brief Enques an %OLSR message which will be sent with a delay of (0, delay].
+///
+/// This buffering system is used in order to piggyback several %OLSR messages in
+/// a same %OLSR packet.
+///
+/// \param msg the %OLSR message which must be sent.
+/// \param delay maximum delay the %OLSR message is going to be buffered.
+///
+void
+AgentImpl::QueueMessage (const olsr::MessageHeader &message, Time delay)
+{
+  m_queuedMessages.push_back (message);
+  if (not m_queuedMessagesTimer.IsRunning ())
+    {
+      m_queuedMessagesTimer.SetDelay (delay);
+      m_queuedMessagesTimer.Schedule ();
+    }
+}
+
+void
+AgentImpl::SendPacket (Packet packet, const MessageList &containedMessages)
+{
+  NS_LOG_DEBUG ("OLSR node " << m_mainAddress << " sending a OLSR packet");
+
+  // Add a header
+  olsr::PacketHeader header;
+  header.SetPacketLength (header.GetSerializedSize () + packet.GetSize ());
+  header.SetPacketSequenceNumber (GetPacketSequenceNumber ());
+  packet.AddHeader (header);
+
+  // Trace it
+  m_txPacketTrace (header, containedMessages);
+
+  // Send it
+  m_sendSocket->Send (packet);
+}
+
+///
+/// \brief Creates as many %OLSR packets as needed in order to send all buffered
+/// %OLSR messages.
+///
+/// Maximum number of messages which can be contained in an %OLSR packet is
+/// dictated by OLSR_MAX_MSGS constant.
+///
+void
+AgentImpl::SendQueuedMessages ()
+{
+  Packet packet;
+  int numMessages = 0;
+
+  NS_LOG_DEBUG ("Olsr node " << m_mainAddress << ": SendQueuedMessages");
+
+  MessageList msglist;
+
+  for (std::vector<olsr::MessageHeader>::const_iterator message = m_queuedMessages.begin ();
+       message != m_queuedMessages.end ();
+       message++)
+    {
+      Packet p;
+      p.AddHeader (*message);
+      packet.AddAtEnd (p);
+      msglist.push_back (*message);
+      if (++numMessages == OLSR_MAX_MSGS)
+        {
+          SendPacket (packet, msglist);
+          msglist.clear ();
+          // Reset variables for next packet
+          numMessages = 0;
+          packet = Packet ();
+        }
+    }
+
+  if (packet.GetSize ())
+    {
+      SendPacket (packet, msglist);
+    }
+
+  m_queuedMessages.clear ();
+}
+
+///
+/// \brief Creates a new %OLSR HELLO message which is buffered for being sent later on.
+///
+void
+AgentImpl::SendHello ()
+{
+  olsr::MessageHeader msg;
+  Time now = Simulator::Now ();
+
+  msg.SetVTime (OLSR_NEIGHB_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (1);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+  olsr::MessageHeader::Hello &hello = msg.GetHello ();
+
+  hello.SetHTime (m_helloInterval);
+  hello.willingness = m_willingness;
+
+  std::vector<olsr::MessageHeader::Hello::LinkMessage>
+    &linkMessages = hello.linkMessages;
+	
+  for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
+       link_tuple != m_state.GetLinks ().end (); link_tuple++)
+    {
+      if (not (link_tuple->localIfaceAddr == m_mainAddress
+               && link_tuple->time >= now))
+        continue;
+
+      uint8_t link_type, nb_type = 0xff;
+			
+      // Establishes link type
+      if (m_useL2Notifications && link_tuple->lostTime >= now)
+        {
+          link_type = OLSR_LOST_LINK;
+        }
+      else if (link_tuple->symTime >= now)
+        {
+          link_type = OLSR_SYM_LINK;
+        }
+      else if (link_tuple->asymTime >= now)
+        {
+          link_type = OLSR_ASYM_LINK;
+        }
+      else
+        {
+          link_type = OLSR_LOST_LINK;
+        }
+      // Establishes neighbor type.
+      if (m_state.FindMprAddress (GetMainAddress (link_tuple->neighborIfaceAddr)))
+        {
+          nb_type = OLSR_MPR_NEIGH;
+        }
+      else
+        {
+          bool ok = false;
+          for (NeighborSet::const_iterator nb_tuple = m_state.GetNeighbors ().begin ();
+               nb_tuple != m_state.GetNeighbors ().end ();
+               nb_tuple++)
+            {
+              if (nb_tuple->neighborMainAddr == link_tuple->neighborIfaceAddr)
+                {
+                  if (nb_tuple->status == NeighborTuple::STATUS_SYM)
+                    {
+                      nb_type = OLSR_SYM_NEIGH;
+                    }
+                  else if (nb_tuple->status == NeighborTuple::STATUS_NOT_SYM)
+                    {
+                      nb_type = OLSR_NOT_NEIGH;
+                    }
+                  else
+                    {
+                      NS_ASSERT (!"There is a neighbor tuple with an unknown status!\n");
+                    }
+                  ok = true;
+                  break;
+                }
+            }
+          if (!ok)
+            {
+              NS_ASSERT (!"Link tuple has no corresponding neighbor tuple\n");
+            }
+        }
+
+      olsr::MessageHeader::Hello::LinkMessage linkMessage;
+      linkMessage.linkCode = (link_type & 0x03) | ((nb_type << 2) & 0x0f);
+      linkMessage.neighborInterfaceAddresses.push_back
+        (link_tuple->neighborIfaceAddr);
+
+      std::vector<Ipv4Address> interfaces =
+        m_state.FindNeighborInterfaces (link_tuple->neighborIfaceAddr);
+
+      linkMessage.neighborInterfaceAddresses.insert
+        (linkMessage.neighborInterfaceAddresses.end (),
+         interfaces.begin (), interfaces.end ());
+
+      linkMessages.push_back (linkMessage);
+    }
+  NS_LOG_DEBUG ("OLSR HELLO message size: " << int (msg.GetSerializedSize ())
+                << " (with " << int (linkMessages.size ()) << " link messages)");
+  QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR TC message which is buffered for being sent later on.
+///
+void
+AgentImpl::SendTc ()
+{
+  olsr::MessageHeader msg;
+
+  msg.SetVTime (OLSR_TOP_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (255);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+  
+  olsr::MessageHeader::Tc &tc = msg.GetTc ();
+  tc.ansn = m_ansn;
+  for (MprSelectorSet::const_iterator mprsel_tuple = m_state.GetMprSelectors ().begin();
+       mprsel_tuple != m_state.GetMprSelectors ().end(); mprsel_tuple++)
+    {
+      tc.neighborAddresses.push_back (mprsel_tuple->mainAddr);
+    }
+  QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief Creates a new %OLSR MID message which is buffered for being sent later on.
+///
+void
+AgentImpl::SendMid ()
+{
+  olsr::MessageHeader msg;
+  olsr::MessageHeader::Mid &mid = msg.GetMid ();
+
+  // A node which has only a single interface address participating in
+  // the MANET (i.e., running OLSR), MUST NOT generate any MID
+  // message.
+
+  // A node with several interfaces, where only one is participating
+  // in the MANET and running OLSR (e.g., a node is connected to a
+  // wired network as well as to a MANET) MUST NOT generate any MID
+  // messages.
+
+  // A node with several interfaces, where more than one is
+  // participating in the MANET and running OLSR MUST generate MID
+  // messages as specified.
+
+  // [ Note: assuming here that all interfaces participate in the
+  // MANET; later we may want to make this configurable. ]
+
+  Ipv4Address loopback ("127.0.0.1");
+  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+    {
+      Ipv4Address addr = m_ipv4->GetAddress (i);
+      if (addr != m_mainAddress && addr != loopback)
+        mid.interfaceAddresses.push_back (addr);
+    }
+  if (mid.interfaceAddresses.size () == 0)
+    return;
+  
+  msg.SetVTime (OLSR_MID_HOLD_TIME);
+  msg.SetOriginatorAddress (m_mainAddress);
+  msg.SetTimeToLive (255);
+  msg.SetHopCount (0);
+  msg.SetMessageSequenceNumber (GetMessageSequenceNumber ());
+
+  QueueMessage (msg, JITTER);
+}
+
+///
+/// \brief	Updates Link Set according to a new received HELLO message (following RFC 3626
+///		specification). Neighbor Set is also updated if needed.
+void
+AgentImpl::LinkSensing (const olsr::MessageHeader &msg,
+                            const olsr::MessageHeader::Hello &hello,
+                            const Ipv4Address &receiverIface,
+                            const Ipv4Address &senderIface)
+{
+  Time now = Simulator::Now ();
+  bool updated = false;
+  bool created = false;
+	
+  LinkTuple *link_tuple = m_state.FindLinkTuple (senderIface);
+  if (link_tuple == NULL)
+    {
+      LinkTuple newLinkTuple;
+      // We have to create a new tuple
+      newLinkTuple.neighborIfaceAddr = senderIface;
+      newLinkTuple.localIfaceAddr = receiverIface;
+      newLinkTuple.symTime = now - Seconds (1);
+      newLinkTuple.lostTime = Seconds (0);
+      newLinkTuple.time = now + msg.GetVTime ();
+      link_tuple = &AddLinkTuple (newLinkTuple, hello.willingness);
+      created = true;
+    }
+  else
+    updated = true;
+	
+  link_tuple->asymTime = now + msg.GetVTime ();
+  for (std::vector<olsr::MessageHeader::Hello::LinkMessage>::const_iterator linkMessage =
+         hello.linkMessages.begin ();
+       linkMessage != hello.linkMessages.end ();
+       linkMessage++)
+    {
+      int lt = linkMessage->linkCode & 0x03; // Link Type
+      int nt = linkMessage->linkCode >> 2; // Neighbor Type
+      
+      // We must not process invalid advertised links
+      if ((lt == OLSR_SYM_LINK && nt == OLSR_NOT_NEIGH) ||
+          (nt != OLSR_SYM_NEIGH && nt != OLSR_MPR_NEIGH
+           && nt != OLSR_NOT_NEIGH))
+        {
+          continue;
+        }
+		
+      for (std::vector<Ipv4Address>::const_iterator neighIfaceAddr =
+             linkMessage->neighborInterfaceAddresses.begin ();
+           neighIfaceAddr != linkMessage->neighborInterfaceAddresses.end ();
+           neighIfaceAddr++)
+        {
+          if (*neighIfaceAddr == receiverIface)
+            {
+              if (lt == OLSR_LOST_LINK)
+                {
+                  link_tuple->symTime = now - Seconds (1);
+                  updated = true;
+                }
+              else if (lt == OLSR_SYM_LINK || lt == OLSR_ASYM_LINK)
+                {
+                  link_tuple->symTime = now + msg.GetVTime ();
+                  link_tuple->time = link_tuple->symTime + OLSR_NEIGHB_HOLD_TIME;
+                  link_tuple->lostTime = Seconds (0);
+                  updated = true;
+                }
+              break;
+            }
+        }
+    }
+  link_tuple->time = std::max(link_tuple->time, link_tuple->asymTime);
+
+  if (updated)
+    LinkTupleUpdated (*link_tuple);
+
+  // Schedules link tuple deletion
+  if (created && link_tuple != NULL)
+    {
+      m_events.Track (Simulator::Schedule (DELAY (std::min (link_tuple->time, link_tuple->symTime)),
+                                           &AgentImpl::LinkTupleTimerExpire, this, *link_tuple));
+    }
+}
+
+///
+/// \brief	Updates the Neighbor Set according to the information contained in a new received
+///		HELLO message (following RFC 3626).
+void
+AgentImpl::PopulateNeighborSet (const olsr::MessageHeader &msg,
+                                    const olsr::MessageHeader::Hello &hello)
+{
+  NeighborTuple *nb_tuple = m_state.FindNeighborTuple (msg.GetOriginatorAddress ());
+  if (nb_tuple != NULL)
+    nb_tuple->willingness = hello.willingness;
+}
+
+
+///
+/// \brief	Updates the 2-hop Neighbor Set according to the information contained in a new
+///		received HELLO message (following RFC 3626).
+void
+AgentImpl::PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg,
+                                          const olsr::MessageHeader::Hello &hello)
+{
+  Time now = Simulator::Now ();
+	
+  for (LinkSet::const_iterator link_tuple = m_state.GetLinks ().begin ();
+       link_tuple != m_state.GetLinks ().end (); link_tuple++)
+    {
+      if (GetMainAddress (link_tuple->neighborIfaceAddr) == msg.GetOriginatorAddress ())
+        {
+          if (link_tuple->symTime >= now)
+            {
+              typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
+              for (LinkMessageVec::const_iterator linkMessage =
+                     hello.linkMessages.begin ();
+                   linkMessage != hello.linkMessages.end ();
+                   linkMessage++)
+                {
+                  int nt = linkMessage->linkCode >> 2;
+
+                  for (std::vector<Ipv4Address>::const_iterator nb2hop_addr =
+                         linkMessage->neighborInterfaceAddresses.begin ();
+                       nb2hop_addr != linkMessage->neighborInterfaceAddresses.end ();
+                       nb2hop_addr++)
+                    {
+                      if (nt == OLSR_SYM_NEIGH || nt == OLSR_MPR_NEIGH)
+                        {
+                          // if the main address of the 2-hop
+                          // neighbor address = main address of
+                          // the receiving node: silently
+                          // discard the 2-hop neighbor address
+                          if (*nb2hop_addr != m_routingAgentAddr)
+                            {
+                              // Otherwise, a 2-hop tuple is created
+                              TwoHopNeighborTuple *nb2hop_tuple =
+                                m_state.FindTwoHopNeighborTuple (msg.GetOriginatorAddress (),
+                                                                 *nb2hop_addr);
+                              if (nb2hop_tuple == NULL)
+                                {
+                                  TwoHopNeighborTuple new_nb2hop_tuple;
+                                  new_nb2hop_tuple.neighborMainAddr = msg.GetOriginatorAddress ();
+                                  new_nb2hop_tuple.twoHopNeighborAddr = *nb2hop_addr;
+                                  AddTwoHopNeighborTuple (new_nb2hop_tuple);
+                                  new_nb2hop_tuple.expirationTime =
+                                    now + msg.GetVTime ();
+                                  // Schedules nb2hop tuple
+                                  // deletion
+                                  m_events.Track (Simulator::Schedule (DELAY (new_nb2hop_tuple.expirationTime),
+                                                                       &AgentImpl::Nb2hopTupleTimerExpire, this,
+                                                                       new_nb2hop_tuple));
+                                }
+                              else
+                                {
+                                  nb2hop_tuple->expirationTime =
+                                    now + msg.GetVTime ();
+                                }
+								
+                            }
+                        }
+                      else if (nt == OLSR_NOT_NEIGH)
+                        {
+                          // For each 2-hop node listed in the HELLO
+                          // message with Neighbor Type equal to
+                          // NOT_NEIGH all 2-hop tuples where:
+                          // N_neighbor_main_addr == Originator
+                          // Address AND N_2hop_addr  == main address
+                          // of the 2-hop neighbor are deleted.
+                          m_state.EraseTwoHopNeighborTuples
+                            (msg.GetOriginatorAddress (), *nb2hop_addr);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+
+///
+/// \brief	Updates the MPR Selector Set according to the information contained in a new
+///		received HELLO message (following RFC 3626).
+void
+AgentImpl::PopulateMprSelectorSet (const olsr::MessageHeader &msg,
+                                       const olsr::MessageHeader::Hello &hello)
+{
+  Time now = Simulator::Now ();
+	
+  typedef std::vector<olsr::MessageHeader::Hello::LinkMessage> LinkMessageVec;
+  for (LinkMessageVec::const_iterator linkMessage = hello.linkMessages.begin ();
+       linkMessage != hello.linkMessages.end ();
+       linkMessage++)
+    {
+      int nt = linkMessage->linkCode >> 2;
+      if (nt == OLSR_MPR_NEIGH)
+        {
+          for (std::vector<Ipv4Address>::const_iterator nb_iface_addr =
+                 linkMessage->neighborInterfaceAddresses.begin ();
+               nb_iface_addr != linkMessage->neighborInterfaceAddresses.end ();
+               nb_iface_addr++)
+            {
+              if (*nb_iface_addr == m_mainAddress)
+                {
+                  // We must create a new entry into the mpr selector set
+                  MprSelectorTuple *existing_mprsel_tuple =
+                    m_state.FindMprSelectorTuple (msg.GetOriginatorAddress ());
+                  if (existing_mprsel_tuple == NULL)
+                    {
+                      MprSelectorTuple mprsel_tuple;
+
+                      mprsel_tuple.mainAddr = msg.GetOriginatorAddress ();
+                      mprsel_tuple.expirationTime = now + msg.GetVTime ();
+                      AddMprSelectorTuple (mprsel_tuple);
+
+                      // Schedules mpr selector tuple deletion
+                      m_events.Track (Simulator::Schedule
+                                      (DELAY (mprsel_tuple.expirationTime),
+                                       &AgentImpl::MprSelTupleTimerExpire, this,
+                                       mprsel_tuple));
+                    }
+                  else
+                    {
+                      existing_mprsel_tuple->expirationTime = now + msg.GetVTime ();
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+#if 0
+///
+/// \brief	Drops a given packet because it couldn't be delivered to the corresponding
+///		destination by the MAC layer. This may cause a neighbor loss, and appropiate
+///		actions are then taken.
+///
+/// \param p the packet which couldn't be delivered by the MAC layer.
+///
+void
+OLSR::mac_failed(Packet* p) {
+	double now		= Simulator::Now ();
+	struct hdr_ip* ih	= HDR_IP(p);
+	struct hdr_cmn* ch	= HDR_CMN(p);
+	
+	debug("%f: Node %d MAC Layer detects a breakage on link to %d\n",
+		now,
+		OLSR::node_id(ra_addr()),
+		OLSR::node_id(ch->next_hop()));
+	
+	if ((u_int32_t)ih->daddr() == IP_BROADCAST) {
+		drop(p, DROP_RTR_MAC_CALLBACK);
+		return;
+	}
+	
+	OLSR_link_tuple* link_tuple = state_.find_link_tuple(ch->next_hop());
+	if (link_tuple != NULL) {
+		link_tuple->lost_time()	= now + OLSR_NEIGHB_HOLD_TIME;
+		link_tuple->time()	= now + OLSR_NEIGHB_HOLD_TIME;
+		nb_loss(link_tuple);
+	}
+	drop(p, DROP_RTR_MAC_CALLBACK);
+}
+#endif
+
+
+
+
+///
+/// \brief Performs all actions needed when a neighbor loss occurs.
+///
+/// Neighbor Set, 2-hop Neighbor Set, MPR Set and MPR Selector Set are updated.
+///
+/// \param tuple link tuple with the information of the link to the neighbor which has been lost.
+///
+void
+AgentImpl::NeighborLoss (const LinkTuple &tuple)
+{
+//   debug("%f: Node %d detects neighbor %d loss\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr));
+	
+  LinkTupleUpdated (tuple);
+  m_state.EraseTwoHopNeighborTuples (GetMainAddress (tuple.neighborIfaceAddr));
+  m_state.EraseMprSelectorTuples (GetMainAddress (tuple.neighborIfaceAddr));
+  
+  MprComputation();
+  RoutingTableComputation();
+}
+
+///
+/// \brief Adds a duplicate tuple to the Duplicate Set.
+///
+/// \param tuple the duplicate tuple to be added.
+///
+void
+AgentImpl::AddDuplicateTuple (const DuplicateTuple &tuple)
+{
+	/*debug("%f: Node %d adds dup tuple: addr = %d seq_num = %d\n",
+		Simulator::Now (),
+		OLSR::node_id(ra_addr()),
+		OLSR::node_id(tuple->addr()),
+		tuple->seq_num());*/
+  m_state.InsertDuplicateTuple (tuple);
+}
+
+///
+/// \brief Removes a duplicate tuple from the Duplicate Set.
+///
+/// \param tuple the duplicate tuple to be removed.
+///
+void
+AgentImpl::RemoveDuplicateTuple (const DuplicateTuple &tuple)
+{
+  /*debug("%f: Node %d removes dup tuple: addr = %d seq_num = %d\n",
+    Simulator::Now (),
+    OLSR::node_id(ra_addr()),
+    OLSR::node_id(tuple->addr()),
+    tuple->seq_num());*/
+  m_state.EraseDuplicateTuple (tuple);
+}
+
+///
+/// \brief Adds a link tuple to the Link Set (and an associated neighbor tuple to the Neighbor Set).
+///
+/// \param tuple the link tuple to be added.
+/// \param willingness willingness of the node which is going to be inserted in the Neighbor Set.
+///
+LinkTuple&
+AgentImpl::AddLinkTuple (const LinkTuple &tuple, uint8_t willingness)
+{
+//   debug("%f: Node %d adds link tuple: nb_addr = %d\n",
+//         now,
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr));
+  LinkTuple &addedLinkTuple = m_state.InsertLinkTuple (tuple);
+  // Creates associated neighbor tuple
+  NeighborTuple nb_tuple;
+  nb_tuple.neighborMainAddr = GetMainAddress (tuple.neighborIfaceAddr);
+  nb_tuple.willingness = willingness;
+
+  if (tuple.symTime >= Simulator::Now ())
+    nb_tuple.status = NeighborTuple::STATUS_SYM;
+  else
+    nb_tuple.status = NeighborTuple::STATUS_NOT_SYM;
+
+  AddNeighborTuple (nb_tuple);
+  return addedLinkTuple;
+}
+
+///
+/// \brief Removes a link tuple from the Link Set.
+///
+/// \param tuple the link tuple to be removed.
+///
+void
+AgentImpl::RemoveLinkTuple (const LinkTuple &tuple)
+{
+//   nsaddr_t nb_addr	= get_main_addr(tuple->neighborIfaceAddr);
+//   double now		= Simulator::Now ();
+	
+//   debug("%f: Node %d removes link tuple: nb_addr = %d\n",
+//         now,
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr));
+	// Prints this here cause we are not actually calling rm_nb_tuple() (efficiency stuff)
+  // 	debug("%f: Node %d removes neighbor tuple: nb_addr = %d\n",
+  // 		now,
+  // 		OLSR::node_id(ra_addr()),
+  // 		OLSR::node_id(nb_addr));
+
+  m_state.EraseLinkTuple (tuple);
+  m_state.EraseNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+}
+
+///
+/// \brief	This function is invoked when a link tuple is updated. Its aim is to
+///		also update the corresponding neighbor tuple if it is needed.
+///
+/// \param tuple the link tuple which has been updated.
+///
+void
+AgentImpl::LinkTupleUpdated (const LinkTuple &tuple)
+{
+  // Each time a link tuple changes, the associated neighbor tuple must be recomputed
+  NeighborTuple *nb_tuple =
+    m_state.FindNeighborTuple (GetMainAddress (tuple.neighborIfaceAddr));
+  if (nb_tuple != NULL)
+    {
+      if (m_useL2Notifications && tuple.lostTime >= Simulator::Now ())
+        {
+          nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
+        }
+      else if (tuple.symTime >= Simulator::Now ())
+        {
+          nb_tuple->status = NeighborTuple::STATUS_SYM;
+        }
+      else
+        {
+          nb_tuple->status = NeighborTuple::STATUS_NOT_SYM;
+        }
+    }
+	
+//   debug("%f: Node %d has updated link tuple: nb_addr = %d status = %s\n",
+//         now,
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborIfaceAddr),
+//         ((nb_tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+
+}
+
+///
+/// \brief Adds a neighbor tuple to the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be added.
+///
+void
+AgentImpl::AddNeighborTuple (const NeighborTuple &tuple)
+{
+//   debug("%f: Node %d adds neighbor tuple: nb_addr = %d status = %s\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+  
+  m_state.InsertNeighborTuple (tuple);
+}
+
+///
+/// \brief Removes a neighbor tuple from the Neighbor Set.
+///
+/// \param tuple the neighbor tuple to be removed.
+///
+void
+AgentImpl::RemoveNeighborTuple (const NeighborTuple &tuple)
+{
+//   debug("%f: Node %d removes neighbor tuple: nb_addr = %d status = %s\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         ((tuple->status() == OLSR_STATUS_SYM) ? "sym" : "not_sym"));
+	
+  m_state.EraseNeighborTuple (tuple);
+}
+
+///
+/// \brief Adds a 2-hop neighbor tuple to the 2-hop Neighbor Set.
+///
+/// \param tuple the 2-hop neighbor tuple to be added.
+///
+void
+AgentImpl::AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+//   debug("%f: Node %d adds 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         OLSR::node_id(tuple->twoHopNeighborAddr));
+  
+  m_state.InsertTwoHopNeighborTuple (tuple);
+}
+
+///
+/// \brief Removes a 2-hop neighbor tuple from the 2-hop Neighbor Set.
+///
+/// \param tuple the 2-hop neighbor tuple to be removed.
+///
+void
+AgentImpl::RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+//   debug("%f: Node %d removes 2-hop neighbor tuple: nb_addr = %d nb2hop_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->neighborMainAddr),
+//         OLSR::node_id(tuple->twoHopNeighborAddr));
+
+  m_state.EraseTwoHopNeighborTuple (tuple);
+}
+
+///
+/// \brief Adds an MPR selector tuple to the MPR Selector Set.
+///
+/// Advertised Neighbor Sequence Number (ANSN) is also updated.
+///
+/// \param tuple the MPR selector tuple to be added.
+///
+void
+AgentImpl::AddMprSelectorTuple (const MprSelectorTuple  &tuple)
+{
+//   debug("%f: Node %d adds MPR selector tuple: nb_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()));
+  
+  m_state.InsertMprSelectorTuple (tuple);
+  m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
+}
+
+///
+/// \brief Removes an MPR selector tuple from the MPR Selector Set.
+///
+/// Advertised Neighbor Sequence Number (ANSN) is also updated.
+///
+/// \param tuple the MPR selector tuple to be removed.
+///
+void
+AgentImpl::RemoveMprSelectorTuple (const MprSelectorTuple &tuple)
+{
+//   debug("%f: Node %d removes MPR selector tuple: nb_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()));
+  
+  m_state.EraseMprSelectorTuple (tuple);
+  m_ansn = (m_ansn + 1) % (OLSR_MAX_SEQ_NUM + 1);
+}
+
+///
+/// \brief Adds a topology tuple to the Topology Set.
+///
+/// \param tuple the topology tuple to be added.
+///
+void
+AgentImpl::AddTopologyTuple (const TopologyTuple &tuple)
+{
+//   debug("%f: Node %d adds topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->dest_addr()),
+//         OLSR::node_id(tuple->last_addr()),
+//         tuple->seq());
+
+  m_state.InsertTopologyTuple(tuple);
+}
+
+///
+/// \brief Removes a topology tuple from the Topology Set.
+///
+/// \param tuple the topology tuple to be removed.
+///
+void
+AgentImpl::RemoveTopologyTuple (const TopologyTuple &tuple)
+{
+//   debug("%f: Node %d removes topology tuple: dest_addr = %d last_addr = %d seq = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->dest_addr()),
+//         OLSR::node_id(tuple->last_addr()),
+//         tuple->seq());
+
+  m_state.EraseTopologyTuple (tuple);
+}
+
+///
+/// \brief Adds an interface association tuple to the Interface Association Set.
+///
+/// \param tuple the interface association tuple to be added.
+///
+void
+AgentImpl::AddIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+//   debug("%f: Node %d adds iface association tuple: main_addr = %d iface_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()),
+//         OLSR::node_id(tuple->iface_addr()));
+
+  m_state.InsertIfaceAssocTuple (tuple);
+}
+
+///
+/// \brief Removes an interface association tuple from the Interface Association Set.
+///
+/// \param tuple the interface association tuple to be removed.
+///
+void
+AgentImpl::RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+//   debug("%f: Node %d removes iface association tuple: main_addr = %d iface_addr = %d\n",
+//         Simulator::Now (),
+//         OLSR::node_id(ra_addr()),
+//         OLSR::node_id(tuple->main_addr()),
+//         OLSR::node_id(tuple->iface_addr()));
+
+  m_state.EraseIfaceAssocTuple (tuple);
+}
+
+
+uint16_t AgentImpl::GetPacketSequenceNumber ()
+{
+  m_packetSequenceNumber = (m_packetSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
+  return m_packetSequenceNumber;
+}
+
+/// Increments message sequence number and returns the new value.
+uint16_t AgentImpl::GetMessageSequenceNumber ()
+{
+  m_messageSequenceNumber = (m_messageSequenceNumber + 1) % (OLSR_MAX_SEQ_NUM + 1);
+  return m_messageSequenceNumber;
+}
+
+
+///
+/// \brief Sends a HELLO message and reschedules the HELLO timer.
+/// \param e The event which has expired.
+///
+void
+AgentImpl::HelloTimerExpire ()
+{
+  SendHello ();
+  m_helloTimer.Schedule (m_helloInterval);
+}
+
+///
+/// \brief Sends a TC message (if there exists any MPR selector) and reschedules the TC timer.
+/// \param e The event which has expired.
+///
+void
+AgentImpl::TcTimerExpire ()
+{
+  if (m_state.GetMprSelectors ().size () > 0)
+    {
+      SendTc ();
+    }
+  m_tcTimer.Schedule (m_tcInterval);
+}
+
+///
+/// \brief Sends a MID message (if the node has more than one interface) and resets the MID timer.
+/// \warning Currently it does nothing because there is no support for multiple interfaces.
+/// \param e The event which has expired.
+///
+void
+AgentImpl::MidTimerExpire ()
+{
+  SendMid ();
+  m_midTimer.Schedule (m_midInterval);
+}
+
+///
+/// \brief Removes tuple if expired. Else timer is rescheduled to expire at tuple.expirationTime.
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param tuple The tuple which has expired.
+///
+void
+AgentImpl::DupTupleTimerExpire (DuplicateTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveDuplicateTuple (tuple);
+    }
+  else
+    {
+      m_events.Track (Simulator::Schedule (DELAY (tuple.expirationTime),
+                                           &AgentImpl::DupTupleTimerExpire, this,
+                                           tuple));
+    }
+}
+
+///
+/// \brief Removes tuple_ if expired. Else if symmetric time
+/// has expired then it is assumed a neighbor loss and agent_->nb_loss()
+/// is called. In this case the timer is rescheduled to expire at
+/// tuple_->time(). Otherwise the timer is rescheduled to expire at
+/// the minimum between tuple_->time() and tuple_->sym_time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+AgentImpl::LinkTupleTimerExpire (LinkTuple tuple)
+{
+  Time now = Simulator::Now ();
+	
+  if (tuple.time < now)
+    {
+      RemoveLinkTuple (tuple);
+    }
+  else if (tuple.symTime < now)
+    {
+      if (m_linkTupleTimerFirstTime)
+        m_linkTupleTimerFirstTime = false;
+      else
+        NeighborLoss (tuple);
+
+      m_events.Track (Simulator::Schedule (DELAY (tuple.time),
+                                           &AgentImpl::LinkTupleTimerExpire, this,
+                                           tuple));
+    }
+  else
+    {
+      m_events.Track (Simulator::Schedule (DELAY (std::min (tuple.time, tuple.symTime)),
+                                           &AgentImpl::LinkTupleTimerExpire, this,
+                                           tuple));
+    }
+}
+
+///
+/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+AgentImpl::Nb2hopTupleTimerExpire (TwoHopNeighborTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveTwoHopNeighborTuple (tuple);
+    }
+  else
+    {
+      m_events.Track (Simulator::Schedule (DELAY (tuple.expirationTime),
+                                           &AgentImpl::Nb2hopTupleTimerExpire,
+                                           this, tuple));
+    }
+}
+
+///
+/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+AgentImpl::MprSelTupleTimerExpire (MprSelectorTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveMprSelectorTuple (tuple);
+    }
+  else
+    {
+      m_events.Track (Simulator::Schedule (DELAY (tuple.expirationTime),
+                                           &AgentImpl::MprSelTupleTimerExpire,
+                                           this, tuple));
+    }
+}
+
+///
+/// \brief Removes tuple_ if expired. Else the timer is rescheduled to expire at tuple_->time().
+///
+/// The task of actually removing the tuple is left to the OLSR agent.
+///
+/// \param e The event which has expired.
+///
+void
+AgentImpl::TopologyTupleTimerExpire (TopologyTuple tuple)
+{
+  if (tuple.expirationTime < Simulator::Now ())
+    {
+      RemoveTopologyTuple (tuple);
+    }
+  else
+    {
+      m_events.Track (Simulator::Schedule (DELAY (tuple.expirationTime),
+                                           &AgentImpl::TopologyTupleTimerExpire,
+                                           this, tuple));
+    }
+}
+
+///
+/// \brief Removes tuple_ if expired. Else timer is rescheduled to expire at tuple_->time().
+/// \warning Actually this is never invoked because there is no support for multiple interfaces.
+/// \param e The event which has expired.
+///
+void
+AgentImpl::IfaceAssocTupleTimerExpire (IfaceAssocTuple tuple)
+{
+  if (tuple.time < Simulator::Now ())
+    {
+      RemoveIfaceAssocTuple (tuple);
+    }
+  else
+    {
+      m_events.Track (Simulator::Schedule (DELAY (tuple.time),
+                                           &AgentImpl::IfaceAssocTupleTimerExpire,
+                                           this, tuple));
+    }
+}
+
+
+
+}} // namespace olsr, ns3
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-agent-impl.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,190 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+
+#ifndef __OLSR_AGENT_IMPL_H__
+#define __OLSR_AGENT_IMPL_H__
+
+#include <vector>
+
+#include "olsr-agent.h"
+#include "olsr-header.h"
+#include "olsr-state.h"
+
+#include "routing-table.h"
+#include "repositories.h"
+
+#include "ns3/object.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/socket.h"
+#include "event-garbage-collector.h"
+#include "ns3/timer.h"
+#include "ns3/callback-trace-source.h"
+
+
+namespace ns3 {
+namespace olsr {
+
+
+class AgentImpl : public Agent
+{
+public:
+  AgentImpl (Ptr<Node> node);
+
+  virtual void Start ();
+  virtual void SetMainInterface (uint32_t interface);
+
+private:
+  EventGarbageCollector m_events;
+
+  /// Address of the routing agent.
+  Ipv4Address m_routingAgentAddr;
+	
+  /// Packets sequence number counter.
+  uint16_t m_packetSequenceNumber;
+  /// Messages sequence number counter.
+  uint16_t m_messageSequenceNumber;
+  /// Advertised Neighbor Set sequence number.
+  uint16_t m_ansn;
+  
+  /// HELLO messages' emission interval.
+  Time m_helloInterval;
+  /// TC messages' emission interval.
+  Time m_tcInterval;
+  /// MID messages' emission interval.
+  Time m_midInterval;
+  /// Willingness for forwarding packets on behalf of other nodes.
+  uint8_t m_willingness;
+  /// Determines if layer 2 notifications are enabled or not.
+  bool m_useL2Notifications;
+	
+  /// Routing table.
+  Ptr<RoutingTable> m_routingTable;
+  /// Internal state with all needed data structs.
+  OlsrState m_state;
+
+  Ptr<Ipv4> m_ipv4;
+	
+protected:
+  void DoDispose ();
+  Ptr<TraceResolver> GetTraceResolver (void) const;
+
+  void SendPacket (Packet packet, const MessageList &containedMessages);
+	
+  /// Increments packet sequence number and returns the new value.
+  inline uint16_t GetPacketSequenceNumber ();
+  /// Increments message sequence number and returns the new value.
+  inline uint16_t GetMessageSequenceNumber ();
+	
+  void RecvOlsr (Ptr<Socket> socket,
+                 const Packet &receivedPacket,
+                 const Address &sourceAddress);
+
+  void MprComputation ();
+  void RoutingTableComputation ();
+  Ipv4Address GetMainAddress (Ipv4Address iface_addr) const;
+
+  // Timer handlers
+  Timer m_helloTimer;
+  void HelloTimerExpire ();
+  
+  Timer m_tcTimer;
+  void TcTimerExpire ();
+
+  Timer m_midTimer;
+  void MidTimerExpire ();
+
+  void DupTupleTimerExpire (DuplicateTuple tuple);
+  bool m_linkTupleTimerFirstTime;
+  void LinkTupleTimerExpire (LinkTuple tuple);
+  void Nb2hopTupleTimerExpire (TwoHopNeighborTuple tuple);
+  void MprSelTupleTimerExpire (MprSelectorTuple tuple);
+  void TopologyTupleTimerExpire (TopologyTuple tuple);
+  void IfaceAssocTupleTimerExpire (IfaceAssocTuple tuple);
+
+  /// A list of pending messages which are buffered awaiting for being sent.
+  olsr::MessageList m_queuedMessages;
+  Timer m_queuedMessagesTimer; // timer for throttling outgoing messages
+
+  void ForwardDefault (olsr::MessageHeader olsrMessage,
+                       DuplicateTuple *duplicated,
+                       const Ipv4Address &localIface,
+                       const Ipv4Address &senderAddress);
+  void QueueMessage (const olsr::MessageHeader &message, Time delay);
+  void SendQueuedMessages ();
+  void SendHello ();
+  void SendTc ();
+  void SendMid ();
+
+  void NeighborLoss (const LinkTuple &tuple);
+  void AddDuplicateTuple (const DuplicateTuple &tuple);
+  void RemoveDuplicateTuple (const DuplicateTuple &tuple);
+  LinkTuple & AddLinkTuple (const LinkTuple &tuple, uint8_t willingness);
+  void RemoveLinkTuple (const LinkTuple &tuple);
+  void LinkTupleUpdated (const LinkTuple &tuple);
+  void AddNeighborTuple (const NeighborTuple &tuple);
+  void RemoveNeighborTuple (const NeighborTuple &tuple);
+  void AddTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+  void RemoveTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+  void AddMprSelectorTuple (const MprSelectorTuple  &tuple);
+  void RemoveMprSelectorTuple (const MprSelectorTuple &tuple);
+  void AddTopologyTuple (const TopologyTuple &tuple);
+  void RemoveTopologyTuple (const TopologyTuple &tuple);
+  void AddIfaceAssocTuple (const IfaceAssocTuple &tuple);
+  void RemoveIfaceAssocTuple (const IfaceAssocTuple &tuple);
+
+  void ProcessHello (const olsr::MessageHeader &msg,
+                     const Ipv4Address &receiverIface,
+                     const Ipv4Address &senderIface);
+  void ProcessTc (const olsr::MessageHeader &msg,
+                  const Ipv4Address &senderIface);
+  void ProcessMid (const olsr::MessageHeader &msg,
+                   const Ipv4Address &senderIface);
+
+  void LinkSensing (const olsr::MessageHeader &msg,
+                    const olsr::MessageHeader::Hello &hello,
+                    const Ipv4Address &receiverIface,
+                    const Ipv4Address &sender_iface);
+  void PopulateNeighborSet (const olsr::MessageHeader &msg,
+                            const olsr::MessageHeader::Hello &hello);
+  void PopulateTwoHopNeighborSet (const olsr::MessageHeader &msg,
+                                  const olsr::MessageHeader::Hello &hello);
+  void PopulateMprSelectorSet (const olsr::MessageHeader &msg,
+                               const olsr::MessageHeader::Hello &hello);
+
+  int Degree (NeighborTuple const &tuple);
+
+  Ipv4Address m_mainAddress;
+  Ptr<Socket> m_receiveSocket; // UDP socket for receving OSLR packets
+  Ptr<Socket> m_sendSocket; // UDP socket for sending OSLR packets
+
+  CallbackTraceSource <const PacketHeader &,
+                       const MessageList &> m_rxPacketTrace;
+  CallbackTraceSource <const PacketHeader &,
+                       const MessageList &> m_txPacketTrace;
+
+};
+
+}} // namespace ns3
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-agent.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,30 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#include "olsr-agent.h"
+#include "olsr-agent-impl.h"
+
+namespace ns3 {
+namespace olsr {
+
+const InterfaceId Agent::iid = MakeInterfaceId ("OlsrAgent", Object::iid);
+const ClassId Agent::cid = MakeClassId< AgentImpl, Ptr<Node> > ("OlsrAgent", Agent::iid);
+
+}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-agent.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,81 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#ifndef OLSR_AGENT_H
+#define OLSR_AGENT_H
+
+#include "ns3/node.h"
+#include "ns3/component-manager.h"
+
+namespace ns3 {
+namespace olsr {
+
+/**
+ * \brief Class implementing the OLSR state machine
+ *
+ * This class represents an instance of the OLSR protocol.  It
+ * attaches itself to a Node, and its lifecycle is bound to that node.
+ * Normally the functions in the ns3::olsr namespace are more simple
+ * to use to start OLSR on nodes, but access to the underlying OLSR
+ * agent can be useful in order to customize the OLSR parameters.
+ * Example:
+ *
+ * \code
+ * Ptr<olsr::Agent> olsr = ComponentManager::Create<olsr::Agent, Ptr<Node> > (olsr::Agent::cid, olsr::Agent::iid, node);
+ * agent->SetMainInterface (2);
+ * agent->Start ();
+ * \endcode
+ */
+class Agent : public Object
+{
+public:
+  static const InterfaceId iid;
+  static const ClassId cid;
+
+  /**
+   * \brief Sets the main interface to be used by OLSR
+   *
+   * Normally OLSR supports multiple interfaces, but the protocol
+   * requires the definition of a "main interface".  This interface's
+   * IPv4 address provides the identity of the node, and all outgoing
+   * OLSR routing messages must have the main interface address,
+   * regardless of the actual interface used to transmit the packet.
+   * This method allows one to explicitly select an interface as the
+   * main interface.  It must be called before the agent starts, but
+   * calling it is optional; if not called, the agent tries to guess
+   * and uses a suitable interface.
+   */
+  virtual void SetMainInterface (uint32_t interface) = 0;
+
+  /**
+   * \brief Starts the OLSR protocol operation
+   *
+   * Calling this method essentially bootstraps the OLSR protocol, and
+   * causes the agent to start broadcasting OLSR messages to
+   * neighbors, as well start listening to messages from neighbors.
+   */
+  virtual void Start () = 0;
+};
+
+
+}} // namespace olsr, ns3
+
+#endif /* OLSR_AGENT_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-header.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,735 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#include "ns3/assert.h"
+
+#include "olsr-header.h"
+
+#define IPV4_ADDRESS_SIZE 4
+#define OLSR_MSG_HEADER_SIZE 12
+#define OLSR_PKT_HEADER_SIZE 4
+
+namespace ns3 {
+namespace olsr {
+
+/// Scaling factor used in RFC 3626.
+#define OLSR_C 0.0625
+
+///
+/// \brief Converts a decimal number of seconds to the mantissa/exponent format.
+///
+/// \param seconds decimal number of seconds we want to convert.
+/// \return the number of seconds in mantissa/exponent format.
+///
+uint8_t
+SecondsToEmf (double seconds)
+{
+  int a, b = 0;
+  
+  // find the largest integer 'b' such that: T/C >= 2^b
+  for (b = 0; (seconds/OLSR_C) >= (1 << b); ++b)
+    ;
+  NS_ASSERT ((seconds/OLSR_C) < (1 << b));
+  b--;
+  NS_ASSERT ((seconds/OLSR_C) >= (1 << b));
+
+  // compute the expression 16*(T/(C*(2^b))-1), which may not be a integer
+  double tmp = 16*(seconds/(OLSR_C*(1<<b))-1);
+
+  // round it up.  This results in the value for 'a'
+  a = (int) ceil (tmp);
+
+  // if 'a' is equal to 16: increment 'b' by one, and set 'a' to 0
+  if (a == 16)
+    {
+      b += 1;
+      a = 0;
+    }
+
+  // now, 'a' and 'b' should be integers between 0 and 15,
+  NS_ASSERT (a >= 0 && a < 16);
+  NS_ASSERT (b >= 0 && b < 16);
+
+  // the field will be a byte holding the value a*16+b
+  return (uint8_t) ((a << 4) | b);
+}
+
+///
+/// \brief Converts a number of seconds in the mantissa/exponent format to a decimal number.
+///
+/// \param olsr_format number of seconds in mantissa/exponent format.
+/// \return the decimal number of seconds.
+///
+double
+EmfToSeconds (uint8_t olsrFormat)
+{
+  int a = (olsrFormat >> 4);
+  int b = (olsrFormat & 0xf);
+  // value = C*(1+a/16)*2^b [in seconds]
+  return OLSR_C * (1 + a/16.0) * (1 << b);
+}
+
+
+
+// ---------------- OLSR Packet -------------------------------
+
+PacketHeader::PacketHeader ()
+{}
+
+PacketHeader::~PacketHeader ()
+{}
+
+uint32_t
+PacketHeader::GetUid (void)
+{
+  static uint32_t uid = AllocateUid<PacketHeader>
+    ("PacketHeader.nsnam.org");
+  return uid;
+}
+
+uint32_t 
+PacketHeader::GetSerializedSize (void) const
+{
+  return OLSR_PKT_HEADER_SIZE;
+}
+
+void 
+PacketHeader::Print (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+PacketHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteHtonU16 (m_packetLength);
+  i.WriteHtonU16 (m_packetSequenceNumber);
+}
+
+uint32_t
+PacketHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  m_packetLength  = i.ReadNtohU16 ();
+  m_packetSequenceNumber = i.ReadNtohU16 ();
+  return GetSerializedSize ();
+}
+
+
+// ---------------- OLSR Message -------------------------------
+
+MessageHeader::MessageHeader ()
+  : m_messageType (MessageHeader::MessageType (0))
+{}
+
+MessageHeader::~MessageHeader ()
+{}
+
+uint32_t
+MessageHeader::GetUid (void)
+{
+  static uint32_t uid = AllocateUid<MessageHeader>
+    ("MessageHeader.nsnam.org");
+  return uid;
+}
+
+uint32_t
+MessageHeader::GetSerializedSize (void) const
+{
+  uint32_t size = OLSR_MSG_HEADER_SIZE;
+  switch (m_messageType)
+    {
+    case MID_MESSAGE:
+      size += m_message.mid.GetSerializedSize ();
+      break;
+    case HELLO_MESSAGE:
+      size += m_message.hello.GetSerializedSize ();
+      break;
+    case TC_MESSAGE:
+      size += m_message.tc.GetSerializedSize ();
+      break;
+    case HNA_MESSAGE:
+      size += m_message.hna.GetSerializedSize ();
+      break;
+    default:
+      NS_ASSERT (false);
+    }
+  return size;
+}
+
+void 
+MessageHeader::Print (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+MessageHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  i.WriteU8 (m_messageType);
+  i.WriteU8 (m_vTime);
+  i.WriteHtonU16 (GetSerializedSize () - OLSR_MSG_HEADER_SIZE);
+  i.WriteHtonU32 (m_originatorAddress.GetHostOrder ());
+  i.WriteU8 (m_timeToLive);
+  i.WriteU8 (m_hopCount);
+  i.WriteHtonU16 (m_messageSequenceNumber);
+
+  switch (m_messageType)
+    {
+    case MID_MESSAGE:
+      m_message.mid.Serialize (i);
+      break;
+    case HELLO_MESSAGE:
+      m_message.hello.Serialize (i);
+      break;
+    case TC_MESSAGE:
+      m_message.tc.Serialize (i);
+      break;
+    case HNA_MESSAGE:
+      m_message.hna.Serialize (i);
+      break;
+    default:
+      NS_ASSERT (false);
+    }
+
+}
+
+uint32_t
+MessageHeader::Deserialize (Buffer::Iterator start)
+{
+  uint32_t size;
+  Buffer::Iterator i = start;
+  m_messageType  = (MessageType) i.ReadU8 ();
+  NS_ASSERT (m_messageType >= HELLO_MESSAGE && m_messageType <= HNA_MESSAGE);
+  m_vTime  = i.ReadU8 ();
+  m_messageSize  = i.ReadNtohU16 ();
+  m_originatorAddress = Ipv4Address (i.ReadNtohU32 ());
+  m_timeToLive  = i.ReadU8 ();
+  m_hopCount  = i.ReadU8 ();
+  m_messageSequenceNumber = i.ReadNtohU16 ();
+  size = OLSR_MSG_HEADER_SIZE;
+  switch (m_messageType)
+    {
+    case MID_MESSAGE:
+      size += m_message.mid.Deserialize (i, m_messageSize);
+      break;
+    case HELLO_MESSAGE:
+      size += m_message.hello.Deserialize (i, m_messageSize);
+      break;
+    case TC_MESSAGE:
+      size += m_message.tc.Deserialize (i, m_messageSize);
+      break;
+    case HNA_MESSAGE:
+      size += m_message.hna.Deserialize (i, m_messageSize);
+      break;
+    default:
+      NS_ASSERT (false);
+    }
+  return size;
+}
+
+
+// ---------------- OLSR MID Message -------------------------------
+
+uint32_t 
+MessageHeader::Mid::GetSerializedSize (void) const
+{
+  return this->interfaceAddresses.size () * IPV4_ADDRESS_SIZE;
+}
+
+void 
+MessageHeader::Mid::Print (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+MessageHeader::Mid::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  for (std::vector<Ipv4Address>::const_iterator iter = this->interfaceAddresses.begin ();
+       iter != this->interfaceAddresses.end (); iter++)
+    {
+      i.WriteHtonU32 (iter->GetHostOrder ());
+    }
+}
+
+uint32_t
+MessageHeader::Mid::Deserialize (Buffer::Iterator start, uint32_t messageSize)
+{
+  Buffer::Iterator i = start;
+
+  this->interfaceAddresses.clear ();
+  NS_ASSERT (messageSize >= 0);
+  NS_ASSERT (messageSize % IPV4_ADDRESS_SIZE == 0);
+  
+  int numAddresses = messageSize / IPV4_ADDRESS_SIZE;
+  this->interfaceAddresses.erase (this->interfaceAddresses.begin(),
+                                  this->interfaceAddresses.end ());
+  for (int n = 0; n < numAddresses; ++n)
+      this->interfaceAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
+  return GetSerializedSize ();
+}
+
+
+
+// ---------------- OLSR HELLO Message -------------------------------
+
+uint32_t 
+MessageHeader::Hello::GetSerializedSize (void) const
+{
+  uint32_t size = 4;
+  for (std::vector<LinkMessage>::const_iterator iter = this->linkMessages.begin ();
+       iter != this->linkMessages.end (); iter++)
+    {
+      const LinkMessage &lm = *iter;
+      size += 4;
+      size += IPV4_ADDRESS_SIZE * lm.neighborInterfaceAddresses.size ();
+    }
+  return size;
+}
+
+void 
+MessageHeader::Hello::Print (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+MessageHeader::Hello::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU16 (0); // Reserved
+  i.WriteU8 (this->hTime);
+  i.WriteU8 (this->willingness);
+  
+  for (std::vector<LinkMessage>::const_iterator iter = this->linkMessages.begin ();
+       iter != this->linkMessages.end (); iter++)
+    {
+      const LinkMessage &lm = *iter;
+
+      i.WriteU8 (lm.linkCode);
+      i.WriteU8 (0); // Reserved
+
+      // The size of the link message, counted in bytes and measured
+      // from the beginning of the "Link Code" field and until the
+      // next "Link Code" field (or - if there are no more link types
+      // - the end of the message).
+      i.WriteHtonU16 (4 + lm.neighborInterfaceAddresses.size () * IPV4_ADDRESS_SIZE);
+      
+      for (std::vector<Ipv4Address>::const_iterator neigh_iter = lm.neighborInterfaceAddresses.begin ();
+           neigh_iter != lm.neighborInterfaceAddresses.end (); neigh_iter++)
+        {
+          i.WriteHtonU32 (neigh_iter->GetHostOrder ());
+        }
+    }
+}
+
+uint32_t
+MessageHeader::Hello::Deserialize (Buffer::Iterator start, uint32_t messageSize)
+{
+  Buffer::Iterator i = start;
+
+  NS_ASSERT (messageSize >= 4);
+
+  this->linkMessages.clear ();
+  
+  uint16_t helloSizeLeft = messageSize;
+  
+  i.ReadNtohU16 (); // Reserved
+  this->hTime = i.ReadU8 ();
+  this->willingness = i.ReadU8 ();
+  
+  helloSizeLeft -= 4;
+
+  while (helloSizeLeft)
+    {
+      LinkMessage lm;
+      NS_ASSERT (helloSizeLeft >= 4);
+      lm.linkCode = i.ReadU8 ();
+      i.ReadU8 (); // Reserved
+      uint16_t lmSize = i.ReadNtohU16 ();
+      NS_ASSERT ((lmSize - 4) % IPV4_ADDRESS_SIZE == 0);
+      for (int n = (lmSize - 4) / IPV4_ADDRESS_SIZE; n; --n)
+        {
+          lm.neighborInterfaceAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
+        }
+      helloSizeLeft -= lmSize;
+      this->linkMessages.push_back (lm);
+    }
+
+  return messageSize;
+}
+
+
+
+// ---------------- OLSR TC Message -------------------------------
+
+uint32_t 
+MessageHeader::Tc::GetSerializedSize (void) const
+{
+  return 4 + this->neighborAddresses.size () * IPV4_ADDRESS_SIZE;
+}
+
+void 
+MessageHeader::Tc::Print (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+MessageHeader::Tc::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteHtonU16 (this->ansn);
+  i.WriteHtonU16 (0); // Reserved
+
+  for (std::vector<Ipv4Address>::const_iterator iter = this->neighborAddresses.begin ();
+       iter != this->neighborAddresses.end (); iter++)
+    {
+      i.WriteHtonU32 (iter->GetHostOrder ());
+    }
+}
+
+uint32_t
+MessageHeader::Tc::Deserialize (Buffer::Iterator start, uint32_t messageSize)
+{
+  Buffer::Iterator i = start;
+
+  this->neighborAddresses.clear ();
+  NS_ASSERT (messageSize >= 4);
+
+  this->ansn = i.ReadNtohU16 ();
+  i.ReadNtohU16 (); // Reserved
+  
+  NS_ASSERT ((messageSize - 4) % IPV4_ADDRESS_SIZE == 0);
+  int numAddresses = (messageSize - 4) / IPV4_ADDRESS_SIZE;
+  this->neighborAddresses.clear ();
+  for (int n = 0; n < numAddresses; ++n)
+    this->neighborAddresses.push_back (Ipv4Address (i.ReadNtohU32 ()));
+
+  return messageSize;
+}
+
+
+// ---------------- OLSR HNA Message -------------------------------
+
+uint32_t 
+MessageHeader::Hna::GetSerializedSize (void) const
+{
+  return 2*this->associations.size () * IPV4_ADDRESS_SIZE;
+}
+
+void 
+MessageHeader::Hna::Print (std::ostream &os) const
+{
+  // TODO
+}
+
+void
+MessageHeader::Hna::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  for (size_t n = 0; n < this->associations.size (); ++n)
+    {
+      i.WriteHtonU32 (this->associations[n].address.GetHostOrder ());
+      i.WriteHtonU32 (this->associations[n].mask.GetHostOrder ());
+    }
+}
+
+uint32_t
+MessageHeader::Hna::Deserialize (Buffer::Iterator start, uint32_t messageSize)
+{
+  Buffer::Iterator i = start;
+
+  NS_ASSERT (messageSize % (IPV4_ADDRESS_SIZE*2) == 0);
+  int numAddresses = messageSize / IPV4_ADDRESS_SIZE / 2;
+  this->associations.clear ();
+  for (int n = 0; n < numAddresses; ++n)
+    {
+      Ipv4Address address (i.ReadNtohU32 ());
+      Ipv4Mask mask (i.ReadNtohU32 ());
+      this->associations.push_back ((Association) {address, mask});
+    }
+  return messageSize;
+}
+
+
+
+}} // namespace olsr, ns3
+
+
+#ifdef RUN_SELF_TESTS
+
+
+#include "ns3/test.h"
+#include "ns3/packet.h"
+#include <math.h>
+
+
+namespace ns3 {
+
+class OlsrHeaderTest : public ns3::Test {
+private:
+public:
+  OlsrHeaderTest ();
+  virtual bool RunTests (void);
+
+
+};
+
+OlsrHeaderTest::OlsrHeaderTest ()
+  : ns3::Test ("OlsrHeader")
+{}
+
+
+bool 
+OlsrHeaderTest::RunTests (void)
+{
+  bool result = true;
+
+  // Testing packet header + message header + MID message
+  {
+    Packet packet;
+
+    {
+      olsr::PacketHeader hdr;
+      olsr::MessageHeader msg1;
+      olsr::MessageHeader::Mid &mid1 = msg1.GetMid ();
+      olsr::MessageHeader msg2;
+      olsr::MessageHeader::Mid &mid2 = msg2.GetMid ();
+    
+      // MID message #1
+      {
+        std::vector<Ipv4Address> &addresses = mid1.interfaceAddresses;
+        addresses.clear ();
+        addresses.push_back (Ipv4Address ("1.2.3.4"));
+        addresses.push_back (Ipv4Address ("1.2.3.5"));
+      }
+
+      msg1.SetTimeToLive (255);
+      msg1.SetOriginatorAddress (Ipv4Address ("11.22.33.44"));
+      msg1.SetVTime (Seconds (9));
+      msg1.SetMessageSequenceNumber (7);
+
+      // MID message #2
+      {
+        std::vector<Ipv4Address> &addresses = mid2.interfaceAddresses;
+        addresses.clear ();
+        addresses.push_back (Ipv4Address ("2.2.3.4"));
+        addresses.push_back (Ipv4Address ("2.2.3.5"));
+      }
+
+      msg2.SetTimeToLive (254);
+      msg2.SetOriginatorAddress (Ipv4Address ("12.22.33.44"));
+      msg2.SetVTime (Seconds (10));
+      msg2.SetMessageType (olsr::MessageHeader::MID_MESSAGE);
+      msg2.SetMessageSequenceNumber (7);
+
+      // Build an OLSR packet header
+      hdr.SetPacketLength (hdr.GetSerializedSize () + msg1.GetSerializedSize () + msg2.GetSerializedSize ());
+      hdr.SetPacketSequenceNumber (123);
+    
+
+      // Now add all the headers in the correct order
+      packet.AddHeader (msg2);
+      packet.AddHeader (msg1);
+      packet.AddHeader (hdr);
+    }    
+
+    {
+      olsr::PacketHeader hdr;
+      packet.RemoveHeader (hdr);
+      NS_TEST_ASSERT_EQUAL (hdr.GetPacketSequenceNumber (), 123);
+      uint32_t sizeLeft = hdr.GetPacketLength () - hdr.GetSerializedSize ();
+      {
+        olsr::MessageHeader msg1;
+
+        packet.RemoveHeader (msg1);
+
+        NS_TEST_ASSERT_EQUAL (msg1.GetTimeToLive (),  255);
+        NS_TEST_ASSERT_EQUAL (msg1.GetOriginatorAddress (), Ipv4Address ("11.22.33.44"));
+        NS_TEST_ASSERT_EQUAL (msg1.GetVTime (), Seconds (9));
+        NS_TEST_ASSERT_EQUAL (msg1.GetMessageType (), olsr::MessageHeader::MID_MESSAGE);
+        NS_TEST_ASSERT_EQUAL (msg1.GetMessageSequenceNumber (), 7);
+
+        olsr::MessageHeader::Mid &mid1 = msg1.GetMid ();
+        NS_TEST_ASSERT_EQUAL (mid1.interfaceAddresses.size (), 2);
+        NS_TEST_ASSERT_EQUAL (*mid1.interfaceAddresses.begin (), Ipv4Address ("1.2.3.4"));
+
+        sizeLeft -= msg1.GetSerializedSize ();
+        NS_TEST_ASSERT (sizeLeft > 0);
+      }
+      {
+        // now read the second message
+        olsr::MessageHeader msg2;
+
+        packet.RemoveHeader (msg2);
+
+        NS_TEST_ASSERT_EQUAL (msg2.GetTimeToLive (),  254);
+        NS_TEST_ASSERT_EQUAL (msg2.GetOriginatorAddress (), Ipv4Address ("12.22.33.44"));
+        NS_TEST_ASSERT_EQUAL (msg2.GetVTime (), Seconds (10));
+        NS_TEST_ASSERT_EQUAL (msg2.GetMessageType (), olsr::MessageHeader::MID_MESSAGE);
+        NS_TEST_ASSERT_EQUAL (msg2.GetMessageSequenceNumber (), 7);
+
+        olsr::MessageHeader::Mid mid2 = msg2.GetMid ();
+        NS_TEST_ASSERT_EQUAL (mid2.interfaceAddresses.size (), 2);
+        NS_TEST_ASSERT_EQUAL (*mid2.interfaceAddresses.begin (), Ipv4Address ("2.2.3.4"));
+
+        sizeLeft -= msg2.GetSerializedSize ();
+        NS_TEST_ASSERT_EQUAL (sizeLeft, 0);
+      }
+    }
+  }
+  
+  // Test the HELLO message
+  {
+    Packet packet;
+    olsr::MessageHeader msgIn;
+    olsr::MessageHeader::Hello &helloIn = msgIn.GetHello ();
+
+    helloIn.SetHTime (Seconds (7));
+    helloIn.willingness = 66;
+
+    {
+      olsr::MessageHeader::Hello::LinkMessage lm1;
+      lm1.linkCode = 2;
+      lm1.neighborInterfaceAddresses.push_back (Ipv4Address ("1.2.3.4"));
+      lm1.neighborInterfaceAddresses.push_back (Ipv4Address ("1.2.3.5"));
+      helloIn.linkMessages.push_back (lm1);
+
+      olsr::MessageHeader::Hello::LinkMessage lm2;
+      lm2.linkCode = 3;
+      lm2.neighborInterfaceAddresses.push_back (Ipv4Address ("2.2.3.4"));
+      lm2.neighborInterfaceAddresses.push_back (Ipv4Address ("2.2.3.5"));
+      helloIn.linkMessages.push_back (lm2);
+    }
+
+    packet.AddHeader (msgIn);
+
+    olsr::MessageHeader msgOut;
+    packet.RemoveHeader (msgOut);
+    olsr::MessageHeader::Hello &helloOut = msgOut.GetHello ();
+    
+    NS_TEST_ASSERT_EQUAL (helloOut.GetHTime (), Seconds (7));
+    NS_TEST_ASSERT_EQUAL (helloOut.willingness, 66);
+    NS_TEST_ASSERT_EQUAL (helloOut.linkMessages.size (), 2);
+
+    NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[0].linkCode, 2);
+    NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[0].neighborInterfaceAddresses[0],
+                          Ipv4Address ("1.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[0].neighborInterfaceAddresses[1],
+                          Ipv4Address ("1.2.3.5"));
+
+    NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[1].linkCode, 3);
+    NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[1].neighborInterfaceAddresses[0],
+                          Ipv4Address ("2.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (helloOut.linkMessages[1].neighborInterfaceAddresses[1],
+                          Ipv4Address ("2.2.3.5"));
+
+    // check that all bytes of the message were read
+    NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
+  }
+
+  // Test the TC message
+  {
+    Packet packet;
+    olsr::MessageHeader msgIn;
+    olsr::MessageHeader::Tc &tcIn = msgIn.GetTc ();
+
+    tcIn.ansn = 0x1234;
+    tcIn.neighborAddresses.push_back (Ipv4Address ("1.2.3.4"));
+    tcIn.neighborAddresses.push_back (Ipv4Address ("1.2.3.5"));
+    packet.AddHeader (msgIn);
+
+    olsr::MessageHeader msgOut;
+    packet.RemoveHeader (msgOut);
+    olsr::MessageHeader::Tc &tcOut = msgOut.GetTc ();
+    
+    NS_TEST_ASSERT_EQUAL (tcOut.ansn, 0x1234);
+    NS_TEST_ASSERT_EQUAL (tcOut.neighborAddresses.size (), 2);
+
+    NS_TEST_ASSERT_EQUAL (tcOut.neighborAddresses[0],
+                          Ipv4Address ("1.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (tcOut.neighborAddresses[1],
+                          Ipv4Address ("1.2.3.5"));
+
+    // check that all bytes of the message were read
+    NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
+  }
+
+  // Test the HNA message
+  {
+    Packet packet;
+    olsr::MessageHeader msgIn;
+    olsr::MessageHeader::Hna &hnaIn = msgIn.GetHna ();
+
+    hnaIn.associations.push_back ((olsr::MessageHeader::Hna::Association)
+                                  { Ipv4Address ("1.2.3.4"), Ipv4Mask ("255.255.255.0")});
+    hnaIn.associations.push_back ((olsr::MessageHeader::Hna::Association)
+                                  {Ipv4Address ("1.2.3.5"), Ipv4Mask ("255.255.0.0")});
+    packet.AddHeader (msgIn);
+
+    olsr::MessageHeader msgOut;
+    packet.RemoveHeader (msgOut);
+    olsr::MessageHeader::Hna &hnaOut = msgOut.GetHna ();
+    
+    NS_TEST_ASSERT_EQUAL (hnaOut.associations.size (), 2);
+
+    NS_TEST_ASSERT_EQUAL (hnaOut.associations[0].address,
+                          Ipv4Address ("1.2.3.4"));
+    NS_TEST_ASSERT_EQUAL (hnaOut.associations[0].mask,
+                          Ipv4Mask ("255.255.255.0"));
+
+    NS_TEST_ASSERT_EQUAL (hnaOut.associations[1].address,
+                          Ipv4Address ("1.2.3.5"));
+    NS_TEST_ASSERT_EQUAL (hnaOut.associations[1].mask,
+                          Ipv4Mask ("255.255.0.0"));
+
+    // check that all bytes of the message were read
+    NS_TEST_ASSERT_EQUAL (packet.GetSize (), 0);
+  }
+
+  for (int time = 1; time <= 30; time++)
+    {
+      uint8_t emf = olsr::SecondsToEmf (time);
+      double seconds = olsr::EmfToSeconds (emf);
+      if (seconds < 0 || fabs (seconds - time) > 0.1)
+        {
+          result = false;
+          Failure () << "In " << time << " out " << seconds << std::endl;
+        }
+    }
+
+  return result;
+}
+
+static OlsrHeaderTest gOlsrHeaderTest;
+
+}; // namespace
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-header.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,470 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#ifndef OLSR_HEADER_H
+#define OLSR_HEADER_H
+
+#include <stdint.h>
+#include <vector>
+#include "ns3/header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/nstime.h"
+
+
+namespace ns3 {
+namespace olsr {
+
+double EmfToSeconds (uint8_t emf);
+uint8_t SecondsToEmf (double seconds);
+
+// 3.3.  Packet Format
+//
+//    The basic layout of any packet in OLSR is as follows (omitting IP and
+//    UDP headers):
+//
+//        0                   1                   2                   3
+//        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |         Packet Length         |    Packet Sequence Number     |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Message Type |     Vtime     |         Message Size          |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                      Originator Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Time To Live |   Hop Count   |    Message Sequence Number    |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                                                               |
+//       :                            MESSAGE                            :
+//       |                                                               |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Message Type |     Vtime     |         Message Size          |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                      Originator Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Time To Live |   Hop Count   |    Message Sequence Number    |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                                                               |
+//       :                            MESSAGE                            :
+//       |                                                               |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       :                                                               :
+//                (etc.)
+class PacketHeader : public Header
+{
+public:
+  PacketHeader ();
+  virtual ~PacketHeader ();
+
+  void SetPacketLength (uint16_t length)
+  {
+    m_packetLength = length;
+  }
+  uint16_t GetPacketLength () const
+  {
+    return m_packetLength;
+  }
+
+  void SetPacketSequenceNumber (uint16_t seqnum)
+  {
+    m_packetSequenceNumber = seqnum;
+  }
+  uint16_t GetPacketSequenceNumber () const
+  {
+    return m_packetSequenceNumber;
+  }
+
+private:
+  uint16_t m_packetLength;
+  uint16_t m_packetSequenceNumber;
+
+public:  
+  static uint32_t GetUid (void);
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual std::string GetName (void) const { return "OlsrPacket"; }
+};
+
+
+//        0                   1                   2                   3
+//        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Message Type |     Vtime     |         Message Size          |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |                      Originator Address                       |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//       |  Time To Live |   Hop Count   |    Message Sequence Number    |
+//       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+class MessageHeader : public Header
+{
+public:
+
+  enum MessageType {
+    HELLO_MESSAGE = 1,
+    TC_MESSAGE    = 2,
+    MID_MESSAGE   = 3,
+    HNA_MESSAGE   = 4,
+  };
+
+  MessageHeader ();
+  virtual ~MessageHeader ();
+
+  void SetMessageType (MessageType messageType)
+  {
+    m_messageType = messageType;
+  }
+  MessageType GetMessageType () const
+  {
+    return m_messageType;
+  }
+
+  void SetVTime (Time time)
+  {
+    m_vTime = SecondsToEmf (time.GetSeconds ());
+  }
+  Time GetVTime () const
+  {
+    return Seconds (EmfToSeconds (m_vTime));
+  }
+
+  void SetOriginatorAddress (Ipv4Address originatorAddress)
+  {
+    m_originatorAddress = originatorAddress;
+  }
+  Ipv4Address GetOriginatorAddress () const
+  {
+    return m_originatorAddress;
+  }
+
+  void SetTimeToLive (uint8_t timeToLive)
+  {
+    m_timeToLive = timeToLive;
+  }
+  uint8_t GetTimeToLive () const
+  {
+    return m_timeToLive;
+  }
+
+  void SetHopCount (uint8_t hopCount)
+  {
+    m_hopCount = hopCount;
+  }
+  uint8_t GetHopCount () const
+  {
+    return m_hopCount;
+  }
+
+  void SetMessageSequenceNumber (uint16_t messageSequenceNumber)
+  {
+    m_messageSequenceNumber = messageSequenceNumber;
+  }
+  uint16_t GetMessageSequenceNumber () const
+  {
+    return m_messageSequenceNumber;
+  }
+
+//   void SetMessageSize (uint16_t messageSize)
+//   {
+//     m_messageSize = messageSize;
+//   }
+//   uint16_t GetMessageSize () const
+//   {
+//     return m_messageSize;
+//   }
+  
+private:
+  MessageType m_messageType;
+  uint8_t m_vTime;
+  Ipv4Address m_originatorAddress;
+  uint8_t m_timeToLive;
+  uint8_t m_hopCount;
+  uint16_t m_messageSequenceNumber;
+  uint16_t m_messageSize;
+
+public:  
+  static uint32_t GetUid (void);
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  virtual std::string GetName (void) const { return "OlsrMessage"; }
+
+  // 5.1.  MID Message Format
+  //
+  //    The proposed format of a MID message is as follows:
+  //
+  //        0                   1                   2                   3
+  //        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                    OLSR Interface Address                     |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                    OLSR Interface Address                     |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                              ...                              |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  struct Mid
+  {
+    std::vector<Ipv4Address> interfaceAddresses;
+    void Print (std::ostream &os) const;
+    uint32_t GetSerializedSize (void) const;
+    void Serialize (Buffer::Iterator start) const;
+    uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
+  };
+
+  // 6.1.  HELLO Message Format
+  //
+  //        0                   1                   2                   3
+  //        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  //
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |          Reserved             |     Htime     |  Willingness  |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |   Link Code   |   Reserved    |       Link Message Size       |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                  Neighbor Interface Address                   |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                  Neighbor Interface Address                   |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       :                             .  .  .                           :
+  //       :                                                               :
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |   Link Code   |   Reserved    |       Link Message Size       |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                  Neighbor Interface Address                   |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                  Neighbor Interface Address                   |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       :                                                               :
+  //       :                                       :
+  //    (etc.)
+  struct Hello
+  {
+    struct LinkMessage {
+      uint8_t linkCode;
+      std::vector<Ipv4Address> neighborInterfaceAddresses;
+    };
+
+    uint8_t hTime;
+    void SetHTime (Time time)
+    {
+      this->hTime = SecondsToEmf (time.GetSeconds ());
+    }
+    Time GetHTime () const
+    {
+      return Seconds (EmfToSeconds (this->hTime));
+    }
+
+    uint8_t willingness;
+    std::vector<LinkMessage> linkMessages;
+
+    void Print (std::ostream &os) const;
+    uint32_t GetSerializedSize (void) const;
+    void Serialize (Buffer::Iterator start) const;
+    uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
+  };
+
+  // 9.1.  TC Message Format
+  //
+  //    The proposed format of a TC message is as follows:
+  //
+  //        0                   1                   2                   3
+  //        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |              ANSN             |           Reserved            |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |               Advertised Neighbor Main Address                |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |               Advertised Neighbor Main Address                |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                              ...                              |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+  struct Tc
+  {
+    std::vector<Ipv4Address> neighborAddresses;
+    uint16_t ansn;
+
+    void Print (std::ostream &os) const;
+    uint32_t GetSerializedSize (void) const;
+    void Serialize (Buffer::Iterator start) const;
+    uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
+  };
+
+
+  // 12.1.  HNA Message Format
+  //
+  //    The proposed format of an HNA-message is:
+  //
+  //        0                   1                   2                   3
+  //        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                         Network Address                       |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                             Netmask                           |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                         Network Address                       |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                             Netmask                           |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  //       |                              ...                              |
+  //       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+  // Note: HNA stands for Host Network Association
+  struct Hna
+  {
+    struct Association
+    {
+      Ipv4Address address;
+      Ipv4Mask mask;
+    };
+    std::vector<Association> associations;
+
+    void Print (std::ostream &os) const;
+    uint32_t GetSerializedSize (void) const;
+    void Serialize (Buffer::Iterator start) const;
+    uint32_t Deserialize (Buffer::Iterator start, uint32_t messageSize);
+  };
+
+private:
+  struct
+  {
+    Mid mid;
+    Hello hello;
+    Tc tc;
+    Hna hna;
+  } m_message; // union not allowed
+
+public:
+
+  Mid& GetMid ()
+  {
+    if (m_messageType == 0)
+      {
+        m_messageType = MID_MESSAGE;
+      }
+    else
+      {
+        NS_ASSERT (m_messageType == MID_MESSAGE);
+      }
+    return m_message.mid;
+  }
+
+  Hello& GetHello ()
+  {
+    if (m_messageType == 0)
+      {
+        m_messageType = HELLO_MESSAGE;
+      }
+    else
+      {
+        NS_ASSERT (m_messageType == HELLO_MESSAGE);
+      }
+    return m_message.hello;
+  }
+
+  Tc& GetTc ()
+  {
+    if (m_messageType == 0)
+      {
+        m_messageType = TC_MESSAGE;
+      }
+    else
+      {
+        NS_ASSERT (m_messageType == TC_MESSAGE);
+      }
+    return m_message.tc;
+  }
+
+  Hna& GetHna ()
+  {
+    if (m_messageType == 0)
+      {
+        m_messageType = HNA_MESSAGE;
+      }
+    else
+      {
+        NS_ASSERT (m_messageType == HNA_MESSAGE);
+      }
+    return m_message.hna;
+  }
+
+
+  const Mid& GetMid () const
+  {
+    NS_ASSERT (m_messageType == MID_MESSAGE);
+    return m_message.mid;
+  }
+
+  const Hello& GetHello () const
+  {
+    NS_ASSERT (m_messageType == HELLO_MESSAGE);
+    return m_message.hello;
+  }
+
+  const Tc& GetTc () const
+  {
+    NS_ASSERT (m_messageType == TC_MESSAGE);
+    return m_message.tc;
+  }
+
+  const Hna& GetHna () const
+  {
+    NS_ASSERT (m_messageType == HNA_MESSAGE);
+    return m_message.hna;
+  }
+
+  
+};
+
+
+static inline std::ostream& operator<< (std::ostream& os, const PacketHeader & packet)
+{
+  packet.Print (os);
+  return os;
+}
+
+static inline std::ostream& operator<< (std::ostream& os, const MessageHeader & message)
+{
+  message.Print (os);
+  return os;
+}
+
+typedef std::vector<MessageHeader> MessageList;
+
+static inline std::ostream& operator<< (std::ostream& os, const MessageList & messages)
+{
+  os << "[";
+  for (std::vector<MessageHeader>::const_iterator messageIter = messages.begin ();
+       messageIter != messages.end (); messageIter++)
+    {
+      messageIter->Print (os);
+      if (messageIter+1 != messages.end ())
+        os << ", ";
+    }
+  os << "]";
+  return os;
+}
+
+
+}} // namespace olsr, ns3
+
+#endif /* OLSR_HEADER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-state.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,448 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+///
+/// \file	OlsrState.cc
+/// \brief	Implementation of all functions needed for manipulating the internal
+///		state of an OLSR node.
+///
+
+#include "olsr-state.h"
+
+
+namespace ns3 {
+
+
+/********** MPR Selector Set Manipulation **********/
+
+MprSelectorTuple*
+OlsrState::FindMprSelectorTuple (Ipv4Address const &mainAddr)
+{
+  for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
+       it != m_mprSelectorSet.end (); it++)
+    {
+      if (it->mainAddr == mainAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseMprSelectorTuple (const MprSelectorTuple &tuple)
+{
+  for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
+       it != m_mprSelectorSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_mprSelectorSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseMprSelectorTuples (const Ipv4Address &mainAddr)
+{
+  for (MprSelectorSet::iterator it = m_mprSelectorSet.begin ();
+       it != m_mprSelectorSet.end (); it++)
+    {
+      if (it->mainAddr == mainAddr)
+        {
+          it = m_mprSelectorSet.erase (it);
+          it--;
+        }
+    }
+}
+
+void
+OlsrState::InsertMprSelectorTuple (MprSelectorTuple const &tuple)
+{
+  m_mprSelectorSet.push_back (tuple);
+}
+
+/********** Neighbor Set Manipulation **********/
+
+NeighborTuple*
+OlsrState::FindNeighborTuple (Ipv4Address const &mainAddr)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+const NeighborTuple*
+OlsrState::FindSymNeighborTuple (Ipv4Address const &mainAddr) const
+{
+  for (NeighborSet::const_iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr && it->status == NeighborTuple::STATUS_SYM)
+        return &(*it);
+    }
+  return NULL;
+}
+
+NeighborTuple*
+OlsrState::FindNeighborTuple (Ipv4Address const &mainAddr, uint8_t willingness)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr && it->willingness == willingness)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseNeighborTuple (const NeighborTuple &tuple)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_neighborSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseNeighborTuple (const Ipv4Address &mainAddr)
+{
+  for (NeighborSet::iterator it = m_neighborSet.begin ();
+       it != m_neighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == mainAddr)
+        {
+          it = m_neighborSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::InsertNeighborTuple (NeighborTuple const &tuple)
+{
+  m_neighborSet.push_back (tuple);
+}
+
+/********** Neighbor 2 Hop Set Manipulation **********/
+
+TwoHopNeighborTuple*
+OlsrState::FindTwoHopNeighborTuple (Ipv4Address const &neighborMainAddr,
+                                    Ipv4Address const &twoHopNeighborAddr)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == neighborMainAddr
+          && it->twoHopNeighborAddr == twoHopNeighborAddr)
+        {
+          return &(*it);
+        }
+  }
+  return NULL;
+}
+
+void
+OlsrState::EraseTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_twoHopNeighborSet.erase(it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseTwoHopNeighborTuples (const Ipv4Address &neighborMainAddr,
+                                      const Ipv4Address &twoHopNeighborAddr)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == neighborMainAddr
+          && it->twoHopNeighborAddr == twoHopNeighborAddr)
+        {
+          it = m_twoHopNeighborSet.erase (it);
+          it--; // FIXME: is this correct in the case 'it' pointed to the first element?
+        }
+    }
+}
+
+void
+OlsrState::EraseTwoHopNeighborTuples (const Ipv4Address &neighborMainAddr)
+{
+  for (TwoHopNeighborSet::iterator it = m_twoHopNeighborSet.begin ();
+       it != m_twoHopNeighborSet.end (); it++)
+    {
+      if (it->neighborMainAddr == neighborMainAddr) {
+        it = m_twoHopNeighborSet.erase (it);
+        it--;
+      }
+    }
+}
+
+void
+OlsrState::InsertTwoHopNeighborTuple (TwoHopNeighborTuple const &tuple){
+  m_twoHopNeighborSet.push_back (tuple);
+}
+
+/********** MPR Set Manipulation **********/
+
+bool
+OlsrState::FindMprAddress (Ipv4Address const &addr)
+{
+  MprSet::iterator it = m_mprSet.find (addr);
+  return (it != m_mprSet.end ());
+}
+
+void
+OlsrState::InsertMprAddress (Ipv4Address const & addr)
+{
+  m_mprSet.insert (addr);
+}
+
+void
+OlsrState::ClearMprSet ()
+{
+  m_mprSet.clear ();
+}
+
+/********** Duplicate Set Manipulation **********/
+
+DuplicateTuple*
+OlsrState::FindDuplicateTuple (Ipv4Address const &addr, uint16_t sequenceNumber)
+{
+  for (DuplicateSet::iterator it = m_duplicateSet.begin ();
+       it != m_duplicateSet.end(); it++)
+    {
+      if (it->address == addr && it->sequenceNumber == sequenceNumber)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseDuplicateTuple (const DuplicateTuple &tuple)
+{
+  for (DuplicateSet::iterator it = m_duplicateSet.begin ();
+       it != m_duplicateSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_duplicateSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::InsertDuplicateTuple (DuplicateTuple const &tuple)
+{
+  m_duplicateSet.push_back (tuple);
+}
+
+/********** Link Set Manipulation **********/
+
+LinkTuple*
+OlsrState::FindLinkTuple (Ipv4Address const & ifaceAddr)
+{
+  for (LinkSet::iterator it = m_linkSet.begin ();
+       it != m_linkSet.end (); it++)
+    {
+      if (it->neighborIfaceAddr == ifaceAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+LinkTuple*
+OlsrState::FindSymLinkTuple (Ipv4Address const &ifaceAddr, Time now)
+{
+  for (LinkSet::iterator it = m_linkSet.begin ();
+       it != m_linkSet.end (); it++)
+    {
+      if (it->neighborIfaceAddr == ifaceAddr)
+        {
+          if (it->symTime > now)
+            return &(*it);
+          else
+            break;
+        }
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseLinkTuple (const LinkTuple &tuple)
+{
+  for (LinkSet::iterator it = m_linkSet.begin ();
+       it != m_linkSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_linkSet.erase (it);
+          break;
+        }
+    }
+}
+
+LinkTuple&
+OlsrState::InsertLinkTuple (LinkTuple const &tuple)
+{
+  m_linkSet.push_back (tuple);
+  return m_linkSet.back ();
+}
+
+/********** Topology Set Manipulation **********/
+
+TopologyTuple*
+OlsrState::FindTopologyTuple (Ipv4Address const &destAddr,
+                              Ipv4Address const &lastAddr)
+{
+  for (TopologySet::iterator it = m_topologySet.begin ();
+       it != m_topologySet.end (); it++)
+    {
+      if (it->destAddr == destAddr && it->lastAddr == lastAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+TopologyTuple*
+OlsrState::FindNewerTopologyTuple (Ipv4Address const & lastAddr, uint16_t ansn)
+{
+  for (TopologySet::iterator it = m_topologySet.begin ();
+       it != m_topologySet.end (); it++)
+    {
+      if (it->lastAddr == lastAddr && it->sequenceNumber > ansn)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseTopologyTuple(const TopologyTuple &tuple)
+{
+  for (TopologySet::iterator it = m_topologySet.begin ();
+       it != m_topologySet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_topologySet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::EraseOlderTopologyTuples (const Ipv4Address &lastAddr, uint16_t ansn)
+{
+  for (TopologySet::iterator it = m_topologySet.begin();
+       it != m_topologySet.end(); it++)
+    {
+      if (it->lastAddr == lastAddr && it->sequenceNumber < ansn)
+        {
+          it = m_topologySet.erase (it);
+          it--;
+        }
+    }
+}
+
+void
+OlsrState::InsertTopologyTuple (TopologyTuple const &tuple)
+{
+  m_topologySet.push_back (tuple);
+}
+
+/********** Interface Association Set Manipulation **********/
+
+IfaceAssocTuple*
+OlsrState::FindIfaceAssocTuple (Ipv4Address const &ifaceAddr)
+{
+  for (IfaceAssocSet::iterator it = m_ifaceAssocSet.begin ();
+       it != m_ifaceAssocSet.end (); it++)
+    {
+      if (it->ifaceAddr == ifaceAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+const IfaceAssocTuple*
+OlsrState::FindIfaceAssocTuple (Ipv4Address const &ifaceAddr) const
+{
+  for (IfaceAssocSet::const_iterator it = m_ifaceAssocSet.begin ();
+       it != m_ifaceAssocSet.end (); it++)
+    {
+      if (it->ifaceAddr == ifaceAddr)
+        return &(*it);
+    }
+  return NULL;
+}
+
+void
+OlsrState::EraseIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+  for (IfaceAssocSet::iterator it = m_ifaceAssocSet.begin ();
+       it != m_ifaceAssocSet.end (); it++)
+    {
+      if (*it == tuple)
+        {
+          m_ifaceAssocSet.erase (it);
+          break;
+        }
+    }
+}
+
+void
+OlsrState::InsertIfaceAssocTuple (const IfaceAssocTuple &tuple)
+{
+  m_ifaceAssocSet.push_back (tuple);
+}
+
+std::vector<Ipv4Address>
+OlsrState::FindNeighborInterfaces (const Ipv4Address &neighborMainAddr) const
+{
+  std::vector<Ipv4Address> retval;
+  for (IfaceAssocSet::const_iterator it = m_ifaceAssocSet.begin ();
+       it != m_ifaceAssocSet.end (); it++)
+    {
+      if (it->mainAddr == neighborMainAddr)
+        retval.push_back (it->ifaceAddr);
+    }
+  return retval;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-state.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,145 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+/// \brief	This header file declares and defines internal state of an OLSR node.
+
+#ifndef __OLSR_STATE_H__
+#define __OLSR_STATE_H__
+
+#include "repositories.h"
+
+namespace ns3 {
+
+using namespace olsr;
+
+/// This class encapsulates all data structures needed for maintaining internal state of an OLSR node.
+class OlsrState
+{
+  //  friend class Olsr;
+  
+protected:
+  LinkSet m_linkSet;	///< Link Set (RFC 3626, section 4.2.1).
+  NeighborSet m_neighborSet;		///< Neighbor Set (RFC 3626, section 4.3.1).
+  TwoHopNeighborSet m_twoHopNeighborSet;	///< 2-hop Neighbor Set (RFC 3626, section 4.3.2).
+  TopologySet m_topologySet;	///< Topology Set (RFC 3626, section 4.4).
+  MprSet m_mprSet;	///< MPR Set (RFC 3626, section 4.3.3).
+  MprSelectorSet m_mprSelectorSet;	///< MPR Selector Set (RFC 3626, section 4.3.4).
+  DuplicateSet m_duplicateSet;	///< Duplicate Set (RFC 3626, section 3.4).
+  IfaceAssocSet m_ifaceAssocSet;	///< Interface Association Set (RFC 3626, section 4.1).
+
+public:
+
+  // MPR selector
+  const MprSelectorSet & GetMprSelectors () const
+  {
+    return m_mprSelectorSet;
+  }
+  MprSelectorTuple* FindMprSelectorTuple (const Ipv4Address &mainAddr);
+  void EraseMprSelectorTuple (const MprSelectorTuple &tuple);
+  void EraseMprSelectorTuples (const Ipv4Address &mainAddr);
+  void InsertMprSelectorTuple (const MprSelectorTuple &tuple);
+
+  // Neighbor
+  const NeighborSet & GetNeighbors () const
+  {
+    return m_neighborSet;
+  }
+  NeighborTuple* FindNeighborTuple (const Ipv4Address &mainAddr);
+  const NeighborTuple* FindSymNeighborTuple (const Ipv4Address &mainAddr) const;
+  NeighborTuple* FindNeighborTuple (const Ipv4Address &mainAddr,
+                                    uint8_t willingness);
+  void EraseNeighborTuple (const NeighborTuple &neighborTuple);
+  void EraseNeighborTuple (const Ipv4Address &mainAddr);
+  void InsertNeighborTuple (const NeighborTuple &tuple);
+
+  // Two-hop neighbor
+  const TwoHopNeighborSet & GetTwoHopNeighbors () const
+  {
+    return m_twoHopNeighborSet;
+  }
+  TwoHopNeighborTuple* FindTwoHopNeighborTuple (const Ipv4Address &neighbor,
+                                                const Ipv4Address &twoHopNeighbor);
+  void EraseTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+  void EraseTwoHopNeighborTuples (const Ipv4Address &neighbor);
+  void EraseTwoHopNeighborTuples (const Ipv4Address &neighbor,
+                                  const Ipv4Address &twoHopNeighbor);
+  void InsertTwoHopNeighborTuple (const TwoHopNeighborTuple &tuple);
+
+  // MPR
+  bool FindMprAddress (const Ipv4Address &address);
+  void InsertMprAddress (const Ipv4Address &address);
+  void ClearMprSet ();
+
+  // Duplicate
+  DuplicateTuple* FindDuplicateTuple (const Ipv4Address &address,
+                                      uint16_t sequenceNumber);
+  void EraseDuplicateTuple (const DuplicateTuple &tuple);
+  void InsertDuplicateTuple (const DuplicateTuple &tuple);
+
+  // Link
+  const LinkSet & GetLinks () const
+  {
+    return m_linkSet;
+  }
+  LinkTuple* FindLinkTuple (const Ipv4Address &ifaceAddr);
+  LinkTuple* FindSymLinkTuple (const Ipv4Address &ifaceAddr, Time time);
+  void EraseLinkTuple (const LinkTuple &tuple);
+  LinkTuple& InsertLinkTuple (const LinkTuple &tuple);
+
+  // Topology
+  const TopologySet & GetTopologySet () const
+  {
+    return m_topologySet;
+  }
+  TopologyTuple* FindTopologyTuple (const Ipv4Address &destAddr,
+                                    const Ipv4Address &lastAddr);
+  TopologyTuple* FindNewerTopologyTuple (const Ipv4Address &lastAddr,
+                                         uint16_t ansn);
+  void EraseTopologyTuple (const TopologyTuple &tuple);
+  void EraseOlderTopologyTuples (const Ipv4Address &lastAddr,
+                                 uint16_t ansn);
+  void InsertTopologyTuple (const TopologyTuple &tuple);
+
+  // Interface association
+  const IfaceAssocSet & GetIfaceAssocSet () const
+  {
+    return m_ifaceAssocSet;
+  }
+  IfaceAssocSet & GetIfaceAssocSetMutable ()
+  {
+    return m_ifaceAssocSet;
+  }
+  IfaceAssocTuple* FindIfaceAssocTuple (const Ipv4Address &ifaceAddr);
+  const IfaceAssocTuple* FindIfaceAssocTuple (const Ipv4Address &ifaceAddr) const;
+  void EraseIfaceAssocTuple (const IfaceAssocTuple &tuple);
+  void InsertIfaceAssocTuple (const IfaceAssocTuple &tuple);
+
+  // Returns a vector of all interfaces of a given neighbor, with the
+  // exception of the "main" one.
+  std::vector<Ipv4Address>
+  FindNeighborInterfaces (const Ipv4Address &neighborMainAddr) const;
+
+};
+
+} // namespace ns3
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,42 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#include "olsr-agent.h"
+#include "olsr.h"
+
+namespace ns3 { namespace olsr {
+
+
+void
+EnableAllNodes (void)
+{
+  EnableNodes <NodeList::Iterator> (NodeList::Begin (), NodeList::End ());
+}
+
+void
+EnableNode (Ptr<Node> node)
+{
+  ComponentManager::Create<olsr::Agent, Ptr<Node> >
+    (olsr::Agent::cid, olsr::Agent::iid, node)->Start ();
+}
+
+
+}} // namespace ns3, olsr
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,66 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INESC Porto
+ *
+ * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
+ */
+
+#ifndef OLSR_H
+#define OLSR_H
+
+#include "ns3/node-list.h"
+
+namespace ns3
+{
+  /**
+   * \namespace ns3::olsr
+   * \brief Includes a set of utility functions to enable OLSR on
+   * certain nodes with default parameters.  For finer grained control
+   * of OLSR parameters, see OlsrAgent.
+   */
+  namespace olsr
+  {
+    /// \brief Start the OLSR routing agent on all nodes
+    void EnableAllNodes (void);
+
+    /// \brief Start the OLSR routing agent on a given list of nodes
+    template <typename InputIterator>
+    void EnableNodes (InputIterator begin, InputIterator end);
+
+    /// \brief Start the OLSR routing agent on the given node
+    void EnableNode (Ptr<Node> node);
+  }
+}
+
+
+// implementation
+namespace ns3
+{
+  namespace olsr
+  {
+    template <typename InputIterator>
+    void EnableNodes (InputIterator begin, InputIterator end)
+    {
+      for (InputIterator i = begin; i != end; i++)
+        {
+          EnableNode (*i);
+        }
+    }
+  }
+}
+
+
+#endif /* OLSR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/repositories.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,198 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+///
+/// \file	OLSR_repositories.h
+/// \brief	Here are defined all data structures needed by an OLSR node.
+///
+
+#ifndef __OLSR_REPOSITORIES_H__
+#define __OLSR_REPOSITORIES_H__
+
+#include <set>
+#include <vector>
+
+#include "ns3/ipv4-address.h"
+#include "ns3/nstime.h"
+
+namespace ns3 { namespace olsr {
+
+
+
+/// An Interface Association Tuple.
+struct IfaceAssocTuple
+{
+  /// Interface address of a node.
+  Ipv4Address ifaceAddr;
+  /// Main address of the node.
+  Ipv4Address mainAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time time;
+};
+
+static inline bool
+operator == (const IfaceAssocTuple &a, const IfaceAssocTuple &b)
+{
+  return (a.ifaceAddr == b.ifaceAddr
+          && a.mainAddr == b.mainAddr);
+}
+
+/// A Link Tuple.
+struct LinkTuple
+{
+  /// Interface address of the local node.
+  Ipv4Address localIfaceAddr;
+  /// Interface address of the neighbor node.
+  Ipv4Address neighborIfaceAddr;
+  /// The link is considered bidirectional until this time.
+  Time symTime;
+  /// The link is considered unidirectional until this time.
+  Time asymTime;
+  /// The link is considered lost until this time (used for link layer notification).
+  Time lostTime;
+  /// Time at which this tuple expires and must be removed.
+  Time time;
+};
+
+static inline bool
+operator == (const LinkTuple &a, const LinkTuple &b)
+{
+  return (a.localIfaceAddr == b.localIfaceAddr
+          && a.neighborIfaceAddr == b.neighborIfaceAddr);
+}
+
+/// A Neighbor Tuple.
+struct NeighborTuple
+{
+  /// Main address of a neighbor node.
+  Ipv4Address neighborMainAddr;
+  /// Neighbor Type and Link Type at the four less significative digits.
+  enum Status {
+    STATUS_NOT_SYM = 0, // "not symmetric"
+    STATUS_SYM = 1, // "symmetric"
+  } status;
+  /// A value between 0 and 7 specifying the node's willingness to carry traffic on behalf of other nodes.
+  uint8_t willingness;
+};
+
+static inline bool
+operator == (const NeighborTuple &a, const NeighborTuple &b)
+{
+  return (a.neighborMainAddr == b.neighborMainAddr
+          && a.status == b.status
+          && a.willingness == b.willingness);
+}
+
+/// A 2-hop Tuple.
+struct TwoHopNeighborTuple
+{
+  /// Main address of a neighbor.
+  Ipv4Address neighborMainAddr;
+  /// Main address of a 2-hop neighbor with a symmetric link to nb_main_addr.
+  Ipv4Address twoHopNeighborAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;        // previously called 'time_'
+};
+
+static inline bool
+operator == (const TwoHopNeighborTuple &a, const TwoHopNeighborTuple &b)
+{
+  return (a.neighborMainAddr == b.neighborMainAddr
+          && a.twoHopNeighborAddr == b.twoHopNeighborAddr);
+}
+
+/// An MPR-Selector Tuple.
+struct MprSelectorTuple
+{
+  /// Main address of a node which have selected this node as a MPR.
+  Ipv4Address mainAddr;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;       // previously called 'time_'
+};
+
+static inline bool
+operator == (const MprSelectorTuple &a, const MprSelectorTuple &b)
+{
+  return (a.mainAddr == b.mainAddr);
+}
+
+
+/// The type "list of interface addresses"
+//typedef std::vector<nsaddr_t> addr_list_t;
+
+/// A Duplicate Tuple
+struct DuplicateTuple
+{
+  /// Originator address of the message.
+  Ipv4Address address;
+  /// Message sequence number.
+  uint16_t sequenceNumber;
+  /// Indicates whether the message has been retransmitted or not.
+  bool retransmitted;
+  /// List of interfaces which the message has been received on.
+  std::vector<Ipv4Address> ifaceList;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;
+};
+
+static inline bool
+operator == (const DuplicateTuple &a, const DuplicateTuple &b)
+{
+  return (a.address == b.address
+          && a.sequenceNumber == b.sequenceNumber);
+}
+
+/// A Topology Tuple
+struct TopologyTuple
+{
+  /// Main address of the destination.
+  Ipv4Address destAddr;
+  /// Main address of a node which is a neighbor of the destination.
+  Ipv4Address lastAddr;
+  /// Sequence number.
+  uint16_t sequenceNumber;
+  /// Time at which this tuple expires and must be removed.
+  Time expirationTime;
+};
+
+static inline bool
+operator == (const TopologyTuple &a, const TopologyTuple &b)
+{
+  return (a.destAddr == b.destAddr
+          && a.lastAddr == b.lastAddr
+          && a.sequenceNumber == b.sequenceNumber);
+}
+
+
+typedef std::set<Ipv4Address> 			MprSet;	///< MPR Set type.
+typedef std::vector<MprSelectorTuple>		MprSelectorSet;	///< MPR Selector Set type.
+typedef std::vector<LinkTuple>			LinkSet;	///< Link Set type.
+typedef std::vector<NeighborTuple>		NeighborSet;	///< Neighbor Set type.
+typedef std::vector<TwoHopNeighborTuple>	TwoHopNeighborSet; ///< 2-hop Neighbor Set type.
+typedef std::vector<TopologyTuple>		TopologySet;	///< Topology Set type.
+typedef std::vector<DuplicateTuple>		DuplicateSet;	///< Duplicate Set type.
+typedef std::vector<IfaceAssocTuple>		IfaceAssocSet; ///< Interface Association Set type.
+
+
+}}; // namespace ns3, olsr
+
+#endif  /* __OLSR_REPOSITORIES_H__ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/routing-table.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,290 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+///
+/// \file	OLSR_rtable.cc
+/// \brief	Implementation of our routing table.
+///
+
+#include "routing-table.h"
+#include "ns3/packet.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/log.h"
+
+namespace ns3 { namespace olsr {
+
+NS_LOG_COMPONENT_DEFINE ("OlsrRoutingTable");
+
+///
+/// \brief Clears the routing table and frees the memory assigned to each one of its entries.
+///
+void
+RoutingTable::Clear ()
+{
+  m_table.clear ();
+}
+
+///
+/// \brief Deletes the entry whose destination address is given.
+/// \param dest	address of the destination node.
+///
+void
+RoutingTable::RemoveEntry (Ipv4Address const &dest)
+{
+  m_table.erase (dest);
+}
+
+///
+/// \brief Looks up an entry for the specified destination address.
+/// \param dest	destination address.
+/// \param outEntry output parameter to hold the routing entry result, if fuond
+/// \return	true if found, false if not found
+///
+bool
+RoutingTable::Lookup (Ipv4Address const &dest,
+                      RoutingTableEntry &outEntry) const
+{
+  // Get the iterator at "dest" position
+  std::map<Ipv4Address, RoutingTableEntry>::const_iterator it =
+    m_table.find (dest);
+  // If there is no route to "dest", return NULL
+  if (it == m_table.end ())
+    return false;
+  outEntry = it->second;
+  return true;
+}
+
+///
+/// \brief	Finds the appropiate entry which must be used in order to forward
+///		a data packet to a next hop (given a destination).
+///
+/// Imagine a routing table like this: [A,B] [B,C] [C,C]; being each pair of the
+/// form [dest addr,next-hop addr]. In this case, if this function is invoked with
+/// [A,B] then pair [C,C] is returned because C is the next hop that must be used
+/// to forward a data packet destined to A. That is, C is a neighbor of this node,
+/// but B isn't. This function finds the appropiate neighbor for forwarding a packet.
+///
+/// \param entry	the routing table entry which indicates the destination node
+///			we are interested in.
+/// \return		the appropiate routing table entry which indicates the next
+///			hop which must be used for forwarding a data packet, or NULL
+///			if there is no such entry.
+///
+bool
+RoutingTable::FindSendEntry (RoutingTableEntry const &entry,
+                             RoutingTableEntry &outEntry) const
+{
+  outEntry = entry;
+  while (outEntry.destAddr != outEntry.nextAddr)
+    {
+      if (not Lookup(outEntry.nextAddr, outEntry))
+        return false;
+    }
+  return true;
+}
+
+
+bool
+RoutingTable::RequestRoute (uint32_t ifIndex,
+                            const Ipv4Header &ipHeader,
+                            Packet packet,
+                            RouteReplyCallback routeReply)
+{
+  RoutingTableEntry entry1, entry2;
+  if (Lookup (ipHeader.GetDestination (), entry1))
+    {
+      bool foundSendEntry = FindSendEntry (entry1, entry2);
+      if (!foundSendEntry)
+        NS_FATAL_ERROR ("FindSendEntry failure");
+
+      Ipv4Route route = Ipv4Route::CreateHostRouteTo
+        (ipHeader.GetDestination (), entry2.nextAddr, entry2.interface);
+
+      NS_LOG_DEBUG ("Olsr node" << m_mainAddress
+                    << ": RouteRequest for dest=" << ipHeader.GetDestination ()
+                    << " --> destHop=" << entry2.nextAddr
+                    << " interface=" << entry2.interface);
+      
+      routeReply (true, route, packet, ipHeader);
+      return true;
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Olsr node" << m_mainAddress
+                    << ": RouteRequest for dest=" << ipHeader.GetDestination ()
+                    << " --> NOT FOUND");
+      return false;
+    }
+}
+
+bool
+RoutingTable::RequestIfIndex (Ipv4Address destination,
+                              uint32_t& ifIndex)
+{
+  RoutingTableEntry entry1, entry2;
+  if (Lookup (destination, entry1))
+    {
+      bool foundSendEntry = FindSendEntry (entry1, entry2);
+      if (!foundSendEntry)
+        NS_FATAL_ERROR ("FindSendEntry failure");
+      ifIndex = entry2.interface;
+      return true;
+    }
+  else
+    {
+      return false;
+    }
+}
+
+
+///
+/// \brief Adds a new entry into the routing table.
+///
+/// If an entry for the given destination existed, it is deleted and freed.
+///
+/// \param dest		address of the destination node.
+/// \param next		address of the next hop node.
+/// \param iface	address of the local interface.
+/// \param dist		distance to the destination node.
+///
+void
+RoutingTable::AddEntry (Ipv4Address const &dest,
+                        Ipv4Address const &next,
+                        uint32_t interface,
+                        uint32_t distance)
+{
+  // Creates a new rt entry with specified values
+  RoutingTableEntry &entry = m_table[dest];
+
+  entry.destAddr = dest;
+  entry.nextAddr = next;
+  entry.interface = interface;
+  entry.distance = distance;
+}
+
+void
+RoutingTable::AddEntry (Ipv4Address const &dest,
+                        Ipv4Address const &next,
+                        Ipv4Address const &interfaceAddress,
+                        uint32_t distance)
+{
+  RoutingTableEntry entry;
+  NS_ASSERT (m_ipv4);
+  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+    {
+      if (m_ipv4->GetAddress (i) == interfaceAddress)
+        {
+          AddEntry (dest, next, i, distance);
+          return;
+        }
+    }
+  NS_ASSERT (false); // should not be reached
+  AddEntry (dest, next, 0, distance);
+}
+
+
+///
+/// \brief Returns the number of entries in the routing table.
+/// \return the number of entries in the routing table.
+///
+// u_int32_t
+// RoutingTable::size() {
+// 	return rt_.size();
+// }
+
+}}; // namespace ns3, olsr
+
+
+
+#ifdef RUN_SELF_TESTS
+
+
+#include "ns3/test.h"
+
+
+namespace ns3 { namespace olsr {
+
+class OlsrRoutingTableTest : public ns3::Test {
+private:
+public:
+  OlsrRoutingTableTest ();
+  virtual bool RunTests (void);
+
+
+};
+
+OlsrRoutingTableTest::OlsrRoutingTableTest ()
+  : ns3::Test ("OlsrRoutingTable")
+{}
+
+
+bool 
+OlsrRoutingTableTest::RunTests (void)
+{
+  bool result = true;
+
+  RoutingTable table;
+
+  table.AddEntry (Ipv4Address ("1.2.3.5"),
+                  Ipv4Address ("1.2.3.4"),
+                  0,
+                  1);
+
+  table.AddEntry (Ipv4Address ("1.2.3.4"),
+                  Ipv4Address ("1.2.3.4"),
+                  0,
+                  1);
+  
+  RoutingTableEntry entry1;
+  NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.5"), entry1));
+  NS_TEST_ASSERT_EQUAL (entry1.destAddr, Ipv4Address ("1.2.3.5"));
+  NS_TEST_ASSERT_EQUAL (entry1.nextAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (entry1.interface, 0);
+  NS_TEST_ASSERT_EQUAL (entry1.distance, 1);
+
+  RoutingTableEntry entry2;
+  NS_TEST_ASSERT (table.Lookup (Ipv4Address ("1.2.3.4"), entry2));
+  NS_TEST_ASSERT_EQUAL (entry2.destAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (entry2.nextAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (entry2.interface, 0);
+  NS_TEST_ASSERT_EQUAL (entry2.distance, 1);
+
+  RoutingTableEntry sendEntry;
+  NS_TEST_ASSERT (table.FindSendEntry (entry1, sendEntry));
+  NS_TEST_ASSERT_EQUAL (sendEntry.destAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (sendEntry.nextAddr, Ipv4Address ("1.2.3.4"));
+  NS_TEST_ASSERT_EQUAL (sendEntry.interface, 0);
+  NS_TEST_ASSERT_EQUAL (sendEntry.distance, 1);
+
+  table.RemoveEntry (Ipv4Address ("1.2.3.5"));
+  RoutingTableEntry removedEntry;
+  NS_TEST_ASSERT (not table.Lookup (Ipv4Address ("1.2.3.5"), removedEntry));
+
+  return result;
+}
+
+static OlsrRoutingTableTest gOlsrRoutingTableTest;
+
+}}; // namespace
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/routing-table.h	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,112 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2004 Francisco J. Ros 
+ * Copyright (c) 2007 INESC Porto
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Authors: Francisco J. Ros  <fjrm@dif.um.es>
+ *          Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
+ */
+
+///
+/// \file	OLSR_rtable.h
+/// \brief	Header file for routing table's related stuff.
+///
+
+#ifndef __OLSR_RTABLE_H__
+#define __OLSR_RTABLE_H__
+
+#include "ns3/ipv4.h"
+#include <map>
+
+
+namespace ns3 { namespace olsr {
+
+/// An %OLSR's routing table entry.
+struct RoutingTableEntry
+{
+  Ipv4Address destAddr;	///< Address of the destination node.
+  Ipv4Address nextAddr;	///< Address of the next hop.
+  uint32_t interface; ///< Interface index
+  uint32_t distance; ///< Distance in hops to the destination.
+
+  RoutingTableEntry () : // default values
+    destAddr (), nextAddr (),
+    interface (0), distance (0) {};
+};
+
+///
+/// \brief Defines rtable_t as a map of OLSR_rt_entry, whose key is the destination address.
+///
+/// The routing table is thus defined as pairs: [dest address, entry]. Each element
+/// of the pair can be accesed via "first" and "second" members.
+///
+//typedef std::map<Ipv4Address, RoutingTableEntry> RoutingTable;
+
+///
+/// \brief This class is a representation of the OLSR's Routing Table.
+///
+class RoutingTable : public Ipv4RoutingProtocol
+{
+  std::map<Ipv4Address, RoutingTableEntry> m_table; ///< Data structure for the routing table.
+  Ptr<Ipv4> m_ipv4;
+
+  Ipv4Address m_mainAddress; // used only for printing debug messages
+
+  void DoDispose ()
+  {
+    m_ipv4 = 0;
+    Ipv4RoutingProtocol::DoDispose ();
+  }
+  
+public:
+	
+  RoutingTable () {}
+  RoutingTable (Ptr<Ipv4> ipv4, const Ipv4Address &mainAddress)
+    :
+    m_ipv4 (ipv4),
+    m_mainAddress (mainAddress)
+  {}
+
+  ~RoutingTable () {}
+  
+  void Clear ();
+  void RemoveEntry (const Ipv4Address &dest);
+  void AddEntry (const Ipv4Address &dest,
+                 const Ipv4Address &next,
+                 uint32_t interface,
+                 uint32_t distance);
+  void AddEntry (const Ipv4Address &dest,
+                 const Ipv4Address &next,
+                 const Ipv4Address &interfaceAddress,
+                 uint32_t distance);
+  bool Lookup (const Ipv4Address &dest,
+               RoutingTableEntry &outEntry) const;
+  bool FindSendEntry (const RoutingTableEntry &entry,
+                      RoutingTableEntry &outEntry) const;
+
+  // From Ipv4RoutingProtocol
+  virtual bool RequestRoute (uint32_t ifIndex,
+                             const Ipv4Header &ipHeader,
+                             Packet packet,
+                             RouteReplyCallback routeReply);
+  virtual bool RequestIfIndex (Ipv4Address destination, 
+                               uint32_t& ifIndex);
+
+};
+
+}}; // namespace ns3, olsr
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,22 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    module = bld.create_ns3_module('olsr', ['internet-node'])
+    module.includes = '.'
+    module.source = [
+        'olsr-header.cc',
+        'olsr-state.cc',
+        'routing-table.cc',
+        'olsr-agent.cc',
+        'olsr-agent-impl.cc',
+        'olsr.cc',
+        'event-garbage-collector.cc',
+        ]
+
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'olsr-agent.h',
+        'olsr.h',
+        'olsr-header.h',
+        ]
+
--- a/src/simulator/event-garbage-collector.cc	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INESC Porto
- * All rights reserved.
- *
- * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
- */
-#include "event-garbage-collector.h"
-
-#define CLEANUP_CHUNK_MIN_SIZE 8
-#define CLEANUP_CHUNK_MAX_SIZE 128
-
-
-namespace ns3 {
-
-
-EventGarbageCollector::EventGarbageCollector () :
-  m_nextCleanupSize (CLEANUP_CHUNK_MIN_SIZE)
-{}
-
-void
-EventGarbageCollector::Track (EventId event)
-{
-  m_events.push_back (event);
-  if (m_events.size () >= m_nextCleanupSize)
-    Cleanup ();
-}
-
-inline bool
-EventExpiredPredicate (const EventId &event)
-{
-  return event.IsExpired ();
-}
-
-void
-EventGarbageCollector::Grow ()
-{
-  m_nextCleanupSize += (m_nextCleanupSize < CLEANUP_CHUNK_MAX_SIZE?
-                        m_nextCleanupSize : CLEANUP_CHUNK_MAX_SIZE);
-}
-
-void
-EventGarbageCollector::Shrink ()
-{
-  while (m_nextCleanupSize > m_events.size ())
-    m_nextCleanupSize >>= 1;
-  Grow ();
-}
-
-// Called when a new event was added and the cleanup limit was exceeded in consequence.
-void
-EventGarbageCollector::Cleanup ()
-{
-  m_events.remove_if (EventExpiredPredicate);
-
-  // If after cleanup we are still over the limit, increase the limit.
-  if (m_events.size () >= m_nextCleanupSize)
-    Grow ();
-  else
-    Shrink ();
-}
-
-
-EventGarbageCollector::~EventGarbageCollector ()
-{
-  for (std::list<EventId>::iterator event = m_events.begin ();
-       event != m_events.end (); event++)
-    {
-      Simulator::Cancel (*event);
-    }
-}
-
-}; // namespace ns3
-
-
-
-#ifdef RUN_SELF_TESTS
-
-#include "ns3/test.h"
-
-namespace ns3 {
-
-class EventGarbageCollectorTests : public Test
-{
-  int m_counter;
-  EventGarbageCollector *m_events;
-
-  void EventGarbageCollectorCallback ();
-
-public:
-
-  EventGarbageCollectorTests ();
-  virtual ~EventGarbageCollectorTests ();
-  virtual bool RunTests (void);
-};
-
-EventGarbageCollectorTests::EventGarbageCollectorTests ()
-  : Test ("EventGarbageCollector"), m_counter (0), m_events (0)
-{}
-
-EventGarbageCollectorTests::~EventGarbageCollectorTests ()
-{}
-
-void
-EventGarbageCollectorTests::EventGarbageCollectorCallback ()
-{
-  m_counter++;
-  if (m_counter == 50)
-    {
-      // this should cause the remaining (50) events to be cancelled
-      delete m_events;
-      m_events = 0;
-    }
-}
-
-bool EventGarbageCollectorTests::RunTests (void)
-{
-  bool result = true;
-
-  m_events = new EventGarbageCollector ();
-
-  for (int n = 0; n < 100; n++)
-    {
-      m_events->Track (Simulator::Schedule
-                       (Simulator::Now (),
-                        &EventGarbageCollectorTests::EventGarbageCollectorCallback,
-                        this));
-    }
-  Simulator::Run ();
-  NS_TEST_ASSERT_EQUAL (m_events, 0);
-  NS_TEST_ASSERT_EQUAL (m_counter, 50);
-  return result;
-}
-
-static EventGarbageCollectorTests g_eventCollectorTests;
-    
-};
-
-#endif /* RUN_SELF_TESTS */
--- a/src/simulator/event-garbage-collector.h	Wed Oct 10 12:25:52 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INESC Porto
- * All rights reserved.
- *
- * 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: Gustavo J. A. M. Carneiro  <gjc@inescporto.pt>
- */
-#ifndef EVENT_GARBAGE_COLLECTOR_H
-#define EVENT_GARBAGE_COLLECTOR_H
-
-#include <list>
-#include "event-id.h"
-#include "simulator.h"
-
-namespace ns3 {
-
-/**
- * \brief An object that tracks scheduled events and automatically
- * cancels them when it is destroyed.  It is useful in situations
- * where multiple instances of the same type of event can
- * simultaneously be scheduled, and when the events should be limited
- * to the lifetime of a container object.
- */
-class EventGarbageCollector
-{
-public:
-
-  EventGarbageCollector ();
-
-  /**
-   * \brief Tracks a new event
-   */
-  void Track (EventId event);
-
-  ~EventGarbageCollector ();
-
-private:
-
-  std::list<EventId>::size_type m_nextCleanupSize;
-  std::list<EventId> m_events;
-
-  void Cleanup ();
-  void Grow ();
-  void Shrink ();
-};
-
-}; // namespace ns3
-
-#endif /* EVENT_GARBAGE_COLLECTOR_H */
--- a/src/simulator/timer.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/simulator/timer.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -20,7 +20,6 @@
 #include "timer.h"
 #include "simulator.h"
 #include "simulation-singleton.h"
-#include "event-garbage-collector.h"
 
 namespace ns3 {
 
@@ -31,16 +30,8 @@
     m_impl (0)
 {}
 
-Timer::Timer (enum SchedulePolicy schedulePolicy, 
-	      enum DestroyPolicy destroyPolicy)
-  : m_flags (schedulePolicy | destroyPolicy),
-    m_delay (FemtoSeconds (0)),
-    m_event (),
-    m_impl (0)
-{}
-
-Timer::Timer (enum GarbageCollectPolicy policy)
-  : m_flags (GARBAGE_COLLECT),
+Timer::Timer (enum DestroyPolicy destroyPolicy)
+  : m_flags (destroyPolicy),
     m_delay (FemtoSeconds (0)),
     m_event (),
     m_impl (0)
@@ -149,26 +140,11 @@
 Timer::Schedule (Time delay)
 {
   NS_ASSERT (m_impl != 0);
-  if (m_flags & CHECK_ON_SCHEDULE)
+  if (m_event.IsRunning ())
     {
-      if (m_event.IsRunning ())
-	{
-	  NS_FATAL_ERROR ("Event is still running while re-scheduling.");
-	}
-    }
-  else if (m_flags & CANCEL_ON_SCHEDULE)
-    {
-      m_event.Cancel ();
-    }
-  else if (m_flags & REMOVE_ON_SCHEDULE)
-    {
-      Simulator::Remove (m_event);
+      NS_FATAL_ERROR ("Event is still running while re-scheduling.");
     }
   m_event = m_impl->Schedule (delay);
-  if (m_flags & GARBAGE_COLLECT)
-    {
-      SimulationSingleton<EventGarbageCollector>::Get ()->Track (m_event);
-    }
 }
 
 void
--- a/src/simulator/timer.h	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/simulator/timer.h	Thu Nov 08 16:58:24 2007 -0800
@@ -43,23 +43,10 @@
 class Timer 
 {
 public:
-  enum SchedulePolicy {
-    /**
-     * This policy cancels the event before scheduling a new event 
-     * for each call to Timer::Schedule.
-     */
-    CANCEL_ON_SCHEDULE = (1<<0),
-    /**
-     * This policy removes the event from the simulation event list 
-     * before scheduling a new event for each call to Timer::Schedule. 
-     */
-    REMOVE_ON_SCHEDULE = (1<<1),
-    /**
-     * This policy enforces a check before each call to Timer::Schedule
-     * to verify that the timer has already expired.
-     */
-    CHECK_ON_SCHEDULE = (1<<2),
-  };
+  /**
+   * The policy to use to manager the internal timer when and
+   * instance of the Timer class is destroyed.
+   */
   enum DestroyPolicy {
     /**
      * This policy cancels the event from the destructor of the Timer
@@ -77,15 +64,6 @@
      */
     CHECK_ON_DESTROY = (1<<5)
   };
-  enum GarbageCollectPolicy {
-    /**
-     * Every event scheduled with this policy is kept track of by an
-     * event garbage collector which makes sure that all events
-     * of timers with a GARBAGE_COLLECT policy are cancelled at the
-     * end of the simulation.
-     */
-    GARBAGE_COLLECT = (1<<6)
-  };
   enum State {
     RUNNING,
     EXPIRED,
@@ -93,21 +71,13 @@
   };
   /**
    * create a timer with a default event lifetime management policy:
-   *  - CHECK_ON_SCHEDULE
    *  - CHECK_ON_DESTROY
    */
   Timer ();
   /**
-   * \param scheduleFlags the event lifetime management policies to use for schedule events
-   * \param destroyFlags the event lifetime management policies to use for destroy events
+   * \param destroyPolicy the event lifetime management policies to use for destroy events
    */
-  Timer (enum SchedulePolicy schedulePolicy, 
-	 enum DestroyPolicy destroyPolicy);
-  /**
-   * \param policy the garbage collect policy. Only one
-   *        value is possible.
-   */
-  Timer (enum GarbageCollectPolicy policy);
+  Timer (enum DestroyPolicy destroyPolicy);
   ~Timer ();
 
   /**
--- a/src/simulator/wscript	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/simulator/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -61,7 +61,6 @@
         'simulator.cc',
         'time-default-value.cc',
         'timer.cc',
-        'event-garbage-collector.cc',
         ]
 
     headers = bld.create_obj('ns3header')
--- a/src/wscript	Wed Oct 10 12:25:52 2007 -0700
+++ b/src/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -21,6 +21,7 @@
     'applications/onoff',
     'applications/packet-sink',
     'applications/udp-echo',
+    'routing/olsr',
     'routing/global-routing',
     'mobility',
     )
--- a/tutorial/hello-simulator.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/tutorial/hello-simulator.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -23,8 +23,8 @@
 int 
 main (int argc, char *argv[])
 {
-  LogComponentEnable ("HelloSimulator", 
-    LogLevel (LOG_LEVEL_INFO | LOG_PREFIX_ALL));
+  //  LogComponentEnable ("HelloSimulator", 
+  //    LogLevel (LOG_LEVEL_INFO | LOG_PREFIX_ALL));
 
   NS_LOG_INFO ("Hello Simulator");
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/bench-event-collector.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -0,0 +1,35 @@
+#include <iostream>
+#include <vector>
+#include <stdlib.h>
+#include "ns3/event-collector.h"
+#include "ns3/simulator.h"
+
+using namespace ns3;
+
+void Foo ()
+{
+
+}
+
+int main (int argc, char *argv[])
+{
+    EventCollector events;
+
+    if (argc < 3)
+    {
+        std::cerr << "usage: bench-event-collector NUM_EVENTS NUM_REPETITIONS" << std::endl;
+        return 1;
+    }
+    int numEvents = atoi (argv[1]);
+    int numRepetitions = atoi (argv[2]);
+    
+    for (int repetition = 0; repetition < numRepetitions; ++repetition)
+    {
+        for (int n = 0; n < numEvents; ++n)
+        {
+            events.Track (Simulator::Schedule (Simulator::Now (), Foo));
+        }
+        Simulator::Run ();
+    }
+}
+
--- a/utils/bench-packets.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/utils/bench-packets.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -211,13 +211,19 @@
       argc--;
       argv++;
   }
+  if (n == 0)
+    {
+      std::cerr << "Error-- number of packets must be specified " <<
+        "by command-line argument --n=(number of packets)" << std::endl;
+      exit (1);
+    }
+  std::cout << "Running bench-packets with n=" << n << std::endl;
 
-
+  Packet::EnableMetadata ();
   runBench (&benchPtrA, n, "a");
   runBench (&benchPtrB, n, "b");
   runBench (&benchPtrC, n, "c");
 
-  Packet::EnableMetadata ();
   //runBench (&benchPrint, n, "print");
   PacketMetadata::SetOptOne (false);
   runBench (&benchPtrA, n, "meta-a");
--- a/utils/mobility-visualizer-model.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/utils/mobility-visualizer-model.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -48,15 +48,15 @@
     {
       Ptr<Node> node = *nodeIter;
       Ptr<MobilityModel> mobility = node->QueryInterface<MobilityModel> (MobilityModel::iid);
-      Position pos = mobility->Get ();
-      Speed vel = mobility->GetSpeed ();
+      Vector pos = mobility->GetPosition ();
+      Vector vel = mobility->GetVelocity ();
 
       NodeUpdate update;
       update.node = PeekPointer<Node> (node);
       update.x = pos.x;
       update.y = pos.y;
-      update.vx = vel.dx;
-      update.vy = vel.dy;
+      update.vx = vel.x;
+      update.vy = vel.y;
       data->updateList.push_back (update);
     }
   data->time = Simulator::Now ().GetSeconds ();
--- a/utils/run-tests.cc	Wed Oct 10 12:25:52 2007 -0700
+++ b/utils/run-tests.cc	Thu Nov 08 16:58:24 2007 -0800
@@ -21,11 +21,13 @@
 
 #include "ns3/test.h"
 #include "ns3/packet-metadata.h"
+#include "ns3/random-variable.h"
 
 
 int main (int argc, char *argv[])
 {
 #ifdef RUN_SELF_TESTS
+  ns3::RandomVariable::UseGlobalSeed(1,2,3,4,5,6);
   ns3::PacketMetadata::Enable ();
   ns3::TestManager::EnableVerbose ();
   bool success = ns3::TestManager::RunTests ();
--- a/wscript	Wed Oct 10 12:25:52 2007 -0700
+++ b/wscript	Thu Nov 08 16:58:24 2007 -0800
@@ -118,7 +118,6 @@
         variant_env.append_value('CXXFLAGS', ['-Werror'])
 
     if 'debug' in Params.g_options.debug_level.lower():
-        variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE')
         variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')
         variant_env.append_value('CXXDEFINES', 'NS3_LOG_ENABLE')
 
@@ -174,6 +173,10 @@
 
     check_shell()
 
+    if Params.g_options.doxygen:
+        doxygen()
+        raise SystemExit(0)
+
     # process subfolders from here
     bld.add_subdirs('src')
     bld.add_subdirs('samples utils examples tutorial')